aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/audio/windows/waveout/Audio.java16
-rw-r--r--src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java92
-rw-r--r--src/jogl/classes/com/jogamp/audio/windows/waveout/SoundBuffer.java34
-rw-r--r--src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java32
-rw-r--r--src/jogl/classes/com/jogamp/audio/windows/waveout/Vec3f.java69
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java633
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java169
-rw-r--r--[-rwxr-xr-x]src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java167
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java239
-rw-r--r--[-rwxr-xr-x]src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java46
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/ant/StaticGLGenTask.java93
-rw-r--r--[-rwxr-xr-x]src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java72
-rw-r--r--[-rwxr-xr-x]src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java78
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java92
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java19
-rw-r--r--[-rwxr-xr-x]src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java616
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/OutlineShapeXForm.java16
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/Region.java422
-rw-r--r--[-rwxr-xr-x]src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java174
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java561
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java349
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java281
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java351
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java193
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/tess/Triangulation.java2
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java36
-rw-r--r--src/jogl/classes/com/jogamp/graph/font/Font.java189
-rw-r--r--src/jogl/classes/com/jogamp/graph/font/FontFactory.java178
-rw-r--r--src/jogl/classes/com/jogamp/graph/font/FontSet.java40
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/AABBox.java326
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/Outline.java196
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/SVertex.java (renamed from src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java)158
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/Triangle.java85
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/Vertex.java39
-rwxr-xr-xsrc/jogl/classes/com/jogamp/graph/math/Quaternion.java382
-rwxr-xr-xsrc/jogl/classes/com/jogamp/graph/math/VectorUtil.java433
-rw-r--r--src/jogl/classes/com/jogamp/opengl/FBObject.java2491
-rw-r--r--src/jogl/classes/com/jogamp/opengl/FloatUtil.java294
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java117
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java552
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLExtensions.java26
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java627
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLStateKeeper.java100
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GenericGLCapabilitiesChooser.java (renamed from src/jogl/classes/jogamp/graph/math/MathFloat.java)33
-rw-r--r--src/jogl/classes/com/jogamp/opengl/JoglVersion.java122
-rw-r--r--src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java46
-rw-r--r--src/jogl/classes/com/jogamp/opengl/cg/CgException.java20
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Binary16.java569
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Binary32.java116
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Binary64.java116
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FixedPoint.java (renamed from src/jogl/classes/com/jogamp/opengl/util/FixedPoint.java)22
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java2320
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java182
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Matrix4.java152
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Quaternion.java1209
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Ray.java59
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java1192
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Vert2fImmutable.java (renamed from src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UITextShape.java)18
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.java32
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java761
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java398
-rw-r--r--src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java745
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java63
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/Animator.java376
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java558
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/CustomGLEventListener.java63
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java33
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java423
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java316
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java46
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java567
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java368
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java674
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java346
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java487
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java326
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java230
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/Gamma.java130
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java1558
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java1291
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java401
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java236
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/TGAWriter.java116
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java536
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java664
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/TimeFrameI.java81
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/av/AudioSink.java436
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/av/AudioSinkFactory.java68
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java592
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayerFactory.java43
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java249
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java112
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/ImageUtil.java42
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java42
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java400
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java520
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java157
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapCharRec.java30
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapFontRec.java26
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/CoordRec.java20
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java423
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap8x13.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap9x15.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica10.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica12.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica18.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman10.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman24.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeMonoRoman.java694
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeRoman.java632
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeCharRec.java26
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeFontRec.java28
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeRec.java24
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/gl2/TileRenderer.java601
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java601
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java141
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java661
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java175
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java52
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/ShaderSelectionMode.java27
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java77
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java8
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/packrect/BackingStoreManager.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/packrect/Level.java84
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/packrect/LevelSet.java70
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/packrect/Rect.java31
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/packrect/RectVisitor.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/packrect/RectanglePacker.java80
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java68
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/EyePose.java69
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java262
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java160
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceFactory.java99
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceRenderer.java243
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoGLEventListener.java74
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoUtil.java125
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java190
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java371
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java32
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java302
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java599
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java200
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java168
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java214
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java44
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java190
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java177
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java94
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java59
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java57
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java195
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java168
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java164
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java14
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java53
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java43
-rw-r--r--src/jogl/classes/javax/media/opengl/DebugGL2.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/DebugGL3.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/DebugGL3bc.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/DebugGL4.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/DebugGLES2.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java51
-rw-r--r--src/jogl/classes/javax/media/opengl/FPSCounter.java32
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAnimatorControl.java120
-rw-r--r--src/jogl/classes/javax/media/opengl/GLArrayData.java74
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAutoDrawable.java428
-rw-r--r--src/jogl/classes/javax/media/opengl/GLBase.java321
-rw-r--r--src/jogl/classes/javax/media/opengl/GLBufferStorage.java160
-rw-r--r--src/jogl/classes/javax/media/opengl/GLCapabilities.java130
-rw-r--r--src/jogl/classes/javax/media/opengl/GLCapabilitiesChooser.java16
-rw-r--r--src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java37
-rw-r--r--src/jogl/classes/javax/media/opengl/GLContext.java1241
-rw-r--r--src/jogl/classes/javax/media/opengl/GLDebugListener.java8
-rw-r--r--src/jogl/classes/javax/media/opengl/GLDebugMessage.java175
-rw-r--r--src/jogl/classes/javax/media/opengl/GLDrawable.java152
-rw-r--r--src/jogl/classes/javax/media/opengl/GLDrawableFactory.java505
-rw-r--r--src/jogl/classes/javax/media/opengl/GLEventListener.java48
-rw-r--r--src/jogl/classes/javax/media/opengl/GLException.java32
-rw-r--r--src/jogl/classes/javax/media/opengl/GLFBODrawable.java150
-rw-r--r--src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java38
-rw-r--r--src/jogl/classes/javax/media/opengl/GLPbuffer.java96
-rw-r--r--src/jogl/classes/javax/media/opengl/GLPipelineFactory.java66
-rw-r--r--src/jogl/classes/javax/media/opengl/GLProfile.java1337
-rw-r--r--src/jogl/classes/javax/media/opengl/GLRunnable.java20
-rw-r--r--src/jogl/classes/javax/media/opengl/GLRunnable2.java44
-rw-r--r--src/jogl/classes/javax/media/opengl/GLSharedContextSetter.java181
-rw-r--r--src/jogl/classes/javax/media/opengl/GLUniformData.java145
-rw-r--r--src/jogl/classes/javax/media/opengl/Threading.java100
-rw-r--r--src/jogl/classes/javax/media/opengl/TraceGL2.java23
-rw-r--r--src/jogl/classes/javax/media/opengl/TraceGL3.java23
-rw-r--r--src/jogl/classes/javax/media/opengl/TraceGL3bc.java23
-rw-r--r--src/jogl/classes/javax/media/opengl/TraceGL4.java23
-rw-r--r--src/jogl/classes/javax/media/opengl/TraceGLES2.java23
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/ComponentEvents.java14
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java1054
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java2296
-rw-r--r--src/jogl/classes/javax/media/opengl/fixedfunc/GLMatrixFunc.java175
-rw-r--r--src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFunc.java2
-rw-r--r--src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFuncUtil.java21
-rw-r--r--src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallbackAdapter.java42
-rwxr-xr-xsrc/jogl/classes/jogamp/graph/curve/opengl/RegionFactory.java74
-rwxr-xr-xsrc/jogl/classes/jogamp/graph/curve/opengl/RegionRendererImpl01.java93
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java74
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/TextRendererImpl01.java95
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java340
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java586
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java700
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java318
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/AttributeNames.java31
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/UniformNames.java11
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/attributes.glsl23
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2-merged.vp19
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2.vp9
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-gl2.vp6
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_lineAA.glsl19
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl36
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl47
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_weight.glsl32
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp33
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl10
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_allprop01.glsl113
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl96
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl87
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad.glsl41
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad2.glsl41
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl109
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_fxaa3.glsl56
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_poles_bilin1.glsl91
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_polesequal.glsl49
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_polesprop01.glsl65
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_quincunx.glsl28
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_rgss.glsl25
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp17
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp16
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp33
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-xxx.vp12
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2-merged.fp52
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2.fp13
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-gl2.fp6
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-xxx.fp42
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-es2.fp14
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-gl2.fp6
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-xxx.fp82
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-es2.fp14
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-gl2.fp6
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-xxx.fp48
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-es2.fp14
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-gl2.fp6
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-xxx.fp88
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl25
-rw-r--r--src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl13
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java203
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2DExpAddOn.java340
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java16
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/GraphVertex.java38
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/HEdge.java40
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/Loop.java132
-rw-r--r--src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java99
-rw-r--r--src/jogl/classes/jogamp/graph/curve/text/GlyphString.java213
-rw-r--r--src/jogl/classes/jogamp/graph/font/FontConstructor.java14
-rw-r--r--src/jogl/classes/jogamp/graph/font/JavaFontLoader.java98
-rw-r--r--src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java129
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java248
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java54
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java245
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java50
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java307
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/Disassembler.java30
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/Fixed.java14
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/Mnemonic.java12
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/OTFont.java65
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java76
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java50
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/Point.java7
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceData.java8
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceFile.java24
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceHeader.java16
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceMap.java39
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceReference.java30
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceType.java26
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/BaseTable.java322
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CffTable.java330
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Charstring.java2
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CharstringType2.java83
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDef.java12
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDefFormat1.java17
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDefFormat2.java15
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat.java27
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat0.java13
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat2.java57
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat4.java56
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat6.java13
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormatUnknown.java15
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapIndexEntry.java18
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapTable.java31
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Coverage.java6
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CoverageFormat1.java10
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CoverageFormat2.java12
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/CvtTable.java25
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Device.java18
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/DirectoryEntry.java18
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/DsigEntry.java22
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/DsigTable.java31
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Feature.java10
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/FeatureList.java24
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/FeatureRecord.java8
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/FpgmTable.java19
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GaspRange.java21
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GaspTable.java29
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfCompositeComp.java24
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfCompositeDescript.java78
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfDescript.java26
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfSimpleDescript.java50
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfTable.java38
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyphDescription.java24
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GposTable.java19
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GsubTable.java54
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/HdmxTable.java53
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/HeadTable.java47
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/HheaTable.java45
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/HmtxTable.java21
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/ID.java12
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtable.java22
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtableFormat0.java26
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtableFormat2.java22
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernTable.java28
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/KerningPair.java16
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/LangSys.java24
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/LangSysRecord.java8
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Ligature.java14
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSet.java8
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSubst.java4
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSubstFormat1.java17
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/LocaTable.java29
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Lookup.java16
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/LookupList.java24
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/LookupSubtableFactory.java4
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/LtshTable.java31
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/MaxpTable.java25
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/NameRecord.java41
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/NameTable.java36
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Os2Table.java87
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Panose.java31
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/PcltTable.java51
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/PostTable.java57
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/PrepTable.java19
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Program.java10
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/RangeRecord.java14
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Script.java16
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/ScriptList.java26
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/ScriptRecord.java10
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/SignatureBlock.java23
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubst.java6
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubstFormat1.java17
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubstFormat2.java19
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/TTCHeader.java32
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/Table.java12
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableDirectory.java13
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableException.java8
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableFactory.java18
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/VdmxTable.java97
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/VheaTable.java35
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/VmtxTable.java21
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/t2/T2Interpreter.java534
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/tt/engine/Interpreter.java221
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/tt/engine/Parser.java41
-rw-r--r--src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java433
-rw-r--r--src/jogl/classes/jogamp/graph/geom/plane/Crossing.java (renamed from src/jogl/classes/jogamp/graph/math/plane/Crossing.java)253
-rw-r--r--src/jogl/classes/jogamp/graph/geom/plane/IllegalPathStateException.java2
-rw-r--r--src/jogl/classes/jogamp/graph/geom/plane/NoninvertibleTransformException.java2
-rw-r--r--src/jogl/classes/jogamp/graph/geom/plane/Path2D.java130
-rw-r--r--src/jogl/classes/jogamp/opengl/Debug.java99
-rw-r--r--src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java19
-rw-r--r--src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java133
-rw-r--r--src/jogl/classes/jogamp/opengl/FPSCounterImpl.java66
-rw-r--r--src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java512
-rw-r--r--src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java519
-rw-r--r--src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java193
-rw-r--r--src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java214
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java1888
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextShareSet.java307
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java183
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java534
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableHelper.java1342
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableImpl.java230
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java34
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java14
-rw-r--r--src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java528
-rw-r--r--src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationFactory.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java189
-rw-r--r--src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java86
-rw-r--r--src/jogl/classes/jogamp/opengl/GLPbufferImpl.java144
-rw-r--r--src/jogl/classes/jogamp/opengl/GLRunnableTask.java39
-rw-r--r--src/jogl/classes/jogamp/opengl/GLStateTracker.java108
-rw-r--r--src/jogl/classes/jogamp/opengl/GLVersionNumber.java153
-rw-r--r--src/jogl/classes/jogamp/opengl/GLWorkerThread.java53
-rw-r--r--src/jogl/classes/jogamp/opengl/GLXExtensions.java37
-rw-r--r--src/jogl/classes/jogamp/opengl/ListenerSyncedImplStub.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/MemoryObject.java122
-rw-r--r--src/jogl/classes/jogamp/opengl/ProjectFloat.java905
-rw-r--r--src/jogl/classes/jogamp/opengl/SharedResourceRunner.java240
-rw-r--r--src/jogl/classes/jogamp/opengl/SystemUtil.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/ThreadingImpl.java116
-rw-r--r--src/jogl/classes/jogamp/opengl/ToolkitThreadingPlugin.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java448
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java34
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java400
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/AWTUtil.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/Java2D.java380
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java52
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/VersionApplet.java49
-rw-r--r--src/jogl/classes/jogamp/opengl/cg/CgPackagePlaceholder.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java53
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLContext.java205
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java293
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java39
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java674
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java49
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java64
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java33
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java59
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java25
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java399
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java192
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java45
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java10
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java50
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java149
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/gl2/ProjectDouble.java415
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java278
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/Glue.java20
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/error/Error.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2CurveEvaluator.java59
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2SurfaceEvaluator.java71
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GLUgl2nurbsImpl.java201
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java1118
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1010102.java38
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1555rev.java38
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract2101010rev.java38
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract233rev.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract332.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444.java38
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444rev.java38
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract5551.java38
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565.java36
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565rev.java36
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888.java38
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888rev.java38
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractFloat.java20
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractPrimitive.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSByte.java24
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSInt.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java579
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java441
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java557
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/PixelStorageModes.java46
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ScaleInternal.java601
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Type_Widget.java114
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Arc.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/ArcSdirSorter.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTdirSorter.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTesselator.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Backend.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Bin.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Breakpt.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfArcs.java56
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfBreakpts.java38
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfFloats.java56
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfQuiltspecs.java46
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Curve.java64
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Curvelist.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/DisplayList.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Flist.java12
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Knotspec.java94
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Knotvector.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Mapdesc.java47
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Maplist.java19
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbscurve.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbssurface.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Patch.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Patchlist.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Property.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/PwlArc.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Quilt.java36
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Renderhints.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Splinespec.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Subdivider.java211
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/TrimVertex.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/registry/Registry.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/Dict.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/GLUhalfEdge.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/GLUtessellatorImpl.java51
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/Geom.java46
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/Mesh.java96
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/Normal.java25
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQ.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQHeap.java51
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQSort.java36
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/Render.java51
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/Sweep.java165
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/TessMono.java14
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java972
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java42
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java220
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java24
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java235
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java35
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java54
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java66
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java115
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java95
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java79
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java60
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java27
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java121
-rw-r--r--src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java980
-rw-r--r--src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/shader/texture01_xxx.fp19
-rw-r--r--src/jogl/classes/jogamp/opengl/shader/texture01_xxx.vp19
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java43
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLArrayHandlerFlat.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLArrayHandlerInterleaved.java67
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLDataArrayHandler.java58
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandler.java64
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java51
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLVBOArrayHandler.java71
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/AudioSampleFormat.java64
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java79
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java1690
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/JavaSoundAudioSink.java228
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/NullAudioSink.java181
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java143
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/VideoPixelFormat.java191
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java449
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java1046
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java82
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java41
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java78
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java78
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java78
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java142
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java112
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java76
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java72
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java192
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java384
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java1245
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp28
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.vp6
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorLight.vp16
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp136
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.fp47
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.vp40
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_alphatest.fp33
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_attribute.glsl28
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_const.glsl31
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_lightdef.glsl3
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_settexcoord.vp6
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform.glsl43
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform_light.glsl1
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_varying.glsl2
-rw-r--r--src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java1520
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java71
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/FilterWriteStrategy.java20
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java64
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java376
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java329
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java107
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngDeinterlacer.java277
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngHelper.java213
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java270
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java86
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java1416
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java731
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjBadCrcException.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjException.java10
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java24
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjInputException.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjOutputException.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java9
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java27
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkCopyBehaviour.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java433
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkList.java282
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java30
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkPredicate.java14
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java109
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java181
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java176
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java266
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java64
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java68
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java42
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java42
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java53
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java31
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIHDR.java65
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java60
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java28
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkOFFS.java89
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java52
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPLTE.java49
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSBIT.java54
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java79
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSRGB.java36
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSTER.java60
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java45
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSkipped.java41
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java40
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTIME.java54
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java270
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTextVar.java14
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java33
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java46
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java227
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/package.html5
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/DistortionMesh.java95
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDevice.java468
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceFactory.java43
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceRenderer.java605
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/ScaleAndOffset2D.java107
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.fp26
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.vp33
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.fp22
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.vp27
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp.vp44
-rw-r--r--src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp_chroma.vp65
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java110
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java33
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java67
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java83
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java41
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java17
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java49
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java156
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java114
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java240
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java24
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java555
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java587
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java315
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java51
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/GLXUtil.java127
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java82
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java46
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java403
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java431
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java37
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java449
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java245
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java48
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java67
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java54
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java73
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java34
-rw-r--r--src/jogl/native/GLContext.c46
-rw-r--r--src/jogl/native/GLDebugMessageHandler.c103
-rw-r--r--src/jogl/native/JoglCommon.c115
-rw-r--r--src/jogl/native/JoglCommon.h55
-rw-r--r--src/jogl/native/libav/ffmpeg_dshow.c215
-rw-r--r--src/jogl/native/libav/ffmpeg_dshow.h47
-rw-r--r--src/jogl/native/libav/ffmpeg_impl_template.c1615
-rw-r--r--src/jogl/native/libav/ffmpeg_lavc53_lavf53_lavu51.c33
-rw-r--r--src/jogl/native/libav/ffmpeg_lavc54_lavf54_lavu52_lavr01.c33
-rw-r--r--src/jogl/native/libav/ffmpeg_lavc55_lavf55_lavu53_lavr01.c33
-rw-r--r--src/jogl/native/libav/ffmpeg_static.c91
-rw-r--r--src/jogl/native/libav/ffmpeg_static.h50
-rw-r--r--src/jogl/native/libav/ffmpeg_tool.h122
-rw-r--r--src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c717
-rw-r--r--src/jogl/native/macosx/MacOSXCustomCGLCode.c2
-rw-r--r--src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m673
-rw-r--r--src/jogl/native/macosx/MacOSXWindowSystemInterface.m100
-rw-r--r--src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c9
-rw-r--r--src/jogl/native/openmax/omx_tool.c12
-rw-r--r--src/jogl/native/openmax/omx_tool.h4
-rw-r--r--src/jogl/native/timespec.c5
-rw-r--r--src/jogl/native/timespec.h3
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java12
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java35
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/MutableGraphicsConfiguration.java13
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java22
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java46
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/UpstreamWindowHookMutableSizePos.java56
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java59
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsDevice.java20
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsScreen.java33
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTPrintLifecycle.java175
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java85
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/AppContextInfo.java199
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java297
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java624
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java58
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/macosx/MacOSXGraphicsDevice.java13
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java523
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/windows/WindowsGraphicsDevice.java17
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsConfiguration.java22
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java82
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java31
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java17
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java69
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java16
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/Capabilities.java99
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/CapabilitiesChooser.java16
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/CapabilitiesImmutable.java10
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/DefaultCapabilitiesChooser.java36
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java54
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java127
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java22
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java124
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java4
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java102
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/NativeSurfaceHolder.java41
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java122
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/NativeWindowException.java20
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java549
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerOption.java12
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java44
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java77
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java97
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java12
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java38
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java38
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/VisualIDHolder.java45
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java6
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/package.html94
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java66
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/DimensionImmutable.java13
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/Insets.java89
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/InsetsImmutable.java23
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java197
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java373
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java194
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/Point.java77
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/PointImmutable.java15
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java187
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java33
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java54
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/Debug.java98
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java13
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java82
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java39
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java29
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java38
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java110
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java (renamed from src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java)74
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java152
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java172
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java46
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java47
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java98
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/WrappedWindow.java120
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java164
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTJNILibLoader.java27
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java488
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/JAWT_PlatformInfo.java14
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java341
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/windows/Win32SunJDKReflection.java31
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java39
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java44
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java29
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java22
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java350
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java24
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java35
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java95
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java22
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java71
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java6
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java54
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java45
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java406
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java50
-rw-r--r--src/nativewindow/native/JAWT_DrawingSurfaceInfo.c2
-rw-r--r--src/nativewindow/native/NativewindowCommon.c117
-rw-r--r--src/nativewindow/native/NativewindowCommon.h64
-rw-r--r--src/nativewindow/native/macosx/NativeWindowProtocols.h (renamed from src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionRendererListenerBase01.java)58
-rw-r--r--src/nativewindow/native/macosx/OSXmisc.m833
-rw-r--r--src/nativewindow/native/win32/DeviceDriverQuery.txt41
-rw-r--r--src/nativewindow/native/win32/GDImisc.c542
-rw-r--r--src/nativewindow/native/win32/WindowsDWM.h2
-rw-r--r--src/nativewindow/native/x11/Xmisc.c453
-rw-r--r--src/nativewindow/native/x11/Xmisc.h2
-rw-r--r--src/newt/classes/com/jogamp/newt/Display.java326
-rw-r--r--src/newt/classes/com/jogamp/newt/MonitorDevice.java299
-rw-r--r--src/newt/classes/com/jogamp/newt/MonitorMode.java458
-rw-r--r--src/newt/classes/com/jogamp/newt/NewtFactory.java186
-rw-r--r--src/newt/classes/com/jogamp/newt/NewtVersion.java21
-rw-r--r--src/newt/classes/com/jogamp/newt/Screen.java197
-rw-r--r--src/newt/classes/com/jogamp/newt/ScreenMode.java208
-rw-r--r--src/newt/classes/com/jogamp/newt/Window.java332
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java979
-rw-r--r--[-rwxr-xr-x]src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java145
-rw-r--r--src/newt/classes/com/jogamp/newt/event/DoubleTapScrollGesture.java349
-rw-r--r--src/newt/classes/com/jogamp/newt/event/GestureHandler.java155
-rw-r--r--src/newt/classes/com/jogamp/newt/event/InputEvent.java168
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyAdapter.java18
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyEvent.java1413
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyListener.java36
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MonitorEvent.java73
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java (renamed from src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java)12
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MouseAdapter.java34
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MouseEvent.java580
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MouseListener.java47
-rw-r--r--src/newt/classes/com/jogamp/newt/event/NEWTEvent.java146
-rw-r--r--src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java14
-rw-r--r--src/newt/classes/com/jogamp/newt/event/NEWTEventFiFo.java14
-rw-r--r--src/newt/classes/com/jogamp/newt/event/NEWTEventListener.java12
-rw-r--r--src/newt/classes/com/jogamp/newt/event/OutputEvent.java51
-rw-r--r--src/newt/classes/com/jogamp/newt/event/PinchToZoomGesture.java252
-rw-r--r--src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java22
-rw-r--r--src/newt/classes/com/jogamp/newt/event/TraceMouseAdapter.java36
-rw-r--r--src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java33
-rw-r--r--src/newt/classes/com/jogamp/newt/event/WindowAdapter.java31
-rw-r--r--src/newt/classes/com/jogamp/newt/event/WindowEvent.java34
-rw-r--r--src/newt/classes/com/jogamp/newt/event/WindowListener.java28
-rw-r--r--src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java14
-rw-r--r--src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java180
-rw-r--r--src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java72
-rw-r--r--src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java136
-rw-r--r--src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java183
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java513
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java386
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java280
-rw-r--r--src/newt/classes/com/jogamp/newt/util/EDTUtil.java77
-rw-r--r--src/newt/classes/com/jogamp/newt/util/MainThread.java131
-rw-r--r--src/newt/classes/com/jogamp/newt/util/MonitorMode.java102
-rw-r--r--src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java258
-rw-r--r--src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java341
-rw-r--r--src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtApplet3Run.java360
-rw-r--r--[-rwxr-xr-x]src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java (renamed from src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java)218
-rw-r--r--src/newt/classes/com/jogamp/newt/util/applet/VersionApplet3.java226
-rw-r--r--src/newt/classes/jogamp/newt/Debug.java99
-rw-r--r--src/newt/classes/jogamp/newt/DefaultEDTUtil.java294
-rw-r--r--src/newt/classes/jogamp/newt/DisplayImpl.java566
-rw-r--r--src/newt/classes/jogamp/newt/MonitorDeviceImpl.java146
-rw-r--r--src/newt/classes/jogamp/newt/MonitorModeProps.java418
-rw-r--r--src/newt/classes/jogamp/newt/NEWTJNILibLoader.java47
-rw-r--r--src/newt/classes/jogamp/newt/OffscreenWindow.java65
-rw-r--r--src/newt/classes/jogamp/newt/PointerIconImpl.java171
-rw-r--r--src/newt/classes/jogamp/newt/ScreenImpl.java739
-rw-r--r--src/newt/classes/jogamp/newt/ScreenModeStatus.java231
-rw-r--r--src/newt/classes/jogamp/newt/ScreenMonitorState.java195
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java2916
-rw-r--r--src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java26
-rw-r--r--src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java687
-rw-r--r--src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java152
-rw-r--r--src/newt/classes/jogamp/newt/driver/DriverClearFocus.java6
-rw-r--r--src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java12
-rw-r--r--src/newt/classes/jogamp/newt/driver/PNGIcon.java80
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java13
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/MD.java36
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java325
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java107
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java12
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java153
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/WindowDriver.java603
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java433
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java50
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java125
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java221
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java27
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java98
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java290
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java18
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java82
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java47
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java147
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java89
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java191
-rw-r--r--src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java20
-rw-r--r--src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java88
-rw-r--r--src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java40
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java18
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java92
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java46
-rw-r--r--src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java959
-rw-r--r--src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java109
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java83
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java419
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java220
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java755
-rw-r--r--src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java89
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java91
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java162
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java298
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java142
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR.java86
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR11.java370
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR13.java274
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java445
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java392
-rw-r--r--src/newt/classes/jogamp/newt/event/NEWTEventTask.java18
-rw-r--r--src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java370
-rw-r--r--src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java396
-rw-r--r--src/newt/native/InputEvent.h31
-rw-r--r--src/newt/native/KDWindow.c12
-rw-r--r--src/newt/native/KeyEvent.h388
-rw-r--r--src/newt/native/MacWindow.m975
-rw-r--r--src/newt/native/NewtCommon.c99
-rw-r--r--src/newt/native/NewtCommon.h26
-rw-r--r--src/newt/native/NewtMacWindow.h126
-rw-r--r--src/newt/native/NewtMacWindow.m1267
-rw-r--r--src/newt/native/ScreenMode.h16
-rw-r--r--src/newt/native/Window.h17
-rw-r--r--src/newt/native/WindowsWindow.c2236
-rw-r--r--src/newt/native/X11Common.h5
-rw-r--r--src/newt/native/X11Display.c424
-rw-r--r--src/newt/native/X11Event.c305
-rw-r--r--src/newt/native/X11Event.h9
-rw-r--r--src/newt/native/X11RandR11.c371
-rw-r--r--src/newt/native/X11RandR13.c519
-rw-r--r--src/newt/native/X11Screen.c422
-rw-r--r--src/newt/native/X11Screen.h38
-rw-r--r--src/newt/native/X11Window.c366
-rw-r--r--src/newt/native/XCBEvent.c308
-rw-r--r--src/newt/native/XCBEvent.h10
-rw-r--r--src/newt/native/bcm_vc_iv.c373
-rw-r--r--src/newt/native/bcm_vc_iv.h130
-rw-r--r--src/oculusvr/classes/com/jogamp/oculusvr/OVRDynamicLibraryBundleInfo.java113
-rw-r--r--src/oculusvr/classes/com/jogamp/oculusvr/OVRException.java57
-rw-r--r--src/oculusvr/classes/com/jogamp/oculusvr/OVRVersion.java155
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java219
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java (renamed from src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java)60
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java604
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java173
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_chroma.fp26
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_chroma.vp33
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_plain.fp22
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_plain.vp27
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_timewarp.vp44
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_timewarp_chroma.vp65
-rw-r--r--src/oculusvr/native/OVRImplMisc.cpp30
-rw-r--r--src/test-native/Bug907GetAllWindowNamesViaMessageDispatch.c34
-rw-r--r--src/test-native/contextRetargetDrawable01.c154
-rw-r--r--src/test-native/contextRetargetDrawable02.c382
-rw-r--r--src/test-native/displayMultiple02_mch.c130
-rw-r--r--src/test-native/displayMultiple02_new_mch.c199
-rw-r--r--src/test-native/glExtensionsListGL2.c2
-rw-r--r--src/test-native/glExtensionsListGL3.c25
-rwxr-xr-xsrc/test-native/make.sh4
-rw-r--r--src/test/com/jogamp/opengl/test/android/LauncherUtil.java310
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java119
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieCubeActivity0a.java166
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieCubeActivity0b.java168
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0a.java (renamed from src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java)53
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0b.java86
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1a.java86
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1b.java86
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java134
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java286
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java49
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00c.java (renamed from src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java)49
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java46
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java46
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java46
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java45
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTElektronActivityLauncher.java22
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java45
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGearsES1ActivityLauncher.java22
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java102
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java42
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGearsES2ECTActivityLauncher.java80
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGearsES2RGB565ActivityLauncher.java80
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java53
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivityLauncher.java26
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java45
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java23
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java47
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivityLauncher.java23
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java45
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1ActivityLauncher.java23
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java55
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java12
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java55
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync0-flush-wait-finish.log751
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync1-flush-wait-finish.log745
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait-exclctx.log751
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait.log751
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync1-finish-wait.log745
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java430
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java429
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java272
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug735Inv3AppletAWT.java218
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Bug735Inv4AWT.java202
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/DemoBug910ExtendedAWTAppletLifecycleCheck.java235
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Issue326Test1.java48
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Issue326Test2.java39
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Issue344Base.java56
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Issue344Test1.java4
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Issue344Test2.java2
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Issue344Test3.java2
-rw-r--r--src/test/com/jogamp/opengl/test/bugs/Issue344Test4.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/FontSet01.java35
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java93
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java249
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java447
-rw-r--r--[-rwxr-xr-x]src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java155
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java214
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java224
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java287
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java77
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java132
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo.java156
-rwxr-xr-xsrc/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java98
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java93
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java225
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java45
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo.java (renamed from src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java)114
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo01.java90
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java382
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener02.java9
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener04.java7
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java1189
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java189
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java154
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo01.java48
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo02.java49
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/MSAATool.java65
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/button-pressed-145x53.pngbin0 -> 8603 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/button-released-145x53.pngbin0 -> 9429 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/CrossHair.java110
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/GLEventListenerButton.java132
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/ImageSeqButton.java63
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java86
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java105
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java174
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/MediaPlayerButton.java131
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java271
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RoundButton.java135
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java617
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TextureSeqButton.java79
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIGLListener01.java99
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java182
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UINewtDemo01.java38
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java575
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMono.ttfbin0 -> 592632 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoBold.ttfbin0 -> 299136 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoBoldOblique.ttfbin0 -> 298940 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoOblique.ttfbin0 -> 395188 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSans.ttfbin0 -> 1563256 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansBold.ttfbin0 -> 416128 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansBoldOblique.ttfbin0 -> 342492 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansOblique.ttfbin0 -> 763676 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerif.ttfbin0 -> 3303588 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifBold.ttfbin0 -> 1310828 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifBoldItalic.ttfbin0 -> 608676 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifItalic.ttfbin0 -> 922104 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java140
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00BaseAWT.java120
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrentNEWT.java)177
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java40
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java293
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove02GLWindowNewtCanvasAWT.java289
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove03GLWindowNEWT.java147
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.java138
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext02NEWT.java135
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug692GL3VAONEWT.java444
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestCPUSourcingAPINEWT.java226
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java43
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java310
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java143
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java151
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java152
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java138
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java164
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java210
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java)233
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java384
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java185
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java179
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java253
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java176
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java114
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java175
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java126
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLException01NEWT.java412
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java57
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java226
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java203
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLOffscreenAutoDrawableBug1044AWT.java106
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLPointsNEWT.java159
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java61
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java985
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLCanvasAWT.java212
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java215
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java226
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java204
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java240
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java88
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java104
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLCanvasAWT.java19
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLWindowNEWT.java27
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java153
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java69
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNVSwapGroupNEWT.java57
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java115
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java112
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java49
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java64
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java43
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java52
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java469
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java95
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java399
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java323
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT.java242
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java271
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java333
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java359
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java396
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT4.java231
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java369
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextWithJTabbedPaneAWT.java267
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java108
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java101
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestVersionSemanticsNOUI.java126
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestX11DefaultDisplay.java147
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java129
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAWTCardLayoutAnimatorStartStopBug532.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java)107
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java301
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java267
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java424
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00AWT.java164
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00NEWT.java97
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java217
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10AWT.java164
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10NEWT.java97
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimAWT.java74
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimNEWT.java70
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimAWT.java73
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimNEWT.java70
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext11VSyncAnimNEWT.java70
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext12FPSAnimNEWT.java70
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase0.java264
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase1.java291
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java154
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java)293
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02AWT.java129
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02NEWT.java100
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java277
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java121
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java147
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch13Newt2AWT.java195
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/ManualHiDPIBufferedImage01AWT.java71
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java55
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java42
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java161
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLJPanelRecreate01.java241
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug460GLCanvasNPEAWT.java23
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java108
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461PBufferSupersamplingSwingAWT.java98
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug551AWT.java41
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java170
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug611AWT.java27
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug642JSplitPaneMixHwLw01AWT.java199
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java287
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug675BeansInDesignTimeAWT.java113
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java262
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java194
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java475
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java152
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java166
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java172
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java174
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java152
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java152
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock00AWT.java244
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java351
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java670
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelResize01AWT.java209
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java315
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestIsRealizedConcurrency01AWT.java104
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java82
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestSwingAWT01GLn.java31
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java73
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TextRendererGLEventListener01.java52
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TextRendererTraceGL2Mock01.java46
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleChooser01.java10
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java190
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java179
-rw-r--r--[-rwxr-xr-x]src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java45
-rw-r--r--[-rwxr-xr-x]src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java69
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java49
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java58
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java56
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/GLFinishOnDisplay.java47
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java169
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/PointsDemo.java (renamed from src/jogl/classes/jogamp/graph/font/FontInt.java)29
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java11
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureSequenceDemo01.java118
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java275
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java73
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java40
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java359
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OneTriangle.java36
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java200
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java178
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java54
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestOlympicES1NEWT.java144
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java51
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java226
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java266
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java645
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java120
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java189
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java196
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java96
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java209
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java214
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java281
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java221
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java285
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java335
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java211
-rw-r--r--[-rwxr-xr-x]src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java645
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java872
-rw-r--r--[-rwxr-xr-x]src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java1096
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas01.java134
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02a.java89
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02b.java89
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03a.java102
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03b.java101
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug848AppletGLCanvas01.java94
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java441
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java514
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java422
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java46
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java540
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java550
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java377
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java180
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java222
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java107
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.fp47
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.vp47
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp19
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.java18
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp15
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp22
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/default.vp5
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.fp11
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.vp5
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.fp12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.vp5
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.fp10
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.vp7
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.fp339
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.vp11
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp10
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp4
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/ruler.fp9
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.fp10
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.vp5
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.fp14
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.vp5
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp14
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java337
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java483
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java149
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java80
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/Bug818GLJPanelAndGLCanvasApplet.java318
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/GLJPanelsAndGLCanvasDemoGL2Applet.java180
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java72
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java57
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java66
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java248
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java32
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java104
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestTeapotNEWT.java162
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java292
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/newt/TestGeomShader01TextureGL3NEWT.java129
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/flipXYZ01_xxx.gp32
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/passthrough01_xxx.gp31
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.fp20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.vp20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/IInstancedRenderingView.java33
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TessellationShader01aGLSL440CoreHardcoded.java225
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TessellationShader01bGL4.java154
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TriangleInstancedRendererWithShaderState.java269
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TrianglesInstancedRendererHardcoded.java285
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/awt/TestInstancedReneringGL4AWT.java244
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/newt/TestInstancedReneringGL4NEWT.java108
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/newt/TestTessellationShader01GL4NEWT.java117
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.fp6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.tcp12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.tep8
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.vp12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/triangles.fp15
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/triangles.vp17
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java213
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java415
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java257
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java33
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java313
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java91
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestTransformFeedbackVaryingsBug407NEWT.java76
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug365TextureGenerateMipMaps.java272
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug463ScaleImageMemoryAWT.java73
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug694ScaleImageUnpackBufferSizeAWT.java164
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary16NOUI.java715
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary32NOUI.java93
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary64NOUI.java93
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil01NOUI.java282
-rw-r--r--[-rwxr-xr-x]src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil02MatrixMatrixMultNOUI.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFloatUtil01MatrixMatrixMultNOUI.java)63
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil03InversionNOUI.java262
-rw-r--r--[-rwxr-xr-x]src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectDoubleNOUI.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectDoubleNOUI.java)21
-rw-r--r--[-rwxr-xr-x]src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectFloatNOUI.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectFloatNOUI.java)87
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java473
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix02NOUI.java112
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix03NOUI.java151
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/math/TestQuaternion01NOUI.java817
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java104
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBuffer2File.java20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBuffer2Screen.java56
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java24
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java30
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen01GLPBufferNEWT.java97
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen02BitmapNEWT.java61
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/offscreen/WindowUtilNEWT.java28
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit01AWT.java329
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit02AWT.java512
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLWindowInit03NEWT.java214
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001RawInit00NEWT.java234
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java366
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java333
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java340
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java428
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java116
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java90
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java350
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java51
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java88
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/OffscreenPrintable.java182
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/OnscreenPrintable.java165
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/PrintableBase.java88
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java193
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java261
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java279
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java286
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java411
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java408
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java320
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java243
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java263
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java273
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TransparentPanel.java59
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1ImmModeSink.java121
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1Plain.java189
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java164
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES2ImmModeSink.java193
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/TestES1FixedFunctionPipelineNEWT.java154
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES1NEWT.java143
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES2NEWT.java120
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/TestPNGImage01NEWT.java41
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java54
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java98
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java130
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java49
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java47
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java55
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java47
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java166
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java154
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java270
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java284
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java226
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java207
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java106
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java197
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java364
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java105
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java181
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java120
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java168
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java66
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01NEWT.java42
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_gimpexp.pngbin0 -> 1927 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_orig.pngbin0 -> 2129 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug744-rle32.tgabin0 -> 129555 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug745_qttdef_post_frame.jpgbin0 -> 8415 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug982.rle32.256x256.tgabin0 -> 30510 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/cross-grey-alpha-16x16.pngbin0 -> 286 bytes
-rw-r--r--[-rwxr-xr-x]src/test/com/jogamp/opengl/test/junit/jogl/util/texture/grayscale_texture.pngbin4873 -> 4873 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j1-baseline.jpgbin0 -> 21257 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j2-progressive.jpgbin0 -> 22306 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j3-baseline_gray.jpgbin0 -> 17776 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/pointer-grey-alpha-16x24.pngbin0 -> 511 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT1.ddsbin0 -> 1512 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT5.ddsbin0 -> 2896 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_uncompressed.ddsbin0 -> 8321 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-cmyk-01.jpgbin0 -> 10445 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG3-01-160x90.pngbin0 -> 3745 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG4-01-160x90.pngbin0 -> 4240 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_3-01-160x90.pngbin0 -> 3729 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_4-01-160x90.pngbin0 -> 4224 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscNG4-01-160x90.pngbin0 -> 4240 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-base.jpgbin0 -> 2628 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpgbin0 -> 2376 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpgbin0 -> 4122 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-prog.jpgbin0 -> 4411 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90.pngbin0 -> 2785 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_4-01-160x90.pngbin0 -> 3177 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_3-01-160x90.pngbin0 -> 1898 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_4-01-160x90.pngbin0 -> 1911 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-u32.tgabin0 -> 65580 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ycck-01.jpgbin0 -> 62492 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java140
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java35
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java53
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java68
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestEventSourceNotAWTBug.java19
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowInvisiblePointer01NEWT.java117
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowWarpPointer01NEWT.java174
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java37
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java105
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java153
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows03NEWTAnimResize.java138
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestListenerCom01AWT.java41
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestMultipleNewtCanvasAWT.java185
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java49
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java45
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java142
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java355
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java189
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java187
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestWindowAndPointerIconNEWT.java142
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java80
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java33
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java73
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java71
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom1.java18
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom2.java22
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom3.java18
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java784
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java106
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java87
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java120
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasSWTAWT.java182
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java308
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java292
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java319
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java262
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java240
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus01SwingAWTRobot.java (renamed from src/test/com/jogamp/opengl/test/junit/newt/TestFocus01SwingAWTRobot.java)99
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus02SwingAWTRobot.java (renamed from src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java)187
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus03KeyTraversalAWT.java (renamed from src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java)173
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/ManualScreenMode03aNEWT.java (renamed from src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java)83
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java236
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00bNEWT.java (renamed from src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java)74
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java282
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java267
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java285
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java275
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01dNEWT.java425
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java253
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java261
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/GLRunnableDummy.java14
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/KeyAction.java19
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java229
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java212
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java139
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java46
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java57
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java59
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java127
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java251
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java56
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java69
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java61
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java67
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java81
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentChildWindowBug632NEWT.java135
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java68
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/WindowAction.java16
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/AWTFocusAdapter.java37
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java85
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java76
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java720
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/AWTWindowFocusAdapter.java35
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/DumpGLInfo.java22
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/EventCountAdapter.java19
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/EventCountAdapterUtil.java18
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/FocusEventCountAdapter.java10
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/GLEventListenerCounter.java69
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/GLSLSimpleProgram.java30
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java17
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java36
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java205
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/NEWTFocusAdapter.java47
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java88
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java101
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java213
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java75
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java40
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/UITestCase.java344
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/ValidateLockListener.java (renamed from src/test/com/jogamp/opengl/test/junit/graph/demos/ui/opengl/UIRegion.java)76
-rw-r--r--src/test/jogamp/newt/WindowImplAccess.java12
1518 files changed, 184062 insertions, 60821 deletions
diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/Audio.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/Audio.java
index 2b51be164..fef9d61dd 100644
--- a/src/jogl/classes/com/jogamp/audio/windows/waveout/Audio.java
+++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/Audio.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -36,7 +36,7 @@ import java.io.*;
public class Audio {
private static Audio instance = null;
- private Mixer mixer;
+ private final Mixer mixer;
public synchronized static Audio getInstance() {
if (instance == null) {
@@ -53,9 +53,9 @@ public class Audio {
return mixer;
}
- public Track newTrack(File file) throws IOException
+ public Track newTrack(final File file) throws IOException
{
- Track res = new Track(file);
+ final Track res = new Track(file);
mixer.add(res);
return res;
}
diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java
index 60972873e..bbfe72b08 100644
--- a/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java
+++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -48,12 +48,12 @@ public class Mixer {
private volatile boolean shutdownDone;
// Windows Event object
- private long event;
+ private final long event;
- private volatile ArrayList/*<Track>*/ tracks = new ArrayList();
+ private volatile ArrayList<Track> tracks = new ArrayList<Track>();
- private Vec3f leftSpeakerPosition = new Vec3f(-1, 0, 0);
- private Vec3f rightSpeakerPosition = new Vec3f( 1, 0, 0);
+ private final Vec3f leftSpeakerPosition = new Vec3f(-1, 0, 0);
+ private final Vec3f rightSpeakerPosition = new Vec3f( 1, 0, 0);
private float falloffFactor = 1.0f;
@@ -64,7 +64,7 @@ public class Mixer {
private Mixer() {
event = CreateEvent();
new FillerThread().start();
- MixerThread m = new MixerThread();
+ final MixerThread m = new MixerThread();
m.setPriority(Thread.MAX_PRIORITY - 1);
m.start();
}
@@ -73,14 +73,14 @@ public class Mixer {
return mixer;
}
- synchronized void add(Track track) {
- ArrayList/*<Track>*/ newTracks = (ArrayList) tracks.clone();
+ synchronized void add(final Track track) {
+ final ArrayList<Track> newTracks = new ArrayList<Track>(tracks);
newTracks.add(track);
tracks = newTracks;
}
- synchronized void remove(Track track) {
- ArrayList/*<Track>*/ newTracks = (ArrayList) tracks.clone();
+ synchronized void remove(final Track track) {
+ final ArrayList<Track> newTracks = new ArrayList<Track>(tracks);
newTracks.remove(track);
tracks = newTracks;
}
@@ -88,14 +88,14 @@ public class Mixer {
// NOTE: due to a bug on the APX device, we only have mono sounds,
// so we currently only pay attention to the position of the left
// speaker
- public void setLeftSpeakerPosition(float x, float y, float z) {
+ public void setLeftSpeakerPosition(final float x, final float y, final float z) {
leftSpeakerPosition.set(x, y, z);
}
// NOTE: due to a bug on the APX device, we only have mono sounds,
// so we currently only pay attention to the position of the left
// speaker
- public void setRightSpeakerPosition(float x, float y, float z) {
+ public void setRightSpeakerPosition(final float x, final float y, final float z) {
rightSpeakerPosition.set(x, y, z);
}
@@ -109,7 +109,7 @@ public class Mixer {
falloffFactor + r^2
</PRE>
*/
- public void setFalloffFactor(float factor) {
+ public void setFalloffFactor(final float factor) {
falloffFactor = factor;
}
@@ -119,7 +119,7 @@ public class Mixer {
SetEvent(event);
try {
shutdownLock.wait();
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
}
}
}
@@ -129,15 +129,16 @@ public class Mixer {
super("Mixer Thread");
}
+ @Override
public void run() {
while (!shutdown) {
- List/*<Track>*/ curTracks = tracks;
+ final List<Track> curTracks = tracks;
- for (Iterator iter = curTracks.iterator(); iter.hasNext(); ) {
- Track track = (Track) iter.next();
+ for (final Iterator<Track> iter = curTracks.iterator(); iter.hasNext(); ) {
+ final Track track = iter.next();
try {
track.fill();
- } catch (IOException e) {
+ } catch (final IOException e) {
e.printStackTrace();
remove(track);
}
@@ -146,7 +147,7 @@ public class Mixer {
try {
// Run ten times per second
Thread.sleep(100);
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
e.printStackTrace();
}
}
@@ -157,7 +158,7 @@ public class Mixer {
// Temporary mixing buffer
// Interleaved left and right channels
float[] mixingBuffer;
- private Vec3f temp = new Vec3f();
+ private final Vec3f temp = new Vec3f();
MixerThread() {
super("Mixer Thread");
@@ -166,10 +167,11 @@ public class Mixer {
}
}
+ @Override
public void run() {
while (!shutdown) {
// Get the next buffer
- long mixerBuffer = getNextMixerBuffer();
+ final long mixerBuffer = getNextMixerBuffer();
if (mixerBuffer != 0) {
ByteBuffer buf = getMixerBufferData(mixerBuffer);
@@ -201,27 +203,27 @@ public class Mixer {
// This assertion should be in place if we have stereo
if ((mixingBuffer.length % 2) != 0) {
- String msg = "FATAL ERROR: odd number of samples in the mixing buffer";
+ final String msg = "FATAL ERROR: odd number of samples in the mixing buffer";
System.out.println(msg);
throw new InternalError(msg);
}
// Run down all of the registered tracks mixing them in
- List/*<Track>*/ curTracks = tracks;
+ final List<Track> curTracks = tracks;
- for (Iterator iter = curTracks.iterator(); iter.hasNext(); ) {
- Track track = (Track) iter.next();
+ for (final Iterator<Track> iter = curTracks.iterator(); iter.hasNext(); ) {
+ final Track track = iter.next();
// Consider only playing tracks
if (track.isPlaying()) {
// First recompute its gain
- Vec3f pos = track.getPosition();
- float leftGain = gain(pos, leftSpeakerPosition);
- float rightGain = gain(pos, rightSpeakerPosition);
+ final Vec3f pos = track.getPosition();
+ final float leftGain = gain(pos, leftSpeakerPosition);
+ final float rightGain = gain(pos, rightSpeakerPosition);
// Now mix it in
int i = 0;
while (i < mixingBuffer.length) {
if (track.hasNextSample()) {
- float sample = track.nextSample();
+ final float sample = track.nextSample();
mixingBuffer[i++] = sample * leftGain;
mixingBuffer[i++] = sample * rightGain;
} else {
@@ -238,7 +240,7 @@ public class Mixer {
// Now that we have our data, send it down to the card
int outPos = 0;
for (int i = 0; i < mixingBuffer.length; i++) {
- short val = (short) mixingBuffer[i];
+ final short val = (short) mixingBuffer[i];
buf.put(outPos++, (byte) val);
buf.put(outPos++, (byte) (val >> 8));
}
@@ -277,9 +279,9 @@ public class Mixer {
// falloffFactor
// -------------------
// falloffFactor + r^2
- private float gain(Vec3f pos, Vec3f speakerPos) {
+ private float gain(final Vec3f pos, final Vec3f speakerPos) {
temp.sub(pos, speakerPos);
- float dotp = temp.dot(temp);
+ final float dotp = temp.dot(temp);
return (falloffFactor / (falloffFactor + dotp));
}
}
@@ -319,8 +321,8 @@ public class Mixer {
private static Constructor directByteBufferConstructor;
private static Map createdBuffers = new HashMap(); // Map Long, ByteBuffer
- private static ByteBuffer newDirectByteBuffer(long address, long capacity) {
- Long key = new Long(address);
+ private static ByteBuffer newDirectByteBuffer(final long address, final long capacity) {
+ final Long key = Long.valueOf(address);
ByteBuffer buf = (ByteBuffer) createdBuffers.get(key);
if (buf == null) {
buf = newDirectByteBufferImpl(address, capacity);
@@ -330,30 +332,30 @@ public class Mixer {
}
return buf;
}
- private static ByteBuffer newDirectByteBufferImpl(long address, long capacity) {
+ private static ByteBuffer newDirectByteBufferImpl(final long address, final long capacity) {
if (directByteBufferClass == null) {
try {
directByteBufferClass = Class.forName("java.nio.DirectByteBuffer");
- byte[] tmp = new byte[0];
+ final byte[] tmp = new byte[0];
directByteBufferConstructor =
directByteBufferClass.getDeclaredConstructor(new Class[] { Integer.TYPE,
tmp.getClass(),
Integer.TYPE });
directByteBufferConstructor.setAccessible(true);
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
}
-
+
if (directByteBufferConstructor != null) {
try {
return (ByteBuffer)
directByteBufferConstructor.newInstance(new Object[] {
- new Integer((int) capacity),
+ Integer.valueOf((int) capacity),
null,
- new Integer((int) address)
+ Integer.valueOf((int) address)
});
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
}
diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/SoundBuffer.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/SoundBuffer.java
index c45430d23..18698f5ea 100644
--- a/src/jogl/classes/com/jogamp/audio/windows/waveout/SoundBuffer.java
+++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/SoundBuffer.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -35,16 +35,16 @@ package com.jogamp.audio.windows.waveout;
import java.io.*;
class SoundBuffer {
- private byte[] data;
- private boolean needsByteSwap;
+ private final byte[] data;
+ private final boolean needsByteSwap;
private int numBytes;
- private int bytesPerSample;
+ private final int bytesPerSample;
private int numSamples;
private boolean playing;
private boolean empty;
// Note: needsByteSwap argument makes assumptions about the format
- SoundBuffer(int size, int bytesPerSample, boolean needsByteSwap) {
+ SoundBuffer(final int size, final int bytesPerSample, final boolean needsByteSwap) {
this.bytesPerSample = bytesPerSample;
this.needsByteSwap = needsByteSwap;
data = new byte[size * bytesPerSample];
@@ -55,7 +55,7 @@ class SoundBuffer {
return playing;
}
- void playing(boolean playing) {
+ void playing(final boolean playing) {
this.playing = playing;
}
@@ -63,11 +63,11 @@ class SoundBuffer {
return empty;
}
- void empty(boolean empty) {
+ void empty(final boolean empty) {
this.empty = empty;
}
- void fill(InputStream input) throws IOException {
+ void fill(final InputStream input) throws IOException {
synchronized(this) {
if (playing) {
throw new IllegalStateException("Can not fill a buffer that is playing");
@@ -75,7 +75,7 @@ class SoundBuffer {
}
empty(true);
- int num = input.read(data);
+ final int num = input.read(data);
if (num > 0) {
numBytes = num;
numSamples = numBytes / bytesPerSample;
@@ -96,8 +96,8 @@ class SoundBuffer {
// This is called by the mixer and must be extremely fast
// FIXME: may want to reconsider use of floating point at this point
// FIXME: assumes all sounds are of the same format to avoid normalization
- float getSample(int sample) {
- int startByte = sample * bytesPerSample;
+ float getSample(final int sample) {
+ final int startByte = sample * bytesPerSample;
// FIXME: assumes no more than 4 bytes per sample
int res = 0;
if (needsByteSwap) {
@@ -106,7 +106,7 @@ class SoundBuffer {
res |= (data[i] & 0xff);
}
} else {
- int endByte = startByte + bytesPerSample - 1;
+ final int endByte = startByte + bytesPerSample - 1;
for (int i = startByte; i <= endByte; i++) {
res <<= 8;
res |= (data[i] & 0xff);
@@ -119,6 +119,6 @@ class SoundBuffer {
res = (byte) res;
}
- return (float) res;
+ return res;
}
}
diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java
index b57bf1dc6..5e55786ac 100644
--- a/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java
+++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -56,7 +56,7 @@ public class Track {
// If we're playing the file, this is its input stream
private InputStream input;
// Keep around the file name
- private File file;
+ private final File file;
// Whether we're playing this sound
private boolean playing;
// Whether we're looping this sound
@@ -64,7 +64,7 @@ public class Track {
// The position of this sound; defaults to being at the origin
private volatile Vec3f position = new Vec3f();
- Track(File file) throws IOException {
+ Track(final File file) throws IOException {
if (!file.getName().endsWith(".rawsound")) {
throw new IOException("Unsupported file format (currently supports only raw sounds)");
}
@@ -96,7 +96,7 @@ public class Track {
openInput();
// Fill it immediately
fill();
- } catch (IOException e) {
+ } catch (final IOException e) {
e.printStackTrace();
return;
}
@@ -109,7 +109,7 @@ public class Track {
return playing;
}
- public synchronized void setLooping(boolean looping) {
+ public synchronized void setLooping(final boolean looping) {
this.looping = looping;
}
@@ -117,7 +117,7 @@ public class Track {
return looping;
}
- public void setPosition(float x, float y, float z) {
+ public void setPosition(final float x, final float y, final float z) {
position = new Vec3f(x, y, z);
}
@@ -125,7 +125,7 @@ public class Track {
if (input == null) {
return;
}
- SoundBuffer curBuffer = fillingBuffer;
+ final SoundBuffer curBuffer = fillingBuffer;
if (!curBuffer.empty()) {
return;
}
@@ -151,8 +151,8 @@ public class Track {
// These are only for use by the Mixer
private float leftGain;
private float rightGain;
-
- void setLeftGain(float leftGain) {
+
+ void setLeftGain(final float leftGain) {
this.leftGain = leftGain;
}
@@ -160,7 +160,7 @@ public class Track {
return leftGain;
}
- void setRightGain(float rightGain) {
+ void setRightGain(final float rightGain) {
this.rightGain = rightGain;
}
@@ -180,7 +180,7 @@ public class Track {
// This is called by the mixer and must be extremely fast
float nextSample() {
- float res = activeBuffer.getSample(samplePosition++);
+ final float res = activeBuffer.getSample(samplePosition++);
++samplesRead;
if (!hasNextSample()) {
swapBuffers();
@@ -193,7 +193,7 @@ public class Track {
}
synchronized void swapBuffers() {
- SoundBuffer tmp = activeBuffer;
+ final SoundBuffer tmp = activeBuffer;
activeBuffer = fillingBuffer;
fillingBuffer = tmp;
fillingBuffer.empty(true);
diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/Vec3f.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/Vec3f.java
index 1afdaf081..831b25c91 100644
--- a/src/jogl/classes/com/jogamp/audio/windows/waveout/Vec3f.java
+++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/Vec3f.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -48,11 +48,11 @@ class Vec3f {
public Vec3f() {}
- public Vec3f(Vec3f arg) {
+ public Vec3f(final Vec3f arg) {
set(arg);
}
- public Vec3f(float x, float y, float z) {
+ public Vec3f(final float x, final float y, final float z) {
set(x, y, z);
}
@@ -60,18 +60,18 @@ class Vec3f {
return new Vec3f(this);
}
- public void set(Vec3f arg) {
+ public void set(final Vec3f arg) {
set(arg.x, arg.y, arg.z);
}
- public void set(float x, float y, float z) {
+ public void set(final float x, final float y, final float z) {
this.x = x;
this.y = y;
this.z = z;
}
/** Sets the ith component, 0 <= i < 3 */
- public void set(int i, float val) {
+ public void set(final int i, final float val) {
switch (i) {
case 0: x = val; break;
case 1: y = val; break;
@@ -81,7 +81,7 @@ class Vec3f {
}
/** Gets the ith component, 0 <= i < 3 */
- public float get(int i) {
+ public float get(final int i) {
switch (i) {
case 0: return x;
case 1: return y;
@@ -94,11 +94,11 @@ class Vec3f {
public float y() { return y; }
public float z() { return z; }
- public void setX(float x) { this.x = x; }
- public void setY(float y) { this.y = y; }
- public void setZ(float z) { this.z = z; }
+ public void setX(final float x) { this.x = x; }
+ public void setY(final float y) { this.y = y; }
+ public void setZ(final float z) { this.z = z; }
- public float dot(Vec3f arg) {
+ public float dot(final Vec3f arg) {
return x * arg.x + y * arg.y + z * arg.z;
}
@@ -111,87 +111,87 @@ class Vec3f {
}
public void normalize() {
- float len = length();
+ final float len = length();
if (len == 0.0f) return;
scale(1.0f / len);
}
/** Returns this * val; creates new vector */
- public Vec3f times(float val) {
- Vec3f tmp = new Vec3f(this);
+ public Vec3f times(final float val) {
+ final Vec3f tmp = new Vec3f(this);
tmp.scale(val);
return tmp;
}
/** this = this * val */
- public void scale(float val) {
+ public void scale(final float val) {
x *= val;
y *= val;
z *= val;
}
/** Returns this + arg; creates new vector */
- public Vec3f plus(Vec3f arg) {
- Vec3f tmp = new Vec3f();
+ public Vec3f plus(final Vec3f arg) {
+ final Vec3f tmp = new Vec3f();
tmp.add(this, arg);
return tmp;
}
/** this = this + b */
- public void add(Vec3f b) {
+ public void add(final Vec3f b) {
add(this, b);
}
/** this = a + b */
- public void add(Vec3f a, Vec3f b) {
+ public void add(final Vec3f a, final Vec3f b) {
x = a.x + b.x;
y = a.y + b.y;
z = a.z + b.z;
}
/** Returns this + s * arg; creates new vector */
- public Vec3f addScaled(float s, Vec3f arg) {
- Vec3f tmp = new Vec3f();
+ public Vec3f addScaled(final float s, final Vec3f arg) {
+ final Vec3f tmp = new Vec3f();
tmp.addScaled(this, s, arg);
return tmp;
}
/** this = a + s * b */
- public void addScaled(Vec3f a, float s, Vec3f b) {
+ public void addScaled(final Vec3f a, final float s, final Vec3f b) {
x = a.x + s * b.x;
y = a.y + s * b.y;
z = a.z + s * b.z;
}
/** Returns this - arg; creates new vector */
- public Vec3f minus(Vec3f arg) {
- Vec3f tmp = new Vec3f();
+ public Vec3f minus(final Vec3f arg) {
+ final Vec3f tmp = new Vec3f();
tmp.sub(this, arg);
return tmp;
}
/** this = this - b */
- public void sub(Vec3f b) {
+ public void sub(final Vec3f b) {
sub(this, b);
}
/** this = a - b */
- public void sub(Vec3f a, Vec3f b) {
+ public void sub(final Vec3f a, final Vec3f b) {
x = a.x - b.x;
y = a.y - b.y;
z = a.z - b.z;
}
/** Returns this cross arg; creates new vector */
- public Vec3f cross(Vec3f arg) {
- Vec3f tmp = new Vec3f();
+ public Vec3f cross(final Vec3f arg) {
+ final Vec3f tmp = new Vec3f();
tmp.cross(this, arg);
return tmp;
}
/** this = a cross b. NOTE: "this" must be a different vector than
both a and b. */
- public void cross(Vec3f a, Vec3f b) {
+ public void cross(final Vec3f a, final Vec3f b) {
x = a.y * b.z - a.z * b.y;
y = a.z * b.x - a.x * b.z;
z = a.x * b.y - a.y * b.x;
@@ -200,12 +200,13 @@ class Vec3f {
/** Sets each component of this vector to the product of the
component with the corresponding component of the argument
vector. */
- public void componentMul(Vec3f arg) {
+ public void componentMul(final Vec3f arg) {
x *= arg.x;
y *= arg.y;
z *= arg.z;
}
+ @Override
public String toString() {
return "(" + x + ", " + y + ", " + z + ")";
}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
index 5334d45cf..75067a3b7 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,6 +41,7 @@ package com.jogamp.gluegen.opengl;
import com.jogamp.gluegen.CodeGenUtils;
import com.jogamp.gluegen.JavaType;
+
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
@@ -50,6 +51,9 @@ import java.lang.reflect.Method;
import java.nio.Buffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -57,61 +61,96 @@ import java.util.Set;
public class BuildComposablePipeline {
- public static final int GEN_DEBUG = 1 << 0; // default
- public static final int GEN_TRACE = 1 << 1; // default
+ /** <p>Default: true</p>. */
+ public static final int GEN_DEBUG = 1 << 0;
+ /** <p>Default: true</p>. */
+ public static final int GEN_TRACE = 1 << 1;
+ /** <p>Default: false</p>. */
public static final int GEN_CUSTOM = 1 << 2;
+ /**
+ * By extra command-line argument: <code>prolog_xor_downstream</code>.
+ * <p>
+ * If true, either prolog (if exist) is called or downstream's method, but not both.
+ * By default, both methods would be called.
+ * </p>
+ * <p>Default: false</p>
+ */
public static final int GEN_PROLOG_XOR_DOWNSTREAM = 1 << 3;
+ /**
+ * By extra command-line argument: <code>gl_identity_by_assignable_class</code>.
+ * <p>
+ * If true, implementation does not utilize downstream's <code>isGL*()</code>
+ * implementation, but determines whether the GL profile is matched by interface inheritance.
+ * </p>
+ * <p>Default: false</p>
+ */
+ public static final int GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS = 1 << 4;
+
+ private static final HashMap<String, String> addedGLHooks = new HashMap<String, String>();
+ private static final String[] addedGLHookMethodNames = new String[] {
+ "mapBuffer", "mapBufferRange",
+ "mapNamedBuffer", "mapNamedBufferRange" };
+ static {
+ for(int i=0; i<addedGLHookMethodNames.length; i++) {
+ addedGLHooks.put(addedGLHookMethodNames[i], addedGLHookMethodNames[i]);
+ }
+ }
+
int mode;
- private String outputDir;
- private String outputPackage;
- private String outputName;
- private Class<?> classToComposeAround;
- private Class<?> classPrologOpt;
- private Class<?> classDownstream;
+ private final String outputDir;
+ private final String outputPackage;
+ private final String outputName;
+ private final Class<?> classToComposeAround;
+ private final Class<?> classPrologOpt;
+ private final Class<?> classDownstream;
// Only desktop OpenGL has immediate mode glBegin / glEnd
private boolean hasImmediateMode;
// Desktop OpenGL and GLES1 have GL_STACK_OVERFLOW and GL_STACK_UNDERFLOW errors
- private boolean hasStackOverflow;
+ private boolean hasGL2ES1StackOverflow;
- public static Class<?> getClass(String name) {
+ public static Class<?> getClass(final String name) {
Class<?> clazz = null;
try {
clazz = Class.forName(name);
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new RuntimeException(
"Could not find class \"" + name + "\"", e);
}
return clazz;
}
- public static Method getMethod(Class<?> clazz, Method m) {
+ public static Method getMethod(final Class<?> clazz, final Method m) {
Method res = null;
try {
res = clazz.getMethod(m.getName(), m.getParameterTypes());
- } catch (Exception e) {
+ } catch (final Exception e) {
}
return res;
}
- public static void main(String[] args) {
- String classToComposeAroundName = args[0];
+ public static void main(final String[] args) {
+ final String classToComposeAroundName = args[0];
Class<?> classPrologOpt, classDownstream;
- Class<?> classToComposeAround = getClass(classToComposeAroundName);
+ final Class<?> classToComposeAround = getClass(classToComposeAroundName);
- String outputDir = args[1];
+ final String outputDir = args[1];
String outputPackage, outputName;
int mode;
if (args.length > 2) {
- String outputClazzName = args[2];
+ final String outputClazzName = args[2];
outputPackage = getPackageName(outputClazzName);
outputName = getBaseClassName(outputClazzName);
classPrologOpt = getClass(args[3]);
classDownstream = getClass(args[4]);
mode = GEN_CUSTOM;
if (args.length > 5) {
- if (args[5].equals("prolog_xor_downstream")) {
- mode |= GEN_PROLOG_XOR_DOWNSTREAM;
+ for(int i=5; i<args.length; i++) {
+ if (args[i].equals("prolog_xor_downstream")) {
+ mode |= GEN_PROLOG_XOR_DOWNSTREAM;
+ } else if (args[i].equals("gl_identity_by_assignable_class")) {
+ mode |= GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS;
+ }
}
}
} else {
@@ -119,22 +158,22 @@ public class BuildComposablePipeline {
outputName = null; // TBD ..
classPrologOpt = null;
classDownstream = classToComposeAround;
- mode = GEN_DEBUG | GEN_TRACE;
+ mode = GEN_DEBUG | GEN_TRACE ;
}
- BuildComposablePipeline composer =
+ final BuildComposablePipeline composer =
new BuildComposablePipeline(mode, outputDir, outputPackage, outputName, classToComposeAround, classPrologOpt, classDownstream);
try {
composer.emit();
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(
"Error generating composable pipeline source files", e);
}
}
- protected BuildComposablePipeline(int mode, String outputDir, String outputPackage, String outputName,
- Class<?> classToComposeAround, Class<?> classPrologOpt, Class<?> classDownstream) {
+ protected BuildComposablePipeline(final int mode, final String outputDir, final String outputPackage, final String outputName,
+ final Class<?> classToComposeAround, final Class<?> classPrologOpt, final Class<?> classDownstream) {
this.mode = mode;
this.outputDir = outputDir;
this.outputPackage = outputPackage;
@@ -149,15 +188,17 @@ public class BuildComposablePipeline {
}
try {
+ // Keep assignment w/ null comparison for clarification.
+ // If no exception is thrown, return value is always non-null;
hasImmediateMode =
- (classToComposeAround.getMethod("glBegin", new Class<?>[]{Integer.TYPE}) != null);
- } catch (Exception e) {
+ null != classToComposeAround.getMethod("glBegin", new Class<?>[]{Integer.TYPE});
+ } catch (final Exception e) {
}
try {
- hasStackOverflow =
+ hasGL2ES1StackOverflow = hasImmediateMode &&
(classToComposeAround.getField("GL_STACK_OVERFLOW") != null);
- } catch (Exception e) {
+ } catch (final Exception e) {
}
}
@@ -167,33 +208,46 @@ public class BuildComposablePipeline {
*/
public void emit() throws IOException {
- List<Method> publicMethodsRaw = Arrays.asList(classToComposeAround.getMethods());
+ final List<Method> publicMethodsRaw = Arrays.asList(classToComposeAround.getMethods());
- Set<PlainMethod> publicMethodsPlain = new HashSet<PlainMethod>();
- for (Iterator<Method> iter = publicMethodsRaw.iterator(); iter.hasNext();) {
- Method method = iter.next();
+ final Set<PlainMethod> publicMethodsPlainSet = new HashSet<PlainMethod>();
+ for (final Iterator<Method> iter = publicMethodsRaw.iterator(); iter.hasNext();) {
+ final Method method = iter.next();
// Don't hook methods which aren't real GL methods,
// such as the synthetic "isGL2ES2" "getGL2ES2"
- String name = method.getName();
- boolean runHooks = name.startsWith("gl");
- if (!name.startsWith("getGL") && !name.startsWith("isGL") && !name.equals("toString")) {
- publicMethodsPlain.add(new PlainMethod(method, runHooks));
+ final String name = method.getName();
+ if ( !name.equals("getDownstreamGL") &&
+ !name.equals("toString") ) {
+ final boolean syntheticIsGL = name.startsWith("isGL");
+ final boolean syntheticGetGL = name.startsWith("getGL");
+ final boolean runHooks = name.startsWith("gl") || syntheticIsGL || syntheticGetGL || addedGLHooks.containsKey(name);
+ publicMethodsPlainSet.add(new PlainMethod(method, runHooks, syntheticIsGL, syntheticGetGL));
}
}
+ // sort methods to make them easier to find
+ final List<PlainMethod> publicMethodsPlainSorted = new ArrayList<PlainMethod>();
+ publicMethodsPlainSorted.addAll(publicMethodsPlainSet);
+ Collections.sort(publicMethodsPlainSorted, new Comparator<PlainMethod>() {
+ @Override
+ public int compare(final PlainMethod o1, final PlainMethod o2) {
+ return o1.getWrappedMethod().getName().compareTo(o2.getWrappedMethod().getName());
+ }
+ });
+
if (0 != (mode & GEN_DEBUG)) {
- (new DebugPipeline(outputDir, outputPackage, classToComposeAround, classDownstream)).emit(publicMethodsPlain.iterator());
+ (new DebugPipeline(outputDir, outputPackage, classToComposeAround, classDownstream)).emit(publicMethodsPlainSorted.iterator());
}
if (0 != (mode & GEN_TRACE)) {
- (new TracePipeline(outputDir, outputPackage, classToComposeAround, classDownstream)).emit(publicMethodsPlain.iterator());
+ (new TracePipeline(outputDir, outputPackage, classToComposeAround, classDownstream)).emit(publicMethodsPlainSorted.iterator());
}
if (0 != (mode & GEN_CUSTOM)) {
- (new CustomPipeline(mode, outputDir, outputPackage, outputName, classToComposeAround, classPrologOpt, classDownstream)).emit(publicMethodsPlain.iterator());
+ (new CustomPipeline(mode, outputDir, outputPackage, outputName, classToComposeAround, classPrologOpt, classDownstream)).emit(publicMethodsPlainSorted.iterator());
}
}
- public static String getPackageName(String clazzName) {
- int lastDot = clazzName.lastIndexOf('.');
+ public static String getPackageName(final String clazzName) {
+ final int lastDot = clazzName.lastIndexOf('.');
if (lastDot == -1) {
// no package, class is at root level
return null;
@@ -201,8 +255,8 @@ public class BuildComposablePipeline {
return clazzName.substring(0, lastDot);
}
- public static String getBaseClassName(String clazzName) {
- int lastDot = clazzName.lastIndexOf('.');
+ public static String getBaseClassName(final String clazzName) {
+ final int lastDot = clazzName.lastIndexOf('.');
if (lastDot == -1) {
// no package, class is at root level
return clazzName;
@@ -211,14 +265,18 @@ public class BuildComposablePipeline {
}
//-------------------------------------------------------
- protected class PlainMethod {
+ protected static class PlainMethod {
- Method m;
- boolean runHooks;
+ final Method m;
+ final boolean runHooks;
+ final boolean isSynthethicIsGL;
+ final boolean isSynthethicGetGL;
- PlainMethod(Method m, boolean runHooks) {
+ PlainMethod(final Method m, final boolean runHooks, final boolean isSynthethicIsGL, final boolean isSynthethicGetGL) {
this.m = m;
this.runHooks = runHooks;
+ this.isSynthethicIsGL = isSynthethicIsGL;
+ this.isSynthethicGetGL = isSynthethicGetGL;
}
public Method getWrappedMethod() {
@@ -229,11 +287,15 @@ public class BuildComposablePipeline {
return runHooks;
}
+ public boolean isSynthetic() { return isSynthethicIsGL || isSynthethicGetGL; }
+ public boolean isSyntheticIsGL() { return isSynthethicIsGL; }
+ public boolean isSyntheticGetGL() { return isSynthethicGetGL; }
+
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (obj instanceof PlainMethod) {
- PlainMethod b = (PlainMethod) obj;
- boolean res =
+ final PlainMethod b = (PlainMethod) obj;
+ final boolean res =
m.getName().equals(b.m.getName())
&& m.getModifiers() == b.m.getModifiers()
&& m.getReturnType().equals(b.m.getReturnType())
@@ -246,7 +308,7 @@ public class BuildComposablePipeline {
@Override
public int hashCode() {
int hash = m.getName().hashCode() ^ m.getModifiers() ^ m.getReturnType().hashCode();
- Class<?>[] args = m.getParameterTypes();
+ final Class<?>[] args = m.getParameterTypes();
for (int i = 0; i < args.length; i++) {
hash ^= args[i].hashCode();
}
@@ -255,8 +317,8 @@ public class BuildComposablePipeline {
@Override
public String toString() {
- Class<?>[] args = m.getParameterTypes();
- StringBuilder argsString = new StringBuilder();
+ final Class<?>[] args = m.getParameterTypes();
+ final StringBuilder argsString = new StringBuilder();
argsString.append("(");
for (int i = 0; i < args.length; i++) {
if (i > 0) {
@@ -267,6 +329,7 @@ public class BuildComposablePipeline {
argsString.append(")");
return m.toString()
+ "\n\tname: " + m.getName()
+ + "\n\tsynt: isGL " + isSynthethicIsGL+", getGL "+isSynthethicGetGL
+ "\n\tmods: " + m.getModifiers()
+ "\n\tretu: " + m.getReturnType()
+ "\n\targs[" + args.length + "]: " + argsString.toString();
@@ -300,7 +363,7 @@ public class BuildComposablePipeline {
* @exception IllegalArgumentException if classToComposeAround is not an
* interface.
*/
- PipelineEmitter(String outputDir, String outputPackage, Class<?> baseInterfaceClass, Class<?> prologClassOpt, Class<?> downstreamClass) {
+ PipelineEmitter(final String outputDir, final String outputPackage, final Class<?> baseInterfaceClass, final Class<?> prologClassOpt, final Class<?> downstreamClass) {
this.outputDir = outputDir;
this.outputPackage = outputPackage;
this.baseInterfaceClass = baseInterfaceClass;
@@ -317,38 +380,38 @@ public class BuildComposablePipeline {
}
}
- public void emit(Iterator<PlainMethod> methodsToWrap) throws IOException {
- String outputClassName = getOutputName();
+ public void emit(final Iterator<PlainMethod> methodsToWrap) throws IOException {
+ final String outputClassName = getOutputName();
this.file = new File(outputDir + File.separatorChar + outputClassName + ".java");
- String parentDir = file.getParent();
+ final String parentDir = file.getParent();
if (parentDir != null) {
- File pDirFile = new File(parentDir);
+ final File pDirFile = new File(parentDir);
pDirFile.mkdirs();
}
- PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(file)));
+ final PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(file)));
- List<Class<?>> baseInterfaces = Arrays.asList(baseInterfaceClass.getInterfaces());
- HashSet<Class<?>> clazzList = new HashSet<Class<?>>();
+ final List<Class<?>> baseInterfaces = Arrays.asList(baseInterfaceClass.getInterfaces());
+ final HashSet<Class<?>> clazzList = new HashSet<Class<?>>();
clazzList.add(baseInterfaceClass);
clazzList.addAll(baseInterfaces);
- int ifNamesNumber = clazzList.size();
+ final int ifNamesNumber = clazzList.size();
// keep original order ..
clazzList.clear();
- String[] ifNames = new String[ifNamesNumber];
+ final String[] ifNames = new String[ifNamesNumber];
{
int i = 0;
- for (Iterator<Class<?>> iter = baseInterfaces.iterator(); iter.hasNext();) {
- Class<?> ifClass = iter.next();
+ for (final Iterator<Class<?>> iter = baseInterfaces.iterator(); iter.hasNext();) {
+ final Class<?> ifClass = iter.next();
if (!clazzList.contains(ifClass)) {
ifNames[i++] = ifClass.getName();
clazzList.add(ifClass);
}
}
- if (null != baseInterfaceClass && !clazzList.contains(baseInterfaceClass)) {
+ if ( !clazzList.contains(baseInterfaceClass) ) {
ifNames[i++] = baseInterfaceClass.getName();
clazzList.add(baseInterfaceClass);
}
@@ -359,12 +422,12 @@ public class BuildComposablePipeline {
clazzList.add(prologClassOpt);
}
- ArrayList<String> imports = new ArrayList<String>();
+ final ArrayList<String> imports = new ArrayList<String>();
imports.add("java.io.*");
imports.add("javax.media.opengl.*");
imports.add("com.jogamp.gluegen.runtime.*");
imports.add(Buffer.class.getPackage().getName()+".*");
- for (Class<?> clasS : clazzList) {
+ for (final Class<?> clasS : clazzList) {
imports.add(clasS.getName());
}
@@ -377,7 +440,8 @@ public class BuildComposablePipeline {
ifNames,
null,
new CodeGenUtils.EmissionCallback() {
- public void emit(PrintWriter w) {
+ @Override
+ public void emit(final PrintWriter w) {
emitClassDocComment(w);
}
});
@@ -386,15 +450,14 @@ public class BuildComposablePipeline {
constructorHook(output);
- emitGLIsMethods(output);
- emitGLGetMethods(output);
+ emitSyntheticGLMethods(output);
while (methodsToWrap.hasNext()) {
- PlainMethod pm = methodsToWrap.next();
- Method m = pm.getWrappedMethod();
+ final PlainMethod pm = methodsToWrap.next();
+ final Method m = pm.getWrappedMethod();
emitMethodDocComment(output, m);
emitSignature(output, m);
- emitBody(output, m, pm.runHooks());
+ emitBody(output, pm);
}
postMethodEmissionHook(output);
@@ -426,30 +489,27 @@ public class BuildComposablePipeline {
return null;
}
- protected void emitMethodDocComment(PrintWriter output, Method m) {
+ protected void emitMethodDocComment(final PrintWriter output, final Method m) {
}
- protected void emitSignature(PrintWriter output, Method m) {
- output.print(" public ");
- output.print(' ');
- output.print(JavaType.createForClass(m.getReturnType()).getName());
- output.print(' ');
- output.print(m.getName());
- output.print('(');
- output.print(getArgListAsString(m, true, true));
- output.println(")");
+ protected void emitSignature(final PrintWriter output, final Method m) {
+ output.format(" @Override%n public %s %s(%s)%n",
+ JavaType.createForClass(m.getReturnType()).getName(),
+ m.getName(),
+ getArgListAsString(m, true, true));
}
- protected void emitBody(PrintWriter output, Method m, boolean runHooks) {
+ protected void emitBody(final PrintWriter output, final PlainMethod pm) {
+ final boolean runHooks = pm.runHooks();
+ final Method m = pm.getWrappedMethod();
output.println(" {");
- output.print(" ");
- Class<?> retType = m.getReturnType();
+ final Class<?> retType = m.getReturnType();
- boolean callPreDownstreamHook = runHooks && hasPreDownstreamCallHook(m);
- boolean callPostDownstreamHook = runHooks && hasPostDownstreamCallHook(m);
- boolean callDownstream = (null != getMethod(downstreamClass, m))
+ final boolean callPreDownstreamHook = runHooks && hasPreDownstreamCallHook(pm);
+ final boolean callPostDownstreamHook = runHooks && hasPostDownstreamCallHook(pm);
+ final boolean callDownstream = (null != getMethod(downstreamClass, m))
&& !(0 != (GEN_PROLOG_XOR_DOWNSTREAM & getMode()) && callPreDownstreamHook);
- boolean hasResult = (retType != Void.TYPE);
+ final boolean hasResult = (retType != Void.TYPE);
if (!callDownstream) {
if (!emptyDownstreamAllowed()) {
@@ -476,45 +536,54 @@ public class BuildComposablePipeline {
output.print(" return ");
}
}
- preDownstreamCallHook(output, m);
+ preDownstreamCallHook(output, pm);
}
if (callDownstream) {
- if (hasResult) {
- if (callPostDownstreamHook) {
- output.print(" " + JavaType.createForClass(retType).getName());
- output.print(" _res = ");
- } else {
- output.print(" return ");
+ if( pm.isSyntheticIsGL() ) {
+ emitGLIsMethodBody(output, pm);
+ } else if( pm.isSyntheticGetGL() ) {
+ emitGLGetMethodBody(output, pm);
+ } else {
+ if (hasResult) {
+ if (callPostDownstreamHook) {
+ output.print(" " + JavaType.createForClass(retType).getName());
+ output.print(" _res = ");
+ } else {
+ output.print(" return ");
+ }
+ }
+ else {
+ output.print(" ");
}
+ output.print(getDownstreamObjectName());
+ output.print('.');
+ output.print(m.getName());
+ output.print('(');
+ output.print(getArgListAsString(m, false, true));
+ output.println(");");
}
- output.print(getDownstreamObjectName());
- output.print('.');
- output.print(m.getName());
- output.print('(');
- output.print(getArgListAsString(m, false, true));
- output.println(");");
}
if (callPostDownstreamHook) {
- postDownstreamCallHook(output, m);
+ postDownstreamCallHook(output, pm);
}
if (hasResult && callDownstream && callPostDownstreamHook) {
output.println(" return _res;");
}
- output.println(" }");
+ output.println(" }");
}
- protected String getArgListAsString(Method m, boolean includeArgTypes, boolean includeArgNames) {
- StringBuilder buf = new StringBuilder(256);
+ protected String getArgListAsString(final Method m, final boolean includeArgTypes, final boolean includeArgNames) {
+ final StringBuilder buf = new StringBuilder(256);
if (!includeArgNames && !includeArgTypes) {
throw new IllegalArgumentException(
"Cannot generate arglist without both arg types and arg names");
}
- Class<?>[] argTypes = m.getParameterTypes();
+ final Class<?>[] argTypes = m.getParameterTypes();
for (int i = 0; i < argTypes.length; ++i) {
if (includeArgTypes) {
buf.append(JavaType.createForClass(argTypes[i]).getName());
@@ -549,7 +618,7 @@ public class BuildComposablePipeline {
* Called after the class headers have been generated, but before any
* method wrappers have been generated.
*/
- protected void preMethodEmissionHook(PrintWriter output) {
+ protected void preMethodEmissionHook(final PrintWriter output) {
output.println(" public static final boolean DEBUG = jogamp.opengl.Debug.debug(\"" + getOutputName() + "\");");
}
@@ -562,10 +631,11 @@ public class BuildComposablePipeline {
* Called after the method wrappers have been generated, but before the
* closing parenthesis of the class is emitted.
*/
- protected void postMethodEmissionHook(PrintWriter output) {
+ protected void postMethodEmissionHook(final PrintWriter output) {
+ output.println(" @Override");
output.println(" public String toString() {");
output.println(" StringBuilder sb = new StringBuilder();");
- output.println(" sb.append(\"" + getOutputName() + " [ implementing " + baseInterfaceClass.getName() + ",\\n\\t\");");
+ output.println(" sb.append(\"" + getOutputName() + " [this 0x\"+Integer.toHexString(hashCode())+\" implementing " + baseInterfaceClass.getName() + ",\\n\\t\");");
if (null != prologClassOpt) {
output.println(" sb.append(\" prolog: \"+" + getPrologObjectNameOpt() + ".toString()+\",\\n\\t\");");
}
@@ -577,17 +647,17 @@ public class BuildComposablePipeline {
/**
* Called before the pipeline routes the call to the downstream object.
*/
- protected abstract void preDownstreamCallHook(PrintWriter output, Method m);
+ protected abstract void preDownstreamCallHook(PrintWriter output, PlainMethod pm);
- protected abstract boolean hasPreDownstreamCallHook(Method m);
+ protected abstract boolean hasPreDownstreamCallHook(PlainMethod pm);
/**
* Called after the pipeline has routed the call to the downstream object,
* but before the calling function exits or returns a value.
*/
- protected abstract void postDownstreamCallHook(PrintWriter output, Method m);
+ protected abstract void postDownstreamCallHook(PrintWriter output, PlainMethod pm);
- protected abstract boolean hasPostDownstreamCallHook(Method m);
+ protected abstract boolean hasPostDownstreamCallHook(PlainMethod pm);
protected abstract int getMode();
@@ -601,71 +671,57 @@ public class BuildComposablePipeline {
/**
* Emits one of the isGL* methods.
*/
- protected void emitGLIsMethod(PrintWriter output, String type) {
- output.println(" public boolean is" + type + "() {");
- Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
- if (clazz.isAssignableFrom(baseInterfaceClass)) {
+ protected void emitGLIsMethodBody(final PrintWriter output, final PlainMethod plainMethod) {
+ final String methodName = plainMethod.getWrappedMethod().getName();
+ final String type = methodName.substring(2);
+
+ if( type.equals("GL") ) {
output.println(" return true;");
+ } else if( 0 != ( GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS & getMode() ) &&
+ !type.equals("GLES") &&
+ !type.endsWith("core") &&
+ !type.endsWith("Compatible") )
+ {
+ final Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
+ if (clazz.isAssignableFrom(baseInterfaceClass)) {
+ output.println(" return true;");
+ } else {
+ output.println(" return false;");
+ }
} else {
- output.println(" return false;");
+ output.println(" return " + getDownstreamObjectName() + ".is" + type + "();");
}
- output.println(" }");
- }
-
- /**
- * Emits all of the isGL* methods.
- */
- protected void emitGLIsMethods(PrintWriter output) {
- emitGLIsMethod(output, "GL");
- emitGLIsMethod(output, "GL4bc");
- emitGLIsMethod(output, "GL4");
- emitGLIsMethod(output, "GL3bc");
- emitGLIsMethod(output, "GL3");
- emitGLIsMethod(output, "GL2");
- emitGLIsMethod(output, "GLES1");
- emitGLIsMethod(output, "GLES2");
- emitGLIsMethod(output, "GL2ES1");
- emitGLIsMethod(output, "GL2ES2");
- emitGLIsMethod(output, "GL2GL3");
- output.println(" public boolean isGLES() {");
- output.println(" return isGLES2() || isGLES1();");
- output.println(" }");
- output.println(" public boolean isGLES2Compatible() {");
- output.println(" return " + getDownstreamObjectName() + ".isGLES2Compatible();");
- output.println(" }");
}
/**
* Emits one of the getGL* methods.
*/
- protected void emitGLGetMethod(PrintWriter output, String type) {
- output.println(" public javax.media.opengl." + type + " get" + type + "() {");
- Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
- if (clazz.isAssignableFrom(baseInterfaceClass)) {
+ protected void emitGLGetMethodBody(final PrintWriter output, final PlainMethod plainMethod) {
+ final String methodName = plainMethod.getWrappedMethod().getName();
+ final String type = methodName.substring(3);
+
+ if( type.equals("GL") ) {
output.println(" return this;");
+ } else if( type.equals("GLProfile") ) {
+ output.println(" return " + getDownstreamObjectName() + ".getGLProfile();");
} else {
- output.println(" throw new GLException(\"Not a " + type + " implementation\");");
+ final Class<?> clazz = BuildComposablePipeline.getClass("javax.media.opengl." + type);
+ if (clazz.isAssignableFrom(baseInterfaceClass)) {
+ output.println(" if( is" + type + "() ) { return this; }");
+ output.println(" throw new GLException(\"Not a " + type + " implementation\");");
+ } else {
+ output.println(" throw new GLException(\"Not a " + type + " implementation\");");
+ }
}
- output.println(" }");
}
/**
- * Emits all of the getGL* methods.
+ * Emits all synthetic GL* methods, but not isGL* nor getGL*
*/
- protected void emitGLGetMethods(PrintWriter output) {
- emitGLGetMethod(output, "GL");
- emitGLGetMethod(output, "GL4bc");
- emitGLGetMethod(output, "GL4");
- emitGLGetMethod(output, "GL3bc");
- emitGLGetMethod(output, "GL3");
- emitGLGetMethod(output, "GL2");
- emitGLGetMethod(output, "GLES1");
- emitGLGetMethod(output, "GLES2");
- emitGLGetMethod(output, "GL2ES1");
- emitGLGetMethod(output, "GL2ES2");
- emitGLGetMethod(output, "GL2GL3");
- output.println(" public GLProfile getGLProfile() {");
- output.println(" return " + getDownstreamObjectName() + ".getGLProfile();");
+ protected void emitSyntheticGLMethods(final PrintWriter output) {
+ output.println(" @Override");
+ output.println(" public final GL getDownstreamGL() throws GLException {");
+ output.println(" return " + getDownstreamObjectName() + ";");
output.println(" }");
}
} // end class PipelineEmitter
@@ -676,34 +732,39 @@ public class BuildComposablePipeline {
String className;
int mode;
- CustomPipeline(int mode, String outputDir, String outputPackage, String outputName, Class<?> baseInterfaceClass, Class<?> prologClassOpt, Class<?> downstreamClass) {
+ CustomPipeline(final int mode, final String outputDir, final String outputPackage, final String outputName, final Class<?> baseInterfaceClass, final Class<?> prologClassOpt, final Class<?> downstreamClass) {
super(outputDir, outputPackage, baseInterfaceClass, prologClassOpt, downstreamClass);
className = outputName;
this.mode = mode;
}
+ @Override
protected String getOutputName() {
return className;
}
+ @Override
protected int getMode() {
return mode;
}
+ @Override
protected boolean emptyMethodAllowed() {
return true;
}
+ @Override
protected boolean emptyDownstreamAllowed() {
return true;
}
@Override
- protected void preMethodEmissionHook(PrintWriter output) {
+ protected void preMethodEmissionHook(final PrintWriter output) {
super.preMethodEmissionHook(output);
}
- protected void constructorHook(PrintWriter output) {
+ @Override
+ protected void constructorHook(final PrintWriter output) {
output.print(" public " + getOutputName() + "(");
output.print(downstreamName + " " + getDownstreamObjectName());
if (null != prologNameOpt) {
@@ -726,14 +787,15 @@ public class BuildComposablePipeline {
}
@Override
- protected void postMethodEmissionHook(PrintWriter output) {
+ protected void postMethodEmissionHook(final PrintWriter output) {
super.postMethodEmissionHook(output);
if (null != prologNameOpt) {
output.print(" private " + prologNameOpt + " " + getPrologObjectNameOpt() + ";");
}
}
- protected void emitClassDocComment(PrintWriter output) {
+ @Override
+ protected void emitClassDocComment(final PrintWriter output) {
output.println("/**");
output.println(" * Composable pipeline {@link " + outputPackage + "." + outputName + "}, implementing the interface");
output.println(" * {@link " + baseInterfaceClass.getName() + "}");
@@ -767,11 +829,14 @@ public class BuildComposablePipeline {
output.println("*/");
}
- protected boolean hasPreDownstreamCallHook(Method m) {
- return null != getMethod(prologClassOpt, m);
+ @Override
+ protected boolean hasPreDownstreamCallHook(final PlainMethod pm) {
+ return null != getMethod(prologClassOpt, pm.getWrappedMethod());
}
- protected void preDownstreamCallHook(PrintWriter output, Method m) {
+ @Override
+ protected void preDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
+ final Method m = pm.getWrappedMethod();
if (null != prologNameOpt) {
output.print(getPrologObjectNameOpt());
output.print('.');
@@ -782,11 +847,13 @@ public class BuildComposablePipeline {
}
}
- protected boolean hasPostDownstreamCallHook(Method m) {
+ @Override
+ protected boolean hasPostDownstreamCallHook(final PlainMethod pm) {
return false;
}
- protected void postDownstreamCallHook(PrintWriter output, Method m) {
+ @Override
+ protected void postDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
}
} // end class CustomPipeline
@@ -794,33 +861,38 @@ public class BuildComposablePipeline {
String className;
- DebugPipeline(String outputDir, String outputPackage, Class<?> baseInterfaceClass, Class<?> downstreamClass) {
+ DebugPipeline(final String outputDir, final String outputPackage, final Class<?> baseInterfaceClass, final Class<?> downstreamClass) {
super(outputDir, outputPackage, baseInterfaceClass, null, downstreamClass);
className = "Debug" + getBaseInterfaceName();
}
+ @Override
protected String getOutputName() {
return className;
}
+ @Override
protected int getMode() {
return 0;
}
+ @Override
protected boolean emptyMethodAllowed() {
return false;
}
+ @Override
protected boolean emptyDownstreamAllowed() {
return false;
}
@Override
- protected void preMethodEmissionHook(PrintWriter output) {
+ protected void preMethodEmissionHook(final PrintWriter output) {
super.preMethodEmissionHook(output);
}
- protected void constructorHook(PrintWriter output) {
+ @Override
+ protected void constructorHook(final PrintWriter output) {
output.print(" public " + getOutputName() + "(");
output.println(downstreamName + " " + getDownstreamObjectName() + ")");
output.println(" {");
@@ -840,27 +912,23 @@ public class BuildComposablePipeline {
}
@Override
- protected void postMethodEmissionHook(PrintWriter output) {
+ protected void postMethodEmissionHook(final PrintWriter output) {
super.postMethodEmissionHook(output);
- output.println(" private void checkGLGetError(String caller)");
- output.println(" {");
+ output.println(" private int checkGLError() {");
if (hasImmediateMode) {
- output.println(" if (insideBeginEndPair) {");
- output.println(" return;");
- output.println(" }");
+ output.println(" if (insideBeginEndPair) return GL_NO_ERROR;");
output.println();
}
- output.println(" // Debug code to make sure the pipeline is working; leave commented out unless testing this class");
- output.println(" //System.err.println(\"Checking for GL errors "
- + "after call to \" + caller);");
- output.println();
- output.println(" int err = "
- + getDownstreamObjectName()
- + ".glGetError();");
- output.println(" if (err == GL_NO_ERROR) { return; }");
- output.println();
- output.println(" StringBuilder buf = new StringBuilder(Thread.currentThread()+");
- output.println(" \" glGetError() returned the following error codes after a call to \" + caller + \": \");");
+ output.format(" return %s.glGetError();%n", getDownstreamObjectName());
+ output.println(" }");
+
+ output.println(" private void writeGLError(int err, String fmt, Object... args)");
+ output.println(" {");
+ output.println(" StringBuilder buf = new StringBuilder();");
+ output.println(" buf.append(Thread.currentThread().toString());");
+ output.println(" buf.append(\" glGetError() returned the following error codes after a call to \");");
+ output.println(" buf.append(String.format(fmt, args));");
+ output.println(" buf.append(\": \");");
output.println();
output.println(" // Loop repeatedly to allow for distributed GL implementations,");
output.println(" // as detailed in the glGetError() specification");
@@ -870,9 +938,9 @@ public class BuildComposablePipeline {
output.println(" case GL_INVALID_ENUM: buf.append(\"GL_INVALID_ENUM \"); break;");
output.println(" case GL_INVALID_VALUE: buf.append(\"GL_INVALID_VALUE \"); break;");
output.println(" case GL_INVALID_OPERATION: buf.append(\"GL_INVALID_OPERATION \"); break;");
- if (hasStackOverflow) {
- output.println(" case GL_STACK_OVERFLOW: buf.append(\"GL_STACK_OVERFLOW \"); break;");
- output.println(" case GL_STACK_UNDERFLOW: buf.append(\"GL_STACK_UNDERFLOW \"); break;");
+ if (hasGL2ES1StackOverflow) {
+ output.println(" case GL2ES1.GL_STACK_OVERFLOW: buf.append(\"GL_STACK_OVERFLOW \"); break;");
+ output.println(" case GL2ES1.GL_STACK_UNDERFLOW: buf.append(\"GL_STACK_UNDERFLOW \"); break;");
}
output.println(" case GL_OUT_OF_MEMORY: buf.append(\"GL_OUT_OF_MEMORY \"); break;");
output.println(" case GL_NO_ERROR: throw new InternalError(\"Should not be treating GL_NO_ERROR as error\");");
@@ -901,31 +969,42 @@ public class BuildComposablePipeline {
output.println(" private GLContext _context;");
}
- protected void emitClassDocComment(PrintWriter output) {
- output.println("/** <P> Composable pipeline which wraps an underlying {@link GL} implementation,");
- output.println(" providing error checking after each OpenGL method call. If an error occurs,");
- output.println(" causes a {@link GLException} to be thrown at exactly the point of failure.");
- output.println(" Sample code which installs this pipeline: </P>");
- output.println();
- output.println("<PRE>");
- output.println(" GL gl = drawable.setGL(new DebugGL(drawable.getGL()));");
- output.println("</PRE>");
- output.println("*/");
+ @Override
+ protected void emitClassDocComment(final PrintWriter output) {
+ output.println("/**");
+ output.println(" * <p>");
+ output.println(" * Composable pipeline which wraps an underlying {@link GL} implementation,");
+ output.println(" * providing error checking after each OpenGL method call. If an error occurs,");
+ output.println(" * causes a {@link GLException} to be thrown at exactly the point of failure.");
+ output.println(" * </p>");
+ output.println(" * <p>");
+ output.println(" * Sample code which installs this pipeline:");
+ output.println(" * <pre>");
+ output.println(" * gl = drawable.setGL(new DebugGL(drawable.getGL()));");
+ output.println(" * </pre>");
+ output.println(" * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}");
+ output.println(" * </p>");
+ output.println(" */");
}
- protected boolean hasPreDownstreamCallHook(Method m) {
- return true;
+ @Override
+ protected boolean hasPreDownstreamCallHook(final PlainMethod pm) {
+ return !pm.isSynthetic();
}
- protected void preDownstreamCallHook(PrintWriter output, Method m) {
+ @Override
+ protected void preDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
output.println(" checkContext();");
}
- protected boolean hasPostDownstreamCallHook(Method m) {
- return true;
+ @Override
+ protected boolean hasPostDownstreamCallHook(final PlainMethod pm) {
+ return !pm.isSynthetic();
}
- protected void postDownstreamCallHook(PrintWriter output, Method m) {
+ @Override
+ protected void postDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
+ final Method m = pm.getWrappedMethod();
if (m.getName().equals("glBegin")) {
output.println(" insideBeginEndPair = true;");
output.println(" // NOTE: can't check glGetError(); it's not allowed inside glBegin/glEnd pair");
@@ -934,24 +1013,39 @@ public class BuildComposablePipeline {
output.println(" insideBeginEndPair = false;");
}
- output.println(" String txt = new String(\"" + m.getName() + "(\" +");
- Class<?>[] params = m.getParameterTypes();
- for (int i = 0; params != null && i < params.length; i++) {
- output.print(" \"<" + params[i].getName() + ">");
+ output.println(" final int err = checkGLError();");
+ output.println(" if (err != GL_NO_ERROR) {");
+
+ final StringBuilder fmtsb = new StringBuilder();
+ final StringBuilder argsb = new StringBuilder();
+
+ fmtsb.append("\"%s(");
+ argsb.append("\"").append(m.getName()).append("\"");
+ final Class<?>[] params = m.getParameterTypes();
+ for (int i = 0; i < params.length; i++) {
+ if (i > 0) {
+ fmtsb.append(", ");
+ }
+ fmtsb.append("<").append(params[i].getName()).append(">");
if (params[i].isArray()) {
- output.print("\" +");
+ //nothing
} else if (params[i].equals(int.class)) {
- output.print(" 0x\"+Integer.toHexString(arg" + i + ").toUpperCase() +");
+ fmtsb.append(" 0x%X");
+ argsb.append(", arg").append(i);
} else {
- output.print(" \"+arg" + i + " +");
- }
- if (i < params.length - 1) {
- output.println(" \", \" +");
+ fmtsb.append(" %s");
+ argsb.append(", arg").append(i);
}
}
- output.println(" \")\");");
+ fmtsb.append(")\",");
+ argsb.append(");");
+
// calls to glGetError() are only allowed outside of glBegin/glEnd pairs
- output.println(" checkGLGetError( txt );");
+ output.print(" writeGLError(err, ");
+ output.println(fmtsb.toString());
+ output.print(" ");
+ output.println(argsb.toString());
+ output.println(" }");
}
}
} // end class DebugPipeline
@@ -961,33 +1055,38 @@ public class BuildComposablePipeline {
String className;
- TracePipeline(String outputDir, String outputPackage, Class<?> baseInterfaceClass, Class<?> downstreamClass) {
+ TracePipeline(final String outputDir, final String outputPackage, final Class<?> baseInterfaceClass, final Class<?> downstreamClass) {
super(outputDir, outputPackage, baseInterfaceClass, null, downstreamClass);
className = "Trace" + getBaseInterfaceName();
}
+ @Override
protected String getOutputName() {
return className;
}
+ @Override
protected int getMode() {
return 0;
}
+ @Override
protected boolean emptyMethodAllowed() {
return false;
}
+ @Override
protected boolean emptyDownstreamAllowed() {
return false;
}
@Override
- protected void preMethodEmissionHook(PrintWriter output) {
+ protected void preMethodEmissionHook(final PrintWriter output) {
super.preMethodEmissionHook(output);
}
- protected void constructorHook(PrintWriter output) {
+ @Override
+ protected void constructorHook(final PrintWriter output) {
output.print(" public " + getOutputName() + "(");
output.println(downstreamName + " " + getDownstreamObjectName() + ", PrintStream " + getOutputStreamName() + ")");
output.println(" {");
@@ -1003,7 +1102,7 @@ public class BuildComposablePipeline {
}
@Override
- protected void postMethodEmissionHook(PrintWriter output) {
+ protected void postMethodEmissionHook(final PrintWriter output) {
super.postMethodEmissionHook(output);
output.println("private PrintStream " + getOutputStreamName() + ";");
output.println("private int indent = 0;");
@@ -1037,27 +1136,37 @@ public class BuildComposablePipeline {
output.println("}");
}
- protected void emitClassDocComment(PrintWriter output) {
- output.println("/** <P> Composable pipeline which wraps an underlying {@link GL} implementation,");
- output.println(" providing tracing information to a user-specified {@link java.io.PrintStream}");
- output.println(" before and after each OpenGL method call. Sample code which installs this pipeline: </P>");
- output.println();
- output.println("<PRE>");
- output.println(" GL gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));");
- output.println("</PRE>");
- output.println("*/");
+ @Override
+ protected void emitClassDocComment(final PrintWriter output) {
+ output.println("/**");
+ output.println(" * <p>");
+ output.println(" * Composable pipeline which wraps an underlying {@link GL} implementation,");
+ output.println(" * providing tracing information to a user-specified {@link java.io.PrintStream}");
+ output.println(" * before and after each OpenGL method call.");
+ output.println(" * </p>");
+ output.println(" * <p>");
+ output.println(" * Sample code which installs this pipeline:");
+ output.println(" * <pre>");
+ output.println(" * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));");
+ output.println(" * </pre>");
+ output.println(" * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}");
+ output.println(" * </p>");
+ output.println(" */");
}
- protected boolean hasPreDownstreamCallHook(Method m) {
- return true;
+ @Override
+ protected boolean hasPreDownstreamCallHook(final PlainMethod pm) {
+ return !pm.isSynthetic();
}
- protected void preDownstreamCallHook(PrintWriter output, Method m) {
+ @Override
+ protected void preDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
+ final Method m = pm.getWrappedMethod();
if (m.getName().equals("glEnd") || m.getName().equals("glEndList")) {
- output.println("indent-=2;");
+ output.println(" indent-=2;");
output.println(" printIndent();");
} else {
- output.println("printIndent();");
+ output.println(" printIndent();");
}
output.print(" print(");
@@ -1065,17 +1174,23 @@ public class BuildComposablePipeline {
output.println(");");
}
- protected boolean hasPostDownstreamCallHook(Method m) {
- return true;
+ @Override
+ protected boolean hasPostDownstreamCallHook(final PlainMethod pm) {
+ return !pm.isSynthetic();
}
- protected void postDownstreamCallHook(PrintWriter output, Method m) {
- Class<?> ret = m.getReturnType();
+ @Override
+ protected void postDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
+ final Method m = pm.getWrappedMethod();
+ final Class<?> ret = m.getReturnType();
if (ret != Void.TYPE) {
output.println(" println(\" = \"+_res);");
} else {
output.println(" println(\"\");");
}
+
+ if (m.getName().equals("glBegin"))
+ output.println(" indent+=2;");
}
private String getOutputStreamName() {
@@ -1083,8 +1198,8 @@ public class BuildComposablePipeline {
}
} // end class TracePipeline
- public static final void printFunctionCallString(PrintWriter output, Method m) {
- Class<?>[] params = m.getParameterTypes();
+ public static final void printFunctionCallString(final PrintWriter output, final Method m) {
+ final Class<?>[] params = m.getParameterTypes();
output.print(" \"" + m.getName() + "(\"");
for (int i = 0; i < params.length; i++) {
output.print("+\"<" + params[i].getName() + ">");
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
index 482d35cae..3b08b5386 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -68,7 +68,7 @@ import java.util.regex.Pattern;
* <br>
*
* <pre>
- *
+ *
* #ifndef GL_XXXX
* GLAPI <returnType> <APIENTRY|GLAPIENTRY> glFuncName(<params>)
* #endif GL_XXXX
@@ -78,7 +78,7 @@ import java.util.regex.Pattern;
* For example, if it parses the following data:
*
* <pre>
- *
+ *
* #ifndef GL_VERSION_1_3
* GLAPI void APIENTRY glActiveTexture (GLenum);
* GLAPI void APIENTRY glMultiTexCoord1dv (GLenum, const GLdouble *);
@@ -89,7 +89,7 @@ import java.util.regex.Pattern;
* GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
* GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
* #endif
- *
+ *
* </pre>
*
* It will associate
@@ -105,16 +105,23 @@ import java.util.regex.Pattern;
* */
public class BuildStaticGLInfo {
- // Handles function pointer
- protected static int funcIdentifierGroup = 10;
- protected static Pattern funcPattern =
- Pattern.compile("^(GLAPI|GL_API|GL_APICALL|EGLAPI|extern)?(\\s*)((unsigned|const)\\s+)?(\\w+)(\\s*\\*)?(\\s+)(GLAPIENTRY|GL_APIENTRY|APIENTRY|EGLAPIENTRY|WINAPI)?(\\s*)([ew]?gl\\w+)\\s?(\\(.*)");
+ // Handles function pointer
+ protected static final int funcIdentifierGroup = 9;
+ protected static final Pattern funcPattern =
+ Pattern.compile("^(GLAPI|GL_API|GL_APICALL|EGLAPI|extern)?(\\s*)((unsigned|const)\\s+)?(\\w+)(\\s+\\*\\s*|\\s*\\*\\s+|\\s+)?(GLAPIENTRY|GL_APIENTRY|APIENTRY|EGLAPIENTRY|WINAPI)?(\\s*)([ew]?gl\\w+)\\s?(\\(.*)");
- protected static Pattern associationPattern =
+ protected static final Pattern associationPattern =
Pattern.compile("\\#ifndef ([CEW]?GL[XU]?_[A-Za-z0-9_]+)(.*)");
- protected static int defineIdentifierGroup = 1;
- protected static Pattern definePattern =
+ protected static final Pattern ifPattern =
+ Pattern.compile("\\#if(.*)");
+ protected static final Pattern elsePattern =
+ Pattern.compile("\\#(elif|else)(.*)");
+ protected static final Pattern endifPattern =
+ Pattern.compile("\\#endif(.*)");
+
+ protected static final int defineIdentifierGroup = 1;
+ protected static final Pattern definePattern =
Pattern.compile("\\#define ([CEW]?GL[XU]?_[A-Za-z0-9_]+)\\s*([A-Za-z0-9_]+)(.*)");
// Maps function / #define names to Set of names of the extensions they're declared in
@@ -131,41 +138,41 @@ public class BuildStaticGLInfo {
* classes reside, and the remaining arguments are paths to the C header
* files that should be parsed
*/
- public static void main(String[] args) throws IOException {
+ public static void main(final String[] args) throws IOException {
if (args.length > 0 && args[0].equals("-test")) {
- BuildStaticGLInfo builder = new BuildStaticGLInfo();
+ final BuildStaticGLInfo builder = new BuildStaticGLInfo();
builder.setDebug(true);
- String[] newArgs = new String[args.length - 1];
+ final String[] newArgs = new String[args.length - 1];
System.arraycopy(args, 1, newArgs, 0, args.length - 1);
builder.parse(newArgs);
builder.dump();
System.exit(0);
}
- String packageName = args[0];
- String packageDir = args[1];
+ final String packageName = args[0];
+ final String packageDir = args[1];
- String[] cHeaderFilePaths = new String[args.length - 2];
+ final String[] cHeaderFilePaths = new String[args.length - 2];
System.arraycopy(args, 2, cHeaderFilePaths, 0, cHeaderFilePaths.length);
- BuildStaticGLInfo builder = new BuildStaticGLInfo();
+ final BuildStaticGLInfo builder = new BuildStaticGLInfo();
try {
builder.parse(cHeaderFilePaths);
- File file = new File(packageDir + File.separatorChar + "StaticGLInfo.java");
- String parentDir = file.getParent();
+ final File file = new File(packageDir + File.separatorChar + "StaticGLInfo.java");
+ final String parentDir = file.getParent();
if (parentDir != null) {
- File pDirFile = new File(parentDir);
+ final File pDirFile = new File(parentDir);
pDirFile.mkdirs();
}
- PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(file)));
+ final PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(file)));
builder.emitJavaCode(writer, packageName);
writer.flush();
writer.close();
- } catch (Exception e) {
- StringBuilder buf = new StringBuilder("{ ");
+ } catch (final Exception e) {
+ final StringBuilder buf = new StringBuilder("{ ");
for (int i = 0; i < cHeaderFilePaths.length; ++i) {
buf.append(cHeaderFilePaths[i]);
buf.append(" ");
@@ -176,13 +183,13 @@ public class BuildStaticGLInfo {
}
}
- public void setDebug(boolean v) {
+ public void setDebug(final boolean v) {
DEBUG = v;
}
/** Parses the supplied C header files and adds the function
associations contained therein to the internal map. */
- public void parse(String[] cHeaderFilePaths) throws IOException {
+ public void parse(final String[] cHeaderFilePaths) throws IOException {
for (int i = 0; i < cHeaderFilePaths.length; i++) {
parse(cHeaderFilePaths[i]);
}
@@ -190,42 +197,66 @@ public class BuildStaticGLInfo {
/** Parses the supplied C header file and adds the function
associations contained therein to the internal map. */
- public void parse(String cHeaderFilePath) throws IOException {
- BufferedReader reader = new BufferedReader(new FileReader(cHeaderFilePath));
+ public void parse(final String cHeaderFilePath) throws IOException {
+ final BufferedReader reader = new BufferedReader(new FileReader(cHeaderFilePath));
String line, activeAssociation = null;
Matcher m = null;
+ int block = 0;
while ((line = reader.readLine()) != null) {
int type = 0; // 1-define, 2-function
- // see if we're inside a #ifndef GL_XXX block and matching a function
- if (activeAssociation != null) {
+ if ( 0 < block ) { // inside a #ifndef GL_XXX block and matching a function, if block > 0
String identifier = null;
- if ((m = funcPattern.matcher(line)).matches()) {
- identifier = m.group(funcIdentifierGroup).trim();
- type = 2;
- } else if ((m = definePattern.matcher(line)).matches()) {
- identifier = m.group(defineIdentifierGroup).trim();
- type = 1;
- } else if (line.startsWith("#endif")) {
- if (DEBUG) {
- System.err.println("END ASSOCIATION BLOCK: <" + activeAssociation + ">");
+ if( 2 >= block ) { // not within sub-blocks > 2, i.e. further typedefs
+ if ((m = funcPattern.matcher(line)).matches()) {
+ identifier = m.group(funcIdentifierGroup).trim();
+ type = 2;
+ } else if ((m = definePattern.matcher(line)).matches()) {
+ identifier = m.group(defineIdentifierGroup).trim();
+ type = 1;
}
- activeAssociation = null;
}
- if ((identifier != null)
- && (activeAssociation != null)
- && // Handles #ifndef GL_... #define GL_...
- !identifier.equals(activeAssociation)) {
+ if ( identifier != null &&
+ activeAssociation != null &&
+ !identifier.equals(activeAssociation) // Handles #ifndef GL_... #define GL_...
+ )
+ {
addAssociation(identifier, activeAssociation);
if (DEBUG) {
- System.err.println(" ADDING ASSOCIATION: <" + identifier + "> <" + activeAssociation + "> ; type " + type);
+ System.err.println("<"+block+"> ADDING ASSOCIATION: <" + identifier + "> <" + activeAssociation + "> ; type " + type);
+ }
+ } else {
+ if ((m = ifPattern.matcher(line)).matches()) {
+ final String comment = m.group(1).trim();
+ block++;
+ if (DEBUG) {
+ System.err.println("<"+block+"> BEGIN IF BLOCK: <" + comment + ">");
+ }
+ } else if ((m = elsePattern.matcher(line)).matches()) {
+ final String comment = m.group(1).trim();
+ if (DEBUG) {
+ System.err.println("<"+block+"> ELSE BLOCK: <" + comment + ">");
+ }
+ } else if ((m = endifPattern.matcher(line)).matches()) {
+ final String comment = m.group(1).trim();
+ block--;
+ if( 0 == block ) {
+ if (DEBUG) {
+ System.err.println("<"+block+"> END ASSOCIATION BLOCK: <" + activeAssociation + " <-> " + comment + ">");
+ }
+ activeAssociation = null;
+ } else {
+ if (DEBUG) {
+ System.err.println("<"+block+"> END IF BLOCK: <" + comment + ">");
+ }
+ }
}
}
} else if ((m = associationPattern.matcher(line)).matches()) {
// found a new #ifndef GL_XXX block
activeAssociation = m.group(1).trim();
-
+ block++;
if (DEBUG) {
- System.err.println("BEGIN ASSOCIATION BLOCK: <" + activeAssociation + ">");
+ System.err.println("<"+block+"> BEGIN ASSOCIATION BLOCK: <" + activeAssociation + ">");
}
}
}
@@ -233,23 +264,23 @@ public class BuildStaticGLInfo {
}
public void dump() {
- for (String name : extensionToDeclarationMap.keySet()) {
- Set<String> decls = extensionToDeclarationMap.get(name);
+ for (final String name : extensionToDeclarationMap.keySet()) {
+ final Set<String> decls = extensionToDeclarationMap.get(name);
System.out.println("<" + name + "> :");
- List<String> l = new ArrayList<String>();
+ final List<String> l = new ArrayList<String>();
l.addAll(decls);
Collections.sort(l);
- for (String str : l) {
+ for (final String str : l) {
System.out.println(" <" + str + ">");
}
}
}
- public Set<String> getExtension(String identifier) {
+ public Set<String> getExtension(final String identifier) {
return declarationToExtensionMap.get(identifier);
}
- public Set<String> getDeclarations(String extension) {
+ public Set<String> getDeclarations(final String extension) {
return extensionToDeclarationMap.get(extension);
}
@@ -257,7 +288,7 @@ public class BuildStaticGLInfo {
return extensionToDeclarationMap.keySet();
}
- public void emitJavaCode(PrintWriter output, String packageName) {
+ public void emitJavaCode(final PrintWriter output, final String packageName) {
output.println("package " + packageName + ";");
output.println();
output.println("import java.util.*;");
@@ -309,7 +340,7 @@ public class BuildStaticGLInfo {
// Compute max capacity
int maxCapacity = 0;
- for (String name : declarationToExtensionMap.keySet()) {
+ for (final String name : declarationToExtensionMap.keySet()) {
if (!name.startsWith("GL")) {
++maxCapacity;
}
@@ -317,17 +348,17 @@ public class BuildStaticGLInfo {
output.println(" funcToAssocMap = new HashMap(" + maxCapacity + "); // approximate max capacity");
output.println(" String group;");
- ArrayList<String> sets = new ArrayList<String>(extensionToDeclarationMap.keySet());
+ final ArrayList<String> sets = new ArrayList<String>(extensionToDeclarationMap.keySet());
Collections.sort(sets);
- for (String groupName : sets) {
- Set<String> funcs = extensionToDeclarationMap.get(groupName);
- List<String> l = new ArrayList<String>();
+ for (final String groupName : sets) {
+ final Set<String> funcs = extensionToDeclarationMap.get(groupName);
+ final List<String> l = new ArrayList<String>();
l.addAll(funcs);
Collections.sort(l);
- Iterator<String> funcIter = l.iterator();
+ final Iterator<String> funcIter = l.iterator();
boolean printedHeader = false;
while (funcIter.hasNext()) {
- String funcName = funcIter.next();
+ final String funcName = funcIter.next();
if (!funcName.startsWith("GL")) {
if (!printedHeader) {
output.println();
@@ -349,14 +380,14 @@ public class BuildStaticGLInfo {
//----------------------------------------------------------------------
// Internals only below this point
//
- protected void addAssociation(String identifier, String association) {
+ protected void addAssociation(final String identifier, final String association) {
Set<String> extensions = declarationToExtensionMap.get(identifier);
if(null == extensions) {
extensions = new HashSet<String>();
declarationToExtensionMap.put(identifier, extensions);
}
extensions.add(association);
-
+
Set<String> identifiers = extensionToDeclarationMap.get(association);
if (identifiers == null) {
identifiers = new HashSet<String>();
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
index ba025e18c..5da45abfe 100755..100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -59,15 +59,17 @@ import java.util.StringTokenizer;
public class GLConfiguration extends ProcAddressConfiguration {
// The following data members support ignoring an entire extension at a time
- private List<String> glHeaders = new ArrayList<String>();
- private Set<String> ignoredExtensions = new HashSet<String>();
- private Set<String> extensionsRenamedIntoCore = new HashSet<String>();
+ private final List<String> glHeaders = new ArrayList<String>();
+ private final Set<String> ignoredExtensions = new HashSet<String>();
+ private final Set<String> forcedExtensions = new HashSet<String>();
+ private final Set<String> extensionsRenamedIntoCore = new HashSet<String>();
private BuildStaticGLInfo glInfo;
// Maps function names to the kind of buffer object it deals with
- private Map<String, GLEmitter.BufferObjectKind> bufferObjectKinds = new HashMap<String, GLEmitter.BufferObjectKind>();
- private GLEmitter emitter;
- private Set<String> dropUniqVendorExtensions = new HashSet<String>();
+ private final Map<String, GLEmitter.BufferObjectKind> bufferObjectKinds = new HashMap<String, GLEmitter.BufferObjectKind>();
+ private final Set<String> bufferObjectOnly = new HashSet<String>();
+ private final GLEmitter emitter;
+ private final Set<String> dropUniqVendorExtensions = new HashSet<String>();
// This directive is off by default but can help automatically
// indicate which extensions have been folded into the core OpenGL
@@ -75,46 +77,52 @@ public class GLConfiguration extends ProcAddressConfiguration {
private boolean autoUnifyExtensions = false;
private boolean allowNonGLExtensions = false;
- public GLConfiguration(GLEmitter emitter) {
+ public GLConfiguration(final GLEmitter emitter) {
super();
this.emitter = emitter;
try {
setProcAddressNameExpr("PFN $UPPERCASE({0}) PROC");
- } catch (NoSuchElementException e) {
+ } catch (final NoSuchElementException e) {
throw new RuntimeException("Error configuring ProcAddressNameExpr", e);
}
}
@Override
- protected void dispatch(String cmd, StringTokenizer tok, File file, String filename, int lineNo) throws IOException {
+ protected void dispatch(final String cmd, final StringTokenizer tok, final File file, final String filename, final int lineNo) throws IOException {
if (cmd.equalsIgnoreCase("IgnoreExtension")) {
- String sym = readString("IgnoreExtension", tok, filename, lineNo);
+ final String sym = readString("IgnoreExtension", tok, filename, lineNo);
ignoredExtensions.add(sym);
+ } else if (cmd.equalsIgnoreCase("ForceExtension")) {
+ final String sym = readString("ForceExtension", tok, filename, lineNo);
+ forcedExtensions.add(sym);
} else if (cmd.equalsIgnoreCase("RenameExtensionIntoCore")) {
- String sym = readString("RenameExtensionIntoCore", tok, filename, lineNo);
+ final String sym = readString("RenameExtensionIntoCore", tok, filename, lineNo);
extensionsRenamedIntoCore.add(sym);
} else if (cmd.equalsIgnoreCase("AllowNonGLExtensions")) {
allowNonGLExtensions = readBoolean("AllowNonGLExtensions", tok, filename, lineNo).booleanValue();
} else if (cmd.equalsIgnoreCase("AutoUnifyExtensions")) {
autoUnifyExtensions = readBoolean("AutoUnifyExtensions", tok, filename, lineNo).booleanValue();
} else if (cmd.equalsIgnoreCase("GLHeader")) {
- String sym = readString("GLHeader", tok, filename, lineNo);
+ final String sym = readString("GLHeader", tok, filename, lineNo);
glHeaders.add(sym);
} else if (cmd.equalsIgnoreCase("BufferObjectKind")) {
readBufferObjectKind(tok, filename, lineNo);
+ } else if (cmd.equalsIgnoreCase("BufferObjectOnly")) {
+ final String sym = readString("BufferObjectOnly", tok, filename, lineNo);
+ bufferObjectOnly.add(sym);
} else if (cmd.equalsIgnoreCase("DropUniqVendorExtensions")) {
- String sym = readString("DropUniqVendorExtensions", tok, filename, lineNo);
+ final String sym = readString("DropUniqVendorExtensions", tok, filename, lineNo);
dropUniqVendorExtensions.add(sym);
} else {
super.dispatch(cmd, tok, file, filename, lineNo);
}
}
- protected void readBufferObjectKind(StringTokenizer tok, String filename, int lineNo) {
+ protected void readBufferObjectKind(final StringTokenizer tok, final String filename, final int lineNo) {
try {
- String kindString = tok.nextToken();
+ final String kindString = tok.nextToken();
GLEmitter.BufferObjectKind kind = null;
- String target = tok.nextToken();
+ final String target = tok.nextToken();
if (kindString.equalsIgnoreCase("UnpackPixel")) {
kind = GLEmitter.BufferObjectKind.UNPACK_PIXEL;
} else if (kindString.equalsIgnoreCase("PackPixel")) {
@@ -123,14 +131,16 @@ public class GLConfiguration extends ProcAddressConfiguration {
kind = GLEmitter.BufferObjectKind.ARRAY;
} else if (kindString.equalsIgnoreCase("Element")) {
kind = GLEmitter.BufferObjectKind.ELEMENT;
+ } else if (kindString.equalsIgnoreCase("Indirect")) {
+ kind = GLEmitter.BufferObjectKind.INDIRECT;
} else {
throw new RuntimeException("Error parsing \"BufferObjectKind\" command at line " + lineNo
+ " in file \"" + filename + "\": illegal BufferObjectKind \""
- + kindString + "\", expected one of UnpackPixel, PackPixel, Array, or Element");
+ + kindString + "\", expected one of UnpackPixel, PackPixel, Array, Element or Indirect");
}
bufferObjectKinds.put(target, kind);
- } catch (NoSuchElementException e) {
+ } catch (final NoSuchElementException e) {
throw new RuntimeException("Error parsing \"BufferObjectKind\" command at line " + lineNo
+ " in file \"" + filename + "\"", e);
}
@@ -140,10 +150,10 @@ public class GLConfiguration extends ProcAddressConfiguration {
automatically generates prologue code for functions associated
with buffer objects. */
@Override
- public List<String> javaPrologueForMethod(MethodBinding binding, boolean forImplementingMethodCall, boolean eraseBufferAndArrayTypes) {
+ public List<String> javaPrologueForMethod(final MethodBinding binding, final boolean forImplementingMethodCall, final boolean eraseBufferAndArrayTypes) {
List<String> res = super.javaPrologueForMethod(binding, forImplementingMethodCall, eraseBufferAndArrayTypes);
- GLEmitter.BufferObjectKind kind = getBufferObjectKind(binding.getName());
+ final GLEmitter.BufferObjectKind kind = getBufferObjectKind(binding.getName());
if (kind != null) {
// Need to generate appropriate prologue based on both buffer
// object kind and whether this variant of the MethodBinding
@@ -151,7 +161,7 @@ public class GLConfiguration extends ProcAddressConfiguration {
//
// NOTE we MUST NOT mutate the array returned from the super
// call!
- ArrayList<String> res2 = new ArrayList<String>();
+ final ArrayList<String> res2 = new ArrayList<String>();
if (res != null) {
res2.addAll(res);
}
@@ -167,14 +177,16 @@ public class GLConfiguration extends ProcAddressConfiguration {
prologue = prologue + "ArrayVBO";
} else if (kind == GLEmitter.BufferObjectKind.ELEMENT) {
prologue = prologue + "ElementVBO";
+ } else if (kind == GLEmitter.BufferObjectKind.INDIRECT) {
+ prologue = prologue + "IndirectVBO";
} else {
throw new RuntimeException("Unknown BufferObjectKind " + kind);
}
if (emitter.isBufferObjectMethodBinding(binding)) {
- prologue = prologue + "Enabled";
+ prologue = prologue + "Bound";
} else {
- prologue = prologue + "Disabled";
+ prologue = prologue + "Unbound";
}
prologue = prologue + "(true);";
@@ -184,8 +196,8 @@ public class GLConfiguration extends ProcAddressConfiguration {
// Must also filter out bogus rangeCheck directives for VBO/PBO
// variants
if (emitter.isBufferObjectMethodBinding(binding)) {
- for (Iterator<String> iter = res.iterator(); iter.hasNext();) {
- String line = iter.next();
+ for (final Iterator<String> iter = res.iterator(); iter.hasNext();) {
+ final String line = iter.next();
if (line.indexOf("Buffers.rangeCheck") >= 0) {
iter.remove();
}
@@ -199,19 +211,24 @@ public class GLConfiguration extends ProcAddressConfiguration {
@Override
public void dumpIgnores() {
System.err.println("GL Ignored extensions: ");
- for (String str : ignoredExtensions) {
+ for (final String str : ignoredExtensions) {
+ System.err.println("\t" + str);
+ }
+ System.err.println("GL Forced extensions: ");
+ for (final String str : forcedExtensions) {
System.err.println("\t" + str);
}
super.dumpIgnores();
}
- protected boolean shouldIgnoreExtension(String symbol, boolean criteria) {
+ protected boolean shouldIgnoreExtension(final String symbol, final boolean criteria) {
if (criteria && glInfo != null) {
- Set<String> extensionNames = glInfo.getExtension(symbol);
- if(null!=extensionNames) {
- for(Iterator<String> i=extensionNames.iterator(); i.hasNext(); ) {
- String extensionName = i.next();
- if (extensionName != null && ignoredExtensions.contains(extensionName)) {
+ final Set<String> extensionNames = glInfo.getExtension(symbol);
+ if( null != extensionNames ) {
+ boolean ignoredExtension = false;
+ for(final Iterator<String> i=extensionNames.iterator(); !ignoredExtension && i.hasNext(); ) {
+ final String extensionName = i.next();
+ if ( extensionName != null && ignoredExtensions.contains(extensionName) ) {
if (DEBUG_IGNORES) {
System.err.print("Ignore symbol <" + symbol + "> of extension <" + extensionName + ">");
if(extensionNames.size()==1) {
@@ -220,15 +237,32 @@ public class GLConfiguration extends ProcAddressConfiguration {
System.err.println(", WARNING MULTIPLE OCCURENCE: "+extensionNames);
}
}
- return true;
+ ignoredExtension = true;
+ }
+ }
+ if( ignoredExtension ) {
+ ignoredExtension = !shouldForceExtension( symbol, true, symbol );
+ if( ignoredExtension ) {
+ final Set<String> origSymbols = getRenamedJavaSymbols( symbol );
+ if(null != origSymbols) {
+ for(final String origSymbol : origSymbols) {
+ if( shouldForceExtension( origSymbol, true, symbol ) ) {
+ ignoredExtension = false;
+ break;
+ }
+ }
+ }
}
}
+ if( ignoredExtension ) {
+ return true;
+ }
}
- boolean isGLEnum = GLNameResolver.isGLEnumeration(symbol);
- boolean isGLFunc = GLNameResolver.isGLFunction(symbol);
+ final boolean isGLEnum = GLNameResolver.isGLEnumeration(symbol);
+ final boolean isGLFunc = GLNameResolver.isGLFunction(symbol);
if (isGLFunc || isGLEnum) {
if (GLNameResolver.isExtensionVEN(symbol, isGLFunc)) {
- String extSuffix = GLNameResolver.getExtensionSuffix(symbol, isGLFunc);
+ final String extSuffix = GLNameResolver.getExtensionSuffix(symbol, isGLFunc);
if (getDropUniqVendorExtensions(extSuffix)) {
if (DEBUG_IGNORES) {
System.err.println("Ignore UniqVendorEXT: " + symbol + ", vendor " + extSuffix);
@@ -241,21 +275,44 @@ public class GLConfiguration extends ProcAddressConfiguration {
return false;
}
+ public boolean shouldForceExtension(final String symbol, final boolean criteria, final String renamedSymbol) {
+ if (criteria && glInfo != null) {
+ final Set<String> extensionNames = glInfo.getExtension(symbol);
+ if( null != extensionNames ) {
+ for(final Iterator<String> i=extensionNames.iterator(); i.hasNext(); ) {
+ final String extensionName = i.next();
+ if ( extensionName != null && forcedExtensions.contains(extensionName) ) {
+ if (DEBUG_IGNORES) {
+ System.err.print("Not Ignore symbol <" + symbol + " -> " + renamedSymbol + "> of extension <" + extensionName + ">");
+ if(extensionNames.size()==1) {
+ System.err.println(", single .");
+ } else {
+ System.err.println(", WARNING MULTIPLE OCCURENCE: "+extensionNames);
+ }
+ }
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
@Override
- public boolean shouldIgnoreInInterface(String symbol) {
+ public boolean shouldIgnoreInInterface(final String symbol) {
return shouldIgnoreInInterface(symbol, true);
}
- public boolean shouldIgnoreInInterface(String symbol, boolean checkEXT) {
+ public boolean shouldIgnoreInInterface(final String symbol, final boolean checkEXT) {
return shouldIgnoreExtension(symbol, checkEXT) || super.shouldIgnoreInInterface(symbol);
}
@Override
- public boolean shouldIgnoreInImpl(String symbol) {
+ public boolean shouldIgnoreInImpl(final String symbol) {
return shouldIgnoreInImpl(symbol, true);
}
- public boolean shouldIgnoreInImpl(String symbol, boolean checkEXT) {
+ public boolean shouldIgnoreInImpl(final String symbol, final boolean checkEXT) {
return shouldIgnoreExtension(symbol, checkEXT) || super.shouldIgnoreInImpl(symbol);
}
@@ -273,28 +330,32 @@ public class GLConfiguration extends ProcAddressConfiguration {
}
/** shall the non unified (uniq) vendor extensions be dropped ? */
- public boolean getDropUniqVendorExtensions(String extName) {
+ public boolean getDropUniqVendorExtensions(final String extName) {
return dropUniqVendorExtensions.contains(extName);
}
/** Returns the kind of buffer object this function deals with, or
null if none. */
- GLEmitter.BufferObjectKind getBufferObjectKind(String name) {
+ GLEmitter.BufferObjectKind getBufferObjectKind(final String name) {
return bufferObjectKinds.get(name);
}
- public boolean isBufferObjectFunction(String name) {
+ public boolean isBufferObjectFunction(final String name) {
return (getBufferObjectKind(name) != null);
}
+ public boolean isBufferObjectOnly(final String name) {
+ return bufferObjectOnly.contains(name);
+ }
+
/** Parses any GL headers specified in the configuration file for
the purpose of being able to ignore an extension at a time. */
- public void parseGLHeaders(GlueEmitterControls controls) throws IOException {
+ public void parseGLHeaders(final GlueEmitterControls controls) throws IOException {
if (!glHeaders.isEmpty()) {
glInfo = new BuildStaticGLInfo();
glInfo.setDebug(GlueGen.debug());
- for (String file : glHeaders) {
- String fullPath = controls.findHeaderFile(file);
+ for (final String file : glHeaders) {
+ final String fullPath = controls.findHeaderFile(file);
if (fullPath == null) {
throw new IOException("Unable to locate header file \"" + file + "\"");
}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
index 809c6783d..bc230c83a 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -72,12 +72,12 @@ public class GLEmitter extends ProcAddressEmitter {
// Keeps track of which MethodBindings were created for handling
// Buffer Object variants. Used as a Set rather than a Map.
- private Map<MethodBinding, MethodBinding> bufferObjectMethodBindings = new IdentityHashMap<MethodBinding, MethodBinding>();
+ private final Map<MethodBinding, MethodBinding> bufferObjectMethodBindings = new IdentityHashMap<MethodBinding, MethodBinding>();
- enum BufferObjectKind { UNPACK_PIXEL, PACK_PIXEL, ARRAY, ELEMENT}
+ enum BufferObjectKind { UNPACK_PIXEL, PACK_PIXEL, ARRAY, ELEMENT, INDIRECT}
@Override
- public void beginEmission(GlueEmitterControls controls) throws IOException {
+ public void beginEmission(final GlueEmitterControls controls) throws IOException {
getGLConfig().parseGLHeaders(controls);
renameExtensionsIntoCore();
if (getGLConfig().getAutoUnifyExtensions()) {
@@ -93,30 +93,30 @@ public class GLEmitter extends ProcAddressEmitter {
// already in the core namespace in desktop OpenGL. It builds upon
// renaming mechanisms that are built elsewhere.
- GLConfiguration config = getGLConfig();
- Set<String> extensionsRenamedIntoCore = config.getExtensionsRenamedIntoCore();
- BuildStaticGLInfo glInfo = config.getGLInfo();
+ final GLConfiguration config = getGLConfig();
+ final Set<String> extensionsRenamedIntoCore = config.getExtensionsRenamedIntoCore();
+ final BuildStaticGLInfo glInfo = config.getGLInfo();
if (null == glInfo) {
if (extensionsRenamedIntoCore.size() > 0) {
throw new RuntimeException("ExtensionRenamedIntoCore (num: " + extensionsRenamedIntoCore.size() + "), but no GLHeader");
}
return;
}
- for (String extension : extensionsRenamedIntoCore) {
+ for (final String extension : extensionsRenamedIntoCore) {
if(JavaConfiguration.DEBUG_RENAMES) {
System.err.println("<RenameExtensionIntoCore: "+extension+" BEGIN");
}
- Set<String> declarations = glInfo.getDeclarations(extension);
+ final Set<String> declarations = glInfo.getDeclarations(extension);
if (declarations != null) {
- for (Iterator<String> iterator = declarations.iterator(); iterator.hasNext();) {
- String decl = iterator.next();
- boolean isGLFunction = GLNameResolver.isGLFunction(decl);
+ for (final Iterator<String> iterator = declarations.iterator(); iterator.hasNext();) {
+ final String decl = iterator.next();
+ final boolean isGLFunction = GLNameResolver.isGLFunction(decl);
boolean isGLEnumeration = false;
if (!isGLFunction) {
isGLEnumeration = GLNameResolver.isGLEnumeration(decl);
}
if (isGLFunction || isGLEnumeration) {
- String renamed = GLNameResolver.normalize(decl, isGLFunction);
+ final String renamed = GLNameResolver.normalize(decl, isGLFunction);
if (!renamed.equals(decl)) {
config.addJavaSymbolRename(decl, renamed);
}
@@ -125,7 +125,7 @@ public class GLEmitter extends ProcAddressEmitter {
}
if(JavaConfiguration.DEBUG_RENAMES) {
System.err.println("RenameExtensionIntoCore: "+extension+" END>");
- }
+ }
}
}
@@ -134,33 +134,36 @@ public class GLEmitter extends ProcAddressEmitter {
private List<ConstantDefinition> constants;
private List<FunctionSymbol> functions;
- public void filterSymbols(List<ConstantDefinition> constants,
- List<FunctionSymbol> functions) {
+ @Override
+ public void filterSymbols(final List<ConstantDefinition> constants,
+ final List<FunctionSymbol> functions) {
this.constants = constants;
this.functions = functions;
doWork();
}
+ @Override
public List<ConstantDefinition> getConstants() {
return constants;
}
+ @Override
public List<FunctionSymbol> getFunctions() {
return functions;
}
private void doWork() {
- BuildStaticGLInfo glInfo = getGLConfig().getGLInfo();
+ final BuildStaticGLInfo glInfo = getGLConfig().getGLInfo();
if (glInfo == null) {
return;
}
// Try to retain a "good" ordering for these symbols
- Map<String, ConstantDefinition> constantMap = new LinkedHashMap<String, ConstantDefinition>();
- for (ConstantDefinition def : constants) {
+ final Map<String, ConstantDefinition> constantMap = new LinkedHashMap<String, ConstantDefinition>();
+ for (final ConstantDefinition def : constants) {
constantMap.put(def.getName(), def);
}
- Map<String, FunctionSymbol> functionMap = new LinkedHashMap<String, FunctionSymbol>();
- for (FunctionSymbol sym : functions) {
+ final Map<String, FunctionSymbol> functionMap = new LinkedHashMap<String, FunctionSymbol>();
+ for (final FunctionSymbol sym : functions) {
functionMap.put(sym.getName(), sym);
}
@@ -172,15 +175,15 @@ public class GLEmitter extends ProcAddressEmitter {
// that doesn't support the core version of these APIs, the runtime
// will take care of looking up the extension version of these entry
// points.
- Set<String> extensionNames = glInfo.getExtensions();
+ final Set<String> extensionNames = glInfo.getExtensions();
- for (String extension : extensionNames) {
- Set<String> declarations = glInfo.getDeclarations(extension);
+ for (final String extension : extensionNames) {
+ final Set<String> declarations = glInfo.getDeclarations(extension);
boolean isExtension = true;
boolean shouldUnify = true;
String cause = null;
- for (String decl : declarations) {
- boolean isFunc = !decl.startsWith("GL_");
+ for (final String decl : declarations) {
+ final boolean isFunc = !decl.startsWith("GL_");
if (!GLNameResolver.isExtension(decl, isFunc)) {
isExtension = false;
break;
@@ -199,7 +202,7 @@ public class GLEmitter extends ProcAddressEmitter {
}
}
cause = decl;
- String unifiedName = GLNameResolver.normalize(decl, isFunc);
+ final String unifiedName = GLNameResolver.normalize(decl, isFunc);
// NOTE that we look up the unified name in the
// BuildStaticGLInfo's notion of the APIs -- since
// we might not be emitting glue code for the
@@ -222,8 +225,8 @@ public class GLEmitter extends ProcAddressEmitter {
}
if (isExtension) {
if (shouldUnify) {
- for (String decl : declarations) {
- boolean isFunc = !decl.startsWith("GL_");
+ for (final String decl : declarations) {
+ final boolean isFunc = !decl.startsWith("GL_");
if (isFunc) {
functionMap.remove(decl);
} else {
@@ -241,7 +244,7 @@ public class GLEmitter extends ProcAddressEmitter {
}
}
- private void unifyExtensions(GlueEmitterControls controls) {
+ private void unifyExtensions(final GlueEmitterControls controls) {
controls.runSymbolFilter(new ExtensionUnifier());
}
@@ -261,19 +264,24 @@ public class GLEmitter extends ProcAddressEmitter {
inform the CMethodBindingEmitter that it is overloaded in this
case (though we default to true currently). */
@Override
- protected List<MethodBinding> expandMethodBinding(MethodBinding binding) {
- List<MethodBinding> bindings = super.expandMethodBinding(binding);
+ protected List<MethodBinding> expandMethodBinding(final MethodBinding binding) {
+ final GLConfiguration glConfig = getGLConfig();
+ final List<MethodBinding> bindings = super.expandMethodBinding(binding);
- if (!getGLConfig().isBufferObjectFunction(binding.getName())) {
+ if ( !glConfig.isBufferObjectFunction(binding.getName()) ) {
return bindings;
}
+ final boolean bufferObjectOnly = glConfig.isBufferObjectOnly(binding.getName());
- List<MethodBinding> newBindings = new ArrayList<MethodBinding>(bindings);
+ final List<MethodBinding> newBindings = new ArrayList<MethodBinding>();
// Need to expand each one of the generated bindings to take a
// Java long instead of a Buffer for each void* argument
- for (MethodBinding cur : bindings) {
+ // for (MethodBinding cur : bindings) {
+ int j=0;
+ while( j < bindings.size() ) {
+ final MethodBinding cur = bindings.get(j);
// Some of these routines (glBitmap) take strongly-typed
// primitive pointers as arguments which are expanded into
@@ -281,6 +289,7 @@ public class GLEmitter extends ProcAddressEmitter {
// This test (rather than !signatureUsesNIO) is used to catch
// more unexpected situations
if (cur.signatureUsesJavaPrimitiveArrays()) {
+ j++;
continue;
}
@@ -300,13 +309,20 @@ public class GLEmitter extends ProcAddressEmitter {
// Now need to flag this MethodBinding so that we generate the
// correct flags in the emitters later
bufferObjectMethodBindings.put(result, result);
+
+ if( bufferObjectOnly ) {
+ bindings.remove(j);
+ } else {
+ j++;
+ }
}
+ bindings.addAll(newBindings);
- return newBindings;
+ return bindings;
}
@Override
- protected boolean needsModifiedEmitters(FunctionSymbol sym) {
+ protected boolean needsModifiedEmitters(final FunctionSymbol sym) {
if ((!needsProcAddressWrapper(sym) && !needsBufferObjectVariant(sym))
|| getConfig().isUnimplemented(sym.getName())) {
return false;
@@ -315,22 +331,22 @@ public class GLEmitter extends ProcAddressEmitter {
return true;
}
- public boolean isBufferObjectMethodBinding(MethodBinding binding) {
+ public boolean isBufferObjectMethodBinding(final MethodBinding binding) {
return bufferObjectMethodBindings.containsKey(binding);
}
@Override
- public void emitDefine(ConstantDefinition def, String optionalComment) throws Exception {
- BuildStaticGLInfo glInfo = getGLConfig().getGLInfo();
+ public void emitDefine(final ConstantDefinition def, final String optionalComment) throws Exception {
+ final BuildStaticGLInfo glInfo = getGLConfig().getGLInfo();
if (null == glInfo) {
throw new Exception("No GLInfo for: " + def);
}
- String symbolRenamed = def.getName();
- StringBuilder newComment = new StringBuilder();
+ final String symbolRenamed = def.getName();
+ final StringBuilder newComment = new StringBuilder();
newComment.append("Part of ");
if (0 == addExtensionsOfSymbols2Buffer(newComment, ", ", "; ", symbolRenamed, def.getAliasedNames())) {
if (def.isEnum()) {
- String enumName = def.getEnumName();
+ final String enumName = def.getEnumName();
if (null != enumName) {
newComment.append(enumName);
} else {
@@ -346,7 +362,7 @@ public class GLEmitter extends ProcAddressEmitter {
// ...
// #endif
if (JavaConfiguration.DEBUG_IGNORES) {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
JavaEmitter.addStrings2Buffer(sb, ", ", symbolRenamed, def.getAliasedNames());
System.err.println("Dropping marker: " + sb.toString());
}
@@ -363,12 +379,12 @@ public class GLEmitter extends ProcAddressEmitter {
super.emitDefine(def, newComment.toString());
}
- private int addExtensionListOfSymbol2Buffer(BuildStaticGLInfo glInfo, StringBuilder buf, String sep1, String name) {
+ private int addExtensionListOfSymbol2Buffer(final BuildStaticGLInfo glInfo, final StringBuilder buf, final String sep1, final String name) {
int num = 0;
- Set<String> extensionNames = glInfo.getExtension(name);
+ final Set<String> extensionNames = glInfo.getExtension(name);
if(null!=extensionNames) {
- for(Iterator<String> i=extensionNames.iterator(); i.hasNext(); ) {
- String extensionName = i.next();
+ for(final Iterator<String> i=extensionNames.iterator(); i.hasNext(); ) {
+ final String extensionName = i.next();
if (null != extensionName) {
buf.append("<code>");
buf.append(extensionName);
@@ -382,19 +398,19 @@ public class GLEmitter extends ProcAddressEmitter {
}
return num;
}
- private int addExtensionListOfAliasedSymbols2Buffer(BuildStaticGLInfo glInfo, StringBuilder buf, String sep1, String sep2, String name, Collection<String> exclude) {
+ private int addExtensionListOfAliasedSymbols2Buffer(final BuildStaticGLInfo glInfo, final StringBuilder buf, final String sep1, final String sep2, final String name, final Collection<String> exclude) {
int num = 0;
- if(null != name) {
+ if(null != name) {
num += addExtensionListOfSymbol2Buffer(glInfo, buf, sep1, name); // extensions of given name
boolean needsSep2 = 0<num;
- Set<String> origNames = cfg.getRenamedJavaSymbols(name);
+ final Set<String> origNames = cfg.getRenamedJavaSymbols(name);
if(null != origNames) {
- for(String origName : origNames) {
+ for(final String origName : origNames) {
if(!exclude.contains(origName)) {
if (needsSep2) {
buf.append(sep2); // diff-name seperator
- }
- int num2 = addExtensionListOfSymbol2Buffer(glInfo, buf, sep1, origName); // extensions of orig-name
+ }
+ final int num2 = addExtensionListOfSymbol2Buffer(glInfo, buf, sep1, origName); // extensions of orig-name
needsSep2 = num<num2;
num += num2;
}
@@ -403,9 +419,9 @@ public class GLEmitter extends ProcAddressEmitter {
}
return num;
}
-
- public int addExtensionsOfSymbols2Buffer(StringBuilder buf, String sep1, String sep2, String first, Collection<String> col) {
- BuildStaticGLInfo glInfo = getGLConfig().getGLInfo();
+
+ public int addExtensionsOfSymbols2Buffer(StringBuilder buf, final String sep1, final String sep2, final String first, final Collection<String> col) {
+ final BuildStaticGLInfo glInfo = getGLConfig().getGLInfo();
if (null == glInfo) {
throw new RuntimeException("No GLInfo for: " + first);
}
@@ -416,11 +432,11 @@ public class GLEmitter extends ProcAddressEmitter {
num += addExtensionListOfAliasedSymbols2Buffer(glInfo, buf, sep1, sep2, first, col);
boolean needsSep2 = 0<num;
- for(Iterator<String> iter = col.iterator(); iter.hasNext(); ) {
+ for(final Iterator<String> iter = col.iterator(); iter.hasNext(); ) {
if(needsSep2) {
buf.append(sep2); // diff-name seperator
}
- int num2 = addExtensionListOfAliasedSymbols2Buffer(glInfo, buf, sep1, sep2, iter.next(), col);
+ final int num2 = addExtensionListOfAliasedSymbols2Buffer(glInfo, buf, sep1, sep2, iter.next(), col);
needsSep2 = num<num2;
num += num2;
}
@@ -431,12 +447,12 @@ public class GLEmitter extends ProcAddressEmitter {
// Internals only below this point
//
@Override
- protected void generateModifiedEmitters(JavaMethodBindingEmitter baseJavaEmitter, List<FunctionEmitter> emitters) {
- List<FunctionEmitter> superEmitters = new ArrayList<FunctionEmitter>();
+ protected void generateModifiedEmitters(final JavaMethodBindingEmitter baseJavaEmitter, final List<FunctionEmitter> emitters) {
+ final List<FunctionEmitter> superEmitters = new ArrayList<FunctionEmitter>();
super.generateModifiedEmitters(baseJavaEmitter, superEmitters);
// See whether this is one of the Buffer Object variants
- boolean bufferObjectVariant = bufferObjectMethodBindings.containsKey(baseJavaEmitter.getBinding());
+ final boolean bufferObjectVariant = bufferObjectMethodBindings.containsKey(baseJavaEmitter.getBinding());
for (FunctionEmitter emitter : superEmitters) {
if (emitter instanceof ProcAddressJavaMethodBindingEmitter) {
@@ -446,7 +462,7 @@ public class GLEmitter extends ProcAddressEmitter {
}
}
- protected boolean needsBufferObjectVariant(FunctionSymbol sym) {
+ protected boolean needsBufferObjectVariant(final FunctionSymbol sym) {
return getGLConfig().isBufferObjectFunction(sym.getName());
}
@@ -454,34 +470,69 @@ public class GLEmitter extends ProcAddressEmitter {
return (GLConfiguration) getConfig();
}
+ /**
+ * {@inheritDoc}
+ */
@Override
protected void endProcAddressTable() throws Exception {
- PrintWriter w = tableWriter;
-
- w.println(" /**");
- w.println(" * This is a convenience method to get (by name) the native function");
- w.println(" * pointer for a given function. It lets you avoid having to");
- w.println(" * manually compute the &quot;" + PROCADDRESS_VAR_PREFIX + " + ");
- w.println(" * &lt;functionName&gt;&quot; member variable name and look it up via");
- w.println(" * reflection; it also will throw an exception if you try to get the");
- w.println(" * address of an unknown function, or one that is statically linked");
- w.println(" * and therefore does not have a function pointer in this table.");
- w.println(" *");
- w.println(" * @throws RuntimeException if the function pointer was not found in");
- w.println(" * this table, either because the function was unknown or because");
- w.println(" * it was statically linked.");
- w.println(" */");
- w.println(" public long getAddressFor(String functionNameUsr) {");
- w.println(" String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
- w.println(" String addressFieldNameBase = PROCADDRESS_VAR_PREFIX + functionNameBase;");
- w.println(" java.lang.reflect.Field addressField = null;");
- w.println(" int funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
- w.println(" for(int i = 0; null==addressField && i < funcNamePermNum; i++) {");
- w.println(" String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
- w.println(" try {");
- w.println(" addressField = getClass().getField(addressFieldName);");
- w.println(" } catch (Exception e) { }");
+ final PrintWriter w = tableWriter;
+
+ w.println(" @Override");
+ w.println(" protected boolean isFunctionAvailableImpl(String functionNameUsr) throws IllegalArgumentException {");
+ w.println(" final String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
+ w.println(" final String addressFieldNameBase = \"" + PROCADDRESS_VAR_PREFIX + "\" + functionNameBase;");
+ w.println(" final int funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
+ w.println(" final java.lang.reflect.Field addressField = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<java.lang.reflect.Field>() {");
+ w.println(" public final java.lang.reflect.Field run() {");
+ w.println(" java.lang.reflect.Field addressField = null;");
+ w.println(" for(int i = 0; i < funcNamePermNum; i++) {");
+ w.println(" final String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
+ w.println(" try {");
+ w.println(" addressField = "+tableClassName+".class.getDeclaredField( addressFieldName );");
+ w.println(" addressField.setAccessible(true); // we need to read the protected value!");
+ w.println(" return addressField;");
+ w.println(" } catch (NoSuchFieldException ex) { }");
+ w.println(" }");
+ w.println(" return null;");
+ w.println(" } } );");
+ w.println();
+ w.println(" if(null==addressField) {");
+ w.println(" // The user is calling a bogus function or one which is not");
+ w.println(" // runtime linked");
+ w.println(" throw new RuntimeException(");
+ w.println(" \"WARNING: Address field query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
+ w.println(" \"\\\"; it's either statically linked or address field is not a known \" +");
+ w.println(" \"function\");");
+ w.println(" } ");
+ w.println(" try {");
+ w.println(" return 0 != addressField.getLong(this);");
+ w.println(" } catch (Exception e) {");
+ w.println(" throw new RuntimeException(");
+ w.println(" \"WARNING: Address query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
+ w.println(" \"\\\"; it's either statically linked or is not a known \" +");
+ w.println(" \"function\", e);");
w.println(" }");
+ w.println(" }");
+
+ w.println(" @Override");
+ w.println(" public long getAddressFor(String functionNameUsr) throws SecurityException, IllegalArgumentException {");
+ w.println(" SecurityUtil.checkAllLinkPermission();");
+ w.println(" final String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
+ w.println(" final String addressFieldNameBase = \"" + PROCADDRESS_VAR_PREFIX + "\" + functionNameBase;");
+ w.println(" final int funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
+ w.println(" final java.lang.reflect.Field addressField = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<java.lang.reflect.Field>() {");
+ w.println(" public final java.lang.reflect.Field run() {");
+ w.println(" java.lang.reflect.Field addressField = null;");
+ w.println(" for(int i = 0; i < funcNamePermNum; i++) {");
+ w.println(" final String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
+ w.println(" try {");
+ w.println(" addressField = "+tableClassName+".class.getDeclaredField( addressFieldName );");
+ w.println(" addressField.setAccessible(true); // we need to read the protected value!");
+ w.println(" return addressField;");
+ w.println(" } catch (NoSuchFieldException ex) { }");
+ w.println(" }");
+ w.println(" return null;");
+ w.println(" } } );");
w.println();
w.println(" if(null==addressField) {");
w.println(" // The user is calling a bogus function or one which is not");
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java
index 016674338..d491a3712 100755..100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -43,6 +43,7 @@ import com.jogamp.gluegen.CommentEmitter;
import com.jogamp.gluegen.JavaEmitter;
import com.jogamp.gluegen.JavaMethodBindingEmitter;
import com.jogamp.gluegen.MethodBinding;
+import com.jogamp.gluegen.cgram.types.FunctionSymbol;
import com.jogamp.gluegen.cgram.types.Type;
import com.jogamp.gluegen.procaddress.ProcAddressJavaMethodBindingEmitter;
@@ -57,8 +58,8 @@ public class GLJavaMethodBindingEmitter extends ProcAddressJavaMethodBindingEmit
protected GLEmitter glEmitter;
protected CommentEmitter glCommentEmitter = new GLCommentEmitter();
- public GLJavaMethodBindingEmitter(JavaMethodBindingEmitter methodToWrap, boolean callThroughProcAddress,
- String getProcAddressTableExpr, boolean changeNameAndArguments, boolean bufferObjectVariant, GLEmitter emitter) {
+ public GLJavaMethodBindingEmitter(final JavaMethodBindingEmitter methodToWrap, final boolean callThroughProcAddress,
+ final String getProcAddressTableExpr, final boolean changeNameAndArguments, final boolean bufferObjectVariant, final GLEmitter emitter) {
super(methodToWrap, callThroughProcAddress, getProcAddressTableExpr, changeNameAndArguments, emitter);
this.bufferObjectVariant = bufferObjectVariant;
@@ -66,20 +67,20 @@ public class GLJavaMethodBindingEmitter extends ProcAddressJavaMethodBindingEmit
setCommentEmitter(glCommentEmitter);
}
- public GLJavaMethodBindingEmitter(ProcAddressJavaMethodBindingEmitter methodToWrap, GLEmitter emitter, boolean bufferObjectVariant) {
+ public GLJavaMethodBindingEmitter(final ProcAddressJavaMethodBindingEmitter methodToWrap, final GLEmitter emitter, final boolean bufferObjectVariant) {
super(methodToWrap);
this.bufferObjectVariant = bufferObjectVariant;
this.glEmitter = emitter;
setCommentEmitter(glCommentEmitter);
}
- public GLJavaMethodBindingEmitter(GLJavaMethodBindingEmitter methodToWrap) {
+ public GLJavaMethodBindingEmitter(final GLJavaMethodBindingEmitter methodToWrap) {
this(methodToWrap, methodToWrap.glEmitter, methodToWrap.bufferObjectVariant);
}
@Override
- protected String getArgumentName(int i) {
- String name = super.getArgumentName(i);
+ protected String getArgumentName(final int i) {
+ final String name = super.getArgumentName(i);
if (!bufferObjectVariant) {
return name;
@@ -88,8 +89,8 @@ public class GLJavaMethodBindingEmitter extends ProcAddressJavaMethodBindingEmit
// Emitters for VBO/PBO-related routines change the outgoing
// argument name for the buffer
if (binding.getJavaArgumentType(i).isLong()) {
- Type cType = binding.getCArgumentType(i);
- Type targetType = cType.asPointer().getTargetType();
+ final Type cType = binding.getCArgumentType(i);
+ final Type targetType = cType.asPointer().getTargetType();
if (cType.isPointer() && (targetType.isVoid() || targetType.isPrimitive())) {
return name + "_buffer_offset";
}
@@ -101,21 +102,24 @@ public class GLJavaMethodBindingEmitter extends ProcAddressJavaMethodBindingEmit
protected class GLCommentEmitter extends JavaMethodBindingEmitter.DefaultCommentEmitter {
@Override
- protected void emitBindingCSignature(MethodBinding binding, PrintWriter writer) {
+ protected void emitBindingCSignature(final MethodBinding binding, final PrintWriter writer) {
- super.emitBindingCSignature(binding, writer);
+ final String symbolRenamed = binding.getName();
+ final StringBuilder newComment = new StringBuilder();
- String symbolRenamed = binding.getName();
- StringBuilder newComment = new StringBuilder();
+ final FunctionSymbol funcSym = binding.getCSymbol();
+ writer.print("<code> ");
+ writer.print(funcSym.getType().toString(symbolRenamed, tagNativeBinding));
+ writer.print(" </code> ");
newComment.append("<br>Part of ");
if (0 == glEmitter.addExtensionsOfSymbols2Buffer(newComment, ", ", "; ", symbolRenamed, binding.getAliasedNames())) {
if (glEmitter.getGLConfig().getAllowNonGLExtensions()) {
newComment.append("CORE FUNC");
} else {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
JavaEmitter.addStrings2Buffer(sb, ", ", symbolRenamed, binding.getAliasedNames());
- RuntimeException ex = new RuntimeException("Couldn't find extension to: " + binding + " ; " + sb.toString());
+ final RuntimeException ex = new RuntimeException("Couldn't find extension to: " + binding + " ; " + sb.toString());
glEmitter.getGLConfig().getGLInfo().dump();
// glEmitter.getGLConfig().dumpRenames();
throw ex;
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/ant/StaticGLGenTask.java b/src/jogl/classes/com/jogamp/gluegen/opengl/ant/StaticGLGenTask.java
index e3e7cb970..66819a83e 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/ant/StaticGLGenTask.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/ant/StaticGLGenTask.java
@@ -55,13 +55,13 @@ import org.apache.tools.ant.util.JavaEnvUtils;
/**
* <p>An <a href="http://ant.apache.org">ANT</a> {@link org.apache.tools.ant.Task}
* for using {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo}.</p>
- *
+ *
* <p>Usage:</p>
* <pre>
- &lt;staticglgen package="[generated files package]"
+ &lt;staticglgen package="[generated files package]"
headers="[file pattern of GL headers]"
outputdir="[directory to output the generated files]" /&gt;
- * </pre>
+ * </pre>
*
* @author Rob Grzywinski <a href="mailto:[email protected]">[email protected]</a>
*/
@@ -72,13 +72,13 @@ public class StaticGLGenTask extends Task
* <p>The {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo} classname.</p>
*/
private static final String GL_GEN = "com.jogamp.gluegen.opengl.BuildStaticGLInfo";
-
+
// =========================================================================
/**
* <p>The {@link org.apache.tools.ant.types.CommandlineJava} that is used
* to execute {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo}.</p>
*/
- private CommandlineJava glgenCommandline;
+ private final CommandlineJava glgenCommandline;
// =========================================================================
/**
@@ -90,12 +90,12 @@ public class StaticGLGenTask extends Task
* <p>The output directory.</p>
*/
private String outputDirectory;
-
+
/**
* <p>The {@link org.apache.tools.ant.types.FileSet} of GL headers.</p>
*/
- private FileSet headerSet = new FileSet();
-
+ private final FileSet headerSet = new FileSet();
+
// =========================================================================
/**
* <p>Create and add the VM and classname to {@link org.apache.tools.ant.types.CommandlineJava}.</p>
@@ -104,7 +104,7 @@ public class StaticGLGenTask extends Task
{
// create the CommandlineJava that will be used to call BuildStaticGLInfo
glgenCommandline = new CommandlineJava();
-
+
// set the VM and classname in the commandline
glgenCommandline.setVm(JavaEnvUtils.getJreExecutable("java"));
glgenCommandline.setClassname(GL_GEN);
@@ -114,10 +114,10 @@ public class StaticGLGenTask extends Task
// ANT getters and setters
/**
* <p>Set the package name for the generated files. This is called by ANT.</p>
- *
+ *
* @param packageName the name of the package for the generated files
*/
- public void setPackage(String packageName)
+ public void setPackage(final String packageName)
{
log( ("Setting package name to: " + packageName), Project.MSG_VERBOSE);
this.packageName = packageName;
@@ -125,12 +125,12 @@ public class StaticGLGenTask extends Task
/**
* <p>Set the output directory. This is called by ANT.</p>
- *
+ *
* @param directory the output directory
*/
- public void setOutputDir(String directory)
+ public void setOutputDir(final String directory)
{
- log( ("Setting output directory to: " + directory),
+ log( ("Setting output directory to: " + directory),
Project.MSG_VERBOSE);
this.outputDirectory = directory;
}
@@ -138,7 +138,7 @@ public class StaticGLGenTask extends Task
/**
* <p>Add a header file to the list. This is called by ANT for a nested
* element.</p>
- *
+ *
* @return {@link org.apache.tools.ant.types.PatternSet.NameEntry}
*/
public PatternSet.NameEntry createHeader()
@@ -149,7 +149,7 @@ public class StaticGLGenTask extends Task
/**
* <p>Add a header file to the list. This is called by ANT for a nested
* element.</p>
- *
+ *
* @return {@link org.apache.tools.ant.types.PatternSet.NameEntry}
*/
public PatternSet.NameEntry createHeadersFile()
@@ -163,7 +163,7 @@ public class StaticGLGenTask extends Task
*
* @param headers the string containing the header patterns
*/
- public void setHeaders(String headers)
+ public void setHeaders(final String headers)
{
headerSet.setIncludes(headers);
}
@@ -171,7 +171,7 @@ public class StaticGLGenTask extends Task
/**
* <p>Add an optional classpath that defines the location of {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo}
* and <code>BuildStaticGLInfo</code>'s dependencies.</p>
- *
+ *
* @returns {@link org.apache.tools.ant.types.Path}
*/
public Path createClasspath()
@@ -183,23 +183,24 @@ public class StaticGLGenTask extends Task
/**
* <p>Run the task. This involves validating the set attributes, creating
* the command line to be executed and finally executing the command.</p>
- *
+ *
* @see org.apache.tools.ant.Task#execute()
*/
- public void execute()
- throws BuildException
+ @Override
+ public void execute()
+ throws BuildException
{
// validate that all of the required attributes have been set
validateAttributes();
-
+
// TODO: add logic to determine if the generated file needs to be
// regenerated
-
+
// add the attributes to the CommandlineJava
addAttributes();
log(glgenCommandline.describeCommand(), Project.MSG_VERBOSE);
-
+
// execute the command and throw on error
final int error = execute(glgenCommandline.getCommandline());
if(error == 1)
@@ -208,11 +209,11 @@ public class StaticGLGenTask extends Task
/**
* <p>Ensure that the user specified all required arguments.</p>
- *
- * @throws BuildException if there are required arguments that are not
+ *
+ * @throws BuildException if there are required arguments that are not
* present or not valid
*/
- private void validateAttributes()
+ private void validateAttributes()
throws BuildException
{
// validate that the package name is set
@@ -223,29 +224,29 @@ public class StaticGLGenTask extends Task
// TODO: switch to file and ensure that it exists
if(!isValid(outputDirectory))
throw new BuildException("Invalid output directory name: " + outputDirectory);
-
+
// TODO: validate that there are headers set
}
/**
* <p>Is the specified string valid? A valid string is non-<code>null</code>
* and has a non-zero length.</p>
- *
+ *
* @param string the string to be tested for validity
* @return <code>true</code> if the string is valid. <code>false</code>
- * otherwise.
+ * otherwise.
*/
- private boolean isValid(String string)
+ private boolean isValid(final String string)
{
// check for null
if(string == null)
return false;
-
+
// ensure that the string has a non-zero length
// NOTE: must trim() to remove leading and trailing whitespace
if(string.trim().length() < 1)
return false;
-
+
// the string is valid
return true;
}
@@ -258,44 +259,44 @@ public class StaticGLGenTask extends Task
{
// add the package name
glgenCommandline.createArgument().setValue(packageName);
-
+
// add the output directory name
glgenCommandline.createArgument().setValue(outputDirectory);
-
+
// add the header -files- from the FileSet
headerSet.setDir(getProject().getBaseDir());
- DirectoryScanner directoryScanner = headerSet.getDirectoryScanner(getProject());
- String[] directoryFiles = directoryScanner.getIncludedFiles();
+ final DirectoryScanner directoryScanner = headerSet.getDirectoryScanner(getProject());
+ final String[] directoryFiles = directoryScanner.getIncludedFiles();
for(int i=0; i<directoryFiles.length; i++)
{
glgenCommandline.createArgument().setValue(directoryFiles[i]);
}
}
- /**
- * <p>Execute {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo} in a
+ /**
+ * <p>Execute {@link com.jogamp.gluegen.opengl.BuildStaticGLInfo} in a
* forked JVM.</p>
- *
+ *
* @throws BuildException
*/
- private int execute(String[] command)
+ private int execute(final String[] command)
throws BuildException
{
// create the object that will perform the command execution
- Execute execute = new Execute(new LogStreamHandler(this, Project.MSG_INFO,
- Project.MSG_WARN),
+ final Execute execute = new Execute(new LogStreamHandler(this, Project.MSG_INFO,
+ Project.MSG_WARN),
null);
-
+
// set the project and command line
execute.setAntRun(project);
execute.setCommandline(command);
execute.setWorkingDirectory( project.getBaseDir() );
-
+
// execute the command
try
{
return execute.execute();
- } catch(IOException ioe)
+ } catch(final IOException ioe)
{
throw new BuildException(ioe, location);
}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java
index adb1c2ae0..de9e3ed25 100755..100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -55,20 +55,20 @@ import java.util.Set;
/**
* Emitter producing NativeSignature attributes.
- *
- * Review: This Package/Class is not used and subject to be deleted.
+ *
+ * Review: This Package/Class is not used and subject to be deleted.
*/
public class NativeSignatureEmitter extends GLEmitter {
@Override
- protected List<? extends FunctionEmitter> generateMethodBindingEmitters(Set<MethodBinding> methodBindingSet, FunctionSymbol sym) throws Exception {
+ protected List<? extends FunctionEmitter> generateMethodBindingEmitters(final Set<MethodBinding> methodBindingSet, final FunctionSymbol sym) throws Exception {
// Allow superclass to do most of the work for us
- List<? extends FunctionEmitter> res = super.generateMethodBindingEmitters(methodBindingSet, sym);
+ final List<? extends FunctionEmitter> res = super.generateMethodBindingEmitters(methodBindingSet, sym);
// Filter out all non-JavaMethodBindingEmitters
- for (Iterator<? extends FunctionEmitter> iter = res.iterator(); iter.hasNext();) {
- FunctionEmitter emitter = iter.next();
+ for (final Iterator<? extends FunctionEmitter> iter = res.iterator(); iter.hasNext();) {
+ final FunctionEmitter emitter = iter.next();
if (!(emitter instanceof JavaMethodBindingEmitter)) {
iter.remove();
}
@@ -78,13 +78,13 @@ public class NativeSignatureEmitter extends GLEmitter {
return res;
}
- PrintWriter writer = (getConfig().allStatic() ? javaWriter() : javaImplWriter());
+ final PrintWriter writer = (getConfig().allStatic() ? javaWriter() : javaImplWriter());
- List<FunctionEmitter> processed = new ArrayList<FunctionEmitter>();
+ final List<FunctionEmitter> processed = new ArrayList<FunctionEmitter>();
// First, filter out all emitters going to the "other" (public) writer
- for (Iterator<? extends FunctionEmitter> iter = res.iterator(); iter.hasNext();) {
- FunctionEmitter emitter = iter.next();
+ for (final Iterator<? extends FunctionEmitter> iter = res.iterator(); iter.hasNext();) {
+ final FunctionEmitter emitter = iter.next();
if (emitter.getDefaultOutput() != writer) {
processed.add(emitter);
iter.remove();
@@ -93,12 +93,12 @@ public class NativeSignatureEmitter extends GLEmitter {
// Now process all of the remaining emitters sorted by MethodBinding
while (!res.isEmpty()) {
- List<JavaMethodBindingEmitter> emittersForBinding = new ArrayList<JavaMethodBindingEmitter>();
- JavaMethodBindingEmitter emitter = (JavaMethodBindingEmitter) res.remove(0);
+ final List<JavaMethodBindingEmitter> emittersForBinding = new ArrayList<JavaMethodBindingEmitter>();
+ final JavaMethodBindingEmitter emitter = (JavaMethodBindingEmitter) res.remove(0);
emittersForBinding.add(emitter);
- MethodBinding binding = emitter.getBinding();
- for (Iterator<? extends FunctionEmitter> iter = res.iterator(); iter.hasNext();) {
- JavaMethodBindingEmitter emitter2 = (JavaMethodBindingEmitter) iter.next();
+ final MethodBinding binding = emitter.getBinding();
+ for (final Iterator<? extends FunctionEmitter> iter = res.iterator(); iter.hasNext();) {
+ final JavaMethodBindingEmitter emitter2 = (JavaMethodBindingEmitter) iter.next();
if (emitter2.getBinding() == binding) {
emittersForBinding.add(emitter2);
iter.remove();
@@ -111,17 +111,17 @@ public class NativeSignatureEmitter extends GLEmitter {
return processed;
}
- protected void generateNativeSignatureEmitters(MethodBinding binding, List<JavaMethodBindingEmitter> allEmitters) {
+ protected void generateNativeSignatureEmitters(final MethodBinding binding, final List<JavaMethodBindingEmitter> allEmitters) {
if (allEmitters.isEmpty()) {
return;
}
- PrintWriter writer = (getConfig().allStatic() ? javaWriter() : javaImplWriter());
+ final PrintWriter writer = (getConfig().allStatic() ? javaWriter() : javaImplWriter());
// Give ourselves the chance to interpose on the generation of all code to keep things simple
- List<JavaMethodBindingEmitter> newEmitters = new ArrayList<JavaMethodBindingEmitter>();
- for (JavaMethodBindingEmitter javaEmitter : allEmitters) {
+ final List<JavaMethodBindingEmitter> newEmitters = new ArrayList<JavaMethodBindingEmitter>();
+ for (final JavaMethodBindingEmitter javaEmitter : allEmitters) {
NativeSignatureJavaMethodBindingEmitter newEmitter = null;
if (javaEmitter instanceof GLJavaMethodBindingEmitter) {
newEmitter = new NativeSignatureJavaMethodBindingEmitter((GLJavaMethodBindingEmitter) javaEmitter);
@@ -138,11 +138,11 @@ public class NativeSignatureEmitter extends GLEmitter {
// been called with signatureOnly both true and false.
if (signatureContainsStrings(binding) && !haveEmitterWithBody(allEmitters)) {
// This basically handles glGetString but also any similar methods
- NativeSignatureJavaMethodBindingEmitter javaEmitter = findEmitterWithWriter(allEmitters, writer);
+ final NativeSignatureJavaMethodBindingEmitter javaEmitter = findEmitterWithWriter(allEmitters, writer);
// First, we need to clone this emitter to produce the native
// entry point
- NativeSignatureJavaMethodBindingEmitter emitter = new NativeSignatureJavaMethodBindingEmitter(javaEmitter);
+ final NativeSignatureJavaMethodBindingEmitter emitter = new NativeSignatureJavaMethodBindingEmitter(javaEmitter);
emitter.removeModifier(JavaMethodBindingEmitter.PUBLIC);
emitter.addModifier(JavaMethodBindingEmitter.PRIVATE);
emitter.setForImplementingMethodCall(true);
@@ -158,22 +158,22 @@ public class NativeSignatureEmitter extends GLEmitter {
}
}
- protected boolean signatureContainsStrings(MethodBinding binding) {
+ protected boolean signatureContainsStrings(final MethodBinding binding) {
for (int i = 0; i < binding.getNumArguments(); i++) {
- JavaType type = binding.getJavaArgumentType(i);
+ final JavaType type = binding.getJavaArgumentType(i);
if (type.isString() || type.isStringArray()) {
return true;
}
}
- JavaType retType = binding.getJavaReturnType();
+ final JavaType retType = binding.getJavaReturnType();
if (retType.isString() || retType.isStringArray()) {
return true;
}
return false;
}
- protected boolean haveEmitterWithBody(List<JavaMethodBindingEmitter> allEmitters) {
- for (JavaMethodBindingEmitter emitter : allEmitters) {
+ protected boolean haveEmitterWithBody(final List<JavaMethodBindingEmitter> allEmitters) {
+ for (final JavaMethodBindingEmitter emitter : allEmitters) {
if (!emitter.signatureOnly()) {
return true;
}
@@ -181,9 +181,9 @@ public class NativeSignatureEmitter extends GLEmitter {
return false;
}
- protected NativeSignatureJavaMethodBindingEmitter findEmitterWithWriter(List<JavaMethodBindingEmitter> allEmitters, PrintWriter writer) {
- for (JavaMethodBindingEmitter jemitter : allEmitters) {
- NativeSignatureJavaMethodBindingEmitter emitter = (NativeSignatureJavaMethodBindingEmitter)jemitter;
+ protected NativeSignatureJavaMethodBindingEmitter findEmitterWithWriter(final List<JavaMethodBindingEmitter> allEmitters, final PrintWriter writer) {
+ for (final JavaMethodBindingEmitter jemitter : allEmitters) {
+ final NativeSignatureJavaMethodBindingEmitter emitter = (NativeSignatureJavaMethodBindingEmitter)jemitter;
if (emitter.getDefaultOutput() == writer) {
return emitter;
}
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java
index e98478b6e..86080d84f 100755..100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -53,31 +53,31 @@ import java.io.PrintWriter;
/** Review: This Package/Class is not used and subject to be deleted. */
public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBindingEmitter {
- public NativeSignatureJavaMethodBindingEmitter(GLJavaMethodBindingEmitter methodToWrap) {
+ public NativeSignatureJavaMethodBindingEmitter(final GLJavaMethodBindingEmitter methodToWrap) {
super(methodToWrap);
}
- public NativeSignatureJavaMethodBindingEmitter(ProcAddressJavaMethodBindingEmitter methodToWrap, GLEmitter emitter, boolean bufferObjectVariant) {
+ public NativeSignatureJavaMethodBindingEmitter(final ProcAddressJavaMethodBindingEmitter methodToWrap, final GLEmitter emitter, final boolean bufferObjectVariant) {
super(methodToWrap, emitter, bufferObjectVariant);
}
- public NativeSignatureJavaMethodBindingEmitter(JavaMethodBindingEmitter methodToWrap, NativeSignatureEmitter emitter) {
+ public NativeSignatureJavaMethodBindingEmitter(final JavaMethodBindingEmitter methodToWrap, final NativeSignatureEmitter emitter) {
super(methodToWrap, false, null, false, false, emitter);
}
@Override
- protected void emitSignature(PrintWriter writer) {
+ protected void emitSignature(final PrintWriter writer) {
writer.print(getBaseIndentString());
emitNativeSignatureAnnotation(writer);
super.emitSignature(writer);
}
- protected void emitNativeSignatureAnnotation(PrintWriter writer) {
+ protected void emitNativeSignatureAnnotation(final PrintWriter writer) {
if (hasModifier(JavaMethodBindingEmitter.NATIVE)) {
// Emit everything as a leaf for now
// FIXME: make this configurable
writer.print("@NativeSignature(\"l");
- MethodBinding binding = getBinding();
+ final MethodBinding binding = getBinding();
if (callThroughProcAddress) {
writer.print("p");
}
@@ -94,7 +94,7 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
}
}
- protected void emitNativeSignatureElement(PrintWriter writer, JavaType type, Type cType, int index) {
+ protected void emitNativeSignatureElement(final PrintWriter writer, final JavaType type, final Type cType, final int index) {
if (type.isVoid()) {
if (index > 0) {
throw new InternalError("Error parsing arguments -- void should not be seen aside from argument 0");
@@ -107,7 +107,7 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
} else if (type.isPrimitiveArray()) {
writer.print("MO");
} else if (type.isPrimitive()) {
- Class<?> clazz = type.getJavaClass();
+ final Class<?> clazz = type.getJavaClass();
if (clazz == Byte.TYPE) { writer.print("B"); }
else if (clazz == Character.TYPE) { writer.print("C"); }
else if (clazz == Double.TYPE) { writer.print("D"); }
@@ -131,9 +131,10 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
}
}
- protected String getReturnTypeString(boolean skipArray) {
+ @Override
+ protected String getReturnTypeString(final boolean skipArray) {
if (isForImplementingMethodCall()) {
- JavaType returnType = getBinding().getJavaReturnType();
+ final JavaType returnType = getBinding().getJavaReturnType();
if (returnType.isString() || returnType.isNIOByteBuffer()) {
// Treat these as addresses
return "long";
@@ -142,10 +143,11 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
return super.getReturnTypeString(skipArray);
}
- protected void emitPreCallSetup(MethodBinding binding, PrintWriter writer) {
+ @Override
+ protected void emitPreCallSetup(final MethodBinding binding, final PrintWriter writer) {
super.emitPreCallSetup(binding, writer);
for (int i = 0; i < binding.getNumArguments(); i++) {
- JavaType type = binding.getJavaArgumentType(i);
+ final JavaType type = binding.getJavaArgumentType(i);
if (type.isNIOBuffer() && !useNIODirectOnly ) {
// Emit declarations for variables holding primitive arrays as type Object
// We don't know 100% sure we're going to use these at this point in the code, though
@@ -158,11 +160,12 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
}
}
- protected String getNIOBufferArrayName(int argNumber) {
+ protected String getNIOBufferArrayName(final int argNumber) {
return "__buffer_array_" + argNumber;
}
- protected int emitArguments(PrintWriter writer)
+ @Override
+ protected int emitArguments(final PrintWriter writer)
{
boolean needComma = false;
int numEmitted = 0;
@@ -182,14 +185,14 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
// Always emit outgoing "this" argument
writer.print("long ");
- writer.print(javaThisArgumentName());
+ writer.print(javaThisArgumentName());
++numEmitted;
needComma = true;
}
for (int i = 0; i < binding.getNumArguments(); i++) {
- JavaType type = binding.getJavaArgumentType(i);
- if (type.isVoid()) {
+ final JavaType type = binding.getJavaArgumentType(i);
+ if (type.isVoid()) {
// Make sure this is the only param to the method; if it isn't,
// there's something wrong with our parsing of the headers.
if (binding.getNumArguments() != 1) {
@@ -198,7 +201,7 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
"multi-argument function \"" + binding + "\"");
}
continue;
- }
+ }
if (type.isJNIEnv() || binding.isArgumentThisPointer(i)) {
// Don't need to expose these at the Java level
@@ -229,7 +232,7 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
if (type.isNIOBuffer()) {
writer.print(", int " + byteOffsetArgName(i));
} else if (type.isNIOBufferArray()) {
- writer.print(", int[] " +
+ writer.print(", int[] " +
byteOffsetArrayArgName(i));
}
}
@@ -242,11 +245,12 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
return numEmitted;
}
- protected void emitReturnVariableSetupAndCall(MethodBinding binding, PrintWriter writer) {
+ @Override
+ protected void emitReturnVariableSetupAndCall(final MethodBinding binding, final PrintWriter writer) {
writer.print(" ");
- JavaType returnType = binding.getJavaReturnType();
+ final JavaType returnType = binding.getJavaReturnType();
boolean needsResultAssignment = false;
-
+
if (!returnType.isVoid()) {
if (returnType.isCompoundTypeWrapper() ||
returnType.isNIOByteBuffer()) {
@@ -340,7 +344,7 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
}
}
- protected int emitCallArguments(MethodBinding binding, PrintWriter writer, boolean direct) {
+ protected int emitCallArguments(final MethodBinding binding, final PrintWriter writer, final boolean direct) {
// Note that we override this completely because we both need to
// move the potential location of the outgoing proc address as
// well as change the way we pass out Buffers, arrays, Strings, etc.
@@ -364,7 +368,7 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
++numArgsEmitted;
}
for (int i = 0; i < binding.getNumArguments(); i++) {
- JavaType type = binding.getJavaArgumentType(i);
+ final JavaType type = binding.getJavaArgumentType(i);
if (type.isJNIEnv() || binding.isArgumentThisPointer(i)) {
// Don't need to expose these at the Java level
continue;
@@ -375,7 +379,7 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
// there's something wrong with our parsing of the headers.
assert(binding.getNumArguments() == 1);
continue;
- }
+ }
if (needComma) {
writer.print(", ");
@@ -455,9 +459,10 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
return numArgsEmitted;
}
- protected void emitCallResultReturn(MethodBinding binding, PrintWriter writer) {
+ @Override
+ protected void emitCallResultReturn(final MethodBinding binding, final PrintWriter writer) {
for (int i = 0; i < binding.getNumArguments(); i++) {
- JavaType type = binding.getJavaArgumentType(i);
+ final JavaType type = binding.getJavaArgumentType(i);
if (type.isString()) {
writer.println(";");
writer.println(" BuffersInternal.freeCString(" + binding.getArgumentName(i) + "_c_str);");
@@ -468,15 +473,16 @@ public class NativeSignatureJavaMethodBindingEmitter extends GLJavaMethodBinding
super.emitCallResultReturn(binding, writer);
}
+ @Override
public String getName() {
- String res = super.getName();
+ final String res = super.getName();
if (forImplementingMethodCall && bufferObjectVariant) {
return res + "BufObj";
}
return res;
}
- protected String getImplMethodName(boolean direct) {
+ protected String getImplMethodName(final boolean direct) {
String name = null;
if (direct) {
name = binding.getName() + "$0";
diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java
index 92554776a..d400381c8 100644
--- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java
+++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
*/
package com.jogamp.gluegen.runtime.opengl;
@@ -43,48 +43,48 @@ public class GLNameResolver {
//GL_XYZ : GL_XYZ, GL_GL2_XYZ, GL_ARB_XYZ, GL_OES_XYZ, GL_OML_XYZ
//
// Pass-1 Unify ARB extensions with the same value
- // Pass-2 Unify vendor extensions,
+ // Pass-2 Unify vendor extensions,
// if exist as an ARB extension with the same value.
// Pass-3 Emit
- public static final String[] extensionsARB = { "ARB", "GL2", "OES", "KHR", "OML" };
- public static final String[] extensionsVEN = { "3DFX",
- "AMD",
- "ANGLE",
- "ARM",
- "APPLE",
- "ATI",
- "EXT",
- "HI",
- "HP",
- "IBM",
- "IMG",
- "MESA",
- "MESAX",
- "NV",
- "QCOM",
- "SGI",
- "SGIS",
- "SGIX",
- "SUN",
- "VIV",
- "WIN"
- };
+ private static final String[] extensionsARB = { "ARB", "GL2", "OES", "KHR", "OML" };
+ private static final String[] extensionsVEN = { "3DFX",
+ "AMD",
+ "ANGLE",
+ "ARM",
+ "APPLE",
+ "ATI",
+ "EXT",
+ "HI",
+ "HP",
+ "IBM",
+ "IMG",
+ "MESA",
+ "MESAX",
+ "NV",
+ "QCOM",
+ "SGI",
+ "SGIS",
+ "SGIX",
+ "SUN",
+ "VIV",
+ "WIN"
+ };
- public static final boolean isGLFunction(String str) {
+ public static final boolean isGLFunction(final String str) {
return str.startsWith("gl") || /* str.startsWith("glu") || str.startsWith("glX") || */
str.startsWith("egl") || str.startsWith("wgl") || str.startsWith("agl") ||
str.startsWith("cgl") ;
}
- public static final boolean isGLEnumeration(String str) {
+ public static final boolean isGLEnumeration(final String str) {
return str.startsWith("GL_") || str.startsWith("GLU_") || str.startsWith("GLX_") ||
str.startsWith("EGL_") || str.startsWith("WGL_") || str.startsWith("AGL_") ||
str.startsWith("CGL_") ;
}
- public static final int getExtensionIdx(String[] extensions, String str, boolean isGLFunc) {
+ public static final int getExtensionIdx(final String[] extensions, final String str, final boolean isGLFunc) {
if(isGLFunc) {
for(int i = extensions.length - 1 ; i>=0 ; i--) {
if( str.endsWith(extensions[i]) ) {
@@ -101,11 +101,11 @@ public class GLNameResolver {
return -1;
}
- public static final boolean isExtension(String[] extensions, String str, boolean isGLFunc) {
+ public static final boolean isExtension(final String[] extensions, final String str, final boolean isGLFunc) {
return getExtensionIdx(extensions, str, isGLFunc)>=0;
}
- public static final String getExtensionSuffix(String str, boolean isGLFunc) {
+ public static final String getExtensionSuffix(final String str, final boolean isGLFunc) {
int idx = getExtensionIdx(extensionsARB, str, isGLFunc);
if(idx>=0) {
return extensionsARB[idx];
@@ -117,7 +117,7 @@ public class GLNameResolver {
return null;
}
- public static final String normalize(String[] extensions, String str, boolean isGLFunc) {
+ public static final String normalize(final String[] extensions, String str, final boolean isGLFunc) {
boolean touched = false;
for(int i = extensions.length - 1 ; !touched && i>=0 ; i--) {
if(isGLFunc) {
@@ -136,19 +136,19 @@ public class GLNameResolver {
}
return str;
}
- public static final String normalizeARB(String str, boolean isGLFunc) {
+ public static final String normalizeARB(final String str, final boolean isGLFunc) {
return normalize(extensionsARB, str, isGLFunc);
}
- public static final boolean isExtensionARB(String str, boolean isGLFunc) {
+ public static final boolean isExtensionARB(final String str, final boolean isGLFunc) {
return isExtension(extensionsARB, str, isGLFunc);
}
- public static final String normalizeVEN(String str, boolean isGLFunc) {
+ public static final String normalizeVEN(final String str, final boolean isGLFunc) {
return normalize(extensionsVEN, str, isGLFunc);
}
- public static final boolean isExtensionVEN(String str, boolean isGLFunc) {
+ public static final boolean isExtensionVEN(final String str, final boolean isGLFunc) {
return isExtension(extensionsVEN, str, isGLFunc);
}
- public static final String normalize(String str, boolean isGLFunc) {
+ public static final String normalize(final String str, final boolean isGLFunc) {
if (isExtensionARB(str, isGLFunc)) {
return normalizeARB(str, isGLFunc);
}
@@ -157,12 +157,12 @@ public class GLNameResolver {
}
return str;
}
- public static final boolean isExtension(String str, boolean isGLFunc) {
- return isExtension(extensionsARB, str, isGLFunc) ||
+ public static final boolean isExtension(final String str, final boolean isGLFunc) {
+ return isExtension(extensionsARB, str, isGLFunc) ||
isExtension(extensionsVEN, str, isGLFunc);
}
- public static final int getFuncNamePermutationNumber(String name) {
+ public static final int getFuncNamePermutationNumber(final String name) {
if(isExtensionARB(name, true) || isExtensionVEN(name, true)) {
// no name permutation, if it's already a known extension
return 1;
@@ -170,7 +170,7 @@ public class GLNameResolver {
return 1 + extensionsARB.length + extensionsVEN.length;
}
- public static final String getFuncNamePermutation(String name, int i) {
+ public static final String getFuncNamePermutation(final String name, int i) {
// identity
if(i==0) {
return name;
diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
index 9775de491..23d4fc3cf 100644
--- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
+++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
/*
* Created on Saturday, April 24 2010 16:44
*/
@@ -42,16 +42,17 @@ public class GLProcAddressResolver implements FunctionAddressResolver {
public static final boolean DEBUG = false;
- public long resolve(String name, DynamicLookupHelper lookup) {
+ @Override
+ public long resolve(final String name, final DynamicLookupHelper lookup) {
long newProcAddress = 0;
- int permutations = GLNameResolver.getFuncNamePermutationNumber(name);
+ final int permutations = GLNameResolver.getFuncNamePermutationNumber(name);
for (int i = 0; 0 == newProcAddress && i < permutations; i++) {
- String funcName = GLNameResolver.getFuncNamePermutation(name, i);
+ final String funcName = GLNameResolver.getFuncNamePermutation(name, i);
try {
newProcAddress = lookup.dynamicLookupFunction(funcName);
- } catch (Exception e) {
+ } catch (final Exception e) {
if (DEBUG) {
e.printStackTrace();
}
diff --git a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
index e60fba02b..bc500d87f 100755..100644
--- a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
@@ -29,26 +29,31 @@ package com.jogamp.graph.curve;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
+
+import jogamp.graph.geom.plane.AffineTransform;
import com.jogamp.graph.curve.tess.Triangulation;
import com.jogamp.graph.curve.tess.Triangulator;
-import com.jogamp.graph.geom.AABBox;
import com.jogamp.graph.geom.Outline;
import com.jogamp.graph.geom.Triangle;
import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.math.VectorUtil;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.math.geom.AABBox;
-/** A Generic shape objects which is defined by a list of Outlines.
- * This Shape can be transformed to Triangulations.
+/**
+ * A Generic shape objects which is defined by a list of Outlines.
+ * This Shape can be transformed to triangulations.
* The list of triangles generated are render-able by a Region object.
- * The triangulation produced by this Shape will define the
+ * The triangulation produced by this Shape will define the
* closed region defined by the outlines.
- *
+ *
* One or more OutlineShape Object can be associated to a region
* this is left as a high-level representation of the Objects. For
* optimizations, flexibility requirements for future features.
- *
+ *
* <br><br>
* Example to creating an Outline Shape:
* <pre>
@@ -60,18 +65,18 @@ import com.jogamp.graph.math.VectorUtil;
addVertex(...)
addVertex(...)
* </pre>
- *
- * The above will create two outlines each with three vertices. By adding these two outlines to
+ *
+ * The above will create two outlines each with three vertices. By adding these two outlines to
* the OutlineShape, we are stating that the combination of the two outlines represent the shape.
* <br>
- *
- * To specify that the shape is curved at a region, the on-curve flag should be set to false
+ *
+ * To specify that the shape is curved at a region, the on-curve flag should be set to false
* for the vertex that is in the middle of the curved region (if the curved region is defined by 3
* vertices (quadratic curve).
* <br>
- * In case the curved region is defined by 4 or more vertices the middle vertices should both have
+ * In case the curved region is defined by 4 or more vertices the middle vertices should both have
* the on-curve flag set to false.
- *
+ *
* <br>Example: <br>
* <pre>
addVertex(0,0, true);
@@ -79,16 +84,16 @@ import com.jogamp.graph.math.VectorUtil;
addVertex(1,1, false);
addVertex(1,0, true);
* </pre>
- *
- * The above snippet defines a cubic nurbs curve where (0,1 and 1,1)
+ *
+ * The above snippet defines a cubic nurbs curve where (0,1 and 1,1)
* do not belong to the final rendered shape.
- *
+ *
* <i>Implementation Notes:</i><br>
* <ul>
* <li> The first vertex of any outline belonging to the shape should be on-curve</li>
* <li> Intersections between off-curved parts of the outline is not handled</li>
* </ul>
- *
+ *
* @see Outline
* @see Region
*/
@@ -101,34 +106,80 @@ public class OutlineShape implements Comparable<OutlineShape> {
public final int state;
- VerticesState(int state){
+ VerticesState(final int state){
this.state = state;
}
- }
+ }
+
+ /** Initial {@link #getSharpness()} value, which can be modified via {@link #setSharpness(float)}. */
+ public static final float DEFAULT_SHARPNESS = 0.5f;
public static final int DIRTY_BOUNDS = 1 << 0;
+ /**
+ * Modified shape, requires to update the vertices and triangles, here: vertices.
+ */
+ public static final int DIRTY_VERTICES = 1 << 1;
+ /**
+ * Modified shape, requires to update the vertices and triangles, here: triangulation.
+ */
+ public static final int DIRTY_TRIANGLES = 1 << 2;
private final Vertex.Factory<? extends Vertex> vertexFactory;
- private VerticesState outlineState;
- /** The list of {@link Outline}s that are part of this
+ /** The list of {@link Outline}s that are part of this
* outline shape.
*/
- private ArrayList<Outline> outlines;
- private AABBox bbox;
+ /* pp */ final ArrayList<Outline> outlines;
+
+ private final AABBox bbox;
+ private final ArrayList<Triangle> triangles;
+ private final ArrayList<Vertex> vertices;
+ private int addedVerticeCount;
+
+ private VerticesState outlineState;
/** dirty bits DIRTY_BOUNDS */
- private int dirtyBits;
+ private int dirtyBits;
+
+ private float sharpness;
+
+ private final float[] tmpV1 = new float[3];
+ private final float[] tmpV2 = new float[3];
+ private final float[] tmpV3 = new float[3];
/** Create a new Outline based Shape
*/
- public OutlineShape(Vertex.Factory<? extends Vertex> factory) {
+ public OutlineShape(final Vertex.Factory<? extends Vertex> factory) {
this.vertexFactory = factory;
this.outlines = new ArrayList<Outline>(3);
this.outlines.add(new Outline());
this.outlineState = VerticesState.UNDEFINED;
this.bbox = new AABBox();
- this.dirtyBits = 0;
+ this.triangles = new ArrayList<Triangle>();
+ this.vertices = new ArrayList<Vertex>();
+ this.addedVerticeCount = 0;
+ this.dirtyBits = 0;
+ this.sharpness = DEFAULT_SHARPNESS;
+ }
+
+ /**
+ * Return the number of newly added vertices during {@link #getTriangles(VerticesState)}
+ * while transforming the outlines to {@link VerticesState#QUADRATIC_NURBS} and triangulation.
+ * @see #setIsQuadraticNurbs()
+ */
+ public int getAddedVerticeCount() {
+ return addedVerticeCount;
+ }
+
+ /** Sharpness value, defaults to {@link #DEFAULT_SHARPNESS}. */
+ public float getSharpness() { return sharpness; }
+
+ /** Sets sharpness, defaults to {@link #DEFAULT_SHARPNESS}. */
+ public void setSharpness(final float s) {
+ if( this.sharpness != s ) {
+ clearCache();
+ sharpness=s;
+ }
}
/** Clears all data and reset all states as if this instance was newly created */
@@ -137,56 +188,70 @@ public class OutlineShape implements Comparable<OutlineShape> {
outlines.add(new Outline());
outlineState = VerticesState.UNDEFINED;
bbox.reset();
- dirtyBits = 0;
+ vertices.clear();
+ triangles.clear();
+ addedVerticeCount = 0;
+ dirtyBits = 0;
}
- /** Returns the associated vertex factory of this outline shape
+ /** Clears cached triangulated data, i.e. {@link #getTriangles(VerticesState)} and {@link #getVertices()}. */
+ public void clearCache() {
+ vertices.clear();
+ triangles.clear();
+ dirtyBits |= DIRTY_TRIANGLES | DIRTY_VERTICES;
+ }
+
+ /**
+ * Returns the associated vertex factory of this outline shape
* @return Vertex.Factory object
*/
public final Vertex.Factory<? extends Vertex> vertexFactory() { return vertexFactory; }
- public int getOutlineNumber() {
+ public final int getOutlineNumber() {
return outlines.size();
}
- /** Add a new empty {@link Outline}
+ /**
+ * Add a new empty {@link Outline}
* to the end of this shape's outline list.
* <p>If the {@link #getLastOutline()} is empty already, no new one will be added.</p>
- *
+ *
* After a call to this function all new vertices added
* will belong to the new outline
*/
- public void addEmptyOutline() {
+ public final void addEmptyOutline() {
if( !getLastOutline().isEmpty() ) {
outlines.add(new Outline());
}
}
- /** Appends the {@link Outline} element to the end,
+ /**
+ * Appends the {@link Outline} element to the end,
* ensuring a clean tail.
- *
+ *
* <p>A clean tail is ensured, no double empty Outlines are produced
* and a pre-existing empty outline will be replaced with the given one. </p>
- *
+ *
* @param outline Outline object to be added
- * @throws NullPointerException if the {@link Outline} element is null
+ * @throws NullPointerException if the {@link Outline} element is null
*/
- public void addOutline(Outline outline) throws NullPointerException {
+ public final void addOutline(final Outline outline) throws NullPointerException {
addOutline(outlines.size(), outline);
}
- /** Insert the {@link Outline} element at the given {@code position}.
- *
+ /**
+ * Insert the {@link Outline} element at the given {@code position}.
+ *
* <p>If the {@code position} indicates the end of this list,
* a clean tail is ensured, no double empty Outlines are produced
* and a pre-existing empty outline will be replaced with the given one. </p>
- *
+ *
* @param position of the added Outline
* @param outline Outline object to be added
- * @throws NullPointerException if the {@link Outline} element is null
+ * @throws NullPointerException if the {@link Outline} element is null
* @throws IndexOutOfBoundsException if position is out of range (position < 0 || position > getOutlineNumber())
*/
- public void addOutline(int position, Outline outline) throws NullPointerException, IndexOutOfBoundsException {
+ public final void addOutline(final int position, final Outline outline) throws NullPointerException, IndexOutOfBoundsException {
if (null == outline) {
throw new NullPointerException("outline is null");
}
@@ -200,6 +265,8 @@ public class OutlineShape implements Comparable<OutlineShape> {
if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) {
bbox.resize(outline.getBounds());
}
+ // vertices.addAll(outline.getVertices()); // FIXME: can do and remove DIRTY_VERTICES ?
+ dirtyBits |= DIRTY_TRIANGLES | DIRTY_VERTICES;
return;
}
}
@@ -207,53 +274,58 @@ public class OutlineShape implements Comparable<OutlineShape> {
if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) {
bbox.resize(outline.getBounds());
}
+ dirtyBits |= DIRTY_TRIANGLES | DIRTY_VERTICES;
}
- /** Insert the {@link OutlineShape} elements of type {@link Outline}, .. at the end of this shape,
+ /**
+ * Insert the {@link OutlineShape} elements of type {@link Outline}, .. at the end of this shape,
* using {@link #addOutline(Outline)} for each element.
- * <p>Closes the current last outline via {@link #closeLastOutline()} before adding the new ones.</p>
+ * <p>Closes the current last outline via {@link #closeLastOutline(boolean)} before adding the new ones.</p>
* @param outlineShape OutlineShape elements to be added.
- * @throws NullPointerException if the {@link OutlineShape} is null
+ * @throws NullPointerException if the {@link OutlineShape} is null
* @throws IndexOutOfBoundsException if position is out of range (position < 0 || position > getOutlineNumber())
*/
- public void addOutlineShape(OutlineShape outlineShape) throws NullPointerException {
+ public final void addOutlineShape(final OutlineShape outlineShape) throws NullPointerException {
if (null == outlineShape) {
throw new NullPointerException("OutlineShape is null");
}
- closeLastOutline();
+ closeLastOutline(true);
for(int i=0; i<outlineShape.getOutlineNumber(); i++) {
addOutline(outlineShape.getOutline(i));
}
}
- /** Replaces the {@link Outline} element at the given {@code position}.
+ /**
+ * Replaces the {@link Outline} element at the given {@code position}.
* <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p>
- *
+ *
* @param position of the replaced Outline
- * @param outline replacement Outline object
- * @throws NullPointerException if the {@link Outline} element is null
+ * @param outline replacement Outline object
+ * @throws NullPointerException if the {@link Outline} element is null
* @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber())
*/
- public void setOutline(int position, Outline outline) throws NullPointerException, IndexOutOfBoundsException {
+ public final void setOutline(final int position, final Outline outline) throws NullPointerException, IndexOutOfBoundsException {
if (null == outline) {
throw new NullPointerException("outline is null");
}
outlines.set(position, outline);
- dirtyBits |= DIRTY_BOUNDS;
+ dirtyBits |= DIRTY_BOUNDS | DIRTY_TRIANGLES | DIRTY_VERTICES;
}
- /** Removes the {@link Outline} element at the given {@code position}.
+ /**
+ * Removes the {@link Outline} element at the given {@code position}.
* <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p>
- *
+ *
* @param position of the to be removed Outline
* @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber())
*/
- public final Outline removeOutline(int position) throws IndexOutOfBoundsException {
- dirtyBits |= DIRTY_BOUNDS;
+ public final Outline removeOutline(final int position) throws IndexOutOfBoundsException {
+ dirtyBits |= DIRTY_BOUNDS | DIRTY_TRIANGLES | DIRTY_VERTICES;
return outlines.remove(position);
}
- /** Get the last added outline to the list
+ /**
+ * Get the last added outline to the list
* of outlines that define the shape
* @return the last outline
*/
@@ -261,51 +333,57 @@ public class OutlineShape implements Comparable<OutlineShape> {
return outlines.get(outlines.size()-1);
}
- /** @return the {@code Outline} at {@code position}
+ /**
+ * Returns the {@code Outline} at {@code position}
* @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber())
*/
- public Outline getOutline(int position) throws IndexOutOfBoundsException {
+ public final Outline getOutline(final int position) throws IndexOutOfBoundsException {
return outlines.get(position);
- }
+ }
- /** Adds a vertex to the last open outline in the
- * shape.
+ /**
+ * Adds a vertex to the last open outline to the shape's tail.
* @param v the vertex to be added to the OutlineShape
*/
- public final void addVertex(Vertex v) {
+ public final void addVertex(final Vertex v) {
final Outline lo = getLastOutline();
lo.addVertex(v);
if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) {
- bbox.resize(lo.getBounds());
+ bbox.resize(v.getCoord());
}
+ // vertices.add(v); // FIXME: can do and remove DIRTY_VERTICES ?
+ dirtyBits |= DIRTY_TRIANGLES | DIRTY_VERTICES;
}
- /** Adds a vertex to the last open outline in the shape.
- * at {@code position}
- * @param position indx at which the vertex will be added
+ /**
+ * Adds a vertex to the last open outline to the shape at {@code position}
+ * @param position indx at which the vertex will be added
* @param v the vertex to be added to the OutlineShape
*/
- public final void addVertex(int position, Vertex v) {
+ public final void addVertex(final int position, final Vertex v) {
final Outline lo = getLastOutline();
lo.addVertex(position, v);
if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) {
- bbox.resize(lo.getBounds());
+ bbox.resize(v.getCoord());
}
+ dirtyBits |= DIRTY_TRIANGLES | DIRTY_VERTICES;
}
- /** Add a 2D {@link Vertex} to the last outline by defining the coordniate attribute
+ /**
+ * Add a 2D {@link Vertex} to the last outline by defining the coordinate attribute
* of the vertex. The 2D vertex will be represented as Z=0.
- *
+ *
* @param x the x coordinate
* @param y the y coordniate
* @param onCurve flag if this vertex is on the final curve or defines a curved region
* of the shape around this vertex.
*/
- public final void addVertex(float x, float y, boolean onCurve) {
+ public final void addVertex(final float x, final float y, final boolean onCurve) {
addVertex(vertexFactory.create(x, y, 0f, onCurve));
}
- /** Add a 3D {@link Vertex} to the last outline by defining the coordniate attribute
+ /**
+ * Add a 3D {@link Vertex} to the last outline by defining the coordniate attribute
* of the vertex.
* @param x the x coordinate
* @param y the y coordinate
@@ -313,14 +391,15 @@ public class OutlineShape implements Comparable<OutlineShape> {
* @param onCurve flag if this vertex is on the final curve or defines a curved region
* of the shape around this vertex.
*/
- public final void addVertex(float x, float y, float z, boolean onCurve) {
+ public final void addVertex(final float x, final float y, final float z, final boolean onCurve) {
addVertex(vertexFactory.create(x, y, z, onCurve));
}
- /** Add a vertex to the last outline by passing a float array and specifying the
- * offset and length in which. The attributes of the vertex are located.
+ /**
+ * Add a vertex to the last outline by passing a float array and specifying the
+ * offset and length in which. The attributes of the vertex are located.
* The attributes should be continuous (stride = 0).
- * Attributes which value are not set (when length less than 3)
+ * Attributes which value are not set (when length less than 3)
* are set implicitly to zero.
* @param coordsBuffer the coordinate array where the vertex attributes are to be picked from
* @param offset the offset in the buffer to the x coordinate
@@ -328,70 +407,72 @@ public class OutlineShape implements Comparable<OutlineShape> {
* @param onCurve flag if this vertex is on the final curve or defines a curved region
* of the shape around this vertex.
*/
- public final void addVertex(float[] coordsBuffer, int offset, int length, boolean onCurve) {
+ public final void addVertex(final float[] coordsBuffer, final int offset, final int length, final boolean onCurve) {
addVertex(vertexFactory.create(coordsBuffer, offset, length, onCurve));
- }
+ }
- /** Closes the last outline in the shape.
- * <p>If last vertex is not equal to first vertex.
- * A new temp vertex is added at the end which
- * is equal to the first.</p>
+ /**
+ * Closes the last outline in the shape.
+ * <p>
+ * Checks whether the last vertex equals to the first of the last outline.
+ * If not equal, it either appends a clone of the first vertex
+ * or prepends a clone of the last vertex, depending on <code>closeTail</code>.
+ * </p>
+ * @param closeTail if true, a clone of the first vertex will be appended,
+ * otherwise a clone of the last vertex will be prepended.
*/
- public void closeLastOutline() {
- getLastOutline().setClosed(true);
+ public final void closeLastOutline(final boolean closeTail) {
+ if( getLastOutline().setClosed(true) ) {
+ dirtyBits |= DIRTY_TRIANGLES | DIRTY_VERTICES;
+ }
}
/**
- * @return the outline's vertices state, {@link OutlineShape.VerticesState}
+ * Return the outline's vertices state, {@link OutlineShape.VerticesState}
*/
public final VerticesState getOutlineState() {
return outlineState;
}
- /** Ensure the outlines represent
- * the specified destinationType.
- * and removes all overlaps in boundary triangles
- * @param destinationType the target outline's vertices state. Currently only
- * {@link OutlineShape.VerticesState#QUADRATIC_NURBS} are supported.
+ /**
+ * Claim this outline's vertices are all {@link OutlineShape.VerticesState#QUADRATIC_NURBS},
+ * hence no cubic transformations will be performed.
*/
- public void transformOutlines(VerticesState destinationType) {
- if(outlineState != destinationType){
- if(destinationType == VerticesState.QUADRATIC_NURBS){
- transformOutlines2Quadratic();
- checkOverlaps();
- } else {
- throw new IllegalStateException("destinationType "+destinationType.name()+" not supported (currently "+outlineState.name()+")");
- }
- }
+ public final void setIsQuadraticNurbs() {
+ outlineState = VerticesState.QUADRATIC_NURBS;
+ // checkPossibleOverlaps = false;
}
- private void subdivideTriangle(final Outline outline, Vertex a, Vertex b, Vertex c, int index){
- float[] v1 = VectorUtil.mid(a.getCoord(), b.getCoord());
- float[] v3 = VectorUtil.mid(b.getCoord(), c.getCoord());
- float[] v2 = VectorUtil.mid(v1, v3);
+ private void subdivideTriangle(final Outline outline, final Vertex a, final Vertex b, final Vertex c, final int index){
+ VectorUtil.midVec3(tmpV1, a.getCoord(), b.getCoord());
+ VectorUtil.midVec3(tmpV3, b.getCoord(), c.getCoord());
+ VectorUtil.midVec3(tmpV2, tmpV1, tmpV3);
//drop off-curve vertex to image on the curve
- b.setCoord(v2, 0, 3);
+ b.setCoord(tmpV2, 0, 3);
b.setOnCurve(true);
- outline.addVertex(index, vertexFactory.create(v1, 0, 3, false));
- outline.addVertex(index+2, vertexFactory.create(v3, 0, 3, false));
+ outline.addVertex(index, vertexFactory.create(tmpV1, 0, 3, false));
+ outline.addVertex(index+2, vertexFactory.create(tmpV3, 0, 3, false));
+
+ addedVerticeCount += 2;
}
- /** Check overlaps between curved triangles
- * first check if any vertex in triangle a is in triangle b
- * second check if edges of triangle a intersect segments of triangle b
- * if any of the two tests is true we divide current triangle
- * and add the other to the list of overlaps
- *
- * Loop until overlap array is empty. (check only in first pass)
+ /**
+ * Check overlaps between curved triangles
+ * first check if any vertex in triangle a is in triangle b
+ * second check if edges of triangle a intersect segments of triangle b
+ * if any of the two tests is true we divide current triangle
+ * and add the other to the list of overlaps
+ *
+ * Loop until overlap array is empty. (check only in first pass)
*/
- private void checkOverlaps() {
- ArrayList<Vertex> overlaps = new ArrayList<Vertex>(3);
- int count = getOutlineNumber();
+ private void checkOverlaps() {
+ final ArrayList<Vertex> overlaps = new ArrayList<Vertex>(3);
+ final int count = getOutlineNumber();
boolean firstpass = true;
do {
- for (int cc = 0; cc < count; cc++) {
+ for (int cc = 0; cc < count; cc++) {
final Outline outline = getOutline(cc);
int vertexCount = outline.getVertexCount();
for(int i=0; i < outline.getVertexCount(); i++) {
@@ -399,39 +480,43 @@ public class OutlineShape implements Comparable<OutlineShape> {
if ( !currentVertex.isOnCurve()) {
final Vertex nextV = outline.getVertex((i+1)%vertexCount);
final Vertex prevV = outline.getVertex((i+vertexCount-1)%vertexCount);
- Vertex overlap =null;
-
- //check for overlap even if already set for subdivision
- //ensuring both trianglur overlaps get divided
- //for pref. only check in first pass
- //second pass to clear the overlaps arrray(reduces precision errors)
- if(firstpass) {
- overlap = checkTriOverlaps(prevV, currentVertex, nextV);
+ final Vertex overlap;
+
+ // check for overlap even if already set for subdivision
+ // ensuring both triangular overlaps get divided
+ // for pref. only check in first pass
+ // second pass to clear the overlaps array(reduces precision errors)
+ if( firstpass ) {
+ overlap = checkTriOverlaps0(prevV, currentVertex, nextV);
+ } else {
+ overlap = null;
}
- if(overlaps.contains(currentVertex) || overlap != null) {
+ if( overlaps.contains(currentVertex) || overlap != null ) {
overlaps.remove(currentVertex);
subdivideTriangle(outline, prevV, currentVertex, nextV, i);
i+=3;
vertexCount+=2;
+ addedVerticeCount+=2;
if(overlap != null && !overlap.isOnCurve()) {
- if(!overlaps.contains(overlap))
+ if(!overlaps.contains(overlap)) {
overlaps.add(overlap);
+ }
}
}
}
}
}
firstpass = false;
- }while(!overlaps.isEmpty());
+ } while( !overlaps.isEmpty() );
}
- private Vertex checkTriOverlaps(Vertex a, Vertex b, Vertex c) {
- int count = getOutlineNumber();
- for (int cc = 0; cc < count; cc++) {
+ private Vertex checkTriOverlaps0(final Vertex a, final Vertex b, final Vertex c) {
+ final int count = getOutlineNumber();
+ for (int cc = 0; cc < count; cc++) {
final Outline outline = getOutline(cc);
- int vertexCount = outline.getVertexCount();
+ final int vertexCount = outline.getVertexCount();
for(int i=0; i < vertexCount; i++) {
final Vertex current = outline.getVertex(i);
if(current.isOnCurve() || current == a || current == b || current == c) {
@@ -445,15 +530,47 @@ public class OutlineShape implements Comparable<OutlineShape> {
continue;
}
- if(VectorUtil.vertexInTriangle(a.getCoord(), b.getCoord(), c.getCoord(), current.getCoord())
- || VectorUtil.vertexInTriangle(a.getCoord(), b.getCoord(), c.getCoord(), nextV.getCoord())
- || VectorUtil.vertexInTriangle(a.getCoord(), b.getCoord(), c.getCoord(), prevV.getCoord())) {
+ if( VectorUtil.isVec3InTriangle3(a.getCoord(), b.getCoord(), c.getCoord(),
+ current.getCoord(), nextV.getCoord(), prevV.getCoord(),
+ tmpV1, tmpV2, tmpV3) ) {
+ return current;
+ }
+ if(VectorUtil.testTri2SegIntersection(a, b, c, prevV, current) ||
+ VectorUtil.testTri2SegIntersection(a, b, c, current, nextV) ||
+ VectorUtil.testTri2SegIntersection(a, b, c, prevV, nextV) ) {
+ return current;
+ }
+ }
+ }
+ return null;
+ }
+ @SuppressWarnings("unused")
+ private Vertex checkTriOverlaps1(final Vertex a, final Vertex b, final Vertex c) {
+ final int count = getOutlineNumber();
+ for (int cc = 0; cc < count; cc++) {
+ final Outline outline = getOutline(cc);
+ final int vertexCount = outline.getVertexCount();
+ for(int i=0; i < vertexCount; i++) {
+ final Vertex current = outline.getVertex(i);
+ if(current.isOnCurve() || current == a || current == b || current == c) {
+ continue;
+ }
+ final Vertex nextV = outline.getVertex((i+1)%vertexCount);
+ final Vertex prevV = outline.getVertex((i+vertexCount-1)%vertexCount);
+
+ //skip neighboring triangles
+ if(prevV == c || nextV == a) {
+ continue;
+ }
+ if( VectorUtil.isVec3InTriangle3(a.getCoord(), b.getCoord(), c.getCoord(),
+ current.getCoord(), nextV.getCoord(), prevV.getCoord(),
+ tmpV1, tmpV2, tmpV3, FloatUtil.EPSILON) ) {
return current;
}
- if(VectorUtil.tri2SegIntersection(a, b, c, prevV, current)
- || VectorUtil.tri2SegIntersection(a, b, c, current, nextV)
- || VectorUtil.tri2SegIntersection(a, b, c, prevV, nextV)) {
+ if(VectorUtil.testTri2SegIntersection(a, b, c, prevV, current, FloatUtil.EPSILON) ||
+ VectorUtil.testTri2SegIntersection(a, b, c, current, nextV, FloatUtil.EPSILON) ||
+ VectorUtil.testTri2SegIntersection(a, b, c, prevV, nextV, FloatUtil.EPSILON) ) {
return current;
}
}
@@ -461,112 +578,175 @@ public class OutlineShape implements Comparable<OutlineShape> {
return null;
}
- private void transformOutlines2Quadratic() {
+ private void cleanupOutlines() {
+ final boolean transformOutlines2Quadratic = VerticesState.QUADRATIC_NURBS != outlineState;
int count = getOutlineNumber();
- for (int cc = 0; cc < count; cc++) {
+ for (int cc = 0; cc < count; cc++) {
final Outline outline = getOutline(cc);
int vertexCount = outline.getVertexCount();
- for(int i=0; i < vertexCount; i++) {
- final Vertex currentVertex = outline.getVertex(i);
- final Vertex nextVertex = outline.getVertex((i+1)%vertexCount);
- if ( !currentVertex.isOnCurve() && !nextVertex.isOnCurve() ) {
- final float[] newCoords = VectorUtil.mid(currentVertex.getCoord(),
- nextVertex.getCoord());
- final Vertex v = vertexFactory.create(newCoords, 0, 3, true);
- i++;
- vertexCount++;
- outline.addVertex(i, v);
- }
+ if( transformOutlines2Quadratic ) {
+ for(int i=0; i < vertexCount; i++) {
+ final Vertex currentVertex = outline.getVertex(i);
+ final int j = (i+1)%vertexCount;
+ final Vertex nextVertex = outline.getVertex(j);
+ if ( !currentVertex.isOnCurve() && !nextVertex.isOnCurve() ) {
+ VectorUtil.midVec3(tmpV1, currentVertex.getCoord(), nextVertex.getCoord());
+ System.err.println("XXX: Cubic: "+i+": "+currentVertex+", "+j+": "+nextVertex);
+ final Vertex v = vertexFactory.create(tmpV1, 0, 3, true);
+ i++;
+ vertexCount++;
+ addedVerticeCount++;
+ outline.addVertex(i, v);
+ }
+ }
}
- if(vertexCount <= 0) {
+ if( 0 >= vertexCount ) {
outlines.remove(outline);
cc--;
count--;
- continue;
- }
-
- if( vertexCount > 0 ) {
- if(VectorUtil.checkEquality(outline.getVertex(0).getCoord(),
- outline.getLastVertex().getCoord())) {
- outline.removeVertex(vertexCount-1);
- }
+ } else if( 0 < vertexCount &&
+ VectorUtil.isVec3Equal( outline.getVertex(0).getCoord(), 0, outline.getLastVertex().getCoord(), 0, FloatUtil.EPSILON )) {
+ outline.removeVertex(vertexCount-1);
}
}
outlineState = VerticesState.QUADRATIC_NURBS;
+ checkOverlaps();
}
- private void generateVertexIds() {
+ private int generateVertexIds() {
int maxVertexId = 0;
for(int i=0; i<outlines.size(); i++) {
final ArrayList<Vertex> vertices = outlines.get(i).getVertices();
for(int pos=0; pos<vertices.size(); pos++) {
- Vertex vert = vertices.get(pos);
- vert.setId(maxVertexId);
- maxVertexId++;
+ vertices.get(pos).setId(maxVertexId++);
}
}
+ return maxVertexId;
}
- /** @return the list of concatenated vertices associated with all
- * {@code Outline}s of this object
+ /**
+ * Return list of concatenated vertices associated with all
+ * {@code Outline}s of this object.
+ * <p>
+ * Vertices are cached until marked dirty.
+ * </p>
+ * <p>
+ * Should always be called <i>after</i> {@link #getTriangles(VerticesState)},
+ * since the latter will mark all cached vertices dirty!
+ * </p>
*/
- public ArrayList<Vertex> getVertices() {
- ArrayList<Vertex> vertices = new ArrayList<Vertex>();
- for(int i=0; i<outlines.size(); i++) {
- vertices.addAll(outlines.get(i).getVertices());
+ public final ArrayList<Vertex> getVertices() {
+ final boolean updated;
+ if( 0 != ( DIRTY_VERTICES & dirtyBits ) ) {
+ vertices.clear();
+ for(int i=0; i<outlines.size(); i++) {
+ vertices.addAll(outlines.get(i).getVertices());
+ }
+ dirtyBits &= ~DIRTY_VERTICES;
+ updated = true;
+ } else {
+ updated = false;
+ }
+ if(Region.DEBUG_INSTANCE) {
+ System.err.println("OutlineShape.getVertices(): o "+outlines.size()+", v "+vertices.size()+", updated "+updated);
}
return vertices;
}
+ private void triangulateImpl() {
+ if( 0 < outlines.size() ) {
+ sortOutlines();
+ generateVertexIds();
+
+ triangles.clear();
+ final Triangulator triangulator2d = Triangulation.create();
+ for(int index = 0; index<outlines.size(); index++) {
+ triangulator2d.addCurve(triangles, outlines.get(index), sharpness);
+ }
+ triangulator2d.generate(triangles);
+ addedVerticeCount += triangulator2d.getAddedVerticeCount();
+ triangulator2d.reset();
+ }
+ }
+
/**
- * Triangulate the {@link OutlineShape} generating a list of triangles
+ * Triangulate the {@link OutlineShape} generating a list of triangles,
+ * while {@link #transformOutlines(VerticesState)} beforehand.
+ * <p>
+ * Triangles are cached until marked dirty.
+ * </p>
* @return an arraylist of triangles representing the filled region
* which is produced by the combination of the outlines
*/
- public ArrayList<Triangle> triangulate() {
- if(outlines.size() == 0){
- return null;
+ public ArrayList<Triangle> getTriangles(final VerticesState destinationType) {
+ final boolean updated;
+ if(destinationType != VerticesState.QUADRATIC_NURBS) {
+ throw new IllegalStateException("destinationType "+destinationType.name()+" not supported (currently "+outlineState.name()+")");
}
- sortOutlines();
- generateVertexIds();
-
- Triangulator triangulator2d = Triangulation.create();
- for(int index = 0; index<outlines.size(); index++) {
- triangulator2d.addCurve(outlines.get(index));
+ if( 0 != ( DIRTY_TRIANGLES & dirtyBits ) ) {
+ cleanupOutlines();
+ triangulateImpl();
+ updated = true;
+ dirtyBits |= DIRTY_VERTICES;
+ dirtyBits &= ~DIRTY_TRIANGLES;
+ } else {
+ updated = false;
+ }
+ if(Region.DEBUG_INSTANCE) {
+ System.err.println("OutlineShape.getTriangles().X: "+triangles.size()+", updated "+updated);
}
-
- ArrayList<Triangle> triangles = triangulator2d.generate();
- triangulator2d.reset();
-
return triangles;
}
- /** Sort the outlines from large
- * to small depending on the AABox
+ /**
+ * Return a transformed instance with all {@link Outline}s are copied and transformed.
+ * <p>
+ * Note: Triangulated data is lost in returned instance!
+ * </p>
+ */
+ public final OutlineShape transform(final AffineTransform t) {
+ final OutlineShape newOutlineShape = new OutlineShape(vertexFactory);
+ final int osize = outlines.size();
+ for(int i=0; i<osize; i++) {
+ newOutlineShape.addOutline( outlines.get(i).transform(t, vertexFactory) );
+ }
+ return newOutlineShape;
+ }
+
+ /**
+ * Sort the outlines from large
+ * to small depending on the AABox
*/
private void sortOutlines() {
- Collections.sort(outlines);
- Collections.reverse(outlines);
+ Collections.sort(outlines, reversSizeComparator);
}
- /** Compare two outline shapes with Bounding Box area
- * as criteria.
+ private static Comparator<Outline> reversSizeComparator = new Comparator<Outline>() {
+ @Override
+ public int compare(final Outline o1, final Outline o2) {
+ return o2.compareTo(o1); // reverse !
+ } };
+
+ /**
+ * Compare two outline shape's Bounding Box size.
+ * @see AABBox#getSize()
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
- public final int compareTo(OutlineShape outline) {
- float size = getBounds().getSize();
- float newSize = outline.getBounds().getSize();
- if(size < newSize){
+ @Override
+ public final int compareTo(final OutlineShape other) {
+ final float thisSize = getBounds().getSize();
+ final float otherSize = other.getBounds().getSize();
+ if( FloatUtil.isEqual(thisSize, otherSize, FloatUtil.EPSILON) ) {
+ return 0;
+ } else if( thisSize < otherSize ){
return -1;
- }
- else if(size > newSize){
+ } else {
return 1;
}
- return 0;
}
- private final void validateBoundingBox() {
+ private void validateBoundingBox() {
dirtyBits &= ~DIRTY_BOUNDS;
bbox.reset();
for (int i=0; i<outlines.size(); i++) {
@@ -579,20 +759,21 @@ public class OutlineShape implements Comparable<OutlineShape> {
validateBoundingBox();
}
return bbox;
- }
+ }
/**
* @param obj the Object to compare this OutlineShape with
- * @return true if {@code obj} is an OutlineShape, not null,
- * same outlineState, equal bounds and equal outlines in the same order
+ * @return true if {@code obj} is an OutlineShape, not null,
+ * same outlineState, equal bounds and equal outlines in the same order
*/
- public boolean equals(Object obj) {
+ @Override
+ public boolean equals(final Object obj) {
if( obj == this) {
return true;
}
if( null == obj || !(obj instanceof OutlineShape) ) {
return false;
- }
+ }
final OutlineShape o = (OutlineShape) obj;
if(getOutlineState() != o.getOutlineState()) {
return false;
@@ -611,19 +792,14 @@ public class OutlineShape implements Comparable<OutlineShape> {
return true;
}
- /**
- * @return deep clone of this OutlineShape w/o Region
- */
- public OutlineShape clone() {
- OutlineShape o;
- try {
- o = (OutlineShape) super.clone();
- } catch (CloneNotSupportedException e) { throw new InternalError(); }
- o.bbox = bbox.clone();
- o.outlines = new ArrayList<Outline>(outlines.size());
- for(int i=0; i<outlines.size(); i++) {
- o.outlines.add(outlines.get(i).clone());
- }
- return o;
- }
+ @Override
+ public final int hashCode() {
+ throw new InternalError("hashCode not designed");
+ }
+
+ @Override
+ public String toString() {
+ // Avoid calling this.hashCode() !
+ return getClass().getName() + "@" + Integer.toHexString(super.hashCode());
+ }
}
diff --git a/src/jogl/classes/com/jogamp/graph/curve/OutlineShapeXForm.java b/src/jogl/classes/com/jogamp/graph/curve/OutlineShapeXForm.java
new file mode 100644
index 000000000..cf4d38450
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/graph/curve/OutlineShapeXForm.java
@@ -0,0 +1,16 @@
+package com.jogamp.graph.curve;
+
+import jogamp.graph.geom.plane.AffineTransform;
+
+public class OutlineShapeXForm {
+ public final OutlineShape shape;
+ private AffineTransform t;
+
+ public OutlineShapeXForm(final OutlineShape shape, final AffineTransform t) {
+ this.shape = shape;
+ this.t = t;
+ }
+
+ public final AffineTransform getTransform() { return t; }
+ public final void setTransform(final AffineTransform t) { this.t = t; }
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/graph/curve/Region.java b/src/jogl/classes/com/jogamp/graph/curve/Region.java
index af15f9dc4..023ca8373 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/Region.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/Region.java
@@ -28,164 +28,384 @@
package com.jogamp.graph.curve;
import java.util.ArrayList;
+import java.util.List;
+import jogamp.graph.geom.plane.AffineTransform;
import jogamp.opengl.Debug;
-import com.jogamp.graph.geom.AABBox;
import com.jogamp.graph.geom.Triangle;
import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.math.geom.Frustum;
+import com.jogamp.opengl.util.texture.TextureSequence;
-/** Abstract Outline shape GL representation
- * define the method an OutlineShape(s) is
- * binded rendered.
- *
- * @see GLRegion
+/**
+ * Abstract Outline shape representation define the method an OutlineShape(s)
+ * is bound and rendered.
+ *
+ * @see GLRegion
*/
public abstract class Region {
-
- /** Debug flag for region impl (graph.curve)
- */
+
+ /** Debug flag for region impl (graph.curve) */
public static final boolean DEBUG = Debug.debug("graph.curve");
-
- public static final boolean DEBUG_INSTANCE = false;
+ public static final boolean DEBUG_INSTANCE = Debug.debug("graph.curve.Instance");
- /** View based Anti-Aliasing, A Two pass region rendering, slower
- * and more resource hungry (FBO), but AA is perfect.
- * Otherwise the default fast one pass MSAA region rendering is being used.
+ /**
+ * Rendering-Mode bit for {@link #getRenderModes() Region}
+ * <p>
+ * MSAA based Anti-Aliasing, a two pass region rendering, slower and more
+ * resource hungry (FBO), but providing fast MSAA in case
+ * the whole scene is not rendered with MSAA.
+ * </p>
*/
- public static final int VBAA_RENDERING_BIT = 1 << 0;
+ public static final int MSAA_RENDERING_BIT = 1 << 0;
- /** Use non uniform weights [0.0 .. 1.9] for curve region rendering.
- * Otherwise the default weight 1.0 for uniform curve region rendering is being applied.
+ /**
+ * Rendering-Mode bit for {@link #getRenderModes() Region}
+ * <p>
+ * View based Anti-Aliasing, a two pass region rendering, slower and more
+ * resource hungry (FBO), but AA is perfect. Otherwise the default fast one
+ * pass MSAA region rendering is being used.
+ * </p>
+ */
+ public static final int VBAA_RENDERING_BIT = 1 << 1;
+
+ /**
+ * Rendering-Mode bit for {@link #getRenderModes() Region}
+ * <p>
+ * Use non uniform weights [0.0 .. 1.9] for curve region rendering.
+ * Otherwise the default weight 1.0 for uniform curve region rendering is
+ * being applied.
+ * </p>
*/
- public static final int VARIABLE_CURVE_WEIGHT_BIT = 1 << 1;
+ public static final int VARWEIGHT_RENDERING_BIT = 1 << 8;
+
+ /**
+ * Rendering-Mode bit for {@link #getRenderModes() Region}
+ * <p>
+ * If set, a color channel attribute per vertex is added to the stream,
+ * otherwise only the
+ * {@link com.jogamp.graph.curve.opengl.RegionRenderer#setColorStatic(javax.media.opengl.GL2ES2, float, float, float, float) static color}
+ * is being used.
+ * </p>
+ */
+ public static final int COLORCHANNEL_RENDERING_BIT = 1 << 9;
+
+ /**
+ * Rendering-Mode bit for {@link #getRenderModes() Region}
+ * <p>
+ * If set, a color texture is used to determine the color.
+ * </p>
+ */
+ public static final int COLORTEXTURE_RENDERING_BIT = 1 << 10;
+
+ /** Default maximum {@link #getQuality() quality}, {@value}. */
+ public static final int MAX_QUALITY = 1;
+
+ public static final int DEFAULT_TWO_PASS_TEXTURE_UNIT = 0;
- public static final int TWO_PASS_DEFAULT_TEXTURE_UNIT = 0;
+ protected static final int DIRTY_SHAPE = 1 << 0 ;
+ protected static final int DIRTY_STATE = 1 << 1 ;
private final int renderModes;
- private boolean dirty = true;
- protected int numVertices = 0;
+ private int quality;
+ private int dirty = DIRTY_SHAPE | DIRTY_STATE;
+ private int numVertices = 0;
protected final AABBox box = new AABBox();
- protected ArrayList<Triangle> triangles = new ArrayList<Triangle>();
- protected ArrayList<Vertex> vertices = new ArrayList<Vertex>();
+ protected Frustum frustum = null;
- public static boolean isVBAA(int renderModes) {
- return 0 != ( renderModes & Region.VBAA_RENDERING_BIT );
+ public static boolean isVBAA(final int renderModes) {
+ return 0 != (renderModes & Region.VBAA_RENDERING_BIT);
}
- /** Check if render mode capable of non uniform weights
- * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT},
- * {@link Region#VBAA_RENDERING_BIT}
- * @return true of capable of non uniform weights
+ public static boolean isMSAA(final int renderModes) {
+ return 0 != (renderModes & Region.MSAA_RENDERING_BIT);
+ }
+
+ public static boolean isTwoPass(final int renderModes) {
+ return 0 != ( renderModes & ( Region.VBAA_RENDERING_BIT | Region.MSAA_RENDERING_BIT) );
+ }
+
+ /**
+ * Returns true if render mode capable of variable weights,
+ * i.e. the bit {@link #VARWEIGHT_RENDERING_BIT} is set,
+ * otherwise false.
+ */
+ public static boolean hasVariableWeight(final int renderModes) {
+ return 0 != (renderModes & Region.VARWEIGHT_RENDERING_BIT);
+ }
+
+ /**
+ * Returns true if render mode has a color channel,
+ * i.e. the bit {@link #COLORCHANNEL_RENDERING_BIT} is set,
+ * otherwise false.
+ */
+ public static boolean hasColorChannel(final int renderModes) {
+ return 0 != (renderModes & Region.COLORCHANNEL_RENDERING_BIT);
+ }
+
+ /**
+ * Returns true if render mode has a color texture,
+ * i.e. the bit {@link #COLORTEXTURE_RENDERING_BIT} is set,
+ * otherwise false.
*/
- public static boolean isNonUniformWeight(int renderModes) {
- return 0 != ( renderModes & Region.VARIABLE_CURVE_WEIGHT_BIT );
+ public static boolean hasColorTexture(final int renderModes) {
+ return 0 != (renderModes & Region.COLORTEXTURE_RENDERING_BIT);
+ }
+
+ public static String getRenderModeString(final int renderModes) {
+ final String curveS = hasVariableWeight(renderModes) ? "-curve" : "";
+ final String cChanS = hasColorChannel(renderModes) ? "-cols" : "";
+ final String cTexS = hasColorTexture(renderModes) ? "-ctex" : "";
+ if( Region.isVBAA(renderModes) ) {
+ return "vbaa"+curveS+cChanS+cTexS;
+ } else if( Region.isMSAA(renderModes) ) {
+ return "msaa"+curveS+cChanS+cTexS;
+ } else {
+ return "norm"+curveS+cChanS+cTexS;
+ }
}
- protected Region(int regionRenderModes) {
+ protected Region(final int regionRenderModes) {
this.renderModes = regionRenderModes;
+ this.quality = MAX_QUALITY;
}
- /** Get current Models
- * @return bit-field of render modes
+ // FIXME: Better handling of impl. buffer growth .. !
+ // protected abstract void setupInitialComponentCount(int attributeCount, int indexCount);
+
+ protected abstract void pushVertex(final float[] coords, final float[] texParams, float[] rgba);
+ protected abstract void pushIndex(int idx);
+
+ /**
+ * Return bit-field of render modes, see {@link GLRegion#create(int, TextureSequence)}.
*/
- public final int getRenderModes() {
- return renderModes;
+ public final int getRenderModes() { return renderModes; }
+
+ /** See {@link #MAX_QUALITY} */
+ public final int getQuality() { return quality; }
+
+ /** See {@link #MAX_QUALITY} */
+ public final void setQuality(final int q) { quality=q; }
+
+ protected void clearImpl() {
+ dirty = DIRTY_SHAPE | DIRTY_STATE;
+ numVertices = 0;
+ box.reset();
}
- /** Check if current Region is using VBAA
- * @return true if capable of two pass rendering - VBAA
+ /**
+ * Returns true if capable of two pass rendering - VBAA, otherwise false.
*/
- public boolean isVBAA() {
- return Region.isVBAA(renderModes);
+ public final boolean isVBAA() {
+ return Region.isVBAA(renderModes);
}
- /** Check if current instance uses non uniform weights
- * @return true if capable of nonuniform weights
+ /**
+ * Returns true if capable of two pass rendering - MSAA, otherwise false.
*/
- public boolean isNonUniformWeight() {
- return Region.isNonUniformWeight(renderModes);
+ public final boolean isMSAA() {
+ return Region.isMSAA(renderModes);
}
- /** Get the current number of vertices associated
- * with this region. This number is not necessary equal to
- * the OGL bound number of vertices.
- * @return vertices count
+ /**
+ * Returns true if capable of variable weights, otherwise false.
*/
- public final int getNumVertices(){
- return numVertices;
+ public final boolean hasVariableWeight() {
+ return Region.hasVariableWeight(renderModes);
}
- /** Adds a {@link Triangle} object to the Region
- * This triangle will be bound to OGL objects
- * on the next call to {@code update}
- * @param tri a triangle object
- *
- * @see update(GL2ES2)
+ /**
+ * Returns true if render mode has a color channel,
+ * i.e. the bit {@link #COLORCHANNEL_RENDERING_BIT} is set,
+ * otherwise false.
*/
- public void addTriangle(Triangle tri) {
- triangles.add(tri);
- setDirty(true);
+ public boolean hasColorChannel() {
+ return Region.hasColorChannel(renderModes);
}
- /** Adds a list of {@link Triangle} objects to the Region
- * These triangles are to be binded to OGL objects
- * on the next call to {@code update}
- * @param tris an arraylist of triangle objects
- *
- * @see update(GL2ES2)
+ /**
+ * Returns true if render mode has a color texture,
+ * i.e. the bit {@link #COLORTEXTURE_RENDERING_BIT} is set,
+ * otherwise false.
*/
- public void addTriangles(ArrayList<Triangle> tris) {
- triangles.addAll(tris);
- setDirty(true);
+ public boolean hasColorTexture() {
+ return Region.hasColorTexture(renderModes);
}
- /** Adds a {@link Vertex} object to the Region
- * This vertex will be bound to OGL objects
- * on the next call to {@code update}
- * @param vert a vertex objects
- *
- * @see update(GL2ES2)
+
+ /** See {@link #setFrustum(Frustum)} */
+ public final Frustum getFrustum() { return frustum; }
+
+ /**
+ * Set {@link Frustum} culling for {@link #addOutlineShape(OutlineShape, AffineTransform, float[])}.
*/
- public void addVertex(Vertex vert) {
- vertices.add(vert);
+ public final void setFrustum(final Frustum frustum) {
+ this.frustum = frustum;
+ }
+
+ final float[] coordsEx = new float[3];
+
+ private void pushNewVertexImpl(final Vertex vertIn, final AffineTransform transform, final float[] rgba) {
+ if( null != transform ) {
+ final float[] coordsIn = vertIn.getCoord();
+ transform.transform(coordsIn, coordsEx);
+ coordsEx[2] = coordsIn[2];
+ box.resize(coordsEx[0], coordsEx[1], coordsEx[2]);
+ pushVertex(coordsEx, vertIn.getTexCoord(), rgba);
+ } else {
+ box.resize(vertIn.getX(), vertIn.getY(), vertIn.getZ());
+ pushVertex(vertIn.getCoord(), vertIn.getTexCoord(), rgba);
+ }
numVertices++;
- setDirty(true);
}
- /** Adds a list of {@link Vertex} objects to the Region
- * These vertices are to be binded to OGL objects
- * on the next call to {@code update}
- * @param verts an arraylist of vertex objects
- *
- * @see update(GL2ES2)
- */
- public void addVertices(ArrayList<Vertex> verts) {
- vertices.addAll(verts);
- numVertices = vertices.size();
- setDirty(true);
+ private void pushNewVertexIdxImpl(final Vertex vertIn, final AffineTransform transform, final float[] rgba) {
+ pushIndex(numVertices);
+ pushNewVertexImpl(vertIn, transform, rgba);
}
+ private final AABBox tmpBox = new AABBox();
+
/**
- * @return the AxisAligned bounding box of
- * current region
+ * Add the given {@link OutlineShape} to this region with the given optional {@link AffineTransform}.
+ * <p>
+ * In case {@link #setFrustum(Frustum) frustum culling is set}, the {@link OutlineShape}
+ * is dropped if it's {@link OutlineShape#getBounds() bounding-box} is fully outside of the frustum.
+ * The optional {@link AffineTransform} is applied to the bounding-box beforehand.
+ * </p>
+ * @param rgbaColor TODO
*/
- public final AABBox getBounds(){
+ public final void addOutlineShape(final OutlineShape shape, final AffineTransform t, final float[] rgbaColor) {
+ if( null != frustum ) {
+ final AABBox shapeBox = shape.getBounds();
+ final AABBox shapeBoxT;
+ if( null != t ) {
+ t.transform(shapeBox, tmpBox);
+ shapeBoxT = tmpBox;
+ } else {
+ shapeBoxT = shapeBox;
+ }
+ if( frustum.isAABBoxOutside(shapeBoxT) ) {
+ if(DEBUG_INSTANCE) {
+ System.err.println("Region.addOutlineShape(): Dropping outside shapeBoxT: "+shapeBoxT);
+ }
+ return;
+ }
+ }
+ final List<Triangle> trisIn = shape.getTriangles(OutlineShape.VerticesState.QUADRATIC_NURBS);
+ final ArrayList<Vertex> vertsIn = shape.getVertices();
+ if(DEBUG_INSTANCE) {
+ final int addedVerticeCount = shape.getAddedVerticeCount();
+ final int verticeCount = vertsIn.size() + addedVerticeCount;
+ final int indexCount = trisIn.size() * 3;
+ System.err.println("Region.addOutlineShape().0: tris: "+trisIn.size()+", verts "+vertsIn.size()+", transform "+t);
+ System.err.println("Region.addOutlineShape().0: VerticeCount "+vertsIn.size()+" + "+addedVerticeCount+" = "+verticeCount);
+ System.err.println("Region.addOutlineShape().0: IndexCount "+indexCount);
+ }
+ // setupInitialComponentCount(verticeCount, indexCount); // FIXME: Use it ?
+
+ final int idxOffset = numVertices;
+ int vertsVNewIdxCount = 0, vertsTMovIdxCount = 0, vertsTNewIdxCount = 0, tris = 0;
+ final int vertsDupCountV = 0, vertsDupCountT = 0, vertsKnownMovedT = 0;
+ if( vertsIn.size() >= 3 ) {
+ if(DEBUG_INSTANCE) {
+ System.err.println("Region.addOutlineShape(): Processing Vertices");
+ }
+ for(int i=0; i<vertsIn.size(); i++) {
+ pushNewVertexImpl(vertsIn.get(i), t, rgbaColor);
+ vertsVNewIdxCount++;
+ }
+ if(DEBUG_INSTANCE) {
+ System.err.println("Region.addOutlineShape(): Processing Triangles");
+ }
+ for(int i=0; i<trisIn.size(); i++) {
+ final Triangle triIn = trisIn.get(i);
+ if(Region.DEBUG_INSTANCE) {
+ System.err.println("T["+i+"]: "+triIn);
+ }
+ // triEx.addVertexIndicesOffset(idxOffset);
+ // triangles.add( triEx );
+ final Vertex[] triInVertices = triIn.getVertices();
+ final int tv0Idx = triInVertices[0].getId();
+ if( Integer.MAX_VALUE-idxOffset > tv0Idx ) { // Integer.MAX_VALUE != i0 // FIXME: renderer uses SHORT!
+ // valid 'known' idx - move by offset
+ if(Region.DEBUG_INSTANCE) {
+ System.err.println("T["+i+"]: Moved "+tv0Idx+" + "+idxOffset+" -> "+(tv0Idx+idxOffset));
+ }
+ pushIndex(tv0Idx+idxOffset);
+ pushIndex(triInVertices[1].getId()+idxOffset);
+ pushIndex(triInVertices[2].getId()+idxOffset);
+ vertsTMovIdxCount+=3;
+ } else {
+ // invalid idx - generate new one
+ if(Region.DEBUG_INSTANCE) {
+ System.err.println("T["+i+"]: New Idx "+numVertices);
+ }
+ pushNewVertexIdxImpl(triInVertices[0], t, rgbaColor);
+ pushNewVertexIdxImpl(triInVertices[1], t, rgbaColor);
+ pushNewVertexIdxImpl(triInVertices[2], t, rgbaColor);
+ vertsTNewIdxCount+=3;
+ }
+ tris++;
+ }
+ }
+ if(DEBUG_INSTANCE) {
+ System.err.println("Region.addOutlineShape().X: idxOffset "+idxOffset+", tris: "+tris+", verts [idx "+vertsTNewIdxCount+", add "+vertsTNewIdxCount+" = "+(vertsVNewIdxCount+vertsTNewIdxCount)+"]");
+ System.err.println("Region.addOutlineShape().X: verts: idx[v-new "+vertsVNewIdxCount+", t-new "+vertsTNewIdxCount+" = "+(vertsVNewIdxCount+vertsTNewIdxCount)+"]");
+ System.err.println("Region.addOutlineShape().X: verts: idx t-moved "+vertsTMovIdxCount+", numVertices "+numVertices);
+ System.err.println("Region.addOutlineShape().X: verts: v-dups "+vertsDupCountV+", t-dups "+vertsDupCountT+", t-known "+vertsKnownMovedT);
+ // int vertsDupCountV = 0, vertsDupCountT = 0;
+ System.err.println("Region.addOutlineShape().X: box "+box);
+ }
+ markShapeDirty();
+ }
+
+ public final void addOutlineShapes(final List<OutlineShape> shapes, final AffineTransform transform, final float[] rgbaColor) {
+ for (int i = 0; i < shapes.size(); i++) {
+ addOutlineShape(shapes.get(i), transform, rgbaColor);
+ }
+ }
+
+ /** @return the AxisAligned bounding box of current region */
+ public final AABBox getBounds() {
return box;
}
- /** Check if this region is dirty. A region is marked dirty
- * when new Vertices, Triangles, and or Lines are added after a
- * call to update()
- * @return true if region is Dirty, false otherwise
- *
- * @see update(GL2ES2)
+ /**
+ * Mark this region's shape dirty, i.e. it's
+ * Vertices, Triangles, and or Lines changed.
+ */
+ public final void markShapeDirty() {
+ dirty |= DIRTY_SHAPE;
+ }
+ /** Returns true if this region's shape are dirty, see {@link #markShapeDirty()}. */
+ public final boolean isShapeDirty() {
+ return 0 != ( dirty & DIRTY_SHAPE ) ;
+ }
+ /**
+ * Mark this region's state dirty, i.e.
+ * it's render attributes or parameters changed.
+ */
+ public final void markStateDirty() {
+ dirty |= DIRTY_STATE;
+ }
+ /** Returns true if this region's state is dirty, see {@link #markStateDirty()}. */
+ public final boolean isStateDirty() {
+ return 0 != ( dirty & DIRTY_STATE ) ;
+ }
+
+ /**
+ * See {@link #markShapeDirty()} and {@link #markStateDirty()}.
*/
- public final boolean isDirty() {
- return dirty;
+ protected final void clearDirtyBits(final int v) {
+ dirty &= ~v;
}
+ protected final int getDirtyBits() { return dirty; }
- protected final void setDirty(boolean v) {
- dirty = v;
+ public String toString() {
+ return "Region["+getRenderModeString(this.renderModes)+", q "+quality+", dirty "+dirty+", vertices "+numVertices+", box "+box+"]";
}
} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
index 63713887b..654f9a692 100755..100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
@@ -27,103 +27,125 @@
*/
package com.jogamp.graph.curve.opengl;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
-import java.util.ArrayList;
+import jogamp.graph.curve.opengl.VBORegion2PMSAAES2;
+import jogamp.graph.curve.opengl.VBORegion2PVBAAES2;
+import jogamp.graph.curve.opengl.VBORegionSPES2;
-import javax.media.opengl.GL2ES2;
import com.jogamp.opengl.util.PMVMatrix;
-
-import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.opengl.util.texture.TextureSequence;
import com.jogamp.graph.curve.Region;
-import com.jogamp.graph.geom.Triangle;
-import com.jogamp.graph.geom.Vertex;
-import jogamp.graph.curve.opengl.RegionFactory;
+import com.jogamp.graph.curve.OutlineShape;
/** A GLRegion is the OGL binding of one or more OutlineShapes
* Defined by its vertices and generated triangles. The Region
- * defines the final shape of the OutlineShape(s), which shall produced a shaded
+ * defines the final shape of the OutlineShape(s), which shall produced a shaded
* region on the screen.
- *
- * Implementations of the GLRegion shall take care of the OGL
+ *
+ * Implementations of the GLRegion shall take care of the OGL
* binding of the depending on its context, profile.
- *
- * @see Region, RegionFactory, OutlineShape
+ *
+ * @see Region
+ * @see OutlineShape
*/
-public abstract class GLRegion extends Region {
-
- /** Create an ogl {@link GLRegion} defining the list of {@link OutlineShape}.
- * Combining the Shapes into single buffers.
- * @return the resulting Region inclusive the generated region
+public abstract class GLRegion extends Region {
+
+ /**
+ * Create a GLRegion using the passed render mode
+ *
+ * <p> In case {@link Region#VBAA_RENDERING_BIT} is being requested the default texture unit
+ * {@link Region#DEFAULT_TWO_PASS_TEXTURE_UNIT} is being used.</p>
+ * @param renderModes bit-field of modes, e.g. {@link Region#VARWEIGHT_RENDERING_BIT}, {@link Region#VBAA_RENDERING_BIT}
+ * @param colorTexSeq optional {@link TextureSequence} for {@link Region#COLORTEXTURE_RENDERING_BIT} rendering mode.
*/
- public static GLRegion create(OutlineShape[] outlineShapes, int renderModes) {
- final GLRegion region = RegionFactory.create(renderModes);
-
- int numVertices = region.getNumVertices();
-
- for(int index=0; index<outlineShapes.length; index++) {
- OutlineShape outlineShape = outlineShapes[index];
- outlineShape.transformOutlines(OutlineShape.VerticesState.QUADRATIC_NURBS);
-
- ArrayList<Triangle> triangles = outlineShape.triangulate();
- region.addTriangles(triangles);
-
- ArrayList<Vertex> vertices = outlineShape.getVertices();
- for(int pos=0; pos < vertices.size(); pos++){
- Vertex vert = vertices.get(pos);
- vert.setId(numVertices++);
- }
- region.addVertices(vertices);
+ public static GLRegion create(int renderModes, final TextureSequence colorTexSeq) {
+ if( null != colorTexSeq ) {
+ renderModes |= Region.COLORTEXTURE_RENDERING_BIT;
+ } else if( Region.hasColorTexture(renderModes) ) {
+ throw new IllegalArgumentException("COLORTEXTURE_RENDERING_BIT set but null TextureSequence");
+ }
+ if( isVBAA(renderModes) ) {
+ return new VBORegion2PVBAAES2(renderModes, colorTexSeq, Region.DEFAULT_TWO_PASS_TEXTURE_UNIT);
+ } else if( isMSAA(renderModes) ) {
+ return new VBORegion2PMSAAES2(renderModes, colorTexSeq, Region.DEFAULT_TWO_PASS_TEXTURE_UNIT);
+ } else {
+ return new VBORegionSPES2(renderModes, colorTexSeq);
}
-
- return region;
}
- /**
- * Create an ogl {@link GLRegion} defining this {@link OutlineShape}
- * @return the resulting Region.
- */
- public static GLRegion create(OutlineShape outlineShape, int renderModes) {
- final GLRegion region = RegionFactory.create(renderModes);
-
- outlineShape.transformOutlines(OutlineShape.VerticesState.QUADRATIC_NURBS);
- ArrayList<Triangle> triangles = (ArrayList<Triangle>) outlineShape.triangulate();
- ArrayList<Vertex> vertices = (ArrayList<Vertex>) outlineShape.getVertices();
- region.addVertices(vertices);
- region.addTriangles(triangles);
- return region;
- }
-
- protected GLRegion(int renderModes) {
+ protected final TextureSequence colorTexSeq;
+
+ protected GLRegion(final int renderModes, final TextureSequence colorTexSeq) {
super(renderModes);
+ this.colorTexSeq = colorTexSeq;
}
-
- /** Updates a graph region by updating the ogl related
- * objects for use in rendering if {@link #isDirty()}.
- * <p>Allocates the ogl related data and initializes it the 1st time.<p>
- * <p>Called by {@link #draw(GL2ES2, RenderState, int, int, int)}.</p>
- * @param rs TODO
+
+ /**
+ * Updates a graph region by updating the ogl related
+ * objects for use in rendering if {@link #isShapeDirty()}.
+ * <p>Allocates the ogl related data and initializes it the 1st time.<p>
+ * <p>Called by {@link #draw(GL2ES2, RenderState, int, int, int)}.</p>
*/
- protected abstract void update(GL2ES2 gl, RenderState rs);
-
- /** Delete and clean the associated OGL
- * objects
+ protected abstract void updateImpl(final GL2ES2 gl);
+
+ protected abstract void destroyImpl(final GL2ES2 gl);
+
+ protected abstract void clearImpl(final GL2ES2 gl);
+
+ /**
+ * Clears all data, i.e. triangles, vertices etc.
*/
- public abstract void destroy(GL2ES2 gl, RenderState rs);
-
- /** Renders the associated OGL objects specifying
+ public void clear(final GL2ES2 gl) {
+ clearImpl(gl);
+ clearImpl();
+ }
+
+ /**
+ * Delete and clear the associated OGL objects.
+ */
+ public final void destroy(final GL2ES2 gl) {
+ clear(gl);
+ destroyImpl(gl);
+ }
+
+ /**
+ * Renders the associated OGL objects specifying
* current width/hight of window for multi pass rendering
* of the region.
+ * <p>
+ * User shall consider {@link RegionRenderer#enable(GL2ES2, boolean) enabling}
+ * the renderer beforehand and {@link RegionRenderer#enable(GL2ES2, boolean) disabling}
+ * it afterwards when used in conjunction with other renderer.
+ * </p>
+ * <p>
+ * Users shall also consider setting the {@link GL#glClearColor(float, float, float, float) clear-color}
+ * appropriately:
+ * <ul>
+ * <li>If {@link GL#GL_BLEND blending} is enabled, <i>RGB</i> shall be set to text color, otherwise
+ * blending will reduce the alpha seam's contrast and the font will appear thinner.</li>
+ * <li>If {@link GL#GL_BLEND blending} is disabled, <i>RGB</i> shall be set to the actual desired background.</li>
+ * </ul>
+ * The <i>alpha</i> component shall be set to zero.
+ * Note: If {@link GL#GL_BLEND blending} is enabled, the
+ * {@link RegionRenderer} might need to be
+ * {@link RegionRenderer#create(RenderState, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback) created}
+ * with the appropriate {@link RegionRenderer.GLCallback callbacks}.
+ * </p>
* @param matrix current {@link PMVMatrix}.
- * @param rs the RenderState to be used
- * @param vp_width current screen width
- * @param vp_height current screen height
- * @param texWidth desired texture width for multipass-rendering.
- * The actual used texture-width is written back when mp rendering is enabled, otherwise the store is untouched.
+ * @param renderer the {@link RegionRenderer} to be used
+ * @param sampleCount desired multisampling sample count for msaa-rendering.
+ * The actual used scample-count is written back when msaa-rendering is enabled, otherwise the store is untouched.
+ * @see RegionRenderer#enable(GL2ES2, boolean)
*/
- public final void draw(GL2ES2 gl, RenderState rs, int vp_width, int vp_height, int[/*1*/] texWidth) {
- update(gl, rs);
- drawImpl(gl, rs, vp_width, vp_height, texWidth);
+ public final void draw(final GL2ES2 gl, final RegionRenderer renderer, final int[/*1*/] sampleCount) {
+ if( isShapeDirty() ) {
+ updateImpl(gl);
+ }
+ drawImpl(gl, renderer, sampleCount);
+ clearDirtyBits(DIRTY_SHAPE|DIRTY_STATE);
}
-
- protected abstract void drawImpl(GL2ES2 gl, RenderState rs, int vp_width, int vp_height, int[/*1*/] texWidth);
+
+ protected abstract void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int[/*1*/] sampleCount);
}
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
index 2f078d7bb..a0f54d3b5 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
@@ -27,58 +27,543 @@
*/
package com.jogamp.graph.curve.opengl;
+import java.io.IOException;
+import java.util.Iterator;
+
+import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLES2;
import javax.media.opengl.GLException;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import jogamp.graph.curve.opengl.shader.AttributeNames;
+import jogamp.graph.curve.opengl.shader.UniformNames;
-import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.texture.TextureSequence;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.IntObjectHashMap;
import com.jogamp.graph.curve.Region;
-public abstract class RegionRenderer extends Renderer {
+/**
+ * OpenGL {@link Region} renderer
+ * <p>
+ * All OpenGL related operations regarding {@link Region}s
+ * are passed through an instance of this class.
+ * </p>
+ */
+public class RegionRenderer {
+ protected static final boolean DEBUG = Region.DEBUG;
+ protected static final boolean DEBUG_INSTANCE = Region.DEBUG_INSTANCE;
+
+ /**
+ * May be passed to
+ * {@link RegionRenderer#create(RenderState, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback) RegionRenderer ctor},
+ * e.g.
+ * <ul>
+ * <li>{@link RegionRenderer#defaultBlendEnable}</li>
+ * <li>{@link RegionRenderer#defaultBlendDisable}</li>
+ * </ul>
+ */
+ public interface GLCallback {
+ /**
+ * @param gl a current GL object
+ * @param renderer {@link RegionRenderer} calling this method.
+ */
+ void run(GL gl, RegionRenderer renderer);
+ }
+
+ /**
+ * Default {@link GL#GL_BLEND} <i>enable</i> {@link GLCallback},
+ * turning-off depth writing via {@link GL#glDepthMask(boolean)} if {@link RenderState#BITHINT_GLOBAL_DEPTH_TEST_ENABLED} is set
+ * and turning-on the {@link GL#GL_BLEND} state.
+ * <p>
+ * Implementation also sets {@link RegionRenderer#getRenderState() RenderState}'s {@link RenderState#BITHINT_BLENDING_ENABLED blending bit-hint},
+ * which will cause {@link GLRegion#draw(GL2ES2, RegionRenderer, int[]) GLRegion's draw-method}
+ * to set the proper {@link GL#glBlendFuncSeparate(int, int, int, int) blend-function}
+ * and the clear-color to <i>transparent-black</i> in case of {@link Region#isTwoPass(int) multipass} FBO rendering.
+ * </p>
+ * @see #create(RenderState, GLCallback, GLCallback)
+ * @see #enable(GL2ES2, boolean)
+ */
+ public static final GLCallback defaultBlendEnable = new GLCallback() {
+ @Override
+ public void run(final GL gl, final RegionRenderer renderer) {
+ if( renderer.rs.isHintMaskSet(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED) ) {
+ gl.glDepthMask(false);
+ // gl.glDisable(GL.GL_DEPTH_TEST);
+ // gl.glDepthFunc(GL.GL_ALWAYS);
+ }
+ gl.glEnable(GL.GL_BLEND);
+ gl.glBlendEquation(GL.GL_FUNC_ADD); // default
+ renderer.rs.setHintMask(RenderState.BITHINT_BLENDING_ENABLED);
+ }
+ };
+
+ /**
+ * Default {@link GL#GL_BLEND} <i>disable</i> {@link GLCallback},
+ * simply turning-off the {@link GL#GL_BLEND} state
+ * and turning-on depth writing via {@link GL#glDepthMask(boolean)} if {@link RenderState#BITHINT_GLOBAL_DEPTH_TEST_ENABLED} is set.
+ * <p>
+ * Implementation also clears {@link RegionRenderer#getRenderState() RenderState}'s {@link RenderState#BITHINT_BLENDING_ENABLED blending bit-hint}.
+ * </p>
+ * @see #create(RenderState, GLCallback, GLCallback)
+ * @see #enable(GL2ES2, boolean)
+ */
+ public static final GLCallback defaultBlendDisable = new GLCallback() {
+ @Override
+ public void run(final GL gl, final RegionRenderer renderer) {
+ renderer.rs.clearHintMask(RenderState.BITHINT_BLENDING_ENABLED);
+ gl.glDisable(GL.GL_BLEND);
+ if( renderer.rs.isHintMaskSet(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED) ) {
+ // gl.glEnable(GL.GL_DEPTH_TEST);
+ // gl.glDepthFunc(GL.GL_LESS);
+ gl.glDepthMask(true);
+ }
+ }
+ };
- /**
+ /**
* Create a Hardware accelerated Region Renderer.
- * @param rs the used {@link RenderState}
- * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, {@link Region#VBAA_RENDERING_BIT}
+ * <p>
+ * The optional {@link GLCallback}s <code>enableCallback</code> and <code>disableCallback</code>
+ * maybe used to issue certain tasks at {@link #enable(GL2ES2, boolean)}.<br/>
+ * For example, instances {@link #defaultBlendEnable} and {@link #defaultBlendDisable}
+ * can be utilized to enable and disable {@link GL#GL_BLEND}.
+ * </p>
+ * @param rs the used {@link RenderState}
+ * @param enableCallback optional {@link GLCallback}, if not <code>null</code> will be issued at
+ * {@link #init(GL2ES2, int) init(gl)} and {@link #enable(GL2ES2, boolean) enable(gl, true)}.
+ * @param disableCallback optional {@link GLCallback}, if not <code>null</code> will be issued at
+ * {@link #enable(GL2ES2, boolean) enable(gl, false)}.
* @return an instance of Region Renderer
+ * @see #enable(GL2ES2, boolean)
*/
- public static RegionRenderer create(RenderState rs, int renderModes) {
- return new jogamp.graph.curve.opengl.RegionRendererImpl01(rs, renderModes);
+ public static RegionRenderer create(final RenderState rs, final GLCallback enableCallback,
+ final GLCallback disableCallback) {
+ return new RegionRenderer(rs, enableCallback, disableCallback);
}
-
- protected RegionRenderer(RenderState rs, int renderModes) {
- super(rs, renderModes);
+
+ private final RenderState rs;
+
+ private final GLCallback enableCallback;
+ private final GLCallback disableCallback;
+
+ private int vp_width;
+ private int vp_height;
+ private boolean initialized;
+ private boolean vboSupported = false;
+
+ public final boolean isInitialized() { return initialized; }
+
+ /** Return width of current viewport */
+ public final int getWidth() { return vp_width; }
+ /** Return height of current viewport */
+ public final int getHeight() { return vp_height; }
+
+ public final PMVMatrix getMatrix() { return rs.getMatrix(); }
+
+ //////////////////////////////////////
+
+ /**
+ * @param rs the used {@link RenderState}
+ */
+ protected RegionRenderer(final RenderState rs, final GLCallback enableCallback, final GLCallback disableCallback) {
+ this.rs = rs;
+ this.enableCallback = enableCallback;
+ this.disableCallback = disableCallback;
}
-
-
- /** Render an {@link OutlineShape} in 3D space at the position provided
- * the triangles of the shapes will be generated, if not yet generated
- * @param region the OutlineShape to Render.
- * @param position the initial translation of the outlineShape.
- * @param texWidth desired texture width for multipass-rendering.
- * The actual used texture-width is written back when mp rendering is enabled, otherwise the store is untouched.
- * @throws Exception if HwRegionRenderer not initialized
+
+ public final boolean isVBOSupported() { return vboSupported; }
+
+ /**
+ * Initialize shader and bindings for GPU based rendering bound to the given GL object's GLContext
+ * if not initialized yet.
+ * <p>Leaves the renderer enabled, ie ShaderState.</p>
+ * <p>Shall be called by a {@code draw()} method, e.g. {@link RegionRenderer#draw(GL2ES2, Region, int)}</p>
+ *
+ * @param gl referencing the current GLContext to which the ShaderState is bound to
+ * @param renderModes
+ * @throws GLException if initialization failed
*/
- public final void draw(GL2ES2 gl, Region region, float[] position, int[/*1*/] texWidth) {
- if(!isInitialized()) {
- throw new GLException("RegionRenderer: not initialized!");
- }
- if( !areRenderModesCompatible(region) ) {
- throw new GLException("Incompatible render modes, : region modes "+region.getRenderModes()+
- " doesn't contain renderer modes "+this.getRenderModes());
- }
- drawImpl(gl, region, position, texWidth);
+ public final void init(final GL2ES2 gl, final int renderModes) throws GLException {
+ if(initialized){
+ return;
+ }
+ vboSupported = gl.isFunctionAvailable("glGenBuffers") &&
+ gl.isFunctionAvailable("glBindBuffer") &&
+ gl.isFunctionAvailable("glBufferData") &&
+ gl.isFunctionAvailable("glDrawElements") &&
+ gl.isFunctionAvailable("glVertexAttribPointer") &&
+ gl.isFunctionAvailable("glDeleteBuffers");
+
+ if(DEBUG) {
+ System.err.println("TextRendererImpl01: VBO Supported = " + isVBOSupported());
+ }
+
+ if(!vboSupported){
+ throw new GLException("VBO not supported");
+ }
+
+ rs.attachTo(gl);
+
+ if( null != enableCallback ) {
+ enableCallback.run(gl, this);
+ }
+ initialized = true;
+ }
+
+ public final void destroy(final GL2ES2 gl) {
+ if(!initialized){
+ if(DEBUG_INSTANCE) {
+ System.err.println("TextRenderer: Not initialized!");
+ }
+ return;
+ }
+ for(final Iterator<IntObjectHashMap.Entry> i = shaderPrograms.iterator(); i.hasNext(); ) {
+ final ShaderProgram sp = (ShaderProgram) i.next().getValue();
+ sp.destroy(gl);
+ }
+ shaderPrograms.clear();
+ rs.destroy(gl);
+ initialized = false;
}
-
+
+ public final RenderState getRenderState() { return rs; }
+
/**
- * Usually just dispatched the draw call to the Region's draw implementation,
- * e.g. {@link com.jogamp.graph.curve.opengl.GLRegion#draw(GL2ES2, RenderState, int, int, int[]) GLRegion#draw(GL2ES2, RenderState, int, int, int[])}.
+ * Enabling or disabling the {@link #getRenderState() RenderState}'s
+ * {@link RenderState#getShaderProgram() shader program}.
+ * <p>
+ * In case enable and disable {@link GLCallback}s are setup via {@link #create(RenderState, GLCallback, GLCallback)},
+ * they will be called before toggling the shader program.
+ * </p>
+ * @see #create(RenderState, GLCallback, GLCallback)
*/
- protected abstract void drawImpl(GL2ES2 gl, Region region, float[] position, int[] texWidth);
+ public final void enable(final GL2ES2 gl, final boolean enable) {
+ if( enable ) {
+ if( null != enableCallback ) {
+ enableCallback.run(gl, this);
+ }
+ } else {
+ if( null != disableCallback ) {
+ disableCallback.run(gl, this);
+ }
+ }
+ if( !enable ) {
+ final ShaderProgram sp = rs.getShaderProgram();
+ if( null != sp ) {
+ sp.useProgram(gl, false);
+ }
+ }
+ }
+
+ /** No PMVMatrix operation is performed here. PMVMatrix is marked dirty. */
+ public final void reshapeNotify(final int width, final int height) {
+ this.vp_width = width;
+ this.vp_height = height;
+ }
+
+ public final void reshapePerspective(final float angle, final int width, final int height, final float near, final float far) {
+ this.vp_width = width;
+ this.vp_height = height;
+ final float ratio = (float)width/(float)height;
+ final PMVMatrix p = rs.getMatrix();
+ p.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ p.glLoadIdentity();
+ p.gluPerspective(angle, ratio, near, far);
+ }
+
+ public final void reshapeOrtho(final int width, final int height, final float near, final float far) {
+ this.vp_width = width;
+ this.vp_height = height;
+ final PMVMatrix p = rs.getMatrix();
+ p.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ p.glLoadIdentity();
+ p.glOrthof(0, width, 0, height, near, far);
+ }
+
+ //
+ // Shader Management
+ //
+
+ private static final String SHADER_SRC_SUB = "";
+ private static final String SHADER_BIN_SUB = "bin";
+
+ private static String GLSL_USE_COLOR_CHANNEL = "#define USE_COLOR_CHANNEL 1\n";
+ private static String GLSL_USE_COLOR_TEXTURE = "#define USE_COLOR_TEXTURE 1\n";
+ private static String GLSL_DEF_SAMPLE_COUNT = "#define SAMPLE_COUNT ";
+ private static String GLSL_CONST_SAMPLE_COUNT = "const float sample_count = ";
+ private static String GLSL_MAIN_BEGIN = "void main (void)\n{\n";
+ private static final String gcuTexture2D = "gcuTexture2D";
- @Override
- protected void destroyImpl(GL2ES2 gl) {
- // nop
+ private String getVersionedShaderName() {
+ return "curverenderer01";
+ }
+
+ // FIXME: Really required to have sampler2D def. precision ? If not, we can drop getFragmentShaderPrecision(..) and use default ShaderCode ..
+ private static final String es2_precision_fp = "\nprecision mediump float;\nprecision mediump int;\nprecision mediump sampler2D;\n";
+
+ private final String getFragmentShaderPrecision(final GL2ES2 gl) {
+ if( gl.isGLES() ) {
+ return es2_precision_fp;
+ }
+ if( ShaderCode.requiresGL3DefaultPrecision(gl) ) {
+ return ShaderCode.gl3_default_precision_fp;
+ }
+ return null;
+ }
+
+ private static enum ShaderModeSelector1 {
+ /** Pass-1: Curve Simple */
+ PASS1_SIMPLE("curve", "_simple", 0),
+ /** Pass-1: Curve Varying Weight */
+ PASS1_WEIGHT("curve", "_weight", 0),
+ /** Pass-2: MSAA */
+ PASS2_MSAA("msaa", "", 0),
+ /** Pass-2: VBAA Flipquad3, 1 sample */
+ PASS2_VBAA_QUAL0_SAMPLES1("vbaa", "_flipquad3", 1),
+ /** Pass-2: VBAA Flipquad3, 2 samples */
+ PASS2_VBAA_QUAL0_SAMPLES2("vbaa", "_flipquad3", 2),
+ /** Pass-2: VBAA Flipquad3, 4 samples */
+ PASS2_VBAA_QUAL0_SAMPLES4("vbaa", "_flipquad3", 4),
+ /** Pass-2: VBAA Flipquad3, 8 samples */
+ PASS2_VBAA_QUAL0_SAMPLES8("vbaa", "_flipquad3", 8),
+
+ /** Pass-2: VBAA Brute-Force, Odd, 1 samples */
+ PASS2_VBAA_QUAL1_SAMPLES1("vbaa", "_bforce_odd", 1),
+ /** Pass-2: VBAA Brute-Force, Even, 2 samples */
+ PASS2_VBAA_QUAL1_SAMPLES2("vbaa", "_bforce_even", 2),
+ /** Pass-2: VBAA Brute-Force, Odd, 3 samples */
+ PASS2_VBAA_QUAL1_SAMPLES3("vbaa", "_bforce_odd", 3),
+ /** Pass-2: VBAA Brute-Force, Even, 4 samples */
+ PASS2_VBAA_QUAL1_SAMPLES4("vbaa", "_bforce_even", 4),
+ /** Pass-2: VBAA Brute-Force, Odd, 5 samples */
+ PASS2_VBAA_QUAL1_SAMPLES5("vbaa", "_bforce_odd", 5),
+ /** Pass-2: VBAA Brute-Force, Even, 6 samples */
+ PASS2_VBAA_QUAL1_SAMPLES6("vbaa", "_bforce_even", 6),
+ /** Pass-2: VBAA Brute-Force, Odd, 7 samples */
+ PASS2_VBAA_QUAL1_SAMPLES7("vbaa", "_bforce_odd", 7),
+ /** Pass-2: VBAA Brute-Force, Even, 8 samples */
+ PASS2_VBAA_QUAL1_SAMPLES8("vbaa", "_bforce_even", 8);
+
+ public final String tech;
+ public final String sub;
+ public final int sampleCount;
+
+ ShaderModeSelector1(final String tech, final String sub, final int sampleCount) {
+ this.tech = tech;
+ this.sub= sub;
+ this.sampleCount = sampleCount;
+ }
+
+ public static ShaderModeSelector1 selectPass1(final int renderModes) {
+ return Region.hasVariableWeight(renderModes) ? PASS1_WEIGHT : PASS1_SIMPLE;
+ }
+
+ public static ShaderModeSelector1 selectPass2(final int renderModes, final int quality, final int sampleCount) {
+ if( Region.isMSAA(renderModes) ) {
+ return PASS2_MSAA;
+ } else if( Region.isVBAA(renderModes) ) {
+ if( 0 == quality ) {
+ if( sampleCount < 2 ) {
+ return PASS2_VBAA_QUAL0_SAMPLES1;
+ } else if( sampleCount < 4 ) {
+ return PASS2_VBAA_QUAL0_SAMPLES2;
+ } else if( sampleCount < 8 ) {
+ return PASS2_VBAA_QUAL0_SAMPLES4;
+ } else {
+ return PASS2_VBAA_QUAL0_SAMPLES8;
+ }
+ } else {
+ switch( sampleCount ) {
+ case 0: // Fall through intended
+ case 1: return PASS2_VBAA_QUAL1_SAMPLES1;
+ case 2: return PASS2_VBAA_QUAL1_SAMPLES2;
+ case 3: return PASS2_VBAA_QUAL1_SAMPLES3;
+ case 4: return PASS2_VBAA_QUAL1_SAMPLES4;
+ case 5: return PASS2_VBAA_QUAL1_SAMPLES5;
+ case 6: return PASS2_VBAA_QUAL1_SAMPLES6;
+ case 7: return PASS2_VBAA_QUAL1_SAMPLES7;
+ default: return PASS2_VBAA_QUAL1_SAMPLES8;
+ }
+ }
+ } else {
+ return null;
+ }
+ }
+ }
+ private final IntObjectHashMap shaderPrograms = new IntObjectHashMap();
+
+ private static final int HIGH_MASK = Region.COLORCHANNEL_RENDERING_BIT | Region.COLORTEXTURE_RENDERING_BIT;
+ private static final int TWO_PASS_BIT = 1 << 31;
+
+ /**
+ * @param gl
+ * @param renderModes
+ * @param pass1
+ * @param quality
+ * @param sampleCount
+ * @param colorTexSeq
+ * @return true if a new shader program is being used and hence external uniform-data and -location,
+ * as well as the attribute-location must be updated, otherwise false.
+ */
+ public final boolean useShaderProgram(final GL2ES2 gl, final int renderModes,
+ final boolean pass1, final int quality, final int sampleCount, final TextureSequence colorTexSeq) {
+ final int colorTexSeqHash;
+ if( null != colorTexSeq ) {
+ colorTexSeqHash = colorTexSeq.getTextureFragmentShaderHashCode();
+ } else {
+ colorTexSeqHash = 0;
+ }
+ final ShaderModeSelector1 sel1 = pass1 ? ShaderModeSelector1.selectPass1(renderModes) :
+ ShaderModeSelector1.selectPass2(renderModes, quality, sampleCount);
+ final boolean isTwoPass = Region.isTwoPass( renderModes );
+ final boolean isPass1ColorTexSeq = pass1 && null != colorTexSeq;
+ final int shaderKey = ( (colorTexSeqHash << 5) - colorTexSeqHash ) +
+ ( sel1.ordinal() | ( HIGH_MASK & renderModes ) | ( isTwoPass ? TWO_PASS_BIT : 0 ) );
+
+ /**
+ if(DEBUG) {
+ System.err.printf("RegionRendererImpl01.useShaderProgram.0: renderModes %s, sel1 %s, key 0x%X (pass1 %b, q %d, samples %d) - Thread %s%n",
+ Region.getRenderModeString(renderModes), sel1, shaderKey, pass1, quality, sampleCount, Thread.currentThread());
+ } */
+
+ ShaderProgram sp = (ShaderProgram) shaderPrograms.get( shaderKey );
+ if( null != sp ) {
+ final boolean spChanged = getRenderState().setShaderProgram(gl, sp);
+ if(DEBUG) {
+ if( spChanged ) {
+ System.err.printf("RegionRendererImpl01.useShaderProgram.X1: GOT renderModes %s, sel1 %s, key 0x%X -> sp %d / %d (changed)%n", Region.getRenderModeString(renderModes), sel1, shaderKey, sp.program(), sp.id());
+ } else {
+ System.err.printf("RegionRendererImpl01.useShaderProgram.X1: GOT renderModes %s, sel1 %s, key 0x%X -> sp %d / %d (keep)%n", Region.getRenderModeString(renderModes), sel1, shaderKey, sp.program(), sp.id());
+ }
+ }
+ return spChanged;
+ }
+ final String versionedBaseName = getVersionedShaderName();
+ final String vertexShaderName;
+ if( isTwoPass ) {
+ vertexShaderName = versionedBaseName+"-pass"+(pass1?1:2);
+ } else {
+ vertexShaderName = versionedBaseName+"-single";
+ }
+ final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, AttributeNames.class, SHADER_SRC_SUB, SHADER_BIN_SUB, vertexShaderName, true);
+ final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, AttributeNames.class, SHADER_SRC_SUB, SHADER_BIN_SUB, versionedBaseName+"-segment-head", true);
+
+ if( isPass1ColorTexSeq && GLES2.GL_TEXTURE_EXTERNAL_OES == colorTexSeq.getTextureTarget() ) {
+ if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) {
+ throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available");
+ }
+ }
+ boolean supressGLSLVersionES30 = false;
+ if( isPass1ColorTexSeq && GLES2.GL_TEXTURE_EXTERNAL_OES == colorTexSeq.getTextureTarget() ) {
+ if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) {
+ // Bug on Nexus 10, ES3 - Android 4.3, where
+ // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' !
+ // P0003: Extension 'GL_OES_EGL_image_external' not supported
+ supressGLSLVersionES30 = true;
+ }
+ }
+ //
+ // GLSL customization at top
+ //
+ int posVp = rsVp.defaultShaderCustomization(gl, !supressGLSLVersionES30, true);
+ // rsFp.defaultShaderCustomization(gl, true, true);
+ int posFp = supressGLSLVersionES30 ? 0 : rsFp.addGLSLVersion(gl);
+ if( isPass1ColorTexSeq ) {
+ posFp = rsFp.insertShaderSource(0, posFp, colorTexSeq.getRequiredExtensionsShaderStub());
+ }
+ if( pass1 && supressGLSLVersionES30 || ( gl.isGLES2() && !gl.isGLES3() ) ) {
+ posFp = rsFp.insertShaderSource(0, posFp, ShaderCode.createExtensionDirective(GLExtensions.OES_standard_derivatives, ShaderCode.ENABLE));
+ }
+ if( false ) {
+ final String rsFpDefPrecision = getFragmentShaderPrecision(gl);
+ if( null != rsFpDefPrecision ) {
+ posFp = rsFp.insertShaderSource(0, posFp, rsFpDefPrecision);
+ }
+ } else {
+ posFp = rsFp.addDefaultShaderPrecision(gl, posFp);
+ }
+
+ //
+ // GLSL append from here on
+ posFp = -1;
+
+ if( Region.hasColorChannel( renderModes ) ) {
+ posVp = rsVp.insertShaderSource(0, posVp, GLSL_USE_COLOR_CHANNEL);
+ posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_COLOR_CHANNEL);
+ }
+ if( Region.hasColorTexture( renderModes ) ) {
+ rsVp.insertShaderSource(0, posVp, GLSL_USE_COLOR_TEXTURE);
+ posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_COLOR_TEXTURE);
+ }
+ if( !pass1 ) {
+ posFp = rsFp.insertShaderSource(0, posFp, GLSL_DEF_SAMPLE_COUNT+sel1.sampleCount+"\n");
+ posFp = rsFp.insertShaderSource(0, posFp, GLSL_CONST_SAMPLE_COUNT+sel1.sampleCount+".0;\n");
+ }
+
+ try {
+ posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "uniforms.glsl");
+ posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "varyings.glsl");
+ } catch (final IOException ioe) {
+ throw new RuntimeException("Failed to read: includes", ioe);
+ }
+ if( 0 > posFp ) {
+ throw new RuntimeException("Failed to read: includes");
+ }
+
+ final String texLookupFuncName;
+ if( isPass1ColorTexSeq ) {
+ posFp = rsFp.insertShaderSource(0, posFp, "uniform "+colorTexSeq.getTextureSampler2DType()+" "+UniformNames.gcu_ColorTexUnit+";\n");
+ texLookupFuncName = colorTexSeq.getTextureLookupFunctionName(gcuTexture2D);
+ posFp = rsFp.insertShaderSource(0, posFp, colorTexSeq.getTextureLookupFragmentShaderImpl());
+ } else {
+ texLookupFuncName = null;
+ }
+
+ posFp = rsFp.insertShaderSource(0, posFp, GLSL_MAIN_BEGIN);
+
+ final String passS = pass1 ? "-pass1-" : "-pass2-";
+ final String shaderSegment = versionedBaseName+passS+sel1.tech+sel1.sub+".glsl";
+ if(DEBUG) {
+ System.err.printf("RegionRendererImpl01.useShaderProgram.1: segment %s%n", shaderSegment);
+ }
+ try {
+ posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, shaderSegment);
+ } catch (final IOException ioe) {
+ throw new RuntimeException("Failed to read: "+shaderSegment, ioe);
+ }
+ if( 0 > posFp ) {
+ throw new RuntimeException("Failed to read: "+shaderSegment);
+ }
+ posFp = rsFp.insertShaderSource(0, posFp, "}\n");
+
+ if( isPass1ColorTexSeq ) {
+ rsFp.replaceInShaderSource(gcuTexture2D, texLookupFuncName);
+ }
+
+ sp = new ShaderProgram();
+ sp.add(rsVp);
+ sp.add(rsFp);
+
+ if( !sp.init(gl) ) {
+ throw new GLException("RegionRenderer: Couldn't init program: "+sp);
+ }
+
+ if( !sp.link(gl, System.err) ) {
+ throw new GLException("could not link program: "+sp);
+ }
+ getRenderState().setShaderProgram(gl, sp);
+
+ shaderPrograms.put(shaderKey, sp);
+ if(DEBUG) {
+ System.err.printf("RegionRendererImpl01.useShaderProgram.X1: PUT renderModes %s, sel1 %s, key 0x%X -> sp %d / %d (changed)%n",
+ Region.getRenderModeString(renderModes), sel1, shaderKey, sp.program(), sp.id());
+ }
+ return true;
}
-
-
-}
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
index eb07142a3..6ff9bf9cd 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
@@ -27,85 +27,326 @@
*/
package com.jogamp.graph.curve.opengl;
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLException;
import javax.media.opengl.GLUniformData;
-import jogamp.graph.curve.opengl.RenderStateImpl;
+import jogamp.common.os.PlatformPropsImpl;
import jogamp.graph.curve.opengl.shader.UniformNames;
import com.jogamp.common.os.Platform;
+import com.jogamp.graph.curve.Region;
import com.jogamp.graph.geom.Vertex;
+import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
-import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
-public abstract class RenderState {
+public class RenderState {
private static final String thisKey = "jogamp.graph.curve.RenderState" ;
-
- public static RenderState createRenderState(ShaderState st, Vertex.Factory<? extends Vertex> pointFactory) {
- return new RenderStateImpl(st, pointFactory);
+
+ /**
+ * Bitfield hint, {@link #isHintMaskSet(int) if set}
+ * stating <i>enabled</i> {@link GL#GL_BLEND}, otherwise <i>disabled</i>.
+ * <p>
+ * Shall be set via {@link #setHintMask(int)} and cleared via {@link #clearHintMask(int)}.
+ * </p>
+ * <p>
+ * If set, {@link GLRegion#draw(GL2ES2, RegionRenderer, int[]) GLRegion's draw-method}
+ * will set the proper {@link GL#glBlendFuncSeparate(int, int, int, int) blend-function}
+ * and the clear-color to <i>transparent-black</i> in case of {@link Region#isTwoPass(int) multipass} FBO rendering.
+ * </p>
+ * <p>
+ * Shall be set by custom code, e.g. via {@link RegionRenderer}'s
+ * enable and disable {@link RegionRenderer.GLCallback} as done in
+ * {@link RegionRenderer#defaultBlendEnable} and {@link RegionRenderer#defaultBlendDisable}.
+ * </p>
+ */
+ public static final int BITHINT_BLENDING_ENABLED = 1 << 0 ;
+
+ /**
+ * Bitfield hint, {@link #isHintMaskSet(int) if set}
+ * stating globally <i>enabled</i> {@link GL#GL_DEPTH_TEST}, otherwise <i>disabled</i>.
+ * <p>
+ * Shall be set via {@link #setHintMask(int)} and cleared via {@link #clearHintMask(int)}.
+ * </p>
+ * <p>
+ * {@link GLRegion#draw(GL2ES2, RegionRenderer, int[]) GLRegion's draw-method}
+ * may toggle depth test, and reset it's state according to this hint.
+ * </p>
+ * <p>
+ * Shall be set by custom code, e.g. after {@link RenderState} or {@link RegionRenderer} construction.
+ * </p>
+ */
+ public static final int BITHINT_GLOBAL_DEPTH_TEST_ENABLED = 1 << 1 ;
+
+ public static RenderState createRenderState(final Vertex.Factory<? extends Vertex> pointFactory) {
+ return new RenderState(pointFactory, null);
}
- public static RenderState createRenderState(ShaderState st, Vertex.Factory<? extends Vertex> pointFactory, PMVMatrix pmvMatrix) {
- return new RenderStateImpl(st, pointFactory, pmvMatrix);
+ public static RenderState createRenderState(final Vertex.Factory<? extends Vertex> pointFactory, final PMVMatrix pmvMatrix) {
+ return new RenderState(pointFactory, pmvMatrix);
}
-
- public static final RenderState getRenderState(GL2ES2 gl) {
+
+ public static final RenderState getRenderState(final GL2ES2 gl) {
return (RenderState) gl.getContext().getAttachedObject(thisKey);
}
-
- protected final ShaderState st;
- protected final Vertex.Factory<? extends Vertex> vertexFactory;
- protected final PMVMatrix pmvMatrix;
- protected final GLUniformData gcu_PMVMatrix;
-
- protected RenderState(ShaderState st, Vertex.Factory<? extends Vertex> vertexFactory, PMVMatrix pmvMatrix) {
- this.st = st;
+
+ private final Vertex.Factory<? extends Vertex> vertexFactory;
+ private final PMVMatrix pmvMatrix;
+ private final float[] weight;
+ private final FloatBuffer weightBuffer;
+ private final float[] colorStatic;
+ private final FloatBuffer colorStaticBuffer;
+ private ShaderProgram sp;
+ private int hintBitfield;
+
+ private final int id;
+ private static synchronized int getNextID() {
+ return nextID++;
+ }
+ private static int nextID = 1;
+
+ /**
+ * Representation of {@link RenderState} data for one {@link ShaderProgram}
+ * as {@link GLUniformData}.
+ * <p>
+ * FIXME: Utilize 'ARB_Uniform_Buffer_Object' where available!
+ * </p>
+ */
+ public static class ProgramLocal {
+ public final GLUniformData gcu_PMVMatrix01;
+ public final GLUniformData gcu_Weight;
+ public final GLUniformData gcu_ColorStatic;
+ private int rsId = -1;
+
+ public ProgramLocal() {
+ gcu_PMVMatrix01 = GLUniformData.creatEmptyMatrix(UniformNames.gcu_PMVMatrix01, 4, 4);
+ gcu_Weight = GLUniformData.creatEmptyVector(UniformNames.gcu_Weight, 1);
+ gcu_ColorStatic = GLUniformData.creatEmptyVector(UniformNames.gcu_ColorStatic, 4);
+ }
+
+ public final int getRenderStateId() { return rsId; }
+
+ /**
+ * <p>
+ * Since {@link RenderState} data is being used in multiple
+ * {@link ShaderProgram}s the data must always be written.
+ * </p>
+ * @param gl
+ * @param updateLocation
+ * @param renderModes
+ * @param throwOnError TODO
+ * @return true if no error occurred, i.e. all locations found, otherwise false.
+ */
+ public final boolean update(final GL2ES2 gl, final RenderState rs, final boolean updateLocation, final int renderModes, final boolean pass1, final boolean throwOnError) {
+ if( rs.id() != rsId ) {
+ gcu_PMVMatrix01.setData(rs.pmvMatrix.glGetPMvMatrixf());
+ gcu_Weight.setData(rs.weightBuffer);
+ gcu_ColorStatic.setData(rs.colorStaticBuffer);
+ rsId = rs.id();
+ }
+ boolean res = true;
+ if( null != rs.sp && rs.sp.inUse() ) {
+ if( !Region.isTwoPass(renderModes) || !pass1 ) {
+ final boolean r0 = rs.updateUniformDataLoc(gl, updateLocation, true, gcu_PMVMatrix01, throwOnError);
+ res = res && r0;
+ }
+ if( pass1 ) {
+ if( Region.hasVariableWeight( renderModes ) ) {
+ final boolean r0 = rs.updateUniformDataLoc(gl, updateLocation, true, gcu_Weight, throwOnError);
+ res = res && r0;
+ }
+ {
+ final boolean r0 = rs.updateUniformDataLoc(gl, updateLocation, true, gcu_ColorStatic, throwOnError);
+ res = res && r0;
+ }
+ }
+ }
+ return res;
+ }
+
+ public StringBuilder toString(StringBuilder sb, final boolean alsoUnlocated) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("ProgramLocal[rsID ").append(rsId).append(PlatformPropsImpl.NEWLINE);
+ // pmvMatrix.toString(sb, "%.2f");
+ sb.append(gcu_PMVMatrix01).append(", ").append(PlatformPropsImpl.NEWLINE);
+ sb.append(gcu_ColorStatic).append(", ");
+ sb.append(gcu_Weight).append("]");
+ return sb;
+ }
+
+ @Override
+ public String toString() {
+ return toString(null, false).toString();
+ }
+ }
+
+ protected RenderState(final Vertex.Factory<? extends Vertex> vertexFactory, final PMVMatrix pmvMatrix) {
+ this.id = getNextID();
+ this.sp = null;
this.vertexFactory = vertexFactory;
- this.pmvMatrix = pmvMatrix;
- this.gcu_PMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, pmvMatrix.glGetPMvMatrixf());
- st.ownUniform(gcu_PMVMatrix);
+ this.pmvMatrix = null != pmvMatrix ? pmvMatrix : new PMVMatrix();
+ this.weight = new float[1];
+ this.weightBuffer = FloatBuffer.wrap(weight);
+ this.colorStatic = new float[4];
+ this.colorStaticBuffer = FloatBuffer.wrap(colorStatic);
+ this.hintBitfield = 0;
+ }
+
+ public final int id() { return id; }
+ public final ShaderProgram getShaderProgram() { return sp; }
+ public final boolean isShaderProgramInUse() { return null != sp ? sp.inUse() : false; }
+
+ /**
+ * Set a {@link ShaderProgram} and enable it. If the given {@link ShaderProgram} is new,
+ * method returns true, otherwise false.
+ * @param gl
+ * @param spNext
+ * @return true if a new shader program is being used and hence external uniform-data and -location,
+ * as well as the attribute-location must be updated, otherwise false.
+ */
+ public final boolean setShaderProgram(final GL2ES2 gl, final ShaderProgram spNext) {
+ if( spNext.equals(this.sp) ) {
+ spNext.useProgram(gl, true);
+ return false;
+ }
+ if( null != this.sp ) {
+ this.sp.notifyNotInUse();
+ }
+ this.sp = spNext;
+ spNext.useProgram(gl, true);
+ return true;
}
-
- public final ShaderState getShaderState() { return st; }
+
public final Vertex.Factory<? extends Vertex> getVertexFactory() { return vertexFactory; }
- public final PMVMatrix pmvMatrix() { return pmvMatrix; }
- public final GLUniformData getPMVMatrix() { return gcu_PMVMatrix; }
-
- public void destroy(GL2ES2 gl) {
- st.destroy(gl);
- }
-
- public abstract GLUniformData getWeight();
- public abstract GLUniformData getAlpha();
- public abstract GLUniformData getColorStatic();
- // public abstract GLUniformData getStrength();
-
- public final RenderState attachTo(GL2ES2 gl) {
+
+ public final PMVMatrix getMatrix() { return pmvMatrix; }
+
+ public static boolean isWeightValid(final float v) {
+ return 0.0f <= v && v <= 1.9f ;
+ }
+ public final float getWeight() { return weight[0]; }
+ public final void setWeight(final float v) {
+ if( !isWeightValid(v) ) {
+ throw new IllegalArgumentException("Weight out of range");
+ }
+ weight[0] = v;
+ }
+
+
+ public final float[] getColorStatic(final float[] rgbaColor) {
+ System.arraycopy(colorStatic, 0, rgbaColor, 0, 4);
+ return rgbaColor;
+ }
+ public final void setColorStatic(final float r, final float g, final float b, final float a){
+ colorStatic[0] = r;
+ colorStatic[1] = g;
+ colorStatic[2] = b;
+ colorStatic[3] = a;
+ }
+
+
+ /**
+ *
+ * @param gl
+ * @param updateLocation
+ * @param data
+ * @param throwOnError TODO
+ * @return true if no error occured, i.e. all locations found, otherwise false.
+ */
+ public final boolean updateUniformLoc(final GL2ES2 gl, final boolean updateLocation, final GLUniformData data, final boolean throwOnError) {
+ if( updateLocation || 0 > data.getLocation() ) {
+ final boolean ok = 0 <= data.setLocation(gl, sp.program());
+ if( throwOnError && !ok ) {
+ throw new GLException("Could not locate "+data);
+ }
+ return ok;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ *
+ * @param gl
+ * @param updateLocation
+ * @param updateData TODO
+ * @param data
+ * @param throwOnError TODO
+ * @return true if no error occured, i.e. all locations found, otherwise false.
+ */
+ public final boolean updateUniformDataLoc(final GL2ES2 gl, boolean updateLocation, boolean updateData, final GLUniformData data, final boolean throwOnError) {
+ updateLocation = updateLocation || 0 > data.getLocation();
+ if( updateLocation ) {
+ updateData = 0 <= data.setLocation(gl, sp.program());
+ if( throwOnError && !updateData ) {
+ throw new GLException("Could not locate "+data);
+ }
+ }
+ if( updateData ){
+ gl.glUniform(data);
+ return true;
+ } else {
+ return !updateLocation;
+ }
+ }
+
+ /**
+ * @param gl
+ * @param data
+ * @param throwOnError TODO
+ * @return true if no error occured, i.e. all locations found, otherwise false.
+ */
+ public final boolean updateAttributeLoc(final GL2ES2 gl, final boolean updateLocation, final GLArrayDataServer data, final boolean throwOnError) {
+ if( updateLocation || 0 > data.getLocation() ) {
+ final boolean ok = 0 <= data.setLocation(gl, sp.program());
+ if( throwOnError && !ok ) {
+ throw new GLException("Could not locate "+data);
+ }
+ return ok;
+ } else {
+ return true;
+ }
+ }
+
+
+ public final boolean isHintMaskSet(final int mask) {
+ return mask == ( hintBitfield & mask );
+ }
+ public final void setHintMask(final int mask) {
+ hintBitfield |= mask;
+ }
+ public final void clearHintMask(final int mask) {
+ hintBitfield &= ~mask;
+ }
+
+ public void destroy(final GL2ES2 gl) {
+ if( null != sp ) {
+ sp.destroy(gl);
+ sp = null;
+ }
+ }
+
+ public final RenderState attachTo(final GL2ES2 gl) {
return (RenderState) gl.getContext().attachObject(thisKey, this);
}
-
- public final boolean detachFrom(GL2ES2 gl) {
- RenderState _rs = (RenderState) gl.getContext().getAttachedObject(thisKey);
+
+ public final boolean detachFrom(final GL2ES2 gl) {
+ final RenderState _rs = (RenderState) gl.getContext().getAttachedObject(thisKey);
if(_rs == this) {
gl.getContext().detachObject(thisKey);
return true;
}
return false;
- }
-
- public StringBuilder toString(StringBuilder sb) {
- if(null==sb) {
- sb = new StringBuilder();
- }
-
- sb.append("RenderState[");
- st.toString(sb).append(Platform.getNewline());
- sb.append("]");
-
- return sb;
}
-
+
+ @Override
public String toString() {
- return toString(null).toString();
- }
+ return "RenderState["+sp+"]";
+ }
}
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
deleted file mode 100644
index 3c23733a5..000000000
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.graph.curve.opengl;
-
-import java.nio.FloatBuffer;
-
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLException;
-import javax.media.opengl.fixedfunc.GLMatrixFunc;
-
-import com.jogamp.opengl.util.glsl.ShaderState;
-import com.jogamp.opengl.util.PMVMatrix;
-
-import com.jogamp.graph.curve.Region;
-
-public abstract class Renderer {
- protected static final boolean DEBUG = Region.DEBUG;
- protected static final boolean DEBUG_INSTANCE = Region.DEBUG_INSTANCE;
-
- public static boolean isWeightValid(float v) {
- return 0.0f <= v && v <= 1.9f ;
- }
-
- protected final int renderModes;
- protected int vp_width;
- protected int vp_height;
- protected boolean initialized;
- protected final RenderState rs;
- private boolean vboSupported = false;
-
- public final boolean isInitialized() { return initialized; }
-
- public final int getWidth() { return vp_width; }
- public final int getHeight() { return vp_height; }
-
- public float getWeight() { return rs.getWeight().floatValue(); }
- public float getAlpha() { return rs.getAlpha().floatValue(); }
- public final PMVMatrix getMatrix() { return rs.pmvMatrix(); }
-
- /**
- * Implementation shall load, compile and link the shader program and leave it active.
- * @param gl referencing the current GLContext to which the ShaderState is bound to
- * @return
- */
- protected abstract boolean initShaderProgram(GL2ES2 gl);
-
- protected abstract void destroyImpl(GL2ES2 gl);
-
- /**
- * @param rs the used {@link RenderState}
- * @param renderModes bit-field of modes
- */
- protected Renderer(RenderState rs, int renderModes) {
- this.rs = rs;
- this.renderModes = renderModes;
- }
-
- public final int getRenderModes() {
- return renderModes;
- }
-
- public boolean usesVariableCurveWeight() { return Region.isNonUniformWeight(renderModes); }
-
- /**
- * @return true if Region's renderModes contains all bits as this Renderer's renderModes
- * except {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, otherwise false.
- */
- public final boolean areRenderModesCompatible(Region region) {
- final int cleanRenderModes = getRenderModes() & ( Region.VARIABLE_CURVE_WEIGHT_BIT );
- return cleanRenderModes == ( region.getRenderModes() & cleanRenderModes );
- }
-
- public final boolean isVBOSupported() { return vboSupported; }
-
- /**
- * Initialize shader and bindings for GPU based rendering bound to the given GL object's GLContext
- * if not initialized yet.
- * <p>Leaves the renderer enabled, ie ShaderState.</p>
- * <p>Shall be called by a {@code draw()} method, e.g. {@link RegionRenderer#draw(GL2ES2, Region, float[], int)}</p>
- *
- * @param gl referencing the current GLContext to which the ShaderState is bound to
- * @throws GLException if initialization failed
- */
- public final void init(GL2ES2 gl) throws GLException {
- if(initialized){
- return;
- }
- vboSupported = gl.isFunctionAvailable("glGenBuffers") &&
- gl.isFunctionAvailable("glBindBuffer") &&
- gl.isFunctionAvailable("glBufferData") &&
- gl.isFunctionAvailable("glDrawElements") &&
- gl.isFunctionAvailable("glVertexAttribPointer") &&
- gl.isFunctionAvailable("glDeleteBuffers");
-
- if(DEBUG) {
- System.err.println("TextRendererImpl01: VBO Supported = " + isVBOSupported());
- }
-
- if(!vboSupported){
- throw new GLException("VBO not supported");
- }
-
- rs.attachTo(gl);
-
- gl.glEnable(GL2ES2.GL_BLEND);
- gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); // FIXME: alpha blending stage ?
-
- initialized = initShaderProgram(gl);
- if(!initialized) {
- throw new GLException("Shader initialization failed");
- }
-
- if(!rs.getShaderState().uniform(gl, rs.getPMVMatrix())) {
- throw new GLException("Error setting PMVMatrix in shader: "+rs.getShaderState());
- }
-
- if(!rs.getShaderState().uniform(gl, rs.getWeight())) {
- throw new GLException("Error setting weight in shader: "+rs.getShaderState());
- }
-
- if(!rs.getShaderState().uniform(gl, rs.getAlpha())) {
- throw new GLException("Error setting global alpha in shader: "+rs.getShaderState());
- }
-
- if(!rs.getShaderState().uniform(gl, rs.getColorStatic())) {
- throw new GLException("Error setting global color in shader: "+rs.getShaderState());
- }
- }
-
- public final void flushCache(GL2ES2 gl) {
- // FIXME: REMOVE !
- }
-
- public void destroy(GL2ES2 gl) {
- if(!initialized){
- if(DEBUG_INSTANCE) {
- System.err.println("TextRenderer: Not initialized!");
- }
- return;
- }
- rs.getShaderState().useProgram(gl, false);
- destroyImpl(gl);
- rs.destroy(gl);
- initialized = false;
- }
-
- public final RenderState getRenderState() { return rs; }
- public final ShaderState getShaderState() { return rs.getShaderState(); }
-
- public final void enable(GL2ES2 gl, boolean enable) {
- rs.getShaderState().useProgram(gl, enable);
- }
-
- public void setWeight(GL2ES2 gl, float v) {
- if( !isWeightValid(v) ) {
- throw new IllegalArgumentException("Weight out of range");
- }
- rs.getWeight().setData(v);
- if(null != gl && rs.getShaderState().inUse()) {
- rs.getShaderState().uniform(gl, rs.getWeight());
- }
- }
-
- public void setAlpha(GL2ES2 gl, float alpha_t) {
- rs.getAlpha().setData(alpha_t);
- if(null != gl && rs.getShaderState().inUse()) {
- rs.getShaderState().uniform(gl, rs.getAlpha());
- }
-
- }
-
- public void getColorStatic(GL2ES2 gl, float[] rgb) {
- FloatBuffer fb = (FloatBuffer) rs.getColorStatic().getBuffer();
- rgb[0] = fb.get(0);
- rgb[1] = fb.get(1);
- rgb[2] = fb.get(2);
- }
-
- public void setColorStatic(GL2ES2 gl, float r, float g, float b){
- FloatBuffer fb = (FloatBuffer) rs.getColorStatic().getBuffer();
- fb.put(0, r);
- fb.put(1, g);
- fb.put(2, b);
- if(null != gl && rs.getShaderState().inUse()) {
- rs.getShaderState().uniform(gl, rs.getColorStatic());
- }
- }
-
- public void rotate(GL2ES2 gl, float angle, float x, float y, float z) {
- rs.pmvMatrix().glRotatef(angle, x, y, z);
- updateMatrix(gl);
- }
-
- public void translate(GL2ES2 gl, float x, float y, float z) {
- rs.pmvMatrix().glTranslatef(x, y, z);
- updateMatrix(gl);
- }
-
- public void scale(GL2ES2 gl, float x, float y, float z) {
- rs.pmvMatrix().glScalef(x, y, z);
- updateMatrix(gl);
- }
-
- public void resetModelview(GL2ES2 gl) {
- rs.pmvMatrix().glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
- rs.pmvMatrix().glLoadIdentity();
- updateMatrix(gl);
- }
-
- public void updateMatrix(GL2ES2 gl) {
- if(initialized && null != gl && rs.getShaderState().inUse()) {
- rs.getShaderState().uniform(gl, rs.getPMVMatrix());
- }
- }
-
- public boolean reshapePerspective(GL2ES2 gl, float angle, int width, int height, float near, float far) {
- this.vp_width = width;
- this.vp_height = height;
- final float ratio = (float)width/(float)height;
- final PMVMatrix p = rs.pmvMatrix();
- p.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
- p.glLoadIdentity();
- p.gluPerspective(angle, ratio, near, far);
- updateMatrix(gl);
- return true;
- }
-
- public boolean reshapeOrtho(GL2ES2 gl, int width, int height, float near, float far) {
- this.vp_width = width;
- this.vp_height = height;
- final PMVMatrix p = rs.pmvMatrix();
- p.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
- p.glLoadIdentity();
- p.glOrthof(0, width, 0, height, near, far);
- updateMatrix(gl);
- return true;
- }
-
- protected String getVertexShaderName(GL2ES2 gl) {
- return "curverenderer01" + getShaderGLVersionSuffix(gl);
- }
-
- protected String getFragmentShaderName(GL2ES2 gl) {
- final String type = "01" ; // Region.isNonUniformWeight(renderModes) ? "02" : "01" ;
- final String pass = Region.isVBAA(renderModes) ? "b" : "a" ;
- return "curverenderer" + type + pass + getShaderGLVersionSuffix(gl);
- }
-
- protected String getShaderGLVersionSuffix(GL2ES2 gl) {
- if(gl.isGLES2()) {
- return "-es2";
- }
- return "-gl2";
- }
-
-} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
new file mode 100644
index 000000000..0fa1f49f1
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
@@ -0,0 +1,351 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.graph.curve.opengl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLException;
+
+import jogamp.graph.geom.plane.AffineTransform;
+
+import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.Font.Glyph;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
+
+/**
+ * Text {@link GLRegion} Utility Class
+ */
+public class TextRegionUtil {
+
+ public final int renderModes;
+
+ public TextRegionUtil(final int renderModes) {
+ this.renderModes = renderModes;
+ }
+
+ public static interface ShapeVisitor {
+ /**
+ * Visiting the given {@link OutlineShape} with it's corresponding {@link AffineTransform}.
+ * @param shape may be used as is, otherwise a copy shall be made if intended to be modified.
+ * @param t may be used immediately as is, otherwise a copy shall be made if stored.
+ */
+ public void visit(final OutlineShape shape, final AffineTransform t);
+ }
+
+ public static int getCharCount(final String s, final char c) {
+ final int sz = s.length();
+ int count = 0;
+ for(int i=0; i<sz; i++) {
+ if( s.charAt(i) == c ) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Visit each {@link Font.Glyph}'s {@link OutlineShape} with the given {@link ShapeVisitor}
+ * additionally passing the progressed {@link AffineTransform}.
+ * The latter reflects the given font metric, pixelSize and hence character position.
+ * @param visitor
+ * @param transform optional given transform
+ * @param font the target {@link Font}
+ * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
+ * @param str string text
+ * @param temp1 temporary AffineTransform storage, mandatory, will be passed to {@link ShapeVisitor#visit(OutlineShape, AffineTransform)} and can be modified.
+ * @param temp2 temporary AffineTransform storage, mandatory, can be re-used in {@link ShapeVisitor#visit(OutlineShape, AffineTransform)} by user code.
+ */
+ public static void processString(final ShapeVisitor visitor, final AffineTransform transform,
+ final Font font, final float pixelSize, final CharSequence str,
+ final AffineTransform temp1, final AffineTransform temp2) {
+ final int charCount = str.length();
+
+ // region.setFlipped(true);
+ final Font.Metrics metrics = font.getMetrics();
+ final float lineHeight = font.getLineHeight(pixelSize);
+
+ final float scale = metrics.getScale(pixelSize);
+
+ float y = 0;
+ float advanceTotal = 0;
+
+ for(int i=0; i< charCount; i++) {
+ final char character = str.charAt(i);
+ if( '\n' == character ) {
+ y -= lineHeight;
+ advanceTotal = 0;
+ } else if (character == ' ') {
+ advanceTotal += font.getAdvanceWidth(Glyph.ID_SPACE, pixelSize);
+ } else {
+ if(Region.DEBUG_INSTANCE) {
+ System.err.println("XXXXXXXXXXXXXXx char: "+character+", scale: "+scale+"; translate: "+advanceTotal+", "+y);
+ }
+ // reset transform
+ if( null != transform ) {
+ temp1.setTransform(transform);
+ } else {
+ temp1.setToIdentity();
+ }
+ temp1.translate(advanceTotal, y, temp2);
+ temp1.scale(scale, scale, temp2);
+
+ final Font.Glyph glyph = font.getGlyph(character);
+ final OutlineShape glyphShape = glyph.getShape();
+ if( null == glyphShape ) {
+ continue;
+ }
+ visitor.visit(glyphShape, temp1);
+
+ advanceTotal += glyph.getAdvance(pixelSize, true);
+ }
+ }
+ }
+
+ /**
+ * Add the string in 3D space w.r.t. the font and pixelSize at the end of the {@link GLRegion}.
+ * @param region the {@link GLRegion} sink
+ * @param vertexFactory vertex impl factory {@link Factory}
+ * @param font the target {@link Font}
+ * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
+ * @param str string text
+ * @param rgbaColor if {@link Region#hasColorChannel()} RGBA color must be passed, otherwise value is ignored.
+ * @param temp1 temporary AffineTransform storage, mandatory
+ * @param temp2 temporary AffineTransform storage, mandatory
+ */
+ public static void addStringToRegion(final GLRegion region, final Factory<? extends Vertex> vertexFactory,
+ final Font font, final float pixelSize, final CharSequence str, final float[] rgbaColor,
+ final AffineTransform temp1, final AffineTransform temp2) {
+ final ShapeVisitor visitor = new ShapeVisitor() {
+ public final void visit(final OutlineShape shape, final AffineTransform t) {
+ region.addOutlineShape(shape, t, region.hasColorChannel() ? rgbaColor : null);
+ } };
+ processString(visitor, null, font, pixelSize, str, temp1, temp2);
+ }
+
+ /**
+ * Render the string in 3D space w.r.t. the font and pixelSize
+ * using a cached {@link GLRegion} for reuse.
+ * <p>
+ * Cached {@link GLRegion}s will be destroyed w/ {@link #clear(GL2ES2)} or to free memory.
+ * </p>
+ * @param gl the current GL state
+ * @param renderer TODO
+ * @param font {@link Font} to be used
+ * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
+ * @param str text to be rendered
+ * @param rgbaColor if {@link Region#hasColorChannel()} RGBA color must be passed, otherwise value is ignored.
+ * @param sampleCount desired multisampling sample count for msaa-rendering.
+ * The actual used scample-count is written back when msaa-rendering is enabled, otherwise the store is untouched.
+ * @throws Exception if TextRenderer not initialized
+ */
+ public void drawString3D(final GL2ES2 gl,
+ final RegionRenderer renderer, final Font font, final float pixelSize,
+ final CharSequence str, final float[] rgbaColor, final int[/*1*/] sampleCount) {
+ if( !renderer.isInitialized() ) {
+ throw new GLException("TextRendererImpl01: not initialized!");
+ }
+ final int special = 0;
+ GLRegion region = getCachedRegion(font, str, pixelSize, special);
+ if(null == region) {
+ region = GLRegion.create(renderModes, null);
+ addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, pixelSize, str, rgbaColor, tempT1, tempT2);
+ addCachedRegion(gl, font, str, pixelSize, special, region);
+ }
+ region.draw(gl, renderer, sampleCount);
+ }
+
+ /**
+ * Render the string in 3D space w.r.t. the font and pixelSize
+ * using a temporary {@link GLRegion}, which will be destroyed afterwards.
+ * <p>
+ * In case of a multisampling region renderer, i.e. {@link Region#VBAA_RENDERING_BIT}, recreating the {@link GLRegion}
+ * is a huge performance impact.
+ * In such case better use {@link #drawString3D(GL2ES2, GLRegion, RegionRenderer, Font, float, CharSequence, float[], int[], AffineTransform, AffineTransform)}
+ * instead.
+ * </p>
+ * @param gl the current GL state
+ * @param renderModes TODO
+ * @param font {@link Font} to be used
+ * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
+ * @param str text to be rendered
+ * @param rgbaColor if {@link Region#hasColorChannel()} RGBA color must be passed, otherwise value is ignored.
+ * @param sampleCount desired multisampling sample count for msaa-rendering.
+ * The actual used scample-count is written back when msaa-rendering is enabled, otherwise the store is untouched.
+ * @param temp1 temporary AffineTransform storage, mandatory
+ * @param temp2 temporary AffineTransform storage, mandatory
+ * @throws Exception if TextRenderer not initialized
+ */
+ public static void drawString3D(final GL2ES2 gl, final int renderModes,
+ final RegionRenderer renderer, final Font font, final float pixelSize,
+ final CharSequence str, final float[] rgbaColor, final int[/*1*/] sampleCount,
+ final AffineTransform temp1, final AffineTransform temp2) {
+ if(!renderer.isInitialized()){
+ throw new GLException("TextRendererImpl01: not initialized!");
+ }
+ final GLRegion region = GLRegion.create(renderModes, null);
+ addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, pixelSize, str, rgbaColor, temp1, temp2);
+ region.draw(gl, renderer, sampleCount);
+ region.destroy(gl);
+ }
+
+ /**
+ * Render the string in 3D space w.r.t. the font and pixelSize
+ * using the given {@link GLRegion}, which will {@link GLRegion#clear(GL2ES2) cleared} beforehand.
+ * @param gl the current GL state
+ * @param font {@link Font} to be used
+ * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
+ * @param str text to be rendered
+ * @param rgbaColor if {@link Region#hasColorChannel()} RGBA color must be passed, otherwise value is ignored.
+ * @param sampleCount desired multisampling sample count for msaa-rendering.
+ * The actual used scample-count is written back when msaa-rendering is enabled, otherwise the store is untouched.
+ * @param temp1 temporary AffineTransform storage, mandatory
+ * @param temp2 temporary AffineTransform storage, mandatory
+ * @throws Exception if TextRenderer not initialized
+ */
+ public static void drawString3D(final GL2ES2 gl, final GLRegion region, final RegionRenderer renderer,
+ final Font font, final float pixelSize, final CharSequence str,
+ final float[] rgbaColor, final int[/*1*/] sampleCount,
+ final AffineTransform temp1, final AffineTransform temp2) {
+ if(!renderer.isInitialized()){
+ throw new GLException("TextRendererImpl01: not initialized!");
+ }
+ region.clear(gl);
+ addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, pixelSize, str, rgbaColor, temp1, temp2);
+ region.draw(gl, renderer, sampleCount);
+ }
+
+ /**
+ * Clear all cached {@link GLRegions}.
+ */
+ public void clear(final GL2ES2 gl) {
+ // fluchCache(gl) already called
+ final Iterator<GLRegion> iterator = stringCacheMap.values().iterator();
+ while(iterator.hasNext()){
+ final GLRegion region = iterator.next();
+ region.destroy(gl);
+ }
+ stringCacheMap.clear();
+ stringCacheArray.clear();
+ }
+
+ /**
+ * <p>Sets the cache limit for reusing GlyphString's and their Region.
+ * Default is {@link #DEFAULT_CACHE_LIMIT}, -1 unlimited, 0 turns cache off, >0 limited </p>
+ *
+ * <p>The cache will be validate when the next string rendering happens.</p>
+ *
+ * @param newLimit new cache size
+ *
+ * @see #DEFAULT_CACHE_LIMIT
+ */
+ public final void setCacheLimit(final int newLimit ) { stringCacheLimit = newLimit; }
+
+ /**
+ * Sets the cache limit, see {@link #setCacheLimit(int)} and validates the cache.
+ *
+ * @see #setCacheLimit(int)
+ *
+ * @param gl current GL used to remove cached objects if required
+ * @param newLimit new cache size
+ */
+ public final void setCacheLimit(final GL2ES2 gl, final int newLimit ) { stringCacheLimit = newLimit; validateCache(gl, 0); }
+
+ /**
+ * @return the current cache limit
+ */
+ public final int getCacheLimit() { return stringCacheLimit; }
+
+ /**
+ * @return the current utilized cache size, <= {@link #getCacheLimit()}
+ */
+ public final int getCacheSize() { return stringCacheArray.size(); }
+
+ protected final void validateCache(final GL2ES2 gl, final int space) {
+ if ( getCacheLimit() > 0 ) {
+ while ( getCacheSize() + space > getCacheLimit() ) {
+ removeCachedRegion(gl, 0);
+ }
+ }
+ }
+
+ protected final GLRegion getCachedRegion(final Font font, final CharSequence str, final float pixelSize, final int special) {
+ return stringCacheMap.get(getKey(font, str, pixelSize, special));
+ }
+
+ protected final void addCachedRegion(final GL2ES2 gl, final Font font, final CharSequence str, final float pixelSize, final int special, final GLRegion glyphString) {
+ if ( 0 != getCacheLimit() ) {
+ final String key = getKey(font, str, pixelSize, special);
+ final GLRegion oldRegion = stringCacheMap.put(key, glyphString);
+ if ( null == oldRegion ) {
+ // new entry ..
+ validateCache(gl, 1);
+ stringCacheArray.add(stringCacheArray.size(), key);
+ } /// else overwrite is nop ..
+ }
+ }
+
+ protected final void removeCachedRegion(final GL2ES2 gl, final Font font, final CharSequence str, final int pixelSize, final int special) {
+ final String key = getKey(font, str, pixelSize, special);
+ final GLRegion region = stringCacheMap.remove(key);
+ if(null != region) {
+ region.destroy(gl);
+ }
+ stringCacheArray.remove(key);
+ }
+
+ protected final void removeCachedRegion(final GL2ES2 gl, final int idx) {
+ final String key = stringCacheArray.remove(idx);
+ if( null != key ) {
+ final GLRegion region = stringCacheMap.remove(key);
+ if(null != region) {
+ region.destroy(gl);
+ }
+ }
+ }
+
+ protected final String getKey(final Font font, final CharSequence str, final float pixelSize, final int special) {
+ final StringBuilder sb = new StringBuilder();
+ return font.getName(sb, Font.NAME_UNIQUNAME)
+ .append(".").append(str.hashCode()).append(".").append(Float.floatToIntBits(pixelSize)).append(special).toString();
+ }
+
+ /** Default cache limit, see {@link #setCacheLimit(int)} */
+ public static final int DEFAULT_CACHE_LIMIT = 256;
+
+ public final AffineTransform tempT1 = new AffineTransform();
+ public final AffineTransform tempT2 = new AffineTransform();
+ private final HashMap<String, GLRegion> stringCacheMap = new HashMap<String, GLRegion>(DEFAULT_CACHE_LIMIT);
+ private final ArrayList<String> stringCacheArray = new ArrayList<String>(DEFAULT_CACHE_LIMIT);
+ private int stringCacheLimit = DEFAULT_CACHE_LIMIT;
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java
deleted file mode 100644
index 8dc41b0c0..000000000
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.graph.curve.opengl;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-
-import javax.media.opengl.GL2ES2;
-
-import jogamp.graph.curve.text.GlyphString;
-
-import com.jogamp.graph.font.Font;
-
-public abstract class TextRenderer extends Renderer {
- /**
- * Create a Hardware accelerated Text Renderer.
- * @param rs the used {@link RenderState}
- * @param renderModes either {@link com.jogamp.graph.curve.opengl.GLRegion#SINGLE_PASS} or {@link com.jogamp.graph.curve.Region#VBAA_RENDERING_BIT}
- */
- public static TextRenderer create(RenderState rs, int renderModes) {
- return new jogamp.graph.curve.opengl.TextRendererImpl01(rs, renderModes);
- }
-
- protected TextRenderer(RenderState rs, int type) {
- super(rs, type);
- }
-
-
- /** Render the String in 3D space wrt to the font provided at the position provided
- * the outlines will be generated, if not yet generated
- * @param gl the current GL state
- * @param font {@link Font} to be used
- * @param str text to be rendered
- * @param position the lower left corner of the string
- * @param fontSize font size
- * @param texWidth desired texture width for multipass-rendering.
- * The actual used texture-width is written back when mp rendering is enabled, otherwise the store is untouched.
- * @throws Exception if TextRenderer not initialized
- */
- public abstract void drawString3D(GL2ES2 gl, Font font,
- String str, float[] position, int fontSize, int[/*1*/] texSize);
-
- /**Create the resulting {@link GlyphString} that represents
- * the String wrt to the font.
- * @param font {@link Font} to be used
- * @param size font size
- * @param str {@link String} to be created
- * @return the resulting GlyphString inclusive the generated region
- */
- public GlyphString createString(GL2ES2 gl, Font font, int size, String str) {
- if(DEBUG_INSTANCE) {
- System.err.println("createString: "+getCacheSize()+"/"+getCacheLimit()+" - "+Font.NAME_UNIQUNAME + " - " + str + " - " + size);
- }
- final GlyphString glyphString = GlyphString.createString(null, rs.getVertexFactory(), font, size, str);
- glyphString.createRegion(gl, renderModes);
- return glyphString;
- }
-
- /** FIXME
- public void flushCache(GL2ES2 gl) {
- Iterator<GlyphString> iterator = stringCacheMap.values().iterator();
- while(iterator.hasNext()){
- GlyphString glyphString = iterator.next();
- glyphString.destroy(gl, rs);
- }
- stringCacheMap.clear();
- stringCacheArray.clear();
- } */
-
- @Override
- protected void destroyImpl(GL2ES2 gl) {
- // fluchCache(gl) already called
- Iterator<GlyphString> iterator = stringCacheMap.values().iterator();
- while(iterator.hasNext()){
- GlyphString glyphString = iterator.next();
- glyphString.destroy(gl, rs);
- }
- stringCacheMap.clear();
- stringCacheArray.clear();
- }
-
- /**
- * <p>Sets the cache limit for reusing GlyphString's and their Region.
- * Default is {@link #DEFAULT_CACHE_LIMIT}, -1 unlimited, 0 turns cache off, >0 limited </p>
- *
- * <p>The cache will be validate when the next string rendering happens.</p>
- *
- * @param newLimit new cache size
- *
- * @see #DEFAULT_CACHE_LIMIT
- */
- public final void setCacheLimit(int newLimit ) { stringCacheLimit = newLimit; }
-
- /**
- * Sets the cache limit, see {@link #setCacheLimit(int)} and validates the cache.
- *
- * @see #setCacheLimit(int)
- *
- * @param gl current GL used to remove cached objects if required
- * @param newLimit new cache size
- */
- public final void setCacheLimit(GL2ES2 gl, int newLimit ) { stringCacheLimit = newLimit; validateCache(gl, 0); }
-
- /**
- * @return the current cache limit
- */
- public final int getCacheLimit() { return stringCacheLimit; }
-
- /**
- * @return the current utilized cache size, <= {@link #getCacheLimit()}
- */
- public final int getCacheSize() { return stringCacheArray.size(); }
-
- protected final void validateCache(GL2ES2 gl, int space) {
- if ( getCacheLimit() > 0 ) {
- while ( getCacheSize() + space > getCacheLimit() ) {
- removeCachedGlyphString(gl, 0);
- }
- }
- }
-
- protected final GlyphString getCachedGlyphString(Font font, String str, int fontSize) {
- return stringCacheMap.get(getKey(font, str, fontSize));
- }
-
- protected final void addCachedGlyphString(GL2ES2 gl, Font font, String str, int fontSize, GlyphString glyphString) {
- if ( 0 != getCacheLimit() ) {
- final String key = getKey(font, str, fontSize);
- GlyphString oldGlyphString = stringCacheMap.put(key, glyphString);
- if ( null == oldGlyphString ) {
- // new entry ..
- validateCache(gl, 1);
- stringCacheArray.add(stringCacheArray.size(), key);
- } /// else overwrite is nop ..
- }
- }
-
- protected final void removeCachedGlyphString(GL2ES2 gl, Font font, String str, int fontSize) {
- final String key = getKey(font, str, fontSize);
- GlyphString glyphString = stringCacheMap.remove(key);
- if(null != glyphString) {
- glyphString.destroy(gl, rs);
- }
- stringCacheArray.remove(key);
- }
-
- protected final void removeCachedGlyphString(GL2ES2 gl, int idx) {
- final String key = stringCacheArray.remove(idx);
- final GlyphString glyphString = stringCacheMap.remove(key);
- if(null != glyphString) {
- glyphString.destroy(gl, rs);
- }
- }
-
- protected final String getKey(Font font, String str, int fontSize) {
- final StringBuilder sb = new StringBuilder();
- return font.getName(sb, Font.NAME_UNIQUNAME)
- .append(".").append(str.hashCode()).append(".").append(fontSize).toString();
- }
-
- /** Default cache limit, see {@link #setCacheLimit(int)} */
- public static final int DEFAULT_CACHE_LIMIT = 256;
-
- private HashMap<String, GlyphString> stringCacheMap = new HashMap<String, GlyphString>(DEFAULT_CACHE_LIMIT);
- private ArrayList<String> stringCacheArray = new ArrayList<String>(DEFAULT_CACHE_LIMIT);
- private int stringCacheLimit = DEFAULT_CACHE_LIMIT;
-} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulation.java b/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulation.java
index 7728efcaf..ae2849536 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulation.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulation.java
@@ -33,7 +33,7 @@ import jogamp.graph.curve.tess.CDTriangulator2D;
public class Triangulation {
/** Create a new instance of a triangulation.
- * Currently only a modified version of Constraint Delaunay
+ * Currently only a modified version of Constraint Delaunay
* is implemented.
* @return instance of a triangulator
* @see Triangulator
diff --git a/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java b/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java
index 1ffaccebc..20fe9bfd9 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java
@@ -28,7 +28,7 @@
package com.jogamp.graph.curve.tess;
-import java.util.ArrayList;
+import java.util.List;
import com.jogamp.graph.geom.Outline;
import com.jogamp.graph.geom.Triangle;
@@ -36,34 +36,42 @@ import com.jogamp.graph.geom.Triangle;
/** Interface to the triangulation algorithms provided
* A triangulation of 2D outlines where you can
* provides an easy one or more outlines to be triangulated
- *
+ *
* example usage:
* addCurve(o1);
* addCurve(o2);
* addCurve(o3);
* generate();
* reset();
- *
+ *
* @see Outline
* @see Triangulation
*/
public interface Triangulator {
-
- /** Add a curve to the list of Outlines
+
+ /**
+ * Add a curve to the list of Outlines
* describing the shape
+ * @param sink list where the generated triangles will be added
* @param outline a bounding {@link Outline}
+ * @param sharpness TODO
*/
- public void addCurve(Outline outline);
-
- /** Generate the triangulation of the provided
+ public void addCurve(List<Triangle> sink, Outline outline, float sharpness);
+
+ /** Generate the triangulation of the provided
* List of {@link Outline}s
- * @return an arraylist of {@link Triangle}s resembling the
- * final shape.
+ * @param sink list where the generated triangles will be added
*/
- public ArrayList<Triangle> generate();
-
- /** Reset the triangulation to initial state
- * Clearing cached data
+ public void generate(List<Triangle> sink);
+
+ /**
+ * Reset the triangulation to initial state
+ * Clearing cached data
*/
public void reset();
+
+ /**
+ * Return the number of newly added vertices during {@link #addCurve(List, Outline, float)}.
+ */
+ public int getAddedVerticeCount();
}
diff --git a/src/jogl/classes/com/jogamp/graph/font/Font.java b/src/jogl/classes/com/jogamp/graph/font/Font.java
index e2b3fe5d7..52ad4076d 100644
--- a/src/jogl/classes/com/jogamp/graph/font/Font.java
+++ b/src/jogl/classes/com/jogamp/graph/font/Font.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+// * Copyright 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -27,16 +27,35 @@
*/
package com.jogamp.graph.font;
-import com.jogamp.graph.geom.AABBox;
+import jogamp.graph.geom.plane.AffineTransform;
+
+import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.opengl.math.geom.AABBox;
/**
* Interface wrapper for font implementation.
- *
+ * <p>
* TrueType Font Specification:
- * http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html
- *
+ * <ul>
+ * <li>http://www.freetype.org/freetype2/documentation.html</li>
+ * <li>http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html</li>
+ * <li>http://www.microsoft.com/typography/SpecificationsOverview.mspx</li>
+ * <li>http://www.microsoft.com/typography/otspec/</li>
+ * </ul>
+ * </p>
+ * <p>
* TrueType Font Table Introduction:
- * http://scripts.sil.org/cms/scripts/page.php?item_id=IWS-Chapter08
+ * <ul>
+ * <li>http://scripts.sil.org/cms/scripts/page.php?item_id=IWS-Chapter08</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Misc.:
+ * <ul>
+ * <li>Treatis on Font <code>Rasterization https://freddie.witherden.org/pages/font-rasterisation/</code></li>
+ * <li>Glyph Hell <code>http://walon.org/pub/ttf/ttf_glyphs.htm</code></li>
+ * </ul>
+ * </p>
*/
public interface Font {
@@ -50,64 +69,158 @@ public interface Font {
public static final int NAME_VERSION = 5;
public static final int NAME_MANUFACTURER = 8;
public static final int NAME_DESIGNER = 9;
-
-
+
+
/**
* Metrics for font
- *
+ *
* Depending on the font's direction, horizontal or vertical,
* the following tables shall be used:
- *
+ *
* Vertical http://developer.apple.com/fonts/TTRefMan/RM06/Chap6vhea.html
* Horizontal http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html
*/
- public interface Metrics {
- float getAscent(float pixelSize);
- float getDescent(float pixelSize);
- float getLineGap(float pixelSize);
- float getMaxExtend(float pixelSize);
- float getScale(float pixelSize);
- AABBox getBBox(float pixelSize);
+ public interface Metrics {
+ float getAscent(final float pixelSize);
+ float getDescent(final float pixelSize);
+ float getLineGap(final float pixelSize);
+ float getMaxExtend(final float pixelSize);
+ float getScale(final float pixelSize);
+ /**
+ * @param dest AABBox instance set to this metrics boundary w/ given pixelSize
+ * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link Font#getPixelSize(float, float)}
+ * @param tmpV3 caller provided temporary 3-component vector
+ * @return the given and set AABBox 'dest'
+ */
+ AABBox getBBox(final AABBox dest, final float pixelSize, final float[] tmpV3);
}
/**
* Glyph for font
+ *
+ * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6cmap.html
+ * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6glyf.html
+ * http://www.microsoft.com/typography/otspec/glyf.htm
*/
public interface Glyph {
- // reserved special glyph IDs
+ // reserved special glyph IDs
// http://scripts.sil.org/cms/scripts/page.php?item_id=IWS-Chapter08#ba57949e
public static final int ID_UNKNOWN = 0;
public static final int ID_CR = 2;
public static final int ID_SPACE = 3;
-
+
public Font getFont();
public char getSymbol();
- public AABBox getBBox(float pixelSize);
- public float getAdvance(float pixelSize, boolean useFrationalMetrics);
+ public short getID();
+ public AABBox getBBox();
+ /**
+ *
+ * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link Font#getPixelSize(float, float)}
+ * @return
+ */
+ public float getScale(final float pixelSize);
+ /**
+ * @param dest AABBox instance set to this metrics boundary w/ given pixelSize
+ * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link Font#getPixelSize(float, float)}
+ * @param tmpV3 caller provided temporary 3-component vector
+ * @return the given and set AABBox 'dest'
+ */
+ public AABBox getBBox(final AABBox dest, final float pixelSize, float[] tmpV3);
+ /**
+ *
+ * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link Font#getPixelSize(float, float)}
+ * @param useFrationalMetrics
+ * @return
+ */
+ public float getAdvance(final float pixelSize, boolean useFrationalMetrics);
+ public OutlineShape getShape();
+ public int hashCode();
}
- public String getName(int nameIndex);
- public StringBuilder getName(StringBuilder string, int nameIndex);
-
+ public String getName(final int nameIndex);
+ public StringBuilder getName(final StringBuilder string, final int nameIndex);
+
/** Shall return the family and subfamily name, separated a dash.
* <p>{@link #getName(StringBuilder, int)} w/ {@link #NAME_FAMILY} and {@link #NAME_SUBFAMILY}</p>
* <p>Example: "{@code Ubuntu-Regular}"</p> */
- public StringBuilder getFullFamilyName(StringBuilder buffer);
-
- public StringBuilder getAllNames(StringBuilder string, String separator);
-
- public float getAdvanceWidth(int i, float pixelSize);
+ public StringBuilder getFullFamilyName(final StringBuilder buffer);
+
+ public StringBuilder getAllNames(final StringBuilder string, final String separator);
+
+ /**
+ * <pre>
+ Font Scale Formula:
+ inch: 25.4 mm
+ pointSize: [point] = [1/72 inch]
+
+ [1] Scale := pointSize * resolution / ( 72 points per inch * units_per_em )
+ [2] PixelSize := pointSize * resolution / ( 72 points per inch )
+ [3] Scale := PixelSize / units_per_em
+ * </pre>
+ * @param fontSize in point-per-inch
+ * @param resolution display resolution in dots-per-inch
+ * @return pixel-per-inch, pixelSize scale factor for font operations.
+ */
+ public float getPixelSize(final float fontSize /* points per inch */, final float resolution);
+
+ /**
+ *
+ * @param glyphID
+ * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
+ * @return
+ */
+ public float getAdvanceWidth(final int glyphID, final float pixelSize);
public Metrics getMetrics();
- public Glyph getGlyph(char symbol);
+ public Glyph getGlyph(final char symbol);
public int getNumGlyphs();
-
- public float getStringWidth(CharSequence string, float pixelSize);
- public float getStringHeight(CharSequence string, float pixelSize);
- public AABBox getStringBounds(CharSequence string, float pixelSize);
-
- public boolean isPrintableChar( char c );
-
+
+ /**
+ *
+ * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
+ * @return
+ */
+ public float getLineHeight(final float pixelSize);
+ /**
+ *
+ * @param string
+ * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
+ * @return
+ */
+ public float getMetricWidth(final CharSequence string, final float pixelSize);
+ /**
+ *
+ * @param string
+ * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
+ * @param tmp
+ * @return
+ */
+ public float getMetricHeight(final CharSequence string, final float pixelSize, final AABBox tmp);
+ /**
+ * Return the <i>layout</i> bounding box as computed by each glyph's metrics.
+ * The result is not pixel correct, bit reflects layout specific metrics.
+ * <p>
+ * See {@link #getPointsBounds(AffineTransform, CharSequence, float, AffineTransform, AffineTransform)} for pixel correct results.
+ * </p>
+ * @param string string text
+ * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
+ */
+ public AABBox getMetricBounds(final CharSequence string, final float pixelSize);
+
+ /**
+ * Return the bounding box by taking each glyph's point-based bounding box into account.
+ * @param transform optional given transform
+ * @param string string text
+ * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
+ * @param temp1 temporary AffineTransform storage, mandatory
+ * @param temp2 temporary AffineTransform storage, mandatory
+ */
+ public AABBox getPointsBounds(final AffineTransform transform, final CharSequence string, final float pixelSize,
+ final AffineTransform temp1, final AffineTransform temp2);
+
+ public boolean isPrintableChar(final char c);
+
/** Shall return {@link #getFullFamilyName()} */
+ @Override
public String toString();
-} \ No newline at end of file
+}
diff --git a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
index 33d487355..be16e030f 100644
--- a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
+++ b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
@@ -27,25 +27,42 @@
*/
package com.jogamp.graph.font;
+import java.io.BufferedInputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
-import java.net.URLConnection;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import com.jogamp.common.net.Uri;
+import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
-import com.jogamp.common.util.SecurityUtil;
+import com.jogamp.common.util.cache.TempJarCache;
import jogamp.graph.font.FontConstructor;
import jogamp.graph.font.JavaFontLoader;
import jogamp.graph.font.UbuntuFontLoader;
+/**
+ * The optional property <i>jogamp.graph.font.ctor</i>
+ * allows user to specify the {@link FontConstructor} implementation.
+ * <p>
+ * Default {@link FontConstructor} is {@link jogamp.graph.font.typecast.TypecastFontConstructor},
+ * i.e. using our internal <i>typecast</i> branch.
+ * </p>
+ */
public class FontFactory {
- /** Ubuntu is the default font family */
+ private static final String FontConstructorPropKey = "jogamp.graph.font.ctor";
+ private static final String DefaultFontConstructor = "jogamp.graph.font.typecast.TypecastFontConstructor";
+
+ /** Ubuntu is the default font family, {@value} */
public static final int UBUNTU = 0;
-
- /** Java fonts are optional */
+
+ /** Java fonts are optional, {@value} */
public static final int JAVA = 1;
-
+
private static final FontConstructor fontConstr;
static {
@@ -53,19 +70,19 @@ public class FontFactory {
* For example:
* "jogamp.graph.font.typecast.TypecastFontFactory" (default)
* "jogamp.graph.font.ttf.TTFFontImpl"
- */
- String fontImplName = PropertyAccess.getProperty("FontImpl", true, SecurityUtil.getCommonAccessControlContext(FontFactory.class));
+ */
+ String fontImplName = PropertyAccess.getProperty(FontConstructorPropKey, true);
if(null == fontImplName) {
- fontImplName = "jogamp.graph.font.typecast.TypecastFontConstructor";
+ fontImplName = DefaultFontConstructor;
}
fontConstr = (FontConstructor) ReflectionUtil.createInstance(fontImplName, FontFactory.class.getClassLoader());
}
-
+
public static final FontSet getDefault() {
return get(UBUNTU);
}
-
- public static final FontSet get(int font) {
+
+ public static final FontSet get(final int font) {
switch (font) {
case JAVA:
return JavaFontLoader.get();
@@ -73,20 +90,131 @@ public class FontFactory {
return UbuntuFontLoader.get();
}
}
-
- public static final Font get(File file) throws IOException {
+
+ /**
+ * Creates a Font instance.
+ * @param file font file
+ * @return the new Font instance
+ * @throws IOException
+ */
+ public static final Font get(final File file) throws IOException {
return fontConstr.create(file);
}
- public static final Font get(final URLConnection conn) throws IOException {
- return fontConstr.create(conn);
- }
-
- public static boolean isPrintableChar( char c ) {
- Character.UnicodeBlock block = Character.UnicodeBlock.of( c );
- return (!Character.isISOControl(c)) &&
- c != 0 &&
- block != null &&
- block != Character.UnicodeBlock.SPECIALS;
- }
+ /**
+ * Creates a Font instance based on a determinated font stream with its given length
+ * of the font segment.
+ * <p>
+ * No explicit stream copy is performed as in {@link #get(InputStream, boolean)}
+ * due to the known {@code streamLen}.
+ * </p>
+ * @param stream font stream
+ * @param streamLen length of the font segment within this font stream
+ * @param closeStream {@code true} to close the {@code stream}
+ * @return the new Font instance
+ * @throws IOException
+ */
+ public static final Font get(final InputStream stream, final int streamLen, final boolean closeStream) throws IOException {
+ try {
+ return fontConstr.create(stream, streamLen);
+ } finally {
+ if( closeStream ) {
+ stream.close();
+ }
+ }
+ }
+
+ /**
+ * Creates a Font instance based on an undeterminated font stream length.
+ * <p>
+ * The font stream is temporarily copied into a temp file
+ * to gather it's size and to gain random access.
+ * The temporary file will be deleted at exit.
+ * </p>
+ * @param stream dedicated font stream
+ * @param closeStream {@code true} to close the {@code stream}
+ * @return the new Font instance
+ * @throws IOException
+ */
+ public static final Font get(final InputStream stream, final boolean closeStream) throws IOException {
+ final IOException[] ioe = { null };
+ final int[] streamLen = { 0 };
+ final File tempFile[] = { null };
+
+ final InputStream bis = AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
+ @Override
+ public InputStream run() {
+ InputStream bis = null;
+ try {
+ tempFile[0] = IOUtil.createTempFile( "jogl.font", ".ttf", false);
+ streamLen[0] = IOUtil.copyStream2File(stream, tempFile[0], -1);
+ if( 0 == streamLen[0] ) {
+ throw new IOException("Font stream has zero bytes");
+ }
+ bis = new BufferedInputStream(new FileInputStream(tempFile[0]), streamLen[0]);
+ } catch (final IOException e) {
+ ioe[0] = e;
+ if( null != tempFile[0] ) {
+ tempFile[0].delete();
+ tempFile[0] = null;
+ }
+ streamLen[0] = 0;
+ } finally {
+ if( closeStream ) {
+ IOUtil.close(stream, ioe, System.err);
+ }
+ }
+ return bis;
+ } });
+ if( null != ioe[0] ) {
+ throw ioe[0];
+ }
+ if( null == bis ) {
+ throw new IOException("Could not cache font stream"); // should not be reached
+ }
+ try {
+ return fontConstr.create(bis, streamLen[0]);
+ } finally {
+ if( null != bis ) {
+ bis.close();
+ }
+ if( null != tempFile[0] ) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ tempFile[0].delete();
+ return null;
+ } } );
+ }
+ }
+ }
+
+ public static final Font get(final Class<?> context, final String fname, final boolean useTempJarCache) throws IOException {
+ InputStream stream = null;
+ if( useTempJarCache ) {
+ try {
+ final Uri uri = TempJarCache.getResourceUri(fname);
+ stream = null != uri ? uri.toURL().openConnection().getInputStream() : null;
+ } catch (final Exception e) {
+ throw new IOException(e);
+ }
+ } else {
+ stream = IOUtil.getResource(context, fname).getInputStream();
+ }
+ if( null != stream ) {
+ return FontFactory.get ( stream, true ) ;
+ }
+ return null;
+ }
+
+ public static boolean isPrintableChar( final char c ) {
+ if( Character.isWhitespace(c) ) {
+ return true;
+ }
+ if( 0 == c || Character.isISOControl(c) ) {
+ return false;
+ }
+ final Character.UnicodeBlock block = Character.UnicodeBlock.of( c );
+ return block != null && block != Character.UnicodeBlock.SPECIALS;
+ }
}
diff --git a/src/jogl/classes/com/jogamp/graph/font/FontSet.java b/src/jogl/classes/com/jogamp/graph/font/FontSet.java
index d376922ab..60a16b241 100644
--- a/src/jogl/classes/com/jogamp/graph/font/FontSet.java
+++ b/src/jogl/classes/com/jogamp/graph/font/FontSet.java
@@ -32,31 +32,39 @@ import java.io.IOException;
public interface FontSet {
- /** Font family REGULAR **/
+ /** Font family REGULAR, {@value} **/
public static final int FAMILY_REGULAR = 0;
-
- /** Font family LIGHT **/
+
+ /** Font family LIGHT, {@value} **/
public static final int FAMILY_LIGHT = 1;
-
- /** Font family MEDIUM **/
+
+ /** Font family MEDIUM, {@value} **/
public static final int FAMILY_MEDIUM = 2;
-
- /** Font family CONDENSED **/
+
+ /** Font family CONDENSED, {@value} **/
public static final int FAMILY_CONDENSED = 3;
-
- /** Font family MONO **/
+
+ /** Font family MONO, {@value} **/
public static final int FAMILY_MONOSPACED = 4;
-
- /** SERIF style/family bit flag. Fallback to Sans Serif. */
+
+ /** Zero style, {@value} */
+ public static final int STYLE_NONE = 0;
+
+ /** SERIF style/family bit flag. Fallback to Sans Serif, {@value} */
public static final int STYLE_SERIF = 1 << 1;
-
- /** BOLD style bit flag */
+
+ /** BOLD style bit flag, {@value} */
public static final int STYLE_BOLD = 1 << 2;
-
- /** ITALIC style bit flag */
+
+ /** ITALIC style bit flag, {@value} */
public static final int STYLE_ITALIC = 1 << 3;
+ /**
+ * Returns the family {@link #FAMILY_REGULAR} with {@link #STYLE_NONE}
+ * as retrieved with {@link #get(int, int)}.
+ * @throws IOException
+ */
Font getDefault() throws IOException ;
-
+
Font get(int family, int stylebits) throws IOException ;
}
diff --git a/src/jogl/classes/com/jogamp/graph/geom/AABBox.java b/src/jogl/classes/com/jogamp/graph/geom/AABBox.java
deleted file mode 100644
index 87f084919..000000000
--- a/src/jogl/classes/com/jogamp/graph/geom/AABBox.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.graph.geom;
-
-import com.jogamp.graph.math.VectorUtil;
-
-/**
- * Axis Aligned Bounding Box. Defined by two 3D coordinates (low and high)
- * The low being the the lower left corner of the box, and the high being the upper
- * right corner of the box.
- *
- */
-public class AABBox implements Cloneable {
- private float[] low = new float[3];
- private float[] high = new float[3];
- private float[] center = new float[3];
-
- /** Create a Axis Aligned bounding box (AABBox)
- * where the low and and high MAX float Values.
- */
- public AABBox() {
- reset();
- }
-
- /** Create an AABBox specifying the coordinates
- * of the low and high
- * @param lx min x-coordinate
- * @param ly min y-coordnate
- * @param lz min z-coordinate
- * @param hx max x-coordinate
- * @param hy max y-coordinate
- * @param hz max z-coordinate
- */
- public AABBox(float lx, float ly, float lz,
- float hx, float hy, float hz)
- {
- reset();
- resize(lx, ly, lz);
- resize(hx, hy, hz);
-
- computeCenter();
- }
-
- /** Create a AABBox defining the low and high
- * @param low min xyz-coordinates
- * @param high max xyz-coordinates
- */
- public AABBox(float[] low, float[] high) {
- reset();
- resize(low[0],low[1],low[2]);
- resize(high[0],high[1],high[2]);
-
- computeCenter();
- }
-
- /** resets this box to the inverse low/high, allowing the next {@link #resize(float, float, float)} command to hit. */
- public final void reset() {
- setLow(Float.MAX_VALUE,Float.MAX_VALUE,Float.MAX_VALUE);
- setHigh(-1*Float.MAX_VALUE,-1*Float.MAX_VALUE,-1*Float.MAX_VALUE);
- center[0] = 0f;
- center[1] = 0f;
- center[2] = 0f;
- }
-
- /** Get the max xyz-coordinates
- * @return a float array containing the max xyz coordinates
- */
- public final float[] getHigh() {
- return high;
- }
-
- private final void setHigh(float hx, float hy, float hz) {
- this.high[0] = hx;
- this.high[1] = hy;
- this.high[2] = hz;
- }
-
- /** Get the min xyz-coordinates
- * @return a float array containing the min xyz coordinates
- */
- public final float[] getLow() {
- return low;
- }
-
- private final void setLow(float lx, float ly, float lz) {
- this.low[0] = lx;
- this.low[1] = ly;
- this.low[2] = lz;
- }
-
- /** Resize the AABBox to encapsulate another AABox
- * @param newBox AABBox to be encapsulated in
- */
- public final void resize(AABBox newBox) {
- float[] newLow = newBox.getLow();
- float[] newHigh = newBox.getHigh();
-
- /** test low */
- if (newLow[0] < low[0])
- low[0] = newLow[0];
- if (newLow[1] < low[1])
- low[1] = newLow[1];
- if (newLow[2] < low[2])
- low[2] = newLow[2];
-
- /** test high */
- if (newHigh[0] > high[0])
- high[0] = newHigh[0];
- if (newHigh[1] > high[1])
- high[1] = newHigh[1];
- if (newHigh[2] > high[2])
- high[2] = newHigh[2];
-
- computeCenter();
- }
-
- private final void computeCenter() {
- center[0] = (high[0] + low[0])/2;
- center[1] = (high[1] + low[1])/2;
- center[2] = (high[2] + low[2])/2;
- }
-
- /** Resize the AABBox to encapsulate the passed
- * xyz-coordinates.
- * @param x x-axis coordinate value
- * @param y y-axis coordinate value
- * @param z z-axis coordinate value
- */
- public final void resize(float x, float y, float z) {
- /** test low */
- if (x < low[0])
- low[0] = x;
- if (y < low[1])
- low[1] = y;
- if (z < low[2])
- low[2] = z;
-
- /** test high */
- if (x > high[0])
- high[0] = x;
- if (y > high[1])
- high[1] = y;
- if (z > high[2])
- high[2] = z;
-
- computeCenter();
- }
-
- /** Resize the AABBox to encapsulate the passed
- * xyz-coordinates.
- * @param xyz xyz-axis coordinate values
- * @param offset of the array
- */
- public final void resize(float[] xyz, int offset) {
- resize(xyz[0+offset], xyz[1+offset], xyz[2+offset]);
- }
-
- /** Check if the x & y coordinates are bounded/contained
- * by this AABBox
- * @param x x-axis coordinate value
- * @param y y-axis coordinate value
- * @return true if x belong to (low.x, high.x) and
- * y belong to (low.y, high.y)
- */
- public final boolean contains(float x, float y) {
- if(x<low[0] || x>high[0]){
- return false;
- }
- if(y<low[1]|| y>high[1]){
- return false;
- }
- return true;
- }
-
- /** Check if the xyz coordinates are bounded/contained
- * by this AABBox.
- * @param x x-axis coordinate value
- * @param y y-axis coordinate value
- * @param z z-axis coordinate value
- * @return true if x belong to (low.x, high.x) and
- * y belong to (low.y, high.y) and z belong to (low.z, high.z)
- */
- public final boolean contains(float x, float y, float z) {
- if(x<low[0] || x>high[0]){
- return false;
- }
- if(y<low[1]|| y>high[1]){
- return false;
- }
- if(z<low[2] || z>high[2]){
- return false;
- }
- return true;
- }
-
- /** Check if there is a common region between this AABBox and the passed
- * 2D region irrespective of z range
- * @param x lower left x-coord
- * @param y lower left y-coord
- * @param w width
- * @param h hight
- * @return true if this AABBox might have a common region with this 2D region
- */
- public final boolean intersects(float x, float y, float w, float h) {
- if (w <= 0 || h <= 0) {
- return false;
- }
-
- final float _w = getWidth();
- final float _h = getHeight();
- if (_w <= 0 || _h <= 0) {
- return false;
- }
-
- final float x0 = getMinX();
- final float y0 = getMinY();
- return (x + w > x0 &&
- y + h > y0 &&
- x < x0 + _w &&
- y < y0 + _h);
- }
-
-
- /** Get the size of the Box where the size is represented by the
- * length of the vector between low and high.
- * @return a float representing the size of the AABBox
- */
- public final float getSize() {
- return VectorUtil.computeLength(low, high);
- }
-
- /**Get the Center of the AABBox
- * @return the xyz-coordinates of the center of the AABBox
- */
- public final float[] getCenter() {
- return center;
- }
-
- /** Scale the AABBox by a constant
- * @param size a constant float value
- */
- public final void scale(float size) {
- float[] diffH = new float[3];
- diffH[0] = high[0] - center[0];
- diffH[1] = high[1] - center[1];
- diffH[2] = high[2] - center[2];
-
- diffH = VectorUtil.scale(diffH, size);
-
- float[] diffL = new float[3];
- diffL[0] = low[0] - center[0];
- diffL[1] = low[1] - center[1];
- diffL[2] = low[2] - center[2];
-
- diffL = VectorUtil.scale(diffL, size);
-
- high = VectorUtil.vectorAdd(center, diffH);
- low = VectorUtil.vectorAdd(center, diffL);
- }
-
- public final float getMinX() {
- return low[0];
- }
-
- public final float getMinY() {
- return low[1];
- }
-
- public final float getWidth(){
- return high[0] - low[0];
- }
-
- public final float getHeight() {
- return high[1] - low[1];
- }
-
- public final float getDepth() {
- return high[2] - low[2];
- }
-
- public final AABBox clone() {
- return new AABBox(this.low, this.high);
- }
-
- public final boolean equals(Object obj) {
- if( obj == this ) {
- return true;
- }
- if( null == obj || !(obj instanceof AABBox) ) {
- return false;
- }
- final AABBox other = (AABBox) obj;
- return VectorUtil.checkEquality(low, other.low) &&
- VectorUtil.checkEquality(high, other.high) ;
- }
-
- public final String toString() {
- return "[ "+low[0]+"/"+low[1]+"/"+low[1]+" .. "+high[0]+"/"+high[0]+"/"+high[0]+", ctr "+
- center[0]+"/"+center[1]+"/"+center[1]+" ]";
- }
-}
diff --git a/src/jogl/classes/com/jogamp/graph/geom/Outline.java b/src/jogl/classes/com/jogamp/graph/geom/Outline.java
index 5030488cc..ec0225b37 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/Outline.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/Outline.java
@@ -29,71 +29,97 @@ package com.jogamp.graph.geom;
import java.util.ArrayList;
+import jogamp.graph.geom.plane.AffineTransform;
+
import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.math.VectorUtil;
+import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.math.geom.AABBox;
/** Define a single continuous stroke by control vertices.
- * The vertices define the shape of the region defined by this
+ * The vertices define the shape of the region defined by this
* outline. The Outline can contain a list of off-curve and on-curve
* vertices which define curved regions.
- *
+ *
* Note: An outline should be closed to be rendered as a region.
- *
- * @see OutlineShape, Region
+ *
+ * @see OutlineShape
+ * @see Region
*/
-public class Outline implements Cloneable, Comparable<Outline> {
+public class Outline implements Comparable<Outline> {
- private ArrayList<Vertex> vertices = new ArrayList<Vertex>(3);
- private boolean closed = false;
- private AABBox bbox = new AABBox();
- private boolean dirtyBBox = false;
+ private ArrayList<Vertex> vertices;
+ private boolean closed;
+ private final AABBox bbox;
+ private boolean dirtyBBox;
/**Create an outline defined by control vertices.
* An outline can contain off Curve vertices which define curved
* regions in the outline.
*/
- public Outline() {
+ public Outline() {
+ vertices = new ArrayList<Vertex>(3);
+ closed = false;
+ bbox = new AABBox();
+ dirtyBBox = false;
+ }
+
+ /**
+ * Copy ctor
+ */
+ public Outline(final Outline src) {
+ vertices = new ArrayList<Vertex>(src.vertices.size());
+ for(int i=0; i<vertices.size(); i++) {
+ vertices.add( src.vertices.get(i).clone() );
+ }
+ closed = src.closed;
+ bbox = new AABBox(src.bbox);
+ dirtyBBox = src.dirtyBBox;
}
public final int getVertexCount() {
return vertices.size();
}
- /** Appends a vertex to the outline loop/strip.
+ /**
+ * Appends a vertex to the outline loop/strip.
* @param vertex Vertex to be added
- * @throws NullPointerException if the {@link Vertex} element is null
+ * @throws NullPointerException if the {@link Vertex} element is null
*/
- public final void addVertex(Vertex vertex) throws NullPointerException {
+ public final void addVertex(final Vertex vertex) throws NullPointerException {
addVertex(vertices.size(), vertex);
}
- /** Insert the {@link Vertex} element at the given {@code position} to the outline loop/strip.
+ /**
+ * Insert the {@link Vertex} element at the given {@code position} to the outline loop/strip.
* @param position of the added Vertex
* @param vertex Vertex object to be added
- * @throws NullPointerException if the {@link Vertex} element is null
+ * @throws NullPointerException if the {@link Vertex} element is null
* @throws IndexOutOfBoundsException if position is out of range (position < 0 || position > getVertexNumber())
*/
- public final void addVertex(int position, Vertex vertex) throws NullPointerException, IndexOutOfBoundsException {
+ public final void addVertex(final int position, final Vertex vertex) throws NullPointerException, IndexOutOfBoundsException {
if (null == vertex) {
throw new NullPointerException("vertex is null");
}
vertices.add(position, vertex);
if(!dirtyBBox) {
- bbox.resize(vertex.getX(), vertex.getY(), vertex.getZ());
+ bbox.resize(vertex.getCoord());
}
}
/** Replaces the {@link Vertex} element at the given {@code position}.
* <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p>
- *
+ *
* @param position of the replaced Vertex
- * @param vertex replacement Vertex object
- * @throws NullPointerException if the {@link Outline} element is null
+ * @param vertex replacement Vertex object
+ * @throws NullPointerException if the {@link Outline} element is null
* @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getVertexNumber())
*/
- public final void setVertex(int position, Vertex vertex) throws NullPointerException, IndexOutOfBoundsException {
+ public final void setVertex(final int position, final Vertex vertex) throws NullPointerException, IndexOutOfBoundsException {
if (null == vertex) {
throw new NullPointerException("vertex is null");
}
@@ -101,22 +127,22 @@ public class Outline implements Cloneable, Comparable<Outline> {
dirtyBBox = true;
}
- public final Vertex getVertex(int index){
+ public final Vertex getVertex(final int index){
return vertices.get(index);
}
- public int getVertexIndex(Vertex vertex){
+ public int getVertexIndex(final Vertex vertex){
return vertices.indexOf(vertex);
}
/** Removes the {@link Vertex} element at the given {@code position}.
* <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p>
- *
+ *
* @param position of the to be removed Vertex
* @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getVertexNumber())
*/
- public final Vertex removeVertex(int position) throws IndexOutOfBoundsException {
- dirtyBBox = true;
+ public final Vertex removeVertex(final int position) throws IndexOutOfBoundsException {
+ dirtyBBox = true;
return vertices.remove(position);
}
@@ -138,10 +164,10 @@ public class Outline implements Cloneable, Comparable<Outline> {
/**
* Use the given outline loop/strip.
* <p>Validates the bounding box.</p>
- *
+ *
* @param vertices the new outline loop/strip
*/
- public final void setVertices(ArrayList<Vertex> vertices) {
+ public final void setVertices(final ArrayList<Vertex> vertices) {
this.vertices = vertices;
validateBoundingBox();
}
@@ -150,45 +176,53 @@ public class Outline implements Cloneable, Comparable<Outline> {
return closed;
}
- /** define if this outline is closed or not.
- * if set to closed, checks if the last vertex is
- * equal to the first vertex. If not Equal adds a
- * vertex at the end to the list.
- * @param closed
+ /**
+ * Ensure this outline is closed.
+ * <p>
+ * Checks whether the last vertex equals to the first.
+ * If not equal, it either appends a clone of the first vertex
+ * or prepends a clone of the last vertex, depending on <code>closeTail</code>.
+ * </p>
+ * @param closeTail if true, a clone of the first vertex will be appended,
+ * otherwise a clone of the last vertex will be prepended.
+ * @return true if closing performed, otherwise false for NOP
*/
- public final void setClosed(boolean closed) {
- this.closed = closed;
- if( closed && !isEmpty() ) {
- Vertex first = vertices.get(0);
- Vertex last = getLastVertex();
- if(!VectorUtil.checkEquality(first.getCoord(), last.getCoord())){
- Vertex v = first.clone();
- vertices.add(v);
+ public final boolean setClosed(final boolean closeTail) {
+ this.closed = true;
+ if( !isEmpty() ) {
+ final Vertex first = vertices.get(0);
+ final Vertex last = getLastVertex();
+ if( !VectorUtil.isVec3Equal( first.getCoord(), 0, last.getCoord(), 0, FloatUtil.EPSILON ) ) {
+ if( closeTail ) {
+ vertices.add(first.clone());
+ } else {
+ vertices.add(0, last.clone());
+ }
+ return true;
}
}
+ return false;
}
- /** Compare two outlines with Bounding Box area
- * as criteria.
- * @see java.lang.Comparable#compareTo(java.lang.Object)
+ /**
+ * Return a transformed instance with all vertices are copied and transformed.
*/
- public final int compareTo(Outline outline) {
- float size = getBounds().getSize();
- float newSize = outline.getBounds().getSize();
- if(size < newSize){
- return -1;
- }
- else if(size > newSize){
- return 1;
+ public final Outline transform(final AffineTransform t, final Vertex.Factory<? extends Vertex> vertexFactory) {
+ final Outline newOutline = new Outline();
+ final int vsize = vertices.size();
+ for(int i=0; i<vsize; i++) {
+ final Vertex v = vertices.get(i);
+ newOutline.addVertex(t.transform(v, vertexFactory.create()));
}
- return 0;
+ newOutline.closed = this.closed;
+ return newOutline;
}
private final void validateBoundingBox() {
dirtyBBox = false;
bbox.reset();
for (int i=0; i<vertices.size(); i++) {
- bbox.resize(vertices.get(i).getCoord(), 0);
+ bbox.resize(vertices.get(i).getCoord());
}
}
@@ -197,19 +231,38 @@ public class Outline implements Cloneable, Comparable<Outline> {
validateBoundingBox();
}
return bbox;
- }
+ }
+
+ /**
+ * Compare two outline's Bounding Box size.
+ * @see AABBox#getSize()
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ @Override
+ public final int compareTo(final Outline other) {
+ final float thisSize = getBounds().getSize();
+ final float otherSize = other.getBounds().getSize();
+ if( FloatUtil.isEqual(thisSize, otherSize, FloatUtil.EPSILON) ) {
+ return 0;
+ } else if(thisSize < otherSize){
+ return -1;
+ } else {
+ return 1;
+ }
+ }
/**
* @param obj the Object to compare this Outline with
- * @return true if {@code obj} is an Outline, not null, equals bounds and equal vertices in the same order
+ * @return true if {@code obj} is an Outline, not null, equals bounds and equal vertices in the same order
*/
- public boolean equals(Object obj) {
+ @Override
+ public boolean equals(final Object obj) {
if( obj == this) {
return true;
}
if( null == obj || !(obj instanceof Outline) ) {
return false;
- }
+ }
final Outline o = (Outline) obj;
if(getVertexCount() != o.getVertexCount()) {
return false;
@@ -224,20 +277,13 @@ public class Outline implements Cloneable, Comparable<Outline> {
}
return true;
}
-
- /**
- * @return deep clone of this Outline
- */
- public Outline clone() {
- Outline o;
- try {
- o = (Outline) super.clone();
- } catch (CloneNotSupportedException e) { throw new InternalError(); }
- o.bbox = bbox.clone();
- o.vertices = new ArrayList<Vertex>(vertices.size());
- for(int i=0; i<vertices.size(); i++) {
- o.vertices.add(vertices.get(i).clone());
- }
- return o;
- }
+ @Override
+ public final int hashCode() {
+ throw new InternalError("hashCode not designed");
+ }
+ @Override
+ public String toString() {
+ // Avoid calling this.hashCode() !
+ return getClass().getName() + "@" + Integer.toHexString(super.hashCode());
+ }
}
diff --git a/src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java b/src/jogl/classes/com/jogamp/graph/geom/SVertex.java
index 9dade17e9..dc6982025 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/SVertex.java
@@ -25,114 +25,154 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package com.jogamp.graph.geom.opengl;
+package com.jogamp.graph.geom;
-import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.math.VectorUtil;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.VectorUtil;
/** A Simple Vertex Implementation. Where the coordinates, and other attributes are
* float based, and the coordinates and texture coordinates are saved in two float arrays.
*
*/
public class SVertex implements Vertex {
- private int id = Integer.MAX_VALUE;
- protected float[] coord = new float[3];
+ private int id;
protected boolean onCurve;
- private float[] texCoord = new float[2];
-
+ protected final float[] coord = new float[3];
+ private final float[] texCoord = new float[3];
+
static final Factory factory = new Factory();
-
- public static Factory factory() { return factory; }
-
+
+ public static Factory factory() { return factory; }
+
public static class Factory implements Vertex.Factory<SVertex> {
+ @Override
public SVertex create() {
return new SVertex();
}
- public SVertex create(float x, float y, float z, boolean onCurve) {
+ public SVertex create(final Vertex src) {
+ return new SVertex(src);
+ }
+
+ @Override
+ public SVertex create(final int id, final boolean onCurve, final float[] texCoordsBuffer) {
+ return new SVertex(id, onCurve, texCoordsBuffer);
+ }
+
+ @Override
+ public SVertex create(final float x, final float y, final float z, final boolean onCurve) {
return new SVertex(x, y, z, onCurve);
}
- public SVertex create(float[] coordsBuffer, int offset, int length, boolean onCurve) {
+ @Override
+ public SVertex create(final float[] coordsBuffer, final int offset, final int length, final boolean onCurve) {
return new SVertex(coordsBuffer, offset, length, onCurve);
- }
+ }
}
-
+
public SVertex() {
+ this.id = Integer.MAX_VALUE;
}
- public SVertex(float x, float y, float z, boolean onCurve) {
- setCoord(x, y, z);
- setOnCurve(onCurve);
+ public SVertex(final Vertex src) {
+ this.id = Integer.MAX_VALUE;
+ System.arraycopy(src.getCoord(), 0, coord, 0, 3);
+ System.arraycopy(src.getTexCoord(), 0, texCoord, 0, 3);
+ setOnCurve(src.isOnCurve());
}
-
- public SVertex(float[] coordsBuffer, int offset, int length, boolean onCurve) {
- setCoord(coordsBuffer, offset, length);
+
+ public SVertex(final int id, final boolean onCurve, final float[] texCoordsBuffer) {
+ this.id = id;
+ this.onCurve = onCurve;
+ System.arraycopy(texCoordsBuffer, 0, texCoord, 0, 3);
+ }
+
+ public SVertex(final float x, final float y, final float z, final boolean onCurve) {
+ this.id = Integer.MAX_VALUE;
+ setCoord(x, y, z);
setOnCurve(onCurve);
}
-
- public SVertex(float[] coordsBuffer, int offset, int length,
- float[] texCoordsBuffer, int offsetTC, int lengthTC, boolean onCurve) {
+
+ public SVertex(final float[] coordsBuffer, final int offset, final int length, final boolean onCurve) {
+ this.id = Integer.MAX_VALUE;
setCoord(coordsBuffer, offset, length);
- setTexCoord(texCoordsBuffer, offsetTC, lengthTC);
setOnCurve(onCurve);
}
-
- public final void setCoord(float x, float y, float z) {
- this.coord[0] = x;
- this.coord[1] = y;
- this.coord[2] = z;
+
+ @Override
+ public final void setCoord(final float x, final float y, final float z) {
+ coord[0] = x;
+ coord[1] = y;
+ coord[2] = z;
}
- public final void setCoord(float[] coordsBuffer, int offset, int length) {
+ @Override
+ public final void setCoord(final float[] coordsBuffer, final int offset, final int length) {
System.arraycopy(coordsBuffer, offset, coord, 0, length);
}
-
+
+ @Override
+ public int getCoordCount() {
+ return 3;
+ }
+
+ @Override
public final float[] getCoord() {
return coord;
}
- public final void setX(float x) {
+ @Override
+ public final void setX(final float x) {
this.coord[0] = x;
}
- public final void setY(float y) {
+ @Override
+ public final void setY(final float y) {
this.coord[1] = y;
}
- public final void setZ(float z) {
+ @Override
+ public final void setZ(final float z) {
this.coord[2] = z;
}
+ @Override
public final float getX() {
return this.coord[0];
}
+ @Override
public final float getY() {
return this.coord[1];
}
+ @Override
public final float getZ() {
return this.coord[2];
}
+ @Override
public final boolean isOnCurve() {
return onCurve;
}
- public final void setOnCurve(boolean onCurve) {
+ @Override
+ public final void setOnCurve(final boolean onCurve) {
this.onCurve = onCurve;
}
+ @Override
public final int getId(){
return id;
}
-
- public final void setId(int id){
+
+ @Override
+ public final void setId(final int id){
this.id = id;
}
-
- public boolean equals(Object obj) {
+
+ @Override
+ public boolean equals(final Object obj) {
if( obj == this) {
return true;
}
@@ -140,35 +180,45 @@ public class SVertex implements Vertex {
return false;
}
final Vertex v = (Vertex) obj;
- return this == v ||
- isOnCurve() == v.isOnCurve() &&
- VectorUtil.checkEqualityVec2(getTexCoord(), v.getTexCoord()) &&
- VectorUtil.checkEquality(getCoord(), v.getCoord()) ;
+ return this == v ||
+ isOnCurve() == v.isOnCurve() &&
+ VectorUtil.isVec3Equal(getTexCoord(), 0, v.getTexCoord(), 0, FloatUtil.EPSILON) &&
+ VectorUtil.isVec3Equal(getCoord(), 0, v.getCoord(), 0, FloatUtil.EPSILON) ;
}
-
+ @Override
+ public final int hashCode() {
+ throw new InternalError("hashCode not designed");
+ }
+
+ @Override
public final float[] getTexCoord() {
return texCoord;
}
- public final void setTexCoord(float s, float t) {
- this.texCoord[0] = s;
- this.texCoord[1] = t;
+ @Override
+ public final void setTexCoord(final float s, final float t, final float p) {
+ texCoord[0] = s;
+ texCoord[1] = t;
+ texCoord[2] = p;
}
- public final void setTexCoord(float[] texCoordsBuffer, int offset, int length) {
+ @Override
+ public final void setTexCoord(final float[] texCoordsBuffer, final int offset, final int length) {
System.arraycopy(texCoordsBuffer, offset, texCoord, 0, length);
}
-
+
/**
- * @return deep clone of this Vertex, but keeping the id blank
+ * @return deep clone of this Vertex elements
*/
+ @Override
public SVertex clone(){
- return new SVertex(this.coord, 0, 3, this.texCoord, 0, 2, this.onCurve);
+ return new SVertex(this); // OK to not call super.clone(), using own copy-ctor
}
-
+
+ @Override
public String toString() {
- return "[ID: " + id + ", onCurve: " + onCurve +
+ return "[ID: " + id + ", onCurve: " + onCurve +
": p " + coord[0] + ", " + coord[1] + ", " + coord[2] +
- ", t " + texCoord[0] + ", " + texCoord[1] + "]";
+ ", t " + texCoord[0] + ", " + texCoord[1] + ", " + texCoord[2] + "]";
}
}
diff --git a/src/jogl/classes/com/jogamp/graph/geom/Triangle.java b/src/jogl/classes/com/jogamp/graph/geom/Triangle.java
index fb34de221..fc345f2a7 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/Triangle.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/Triangle.java
@@ -27,53 +27,106 @@
*/
package com.jogamp.graph.geom;
+import com.jogamp.opengl.math.VectorUtil;
+
+import jogamp.graph.geom.plane.AffineTransform;
+
public class Triangle {
- private int id = Integer.MAX_VALUE;
- final private Vertex[] vertices;
- private boolean[] boundaryEdges = new boolean[3];
+ private final Vertex[] vertices = new Vertex[3];
+ private final boolean[] boundaryEdges = new boolean[3];
private boolean[] boundaryVertices = null;
+ private int id;
+
+ public Triangle(final Vertex v1, final Vertex v2, final Vertex v3, final boolean[] boundaryVertices) {
+ id = Integer.MAX_VALUE;
+ vertices[0] = v1;
+ vertices[1] = v2;
+ vertices[2] = v3;
+ this.boundaryVertices = boundaryVertices;
+ }
+
+ public Triangle(final Triangle src) {
+ id = src.id;
+ vertices[0] = src.vertices[0].clone();
+ vertices[1] = src.vertices[1].clone();
+ vertices[2] = src.vertices[2].clone();
+ System.arraycopy(src.boundaryEdges, 0, boundaryEdges, 0, 3);
+ boundaryVertices = new boolean[3];
+ System.arraycopy(src.boundaryVertices, 0, boundaryVertices, 0, 3);
+ }
+
+ private Triangle(final int id, final boolean[] boundaryEdges, final boolean[] boundaryVertices){
+ this.id = id;
+ System.arraycopy(boundaryEdges, 0, this.boundaryEdges, 0, 3);
+ this.boundaryVertices = new boolean[3];
+ System.arraycopy(boundaryVertices, 0, this.boundaryVertices, 0, 3);
+ }
- public Triangle(Vertex ... v123){
- vertices = v123;
+ /**
+ * Returns a transformed a clone of this instance using the given AffineTransform.
+ */
+ public Triangle transform(final AffineTransform t, final Vertex.Factory<? extends Vertex> vertexFactory) {
+ final Triangle tri = new Triangle(id, boundaryEdges, boundaryVertices);
+ tri.vertices[0] = t.transform(vertices[0], vertexFactory.create());
+ tri.vertices[1] = t.transform(vertices[1], vertexFactory.create());
+ tri.vertices[2] = t.transform(vertices[2], vertexFactory.create());
+ return tri;
+ }
+
+ /**
+ * Returns true if all vertices are on-curve, otherwise false.
+ */
+ public final boolean isOnCurve() {
+ return vertices[0].isOnCurve() && vertices[1].isOnCurve() && vertices[2].isOnCurve();
+ }
+
+ /**
+ * Returns true if all vertices are lines, i.e. zero tex-coord, otherwise false.
+ */
+ public final boolean isLine() {
+ return VectorUtil.isVec2Zero(vertices[0].getTexCoord(), 0) &&
+ VectorUtil.isVec2Zero(vertices[1].getTexCoord(), 0) &&
+ VectorUtil.isVec2Zero(vertices[2].getTexCoord(), 0) ;
}
public int getId() {
return id;
}
- public void setId(int id) {
+ public void setId(final int id) {
this.id = id;
}
+ /** Returns array of 3 vertices, denominating the triangle. */
public Vertex[] getVertices() {
return vertices;
}
-
+
public boolean isEdgesBoundary() {
return boundaryEdges[0] || boundaryEdges[1] || boundaryEdges[2];
}
-
+
public boolean isVerticesBoundary() {
return boundaryVertices[0] || boundaryVertices[1] || boundaryVertices[2];
}
- public void setEdgesBoundary(boolean[] boundary) {
- this.boundaryEdges = boundary;
- }
-
public boolean[] getEdgeBoundary() {
return boundaryEdges;
}
-
+
public boolean[] getVerticesBoundary() {
return boundaryVertices;
}
- public void setVerticesBoundary(boolean[] boundaryVertices) {
+ public void setVerticesBoundary(final boolean[] boundaryVertices) {
this.boundaryVertices = boundaryVertices;
}
-
+
+ @Override
public String toString() {
- return "Tri ID: " + id + "\n" + vertices[0] + "\n" + vertices[1] + "\n" + vertices[2];
+ return "Tri ID: " + id + ", onCurve "+isOnCurve()+"\n\t" +
+ vertices[0] + ", bound "+boundaryVertices[0]+"\n\t" +
+ vertices[1] + ", bound "+boundaryVertices[1]+"\n\t" +
+ vertices[2] + ", bound "+boundaryVertices[2];
}
}
diff --git a/src/jogl/classes/com/jogamp/graph/geom/Vertex.java b/src/jogl/classes/com/jogamp/graph/geom/Vertex.java
index 3080f32cc..e9c8dd193 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/Vertex.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/Vertex.java
@@ -27,27 +27,31 @@
*/
package com.jogamp.graph.geom;
+import com.jogamp.opengl.math.Vert3fImmutable;
+
/**
- * A Vertex with custom memory layout using custom factory.
+ * A Vertex with custom memory layout using custom factory.
*/
-public interface Vertex extends Cloneable {
+public interface Vertex extends Vert3fImmutable, Cloneable {
public static interface Factory <T extends Vertex> {
T create();
+ T create(Vertex src);
+
+ T create(int id, boolean onCurve, float[] texCoordsBuffer);
+
T create(float x, float y, float z, boolean onCurve);
- T create(float[] coordsBuffer, int offset, int length, boolean onCurve);
+ T create(float[] coordsBuffer, int offset, int length, boolean onCurve);
}
-
+
void setCoord(float x, float y, float z);
/**
* @see System#arraycopy(Object, int, Object, int, int) for thrown IndexOutOfBoundsException
*/
void setCoord(float[] coordsBuffer, int offset, int length);
-
- float[] getCoord();
void setX(float x);
@@ -55,35 +59,30 @@ public interface Vertex extends Cloneable {
void setZ(float z);
- float getX();
-
- float getY();
-
- float getZ();
-
boolean isOnCurve();
void setOnCurve(boolean onCurve);
int getId();
-
+
void setId(int id);
-
+
float[] getTexCoord();
-
- void setTexCoord(float s, float t);
-
+
+ void setTexCoord(float s, float t, float p);
+
/**
* @see System#arraycopy(Object, int, Object, int, int) for thrown IndexOutOfBoundsException
*/
void setTexCoord(float[] texCoordsBuffer, int offset, int length);
-
+
/**
* @param obj the Object to compare this Vertex with
- * @return true if {@code obj} is a Vertex and not null, on-curve flag is equal and has same vertex- and tex-coords.
+ * @return true if {@code obj} is a Vertex and not null, on-curve flag is equal and has same vertex- and tex-coords.
*/
+ @Override
boolean equals(Object obj);
-
+
/**
* @return deep clone of this Vertex
*/
diff --git a/src/jogl/classes/com/jogamp/graph/math/Quaternion.java b/src/jogl/classes/com/jogamp/graph/math/Quaternion.java
deleted file mode 100755
index adaf073e3..000000000
--- a/src/jogl/classes/com/jogamp/graph/math/Quaternion.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.graph.math;
-
-import jogamp.graph.math.MathFloat;
-
-public class Quaternion {
- protected float x,y,z,w;
-
- public Quaternion(){
-
- }
-
- public Quaternion(float x, float y, float z, float w) {
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
- }
-
- /** Constructor to create a rotation based quaternion from two vectors
- * @param vector1
- * @param vector2
- */
- public Quaternion(float[] vector1, float[] vector2)
- {
- float theta = (float)MathFloat.acos(dot(vector1, vector2));
- float[] cross = cross(vector1,vector2);
- cross = normalizeVec(cross);
-
- this.x = (float)MathFloat.sin(theta/2)*cross[0];
- this.y = (float)MathFloat.sin(theta/2)*cross[1];
- this.z = (float)MathFloat.sin(theta/2)*cross[2];
- this.w = (float)MathFloat.cos(theta/2);
- this.normalize();
- }
-
- /** Transform the rotational quaternion to axis based rotation angles
- * @return new float[4] with ,theta,Rx,Ry,Rz
- */
- public float[] toAxis()
- {
- float[] vec = new float[4];
- float scale = (float)MathFloat.sqrt(x * x + y * y + z * z);
- vec[0] =(float) MathFloat.acos(w) * 2.0f;
- vec[1] = x / scale;
- vec[2] = y / scale;
- vec[3] = z / scale;
- return vec;
- }
-
- /** Normalize a vector
- * @param vector input vector
- * @return normalized vector
- */
- private float[] normalizeVec(float[] vector)
- {
- float[] newVector = new float[3];
-
- float d = MathFloat.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]);
- if(d> 0.0f)
- {
- newVector[0] = vector[0]/d;
- newVector[1] = vector[1]/d;
- newVector[2] = vector[2]/d;
- }
- return newVector;
- }
- /** compute the dot product of two points
- * @param vec1 vector 1
- * @param vec2 vector 2
- * @return the dot product as float
- */
- private float dot(float[] vec1, float[] vec2)
- {
- return (vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]);
- }
- /** cross product vec1 x vec2
- * @param vec1 vector 1
- * @param vec2 vecttor 2
- * @return the resulting vector
- */
- private float[] cross(float[] vec1, float[] vec2)
- {
- float[] out = new float[3];
-
- out[0] = vec2[2]*vec1[1] - vec2[1]*vec1[2];
- out[1] = vec2[0]*vec1[2] - vec2[2]*vec1[0];
- out[2] = vec2[1]*vec1[0] - vec2[0]*vec1[1];
-
- return out;
- }
- public float getW() {
- return w;
- }
- public void setW(float w) {
- this.w = w;
- }
- public float getX() {
- return x;
- }
- public void setX(float x) {
- this.x = x;
- }
- public float getY() {
- return y;
- }
- public void setY(float y) {
- this.y = y;
- }
- public float getZ() {
- return z;
- }
- public void setZ(float z) {
- this.z = z;
- }
-
- /** Add a quaternion
- * @param q quaternion
- */
- public void add(Quaternion q)
- {
- x+=q.x;
- y+=q.y;
- z+=q.z;
- }
-
- /** Subtract a quaternion
- * @param q quaternion
- */
- public void subtract(Quaternion q)
- {
- x-=q.x;
- y-=q.y;
- z-=q.z;
- }
-
- /** Divide a quaternion by a constant
- * @param n a float to divide by
- */
- public void divide(float n)
- {
- x/=n;
- y/=n;
- z/=n;
- }
-
- /** Multiply this quaternion by
- * the param quaternion
- * @param q a quaternion to multiply with
- */
- public void mult(Quaternion q)
- {
- float w1 = w*q.w - (x*q.x + y*q.y + z*q.z);
-
- float x1 = w*q.z + q.w*z + y*q.z - z*q.y;
- float y1 = w*q.x + q.w*x + z*q.x - x*q.z;
- float z1 = w*q.y + q.w*y + x*q.y - y*q.x;
-
- w = w1;
- x = x1;
- y = y1;
- z = z1;
- }
-
- /** Multiply a quaternion by a constant
- * @param n a float constant
- */
- public void mult(float n)
- {
- x*=n;
- y*=n;
- z*=n;
- }
-
- /** Normalize a quaternion required if
- * to be used as a rotational quaternion
- */
- public void normalize()
- {
- float norme = (float)MathFloat.sqrt(w*w + x*x + y*y + z*z);
- if (norme == 0.0f)
- {
- w = 1.0f;
- x = y = z = 0.0f;
- }
- else
- {
- float recip = 1.0f/norme;
-
- w *= recip;
- x *= recip;
- y *= recip;
- z *= recip;
- }
- }
-
- /** Invert the quaternion If rotational,
- * will produce a the inverse rotation
- */
- public void inverse()
- {
- float norm = w*w + x*x + y*y + z*z;
-
- float recip = 1.0f/norm;
-
- w *= recip;
- x = -1*x*recip;
- y = -1*y*recip;
- z = -1*z*recip;
- }
-
- /** Transform this quaternion to a
- * 4x4 column matrix representing the rotation
- * @return new float[16] column matrix 4x4
- */
- public float[] toMatrix()
- {
- float[] matrix = new float[16];
- matrix[0] = 1.0f - 2*y*y - 2*z*z;
- matrix[1] = 2*x*y + 2*w*z;
- matrix[2] = 2*x*z - 2*w*y;
- matrix[3] = 0;
-
- matrix[4] = 2*x*y - 2*w*z;
- matrix[5] = 1.0f - 2*x*x - 2*z*z;
- matrix[6] = 2*y*z + 2*w*x;
- matrix[7] = 0;
-
- matrix[8] = 2*x*z + 2*w*y;
- matrix[9] = 2*y*z - 2*w*x;
- matrix[10] = 1.0f - 2*x*x - 2*y*y;
- matrix[11] = 0;
-
- matrix[12] = 0;
- matrix[13] = 0;
- matrix[14] = 0;
- matrix[15] = 1;
- return matrix;
- }
-
- /** Set this quaternion from a Sphereical interpolation
- * of two param quaternion, used mostly for rotational animation
- * @param a initial quaternion
- * @param b target quaternion
- * @param t float between 0 and 1 representing interp.
- */
- public void slerp(Quaternion a,Quaternion b, float t)
- {
- float omega, cosom, sinom, sclp, sclq;
- cosom = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
- if ((1.0f+cosom) > MathFloat.E) {
- if ((1.0f-cosom) > MathFloat.E) {
- omega = (float)MathFloat.acos(cosom);
- sinom = (float)MathFloat.sin(omega);
- sclp = (float)MathFloat.sin((1.0f-t)*omega) / sinom;
- sclq = (float)MathFloat.sin(t*omega) / sinom;
- }
- else {
- sclp = 1.0f - t;
- sclq = t;
- }
- x = sclp*a.x + sclq*b.x;
- y = sclp*a.y + sclq*b.y;
- z = sclp*a.z + sclq*b.z;
- w = sclp*a.w + sclq*b.w;
- }
- else {
- x =-a.y;
- y = a.x;
- z =-a.w;
- w = a.z;
- sclp = MathFloat.sin((1.0f-t) * MathFloat.PI * 0.5f);
- sclq = MathFloat.sin(t * MathFloat.PI * 0.5f);
- x = sclp*a.x + sclq*b.x;
- y = sclp*a.y + sclq*b.y;
- z = sclp*a.z + sclq*b.z;
- }
- }
-
- /** Check if this quaternion is empty, ie (0,0,0,1)
- * @return true if empty, false otherwise
- */
- public boolean isEmpty()
- {
- if (w==1 && x==0 && y==0 && z==0)
- return true;
- return false;
- }
-
- /** Check if this quaternion represents an identity
- * matrix, for rotation.
- * @return true if it is an identity rep., false otherwise
- */
- public boolean isIdentity()
- {
- if (w==0 && x==0 && y==0 && z==0)
- return true;
- return false;
- }
-
- /** compute the quaternion from a 3x3 column matrix
- * @param m 3x3 column matrix
- */
- public void setFromMatrix(float[] m) {
- float T= m[0] + m[4] + m[8] + 1;
- if (T>0){
- float S = 0.5f / (float)MathFloat.sqrt(T);
- w = 0.25f / S;
- x = ( m[5] - m[7]) * S;
- y = ( m[6] - m[2]) * S;
- z = ( m[1] - m[3] ) * S;
- }
- else{
- if ((m[0] > m[4])&(m[0] > m[8])) {
- float S = MathFloat.sqrt( 1.0f + m[0] - m[4] - m[8] ) * 2f; // S=4*qx
- w = (m[7] - m[5]) / S;
- x = 0.25f * S;
- y = (m[3] + m[1]) / S;
- z = (m[6] + m[2]) / S;
- }
- else if (m[4] > m[8]) {
- float S = MathFloat.sqrt( 1.0f + m[4] - m[0] - m[8] ) * 2f; // S=4*qy
- w = (m[6] - m[2]) / S;
- x = (m[3] + m[1]) / S;
- y = 0.25f * S;
- z = (m[7] + m[5]) / S;
- }
- else {
- float S = MathFloat.sqrt( 1.0f + m[8] - m[0] - m[4] ) * 2f; // S=4*qz
- w = (m[3] - m[1]) / S;
- x = (m[6] + m[2]) / S;
- y = (m[7] + m[5]) / S;
- z = 0.25f * S;
- }
- }
- }
-
- /** Check if the the 3x3 matrix (param) is in fact
- * an affine rotational matrix
- * @param m 3x3 column matrix
- * @return true if representing a rotational matrix, false otherwise
- */
- public boolean isRotationMatrix(float[] m) {
- double epsilon = 0.01; // margin to allow for rounding errors
- if (MathFloat.abs(m[0]*m[3] + m[3]*m[4] + m[6]*m[7]) > epsilon) return false;
- if (MathFloat.abs(m[0]*m[2] + m[3]*m[5] + m[6]*m[8]) > epsilon) return false;
- if (MathFloat.abs(m[1]*m[2] + m[4]*m[5] + m[7]*m[8]) > epsilon) return false;
- if (MathFloat.abs(m[0]*m[0] + m[3]*m[3] + m[6]*m[6] - 1) > epsilon) return false;
- if (MathFloat.abs(m[1]*m[1] + m[4]*m[4] + m[7]*m[7] - 1) > epsilon) return false;
- if (MathFloat.abs(m[2]*m[2] + m[5]*m[5] + m[8]*m[8] - 1) > epsilon) return false;
- return (MathFloat.abs(determinant(m)-1) < epsilon);
- }
- private float determinant(float[] m) {
- return m[0]*m[4]*m[8] + m[3]*m[7]*m[2] + m[6]*m[1]*m[5] - m[0]*m[7]*m[5] - m[3]*m[1]*m[8] - m[6]*m[4]*m[2];
- }
-}
diff --git a/src/jogl/classes/com/jogamp/graph/math/VectorUtil.java b/src/jogl/classes/com/jogamp/graph/math/VectorUtil.java
deleted file mode 100755
index d51afcbab..000000000
--- a/src/jogl/classes/com/jogamp/graph/math/VectorUtil.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.graph.math;
-
-import java.util.ArrayList;
-
-import jogamp.graph.math.MathFloat;
-
-import com.jogamp.graph.geom.Vertex;
-
-public class VectorUtil {
-
- public enum Winding {
- CW(-1), CCW(1);
-
- public final int dir;
-
- Winding(int dir) {
- this.dir = dir;
- }
- }
-
- public static final int COLLINEAR = 0;
-
- /** compute the dot product of two points
- * @param vec1 vector 1
- * @param vec2 vector 2
- * @return the dot product as float
- */
- public static float dot(float[] vec1, float[] vec2)
- {
- return (vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]);
- }
- /** Normalize a vector
- * @param vector input vector
- * @return normalized vector
- */
- public static float[] normalize(float[] vector)
- {
- float[] newVector = new float[3];
-
- float d = MathFloat.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]);
- if(d> 0.0f)
- {
- newVector[0] = vector[0]/d;
- newVector[1] = vector[1]/d;
- newVector[2] = vector[2]/d;
- }
- return newVector;
- }
-
- /** Scales a vector by param
- * @param vector input vector
- * @param scale constant to scale by
- * @return scaled vector
- */
- public static float[] scale(float[] vector, float scale)
- {
- float[] newVector = new float[3];
-
- newVector[0] = vector[0]*scale;
- newVector[1] = vector[1]*scale;
- newVector[2] = vector[2]*scale;
- return newVector;
- }
-
- /** Adds to vectors
- * @param v1 vector 1
- * @param v2 vector 2
- * @return v1 + v2
- */
- public static float[] vectorAdd(float[] v1, float[] v2)
- {
- float[] newVector = new float[3];
-
- newVector[0] = v1[0] + v2[0];
- newVector[1] = v1[1] + v2[1];
- newVector[2] = v1[2] + v2[2];
- return newVector;
- }
-
- /** cross product vec1 x vec2
- * @param vec1 vector 1
- * @param vec2 vecttor 2
- * @return the resulting vector
- */
- public static float[] cross(float[] vec1, float[] vec2)
- {
- float[] out = new float[3];
-
- out[0] = vec2[2]*vec1[1] - vec2[1]*vec1[2];
- out[1] = vec2[0]*vec1[2] - vec2[2]*vec1[0];
- out[2] = vec2[1]*vec1[0] - vec2[0]*vec1[1];
-
- return out;
- }
-
- /** Column Matrix Vector multiplication
- * @param colMatrix column matrix (4x4)
- * @param vec vector(x,y,z)
- * @return result new float[3]
- */
- public static float[] colMatrixVectorMult(float[] colMatrix, float[] vec)
- {
- float[] out = new float[3];
-
- out[0] = vec[0]*colMatrix[0] + vec[1]*colMatrix[4] + vec[2]*colMatrix[8] + colMatrix[12];
- out[1] = vec[0]*colMatrix[1] + vec[1]*colMatrix[5] + vec[2]*colMatrix[9] + colMatrix[13];
- out[2] = vec[0]*colMatrix[2] + vec[1]*colMatrix[6] + vec[2]*colMatrix[10] + colMatrix[14];
-
- return out;
- }
-
- /** Matrix Vector multiplication
- * @param rawMatrix column matrix (4x4)
- * @param vec vector(x,y,z)
- * @return result new float[3]
- */
- public static float[] rowMatrixVectorMult(float[] rawMatrix, float[] vec)
- {
- float[] out = new float[3];
-
- out[0] = vec[0]*rawMatrix[0] + vec[1]*rawMatrix[1] + vec[2]*rawMatrix[2] + rawMatrix[3];
- out[1] = vec[0]*rawMatrix[4] + vec[1]*rawMatrix[5] + vec[2]*rawMatrix[6] + rawMatrix[7];
- out[2] = vec[0]*rawMatrix[8] + vec[1]*rawMatrix[9] + vec[2]*rawMatrix[10] + rawMatrix[11];
-
- return out;
- }
-
- /** Calculate the midpoint of two values
- * @param p1 first value
- * @param p2 second vale
- * @return midpoint
- */
- public static float mid(float p1, float p2)
- {
- return (p1+p2)/2.0f;
- }
- /** Calculate the midpoint of two points
- * @param p1 first point
- * @param p2 second point
- * @return midpoint
- */
- public static float[] mid(float[] p1, float[] p2)
- {
- float[] midPoint = new float[3];
- midPoint[0] = (p1[0] + p2[0])*0.5f;
- midPoint[1] = (p1[1] + p2[1])*0.5f;
- midPoint[2] = (p1[2] + p2[2])*0.5f;
-
- return midPoint;
- }
- /** Compute the norm of a vector
- * @param vec vector
- * @return vorm
- */
- public static float norm(float[] vec)
- {
- return MathFloat.sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
- }
- /** Compute distance between 2 points
- * @param p0 a ref point on the line
- * @param vec vector representing the direction of the line
- * @param point the point to compute the relative distance of
- * @return distance float
- */
- public static float computeLength(float[] p0, float[] point)
- {
- float[] w = new float[]{point[0]-p0[0],point[1]-p0[1],point[2]-p0[2]};
-
- float distance = MathFloat.sqrt(w[0]*w[0] + w[1]*w[1] + w[2]*w[2]);
-
- return distance;
- }
-
- /**Check equality of 2 vec3 vectors
- * @param v1 vertex 1
- * @param v2 vertex 2
- * @return
- */
- public static boolean checkEquality(float[] v1, float[] v2)
- {
- if(Float.compare(v1[0], v2[0]) == 0 &&
- Float.compare(v1[1], v2[1]) == 0 &&
- Float.compare(v1[2], v2[2]) == 0 )
- return true;
- return false;
- }
-
- /**Check equality of 2 vec2 vectors
- * @param v1 vertex 1
- * @param v2 vertex 2
- * @return
- */
- public static boolean checkEqualityVec2(float[] v1, float[] v2)
- {
- if(Float.compare(v1[0], v2[0]) == 0 &&
- Float.compare(v1[1], v2[1]) == 0)
- return true;
- return false;
- }
-
- /** Compute the determinant of 3 vectors
- * @param a vector 1
- * @param b vector 2
- * @param c vector 3
- * @return the determinant value
- */
- public static float computeDeterminant(float[] a, float[] b, float[] c)
- {
- float area = a[0]*b[1]*c[2] + a[1]*b[2]*c[0] + a[2]*b[0]*c[1] - a[0]*b[2]*c[1] - a[1]*b[0]*c[2] - a[2]*b[1]*c[0];
- return area;
- }
-
- /** Check if three vertices are colliniear
- * @param v1 vertex 1
- * @param v2 vertex 2
- * @param v3 vertex 3
- * @return true if collinear, false otherwise
- */
- public static boolean checkCollinear(float[] v1, float[] v2, float[] v3)
- {
- return (computeDeterminant(v1, v2, v3) == VectorUtil.COLLINEAR);
- }
-
- /** Compute Vector
- * @param v1 vertex 1
- * @param v2 vertex2 2
- * @return Vector V1V2
- */
- public static float[] computeVector(float[] v1, float[] v2)
- {
- float[] vector = new float[3];
- vector[0] = v2[0] - v1[0];
- vector[1] = v2[1] - v1[1];
- vector[2] = v2[2] - v1[2];
- return vector;
- }
-
- /** Check if vertices in triangle circumcircle
- * @param a triangle vertex 1
- * @param b triangle vertex 2
- * @param c triangle vertex 3
- * @param d vertex in question
- * @return true if the vertex d is inside the circle defined by the
- * vertices a, b, c. from paper by Guibas and Stolfi (1985).
- */
- public static boolean inCircle(Vertex a, Vertex b, Vertex c, Vertex d){
- return (a.getX() * a.getX() + a.getY() * a.getY()) * triArea(b, c, d) -
- (b.getX() * b.getX() + b.getY() * b.getY()) * triArea(a, c, d) +
- (c.getX() * c.getX() + c.getY() * c.getY()) * triArea(a, b, d) -
- (d.getX() * d.getX() + d.getY() * d.getY()) * triArea(a, b, c) > 0;
- }
-
- /** Computes oriented area of a triangle
- * @param a first vertex
- * @param b second vertex
- * @param c third vertex
- * @return compute twice the area of the oriented triangle (a,b,c), the area
- * is positive if the triangle is oriented counterclockwise.
- */
- public static float triArea(Vertex a, Vertex b, Vertex c){
- return (b.getX() - a.getX()) * (c.getY() - a.getY()) - (b.getY() - a.getY())*(c.getX() - a.getX());
- }
-
- /** Check if a vertex is in triangle using
- * barycentric coordinates computation.
- * @param a first triangle vertex
- * @param b second triangle vertex
- * @param c third triangle vertex
- * @param p the vertex in question
- * @return true if p is in triangle (a, b, c), false otherwise.
- */
- public static boolean vertexInTriangle(float[] a, float[] b, float[] c, float[] p){
- // Compute vectors
- float[] ac = computeVector(a, c); //v0
- float[] ab = computeVector(a, b); //v1
- float[] ap = computeVector(a, p); //v2
-
- // Compute dot products
- float dot00 = dot(ac, ac);
- float dot01 = dot(ac, ab);
- float dot02 = dot(ac, ap);
- float dot11 = dot(ab, ab);
- float dot12 = dot(ab, ap);
-
- // Compute barycentric coordinates
- float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
- float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
- float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
-
- // Check if point is in triangle
- return (u >= 0) && (v >= 0) && (u + v < 1);
- }
-
- /** Check if points are in ccw order
- * @param a first vertex
- * @param b second vertex
- * @param c third vertex
- * @return true if the points a,b,c are in a ccw order
- */
- public static boolean ccw(Vertex a, Vertex b, Vertex c){
- return triArea(a,b,c) > 0;
- }
-
- /** Compute the winding of given points
- * @param a first vertex
- * @param b second vertex
- * @param c third vertex
- * @return Winding
- */
- public static Winding getWinding(Vertex a, Vertex b, Vertex c) {
- return triArea(a,b,c) > 0 ? Winding.CCW : Winding.CW ;
- }
-
- /** Computes the area of a list of vertices to check if ccw
- * @param vertices
- * @return positive area if ccw else negative area value
- */
- public static float area(ArrayList<Vertex> vertices) {
- int n = vertices.size();
- float area = 0.0f;
- for (int p = n - 1, q = 0; q < n; p = q++)
- {
- float[] pCoord = vertices.get(p).getCoord();
- float[] qCoord = vertices.get(q).getCoord();
- area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1];
- }
- return area;
- }
-
- /** Compute the general winding of the vertices
- * @param vertices array of Vertices
- * @return CCW or CW {@link Winding}
- */
- public static Winding getWinding(ArrayList<Vertex> vertices) {
- return area(vertices) >= 0 ? Winding.CCW : Winding.CW ;
- }
-
-
- /** Compute intersection between two segments
- * @param a vertex 1 of first segment
- * @param b vertex 2 of first segment
- * @param c vertex 1 of second segment
- * @param d vertex 2 of second segment
- * @return the intersection coordinates if the segments intersect, otherwise
- * returns null
- */
- public static float[] seg2SegIntersection(Vertex a, Vertex b, Vertex c, Vertex d) {
- float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
-
- if (determinant == 0)
- return null;
-
- float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
- float beta = (c.getX()*d.getY()-c.getY()*d.getY());
- float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
- float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
-
- float gamma = (xi - a.getX())/(b.getX() - a.getX());
- float gamma1 = (xi - c.getX())/(d.getX() - c.getX());
- if(gamma <= 0 || gamma >= 1) return null;
- if(gamma1 <= 0 || gamma1 >= 1) return null;
-
- return new float[]{xi,yi,0};
- }
-
- /** Compute intersection between two lines
- * @param a vertex 1 of first line
- * @param b vertex 2 of first line
- * @param c vertex 1 of second line
- * @param d vertex 2 of second line
- * @return the intersection coordinates if the lines intersect, otherwise
- * returns null
- */
- public static float[] line2lineIntersection(Vertex a, Vertex b, Vertex c, Vertex d) {
- float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
-
- if (determinant == 0)
- return null;
-
- float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
- float beta = (c.getX()*d.getY()-c.getY()*d.getY());
- float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
- float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
-
- return new float[]{xi,yi,0};
- }
-
- /** Check if a segment intersects with a triangle
- * @param a vertex 1 of the triangle
- * @param b vertex 2 of the triangle
- * @param c vertex 3 of the triangle
- * @param d vertex 1 of first segment
- * @param e vertex 2 of first segment
- * @return true if the segment intersects at least one segment of the triangle, false otherwise
- */
- public static boolean tri2SegIntersection(Vertex a, Vertex b, Vertex c, Vertex d, Vertex e){
- if(seg2SegIntersection(a, b, d, e) != null)
- return true;
- if(seg2SegIntersection(b, c, d, e) != null)
- return true;
- if(seg2SegIntersection(a, c, d, e) != null)
- return true;
-
- return false;
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java
index cc0af29a9..03693a688 100644
--- a/src/jogl/classes/com/jogamp/opengl/FBObject.java
+++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java
@@ -28,79 +28,120 @@
package com.jogamp.opengl;
-import java.util.ArrayList;
import java.util.Arrays;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GL3;
import javax.media.opengl.GLBase;
import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import jogamp.opengl.Debug;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.opengl.FBObject.Attachment.Type;
/**
* Core utility class simplifying usage of framebuffer objects (FBO)
- * with all {@link GLProfile}s.
+ * with all {@link GLProfile}s.
* <p>
- * Supports on-the-fly reconfiguration of dimension and multisample buffers via {@link #reset(GL, int, int, int)}
+ * Supports on-the-fly reconfiguration of dimension and multisample buffers via {@link #reset(GL, int, int, int, boolean)}
* while preserving the {@link Attachment} references.
* </p>
* <p>
* Integrates default read/write framebuffers via {@link GLContext#getDefaultReadFramebuffer()} and {@link GLContext#getDefaultReadFramebuffer()},
* which is being hooked at {@link GL#glBindFramebuffer(int, int)} when the default (<code>zero</code>) framebuffer is selected.
* </p>
- *
+ *
* <p>FIXME: Implement support for {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} .</p>
*/
public class FBObject {
- protected static final boolean DEBUG = Debug.debug("FBObject");
- private static final boolean forceMinimumFBOSupport = Debug.isPropertyDefined("jogl.fbo.force.min", true);
-
+ protected static final boolean DEBUG;
+ private static final int USER_MAX_TEXTURE_SIZE;
+ private static final boolean FBOResizeQuirk = false;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = Debug.debug("FBObject");
+ USER_MAX_TEXTURE_SIZE = PropertyAccess.getIntProperty("jogl.debug.FBObject.MaxTextureSize", true, 0);
+ }
+
private static enum DetachAction { NONE, DISPOSE, RECREATE };
-
- /**
- * Marker interface, denotes a color buffer attachment.
+
+ /**
+ * Generic color buffer FBO attachment, either of type {@link ColorAttachment} or {@link TextureAttachment}.
* <p>Always an instance of {@link Attachment}.</p>
- * <p>Either an instance of {@link ColorAttachment} or {@link TextureAttachment}.</b>
*/
- public static interface Colorbuffer {
- /**
+ public static interface Colorbuffer {
+ /**
* Initializes the color buffer and set it's parameter, if uninitialized, i.e. name is <code>zero</code>.
* @return <code>true</code> if newly initialized, otherwise <code>false</code>.
- * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case.
+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case.
*/
- public boolean initialize(GL gl) throws GLException;
-
- /**
+ boolean initialize(final GL gl) throws GLException;
+
+ /**
* Releases the color buffer if initialized, i.e. name is not <code>zero</code>.
- * @throws GLException if buffer release fails.
+ * @throws GLException if buffer release fails.
*/
- public void free(GL gl) throws GLException;
-
+ void free(final GL gl) throws GLException;
+
/**
* Writes the internal format to the given GLCapabilities object.
* @param caps the destination for format bits
* @param rgba8Avail whether rgba8 is available
*/
- public void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail);
+ void formatToGLCapabilities(final GLCapabilities caps, final boolean rgba8Avail);
+
+ /**
+ * Returns <code>true</code> if instance is of type {@link TextureAttachment}
+ * and <code>false</code> if instance is of type {@link ColorAttachment}.
+ */
+ boolean isTextureAttachment();
+
+ /**
+ * Casts this object to a {@link TextureAttachment} reference, see {@link #isTextureAttachment()}.
+ * @throws GLException if this object is not of type {@link TextureAttachment}
+ * @see #isTextureAttachment()
+ */
+ TextureAttachment getTextureAttachment();
+
+ /**
+ * Casts this object to a {@link ColorAttachment} reference, see {@link #isTextureAttachment()}.
+ * @throws GLException if this object is not of type {@link ColorAttachment}
+ * @see #isTextureAttachment()
+ */
+ ColorAttachment getColorAttachment();
+
+ /** internal format of colorbuffer */
+ int getFormat();
+
+ /** width of colorbuffer */
+ int getWidth();
+
+ /** height of colorbuffer */
+ int getHeight();
+
+ /** colorbuffer name [1..max] */
+ int getName();
}
-
- /** Common super class of all attachments */
+
+ /** Common super class of all FBO attachments */
public static abstract class Attachment {
- public enum Type {
+ public enum Type {
NONE, DEPTH, STENCIL, DEPTH_STENCIL, COLOR, COLOR_TEXTURE, DEPTH_TEXTURE, STENCIL_TEXTURE;
-
- /**
+
+ /**
* Returns {@link #COLOR}, {@link #DEPTH}, {@link #STENCIL} or {@link #DEPTH_STENCIL}
- * @throws IllegalArgumentException if <code>format</code> cannot be handled.
+ * @throws IllegalArgumentException if <code>format</code> cannot be handled.
*/
- public static Type determine(int format) throws IllegalArgumentException {
+ public static Type determine(final int format) throws IllegalArgumentException {
switch(format) {
case GL.GL_RGBA4:
case GL.GL_RGB5_A1:
@@ -119,41 +160,43 @@ public class FBObject {
case GL.GL_DEPTH24_STENCIL8:
return Type.DEPTH_STENCIL;
default:
- throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format));
- }
+ throw new IllegalArgumentException("format invalid: "+toHexString(format));
+ }
}
};
-
+
/** immutable type [{@link #COLOR}, {@link #DEPTH}, {@link #STENCIL}, {@link #COLOR_TEXTURE}, {@link #DEPTH_TEXTURE}, {@link #STENCIL_TEXTURE} ] */
public final Type type;
-
+
/** immutable the internal format */
public final int format;
-
+
private int width, height;
-
+
private int name;
-
- protected Attachment(Type type, int iFormat, int width, int height, int name) {
+
+ protected Attachment(final Type type, final int iFormat, final int width, final int height, final int name) {
this.type = type;
this.format = iFormat;
this.width = width;
this.height = height;
this.name = name;
}
-
+
/**
* Writes the internal format to the given GLCapabilities object.
* @param caps the destination for format bits
* @param rgba8Avail whether rgba8 is available
*/
- public final void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail) {
+ public final void formatToGLCapabilities(final GLCapabilities caps, final boolean rgba8Avail) {
final int _format;
switch(format) {
case GL.GL_RGBA:
- _format = rgba8Avail ? GL.GL_RGBA8 : GL.GL_RGBA4;
+ case 4:
+ _format = rgba8Avail ? GL.GL_RGBA8 : GL.GL_RGBA4;
break;
case GL.GL_RGB:
+ case 3:
_format = rgba8Avail ? GL.GL_RGB8 : GL.GL_RGB565;
break;
default:
@@ -189,7 +232,7 @@ public class FBObject {
caps.setGreenBits(8);
caps.setBlueBits(8);
caps.setAlphaBits(8);
- break;
+ break;
case GL.GL_DEPTH_COMPONENT16:
caps.setDepthBits(16);
break;
@@ -213,21 +256,24 @@ public class FBObject {
caps.setStencilBits(8);
break;
default:
- throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format));
+ throw new IllegalArgumentException("format invalid: "+toHexString(format));
}
}
-
+
+ /** immutable internal format of attachment */
+ public final int getFormat() { return format; }
+
/** width of attachment */
public final int getWidth() { return width; }
/** height of attachment */
public final int getHeight() { return height; }
- /* pp */ final void setSize(int w, int h) { width = w; height = h; }
-
+ /* pp */ final void setSize(final int w, final int h) { width = w; height = h; }
+
/** buffer name [1..max], maybe a texture or renderbuffer name, depending on type. */
- public final int getName() { return name; }
- /* pp */ final void setName(int n) { name = n; }
-
- /**
+ public final int getName() { return name; }
+ /* pp */ final void setName(final int n) { name = n; }
+
+ /**
* Initializes the attachment and set it's parameter, if uninitialized, i.e. name is <code>zero</code>.
* <pre>
final boolean init = 0 == name;
@@ -237,11 +283,11 @@ public class FBObject {
return init;
* </pre>
* @return <code>true</code> if newly initialized, otherwise <code>false</code>.
- * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case.
+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case.
*/
- public abstract boolean initialize(GL gl) throws GLException;
-
- /**
+ public abstract boolean initialize(final GL gl) throws GLException;
+
+ /**
* Releases the attachment if initialized, i.e. name is not <code>zero</code>.
* <pre>
if(0 != name) {
@@ -249,10 +295,10 @@ public class FBObject {
name = 0;
}
* </pre>
- * @throws GLException if buffer release fails.
+ * @throws GLException if buffer release fails.
*/
- public abstract void free(GL gl) throws GLException;
-
+ public abstract void free(final GL gl) throws GLException;
+
/**
* <p>
* Comparison by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}.
@@ -260,7 +306,7 @@ public class FBObject {
* {@inheritDoc}
*/
@Override
- public boolean equals(Object o) {
+ public boolean equals(final Object o) {
if( this == o ) return true;
if( ! ( o instanceof Attachment ) ) return false;
final Attachment a = (Attachment)o;
@@ -270,7 +316,7 @@ public class FBObject {
height== a.height &&
name == a.name ;
}
-
+
/**
* <p>
* Hashed by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}.
@@ -287,25 +333,26 @@ public class FBObject {
hash = ((hash << 5) - hash) + name;
return hash;
}
-
+
int objectHashCode() { return super.hashCode(); }
-
+
+ @Override
public String toString() {
- return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+
- ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+"]";
+ return getClass().getSimpleName()+"[type "+type+", format "+toHexString(format)+", "+width+"x"+height+
+ "; name "+toHexString(name)+", obj "+toHexString(objectHashCode())+"]";
}
-
- public static Type getType(int attachmentPoint, int maxColorAttachments) {
+
+ public static Type getType(final int attachmentPoint, final int maxColorAttachments) {
if( GL.GL_COLOR_ATTACHMENT0 <= attachmentPoint && attachmentPoint < GL.GL_COLOR_ATTACHMENT0+maxColorAttachments ) {
return Type.COLOR;
}
switch(attachmentPoint) {
case GL.GL_DEPTH_ATTACHMENT:
return Type.DEPTH;
- case GL.GL_STENCIL_ATTACHMENT:
+ case GL.GL_STENCIL_ATTACHMENT:
return Type.STENCIL;
- default:
- throw new IllegalArgumentException("Invalid attachment point 0x"+Integer.toHexString(attachmentPoint));
+ default:
+ throw new IllegalArgumentException("Invalid attachment point "+toHexString(attachmentPoint));
}
}
}
@@ -313,35 +360,36 @@ public class FBObject {
/** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */
public static class RenderAttachment extends Attachment {
private int samples;
-
+
/**
- * @param type allowed types are {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#COLOR}
+ * @param type allowed types are {@link Type#DEPTH_STENCIL} {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#COLOR}
* @param iFormat
* @param samples
* @param width
* @param height
* @param name
*/
- public RenderAttachment(Type type, int iFormat, int samples, int width, int height, int name) {
+ public RenderAttachment(final Type type, final int iFormat, final int samples, final int width, final int height, final int name) {
super(validateType(type), iFormat, width, height, name);
this.samples = samples;
}
-
+
/** number of samples, or zero for no multisampling */
public final int getSamples() { return samples; }
- /* pp */ final void setSamples(int s) { samples = s; }
-
- private static Type validateType(Type type) {
+ /* pp */ final void setSamples(final int s) { samples = s; }
+
+ private static Type validateType(final Type type) {
switch(type) {
+ case DEPTH_STENCIL:
case DEPTH:
case STENCIL:
case COLOR:
return type;
- default:
+ default:
throw new IllegalArgumentException("Invalid type: "+type);
}
}
-
+
/**
* <p>
* Comparison by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}.
@@ -349,13 +397,13 @@ public class FBObject {
* {@inheritDoc}
*/
@Override
- public boolean equals(Object o) {
+ public boolean equals(final Object o) {
if( this == o ) return true;
if( ! ( o instanceof RenderAttachment ) ) return false;
return super.equals(o) &&
samples == ((RenderAttachment)o).samples;
}
-
+
/**
* <p>
* Hashed by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}.
@@ -371,60 +419,72 @@ public class FBObject {
}
@Override
- public boolean initialize(GL gl) throws GLException {
+ public boolean initialize(final GL gl) throws GLException {
final boolean init = 0 == getName();
if( init ) {
- int glerr = checkPreGLError(gl);
-
+ final boolean checkError = DEBUG || GLContext.DEBUG_GL;
+ if( checkError ) {
+ checkPreGLError(gl);
+ }
final int[] name = new int[] { -1 };
gl.glGenRenderbuffers(1, name, 0);
setName(name[0]);
-
+
gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName());
if( samples > 0 ) {
- ((GL2GL3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight());
+ ((GL2ES3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight());
} else {
gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight());
}
- glerr = gl.glGetError();
- if(GL.GL_NO_ERROR != glerr) {
- gl.glDeleteRenderbuffers(1, name, 0);
- setName(0);
- throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this);
+ if( checkError ) {
+ final int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR != glerr) {
+ gl.glDeleteRenderbuffers(1, name, 0);
+ setName(0);
+ throw new GLException("GL Error "+toHexString(glerr)+" while creating "+this);
+ }
}
if(DEBUG) {
- System.err.println("Attachment.init: "+this);
+ System.err.println("Attachment.init.X: "+this);
}
}
return init;
}
-
+
@Override
- public void free(GL gl) {
+ public void free(final GL gl) {
final int[] name = new int[] { getName() };
if( 0 != name[0] ) {
- gl.glDeleteRenderbuffers(1, name, 0);
- setName(0);
if(DEBUG) {
- System.err.println("Attachment.free: "+this);
+ System.err.println("Attachment.free.0: "+this);
}
+ gl.glDeleteRenderbuffers(1, name, 0);
+ setName(0);
}
}
-
+
+ @Override
public String toString() {
- return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+
- ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+"]";
+ return getClass().getSimpleName()+"[type "+type+", format "+toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+
+ ", name "+toHexString(getName())+", obj "+toHexString(objectHashCode())+"]";
}
}
-
- /** Color render buffer attachment */
+
+ /** Color render buffer FBO attachment */
public static class ColorAttachment extends RenderAttachment implements Colorbuffer {
- public ColorAttachment(int iFormat, int samples, int width, int height, int name) {
+ public ColorAttachment(final int iFormat, final int samples, final int width, final int height, final int name) {
super(Type.COLOR, iFormat, samples, width, height, name);
- }
+ }
+ @Override
+ public final boolean isTextureAttachment() { return false; }
+ @Override
+ public final TextureAttachment getTextureAttachment() { throw new GLException("Not a TextureAttachment, but ColorAttachment"); }
+ @Override
+ public final ColorAttachment getColorAttachment() { return this; }
+
}
-
- /** Texture attachment */
+
+ /** Texture FBO attachment */
public static class TextureAttachment extends Attachment implements Colorbuffer {
/** details of the texture setup */
public final int dataFormat, dataType, magFilter, minFilter, wrapS, wrapT;
@@ -442,8 +502,8 @@ public class FBObject {
* @param wrapT
* @param name
*/
- public TextureAttachment(Type type, int iFormat, int width, int height, int dataFormat, int dataType,
- int magFilter, int minFilter, int wrapS, int wrapT, int name) {
+ public TextureAttachment(final Type type, final int iFormat, final int width, final int height, final int dataFormat, final int dataType,
+ final int magFilter, final int minFilter, final int wrapS, final int wrapT, final int name) {
super(validateType(type), iFormat, width, height, name);
this.dataFormat = dataFormat;
this.dataType = dataType;
@@ -452,37 +512,38 @@ public class FBObject {
this.wrapS = wrapS;
this.wrapT = wrapT;
}
-
- private static Type validateType(Type type) {
+
+ private static Type validateType(final Type type) {
switch(type) {
case COLOR_TEXTURE:
case DEPTH_TEXTURE:
case STENCIL_TEXTURE:
return type;
- default:
+ default:
throw new IllegalArgumentException("Invalid type: "+type);
}
}
-
- /**
+
+ /**
* Initializes the texture and set it's parameter, if uninitialized, i.e. name is <code>zero</code>.
- * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case.
+ * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case.
*/
@Override
- public boolean initialize(GL gl) throws GLException {
+ public boolean initialize(final GL gl) throws GLException {
final boolean init = 0 == getName();
if( init ) {
- int glerr = checkPreGLError(gl);
-
- final int[] name = new int[] { -1 };
+ final boolean checkError = DEBUG || GLContext.DEBUG_GL;
+ if( checkError ) {
+ checkPreGLError(gl);
+ }
+ final int[] name = new int[] { -1 };
gl.glGenTextures(1, name, 0);
if(0 == name[0]) {
throw new GLException("null texture, "+this);
}
setName(name[0]);
-
+
gl.glBindTexture(GL.GL_TEXTURE_2D, name[0]);
- gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
if( 0 < magFilter ) {
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter);
}
@@ -493,100 +554,184 @@ public class FBObject {
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS);
}
if( 0 < wrapT ) {
- gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT);
- }
- glerr = gl.glGetError();
- if(GL.GL_NO_ERROR != glerr) {
- gl.glDeleteTextures(1, name, 0);
- setName(0);
- throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT);
+ }
+ if( checkError ) {
+ boolean preTexImage2D = true;
+ int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR == glerr) {
+ preTexImage2D = false;
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
+ glerr = gl.glGetError();
+ }
+ if(GL.GL_NO_ERROR != glerr) {
+ gl.glDeleteTextures(1, name, 0);
+ setName(0);
+ throw new GLException("GL Error "+toHexString(glerr)+" while creating (pre TexImage2D "+preTexImage2D+") "+this);
+ }
+ } else {
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
}
if(DEBUG) {
- System.err.println("Attachment.init: "+this);
+ System.err.println("Attachment.init.X: "+this);
}
}
return init;
}
@Override
- public void free(GL gl) {
+ public void free(final GL gl) {
final int[] name = new int[] { getName() };
if( 0 != name[0] ) {
- gl.glDeleteTextures(1, name, 0);
- setName(0);
if(DEBUG) {
- System.err.println("Attachment.free: "+this);
+ System.err.println("Attachment.free.0: "+this);
}
+ gl.glDeleteTextures(1, name, 0);
+ setName(0);
}
}
+
+ @Override
+ public final boolean isTextureAttachment() { return true; }
+ @Override
+ public final TextureAttachment getTextureAttachment() { return this; }
+ @Override
+ public final ColorAttachment getColorAttachment() { throw new GLException("Not a ColorAttachment, but TextureAttachment"); }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()+"[type "+type+", target GL_TEXTURE_2D, level 0, format "+toHexString(format)+
+ ", "+getWidth()+"x"+getHeight()+", border 0, dataFormat "+toHexString(dataFormat)+
+ ", dataType "+toHexString(dataType)+
+ "; min/mag "+toHexString(minFilter)+"/"+toHexString(magFilter)+
+ ", wrap S/T "+toHexString(wrapS)+"/"+toHexString(wrapT)+
+ "; name "+toHexString(getName())+", obj "+toHexString(objectHashCode())+"]";
+ }
+ }
+ static String toHexString(final int v) {
+ return "0x"+Integer.toHexString(v);
}
-
+
/**
- * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE},
+ * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE},
* selecting the texture data type and format automatically.
- *
+ *
* <p>Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.</p>
- *
- * @param glp the chosen {@link GLProfile}
+ *
+ * @param gl the used {@link GLContext}'s {@link GL} object
* @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
- * @param width texture width
+ * @param width texture width
* @param height texture height
* @return the created and uninitialized color {@link TextureAttachment}
*/
- public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height) {
- return createColorTextureAttachment(glp, alpha, width, height, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ public static final TextureAttachment createColorTextureAttachment(final GL gl, final boolean alpha, final int width, final int height) {
+ return createColorTextureAttachment(gl, alpha, width, height, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
}
-
+
/**
- * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE},
+ * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE},
* selecting the texture data type and format automatically.
- *
- * @param glp the chosen {@link GLProfile}
+ * <p>
+ * For GLES3, sampling-sink format <b>must be equal</b> w/ the sampling-source {@link Colorbuffer},
+ * see details below. Implementation aligns w/ {@link #createColorAttachment(boolean)}
+ * and is enforced via {@link #sampleSinkExFormatMismatch(GL)}.
+ * </p>
+ * <p>
+ * ES3 BlitFramebuffer Requirements: OpenGL ES 3.0.2 p194: 4.3.2 Copying Pixels
+ * <pre>
+ * If SAMPLE_BUFFERS for the read framebuffer is greater than zero, no copy
+ * is performed and an INVALID_OPERATION error is generated if the formats of
+ * the read and draw framebuffers are not identical or if the source and destination
+ * rectangles are not defined with the same (X0, Y 0) and (X1, Y 1) bounds.
+ * </pre>
+ * Texture and Renderbuffer format details:
+ * <pre>
+ * ES2 Base iFormat: OpenGL ES 2.0.24 p66: 3.7.1 Texture Image Specification, Table 3.8
+ * ALPHA, LUMINANCE, LUMINANCE_ALPHA, RGB, RGBA
+ *
+ * ES3 Base iFormat: OpenGL ES 3.0.2 p125: 3.8.3 Texture Image Specification, Table 3.11
+ * ALPHA, LUMINANCE, LUMINANCE_ALPHA, RGB, RGBA
+ * DEPTH_COMPONENT, STENCIL_COMPONENT, RED, RG
+ *
+ * ES3 Required Texture and Renderbuffer iFormat: OpenGL ES 3.0.2 p126: 3.8.3 Texture Image Specification
+ * - RGBA32I, RGBA32UI, RGBA16I, RGBA16UI, RGBA8, RGBA8I,
+ * RGBA8UI, SRGB8_ALPHA8, RGB10_A2, RGB10_A2UI, RGBA4, and
+ * RGB5_A1.
+ * - RGB8 and RGB565.
+ * - RG32I, RG32UI, RG16I, RG16UI, RG8, RG8I, and RG8UI.
+ * - R32I, R32UI, R16I, R16UI, R8, R8I, and R8UI.
+ * </pre>
+ * </p>
+ *
+ * @param gl the used {@link GLContext}'s {@link GL} object
* @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
- * @param width texture width
+ * @param width texture width
* @param height texture height
* @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
- * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
* @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
* @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
* @return the created and uninitialized color {@link TextureAttachment}
*/
- public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height,
- int magFilter, int minFilter, int wrapS, int wrapT) {
- final int textureInternalFormat, textureDataFormat, textureDataType;
- if(glp.isGLES()) {
- textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
- textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
- textureDataType = GL.GL_UNSIGNED_BYTE;
- } else {
- textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
- textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
- textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
- }
- return createColorTextureAttachment(textureInternalFormat, width, height, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT);
- }
-
+ public static final TextureAttachment createColorTextureAttachment(final GL gl, final boolean alpha, final int width, final int height,
+ final int magFilter, final int minFilter, final int wrapS, final int wrapT) {
+ final int internalFormat, dataFormat, dataType;
+ if(gl.isGLES3()) {
+ internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ dataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ dataType = GL.GL_UNSIGNED_BYTE;
+ } else if(gl.isGLES()) {
+ internalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ dataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ dataType = GL.GL_UNSIGNED_BYTE;
+ } else {
+ internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ // textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ // textureInternalFormat = alpha ? 4 : 3;
+ dataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
+ dataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
+ }
+ return createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT);
+ }
+
+ public static final TextureAttachment createColorTextureAttachment(final GL gl, final int internalFormat, final int width, final int height,
+ final int magFilter, final int minFilter, final int wrapS, final int wrapT) {
+ final int dataFormat, dataType;
+ final boolean alpha = hasAlpha(internalFormat);
+ if( gl.isGLES3() ) {
+ dataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ dataType = GL.GL_UNSIGNED_BYTE;
+ } else if( gl.isGLES() ) {
+ dataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ dataType = GL.GL_UNSIGNED_BYTE;
+ } else {
+ dataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
+ dataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
+ }
+ return createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT);
+ }
+
/**
- * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}.
+ * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}.
*
* @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
- * @param width texture width
+ * @param width texture width
* @param height texture height
* @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
* @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
* @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
- * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
* @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
* @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
* @return the created and uninitialized color {@link TextureAttachment}
*/
- public static final TextureAttachment createColorTextureAttachment(int internalFormat, int width, int height, int dataFormat, int dataType,
- int magFilter, int minFilter, int wrapS, int wrapT) {
- return new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType,
+ public static final TextureAttachment createColorTextureAttachment(final int internalFormat, final int width, final int height, final int dataFormat, final int dataType,
+ final int magFilter, final int minFilter, final int wrapS, final int wrapT) {
+ return new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType,
magFilter, minFilter, wrapS, wrapT, 0 /* name */);
}
-
- private static boolean hasAlpha(int format) {
+
+ private static boolean hasAlpha(final int format) {
switch(format) {
case GL.GL_RGBA8:
case GL.GL_RGBA4:
@@ -598,7 +743,7 @@ public class FBObject {
return false;
}
}
-
+
private boolean initialized;
private boolean fullFBOSupport;
private boolean rgba8Avail;
@@ -608,7 +753,7 @@ public class FBObject {
private boolean stencil04Avail;
private boolean stencil08Avail;
private boolean stencil16Avail;
- private boolean packedDepthStencilAvail;
+ private boolean packedDepthStencilAvail;
private int maxColorAttachments, maxSamples, maxTextureSize, maxRenderbufferSize;
private int width, height, samples;
@@ -617,70 +762,93 @@ public class FBObject {
private int fbName;
private boolean bound;
- private int colorAttachmentCount;
- private Colorbuffer[] colorAttachmentPoints; // colorbuffer attachment points
+ private int colorbufferCount;
+ private int textureAttachmentCount;
+ private Colorbuffer[] colorbufferAttachments; // colorbuffer attachment points
private RenderAttachment depth, stencil; // depth and stencil maybe equal in case of packed-depth-stencil
+ private boolean modified; // size, sampleCount, or any attachment modified
- private final FBObject samplesSink; // MSAA sink
- private TextureAttachment samplesSinkTexture;
- private boolean samplesSinkDirty;
+ private FBObject samplingSink; // MSAA sink
+ private Colorbuffer samplingColorSink;
+ private boolean samplingSinkDirty;
//
// ColorAttachment helper ..
//
-
- private final void validateColorAttachmentPointRange(int point) {
+
+ private final void validateColorAttachmentPointRange(final int point) {
if(!initialized) {
throw new GLException("FBO not initialized");
- }
- if(maxColorAttachments != colorAttachmentPoints.length) {
- throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints);
+ }
+ if(maxColorAttachments != colorbufferAttachments.length) {
+ throw new InternalError(String.format("maxColorAttachments %d, array.length %d",
+ maxColorAttachments, colorbufferAttachments.length) );
}
if(0 > point || point >= maxColorAttachments) {
- throw new IllegalArgumentException("attachment point out of range: "+point+", should be within [0.."+(maxColorAttachments-1)+"]");
+ throw new IllegalArgumentException(String.format("attachment point out of range: %d, should be within [0..%d], %s",
+ point, maxColorAttachments-1, this.toString() ) );
}
}
-
- private final void validateAddColorAttachment(int point, Colorbuffer ca) {
+
+ private final void validateAddColorAttachment(final int point, final Colorbuffer ca) {
validateColorAttachmentPointRange(point);
- if( null != colorAttachmentPoints[point] ) {
- throw new IllegalArgumentException("Cannot attach "+ca+", attachment point already in use by "+colorAttachmentPoints[point]);
- }
+ if( null != colorbufferAttachments[point] ) {
+ throw new IllegalStateException(String.format("Cannot attach %s at %d, attachment point already in use by %s, %s",
+ ca.toString(), point, colorbufferAttachments[point].toString(), this.toString() ) );
+ }
}
-
- private final void addColorAttachment(int point, Colorbuffer ca) {
- validateColorAttachmentPointRange(point);
- final Colorbuffer c = colorAttachmentPoints[point];
- if( null != c && c != ca ) {
- throw new IllegalArgumentException("Add failed: requested to add "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+
+ private final void addColorAttachment(final int point, final Colorbuffer ca, final boolean validate) {
+ final Colorbuffer c = colorbufferAttachments[point];
+ if( validate ) {
+ validateColorAttachmentPointRange(point);
+ if( null == ca ) {
+ throw new IllegalArgumentException("Colorbuffer is null");
+ }
+ if( null != c ) {
+ throw new IllegalStateException(String.format("Cannot attach %s at %d, attachment point already in use by %s, %s",
+ ca.toString(), point, c.toString(), this.toString() ) );
+ }
+ }
+ colorbufferAttachments[point] = ca;
+ colorbufferCount++;
+ if( ca.isTextureAttachment() ) {
+ textureAttachmentCount++;
}
- colorAttachmentPoints[point] = ca;
- colorAttachmentCount++;
+ modified = true;
}
-
- private final void removeColorAttachment(int point, Colorbuffer ca) {
+
+ private final void removeColorAttachment(final int point, final Colorbuffer ca) {
validateColorAttachmentPointRange(point);
- final Colorbuffer c = colorAttachmentPoints[point];
- if( null != c && c != ca ) {
- throw new IllegalArgumentException("Remove failed: requested to removed "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ if( null == ca ) {
+ throw new IllegalArgumentException("Colorbuffer is null");
}
- colorAttachmentPoints[point] = null;
- colorAttachmentCount--;
+ final Colorbuffer c = colorbufferAttachments[point];
+ if( c != ca ) {
+ throw new IllegalStateException(String.format("Cannot detach %s at %d, slot is holding other: %s, %s",
+ ca.toString(), point, c.toString(), this.toString() ) );
+ }
+ colorbufferAttachments[point] = null;
+ colorbufferCount--;
+ if( ca.isTextureAttachment() ) {
+ textureAttachmentCount--;
+ }
+ modified = true;
}
-
+
/**
* Return the {@link Colorbuffer} attachment at <code>attachmentPoint</code> if it is attached to this FBO, otherwise null.
- *
+ *
* @see #attachColorbuffer(GL, boolean)
* @see #attachColorbuffer(GL, boolean)
* @see #attachTexture2D(GL, int, boolean, int, int, int, int)
- * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int)
+ * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int)
*/
- public final Colorbuffer getColorbuffer(int attachmentPoint) {
- validateColorAttachmentPointRange(attachmentPoint);
- return colorAttachmentPoints[attachmentPoint];
+ public final Colorbuffer getColorbuffer(final int attachmentPoint) {
+ validateColorAttachmentPointRange(attachmentPoint);
+ return colorbufferAttachments[attachmentPoint];
}
-
+
/**
* Finds the passed {@link Colorbuffer} within the valid range of attachment points
* using <i>reference</i> comparison only.
@@ -688,36 +856,56 @@ public class FBObject {
* Note: Slow. Implementation uses a logN array search to save resources, i.e. not using a HashMap.
* </p>
* @param ca the {@link Colorbuffer} to look for.
- * @return -1 if the {@link Colorbuffer} could not be found, otherwise [0..{@link #getMaxColorAttachments()}-1]
+ * @return -1 if the {@link Colorbuffer} could not be found, otherwise [0..{@link #getMaxColorAttachments()}-1]
*/
- public final int getColorbufferAttachmentPoint(Colorbuffer ca) {
- for(int i=0; i<colorAttachmentPoints.length; i++) {
- if( colorAttachmentPoints[i] == ca ) {
- return i;
+ public final int getColorbufferAttachmentPoint(final Colorbuffer ca) {
+ for(int i=0; i<colorbufferAttachments.length; i++) {
+ if( colorbufferAttachments[i] == ca ) {
+ return i;
}
}
return -1;
}
-
+
/**
* Returns the passed {@link Colorbuffer} if it is attached to this FBO, otherwise null.
* Implementation compares the <i>reference</i> only.
- *
+ *
* <p>
* Note: Slow. Uses {@link #getColorbufferAttachmentPoint(Colorbuffer)} to determine it's attachment point
* to be used for {@link #getColorbuffer(int)}
* </p>
- *
+ *
* @see #attachColorbuffer(GL, boolean)
* @see #attachColorbuffer(GL, boolean)
* @see #attachTexture2D(GL, int, boolean, int, int, int, int)
- * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int)
+ * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int)
*/
- public final Colorbuffer getColorbuffer(Colorbuffer ca) {
+ public final Colorbuffer getColorbuffer(final Colorbuffer ca) {
final int p = getColorbufferAttachmentPoint(ca);
return p>=0 ? getColorbuffer(p) : null;
}
-
+
+ /**
+ * Returns true if any attached {@link Colorbuffer} uses alpha,
+ * otherwise false.
+ */
+ public final boolean hasAttachmentUsingAlpha() {
+ final int caCount = getColorbufferCount();
+ boolean hasAlpha = false;
+ for(int i=0; i<caCount; i++) {
+ final Attachment ca = (Attachment)getColorbuffer(i);
+ if( null == ca ) {
+ break;
+ }
+ if( hasAlpha(ca.format) ) {
+ hasAlpha = true;
+ break;
+ }
+ }
+ return hasAlpha;
+ }
+
/**
* Creates an uninitialized FBObject instance.
* <p>
@@ -725,11 +913,8 @@ public class FBObject {
* </p>
*/
public FBObject() {
- this(false);
- }
- /* pp */ FBObject(boolean isSampleSink) {
this.initialized = false;
-
+
// TBD @ init
this.fullFBOSupport = false;
this.rgba8Avail = false;
@@ -744,7 +929,7 @@ public class FBObject {
this.maxSamples=-1;
this.maxTextureSize = 0;
this.maxRenderbufferSize = 0;
-
+
this.width = 0;
this.height = 0;
this.samples = 0;
@@ -752,86 +937,98 @@ public class FBObject {
this.ignoreStatus = false;
this.fbName = 0;
this.bound = false;
-
- this.colorAttachmentPoints = null; // at init ..
- this.colorAttachmentCount = 0;
+
+ this.colorbufferAttachments = null; // at init ..
+ this.colorbufferCount = 0;
+ this.textureAttachmentCount = 0;
this.depth = null;
- this.stencil = null;
-
- this.samplesSink = isSampleSink ? null : new FBObject(true);
- this.samplesSinkTexture = null;
- this.samplesSinkDirty = true;
+ this.stencil = null;
+ this.modified = true;
+
+ this.samplingSink = null;
+ this.samplingColorSink = null;
+ this.samplingSinkDirty = true;
}
-
- private void init(GL gl, int width, int height, int samples) throws GLException {
- if(initialized) {
- throw new GLException("FBO already initialized");
+
+ /**
+ * Initializes this FBO's instance.
+ * <p>
+ * The sampling sink is not initializes, allowing manual assignment via {@link #setSamplingSink(FBObject)}
+ * if {@code newSamples > 0}.
+ * </p>
+ *
+ * <p>Leaves the FBO bound</p>
+ *
+ * @param gl the current GL context
+ * @param newWidth the initial width, it's minimum is capped to 1
+ * @param newHeight the initial height, it's minimum is capped to 1
+ * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}.
+ * @throws IllegalStateException if already initialized
+ * @throws GLException in case of an error, i.e. size too big, etc ..
+ */
+ public void init(final GL gl, final int newWidth, final int newHeight, final int newSamples) throws IllegalStateException, GLException {
+ if( initialized ) {
+ throw new IllegalStateException("FBO already initialized");
}
if( !gl.hasBasicFBOSupport() ) {
throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this);
}
- fullFBOSupport = gl.hasFullFBOSupport();
-
- rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8);
+ fullFBOSupport = gl.hasFullFBOSupport();
+
+ rgba8Avail = gl.isGL2ES3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8);
depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24);
depth32Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth32);
stencil01Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil1);
stencil04Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil4);
stencil08Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil8);
stencil16Avail = fullFBOSupport;
-
- packedDepthStencilAvail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_packed_depth_stencil);
-
+
+ packedDepthStencilAvail = fullFBOSupport ||
+ gl.isExtensionAvailable(GLExtensions.OES_packed_depth_stencil) ||
+ gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) ;
+
final boolean NV_fbo_color_attachments = gl.isExtensionAvailable(GLExtensions.NV_fbo_color_attachments);
-
- int val[] = new int[1];
-
- int glerr = checkPreGLError(gl);
+
+ final int val[] = new int[1];
+
+ checkPreGLError(gl);
int realMaxColorAttachments = 1;
maxColorAttachments = 1;
- if( null != samplesSink && fullFBOSupport || NV_fbo_color_attachments ) {
+ if( fullFBOSupport || NV_fbo_color_attachments ) {
try {
- gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, val, 0);
- glerr = gl.glGetError();
- if(GL.GL_NO_ERROR == glerr) {
- realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1
- } else if(DEBUG) {
- System.err.println("FBObject.init-GL_MAX_COLOR_ATTACHMENTS query GL Error 0x"+Integer.toHexString(glerr));
- }
- } catch (GLException gle) {}
+ val[0] = 0;
+ gl.glGetIntegerv(GL2ES2.GL_MAX_COLOR_ATTACHMENTS, val, 0);
+ realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1
+ } catch (final GLException gle) { gle.printStackTrace(); }
}
maxColorAttachments = realMaxColorAttachments <= 8 ? realMaxColorAttachments : 8; // cap to limit array size
-
- colorAttachmentPoints = new Colorbuffer[maxColorAttachments];
- colorAttachmentCount = 0;
-
- maxSamples = gl.getMaxRenderbufferSamples();
- if(!forceMinimumFBOSupport) {
- gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
- maxTextureSize = val[0];
- gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0);
- maxRenderbufferSize = val[0];
+
+ colorbufferAttachments = new Colorbuffer[maxColorAttachments];
+ colorbufferCount = 0;
+ textureAttachmentCount = 0;
+
+ maxSamples = gl.getMaxRenderbufferSamples(); // if > 0 implies fullFBOSupport
+ gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
+ final int _maxTextureSize = val[0];
+ if( 0 < USER_MAX_TEXTURE_SIZE ) {
+ maxTextureSize = USER_MAX_TEXTURE_SIZE;
} else {
- maxTextureSize = 2048;
- maxRenderbufferSize = 2048;
+ maxTextureSize = _maxTextureSize;
}
-
- glerr = gl.glGetError();
- if(DEBUG && GL.GL_NO_ERROR != glerr) {
- System.err.println("Info: FBObject.init: pre-existing GL error 0x"+Integer.toHexString(glerr));
- }
-
- this.width = width;
- this.height = height;
- this.samples = samples <= maxSamples ? samples : maxSamples;
-
+ gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0);
+ maxRenderbufferSize = val[0];
+
+ this.width = 0 < newWidth ? newWidth : 1;
+ this.height = 0 < newHeight ? newHeight : 1;
+ this.samples = newSamples <= maxSamples ? newSamples : maxSamples;
+
if(DEBUG) {
- System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+this.samples+" samples");
+ System.err.println("FBObject.init() START: "+width+"x"+height+", "+newSamples+" -> "+this.samples+" samples");
System.err.println("fullFBOSupport: "+fullFBOSupport);
System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments+" [capped/real]");
System.err.println("maxSamples: "+maxSamples);
- System.err.println("maxTextureSize: "+maxTextureSize);
+ System.err.println("maxTextureSize: "+_maxTextureSize+" -> "+maxTextureSize);
System.err.println("maxRenderbufferSize: "+maxRenderbufferSize);
System.err.println("rgba8: "+rgba8Avail);
System.err.println("depth24: "+depth24Avail);
@@ -843,19 +1040,18 @@ public class FBObject {
System.err.println("packedDepthStencil: "+packedDepthStencilAvail);
System.err.println("NV_fbo_color_attachments: "+NV_fbo_color_attachments);
System.err.println(gl.getContext().getGLVersion());
- System.err.println(JoglVersion.getGLStrings(gl, null).toString());
- System.err.println(gl.getContext());
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
}
-
- checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error
-
- if(width > 2 + maxTextureSize || height> 2 + maxTextureSize ||
- width > maxRenderbufferSize || height> maxRenderbufferSize ) {
- throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]");
+
+ checkPreGLError(gl);
+
+ if( width > maxRenderbufferSize || height > maxRenderbufferSize ) {
+ throw new GLException("Size "+width+"x"+height+" exceeds on of the maxima renderbuffer size "+maxRenderbufferSize+": \n\t"+this);
}
- resetMSAATexture2DSink(gl);
-
+ modified = true;
+ samplingSinkDirty = true;
+
// generate fbo ..
gl.glGenFramebuffers(1, val, 0);
fbName = val[0];
@@ -864,125 +1060,154 @@ public class FBObject {
}
// bind fbo ..
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbName);
- checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbName);
+ checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error
if(!gl.glIsFramebuffer(fbName)) {
checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException
}
bound = true;
- samplesSinkDirty = true;
initialized = true;
-
- updateStatus(gl);
+
+ vStatus = GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; // always incomplete w/o attachments!
if(DEBUG) {
- System.err.println("FBObject.init(): "+this);
+ System.err.println("FBObject.init() END: "+this);
+ Thread.dumpStack();
}
}
/**
- * Initializes or resets this FBO's instance.
+ * Resets this FBO's instance.
* <p>
* In case the new parameters are compatible with the current ones
- * no action will be performed. Otherwise all attachments will be recreated
+ * no action will be performed and method returns immediately.<br>
+ * Otherwise all attachments will be recreated
* to match the new given parameters.
* </p>
* <p>
- * Incompatibility and hence recreation is forced if
- * the size or sample count doesn't match for subsequent calls.
- * </p>
- *
- * <p>Leaves the FBO bound state untouched</p>
- *
- * @param gl the current GL context
- * @param newWidth
- * @param newHeight
- * @throws GLException in case of an error
- */
- public final void reset(GL gl, int newWidth, int newHeight) {
- reset(gl, newWidth, newHeight, 0);
- }
-
- /**
- * Initializes or resets this FBO's instance.
- * <p>
- * In case the new parameters are compatible with the current ones
- * no action will be performed. Otherwise all attachments will be recreated
- * to match the new given parameters.
+ * {@link #resetSamplingSink(GL)} is being issued immediately
+ * to match the new configuration.
* </p>
- * <p>
- * Currently incompatibility and hence recreation of the attachments will be performed
- * if the size or sample count doesn't match for subsequent calls.
- * </p>
- *
+ *
* <p>Leaves the FBO bound state untouched</p>
- *
+ *
* @param gl the current GL context
* @param newWidth the new width, it's minimum is capped to 1
* @param newHeight the new height, it's minimum is capped to 1
* @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}.
+ * @return {@code true} if this instance has been modified, otherwise {@code false}.
+ * @throws IllegalStateException if not initialized via {@link #init(GL, int, int, int)}.
* @throws GLException in case of an error, i.e. size too big, etc ..
*/
- public final void reset(GL gl, int newWidth, int newHeight, int newSamples) {
- if(!initialized) {
- init(gl, newWidth, newHeight, newSamples);
- return;
+ public final boolean reset(final GL gl, int newWidth, int newHeight, int newSamples) throws GLException, IllegalStateException {
+ if( !initialized ) {
+ throw new IllegalStateException("FBO not initialized");
}
-
+
newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp
-
+
if( newWidth != width || newHeight != height || newSamples != samples ) {
- if(0>=newWidth) { newWidth = 1; }
- if(0>=newHeight) { newHeight = 1; }
- if(newWidth > 2 + maxTextureSize || newHeight> 2 + maxTextureSize ||
- newWidth > maxRenderbufferSize || newHeight> maxRenderbufferSize ) {
- throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]");
+ if( 0 >= newWidth ) { newWidth = 1; }
+ if( 0 >= newHeight ) { newHeight = 1; }
+ if( textureAttachmentCount > 0 && ( newWidth > 2 + maxTextureSize || newHeight > 2 + maxTextureSize ) ) {
+ throw new GLException("Size "+newWidth+"x"+newHeight+" exceeds on of the maximum texture size "+maxTextureSize+": \n\t"+this);
}
-
+ if( newWidth > maxRenderbufferSize || newHeight > maxRenderbufferSize ) {
+ throw new GLException("Size "+newWidth+"x"+newHeight+" exceeds on of the maxima renderbuffer size "+maxRenderbufferSize+": \n\t"+this);
+ }
+
if(DEBUG) {
System.err.println("FBObject.reset - START - "+width+"x"+height+", "+samples+" -> "+newWidth+"x"+newHeight+", "+newSamples+"; "+this);
- }
-
+ }
+
final boolean wasBound = isBound();
-
+
+ final int sampleCountChange;
+ if( 0 < samples && 0 < newSamples || 0 == samples && 0 == newSamples ) {
+ sampleCountChange = 0; // keep MSAA settings
+ } else if( 0 == samples && 0 < newSamples ) {
+ sampleCountChange = 1; // add MSAA
+ } else if( 0 < samples && 0 == newSamples ) {
+ sampleCountChange = -1; // remove MSAA
+ } else {
+ throw new IllegalArgumentException("Error in sampleCount change: "+samples+" -> "+newSamples);
+ }
width = newWidth;
height = newHeight;
samples = newSamples;
- detachAllImpl(gl, true , true);
-
- /**
- * Postpone reset of samplesSink until syncFramebuffer,
- * issued at use(..) method (swapBuffer usually initiates it).
- * This allows another thread to still use the 'samplesSinkTexture'
- * until swapBuffer happens and does not invalidate the GL_FRONT
- * FBO (framebuffer & texture).
- resetMSAATexture2DSink(gl);
- */
- samplesSinkDirty = true;
+
+ modified = true;
+ samplingSinkDirty = true;
+
+ detachAllImpl(gl, true, true, sampleCountChange);
+ resetSamplingSink(gl);
if(!wasBound) {
unbind(gl);
}
-
+
if(DEBUG) {
- System.err.println("FBObject.reset - END - "+this);
+ System.err.println("FBObject.reset - END - wasBound, "+wasBound+", "+this);
}
- }
+ return true;
+ } else {
+ return false;
+ }
}
-
+
+ /**
+ * Simply resets this instance's size only, w/o validation.
+ *
+ * <p>Leaves the FBO bound</p>
+ *
+ * @param gl the current GL context
+ * @param newWidth the new width, it's minimum is capped to 1
+ * @param newHeight the new height, it's minimum is capped to 1
+ */
+ private final void resetSizeImpl(final GL gl, final int newWidth, final int newHeight) {
+ if(DEBUG) {
+ System.err.println("FBObject.resetSize - START - "+width+"x"+height+", "+samples+" -> "+newWidth+"x"+newHeight);
+ }
+
+ final int sampleCountChange = 0; // keep MSAA settings
+ width = newWidth;
+ height = newHeight;
+
+ modified = true;
+ samplingSinkDirty = true;
+
+ detachAllImpl(gl, true, true, sampleCountChange);
+
+ if(DEBUG) {
+ System.err.println("FBObject.resetSize - END - "+this);
+ }
+ }
+
+ private void validateAttachmentSize(final Attachment a) {
+ final int aWidth = a.getWidth();
+ final int aHeight = a.getHeight();
+
+ if( a instanceof TextureAttachment && ( aWidth > 2 + maxTextureSize || aHeight > 2 + maxTextureSize ) ) {
+ throw new GLException("Size "+aWidth+"x"+aHeight+" of "+a+" exceeds on of the maximum texture size "+maxTextureSize+": \n\t"+this);
+ }
+ if( aWidth > maxRenderbufferSize || aHeight > maxRenderbufferSize ) {
+ throw new GLException("Size "+aWidth+"x"+aHeight+" of "+a+" exceeds on of the maxima renderbuffer size "+maxRenderbufferSize+": \n\t"+this);
+ }
+ }
+
/**
* Writes the internal format of the attachments to the given GLCapabilities object.
* @param caps the destination for format bits
*/
- public final void formatToGLCapabilities(GLCapabilities caps) {
+ public final void formatToGLCapabilities(final GLCapabilities caps) {
caps.setSampleBuffers(samples > 0);
caps.setNumSamples(samples);
caps.setDepthBits(0);
caps.setStencilBits(0);
-
+
final Colorbuffer cb = samples > 0 ? getSamplingSink() : getColorbuffer(0);
if(null != cb) {
cb.formatToGLCapabilities(caps, rgba8Avail);
- }
+ }
if(null != depth) {
depth.formatToGLCapabilities(caps, rgba8Avail);
}
@@ -990,11 +1215,11 @@ public class FBObject {
stencil.formatToGLCapabilities(caps, rgba8Avail);
}
}
-
- /**
+
+ /**
* Note that the status may reflect an incomplete state during transition of attachments.
* @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1
- * @see #validateStatus()
+ * @see #validateStatus()
*/
public final int getStatus() {
return vStatus;
@@ -1004,44 +1229,44 @@ public class FBObject {
public final String getStatusString() {
return getStatusString(vStatus);
}
-
- public static final String getStatusString(int fbStatus) {
+
+ public static final String getStatusString(final int fbStatus) {
switch(fbStatus) {
case -1:
return "NOT A FBO";
-
+
case GL.GL_FRAMEBUFFER_COMPLETE:
return "OK";
-
+
case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- return("GL FBO: incomplete, incomplete attachment\n");
+ return("FBO incomplete attachment\n");
case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- return("GL FBO: incomplete, missing attachment");
+ return("FBO missing attachment");
case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- return("GL FBO: incomplete, attached images must have same dimensions");
+ return("FBO attached images must have same dimensions");
case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- return("GL FBO: incomplete, attached images must have same format");
+ return("FBO attached images must have same format");
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- return("GL FBO: incomplete, missing draw buffer");
+ return("FBO missing draw buffer");
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- return("GL FBO: incomplete, missing read buffer");
- case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
- return("GL FBO: incomplete, missing multisample buffer");
- case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
- return("GL FBO: incomplete, layer targets");
-
+ return("FBO missing read buffer");
+ case GL2ES3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+ return("FBO missing multisample buffer");
+ case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
+ return("FBO missing layer targets");
+
case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- return("GL FBO: Unsupported framebuffer format");
- case GL2GL3.GL_FRAMEBUFFER_UNDEFINED:
- return("GL FBO: framebuffer undefined");
-
+ return("Unsupported FBO format");
+ case GL2ES3.GL_FRAMEBUFFER_UNDEFINED:
+ return("FBO undefined");
+
case 0:
- return("GL FBO: incomplete, implementation fault");
+ return("FBO implementation fault");
default:
- return("GL FBO: incomplete, implementation ERROR 0x"+Integer.toHexString(fbStatus));
+ return("FBO incomplete, implementation ERROR "+toHexString(fbStatus));
}
}
-
+
/**
* The status may even be valid if incomplete during transition of attachments.
* @see #getStatus()
@@ -1050,47 +1275,49 @@ public class FBObject {
switch(vStatus) {
case GL.GL_FRAMEBUFFER_COMPLETE:
return true;
-
+
case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+ case GL2ES3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
- if(0 == colorAttachmentCount || null == depth) {
+ if(0 == colorbufferCount || null == depth) {
// we are in transition
return true;
}
-
+
case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- case GL2GL3.GL_FRAMEBUFFER_UNDEFINED:
-
- case 0:
+ case GL2ES3.GL_FRAMEBUFFER_UNDEFINED:
+
+ case 0:
default:
- System.out.println("Framebuffer " + fbName + " is incomplete: status = 0x" + Integer.toHexString(vStatus) +
- " : " + getStatusString(vStatus));
+ if(DEBUG) {
+ System.err.println("Framebuffer " + fbName + " is incomplete, status = " + toHexString(vStatus) +
+ " : " + getStatusString(vStatus));
+ }
return false;
}
}
-
- private static int checkPreGLError(GL gl) {
- int glerr = gl.glGetError();
+
+ private static int checkPreGLError(final GL gl) {
+ final int glerr = gl.glGetError();
if(DEBUG && GL.GL_NO_ERROR != glerr) {
- System.err.println("Pre-existing GL error: 0x"+Integer.toHexString(glerr));
+ System.err.println("Pre-existing GL error: "+toHexString(glerr));
Thread.dumpStack();
}
- return glerr;
+ return glerr;
}
-
- private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException {
+
+ private final boolean checkNoError(final GL gl, final int err, final String exceptionMessage) throws GLException {
if(GL.GL_NO_ERROR != err) {
if(null != gl) {
destroy(gl);
}
if(null != exceptionMessage) {
- throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err));
+ throw new GLException(exceptionMessage+" GL Error "+toHexString(err)+" of "+this.toString());
}
return false;
}
@@ -1100,17 +1327,17 @@ public class FBObject {
private final void checkInitialized() throws GLException {
if(!initialized) {
throw new GLException("FBO not initialized, call init(GL) first.");
- }
+ }
}
-
+
/**
* Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point,
* selecting the texture data type and format automatically.
- *
+ *
* <p>Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.</p>
- *
+ *
* <p>Leaves the FBO bound.</p>
- *
+ *
* @param gl the current GL context
* @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
* @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
@@ -1118,80 +1345,108 @@ public class FBObject {
* @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
* @see #createColorTextureAttachment(GLProfile, boolean, int, int)
*/
- public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException {
- return (TextureAttachment)attachColorbuffer(gl, attachmentPoint,
- createColorTextureAttachment(gl.getGLProfile(), alpha, width, height));
+ public final TextureAttachment attachTexture2D(final GL gl, final int attachmentPoint, final boolean alpha) throws GLException {
+ return attachColorbuffer(gl, attachmentPoint,
+ createColorTextureAttachment(gl, alpha, width, height)).getTextureAttachment();
}
-
+
/**
* Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point,
* selecting the texture data type and format automatically.
- *
+ *
* <p>Leaves the FBO bound.</p>
- *
+ *
* @param gl the current GL context
* @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
* @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
* @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
- * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
* @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
* @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
* @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
* @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
* @see #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int)
*/
- public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
- return (TextureAttachment)attachColorbuffer(gl, attachmentPoint,
- createColorTextureAttachment(gl.getGLProfile(), alpha, width, height, magFilter, minFilter, wrapS, wrapT));
+ public final TextureAttachment attachTexture2D(final GL gl, final int attachmentPoint, final boolean alpha, final int magFilter, final int minFilter, final int wrapS, final int wrapT) throws GLException {
+ return attachColorbuffer(gl, attachmentPoint,
+ createColorTextureAttachment(gl, alpha, width, height, magFilter, minFilter, wrapS, wrapT)).getTextureAttachment();
}
-
+
/**
* Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point.
- *
+ *
* <p>Leaves the FBO bound.</p>
- *
+ *
* @param gl the current GL context
* @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
* @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
* @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
* @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
* @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
- * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
* @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
* @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
* @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
* @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
* @see #createColorTextureAttachment(int, int, int, int, int, int, int, int, int)
*/
- public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint,
- int internalFormat, int dataFormat, int dataType,
- int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
- return (TextureAttachment)attachColorbuffer(gl, attachmentPoint,
- createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT));
+ public final TextureAttachment attachTexture2D(final GL gl, final int attachmentPoint,
+ final int internalFormat, final int dataFormat, final int dataType,
+ final int magFilter, final int minFilter, final int wrapS, final int wrapT) throws GLException {
+ return attachColorbuffer(gl, attachmentPoint,
+ createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT)).getTextureAttachment();
}
-
+
/**
* Creates a {@link ColorAttachment}, selecting the format automatically.
- *
+ * <p>
+ * For GLES3, sampling-sink {@link Colorbuffer} format <b>must be equal</b> w/ the sampling-source {@link Colorbuffer}.
+ * Implementation aligns w/ {@link #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int)}
+ * and is enforced via {@link #sampleSinkExFormatMismatch(GL)}.
+ * </p>
+ *
* @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
* @return uninitialized ColorAttachment instance describing the new attached colorbuffer
*/
- public final ColorAttachment createColorAttachment(boolean alpha) {
+ public final ColorAttachment createColorAttachment(final boolean alpha) {
final int internalFormat;
+
if( rgba8Avail ) {
internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ;
} else {
internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565;
}
- return new ColorAttachment(internalFormat, samples, width, height, 0);
+ return createColorAttachment(internalFormat, samples, width, height);
}
-
+
/**
- * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point,
- * selecting the format automatically.
- *
+ * Creates a {@link ColorAttachment}, selecting the format automatically.
+ * <p>
+ * For GLES3, sampling-sink {@link Colorbuffer} format <b>must be equal</b> w/ the sampling-source {@link Colorbuffer}.
+ * Implementation aligns w/ {@link #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int)}
+ * and is enforced via {@link #sampleSinkExFormatMismatch(GL)}.
+ * </p>
+ *
+ * @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
+ * @return uninitialized ColorAttachment instance describing the new attached colorbuffer
+ */
+ public static final ColorAttachment createColorAttachment(final int internalFormat, final int samples, final int width, final int height) {
+ return new ColorAttachment(internalFormat, samples, width, height, 0 /* name not yet determined */);
+ }
+
+ public static final RenderAttachment createRenderAttachment(final Type type, final int internalFormat, final int samples, final int width, final int height) {
+ return new RenderAttachment(type, internalFormat, samples, width, height, 0 /* name not yet determined */);
+ }
+
+ /**
+ * Attaches a newly created and {@link Colorbuffer#initialize(GL) initialized} {@link Colorbuffer}, i.e. a {@link ColorAttachment},
+ * at the given attachment point.
+ * <p>
+ * The {@link ColorAttachment} is created using {@code alpha} if {@code true} and current {@code sample count} and {@code size}.
+ * </p>
+ *
* <p>Leaves the FBO bound.</p>
- *
+ *
* @param gl the current GL context
* @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
* @param alpha set to <code>true</code> if you request alpha channel, otherwise <code>false</code>;
@@ -1199,89 +1454,98 @@ public class FBObject {
* @throws GLException in case the colorbuffer couldn't be allocated
* @see #createColorAttachment(boolean)
*/
- public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException {
- return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, createColorAttachment(alpha));
+ public final ColorAttachment attachColorbuffer(final GL gl, final int attachmentPoint, final boolean alpha) throws GLException {
+ return attachColorbuffer(gl, attachmentPoint, createColorAttachment(alpha)).getColorAttachment();
}
-
+
/**
- * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point.
- *
+ * Attaches a newly created and {@link Colorbuffer#initialize(GL) initialized} {@link Colorbuffer}, i.e. a {@link ColorAttachment},
+ * at the given attachment point.
+ * <p>
+ * The {@link ColorAttachment} is created using the given {@code internalFormat} and current {@code sample count} and {@code size}.
+ * </p>
+ *
* <p>Leaves the FBO bound.</p>
- *
+ *
* @param gl the current GL context
* @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
- * @param internalFormat usually {@link GL#GL_RGBA4}, {@link GL#GL_RGB5_A1}, {@link GL#GL_RGB565}, {@link GL#GL_RGB8} or {@link GL#GL_RGBA8}
+ * @param internalFormat usually {@link GL#GL_RGBA4}, {@link GL#GL_RGB5_A1}, {@link GL#GL_RGB565}, {@link GL#GL_RGB8} or {@link GL#GL_RGBA8}
* @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
* @throws GLException in case the colorbuffer couldn't be allocated
* @throws IllegalArgumentException if <code>internalFormat</code> doesn't reflect a colorbuffer
*/
- public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, int internalFormat) throws GLException, IllegalArgumentException {
+ public final ColorAttachment attachColorbuffer(final GL gl, final int attachmentPoint, final int internalFormat) throws GLException, IllegalArgumentException {
final Attachment.Type atype = Attachment.Type.determine(internalFormat);
if( Attachment.Type.COLOR != atype ) {
- throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this);
+ throw new IllegalArgumentException("colorformat invalid: "+toHexString(internalFormat)+", "+this);
}
-
- return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0));
+
+ return attachColorbuffer(gl, attachmentPoint, createColorAttachment(internalFormat, samples, width, height)).getColorAttachment();
}
-
+
/**
- * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment},
- * to this FBO's instance at the given attachment point.
- *
+ * Attaches a {@link Colorbuffer} at the given attachment point
+ * and {@link Colorbuffer#initialize(GL) initializes} it, if not done yet.
+ * <p>
+ * {@link Colorbuffer} may be a {@link ColorAttachment} or {@link TextureAttachment}.
+ * </p>
* <p>
* If {@link Colorbuffer} is a {@link TextureAttachment} and is uninitialized, i.e. it's texture name is <code>zero</code>,
* a new texture name is generated and setup w/ the texture parameter.<br/>
* Otherwise, i.e. texture name is not <code>zero</code>, the passed TextureAttachment <code>texA</code> is
- * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue.
+ * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue.
* </p>
- *
+ *
* <p>Leaves the FBO bound.</p>
- *
+ *
* @param gl
* @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1]
- * @param colbuf the to be attached {@link Colorbuffer}
- * @return newly attached {@link Colorbuffer} instance if bound and configured successfully, otherwise GLException is thrown
- * @throws GLException in case the colorbuffer couldn't be allocated or MSAA has been chosen in case of a {@link TextureAttachment}
+ * @param colbuf the to be attached {@link Colorbuffer}
+ * @return given {@link Colorbuffer} instance if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the colorbuffer couldn't be allocated or MSAA has been chosen in case of a {@link TextureAttachment}
*/
- public final Colorbuffer attachColorbuffer(GL gl, int attachmentPoint, Colorbuffer colbuf) throws GLException {
+ public final Colorbuffer attachColorbuffer(final GL gl, final int attachmentPoint, final Colorbuffer colbuf) throws GLException {
+ bind(gl);
+ return attachColorbufferImpl(gl, attachmentPoint, colbuf);
+ }
+
+ private final Colorbuffer attachColorbufferImpl(final GL gl, final int attachmentPoint, final Colorbuffer colbuf) throws GLException {
validateAddColorAttachment(attachmentPoint, colbuf);
-
+ validateAttachmentSize((Attachment)colbuf);
+
final boolean initializedColorbuf = colbuf.initialize(gl);
- addColorAttachment(attachmentPoint, colbuf);
-
- bind(gl);
+ addColorAttachment(attachmentPoint, colbuf, false);
- if(colbuf instanceof TextureAttachment) {
- final TextureAttachment texA = (TextureAttachment) colbuf;
-
- if(samples>0) {
+ if( colbuf.isTextureAttachment() ) {
+ final TextureAttachment texA = colbuf.getTextureAttachment();
+ if( samples > 0 ) {
removeColorAttachment(attachmentPoint, texA);
if(initializedColorbuf) {
texA.free(gl);
}
throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl).");
}
-
+
// Set up the color buffer for use as a renderable texture:
gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
GL.GL_TEXTURE_2D, texA.getName(), 0);
-
+
if(!ignoreStatus) {
- updateStatus(gl);
+ updateStatus(gl);
if(!isStatusValid()) {
detachColorbuffer(gl, attachmentPoint, true);
throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
}
}
- } else if(colbuf instanceof ColorAttachment) {
- final ColorAttachment colA = (ColorAttachment) colbuf;
-
+ } else {
+ final ColorAttachment colA = colbuf.getColorAttachment();
+
// Attach the color buffer
- gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
- GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
GL.GL_RENDERBUFFER, colA.getName());
-
+
if(!ignoreStatus) {
updateStatus(gl);
if(!isStatusValid()) {
@@ -1291,11 +1555,73 @@ public class FBObject {
}
}
if(DEBUG) {
- System.err.println("FBObject.attachColorbuffer: [attachmentPoint "+attachmentPoint+", colbuf "+colbuf+"]: "+this);
+ System.err.println("FBObject.attachColorbuffer.X: [attachmentPoint "+attachmentPoint+", colbuf "+colbuf+"]: "+this);
}
return colbuf;
}
-
+
+ private final int getDepthIFormat(final int reqBits) {
+ if( 32 <= reqBits && depth32Avail ) {
+ return GL.GL_DEPTH_COMPONENT32;
+ } else if( 24 <= reqBits && ( depth24Avail || depth32Avail ) ) {
+ if( depth24Avail ) {
+ return GL.GL_DEPTH_COMPONENT24;
+ } else {
+ return GL.GL_DEPTH_COMPONENT32;
+ }
+ } else {
+ return GL.GL_DEPTH_COMPONENT16;
+ }
+ }
+ private final int getStencilIFormat(final int reqBits) {
+ if( 16 <= reqBits && stencil16Avail ) {
+ return GL2GL3.GL_STENCIL_INDEX16;
+ } else if( 8 <= reqBits && ( stencil08Avail || stencil16Avail ) ) {
+ if( stencil08Avail ) {
+ return GL.GL_STENCIL_INDEX8;
+ } else {
+ return GL2GL3.GL_STENCIL_INDEX16;
+ }
+ } else if( 4 <= reqBits && ( stencil04Avail || stencil08Avail || stencil16Avail ) ) {
+ if( stencil04Avail ) {
+ return GL.GL_STENCIL_INDEX4;
+ } else if( stencil08Avail ) {
+ return GL.GL_STENCIL_INDEX8;
+ } else {
+ return GL2GL3.GL_STENCIL_INDEX16;
+ }
+ } else if( 1 <= reqBits && ( stencil01Avail || stencil04Avail || stencil08Avail || stencil16Avail ) ) {
+ if( stencil01Avail ) {
+ return GL.GL_STENCIL_INDEX1;
+ } else if( stencil04Avail ) {
+ return GL.GL_STENCIL_INDEX4;
+ } else if( stencil08Avail ) {
+ return GL.GL_STENCIL_INDEX8;
+ } else {
+ return GL2GL3.GL_STENCIL_INDEX16;
+ }
+ } else {
+ throw new GLException("stencil buffer n/a");
+ }
+ }
+
+ /** Request default bit count for depth- or stencil buffer (depth 24 bits, stencil 8 bits), value {@value} */
+ public static final int DEFAULT_BITS = 0;
+
+ /**
+ * Request current context drawable's <i>requested</i>
+ * {@link GLCapabilitiesImmutable#getDepthBits() depth-} or {@link GLCapabilitiesImmutable#getStencilBits() stencil-}bits; value {@value} */
+ public static final int REQUESTED_BITS = -1;
+
+ /**
+ * Request current context drawable's <i>chosen</i>
+ * {@link GLCapabilitiesImmutable#getDepthBits() depth-} or {@link GLCapabilitiesImmutable#getStencilBits() stencil-}bits; value {@value} */
+ public static final int CHOSEN_BITS = -2;
+
+ /** Request maximum bit count for depth- or stencil buffer (depth 32 bits, stencil 16 bits), value {@value} */
+ public static final int MAXIMUM_BITS = -3;
+
+
/**
* Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance,
* selecting the internalFormat automatically.
@@ -1303,90 +1629,81 @@ public class FBObject {
* Stencil and depth buffer can be attached only once.
* </p>
* <p>
- * In case the desired type or bit-number is not supported, the next available one is chosen.
- * </p>
+ * In case the bit-count is not supported,
+ * the next available one is chosen, i.e. next higher (preferred) or lower bit-count.
+ * </p>
* <p>
* Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details
* about the attached buffer. The details cannot be returned, since it's possible 2 buffers
* are being created, depth and stencil.
* </p>
- *
+ *
* <p>Leaves the FBO bound.</p>
- *
+ *
* @param gl
- * @param atype either {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#DEPTH_STENCIL}
- * @param reqBits desired bits for depth or -1 for default (24 bits)
+ * @param atype either {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#DEPTH_STENCIL}
+ * @param reqBits desired bits for depth or stencil,
+ * may use generic values {@link #DEFAULT_BITS}, {@link #REQUESTED_BITS}, {@link #CHOSEN_BITS} or {@link #MAXIMUM_BITS}.
* @throws GLException in case the renderbuffer couldn't be allocated or one is already attached.
* @throws IllegalArgumentException
* @see #getDepthAttachment()
* @see #getStencilAttachment()
*/
- public final void attachRenderbuffer(GL gl, Attachment.Type atype, int reqBits) throws GLException, IllegalArgumentException {
- if( 0 > reqBits ) {
- reqBits = 24;
- }
+ public final void attachRenderbuffer(final GL gl, final Attachment.Type atype, final int reqBits) throws GLException, IllegalArgumentException {
+ final int reqDepth, reqStencil;
+ if( MAXIMUM_BITS > reqBits ) {
+ throw new IllegalArgumentException("reqBits out of range, shall be >= "+MAXIMUM_BITS);
+ } else if( MAXIMUM_BITS == reqBits ) {
+ reqDepth = 32;
+ reqStencil = 16;
+ } else if( CHOSEN_BITS == reqBits ) {
+ final GLCapabilitiesImmutable caps = gl.getContext().getGLDrawable().getChosenGLCapabilities();
+ reqDepth = caps.getDepthBits();
+ reqStencil = caps.getStencilBits();
+ } else if( REQUESTED_BITS == reqBits ) {
+ final GLCapabilitiesImmutable caps = gl.getContext().getGLDrawable().getRequestedGLCapabilities();
+ reqDepth = caps.getDepthBits();
+ reqStencil = caps.getStencilBits();
+ } else if( DEFAULT_BITS == reqBits ) {
+ reqDepth = 24;
+ reqStencil = 8;
+ } else {
+ reqDepth = reqBits;
+ reqStencil = reqBits;
+ }
final int internalFormat;
int internalStencilFormat = -1;
-
+
switch ( atype ) {
case DEPTH:
- if( 32 <= reqBits && depth32Avail ) {
- internalFormat = GL.GL_DEPTH_COMPONENT32;
- } else if( 24 <= reqBits && depth24Avail ) {
- internalFormat = GL.GL_DEPTH_COMPONENT24;
- } else {
- internalFormat = GL.GL_DEPTH_COMPONENT16;
- }
+ internalFormat = getDepthIFormat(reqDepth);
break;
-
+
case STENCIL:
- if( 16 <= reqBits && stencil16Avail ) {
- internalFormat = GL2GL3.GL_STENCIL_INDEX16;
- } else if( 8 <= reqBits && stencil08Avail ) {
- internalFormat = GL.GL_STENCIL_INDEX8;
- } else if( 4 <= reqBits && stencil04Avail ) {
- internalFormat = GL.GL_STENCIL_INDEX4;
- } else if( 1 <= reqBits && stencil01Avail ) {
- internalFormat = GL.GL_STENCIL_INDEX1;
- } else {
- throw new GLException("stencil buffer n/a");
- }
+ internalFormat = getStencilIFormat(reqStencil);
break;
-
+
case DEPTH_STENCIL:
if( packedDepthStencilAvail ) {
internalFormat = GL.GL_DEPTH24_STENCIL8;
} else {
- if( 24 <= reqBits && depth24Avail ) {
- internalFormat = GL.GL_DEPTH_COMPONENT24;
- } else {
- internalFormat = GL.GL_DEPTH_COMPONENT16;
- }
- if( stencil08Avail ) {
- internalStencilFormat = GL.GL_STENCIL_INDEX8;
- } else if( stencil04Avail ) {
- internalStencilFormat = GL.GL_STENCIL_INDEX4;
- } else if( stencil01Avail ) {
- internalStencilFormat = GL.GL_STENCIL_INDEX1;
- } else {
- throw new GLException("stencil buffer n/a");
- }
+ internalFormat = getDepthIFormat(reqDepth);
+ internalStencilFormat = getStencilIFormat(reqStencil);
}
break;
default:
throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this);
}
-
attachRenderbufferImpl(gl, atype, internalFormat);
-
+
if(0<=internalStencilFormat) {
attachRenderbufferImpl(gl, Attachment.Type.STENCIL, internalStencilFormat);
}
}
-
+
/**
* Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance,
- * depending on the <code>internalFormat</code>.
+ * depending on the <code>internalFormat</code>.
* <p>
* Stencil and depth buffer can be attached only once.
* </p>
@@ -1395,9 +1712,9 @@ public class FBObject {
* about the attached buffer. The details cannot be returned, since it's possible 2 buffers
* are being created, depth and stencil.
* </p>
- *
+ *
* <p>Leaves the FBO bound.</p>
- *
+ *
* @param gl the current GL context
* @param internalFormat {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24}, {@link GL#GL_DEPTH_COMPONENT32},
* {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8}
@@ -1407,376 +1724,478 @@ public class FBObject {
* @see #getDepthAttachment()
* @see #getStencilAttachment()
*/
- public final void attachRenderbuffer(GL gl, int internalFormat) throws GLException, IllegalArgumentException {
+ public final void attachRenderbuffer(final GL gl, final int internalFormat) throws GLException, IllegalArgumentException {
final Attachment.Type atype = Attachment.Type.determine(internalFormat);
if( Attachment.Type.DEPTH != atype && Attachment.Type.STENCIL != atype && Attachment.Type.DEPTH_STENCIL != atype ) {
- throw new IllegalArgumentException("renderformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this);
+ throw new IllegalArgumentException("renderformat invalid: "+toHexString(internalFormat)+", "+this);
}
attachRenderbufferImpl(gl, atype, internalFormat);
}
-
- protected final void attachRenderbufferImpl(GL gl, Attachment.Type atype, int internalFormat) throws GLException {
+
+ protected final void attachRenderbufferImpl(final GL gl, final Attachment.Type atype, final int internalFormat) throws GLException {
if( null != depth && ( Attachment.Type.DEPTH == atype || Attachment.Type.DEPTH_STENCIL == atype ) ) {
- throw new GLException("FBO depth buffer already attached (rb "+depth+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this);
- }
+ throw new GLException("FBO depth buffer already attached (rb "+depth+"), type is "+atype+", "+toHexString(internalFormat)+", "+this);
+ }
if( null != stencil && ( Attachment.Type.STENCIL== atype || Attachment.Type.DEPTH_STENCIL == atype ) ) {
- throw new GLException("FBO stencil buffer already attached (rb "+stencil+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this);
+ throw new GLException("FBO stencil buffer already attached (rb "+stencil+"), type is "+atype+", "+toHexString(internalFormat)+", "+this);
}
+ bind(gl);
+
attachRenderbufferImpl2(gl, atype, internalFormat);
}
-
- private final void attachRenderbufferImpl2(GL gl, Attachment.Type atype, int internalFormat) throws GLException {
+
+ private final void attachRenderbufferImpl2(final GL gl, final Attachment.Type atype, final int internalFormat) throws GLException {
+ // atype and current depth and stencil instance are already validated in 'attachRenderbufferImpl(..)'
if( Attachment.Type.DEPTH == atype ) {
if(null == depth) {
- depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0);
+ depth = createRenderAttachment(Type.DEPTH, internalFormat, samples, width, height);
} else {
depth.setSize(width, height);
depth.setSamples(samples);
}
+ validateAttachmentSize(depth);
depth.initialize(gl);
} else if( Attachment.Type.STENCIL == atype ) {
if(null == stencil) {
- stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, 0);
+ stencil = createRenderAttachment(Type.STENCIL, internalFormat, samples, width, height);
} else {
stencil.setSize(width, height);
stencil.setSamples(samples);
}
+ validateAttachmentSize(stencil);
stencil.initialize(gl);
} else if( Attachment.Type.DEPTH_STENCIL == atype ) {
if(null == depth) {
- depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0);
+ if(null != stencil) {
+ throw new InternalError("XXX: DEPTH_STENCIL, depth was null, stencil not: "+this.toString());
+ }
+ depth = createRenderAttachment(Type.DEPTH_STENCIL, internalFormat, samples, width, height);
} else {
depth.setSize(width, height);
depth.setSamples(samples);
}
+ validateAttachmentSize(depth);
depth.initialize(gl);
- if(null == stencil) {
- stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, depth.getName());
- } else {
- stencil.setName(depth.getName());
- stencil.setSize(width, height);
- stencil.setSamples(samples);
- }
- stencil.initialize(gl);
+ // DEPTH_STENCIL shares buffer w/ depth and stencil
+ stencil = depth;
}
- bind(gl);
-
// Attach the buffer
if( Attachment.Type.DEPTH == atype ) {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName());
} else if( Attachment.Type.STENCIL == atype ) {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName());
} else if( Attachment.Type.DEPTH_STENCIL == atype ) {
- gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName());
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName());
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName());
}
-
+
+ modified = true;
+
if(!ignoreStatus) {
updateStatus(gl);
if( !isStatusValid() ) {
detachRenderbuffer(gl, atype, true);
- throw new GLException("renderbuffer attachment failed: "+this.getStatusString());
+ throw new GLException("renderbuffer [attachmentType "+atype+", iformat "+toHexString(internalFormat)+"] failed: "+this.getStatusString()+": "+this.toString());
}
}
if(DEBUG) {
- System.err.println("FBObject.attachRenderbuffer: [attachmentType "+atype+"]: "+this);
- }
+ System.err.println("FBObject.attachRenderbuffer.X: [attachmentType "+atype+", iformat "+toHexString(internalFormat)+"]: "+this);
+ }
}
-
+
/**
- * Detaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}.
+ * Detaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}.
* <p>Leaves the FBO bound!</p>
- *
+ *
* @param gl
* @param attachmentPoint
* @param dispose true if the Colorbuffer shall be disposed
* @return the detached Colorbuffer
* @throws IllegalArgumentException
*/
- public final Colorbuffer detachColorbuffer(GL gl, int attachmentPoint, boolean dispose) throws IllegalArgumentException {
- final Colorbuffer res = detachColorbufferImpl(gl, attachmentPoint, dispose ? DetachAction.DISPOSE : DetachAction.NONE);
+ public final Colorbuffer detachColorbuffer(final GL gl, final int attachmentPoint, final boolean dispose) throws IllegalArgumentException {
+ bind(gl);
+
+ final Colorbuffer res = detachColorbufferImpl(gl, attachmentPoint, dispose ? DetachAction.DISPOSE : DetachAction.NONE, 0);
if(null == res) {
- throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this);
+ throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this);
}
if(DEBUG) {
- System.err.println("FBObject.detachColorbuffer: [attachmentPoint "+attachmentPoint+", dispose "+dispose+"]: "+res+", "+this);
+ System.err.println("FBObject.detachColorbuffer.X: [attachmentPoint "+attachmentPoint+", dispose "+dispose+"]: "+res+", "+this);
}
return res;
}
-
- private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, DetachAction detachAction) {
- Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here
-
- if(null == colbuf) {
+
+ private final Colorbuffer detachColorbufferImpl(final GL gl, final int attachmentPoint, final DetachAction detachAction, final int sampleCountChange) {
+ final Colorbuffer colbufOld = colorbufferAttachments[attachmentPoint]; // shortcut, don't validate here
+
+ if(null == colbufOld) {
return null;
}
-
- bind(gl);
-
- removeColorAttachment(attachmentPoint, colbuf);
-
- if(colbuf instanceof TextureAttachment) {
- final TextureAttachment texA = (TextureAttachment) colbuf;
+
+ removeColorAttachment(attachmentPoint, colbufOld);
+
+ if( colbufOld.isTextureAttachment() ) {
+ final TextureAttachment texA = colbufOld.getTextureAttachment();
if( 0 != texA.getName() ) {
gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
GL.GL_TEXTURE_2D, 0, 0);
gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
+ switch(detachAction) {
+ case DISPOSE:
+ case RECREATE:
+ texA.free(gl);
+ break;
+ default:
+ }
}
- switch(detachAction) {
- case DISPOSE:
- texA.free(gl);
- break;
- case RECREATE:
- texA.free(gl);
- if(samples == 0) {
- // stay non MSAA
- texA.setSize(width, height);
- } else {
- // switch to MSAA
- colbuf = createColorAttachment(hasAlpha(texA.format));
- }
- attachColorbuffer(gl, attachmentPoint, colbuf);
- break;
- default:
+ if(DetachAction.RECREATE == detachAction) {
+ final Colorbuffer colbufNew;
+ if( 0 < sampleCountChange ) {
+ // switch to MSAA: TextureAttachment -> ColorAttachment
+ colbufNew = createColorAttachment(hasAlpha(texA.format));
+ } else {
+ // keep MSAA settings
+ texA.setSize(width, height);
+ colbufNew = texA;
+ }
+ attachColorbufferImpl(gl, attachmentPoint, colbufNew);
}
- } else if(colbuf instanceof ColorAttachment) {
- final ColorAttachment colA = (ColorAttachment) colbuf;
+ } else {
+ final ColorAttachment colA = colbufOld.getColorAttachment();
if( 0 != colA.getName() ) {
- gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
- GL.GL_COLOR_ATTACHMENT0+attachmentPoint,
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0+attachmentPoint,
GL.GL_RENDERBUFFER, 0);
+ switch(detachAction) {
+ case DISPOSE:
+ case RECREATE:
+ colA.free(gl);
+ break;
+ default:
+ }
}
- switch(detachAction) {
- case DISPOSE:
- colA.free(gl);
- break;
- case RECREATE:
- colA.free(gl);
- if(samples > 0) {
- // stay MSAA
- colA.setSize(width, height);
- colA.setSamples(samples);
+ if(DetachAction.RECREATE == detachAction) {
+ final Colorbuffer colbufNew;
+ if( 0 <= sampleCountChange || null == samplingColorSink ) {
+ // keep ColorAttachment,
+ // including 'switch to non-MSAA' if no samplingColorSink is available
+ // to determine whether a TextureAttachment or ColorAttachment is desired!
+ colA.setSize(width, height);
+ colA.setSamples(samples);
+ colbufNew = colA;
+ } else {
+ // switch to non MSAA
+ if( samplingColorSink.isTextureAttachment() ) {
+ final TextureAttachment samplingTextureSink = samplingColorSink.getTextureAttachment();
+ colbufNew = createColorTextureAttachment(samplingTextureSink.format, width, height,
+ samplingTextureSink.dataFormat, samplingTextureSink.dataType,
+ samplingTextureSink.magFilter, samplingTextureSink.minFilter,
+ samplingTextureSink.wrapS, samplingTextureSink.wrapT);
} else {
- // switch to non MSAA
- if(null != samplesSinkTexture) {
- colbuf = createColorTextureAttachment(samplesSinkTexture.format, width, height,
- samplesSinkTexture.dataFormat, samplesSinkTexture.dataType,
- samplesSinkTexture.magFilter, samplesSinkTexture.minFilter,
- samplesSinkTexture.wrapS, samplesSinkTexture.wrapT);
- } else {
- colbuf = createColorTextureAttachment(gl.getGLProfile(), true, width, height);
- }
+ colbufNew = createColorAttachment(samplingColorSink.getFormat(), 0, width, height);
}
- attachColorbuffer(gl, attachmentPoint, colbuf);
- break;
- default:
+ }
+ attachColorbuffer(gl, attachmentPoint, colbufNew);
+ }
+ }
+ return colbufOld;
+ }
+
+ private final void freeAllColorbufferImpl(final GL gl) {
+ for(int i=0; i<maxColorAttachments; i++) {
+ final Colorbuffer colbuf = colorbufferAttachments[i]; // shortcut, don't validate here
+
+ if(null == colbuf) {
+ return;
+ }
+
+ if( colbuf.isTextureAttachment() ) {
+ final TextureAttachment texA = colbuf.getTextureAttachment();
+ if( 0 != texA.getName() ) {
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + i,
+ GL.GL_TEXTURE_2D, 0, 0);
+ gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
+ }
+ texA.free(gl);
+ } else {
+ final ColorAttachment colA = colbuf.getColorAttachment();
+ if( 0 != colA.getName() ) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + i,
+ GL.GL_RENDERBUFFER, 0);
+ }
+ colA.free(gl);
}
}
- return colbuf;
}
-
+
/**
- *
+ *
* @param gl
* @param dispose true if the Colorbuffer shall be disposed
- * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL}
+ * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL}
*/
- public final void detachRenderbuffer(GL gl, Attachment.Type atype, boolean dispose) throws IllegalArgumentException {
- detachRenderbufferImpl(gl, atype, dispose ? DetachAction.DISPOSE : DetachAction.NONE);
+ public final void detachRenderbuffer(final GL gl, final Attachment.Type atype, final boolean dispose) throws IllegalArgumentException {
+ bind(gl);
+ final RenderAttachment res = detachRenderbufferImpl(gl, atype, dispose ? DetachAction.DISPOSE : DetachAction.NONE);
+ if(null == res) {
+ throw new IllegalArgumentException("RenderAttachment type "+atype+", not attached, "+this);
+ }
if(DEBUG) {
- System.err.println("FBObject.detachRenderbuffer: [attachmentType "+atype+", dispose "+dispose+"]: "+this);
- }
+ System.err.println("FBObject.detachRenderbuffer.X: [attachmentType "+atype+", dispose "+dispose+"]: "+this);
+ }
}
-
+
public final boolean isDepthStencilPackedFormat() {
final boolean res = null != depth && null != stencil &&
depth.format == stencil.format ;
- if(res && depth.getName() != stencil.getName() ) {
- throw new InternalError("depth/stencil packed format not sharing: depth "+depth+", stencil "+stencil);
+ if(res) {
+ if(depth.getName() != stencil.getName() ) {
+ throw new InternalError("depth/stencil packed format not sharing: depth "+depth+", stencil "+stencil);
+ }
+ if(depth != stencil) {
+ throw new InternalError("depth/stencil packed format not a shared reference: depth "+depth+", stencil "+stencil);
+ }
}
return res;
}
-
- private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, DetachAction detachAction) throws IllegalArgumentException {
+
+ private final RenderAttachment detachRenderbufferImpl(final GL gl, Attachment.Type atype, final DetachAction detachAction) throws IllegalArgumentException {
switch ( atype ) {
case DEPTH:
case STENCIL:
- case DEPTH_STENCIL:
+ case DEPTH_STENCIL:
break;
default:
throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this);
- }
+ }
if( null == depth && null == stencil ) {
- return ; // nop
- }
- // reduction of possible combinations, create unique atype command(s)
- final ArrayList<Attachment.Type> actions = new ArrayList<Attachment.Type>(2);
- if( isDepthStencilPackedFormat() ) {
- // packed
- actions.add(Attachment.Type.DEPTH_STENCIL);
- } else {
- // individual
- switch ( atype ) {
- case DEPTH:
- if( null != depth ) { actions.add(Attachment.Type.DEPTH); }
- break;
- case STENCIL:
- if( null != stencil ) { actions.add(Attachment.Type.STENCIL); }
- break;
- case DEPTH_STENCIL:
- if( null != depth ) { actions.add(Attachment.Type.DEPTH); }
- if( null != stencil ) { actions.add(Attachment.Type.STENCIL); }
- break;
- default: // handled
- }
+ return null; // nop
}
-
- bind(gl);
-
- for(int i = 0; i < actions.size(); i++) {
- final int format;
-
- Attachment.Type action = actions.get(i);
- switch ( action ) {
- case DEPTH:
- format = depth.format;
- if( 0 != depth.getName() ) {
+ final boolean packed = isDepthStencilPackedFormat();
+ if( packed ) {
+ // Note: DEPTH_STENCIL shares buffer w/ depth and stencil
+ atype = Attachment.Type.DEPTH_STENCIL;
+ }
+ final RenderAttachment renderOld;
+ switch ( atype ) {
+ case DEPTH:
+ renderOld = depth;
+ if( null != renderOld ) {
+ final int format = renderOld.format;
+ if( 0 != renderOld.getName() ) {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ switch(detachAction) {
+ case DISPOSE:
+ case RECREATE:
+ renderOld.free(gl);
+ break;
+ default:
+ }
}
- switch(detachAction) {
- case DISPOSE:
- case RECREATE:
- depth.free(gl);
- break;
- default:
- }
- if(DetachAction.RECREATE != detachAction) {
+ if(DetachAction.RECREATE == detachAction) {
+ attachRenderbufferImpl2(gl, atype, format);
+ } else {
depth = null;
}
- break;
- case STENCIL:
- format = stencil.format;
- if(0 != stencil.getName()) {
+ }
+ break;
+ case STENCIL:
+ renderOld = stencil;
+ if( null != renderOld ) {
+ final int format = renderOld.format;
+ if(0 != renderOld.getName()) {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ switch(detachAction) {
+ case DISPOSE:
+ case RECREATE:
+ renderOld.free(gl);
+ break;
+ default:
+ }
}
- switch(detachAction) {
- case DISPOSE:
- case RECREATE:
- stencil.free(gl);
- break;
- default:
- }
- if(DetachAction.RECREATE != detachAction) {
+ if(DetachAction.RECREATE == detachAction) {
+ attachRenderbufferImpl2(gl, atype, format);
+ } else {
stencil = null;
}
- break;
- case DEPTH_STENCIL:
- format = depth.format;
- if(0 != depth.getName()) {
+ }
+ break;
+ case DEPTH_STENCIL:
+ renderOld = depth;
+ if( null != renderOld ) {
+ final int format = renderOld.format;
+ if(0 != renderOld.getName()) {
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
- gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
- }
- switch(detachAction) {
- case DISPOSE:
- case RECREATE:
- depth.free(gl);
- stencil.free(gl);
- break;
- default:
+ if(packed) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ }
+ switch(detachAction) {
+ case DISPOSE:
+ case RECREATE:
+ renderOld.free(gl);
+ break;
+ default:
+ }
}
- if(DetachAction.RECREATE != detachAction) {
+ if(DetachAction.RECREATE == detachAction) {
+ attachRenderbufferImpl2(gl, packed ? Attachment.Type.DEPTH_STENCIL : Attachment.Type.DEPTH, format);
+ } else {
depth = null;
+ if(packed) {
+ stencil = null;
+ }
+ }
+ }
+ if( !packed && null != stencil ) {
+ final int format = stencil.format;
+ if(0 != stencil.getName()) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ switch(detachAction) {
+ case DISPOSE:
+ case RECREATE:
+ stencil.free(gl);
+ break;
+ default:
+ }
+ }
+ if(DetachAction.RECREATE == detachAction) {
+ attachRenderbufferImpl2(gl, Attachment.Type.STENCIL, format);
+ } else {
stencil = null;
}
- break;
- default:
- throw new InternalError("XXX");
+ }
+ break;
+ default:
+ throw new InternalError("XXX"); // handled by caller
+ }
+ modified = true;
+ return renderOld;
+ }
+
+ private final void freeAllRenderbufferImpl(final GL gl) throws IllegalArgumentException {
+ // Note: DEPTH_STENCIL shares buffer w/ depth and stencil
+ final boolean packed = isDepthStencilPackedFormat();
+ if( null != depth ) {
+ if(0 != depth.getName()) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ if(packed) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ }
+ depth.free(gl);
}
- if(DetachAction.RECREATE == detachAction) {
- attachRenderbufferImpl2(gl, action, format);
+ }
+ if( !packed && null != stencil ) {
+ if(0 != stencil.getName()) {
+ gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0);
+ stencil.free(gl);
}
- }
+ }
}
-
- /**
+
+ /**
* Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s
* and disposes them.
- * <p>Leaves the FBO bound!</p>
+ * <p>Leaves the FBO bound, if initialized!</p>
* <p>
- * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
- * </p>
+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingTextureSink()}.
+ * </p>
* @param gl the current GL context
*/
- public final void detachAll(GL gl) {
- if(null != samplesSink) {
- samplesSink.detachAll(gl);
- }
- detachAllImpl(gl, true/* detachNonColorbuffer */, false /* recreate */);
- }
-
- /**
- * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s
+ public final void detachAll(final GL gl) {
+ if(null != samplingSink) {
+ samplingSink.detachAll(gl);
+ }
+ detachAllImpl(gl, true/* detachNonColorbuffer */, false /* recreate */, 0);
+ }
+
+ /**
+ * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s
* and disposes them.
- * <p>Leaves the FBO bound!</p>
+ * <p>Leaves the FBO bound, if initialized!</p>
* <p>
- * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
- * </p>
+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingTextureSink()}.
+ * </p>
* @param gl the current GL context
*/
- public final void detachAllColorbuffer(GL gl) {
- if(null != samplesSink) {
- samplesSink.detachAllColorbuffer(gl);
- }
- detachAllImpl(gl, false/* detachNonColorbuffer */, false /* recreate */);
- }
-
- /**
- * Detaches all {@link TextureAttachment}s and disposes them.
- * <p>Leaves the FBO bound!</p>
+ public final void detachAllColorbuffer(final GL gl) {
+ if(null != samplingSink) {
+ samplingSink.detachAllColorbuffer(gl);
+ }
+ detachAllImpl(gl, false/* detachNonColorbuffer */, false /* recreate */, 0);
+ }
+
+ /**
+ * Detaches all {@link TextureAttachment}s and disposes them.
+ * <p>Leaves the FBO bound, if initialized!</p>
* <p>
- * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
- * </p>
+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingTextureSink()}.
+ * </p>
* @param gl the current GL context
*/
- public final void detachAllTexturebuffer(GL gl) {
- if(null != samplesSink) {
- samplesSink.detachAllTexturebuffer(gl);
+ public final void detachAllTexturebuffer(final GL gl) {
+ if( !isInitialized() ) {
+ return;
}
+ if(null != samplingSink) {
+ samplingSink.detachAllTexturebuffer(gl);
+ }
+ bind(gl);
for(int i=0; i<maxColorAttachments; i++) {
- if(colorAttachmentPoints[i] instanceof TextureAttachment) {
- detachColorbufferImpl(gl, i, DetachAction.DISPOSE);
+ if( colorbufferAttachments[i].isTextureAttachment() ) {
+ detachColorbufferImpl(gl, i, DetachAction.DISPOSE, 0);
}
}
if(DEBUG) {
- System.err.println("FBObject.detachAllTexturebuffer: "+this);
+ System.err.println("FBObject.detachAllTexturebuffer.X: "+this);
}
}
-
- public final void detachAllRenderbuffer(GL gl) {
- if(null != samplesSink) {
- samplesSink.detachAllRenderbuffer(gl);
+
+ public final void detachAllRenderbuffer(final GL gl) {
+ if( !isInitialized() ) {
+ return;
+ }
+ if(null != samplingSink) {
+ samplingSink.detachAllRenderbuffer(gl);
}
+ bind(gl);
detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, DetachAction.DISPOSE);
}
-
- private final void detachAllImpl(GL gl, boolean detachNonColorbuffer, boolean recreate) {
+
+ private final void detachAllImpl(final GL gl, final boolean detachNonColorbuffer, final boolean recreate, final int sampleCountChange) {
+ if( !isInitialized() ) {
+ return;
+ }
ignoreStatus = recreate; // ignore status on single calls only if recreate -> reset
try {
+ bind(gl);
+ if(FBOResizeQuirk) {
+ if(detachNonColorbuffer && recreate) {
+ // free all colorbuffer & renderbuffer 1st
+ freeAllColorbufferImpl(gl);
+ freeAllRenderbufferImpl(gl);
+ }
+ }
for(int i=0; i<maxColorAttachments; i++) {
- detachColorbufferImpl(gl, i, recreate ? DetachAction.RECREATE : DetachAction.DISPOSE);
+ detachColorbufferImpl(gl, i, recreate ? DetachAction.RECREATE : DetachAction.DISPOSE, sampleCountChange);
}
- if( !recreate && colorAttachmentCount>0 ) {
+ if( !recreate && colorbufferCount>0 ) {
throw new InternalError("Non zero ColorAttachments "+this);
}
-
+
if(detachNonColorbuffer) {
detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, recreate ? DetachAction.RECREATE : DetachAction.DISPOSE);
}
if(ignoreStatus) { // post validate
- updateStatus(gl);
+ /* if(true) {
+ throw new GLException("Simulating bug 617, reset FBO failure");
+ } */
+ updateStatus(gl);
if(!isStatusValid()) {
throw new GLException("detachAllImpl failed "+getStatusString()+", "+this);
}
@@ -1785,182 +2204,337 @@ public class FBObject {
ignoreStatus = false;
}
if(DEBUG) {
- System.err.println("FBObject.detachAll: [resetNonColorbuffer "+detachNonColorbuffer+", recreate "+recreate+"]: "+this);
+ System.err.println("FBObject.detachAll.X: [resetNonColorbuffer "+detachNonColorbuffer+", recreate "+recreate+"]: "+this);
}
}
-
+
/**
* @param gl the current GL context
*/
- public final void destroy(GL gl) {
- if(null != samplesSink) {
- samplesSink.destroy(gl);
+ public final void destroy(final GL gl) {
+ if(!initialized) {
+ return;
+ }
+ if(DEBUG) {
+ System.err.println("FBObject.destroy.0: "+this);
+ // Thread.dumpStack();
}
-
- detachAllImpl(gl, true /* detachNonColorbuffer */, false /* recreate */);
-
+ if( null != samplingSink && samplingSink.isInitialized() ) {
+ samplingSink.destroy(gl);
+ }
+
+ detachAllImpl(gl, true /* detachNonColorbuffer */, false /* recreate */, 0);
+
// cache FB names, preset exposed to zero,
// braking ties w/ GL/GLContext link to getReadFramebuffer()/getWriteFramebuffer()
final int fb_cache = fbName;
fbName = 0;
- int name[] = new int[1];
+ final int name[] = new int[1];
if(0!=fb_cache) {
name[0] = fb_cache;
gl.glDeleteFramebuffers(1, name, 0);
- }
+ }
initialized = false;
bound = false;
if(DEBUG) {
- System.err.println("FBObject.destroy: "+this);
+ System.err.println("FBObject.destroy.X: "+this);
}
}
private final boolean sampleSinkSizeMismatch() {
- return samplesSink.getWidth() != width || samplesSink.getHeight() != height ;
- }
- private final boolean sampleSinkTexMismatch() {
- return null == samplesSinkTexture || 0 == samplesSinkTexture.getName() ;
+ return samplingSink.getWidth() != width || samplingSink.getHeight() != height ;
}
private final boolean sampleSinkDepthStencilMismatch() {
- final boolean depthMismatch = ( null != depth && null == samplesSink.depth ) ||
- ( null != depth && null != samplesSink.depth &&
- depth.format != samplesSink.depth.format );
-
- final boolean stencilMismatch = ( null != stencil && null == samplesSink.stencil ) ||
- ( null != stencil && null != samplesSink.stencil &&
- stencil.format != samplesSink.stencil.format );
-
- return depthMismatch || stencilMismatch;
- }
-
- private final void resetMSAATexture2DSink(GL gl) throws GLException {
- if(null == samplesSink ) {
- return; // this is the sample sink!
- }
- if(0 == samples) {
+ if ( ( null != depth && ( null == samplingSink.depth || depth.format != samplingSink.depth.format ) )
+ ||
+ ( null == depth && null != samplingSink.depth )
+ ) {
+ return true;
+ }
+
+ if ( ( null != stencil && ( null == samplingSink.stencil || stencil.format != samplingSink.stencil.format ) )
+ ||
+ ( null == stencil && null != samplingSink.stencil )
+ ) {
+ return true;
+ }
+
+ return false;
+ }
+ /**
+ * For GLES3, sampling-sink {@link Colorbuffer} <i>internal format</i> <b>must be equal</b> w/ the sampling-source {@link Colorbuffer}.
+ * Implementation aligns w/ {@link #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int)}
+ * and {@link #createColorAttachment(boolean)}.
+ */
+ private final boolean sampleSinkExFormatMismatch(final GL gl) {
+ if( null != samplingColorSink && getColorbufferCount() > 0 && gl.isGL2ES3() ) {
+ final Attachment ca = (Attachment)getColorbuffer(0); // should be at attachment-point 0
+ // We cannot comply w/ attachment's format other than attachment point 0!
+ // return ( null != ca && ca.format != samplingColorSink.getFormat() ) ||
+ // hasAlpha(samplingColorSink.getFormat()) != hasAttachmentUsingAlpha();
+ return null != ca && ca.format != samplingColorSink.getFormat();
+ }
+ return false;
+ }
+
+ /**
+ * Manually validates the MSAA sampling sink, if used.
+ * <p>
+ * If MSAA is being used and no sampling sink is attached via {@link #setSamplingSink(FBObject)}
+ * a new sampling sink is being created.
+ * </p>
+ * <p>
+ * If the sampling sink size or attributes differs from the source, its attachments are reset
+ * to match the source.
+ * </p>
+ * <p>
+ * Automatically called by {@link #reset(GL, int, int, int, boolean)}
+ * and {@link #syncSamplingSink(GL)}.
+ * </p>
+ * <p>
+ * It is recommended to call this method after initializing the FBO and attaching renderbuffer etc for the 1st time
+ * if access to sampling sink resources is required.
+ * </p>
+ *
+ * <p>Leaves the FBO bound state untouched</p>
+ *
+ * @param gl the current GL context
+ * @return {@code true} if this instance has been modified, otherwise {@code false}.
+ * @throws GLException in case of an error, i.e. size too big, etc ..
+ */
+ public final boolean resetSamplingSink(final GL gl) throws GLException {
+ if(DEBUG) {
+ System.err.println("FBObject.resetSamplingSink.0");
+ Thread.dumpStack();
+ }
+
+ if( 0 == samples ) {
+ final boolean modifiedInstance;
// MSAA off
- if(samplesSink.initialized) {
+ if( null != samplingSink ) {
// cleanup
- samplesSink.detachAll(gl);
+ if( samplingSink.initialized ) {
+ samplingSink.detachAll(gl);
+ }
+ samplingSink = null;
+ samplingColorSink = null;
+ modifiedInstance = true;
+ } else {
+ modifiedInstance = false;
}
- return;
+ this.modified = false;
+ if(DEBUG) {
+ System.err.println("FBObject.resetSamplingSink.X1: zero samples, mod "+modifiedInstance+"\n\tTHIS "+this);
+ }
+ return modifiedInstance;
+ }
+
+ boolean modifiedInstance = false;
+
+ if( null == samplingSink ) {
+ samplingSink = new FBObject();
+ samplingSink.init(gl, width, height, 0);
+ samplingColorSink = null;
+ modifiedInstance = true;
+ } else if( !samplingSink.initialized ) {
+ throw new InternalError("InitState Mismatch: samplingSink set, but not initialized "+samplingSink);
+ } else if( null == samplingColorSink || 0 == samplingColorSink.getName() ) {
+ throw new InternalError("InitState Mismatch: samplingColorSink set, but not initialized "+samplingColorSink+", "+samplingSink);
}
-
- if(!samplesSink.initialized) {
- samplesSink.init(gl, width, height, 0);
+
+ if(DEBUG) {
+ System.err.println("FBObject.resetSamplingSink.1: mod "+modifiedInstance+"\n\tTHIS "+this+",\n\tSINK "+samplingSink);
}
-
+ boolean sampleSinkExFormatMismatch = sampleSinkExFormatMismatch(gl);
boolean sampleSinkSizeMismatch = sampleSinkSizeMismatch();
- boolean sampleSinkTexMismatch = sampleSinkTexMismatch();
boolean sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch();
-
- /** if(DEBUG) {
- System.err.println("FBObject.resetMSAATexture2DSink.0: \n\tTHIS "+this+",\n\tSINK "+samplesSink+
- "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
- } */
-
- if(!sampleSinkSizeMismatch && !sampleSinkTexMismatch && !sampleSinkDepthStencilMismatch) {
- // all properties match ..
- return;
- }
-
- unbind(gl);
-
+
+ if( modifiedInstance ) {
+ // samplingColorSink == null
+ // must match size, format and colorbuffer do not exist yet
+ if( sampleSinkExFormatMismatch || sampleSinkSizeMismatch ) {
+ throw new InternalError("InitState Mismatch: Matching exFormat "+!sampleSinkExFormatMismatch+
+ ", size "+!sampleSinkSizeMismatch +", "+this);
+ }
+ } else {
+ // samplingColorSink != null
+ if(!sampleSinkExFormatMismatch && !sampleSinkSizeMismatch && !sampleSinkDepthStencilMismatch) {
+ if(DEBUG) {
+ System.err.println("FBObject.resetSamplingSink.X2: Matching: exFormat "+!sampleSinkExFormatMismatch+
+ ", size "+!sampleSinkSizeMismatch +", depthStencil "+!sampleSinkDepthStencilMismatch+
+ ", mod "+modifiedInstance);
+ }
+ // all properties match ..
+ samplingSink.modified = false;
+ this.modified = false;
+ return modifiedInstance;
+ }
+ }
+
+ final boolean wasBound;
+ if( isBound() ) {
+ markUnbound(); // automatic GL unbind by sampleSink binding
+ wasBound = true;
+ } else {
+ wasBound = false;
+ }
+
if(DEBUG) {
- System.err.println("FBObject.resetMSAATexture2DSink: BEGIN\n\tTHIS "+this+",\n\tSINK "+samplesSink+
- "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
- }
-
- if( sampleSinkDepthStencilMismatch ) {
- samplesSink.detachAllRenderbuffer(gl);
- }
-
- if( sampleSinkSizeMismatch ) {
- samplesSink.reset(gl, width, height);
- }
-
- if(null == samplesSinkTexture) {
- samplesSinkTexture = samplesSink.attachTexture2D(gl, 0, true);
- } else if( 0 == samplesSinkTexture.getName() ) {
- samplesSinkTexture.setSize(width, height);
- samplesSink.attachColorbuffer(gl, 0, samplesSinkTexture);
- }
-
- if( sampleSinkDepthStencilMismatch ) {
- samplesSink.attachRenderbuffer(gl, depth.format);
+ System.err.println("FBObject.resetSamplingSink.2: wasBound "+wasBound+", matching: exFormat "+!sampleSinkExFormatMismatch+
+ ", size "+!sampleSinkSizeMismatch +", depthStencil "+!sampleSinkDepthStencilMismatch);
+ }
+
+ modifiedInstance = true;
+
+ if( sampleSinkDepthStencilMismatch ) { // includes 1st init
+ samplingSink.detachAllRenderbuffer(gl);
+ }
+
+ final boolean samplingColorSinkShallBeTA = null == samplingColorSink || samplingColorSink.isTextureAttachment();
+
+ if( sampleSinkExFormatMismatch ) {
+ samplingSink.detachAllColorbuffer(gl);
+ samplingColorSink = null;
+ } else if( sampleSinkSizeMismatch ) {
+ samplingSink.resetSizeImpl(gl, width, height);
+ samplingColorSink = samplingSink.getColorbuffer(0);
+ }
+
+ if( null == samplingColorSink ) { // sampleSinkFormatMismatch || 1st init
+ final Colorbuffer cb0 = getColorbuffer(0); // align with colorbuffer at attachment-point 0
+ if( null != cb0 ) {
+ // match pre-existing format
+ if( samplingColorSinkShallBeTA ) {
+ samplingColorSink = createColorTextureAttachment(gl, cb0.getFormat(), width, height,
+ GL.GL_NEAREST, GL.GL_NEAREST,
+ GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ } else {
+ samplingColorSink = createColorAttachment(cb0.getFormat(), 0, width, height);
+ }
+ samplingSink.attachColorbuffer(gl, 0, samplingColorSink);
+ } else {
+ // match default format
+ final boolean hasAlpha = hasAttachmentUsingAlpha();
+ if( samplingColorSinkShallBeTA ) {
+ samplingColorSink = samplingSink.attachTexture2D(gl, 0, hasAlpha);
+ } else {
+ samplingColorSink = samplingSink.attachColorbuffer(gl, 0, hasAlpha);
+ }
+ }
+ }
+
+ if( sampleSinkDepthStencilMismatch ) { // includes 1st init
+ samplingSink.attachRenderbuffer(gl, depth.format);
if( null != stencil && !isDepthStencilPackedFormat() ) {
- samplesSink.attachRenderbuffer(gl, stencil.format);
+ samplingSink.attachRenderbuffer(gl, stencil.format);
}
- }
-
+ }
+
+ sampleSinkExFormatMismatch = sampleSinkExFormatMismatch(gl);
sampleSinkSizeMismatch = sampleSinkSizeMismatch();
- sampleSinkTexMismatch = sampleSinkTexMismatch();
sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch();
- if(sampleSinkSizeMismatch || sampleSinkTexMismatch || sampleSinkDepthStencilMismatch) {
- throw new InternalError("Samples sink mismatch after reset: \n\tTHIS "+this+",\n\t SINK "+samplesSink+
- "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
+ if(sampleSinkExFormatMismatch || sampleSinkSizeMismatch || sampleSinkDepthStencilMismatch) {
+ throw new InternalError("Samples sink mismatch after reset: \n\tTHIS "+this+",\n\t SINK "+samplingSink+
+ "\n\t Mismatch. Matching: exFormat "+!sampleSinkExFormatMismatch+
+ ", size "+!sampleSinkSizeMismatch +", depthStencil "+!sampleSinkDepthStencilMismatch);
+ }
+
+ samplingSink.modified = false;
+ samplingSink.unbind(gl);
+ this.modified = false;
+
+ if(wasBound) {
+ bind(gl);
}
-
+
if(DEBUG) {
- System.err.println("FBObject.resetMSAATexture2DSink: END\n\tTHIS "+this+",\n\tSINK "+samplesSink+
- "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
+ System.err.println("FBObject.resetSamplingSink.XX: END mod "+modifiedInstance+"\n\tTHIS "+this+",\n\tSINK "+samplingSink+
+ "\n\t Matching: exFormat "+!sampleSinkExFormatMismatch+
+ ", size "+!sampleSinkSizeMismatch +", depthStencil "+!sampleSinkDepthStencilMismatch);
+ }
+ return modifiedInstance;
+ }
+
+ /**
+ * Setting this FBO sampling sink.
+ * @param newSamplingSink the new and initialized FBO sampling sink to use, or null to remove current sampling sink
+ * @return the previous sampling sink or null if none was attached
+ * @throws GLException if this FBO doesn't use MSAA or the given sink uses MSAA itself
+ * @throws IllegalStateException if the {@code newSamplingSink} is not null and not initialized
+ */
+ public FBObject setSamplingSink(final FBObject newSamplingSink) throws IllegalStateException, GLException {
+ final FBObject prev = samplingSink;
+ if( null == newSamplingSink) {
+ samplingSink = null;
+ samplingColorSink = null;
+ } else if( samples > 0 ) {
+ if( !newSamplingSink.isInitialized() ) {
+ throw new IllegalStateException("SamplingSink not initialized: "+newSamplingSink);
+ }
+ if( newSamplingSink.getNumSamples() > 0 ) {
+ throw new GLException("SamplingSink FBO cannot use MSAA itself: "+newSamplingSink);
+ }
+ samplingSink = newSamplingSink;
+ samplingColorSink = newSamplingSink.getColorbuffer(0);
+ } else {
+ throw new GLException("Setting SamplingSink for non MSAA FBO not allowed: "+this);
}
+ modified = true;
+ samplingSinkDirty = true;
+ return prev;
}
-
- /**
+
+ /**
* Bind this FBO, i.e. bind write framebuffer to {@link #getWriteFramebuffer()}.
- *
- * <p>If multisampling is used, it sets the read framebuffer to the sampling sink {@link #getWriteFramebuffer()},
- * if full FBO is supported.</p>
- *
- * <p>
+ *
+ * <p>
+ * If multisampling is used, it sets the read framebuffer to the sampling sink {@link #getWriteFramebuffer()}.
+ * </p>
+ * <p>
* In case you have attached more than one color buffer,
- * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}.
+ * you may want to setup {@link GL2ES3#glDrawBuffers(int, int[], int)}.
* </p>
* @param gl the current GL context
* @throws GLException
*/
- public final void bind(GL gl) throws GLException {
+ public final void bind(final GL gl) throws GLException {
if(!bound || fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER)) {
checkInitialized();
- if(samples > 0 && fullFBOSupport) {
- // draw to multisampling - read from samplesSink
- gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, getWriteFramebuffer());
- gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, getReadFramebuffer());
+ if( fullFBOSupport ) {
+ gl.glBindFramebuffer(GL2ES3.GL_DRAW_FRAMEBUFFER, getWriteFramebuffer()); // this fb, msaa or normal
+ gl.glBindFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER, getReadFramebuffer()); // msaa: sampling sink, normal: this fb
} else {
- // one for all
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, getWriteFramebuffer());
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, getWriteFramebuffer()); // normal: read/write
}
-
bound = true;
- samplesSinkDirty = true;
+ samplingSinkDirty = true;
}
}
- /**
+ /**
* Unbind this FBO, i.e. bind read and write framebuffer to default, see {@link GLBase#getDefaultDrawFramebuffer()}.
- *
- * <p>If full FBO is supported, sets the read and write framebuffer individually to default, hence not disturbing
+ *
+ * <p>If full FBO is supported, sets the read and write framebuffer individually to default, hence not disturbing
* an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}</p>
- *
+ *
* @param gl the current GL context
* @throws GLException
*/
- public final void unbind(GL gl) throws GLException {
+ public final void unbind(final GL gl) throws GLException {
if(bound) {
if(fullFBOSupport) {
- // default read/draw buffers, may utilize GLContext/GLDrawable override of
+ // default read/draw buffers, may utilize GLContext/GLDrawable override of
// GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer()
- gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0);
- gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0);
+ gl.glBindFramebuffer(GL2ES3.GL_DRAW_FRAMEBUFFER, 0);
+ gl.glBindFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER, 0);
} else {
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer
}
bound = false;
}
}
-
+
/**
* Method simply marks this FBO unbound w/o interfering w/ the bound framebuffer as perfomed by {@link #unbind(GL)}.
* <p>
@@ -1972,154 +2546,168 @@ public class FBObject {
bound = false;
}
- /**
+ /**
* Returns <code>true</code> if framebuffer object is bound via {@link #bind(GL)}, otherwise <code>false</code>.
* <p>
* Method verifies the bound state via {@link GL#getBoundFramebuffer(int)}.
* </p>
* @param gl the current GL context
*/
- public final boolean isBound(GL gl) {
- bound = bound && fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ;
+ public final boolean isBound(final GL gl) {
+ bound = bound && fbName == gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ;
return bound;
}
-
+
/** Returns <code>true</code> if framebuffer object is bound via {@link #bind(GL)}, otherwise <code>false</code>. */
public final boolean isBound() { return bound; }
-
- /**
+
+ /**
* If multisampling is being used and flagged dirty by a previous call of {@link #bind(GL)} or after initialization,
- * the msaa-buffers are sampled to it's sink {@link #getSamplingSink()}.
+ * the msaa-buffers are sampled to it's sink {@link #getSamplingTextureSink()}.
+ * <p>
+ * Method also resets the sampling sink configuration via {@link #resetSamplingSink(GL)} if used and required.
+ * </p>
* <p>
- * Method also updates the sampling sink configuration (if used). Hence it is recommended to call this
- * method after your have initialized the FBO and attached renderbuffer etc for the 1st time.
* Method is called automatically by {@link #use(GL, TextureAttachment)}.
* </p>
* <p>
- * Methos always resets the framebuffer binding to default in the end.
- * If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing
+ * Method always resets the framebuffer binding to default in the end.
+ * If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing
* an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}
* </p>
* <p>
* In case you use this FBO w/o the {@link GLFBODrawable} and intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
- * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()});
+ * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2ES3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()});
* </p>
* <p>Leaves the FBO unbound.</p>
- *
+ *
* @param gl the current GL context
* @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)}
- * @throws IllegalArgumentException
+ * @throws IllegalArgumentException
*/
- public final void syncFramebuffer(GL gl) {
+ public final void syncSamplingSink(final GL gl) {
markUnbound();
- if(samples>0 && samplesSinkDirty) {
- samplesSinkDirty = false;
- resetMSAATexture2DSink(gl);
- gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbName);
- gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplesSink.getWriteFramebuffer());
- ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, casting to GL2GL3 is OK
+ if(samples>0 && samplingSinkDirty) { // implies fullFBOSupport
+ samplingSinkDirty = false;
+ if( isModified() ) {
+ resetSamplingSink(gl);
+ }
+ final boolean checkError = DEBUG || GLContext.DEBUG_GL;
+ if( checkError ) {
+ checkPreGLError(gl);
+ }
+ gl.glBindFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER, fbName); // read from this MSAA fb
+ gl.glBindFramebuffer(GL2ES3.GL_DRAW_FRAMEBUFFER, samplingSink.getWriteFramebuffer()); // write to sampling sink
+ ((GL2ES3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, casting to GL2ES3 is OK
GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST);
+ if( checkError ) {
+ checkNoError(null, gl.glGetError(), "FBObject syncSampleSink"); // throws GLException if error
+ }
+ } else {
+ modified = false;
}
if(fullFBOSupport) {
- // default read/draw buffers, may utilize GLContext/GLDrawable override of
+ // default read/draw buffers, may utilize GLContext/GLDrawable override of
// GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer()
- gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0);
- gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0);
+ gl.glBindFramebuffer(GL2ES3.GL_DRAW_FRAMEBUFFER, 0);
+ gl.glBindFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER, 0);
} else {
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer
}
}
-
- /**
- * Bind the given texture colorbuffer.
- *
- * <p>If using multiple texture units, ensure you call {@link GL#glActiveTexture(int)} first!</p>
- *
- * <p>{@link #syncFramebuffer(GL)} is being called</p>
- *
+
+ /**
+ * {@link #syncSamplingSink(GL) Synchronize the sampling sink} and bind the given {@link TextureAttachment}, if not <code>null</code>.
+ *
+ * <p>If using a {@link TextureAttachment} and multiple texture units, ensure you call {@link GL#glActiveTexture(int)} first!</p>
+ *
+ * <p>{@link #syncSamplingSink(GL)} is being called</p>
+ *
* <p>Leaves the FBO unbound!</p>
- *
+ *
* @param gl the current GL context
- * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)}
- * @throws IllegalArgumentException
+ * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)},
+ * may be <code>null</code> in case no {@link TextureAttachment} is used.
+ * @throws IllegalArgumentException
*/
- public final void use(GL gl, TextureAttachment ta) throws IllegalArgumentException {
- if(null == ta) { throw new IllegalArgumentException("null TextureAttachment, this: "+toString()); }
- syncFramebuffer(gl);
- gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it ..
+ public final void use(final GL gl, final TextureAttachment ta) throws IllegalArgumentException {
+ syncSamplingSink(gl);
+ if( null != ta ) {
+ gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it ..
+ }
}
- /**
+ /**
* Unbind texture, ie bind 'non' texture 0
- *
+ *
* <p>Leaves the FBO unbound.</p>
- */
- public final void unuse(GL gl) {
+ */
+ public final void unuse(final GL gl) {
unbind(gl);
gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it
}
- /** @see GL#hasFullFBOSupport() */
+ /** @see GL#hasFullFBOSupport() */
public final boolean hasFullFBOSupport() throws GLException { checkInitialized(); return this.fullFBOSupport; }
-
- /**
+
+ /**
* Returns <code>true</code> if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise <code>false</code>.
* @throws GLException if {@link #init(GL)} hasn't been called.
*/
public final boolean supportsRGBA8() throws GLException { checkInitialized(); return rgba8Avail; }
-
- /**
+
+ /**
* Returns <code>true</code> if {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} is supported, otherwise <code>false</code>.
* @param bits 16, 24 or 32 bits
* @throws GLException if {@link #init(GL)} hasn't been called.
*/
- public final boolean supportsDepth(int bits) throws GLException {
+ public final boolean supportsDepth(final int bits) throws GLException {
checkInitialized();
switch(bits) {
- case 16: return true;
+ case 16: return true;
case 24: return depth24Avail;
case 32: return depth32Avail;
- default: return false;
+ default: return false;
}
}
-
- /**
+
+ /**
* Returns <code>true</code> if {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} or {@link GL2GL3#GL_STENCIL_INDEX16} is supported, otherwise <code>false</code>.
* @param bits 1, 4, 8 or 16 bits
* @throws GLException if {@link #init(GL)} hasn't been called.
*/
- public final boolean supportsStencil(int bits) throws GLException {
+ public final boolean supportsStencil(final int bits) throws GLException {
checkInitialized();
switch(bits) {
- case 1: return stencil01Avail;
+ case 1: return stencil01Avail;
case 4: return stencil04Avail;
case 8: return stencil08Avail;
case 16: return stencil16Avail;
- default: return false;
+ default: return false;
}
}
-
- /**
+
+ /**
* Returns <code>true</code> if {@link GL#GL_DEPTH24_STENCIL8} is supported, otherwise <code>false</code>.
* @throws GLException if {@link #init(GL)} hasn't been called.
*/
public final boolean supportsPackedDepthStencil() throws GLException { checkInitialized(); return packedDepthStencilAvail; }
-
+
/**
* Returns the maximum number of colorbuffer attachments.
* @throws GLException if {@link #init(GL)} hasn't been called.
*/
public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; }
-
+
public final int getMaxTextureSize() throws GLException { checkInitialized(); return this.maxTextureSize; }
public final int getMaxRenderbufferSize() throws GLException { checkInitialized(); return this.maxRenderbufferSize; }
-
+
/** @see GL#getMaxRenderbufferSamples() */
public final int getMaxSamples() throws GLException { checkInitialized(); return this.maxSamples; }
-
+
/**
- * Returns <code>true</code> if this instance has been initialized with {@link #reset(GL, int, int)}
- * or {@link #reset(GL, int, int, int)}, otherwise <code>false</code>
+ * Returns <code>true</code> if this instance has been initialized with {@link #reset(GL, int, int)}
+ * or {@link #reset(GL, int, int, int, boolean)}, otherwise <code>false</code>
*/
public final boolean isInitialized() { return initialized; }
/** Returns the width */
@@ -2131,41 +2719,60 @@ public class FBObject {
/** Returns the framebuffer name to render to. */
public final int getWriteFramebuffer() { return fbName; }
/** Returns the framebuffer name to read from. Depending on multisampling, this may be a different framebuffer. */
- public final int getReadFramebuffer() { return ( samples > 0 ) ? samplesSink.getReadFramebuffer() : fbName; }
- /** Return the number of color/texture attachments */
- public final int getColorAttachmentCount() { return colorAttachmentCount; }
- /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */
+ public final int getReadFramebuffer() {
+ return 0 < samples ? ( null != samplingSink ? samplingSink.getReadFramebuffer() : 0 ) : fbName;
+ }
+ public final int getDefaultReadBuffer() { return GL.GL_COLOR_ATTACHMENT0; }
+ /** Return the number of attached {@link Colorbuffer}s */
+ public final int getColorbufferCount() { return colorbufferCount; }
+ /** Return the number of attached {@link TextureAttachment}s */
+ public final int getTextureAttachmentCount() { return textureAttachmentCount; }
+ /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */
public final RenderAttachment getStencilAttachment() { return stencil; }
- /** Return the depth {@link RenderAttachment} attachment. Maybe share the same {@link Attachment#getName()} as {@link #getStencilAttachment()}, if packed depth-stencil is being used. */
+ /** Return the depth {@link RenderAttachment} attachment. Maybe share the same {@link Attachment#getName()} as {@link #getStencilAttachment()}, if packed depth-stencil is being used. */
public final RenderAttachment getDepthAttachment() { return depth; }
-
- /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */
- public final FBObject getSamplingSinkFBO() { return samplesSink; }
-
- /** Return the multisampling {@link TextureAttachment} sink, if using multisampling. */
- public final TextureAttachment getSamplingSink() { return samplesSinkTexture; }
- /**
- * Returns <code>true</code> if the multisampling colorbuffer (msaa-buffer)
+
+ /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */
+ public final FBObject getSamplingSinkFBO() { return samplingSink; }
+
+ /** Return the multisampling {@link Colorbuffer} sink, if using multisampling. */
+ public final Colorbuffer getSamplingSink() { return samplingColorSink; }
+
+ /**
+ * Returns <code>true</code> if the multisampling colorbuffer (msaa-buffer)
* has been flagged dirty by a previous call of {@link #bind(GL)},
* otherwise <code>false</code>.
*/
- public final boolean isSamplingBufferDirty() { return samplesSinkDirty; }
-
+ public final boolean isSamplingBufferDirty() { return samplingSinkDirty; }
+
+ /**
+ * Returns <code>true</code> if size, sample-count or any attachment of this instance
+ * or its {@link #getSamplingSink() sampling-sink} has been modified since last {@link #syncSamplingSink(GL) sync},
+ * {@link #use(GL, TextureAttachment) use}, {@link #reset(GL, int, int, int) reset}
+ * or {@link #resetSamplingSink(GL) resetSamplingSink}.
+ * <p>
+ * Otherwise method returns <code>false</code>.
+ * </p>
+ */
+ public final boolean isModified() { return modified || ( null != samplingSink && samplingSink.modified ); }
+
int objectHashCode() { return super.hashCode(); }
-
+
+ @Override
public final String toString() {
- final String caps = null != colorAttachmentPoints ? Arrays.asList(colorAttachmentPoints).toString() : null ;
- return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+", samples "+samples+"/"+maxSamples+
- ", depth "+depth+", stencil "+stencil+", color attachments: "+colorAttachmentCount+"/"+maxColorAttachments+
- ": "+caps+", msaa-sink "+samplesSinkTexture+", isSamplesSink "+(null == samplesSink)+
- ", obj 0x"+Integer.toHexString(objectHashCode())+"]";
- }
-
- private final void updateStatus(GL gl) {
+ final String caps = null != colorbufferAttachments ? Arrays.asList(colorbufferAttachments).toString() : null ;
+ return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+
+ ", samples "+samples+"/"+maxSamples+", modified "+modified+"/"+isModified()+", depth "+depth+", stencil "+stencil+
+ ", colorbuffer attachments: "+colorbufferCount+"/"+maxColorAttachments+", with "+textureAttachmentCount+" textures"+
+ ": "+caps+", msaa["+samplingColorSink+", hasSink "+(null != samplingSink)+
+ ", dirty "+samplingSinkDirty+"], state "+getStatusString()+", obj "+toHexString(objectHashCode())+"]";
+ }
+
+ private final void updateStatus(final GL gl) {
if( 0 == fbName ) {
vStatus = -1;
} else {
vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
}
- }
+ }
}
diff --git a/src/jogl/classes/com/jogamp/opengl/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/FloatUtil.java
deleted file mode 100644
index 93543eaf6..000000000
--- a/src/jogl/classes/com/jogamp/opengl/FloatUtil.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.opengl;
-
-import java.nio.FloatBuffer;
-
-/**
- * Basic Float math utility functions.
- * <p>
- * Implementation assumes linear matrix layout in column-major order
- * matching OpenGL's implementation.
- * </p>
- * <p>
- * Derived from ProjectFloat.java - Created 11-jan-2004
- * </p>
- *
- * @author Erik Duijs
- * @author Kenneth Russell
- * @author Sven Gothel
- */
-public class FloatUtil {
- private static final float[] IDENTITY_MATRIX =
- new float[] {
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f };
-
- private static final float[] ZERO_MATRIX =
- new float[] {
- 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f };
-
- /**
- * Make matrix an identity matrix
- */
- public static final void makeIdentityf(float[] m, int offset) {
- for (int i = 0; i < 16; i++) {
- m[i+offset] = IDENTITY_MATRIX[i];
- }
- }
-
- /**
- * Make matrix an identity matrix
- */
- public static final void makeIdentityf(FloatBuffer m) {
- int oldPos = m.position();
- m.put(IDENTITY_MATRIX);
- m.position(oldPos);
- }
-
- /**
- * Make matrix an zero matrix
- */
- public static final void makeZero(float[] m, int offset) {
- for (int i = 0; i < 16; i++) {
- m[i+offset] = 0;
- }
- }
-
- /**
- * Make matrix an zero matrix
- */
- public static final void makeZero(FloatBuffer m) {
- int oldPos = m.position();
- m.put(ZERO_MATRIX);
- m.position(oldPos);
- }
-
- /**
- * @param a 4x4 matrix in column-major order
- * @param b 4x4 matrix in column-major order
- * @param d result a*b in column-major order
- */
- public static final void multMatrixf(final float[] a, int a_off, final float[] b, int b_off, float[] d, int d_off) {
- for (int i = 0; i < 4; i++) {
- // one row in column-major order
- final float ai0=a[a_off+i+0*4], ai1=a[a_off+i+1*4], ai2=a[a_off+i+2*4], ai3=a[a_off+i+3*4]; // row-i of a
- d[d_off+i+0*4] = ai0 * b[b_off+0+0*4] + ai1 * b[b_off+1+0*4] + ai2 * b[b_off+2+0*4] + ai3 * b[b_off+3+0*4] ;
- d[d_off+i+1*4] = ai0 * b[b_off+0+1*4] + ai1 * b[b_off+1+1*4] + ai2 * b[b_off+2+1*4] + ai3 * b[b_off+3+1*4] ;
- d[d_off+i+2*4] = ai0 * b[b_off+0+2*4] + ai1 * b[b_off+1+2*4] + ai2 * b[b_off+2+2*4] + ai3 * b[b_off+3+2*4] ;
- d[d_off+i+3*4] = ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] ;
- }
- }
-
- /**
- * @param a 4x4 matrix in column-major order
- * @param b 4x4 matrix in column-major order
- * @param d result a*b in column-major order
- */
- public static final void multMatrixf(final float[] a, int a_off, final float[] b, int b_off, FloatBuffer d) {
- final int dP = d.position();
- for (int i = 0; i < 4; i++) {
- // one row in column-major order
- final float ai0=a[a_off+i+0*4], ai1=a[a_off+i+1*4], ai2=a[a_off+i+2*4], ai3=a[a_off+i+3*4]; // row-i of a
- d.put(dP+i+0*4 , ai0 * b[b_off+0+0*4] + ai1 * b[b_off+1+0*4] + ai2 * b[b_off+2+0*4] + ai3 * b[b_off+3+0*4] );
- d.put(dP+i+1*4 , ai0 * b[b_off+0+1*4] + ai1 * b[b_off+1+1*4] + ai2 * b[b_off+2+1*4] + ai3 * b[b_off+3+1*4] );
- d.put(dP+i+2*4 , ai0 * b[b_off+0+2*4] + ai1 * b[b_off+1+2*4] + ai2 * b[b_off+2+2*4] + ai3 * b[b_off+3+2*4] );
- d.put(dP+i+3*4 , ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] );
- }
- }
-
- /**
- * @param a 4x4 matrix in column-major order
- * @param b 4x4 matrix in column-major order
- * @param d result a*b in column-major order
- */
- public static final void multMatrixf(final FloatBuffer a, final float[] b, int b_off, FloatBuffer d) {
- final int aP = a.position();
- final int dP = d.position();
- for (int i = 0; i < 4; i++) {
- // one row in column-major order
- final float ai0=a.get(aP+i+0*4), ai1=a.get(aP+i+1*4), ai2=a.get(aP+i+2*4), ai3=a.get(aP+i+3*4); // row-i of a
- d.put(dP+i+0*4 , ai0 * b[b_off+0+0*4] + ai1 * b[b_off+1+0*4] + ai2 * b[b_off+2+0*4] + ai3 * b[b_off+3+0*4] );
- d.put(dP+i+1*4 , ai0 * b[b_off+0+1*4] + ai1 * b[b_off+1+1*4] + ai2 * b[b_off+2+1*4] + ai3 * b[b_off+3+1*4] );
- d.put(dP+i+2*4 , ai0 * b[b_off+0+2*4] + ai1 * b[b_off+1+2*4] + ai2 * b[b_off+2+2*4] + ai3 * b[b_off+3+2*4] );
- d.put(dP+i+3*4 , ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] );
- }
- }
-
- /**
- * @param a 4x4 matrix in column-major order
- * @param b 4x4 matrix in column-major order
- * @param d result a*b in column-major order
- */
- public static final void multMatrixf(final FloatBuffer a, final FloatBuffer b, FloatBuffer d) {
- final int aP = a.position();
- final int bP = b.position();
- final int dP = d.position();
- for (int i = 0; i < 4; i++) {
- // one row in column-major order
- final float ai0=a.get(aP+i+0*4), ai1=a.get(aP+i+1*4), ai2=a.get(aP+i+2*4), ai3=a.get(aP+i+3*4); // row-i of a
- d.put(dP+i+0*4 , ai0 * b.get(bP+0+0*4) + ai1 * b.get(bP+1+0*4) + ai2 * b.get(bP+2+0*4) + ai3 * b.get(bP+3+0*4) );
- d.put(dP+i+1*4 , ai0 * b.get(bP+0+1*4) + ai1 * b.get(bP+1+1*4) + ai2 * b.get(bP+2+1*4) + ai3 * b.get(bP+3+1*4) );
- d.put(dP+i+2*4 , ai0 * b.get(bP+0+2*4) + ai1 * b.get(bP+1+2*4) + ai2 * b.get(bP+2+2*4) + ai3 * b.get(bP+3+2*4) );
- d.put(dP+i+3*4 , ai0 * b.get(bP+0+3*4) + ai1 * b.get(bP+1+3*4) + ai2 * b.get(bP+2+3*4) + ai3 * b.get(bP+3+3*4) );
- }
- }
-
-
- /**
- * Normalize vector
- *
- * @param v makes len(v)==1
- */
- public static final void normalize(float[] v) {
- float r = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
-
- if ( r == 0.0 || r == 1.0) {
- return;
- }
-
- r = 1.0f / r;
-
- v[0] *= r;
- v[1] *= r;
- v[2] *= r;
- }
-
- /**
- * Normalize vector
- *
- * @param v makes len(v)==1
- */
- public static final void normalize(FloatBuffer v) {
- final int vPos = v.position();
-
- float r = (float) Math.sqrt(v.get(0+vPos) * v.get(0+vPos) +
- v.get(1+vPos) * v.get(1+vPos) +
- v.get(2+vPos) * v.get(2+vPos));
-
- if ( r == 0.0 || r == 1.0) {
- return;
- }
-
- r = 1.0f / r;
-
- v.put(0+vPos, v.get(0+vPos) * r);
- v.put(1+vPos, v.get(1+vPos) * r);
- v.put(2+vPos, v.get(2+vPos) * r);
- }
-
-
- /**
- * Calculate cross-product of 2 vector
- *
- * @param v1 3-component vector
- * @param v2 3-component vector
- * @param result v1 X v2
- */
- public static final void cross(float[] v1, float[] v2, float[] result) {
- result[0] = v1[1] * v2[2] - v1[2] * v2[1];
- result[1] = v1[2] * v2[0] - v1[0] * v2[2];
- result[2] = v1[0] * v2[1] - v1[1] * v2[0];
- }
-
- /**
- * Calculate cross-product of 2 vector
- *
- * @param v1 3-component vector
- * @param v2 3-component vector
- * @param result v1 X v2
- */
- public static final void cross(FloatBuffer v1, FloatBuffer v2, FloatBuffer result) {
- final int v1Pos = v1.position();
- final int v2Pos = v2.position();
- final int rPos = result.position();
-
- result.put(0+rPos, v1.get(1+v1Pos) * v2.get(2+v2Pos) - v1.get(2+v1Pos) * v2.get(1+v2Pos));
- result.put(1+rPos, v1.get(2+v1Pos) * v2.get(0+v2Pos) - v1.get(0+v1Pos) * v2.get(2+v2Pos));
- result.put(2+rPos, v1.get(0+v1Pos) * v2.get(1+v2Pos) - v1.get(1+v1Pos) * v2.get(0+v2Pos));
- }
-
- /**
- * @param m_in 4x4 matrix in column-major order
- * @param m_in_off
- * @param v_in 4-component column-vector
- * @param v_out m_in * v_in
- */
- public static final void multMatrixVecf(float[] m_in, int m_in_off, float[] v_in, int v_in_off, float[] v_out) {
- for (int i = 0; i < 4; i++) {
- // (one matrix row in column-major order) X (column vector)
- v_out[i] =
- v_in[0+v_in_off] * m_in[0*4+i+m_in_off] +
- v_in[1+v_in_off] * m_in[1*4+i+m_in_off] +
- v_in[2+v_in_off] * m_in[2*4+i+m_in_off] +
- v_in[3+v_in_off] * m_in[3*4+i+m_in_off];
- }
- }
-
- /**
- * @param m_in 4x4 matrix in column-major order
- * @param m_in_off
- * @param v_in 4-component column-vector
- * @param v_out m_in * v_in
- */
- public static final void multMatrixVecf(float[] m_in, float[] v_in, float[] v_out) {
- for (int i = 0; i < 4; i++) {
- // (one matrix row in column-major order) X (column vector)
- v_out[i] =
- v_in[0] * m_in[0*4+i] +
- v_in[1] * m_in[1*4+i] +
- v_in[2] * m_in[2*4+i] +
- v_in[3] * m_in[3*4+i];
- }
- }
-
- /**
- * @param m_in 4x4 matrix in column-major order
- * @param v_in 4-component column-vector
- * @param v_out m_in * v_in
- */
- public static final void multMatrixVecf(FloatBuffer m_in, FloatBuffer v_in, FloatBuffer v_out) {
- int inPos = v_in.position();
- int outPos = v_out.position();
- int matrixPos = m_in.position();
- for (int i = 0; i < 4; i++) {
- // (one matrix row in column-major order) X (column vector)
- v_out.put(i + outPos,
- v_in.get(0+inPos) * m_in.get(0*4+i+matrixPos) +
- v_in.get(1+inPos) * m_in.get(1*4+i+matrixPos) +
- v_in.get(2+inPos) * m_in.get(2*4+i+matrixPos) +
- v_in.get(3+inPos) * m_in.get(3*4+i+matrixPos));
- }
- }
-
-} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
index 38a8deef8..b9f1fb10c 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -36,7 +36,9 @@ import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLSharedContextSetter;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
@@ -48,24 +50,40 @@ import jogamp.opengl.GLDrawableImpl;
/**
* Fully functional {@link GLAutoDrawable} implementation
- * utilizing already created created {@link GLDrawable} and {@link GLContext} instances.
+ * utilizing already created {@link GLDrawable} and {@link GLContext} instances.
* <p>
* Since no native windowing system events are being processed, it is recommended
- * to handle at least:
+ * to handle at least the {@link com.jogamp.newt.event.WindowEvent window events}:
* <ul>
* <li>{@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint} using {@link #windowRepaintOp()}</li>
* <li>{@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize} using {@link #windowResizedOp()}</li>
- * <li>{@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify} using {@link #windowDestroyNotifyOp()}</li>
- * </ul>
+ * </ul>
+ * and setup a {@link com.jogamp.newt.Window#setWindowDestroyNotifyAction(Runnable) custom toolkit destruction} issuing {@link #windowDestroyNotifyOp()}.
* </p>
- * <p>
+ * <p>
* See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}.
* </p>
+ * <p>
+ * <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a>
+ * To share a {@link GLContext} see the following note in the documentation overview:
+ * <a href="../../../overview-summary.html#SHARING">context sharing</a>
+ * as well as {@link GLSharedContextSetter}.
+ * </p>
*/
public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAutoDrawable {
/**
- * @param drawable a valid and already realized {@link GLDrawable}
- * @param context a valid {@link GLContext}, may not be made current (created) yet.
+ * <p>
+ * The {@link GLContext} can be assigned later manually via {@link GLAutoDrawable#setContext(GLContext, boolean) setContext(ctx)}
+ * <i>or</i> it will be created <i>lazily</i> at the 1st {@link GLAutoDrawable#display() display()} method call.<br>
+ * <i>Lazy</i> {@link GLContext} creation will take a shared {@link GLContext} into account
+ * which has been set {@link #setSharedContext(GLContext) directly}
+ * or {@link #setSharedAutoDrawable(GLAutoDrawable) via another GLAutoDrawable}.
+ * </p>
+ * @param drawable a valid {@link GLDrawable}, may not be {@link GLDrawable#isRealized() realized} yet.
+ * @param context a valid {@link GLContext},
+ * may not have been made current (created) yet,
+ * may not be associated w/ <code>drawable<code> yet,
+ * may be <code>null</code> for lazy initialization at 1st {@link #display()}.
* @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
* @param ownDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
* otherwise pass <code>false</code>. Closing the device is required in case
@@ -73,21 +91,15 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAuto
* and no further lifecycle handling is applied.
* @param lock optional custom {@link RecursiveLock}.
*/
- public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice, RecursiveLock lock) {
+ public GLAutoDrawableDelegate(final GLDrawable drawable, final GLContext context, final Object upstreamWidget, final boolean ownDevice, final RecursiveLock lock) {
super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice);
if(null == drawable) {
throw new IllegalArgumentException("null drawable");
}
- if(null == context) {
- throw new IllegalArgumentException("null context");
- }
- if(!drawable.isRealized()) {
- throw new IllegalArgumentException("drawable not realized");
- }
this.upstreamWidget = upstreamWidget;
this.lock = ( null != lock ) ? lock : LockFactory.createRecursiveLock() ;
}
-
+
//
// expose default methods
//
@@ -96,48 +108,63 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAuto
public final void windowRepaintOp() {
super.defaultWindowRepaintOp();
}
-
- /** Implementation to handle resize events from the windowing system. All required locks are being claimed. */
- public final void windowResizedOp(int newWidth, int newHeight) {
+
+ /**
+ * Handling resize events from the windowing system.
+ * <p>
+ * Implementation:
+ * <ul>
+ * <li>resizes {@link #getDelegatedDrawable() the GLDrawable}, if offscreen,</li>
+ * <li>triggers a pending {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape events}, and</li>
+ * <li>issues a {@link #display()} call, if no animator is present.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * All required locks are being claimed.
+ * </p>
+ * @param newWidth new width in pixel units
+ * @param newWidth new height in pixel units
+ */
+ public final void windowResizedOp(final int newWidth, final int newHeight) {
super.defaultWindowResizedOp(newWidth, newHeight);
}
-
- /**
+
+ /**
* Implementation to handle destroy notifications from the windowing system.
- *
+ *
* <p>
- * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol}
+ * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol}
* or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default),
* a thread safe destruction is being induced.
- * </p>
+ * </p>
*/
public final void windowDestroyNotifyOp() {
super.defaultWindowDestroyNotifyOp();
}
-
+
//
// Complete GLAutoDrawable
//
-
+
private Object upstreamWidget;
private final RecursiveLock lock;
-
+
@Override
- protected final RecursiveLock getLock() { return lock; }
-
+ public final RecursiveLock getUpstreamLock() { return lock; }
+
@Override
public final Object getUpstreamWidget() {
return upstreamWidget;
}
-
+
/**
* Set the upstream UI toolkit object.
* @see #getUpstreamWidget()
*/
- public final void setUpstreamWidget(Object newUpstreamWidget) {
+ public final void setUpstreamWidget(final Object newUpstreamWidget) {
upstreamWidget = newUpstreamWidget;
}
-
+
/**
* {@inheritDoc}
* <p>
@@ -145,7 +172,7 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAuto
* </p>
* <p>
* User still needs to destroy the upstream window, which details are hidden from this aspect.
- * This can be performed by overriding {@link #destroyImplInLock()}.
+ * This can be performed by overriding {@link #destroyImplInLock()}.
* </p>
*/
@Override
@@ -157,33 +184,29 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAuto
protected void destroyImplInLock() {
super.destroyImplInLock();
}
-
+
@Override
- public void display() {
+ public void display() {
defaultDisplay();
}
-
+
//
// GLDrawable delegation
//
-
+
@Override
public final GLDrawableFactory getFactory() {
return drawable.getFactory();
}
-
- @Override
- public final void setRealized(boolean realized) {
- }
@Override
public final void swapBuffers() throws GLException {
defaultSwapBuffers();
}
-
+
@Override
public String toString() {
return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable +
", \n\tContext: " + context + ", \n\tUpstreamWidget: "+upstreamWidget+ /** ", \n\tFactory: "+factory+ */ "]";
- }
+ }
}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java b/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java
new file mode 100644
index 000000000..bfd5fe115
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java
@@ -0,0 +1,552 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.DefaultGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLRunnable;
+
+import jogamp.opengl.Debug;
+
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+import com.jogamp.opengl.util.GLDrawableUtil;
+
+/**
+ * GLEventListenerState is holding {@link GLAutoDrawable} components crucial
+ * to relocating all its {@link GLEventListener} w/ their operating {@link GLContext}, etc.
+ * The components are:
+ * <ul>
+ * <li>{@link GLContext}</li>
+ * <li>All {@link GLEventListener}, incl. their init state</li>
+ * <li>{@link GLAnimatorControl}</li>
+ * <!--li>{@link GLCapabilitiesImmutable} for compatibility check</li-->
+ * <li>{@link AbstractGraphicsDevice} for compatibility check and preserving the native device handle incl. ownership</li>
+ * </ul>
+ * <p>
+ * A GLEventListenerState instance can be created while components are {@link #moveFrom(GLAutoDrawable) moved from} a {@link GLAutoDrawable}
+ * to the new instance, which gains {@link #isOwner() ownership} of the moved components.
+ * </p>
+ * <p>
+ * A GLEventListenerState instance's components can be {@link #moveTo(GLAutoDrawable) moved to} a {@link GLAutoDrawable},
+ * while loosing {@link #isOwner() ownership} of the moved components.
+ * </p>
+ */
+public class GLEventListenerState {
+ private static final boolean DEBUG = Debug.debug("GLDrawable") || Debug.debug("GLEventListenerState");
+
+ private GLEventListenerState(final AbstractGraphicsDevice upstreamDevice, final boolean proxyOwnsUpstreamDevice, final AbstractGraphicsDevice device,
+ final GLCapabilitiesImmutable caps,
+ final RecursiveLock upstreamLock, final NativeSurface lockedSurface,
+ final GLContext context, final int count, final GLAnimatorControl anim, final boolean animStarted) {
+ this.upstreamDevice = upstreamDevice;
+ this.proxyOwnsUpstreamDevice = proxyOwnsUpstreamDevice;
+ this.device = device;
+ this.caps = caps;
+ this.upstreamLock = upstreamLock;
+ this.lockedSurface = lockedSurface;
+ this.context = context;
+ this.listeners = new GLEventListener[count];
+ this.listenersInit = new boolean[count];
+ this.anim = anim;
+ this.animStarted = animStarted;
+
+ this.owner = true;
+ }
+ /**
+ * Returns <code>true</code>, if this instance is the current owner of the components,
+ * otherwise <code>false</code>.
+ * <p>
+ * Ownership is lost if {@link #moveTo(GLAutoDrawable)} is being called successfully
+ * and all components are transferred to the new {@link GLAutoDrawable}.
+ * </p>
+ */
+ public final boolean isOwner() { return owner; }
+
+ public final int listenerCount() { return listeners.length; }
+
+ public final AbstractGraphicsDevice upstreamDevice;
+ public final boolean proxyOwnsUpstreamDevice;
+ public final AbstractGraphicsDevice device;
+ public final GLCapabilitiesImmutable caps;
+ public final GLContext context;
+ public final GLEventListener[] listeners;
+ public final boolean[] listenersInit;
+ public final GLAnimatorControl anim;
+ public final boolean animStarted;
+
+ private volatile RecursiveLock upstreamLock;
+ private volatile NativeSurface lockedSurface;
+ private volatile boolean owner;
+
+ /**
+ * Returns a {@link Runnable} {@link NativeSurface#unlockSurface() unlocking} an eventually locked {@link NativeSurface},
+ * see {@link #moveFrom(GLAutoDrawable, boolean)} and {@link #moveTo(GLAutoDrawable, Runnable)}.
+ */
+ public Runnable getUnlockSurfaceOp() { return unlockOp; }
+
+ private final Runnable unlockOp = new Runnable() {
+ public void run() {
+ final RecursiveLock rl = upstreamLock;
+ final NativeSurface ls = lockedSurface;
+ upstreamLock = null;
+ lockedSurface = null;
+ if( null != rl ) {
+ rl.unlock();
+ }
+ if( null != ls ) {
+ ls.unlockSurface();
+ }
+ } };
+
+ /**
+ * Last resort to destroy and loose ownership
+ */
+ public void destroy() {
+ if( owner ) {
+ final int aSz = listenerCount();
+ for(int i=0; i<aSz; i++) {
+ listeners[i] = null;
+ }
+ // context.destroy(); - NPE (null drawable)
+ unlockOp.run();
+ device.close();
+ owner = false;
+ }
+ }
+
+ private static AbstractGraphicsDevice cloneDevice(final AbstractGraphicsDevice aDevice) {
+ return (AbstractGraphicsDevice) aDevice.clone();
+ }
+
+ /**
+ * Moves all GLEventListenerState components from the given {@link GLAutoDrawable}
+ * to a newly created instance.
+ * <p>
+ * Note that all components are removed from the {@link GLAutoDrawable},
+ * i.e. the {@link GLContext}, all {@link GLEventListener}.
+ * </p>
+ * <p>
+ * If the {@link GLAutoDrawable} was added to a {@link GLAnimatorControl}, it is removed
+ * and the {@link GLAnimatorControl} added to the GLEventListenerState.
+ * </p>
+ * <p>
+ * The returned GLEventListenerState instance is the {@link #isOwner() owner of the components}.
+ * </p>
+ * <p>
+ * Locking is performed on the {@link GLAutoDrawable auto-drawable's}
+ * {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface}.
+ * See <a href="../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * </p>
+ *
+ * @param src {@link GLAutoDrawable} source to move components from
+ * @return new GLEventListenerState instance {@link #isOwner() owning} moved components.
+ *
+ * @see #moveTo(GLAutoDrawable)
+ */
+ public static GLEventListenerState moveFrom(final GLAutoDrawable src) {
+ return GLEventListenerState.moveFrom(src, false);
+ }
+
+ /**
+ * Moves all GLEventListenerState components from the given {@link GLAutoDrawable}
+ * to a newly created instance.
+ * <p>
+ * Note that all components are removed from the {@link GLAutoDrawable},
+ * i.e. the {@link GLContext}, all {@link GLEventListener}.
+ * </p>
+ * <p>
+ * If the {@link GLAutoDrawable} was added to a {@link GLAnimatorControl}, it is removed
+ * and the {@link GLAnimatorControl} added to the GLEventListenerState.
+ * </p>
+ * <p>
+ * The returned GLEventListenerState instance is the {@link #isOwner() owner of the components}.
+ * </p>
+ * <p>
+ * Locking is performed on the {@link GLAutoDrawable auto-drawable's}
+ * {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface},
+ * which is <i>not released</i> if <code>keepLocked</code> is <code>true</code>.
+ * See <a href="../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * </p>
+ * <p>
+ * <code>keepLocked</code> may be utilized if swapping a context between drawables
+ * and to ensure atomicity of operation.
+ * Here, the {@link #getUnlockSurfaceOp()} shall be passed to {@link #moveTo(GLAutoDrawable, Runnable)}.
+ * See {@link GLDrawableUtil#swapGLContextAndAllGLEventListener(GLAutoDrawable, GLAutoDrawable)}.
+ * </p>
+ *
+ * @param src {@link GLAutoDrawable} source to move components from
+ * @param keepLocked keep {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface} locked, see above
+ * @return new GLEventListenerState instance {@link #isOwner() owning} moved components.
+ *
+ * @see #moveTo(GLAutoDrawable, Runnable)
+ */
+ public static GLEventListenerState moveFrom(final GLAutoDrawable src, final boolean keepLocked) {
+ final GLAnimatorControl srcAnim = src.getAnimator();
+ final boolean srcAnimStarted;
+ if( null != srcAnim ) {
+ srcAnimStarted = srcAnim.isStarted();
+ srcAnim.remove(src); // also handles ECT
+ } else {
+ srcAnimStarted = false;
+ }
+
+ final GLEventListenerState glls;
+ final RecursiveLock srcUpstreamLock = src.getUpstreamLock();
+ srcUpstreamLock.lock();
+ try {
+ final NativeSurface srcSurface = src.getNativeSurface();
+ final boolean srcSurfaceLocked = NativeSurface.LOCK_SURFACE_NOT_READY < srcSurface.lockSurface();
+ if( src.isRealized() && !srcSurfaceLocked ) {
+ throw new GLException("Could not lock realized surface "+src);
+ }
+
+ try {
+ final int aSz = src.getGLEventListenerCount();
+
+ // Create new AbstractGraphicsScreen w/ cloned AbstractGraphicsDevice for future GLAutoDrawable
+ // allowing this AbstractGraphicsDevice to loose ownership -> not closing display/device!
+ final AbstractGraphicsConfiguration aCfg = srcSurface.getGraphicsConfiguration();
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities();
+ final AbstractGraphicsDevice aDevice1 = aCfg.getScreen().getDevice();
+ final AbstractGraphicsDevice aDevice2 = cloneDevice(aDevice1);
+ aDevice1.clearHandleOwner(); // don't close device handle
+ if( DEBUG ) {
+ System.err.println("GLEventListenerState.moveFrom.0a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1);
+ System.err.println("GLEventListenerState.moveFrom.0b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2);
+ System.err.println("GLEventListenerState.moveFrom.1: "+srcSurface.getClass().getName()/*+", "+aSurface*/);
+ }
+ final AbstractGraphicsDevice aUpDevice2;
+ final boolean proxyOwnsUpstreamDevice;
+ {
+ AbstractGraphicsDevice _aUpDevice2 = null;
+ if(srcSurface instanceof ProxySurface) {
+ final ProxySurface aProxy = (ProxySurface)srcSurface;
+ proxyOwnsUpstreamDevice = aProxy.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ final NativeSurface aUpSurface = aProxy.getUpstreamSurface();
+ if(DEBUG && null != aUpSurface) {
+ System.err.println("GLEventListenerState.moveFrom.2: "+aUpSurface.getClass().getName()+", "+aUpSurface);
+ }
+ if(null != aUpSurface) {
+ final AbstractGraphicsDevice aUpDevice1 = aUpSurface.getGraphicsConfiguration().getScreen().getDevice();
+ _aUpDevice2 = cloneDevice(aUpDevice1);
+ aUpDevice1.clearHandleOwner(); // don't close device handle
+ if(DEBUG) {
+ System.err.println("GLEventListenerState.moveFrom.3a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1);
+ System.err.println("GLEventListenerState.moveFrom.3b: up-pres 0x"+Integer.toHexString(_aUpDevice2.hashCode())+", "+_aUpDevice2);
+ System.err.println("GLEventListenerState.moveFrom.3c: "+srcSurface.getClass().getName()+", "+srcSurface);
+ System.err.println("GLEventListenerState.moveFrom.3d: "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString());
+ }
+ }
+ } else {
+ proxyOwnsUpstreamDevice = false;
+ }
+ aUpDevice2 = _aUpDevice2;
+ }
+
+ glls = new GLEventListenerState(aUpDevice2, proxyOwnsUpstreamDevice, aDevice2, caps,
+ keepLocked ? srcUpstreamLock : null,
+ srcSurfaceLocked && keepLocked ? srcSurface : null,
+ src.getContext(), aSz, srcAnim, srcAnimStarted);
+
+ //
+ // remove and cache all GLEventListener and their init-state
+ //
+ for(int i=0; i<aSz; i++) {
+ final GLEventListener l = src.getGLEventListener(0);
+ glls.listenersInit[i] = src.getGLEventListenerInitState(l);
+ glls.listeners[i] = src.removeGLEventListener( l );
+ }
+
+ src.setContext( null, false ); // implicit glFinish() ctx/drawable sync
+
+ } finally {
+ if( srcSurfaceLocked && !keepLocked ) {
+ srcSurface.unlockSurface();
+ }
+ }
+ } finally {
+ if( !keepLocked ) {
+ srcUpstreamLock.unlock();
+ }
+ }
+ return glls;
+ }
+
+ /**
+ * Moves all GLEventListenerState components to the given {@link GLAutoDrawable}
+ * from this instance, while loosing {@link #isOwner() ownership}.
+ * <p>
+ * If the previous {@link GLAutoDrawable} was removed from a {@link GLAnimatorControl} by previous {@link #moveFrom(GLAutoDrawable)},
+ * the given {@link GLAutoDrawable} is added to the cached {@link GLAnimatorControl}.
+ * This operation is skipped, if the given {@link GLAutoDrawable} is already added to a {@link GLAnimatorControl} instance.
+ * </p>
+ * <p>
+ * Locking is performed on the {@link GLAutoDrawable auto-drawable's}
+ * {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface}.
+ * See <a href="../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * </p>
+ * <p>
+ * Note: After this operation, the GLEventListenerState reference should be released.
+ * </p>
+ *
+ * @param dest {@link GLAutoDrawable} destination to move GLEventListenerState components to
+ *
+ * @throws GLException if a realized surface could not be locked.
+ * @throws GLException if this preserved {@link AbstractGraphicsDevice} is incompatible w/ the given destination one.
+ * <!-- @throws GLException if the {@link GLAutoDrawable}'s configuration is incompatible, i.e. different {@link GLCapabilitiesImmutable}. -->
+ *
+ * @see #moveFrom(GLAutoDrawable)
+ * @see #isOwner()
+ */
+ public final void moveTo(final GLAutoDrawable dest) throws GLException {
+ this.moveTo(dest, null);
+ }
+
+ /**
+ * Moves all GLEventListenerState components to the given {@link GLAutoDrawable}
+ * from this instance, while loosing {@link #isOwner() ownership}.
+ * <p>
+ * If the previous {@link GLAutoDrawable} was removed from a {@link GLAnimatorControl} by previous {@link #moveFrom(GLAutoDrawable, boolean)},
+ * the given {@link GLAutoDrawable} is added to the cached {@link GLAnimatorControl}.
+ * This operation is skipped, if the given {@link GLAutoDrawable} is already added to a {@link GLAnimatorControl} instance.
+ * </p>
+ * <p>
+ * Locking is performed on the {@link GLAutoDrawable auto-drawable's}
+ * {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface}.
+ * See <a href="../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * </p>
+ * <p>
+ * If the {@link GLAutoDrawable} <code>dest</code> has been kept locked by {@link #moveFrom(GLAutoDrawable, boolean)},
+ * it's {@link #getUnlockSurfaceOp()} shall be passed here to <code>destUnlockOperation</code> to be unlocked.
+ * </p>
+ * <p>
+ * Note: After this operation, the GLEventListenerState reference should be released.
+ * </p>
+ *
+ * @param dest {@link GLAutoDrawable} destination to move GLEventListenerState components to
+ * @param destUnlockOperation optional unlock operation for <code>dest</code>, see {@link #moveFrom(GLAutoDrawable, boolean)}.
+ *
+ * @throws GLException if a realized surface could not be locked.
+ * @throws GLException if this preserved {@link AbstractGraphicsDevice} is incompatible w/ the given destination one.
+ * <!-- @throws GLException if the {@link GLAutoDrawable}'s configuration is incompatible, i.e. different {@link GLCapabilitiesImmutable}. -->
+ *
+ * @see #moveFrom(GLAutoDrawable, boolean)
+ * @see #isOwner()
+ */
+ public final void moveTo(final GLAutoDrawable dest, final Runnable destUnlockOperation) throws GLException {
+ final GLAnimatorControl destAnim = dest.getAnimator();
+ final boolean destAnimPaused;
+ if( null != destAnim ) {
+ destAnimPaused = destAnim.pause();
+ destAnim.remove(dest); // also handles ECT
+ } else {
+ destAnimPaused = false;
+ }
+
+ final List<GLRunnable> aGLCmds = new ArrayList<GLRunnable>();
+ final int aSz = listenerCount();
+
+ final RecursiveLock destUpstreamLock = dest.getUpstreamLock();
+ destUpstreamLock.lock();
+ final boolean destIsRealized;
+ try {
+ final NativeSurface destSurface = dest.getNativeSurface();
+ final boolean destSurfaceLocked = NativeSurface.LOCK_SURFACE_NOT_READY < destSurface.lockSurface();
+ if( dest.isRealized() && !destSurfaceLocked ) {
+ throw new GLException("Could not lock realized surface "+dest);
+ }
+ try {
+
+ final MutableGraphicsConfiguration aCfg = (MutableGraphicsConfiguration) destSurface.getGraphicsConfiguration();
+ /**
+ final GLCapabilitiesImmutable aCaps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities();
+ if( caps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) != aCaps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) ||
+ caps.getVisualID(VisualIDHolder.VIDType.NATIVE) != aCaps.getVisualID(VisualIDHolder.VIDType.NATIVE) ) {
+ throw new GLException("Incompatible Capabilities - Prev-Holder: "+caps+", New-Holder "+caps);
+ } */
+ final DefaultGraphicsDevice aDevice1 = (DefaultGraphicsDevice) aCfg.getScreen().getDevice();
+ final DefaultGraphicsDevice aDevice2 = (DefaultGraphicsDevice) device;
+ if( !aDevice1.getUniqueID().equals( aDevice2.getUniqueID() ) ) {
+ throw new GLException("Incompatible devices: Preserved <"+aDevice2.getUniqueID()+">, target <"+aDevice1.getUniqueID()+">");
+ }
+
+ // collect optional upstream surface info
+ final ProxySurface aProxy;
+ final NativeSurface aUpSurface;
+ if(destSurface instanceof ProxySurface) {
+ aProxy = (ProxySurface)destSurface;
+ aUpSurface = aProxy.getUpstreamSurface();
+ } else {
+ aProxy = null;
+ aUpSurface = null;
+ }
+ if( DEBUG ) {
+ System.err.println("GLEventListenerState.moveTo.0 : has aProxy "+(null!=aProxy));
+ System.err.println("GLEventListenerState.moveTo.0 : has aUpSurface "+(null!=aUpSurface));
+ }
+ if( null==aUpSurface && null != upstreamDevice ) {
+ throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = true, New-Holder = false");
+ }
+
+ // Destroy and remove currently associated GLContext, if any (will be replaced)
+ dest.setContext( null, true );
+ destIsRealized = dest.isRealized();
+ if( destIsRealized && null != aUpSurface ) {
+ // Unrealize due to device dependencies of an upstream surface, e.g. EGLUpstreamSurfaceHook
+ dest.getDelegatedDrawable().setRealized(false);
+ }
+
+ // Set new Screen and close previous one
+ {
+ if( DEBUG ) {
+ System.err.println("GLEventListenerState.moveTo.0a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1);
+ System.err.println("GLEventListenerState.moveTo.0b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2);
+ }
+ DefaultGraphicsDevice.swapDeviceHandleAndOwnership(aDevice1, aDevice2);
+ aDevice2.close();
+ if( DEBUG ) {
+ System.err.println("GLEventListenerState.moveTo.1a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1);
+ System.err.println("GLEventListenerState.moveTo.1b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2);
+ }
+ }
+
+ // If using a ProxySurface w/ an upstream surface, set new Screen and close previous one on it
+ if( null != aUpSurface ) {
+ final MutableGraphicsConfiguration aUpCfg = (MutableGraphicsConfiguration) aUpSurface.getGraphicsConfiguration();
+ if( null != upstreamDevice ) {
+ final DefaultGraphicsDevice aUpDevice1 = (DefaultGraphicsDevice) aUpCfg.getScreen().getDevice();
+ final DefaultGraphicsDevice aUpDevice2 = (DefaultGraphicsDevice)upstreamDevice;
+ if( !aUpDevice1.getUniqueID().equals( aUpDevice2.getUniqueID() ) ) {
+ throw new GLException("Incompatible updtream devices: Preserved <"+aUpDevice2.getUniqueID()+">, target <"+aUpDevice1.getUniqueID()+">");
+ }
+ if( DEBUG ) {
+ System.err.println("GLEventListenerState.moveTo.2a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1);
+ System.err.println("GLEventListenerState.moveTo.2b: up-pres 0x"+Integer.toHexString(aUpDevice2.hashCode())+", "+aUpDevice2);
+ System.err.println("GLEventListenerState.moveTo.2c: "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString());
+ }
+ DefaultGraphicsDevice.swapDeviceHandleAndOwnership(aUpDevice1, aUpDevice2);
+ aUpDevice2.close();
+ if( proxyOwnsUpstreamDevice ) {
+ aProxy.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ if( DEBUG ) {
+ System.err.println("GLEventListenerState.moveTo.3a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1);
+ System.err.println("GLEventListenerState.moveTo.3b: up-pres 0x"+Integer.toHexString(aUpDevice2.hashCode())+", "+aUpDevice2);
+ System.err.println("GLEventListenerState.moveTo.3c: "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString());
+ }
+ } else {
+ throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = false, New-Holder = true");
+ }
+ }
+
+ if( destIsRealized && null != aUpSurface ) {
+ dest.getDelegatedDrawable().setRealized(true);
+ }
+ if( DEBUG ) {
+ System.err.println("GLEventListenerState.moveTo.X : has aProxy "+(null!=aProxy));
+ System.err.println("GLEventListenerState.moveTo.X : has aUpSurface "+(null!=aUpSurface));
+ }
+ dest.setContext( context, false );
+ } finally {
+ if( destSurfaceLocked ) {
+ destSurface.unlockSurface();
+ }
+ }
+ } finally {
+ destUpstreamLock.unlock();
+ }
+ if( null != destUnlockOperation ) {
+ destUnlockOperation.run();
+ }
+
+ owner = false;
+
+ //
+ // Trigger GL-Viewport reset and reshape of all initialized GLEventListeners
+ //
+ aGLCmds.add(setViewport);
+ for(int i=0; i<aSz; i++) {
+ if( listenersInit[i] ) {
+ aGLCmds.add(new GLDrawableUtil.ReshapeGLEventListener( listeners[i], false ) );
+ }
+ }
+ aGLCmds.add(glFinish);
+ dest.invoke(destIsRealized, aGLCmds); // only wait if already realized
+
+ // add all cached GLEventListener to their destination and fix their init-state
+ for(int i=0; i<aSz; i++) {
+ final GLEventListener l = listeners[i];
+ dest.addGLEventListener( l );
+ dest.setGLEventListenerInitState(l, listenersInit[i]);
+ listeners[i] = null;
+ }
+
+ if( null != destAnim ) {
+ // prefer already bound animator
+ destAnim.add(dest);
+ if( destAnimPaused ) {
+ destAnim.resume();
+ }
+ } else if ( null != anim ) {
+ // use previously bound animator
+ anim.add(dest); // also handles ECT
+ if(animStarted) {
+ anim.start();
+ }
+ }
+ }
+
+ private static final GLRunnable setViewport = new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ drawable.getGL().glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ return true;
+ }
+ };
+
+ private static final GLRunnable glFinish = new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ drawable.getGL().glFinish();
+ return true;
+ }
+ };
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
index cf81b85ee..1593da25c 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
@@ -28,17 +28,17 @@
package com.jogamp.opengl;
/**
- * Class holding OpenGL extension strings, commonly used by JOGL's implementation.
+ * Class holding OpenGL extension strings, commonly used by JOGL's implementation.
*/
public class GLExtensions {
public static final String VERSION_1_2 = "GL_VERSION_1_2";
public static final String VERSION_1_4 = "GL_VERSION_1_4";
public static final String VERSION_1_5 = "GL_VERSION_1_5";
public static final String VERSION_2_0 = "GL_VERSION_2_0";
-
+
public static final String ARB_debug_output = "GL_ARB_debug_output";
public static final String AMD_debug_output = "GL_AMD_debug_output";
-
+
public static final String ARB_framebuffer_object = "GL_ARB_framebuffer_object";
public static final String OES_framebuffer_object = "GL_OES_framebuffer_object";
public static final String EXT_framebuffer_object = "GL_EXT_framebuffer_object";
@@ -49,16 +49,17 @@ public class GLExtensions {
public static final String OES_depth32 = "GL_OES_depth32";
public static final String OES_packed_depth_stencil = "GL_OES_packed_depth_stencil";
public static final String NV_fbo_color_attachments = "GL_NV_fbo_color_attachments";
-
+
public static final String ARB_ES2_compatibility = "GL_ARB_ES2_compatibility";
-
+ public static final String ARB_ES3_compatibility = "GL_ARB_ES3_compatibility";
+
public static final String EXT_abgr = "GL_EXT_abgr";
public static final String OES_rgb8_rgba8 = "GL_OES_rgb8_rgba8";
public static final String OES_stencil1 = "GL_OES_stencil1";
public static final String OES_stencil4 = "GL_OES_stencil4";
public static final String OES_stencil8 = "GL_OES_stencil8";
public static final String APPLE_float_pixels = "GL_APPLE_float_pixels";
-
+
public static final String ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
public static final String ARB_texture_rectangle = "GL_ARB_texture_rectangle";
public static final String EXT_texture_rectangle = "GL_EXT_texture_rectangle";
@@ -69,16 +70,19 @@ public class GLExtensions {
public static final String NV_texture_compression_vtc = "GL_NV_texture_compression_vtc";
public static final String SGIS_generate_mipmap = "GL_SGIS_generate_mipmap";
public static final String OES_read_format = "GL_OES_read_format";
-
+ public static final String OES_single_precision = "GL_OES_single_precision";
public static final String OES_EGL_image_external = "GL_OES_EGL_image_external";
-
+ /** Required to be requested for OpenGL ES 2.0, <i>not</i> ES 3.0! */
+ public static final String OES_standard_derivatives = "GL_OES_standard_derivatives";
+
public static final String ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64";
public static final String ARB_shader_objects = "GL_ARB_shader_objects";
-
+ public static final String ARB_geometry_shader4 = "GL_ARB_geometry_shader4";
+
//
// Aliased GLX/WGL/.. extensions
//
-
- public static final String ARB_pixel_format = "GL_ARB_pixel_format";
+
+ public static final String ARB_pixel_format = "GL_ARB_pixel_format";
public static final String ARB_pbuffer = "GL_ARB_pbuffer";
}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
new file mode 100644
index 000000000..e4cd5c5d9
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -0,0 +1,627 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+import java.util.IdentityHashMap;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.opengl.GLCapabilitiesImmutable;
+
+import com.jogamp.common.os.Platform;
+
+import jogamp.opengl.egl.EGL;
+import jogamp.opengl.egl.EGLExt;
+
+/**
+ * GLRendererQuirks contains information of known bugs of various GL renderer.
+ * This information allows us to workaround them.
+ * <p>
+ * Using centralized quirk identifier enables us to
+ * locate code dealing w/ it and hence eases it's maintenance.
+ * </p>
+ * <p>
+ * <i>Some</i> <code>GL_VENDOR</code> and <code>GL_RENDERER</code> strings are
+ * listed here <http://feedback.wildfiregames.com/report/opengl/feature/GL_VENDOR>.
+ * </p>
+ */
+public class GLRendererQuirks {
+ /**
+ * Crashes XServer when using double buffered PBuffer with GL_RENDERER:
+ * <ul>
+ * <li>Mesa DRI Intel(R) Sandybridge Desktop</li>
+ * <li>Mesa DRI Intel(R) Ivybridge Mobile - 3.0 Mesa 8.0.4</li>
+ * <li>Gallium 0.4 on AMD CYPRESS</li>
+ * </ul>
+ * For now, it is safe to disable it w/ hw-acceleration.
+ */
+ public static final int NoDoubleBufferedPBuffer = 0;
+
+ /** On Windows no double buffered bitmaps are guaranteed to be available. */
+ public static final int NoDoubleBufferedBitmap = 1;
+
+ /** Crashes application when trying to set EGL swap interval on Android 4.0.3 / Pandaboard ES / PowerVR SGX 540 */
+ public static final int NoSetSwapInterval = 2;
+
+ /** No offscreen bitmap available, currently true for JOGL's OSX implementation. */
+ public static final int NoOffscreenBitmap = 3;
+
+ /** SIGSEGV on setSwapInterval() after changing the context's drawable w/ 'Mesa 8.0.4' dri2SetSwapInterval/DRI2 (soft & intel) */
+ public static final int NoSetSwapIntervalPostRetarget = 4;
+
+ /**
+ * GLSL <code>discard</code> command leads to undefined behavior or won't get compiled if being used.
+ * <p>
+ * Appears to <i>have</i> happened on Nvidia Tegra2, but seems to be fine now.<br/>
+ * FIXME: Constrain version.
+ * </p>
+ */
+ public static final int GLSLBuggyDiscard = 5;
+
+ /**
+ * Non compliant GL context due to a buggy implementation not suitable for use.
+ * <p>
+ * Currently, Mesa >= 9.1.3 (may extend back as far as 9.0) OpenGL 3.1 compatibility
+ * context is not compliant. Most programs will give completely broken output (or no
+ * output at all. For now, this context is not trusted.
+ * </p>
+ * The above has been confirmed for the following Mesa 9.* GL_RENDERER strings:
+ * <ul>
+ * <li>Mesa .* Intel(R) Sandybridge Desktop</li>
+ * <li>Gallium 0.4 on AMD RS880</li>
+ * </ul>
+ * </p>
+ * <p>
+ * It still has to be verified whether the AMD OpenGL 3.1 core driver is compliant enought.
+ */
+ public static final int GLNonCompliant = 6;
+
+ /**
+ * The OpenGL context needs a <code>glFlush()</code> before releasing it, otherwise driver may freeze:
+ * <ul>
+ * <li>OSX < 10.7.3 - NVidia Driver. Bug 533 and Bug 548 @ https://jogamp.org/bugzilla/.</li>
+ * </ul>
+ */
+ public static final int GLFlushBeforeRelease = 7;
+
+ /**
+ * Closing X11 displays may cause JVM crashes or X11 errors with some buggy drivers
+ * while being used in concert w/ OpenGL.
+ * <p>
+ * Some drivers may require X11 displays to be closed in the same order as they were created,
+ * some may not allow them to be closed at all while resources are being used somehow.
+ * </p>
+ * <p>
+ * Drivers known exposing such bug:
+ * <ul>
+ * <li>Mesa &lt; 8.0 _with_ X11 software renderer <code>Mesa X11</code>, not with GLX/DRI renderer.</li>
+ * <li>ATI proprietary Catalyst X11 driver versions:
+ * <ul>
+ * <li>8.78.6</li>
+ * <li>8.881</li>
+ * <li>8.911</li>
+ * <li>9.01.8</li>
+ * </ul></li>
+ * </ul>
+ * </p>
+ * <p>
+ * See Bug 515 - https://jogamp.org/bugzilla/show_bug.cgi?id=515
+ * and {@link jogamp.nativewindow.x11.X11Util#ATI_HAS_XCLOSEDISPLAY_BUG}.
+ * </p>
+ * <p>
+ * See Bug 705 - https://jogamp.org/bugzilla/show_bug.cgi?id=705
+ * </p>
+ */
+ public static final int DontCloseX11Display = 8;
+
+ /**
+ * Need current GL context when calling new ARB <i>pixel format query</i> functions,
+ * otherwise driver crashes the VM.
+ * <p>
+ * Drivers known exposing such bug:
+ * <ul>
+ * <li>ATI proprietary Catalyst driver on Windows version &le; XP.
+ * TODO: Validate if bug actually relates to 'old' ATI Windows drivers for old GPU's like X300
+ * regardless of the Windows version.</li>
+ * </ul>
+ * <p>
+ * See Bug 480 - https://jogamp.org/bugzilla/show_bug.cgi?id=480
+ * </p>
+ */
+ public static final int NeedCurrCtx4ARBPixFmtQueries = 9;
+
+ /**
+ * Need current GL context when calling new ARB <i>CreateContext</i> function,
+ * otherwise driver crashes the VM.
+ * <p>
+ * Drivers known exposing such bug:
+ * <ul>
+ * <li>ATI proprietary Catalyst Windows driver on laptops with a driver version as reported in <i>GL_VERSION</i>:
+ * <ul>
+ * <li> <i>null</i> </li>
+ * <li> &lt; <code>12.102.3.0</code> ( <i>amd_catalyst_13.5_mobility_beta2</i> ) </li>
+ * </ul></li>
+ * </ul>
+ * </p>
+ * <p>
+ * See Bug 706 - https://jogamp.org/bugzilla/show_bug.cgi?id=706<br/>
+ * See Bug 520 - https://jogamp.org/bugzilla/show_bug.cgi?id=520
+ * </p>
+ */
+ public static final int NeedCurrCtx4ARBCreateContext = 10;
+
+ /**
+ * No full FBO support, i.e. not compliant w/
+ * <ul>
+ * <li>GL_ARB_framebuffer_object</li>
+ * <li>EXT_framebuffer_object</li>
+ * <li>EXT_framebuffer_multisample</li>
+ * <li>EXT_framebuffer_blit</li>
+ * <li>EXT_packed_depth_stencil</li>
+ * </ul>.
+ * Drivers known exposing such bug:
+ * <ul>
+ * <li>Mesa <i>7.12-devel</i> on Windows with VMware <i>SVGA3D</i> renderer:
+ * <ul>
+ * <li>GL_VERSION: <i>2.1 Mesa 7.12-devel (git-d6c318e)</i> </li>
+ * <li>GL_RENDERER: <i>Gallium 0.4 on SVGA3D; build: RELEASE;</i> </li>
+ * </ul></li>
+ * </ul>
+ * <p>
+ * Also enabled via {@link #BuggyColorRenderbuffer}.
+ * </p>
+ * <p>
+ * Quirk can also be enabled via property: <code>jogl.fbo.force.min</code>.
+ * </p>
+ */
+ public static final int NoFullFBOSupport = 11;
+
+ /**
+ * GLSL is not compliant or even not stable (crash)
+ * <ul>
+ * <li>OSX < 10.7.0 (?) - NVidia Driver. Bug 818 @ https://jogamp.org/bugzilla/.</li>
+ * </ul>
+ */
+ public static final int GLSLNonCompliant = 12;
+
+ /**
+ * GL4 context needs to be requested via GL3 profile attribute
+ * <ul>
+ * <li>OSX >= 10.9.0 - kCGLOGLPVersion_GL4_Core may not produce hw-accel context. Bug 867 @ https://jogamp.org/bugzilla/.</li>
+ * </ul>
+ */
+ public static final int GL4NeedsGL3Request = 13;
+
+ /**
+ * Buggy shared OpenGL context support within a multithreaded use-case, not suitable for stable usage.
+ * <p>
+ * <i>X11 Mesa DRI Intel(R) driver >= 9.2.1</i> cannot handle multithreaded shared GLContext usage
+ * with non-blocking exclusive X11 display connections.
+ * References:
+ * <ul>
+ * <li>Bug 873: https://jogamp.org/bugzilla/show_bug.cgi?id=873</li>
+ * <li>https://bugs.freedesktop.org/show_bug.cgi?id=41736#c8</li>
+ * </ul>
+ * <p>
+ * However, not all multithreaded use-cases are broken, e.g. our GLMediaPlayer does work.
+ * </p>
+ * The above has been confirmed for the following Mesa 9.* strings:
+ * <ul>
+ * <li>GL_VENDOR Intel Open Source Technology Center</li>
+ * <li>GL_RENDERER Mesa DRI Intel(R) Sandybridge Desktop</li>
+ * <li>GL_RENDERER Mesa DRI Intel(R) Ivybridge Mobile</li>
+ * <li>GL_VERSION 3.1 (Core Profile) Mesa 9.2.1</li>
+ * </ul>
+ * </p>
+ * <p>
+ * On Android 4.*, <i>Huawei's Ascend G615 w/ Immersion.16</i> could not make a shared context
+ * current, which uses a pbuffer drawable:
+ * <ul>
+ * <li>Android 4.*</li>
+ * <li>GL_VENDOR Hisilicon Technologies</li>
+ * <li>GL_RENDERER Immersion.16</li>
+ * <li>GL_VERSION OpenGL ES 2.0</li>
+ * </ul>
+ * </p>
+ * <p>
+ * </p>
+ */
+ public static final int GLSharedContextBuggy = 14;
+
+ /**
+ * Bug 925 - Accept an ES3 Context, if reported via GL-Version-String w/o {@link EGLExt#EGL_OPENGL_ES3_BIT_KHR}.
+ * <p>
+ * The ES3 Context can be used via {@link EGL#EGL_OPENGL_ES2_BIT}.
+ * </p>
+ * <p>
+ * The ES3 Context {@link EGL#eglCreateContext(long, long, long, java.nio.IntBuffer) must be created} with version attributes:
+ * <pre>
+ * EGL.EGL_CONTEXT_CLIENT_VERSION, 2, ..
+ * </pre>
+ * </p>
+ * <ul>
+ * <li>Mesa/AMD >= 9.2.1</li>
+ * <li>Some Android ES3 drivers ..</li>
+ * </ul>
+ */
+ public static final int GLES3ViaEGLES2Config = 15;
+
+ /**
+ * Bug 948 - NVIDIA 331.38 (Linux X11) EGL impl. only supports _one_ EGL Device via {@link EGL#eglGetDisplay(long)}.
+ * <p>
+ * Subsequent calls to {@link EGL#eglGetDisplay(long)} fail.
+ * </p>
+ * <p>
+ * Reusing global EGL display works.
+ * </p>
+ * <p>
+ * The quirk is autodetected within EGLDrawableFactory's initial default device setup!
+ * </p>
+ * <p>
+ * Appears on:
+ * <ul>
+ * <li>EGL_VENDOR NVIDIA</li>
+ * <li>EGL_VERSION 1.4</li>
+ * <li>GL_VENDOR NVIDIA Corporation</li>
+ * <li>GL_VERSION OpenGL ES 3.0 331.38 (probably w/ 1st NV EGL lib on x86)</li>
+ * <li>Platform X11</li>
+ * <li>CPU Family {@link Platform.CPUFamily#X86}</li>
+ * </ul>
+ * </p>
+ */
+ public static final int SingletonEGLDisplayOnly = 16;
+
+ /**
+ * No reliable MSAA / FSAA {@link GLCapabilitiesImmutable#getSampleBuffers() multi}
+ * {@link GLCapabilitiesImmutable#getNumSamples() sampling} available,
+ * i.e. driver <i>may crash</i>.
+ * <p>
+ * Appears on:
+ * <ul>
+ * <li>GL_VENDOR nouveau</li>
+ * <li>GL_RENDERER Gallium 0.4 on NV34</li>
+ * </ul>
+ * TODO: We have to determine the exact version range, i.e. not adding the quirk with fixed driver version!
+ * </p>
+ * TODO: Since we currently don't handle this quirk internally, a user may need to do the following:
+ * <pre>
+ * final AbstractGraphicsDevice adevice = GLDrawableFactory.getDesktopFactory(); // or similar
+ * if( GLRendererQuirks.existStickyDeviceQuirk(adevice, GLRendererQuirks.NoMultiSamplingBuffers) ) {
+ * // don't use MSAA
+ * }
+ * </pre>
+ */
+ public static final int NoMultiSamplingBuffers = 17;
+
+ /**
+ * Buggy FBO color renderbuffer target,
+ * i.e. driver <i>may crash</i>.
+ * <p>
+ * Appears on:
+ * <ul>
+ * <li>GL_VENDOR Brian Paul</li>
+ * <li>GL_RENDERER Mesa X11</li>
+ * <li>GL_VERSION 2.1 Mesa 7.2</li>
+ * </ul>
+ * TODO: We have to determine the exact version range, i.e. not adding the quirk with fixed driver version!
+ * </p>
+ * <p>
+ * Note: Also enables {@link #NoFullFBOSupport}.
+ * </p>
+ * <p>
+ * Note: GLFBODrawable always uses texture attachments if set.
+ * </p>
+ * <p>
+ * Quirk can also be enabled via property: <code>jogl.fbo.force.nocolorrenderbuffer</code>.
+ * </p>
+ */
+ public static final int BuggyColorRenderbuffer = 18;
+
+ /**
+ * No pbuffer supporting accumulation buffers available,
+ * even if driver claims otherwise.
+ * <p>
+ * Some drivers wrongly claim to support pbuffers
+ * with accumulation buffers. However, the creation of such pbuffer fails:
+ * <pre>
+ * javax.media.opengl.GLException: pbuffer creation error: Couldn't find a suitable pixel format
+ * </pre>
+ * </p>
+ * <p>
+ * Appears on:
+ * <ul>
+ * <li>GL_VENDOR Intel</li>
+ * <li>GL_RENDERER Intel Bear Lake B</li>
+ * <li>GL_VERSION 1.4.0 - Build 8.14.10.1930</li>
+ * <li>Platform Windows</li>
+ * </ul>
+ * </p>
+ */
+ public static final int NoPBufferWithAccum = 19;
+
+ /**
+ * Need GL objects (VBO, ..) to be synchronized when utilized
+ * concurrently from multiple threads via a shared GL context,
+ * otherwise driver crashes the VM.
+ * <p>
+ * Usually synchronization should not be required, if the shared GL objects
+ * are created and immutable before concurrent usage.<br>
+ * However, using drivers exposing this issue always require the user to
+ * synchronize access of shared GL objects.
+ * </p>
+ * <p>
+ * Synchronization can be avoided if accessing the shared GL objects
+ * exclusively via a queue or {@link com.jogamp.common.util.Ringbuffer Ringbuffer}, see GLMediaPlayerImpl as an example.
+ * </p>
+ * <p>
+ * Appears on:
+ * <ul>
+ * <li>Platform OSX
+ * <ul>
+ * <li>detected on OSX 10.9.5 first</li>
+ * <li>any driver</li>
+ * <li>enabled for all OSX versions</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </p>
+ * <p>
+ * See Bug 1088 - https://jogamp.org/bugzilla/show_bug.cgi?id=1088
+ * </p>
+ */
+ public static final int NeedSharedObjectSync = 20;
+
+ /**
+ * No reliable ARB_create_context implementation,
+ * even if driver claims otherwise.
+ * <p>
+ * Some drivers wrongly claim to support ARB_create_context.
+ * However, the creation of such context fails:
+ * <pre>
+ * javax.media.opengl.GLException: AWT-EventQueue-0: WindowsWGLContex.createContextImpl ctx !ARB, profile > GL2
+ * requested (OpenGL >= 3.0.1). Requested: GLProfile[GL3bc/GL3bc.hw], current: 2.1 (Compat profile, FBO, hardware)
+ * - 2.1.8787
+ * </pre>
+ * </p>
+ * <p>
+ * Appears on:
+ * <ul>
+ * <li>GL_VENDOR ATI Technologies Inc.</li>
+ * <li>GL_RENDERER ATI Radeon 3100 Graphics</li>
+ * <li>GL_VERSION 2.1.8787</li>
+ * <li>Platform Windows</li>
+ * </ul>
+ * </p>
+ */
+ public static final int NoARBCreateContext = 21;
+
+ /** Return the number of known quirks. */
+ public static final int getCount() { return 22; }
+
+ private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
+ "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard",
+ "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11Display",
+ "NeedCurrCtx4ARBPixFmtQueries", "NeedCurrCtx4ARBCreateContext",
+ "NoFullFBOSupport", "GLSLNonCompliant", "GL4NeedsGL3Request",
+ "GLSharedContextBuggy", "GLES3ViaEGLES2Config", "SingletonEGLDisplayOnly",
+ "NoMultiSamplingBuffers", "BuggyColorRenderbuffer", "NoPBufferWithAccum",
+ "NeedSharedObjectSync", "NoARBCreateContext"
+ };
+
+ private static final IdentityHashMap<String, GLRendererQuirks> stickyDeviceQuirks = new IdentityHashMap<String, GLRendererQuirks>();
+
+ /**
+ * Retrieval of sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}.
+ * <p>
+ * The {@link AbstractGraphicsDevice}s are mapped via their {@link AbstractGraphicsDevice#getUniqueID()}.
+ * </p>
+ * <p>
+ * Not thread safe.
+ * </p>
+ * @see #areSameStickyDevice(AbstractGraphicsDevice, AbstractGraphicsDevice)
+ */
+ public static GLRendererQuirks getStickyDeviceQuirks(final AbstractGraphicsDevice device) {
+ final String key = device.getUniqueID();
+ final GLRendererQuirks has = stickyDeviceQuirks.get(key);
+ final GLRendererQuirks res;
+ if( null == has ) {
+ res = new GLRendererQuirks();
+ stickyDeviceQuirks.put(key, res);
+ } else {
+ res = has;
+ }
+ return res;
+ }
+
+ /**
+ * Returns true if both devices have the same {@link AbstractGraphicsDevice#getUniqueID()},
+ * otherwise false.
+ */
+ public static boolean areSameStickyDevice(final AbstractGraphicsDevice device1, final AbstractGraphicsDevice device2) {
+ return device1.getUniqueID() == device2.getUniqueID(); // uses .intern()!
+ }
+
+ /**
+ * {@link #addQuirk(int) Adding given quirk} of sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}.
+ * <p>
+ * Not thread safe.
+ * </p>
+ * @see #getStickyDeviceQuirks(AbstractGraphicsDevice)
+ */
+ public static void addStickyDeviceQuirk(final AbstractGraphicsDevice device, final int quirk) throws IllegalArgumentException {
+ final GLRendererQuirks sq = getStickyDeviceQuirks(device);
+ sq.addQuirk(quirk);
+ }
+ /**
+ * {@link #addQuirks(int[], int, int) Adding given quirks} of sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}.
+ * <p>
+ * Not thread safe.
+ * </p>
+ * @see #getStickyDeviceQuirks(AbstractGraphicsDevice)
+ */
+ public static void addStickyDeviceQuirks(final AbstractGraphicsDevice device, final int[] quirks, final int offset, final int len) throws IllegalArgumentException {
+ final GLRendererQuirks sq = getStickyDeviceQuirks(device);
+ sq.addQuirks(quirks, offset, len);
+ }
+ /**
+ * {@link #addQuirks(GLRendererQuirks) Adding given quirks} of sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}.
+ * <p>
+ * Not thread safe.
+ * </p>
+ * @see #getStickyDeviceQuirks(AbstractGraphicsDevice)
+ */
+ public static void addStickyDeviceQuirks(final AbstractGraphicsDevice device, final GLRendererQuirks quirks) throws IllegalArgumentException {
+ final GLRendererQuirks sq = getStickyDeviceQuirks(device);
+ sq.addQuirks(quirks);
+ }
+ /**
+ * {@link #exist(int) Query} of sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}.
+ * <p>
+ * Not thread safe. However, use after changing the sticky quirks is safe.
+ * </p>
+ * @see #getStickyDeviceQuirks(AbstractGraphicsDevice)
+ */
+ public static boolean existStickyDeviceQuirk(final AbstractGraphicsDevice device, final int quirk) {
+ return getStickyDeviceQuirks(device).exist(quirk);
+ }
+ /**
+ * {@link #addQuirks(GLRendererQuirks) Pushing} the sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}
+ * to the given {@link GLRendererQuirks destination}.
+ * <p>
+ * Not thread safe. However, use after changing the sticky quirks is safe.
+ * </p>
+ * @see #getStickyDeviceQuirks(AbstractGraphicsDevice)
+ */
+ public static void pushStickyDeviceQuirks(final AbstractGraphicsDevice device, final GLRendererQuirks dest) {
+ dest.addQuirks(getStickyDeviceQuirks(device));
+ }
+
+ private int _bitmask;
+
+ public GLRendererQuirks() {
+ _bitmask = 0;
+ }
+
+ /**
+ * @param quirks an array of valid quirks
+ * @param offset offset in quirks array to start reading
+ * @param len number of quirks to read from offset within quirks array
+ * @throws IllegalArgumentException if one of the quirks is out of range
+ */
+ public GLRendererQuirks(final int[] quirks, final int offset, final int len) throws IllegalArgumentException {
+ this();
+ addQuirks(quirks, offset, len);
+ }
+
+ /**
+ * @param quirk valid quirk to be added
+ * @throws IllegalArgumentException if the quirk is out of range
+ */
+ public final void addQuirk(final int quirk) throws IllegalArgumentException {
+ validateQuirk(quirk);
+ _bitmask |= 1 << quirk;
+ }
+
+ /**
+ * @param quirks an array of valid quirks to be added
+ * @param offset offset in quirks array to start reading
+ * @param len number of quirks to read from offset within quirks array
+ * @throws IllegalArgumentException if one of the quirks is out of range
+ */
+ public final void addQuirks(final int[] quirks, final int offset, final int len) throws IllegalArgumentException {
+ int bitmask = 0;
+ if( !( 0 <= offset + len && offset + len <= quirks.length ) ) {
+ throw new IllegalArgumentException("offset and len out of bounds: offset "+offset+", len "+len+", array-len "+quirks.length);
+ }
+ for(int i=offset; i<offset+len; i++) {
+ final int quirk = quirks[i];
+ validateQuirk(quirk);
+ bitmask |= 1 << quirk;
+ }
+ _bitmask |= bitmask;
+ }
+
+ /**
+ * @param quirks valid GLRendererQuirks to be added
+ */
+ public final void addQuirks(final GLRendererQuirks quirks) {
+ _bitmask |= quirks._bitmask;
+ }
+
+ /**
+ * @param quirk the quirk to be tested
+ * @return true if quirk exist, otherwise false
+ * @throws IllegalArgumentException if quirk is out of range
+ */
+ public final boolean exist(final int quirk) throws IllegalArgumentException {
+ validateQuirk(quirk);
+ return 0 != ( ( 1 << quirk ) & _bitmask );
+ }
+
+ public final StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("[");
+ boolean first=true;
+ for(int i=0; i<getCount(); i++) {
+ final int testmask = 1 << i;
+ if( 0 != ( _bitmask & testmask ) ) {
+ if(!first) { sb.append(", "); }
+ sb.append(toString(i));
+ first=false;
+ }
+ }
+ sb.append("]");
+ return sb;
+ }
+
+ @Override
+ public final String toString() {
+ return toString(null).toString();
+ }
+
+ /**
+ * @param quirk the quirk to be validated, i.e. whether it is out of range
+ * @throws IllegalArgumentException if quirk is out of range
+ */
+ public static void validateQuirk(final int quirk) throws IllegalArgumentException {
+ if( !( 0 <= quirk && quirk < getCount() ) ) {
+ throw new IllegalArgumentException("Quirks must be in range [0.."+getCount()+"[, but quirk: "+quirk);
+ }
+ }
+
+ /**
+ * @param quirk the quirk to be converted to String
+ * @return the String equivalent of this quirk
+ * @throws IllegalArgumentException if quirk is out of range
+ */
+ public static final String toString(final int quirk) throws IllegalArgumentException {
+ validateQuirk(quirk);
+ return _names[quirk];
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLStateKeeper.java b/src/jogl/classes/com/jogamp/opengl/GLStateKeeper.java
new file mode 100644
index 000000000..2b452e138
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLStateKeeper.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+/**
+ * Interface adding a {@link GLEventListenerState} protocol to {@link GLAutoDrawable}s
+ * or other self-contained compound types combining {@link GLDrawable}, {@link GLContext} and {@link GLEventListener}.
+ * <p>
+ * Implementing classes {@link #isGLStatePreservationSupported() may support} preservation
+ * of the {@link GLContext} state and it's associated {@link GLEventListener}.
+ * </p>
+ */
+public interface GLStateKeeper {
+
+ /** Listener for preserve and restore notifications. */
+ public static interface Listener {
+ /** Invoked before preservation. */
+ void glStatePreserveNotify(GLStateKeeper glsk);
+ /** Invoked after restoration. */
+ void glStateRestored(GLStateKeeper glsk);
+ }
+
+ /**
+ * Sets a {@link Listener}, overriding the old one.
+ * @param l the new {@link Listener}.
+ * @return the previous {@link Listener}.
+ */
+ public Listener setGLStateKeeperListener(Listener l);
+
+ /**
+ * @return <code>true</code> if GL state preservation is supported in implementation and on current platform, <code>false</code> otherwise.
+ * @see #preserveGLStateAtDestroy(boolean)
+ * @see #getPreservedGLState()
+ * @see #clearPreservedGLState()
+ */
+ public boolean isGLStatePreservationSupported();
+
+ /**
+ * If set to <code>true</code>, the next {@link GLAutoDrawable#destroy()} operation will
+ * {@link #preserveGLEventListenerState() preserve} the {@link GLEventListenerState}.
+ * <p>
+ * This is a one-shot flag, i.e. after preserving the {@link GLEventListenerState},
+ * the flag is cleared.
+ * </p>
+ * <p>
+ * A preserved {@link GLEventListenerState} will be
+ * {@link #restoreGLEventListenerState() restored} again.
+ * </p>
+ * @return <code>true</code> if supported and successful, <code>false</code> otherwise.
+ * @see #isGLStatePreservationSupported()
+ * @see #getPreservedGLState()
+ * @see #clearPreservedGLState()
+ */
+ public boolean preserveGLStateAtDestroy(boolean value);
+
+ /**
+ * Returns the preserved {@link GLEventListenerState} if preservation was performed,
+ * otherwise <code>null</code>.
+ * @see #isGLStatePreservationSupported()
+ * @see #preserveGLStateAtDestroy(boolean)
+ * @see #clearPreservedGLState()
+ */
+ public GLEventListenerState getPreservedGLState();
+
+ /**
+ * Clears the preserved {@link GLEventListenerState} from this {@link GLStateKeeper}, without destroying it.
+ *
+ * @return the preserved and cleared {@link GLEventListenerState} if preservation was performed,
+ * otherwise <code>null</code>.
+ * @see #isGLStatePreservationSupported()
+ * @see #preserveGLStateAtDestroy(boolean)
+ * @see #getPreservedGLState()
+ */
+ public GLEventListenerState clearPreservedGLState();
+}
diff --git a/src/jogl/classes/jogamp/graph/math/MathFloat.java b/src/jogl/classes/com/jogamp/opengl/GenericGLCapabilitiesChooser.java
index 82e7823a6..3693f647a 100644
--- a/src/jogl/classes/jogamp/graph/math/MathFloat.java
+++ b/src/jogl/classes/com/jogamp/opengl/GenericGLCapabilitiesChooser.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2011 JogAmp Community. All rights reserved.
+ * Copyright 2012 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -25,21 +25,24 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package jogamp.graph.math;
-public class MathFloat {
+package com.jogamp.opengl;
- public static final float E = 2.7182818284590452354f;
+import java.util.List;
+import javax.media.nativewindow.CapabilitiesImmutable;
+import javax.media.opengl.DefaultGLCapabilitiesChooser;
+
+/**
+ * Ignores windowSystemRecommendedChoice parameter,
+ * otherwise uses {@link DefaultGLCapabilitiesChooser} implementation.
+ */
+public class GenericGLCapabilitiesChooser extends DefaultGLCapabilitiesChooser {
+
+ @Override
+ public int chooseCapabilities(final CapabilitiesImmutable desired,
+ final List<? extends CapabilitiesImmutable> available,
+ final int windowSystemRecommendedChoice) {
+ return super.chooseCapabilities(desired, available, -1);
+ }
- public static final float PI = 3.14159265358979323846f;
-
- public static float abs(float a) { return (float) java.lang.Math.abs(a); }
- public static float pow(float a, float b) { return (float) java.lang.Math.pow(a, b); }
-
- public static float sin(float a) { return (float) java.lang.Math.sin(a); }
- public static float cos(float a) { return (float) java.lang.Math.cos(a); }
- public static float acos(float a) { return (float) java.lang.Math.acos(a); }
-
- public static float sqrt(float a) { return (float) java.lang.Math.sqrt(a); }
-
}
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index cdb4b82bb..8d6765036 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl;
import com.jogamp.common.GlueGenVersion;
@@ -43,7 +43,7 @@ public class JoglVersion extends JogampVersion {
protected static volatile JoglVersion jogampCommonVersionInfo;
- protected JoglVersion(String packageName, Manifest mf) {
+ protected JoglVersion(final String packageName, final Manifest mf) {
super(packageName, mf);
}
@@ -60,17 +60,17 @@ public class JoglVersion extends JogampVersion {
return jogampCommonVersionInfo;
}
- public StringBuilder toString(GL gl, StringBuilder sb) {
+ public StringBuilder toString(final GL gl, StringBuilder sb) {
sb = super.toString(sb).append(Platform.getNewline());
getGLInfo(gl, sb);
return sb;
}
- public String toString(GL gl) {
+ public String toString(final GL gl) {
return toString(gl, null).toString();
}
- public static StringBuilder getAvailableCapabilitiesInfo(GLDrawableFactory factory, AbstractGraphicsDevice device, StringBuilder sb) {
+ public static StringBuilder getAvailableCapabilitiesInfo(final GLDrawableFactory factory, final AbstractGraphicsDevice device, StringBuilder sb) {
if(null==sb) {
sb = new StringBuilder();
}
@@ -84,55 +84,78 @@ public class JoglVersion extends JogampVersion {
}
done = true;
}
- } catch (GLException gle) { /* n/a */ }
+ } catch (final GLException gle) { /* n/a */ }
}
if(!done) {
sb.append("\tnone").append(Platform.getNewline());
}
sb.append(Platform.getNewline());
- return sb;
+ return sb;
+ }
+
+ public static StringBuilder getAllAvailableCapabilitiesInfo(AbstractGraphicsDevice device, StringBuilder sb) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ if(null == device) {
+ device = GLProfile.getDefaultDevice();
+ }
+ sb.append(Platform.getNewline()).append(Platform.getNewline());
+ sb.append("Desktop Capabilities: ").append(Platform.getNewline());
+ getAvailableCapabilitiesInfo(GLDrawableFactory.getDesktopFactory(), device, sb);
+ sb.append("EGL Capabilities: ").append(Platform.getNewline());
+ getAvailableCapabilitiesInfo(GLDrawableFactory.getEGLFactory(), device, sb);
+ return sb;
}
-
- public static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, boolean withCapabilitiesInfo) {
+
+ public static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, final boolean withCapabilitiesInfo) {
if(null==sb) {
sb = new StringBuilder();
}
if(null == device) {
device = GLProfile.getDefaultDevice();
}
- sb.append("Default Profiles on device ").append(device).append(Platform.getNewline());
+ sb.append("GLProfiles on device ").append(device).append(Platform.getNewline());
if(null!=device) {
GLProfile.glAvailabilityToString(device, sb, "\t", 1);
} else {
sb.append("none");
}
if(withCapabilitiesInfo) {
- sb.append(Platform.getNewline()).append(Platform.getNewline());
- sb.append("Desktop Capabilities: ").append(Platform.getNewline());
- getAvailableCapabilitiesInfo(GLDrawableFactory.getDesktopFactory(), device, sb);
- sb.append("EGL Capabilities: ").append(Platform.getNewline());
- getAvailableCapabilitiesInfo(GLDrawableFactory.getEGLFactory(), device, sb);
+ sb = getAllAvailableCapabilitiesInfo(device, sb);
}
return sb;
}
-
- public static StringBuilder getGLInfo(GL gl, StringBuilder sb) {
- AbstractGraphicsDevice device = gl.getContext().getGLDrawable().getNativeSurface()
+
+ public static StringBuilder getGLInfo(final GL gl, final StringBuilder sb) {
+ return getGLInfo(gl, sb, false);
+ }
+ public static StringBuilder getGLInfo(final GL gl, StringBuilder sb, final boolean withCapabilitiesAndExtensionInfo) {
+ final AbstractGraphicsDevice device = gl.getContext().getGLDrawable().getNativeSurface()
.getGraphicsConfiguration().getScreen().getDevice();
if(null==sb) {
sb = new StringBuilder();
}
-
+
sb.append(VersionUtil.SEPERATOR).append(Platform.getNewline());
sb.append(device.getClass().getSimpleName()).append("[type ")
.append(device.getType()).append(", connection ").append(device.getConnection()).append("]: ").append(Platform.getNewline());
- GLProfile.glAvailabilityToString(device, sb, "\t", 1);
+ GLProfile.glAvailabilityToString(device, sb, "\t", 1);
sb.append(Platform.getNewline());
- return getGLStrings(gl, sb);
+ sb = getGLStrings(gl, sb, withCapabilitiesAndExtensionInfo);
+
+ if( withCapabilitiesAndExtensionInfo ) {
+ sb = getAllAvailableCapabilitiesInfo(device, sb);
+ }
+ return sb;
}
-
- public static StringBuilder getGLStrings(GL gl, StringBuilder sb) {
+
+ public static StringBuilder getGLStrings(final GL gl, final StringBuilder sb) {
+ return getGLStrings(gl, sb, true);
+ }
+
+ public static StringBuilder getGLStrings(final GL gl, StringBuilder sb, final boolean withExtensions) {
if(null==sb) {
sb = new StringBuilder();
}
@@ -141,35 +164,60 @@ public class JoglVersion extends JogampVersion {
sb.append(Platform.getNewline());
sb.append("GL Profile ").append(gl.getGLProfile());
sb.append(Platform.getNewline());
- sb.append("CTX VERSION ").append(gl.getContext().getGLVersion());
+ sb.append("GL Version ").append(ctx.getGLVersion()).append(" [GL ").append(ctx.getGLVersionNumber()).append(", vendor ").append(ctx.getGLVendorVersionNumber()).append("]");
sb.append(Platform.getNewline());
- sb.append("GL ").append(gl);
+ sb.append("Quirks ").append(ctx.getRendererQuirks());
+ sb.append(Platform.getNewline());
+ sb.append("Impl. class ").append(gl.getClass().getCanonicalName());
sb.append(Platform.getNewline());
sb.append("GL_VENDOR ").append(gl.glGetString(GL.GL_VENDOR));
sb.append(Platform.getNewline());
sb.append("GL_RENDERER ").append(gl.glGetString(GL.GL_RENDERER));
sb.append(Platform.getNewline());
sb.append("GL_VERSION ").append(gl.glGetString(GL.GL_VERSION));
- sb.append(Platform.getNewline());
- sb.append("GLSL ").append(gl.hasGLSL()).append(", has-compiler: ").append(gl.isFunctionAvailable("glCompileShader"));
+ sb.append(Platform.getNewline());
+ sb.append("GLSL ").append(gl.hasGLSL()).append(", has-compiler-func: ").append(gl.isFunctionAvailable("glCompileShader"));
if(gl.hasGLSL()) {
- sb.append(", version: ").append(gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION));
+ sb.append(", version: ").append(gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION)).append(" / ").append(ctx.getGLSLVersionNumber());
}
sb.append(Platform.getNewline());
- sb.append("GL_EXTENSIONS ").append(ctx.getGLExtensionCount());
+ sb.append("GL FBO: basic ").append(gl.hasBasicFBOSupport()).append(", full ").append(gl.hasFullFBOSupport());
sb.append(Platform.getNewline());
- sb.append(" ").append(ctx.getGLExtensionsString());
+ sb.append("GL_EXTENSIONS ").append(ctx.getGLExtensionCount());
sb.append(Platform.getNewline());
+ if( withExtensions ) {
+ sb.append(" ").append(ctx.getGLExtensionsString());
+ sb.append(Platform.getNewline());
+ }
sb.append("GLX_EXTENSIONS ").append(ctx.getPlatformExtensionCount());
sb.append(Platform.getNewline());
- sb.append(" ").append(ctx.getPlatformExtensionsString());
- sb.append(Platform.getNewline());
+ if( withExtensions ) {
+ sb.append(" ").append(ctx.getPlatformExtensionsString());
+ sb.append(Platform.getNewline());
+ }
sb.append(VersionUtil.SEPERATOR);
return sb;
}
- public static void main(String args[]) {
+ public StringBuilder getBriefOSGLBuildInfo(final GL gl, StringBuilder sb) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("OS: ").append(Platform.getOSName()).append(", version ").append(Platform.getOSVersion()).append(", arch ").append(Platform.getArchName());
+ sb.append(Platform.getNewline());
+ sb.append("GL_VENDOR ").append(gl.glGetString(GL.GL_VENDOR));
+ sb.append(Platform.getNewline());
+ sb.append("GL_RENDERER ").append(gl.glGetString(GL.GL_RENDERER));
+ sb.append(Platform.getNewline());
+ sb.append("GL_VERSION ").append(gl.glGetString(GL.GL_VERSION));
+ sb.append(Platform.getNewline());
+ sb.append("JOGL GIT sha1 ").append(getImplementationCommit());
+ sb.append(Platform.getNewline());
+ return sb;
+ }
+
+ public static void main(final String args[]) {
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
// System.err.println(NativeWindowVersion.getInstance());
diff --git a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java
index d160eccff..8f033a8b8 100644
--- a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.cg;
import com.jogamp.common.jvm.JNILibLoaderBase;
@@ -39,21 +39,22 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
-public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
- private static List<String> glueLibNames;
+public final class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
+ private static final List<String> glueLibNames;
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
Platform.initSingleton();
-
+
if(TempJarCache.isInitialized()) {
// only: jogl-cg.jar -> jogl-cg-natives-<os.and.arch>.jar [atomic JAR files only]
- JNILibLoaderBase.addNativeJarLibs(new Class<?>[] { CgDynamicLibraryBundleInfo.class }, null, null );
+ JNILibLoaderBase.addNativeJarLibs(new Class<?>[] { jogamp.opengl.cg.CgPackagePlaceholder.class }, null);
}
return null;
}
});
-
+
glueLibNames = new ArrayList<String>();
// glueLibNames.addAll(getGlueLibNamesPreload());
glueLibNames.add("jogl_cg");
@@ -69,11 +70,16 @@ public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
/** Make Cg symbols available to CgGL */
@Override
- public boolean shallLinkGlobal() { return true; }
+ public final boolean shallLinkGlobal() { return true; }
- /** default **/
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns <code>false</code>.
+ * </p>
+ */
@Override
- public boolean shallLookupGlobal() { return false; }
+ public final boolean shallLookupGlobal() { return false; }
/** Tool has none **/
@Override
@@ -83,22 +89,22 @@ public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
/** Tool has none **/
@Override
- public final long toolGetProcAddress(long toolGetProcAddressHandle, String funcName) {
+ public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) {
return 0;
}
-
+
@Override
- public boolean useToolGetProcAdressFirst(String funcName) {
+ public final boolean useToolGetProcAdressFirst(final String funcName) {
return false;
}
@Override
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsCg = new ArrayList<String>();
libsCg.add("Cg");
libsList.add(libsCg);
-
+
final List<String> libsCgGL = new ArrayList<String>();
libsCgGL.add("CgGL");
libsList.add(libsCgGL);
@@ -112,9 +118,9 @@ public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
@Override
- public RunnableExecutor getLibLoaderExecutor() {
+ public final RunnableExecutor getLibLoaderExecutor() {
return DynamicLibraryBundle.getDefaultRunnableExecutor();
- }
+ }
}
diff --git a/src/jogl/classes/com/jogamp/opengl/cg/CgException.java b/src/jogl/classes/com/jogamp/opengl/cg/CgException.java
index 8bfd9e23e..0a3535ba6 100644
--- a/src/jogl/classes/com/jogamp/opengl/cg/CgException.java
+++ b/src/jogl/classes/com/jogamp/opengl/cg/CgException.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -50,18 +50,18 @@ public class CgException extends RuntimeException {
}
/** Constructs a CgException object with the specified detail message. */
- public CgException(String message) {
+ public CgException(final String message) {
super(message);
}
/** Constructs a CgException object with the specified detail message and
root cause. */
- public CgException(String message, Throwable cause) {
+ public CgException(final String message, final Throwable cause) {
super(message, cause);
}
/** Constructs a CgException object with the specified root cause. */
- public CgException(Throwable cause) {
+ public CgException(final Throwable cause) {
super(cause);
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Binary16.java b/src/jogl/classes/com/jogamp/opengl/math/Binary16.java
new file mode 100644
index 000000000..8e4aa9176
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/Binary16.java
@@ -0,0 +1,569 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.math;
+
+/**
+ * <p>
+ * Functions to convert values to/from the <code>binary16</code> format
+ * specified in <code>IEEE 754 2008</code>.
+ * </p>
+ */
+
+public final class Binary16
+{
+ /**
+ * The encoded form of negative infinity <code>-∞</code>.
+ */
+
+ public static final char NEGATIVE_INFINITY;
+
+ /**
+ * The encoded form of positive infinity <code>∞</code>.
+ */
+
+ public static final char POSITIVE_INFINITY;
+
+ /**
+ * The encoded form of positive zero <code>0</code>.
+ */
+
+ public static final char POSITIVE_ZERO;
+
+ /**
+ * The encoded form of negative zero <code>-0</code>.
+ */
+
+ public static final char NEGATIVE_ZERO;
+
+ /**
+ * The <i>bias</i> value used to offset the encoded exponent. A given
+ * exponent <code>e</code> is encoded as <code>{@link #BIAS} + e</code>.
+ */
+
+ public static final int BIAS;
+
+ static {
+ NEGATIVE_INFINITY = 0xFC00;
+ POSITIVE_INFINITY = 0x7C00;
+ POSITIVE_ZERO = 0x0000;
+ NEGATIVE_ZERO = 0x8000;
+ BIAS = 15;
+ }
+
+ private static final int MASK_SIGN;
+ private static final int MASK_EXPONENT;
+ private static final int MASK_SIGNIFICAND;
+
+ static {
+ MASK_SIGN = 0x8000;
+ MASK_EXPONENT = 0x7C00;
+ MASK_SIGNIFICAND = 0x03FF;
+ }
+
+ /**
+ * One possible not-a-number value.
+ */
+
+ public static char exampleNaN()
+ {
+ final int n =
+ Binary16.packSetExponentUnbiasedUnchecked(16)
+ | Binary16.packSetSignificandUnchecked(1);
+ final char c = (char) n;
+ return c;
+ }
+
+ /**
+ * Return <code>true</code> if the given packed <code>binary16</code> value
+ * is infinite.
+ */
+
+ public static boolean isInfinite(
+ final char k)
+ {
+ if (Binary16.unpackGetExponentUnbiased(k) == 16) {
+ if (Binary16.unpackGetSignificand(k) == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return <code>true</code> if the given packed <code>binary16</code> value
+ * is not a number (<code>NaN</code>).
+ */
+
+ public static boolean isNaN(
+ final char k)
+ {
+ final int e = Binary16.unpackGetExponentUnbiased(k);
+ final int s = Binary16.unpackGetSignificand(k);
+ return (e == 16) && (s > 0);
+ }
+
+ /**
+ * <p>
+ * Convert a double precision floating point value to a packed
+ * <code>binary16</code> value.
+ * </p>
+ * <p>
+ * For the following specific cases, the function returns:
+ * </p>
+ * <ul>
+ * <li><code>NaN</code> iff <code>isNaN(k)</code></li>
+ * <li>{@link #POSITIVE_INFINITY} iff
+ * <code>k == {@link Double#POSITIVE_INFINITY}</code></li>
+ * <li>{@link #NEGATIVE_INFINITY} iff
+ * <code>k == {@link Double#NEGATIVE_INFINITY}</code></li>
+ * <li>{@link #NEGATIVE_ZERO} iff <code>k == -0.0</code></li>
+ * <li>{@link #POSITIVE_ZERO} iff <code>k == 0.0</code></li>
+ * </ul>
+ * <p>
+ * Otherwise, the <code>binary16</code> value that most closely represents
+ * <code>k</code> is returned. This may obviously be an infinite value as
+ * the interval of double precision values is far larger than that of the
+ * <code>binary16</code> type.
+ * </p>
+ *
+ * @see #unpackDouble(char)
+ */
+
+ public static char packDouble(
+ final double k)
+ {
+ if (Double.isNaN(k)) {
+ return Binary16.exampleNaN();
+ }
+ if (k == Double.POSITIVE_INFINITY) {
+ return Binary16.POSITIVE_INFINITY;
+ }
+ if (k == Double.NEGATIVE_INFINITY) {
+ return Binary16.NEGATIVE_INFINITY;
+ }
+ if (Double.doubleToLongBits(k) == Binary64.NEGATIVE_ZERO_BITS) {
+ return Binary16.NEGATIVE_ZERO;
+ }
+ if (k == 0.0) {
+ return Binary16.POSITIVE_ZERO;
+ }
+
+ final long de = Binary64.unpackGetExponentUnbiased(k);
+ final long ds = Binary64.unpackGetSign(k);
+ final long dn = Binary64.unpackGetSignificand(k);
+ final char rsr = Binary16.packSetSignUnchecked((int) ds);
+
+ /**
+ * Extract the 5 least-significant bits of the exponent.
+ */
+
+ final int rem = (int) (de & 0x001F);
+ final char rer = Binary16.packSetExponentUnbiasedUnchecked(rem);
+
+ /**
+ * Extract the 10 most-significant bits of the significand.
+ */
+
+ final long rnm = dn & 0xFFC0000000000L;
+ final long rns = rnm >> 42;
+ final char rnr = Binary16.packSetSignificandUnchecked((int) rns);
+
+ /**
+ * Combine the results.
+ */
+
+ return (char) (rsr | rer | rnr);
+ }
+
+ /**
+ * <p>
+ * Convert a single precision floating point value to a packed
+ * <code>binary16</code> value.
+ * </p>
+ * <p>
+ * For the following specific cases, the function returns:
+ * </p>
+ * <ul>
+ * <li><code>NaN</code> iff <code>isNaN(k)</code></li>
+ * <li>{@link #POSITIVE_INFINITY} iff
+ * <code>k == {@link Float#POSITIVE_INFINITY}</code></li>
+ * <li>{@link #NEGATIVE_INFINITY} iff
+ * <code>k == {@link Float#NEGATIVE_INFINITY}</code></li>
+ * <li>{@link #NEGATIVE_ZERO} iff <code>k == -0.0</code></li>
+ * <li>{@link #POSITIVE_ZERO} iff <code>k == 0.0</code></li>
+ * </ul>
+ * <p>
+ * Otherwise, the <code>binary16</code> value that most closely represents
+ * <code>k</code> is returned. This may obviously be an infinite value as
+ * the interval of single precision values is far larger than that of the
+ * <code>binary16</code> type.
+ * </p>
+ *
+ * @see #unpackFloat(char)
+ */
+
+ public static char packFloat(
+ final float k)
+ {
+ if (Float.isNaN(k)) {
+ return Binary16.exampleNaN();
+ }
+ if (k == Float.POSITIVE_INFINITY) {
+ return Binary16.POSITIVE_INFINITY;
+ }
+ if (k == Float.NEGATIVE_INFINITY) {
+ return Binary16.NEGATIVE_INFINITY;
+ }
+ if (Float.floatToIntBits(k) == Binary32.NEGATIVE_ZERO_BITS) {
+ return Binary16.NEGATIVE_ZERO;
+ }
+ if (k == 0.0) {
+ return Binary16.POSITIVE_ZERO;
+ }
+
+ final long de = Binary32.unpackGetExponentUnbiased(k);
+ final long ds = Binary32.unpackGetSign(k);
+ final long dn = Binary32.unpackGetSignificand(k);
+ final char rsr = Binary16.packSetSignUnchecked((int) ds);
+
+ /**
+ * Extract the 5 least-significant bits of the exponent.
+ */
+
+ final int rem = (int) (de & 0x001F);
+ final char rer = Binary16.packSetExponentUnbiasedUnchecked(rem);
+
+ /**
+ * Extract the 10 most-significant bits of the significand.
+ */
+
+ final long rnm = dn & 0x7FE000L;
+ final long rns = rnm >> 13;
+ final char rnr = Binary16.packSetSignificandUnchecked((int) rns);
+
+ /**
+ * Combine the results.
+ */
+
+ return (char) (rsr | rer | rnr);
+ }
+
+ /**
+ * <p>
+ * Encode the unbiased exponent <code>e</code>. Values should be in the
+ * range <code>[-15, 16]</code> - values outside of this range will be
+ * truncated.
+ * </p>
+ *
+ * @see #unpackGetExponentUnbiased(char)
+ */
+
+ public static char packSetExponentUnbiasedUnchecked(
+ final int e)
+ {
+ final int eb = e + Binary16.BIAS;
+ final int es = eb << 10;
+ final int em = es & Binary16.MASK_EXPONENT;
+ return (char) em;
+ }
+
+ /**
+ * <p>
+ * Encode the significand <code>s</code>. Values should be in the range
+ * <code>[0, 1023]</code>. Values outside of this range will be truncated.
+ * </p>
+ *
+ * @see #unpackGetSignificand(char)
+ */
+
+ public static char packSetSignificandUnchecked(
+ final int s)
+ {
+ final int sm = s & Binary16.MASK_SIGNIFICAND;
+ return (char) sm;
+ }
+
+ /**
+ * <p>
+ * Encode the sign bit <code>s</code>. Values should be in the range
+ * <code>[0, 1]</code>, with <code>0</code> ironically denoting a positive
+ * value. Values outside of this range will be truncated.
+ * </p>
+ *
+ * @see #unpackGetSign(char)
+ */
+
+ public static char packSetSignUnchecked(
+ final int s)
+ {
+ final int ss = s << 15;
+ final int sm = ss & Binary16.MASK_SIGN;
+ return (char) sm;
+ }
+
+ /**
+ * Show the given raw packed <code>binary16</code> value as a string of
+ * binary digits.
+ */
+
+ public static String toRawBinaryString(
+ final char k)
+ {
+ final StringBuilder b = new StringBuilder();
+ int z = k;
+ for (int i = 0; i < 16; ++i) {
+ if ((z & 1) == 1) {
+ b.insert(0, "1");
+ } else {
+ b.insert(0, "0");
+ }
+ z >>= 1;
+ }
+ return b.toString();
+ }
+
+ /**
+ * <p>
+ * Convert a packed <code>binary16</code> value <code>k</code> to a
+ * double-precision floating point value.
+ * </p>
+ * <p>
+ * The function returns:
+ * </p>
+ * <ul>
+ * <li><code>NaN</code> iff <code>isNaN(k)</code></li>
+ * <li>{@link Double#POSITIVE_INFINITY} iff
+ * <code>k == {@link #POSITIVE_INFINITY}</code></li>
+ * <li>{@link Double#NEGATIVE_INFINITY} iff
+ * <code>k == {@link #NEGATIVE_INFINITY}</code></li>
+ * <li><code>-0.0</code> iff <code>k == {@link #NEGATIVE_ZERO}</code></li>
+ * <li><code>0.0</code> iff <code>k == {@link #POSITIVE_ZERO}</code></li>
+ * <li><code>(-1.0 * n) * (2 ^ e) * 1.s</code>, for the decoded sign
+ * <code>n</code> of <code>k</code>, the decoded exponent <code>e</code> of
+ * <code>k</code>, and the decoded significand <code>s</code> of
+ * <code>k</code>.</li>
+ * </ul>
+ *
+ * @see #packDouble(double)
+ */
+
+ public static double unpackDouble(
+ final char k)
+ {
+ if (Binary16.isNaN(k)) {
+ return Double.NaN;
+ }
+ if (k == Binary16.POSITIVE_INFINITY) {
+ return Double.POSITIVE_INFINITY;
+ }
+ if (k == Binary16.NEGATIVE_INFINITY) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ if (k == Binary16.NEGATIVE_ZERO) {
+ return -0.0;
+ }
+ if (k == Binary16.POSITIVE_ZERO) {
+ return 0.0;
+ }
+
+ final long e = Binary16.unpackGetExponentUnbiased(k);
+ final long s = Binary16.unpackGetSign(k);
+ final long n = Binary16.unpackGetSignificand(k);
+
+ /**
+ * Shift the sign bit to the position at which it will appear in the
+ * resulting value.
+ */
+
+ final long rsr = s << 63;
+
+ /**
+ * 1. Bias the exponent.
+ *
+ * 2. Shift the result left to the position at which it will appear in the
+ * resulting value.
+ */
+
+ final long reb = (e + Binary64.BIAS);
+ final long rer = reb << 52;
+
+ /**
+ * Shift the significand left to the position at which it will appear in
+ * the resulting value.
+ */
+
+ final long rnr = n << 42;
+ return Double.longBitsToDouble(rsr | rer | rnr);
+ }
+
+ /**
+ * <p>
+ * Convert a packed <code>binary16</code> value <code>k</code> to a
+ * single-precision floating point value.
+ * </p>
+ * <p>
+ * The function returns:
+ * </p>
+ * <ul>
+ * <li><code>NaN</code> iff <code>isNaN(k)</code></li>
+ * <li>{@link Float#POSITIVE_INFINITY} iff
+ * <code>k == {@link #POSITIVE_INFINITY}</code></li>
+ * <li>{@link Float#NEGATIVE_INFINITY} iff
+ * <code>k == {@link #NEGATIVE_INFINITY}</code></li>
+ * <li><code>-0.0</code> iff <code>k == {@link #NEGATIVE_ZERO}</code></li>
+ * <li><code>0.0</code> iff <code>k == {@link #POSITIVE_ZERO}</code></li>
+ * <li><code>(-1.0 * n) * (2 ^ e) * 1.s</code>, for the decoded sign
+ * <code>n</code> of <code>k</code>, the decoded exponent <code>e</code> of
+ * <code>k</code>, and the decoded significand <code>s</code> of
+ * <code>k</code>.</li>
+ * </ul>
+ *
+ * @see #packFloat(float)
+ */
+
+ public static float unpackFloat(
+ final char k)
+ {
+ if (Binary16.isNaN(k)) {
+ return Float.NaN;
+ }
+ if (k == Binary16.POSITIVE_INFINITY) {
+ return Float.POSITIVE_INFINITY;
+ }
+ if (k == Binary16.NEGATIVE_INFINITY) {
+ return Float.NEGATIVE_INFINITY;
+ }
+ if (k == Binary16.NEGATIVE_ZERO) {
+ return -0.0f;
+ }
+ if (k == Binary16.POSITIVE_ZERO) {
+ return 0.0f;
+ }
+
+ final int e = Binary16.unpackGetExponentUnbiased(k);
+ final int s = Binary16.unpackGetSign(k);
+ final int n = Binary16.unpackGetSignificand(k);
+
+ /**
+ * Shift the sign bit to the position at which it will appear in the
+ * resulting value.
+ */
+
+ final int rsr = s << 31;
+
+ /**
+ * 1. Bias the exponent.
+ *
+ * 2. Shift the result left to the position at which it will appear in the
+ * resulting value.
+ */
+
+ final int reb = (e + Binary32.BIAS);
+ final int rer = reb << 23;
+
+ /**
+ * Shift the significand left to the position at which it will appear in
+ * the resulting value.
+ */
+
+ final int rnr = n << 13;
+ return Float.intBitsToFloat(rsr | rer | rnr);
+ }
+
+ /**
+ * <p>
+ * Extract and unbias the exponent of the given packed <code>binary16</code>
+ * value.
+ * </p>
+ * <p>
+ * The exponent is encoded <i>biased</i> as a number in the range
+ * <code>[0, 31]</code>, with <code>0</code> indicating that the number is
+ * <i>subnormal</i> and <code>[1, 30]</code> denoting the actual exponent
+ * plus {@link #BIAS}. Infinite and <code>NaN</code> values always have an
+ * exponent of <code>31</code>.
+ * </p>
+ * <p>
+ * This function will therefore return:
+ * </p>
+ * <ul>
+ * <li>
+ * <code>0 - {@link #BIAS} = -15</code> iff the input is a <i>subnormal</i>
+ * number.</li>
+ * <li>An integer in the range
+ * <code>[1 - {@link #BIAS}, 30 - {@link #BIAS}] = [-14, 15]</code> iff the
+ * input is a <i>normal</i> number.</li>
+ * <li>
+ * <code>16</code> iff the input is {@link #POSITIVE_INFINITY},
+ * {@link #NEGATIVE_INFINITY}, or <code>NaN</code>.</li>
+ * </ul>
+ *
+ * @see #packSetExponentUnbiasedUnchecked(int)
+ */
+
+ public static int unpackGetExponentUnbiased(
+ final char k)
+ {
+ final int em = k & Binary16.MASK_EXPONENT;
+ final int es = em >> 10;
+ return es - Binary16.BIAS;
+ }
+
+ /**
+ * Retrieve the sign bit of the given packed <code>binary16</code> value, as
+ * an integer in the range <code>[0, 1]</code>.
+ *
+ * @see Binary16#packSetSignUnchecked(int)
+ */
+
+ public static int unpackGetSign(
+ final char k)
+ {
+ return (k & Binary16.MASK_SIGN) >> 15;
+ }
+
+ /**
+ * <p>
+ * Return the significand of the given packed <code>binary16</code> value as
+ * an integer in the range <code>[0, 1023]</code>.
+ * </p>
+ *
+ * @see Binary16#packSetSignificandUnchecked(int)
+ */
+
+ public static int unpackGetSignificand(
+ final char k)
+ {
+ return k & Binary16.MASK_SIGNIFICAND;
+ }
+
+ private Binary16()
+ {
+ throw new AssertionError("Unreachable code, report this bug!");
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Binary32.java b/src/jogl/classes/com/jogamp/opengl/math/Binary32.java
new file mode 100644
index 000000000..599b1ff68
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/Binary32.java
@@ -0,0 +1,116 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.math;
+
+/**
+ * Functions for interrogating <code>binary32</code> (float) values.
+ */
+
+public final class Binary32
+{
+ static final int NEGATIVE_ZERO_BITS;
+ static final int MASK_SIGN;
+ static final int MASK_EXPONENT;
+ static final int MASK_SIGNIFICAND;
+ static final int BIAS;
+
+ static {
+ NEGATIVE_ZERO_BITS = 0x80000000;
+ MASK_SIGN = 0x80000000;
+ MASK_EXPONENT = 0x7ff00000;
+ MASK_SIGNIFICAND = 0x7fffff;
+ BIAS = 127;
+ }
+
+ /**
+ * <p>
+ * Extract and unbias the exponent of the given packed <code>float</code>
+ * value.
+ * </p>
+ * <p>
+ * The exponent is encoded <i>biased</i> as a number in the range
+ * <code>[0, 255]</code>, with <code>0</code> indicating that the number is
+ * <i>subnormal</i> and <code>[1, 254]</code> denoting the actual exponent
+ * plus {@link #BIAS}. Infinite and <code>NaN</code> values always have a
+ * biased exponent of <code>255</code>.
+ * </p>
+ * <p>
+ * This function will therefore return:
+ * </p>
+ * <ul>
+ * <li>
+ * <code>0 - {@link #BIAS} = -127</code> iff the input is a <i>subnormal</i>
+ * number.</li>
+ * <li>An integer in the range
+ * <code>[1 - {@link #BIAS}, 254 - {@link #BIAS}] = [-126, 127]</code> iff
+ * the input is a <i>normal</i> number.</li>
+ * <li>
+ * <code>255 - {@link #BIAS} = 128</code> iff the input is
+ * {@link #POSITIVE_INFINITY}, {@link #NEGATIVE_INFINITY}, or
+ * <code>NaN</code>.</li>
+ * </ul>
+ *
+ * @see #packSetExponentUnbiasedUnchecked(int)
+ */
+
+ public static int unpackGetExponentUnbiased(
+ final float d)
+ {
+ final int b = Float.floatToRawIntBits(d);
+ final int em = b & Binary32.MASK_EXPONENT;
+ final int es = em >> 23;
+ return es - Binary32.BIAS;
+ }
+
+ /**
+ * <p>
+ * Return the sign of the given float value.
+ * </p>
+ */
+
+ public static int unpackGetSign(
+ final float d)
+ {
+ final int b = Float.floatToRawIntBits(d);
+ return ((b & Binary32.MASK_SIGN) >> 31) & 1;
+ }
+
+ /**
+ * <p>
+ * Return the significand of the given float value.
+ * </p>
+ */
+
+ public static int unpackGetSignificand(
+ final float d)
+ {
+ final int b = Float.floatToRawIntBits(d);
+ return b & Binary32.MASK_SIGNIFICAND;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Binary64.java b/src/jogl/classes/com/jogamp/opengl/math/Binary64.java
new file mode 100644
index 000000000..d4ec636a5
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/Binary64.java
@@ -0,0 +1,116 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.math;
+
+/**
+ * Functions for interrogating <code>binary64</code> (double) values.
+ */
+
+public final class Binary64
+{
+ static final long NEGATIVE_ZERO_BITS;
+ static final long MASK_SIGN;
+ static final long MASK_EXPONENT;
+ static final long MASK_SIGNIFICAND;
+ static final long BIAS;
+
+ static {
+ NEGATIVE_ZERO_BITS = 0x8000000000000000L;
+ MASK_SIGN = 0x8000000000000000L;
+ MASK_EXPONENT = 0x7ff0000000000000L;
+ MASK_SIGNIFICAND = 0x000fffffffffffffL;
+ BIAS = 1023;
+ }
+
+ /**
+ * <p>
+ * Extract and unbias the exponent of the given packed <code>double</code>
+ * value.
+ * </p>
+ * <p>
+ * The exponent is encoded <i>biased</i> as a number in the range
+ * <code>[0, 2047]</code>, with <code>0</code> indicating that the number is
+ * <i>subnormal</i> and <code>[1, 2046]</code> denoting the actual exponent
+ * plus {@link #BIAS}. Infinite and <code>NaN</code> values always have a
+ * biased exponent of <code>2047</code>.
+ * </p>
+ * <p>
+ * This function will therefore return:
+ * </p>
+ * <ul>
+ * <li>
+ * <code>0 - {@link #BIAS} = -1023</code> iff the input is a
+ * <i>subnormal</i> number.</li>
+ * <li>An integer in the range
+ * <code>[1 - {@link #BIAS}, 2046 - {@link #BIAS}] = [-1022, 1023]</code>
+ * iff the input is a <i>normal</i> number.</li>
+ * <li>
+ * <code>2047 - {@link #BIAS} = 1024</code> iff the input is
+ * {@link #POSITIVE_INFINITY}, {@link #NEGATIVE_INFINITY}, or
+ * <code>NaN</code>.</li>
+ * </ul>
+ *
+ * @see #packSetExponentUnbiasedUnchecked(int)
+ */
+
+ public static long unpackGetExponentUnbiased(
+ final double d)
+ {
+ final long b = Double.doubleToRawLongBits(d);
+ final long em = b & Binary64.MASK_EXPONENT;
+ final long es = em >> 52;
+ return es - Binary64.BIAS;
+ }
+
+ /**
+ * <p>
+ * Return the significand of the given double value.
+ * </p>
+ */
+
+ public static long unpackGetSignificand(
+ final double d)
+ {
+ final long b = Double.doubleToRawLongBits(d);
+ return b & Binary64.MASK_SIGNIFICAND;
+ }
+
+ /**
+ * <p>
+ * Return the sign of the given double value.
+ * </p>
+ */
+
+ public static long unpackGetSign(
+ final double d)
+ {
+ final long b = Double.doubleToRawLongBits(d);
+ return ((b & Binary64.MASK_SIGN) >> 63) & 1;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FixedPoint.java b/src/jogl/classes/com/jogamp/opengl/math/FixedPoint.java
index 6412db5ef..31408b079 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/FixedPoint.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/FixedPoint.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,10 +28,10 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
-package com.jogamp.opengl.util;
+package com.jogamp.opengl.math;
public class FixedPoint {
public static final int toFixed(int value) {
@@ -46,15 +46,15 @@ public class FixedPoint {
return (int)(value * 65536.0f);
}
- public static final float toFloat(int value) {
- return (float)value/65536.0f;
+ public static final float toFloat(final int value) {
+ return value/65536.0f;
}
- public static final int mult(int x1, int x2) {
+ public static final int mult(final int x1, final int x2) {
return (int) ( ((long)x1*(long)x2)/65536 );
}
- public static final int div(int x1, int x2) {
+ public static final int div(final int x1, final int x2) {
return (int) ( (((long)x1)<<16)/x2 );
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
new file mode 100644
index 000000000..1a8924c8f
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
@@ -0,0 +1,2320 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.math;
+
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GLException;
+
+import jogamp.opengl.Debug;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.math.geom.AABBox;
+
+/**
+ * Basic Float math utility functions.
+ * <p>
+ * Implementation assumes linear matrix layout in column-major order
+ * matching OpenGL's implementation, illustration:
+ * <pre>
+ Row-Major Column-Major (OpenGL):
+
+ | 0 1 2 3 | | 0 4 8 12 |
+ | | | |
+ | 4 5 6 7 | | 1 5 9 13 |
+ M = | | M = | |
+ | 8 9 10 11 | | 2 6 10 14 |
+ | | | |
+ | 12 13 14 15 | | 3 7 11 15 |
+
+ C R C R
+ m[0*4+3] = tx; m[0+4*3] = tx;
+ m[1*4+3] = ty; m[1+4*3] = ty;
+ m[2*4+3] = tz; m[2+4*3] = tz;
+ * </pre>
+ * </p>
+ * <p>
+ * <ul>
+ * <li><a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html">Matrix-FAQ</a></li>
+ * <li><a href="https://en.wikipedia.org/wiki/Matrix_%28mathematics%29">Wikipedia-Matrix</a></li>
+ * <li><a href="http://www.euclideanspace.com/maths/algebra/matrix/index.htm">euclideanspace.com-Matrix</a></li>
+ * </ul>
+ * </p>
+ * <p>
+ * Implementation utilizes unrolling of small vertices and matrices wherever possible
+ * while trying to access memory in a linear fashion for performance reasons, see:
+ * <ul>
+ * <li><a href="https://code.google.com/p/java-matrix-benchmark/">java-matrix-benchmark</a></li>
+ * <li><a href="https://github.com/lessthanoptimal/ejml">EJML Efficient Java Matrix Library</a></li>
+ * </ul>
+ * </p>
+ */
+public final class FloatUtil {
+ public static final boolean DEBUG = Debug.debug("Math");
+
+ //
+ // Matrix Ops
+ //
+
+ /**
+ * Make matrix an identity matrix
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @return given matrix for chaining
+ */
+ public static float[] makeIdentity(final float[] m, final int m_offset) {
+ m[m_offset+0+4*0] = 1f;
+ m[m_offset+1+4*0] = 0f;
+ m[m_offset+2+4*0] = 0f;
+ m[m_offset+3+4*0] = 0f;
+
+ m[m_offset+0+4*1] = 0f;
+ m[m_offset+1+4*1] = 1f;
+ m[m_offset+2+4*1] = 0f;
+ m[m_offset+3+4*1] = 0f;
+
+ m[m_offset+0+4*2] = 0f;
+ m[m_offset+1+4*2] = 0f;
+ m[m_offset+2+4*2] = 1f;
+ m[m_offset+3+4*2] = 0f;
+
+ m[m_offset+0+4*3] = 0f;
+ m[m_offset+1+4*3] = 0f;
+ m[m_offset+2+4*3] = 0f;
+ m[m_offset+3+4*3] = 1f;
+ return m;
+ }
+
+ /**
+ * Make matrix an identity matrix
+ * @param m 4x4 matrix in column-major order (also result)
+ * @return given matrix for chaining
+ */
+ public static float[] makeIdentity(final float[] m) {
+ m[0+4*0] = 1f;
+ m[1+4*0] = 0f;
+ m[2+4*0] = 0f;
+ m[3+4*0] = 0f;
+
+ m[0+4*1] = 0f;
+ m[1+4*1] = 1f;
+ m[2+4*1] = 0f;
+ m[3+4*1] = 0f;
+
+ m[0+4*2] = 0f;
+ m[1+4*2] = 0f;
+ m[2+4*2] = 1f;
+ m[3+4*2] = 0f;
+
+ m[0+4*3] = 0f;
+ m[1+4*3] = 0f;
+ m[2+4*3] = 0f;
+ m[3+4*3] = 1f;
+ return m;
+ }
+
+ /**
+ * Make a translation matrix in column-major order from the given axis deltas
+ * <pre>
+ Translation matrix (Column Order):
+ 1 0 0 0
+ 0 1 0 0
+ 0 0 1 0
+ x y z 1
+ * </pre>
+ * <p>
+ * All matrix fields are only set if <code>initM</code> is <code>true</code>.
+ * </p>
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @param initM if true, given matrix will be initialized w/ identity matrix,
+ * otherwise only the diagonal and last-row is set.
+ * The latter can be utilized to share a once {@link #makeIdentity(float[], int) identity set} matrix
+ * for {@link #makeScale(float[], int, boolean, float, float, float) scaling}
+ * and {@link #makeTranslation(float[], int, boolean, float, float, float) translation},
+ * while leaving the other fields untouched for performance reasons.
+ * @return given matrix for chaining
+ */
+ public static float[] makeTranslation(final float[] m, final int m_offset, final boolean initM, final float tx, final float ty, final float tz) {
+ if( initM ) {
+ makeIdentity(m, m_offset);
+ } else {
+ m[m_offset+0+4*0] = 1;
+ m[m_offset+1+4*1] = 1;
+ m[m_offset+2+4*2] = 1;
+ m[m_offset+3+4*3] = 1;
+ }
+ m[m_offset+0+4*3] = tx;
+ m[m_offset+1+4*3] = ty;
+ m[m_offset+2+4*3] = tz;
+ return m;
+ }
+
+ /**
+ * Make a translation matrix in column-major order from the given axis deltas
+ * <pre>
+ Translation matrix (Column Order):
+ 1 0 0 0
+ 0 1 0 0
+ 0 0 1 0
+ x y z 1
+ * </pre>
+ * <p>
+ * All matrix fields are only set if <code>initM</code> is <code>true</code>.
+ * </p>
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param initM if true, given matrix will be initialized w/ identity matrix,
+ * otherwise only the diagonal and last-row is set.
+ * The latter can be utilized to share a once {@link #makeIdentity(float[], int) identity set} matrix
+ * for {@link #makeScale(float[], int, boolean, float, float, float) scaling}
+ * and {@link #makeTranslation(float[], int, boolean, float, float, float) translation},
+ * while leaving the other fields untouched for performance reasons.
+ * @return given matrix for chaining
+ */
+ public static float[] makeTranslation(final float[] m, final boolean initM, final float tx, final float ty, final float tz) {
+ if( initM ) {
+ makeIdentity(m);
+ } else {
+ m[0+4*0] = 1;
+ m[1+4*1] = 1;
+ m[2+4*2] = 1;
+ m[3+4*3] = 1;
+ }
+ m[0+4*3] = tx;
+ m[1+4*3] = ty;
+ m[2+4*3] = tz;
+ return m;
+ }
+
+ /**
+ * Make a scale matrix in column-major order from the given axis factors
+ * <pre>
+ Scale matrix (Any Order):
+ x 0 0 0
+ 0 y 0 0
+ 0 0 z 0
+ 0 0 0 1
+ * </pre>
+ * <p>
+ * All matrix fields are only set if <code>initM</code> is <code>true</code>.
+ * </p>
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @param initM if true, given matrix will be initialized w/ identity matrix,
+ * otherwise only the diagonal and last-row is set.
+ * The latter can be utilized to share a once {@link #makeIdentity(float[], int) identity set} matrix
+ * for {@link #makeScale(float[], int, boolean, float, float, float) scaling}
+ * and {@link #makeTranslation(float[], int, boolean, float, float, float) translation},
+ * while leaving the other fields untouched for performance reasons.
+ * @return given matrix for chaining
+ */
+ public static float[] makeScale(final float[] m, final int m_offset, final boolean initM, final float sx, final float sy, final float sz) {
+ if( initM ) {
+ makeIdentity(m, m_offset);
+ } else {
+ m[m_offset+0+4*3] = 0;
+ m[m_offset+1+4*3] = 0;
+ m[m_offset+2+4*3] = 0;
+ m[m_offset+3+4*3] = 1;
+ }
+ m[m_offset+0+4*0] = sx;
+ m[m_offset+1+4*1] = sy;
+ m[m_offset+2+4*2] = sz;
+ return m;
+ }
+
+ /**
+ * Make a scale matrix in column-major order from the given axis factors
+ * <pre>
+ Scale matrix (Any Order):
+ x 0 0 0
+ 0 y 0 0
+ 0 0 z 0
+ 0 0 0 1
+ * </pre>
+ * <p>
+ * All matrix fields are only set if <code>initM</code> is <code>true</code>.
+ * </p>
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param initM if true, given matrix will be initialized w/ identity matrix,
+ * otherwise only the diagonal and last-row is set.
+ * The latter can be utilized to share a once {@link #makeIdentity(float[], int) identity set} matrix
+ * for {@link #makeScale(float[], int, boolean, float, float, float) scaling}
+ * and {@link #makeTranslation(float[], int, boolean, float, float, float) translation},
+ * while leaving the other fields untouched for performance reasons.
+ * @return given matrix for chaining
+ */
+ public static float[] makeScale(final float[] m, final boolean initM, final float sx, final float sy, final float sz) {
+ if( initM ) {
+ makeIdentity(m);
+ } else {
+ m[0+4*3] = 0;
+ m[1+4*3] = 0;
+ m[2+4*3] = 0;
+ m[3+4*3] = 1;
+ }
+ m[0+4*0] = sx;
+ m[1+4*1] = sy;
+ m[2+4*2] = sz;
+ return m;
+ }
+
+ /**
+ * Make a rotation matrix from the given axis and angle in radians.
+ * <pre>
+ Rotation matrix (Column Order):
+ xx(1-c)+c xy(1-c)+zs xz(1-c)-ys 0
+ xy(1-c)-zs yy(1-c)+c yz(1-c)+xs 0
+ xz(1-c)+ys yz(1-c)-xs zz(1-c)+c 0
+ 0 0 0 1
+ * </pre>
+ * <p>
+ * All matrix fields are set.
+ * </p>
+ * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @return given matrix for chaining
+ */
+ public static float[] makeRotationAxis(final float[] m, final int m_offset, final float angrad, float x, float y, float z, final float[] tmpVec3f) {
+ final float c = cos(angrad);
+ final float ic= 1.0f - c;
+ final float s = sin(angrad);
+
+ tmpVec3f[0]=x; tmpVec3f[1]=y; tmpVec3f[2]=z;
+ VectorUtil.normalizeVec3(tmpVec3f);
+ x = tmpVec3f[0]; y = tmpVec3f[1]; z = tmpVec3f[2];
+
+ final float xy = x*y;
+ final float xz = x*z;
+ final float xs = x*s;
+ final float ys = y*s;
+ final float yz = y*z;
+ final float zs = z*s;
+ m[0+0*4+m_offset] = x*x*ic+c;
+ m[1+0*4+m_offset] = xy*ic+zs;
+ m[2+0*4+m_offset] = xz*ic-ys;
+ m[3+0*4+m_offset] = 0;
+
+ m[0+1*4+m_offset] = xy*ic-zs;
+ m[1+1*4+m_offset] = y*y*ic+c;
+ m[2+1*4+m_offset] = yz*ic+xs;
+ m[3+1*4+m_offset] = 0;
+
+ m[0+2*4+m_offset] = xz*ic+ys;
+ m[1+2*4+m_offset] = yz*ic-xs;
+ m[2+2*4+m_offset] = z*z*ic+c;
+ m[3+2*4+m_offset] = 0;
+
+ m[0+3*4+m_offset] = 0f;
+ m[1+3*4+m_offset] = 0f;
+ m[2+3*4+m_offset] = 0f;
+ m[3+3*4+m_offset] = 1f;
+
+ return m;
+ }
+
+ /**
+ * Make a concatenated rotation matrix in column-major order from the given Euler rotation angles in radians.
+ * <p>
+ * The rotations are applied in the given order:
+ * <ul>
+ * <li>y - heading</li>
+ * <li>z - attitude</li>
+ * <li>x - bank</li>
+ * </ul>
+ * </p>
+ * <p>
+ * All matrix fields are set.
+ * </p>
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @param bankX the Euler pitch angle in radians. (rotation about the X axis)
+ * @param headingY the Euler yaw angle in radians. (rotation about the Y axis)
+ * @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis)
+ * @return given matrix for chaining
+ * <p>
+ * Implementation does not use Quaternion and hence is exposed to
+ * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a>
+ * </p>
+ * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q36">Matrix-FAQ Q36</a>
+ * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm">euclideanspace.com-eulerToMatrix</a>
+ */
+ public static float[] makeRotationEuler(final float[] m, final int m_offset, final float bankX, final float headingY, final float attitudeZ) {
+ // Assuming the angles are in radians.
+ final float ch = cos(headingY);
+ final float sh = sin(headingY);
+ final float ca = cos(attitudeZ);
+ final float sa = sin(attitudeZ);
+ final float cb = cos(bankX);
+ final float sb = sin(bankX);
+
+ m[0+0*4+m_offset] = ch*ca;
+ m[1+0*4+m_offset] = sa;
+ m[2+0*4+m_offset] = -sh*ca;
+ m[3+0*4+m_offset] = 0;
+
+ m[0+1*4+m_offset] = sh*sb - ch*sa*cb;
+ m[1+1*4+m_offset] = ca*cb;
+ m[2+1*4+m_offset] = sh*sa*cb + ch*sb;
+ m[3+1*4+m_offset] = 0;
+
+ m[0+2*4+m_offset] = ch*sa*sb + sh*cb;
+ m[1+2*4+m_offset] = -ca*sb;
+ m[2+2*4+m_offset] = -sh*sa*sb + ch*cb;
+ m[3+2*4+m_offset] = 0;
+
+ m[0+3*4+m_offset] = 0;
+ m[1+3*4+m_offset] = 0;
+ m[2+3*4+m_offset] = 0;
+ m[3+3*4+m_offset] = 1;
+
+ return m;
+ }
+
+ /**
+ * Make given matrix the orthogonal matrix based on given parameters.
+ * <pre>
+ Ortho matrix (Column Order):
+ 2/dx 0 0 0
+ 0 2/dy 0 0
+ 0 0 2/dz 0
+ tx ty tz 1
+ * </pre>
+ * <p>
+ * All matrix fields are only set if <code>initM</code> is <code>true</code>.
+ * </p>
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @param initM if true, given matrix will be initialized w/ identity matrix,
+ * otherwise only the orthogonal fields are set.
+ * @param left
+ * @param right
+ * @param bottom
+ * @param top
+ * @param zNear
+ * @param zFar
+ * @return given matrix for chaining
+ */
+ public static float[] makeOrtho(final float[] m, final int m_offset, final boolean initM,
+ final float left, final float right,
+ final float bottom, final float top,
+ final float zNear, final float zFar) {
+ if( initM ) {
+ // m[m_offset+0+4*0] = 1f;
+ m[m_offset+1+4*0] = 0f;
+ m[m_offset+2+4*0] = 0f;
+ m[m_offset+3+4*0] = 0f;
+
+ m[m_offset+0+4*1] = 0f;
+ // m[m_offset+1+4*1] = 1f;
+ m[m_offset+2+4*1] = 0f;
+ m[m_offset+3+4*1] = 0f;
+
+ m[m_offset+0+4*2] = 0f;
+ m[m_offset+1+4*2] = 0f;
+ // m[m_offset+2+4*2] = 1f;
+ m[m_offset+3+4*2] = 0f;
+
+ // m[m_offset+0+4*3] = 0f;
+ // m[m_offset+1+4*3] = 0f;
+ // m[m_offset+2+4*3] = 0f;
+ // m[m_offset+3+4*3] = 1f;
+ }
+ final float dx=right-left;
+ final float dy=top-bottom;
+ final float dz=zFar-zNear;
+ final float tx=-1.0f*(right+left)/dx;
+ final float ty=-1.0f*(top+bottom)/dy;
+ final float tz=-1.0f*(zFar+zNear)/dz;
+
+ m[m_offset+0+4*0] = 2.0f/dx;
+
+ m[m_offset+1+4*1] = 2.0f/dy;
+
+ m[m_offset+2+4*2] = -2.0f/dz;
+
+ m[m_offset+0+4*3] = tx;
+ m[m_offset+1+4*3] = ty;
+ m[m_offset+2+4*3] = tz;
+ m[m_offset+3+4*3] = 1f;
+
+ return m;
+ }
+
+ /**
+ * Make given matrix the frustum matrix based on given parameters.
+ * <pre>
+ Frustum matrix (Column Order):
+ 2*zNear/dx 0 0 0
+ 0 2*zNear/dy 0 0
+ A B C -1
+ 0 0 D 0
+ * </pre>
+ * <p>
+ * All matrix fields are only set if <code>initM</code> is <code>true</code>.
+ * </p>
+ *
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @param initM if true, given matrix will be initialized w/ identity matrix,
+ * otherwise only the frustum fields are set.
+ * @param left
+ * @param right
+ * @param bottom
+ * @param top
+ * @param zNear
+ * @param zFar
+ * @return given matrix for chaining
+ */
+ public static float[] makeFrustum(final float[] m, final int m_offset, final boolean initM,
+ final float left, final float right,
+ final float bottom, final float top,
+ final float zNear, final float zFar) {
+ if(zNear<=0.0f||zFar<0.0f) {
+ throw new GLException("GL_INVALID_VALUE: zNear and zFar must be positive, and zNear>0");
+ }
+ if(left==right || top==bottom) {
+ throw new GLException("GL_INVALID_VALUE: top,bottom and left,right must not be equal");
+ }
+ if( initM ) {
+ // m[m_offset+0+4*0] = 1f;
+ m[m_offset+1+4*0] = 0f;
+ m[m_offset+2+4*0] = 0f;
+ m[m_offset+3+4*0] = 0f;
+
+ m[m_offset+0+4*1] = 0f;
+ // m[m_offset+1+4*1] = 1f;
+ m[m_offset+2+4*1] = 0f;
+ m[m_offset+3+4*1] = 0f;
+
+ // m[m_offset+0+4*2] = 0f;
+ // m[m_offset+1+4*2] = 0f;
+ // m[m_offset+2+4*2] = 1f;
+ // m[m_offset+3+4*2] = 0f;
+
+ m[m_offset+0+4*3] = 0f;
+ m[m_offset+1+4*3] = 0f;
+ // m[m_offset+2+4*3] = 0f;
+ // m[m_offset+3+4*3] = 1f;
+ }
+ final float zNear2 = 2.0f*zNear;
+ final float dx=right-left;
+ final float dy=top-bottom;
+ final float dz=zFar-zNear;
+ final float A=(right+left)/dx;
+ final float B=(top+bottom)/dy;
+ final float C=-1.0f*(zFar+zNear)/dz;
+ final float D=-2.0f*(zFar*zNear)/dz;
+
+ m[m_offset+0+4*0] = zNear2/dx;
+
+ m[m_offset+1+4*1] = zNear2/dy;
+
+ m[m_offset+0+4*2] = A;
+ m[m_offset+1+4*2] = B;
+ m[m_offset+2+4*2] = C;
+ m[m_offset+3+4*2] = -1.0f;
+
+ m[m_offset+2+4*3] = D;
+ m[m_offset+3+4*3] = 0f;
+
+ return m;
+ }
+
+ /**
+ * Make given matrix the perspective {@link #makeFrustum(float[], int, boolean, float, float, float, float, float, float) frustum}
+ * matrix based on given parameters.
+ * <p>
+ * All matrix fields are only set if <code>initM</code> is <code>true</code>.
+ * </p>
+ *
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @param initM if true, given matrix will be initialized w/ identity matrix,
+ * otherwise only the frustum fields are set.
+ * @param fovy_rad angle in radians
+ * @param aspect aspect ratio width / height
+ * @param zNear
+ * @param zFar
+ * @return given matrix for chaining
+ */
+ public static float[] makePerspective(final float[] m, final int m_off, final boolean initM,
+ final float fovy_rad, final float aspect, final float zNear, final float zFar) {
+ final float top = tan(fovy_rad/2f) * zNear; // use tangent of half-fov !
+ final float bottom = -1.0f * top;
+ final float left = aspect * bottom;
+ final float right = aspect * top;
+ return makeFrustum(m, m_off, initM, left, right, bottom, top, zNear, zFar);
+ }
+
+ /**
+ * Make given matrix the perspective {@link #makeFrustum(float[], int, boolean, float, float, float, float, float, float) frustum}
+ * matrix based on given parameters.
+ * <p>
+ * All matrix fields are only set if <code>initM</code> is <code>true</code>.
+ * </p>
+ *
+ * @param m 4x4 matrix in column-major order (also result)
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @param initM if true, given matrix will be initialized w/ identity matrix,
+ * otherwise only the frustum fields are set.
+ * @param fovhv {@link FovHVHalves} field of view in both directions, may not be centered, either in radians or tangent
+ * @param zNear
+ * @param zFar
+ * @return given matrix for chaining
+ */
+ public static float[] makePerspective(final float[] m, final int m_offset, final boolean initM,
+ final FovHVHalves fovhv, final float zNear, final float zFar) {
+ final FovHVHalves fovhvTan = fovhv.toTangents(); // use tangent of half-fov !
+ final float top = fovhvTan.top * zNear;
+ final float bottom = -1.0f * fovhvTan.bottom * zNear;
+ final float left = -1.0f * fovhvTan.left * zNear;
+ final float right = fovhvTan.right * zNear;
+ return makeFrustum(m, m_offset, initM, left, right, bottom, top, zNear, zFar);
+ }
+
+ /**
+ * Make given matrix the <i>look-at</i> matrix based on given parameters.
+ * <p>
+ * Consist out of two matrix multiplications:
+ * <pre>
+ * <b>R</b> = <b>L</b> x <b>T</b>,
+ * with <b>L</b> for <i>look-at</i> matrix and
+ * <b>T</b> for eye translation.
+ *
+ * Result <b>R</b> can be utilized for <i>modelview</i> multiplication, i.e.
+ * <b>M</b> = <b>M</b> x <b>R</b>,
+ * with <b>M</b> being the <i>modelview</i> matrix.
+ * </pre>
+ * </p>
+ * <p>
+ * All matrix fields are set.
+ * </p>
+ * @param m 4x4 matrix in column-major order, result only
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @param eye 3 component eye vector
+ * @param eye_offset
+ * @param center 3 component center vector
+ * @param center_offset
+ * @param up 3 component up vector
+ * @param up_offset
+ * @param mat4Tmp temp float[16] storage
+ * @return given matrix <code>m</code> for chaining
+ */
+ public static float[] makeLookAt(final float[] m, final int m_offset,
+ final float[] eye, final int eye_offset,
+ final float[] center, final int center_offset,
+ final float[] up, final int up_offset,
+ final float[] mat4Tmp) {
+ final int forward_off = 0;
+ final int side_off = 3;
+ final int up2_off = 6;
+
+ // forward!
+ mat4Tmp[0] = center[0+center_offset] - eye[0+eye_offset];
+ mat4Tmp[1] = center[1+center_offset] - eye[1+eye_offset];
+ mat4Tmp[2] = center[2+center_offset] - eye[2+eye_offset];
+
+ VectorUtil.normalizeVec3(mat4Tmp); // normalize forward
+
+ /* Side = forward x up */
+ VectorUtil.crossVec3(mat4Tmp, side_off, mat4Tmp, forward_off, up, up_offset);
+ VectorUtil.normalizeVec3(mat4Tmp, side_off); // normalize side
+
+ /* Recompute up as: up = side x forward */
+ VectorUtil.crossVec3(mat4Tmp, up2_off, mat4Tmp, side_off, mat4Tmp, forward_off);
+
+ m[m_offset + 0 * 4 + 0] = mat4Tmp[0+side_off]; // side
+ m[m_offset + 0 * 4 + 1] = mat4Tmp[0+up2_off]; // up2
+ m[m_offset + 0 * 4 + 2] = -mat4Tmp[0]; // forward
+ m[m_offset + 0 * 4 + 3] = 0;
+
+ m[m_offset + 1 * 4 + 0] = mat4Tmp[1+side_off]; // side
+ m[m_offset + 1 * 4 + 1] = mat4Tmp[1+up2_off]; // up2
+ m[m_offset + 1 * 4 + 2] = -mat4Tmp[1]; // forward
+ m[m_offset + 1 * 4 + 3] = 0;
+
+ m[m_offset + 2 * 4 + 0] = mat4Tmp[2+side_off]; // side
+ m[m_offset + 2 * 4 + 1] = mat4Tmp[2+up2_off]; // up2
+ m[m_offset + 2 * 4 + 2] = -mat4Tmp[2]; // forward
+ m[m_offset + 2 * 4 + 3] = 0;
+
+ m[m_offset + 3 * 4 + 0] = 0;
+ m[m_offset + 3 * 4 + 1] = 0;
+ m[m_offset + 3 * 4 + 2] = 0;
+ m[m_offset + 3 * 4 + 3] = 1;
+
+ makeTranslation(mat4Tmp, true, -eye[0+eye_offset], -eye[1+eye_offset], -eye[2+eye_offset]);
+ multMatrix(m, m_offset, mat4Tmp, 0);
+
+ return m;
+ }
+
+ /**
+ * Make given matrix the <i>pick</i> matrix based on given parameters.
+ * <p>
+ * Traditional <code>gluPickMatrix</code> implementation.
+ * </p>
+ * <p>
+ * Consist out of two matrix multiplications:
+ * <pre>
+ * <b>R</b> = <b>T</b> x <b>S</b>,
+ * with <b>T</b> for viewport translation matrix and
+ * <b>S</b> for viewport scale matrix.
+ *
+ * Result <b>R</b> can be utilized for <i>projection</i> multiplication, i.e.
+ * <b>P</b> = <b>P</b> x <b>R</b>,
+ * with <b>P</b> being the <i>projection</i> matrix.
+ * </pre>
+ * </p>
+ * <p>
+ * To effectively use the generated pick matrix for picking,
+ * call {@link #makePick(float[], int, float, float, float, float, int[], int, float[]) makePick}
+ * and multiply a {@link #makePerspective(float[], int, boolean, float, float, float, float) custom perspective matrix}
+ * by this pick matrix. Then you may load the result onto the perspective matrix stack.
+ * </p>
+ * <p>
+ * All matrix fields are set.
+ * </p>
+ * @param m 4x4 matrix in column-major order, result only
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @param x the center x-component of a picking region in window coordinates
+ * @param y the center y-component of a picking region in window coordinates
+ * @param deltaX the width of the picking region in window coordinates.
+ * @param deltaY the height of the picking region in window coordinates.
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param mat4Tmp temp float[16] storage
+ * @return given matrix <code>m</code> for chaining or <code>null</code> if either delta value is <= zero.
+ */
+ public static float[] makePick(final float[] m, final int m_offset,
+ final float x, final float y,
+ final float deltaX, final float deltaY,
+ final int[] viewport, final int viewport_offset,
+ final float[] mat4Tmp) {
+ if (deltaX <= 0 || deltaY <= 0) {
+ return null;
+ }
+
+ /* Translate and scale the picked region to the entire window */
+ makeTranslation(m, m_offset, true,
+ (viewport[2+viewport_offset] - 2 * (x - viewport[0+viewport_offset])) / deltaX,
+ (viewport[3+viewport_offset] - 2 * (y - viewport[1+viewport_offset])) / deltaY,
+ 0);
+ makeScale(mat4Tmp, true,
+ viewport[2+viewport_offset] / deltaX, viewport[3+viewport_offset] / deltaY, 1.0f);
+ multMatrix(m, m_offset, mat4Tmp, 0);
+ return m;
+ }
+
+ /**
+ * Transpose the given matrix.
+ *
+ * @param msrc 4x4 matrix in column-major order, the source
+ * @param msrc_offset offset in given array <i>msrc</i>, i.e. start of the 4x4 matrix
+ * @param mres 4x4 matrix in column-major order, the result
+ * @param mres_offset offset in given array <i>mres</i>, i.e. start of the 4x4 matrix
+ * @return given result matrix <i>mres</i> for chaining
+ */
+ public static float[] transposeMatrix(final float[] msrc, final int msrc_offset, final float[] mres, final int mres_offset) {
+ mres[mres_offset+0] = msrc[msrc_offset+0*4];
+ mres[mres_offset+1] = msrc[msrc_offset+1*4];
+ mres[mres_offset+2] = msrc[msrc_offset+2*4];
+ mres[mres_offset+3] = msrc[msrc_offset+3*4];
+
+ final int i4_1 = 1*4;
+ mres[mres_offset+0+i4_1] = msrc[msrc_offset+1+0*4];
+ mres[mres_offset+1+i4_1] = msrc[msrc_offset+1+1*4];
+ mres[mres_offset+2+i4_1] = msrc[msrc_offset+1+2*4];
+ mres[mres_offset+3+i4_1] = msrc[msrc_offset+1+3*4];
+
+ final int i4_2 = 2*4;
+ mres[mres_offset+0+i4_2] = msrc[msrc_offset+2+0*4];
+ mres[mres_offset+1+i4_2] = msrc[msrc_offset+2+1*4];
+ mres[mres_offset+2+i4_2] = msrc[msrc_offset+2+2*4];
+ mres[mres_offset+3+i4_2] = msrc[msrc_offset+2+3*4];
+
+ final int i4_3 = 3*4;
+ mres[mres_offset+0+i4_3] = msrc[msrc_offset+3+0*4];
+ mres[mres_offset+1+i4_3] = msrc[msrc_offset+3+1*4];
+ mres[mres_offset+2+i4_3] = msrc[msrc_offset+3+2*4];
+ mres[mres_offset+3+i4_3] = msrc[msrc_offset+3+3*4];
+
+ return mres;
+ }
+
+ /**
+ * Transpose the given matrix.
+ *
+ * @param msrc 4x4 matrix in column-major order, the source
+ * @param mres 4x4 matrix in column-major order, the result
+ * @return given result matrix <i>mres</i> for chaining
+ */
+ public static float[] transposeMatrix(final float[] msrc, final float[] mres) {
+ mres[0] = msrc[0*4];
+ mres[1] = msrc[1*4];
+ mres[2] = msrc[2*4];
+ mres[3] = msrc[3*4];
+
+ final int i4_1 = 1*4;
+ mres[0+i4_1] = msrc[1+0*4];
+ mres[1+i4_1] = msrc[1+1*4];
+ mres[2+i4_1] = msrc[1+2*4];
+ mres[3+i4_1] = msrc[1+3*4];
+
+ final int i4_2 = 2*4;
+ mres[0+i4_2] = msrc[2+0*4];
+ mres[1+i4_2] = msrc[2+1*4];
+ mres[2+i4_2] = msrc[2+2*4];
+ mres[3+i4_2] = msrc[2+3*4];
+
+ final int i4_3 = 3*4;
+ mres[0+i4_3] = msrc[3+0*4];
+ mres[1+i4_3] = msrc[3+1*4];
+ mres[2+i4_3] = msrc[3+2*4];
+ mres[3+i4_3] = msrc[3+3*4];
+
+ return mres;
+ }
+
+ /**
+ * Returns the determinant of the given matrix
+ * @param m 4x4 matrix in column-major order, the source
+ * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
+ * @return the matrix determinant
+ */
+ public static float matrixDeterminant(final float[] m, final int m_offset) {
+ float a11 = m[ 1+4*1 + m_offset ];
+ float a21 = m[ 2+4*1 + m_offset ];
+ float a31 = m[ 3+4*1 + m_offset ];
+ float a12 = m[ 1+4*2 + m_offset ];
+ float a22 = m[ 2+4*2 + m_offset ];
+ float a32 = m[ 3+4*2 + m_offset ];
+ float a13 = m[ 1+4*3 + m_offset ];
+ float a23 = m[ 2+4*3 + m_offset ];
+ float a33 = m[ 3+4*3 + m_offset ];
+
+ float ret = 0;
+ ret += m[ 0 + m_offset ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
+ a11 = m[ 1+4*0 + m_offset ];
+ a21 = m[ 2+4*0 + m_offset ];
+ a31 = m[ 3+4*0 + m_offset ];
+ ret -= m[ 0+4*1 + m_offset ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
+ a12 = m[ 1+4*1 + m_offset ];
+ a22 = m[ 2+4*1 + m_offset ];
+ a32 = m[ 3+4*1 + m_offset ];
+ ret += m[ 0+4*2 + m_offset ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
+ a13 = m[ 1+4*2 + m_offset ];
+ a23 = m[ 2+4*2 + m_offset ];
+ a33 = m[ 3+4*2 + m_offset ];
+ ret -= m[ 0+4*3 + m_offset ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
+ return ret;
+ }
+
+ /**
+ * Returns the determinant of the given matrix
+ * @param m 4x4 matrix in column-major order, the source
+ * @return the matrix determinant
+ */
+ public static float matrixDeterminant(final float[] m) {
+ float a11 = m[ 1+4*1 ];
+ float a21 = m[ 2+4*1 ];
+ float a31 = m[ 3+4*1 ];
+ float a12 = m[ 1+4*2 ];
+ float a22 = m[ 2+4*2 ];
+ float a32 = m[ 3+4*2 ];
+ float a13 = m[ 1+4*3 ];
+ float a23 = m[ 2+4*3 ];
+ float a33 = m[ 3+4*3 ];
+
+ float ret = 0;
+ ret += m[ 0 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
+ a11 = m[ 1+4*0 ];
+ a21 = m[ 2+4*0 ];
+ a31 = m[ 3+4*0 ];
+ ret -= m[ 0+4*1 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
+ a12 = m[ 1+4*1 ];
+ a22 = m[ 2+4*1 ];
+ a32 = m[ 3+4*1 ];
+ ret += m[ 0+4*2 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
+ a13 = m[ 1+4*2 ];
+ a23 = m[ 2+4*2 ];
+ a33 = m[ 3+4*2 ];
+ ret -= m[ 0+4*3 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
+ return ret;
+ }
+
+ /**
+ * Invert the given matrix.
+ * <p>
+ * Returns <code>null</code> if inversion is not possible,
+ * e.g. matrix is singular due to a bad matrix.
+ * </p>
+ *
+ * @param msrc 4x4 matrix in column-major order, the source
+ * @param msrc_offset offset in given array <i>msrc</i>, i.e. start of the 4x4 matrix
+ * @param mres 4x4 matrix in column-major order, the result - may be <code>msrc</code> (in-place)
+ * @param mres_offset offset in given array <i>mres</i>, i.e. start of the 4x4 matrix - may be <code>msrc_offset</code> (in-place)
+ * @return given result matrix <i>mres</i> for chaining if successful, otherwise <code>null</code>. See above.
+ */
+ public static float[] invertMatrix(final float[] msrc, final int msrc_offset, final float[] mres, final int mres_offset) {
+ final float scale;
+ {
+ float max = Math.abs(msrc[0]);
+
+ for( int i = 1; i < 16; i++ ) {
+ final float a = Math.abs(msrc[i]);
+ if( a > max ) max = a;
+ }
+ if( 0 == max ) {
+ return null;
+ }
+ scale = 1.0f/max;
+ }
+
+ final float a11 = msrc[0+4*0+msrc_offset]*scale;
+ final float a21 = msrc[1+4*0+msrc_offset]*scale;
+ final float a31 = msrc[2+4*0+msrc_offset]*scale;
+ final float a41 = msrc[3+4*0+msrc_offset]*scale;
+ final float a12 = msrc[0+4*1+msrc_offset]*scale;
+ final float a22 = msrc[1+4*1+msrc_offset]*scale;
+ final float a32 = msrc[2+4*1+msrc_offset]*scale;
+ final float a42 = msrc[3+4*1+msrc_offset]*scale;
+ final float a13 = msrc[0+4*2+msrc_offset]*scale;
+ final float a23 = msrc[1+4*2+msrc_offset]*scale;
+ final float a33 = msrc[2+4*2+msrc_offset]*scale;
+ final float a43 = msrc[3+4*2+msrc_offset]*scale;
+ final float a14 = msrc[0+4*3+msrc_offset]*scale;
+ final float a24 = msrc[1+4*3+msrc_offset]*scale;
+ final float a34 = msrc[2+4*3+msrc_offset]*scale;
+ final float a44 = msrc[3+4*3+msrc_offset]*scale;
+
+ final float m11 = + a22*(a33*a44 - a34*a43) - a23*(a32*a44 - a34*a42) + a24*(a32*a43 - a33*a42);
+ final float m12 = -( + a21*(a33*a44 - a34*a43) - a23*(a31*a44 - a34*a41) + a24*(a31*a43 - a33*a41));
+ final float m13 = + a21*(a32*a44 - a34*a42) - a22*(a31*a44 - a34*a41) + a24*(a31*a42 - a32*a41);
+ final float m14 = -( + a21*(a32*a43 - a33*a42) - a22*(a31*a43 - a33*a41) + a23*(a31*a42 - a32*a41));
+ final float m21 = -( + a12*(a33*a44 - a34*a43) - a13*(a32*a44 - a34*a42) + a14*(a32*a43 - a33*a42));
+ final float m22 = + a11*(a33*a44 - a34*a43) - a13*(a31*a44 - a34*a41) + a14*(a31*a43 - a33*a41);
+ final float m23 = -( + a11*(a32*a44 - a34*a42) - a12*(a31*a44 - a34*a41) + a14*(a31*a42 - a32*a41));
+ final float m24 = + a11*(a32*a43 - a33*a42) - a12*(a31*a43 - a33*a41) + a13*(a31*a42 - a32*a41);
+ final float m31 = + a12*(a23*a44 - a24*a43) - a13*(a22*a44 - a24*a42) + a14*(a22*a43 - a23*a42);
+ final float m32 = -( + a11*(a23*a44 - a24*a43) - a13*(a21*a44 - a24*a41) + a14*(a21*a43 - a23*a41));
+ final float m33 = + a11*(a22*a44 - a24*a42) - a12*(a21*a44 - a24*a41) + a14*(a21*a42 - a22*a41);
+ final float m34 = -( + a11*(a22*a43 - a23*a42) - a12*(a21*a43 - a23*a41) + a13*(a21*a42 - a22*a41));
+ final float m41 = -( + a12*(a23*a34 - a24*a33) - a13*(a22*a34 - a24*a32) + a14*(a22*a33 - a23*a32));
+ final float m42 = + a11*(a23*a34 - a24*a33) - a13*(a21*a34 - a24*a31) + a14*(a21*a33 - a23*a31);
+ final float m43 = -( + a11*(a22*a34 - a24*a32) - a12*(a21*a34 - a24*a31) + a14*(a21*a32 - a22*a31));
+ final float m44 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31);
+
+ final float det = (a11*m11 + a12*m12 + a13*m13 + a14*m14)/scale;
+
+ if( 0 == det ) {
+ return null;
+ }
+
+ mres[0+4*0+mres_offset] = m11 / det;
+ mres[1+4*0+mres_offset] = m12 / det;
+ mres[2+4*0+mres_offset] = m13 / det;
+ mres[3+4*0+mres_offset] = m14 / det;
+ mres[0+4*1+mres_offset] = m21 / det;
+ mres[1+4*1+mres_offset] = m22 / det;
+ mres[2+4*1+mres_offset] = m23 / det;
+ mres[3+4*1+mres_offset] = m24 / det;
+ mres[0+4*2+mres_offset] = m31 / det;
+ mres[1+4*2+mres_offset] = m32 / det;
+ mres[2+4*2+mres_offset] = m33 / det;
+ mres[3+4*2+mres_offset] = m34 / det;
+ mres[0+4*3+mres_offset] = m41 / det;
+ mres[1+4*3+mres_offset] = m42 / det;
+ mres[2+4*3+mres_offset] = m43 / det;
+ mres[3+4*3+mres_offset] = m44 / det;
+ return mres;
+ }
+
+ /**
+ * Invert the given matrix.
+ * <p>
+ * Returns <code>null</code> if inversion is not possible,
+ * e.g. matrix is singular due to a bad matrix.
+ * </p>
+ *
+ * @param msrc 4x4 matrix in column-major order, the source
+ * @param mres 4x4 matrix in column-major order, the result - may be <code>msrc</code> (in-place)
+ * @return given result matrix <i>mres</i> for chaining if successful, otherwise <code>null</code>. See above.
+ */
+ public static float[] invertMatrix(final float[] msrc, final float[] mres) {
+ final float scale;
+ {
+ float max = Math.abs(msrc[0]);
+
+ for( int i = 1; i < 16; i++ ) {
+ final float a = Math.abs(msrc[i]);
+ if( a > max ) max = a;
+ }
+ if( 0 == max ) {
+ return null;
+ }
+ scale = 1.0f/max;
+ }
+
+ final float a11 = msrc[0+4*0]*scale;
+ final float a21 = msrc[1+4*0]*scale;
+ final float a31 = msrc[2+4*0]*scale;
+ final float a41 = msrc[3+4*0]*scale;
+ final float a12 = msrc[0+4*1]*scale;
+ final float a22 = msrc[1+4*1]*scale;
+ final float a32 = msrc[2+4*1]*scale;
+ final float a42 = msrc[3+4*1]*scale;
+ final float a13 = msrc[0+4*2]*scale;
+ final float a23 = msrc[1+4*2]*scale;
+ final float a33 = msrc[2+4*2]*scale;
+ final float a43 = msrc[3+4*2]*scale;
+ final float a14 = msrc[0+4*3]*scale;
+ final float a24 = msrc[1+4*3]*scale;
+ final float a34 = msrc[2+4*3]*scale;
+ final float a44 = msrc[3+4*3]*scale;
+
+ final float m11 = + a22*(a33*a44 - a34*a43) - a23*(a32*a44 - a34*a42) + a24*(a32*a43 - a33*a42);
+ final float m12 = -( + a21*(a33*a44 - a34*a43) - a23*(a31*a44 - a34*a41) + a24*(a31*a43 - a33*a41));
+ final float m13 = + a21*(a32*a44 - a34*a42) - a22*(a31*a44 - a34*a41) + a24*(a31*a42 - a32*a41);
+ final float m14 = -( + a21*(a32*a43 - a33*a42) - a22*(a31*a43 - a33*a41) + a23*(a31*a42 - a32*a41));
+ final float m21 = -( + a12*(a33*a44 - a34*a43) - a13*(a32*a44 - a34*a42) + a14*(a32*a43 - a33*a42));
+ final float m22 = + a11*(a33*a44 - a34*a43) - a13*(a31*a44 - a34*a41) + a14*(a31*a43 - a33*a41);
+ final float m23 = -( + a11*(a32*a44 - a34*a42) - a12*(a31*a44 - a34*a41) + a14*(a31*a42 - a32*a41));
+ final float m24 = + a11*(a32*a43 - a33*a42) - a12*(a31*a43 - a33*a41) + a13*(a31*a42 - a32*a41);
+ final float m31 = + a12*(a23*a44 - a24*a43) - a13*(a22*a44 - a24*a42) + a14*(a22*a43 - a23*a42);
+ final float m32 = -( + a11*(a23*a44 - a24*a43) - a13*(a21*a44 - a24*a41) + a14*(a21*a43 - a23*a41));
+ final float m33 = + a11*(a22*a44 - a24*a42) - a12*(a21*a44 - a24*a41) + a14*(a21*a42 - a22*a41);
+ final float m34 = -( + a11*(a22*a43 - a23*a42) - a12*(a21*a43 - a23*a41) + a13*(a21*a42 - a22*a41));
+ final float m41 = -( + a12*(a23*a34 - a24*a33) - a13*(a22*a34 - a24*a32) + a14*(a22*a33 - a23*a32));
+ final float m42 = + a11*(a23*a34 - a24*a33) - a13*(a21*a34 - a24*a31) + a14*(a21*a33 - a23*a31);
+ final float m43 = -( + a11*(a22*a34 - a24*a32) - a12*(a21*a34 - a24*a31) + a14*(a21*a32 - a22*a31));
+ final float m44 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31);
+
+ final float det = (a11*m11 + a12*m12 + a13*m13 + a14*m14)/scale;
+
+ if( 0 == det ) {
+ return null;
+ }
+
+ mres[0+4*0] = m11 / det;
+ mres[1+4*0] = m12 / det;
+ mres[2+4*0] = m13 / det;
+ mres[3+4*0] = m14 / det;
+ mres[0+4*1] = m21 / det;
+ mres[1+4*1] = m22 / det;
+ mres[2+4*1] = m23 / det;
+ mres[3+4*1] = m24 / det;
+ mres[0+4*2] = m31 / det;
+ mres[1+4*2] = m32 / det;
+ mres[2+4*2] = m33 / det;
+ mres[3+4*2] = m34 / det;
+ mres[0+4*3] = m41 / det;
+ mres[1+4*3] = m42 / det;
+ mres[2+4*3] = m43 / det;
+ mres[3+4*3] = m44 / det;
+ return mres;
+ }
+
+ /**
+ * Map object coordinates to window coordinates.
+ * <p>
+ * Traditional <code>gluProject</code> implementation.
+ * </p>
+ *
+ * @param objx
+ * @param objy
+ * @param objz
+ * @param modelMatrix 4x4 modelview matrix
+ * @param modelMatrix_offset
+ * @param projMatrix 4x4 projection matrix
+ * @param projMatrix_offset
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param win_pos 3 component window coordinate, the result
+ * @param win_pos_offset
+ * @param vec4Tmp1 4 component vector for temp storage
+ * @param vec4Tmp2 4 component vector for temp storage
+ * @return true if successful, otherwise false (z is 1)
+ */
+ public static boolean mapObjToWinCoords(final float objx, final float objy, final float objz,
+ final float[] modelMatrix, final int modelMatrix_offset,
+ final float[] projMatrix, final int projMatrix_offset,
+ final int[] viewport, final int viewport_offset,
+ final float[] win_pos, final int win_pos_offset,
+ final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) {
+ vec4Tmp1[0] = objx;
+ vec4Tmp1[1] = objy;
+ vec4Tmp1[2] = objz;
+ vec4Tmp1[3] = 1.0f;
+
+ // vec4Tmp2 = Mv * o
+ // vec4Tmp1 = P * vec4Tmp2
+ // vec4Tmp1 = P * ( Mv * o )
+ // vec4Tmp1 = P * Mv * o
+ multMatrixVec(modelMatrix, modelMatrix_offset, vec4Tmp1, 0, vec4Tmp2, 0);
+ multMatrixVec(projMatrix, projMatrix_offset, vec4Tmp2, 0, vec4Tmp1, 0);
+
+ if (vec4Tmp1[3] == 0.0f) {
+ return false;
+ }
+
+ vec4Tmp1[3] = (1.0f / vec4Tmp1[3]) * 0.5f;
+
+ // Map x, y and z to range 0-1
+ vec4Tmp1[0] = vec4Tmp1[0] * vec4Tmp1[3] + 0.5f;
+ vec4Tmp1[1] = vec4Tmp1[1] * vec4Tmp1[3] + 0.5f;
+ vec4Tmp1[2] = vec4Tmp1[2] * vec4Tmp1[3] + 0.5f;
+
+ // Map x,y to viewport
+ win_pos[0+win_pos_offset] = vec4Tmp1[0] * viewport[2+viewport_offset] + viewport[0+viewport_offset];
+ win_pos[1+win_pos_offset] = vec4Tmp1[1] * viewport[3+viewport_offset] + viewport[1+viewport_offset];
+ win_pos[2+win_pos_offset] = vec4Tmp1[2];
+
+ return true;
+ }
+
+ /**
+ * Map object coordinates to window coordinates.
+ * <p>
+ * Traditional <code>gluProject</code> implementation.
+ * </p>
+ *
+ * @param objx
+ * @param objy
+ * @param objz
+ * @param mat4PMv [projection] x [modelview] matrix, i.e. P x Mv
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param win_pos 3 component window coordinate, the result
+ * @param win_pos_offset
+ * @param vec4Tmp1 4 component vector for temp storage
+ * @param vec4Tmp2 4 component vector for temp storage
+ * @return true if successful, otherwise false (z is 1)
+ */
+ public static boolean mapObjToWinCoords(final float objx, final float objy, final float objz,
+ final float[/*16*/] mat4PMv,
+ final int[] viewport, final int viewport_offset,
+ final float[] win_pos, final int win_pos_offset,
+ final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) {
+ vec4Tmp2[0] = objx;
+ vec4Tmp2[1] = objy;
+ vec4Tmp2[2] = objz;
+ vec4Tmp2[3] = 1.0f;
+
+ // vec4Tmp1 = P * Mv * o
+ multMatrixVec(mat4PMv, vec4Tmp2, vec4Tmp1);
+
+ if (vec4Tmp1[3] == 0.0f) {
+ return false;
+ }
+
+ vec4Tmp1[3] = (1.0f / vec4Tmp1[3]) * 0.5f;
+
+ // Map x, y and z to range 0-1
+ vec4Tmp1[0] = vec4Tmp1[0] * vec4Tmp1[3] + 0.5f;
+ vec4Tmp1[1] = vec4Tmp1[1] * vec4Tmp1[3] + 0.5f;
+ vec4Tmp1[2] = vec4Tmp1[2] * vec4Tmp1[3] + 0.5f;
+
+ // Map x,y to viewport
+ win_pos[0+win_pos_offset] = vec4Tmp1[0] * viewport[2+viewport_offset] + viewport[0+viewport_offset];
+ win_pos[1+win_pos_offset] = vec4Tmp1[1] * viewport[3+viewport_offset] + viewport[1+viewport_offset];
+ win_pos[2+win_pos_offset] = vec4Tmp1[2];
+
+ return true;
+ }
+
+ /**
+ * Map window coordinates to object coordinates.
+ * <p>
+ * Traditional <code>gluUnProject</code> implementation.
+ * </p>
+ *
+ * @param winx
+ * @param winy
+ * @param winz
+ * @param modelMatrix 4x4 modelview matrix
+ * @param modelMatrix_offset
+ * @param projMatrix 4x4 projection matrix
+ * @param projMatrix_offset
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param obj_pos 3 component object coordinate, the result
+ * @param obj_pos_offset
+ * @param mat4Tmp1 16 component matrix for temp storage
+ * @param mat4Tmp2 16 component matrix for temp storage
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
+ */
+ public static boolean mapWinToObjCoords(final float winx, final float winy, final float winz,
+ final float[] modelMatrix, final int modelMatrix_offset,
+ final float[] projMatrix, final int projMatrix_offset,
+ final int[] viewport, final int viewport_offset,
+ final float[] obj_pos, final int obj_pos_offset,
+ final float[/*16*/] mat4Tmp1, final float[/*16*/] mat4Tmp2) {
+ // mat4Tmp1 = P x Mv
+ multMatrix(projMatrix, projMatrix_offset, modelMatrix, modelMatrix_offset, mat4Tmp1, 0);
+
+ // mat4Tmp1 = Inv(P x Mv)
+ if ( null == invertMatrix(mat4Tmp1, mat4Tmp1) ) {
+ return false;
+ }
+ mat4Tmp2[0] = winx;
+ mat4Tmp2[1] = winy;
+ mat4Tmp2[2] = winz;
+ mat4Tmp2[3] = 1.0f;
+
+ // Map x and y from window coordinates
+ mat4Tmp2[0] = (mat4Tmp2[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset];
+ mat4Tmp2[1] = (mat4Tmp2[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset];
+
+ // Map to range -1 to 1
+ mat4Tmp2[0] = mat4Tmp2[0] * 2 - 1;
+ mat4Tmp2[1] = mat4Tmp2[1] * 2 - 1;
+ mat4Tmp2[2] = mat4Tmp2[2] * 2 - 1;
+
+ final int raw_off = 4;
+ // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2
+ multMatrixVec(mat4Tmp1, 0, mat4Tmp2, 0, mat4Tmp2, raw_off);
+
+ if (mat4Tmp2[3+raw_off] == 0.0) {
+ return false;
+ }
+
+ mat4Tmp2[3+raw_off] = 1.0f / mat4Tmp2[3+raw_off];
+
+ obj_pos[0+obj_pos_offset] = mat4Tmp2[0+raw_off] * mat4Tmp2[3+raw_off];
+ obj_pos[1+obj_pos_offset] = mat4Tmp2[1+raw_off] * mat4Tmp2[3+raw_off];
+ obj_pos[2+obj_pos_offset] = mat4Tmp2[2+raw_off] * mat4Tmp2[3+raw_off];
+
+ return true;
+ }
+
+ /**
+ * Map window coordinates to object coordinates.
+ * <p>
+ * Traditional <code>gluUnProject</code> implementation.
+ * </p>
+ *
+ * @param winx
+ * @param winy
+ * @param winz
+ * @param mat4PMvI inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv)
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param obj_pos 3 component object coordinate, the result
+ * @param obj_pos_offset
+ * @param vec4Tmp1 4 component vector for temp storage
+ * @param vec4Tmp2 4 component vector for temp storage
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
+ */
+ public static boolean mapWinToObjCoords(final float winx, final float winy, final float winz,
+ final float[/*16*/] mat4PMvI,
+ final int[] viewport, final int viewport_offset,
+ final float[] obj_pos, final int obj_pos_offset,
+ final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) {
+ vec4Tmp1[0] = winx;
+ vec4Tmp1[1] = winy;
+ vec4Tmp1[2] = winz;
+ vec4Tmp1[3] = 1.0f;
+
+ // Map x and y from window coordinates
+ vec4Tmp1[0] = (vec4Tmp1[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset];
+ vec4Tmp1[1] = (vec4Tmp1[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset];
+
+ // Map to range -1 to 1
+ vec4Tmp1[0] = vec4Tmp1[0] * 2 - 1;
+ vec4Tmp1[1] = vec4Tmp1[1] * 2 - 1;
+ vec4Tmp1[2] = vec4Tmp1[2] * 2 - 1;
+
+ // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2
+ multMatrixVec(mat4PMvI, vec4Tmp1, vec4Tmp2);
+
+ if (vec4Tmp2[3] == 0.0) {
+ return false;
+ }
+
+ vec4Tmp2[3] = 1.0f / vec4Tmp2[3];
+
+ obj_pos[0+obj_pos_offset] = vec4Tmp2[0] * vec4Tmp2[3];
+ obj_pos[1+obj_pos_offset] = vec4Tmp2[1] * vec4Tmp2[3];
+ obj_pos[2+obj_pos_offset] = vec4Tmp2[2] * vec4Tmp2[3];
+
+ return true;
+ }
+
+ /**
+ * Map two window coordinates to two object coordinates,
+ * distinguished by their z component.
+ *
+ * @param winx
+ * @param winy
+ * @param winz1
+ * @param winz2
+ * @param mat4PMvI inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv)
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param obj1_pos 3 component object coordinate, the result for winz1
+ * @param obj1_pos_offset
+ * @param obj2_pos 3 component object coordinate, the result for winz2
+ * @param obj2_pos_offset
+ * @param vec4Tmp1 4 component vector for temp storage
+ * @param vec4Tmp2 4 component vector for temp storage
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
+ */
+ public static boolean mapWinToObjCoords(final float winx, final float winy, final float winz1, final float winz2,
+ final float[/*16*/] mat4PMvI,
+ final int[] viewport, final int viewport_offset,
+ final float[] obj1_pos, final int obj1_pos_offset,
+ final float[] obj2_pos, final int obj2_pos_offset,
+ final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) {
+ vec4Tmp1[0] = winx;
+ vec4Tmp1[1] = winy;
+ vec4Tmp1[3] = 1.0f;
+
+ // Map x and y from window coordinates
+ vec4Tmp1[0] = (vec4Tmp1[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset];
+ vec4Tmp1[1] = (vec4Tmp1[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset];
+
+ // Map to range -1 to 1
+ vec4Tmp1[0] = vec4Tmp1[0] * 2 - 1;
+ vec4Tmp1[1] = vec4Tmp1[1] * 2 - 1;
+
+ //
+ // winz1
+ //
+ vec4Tmp1[2] = winz1;
+ vec4Tmp1[2] = vec4Tmp1[2] * 2 - 1;
+
+ // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2
+ multMatrixVec(mat4PMvI, vec4Tmp1, vec4Tmp2);
+
+ if (vec4Tmp2[3] == 0.0) {
+ return false;
+ }
+
+ vec4Tmp2[3] = 1.0f / vec4Tmp2[3];
+
+ obj1_pos[0+obj1_pos_offset] = vec4Tmp2[0] * vec4Tmp2[3];
+ obj1_pos[1+obj1_pos_offset] = vec4Tmp2[1] * vec4Tmp2[3];
+ obj1_pos[2+obj1_pos_offset] = vec4Tmp2[2] * vec4Tmp2[3];
+
+ //
+ // winz2
+ //
+ vec4Tmp1[2] = winz2;
+ vec4Tmp1[2] = vec4Tmp1[2] * 2 - 1;
+
+ // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2
+ multMatrixVec(mat4PMvI, vec4Tmp1, vec4Tmp2);
+
+ if (vec4Tmp2[3] == 0.0) {
+ return false;
+ }
+
+ vec4Tmp2[3] = 1.0f / vec4Tmp2[3];
+
+ obj2_pos[0+obj2_pos_offset] = vec4Tmp2[0] * vec4Tmp2[3];
+ obj2_pos[1+obj2_pos_offset] = vec4Tmp2[1] * vec4Tmp2[3];
+ obj2_pos[2+obj2_pos_offset] = vec4Tmp2[2] * vec4Tmp2[3];
+
+ return true;
+ }
+
+ /**
+ * Map window coordinates to object coordinates.
+ * <p>
+ * Traditional <code>gluUnProject4</code> implementation.
+ * </p>
+ *
+ * @param winx
+ * @param winy
+ * @param winz
+ * @param clipw
+ * @param modelMatrix 4x4 modelview matrix
+ * @param modelMatrix_offset
+ * @param projMatrix 4x4 projection matrix
+ * @param projMatrix_offset
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param near
+ * @param far
+ * @param obj_pos 4 component object coordinate, the result
+ * @param obj_pos_offset
+ * @param mat4Tmp1 16 component matrix for temp storage
+ * @param mat4Tmp2 16 component matrix for temp storage
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
+ */
+ public static boolean mapWinToObjCoords(final float winx, final float winy, final float winz, final float clipw,
+ final float[] modelMatrix, final int modelMatrix_offset,
+ final float[] projMatrix, final int projMatrix_offset,
+ final int[] viewport, final int viewport_offset,
+ final float near, final float far,
+ final float[] obj_pos, final int obj_pos_offset,
+ final float[/*16*/] mat4Tmp1, final float[/*16*/] mat4Tmp2) {
+ // mat4Tmp1 = P x Mv
+ multMatrix(projMatrix, projMatrix_offset, modelMatrix, modelMatrix_offset, mat4Tmp1, 0);
+
+ // mat4Tmp1 = Inv(P x Mv)
+ if ( null == invertMatrix(mat4Tmp1, mat4Tmp1) ) {
+ return false;
+ }
+
+ mat4Tmp2[0] = winx;
+ mat4Tmp2[1] = winy;
+ mat4Tmp2[2] = winz;
+ mat4Tmp2[3] = 1.0f;
+
+ // Map x and y from window coordinates
+ mat4Tmp2[0] = (mat4Tmp2[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset];
+ mat4Tmp2[1] = (mat4Tmp2[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset];
+ mat4Tmp2[2] = (mat4Tmp2[2] - near) / (far - near);
+
+ // Map to range -1 to 1
+ mat4Tmp2[0] = mat4Tmp2[0] * 2 - 1;
+ mat4Tmp2[1] = mat4Tmp2[1] * 2 - 1;
+ mat4Tmp2[2] = mat4Tmp2[2] * 2 - 1;
+
+ final int raw_off = 4;
+ // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2
+ multMatrixVec(mat4Tmp1, 0, mat4Tmp2, 0, mat4Tmp2, raw_off);
+
+ if (mat4Tmp2[3+raw_off] == 0.0) {
+ return false;
+ }
+
+ mat4Tmp2[3+raw_off] = 1.0f / mat4Tmp2[3+raw_off];
+
+ obj_pos[0+obj_pos_offset] = mat4Tmp2[0+raw_off];
+ obj_pos[1+obj_pos_offset] = mat4Tmp2[1+raw_off];
+ obj_pos[2+obj_pos_offset] = mat4Tmp2[2+raw_off];
+ obj_pos[3+obj_pos_offset] = mat4Tmp2[3+raw_off];
+
+ return true;
+ }
+
+
+ /**
+ * Map two window coordinates w/ shared X/Y and distinctive Z
+ * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i>
+ * using a {@link AABBox#getRayIntersection(Ray, float[]) bounding box}.
+ * <p>
+ * Notes for picking <i>winz0</i> and <i>winz1</i>:
+ * <ul>
+ * <li>see {@link #getZBufferEpsilon(int, float, float)}</li>
+ * <li>see {@link #getZBufferValue(int, float, float, float)}</li>
+ * <li>see {@link #getOrthoWinZ(float, float, float)}</li>
+ * </ul>
+ * </p>
+ * @param winx
+ * @param winy
+ * @param winz0
+ * @param winz1
+ * @param modelMatrix 4x4 modelview matrix
+ * @param modelMatrix_offset
+ * @param projMatrix 4x4 projection matrix
+ * @param projMatrix_offset
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param ray storage for the resulting {@link Ray}
+ * @param mat4Tmp1 16 component matrix for temp storage
+ * @param mat4Tmp2 16 component matrix for temp storage
+ * @param vec4Tmp2 4 component vector for temp storage
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
+ */
+ public static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1,
+ final float[] modelMatrix, final int modelMatrix_offset,
+ final float[] projMatrix, final int projMatrix_offset,
+ final int[] viewport, final int viewport_offset,
+ final Ray ray,
+ final float[/*16*/] mat4Tmp1, final float[/*16*/] mat4Tmp2, final float[/*4*/] vec4Tmp2) {
+ // mat4Tmp1 = P x Mv
+ multMatrix(projMatrix, projMatrix_offset, modelMatrix, modelMatrix_offset, mat4Tmp1, 0);
+
+ // mat4Tmp1 = Inv(P x Mv)
+ if ( null == invertMatrix(mat4Tmp1, mat4Tmp1) ) {
+ return false;
+ }
+ if( mapWinToObjCoords(winx, winy, winz0, winz1, mat4Tmp1,
+ viewport, viewport_offset,
+ ray.orig, 0, ray.dir, 0,
+ mat4Tmp2, vec4Tmp2) ) {
+ VectorUtil.normalizeVec3( VectorUtil.subVec3(ray.dir, ray.dir, ray.orig) );
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Multiply matrix: [d] = [a] x [b]
+ * @param a 4x4 matrix in column-major order
+ * @param b 4x4 matrix in column-major order
+ * @param d result a*b in column-major order
+ * @return given result matrix <i>d</i> for chaining
+ */
+ public static float[] multMatrix(final float[] a, final int a_off, final float[] b, final int b_off, final float[] d, final int d_off) {
+ final float b00 = b[b_off+0+0*4];
+ final float b10 = b[b_off+1+0*4];
+ final float b20 = b[b_off+2+0*4];
+ final float b30 = b[b_off+3+0*4];
+ final float b01 = b[b_off+0+1*4];
+ final float b11 = b[b_off+1+1*4];
+ final float b21 = b[b_off+2+1*4];
+ final float b31 = b[b_off+3+1*4];
+ final float b02 = b[b_off+0+2*4];
+ final float b12 = b[b_off+1+2*4];
+ final float b22 = b[b_off+2+2*4];
+ final float b32 = b[b_off+3+2*4];
+ final float b03 = b[b_off+0+3*4];
+ final float b13 = b[b_off+1+3*4];
+ final float b23 = b[b_off+2+3*4];
+ final float b33 = b[b_off+3+3*4];
+
+ float ai0=a[a_off+ 0*4]; // row-0 of a
+ float ai1=a[a_off+ 1*4];
+ float ai2=a[a_off+ 2*4];
+ float ai3=a[a_off+ 3*4];
+ d[d_off+ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ d[d_off+ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ d[d_off+ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ d[d_off+ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[a_off+1+0*4]; // row-1 of a
+ ai1=a[a_off+1+1*4];
+ ai2=a[a_off+1+2*4];
+ ai3=a[a_off+1+3*4];
+ d[d_off+1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ d[d_off+1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ d[d_off+1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ d[d_off+1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[a_off+2+0*4]; // row-2 of a
+ ai1=a[a_off+2+1*4];
+ ai2=a[a_off+2+2*4];
+ ai3=a[a_off+2+3*4];
+ d[d_off+2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ d[d_off+2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ d[d_off+2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ d[d_off+2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[a_off+3+0*4]; // row-3 of a
+ ai1=a[a_off+3+1*4];
+ ai2=a[a_off+3+2*4];
+ ai3=a[a_off+3+3*4];
+ d[d_off+3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ d[d_off+3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ d[d_off+3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ d[d_off+3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ return d;
+ }
+
+ /**
+ * Multiply matrix: [d] = [a] x [b]
+ * @param a 4x4 matrix in column-major order
+ * @param b 4x4 matrix in column-major order
+ * @param d result a*b in column-major order
+ * @return given result matrix <i>d</i> for chaining
+ */
+ public static float[] multMatrix(final float[] a, final float[] b, final float[] d) {
+ final float b00 = b[0+0*4];
+ final float b10 = b[1+0*4];
+ final float b20 = b[2+0*4];
+ final float b30 = b[3+0*4];
+ final float b01 = b[0+1*4];
+ final float b11 = b[1+1*4];
+ final float b21 = b[2+1*4];
+ final float b31 = b[3+1*4];
+ final float b02 = b[0+2*4];
+ final float b12 = b[1+2*4];
+ final float b22 = b[2+2*4];
+ final float b32 = b[3+2*4];
+ final float b03 = b[0+3*4];
+ final float b13 = b[1+3*4];
+ final float b23 = b[2+3*4];
+ final float b33 = b[3+3*4];
+
+ float ai0=a[ 0*4]; // row-0 of a
+ float ai1=a[ 1*4];
+ float ai2=a[ 2*4];
+ float ai3=a[ 3*4];
+ d[ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ d[ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ d[ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ d[ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[1+0*4]; // row-1 of a
+ ai1=a[1+1*4];
+ ai2=a[1+2*4];
+ ai3=a[1+3*4];
+ d[1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ d[1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ d[1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ d[1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[2+0*4]; // row-2 of a
+ ai1=a[2+1*4];
+ ai2=a[2+2*4];
+ ai3=a[2+3*4];
+ d[2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ d[2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ d[2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ d[2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[3+0*4]; // row-3 of a
+ ai1=a[3+1*4];
+ ai2=a[3+2*4];
+ ai3=a[3+3*4];
+ d[3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ d[3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ d[3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ d[3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ return d;
+ }
+
+ /**
+ * Multiply matrix: [a] = [a] x [b]
+ * @param a 4x4 matrix in column-major order (also result)
+ * @param b 4x4 matrix in column-major order
+ * @return given result matrix <i>a</i> for chaining
+ */
+ public static float[] multMatrix(final float[] a, final int a_off, final float[] b, final int b_off) {
+ final float b00 = b[b_off+0+0*4];
+ final float b10 = b[b_off+1+0*4];
+ final float b20 = b[b_off+2+0*4];
+ final float b30 = b[b_off+3+0*4];
+ final float b01 = b[b_off+0+1*4];
+ final float b11 = b[b_off+1+1*4];
+ final float b21 = b[b_off+2+1*4];
+ final float b31 = b[b_off+3+1*4];
+ final float b02 = b[b_off+0+2*4];
+ final float b12 = b[b_off+1+2*4];
+ final float b22 = b[b_off+2+2*4];
+ final float b32 = b[b_off+3+2*4];
+ final float b03 = b[b_off+0+3*4];
+ final float b13 = b[b_off+1+3*4];
+ final float b23 = b[b_off+2+3*4];
+ final float b33 = b[b_off+3+3*4];
+
+ float ai0=a[a_off+ 0*4]; // row-0 of a
+ float ai1=a[a_off+ 1*4];
+ float ai2=a[a_off+ 2*4];
+ float ai3=a[a_off+ 3*4];
+ a[a_off+ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ a[a_off+ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ a[a_off+ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ a[a_off+ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[a_off+1+0*4]; // row-1 of a
+ ai1=a[a_off+1+1*4];
+ ai2=a[a_off+1+2*4];
+ ai3=a[a_off+1+3*4];
+ a[a_off+1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ a[a_off+1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ a[a_off+1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ a[a_off+1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[a_off+2+0*4]; // row-2 of a
+ ai1=a[a_off+2+1*4];
+ ai2=a[a_off+2+2*4];
+ ai3=a[a_off+2+3*4];
+ a[a_off+2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ a[a_off+2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ a[a_off+2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ a[a_off+2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[a_off+3+0*4]; // row-3 of a
+ ai1=a[a_off+3+1*4];
+ ai2=a[a_off+3+2*4];
+ ai3=a[a_off+3+3*4];
+ a[a_off+3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ a[a_off+3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ a[a_off+3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ a[a_off+3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ return a;
+ }
+
+ /**
+ * Multiply matrix: [a] = [a] x [b]
+ * @param a 4x4 matrix in column-major order (also result)
+ * @param b 4x4 matrix in column-major order
+ * @return given result matrix <i>a</i> for chaining
+ */
+ public static float[] multMatrix(final float[] a, final float[] b) {
+ final float b00 = b[0+0*4];
+ final float b10 = b[1+0*4];
+ final float b20 = b[2+0*4];
+ final float b30 = b[3+0*4];
+ final float b01 = b[0+1*4];
+ final float b11 = b[1+1*4];
+ final float b21 = b[2+1*4];
+ final float b31 = b[3+1*4];
+ final float b02 = b[0+2*4];
+ final float b12 = b[1+2*4];
+ final float b22 = b[2+2*4];
+ final float b32 = b[3+2*4];
+ final float b03 = b[0+3*4];
+ final float b13 = b[1+3*4];
+ final float b23 = b[2+3*4];
+ final float b33 = b[3+3*4];
+
+ float ai0=a[ 0*4]; // row-0 of a
+ float ai1=a[ 1*4];
+ float ai2=a[ 2*4];
+ float ai3=a[ 3*4];
+ a[ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ a[ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ a[ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ a[ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[1+0*4]; // row-1 of a
+ ai1=a[1+1*4];
+ ai2=a[1+2*4];
+ ai3=a[1+3*4];
+ a[1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ a[1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ a[1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ a[1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[2+0*4]; // row-2 of a
+ ai1=a[2+1*4];
+ ai2=a[2+2*4];
+ ai3=a[2+3*4];
+ a[2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ a[2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ a[2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ a[2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ ai0=a[3+0*4]; // row-3 of a
+ ai1=a[3+1*4];
+ ai2=a[3+2*4];
+ ai3=a[3+3*4];
+ a[3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
+ a[3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
+ a[3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
+ a[3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
+
+ return a;
+ }
+
+ /**
+ * Multiply matrix: [d] = [a] x [b]
+ * @param a 4x4 matrix in column-major order
+ * @param b 4x4 matrix in column-major order
+ * @param d result a*b in column-major order
+ * @deprecated use on of the float[] variants
+ */
+ public static void multMatrix(final FloatBuffer a, final FloatBuffer b, final float[] d) {
+ final int a_off = a.position();
+ final int b_off = b.position();
+ for (int i = 0; i < 4; i++) {
+ // one row in column-major order
+ final int a_off_i = a_off+i;
+ final float ai0=a.get(a_off_i+0*4), ai1=a.get(a_off_i+1*4), ai2=a.get(a_off_i+2*4), ai3=a.get(a_off_i+3*4); // row-i of a
+ d[i+0*4] = ai0 * b.get(b_off+0+0*4) + ai1 * b.get(b_off+1+0*4) + ai2 * b.get(b_off+2+0*4) + ai3 * b.get(b_off+3+0*4) ;
+ d[i+1*4] = ai0 * b.get(b_off+0+1*4) + ai1 * b.get(b_off+1+1*4) + ai2 * b.get(b_off+2+1*4) + ai3 * b.get(b_off+3+1*4) ;
+ d[i+2*4] = ai0 * b.get(b_off+0+2*4) + ai1 * b.get(b_off+1+2*4) + ai2 * b.get(b_off+2+2*4) + ai3 * b.get(b_off+3+2*4) ;
+ d[i+3*4] = ai0 * b.get(b_off+0+3*4) + ai1 * b.get(b_off+1+3*4) + ai2 * b.get(b_off+2+3*4) + ai3 * b.get(b_off+3+3*4) ;
+ }
+ }
+
+ /**
+ * Multiply matrix: [a] = [a] x [b]
+ * @param a 4x4 matrix in column-major order (also result)
+ * @param b 4x4 matrix in column-major order
+ * @deprecated use on of the float[] variants
+ */
+ public static void multMatrix(final FloatBuffer a, final FloatBuffer b) {
+ final int a_off = a.position();
+ final int b_off = b.position();
+ for (int i = 0; i < 4; i++) {
+ // one row in column-major order
+ final int a_off_i = a_off+i;
+ final float ai0=a.get(a_off_i+0*4), ai1=a.get(a_off_i+1*4), ai2=a.get(a_off_i+2*4), ai3=a.get(a_off_i+3*4); // row-i of a
+ a.put(a_off_i+0*4 , ai0 * b.get(b_off+0+0*4) + ai1 * b.get(b_off+1+0*4) + ai2 * b.get(b_off+2+0*4) + ai3 * b.get(b_off+3+0*4) );
+ a.put(a_off_i+1*4 , ai0 * b.get(b_off+0+1*4) + ai1 * b.get(b_off+1+1*4) + ai2 * b.get(b_off+2+1*4) + ai3 * b.get(b_off+3+1*4) );
+ a.put(a_off_i+2*4 , ai0 * b.get(b_off+0+2*4) + ai1 * b.get(b_off+1+2*4) + ai2 * b.get(b_off+2+2*4) + ai3 * b.get(b_off+3+2*4) );
+ a.put(a_off_i+3*4 , ai0 * b.get(b_off+0+3*4) + ai1 * b.get(b_off+1+3*4) + ai2 * b.get(b_off+2+3*4) + ai3 * b.get(b_off+3+3*4) );
+ }
+ }
+
+ /**
+ * @param m_in 4x4 matrix in column-major order
+ * @param m_in_off
+ * @param v_in 4-component column-vector
+ * @param v_out m_in * v_in
+ * @return given result vector <i>v_out</i> for chaining
+ */
+ public static float[] multMatrixVec(final float[] m_in, final int m_in_off,
+ final float[] v_in, final int v_in_off,
+ final float[] v_out, final int v_out_off) {
+ // (one matrix row in column-major order) X (column vector)
+ v_out[0 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off ] + v_in[1+v_in_off] * m_in[1*4+m_in_off ] +
+ v_in[2+v_in_off] * m_in[2*4+m_in_off ] + v_in[3+v_in_off] * m_in[3*4+m_in_off ];
+
+ final int m_in_off_1 = 1+m_in_off;
+ v_out[1 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off_1] + v_in[1+v_in_off] * m_in[1*4+m_in_off_1] +
+ v_in[2+v_in_off] * m_in[2*4+m_in_off_1] + v_in[3+v_in_off] * m_in[3*4+m_in_off_1];
+
+ final int m_in_off_2 = 2+m_in_off;
+ v_out[2 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off_2] + v_in[1+v_in_off] * m_in[1*4+m_in_off_2] +
+ v_in[2+v_in_off] * m_in[2*4+m_in_off_2] + v_in[3+v_in_off] * m_in[3*4+m_in_off_2];
+
+ final int m_in_off_3 = 3+m_in_off;
+ v_out[3 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off_3] + v_in[1+v_in_off] * m_in[1*4+m_in_off_3] +
+ v_in[2+v_in_off] * m_in[2*4+m_in_off_3] + v_in[3+v_in_off] * m_in[3*4+m_in_off_3];
+
+ return v_out;
+ }
+
+ /**
+ * @param m_in 4x4 matrix in column-major order
+ * @param m_in_off
+ * @param v_in 4-component column-vector
+ * @param v_out m_in * v_in
+ * @return given result vector <i>v_out</i> for chaining
+ */
+ public static float[] multMatrixVec(final float[] m_in, final float[] v_in, final float[] v_out) {
+ // (one matrix row in column-major order) X (column vector)
+ v_out[0] = v_in[0] * m_in[0*4 ] + v_in[1] * m_in[1*4 ] +
+ v_in[2] * m_in[2*4 ] + v_in[3] * m_in[3*4 ];
+
+ v_out[1] = v_in[0] * m_in[0*4+1] + v_in[1] * m_in[1*4+1] +
+ v_in[2] * m_in[2*4+1] + v_in[3] * m_in[3*4+1];
+
+ v_out[2] = v_in[0] * m_in[0*4+2] + v_in[1] * m_in[1*4+2] +
+ v_in[2] * m_in[2*4+2] + v_in[3] * m_in[3*4+2];
+
+ v_out[3] = v_in[0] * m_in[0*4+3] + v_in[1] * m_in[1*4+3] +
+ v_in[2] * m_in[2*4+3] + v_in[3] * m_in[3*4+3];
+
+ return v_out;
+ }
+
+ /**
+ * @param m_in 4x4 matrix in column-major order
+ * @param v_in 4-component column-vector
+ * @param v_out m_in * v_in
+ * @deprecated use on of the float[] variants
+ */
+ public static void multMatrixVec(final FloatBuffer m_in, final float[] v_in, final float[] v_out) {
+ final int m_in_off = m_in.position();
+ for (int i = 0; i < 4; i++) {
+ // (one matrix row in column-major order) X (column vector)
+ final int i_m_in_off = i+m_in_off;
+ v_out[i] =
+ v_in[0] * m_in.get(0*4+i_m_in_off) +
+ v_in[1] * m_in.get(1*4+i_m_in_off) +
+ v_in[2] * m_in.get(2*4+i_m_in_off) +
+ v_in[3] * m_in.get(3*4+i_m_in_off);
+ }
+ }
+
+ /**
+ * Copy the named column of the given column-major matrix to v_out.
+ * <p>
+ * v_out may be 3 or 4 components long, hence the 4th row may not be stored.
+ * </p>
+ * @param m_in input column-major matrix
+ * @param m_in_off offset to input matrix
+ * @param column named column to copy
+ * @param v_out the column-vector storage, at least 3 components long
+ * @param v_out_off offset to storage
+ * @return given result vector <i>v_out</i> for chaining
+ */
+ public static float[] copyMatrixColumn(final float[] m_in, final int m_in_off, final int column, final float[] v_out, final int v_out_off) {
+ v_out[0+v_out_off]=m_in[0+column*4+m_in_off];
+ v_out[1+v_out_off]=m_in[1+column*4+m_in_off];
+ v_out[2+v_out_off]=m_in[2+column*4+m_in_off];
+ if( v_out.length > 3+v_out_off ) {
+ v_out[3+v_out_off]=m_in[3+column*4+m_in_off];
+ }
+ return v_out;
+ }
+
+ /**
+ * Copy the named row of the given column-major matrix to v_out.
+ * <p>
+ * v_out may be 3 or 4 components long, hence the 4th column may not be stored.
+ * </p>
+ * @param m_in input column-major matrix
+ * @param m_in_off offset to input matrix
+ * @param row named row to copy
+ * @param v_out the row-vector storage, at least 3 components long
+ * @param v_out_off offset to storage
+ * @return given result vector <i>v_out</i> for chaining
+ */
+ public static float[] copyMatrixRow(final float[] m_in, final int m_in_off, final int row, final float[] v_out, final int v_out_off) {
+ v_out[0+v_out_off]=m_in[row+0*4+m_in_off];
+ v_out[1+v_out_off]=m_in[row+1*4+m_in_off];
+ v_out[2+v_out_off]=m_in[row+2*4+m_in_off];
+ if( v_out.length > 3+v_out_off ) {
+ v_out[3+v_out_off]=m_in[row+3*4+m_in_off];
+ }
+ return v_out;
+ }
+
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param a mxn matrix (rows x columns)
+ * @param aOffset offset to <code>a</code>'s current position
+ * @param rows
+ * @param columns
+ * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
+ * @param row row number to print
+ * @return matrix row string representation
+ * @deprecated use on of the float[] variants
+ */
+ public static StringBuilder matrixRowToString(StringBuilder sb, final String f,
+ final FloatBuffer a, final int aOffset,
+ final int rows, final int columns, final boolean rowMajorOrder, final int row) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ final int a0 = aOffset + a.position();
+ if(rowMajorOrder) {
+ for(int c=0; c<columns; c++) {
+ sb.append( String.format( f+" ", a.get( a0 + row*columns + c ) ) );
+ }
+ } else {
+ for(int r=0; r<columns; r++) {
+ sb.append( String.format( f+" ", a.get( a0 + row + r*rows ) ) );
+ }
+ }
+ return sb;
+ }
+
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param a mxn matrix (rows x columns)
+ * @param aOffset offset to <code>a</code>'s current position
+ * @param rows
+ * @param columns
+ * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
+ * @param row row number to print
+ * @return matrix row string representation
+ */
+ public static StringBuilder matrixRowToString(StringBuilder sb, final String f,
+ final float[] a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder, final int row) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ if(rowMajorOrder) {
+ for(int c=0; c<columns; c++) {
+ sb.append( String.format( f+" ", a[ aOffset + row*columns + c ] ) );
+ }
+ } else {
+ for(int r=0; r<columns; r++) {
+ sb.append( String.format( f+" ", a[ aOffset + row + r*rows ] ) );
+ }
+ }
+ return sb;
+ }
+
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param rowPrefix optional prefix for each row
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param a mxn matrix (rows x columns)
+ * @param aOffset offset to <code>a</code>'s current position
+ * @param rows
+ * @param columns
+ * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
+ * @return matrix string representation
+ * @deprecated use on of the float[] variants
+ */
+ public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f,
+ final FloatBuffer a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ final String prefix = ( null == rowPrefix ) ? "" : rowPrefix;
+ for(int i=0; i<rows; i++) {
+ sb.append(prefix).append("[ ");
+ matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i);
+ sb.append("]").append(Platform.getNewline());
+ }
+ return sb;
+ }
+
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param rowPrefix optional prefix for each row
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param a mxn matrix (rows x columns)
+ * @param aOffset offset to <code>a</code>'s current position
+ * @param rows
+ * @param columns
+ * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
+ * @return matrix string representation
+ */
+ public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f,
+ final float[] a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ final String prefix = ( null == rowPrefix ) ? "" : rowPrefix;
+ for(int i=0; i<rows; i++) {
+ sb.append(prefix).append("[ ");
+ matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i);
+ sb.append("]").append(Platform.getNewline());
+ }
+ return sb;
+ }
+
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param rowPrefix optional prefix for each row
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param a 4x4 matrix in column major order (OpenGL)
+ * @param aOffset offset to <code>a</code>'s current position
+ * @param b 4x4 matrix in column major order (OpenGL)
+ * @param bOffset offset to <code>a</code>'s current position
+ * @param rows
+ * @param columns
+ * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
+ * @return side by side representation
+ * @deprecated use on of the float[] variants
+ */
+ public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f,
+ final FloatBuffer a, final int aOffset, final FloatBuffer b, final int bOffset,
+ final int rows, final int columns, final boolean rowMajorOrder) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ final String prefix = ( null == rowPrefix ) ? "" : rowPrefix;
+ for(int i=0; i<rows; i++) {
+ sb.append(prefix).append("[ ");
+ matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i);
+ sb.append("=?= ");
+ matrixRowToString(sb, f, b, bOffset, rows, columns, rowMajorOrder, i);
+ sb.append("]").append(Platform.getNewline());
+ }
+ return sb;
+ }
+
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param rowPrefix optional prefix for each row
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param a 4x4 matrix in column major order (OpenGL)
+ * @param aOffset offset to <code>a</code>'s current position
+ * @param b 4x4 matrix in column major order (OpenGL)
+ * @param bOffset offset to <code>a</code>'s current position
+ * @param rows
+ * @param columns
+ * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
+ * @return side by side representation
+ */
+ public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f,
+ final float[] a, final int aOffset, final float[] b, final int bOffset,
+ final int rows, final int columns, final boolean rowMajorOrder) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ final String prefix = ( null == rowPrefix ) ? "" : rowPrefix;
+ for(int i=0; i<rows; i++) {
+ sb.append(prefix).append("[ ");
+ matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i);
+ sb.append("=?= ");
+ matrixRowToString(sb, f, b, bOffset, rows, columns, rowMajorOrder, i);
+ sb.append("]").append(Platform.getNewline());
+ }
+ return sb;
+ }
+
+ //
+ // Scalar Ops
+ //
+
+ @SuppressWarnings("unused")
+ private static void calculateMachineEpsilonFloat() {
+ final long t0;
+ if( DEBUG_EPSILON ) {
+ t0 = Platform.currentTimeMillis();
+ }
+ float machEps = 1.0f;
+ int i=0;
+ do {
+ machEps /= 2.0f;
+ i++;
+ } while (1.0f + (machEps / 2.0f) != 1.0f);
+ machEpsilon = machEps;
+ if( DEBUG_EPSILON ) {
+ final long t1 = Platform.currentTimeMillis();
+ System.err.println("MachineEpsilon: "+machEpsilon+", in "+i+" iterations within "+(t1-t0)+" ms");
+ }
+ }
+ private static volatile boolean machEpsilonAvail = false;
+ private static float machEpsilon = 0f;
+ private static final boolean DEBUG_EPSILON = false;
+
+ /**
+ * Return computed machine Epsilon value.
+ * <p>
+ * The machine Epsilon value is computed once.
+ * </p>
+ * <p>
+ * On a reference machine the result was {@link #EPSILON} in 23 iterations.
+ * </p>
+ * @see #EPSILON
+ */
+ public static float getMachineEpsilon() {
+ if( !machEpsilonAvail ) {
+ synchronized(FloatUtil.class) {
+ if( !machEpsilonAvail ) {
+ machEpsilonAvail = true;
+ calculateMachineEpsilonFloat();
+ }
+ }
+ }
+ return machEpsilon;
+ }
+
+ public static final float E = 2.7182818284590452354f;
+
+ /** The value PI, i.e. 180 degrees in radians. */
+ public static final float PI = 3.14159265358979323846f;
+
+ /** The value 2PI, i.e. 360 degrees in radians. */
+ public static final float TWO_PI = 2f * PI;
+
+ /** The value PI/2, i.e. 90 degrees in radians. */
+ public static final float HALF_PI = PI / 2f;
+
+ /** The value PI/4, i.e. 45 degrees in radians. */
+ public static final float QUARTER_PI = PI / 4f;
+
+ /** The value PI^2. */
+ public final static float SQUARED_PI = PI * PI;
+
+ /**
+ * Epsilon for floating point {@value}, as once computed via {@link #getMachineEpsilon()} on an AMD-64 CPU.
+ * <p>
+ * Definition of machine epsilon guarantees that:
+ * <pre>
+ * 1.0f + EPSILON != 1.0f
+ * </pre>
+ * In other words: <i>machEps</i> is the maximum relative error of the chosen rounding procedure.
+ * </p>
+ * <p>
+ * A number can be considered zero if it is in the range (or in the set):
+ * <pre>
+ * <b>MaybeZeroSet</b> e ]-<i>machEps</i> .. <i>machEps</i>[ <i>(exclusive)</i>
+ * </pre>
+ * While comparing floating point values, <i>machEps</i> allows to clip the relative error:
+ * <pre>
+ * boolean isZero = afloat < EPSILON;
+ * boolean isNotZero = afloat >= EPSILON;
+ *
+ * boolean isEqual = abs(bfloat - afloat) < EPSILON;
+ * boolean isNotEqual = abs(bfloat - afloat) >= EPSILON;
+ * </pre>
+ * </p>
+ * @see #isEqual(float, float, float)
+ * @see #isZero(float, float)
+ */
+ public static final float EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d
+
+ /**
+ * Inversion Epsilon, used with equals method to determine if two inverted matrices are close enough to be considered equal.
+ * <p>
+ * Using {@value}, which is ~100 times {@link FloatUtil#EPSILON}.
+ * </p>
+ */
+ public static final float INV_DEVIANCE = 1.0E-5f; // FloatUtil.EPSILON == 1.1920929E-7f; double ALLOWED_DEVIANCE: 1.0E-8f
+
+ /**
+ * Return true if both values are equal w/o regarding an epsilon.
+ * <p>
+ * Implementation considers following corner cases:
+ * <ul>
+ * <li>NaN == NaN</li>
+ * <li>+Inf == +Inf</li>
+ * <li>-Inf == -Inf</li>
+ * </ul>
+ * </p>
+ * @see #isEqual(float, float, float)
+ */
+ public static boolean isEqual(final float a, final float b) {
+ // Values are equal (Inf, Nan .. )
+ return Float.floatToIntBits(a) == Float.floatToIntBits(b);
+ }
+
+ /**
+ * Return true if both values are equal, i.e. their absolute delta < <code>epsilon</code>.
+ * <p>
+ * Implementation considers following corner cases:
+ * <ul>
+ * <li>NaN == NaN</li>
+ * <li>+Inf == +Inf</li>
+ * <li>-Inf == -Inf</li>
+ * </ul>
+ * </p>
+ * @see #EPSILON
+ */
+ public static boolean isEqual(final float a, final float b, final float epsilon) {
+ if ( Math.abs(a - b) < epsilon ) {
+ return true;
+ } else {
+ // Values are equal (Inf, Nan .. )
+ return Float.floatToIntBits(a) == Float.floatToIntBits(b);
+ }
+ }
+
+ /**
+ * Return true if both values are equal w/o regarding an epsilon.
+ * <p>
+ * Implementation considers following corner cases:
+ * <ul>
+ * <li>NaN == NaN</li>
+ * <li>+Inf == +Inf</li>
+ * <li>-Inf == -Inf</li>
+ * <li>NaN > 0</li>
+ * <li>+Inf > -Inf</li>
+ * </ul>
+ * </p>
+ * @see #compare(float, float, float)
+ */
+ public static int compare(final float a, final float b) {
+ if (a < b) {
+ return -1; // Neither is NaN, a is smaller
+ }
+ if (a > b) {
+ return 1; // Neither is NaN, a is larger
+ }
+ final int aBits = Float.floatToIntBits(a);
+ final int bBits = Float.floatToIntBits(b);
+ if( aBits == bBits ) {
+ return 0; // Values are equal (Inf, Nan .. )
+ } else if( aBits < bBits ) {
+ return -1; // (-0.0, 0.0) or (!NaN, NaN)
+ } else {
+ return 1; // ( 0.0, -0.0) or ( NaN, !NaN)
+ }
+ }
+
+ /**
+ * Return true if both values are equal, i.e. their absolute delta < <code>epsilon</code>.
+ * <p>
+ * Implementation considers following corner cases:
+ * <ul>
+ * <li>NaN == NaN</li>
+ * <li>+Inf == +Inf</li>
+ * <li>-Inf == -Inf</li>
+ * <li>NaN > 0</li>
+ * <li>+Inf > -Inf</li>
+ * </ul>
+ * </p>
+ * @see #EPSILON
+ */
+ public static int compare(final float a, final float b, final float epsilon) {
+ if ( Math.abs(a - b) < epsilon ) {
+ return 0;
+ } else {
+ return compare(a, b);
+ }
+ }
+
+ /**
+ * Return true if value is zero, i.e. it's absolute value < <code>epsilon</code>.
+ * @see #EPSILON
+ */
+ public static boolean isZero(final float a, final float epsilon) {
+ return Math.abs(a) < epsilon;
+ }
+
+ public static float abs(final float a) { return java.lang.Math.abs(a); }
+
+ public static float pow(final float a, final float b) { return (float) java.lang.Math.pow(a, b); }
+
+ public static float sin(final float a) { return (float) java.lang.Math.sin(a); }
+
+ public static float asin(final float a) { return (float) java.lang.Math.asin(a); }
+
+ public static float cos(final float a) { return (float) java.lang.Math.cos(a); }
+
+ public static float acos(final float a) { return (float) java.lang.Math.acos(a); }
+
+ public static float tan(final float a) { return (float) java.lang.Math.tan(a); }
+
+ public static float atan(final float a) { return (float) java.lang.Math.atan(a); }
+
+ public static float atan2(final float y, final float x) { return (float) java.lang.Math.atan2(y, x); }
+
+ public static float sqrt(final float a) { return (float) java.lang.Math.sqrt(a); }
+
+ /**
+ * Returns resolution of Z buffer of given parameter,
+ * see <a href="http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html">Love Your Z-Buffer</a>.
+ * <pre>
+ * return z * z / ( zNear * (1&lt;&lt;zBits) - z )
+ * </pre>
+ * @param zBits number of bits of Z precision, i.e. z-buffer depth
+ * @param z distance from the eye to the object
+ * @param zNear distance from eye to near clip plane
+ * @return smallest resolvable Z separation at this range.
+ */
+ public static float getZBufferEpsilon(final int zBits, final float z, final float zNear) {
+ return z * z / ( zNear * ( 1 << zBits ) - z );
+ }
+
+ /**
+ * Returns Z buffer value of given parameter,
+ * see <a href="http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html">Love Your Z-Buffer</a>.
+ * <pre>
+ * float a = zFar / ( zFar - zNear )
+ * float b = zFar * zNear / ( zNear - zFar )
+ * return (int) ( (1&lt;&lt;zBits) * ( a + b / z ) )
+ * </pre>
+ * @param zBits number of bits of Z precision, i.e. z-buffer depth
+ * @param z distance from the eye to the object
+ * @param zNear distance from eye to near clip plane
+ * @param zFar distance from eye to far clip plane
+ * @return z buffer value
+ */
+ public static int getZBufferValue(final int zBits, final float z, final float zNear, final float zFar) {
+ final float a = zFar / ( zFar - zNear );
+ final float b = zFar * zNear / ( zNear - zFar );
+ return (int) ( (1<<zBits) * ( a + b / z ) );
+ }
+
+ /**
+ * Returns orthogonal distance
+ * (1f/zNear-1f/orthoDist)/(1f/zNear-1f/zFar);
+ */
+ public static float getOrthoWinZ(final float orthoZ, final float zNear, final float zFar) {
+ return (1f/zNear-1f/orthoZ)/(1f/zNear-1f/zFar);
+ }
+
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java b/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java
new file mode 100644
index 000000000..26ed57009
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java
@@ -0,0 +1,182 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.math;
+
+/**
+ * Horizontal and vertical field of view (FOV) halves,
+ * allowing a non-centered projection.
+ * <p>
+ * The values might be either in tangent or radians.
+ * </p>
+ */
+public final class FovHVHalves {
+ /** Half horizontal FOV from center to left. */
+ public final float left;
+ /** Half horizontal FOV from center to right. */
+ public final float right;
+ /** Half vertical FOV from center to top. */
+ public final float top;
+ /** Half vertical FOV from center to bottom. */
+ public final float bottom;
+ /** If true, values are in tangent, otherwise radians.*/
+ public final boolean inTangents;
+
+ /**
+ * Constructor for one {@link FovHVHalves} instance.
+ * <p>
+ * It is recommended to pass and store values in tangent
+ * if used for perspective FOV calculations, since it will avoid conversion to tangent later on.
+ * </p>
+ * @param left half horizontal FOV, left side, in tangent or radians
+ * @param right half horizontal FOV, right side, in tangent or radians
+ * @param top half vertical FOV, top side, in tangent or radians
+ * @param bottom half vertical FOV, bottom side, in tangent or radians
+ * @param inTangents if true, values are in tangent, otherwise radians
+ */
+ public FovHVHalves(final float left, final float right, final float top, final float bottom, final boolean inTangents) {
+ this.left = left;
+ this.right = right;
+ this.top = top;
+ this.bottom = bottom;
+ this.inTangents = inTangents;
+ }
+
+ /**
+ * Returns a symmetrical centered {@link FovHVHalves} instance in tangents, using:
+ * <pre>
+ halfHorizFovTan = tan( horizontalFov / 2f );
+ halfVertFovTan = tan( verticalFov / 2f );
+ * </pre>
+ * @param horizontalFov whole horizontal FOV in radians
+ * @param verticalFov whole vertical FOV in radians
+ */
+ public static FovHVHalves byRadians(final float horizontalFov, final float verticalFov) {
+ final float halfHorizFovTan = FloatUtil.tan(horizontalFov/2f);
+ final float halfVertFovTan = FloatUtil.tan(verticalFov/2f);
+ return new FovHVHalves(halfHorizFovTan, halfHorizFovTan, halfVertFovTan, halfVertFovTan, true);
+ }
+
+ /**
+ * Returns a symmetrical centered {@link FovHVHalves} instance in tangents, using:
+ * <pre>
+ top = bottom = tan( verticalFov / 2f );
+ left = right = aspect * top;
+ * </pre>
+ *
+ * @param verticalFov vertical FOV in radians
+ * @param aspect aspect ration width / height
+ */
+ public static FovHVHalves byFovyRadianAndAspect(final float verticalFov, final float aspect) {
+ final float halfVertFovTan = FloatUtil.tan(verticalFov/2f);
+ final float halfHorizFovTan = aspect * halfVertFovTan;
+ return new FovHVHalves(halfHorizFovTan, halfHorizFovTan,
+ halfVertFovTan, halfVertFovTan, true);
+ }
+
+ /**
+ * Returns a custom symmetry {@link FovHVHalves} instance in tangents, using:
+ * <pre>
+ left = tan( horizontalFov * horizCenterFromLeft )
+ right = tan( horizontalFov * ( 1f - horizCenterFromLeft ) )
+ top = tan( verticalFov * vertCenterFromTop )
+ bottom = tan( verticalFov * (1f - vertCenterFromTop ) )
+ * </pre>
+ * @param horizontalFov whole horizontal FOV in radians
+ * @param horizCenterFromLeft horizontal center from left in [0..1]
+ * @param verticalFov whole vertical FOV in radians
+ * @param vertCenterFromTop vertical center from top in [0..1]
+ */
+ public static FovHVHalves byRadians(final float horizontalFov, final float horizCenterFromLeft,
+ final float verticalFov, final float vertCenterFromTop) {
+ return new FovHVHalves(FloatUtil.tan(horizontalFov * horizCenterFromLeft),
+ FloatUtil.tan(horizontalFov * ( 1f - horizCenterFromLeft )),
+ FloatUtil.tan(verticalFov * vertCenterFromTop),
+ FloatUtil.tan(verticalFov * (1f - vertCenterFromTop )),
+ true);
+ }
+
+ /**
+ * Returns a custom symmetry {@link FovHVHalves} instance in tangents,
+ * via computing the <code>horizontalFov</code> using:
+ * <pre>
+ halfVertFovTan = tan( verticalFov / 2f );
+ halfHorizFovTan = aspect * halfVertFovTan;
+ horizontalFov = atan( halfHorizFovTan ) * 2f;
+ return {@link #byRadians(float, float, float, float) byRadians}(horizontalFov, horizCenterFromLeft, verticalFov, vertCenterFromTop)
+ * </pre>
+ * @param verticalFov whole vertical FOV in radians
+ * @param vertCenterFromTop vertical center from top in [0..1]
+ * @param aspect aspect ration width / height
+ * @param horizCenterFromLeft horizontal center from left in [0..1]
+ */
+ public static FovHVHalves byFovyRadianAndAspect(final float verticalFov, final float vertCenterFromTop,
+ final float aspect, final float horizCenterFromLeft) {
+ final float halfVertFovTan = FloatUtil.tan(verticalFov/2f);
+ final float halfHorizFovTan = aspect * halfVertFovTan;
+ final float horizontalFov = FloatUtil.atan(halfHorizFovTan) * 2f;
+ return byRadians(horizontalFov, horizCenterFromLeft, verticalFov, vertCenterFromTop);
+ }
+
+ /**
+ * Returns this instance <i>in tangent</i> values.
+ * <p>
+ * If this instance is {@link #inTangents} already, method returns this instance,
+ * otherwise a newly created instance w/ converted values to tangent.
+ * </p>
+ */
+ public final FovHVHalves toTangents() {
+ if( inTangents ) {
+ return this;
+ } else {
+ return new FovHVHalves(FloatUtil.tan(left), FloatUtil.tan(right), FloatUtil.tan(top), FloatUtil.tan(bottom), true);
+ }
+ }
+
+ /** Returns the full horizontal FOV, i.e. {@link #left} + {@link #right}. */
+ public final float horzFov() { return left+right; }
+
+ /** Returns the full vertical FOV, i.e. {@link #top} + {@link #bottom}. */
+ public final float vertFov() { return top+bottom; }
+
+ public final String toString() {
+ return "FovHVH["+(inTangents?"tangents":"radians")+": "+left+" l, "+right+" r, "+top+" t, "+bottom+" b]";
+ }
+ public final String toStringInDegrees() {
+ final float f = 180.0f / FloatUtil.PI;
+ final String storedAs = inTangents?"tangents":"radians";
+ if( inTangents ) {
+ final float aleft = FloatUtil.atan(left);
+ final float aright = FloatUtil.atan(right);
+ final float atop = FloatUtil.atan(top);
+ final float abottom = FloatUtil.atan(bottom);
+ return "FovHVH[degrees: "+aleft*f+" l, "+aright*f+" r, "+atop*f+" t, "+abottom*f+" b, stored-as: "+storedAs+"]";
+ } else {
+ return "FovHVH[degrees: "+left*f+" l, "+right*f+" r, "+top*f+" t, "+bottom*f+" b, stored-as: "+storedAs+"]";
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Matrix4.java b/src/jogl/classes/com/jogamp/opengl/math/Matrix4.java
new file mode 100644
index 000000000..830f1a882
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/Matrix4.java
@@ -0,0 +1,152 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.math;
+
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.opengl.util.PMVMatrix;
+
+/**
+ * Simple float array-backed float 4x4 matrix
+ * exposing {@link FloatUtil} matrix functionality in an object oriented manner.
+ * <p>
+ * Unlike {@link PMVMatrix}, this class only represents one single matrix
+ * without a complete {@link GLMatrixFunc} implementation,
+ * allowing this class to be more lightweight.
+ * </p>
+ * <p>
+ * Implementation is not mature - WIP and subject to change.
+ * </p>
+ */
+public class Matrix4 {
+
+ public Matrix4() {
+ matrix = new float[16];
+ matrixTxSx = new float[16];
+ mat4Tmp1 = new float[16];
+ vec4Tmp1 = new float[4];
+ FloatUtil.makeIdentity(matrixTxSx);
+ loadIdentity();
+ }
+
+ public final float[] getMatrix() {
+ return matrix;
+ }
+
+ public final void loadIdentity() {
+ FloatUtil.makeIdentity(matrix);
+ }
+
+ /**
+ * Multiply matrix: [this] = [this] x [m]
+ * @param m 4x4 matrix in column-major order
+ */
+ public final void multMatrix(final float[] m, final int m_offset) {
+ FloatUtil.multMatrix(matrix, 0, m, m_offset);
+ }
+
+ /**
+ * Multiply matrix: [this] = [this] x [m]
+ * @param m 4x4 matrix in column-major order
+ */
+ public final void multMatrix(final float[] m) {
+ FloatUtil.multMatrix(matrix, m);
+ }
+
+ /**
+ * Multiply matrix: [this] = [this] x [m]
+ * @param m 4x4 matrix in column-major order
+ */
+ public final void multMatrix(final Matrix4 m) {
+ FloatUtil.multMatrix(matrix, m.getMatrix());
+ }
+
+ /**
+ * @param v_in 4-component column-vector
+ * @param v_out this * v_in
+ */
+ public final void multVec(final float[] v_in, final float[] v_out) {
+ FloatUtil.multMatrixVec(matrix, v_in, v_out);
+ }
+
+ /**
+ * @param v_in 4-component column-vector
+ * @param v_out this * v_in
+ */
+ public final void multVec(final float[] v_in, final int v_in_offset, final float[] v_out, final int v_out_offset) {
+ FloatUtil.multMatrixVec(matrix, 0, v_in, v_in_offset, v_out, v_out_offset);
+ }
+
+ public final void translate(final float x, final float y, final float z) {
+ multMatrix(FloatUtil.makeTranslation(matrixTxSx, false, x, y, z));
+ }
+
+ public final void scale(final float x, final float y, final float z) {
+ multMatrix(FloatUtil.makeScale(matrixTxSx, false, x, y, z));
+ }
+
+ public final void rotate(final float angrad, final float x, final float y, final float z) {
+ multMatrix(FloatUtil.makeRotationAxis(mat4Tmp1, 0, angrad, x, y, z, vec4Tmp1));
+ }
+
+ /**
+ * Rotate the current matrix with the given {@link Quaternion}'s rotation {@link Quaternion#toMatrix(float[], int) matrix representation}.
+ */
+ public final void rotate(final Quaternion quat) {
+ multMatrix(quat.toMatrix(mat4Tmp1, 0));
+ }
+
+ public final void transpose() {
+ System.arraycopy(matrix, 0, mat4Tmp1, 0, 16);
+ FloatUtil.transposeMatrix(mat4Tmp1, matrix);
+ }
+
+ public final float determinant() {
+ return FloatUtil.matrixDeterminant(matrix);
+ }
+
+ public final boolean invert() {
+ return null != FloatUtil.invertMatrix(matrix, matrix);
+ }
+
+ public final void makeOrtho(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) {
+ multMatrix( FloatUtil.makeOrtho(mat4Tmp1, 0, true, left, right, bottom, top, zNear, zFar) );
+ }
+
+ public final void makeFrustum(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) {
+ multMatrix( FloatUtil.makeFrustum(mat4Tmp1, 0, true, left, right, bottom, top, zNear, zFar) );
+ }
+
+ public final void makePerspective(final float fovy_rad, final float aspect, final float zNear, final float zFar) {
+ multMatrix( FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy_rad, aspect, zNear, zFar) );
+ }
+
+ private final float[] matrix, matrixTxSx;
+ private final float[] mat4Tmp1, vec4Tmp1;
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
new file mode 100644
index 000000000..430450767
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
@@ -0,0 +1,1209 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.math;
+
+/**
+ * Quaternion implementation supporting
+ * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a> free rotations.
+ * <p>
+ * All matrix operation provided are in column-major order,
+ * as specified in the OpenGL fixed function pipeline, i.e. compatibility profile.
+ * See {@link FloatUtil}.
+ * </p>
+ * <p>
+ * See <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html">Matrix-FAQ</a>
+ * </p>
+ * <p>
+ * See <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/index.htm">euclideanspace.com-Quaternion</a>
+ * </p>
+ */
+public class Quaternion {
+ private float x, y, z, w;
+
+ /**
+ * Quaternion Epsilon, used with equals method to determine if two Quaternions are close enough to be considered equal.
+ * <p>
+ * Using {@value}, which is ~10 times {@link FloatUtil#EPSILON}.
+ * </p>
+ */
+ public static final float ALLOWED_DEVIANCE = 1.0E-6f; // FloatUtil.EPSILON == 1.1920929E-7f; double ALLOWED_DEVIANCE: 1.0E-8f
+
+ public Quaternion() {
+ x = y = z = 0; w = 1;
+ }
+
+ public Quaternion(final Quaternion q) {
+ set(q);
+ }
+
+ public Quaternion(final float x, final float y, final float z, final float w) {
+ set(x, y, z, w);
+ }
+
+ /**
+ * See {@link #magnitude()} for special handling of {@link FloatUtil#EPSILON epsilon},
+ * which is not applied here.
+ * @return the squared magnitude of this quaternion.
+ */
+ public final float magnitudeSquared() {
+ return w*w + x*x + y*y + z*z;
+ }
+
+ /**
+ * Return the magnitude of this quaternion, i.e. sqrt({@link #magnitude()})
+ * <p>
+ * A magnitude of zero shall equal {@link #isIdentity() identity},
+ * as performed by {@link #normalize()}.
+ * </p>
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> returns 0f if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * <li> returns 1f if {@link #magnitudeSquared()} is {@link FloatUtil#isEqual(float, float, float) equals 1f} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
+ */
+ public final float magnitude() {
+ final float magnitudeSQ = magnitudeSquared();
+ if ( FloatUtil.isZero(magnitudeSQ, FloatUtil.EPSILON) ) {
+ return 0f;
+ }
+ if ( FloatUtil.isEqual(1f, magnitudeSQ, FloatUtil.EPSILON) ) {
+ return 1f;
+ }
+ return FloatUtil.sqrt(magnitudeSQ);
+ }
+
+ public final float getW() {
+ return w;
+ }
+
+ public final void setW(final float w) {
+ this.w = w;
+ }
+
+ public final float getX() {
+ return x;
+ }
+
+ public final void setX(final float x) {
+ this.x = x;
+ }
+
+ public final float getY() {
+ return y;
+ }
+
+ public final void setY(final float y) {
+ this.y = y;
+ }
+
+ public final float getZ() {
+ return z;
+ }
+
+ public final void setZ(final float z) {
+ this.z = z;
+ }
+
+ /**
+ * Returns the dot product of this quaternion with the given x,y,z and w components.
+ */
+ public final float dot(final float x, final float y, final float z, final float w) {
+ return this.x * x + this.y * y + this.z * z + this.w * w;
+ }
+
+ /**
+ * Returns the dot product of this quaternion with the given quaternion
+ */
+ public final float dot(final Quaternion quat) {
+ return dot(quat.getX(), quat.getY(), quat.getZ(), quat.getW());
+ }
+
+ /**
+ * Returns <code>true</code> if this quaternion has identity.
+ * <p>
+ * Implementation uses {@link FloatUtil#EPSILON epsilon} to compare
+ * {@link #getW() W} {@link FloatUtil#isEqual(float, float, float) against 1f} and
+ * {@link #getX() X}, {@link #getY() Y} and {@link #getZ() Z}
+ * {@link FloatUtil#isZero(float, float) against zero}.
+ * </p>
+ */
+ public final boolean isIdentity() {
+ return FloatUtil.isEqual(1f, w, FloatUtil.EPSILON) && VectorUtil.isZero(x, y, z, FloatUtil.EPSILON);
+ // return w == 1f && x == 0f && y == 0f && z == 0f;
+ }
+
+ /***
+ * Set this quaternion to identity (x=0,y=0,z=0,w=1)
+ * @return this quaternion for chaining.
+ */
+ public final Quaternion setIdentity() {
+ x = y = z = 0f; w = 1f;
+ return this;
+ }
+
+ /**
+ * Normalize a quaternion required if to be used as a rotational quaternion.
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if {@link #magnitude()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
+ * @return this quaternion for chaining.
+ */
+ public final Quaternion normalize() {
+ final float norm = magnitude();
+ if ( FloatUtil.isZero(norm, FloatUtil.EPSILON) ) {
+ setIdentity();
+ } else {
+ final float invNorm = 1f/norm;
+ w *= invNorm;
+ x *= invNorm;
+ y *= invNorm;
+ z *= invNorm;
+ }
+ return this;
+ }
+
+ /**
+ * Conjugates this quaternion <code>[-x, -y, -z, w]</code>.
+ * @return this quaternion for chaining.
+ * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q49">Matrix-FAQ Q49</a>
+ */
+ public Quaternion conjugate() {
+ x = -x;
+ y = -y;
+ z = -z;
+ return this;
+ }
+
+ /**
+ * Invert the quaternion If rotational, will produce a the inverse rotation
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #conjugate() conjugates} if {@link #magnitudeSquared()} is is {@link FloatUtil#isEqual(float, float, float) equals 1f} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
+ * @return this quaternion for chaining.
+ * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q50">Matrix-FAQ Q50</a>
+ */
+ public final Quaternion invert() {
+ final float magnitudeSQ = magnitudeSquared();
+ if ( FloatUtil.isEqual(1.0f, magnitudeSQ, FloatUtil.EPSILON) ) {
+ conjugate();
+ } else {
+ final float invmsq = 1f/magnitudeSQ;
+ w *= invmsq;
+ x = -x * invmsq;
+ y = -y * invmsq;
+ z = -z * invmsq;
+ }
+ return this;
+ }
+
+ /**
+ * Set all values of this quaternion using the given src.
+ * @return this quaternion for chaining.
+ */
+ public final Quaternion set(final Quaternion src) {
+ this.x = src.x;
+ this.y = src.y;
+ this.z = src.z;
+ this.w = src.w;
+ return this;
+ }
+
+ /**
+ * Set all values of this quaternion using the given components.
+ * @return this quaternion for chaining.
+ */
+ public final Quaternion set(final float x, final float y, final float z, final float w) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ return this;
+ }
+
+ /**
+ * Add a quaternion
+ *
+ * @param q quaternion
+ * @return this quaternion for chaining.
+ * @see <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm#add">euclideanspace.com-QuaternionAdd</a>
+ */
+ public final Quaternion add(final Quaternion q) {
+ x += q.x;
+ y += q.y;
+ z += q.z;
+ w += q.w;
+ return this;
+ }
+
+ /**
+ * Subtract a quaternion
+ *
+ * @param q quaternion
+ * @return this quaternion for chaining.
+ * @see <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm#add">euclideanspace.com-QuaternionAdd</a>
+ */
+ public final Quaternion subtract(final Quaternion q) {
+ x -= q.x;
+ y -= q.y;
+ z -= q.z;
+ w -= q.w;
+ return this;
+ }
+
+ /**
+ * Multiply this quaternion by the param quaternion
+ *
+ * @param q a quaternion to multiply with
+ * @return this quaternion for chaining.
+ * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q53">Matrix-FAQ Q53</a>
+ * @see <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm#mul">euclideanspace.com-QuaternionMul</a>
+ */
+ public final Quaternion mult(final Quaternion q) {
+ return set( w * q.x + x * q.w + y * q.z - z * q.y,
+ w * q.y - x * q.z + y * q.w + z * q.x,
+ w * q.z + x * q.y - y * q.x + z * q.w,
+ w * q.w - x * q.x - y * q.y - z * q.z );
+ }
+
+ /**
+ * Scale this quaternion by a constant
+ *
+ * @param n a float constant
+ * @return this quaternion for chaining.
+ * @see <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm#scale">euclideanspace.com-QuaternionScale</a>
+ */
+ public final Quaternion scale(final float n) {
+ x *= n;
+ y *= n;
+ z *= n;
+ w *= n;
+ return this;
+ }
+
+ /**
+ * Rotate this quaternion by the given angle and axis.
+ * <p>
+ * The axis must be a normalized vector.
+ * </p>
+ * <p>
+ * A rotational quaternion is made from the given angle and axis.
+ * </p>
+ *
+ * @param angle in radians
+ * @param axisX x-coord of rotation axis
+ * @param axisY y-coord of rotation axis
+ * @param axisZ z-coord of rotation axis
+ * @return this quaternion for chaining.
+ */
+ public Quaternion rotateByAngleNormalAxis(final float angle, final float axisX, final float axisY, final float axisZ) {
+ if( VectorUtil.isZero(axisX, axisY, axisZ, FloatUtil.EPSILON) ) {
+ // no change
+ return this;
+ }
+ final float halfAngle = 0.5f * angle;
+ final float sin = FloatUtil.sin(halfAngle);
+ final float qw = FloatUtil.cos(halfAngle);
+ final float qx = sin * axisX;
+ final float qy = sin * axisY;
+ final float qz = sin * axisZ;
+ return set( x * qw + y * qz - z * qy + w * qx,
+ -x * qz + y * qw + z * qx + w * qy,
+ x * qy - y * qx + z * qw + w * qz,
+ -x * qx - y * qy - z * qz + w * qw);
+ }
+
+ /**
+ * Rotate this quaternion around X axis with the given angle in radians
+ *
+ * @param angle in radians
+ * @return this quaternion for chaining.
+ */
+ public Quaternion rotateByAngleX(final float angle) {
+ final float halfAngle = 0.5f * angle;
+ final float sin = FloatUtil.sin(halfAngle);
+ final float cos = FloatUtil.cos(halfAngle);
+ return set( x * cos + w * sin,
+ y * cos + z * sin,
+ -y * sin + z * cos,
+ -x * sin + w * cos);
+ }
+
+ /**
+ * Rotate this quaternion around Y axis with the given angle in radians
+ *
+ * @param angle in radians
+ * @return this quaternion for chaining.
+ */
+ public Quaternion rotateByAngleY(final float angle) {
+ final float halfAngle = 0.5f * angle;
+ final float sin = FloatUtil.sin(halfAngle);
+ final float cos = FloatUtil.cos(halfAngle);
+ return set( x * cos - z * sin,
+ y * cos + w * sin,
+ x * sin + z * cos,
+ -y * sin + w * cos);
+ }
+
+ /**
+ * Rotate this quaternion around Z axis with the given angle in radians
+ *
+ * @param angle in radians
+ * @return this quaternion for chaining.
+ */
+ public Quaternion rotateByAngleZ(final float angle) {
+ final float halfAngle = 0.5f * angle;
+ final float sin = FloatUtil.sin(halfAngle);
+ final float cos = FloatUtil.cos(halfAngle);
+ return set( x * cos + y * sin,
+ -x * sin + y * cos,
+ z * cos + w * sin,
+ -z * sin + w * cos);
+ }
+
+ /**
+ * Rotates this quaternion from the given Euler rotation array <code>angradXYZ</code> in radians.
+ * <p>
+ * The <code>angradXYZ</code> array is laid out in natural order:
+ * <ul>
+ * <li>x - bank</li>
+ * <li>y - heading</li>
+ * <li>z - attitude</li>
+ * </ul>
+ * </p>
+ * For details see {@link #rotateByEuler(float, float, float)}.
+ * @param angradXYZ euler angel array in radians
+ * @return this quaternion for chaining.
+ * @see #rotateByEuler(float, float, float)
+ */
+ public final Quaternion rotateByEuler(final float[] angradXYZ) {
+ return rotateByEuler(angradXYZ[0], angradXYZ[1], angradXYZ[2]);
+ }
+
+ /**
+ * Rotates this quaternion from the given Euler rotation angles in radians.
+ * <p>
+ * The rotations are applied in the given order and using chained rotation per axis:
+ * <ul>
+ * <li>y - heading - {@link #rotateByAngleY(float)}</li>
+ * <li>z - attitude - {@link #rotateByAngleZ(float)}</li>
+ * <li>x - bank - {@link #rotateByAngleX(float)}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> NOP if all angles are {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * <li> result is {@link #normalize()}ed</li>
+ * </ul>
+ * </p>
+ * @param bankX the Euler pitch angle in radians. (rotation about the X axis)
+ * @param headingY the Euler yaw angle in radians. (rotation about the Y axis)
+ * @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis)
+ * @return this quaternion for chaining.
+ * @see #rotateByAngleY(float)
+ * @see #rotateByAngleZ(float)
+ * @see #rotateByAngleX(float)
+ * @see #setFromEuler(float, float, float)
+ */
+ public final Quaternion rotateByEuler(final float bankX, final float headingY, final float attitudeZ) {
+ if ( VectorUtil.isZero(bankX, headingY, attitudeZ, FloatUtil.EPSILON) ) {
+ return this;
+ } else {
+ // setFromEuler muls: ( 8 + 4 ) , + quat muls 24 = 36
+ // this: 8 + 8 + 8 + 4 = 28 muls
+ return rotateByAngleY(headingY).rotateByAngleZ(attitudeZ).rotateByAngleX(bankX).normalize();
+ }
+ }
+
+ /***
+ * Rotate the given vector by this quaternion
+ *
+ * @param vecOut result float[3] storage for rotated vector, maybe equal to vecIn for in-place rotation
+ * @param vecOutOffset offset in result storage
+ * @param vecIn float[3] vector to be rotated
+ * @param vecInOffset offset in vecIn
+ * @return the given vecOut store for chaining
+ * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q63">Matrix-FAQ Q63</a>
+ */
+ public final float[] rotateVector(final float[] vecOut, final int vecOutOffset, final float[] vecIn, final int vecInOffset) {
+ if ( VectorUtil.isVec3Zero(vecIn, vecInOffset, FloatUtil.EPSILON) ) {
+ vecOut[0+vecOutOffset] = 0f;
+ vecOut[1+vecOutOffset] = 0f;
+ vecOut[2+vecOutOffset] = 0f;
+ } else {
+ final float vecX = vecIn[0+vecInOffset];
+ final float vecY = vecIn[1+vecInOffset];
+ final float vecZ = vecIn[2+vecInOffset];
+ final float x_x = x*x;
+ final float y_y = y*y;
+ final float z_z = z*z;
+ final float w_w = w*w;
+
+ vecOut[0+vecOutOffset] = w_w * vecX
+ + x_x * vecX
+ - z_z * vecX
+ - y_y * vecX
+ + 2f * ( y*w*vecZ - z*w*vecY + y*x*vecY + z*x*vecZ );
+ ;
+
+ vecOut[1+vecOutOffset] = y_y * vecY
+ - z_z * vecY
+ + w_w * vecY
+ - x_x * vecY
+ + 2f * ( x*y*vecX + z*y*vecZ + w*z*vecX - x*w*vecZ );
+ ;
+
+ vecOut[2+vecOutOffset] = z_z * vecZ
+ - y_y * vecZ
+ - x_x * vecZ
+ + w_w * vecZ
+ + 2f * ( x*z*vecX + y*z*vecY - w*y*vecX + w*x*vecY );
+ ;
+ }
+ return vecOut;
+ }
+
+ /**
+ * Set this quaternion to a spherical linear interpolation
+ * between the given start and end quaternions by the given change amount.
+ * <p>
+ * Note: Method <i>does not</i> normalize this quaternion!
+ * </p>
+ *
+ * @param a start quaternion
+ * @param b end quaternion
+ * @param changeAmnt float between 0 and 1 representing interpolation.
+ * @return this quaternion for chaining.
+ * @see <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/">euclideanspace.com-QuaternionSlerp</a>
+ */
+ public final Quaternion setSlerp(final Quaternion a, final Quaternion b, final float changeAmnt) {
+ // System.err.println("Slerp.0: A "+a+", B "+b+", t "+changeAmnt);
+ if (changeAmnt == 0.0f) {
+ set(a);
+ } else if (changeAmnt == 1.0f) {
+ set(b);
+ } else {
+ float bx = b.x;
+ float by = b.y;
+ float bz = b.z;
+ float bw = b.w;
+
+ // Calculate angle between them (quat dot product)
+ float cosHalfTheta = a.x * bx + a.y * by + a.z * bz + a.w * bw;
+
+ final float scale0, scale1;
+
+ if( cosHalfTheta >= 0.95f ) {
+ // quaternions are close, just use linear interpolation
+ scale0 = 1.0f - changeAmnt;
+ scale1 = changeAmnt;
+ // System.err.println("Slerp.1: Linear Interpol; cosHalfTheta "+cosHalfTheta);
+ } else if ( cosHalfTheta <= -0.99f ) {
+ // the quaternions are nearly opposite,
+ // we can pick any axis normal to a,b to do the rotation
+ scale0 = 0.5f;
+ scale1 = 0.5f;
+ // System.err.println("Slerp.2: Any; cosHalfTheta "+cosHalfTheta);
+ } else {
+ // System.err.println("Slerp.3: cosHalfTheta "+cosHalfTheta);
+ if( cosHalfTheta <= -FloatUtil.EPSILON ) { // FIXME: .. or shall we use the upper bound 'cosHalfTheta < FloatUtil.EPSILON' ?
+ // Negate the second quaternion and the result of the dot product (Inversion)
+ bx *= -1f;
+ by *= -1f;
+ bz *= -1f;
+ bw *= -1f;
+ cosHalfTheta *= -1f;
+ // System.err.println("Slerp.4: Inverted cosHalfTheta "+cosHalfTheta);
+ }
+ final float halfTheta = FloatUtil.acos(cosHalfTheta);
+ final float sinHalfTheta = FloatUtil.sqrt(1.0f - cosHalfTheta*cosHalfTheta);
+ // if theta = 180 degrees then result is not fully defined
+ // we could rotate around any axis normal to qa or qb
+ if ( Math.abs(sinHalfTheta) < 0.001f ){ // fabs is floating point absolute
+ scale0 = 0.5f;
+ scale1 = 0.5f;
+ // throw new InternalError("XXX"); // FIXME should not be reached due to above inversion ?
+ } else {
+ // Calculate the scale for q1 and q2, according to the angle and
+ // it's sine value
+ scale0 = FloatUtil.sin((1f - changeAmnt) * halfTheta) / sinHalfTheta;
+ scale1 = FloatUtil.sin(changeAmnt * halfTheta) / sinHalfTheta;
+ }
+ }
+
+ x = a.x * scale0 + bx * scale1;
+ y = a.y * scale0 + by * scale1;
+ z = a.z * scale0 + bz * scale1;
+ w = a.w * scale0 + bw * scale1;
+ }
+ // System.err.println("Slerp.X: Result "+this);
+ return this;
+ }
+
+ /**
+ * Set this quaternion to equal the rotation required
+ * to point the z-axis at <i>direction</i> and the y-axis to <i>up</i>.
+ * <p>
+ * Implementation generates a 3x3 matrix
+ * and is equal with ProjectFloat's lookAt(..).<br/>
+ * </p>
+ * Implementation Details:
+ * <ul>
+ * <li> result is {@link #normalize()}ed</li>
+ * </ul>
+ * </p>
+ * @param directionIn where to <i>look</i> at
+ * @param upIn a vector indicating the local <i>up</i> direction.
+ * @param xAxisOut vector storing the <i>orthogonal</i> x-axis of the coordinate system.
+ * @param yAxisOut vector storing the <i>orthogonal</i> y-axis of the coordinate system.
+ * @param zAxisOut vector storing the <i>orthogonal</i> z-axis of the coordinate system.
+ * @return this quaternion for chaining.
+ * @see <a href="http://www.euclideanspace.com/maths/algebra/vectors/lookat/index.htm">euclideanspace.com-LookUp</a>
+ */
+ public Quaternion setLookAt(final float[] directionIn, final float[] upIn,
+ final float[] xAxisOut, final float[] yAxisOut, final float[] zAxisOut) {
+ // Z = norm(dir)
+ VectorUtil.normalizeVec3(zAxisOut, directionIn);
+
+ // X = upIn x Z
+ // (borrow yAxisOut for upNorm)
+ VectorUtil.normalizeVec3(yAxisOut, upIn);
+ VectorUtil.crossVec3(xAxisOut, yAxisOut, zAxisOut);
+ VectorUtil.normalizeVec3(xAxisOut);
+
+ // Y = Z x X
+ //
+ VectorUtil.crossVec3(yAxisOut, zAxisOut, xAxisOut);
+ VectorUtil.normalizeVec3(yAxisOut);
+
+ /**
+ final float m00 = xAxisOut[0];
+ final float m01 = yAxisOut[0];
+ final float m02 = zAxisOut[0];
+ final float m10 = xAxisOut[1];
+ final float m11 = yAxisOut[1];
+ final float m12 = zAxisOut[1];
+ final float m20 = xAxisOut[2];
+ final float m21 = yAxisOut[2];
+ final float m22 = zAxisOut[2];
+ */
+ return setFromAxes(xAxisOut, yAxisOut, zAxisOut).normalize();
+ }
+
+ //
+ // Conversions
+ //
+
+ /**
+ * Initialize this quaternion from two vectors
+ * <pre>
+ * q = (s,v) = (v1•v2 , v1 × v2),
+ * angle = angle(v1, v2) = v1•v2
+ * axis = normal(v1 x v2)
+ * </pre>
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if square vector-length is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
+ * @param v1 not normalized
+ * @param v2 not normalized
+ * @param tmpPivotVec float[3] temp storage for cross product
+ * @param tmpNormalVec float[3] temp storage to normalize vector
+ * @return this quaternion for chaining.
+ */
+ public final Quaternion setFromVectors(final float[] v1, final float[] v2, final float[] tmpPivotVec, final float[] tmpNormalVec) {
+ final float factor = VectorUtil.normVec3(v1) * VectorUtil.normVec3(v2);
+ if ( FloatUtil.isZero(factor, FloatUtil.EPSILON ) ) {
+ return setIdentity();
+ } else {
+ final float dot = VectorUtil.dotVec3(v1, v2) / factor; // normalize
+ final float theta = FloatUtil.acos(Math.max(-1.0f, Math.min(dot, 1.0f))); // clipping [-1..1]
+
+ VectorUtil.crossVec3(tmpPivotVec, v1, v2);
+
+ if ( dot < 0.0f && FloatUtil.isZero( VectorUtil.normVec3(tmpPivotVec), FloatUtil.EPSILON ) ) {
+ // Vectors parallel and opposite direction, therefore a rotation of 180 degrees about any vector
+ // perpendicular to this vector will rotate vector a onto vector b.
+ //
+ // The following guarantees the dot-product will be 0.0.
+ int dominantIndex;
+ if (Math.abs(v1[0]) > Math.abs(v1[1])) {
+ if (Math.abs(v1[0]) > Math.abs(v1[2])) {
+ dominantIndex = 0;
+ } else {
+ dominantIndex = 2;
+ }
+ } else {
+ if (Math.abs(v1[1]) > Math.abs(v1[2])) {
+ dominantIndex = 1;
+ } else {
+ dominantIndex = 2;
+ }
+ }
+ tmpPivotVec[dominantIndex] = -v1[(dominantIndex + 1) % 3];
+ tmpPivotVec[(dominantIndex + 1) % 3] = v1[dominantIndex];
+ tmpPivotVec[(dominantIndex + 2) % 3] = 0f;
+ }
+ return setFromAngleAxis(theta, tmpPivotVec, tmpNormalVec);
+ }
+ }
+
+ /**
+ * Initialize this quaternion from two normalized vectors
+ * <pre>
+ * q = (s,v) = (v1•v2 , v1 × v2),
+ * angle = angle(v1, v2) = v1•v2
+ * axis = v1 x v2
+ * </pre>
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if square vector-length is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
+ * @param v1 normalized
+ * @param v2 normalized
+ * @param tmpPivotVec float[3] temp storage for cross product
+ * @return this quaternion for chaining.
+ */
+ public final Quaternion setFromNormalVectors(final float[] v1, final float[] v2, final float[] tmpPivotVec) {
+ final float factor = VectorUtil.normVec3(v1) * VectorUtil.normVec3(v2);
+ if ( FloatUtil.isZero(factor, FloatUtil.EPSILON ) ) {
+ return setIdentity();
+ } else {
+ final float dot = VectorUtil.dotVec3(v1, v2) / factor; // normalize
+ final float theta = FloatUtil.acos(Math.max(-1.0f, Math.min(dot, 1.0f))); // clipping [-1..1]
+
+ VectorUtil.crossVec3(tmpPivotVec, v1, v2);
+
+ if ( dot < 0.0f && FloatUtil.isZero( VectorUtil.normVec3(tmpPivotVec), FloatUtil.EPSILON ) ) {
+ // Vectors parallel and opposite direction, therefore a rotation of 180 degrees about any vector
+ // perpendicular to this vector will rotate vector a onto vector b.
+ //
+ // The following guarantees the dot-product will be 0.0.
+ int dominantIndex;
+ if (Math.abs(v1[0]) > Math.abs(v1[1])) {
+ if (Math.abs(v1[0]) > Math.abs(v1[2])) {
+ dominantIndex = 0;
+ } else {
+ dominantIndex = 2;
+ }
+ } else {
+ if (Math.abs(v1[1]) > Math.abs(v1[2])) {
+ dominantIndex = 1;
+ } else {
+ dominantIndex = 2;
+ }
+ }
+ tmpPivotVec[dominantIndex] = -v1[(dominantIndex + 1) % 3];
+ tmpPivotVec[(dominantIndex + 1) % 3] = v1[dominantIndex];
+ tmpPivotVec[(dominantIndex + 2) % 3] = 0f;
+ }
+ return setFromAngleNormalAxis(theta, tmpPivotVec);
+ }
+ }
+
+ /***
+ * Initialize this quaternion with given non-normalized axis vector and rotation angle
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if axis is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
+ * @param angle rotation angle (rads)
+ * @param vector axis vector not normalized
+ * @param tmpV3f float[3] temp storage to normalize vector
+ * @return this quaternion for chaining.
+ *
+ * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56">Matrix-FAQ Q56</a>
+ * @see #toAngleAxis(float[])
+ */
+ public final Quaternion setFromAngleAxis(final float angle, final float[] vector, final float[] tmpV3f) {
+ VectorUtil.normalizeVec3(tmpV3f, vector);
+ return setFromAngleNormalAxis(angle, tmpV3f);
+ }
+
+ /***
+ * Initialize this quaternion with given normalized axis vector and rotation angle
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if axis is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
+ * @param angle rotation angle (rads)
+ * @param vector axis vector normalized
+ * @return this quaternion for chaining.
+ *
+ * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56">Matrix-FAQ Q56</a>
+ * @see #toAngleAxis(float[])
+ */
+ public final Quaternion setFromAngleNormalAxis(final float angle, final float[] vector) {
+ if ( VectorUtil.isVec3Zero(vector, 0, FloatUtil.EPSILON) ) {
+ setIdentity();
+ } else {
+ final float halfangle = angle * 0.5f;
+ final float sin = FloatUtil.sin(halfangle);
+ x = vector[0] * sin;
+ y = vector[1] * sin;
+ z = vector[2] * sin;
+ w = FloatUtil.cos(halfangle);
+ }
+ return this;
+ }
+
+ /**
+ * Transform the rotational quaternion to axis based rotation angles
+ *
+ * @param axis float[3] storage for computed axis
+ * @return the rotation angle in radians
+ * @see #setFromAngleAxis(float, float[], float[])
+ */
+ public final float toAngleAxis(final float[] axis) {
+ final float sqrLength = x*x + y*y + z*z;
+ float angle;
+ if ( FloatUtil.isZero(sqrLength, FloatUtil.EPSILON) ) { // length is ~0
+ angle = 0.0f;
+ axis[0] = 1.0f;
+ axis[1] = 0.0f;
+ axis[2] = 0.0f;
+ } else {
+ angle = FloatUtil.acos(w) * 2.0f;
+ final float invLength = 1.0f / FloatUtil.sqrt(sqrLength);
+ axis[0] = x * invLength;
+ axis[1] = y * invLength;
+ axis[2] = z * invLength;
+ }
+ return angle;
+ }
+
+ /**
+ * Initializes this quaternion from the given Euler rotation array <code>angradXYZ</code> in radians.
+ * <p>
+ * The <code>angradXYZ</code> array is laid out in natural order:
+ * <ul>
+ * <li>x - bank</li>
+ * <li>y - heading</li>
+ * <li>z - attitude</li>
+ * </ul>
+ * </p>
+ * For details see {@link #setFromEuler(float, float, float)}.
+ * @param angradXYZ euler angel array in radians
+ * @return this quaternion for chaining.
+ * @see #setFromEuler(float, float, float)
+ */
+ public final Quaternion setFromEuler(final float[] angradXYZ) {
+ return setFromEuler(angradXYZ[0], angradXYZ[1], angradXYZ[2]);
+ }
+
+ /**
+ * Initializes this quaternion from the given Euler rotation angles in radians.
+ * <p>
+ * The rotations are applied in the given order:
+ * <ul>
+ * <li>y - heading</li>
+ * <li>z - attitude</li>
+ * <li>x - bank</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> {@link #setIdentity()} if all angles are {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * <li> result is {@link #normalize()}ed</li>
+ * </ul>
+ * </p>
+ * @param bankX the Euler pitch angle in radians. (rotation about the X axis)
+ * @param headingY the Euler yaw angle in radians. (rotation about the Y axis)
+ * @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis)
+ * @return this quaternion for chaining.
+ *
+ * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q60">Matrix-FAQ Q60</a>
+ * @see <a href="http://vered.rose.utoronto.ca/people/david_dir/GEMS/GEMS.html">Gems</a>
+ * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm">euclideanspace.com-eulerToQuaternion</a>
+ * @see #toEuler(float[])
+ */
+ public final Quaternion setFromEuler(final float bankX, final float headingY, final float attitudeZ) {
+ if ( VectorUtil.isZero(bankX, headingY, attitudeZ, FloatUtil.EPSILON) ) {
+ return setIdentity();
+ } else {
+ float angle = headingY * 0.5f;
+ final float sinHeadingY = FloatUtil.sin(angle);
+ final float cosHeadingY = FloatUtil.cos(angle);
+ angle = attitudeZ * 0.5f;
+ final float sinAttitudeZ = FloatUtil.sin(angle);
+ final float cosAttitudeZ = FloatUtil.cos(angle);
+ angle = bankX * 0.5f;
+ final float sinBankX = FloatUtil.sin(angle);
+ final float cosBankX = FloatUtil.cos(angle);
+
+ // variables used to reduce multiplication calls.
+ final float cosHeadingXcosAttitude = cosHeadingY * cosAttitudeZ;
+ final float sinHeadingXsinAttitude = sinHeadingY * sinAttitudeZ;
+ final float cosHeadingXsinAttitude = cosHeadingY * sinAttitudeZ;
+ final float sinHeadingXcosAttitude = sinHeadingY * cosAttitudeZ;
+
+ w = cosHeadingXcosAttitude * cosBankX - sinHeadingXsinAttitude * sinBankX;
+ x = cosHeadingXcosAttitude * sinBankX + sinHeadingXsinAttitude * cosBankX;
+ y = sinHeadingXcosAttitude * cosBankX + cosHeadingXsinAttitude * sinBankX;
+ z = cosHeadingXsinAttitude * cosBankX - sinHeadingXcosAttitude * sinBankX;
+ return normalize();
+ }
+ }
+
+ /**
+ * Transform this quaternion to Euler rotation angles in radians (pitchX, yawY and rollZ).
+ *
+ * @param result the float[] array storing the computed angles.
+ * @return the double[] array, filled with heading, attitude and bank in that order..
+ * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm">euclideanspace.com-quaternionToEuler</a>
+ * @see #setFromEuler(float, float, float)
+ */
+ public float[] toEuler(final float[] result) {
+ final float sqw = w*w;
+ final float sqx = x*x;
+ final float sqy = y*y;
+ final float sqz = z*z;
+ final float unit = sqx + sqy + sqz + sqw; // if normalized is one, otherwise
+ // is correction factor
+ final float test = x*y + z*w;
+
+ if (test > 0.499f * unit) { // singularity at north pole
+ result[0] = 0f;
+ result[1] = 2f * FloatUtil.atan2(x, w);
+ result[2] = FloatUtil.HALF_PI;
+ } else if (test < -0.499f * unit) { // singularity at south pole
+ result[0] = 0f;
+ result[1] = -2 * FloatUtil.atan2(x, w);
+ result[2] = -FloatUtil.HALF_PI;
+ } else {
+ result[0] = FloatUtil.atan2(2f * x * w - 2 * y * z, -sqx + sqy - sqz + sqw);
+ result[1] = FloatUtil.atan2(2f * y * w - 2 * x * z, sqx - sqy - sqz + sqw);
+ result[2] = FloatUtil.asin( 2f * test / unit);
+ }
+ return result;
+ }
+
+ /**
+ * Initializes this quaternion from a 4x4 column rotation matrix
+ * <p>
+ * See <a href="ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z">Graphics Gems Code</a>,<br/>
+ * <a href="http://mathworld.wolfram.com/MatrixTrace.html">MatrixTrace</a>.
+ * </p>
+ * <p>
+ * Buggy <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q55">Matrix-FAQ Q55</a>
+ * </p>
+ *
+ * @param m 4x4 column matrix
+ * @return this quaternion for chaining.
+ * @see #toMatrix(float[], int)
+ */
+ public final Quaternion setFromMatrix(final float[] m, final int m_off) {
+ return setFromMatrix(m[0+0*4+m_off], m[0+1*4+m_off], m[0+2*4+m_off],
+ m[1+0*4+m_off], m[1+1*4+m_off], m[1+2*4+m_off],
+ m[2+0*4+m_off], m[2+1*4+m_off], m[2+2*4+m_off]);
+ }
+
+ /**
+ * Compute the quaternion from a 3x3 column rotation matrix
+ * <p>
+ * See <a href="ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z">Graphics Gems Code</a>,<br/>
+ * <a href="http://mathworld.wolfram.com/MatrixTrace.html">MatrixTrace</a>.
+ * </p>
+ * <p>
+ * Buggy <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q55">Matrix-FAQ Q55</a>
+ * </p>
+ *
+ * @return this quaternion for chaining.
+ * @see #toMatrix(float[], int)
+ */
+ public Quaternion setFromMatrix(final float m00, final float m01, final float m02,
+ final float m10, final float m11, final float m12,
+ final float m20, final float m21, final float m22) {
+ // Note: Other implementations uses 'T' w/o '+1f' and compares 'T >= 0' while adding missing 1f in sqrt expr.
+ // However .. this causes setLookAt(..) to fail and actually violates the 'trace definition'.
+
+ // The trace T is the sum of the diagonal elements; see
+ // http://mathworld.wolfram.com/MatrixTrace.html
+ final float T = m00 + m11 + m22 + 1f;
+ // System.err.println("setFromMatrix.0 T "+T+", m00 "+m00+", m11 "+m11+", m22 "+m22);
+ if ( T > 0f ) {
+ // System.err.println("setFromMatrix.1");
+ final float S = 0.5f / FloatUtil.sqrt(T); // S = 1 / ( 2 t )
+ w = 0.25f / S; // w = 1 / ( 4 S ) = t / 2
+ x = ( m21 - m12 ) * S;
+ y = ( m02 - m20 ) * S;
+ z = ( m10 - m01 ) * S;
+ } else if ( m00 > m11 && m00 > m22) {
+ // System.err.println("setFromMatrix.2");
+ final float S = 0.5f / FloatUtil.sqrt(1.0f + m00 - m11 - m22); // S=4*qx
+ w = ( m21 - m12 ) * S;
+ x = 0.25f / S;
+ y = ( m10 + m01 ) * S;
+ z = ( m02 + m20 ) * S;
+ } else if ( m11 > m22 ) {
+ // System.err.println("setFromMatrix.3");
+ final float S = 0.5f / FloatUtil.sqrt(1.0f + m11 - m00 - m22); // S=4*qy
+ w = ( m02 - m20 ) * S;
+ x = ( m20 + m01 ) * S;
+ y = 0.25f / S;
+ z = ( m21 + m12 ) * S;
+ } else {
+ // System.err.println("setFromMatrix.3");
+ final float S = 0.5f / FloatUtil.sqrt(1.0f + m22 - m00 - m11); // S=4*qz
+ w = ( m10 - m01 ) * S;
+ x = ( m02 + m20 ) * S;
+ y = ( m21 + m12 ) * S;
+ z = 0.25f / S;
+ }
+ return this;
+ }
+
+ /**
+ * Transform this quaternion to a normalized 4x4 column matrix representing the rotation.
+ * <p>
+ * Implementation Details:
+ * <ul>
+ * <li> makes identity matrix if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
+ * </ul>
+ * </p>
+ *
+ * @param matrix float[16] store for the resulting normalized column matrix 4x4
+ * @param mat_offset
+ * @return the given matrix store
+ * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54">Matrix-FAQ Q54</a>
+ * @see #setFromMatrix(float[], int)
+ */
+ public final float[] toMatrix(final float[] matrix, final int mat_offset) {
+ // pre-multiply scaled-reciprocal-magnitude to reduce multiplications
+ final float norm = magnitudeSquared();
+ if ( FloatUtil.isZero(norm, FloatUtil.EPSILON) ) {
+ // identity matrix -> srecip = 0f
+ return FloatUtil.makeIdentity(matrix, mat_offset);
+ }
+ final float srecip;
+ if ( FloatUtil.isEqual(1f, norm, FloatUtil.EPSILON) ) {
+ srecip = 2f;
+ } else {
+ srecip = 2.0f / norm;
+ }
+
+ final float xs = srecip * x;
+ final float ys = srecip * y;
+ final float zs = srecip * z;
+
+ final float xx = x * xs;
+ final float xy = x * ys;
+ final float xz = x * zs;
+ final float xw = xs * w;
+ final float yy = y * ys;
+ final float yz = y * zs;
+ final float yw = ys * w;
+ final float zz = z * zs;
+ final float zw = zs * w;
+
+ matrix[0+0*4+mat_offset] = 1f - ( yy + zz );
+ matrix[0+1*4+mat_offset] = ( xy - zw );
+ matrix[0+2*4+mat_offset] = ( xz + yw );
+ matrix[0+3*4+mat_offset] = 0f;
+
+ matrix[1+0*4+mat_offset] = ( xy + zw );
+ matrix[1+1*4+mat_offset] = 1f - ( xx + zz );
+ matrix[1+2*4+mat_offset] = ( yz - xw );
+ matrix[1+3*4+mat_offset] = 0f;
+
+ matrix[2+0*4+mat_offset] = ( xz - yw );
+ matrix[2+1*4+mat_offset] = ( yz + xw );
+ matrix[2+2*4+mat_offset] = 1f - ( xx + yy );
+ matrix[2+3*4+mat_offset] = 0f;
+
+ matrix[3+0*4+mat_offset] = 0f;
+ matrix[3+1*4+mat_offset] = 0f;
+ matrix[3+2*4+mat_offset] = 0f;
+ matrix[3+3*4+mat_offset] = 1f;
+ return matrix;
+ }
+
+ /**
+ * @param index the 3x3 rotation matrix column to retrieve from this quaternion (normalized). Must be between 0 and 2.
+ * @param result the vector object to store the result in.
+ * @return the result column-vector for chaining.
+ */
+ public float[] copyMatrixColumn(final int index, final float[] result, final int resultOffset) {
+ // pre-multipliy scaled-reciprocal-magnitude to reduce multiplications
+ final float norm = magnitudeSquared();
+ final float srecip;
+ if ( FloatUtil.isZero(norm, FloatUtil.EPSILON) ) {
+ srecip= 0f;
+ } else if ( FloatUtil.isEqual(1f, norm, FloatUtil.EPSILON) ) {
+ srecip= 2f;
+ } else {
+ srecip= 2.0f / norm;
+ }
+
+ // compute xs/ys/zs first to save 6 multiplications, since xs/ys/zs
+ // will be used 2-4 times each.
+ final float xs = x * srecip;
+ final float ys = y * srecip;
+ final float zs = z * srecip;
+ final float xx = x * xs;
+ final float xy = x * ys;
+ final float xz = x * zs;
+ final float xw = w * xs;
+ final float yy = y * ys;
+ final float yz = y * zs;
+ final float yw = w * ys;
+ final float zz = z * zs;
+ final float zw = w * zs;
+
+ // using s=2/norm (instead of 1/norm) saves 3 multiplications by 2 here
+ switch (index) {
+ case 0:
+ result[0+resultOffset] = 1.0f - (yy + zz);
+ result[1+resultOffset] = xy + zw;
+ result[2+resultOffset] = xz - yw;
+ break;
+ case 1:
+ result[0+resultOffset] = xy - zw;
+ result[1+resultOffset] = 1.0f - (xx + zz);
+ result[2+resultOffset] = yz + xw;
+ break;
+ case 2:
+ result[0+resultOffset] = xz + yw;
+ result[1+resultOffset] = yz - xw;
+ result[2+resultOffset] = 1.0f - (xx + yy);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid column index. " + index);
+ }
+ return result;
+ }
+
+ /**
+ * Initializes this quaternion to represent a rotation formed by the given three <i>orthogonal</i> axes.
+ * <p>
+ * No validation whether the axes are <i>orthogonal</i> is performed.
+ * </p>
+ *
+ * @param xAxis vector representing the <i>orthogonal</i> x-axis of the coordinate system.
+ * @param yAxis vector representing the <i>orthogonal</i> y-axis of the coordinate system.
+ * @param zAxis vector representing the <i>orthogonal</i> z-axis of the coordinate system.
+ * @return this quaternion for chaining.
+ */
+ public final Quaternion setFromAxes(final float[] xAxis, final float[] yAxis, final float[] zAxis) {
+ return setFromMatrix(xAxis[0], yAxis[0], zAxis[0],
+ xAxis[1], yAxis[1], zAxis[1],
+ xAxis[2], yAxis[2], zAxis[2]);
+ }
+
+ /**
+ * Extracts this quaternion's <i>orthogonal</i> rotation axes.
+ *
+ * @param xAxis vector representing the <i>orthogonal</i> x-axis of the coordinate system.
+ * @param yAxis vector representing the <i>orthogonal</i> y-axis of the coordinate system.
+ * @param zAxis vector representing the <i>orthogonal</i> z-axis of the coordinate system.
+ * @param tmpMat4 temporary float[4] matrix, used to transform this quaternion to a matrix.
+ */
+ public void toAxes(final float[] xAxis, final float[] yAxis, final float[] zAxis, final float[] tmpMat4) {
+ toMatrix(tmpMat4, 0);
+ FloatUtil.copyMatrixColumn(tmpMat4, 0, 2, zAxis, 0);
+ FloatUtil.copyMatrixColumn(tmpMat4, 0, 1, yAxis, 0);
+ FloatUtil.copyMatrixColumn(tmpMat4, 0, 0, xAxis, 0);
+ }
+
+ /**
+ * Check if the the 3x3 matrix (param) is in fact an affine rotational
+ * matrix
+ *
+ * @param m 3x3 column matrix
+ * @return true if representing a rotational matrix, false otherwise
+ */
+ public final boolean isRotationMatrix3f(final float[] m) {
+ final float epsilon = 0.01f; // margin to allow for rounding errors
+ if (FloatUtil.abs(m[0] * m[3] + m[3] * m[4] + m[6] * m[7]) > epsilon)
+ return false;
+ if (FloatUtil.abs(m[0] * m[2] + m[3] * m[5] + m[6] * m[8]) > epsilon)
+ return false;
+ if (FloatUtil.abs(m[1] * m[2] + m[4] * m[5] + m[7] * m[8]) > epsilon)
+ return false;
+ if (FloatUtil.abs(m[0] * m[0] + m[3] * m[3] + m[6] * m[6] - 1) > epsilon)
+ return false;
+ if (FloatUtil.abs(m[1] * m[1] + m[4] * m[4] + m[7] * m[7] - 1) > epsilon)
+ return false;
+ if (FloatUtil.abs(m[2] * m[2] + m[5] * m[5] + m[8] * m[8] - 1) > epsilon)
+ return false;
+ return (FloatUtil.abs(determinant3f(m) - 1) < epsilon);
+ }
+
+ private final float determinant3f(final float[] m) {
+ return m[0] * m[4] * m[8] + m[3] * m[7] * m[2] + m[6] * m[1] * m[5]
+ - m[0] * m[7] * m[5] - m[3] * m[1] * m[8] - m[6] * m[4] * m[2];
+ }
+
+ //
+ // std java overrides
+ //
+
+ /**
+ * @param o the object to compare for equality
+ * @return true if this quaternion and the provided quaternion have roughly the same x, y, z and w values.
+ */
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Quaternion)) {
+ return false;
+ }
+ final Quaternion comp = (Quaternion) o;
+ return Math.abs(x - comp.getX()) <= ALLOWED_DEVIANCE &&
+ Math.abs(y - comp.getY()) <= ALLOWED_DEVIANCE &&
+ Math.abs(z - comp.getZ()) <= ALLOWED_DEVIANCE &&
+ Math.abs(w - comp.getW()) <= ALLOWED_DEVIANCE;
+ }
+ @Override
+ public final int hashCode() {
+ throw new InternalError("hashCode not designed");
+ }
+
+ public String toString() {
+ return "Quaternion[x "+x+", y "+y+", z "+z+", w "+w+"]";
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Ray.java b/src/jogl/classes/com/jogamp/opengl/math/Ray.java
new file mode 100644
index 000000000..4d651d1c3
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/Ray.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.math;
+
+import com.jogamp.opengl.math.geom.AABBox;
+
+/**
+ * Simple compound denoting a ray.
+ * <p>
+ * A ray, also known as a half line, consists out of it's <i>origin</i>
+ * and <i>direction</i>. Hence it is bound to only the <i>origin</i> side,
+ * where the other end is +infinitive.
+ * <pre>
+ * R(t) = R0 + Rd * t with R0 origin, Rd direction and t > 0.0
+ * </pre>
+ * </p>
+ * <p>
+ * A {@link Ray} maybe used for <i>picking</i>
+ * using a {@link AABBox bounding box} via
+ * {@link AABBox#intersectsRay(Ray) fast probe} or
+ * {@link AABBox#getRayIntersection(float[], Ray, float, boolean, float[], float[], float[]) returning the intersection}.
+ * </p>
+ */
+public class Ray {
+ /** Origin of Ray, float[3]. */
+ public final float[] orig = new float[3];
+
+ /** Normalized direction vector of ray, float[3]. */
+ public final float[] dir = new float[3];
+
+ public String toString() {
+ return "Ray[orig["+orig[0]+", "+orig[1]+", "+orig[2]+"], dir["+dir[0]+", "+dir[1]+", "+dir[2]+"]]";
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
new file mode 100644
index 000000000..36222cf4a
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
@@ -0,0 +1,1192 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.math;
+
+import java.util.ArrayList;
+
+public final class VectorUtil {
+
+ public static final float[] VEC3_ONE = { 1f, 1f, 1f };
+ public static final float[] VEC3_ZERO = { 0f, 0f, 0f };
+ public static final float[] VEC3_UNIT_Y = { 0f, 1f, 0f };
+ public static final float[] VEC3_UNIT_Y_NEG = { 0f, -1f, 0f };
+ public static final float[] VEC3_UNIT_Z = { 0f, 0f, 1f };
+ public static final float[] VEC3_UNIT_Z_NEG = { 0f, 0f, -1f };
+
+ public enum Winding {
+ CW(-1), CCW(1);
+
+ public final int dir;
+
+ Winding(final int dir) {
+ this.dir = dir;
+ }
+ }
+
+ /**
+ * Copies a vector of length 2
+ * @param dst output vector
+ * @param dstOffset offset of dst in array
+ * @param src input vector
+ * @param srcOffset offset of src in array
+ * @return copied output vector for chaining
+ */
+ public static float[] copyVec2(final float[] dst, final int dstOffset, final float[] src, final int srcOffset)
+ {
+ System.arraycopy(src, srcOffset, dst, dstOffset, 2);
+ return dst;
+ }
+
+ /**
+ * Copies a vector of length 3
+ * @param dst output vector
+ * @param dstOffset offset of dst in array
+ * @param src input vector
+ * @param srcOffset offset of src in array
+ * @return copied output vector for chaining
+ */
+ public static float[] copyVec3(final float[] dst, final int dstOffset, final float[] src, final int srcOffset)
+ {
+ System.arraycopy(src, srcOffset, dst, dstOffset, 3);
+ return dst;
+ }
+
+ /**
+ * Copies a vector of length 4
+ * @param dst output vector
+ * @param dstOffset offset of dst in array
+ * @param src input vector
+ * @param srcOffset offset of src in array
+ * @return copied output vector for chaining
+ */
+ public static float[] copyVec4(final float[] dst, final int dstOffset, final float[] src, final int srcOffset)
+ {
+ System.arraycopy(src, srcOffset, dst, dstOffset, 4);
+ return dst;
+ }
+
+ /**
+ * Return true if both vectors are equal w/o regarding an epsilon.
+ * <p>
+ * Implementation uses {@link FloatUtil#isEqual(float, float)}, see API doc for details.
+ * </p>
+ */
+ public static boolean isVec2Equal(final float[] vec1, final int vec1Offset, final float[] vec2, final int vec2Offset) {
+ return FloatUtil.isEqual(vec1[0+vec1Offset], vec2[0+vec2Offset]) &&
+ FloatUtil.isEqual(vec1[1+vec1Offset], vec2[1+vec2Offset]) ;
+ }
+
+ /**
+ * Return true if both vectors are equal w/o regarding an epsilon.
+ * <p>
+ * Implementation uses {@link FloatUtil#isEqual(float, float)}, see API doc for details.
+ * </p>
+ */
+ public static boolean isVec3Equal(final float[] vec1, final int vec1Offset, final float[] vec2, final int vec2Offset) {
+ return FloatUtil.isEqual(vec1[0+vec1Offset], vec2[0+vec2Offset]) &&
+ FloatUtil.isEqual(vec1[1+vec1Offset], vec2[1+vec2Offset]) &&
+ FloatUtil.isEqual(vec1[2+vec1Offset], vec2[2+vec2Offset]) ;
+ }
+
+ /**
+ * Return true if both vectors are equal, i.e. their absolute delta < <code>epsilon</code>.
+ * <p>
+ * Implementation uses {@link FloatUtil#isEqual(float, float, float)}, see API doc for details.
+ * </p>
+ */
+ public static boolean isVec2Equal(final float[] vec1, final int vec1Offset, final float[] vec2, final int vec2Offset, final float epsilon) {
+ return FloatUtil.isEqual(vec1[0+vec1Offset], vec2[0+vec2Offset], epsilon) &&
+ FloatUtil.isEqual(vec1[1+vec1Offset], vec2[1+vec2Offset], epsilon) ;
+ }
+
+ /**
+ * Return true if both vectors are equal, i.e. their absolute delta < <code>epsilon</code>.
+ * <p>
+ * Implementation uses {@link FloatUtil#isEqual(float, float, float)}, see API doc for details.
+ * </p>
+ */
+ public static boolean isVec3Equal(final float[] vec1, final int vec1Offset, final float[] vec2, final int vec2Offset, final float epsilon) {
+ return FloatUtil.isEqual(vec1[0+vec1Offset], vec2[0+vec2Offset], epsilon) &&
+ FloatUtil.isEqual(vec1[1+vec1Offset], vec2[1+vec2Offset], epsilon) &&
+ FloatUtil.isEqual(vec1[2+vec1Offset], vec2[2+vec2Offset], epsilon) ;
+ }
+
+ /**
+ * Return true if vector is zero, no {@link FloatUtil#EPSILON} is taken into consideration.
+ */
+ public static boolean isVec2Zero(final float[] vec, final int vecOffset) {
+ return 0f == vec[0+vecOffset] && 0f == vec[1+vecOffset];
+ }
+
+ /**
+ * Return true if vector is zero, no {@link FloatUtil#EPSILON} is taken into consideration.
+ */
+ public static boolean isVec3Zero(final float[] vec, final int vecOffset) {
+ return 0f == vec[0+vecOffset] && 0f == vec[1+vecOffset] && 0f == vec[2+vecOffset];
+ }
+
+ /**
+ * Return true if vector is zero, i.e. it's absolute components < <code>epsilon</code>.
+ * <p>
+ * Implementation uses {@link FloatUtil#isZero(float, float)}, see API doc for details.
+ * </p>
+ */
+ public static boolean isVec2Zero(final float[] vec, final int vecOffset, final float epsilon) {
+ return isZero(vec[0+vecOffset], vec[1+vecOffset], epsilon);
+ }
+
+ /**
+ * Return true if vector is zero, i.e. it's absolute components < <code>epsilon</code>.
+ * <p>
+ * Implementation uses {@link FloatUtil#isZero(float, float)}, see API doc for details.
+ * </p>
+ */
+ public static boolean isVec3Zero(final float[] vec, final int vecOffset, final float epsilon) {
+ return isZero(vec[0+vecOffset], vec[1+vecOffset], vec[2+vecOffset], epsilon);
+ }
+
+ /**
+ * Return true if all two vector components are zero, i.e. it's their absolute value < <code>epsilon</code>.
+ * <p>
+ * Implementation uses {@link FloatUtil#isZero(float, float)}, see API doc for details.
+ * </p>
+ */
+ public static boolean isZero(final float x, final float y, final float epsilon) {
+ return FloatUtil.isZero(x, epsilon) &&
+ FloatUtil.isZero(y, epsilon) ;
+ }
+
+ /**
+ * Return true if all three vector components are zero, i.e. it's their absolute value < <code>epsilon</code>.
+ * <p>
+ * Implementation uses {@link FloatUtil#isZero(float, float)}, see API doc for details.
+ * </p>
+ */
+ public static boolean isZero(final float x, final float y, final float z, final float epsilon) {
+ return FloatUtil.isZero(x, epsilon) &&
+ FloatUtil.isZero(y, epsilon) &&
+ FloatUtil.isZero(z, epsilon) ;
+ }
+
+ /**
+ * Return the squared distance between the given two points described vector v1 and v2.
+ * <p>
+ * When comparing the relative distance between two points it is usually sufficient to compare the squared
+ * distances, thus avoiding an expensive square root operation.
+ * </p>
+ */
+ public static float distSquareVec3(final float[] v1, final float[] v2) {
+ final float dx = v1[0] - v2[0];
+ final float dy = v1[1] - v2[1];
+ final float dz = v1[2] - v2[2];
+ return dx * dx + dy * dy + dz * dz;
+ }
+
+ /**
+ * Return the distance between the given two points described vector v1 and v2.
+ */
+ public static float distVec3(final float[] v1, final float[] v2) {
+ return FloatUtil.sqrt(distSquareVec3(v1, v2));
+ }
+
+ /**
+ * Return the dot product of two points
+ * @param vec1 vector 1
+ * @param vec2 vector 2
+ * @return the dot product as float
+ */
+ public static float dotVec3(final float[] vec1, final float[] vec2) {
+ return vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2];
+ }
+
+ /**
+ * Return the cosines of the angle between to vectors
+ * @param vec1 vector 1
+ * @param vec2 vector 2
+ */
+ public static float cosAngleVec3(final float[] vec1, final float[] vec2) {
+ return dotVec3(vec1, vec2) / ( normVec3(vec1) * normVec3(vec2) ) ;
+ }
+
+ /**
+ * Return the angle between to vectors in radians
+ * @param vec1 vector 1
+ * @param vec2 vector 2
+ */
+ public static float angleVec3(final float[] vec1, final float[] vec2) {
+ return FloatUtil.acos(cosAngleVec3(vec1, vec2));
+ }
+
+ /**
+ * Return the squared length of a vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
+ */
+ public static float normSquareVec2(final float[] vec) {
+ return vec[0]*vec[0] + vec[1]*vec[1];
+ }
+
+ /**
+ * Return the squared length of a vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
+ */
+ public static float normSquareVec2(final float[] vec, final int offset) {
+ float v = vec[0+offset];
+ final float r = v*v;
+ v = vec[1+offset];
+ return r + v*v;
+ }
+
+ /**
+ * Return the squared length of a vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
+ */
+ public static float normSquareVec3(final float[] vec) {
+ return vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2];
+ }
+
+ /**
+ * Return the squared length of a vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
+ */
+ public static float normSquareVec3(final float[] vec, final int offset) {
+ float v = vec[0+offset];
+ float r = v*v;
+ v = vec[1+offset];
+ r += v*v;
+ v = vec[2+offset];
+ return r + v*v;
+ }
+
+ /**
+ * Return the length of a vector, a.k.a the <i>norm</i> or <i>magnitude</i>
+ */
+ public static float normVec2(final float[] vec) {
+ return FloatUtil.sqrt(normSquareVec2(vec));
+ }
+
+ /**
+ * Return the length of a vector, a.k.a the <i>norm</i> or <i>magnitude</i>
+ */
+ public static float normVec3(final float[] vec) {
+ return FloatUtil.sqrt(normSquareVec3(vec));
+ }
+
+ /**
+ * Normalize a vector
+ * @param result output vector, may be vector (in-place)
+ * @param vector input vector
+ * @return normalized output vector
+ * @return result vector for chaining
+ */
+ public static float[] normalizeVec2(final float[] result, final float[] vector) {
+ final float lengthSq = normSquareVec2(vector);
+ if ( FloatUtil.isZero(lengthSq, FloatUtil.EPSILON) ) {
+ result[0] = 0f;
+ result[1] = 0f;
+ } else {
+ final float invSqr = 1f / FloatUtil.sqrt(lengthSq);
+ result[0] = vector[0] * invSqr;
+ result[1] = vector[1] * invSqr;
+ }
+ return result;
+ }
+
+ /**
+ * Normalize a vector in place
+ * @param vector input vector
+ * @return normalized output vector
+ */
+ public static float[] normalizeVec2(final float[] vector) {
+ final float lengthSq = normSquareVec2(vector);
+ if ( FloatUtil.isZero(lengthSq, FloatUtil.EPSILON) ) {
+ vector[0] = 0f;
+ vector[1] = 0f;
+ } else {
+ final float invSqr = 1f / FloatUtil.sqrt(lengthSq);
+ vector[0] *= invSqr;
+ vector[1] *= invSqr;
+ }
+ return vector;
+ }
+
+ /**
+ * Normalize a vector
+ * @param result output vector, may be vector (in-place)
+ * @param vector input vector
+ * @return normalized output vector
+ * @return result vector for chaining
+ */
+ public static float[] normalizeVec3(final float[] result, final float[] vector) {
+ final float lengthSq = normSquareVec3(vector);
+ if ( FloatUtil.isZero(lengthSq, FloatUtil.EPSILON) ) {
+ result[0] = 0f;
+ result[1] = 0f;
+ result[2] = 0f;
+ } else {
+ final float invSqr = 1f / FloatUtil.sqrt(lengthSq);
+ result[0] = vector[0] * invSqr;
+ result[1] = vector[1] * invSqr;
+ result[2] = vector[2] * invSqr;
+ }
+ return result;
+ }
+
+ /**
+ * Normalize a vector in place
+ * @param vector input vector
+ * @return normalized output vector
+ */
+ public static float[] normalizeVec3(final float[] vector) {
+ final float lengthSq = normSquareVec3(vector);
+ if ( FloatUtil.isZero(lengthSq, FloatUtil.EPSILON) ) {
+ vector[0] = 0f;
+ vector[1] = 0f;
+ vector[2] = 0f;
+ } else {
+ final float invSqr = 1f / FloatUtil.sqrt(lengthSq);
+ vector[0] *= invSqr;
+ vector[1] *= invSqr;
+ vector[2] *= invSqr;
+ }
+ return vector;
+ }
+
+ /**
+ * Normalize a vector in place
+ * @param vector input vector
+ * @return normalized output vector
+ */
+ public static float[] normalizeVec3(final float[] vector, final int offset) {
+ final float lengthSq = normSquareVec3(vector, offset);
+ if ( FloatUtil.isZero(lengthSq, FloatUtil.EPSILON) ) {
+ vector[0+offset] = 0f;
+ vector[1+offset] = 0f;
+ vector[2+offset] = 0f;
+ } else {
+ final float invSqr = 1f / FloatUtil.sqrt(lengthSq);
+ vector[0+offset] *= invSqr;
+ vector[1+offset] *= invSqr;
+ vector[2+offset] *= invSqr;
+ }
+ return vector;
+ }
+
+ /**
+ * Scales a vector by param using given result float[], result = vector * scale
+ * @param result vector for the result, may be vector (in-place)
+ * @param vector input vector
+ * @param scale single scale constant for all vector components
+ * @return result vector for chaining
+ */
+ public static float[] scaleVec2(final float[] result, final float[] vector, final float scale) {
+ result[0] = vector[0] * scale;
+ result[1] = vector[1] * scale;
+ return result;
+ }
+
+ /**
+ * Scales a vector by param using given result float[], result = vector * scale
+ * @param result vector for the result, may be vector (in-place)
+ * @param vector input vector
+ * @param scale single scale constant for all vector components
+ * @return result vector for chaining
+ */
+ public static float[] scaleVec3(final float[] result, final float[] vector, final float scale) {
+ result[0] = vector[0] * scale;
+ result[1] = vector[1] * scale;
+ result[2] = vector[2] * scale;
+ return result;
+ }
+
+ /**
+ * Scales a vector by param using given result float[], result = vector * scale
+ * @param result vector for the result, may be vector (in-place)
+ * @param vector input vector
+ * @param scale 3 component scale constant for each vector component
+ * @return result vector for chaining
+ */
+ public static float[] scaleVec3(final float[] result, final float[] vector, final float[] scale)
+ {
+ result[0] = vector[0] * scale[0];
+ result[1] = vector[1] * scale[1];
+ result[2] = vector[2] * scale[2];
+ return result;
+ }
+
+ /**
+ * Scales a vector by param using given result float[], result = vector * scale
+ * @param result vector for the result, may be vector (in-place)
+ * @param vector input vector
+ * @param scale 2 component scale constant for each vector component
+ * @return result vector for chaining
+ */
+ public static float[] scaleVec2(final float[] result, final float[] vector, final float[] scale)
+ {
+ result[0] = vector[0] * scale[0];
+ result[1] = vector[1] * scale[1];
+ return result;
+ }
+
+ /**
+ * Divides a vector by param using given result float[], result = vector / scale
+ * @param result vector for the result, may be vector (in-place)
+ * @param vector input vector
+ * @param scale single scale constant for all vector components
+ * @return result vector for chaining
+ */
+ public static float[] divVec2(final float[] result, final float[] vector, final float scale) {
+ result[0] = vector[0] / scale;
+ result[1] = vector[1] / scale;
+ return result;
+ }
+
+ /**
+ * Divides a vector by param using given result float[], result = vector / scale
+ * @param result vector for the result, may be vector (in-place)
+ * @param vector input vector
+ * @param scale single scale constant for all vector components
+ * @return result vector for chaining
+ */
+ public static float[] divVec3(final float[] result, final float[] vector, final float scale) {
+ result[0] = vector[0] / scale;
+ result[1] = vector[1] / scale;
+ result[2] = vector[2] / scale;
+ return result;
+ }
+
+ /**
+ * Divides a vector by param using given result float[], result = vector / scale
+ * @param result vector for the result, may be vector (in-place)
+ * @param vector input vector
+ * @param scale 3 component scale constant for each vector component
+ * @return result vector for chaining
+ */
+ public static float[] divVec3(final float[] result, final float[] vector, final float[] scale)
+ {
+ result[0] = vector[0] / scale[0];
+ result[1] = vector[1] / scale[1];
+ result[2] = vector[2] / scale[2];
+ return result;
+ }
+
+ /**
+ * Divides a vector by param using given result float[], result = vector / scale
+ * @param result vector for the result, may be vector (in-place)
+ * @param vector input vector
+ * @param scale 2 component scale constant for each vector component
+ * @return result vector for chaining
+ */
+ public static float[] divVec2(final float[] result, final float[] vector, final float[] scale)
+ {
+ result[0] = vector[0] / scale[0];
+ result[1] = vector[1] / scale[1];
+ return result;
+ }
+
+ /**
+ * Adds two vectors, result = v1 + v2
+ * @param result float[2] result vector, may be either v1 or v2 (in-place)
+ * @param v1 vector 1
+ * @param v2 vector 2
+ * @return result vector for chaining
+ */
+ public static float[] addVec2(final float[] result, final float[] v1, final float[] v2) {
+ result[0] = v1[0] + v2[0];
+ result[1] = v1[1] + v2[1];
+ return result;
+ }
+
+ /**
+ * Adds two vectors, result = v1 + v2
+ * @param result float[3] result vector, may be either v1 or v2 (in-place)
+ * @param v1 vector 1
+ * @param v2 vector 2
+ * @return result vector for chaining
+ */
+ public static float[] addVec3(final float[] result, final float[] v1, final float[] v2) {
+ result[0] = v1[0] + v2[0];
+ result[1] = v1[1] + v2[1];
+ result[2] = v1[2] + v2[2];
+ return result;
+ }
+
+ /**
+ * Subtracts two vectors, result = v1 - v2
+ * @param result float[2] result vector, may be either v1 or v2 (in-place)
+ * @param v1 vector 1
+ * @param v2 vector 2
+ * @return result vector for chaining
+ */
+ public static float[] subVec2(final float[] result, final float[] v1, final float[] v2) {
+ result[0] = v1[0] - v2[0];
+ result[1] = v1[1] - v2[1];
+ return result;
+ }
+
+ /**
+ * Subtracts two vectors, result = v1 - v2
+ * @param result float[3] result vector, may be either v1 or v2 (in-place)
+ * @param v1 vector 1
+ * @param v2 vector 2
+ * @return result vector for chaining
+ */
+ public static float[] subVec3(final float[] result, final float[] v1, final float[] v2) {
+ result[0] = v1[0] - v2[0];
+ result[1] = v1[1] - v2[1];
+ result[2] = v1[2] - v2[2];
+ return result;
+ }
+
+ /**
+ * cross product vec1 x vec2
+ * @param v1 vector 1
+ * @param v2 vector 2
+ * @return the resulting vector
+ */
+ public static float[] crossVec3(final float[] result, final float[] v1, final float[] v2)
+ {
+ result[0] = v1[1] * v2[2] - v1[2] * v2[1];
+ result[1] = v1[2] * v2[0] - v1[0] * v2[2];
+ result[2] = v1[0] * v2[1] - v1[1] * v2[0];
+ return result;
+ }
+
+ /**
+ * cross product vec1 x vec2
+ * @param v1 vector 1
+ * @param v2 vector 2
+ * @return the resulting vector
+ */
+ public static float[] crossVec3(final float[] r, final int r_offset, final float[] v1, final int v1_offset, final float[] v2, final int v2_offset)
+ {
+ r[0+r_offset] = v1[1+v1_offset] * v2[2+v2_offset] - v1[2+v1_offset] * v2[1+v2_offset];
+ r[1+r_offset] = v1[2+v1_offset] * v2[0+v2_offset] - v1[0+v1_offset] * v2[2+v2_offset];
+ r[2+r_offset] = v1[0+v1_offset] * v2[1+v2_offset] - v1[1+v1_offset] * v2[0+v2_offset];
+ return r;
+ }
+
+ /**
+ * Multiplication of column-major 4x4 matrix with vector
+ * @param colMatrix column matrix (4x4)
+ * @param vec vector(x,y,z)
+ * @return result
+ */
+ public static float[] mulColMat4Vec3(final float[] result, final float[] colMatrix, final float[] vec)
+ {
+ result[0] = vec[0]*colMatrix[0] + vec[1]*colMatrix[4] + vec[2]*colMatrix[8] + colMatrix[12];
+ result[1] = vec[0]*colMatrix[1] + vec[1]*colMatrix[5] + vec[2]*colMatrix[9] + colMatrix[13];
+ result[2] = vec[0]*colMatrix[2] + vec[1]*colMatrix[6] + vec[2]*colMatrix[10] + colMatrix[14];
+
+ return result;
+ }
+
+ /**
+ * Matrix Vector multiplication
+ * @param rawMatrix column matrix (4x4)
+ * @param vec vector(x,y,z)
+ * @return result
+ */
+ public static float[] mulRowMat4Vec3(final float[] result, final float[] rawMatrix, final float[] vec)
+ {
+ result[0] = vec[0]*rawMatrix[0] + vec[1]*rawMatrix[1] + vec[2]*rawMatrix[2] + rawMatrix[3];
+ result[1] = vec[0]*rawMatrix[4] + vec[1]*rawMatrix[5] + vec[2]*rawMatrix[6] + rawMatrix[7];
+ result[2] = vec[0]*rawMatrix[8] + vec[1]*rawMatrix[9] + vec[2]*rawMatrix[10] + rawMatrix[11];
+
+ return result;
+ }
+
+ /**
+ * Calculate the midpoint of two values
+ * @param p1 first value
+ * @param p2 second vale
+ * @return midpoint
+ */
+ public static float mid(final float p1, final float p2) {
+ return (p1+p2)*0.5f;
+ }
+
+ /**
+ * Calculate the midpoint of two points
+ * @param p1 first point vector
+ * @param p2 second point vector
+ * @return midpoint
+ */
+ public static float[] midVec3(final float[] result, final float[] p1, final float[] p2) {
+ result[0] = (p1[0] + p2[0])*0.5f;
+ result[1] = (p1[1] + p2[1])*0.5f;
+ result[2] = (p1[2] + p2[2])*0.5f;
+ return result;
+ }
+
+ /**
+ * Return the determinant of 3 vectors
+ * @param a vector 1
+ * @param b vector 2
+ * @param c vector 3
+ * @return the determinant value
+ */
+ public static float determinantVec3(final float[] a, final float[] b, final float[] c) {
+ return a[0]*b[1]*c[2] + a[1]*b[2]*c[0] + a[2]*b[0]*c[1] - a[0]*b[2]*c[1] - a[1]*b[0]*c[2] - a[2]*b[1]*c[0];
+ }
+
+ /**
+ * Check if three vertices are colliniear
+ * @param v1 vertex 1
+ * @param v2 vertex 2
+ * @param v3 vertex 3
+ * @return true if collinear, false otherwise
+ */
+ public static boolean isCollinearVec3(final float[] v1, final float[] v2, final float[] v3) {
+ return FloatUtil.isZero( determinantVec3(v1, v2, v3), FloatUtil.EPSILON );
+ }
+
+ /**
+ * Check if vertices in triangle circumcircle
+ * @param a triangle vertex 1
+ * @param b triangle vertex 2
+ * @param c triangle vertex 3
+ * @param d vertex in question
+ * @return true if the vertex d is inside the circle defined by the
+ * vertices a, b, c. from paper by Guibas and Stolfi (1985).
+ */
+ public static boolean isInCircleVec2(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, final Vert2fImmutable d) {
+ final float[] A = a.getCoord();
+ final float[] B = b.getCoord();
+ final float[] C = c.getCoord();
+ final float[] D = d.getCoord();
+ return (A[0] * A[0] + A[1] * A[1]) * triAreaVec2(B, C, D) -
+ (B[0] * B[0] + B[1] * B[1]) * triAreaVec2(A, C, D) +
+ (C[0] * C[0] + C[1] * C[1]) * triAreaVec2(A, B, D) -
+ (D[0] * D[0] + D[1] * D[1]) * triAreaVec2(A, B, C) > 0;
+ }
+
+ /**
+ * Computes oriented area of a triangle
+ * @param a first vertex
+ * @param b second vertex
+ * @param c third vertex
+ * @return compute twice the area of the oriented triangle (a,b,c), the area
+ * is positive if the triangle is oriented counterclockwise.
+ */
+ public static float triAreaVec2(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c){
+ final float[] A = a.getCoord();
+ final float[] B = b.getCoord();
+ final float[] C = c.getCoord();
+ return (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
+ }
+
+ /**
+ * Computes oriented area of a triangle
+ * @param A first vertex
+ * @param B second vertex
+ * @param C third vertex
+ * @return compute twice the area of the oriented triangle (a,b,c), the area
+ * is positive if the triangle is oriented counterclockwise.
+ */
+ public static float triAreaVec2(final float[] A, final float[] B, final float[] C){
+ return (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1])*(C[0] - A[0]);
+ }
+
+ /**
+ * Check if a vertex is in triangle using
+ * barycentric coordinates computation.
+ * @param a first triangle vertex
+ * @param b second triangle vertex
+ * @param c third triangle vertex
+ * @param p the vertex in question
+ * @return true if p is in triangle (a, b, c), false otherwise.
+ */
+ public static boolean isInTriangleVec3(final float[] a, final float[] b, final float[] c,
+ final float[] p,
+ final float[] ac, final float[] ab, final float[] ap){
+ // Compute vectors
+ subVec3(ac, c, a); //v0
+ subVec3(ab, b, a); //v1
+ subVec3(ap, p, a); //v2
+
+ // Compute dot products
+ final float dotAC_AC = dotVec3(ac, ac);
+ final float dotAC_AB = dotVec3(ac, ab);
+ final float dotAB_AB = dotVec3(ab, ab);
+ final float dotAC_AP = dotVec3(ac, ap);
+ final float dotAB_AP = dotVec3(ab, ap);
+
+ // Compute barycentric coordinates
+ final float invDenom = 1 / (dotAC_AC * dotAB_AB - dotAC_AB * dotAC_AB);
+ final float u = (dotAB_AB * dotAC_AP - dotAC_AB * dotAB_AP) * invDenom;
+ final float v = (dotAC_AC * dotAB_AP - dotAC_AB * dotAC_AP) * invDenom;
+
+ // Check if point is in triangle
+ return (u >= 0) && (v >= 0) && (u + v < 1);
+ }
+
+ /**
+ * Check if one of three vertices are in triangle using
+ * barycentric coordinates computation.
+ * @param a first triangle vertex
+ * @param b second triangle vertex
+ * @param c third triangle vertex
+ * @param p1 the vertex in question
+ * @param p2 the vertex in question
+ * @param p3 the vertex in question
+ * @param tmpAC
+ * @param tmpAB
+ * @param tmpAP
+ * @return true if p1 or p2 or p3 is in triangle (a, b, c), false otherwise.
+ */
+ public static boolean isVec3InTriangle3(final float[] a, final float[] b, final float[] c,
+ final float[] p1, final float[] p2, final float[] p3,
+ final float[] tmpAC, final float[] tmpAB, final float[] tmpAP){
+ // Compute vectors
+ subVec3(tmpAC, c, a); //v0
+ subVec3(tmpAB, b, a); //v1
+
+ // Compute dot products
+ final float dotAC_AC = dotVec3(tmpAC, tmpAC);
+ final float dotAC_AB = dotVec3(tmpAC, tmpAB);
+ final float dotAB_AB = dotVec3(tmpAB, tmpAB);
+
+ // Compute barycentric coordinates
+ final float invDenom = 1 / (dotAC_AC * dotAB_AB - dotAC_AB * dotAC_AB);
+ {
+ subVec3(tmpAP, p1, a); //v2
+ final float dotAC_AP1 = dotVec3(tmpAC, tmpAP);
+ final float dotAB_AP1 = dotVec3(tmpAB, tmpAP);
+ final float u = (dotAB_AB * dotAC_AP1 - dotAC_AB * dotAB_AP1) * invDenom;
+ final float v = (dotAC_AC * dotAB_AP1 - dotAC_AB * dotAC_AP1) * invDenom;
+
+ // Check if point is in triangle
+ if ( (u >= 0) && (v >= 0) && (u + v < 1) ) {
+ return true;
+ }
+ }
+
+ {
+ subVec3(tmpAP, p1, a); //v2
+ final float dotAC_AP2 = dotVec3(tmpAC, tmpAP);
+ final float dotAB_AP2 = dotVec3(tmpAB, tmpAP);
+ final float u = (dotAB_AB * dotAC_AP2 - dotAC_AB * dotAB_AP2) * invDenom;
+ final float v = (dotAC_AC * dotAB_AP2 - dotAC_AB * dotAC_AP2) * invDenom;
+
+ // Check if point is in triangle
+ if ( (u >= 0) && (v >= 0) && (u + v < 1) ) {
+ return true;
+ }
+ }
+
+ {
+ subVec3(tmpAP, p2, a); //v2
+ final float dotAC_AP3 = dotVec3(tmpAC, tmpAP);
+ final float dotAB_AP3 = dotVec3(tmpAB, tmpAP);
+ final float u = (dotAB_AB * dotAC_AP3 - dotAC_AB * dotAB_AP3) * invDenom;
+ final float v = (dotAC_AC * dotAB_AP3 - dotAC_AB * dotAC_AP3) * invDenom;
+
+ // Check if point is in triangle
+ if ( (u >= 0) && (v >= 0) && (u + v < 1) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+ /**
+ * Check if one of three vertices are in triangle using
+ * barycentric coordinates computation, using given epsilon for comparison.
+ * @param a first triangle vertex
+ * @param b second triangle vertex
+ * @param c third triangle vertex
+ * @param p1 the vertex in question
+ * @param p2 the vertex in question
+ * @param p3 the vertex in question
+ * @param tmpAC
+ * @param tmpAB
+ * @param tmpAP
+ * @return true if p1 or p2 or p3 is in triangle (a, b, c), false otherwise.
+ */
+ public static boolean isVec3InTriangle3(final float[] a, final float[] b, final float[] c,
+ final float[] p1, final float[] p2, final float[] p3,
+ final float[] tmpAC, final float[] tmpAB, final float[] tmpAP,
+ final float epsilon){
+ // Compute vectors
+ subVec3(tmpAC, c, a); //v0
+ subVec3(tmpAB, b, a); //v1
+
+ // Compute dot products
+ final float dotAC_AC = dotVec3(tmpAC, tmpAC);
+ final float dotAC_AB = dotVec3(tmpAC, tmpAB);
+ final float dotAB_AB = dotVec3(tmpAB, tmpAB);
+
+ // Compute barycentric coordinates
+ final float invDenom = 1 / (dotAC_AC * dotAB_AB - dotAC_AB * dotAC_AB);
+ {
+ subVec3(tmpAP, p1, a); //v2
+ final float dotAC_AP1 = dotVec3(tmpAC, tmpAP);
+ final float dotAB_AP1 = dotVec3(tmpAB, tmpAP);
+ final float u = (dotAB_AB * dotAC_AP1 - dotAC_AB * dotAB_AP1) * invDenom;
+ final float v = (dotAC_AC * dotAB_AP1 - dotAC_AB * dotAC_AP1) * invDenom;
+
+ // Check if point is in triangle
+ if( FloatUtil.compare(u, 0.0f, epsilon) >= 0 &&
+ FloatUtil.compare(v, 0.0f, epsilon) >= 0 &&
+ FloatUtil.compare(u+v, 1.0f, epsilon) < 0 ) {
+ return true;
+ }
+ }
+
+ {
+ subVec3(tmpAP, p1, a); //v2
+ final float dotAC_AP2 = dotVec3(tmpAC, tmpAP);
+ final float dotAB_AP2 = dotVec3(tmpAB, tmpAP);
+ final float u = (dotAB_AB * dotAC_AP2 - dotAC_AB * dotAB_AP2) * invDenom;
+ final float v = (dotAC_AC * dotAB_AP2 - dotAC_AB * dotAC_AP2) * invDenom;
+
+ // Check if point is in triangle
+ if( FloatUtil.compare(u, 0.0f, epsilon) >= 0 &&
+ FloatUtil.compare(v, 0.0f, epsilon) >= 0 &&
+ FloatUtil.compare(u+v, 1.0f, epsilon) < 0 ) {
+ return true;
+ }
+ }
+
+ {
+ subVec3(tmpAP, p2, a); //v2
+ final float dotAC_AP3 = dotVec3(tmpAC, tmpAP);
+ final float dotAB_AP3 = dotVec3(tmpAB, tmpAP);
+ final float u = (dotAB_AB * dotAC_AP3 - dotAC_AB * dotAB_AP3) * invDenom;
+ final float v = (dotAC_AC * dotAB_AP3 - dotAC_AB * dotAC_AP3) * invDenom;
+
+ // Check if point is in triangle
+ if( FloatUtil.compare(u, 0.0f, epsilon) >= 0 &&
+ FloatUtil.compare(v, 0.0f, epsilon) >= 0 &&
+ FloatUtil.compare(u+v, 1.0f, epsilon) < 0 ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /** Check if points are in ccw order
+ * @param a first vertex
+ * @param b second vertex
+ * @param c third vertex
+ * @return true if the points a,b,c are in a ccw order
+ */
+ public static boolean ccw(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c){
+ return triAreaVec2(a,b,c) > 0;
+ }
+
+ /** Compute the winding of given points
+ * @param a first vertex
+ * @param b second vertex
+ * @param c third vertex
+ * @return Winding
+ */
+ public static Winding getWinding(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c) {
+ return triAreaVec2(a,b,c) > 0 ? Winding.CCW : Winding.CW ;
+ }
+
+ /** Computes the area of a list of vertices to check if ccw
+ * @param vertices
+ * @return positive area if ccw else negative area value
+ */
+ public static float area(final ArrayList<? extends Vert2fImmutable> vertices) {
+ final int n = vertices.size();
+ float area = 0.0f;
+ for (int p = n - 1, q = 0; q < n; p = q++)
+ {
+ final float[] pCoord = vertices.get(p).getCoord();
+ final float[] qCoord = vertices.get(q).getCoord();
+ area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1];
+ }
+ return area;
+ }
+
+ /** Compute the general winding of the vertices
+ * @param vertices array of Vertices
+ * @return CCW or CW {@link Winding}
+ */
+ public static Winding getWinding(final ArrayList<? extends Vert2fImmutable> vertices) {
+ return area(vertices) >= 0 ? Winding.CCW : Winding.CW ;
+ }
+
+ /**
+ * @param result vec2 result for normal
+ * @param v1 vec2
+ * @param v2 vec2
+ * @return result for chaining
+ */
+ public static float[] getNormalVec2(final float[] result, final float[] v1, final float[] v2 ) {
+ subVec2(result, v2, v1);
+ final float tmp = result [ 0 ] ; result [ 0 ] = -result [ 1 ] ; result [ 1 ] = tmp ;
+ return normalizeVec2 ( result ) ;
+ }
+
+ /**
+ * Returns the 3d surface normal of a triangle given three vertices.
+ *
+ * @param result vec3 result for normal
+ * @param v1 vec3
+ * @param v2 vec3
+ * @param v3 vec3
+ * @param tmp1Vec3 temp vec3
+ * @param tmp2Vec3 temp vec3
+ * @return result for chaining
+ */
+ public static float[] getNormalVec3(final float[] result, final float[] v1, final float[] v2, final float[] v3,
+ final float[] tmp1Vec3, final float[] tmp2Vec3) {
+ subVec3 ( tmp1Vec3, v2, v1 );
+ subVec3 ( tmp2Vec3, v3, v1 ) ;
+ return normalizeVec3 ( crossVec3(result, tmp1Vec3, tmp2Vec3) ) ;
+ }
+
+ /**
+ * Finds the plane equation of a plane given its normal and a point on the plane.
+ *
+ * @param resultV4 vec4 plane equation
+ * @param normalVec3
+ * @param pVec3
+ * @return result for chaining
+ */
+ public static float[] getPlaneVec3(final float[/*4*/] resultV4, final float[] normalVec3, final float[] pVec3) {
+ /**
+ Ax + By + Cz + D == 0 ;
+ D = - ( Ax + By + Cz )
+ = - ( A*a[0] + B*a[1] + C*a[2] )
+ = - vec3Dot ( normal, a ) ;
+ */
+ System.arraycopy(normalVec3, 0, resultV4, 0, 3);
+ resultV4 [ 3 ] = -dotVec3(normalVec3, pVec3) ;
+ return resultV4;
+ }
+
+ /**
+ * This finds the plane equation of a triangle given three vertices.
+ *
+ * @param resultVec4 vec4 plane equation
+ * @param v1 vec3
+ * @param v2 vec3
+ * @param v3 vec3
+ * @param temp1V3
+ * @param temp2V3
+ * @return result for chaining
+ */
+ public static float[] getPlaneVec3(final float[/*4*/] resultVec4, final float[] v1, final float[] v2, final float[] v3,
+ final float[] temp1V3, final float[] temp2V3) {
+ /**
+ Ax + By + Cz + D == 0 ;
+ D = - ( Ax + By + Cz )
+ = - ( A*a[0] + B*a[1] + C*a[2] )
+ = - vec3Dot ( normal, a ) ;
+ */
+ getNormalVec3( resultVec4, v1, v2, v3, temp1V3, temp2V3 ) ;
+ resultVec4 [ 3 ] = -dotVec3 (resultVec4, v1) ;
+ return resultVec4;
+ }
+
+ /**
+ * Return intersection of an infinite line with a plane if exists, otherwise null.
+ * <p>
+ * Thanks to <i>Norman Vine -- [email protected] (with hacks by Steve)</i>
+ * </p>
+ *
+ * @param result vec3 result buffer for intersecting coords
+ * @param ray here representing an infinite line, origin and direction.
+ * @param plane vec4 plane equation
+ * @param epsilon
+ * @return resulting intersecting if exists, otherwise null
+ */
+ public static float[] line2PlaneIntersection(final float[] result, final Ray ray, final float[/*4*/] plane, final float epsilon) {
+ final float tmp = dotVec3(ray.dir, plane) ;
+
+ if ( Math.abs(tmp) < epsilon ) {
+ return null; // ray is parallel to plane
+ }
+ scaleVec3 ( result, ray.dir, -( dotVec3(ray.orig, plane) + plane[3] ) / tmp ) ;
+ return addVec3(result, result, ray.orig);
+ }
+
+ /** Compute intersection between two segments
+ * @param a vertex 1 of first segment
+ * @param b vertex 2 of first segment
+ * @param c vertex 1 of second segment
+ * @param d vertex 2 of second segment
+ * @return the intersection coordinates if the segments intersect, otherwise returns null
+ */
+ public static float[] seg2SegIntersection(final float[] result, final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, final Vert2fImmutable d) {
+ final float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
+
+ if (determinant == 0)
+ return null;
+
+ final float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
+ final float beta = (c.getX()*d.getY()-c.getY()*d.getY());
+ final float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
+ final float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
+
+ final float gamma = (xi - a.getX())/(b.getX() - a.getX());
+ final float gamma1 = (xi - c.getX())/(d.getX() - c.getX());
+ if(gamma <= 0 || gamma >= 1) return null;
+ if(gamma1 <= 0 || gamma1 >= 1) return null;
+
+ result[0] = xi;
+ result[1] = yi;
+ result[2] = 0;
+ return result;
+ }
+
+ /**
+ * Compute intersection between two segments
+ * @param a vertex 1 of first segment
+ * @param b vertex 2 of first segment
+ * @param c vertex 1 of second segment
+ * @param d vertex 2 of second segment
+ * @return true if the segments intersect, otherwise returns false
+ */
+ public static boolean testSeg2SegIntersection(final Vert2fImmutable a, final Vert2fImmutable b,
+ final Vert2fImmutable c, final Vert2fImmutable d) {
+ final float[] A = a.getCoord();
+ final float[] B = b.getCoord();
+ final float[] C = c.getCoord();
+ final float[] D = d.getCoord();
+
+ final float determinant = (A[0]-B[0])*(C[1]-D[1]) - (A[1]-B[1])*(C[0]-D[0]);
+
+ if (determinant == 0) {
+ return false;
+ }
+
+ final float alpha = (A[0]*B[1]-A[1]*B[0]);
+ final float beta = (C[0]*D[1]-C[1]*D[1]);
+ final float xi = ((C[0]-D[0])*alpha-(A[0]-B[0])*beta)/determinant;
+
+ final float gamma0 = (xi - A[0])/(B[0] - A[0]);
+ final float gamma1 = (xi - C[0])/(D[0] - C[0]);
+ if(gamma0 <= 0 || gamma0 >= 1 || gamma1 <= 0 || gamma1 >= 1) {
+ return false;
+ }
+
+ return true;
+ }
+ /**
+ * Compute intersection between two segments, using given epsilon for comparison.
+ * @param a vertex 1 of first segment
+ * @param b vertex 2 of first segment
+ * @param c vertex 1 of second segment
+ * @param d vertex 2 of second segment
+ * @return true if the segments intersect, otherwise returns false
+ */
+ public static boolean testSeg2SegIntersection(final Vert2fImmutable a, final Vert2fImmutable b,
+ final Vert2fImmutable c, final Vert2fImmutable d,
+ final float epsilon) {
+ final float[] A = a.getCoord();
+ final float[] B = b.getCoord();
+ final float[] C = c.getCoord();
+ final float[] D = d.getCoord();
+
+ final float determinant = (A[0]-B[0])*(C[1]-D[1]) - (A[1]-B[1])*(C[0]-D[0]);
+
+ if ( FloatUtil.isZero(determinant, epsilon) ) {
+ return false;
+ }
+
+ final float alpha = (A[0]*B[1]-A[1]*B[0]);
+ final float beta = (C[0]*D[1]-C[1]*D[1]);
+ final float xi = ((C[0]-D[0])*alpha-(A[0]-B[0])*beta)/determinant;
+
+ final float gamma0 = (xi - A[0])/(B[0] - A[0]);
+ final float gamma1 = (xi - C[0])/(D[0] - C[0]);
+ if( FloatUtil.compare(gamma0, 0.0f, epsilon) <= 0 ||
+ FloatUtil.compare(gamma0, 1.0f, epsilon) >= 0 ||
+ FloatUtil.compare(gamma1, 0.0f, epsilon) <= 0 ||
+ FloatUtil.compare(gamma1, 1.0f, epsilon) >= 0 ) {
+ return false;
+ }
+
+ if(gamma0 <= 0 || gamma0 >= 1 || gamma1 <= 0 || gamma1 >= 1) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Compute intersection between two lines
+ * @param a vertex 1 of first line
+ * @param b vertex 2 of first line
+ * @param c vertex 1 of second line
+ * @param d vertex 2 of second line
+ * @return the intersection coordinates if the lines intersect, otherwise
+ * returns null
+ */
+ public static float[] line2lineIntersection(final float[] result,
+ final Vert2fImmutable a, final Vert2fImmutable b,
+ final Vert2fImmutable c, final Vert2fImmutable d) {
+ final float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
+
+ if (determinant == 0)
+ return null;
+
+ final float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
+ final float beta = (c.getX()*d.getY()-c.getY()*d.getY());
+ final float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
+ final float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
+
+ result[0] = xi;
+ result[1] = yi;
+ result[2] = 0;
+ return result;
+ }
+
+ /**
+ * Check if a segment intersects with a triangle
+ * @param a vertex 1 of the triangle
+ * @param b vertex 2 of the triangle
+ * @param c vertex 3 of the triangle
+ * @param d vertex 1 of first segment
+ * @param e vertex 2 of first segment
+ * @return true if the segment intersects at least one segment of the triangle, false otherwise
+ */
+ public static boolean testTri2SegIntersection(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c,
+ final Vert2fImmutable d, final Vert2fImmutable e){
+ return testSeg2SegIntersection(a, b, d, e) ||
+ testSeg2SegIntersection(b, c, d, e) ||
+ testSeg2SegIntersection(a, c, d, e) ;
+ }
+ /**
+ * Check if a segment intersects with a triangle, using given epsilon for comparison.
+ * @param a vertex 1 of the triangle
+ * @param b vertex 2 of the triangle
+ * @param c vertex 3 of the triangle
+ * @param d vertex 1 of first segment
+ * @param e vertex 2 of first segment
+ * @return true if the segment intersects at least one segment of the triangle, false otherwise
+ */
+ public static boolean testTri2SegIntersection(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c,
+ final Vert2fImmutable d, final Vert2fImmutable e,
+ final float epsilon){
+ return testSeg2SegIntersection(a, b, d, e, epsilon) ||
+ testSeg2SegIntersection(b, c, d, e, epsilon) ||
+ testSeg2SegIntersection(a, c, d, e, epsilon) ;
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UITextShape.java b/src/jogl/classes/com/jogamp/opengl/math/Vert2fImmutable.java
index ee79d9a0b..ec90b401f 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UITextShape.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/Vert2fImmutable.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright 2012 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -25,13 +25,15 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package com.jogamp.opengl.test.junit.graph.demos.ui;
+package com.jogamp.opengl.math;
-import jogamp.graph.curve.text.GlyphString;
+public interface Vert2fImmutable {
+ float getX();
+
+ float getY();
+
+ int getCoordCount();
+
+ float[] getCoord();
-/**
- * Marker interface to mark a UIShape implementation for text usage
- */
-public interface UITextShape {
- GlyphString getGlyphString();
}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.java b/src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.java
new file mode 100644
index 000000000..76bd02fbc
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.math;
+
+public interface Vert3fImmutable extends Vert2fImmutable {
+ float getZ();
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java b/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java
new file mode 100644
index 000000000..29cc2b51a
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java
@@ -0,0 +1,761 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.math.geom;
+
+import jogamp.graph.geom.plane.AffineTransform;
+
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.Ray;
+import com.jogamp.opengl.math.VectorUtil;
+
+
+/**
+ * Axis Aligned Bounding Box. Defined by two 3D coordinates (low and high)
+ * The low being the the lower left corner of the box, and the high being the upper
+ * right corner of the box.
+ * <p>
+ * A few references for collision detection, intersections:
+ * <pre>
+ * http://www.realtimerendering.com/intersections.html
+ * http://www.codercorner.com/RayAABB.cpp
+ * http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter0.htm
+ * http://realtimecollisiondetection.net/files/levine_swept_sat.txt
+ * </pre>
+ * </p>
+ *
+ */
+public class AABBox {
+ private static final boolean DEBUG = FloatUtil.DEBUG;
+ private final float[] low = new float[3];
+ private final float[] high = new float[3];
+ private final float[] center = new float[3];
+
+ /**
+ * Create an Axis Aligned bounding box (AABBox)
+ * where the low and and high MAX float Values.
+ */
+ public AABBox() {
+ reset();
+ }
+
+ /**
+ * Create an AABBox copying all values from the given one
+ * @param src the box value to be used for the new instance
+ */
+ public AABBox(final AABBox src) {
+ copy(src);
+ }
+
+ /**
+ * Create an AABBox specifying the coordinates
+ * of the low and high
+ * @param lx min x-coordinate
+ * @param ly min y-coordnate
+ * @param lz min z-coordinate
+ * @param hx max x-coordinate
+ * @param hy max y-coordinate
+ * @param hz max z-coordinate
+ */
+ public AABBox(final float lx, final float ly, final float lz,
+ final float hx, final float hy, final float hz) {
+ setSize(lx, ly, lz, hx, hy, hz);
+ }
+
+ /**
+ * Create a AABBox defining the low and high
+ * @param low min xyz-coordinates
+ * @param high max xyz-coordinates
+ */
+ public AABBox(final float[] low, final float[] high) {
+ setSize(low, high);
+ }
+
+ /**
+ * resets this box to the inverse low/high, allowing the next {@link #resize(float, float, float)} command to hit.
+ * @return this AABBox for chaining
+ */
+ public final AABBox reset() {
+ setLow(Float.MAX_VALUE,Float.MAX_VALUE,Float.MAX_VALUE);
+ setHigh(-1*Float.MAX_VALUE,-1*Float.MAX_VALUE,-1*Float.MAX_VALUE);
+ center[0] = 0f;
+ center[1] = 0f;
+ center[2] = 0f;
+ return this;
+ }
+
+ /** Get the max xyz-coordinates
+ * @return a float array containing the max xyz coordinates
+ */
+ public final float[] getHigh() {
+ return high;
+ }
+
+ private final void setHigh(final float hx, final float hy, final float hz) {
+ this.high[0] = hx;
+ this.high[1] = hy;
+ this.high[2] = hz;
+ }
+
+ /** Get the min xyz-coordinates
+ * @return a float array containing the min xyz coordinates
+ */
+ public final float[] getLow() {
+ return low;
+ }
+
+ private final void setLow(final float lx, final float ly, final float lz) {
+ this.low[0] = lx;
+ this.low[1] = ly;
+ this.low[2] = lz;
+ }
+
+ private final void computeCenter() {
+ center[0] = (high[0] + low[0])/2f;
+ center[1] = (high[1] + low[1])/2f;
+ center[2] = (high[2] + low[2])/2f;
+ }
+
+ /**
+ * Copy given AABBox 'src' values to this AABBox.
+ *
+ * @param src source AABBox
+ * @return this AABBox for chaining
+ */
+ public final AABBox copy(final AABBox src) {
+ System.arraycopy(src.low, 0, low, 0, 3);
+ System.arraycopy(src.high, 0, high, 0, 3);
+ System.arraycopy(src.center, 0, center, 0, 3);
+ return this;
+ }
+
+ /**
+ * Set size of the AABBox specifying the coordinates
+ * of the low and high.
+ *
+ * @param low min xyz-coordinates
+ * @param high max xyz-coordinates
+ * @return this AABBox for chaining
+ */
+ public final AABBox setSize(final float[] low, final float[] high) {
+ return setSize(low[0],low[1],low[2], high[0],high[1],high[2]);
+ }
+
+ /**
+ * Set size of the AABBox specifying the coordinates
+ * of the low and high.
+ *
+ * @param lx min x-coordinate
+ * @param ly min y-coordnate
+ * @param lz min z-coordinate
+ * @param hx max x-coordinate
+ * @param hy max y-coordinate
+ * @param hz max z-coordinate
+ * @return this AABBox for chaining
+ */
+ public final AABBox setSize(final float lx, final float ly, final float lz,
+ final float hx, final float hy, final float hz) {
+ this.low[0] = lx;
+ this.low[1] = ly;
+ this.low[2] = lz;
+ this.high[0] = hx;
+ this.high[1] = hy;
+ this.high[2] = hz;
+ computeCenter();
+ return this;
+ }
+
+ /**
+ * Resize the AABBox to encapsulate another AABox
+ * @param newBox AABBox to be encapsulated in
+ * @return this AABBox for chaining
+ */
+ public final AABBox resize(final AABBox newBox) {
+ final float[] newLow = newBox.getLow();
+ final float[] newHigh = newBox.getHigh();
+
+ /** test low */
+ if (newLow[0] < low[0])
+ low[0] = newLow[0];
+ if (newLow[1] < low[1])
+ low[1] = newLow[1];
+ if (newLow[2] < low[2])
+ low[2] = newLow[2];
+
+ /** test high */
+ if (newHigh[0] > high[0])
+ high[0] = newHigh[0];
+ if (newHigh[1] > high[1])
+ high[1] = newHigh[1];
+ if (newHigh[2] > high[2])
+ high[2] = newHigh[2];
+
+ computeCenter();
+ return this;
+ }
+
+ /**
+ * Resize the AABBox to encapsulate another AABox, which will be <i>transformed</i> on the fly first.
+ * @param newBox AABBox to be encapsulated in
+ * @param t the {@link AffineTransform} applied on <i>newBox</i> on the fly
+ * @param tmpV3 temp float[3] storage
+ * @return this AABBox for chaining
+ */
+ public final AABBox resize(final AABBox newBox, final AffineTransform t, final float[] tmpV3) {
+ /** test low */
+ {
+ final float[] newBoxLow = newBox.getLow();
+ t.transform(newBoxLow, tmpV3);
+ tmpV3[2] = newBoxLow[2];
+ if (tmpV3[0] < low[0])
+ low[0] = tmpV3[0];
+ if (tmpV3[1] < low[1])
+ low[1] = tmpV3[1];
+ if (tmpV3[2] < low[2])
+ low[2] = tmpV3[2];
+ }
+
+ /** test high */
+ {
+ final float[] newBoxHigh = newBox.getHigh();
+ t.transform(newBoxHigh, tmpV3);
+ tmpV3[2] = newBoxHigh[2];
+ if (tmpV3[0] > high[0])
+ high[0] = tmpV3[0];
+ if (tmpV3[1] > high[1])
+ high[1] = tmpV3[1];
+ if (tmpV3[2] > high[2])
+ high[2] = tmpV3[2];
+ }
+
+ computeCenter();
+ return this;
+ }
+
+ /**
+ * Resize the AABBox to encapsulate the passed
+ * xyz-coordinates.
+ * @param x x-axis coordinate value
+ * @param y y-axis coordinate value
+ * @param z z-axis coordinate value
+ * @return this AABBox for chaining
+ */
+ public final AABBox resize(final float x, final float y, final float z) {
+ /** test low */
+ if (x < low[0]) {
+ low[0] = x;
+ }
+ if (y < low[1]) {
+ low[1] = y;
+ }
+ if (z < low[2]) {
+ low[2] = z;
+ }
+
+ /** test high */
+ if (x > high[0]) {
+ high[0] = x;
+ }
+ if (y > high[1]) {
+ high[1] = y;
+ }
+ if (z > high[2]) {
+ high[2] = z;
+ }
+
+ computeCenter();
+ return this;
+ }
+
+ /**
+ * Resize the AABBox to encapsulate the passed
+ * xyz-coordinates.
+ * @param xyz xyz-axis coordinate values
+ * @param offset of the array
+ * @return this AABBox for chaining
+ */
+ public final AABBox resize(final float[] xyz, final int offset) {
+ return resize(xyz[0+offset], xyz[1+offset], xyz[2+offset]);
+ }
+
+ /**
+ * Resize the AABBox to encapsulate the passed
+ * xyz-coordinates.
+ * @param xyz xyz-axis coordinate values
+ * @return this AABBox for chaining
+ */
+ public final AABBox resize(final float[] xyz) {
+ return resize(xyz[0], xyz[1], xyz[2]);
+ }
+
+ /**
+ * Check if the x & y coordinates are bounded/contained
+ * by this AABBox
+ * @param x x-axis coordinate value
+ * @param y y-axis coordinate value
+ * @return true if x belong to (low.x, high.x) and
+ * y belong to (low.y, high.y)
+ */
+ public final boolean contains(final float x, final float y) {
+ if(x<low[0] || x>high[0]){
+ return false;
+ }
+ if(y<low[1]|| y>high[1]){
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check if the xyz coordinates are bounded/contained
+ * by this AABBox.
+ * @param x x-axis coordinate value
+ * @param y y-axis coordinate value
+ * @param z z-axis coordinate value
+ * @return true if x belong to (low.x, high.x) and
+ * y belong to (low.y, high.y) and z belong to (low.z, high.z)
+ */
+ public final boolean contains(final float x, final float y, final float z) {
+ if(x<low[0] || x>high[0]){
+ return false;
+ }
+ if(y<low[1]|| y>high[1]){
+ return false;
+ }
+ if(z<low[2] || z>high[2]){
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check if there is a common region between this AABBox and the passed
+ * 2D region irrespective of z range
+ * @param x lower left x-coord
+ * @param y lower left y-coord
+ * @param w width
+ * @param h hight
+ * @return true if this AABBox might have a common region with this 2D region
+ */
+ public final boolean intersects2DRegion(final float x, final float y, final float w, final float h) {
+ if (w <= 0 || h <= 0) {
+ return false;
+ }
+
+ final float _w = getWidth();
+ final float _h = getHeight();
+ if (_w <= 0 || _h <= 0) {
+ return false;
+ }
+
+ final float x0 = getMinX();
+ final float y0 = getMinY();
+ return (x + w > x0 &&
+ y + h > y0 &&
+ x < x0 + _w &&
+ y < y0 + _h);
+ }
+
+ /**
+ * Check if {@link Ray} intersects this bounding box.
+ * <p>
+ * Versions uses the SAT[1], testing 6 axes.
+ * Original code for OBBs from MAGIC.
+ * Rewritten for AABBs and reorganized for early exits[2].
+ * </p>
+ * <pre>
+ * [1] SAT = Separating Axis Theorem
+ * [2] http://www.codercorner.com/RayAABB.cpp
+ * </pre>
+ * @param ray
+ * @return
+ */
+ public final boolean intersectsRay(final Ray ray) {
+ // diff[XYZ] -> VectorUtil.subVec3(diff, ray.orig, center);
+ // ext[XYZ] -> extend VectorUtil.subVec3(ext, high, center);
+
+ final float dirX = ray.dir[0];
+ final float diffX = ray.orig[0] - center[0];
+ final float extX = high[0] - center[0];
+ if( Math.abs(diffX) > extX && diffX*dirX >= 0f ) return false;
+
+ final float dirY = ray.dir[1];
+ final float diffY = ray.orig[1] - center[1];
+ final float extY = high[1] - center[1];
+ if( Math.abs(diffY) > extY && diffY*dirY >= 0f ) return false;
+
+ final float dirZ = ray.dir[2];
+ final float diffZ = ray.orig[2] - center[2];
+ final float extZ = high[2] - center[2];
+ if( Math.abs(diffZ) > extZ && diffZ*dirZ >= 0f ) return false;
+
+ final float absDirY = Math.abs(dirY);
+ final float absDirZ = Math.abs(dirZ);
+
+ float f = dirY * diffZ - dirZ * diffY;
+ if( Math.abs(f) > extY*absDirZ + extZ*absDirY ) return false;
+
+ final float absDirX = Math.abs(dirX);
+
+ f = dirZ * diffX - dirX * diffZ;
+ if( Math.abs(f) > extX*absDirZ + extZ*absDirX ) return false;
+
+ f = dirX * diffY - dirY * diffX;
+ if( Math.abs(f) > extX*absDirY + extY*absDirX ) return false;
+
+ return true;
+ }
+
+ /**
+ * Return intersection of a {@link Ray} with this bounding box,
+ * or null if none exist.
+ * <p>
+ * <ul>
+ * <li>Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990 [2]</li>
+ * <li>Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)</li>
+ * <li>Epsilon value added by Klaus Hartmann.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Method is based on the requirements:
+ * <ul>
+ * <li>the integer representation of 0.0f is 0x00000000</li>
+ * <li>the sign bit of the float is the most significant one</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Report bugs: [email protected] (original author)
+ * </p>
+ * <pre>
+ * [1] http://www.codercorner.com/RayAABB.cpp
+ * [2] http://tog.acm.org/resources/GraphicsGems/gems/RayBox.c
+ * </pre>
+ * @param result vec3
+ * @param ray
+ * @param epsilon
+ * @param assumeIntersection if true, method assumes an intersection, i.e. by pre-checking via {@link #intersectsRay(Ray)}.
+ * In this case method will not validate a possible non-intersection and just computes
+ * coordinates.
+ * @param tmp1V3 temp vec3
+ * @param tmp2V3 temp vec3
+ * @param tmp3V3 temp vec3
+ * @return float[3] result of intersection coordinates, or null if none exists
+ */
+ public final float[] getRayIntersection(final float[] result, final Ray ray, final float epsilon,
+ final boolean assumeIntersection,
+ final float[] tmp1V3, final float[] tmp2V3, final float[] tmp3V3) {
+ final float[] maxT = { -1f, -1f, -1f };
+
+ final float[] origin = ray.orig;
+ final float[] dir = ray.dir;
+
+ boolean inside = true;
+
+ // Find candidate planes.
+ for(int i=0; i<3; i++) {
+ if(origin[i] < low[i]) {
+ result[i] = low[i];
+ inside = false;
+
+ // Calculate T distances to candidate planes
+ if( 0 != Float.floatToIntBits(dir[i]) ) {
+ maxT[i] = (low[i] - origin[i]) / dir[i];
+ }
+ } else if(origin[i] > high[i]) {
+ result[i] = high[i];
+ inside = false;
+
+ // Calculate T distances to candidate planes
+ if( 0 != Float.floatToIntBits(dir[i]) ) {
+ maxT[i] = (high[i] - origin[i]) / dir[i];
+ }
+ }
+ }
+
+ // Ray origin inside bounding box
+ if(inside) {
+ System.arraycopy(origin, 0, result, 0, 3);
+ return result;
+ }
+
+ // Get largest of the maxT's for final choice of intersection
+ int whichPlane = 0;
+ if(maxT[1] > maxT[whichPlane]) { whichPlane = 1; }
+ if(maxT[2] > maxT[whichPlane]) { whichPlane = 2; }
+
+ if( !assumeIntersection ) {
+ // Check final candidate actually inside box
+ if( 0 != ( Float.floatToIntBits(maxT[whichPlane]) & 0x80000000 ) ) {
+ return null;
+ }
+
+ /** Use unrolled version below ..
+ for(int i=0; i<3; i++) {
+ if( i!=whichPlane ) {
+ result[i] = origin[i] + maxT[whichPlane] * dir[i];
+ if(result[i] < minB[i] - epsilon || result[i] > maxB[i] + epsilon) { return null; }
+ // if(result[i] < minB[i] || result[i] > maxB[i] ) { return null; }
+ }
+ } */
+ switch( whichPlane ) {
+ case 0:
+ result[1] = origin[1] + maxT[whichPlane] * dir[1];
+ if(result[1] < low[1] - epsilon || result[1] > high[1] + epsilon) { return null; }
+ result[2] = origin[2] + maxT[whichPlane] * dir[2];
+ if(result[2] < low[2] - epsilon || result[2] > high[2] + epsilon) { return null; }
+ break;
+ case 1:
+ result[0] = origin[0] + maxT[whichPlane] * dir[0];
+ if(result[0] < low[0] - epsilon || result[0] > high[0] + epsilon) { return null; }
+ result[2] = origin[2] + maxT[whichPlane] * dir[2];
+ if(result[2] < low[2] - epsilon || result[2] > high[2] + epsilon) { return null; }
+ break;
+ case 2:
+ result[0] = origin[0] + maxT[whichPlane] * dir[0];
+ if(result[0] < low[0] - epsilon || result[0] > high[0] + epsilon) { return null; }
+ result[1] = origin[1] + maxT[whichPlane] * dir[1];
+ if(result[1] < low[1] - epsilon || result[1] > high[1] + epsilon) { return null; }
+ break;
+ default:
+ throw new InternalError("XXX");
+ }
+ } else {
+ switch( whichPlane ) {
+ case 0:
+ result[1] = origin[1] + maxT[whichPlane] * dir[1];
+ result[2] = origin[2] + maxT[whichPlane] * dir[2];
+ break;
+ case 1:
+ result[0] = origin[0] + maxT[whichPlane] * dir[0];
+ result[2] = origin[2] + maxT[whichPlane] * dir[2];
+ break;
+ case 2:
+ result[0] = origin[0] + maxT[whichPlane] * dir[0];
+ result[1] = origin[1] + maxT[whichPlane] * dir[1];
+ break;
+ default:
+ throw new InternalError("XXX");
+ }
+ }
+ return result; // ray hits box
+ }
+
+ /**
+ * Get the size of this AABBox where the size is represented by the
+ * length of the vector between low and high.
+ * @return a float representing the size of the AABBox
+ */
+ public final float getSize() {
+ return VectorUtil.distVec3(low, high);
+ }
+
+ /**
+ * Get the Center of this AABBox
+ * @return the xyz-coordinates of the center of the AABBox
+ */
+ public final float[] getCenter() {
+ return center;
+ }
+
+ /**
+ * Scale this AABBox by a constant
+ * @param size a constant float value
+ * @param tmpV3 caller provided temporary 3-component vector
+ * @return this AABBox for chaining
+ */
+ public final AABBox scale(final float size, final float[] tmpV3) {
+ tmpV3[0] = high[0] - center[0];
+ tmpV3[1] = high[1] - center[1];
+ tmpV3[2] = high[2] - center[2];
+
+ VectorUtil.scaleVec3(tmpV3, tmpV3, size); // in-place scale
+ VectorUtil.addVec3(high, center, tmpV3);
+
+ tmpV3[0] = low[0] - center[0];
+ tmpV3[1] = low[1] - center[1];
+ tmpV3[2] = low[2] - center[2];
+
+ VectorUtil.scaleVec3(tmpV3, tmpV3, size); // in-place scale
+ VectorUtil.addVec3(low, center, tmpV3);
+ return this;
+ }
+
+ /**
+ * Translate this AABBox by a float[3] vector
+ * @param t the float[3] translation vector
+ * @return this AABBox for chaining
+ */
+ public final AABBox translate(final float[] t) {
+ VectorUtil.addVec3(low, low, t); // in-place translate
+ VectorUtil.addVec3(high, high, t); // in-place translate
+ computeCenter();
+ return this;
+ }
+
+ /**
+ * Rotate this AABBox by a float[3] vector
+ * @param quat the {@link Quaternion} used for rotation
+ * @return this AABBox for chaining
+ */
+ public final AABBox rotate(final Quaternion quat) {
+ quat.rotateVector(low, 0, low, 0);
+ quat.rotateVector(high, 0, high, 0);
+ computeCenter();
+ return this;
+ }
+
+ public final float getMinX() {
+ return low[0];
+ }
+
+ public final float getMinY() {
+ return low[1];
+ }
+
+ public final float getMinZ() {
+ return low[2];
+ }
+
+ public final float getMaxX() {
+ return high[0];
+ }
+
+ public final float getMaxY() {
+ return high[1];
+ }
+
+ public final float getMaxZ() {
+ return high[2];
+ }
+
+ public final float getWidth(){
+ return high[0] - low[0];
+ }
+
+ public final float getHeight() {
+ return high[1] - low[1];
+ }
+
+ public final float getDepth() {
+ return high[2] - low[2];
+ }
+
+ @Override
+ public final boolean equals(final Object obj) {
+ if( obj == this ) {
+ return true;
+ }
+ if( null == obj || !(obj instanceof AABBox) ) {
+ return false;
+ }
+ final AABBox other = (AABBox) obj;
+ return VectorUtil.isVec2Equal(low, 0, other.low, 0, FloatUtil.EPSILON) &&
+ VectorUtil.isVec3Equal(high, 0, other.high, 0, FloatUtil.EPSILON) ;
+ }
+ @Override
+ public final int hashCode() {
+ throw new InternalError("hashCode not designed");
+ }
+
+ /**
+ * Assume this bounding box as being in object space and
+ * compute the window bounding box.
+ * <p>
+ * If <code>useCenterZ</code> is <code>true</code>,
+ * only 4 {@link FloatUtil#mapObjToWinCoords(float, float, float, float[], int[], int, float[], int, float[], float[]) mapObjToWinCoords}
+ * operations are made on points [1..4] using {@link #getCenter()}'s z-value.
+ * Otherwise 8 {@link FloatUtil#mapObjToWinCoords(float, float, float, float[], int[], int, float[], int, float[], float[]) mapObjToWinCoords}
+ * operation on all 8 points are performed.
+ * </p>
+ * <pre>
+ * [2] ------ [4]
+ * | |
+ * | |
+ * [1] ------ [3]
+ * </pre>
+ * @param mat4PMv P x Mv matrix
+ * @param view
+ * @param useCenterZ
+ * @param vec3Tmp0 3 component vector for temp storage
+ * @param vec4Tmp1 4 component vector for temp storage
+ * @param vec4Tmp2 4 component vector for temp storage
+ * @return
+ */
+ public AABBox mapToWindow(final AABBox result, final float[/*16*/] mat4PMv, final int[] view, final boolean useCenterZ,
+ final float[] vec3Tmp0, final float[] vec4Tmp1, final float[] vec4Tmp2) {
+ {
+ // System.err.printf("AABBox.mapToWindow.0: view[%d, %d, %d, %d], this %s%n", view[0], view[1], view[2], view[3], toString());
+ final float objZ = useCenterZ ? center[2] : getMinZ();
+ FloatUtil.mapObjToWinCoords(getMinX(), getMinY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2);
+ // System.err.printf("AABBox.mapToWindow.p1: %f, %f, %f -> %f, %f, %f%n", getMinX(), getMinY(), objZ, vec3Tmp0[0], vec3Tmp0[1], vec3Tmp0[2]);
+ // System.err.println("AABBox.mapToWindow.p1:");
+ // System.err.println(FloatUtil.matrixToString(null, " mat4PMv", "%10.5f", mat4PMv, 0, 4, 4, false /* rowMajorOrder */));
+
+ result.reset();
+ result.resize(vec3Tmp0, 0);
+
+ FloatUtil.mapObjToWinCoords(getMinX(), getMaxY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2);
+ // System.err.printf("AABBox.mapToWindow.p2: %f, %f, %f -> %f, %f, %f%n", getMinX(), getMaxY(), objZ, vec3Tmp0[0], vec3Tmp0[1], vec3Tmp0[2]);
+ result.resize(vec3Tmp0, 0);
+
+ FloatUtil.mapObjToWinCoords(getMaxX(), getMinY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2);
+ // System.err.printf("AABBox.mapToWindow.p3: %f, %f, %f -> %f, %f, %f%n", getMaxX(), getMinY(), objZ, vec3Tmp0[0], vec3Tmp0[1], vec3Tmp0[2]);
+ result.resize(vec3Tmp0, 0);
+
+ FloatUtil.mapObjToWinCoords(getMaxX(), getMaxY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2);
+ // System.err.printf("AABBox.mapToWindow.p4: %f, %f, %f -> %f, %f, %f%n", getMaxX(), getMaxY(), objZ, vec3Tmp0[0], vec3Tmp0[1], vec3Tmp0[2]);
+ result.resize(vec3Tmp0, 0);
+ }
+
+ if( !useCenterZ ) {
+ final float objZ = getMaxZ();
+ FloatUtil.mapObjToWinCoords(getMinX(), getMinY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2);
+ result.resize(vec3Tmp0, 0);
+
+ FloatUtil.mapObjToWinCoords(getMinX(), getMaxY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2);
+ result.resize(vec3Tmp0, 0);
+
+ FloatUtil.mapObjToWinCoords(getMaxX(), getMinY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2);
+ result.resize(vec3Tmp0, 0);
+
+ FloatUtil.mapObjToWinCoords(getMaxX(), getMaxY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2);
+ result.resize(vec3Tmp0, 0);
+ }
+ if( DEBUG ) {
+ System.err.printf("AABBox.mapToWindow: view[%d, %d], this %s -> %s%n", view[0], view[1], toString(), result.toString());
+ }
+ return result;
+ }
+
+ @Override
+ public final String toString() {
+ return "[ dim "+getWidth()+" x "+getHeight()+" x "+getDepth()+
+ ", box "+low[0]+" / "+low[1]+" / "+low[2]+" .. "+high[0]+" / "+high[1]+" / "+high[2]+
+ ", ctr "+center[0]+" / "+center[1]+" / "+center[2]+" ]";
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java b/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java
new file mode 100644
index 000000000..b73bad613
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java
@@ -0,0 +1,398 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.math.geom;
+
+import jogamp.common.os.PlatformPropsImpl;
+
+import com.jogamp.common.os.Platform;
+
+/**
+ * Providing frustum {@link #getPlanes() planes} derived by different inputs
+ * ({@link #updateByPMV(float[], int) P*MV}, ..) used to classify objects
+ * <ul>
+ * <li> {@link #classifyPoint(float[]) point} </li>
+ * <li> {@link #classifySphere(float[], float) sphere} </li>
+ * </ul>
+ * and to test whether they are outside
+ * <ul>
+ * <li> {@link #isPointOutside(float[]) point} </li>
+ * <li> {@link #isSphereOutside(float[], float) sphere} </li>
+ * <li> {@link #isAABBoxOutside(AABBox) bounding-box} </li>
+ * </ul>
+ *
+ * <p>
+ * Extracting the world-frustum planes from the P*Mv:
+ * <pre>
+ * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix
+ * Gil Gribb <[email protected]>
+ * Klaus Hartmann <[email protected]>
+ * http://graphics.cs.ucf.edu/cap4720/fall2008/plane_extraction.pdf
+ * </pre>
+ * Classifying Point, Sphere and AABBox:
+ * <pre>
+ * Efficient View Frustum Culling
+ * Daniel Sýkora <[email protected]>
+ * Josef Jelínek <[email protected]>
+ * http://www.cg.tuwien.ac.at/hostings/cescg/CESCG-2002/DSykoraJJelinek/index.html
+ * </pre>
+ * <pre>
+ * Lighthouse3d.com
+ * http://www.lighthouse3d.com/tutorials/view-frustum-culling/
+ * </pre>
+ *
+ * Fundamentals about Planes, Half-Spaces and Frustum-Culling:<br/>
+ * <pre>
+ * Planes and Half-Spaces, Max Wagner <[email protected]>
+ * http://www.emeyex.com/site/tuts/PlanesHalfSpaces.pdf
+ * </pre>
+ * <pre>
+ * Frustum Culling, Max Wagner <[email protected]>
+ * http://www.emeyex.com/site/tuts/FrustumCulling.pdf
+ * </pre>
+ * </p>
+ */
+public class Frustum {
+ /** Normalized planes[l, r, b, t, n, f] */
+ protected final Plane[] planes = new Plane[6];
+
+ /**
+ * Creates an undefined instance w/o calculating the frustum.
+ * <p>
+ * Use one of the <code>update(..)</code> methods to set the {@link #getPlanes() planes}.
+ * </p>
+ * @see #updateByPlanes(Plane[])
+ * @see #updateByPMV(float[], int)
+ */
+ public Frustum() {
+ for (int i = 0; i < 6; ++i) {
+ planes[i] = new Plane();
+ }
+ }
+
+ /**
+ * Plane equation := dot(n, x - p) = 0 -> ax + bc + cx + d == 0
+ * <p>
+ * In order to work w/ {@link Frustum#isOutside(AABBox) isOutside(..)} methods,
+ * the normals have to point to the inside of the frustum.
+ * </p>
+ */
+ public static class Plane {
+ /** Normal of the plane */
+ public final float[] n = new float[3];
+
+ /** Distance to origin */
+ public float d;
+
+ /**
+ * Return signed distance of plane to given point.
+ * <ul>
+ * <li>If dist &lt; 0 , then the point p lies in the negative halfspace.</li>
+ * <li>If dist = 0 , then the point p lies in the plane.</li>
+ * <li>If dist &gt; 0 , then the point p lies in the positive halfspace.</li>
+ * </ul>
+ * A plane cuts 3D space into 2 half spaces.
+ * <p>
+ * Positive halfspace is where the plane’s normals vector points into.
+ * </p>
+ * <p>
+ * Negative halfspace is the <i>other side</i> of the plane, i.e. *-1
+ * </p>
+ **/
+ public final float distanceTo(final float x, final float y, final float z) {
+ return n[0] * x + n[1] * y + n[2] * z + d;
+ }
+
+ /** Return distance of plane to given point, see {@link #distanceTo(float, float, float)}. */
+ public final float distanceTo(final float[] p) {
+ return n[0] * p[0] + n[1] * p[1] + n[2] * p[2] + d;
+ }
+
+ @Override
+ public String toString() {
+ return "Plane[ [ " + n[0] + ", " + n[1] + ", " + n[2] + " ], " + d + "]";
+ }
+ }
+
+ /** Index for left plane: {@value} */
+ public static final int LEFT = 0;
+ /** Index for right plane: {@value} */
+ public static final int RIGHT = 1;
+ /** Index for bottom plane: {@value} */
+ public static final int BOTTOM = 2;
+ /** Index for top plane: {@value} */
+ public static final int TOP = 3;
+ /** Index for near plane: {@value} */
+ public static final int NEAR = 4;
+ /** Index for far plane: {@value} */
+ public static final int FAR = 5;
+
+ /**
+ * {@link Plane}s are ordered in the returned array as follows:
+ * <ul>
+ * <li>{@link #LEFT}</li>
+ * <li>{@link #RIGHT}</li>
+ * <li>{@link #BOTTOM}</li>
+ * <li>{@link #TOP}</li>
+ * <li>{@link #NEAR}</li>
+ * <li>{@link #FAR}</li>
+ * </ul>
+ * <p>
+ * {@link Plane}'s normals are pointing to the inside of the frustum
+ * in order to work w/ {@link #isOutside(AABBox) isOutside(..)} methods.
+ * </p>
+ *
+ * @return array of normalized {@link Plane}s, order see above.
+ */
+ public final Plane[] getPlanes() { return planes; }
+
+ /**
+ * Copy the given <code>src</code> planes into this this instance's planes.
+ * @param src the 6 source planes
+ */
+ public final void updateByPlanes(final Plane[] src) {
+ for (int i = 0; i < 6; ++i) {
+ final Plane p0 = planes[i];
+ final float[] p0_n = p0.n;
+ final Plane p1 = src[i];
+ final float[] p1_n = p1.n;
+ p0_n[0] = p1_n[0];
+ p0_n[1] = p1_n[1];
+ p0_n[2] = p1_n[2];
+ p0.d = p1.d;
+ }
+ }
+
+ /**
+ * Calculate the frustum planes in world coordinates
+ * using the passed float[16] as premultiplied P*MV (column major order).
+ * <p>
+ * Frustum plane's normals will point to the inside of the viewing frustum,
+ * as required by this class.
+ * </p>
+ */
+ public void updateByPMV(final float[] pmv, final int pmv_off) {
+ // Left: a = m41 + m11, b = m42 + m12, c = m43 + m13, d = m44 + m14 - [1..4] column-major
+ // Left: a = m30 + m00, b = m31 + m01, c = m32 + m02, d = m33 + m03 - [0..3] column-major
+ {
+ final Plane p = planes[LEFT];
+ final float[] p_n = p.n;
+ p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 0 + 0 * 4 ];
+ p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 0 + 1 * 4 ];
+ p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 0 + 2 * 4 ];
+ p.d = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 0 + 3 * 4 ];
+ }
+
+ // Right: a = m41 - m11, b = m42 - m12, c = m43 - m13, d = m44 - m14 - [1..4] column-major
+ // Right: a = m30 - m00, b = m31 - m01, c = m32 - m02, d = m33 - m03 - [0..3] column-major
+ {
+ final Plane p = planes[RIGHT];
+ final float[] p_n = p.n;
+ p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 0 + 0 * 4 ];
+ p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 0 + 1 * 4 ];
+ p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 0 + 2 * 4 ];
+ p.d = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 0 + 3 * 4 ];
+ }
+
+ // Bottom: a = m41 + m21, b = m42 + m22, c = m43 + m23, d = m44 + m24 - [1..4] column-major
+ // Bottom: a = m30 + m10, b = m31 + m11, c = m32 + m12, d = m33 + m13 - [0..3] column-major
+ {
+ final Plane p = planes[BOTTOM];
+ final float[] p_n = p.n;
+ p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 1 + 0 * 4 ];
+ p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 1 + 1 * 4 ];
+ p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 1 + 2 * 4 ];
+ p.d = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 1 + 3 * 4 ];
+ }
+
+ // Top: a = m41 - m21, b = m42 - m22, c = m43 - m23, d = m44 - m24 - [1..4] column-major
+ // Top: a = m30 - m10, b = m31 - m11, c = m32 - m12, d = m33 - m13 - [0..3] column-major
+ {
+ final Plane p = planes[TOP];
+ final float[] p_n = p.n;
+ p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 1 + 0 * 4 ];
+ p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 1 + 1 * 4 ];
+ p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 1 + 2 * 4 ];
+ p.d = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 1 + 3 * 4 ];
+ }
+
+ // Near: a = m41 + m31, b = m42 + m32, c = m43 + m33, d = m44 + m34 - [1..4] column-major
+ // Near: a = m30 + m20, b = m31 + m21, c = m32 + m22, d = m33 + m23 - [0..3] column-major
+ {
+ final Plane p = planes[NEAR];
+ final float[] p_n = p.n;
+ p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 2 + 0 * 4 ];
+ p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 2 + 1 * 4 ];
+ p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 2 + 2 * 4 ];
+ p.d = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 2 + 3 * 4 ];
+ }
+
+ // Far: a = m41 - m31, b = m42 - m32, c = m43 - m33, d = m44 - m34 - [1..4] column-major
+ // Far: a = m30 - m20, b = m31 - m21, c = m32 + m22, d = m33 + m23 - [0..3] column-major
+ {
+ final Plane p = planes[FAR];
+ final float[] p_n = p.n;
+ p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 2 + 0 * 4 ];
+ p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 2 + 1 * 4 ];
+ p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 2 + 2 * 4 ];
+ p.d = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 2 + 3 * 4 ];
+ }
+
+ // Normalize all planes
+ for (int i = 0; i < 6; ++i) {
+ final Plane p = planes[i];
+ final float[] p_n = p.n;
+ final double invl = Math.sqrt(p_n[0] * p_n[0] + p_n[1] * p_n[1] + p_n[2] * p_n[2]);
+
+ p_n[0] /= invl;
+ p_n[1] /= invl;
+ p_n[2] /= invl;
+ p.d /= invl;
+ }
+ }
+
+ private static final boolean isOutsideImpl(final Plane p, final AABBox box) {
+ final float[] low = box.getLow();
+ final float[] high = box.getHigh();
+
+ if ( p.distanceTo(low[0], low[1], low[2]) > 0.0f ||
+ p.distanceTo(high[0], low[1], low[2]) > 0.0f ||
+ p.distanceTo(low[0], high[1], low[2]) > 0.0f ||
+ p.distanceTo(high[0], high[1], low[2]) > 0.0f ||
+ p.distanceTo(low[0], low[1], high[2]) > 0.0f ||
+ p.distanceTo(high[0], low[1], high[2]) > 0.0f ||
+ p.distanceTo(low[0], high[1], high[2]) > 0.0f ||
+ p.distanceTo(high[0], high[1], high[2]) > 0.0f ) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check to see if an axis aligned bounding box is completely outside of the frustum.
+ * <p>
+ * Note: If method returns false, the box may only be partially inside.
+ * </p>
+ */
+ public final boolean isAABBoxOutside(final AABBox box) {
+ for (int i = 0; i < 6; ++i) {
+ if ( isOutsideImpl(planes[i], box) ) {
+ // fully outside
+ return true;
+ }
+ }
+ // We make no attempt to determine whether it's fully inside or not.
+ return false;
+ }
+
+
+ public static enum Location { OUTSIDE, INSIDE, INTERSECT };
+
+ /**
+ * Check to see if a point is outside, inside or on a plane of the frustum.
+ *
+ * @param p the point
+ * @return {@link Location} of point related to frustum planes
+ */
+ public final Location classifyPoint(final float[] p) {
+ Location res = Location.INSIDE;
+
+ for (int i = 0; i < 6; ++i) {
+ final float d = planes[i].distanceTo(p);
+ if ( d < 0.0f ) {
+ return Location.OUTSIDE;
+ } else if ( d == 0.0f ) {
+ res = Location.INTERSECT;
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Check to see if a point is outside of the frustum.
+ *
+ * @param p the point
+ * @return true if outside of the frustum, otherwise inside or on a plane
+ */
+ public final boolean isPointOutside(final float[] p) {
+ return Location.OUTSIDE == classifyPoint(p);
+ }
+
+ /**
+ * Check to see if a sphere is outside, intersecting or inside of the frustum.
+ *
+ * @param p center of the sphere
+ * @param radius radius of the sphere
+ * @return {@link Location} of point related to frustum planes
+ */
+ public final Location classifySphere(final float[] p, final float radius) {
+ Location res = Location.INSIDE; // fully inside
+
+ for (int i = 0; i < 6; ++i) {
+ final float d = planes[i].distanceTo(p);
+ if ( d < -radius ) {
+ // fully outside
+ return Location.OUTSIDE;
+ } else if (d < radius ) {
+ // intersecting
+ res = Location.INTERSECT;
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Check to see if a sphere is outside of the frustum.
+ *
+ * @param p center of the sphere
+ * @param radius radius of the sphere
+ * @return true if outside of the frustum, otherwise inside or intersecting
+ */
+ public final boolean isSphereOutside(final float[] p, final float radius) {
+ return Location.OUTSIDE == classifySphere(p, radius);
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ if( null == sb ) {
+ sb = new StringBuilder();
+ }
+ sb.append("Frustum[ Planes[ ").append(PlatformPropsImpl.NEWLINE)
+ .append(" L: ").append(planes[0]).append(", ").append(PlatformPropsImpl.NEWLINE)
+ .append(" R: ").append(planes[1]).append(", ").append(PlatformPropsImpl.NEWLINE)
+ .append(" B: ").append(planes[2]).append(", ").append(PlatformPropsImpl.NEWLINE)
+ .append(" T: ").append(planes[3]).append(", ").append(PlatformPropsImpl.NEWLINE)
+ .append(" N: ").append(planes[4]).append(", ").append(PlatformPropsImpl.NEWLINE)
+ .append(" F: ").append(planes[5]).append("], ").append(PlatformPropsImpl.NEWLINE)
+ .append("]");
+ return sb;
+ }
+
+ @Override
+ public String toString() {
+ return toString(null).toString();
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 02f62daec..28f572d7d 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -27,10 +27,18 @@
*/
package com.jogamp.opengl.swt;
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.opengl.GL;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
@@ -44,23 +52,23 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
+import javax.media.opengl.GLSharedContextSetter;
import javax.media.opengl.Threading;
+import jogamp.nativewindow.x11.X11Util;
import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableHelper;
import jogamp.opengl.GLDrawableImpl;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ControlAdapter;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.jogamp.common.GlueGenVersion;
@@ -69,15 +77,22 @@ import com.jogamp.common.util.VersionUtil;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.opengl.JoglVersion;
/**
* Native SWT Canvas implementing GLAutoDrawable
- *
- * <p>Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used instead.</p>
- *
+ * <p>
+ * Implementation allows use of custom {@link GLCapabilities}.
+ * </p>
+ * <p>
+ * <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a>
+ * To share a {@link GLContext} see the following note in the documentation overview:
+ * <a href="../../../../overview-summary.html#SHARING">context sharing</a>
+ * as well as {@link GLSharedContextSetter}.
+ * </p>
*/
-public class GLCanvas extends Canvas implements GLAutoDrawable {
+public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextSetter {
private static final boolean DEBUG = Debug.debug("GLCanvas");
/*
@@ -94,16 +109,19 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
/* GL Stuff */
private final RecursiveLock lock = LockFactory.createRecursiveLock();
private final GLDrawableHelper helper = new GLDrawableHelper();
-
- private final GLContext shareWith;
+
private final GLCapabilitiesImmutable capsRequested;
- private final GLCapabilitiesChooser capsChooser;
-
+ private final GLCapabilitiesChooser capsChooser;
+
+ private volatile Rectangle clientArea;
private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
- private GLContextImpl context;
+ private volatile GLContextImpl context; // volatile: avoid locking for read-only access
/* Native window surface */
- private AbstractGraphicsDevice device;
+ private final boolean useX11GTK;
+ private volatile long gdkWindow; // either GDK child window ..
+ private volatile long x11Window; // .. or X11 child window (for GL rendering)
+ private final AbstractGraphicsScreen screen;
/* Construction parameters stored for GLAutoDrawable accessor methods */
private int additionalCtxCreationFlags = 0;
@@ -112,13 +130,17 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
/* Flag indicating whether an unprocessed reshape is pending. */
private volatile boolean sendReshape; // volatile: maybe written by WindowManager thread w/o locking
+ private static String getThreadName() { return Thread.currentThread().getName(); }
+ private static String toHexString(final int v) { return "0x"+Integer.toHexString(v); }
+ private static String toHexString(final long v) { return "0x"+Long.toHexString(v); }
+
/*
* Invokes init(...) on all GLEventListeners. Assumes context is current when run.
*/
private final Runnable initAction = new Runnable() {
@Override
public void run() {
- helper.init(GLCanvas.this);
+ helper.init(GLCanvas.this, !sendReshape);
}
};
@@ -131,7 +153,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public void run() {
if (sendReshape) {
- helper.reshape(GLCanvas.this, 0, 0, getWidth(), getHeight());
+ helper.reshape(GLCanvas.this, 0, 0, clientArea.width, clientArea.height);
sendReshape = false;
}
helper.display(GLCanvas.this);
@@ -139,13 +161,15 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
};
/* Action to make specified context current prior to running displayAction */
- private final Runnable makeCurrentAndDisplayOnEDTAction = new Runnable() {
+ private final Runnable makeCurrentAndDisplayOnGLAction = new Runnable() {
@Override
public void run() {
final RecursiveLock _lock = lock;
_lock.lock();
- try {
- helper.invokeGL(drawable, context, displayAction, initAction);
+ try {
+ if( !GLCanvas.this.isDisposed() ) {
+ helper.invokeGL(drawable, context, displayAction, initAction);
+ }
} finally {
_lock.unlock();
}
@@ -153,84 +177,126 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
};
/* Swaps buffers, assuming the GLContext is current */
- private final Runnable swapBuffersAction = new Runnable() {
+ private final Runnable swapBuffersOnGLAction = new Runnable() {
@Override
public void run() {
- drawable.swapBuffers();
- }
- };
-
- /* Swaps buffers, making the GLContext current first */
- private final Runnable makeCurrentAndSwapBuffersOnEDTAction = new Runnable() {
- @Override
- public void run() {
- final RecursiveLock _lock = lock;
- _lock.lock();
- try {
- helper.invokeGL(drawable, context, swapBuffersAction, initAction);
- } finally {
- _lock.unlock();
- }
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final boolean drawableOK = null != drawable && drawable.isRealized();
+ if( drawableOK && !GLCanvas.this.isDisposed() ) {
+ drawable.swapBuffers();
+ }
+ } finally {
+ _lock.unlock();
+ }
}
};
/*
* Disposes of OpenGL resources
*/
- private final Runnable postDisposeGLAction = new Runnable() {
- @Override
- public void run() {
- context = null;
- if (null != drawable) {
- drawable.setRealized(false);
- drawable = null;
- }
- }
- };
-
private final Runnable disposeOnEDTGLAction = new Runnable() {
@Override
public void run() {
final RecursiveLock _lock = lock;
_lock.lock();
try {
- if (null != drawable && null != context) {
- boolean animatorPaused = false;
- final GLAnimatorControl animator = getAnimator();
- if (null != animator) {
- animatorPaused = animator.pause();
- }
-
- if(context.isCreated()) {
- helper.disposeGL(GLCanvas.this, drawable, context, postDisposeGLAction);
- }
-
- if (animatorPaused) {
- animator.resume();
- }
+ final GLAnimatorControl animator = getAnimator();
+ final boolean animatorPaused;
+ if(null!=animator) {
+ // can't remove us from animator for recreational addNotify()
+ animatorPaused = animator.pause();
+ } else {
+ animatorPaused = false;
+ }
+
+ GLException exceptionOnDisposeGL = null;
+ if( null != context ) {
+ if( context.isCreated() ) {
+ try {
+ if( !GLCanvas.this.isDisposed() ) {
+ helper.disposeGL(GLCanvas.this, context, true);
+ } else {
+ context.destroy();
+ }
+ } catch (final GLException gle) {
+ exceptionOnDisposeGL = gle;
+ }
+ }
+ context = null;
+ }
+
+ Throwable exceptionOnUnrealize = null;
+ if( null != drawable ) {
+ try {
+ drawable.setRealized(false);
+ } catch( final Throwable re ) {
+ exceptionOnUnrealize = re;
+ }
+ drawable = null;
+ }
+
+ Throwable exceptionOnDeviceClose = null;
+ try {
+ if( 0 != x11Window) {
+ SWTAccessor.destroyX11Window(screen.getDevice(), x11Window);
+ x11Window = 0;
+ } else if( 0 != gdkWindow) {
+ SWTAccessor.destroyGDKWindow(gdkWindow);
+ gdkWindow = 0;
+ }
+ screen.getDevice().close();
+ } catch (final Throwable re) {
+ exceptionOnDeviceClose = re;
+ }
+
+ if (animatorPaused) {
+ animator.resume();
+ }
+
+ // throw exception in order of occurrence ..
+ if( null != exceptionOnDisposeGL ) {
+ throw exceptionOnDisposeGL;
}
- // SWT is owner of the device handle, not us.
- // Hence close() operation is a NOP.
- if (null != device) {
- device.close();
- device = null;
+ if( null != exceptionOnUnrealize ) {
+ throw GLException.newGLException(exceptionOnUnrealize);
+ }
+ if( null != exceptionOnDeviceClose ) {
+ throw GLException.newGLException(exceptionOnDeviceClose);
}
- SWTAccessor.setRealized(GLCanvas.this, false); // unrealize ..
} finally {
_lock.unlock();
}
}
};
- /**
- * Storage for the client area rectangle so that it may be accessed from outside of the SWT thread.
- */
- private volatile Rectangle clientArea;
+ private class DisposeGLEventListenerAction implements Runnable {
+ private GLEventListener listener;
+ private final boolean remove;
+ private DisposeGLEventListenerAction(final GLEventListener listener, final boolean remove) {
+ this.listener = listener;
+ this.remove = remove;
+ }
+
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( !GLCanvas.this.isDisposed() ) {
+ listener = helper.disposeGLEventListener(GLCanvas.this, drawable, context, listener, remove);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
- /**
- * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser, GLContext)}
+ /**
+ * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser)}
* on the SWT thread.
- *
+ *
* @param parent
* Required (non-null) parent Composite.
* @param style
@@ -243,16 +309,15 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
* @param chooser
* Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the
* requested GLCapabilities, and the available capabilities of the graphics device.
- * @param shareWith
- * Optional GLContext to share state (textures, vbos, shaders, etc.) with.
* @return a new instance
*/
public static GLCanvas create(final Composite parent, final int style, final GLCapabilitiesImmutable caps,
- final GLCapabilitiesChooser chooser, final GLContext shareWith) {
- final GLCanvas[] res = new GLCanvas[] { null };
+ final GLCapabilitiesChooser chooser) {
+ final GLCanvas[] res = new GLCanvas[] { null };
parent.getDisplay().syncExec(new Runnable() {
+ @Override
public void run() {
- res[0] = new GLCanvas( parent, style, caps, chooser, shareWith );
+ res[0] = new GLCanvas( parent, style, caps, chooser );
}
});
return res[0];
@@ -266,18 +331,16 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
* @param style
* Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the
* Canvas constructor, so OpenGL handles the background.
- * @param caps
+ * @param capsReqUser
* Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the
* graphics device determined by the parent Composite are used. Note that the GLCapabilities that are
* actually used may differ based on the capabilities of the graphics device.
- * @param chooser
+ * @param capsChooser
* Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the
* requested GLCapabilities, and the available capabilities of the graphics device.
- * @param shareWith
- * Optional GLContext to share state (textures, vbos, shaders, etc.) with.
*/
- public GLCanvas(final Composite parent, final int style, GLCapabilitiesImmutable caps,
- final GLCapabilitiesChooser chooser, final GLContext shareWith) {
+ public GLCanvas(final Composite parent, final int style, final GLCapabilitiesImmutable capsReqUser,
+ final GLCapabilitiesChooser capsChooser) {
/* NO_BACKGROUND required to avoid clearing bg in native SWT widget (we do this in the GL display) */
super(parent, style | SWT.NO_BACKGROUND);
@@ -287,54 +350,82 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
clientArea = GLCanvas.this.getClientArea();
- /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
- * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */
- device = SWTAccessor.getDevice(this);
+ /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
+ * Note: SWT is owner of the native handle, hence closing operation will be a NOP. */
+ final AbstractGraphicsDevice swtDevice = SWTAccessor.getDevice(this);
- /* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */
- if(null == caps) {
- caps = new GLCapabilities(GLProfile.getDefault(device));
+ useX11GTK = SWTAccessor.useX11GTK();
+ if(useX11GTK) {
+ // Decoupled X11 Device/Screen allowing X11 display lock-free off-thread rendering
+ final long x11DeviceHandle = X11Util.openDisplay(swtDevice.getConnection());
+ if( 0 == x11DeviceHandle ) {
+ throw new RuntimeException("Error creating display(EDT): "+swtDevice.getConnection());
+ }
+ final AbstractGraphicsDevice x11Device = new X11GraphicsDevice(x11DeviceHandle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
+ screen = SWTAccessor.getScreen(x11Device, -1 /* default */);
+ } else {
+ screen = SWTAccessor.getScreen(swtDevice, -1 /* default */);
}
- this.capsRequested = caps;
- this.capsChooser = chooser;
- this.shareWith = shareWith;
+
+ /* Select default GLCapabilities if none was provided, otherwise use cloned provided caps */
+ if(null == capsReqUser) {
+ this.capsRequested = new GLCapabilities(GLProfile.getDefault(screen.getDevice()));
+ } else {
+ this.capsRequested = (GLCapabilitiesImmutable) capsReqUser.cloneMutable();
+ }
+ this.capsChooser = capsChooser;
// post create .. when ready
+ gdkWindow = 0;
+ x11Window = 0;
drawable = null;
context = null;
-
- /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
- /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
- addPaintListener(new PaintListener() {
- @Override
- public void paintControl(final PaintEvent arg0) {
- if ( !helper.isExternalAnimatorAnimating() ) {
- display(); // checks: null != drawable
- }
- }
- });
- addControlListener(new ControlAdapter() {
- @Override
- public void controlResized(final ControlEvent arg0) {
- updateSizeCheck();
- }
- });
+ final Listener listener = new Listener () {
+ @Override
+ public void handleEvent (final Event event) {
+ switch (event.type) {
+ case SWT.Paint:
+ displayIfNoAnimatorNoCheck();
+ break;
+ case SWT.Resize:
+ updateSizeCheck();
+ break;
+ case SWT.Dispose:
+ GLCanvas.this.dispose();
+ break;
+ }
+ }
+ };
+ addListener (SWT.Resize, listener);
+ addListener (SWT.Paint, listener);
+ addListener (SWT.Dispose, listener);
}
+
+ @Override
+ public final void setSharedContext(final GLContext sharedContext) throws IllegalStateException {
+ helper.setSharedContext(this.context, sharedContext);
+ }
+
+ @Override
+ public final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
+ helper.setSharedAutoDrawable(this, sharedAutoDrawable);
+ }
+
private final UpstreamSurfaceHook swtCanvasUpStreamHook = new UpstreamSurfaceHook() {
@Override
- public final void create(ProxySurface s) { /* nop */ }
+ public final void create(final ProxySurface s) { /* nop */ }
@Override
- public final void destroy(ProxySurface s) { /* nop */ }
+ public final void destroy(final ProxySurface s) { /* nop */ }
@Override
- public final int getWidth(ProxySurface s) {
+ public final int getSurfaceWidth(final ProxySurface s) {
return clientArea.width;
}
@Override
- public final int getHeight(ProxySurface s) {
+ public final int getSurfaceHeight(final ProxySurface s) {
return clientArea.height;
}
@@ -342,116 +433,301 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
public String toString() {
return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientArea.width+"x"+clientArea.height+"]";
}
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns <code>null</code>.
+ * </p>
+ */
+ @Override
+ public final NativeSurface getUpstreamSurface() {
+ return null;
+ }
};
protected final void updateSizeCheck() {
final Rectangle oClientArea = clientArea;
final Rectangle nClientArea = GLCanvas.this.getClientArea();
- if ( nClientArea != null &&
+ if ( nClientArea != null &&
( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
) {
clientArea = nClientArea; // write back new value
-
- GLDrawableImpl _drawable = drawable;
- if( null != _drawable ) {
- if(DEBUG) {
- System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
- }
+
+ final GLDrawableImpl _drawable = drawable;
+ final boolean drawableOK = null != _drawable && _drawable.isRealized();
+ if(DEBUG) {
+ final long dh = drawableOK ? _drawable.getHandle() : 0;
+ System.err.println(getThreadName()+": GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - drawableHandle "+toHexString(dh));
+ }
+ if( drawableOK ) {
if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
final RecursiveLock _lock = lock;
_lock.lock();
try {
final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, nClientArea.width, nClientArea.height);
if(_drawable != _drawableNew) {
- // write back
+ // write back
drawable = _drawableNew;
}
} finally {
_lock.unlock();
}
- sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
}
- }
+ }
+ if(0 != x11Window) {
+ SWTAccessor.resizeX11Window(screen.getDevice(), clientArea, x11Window);
+ } else if(0 != gdkWindow) {
+ SWTAccessor.resizeGDKWindow(clientArea, gdkWindow);
+ }
+ sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
}
}
-
- @Override
- public void display() {
- if( null != drawable || validateDrawableAndContext() ) {
- runInGLThread(makeCurrentAndDisplayOnEDTAction);
- }
+
+ private boolean isValidAndVisibleOnEDTActionResult;
+ private final Runnable isValidAndVisibleOnEDTAction = new Runnable() {
+ @Override
+ public void run() {
+ isValidAndVisibleOnEDTActionResult = !GLCanvas.this.isDisposed() && GLCanvas.this.isVisible();
+ } };
+
+ private final boolean isValidAndVisibleOnEDT() {
+ synchronized(isValidAndVisibleOnEDTAction) {
+ runOnEDTIfAvail(true, isValidAndVisibleOnEDTAction);
+ return isValidAndVisibleOnEDTActionResult;
+ }
}
-
- /** assumes drawable == null ! */
- protected final boolean validateDrawableAndContext() {
- if( GLCanvas.this.isDisposed() ) {
+ /** assumes drawable == null (implying !drawable.isRealized()) ! Checks of !isDispose() and isVisible() */
+ protected final boolean validateDrawableAndContextWithCheck() {
+ if( !isValidAndVisibleOnEDT() ) {
return false;
}
- final Rectangle nClientArea = clientArea;
- if(0 == nClientArea.width * nClientArea.height) {
- return false;
- }
-
+ return validateDrawableAndContextPostCheck();
+ }
+
+ private final boolean isDrawableAndContextValid() {
+ // drawable != null implies drawable.isRealized()==true
+ return null != drawable && null != context;
+ }
+
+ /** assumes drawable == null (implying !drawable.isRealized()) || context == null ! No check of !isDispose() and isVisible() */
+ private final boolean validateDrawableAndContextPostCheck() {
+ boolean res;
final RecursiveLock _lock = lock;
_lock.lock();
try {
- final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile());
-
- /* Native handle for the control, used to associate with GLContext */
- final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
-
- /* Create a NativeWindow proxy for the SWT canvas */
- ProxySurface proxySurface = null;
- try {
- proxySurface = glFactory.createProxySurface(device, 0 /* screenIdx */, nativeWindowHandle,
- capsRequested, capsChooser, swtCanvasUpStreamHook);
- } catch (GLException gle) {
- // not ready yet ..
- if(DEBUG) { System.err.println(gle.getMessage()); }
+ if(null == drawable) {
+ // 'displayable' (isValidAndVisibleOnEDT()) must have been checked upfront if appropriate!
+ createDrawableImpl(); // checks clientArea size (i.e. drawable size) and perf. realization
+ }
+ final GLDrawable _drawable = drawable;
+ if ( null != _drawable ) {
+ // drawable realization goes in-hand w/ it's construction
+ if( null == context ) {
+ // re-try context creation
+ res = createContextImpl(_drawable); // pending creation.
+ } else {
+ res = true;
+ }
+ if(res) {
+ sendReshape = true;
+ }
+ } else {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": SWT.GLCanvas.validate "+toHexString(hashCode())+": null drawable");
+ }
+ res = false;
}
-
- if(null != proxySurface) {
- /* Associate a GL surface with the proxy */
- drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface);
- drawable.setRealized(true);
-
- context = (GLContextImpl) drawable.createContext(shareWith);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": SWT.GLCanvas.validate.X "+toHexString(hashCode())+": "+res+", drawable-realized "+drawable.isRealized()+", has context "+(null!=context));
}
} finally {
_lock.unlock();
}
- final boolean res = null != drawable;
- if(DEBUG && res) {
- System.err.println("SWT GLCanvas realized! "+this+", "+drawable);
- Thread.dumpStack();
- }
return res;
}
-
+ private final void createDrawableImpl() {
+ final Rectangle nClientArea = clientArea;
+ if(0 >= nClientArea.width || 0 >= nClientArea.height) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": SWT.GLCanvas.validate.X "+toHexString(hashCode())+": drawable could not be created: size < 0x0");
+ }
+ return; // early out
+ }
+ final AbstractGraphicsDevice device = screen.getDevice();
+ device.open();
+
+ final long nativeWindowHandle;
+ if( useX11GTK ) {
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(device, capsRequested);
+ final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capsChooser, screen, VisualIDHolder.VID_UNDEFINED);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": SWT.GLCanvas.X11 "+toHexString(hashCode())+": factory: "+factory+", chosen config: "+cfg);
+ }
+ if (null == cfg) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+ final int visualID = cfg.getVisualID(VIDType.NATIVE);
+ if( VisualIDHolder.VID_UNDEFINED != visualID ) {
+ // gdkWindow = SWTAccessor.createCompatibleGDKChildWindow(this, visualID, clientArea.width, clientArea.height);
+ // nativeWindowHandle = SWTAccessor.gdk_window_get_xwindow(gdkWindow);
+ x11Window = SWTAccessor.createCompatibleX11ChildWindow(screen, this, visualID, clientArea.width, clientArea.height);
+ nativeWindowHandle = x11Window;
+ } else {
+ throw new GLException("Could not choose valid visualID: "+toHexString(visualID)+", "+this);
+ }
+ } else {
+ nativeWindowHandle = SWTAccessor.getWindowHandle(this);
+ }
+ final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile());
+
+ // Create a NativeWindow proxy for the SWT canvas
+ final ProxySurface proxySurface = glFactory.createProxySurface(device, screen.getIndex(), nativeWindowHandle,
+ capsRequested, capsChooser, swtCanvasUpStreamHook);
+ // Associate a GL surface with the proxy
+ final GLDrawableImpl _drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface);
+ _drawable.setRealized(true);
+ if(!_drawable.isRealized()) {
+ // oops
+ if(DEBUG) {
+ System.err.println(getThreadName()+": SWT.GLCanvas.validate.X "+toHexString(hashCode())+": Drawable could not be realized: "+_drawable);
+ }
+ } else {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": SWT.GLCanvas.validate "+toHexString(hashCode())+": Drawable created and realized");
+ }
+ drawable = _drawable;
+ }
+ }
+ private boolean createContextImpl(final GLDrawable drawable) {
+ final GLContext[] shareWith = { null };
+ if( !helper.isSharedGLContextPending(shareWith) ) {
+ context = (GLContextImpl) drawable.createContext(shareWith[0]);
+ context.setContextCreationFlags(additionalCtxCreationFlags);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": SWT.GLCanvas.validate "+toHexString(hashCode())+": Context created: has shared "+(null != shareWith[0]));
+ }
+ return true;
+ } else {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": SWT.GLCanvas.validate "+toHexString(hashCode())+": Context !created: pending share");
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public void update() {
+ // don't paint background etc .. nop avoids flickering
+ // super.update();
+ }
+
+ /**
+ @Override
+ public boolean forceFocus() {
+ final boolean r = super.forceFocus();
+ if(r && 0 != gdkWindow) {
+ SWTGTKUtil.focusGDKWindow(gdkWindow);
+ }
+ return r;
+ } */
+
+ @Override
+ public void dispose() {
+ runInGLThread(disposeOnEDTGLAction);
+ super.dispose();
+ }
+
+ private final void displayIfNoAnimatorNoCheck() {
+ if ( !helper.isAnimatorAnimatingOnOtherThread() ) {
+ if( isDrawableAndContextValid() || validateDrawableAndContextPostCheck() ) {
+ runInGLThread(makeCurrentAndDisplayOnGLAction);
+ }
+ }
+ }
+
+ //
+ // GL[Auto]Drawable
+ //
+
+ @Override
+ public void display() {
+ if( isDrawableAndContextValid() || validateDrawableAndContextWithCheck() ) {
+ runInGLThread(makeCurrentAndDisplayOnGLAction);
+ }
+ }
+
@Override
public final Object getUpstreamWidget() {
return this;
}
-
+
@Override
- public int getWidth() {
+ public final RecursiveLock getUpstreamLock() { return lock; }
+
+ @Override
+ public int getSurfaceWidth() {
return clientArea.width;
}
@Override
- public int getHeight() {
+ public int getSurfaceHeight() {
return clientArea.height;
}
@Override
- public void addGLEventListener(final GLEventListener arg0) {
- helper.addGLEventListener(arg0);
+ public boolean isGLOriented() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.isGLOriented() : true;
+ }
+
+ @Override
+ public void addGLEventListener(final GLEventListener listener) {
+ helper.addGLEventListener(listener);
+ }
+
+ @Override
+ public void addGLEventListener(final int idx, final GLEventListener listener) throws IndexOutOfBoundsException {
+ helper.addGLEventListener(idx, listener);
+ }
+
+ @Override
+ public int getGLEventListenerCount() {
+ return helper.getGLEventListenerCount();
+ }
+
+ @Override
+ public GLEventListener getGLEventListener(final int index) throws IndexOutOfBoundsException {
+ return helper.getGLEventListener(index);
}
@Override
- public void addGLEventListener(final int arg0, final GLEventListener arg1) throws IndexOutOfBoundsException {
- helper.addGLEventListener(arg0, arg1);
+ public boolean areAllGLEventListenerInitialized() {
+ return helper.areAllGLEventListenerInitialized();
+ }
+
+ @Override
+ public boolean getGLEventListenerInitState(final GLEventListener listener) {
+ return helper.getGLEventListenerInitState(listener);
+ }
+
+ @Override
+ public void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized) {
+ helper.setGLEventListenerInitState(listener, initialized);
+ }
+
+ @Override
+ public GLEventListener disposeGLEventListener(final GLEventListener listener, final boolean remove) {
+ final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
+ runInGLThread(r);
+ return r.listener;
+ }
+
+ @Override
+ public GLEventListener removeGLEventListener(final GLEventListener listener) {
+ return helper.removeGLEventListener(listener);
}
/**
@@ -473,6 +749,16 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
@Override
+ public final Thread setExclusiveContextThread(final Thread t) throws GLException {
+ return helper.setExclusiveContextThread(t, context);
+ }
+
+ @Override
+ public final Thread getExclusiveContextThread() {
+ return helper.getExclusiveContextThread();
+ }
+
+ @Override
public boolean getAutoSwapBufferMode() {
return helper.getAutoSwapBufferMode();
}
@@ -481,10 +767,10 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
public final GLDrawable getDelegatedDrawable() {
return drawable;
}
-
+
@Override
public GLContext getContext() {
- return null != drawable ? context : null;
+ return context;
}
@Override
@@ -499,20 +785,20 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
@Override
- public boolean invoke(final boolean wait, final GLRunnable run) {
- return helper.invoke(this, wait, run);
+ public boolean invoke(final boolean wait, final GLRunnable runnable) throws IllegalStateException {
+ return helper.invoke(this, wait, runnable);
}
@Override
- public void removeGLEventListener(final GLEventListener arg0) {
- helper.removeGLEventListener(arg0);
+ public boolean invoke(final boolean wait, final List<GLRunnable> runnables) throws IllegalStateException {
+ return helper.invoke(this, wait, runnables);
}
@Override
- public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
- return helper.removeGLEventListener(index);
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
}
-
+
@Override
public void setAnimator(final GLAnimatorControl arg0) throws GLException {
helper.setAnimator(arg0);
@@ -524,16 +810,13 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
@Override
- public GLContext setContext(GLContext newCtx) {
+ public GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx) {
final RecursiveLock _lock = lock;
_lock.lock();
- try {
+ try {
final GLContext oldCtx = context;
- final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
- }
return oldCtx;
} finally {
_lock.unlock();
@@ -577,18 +860,14 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GLCapabilitiesImmutable getChosenGLCapabilities() {
- final GLDrawable _drawable = drawable;
+ final GLDrawable _drawable = drawable;
return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getChosenGLCapabilities() : null;
}
- /**
- * Accessor for the GLCapabilities that were requested (via the constructor parameter).
- *
- * @return Non-null GLCapabilities.
- */
+ @Override
public GLCapabilitiesImmutable getRequestedGLCapabilities() {
- final GLDrawable _drawable = drawable;
- return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities() : null;
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getRequestedGLCapabilities() : null;
}
@Override
@@ -604,7 +883,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public long getHandle() {
- final GLDrawable _drawable = drawable;
+ final GLDrawable _drawable = drawable;
return (_drawable != null) ? _drawable.getHandle() : 0;
}
@@ -627,19 +906,17 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public void swapBuffers() throws GLException {
- runInGLThread(makeCurrentAndSwapBuffersOnEDTAction);
- }
-
- @Override
- public void update() {
- // don't paint background etc .. nop avoids flickering
+ runInGLThread(swapBuffersOnGLAction);
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Implementation always supports multithreading, hence method always returns <code>true</code>.
+ * </p>
+ */
@Override
- public void dispose() {
- runInGLThread(disposeOnEDTGLAction);
- super.dispose();
- }
+ public final boolean isThreadGLCapable() { return true; }
/**
* Runs the specified action in an SWT compatible thread, which is:
@@ -647,22 +924,64 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
* <li>Mac OSX
* <ul>
* <!--li>AWT EDT: In case AWT is available, the AWT EDT is the OSX UI main thread</li-->
- * <li><i>Main Thread</i>: Run on OSX UI main thread.</li>
+ * <!--li><i>Main Thread</i>: Run on OSX UI main thread.</li-->
+ * <li>Current thread</li>
* </ul></li>
* <li>Linux, Windows, ..
* <ul>
- * <li>Use {@link Threading#invokeOnOpenGLThread(boolean, Runnable)}</li>
- * </ul></li>
+ * <!--li>Use {@link Threading#invokeOnOpenGLThread(boolean, Runnable)}</li-->
+ * <li>Current thread</li>
+ * </ul></li>
* </ul>
+ * The current thread seems to be valid for all platforms,
+ * since no SWT lifecycle tasks are being performed w/ this call.
+ * Only GL task, which are independent from the SWT threading model.
+ *
* @see Platform#AWT_AVAILABLE
* @see Platform#getOSType()
*/
- private static void runInGLThread(final Runnable action) {
+ private void runInGLThread(final Runnable action) {
+ /**
if(Platform.OSType.MACOS == Platform.OS_TYPE) {
SWTAccessor.invoke(true, action);
} else {
Threading.invokeOnOpenGLThread(true, action);
- }
+ } */
+ /**
+ if( !isDisposed() ) {
+ final Display d = getDisplay();
+ if( d.getThread() == Thread.currentThread() ) {
+ action.run();
+ } else {
+ d.syncExec(action);
+ }
+ } */
+ action.run();
+ }
+
+ private void runOnEDTIfAvail(final boolean wait, final Runnable action) {
+ final Display d = isDisposed() ? null : getDisplay();
+ if( null == d || d.isDisposed() || d.getThread() == Thread.currentThread() ) {
+ action.run();
+ } else if(wait) {
+ d.syncExec(action);
+ } else {
+ d.asyncExec(action);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final GLDrawable _drawable = drawable;
+ final int dw = (null!=_drawable) ? _drawable.getSurfaceWidth() : -1;
+ final int dh = (null!=_drawable) ? _drawable.getSurfaceHeight() : -1;
+
+ return "SWT-GLCanvas[Realized "+isRealized()+
+ ",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+
+ ",\n\tFactory "+getFactory()+
+ ",\n\thandle "+toHexString(getHandle())+
+ ",\n\tDrawable size "+dw+"x"+dh+
+ ",\n\tSWT size "+getSurfaceWidth()+"x"+getSurfaceHeight()+"]";
}
public static void main(final String[] args) {
@@ -679,12 +998,12 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
shell.setSize(128,128);
shell.setLayout(new FillLayout());
- final GLCanvas canvas = new GLCanvas(shell, 0, caps, null, null);
+ final GLCanvas canvas = new GLCanvas(shell, 0, caps, null);
canvas.addGLEventListener(new GLEventListener() {
@Override
public void init(final GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
+ final GL gl = drawable.getGL();
System.err.println(JoglVersion.getGLInfo(gl, null));
}
@Override
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
index 26d299663..62df3faca 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -41,12 +41,14 @@ import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+
import javax.swing.JComponent;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
-
import javax.media.opengl.GLAutoDrawable;
+import com.jogamp.opengl.util.AnimatorBase.UncaughtAnimatorException;
+
/** Abstraction to factor out AWT dependencies from the Animator's
implementation in a way that still allows the FPSAnimator to pick
up this behavior if desired. */
@@ -54,15 +56,16 @@ import javax.media.opengl.GLAutoDrawable;
class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
// For efficient rendering of Swing components, in particular when
// they overlap one another
- private List<JComponent> lightweights = new ArrayList<JComponent>();
- private Map<RepaintManager,RepaintManager> repaintManagers = new IdentityHashMap<RepaintManager,RepaintManager>();
- private Map<JComponent,Rectangle> dirtyRegions = new IdentityHashMap<JComponent,Rectangle>();
+ private final List<JComponent> lightweights = new ArrayList<JComponent>();
+ private final Map<RepaintManager,RepaintManager> repaintManagers = new IdentityHashMap<RepaintManager,RepaintManager>();
+ private final Map<JComponent,Rectangle> dirtyRegions = new IdentityHashMap<JComponent,Rectangle>();
- public void display(ArrayList<GLAutoDrawable> drawables,
- boolean ignoreExceptions,
- boolean printExceptions) {
+ @Override
+ public void display(final ArrayList<GLAutoDrawable> drawables,
+ final boolean ignoreExceptions,
+ final boolean printExceptions) throws UncaughtAnimatorException {
for (int i=0; i<drawables.size(); i++) {
- GLAutoDrawable drawable = drawables.get(i);
+ final GLAutoDrawable drawable = drawables.get(i);
if (drawable instanceof JComponent) {
// Lightweight components need a more efficient drawing
// scheme than simply forcing repainting of each one in
@@ -72,13 +75,13 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
} else {
try {
drawable.display();
- } catch (RuntimeException e) {
+ } catch (final Throwable t) {
if (ignoreExceptions) {
if (printExceptions) {
- e.printStackTrace();
+ t.printStackTrace();
}
} else {
- throw(e);
+ throw new UncaughtAnimatorException(drawable, t);
}
}
}
@@ -87,7 +90,7 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
if (lightweights.size() > 0) {
try {
SwingUtilities.invokeAndWait(drawWithRepaintManagerRunnable);
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
lightweights.clear();
@@ -96,9 +99,10 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
// Uses RepaintManager APIs to implement more efficient redrawing of
// the Swing widgets we're animating
- private Runnable drawWithRepaintManagerRunnable = new Runnable() {
+ private final Runnable drawWithRepaintManagerRunnable = new Runnable() {
+ @Override
public void run() {
- for (Iterator<JComponent> iter = lightweights.iterator(); iter.hasNext(); ) {
+ for (final Iterator<JComponent> iter = lightweights.iterator(); iter.hasNext(); ) {
JComponent comp = iter.next();
RepaintManager rm = RepaintManager.currentManager(comp);
rm.markCompletelyDirty(comp);
@@ -115,13 +119,13 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
// Walk up the hierarchy trying to find a non-optimizable
// ancestor
- Rectangle visible = comp.getVisibleRect();
+ final Rectangle visible = comp.getVisibleRect();
int x = visible.x;
int y = visible.y;
while (comp != null) {
x += comp.getX();
y += comp.getY();
- Component c = comp.getParent();
+ final Component c = comp.getParent();
if ((c == null) || (!(c instanceof JComponent))) {
comp = null;
} else {
@@ -130,7 +134,7 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
rm = RepaintManager.currentManager(comp);
repaintManagers.put(rm, rm);
// Need to dirty this region
- Rectangle dirty = (Rectangle) dirtyRegions.get(comp);
+ Rectangle dirty = dirtyRegions.get(comp);
if (dirty == null) {
dirty = new Rectangle(x, y, visible.width, visible.height);
dirtyRegions.put(comp, dirty);
@@ -148,15 +152,15 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
}
// Dirty any needed regions on non-optimizable components
- for (Iterator<JComponent> iter = dirtyRegions.keySet().iterator(); iter.hasNext(); ) {
- JComponent comp = iter.next();
- Rectangle rect = dirtyRegions.get(comp);
- RepaintManager rm = RepaintManager.currentManager(comp);
+ for (final Iterator<JComponent> iter = dirtyRegions.keySet().iterator(); iter.hasNext(); ) {
+ final JComponent comp = iter.next();
+ final Rectangle rect = dirtyRegions.get(comp);
+ final RepaintManager rm = RepaintManager.currentManager(comp);
rm.addDirtyRegion(comp, rect.x, rect.y, rect.width, rect.height);
}
// Draw all dirty regions
- for (Iterator<RepaintManager> iter = repaintManagers.keySet().iterator(); iter.hasNext(); ) {
+ for (final Iterator<RepaintManager> iter = repaintManagers.keySet().iterator(); iter.hasNext(); ) {
iter.next().paintDirtyRegions();
}
dirtyRegions.clear();
@@ -164,7 +168,8 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
}
};
- public boolean blockUntilDone(Thread thread) {
- return ((Thread.currentThread() != thread) && !EventQueue.isDispatchThread());
+ @Override
+ public boolean blockUntilDone(final Thread thread) {
+ return Thread.currentThread() != thread && !EventQueue.isDispatchThread();
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
index 20ba27c16..b38a42ee3 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,7 +41,7 @@
package com.jogamp.opengl.util;
import javax.media.opengl.GLAutoDrawable;
-
+import javax.media.opengl.GLException;
/** <P> An Animator can be attached to one or more {@link
GLAutoDrawable}s to drive their display() methods in a loop. </P>
@@ -56,19 +56,18 @@ import javax.media.opengl.GLAutoDrawable;
* so it is able to keep an application from terminating.<br>
* Call {@link #stop() } to terminate the animation and it's execution thread.
* </p>
-*/
-
+ */
public class Animator extends AnimatorBase {
- /** timeout in milliseconds, 15 frames @ 60Hz = 240ms, limiting {@link #finishLifecycleAction(Condition)} */
- private static final long TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION = 15*16;
-
- protected ThreadGroup threadGroup;
+ private ThreadGroup threadGroup;
private Runnable runnable;
private boolean runAsFastAsPossible;
- protected boolean isAnimating;
- protected boolean pauseIssued;
- protected volatile boolean stopIssued;
+ boolean isAnimating;
+ volatile boolean pauseIssued;
+ volatile boolean stopIssued;
+ /**
+ * Creates a new, empty Animator.
+ */
public Animator() {
super();
if(DEBUG) {
@@ -76,28 +75,42 @@ public class Animator extends AnimatorBase {
}
}
- public Animator(ThreadGroup tg) {
+ /**
+ * Creates a new Animator w/ an associated ThreadGroup.
+ */
+ public Animator(final ThreadGroup tg) {
super();
- threadGroup = tg;
-
+ setThreadGroup(tg);
if(DEBUG) {
System.err.println("Animator created, ThreadGroup: "+threadGroup);
}
}
- /** Creates a new Animator for a particular drawable. */
- public Animator(GLAutoDrawable drawable) {
+ /**
+ * Creates a new Animator for a particular drawable.
+ */
+ public Animator(final GLAutoDrawable drawable) {
super();
add(drawable);
+ if(DEBUG) {
+ System.err.println("Animator created, w/ "+drawable);
+ }
}
- /** Creates a new Animator for a particular drawable. */
- public Animator(ThreadGroup tg, GLAutoDrawable drawable) {
- this(tg);
+ /**
+ * Creates a new Animator w/ an associated ThreadGroup for a particular drawable.
+ */
+ public Animator(final ThreadGroup tg, final GLAutoDrawable drawable) {
+ super();
+ setThreadGroup(tg);
add(drawable);
+ if(DEBUG) {
+ System.err.println("Animator created, ThreadGroup: "+threadGroup+" and "+drawable);
+ }
}
- protected String getBaseName(String prefix) {
+ @Override
+ protected final String getBaseName(final String prefix) {
return prefix + "Animator" ;
}
@@ -107,252 +120,239 @@ public class Animator extends AnimatorBase {
* animation loop which prevents the CPU from getting swamped.
* This method may not have an effect on subclasses.
*/
- public final void setRunAsFastAsPossible(boolean runFast) {
- stateSync.lock();
- try {
- runAsFastAsPossible = runFast;
- } finally {
- stateSync.unlock();
- }
- }
-
- private final void setIsAnimatingSynced(boolean v) {
- stateSync.lock();
- try {
- isAnimating = v;
- } finally {
- stateSync.unlock();
- }
+ public final synchronized void setRunAsFastAsPossible(final boolean runFast) {
+ runAsFastAsPossible = runFast;
}
class MainLoop implements Runnable {
+ @Override
public String toString() {
- return "[started "+isStartedImpl()+", animating "+isAnimatingImpl()+", paused "+isPausedImpl()+", drawable "+drawables.size()+"]";
+ return "[started "+isStarted()+", animating "+isAnimating()+", paused "+isPaused()+", drawable "+drawables.size()+", drawablesEmpty "+drawablesEmpty+"]";
}
+ @Override
public void run() {
+ ThreadDeath caughtThreadDeath = null;
+ UncaughtAnimatorException caughtException = null;
+
try {
synchronized (Animator.this) {
if(DEBUG) {
- System.err.println("Animator start:" + Thread.currentThread() + ": " + toString());
+ System.err.println("Animator start on " + getThreadName() + ": " + toString());
}
fpsCounter.resetFPSCounter();
animThread = Thread.currentThread();
- setIsAnimatingSynced(false); // barrier
- Animator.this.notifyAll();
+ isAnimating = false;
+ // 'waitForStartedCondition' wake-up is handled below!
}
while (!stopIssued) {
synchronized (Animator.this) {
- // Don't consume CPU unless there is work to be done and not paused
- while (!stopIssued && (pauseIssued || drawablesEmpty)) {
- boolean wasPaused = pauseIssued;
+ // Pause; Also don't consume CPU unless there is work to be done and not paused
+ boolean ectCleared = false;
+ while ( !stopIssued && ( pauseIssued || drawablesEmpty ) ) {
+ if( drawablesEmpty ) {
+ pauseIssued = true;
+ }
+ final boolean wasPaused = pauseIssued;
if (DEBUG) {
- System.err.println("Animator pause:" + Thread.currentThread() + ": " + toString());
+ System.err.println("Animator pause on " + animThread.getName() + ": " + toString());
+ }
+ if ( exclusiveContext && !drawablesEmpty && !ectCleared ) {
+ ectCleared = true;
+ setDrawablesExclCtxState(false);
+ try {
+ display(); // propagate exclusive context -> off!
+ } catch (final UncaughtAnimatorException dre) {
+ caughtException = dre;
+ stopIssued = true;
+ break; // end pause loop
+ }
}
- setIsAnimatingSynced(false); // barrier
+ isAnimating = false;
Animator.this.notifyAll();
try {
Animator.this.wait();
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
}
-
if (wasPaused) {
// resume from pause -> reset counter
fpsCounter.resetFPSCounter();
if (DEBUG) {
- System.err.println("Animator resume:" + Thread.currentThread() + ": " + toString());
+ System.err.println("Animator resume on " + animThread.getName() + ": " + toString());
}
}
}
if (!stopIssued && !isAnimating) {
- // resume from pause or drawablesEmpty,
+ // Wakes up 'waitForStartedCondition' sync
+ // - and -
+ // Resume from pause or drawablesEmpty,
// implies !pauseIssued and !drawablesEmpty
- setIsAnimatingSynced(true);
+ isAnimating = true;
+ setDrawablesExclCtxState(exclusiveContext); // may re-enable exclusive context
Animator.this.notifyAll();
}
} // sync Animator.this
- if (!stopIssued) {
- display();
+ if ( !pauseIssued && !stopIssued ) {
+ try {
+ display();
+ } catch (final UncaughtAnimatorException dre) {
+ caughtException = dre;
+ stopIssued = true;
+ break; // end animation loop
+ }
+ if ( !runAsFastAsPossible ) {
+ // Avoid swamping the CPU
+ Thread.yield();
+ }
}
- if (!stopIssued && !runAsFastAsPossible) {
- // Avoid swamping the CPU
- Thread.yield();
+ }
+ } catch(final ThreadDeath td) {
+ if(DEBUG) {
+ System.err.println("Animator caught: "+td.getClass().getName()+": "+td.getMessage());
+ td.printStackTrace();
+ }
+ caughtThreadDeath = td;
+ }
+ if( exclusiveContext && !drawablesEmpty ) {
+ setDrawablesExclCtxState(false);
+ try {
+ display(); // propagate exclusive context -> off!
+ } catch (final UncaughtAnimatorException dre) {
+ if( null == caughtException ) {
+ caughtException = dre;
+ } else {
+ System.err.println("Animator.setExclusiveContextThread: caught: "+dre.getMessage());
+ dre.printStackTrace();
}
}
- } finally {
- synchronized (Animator.this) {
- if(DEBUG) {
- System.err.println("Animator stop " + Thread.currentThread() + ": " + toString());
+ }
+ boolean flushGLRunnables = false;
+ boolean throwCaughtException = false;
+ synchronized (Animator.this) {
+ if(DEBUG) {
+ System.err.println("Animator stop on " + animThread.getName() + ": " + toString());
+ if( null != caughtException ) {
+ System.err.println("Animator caught: "+caughtException.getMessage());
+ caughtException.printStackTrace();
}
- stopIssued = false;
- pauseIssued = false;
- animThread = null;
- setIsAnimatingSynced(false); // barrier
- Animator.this.notifyAll();
}
+ stopIssued = false;
+ pauseIssued = false;
+ isAnimating = false;
+ if( null != caughtException ) {
+ flushGLRunnables = true;
+ throwCaughtException = !handleUncaughtException(caughtException);
+ }
+ animThread = null;
+ Animator.this.notifyAll();
+ }
+ if( flushGLRunnables ) {
+ flushGLRunnables();
+ }
+ if( throwCaughtException ) {
+ throw caughtException;
+ }
+ if( null != caughtThreadDeath ) {
+ throw caughtThreadDeath;
}
}
}
- private final boolean isStartedImpl() {
- return animThread != null ;
- }
- public final boolean isStarted() {
- stateSync.lock();
- try {
- return animThread != null ;
- } finally {
- stateSync.unlock();
- }
- }
-
- private final boolean isAnimatingImpl() {
+ @Override
+ public final synchronized boolean isAnimating() {
return animThread != null && isAnimating ;
}
- public final boolean isAnimating() {
- stateSync.lock();
- try {
- return animThread != null && isAnimating ;
- } finally {
- stateSync.unlock();
- }
- }
- private final boolean isPausedImpl() {
+ @Override
+ public final synchronized boolean isPaused() {
return animThread != null && pauseIssued ;
}
- public final boolean isPaused() {
- stateSync.lock();
- try {
- return animThread != null && pauseIssued ;
- } finally {
- stateSync.unlock();
- }
- }
- interface Condition {
- /**
- * @return true if branching (cont waiting, action), otherwise false
- */
- boolean result();
- }
-
- private synchronized void finishLifecycleAction(Condition condition) {
- // It's hard to tell whether the thread which changes the lifecycle has
- // dependencies on the Animator's internal thread. Currently we
- // use a couple of heuristics to determine whether we should do
- // the blocking wait().
- final boolean blocking = impl.blockUntilDone(animThread);
- long remaining = blocking ? TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION : 0;
- while (remaining>0 && condition.result()) {
- long td = System.currentTimeMillis();
- try {
- wait(remaining);
- } catch (InterruptedException ie) { }
- remaining -= (System.currentTimeMillis() - td) ;
- }
- if(DEBUG) {
- if(remaining<0) {
- System.err.println("finishLifecycleAction(" + condition.getClass().getName() + "): ++++++ timeout reached ++++++ " + Thread.currentThread().getName());
- }
- System.err.println("finishLifecycleAction(" + condition.getClass().getName() + "): finished "+
- "- blocking "+blocking+
- ", waited " + (blocking ? ( TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION - remaining ) : 0 ) + "/" + TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION +
- ", started: " + isStartedImpl() +", animating: " + isAnimatingImpl() +
- ", paused: " + isPausedImpl() + ", drawables " + drawables.size() + " - " + Thread.currentThread().getName());
+ /**
+ * Set a {@link ThreadGroup} for the {@link #getThread() animation thread}.
+ *
+ * @param tg the {@link ThreadGroup}
+ * @throws GLException if the animator has already been started
+ */
+ public final synchronized void setThreadGroup(final ThreadGroup tg) throws GLException {
+ if ( isStarted() ) {
+ throw new GLException("Animator already started.");
}
+ threadGroup = tg;
}
- public synchronized boolean start() {
- if ( isStartedImpl() ) {
+ @Override
+ public final synchronized boolean start() {
+ if ( isStarted() ) {
return false;
}
if (runnable == null) {
runnable = new MainLoop();
}
fpsCounter.resetFPSCounter();
- String threadName = Thread.currentThread().getName()+"-"+baseName;
+ final String threadName = getThreadName()+"-"+baseName;
Thread thread;
if(null==threadGroup) {
thread = new Thread(runnable, threadName);
} else {
thread = new Thread(threadGroup, runnable, threadName);
}
- thread.setDaemon(false); // force to be non daemon, regardless of parent thread
+ thread.setDaemon(false); // force to be non daemon, regardless of parent thread
if(DEBUG) {
final Thread ct = Thread.currentThread();
System.err.println("Animator "+ct.getName()+"[daemon "+ct.isDaemon()+"]: starting "+thread.getName()+"[daemon "+thread.isDaemon()+"]");
}
thread.start();
- finishLifecycleAction(waitForStartedCondition);
- return true;
- }
-
- private class WaitForStartedCondition implements Condition {
- public boolean result() {
- return !isStartedImpl() || (!drawablesEmpty && !isAnimating) ;
- }
+ return finishLifecycleAction(waitForStartedCondition, 0);
}
- Condition waitForStartedCondition = new WaitForStartedCondition();
+ private final Condition waitForStartedCondition = new Condition() {
+ @Override
+ public boolean eval() {
+ return !isStarted() || (!drawablesEmpty && !isAnimating) ;
+ } };
- public synchronized boolean stop() {
- if ( !isStartedImpl() ) {
+ @Override
+ public final synchronized boolean stop() {
+ if ( !isStarted() ) {
return false;
}
stopIssued = true;
- notifyAll();
- finishLifecycleAction(waitForStoppedCondition);
- return true;
+ return finishLifecycleAction(waitForStoppedCondition, 0);
}
- private class WaitForStoppedCondition implements Condition {
- public boolean result() {
- return isStartedImpl();
- }
- }
- Condition waitForStoppedCondition = new WaitForStoppedCondition();
+ private final Condition waitForStoppedCondition = new Condition() {
+ @Override
+ public boolean eval() {
+ return isStarted();
+ } };
- public synchronized boolean pause() {
- if ( !isStartedImpl() || pauseIssued ) {
+ @Override
+ public final synchronized boolean pause() {
+ if ( !isStarted() || pauseIssued ) {
return false;
}
- stateSync.lock();
- try {
- pauseIssued = true;
- } finally {
- stateSync.unlock();
- }
- notifyAll();
- finishLifecycleAction(waitForPausedCondition);
- return true;
+ pauseIssued = true;
+ return finishLifecycleAction(waitForPausedCondition, 0);
}
- private class WaitForPausedCondition implements Condition {
- public boolean result() {
+ private final Condition waitForPausedCondition = new Condition() {
+ @Override
+ public boolean eval() {
// end waiting if stopped as well
- return isAnimating && isStartedImpl();
- }
- }
- Condition waitForPausedCondition = new WaitForPausedCondition();
+ return isStarted() && isAnimating;
+ } };
- public synchronized boolean resume() {
- if ( !isStartedImpl() || !pauseIssued ) {
+ @Override
+ public final synchronized boolean resume() {
+ if ( !isStarted() || !pauseIssued ) {
return false;
}
- stateSync.lock();
- try {
- pauseIssued = false;
- } finally {
- stateSync.unlock();
- }
- notifyAll();
- finishLifecycleAction(waitForResumeCondition);
- return true;
+ pauseIssued = false;
+ return finishLifecycleAction(waitForResumeCondition, 0);
}
- private class WaitForResumeCondition implements Condition {
- public boolean result() {
+ private final Condition waitForResumeCondition = new Condition() {
+ @Override
+ public boolean eval() {
// end waiting if stopped as well
- return !drawablesEmpty && !isAnimating && isStartedImpl();
- }
- }
- Condition waitForResumeCondition = new WaitForResumeCondition();
+ return isStarted() && ( !drawablesEmpty && !isAnimating || drawablesEmpty && !pauseIssued ) ;
+ } };
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
index 46fc1d991..5f2db20bd 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
@@ -28,8 +28,6 @@
package com.jogamp.opengl.util;
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
import jogamp.opengl.Debug;
import jogamp.opengl.FPSCounterImpl;
@@ -38,6 +36,7 @@ import java.util.ArrayList;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
/**
@@ -52,150 +51,459 @@ import javax.media.opengl.GLProfile;
public abstract class AnimatorBase implements GLAnimatorControl {
protected static final boolean DEBUG = Debug.debug("Animator");
- private static int animatorCount = 0;
+ /** A 1s timeout while waiting for a native action response, limiting {@link #finishLifecycleAction(Condition, long)} */
+ protected static final long TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION = 1000;
- public interface AnimatorImpl {
- void display(ArrayList<GLAutoDrawable> drawables, boolean ignoreExceptions, boolean printExceptions);
- boolean blockUntilDone(Thread thread);
+ protected static final long POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION = 32; // 2 frames @ 60Hz
+
+ /**
+ * If present in <code>modeBits</code> field and
+ * {@link GLProfile#isAWTAvailable() AWT is available},
+ * implementation is aware of the AWT EDT, otherwise not.
+ * <p>
+ * This is the <i>default</i>.
+ * </p>
+ * @see #setModeBits(boolean, int)
+ */
+ public static final int MODE_EXPECT_AWT_RENDERING_THREAD = 1 << 0;
+
+
+ @SuppressWarnings("serial")
+ public static class UncaughtAnimatorException extends RuntimeException {
+ final GLAutoDrawable drawable;
+ public UncaughtAnimatorException(final GLAutoDrawable drawable, final Throwable cause) {
+ super(cause);
+ this.drawable = drawable;
+ }
+ public final GLAutoDrawable getGLAutoDrawable() { return drawable; }
}
- protected ArrayList<GLAutoDrawable> drawables = new ArrayList<GLAutoDrawable>();
- protected boolean drawablesEmpty;
+ public static interface AnimatorImpl {
+ /**
+ * @param drawables
+ * @param ignoreExceptions
+ * @param printExceptions
+ * @throws UncaughtAnimatorException as caused by {@link GLAutoDrawable#display()}
+ */
+ void display(final ArrayList<GLAutoDrawable> drawables, final boolean ignoreExceptions, final boolean printExceptions) throws UncaughtAnimatorException;
+ boolean blockUntilDone(final Thread thread);
+ }
+
+ private static int seqInstanceNumber = 0;
+
+ protected int modeBits;
protected AnimatorImpl impl;
protected String baseName;
+
+ protected ArrayList<GLAutoDrawable> drawables = new ArrayList<GLAutoDrawable>();
+ protected boolean drawablesEmpty;
protected Thread animThread;
protected boolean ignoreExceptions;
protected boolean printExceptions;
- protected FPSCounterImpl fpsCounter = new FPSCounterImpl();
- protected RecursiveLock stateSync = LockFactory.createRecursiveLock();
+ protected boolean exclusiveContext;
+ protected Thread userExclusiveContextThread;
+ protected UncaughtExceptionHandler uncaughtExceptionHandler;
+ protected FPSCounterImpl fpsCounter = new FPSCounterImpl();
- /** Creates a new, empty Animator. */
- public AnimatorBase() {
- if(GLProfile.isAWTAvailable()) {
+ private final static Class<?> awtAnimatorImplClazz;
+ static {
+ GLProfile.initSingleton();
+ if( GLProfile.isAWTAvailable() ) {
+ Class<?> clazz;
try {
- impl = (AnimatorImpl) Class.forName("com.jogamp.opengl.util.AWTAnimatorImpl").newInstance();
- baseName = "AWTAnimator";
- } catch (Exception e) { e.printStackTrace(); }
+ clazz = Class.forName("com.jogamp.opengl.util.AWTAnimatorImpl");
+ } catch (final Exception e) {
+ clazz = null;
+ }
+ awtAnimatorImplClazz = clazz;
+ } else {
+ awtAnimatorImplClazz = null;
}
- if(null==impl) {
- impl = new DefaultAnimatorImpl();
- baseName = "Animator";
+ }
+
+ /**
+ * Creates a new, empty Animator instance
+ * while expecting an AWT rendering thread if AWT is available.
+ *
+ * @see GLProfile#isAWTAvailable()
+ */
+ public AnimatorBase() {
+ modeBits = MODE_EXPECT_AWT_RENDERING_THREAD; // default!
+ drawablesEmpty = true;
+ }
+
+ private static final boolean useAWTAnimatorImpl(final int modeBits) {
+ return 0 != ( MODE_EXPECT_AWT_RENDERING_THREAD & modeBits ) && null != awtAnimatorImplClazz;
+ }
+
+ /**
+ * Initializes implementation details post setup,
+ * invoked at {@link #add(GLAutoDrawable)}, {@link #start()}, ..
+ * <p>
+ * Operation is a NOP if <code>force</code> is <code>false</code>
+ * and this instance is already initialized.
+ * </p>
+ *
+ * @throws GLException if Animator is {@link #isStarted()}
+ */
+ protected final synchronized void initImpl(final boolean force) {
+ if( force || null == impl ) {
+ final String seqSuffix = String.format("#%02d", seqInstanceNumber++);
+ if( useAWTAnimatorImpl( modeBits ) ) {
+ try {
+ impl = (AnimatorImpl) awtAnimatorImplClazz.newInstance();
+ baseName = getBaseName("AWT")+seqSuffix;
+ } catch (final Exception e) { e.printStackTrace(); }
+ }
+ if( null == impl ) {
+ impl = new DefaultAnimatorImpl();
+ baseName = getBaseName("")+seqSuffix;
+ }
+ if(DEBUG) {
+ System.err.println("Animator.initImpl: baseName "+baseName+", implClazz "+impl.getClass().getName()+" - "+toString()+" - "+getThreadName());
+ }
+ }
+ }
+ protected abstract String getBaseName(String prefix);
+
+ /**
+ * Enables or disables the given <code>bitValues</code>
+ * in this Animators <code>modeBits</code>.
+ * @param enable
+ * @param bitValues
+ *
+ * @throws GLException if Animator is {@link #isStarted()} and {@link #MODE_EXPECT_AWT_RENDERING_THREAD} about to change
+ * @see AnimatorBase#MODE_EXPECT_AWT_RENDERING_THREAD
+ */
+ public final synchronized void setModeBits(final boolean enable, final int bitValues) throws GLException {
+ final int _oldModeBits = modeBits;
+ if(enable) {
+ modeBits |= bitValues;
+ } else {
+ modeBits &= ~bitValues;
}
- synchronized (Animator.class) {
- animatorCount++;
- baseName = baseName.concat("-"+animatorCount);
- drawablesEmpty = true;
+ if( useAWTAnimatorImpl( _oldModeBits ) != useAWTAnimatorImpl( modeBits ) ) {
+ if( isStarted() ) {
+ throw new GLException("Animator already started");
+ }
+ initImpl(true);
}
}
+ public synchronized int getModeBits() { return modeBits; }
- protected abstract String getBaseName(String prefix);
- public synchronized void add(GLAutoDrawable drawable) {
+ @Override
+ public final synchronized void add(final GLAutoDrawable drawable) {
if(DEBUG) {
- System.err.println("Animator add: "+drawable.hashCode()+" - "+Thread.currentThread().getName());
+ System.err.println("Animator add: 0x"+Integer.toHexString(drawable.hashCode())+" - "+toString()+" - "+getThreadName());
+ }
+ if( drawables.contains(drawable) ) {
+ throw new IllegalArgumentException("Drawable already added to animator: "+this+", "+drawable);
+ }
+ initImpl(false);
+ pause();
+ if( isStarted() ) {
+ drawable.setExclusiveContextThread( exclusiveContext ? getExclusiveContextThread() : null ); // if already running ..
}
- boolean paused = pause();
drawables.add(drawable);
drawablesEmpty = drawables.size() == 0;
drawable.setAnimator(this);
- if(paused) {
+ if( isPaused() ) { // either paused by pause() above, or if previously drawablesEmpty==true
resume();
}
- if(impl.blockUntilDone(animThread)) {
- while(isStarted() && !isPaused() && !isAnimating()) {
- try {
- wait();
- } catch (InterruptedException ie) { }
- }
+ final Condition waitForAnimatingAndECTCondition = new Condition() {
+ @Override
+ public boolean eval() {
+ final Thread dect = drawable.getExclusiveContextThread();
+ return isStarted() && !isPaused() && !isAnimating() && ( exclusiveContext && null == dect || !exclusiveContext && null != dect );
+ } };
+ final boolean res = finishLifecycleAction(waitForAnimatingAndECTCondition, 0);
+ if(DEBUG) {
+ System.err.println("Animator add: Wait for Animating/ECT OK: "+res+", "+toString()+", dect "+drawable.getExclusiveContextThread());
}
notifyAll();
}
- public synchronized void remove(GLAutoDrawable drawable) {
+ @Override
+ public final synchronized void remove(final GLAutoDrawable drawable) {
if(DEBUG) {
- System.err.println("Animator remove: "+drawable.hashCode()+" - "+Thread.currentThread().getName() + ": "+toString());
+ System.err.println("Animator remove: 0x"+Integer.toHexString(drawable.hashCode())+" - "+toString()+" - "+getThreadName());
+ }
+ if( !drawables.contains(drawable) ) {
+ throw new IllegalArgumentException("Drawable not added to animator: "+this+", "+drawable);
+ }
+
+ if( exclusiveContext && isAnimating() ) {
+ drawable.setExclusiveContextThread( null );
+ final Condition waitForNullECTCondition = new Condition() {
+ @Override
+ public boolean eval() {
+ return null != drawable.getExclusiveContextThread();
+ } };
+ final boolean res = finishLifecycleAction(waitForNullECTCondition, POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION);
+ if(DEBUG) {
+ System.err.println("Animator remove: Wait for Null-ECT OK: "+res+", "+toString()+", dect "+drawable.getExclusiveContextThread());
+ }
}
- boolean paused = pause();
+ final boolean paused = pause();
drawables.remove(drawable);
drawablesEmpty = drawables.size() == 0;
drawable.setAnimator(null);
if(paused) {
resume();
}
- if(impl.blockUntilDone(animThread)) {
- while(isStarted() && drawablesEmpty && isAnimating()) {
- try {
- wait();
- } catch (InterruptedException ie) { }
- }
+ final boolean res = finishLifecycleAction(waitForNotAnimatingIfEmptyCondition, 0);
+ if(DEBUG) {
+ System.err.println("Animator remove: Wait for !Animating-if-empty OK: "+res+", "+toString());
}
notifyAll();
}
+ private final Condition waitForNotAnimatingIfEmptyCondition = new Condition() {
+ @Override
+ public boolean eval() {
+ return isStarted() && drawablesEmpty && isAnimating();
+ } };
+
+
+ /**
+ * Dedicate all {@link GLAutoDrawable}'s context to the given exclusive context thread.
+ * <p>
+ * The given thread will be exclusive to all {@link GLAutoDrawable}'s context while {@link #isAnimating()}.
+ * </p>
+ * <p>
+ * If already started and disabling, method waits
+ * until change is propagated to all {@link GLAutoDrawable} if not
+ * called from the animator thread or {@link #getExclusiveContextThread() exclusive context thread}.
+ * </p>
+ * <p>
+ * Note: Utilizing this feature w/ AWT could lead to an AWT-EDT deadlock, depending on the AWT implementation.
+ * Hence it is advised not to use it with native AWT GLAutoDrawable like GLCanvas.
+ * </p>
+ *
+ * @param enable
+ * @return previous value
+ * @see #setExclusiveContext(boolean)
+ * @see #getExclusiveContextThread()
+ * @see #isExclusiveContextEnabled()
+ */
+ // @Override
+ public final synchronized Thread setExclusiveContext(final Thread t) {
+ final boolean enable = null != t;
+ final Thread old = userExclusiveContextThread;
+ if( enable && t != animThread ) { // disable: will be cleared at end after propagation && filter out own animThread usae
+ userExclusiveContextThread=t;
+ }
+ setExclusiveContext(enable);
+ return old;
+ }
+
+ /**
+ * Dedicate all {@link GLAutoDrawable}'s context to this animator thread.
+ * <p>
+ * The given thread will be exclusive to all {@link GLAutoDrawable}'s context while {@link #isAnimating()}.
+ * </p>
+ * <p>
+ * If already started and disabling, method waits
+ * until change is propagated to all {@link GLAutoDrawable} if not
+ * called from the animator thread or {@link #getExclusiveContextThread() exclusive context thread}.
+ * </p>
+ * <p>
+ * Note: Utilizing this feature w/ AWT could lead to an AWT-EDT deadlock, depending on the AWT implementation.
+ * Hence it is advised not to use it with native AWT GLAutoDrawable like GLCanvas.
+ * </p>
+ *
+ * @param enable
+ * @return previous value
+ * @see #setExclusiveContext(Thread)
+ * @see #getExclusiveContextThread()
+ * @see #isExclusiveContextEnabled()
+ */
+ // @Override
+ public final boolean setExclusiveContext(final boolean enable) {
+ final boolean propagateState;
+ final boolean oldExclusiveContext;
+ final Thread _exclusiveContextThread;
+ synchronized (AnimatorBase.this) {
+ propagateState = isStarted() && !drawablesEmpty;
+ _exclusiveContextThread = userExclusiveContextThread;
+ oldExclusiveContext = exclusiveContext;
+ exclusiveContext = enable;
+ if(DEBUG) {
+ System.err.println("AnimatorBase.setExclusiveContextThread: "+oldExclusiveContext+" -> "+exclusiveContext+", propagateState "+propagateState+", "+this);
+ }
+ }
+ final Thread dECT = enable ? ( null != _exclusiveContextThread ? _exclusiveContextThread : animThread ) : null ;
+ UncaughtAnimatorException displayCaught = null;
+ if( propagateState ) {
+ setDrawablesExclCtxState(enable);
+ if( !enable ) {
+ if( Thread.currentThread() == getThread() || Thread.currentThread() == _exclusiveContextThread ) {
+ try {
+ display(); // propagate exclusive context -> off!
+ } catch (final UncaughtAnimatorException dre) {
+ displayCaught = dre;
+ }
+ } else {
+ final boolean resumed = isAnimating() ? false : resume();
+ int counter = 10;
+ while( 0<counter && isAnimating() && !validateDrawablesExclCtxState(dECT) ) {
+ try {
+ Thread.sleep(20);
+ } catch (final InterruptedException e) { }
+ counter--;
+ }
+ if(resumed) {
+ pause();
+ }
+ }
+ synchronized(AnimatorBase.this) {
+ userExclusiveContextThread=null;
+ }
+ }
+ }
+ if(DEBUG) {
+ System.err.println("AnimatorBase.setExclusiveContextThread: all-GLAD Ok: "+validateDrawablesExclCtxState(dECT)+", "+this);
+ if( null != displayCaught ) {
+ System.err.println("AnimatorBase.setExclusiveContextThread: caught: "+displayCaught.getMessage());
+ displayCaught.printStackTrace();
+ }
+ }
+ if( null != displayCaught ) {
+ throw displayCaught;
+ }
+ return oldExclusiveContext;
+ }
+
+ /**
+ * Returns <code>true</code>, if the exclusive context thread is enabled, otherwise <code>false</code>.
+ *
+ * @see #setExclusiveContext(boolean)
+ * @see #setExclusiveContext(Thread)
+ */
+ // @Override
+ public final synchronized boolean isExclusiveContextEnabled() {
+ return exclusiveContext;
+ }
+
+ /**
+ * Returns the exclusive context thread if {@link #isExclusiveContextEnabled()} and {@link #isStarted()}, otherwise <code>null</code>.
+ * <p>
+ * If exclusive context is enabled via {@link #setExclusiveContext(boolean)}
+ * the {@link #getThread() animator thread} is returned if above conditions are met.
+ * </p>
+ * <p>
+ * If exclusive context is enabled via {@link #setExclusiveContext(Thread)}
+ * the user passed thread is returned if above conditions are met.
+ * </p>
+ * @see #setExclusiveContext(boolean)
+ * @see #setExclusiveContext(Thread)
+ */
+ // @Override
+ public final synchronized Thread getExclusiveContextThread() {
+ return ( isStarted() && exclusiveContext ) ? ( null != userExclusiveContextThread ? userExclusiveContextThread : animThread ) : null ;
+ }
+
+ /**
+ * Should be called at {@link #start()} and {@link #stop()}
+ * from within the animator thread.
+ * <p>
+ * At {@link #stop()} an additional {@link #display()} call shall be issued
+ * to allow propagation of releasing the exclusive thread.
+ * </p>
+ */
+ protected final synchronized void setDrawablesExclCtxState(final boolean enable) {
+ if(DEBUG) {
+ System.err.println("AnimatorBase.setExclusiveContextImpl exlusive "+exclusiveContext+": Enable "+enable+" for "+this+" - "+Thread.currentThread());
+ // Thread.dumpStack();
+ }
+ final Thread ect = getExclusiveContextThread();
+ for (int i=0; i<drawables.size(); i++) {
+ try {
+ drawables.get(i).setExclusiveContextThread( enable ? ect : null );
+ } catch (final RuntimeException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ protected final boolean validateDrawablesExclCtxState(final Thread expected) {
+ for (int i=0; i<drawables.size(); i++) {
+ if( expected != drawables.get(i).getExclusiveContextThread() ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public final synchronized Thread getThread() {
+ return animThread;
+ }
/** Called every frame to cause redrawing of all of the
GLAutoDrawables this Animator manages. Subclasses should call
this to get the most optimized painting behavior for the set of
components this Animator manages, in particular when multiple
lightweight widgets are continually being redrawn. */
- protected void display() {
+ protected final void display() throws UncaughtAnimatorException {
impl.display(drawables, ignoreExceptions, printExceptions);
fpsCounter.tickFPS();
}
- public final void setUpdateFPSFrames(int frames, PrintStream out) {
+ @Override
+ public final void setUpdateFPSFrames(final int frames, final PrintStream out) {
fpsCounter.setUpdateFPSFrames(frames, out);
}
-
+
+ @Override
public final void resetFPSCounter() {
fpsCounter.resetFPSCounter();
}
+ @Override
public final int getUpdateFPSFrames() {
return fpsCounter.getUpdateFPSFrames();
}
-
+
+ @Override
public final long getFPSStartTime() {
return fpsCounter.getFPSStartTime();
}
+ @Override
public final long getLastFPSUpdateTime() {
return fpsCounter.getLastFPSUpdateTime();
}
+ @Override
public final long getLastFPSPeriod() {
return fpsCounter.getLastFPSPeriod();
}
-
+
+ @Override
public final float getLastFPS() {
return fpsCounter.getLastFPS();
}
-
+
+ @Override
public final int getTotalFPSFrames() {
return fpsCounter.getTotalFPSFrames();
}
+ @Override
public final long getTotalFPSDuration() {
return fpsCounter.getTotalFPSDuration();
}
-
+
+ @Override
public final float getTotalFPS() {
return fpsCounter.getTotalFPS();
- }
-
- public final Thread getThread() {
- stateSync.lock();
- try {
- return animThread;
- } finally {
- stateSync.unlock();
- }
}
/** Sets a flag causing this Animator to ignore exceptions produced
while redrawing the drawables. By default this flag is set to
false, causing any exception thrown to halt the Animator. */
- public void setIgnoreExceptions(boolean ignoreExceptions) {
+ public final void setIgnoreExceptions(final boolean ignoreExceptions) {
this.ignoreExceptions = ignoreExceptions;
}
@@ -203,11 +511,137 @@ public abstract class AnimatorBase implements GLAnimatorControl {
this Animator (see {@link #setIgnoreExceptions}), to print the
exceptions' stack traces for diagnostic information. Defaults to
false. */
- public void setPrintExceptions(boolean printExceptions) {
+ public final void setPrintExceptions(final boolean printExceptions) {
this.printExceptions = printExceptions;
}
+ @Override
+ public final UncaughtExceptionHandler getUncaughtExceptionHandler() {
+ return uncaughtExceptionHandler;
+ }
+
+ @Override
+ public final void setUncaughtExceptionHandler(final UncaughtExceptionHandler handler) {
+ uncaughtExceptionHandler = handler;
+ }
+
+ /**
+ * Should be called in case of an uncaught exception
+ * from within the animator thread, throws given exception if no handler has been installed.
+ * @return {@code true} if handled, otherwise {@code false}. In case of {@code false},
+ * caller needs to propagate the exception.
+ */
+ protected final synchronized boolean handleUncaughtException(final UncaughtAnimatorException ue) {
+ if( null != uncaughtExceptionHandler ) {
+ try {
+ uncaughtExceptionHandler.uncaughtException(this, ue.getGLAutoDrawable(), ue.getCause());
+ } catch (final Throwable t) { /* ignore intentionally */ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Should be called in case of an uncaught exception
+ * from within the animator thread to flush all animator.
+ * <p>
+ * The animator instance shall not be locked when calling this method!
+ * </p>
+ */
+ protected final void flushGLRunnables() {
+ for (int i=0; i<drawables.size(); i++) {
+ drawables.get(i).flushGLRunnables();
+ }
+ }
+
+ protected static interface Condition {
+ /**
+ * @return true if branching (continue waiting, action), otherwise false
+ */
+ boolean eval();
+ }
+
+ /**
+ * @param waitCondition method will wait until TO is reached or {@link Condition#eval() waitCondition.eval()} returns <code>false</code>.
+ * @param pollPeriod if <code>0</code>, method will wait until TO is reached or being notified.
+ * if &gt; <code>0</code>, method will wait for the given <code>pollPeriod</code> in milliseconds.
+ * @return <code>true</code> if {@link Condition#eval() waitCondition.eval()} returned <code>false</code>
+ * or if {@link AnimatorImpl#blockUntilDone(Thread) non-blocking}. Otherwise returns <code>false</code>.
+ */
+ protected final synchronized boolean finishLifecycleAction(final Condition waitCondition, long pollPeriod) {
+ /**
+ * It's hard to tell whether the thread which changes the lifecycle has
+ * dependencies on the Animator's internal thread. Currently we
+ * use a couple of heuristics to determine whether we should do
+ * the blocking wait().
+ */
+ initImpl(false);
+ final boolean blocking;
+ long remaining;
+ boolean nok;
+
+ if( impl.blockUntilDone(animThread) ) {
+ blocking = true;
+ remaining = TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION;
+ if( 0 >= pollPeriod ) {
+ pollPeriod = remaining;
+ }
+ nok = waitCondition.eval();
+ while ( nok && remaining>0 ) {
+ final long t1 = System.currentTimeMillis();
+ if( pollPeriod > remaining ) { pollPeriod = remaining; }
+ notifyAll();
+ try {
+ wait(pollPeriod);
+ } catch (final InterruptedException ie) { }
+ remaining -= System.currentTimeMillis() - t1 ;
+ nok = waitCondition.eval();
+ }
+ } else {
+ /**
+ * Even though we are not able to block until operation is completed at this point,
+ * best effort shall be made to preserve functionality.
+ * Here: Issue notifyAll() if waitCondition still holds and test again.
+ *
+ * Non blocking reason could be utilizing AWT Animator while operation is performed on AWT-EDT.
+ */
+ blocking = false;
+ remaining = 0;
+ nok = waitCondition.eval();
+ if( nok ) {
+ notifyAll();
+ nok = waitCondition.eval();
+ }
+ }
+ final boolean res = !nok || !blocking;
+ if(DEBUG || blocking && nok) { // Info only if DEBUG or ( blocking && not-ok ) ; !blocking possible if AWT
+ if( blocking && remaining<=0 && nok ) {
+ System.err.println("finishLifecycleAction(" + waitCondition.getClass().getName() + "): ++++++ timeout reached ++++++ " + getThreadName());
+ }
+ System.err.println("finishLifecycleAction(" + waitCondition.getClass().getName() + "): OK "+(!nok)+
+ "- pollPeriod "+pollPeriod+", blocking "+blocking+" -> res "+res+
+ ", waited " + (blocking ? ( TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION - remaining ) : 0 ) + "/" + TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION +
+ " - " + getThreadName());
+ System.err.println(" - "+toString());
+ if(nok) {
+ Thread.dumpStack();
+ }
+ }
+ return res;
+ }
+
+ @Override
+ public synchronized boolean isStarted() {
+ return animThread != null ;
+ }
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
+
+ @Override
public String toString() {
- return getClass().getName()+"[started "+isStarted()+", animating "+isAnimating()+", paused "+isPaused()+", drawable "+drawables.size()+", totals[dt "+getTotalFPSDuration()+", frames "+getTotalFPSFrames()+", fps "+getTotalFPS()+"]]";
+ return getClass().getName()+"[started "+isStarted()+", animating "+isAnimating()+", paused "+isPaused()+", drawable "+drawables.size()+
+ ", totals[dt "+getTotalFPSDuration()+", frames "+getTotalFPSFrames()+", fps "+getTotalFPS()+
+ "], modeBits "+modeBits+", init'ed "+(null!=impl)+", animThread "+getThread()+", exclCtxThread "+exclusiveContext+"("+getExclusiveContextThread()+")]";
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/CustomGLEventListener.java b/src/jogl/classes/com/jogamp/opengl/util/CustomGLEventListener.java
new file mode 100644
index 000000000..86443087e
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/CustomGLEventListener.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+
+/**
+ * Extended {@link GLEventListener} interface
+ * supporting more fine grained control over the implementation.
+ */
+public interface CustomGLEventListener extends GLEventListener {
+ /**
+ * {@link #display(GLAutoDrawable, int) display flag}: Repeat last produced image.
+ * <p>
+ * While a repeated frame shall produce the same artifacts as the last <code>display</code> call,
+ * e.g. not change animated objects, it shall reflect the {@link #setProjectionModelview(GLAutoDrawable, float[], float[]) current matrix}.
+ * </p>
+ */
+ public static final int DISPLAY_REPEAT = 1 << 0;
+
+ /**
+ * {@link #display(GLAutoDrawable, int) display flag}: Do not clear any target buffer, e.g. color-, depth- or stencil-buffers.
+ */
+ public static final int DISPLAY_DONTCLEAR = 1 << 1;
+
+ /**
+ * Extended {@link #display(GLAutoDrawable) display} method,
+ * allowing to pass a display flag, e.g. {@link #DISPLAY_REPEAT} or {@link #DISPLAY_DONTCLEAR}.
+ * <p>
+ * Method is usually called by a custom rendering loop,
+ * e.g. for manual stereo rendering or the like.
+ * </p>
+ * @param drawable
+ * @param flags
+ */
+ public void display(final GLAutoDrawable drawable, final int flags);
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
index 23b0845ee..6b1485a6a 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -34,33 +34,38 @@
package com.jogamp.opengl.util;
import java.util.ArrayList;
+
import javax.media.opengl.GLAutoDrawable;
+import com.jogamp.opengl.util.AnimatorBase.UncaughtAnimatorException;
+
/** Abstraction to factor out AWT dependencies from the Animator's
implementation in a way that still allows the FPSAnimator to pick
up this behavior if desired. */
class DefaultAnimatorImpl implements AnimatorBase.AnimatorImpl {
- public void display(ArrayList<GLAutoDrawable> drawables,
- boolean ignoreExceptions,
- boolean printExceptions) {
+ @Override
+ public void display(final ArrayList<GLAutoDrawable> drawables,
+ final boolean ignoreExceptions,
+ final boolean printExceptions) throws UncaughtAnimatorException {
for (int i=0; i<drawables.size(); i++) {
- GLAutoDrawable drawable = drawables.get(i);
+ final GLAutoDrawable drawable = drawables.get(i);
try {
drawable.display();
- } catch (RuntimeException e) {
+ } catch (final Throwable t) {
if (ignoreExceptions) {
if (printExceptions) {
- e.printStackTrace();
+ t.printStackTrace();
}
} else {
- throw(e);
+ throw new UncaughtAnimatorException(drawable, t);
}
}
}
}
- public boolean blockUntilDone(Thread thread) {
- return (Thread.currentThread() != thread);
+ @Override
+ public boolean blockUntilDone(final Thread thread) {
+ return Thread.currentThread() != thread;
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
index f7fc58160..54d40f285 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,36 +29,49 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package com.jogamp.opengl.util;
-import java.util.*;
-import javax.media.opengl.*;
+import java.util.Timer;
+import java.util.TimerTask;
-/** An Animator subclass which attempts to achieve a target
-frames-per-second rate to avoid using all CPU time. The target FPS
-is only an estimate and is not guaranteed. */
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLException;
+
+/**
+ * An Animator subclass which attempts to achieve a target
+ * frames-per-second rate to avoid using all CPU time. The target FPS
+ * is only an estimate and is not guaranteed.
+ * <p>
+ * The Animator execution thread does not run as a daemon thread,
+ * so it is able to keep an application from terminating.<br>
+ * Call {@link #stop() } to terminate the animation and it's execution thread.
+ * </p>
+ */
public class FPSAnimator extends AnimatorBase {
private Timer timer = null;
- private TimerTask task = null;
+ private MainTask task = null;
private int fps;
- private boolean scheduleAtFixedRate;
- private volatile boolean shouldRun;
+ private final boolean scheduleAtFixedRate;
+ private boolean isAnimating; // MainTask feedback
+ private volatile boolean pauseIssued; // MainTask trigger
+ private volatile boolean stopIssued; // MainTask trigger
- protected String getBaseName(String prefix) {
+ @Override
+ protected String getBaseName(final String prefix) {
return "FPS" + prefix + "Animator" ;
}
/** Creates an FPSAnimator with a given target frames-per-second
value. Equivalent to <code>FPSAnimator(null, fps)</code>. */
- public FPSAnimator(int fps) {
+ public FPSAnimator(final int fps) {
this(null, fps);
}
@@ -66,21 +79,22 @@ public class FPSAnimator extends AnimatorBase {
value and a flag indicating whether to use fixed-rate
scheduling. Equivalent to <code>FPSAnimator(null, fps,
scheduleAtFixedRate)</code>. */
- public FPSAnimator(int fps, boolean scheduleAtFixedRate) {
+ public FPSAnimator(final int fps, final boolean scheduleAtFixedRate) {
this(null, fps, scheduleAtFixedRate);
}
/** Creates an FPSAnimator with a given target frames-per-second
value and an initial drawable to animate. Equivalent to
<code>FPSAnimator(null, fps, false)</code>. */
- public FPSAnimator(GLAutoDrawable drawable, int fps) {
+ public FPSAnimator(final GLAutoDrawable drawable, final int fps) {
this(drawable, fps, false);
}
/** Creates an FPSAnimator with a given target frames-per-second
value, an initial drawable to animate, and a flag indicating
whether to use fixed-rate scheduling. */
- public FPSAnimator(GLAutoDrawable drawable, int fps, boolean scheduleAtFixedRate) {
+ public FPSAnimator(final GLAutoDrawable drawable, final int fps, final boolean scheduleAtFixedRate) {
+ super();
this.fps = fps;
if (drawable != null) {
add(drawable);
@@ -88,131 +102,314 @@ public class FPSAnimator extends AnimatorBase {
this.scheduleAtFixedRate = scheduleAtFixedRate;
}
- public final boolean isStarted() {
- stateSync.lock();
- try {
- return (timer != null);
- } finally {
- stateSync.unlock();
+ /**
+ * @param fps
+ * @throws GLException if the animator has already been started
+ */
+ public final void setFPS(final int fps) throws GLException {
+ if ( isStarted() ) {
+ throw new GLException("Animator already started.");
}
+ this.fps = fps;
}
+ public final int getFPS() { return fps; }
+
+ class MainTask extends TimerTask {
+ private boolean justStarted;
+ private boolean alreadyStopped;
+ private boolean alreadyPaused;
- public final boolean isAnimating() {
- stateSync.lock();
- try {
- return (timer != null) && (task != null);
- } finally {
- stateSync.unlock();
+ public MainTask() {
+ }
+
+ public void start(final Timer timer) {
+ fpsCounter.resetFPSCounter();
+ pauseIssued = false;
+ stopIssued = false;
+ isAnimating = false;
+
+ justStarted = true;
+ alreadyStopped = false;
+ alreadyPaused = false;
+
+ final long period = 0 < fps ? (long) (1000.0f / fps) : 1; // 0 -> 1: IllegalArgumentException: Non-positive period
+ if (scheduleAtFixedRate) {
+ timer.scheduleAtFixedRate(this, 0, period);
+ } else {
+ timer.schedule(this, 0, period);
+ }
}
- }
- public final boolean isPaused() {
- stateSync.lock();
- try {
- return (timer != null) && (task == null);
- } finally {
- stateSync.unlock();
+ public boolean isActive() { return !alreadyStopped && !alreadyPaused; }
+
+ @Override
+ public final String toString() {
+ return "Task[thread "+animThread+", stopped "+alreadyStopped+", paused "+alreadyPaused+" pauseIssued "+pauseIssued+", stopIssued "+stopIssued+" -- started "+isStarted()+", animating "+isAnimatingImpl()+", paused "+isPaused()+", drawable "+drawables.size()+", drawablesEmpty "+drawablesEmpty+"]";
}
- }
- private void startTask() {
- if(null != task) {
- return;
- }
- long delay = (long) (1000.0f / (float) fps);
- task = new TimerTask() {
- public void run() {
- if(FPSAnimator.this.shouldRun) {
- FPSAnimator.this.animThread = Thread.currentThread();
- // display impl. uses synchronized block on the animator instance
- display();
+ @Override
+ public void run() {
+ UncaughtAnimatorException caughtException = null;
+
+ if( justStarted ) {
+ justStarted = false;
+ synchronized (FPSAnimator.this) {
+ animThread = Thread.currentThread();
+ if(DEBUG) {
+ System.err.println("FPSAnimator start/resume:" + Thread.currentThread() + ": " + toString());
+ }
+ isAnimating = true;
+ if( drawablesEmpty ) {
+ pauseIssued = true; // isAnimating:=false @ pause below
+ } else {
+ pauseIssued = false;
+ setDrawablesExclCtxState(exclusiveContext); // may re-enable exclusive context
+ }
+ FPSAnimator.this.notifyAll(); // Wakes up 'waitForStartedCondition' sync -and resume from pause or drawablesEmpty
+ if(DEBUG) {
+ System.err.println("FPSAnimator P1:" + Thread.currentThread() + ": " + toString());
+ }
}
}
- };
+ if( !pauseIssued && !stopIssued ) { // RUN
+ try {
+ display();
+ } catch (final UncaughtAnimatorException dre) {
+ caughtException = dre;
+ stopIssued = true;
+ }
+ } else if( pauseIssued && !stopIssued ) { // PAUSE
+ if(DEBUG) {
+ System.err.println("FPSAnimator pausing: "+alreadyPaused+", "+ Thread.currentThread() + ": " + toString());
+ }
+ this.cancel();
- fpsCounter.resetFPSCounter();
- shouldRun = true;
+ if( !alreadyPaused ) { // PAUSE
+ alreadyPaused = true;
+ if( exclusiveContext && !drawablesEmpty ) {
+ setDrawablesExclCtxState(false);
+ try {
+ display(); // propagate exclusive context -> off!
+ } catch (final UncaughtAnimatorException dre) {
+ caughtException = dre;
+ stopIssued = true;
+ }
+ }
+ if( null == caughtException ) {
+ synchronized (FPSAnimator.this) {
+ if(DEBUG) {
+ System.err.println("FPSAnimator pause " + Thread.currentThread() + ": " + toString());
+ }
+ isAnimating = false;
+ FPSAnimator.this.notifyAll();
+ }
+ }
+ }
+ }
+ if( stopIssued ) { // STOP incl. immediate exception handling of 'displayCaught'
+ if(DEBUG) {
+ System.err.println("FPSAnimator stopping: "+alreadyStopped+", "+ Thread.currentThread() + ": " + toString());
+ }
+ this.cancel();
- if (scheduleAtFixedRate) {
- timer.scheduleAtFixedRate(task, 0, delay);
- } else {
- timer.schedule(task, 0, delay);
+ if( !alreadyStopped ) {
+ alreadyStopped = true;
+ if( exclusiveContext && !drawablesEmpty ) {
+ setDrawablesExclCtxState(false);
+ try {
+ display(); // propagate exclusive context -> off!
+ } catch (final UncaughtAnimatorException dre) {
+ if( null == caughtException ) {
+ caughtException = dre;
+ } else {
+ System.err.println("FPSAnimator.setExclusiveContextThread: caught: "+dre.getMessage());
+ dre.printStackTrace();
+ }
+ }
+ }
+ boolean flushGLRunnables = false;
+ boolean throwCaughtException = false;
+ synchronized (FPSAnimator.this) {
+ if(DEBUG) {
+ System.err.println("FPSAnimator stop " + Thread.currentThread() + ": " + toString());
+ if( null != caughtException ) {
+ System.err.println("Animator caught: "+caughtException.getMessage());
+ caughtException.printStackTrace();
+ }
+ }
+ isAnimating = false;
+ if( null != caughtException ) {
+ flushGLRunnables = true;
+ throwCaughtException = !handleUncaughtException(caughtException);
+ }
+ animThread = null;
+ FPSAnimator.this.notifyAll();
+ }
+ if( flushGLRunnables ) {
+ flushGLRunnables();
+ }
+ if( throwCaughtException ) {
+ throw caughtException;
+ }
+ }
+ }
}
}
+ private final boolean isAnimatingImpl() {
+ return animThread != null && isAnimating ;
+ }
+ @Override
+ public final synchronized boolean isAnimating() {
+ return animThread != null && isAnimating ;
+ }
+
+ @Override
+ public final synchronized boolean isPaused() {
+ return animThread != null && pauseIssued;
+ }
- public synchronized boolean start() {
- if (timer != null) {
+ static int timerNo = 0;
+
+ @Override
+ public final synchronized boolean start() {
+ if ( null != timer || null != task || isStarted() ) {
return false;
}
- stateSync.lock();
- try {
- timer = new Timer();
- startTask();
- } finally {
- stateSync.unlock();
+ timer = new Timer( getThreadName()+"-"+baseName+"-Timer"+(timerNo++) );
+ task = new MainTask();
+ if(DEBUG) {
+ System.err.println("FPSAnimator.start() START: "+task+", "+ Thread.currentThread() + ": " + toString());
+ }
+ task.start(timer);
+
+ final boolean res = finishLifecycleAction( drawablesEmpty ? waitForStartedEmptyCondition : waitForStartedAddedCondition,
+ POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION);
+ if(DEBUG) {
+ System.err.println("FPSAnimator.start() END: "+task+", "+ Thread.currentThread() + ": " + toString());
}
- return true;
+ if( drawablesEmpty ) {
+ task.cancel();
+ task = null;
+ }
+ return res;
}
+ private final Condition waitForStartedAddedCondition = new Condition() {
+ @Override
+ public boolean eval() {
+ return !isStarted() || !isAnimating ;
+ } };
+ private final Condition waitForStartedEmptyCondition = new Condition() {
+ @Override
+ public boolean eval() {
+ return !isStarted() || isAnimating ;
+ } };
/** Stops this FPSAnimator. Due to the implementation of the
FPSAnimator it is not guaranteed that the FPSAnimator will be
completely stopped by the time this method returns. */
- public synchronized boolean stop() {
- if (timer == null) {
+ @Override
+ public final synchronized boolean stop() {
+ if ( null == timer || !isStarted() ) {
return false;
}
- stateSync.lock();
- try {
- shouldRun = false;
- if(null != task) {
- task.cancel();
- task = null;
- }
- if(null != timer) {
- timer.cancel();
- timer = null;
- }
- animThread = null;
- try {
- Thread.sleep(20); // ~ 1/60 hz wait, since we can't ctrl stopped threads
- } catch (InterruptedException e) { }
- } finally {
- stateSync.unlock();
- }
- return true;
+ if(DEBUG) {
+ System.err.println("FPSAnimator.stop() START: "+task+", "+ Thread.currentThread() + ": " + toString());
+ }
+ final boolean res;
+ if( null == task ) {
+ // start/resume case w/ drawablesEmpty
+ res = true;
+ } else {
+ stopIssued = true;
+ res = finishLifecycleAction(waitForStoppedCondition, POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION);
+ }
+
+ if(DEBUG) {
+ System.err.println("FPSAnimator.stop() END: "+task+", "+ Thread.currentThread() + ": " + toString());
+ }
+ if(null != task) {
+ task.cancel();
+ task = null;
+ }
+ if(null != timer) {
+ timer.cancel();
+ timer = null;
+ }
+ animThread = null;
+ return res;
}
+ private final Condition waitForStoppedCondition = new Condition() {
+ @Override
+ public boolean eval() {
+ return isStarted();
+ } };
- public synchronized boolean pause() {
- if (timer == null) {
+ @Override
+ public final synchronized boolean pause() {
+ if ( !isStarted() || pauseIssued ) {
return false;
}
- stateSync.lock();
- try {
- shouldRun = false;
- if(null != task) {
- task.cancel();
- task = null;
- }
- animThread = null;
- try {
- Thread.sleep(20); // ~ 1/60 hz wait, since we can't ctrl stopped threads
- } catch (InterruptedException e) { }
- } finally {
- stateSync.unlock();
- }
- return true;
+ if(DEBUG) {
+ System.err.println("FPSAnimator.pause() START: "+task+", "+ Thread.currentThread() + ": " + toString());
+ }
+ final boolean res;
+ if( null == task ) {
+ // start/resume case w/ drawablesEmpty
+ res = true;
+ } else {
+ pauseIssued = true;
+ res = finishLifecycleAction(waitForPausedCondition, POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION);
+ }
+
+ if(DEBUG) {
+ System.err.println("FPSAnimator.pause() END: "+task+", "+ Thread.currentThread() + ": " + toString());
+ }
+ if(null != task) {
+ task.cancel();
+ task = null;
+ }
+ return res;
}
+ private final Condition waitForPausedCondition = new Condition() {
+ @Override
+ public boolean eval() {
+ // end waiting if stopped as well
+ return isStarted() && isAnimating;
+ } };
- public synchronized boolean resume() {
- if (timer == null) {
+ @Override
+ public final synchronized boolean resume() {
+ if ( !isStarted() || !pauseIssued ) {
return false;
}
- stateSync.lock();
- try {
- startTask();
- } finally {
- stateSync.unlock();
+ if(DEBUG) {
+ System.err.println("FPSAnimator.resume() START: "+ Thread.currentThread() + ": " + toString());
+ }
+ final boolean res;
+ if( drawablesEmpty ) {
+ res = true;
+ } else {
+ if( null != task ) {
+ if( DEBUG ) {
+ System.err.println("FPSAnimator.resume() Ops: !pauseIssued, but task != null: "+toString());
+ Thread.dumpStack();
+ }
+ task.cancel();
+ task = null;
+ }
+ task = new MainTask();
+ task.start(timer);
+ res = finishLifecycleAction(waitForResumeCondition, POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION);
+ }
+ if(DEBUG) {
+ System.err.println("FPSAnimator.resume() END: "+task+", "+ Thread.currentThread() + ": " + toString());
}
- return true;
+ return res;
}
+ private final Condition waitForResumeCondition = new Condition() {
+ @Override
+ public boolean eval() {
+ // end waiting if stopped as well
+ return !drawablesEmpty && !isAnimating && isStarted();
+ } };
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java
index 134dd9677..1a9ec2782 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java
@@ -1,6 +1,34 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
package com.jogamp.opengl.util;
+import java.lang.reflect.Constructor;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
@@ -26,13 +54,13 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
* and starting with a new created Buffer object with initialElementCount size
*
* On profiles GL2 and ES1 the fixed function pipeline behavior is as expected.
- * On profile ES2 the fixed function emulation will transform these calls to
+ * On profile ES2 the fixed function emulation will transform these calls to
* EnableVertexAttribArray and VertexAttribPointer calls,
* and a predefined vertex attribute variable name will be chosen.
- *
- * The default name mapping will be used,
+ *
+ * The default name mapping will be used,
* see {@link GLPointerFuncUtil#getPredefinedArrayIndexName(int)}.
- *
+ *
* @param index The GL array index
* @param comps The array component number
* @param dataType The array index GL data type
@@ -40,13 +68,13 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
* @param initialElementCount
*
* @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
- */
- public static GLArrayDataClient createFixed(int index, int comps, int dataType, boolean normalized, int initialElementCount)
+ */
+ public static GLArrayDataClient createFixed(final int index, final int comps, final int dataType, final boolean normalized, final int initialElementCount)
throws GLException
{
- GLArrayDataClient adc = new GLArrayDataClient();
- GLArrayHandler glArrayHandler = new GLFixedArrayHandler(adc);
- adc.init(null, index, comps, dataType, normalized, 0, null, initialElementCount, false, glArrayHandler, 0, 0, 0, 0, false);
+ final GLArrayDataClient adc = new GLArrayDataClient();
+ final GLArrayHandler glArrayHandler = new GLFixedArrayHandler(adc);
+ adc.init(null, index, comps, dataType, normalized, 0, null, initialElementCount, 0 /* mappedElementCount */, false, glArrayHandler, 0, 0, 0, 0, false);
return adc;
}
@@ -55,13 +83,13 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
* and starting with a given Buffer object incl it's stride
*
* On profiles GL2 and ES1 the fixed function pipeline behavior is as expected.
- * On profile ES2 the fixed function emulation will transform these calls to
+ * On profile ES2 the fixed function emulation will transform these calls to
* EnableVertexAttribArray and VertexAttribPointer calls,
* and a predefined vertex attribute variable name will be chosen.
- *
- * The default name mapping will be used,
+ *
+ * The default name mapping will be used,
* see {@link GLPointerFuncUtil#getPredefinedArrayIndexName(int)}.
- *
+ *
* @param index The GL array index
* @param comps The array component number
* @param dataType The array index GL data type
@@ -70,115 +98,132 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
* @param buffer the user define data
*
* @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
- */
- public static GLArrayDataClient createFixed(int index, int comps, int dataType, boolean normalized, int stride,
- Buffer buffer)
+ */
+ public static GLArrayDataClient createFixed(final int index, final int comps, final int dataType, final boolean normalized, final int stride,
+ final Buffer buffer)
throws GLException
{
- GLArrayDataClient adc = new GLArrayDataClient();
- GLArrayHandler glArrayHandler = new GLFixedArrayHandler(adc);
- adc.init(null, index, comps, dataType, normalized, stride, buffer, comps*comps, false, glArrayHandler, 0, 0, 0, 0, false);
+ final GLArrayDataClient adc = new GLArrayDataClient();
+ final GLArrayHandler glArrayHandler = new GLFixedArrayHandler(adc);
+ adc.init(null, index, comps, dataType, normalized, stride, buffer, comps*comps, 0 /* mappedElementCount */, false, glArrayHandler, 0, 0, 0, 0, false);
return adc;
}
/**
* Create a client side buffer object, using a custom GLSL array attribute name
* and starting with a new created Buffer object with initialElementCount size
- * @param name The custom name for the GL attribute.
+ * @param name The custom name for the GL attribute.
* @param comps The array component number
* @param dataType The array index GL data type
* @param normalized Whether the data shall be normalized
* @param initialElementCount
*/
- public static GLArrayDataClient createGLSL(String name, int comps,
- int dataType, boolean normalized, int initialElementCount)
+ public static GLArrayDataClient createGLSL(final String name, final int comps,
+ final int dataType, final boolean normalized, final int initialElementCount)
throws GLException
{
- GLArrayDataClient adc = new GLArrayDataClient();
- GLArrayHandler glArrayHandler = new GLSLArrayHandler(adc);
- adc.init(name, -1, comps, dataType, normalized, 0, null, initialElementCount, true, glArrayHandler, 0, 0, 0, 0, true);
+ final GLArrayDataClient adc = new GLArrayDataClient();
+ final GLArrayHandler glArrayHandler = new GLSLArrayHandler(adc);
+ adc.init(name, -1, comps, dataType, normalized, 0, null, initialElementCount, 0 /* mappedElementCount */, true, glArrayHandler, 0, 0, 0, 0, true);
return adc;
}
/**
* Create a client side buffer object, using a custom GLSL array attribute name
* and starting with a given Buffer object incl it's stride
- * @param name The custom name for the GL attribute.
+ * @param name The custom name for the GL attribute.
* @param comps The array component number
* @param dataType The array index GL data type
* @param normalized Whether the data shall be normalized
* @param stride
* @param buffer the user define data
*/
- public static GLArrayDataClient createGLSL(String name, int comps,
- int dataType, boolean normalized, int stride, Buffer buffer)
+ public static GLArrayDataClient createGLSL(final String name, final int comps,
+ final int dataType, final boolean normalized, final int stride, final Buffer buffer)
throws GLException
{
- GLArrayDataClient adc = new GLArrayDataClient();
- GLArrayHandler glArrayHandler = new GLSLArrayHandler(adc);
- adc.init(name, -1, comps, dataType, normalized, stride, buffer, comps*comps, true, glArrayHandler, 0, 0, 0, 0, true);
+ final GLArrayDataClient adc = new GLArrayDataClient();
+ final GLArrayHandler glArrayHandler = new GLSLArrayHandler(adc);
+ adc.init(name, -1, comps, dataType, normalized, stride, buffer, comps*comps, 0 /* mappedElementCount */, true, glArrayHandler, 0, 0, 0, 0, true);
return adc;
}
- //
+ @Override
+ public void associate(final Object obj, final boolean enable) {
+ if(obj instanceof ShaderState) {
+ if(enable) {
+ shaderState = (ShaderState)obj;
+ } else {
+ shaderState = null;
+ }
+ }
+ }
+
+ //
// Data read access
//
+ @Override
public final boolean isVBOWritten() { return bufferWritten; }
+ @Override
public final boolean sealed() { return sealed; }
-
+
+ @Override
public final boolean enabled() { return bufferEnabled; }
//
// Data and GL state modification ..
//
- public final void setVBOWritten(boolean written) { bufferWritten=written; }
+ @Override
+ public final void setVBOWritten(final boolean written) {
+ bufferWritten = ( 0 == mappedElementCount ) ? written : true;
+ }
- public void destroy(GL gl) {
+ @Override
+ public void destroy(final GL gl) {
reset(gl);
super.destroy(gl);
}
- public void reset(GL gl) {
+ @Override
+ public void reset(final GL gl) {
enableBuffer(gl, false);
reset();
}
- public void seal(GL gl, boolean seal) {
+ @Override
+ public void seal(final GL gl, final boolean seal) {
seal(seal);
enableBuffer(gl, seal);
}
- public void enableBuffer(GL gl, boolean enable) {
- if( enableBufferAlways || bufferEnabled != enable ) {
+ @Override
+ public void enableBuffer(final GL gl, final boolean enable) {
+ if( enableBufferAlways || bufferEnabled != enable ) {
if(enable) {
checkSeal(true);
// init/generate VBO name if not done yet
init_vbo(gl);
}
- final Object ext;
- if(usesGLSL) {
- ext = ShaderState.getShaderState(gl);
- if(null == ext) {
- throw new GLException("A ShaderState must be bound to the GL context, use 'ShaderState.setShaderState(gl)'");
- }
- } else {
- ext = null;
- }
- if(enable) {
- glArrayHandler.syncData(gl, true, ext);
- glArrayHandler.enableState(gl, true, ext);
- } else {
- glArrayHandler.enableState(gl, false, ext);
- glArrayHandler.syncData(gl, false, ext);
- }
+ glArrayHandler.enableState(gl, enable, usesGLSL ? shaderState : null);
bufferEnabled = enable;
}
}
- public void setEnableAlways(boolean always) {
+ @Override
+ public boolean bindBuffer(final GL gl, final boolean bind) {
+ if(bind) {
+ checkSeal(true);
+ // init/generate VBO name if not done yet
+ init_vbo(gl);
+ }
+ return glArrayHandler.bindBuffer(gl, bind);
+ }
+
+ @Override
+ public void setEnableAlways(final boolean always) {
enableBufferAlways = always;
}
@@ -186,37 +231,41 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
// Data modification ..
//
+ @Override
public void reset() {
- if(buffer!=null) {
+ if( buffer != null ) {
buffer.clear();
}
- this.sealed=false;
- this.bufferEnabled=false;
- this.bufferWritten=false;
+ sealed = false;
+ bufferEnabled = false;
+ bufferWritten = ( 0 == mappedElementCount ) ? false : true;
}
- public void seal(boolean seal)
+ @Override
+ public void seal(final boolean seal)
{
- if(sealed==seal) return;
+ if( sealed == seal ) return;
sealed = seal;
- bufferWritten=false;
- if(seal) {
- if (null!=buffer) {
+ bufferWritten = ( 0 == mappedElementCount ) ? false : true;
+ if( seal ) {
+ if ( null != buffer ) {
buffer.flip();
}
- } else if (null!=buffer) {
+ } else if ( null != buffer ) {
buffer.position(buffer.limit());
buffer.limit(buffer.capacity());
}
}
+ @Override
public void rewind() {
if(buffer!=null) {
buffer.rewind();
}
}
+ @Override
public void padding(int doneInByteSize) {
if ( buffer==null || sealed ) return;
while(doneInByteSize<strideB) {
@@ -231,7 +280,8 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
* This class buffer Class must match the arguments buffer class.
* The arguments remaining elements must be a multiple of this arrays element stride.
*/
- public void put(Buffer v) {
+ @Override
+ public void put(final Buffer v) {
if ( sealed ) return;
/** FIXME: isn't true for interleaved arrays !
if(0!=(v.remaining() % strideL)) {
@@ -241,48 +291,57 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
Buffers.put(buffer, v);
}
- public void putb(byte v) {
+ @Override
+ public void putb(final byte v) {
if ( sealed ) return;
growBufferIfNecessary(1);
Buffers.putb(buffer, v);
}
- public void puts(short v) {
+ @Override
+ public void puts(final short v) {
if ( sealed ) return;
growBufferIfNecessary(1);
Buffers.puts(buffer, v);
}
- public void puti(int v) {
+ @Override
+ public void puti(final int v) {
if ( sealed ) return;
growBufferIfNecessary(1);
Buffers.puti(buffer, v);
}
- public void putx(int v) {
+ @Override
+ public void putx(final int v) {
puti(v);
}
- public void putf(float v) {
+ @Override
+ public void putf(final float v) {
if ( sealed ) return;
growBufferIfNecessary(1);
Buffers.putf(buffer, v);
}
+ @Override
public String toString() {
return "GLArrayDataClient["+name+
", index "+index+
", location "+location+
", isVertexAttribute "+isVertexAttribute+
- ", dataType 0x"+Integer.toHexString(componentType)+
- ", bufferClazz "+componentClazz+
+ ", usesGLSL "+usesGLSL+
+ ", usesShaderState "+(null!=shaderState)+
+ ", dataType 0x"+Integer.toHexString(componentType)+
+ ", bufferClazz "+componentClazz+
", elements "+getElementCount()+
- ", components "+components+
+ ", components "+componentsPerElement+
", stride "+strideB+"b "+strideL+"c"+
- ", initialElementCount "+initialElementCount+
- ", sealed "+sealed+
- ", bufferEnabled "+bufferEnabled+
- ", bufferWritten "+bufferWritten+
+ ", mappedElementCount "+mappedElementCount+
+ ", initialElementCount "+initialElementCount+
+ ", sealed "+sealed+
+ ", bufferEnabled "+bufferEnabled+
+ ", bufferWritten "+bufferWritten+
", buffer "+buffer+
", alive "+alive+
"]";
@@ -290,48 +349,54 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
// non public matters
- protected final boolean growBufferIfNecessary(int spare) {
- if(buffer==null || buffer.remaining()<spare) {
- growBuffer(Math.max(initialElementCount, spare));
+ protected final boolean growBufferIfNecessary(final int spareComponents) {
+ if( buffer==null || buffer.remaining()<spareComponents ) {
+ if( 0 != mappedElementCount ) {
+ throw new GLException("Mapped buffer can't grow. Insufficient storage size: Needed "+spareComponents+" components, "+
+ "mappedElementCount "+mappedElementCount+
+ ", has mapped buffer "+buffer+"; "+this);
+ }
+ growBuffer(Math.max(initialElementCount, (spareComponents+componentsPerElement-1)/componentsPerElement));
return true;
}
return false;
}
- protected final void growBuffer(int additionalElements) {
+ protected final void growBuffer(int additionalElements) {
if(!alive || sealed) {
- throw new GLException("Invalid state: "+this);
+ throw new GLException("Invalid state: "+this);
}
// add the stride delta
- additionalElements += (additionalElements/components)*(strideL-components);
+ additionalElements += (additionalElements/componentsPerElement)*(strideL-componentsPerElement);
final int osize = (buffer!=null) ? buffer.capacity() : 0;
- final int nsize = osize + ( additionalElements * components );
-
+ final int nsize = osize + ( additionalElements * componentsPerElement );
+ final Buffer oldBuffer = buffer;
+
if(componentClazz==ByteBuffer.class) {
- ByteBuffer newBBuffer = Buffers.newDirectByteBuffer( nsize );
+ final ByteBuffer newBBuffer = Buffers.newDirectByteBuffer( nsize );
if(buffer!=null) {
buffer.flip();
newBBuffer.put((ByteBuffer)buffer);
}
buffer = newBBuffer;
} else if(componentClazz==ShortBuffer.class) {
- ShortBuffer newSBuffer = Buffers.newDirectShortBuffer( nsize );
+ final ShortBuffer newSBuffer = Buffers.newDirectShortBuffer( nsize );
if(buffer!=null) {
buffer.flip();
newSBuffer.put((ShortBuffer)buffer);
}
buffer = newSBuffer;
} else if(componentClazz==IntBuffer.class) {
- IntBuffer newIBuffer = Buffers.newDirectIntBuffer( nsize );
+ final IntBuffer newIBuffer = Buffers.newDirectIntBuffer( nsize );
if(buffer!=null) {
buffer.flip();
newIBuffer.put((IntBuffer)buffer);
}
buffer = newIBuffer;
} else if(componentClazz==FloatBuffer.class) {
- FloatBuffer newFBuffer = Buffers.newDirectFloatBuffer( nsize );
+ final FloatBuffer newFBuffer = Buffers.newDirectFloatBuffer( nsize );
if(buffer!=null) {
buffer.flip();
newFBuffer.put((FloatBuffer)buffer);
@@ -341,54 +406,91 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
throw new GLException("Given Buffer Class not supported: "+componentClazz+":\n\t"+this);
}
if(DEBUG) {
- System.err.println("*** Grow: comps: "+components+", "+(osize/components)+"/"+osize+" -> "+(nsize/components)+"/"+nsize+", "+this);
+ System.err.println("*** Grow: comps: "+componentsPerElement+", "+(osize/componentsPerElement)+"/"+osize+" -> "+(nsize/componentsPerElement)+"/"+nsize+
+ "; "+oldBuffer+" -> "+buffer+"; "+this);
}
}
- protected final void checkSeal(boolean test) throws GLException {
+ protected final void checkSeal(final boolean test) throws GLException {
if(!alive) {
- throw new GLException("Invalid state: "+this);
- }
+ throw new GLException("Invalid state: "+this);
+ }
if(sealed!=test) {
if(test) {
- throw new GLException("Not Sealed yet, seal first:\n\t"+this);
+ throw new GLException("Not Sealed yet, seal first:\n\t"+this);
} else {
- throw new GLException("Already Sealed, can't modify VBO:\n\t"+this);
+ throw new GLException("Already Sealed, can't modify VBO:\n\t"+this);
}
}
}
- protected void init(String name, int index, int comps, int dataType, boolean normalized, int stride, Buffer data,
- int initialElementCount, boolean isVertexAttribute, GLArrayHandler handler,
- int vboName, long vboOffset, int vboUsage, int vboTarget, boolean usesGLSL)
+ protected void init(final String name, final int index, final int comps, final int dataType, final boolean normalized, final int stride, final Buffer data,
+ final int initialElementCount, final int mappedElementCount, final boolean isVertexAttribute,
+ final GLArrayHandler handler, final int vboName, final long vboOffset, final int vboUsage, final int vboTarget, final boolean usesGLSL)
throws GLException
{
- super.init(name, index, comps, dataType, normalized, stride, data, isVertexAttribute,
- vboName, vboOffset, vboUsage, vboTarget);
+ super.init(name, index, comps, dataType, normalized, stride, data, mappedElementCount,
+ isVertexAttribute, vboName, vboOffset, vboUsage, vboTarget);
+ if( 0<mappedElementCount && 0<initialElementCount ) { // null!=buffer case validated in super.init(..)
+ throw new IllegalArgumentException("mappedElementCount:="+mappedElementCount+" specified, but passing non zero initialElementSize");
+ }
this.initialElementCount = initialElementCount;
this.glArrayHandler = handler;
this.usesGLSL = usesGLSL;
this.sealed=false;
this.bufferEnabled=false;
this.enableBufferAlways=false;
- this.bufferWritten=false;
+ this.bufferWritten = ( 0 == mappedElementCount ) ? false : true;
+
if(null==buffer && initialElementCount>0) {
growBuffer(initialElementCount);
}
}
private boolean isValidated = false;
-
- protected void init_vbo(GL gl) {
+
+ protected void init_vbo(final GL gl) {
if(!isValidated ) {
isValidated = true;
validate(gl.getGLProfile(), true);
- }
+ }
}
protected GLArrayDataClient() { }
+ /**
+ * Copy Constructor
+ * <p>
+ * Buffer is {@link Buffers#slice(Buffer) sliced}, i.e. sharing content but using own state.
+ * </p>
+ * <p>
+ * All other values are simply copied.
+ * </p>
+ */
+ public GLArrayDataClient(final GLArrayDataClient src) {
+ super(src);
+ this.isValidated = src.isValidated;
+ this.sealed = src.sealed;
+ this.bufferEnabled = src.bufferEnabled;
+ this.bufferWritten = src.bufferWritten;
+ this.enableBufferAlways = src.enableBufferAlways;
+ this.initialElementCount = src.initialElementCount;
+ if( null != src.glArrayHandler ) {
+ final Class<? extends GLArrayHandler> clazz = src.glArrayHandler.getClass();
+ try {
+ final Constructor<? extends GLArrayHandler> ctor = clazz.getConstructor(GLArrayDataEditable.class);
+ this.glArrayHandler = ctor.newInstance(this);
+ } catch (final Exception e) {
+ throw new RuntimeException("Could not ctor "+clazz.getName()+"("+this.getClass().getName()+")", e);
+ }
+ } else {
+ this.glArrayHandler = null;
+ }
+ this.usesGLSL = src.usesGLSL;
+ this.shaderState = src.shaderState;
+ }
+
protected boolean sealed;
protected boolean bufferEnabled;
protected boolean bufferWritten;
@@ -398,5 +500,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
protected GLArrayHandler glArrayHandler;
protected boolean usesGLSL;
+ protected ShaderState shaderState;
+
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java
index bb22a4b7e..9a0f1cb37 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java
@@ -14,7 +14,7 @@ import java.nio.*;
public interface GLArrayDataEditable extends GLArrayData {
public boolean sealed();
-
+
public boolean enabled();
/**
@@ -31,6 +31,7 @@ public interface GLArrayDataEditable extends GLArrayData {
// Data and GL state modification ..
//
+ @Override
public void destroy(GL gl);
public void reset(GL gl);
@@ -40,19 +41,24 @@ public interface GLArrayDataEditable extends GLArrayData {
*
* @see #seal(boolean)
* @see #enableBuffer(GL, boolean)
- *
+ *
*/
public void seal(GL gl, boolean seal);
/**
- * <p>Enables/disables the buffer,
- * sets the client state, binds the VBO if used
- * and transfers the data if necessary.</p>
- *
+ * Enables the buffer if <code>enable</code> is <code>true</code>,
+ * and transfers the data if required.
+ * In case {@link #isVBO() VBO is used}, it is bound accordingly for the data transfer and association,
+ * i.e. it issued {@link #bindBuffer(GL, boolean)}.
+ * The VBO buffer is unbound when the method returns.
+ * <p>
+ * Disables the buffer if <code>enable</code> is <code>false</code>.
+ * </p>
+ *
* <p>The action will only be executed,
- * if the internal enable state differs,
+ * if the internal enable state differs,
* or 'setEnableAlways' was called with 'true'.</b>
- *
+ *
* <p>It is up to the user to enable/disable the array properly,
* ie in case of multiple data sets for the same vertex attribute (VA).
* Meaning in such case usage of one set while expecting another one
@@ -63,11 +69,31 @@ public interface GLArrayDataEditable extends GLArrayData {
public void enableBuffer(GL gl, boolean enable);
/**
+ * if <code>bind</code> is true and the data uses {@link #isVBO() VBO},
+ * the latter will be bound and data written to the GPU if required.
+ * <p>
+ * If <code>bind</code> is false and the data uses {@link #isVBO() VBO},
+ * the latter will be unbound.
+ * </p>
+ * <p>
+ * This method is exposed to allow data VBO arrays, i.e. {@link GL#GL_ELEMENT_ARRAY_BUFFER},
+ * to be bounded and written while keeping the VBO bound. The latter is in contrast to {@link #enableBuffer(GL, boolean)},
+ * which leaves the VBO unbound, since it's not required for vertex attributes or pointers.
+ * </p>
+ *
+ * @param gl current GL object
+ * @param bind true if VBO shall be bound and data written,
+ * otherwise clear VBO binding.
+ * @return true if data uses VBO and action was performed, otherwise false
+ */
+ public boolean bindBuffer(GL gl, boolean bind);
+
+ /**
* Affects the behavior of 'enableBuffer'.
*
* The default is 'false'
*
- * This is useful when you mix up
+ * This is useful when you mix up
* GLArrayData usage with conventional GL array calls
* or in case of a buggy GL VBO implementation.
*
@@ -92,7 +118,7 @@ public interface GLArrayDataEditable extends GLArrayData {
* ie position:=limit and limit:=capacity.</p>
*
* @see #seal(boolean)
- */
+ */
public void seal(boolean seal);
public void rewind();
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java
index c9dd98751..51c55e326 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java
@@ -1,14 +1,48 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
package com.jogamp.opengl.util;
import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLArrayData;
+import javax.media.opengl.GLBufferStorage;
import javax.media.opengl.GLException;
import javax.media.opengl.fixedfunc.GLPointerFuncUtil;
+import com.jogamp.common.nio.Buffers;
+
import jogamp.opengl.util.GLArrayHandler;
import jogamp.opengl.util.GLArrayHandlerInterleaved;
import jogamp.opengl.util.GLDataArrayHandler;
@@ -30,31 +64,31 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE
* and starting with a given Buffer object incl it's stride
*
* On profiles GL2 and ES1 the fixed function pipeline behavior is as expected.
- * On profile ES2 the fixed function emulation will transform these calls to
+ * On profile ES2 the fixed function emulation will transform these calls to
* EnableVertexAttribArray and VertexAttribPointer calls,
* and a predefined vertex attribute variable name will be chosen.
- *
- * The default name mapping will be used,
+ *
+ * The default name mapping will be used,
* see {@link GLPointerFuncUtil#getPredefinedArrayIndexName(int)}.
- *
+ *
* @param index The GL array index
- * @param comps The array component number
- * @param dataType The array index GL data type
+ * @param compsPerElement component count per element
+ * @param dataType The component's OpenGL data type
* @param normalized Whether the data shall be normalized
- * @param stride
+ * @param stride in bytes from one element to the other. If zero, compsPerElement * compSizeInBytes
* @param buffer the user define data
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
*
* @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
*/
- public static GLArrayDataServer createFixed(int index, int comps, int dataType, boolean normalized, int stride,
- Buffer buffer, int vboUsage)
+ public static GLArrayDataServer createFixed(final int index, final int compsPerElement, final int dataType, final boolean normalized, final int stride,
+ final Buffer buffer, final int vboUsage)
throws GLException
{
- GLArrayDataServer ads = new GLArrayDataServer();
- GLArrayHandler glArrayHandler = new GLFixedArrayHandler(ads);
- ads.init(null, index, comps, dataType, normalized, stride, buffer, buffer.limit(), false, glArrayHandler,
- 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false);
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLFixedArrayHandler(ads);
+ ads.init(null, index, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false,
+ glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false);
return ads;
}
@@ -63,143 +97,234 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE
* and starting with a new created Buffer object with initialElementCount size
*
* On profiles GL2 and ES1 the fixed function pipeline behavior is as expected.
- * On profile ES2 the fixed function emulation will transform these calls to
+ * On profile ES2 the fixed function emulation will transform these calls to
* EnableVertexAttribArray and VertexAttribPointer calls,
* and a predefined vertex attribute variable name will be chosen.
- *
- * The default name mapping will be used,
+ *
+ * The default name mapping will be used,
* see {@link GLPointerFuncUtil#getPredefinedArrayIndexName(int)}.
- *
+ *
* @param index The GL array index
- * @param comps The array component number
- * @param dataType The array index GL data type
+ * @param compsPerElement component count per element
+ * @param dataType The component's OpenGL data type
* @param normalized Whether the data shall be normalized
* @param initialElementCount
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
*
* @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
*/
- public static GLArrayDataServer createFixed(int index, int comps, int dataType, boolean normalized, int initialElementCount,
- int vboUsage)
+ public static GLArrayDataServer createFixed(final int index, final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount,
+ final int vboUsage)
throws GLException
{
- GLArrayDataServer ads = new GLArrayDataServer();
- GLArrayHandler glArrayHandler = new GLFixedArrayHandler(ads);
- ads.init(null, index, comps, dataType, normalized, 0, null, initialElementCount, false, glArrayHandler,
- 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false);
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLFixedArrayHandler(ads);
+ ads.init(null, index, compsPerElement, dataType, normalized, 0, null, initialElementCount, 0 /* mappedElementCount */, false,
+ glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false);
return ads;
}
/**
* Create a VBO, using a custom GLSL array attribute name
* and starting with a new created Buffer object with initialElementCount size
- * @param name The custom name for the GL attribute
- * @param comps The array component number
- * @param dataType The array index GL data type
+ * @param name The custom name for the GL attribute
+ * @param compsPerElement component count per element
+ * @param dataType The component's OpenGL data type
* @param normalized Whether the data shall be normalized
* @param initialElementCount
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
*/
- public static GLArrayDataServer createGLSL(String name, int comps,
- int dataType, boolean normalized, int initialElementCount, int vboUsage)
- throws GLException
+ public static GLArrayDataServer createGLSL(final String name, final int compsPerElement,
+ final int dataType, final boolean normalized, final int initialElementCount, final int vboUsage)
+ throws GLException
{
- GLArrayDataServer ads = new GLArrayDataServer();
- GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads);
- ads.init(name, -1, comps, dataType, normalized, 0, null, initialElementCount,
- true, glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true);
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads);
+ ads.init(name, -1, compsPerElement, dataType, normalized, 0, null, initialElementCount,
+ 0 /* mappedElementCount */, true, glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true);
return ads;
- }
-
+ }
+
+ /**
+ * Create a VBO, using a custom GLSL array attribute name
+ * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}.
+ * @param name The custom name for the GL attribute
+ * @param compsPerElement component count per element
+ * @param dataType The component's OpenGL data type
+ * @param normalized Whether the data shall be normalized
+ * @param mappedElementCount
+ * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
+ */
+ public static GLArrayDataServer createGLSLMapped(final String name, final int compsPerElement,
+ final int dataType, final boolean normalized, final int mappedElementCount, final int vboUsage)
+ throws GLException
+ {
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads);
+ ads.init(name, -1, compsPerElement, dataType, normalized, 0, null, 0 /* initialElementCount */,
+ mappedElementCount, true, glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true);
+ ads.seal(true);
+ return ads;
+ }
+
/**
* Create a VBO, using a custom GLSL array attribute name
* and starting with a given Buffer object incl it's stride
- * @param name The custom name for the GL attribute
- * @param comps The array component number
- * @param dataType The array index GL data type
+ * @param name The custom name for the GL attribute
+ * @param compsPerElement component count per element
+ * @param dataType The component's OpenGL data type
* @param normalized Whether the data shall be normalized
- * @param stride
+ * @param stride in bytes from one element to the other. If zero, compsPerElement * compSizeInBytes
* @param buffer the user define data
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
*/
- public static GLArrayDataServer createGLSL(String name, int comps,
- int dataType, boolean normalized, int stride, Buffer buffer,
- int vboUsage)
+ public static GLArrayDataServer createGLSL(final String name, final int compsPerElement,
+ final int dataType, final boolean normalized, final int stride, final Buffer buffer,
+ final int vboUsage)
throws GLException
{
- GLArrayDataServer ads = new GLArrayDataServer();
- GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads);
- ads.init(name, -1, comps, dataType, normalized, stride, buffer, buffer.limit(), true, glArrayHandler,
- 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true);
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads);
+ ads.init(name, -1, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, true,
+ glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true);
return ads;
}
-
+
/**
* Create a VBO data object for any target w/o render pipeline association, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}.
- *
+ *
* Hence no index, name for a fixed function pipeline nor vertex attribute is given.
- *
- * @param comps The array component number
- * @param dataType The array index GL data type
- * @param stride
+ *
+ * @param compsPerElement component count per element
+ * @param dataType The component's OpenGL data type
+ * @param stride in bytes from one element to the other. If zero, compsPerElement * compSizeInBytes
* @param buffer the user define data
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
* @param vboTarget {@link GL#GL_ELEMENT_ARRAY_BUFFER}, ..
* {@link GL#glGenBuffers(int, int[], int)
*/
- public static GLArrayDataServer createData(int comps, int dataType, int stride,
- Buffer buffer, int vboUsage, int vboTarget)
+ public static GLArrayDataServer createData(final int compsPerElement, final int dataType, final int stride,
+ final Buffer buffer, final int vboUsage, final int vboTarget)
throws GLException
{
- GLArrayDataServer ads = new GLArrayDataServer();
- GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads);
- ads.init(null, -1, comps, dataType, false, stride, buffer, buffer.limit(), false, glArrayHandler,
- 0, 0, vboUsage, vboTarget, false);
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads);
+ ads.init(null, -1, compsPerElement, dataType, false, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false,
+ glArrayHandler, 0, 0, vboUsage, vboTarget, false);
return ads;
}
/**
* Create a VBO data object for any target w/o render pipeline association, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}.
- *
+ *
* Hence no index, name for a fixed function pipeline nor vertex attribute is given.
- *
- * @param comps The array component number
- * @param dataType The array index GL data type
+ *
+ * @param compsPerElement component count per element
+ * @param dataType The component's OpenGL data type
+ * @param initialElementCount
+ * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
+ * @param vboTarget {@link GL#GL_ELEMENT_ARRAY_BUFFER}, ..
+ */
+ public static GLArrayDataServer createData(final int compsPerElement, final int dataType, final int initialElementCount,
+ final int vboUsage, final int vboTarget)
+ throws GLException
+ {
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads);
+ ads.init(null, -1, compsPerElement, dataType, false, 0, null, initialElementCount, 0 /* mappedElementCount */, false,
+ glArrayHandler, 0, 0, vboUsage, vboTarget, false);
+ return ads;
+ }
+
+ /**
+ * Create a VBO data object for any target w/o render pipeline association, i.e. {@link GL#GL_ELEMENT_ARRAY_BUFFER},
+ * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}.
+ * <p>
+ * No index, name for a fixed function pipeline nor vertex attribute is given.
+ * </p>
+ *
+ * @param compsPerElement component count per element
+ * @param dataType The component's OpenGL data type
* @param initialElementCount
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
* @param vboTarget {@link GL#GL_ELEMENT_ARRAY_BUFFER}, ..
*/
- public static GLArrayDataServer createData(int comps, int dataType, int initialElementCount,
- int vboUsage, int vboTarget)
+ public static GLArrayDataServer createDataMapped(final int compsPerElement, final int dataType, final int mappedElementCount,
+ final int vboUsage, final int vboTarget)
throws GLException
{
- GLArrayDataServer ads = new GLArrayDataServer();
- GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads);
- ads.init(null, -1, comps, dataType, false, 0, null, initialElementCount, false, glArrayHandler,
- 0, 0, vboUsage, vboTarget, false);
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads);
+ ads.init(null, -1, compsPerElement, dataType, false, 0, null, 0 /* initialElementCount */, mappedElementCount, false,
+ glArrayHandler, 0, 0, vboUsage, vboTarget, false);
return ads;
}
-
/**
* Create a VBO for fixed function interleaved array data
* starting with a new created Buffer object with initialElementCount size.
* <p>User needs to <i>configure</i> the interleaved segments via {@link #addFixedSubArray(int, int, int)}.</p>
- *
- * @param comps The total number of all interleaved components.
- * @param dataType The array index GL data type
+ *
+ * @param compsPerElement The total number of all interleaved components per element.
+ * @param dataType The component's OpenGL data type
* @param normalized Whether the data shall be normalized
- * @param initialElementCount
+ * @param initialElementCount The initial number of all interleaved elements
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
*/
- public static GLArrayDataServer createFixedInterleaved(int comps, int dataType, boolean normalized, int initialElementCount,
- int vboUsage)
+ public static GLArrayDataServer createFixedInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount,
+ final int vboUsage)
throws GLException
{
- GLArrayDataServer ads = new GLArrayDataServer();
- GLArrayHandler glArrayHandler = new GLArrayHandlerInterleaved(ads);
- ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, comps, dataType, false, 0, null, initialElementCount, false, glArrayHandler,
- 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false);
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLArrayHandlerInterleaved(ads);
+ ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, false, 0, null, initialElementCount, 0 /* mappedElementCount */, false,
+ glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false);
+ return ads;
+ }
+
+ /**
+ * Create a VBO for fixed function interleaved array data
+ * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}.
+ * <p>User needs to <i>configure</i> the interleaved segments via {@link #addFixedSubArray(int, int, int)}.</p>
+ *
+ * @param compsPerElement The total number of all interleaved components per element.
+ * @param dataType The component's OpenGL data type
+ * @param normalized Whether the data shall be normalized
+ * @param mappedElementCount The total number of all interleaved elements
+ * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
+ */
+ public static GLArrayDataServer createFixedInterleavedMapped(final int compsPerElement, final int dataType, final boolean normalized, final int mappedElementCount,
+ final int vboUsage)
+ throws GLException
+ {
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLArrayHandlerInterleaved(ads);
+ ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, false, 0, null, 0 /* initialElementCount */, mappedElementCount, false,
+ glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false);
+ ads.seal(true);
+ return ads;
+ }
+
+ /**
+ * Create a VBO for fixed function interleaved array data
+ * starting with a given Buffer object incl it's stride
+ * <p>User needs to <i>configure</i> the interleaved segments via {@link #addFixedSubArray(int, int, int)}.</p>
+ *
+ * @param compsPerElement The total number of all interleaved components per element.
+ * @param dataType The component's OpenGL data type
+ * @param normalized Whether the data shall be normalized
+ * @param stride in bytes from one element of a sub-array to the other. If zero, compsPerElement * compSizeInBytes
+ * @param buffer The user define data of all interleaved elements
+ * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
+ */
+ public static GLArrayDataServer createFixedInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int stride, final Buffer buffer,
+ final int vboUsage)
+ throws GLException
+ {
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLArrayHandlerInterleaved(ads);
+ ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false,
+ glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false);
return ads;
}
@@ -207,91 +332,162 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE
* Configure a segment of this fixed function interleaved array (see {@link #createFixedInterleaved(int, int, boolean, int, int)}).
* <p>
* This method may be called several times as long the sum of interleaved components does not
- * exceed the total number of components of the created interleaved array.</p>
+ * exceed the total component count of the created interleaved array.</p>
* <p>
* The memory of the the interleaved array is being used.</p>
* <p>
* Must be called before using the array, eg: {@link #seal(boolean)}, {@link #putf(float)}, .. </p>
- *
+ *
* @param index The GL array index, maybe -1 if vboTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER}
- * @param comps This interleaved array segment's component number
+ * @param comps This interleaved array segment's component count per element
* @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
*/
- public GLArrayData addFixedSubArray(int index, int comps, int vboTarget) {
+ public GLArrayData addFixedSubArray(final int index, final int comps, final int vboTarget) {
if(interleavedOffset >= getComponentCount() * getComponentSizeInBytes()) {
final int iOffC = interleavedOffset / getComponentSizeInBytes();
throw new GLException("Interleaved offset > total components ("+iOffC+" > "+getComponentCount()+")");
}
if(usesGLSL) {
- throw new GLException("buffer uses GLSL");
+ throw new GLException("buffer uses GLSL");
+ }
+ final int subStrideB = ( 0 == getStride() ) ? getComponentCount() * getComponentSizeInBytes() : getStride();
+ final GLArrayDataWrapper ad;
+ if( 0 < mappedElementCount ) {
+ ad = GLArrayDataWrapper.createFixed(
+ index, comps, getComponentType(),
+ getNormalized(), subStrideB, mappedElementCount,
+ getVBOName(), interleavedOffset, getVBOUsage(), vboTarget);
+ } else {
+ ad = GLArrayDataWrapper.createFixed(
+ index, comps, getComponentType(),
+ getNormalized(), subStrideB, getBuffer(),
+ getVBOName(), interleavedOffset, getVBOUsage(), vboTarget);
}
- final GLArrayDataWrapper ad = GLArrayDataWrapper.createFixed(
- index, comps, getComponentType(),
- getNormalized(), getStride(), getBuffer(),
- getVBOName(), interleavedOffset, getVBOUsage(), vboTarget);
ad.setVBOEnabled(isVBO());
interleavedOffset += comps * getComponentSizeInBytes();
- if(GL.GL_ARRAY_BUFFER == vboTarget) {
+ if(GL.GL_ARRAY_BUFFER == vboTarget) {
glArrayHandler.addSubHandler(new GLFixedArrayHandlerFlat(ad));
}
return ad;
}
-
+
/**
* Create a VBO for GLSL interleaved array data
* starting with a new created Buffer object with initialElementCount size.
* <p>User needs to <i>configure</i> the interleaved segments via {@link #addGLSLSubArray(int, int, int)}.</p>
- *
- * @param comps The total number of all interleaved components.
- * @param dataType The array index GL data type
+ *
+ * @param compsPerElement The total number of all interleaved components per element.
+ * @param dataType The component's OpenGL data type
* @param normalized Whether the data shall be normalized
- * @param initialElementCount
+ * @param initialElementCount The initial number of all interleaved elements
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
*/
- public static GLArrayDataServer createGLSLInterleaved(int comps, int dataType, boolean normalized, int initialElementCount,
- int vboUsage)
+ public static GLArrayDataServer createGLSLInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount,
+ final int vboUsage)
throws GLException
{
- GLArrayDataServer ads = new GLArrayDataServer();
- GLArrayHandler glArrayHandler = new GLSLArrayHandlerInterleaved(ads);
- ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, comps, dataType, false, 0, null, initialElementCount, false, glArrayHandler,
- 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true);
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLSLArrayHandlerInterleaved(ads);
+ ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, 0, null, initialElementCount, 0 /* mappedElementCount */, false,
+ glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true);
return ads;
}
-
+
+ /**
+ * Create a VBO for GLSL interleaved array data
+ * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}.
+ * <p>User needs to <i>configure</i> the interleaved segments via {@link #addGLSLSubArray(int, int, int)}.</p>
+ *
+ * @param compsPerElement The total number of all interleaved components per element.
+ * @param dataType The component's OpenGL data type
+ * @param normalized Whether the data shall be normalized
+ * @param mappedElementCount The total number of all interleaved elements
+ * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
+ */
+ public static GLArrayDataServer createGLSLInterleavedMapped(final int compsPerElement, final int dataType, final boolean normalized, final int mappedElementCount, final int vboUsage)
+ throws GLException
+ {
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLSLArrayHandlerInterleaved(ads);
+ ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, 0, null, 0 /* initialElementCount */, mappedElementCount, false,
+ glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true);
+ ads.seal(true);
+ return ads;
+ }
+
+ /**
+ * Create a VBO for GLSL interleaved array data
+ * starting with a given Buffer object incl it's stride
+ * <p>User needs to <i>configure</i> the interleaved segments via {@link #addGLSLSubArray(int, int, int)}.</p>
+ *
+ * @param compsPerElement The total number of all interleaved components per element.
+ * @param dataType The component's OpenGL data type
+ * @param normalized Whether the data shall be normalized
+ * @param stride in bytes from one element of a sub-array to the other. If zero, compsPerElement * compSizeInBytes
+ * @param buffer The user define data of all interleaved elements
+ * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
+ */
+ public static GLArrayDataServer createGLSLInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int stride, final Buffer buffer,
+ final int vboUsage)
+ throws GLException
+ {
+ final GLArrayDataServer ads = new GLArrayDataServer();
+ final GLArrayHandler glArrayHandler = new GLSLArrayHandlerInterleaved(ads);
+ ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false,
+ glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true);
+ return ads;
+ }
+
/**
* Configure a segment of this GLSL interleaved array (see {@link #createGLSLInterleaved(int, int, boolean, int, int)}).
* <p>
* This method may be called several times as long the sum of interleaved components does not
- * exceed the total number of components of the created interleaved array.</p>
+ * exceed the total component count of the created interleaved array.</p>
* <p>
* The memory of the the interleaved array is being used.</p>
* <p>
* Must be called before using the array, eg: {@link #seal(boolean)}, {@link #putf(float)}, .. </p>
* @param name The custom name for the GL attribute, maybe null if vboTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER}
- * @param comps This interleaved array segment's component number
+ * @param comps This interleaved array segment's component count per element
* @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
*/
- public GLArrayData addGLSLSubArray(String name, int comps, int vboTarget) {
+ public GLArrayData addGLSLSubArray(final String name, final int comps, final int vboTarget) {
if(interleavedOffset >= getComponentCount() * getComponentSizeInBytes()) {
final int iOffC = interleavedOffset / getComponentSizeInBytes();
throw new GLException("Interleaved offset > total components ("+iOffC+" > "+getComponentCount()+")");
}
if(!usesGLSL) {
- throw new GLException("buffer uses fixed function");
+ throw new GLException("buffer uses fixed function");
+ }
+ final int subStrideB = ( 0 == getStride() ) ? getComponentCount() * getComponentSizeInBytes() : getStride();
+ final GLArrayDataWrapper ad;
+ if( 0 < mappedElementCount ) {
+ ad = GLArrayDataWrapper.createGLSL(
+ name, comps, getComponentType(),
+ getNormalized(), subStrideB, mappedElementCount,
+ getVBOName(), interleavedOffset, getVBOUsage(), vboTarget);
+ } else {
+ ad = GLArrayDataWrapper.createGLSL(
+ name, comps, getComponentType(),
+ getNormalized(), subStrideB, getBuffer(),
+ getVBOName(), interleavedOffset, getVBOUsage(), vboTarget);
}
- final GLArrayDataWrapper ad = GLArrayDataWrapper.createGLSL(
- name, comps, getComponentType(),
- getNormalized(), getStride(), getBuffer(),
- getVBOName(), interleavedOffset, getVBOUsage(), vboTarget);
ad.setVBOEnabled(isVBO());
interleavedOffset += comps * getComponentSizeInBytes();
- if(GL.GL_ARRAY_BUFFER == vboTarget) {
+ if(GL.GL_ARRAY_BUFFER == vboTarget) {
glArrayHandler.addSubHandler(new GLSLArrayHandlerFlat(ad));
}
return ad;
}
-
+
+ public final void setInterleavedOffset(final int interleavedOffset) {
+ this.interleavedOffset = interleavedOffset;
+ }
+
+ public final int getInterleavedOffset() {
+ return interleavedOffset;
+ }
+
//
// Data matters GLArrayData
//
@@ -300,11 +496,12 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE
// Data and GL state modification ..
//
- public void destroy(GL gl) {
+ @Override
+ public void destroy(final GL gl) {
// super.destroy(gl):
// - GLArrayDataClient.destroy(gl): disables & clears client-side buffer
// - GLArrayDataWrapper.destroy(gl) (clears all values 'vboName' ..)
- int _vboName = vboName;
+ final int _vboName = vboName;
super.destroy(gl);
if(_vboName!=0) {
final int[] tmp = new int[] { _vboName } ;
@@ -314,40 +511,108 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE
}
//
- // data matters
+ // data matters
//
/**
- * Convenient way do disable the VBO behavior and
+ * Convenient way do disable the VBO behavior and
* switch to client side data one
* Only possible if buffer is defined.
*/
- public void setVBOEnabled(boolean vboUsage) {
+ @Override
+ public void setVBOEnabled(final boolean vboUsage) {
checkSeal(false);
super.setVBOEnabled(vboUsage);
}
+ public GLBufferStorage mapStorage(final GL gl, final int access) {
+ if( null != this.getBuffer() ) {
+ throw new IllegalStateException("user buffer not null");
+ }
+ if( null != mappedStorage ) {
+ throw new IllegalStateException("already mapped: "+mappedStorage);
+ }
+ checkSeal(true);
+ bindBuffer(gl, true);
+ gl.glBufferData(getVBOTarget(), getSizeInBytes(), null, getVBOUsage());
+ final GLBufferStorage storage = gl.mapBuffer(getVBOTarget(), access);
+ setMappedBuffer(storage);
+ bindBuffer(gl, false);
+ seal(false);
+ rewind();
+ return storage;
+ }
+ public GLBufferStorage mapStorage(final GL gl, final long offset, final long length, final int access) {
+ if( null != this.getBuffer() ) {
+ throw new IllegalStateException("user buffer not null");
+ }
+ if( null != mappedStorage ) {
+ throw new IllegalStateException("already mapped: "+mappedStorage);
+ }
+ checkSeal(true);
+ bindBuffer(gl, true);
+ gl.glBufferData(getVBOTarget(), getSizeInBytes(), null, getVBOUsage());
+ final GLBufferStorage storage = gl.mapBufferRange(getVBOTarget(), offset, length, access);
+ setMappedBuffer(storage);
+ bindBuffer(gl, false);
+ seal(false);
+ rewind();
+ return storage;
+ }
+ private final void setMappedBuffer(final GLBufferStorage storage) {
+ mappedStorage = storage;
+ final ByteBuffer bb = storage.getMappedBuffer();
+ if(componentClazz==ByteBuffer.class) {
+ buffer = bb;
+ } else if(componentClazz==ShortBuffer.class) {
+ buffer = bb.asShortBuffer();
+ } else if(componentClazz==IntBuffer.class) {
+ buffer = bb.asIntBuffer();
+ } else if(componentClazz==FloatBuffer.class) {
+ buffer = bb.asFloatBuffer();
+ } else {
+ throw new GLException("Given Buffer Class not supported: "+componentClazz+":\n\t"+this);
+ }
+ }
+
+ public void unmapStorage(final GL gl) {
+ if( null == mappedStorage ) {
+ throw new IllegalStateException("not mapped");
+ }
+ mappedStorage = null;
+ buffer = null;
+ seal(true);
+ bindBuffer(gl, true);
+ gl.glUnmapBuffer(getVBOTarget());
+ bindBuffer(gl, false);
+ }
+
+ @Override
public String toString() {
return "GLArrayDataServer["+name+
", index "+index+
", location "+location+
", isVertexAttribute "+isVertexAttribute+
- ", dataType 0x"+Integer.toHexString(componentType)+
- ", bufferClazz "+componentClazz+
+ ", usesGLSL "+usesGLSL+
+ ", usesShaderState "+(null!=shaderState)+
+ ", dataType 0x"+Integer.toHexString(componentType)+
+ ", bufferClazz "+componentClazz+
", elements "+getElementCount()+
- ", components "+components+
+ ", components "+componentsPerElement+
", stride "+strideB+"b "+strideL+"c"+
", initialElementCount "+initialElementCount+
- ", vboEnabled "+vboEnabled+
- ", vboName "+vboName+
- ", vboUsage 0x"+Integer.toHexString(vboUsage)+
- ", vboTarget 0x"+Integer.toHexString(vboTarget)+
- ", vboOffset "+vboOffset+
- ", sealed "+sealed+
- ", bufferEnabled "+bufferEnabled+
- ", bufferWritten "+bufferWritten+
- ", buffer "+buffer+
- ", alive "+alive+
+ ", mappedElementCount "+mappedElementCount+
+ ", mappedStorage "+mappedStorage+
+ ", vboEnabled "+vboEnabled+
+ ", vboName "+vboName+
+ ", vboUsage 0x"+Integer.toHexString(vboUsage)+
+ ", vboTarget 0x"+Integer.toHexString(vboTarget)+
+ ", vboOffset "+vboOffset+
+ ", sealed "+sealed+
+ ", bufferEnabled "+bufferEnabled+
+ ", bufferWritten "+bufferWritten+
+ ", buffer "+buffer+
+ ", alive "+alive+
"]";
}
@@ -355,22 +620,24 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE
// non public matters ..
//
- protected void init(String name, int index, int comps, int dataType, boolean normalized,
- int stride, Buffer data, int initialElementCount, boolean isVertexAttribute,
- GLArrayHandler glArrayHandler,
- int vboName, long vboOffset, int vboUsage, int vboTarget, boolean usesGLSL)
+ @Override
+ protected void init(final String name, final int index, final int comps, final int dataType, final boolean normalized,
+ final int stride, final Buffer data, final int initialElementCount, final int mappedElementCount,
+ final boolean isVertexAttribute,
+ final GLArrayHandler glArrayHandler, final int vboName, final long vboOffset, final int vboUsage, final int vboTarget, final boolean usesGLSL)
throws GLException
{
- super.init(name, index, comps, dataType, normalized, stride, data, initialElementCount, isVertexAttribute, glArrayHandler,
- vboName, vboOffset, vboUsage, vboTarget, usesGLSL);
+ super.init(name, index, comps, dataType, normalized, stride, data, initialElementCount, mappedElementCount, isVertexAttribute,
+ glArrayHandler, vboName, vboOffset, vboUsage, vboTarget, usesGLSL);
vboEnabled=true;
}
- protected void init_vbo(GL gl) {
+ @Override
+ protected void init_vbo(final GL gl) {
super.init_vbo(gl);
if(vboEnabled && vboName==0) {
- int[] tmp = new int[1];
+ final int[] tmp = new int[1];
gl.glGenBuffers(1, tmp, 0);
vboName = tmp[0];
if(0 < interleavedOffset) {
@@ -378,7 +645,25 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE
}
}
}
-
- private int interleavedOffset = 0;
+
+ protected GLArrayDataServer() { }
+
+ /**
+ * Copy Constructor
+ * <p>
+ * Buffer is {@link Buffers#slice(Buffer) sliced}, i.e. sharing content but using own state.
+ * </p>
+ * <p>
+ * All other values are simply copied.
+ * </p>
+ */
+ public GLArrayDataServer(final GLArrayDataServer src) {
+ super(src);
+ this.interleavedOffset = src.interleavedOffset;
+ this.mappedStorage = src.mappedStorage;
+ }
+
+ private int interleavedOffset = 0;
+ private GLBufferStorage mappedStorage = null;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java
index bade0a3ae..867bc00ac 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java
@@ -1,3 +1,30 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
package com.jogamp.opengl.util;
@@ -15,6 +42,8 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.fixedfunc.GLPointerFuncUtil;
+import com.jogamp.common.nio.Buffers;
+
import jogamp.opengl.Debug;
public class GLArrayDataWrapper implements GLArrayData {
@@ -22,7 +51,7 @@ public class GLArrayDataWrapper implements GLArrayData {
/**
* Create a VBO, using a predefined fixed function array index, wrapping the given data.
- *
+ *
* @param index The GL array index
* @param comps The array component number
* @param dataType The array index GL data type
@@ -34,23 +63,50 @@ public class GLArrayDataWrapper implements GLArrayData {
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
* @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
* @return the new create instance
- *
+ *
+ * @throws GLException
+ */
+ public static GLArrayDataWrapper createFixed(final int index, final int comps, final int dataType, final boolean normalized, final int stride,
+ final Buffer buffer, final int vboName, final long vboOffset, final int vboUsage, final int vboTarget)
+ throws GLException
+ {
+ final GLArrayDataWrapper adc = new GLArrayDataWrapper();
+ adc.init(null, index, comps, dataType, normalized, stride, buffer, 0 /* mappedElementCount */,
+ false, vboName, vboOffset, vboUsage, vboTarget);
+ return adc;
+ }
+
+ /**
+ * Create a VBO, using a predefined fixed function array index, wrapping the mapped data characteristics.
+ *
+ * @param index The GL array index
+ * @param comps The array component number
+ * @param dataType The array index GL data type
+ * @param normalized Whether the data shall be normalized
+ * @param stride
+ * @param mappedElementCount
+ * @param vboName
+ * @param vboOffset
+ * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
+ * @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
+ * @return the new create instance
+ *
* @throws GLException
*/
- public static GLArrayDataWrapper createFixed(int index, int comps, int dataType, boolean normalized, int stride,
- Buffer buffer, int vboName, long vboOffset, int vboUsage, int vboTarget)
+ public static GLArrayDataWrapper createFixed(final int index, final int comps, final int dataType, final boolean normalized, final int stride,
+ final int mappedElementCount, final int vboName, final long vboOffset, final int vboUsage, final int vboTarget)
throws GLException
{
- GLArrayDataWrapper adc = new GLArrayDataWrapper();
- adc.init(null, index, comps, dataType, normalized, stride, buffer, false,
- vboName, vboOffset, vboUsage, vboTarget);
+ final GLArrayDataWrapper adc = new GLArrayDataWrapper();
+ adc.init(null, index, comps, dataType, normalized, stride, null, mappedElementCount,
+ false, vboName, vboOffset, vboUsage, vboTarget);
return adc;
}
/**
* Create a VBO, using a custom GLSL array attribute name, wrapping the given data.
- *
- * @param name The custom name for the GL attribute, maybe null if gpuBufferTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER}
+ *
+ * @param name The custom name for the GL attribute, maybe null if gpuBufferTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER}
* @param comps The array component number
* @param dataType The array index GL data type
* @param normalized Whether the data shall be normalized
@@ -63,30 +119,56 @@ public class GLArrayDataWrapper implements GLArrayData {
* @return the new create instance
* @throws GLException
*/
- public static GLArrayDataWrapper createGLSL(String name, int comps, int dataType, boolean normalized, int stride,
- Buffer buffer, int vboName, long vboOffset, int vboUsage, int vboTarget)
+ public static GLArrayDataWrapper createGLSL(final String name, final int comps, final int dataType, final boolean normalized, final int stride,
+ final Buffer buffer, final int vboName, final long vboOffset, final int vboUsage, final int vboTarget)
throws GLException
{
- GLArrayDataWrapper adc = new GLArrayDataWrapper();
- adc.init(name, -1, comps, dataType, normalized, stride, buffer, true,
- vboName, vboOffset, vboUsage, vboTarget);
+ final GLArrayDataWrapper adc = new GLArrayDataWrapper();
+ adc.init(name, -1, comps, dataType, normalized, stride, buffer, 0 /* mappedElementCount */,
+ true, vboName, vboOffset, vboUsage, vboTarget);
+ return adc;
+ }
+
+ /**
+ * Create a VBO, using a custom GLSL array attribute name, wrapping the mapped data characteristics.
+ *
+ * @param name The custom name for the GL attribute, maybe null if gpuBufferTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER}
+ * @param comps The array component number
+ * @param dataType The array index GL data type
+ * @param normalized Whether the data shall be normalized
+ * @param stride
+ * @param mappedElementCount
+ * @param vboName
+ * @param vboOffset
+ * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
+ * @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
+ * @return the new create instance
+ * @throws GLException
+ */
+ public static GLArrayDataWrapper createGLSL(final String name, final int comps, final int dataType, final boolean normalized, final int stride,
+ final int mappedElementCount, final int vboName, final long vboOffset, final int vboUsage, final int vboTarget)
+ throws GLException
+ {
+ final GLArrayDataWrapper adc = new GLArrayDataWrapper();
+ adc.init(name, -1, comps, dataType, normalized, stride, null, mappedElementCount,
+ true, vboName, vboOffset, vboUsage, vboTarget);
return adc;
}
/**
* Validates this instance's parameter. Called automatically by {@link GLArrayDataClient} and {@link GLArrayDataServer}.
- * {@link GLArrayDataWrapper} does not validate it's instance by itself.
- *
+ * {@link GLArrayDataWrapper} does not validate it's instance by itself.
+ *
* @param glp the GLProfile to use
* @param throwException whether to throw an exception if this instance has invalid parameter or not
* @return true if this instance has invalid parameter, otherwise false
*/
- public final boolean validate(GLProfile glp, boolean throwException) {
+ public final boolean validate(final GLProfile glp, final boolean throwException) {
if(!alive) {
if(throwException) {
throw new GLException("Instance !alive "+this);
}
- return false;
+ return false;
}
if(this.isVertexAttribute() && !glp.hasGLSL()) {
if(throwException) {
@@ -96,55 +178,104 @@ public class GLArrayDataWrapper implements GLArrayData {
}
return glp.isValidArrayDataType(getIndex(), getComponentCount(), getComponentType(), isVertexAttribute(), throwException);
}
-
- //
+
+ @Override
+ public void associate(final Object obj, final boolean enable) {
+ // nop
+ }
+
+ //
// Data read access
//
+ @Override
public final boolean isVertexAttribute() { return isVertexAttribute; }
+ @Override
public final int getIndex() { return index; }
+ @Override
public final int getLocation() { return location; }
- public final void setLocation(int v) { location = v; }
+ @Override
+ public final int setLocation(final int v) { location = v; return location; }
+
+ @Override
+ public final int setLocation(final GL2ES2 gl, final int program) {
+ location = gl.glGetAttribLocation(program, name);
+ return location;
+ }
+
+ @Override
+ public final int setLocation(final GL2ES2 gl, final int program, final int location) {
+ this.location = location;
+ gl.glBindAttribLocation(program, location, name);
+ return location;
+ }
+ @Override
public final String getName() { return name; }
+ @Override
public final long getVBOOffset() { return vboEnabled?vboOffset:0; }
+ @Override
public final int getVBOName() { return vboEnabled?vboName:0; }
+ @Override
public final boolean isVBO() { return vboEnabled; }
+ @Override
public final int getVBOUsage() { return vboEnabled?vboUsage:0; }
-
+
+ @Override
public final int getVBOTarget() { return vboEnabled?vboTarget:0; }
-
- public final Buffer getBuffer() { return buffer; }
- public final int getComponentCount() { return components; }
+ @Override
+ public Buffer getBuffer() { return buffer; }
+
+ @Override
+ public final int getComponentCount() { return componentsPerElement; }
+ @Override
public final int getComponentType() { return componentType; }
+ @Override
public final int getComponentSizeInBytes() { return componentByteSize; }
-
+
+ @Override
public final int getElementCount() {
- if(null==buffer) return 0;
- return ( buffer.position()==0 ) ? ( buffer.limit() / components ) : ( buffer.position() / components ) ;
+ if( 0 != mappedElementCount ) {
+ return mappedElementCount;
+ } else if( null != buffer ) {
+ final int remainingComponents = ( 0 == buffer.position() ) ? buffer.limit() : buffer.position();
+ return ( remainingComponents * componentByteSize ) / strideB ;
+ } else {
+ return 0;
+ }
}
+
+ @Override
public final int getSizeInBytes() {
- if(null==buffer) return 0;
- return ( buffer.position()==0 ) ? ( buffer.limit() * componentByteSize ) : ( buffer.position() * componentByteSize ) ;
+ if( 0 != mappedElementCount ) {
+ return mappedElementCount * componentsPerElement * componentByteSize ;
+ } else if( null != buffer ) {
+ return ( buffer.position()==0 ) ? ( buffer.limit() * componentByteSize ) : ( buffer.position() * componentByteSize ) ;
+ } else {
+ return 0;
+ }
}
-
+
+ @Override
public final boolean getNormalized() { return normalized; }
+ @Override
public final int getStride() { return strideB; }
- public final Class getBufferClass() { return componentClazz; }
+ public final Class<?> getBufferClass() { return componentClazz; }
- public void destroy(GL gl) {
+ @Override
+ public void destroy(final GL gl) {
buffer = null;
vboName=0;
vboEnabled=false;
@@ -152,27 +283,29 @@ public class GLArrayDataWrapper implements GLArrayData {
alive = false;
}
+ @Override
public String toString() {
return "GLArrayDataWrapper["+name+
", index "+index+
", location "+location+
", isVertexAttribute "+isVertexAttribute+
- ", dataType 0x"+Integer.toHexString(componentType)+
- ", bufferClazz "+componentClazz+
+ ", dataType 0x"+Integer.toHexString(componentType)+
+ ", bufferClazz "+componentClazz+
", elements "+getElementCount()+
- ", components "+components+
+ ", components "+componentsPerElement+
", stride "+strideB+"b "+strideL+"c"+
- ", buffer "+buffer+
- ", vboEnabled "+vboEnabled+
- ", vboName "+vboName+
- ", vboUsage 0x"+Integer.toHexString(vboUsage)+
- ", vboTarget 0x"+Integer.toHexString(vboTarget)+
- ", vboOffset "+vboOffset+
- ", alive "+alive+
+ ", mappedElementCount "+mappedElementCount+
+ ", buffer "+buffer+
+ ", vboEnabled "+vboEnabled+
+ ", vboName "+vboName+
+ ", vboUsage 0x"+Integer.toHexString(vboUsage)+
+ ", vboTarget 0x"+Integer.toHexString(vboTarget)+
+ ", vboOffset "+vboOffset+
+ ", alive "+alive+
"]";
}
- public static final Class getBufferClass(int dataType) {
+ public static final Class<?> getBufferClass(final int dataType) {
switch(dataType) {
case GL.GL_BYTE:
case GL.GL_UNSIGNED_BYTE:
@@ -180,16 +313,19 @@ public class GLArrayDataWrapper implements GLArrayData {
case GL.GL_SHORT:
case GL.GL_UNSIGNED_SHORT:
return ShortBuffer.class;
- case GL2ES1.GL_FIXED:
+ case GL.GL_UNSIGNED_INT:
+ case GL.GL_FIXED:
+ case GL2ES2.GL_INT:
return IntBuffer.class;
case GL.GL_FLOAT:
return FloatBuffer.class;
- default:
+ default:
throw new GLException("Given OpenGL data type not supported: "+dataType);
}
}
- public void setName(String newName) {
+ @Override
+ public void setName(final String newName) {
location = -1;
name = newName;
}
@@ -198,94 +334,91 @@ public class GLArrayDataWrapper implements GLArrayData {
* Enable or disable use of VBO.
* Only possible if a VBO buffer name is defined.
* @see #setVBOName(int)
- */
- public void setVBOEnabled(boolean vboEnabled) {
+ */
+ public void setVBOEnabled(final boolean vboEnabled) {
this.vboEnabled=vboEnabled;
}
/**
* Set the VBO buffer name, if valid (!= 0) enable use of VBO,
* otherwise (==0) disable VBO usage.
- *
+ *
* @see #setVBOEnabled(boolean)
- */
- public void setVBOName(int vboName) {
+ */
+ public void setVBOName(final int vboName) {
this.vboName=vboName;
setVBOEnabled(0!=vboName);
}
- /**
+ /**
* @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW}
- */
- public void setVBOUsage(int vboUsage) {
- this.vboUsage = vboUsage;
+ */
+ public void setVBOUsage(final int vboUsage) {
+ this.vboUsage = vboUsage;
}
-
- /**
+
+ /**
* @param vboTarget either {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER}
- */
- public void setVBOTarget(int vboTarget) {
+ */
+ public void setVBOTarget(final int vboTarget) {
this.vboTarget = vboTarget;
- }
+ }
- protected void init(String name, int index, int components, int componentType,
- boolean normalized, int stride, Buffer data,
- boolean isVertexAttribute,
- int vboName, long vboOffset, int vboUsage, int vboTarget)
+ protected void init(final String name, final int index, final int componentsPerElement, final int componentType,
+ final boolean normalized, final int stride, final Buffer data, final int mappedElementCount,
+ final boolean isVertexAttribute, final int vboName, final long vboOffset, final int vboUsage, final int vboTarget)
throws GLException
{
+ if( 0<mappedElementCount && null != data ) {
+ throw new IllegalArgumentException("mappedElementCount:="+mappedElementCount+" specified, but passing non null buffer");
+ }
this.isVertexAttribute = isVertexAttribute;
this.index = index;
this.location = -1;
// We can't have any dependence on the FixedFuncUtil class here for build bootstrapping reasons
-
+
if( GL.GL_ELEMENT_ARRAY_BUFFER == vboTarget ) {
- // ok ..
- } else if( GL.GL_ARRAY_BUFFER == vboTarget ) {
- // check name ..
+ // OK ..
+ } else if( ( 0 == vboUsage && 0 == vboTarget ) || GL.GL_ARRAY_BUFFER == vboTarget ) {
+ // Set/Check name .. - Required for GLSL case. Validation and debug-name for FFP.
this.name = ( null == name ) ? GLPointerFuncUtil.getPredefinedArrayIndexName(index) : name ;
if(null == this.name ) {
throw new GLException("Not a valid array buffer index: "+index);
- }
+ }
} else if( 0 < vboTarget ) {
throw new GLException("Invalid GPUBuffer target: 0x"+Integer.toHexString(vboTarget));
}
-
+
this.componentType = componentType;
componentClazz = getBufferClass(componentType);
- switch(componentType) {
- case GL.GL_BYTE:
- case GL.GL_UNSIGNED_BYTE:
- case GL.GL_SHORT:
- case GL.GL_UNSIGNED_SHORT:
- case GL.GL_FIXED:
- this.normalized = normalized;
- break;
- default:
- this.normalized = false;
+ if( GLBuffers.isGLTypeFixedPoint(componentType) ) {
+ this.normalized = normalized;
+ } else {
+ this.normalized = false;
}
componentByteSize = GLBuffers.sizeOfGLType(componentType);
if(0 > componentByteSize) {
- throw new GLException("Given componentType not supported: "+componentType+":\n\t"+this);
+ throw new GLException("Given componentType not supported: "+componentType+":\n\t"+this);
}
- if(0 >= components) {
- throw new GLException("Invalid number of components: " + components);
+ if(0 >= componentsPerElement) {
+ throw new GLException("Invalid number of components: " + componentsPerElement);
}
- this.components = components;
+ this.componentsPerElement = componentsPerElement;
- if(0<stride && stride<components*componentByteSize) {
- throw new GLException("stride ("+stride+") lower than component bytes, "+components+" * "+componentByteSize);
+ if(0<stride && stride<componentsPerElement*componentByteSize) {
+ throw new GLException("stride ("+stride+") lower than component bytes, "+componentsPerElement+" * "+componentByteSize);
}
if(0<stride && stride%componentByteSize!=0) {
throw new GLException("stride ("+stride+") not a multiple of bpc "+componentByteSize);
}
this.buffer = data;
- this.strideB=(0==stride)?components*componentByteSize:stride;
+ this.mappedElementCount = mappedElementCount;
+ this.strideB=(0==stride)?componentsPerElement*componentByteSize:stride;
this.strideL=strideB/componentByteSize;
this.vboName= vboName;
this.vboEnabled= 0 != vboName ;
this.vboOffset=vboOffset;
-
+
switch(vboUsage) {
case 0: // nop
case GL.GL_STATIC_DRAW:
@@ -293,7 +426,7 @@ public class GLArrayDataWrapper implements GLArrayData {
case GL2ES2.GL_STREAM_DRAW:
break;
default:
- throw new GLException("invalid gpuBufferUsage: "+vboUsage+":\n\t"+this);
+ throw new GLException("invalid gpuBufferUsage: "+vboUsage+":\n\t"+this);
}
switch(vboTarget) {
case 0: // nop
@@ -304,30 +437,71 @@ public class GLArrayDataWrapper implements GLArrayData {
throw new GLException("invalid gpuBufferTarget: "+vboTarget+":\n\t"+this);
}
this.vboUsage=vboUsage;
- this.vboTarget=vboTarget;
+ this.vboTarget=vboTarget;
this.alive=true;
}
protected GLArrayDataWrapper() { }
+ /**
+ * Copy Constructor
+ * <p>
+ * Buffer is {@link Buffers#slice(Buffer) sliced}, i.e. sharing content but using own state.
+ * </p>
+ * <p>
+ * All other values are simply copied.
+ * </p>
+ */
+ public GLArrayDataWrapper(final GLArrayDataWrapper src) {
+ this.alive = src.alive;
+ this.index = src.index;
+ this.location = src.location;
+ this.name = src.name;
+ this.componentsPerElement = src.componentsPerElement;
+ this.componentType = src.componentType;
+ this.componentClazz = src.componentClazz;
+ this.componentByteSize = src.componentByteSize;
+ this.normalized = src.normalized;
+ this.strideB = src.strideB;
+ this.strideL = src.strideL;
+ if( null != src.buffer ) {
+ if( src.buffer.position() == 0 ) {
+ this.buffer = Buffers.slice(src.buffer);
+ } else {
+ this.buffer = Buffers.slice(src.buffer, 0, src.buffer.limit());
+ }
+ } else {
+ this.buffer = null;
+ }
+ this.mappedElementCount = src.mappedElementCount;
+ this.isVertexAttribute = src.isVertexAttribute;
+ this.vboOffset = src.vboOffset;
+ this.vboName = src.vboName;
+ this.vboEnabled = src.vboEnabled;
+ this.vboUsage = src.vboUsage;
+ this.vboTarget = src.vboTarget;
+ }
+
protected boolean alive;
protected int index;
protected int location;
protected String name;
- protected int components;
+ protected int componentsPerElement;
protected int componentType;
- protected Class componentClazz;
+ protected Class<?> componentClazz;
protected int componentByteSize;
protected boolean normalized;
- protected int strideB; // stride in bytes
- protected int strideL; // stride in logical components
+ /** stride in bytes; strideB >= componentsPerElement * componentByteSize */
+ protected int strideB;
+ /** stride in logical components */
+ protected int strideL;
protected Buffer buffer;
+ protected int mappedElementCount;
protected boolean isVertexAttribute;
-
protected long vboOffset;
protected int vboName;
protected boolean vboEnabled;
protected int vboUsage;
- protected int vboTarget;
+ protected int vboTarget;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
index 331d6fa4e..d4ab4e4f4 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,59 +28,104 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package com.jogamp.opengl.util;
-import com.jogamp.common.nio.Buffers;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLES2;
import javax.media.opengl.GLException;
-import java.nio.*;
+import com.jogamp.common.nio.Buffers;
/**
* Utility routines for dealing with direct buffers.
- *
+ *
* @author Kenneth Russel, et.al.
*/
public class GLBuffers extends Buffers {
/**
- * @param glType shall be one of (29) <br/>
+ * @param glType GL primitive type
+ * @return false if one of GL primitive unsigned types, otherwise true
+ * GL_UNSIGNED_BYTE, <br/>
+ * GL_UNSIGNED_SHORT, <br/>
+ * GL_UNSIGNED_INT, <br/>
+ * GL_HILO16_NV <br/>
+ */
+ public static final boolean isSignedGLType(final int glType) {
+ switch (glType) { // 29
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_UNSIGNED_INT:
+ case GL2.GL_HILO16_NV:
+ return false;
+
+ }
+ return true;
+ }
+
+ /**
+ * @param glType GL primitive type
+ * @return false if one of GL primitive floating point types, otherwise true
+ * GL_FLOAT, <br/>
+ * GL_HALF_FLOAT, <br/>
+ * GL_HALF_FLOAT_OES, <br/>
+ * GL_DOUBLE <br/>
+ */
+ public static final boolean isGLTypeFixedPoint(final int glType) {
+ switch(glType) {
+ case GL.GL_FLOAT:
+ case GL.GL_HALF_FLOAT:
+ case GLES2.GL_HALF_FLOAT_OES:
+ case GL2GL3.GL_DOUBLE:
+ return false;
+
+ default:
+ return true;
+ }
+ }
+
+ /**
+ * @param glType shall be one of (31) <br/>
* GL_BYTE, GL_UNSIGNED_BYTE, <br/>
* GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
* <br/>
* GL_SHORT, GL_UNSIGNED_SHORT, <br/>
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
* GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
* GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_8_8_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, <br/>
* GL.GL_HALF_FLOAT, GLES2.GL_HALF_FLOAT_OES: <br/>
* <br/>
* GL_FIXED, GL_INT <br/>
* GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
- * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
* GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
- * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
* GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
* <br/>
* GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
* <br/>
- * GL_FLOAT, GL_DOUBLE <br/>
- *
- * @return -1 if glType is unhandled, otherwise the actual value > 0
+ * GL_FLOAT, GL_DOUBLE <br/>
+ *
+ * @return -1 if glType is unhandled, otherwise the actual value > 0
*/
- public static final int sizeOfGLType(int glType) {
+ public static final int sizeOfGLType(final int glType) {
switch (glType) { // 29
// case GL2.GL_BITMAP:
case GL.GL_BYTE:
@@ -88,249 +133,272 @@ public class GLBuffers extends Buffers {
case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
case GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV:
return SIZEOF_BYTE;
-
+
case GL.GL_SHORT:
case GL.GL_UNSIGNED_SHORT:
case GL.GL_UNSIGNED_SHORT_5_6_5:
case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
- case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL.GL_UNSIGNED_SHORT_4_4_4_4:
case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
- case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL.GL_UNSIGNED_SHORT_5_5_5_1:
case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL2.GL_UNSIGNED_SHORT_8_8_APPLE:
+ case GL2.GL_UNSIGNED_SHORT_8_8_REV_APPLE:
case GL.GL_HALF_FLOAT:
case GLES2.GL_HALF_FLOAT_OES:
return SIZEOF_SHORT;
-
+
case GL.GL_FIXED:
case GL2ES2.GL_INT:
case GL.GL_UNSIGNED_INT:
case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:
- case GL2GL3.GL_UNSIGNED_INT_10_10_10_2:
- case GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV:
- case GL2GL3.GL_UNSIGNED_INT_24_8:
- case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV:
- case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV:
+ case GL2ES2.GL_UNSIGNED_INT_10_10_10_2:
+ case GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL.GL_UNSIGNED_INT_24_8:
+ case GL.GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL2ES3.GL_UNSIGNED_INT_5_9_9_9_REV:
case GL2.GL_HILO16_NV:
case GL2.GL_SIGNED_HILO16_NV:
return SIZEOF_INT;
-
- case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+
+ case GL2ES3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
return SIZEOF_LONG;
-
+
case GL.GL_FLOAT:
return SIZEOF_FLOAT;
-
+
case GL2GL3.GL_DOUBLE:
return SIZEOF_DOUBLE;
}
return -1;
}
-
+
/**
- * @param glType shall be one of (29) <br/>
+ * @param glType shall be one of (31) <br/>
* GL_BYTE, GL_UNSIGNED_BYTE, <br/>
* GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
* <br/>
* GL_SHORT, GL_UNSIGNED_SHORT, <br/>
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
* GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
* GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_8_8_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, <br/>
* GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
* <br/>
* GL_FIXED, GL_INT <br/>
* GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
- * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
* GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
- * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
* GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
* <br/>
* GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
* <br/>
- * GL_FLOAT, GL_DOUBLE <br/>
- *
- * @return null if glType is unhandled, otherwise the new Buffer object
+ * GL_FLOAT, GL_DOUBLE <br/>
+ *
+ * @return null if glType is unhandled, otherwise the new Buffer object
*/
- public static final Buffer newDirectGLBuffer(int glType, int numElements) {
+ public static final Buffer newDirectGLBuffer(final int glType, final int numElements) {
switch (glType) { // 29
case GL.GL_BYTE:
case GL.GL_UNSIGNED_BYTE:
case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
case GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV:
return newDirectByteBuffer(numElements);
-
+
case GL.GL_SHORT:
case GL.GL_UNSIGNED_SHORT:
case GL.GL_UNSIGNED_SHORT_5_6_5:
case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
- case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL.GL_UNSIGNED_SHORT_4_4_4_4:
case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
- case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL.GL_UNSIGNED_SHORT_5_5_5_1:
case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL2.GL_UNSIGNED_SHORT_8_8_APPLE:
+ case GL2.GL_UNSIGNED_SHORT_8_8_REV_APPLE:
case GL.GL_HALF_FLOAT:
case GLES2.GL_HALF_FLOAT_OES:
return newDirectShortBuffer(numElements);
-
+
case GL.GL_FIXED:
case GL2ES2.GL_INT:
case GL.GL_UNSIGNED_INT:
case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:
- case GL2GL3.GL_UNSIGNED_INT_10_10_10_2:
- case GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV:
- case GL2GL3.GL_UNSIGNED_INT_24_8:
- case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV:
- case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV:
+ case GL2ES2.GL_UNSIGNED_INT_10_10_10_2:
+ case GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL.GL_UNSIGNED_INT_24_8:
+ case GL.GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL2ES3.GL_UNSIGNED_INT_5_9_9_9_REV:
case GL2.GL_HILO16_NV:
case GL2.GL_SIGNED_HILO16_NV:
return newDirectIntBuffer(numElements);
-
- case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+
+ case GL2ES3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
return newDirectLongBuffer(numElements);
-
+
case GL.GL_FLOAT:
return newDirectFloatBuffer(numElements);
-
- case GL2.GL_DOUBLE:
+
+ case GL2GL3.GL_DOUBLE:
return newDirectDoubleBuffer(numElements);
}
return null;
}
/**
- * @param glType shall be one of (29) <br/>
+ * @param glType shall be one of (31) <br/>
* GL_BYTE, GL_UNSIGNED_BYTE, <br/>
* GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
* <br/>
* GL_SHORT, GL_UNSIGNED_SHORT, <br/>
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
* GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
* GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_8_8_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, <br/>
* GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
* <br/>
* GL_FIXED, GL_INT <br/>
* GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
- * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
* GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
- * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
* GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
* <br/>
* GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
* <br/>
- * GL_FLOAT, GL_DOUBLE <br/>
- * @return null if glType is unhandled or parent is null or bufLen is 0, otherwise the new Buffer object
+ * GL_FLOAT, GL_DOUBLE <br/>
+ * @return null if glType is unhandled or parent is null or bufLen is 0, otherwise the new Buffer object
*/
- public static final Buffer sliceGLBuffer(ByteBuffer parent, int bytePos, int byteLen, int glType) {
+ public static final Buffer sliceGLBuffer(final ByteBuffer parent, final int bytePos, final int byteLen, final int glType) {
if (parent == null || byteLen == 0) {
return null;
}
+ final int parentPos = parent.position();
+ final int parentLimit = parent.limit();
+
parent.position(bytePos);
parent.limit(bytePos + byteLen);
+ Buffer res = null;
switch (glType) { // 29
case GL.GL_BYTE:
case GL.GL_UNSIGNED_BYTE:
case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
case GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV:
- return parent.slice();
-
+ res = parent.slice().order(parent.order()); // slice and duplicate may change byte order
+ break;
+
case GL.GL_SHORT:
case GL.GL_UNSIGNED_SHORT:
case GL.GL_UNSIGNED_SHORT_5_6_5:
case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
- case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL.GL_UNSIGNED_SHORT_4_4_4_4:
case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
- case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL.GL_UNSIGNED_SHORT_5_5_5_1:
case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL2.GL_UNSIGNED_SHORT_8_8_APPLE:
+ case GL2.GL_UNSIGNED_SHORT_8_8_REV_APPLE:
case GL.GL_HALF_FLOAT:
case GLES2.GL_HALF_FLOAT_OES:
- return parent.asShortBuffer();
-
+ res = parent.slice().order(parent.order()).asShortBuffer(); // slice and duplicate may change byte order
+ break;
+
case GL.GL_FIXED:
- case GL2GL3.GL_INT:
- case GL2ES2.GL_UNSIGNED_INT:
+ case GL2ES2.GL_INT:
+ case GL.GL_UNSIGNED_INT:
case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:
- case GL2GL3.GL_UNSIGNED_INT_10_10_10_2:
- case GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV:
- case GL2GL3.GL_UNSIGNED_INT_24_8:
- case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV:
- case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV:
+ case GL2ES2.GL_UNSIGNED_INT_10_10_10_2:
+ case GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL.GL_UNSIGNED_INT_24_8:
+ case GL.GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL2ES3.GL_UNSIGNED_INT_5_9_9_9_REV:
case GL2.GL_HILO16_NV:
case GL2.GL_SIGNED_HILO16_NV:
- return parent.asIntBuffer();
-
- case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
- return parent.asLongBuffer();
-
+ res = parent.slice().order(parent.order()).asIntBuffer(); // slice and duplicate may change byte order
+ break;
+
+ case GL2ES3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ res = parent.slice().order(parent.order()).asLongBuffer(); // slice and duplicate may change byte order
+ break;
+
case GL.GL_FLOAT:
- return parent.asFloatBuffer();
-
- case GL2.GL_DOUBLE:
- return parent.asDoubleBuffer();
+ res = parent.slice().order(parent.order()).asFloatBuffer(); // slice and duplicate may change byte order
+ break;
+
+ case GL2GL3.GL_DOUBLE:
+ res = parent.slice().order(parent.order()).asDoubleBuffer(); // slice and duplicate may change byte order
+ break;
}
- return null;
+ parent.position(parentPos).limit(parentLimit);
+ return res;
}
- private static final int glGetInteger(GL gl, int pname, int[] tmp) {
+ private static final int glGetInteger(final GL gl, final int pname, final int[] tmp) {
gl.glGetIntegerv(pname, tmp, 0);
return tmp[0];
}
-
- /**
+
+ /**
* Returns the number of bytes required to read/write a memory buffer via OpenGL
* using the current GL pixel storage state and the given parameters.
- *
+ *
* <p>This method is security critical, hence it throws an exception (fail-fast)
- * in case of an invalid alignment. In case we forgot to handle
- * proper values, please contact the maintainer.</p>
- *
+ * in case of an invalid alignment. In case we forgot to handle
+ * proper values, please contact the maintainer.</p>
+ *
* @param gl the current GL object
- *
+ *
* @param tmp a pass through integer array of size >= 1 used to store temp data (performance)
- *
- * @param bytesPerElement bytes per element
+ *
+ * @param bytesPerPixel bytes per pixel, i.e. via {@link #bytesPerPixel(int, int)}.
* @param width in pixels
* @param height in pixels
* @param depth in pixels
- * @param pack true for read mode GPU -> CPU (pack), otherwise false for write mode CPU -> GPU (unpack)
+ * @param pack true for read mode GPU -> CPU (pack), otherwise false for write mode CPU -> GPU (unpack)
* @return required minimum size of the buffer in bytes
* @throws GLException if alignment is invalid. Please contact the maintainer if this is our bug.
*/
- public static final int sizeof(GL gl, int tmp[],
- int bytesPerElement, int width, int height, int depth,
- boolean pack) {
+ public static final int sizeof(final GL gl, final int tmp[],
+ final int bytesPerPixel, int width, int height, int depth,
+ final boolean pack) {
int rowLength = 0;
int skipRows = 0;
int skipPixels = 0;
int alignment = 1;
int imageHeight = 0;
int skipImages = 0;
-
- if (pack) {
+
+ if (pack) {
alignment = glGetInteger(gl, GL.GL_PACK_ALIGNMENT, tmp);
- if(gl.isGL2GL3()) {
- rowLength = glGetInteger(gl, GL2GL3.GL_PACK_ROW_LENGTH, tmp);
- skipRows = glGetInteger(gl, GL2GL3.GL_PACK_SKIP_ROWS, tmp);
- skipPixels = glGetInteger(gl, GL2GL3.GL_PACK_SKIP_PIXELS, tmp);
- if (depth > 1) {
- imageHeight = glGetInteger(gl, GL2GL3.GL_PACK_IMAGE_HEIGHT, tmp);
+ if( gl.isGL2ES3() ) {
+ rowLength = glGetInteger(gl, GL2ES3.GL_PACK_ROW_LENGTH, tmp);
+ skipRows = glGetInteger(gl, GL2ES3.GL_PACK_SKIP_ROWS, tmp);
+ skipPixels = glGetInteger(gl, GL2ES3.GL_PACK_SKIP_PIXELS, tmp);
+ if (depth > 1 && gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version120) >= 0 ) {
+ imageHeight = glGetInteger(gl, GL2GL3.GL_PACK_IMAGE_HEIGHT, tmp);
skipImages = glGetInteger(gl, GL2GL3.GL_PACK_SKIP_IMAGES, tmp);
}
}
- } else {
+ } else {
alignment = glGetInteger(gl, GL.GL_UNPACK_ALIGNMENT, tmp);
- if(gl.isGL2GL3 ()) {
- rowLength = glGetInteger(gl, GL2GL3.GL_UNPACK_ROW_LENGTH, tmp);
- skipRows = glGetInteger(gl, GL2GL3.GL_UNPACK_SKIP_ROWS, tmp);
- skipPixels = glGetInteger(gl, GL2GL3.GL_UNPACK_SKIP_PIXELS, tmp);
- if (depth > 1) {
- imageHeight = glGetInteger(gl, GL2GL3.GL_UNPACK_IMAGE_HEIGHT, tmp);
- skipImages = glGetInteger(gl, GL2GL3.GL_UNPACK_SKIP_IMAGES, tmp);
- }
+ if( gl.isGL2ES3() ) {
+ rowLength = glGetInteger(gl, GL2ES2.GL_UNPACK_ROW_LENGTH, tmp);
+ skipRows = glGetInteger(gl, GL2ES2.GL_UNPACK_SKIP_ROWS, tmp);
+ skipPixels = glGetInteger(gl, GL2ES2.GL_UNPACK_SKIP_PIXELS, tmp);
+ if( depth > 1 &&
+ ( gl.isGL3ES3() ||
+ ( gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version120) >= 0 )
+ )
+ ) {
+ imageHeight = glGetInteger(gl, GL2ES3.GL_UNPACK_IMAGE_HEIGHT, tmp);
+ skipImages = glGetInteger(gl, GL2ES3.GL_UNPACK_SKIP_IMAGES, tmp);
+ }
}
}
-
+
// Try to deal somewhat correctly with potentially invalid values
width = Math.max(0, width );
height = Math.max(1, height); // min 1D
@@ -339,13 +407,13 @@ public class GLBuffers extends Buffers {
skipPixels = Math.max(0, skipPixels);
alignment = Math.max(1, alignment);
skipImages = Math.max(0, skipImages);
-
+
imageHeight = ( imageHeight > 0 ) ? imageHeight : height;
rowLength = ( rowLength > 0 ) ? rowLength : width;
-
- int rowLengthInBytes = rowLength * bytesPerElement;
- int skipBytes = skipPixels * bytesPerElement;
-
+
+ int rowLengthInBytes = rowLength * bytesPerPixel;
+ int skipBytes = skipPixels * bytesPerPixel;
+
switch(alignment) {
case 1:
break;
@@ -361,208 +429,318 @@ public class GLBuffers extends Buffers {
if (remainder > 0) {
skipBytes += alignment - remainder;
}
- }
+ }
break;
default:
- throw new GLException("Invalid alignment "+alignment+", must be 2**n (1,2,4,8). Pls notify the maintainer in case this is our bug.");
+ throw new GLException("Invalid alignment "+alignment+", must be 2**n (1,2,4,8). Pls notify the maintainer in case this is our bug.");
}
-
+
/**
* skipImages, depth, skipPixels and skipRows are static offsets.
*
* skipImages and depth are in multiples of image size.
*
* skipBytes and rowLengthInBytes are aligned
- *
- * rowLengthInBytes is the aligned byte offset
+ *
+ * rowLengthInBytes is the aligned byte offset
* from line n to line n+1 at the same x-axis position.
*/
return
skipBytes + // aligned skipPixels * bpp
- ( skipImages + depth - 1 ) * imageHeight * rowLengthInBytes + // aligned whole images
+ ( skipImages + depth - 1 ) * imageHeight * rowLengthInBytes + // aligned whole images
( skipRows + height - 1 ) * rowLengthInBytes + // aligned lines
- width * bytesPerElement; // last line
+ width * bytesPerPixel; // last line
}
-
- /**
+
+ /**
* Returns the number of bytes required to read/write a memory buffer via OpenGL
* using the current GL pixel storage state and the given parameters.
- *
+ *
* <p>This method is security critical, hence it throws an exception (fail-fast)
- * in case either the format, type or alignment is unhandled. In case we forgot to handle
- * proper values, please contact the maintainer.</p>
- *
+ * in case either the format, type or alignment is unhandled. In case we forgot to handle
+ * proper values, please contact the maintainer.</p>
+ *
+ * <p> See {@link #bytesPerPixel(int, int)}. </p>
+ *
* @param gl the current GL object
- *
+ *
* @param tmp a pass through integer array of size >= 1 used to store temp data (performance)
- *
- * @param format must be one of (26) <br/>
- * GL_COLOR_INDEX GL_STENCIL_INDEX <br/>
- * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/>
- * GL_RED GL_RED_INTEGER <br/>
- * GL_GREEN GL_GREEN_INTEGER <br/>
- * GL_BLUE GL_BLUE_INTEGER <br/>
- * GL_ALPHA GL_LUMINANCE (12) <br/>
- * <br/>
+ *
+ * @param format must be one of (27) <br/>
+ * GL_COLOR_INDEX GL_STENCIL_INDEX <br/>
+ * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/>
+ * GL_RED GL_RED_INTEGER <br/>
+ * GL_GREEN GL_GREEN_INTEGER <br/>
+ * GL_BLUE GL_BLUE_INTEGER <br/>
+ * GL_ALPHA GL_LUMINANCE (12) <br/>
+ * <br/>
* GL_LUMINANCE_ALPHA GL_RG <br/>
- * GL_RG_INTEGER GL_HILO_NV <br/>
- * GL_SIGNED_HILO_NV (5) <br/>
- * <br/>
- * GL_RGB GL_RGB_INTEGER <br/>
- * GL_BGR GL_BGR_INTEGER (4)<br/>
- * <br/>
- * GL_RGBA GL_RGBA_INTEGER <br/>
+ * GL_RG_INTEGER GL_HILO_NV <br/>
+ * GL_SIGNED_HILO_NV (5) <br/>
+ * <br/>
+ * GL_YCBCR_422_APPLE <br/>
+ * <br/>
+ * GL_RGB GL_RGB_INTEGER <br/>
+ * GL_BGR GL_BGR_INTEGER (4)<br/>
+ * <br/>
+ * GL_RGBA GL_RGBA_INTEGER <br/>
* GL_BGRA GL_BGRA_INTEGER <br/>
- * GL_ABGR_EXT (5)<br/>
- *
- * @param type must be one of (30) <br/>
- * GL_BITMAP, <br/>
+ * GL_ABGR_EXT (5)<br/>
+ *
+ * @param type must be one of (32) <br/>
+ * GL_BITMAP, <br/>
* GL_BYTE, GL_UNSIGNED_BYTE, <br/>
* GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
* <br/>
* GL_SHORT, GL_UNSIGNED_SHORT, <br/>
- * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
* GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
* GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_8_8_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, <br/>
* GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
* <br/>
* GL_FIXED, GL_INT <br/>
* GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
- * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
* GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
- * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
* GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
* <br/>
* GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
* <br/>
- * GL_FLOAT, GL_DOUBLE <br/>
- *
+ * GL_FLOAT, GL_DOUBLE <br/>
+ *
* @param width in pixels
* @param height in pixels
* @param depth in pixels
- * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
+ * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
* @return required minimum size of the buffer in bytes
* @throws GLException if format, type or alignment is not handled. Please contact the maintainer if this is our bug.
*/
- public static final int sizeof(GL gl, int tmp[],
- int format, int type, int width, int height, int depth,
- boolean pack) throws GLException {
- int elements = 0;
- int esize = 0;
-
+ public static final int sizeof(final GL gl, final int tmp[],
+ final int format, final int type, final int width, final int height, final int depth,
+ final boolean pack) throws GLException {
if (width < 0) return 0;
if (height < 0) return 0;
if (depth < 0) return 0;
-
- switch (format) /* 26 */ {
- case GL2.GL_COLOR_INDEX:
- case GL2GL3.GL_STENCIL_INDEX:
- case GL2GL3.GL_DEPTH_COMPONENT:
- case GL2GL3.GL_DEPTH_STENCIL:
- case GL2GL3.GL_RED:
- case GL2GL3.GL_RED_INTEGER:
- case GL2GL3.GL_GREEN:
- case GL2GL3.GL_GREEN_INTEGER:
- case GL2GL3.GL_BLUE:
- case GL2GL3.GL_BLUE_INTEGER:
- case GL.GL_ALPHA:
- case GL.GL_LUMINANCE:
- elements = 1;
- break;
- case GL.GL_LUMINANCE_ALPHA:
- case GL2GL3.GL_RG:
- case GL2GL3.GL_RG_INTEGER:
- case GL2.GL_HILO_NV:
- case GL2.GL_SIGNED_HILO_NV:
- elements = 2;
- break;
- case GL.GL_RGB:
- case GL2GL3.GL_RGB_INTEGER:
- case GL2GL3.GL_BGR:
- case GL2GL3.GL_BGR_INTEGER:
- elements = 3;
- break;
- case GL.GL_RGBA:
- case GL2GL3.GL_RGBA_INTEGER:
- case GL.GL_BGRA:
- case GL2GL3.GL_BGRA_INTEGER:
- case GL2.GL_ABGR_EXT:
- elements = 4;
- break;
- /* FIXME ??
- case GL.GL_HILO_NV:
- elements = 2;
- break; */
- default:
- throw new GLException("format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug.");
- }
-
+
+ final int bytesPerPixel = bytesPerPixel(format, type);
+ return sizeof(gl, tmp, bytesPerPixel, width, height, depth, pack);
+ }
+
+ /**
+ * Returns the number of bytes required for one pixel with the the given OpenGL format and type.
+ *
+ * <p>This method is security critical, hence it throws an exception (fail-fast)
+ * in case either the format, type or alignment is unhandled. In case we forgot to handle
+ * proper values, please contact the maintainer.</p>
+ *
+ * <p> See {@link #componentCount(int)}. </p>
+ *
+ * @param format must be one of (27) <br/>
+ * GL_COLOR_INDEX GL_STENCIL_INDEX <br/>
+ * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/>
+ * GL_RED GL_RED_INTEGER <br/>
+ * GL_GREEN GL_GREEN_INTEGER <br/>
+ * GL_BLUE GL_BLUE_INTEGER <br/>
+ * GL_ALPHA GL_LUMINANCE (12) <br/>
+ * <br/>
+ * GL_LUMINANCE_ALPHA GL_RG <br/>
+ * GL_RG_INTEGER GL_HILO_NV <br/>
+ * GL_SIGNED_HILO_NV (5) <br/>
+ * <br/>
+ * GL_YCBCR_422_APPLE <br/>
+ * <br/>
+ * GL_RGB GL_RGB_INTEGER <br/>
+ * GL_BGR GL_BGR_INTEGER (4)<br/>
+ * <br/>
+ * GL_RGBA GL_RGBA_INTEGER <br/>
+ * GL_BGRA GL_BGRA_INTEGER <br/>
+ * GL_ABGR_EXT (5)<br/>
+ *
+ * @param type must be one of (32) <br/>
+ * GL_BITMAP, <br/>
+ * GL_BYTE, GL_UNSIGNED_BYTE, <br/>
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
+ * <br/>
+ * GL_SHORT, GL_UNSIGNED_SHORT, <br/>
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+ * GL_UNSIGNED_SHORT_8_8_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, <br/>
+ * GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
+ * <br/>
+ * GL_FIXED, GL_INT <br/>
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/>
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/>
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
+ * <br/>
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
+ * <br/>
+ * GL_FLOAT, GL_DOUBLE <br/>
+ *
+ * @return required size of one pixel in bytes
+ * @throws GLException if format or type alignment is not handled. Please contact the maintainer if this is our bug.
+ */
+ public static final int bytesPerPixel(final int format, final int type) throws GLException {
+ int compSize = 0;
+
+ int compCount = componentCount(format);
+
switch (type) /* 30 */ {
case GL2.GL_BITMAP:
- if (GL2.GL_COLOR_INDEX == format || GL2GL3.GL_STENCIL_INDEX == format) {
- return (depth * (height * ((width+7)/8)));
+ if (GL2.GL_COLOR_INDEX == format || GL2ES2.GL_STENCIL_INDEX == format) {
+ compSize = 1;
+ } else {
+ throw new GLException("BITMAP type only supported for format COLOR_INDEX and STENCIL_INDEX, not 0x"+Integer.toHexString(format));
}
+ break;
case GL.GL_BYTE:
- case GL.GL_UNSIGNED_BYTE:
- esize = 1;
+ case GL.GL_UNSIGNED_BYTE:
+ compSize = 1;
break;
case GL.GL_SHORT:
case GL.GL_UNSIGNED_SHORT:
case GL.GL_HALF_FLOAT:
case GLES2.GL_HALF_FLOAT_OES:
- esize = 2;
+ compSize = 2;
break;
case GL.GL_FIXED:
case GL2ES2.GL_INT:
case GL.GL_UNSIGNED_INT:
case GL.GL_FLOAT:
- esize = 4;
+ compSize = 4;
break;
case GL2GL3.GL_DOUBLE:
- esize = 8;
+ compSize = 8;
break;
-
+
case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
case GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV:
- esize = 1;
- elements = 1;
+ compSize = 1;
+ compCount = 1;
break;
case GL.GL_UNSIGNED_SHORT_5_6_5:
case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
- case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL.GL_UNSIGNED_SHORT_4_4_4_4:
case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
- case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL.GL_UNSIGNED_SHORT_5_5_5_1:
case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
- esize = 2;
- elements = 1;
+ case GL2.GL_UNSIGNED_SHORT_8_8_APPLE:
+ case GL2.GL_UNSIGNED_SHORT_8_8_REV_APPLE:
+ compSize = 2;
+ compCount = 1;
break;
case GL2.GL_HILO16_NV:
case GL2.GL_SIGNED_HILO16_NV:
- esize = 2;
- elements = 2;
- break;
+ compSize = 2;
+ compCount = 2;
+ break;
case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:
- case GL2GL3.GL_UNSIGNED_INT_10_10_10_2:
- case GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV:
- case GL2GL3.GL_UNSIGNED_INT_24_8:
- case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV:
- case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV:
- esize = 4;
- elements = 1;
- break;
- case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
- esize = 8;
- elements = 1;
- break;
-
+ case GL2ES2.GL_UNSIGNED_INT_10_10_10_2:
+ case GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL.GL_UNSIGNED_INT_24_8:
+ case GL.GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL2ES3.GL_UNSIGNED_INT_5_9_9_9_REV:
+ compSize = 4;
+ compCount = 1;
+ break;
+ case GL2ES3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ compSize = 8;
+ compCount = 1;
+ break;
+
default:
throw new GLException("type 0x"+Integer.toHexString(type)+"/"+"format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug.");
}
-
- return sizeof(gl, tmp, elements * esize, width, height, depth, pack);
+ return compCount * compSize;
+ }
+
+ /**
+ * Returns the number of components required for the given OpenGL format.
+ *
+ * <p>This method is security critical, hence it throws an exception (fail-fast)
+ * in case either the format, type or alignment is unhandled. In case we forgot to handle
+ * proper values, please contact the maintainer.</p>
+ *
+ * @param format must be one of (27) <br/>
+ * GL_COLOR_INDEX GL_STENCIL_INDEX <br/>
+ * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/>
+ * GL_RED GL_RED_INTEGER <br/>
+ * GL_GREEN GL_GREEN_INTEGER <br/>
+ * GL_BLUE GL_BLUE_INTEGER <br/>
+ * GL_ALPHA GL_LUMINANCE (12) <br/>
+ * <br/>
+ * GL_LUMINANCE_ALPHA GL_RG <br/>
+ * GL_RG_INTEGER GL_HILO_NV <br/>
+ * GL_SIGNED_HILO_NV (5) <br/>
+ * <br/>
+ * GL_YCBCR_422_APPLE <br/>
+ * <br/>
+ * GL_RGB GL_RGB_INTEGER <br/>
+ * GL_BGR GL_BGR_INTEGER (4)<br/>
+ * <br/>
+ * GL_RGBA GL_RGBA_INTEGER <br/>
+ * GL_BGRA GL_BGRA_INTEGER <br/>
+ * GL_ABGR_EXT (5)<br/>
+ *
+ * @return number of components required for the given OpenGL format
+ * @throws GLException if format is not handled. Please contact the maintainer if this is our bug.
+ */
+ public static final int componentCount(final int format) throws GLException {
+ final int compCount;
+
+ switch (format) /* 26 */ {
+ case GL2.GL_COLOR_INDEX:
+ case GL2ES2.GL_STENCIL_INDEX:
+ case GL2ES2.GL_DEPTH_COMPONENT:
+ case GL.GL_DEPTH_STENCIL:
+ case GL2ES2.GL_RED:
+ case GL2ES3.GL_RED_INTEGER:
+ case GL2ES3.GL_GREEN:
+ case GL2GL3.GL_GREEN_INTEGER:
+ case GL2ES3.GL_BLUE:
+ case GL2GL3.GL_BLUE_INTEGER:
+ case GL.GL_ALPHA:
+ case GL.GL_LUMINANCE:
+ compCount = 1;
+ break;
+ case GL.GL_LUMINANCE_ALPHA:
+ case GL2ES2.GL_RG:
+ case GL2ES3.GL_RG_INTEGER:
+ case GL2.GL_HILO_NV:
+ case GL2.GL_SIGNED_HILO_NV:
+ compCount = 2;
+ break;
+ case GL.GL_RGB:
+ case GL2ES3.GL_RGB_INTEGER:
+ case GL2GL3.GL_BGR:
+ case GL2GL3.GL_BGR_INTEGER:
+ compCount = 3;
+ break;
+ case GL2.GL_YCBCR_422_APPLE:
+ compCount = 3;
+ break;
+ case GL.GL_RGBA:
+ case GL2ES3.GL_RGBA_INTEGER:
+ case GL.GL_BGRA:
+ case GL2GL3.GL_BGRA_INTEGER:
+ case GL2.GL_ABGR_EXT:
+ compCount = 4;
+ break;
+ /* FIXME ??
+ case GL.GL_HILO_NV:
+ elements = 2;
+ break; */
+ default:
+ throw new GLException("format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug.");
+ }
+ return compCount;
}
-
+
public static final int getNextPowerOf2(int number) {
if (((number-1) & number) == 0) {
//ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0
@@ -574,14 +752,14 @@ public class GLBuffers extends Buffers {
power++;
}
return (1<<power);
- }
-
+ }
+
//----------------------------------------------------------------------
// Conversion routines
//
- public final static float[] getFloatArray(double[] source) {
+ public final static float[] getFloatArray(final double[] source) {
int i = source.length;
- float[] dest = new float[i--];
+ final float[] dest = new float[i--];
while (i >= 0) {
dest[i] = (float) source[i];
i--;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
new file mode 100644
index 000000000..634cfeaed
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
@@ -0,0 +1,346 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLBase;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLRunnable;
+import javax.media.opengl.Threading;
+
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.opengl.GLEventListenerState;
+
+import jogamp.opengl.Debug;
+
+/**
+ * Providing utility functions dealing w/ {@link GLDrawable}s, {@link GLAutoDrawable} and their {@link GLEventListener}.
+ */
+public class GLDrawableUtil {
+ protected static final boolean DEBUG = Debug.debug("GLDrawable");
+
+ public static final boolean isAnimatorStartedOnOtherThread(final GLAnimatorControl animatorCtrl) {
+ return ( null != animatorCtrl ) ? animatorCtrl.isStarted() && animatorCtrl.getThread() != Thread.currentThread() : false ;
+ }
+
+ public static final boolean isAnimatorStarted(final GLAnimatorControl animatorCtrl) {
+ return ( null != animatorCtrl ) ? animatorCtrl.isStarted() : false ;
+ }
+
+ public static final boolean isAnimatorAnimatingOnOtherThread(final GLAnimatorControl animatorCtrl) {
+ return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() && animatorCtrl.getThread() != Thread.currentThread() : false ;
+ }
+
+ public static final boolean isAnimatorAnimating(final GLAnimatorControl animatorCtrl) {
+ return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() : false ;
+ }
+
+ /**
+ * {@link GLRunnable} to issue {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int)},
+ * returning <code>true</code> on {@link GLRunnable#run(GLAutoDrawable)}.
+ */
+ public static class ReshapeGLEventListener implements GLRunnable {
+ private final GLEventListener listener;
+ private final boolean displayAfterReshape;
+ /**
+ *
+ * @param listener
+ * @param displayAfterReshape <code>true</code> to issue {@link GLEventListener#display(GLAutoDrawable)}
+ * after {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int)},
+ * otherwise false.
+ */
+ public ReshapeGLEventListener(final GLEventListener listener, final boolean displayAfterReshape) {
+ this.listener = listener;
+ this.displayAfterReshape = displayAfterReshape;
+ }
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ listener.reshape(drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ if( displayAfterReshape ) {
+ listener.display(drawable);
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Moves the designated {@link GLEventListener} from {@link GLAutoDrawable} <code>src</code> to <code>dest</code>.
+ * If <code>preserveInitState</code> is <code>true</code>, it's initialized state is preserved
+ * and {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape(..)} issued w/ the next {@link GLAutoDrawable#display()} call.
+ * <p>
+ * Note that it is only legal to pass <code>preserveInitState := true</code>,
+ * if the {@link GLContext} of both <code>src</code> and <code>dest</code> are shared, or has itself moved from <code>src</code> to <code>dest</code>.
+ * </p>
+ * <p>
+ * Also note that the caller is encouraged to pause an attached {@link GLAnimatorControl}.
+ * </p>
+ * @param src
+ * @param dest
+ * @param listener
+ * @param preserveInitState
+ */
+ public static final void moveGLEventListener(final GLAutoDrawable src, final GLAutoDrawable dest, final GLEventListener listener, final boolean preserveInitState) {
+ final boolean initialized = src.getGLEventListenerInitState(listener);
+ if( preserveInitState ) {
+ src.removeGLEventListener(listener);
+ dest.addGLEventListener(listener);
+ if( initialized ) {
+ dest.setGLEventListenerInitState(listener, true);
+ dest.invoke(false, new ReshapeGLEventListener(listener, true));
+ }
+ } else {
+ src.disposeGLEventListener(listener, true);
+ dest.addGLEventListener(listener);
+ }
+ }
+
+ /**
+ * Moves all {@link GLEventListener} from {@link GLAutoDrawable} <code>src</code> to <code>dest</code>.
+ * If <code>preserveInitState</code> is <code>true</code>, it's initialized state is preserved
+ * and {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape(..)} issued w/ the next {@link GLAutoDrawable#display()} call.
+ * <p>
+ * Note that it is only legal to pass <code>preserveInitState := true</code>,
+ * if the {@link GLContext} of both <code>src</code> and <code>dest</code> are shared, or has itself moved from <code>src</code> to <code>dest</code>.
+ * </p>
+ * <p>
+ * Also note that the caller is encouraged to pause an attached {@link GLAnimatorControl}.
+ * </p>
+ * @param src
+ * @param dest
+ * @param listener
+ * @param preserveInitState
+ */
+ public static final void moveAllGLEventListener(final GLAutoDrawable src, final GLAutoDrawable dest, final boolean preserveInitState) {
+ for(int count = src.getGLEventListenerCount(); 0<count; count--) {
+ final GLEventListener listener = src.getGLEventListener(0);
+ moveGLEventListener(src, dest, listener, preserveInitState);
+ }
+ }
+
+ /**
+ * Return a heuristic value whether switching the {@link GLContext} is safe between {@link GLAutoDrawable}s,
+ * i.e. via {@link #swapGLContext(GLAutoDrawable, GLAutoDrawable)} or {@link #swapGLContextAndAllGLEventListener(GLAutoDrawable, GLAutoDrawable)}.
+ * <p>
+ * Method currently returns <code>false</code> if:
+ * <ul>
+ * <li>Switching between on- and offscreen and one of the following is <code>true</code>:
+ * <ul>
+ * <li>{@link GLCapabilitiesImmutable#getSampleBuffers() MSAA is <i>used</i>} [1] in <code>chosenCapsA</code> or <code>chosenCapsB</code></li>
+ * <li>{@link GLCapabilitiesImmutable#getStereo() Stereo is <i>used</i>} in <code>chosenCapsA</code> or <code>chosenCapsB</code></li>
+ * <li>{@link GLCapabilitiesImmutable#getAccumAlphaBits() Accumulator Buffer is <i>requested</i>} [2] in <code>requestedCaps</code></li>
+ * </ul></li>
+ * </ul>
+ * Otherwise method returns <code>true</code>
+ * </p>
+ * <pre>
+ * [1] See Bug 830: swapGLContextAndAllGLEventListener and onscreen MSAA w/ NV/GLX
+ * On NVidia GPUs w/ it's proprietary driver context swapping does not work if MSAA is involved
+ * and when swapping on- to offscreen.
+ * </pre>
+ * <pre>
+ * [2] On AMD GPUs w/ it's proprietary driver, requesting an accumulator buffer leads to receive an accumulator buffer configuration,
+ * for which context swapping does not work when swapping on- to offscreen and vice-versa, i.e. cannot make context current.
+ * With AMD and Mesa drivers we only receive an accumulator buffer if requested,
+ * where on NVidia drivers all configurations contain the accumulator buffer.
+ * On both drivers, NVidia and Mesa, context swapping with accumulator buffer works.
+ * </pre>
+ * @param requestedCaps requested {@link GLCapabilitiesImmutable} which are intended for usage by both {@link GLAutoDrawable}s A and B
+ * @param chosenCapsA chosen {@link GLCapabilitiesImmutable} of {@link GLAutoDrawable} A, which {@link GLContext} is intended to be swapped
+ * @param chosenCapsB chosen {@link GLCapabilitiesImmutable} of {@link GLAutoDrawable} B, which {@link GLContext} is intended to be swapped
+ * @see #swapGLContext(GLAutoDrawable, GLAutoDrawable)
+ * @see #swapGLContextAndAllGLEventListener(GLAutoDrawable, GLAutoDrawable)
+ */
+ public static boolean isSwapGLContextSafe(final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesImmutable chosenCapsA, final GLCapabilitiesImmutable chosenCapsB) {
+ final boolean usingAccumulatorBuffer = requestedCaps.getAccumAlphaBits() > 0 ||
+ requestedCaps.getAccumRedBits() > 0 ||
+ requestedCaps.getAccumGreenBits() > 0 ||
+ requestedCaps.getAccumBlueBits() > 0;
+ if( ( chosenCapsA.isOnscreen() && !chosenCapsB.isOnscreen() || !chosenCapsA.isOnscreen() && chosenCapsB.isOnscreen() ) && // switching between on- and offscreen
+ (
+ ( chosenCapsA.getSampleBuffers() || chosenCapsB.getSampleBuffers() ) || // MSAA involved
+ ( chosenCapsA.getStereo() || chosenCapsB.getStereo() ) || // Stereo involved
+ usingAccumulatorBuffer // Using accumulator buffer
+ )
+ )
+ {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ /**
+ * Swaps the {@link GLContext} and all {@link GLEventListener} between {@link GLAutoDrawable} <code>a</code> and <code>b</code>,
+ * while preserving it's initialized state, resets the GL-Viewport and issuing {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape(..)}.
+ * <p>
+ * The {@link GLAutoDrawable} to {@link GLAnimatorControl} association
+ * is also swapped.
+ * </p>
+ * <p>
+ * If an {@link GLAnimatorControl} is being attached to {@link GLAutoDrawable} <code>a</code> or <code>b</code>
+ * and the current thread is different than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+ * </p>
+ * <p>
+ * During operation, both {@link GLAutoDrawable auto-drawable's}
+ * {@link GLAutoDrawable#getUpstreamLock() upstream-locks} and {@link GLAutoDrawable#getNativeSurface() surfaces} are locked,
+ * hence atomicity of operation is guaranteed,
+ * see <a href="../../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.
+ * </p>
+ * <p>
+ * Because of above mentioned locking, if this method is not performed
+ * on {@link GLAutoDrawable#isThreadGLCapable() a OpenGL capable thread} of <i>both</i>
+ * {@link GLAutoDrawable}s, it must be invoked on such an OpenGL capable thread,
+ * e.g. via {@link Threading#invokeOnOpenGLThread(boolean, Runnable)}.
+ * </p>
+ * @throws GLException if the {@link AbstractGraphicsDevice} are incompatible w/ each other.
+ * @see #isSwapGLContextSafe(GLCapabilitiesImmutable, GLCapabilitiesImmutable, GLCapabilitiesImmutable)
+ */
+ public static final void swapGLContextAndAllGLEventListener(final GLAutoDrawable a, final GLAutoDrawable b) {
+ final GLEventListenerState gllsA = GLEventListenerState.moveFrom(a, true);
+ final GLEventListenerState gllsB = GLEventListenerState.moveFrom(b, true);
+ final Runnable gllsAUnlockOp = gllsA.getUnlockSurfaceOp();
+ final Runnable gllsBUnlockOp = gllsB.getUnlockSurfaceOp();
+ try {
+ gllsA.moveTo(b, gllsBUnlockOp);
+ gllsB.moveTo(a, gllsAUnlockOp);
+ } finally {
+ // guarantee unlock in case of an exception
+ gllsBUnlockOp.run();
+ gllsAUnlockOp.run();
+ }
+ }
+
+ /**
+ * Swaps the {@link GLContext} of given {@link GLAutoDrawable}
+ * and {@link GLAutoDrawable#disposeGLEventListener(GLEventListener, boolean) disposes}
+ * each {@link GLEventListener} w/o removing it.
+ * <p>
+ * The GL-Viewport is reset and {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape(..)} issued implicit.
+ * </p>
+ * <p>
+ * If an {@link GLAnimatorControl} is being attached to GLAutoDrawable src or dest and the current thread is different
+ * than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+ * </p>
+ * <p>
+ * During operation, both {@link GLAutoDrawable auto-drawable's}
+ * {@link GLAutoDrawable#getUpstreamLock() upstream-locks} and {@link GLAutoDrawable#getNativeSurface() surfaces} are locked,
+ * hence atomicity of operation is guaranteed,
+ * see <a href="../../../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.
+ * </p>
+ * <p>
+ * Because of above mentioned locking, if this method is not performed
+ * on {@link GLAutoDrawable#isThreadGLCapable() a OpenGL capable thread} of <i>both</i>
+ * {@link GLAutoDrawable}s, it must be invoked on such an OpenGL capable thread,
+ * e.g. via {@link Threading#invokeOnOpenGLThread(boolean, Runnable)}.
+ * </p>
+ * @param a
+ * @param b
+ * @see #isSwapGLContextSafe(GLCapabilitiesImmutable, GLCapabilitiesImmutable, GLCapabilitiesImmutable)
+ */
+ public static final void swapGLContext(final GLAutoDrawable a, final GLAutoDrawable b) {
+ final GLAnimatorControl aAnim = a.getAnimator();
+ final GLAnimatorControl bAnim = b.getAnimator();
+ final boolean aIsPaused = isAnimatorAnimatingOnOtherThread(aAnim) && aAnim.pause();
+ final boolean bIsPaused = isAnimatorAnimatingOnOtherThread(bAnim) && bAnim.pause();
+
+ final RecursiveLock aUpstreamLock = a.getUpstreamLock();
+ final RecursiveLock bUpstreamLock = b.getUpstreamLock();
+ aUpstreamLock.lock();
+ bUpstreamLock.lock();
+ try {
+ final NativeSurface aSurface = a.getNativeSurface();
+ final boolean aSurfaceLocked = NativeSurface.LOCK_SURFACE_NOT_READY < aSurface.lockSurface();
+ if( a.isRealized() && !aSurfaceLocked ) {
+ throw new GLException("Could not lock realized a surface "+a);
+ }
+ final NativeSurface bSurface = b.getNativeSurface();
+ final boolean bSurfaceLocked = NativeSurface.LOCK_SURFACE_NOT_READY < bSurface.lockSurface();
+ if( b.isRealized() && !bSurfaceLocked ) {
+ throw new GLException("Could not lock realized b surface "+b);
+ }
+ try {
+ for(int i = a.getGLEventListenerCount() - 1; 0 <= i; i--) {
+ a.disposeGLEventListener(a.getGLEventListener(i), false);
+ }
+ for(int i = b.getGLEventListenerCount() - 1; 0 <= i; i--) {
+ b.disposeGLEventListener(b.getGLEventListener(i), false);
+ }
+ b.setContext( a.setContext( b.getContext(), false ), false );
+
+ } finally {
+ if( bSurfaceLocked ) {
+ bSurface.unlockSurface();
+ }
+ if( aSurfaceLocked ) {
+ aSurface.unlockSurface();
+ }
+ }
+ } finally {
+ bUpstreamLock.unlock();
+ aUpstreamLock.unlock();
+ }
+ a.invoke(true, setViewport);
+ b.invoke(true, setViewport);
+ if(aIsPaused) { aAnim.resume(); }
+ if(bIsPaused) { bAnim.resume(); }
+ }
+
+ private static final GLRunnable setViewport = new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ drawable.getGL().glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ return false; // issue re-display w/ new viewport!
+ }
+ };
+
+ /**
+ * Determines whether the chosen {@link GLCapabilitiesImmutable}
+ * requires a {@link GLDrawable#swapBuffers() swap-buffers}
+ * before reading pixels.
+ * <p>
+ * Usually one uses the {@link GLBase#getDefaultReadBuffer() default-read-buffer}
+ * in which case {@link GLDrawable#swapBuffers() swap-buffers} shall happen <b>after</b> calling reading pixels, the default.
+ * </p>
+ * <p>
+ * However, <i>multisampling</i> offscreen {@link javax.media.opengl.GLFBODrawable}s
+ * utilize {@link GLDrawable#swapBuffers() swap-buffers} to <i>downsample</i>
+ * the multisamples into the readable sampling sink.
+ * In this case, we require {@link GLDrawable#swapBuffers() swap-buffers} <b>before</b> reading pixels.
+ * </p>
+ * @return chosenCaps.isFBO() && chosenCaps.getSampleBuffers()
+ */
+ public static final boolean swapBuffersBeforeRead(final GLCapabilitiesImmutable chosenCaps) {
+ return chosenCaps.isFBO() && chosenCaps.getSampleBuffers();
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
new file mode 100644
index 000000000..a09321d75
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
@@ -0,0 +1,487 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.texture.TextureData;
+
+/**
+ * OpenGL pixel data buffer, allowing user to provide buffers via their {@link GLPixelBufferProvider} implementation.
+ * <p>
+ * {@link GLPixelBufferProvider} produces a {@link GLPixelBuffer}.
+ * </p>
+ * <p>
+ * You may use {@link #defaultProviderNoRowStride}.
+ * </p>
+ */
+public class GLPixelBuffer {
+
+ /** Allows user to interface with another toolkit to define {@link GLPixelAttributes} and memory buffer to produce {@link TextureData}. */
+ public static interface GLPixelBufferProvider {
+ /** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. */
+ boolean getAllowRowStride();
+
+ /** Called first to determine {@link GLPixelAttributes}. */
+ GLPixelAttributes getAttributes(GL gl, int componentCount);
+
+ /**
+ * Allocates a new {@link GLPixelBuffer} object.
+ * <p>
+ * Being called to gather the initial {@link GLPixelBuffer},
+ * or a new replacement {@link GLPixelBuffer} if {@link GLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+ * </p>
+ * <p>
+ * The minimum required {@link Buffer#remaining() remaining} byte size equals to <code>minByteSize</code>, if &gt; 0,
+ * otherwise utilize {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean)}
+ * to calculate it.
+ * </p>
+ *
+ * @param gl the corresponding current GL context object
+ * @param pixelAttributes the desired {@link GLPixelAttributes}
+ * @param width in pixels
+ * @param height in pixels
+ * @param depth in pixels
+ * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
+ * @param minByteSize if &gt; 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore.
+ */
+ GLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize);
+ }
+
+ /** Single {@link GLPixelBuffer} provider. */
+ public static interface SingletonGLPixelBufferProvider extends GLPixelBufferProvider {
+ /** Return the last {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated} {@link GLPixelBuffer} w/ {@link GLPixelAttributes#componentCount}. */
+ GLPixelBuffer getSingleBuffer(GLPixelAttributes pixelAttributes);
+ /**
+ * Initializes the single {@link GLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+ * @return the newly initialized single {@link GLPixelBuffer}, or null if already allocated.
+ */
+ GLPixelBuffer initSingleton(int componentCount, int width, int height, int depth, boolean pack);
+ }
+
+ public static class DefaultGLPixelBufferProvider implements GLPixelBufferProvider {
+ private final boolean allowRowStride;
+
+ /**
+ * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not.
+ * See {@link #getAllowRowStride()} and {@link GLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+ */
+ public DefaultGLPixelBufferProvider(final boolean allowRowStride) {
+ this.allowRowStride = allowRowStride;
+ }
+
+ @Override
+ public boolean getAllowRowStride() { return allowRowStride; }
+
+ @Override
+ public GLPixelAttributes getAttributes(final GL gl, final int componentCount) {
+ final GLContext ctx = gl.getContext();
+ final int dFormat, dType;
+
+ if( 1 == componentCount ) {
+ if( gl.isGL3ES3() ) {
+ // RED is supported on ES3 and >= GL3 [core]; ALPHA is deprecated on core
+ dFormat = GL2ES2.GL_RED;
+ } else {
+ // ALPHA is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
+ dFormat = GL.GL_ALPHA;
+ }
+ dType = GL.GL_UNSIGNED_BYTE;
+ } else if( 3 == componentCount ) {
+ dFormat = GL.GL_RGB;
+ dType = GL.GL_UNSIGNED_BYTE;
+ } else if( 4 == componentCount ) {
+ final int _dFormat = ctx.getDefaultPixelDataFormat();
+ final int dComps = GLBuffers.componentCount(_dFormat);
+ if( dComps == componentCount ) {
+ dFormat = _dFormat;
+ dType = ctx.getDefaultPixelDataType();
+ } else {
+ dFormat = GL.GL_RGBA;
+ dType = GL.GL_UNSIGNED_BYTE;
+ }
+ } else {
+ throw new GLException("Unsupported componentCount "+componentCount+", contact maintainer to enhance");
+ }
+ return new GLPixelAttributes(componentCount, dFormat, dType);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns an NIO {@link ByteBuffer}.
+ * </p>
+ */
+ @Override
+ public GLPixelBuffer allocate(final GL gl, final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
+ if( minByteSize > 0 ) {
+ return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(minByteSize), getAllowRowStride());
+ } else {
+ final int[] tmp = { 0 };
+ final int byteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.bytesPerPixel, width, height, depth, pack);
+ return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(byteSize), getAllowRowStride());
+ }
+ }
+ }
+
+ /**
+ * Default {@link GLPixelBufferProvider} with {@link GLPixelBufferProvider#getAllowRowStride()} == <code>false</code>,
+ * utilizing best match for {@link GLPixelAttributes}
+ * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}.
+ */
+ public static final GLPixelBufferProvider defaultProviderNoRowStride = new DefaultGLPixelBufferProvider(false);
+
+ /**
+ * Default {@link GLPixelBufferProvider} with {@link GLPixelBufferProvider#getAllowRowStride()} == <code>true</code>,
+ * utilizing best match for {@link GLPixelAttributes}
+ * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}.
+ */
+ public static final GLPixelBufferProvider defaultProviderWithRowStride = new DefaultGLPixelBufferProvider(true);
+
+ /** Pixel attributes. */
+ public static class GLPixelAttributes {
+ /** Undefined instance of {@link GLPixelAttributes}, having componentCount:=0, format:=0 and type:= 0. */
+ public static final GLPixelAttributes UNDEF = new GLPixelAttributes(0, 0, 0, false);
+
+ /** Pixel <i>source</i> component count, i.e. number of meaningful components. */
+ public final int componentCount;
+ /** The OpenGL pixel data format */
+ public final int format;
+ /** The OpenGL pixel data type */
+ public final int type;
+ /** The OpenGL pixel size in bytes */
+ public final int bytesPerPixel;
+
+ /**
+ * Deriving {@link #componentCount} via GL <code>dataFormat</code>, i.e. {@link GLBuffers#componentCount(int)} if &gt; 0.
+ * @param dataFormat GL data format
+ * @param dataType GL data type
+ */
+ public GLPixelAttributes(final int dataFormat, final int dataType) {
+ this(0 < dataFormat ? GLBuffers.componentCount(dataFormat) : 0, dataFormat, dataType);
+ }
+ /**
+ * Using user specified source {@link #componentCount}.
+ * @param componentCount source component count
+ * @param dataFormat GL data format
+ * @param dataType GL data type
+ */
+ public GLPixelAttributes(final int componentCount, final int dataFormat, final int dataType) {
+ this(componentCount, dataFormat, dataType, true);
+ }
+
+ /**
+ * Returns the matching {@link GLPixelAttributes} for the given {@link PixelFormat} and {@link GLProfile} if exists,
+ * otherwise returns <code>null</code>.
+ */
+ public static final GLPixelAttributes convert(final PixelFormat pixFmt, final GLProfile glp) {
+ int df = 0; // format
+ int dt = GL.GL_UNSIGNED_BYTE; // data type
+ switch(pixFmt) {
+ case LUMINANCE:
+ if( glp.isGL3ES3() ) {
+ // RED is supported on ES3 and >= GL3 [core]; ALPHA/LUMINANCE is deprecated on core
+ df = GL2ES2.GL_RED;
+ } else {
+ // ALPHA/LUMINANCE is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
+ df = GL.GL_LUMINANCE;
+ }
+ break;
+ case BGR888:
+ if( glp.isGL2GL3() ) {
+ df = GL2GL3.GL_BGR;
+ }
+ break;
+ case RGB888:
+ df = GL.GL_RGB;
+ break;
+ case RGBA8888:
+ df = GL.GL_RGBA;
+ break;
+ case ABGR8888:
+ if( glp.isGL2GL3() ) {
+ df = GL.GL_RGBA; dt = GL2GL3.GL_UNSIGNED_INT_8_8_8_8;
+ }
+ break;
+ case BGRA8888:
+ df = GL.GL_BGRA;
+ break;
+ case ARGB8888:
+ if( glp.isGL2GL3() ) {
+ df = GL.GL_BGRA; dt = GL2GL3.GL_UNSIGNED_INT_8_8_8_8;
+ }
+ break;
+ default:
+ break;
+ }
+ if( 0 != df ) {
+ return new GLPixelAttributes(pixFmt.componentCount, df, dt, true);
+ }
+ return null;
+ }
+ private GLPixelAttributes(final int componentCount, final int dataFormat, final int dataType, final boolean checkArgs) {
+ this.componentCount = componentCount;
+ this.format = dataFormat;
+ this.type = dataType;
+ this.bytesPerPixel = ( 0 < dataFormat && 0 < dataType ) ? GLBuffers.bytesPerPixel(dataFormat, dataType) : 0;
+ if( checkArgs ) {
+ if( 0 == componentCount || 0 == format || 0 == type ) {
+ throw new GLException("Zero components, format and/or type: "+this);
+ }
+ if( 0 == bytesPerPixel ) {
+ throw new GLException("Zero bytesPerPixel: "+this);
+ }
+ }
+ }
+
+ /**
+ * Returns the matching {@link PixelFormat} of this {@link GLPixelAttributes} if exists,
+ * otherwise returns <code>null</code>.
+ */
+ public final PixelFormat getPixelFormat() {
+ final PixelFormat pixFmt;
+ // FIXME: Take 'type' into consideration and complete mapping!
+ switch(format) {
+ case GL.GL_ALPHA:
+ case GL.GL_LUMINANCE:
+ case GL2ES2.GL_RED:
+ pixFmt = PixelFormat.LUMINANCE;
+ break;
+ case GL.GL_RGB:
+ pixFmt = PixelFormat.RGB888;
+ break;
+ case GL.GL_RGBA:
+ pixFmt = PixelFormat.RGBA8888;
+ break;
+ case GL2GL3.GL_BGR:
+ pixFmt = PixelFormat.BGR888;
+ break;
+ case GL.GL_BGRA:
+ pixFmt = PixelFormat.BGRA8888;
+ break;
+ default:
+ switch( bytesPerPixel ) {
+ case 1:
+ pixFmt = PixelFormat.LUMINANCE;
+ break;
+ case 3:
+ pixFmt = PixelFormat.RGB888;
+ break;
+ case 4:
+ pixFmt = PixelFormat.RGBA8888;
+ break;
+ default:
+ pixFmt = null;
+ break;
+ }
+ break;
+ }
+ return pixFmt;
+ }
+
+ @Override
+ public String toString() {
+ return "PixelAttributes[comp "+componentCount+", fmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+", bytesPerPixel "+bytesPerPixel+"]";
+ }
+ }
+
+ /** The {@link GLPixelAttributes}. */
+ public final GLPixelAttributes pixelAttributes;
+ /**
+ * Width in pixels, representing {@link #buffer}'s {@link #byteSize}.
+ * <p>
+ * May not represent actual image width as user may re-use buffer for different dimensions, see {@link #requiresNewBuffer(GL, int, int, int)}.
+ * </p>
+ */
+ public final int width;
+ /**
+ * Height in pixels, representing {@link #buffer}'s {@link #byteSize}.
+ * <p>
+ * May not represent actual image height as user may re-use buffer for different dimensions, see {@link #requiresNewBuffer(GL, int, int, int)}.
+ * </p>
+ */
+ public final int height;
+ /** Depth in pixels. */
+ public final int depth;
+ /** Data packing direction. If <code>true</code> for read mode GPU -> CPU, <code>false</code> for write mode CPU -> GPU. */
+ public final boolean pack;
+ /** Byte size of the buffer. Actually the number of {@link Buffer#remaining()} bytes when passed in ctor. */
+ public final int byteSize;
+ /**
+ * Buffer holding the pixel data. If {@link #rewind()}, it holds <code>byteSize</code> {@link Buffer#remaining()} bytes.
+ * <p>
+ * By default the {@link Buffer} is a {@link ByteBuffer}, due to {@link DefProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int)}.
+ * However, other {@link GLPixelBufferProvider} may utilize different {@link Buffer} types.
+ * </p>
+ */
+ public final Buffer buffer;
+ /** Buffer element size in bytes. */
+ public final int bufferElemSize;
+
+ /** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. See {@link #requiresNewBuffer(GL, int, int, int)}. */
+ public final boolean allowRowStride;
+
+ private boolean disposed = false;
+
+ public StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append(pixelAttributes).append(", dim ").append(width).append("x").append(height).append("x").append(depth).append(", pack ").append(pack)
+ .append(", disposed ").append(disposed).append(", valid ").append(isValid())
+ .append(", buffer[bytes ").append(byteSize).append(", elemSize ").append(bufferElemSize).append(", ").append(buffer).append("]");
+ return sb;
+ }
+ @Override
+ public String toString() {
+ return "GLPixelBuffer["+toString(null).toString()+"]";
+ }
+
+ /**
+ * @param pixelAttributes the desired {@link GLPixelAttributes}
+ * @param width in pixels
+ * @param height in pixels
+ * @param depth in pixels
+ * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
+ * @param buffer the backing array
+ * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link #requiresNewBuffer(GL, int, int, int)}.
+ */
+ public GLPixelBuffer(final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final Buffer buffer, final boolean allowRowStride) {
+ this.pixelAttributes = pixelAttributes;
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
+ this.pack = pack;
+ this.buffer = buffer;
+ this.byteSize = Buffers.remainingBytes(buffer);
+ this.bufferElemSize = Buffers.sizeOfBufferElem(buffer);
+ this.allowRowStride = allowRowStride;
+ }
+
+ /** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. */
+ public final boolean getAllowRowStride() { return allowRowStride; }
+
+ /** Is not {@link #dispose() disposed} and has {@link #byteSize} &gt; 0. */
+ public boolean isValid() {
+ return !disposed && 0 < byteSize;
+ }
+
+ /** See {@link Buffer#rewind()}. */
+ public Buffer rewind() {
+ return buffer.rewind();
+ }
+
+ /** Returns the byte position of the {@link #buffer}. */
+ public int position() {
+ return buffer.position() * bufferElemSize;
+ }
+
+ /** Sets the byte position of the {@link #buffer}. */
+ public Buffer position(final int bytePos) {
+ return buffer.position( bytePos / bufferElemSize );
+ }
+
+ /** Returns the byte capacity of the {@link #buffer}. */
+ public int capacity() {
+ return buffer.capacity() * bufferElemSize;
+ }
+
+ /** Returns the byte limit of the {@link #buffer}. */
+ public int limit() {
+ return buffer.limit() * bufferElemSize;
+ }
+
+ /** See {@link Buffer#flip()}. */
+ public Buffer flip() {
+ return buffer.flip();
+ }
+
+ /** See {@link Buffer#clear()}. */
+ public Buffer clear() {
+ return buffer.clear();
+ }
+
+ /**
+ * Returns true, if {@link #isValid() invalid} or implementation requires a new buffer based on the new size
+ * due to pixel alignment or byte size, otherwise false.
+ * <p>
+ * It is assumed that <code>pixelAttributes</code>, <code>depth</code> and <code>pack</code> stays the same!
+ * </p>
+ * <p>
+ * The minimum required byte size equals to <code>minByteSize</code>, if &gt; 0,
+ * otherwise {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean) GLBuffers.sizeof(..)}
+ * is being used to calculate it. This value is referred to <i>newByteSize</i>.
+ * </p>
+ * <p>
+ * If <code>{@link #allowRowStride} = false</code>,
+ * method returns <code>true</code> if the <i>newByteSize</i> &gt; <i>currentByteSize</i>
+ * or the <code>newWidth</code> != <code>currentWidth</code>.
+ * </p>
+ * <p>
+ * If <code>{@link #allowRowStride} = true</code>, see {@link GLPixelBufferProvider#getAllowRowStride()},
+ * method returns <code>true</code> only if the <i>newByteSize</i> &gt; <i>currentByteSize</i>.
+ * Assuming user utilizes the row-stride when dealing w/ the data, i.e. {@link GL2ES3#GL_PACK_ROW_LENGTH}.
+ * </p>
+ * @param gl the corresponding current GL context object
+ * @param newWidth new width in pixels
+ * @param newHeight new height in pixels
+ * @param newByteSize if &gt; 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore.
+ * @see GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int)
+ */
+ public boolean requiresNewBuffer(final GL gl, final int newWidth, final int newHeight, int newByteSize) {
+ if( !isValid() ) {
+ return true;
+ }
+ if( 0 >= newByteSize ) {
+ final int[] tmp = { 0 };
+ newByteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.bytesPerPixel, newWidth, newHeight, 1, true);
+ }
+ if( allowRowStride ) {
+ return byteSize < newByteSize;
+ }
+ return byteSize < newByteSize || width != newWidth;
+ }
+
+ /** Dispose resources. See {@link #isValid()}. */
+ public void dispose() {
+ disposed = true;
+ buffer.clear();
+ }
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
index 05eb67269..290033e99 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
@@ -31,106 +31,290 @@ package com.jogamp.opengl.util;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
/**
- * Utility to safely set and restore the pack and unpack pixel storage mode,
+ * Utility to safely set and restore the PACK and UNPACK pixel storage mode,
* regardless of the GLProfile.
+ * <p>
+ * PACK for GPU to CPU transfers, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) ReadPixels}, etc.
+ * </p>
+ * <p>
+ * UNPACK for CPU o GPU transfers, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long) TexImage2D}, etc
+ * </p>
*/
public class GLPixelStorageModes {
- private int[] savedGL2GL3Modes = new int[8];
- private int[] savedAlignment = new int[2];
- private boolean saved = false;
+ private final int[] cachePack = new int[8];
+ private final int[] cacheUnpack = new int[8];
+ private boolean savedPack = false;
+ private boolean savedUnpack = false;
+
+ /** Create instance w/o {@link #saveAll(GL)} */
+ public GLPixelStorageModes() {}
+
+ /** Create instance w/ {@link #saveAll(GL)} */
+ public GLPixelStorageModes(final GL gl) { saveAll(gl); }
/**
- * Sets the {@link GL2ES2.GL_PACK_ALIGNMENT}. Saves the pixel storage modes if not saved yet.
+ * Sets the {@link GL#GL_PACK_ALIGNMENT}.
+ * <p>
+ * Saves the PACK pixel storage modes and {@link #resetPack(GL) resets} them if not saved yet, see {@link #savePack(GL)}.
+ * </p>
*/
- public final void setPackAlignment(GL gl, int packAlignment) {
- if(!saved) { save(gl); }
- gl.glPixelStorei(GL2ES2.GL_PACK_ALIGNMENT, packAlignment);
+ public final void setPackAlignment(final GL gl, final int packAlignment) {
+ savePack(gl);
+ gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, packAlignment);
}
/**
- * Sets the {@link GL2ES2.GL_UNPACK_ALIGNMENT}. Saves the pixel storage modes if not saved yet.
+ * Sets the {@link GL#GL_UNPACK_ALIGNMENT}.
+ * <p>
+ * Saves the UNPACK pixel storage modes and {@link #resetUnpack(GL) resets} them if not saved yet, see {@link #saveUnpack(GL)}.
+ * </p>
*/
- public final void setUnpackAlignment(GL gl, int unpackAlignment) {
- if(!saved) { save(gl); }
- gl.glPixelStorei(GL2ES2.GL_UNPACK_ALIGNMENT, unpackAlignment);
+ public final void setUnpackAlignment(final GL gl, final int unpackAlignment) {
+ saveUnpack(gl);
+ gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, unpackAlignment);
}
-
+
/**
- * Sets the {@link GL2ES2.GL_PACK_ALIGNMENT} and {@link GL2ES2.GL_UNPACK_ALIGNMENT}.
- * Saves the pixel storage modes if not saved yet.
+ * Sets the {@link GL#GL_PACK_ALIGNMENT} and {@link GL#GL_UNPACK_ALIGNMENT}.
+ * <p>
+ * Saves the PACK and UNPACK pixel storage modes and resets them if not saved yet, see {@link #saveAll(GL)}.
+ * </p>
*/
- public final void setAlignment(GL gl, int packAlignment, int unpackAlignment) {
+ public final void setAlignment(final GL gl, final int packAlignment, final int unpackAlignment) {
setPackAlignment(gl, packAlignment);
setUnpackAlignment(gl, unpackAlignment);
}
-
- private final void save(GL gl) {
- if(gl.isGL2GL3()) {
- if(gl.isGL2()) {
- gl.getGL2().glPushClientAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT);
- } else {
- gl.glGetIntegerv(GL2ES2.GL_PACK_ALIGNMENT, savedAlignment, 0);
- gl.glGetIntegerv(GL2ES2.GL_UNPACK_ALIGNMENT, savedAlignment, 1);
- gl.glGetIntegerv(GL2GL3.GL_PACK_ROW_LENGTH, savedGL2GL3Modes, 0);
- gl.glGetIntegerv(GL2GL3.GL_PACK_SKIP_ROWS, savedGL2GL3Modes, 1);
- gl.glGetIntegerv(GL2GL3.GL_PACK_SKIP_PIXELS, savedGL2GL3Modes, 2);
- gl.glGetIntegerv(GL2GL3.GL_PACK_SWAP_BYTES, savedGL2GL3Modes, 3);
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_ROW_LENGTH, savedGL2GL3Modes, 4);
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_SKIP_ROWS, savedGL2GL3Modes, 5);
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_SKIP_PIXELS, savedGL2GL3Modes, 6);
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_SWAP_BYTES, savedGL2GL3Modes, 7);
+
+ /**
+ * Sets the {@link GL2ES3#GL_PACK_ROW_LENGTH}.
+ * <p>
+ * Saves the PACK pixel storage modes and {@link #resetPack(GL) resets} them if not saved yet, see {@link #savePack(GL)}.
+ * </p>
+ */
+ public final void setPackRowLength(final GL2ES3 gl, final int packRowLength) {
+ savePack(gl);
+ gl.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, packRowLength);
+ }
+
+ /**
+ * Sets the {@link GL2ES2#GL_UNPACK_ROW_LENGTH}.
+ * <p>
+ * Saves the UNPACK pixel storage modes and {@link #resetUnpack(GL) resets} them if not saved yet, see {@link #saveUnpack(GL)}.
+ * </p>
+ */
+ public final void setUnpackRowLength(final GL2ES3 gl, final int unpackRowLength) {
+ saveUnpack(gl);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, unpackRowLength);
+ }
+
+ /**
+ * Sets the {@link GL2ES3#GL_PACK_ROW_LENGTH} and {@link GL2ES2#GL_UNPACK_ROW_LENGTH} if {@link GL#isGL2ES3()}.
+ * <p>
+ * Saves the PACK and UNPACK pixel storage modes and resets them if not saved yet, see {@link #saveAll(GL)}.
+ * </p>
+ */
+ public final void setRowLength(final GL2ES3 gl, final int packRowLength, final int unpackRowLength) {
+ setPackRowLength(gl, packRowLength);
+ setUnpackRowLength(gl, unpackRowLength);
+ }
+
+ /**
+ * Saves PACK and UNPACK pixel storage modes and {@link #resetAll(GL) resets} them,
+ * i.e. issues {@link #savePack(GL)} and {@link #saveUnpack(GL)}.
+ * <p>
+ * Operation is skipped, if the modes were already saved.
+ * </p>
+ * <p>
+ * Restore via {@link #restore(GL)}
+ * </p>
+ */
+ public final void saveAll(final GL gl) {
+ savePack(gl);
+ saveUnpack(gl);
+ }
+
+ /**
+ * Resets PACK and UNPACK pixel storage modes to their default value,
+ * i.e. issues {@link #resetPack(GL)} and {@link #resetUnpack(GL)}.
+ */
+ public final void resetAll(final GL gl) {
+ resetPack(gl);
+ resetUnpack(gl);
+ }
+
+ /**
+ * Restores PACK and UNPACK pixel storage mode previously saved w/ {@link #saveAll(GL)}
+ * or {@link #savePack(GL)} and {@link #saveUnpack(GL)}.
+ * @throws GLException if neither PACK nor UNPACK modes were saved.
+ */
+ public final void restore(final GL gl) throws GLException {
+ if(!savedPack && !savedUnpack) {
+ throw new GLException("Neither PACK nor UNPACK pixel storage modes were saved");
+ }
+ if( savedPack ) {
+ restorePack(gl);
+ savedPack = false;
+ }
+ if( savedUnpack ) {
+ restoreUnpack(gl);
+ savedUnpack = false;
+ }
+ }
+
+ /**
+ * Resets PACK pixel storage modes to their default value.
+ */
+ public final void resetPack(final GL gl) {
+ // Compared w/ ES2, ES3 and GL3-core spec
+ gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 4); // es2, es3, gl3
+ if( gl.isGL2ES3() ) {
+ gl.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, 0); // es3, gl3
+ gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_ROWS, 0); // es3, gl3
+ gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_PIXELS, 0); // es3, gl3
+ if( gl.isGL2GL3() ) {
+ gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, GL.GL_FALSE); // gl3
+ gl.glPixelStorei(GL2GL3.GL_PACK_LSB_FIRST, GL.GL_FALSE); // gl3
+ if( gl.getContext().getGLVersionNumber().compareTo(GLContext.Version120) >= 0 ) {
+ gl.glPixelStorei(GL2GL3.GL_PACK_IMAGE_HEIGHT, 0); // gl3, GL_VERSION_1_2
+ gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_IMAGES, 0); // gl3, GL_VERSION_1_2
+ }
}
- gl.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, 0);
- gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_ROWS, 0);
- gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_PIXELS, 0);
- gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, 0);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_ROW_LENGTH, 0);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_ROWS, 0);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_PIXELS, 0);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, 0);
+ }
+ }
+ /**
+ * Saves PACK pixel storage modes and {@link #resetPack(GL) resets} them.
+ * <p>
+ * Operation is skipped, if the modes were already saved.
+ * </p>
+ * <p>
+ * Restore via {@link #restore(GL)}
+ * </p>
+ */
+ public final void savePack(final GL gl) {
+ if(savedPack) {
+ return;
+ }
+ if( gl.isGL2() ) {
+ // See GLStateTracker.pushAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT)
+ gl.getGL2().glPushClientAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT);
} else {
- // embedded deals with pack/unpack alignment only
- gl.glGetIntegerv(GL2ES2.GL_PACK_ALIGNMENT, savedAlignment, 0);
- gl.glGetIntegerv(GL2ES2.GL_UNPACK_ALIGNMENT, savedAlignment, 1);
- }
- saved = true;
+ // ES1 or ES2 deals with pack/unpack alignment only
+ gl.glGetIntegerv(GL.GL_PACK_ALIGNMENT, cachePack, 0);
+ if( gl.isGL2ES3() ) {
+ gl.glGetIntegerv(GL2ES3.GL_PACK_ROW_LENGTH, cachePack, 1);
+ gl.glGetIntegerv(GL2ES3.GL_PACK_SKIP_ROWS, cachePack, 2);
+ gl.glGetIntegerv(GL2ES3.GL_PACK_SKIP_PIXELS, cachePack, 3);
+ if( gl.isGL2GL3() ) {
+ gl.glGetIntegerv(GL2GL3.GL_PACK_SWAP_BYTES, cachePack, 4);
+ gl.glGetIntegerv(GL2GL3.GL_PACK_LSB_FIRST, cachePack, 5);
+ gl.glGetIntegerv(GL2GL3.GL_PACK_IMAGE_HEIGHT, cachePack, 6);
+ gl.glGetIntegerv(GL2GL3.GL_PACK_SKIP_IMAGES, cachePack, 7);
+ }
+ }
+ }
+ savedPack = true;
+ resetPack(gl);
+ }
+ private final void restorePack(final GL gl) {
+ if( gl.isGL2() ) {
+ gl.getGL2().glPopClientAttrib();
+ } else {
+ gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, cachePack[0]);
+ if( gl.isGL2ES3() ) {
+ gl.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, cachePack[1]);
+ gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_ROWS, cachePack[2]);
+ gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_PIXELS, cachePack[3]);
+ if( gl.isGL2GL3() ) {
+ gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, cachePack[4]);
+ gl.glPixelStorei(GL2GL3.GL_PACK_LSB_FIRST, cachePack[5]);
+ gl.glPixelStorei(GL2GL3.GL_PACK_IMAGE_HEIGHT, cachePack[6]);
+ gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_IMAGES, cachePack[7]);
+ }
+ }
+ }
}
/**
- * Restores the pixel storage mode.
- * @throws GLException if not saved via one of the set methods.
+ * Resets UNPACK pixel storage modes to their default value.
*/
- public final void restore(GL gl) throws GLException {
- if(!saved) {
- throw new GLException("pixel storage modes not saved");
- }
-
- if(gl.isGL2GL3()) {
- if(gl.isGL2()) {
- gl.getGL2().glPopClientAttrib();
+ public final void resetUnpack(final GL gl) {
+ // Compared w/ ES2, ES3 and GL3-core spec
+ gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 4); // es2, es3, gl3
+ if( gl.isGL2ES3() ) {
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, 0); // es3, gl3
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, 0); // es3, gl3
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, 0); // es3, gl3
+ if( gl.isGL2GL3() ) {
+ if( gl.getContext().getGLVersionNumber().compareTo(GLContext.Version120) >= 0 ) {
+ gl.glPixelStorei(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, 0); // es3, gl3, GL_VERSION_1_2
+ gl.glPixelStorei(GL2ES3.GL_UNPACK_SKIP_IMAGES, 0); // es3, gl3, GL_VERSION_1_2
+ }
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE); // gl3
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_LSB_FIRST, GL.GL_FALSE); // gl3
} else {
- gl.glPixelStorei(GL2ES2.GL_PACK_ALIGNMENT, savedAlignment[0]);
- gl.glPixelStorei(GL2ES2.GL_UNPACK_ALIGNMENT, savedAlignment[1]);
- gl.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, savedGL2GL3Modes[0]);
- gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_ROWS, savedGL2GL3Modes[1]);
- gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_PIXELS, savedGL2GL3Modes[2]);
- gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, savedGL2GL3Modes[3]);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_ROW_LENGTH, savedGL2GL3Modes[4]);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_ROWS, savedGL2GL3Modes[5]);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_PIXELS, savedGL2GL3Modes[6]);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, savedGL2GL3Modes[7]);
+ gl.glPixelStorei(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, 0); // es3, gl3, GL_VERSION_1_2
+ gl.glPixelStorei(GL2ES3.GL_UNPACK_SKIP_IMAGES, 0); // es3, gl3, GL_VERSION_1_2
+ }
+ }
+ }
+ /**
+ * Saves UNPACK pixel storage modes and {@link #resetUnpack(GL) resets} them.
+ * <p>
+ * Operation is skipped, if the modes were already saved.
+ * </p>
+ * <p>
+ * Restore via {@link #restore(GL)}
+ * </p>
+ */
+ public final void saveUnpack(final GL gl) {
+ if(savedUnpack) {
+ return;
+ }
+ if( gl.isGL2() ) {
+ // See GLStateTracker.pushAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT)
+ gl.getGL2().glPushClientAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT);
+ } else {
+ // ES1 or ES2 deals with pack/unpack alignment only
+ gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, cacheUnpack, 0);
+ if( gl.isGL2ES3() ) {
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_ROW_LENGTH, cacheUnpack, 1);
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_ROWS, cacheUnpack, 2);
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_PIXELS, cacheUnpack, 3);
+ gl.glGetIntegerv(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, cacheUnpack, 4);
+ gl.glGetIntegerv(GL2ES3.GL_UNPACK_SKIP_IMAGES, cacheUnpack, 5);
+ if( gl.isGL2GL3() ) {
+ gl.glGetIntegerv(GL2GL3.GL_UNPACK_SWAP_BYTES, cacheUnpack, 6);
+ gl.glGetIntegerv(GL2GL3.GL_UNPACK_LSB_FIRST, cacheUnpack, 7);
+ }
}
+ }
+ savedUnpack = true;
+ resetUnpack(gl);
+ }
+ private final void restoreUnpack(final GL gl) {
+ if( gl.isGL2() ) {
+ gl.getGL2().glPopClientAttrib();
} else {
- // embedded deals with pack/unpack alignment only
- gl.glPixelStorei(GL2ES2.GL_PACK_ALIGNMENT, savedAlignment[0]);
- gl.glPixelStorei(GL2ES2.GL_UNPACK_ALIGNMENT, savedAlignment[1]);
- }
- saved = false;
- }
+ gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, cacheUnpack[0]);
+ if( gl.isGL2ES3() ) {
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, cacheUnpack[1]);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, cacheUnpack[2]);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, cacheUnpack[3]);
+ gl.glPixelStorei(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, cacheUnpack[4]);
+ gl.glPixelStorei(GL2ES3.GL_UNPACK_SKIP_IMAGES, cacheUnpack[5]);
+ if( gl.isGL2GL3() ) {
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, cacheUnpack[6]);
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_LSB_FIRST, cacheUnpack[7]);
+ }
+ }
+ }
+ }
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index 34cc0eb07..e84a1d874 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,24 +20,29 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.util;
-import com.jogamp.common.nio.Buffers;
+package com.jogamp.opengl.util;
import java.io.File;
import java.io.IOException;
-import java.nio.*;
-import javax.media.opengl.*;
-import com.jogamp.opengl.GLExtensions;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
+
+import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.GLPixelBuffer;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelBufferProvider;
import com.jogamp.opengl.util.texture.TextureIO;
/**
@@ -45,38 +50,46 @@ import com.jogamp.opengl.util.texture.TextureIO;
* <p>May be used directly to write the TextureData to file (screenshot).</p>
*/
public class GLReadBufferUtil {
- protected final int components, alignment;
+ protected final GLPixelBufferProvider pixelBufferProvider;
+ protected final int componentCount, alignment;
protected final Texture readTexture;
protected final GLPixelStorageModes psm;
-
- protected int readPixelSizeLast = 0;
- protected ByteBuffer readPixelBuffer = null;
+
+ protected GLPixelBuffer readPixelBuffer = null;
protected TextureData readTextureData = null;
/**
- * @param alpha true for RGBA readPixels, otherwise RGB readPixels. Disclaimer: Alpha maybe forced on ES platforms!
+ * @param alpha true for RGBA readPixels, otherwise RGB readPixels. Disclaimer: Alpha maybe forced on ES platforms!
* @param write2Texture true if readPixel's TextureData shall be written to a 2d Texture
*/
- public GLReadBufferUtil(boolean alpha, boolean write2Texture) {
- components = alpha ? 4 : 3 ;
- alignment = alpha ? 4 : 1 ;
- readTexture = write2Texture ? new Texture(GL.GL_TEXTURE_2D) : null ;
- psm = new GLPixelStorageModes();
+ public GLReadBufferUtil(final boolean alpha, final boolean write2Texture) {
+ this(GLPixelBuffer.defaultProviderNoRowStride, alpha, write2Texture);
}
-
+
+ public GLReadBufferUtil(final GLPixelBufferProvider pixelBufferProvider, final boolean alpha, final boolean write2Texture) {
+ this.pixelBufferProvider = pixelBufferProvider;
+ this.componentCount = alpha ? 4 : 3 ;
+ this.alignment = alpha ? 4 : 1 ;
+ this.readTexture = write2Texture ? new Texture(GL.GL_TEXTURE_2D) : null ;
+ this.psm = new GLPixelStorageModes();
+ }
+
+ /** Returns the {@link GLPixelBufferProvider} used by this instance. */
+ public GLPixelBufferProvider getPixelBufferProvider() { return pixelBufferProvider; }
+
public boolean isValid() {
- return null!=readTextureData && null!=readPixelBuffer ;
+ return null!=readTextureData && null!=readPixelBuffer && readPixelBuffer.isValid();
}
-
- public boolean hasAlpha() { return 4 == components ? true : false ; }
-
+
+ public boolean hasAlpha() { return 4 == componentCount ? true : false ; }
+
public GLPixelStorageModes getGLPixelStorageModes() { return psm; }
-
+
/**
- * @return the raw pixel ByteBuffer, filled by {@link #readPixels(GLAutoDrawable, boolean)}
+ * Returns the {@link GLPixelBuffer}, created and filled by {@link #readPixels(GLAutoDrawable, boolean)}.
*/
- public ByteBuffer getPixelBuffer() { return readPixelBuffer; }
-
+ public GLPixelBuffer getPixelBuffer() { return readPixelBuffer; }
+
/**
* rewind the raw pixel ByteBuffer
*/
@@ -86,7 +99,7 @@ public class GLReadBufferUtil {
* @return the resulting TextureData, filled by {@link #readPixels(GLAutoDrawable, boolean)}
*/
public TextureData getTextureData() { return readTextureData; }
-
+
/**
* @return the Texture object filled by {@link #readPixels(GLAutoDrawable, boolean)},
* if this instance writes to a 2d Texture, otherwise null.
@@ -97,108 +110,144 @@ public class GLReadBufferUtil {
/**
* Write the TextureData filled by {@link #readPixels(GLAutoDrawable, boolean)} to file
*/
- public void write(File dest) {
+ public void write(final File dest) {
try {
TextureIO.write(readTextureData, dest);
rewindPixelBuffer();
- } catch (IOException ex) {
+ } catch (final IOException ex) {
throw new RuntimeException("can not write to file: " + dest.getAbsolutePath(), ex);
}
}
/**
- * Read the drawable's pixels to TextureData and Texture, if requested at construction
- *
+ * Read the drawable's pixels to TextureData and Texture, if requested at construction.
+ *
* @param gl the current GL context object. It's read drawable is being used as the pixel source.
- * @param drawable the drawable to read from
- * @param flip weather to flip the data vertically or not
- *
+ * @param mustFlipVertically indicates whether to flip the data vertically or not.
+ * The context's drawable {@link GLDrawable#isGLOriented()} state
+ * is taken into account.
+ * Vertical flipping is propagated to TextureData
+ * and handled in a efficient manner there (TextureCoordinates and TextureIO writer).
+ *
* @see #GLReadBufferUtil(boolean, boolean)
*/
- public boolean readPixels(GL gl, boolean flip) {
+ public boolean readPixels(final GL gl, final boolean mustFlipVertically) {
+ return readPixels(gl, 0, 0, 0, 0, mustFlipVertically);
+ }
+
+ /**
+ * Read the drawable's pixels to TextureData and Texture, if requested at construction.
+ *
+ * @param gl the current GL context object. It's read drawable is being used as the pixel source.
+ * @param inX readPixel x offset
+ * @param inY readPixel y offset
+ * @param inWidth optional readPixel width value, used if [1 .. drawable.width], otherwise using drawable.width
+ * @param inHeight optional readPixel height, used if [1 .. drawable.height], otherwise using drawable.height
+ * @param mustFlipVertically indicates whether to flip the data vertically or not.
+ * The context's drawable {@link GLDrawable#isGLOriented()} state
+ * is taken into account.
+ * Vertical flipping is propagated to TextureData
+ * and handled in a efficient manner there (TextureCoordinates and TextureIO writer).
+ * @see #GLReadBufferUtil(boolean, boolean)
+ */
+ public boolean readPixels(final GL gl, final int inX, final int inY, final int inWidth, final int inHeight, final boolean mustFlipVertically) {
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ final int width, height;
+ if( 0 >= inWidth || drawable.getSurfaceWidth() < inWidth ) {
+ width = drawable.getSurfaceWidth();
+ } else {
+ width = inWidth;
+ }
+ if( 0 >= inHeight || drawable.getSurfaceHeight() < inHeight ) {
+ height = drawable.getSurfaceHeight();
+ } else {
+ height= inHeight;
+ }
+ return readPixelsImpl(drawable, gl, inX, inY, width, height, mustFlipVertically);
+ }
+
+ protected boolean readPixelsImpl(final GLDrawable drawable, final GL gl,
+ final int inX, final int inY, final int width, final int height,
+ final boolean mustFlipVertically) {
final int glerr0 = gl.glGetError();
if(GL.GL_NO_ERROR != glerr0) {
System.err.println("Info: GLReadBufferUtil.readPixels: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
}
- final GLDrawable drawable = gl.getContext().getGLReadDrawable();
- final int textureInternalFormat, textureDataFormat, textureDataType;
- final int[] glImplColorReadVals = new int[] { 0, 0 };
-
- if(gl.isGL2GL3() && 3 == components) {
- textureInternalFormat=GL.GL_RGB;
- textureDataFormat=GL.GL_RGB;
- textureDataType = GL.GL_UNSIGNED_BYTE;
- } else if(gl.isGLES2Compatible() || gl.isExtensionAvailable(GLExtensions.OES_read_format)) {
- gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
- gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);
- textureInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
- textureDataFormat = glImplColorReadVals[0];
- textureDataType = glImplColorReadVals[1];
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
+ final int internalFormat;
+ if(gl.isGL2GL3() && 3 == componentCount) {
+ internalFormat = GL.GL_RGB;
+ } else {
+ internalFormat = (4 == componentCount) ? GL.GL_RGBA : GL.GL_RGB;
+ }
+
+ final boolean flipVertically;
+ if( drawable.isGLOriented() ) {
+ flipVertically = mustFlipVertically;
} else {
- // RGBA read is safe for all GL profiles
- textureInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
- textureDataFormat=GL.GL_RGBA;
- textureDataType = GL.GL_UNSIGNED_BYTE;
+ flipVertically = !mustFlipVertically;
}
-
+
final int tmp[] = new int[1];
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, textureDataFormat, textureDataType,
- drawable.getWidth(), drawable.getHeight(), 1, true);
-
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, width, height, 1, true);
+
boolean newData = false;
- if(readPixelSize>readPixelSizeLast) {
- readPixelBuffer = Buffers.newDirectByteBuffer(readPixelSize);
- readPixelSizeLast = readPixelSize ;
+ if( null == readPixelBuffer || readPixelBuffer.requiresNewBuffer(gl, width, height, readPixelSize) ) {
+ readPixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, width, height, 1, true, readPixelSize);
+ Buffers.rangeCheckBytes(readPixelBuffer.buffer, readPixelSize);
try {
readTextureData = new TextureData(
gl.getGLProfile(),
- textureInternalFormat,
- drawable.getWidth(), drawable.getHeight(),
- 0,
- textureDataFormat,
- textureDataType,
- false, false,
- flip,
- readPixelBuffer,
+ internalFormat,
+ width, height,
+ 0,
+ pixelAttribs,
+ false, false,
+ flipVertically,
+ readPixelBuffer.buffer,
null /* Flusher */);
newData = true;
- } catch (Exception e) {
+ } catch (final Exception e) {
readTextureData = null;
readPixelBuffer = null;
- readPixelSizeLast = 0;
throw new RuntimeException("can not fetch offscreen texture", e);
}
} else {
- readTextureData.setInternalFormat(textureInternalFormat);
- readTextureData.setWidth(drawable.getWidth());
- readTextureData.setHeight(drawable.getHeight());
- readTextureData.setPixelFormat(textureDataFormat);
- readTextureData.setPixelType(textureDataType);
+ readTextureData.setInternalFormat(internalFormat);
+ readTextureData.setWidth(width);
+ readTextureData.setHeight(height);
+ readTextureData.setPixelAttributes(pixelAttribs);
}
- boolean res = null!=readPixelBuffer;
+ boolean res = null!=readPixelBuffer && readPixelBuffer.isValid();
if(res) {
- psm.setAlignment(gl, alignment, alignment);
+ psm.setPackAlignment(gl, alignment);
+ if(gl.isGL2ES3()) {
+ final GL2ES3 gl2es3 = gl.getGL2ES3();
+ psm.setPackRowLength(gl2es3, width);
+ gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
+ }
readPixelBuffer.clear();
- gl.glReadPixels(0, 0, drawable.getWidth(), drawable.getHeight(), textureDataFormat, textureDataType, readPixelBuffer);
- readPixelBuffer.position(readPixelSize);
+ try {
+ gl.glReadPixels(inX, inY, width, height, pixelAttribs.format, pixelAttribs.type, readPixelBuffer.buffer);
+ } catch(final GLException gle) { res = false; gle.printStackTrace(); }
+ readPixelBuffer.position( readPixelSize );
readPixelBuffer.flip();
final int glerr1 = gl.glGetError();
if(GL.GL_NO_ERROR != glerr1) {
System.err.println("GLReadBufferUtil.readPixels: readPixels error 0x"+Integer.toHexString(glerr1)+
- " "+drawable.getWidth()+"x"+drawable.getHeight()+
- ", fmt 0x"+Integer.toHexString(textureDataFormat)+", type 0x"+Integer.toHexString(textureDataType)+
- ", impl-fmt 0x"+Integer.toHexString(glImplColorReadVals[0])+", impl-type 0x"+Integer.toHexString(glImplColorReadVals[1])+
+ " "+width+"x"+height+
+ ", "+pixelAttribs+
", "+readPixelBuffer+", sz "+readPixelSize);
- res = false;
+ res = false;
}
if(res && null != readTexture) {
if(newData) {
readTexture.updateImage(gl, readTextureData);
} else {
- readTexture.updateSubImage(gl, readTextureData, 0,
+ readTexture.updateSubImage(gl, readTextureData, 0,
0, 0, // src offset
0, 0, // dst offset
- drawable.getWidth(), drawable.getHeight());
+ width, height);
}
readPixelBuffer.rewind();
}
@@ -207,16 +256,15 @@ public class GLReadBufferUtil {
return res;
}
- public void dispose(GL gl) {
+ public void dispose(final GL gl) {
if(null != readTexture) {
readTexture.destroy(gl);
readTextureData = null;
}
if(null != readPixelBuffer) {
- readPixelBuffer.clear();
+ readPixelBuffer.dispose();
readPixelBuffer = null;
}
- readPixelSizeLast = 0;
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/Gamma.java b/src/jogl/classes/com/jogamp/opengl/util/Gamma.java
index c649d1c6a..bab85e531 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/Gamma.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/Gamma.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,80 +28,90 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package com.jogamp.opengl.util;
-import javax.media.opengl.*;
-import jogamp.opengl.*;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
-/** Provides control over the primary display's gamma, brightness and
- contrast controls via the hardware gamma ramp tables. Not
- supported on all platforms or graphics hardware. <P>
-
- Thanks to the LWJGL project for illustrating how to access gamma
- control on the various platforms.
-*/
+import com.jogamp.common.util.locks.RecursiveLock;
+/**
+ * Provides convenient wrapper for {@link GLDrawableFactory} control over
+ * individual display's gamma, brightness and contrast values
+ * via the hardware gamma ramp tables.
+ * <p>
+ * Not supported on all platforms or graphics hardware.
+ * </p>
+ * <p>
+ * Thanks to the LWJGL project for illustrating how to access gamma
+ * control on the various platforms.
+ * </p>
+ */
public class Gamma {
private Gamma() {}
/**
- * Sets the gamma, brightness, and contrast of the current main
- * display. This functionality is not available on all platforms and
- * graphics hardware. Returns true if the settings were successfully
- * changed, false if not. This method may return false for some
- * values of the incoming arguments even on hardware which does
- * support the underlying functionality. <P>
- *
- * If this method returns true, the display settings will
- * automatically be reset to their original values upon JVM exit
- * (assuming the JVM does not crash); if the user wishes to change
- * the display settings back to normal ahead of time, use {@link
- * #resetDisplayGamma resetDisplayGamma}(). It is recommended to
- * call {@link #resetDisplayGamma resetDisplayGamma} before calling
- * e.g. <code>System.exit()</code> from the application rather than
- * rely on the shutdown hook functionality due to inevitable race
- * conditions and unspecified behavior during JVM teardown. <P>
- *
- * This method may be called multiple times during the application's
- * execution, but calling {@link #resetDisplayGamma
- * resetDisplayGamma} will only reset the settings to the values
- * before the first call to this method. <P>
- *
- * @param gamma The gamma value, typically > 1.0 (default values
- * vary, but typically roughly 1.0)
- * @param brightness The brightness value between -1.0 and 1.0,
- * inclusive (default values vary, but typically 0)
- * @param contrast The contrast, greater than 0.0 (default values
- * vary, but typically 1)
- * @return true if gamma settings were successfully changed, false
- * if not
- * @throws IllegalArgumentException if any of the parameters were
- * out-of-bounds
+ * Convenient wrapper for {@link GLDrawableFactory#setDisplayGamma(javax.media.nativewindow.NativeSurface, float, float, float)}.
+ * <p>
+ * Use {@link #setDisplayGamma(GLAutoDrawable, float, float, float)} in case of using an {#link GLAutoDrawable}.
+ * </p>
+ */
+ public static boolean setDisplayGamma(final GLDrawable drawable, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException {
+ return GLDrawableFactory.getFactory(drawable.getGLProfile()).setDisplayGamma(drawable.getNativeSurface(), gamma, brightness, contrast);
+ }
+
+ /**
+ * Convenient wrapper for {@link GLDrawableFactory#setDisplayGamma(javax.media.nativewindow.NativeSurface, float, float, float)}
+ * locking {@link GLAutoDrawable#getUpstreamLock()} to ensure proper atomic operation.
+ */
+ public static boolean setDisplayGamma(final GLAutoDrawable drawable, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException {
+ final RecursiveLock lock = drawable.getUpstreamLock();
+ lock.lock();
+ try {
+ return GLDrawableFactory.getFactory(drawable.getGLProfile()).setDisplayGamma(drawable.getNativeSurface(), gamma, brightness, contrast);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Convenient wrapper for {@link GLDrawableFactory#resetDisplayGamma(javax.media.nativewindow.NativeSurface)}.
+ * <p>
+ * Use {@link #resetDisplayGamma(GLAutoDrawable)} in case of using an {#link GLAutoDrawable}.
+ * </p>
+ */
+ public static void resetDisplayGamma(final GLDrawable drawable) {
+ GLDrawableFactory.getFactory(drawable.getGLProfile()).resetDisplayGamma(drawable.getNativeSurface());
+ }
+
+ /**
+ * Convenient wrapper for {@link GLDrawableFactory#resetDisplayGamma(javax.media.nativewindow.NativeSurface)}
+ * locking {@link GLAutoDrawable#getUpstreamLock()} to ensure proper atomic operation.
*/
- public static boolean setDisplayGamma(GL gl, float gamma, float brightness, float contrast) throws IllegalArgumentException {
- return GLDrawableFactoryImpl.getFactoryImpl(gl.getContext().getGLDrawable().getGLProfile()).setDisplayGamma(gamma, brightness, contrast);
+ public static void resetDisplayGamma(final GLAutoDrawable drawable) {
+ final RecursiveLock lock = drawable.getUpstreamLock();
+ lock.lock();
+ try {
+ GLDrawableFactory.getFactory(drawable.getGLProfile()).resetDisplayGamma(drawable.getNativeSurface());
+ } finally {
+ lock.unlock();
+ }
}
/**
- * Resets the gamma, brightness and contrast values for the primary
- * display to their original values before {@link #setDisplayGamma
- * setDisplayGamma} was called the first time. {@link
- * #setDisplayGamma setDisplayGamma} must be called before calling
- * this method or an unspecified exception will be thrown. While it
- * is not explicitly required that this method be called before
- * exiting, calling it is recommended because of the inevitable
- * unspecified behavior during JVM teardown.
+ * Convenient wrapper for {@link GLDrawableFactory#resetAllDisplayGamma()}.
*/
- public static void resetDisplayGamma(GL gl) {
- GLDrawableFactoryImpl.getFactoryImpl(gl.getContext().getGLDrawable().getGLProfile()).resetDisplayGamma();
+ public static void resetAllDisplayGamma(final GLDrawable drawable) {
+ GLDrawableFactory.getFactory(drawable.getGLProfile()).resetAllDisplayGamma();
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
index cf0373044..150e92c2e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
@@ -3,6 +3,7 @@ package com.jogamp.opengl.util;
import java.nio.Buffer;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Iterator;
@@ -13,53 +14,152 @@ import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLException;
import javax.media.opengl.fixedfunc.GLPointerFunc;
-import com.jogamp.common.util.ReflectionUtil;
+import jogamp.opengl.Debug;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.opengl.util.glsl.ShaderState;
+/**
+ * <p>
+ * Immediate mode sink, implementing OpenGL fixed function subset of immediate mode operations, i.e.
+ * <pre>
+ * glBegin();
+ * glVertex3f(1f, 1f, 1f);
+ * glColor4f(1f, 1f, 1f, 1f);
+ * ...
+ * glEnd();
+ * </pre>
+ * Implementation buffers all vertex, colors, normal and texture-coord elements in their respective buffers
+ * to be either rendered directly via {@link #glEnd(GL)} or to be added to an internal display list
+ * via {@link #glEnd(GL, boolean) glEnd(gl, false)} for deferred rendering via {@link #draw(GL, boolean)}.
+ * </p>
+ * <a name="storageDetails"><h5>Buffer storage and it's creation via {@link #createFixed(int, int, int, int, int, int, int, int, int, int) createFixed(..)}
+ * and {@link #createGLSL(int, int, int, int, int, int, int, int, int, int, ShaderState) createGLSL(..)}</h5></a>
+ * <p>
+ * If unsure whether <i>colors</i>, <i>normals</i> and <i>textures</i> will be used,
+ * simply add them with an expected component count.
+ * This implementation will only render buffers which are being filled.<br/>
+ * The buffer growing implementation will only grow the exceeded buffers, unused buffers are not resized.
+ * </p>
+ * <p>
+ * Note: Optional types, i.e. color, must be either not used or used w/ the same element count as vertex, etc.
+ * This is a semantic constraint, same as in the original OpenGL spec.
+ * </p>
+ */
public class ImmModeSink {
+ protected static final boolean DEBUG_BEGIN_END;
+ protected static final boolean DEBUG_DRAW;
+ protected static final boolean DEBUG_BUFFER;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_BEGIN_END = PropertyAccess.isPropertyDefined("jogl.debug.ImmModeSink.BeginEnd", true);
+ DEBUG_DRAW = PropertyAccess.isPropertyDefined("jogl.debug.ImmModeSink.Draw", true);
+ DEBUG_BUFFER = PropertyAccess.isPropertyDefined("jogl.debug.ImmModeSink.Buffer", true);
+ }
- public static final boolean DEBUG_BEGIN_END = false;
- public static final boolean DEBUG_DRAW = false;
-
- // public static final int GL_QUADS = 0x0007; // Needs data manipulation
+ public static final int GL_QUADS = 0x0007; // Needs data manipulation on ES1/ES2
public static final int GL_QUAD_STRIP = 0x0008;
public static final int GL_POLYGON = 0x0009;
/**
* Uses a GL2ES1, or ES2 fixed function emulation immediate mode sink
+ * <p>
+ * See <a href="#storageDetails"> buffer storage details</a>.
+ * </p>
+ *
+ * @param initialElementCount initial buffer size, if subsequent mutable operations are about to exceed the buffer size, the buffer will grow about the initial size.
+ * @param vComps mandatory vertex component count, should be 2, 3 or 4.
+ * @param vDataType mandatory vertex data type, e.g. {@link GL#GL_FLOAT}
+ * @param cComps optional color component count, may be 0, 3 or 4
+ * @param cDataType optional color data type, e.g. {@link GL#GL_FLOAT}
+ * @param nComps optional normal component count, may be 0, 3 or 4
+ * @param nDataType optional normal data type, e.g. {@link GL#GL_FLOAT}
+ * @param tComps optional texture-coordinate component count, may be 0, 2 or 3
+ * @param tDataType optional texture-coordinate data type, e.g. {@link GL#GL_FLOAT}
+ * @param glBufferUsage VBO <code>usage</code> parameter for {@link GL#glBufferData(int, long, Buffer, int)}, e.g. {@link GL#GL_STATIC_DRAW},
+ * set to <code>0</code> for no VBO usage
*/
- public static ImmModeSink createFixed(GL gl, int glBufferUsage, int initialElementCount,
- int vComps, int vDataType,
- int cComps, int cDataType,
- int nComps, int nDataType,
- int tComps, int tDataType) {
- return new ImmModeSink(gl, glBufferUsage, initialElementCount,
- vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, false);
+ public static ImmModeSink createFixed(final int initialElementCount,
+ final int vComps, final int vDataType,
+ final int cComps, final int cDataType,
+ final int nComps, final int nDataType,
+ final int tComps, final int tDataType,
+ final int glBufferUsage) {
+ return new ImmModeSink(initialElementCount,
+ vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType,
+ false, glBufferUsage, null, 0);
}
/**
- * Uses a GL2ES2 GLSL shader immediate mode sink.
- * To issue the draw() command,
- * a ShaderState must be current, using ShaderState.glUseProgram().
+ * Uses a GL2ES2 GLSL shader immediate mode sink, utilizing the given ShaderState.
+ * <p>
+ * See <a href="#storageDetails"> buffer storage details</a>.
+ * </p>
*
+ * @param initialElementCount initial buffer size, if subsequent mutable operations are about to exceed the buffer size, the buffer will grow about the initial size.
+ * @param vComps mandatory vertex component count, should be 2, 3 or 4.
+ * @param vDataType mandatory vertex data type, e.g. {@link GL#GL_FLOAT}
+ * @param cComps optional color component count, may be 0, 3 or 4
+ * @param cDataType optional color data type, e.g. {@link GL#GL_FLOAT}
+ * @param nComps optional normal component count, may be 0, 3 or 4
+ * @param nDataType optional normal data type, e.g. {@link GL#GL_FLOAT}
+ * @param tComps optional texture-coordinate component count, may be 0, 2 or 3
+ * @param tDataType optional texture-coordinate data type, e.g. {@link GL#GL_FLOAT}
+ * @param glBufferUsage VBO <code>usage</code> parameter for {@link GL#glBufferData(int, long, Buffer, int)}, e.g. {@link GL#GL_STATIC_DRAW},
+ * set to <code>0</code> for no VBO usage
+ * @param st ShaderState to locate the vertex attributes
* @see #draw(GL, boolean)
* @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
* @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
*/
- public static ImmModeSink createGLSL(GL gl, int glBufferUsage, int initialElementCount,
- int vComps, int vDataType,
- int cComps, int cDataType,
- int nComps, int nDataType,
- int tComps, int tDataType) {
- return new ImmModeSink(gl, glBufferUsage, initialElementCount,
- vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, true);
+ public static ImmModeSink createGLSL(final int initialElementCount,
+ final int vComps, final int vDataType,
+ final int cComps, final int cDataType,
+ final int nComps, final int nDataType,
+ final int tComps, final int tDataType,
+ final int glBufferUsage, final ShaderState st) {
+ return new ImmModeSink(initialElementCount,
+ vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType,
+ true, glBufferUsage, st, 0);
}
- public static boolean usesVBO() { return vboUsage; }
-
- public static void setVBOUsage(boolean v) { vboUsage = v; }
+ /**
+ * Uses a GL2ES2 GLSL shader immediate mode sink, utilizing the given shader-program.
+ * <p>
+ * See <a href="#storageDetails"> buffer storage details</a>.
+ * </p>
+ *
+ * @param initialElementCount initial buffer size, if subsequent mutable operations are about to exceed the buffer size, the buffer will grow about the initial size.
+ * @param vComps mandatory vertex component count, should be 2, 3 or 4.
+ * @param vDataType mandatory vertex data type, e.g. {@link GL#GL_FLOAT}
+ * @param cComps optional color component count, may be 0, 3 or 4
+ * @param cDataType optional color data type, e.g. {@link GL#GL_FLOAT}
+ * @param nComps optional normal component count, may be 0, 3 or 4
+ * @param nDataType optional normal data type, e.g. {@link GL#GL_FLOAT}
+ * @param tComps optional texture-coordinate component count, may be 0, 2 or 3
+ * @param tDataType optional texture-coordinate data type, e.g. {@link GL#GL_FLOAT}
+ * @param glBufferUsage VBO <code>usage</code> parameter for {@link GL#glBufferData(int, long, Buffer, int)}, e.g. {@link GL#GL_STATIC_DRAW},
+ * set to <code>0</code> for no VBO usage
+ * @param shaderProgram shader-program name to locate the vertex attributes
+ * @see #draw(GL, boolean)
+ * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
+ * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
+ */
+ public static ImmModeSink createGLSL(final int initialElementCount,
+ final int vComps, final int vDataType,
+ final int cComps, final int cDataType,
+ final int nComps, final int nDataType,
+ final int tComps, final int tDataType,
+ final int glBufferUsage, final int shaderProgram) {
+ return new ImmModeSink(initialElementCount,
+ vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType,
+ true, glBufferUsage, null, shaderProgram);
+ }
- public void destroy(GL gl) {
+ public void destroy(final GL gl) {
destroyList(gl);
vboSet.destroy(gl);
@@ -69,15 +169,16 @@ public class ImmModeSink {
reset(null);
}
- public void reset(GL gl) {
+ public void reset(final GL gl) {
destroyList(gl);
vboSet.reset(gl);
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder("ImmModeSink[");
+ final StringBuilder sb = new StringBuilder("ImmModeSink[");
sb.append(",\n\tVBO list: "+vboSetList.size()+" [");
- for(Iterator<VBOSet> i=vboSetList.iterator(); i.hasNext() ; ) {
+ for(final Iterator<VBOSet> i=vboSetList.iterator(); i.hasNext() ; ) {
sb.append("\n\t");
sb.append( i.next() );
}
@@ -91,66 +192,58 @@ public class ImmModeSink {
return sb.toString();
}
- public void draw(GL gl, boolean disableBufferAfterDraw) {
+ public void draw(final GL gl, final boolean disableBufferAfterDraw) {
if(DEBUG_DRAW) {
- Exception e = new Exception("Info: ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this);
- e.printStackTrace();
+ System.err.println("ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this);
}
int n=0;
- for(Iterator<VBOSet> i=vboSetList.iterator(); i.hasNext() ; n++) {
- i.next().draw(gl, null, disableBufferAfterDraw, n);
+ for(int i=0; i<vboSetList.size(); i++, n++) {
+ vboSetList.get(i).draw(gl, null, disableBufferAfterDraw, n);
}
}
- public void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw) {
+ public void draw(final GL gl, final Buffer indices, final boolean disableBufferAfterDraw) {
if(DEBUG_DRAW) {
- Exception e = new Exception("Info: ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this);
- e.printStackTrace();
+ System.err.println("ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this);
}
int n=0;
- for(Iterator<VBOSet> i=vboSetList.iterator(); i.hasNext() ; n++) {
- i.next().draw(gl, indices, disableBufferAfterDraw, n);
+ for(int i=0; i<vboSetList.size(); i++, n++) {
+ vboSetList.get(i).draw(gl, indices, disableBufferAfterDraw, n);
}
}
public void glBegin(int mode) {
- if(DEBUG_BEGIN_END) {
- Exception e = new Exception("Info: ImmModeSink.glBegin("+vboSet.mode+"):\n\t"+this);
- e.printStackTrace();
- }
vboSet.modeOrig = mode;
switch(mode) {
- // Needs data manipulation ..
- //case GL_QUADS:
- // mode=GL.GL_LINES;
- // break;
case GL_QUAD_STRIP:
mode=GL.GL_TRIANGLE_STRIP;
break;
case GL_POLYGON:
- mode=GL.GL_LINES;
+ mode=GL.GL_TRIANGLE_FAN;
break;
}
vboSet.mode = mode;
+ if(DEBUG_BEGIN_END) {
+ System.err.println("ImmModeSink.glBegin("+vboSet.modeOrig+" -> "+vboSet.mode+")");
+ }
vboSet.checkSeal(false);
}
- public final void glEnd(GL gl) {
+ public final void glEnd(final GL gl) {
glEnd(gl, null, true);
}
- public void glEnd(GL gl, boolean immediateDraw) {
+ public void glEnd(final GL gl, final boolean immediateDraw) {
glEnd(gl, null, immediateDraw);
}
- public final void glEnd(GL gl, Buffer indices) {
+ public final void glEnd(final GL gl, final Buffer indices) {
glEnd(gl, indices, true);
}
- private void glEnd(GL gl, Buffer indices, boolean immediateDraw) {
+ private void glEnd(final GL gl, final Buffer indices, final boolean immediateDraw) {
if(DEBUG_BEGIN_END) {
- Exception e = new Exception("Info: ImmModeSink START glEnd(immediate: "+immediateDraw+"):\n\t"+this);
- e.printStackTrace();
+ System.err.println("ImmModeSink START glEnd(immediate: "+immediateDraw+")");
}
if(immediateDraw) {
vboSet.seal(gl, true);
@@ -160,151 +253,206 @@ public class ImmModeSink {
vboSet.seal(gl, true);
vboSet.enableBuffer(gl, false);
vboSetList.add(vboSet);
- vboSet = vboSet.regenerate();
+ vboSet = vboSet.regenerate(gl);
+ }
+ if(DEBUG_BEGIN_END) {
+ System.err.println("ImmModeSink END glEnd(immediate: "+immediateDraw+")");
}
}
- public void glVertexv(Buffer v) {
+ public void glVertexv(final Buffer v) {
vboSet.glVertexv(v);
}
- public void glNormalv(Buffer v) {
+ public void glNormalv(final Buffer v) {
vboSet.glNormalv(v);
}
- public void glColorv(Buffer v) {
+ public void glColorv(final Buffer v) {
vboSet.glColorv(v);
}
- public void glTexCoordv(Buffer v) {
+ public void glTexCoordv(final Buffer v) {
vboSet.glTexCoordv(v);
}
- public final void glVertex2f(float x, float y) {
+ public final void glVertex2f(final float x, final float y) {
vboSet.glVertex2f(x,y);
}
- public final void glVertex3f(float x, float y, float z) {
+ public final void glVertex3f(final float x, final float y, final float z) {
vboSet.glVertex3f(x,y,z);
}
- public final void glNormal3f(float x, float y, float z) {
+ public final void glNormal3f(final float x, final float y, final float z) {
vboSet.glNormal3f(x,y,z);
}
- public final void glColor3f(float x, float y, float z) {
+ public final void glColor3f(final float x, final float y, final float z) {
vboSet.glColor3f(x,y,z);
}
- public final void glColor4f(float x, float y, float z, float a) {
+ public final void glColor4f(final float x, final float y, final float z, final float a) {
vboSet.glColor4f(x,y,z, a);
}
- public final void glTexCoord2f(float x, float y) {
+ public final void glTexCoord2f(final float x, final float y) {
vboSet.glTexCoord2f(x,y);
}
- public final void glTexCoord3f(float x, float y, float z) {
+ public final void glTexCoord3f(final float x, final float y, final float z) {
vboSet.glTexCoord3f(x,y,z);
}
- public final void glVertex2s(short x, short y) {
+ public final void glVertex2s(final short x, final short y) {
vboSet.glVertex2s(x,y);
}
- public final void glVertex3s(short x, short y, short z) {
+ public final void glVertex3s(final short x, final short y, final short z) {
vboSet.glVertex3s(x,y,z);
}
- public final void glNormal3s(short x, short y, short z) {
+ public final void glNormal3s(final short x, final short y, final short z) {
vboSet.glNormal3s(x,y,z);
}
- public final void glColor3s(short x, short y, short z) {
+ public final void glColor3s(final short x, final short y, final short z) {
vboSet.glColor3s(x,y,z);
}
- public final void glColor4s(short x, short y, short z, short a) {
+ public final void glColor4s(final short x, final short y, final short z, final short a) {
vboSet.glColor4s(x,y,z,a);
}
- public final void glTexCoord2s(short x, short y) {
+ public final void glTexCoord2s(final short x, final short y) {
vboSet.glTexCoord2s(x,y);
}
- public final void glTexCoord3s(short x, short y, short z) {
+ public final void glTexCoord3s(final short x, final short y, final short z) {
vboSet.glTexCoord3s(x,y,z);
}
- public final void glVertex2b(byte x, byte y) {
+ public final void glVertex2b(final byte x, final byte y) {
vboSet.glVertex2b(x,y);
}
- public final void glVertex3b(byte x, byte y, byte z) {
+ public final void glVertex3b(final byte x, final byte y, final byte z) {
vboSet.glVertex3b(x,y,z);
}
- public final void glNormal3b(byte x, byte y, byte z) {
+ public final void glNormal3b(final byte x, final byte y, final byte z) {
vboSet.glNormal3b(x,y,z);
}
- public final void glColor3b(byte x, byte y, byte z) {
+ public final void glColor3b(final byte x, final byte y, final byte z) {
vboSet.glColor3b(x,y,z);
}
- public final void glColor4b(byte x, byte y, byte z, byte a) {
+ public final void glColor3ub(final byte x, final byte y, final byte z) {
+ vboSet.glColor3ub(x,y,z);
+ }
+
+ public final void glColor4b(final byte x, final byte y, final byte z, final byte a) {
vboSet.glColor4b(x,y,z,a);
}
- public final void glTexCoord2b(byte x, byte y) {
+ public final void glColor4ub(final byte x, final byte y, final byte z, final byte a) {
+ vboSet.glColor4ub(x,y,z,a);
+ }
+
+ public final void glTexCoord2b(final byte x, final byte y) {
vboSet.glTexCoord2b(x,y);
}
- public final void glTexCoord3b(byte x, byte y, byte z) {
+ public final void glTexCoord3b(final byte x, final byte y, final byte z) {
vboSet.glTexCoord3b(x,y,z);
}
- protected ImmModeSink(GL gl, int glBufferUsage, int initialElementCount,
- int vComps, int vDataType,
- int cComps, int cDataType,
- int nComps, int nDataType,
- int tComps, int tDataType, boolean useGLSL) {
- if(useGLSL && !gl.hasGLSL()) {
- throw new GLException("ImmModeSink GLSL usage not supported: "+gl);
- }
- vboSet = new VBOSet(gl, glBufferUsage, initialElementCount,
- vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL);
+ protected ImmModeSink(final int initialElementCount,
+ final int vComps, final int vDataType,
+ final int cComps, final int cDataType,
+ final int nComps, final int nDataType,
+ final int tComps, final int tDataType,
+ final boolean useGLSL, final int glBufferUsage, final ShaderState st, final int shaderProgram) {
+ vboSet = new VBOSet(initialElementCount,
+ vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType,
+ useGLSL, glBufferUsage, st, shaderProgram);
this.vboSetList = new ArrayList<VBOSet>();
}
- private void destroyList(GL gl) {
- for(Iterator<VBOSet> i=vboSetList.iterator(); i.hasNext() ; ) {
- i.next().destroy(gl);
+ public boolean getUseVBO() { return vboSet.getUseVBO(); }
+
+ /**
+ * Returns the additional element count if buffer resize is required.
+ * @see #setResizeElementCount(int)
+ */
+ public int getResizeElementCount() { return vboSet.getResizeElementCount(); }
+
+ /**
+ * Sets the additional element count if buffer resize is required,
+ * defaults to <code>initialElementCount</code> of factory method.
+ * @see #createFixed(int, int, int, int, int, int, int, int, int, int)
+ * @see #createGLSL(int, int, int, int, int, int, int, int, int, int, ShaderState)
+ */
+ public void setResizeElementCount(final int v) { vboSet.setResizeElementCount(v); }
+
+ private void destroyList(final GL gl) {
+ for(int i=0; i<vboSetList.size(); i++) {
+ vboSetList.get(i).destroy(gl);
}
vboSetList.clear();
}
private VBOSet vboSet;
- private ArrayList<VBOSet> vboSetList;
- private static boolean vboUsage = true;
+ private final ArrayList<VBOSet> vboSetList;
protected static class VBOSet {
- protected VBOSet (GL gl, int glBufferUsage, int initialElementCount,
- int vComps, int vDataType,
- int cComps, int cDataType,
- int nComps, int nDataType,
- int tComps, int tDataType, boolean useGLSL) {
- this.gl=gl;
+ protected VBOSet (final int initialElementCount,
+ final int vComps, final int vDataType,
+ final int cComps, final int cDataType,
+ final int nComps, final int nDataType,
+ final int tComps, final int tDataType,
+ final boolean useGLSL, final int glBufferUsage, final ShaderState st, final int shaderProgram) {
+ // final ..
this.glBufferUsage=glBufferUsage;
this.initialElementCount=initialElementCount;
+ this.useVBO = 0 != glBufferUsage;
+ this.useGLSL=useGLSL;
+ this.shaderState = st;
+ this.shaderProgram = shaderProgram;
+
+ if(useGLSL && null == shaderState && 0 == shaderProgram) {
+ throw new IllegalArgumentException("Using GLSL but neither a valid shader-program nor ShaderState has been passed!");
+ }
+ // variable ..
+ this.resizeElementCount=initialElementCount;
this.vDataType=vDataType;
+ this.vDataTypeSigned=GLBuffers.isSignedGLType(vDataType);
this.vComps=vComps;
+ this.vCompsBytes=vComps * GLBuffers.sizeOfGLType(vDataType);
this.cDataType=cDataType;
+ this.cDataTypeSigned=GLBuffers.isSignedGLType(cDataType);
this.cComps=cComps;
+ this.cCompsBytes=cComps * GLBuffers.sizeOfGLType(cDataType);
this.nDataType=nDataType;
+ this.nDataTypeSigned=GLBuffers.isSignedGLType(nDataType);
this.nComps=nComps;
+ this.nCompsBytes=nComps * GLBuffers.sizeOfGLType(nDataType);
this.tDataType=tDataType;
+ this.tDataTypeSigned=GLBuffers.isSignedGLType(tDataType);
this.tComps=tComps;
- this.useGLSL=useGLSL;
+ this.tCompsBytes=tComps * GLBuffers.sizeOfGLType(tDataType);
+ this.vboName = 0;
- allocateBuffer(initialElementCount);
+ this.vCount=0;
+ this.cCount=0;
+ this.nCount=0;
+ this.tCount=0;
+ this.vElems=0;
+ this.cElems=0;
+ this.nElems=0;
+ this.tElems=0;
+
+ this.pageSize = Platform.getMachineDescription().pageSizeInBytes();
+
+ reallocateBuffer(initialElementCount);
rewind();
this.sealed=false;
@@ -313,302 +461,387 @@ public class ImmModeSink {
this.modeOrig = 0;
this.bufferEnabled=false;
this.bufferWritten=false;
+ this.bufferWrittenOnce=false;
+ this.glslLocationSet = false;
}
- protected final VBOSet regenerate() {
- return new VBOSet(gl, glBufferUsage, initialElementCount,
- vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL);
+ protected int getResizeElementCount() { return resizeElementCount; }
+ protected void setResizeElementCount(final int v) { resizeElementCount=v; }
+
+ protected boolean getUseVBO() { return useVBO; }
+
+ protected final VBOSet regenerate(final GL gl) {
+ return new VBOSet(initialElementCount, vComps,
+ vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType,
+ useGLSL, glBufferUsage, shaderState, shaderProgram);
}
- protected void checkSeal(boolean test) throws GLException {
+ protected void checkSeal(final boolean test) throws GLException {
if(0==mode) {
- throw new GLException("No mode set yet, call glBegin(mode) first:\n\t"+this);
+ throw new GLException("No mode set yet, call glBegin(mode) first:\n\t"+this);
}
if(sealed!=test) {
if(test) {
- throw new GLException("Not Sealed yet, call glEnd() first:\n\t"+this);
+ throw new GLException("Not Sealed yet, call glEnd() first:\n\t"+this);
} else {
- throw new GLException("Already Sealed, can't modify VBO after glEnd():\n\t"+this);
+ throw new GLException("Already Sealed, can't modify VBO after glEnd():\n\t"+this);
}
}
}
- protected void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw, int i)
+ private boolean usingShaderProgram = false;
+
+ protected void useShaderProgram(final GL2ES2 gl, final boolean force) {
+ if( force || !usingShaderProgram ) {
+ if(null != shaderState) {
+ shaderState.useProgram(gl, true);
+ } else /* if( 0 != shaderProgram) */ {
+ gl.glUseProgram(shaderProgram);
+ }
+ usingShaderProgram = true;
+ }
+ }
+
+ protected void draw(final GL gl, final Buffer indices, final boolean disableBufferAfterDraw, final int i)
{
+ enableBuffer(gl, true);
+
+ if(null != shaderState || 0 != shaderProgram) {
+ useShaderProgram(gl.getGL2ES2(), false);
+ }
+
if(DEBUG_DRAW) {
- Exception e = new Exception("Info: ImmModeSink.draw["+i+"](disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this);
- e.printStackTrace();
+ System.err.println("ImmModeSink.draw["+i+"].0 (disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this);
}
- enableBuffer(gl, true);
if (buffer!=null) {
if(null==indices) {
- gl.glDrawArrays(mode, 0, count);
+ if ( GL_QUADS == mode && !gl.isGL2() ) {
+ for (int j = 0; j < vElems - 3; j += 4) {
+ gl.glDrawArrays(GL.GL_TRIANGLE_FAN, j, 4);
+ }
+ } else {
+ gl.glDrawArrays(mode, 0, vElems);
+ }
} else {
- Class<?> clazz = indices.getClass();
- int type=-1;
- if(ReflectionUtil.instanceOf(clazz, ByteBuffer.class.getName())) {
+ // FIXME: Impl. VBO usage .. or unroll.
+ if( !gl.getContext().isCPUDataSourcingAvail() ) {
+ throw new GLException("CPU data sourcing n/a w/ "+gl.getContext());
+ }
+ final int type;
+ if(indices instanceof ByteBuffer) {
type = GL.GL_UNSIGNED_BYTE;
- } else if(ReflectionUtil.instanceOf(clazz, ShortBuffer.class.getName())) {
+ } else if(indices instanceof ShortBuffer) {
type = GL.GL_UNSIGNED_SHORT;
+ } else if(indices instanceof IntBuffer) {
+ type = GL.GL_UNSIGNED_INT;
+ } else {
+ throw new GLException("Given Buffer Class not supported: "+indices.getClass()+", should be ubyte, ushort or uint:\n\t"+this);
}
- if(0>type) {
- throw new GLException("Given Buffer Class not supported: "+clazz+", should be ubyte or ushort:\n\t"+this);
+ final int idxLen = indices.remaining();
+ final int idx0 = indices.position();
+
+ if ( GL_QUADS == mode && !gl.isGL2() ) {
+ if( GL.GL_UNSIGNED_BYTE == type ) {
+ final ByteBuffer b = (ByteBuffer) indices;
+ for (int j = 0; j < idxLen; j++) {
+ gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 0x000000ff & b.get(idx0+j), 4);
+ }
+ } else if( GL.GL_UNSIGNED_SHORT == type ){
+ final ShortBuffer b = (ShortBuffer) indices;
+ for (int j = 0; j < idxLen; j++) {
+ gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 0x0000ffff & b.get(idx0+j), 4);
+ }
+ } else {
+ final IntBuffer b = (IntBuffer) indices;
+ for (int j = 0; j < idxLen; j++) {
+ gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 0xffffffff & b.get(idx0+j), 4);
+ }
+ }
+ } else {
+ ((GL2ES1)gl).glDrawElements(mode, idxLen, type, indices);
+ // GL2: gl.glDrawRangeElements(mode, 0, idxLen-1, idxLen, type, indices);
}
- gl.glDrawElements(mode, indices.remaining(), type, indices);
- // GL2: gl.glDrawRangeElements(mode, 0, indices.remaining()-1, indices.remaining(), type, indices);
}
}
if(disableBufferAfterDraw) {
enableBuffer(gl, false);
}
+
+ if(DEBUG_DRAW) {
+ System.err.println("ImmModeSink.draw["+i+"].X (disableBufferAfterDraw: "+disableBufferAfterDraw+")");
+ }
}
- public void glVertexv(Buffer v) {
+ public void glVertexv(final Buffer v) {
checkSeal(false);
- GLBuffers.put(vertexArray, v);
+ Buffers.put(vertexArray, v);
}
- public void glNormalv(Buffer v) {
+ public void glNormalv(final Buffer v) {
checkSeal(false);
- GLBuffers.put(normalArray, v);
+ Buffers.put(normalArray, v);
}
- public void glColorv(Buffer v) {
+ public void glColorv(final Buffer v) {
checkSeal(false);
- GLBuffers.put(colorArray, v);
+ Buffers.put(colorArray, v);
}
- public void glTexCoordv(Buffer v) {
+ public void glTexCoordv(final Buffer v) {
checkSeal(false);
- GLBuffers.put(textCoordArray, v);
+ Buffers.put(textCoordArray, v);
}
- public void glVertex2b(byte x, byte y) {
+ public void glVertex2b(final byte x, final byte y) {
checkSeal(false);
- growBufferIfNecessary(VERTEX, 2);
- if(vComps>0)
- GLBuffers.putb(vertexArray, x);
- if(vComps>1)
- GLBuffers.putb(vertexArray, y);
- padding(VERTEX, vComps-2);
- }
- public void glVertex3b(byte x, byte y, byte z) {
+ growBuffer(VERTEX);
+ if(vComps>0)
+ Buffers.putNb(vertexArray, vDataTypeSigned, x, true);
+ if(vComps>1)
+ Buffers.putNb(vertexArray, vDataTypeSigned, y, true);
+ countAndPadding(VERTEX, vComps-2);
+ }
+ public void glVertex3b(final byte x, final byte y, final byte z) {
checkSeal(false);
- growBufferIfNecessary(VERTEX, 3);
- if(vComps>0)
- GLBuffers.putb(vertexArray, x);
- if(vComps>1)
- GLBuffers.putb(vertexArray, y);
- if(vComps>2)
- GLBuffers.putb(vertexArray, z);
- padding(VERTEX, vComps-3);
- }
- public void glVertex2s(short x, short y) {
+ growBuffer(VERTEX);
+ if(vComps>0)
+ Buffers.putNb(vertexArray, vDataTypeSigned, x, true);
+ if(vComps>1)
+ Buffers.putNb(vertexArray, vDataTypeSigned, y, true);
+ if(vComps>2)
+ Buffers.putNb(vertexArray, vDataTypeSigned, z, true);
+ countAndPadding(VERTEX, vComps-3);
+ }
+ public void glVertex2s(final short x, final short y) {
checkSeal(false);
- growBufferIfNecessary(VERTEX, 2);
- if(vComps>0)
- GLBuffers.puts(vertexArray, x);
- if(vComps>1)
- GLBuffers.puts(vertexArray, y);
- padding(VERTEX, vComps-2);
- }
- public void glVertex3s(short x, short y, short z) {
+ growBuffer(VERTEX);
+ if(vComps>0)
+ Buffers.putNs(vertexArray, vDataTypeSigned, x, true);
+ if(vComps>1)
+ Buffers.putNs(vertexArray, vDataTypeSigned, y, true);
+ countAndPadding(VERTEX, vComps-2);
+ }
+ public void glVertex3s(final short x, final short y, final short z) {
checkSeal(false);
- growBufferIfNecessary(VERTEX, 3);
- if(vComps>0)
- GLBuffers.puts(vertexArray, x);
- if(vComps>1)
- GLBuffers.puts(vertexArray, y);
- if(vComps>2)
- GLBuffers.puts(vertexArray, z);
- padding(VERTEX, vComps-3);
- }
- public void glVertex2f(float x, float y) {
+ growBuffer(VERTEX);
+ if(vComps>0)
+ Buffers.putNs(vertexArray, vDataTypeSigned, x, true);
+ if(vComps>1)
+ Buffers.putNs(vertexArray, vDataTypeSigned, y, true);
+ if(vComps>2)
+ Buffers.putNs(vertexArray, vDataTypeSigned, z, true);
+ countAndPadding(VERTEX, vComps-3);
+ }
+ public void glVertex2f(final float x, final float y) {
checkSeal(false);
- growBufferIfNecessary(VERTEX, 2);
- if(vComps>0)
- GLBuffers.putf(vertexArray, x);
- if(vComps>1)
- GLBuffers.putf(vertexArray, y);
- padding(VERTEX, vComps-2);
- }
- public void glVertex3f(float x, float y, float z) {
+ growBuffer(VERTEX);
+ if(vComps>0)
+ Buffers.putNf(vertexArray, vDataTypeSigned, x);
+ if(vComps>1)
+ Buffers.putNf(vertexArray, vDataTypeSigned, y);
+ countAndPadding(VERTEX, vComps-2);
+ }
+ public void glVertex3f(final float x, final float y, final float z) {
checkSeal(false);
- growBufferIfNecessary(VERTEX, 3);
- if(vComps>0)
- GLBuffers.putf(vertexArray, x);
- if(vComps>1)
- GLBuffers.putf(vertexArray, y);
- if(vComps>2)
- GLBuffers.putf(vertexArray, z);
- padding(VERTEX, vComps-3);
+ growBuffer(VERTEX);
+ if(vComps>0)
+ Buffers.putNf(vertexArray, vDataTypeSigned, x);
+ if(vComps>1)
+ Buffers.putNf(vertexArray, vDataTypeSigned, y);
+ if(vComps>2)
+ Buffers.putNf(vertexArray, vDataTypeSigned, z);
+ countAndPadding(VERTEX, vComps-3);
}
- public void glNormal3b(byte x, byte y, byte z) {
+ public void glNormal3b(final byte x, final byte y, final byte z) {
checkSeal(false);
- growBufferIfNecessary(NORMAL, 3);
- if(nComps>0)
- GLBuffers.putb(normalArray, x);
- if(nComps>1)
- GLBuffers.putb(normalArray, y);
- if(nComps>2)
- GLBuffers.putb(normalArray, z);
- padding(NORMAL, nComps-3);
- }
- public void glNormal3s(short x, short y, short z) {
+ growBuffer(NORMAL);
+ if(nComps>0)
+ Buffers.putNb(normalArray, nDataTypeSigned, x, true);
+ if(nComps>1)
+ Buffers.putNb(normalArray, nDataTypeSigned, y, true);
+ if(nComps>2)
+ Buffers.putNb(normalArray, nDataTypeSigned, z, true);
+ countAndPadding(NORMAL, nComps-3);
+ }
+ public void glNormal3s(final short x, final short y, final short z) {
checkSeal(false);
- growBufferIfNecessary(NORMAL, 3);
- if(nComps>0)
- GLBuffers.puts(normalArray, x);
- if(nComps>1)
- GLBuffers.puts(normalArray, y);
- if(nComps>2)
- GLBuffers.puts(normalArray, z);
- padding(NORMAL, nComps-3);
- }
- public void glNormal3f(float x, float y, float z) {
+ growBuffer(NORMAL);
+ if(nComps>0)
+ Buffers.putNs(normalArray, nDataTypeSigned, x, true);
+ if(nComps>1)
+ Buffers.putNs(normalArray, nDataTypeSigned, y, true);
+ if(nComps>2)
+ Buffers.putNs(normalArray, nDataTypeSigned, z, true);
+ countAndPadding(NORMAL, nComps-3);
+ }
+ public void glNormal3f(final float x, final float y, final float z) {
checkSeal(false);
- growBufferIfNecessary(NORMAL, 3);
- if(nComps>0)
- GLBuffers.putf(normalArray, x);
- if(nComps>1)
- GLBuffers.putf(normalArray, y);
- if(nComps>2)
- GLBuffers.putf(normalArray, z);
- padding(NORMAL, nComps-3);
+ growBuffer(NORMAL);
+ if(nComps>0)
+ Buffers.putNf(normalArray, nDataTypeSigned, x);
+ if(nComps>1)
+ Buffers.putNf(normalArray, nDataTypeSigned, y);
+ if(nComps>2)
+ Buffers.putNf(normalArray, nDataTypeSigned, z);
+ countAndPadding(NORMAL, nComps-3);
}
- public void glColor3b(byte r, byte g, byte b) {
+ public void glColor3b(final byte r, final byte g, final byte b) {
checkSeal(false);
- growBufferIfNecessary(COLOR, 3);
- if(cComps>0)
- GLBuffers.putb(colorArray, r);
- if(cComps>1)
- GLBuffers.putb(colorArray, g);
- if(cComps>2)
- GLBuffers.putb(colorArray, b);
- padding(COLOR, cComps-3);
- }
- public void glColor4b(byte r, byte g, byte b, byte a) {
+ growBuffer(COLOR);
+ if(cComps>0)
+ Buffers.putNb(colorArray, cDataTypeSigned, r, true);
+ if(cComps>1)
+ Buffers.putNb(colorArray, cDataTypeSigned, g, true);
+ if(cComps>2)
+ Buffers.putNb(colorArray, cDataTypeSigned, b, true);
+ countAndPadding(COLOR, cComps-3);
+ }
+ public void glColor3ub(final byte r, final byte g, final byte b) {
checkSeal(false);
- growBufferIfNecessary(COLOR, 4);
- if(cComps>0)
- GLBuffers.putb(colorArray, r);
- if(cComps>1)
- GLBuffers.putb(colorArray, g);
- if(cComps>2)
- GLBuffers.putb(colorArray, b);
- if(cComps>3)
- GLBuffers.putb(colorArray, a);
- padding(COLOR, cComps-4);
- }
- public void glColor3s(short r, short g, short b) {
+ growBuffer(COLOR);
+ if(cComps>0)
+ Buffers.putNb(colorArray, cDataTypeSigned, r, false);
+ if(cComps>1)
+ Buffers.putNb(colorArray, cDataTypeSigned, g, false);
+ if(cComps>2)
+ Buffers.putNb(colorArray, cDataTypeSigned, b, false);
+ countAndPadding(COLOR, cComps-3);
+ }
+ public void glColor4b(final byte r, final byte g, final byte b, final byte a) {
checkSeal(false);
- growBufferIfNecessary(COLOR, 3);
- if(cComps>0)
- GLBuffers.puts(colorArray, r);
- if(cComps>1)
- GLBuffers.puts(colorArray, g);
- if(cComps>2)
- GLBuffers.puts(colorArray, b);
- padding(COLOR, cComps-3);
- }
- public void glColor4s(short r, short g, short b, short a) {
+ growBuffer(COLOR);
+ if(cComps>0)
+ Buffers.putNb(colorArray, cDataTypeSigned, r, true);
+ if(cComps>1)
+ Buffers.putNb(colorArray, cDataTypeSigned, g, true);
+ if(cComps>2)
+ Buffers.putNb(colorArray, cDataTypeSigned, b, true);
+ if(cComps>3)
+ Buffers.putNb(colorArray, cDataTypeSigned, a, true);
+ countAndPadding(COLOR, cComps-4);
+ }
+ public void glColor4ub(final byte r, final byte g, final byte b, final byte a) {
checkSeal(false);
- growBufferIfNecessary(COLOR, 4);
- if(cComps>0)
- GLBuffers.puts(colorArray, r);
- if(cComps>1)
- GLBuffers.puts(colorArray, g);
- if(cComps>2)
- GLBuffers.puts(colorArray, b);
- if(cComps>3)
- GLBuffers.puts(colorArray, a);
- padding(COLOR, cComps-4);
- }
- public void glColor3f(float r, float g, float b) {
+ growBuffer(COLOR);
+ if(cComps>0)
+ Buffers.putNb(colorArray, cDataTypeSigned, r, false);
+ if(cComps>1)
+ Buffers.putNb(colorArray, cDataTypeSigned, g, false);
+ if(cComps>2)
+ Buffers.putNb(colorArray, cDataTypeSigned, b, false);
+ if(cComps>3)
+ Buffers.putNb(colorArray, cDataTypeSigned, a, false);
+ countAndPadding(COLOR, cComps-4);
+ }
+ public void glColor3s(final short r, final short g, final short b) {
checkSeal(false);
- growBufferIfNecessary(COLOR, 3);
- if(cComps>0)
- GLBuffers.putf(colorArray, r);
- if(cComps>1)
- GLBuffers.putf(colorArray, g);
- if(cComps>2)
- GLBuffers.putf(colorArray, b);
- padding(COLOR, cComps-3);
- }
- public void glColor4f(float r, float g, float b, float a) {
+ growBuffer(COLOR);
+ if(cComps>0)
+ Buffers.putNs(colorArray, cDataTypeSigned, r, true);
+ if(cComps>1)
+ Buffers.putNs(colorArray, cDataTypeSigned, g, true);
+ if(cComps>2)
+ Buffers.putNs(colorArray, cDataTypeSigned, b, true);
+ countAndPadding(COLOR, cComps-3);
+ }
+ public void glColor4s(final short r, final short g, final short b, final short a) {
checkSeal(false);
- growBufferIfNecessary(COLOR, 4);
- if(cComps>0)
- GLBuffers.putf(colorArray, r);
- if(cComps>1)
- GLBuffers.putf(colorArray, g);
- if(cComps>2)
- GLBuffers.putf(colorArray, b);
- if(cComps>3)
- GLBuffers.putf(colorArray, a);
- padding(COLOR, cComps-4);
- }
-
- public void glTexCoord2b(byte x, byte y) {
+ growBuffer(COLOR);
+ if(cComps>0)
+ Buffers.putNs(colorArray, cDataTypeSigned, r, true);
+ if(cComps>1)
+ Buffers.putNs(colorArray, cDataTypeSigned, g, true);
+ if(cComps>2)
+ Buffers.putNs(colorArray, cDataTypeSigned, b, true);
+ if(cComps>3)
+ Buffers.putNs(colorArray, cDataTypeSigned, a, true);
+ countAndPadding(COLOR, cComps-4);
+ }
+ public void glColor3f(final float r, final float g, final float b) {
checkSeal(false);
- growBufferIfNecessary(TEXTCOORD, 2);
- if(tComps>0)
- GLBuffers.putb(textCoordArray, x);
- if(tComps>1)
- GLBuffers.putb(textCoordArray, y);
- padding(TEXTCOORD, tComps-2);
- }
- public void glTexCoord3b(byte x, byte y, byte z) {
+ growBuffer(COLOR);
+ if(cComps>0)
+ Buffers.putNf(colorArray, cDataTypeSigned, r);
+ if(cComps>1)
+ Buffers.putNf(colorArray, cDataTypeSigned, g);
+ if(cComps>2)
+ Buffers.putNf(colorArray, cDataTypeSigned, b);
+ countAndPadding(COLOR, cComps-3);
+ }
+ public void glColor4f(final float r, final float g, final float b, final float a) {
checkSeal(false);
- growBufferIfNecessary(TEXTCOORD, 3);
- if(tComps>0)
- GLBuffers.putb(textCoordArray, x);
- if(tComps>1)
- GLBuffers.putb(textCoordArray, y);
- if(tComps>2)
- GLBuffers.putb(textCoordArray, z);
- padding(TEXTCOORD, tComps-3);
- }
- public void glTexCoord2s(short x, short y) {
+ growBuffer(COLOR);
+ if(cComps>0)
+ Buffers.putNf(colorArray, cDataTypeSigned, r);
+ if(cComps>1)
+ Buffers.putNf(colorArray, cDataTypeSigned, g);
+ if(cComps>2)
+ Buffers.putNf(colorArray, cDataTypeSigned, b);
+ if(cComps>3)
+ Buffers.putNf(colorArray, cDataTypeSigned, a);
+ countAndPadding(COLOR, cComps-4);
+ }
+
+ public void glTexCoord2b(final byte x, final byte y) {
checkSeal(false);
- growBufferIfNecessary(TEXTCOORD, 2);
- if(tComps>0)
- GLBuffers.puts(textCoordArray, x);
- if(tComps>1)
- GLBuffers.puts(textCoordArray, y);
- padding(TEXTCOORD, tComps-2);
- }
- public void glTexCoord3s(short x, short y, short z) {
+ growBuffer(TEXTCOORD);
+ if(tComps>0)
+ Buffers.putNb(textCoordArray, tDataTypeSigned, x, true);
+ if(tComps>1)
+ Buffers.putNb(textCoordArray, tDataTypeSigned, y, true);
+ countAndPadding(TEXTCOORD, tComps-2);
+ }
+ public void glTexCoord3b(final byte x, final byte y, final byte z) {
checkSeal(false);
- growBufferIfNecessary(TEXTCOORD, 3);
- if(tComps>0)
- GLBuffers.puts(textCoordArray, x);
- if(tComps>1)
- GLBuffers.puts(textCoordArray, y);
- if(tComps>2)
- GLBuffers.puts(textCoordArray, z);
- padding(TEXTCOORD, tComps-3);
- }
- public void glTexCoord2f(float x, float y) {
+ growBuffer(TEXTCOORD);
+ if(tComps>0)
+ Buffers.putNb(textCoordArray, tDataTypeSigned, x, true);
+ if(tComps>1)
+ Buffers.putNb(textCoordArray, tDataTypeSigned, y, true);
+ if(tComps>2)
+ Buffers.putNb(textCoordArray, tDataTypeSigned, z, true);
+ countAndPadding(TEXTCOORD, tComps-3);
+ }
+ public void glTexCoord2s(final short x, final short y) {
checkSeal(false);
- growBufferIfNecessary(TEXTCOORD, 2);
- if(tComps>0)
- GLBuffers.putf(textCoordArray, x);
- if(tComps>1)
- GLBuffers.putf(textCoordArray, y);
- padding(TEXTCOORD, tComps-2);
- }
- public void glTexCoord3f(float x, float y, float z) {
+ growBuffer(TEXTCOORD);
+ if(tComps>0)
+ Buffers.putNs(textCoordArray, tDataTypeSigned, x, true);
+ if(tComps>1)
+ Buffers.putNs(textCoordArray, tDataTypeSigned, y, true);
+ countAndPadding(TEXTCOORD, tComps-2);
+ }
+ public void glTexCoord3s(final short x, final short y, final short z) {
+ checkSeal(false);
+ growBuffer(TEXTCOORD);
+ if(tComps>0)
+ Buffers.putNs(textCoordArray, tDataTypeSigned, x, true);
+ if(tComps>1)
+ Buffers.putNs(textCoordArray, tDataTypeSigned, y, true);
+ if(tComps>2)
+ Buffers.putNs(textCoordArray, tDataTypeSigned, z, true);
+ countAndPadding(TEXTCOORD, tComps-3);
+ }
+ public void glTexCoord2f(final float x, final float y) {
checkSeal(false);
- growBufferIfNecessary(TEXTCOORD, 3);
- if(tComps>0)
- GLBuffers.putf(textCoordArray, x);
- if(tComps>1)
- GLBuffers.putf(textCoordArray, y);
- if(tComps>2)
- GLBuffers.putf(textCoordArray, z);
- padding(TEXTCOORD, tComps-3);
+ growBuffer(TEXTCOORD);
+ if(tComps>0)
+ Buffers.putNf(textCoordArray, tDataTypeSigned, x);
+ if(tComps>1)
+ Buffers.putNf(textCoordArray, tDataTypeSigned, y);
+ countAndPadding(TEXTCOORD, tComps-2);
+ }
+ public void glTexCoord3f(final float x, final float y, final float z) {
+ checkSeal(false);
+ growBuffer(TEXTCOORD);
+ if(tComps>0)
+ Buffers.putNf(textCoordArray, tDataTypeSigned, x);
+ if(tComps>1)
+ Buffers.putNf(textCoordArray, tDataTypeSigned, y);
+ if(tComps>2)
+ Buffers.putNf(textCoordArray, tDataTypeSigned, z);
+ countAndPadding(TEXTCOORD, tComps-3);
}
public void rewind() {
@@ -626,16 +859,61 @@ public class ImmModeSink {
}
}
- public void destroy(GL gl) {
+ public void setShaderProgram(final int program) {
+ if(null == shaderState && 0 == program) {
+ throw new IllegalArgumentException("Not allowed to zero shader program if no ShaderState is set");
+ }
+ shaderProgram = program;
+ glslLocationSet = false; // enforce location reset!
+ }
+
+ /**
+ * @param gl
+ * @return true if all locations for all used arrays are found (min 1 array), otherwise false.
+ * Also sets 'glslLocationSet' to the return value!
+ */
+ private boolean resetGLSLArrayLocation(final GL2ES2 gl) {
+ int iA = 0;
+ int iL = 0;
+
+ if(null != vArrayData) {
+ iA++;
+ if( vArrayData.setLocation(gl, shaderProgram) >= 0 ) {
+ iL++;
+ }
+ }
+ if(null != cArrayData) {
+ iA++;
+ if( cArrayData.setLocation(gl, shaderProgram) >= 0 ) {
+ iL++;
+ }
+ }
+ if(null != nArrayData) {
+ iA++;
+ if( nArrayData.setLocation(gl, shaderProgram) >= 0 ) {
+ iL++;
+ }
+ }
+ if(null != tArrayData) {
+ iA++;
+ if( tArrayData.setLocation(gl, shaderProgram) >= 0 ) {
+ iL++;
+ }
+ }
+ glslLocationSet = iA == iL;
+ return glslLocationSet;
+ }
+
+ public void destroy(final GL gl) {
reset(gl);
+ vCount=0; cCount=0; nCount=0; tCount=0;
vertexArray=null; colorArray=null; normalArray=null; textCoordArray=null;
vArrayData=null; cArrayData=null; nArrayData=null; tArrayData=null;
buffer=null;
- bSize=0; count=0;
}
- public void reset(GL gl) {
+ public void reset(final GL gl) {
enableBuffer(gl, false);
reset();
}
@@ -649,162 +927,334 @@ public class ImmModeSink {
this.mode = 0;
this.modeOrig = 0;
this.sealed=false;
+ this.sealedGL=false;
this.bufferEnabled=false;
this.bufferWritten=false;
+ this.vElems=0;
+ this.cElems=0;
+ this.nElems=0;
+ this.tElems=0;
}
- public void seal(GL glObj, boolean seal)
+ public void seal(final GL glObj, final boolean seal)
{
seal(seal);
if(sealedGL==seal) return;
sealedGL = seal;
- GL gl = glObj.getGL();
+ final GL gl = glObj.getGL();
if(seal) {
- if(vboUsage && vboName==0) {
- int[] tmp = new int[1];
- gl.glGenBuffers(1, tmp, 0);
- vboName = tmp[0];
+ if(useVBO) {
+ if(0 == vboName) {
+ final int[] tmp = new int[1];
+ gl.glGenBuffers(1, tmp, 0);
+ vboName = tmp[0];
+ }
+ if(null!=vArrayData) {
+ vArrayData.setVBOName(vboName);
+ }
+ if(null!=cArrayData) {
+ cArrayData.setVBOName(vboName);
+ }
+ if(null!=nArrayData) {
+ nArrayData.setVBOName(vboName);
+ }
+ if(null!=tArrayData) {
+ tArrayData.setVBOName(vboName);
+ }
}
- if(null!=vArrayData)
- vArrayData.setVBOName(vboName);
- if(null!=cArrayData)
- cArrayData.setVBOName(vboName);
- if(null!=nArrayData)
- nArrayData.setVBOName(vboName);
- if(null!=tArrayData)
- tArrayData.setVBOName(vboName);
enableBuffer(gl, true);
} else {
enableBuffer(gl, false);
}
}
- public void seal(boolean seal)
+ public void seal(final boolean seal)
{
if(sealed==seal) return;
sealed = seal;
if(seal) {
bufferWritten=false;
+ rewind();
}
}
- public void enableBuffer(GL gl, boolean enable) {
- /* if(enableBufferAlways && enable) {
- bufferEnabled = false;
- } */
- if( bufferEnabled != enable && count>0 ) {
+ public void enableBuffer(final GL gl, final boolean enable) {
+ if( bufferEnabled != enable && vElems>0 ) {
if(enable) {
checkSeal(true);
}
- if(useGLSL) {
- enableBufferGLSL(gl, enable);
+ bufferEnabled = enable;
+ if(useGLSL) {
+ useShaderProgram(gl.getGL2ES2(), true);
+ if(null != shaderState) {
+ enableBufferGLSLShaderState(gl, enable);
+ } else {
+ enableBufferGLSLSimple(gl, enable);
+ }
} else {
enableBufferFixed(gl, enable);
}
- bufferEnabled = enable;
}
}
- public void enableBufferFixed(GL gl, boolean enable) {
- GL2ES1 glf = gl.getGL2ES1();
+ private final void writeBuffer(final GL gl) {
+ final int vBytes = vElems * vCompsBytes;
+ final int cBytes = cElems * cCompsBytes;
+ final int nBytes = nElems * nCompsBytes;
+ final int tBytes = tElems * tCompsBytes;
+ final int delta = buffer.limit() - (vBytes+cBytes+nBytes+tBytes);
+ if( bufferWrittenOnce && delta > pageSize ) {
+ if(0 < vBytes) {
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, vOffset, vBytes, vertexArray);
+ }
+ if(0 < cBytes) {
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, cOffset, cBytes, colorArray);
+ }
+ if(0 < nBytes) {
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, nOffset, nBytes, normalArray);
+ }
+ if(0 < tBytes) {
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, tOffset, tBytes, textCoordArray);
+ }
+ } else {
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, glBufferUsage);
+ bufferWrittenOnce = true;
+ }
+ }
+
+ private void enableBufferFixed(final GL gl, final boolean enable) {
+ final GL2ES1 glf = gl.getGL2ES1();
+
+ final boolean useV = vComps>0 && vElems>0 ;
+ final boolean useC = cComps>0 && cElems>0 ;
+ final boolean useN = nComps>0 && nElems>0 ;
+ final boolean useT = tComps>0 && tElems>0 ;
+
+ if(DEBUG_DRAW) {
+ System.err.println("ImmModeSink.enableFixed.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer);
+ }
if(enable) {
- gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName);
+ if(useVBO) {
+ if(0 == vboName) {
+ throw new InternalError("Using VBO but no vboName");
+ }
+ glf.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName);
- if(!bufferWritten) {
- gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, GL.GL_STATIC_DRAW);
- bufferWritten=true;
+ if(!bufferWritten) {
+ writeBuffer(gl);
+ }
}
+ bufferWritten=true;
+ }
- if(vComps>0) {
+ if(useV) {
+ if(enable) {
glf.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
glf.glVertexPointer(vArrayData);
- }
- if(cComps>0) {
+ } else {
+ glf.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ }
+ }
+ if(useC) {
+ if(enable) {
glf.glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY);
glf.glColorPointer(cArrayData);
- }
- if(nComps>0) {
+ } else {
+ glf.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
+ }
+ }
+ if(useN) {
+ if(enable) {
glf.glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
glf.glNormalPointer(nArrayData);
- }
- if(tComps>0) {
+ } else {
+ glf.glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ }
+ }
+ if(useT) {
+ if(enable) {
glf.glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
glf.glTexCoordPointer(tArrayData);
- }
+ } else {
+ glf.glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+ }
+ }
+ if(enable && useVBO) {
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
- } else {
- if(vComps>0) {
- glf.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
- }
- if(cComps>0) {
- glf.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
- }
- if(nComps>0) {
- glf.glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
- }
- if(tComps>0) {
- glf.glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
- }
+ }
+
+ if(DEBUG_DRAW) {
+ System.err.println("ImmModeSink.enableFixed.X ");
}
}
- public void enableBufferGLSL(GL gl, boolean enable) {
- ShaderState st = ShaderState.getShaderState(gl);
- if(null==st) {
- throw new GLException("No ShaderState in "+gl);
- }
- GL2ES2 glsl = gl.getGL2ES2();
-
- if(enable) {
- glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName);
+ private void enableBufferGLSLShaderState(final GL gl, final boolean enable) {
+ final GL2ES2 glsl = gl.getGL2ES2();
- if(!bufferWritten) {
- glsl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, GL.GL_STATIC_DRAW);
- bufferWritten=true;
- }
+ final boolean useV = vComps>0 && vElems>0 ;
+ final boolean useC = cComps>0 && cElems>0 ;
+ final boolean useN = nComps>0 && nElems>0 ;
+ final boolean useT = tComps>0 && tElems>0 ;
- if(vComps>0) {
- st.enableVertexAttribArray(glsl, vArrayData);
- st.vertexAttribPointer(glsl, vArrayData);
- }
- if(cComps>0) {
- st.enableVertexAttribArray(glsl, cArrayData);
- st.vertexAttribPointer(glsl, cArrayData);
- }
- if(nComps>0) {
- st.enableVertexAttribArray(glsl, nArrayData);
- st.vertexAttribPointer(glsl, nArrayData);
- }
- if(tComps>0) {
- st.enableVertexAttribArray(glsl, tArrayData);
- st.vertexAttribPointer(glsl, tArrayData);
+ if(DEBUG_DRAW) {
+ System.err.println("ImmModeSink.enableGLSL.A.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer);
+ }
+
+ if(enable) {
+ if(useVBO) {
+ if(0 == vboName) {
+ throw new InternalError("Using VBO but no vboName");
+ }
+ glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName);
+ if(!bufferWritten) {
+ writeBuffer(gl);
+ }
}
+ bufferWritten=true;
+ }
+ if(useV) {
+ if(enable) {
+ shaderState.enableVertexAttribArray(glsl, vArrayData);
+ shaderState.vertexAttribPointer(glsl, vArrayData);
+ } else {
+ shaderState.disableVertexAttribArray(glsl, vArrayData);
+ }
+ }
+ if(useC) {
+ if(enable) {
+ shaderState.enableVertexAttribArray(glsl, cArrayData);
+ shaderState.vertexAttribPointer(glsl, cArrayData);
+ } else {
+ shaderState.disableVertexAttribArray(glsl, cArrayData);
+ }
+ }
+ if(useN) {
+ if(enable) {
+ shaderState.enableVertexAttribArray(glsl, nArrayData);
+ shaderState.vertexAttribPointer(glsl, nArrayData);
+ } else {
+ shaderState.disableVertexAttribArray(glsl, nArrayData);
+ }
+ }
+ if(useT) {
+ if(enable) {
+ shaderState.enableVertexAttribArray(glsl, tArrayData);
+ shaderState.vertexAttribPointer(glsl, tArrayData);
+ } else {
+ shaderState.disableVertexAttribArray(glsl, tArrayData);
+ }
+ }
+ glslLocationSet = true; // ShaderState does set the location implicit
+
+ if(enable && useVBO) {
glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
- } else {
- if(vComps>0) {
- st.disableVertexAttribArray(glsl, vArrayData);
- }
- if(cComps>0) {
- st.disableVertexAttribArray(glsl, cArrayData);
- }
- if(nComps>0) {
- st.disableVertexAttribArray(glsl, nArrayData);
+ }
+
+ if(DEBUG_DRAW) {
+ System.err.println("ImmModeSink.enableGLSL.A.X ");
+ }
+ }
+
+ private void enableBufferGLSLSimple(final GL gl, final boolean enable) {
+ final GL2ES2 glsl = gl.getGL2ES2();
+
+ final boolean useV = vComps>0 && vElems>0 ;
+ final boolean useC = cComps>0 && cElems>0 ;
+ final boolean useN = nComps>0 && nElems>0 ;
+ final boolean useT = tComps>0 && tElems>0 ;
+
+ if(DEBUG_DRAW) {
+ System.err.println("ImmModeSink.enableGLSL.B.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer);
+ }
+
+ if(!glslLocationSet) {
+ if( !resetGLSLArrayLocation(glsl) ) {
+ if(DEBUG_DRAW) {
+ final int vLoc = null != vArrayData ? vArrayData.getLocation() : -1;
+ final int cLoc = null != cArrayData ? cArrayData.getLocation() : -1;
+ final int nLoc = null != nArrayData ? nArrayData.getLocation() : -1;
+ final int tLoc = null != tArrayData ? tArrayData.getLocation() : -1;
+ System.err.println("ImmModeSink.enableGLSL.B.X attribute locations in shader program "+shaderProgram+", incomplete ["+vLoc+", "+cLoc+", "+nLoc+", "+tLoc+"] - glslLocationSet "+glslLocationSet);
+ }
+ return;
}
- if(tComps>0) {
- st.disableVertexAttribArray(glsl, tArrayData);
+ }
+
+ if(enable) {
+ if(useVBO) {
+ if(0 == vboName) {
+ throw new InternalError("Using VBO but no vboName");
+ }
+ glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName);
+ if(!bufferWritten) {
+ writeBuffer(gl);
+ }
}
+ bufferWritten=true;
+ }
+
+ if(useV) {
+ if(enable) {
+ glsl.glEnableVertexAttribArray(vArrayData.getLocation());
+ glsl.glVertexAttribPointer(vArrayData);
+ } else {
+ glsl.glDisableVertexAttribArray(vArrayData.getLocation());
+ }
+ }
+ if(useC) {
+ if(enable) {
+ glsl.glEnableVertexAttribArray(cArrayData.getLocation());
+ glsl.glVertexAttribPointer(cArrayData);
+ } else {
+ glsl.glDisableVertexAttribArray(cArrayData.getLocation());
+ }
+ }
+ if(useN) {
+ if(enable) {
+ glsl.glEnableVertexAttribArray(nArrayData.getLocation());
+ glsl.glVertexAttribPointer(nArrayData);
+ } else {
+ glsl.glDisableVertexAttribArray(nArrayData.getLocation());
+ }
+ }
+ if(useT) {
+ if(enable) {
+ glsl.glEnableVertexAttribArray(tArrayData.getLocation());
+ glsl.glVertexAttribPointer(tArrayData);
+ } else {
+ glsl.glDisableVertexAttribArray(tArrayData.getLocation());
+ }
+ }
+
+ if(enable && useVBO) {
+ glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ }
+
+ if(DEBUG_DRAW) {
+ System.err.println("ImmModeSink.enableGLSL.B.X ");
}
}
+ @Override
public String toString() {
- return "VBOSet[mode "+mode+
- ", modeOrig "+modeOrig+
- ", sealed "+sealed+
- ", bufferEnabled "+bufferEnabled+
- ", bufferWritten "+bufferWritten+
+ final String glslS = useGLSL ?
+ ", useShaderState "+(null!=shaderState)+
+ ", shaderProgram "+shaderProgram+
+ ", glslLocationSet "+glslLocationSet : "";
+
+ return "VBOSet[mode "+mode+
+ ", modeOrig "+modeOrig+
+ ", use/count "+getElemUseCountStr()+
+ ", sealed "+sealed+
+ ", sealedGL "+sealedGL+
+ ", bufferEnabled "+bufferEnabled+
+ ", bufferWritten "+bufferWritten+" (once "+bufferWrittenOnce+")"+
+ ", useVBO "+useVBO+", vboName "+vboName+
+ ", useGLSL "+useGLSL+
+ glslS+
",\n\t"+vArrayData+
",\n\t"+cArrayData+
",\n\t"+nArrayData+
@@ -814,165 +1264,239 @@ public class ImmModeSink {
// non public matters
- protected void allocateBuffer(int elementCount) {
- int vWidth = vComps * GLBuffers.sizeOfGLType(vDataType);
- int cWidth = cComps * GLBuffers.sizeOfGLType(cDataType);
- int nWidth = nComps * GLBuffers.sizeOfGLType(nDataType);
- int tWidth = tComps * GLBuffers.sizeOfGLType(tDataType);
+ protected String getElemUseCountStr() {
+ return "[v "+vElems+"/"+vCount+", c "+cElems+"/"+cCount+", n "+nElems+"/"+nCount+", t "+tElems+"/"+tCount+"]";
+ }
+
+ protected boolean fitElementInBuffer(final int type) {
+ final int addElems = 1;
+ switch (type) {
+ case VERTEX:
+ return ( vCount - vElems ) >= addElems ;
+ case COLOR:
+ return ( cCount - cElems ) >= addElems ;
+ case NORMAL:
+ return ( nCount - nElems ) >= addElems ;
+ case TEXTCOORD:
+ return ( tCount - tElems ) >= addElems ;
+ default:
+ throw new InternalError("XXX");
+ }
+ }
- count = elementCount;
- bSize = count * ( vWidth + cWidth + nWidth + tWidth ) ;
+ protected boolean reallocateBuffer(final int addElems) {
+ final int vAdd = addElems - ( vCount - vElems );
+ final int cAdd = addElems - ( cCount - cElems );
+ final int nAdd = addElems - ( nCount - nElems );
+ final int tAdd = addElems - ( tCount - tElems );
- buffer = GLBuffers.newDirectByteBuffer(bSize);
+ if( 0>=vAdd && 0>=cAdd && 0>=nAdd && 0>=tAdd) {
+ if(DEBUG_BUFFER) {
+ System.err.println("ImmModeSink.realloc: "+getElemUseCountStr()+" + "+addElems+" -> NOP");
+ }
+ return false;
+ }
+
+ if(DEBUG_BUFFER) {
+ System.err.println("ImmModeSink.realloc: "+getElemUseCountStr()+" + "+addElems);
+ }
+ vCount += vAdd;
+ cCount += cAdd;
+ nCount += nAdd;
+ tCount += tAdd;
+
+ final int vBytes = vCount * vCompsBytes;
+ final int cBytes = cCount * cCompsBytes;
+ final int nBytes = nCount * nCompsBytes;
+ final int tBytes = tCount * tCompsBytes;
- int pos = 0;
- int size= count * vWidth ;
- if(size>0) {
- vertexArray = GLBuffers.sliceGLBuffer(buffer, pos, size, vDataType);
+ buffer = Buffers.newDirectByteBuffer( vBytes + cBytes + nBytes + tBytes );
+ vOffset = 0;
+
+ if(vBytes>0) {
+ vertexArray = GLBuffers.sliceGLBuffer(buffer, vOffset, vBytes, vDataType);
} else {
vertexArray = null;
}
- vOffset = pos;
- pos+=size;
+ cOffset=vOffset+vBytes;
- size= count * cWidth ;
- if(size>0) {
- colorArray = GLBuffers.sliceGLBuffer(buffer, pos, size, cDataType);
+ if(cBytes>0) {
+ colorArray = GLBuffers.sliceGLBuffer(buffer, cOffset, cBytes, cDataType);
} else {
colorArray = null;
}
- cOffset = pos;
- pos+=size;
+ nOffset=cOffset+cBytes;
- size= count * nWidth ;
- if(size>0) {
- normalArray = GLBuffers.sliceGLBuffer(buffer, pos, size, nDataType);
+ if(nBytes>0) {
+ normalArray = GLBuffers.sliceGLBuffer(buffer, nOffset, nBytes, nDataType);
} else {
normalArray = null;
}
- nOffset = pos;
- pos+=size;
+ tOffset=nOffset+nBytes;
- size= count * tWidth ;
- if(size>0) {
- textCoordArray = GLBuffers.sliceGLBuffer(buffer, pos, size, tDataType);
+ if(tBytes>0) {
+ textCoordArray = GLBuffers.sliceGLBuffer(buffer, tOffset, tBytes, tDataType);
} else {
textCoordArray = null;
}
- tOffset = pos;
- pos+=size;
- buffer.position(pos);
+ buffer.position(tOffset+tBytes);
buffer.flip();
if(vComps>0) {
- vArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_VERTEX_ARRAY, vComps, vDataType, false, 0,
+ vArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_VERTEX_ARRAY, vComps,
+ vDataType, GLBuffers.isGLTypeFixedPoint(vDataType), 0,
vertexArray, 0, vOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER);
} else {
vArrayData = null;
}
if(cComps>0) {
- cArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_COLOR_ARRAY, cComps, cDataType, false, 0,
+ cArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_COLOR_ARRAY, cComps,
+ cDataType, GLBuffers.isGLTypeFixedPoint(cDataType), 0,
colorArray, 0, cOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER);
} else {
cArrayData = null;
}
if(nComps>0) {
- nArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_NORMAL_ARRAY, nComps, nDataType, false, 0,
+ nArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_NORMAL_ARRAY, nComps,
+ nDataType, GLBuffers.isGLTypeFixedPoint(nDataType), 0,
normalArray, 0, nOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER);
} else {
nArrayData = null;
}
if(tComps>0) {
- tArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_TEXTURE_COORD_ARRAY, tComps, tDataType, false, 0,
+ tArrayData = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_TEXTURE_COORD_ARRAY, tComps,
+ tDataType, GLBuffers.isGLTypeFixedPoint(tDataType), 0,
textCoordArray, 0, tOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER);
} else {
tArrayData = null;
}
- }
+ bufferWrittenOnce = false; // new buffer data storage size!
- protected final boolean growBufferIfNecessary(int type, int spare) {
- if(buffer==null || count < spare) {
- growBuffer(type, initialElementCount);
- return true;
+ if(DEBUG_BUFFER) {
+ System.err.println("ImmModeSink.realloc.X: "+this.toString());
+ Thread.dumpStack();
}
- return false;
+ return true;
}
- protected final void growBuffer(int type, int additional) {
- if(sealed || 0==additional) return;
-
- // save olde values ..
- Buffer _vertexArray=vertexArray, _colorArray=colorArray, _normalArray=normalArray, _textCoordArray=textCoordArray;
-
- allocateBuffer(count+additional);
-
- if(null!=_vertexArray) {
- _vertexArray.flip();
- GLBuffers.put(vertexArray, _vertexArray);
- }
- if(null!=_colorArray) {
- _colorArray.flip();
- GLBuffers.put(colorArray, _colorArray);
- }
- if(null!=_normalArray) {
- _normalArray.flip();
- GLBuffers.put(normalArray, _normalArray);
- }
- if(null!=_textCoordArray) {
- _textCoordArray.flip();
- GLBuffers.put(textCoordArray, _textCoordArray);
+ /** grow buffer by initialElementCount if there is no space for one more element in the designated buffer */
+ protected final boolean growBuffer(final int type) {
+ if( null !=buffer && !sealed ) {
+ if( !fitElementInBuffer(type) ) {
+ // save olde values ..
+ final Buffer _vertexArray=vertexArray, _colorArray=colorArray, _normalArray=normalArray, _textCoordArray=textCoordArray;
+
+ if ( reallocateBuffer(resizeElementCount) ) {
+ if(null!=_vertexArray) {
+ _vertexArray.flip();
+ Buffers.put(vertexArray, _vertexArray);
+ }
+ if(null!=_colorArray) {
+ _colorArray.flip();
+ Buffers.put(colorArray, _colorArray);
+ }
+ if(null!=_normalArray) {
+ _normalArray.flip();
+ Buffers.put(normalArray, _normalArray);
+ }
+ if(null!=_textCoordArray) {
+ _textCoordArray.flip();
+ Buffers.put(textCoordArray, _textCoordArray);
+ }
+ return true;
+ }
+ }
}
+ return false;
}
- protected void padding(int type, int fill) {
+ /**
+ * Fourth element default value for color (alpha), vertex (w) is '1',
+ * as specified w/ VertexAttributes (ES2/GL3).
+ * <p>
+ * vec4 v = vec4(0, 0, 0, 1);
+ * vec4 c = vec4(0, 0, 0, 1);
+ * </p>
+ *
+ * @param type
+ * @param fill
+ */
+ private void countAndPadding(final int type, int fill) {
if ( sealed ) return;
- Buffer dest = null;
+ final Buffer dest;
+ final boolean dSigned;
+ final int e; // either 0 or 1
switch (type) {
case VERTEX:
dest = vertexArray;
+ dSigned = vDataTypeSigned;
+ e = 4 == vComps ? 1 : 0;
+ vElems++;
break;
case COLOR:
dest = colorArray;
+ dSigned = cDataTypeSigned;
+ e = 4 == cComps ? 1 : 0;
+ cElems++;
break;
case NORMAL:
dest = normalArray;
+ dSigned = nDataTypeSigned;
+ e = 0;
+ nElems++;
break;
case TEXTCOORD:
dest = textCoordArray;
+ dSigned = tDataTypeSigned;
+ e = 0;
+ tElems++;
break;
+ default: throw new InternalError("Invalid type "+type);
}
if ( null==dest ) return;
- while((fill--)>0) {
- GLBuffers.putb(dest, (byte)0);
+ while( fill > e ) {
+ fill--;
+ Buffers.putNf(dest, dSigned, 0f);
+ }
+ if( fill > 0 ) { // e == 1, add missing '1f end component'
+ Buffers.putNf(dest, dSigned, 1f);
}
}
- protected int mode, modeOrig;
- protected int glBufferUsage, initialElementCount;
-
- protected ByteBuffer buffer;
- protected int bSize, count, vboName;
-
- public static final int VERTEX = 0;
- public static final int COLOR = 1;
- public static final int NORMAL = 2;
- public static final int TEXTCOORD = 3;
-
- protected int vOffset, cOffset, nOffset, tOffset;
- protected int vComps, cComps, nComps, tComps;
- protected int vDataType, cDataType, nDataType, tDataType;
- protected Buffer vertexArray, colorArray, normalArray, textCoordArray;
- protected GLArrayDataWrapper vArrayData, cArrayData, nArrayData, tArrayData;
-
- protected boolean sealed, sealedGL, useGLSL;
- protected boolean bufferEnabled, bufferWritten;
- protected GL gl;
+ final private int glBufferUsage, initialElementCount;
+ final private boolean useVBO, useGLSL;
+ final private ShaderState shaderState;
+ private int shaderProgram;
+ private int mode, modeOrig, resizeElementCount;
+
+ private ByteBuffer buffer;
+ private int vboName;
+
+ private static final int VERTEX = 0;
+ private static final int COLOR = 1;
+ private static final int NORMAL = 2;
+ private static final int TEXTCOORD = 3;
+
+ private int vCount, cCount, nCount, tCount; // number of elements fit in each buffer
+ private int vOffset, cOffset, nOffset, tOffset; // offset of specific array in common buffer
+ private int vElems, cElems, nElems, tElems; // number of used elements in each buffer
+ private final int vComps, cComps, nComps, tComps; // number of components for each elements [2, 3, 4]
+ private final int vCompsBytes, cCompsBytes, nCompsBytes, tCompsBytes; // byte size of all components
+ private final int vDataType, cDataType, nDataType, tDataType;
+ private final boolean vDataTypeSigned, cDataTypeSigned, nDataTypeSigned, tDataTypeSigned;
+ private final int pageSize;
+ private Buffer vertexArray, colorArray, normalArray, textCoordArray;
+ private GLArrayDataWrapper vArrayData, cArrayData, nArrayData, tArrayData;
+
+ private boolean sealed, sealedGL;
+ private boolean bufferEnabled, bufferWritten, bufferWrittenOnce;
+ private boolean glslLocationSet;
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
index fc6ef3ede..11acb0c58 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2011 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,147 +29,87 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.opengl.util;
-import java.nio.Buffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
-import java.util.ArrayList;
-import java.util.List;
import javax.media.opengl.GL;
import javax.media.opengl.GLException;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
-import jogamp.opengl.ProjectFloat;
+import jogamp.common.os.PlatformPropsImpl;
-import com.jogamp.opengl.FloatUtil;
import com.jogamp.common.nio.Buffers;
-
-public class PMVMatrix implements GLMatrixFunc {
-
- protected final float[] matrixBufferArray;
+import com.jogamp.common.util.FloatStack;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.Ray;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.math.geom.Frustum;
+
+/**
+ * PMVMatrix implements a subset of the fixed function pipeline
+ * regarding the projection (P), modelview (Mv) matrix operation
+ * which is specified in {@link GLMatrixFunc}.
+ * <p>
+ * Further more, PMVMatrix provides the {@link #glGetMviMatrixf() inverse modelview matrix (Mvi)} and
+ * {@link #glGetMvitMatrixf() inverse transposed modelview matrix (Mvit)}.
+ * {@link Frustum} is also provided by {@link #glGetFrustum()}.
+ * To keep these derived values synchronized after mutable Mv operations like {@link #glRotatef(float, float, float, float) glRotatef(..)}
+ * in {@link #glMatrixMode(int) glMatrixMode}({@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}),
+ * users have to call {@link #update()} before using Mvi and Mvit.
+ * </p>
+ * <p>
+ * All matrices are provided in column-major order,
+ * as specified in the OpenGL fixed function pipeline, i.e. compatibility profile.
+ * See {@link FloatUtil}.
+ * </p>
+ * <p>
+ * PMVMatrix can supplement {@link GL2ES2} applications w/ the
+ * lack of the described matrix functionality.
+ * </p>
+ * <a name="storageDetails"><h5>Matrix storage details</h5></a>
+ * <p>
+ * All matrices are backed up by a common primitive float-array for performance considerations
+ * and are a {@link Buffers#slice2Float(float[], int, int) sliced} representation of it.
+ * </p>
+ * <p>
+ * <b>Note:</b>
+ * <ul>
+ * <li>The matrix is a {@link Buffers#slice2Float(float[], int, int) sliced part } of a host matrix and it's start position has been {@link FloatBuffer#mark() marked}.</li>
+ * <li>Use {@link FloatBuffer#reset() reset()} to rewind it to it's start position after relative operations, like {@link FloatBuffer#get() get()}.</li>
+ * <li>If using absolute operations like {@link FloatBuffer#get(int) get(int)}, use it's {@link FloatBuffer#reset() reset} {@link FloatBuffer#position() position} as it's offset.</li>
+ * </ul>
+ * </p>
+ */
+public final class PMVMatrix implements GLMatrixFunc {
+
+ /** Bit value stating a modified {@link #glGetPMatrixf() projection matrix (P)}, since last {@link #update()} call. */
+ public static final int MODIFIED_PROJECTION = 1 << 0;
+ /** Bit value stating a modified {@link #glGetMvMatrixf() modelview matrix (Mv)}, since last {@link #update()} call. */
+ public static final int MODIFIED_MODELVIEW = 1 << 1;
+ /** Bit value stating a modified {@link #glGetTMatrixf() texture matrix (T)}, since last {@link #update()} call. */
+ public static final int MODIFIED_TEXTURE = 1 << 2;
+ /** Bit value stating all is modified */
+ public static final int MODIFIED_ALL = MODIFIED_PROJECTION | MODIFIED_MODELVIEW | MODIFIED_TEXTURE ;
+
+ /** Bit value stating a dirty {@link #glGetMviMatrixf() inverse modelview matrix (Mvi)}. */
+ public static final int DIRTY_INVERSE_MODELVIEW = 1 << 0;
+ /** Bit value stating a dirty {@link #glGetMvitMatrixf() inverse transposed modelview matrix (Mvit)}. */
+ public static final int DIRTY_INVERSE_TRANSPOSED_MODELVIEW = 1 << 1;
+ /** Bit value stating a dirty {@link #glGetFrustum() frustum}. */
+ public static final int DIRTY_FRUSTUM = 1 << 2;
+ /** Bit value stating all is dirty */
+ public static final int DIRTY_ALL = DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM;
/**
- * Creates an instance of PMVMatrix {@link #PMVMatrix(boolean) PMVMatrix(boolean useBackingArray)},
- * with <code>useBackingArray = true</code>.
+ * @param matrixModeName One of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}
+ * @return true if the given matrix-mode name is valid, otherwise false.
*/
- public PMVMatrix() {
- this(true);
- }
-
- /**
- * Creates an instance of PMVMatrix.
- *
- * @param useBackingArray <code>true</code> for non direct NIO Buffers with guaranteed backing array,
- * which allows faster access in Java computation.
- * <p><code>false</code> for direct NIO buffers w/o a guaranteed backing array.
- * In most Java implementations, direct NIO buffers have no backing array
- * and hence the Java computation will be throttled down by direct IO get/put
- * operations.</p>
- * <p>Depending on the application, ie. whether the Java computation or
- * JNI invocation and hence native data transfer part is heavier,
- * this flag shall be set to <code>true</code> or <code>false</code></p>.
- */
- public PMVMatrix(boolean useBackingArray) {
- this.usesBackingArray = useBackingArray;
-
- // I Identity
- // T Texture
- // P Projection
- // Mv ModelView
- // Mvi Modelview-Inverse
- // Mvit Modelview-Inverse-Transpose
- if(useBackingArray) {
- matrixBufferArray = new float[ 6*16 + ProjectFloat.getRequiredFloatBufferSize() ];
- matrixBuffer = null;
- } else {
- matrixBufferArray = null;
- matrixBuffer = Buffers.newDirectByteBuffer( ( 6*16 + ProjectFloat.getRequiredFloatBufferSize() ) * Buffers.SIZEOF_FLOAT );
- matrixBuffer.mark();
- }
-
- matrixIdent = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 0*16, 1*16); // I
- matrixTex = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 1*16, 1*16); // T
- matrixPMvMvit = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 2*16, 4*16); // P + Mv + Mvi + Mvit
- matrixPMvMvi = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 2*16, 3*16); // P + Mv + Mvi
- matrixPMv = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 2*16, 2*16); // P + Mv
- matrixP = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 2*16, 1*16); // P
- matrixMv = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 3*16, 1*16); // Mv
- matrixMvi = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 4*16, 1*16); // Mvi
- matrixMvit = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 5*16, 1*16); // Mvit
-
- projectFloat = new ProjectFloat(matrixBuffer, matrixBufferArray, 6*16);
-
- if(null != matrixBuffer) {
- matrixBuffer.reset();
- }
- FloatUtil.makeIdentityf(matrixIdent);
-
- vec3f = new float[3];
- matrixMult = new float[16];
- matrixTrans = new float[16];
- matrixRot = new float[16];
- matrixScale = new float[16];
- matrixOrtho = new float[16];
- matrixFrustum = new float[16];
- FloatUtil.makeIdentityf(matrixTrans, 0);
- FloatUtil.makeIdentityf(matrixRot, 0);
- FloatUtil.makeIdentityf(matrixScale, 0);
- FloatUtil.makeIdentityf(matrixOrtho, 0);
- FloatUtil.makeZero(matrixFrustum, 0);
-
- matrixPStack = new ArrayList<float[]>();
- matrixMvStack= new ArrayList<float[]>();
-
- // default values and mode
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glMatrixMode(GL.GL_TEXTURE);
- glLoadIdentity();
- setDirty();
- update();
- }
-
- public final boolean usesBackingArray() { return usesBackingArray; }
-
- public void destroy() {
- if(null!=projectFloat) {
- projectFloat.destroy(); projectFloat=null;
- }
-
- matrixBuffer=null;
- matrixBuffer=null; matrixPMvMvit=null; matrixPMvMvi=null; matrixPMv=null;
- matrixP=null; matrixTex=null; matrixMv=null; matrixMvi=null; matrixMvit=null;
-
- vec3f = null;
- matrixMult = null;
- matrixTrans = null;
- matrixRot = null;
- matrixScale = null;
- matrixOrtho = null;
- matrixFrustum = null;
-
- if(null!=matrixPStack) {
- matrixPStack.clear(); matrixPStack=null;
- }
- if(null!=matrixMvStack) {
- matrixMvStack.clear(); matrixMvStack=null;
- }
- if(null!=matrixPStack) {
- matrixPStack.clear(); matrixPStack=null;
- }
- if(null!=matrixTStack) {
- matrixTStack.clear(); matrixTStack=null;
- }
- }
-
-
public static final boolean isMatrixModeName(final int matrixModeName) {
switch(matrixModeName) {
case GL_MODELVIEW_MATRIX:
@@ -180,6 +120,10 @@ public class PMVMatrix implements GLMatrixFunc {
return false;
}
+ /**
+ * @param matrixModeName One of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}
+ * @return The corresponding matrix-get name, one of {@link GLMatrixFunc#GL_MODELVIEW_MATRIX GL_MODELVIEW_MATRIX}, {@link GLMatrixFunc#GL_PROJECTION_MATRIX GL_PROJECTION_MATRIX} or {@link GLMatrixFunc#GL_TEXTURE_MATRIX GL_TEXTURE_MATRIX}
+ */
public static final int matrixModeName2MatrixGetName(final int matrixModeName) {
switch(matrixModeName) {
case GL_MODELVIEW:
@@ -193,6 +137,10 @@ public class PMVMatrix implements GLMatrixFunc {
}
}
+ /**
+ * @param matrixGetName One of {@link GLMatrixFunc#GL_MODELVIEW_MATRIX GL_MODELVIEW_MATRIX}, {@link GLMatrixFunc#GL_PROJECTION_MATRIX GL_PROJECTION_MATRIX} or {@link GLMatrixFunc#GL_TEXTURE_MATRIX GL_TEXTURE_MATRIX}
+ * @return true if the given matrix-get name is valid, otherwise false.
+ */
public static final boolean isMatrixGetName(final int matrixGetName) {
switch(matrixGetName) {
case GL_MATRIX_MODE:
@@ -204,6 +152,10 @@ public class PMVMatrix implements GLMatrixFunc {
return false;
}
+ /**
+ * @param matrixGetName One of {@link GLMatrixFunc#GL_MODELVIEW_MATRIX GL_MODELVIEW_MATRIX}, {@link GLMatrixFunc#GL_PROJECTION_MATRIX GL_PROJECTION_MATRIX} or {@link GLMatrixFunc#GL_TEXTURE_MATRIX GL_TEXTURE_MATRIX}
+ * @return The corresponding matrix-mode name, one of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}
+ */
public static final int matrixGetName2MatrixModeName(final int matrixGetName) {
switch(matrixGetName) {
case GL_MODELVIEW_MATRIX:
@@ -217,122 +169,275 @@ public class PMVMatrix implements GLMatrixFunc {
}
}
- public void setDirty() {
- modified = DIRTY_MODELVIEW | DIRTY_PROJECTION | DIRTY_TEXTURE ;
- matrixMode = GL_MODELVIEW;
- }
-
- public int getDirtyBits() {
- return modified;
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param a 4x4 matrix in column major order (OpenGL)
+ * @return matrix string representation
+ */
+ @SuppressWarnings("deprecation")
+ public static StringBuilder matrixToString(final StringBuilder sb, final String f, final FloatBuffer a) {
+ return FloatUtil.matrixToString(sb, null, f, a, 0, 4, 4, false);
}
- public boolean isDirty(final int matrixName) {
- boolean res;
- switch(matrixName) {
- case GL_MODELVIEW:
- res = (modified&DIRTY_MODELVIEW)!=0 ;
- break;
- case GL_PROJECTION:
- res = (modified&DIRTY_PROJECTION)!=0 ;
- break;
- case GL.GL_TEXTURE:
- res = (modified&DIRTY_TEXTURE)!=0 ;
- break;
- default:
- throw new GLException("unsupported matrixName: "+matrixName);
- }
- return res;
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param a 4x4 matrix in column major order (OpenGL)
+ * @param b 4x4 matrix in column major order (OpenGL)
+ * @return side by side representation
+ */
+ @SuppressWarnings("deprecation")
+ public static StringBuilder matrixToString(final StringBuilder sb, final String f, final FloatBuffer a, final FloatBuffer b) {
+ return FloatUtil.matrixToString(sb, null, f, a, 0, b, 0, 4, 4, false);
}
- public boolean isDirty() {
- return modified!=0;
+ /**
+ * Creates an instance of PMVMatrix.
+ * <p>
+ * Implementation uses non-direct non-NIO Buffers with guaranteed backing array,
+ * which allows faster access in Java computation.
+ * </p>
+ */
+ public PMVMatrix() {
+ // I Identity
+ // T Texture
+ // P Projection
+ // Mv ModelView
+ // Mvi Modelview-Inverse
+ // Mvit Modelview-Inverse-Transpose
+ matrixArray = new float[5*16];
+
+ mP_offset = 0*16;
+ mMv_offset = 1*16;
+ mTex_offset = 4*16;
+
+ matrixPMvMvit = Buffers.slice2Float(matrixArray, 0*16, 4*16); // P + Mv + Mvi + Mvit
+ matrixPMvMvi = Buffers.slice2Float(matrixArray, 0*16, 3*16); // P + Mv + Mvi
+ matrixPMv = Buffers.slice2Float(matrixArray, 0*16, 2*16); // P + Mv
+ matrixP = Buffers.slice2Float(matrixArray, 0*16, 1*16); // P
+ matrixMv = Buffers.slice2Float(matrixArray, 1*16, 1*16); // Mv
+ matrixMvi = Buffers.slice2Float(matrixArray, 2*16, 1*16); // Mvi
+ matrixMvit = Buffers.slice2Float(matrixArray, 3*16, 1*16); // Mvit
+ matrixTex = Buffers.slice2Float(matrixArray, 4*16, 1*16); // T
+
+ mat4Tmp1 = new float[16];
+ mat4Tmp2 = new float[16];
+ mat4Tmp3 = new float[16];
+ matrixTxSx = new float[16];
+ FloatUtil.makeIdentity(matrixTxSx);
+
+ // Start w/ zero size to save memory
+ matrixTStack = new FloatStack( 0, 2*16); // growSize: GL-min size (2)
+ matrixPStack = new FloatStack( 0, 2*16); // growSize: GL-min size (2)
+ matrixMvStack= new FloatStack( 0, 16*16); // growSize: half GL-min size (32)
+
+ reset();
+
+ frustum = null;
}
/**
- * Update the derived Mvi, Mvit and Pmv matrices
- * in case Mv or P has changed.
- *
- * @return
+ * Issues {@link #glLoadIdentity()} on all matrices,
+ * i.e. {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}
+ * and resets all internal states.
*/
- public boolean update() {
- if(0==modified) return false;
-
- final int res = modified;
- if( (res&DIRTY_MODELVIEW)!=0 ) {
- setMviMvit();
- }
- modified=0;
- return res!=0;
+ public final void reset() {
+ FloatUtil.makeIdentity(matrixArray, mMv_offset);
+ FloatUtil.makeIdentity(matrixArray, mP_offset);
+ FloatUtil.makeIdentity(matrixArray, mTex_offset);
+
+ modifiedBits = MODIFIED_ALL;
+ dirtyBits = DIRTY_ALL;
+ requestMask = 0;
+ matrixMode = GL_MODELVIEW;
}
+ /** Returns the current matrix-mode, one of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}. */
public final int glGetMatrixMode() {
return matrixMode;
}
+ /**
+ * Returns the {@link GLMatrixFunc#GL_TEXTURE_MATRIX texture matrix} (T).
+ * <p>
+ * See <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ */
public final FloatBuffer glGetTMatrixf() {
return matrixTex;
}
+ /**
+ * Returns the {@link GLMatrixFunc#GL_PROJECTION_MATRIX projection matrix} (P).
+ * <p>
+ * See <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ */
public final FloatBuffer glGetPMatrixf() {
return matrixP;
}
+ /**
+ * Returns the {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mv).
+ * <p>
+ * See <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ */
public final FloatBuffer glGetMvMatrixf() {
return matrixMv;
}
- public final FloatBuffer glGetPMvMviMatrixf() {
- usesMviMvit |= 1;
- return matrixPMvMvi;
+ /**
+ * Returns the inverse {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvi).
+ * <p>
+ * Method enables the Mvi matrix update, and performs it's update w/o clearing the modified bits.
+ * </p>
+ * <p>
+ * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ * @see #update()
+ * @see #clearAllUpdateRequests()
+ */
+ public final FloatBuffer glGetMviMatrixf() {
+ requestMask |= DIRTY_INVERSE_MODELVIEW ;
+ updateImpl(false);
+ return matrixMvi;
}
+ /**
+ * Returns the inverse transposed {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvit).
+ * <p>
+ * Method enables the Mvit matrix update, and performs it's update w/o clearing the modified bits.
+ * </p>
+ * <p>
+ * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ * @see #update()
+ * @see #clearAllUpdateRequests()
+ */
+ public final FloatBuffer glGetMvitMatrixf() {
+ requestMask |= DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
+ updateImpl(false);
+ return matrixMvit;
+ }
+
+ /**
+ * Returns 2 matrices within one FloatBuffer: {@link #glGetPMatrixf() P} and {@link #glGetMvMatrixf() Mv}.
+ * <p>
+ * See <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ */
public final FloatBuffer glGetPMvMatrixf() {
return matrixPMv;
}
- public final FloatBuffer glGetMviMatrixf() {
- usesMviMvit |= 1;
- return matrixMvi;
+ /**
+ * Returns 3 matrices within one FloatBuffer: {@link #glGetPMatrixf() P}, {@link #glGetMvMatrixf() Mv} and {@link #glGetMviMatrixf() Mvi}.
+ * <p>
+ * Method enables the Mvi matrix update, and performs it's update w/o clearing the modified bits.
+ * </p>
+ * <p>
+ * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ * @see #update()
+ * @see #clearAllUpdateRequests()
+ */
+ public final FloatBuffer glGetPMvMviMatrixf() {
+ requestMask |= DIRTY_INVERSE_MODELVIEW ;
+ updateImpl(false);
+ return matrixPMvMvi;
}
+ /**
+ * Returns 4 matrices within one FloatBuffer: {@link #glGetPMatrixf() P}, {@link #glGetMvMatrixf() Mv}, {@link #glGetMviMatrixf() Mvi} and {@link #glGetMvitMatrixf() Mvit}.
+ * <p>
+ * Method enables the Mvi and Mvit matrix update, and performs it's update w/o clearing the modified bits.
+ * </p>
+ * <p>
+ * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ * @see #update()
+ * @see #clearAllUpdateRequests()
+ */
public final FloatBuffer glGetPMvMvitMatrixf() {
- usesMviMvit |= 1 | 2;
+ requestMask |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
+ updateImpl(false);
return matrixPMvMvit;
}
-
- public final FloatBuffer glGetMvitMatrixf() {
- usesMviMvit |= 1 | 2;
- return matrixMvit;
+
+ /** Returns the frustum, derived from projection * modelview */
+ public final Frustum glGetFrustum() {
+ requestMask |= DIRTY_FRUSTUM;
+ updateImpl(false);
+ return frustum;
}
-
- /*
- * @return the current matrix
- */
+
+ /*
+ * @return the matrix of the current matrix-mode
+ */
public final FloatBuffer glGetMatrixf() {
return glGetMatrixf(matrixMode);
}
- /**
- * @param matrixName GL_MODELVIEW, GL_PROJECTION or GL.GL_TEXTURE
- * @return the given matrix
- */
+ /**
+ * @param matrixName Either a matrix-get-name, i.e.
+ * {@link GLMatrixFunc#GL_MODELVIEW_MATRIX GL_MODELVIEW_MATRIX}, {@link GLMatrixFunc#GL_PROJECTION_MATRIX GL_PROJECTION_MATRIX} or {@link GLMatrixFunc#GL_TEXTURE_MATRIX GL_TEXTURE_MATRIX},
+ * or a matrix-mode-name, i.e.
+ * {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}
+ * @return the named matrix, not a copy!
+ */
public final FloatBuffer glGetMatrixf(final int matrixName) {
- if(matrixName==GL_MODELVIEW) {
- return matrixMv;
- } else if(matrixName==GL_PROJECTION) {
- return matrixP;
- } else if(matrixName==GL.GL_TEXTURE) {
- return matrixTex;
- } else {
- throw new GLException("unsupported matrixName: "+matrixName);
+ switch(matrixName) {
+ case GL_MODELVIEW_MATRIX:
+ case GL_MODELVIEW:
+ return matrixMv;
+ case GL_PROJECTION_MATRIX:
+ case GL_PROJECTION:
+ return matrixP;
+ case GL_TEXTURE_MATRIX:
+ case GL.GL_TEXTURE:
+ return matrixTex;
+ default:
+ throw new GLException("unsupported matrixName: "+matrixName);
}
}
- //
- // MatrixIf
+
+ /**
+ * Multiplies the {@link #glGetPMatrixf() P} and {@link #glGetMvMatrixf() Mv} matrix, i.e.
+ * <pre>
+ * mat4PMv = P x Mv
+ * </pre>
+ * @param mat4PMv 4x4 matrix storage for result
+ * @param mat4PMv_offset
+ * @return given matrix for chaining
+ */
+ public final float[] multPMvMatrixf(final float[/*16*/] mat4PMv, final int mat4PMv_offset) {
+ FloatUtil.multMatrix(matrixArray, mP_offset, matrixArray, mMv_offset, mat4PMv, mat4PMv_offset);
+ return mat4PMv;
+ }
+
+ /**
+ * Multiplies the {@link #glGetMvMatrixf() Mv} and {@link #glGetPMatrixf() P} matrix, i.e.
+ * <pre>
+ * mat4MvP = Mv x P
+ * </pre>
+ * @param mat4MvP 4x4 matrix storage for result
+ * @param mat4MvP_offset
+ * @return given matrix for chaining
+ */
+ public final float[] multMvPMatrixf(final float[/*16*/] mat4MvP, final int mat4MvP_offset) {
+ FloatUtil.multMatrix(matrixArray, mMv_offset, matrixArray, mP_offset, mat4MvP, mat4MvP_offset);
+ return mat4MvP;
+ }
+
+ //
+ // GLMatrixFunc implementation
//
- public void glMatrixMode(final int matrixName) {
+ @Override
+ public final void glMatrixMode(final int matrixName) {
switch(matrixName) {
case GL_MODELVIEW:
case GL_PROJECTION:
@@ -344,28 +449,33 @@ public class PMVMatrix implements GLMatrixFunc {
matrixMode = matrixName;
}
- public void glGetFloatv(int matrixGetName, FloatBuffer params) {
- int pos = params.position();
+ @Override
+ public final void glGetFloatv(final int matrixGetName, final FloatBuffer params) {
+ final int pos = params.position();
if(matrixGetName==GL_MATRIX_MODE) {
- params.put((float)matrixMode);
+ params.put(matrixMode);
} else {
- FloatBuffer matrix = glGetMatrixf(matrixGetName2MatrixModeName(matrixGetName));
+ final FloatBuffer matrix = glGetMatrixf(matrixGetName);
params.put(matrix); // matrix -> params
matrix.reset();
}
params.position(pos);
}
- public void glGetFloatv(int matrixGetName, float[] params, int params_offset) {
+
+ @Override
+ public final void glGetFloatv(final int matrixGetName, final float[] params, final int params_offset) {
if(matrixGetName==GL_MATRIX_MODE) {
- params[params_offset]=(float)matrixMode;
+ params[params_offset]=matrixMode;
} else {
- FloatBuffer matrix = glGetMatrixf(matrixGetName2MatrixModeName(matrixGetName));
+ final FloatBuffer matrix = glGetMatrixf(matrixGetName);
matrix.get(params, params_offset, 16); // matrix -> params
matrix.reset();
}
}
- public void glGetIntegerv(int pname, IntBuffer params) {
- int pos = params.position();
+
+ @Override
+ public final void glGetIntegerv(final int pname, final IntBuffer params) {
+ final int pos = params.position();
if(pname==GL_MATRIX_MODE) {
params.put(matrixMode);
} else {
@@ -373,7 +483,9 @@ public class PMVMatrix implements GLMatrixFunc {
}
params.position(pos);
}
- public void glGetIntegerv(int pname, int[] params, int params_offset) {
+
+ @Override
+ public final void glGetIntegerv(final int pname, final int[] params, final int params_offset) {
if(pname==GL_MATRIX_MODE) {
params[params_offset]=matrixMode;
} else {
@@ -381,374 +493,581 @@ public class PMVMatrix implements GLMatrixFunc {
}
}
+ @Override
public final void glLoadMatrixf(final float[] values, final int offset) {
- int len = values.length-offset;
if(matrixMode==GL_MODELVIEW) {
- matrixMv.put(values, offset, len);
+ matrixMv.put(values, offset, 16);
matrixMv.reset();
- modified |= DIRTY_MODELVIEW ;
+ dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
- matrixP.put(values, offset, len);
+ matrixP.put(values, offset, 16);
matrixP.reset();
- modified |= DIRTY_PROJECTION ;
+ dirtyBits |= DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
- matrixTex.put(values, offset, len);
+ matrixTex.put(values, offset, 16);
matrixTex.reset();
- modified |= DIRTY_TEXTURE ;
- }
+ modifiedBits |= MODIFIED_TEXTURE;
+ }
}
- public final void glLoadMatrixf(java.nio.FloatBuffer m) {
- int spos = m.position();
+ @Override
+ public final void glLoadMatrixf(final java.nio.FloatBuffer m) {
+ final int spos = m.position();
if(matrixMode==GL_MODELVIEW) {
matrixMv.put(m);
matrixMv.reset();
- modified |= DIRTY_MODELVIEW ;
+ dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
matrixP.put(m);
matrixP.reset();
- modified |= DIRTY_PROJECTION ;
+ dirtyBits |= DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
matrixTex.put(m);
matrixTex.reset();
- modified |= DIRTY_TEXTURE ;
- }
+ modifiedBits |= MODIFIED_TEXTURE;
+ }
m.position(spos);
}
+ /**
+ * Load the current matrix with the values of the given {@link Quaternion}'s rotation {@link Quaternion#toMatrix(float[], int) matrix representation}.
+ */
+ public final void glLoadMatrix(final Quaternion quat) {
+ if(matrixMode==GL_MODELVIEW) {
+ quat.toMatrix(matrixArray, mMv_offset);
+ matrixMv.reset();
+ dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_MODELVIEW;
+ } else if(matrixMode==GL_PROJECTION) {
+ quat.toMatrix(matrixArray, mP_offset);
+ matrixP.reset();
+ dirtyBits |= DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_PROJECTION;
+ } else if(matrixMode==GL.GL_TEXTURE) {
+ quat.toMatrix(matrixArray, mTex_offset);
+ matrixTex.reset();
+ modifiedBits |= MODIFIED_TEXTURE;
+ }
+ }
+
+ @Override
public final void glPopMatrix() {
- float[] stackEntry=null;
+ final FloatStack stack;
if(matrixMode==GL_MODELVIEW) {
- stackEntry = matrixMvStack.remove(0);
+ stack = matrixMvStack;
} else if(matrixMode==GL_PROJECTION) {
- stackEntry = matrixPStack.remove(0);
+ stack = matrixPStack;
} else if(matrixMode==GL.GL_TEXTURE) {
- stackEntry = matrixTStack.remove(0);
- }
- glLoadMatrixf(stackEntry, 0);
+ stack = matrixTStack;
+ } else {
+ throw new InternalError("XXX: mode "+matrixMode);
+ }
+ stack.position(stack.position() - 16);
+ glLoadMatrixf(stack.buffer(), stack.position());
}
+ @Override
public final void glPushMatrix() {
- float[] stackEntry = new float[1*16];
if(matrixMode==GL_MODELVIEW) {
- matrixMv.get(stackEntry);
+ matrixMvStack.putOnTop(matrixMv, 16);
matrixMv.reset();
- matrixMvStack.add(0, stackEntry);
} else if(matrixMode==GL_PROJECTION) {
- matrixP.get(stackEntry);
+ matrixPStack.putOnTop(matrixP, 16);
matrixP.reset();
- matrixPStack.add(0, stackEntry);
} else if(matrixMode==GL.GL_TEXTURE) {
- matrixTex.get(stackEntry);
+ matrixTStack.putOnTop(matrixTex, 16);
matrixTex.reset();
- matrixTStack.add(0, stackEntry);
}
}
+ @Override
public final void glLoadIdentity() {
if(matrixMode==GL_MODELVIEW) {
- matrixMv.put(matrixIdent);
- matrixMv.reset();
- modified |= DIRTY_MODELVIEW ;
+ FloatUtil.makeIdentity(matrixArray, mMv_offset);
+ dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
- matrixP.put(matrixIdent);
- matrixP.reset();
- modified |= DIRTY_PROJECTION ;
+ FloatUtil.makeIdentity(matrixArray, mP_offset);
+ dirtyBits |= DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
- matrixTex.put(matrixIdent);
- matrixTex.reset();
- modified |= DIRTY_TEXTURE ;
- }
- matrixIdent.reset();
+ FloatUtil.makeIdentity(matrixArray, mTex_offset);
+ modifiedBits |= MODIFIED_TEXTURE;
+ }
}
+ @SuppressWarnings("deprecation")
+ @Override
public final void glMultMatrixf(final FloatBuffer m) {
if(matrixMode==GL_MODELVIEW) {
- FloatUtil.multMatrixf(matrixMv, m, matrixMv);
- modified |= DIRTY_MODELVIEW ;
+ FloatUtil.multMatrix(matrixMv, m);
+ dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
- FloatUtil.multMatrixf(matrixP, m, matrixP);
- modified |= DIRTY_PROJECTION ;
+ FloatUtil.multMatrix(matrixP, m);
+ dirtyBits |= DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
- FloatUtil.multMatrixf(matrixTex, m, matrixTex);
- modified |= DIRTY_TEXTURE ;
- }
+ FloatUtil.multMatrix(matrixTex, m);
+ modifiedBits |= MODIFIED_TEXTURE;
+ }
}
- public void glMultMatrixf(float[] m, int m_offset) {
+ @Override
+ public final void glMultMatrixf(final float[] m, final int m_offset) {
if(matrixMode==GL_MODELVIEW) {
- FloatUtil.multMatrixf(matrixMv, m, m_offset, matrixMv);
- modified |= DIRTY_MODELVIEW ;
+ FloatUtil.multMatrix(matrixArray, mMv_offset, m, m_offset);
+ dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
- FloatUtil.multMatrixf(matrixP, m, m_offset, matrixP);
- modified |= DIRTY_PROJECTION ;
+ FloatUtil.multMatrix(matrixArray, mP_offset, m, m_offset);
+ dirtyBits |= DIRTY_FRUSTUM ;
+ modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
- FloatUtil.multMatrixf(matrixTex, m, m_offset, matrixTex);
- modified |= DIRTY_TEXTURE ;
- }
+ FloatUtil.multMatrix(matrixArray, mTex_offset, m, m_offset);
+ modifiedBits |= MODIFIED_TEXTURE;
+ }
}
+ @Override
public final void glTranslatef(final float x, final float y, final float z) {
- // Translation matrix:
- // 1 0 0 x
- // 0 1 0 y
- // 0 0 1 z
- // 0 0 0 1
- matrixTrans[0+4*3] = x;
- matrixTrans[1+4*3] = y;
- matrixTrans[2+4*3] = z;
- glMultMatrixf(matrixTrans, 0);
- }
-
- public final void glRotatef(final float angdeg, float x, float y, float z) {
- final float angrad = angdeg * (float) Math.PI / 180.0f;
- final float c = (float)Math.cos(angrad);
- final float ic= 1.0f - c;
- final float s = (float)Math.sin(angrad);
-
- vec3f[0]=x; vec3f[1]=y; vec3f[2]=z;
- FloatUtil.normalize(vec3f);
- x = vec3f[0]; y = vec3f[1]; z = vec3f[2];
-
- // Rotation matrix:
- // xx(1-c)+c xy(1-c)+zs xz(1-c)-ys 0
- // xy(1-c)-zs yy(1-c)+c yz(1-c)+xs 0
- // xz(1-c)+ys yz(1-c)-xs zz(1-c)+c 0
- // 0 0 0 1
- final float xy = x*y;
- final float xz = x*z;
- final float xs = x*s;
- final float ys = y*s;
- final float yz = y*z;
- final float zs = z*s;
- matrixRot[0*4+0] = x*x*ic+c;
- matrixRot[0*4+1] = xy*ic+zs;
- matrixRot[0*4+2] = xz*ic-ys;
-
- matrixRot[1*4+0] = xy*ic-zs;
- matrixRot[1*4+1] = y*y*ic+c;
- matrixRot[1*4+2] = yz*ic+xs;
-
- matrixRot[2*4+0] = xz*ic+ys;
- matrixRot[2*4+1] = yz*ic-xs;
- matrixRot[2*4+2] = z*z*ic+c;
-
- glMultMatrixf(matrixRot, 0);
+ glMultMatrixf(FloatUtil.makeTranslation(matrixTxSx, false, x, y, z), 0);
}
+ @Override
public final void glScalef(final float x, final float y, final float z) {
- // Scale matrix:
- // x 0 0 0
- // 0 y 0 0
- // 0 0 z 0
- // 0 0 0 1
- matrixScale[0+4*0] = x;
- matrixScale[1+4*1] = y;
- matrixScale[2+4*2] = z;
+ glMultMatrixf(FloatUtil.makeScale(matrixTxSx, false, x, y, z), 0);
+ }
- glMultMatrixf(matrixScale, 0);
+ @Override
+ public final void glRotatef(final float ang_deg, final float x, final float y, final float z) {
+ glMultMatrixf(FloatUtil.makeRotationAxis(mat4Tmp1, 0, ang_deg * FloatUtil.PI / 180.0f, x, y, z, mat4Tmp2), 0);
}
+ /**
+ * Rotate the current matrix with the given {@link Quaternion}'s rotation {@link Quaternion#toMatrix(float[], int) matrix representation}.
+ */
+ public final void glRotate(final Quaternion quat) {
+ glMultMatrixf(quat.toMatrix(mat4Tmp1, 0), 0);
+ }
+
+ @Override
public final void glOrthof(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) {
- // Ortho matrix:
- // 2/dx 0 0 tx
- // 0 2/dy 0 ty
- // 0 0 2/dz tz
- // 0 0 0 1
- final float dx=right-left;
- final float dy=top-bottom;
- final float dz=zFar-zNear;
- final float tx=-1.0f*(right+left)/dx;
- final float ty=-1.0f*(top+bottom)/dy;
- final float tz=-1.0f*(zFar+zNear)/dz;
-
- matrixOrtho[0+4*0] = 2.0f/dx;
- matrixOrtho[1+4*1] = 2.0f/dy;
- matrixOrtho[2+4*2] = -2.0f/dz;
- matrixOrtho[0+4*3] = tx;
- matrixOrtho[1+4*3] = ty;
- matrixOrtho[2+4*3] = tz;
-
- glMultMatrixf(matrixOrtho, 0);
- }
-
- public final void gluPerspective(final float fovy, final float aspect, final float zNear, final float zFar) {
- float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear;
- float bottom=-1.0f*top;
- float left=aspect*bottom;
- float right=aspect*top;
- glFrustumf(left, right, bottom, top, zNear, zFar);
+ glMultMatrixf( FloatUtil.makeOrtho(mat4Tmp1, 0, true, left, right, bottom, top, zNear, zFar), 0 );
}
+ @Override
public final void glFrustumf(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) {
- if(zNear<=0.0f||zFar<0.0f) {
- throw new GLException("GL_INVALID_VALUE: zNear and zFar must be positive, and zNear>0");
- }
- if(left==right || top==bottom) {
- throw new GLException("GL_INVALID_VALUE: top,bottom and left,right must not be equal");
- }
- // Frustum matrix:
- // 2*zNear/dx 0 A 0
- // 0 2*zNear/dy B 0
- // 0 0 C D
- // 0 0 -1 0
- final float zNear2 = 2.0f*zNear;
- final float dx=right-left;
- final float dy=top-bottom;
- final float dz=zFar-zNear;
- final float A=(right+left)/dx;
- final float B=(top+bottom)/dy;
- final float C=-1.0f*(zFar+zNear)/dz;
- final float D=-2.0f*(zFar*zNear)/dz;
-
- matrixFrustum[0+4*0] = zNear2/dx;
- matrixFrustum[1+4*1] = zNear2/dy;
- matrixFrustum[2+4*2] = C;
-
- matrixFrustum[0+4*2] = A;
- matrixFrustum[1+4*2] = B;
+ glMultMatrixf( FloatUtil.makeFrustum(mat4Tmp1, 0, true, left, right, bottom, top, zNear, zFar), 0 );
+ }
- matrixFrustum[2+4*3] = D;
- matrixFrustum[3+4*2] = -1.0f;
+ //
+ // Extra functionality
+ //
- glMultMatrixf(matrixFrustum, 0);
+ /**
+ * {@link #glMultMatrixf(FloatBuffer) Multiply} the {@link #glGetMatrixMode() current matrix} with the perspective/frustum matrix.
+ *
+ * @param fovy_deg fov angle in degrees
+ * @param aspect aspect ratio width / height
+ * @param zNear
+ * @param zFar
+ */
+ public final void gluPerspective(final float fovy_deg, final float aspect, final float zNear, final float zFar) {
+ glMultMatrixf( FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy_deg * FloatUtil.PI / 180.0f, aspect, zNear, zFar), 0 );
}
- public void gluLookAt(float eyex, float eyey, float eyez,
- float centerx, float centery, float centerz,
- float upx, float upy, float upz) {
- projectFloat.gluLookAt(this, eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz);
+ /**
+ * {@link #glMultMatrixf(FloatBuffer) Multiply} and {@link #glTranslatef(float, float, float) translate} the {@link #glGetMatrixMode() current matrix}
+ * with the eye, object and orientation.
+ */
+ public final void gluLookAt(final float eyex, final float eyey, final float eyez,
+ final float centerx, final float centery, final float centerz,
+ final float upx, final float upy, final float upz) {
+ mat4Tmp2[0+0] = eyex;
+ mat4Tmp2[1+0] = eyey;
+ mat4Tmp2[2+0] = eyez;
+ mat4Tmp2[0+4] = centerx;
+ mat4Tmp2[1+4] = centery;
+ mat4Tmp2[2+4] = centerz;
+ mat4Tmp2[0+8] = upx;
+ mat4Tmp2[1+8] = upy;
+ mat4Tmp2[2+8] = upz;
+ glMultMatrixf(
+ FloatUtil.makeLookAt(mat4Tmp1, 0, mat4Tmp2 /* eye */, 0, mat4Tmp2 /* center */, 4, mat4Tmp2 /* up */, 8, mat4Tmp3), 0);
}
/**
- * Uses this instance {@link #glGetMvMatrixf()} and {@link #glGetPMatrixf()}
- *
+ * Map object coordinates to window coordinates.
+ * <p>
+ * Traditional <code>gluProject</code> implementation.
+ * </p>
+ *
* @param objx
* @param objy
* @param objz
- * @param viewport
+ * @param viewport 4 component viewport vector
* @param viewport_offset
- * @param win_pos
+ * @param win_pos 3 component window coordinate, the result
* @param win_pos_offset
- * @return
- */
- public boolean gluProject(float objx, float objy, float objz,
- int[] viewport, int viewport_offset,
- float[] win_pos, int win_pos_offset ) {
- if(usesBackingArray) {
- return projectFloat.gluProject(objx, objy, objz,
- matrixMv.array(), 0,
- matrixP.array(), 0,
- viewport, viewport_offset,
- win_pos, win_pos_offset);
- } else {
- return projectFloat.gluProject(objx, objy, objz,
- matrixMv,
- matrixP,
- viewport, viewport_offset,
- win_pos, win_pos_offset);
- }
+ * @return true if successful, otherwise false (z is 1)
+ */
+ public final boolean gluProject(final float objx, final float objy, final float objz,
+ final int[] viewport, final int viewport_offset,
+ final float[] win_pos, final int win_pos_offset ) {
+ return FloatUtil.mapObjToWinCoords(objx, objy, objz,
+ matrixArray, mMv_offset,
+ matrixArray, mP_offset,
+ viewport, viewport_offset,
+ win_pos, win_pos_offset,
+ mat4Tmp1, mat4Tmp2);
}
/**
- * Uses this instance {@link #glGetMvMatrixf()} and {@link #glGetPMatrixf()}
- *
+ * Map window coordinates to object coordinates.
+ * <p>
+ * Traditional <code>gluUnProject</code> implementation.
+ * </p>
+ *
* @param winx
* @param winy
* @param winz
- * @param viewport
+ * @param viewport 4 component viewport vector
* @param viewport_offset
- * @param obj_pos
+ * @param obj_pos 3 component object coordinate, the result
* @param obj_pos_offset
- * @return
- */
- public boolean gluUnProject(float winx, float winy, float winz,
- int[] viewport, int viewport_offset,
- float[] obj_pos, int obj_pos_offset) {
- if(usesBackingArray) {
- return projectFloat.gluUnProject(winx, winy, winz,
- matrixMv.array(), 0,
- matrixP.array(), 0,
- viewport, viewport_offset,
- obj_pos, obj_pos_offset);
- } else {
- return projectFloat.gluUnProject(winx, winy, winz,
- matrixMv,
- matrixP,
- viewport, viewport_offset,
- obj_pos, obj_pos_offset);
- }
- }
-
- public void gluPickMatrix(float x, float y,
- float deltaX, float deltaY,
- int[] viewport, int viewport_offset) {
- projectFloat.gluPickMatrix(this, x, y, deltaX, deltaY, viewport, viewport_offset);
- }
-
- //
- // private
- //
- private int nioBackupArraySupported = 0; // -1 not supported, 0 - TBD, 1 - supported
- private final String msgCantComputeInverse = "Invalid source Mv matrix, can't compute inverse";
-
- private final void setMviMvit() {
- if( 0 != (usesMviMvit & 1) ) {
- if(nioBackupArraySupported>=0) {
- try {
- setMviMvitNIOBackupArray();
- nioBackupArraySupported = 1;
- return;
- } catch(UnsupportedOperationException uoe) {
- nioBackupArraySupported = -1;
- }
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
+ */
+ public final boolean gluUnProject(final float winx, final float winy, final float winz,
+ final int[] viewport, final int viewport_offset,
+ final float[] obj_pos, final int obj_pos_offset) {
+ return FloatUtil.mapWinToObjCoords(winx, winy, winz,
+ matrixArray, mMv_offset,
+ matrixArray, mP_offset,
+ viewport, viewport_offset,
+ obj_pos, obj_pos_offset,
+ mat4Tmp1, mat4Tmp2);
+ }
+
+ /**
+ * Map window coordinates to object coordinates.
+ * <p>
+ * Traditional <code>gluUnProject4</code> implementation.
+ * </p>
+ *
+ * @param winx
+ * @param winy
+ * @param winz
+ * @param clipw
+ * @param modelMatrix 4x4 modelview matrix
+ * @param modelMatrix_offset
+ * @param projMatrix 4x4 projection matrix
+ * @param projMatrix_offset
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param near
+ * @param far
+ * @param obj_pos 4 component object coordinate, the result
+ * @param obj_pos_offset
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
+ */
+ public boolean gluUnProject4(final float winx, final float winy, final float winz, final float clipw,
+ final int[] viewport, final int viewport_offset,
+ final float near, final float far,
+ final float[] obj_pos, final int obj_pos_offset ) {
+ return FloatUtil.mapWinToObjCoords(winx, winy, winz, clipw,
+ matrixArray, mMv_offset,
+ matrixArray, mP_offset,
+ viewport, viewport_offset,
+ near, far,
+ obj_pos, obj_pos_offset,
+ mat4Tmp1, mat4Tmp2);
+ }
+
+ /**
+ * Make given matrix the <i>pick</i> matrix based on given parameters.
+ * <p>
+ * Traditional <code>gluPickMatrix</code> implementation.
+ * </p>
+ * <p>
+ * See {@link FloatUtil#makePick(float[], int, float, float, float, float, int[], int, float[]) FloatUtil.makePick(..)} for details.
+ * </p>
+ * @param x the center x-component of a picking region in window coordinates
+ * @param y the center y-component of a picking region in window coordinates
+ * @param deltaX the width of the picking region in window coordinates.
+ * @param deltaY the height of the picking region in window coordinates.
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ */
+ public final void gluPickMatrix(final float x, final float y,
+ final float deltaX, final float deltaY,
+ final int[] viewport, final int viewport_offset) {
+ if( null != FloatUtil.makePick(mat4Tmp1, 0, x, y, deltaX, deltaY, viewport, viewport_offset, mat4Tmp2) ) {
+ glMultMatrixf(mat4Tmp1, 0);
+ }
+ }
+
+ /**
+ * Map two window coordinates w/ shared X/Y and distinctive Z
+ * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i>
+ * using a {@link AABBox#getRayIntersection(Ray, float[]) bounding box}.
+ * <p>
+ * Notes for picking <i>winz0</i> and <i>winz1</i>:
+ * <ul>
+ * <li>see {@link FloatUtil#getZBufferEpsilon(int, float, float)}</li>
+ * <li>see {@link FloatUtil#getZBufferValue(int, float, float, float)}</li>
+ * <li>see {@link FloatUtil#getOrthoWinZ(float, float, float)}</li>
+ * </ul>
+ * </p>
+ * @param winx
+ * @param winy
+ * @param winz0
+ * @param winz1
+ * @param viewport
+ * @param viewport_offset
+ * @param ray storage for the resulting {@link Ray}
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
+ */
+ public final boolean gluUnProjectRay(final float winx, final float winy, final float winz0, final float winz1,
+ final int[] viewport, final int viewport_offset,
+ final Ray ray) {
+ return FloatUtil.mapWinToRay(winx, winy, winz0, winz1,
+ matrixArray, mMv_offset,
+ matrixArray, mP_offset,
+ viewport, viewport_offset,
+ ray,
+ mat4Tmp1, mat4Tmp2, mat4Tmp3);
+ }
+
+ public StringBuilder toString(StringBuilder sb, final String f) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ final boolean mviDirty = 0 != (DIRTY_INVERSE_MODELVIEW & dirtyBits);
+ final boolean mvitDirty = 0 != (DIRTY_INVERSE_TRANSPOSED_MODELVIEW & dirtyBits);
+ final boolean frustumDirty = 0 != (DIRTY_FRUSTUM & dirtyBits);
+ final boolean mviReq = 0 != (DIRTY_INVERSE_MODELVIEW & requestMask);
+ final boolean mvitReq = 0 != (DIRTY_INVERSE_TRANSPOSED_MODELVIEW & requestMask);
+ final boolean frustumReq = 0 != (DIRTY_FRUSTUM & requestMask);
+ final boolean modP = 0 != ( MODIFIED_PROJECTION & modifiedBits );
+ final boolean modMv = 0 != ( MODIFIED_MODELVIEW & modifiedBits );
+ final boolean modT = 0 != ( MODIFIED_TEXTURE & modifiedBits );
+
+ sb.append("PMVMatrix[modified[P ").append(modP).append(", Mv ").append(modMv).append(", T ").append(modT);
+ sb.append("], dirty/req[Mvi ").append(mviDirty).append("/").append(mviReq).append(", Mvit ").append(mvitDirty).append("/").append(mvitReq).append(", Frustum ").append(frustumDirty).append("/").append(frustumReq).append("]").append(PlatformPropsImpl.NEWLINE);
+ sb.append(", Projection").append(PlatformPropsImpl.NEWLINE);
+ matrixToString(sb, f, matrixP);
+ sb.append(", Modelview").append(PlatformPropsImpl.NEWLINE);
+ matrixToString(sb, f, matrixMv);
+ sb.append(", Texture").append(PlatformPropsImpl.NEWLINE);
+ matrixToString(sb, f, matrixTex);
+ if( 0 != ( requestMask & DIRTY_INVERSE_MODELVIEW ) ) {
+ sb.append(", Inverse Modelview").append(PlatformPropsImpl.NEWLINE);
+ matrixToString(sb, f, matrixMvi);
+ }
+ if( 0 != ( requestMask & DIRTY_INVERSE_TRANSPOSED_MODELVIEW ) ) {
+ sb.append(", Inverse Transposed Modelview").append(PlatformPropsImpl.NEWLINE);
+ matrixToString(sb, f, matrixMvit);
+ }
+ sb.append("]");
+ return sb;
+ }
+
+ @Override
+ public String toString() {
+ return toString(null, "%10.5f").toString();
+ }
+
+ /**
+ * Returns the modified bits due to mutable operations..
+ * <p>
+ * A modified bit is set, if the corresponding matrix had been modified by a mutable operation
+ * since last {@link #update()} or {@link #getModifiedBits(boolean) getModifiedBits(true)} call.
+ * </p>
+ * @param clear if true, clears the modified bits, otherwise leaves them untouched.
+ *
+ * @see #MODIFIED_PROJECTION
+ * @see #MODIFIED_MODELVIEW
+ * @see #MODIFIED_TEXTURE
+ */
+ public final int getModifiedBits(final boolean clear) {
+ final int r = modifiedBits;
+ if(clear) {
+ modifiedBits = 0;
+ }
+ return r;
+ }
+
+ /**
+ * Returns the dirty bits due to mutable operations.
+ * <p>
+ * A dirty bit is set , if the corresponding matrix had been modified by a mutable operation
+ * since last {@link #update()} call. The latter clears the dirty state only if the dirty matrix (Mvi or Mvit) or {@link Frustum}
+ * has been requested by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get}
+ * or {@link #glGetFrustum() Frustum get} methods.
+ * </p>
+ *
+ * @deprecated Function is exposed for debugging purposes only.
+ * @see #DIRTY_INVERSE_MODELVIEW
+ * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW
+ * @see #DIRTY_FRUSTUM
+ * @see #glGetMviMatrixf()
+ * @see #glGetMvitMatrixf()
+ * @see #glGetPMvMviMatrixf()
+ * @see #glGetPMvMvitMatrixf()
+ * @see #glGetFrustum()
+ */
+ public final int getDirtyBits() {
+ return dirtyBits;
+ }
+
+ /**
+ * Returns the request bit mask, which uses bit values equal to the dirty mask.
+ * <p>
+ * The request bit mask is set by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get}
+ * or {@link #glGetFrustum() Frustum get} methods.
+ * </p>
+ *
+ * @deprecated Function is exposed for debugging purposes only.
+ * @see #clearAllUpdateRequests()
+ * @see #DIRTY_INVERSE_MODELVIEW
+ * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW
+ * @see #DIRTY_FRUSTUM
+ * @see #glGetMviMatrixf()
+ * @see #glGetMvitMatrixf()
+ * @see #glGetPMvMviMatrixf()
+ * @see #glGetPMvMvitMatrixf()
+ * @see #glGetFrustum()
+ */
+ public final int getRequestMask() {
+ return requestMask;
+ }
+
+
+ /**
+ * Clears all {@link #update()} requests of the Mvi and Mvit matrix and Frustum
+ * after it has been enabled by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get}
+ * or {@link #glGetFrustum() Frustum get} methods.
+ * <p>
+ * Allows user to disable subsequent Mvi, Mvit and {@link Frustum} updates if no more required.
+ * </p>
+ *
+ * @see #glGetMviMatrixf()
+ * @see #glGetMvitMatrixf()
+ * @see #glGetPMvMviMatrixf()
+ * @see #glGetPMvMvitMatrixf()
+ * @see #glGetFrustum()
+ * @see #getRequestMask()
+ */
+ public final void clearAllUpdateRequests() {
+ requestMask &= ~DIRTY_ALL;
+ }
+
+ /**
+ * Update the derived {@link #glGetMviMatrixf() inverse modelview (Mvi)},
+ * {@link #glGetMvitMatrixf() inverse transposed modelview (Mvit)} matrices and {@link Frustum}
+ * <b>if</b> they are dirty <b>and</b> they were requested
+ * by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get}
+ * or {@link #glGetFrustum() Frustum get} methods.
+ * <p>
+ * The Mvi and Mvit matrices and {@link Frustum} are considered dirty, if their corresponding
+ * {@link #glGetMvMatrixf() Mv matrix} has been modified since their last update.
+ * </p>
+ * <p>
+ * Method should be called manually in case mutable operations has been called
+ * and caller operates on already fetched references, i.e. not calling
+ * {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get}
+ * or {@link #glGetFrustum() Frustum get} etc anymore.
+ * </p>
+ * <p>
+ * This method clears the modified bits like {@link #getModifiedBits(boolean) getModifiedBits(true)},
+ * which are set by any mutable operation. The modified bits have no impact
+ * on this method, but the return value.
+ * </p>
+ *
+ * @return true if any matrix has been modified since last update call or
+ * if the derived matrices Mvi and Mvit or {@link Frustum} were updated, otherwise false.
+ * In other words, method returns true if any matrix used by the caller must be updated,
+ * e.g. uniforms in a shader program.
+ *
+ * @see #getModifiedBits(boolean)
+ * @see #MODIFIED_PROJECTION
+ * @see #MODIFIED_MODELVIEW
+ * @see #MODIFIED_TEXTURE
+ * @see #DIRTY_INVERSE_MODELVIEW
+ * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW
+ * @see #DIRTY_FRUSTUM
+ * @see #glGetMviMatrixf()
+ * @see #glGetMvitMatrixf()
+ * @see #glGetPMvMviMatrixf()
+ * @see #glGetPMvMvitMatrixf()
+ * @see #glGetFrustum()
+ * @see #clearAllUpdateRequests()
+ */
+ public final boolean update() {
+ return updateImpl(true);
+ }
+ private final boolean updateImpl(final boolean clearModBits) {
+ boolean mod = 0 != modifiedBits;
+ if(clearModBits) {
+ modifiedBits = 0;
+ }
+
+ if( 0 != ( dirtyBits & ( DIRTY_FRUSTUM & requestMask ) ) ) {
+ if( null == frustum ) {
+ frustum = new Frustum();
}
- setMviMvitNIODirectAccess();
+ FloatUtil.multMatrix(matrixArray, mP_offset, matrixArray, mMv_offset, mat4Tmp1, 0);
+ // FloatUtil.multMatrix(matrixP, matrixMv, mat4Tmp1, 0);
+ frustum.updateByPMV(mat4Tmp1, 0);
+ dirtyBits &= ~DIRTY_FRUSTUM;
+ mod = true;
}
+
+ if( 0 == ( dirtyBits & requestMask ) ) {
+ return mod; // nothing more requested which may have been dirty
+ }
+
+ return setMviMvit() || mod;
}
- private final void setMviMvitNIOBackupArray() {
+
+ //
+ // private
+ //
+ private static final String msgCantComputeInverse = "Invalid source Mv matrix, can't compute inverse";
+
+ private final boolean setMviMvit() {
final float[] _matrixMvi = matrixMvi.array();
final int _matrixMviOffset = matrixMvi.position();
- if(!projectFloat.gluInvertMatrixf(matrixMv.array(), matrixMv.position(), _matrixMvi, _matrixMviOffset)) {
- throw new GLException(msgCantComputeInverse);
- }
- if( 0 != (usesMviMvit & 2) ) {
- // transpose matrix
- final float[] _matrixMvit = matrixMvit.array();
- final int _matrixMvitOffset = matrixMvit.position();
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- _matrixMvit[_matrixMvitOffset+j+i*4] = _matrixMvi[_matrixMviOffset+i+j*4];
- }
+ boolean res = false;
+ if( 0 != ( dirtyBits & DIRTY_INVERSE_MODELVIEW ) ) { // only if dirt; always requested at this point, see update()
+ if( null == FloatUtil.invertMatrix(matrixArray, mMv_offset, _matrixMvi, _matrixMviOffset) ) {
+ throw new GLException(msgCantComputeInverse);
}
- }
- }
-
- private final void setMviMvitNIODirectAccess() {
- if(!projectFloat.gluInvertMatrixf(matrixMv, matrixMvi)) {
- throw new GLException(msgCantComputeInverse);
+ dirtyBits &= ~DIRTY_INVERSE_MODELVIEW;
+ res = true;
}
- if( 0 != (usesMviMvit & 2) ) {
- // transpose matrix
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- matrixMvit.put(j+i*4, matrixMvi.get(i+j*4));
- }
- }
- }
- }
-
- protected final boolean usesBackingArray;
- protected Buffer matrixBuffer;
- protected FloatBuffer matrixIdent, matrixPMvMvit, matrixPMvMvi, matrixPMv, matrixP, matrixTex, matrixMv, matrixMvi, matrixMvit;
- protected float[] matrixMult, matrixTrans, matrixRot, matrixScale, matrixOrtho, matrixFrustum, vec3f;
- protected List<float[]> matrixTStack, matrixPStack, matrixMvStack;
- protected int matrixMode = GL_MODELVIEW;
- protected int modified = 0;
- protected int usesMviMvit = 0; // 0 - none, 1 - Mvi, 2 - Mvit, 3 - MviMvit (ofc no Mvit w/o Mvi!)
- protected ProjectFloat projectFloat;
-
- public static final int DIRTY_MODELVIEW = 1 << 0;
- public static final int DIRTY_PROJECTION = 1 << 1;
- public static final int DIRTY_TEXTURE = 1 << 2;
+ if( 0 != ( requestMask & ( dirtyBits & DIRTY_INVERSE_TRANSPOSED_MODELVIEW ) ) ) { // only if requested & dirty
+ FloatUtil.transposeMatrix(_matrixMvi, _matrixMviOffset, matrixMvit.array(), matrixMvit.position());
+ dirtyBits &= ~DIRTY_INVERSE_TRANSPOSED_MODELVIEW;
+ res = true;
+ }
+ return res;
+ }
+
+ private final float[] matrixArray;
+ private final int mP_offset, mMv_offset, mTex_offset;
+ private final FloatBuffer matrixPMvMvit, matrixPMvMvi, matrixPMv, matrixP, matrixTex, matrixMv, matrixMvi, matrixMvit;
+ private final float[] matrixTxSx;
+ private final float[] mat4Tmp1, mat4Tmp2, mat4Tmp3;
+ private final FloatStack matrixTStack, matrixPStack, matrixMvStack;
+ private int matrixMode = GL_MODELVIEW;
+ private int modifiedBits = MODIFIED_ALL;
+ private int dirtyBits = DIRTY_ALL; // contains the dirty bits, i.e. hinting for update operation
+ private int requestMask = 0; // may contain the requested dirty bits: DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW
+ private Frustum frustum;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
new file mode 100644
index 000000000..64da547c2
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
@@ -0,0 +1,401 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormatUtil;
+
+import jogamp.opengl.Debug;
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.ImageLine;
+import jogamp.opengl.util.pngj.ImageLineHelper;
+import jogamp.opengl.util.pngj.PngReader;
+import jogamp.opengl.util.pngj.PngWriter;
+import jogamp.opengl.util.pngj.chunks.PngChunkPLTE;
+import jogamp.opengl.util.pngj.chunks.PngChunkTRNS;
+import jogamp.opengl.util.pngj.chunks.PngChunkTextVar;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
+
+public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
+ private static final boolean DEBUG = Debug.debug("PNG");
+
+ /**
+ * Reads a PNG image from the specified InputStream.
+ * <p>
+ * Implicitly converts the image to match the desired:
+ * <ul>
+ * <li>{@link PixelFormat}, see {@link #getPixelformat()}</li>
+ * <li><code>destStrideInBytes</code>, see {@link #getStride()}</li>
+ * <li><code>destIsGLOriented</code>, see {@link #isGLOriented()}</li>
+ * </ul>
+ * </p>
+ *
+ * @param in input stream
+ * @param destFmt desired destination {@link PixelFormat} incl. conversion, maybe <code>null</code> to use source {@link PixelFormat}
+ * @param destDirectBuffer if true, using a direct NIO buffer, otherwise an array backed buffer
+ * @param destMinStrideInBytes used if greater than PNG's stride, otherwise using PNG's stride. Stride is width * bytes-per-pixel.
+ * @param destIsGLOriented
+ * @return the newly created PNGPixelRect instance
+ * @throws IOException
+ */
+ public static PNGPixelRect read(final InputStream in,
+ final PixelFormat ddestFmt, final boolean destDirectBuffer, final int destMinStrideInBytes,
+ final boolean destIsGLOriented) throws IOException {
+ final PngReader pngr = new PngReader(new BufferedInputStream(in), null);
+ final ImageInfo imgInfo = pngr.imgInfo;
+ final PngChunkPLTE plte = pngr.getMetadata().getPLTE();
+ final PngChunkTRNS trns = pngr.getMetadata().getTRNS();
+ final boolean indexed = imgInfo.indexed;
+ final boolean hasAlpha = indexed ? ( trns != null ) : imgInfo.alpha ;
+
+ if(DEBUG) {
+ System.err.println("PNGPixelRect: "+imgInfo);
+ }
+ final int channels = indexed ? ( hasAlpha ? 4 : 3 ) : imgInfo.channels ;
+ final boolean isGrayAlpha = 2 == channels && imgInfo.greyscale && imgInfo.alpha;
+ if ( ! ( 1 == channels || 3 == channels || 4 == channels || isGrayAlpha ) ) {
+ throw new RuntimeException("PNGPixelRect can only handle Lum/RGB/RGBA [1/3/4 channels] or Lum+A (GA) images for now. Channels "+channels + " Paletted: " + indexed);
+ }
+ final int bytesPerPixel = indexed ? channels : imgInfo.bytesPixel ;
+ if ( ! ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel || isGrayAlpha ) ) {
+ throw new RuntimeException("PNGPixelRect can only handle Lum/RGB/RGBA [1/3/4 bpp] images for now. BytesPerPixel "+bytesPerPixel);
+ }
+ if( channels != bytesPerPixel ) {
+ throw new RuntimeException("PNGPixelRect currently only handles Channels [1/3/4] == BytePerPixel [1/3/4], channels: "+channels+", bytesPerPixel "+bytesPerPixel);
+ }
+ final int width = imgInfo.cols;
+ final int height = imgInfo.rows;
+ final double dpiX, dpiY;
+ {
+ final double[] dpi = pngr.getMetadata().getDpi();
+ dpiX = dpi[0];
+ dpiY = dpi[1];
+ }
+ final PixelFormat srcFmt;
+ if ( indexed ) {
+ if ( hasAlpha ) {
+ srcFmt = PixelFormat.RGBA8888;
+ } else {
+ srcFmt = PixelFormat.RGB888;
+ }
+ } else {
+ switch( channels ) {
+ case 1: srcFmt = PixelFormat.LUMINANCE; break;
+ case 2: srcFmt = isGrayAlpha ? PixelFormat.LUMINANCE : null; break;
+ case 3: srcFmt = PixelFormat.RGB888; break;
+ case 4: srcFmt = PixelFormat.RGBA8888; break;
+ default: srcFmt = null;
+ }
+ if( null == srcFmt ) {
+ throw new InternalError("XXX: channels: "+channels+", bytesPerPixel "+bytesPerPixel);
+ }
+ }
+ final PixelFormat destFmt;
+ if( null == ddestFmt ) {
+ if( isGrayAlpha ) {
+ destFmt = PixelFormat.BGRA8888; // save alpha value on gray-alpha
+ } else {
+ destFmt = srcFmt; // 1:1
+ }
+ } else {
+ destFmt = ddestFmt; // user choice
+ }
+ final int destStrideInBytes = Math.max(destMinStrideInBytes, destFmt.bytesPerPixel() * width);
+ final ByteBuffer destPixels = destDirectBuffer ? Buffers.newDirectByteBuffer(destStrideInBytes * height) :
+ ByteBuffer.allocate(destStrideInBytes * height);
+ {
+ final int reqBytes = destStrideInBytes * height;
+ if( destPixels.limit() < reqBytes ) {
+ throw new IndexOutOfBoundsException("Dest buffer has insufficient bytes left, needs "+reqBytes+": "+destPixels);
+ }
+ }
+ final boolean vert_flip = destIsGLOriented;
+
+ int[] rgbaScanline = indexed ? new int[width * channels] : null;
+ if(DEBUG) {
+ System.err.println("PNGPixelRect: indexed "+indexed+", alpha "+hasAlpha+", grayscale "+imgInfo.greyscale+", channels "+channels+"/"+imgInfo.channels+
+ ", bytesPerPixel "+bytesPerPixel+"/"+imgInfo.bytesPixel+
+ ", grayAlpha "+isGrayAlpha+", pixels "+width+"x"+height+", dpi "+dpiX+"x"+dpiY+", format "+srcFmt);
+ System.err.println("PNGPixelRect: destFormat "+destFmt+" ("+ddestFmt+", bytesPerPixel "+destFmt.bytesPerPixel()+", fast-path "+(destFmt==srcFmt)+"), destDirectBuffer "+destDirectBuffer+", destIsGLOriented (flip) "+destIsGLOriented);
+ System.err.println("PNGPixelRect: destStrideInBytes "+destStrideInBytes+" (destMinStrideInBytes "+destMinStrideInBytes+")");
+ }
+
+ for (int row = 0; row < height; row++) {
+ final ImageLine l1 = pngr.readRow(row);
+ int lineOff = 0;
+ int dataOff = vert_flip ? ( height - 1 - row ) * destStrideInBytes : row * destStrideInBytes;
+ if( indexed ) {
+ for (int j = width - 1; j >= 0; j--) {
+ rgbaScanline = ImageLineHelper.palette2rgb(l1, plte, trns, rgbaScanline); // reuse rgbaScanline and update if resized
+ dataOff = getPixelRGBA8ToAny(destFmt, destPixels, dataOff, rgbaScanline, lineOff, hasAlpha);
+ lineOff += bytesPerPixel;
+ }
+ } else if( 1 == channels ) {
+ for (int j = width - 1; j >= 0; j--) {
+ dataOff = getPixelLUMToAny(destFmt, destPixels, dataOff, (byte)l1.scanline[lineOff++], (byte)0xff); // Luminance, 1 bytesPerPixel
+ }
+ } else if( isGrayAlpha ) {
+ for (int j = width - 1; j >= 0; j--) {
+ dataOff = getPixelLUMToAny(destFmt, destPixels, dataOff, (byte)l1.scanline[lineOff++], (byte)l1.scanline[lineOff++]); // Luminance+Alpha, 2 bytesPerPixel
+ }
+ } else if( srcFmt == destFmt ) { // fast-path
+ for (int j = width - 1; j >= 0; j--) {
+ dataOff = getPixelRGBSame(destPixels, dataOff, l1.scanline, lineOff, bytesPerPixel);
+ lineOff += bytesPerPixel;
+ }
+ } else {
+ for (int j = width - 1; j >= 0; j--) {
+ dataOff = getPixelRGBA8ToAny(destFmt, destPixels, dataOff, l1.scanline, lineOff, hasAlpha);
+ lineOff += bytesPerPixel;
+ }
+ }
+ }
+ pngr.end();
+
+ return new PNGPixelRect(destFmt, new Dimension(width, height), destStrideInBytes, destIsGLOriented, destPixels, dpiX, dpiY);
+ }
+
+ private static final int getPixelLUMToAny(final PixelFormat dest_fmt, final ByteBuffer d, int dOff, final byte lum, final byte alpha) {
+ switch(dest_fmt) {
+ case LUMINANCE:
+ d.put(dOff++, lum);
+ break;
+ case BGR888:
+ case RGB888:
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ break;
+ case ABGR8888:
+ case ARGB8888:
+ d.put(dOff++, alpha); // A
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ break;
+ case BGRA8888:
+ case RGBA8888:
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ d.put(dOff++, alpha); // A
+ break;
+ default:
+ throw new InternalError("Unhandled format "+dest_fmt);
+ }
+ return dOff;
+ }
+ private static final int getPixelRGBA8ToAny(final PixelFormat dest_fmt, final ByteBuffer d, int dOff, final int[] scanline, final int lineOff, final boolean srcHasAlpha) {
+ final int p = PixelFormatUtil.convertToInt32(dest_fmt, (byte)scanline[lineOff], // R
+ (byte)scanline[lineOff+1], // G
+ (byte)scanline[lineOff+2], // B
+ srcHasAlpha ? (byte)scanline[lineOff+3] : (byte)0xff); // A
+ final int dbpp = dest_fmt.bytesPerPixel();
+ d.put(dOff++, (byte) ( p )); // 1
+ if( 1 < dbpp ) {
+ d.put(dOff++, (byte) ( p >>> 8 )); // 2
+ d.put(dOff++, (byte) ( p >>> 16 )); // 3
+ if( 4 == dbpp ) {
+ d.put(dOff++, (byte) ( p >>> 24 )); // 4
+ }
+ }
+ return dOff;
+ }
+ private static final int getPixelRGBSame(final ByteBuffer d, int dOff, final int[] scanline, final int lineOff, final int bpp) {
+ d.put(dOff++, (byte)scanline[lineOff]); // R
+ if( 1 < bpp ) {
+ d.put(dOff++, (byte)scanline[lineOff + 1]); // G
+ d.put(dOff++, (byte)scanline[lineOff + 2]); // B
+ if( 4 == bpp ) {
+ d.put(dOff++, (byte)scanline[lineOff + 3]); // A
+ }
+ }
+ return dOff;
+ }
+ private int setPixelRGBA8(final ImageLine line, final int lineOff, final ByteBuffer src, final int srcOff, final int bytesPerPixel, final boolean hasAlpha) {
+ final int b = hasAlpha ? 4-1 : 3-1;
+ if( src.limit() <= srcOff + b ) {
+ throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+srcOff+".."+(srcOff+b)+"]: "+src);
+ }
+ final int p = PixelFormatUtil.convertToInt32(hasAlpha ? PixelFormat.RGBA8888 : PixelFormat.RGB888, pixelformat, src, srcOff);
+ line.scanline[lineOff ] = 0xff & p; // R
+ line.scanline[lineOff + 1] = 0xff & ( p >>> 8 ); // G
+ line.scanline[lineOff + 2] = 0xff & ( p >>> 16 ); // B
+ if(hasAlpha) {
+ line.scanline[lineOff + 3] = 0xff & ( p >>> 24 ); // A
+ }
+ return srcOff + pixelformat.bytesPerPixel();
+ }
+
+ private static void setPixelRGBA8(final PixelFormat pixelformat, final ImageLine line, final int lineOff, final int srcPix, final int bytesPerPixel, final boolean hasAlpha) {
+ final int p = PixelFormatUtil.convertToInt32(hasAlpha ? PixelFormat.RGBA8888 : PixelFormat.RGB888, pixelformat, srcPix);
+ line.scanline[lineOff ] = 0xff & p; // R
+ line.scanline[lineOff + 1] = 0xff & ( p >>> 8 ); // G
+ line.scanline[lineOff + 2] = 0xff & ( p >>> 16 ); // B
+ if(hasAlpha) {
+ line.scanline[lineOff + 3] = 0xff & ( p >>> 24 ); // A
+ }
+ }
+
+ /**
+ * Creates a PNGPixelRect from data supplied by the end user. Shares
+ * data with the passed ByteBuffer.
+ *
+ * @param pixelformat
+ * @param size
+ * @param strideInBytes
+ * @param isGLOriented see {@link #isGLOriented()}.
+ * @param pixels
+ * @param dpiX
+ * @param dpiY
+ */
+ public PNGPixelRect(final PixelFormat pixelformat, final DimensionImmutable size,
+ final int strideInBytes, final boolean isGLOriented, final ByteBuffer pixels,
+ final double dpiX, final double dpiY) {
+ super(pixelformat, size, strideInBytes, isGLOriented, pixels);
+ this.dpi = new double[] { dpiX, dpiY };
+ }
+ public PNGPixelRect(final PixelRectangle src, final double dpiX, final double dpiY) {
+ super(src);
+ this.dpi = new double[] { dpiX, dpiY };
+ }
+ private final double[] dpi;
+
+ /** Returns the dpi of the image. */
+ public double[] getDpi() { return dpi; }
+
+ public void write(final OutputStream outstream, final boolean closeOutstream) throws IOException {
+ final int width = size.getWidth();
+ final int height = size.getHeight();
+ final int bytesPerPixel = pixelformat.bytesPerPixel();
+ final ImageInfo imi = new ImageInfo(width, height, 8 /* bitdepth */,
+ (4 == bytesPerPixel) ? true : false /* alpha */,
+ (1 == bytesPerPixel) ? true : false /* grayscale */,
+ false /* indexed */);
+
+ // open image for writing to a output stream
+ try {
+ final PngWriter png = new PngWriter(outstream, imi);
+ // add some optional metadata (chunks)
+ png.getMetadata().setDpi(dpi[0], dpi[1]);
+ png.getMetadata().setTimeNow(0); // 0 seconds from now = now
+ png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGPixelRect");
+ final boolean hasAlpha = 4 == bytesPerPixel;
+
+ final ImageLine l1 = new ImageLine(imi);
+ for (int row = 0; row < height; row++) {
+ int dataOff = isGLOriented ? ( height - 1 - row ) * strideInBytes : row * strideInBytes;
+ int lineOff = 0;
+ if(1 == bytesPerPixel) {
+ for (int j = width - 1; j >= 0; j--) {
+ l1.scanline[lineOff++] = pixels.get(dataOff++); // // Luminance, 1 bytesPerPixel
+ }
+ } else {
+ for (int j = width - 1; j >= 0; j--) {
+ dataOff = setPixelRGBA8(l1, lineOff, pixels, dataOff, bytesPerPixel, hasAlpha);
+ lineOff += bytesPerPixel;
+ }
+ }
+ png.writeRow(l1, row);
+ }
+ png.end();
+ } finally {
+ if( closeOutstream ) {
+ IOUtil.close(outstream, false);
+ }
+ }
+ }
+
+ public static void write(final PixelFormat pixelformat, final DimensionImmutable size,
+ int strideInPixels, final boolean isGLOriented, final IntBuffer pixels,
+ final double dpiX, final double dpiY,
+ final OutputStream outstream, final boolean closeOutstream) throws IOException {
+ final int width = size.getWidth();
+ final int height = size.getHeight();
+ final int bytesPerPixel = pixelformat.bytesPerPixel();
+ final ImageInfo imi = new ImageInfo(width, height, 8 /* bitdepth */,
+ (4 == bytesPerPixel) ? true : false /* alpha */,
+ (1 == bytesPerPixel) ? true : false /* grayscale */,
+ false /* indexed */);
+ if( 0 != strideInPixels ) {
+ if( strideInPixels < size.getWidth()) {
+ throw new IllegalArgumentException("Invalid stride "+bytesPerPixel+", must be greater than width "+size.getWidth());
+ }
+ } else {
+ strideInPixels = size.getWidth();
+ }
+ final int reqPixels = strideInPixels * size.getHeight();
+ if( pixels.limit() < reqPixels ) {
+ throw new IndexOutOfBoundsException("Dest buffer has insufficient pixels left, needs "+reqPixels+": "+pixels);
+ }
+
+ // open image for writing to a output stream
+ try {
+ final PngWriter png = new PngWriter(outstream, imi);
+ // add some optional metadata (chunks)
+ png.getMetadata().setDpi(dpiX, dpiY);
+ png.getMetadata().setTimeNow(0); // 0 seconds from now = now
+ png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGPixelRect");
+ final boolean hasAlpha = 4 == bytesPerPixel;
+
+ final ImageLine l1 = new ImageLine(imi);
+ for (int row = 0; row < height; row++) {
+ int dataOff = isGLOriented ? ( height - 1 - row ) * strideInPixels : row * strideInPixels;
+ int lineOff = 0;
+ if(1 == bytesPerPixel) {
+ for (int j = width - 1; j >= 0; j--) {
+ l1.scanline[lineOff++] = pixels.get(dataOff++); // // Luminance, 1 bytesPerPixel
+ }
+ } else {
+ for (int j = width - 1; j >= 0; j--) {
+ setPixelRGBA8(pixelformat, l1, lineOff, pixels.get(dataOff++), bytesPerPixel, hasAlpha);
+ lineOff += bytesPerPixel;
+ }
+ }
+ png.writeRow(l1, row);
+ }
+ png.end();
+ } finally {
+ if( closeOutstream ) {
+ IOUtil.close(outstream, false);
+ }
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
new file mode 100644
index 000000000..3b65b0824
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
@@ -0,0 +1,236 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLException;
+
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+
+/**
+ * Variation of {@link TileRenderer} w/o using fixed tiles but arbitrary rectangular regions.
+ * <p>
+ * See {@link TileRendererBase} for details.
+ * </p>
+ */
+public class RandomTileRenderer extends TileRendererBase {
+ private boolean tileRectSet = false;
+
+ /**
+ * Creates a new TileRenderer object
+ */
+ public RandomTileRenderer() {
+ super();
+ }
+
+ @Override
+ public final int getParam(final int pname) {
+ switch (pname) {
+ case TR_IMAGE_WIDTH:
+ return imageSize.getWidth();
+ case TR_IMAGE_HEIGHT:
+ return imageSize.getHeight();
+ case TR_CURRENT_TILE_X_POS:
+ return currentTileXPos;
+ case TR_CURRENT_TILE_Y_POS:
+ return currentTileYPos;
+ case TR_CURRENT_TILE_WIDTH:
+ return currentTileWidth;
+ case TR_CURRENT_TILE_HEIGHT:
+ return currentTileHeight;
+ default:
+ throw new IllegalArgumentException("Invalid pname: "+pname);
+ }
+ }
+
+ /**
+ * Set the tile rectangle for the subsequent rendering calls.
+ *
+ * @throws IllegalArgumentException is tile x/y are < 0 or tile size is <= 0x0
+ */
+ public void setTileRect(final int tX, final int tY, final int tWidth, final int tHeight) throws IllegalStateException, IllegalArgumentException {
+ if( 0 > tX || 0 > tY ) {
+ throw new IllegalArgumentException("Tile pos must be >= 0/0");
+ }
+ if( 0 >= tWidth || 0 >= tHeight ) {
+ throw new IllegalArgumentException("Tile size must be > 0x0");
+ }
+ this.currentTileXPos = tX;
+ this.currentTileYPos = tY;
+ this.currentTileWidth = tWidth;
+ this.currentTileHeight = tHeight;
+ tileRectSet = true;
+ }
+
+ @Override
+ public final boolean isSetup() {
+ return 0 < imageSize.getWidth() && 0 < imageSize.getHeight() && tileRectSet;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * <i>end of tiling</i> is never reached w/ {@link RandomRileRenderer},
+ * i.e. method always returns false.
+ * </p>
+ */
+ @Override
+ public final boolean eot() { return false; }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Reset internal states of {@link RandomTileRenderer} are: <i>none</i>.
+ */
+ @Override
+ public final void reset() { }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws IllegalStateException if {@link #setImageSize(int, int) image-size} has not been set or
+ * {@link #setTileRect(int, int, int, int) tile-rect} has not been set.
+ */
+ @Override
+ public final void beginTile(final GL gl) throws IllegalStateException, GLException {
+ if( 0 >= imageSize.getWidth() || 0 >= imageSize.getHeight() ) {
+ throw new IllegalStateException("Image size has not been set");
+ }
+ if( !tileRectSet ) {
+ throw new IllegalStateException("tileRect has not been set");
+ }
+ validateGL(gl);
+
+ gl.glViewport( 0, 0, currentTileWidth, currentTileHeight );
+
+ if( DEBUG ) {
+ System.err.println("TileRenderer.begin.X: "+this.toString());
+ }
+
+ // Do not forget to issue:
+ // reshape( 0, 0, tW, tH );
+ // which shall reflect tile renderer fileds: currentTileXPos, currentTileYPos and imageSize
+
+ beginCalled = true;
+ }
+
+ @Override
+ public void endTile( final GL gl ) throws IllegalStateException, GLException {
+ if( !beginCalled ) {
+ throw new IllegalStateException("beginTile(..) has not been called");
+ }
+ validateGL(gl);
+
+ // be sure OpenGL rendering is finished
+ gl.glFlush();
+
+ // implicitly save current glPixelStore values
+ psm.setPackAlignment(gl, 1);
+ final GL2ES3 gl2es3;
+ final int readBuffer;
+ if( gl.isGL2ES3() ) {
+ gl2es3 = gl.getGL2ES3();
+ readBuffer = gl2es3.getDefaultReadBuffer();
+ gl2es3.glReadBuffer(readBuffer);
+ } else {
+ gl2es3 = null;
+ readBuffer = 0; // undef. probably default: GL_FRONT (single buffering) GL_BACK (double buffering)
+ }
+ if( DEBUG ) {
+ System.err.println("TileRenderer.end.0: readBuffer 0x"+Integer.toHexString(readBuffer)+", "+this.toString());
+ }
+
+ final int tmp[] = new int[1];
+
+ if( tileBuffer != null ) {
+ final GLPixelAttributes pixelAttribs = tileBuffer.pixelAttributes;
+ final int srcX = 0;
+ final int srcY = 0;
+ final int srcWidth = currentTileWidth;
+ final int srcHeight = currentTileHeight;
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+ tileBuffer.clear();
+ if( tileBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
+ throw new IndexOutOfBoundsException("Required " + readPixelSize + " bytes of buffer, only had " + tileBuffer);
+ }
+ gl.glReadPixels( srcX, srcY, srcWidth, srcHeight, pixelAttribs.format, pixelAttribs.type, tileBuffer.buffer);
+ // be sure OpenGL rendering is finished
+ gl.glFlush();
+ tileBuffer.position( readPixelSize );
+ tileBuffer.flip();
+ }
+
+ if( imageBuffer != null ) {
+ final GLPixelAttributes pixelAttribs = imageBuffer.pixelAttributes;
+ final int srcX = 0;
+ final int srcY = 0;
+ final int srcWidth = currentTileWidth;
+ final int srcHeight = currentTileHeight;
+
+ /* setup pixel store for glReadPixels */
+ final int rowLength = imageSize.getWidth();
+ psm.setPackRowLength(gl2es3, rowLength);
+
+ /* read the tile into the final image */
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+
+ final int ibPos = ( currentTileXPos + ( currentTileYPos * rowLength ) ) * pixelAttribs.bytesPerPixel; // skipPixels + skipRows
+ final int ibLim = ibPos + readPixelSize;
+ imageBuffer.clear();
+ if( imageBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
+ throw new IndexOutOfBoundsException("Required " + ibLim + " bytes of buffer, only had " + imageBuffer);
+ }
+ imageBuffer.position(ibPos);
+
+ gl.glReadPixels( srcX, srcY, srcWidth, srcHeight, pixelAttribs.format, pixelAttribs.type, imageBuffer.buffer);
+ // be sure OpenGL rendering is finished
+ gl.glFlush();
+ imageBuffer.position( ibLim );
+ imageBuffer.flip();
+ }
+
+ /* restore previous glPixelStore values */
+ psm.restore(gl);
+
+ beginCalled = false;
+ }
+
+ /**
+ * Rendering one tile, by simply calling {@link GLAutoDrawable#display()}.
+ *
+ * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachAutoDrawable(GLAutoDrawable) attached}
+ * or imageSize is not set
+ */
+ public void display(final int tX, final int tY, final int tWidth, final int tHeight) throws IllegalStateException {
+ setTileRect(tX, tY, tWidth, tHeight);
+ display();
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TGAWriter.java b/src/jogl/classes/com/jogamp/opengl/util/TGAWriter.java
deleted file mode 100644
index b949f0e39..000000000
--- a/src/jogl/classes/com/jogamp/opengl/util/TGAWriter.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- */
-
-package com.jogamp.opengl.util;
-
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-
-/**
- * Utility class which helps take fast screenshots of OpenGL rendering
- * results into Targa-format files. Used by the {@link com.jogamp.opengl.util.awt.Screenshot}
- * class; can also be used in conjunction with the {@link com.jogamp.opengl.util.gl2.TileRenderer} class.
- */
-public class TGAWriter {
-
- private static final int TARGA_HEADER_SIZE = 18;
-
- private FileChannel ch;
- private ByteBuffer buf;
-
- /** Constructor for the TGAWriter. */
- public TGAWriter() {
- }
-
- /**
- * Opens the specified Targa file for writing, overwriting any
- * existing file, and sets up the header of the file expecting the
- * data to be filled in before closing it.
- *
- * @param file the file to write containing the screenshot
- * @param width the width of the current drawable
- * @param height the height of the current drawable
- * @param alpha whether the alpha channel should be saved. If true,
- * requires GL_EXT_abgr extension to be present.
- *
- * @throws IOException if an I/O error occurred while writing the
- * file
- */
- public void open(File file,
- int width,
- int height,
- boolean alpha) throws IOException {
- RandomAccessFile out = new RandomAccessFile(file, "rw");
- ch = out.getChannel();
- int pixelSize = (alpha ? 32 : 24);
- int numChannels = (alpha ? 4 : 3);
-
- int fileLength = TARGA_HEADER_SIZE + width * height * numChannels;
- out.setLength(fileLength);
- MappedByteBuffer image = ch.map(FileChannel.MapMode.READ_WRITE, 0, fileLength);
-
- // write the TARGA header
- image.put(0, (byte) 0).put(1, (byte) 0);
- image.put(2, (byte) 2); // uncompressed type
- image.put(12, (byte) (width & 0xFF)); // width
- image.put(13, (byte) (width >> 8)); // width
- image.put(14, (byte) (height & 0xFF)); // height
- image.put(15, (byte) (height >> 8)); // height
- image.put(16, (byte) pixelSize); // pixel size
-
- // go to image data position
- image.position(TARGA_HEADER_SIZE);
- // jogl needs a sliced buffer
- buf = image.slice();
- }
-
- /**
- * Returns the ByteBuffer corresponding to the data for the image.
- * This must be filled in with data in either BGR or BGRA format
- * depending on whether an alpha channel was specified during
- * open().
- */
- public ByteBuffer getImageData() {
- return buf;
- }
-
- public void close() throws IOException {
- // close the file channel
- ch.close();
- buf = null;
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
new file mode 100644
index 000000000..d8410a102
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
@@ -0,0 +1,536 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ *
+ * ---------------------
+ *
+ * Based on Brian Paul's tile rendering library, found
+ * at <a href = "http://www.mesa3d.org/brianp/TR.html">http://www.mesa3d.org/brianp/TR.html</a>.
+ *
+ * Copyright (C) 1997-2005 Brian Paul.
+ * Licensed under BSD-compatible terms with permission of the author.
+ * See LICENSE.txt for license information.
+ */
+package com.jogamp.opengl.util;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GLException;
+
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+
+/**
+ * A fairly direct port of Brian Paul's tile rendering library, found
+ * at <a href = "http://www.mesa3d.org/brianp/TR.html">
+ * http://www.mesa3d.org/brianp/TR.html </a> . I've java-fied it, but
+ * the functionality is the same.
+ * <p>
+ * Original code Copyright (C) 1997-2005 Brian Paul. Licensed under
+ * BSD-compatible terms with permission of the author. See LICENSE.txt
+ * for license information.
+ * </p>
+ * <p>
+ * Enhanced for {@link GL2ES3}.
+ * </p>
+ * <p>
+ * See {@link TileRendererBase} for details.
+ * </p>
+ *
+ * @author ryanm, sgothel
+ */
+public class TileRenderer extends TileRendererBase {
+ /**
+ * The width of the final clipped image. See {@link #getParam(int)}.
+ */
+ public static final int TR_IMAGE_CLIPPING_WIDTH = 7;
+ /**
+ * The height of the final clipped image. See {@link #getParam(int)}.
+ */
+ public static final int TR_IMAGE_CLIPPING_HEIGHT = 8;
+ /**
+ * The width of the tiles. See {@link #getParam(int)}.
+ */
+ public static final int TR_TILE_WIDTH = 9;
+ /**
+ * The height of the tiles. See {@link #getParam(int)}.
+ */
+ public static final int TR_TILE_HEIGHT = 10;
+ /**
+ * The width of the border around the tiles. See {@link #getParam(int)}.
+ */
+ public static final int TR_TILE_BORDER = 11;
+ /**
+ * The tiles x-offset. See {@link #getParam(int)}.
+ */
+ public static final int TR_TILE_X_OFFSET = 12;
+ /**
+ * The tiles y-offset. See {@link #getParam(int)}.
+ */
+ public static final int TR_TILE_Y_OFFSET = 13;
+ /**
+ * The number of rows of tiles. See {@link #getParam(int)}.
+ */
+ public static final int TR_ROWS = 14;
+ /**
+ * The number of columns of tiles. See {@link #getParam(int)}.
+ */
+ public static final int TR_COLUMNS = 15;
+ /**
+ * The current tile number. Has value -1 if {@link #eot()}. See {@link #getParam(int)}.
+ */
+ public static final int TR_CURRENT_TILE_NUM = 16;
+ /**
+ * The current row number. See {@link #getParam(int)}.
+ */
+ public static final int TR_CURRENT_ROW = 17;
+ /**
+ * The current column number. See {@link #getParam(int)}.
+ */
+ public static final int TR_CURRENT_COLUMN = 18;
+ /**
+ * The order that the rows are traversed. See {@link #getParam(int)}.
+ */
+ public static final int TR_ROW_ORDER = 19;
+ /**
+ * Indicates we are traversing rows from the top to the bottom. See {@link #getParam(int)}.
+ */
+ public static final int TR_TOP_TO_BOTTOM = 20;
+ /**
+ * Indicates we are traversing rows from the bottom to the top (default). See {@link #getParam(int)}.
+ */
+ public static final int TR_BOTTOM_TO_TOP = 21;
+
+ private static final int DEFAULT_TILE_WIDTH = 256;
+ private static final int DEFAULT_TILE_HEIGHT = 256;
+ private static final int DEFAULT_TILE_BORDER = 0;
+
+ private final Dimension tileSize = new Dimension(DEFAULT_TILE_WIDTH, DEFAULT_TILE_HEIGHT);
+ private final Dimension tileSizeNB = new Dimension(DEFAULT_TILE_WIDTH - 2 * DEFAULT_TILE_BORDER, DEFAULT_TILE_HEIGHT - 2 * DEFAULT_TILE_BORDER);
+
+ private boolean isInit = false;
+ private Dimension imageClippingDim = null; // not set - default
+ private int tileBorder = DEFAULT_TILE_BORDER;
+ private int rowOrder = TR_BOTTOM_TO_TOP;
+ private int rows;
+ private int columns;
+ private int currentTile = 0;
+ private int currentRow;
+ private int currentColumn;
+ private int offsetX;
+ private int offsetY;
+
+ @Override
+ protected StringBuilder tileDetails(final StringBuilder sb) {
+ sb.append("# "+currentTile+": ["+currentColumn+"]["+currentRow+"] / "+columns+"x"+rows+", ")
+ .append("rowOrder "+rowOrder+", offset/size "+offsetX+"/"+offsetY+" "+tileSize.getWidth()+"x"+tileSize.getHeight()+" brd "+tileBorder+", ");
+ return super.tileDetails(sb);
+ }
+
+ /**
+ * Creates a new TileRenderer object
+ */
+ public TileRenderer() {
+ super();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Implementation {@link #reset()} internal states.
+ * </p>
+ */
+ @Override
+ public final void setImageSize(final int width, final int height) {
+ super.setImageSize(width, height);
+ reset();
+ }
+
+ /**
+ * Clips the image-size this tile-renderer iterates through,
+ * which can be retrieved via {@link #getClippedImageSize()}.
+ * <p>
+ * Original image-size stored in this tile-renderer is unmodified.
+ * </p>
+ * <p>
+ * Implementation {@link #reset()} internal states.
+ * </p>
+ *
+ * @param width The image-clipping.width
+ * @param height The image-clipping.height
+ * @see #getClippedImageSize()
+ */
+ public final void clipImageSize(final int width, final int height) {
+ if( null == imageClippingDim ) {
+ imageClippingDim = new Dimension(width, height);
+ } else {
+ imageClippingDim.set(width, height);
+ }
+ reset();
+ }
+
+ /**
+ * Returns the clipped image-size.
+ * <p>
+ * If a image-size is clipped via {@link #clipImageSize(int, int)},
+ * method returns:
+ * <ul>
+ * <li><code>min( image-clipping, image-size )</code>, otherwise</li>
+ * <li><code> image-size </code></li>
+ * </ul>
+ * </p>
+ * <p>
+ * The clipping width and height can be retrieved via {@link #TR_IMAGE_CLIPPING_WIDTH}
+ * {@link #TR_IMAGE_CLIPPING_HEIGHT}.
+ * </p>
+ */
+ public final DimensionImmutable getClippedImageSize() {
+ if( null != imageClippingDim ) {
+ return new Dimension(Math.min(imageClippingDim.getWidth(), imageSize.getWidth()),
+ Math.min(imageClippingDim.getHeight(), imageSize.getHeight()) );
+ } else {
+ return imageSize;
+ }
+ }
+
+ /**
+ * Sets the size of the tiles to use in rendering. The actual
+ * effective size of the tile depends on the border size, ie (
+ * width - 2*border ) * ( height - 2 * border )
+ * <p>
+ * Implementation {@link #reset()} internal states.
+ * </p>
+ *
+ * @param width
+ * The width of the tiles. Must not be larger than the GL
+ * context
+ * @param height
+ * The height of the tiles. Must not be larger than the
+ * GL context
+ * @param border
+ * The width of the borders on each tile. This is needed
+ * to avoid artifacts when rendering lines or points with
+ * thickness > 1.
+ */
+ public final void setTileSize(final int width, final int height, final int border) {
+ if( 0 > border ) {
+ throw new IllegalArgumentException("Tile border must be >= 0");
+ }
+ if( 2 * border >= width || 2 * border >= height ) {
+ throw new IllegalArgumentException("Tile size must be > 0x0 minus 2*border");
+ }
+ tileBorder = border;
+ tileSize.set( width, height );
+ tileSizeNB.set( width - 2 * border, height - 2 * border );
+ reset();
+ }
+
+ /**
+ * Sets an xy offset for the resulting tiles
+ * {@link TileRendererBase#TR_CURRENT_TILE_X_POS x-pos} and {@link TileRendererBase#TR_CURRENT_TILE_Y_POS y-pos}.
+ * @see #TR_TILE_X_OFFSET
+ * @see #TR_TILE_Y_OFFSET
+ **/
+ public void setTileOffset(final int xoff, final int yoff) {
+ offsetX = xoff;
+ offsetY = yoff;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Reset internal states of {@link TileRenderer} are:
+ * <ul>
+ * <li>{@link #TR_ROWS}</li>
+ * <li>{@link #TR_COLUMNS}</li>
+ * <li>{@link #TR_CURRENT_COLUMN}</li>
+ * <li>{@link #TR_CURRENT_ROW}</li>
+ * <li>{@link #TR_CURRENT_TILE_NUM}</li>
+ * <li>{@link #TR_CURRENT_TILE_X_POS}</li>
+ * <li>{@link #TR_CURRENT_TILE_Y_POS}</li>
+ * <li>{@link #TR_CURRENT_TILE_WIDTH}</li>
+ * <li>{@link #TR_CURRENT_TILE_HEIGHT}</li>
+ *</ul>
+ */
+ @Override
+ public final void reset() {
+ final DimensionImmutable clippedImageSize = getClippedImageSize();
+ columns = ( clippedImageSize.getWidth() + tileSizeNB.getWidth() - 1 ) / tileSizeNB.getWidth();
+ rows = ( clippedImageSize.getHeight() + tileSizeNB.getHeight() - 1 ) / tileSizeNB.getHeight();
+ currentRow = 0;
+ currentColumn = 0;
+ currentTile = 0;
+ currentTileXPos = 0;
+ currentTileYPos = 0;
+ currentTileWidth = 0;
+ currentTileHeight = 0;
+
+ assert columns >= 0;
+ assert rows >= 0;
+
+ beginCalled = false;
+ isInit = true;
+ }
+
+ /* pp */ final int getCurrentTile() { return currentTile; }
+
+ @Override
+ public final int getParam(final int pname) {
+ switch (pname) {
+ case TR_IMAGE_WIDTH:
+ return imageSize.getWidth();
+ case TR_IMAGE_HEIGHT:
+ return imageSize.getHeight();
+ case TR_CURRENT_TILE_X_POS:
+ return currentTileXPos;
+ case TR_CURRENT_TILE_Y_POS:
+ return currentTileYPos;
+ case TR_CURRENT_TILE_WIDTH:
+ return currentTileWidth;
+ case TR_CURRENT_TILE_HEIGHT:
+ return currentTileHeight;
+ case TR_IMAGE_CLIPPING_WIDTH:
+ return null != imageClippingDim ? imageClippingDim.getWidth() : 0;
+ case TR_IMAGE_CLIPPING_HEIGHT:
+ return null != imageClippingDim ? imageClippingDim.getHeight() : 0;
+ case TR_TILE_WIDTH:
+ return tileSize.getWidth();
+ case TR_TILE_HEIGHT:
+ return tileSize.getHeight();
+ case TR_TILE_BORDER:
+ return tileBorder;
+ case TR_TILE_X_OFFSET:
+ return offsetX;
+ case TR_TILE_Y_OFFSET:
+ return offsetY;
+ case TR_ROWS:
+ return rows;
+ case TR_COLUMNS:
+ return columns;
+ case TR_CURRENT_TILE_NUM:
+ return currentTile;
+ case TR_CURRENT_ROW:
+ return currentRow;
+ case TR_CURRENT_COLUMN:
+ return currentColumn;
+ case TR_ROW_ORDER:
+ return rowOrder;
+ default:
+ throw new IllegalArgumentException("Invalid pname: "+pname);
+ }
+ }
+
+ /**
+ * Sets the order of row traversal, default is {@link #TR_BOTTOM_TO_TOP}.
+ *
+ * @param order The row traversal order, must be either {@link #TR_TOP_TO_BOTTOM} or {@link #TR_BOTTOM_TO_TOP}.
+ */
+ public final void setRowOrder(final int order) {
+ if (order == TR_TOP_TO_BOTTOM || order == TR_BOTTOM_TO_TOP) {
+ rowOrder = order;
+ } else {
+ throw new IllegalArgumentException("Must pass TR_TOP_TO_BOTTOM or TR_BOTTOM_TO_TOP");
+ }
+ }
+
+ @Override
+ public final boolean isSetup() {
+ return 0 < imageSize.getWidth() && 0 < imageSize.getHeight();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * <i>end of tiling</i> is reached w/ {@link TileRenderer}, if at least one of the following is true:
+ * <ul>
+ * <li>all tiles have been rendered, i.e. {@link #TR_CURRENT_TILE_NUM} is -1</li>
+ * <li>no tiles to render, i.e. {@link #TR_COLUMNS} or {@link #TR_ROWS} is 0</li>
+ * </ul>
+ * </p>
+ */
+ @Override
+ public final boolean eot() {
+ if ( !isInit ) { // ensure at least one reset-call
+ reset();
+ }
+ return 0 > currentTile || 0 >= columns*rows;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws IllegalStateException if {@link #setImageSize(int, int) image-size} has not been set or
+ * {@link #eot() end-of-tiling} has been reached.
+ */
+ @Override
+ public final void beginTile( final GL gl ) throws IllegalStateException, GLException {
+ if( !isSetup() ) {
+ throw new IllegalStateException("Image size has not been set: "+this);
+ }
+ if ( eot() ) {
+ throw new IllegalStateException("EOT reached: "+this);
+ }
+ validateGL(gl);
+
+ /* which tile (by row and column) we're about to render */
+ if (rowOrder == TR_BOTTOM_TO_TOP) {
+ currentRow = currentTile / columns;
+ currentColumn = currentTile % columns;
+ } else {
+ currentRow = rows - ( currentTile / columns ) - 1;
+ currentColumn = currentTile % columns;
+ }
+ assert ( currentRow < rows );
+ assert ( currentColumn < columns );
+
+ final int border = tileBorder;
+
+ final DimensionImmutable clippedImageSize = getClippedImageSize();
+ int tH, tW;
+
+ /* Compute actual size of this tile with border */
+ if (currentRow < rows - 1) {
+ tH = tileSize.getHeight();
+ } else {
+ tH = clippedImageSize.getHeight() - ( rows - 1 ) * ( tileSizeNB.getHeight() ) + 2 * border;
+ }
+
+ if (currentColumn < columns - 1) {
+ tW = tileSize.getWidth();
+ } else {
+ tW = clippedImageSize.getWidth() - ( columns - 1 ) * ( tileSizeNB.getWidth() ) + 2 * border;
+ }
+
+ currentTileXPos = currentColumn * tileSizeNB.getWidth() + offsetX;
+ currentTileYPos = currentRow * tileSizeNB.getHeight() + offsetY;
+
+ /* Save tile size, with border */
+ currentTileWidth = tW;
+ currentTileHeight = tH;
+
+ gl.glViewport( 0, 0, tW, tH );
+
+ if( DEBUG ) {
+ System.err.println("TileRenderer.begin: "+this.toString());
+ }
+
+ // Do not forget to issue:
+ // reshape( 0, 0, tW, tH );
+ // which shall reflect tile renderer tiles: currentTileXPos, currentTileYPos and imageSize
+ beginCalled = true;
+ }
+
+ @Override
+ public void endTile( final GL gl ) throws IllegalStateException, GLException {
+ if( !beginCalled ) {
+ throw new IllegalStateException("beginTile(..) has not been called");
+ }
+ validateGL(gl);
+
+ // be sure OpenGL rendering is finished
+ gl.glFlush();
+
+ // implicitly save current glPixelStore values
+ psm.setPackAlignment(gl, 1);
+ final GL2ES3 gl2es3;
+ final int readBuffer;
+ if( gl.isGL2ES3() ) {
+ gl2es3 = gl.getGL2ES3();
+ readBuffer = gl2es3.getDefaultReadBuffer();
+ gl2es3.glReadBuffer(readBuffer);
+ } else {
+ gl2es3 = null;
+ readBuffer = 0; // undef. probably default: GL_FRONT (single buffering) GL_BACK (double buffering)
+ }
+ if( DEBUG ) {
+ System.err.println("TileRenderer.end.0: readBuffer 0x"+Integer.toHexString(readBuffer)+", "+this.toString());
+ }
+
+ final int tmp[] = new int[1];
+
+ if( tileBuffer != null ) {
+ final GLPixelAttributes pixelAttribs = tileBuffer.pixelAttributes;
+ final int srcX = tileBorder;
+ final int srcY = tileBorder;
+ final int srcWidth = tileSizeNB.getWidth();
+ final int srcHeight = tileSizeNB.getHeight();
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+ tileBuffer.clear();
+ if( tileBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
+ throw new IndexOutOfBoundsException("Required " + readPixelSize + " bytes of buffer, only had " + tileBuffer);
+ }
+ gl.glReadPixels( srcX, srcY, srcWidth, srcHeight, pixelAttribs.format, pixelAttribs.type, tileBuffer.buffer);
+ // be sure OpenGL rendering is finished
+ gl.glFlush();
+ tileBuffer.position( readPixelSize );
+ tileBuffer.flip();
+ }
+
+ if( imageBuffer != null ) {
+ final GLPixelAttributes pixelAttribs = imageBuffer.pixelAttributes;
+ final int srcX = tileBorder;
+ final int srcY = tileBorder;
+ final int srcWidth = currentTileWidth - 2 * tileBorder;
+ final int srcHeight = currentTileHeight - 2 * tileBorder;
+
+ /* setup pixel store for glReadPixels */
+ final int rowLength = imageSize.getWidth();
+ psm.setPackRowLength(gl2es3, rowLength);
+
+ /* read the tile into the final image */
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+
+ final int skipPixels = currentColumn * tileSizeNB.getWidth();
+ final int skipRows = currentRow * tileSizeNB.getHeight();
+ final int ibPos = ( skipPixels + ( skipRows * rowLength ) ) * pixelAttribs.bytesPerPixel;
+ final int ibLim = ibPos + readPixelSize;
+ imageBuffer.clear();
+ if( imageBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
+ throw new IndexOutOfBoundsException("Required " + ibLim + " bytes of buffer, only had " + imageBuffer);
+ }
+ imageBuffer.position(ibPos);
+
+ gl.glReadPixels( srcX, srcY, srcWidth, srcHeight, pixelAttribs.format, pixelAttribs.type, imageBuffer.buffer);
+ // be sure OpenGL rendering is finished
+ gl.glFlush();
+ imageBuffer.position( ibLim );
+ imageBuffer.flip();
+ }
+
+ /* restore previous glPixelStore values */
+ psm.restore(gl);
+
+ beginCalled = false;
+
+ /* increment tile counter, return 1 if more tiles left to render */
+ currentTile++;
+ if( currentTile >= rows * columns ) {
+ currentTile = -1; /* all done */
+ }
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
new file mode 100644
index 000000000..a1735766e
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
@@ -0,0 +1,664 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ *
+ * ---------------------
+ *
+ * Based on Brian Paul's tile rendering library, found
+ * at <a href = "http://www.mesa3d.org/brianp/TR.html">http://www.mesa3d.org/brianp/TR.html</a>.
+ *
+ * Copyright (C) 1997-2005 Brian Paul.
+ * Licensed under BSD-compatible terms with permission of the author.
+ * See LICENSE.txt for license information.
+ */
+package com.jogamp.opengl.util;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import jogamp.opengl.Debug;
+
+/**
+ * A fairly direct port of Brian Paul's tile rendering library, found
+ * at <a href = "http://www.mesa3d.org/brianp/TR.html">
+ * http://www.mesa3d.org/brianp/TR.html </a> . I've java-fied it, but
+ * the functionality is the same.
+ * <p>
+ * Original code Copyright (C) 1997-2005 Brian Paul. Licensed under
+ * BSD-compatible terms with permission of the author. See LICENSE.txt
+ * for license information.
+ * </p>
+ * <p>
+ * Enhanced for {@link GL} and {@link GL2ES3}, abstracted to suit {@link TileRenderer} and {@link RandomTileRenderer}.
+ * </p>
+ * <a name="pmvmatrix"><h5>PMV Matrix Considerations</h5></a>
+ * <p>
+ * The PMV matrix needs to be reshaped in user code
+ * after calling {@link #beginTile(GL)}, See {@link #beginTile(GL)}.
+ * </p>
+ * <p>
+ * If {@link #attachAutoDrawable(GLAutoDrawable) attaching to} an {@link GLAutoDrawable},
+ * the {@link TileRendererListener#reshapeTile(TileRendererBase, int, int, int, int, int, int)} method
+ * is being called after {@link #beginTile(GL)} for each rendered tile.
+ * It's implementation shall reshape the PMV matrix according to {@link #beginTile(GL)}.
+ * </p>
+ * <a name="glprequirement"><h5>GL Profile Requirement</h5></a>
+ * <p>
+ * Note that {@link #setImageBuffer(GLPixelBuffer) image buffer} can only be used
+ * in conjunction w/ a {@link GL} instance &ge; {@link GL2ES3} passed to {@link #beginTile(GL)} and {@link #endTile(GL)}.<br>
+ * This is due to setting up the {@link GL2ES3#GL_PACK_ROW_LENGTH pack row length}
+ * for an {@link #setImageSize(int, int) image width} != tile-width, which usually is the case.<br>
+ * Hence a {@link GLException} is thrown in both methods,
+ * if using an {@link #setImageBuffer(GLPixelBuffer) image buffer}
+ * and passing a {@link GL} instance &lt; {@link GL2ES3}.
+ * </p>
+ * <p>
+ * Further more, reading back of MSAA buffers is only supported since {@link GL2ES3}
+ * since it requires to set the {@link GL2ES3#glReadBuffer(int) read-buffer}.
+ * </p>
+ *
+ * @author ryanm, sgothel
+ */
+public abstract class TileRendererBase {
+ /**
+ * The width of the final image. See {@link #getParam(int)}.
+ */
+ public static final int TR_IMAGE_WIDTH = 1;
+ /**
+ * The height of the final image. See {@link #getParam(int)}.
+ */
+ public static final int TR_IMAGE_HEIGHT = 2;
+ /**
+ * The x-pos of the current tile. See {@link #getParam(int)}.
+ */
+ public static final int TR_CURRENT_TILE_X_POS = 3;
+ /**
+ * The y-pos of the current tile. See {@link #getParam(int)}.
+ */
+ public static final int TR_CURRENT_TILE_Y_POS = 4;
+ /**
+ * The width of the current tile. See {@link #getParam(int)}.
+ */
+ public static final int TR_CURRENT_TILE_WIDTH = 5;
+ /**
+ * The height of the current tile. See {@link #getParam(int)}.
+ */
+ public static final int TR_CURRENT_TILE_HEIGHT = 6;
+
+ /* pp */ static final boolean DEBUG = Debug.debug("TileRenderer");
+
+ /**
+ * Listener for tile renderer events, intended to extend {@link GLEventListener} implementations,
+ * enabling tile rendering via {@link TileRendererBase#attachAutoDrawable(GLAutoDrawable)}.
+ */
+ public static interface TileRendererListener {
+ /**
+ * The owning {@link GLAutoDrawable} is {@link TileRendererBase#attachAutoDrawable(GLAutoDrawable) attached}
+ * to the given {@link TileRendererBase} instance.
+ * <p>
+ * The {@link GLContext} of the {@link TileRendererBase}'s {@link TileRendererBase#getAttachedDrawable() attached} {@link GLAutoDrawable}
+ * <i>is not</i> current.
+ * </p>
+ * @param tr the associated {@link TileRendererBase}
+ * @see TileRendererBase#getAttachedDrawable()
+ */
+ public void addTileRendererNotify(TileRendererBase tr);
+
+ /**
+ * The owning {@link GLAutoDrawable} is {@link TileRendererBase#detachAutoDrawable() detached}
+ * from the given {@link TileRendererBase} instance.
+ * <p>
+ * The {@link GLContext} of the {@link TileRendererBase}'s {@link TileRendererBase#getAttachedDrawable() attached} {@link GLAutoDrawable}
+ * <i>is not</i> current.
+ * </p>
+ * @param tr the disassociated {@link TileRendererBase}
+ * @see TileRendererBase#getAttachedDrawable()
+ */
+ public void removeTileRendererNotify(TileRendererBase tr);
+
+ /**
+ * Called by the {@link TileRendererBase} during tile-rendering via an
+ * {@link TileRendererBase#getAttachedDrawable() attached} {@link GLAutoDrawable}'s
+ * {@link GLAutoDrawable#display()} call for each tile before {@link #display(GLAutoDrawable)}.
+ * <p>
+ * The <a href="TileRendererBase#pmvmatrix">PMV Matrix</a> shall be reshaped
+ * according to the given
+ * <ul>
+ * <li>current tile-position</li>
+ * <li>current tile-size</li>
+ * <li>final image-size</li>
+ * </ul>
+ * The GL viewport is already set to origin 0/0 and the current tile-size.<br>
+ * See details in {@link TileRendererBase#beginTile(GL)}.<br>
+ * </p>
+ * <p>
+ * The {@link GLContext} of the {@link TileRendererBase}'s {@link TileRendererBase#getAttachedDrawable() attached} {@link GLAutoDrawable}
+ * <i>is</i> current.
+ * </p>
+ * @param tr the issuing {@link TileRendererBase}
+ * @param tileX the {@link TileRendererBase#TR_CURRENT_TILE_X_POS current tile's x-pos}
+ * @param tileY the {@link TileRendererBase#TR_CURRENT_TILE_Y_POS current tile's y-pos}
+ * @param tileWidth the {@link TileRendererBase#TR_CURRENT_TILE_WIDTH current tile's width}
+ * @param tileHeight the {@link TileRendererBase#TR_CURRENT_TILE_HEIGHT current tile's height}
+ * @param imageWidth the {@link TileRendererBase#TR_IMAGE_WIDTH final image width}
+ * @param imageHeight the {@link TileRendererBase#TR_IMAGE_HEIGHT final image height}
+ * @see TileRendererBase#getAttachedDrawable()
+ */
+ public void reshapeTile(TileRendererBase tr,
+ int tileX, int tileY, int tileWidth, int tileHeight,
+ int imageWidth, int imageHeight);
+
+ /**
+ * Called by the {@link TileRendererBase} during tile-rendering
+ * after {@link TileRendererBase#beginTile(GL)} and before {@link #reshapeTile(TileRendererBase, int, int, int, int, int, int) reshapeTile(..)}.
+ * <p>
+ * If {@link TileRendererBase} is of type {@link TileRenderer},
+ * method is called for the first tile of all tiles.<br>
+ * Otherwise, i.e. {@link RandomTileRenderer}, method is called for each particular tile.
+ * </p>
+ * <p>
+ * The {@link GLContext} of the {@link TileRenderer}'s {@link TileRenderer#getAttachedDrawable() attached} {@link GLAutoDrawable}
+ * <i>is</i> current.
+ * </p>
+ * @param tr the issuing {@link TileRendererBase}
+ */
+ public void startTileRendering(TileRendererBase tr);
+
+ /**
+ * Called by the {@link TileRenderer} during tile-rendering
+ * after {@link TileRendererBase#endTile(GL)} and {@link GLAutoDrawable#swapBuffers()}.
+ * <p>
+ * If {@link TileRendererBase} is of type {@link TileRenderer},
+ * method is called for the last tile of all tiles.<br>
+ * Otherwise, i.e. {@link RandomTileRenderer}, method is called for each particular tile.
+ * </p>
+ * <p>
+ * The {@link GLContext} of the {@link TileRenderer}'s {@link TileRenderer#getAttachedDrawable() attached} {@link GLAutoDrawable}
+ * <i>is</i> current.
+ * </p>
+ * @param tr the issuing {@link TileRendererBase}
+ */
+ public void endTileRendering(TileRendererBase tr);
+ }
+
+ protected final Dimension imageSize = new Dimension(0, 0);
+ protected final GLPixelStorageModes psm = new GLPixelStorageModes();
+ protected GLPixelBuffer imageBuffer;
+ protected GLPixelBuffer tileBuffer;
+ protected boolean beginCalled = false;
+ protected int currentTileXPos;
+ protected int currentTileYPos;
+ protected int currentTileWidth;
+ protected int currentTileHeight;
+ protected GLAutoDrawable glad;
+ protected boolean gladRequiresPreSwap;
+ protected boolean gladAutoSwapBufferMode = true;
+ protected GLEventListener[] listeners;
+ protected boolean[] listenersInit;
+ protected GLEventListener glEventListenerPre = null;
+ protected GLEventListener glEventListenerPost = null;
+
+ private final String hashStr(final Object o) {
+ final int h = null != o ? o.hashCode() : 0;
+ return "0x"+Integer.toHexString(h);
+ }
+ protected StringBuilder tileDetails(final StringBuilder sb) {
+ return sb.append("cur "+currentTileXPos+"/"+currentTileYPos+" "+currentTileWidth+"x"+currentTileHeight+", buffer "+hashStr(tileBuffer));
+ }
+ public StringBuilder toString(final StringBuilder sb) {
+ final int gladListenerCount = null != listeners ? listeners.length : 0;
+ sb.append("tile[");
+ tileDetails(sb);
+ sb.append("], image[size "+imageSize+", buffer "+hashStr(imageBuffer)+"], glad["+
+ gladListenerCount+" listener, pre "+(null!=glEventListenerPre)+", post "+(null!=glEventListenerPost)+", preSwap "+gladRequiresPreSwap+"]");
+ sb.append(", isSetup "+isSetup());
+ return sb;
+ }
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ return getClass().getSimpleName()+
+ "["+toString(sb).toString()+"]";
+ }
+
+ protected TileRendererBase() {
+ }
+
+ /**
+ * Gets the parameters of this TileRenderer object
+ *
+ * @param pname The parameter name that is to be retrieved
+ * @return the value of the parameter
+ * @throws IllegalArgumentException if <code>pname</code> is not handled
+ */
+ public abstract int getParam(int pname) throws IllegalArgumentException;
+
+ /**
+ * Specify a buffer the tiles to be copied to. This is not
+ * necessary for the creation of the final image, but useful if you
+ * want to inspect each tile in turn.
+ *
+ * @param buffer The buffer itself. Must be large enough to contain a random tile
+ */
+ public final void setTileBuffer(final GLPixelBuffer buffer) {
+ tileBuffer = buffer;
+ if( DEBUG ) {
+ System.err.println("TileRenderer: tile-buffer "+tileBuffer);
+ }
+ }
+
+ /** @see #setTileBuffer(GLPixelBuffer) */
+ public final GLPixelBuffer getTileBuffer() { return tileBuffer; }
+
+ /**
+ * Sets the desired size of the final image
+ *
+ * @param width The width of the final image
+ * @param height The height of the final image
+ */
+ public void setImageSize(final int width, final int height) {
+ imageSize.set(width, height);
+ }
+
+ /** @see #setImageSize(int, int) */
+ public final DimensionImmutable getImageSize() { return imageSize; }
+
+ /**
+ * Sets the buffer in which to store the final image
+ *
+ * @param buffer the buffer itself, must be large enough to hold the final image
+ */
+ public final void setImageBuffer(final GLPixelBuffer buffer) {
+ imageBuffer = buffer;
+ if( DEBUG ) {
+ System.err.println("TileRenderer: image-buffer "+imageBuffer);
+ }
+ }
+
+ /** @see #setImageBuffer(GLPixelBuffer) */
+ public final GLPixelBuffer getImageBuffer() { return imageBuffer; }
+
+ /* pp */ final void validateGL(final GL gl) throws GLException {
+ if( imageBuffer != null && !gl.isGL2ES3()) {
+ throw new GLException("Using image-buffer w/ inssufficient GL context: "+gl.getContext().getGLVersion()+", "+gl.getGLProfile());
+ }
+ }
+
+ /**
+ * Returns true if this instance is setup properly, i.e. {@link #setImageSize(int, int)} ..,
+ * and ready for {@link #beginTile(GL)}.
+ * Otherwise returns false.
+ */
+ public abstract boolean isSetup();
+
+ /**
+ * Returns true if <i>end of tiling</i> has been reached, otherwise false.
+ * <p>
+ * <i>end of tiling</i> criteria is implementation specific and may never be reached.
+ * </p>
+ * <p>
+ * User needs to {@link #reset()} tiling after reaching <i>end of tiling</i>
+ * before calling {@link #beginTile(GL)} again.
+ * </p>
+ */
+ public abstract boolean eot();
+
+ /**
+ * Method resets implementation's internal state to <i>start of tiling</i>
+ * as required for {@link #beginTile(GL)} if {@link #eot() end of tiling} has been reached.
+ * <p>
+ * Implementation is a <i>nop</i> where {@link #eot() end of tiling} is never reached.
+ * </p>
+ */
+ public abstract void reset();
+
+ /**
+ * Begins rendering a tile.
+ * <p>
+ * This method modifies the viewport, see below.
+ * User shall reset the viewport when finishing all tile rendering,
+ * i.e. after very last call of {@link #endTile(GL)}!
+ * </p>
+ * <p>
+ * The <a href="TileRendererBase.html#pmvmatrix">PMV Matrix</a>
+ * must be reshaped after this call using:
+ * <ul>
+ * <li>Current Viewport
+ * <ul>
+ * <li>x 0</li>
+ * <li>y 0</li>
+ * <li>{@link #TR_CURRENT_TILE_WIDTH current tile's width}</li>
+ * <li>{@link #TR_CURRENT_TILE_HEIGHT current tile's height}</li>
+ * </ul></li>
+ * <li>{@link #TR_CURRENT_TILE_X_POS current tile's x-pos}</li>
+ * <li>{@link #TR_CURRENT_TILE_Y_POS current tile's y-pos}</li>
+ * <li>{@link #TR_IMAGE_WIDTH final image width}</li>
+ * <li>{@link #TR_IMAGE_HEIGHT final image height}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Use shall render the scene afterwards, concluded with a call to
+ * this renderer {@link #endTile(GL)}.
+ * </p>
+ * <p>
+ * User has to comply with the <a href="TileRendererBase.html#glprequirement">GL profile requirement</a>.
+ * </p>
+ * <p>
+ * If {@link #eot() end of tiling} has been reached,
+ * user needs to {@link #reset()} tiling before calling this method.
+ * </p>
+ *
+ * @param gl The gl context
+ * @throws IllegalStateException if {@link #setImageSize(int, int) image-size} is undefined,
+ * an {@link #isSetup() implementation related setup} has not be performed
+ * or {@ link #eot()} has been reached. See implementing classes.
+ * @throws GLException if {@link #setImageBuffer(GLPixelBuffer) image buffer} is used but <code>gl</code> instance is &lt; {@link GL2ES3}
+ * @see #isSetup()
+ * @see #eot()
+ * @see #reset()
+ */
+ public abstract void beginTile(GL gl) throws IllegalStateException, GLException;
+
+ /**
+ * Must be called after rendering the scene,
+ * see {@link #beginTile(GL)}.
+ * <p>
+ * Please consider {@link #reqPreSwapBuffers(GLCapabilitiesImmutable)} to determine
+ * whether you need to perform {@link GLDrawable#swapBuffers() swap-buffers} before or after
+ * calling this method!
+ * </p>
+ * <p>
+ * User has to comply with the <a href="TileRendererBase.html#glprequirement">GL profile requirement</a>.
+ * </p>
+ *
+ * @param gl the gl context
+ * @throws IllegalStateException if beginTile(gl) has not been called
+ * @throws GLException if {@link #setImageBuffer(GLPixelBuffer) image buffer} is used but <code>gl</code> instance is &lt; {@link GL2ES3}
+ */
+ public abstract void endTile( GL gl ) throws IllegalStateException, GLException;
+
+ /**
+ * Determines whether the chosen {@link GLCapabilitiesImmutable}
+ * requires a <i>pre-{@link GLDrawable#swapBuffers() swap-buffers}</i>
+ * before accessing the results, i.e. before {@link #endTile(GL)}.
+ * <p>
+ * See {@link GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable)}.
+ * </p>
+ */
+ public final boolean reqPreSwapBuffers(final GLCapabilitiesImmutable chosenCaps) {
+ return GLDrawableUtil.swapBuffersBeforeRead(chosenCaps);
+ }
+
+ /**
+ * Attaches the given {@link GLAutoDrawable} to this tile renderer.
+ * <p>
+ * The {@link GLAutoDrawable}'s original {@link GLEventListener} are moved to this tile renderer.
+ * </p>
+ * <p>
+ * {@link GLEventListeners} not implementing {@link TileRendererListener} are ignored while tile rendering.
+ * </p>
+ * <p>
+ * The {@link GLAutoDrawable}'s {@link GLAutoDrawable#getAutoSwapBufferMode() auto-swap mode} is cached
+ * and set to <code>false</code>, since {@link GLAutoDrawable#swapBuffers() swapBuffers()} maybe issued before {@link #endTile(GL)},
+ * see {@link #reqPreSwapBuffers(GLCapabilitiesImmutable)}.
+ * </p>
+ * <p>
+ * This tile renderer's internal {@link GLEventListener} is then added to the attached {@link GLAutoDrawable}
+ * to handle the tile rendering, replacing the original {@link GLEventListener}.<br>
+ * It's {@link GLEventListener#display(GLAutoDrawable) display} implementations issues:
+ * <ul>
+ * <li>Optional {@link #setGLEventListener(GLEventListener, GLEventListener) pre-glel}.{@link GLEventListener#display(GLAutoDrawable) display(..)}</li>
+ * <li>{@link #beginTile(GL)}</li>
+ * <li>for all original {@link TileRendererListener}:
+ * <ul>
+ * <li>{@link TileRendererListener#reshapeTile(TileRendererBase, int, int, int, int, int, int) reshapeTile(tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight)}</li>
+ * <li>{@link GLEventListener#display(GLAutoDrawable) display(autoDrawable)}</li>
+ * </ul></li>
+ * <li>if ( {@link #reqPreSwapBuffers(GLCapabilitiesImmutable) pre-swap} ) { {@link GLAutoDrawable#swapBuffers() swapBuffers()} }</li>
+ * <li>{@link #endTile(GL)}</li>
+ * <li>if ( !{@link #reqPreSwapBuffers(GLCapabilitiesImmutable) pre-swap} ) { {@link GLAutoDrawable#swapBuffers() swapBuffers()} }</li>
+ * <li>Optional {@link #setGLEventListener(GLEventListener, GLEventListener) post-glel}.{@link GLEventListener#display(GLAutoDrawable) display(..)}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Consider using {@link #setGLEventListener(GLEventListener, GLEventListener)} to add pre- and post
+ * hooks to be performed on this renderer {@link GLEventListener}.<br>
+ * The pre-hook is able to allocate memory and setup parameters, since it's called before {@link #beginTile(GL)}.<br>
+ * The post-hook is able to use the rendering result and can even shutdown tile-rendering,
+ * since it's called after {@link #endTile(GL)}.
+ * </p>
+ * <p>
+ * Call {@link #detachAutoDrawable()} to remove the attached {@link GLAutoDrawable} from this tile renderer
+ * and to restore it's original {@link GLEventListener}.
+ * </p>
+ * @param glad the {@link GLAutoDrawable} to attach.
+ * @throws IllegalStateException if an {@link GLAutoDrawable} is already attached
+ * @see #getAttachedDrawable()
+ * @see #detachAutoDrawable()
+ */
+ public final void attachAutoDrawable(final GLAutoDrawable glad) throws IllegalStateException {
+ if( null != this.glad ) {
+ throw new IllegalStateException("GLAutoDrawable already attached");
+ }
+ this.glad = glad;
+
+ final int aSz = glad.getGLEventListenerCount();
+ listeners = new GLEventListener[aSz];
+ listenersInit = new boolean[aSz];
+ for(int i=0; i<aSz; i++) {
+ final GLEventListener l = glad.getGLEventListener(0);
+ listenersInit[i] = glad.getGLEventListenerInitState(l);
+ listeners[i] = glad.removeGLEventListener( l );
+ final boolean trn;
+ if( listeners[i] instanceof TileRendererListener ) {
+ trn = true;
+ ((TileRendererListener)listeners[i]).addTileRendererNotify(this);
+ } else {
+ trn = false;
+ }
+ if( DEBUG ) {
+ System.err.println("TileRenderer.attach["+i+"]: isInit "+listenersInit[i]+", isTRN "+trn+", "+listeners[i].getClass().getName());
+ }
+ }
+ glad.addGLEventListener(tiledGLEL);
+ gladAutoSwapBufferMode = glad.getAutoSwapBufferMode();
+ gladRequiresPreSwap = this.reqPreSwapBuffers(glad.getChosenGLCapabilities());
+ glad.setAutoSwapBufferMode(false);
+ if( DEBUG ) {
+ System.err.println("TileRenderer: attached: "+glad);
+ System.err.println("TileRenderer: preSwap "+gladRequiresPreSwap+", "+glad.getChosenGLCapabilities()+", cached "+listeners.length+" listener");
+ }
+ }
+
+ /**
+ * Returns a previously {@link #attachAutoDrawable(GLAutoDrawable) attached} {@link GLAutoDrawable},
+ * <code>null</code> if none is attached.
+ * <p>
+ * If called from {@link TileRendererListener#addTileRendererNotify(TileRendererBase)}
+ * or {@link TileRendererListener#removeTileRendererNotify(TileRendererBase)}, method returns the
+ * just attached or soon to be detached {@link GLAutoDrawable}.
+ * </p>
+ * @see #attachAutoDrawable(GLAutoDrawable)
+ * @see #detachAutoDrawable()
+ */
+ public final GLAutoDrawable getAttachedDrawable() {
+ return glad;
+ }
+
+ /**
+ * Detaches the given {@link GLAutoDrawable} from this tile renderer.
+ * @see #attachAutoDrawable(GLAutoDrawable)
+ * @see #getAttachedDrawable()
+ */
+ public final void detachAutoDrawable() {
+ if( null != glad ) {
+ glad.removeGLEventListener(tiledGLEL);
+ final int aSz = listenersInit.length;
+ for(int i=0; i<aSz; i++) {
+ final GLEventListener l = listeners[i];
+ if( l instanceof TileRendererListener ) {
+ ((TileRendererListener)l).removeTileRendererNotify(this);
+ }
+ glad.addGLEventListener(l);
+ glad.setGLEventListenerInitState(l, listenersInit[i]);
+ }
+ glad.setAutoSwapBufferMode(gladAutoSwapBufferMode);
+ if( DEBUG ) {
+ System.err.println("TileRenderer: detached: "+glad);
+ System.err.println("TileRenderer: "+glad.getChosenGLCapabilities());
+ }
+
+ listeners = null;
+ listenersInit = null;
+ glad = null;
+ }
+ }
+
+ /**
+ * Set {@link GLEventListener} for pre- and post operations when used w/
+ * {@link #attachAutoDrawable(GLAutoDrawable)}
+ * for each {@link GLEventListener} callback.
+ * @param preTile the pre operations
+ * @param postTile the post operations
+ */
+ public final void setGLEventListener(final GLEventListener preTile, final GLEventListener postTile) {
+ glEventListenerPre = preTile;
+ glEventListenerPost = postTile;
+ }
+
+ /**
+ * Rendering one tile, by simply calling {@link GLAutoDrawable#display()}.
+ *
+ * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachAutoDrawable(GLAutoDrawable) attached}
+ * or imageSize is not set
+ */
+ public final void display() throws IllegalStateException {
+ if( null == glad ) {
+ throw new IllegalStateException("No GLAutoDrawable attached");
+ }
+ glad.display();
+ }
+
+ private final GLEventListener tiledGLEL = new GLEventListener() {
+ final TileRenderer tileRenderer = TileRendererBase.this instanceof TileRenderer ? (TileRenderer) TileRendererBase.this : null;
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ if( null != glEventListenerPre ) {
+ glEventListenerPre.init(drawable);
+ }
+ final int aSz = listenersInit.length;
+ for(int i=0; i<aSz; i++) {
+ final GLEventListener l = listeners[i];
+ if( !listenersInit[i] && l instanceof TileRendererListener ) {
+ l.init(drawable);
+ listenersInit[i] = true;
+ }
+ }
+ if( null != glEventListenerPost ) {
+ glEventListenerPost.init(drawable);
+ }
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( null != glEventListenerPre ) {
+ glEventListenerPre.dispose(drawable);
+ }
+ final int aSz = listenersInit.length;
+ for(int i=0; i<aSz; i++) { // dispose all GLEventListener, last chance!
+ listeners[i].dispose(drawable);
+ }
+ if( null != glEventListenerPost ) {
+ glEventListenerPost.dispose(drawable);
+ }
+ }
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ if( null != glEventListenerPre ) {
+ glEventListenerPre.reshape(drawable, 0, 0, currentTileWidth, currentTileHeight);
+ glEventListenerPre.display(drawable);
+ }
+ if( !isSetup() ) {
+ if( DEBUG ) {
+ System.err.println("TileRenderer.glel.display: !setup: "+TileRendererBase.this);
+ }
+ return;
+ }
+ if( eot() ) {
+ if( DEBUG ) {
+ System.err.println("TileRenderer.glel.display: EOT: "+TileRendererBase.this);
+ }
+ return;
+ }
+ final GL gl = drawable.getGL();
+
+ beginTile(gl);
+
+ final int aSz = listenersInit.length;
+ for(int i=0; i<aSz; i++) {
+ final GLEventListener l = listeners[i];
+ if( l instanceof TileRendererListener ) {
+ final TileRendererListener tl = (TileRendererListener)l;
+ if( null == tileRenderer || 0 == tileRenderer.getCurrentTile() ) {
+ tl.startTileRendering(TileRendererBase.this);
+ }
+ tl.reshapeTile(TileRendererBase.this,
+ currentTileXPos, currentTileYPos, currentTileWidth, currentTileHeight,
+ imageSize.getWidth(), imageSize.getHeight());
+ l.display(drawable);
+ }
+ }
+
+ if( gladRequiresPreSwap ) {
+ glad.swapBuffers();
+ endTile(gl);
+ } else {
+ endTile(gl);
+ glad.swapBuffers();
+ }
+ if( null == tileRenderer || tileRenderer.eot() ) {
+ for(int i=0; i<aSz; i++) {
+ final GLEventListener l = listeners[i];
+ if( l instanceof TileRendererListener ) {
+ ((TileRendererListener)l).endTileRendering(TileRendererBase.this);
+ }
+ }
+ }
+ if( null != glEventListenerPost ) {
+ glEventListenerPost.reshape(drawable, 0, 0, currentTileWidth, currentTileHeight);
+ glEventListenerPost.display(drawable);
+ }
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ };
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TimeFrameI.java b/src/jogl/classes/com/jogamp/opengl/util/TimeFrameI.java
new file mode 100644
index 000000000..99def6f5c
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/TimeFrameI.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util;
+
+/**
+ * Integer time frame in milliseconds, maybe specialized for texture/video, audio, .. animated content.
+ * <p>
+ * Type and value range has been chosen to suit embedded CPUs
+ * and characteristics of audio / video streaming and animations.
+ * Milliseconds of type integer with a maximum value of {@link Integer#MAX_VALUE}
+ * will allow tracking time up 2,147,483.647 seconds or
+ * 24 days 20 hours 31 minutes and 23 seconds.
+ * </p>
+ * <p>
+ * Milliseconds granularity is also more than enough to deal with A-V synchronization,
+ * where the threshold usually lies within 22ms.
+ * </p>
+ * <p>
+ * Milliseconds granularity for displaying video frames might seem inaccurate
+ * for each single frame, i.e. 60Hz != 16ms, however, accumulated values diminish
+ * this error and vertical sync is achieved by build-in V-Sync of the video drivers.
+ * </p>
+ */
+public class TimeFrameI {
+ /** Constant marking an invalid PTS, i.e. Integer.MIN_VALUE == 0x80000000 == {@value}. Sync w/ native code. */
+ public static final int INVALID_PTS = 0x80000000;
+
+ /** Constant marking the end of the stream PTS, i.e. Integer.MIN_VALUE - 1 == 0x7FFFFFFF == {@value}. Sync w/ native code. */
+ public static final int END_OF_STREAM_PTS = 0x7FFFFFFF;
+
+ protected int pts;
+ protected int duration;
+
+ public TimeFrameI() {
+ pts = INVALID_PTS;
+ duration = 0;
+ }
+ public TimeFrameI(final int pts, final int duration) {
+ this.pts = pts;
+ this.duration = duration;
+ }
+
+ /** Get this frame's presentation timestamp (PTS) in milliseconds. */
+ public final int getPTS() { return pts; }
+ /** Set this frame's presentation timestamp (PTS) in milliseconds. */
+ public final void setPTS(final int pts) { this.pts = pts; }
+ /** Get this frame's duration in milliseconds. */
+ public final int getDuration() { return duration; }
+ /** Set this frame's duration in milliseconds. */
+ public final void setDuration(final int duration) { this.duration = duration; }
+
+ @Override
+ public String toString() {
+ return "TimeFrame[pts " + pts + " ms, l " + duration + " ms]";
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/AudioSink.java b/src/jogl/classes/com/jogamp/opengl/util/av/AudioSink.java
new file mode 100644
index 000000000..fd6172e13
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/AudioSink.java
@@ -0,0 +1,436 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.av;
+
+import java.nio.ByteBuffer;
+
+import com.jogamp.opengl.util.TimeFrameI;
+
+import jogamp.opengl.Debug;
+
+public interface AudioSink {
+ public static final boolean DEBUG = Debug.debug("AudioSink");
+
+ /** Default frame duration in millisecond, i.e. 1 frame per {@value} ms. */
+ public static final int DefaultFrameDuration = 32;
+
+ /** Initial audio queue size in milliseconds. {@value} ms, i.e. 16 frames per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ public static final int DefaultInitialQueueSize = 16 * 32; // 512 ms
+ /** Audio queue grow size in milliseconds. {@value} ms, i.e. 16 frames per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ public static final int DefaultQueueGrowAmount = 16 * 32; // 512 ms
+ /** Audio queue limit w/ video in milliseconds. {@value} ms, i.e. 96 frames per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ public static final int DefaultQueueLimitWithVideo = 96 * 32; // 3072 ms
+ /** Audio queue limit w/o video in milliseconds. {@value} ms, i.e. 32 frames per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ public static final int DefaultQueueLimitAudioOnly = 32 * 32; // 1024 ms
+
+ /**
+ * Specifies the linear audio PCM format.
+ */
+ public static class AudioFormat {
+ /**
+ * @param sampleRate sample rate in Hz (1/s)
+ * @param sampleSize sample size in bits
+ * @param channelCount number of channels
+ * @param signed true if signed number, false for unsigned
+ * @param fixedP true for fixed point value, false for unsigned floating point value with a sampleSize of 32 (float) or 64 (double)
+ * @param planar true for planar data package (each channel in own data buffer), false for packed data channels interleaved in one buffer.
+ * @param littleEndian true for little-endian, false for big endian
+ */
+ public AudioFormat(final int sampleRate, final int sampleSize, final int channelCount, final boolean signed, final boolean fixedP, final boolean planar, final boolean littleEndian) {
+ this.sampleRate = sampleRate;
+ this.sampleSize = sampleSize;
+ this.channelCount = channelCount;
+ this.signed = signed;
+ this.fixedP = fixedP;
+ this.planar = planar;
+ this.littleEndian = littleEndian;
+ if( !fixedP ) {
+ if( sampleSize != 32 && sampleSize != 64 ) {
+ throw new IllegalArgumentException("Floating point: sampleSize "+sampleSize+" bits");
+ }
+ if( !signed ) {
+ throw new IllegalArgumentException("Floating point: unsigned");
+ }
+ }
+ }
+
+ /** Sample rate in Hz (1/s). */
+ public final int sampleRate;
+ /** Sample size in bits. */
+ public final int sampleSize;
+ /** Number of channels. */
+ public final int channelCount;
+ public final boolean signed;
+ /** Fixed or floating point values. Floating point 'float' has {@link #sampleSize} 32, 'double' has {@link #sampleSize} 64. */
+ public final boolean fixedP;
+ /** Planar or packed samples. If planar, each channel has their own data buffer. If packed, channel data is interleaved in one buffer. */
+ public final boolean planar;
+ public final boolean littleEndian;
+
+
+ //
+ // Time <-> Bytes
+ //
+
+ /**
+ * Returns the byte size of the given milliseconds
+ * according to {@link #sampleSize}, {@link #channelCount} and {@link #sampleRate}.
+ * <p>
+ * Time -> Byte Count
+ * </p>
+ */
+ public final int getDurationsByteSize(final int millisecs) {
+ final int bytesPerSample = sampleSize >>> 3; // /8
+ return millisecs * ( channelCount * bytesPerSample * ( sampleRate / 1000 ) );
+ }
+
+ /**
+ * Returns the duration in milliseconds of the given byte count
+ * according to {@link #sampleSize}, {@link #channelCount} and {@link #sampleRate}.
+ * <p>
+ * Byte Count -> Time
+ * </p>
+ */
+ public final int getBytesDuration(final int byteCount) {
+ final int bytesPerSample = sampleSize >>> 3; // /8
+ return byteCount / ( channelCount * bytesPerSample * ( sampleRate / 1000 ) );
+ }
+
+ /**
+ * Returns the duration in milliseconds of the given sample count per frame and channel
+ * according to the {@link #sampleRate}, i.e.
+ * <pre>
+ * ( 1000f * sampleCount ) / sampleRate
+ * </pre>
+ * <p>
+ * Sample Count -> Time
+ * </p>
+ * @param sampleCount sample count per frame and channel
+ */
+ public final float getSamplesDuration(final int sampleCount) {
+ return ( 1000f * sampleCount ) / sampleRate;
+ }
+
+ /**
+ * Returns the rounded frame count of the given milliseconds and frame duration.
+ * <pre>
+ * Math.max( 1, millisecs / frameDuration + 0.5f )
+ * </pre>
+ * <p>
+ * Note: <code>frameDuration</code> can be derived by <i>sample count per frame and channel</i>
+ * via {@link #getSamplesDuration(int)}.
+ * </p>
+ * <p>
+ * Frame Time -> Frame Count
+ * </p>
+ * @param millisecs time in milliseconds
+ * @param frameDuration duration per frame in milliseconds.
+ */
+ public final int getFrameCount(final int millisecs, final float frameDuration) {
+ return Math.max(1, (int) ( millisecs / frameDuration + 0.5f ));
+ }
+
+ /**
+ * Returns the byte size of given sample count
+ * according to the {@link #sampleSize}, i.e.:
+ * <pre>
+ * sampleCount * ( sampleSize / 8 )
+ * </pre>
+ * <p>
+ * Note: To retrieve the byte size for all channels,
+ * you need to pre-multiply <code>sampleCount</code> with {@link #channelCount}.
+ * </p>
+ * <p>
+ * Sample Count -> Byte Count
+ * </p>
+ * @param sampleCount sample count
+ */
+ public final int getSamplesByteCount(final int sampleCount) {
+ return sampleCount * ( sampleSize >>> 3 );
+ }
+
+ /**
+ * Returns the sample count of given byte count
+ * according to the {@link #sampleSize}, i.e.:
+ * <pre>
+ * ( byteCount * 8 ) / sampleSize
+ * </pre>
+ * <p>
+ * Note: If <code>byteCount</code> covers all channels and you request the sample size per channel,
+ * you need to divide the result by <code>sampleCount</code> by {@link #channelCount}.
+ * </p>
+ * <p>
+ * Byte Count -> Sample Count
+ * </p>
+ * @param byteCount number of bytes
+ */
+ public final int getBytesSampleCount(final int byteCount) {
+ return ( byteCount << 3 ) / sampleSize;
+ }
+
+ @Override
+ public String toString() {
+ return "AudioDataFormat[sampleRate "+sampleRate+", sampleSize "+sampleSize+", channelCount "+channelCount+
+ ", signed "+signed+", fixedP "+fixedP+", "+(planar?"planar":"packed")+", "+(littleEndian?"little":"big")+"-endian]"; }
+ }
+ /** Default {@link AudioFormat}, [type PCM, sampleRate 44100, sampleSize 16, channelCount 2, signed, fixedP, !planar, littleEndian]. */
+ public static final AudioFormat DefaultFormat = new AudioFormat(44100, 16, 2, true /* signed */,
+ true /* fixed point */, false /* planar */, true /* littleEndian */);
+
+ public static abstract class AudioFrame extends TimeFrameI {
+ protected int byteSize;
+
+ public AudioFrame() {
+ this.byteSize = 0;
+ }
+ public AudioFrame(final int pts, final int duration, final int byteCount) {
+ super(pts, duration);
+ this.byteSize=byteCount;
+ }
+
+ /** Get this frame's size in bytes. */
+ public final int getByteSize() { return byteSize; }
+ /** Set this frame's size in bytes. */
+ public final void setByteSize(final int size) { this.byteSize=size; }
+
+ @Override
+ public String toString() {
+ return "AudioFrame[pts " + pts + " ms, l " + duration + " ms, "+byteSize + " bytes]";
+ }
+ }
+ public static class AudioDataFrame extends AudioFrame {
+ protected final ByteBuffer data;
+
+ public AudioDataFrame(final int pts, final int duration, final ByteBuffer bytes, final int byteCount) {
+ super(pts, duration, byteCount);
+ if( byteCount > bytes.remaining() ) {
+ throw new IllegalArgumentException("Give size "+byteCount+" exceeds remaining bytes in ls "+bytes+". "+this);
+ }
+ this.data=bytes;
+ }
+
+ /** Get this frame's data. */
+ public final ByteBuffer getData() { return data; }
+
+ @Override
+ public String toString() {
+ return "AudioDataFrame[pts " + pts + " ms, l " + duration + " ms, "+byteSize + " bytes, " + data + "]";
+ }
+ }
+
+ /**
+ * Returns the <code>initialized state</code> of this instance.
+ * <p>
+ * The <code>initialized state</code> is affected by this instance
+ * overall availability, i.e. after instantiation,
+ * as well as by {@link #destroy()}.
+ * </p>
+ */
+ public boolean isInitialized();
+
+ /** Returns the playback speed. */
+ public float getPlaySpeed();
+
+ /**
+ * Sets the playback speed.
+ * <p>
+ * To simplify test, play speed is <i>normalized</i>, i.e.
+ * <ul>
+ * <li><code>1.0f</code>: if <code> Math.abs(1.0f - rate) < 0.01f </code></li>
+ * </ul>
+ * </p>
+ * @return true if successful, otherwise false, i.e. due to unsupported value range of implementation.
+ */
+ public boolean setPlaySpeed(float s);
+
+ /** Returns the volume. */
+ public float getVolume();
+
+ /**
+ * Sets the volume [0f..1f].
+ * <p>
+ * To simplify test, volume is <i>normalized</i>, i.e.
+ * <ul>
+ * <li><code>0.0f</code>: if <code> Math.abs(v) < 0.01f </code></li>
+ * <li><code>1.0f</code>: if <code> Math.abs(1.0f - v) < 0.01f </code></li>
+ * </ul>
+ * </p>
+ * @return true if successful, otherwise false, i.e. due to unsupported value range of implementation.
+ */
+ public boolean setVolume(float v);
+
+ /**
+ * Returns the preferred {@link AudioFormat} by this sink.
+ * <p>
+ * The preferred format is guaranteed to be supported
+ * and shall reflect this sinks most native format,
+ * i.e. best performance w/o data conversion.
+ * </p>
+ * <p>
+ * Known {@link #AudioFormat} attributes considered by implementations:
+ * <ul>
+ * <li>ALAudioSink: {@link AudioFormat#sampleRate}.
+ * </ul>
+ * </p>
+ * @see #initSink(AudioFormat)
+ * @see #isSupported(AudioFormat)
+ */
+ public AudioFormat getPreferredFormat();
+
+ /** Return the maximum number of supported channels. */
+ public int getMaxSupportedChannels();
+
+ /**
+ * Returns true if the given format is supported by the sink, otherwise false.
+ * @see #initSink(AudioFormat)
+ * @see #getPreferredFormat()
+ */
+ public boolean isSupported(AudioFormat format);
+
+ /**
+ * Initializes the sink.
+ * <p>
+ * Implementation must match the given <code>requestedFormat</code> {@link AudioFormat}.
+ * </p>
+ * <p>
+ * Caller shall validate <code>requestedFormat</code> via {@link #isSupported(AudioFormat)}
+ * beforehand and try to find a suitable supported one.
+ * {@link #getPreferredFormat()} and {@link #getMaxSupportedChannels()} may help.
+ * </p>
+ * @param requestedFormat the requested {@link AudioFormat}.
+ * @param frameDuration average or fixed frame duration in milliseconds
+ * helping a caching {@link AudioFrame} based implementation to determine the frame count in the queue.
+ * See {@link #DefaultFrameDuration}.
+ * @param initialQueueSize initial time in milliseconds to queue in this sink, see {@link #DefaultInitialQueueSize}.
+ * @param queueGrowAmount time in milliseconds to grow queue if full, see {@link #DefaultQueueGrowAmount}.
+ * @param queueLimit maximum time in milliseconds the queue can hold (and grow), see {@link #DefaultQueueLimitWithVideo} and {@link #DefaultQueueLimitAudioOnly}.
+ * @return true if successful, otherwise false
+ */
+ public boolean init(AudioFormat requestedFormat, float frameDuration,
+ int initialQueueSize, int queueGrowAmount, int queueLimit);
+
+ /**
+ * Returns the {@link AudioFormat} as chosen by {@link #init(AudioFormat, float, int, int, int)},
+ * i.e. it shall match the <i>requestedFormat</i>.
+ */
+ public AudioFormat getChosenFormat();
+
+ /**
+ * Returns true, if {@link #play()} has been requested <i>and</i> the sink is still playing,
+ * otherwise false.
+ */
+ public boolean isPlaying();
+
+ /**
+ * Play buffers queued via {@link #enqueueData(AudioFrame)} from current internal position.
+ * If no buffers are yet queued or the queue runs empty, playback is being continued when buffers are enqueued later on.
+ * @see #enqueueData(AudioFrame)
+ * @see #pause()
+ */
+ public void play();
+
+ /**
+ * Pause playing buffers while keeping enqueued data incl. it's internal position.
+ * @see #play()
+ * @see #flush()
+ * @see #enqueueData(AudioFrame)
+ */
+ public void pause();
+
+ /**
+ * Flush all queued buffers, implies {@link #pause()}.
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ * @see #play()
+ * @see #pause()
+ * @see #enqueueData(AudioFrame)
+ */
+ public void flush();
+
+ /** Destroys this instance, i.e. closes all streams and devices allocated. */
+ public void destroy();
+
+ /**
+ * Returns the number of allocated buffers as requested by
+ * {@link #init(AudioFormat, float, int, int, int)}.
+ */
+ public int getFrameCount();
+
+ /** @return the current enqueued frames count since {@link #init(AudioFormat, float, int, int, int)}. */
+ public int getEnqueuedFrameCount();
+
+ /**
+ * Returns the current number of frames queued for playing.
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ */
+ public int getQueuedFrameCount();
+
+ /**
+ * Returns the current number of bytes queued for playing.
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ */
+ public int getQueuedByteCount();
+
+ /**
+ * Returns the current queued frame time in milliseconds for playing.
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ */
+ public int getQueuedTime();
+
+ /**
+ * Return the current audio presentation timestamp (PTS) in milliseconds.
+ */
+ public int getPTS();
+
+ /**
+ * Returns the current number of frames in the sink available for writing.
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ */
+ public int getFreeFrameCount();
+
+ /**
+ * Enqueue <code>byteCount</code> bytes of the remaining bytes of the given NIO {@link ByteBuffer} to this sink.
+ * <p>
+ * The data must comply with the chosen {@link AudioFormat} as returned by {@link #initSink(AudioFormat)}.
+ * </p>
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ * @returns the enqueued internal {@link AudioFrame}.
+ */
+ public AudioFrame enqueueData(int pts, ByteBuffer bytes, int byteCount);
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/AudioSinkFactory.java b/src/jogl/classes/com/jogamp/opengl/util/av/AudioSinkFactory.java
new file mode 100644
index 000000000..a2b29b4eb
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/AudioSinkFactory.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.av;
+
+import jogamp.opengl.util.av.NullAudioSink;
+
+import com.jogamp.common.util.ReflectionUtil;
+
+public class AudioSinkFactory {
+ private static final String ALAudioSinkClazzName = "jogamp.opengl.openal.av.ALAudioSink";
+ private static final String JavaAudioSinkClazzName = "jogamp.opengl.util.av.JavaSoundAudioSink";
+
+ public static AudioSink createDefault() {
+ final ClassLoader cl = GLMediaPlayerFactory.class.getClassLoader();
+ AudioSink sink = create(cl, ALAudioSinkClazzName);
+ if( null == sink ) {
+ sink = create(cl, JavaAudioSinkClazzName);
+ }
+ if( null == sink ) {
+ sink = createNull();
+ }
+ return sink;
+ }
+ public static AudioSink createNull() {
+ return new NullAudioSink();
+ }
+
+ public static AudioSink create(final ClassLoader cl, final String implName) {
+ final AudioSink audioSink;
+ if(ReflectionUtil.isClassAvailable(implName, cl)){
+ try {
+ audioSink = (AudioSink) ReflectionUtil.createInstance(implName, cl);
+ if( audioSink.isInitialized() ) {
+ return audioSink;
+ }
+ } catch (final Throwable t) {
+ if(AudioSink.DEBUG) { System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage()); t.printStackTrace(); }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
index 3eca01986..2ad102235 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,181 +20,540 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.jogamp.opengl.util.av;
-import java.io.IOException;
-import java.net.URLConnection;
-
import javax.media.opengl.GL;
+import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import jogamp.opengl.Debug;
+import com.jogamp.common.net.Uri;
+import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureSequence;
+import com.jogamp.opengl.util.TimeFrameI;
/**
- * Lifecycle of an GLMediaPlayer:
+ * GLMediaPlayer interface specifies a {@link TextureSequence} state machine
+ * using a multiplexed audio/video stream as it's source.
+ * <p>
+ * Audio maybe supported and played back internally or via an {@link AudioSink} implementation.
+ * </p>
+ * <p>
+ * Audio and video streams can be selected or muted via {@link #initStream(Uri, int, int, int)}
+ * using the appropriate <a href="#streamIDs">stream id</a>'s.
+ * </p>
+ * <p>
+ * Camera input can be selected using the {@link #CameraInputScheme} Uri.
+ * </p>
+ *
+ * <a name="streamworker"><h5><i>StreamWorker</i> Decoding Thread</h5></a>
+ * <p>
+ * Most of the stream processing is performed on the decoding thread, a.k.a. <i>StreamWorker</i>:
+ * <ul>
+ * <li>Stream initialization triggered by {@link #initStream(Uri, int, int, int) initStream(..)} - User gets notified whether the stream has been initialized or not via {@link GLMediaEventListener#attributesChanged(GLMediaPlayer, int, long) attributesChanges(..)}.</li>
+ * <li>Stream decoding - User gets notified of a new frame via {@link GLMediaEventListener#newFrameAvailable(GLMediaPlayer, com.jogamp.opengl.util.texture.TextureSequence.TextureFrame, long) newFrameAvailable(...)}.</li>
+ * <li>Caught <a href="#streamerror">exceptions on the decoding thread</a> are delivered as {@link StreamException}s.</li>
+ * </ul>
+ * <i>StreamWorker</i> generates it's own {@link GLContext}, shared with the one passed to {@link #initGL(GL)}.
+ * The shared {@link GLContext} allows the decoding thread to push the video frame data directly into
+ * the designated {@link TextureFrame}, later returned via {@link #getNextTexture(GL)} and used by the user.
+ * </p>
+ * <a name="streamerror"><h7><i>StreamWorker</i> Error Handling</h7></a>
+ * <p>
+ * Caught exceptions on <a href="#streamworker">StreamWorker</a> are delivered as {@link StreamException}s,
+ * which either degrades the {@link State} to {@link State#Uninitialized} or {@link State#Paused}.
+ * </p>
+ * <p>
+ * An occurring {@link StreamException} triggers a {@link GLMediaEventListener#EVENT_CHANGE_ERR EVENT_CHANGE_ERR} event,
+ * which can be listened to via {@link GLMediaEventListener#attributesChanged(GLMediaPlayer, int, long)}.
+ * </p>
+ * <p>
+ * An occurred {@link StreamException} can be read via {@link #getStreamException()}.
+ * </p>
+ *
+ * </p>
+ * <a name="lifecycle"><h5>GLMediaPlayer Lifecycle</h5></a>
+ * <p>
+ * <table border="1">
+ * <tr><th>Action</th> <th>{@link State} Before</th> <th>{@link State} After</th> <th>{@link GLMediaEventListener Event}</th></tr>
+ * <tr><td>{@link #initStream(Uri, int, int, int)}</td> <td>{@link State#Uninitialized Uninitialized}</td> <td>{@link State#Initialized Initialized}<sup><a href="#streamworker">1</a></sup>, {@link State#Uninitialized Uninitialized}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_INIT EVENT_CHANGE_INIT} or ( {@link GLMediaEventListener#EVENT_CHANGE_ERR EVENT_CHANGE_ERR} + {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT} )</td></tr>
+ * <tr><td>{@link #initGL(GL)}</td> <td>{@link State#Initialized Initialized}</td> <td>{@link State#Paused Paused}, , {@link State#Uninitialized Uninitialized}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE} or ( {@link GLMediaEventListener#EVENT_CHANGE_ERR EVENT_CHANGE_ERR} + {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT} )</td></tr>
+ * <tr><td>{@link #play()}</td> <td>{@link State#Paused Paused}</td> <td>{@link State#Playing Playing}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_PLAY EVENT_CHANGE_PLAY}</td></tr>
+ * <tr><td>{@link #pause(boolean)}</td> <td>{@link State#Playing Playing}</td> <td>{@link State#Paused Paused}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE}</td></tr>
+ * <tr><td>{@link #seek(int)}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>none</td></tr>
+ * <tr><td>{@link #getNextTexture(GL)}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>none</td></tr>
+ * <tr><td>{@link #getLastTexture()}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>{@link State#Paused Paused}, {@link State#Playing Playing}</td> <td>none</td></tr>
+ * <tr><td>{@link TextureFrame#END_OF_STREAM_PTS END_OF_STREAM}</td> <td>{@link State#Playing Playing}</td> <td>{@link State#Paused Paused}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_EOS EVENT_CHANGE_EOS} + {@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE}</td></tr>
+ * <tr><td>{@link StreamException}</td> <td>ANY</td> <td>{@link State#Paused Paused}, {@link State#Uninitialized Uninitialized}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_ERR EVENT_CHANGE_ERR} + ( {@link GLMediaEventListener#EVENT_CHANGE_PAUSE EVENT_CHANGE_PAUSE} or {@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT} )</td></tr>
+ * <tr><td>{@link #destroy(GL)}</td> <td>ANY</td> <td>{@link State#Uninitialized Uninitialized}</td> <td>{@link GLMediaEventListener#EVENT_CHANGE_UNINIT EVENT_CHANGE_UNINIT}</td></tr>
+ * </table>
+ * </p>
+ *
+ * <a name="streamIDs"><h5>Audio and video Stream IDs</h5></a>
+ * <p>
* <table border="1">
- * <tr><th>action</th> <th>state before</th> <th>state after</th></tr>
- * <tr><td>{@link #initGLStream(GL, URLConnection)}</td> <td>Uninitialized</td> <td>Stopped</td></tr>
- * <tr><td>{@link #start()}</td> <td>Stopped, Paused</td> <td>Playing</td></tr>
- * <tr><td>{@link #stop()}</td> <td>Playing, Paused</td> <td>Stopped</td></tr>
- * <tr><td>{@link #pause()}</td> <td>Playing</td> <td>Paused</td></tr>
- * <tr><td>{@link #destroy(GL)}</td> <td>ANY</td> <td>Uninitialized</td></tr>
+ * <tr><th>value</th> <th>request</th> <th>get</th></tr>
+ * <tr><td>{@link #STREAM_ID_NONE}</td> <td>mute</td> <td>not available</td></tr>
+ * <tr><td>{@link #STREAM_ID_AUTO}</td> <td>auto</td> <td>unspecified</td></tr>
+ * <tr><td>&ge;0</td> <td>specific stream</td> <td>specific stream</td></tr>
* </table>
+ * </p>
* <p>
* Current implementations (check each API doc link for details):
* <ul>
* <li>{@link jogamp.opengl.util.av.NullGLMediaPlayer}</li>
* <li>{@link jogamp.opengl.util.av.impl.OMXGLMediaPlayer}</li>
* <li>{@link jogamp.opengl.util.av.impl.FFMPEGMediaPlayer}</li>
- * <li>{@link jogamp.opengl.android.av.AndroidGLMediaPlayerAPI14}</li>
+ * <li>{@link jogamp.opengl.android.av.AndroidGLMediaPlayerAPI14}</li>
* </ul>
* </p>
* <p>
- * Variable type, value range and dimension has been chosen to suit embedded CPUs
- * and characteristics of audio and video streaming.
- * Milliseconds of type integer with a maximum value of {@link Integer#MAX_VALUE}
- * will allow tracking time up 2,147,483.647 seconds or
- * 24 days 20 hours 31 minutes and 23 seconds.
- * Milliseconds granularity is also more than enough to deal with A-V synchronization,
- * where the threshold usually lies within 100ms.
+ * Implementations of this interface must implement:
+ * <pre>
+ * public static final boolean isAvailable();
+ * </pre>
+ * to be properly considered by {@link GLMediaPlayerFactory#create(ClassLoader, String)}
+ * and {@link GLMediaPlayerFactory#createDefault()}.
+ * </p>
+ * <a name="timestampaccuracy"><h5>Timestamp Accuracy</h5></a>
+ * <p>
+ * <p>
+ * Timestamp type and value range has been chosen to suit embedded CPUs
+ * and characteristics of audio and video streaming. See {@link TimeFrameI}.
+ * </p>
+ *
+ * <a name="synchronization"><h5>Audio and video synchronization</h5></a>
+ * <p>
+ * The class follows a passive A/V synchronization pattern.
+ * Audio is being untouched, while {@link #getNextTexture(GL)} delivers a new video frame
+ * only, if its timestamp is less than {@link #MAXIMUM_VIDEO_ASYNC} ahead of <i>time</i>.
+ * If its timestamp is more than {@link #MAXIMUM_VIDEO_ASYNC} ahead of <i>time</i>,
+ * the previous frame is returned.
+ * If its timestamp is more than {@link #MAXIMUM_VIDEO_ASYNC} after <i>time</i>,
+ * the frame is dropped and the next frame is being fetched.
+ * </p>
+ * <p>
+ * https://en.wikipedia.org/wiki/Audio_to_video_synchronization
+ * <pre>
+ * d_av = v_pts - a_pts;
+ * </pre>
+ * </p>
+ * <p>
+ * Recommendation of audio/video pts time lead/lag at production:
+ * <ul>
+ * <li>Overall: +40ms and -60ms audio ahead video / audio after video</li>
+ * <li>Each stage: +5ms and -15ms. audio ahead video / audio after video</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Recommendation of av pts time lead/lag at presentation:
+ * <ul>
+ * <li>TV: +15ms and -45ms. audio ahead video / audio after video.</li>
+ * <li>Film: +22ms and -22ms. audio ahead video / audio after video.</li>
+ * </ul>
+ * </p>
+ *
+ * <a name="teststreams"><h5>Test Streams</h5></a>
+ * <p>
+ * <table border="1">
+ * <tr><th colspan=5>Big Buck Bunny 24f 16:9</th></tr>
+ * <tr><td>Big Buck Bunny</td><td>320p</td><td>h264<td>aac 48000Hz 2 chan</td><td>http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4</td></tr>
+ * <tr><td>Big Buck Bunny</td><td>240p</td><td>h264<td>aac 48000Hz 2 chan</td><td>http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4</td></tr>
+ * <tr><td>Big Buck Bunny</td><td>720p</td><td>mpeg4<td>ac3 48000Hz 5.1 chan</td><td>http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_720p_surround.avi</td></tr>
+ * <tr><td>Big Buck Bunny</td><td>720p</td><td>msmpeg4v2<td>mp3 48000Hz 2 chan</td><td>http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_720p_stereo.avi</td></tr>
+ * <tr><td>Big Buck Bunny</td><td>720p</td><td>theora<td>vorbis 48000Hz 2 chan</td><td>http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_720p_stereo.ogg</td></tr>
+ * <tr><td>Big Buck Bunny</td><td>1080p</td><td>mpeg4<td>ac3 48000Hz 5.1 chan</td><td>http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_1080p_surround.avi</td></tr>
+ * <tr><th colspan=5>WebM/Matroska (vp8/vorbis)</th></tr>
+ * <tr><td>Big Buck Bunny Trailer</td><td>640p</td><td>vp8<td>vorbis 44100Hz 1 chan</td><td>http://video.webmfiles.org/big-buck-bunny_trailer.webm</td></tr>
+ * <tr><td>Elephants Dream</td><td>540p</td><td>vp8<td>vorbis 44100Hz 1 chan</td><td>http://video.webmfiles.org/elephants-dream.webm</td></tr>
+ * <tr><th colspan=5>You Tube http/rtsp</th></tr>
+ * <tr><td>Sintel</td><td colspan=3>http://www.youtube.com/watch?v=eRsGyueVLvQ</td><td>rtsp://v3.cache1.c.youtube.com/CiILENy73wIaGQn0LpXnygYbeRMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp</td></tr>
+ * <tr><th colspan=5>Audio/Video Sync</th></tr>
+ * <tr><td>Five-minute-sync-test1080p</td><td colspan=3>https://www.youtube.com/watch?v=szoOsG9137U</td><td>rtsp://v7.cache8.c.youtube.com/CiILENy73wIaGQm133VvsA46sxMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp</td></tr>
+ * <tr><td>Audio-Video-Sync-Test-Calibration-23.98fps-24fps</td><td colspan=4>https://www.youtube.com/watch?v=cGgf_dbDMsw</td></tr>
+ * <tr><td>sound_in_sync_test</td><td colspan=4>https://www.youtube.com/watch?v=O-zIZkhXNLE</td></tr>
+ * <!-- <tr><td> title </td><td>1080p</td><td>mpeg4<td>ac3 48000Hz 5.1 chan</td><td> url </td></tr> -->
+ * <!-- <tr><td> title </td><td colspan=3> url1 </td><td> url2 </td></tr>
+ * </table>
+ * </p>
+ * <p>
+ * Since 2.3.0 this interface uses {@link Uri} instead of {@link java.net.URI}.
* </p>
*/
public interface GLMediaPlayer extends TextureSequence {
public static final boolean DEBUG = Debug.debug("GLMediaPlayer");
-
+ public static final boolean DEBUG_NATIVE = Debug.debug("GLMediaPlayer.Native");
+
+ /** Default texture count, value {@value}. */
+ public static final int TEXTURE_COUNT_DEFAULT = 4;
+
+ /** Minimum texture count, value {@value}. Using the minimum texture count disables multi-threaded decoding. */
+ public static final int TEXTURE_COUNT_MIN = 1;
+
+ /** Constant {@value} for <i>mute</i> or <i>not available</i>. See <a href="#streamIDs">Audio and video Stream IDs</a>. */
+ public static final int STREAM_ID_NONE = -2;
+ /** Constant {@value} for <i>auto</i> or <i>unspecified</i>. See <a href="#streamIDs">Audio and video Stream IDs</a>. */
+ public static final int STREAM_ID_AUTO = -1;
+
+ /**
+ * {@link Uri#scheme Uri scheme} name {@value} for camera input. E.g. <code>camera:/0</code>
+ * for the 1st camera device.
+ * <p>
+ * The {@link Uri#path Uri path} is being used to identify the camera (<i>ID</i>),
+ * where the root fwd-slash is being cut-off.
+ * </p>
+ * <p>
+ * The <i>ID</i> is usually an integer value indexing the camera
+ * ranging from [0..<i>max-number</i>].
+ * </p>
+ * <p>
+ * The {@link Uri#query Uri query} is used to pass options to the camera
+ * using <i>;</i> as the separator. The latter avoids trouble w/ escaping.
+ * </p>
+ * <pre>
+ * camera:/<id>
+ * camera://somewhere/<id>
+ * camera://somewhere/<id>?width=640;height=480;rate=15
+ * camera://somewhere/<id>?size=640x480;rate=15
+ * </pre>
+ * <pre>
+ * Uri: [scheme:][//authority][path][?query][#fragment]
+ * w/ authority: [user-info@]host[:port]
+ * Note: 'path' starts w/ fwd slash
+ * </pre>
+ * </p>
+ */
+ public static final Uri.Encoded CameraInputScheme = Uri.Encoded.cast("camera");
+ /** Camera property {@value}, size as string, e.g. <code>1280x720</code>, <code>hd720</code>. May not be supported on all platforms. See {@link #CameraInputScheme}. */
+ public static final String CameraPropSizeS = "size";
+ /** Camera property {@value}. See {@link #CameraInputScheme}. */
+ public static final String CameraPropWidth = "width";
+ /** Camera property {@value}. See {@link #CameraInputScheme}. */
+ public static final String CameraPropHeight = "height";
+ /** Camera property {@value}. See {@link #CameraInputScheme}. */
+ public static final String CameraPropRate = "rate";
+
+ /** Maximum video frame async of {@value} milliseconds. */
+ public static final int MAXIMUM_VIDEO_ASYNC = 22;
+
+ /**
+ * A StreamException encapsulates a caught exception in the decoder thread, a.k.a <i>StreamWorker</i>,
+ * see See <a href="#streamerror"><i>StreamWorker</i> Error Handling</a>.
+ */
+ @SuppressWarnings("serial")
+ public static class StreamException extends Exception {
+ public StreamException(final Throwable cause) {
+ super(cause);
+ }
+ public StreamException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * As the contract of {@link TexSeqEventListener} requests,
+ * implementations of {@link GLMediaEventListener} shall also:
+ * <ul>
+ * <li>off-load complex or {@link GLMediaPlayer} commands on another thread, or</li>
+ * <li>simply changing a volatile state of their {@link GLEventListener} implementation.</li>
+ * </ul>
+ * </p>
+ */
public interface GLMediaEventListener extends TexSeqEventListener<GLMediaPlayer> {
-
- static final int EVENT_CHANGE_SIZE = 1<<0;
- static final int EVENT_CHANGE_FPS = 1<<1;
- static final int EVENT_CHANGE_BPS = 1<<2;
- static final int EVENT_CHANGE_LENGTH = 1<<3;
- static final int EVENT_CHANGE_CODEC = 1<<3;
-
+
+ /** State changed to {@link State#Initialized}. See <a href="#lifecycle">Lifecycle</a>.*/
+ static final int EVENT_CHANGE_INIT = 1<<0;
+ /** State changed to {@link State#Uninitialized}. See <a href="#lifecycle">Lifecycle</a>.*/
+ static final int EVENT_CHANGE_UNINIT = 1<<1;
+ /** State changed to {@link State#Playing}. See <a href="#lifecycle">Lifecycle</a>.*/
+ static final int EVENT_CHANGE_PLAY = 1<<2;
+ /** State changed to {@link State#Paused}. See <a href="#lifecycle">Lifecycle</a>.*/
+ static final int EVENT_CHANGE_PAUSE = 1<<3;
+ /** End of stream reached. See <a href="#lifecycle">Lifecycle</a>.*/
+ static final int EVENT_CHANGE_EOS = 1<<4;
+ /** An error occurred, e.g. during off-thread initialization. See {@link StreamException} and <a href="#lifecycle">Lifecycle</a>. */
+ static final int EVENT_CHANGE_ERR = 1<<5;
+
+ /** Stream video id change. */
+ static final int EVENT_CHANGE_VID = 1<<16;
+ /** Stream audio id change. */
+ static final int EVENT_CHANGE_AID = 1<<17;
+ /** TextureFrame size or vertical flip change. */
+ static final int EVENT_CHANGE_SIZE = 1<<18;
+ /** Stream fps change. */
+ static final int EVENT_CHANGE_FPS = 1<<19;
+ /** Stream bps change. */
+ static final int EVENT_CHANGE_BPS = 1<<20;
+ /** Stream length change. */
+ static final int EVENT_CHANGE_LENGTH = 1<<21;
+ /** Stream codec change. */
+ static final int EVENT_CHANGE_CODEC = 1<<22;
+
/**
- * @param mp the event source
+ * @param mp the event source
* @param event_mask the changes attributes
- * @param when system time in msec.
+ * @param when system time in msec.
*/
- public void attributesChanges(GLMediaPlayer mp, int event_mask, long when);
+ public void attributesChanged(GLMediaPlayer mp, int event_mask, long when);
}
-
+
+ /**
+ * See <a href="#lifecycle">Lifecycle</a>.
+ */
public enum State {
- Uninitialized(0), Stopped(1), Playing(2), Paused(3);
-
+ /** Uninitialized player, no resources shall be hold. */
+ Uninitialized(0),
+ /** Stream has been initialized, user may play or call {@link #initGL(GL)}. */
+ Initialized(1),
+ /** Stream is playing. */
+ Playing(2),
+ /** Stream is pausing. */
+ Paused(3);
+
public final int id;
- State(int id){
+ State(final int id){
this.id = id;
}
}
-
+
public int getTextureCount();
-
- /** Defaults to 0 */
+
+ /** Sets the texture unit. Defaults to 0. */
public void setTextureUnit(int u);
+
/** Sets the texture min-mag filter, defaults to {@link GL#GL_NEAREST}. */
public void setTextureMinMagFilter(int[] minMagFilter);
/** Sets the texture min-mag filter, defaults to {@link GL#GL_CLAMP_TO_EDGE}. */
public void setTextureWrapST(int[] wrapST);
-
- /**
- * Sets the stream to be used. Initializes all stream related states inclusive OpenGL ones,
- * if <code>gl</code> is not null.
- * <p>
- * Uninitialized -> Stopped
- * </p>
- * @param gl current GL object. If null, no video output and textures will be available.
- * @param urlConn the stream connection
- * @return the new state
- *
- * @throws IllegalStateException if not invoked in state Uninitialized
- * @throws IOException in case of difficulties to open or process the stream
+
+ /**
+ * Issues asynchronous stream initialization.
+ * <p>
+ * <a href="#lifecycle">Lifecycle</a>: {@link State#Uninitialized} -> {@link State#Initialized}<sup><a href="#streamworker">1</a></sup> or {@link State#Uninitialized}
+ * </p>
+ * <p>
+ * {@link State#Initialized} is reached asynchronous,
+ * i.e. user gets notified via {@link GLMediaEventListener#attributesChanged(GLMediaPlayer, int, long) attributesChanges(..)}.
+ * </p>
+ * <p>
+ * A possible caught asynchronous {@link StreamException} while initializing the stream off-thread
+ * will be thrown at {@link #initGL(GL)}.
+ * </p>
+ * <p>
+ * Muted audio can be achieved by passing {@link #STREAM_ID_NONE} to <code>aid</code>.
+ * </p>
+ * <p>
+ * Muted video can be achieved by passing {@link #STREAM_ID_NONE} to <code>vid</code>,
+ * in which case <code>textureCount</code> is ignored as well as the passed GL object of the subsequent {@link #initGL(GL)} call.
+ * </p>
+ * @param streamLoc the stream location
+ * @param vid video stream id, see <a href="#streamIDs">audio and video Stream IDs</a>
+ * @param aid video stream id, see <a href="#streamIDs">audio and video Stream IDs</a>
+ * @param textureCount desired number of buffered textures to be decoded off-thread, will be validated by implementation.
+ * The minimum value is {@link #TEXTURE_COUNT_DEFAULT}.
+ * Ignored if video is muted.
+ * @throws IllegalStateException if not invoked in {@link State#Uninitialized}
+ * @throws IllegalArgumentException if arguments are invalid
+ * @since 2.3.0
+ */
+ public void initStream(Uri streamLoc, int vid, int aid, int textureCount) throws IllegalStateException, IllegalArgumentException;
+
+ /**
+ * Returns the {@link StreamException} caught in the decoder thread, or <code>null</code> if none occured.
+ * <p>
+ * Method clears the cached {@link StreamException}, hence an immediate subsequent call will return <code>null</code>.
+ * </p>
+ * @see GLMediaEventListener#EVENT_CHANGE_ERR
+ * @see StreamException
+ */
+ public StreamException getStreamException();
+
+ /**
+ * Initializes OpenGL related resources.
+ * <p>
+ * <a href="#lifecycle">Lifecycle</a>: {@link State#Initialized} -> {@link State#Paused} or {@link State#Initialized}
+ * </p>
+ * Argument <code>gl</code> is ignored if video is muted, see {@link #initStream(Uri, int, int, int)}.
+ *
+ * @param gl current GL object. Maybe <code>null</code>, for audio only.
+ * @throws IllegalStateException if not invoked in {@link State#Initialized}.
+ * @throws StreamException forwarded from the off-thread stream initialization
* @throws GLException in case of difficulties to initialize the GL resources
*/
- public State initGLStream(GL gl, URLConnection urlConn) throws IllegalStateException, GLException, IOException;
-
+ public void initGL(GL gl) throws IllegalStateException, StreamException, GLException;
+
/**
- * Releases the GL and stream resources.
+ * If implementation uses a {@link AudioSink}, it's instance will be returned.
* <p>
- * <code>ANY</code> -> Uninitialized
+ * The {@link AudioSink} instance is available after {@link #initStream(Uri, int, int, int)},
+ * if used by implementation.
+ * </p>
+ */
+ public AudioSink getAudioSink();
+
+ /**
+ * Releases the GL, stream and other resources, including {@link #attachObject(String, Object) attached user objects}.
+ * <p>
+ * <a href="#lifecycle">Lifecycle</a>: <code>ANY</code> -> {@link State#Uninitialized}
* </p>
*/
public State destroy(GL gl);
- public void setPlaySpeed(float rate);
+ /**
+ * Sets the playback speed.
+ * <p>
+ * To simplify test, play speed is <i>normalized</i>, i.e.
+ * <ul>
+ * <li><code>1.0f</code>: if <code> Math.abs(1.0f - rate) < 0.01f </code></li>
+ * </ul>
+ * </p>
+ * @return true if successful, otherwise false, i.e. due to unsupported value range of implementation.
+ */
+ public boolean setPlaySpeed(float rate);
+ /** Returns the playback speed. */
public float getPlaySpeed();
/**
- * Stopped/Paused -> Playing
+ * Sets the audio volume, [0f..1f].
+ * <p>
+ * To simplify test, volume is <i>normalized</i>, i.e.
+ * <ul>
+ * <li><code>0.0f</code>: if <code> Math.abs(v) < 0.01f </code></li>
+ * <li><code>1.0f</code>: if <code> Math.abs(1.0f - v) < 0.01f </code></li>
+ * </ul>
+ * </p>
+ * @return true if successful, otherwise false, i.e. due to unsupported value range of implementation.
*/
- public State start();
+ public boolean setAudioVolume(float v);
+
+ /** Returns the audio volume. */
+ public float getAudioVolume();
/**
- * Playing -> Paused
+ * Starts or resumes the <i>StreamWorker</i> decoding thread.
+ * <p>
+ * <a href="#lifecycle">Lifecycle</a>: {@link State#Paused} -> {@link State#Playing}
+ * </p>
*/
- public State pause();
+ public State play();
/**
- * Playing/Paused -> Stopped
+ * Pauses the <i>StreamWorker</i> decoding thread.
+ * <p>
+ * <a href="#lifecycle">Lifecycle</a>: {@link State#Playing} -> {@link State#Paused}
+ * </p>
+ * <p>
+ * If a <i>new</i> frame is desired after the next {@link #play()} call,
+ * e.g. to make a snapshot of a camera input stream,
+ * <code>flush</code> shall be set to <code>true</code>.
+ * </p>
+ * @param flush if <code>true</code> flushes the video and audio buffers, otherwise keep them intact.
*/
- public State stop();
-
+ public State pause(boolean flush);
+
/**
- * @return the current state, either Uninitialized, Stopped, Playing, Paused
+ * Seeks to the new absolute position. The <i>StreamWorker</i> decoding thread
+ * is paused while doing so and the A/V buffers are flushed.
+ * <p>
+ * Allowed in state {@link State#Playing} and {@link State#Paused}, otherwise ignored,
+ * see <a href="#lifecycle">Lifecycle</a>.
+ * </p>
+ *
+ * @param msec absolute desired time position in milliseconds
+ * @return time current position in milliseconds, after seeking to the desired position
+ **/
+ public int seek(int msec);
+
+ /**
+ * See <a href="#lifecycle">Lifecycle</a>.
+ * @return the current state, either {@link State#Uninitialized}, {@link State#Initialized}, {@link State#Playing} or {@link State#Paused}
*/
public State getState();
-
+
/**
- * @return time current position in milliseconds
+ * Return the video stream id, see <a href="#streamIDs">audio and video Stream IDs</a>.
+ */
+ public int getVID();
+
+ /**
+ * Return the audio stream id, see <a href="#streamIDs">audio and video Stream IDs</a>.
+ */
+ public int getAID();
+
+ /**
+ * @return the current decoded frame count since {@link #play()} and {@link #seek(int)}
+ * as increased by {@link #getNextTexture(GL)} or the decoding thread.
+ */
+ public int getDecodedFrameCount();
+
+ /**
+ * @return the current presented frame count since {@link #play()} and {@link #seek(int)}
+ * as increased by {@link #getNextTexture(GL)} for new frames.
+ */
+ public int getPresentedFrameCount();
+
+ /**
+ * @return current video presentation timestamp (PTS) in milliseconds of {@link #getLastTexture()}
**/
- public int getCurrentPosition();
+ public int getVideoPTS();
/**
- * Allowed in state Stopped, Playing and Paused, otherwise ignored.
- *
- * @param msec absolute desired time position in milliseconds
- * @return time current position in milliseconds, after seeking to the desired position
+ * @return current audio presentation timestamp (PTS) in milliseconds.
**/
- public int seek(int msec);
+ public int getAudioPTS();
/**
* {@inheritDoc}
+ * <p>
+ * See <a href="#synchronization">audio and video synchronization</a>.
+ * </p>
+ * @throws IllegalStateException if not invoked in {@link State#Paused} or {@link State#Playing}
*/
@Override
public TextureSequence.TextureFrame getLastTexture() throws IllegalStateException;
/**
* {@inheritDoc}
- *
+ *
* <p>
* In case the current state is not {@link State#Playing}, {@link #getLastTexture()} is returned.
* </p>
- *
+ * <p>
+ * See <a href="#synchronization">audio and video synchronization</a>.
+ * </p>
+ * @throws IllegalStateException if not invoked in {@link State#Paused} or {@link State#Playing}
+ *
* @see #addEventListener(GLMediaEventListener)
- * @see GLMediaEventListener#newFrameAvailable(GLMediaPlayer, long)
+ * @see GLMediaEventListener#newFrameAvailable(GLMediaPlayer, TextureFrame, long)
*/
@Override
- public TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking) throws IllegalStateException;
-
- public URLConnection getURLConnection();
+ public TextureSequence.TextureFrame getNextTexture(GL gl) throws IllegalStateException;
+
+ /**
+ * Return the stream location, as set by {@link #initStream(Uri, int, int, int)}.
+ * @since 2.3.0
+ */
+ public Uri getUri();
/**
* <i>Warning:</i> Optional information, may not be supported by implementation.
- * @return the code of the video stream, if available
+ * @return the code of the video stream, if available
*/
public String getVideoCodec();
/**
* <i>Warning:</i> Optional information, may not be supported by implementation.
- * @return the code of the audio stream, if available
+ * @return the code of the audio stream, if available
*/
public String getAudioCodec();
@@ -202,47 +561,100 @@ public interface GLMediaPlayer extends TextureSequence {
* <i>Warning:</i> Optional information, may not be supported by implementation.
* @return the total number of video frames
*/
- public long getTotalFrames();
+ public int getVideoFrames();
+
+ /**
+ * <i>Warning:</i> Optional information, may not be supported by implementation.
+ * @return the total number of audio frames
+ */
+ public int getAudioFrames();
/**
* @return total duration of stream in msec.
*/
public int getDuration();
-
+
/**
* <i>Warning:</i> Optional information, may not be supported by implementation.
- * @return the overall bitrate of the stream.
+ * @return the overall bitrate of the stream.
*/
public long getStreamBitrate();
/**
* <i>Warning:</i> Optional information, may not be supported by implementation.
- * @return video bitrate
+ * @return video bitrate
*/
public int getVideoBitrate();
-
+
/**
* <i>Warning:</i> Optional information, may not be supported by implementation.
- * @return the audio bitrate
+ * @return the audio bitrate
*/
public int getAudioBitrate();
-
+
/**
* <i>Warning:</i> Optional information, may not be supported by implementation.
* @return the framerate of the video
*/
public float getFramerate();
+ /**
+ * Returns <code>true</code> if the video frame is oriented in
+ * OpenGL's coordinate system, <i>origin at bottom left</i>.
+ * <p>
+ * Otherwise returns <code>false</code>, i.e.
+ * video frame is oriented <i>origin at top left</i>.
+ * </p>
+ * <p>
+ * <code>false</code> is the default assumption for videos,
+ * but user shall not rely on.
+ * </p>
+ * <p>
+ * <code>false</code> GL orientation leads to
+ * {@link Texture#getMustFlipVertically()} == <code>true</code>,
+ * as reflected by all {@link TextureFrame}'s {@link Texture}s
+ * retrieved via {@link #getLastTexture()} or {@link #getNextTexture(GL)}.
+ * </p>
+ */
+ public boolean isGLOriented();
+
+ /** Returns the width of the video. */
public int getWidth();
+ /** Returns the height of the video. */
public int getHeight();
+ /** Returns a string represantation of this player, incl. state and audio/video details. */
+ @Override
public String toString();
+ /** Returns a string represantation of this player's performance values. */
+ public String getPerfString();
+
+ /** Adds a {@link GLMediaEventListener} to this player. */
public void addEventListener(GLMediaEventListener l);
+ /** Removes a {@link GLMediaEventListener} to this player. */
public void removeEventListener(GLMediaEventListener l);
- public GLMediaEventListener[] getEventListeners();
+ /** Return all {@link GLMediaEventListener} of this player. */
+ public GLMediaEventListener[] getEventListeners();
+
+ /**
+ * Returns the attached user object for the given name.
+ */
+ public Object getAttachedObject(String name);
+
+ /**
+ * Attaches the user object for the given name.
+ * Returns the previously set object, may be null.
+ */
+ public Object attachObject(String name, Object obj);
+
+ /**
+ * Detaches the user object for the given name.
+ * Returns the previously set object, may be null.
+ */
+ public Object detachObject(String name);
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayerFactory.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayerFactory.java
index 6fcf20ed2..9378cec91 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayerFactory.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayerFactory.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -29,27 +29,38 @@ package com.jogamp.opengl.util.av;
import jogamp.opengl.util.av.NullGLMediaPlayer;
-import com.jogamp.common.os.AndroidVersion;
-import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
public class GLMediaPlayerFactory {
private static final String AndroidGLMediaPlayerAPI14ClazzName = "jogamp.opengl.android.av.AndroidGLMediaPlayerAPI14";
private static final String FFMPEGMediaPlayerClazzName = "jogamp.opengl.util.av.impl.FFMPEGMediaPlayer";
+ private static final String OMXGLMediaPlayerClazzName = "jogamp.opengl.util.av.impl.OMXGLMediaPlayer";
private static final String isAvailableMethodName = "isAvailable";
-
- public static GLMediaPlayer create() {
+
+ public static GLMediaPlayer createDefault() {
final ClassLoader cl = GLMediaPlayerFactory.class.getClassLoader();
- if(Platform.OS_TYPE.equals(Platform.OSType.ANDROID)) {
- if(AndroidVersion.SDK_INT >= 14) {
- if(((Boolean)ReflectionUtil.callStaticMethod(AndroidGLMediaPlayerAPI14ClazzName, isAvailableMethodName, null, null, cl)).booleanValue()) {
- return (GLMediaPlayer) ReflectionUtil.createInstance(AndroidGLMediaPlayerAPI14ClazzName, cl);
- }
- }
+ GLMediaPlayer sink = create(cl, OMXGLMediaPlayerClazzName);
+ if( null == sink ) {
+ sink = create(cl, AndroidGLMediaPlayerAPI14ClazzName);
}
- if(((Boolean)ReflectionUtil.callStaticMethod(FFMPEGMediaPlayerClazzName, isAvailableMethodName, null, null, cl)).booleanValue()) {
- return (GLMediaPlayer) ReflectionUtil.createInstance(FFMPEGMediaPlayerClazzName, cl);
+ if( null == sink ) {
+ sink = create(cl, FFMPEGMediaPlayerClazzName);
}
+ if( null == sink ) {
+ sink = createNull();
+ }
+ return sink;
+ }
+ public static GLMediaPlayer createNull() {
return new NullGLMediaPlayer();
}
+
+ public static GLMediaPlayer create(final ClassLoader cl, final String implName) {
+ try {
+ if(((Boolean)ReflectionUtil.callStaticMethod(implName, isAvailableMethodName, null, null, cl)).booleanValue()) {
+ return (GLMediaPlayer) ReflectionUtil.createInstance(implName, cl);
+ }
+ } catch (final Throwable t) { if(GLMediaPlayer.DEBUG) { System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage()); t.printStackTrace(); } }
+ return null;
+ }
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
new file mode 100644
index 000000000..04bc0a15d
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
@@ -0,0 +1,249 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.awt;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferInt;
+import java.awt.image.Raster;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.awt.image.WritableRaster;
+import java.nio.Buffer;
+import java.nio.IntBuffer;
+
+import javax.media.opengl.GL;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.GLPixelBuffer;
+
+/**
+ * AWT {@link GLPixelBuffer} backed by an {@link BufferedImage} of type
+ * {@link BufferedImage#TYPE_INT_ARGB} or {@link BufferedImage#TYPE_INT_RGB}.
+ * <p>
+ * Implementation uses an array backed {@link IntBuffer}.
+ * </p>
+ * <p>
+ * {@link AWTGLPixelBuffer} can be produced via {@link AWTGLPixelBufferProvider}'s
+ * {@link AWTGLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocate(..)}.
+ * </p>
+ * <p>
+ * See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)} for {@link #allowRowStride} details.
+ * </p>
+ * <p>
+ * If using <code>allowRowStride == true</code>, user may needs to get the {@link #getAlignedImage(int, int) aligned image}
+ * since {@link #requiresNewBuffer(GL, int, int, int)} will allow different width in this case.
+ * </p>
+ */
+public class AWTGLPixelBuffer extends GLPixelBuffer {
+ public static final GLPixelAttributes awtPixelAttributesIntRGBA4 = new GLPixelAttributes(4, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
+ public static final GLPixelAttributes awtPixelAttributesIntRGB3 = new GLPixelAttributes(3, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
+
+ /** The underlying {@link BufferedImage}. */
+ public final BufferedImage image;
+
+ /**
+ *
+ * @param pixelAttributes the desired {@link GLPixelAttributes}
+ * @param width in pixels
+ * @param height in pixels
+ * @param depth in pixels
+ * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
+ * @param image the AWT image
+ * @param buffer the backing array
+ * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link #requiresNewBuffer(GL, int, int, int)}.
+ * If <code>true</code>, user shall decide whether to use a {@link #getAlignedImage(int, int) width-aligned image}.
+ */
+ public AWTGLPixelBuffer(final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final BufferedImage image,
+ final Buffer buffer, final boolean allowRowStride) {
+ super(pixelAttributes, width, height, depth, pack, buffer, allowRowStride);
+ this.image = image;
+ }
+
+ @Override
+ public void dispose() {
+ image.flush();
+ super.dispose();
+ }
+
+ /**
+ * Returns a width- and height-aligned image representation sharing data w/ {@link #image}.
+ * @param width
+ * @param height
+ * @return
+ * @throws IllegalArgumentException if requested size exceeds image size
+ */
+ public BufferedImage getAlignedImage(final int width, final int height) throws IllegalArgumentException {
+ if( width * height > image.getWidth() * image.getHeight() ) {
+ throw new IllegalArgumentException("Requested size exceeds image size: "+width+"x"+height+" > "+image.getWidth()+"x"+image.getHeight());
+ }
+ if( width == image.getWidth() && height == image.getHeight() ) {
+ return image;
+ } else {
+ final ColorModel cm = image.getColorModel();
+ final WritableRaster raster0 = image.getRaster();
+ final DataBuffer dataBuffer = raster0.getDataBuffer();
+ final SinglePixelPackedSampleModel sppsm0 = (SinglePixelPackedSampleModel) raster0.getSampleModel();
+ final SinglePixelPackedSampleModel sppsm1 = new SinglePixelPackedSampleModel(dataBuffer.getDataType(),
+ width, height, width /* scanLineStride */, sppsm0.getBitMasks());
+ final WritableRaster raster1 = Raster.createWritableRaster(sppsm1, dataBuffer, null);
+ return new BufferedImage (cm, raster1, cm.isAlphaPremultiplied(), null);
+ }
+ }
+
+ public final boolean isDataBufferSource(final BufferedImage imageU) {
+ final DataBuffer dataBuffer0 = image.getRaster().getDataBuffer();
+ final DataBuffer dataBufferU = imageU.getRaster().getDataBuffer();
+ return dataBufferU == dataBuffer0;
+ }
+
+ @Override
+ public StringBuilder toString(StringBuilder sb) {
+ sb = super.toString(sb);
+ sb.append(", allowRowStride ").append(allowRowStride).append(", image [").append(image.getWidth()).append("x").append(image.getHeight()).append(", ").append(image.toString()).append("]");
+ return sb;
+ }
+ @Override
+ public String toString() {
+ return "AWTGLPixelBuffer["+toString(null).toString()+"]";
+ }
+
+ /**
+ * Provider for {@link AWTGLPixelBuffer} instances.
+ */
+ public static class AWTGLPixelBufferProvider implements GLPixelBufferProvider {
+ private final boolean allowRowStride;
+
+ /**
+ * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not.
+ * See {@link #getAllowRowStride()} and {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+ * If <code>true</code>, user shall decide whether to use a {@link AWTGLPixelBuffer#getAlignedImage(int, int) width-aligned image}.
+ */
+ public AWTGLPixelBufferProvider(final boolean allowRowStride) {
+ this.allowRowStride = allowRowStride;
+ }
+ @Override
+ public boolean getAllowRowStride() { return allowRowStride; }
+
+ @Override
+ public GLPixelAttributes getAttributes(final GL gl, final int componentCount) {
+ return 4 == componentCount ? awtPixelAttributesIntRGBA4 : awtPixelAttributesIntRGB3;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns an array backed {@link IntBuffer} of size <pre>width*height*{@link Buffers#SIZEOF_INT SIZEOF_INT}</code>.
+ * </p>
+ */
+ @Override
+ public AWTGLPixelBuffer allocate(final GL gl, final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
+ final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+ final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+ final Buffer ibuffer = IntBuffer.wrap( readBackIntBuffer );
+ return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, allowRowStride);
+ }
+ }
+
+ /**
+ * Provider for singleton {@link AWTGLPixelBuffer} instances.
+ * <p>
+ * Provider instance holds the last {@link AWTGLPixelBuffer} instance
+ * {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+ * A new {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocation}
+ * will return same instance, if a new buffer is not {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int) required}.
+ * The latter is true if size are compatible, hence <code>allowRowStride</code> should be enabled, if possible.
+ * </p>
+ */
+ public static class SingleAWTGLPixelBufferProvider extends AWTGLPixelBufferProvider implements SingletonGLPixelBufferProvider {
+ private AWTGLPixelBuffer singleRGBA4 = null;
+ private AWTGLPixelBuffer singleRGB3 = null;
+
+ /**
+ * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+ */
+ public SingleAWTGLPixelBufferProvider(final boolean allowRowStride) {
+ super(allowRowStride);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns an array backed {@link IntBuffer} of size <pre>width*height*{@link Buffers#SIZEOF_INT SIZEOF_INT}</code>.
+ * </p>
+ */
+ @Override
+ public AWTGLPixelBuffer allocate(final GL gl, final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
+ if( 4 == pixelAttributes.componentCount ) {
+ if( null == singleRGBA4 || singleRGBA4.requiresNewBuffer(gl, width, height, minByteSize) ) {
+ singleRGBA4 = allocateImpl(pixelAttributes, width, height, depth, pack, minByteSize);
+ }
+ return singleRGBA4;
+ } else {
+ if( null == singleRGB3 || singleRGB3.requiresNewBuffer(gl, width, height, minByteSize) ) {
+ singleRGB3 = allocateImpl(pixelAttributes, width, height, depth, pack, minByteSize);
+ }
+ return singleRGB3;
+ }
+ }
+
+ private AWTGLPixelBuffer allocateImpl(final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
+ final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+ final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+ final Buffer ibuffer = IntBuffer.wrap( readBackIntBuffer );
+ return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, getAllowRowStride());
+ }
+
+ /** Return the last {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated} {@link AWTGLPixelBuffer} w/ {@link GLPixelAttributes#componentCount}. */
+ @Override
+ public AWTGLPixelBuffer getSingleBuffer(final GLPixelAttributes pixelAttributes) {
+ return 4 == pixelAttributes.componentCount ? singleRGBA4 : singleRGB3;
+ }
+
+ /**
+ * Initializes the single {@link AWTGLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+ * @return the newly initialized single {@link AWTGLPixelBuffer}, or null if already allocated.
+ */
+ @Override
+ public AWTGLPixelBuffer initSingleton(final int componentCount, final int width, final int height, final int depth, final boolean pack) {
+ if( 4 == componentCount ) {
+ if( null != singleRGBA4 ) {
+ return null;
+ }
+ singleRGBA4 = allocateImpl(AWTGLPixelBuffer.awtPixelAttributesIntRGBA4, width, height, depth, pack, 0);
+ return singleRGBA4;
+ } else {
+ if( null != singleRGB3 ) {
+ return null;
+ }
+ singleRGB3 = allocateImpl(AWTGLPixelBuffer.awtPixelAttributesIntRGB3, width, height, depth, pack, 0);
+ return singleRGB3;
+ }
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
new file mode 100644
index 000000000..b75ad3b17
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.awt;
+
+import java.awt.image.BufferedImage;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.GLReadBufferUtil;
+
+/**
+ * {@link GLReadBufferUtil} specialization allowing to
+ * read out a frambuffer to an AWT BufferedImage
+ * utilizing {@link AWTPixelBufferProviderInt} for further AWT processing.
+ */
+public class AWTGLReadBufferUtil extends GLReadBufferUtil {
+ /**
+ * {@inheritDoc}
+ *
+ * @param alpha
+ */
+ public AWTGLReadBufferUtil(final GLProfile glp, final boolean alpha) {
+ super(new AWTGLPixelBuffer.AWTGLPixelBufferProvider( glp.isGL2ES3() /* allowRowStride */ ), alpha, false);
+ }
+
+ /**
+ * Returns the {@link AWTGLPixelBuffer}, as filled by previous call to {@link #readPixels(GL, int, int, int, int, boolean)}.
+ */
+ public AWTGLPixelBuffer getAWTGLPixelBuffer() { return (AWTGLPixelBuffer)this.getPixelBuffer(); }
+
+ /**
+ * Read the drawable's pixels to TextureData and Texture, if requested at construction,
+ * and returns an aligned {@link BufferedImage}.
+ *
+ * @param gl the current GL context object. It's read drawable is being used as the pixel source.
+ * @param awtOrientation flips the data vertically if <code>true</code>.
+ * The context's drawable {@link GLDrawable#isGLOriented()} state
+ * is taken into account.
+ * Vertical flipping is propagated to TextureData
+ * and handled in a efficient manner there (TextureCoordinates and TextureIO writer).
+ * @see #AWTGLReadBufferUtil(GLProfile, boolean)
+ */
+ public BufferedImage readPixelsToBufferedImage(final GL gl, final boolean awtOrientation) {
+ return readPixelsToBufferedImage(gl, 0, 0, 0, 0, awtOrientation);
+ }
+
+ /**
+ * Read the drawable's pixels to TextureData and Texture, if requested at construction,
+ * and returns an aligned {@link BufferedImage}.
+ *
+ * @param gl the current GL context object. It's read drawable is being used as the pixel source.
+ * @param inX readPixel x offset
+ * @param inY readPixel y offset
+ * @param inWidth optional readPixel width value, used if [1 .. drawable.width], otherwise using drawable.width
+ * @param inHeight optional readPixel height, used if [1 .. drawable.height], otherwise using drawable.height
+ * @param awtOrientation flips the data vertically if <code>true</code>.
+ * The context's drawable {@link GLDrawable#isGLOriented()} state
+ * is taken into account.
+ * Vertical flipping is propagated to TextureData
+ * and handled in a efficient manner there (TextureCoordinates and TextureIO writer).
+ * @see #AWTGLReadBufferUtil(GLProfile, boolean)
+ */
+ public BufferedImage readPixelsToBufferedImage(final GL gl, final int inX, final int inY, final int inWidth, final int inHeight, final boolean awtOrientation) {
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ final int width, height;
+ if( 0 >= inWidth || drawable.getSurfaceWidth() < inWidth ) {
+ width = drawable.getSurfaceWidth();
+ } else {
+ width = inWidth;
+ }
+ if( 0 >= inHeight || drawable.getSurfaceHeight() < inHeight ) {
+ height = drawable.getSurfaceHeight();
+ } else {
+ height= inHeight;
+ }
+ if( readPixelsImpl(drawable, gl, inX, inY, width, height, awtOrientation) ) {
+ final BufferedImage image = getAWTGLPixelBuffer().getAlignedImage(width, height);
+ if( getTextureData().getMustFlipVertically() ) {
+ ImageUtil.flipImageVertically(image);
+ }
+ return image;
+ }
+ return null;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/ImageUtil.java b/src/jogl/classes/com/jogamp/opengl/util/awt/ImageUtil.java
index a3139b16a..4023a06f0 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/ImageUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/ImageUtil.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -50,11 +50,11 @@ public class ImageUtil {
/** Flips the supplied BufferedImage vertically. This is often a
necessary conversion step to display a Java2D image correctly
with OpenGL and vice versa. */
- public static void flipImageVertically(BufferedImage image) {
- WritableRaster raster = image.getRaster();
+ public static void flipImageVertically(final BufferedImage image) {
+ final WritableRaster raster = image.getRaster();
Object scanline1 = null;
Object scanline2 = null;
-
+
for (int i = 0; i < image.getHeight() / 2; i++) {
scanline1 = raster.getDataElements(0, i, image.getWidth(), 1, scanline1);
scanline2 = raster.getDataElements(0, image.getHeight() - i - 1, image.getWidth(), 1, scanline2);
@@ -73,8 +73,8 @@ public class ImageUtil {
*
* @return A instance of <code>BufferedImage</code> with a type compatible with the graphics card.
*/
- public static BufferedImage createCompatibleImage(int width, int height) {
- GraphicsConfiguration configuration =
+ public static BufferedImage createCompatibleImage(final int width, final int height) {
+ final GraphicsConfiguration configuration =
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().getDefaultConfiguration();
return configuration.createCompatibleImage(width, height);
@@ -92,35 +92,35 @@ public class ImageUtil {
*
* @return A thumbnail with the requested width or the original picture if thumbWidth = image.getWidth()
*/
- public static BufferedImage createThumbnail(BufferedImage image, int thumbWidth) {
+ public static BufferedImage createThumbnail(final BufferedImage image, final int thumbWidth) {
// Thanks to Romain Guy for this utility
if (thumbWidth > image.getWidth()) {
throw new IllegalArgumentException("Thumbnail width must be greater than image width");
}
-
+
if (thumbWidth == image.getWidth()) {
return image;
}
-
- float ratio = (float) image.getWidth() / (float) image.getHeight();
+
+ final float ratio = (float) image.getWidth() / (float) image.getHeight();
int width = image.getWidth();
BufferedImage thumb = image;
-
+
do {
width /= 2;
if (width < thumbWidth) {
width = thumbWidth;
}
-
- BufferedImage temp = createCompatibleImage(width, (int) (width / ratio));
- Graphics2D g2 = temp.createGraphics();
+
+ final BufferedImage temp = createCompatibleImage(width, (int) (width / ratio));
+ final Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(thumb, 0, 0, temp.getWidth(), temp.getHeight(), null);
g2.dispose();
thumb = temp;
} while (width != thumbWidth);
-
+
return thumb;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java
index 73d694cd9..a78bc9bb3 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -49,13 +49,13 @@ import javax.media.opengl.*;
efficiency. */
public class Overlay {
- private GLDrawable drawable;
+ private final GLDrawable drawable;
private TextureRenderer renderer;
private boolean contentsLost;
/** Creates a new Java 2D overlay on top of the specified
GLDrawable. */
- public Overlay(GLDrawable drawable) {
+ public Overlay(final GLDrawable drawable) {
this.drawable = drawable;
}
@@ -103,7 +103,7 @@ public class Overlay {
@param height the height of the region to update
@throws GLException If an OpenGL context is not current when this method is called */
- public void markDirty(int x, int y, int width, int height) {
+ public void markDirty(final int x, final int y, final int width, final int height) {
renderer.markDirty(x, y, width, height);
}
@@ -119,7 +119,7 @@ public class Overlay {
*/
public void drawAll() throws GLException {
beginRendering();
- draw(0, 0, drawable.getWidth(), drawable.getHeight());
+ draw(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
endRendering();
}
@@ -130,7 +130,7 @@ public class Overlay {
@throws GLException If an OpenGL context is not current when this method is called
*/
public void beginRendering() throws GLException {
- renderer.beginOrthoRendering(drawable.getWidth(), drawable.getHeight());
+ renderer.beginOrthoRendering(drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
}
/** Ends the OpenGL rendering process for the overlay. This is
@@ -159,7 +159,7 @@ public class Overlay {
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void draw(int x, int y, int width, int height) throws GLException {
+ public void draw(final int x, final int y, final int width, final int height) throws GLException {
draw(x, y, x, y, width, height);
}
@@ -184,9 +184,9 @@ public class Overlay {
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void draw(int screenx, int screeny,
- int overlayx, int overlayy,
- int width, int height) throws GLException {
+ public void draw(final int screenx, final int screeny,
+ final int overlayx, final int overlayy,
+ final int width, final int height) throws GLException {
renderer.drawOrthoRect(screenx, screeny,
overlayx, overlayy,
width, height);
@@ -198,13 +198,13 @@ public class Overlay {
private void validateRenderer() {
if (renderer == null) {
- renderer = new TextureRenderer(drawable.getWidth(),
- drawable.getHeight(),
+ renderer = new TextureRenderer(drawable.getSurfaceWidth(),
+ drawable.getSurfaceHeight(),
true);
contentsLost = true;
- } else if (renderer.getWidth() != drawable.getWidth() ||
- renderer.getHeight() != drawable.getHeight()) {
- renderer.setSize(drawable.getWidth(), drawable.getHeight());
+ } else if (renderer.getWidth() != drawable.getSurfaceWidth() ||
+ renderer.getHeight() != drawable.getSurfaceHeight()) {
+ renderer.setSize(drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
contentsLost = true;
} else {
contentsLost = false;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
deleted file mode 100644
index 0022d5c2d..000000000
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- */
-
-package com.jogamp.opengl.util.awt;
-
-import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferByte;
-import java.io.File;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-import javax.imageio.ImageIO;
-import javax.media.opengl.GL2;
-import javax.media.opengl.GLException;
-import javax.media.opengl.glu.gl2.GLUgl2;
-
-import com.jogamp.common.util.IOUtil;
-import com.jogamp.opengl.GLExtensions;
-import com.jogamp.opengl.util.GLPixelStorageModes;
-import com.jogamp.opengl.util.TGAWriter;
-
-/** Utilities for taking screenshots of OpenGL applications. */
-
-public class Screenshot {
- private Screenshot() {}
-
- /**
- * Takes a fast screenshot of the current OpenGL drawable to a Targa
- * file. Requires the OpenGL context for the desired drawable to be
- * current. Takes the screenshot from the last assigned read buffer,
- * or the OpenGL default read buffer if none has been specified by
- * the user (GL_FRONT for single-buffered configurations and GL_BACK
- * for double-buffered configurations). This is the fastest
- * mechanism for taking a screenshot of an application. Contributed
- * by Carsten Weisse of Bytonic Software (http://bytonic.de/). <p>
- *
- * No alpha channel is written with this variant.
- *
- * @param file the file to write containing the screenshot
- * @param width the width of the current drawable
- * @param height the height of the current drawable
- *
- * @throws GLException if an OpenGL context was not current or
- * another OpenGL-related error occurred
- * @throws IOException if an I/O error occurred while writing the
- * file
- */
- public static void writeToTargaFile(File file,
- int width,
- int height) throws GLException, IOException {
- writeToTargaFile(file, width, height, false);
- }
-
- /**
- * Takes a fast screenshot of the current OpenGL drawable to a Targa
- * file. Requires the OpenGL context for the desired drawable to be
- * current. Takes the screenshot from the last assigned read buffer,
- * or the OpenGL default read buffer if none has been specified by
- * the user (GL_FRONT for single-buffered configurations and GL_BACK
- * for double-buffered configurations). This is the fastest
- * mechanism for taking a screenshot of an application. Contributed
- * by Carsten Weisse of Bytonic Software (http://bytonic.de/).
- *
- * @param file the file to write containing the screenshot
- * @param width the width of the current drawable
- * @param height the height of the current drawable
- * @param alpha whether the alpha channel should be saved. If true,
- * requires GL_EXT_abgr extension to be present.
- *
- * @throws GLException if an OpenGL context was not current or
- * another OpenGL-related error occurred
- * @throws IOException if an I/O error occurred while writing the
- * file
- */
- public static void writeToTargaFile(File file,
- int width,
- int height,
- boolean alpha) throws GLException, IOException {
- writeToTargaFile(file, 0, 0, width, height, alpha);
- }
-
- /**
- * Takes a fast screenshot of the current OpenGL drawable to a Targa
- * file. Requires the OpenGL context for the desired drawable to be
- * current. Takes the screenshot from the last assigned read buffer,
- * or the OpenGL default read buffer if none has been specified by
- * the user (GL_FRONT for single-buffered configurations and GL_BACK
- * for double-buffered configurations). This is the fastest
- * mechanism for taking a screenshot of an application. Contributed
- * by Carsten Weisse of Bytonic Software (http://bytonic.de/).
- *
- * @param file the file to write containing the screenshot
- * @param x the starting x coordinate of the screenshot, measured from the lower-left
- * @param y the starting y coordinate of the screenshot, measured from the lower-left
- * @param width the width of the desired screenshot area
- * @param height the height of the desired screenshot area
- * @param alpha whether the alpha channel should be saved. If true,
- * requires GL_EXT_abgr extension to be present.
- *
- * @throws GLException if an OpenGL context was not current or
- * another OpenGL-related error occurred
- * @throws IOException if an I/O error occurred while writing the
- * file
- */
- public static void writeToTargaFile(File file,
- int x,
- int y,
- int width,
- int height,
- boolean alpha) throws GLException, IOException {
- if (alpha) {
- checkExtABGR();
- }
-
- TGAWriter writer = new TGAWriter();
- writer.open(file, width, height, alpha);
- ByteBuffer bgr = writer.getImageData();
-
- GL2 gl = GLUgl2.getCurrentGL2();
-
- // Set up pixel storage modes
- GLPixelStorageModes psm = new GLPixelStorageModes();
- psm.setPackAlignment(gl, 1);
-
- int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2.GL_BGR);
-
- // read the BGR values into the image buffer
- gl.glReadPixels(x, y, width, height, readbackType,
- GL2.GL_UNSIGNED_BYTE, bgr);
-
- // Restore pixel storage modes
- psm.restore(gl);
-
- // close the file
- writer.close();
- }
-
- /**
- * Takes a screenshot of the current OpenGL drawable to a
- * BufferedImage. Requires the OpenGL context for the desired
- * drawable to be current. Takes the screenshot from the last
- * assigned read buffer, or the OpenGL default read buffer if none
- * has been specified by the user (GL_FRONT for single-buffered
- * configurations and GL_BACK for double-buffered configurations).
- * Note that the scanlines of the resulting image are flipped
- * vertically in order to correctly match the OpenGL contents, which
- * takes time and is therefore not as fast as the Targa screenshot
- * function. <P>
- *
- * No alpha channel is read back with this variant.
- *
- * @param width the width of the current drawable
- * @param height the height of the current drawable
- *
- * @throws GLException if an OpenGL context was not current or
- * another OpenGL-related error occurred
- */
- public static BufferedImage readToBufferedImage(int width,
- int height) throws GLException {
- return readToBufferedImage(width, height, false);
- }
-
- /**
- * Takes a screenshot of the current OpenGL drawable to a
- * BufferedImage. Requires the OpenGL context for the desired
- * drawable to be current. Takes the screenshot from the last
- * assigned read buffer, or the OpenGL default read buffer if none
- * has been specified by the user (GL_FRONT for single-buffered
- * configurations and GL_BACK for double-buffered configurations).
- * Note that the scanlines of the resulting image are flipped
- * vertically in order to correctly match the OpenGL contents, which
- * takes time and is therefore not as fast as the Targa screenshot
- * function.
- *
- * @param width the width of the current drawable
- * @param height the height of the current drawable
- * @param alpha whether the alpha channel should be read back. If
- * true, requires GL_EXT_abgr extension to be present.
- *
- * @throws GLException if an OpenGL context was not current or
- * another OpenGL-related error occurred
- */
- public static BufferedImage readToBufferedImage(int width,
- int height,
- boolean alpha) throws GLException {
- return readToBufferedImage(0, 0, width, height, alpha);
- }
-
- /**
- * Takes a screenshot of the current OpenGL drawable to a
- * BufferedImage. Requires the OpenGL context for the desired
- * drawable to be current. Takes the screenshot from the last
- * assigned read buffer, or the OpenGL default read buffer if none
- * has been specified by the user (GL_FRONT for single-buffered
- * configurations and GL_BACK for double-buffered configurations).
- * Note that the scanlines of the resulting image are flipped
- * vertically in order to correctly match the OpenGL contents, which
- * takes time and is therefore not as fast as the Targa screenshot
- * function.
- *
- * @param x the starting x coordinate of the screenshot, measured from the lower-left
- * @param y the starting y coordinate of the screenshot, measured from the lower-left
- * @param width the width of the desired screenshot area
- * @param height the height of the desired screenshot area
- * @param alpha whether the alpha channel should be read back. If
- * true, requires GL_EXT_abgr extension to be present.
- *
- * @throws GLException if an OpenGL context was not current or
- * another OpenGL-related error occurred
- */
- public static BufferedImage readToBufferedImage(int x,
- int y,
- int width,
- int height,
- boolean alpha) throws GLException {
- int bufImgType = (alpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR);
- int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2.GL_BGR);
-
- if (alpha) {
- checkExtABGR();
- }
-
- // Allocate necessary storage
- BufferedImage image = new BufferedImage(width, height, bufImgType);
-
- GL2 gl = GLUgl2.getCurrentGL2();
-
- // Set up pixel storage modes
- GLPixelStorageModes psm = new GLPixelStorageModes();
- psm.setPackAlignment(gl, 1);
-
- // read the BGR values into the image
- gl.glReadPixels(x, y, width, height, readbackType,
- GL2.GL_UNSIGNED_BYTE,
- ByteBuffer.wrap(((DataBufferByte) image.getRaster().getDataBuffer()).getData()));
-
- // Restore pixel storage modes
- psm.restore(gl);
-
- // Must flip BufferedImage vertically for correct results
- ImageUtil.flipImageVertically(image);
- return image;
- }
-
- /**
- * Takes a screenshot of the current OpenGL drawable to the
- * specified file on disk using the ImageIO package. Requires the
- * OpenGL context for the desired drawable to be current. Takes the
- * screenshot from the last assigned read buffer, or the OpenGL
- * default read buffer if none has been specified by the user
- * (GL_FRONT for single-buffered configurations and GL_BACK for
- * double-buffered configurations). This is not the fastest
- * mechanism for taking a screenshot but may be more convenient than
- * others for getting images for consumption by other packages. The
- * file format is inferred from the suffix of the given file. <P>
- *
- * No alpha channel is saved with this variant.
- *
- * @param file the file to write containing the screenshot
- * @param width the width of the current drawable
- * @param height the height of the current drawable
- *
- * @throws GLException if an OpenGL context was not current or
- * another OpenGL-related error occurred
- *
- * @throws IOException if an I/O error occurred or if the file could
- * not be written to disk due to the requested file format being
- * unsupported by ImageIO
- */
- public static void writeToFile(File file,
- int width,
- int height) throws IOException, GLException {
- writeToFile(file, width, height, false);
- }
-
- /**
- * Takes a screenshot of the current OpenGL drawable to the
- * specified file on disk using the ImageIO package. Requires the
- * OpenGL context for the desired drawable to be current. Takes the
- * screenshot from the last assigned read buffer, or the OpenGL
- * default read buffer if none has been specified by the user
- * (GL_FRONT for single-buffered configurations and GL_BACK for
- * double-buffered configurations). This is not the fastest
- * mechanism for taking a screenshot but may be more convenient than
- * others for getting images for consumption by other packages. The
- * file format is inferred from the suffix of the given file. <P>
- *
- * Note that some file formats, in particular JPEG, can not handle
- * an alpha channel properly. If the "alpha" argument is specified
- * as true for such a file format it will be silently ignored.
- *
- * @param file the file to write containing the screenshot
- * @param width the width of the current drawable
- * @param height the height of the current drawable
- * @param alpha whether an alpha channel should be saved. If true,
- * requires GL_EXT_abgr extension to be present.
- *
- * @throws GLException if an OpenGL context was not current or
- * another OpenGL-related error occurred
- *
- * @throws IOException if an I/O error occurred or if the file could
- * not be written to disk due to the requested file format being
- * unsupported by ImageIO
- */
- public static void writeToFile(File file,
- int width,
- int height,
- boolean alpha) throws IOException, GLException {
- writeToFile(file, 0, 0, width, height, alpha);
- }
-
- /**
- * Takes a screenshot of the current OpenGL drawable to the
- * specified file on disk using the ImageIO package. Requires the
- * OpenGL context for the desired drawable to be current. Takes the
- * screenshot from the last assigned read buffer, or the OpenGL
- * default read buffer if none has been specified by the user
- * (GL_FRONT for single-buffered configurations and GL_BACK for
- * double-buffered configurations). This is not the fastest
- * mechanism for taking a screenshot but may be more convenient than
- * others for getting images for consumption by other packages. The
- * file format is inferred from the suffix of the given file. <P>
- *
- * Note that some file formats, in particular JPEG, can not handle
- * an alpha channel properly. If the "alpha" argument is specified
- * as true for such a file format it will be silently ignored.
- *
- * @param file the file to write containing the screenshot
- * @param x the starting x coordinate of the screenshot, measured from the lower-left
- * @param y the starting y coordinate of the screenshot, measured from the lower-left
- * @param width the width of the current drawable
- * @param height the height of the current drawable
- * @param alpha whether an alpha channel should be saved. If true,
- * requires GL_EXT_abgr extension to be present.
- *
- * @throws GLException if an OpenGL context was not current or
- * another OpenGL-related error occurred
- *
- * @throws IOException if an I/O error occurred or if the file could
- * not be written to disk due to the requested file format being
- * unsupported by ImageIO
- */
- public static void writeToFile(File file,
- int x,
- int y,
- int width,
- int height,
- boolean alpha) throws IOException, GLException {
- String fileSuffix = IOUtil.getFileSuffix(file);
- if (alpha && (fileSuffix.equals("jpg") || fileSuffix.equals("jpeg"))) {
- // JPEGs can't deal properly with alpha channels
- alpha = false;
- }
-
- BufferedImage image = readToBufferedImage(x, y, width, height, alpha);
- if (!ImageIO.write(image, fileSuffix, file)) {
- throw new IOException("Unsupported file format " + fileSuffix);
- }
- }
-
- private static void checkExtABGR() {
- GL2 gl = GLUgl2.getCurrentGL2();
- if (!gl.isExtensionAvailable(GLExtensions.EXT_abgr)) {
- throw new IllegalArgumentException("Saving alpha channel requires GL_EXT_abgr");
- }
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
index 1735fcddd..fc0861eaa 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java
@@ -40,7 +40,7 @@
package com.jogamp.opengl.util.awt;
import com.jogamp.common.nio.Buffers;
-
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.*;
import com.jogamp.opengl.util.packrect.*;
@@ -60,14 +60,12 @@ import java.awt.RenderingHints;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
-
import java.nio.*;
-
import java.text.*;
-
import java.util.*;
import javax.media.opengl.*;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
import javax.media.opengl.glu.*;
import javax.media.opengl.awt.*;
@@ -128,7 +126,12 @@ import jogamp.opengl.Debug;
@author Kenneth Russell
*/
public class TextRenderer {
- private static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.TextRenderer", true);
+ private static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = PropertyAccess.isPropertyDefined("jogl.debug.TextRenderer", true);
+ }
// These are occasionally useful for more in-depth debugging
private static final boolean DISABLE_GLYPH_CACHE = false;
@@ -154,20 +157,20 @@ public class TextRenderer {
static final int kTotalBufferSizeBytesTex = kTotalBufferSizeCoordsTex * 4;
static final int kSizeInBytes_OneVertices_VertexData = kCoordsPerVertVerts * 4;
static final int kSizeInBytes_OneVertices_TexData = kCoordsPerVertTex * 4;
- private Font font;
- private boolean antialiased;
- private boolean useFractionalMetrics;
+ private final Font font;
+ private final boolean antialiased;
+ private final boolean useFractionalMetrics;
// Whether we're attempting to use automatic mipmap generation support
private boolean mipmap;
private RectanglePacker packer;
private boolean haveMaxSize;
- private RenderDelegate renderDelegate;
+ private final RenderDelegate renderDelegate;
private TextureRenderer cachedBackingStore;
private Graphics2D cachedGraphics;
private FontRenderContext cachedFontRenderContext;
- private Map /*<String,Rect>*/ stringLocations = new HashMap /*<String,Rect>*/();
- private GlyphProducer mGlyphProducer;
+ private final Map<String, Rect> stringLocations = new HashMap<String, Rect>();
+ private final GlyphProducer mGlyphProducer;
private int numRenderCycles;
@@ -195,10 +198,10 @@ public class TextRenderer {
// Debugging purposes only
private boolean debugged;
Pipelined_QuadRenderer mPipelinedQuadRenderer;
-
+
//emzic: added boolean flag
private boolean useVertexArrays = true;
-
+
//emzic: added boolean flag
private boolean isExtensionAvailable_GL_VERSION_1_5;
private boolean checkFor_isExtensionAvailable_GL_VERSION_1_5;
@@ -213,7 +216,7 @@ public class TextRenderer {
@param font the font to render with
*/
- public TextRenderer(Font font) {
+ public TextRenderer(final Font font) {
this(font, false, false, null, false);
}
@@ -227,7 +230,7 @@ public class TextRenderer {
@param font the font to render with
@param mipmap whether to attempt use of automatic mipmap generation
*/
- public TextRenderer(Font font, boolean mipmap) {
+ public TextRenderer(final Font font, final boolean mipmap) {
this(font, false, false, null, mipmap);
}
@@ -244,8 +247,8 @@ public class TextRenderer {
@param useFractionalMetrics whether to use fractional font
metrics at the Java 2D level
*/
- public TextRenderer(Font font, boolean antialiased,
- boolean useFractionalMetrics) {
+ public TextRenderer(final Font font, final boolean antialiased,
+ final boolean useFractionalMetrics) {
this(font, antialiased, useFractionalMetrics, null, false);
}
@@ -263,8 +266,8 @@ public class TextRenderer {
@param renderDelegate the render delegate to use to draw the
text's bitmap, or null to use the default one
*/
- public TextRenderer(Font font, boolean antialiased,
- boolean useFractionalMetrics, RenderDelegate renderDelegate) {
+ public TextRenderer(final Font font, final boolean antialiased,
+ final boolean useFractionalMetrics, final RenderDelegate renderDelegate) {
this(font, antialiased, useFractionalMetrics, renderDelegate, false);
}
@@ -285,9 +288,9 @@ public class TextRenderer {
text's bitmap, or null to use the default one
@param mipmap whether to attempt use of automatic mipmap generation
*/
- public TextRenderer(Font font, boolean antialiased,
- boolean useFractionalMetrics, RenderDelegate renderDelegate,
- boolean mipmap) {
+ public TextRenderer(final Font font, final boolean antialiased,
+ final boolean useFractionalMetrics, RenderDelegate renderDelegate,
+ final boolean mipmap) {
this.font = font;
this.antialiased = antialiased;
this.useFractionalMetrics = useFractionalMetrics;
@@ -309,7 +312,7 @@ public class TextRenderer {
/** Returns the bounding rectangle of the given String, assuming it
was rendered at the origin. See {@link #getBounds(CharSequence)
getBounds(CharSequence)}. */
- public Rectangle2D getBounds(String str) {
+ public Rectangle2D getBounds(final String str) {
return getBounds((CharSequence) str);
}
@@ -328,12 +331,12 @@ public class TextRenderer {
{@link java.awt.font.GlyphVector#getPixelBounds getPixelBounds},
etc.) the returned bounds correspond to, although every effort
is made to ensure an accurate bound. */
- public Rectangle2D getBounds(CharSequence str) {
+ public Rectangle2D getBounds(final CharSequence str) {
// FIXME: this should be more optimized and use the glyph cache
- Rect r = null;
+ final Rect r = stringLocations.get(str);
- if ((r = (Rect) stringLocations.get(str)) != null) {
- TextData data = (TextData) r.getUserData();
+ if (r != null) {
+ final TextData data = (TextData) r.getUserData();
// Reconstitute the Java 2D results based on the cached values
return new Rectangle2D.Double(-data.origin().x, -data.origin().y,
@@ -380,7 +383,7 @@ public class TextRenderer {
@param height the height of the current on-screen OpenGL drawable
@throws javax.media.opengl.GLException If an OpenGL context is not current when this method is called
*/
- public void beginRendering(int width, int height) throws GLException {
+ public void beginRendering(final int width, final int height) throws GLException {
beginRendering(width, height, true);
}
@@ -400,7 +403,7 @@ public class TextRenderer {
@param disableDepthTest whether to disable the depth test
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void beginRendering(int width, int height, boolean disableDepthTest)
+ public void beginRendering(final int width, final int height, final boolean disableDepthTest)
throws GLException {
beginRendering(true, width, height, disableDepthTest);
}
@@ -427,8 +430,8 @@ public class TextRenderer {
@param color the new color to use for rendering text
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void setColor(Color color) throws GLException {
- boolean noNeedForFlush = (haveCachedColor && (cachedColor != null) &&
+ public void setColor(final Color color) throws GLException {
+ final boolean noNeedForFlush = (haveCachedColor && (cachedColor != null) &&
color.equals(cachedColor));
if (!noNeedForFlush) {
@@ -455,9 +458,9 @@ public class TextRenderer {
transparent, 1.0f = completely opaque
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void setColor(float r, float g, float b, float a)
+ public void setColor(final float r, final float g, final float b, final float a)
throws GLException {
- boolean noNeedForFlush = (haveCachedColor && (cachedColor == null) &&
+ final boolean noNeedForFlush = (haveCachedColor && (cachedColor == null) &&
(r == cachedR) && (g == cachedG) && (b == cachedB) &&
(a == cachedA));
@@ -485,14 +488,14 @@ public class TextRenderer {
@param y the y coordinate at which to draw
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void draw(CharSequence str, int x, int y) throws GLException {
+ public void draw(final CharSequence str, final int x, final int y) throws GLException {
draw3D(str, x, y, 0, 1);
}
/** Draws the supplied String at the desired location using the
renderer's current color. See {@link #draw(CharSequence, int,
int) draw(CharSequence, int, int)}. */
- public void draw(String str, int x, int y) throws GLException {
+ public void draw(final String str, final int x, final int y) throws GLException {
draw3D(str, x, y, 0, 1);
}
@@ -508,8 +511,8 @@ public class TextRenderer {
@param scaleFactor a uniform scale factor applied to the width and height of the drawn rectangle
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void draw3D(CharSequence str, float x, float y, float z,
- float scaleFactor) {
+ public void draw3D(final CharSequence str, final float x, final float y, final float z,
+ final float scaleFactor) {
internal_draw3D(str, x, y, z, scaleFactor);
}
@@ -517,12 +520,12 @@ public class TextRenderer {
renderer's current color. See {@link #draw3D(CharSequence,
float, float, float, float) draw3D(CharSequence, float, float,
float, float)}. */
- public void draw3D(String str, float x, float y, float z, float scaleFactor) {
+ public void draw3D(final String str, final float x, final float y, final float z, final float scaleFactor) {
internal_draw3D(str, x, y, z, scaleFactor);
}
/** Returns the pixel width of the given character. */
- public float getCharWidth(char inChar) {
+ public float getCharWidth(final char inChar) {
return mGlyphProducer.getGlyphPixelWidth(inChar);
}
@@ -577,20 +580,20 @@ public class TextRenderer {
// Internals only below this point
//
- private static Rectangle2D preNormalize(Rectangle2D src) {
+ private static Rectangle2D preNormalize(final Rectangle2D src) {
// Need to round to integer coordinates
// Also give ourselves a little slop around the reported
// bounds of glyphs because it looks like neither the visual
// nor the pixel bounds works perfectly well
- int minX = (int) Math.floor(src.getMinX()) - 1;
- int minY = (int) Math.floor(src.getMinY()) - 1;
- int maxX = (int) Math.ceil(src.getMaxX()) + 1;
- int maxY = (int) Math.ceil(src.getMaxY()) + 1;
+ final int minX = (int) Math.floor(src.getMinX()) - 1;
+ final int minY = (int) Math.floor(src.getMinY()) - 1;
+ final int maxX = (int) Math.ceil(src.getMaxX()) + 1;
+ final int maxY = (int) Math.ceil(src.getMaxY()) + 1;
return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
}
- private Rectangle2D normalize(Rectangle2D src) {
+ private Rectangle2D normalize(final Rectangle2D src) {
// Give ourselves a boundary around each entity on the backing
// store in order to prevent bleeding of nearby Strings due to
// the fact that we use linear filtering
@@ -598,7 +601,7 @@ public class TextRenderer {
// NOTE that this boundary is quite heuristic and is related
// to how far away in 3D we may view the text --
// heuristically, 1.5% of the font's height
- int boundary = (int) Math.max(1, 0.015 * font.getSize());
+ final int boundary = (int) Math.max(1, 0.015 * font.getSize());
return new Rectangle2D.Double((int) Math.floor(src.getMinX() - boundary),
(int) Math.floor(src.getMinY() - boundary),
@@ -607,7 +610,7 @@ public class TextRenderer {
}
private TextureRenderer getBackingStore() {
- TextureRenderer renderer = (TextureRenderer) packer.getBackingStore();
+ final TextureRenderer renderer = (TextureRenderer) packer.getBackingStore();
if (renderer != cachedBackingStore) {
// Backing store changed since last time; discard any cached Graphics2D
@@ -624,7 +627,7 @@ public class TextRenderer {
}
private Graphics2D getGraphics2D() {
- TextureRenderer renderer = getBackingStore();
+ final TextureRenderer renderer = getBackingStore();
if (cachedGraphics == null) {
cachedGraphics = renderer.createGraphics();
@@ -645,9 +648,9 @@ public class TextRenderer {
return cachedGraphics;
}
- private void beginRendering(boolean ortho, int width, int height,
- boolean disableDepthTestForOrtho) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
+ private void beginRendering(final boolean ortho, final int width, final int height,
+ final boolean disableDepthTestForOrtho) {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
if (DEBUG && !debugged) {
debug(gl);
@@ -672,8 +675,8 @@ public class TextRenderer {
if (!haveMaxSize) {
// Query OpenGL for the maximum texture size and set it in the
// RectanglePacker to keep it from expanding too large
- int[] sz = new int[1];
- gl.glGetIntegerv(GL2.GL_MAX_TEXTURE_SIZE, sz, 0);
+ final int[] sz = new int[1];
+ gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, sz, 0);
packer.setMaxSize(sz[0], sz[0]);
haveMaxSize = true;
}
@@ -702,16 +705,16 @@ public class TextRenderer {
/**
* emzic: here the call to glBindBuffer crashes on certain graphicscard/driver combinations
* this is why the ugly try-catch block has been added, which falls back to the old textrenderer
- *
+ *
* @param ortho
* @throws GLException
*/
- private void endRendering(boolean ortho) throws GLException {
+ private void endRendering(final boolean ortho) throws GLException {
flushGlyphPipeline();
inBeginEndPair = false;
- GL2 gl = GLContext.getCurrentGL().getGL2();
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
// Pop client attrib bits used by the pipelined quad renderer
gl.glPopClientAttrib();
@@ -721,8 +724,8 @@ public class TextRenderer {
// binding
if (getUseVertexArrays() && is15Available(gl)) {
try {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
- } catch (Exception e) {
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ } catch (final Exception e) {
isExtensionAvailable_GL_VERSION_1_5 = false;
}
}
@@ -745,13 +748,14 @@ public class TextRenderer {
}
private void clearUnusedEntries() {
- final java.util.List deadRects = new ArrayList /*<Rect>*/();
+ final java.util.List<Rect> deadRects = new ArrayList<Rect>();
// Iterate through the contents of the backing store, removing
// text strings that haven't been used recently
packer.visit(new RectVisitor() {
- public void visit(Rect rect) {
- TextData data = (TextData) rect.getUserData();
+ @Override
+ public void visit(final Rect rect) {
+ final TextData data = (TextData) rect.getUserData();
if (data.used()) {
data.clearUsed();
@@ -761,12 +765,11 @@ public class TextRenderer {
}
});
- for (Iterator iter = deadRects.iterator(); iter.hasNext();) {
- Rect r = (Rect) iter.next();
+ for (final Rect r : deadRects) {
packer.remove(r);
stringLocations.remove(((TextData) r.getUserData()).string());
- int unicodeToClearFromCache = ((TextData) r.getUserData()).unicodeID;
+ final int unicodeToClearFromCache = ((TextData) r.getUserData()).unicodeID;
if (unicodeToClearFromCache > 0) {
mGlyphProducer.clearCacheEntry(unicodeToClearFromCache);
@@ -781,7 +784,7 @@ public class TextRenderer {
}
// If we removed dead rectangles this cycle, try to do a compaction
- float frag = packer.verticalFragmentationRatio();
+ final float frag = packer.verticalFragmentationRatio();
if (!deadRects.isEmpty() && (frag > MAX_VERTICAL_FRAGMENTATION)) {
if (DEBUG) {
@@ -799,12 +802,10 @@ public class TextRenderer {
}
}
- private void internal_draw3D(CharSequence str, float x, float y, float z,
- float scaleFactor) {
- List/*<Glyph>*/ glyphs = mGlyphProducer.getGlyphs(str);
- for (Iterator iter = glyphs.iterator(); iter.hasNext(); ) {
- Glyph glyph = (Glyph) iter.next();
- float advance = glyph.draw3D(x, y, z, scaleFactor);
+ private void internal_draw3D(final CharSequence str, float x, final float y, final float z,
+ final float scaleFactor) {
+ for (final Glyph glyph : mGlyphProducer.getGlyphs(str)) {
+ final float advance = glyph.draw3D(x, y, z, scaleFactor);
x += advance * scaleFactor;
}
}
@@ -815,8 +816,8 @@ public class TextRenderer {
}
}
- private void draw3D_ROBUST(CharSequence str, float x, float y, float z,
- float scaleFactor) {
+ private void draw3D_ROBUST(final CharSequence str, final float x, final float y, final float z,
+ final float scaleFactor) {
String curStr;
if (str instanceof String) {
curStr = (String) str;
@@ -825,14 +826,14 @@ public class TextRenderer {
}
// Look up the string on the backing store
- Rect rect = (Rect) stringLocations.get(curStr);
+ Rect rect = stringLocations.get(curStr);
if (rect == null) {
// Rasterize this string and place it on the backing store
Graphics2D g = getGraphics2D();
- Rectangle2D origBBox = preNormalize(renderDelegate.getBounds(curStr, font, getFontRenderContext()));
- Rectangle2D bbox = normalize(origBBox);
- Point origin = new Point((int) -bbox.getMinX(),
+ final Rectangle2D origBBox = preNormalize(renderDelegate.getBounds(curStr, font, getFontRenderContext()));
+ final Rectangle2D bbox = normalize(origBBox);
+ final Point origin = new Point((int) -bbox.getMinX(),
(int) -bbox.getMinY());
rect = new Rect(0, 0, (int) bbox.getWidth(),
(int) bbox.getHeight(),
@@ -847,8 +848,8 @@ public class TextRenderer {
// OK, should now have an (x, y) for this rectangle; rasterize
// the String
- int strx = rect.x() + origin.x;
- int stry = rect.y() + origin.y;
+ final int strx = rect.x() + origin.x;
+ final int stry = rect.y() + origin.y;
// Clear out the area we're going to draw into
g.setComposite(AlphaComposite.Clear);
@@ -859,7 +860,7 @@ public class TextRenderer {
renderDelegate.draw(g, curStr, strx, stry);
if (DRAW_BBOXES) {
- TextData data = (TextData) rect.getUserData();
+ final TextData data = (TextData) rect.getUserData();
// Draw a bounding box on the backing store
g.drawRect(strx - data.origOriginX(),
stry - data.origOriginY(),
@@ -877,16 +878,16 @@ public class TextRenderer {
}
// OK, now draw the portion of the backing store to the screen
- TextureRenderer renderer = getBackingStore();
+ final TextureRenderer renderer = getBackingStore();
// NOTE that the rectangles managed by the packer have their
// origin at the upper-left but the TextureRenderer's origin is
// at its lower left!!!
- TextData data = (TextData) rect.getUserData();
+ final TextData data = (TextData) rect.getUserData();
data.markUsed();
- Rectangle2D origRect = data.origRect();
-
+ final Rectangle2D origRect = data.origRect();
+
// Align the leftmost point of the baseline to the (x, y, z) coordinate requested
renderer.draw3DRect(x - (scaleFactor * data.origOriginX()),
y - (scaleFactor * ((float) origRect.getHeight() - data.origOriginY())), z,
@@ -899,21 +900,23 @@ public class TextRenderer {
//----------------------------------------------------------------------
// Debugging functionality
//
- private void debug(GL gl) {
+ private void debug(final GL gl) {
dbgFrame = new Frame("TextRenderer Debug Output");
- GLCanvas dbgCanvas = new GLCanvas(new GLCapabilities(gl.getGLProfile()), null,
- GLContext.getCurrent(), null);
+ final GLCanvas dbgCanvas = new GLCanvas(new GLCapabilities(gl.getGLProfile()));
+ dbgCanvas.setSharedContext(GLContext.getCurrent());
dbgCanvas.addGLEventListener(new DebugListener(gl, dbgFrame));
dbgFrame.add(dbgCanvas);
final FPSAnimator anim = new FPSAnimator(dbgCanvas, 10);
dbgFrame.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
+ @Override
+ public void windowClosing(final WindowEvent e) {
// Run this on another thread than the AWT event queue to
// make sure the call to Animator.stop() completes before
// exiting
new Thread(new Runnable() {
+ @Override
public void run() {
anim.stop();
}
@@ -994,22 +997,24 @@ public class TextRenderer {
CharSequenceIterator() {
}
- CharSequenceIterator(CharSequence sequence) {
+ CharSequenceIterator(final CharSequence sequence) {
initFromCharSequence(sequence);
}
- public void initFromCharSequence(CharSequence sequence) {
+ public void initFromCharSequence(final CharSequence sequence) {
mSequence = sequence;
mLength = mSequence.length();
mCurrentIndex = 0;
}
+ @Override
public char last() {
mCurrentIndex = Math.max(0, mLength - 1);
return current();
}
+ @Override
public char current() {
if ((mLength == 0) || (mCurrentIndex >= mLength)) {
return CharacterIterator.DONE;
@@ -1018,43 +1023,51 @@ public class TextRenderer {
return mSequence.charAt(mCurrentIndex);
}
+ @Override
public char next() {
mCurrentIndex++;
return current();
}
+ @Override
public char previous() {
mCurrentIndex = Math.max(mCurrentIndex - 1, 0);
return current();
}
- public char setIndex(int position) {
+ @Override
+ public char setIndex(final int position) {
mCurrentIndex = position;
return current();
}
+ @Override
public int getBeginIndex() {
return 0;
}
+ @Override
public int getEndIndex() {
return mLength;
}
+ @Override
public int getIndex() {
return mCurrentIndex;
}
+ @Override
public Object clone() {
- CharSequenceIterator iter = new CharSequenceIterator(mSequence);
+ final CharSequenceIterator iter = new CharSequenceIterator(mSequence);
iter.mCurrentIndex = mCurrentIndex;
return iter;
}
+ @Override
public char first() {
if (mLength == 0) {
return CharacterIterator.DONE;
@@ -1070,7 +1083,7 @@ public class TextRenderer {
static class TextData {
// Back-pointer to String this TextData describes, if it
// represents a String rather than a single glyph
- private String str;
+ private final String str;
// If this TextData represents a single glyph, this is its
// unicode ID
@@ -1081,7 +1094,7 @@ public class TextRenderer {
// 2D coordinate system) at which the string must be rasterized in
// order to fit within the rectangle -- the leftmost point of the
// baseline.
- private Point origin;
+ private final Point origin;
// This represents the pre-normalized rectangle, which fits
// within the rectangle on the backing store. We keep a
@@ -1089,11 +1102,11 @@ public class TextRenderer {
// prevent bleeding of adjacent letters when using GL_LINEAR
// filtering for rendering. The origin of this rectangle is
// equivalent to the origin above.
- private Rectangle2D origRect;
+ private final Rectangle2D origRect;
private boolean used; // Whether this text was used recently
- TextData(String str, Point origin, Rectangle2D origRect, int unicodeID) {
+ TextData(final String str, final Point origin, final Rectangle2D origRect, final int unicodeID) {
this.str = str;
this.origin = origin;
this.origRect = origRect;
@@ -1138,7 +1151,8 @@ public class TextRenderer {
class Manager implements BackingStoreManager {
private Graphics2D g;
- public Object allocateBackingStore(int w, int h) {
+ @Override
+ public Object allocateBackingStore(final int w, final int h) {
// FIXME: should consider checking Font's attributes to see
// whether we're likely to need to support a full RGBA backing
// store (i.e., non-default Paint, foreground color, etc.), but
@@ -1160,11 +1174,13 @@ public class TextRenderer {
return renderer;
}
- public void deleteBackingStore(Object backingStore) {
+ @Override
+ public void deleteBackingStore(final Object backingStore) {
((TextureRenderer) backingStore).dispose();
}
- public boolean preExpand(Rect cause, int attemptNumber) {
+ @Override
+ public boolean preExpand(final Rect cause, final int attemptNumber) {
// Only try this one time; clear out potentially obsolete entries
// NOTE: this heuristic and the fact that it clears the used bit
// of all entries seems to cause cycling of entries in some
@@ -1199,7 +1215,8 @@ public class TextRenderer {
return false;
}
- public boolean additionFailed(Rect cause, int attemptNumber) {
+ @Override
+ public boolean additionFailed(final Rect cause, final int attemptNumber) {
// Heavy hammer -- might consider doing something different
packer.clear();
stringLocations.clear();
@@ -1217,17 +1234,19 @@ public class TextRenderer {
return false;
}
+ @Override
public boolean canCompact() {
return true;
}
- public void beginMovement(Object oldBackingStore, Object newBackingStore) {
+ @Override
+ public void beginMovement(final Object oldBackingStore, final Object newBackingStore) {
// Exit the begin / end pair if necessary
if (inBeginEndPair) {
// Draw any outstanding glyphs
flush();
- GL2 gl = GLContext.getCurrentGL().getGL2();
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
// Pop client attrib bits used by the pipelined quad renderer
gl.glPopClientAttrib();
@@ -1237,8 +1256,8 @@ public class TextRenderer {
// binding
if (getUseVertexArrays() && is15Available(gl)) {
try {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
- } catch (Exception e) {
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ } catch (final Exception e) {
isExtensionAvailable_GL_VERSION_1_5 = false;
}
}
@@ -1250,14 +1269,15 @@ public class TextRenderer {
}
}
- TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
+ final TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
g = newRenderer.createGraphics();
}
- public void move(Object oldBackingStore, Rect oldLocation,
- Object newBackingStore, Rect newLocation) {
- TextureRenderer oldRenderer = (TextureRenderer) oldBackingStore;
- TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
+ @Override
+ public void move(final Object oldBackingStore, final Rect oldLocation,
+ final Object newBackingStore, final Rect newLocation) {
+ final TextureRenderer oldRenderer = (TextureRenderer) oldBackingStore;
+ final TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
if (oldRenderer == newRenderer) {
// Movement on the same backing store -- easy case
@@ -1266,7 +1286,7 @@ public class TextRenderer {
newLocation.y() - oldLocation.y());
} else {
// Need to draw from the old renderer's image into the new one
- Image img = oldRenderer.getImage();
+ final Image img = oldRenderer.getImage();
g.drawImage(img, newLocation.x(), newLocation.y(),
newLocation.x() + newLocation.w(),
newLocation.y() + newLocation.h(), oldLocation.x(),
@@ -1275,11 +1295,12 @@ public class TextRenderer {
}
}
- public void endMovement(Object oldBackingStore, Object newBackingStore) {
+ @Override
+ public void endMovement(final Object oldBackingStore, final Object newBackingStore) {
g.dispose();
// Sync the whole surface
- TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
+ final TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
newRenderer.markDirty(0, 0, newRenderer.getWidth(),
newRenderer.getHeight());
@@ -1293,7 +1314,7 @@ public class TextRenderer {
}
// Push client attrib bits used by the pipelined quad renderer
- GL2 gl = GLContext.getCurrentGL().getGL2();
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
gl.glPushClientAttrib((int) GL2.GL_ALL_CLIENT_ATTRIB_BITS);
if (haveCachedColor) {
@@ -1311,32 +1332,38 @@ public class TextRenderer {
}
public static class DefaultRenderDelegate implements RenderDelegate {
+ @Override
public boolean intensityOnly() {
return true;
}
- public Rectangle2D getBounds(CharSequence str, Font font,
- FontRenderContext frc) {
+ @Override
+ public Rectangle2D getBounds(final CharSequence str, final Font font,
+ final FontRenderContext frc) {
return getBounds(font.createGlyphVector(frc,
new CharSequenceIterator(str)),
frc);
}
- public Rectangle2D getBounds(String str, Font font,
- FontRenderContext frc) {
+ @Override
+ public Rectangle2D getBounds(final String str, final Font font,
+ final FontRenderContext frc) {
return getBounds(font.createGlyphVector(frc, str), frc);
}
- public Rectangle2D getBounds(GlyphVector gv, FontRenderContext frc) {
+ @Override
+ public Rectangle2D getBounds(final GlyphVector gv, final FontRenderContext frc) {
return gv.getVisualBounds();
}
- public void drawGlyphVector(Graphics2D graphics, GlyphVector str,
- int x, int y) {
+ @Override
+ public void drawGlyphVector(final Graphics2D graphics, final GlyphVector str,
+ final int x, final int y) {
graphics.drawGlyphVector(str, x, y);
}
- public void draw(Graphics2D graphics, String str, int x, int y) {
+ @Override
+ public void draw(final Graphics2D graphics, final String str, final int x, final int y) {
graphics.drawString(str, x, y);
}
}
@@ -1346,7 +1373,7 @@ public class TextRenderer {
//
// A temporary to prevent excessive garbage creation
- private char[] singleUnicode = new char[1];
+ private final char[] singleUnicode = new char[1];
/** A Glyph represents either a single unicode glyph or a
substring of characters to be drawn. The reason for the dual
@@ -1386,11 +1413,11 @@ public class TextRenderer {
private boolean needAdvance;
// Creates a Glyph representing an individual Unicode character
- public Glyph(int unicodeID,
- int glyphCode,
- float advance,
- GlyphVector singleUnicodeGlyphVector,
- GlyphProducer producer) {
+ public Glyph(final int unicodeID,
+ final int glyphCode,
+ final float advance,
+ final GlyphVector singleUnicodeGlyphVector,
+ final GlyphProducer producer) {
this.unicodeID = unicodeID;
this.glyphCode = glyphCode;
this.advance = advance;
@@ -1401,7 +1428,7 @@ public class TextRenderer {
// Creates a Glyph representing a sequence of characters, with
// an indication of whether additional single glyphs are being
// rendered after it
- public Glyph(String str, boolean needAdvance) {
+ public Glyph(final String str, final boolean needAdvance) {
this.str = str;
this.needAdvance = needAdvance;
}
@@ -1422,14 +1449,14 @@ public class TextRenderer {
}
/** Draws this glyph and returns the (x) advance for this glyph */
- public float draw3D(float inX, float inY, float z, float scaleFactor) {
+ public float draw3D(final float inX, final float inY, final float z, final float scaleFactor) {
if (str != null) {
draw3D_ROBUST(str, inX, inY, z, scaleFactor);
if (!needAdvance) {
return 0;
}
// Compute and return the advance for this string
- GlyphVector gv = font.createGlyphVector(getFontRenderContext(), str);
+ final GlyphVector gv = font.createGlyphVector(getFontRenderContext(), str);
float totalAdvance = 0;
for (int i = 0; i < gv.getNumGlyphs(); i++) {
totalAdvance += gv.getGlyphMetrics(i).getAdvance();
@@ -1447,32 +1474,32 @@ public class TextRenderer {
mPipelinedQuadRenderer = new Pipelined_QuadRenderer();
}
- TextureRenderer renderer = getBackingStore();
+ final TextureRenderer renderer = getBackingStore();
// Handles case where NPOT texture is used for backing store
- TextureCoords wholeImageTexCoords = renderer.getTexture().getImageTexCoords();
- float xScale = wholeImageTexCoords.right();
- float yScale = wholeImageTexCoords.bottom();
+ final TextureCoords wholeImageTexCoords = renderer.getTexture().getImageTexCoords();
+ final float xScale = wholeImageTexCoords.right();
+ final float yScale = wholeImageTexCoords.bottom();
- Rect rect = glyphRectForTextureMapping;
- TextData data = (TextData) rect.getUserData();
+ final Rect rect = glyphRectForTextureMapping;
+ final TextData data = (TextData) rect.getUserData();
data.markUsed();
- Rectangle2D origRect = data.origRect();
+ final Rectangle2D origRect = data.origRect();
- float x = inX - (scaleFactor * data.origOriginX());
- float y = inY - (scaleFactor * ((float) origRect.getHeight() - data.origOriginY()));
+ final float x = inX - (scaleFactor * data.origOriginX());
+ final float y = inY - (scaleFactor * ((float) origRect.getHeight() - data.origOriginY()));
- int texturex = rect.x() + (data.origin().x - data.origOriginX());
- int texturey = renderer.getHeight() - rect.y() - (int) origRect.getHeight() -
+ final int texturex = rect.x() + (data.origin().x - data.origOriginX());
+ final int texturey = renderer.getHeight() - rect.y() - (int) origRect.getHeight() -
(data.origin().y - data.origOriginY());
- int width = (int) origRect.getWidth();
- int height = (int) origRect.getHeight();
+ final int width = (int) origRect.getWidth();
+ final int height = (int) origRect.getHeight();
- float tx1 = xScale * (float) texturex / (float) renderer.getWidth();
- float ty1 = yScale * (1.0f -
+ final float tx1 = xScale * texturex / renderer.getWidth();
+ final float ty1 = yScale * (1.0f -
((float) texturey / (float) renderer.getHeight()));
- float tx2 = xScale * (float) (texturex + width) / (float) renderer.getWidth();
- float ty2 = yScale * (1.0f -
+ final float tx2 = xScale * (texturex + width) / renderer.getWidth();
+ final float ty2 = yScale * (1.0f -
((float) (texturey + height) / (float) renderer.getHeight()));
mPipelinedQuadRenderer.glTexCoord2f(tx1, ty1);
@@ -1486,7 +1513,7 @@ public class TextRenderer {
mPipelinedQuadRenderer.glTexCoord2f(tx1, ty2);
mPipelinedQuadRenderer.glVertex3f(x,
y + (height * scaleFactor), z);
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
return advance;
@@ -1498,21 +1525,21 @@ public class TextRenderer {
}
private void upload() {
- GlyphVector gv = getGlyphVector();
- Rectangle2D origBBox = preNormalize(renderDelegate.getBounds(gv, getFontRenderContext()));
- Rectangle2D bbox = normalize(origBBox);
- Point origin = new Point((int) -bbox.getMinX(),
+ final GlyphVector gv = getGlyphVector();
+ final Rectangle2D origBBox = preNormalize(renderDelegate.getBounds(gv, getFontRenderContext()));
+ final Rectangle2D bbox = normalize(origBBox);
+ final Point origin = new Point((int) -bbox.getMinX(),
(int) -bbox.getMinY());
- Rect rect = new Rect(0, 0, (int) bbox.getWidth(),
+ final Rect rect = new Rect(0, 0, (int) bbox.getWidth(),
(int) bbox.getHeight(),
new TextData(null, origin, origBBox, unicodeID));
packer.add(rect);
glyphRectForTextureMapping = rect;
- Graphics2D g = getGraphics2D();
+ final Graphics2D g = getGraphics2D();
// OK, should now have an (x, y) for this rectangle; rasterize
// the glyph
- int strx = rect.x() + origin.x;
- int stry = rect.y() + origin.y;
+ final int strx = rect.x() + origin.x;
+ final int stry = rect.y() + origin.y;
// Clear out the area we're going to draw into
g.setComposite(AlphaComposite.Clear);
@@ -1523,7 +1550,7 @@ public class TextRenderer {
renderDelegate.drawGlyphVector(g, gv, strx, stry);
if (DRAW_BBOXES) {
- TextData data = (TextData) rect.getUserData();
+ final TextData data = (TextData) rect.getUserData();
// Draw a bounding box on the backing store
g.drawRect(strx - data.origOriginX(),
stry - data.origOriginY(),
@@ -1543,7 +1570,7 @@ public class TextRenderer {
}
private GlyphVector getGlyphVector() {
- GlyphVector gv = singleUnicodeGlyphVector;
+ final GlyphVector gv = singleUnicodeGlyphVector;
if (gv != null) {
singleUnicodeGlyphVector = null; // Don't need this anymore
return gv;
@@ -1554,11 +1581,11 @@ public class TextRenderer {
}
class GlyphProducer {
- final int undefined = -2;
- FontRenderContext fontRenderContext;
- List/*<Glyph>*/ glyphsOutput = new ArrayList/*<Glyph>*/();
- HashMap/*<String, GlyphVector>*/fullGlyphVectorCache = new HashMap/*<String, GlyphVector>*/();
- HashMap/*<Character, GlyphMetrics>*/glyphMetricsCache = new HashMap/*<Character, GlyphMetrics>*/();
+ static final int undefined = -2;
+ final FontRenderContext fontRenderContext = null; // FIXME: Never initialized!
+ List<Glyph> glyphsOutput = new ArrayList<Glyph>();
+ HashMap<String, GlyphVector> fullGlyphVectorCache = new HashMap<String, GlyphVector>();
+ HashMap<Character, GlyphMetrics> glyphMetricsCache = new HashMap<Character, GlyphMetrics>();
// The mapping from unicode character to font-specific glyph ID
int[] unicodes2Glyphs;
// The mapping from glyph ID to Glyph
@@ -1566,45 +1593,45 @@ public class TextRenderer {
// We re-use this for each incoming string
CharSequenceIterator iter = new CharSequenceIterator();
- GlyphProducer(int fontLengthInGlyphs) {
+ GlyphProducer(final int fontLengthInGlyphs) {
unicodes2Glyphs = new int[512];
glyphCache = new Glyph[fontLengthInGlyphs];
clearAllCacheEntries();
}
- public List/*<Glyph>*/ getGlyphs(CharSequence inString) {
+ public List<Glyph> getGlyphs(final CharSequence inString) {
glyphsOutput.clear();
GlyphVector fullRunGlyphVector;
- fullRunGlyphVector = (GlyphVector) fullGlyphVectorCache.get(inString.toString());
+ fullRunGlyphVector = fullGlyphVectorCache.get(inString.toString());
if (fullRunGlyphVector == null) {
iter.initFromCharSequence(inString);
fullRunGlyphVector = font.createGlyphVector(getFontRenderContext(), iter);
fullGlyphVectorCache.put(inString.toString(), fullRunGlyphVector);
}
- boolean complex = (fullRunGlyphVector.getLayoutFlags() != 0);
+ final boolean complex = (fullRunGlyphVector.getLayoutFlags() != 0);
if (complex || DISABLE_GLYPH_CACHE) {
// Punt to the robust version of the renderer
glyphsOutput.add(new Glyph(inString.toString(), false));
return glyphsOutput;
}
- int lengthInGlyphs = fullRunGlyphVector.getNumGlyphs();
+ final int lengthInGlyphs = fullRunGlyphVector.getNumGlyphs();
int i = 0;
while (i < lengthInGlyphs) {
- Character letter = CharacterCache.valueOf(inString.charAt(i));
- GlyphMetrics metrics = (GlyphMetrics) glyphMetricsCache.get(letter);
+ final Character letter = CharacterCache.valueOf(inString.charAt(i));
+ GlyphMetrics metrics = glyphMetricsCache.get(letter);
if (metrics == null) {
metrics = fullRunGlyphVector.getGlyphMetrics(i);
glyphMetricsCache.put(letter, metrics);
}
- Glyph glyph = getGlyph(inString, metrics, i);
+ final Glyph glyph = getGlyph(inString, metrics, i);
if (glyph != null) {
glyphsOutput.add(glyph);
i++;
} else {
// Assemble a run of characters that don't fit in
// the cache
- StringBuilder buf = new StringBuilder();
+ final StringBuilder buf = new StringBuilder();
while (i < lengthInGlyphs &&
getGlyph(inString, fullRunGlyphVector.getGlyphMetrics(i), i) == null) {
buf.append(inString.charAt(i++));
@@ -1617,10 +1644,10 @@ public class TextRenderer {
return glyphsOutput;
}
- public void clearCacheEntry(int unicodeID) {
- int glyphID = unicodes2Glyphs[unicodeID];
+ public void clearCacheEntry(final int unicodeID) {
+ final int glyphID = unicodes2Glyphs[unicodeID];
if (glyphID != undefined) {
- Glyph glyph = glyphCache[glyphID];
+ final Glyph glyph = glyphCache[glyphID];
if (glyph != null) {
glyph.clear();
}
@@ -1635,20 +1662,23 @@ public class TextRenderer {
}
}
- public void register(Glyph glyph) {
+ public void register(final Glyph glyph) {
unicodes2Glyphs[glyph.getUnicodeID()] = glyph.getGlyphCode();
glyphCache[glyph.getGlyphCode()] = glyph;
}
- public float getGlyphPixelWidth(char unicodeID) {
- Glyph glyph = getGlyph(unicodeID);
+ public float getGlyphPixelWidth(final char unicodeID) {
+ final Glyph glyph = getGlyph(unicodeID);
if (glyph != null) {
return glyph.getAdvance();
}
// Have to do this the hard / uncached way
singleUnicode[0] = unicodeID;
- GlyphVector gv = font.createGlyphVector(fontRenderContext,
+ if( null == fontRenderContext ) { // FIXME: Never initialized!
+ throw new InternalError("fontRenderContext never initialized!");
+ }
+ final GlyphVector gv = font.createGlyphVector(fontRenderContext,
singleUnicode);
return gv.getGlyphMetrics(0).getAdvance();
}
@@ -1656,52 +1686,52 @@ public class TextRenderer {
// Returns a glyph object for this single glyph. Returns null
// if the unicode or glyph ID would be out of bounds of the
// glyph cache.
- private Glyph getGlyph(CharSequence inString,
- GlyphMetrics glyphMetrics,
- int index) {
- char unicodeID = inString.charAt(index);
+ private Glyph getGlyph(final CharSequence inString,
+ final GlyphMetrics glyphMetrics,
+ final int index) {
+ final char unicodeID = inString.charAt(index);
if (unicodeID >= unicodes2Glyphs.length) {
return null;
}
- int glyphID = unicodes2Glyphs[unicodeID];
+ final int glyphID = unicodes2Glyphs[unicodeID];
if (glyphID != undefined) {
return glyphCache[glyphID];
}
// Must fabricate the glyph
singleUnicode[0] = unicodeID;
- GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode);
+ final GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode);
return getGlyph(unicodeID, gv, glyphMetrics);
}
// It's unclear whether this variant might produce less
// optimal results than if we can see the entire GlyphVector
// for the incoming string
- private Glyph getGlyph(int unicodeID) {
+ private Glyph getGlyph(final int unicodeID) {
if (unicodeID >= unicodes2Glyphs.length) {
return null;
}
- int glyphID = unicodes2Glyphs[unicodeID];
+ final int glyphID = unicodes2Glyphs[unicodeID];
if (glyphID != undefined) {
return glyphCache[glyphID];
}
singleUnicode[0] = (char) unicodeID;
- GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode);
+ final GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode);
return getGlyph(unicodeID, gv, gv.getGlyphMetrics(0));
}
- private Glyph getGlyph(int unicodeID,
- GlyphVector singleUnicodeGlyphVector,
- GlyphMetrics metrics) {
- int glyphCode = singleUnicodeGlyphVector.getGlyphCode(0);
+ private Glyph getGlyph(final int unicodeID,
+ final GlyphVector singleUnicodeGlyphVector,
+ final GlyphMetrics metrics) {
+ final int glyphCode = singleUnicodeGlyphVector.getGlyphCode(0);
// Have seen huge glyph codes (65536) coming out of some fonts in some Unicode situations
if (glyphCode >= glyphCache.length) {
return null;
}
- Glyph glyph = new Glyph(unicodeID,
+ final Glyph glyph = new Glyph(unicodeID,
glyphCode,
metrics.getAdvance(),
singleUnicodeGlyphVector,
@@ -1710,7 +1740,7 @@ public class TextRenderer {
return glyph;
}
}
-
+
private static class CharacterCache {
private CharacterCache() {
}
@@ -1719,15 +1749,15 @@ public class TextRenderer {
static {
for (int i = 0; i < cache.length; i++) {
- cache[i] = new Character((char) i);
+ cache[i] = Character.valueOf((char) i);
}
}
- public static Character valueOf(char c) {
+ public static Character valueOf(final char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[c];
}
- return new Character(c);
+ return Character.valueOf(c);
}
}
@@ -1740,7 +1770,7 @@ public class TextRenderer {
int mVBO_For_ResuableTileTexCoords;
Pipelined_QuadRenderer() {
- GL2 gl = GLContext.getCurrentGL().getGL2();
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
mVertCoords = Buffers.newDirectFloatBuffer(kTotalBufferSizeCoordsVerts);
mTexCoords = Buffers.newDirectFloatBuffer(kTotalBufferSizeCoordsTex);
@@ -1748,34 +1778,34 @@ public class TextRenderer {
if (usingVBOs) {
try {
- int[] vbos = new int[2];
+ final int[] vbos = new int[2];
gl.glGenBuffers(2, IntBuffer.wrap(vbos));
mVBO_For_ResuableTileVertices = vbos[0];
mVBO_For_ResuableTileTexCoords = vbos[1];
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER,
mVBO_For_ResuableTileVertices);
- gl.glBufferData(GL2.GL_ARRAY_BUFFER, kTotalBufferSizeBytesVerts,
- null, GL2.GL_STREAM_DRAW); // stream draw because this is a single quad use pipeline
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, kTotalBufferSizeBytesVerts,
+ null, GL2ES2.GL_STREAM_DRAW); // stream draw because this is a single quad use pipeline
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER,
mVBO_For_ResuableTileTexCoords);
- gl.glBufferData(GL2.GL_ARRAY_BUFFER, kTotalBufferSizeBytesTex,
- null, GL2.GL_STREAM_DRAW); // stream draw because this is a single quad use pipeline
- } catch (Exception e) {
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, kTotalBufferSizeBytesTex,
+ null, GL2ES2.GL_STREAM_DRAW); // stream draw because this is a single quad use pipeline
+ } catch (final Exception e) {
isExtensionAvailable_GL_VERSION_1_5 = false;
usingVBOs = false;
}
}
}
- public void glTexCoord2f(float v, float v1) {
+ public void glTexCoord2f(final float v, final float v1) {
mTexCoords.put(v);
mTexCoords.put(v1);
}
- public void glVertex3f(float inX, float inY, float inZ) {
+ public void glVertex3f(final float inX, final float inY, final float inZ) {
mVertCoords.put(inX);
mVertCoords.put(inY);
mVertCoords.put(inZ);
@@ -1797,41 +1827,41 @@ public class TextRenderer {
private void drawVertexArrays() {
if (mOutstandingGlyphsVerticesPipeline > 0) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
- TextureRenderer renderer = getBackingStore();
- Texture texture = renderer.getTexture(); // triggers texture uploads. Maybe this should be more obvious?
+ final TextureRenderer renderer = getBackingStore();
+ renderer.getTexture(); // triggers texture uploads. Maybe this should be more obvious?
mVertCoords.rewind();
mTexCoords.rewind();
- gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
if (usingVBOs) {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER,
mVBO_For_ResuableTileVertices);
- gl.glBufferSubData(GL2.GL_ARRAY_BUFFER, 0,
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, 0,
mOutstandingGlyphsVerticesPipeline * kSizeInBytes_OneVertices_VertexData,
mVertCoords); // upload only the new stuff
- gl.glVertexPointer(3, GL2.GL_FLOAT, 0, 0);
+ gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
} else {
- gl.glVertexPointer(3, GL2.GL_FLOAT, 0, mVertCoords);
+ gl.glVertexPointer(3, GL.GL_FLOAT, 0, mVertCoords);
}
- gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
+ gl.glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
if (usingVBOs) {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER,
mVBO_For_ResuableTileTexCoords);
- gl.glBufferSubData(GL2.GL_ARRAY_BUFFER, 0,
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, 0,
mOutstandingGlyphsVerticesPipeline * kSizeInBytes_OneVertices_TexData,
mTexCoords); // upload only the new stuff
- gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, 0);
+ gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0);
} else {
- gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, mTexCoords);
+ gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, mTexCoords);
}
- gl.glDrawArrays(GL2.GL_QUADS, 0,
+ gl.glDrawArrays(GL2GL3.GL_QUADS, 0,
mOutstandingGlyphsVerticesPipeline);
mVertCoords.rewind();
@@ -1842,14 +1872,14 @@ public class TextRenderer {
private void drawIMMEDIATE() {
if (mOutstandingGlyphsVerticesPipeline > 0) {
- TextureRenderer renderer = getBackingStore();
- Texture texture = renderer.getTexture(); // triggers texture uploads. Maybe this should be more obvious?
+ final TextureRenderer renderer = getBackingStore();
+ renderer.getTexture(); // triggers texture uploads. Maybe this should be more obvious?
- GL2 gl = GLContext.getCurrentGL().getGL2();
- gl.glBegin(GL2.GL_QUADS);
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ gl.glBegin(GL2GL3.GL_QUADS);
try {
- int numberOfQuads = mOutstandingGlyphsVerticesPipeline / 4;
+ final int numberOfQuads = mOutstandingGlyphsVerticesPipeline / 4;
mVertCoords.rewind();
mTexCoords.rewind();
@@ -1870,7 +1900,7 @@ public class TextRenderer {
gl.glVertex3f(mVertCoords.get(), mVertCoords.get(),
mVertCoords.get());
}
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
} finally {
gl.glEnd();
@@ -1886,20 +1916,21 @@ public class TextRenderer {
private GLU glu;
private Frame frame;
- DebugListener(GL gl, Frame frame) {
+ DebugListener(final GL gl, final Frame frame) {
this.glu = GLU.createGLU(gl);
this.frame = frame;
}
- public void display(GLAutoDrawable drawable) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
- gl.glClear(GL2.GL_DEPTH_BUFFER_BIT | GL2.GL_COLOR_BUFFER_BIT);
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ gl.glClear(GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT);
if (packer == null) {
return;
}
- TextureRenderer rend = getBackingStore();
+ final TextureRenderer rend = getBackingStore();
final int w = rend.getWidth();
final int h = rend.getHeight();
rend.beginOrthoRendering(w, h);
@@ -1908,6 +1939,7 @@ public class TextRenderer {
if ((frame.getWidth() != w) || (frame.getHeight() != h)) {
EventQueue.invokeLater(new Runnable() {
+ @Override
public void run() {
frame.setSize(w, h);
}
@@ -1915,22 +1947,24 @@ public class TextRenderer {
}
}
- public void dispose(GLAutoDrawable drawable) {
- glu.destroy();
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
glu=null;
frame=null;
}
// Unused methods
- public void init(GLAutoDrawable drawable) {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width,
- int height) {
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width,
+ final int height) {
}
- public void displayChanged(GLAutoDrawable drawable,
- boolean modeChanged, boolean deviceChanged) {
+ public void displayChanged(final GLAutoDrawable drawable,
+ final boolean modeChanged, final boolean deviceChanged) {
}
}
@@ -1941,7 +1975,7 @@ public class TextRenderer {
* certain graphics cards which have poor vertex array
* performance. Defaults to true.
*/
- public void setUseVertexArrays(boolean useVertexArrays) {
+ public void setUseVertexArrays(final boolean useVertexArrays) {
this.useVertexArrays = useVertexArrays;
}
@@ -1960,7 +1994,7 @@ public class TextRenderer {
* graphics cards do not behave well when this is enabled,
* resulting in fuzzy text. Defaults to true.
*/
- public void setSmoothing(boolean smoothing) {
+ public void setSmoothing(final boolean smoothing) {
this.smoothing = smoothing;
getBackingStore().setSmoothing(smoothing);
}
@@ -1975,7 +2009,7 @@ public class TextRenderer {
return smoothing;
}
- private final boolean is15Available(GL gl) {
+ private final boolean is15Available(final GL gl) {
if (!checkFor_isExtensionAvailable_GL_VERSION_1_5) {
isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable(GLExtensions.VERSION_1_5);
checkFor_isExtensionAvailable_GL_VERSION_1_5 = true;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java
index 922fc69c1..ef59f9fa0 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -48,7 +48,10 @@ import java.awt.Rectangle;
import java.awt.image.*;
import javax.media.opengl.*;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.gl2.*;
+
import com.jogamp.opengl.util.texture.*;
import com.jogamp.opengl.util.texture.awt.*;
@@ -70,10 +73,10 @@ public class TextureRenderer {
// appropriate threads, which would be somewhat unfortunate.
// Whether we have an alpha channel in the (RGB/A) backing store
- private boolean alpha;
+ private final boolean alpha;
// Whether we're using only a GL_INTENSITY backing store
- private boolean intensity;
+ private final boolean intensity;
// Whether we're attempting to use automatic mipmap generation support
private boolean mipmap;
@@ -91,7 +94,7 @@ public class TextureRenderer {
private boolean mustReallocateTexture;
private Rectangle dirtyRegion;
- private GLUgl2 glu = new GLUgl2();
+ private final GLUgl2 glu = new GLUgl2();
// Current color
private float r = 1.0f;
@@ -108,7 +111,7 @@ public class TextureRenderer {
@param height the height of the texture to render into
@param alpha whether to allocate an alpha channel for the texture
*/
- public TextureRenderer(int width, int height, boolean alpha) {
+ public TextureRenderer(final int width, final int height, final boolean alpha) {
this(width, height, alpha, false);
}
@@ -123,13 +126,13 @@ public class TextureRenderer {
@param alpha whether to allocate an alpha channel for the texture
@param mipmap whether to attempt use of automatic mipmap generation
*/
- public TextureRenderer(int width, int height, boolean alpha, boolean mipmap) {
+ public TextureRenderer(final int width, final int height, final boolean alpha, final boolean mipmap) {
this(width, height, alpha, false, mipmap);
}
// Internal constructor to avoid confusion since alpha only makes
// sense when intensity is not set
- private TextureRenderer(int width, int height, boolean alpha, boolean intensity, boolean mipmap) {
+ private TextureRenderer(final int width, final int height, final boolean alpha, final boolean intensity, final boolean mipmap) {
this.alpha = alpha;
this.intensity = intensity;
this.mipmap = mipmap;
@@ -140,7 +143,7 @@ public class TextureRenderer {
which acts only as an alpha channel. No mipmap support is
requested. Internally, this associates a GL_INTENSITY OpenGL
texture with the backing store. */
- public static TextureRenderer createAlphaOnlyRenderer(int width, int height) {
+ public static TextureRenderer createAlphaOnlyRenderer(final int width, final int height) {
return createAlphaOnlyRenderer(width, height, false);
}
@@ -150,7 +153,7 @@ public class TextureRenderer {
better smoothing when rendering the TextureRenderer's contents
at a distance. Internally, this associates a GL_INTENSITY OpenGL
texture with the backing store. */
- public static TextureRenderer createAlphaOnlyRenderer(int width, int height, boolean mipmap) {
+ public static TextureRenderer createAlphaOnlyRenderer(final int width, final int height, final boolean mipmap) {
return new TextureRenderer(width, height, false, true, mipmap);
}
@@ -205,7 +208,7 @@ public class TextureRenderer {
@param height the new height of the backing store of this renderer
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void setSize(int width, int height) throws GLException {
+ public void setSize(final int width, final int height) throws GLException {
init(width, height);
}
@@ -216,7 +219,7 @@ public class TextureRenderer {
@param d the new size of the backing store of this renderer
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void setSize(Dimension d) throws GLException {
+ public void setSize(final Dimension d) throws GLException {
setSize(d.width, d.height);
}
@@ -228,7 +231,7 @@ public class TextureRenderer {
@param smoothing whether smoothing is enabled for the OpenGL texture
*/
- public void setSmoothing(boolean smoothing) {
+ public void setSmoothing(final boolean smoothing) {
this.smoothing = smoothing;
smoothingChanged = true;
}
@@ -275,8 +278,8 @@ public class TextureRenderer {
@param width the width of the region to update
@param height the height of the region to update
*/
- public void markDirty(int x, int y, int width, int height) {
- Rectangle curRegion = new Rectangle(x, y, width, height);
+ public void markDirty(final int x, final int y, final int width, final int height) {
+ final Rectangle curRegion = new Rectangle(x, y, width, height);
if (dirtyRegion == null) {
dirtyRegion = curRegion;
} else {
@@ -333,7 +336,7 @@ public class TextureRenderer {
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void beginOrthoRendering(int width, int height) throws GLException {
+ public void beginOrthoRendering(final int width, final int height) throws GLException {
beginOrthoRendering(width, height, true);
}
@@ -355,7 +358,7 @@ public class TextureRenderer {
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void beginOrthoRendering(int width, int height, boolean disableDepthTest) throws GLException {
+ public void beginOrthoRendering(final int width, final int height, final boolean disableDepthTest) throws GLException {
beginRendering(true, width, height, disableDepthTest);
}
@@ -399,15 +402,15 @@ public class TextureRenderer {
transparent, 1.0f = completely opaque
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void setColor(float r, float g, float b, float a) throws GLException {
- GL2 gl = GLContext.getCurrentGL().getGL2();
+ public void setColor(final float r, final float g, final float b, final float a) throws GLException {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
this.r = r * a;
this.g = g * a;
this.b = b * a;
this.a = a;
gl.glColor4f(this.r, this.g, this.b, this.a);
- }
+ }
private float[] compArray;
/** Changes the current color of this TextureRenderer to the
@@ -417,7 +420,7 @@ public class TextureRenderer {
@param color the new color to use for rendering
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void setColor(Color color) throws GLException {
+ public void setColor(final Color color) throws GLException {
// Get color's RGBA components as floats in the range [0,1].
if (compArray == null) {
compArray = new float[4];
@@ -437,10 +440,10 @@ public class TextureRenderer {
@param screenx the on-screen x coordinate at which to draw the rectangle
@param screeny the on-screen y coordinate (relative to lower left) at
which to draw the rectangle
-
+
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void drawOrthoRect(int screenx, int screeny) throws GLException {
+ public void drawOrthoRect(final int screenx, final int screeny) throws GLException {
drawOrthoRect(screenx, screeny, 0, 0, getWidth(), getHeight());
}
@@ -459,12 +462,12 @@ public class TextureRenderer {
rectangle to draw
@param width the width of the rectangle to draw
@param height the height of the rectangle to draw
-
+
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void drawOrthoRect(int screenx, int screeny,
- int texturex, int texturey,
- int width, int height) throws GLException {
+ public void drawOrthoRect(final int screenx, final int screeny,
+ final int texturex, final int texturey,
+ final int width, final int height) throws GLException {
draw3DRect(screenx, screeny, 0, texturex, texturey, width, height, 1);
}
@@ -490,19 +493,19 @@ public class TextureRenderer {
@param height the height in texels of the rectangle to draw
@param scaleFactor the scale factor to apply (multiplicatively)
to the size of the drawn rectangle
-
+
@throws GLException If an OpenGL context is not current when this method is called
*/
- public void draw3DRect(float x, float y, float z,
- int texturex, int texturey,
- int width, int height,
- float scaleFactor) throws GLException {
- GL2 gl = GLContext.getCurrentGL().getGL2();
- Texture texture = getTexture();
- TextureCoords coords = texture.getSubImageTexCoords(texturex, texturey,
+ public void draw3DRect(final float x, final float y, final float z,
+ final int texturex, final int texturey,
+ final int width, final int height,
+ final float scaleFactor) throws GLException {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ final Texture texture = getTexture();
+ final TextureCoords coords = texture.getSubImageTexCoords(texturex, texturey,
texturex + width,
texturey + height);
- gl.glBegin(GL2.GL_QUADS);
+ gl.glBegin(GL2GL3.GL_QUADS);
gl.glTexCoord2f(coords.left(), coords.bottom());
gl.glVertex3f(x, y, z);
gl.glTexCoord2f(coords.right(), coords.bottom());
@@ -518,7 +521,7 @@ public class TextureRenderer {
OpenGL texture to the screen, if the application intends to draw
them as a flat overlay on to the screen. Must be used if {@link
#beginOrthoRendering} is used to set up the rendering stage for
- this overlay.
+ this overlay.
@throws GLException If an OpenGL context is not current when this method is called
*/
@@ -550,70 +553,70 @@ public class TextureRenderer {
// Internals only below this point
//
- private void beginRendering(boolean ortho, int width, int height, boolean disableDepthTestForOrtho) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
- int attribBits =
- GL2.GL_ENABLE_BIT | GL2.GL_TEXTURE_BIT | GL2.GL_COLOR_BUFFER_BIT |
- (ortho ? (GL2.GL_DEPTH_BUFFER_BIT | GL2.GL_TRANSFORM_BIT) : 0);
+ private void beginRendering(final boolean ortho, final int width, final int height, final boolean disableDepthTestForOrtho) {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ final int attribBits =
+ GL2.GL_ENABLE_BIT | GL2.GL_TEXTURE_BIT | GL.GL_COLOR_BUFFER_BIT |
+ (ortho ? (GL.GL_DEPTH_BUFFER_BIT | GL2.GL_TRANSFORM_BIT) : 0);
gl.glPushAttrib(attribBits);
- gl.glDisable(GL2.GL_LIGHTING);
+ gl.glDisable(GLLightingFunc.GL_LIGHTING);
if (ortho) {
if (disableDepthTestForOrtho) {
- gl.glDisable(GL2.GL_DEPTH_TEST);
+ gl.glDisable(GL.GL_DEPTH_TEST);
}
- gl.glDisable(GL2.GL_CULL_FACE);
- gl.glMatrixMode(GL2.GL_PROJECTION);
+ gl.glDisable(GL.GL_CULL_FACE);
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
glu.gluOrtho2D(0, width, 0, height);
- gl.glMatrixMode(GL2.GL_MODELVIEW);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
- gl.glMatrixMode(GL2.GL_TEXTURE);
+ gl.glMatrixMode(GL.GL_TEXTURE);
gl.glPushMatrix();
gl.glLoadIdentity();
}
- gl.glEnable(GL2.GL_BLEND);
- gl.glBlendFunc(GL2.GL_ONE, GL2.GL_ONE_MINUS_SRC_ALPHA);
- Texture texture = getTexture();
+ gl.glEnable(GL.GL_BLEND);
+ gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+ final Texture texture = getTexture();
texture.enable(gl);
texture.bind(gl);
- gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);
+ gl.glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_TEXTURE_ENV_MODE, GL2ES1.GL_MODULATE);
// Change polygon color to last saved
gl.glColor4f(r, g, b, a);
if (smoothingChanged) {
smoothingChanged = false;
if (smoothing) {
- texture.setTexParameteri(gl, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
+ texture.setTexParameteri(gl, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
if (mipmap) {
- texture.setTexParameteri(gl, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR_MIPMAP_LINEAR);
+ texture.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR);
} else {
- texture.setTexParameteri(gl, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
+ texture.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
}
} else {
- texture.setTexParameteri(gl, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
- texture.setTexParameteri(gl, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
+ texture.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
+ texture.setTexParameteri(gl, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
}
}
}
- private void endRendering(boolean ortho) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
- Texture texture = getTexture();
+ private void endRendering(final boolean ortho) {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ final Texture texture = getTexture();
texture.disable(gl);
if (ortho) {
- gl.glMatrixMode(GL2.GL_PROJECTION);
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glPopMatrix();
- gl.glMatrixMode(GL2.GL_MODELVIEW);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glPopMatrix();
- gl.glMatrixMode(GL2.GL_TEXTURE);
+ gl.glMatrixMode(GL.GL_TEXTURE);
gl.glPopMatrix();
}
gl.glPopAttrib();
}
- private void init(int width, int height) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
+ private void init(final int width, final int height) {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
// Discard previous BufferedImage if any
if (image != null) {
image.flush();
@@ -621,8 +624,8 @@ public class TextureRenderer {
}
// Infer the internal format if not an intensity texture
- int internalFormat = (intensity ? GL2.GL_INTENSITY : 0);
- int imageType =
+ final int internalFormat = (intensity ? GL2.GL_INTENSITY : 0);
+ final int imageType =
(intensity ? BufferedImage.TYPE_BYTE_GRAY :
(alpha ? BufferedImage.TYPE_INT_ARGB_PRE : BufferedImage.TYPE_INT_RGB));
image = new BufferedImage(width, height, imageType);
@@ -650,9 +653,9 @@ public class TextureRenderer {
@throws GLException If an OpenGL context is not current when this method is called
*/
- private void sync(int x, int y, int width, int height) throws GLException {
+ private void sync(final int x, final int y, final int width, final int height) throws GLException {
// Force allocation if necessary
- boolean canSkipUpdate = ensureTexture();
+ final boolean canSkipUpdate = ensureTexture();
if (!canSkipUpdate) {
// Update specified region.
@@ -667,7 +670,7 @@ public class TextureRenderer {
// Returns true if the texture was newly allocated, false if not
private boolean ensureTexture() {
- GL gl = GLContext.getCurrentGL();
+ final GL gl = GLContext.getCurrentGL();
if (mustReallocateTexture) {
if (texture != null) {
texture.destroy(gl);
@@ -688,8 +691,8 @@ public class TextureRenderer {
if (!smoothing) {
// The TextureIO classes default to GL_LINEAR filtering
- texture.setTexParameteri(gl, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
- texture.setTexParameteri(gl, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
+ texture.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
+ texture.setTexParameteri(gl, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
}
return true;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapCharRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapCharRec.java
index 34685e1b2..1f055211d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapCharRec.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapCharRec.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,8 +41,8 @@ package com.jogamp.opengl.util.gl2;
/* Copyright (c) Mark J. Kilgard, 1994, 1998. */
-/* This program is freely distributable without licensing fees
- and is provided without guarantee or warrantee expressed or
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
class BitmapCharRec {
@@ -53,12 +53,12 @@ class BitmapCharRec {
public float advance;
public byte[] bitmap;
- public BitmapCharRec(int width,
- int height,
- float xorig,
- float yorig,
- float advance,
- byte[] bitmap) {
+ public BitmapCharRec(final int width,
+ final int height,
+ final float xorig,
+ final float yorig,
+ final float advance,
+ final byte[] bitmap) {
this.width = width;
this.height = height;
this.xorig = xorig;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapFontRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapFontRec.java
index 18f7d3b28..7b8418704 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapFontRec.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapFontRec.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,8 +41,8 @@ package com.jogamp.opengl.util.gl2;
/* Copyright (c) Mark J. Kilgard, 1994, 1998. */
-/* This program is freely distributable without licensing fees
- and is provided without guarantee or warrantee expressed or
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
class BitmapFontRec {
@@ -51,10 +51,10 @@ class BitmapFontRec {
public int first;
public BitmapCharRec[] ch;
- public BitmapFontRec(String name,
- int num_chars,
- int first,
- BitmapCharRec[] ch) {
+ public BitmapFontRec(final String name,
+ final int num_chars,
+ final int first,
+ final BitmapCharRec[] ch) {
this.name = name;
this.num_chars = num_chars;
this.first = first;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/CoordRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/CoordRec.java
index 9ad95ec03..d79f16638 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/CoordRec.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/CoordRec.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,15 +41,15 @@ package com.jogamp.opengl.util.gl2;
/* Copyright (c) Mark J. Kilgard, 1994, 1998. */
-/* This program is freely distributable without licensing fees
- and is provided without guarantee or warrantee expressed or
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
class CoordRec {
public float x;
public float y;
- public CoordRec(float x, float y) {
+ public CoordRec(final float x, final float y) {
this.x = x;
this.y = y;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java
index 010ce6699..92cbd66da 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -40,6 +40,7 @@
package com.jogamp.opengl.util.gl2;
import javax.media.opengl.*;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
import javax.media.opengl.glu.*;
import javax.media.opengl.glu.gl2.*;
@@ -103,13 +104,13 @@ public class GLUT {
public static final int BITMAP_HELVETICA_12 = 7;
public static final int BITMAP_HELVETICA_18 = 8;
- private GLUgl2 glu = new GLUgl2();
+ private final GLUgl2 glu = new GLUgl2();
//----------------------------------------------------------------------
// Shapes
//
- public void glutWireSphere(double radius, int slices, int stacks) {
+ public void glutWireSphere(final double radius, final int slices, final int stacks) {
quadObjInit(glu);
glu.gluQuadricDrawStyle(quadObj, GLU.GLU_LINE);
glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH);
@@ -119,7 +120,7 @@ public class GLUT {
glu.gluSphere(quadObj, radius, slices, stacks);
}
- public void glutSolidSphere(double radius, int slices, int stacks) {
+ public void glutSolidSphere(final double radius, final int slices, final int stacks) {
quadObjInit(glu);
glu.gluQuadricDrawStyle(quadObj, GLU.GLU_FILL);
glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH);
@@ -129,8 +130,8 @@ public class GLUT {
glu.gluSphere(quadObj, radius, slices, stacks);
}
- public void glutWireCone(double base, double height,
- int slices, int stacks) {
+ public void glutWireCone(final double base, final double height,
+ final int slices, final int stacks) {
quadObjInit(glu);
glu.gluQuadricDrawStyle(quadObj, GLU.GLU_LINE);
glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH);
@@ -140,8 +141,8 @@ public class GLUT {
glu.gluCylinder(quadObj, base, 0.0, height, slices, stacks);
}
- public void glutSolidCone(double base, double height,
- int slices, int stacks) {
+ public void glutSolidCone(final double base, final double height,
+ final int slices, final int stacks) {
quadObjInit(glu);
glu.gluQuadricDrawStyle(quadObj, GLU.GLU_FILL);
glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH);
@@ -151,7 +152,7 @@ public class GLUT {
glu.gluCylinder(quadObj, base, 0.0, height, slices, stacks);
}
- public void glutWireCylinder(double radius, double height, int slices, int stacks) {
+ public void glutWireCylinder(final double radius, final double height, final int slices, final int stacks) {
quadObjInit(glu);
glu.gluQuadricDrawStyle(quadObj, GLU.GLU_LINE);
glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH);
@@ -161,22 +162,22 @@ public class GLUT {
glu.gluCylinder(quadObj, radius, radius, height, slices, stacks);
}
- public void glutSolidCylinder(double radius, double height, int slices, int stacks) {
- GL2 gl = GLUgl2.getCurrentGL2();
-
+ public void glutSolidCylinder(final double radius, final double height, final int slices, final int stacks) {
+ final GL2 gl = GLUgl2.getCurrentGL2();
+
// Prepare table of points for drawing end caps
- double [] x = new double[slices];
- double [] y = new double[slices];
- double angleDelta = Math.PI * 2 / slices;
+ final double [] x = new double[slices];
+ final double [] y = new double[slices];
+ final double angleDelta = Math.PI * 2 / slices;
double angle = 0;
for (int i = 0 ; i < slices ; i ++) {
angle = i * angleDelta;
x[i] = Math.cos(angle) * radius;
y[i] = Math.sin(angle) * radius;
}
-
+
// Draw bottom cap
- gl.glBegin(GL2.GL_TRIANGLE_FAN);
+ gl.glBegin(GL.GL_TRIANGLE_FAN);
gl.glNormal3d(0,0,-1);
gl.glVertex3d(0,0,0);
for (int i = 0 ; i < slices ; i ++) {
@@ -184,9 +185,9 @@ public class GLUT {
}
gl.glVertex3d(x[0], y[0], 0);
gl.glEnd();
-
+
// Draw top cap
- gl.glBegin(GL2.GL_TRIANGLE_FAN);
+ gl.glBegin(GL.GL_TRIANGLE_FAN);
gl.glNormal3d(0,0,1);
gl.glVertex3d(0,0,height);
for (int i = 0 ; i < slices ; i ++) {
@@ -194,7 +195,7 @@ public class GLUT {
}
gl.glVertex3d(x[0], y[0], height);
gl.glEnd();
-
+
// Draw walls
quadObjInit(glu);
glu.gluQuadricDrawStyle(quadObj, GLU.GLU_FILL);
@@ -205,68 +206,68 @@ public class GLUT {
glu.gluCylinder(quadObj, radius, radius, height, slices, stacks);
}
- public void glutWireCube(float size) {
- drawBox(GLUgl2.getCurrentGL2(), size, GL2.GL_LINE_LOOP);
+ public void glutWireCube(final float size) {
+ drawBox(GLUgl2.getCurrentGL2(), size, GL.GL_LINE_LOOP);
}
- public void glutSolidCube(float size) {
- drawBox(GLUgl2.getCurrentGL2(), size, GL2.GL_QUADS);
+ public void glutSolidCube(final float size) {
+ drawBox(GLUgl2.getCurrentGL2(), size, GL2GL3.GL_QUADS);
}
- public void glutWireTorus(double innerRadius, double outerRadius,
- int nsides, int rings) {
- GL2 gl = GLUgl2.getCurrentGL2();
+ public void glutWireTorus(final double innerRadius, final double outerRadius,
+ final int nsides, final int rings) {
+ final GL2 gl = GLUgl2.getCurrentGL2();
gl.glPushAttrib(GL2.GL_POLYGON_BIT);
- gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
doughnut(gl, innerRadius, outerRadius, nsides, rings);
gl.glPopAttrib();
}
- public void glutSolidTorus(double innerRadius, double outerRadius,
- int nsides, int rings) {
+ public void glutSolidTorus(final double innerRadius, final double outerRadius,
+ final int nsides, final int rings) {
doughnut(GLUgl2.getCurrentGL2(), innerRadius, outerRadius, nsides, rings);
}
public void glutWireDodecahedron() {
- dodecahedron(GLUgl2.getCurrentGL2(), GL2.GL_LINE_LOOP);
+ dodecahedron(GLUgl2.getCurrentGL2(), GL.GL_LINE_LOOP);
}
public void glutSolidDodecahedron() {
- dodecahedron(GLUgl2.getCurrentGL2(), GL2.GL_TRIANGLE_FAN);
+ dodecahedron(GLUgl2.getCurrentGL2(), GL.GL_TRIANGLE_FAN);
}
public void glutWireOctahedron() {
- octahedron(GLUgl2.getCurrentGL2(), GL2.GL_LINE_LOOP);
+ octahedron(GLUgl2.getCurrentGL2(), GL.GL_LINE_LOOP);
}
public void glutSolidOctahedron() {
- octahedron(GLUgl2.getCurrentGL2(), GL2.GL_TRIANGLES);
+ octahedron(GLUgl2.getCurrentGL2(), GL.GL_TRIANGLES);
}
public void glutWireIcosahedron() {
- icosahedron(GLUgl2.getCurrentGL2(), GL2.GL_LINE_LOOP);
+ icosahedron(GLUgl2.getCurrentGL2(), GL.GL_LINE_LOOP);
}
public void glutSolidIcosahedron() {
- icosahedron(GLUgl2.getCurrentGL2(), GL2.GL_TRIANGLES);
+ icosahedron(GLUgl2.getCurrentGL2(), GL.GL_TRIANGLES);
}
public void glutWireTetrahedron() {
- tetrahedron(GLUgl2.getCurrentGL2(), GL2.GL_LINE_LOOP);
+ tetrahedron(GLUgl2.getCurrentGL2(), GL.GL_LINE_LOOP);
}
public void glutSolidTetrahedron() {
- tetrahedron(GLUgl2.getCurrentGL2(), GL2.GL_TRIANGLES);
+ tetrahedron(GLUgl2.getCurrentGL2(), GL.GL_TRIANGLES);
}
/**
* Renders the teapot as a solid shape of the specified size. The teapot is
* created in a way that replicates the C GLUT implementation.
- *
+ *
* @param scale
* the factor by which to scale the teapot
*/
- public void glutSolidTeapot(double scale) {
+ public void glutSolidTeapot(final double scale) {
glutSolidTeapot(scale, true);
}
@@ -278,28 +279,28 @@ public class GLUT {
* instead of the y=-1 plane). Both surface normals and texture coordinates
* for the teapot are generated. The teapot is generated with OpenGL
* evaluators.
- *
+ *
* @param scale
* the factor by which to scale the teapot
* @param cStyle
* whether to create the teapot in exactly the same way as in the C
* implementation of GLUT
*/
- public void glutSolidTeapot(double scale, boolean cStyle) {
- teapot(GLUgl2.getCurrentGL2(), 14, scale, GL2.GL_FILL, cStyle);
+ public void glutSolidTeapot(final double scale, final boolean cStyle) {
+ teapot(GLUgl2.getCurrentGL2(), 14, scale, GL2GL3.GL_FILL, cStyle);
}
/**
* Renders the teapot as a wireframe shape of the specified size. The teapot
* is created in a way that replicates the C GLUT implementation.
- *
+ *
* @param scale
* the factor by which to scale the teapot
*/
- public void glutWireTeapot(double scale) {
+ public void glutWireTeapot(final double scale) {
glutWireTeapot(scale, true);
}
-
+
/**
* Renders the teapot as a wireframe shape of the specified size. The teapot
* can either be created in a way that is backward-compatible with the
@@ -308,29 +309,29 @@ public class GLUT {
* plane, instead of the y=-1 plane). Both surface normals and texture
* coordinates for the teapot are generated. The teapot is generated with
* OpenGL evaluators.
- *
+ *
* @param scale
* the factor by which to scale the teapot
* @param cStyle
* whether to create the teapot in exactly the same way as in the C
* implementation of GLUT
*/
- public void glutWireTeapot(double scale, boolean cStyle) {
- teapot(GLUgl2.getCurrentGL2(), 10, scale, GL2.GL_LINE, cStyle);
+ public void glutWireTeapot(final double scale, final boolean cStyle) {
+ teapot(GLUgl2.getCurrentGL2(), 10, scale, GL2GL3.GL_LINE, cStyle);
}
//----------------------------------------------------------------------
// Fonts
//
- public void glutBitmapCharacter(int font, char character) {
- GL2 gl = GLUgl2.getCurrentGL2();
- int[] swapbytes = new int[1];
- int[] lsbfirst = new int[1];
- int[] rowlength = new int[1];
- int[] skiprows = new int[1];
- int[] skippixels = new int[1];
- int[] alignment = new int[1];
+ public void glutBitmapCharacter(final int font, final char character) {
+ final GL2 gl = GLUgl2.getCurrentGL2();
+ final int[] swapbytes = new int[1];
+ final int[] lsbfirst = new int[1];
+ final int[] rowlength = new int[1];
+ final int[] skiprows = new int[1];
+ final int[] skippixels = new int[1];
+ final int[] alignment = new int[1];
beginBitmap(gl,
swapbytes,
lsbfirst,
@@ -348,26 +349,26 @@ public class GLUT {
alignment);
}
- public void glutBitmapString (int font, String string) {
- GL2 gl = GLUgl2.getCurrentGL2();
- int[] swapbytes = new int[1];
- int[] lsbfirst = new int[1];
- int[] rowlength = new int[1];
- int[] skiprows = new int[1];
- int[] skippixels = new int[1];
- int[] alignment = new int[1];
- beginBitmap(gl,
+ public void glutBitmapString (final int font, final String string) {
+ final GL2 gl = GLUgl2.getCurrentGL2();
+ final int[] swapbytes = new int[1];
+ final int[] lsbfirst = new int[1];
+ final int[] rowlength = new int[1];
+ final int[] skiprows = new int[1];
+ final int[] skippixels = new int[1];
+ final int[] alignment = new int[1];
+ beginBitmap(gl,
swapbytes,
lsbfirst,
rowlength,
skiprows,
skippixels,
alignment);
- int len = string.length();
+ final int len = string.length();
for (int i = 0; i < len; i++) {
bitmapCharacterImpl(gl, font, string.charAt(i));
}
- endBitmap(gl,
+ endBitmap(gl,
swapbytes,
lsbfirst,
rowlength,
@@ -376,31 +377,31 @@ public class GLUT {
alignment);
}
- public int glutBitmapWidth (int font, char character) {
- BitmapFontRec fontinfo = getBitmapFont(font);
- int c = character & 0xFFFF;
+ public int glutBitmapWidth (final int font, final char character) {
+ final BitmapFontRec fontinfo = getBitmapFont(font);
+ final int c = character & 0xFFFF;
if (c < fontinfo.first || c >= fontinfo.first + fontinfo.num_chars)
return 0;
- BitmapCharRec ch = fontinfo.ch[c - fontinfo.first];
+ final BitmapCharRec ch = fontinfo.ch[c - fontinfo.first];
if (ch != null)
return (int) ch.advance;
else
return 0;
}
- public void glutStrokeCharacter(int font, char character) {
- GL2 gl = GLUgl2.getCurrentGL2();
- StrokeFontRec fontinfo = getStrokeFont(font);
- int c = character & 0xFFFF;
+ public void glutStrokeCharacter(final int font, final char character) {
+ final GL2 gl = GLUgl2.getCurrentGL2();
+ final StrokeFontRec fontinfo = getStrokeFont(font);
+ final int c = character & 0xFFFF;
if (c < 0 || c >= fontinfo.num_chars)
return;
- StrokeCharRec ch = fontinfo.ch[c];
+ final StrokeCharRec ch = fontinfo.ch[c];
if (ch != null) {
for (int i = 0; i < ch.num_strokes; i++) {
- StrokeRec stroke = ch.stroke[i];
- gl.glBegin(GL2.GL_LINE_STRIP);
+ final StrokeRec stroke = ch.stroke[i];
+ gl.glBegin(GL.GL_LINE_STRIP);
for (int j = 0; j < stroke.num_coords; j++) {
- CoordRec coord = stroke.coord[j];
+ final CoordRec coord = stroke.coord[j];
gl.glVertex2f(coord.x, coord.y);
}
gl.glEnd();
@@ -409,21 +410,21 @@ public class GLUT {
}
}
- public void glutStrokeString(int font, String string) {
- GL2 gl = GLUgl2.getCurrentGL2();
- StrokeFontRec fontinfo = getStrokeFont(font);
- int len = string.length();
+ public void glutStrokeString(final int font, final String string) {
+ final GL2 gl = GLUgl2.getCurrentGL2();
+ final StrokeFontRec fontinfo = getStrokeFont(font);
+ final int len = string.length();
for (int pos = 0; pos < len; pos++) {
- int c = string.charAt(pos) & 0xFFFF;
+ final int c = string.charAt(pos) & 0xFFFF;
if (c < 0 || c >= fontinfo.num_chars)
continue;
- StrokeCharRec ch = fontinfo.ch[c];
+ final StrokeCharRec ch = fontinfo.ch[c];
if (ch != null) {
for (int i = 0; i < ch.num_strokes; i++) {
- StrokeRec stroke = ch.stroke[i];
- gl.glBegin(GL2.GL_LINE_STRIP);
+ final StrokeRec stroke = ch.stroke[i];
+ gl.glBegin(GL.GL_LINE_STRIP);
for (int j = 0; j < stroke.num_coords; j++) {
- CoordRec coord = stroke.coord[j];
+ final CoordRec coord = stroke.coord[j];
gl.glVertex2f(coord.x, coord.y);
}
gl.glEnd();
@@ -433,30 +434,30 @@ public class GLUT {
}
}
- public int glutStrokeWidth (int font, char character) {
+ public int glutStrokeWidth (final int font, final char character) {
return (int) glutStrokeWidthf(font, character);
}
- public float glutStrokeWidthf (int font, char character) {
- StrokeFontRec fontinfo = getStrokeFont(font);
- int c = character & 0xFFFF;
+ public float glutStrokeWidthf (final int font, final char character) {
+ final StrokeFontRec fontinfo = getStrokeFont(font);
+ final int c = character & 0xFFFF;
if (c < 0 || c >= fontinfo.num_chars)
return 0;
- StrokeCharRec ch = fontinfo.ch[c];
+ final StrokeCharRec ch = fontinfo.ch[c];
if (ch != null)
return ch.right;
else
return 0;
}
- public int glutBitmapLength (int font, String string) {
- BitmapFontRec fontinfo = getBitmapFont(font);
+ public int glutBitmapLength (final int font, final String string) {
+ final BitmapFontRec fontinfo = getBitmapFont(font);
int length = 0;
- int len = string.length();
+ final int len = string.length();
for (int pos = 0; pos < len; pos++) {
- int c = string.charAt(pos) & 0xFFFF;
+ final int c = string.charAt(pos) & 0xFFFF;
if (c >= fontinfo.first && c < fontinfo.first + fontinfo.num_chars) {
- BitmapCharRec ch = fontinfo.ch[c - fontinfo.first];
+ final BitmapCharRec ch = fontinfo.ch[c - fontinfo.first];
if (ch != null)
length += ch.advance;
}
@@ -464,18 +465,18 @@ public class GLUT {
return length;
}
- public int glutStrokeLength (int font, String string) {
+ public int glutStrokeLength (final int font, final String string) {
return (int) glutStrokeLengthf(font, string);
}
- public float glutStrokeLengthf (int font, String string) {
- StrokeFontRec fontinfo = getStrokeFont(font);
+ public float glutStrokeLengthf (final int font, final String string) {
+ final StrokeFontRec fontinfo = getStrokeFont(font);
float length = 0;
- int len = string.length();
+ final int len = string.length();
for (int i = 0; i < len; i++) {
- char c = string.charAt(i);
+ final char c = string.charAt(i);
if (c >= 0 && c < fontinfo.num_chars) {
- StrokeCharRec ch = fontinfo.ch[c];
+ final StrokeCharRec ch = fontinfo.ch[c];
if (ch != null)
length += ch.right;
}
@@ -491,9 +492,9 @@ public class GLUT {
The polyhedron is centered at the origin.
*/
public void glutWireRhombicDodecahedron() {
- GL2 gl = GLUgl2.getCurrentGL2();
+ final GL2 gl = GLUgl2.getCurrentGL2();
for( int i = 0; i < 12; i++ ) {
- gl.glBegin( GL2.GL_LINE_LOOP );
+ gl.glBegin( GL.GL_LINE_LOOP );
gl.glNormal3dv( rdod_n[ i ],0 );
gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 0 ] ],0 );
gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 1 ] ],0 );
@@ -502,7 +503,7 @@ public class GLUT {
gl.glEnd( );
}
}
-
+
/**
This function draws a solid-shaded dodecahedron
whose facets are rhombic and
@@ -511,8 +512,8 @@ public class GLUT {
The polyhedron is centered at the origin.
*/
public void glutSolidRhombicDodecahedron() {
- GL2 gl = GLUgl2.getCurrentGL2();
- gl.glBegin( GL2.GL_QUADS );
+ final GL2 gl = GLUgl2.getCurrentGL2();
+ gl.glBegin( GL2GL3.GL_QUADS );
for( int i = 0; i < 12; i++ ) {
gl.glNormal3dv( rdod_n[ i ],0 );
gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 0 ] ],0 );
@@ -522,7 +523,7 @@ public class GLUT {
}
gl.glEnd( );
}
-
+
//----------------------------------------------------------------------
// Internals only below this point
//
@@ -532,7 +533,7 @@ public class GLUT {
//
private GLUquadric quadObj;
- private void quadObjInit(GLUgl2 glu) {
+ private void quadObjInit(final GLUgl2 glu) {
if (quadObj == null) {
quadObj = glu.gluNewQuadric();
}
@@ -541,7 +542,7 @@ public class GLUT {
}
}
- private static void doughnut(GL2 gl, double r, double R, int nsides, int rings) {
+ private static void doughnut(final GL2 gl, final double r, final double R, final int nsides, final int rings) {
int i, j;
float theta, phi, theta1;
float cosTheta, sinTheta;
@@ -597,9 +598,9 @@ public class GLUT {
{5, 6, 2, 1},
{7, 4, 0, 3}
};
- private void drawBox(GL2 gl, float size, int type) {
+ private void drawBox(final GL2 gl, final float size, final int type) {
if (boxVertices == null) {
- float[][] v = new float[8][];
+ final float[][] v = new float[8][];
for (int i = 0; i < 8; i++) {
v[i] = new float[3];
}
@@ -611,9 +612,9 @@ public class GLUT {
v[1][2] = v[2][2] = v[5][2] = v[6][2] = 0.5f;
boxVertices = v;
}
- float[][] v = boxVertices;
- float[][] n = boxNormals;
- int[][] faces = boxFaces;
+ final float[][] v = boxVertices;
+ final float[][] n = boxNormals;
+ final int[][] faces = boxFaces;
for (int i = 5; i >= 0; i--) {
gl.glBegin(type);
gl.glNormal3fv(n[i], 0);
@@ -664,14 +665,14 @@ public class GLUT {
dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
}
- private static void diff3(float[] a, float[] b, float[] c) {
+ private static void diff3(final float[] a, final float[] b, final float[] c) {
c[0] = a[0] - b[0];
c[1] = a[1] - b[1];
c[2] = a[2] - b[2];
}
- private static void crossprod(float[] v1, float[] v2, float[] prod) {
- float[] p = new float[3]; /* in case prod == v1 or v2 */
+ private static void crossprod(final float[] v1, final float[] v2, final float[] prod) {
+ final float[] p = new float[3]; /* in case prod == v1 or v2 */
p[0] = v1[1] * v2[2] - v2[1] * v1[2];
p[1] = v1[2] * v2[0] - v2[2] * v1[0];
@@ -681,7 +682,7 @@ public class GLUT {
prod[2] = p[2];
}
- private static void normalize(float[] v) {
+ private static void normalize(final float[] v) {
float d;
d = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
@@ -694,10 +695,10 @@ public class GLUT {
v[2] *= d;
}
- private void pentagon(GL2 gl, int a, int b, int c, int d, int e, int shadeType) {
- float[] n0 = new float[3];
- float[] d1 = new float[3];
- float[] d2 = new float[3];
+ private void pentagon(final GL2 gl, final int a, final int b, final int c, final int d, final int e, final int shadeType) {
+ final float[] n0 = new float[3];
+ final float[] d1 = new float[3];
+ final float[] d2 = new float[3];
diff3(dodec[a], dodec[b], d1);
diff3(dodec[b], dodec[c], d2);
@@ -714,7 +715,7 @@ public class GLUT {
gl.glEnd();
}
- private void dodecahedron(GL2 gl, int type) {
+ private void dodecahedron(final GL2 gl, final int type) {
if (dodec == null) {
initDodecahedron();
}
@@ -732,9 +733,9 @@ public class GLUT {
pentagon(gl, 4, 12, 5, 16, 17, type);
}
- private static void recorditem(GL2 gl, float[] n1, float[] n2, float[] n3, int shadeType) {
- float[] q0 = new float[3];
- float[] q1 = new float[3];
+ private static void recorditem(final GL2 gl, final float[] n1, final float[] n2, final float[] n3, final int shadeType) {
+ final float[] q0 = new float[3];
+ final float[] q1 = new float[3];
diff3(n1, n2, q0);
diff3(n2, n3, q1);
@@ -749,11 +750,11 @@ public class GLUT {
gl.glEnd();
}
- private static void subdivide(GL2 gl, float[] v0, float[] v1, float[] v2, int shadeType) {
+ private static void subdivide(final GL2 gl, final float[] v0, final float[] v1, final float[] v2, final int shadeType) {
int depth;
- float[] w0 = new float[3];
- float[] w1 = new float[3];
- float[] w2 = new float[3];
+ final float[] w0 = new float[3];
+ final float[] w1 = new float[3];
+ final float[] w2 = new float[3];
float l;
int i, j, k, n;
@@ -785,10 +786,10 @@ public class GLUT {
}
}
- private static void drawtriangle(GL2 gl, int i, float[][] data, int[][] ndx, int shadeType) {
- float[] x0 = data[ndx[i][0]];
- float[] x1 = data[ndx[i][1]];
- float[] x2 = data[ndx[i][2]];
+ private static void drawtriangle(final GL2 gl, final int i, final float[][] data, final int[][] ndx, final int shadeType) {
+ final float[] x0 = data[ndx[i][0]];
+ final float[] x1 = data[ndx[i][1]];
+ final float[] x2 = data[ndx[i][2]];
subdivide(gl, x0, x1, x2, shadeType);
}
@@ -816,7 +817,7 @@ public class GLUT {
{1, 3, 5}
};
- private static void octahedron(GL2 gl, int shadeType) {
+ private static void octahedron(final GL2 gl, final int shadeType) {
int i;
for (i = 7; i >= 0; i--) {
@@ -870,7 +871,7 @@ public class GLUT {
{7, 2, 11},
};
- private static void icosahedron(GL2 gl, int shadeType) {
+ private static void icosahedron(final GL2 gl, final int shadeType) {
int i;
for (i = 19; i >= 0; i--) {
@@ -879,7 +880,7 @@ public class GLUT {
}
/* rhombic dodecahedron data: */
-
+
private static final double rdod_r[][] =
{
{ 0.0, 0.0, 1.0 },
@@ -897,7 +898,7 @@ public class GLUT {
{ 0.000000000000, -0.707106781187, -0.5 },
{ 0.0, 0.0, -1.0 }
};
-
+
private static final int rdod_v[][] =
{
{ 0, 1, 5, 2 },
@@ -913,7 +914,7 @@ public class GLUT {
{ 7, 11, 13, 12 },
{ 8, 12, 13, 9 }
};
-
+
private static final double rdod_n[][] =
{
{ 0.353553390594, 0.353553390594, 0.5 },
@@ -929,7 +930,7 @@ public class GLUT {
{ -0.353553390594, -0.353553390594, -0.5 },
{ 0.353553390594, -0.353553390594, -0.5 }
};
-
+
/* tetrahedron data: */
private static final float T = 1.73205080756887729f;
@@ -950,7 +951,7 @@ public class GLUT {
{1, 2, 3}
};
- private static final void tetrahedron(GL2 gl, int shadeType) {
+ private static final void tetrahedron(final GL2 gl, final int shadeType) {
for (int i = 3; i >= 0; i--)
drawtriangle(gl, i, tdata, tndex, shadeType);
}
@@ -1112,28 +1113,28 @@ public class GLUT {
0, 0, 1, 0, 0, 1, 1, 1
};
- private static void teapot(GL2 gl,
- int grid,
- double scale,
- int type,
- boolean backCompatible)
+ private static void teapot(final GL2 gl,
+ final int grid,
+ final double scale,
+ final int type,
+ final boolean backCompatible)
{
// As mentioned above, GL2.glMap2f expects a packed array of floats
- float[] p = new float[4*4*3];
- float[] q = new float[4*4*3];
- float[] r = new float[4*4*3];
- float[] s = new float[4*4*3];
+ final float[] p = new float[4*4*3];
+ final float[] q = new float[4*4*3];
+ final float[] r = new float[4*4*3];
+ final float[] s = new float[4*4*3];
int i, j, k, l;
-
+
gl.glPushAttrib(GL2.GL_ENABLE_BIT | GL2.GL_EVAL_BIT | GL2.GL_POLYGON_BIT);
gl.glEnable(GL2.GL_AUTO_NORMAL);
- gl.glEnable(GL2.GL_NORMALIZE);
+ gl.glEnable(GLLightingFunc.GL_NORMALIZE);
gl.glEnable(GL2.GL_MAP2_VERTEX_3);
gl.glEnable(GL2.GL_MAP2_TEXTURE_COORD_2);
gl.glPushMatrix();
if (!backCompatible) {
// The time has come to have the teapot no longer be inside out
- gl.glFrontFace(GL2.GL_CW);
+ gl.glFrontFace(GL.GL_CW);
gl.glScaled(0.5*scale, 0.5*scale, 0.5*scale);
} else {
// We want the teapot in it's backward compatible position and
@@ -1183,30 +1184,30 @@ public class GLUT {
gl.glPopMatrix();
gl.glPopAttrib();
}
-
- private static void evaluateTeapotMesh(GL2 gl,
- int grid,
- int type,
- int partNum,
- boolean repairSingularities)
+
+ private static void evaluateTeapotMesh(final GL2 gl,
+ final int grid,
+ final int type,
+ final int partNum,
+ final boolean repairSingularities)
{
if (repairSingularities && (partNum == 5 || partNum == 3)) {
// Instead of using evaluators that give bad results at singularities,
// evaluate by hand
- gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, type);
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, type);
for (int nv = 0; nv < grid; nv++) {
if (nv == 0) {
// Draw a small triangle-fan to fill the hole
gl.glDisable(GL2.GL_AUTO_NORMAL);
gl.glNormal3f(0, 0, partNum == 3 ? 1 : -1);
- gl.glBegin(GL2.GL_TRIANGLE_FAN);
+ gl.glBegin(GL.GL_TRIANGLE_FAN);
{
gl.glEvalCoord2f(0, 0);
// Note that we draw in clock-wise order to match the evaluator
// method
for (int nu = 0; nu <= grid; nu++)
{
- gl.glEvalCoord2f(nu / (float)grid, (1f / grid) / (float)grid);
+ gl.glEvalCoord2f(nu / (float)grid, (1f / grid) / grid);
}
}
gl.glEnd();
@@ -1219,7 +1220,7 @@ public class GLUT {
for (int nu = grid; nu >= 0; nu--) {
gl.glEvalCoord2f(nu / (float)grid, (nv + 1) / (float)grid);
gl.glEvalCoord2f(nu / (float)grid, Math.max(nv, 1f / grid)
- / (float)grid);
+ / grid);
}
}
gl.glEnd();
@@ -1233,13 +1234,13 @@ public class GLUT {
// Font implementation
//
- private static void bitmapCharacterImpl(GL2 gl, int font, char cin) {
- BitmapFontRec fontinfo = getBitmapFont(font);
- int c = cin & 0xFFFF;
+ private static void bitmapCharacterImpl(final GL2 gl, final int font, final char cin) {
+ final BitmapFontRec fontinfo = getBitmapFont(font);
+ final int c = cin & 0xFFFF;
if (c < fontinfo.first ||
c >= fontinfo.first + fontinfo.num_chars)
return;
- BitmapCharRec ch = fontinfo.ch[c - fontinfo.first];
+ final BitmapCharRec ch = fontinfo.ch[c - fontinfo.first];
if (ch != null) {
gl.glBitmap(ch.width, ch.height, ch.xorig, ch.yorig,
ch.advance, 0, ch.bitmap, 0);
@@ -1249,7 +1250,7 @@ public class GLUT {
private static final BitmapFontRec[] bitmapFonts = new BitmapFontRec[9];
private static final StrokeFontRec[] strokeFonts = new StrokeFontRec[9];
- private static BitmapFontRec getBitmapFont(int font) {
+ private static BitmapFontRec getBitmapFont(final int font) {
BitmapFontRec rec = bitmapFonts[font];
if (rec == null) {
switch (font) {
@@ -1282,7 +1283,7 @@ public class GLUT {
return rec;
}
- private static StrokeFontRec getStrokeFont(int font) {
+ private static StrokeFontRec getStrokeFont(final int font) {
StrokeFontRec rec = strokeFonts[font];
if (rec == null) {
switch (font) {
@@ -1299,44 +1300,44 @@ public class GLUT {
return rec;
}
- private static void beginBitmap(GL2 gl,
- int[] swapbytes,
- int[] lsbfirst,
- int[] rowlength,
- int[] skiprows,
- int[] skippixels,
- int[] alignment) {
- gl.glGetIntegerv(GL2.GL_UNPACK_SWAP_BYTES, swapbytes, 0);
- gl.glGetIntegerv(GL2.GL_UNPACK_LSB_FIRST, lsbfirst, 0);
- gl.glGetIntegerv(GL2.GL_UNPACK_ROW_LENGTH, rowlength, 0);
- gl.glGetIntegerv(GL2.GL_UNPACK_SKIP_ROWS, skiprows, 0);
- gl.glGetIntegerv(GL2.GL_UNPACK_SKIP_PIXELS, skippixels, 0);
- gl.glGetIntegerv(GL2.GL_UNPACK_ALIGNMENT, alignment, 0);
+ private static void beginBitmap(final GL2 gl,
+ final int[] swapbytes,
+ final int[] lsbfirst,
+ final int[] rowlength,
+ final int[] skiprows,
+ final int[] skippixels,
+ final int[] alignment) {
+ gl.glGetIntegerv(GL2GL3.GL_UNPACK_SWAP_BYTES, swapbytes, 0);
+ gl.glGetIntegerv(GL2GL3.GL_UNPACK_LSB_FIRST, lsbfirst, 0);
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_ROW_LENGTH, rowlength, 0);
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_ROWS, skiprows, 0);
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_PIXELS, skippixels, 0);
+ gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, alignment, 0);
/* Little endian machines (DEC Alpha for example) could
benefit from setting GL_UNPACK_LSB_FIRST to GL_TRUE
instead of GL_FALSE, but this would require changing the
generated bitmaps too. */
- gl.glPixelStorei(GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE);
- gl.glPixelStorei(GL2.GL_UNPACK_LSB_FIRST, GL2.GL_FALSE);
- gl.glPixelStorei(GL2.GL_UNPACK_ROW_LENGTH, 0);
- gl.glPixelStorei(GL2.GL_UNPACK_SKIP_ROWS, 0);
- gl.glPixelStorei(GL2.GL_UNPACK_SKIP_PIXELS, 0);
- gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 1);
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE);
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_LSB_FIRST, GL.GL_FALSE);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, 0);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, 0);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, 0);
+ gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
}
- private static void endBitmap(GL2 gl,
- int[] swapbytes,
- int[] lsbfirst,
- int[] rowlength,
- int[] skiprows,
- int[] skippixels,
- int[] alignment) {
+ private static void endBitmap(final GL2 gl,
+ final int[] swapbytes,
+ final int[] lsbfirst,
+ final int[] rowlength,
+ final int[] skiprows,
+ final int[] skippixels,
+ final int[] alignment) {
/* Restore saved modes. */
- gl.glPixelStorei(GL2.GL_UNPACK_SWAP_BYTES, swapbytes[0]);
- gl.glPixelStorei(GL2.GL_UNPACK_LSB_FIRST, lsbfirst[0]);
- gl.glPixelStorei(GL2.GL_UNPACK_ROW_LENGTH, rowlength[0]);
- gl.glPixelStorei(GL2.GL_UNPACK_SKIP_ROWS, skiprows[0]);
- gl.glPixelStorei(GL2.GL_UNPACK_SKIP_PIXELS, skippixels[0]);
- gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, alignment[0]);
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, swapbytes[0]);
+ gl.glPixelStorei(GL2GL3.GL_UNPACK_LSB_FIRST, lsbfirst[0]);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, rowlength[0]);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, skiprows[0]);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, skippixels[0]);
+ gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, alignment[0]);
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap8x13.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap8x13.java
index 07ded652a..c24483777 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap8x13.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap8x13.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap9x15.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap9x15.java
index 5d357f3f7..62af3b631 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap9x15.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap9x15.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica10.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica10.java
index b9c7e6e50..5f06d697e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica10.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica10.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica12.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica12.java
index bc86f6216..8326d6461 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica12.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica12.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica18.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica18.java
index 1b2e69ba4..cb11f6bec 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica18.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica18.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman10.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman10.java
index f753b56f7..17cbd0796 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman10.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman10.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman24.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman24.java
index 073e6e673..9cc2bdc3a 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman24.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman24.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeMonoRoman.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeMonoRoman.java
index b8296924e..a191efdb4 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeMonoRoman.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeMonoRoman.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -46,14 +46,14 @@ class GLUTStrokeMonoRoman {
/* char: 33 '!' */
static final CoordRec char33_stroke0[] = {
- new CoordRec((float) 52.381, (float) 100 ),
+ new CoordRec((float) 52.381, 100 ),
new CoordRec((float) 52.381, (float) 33.3333 ),
};
static final CoordRec char33_stroke1[] = {
new CoordRec((float) 52.381, (float) 9.5238 ),
new CoordRec((float) 47.6191, (float) 4.7619 ),
- new CoordRec((float) 52.381, (float) 0 ),
+ new CoordRec((float) 52.381, 0 ),
new CoordRec((float) 57.1429, (float) 4.7619 ),
new CoordRec((float) 52.381, (float) 9.5238 ),
};
@@ -66,12 +66,12 @@ static final StrokeRec char33[] = {
/* char: 34 '"' */
static final CoordRec char34_stroke0[] = {
- new CoordRec((float) 33.3334, (float) 100 ),
+ new CoordRec((float) 33.3334, 100 ),
new CoordRec((float) 33.3334, (float) 66.6667 ),
};
static final CoordRec char34_stroke1[] = {
- new CoordRec((float) 71.4286, (float) 100 ),
+ new CoordRec((float) 71.4286, 100 ),
new CoordRec((float) 71.4286, (float) 66.6667 ),
};
@@ -89,7 +89,7 @@ static final CoordRec char35_stroke0[] = {
static final CoordRec char35_stroke1[] = {
new CoordRec((float) 83.3334, (float) 119.048 ),
- new CoordRec((float) 50, (float) -33.3333 ),
+ new CoordRec(50, (float) -33.3333 ),
};
static final CoordRec char35_stroke2[] = {
@@ -124,8 +124,8 @@ static final CoordRec char36_stroke1[] = {
static final CoordRec char36_stroke2[] = {
new CoordRec((float) 85.7143, (float) 85.7143 ),
new CoordRec((float) 76.1905, (float) 95.2381 ),
- new CoordRec((float) 61.9047, (float) 100 ),
- new CoordRec((float) 42.8571, (float) 100 ),
+ new CoordRec((float) 61.9047, 100 ),
+ new CoordRec((float) 42.8571, 100 ),
new CoordRec((float) 28.5714, (float) 95.2381 ),
new CoordRec((float) 19.0476, (float) 85.7143 ),
new CoordRec((float) 19.0476, (float) 76.1905 ),
@@ -138,8 +138,8 @@ static final CoordRec char36_stroke2[] = {
new CoordRec((float) 85.7143, (float) 28.5714 ),
new CoordRec((float) 85.7143, (float) 14.2857 ),
new CoordRec((float) 76.1905, (float) 4.7619 ),
- new CoordRec((float) 61.9047, (float) 0 ),
- new CoordRec((float) 42.8571, (float) 0 ),
+ new CoordRec((float) 61.9047, 0 ),
+ new CoordRec((float) 42.8571, 0 ),
new CoordRec((float) 28.5714, (float) 4.7619 ),
new CoordRec((float) 19.0476, (float) 14.2857 ),
};
@@ -153,12 +153,12 @@ static final StrokeRec char36[] = {
/* char: 37 '%' */
static final CoordRec char37_stroke0[] = {
- new CoordRec((float) 95.2381, (float) 100 ),
- new CoordRec((float) 9.5238, (float) 0 ),
+ new CoordRec((float) 95.2381, 100 ),
+ new CoordRec((float) 9.5238, 0 ),
};
static final CoordRec char37_stroke1[] = {
- new CoordRec((float) 33.3333, (float) 100 ),
+ new CoordRec((float) 33.3333, 100 ),
new CoordRec((float) 42.8571, (float) 90.4762 ),
new CoordRec((float) 42.8571, (float) 80.9524 ),
new CoordRec((float) 38.0952, (float) 71.4286 ),
@@ -167,13 +167,13 @@ static final CoordRec char37_stroke1[] = {
new CoordRec((float) 9.5238, (float) 76.1905 ),
new CoordRec((float) 9.5238, (float) 85.7143 ),
new CoordRec((float) 14.2857, (float) 95.2381 ),
- new CoordRec((float) 23.8095, (float) 100 ),
- new CoordRec((float) 33.3333, (float) 100 ),
+ new CoordRec((float) 23.8095, 100 ),
+ new CoordRec((float) 33.3333, 100 ),
new CoordRec((float) 42.8571, (float) 95.2381 ),
new CoordRec((float) 57.1428, (float) 90.4762 ),
new CoordRec((float) 71.4286, (float) 90.4762 ),
new CoordRec((float) 85.7143, (float) 95.2381 ),
- new CoordRec((float) 95.2381, (float) 100 ),
+ new CoordRec((float) 95.2381, 100 ),
};
static final CoordRec char37_stroke2[] = {
@@ -181,8 +181,8 @@ static final CoordRec char37_stroke2[] = {
new CoordRec((float) 66.6667, (float) 28.5714 ),
new CoordRec((float) 61.9048, (float) 19.0476 ),
new CoordRec((float) 61.9048, (float) 9.5238 ),
- new CoordRec((float) 71.4286, (float) 0 ),
- new CoordRec((float) 80.9524, (float) 0 ),
+ new CoordRec((float) 71.4286, 0 ),
+ new CoordRec((float) 80.9524, 0 ),
new CoordRec((float) 90.4762, (float) 4.7619 ),
new CoordRec((float) 95.2381, (float) 14.2857 ),
new CoordRec((float) 95.2381, (float) 23.8095 ),
@@ -199,8 +199,8 @@ static final StrokeRec char37[] = {
/* char: 38 '&' */
static final CoordRec char38_stroke0[] = {
- new CoordRec((float) 100, (float) 57.1429 ),
- new CoordRec((float) 100, (float) 61.9048 ),
+ new CoordRec(100, (float) 57.1429 ),
+ new CoordRec(100, (float) 61.9048 ),
new CoordRec((float) 95.2381, (float) 66.6667 ),
new CoordRec((float) 90.4762, (float) 66.6667 ),
new CoordRec((float) 85.7143, (float) 61.9048 ),
@@ -208,8 +208,8 @@ static final CoordRec char38_stroke0[] = {
new CoordRec((float) 71.4286, (float) 28.5714 ),
new CoordRec((float) 61.9048, (float) 14.2857 ),
new CoordRec((float) 52.3809, (float) 4.7619 ),
- new CoordRec((float) 42.8571, (float) 0 ),
- new CoordRec((float) 23.8095, (float) 0 ),
+ new CoordRec((float) 42.8571, 0 ),
+ new CoordRec((float) 23.8095, 0 ),
new CoordRec((float) 14.2857, (float) 4.7619 ),
new CoordRec((float) 9.5238, (float) 9.5238 ),
new CoordRec((float) 4.7619, (float) 19.0476 ),
@@ -221,7 +221,7 @@ static final CoordRec char38_stroke0[] = {
new CoordRec((float) 57.1429, (float) 76.1905 ),
new CoordRec((float) 57.1429, (float) 85.7143 ),
new CoordRec((float) 52.3809, (float) 95.2381 ),
- new CoordRec((float) 42.8571, (float) 100 ),
+ new CoordRec((float) 42.8571, 100 ),
new CoordRec((float) 33.3333, (float) 95.2381 ),
new CoordRec((float) 28.5714, (float) 85.7143 ),
new CoordRec((float) 28.5714, (float) 76.1905 ),
@@ -229,10 +229,10 @@ static final CoordRec char38_stroke0[] = {
new CoordRec((float) 42.8571, (float) 47.619 ),
new CoordRec((float) 66.6667, (float) 14.2857 ),
new CoordRec((float) 76.1905, (float) 4.7619 ),
- new CoordRec((float) 85.7143, (float) 0 ),
- new CoordRec((float) 95.2381, (float) 0 ),
- new CoordRec((float) 100, (float) 4.7619 ),
- new CoordRec((float) 100, (float) 9.5238 ),
+ new CoordRec((float) 85.7143, 0 ),
+ new CoordRec((float) 95.2381, 0 ),
+ new CoordRec(100, (float) 4.7619 ),
+ new CoordRec(100, (float) 9.5238 ),
};
static final StrokeRec char38[] = {
@@ -242,7 +242,7 @@ static final StrokeRec char38[] = {
/* char: 39 ''' */
static final CoordRec char39_stroke0[] = {
- new CoordRec((float) 52.381, (float) 100 ),
+ new CoordRec((float) 52.381, 100 ),
new CoordRec((float) 52.381, (float) 66.6667 ),
};
@@ -255,12 +255,12 @@ static final StrokeRec char39[] = {
static final CoordRec char40_stroke0[] = {
new CoordRec((float) 69.0476, (float) 119.048 ),
new CoordRec((float) 59.5238, (float) 109.524 ),
- new CoordRec((float) 50, (float) 95.2381 ),
+ new CoordRec(50, (float) 95.2381 ),
new CoordRec((float) 40.4762, (float) 76.1905 ),
new CoordRec((float) 35.7143, (float) 52.381 ),
new CoordRec((float) 35.7143, (float) 33.3333 ),
new CoordRec((float) 40.4762, (float) 9.5238 ),
- new CoordRec((float) 50, (float) -9.5238 ),
+ new CoordRec(50, (float) -9.5238 ),
new CoordRec((float) 59.5238, (float) -23.8095 ),
new CoordRec((float) 69.0476, (float) -33.3333 ),
};
@@ -315,7 +315,7 @@ static final StrokeRec char42[] = {
static final CoordRec char43_stroke0[] = {
new CoordRec((float) 52.3809, (float) 85.7143 ),
- new CoordRec((float) 52.3809, (float) 0 ),
+ new CoordRec((float) 52.3809, 0 ),
};
static final CoordRec char43_stroke1[] = {
@@ -332,7 +332,7 @@ static final StrokeRec char43[] = {
static final CoordRec char44_stroke0[] = {
new CoordRec((float) 57.1429, (float) 4.7619 ),
- new CoordRec((float) 52.381, (float) 0 ),
+ new CoordRec((float) 52.381, 0 ),
new CoordRec((float) 47.6191, (float) 4.7619 ),
new CoordRec((float) 52.381, (float) 9.5238 ),
new CoordRec((float) 57.1429, (float) 4.7619 ),
@@ -361,7 +361,7 @@ static final StrokeRec char45[] = {
static final CoordRec char46_stroke0[] = {
new CoordRec((float) 52.381, (float) 9.5238 ),
new CoordRec((float) 47.6191, (float) 4.7619 ),
- new CoordRec((float) 52.381, (float) 0 ),
+ new CoordRec((float) 52.381, 0 ),
new CoordRec((float) 57.1429, (float) 4.7619 ),
new CoordRec((float) 52.381, (float) 9.5238 ),
};
@@ -374,7 +374,7 @@ static final StrokeRec char46[] = {
static final CoordRec char47_stroke0[] = {
new CoordRec((float) 19.0476, (float) -14.2857 ),
- new CoordRec((float) 85.7143, (float) 100 ),
+ new CoordRec((float) 85.7143, 100 ),
};
static final StrokeRec char47[] = {
@@ -384,23 +384,23 @@ static final StrokeRec char47[] = {
/* char: 48 '0' */
static final CoordRec char48_stroke0[] = {
- new CoordRec((float) 47.619, (float) 100 ),
+ new CoordRec((float) 47.619, 100 ),
new CoordRec((float) 33.3333, (float) 95.2381 ),
new CoordRec((float) 23.8095, (float) 80.9524 ),
new CoordRec((float) 19.0476, (float) 57.1429 ),
new CoordRec((float) 19.0476, (float) 42.8571 ),
new CoordRec((float) 23.8095, (float) 19.0476 ),
new CoordRec((float) 33.3333, (float) 4.7619 ),
- new CoordRec((float) 47.619, (float) 0 ),
- new CoordRec((float) 57.1428, (float) 0 ),
+ new CoordRec((float) 47.619, 0 ),
+ new CoordRec((float) 57.1428, 0 ),
new CoordRec((float) 71.4286, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 19.0476 ),
new CoordRec((float) 85.7143, (float) 42.8571 ),
new CoordRec((float) 85.7143, (float) 57.1429 ),
new CoordRec((float) 80.9524, (float) 80.9524 ),
new CoordRec((float) 71.4286, (float) 95.2381 ),
- new CoordRec((float) 57.1428, (float) 100 ),
- new CoordRec((float) 47.619, (float) 100 ),
+ new CoordRec((float) 57.1428, 100 ),
+ new CoordRec((float) 47.619, 100 ),
};
static final StrokeRec char48[] = {
@@ -411,9 +411,9 @@ static final StrokeRec char48[] = {
static final CoordRec char49_stroke0[] = {
new CoordRec((float) 40.4762, (float) 80.9524 ),
- new CoordRec((float) 50, (float) 85.7143 ),
- new CoordRec((float) 64.2857, (float) 100 ),
- new CoordRec((float) 64.2857, (float) 0 ),
+ new CoordRec(50, (float) 85.7143 ),
+ new CoordRec((float) 64.2857, 100 ),
+ new CoordRec((float) 64.2857, 0 ),
};
static final StrokeRec char49[] = {
@@ -427,16 +427,16 @@ static final CoordRec char50_stroke0[] = {
new CoordRec((float) 23.8095, (float) 80.9524 ),
new CoordRec((float) 28.5714, (float) 90.4762 ),
new CoordRec((float) 33.3333, (float) 95.2381 ),
- new CoordRec((float) 42.8571, (float) 100 ),
- new CoordRec((float) 61.9047, (float) 100 ),
+ new CoordRec((float) 42.8571, 100 ),
+ new CoordRec((float) 61.9047, 100 ),
new CoordRec((float) 71.4286, (float) 95.2381 ),
new CoordRec((float) 76.1905, (float) 90.4762 ),
new CoordRec((float) 80.9524, (float) 80.9524 ),
new CoordRec((float) 80.9524, (float) 71.4286 ),
new CoordRec((float) 76.1905, (float) 61.9048 ),
new CoordRec((float) 66.6666, (float) 47.619 ),
- new CoordRec((float) 19.0476, (float) 0 ),
- new CoordRec((float) 85.7143, (float) 0 ),
+ new CoordRec((float) 19.0476, 0 ),
+ new CoordRec((float) 85.7143, 0 ),
};
static final StrokeRec char50[] = {
@@ -446,8 +446,8 @@ static final StrokeRec char50[] = {
/* char: 51 '3' */
static final CoordRec char51_stroke0[] = {
- new CoordRec((float) 28.5714, (float) 100 ),
- new CoordRec((float) 80.9524, (float) 100 ),
+ new CoordRec((float) 28.5714, 100 ),
+ new CoordRec((float) 80.9524, 100 ),
new CoordRec((float) 52.3809, (float) 61.9048 ),
new CoordRec((float) 66.6666, (float) 61.9048 ),
new CoordRec((float) 76.1905, (float) 57.1429 ),
@@ -456,8 +456,8 @@ static final CoordRec char51_stroke0[] = {
new CoordRec((float) 85.7143, (float) 28.5714 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
new CoordRec((float) 71.4286, (float) 4.7619 ),
- new CoordRec((float) 57.1428, (float) 0 ),
- new CoordRec((float) 42.8571, (float) 0 ),
+ new CoordRec((float) 57.1428, 0 ),
+ new CoordRec((float) 42.8571, 0 ),
new CoordRec((float) 28.5714, (float) 4.7619 ),
new CoordRec((float) 23.8095, (float) 9.5238 ),
new CoordRec((float) 19.0476, (float) 19.0476 ),
@@ -470,14 +470,14 @@ static final StrokeRec char51[] = {
/* char: 52 '4' */
static final CoordRec char52_stroke0[] = {
- new CoordRec((float) 64.2857, (float) 100 ),
+ new CoordRec((float) 64.2857, 100 ),
new CoordRec((float) 16.6667, (float) 33.3333 ),
new CoordRec((float) 88.0952, (float) 33.3333 ),
};
static final CoordRec char52_stroke1[] = {
- new CoordRec((float) 64.2857, (float) 100 ),
- new CoordRec((float) 64.2857, (float) 0 ),
+ new CoordRec((float) 64.2857, 100 ),
+ new CoordRec((float) 64.2857, 0 ),
};
static final StrokeRec char52[] = {
@@ -488,8 +488,8 @@ static final StrokeRec char52[] = {
/* char: 53 '5' */
static final CoordRec char53_stroke0[] = {
- new CoordRec((float) 76.1905, (float) 100 ),
- new CoordRec((float) 28.5714, (float) 100 ),
+ new CoordRec((float) 76.1905, 100 ),
+ new CoordRec((float) 28.5714, 100 ),
new CoordRec((float) 23.8095, (float) 57.1429 ),
new CoordRec((float) 28.5714, (float) 61.9048 ),
new CoordRec((float) 42.8571, (float) 66.6667 ),
@@ -500,8 +500,8 @@ static final CoordRec char53_stroke0[] = {
new CoordRec((float) 85.7143, (float) 28.5714 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
new CoordRec((float) 71.4286, (float) 4.7619 ),
- new CoordRec((float) 57.1428, (float) 0 ),
- new CoordRec((float) 42.8571, (float) 0 ),
+ new CoordRec((float) 57.1428, 0 ),
+ new CoordRec((float) 42.8571, 0 ),
new CoordRec((float) 28.5714, (float) 4.7619 ),
new CoordRec((float) 23.8095, (float) 9.5238 ),
new CoordRec((float) 19.0476, (float) 19.0476 ),
@@ -516,16 +516,16 @@ static final StrokeRec char53[] = {
static final CoordRec char54_stroke0[] = {
new CoordRec((float) 78.5714, (float) 85.7143 ),
new CoordRec((float) 73.8096, (float) 95.2381 ),
- new CoordRec((float) 59.5238, (float) 100 ),
- new CoordRec((float) 50, (float) 100 ),
+ new CoordRec((float) 59.5238, 100 ),
+ new CoordRec(50, 100 ),
new CoordRec((float) 35.7143, (float) 95.2381 ),
new CoordRec((float) 26.1905, (float) 80.9524 ),
new CoordRec((float) 21.4286, (float) 57.1429 ),
new CoordRec((float) 21.4286, (float) 33.3333 ),
new CoordRec((float) 26.1905, (float) 14.2857 ),
new CoordRec((float) 35.7143, (float) 4.7619 ),
- new CoordRec((float) 50, (float) 0 ),
- new CoordRec((float) 54.7619, (float) 0 ),
+ new CoordRec(50, 0 ),
+ new CoordRec((float) 54.7619, 0 ),
new CoordRec((float) 69.0476, (float) 4.7619 ),
new CoordRec((float) 78.5714, (float) 14.2857 ),
new CoordRec((float) 83.3334, (float) 28.5714 ),
@@ -533,7 +533,7 @@ static final CoordRec char54_stroke0[] = {
new CoordRec((float) 78.5714, (float) 47.619 ),
new CoordRec((float) 69.0476, (float) 57.1429 ),
new CoordRec((float) 54.7619, (float) 61.9048 ),
- new CoordRec((float) 50, (float) 61.9048 ),
+ new CoordRec(50, (float) 61.9048 ),
new CoordRec((float) 35.7143, (float) 57.1429 ),
new CoordRec((float) 26.1905, (float) 47.619 ),
new CoordRec((float) 21.4286, (float) 33.3333 ),
@@ -546,13 +546,13 @@ static final StrokeRec char54[] = {
/* char: 55 '7' */
static final CoordRec char55_stroke0[] = {
- new CoordRec((float) 85.7143, (float) 100 ),
- new CoordRec((float) 38.0952, (float) 0 ),
+ new CoordRec((float) 85.7143, 100 ),
+ new CoordRec((float) 38.0952, 0 ),
};
static final CoordRec char55_stroke1[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 85.7143, (float) 100 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 85.7143, 100 ),
};
static final StrokeRec char55[] = {
@@ -563,7 +563,7 @@ static final StrokeRec char55[] = {
/* char: 56 '8' */
static final CoordRec char56_stroke0[] = {
- new CoordRec((float) 42.8571, (float) 100 ),
+ new CoordRec((float) 42.8571, 100 ),
new CoordRec((float) 28.5714, (float) 95.2381 ),
new CoordRec((float) 23.8095, (float) 85.7143 ),
new CoordRec((float) 23.8095, (float) 76.1905 ),
@@ -576,8 +576,8 @@ static final CoordRec char56_stroke0[] = {
new CoordRec((float) 85.7143, (float) 19.0476 ),
new CoordRec((float) 80.9524, (float) 9.5238 ),
new CoordRec((float) 76.1905, (float) 4.7619 ),
- new CoordRec((float) 61.9047, (float) 0 ),
- new CoordRec((float) 42.8571, (float) 0 ),
+ new CoordRec((float) 61.9047, 0 ),
+ new CoordRec((float) 42.8571, 0 ),
new CoordRec((float) 28.5714, (float) 4.7619 ),
new CoordRec((float) 23.8095, (float) 9.5238 ),
new CoordRec((float) 19.0476, (float) 19.0476 ),
@@ -590,8 +590,8 @@ static final CoordRec char56_stroke0[] = {
new CoordRec((float) 80.9524, (float) 76.1905 ),
new CoordRec((float) 80.9524, (float) 85.7143 ),
new CoordRec((float) 76.1905, (float) 95.2381 ),
- new CoordRec((float) 61.9047, (float) 100 ),
- new CoordRec((float) 42.8571, (float) 100 ),
+ new CoordRec((float) 61.9047, 100 ),
+ new CoordRec((float) 42.8571, 100 ),
};
static final StrokeRec char56[] = {
@@ -605,23 +605,23 @@ static final CoordRec char57_stroke0[] = {
new CoordRec((float) 78.5714, (float) 52.381 ),
new CoordRec((float) 69.0476, (float) 42.8571 ),
new CoordRec((float) 54.7619, (float) 38.0952 ),
- new CoordRec((float) 50, (float) 38.0952 ),
+ new CoordRec(50, (float) 38.0952 ),
new CoordRec((float) 35.7143, (float) 42.8571 ),
new CoordRec((float) 26.1905, (float) 52.381 ),
new CoordRec((float) 21.4286, (float) 66.6667 ),
new CoordRec((float) 21.4286, (float) 71.4286 ),
new CoordRec((float) 26.1905, (float) 85.7143 ),
new CoordRec((float) 35.7143, (float) 95.2381 ),
- new CoordRec((float) 50, (float) 100 ),
- new CoordRec((float) 54.7619, (float) 100 ),
+ new CoordRec(50, 100 ),
+ new CoordRec((float) 54.7619, 100 ),
new CoordRec((float) 69.0476, (float) 95.2381 ),
new CoordRec((float) 78.5714, (float) 85.7143 ),
new CoordRec((float) 83.3334, (float) 66.6667 ),
new CoordRec((float) 83.3334, (float) 42.8571 ),
new CoordRec((float) 78.5714, (float) 19.0476 ),
new CoordRec((float) 69.0476, (float) 4.7619 ),
- new CoordRec((float) 54.7619, (float) 0 ),
- new CoordRec((float) 45.2381, (float) 0 ),
+ new CoordRec((float) 54.7619, 0 ),
+ new CoordRec((float) 45.2381, 0 ),
new CoordRec((float) 30.9524, (float) 4.7619 ),
new CoordRec((float) 26.1905, (float) 14.2857 ),
};
@@ -643,7 +643,7 @@ static final CoordRec char58_stroke0[] = {
static final CoordRec char58_stroke1[] = {
new CoordRec((float) 52.381, (float) 9.5238 ),
new CoordRec((float) 47.6191, (float) 4.7619 ),
- new CoordRec((float) 52.381, (float) 0 ),
+ new CoordRec((float) 52.381, 0 ),
new CoordRec((float) 57.1429, (float) 4.7619 ),
new CoordRec((float) 52.381, (float) 9.5238 ),
};
@@ -665,7 +665,7 @@ static final CoordRec char59_stroke0[] = {
static final CoordRec char59_stroke1[] = {
new CoordRec((float) 57.1429, (float) 4.7619 ),
- new CoordRec((float) 52.381, (float) 0 ),
+ new CoordRec((float) 52.381, 0 ),
new CoordRec((float) 47.6191, (float) 4.7619 ),
new CoordRec((float) 52.381, (float) 9.5238 ),
new CoordRec((float) 57.1429, (float) 4.7619 ),
@@ -684,7 +684,7 @@ static final StrokeRec char59[] = {
static final CoordRec char60_stroke0[] = {
new CoordRec((float) 90.4762, (float) 85.7143 ),
new CoordRec((float) 14.2857, (float) 42.8571 ),
- new CoordRec((float) 90.4762, (float) 0 ),
+ new CoordRec((float) 90.4762, 0 ),
};
static final StrokeRec char60[] = {
@@ -713,7 +713,7 @@ static final StrokeRec char61[] = {
static final CoordRec char62_stroke0[] = {
new CoordRec((float) 14.2857, (float) 85.7143 ),
new CoordRec((float) 90.4762, (float) 42.8571 ),
- new CoordRec((float) 14.2857, (float) 0 ),
+ new CoordRec((float) 14.2857, 0 ),
};
static final StrokeRec char62[] = {
@@ -727,8 +727,8 @@ static final CoordRec char63_stroke0[] = {
new CoordRec((float) 23.8095, (float) 80.9524 ),
new CoordRec((float) 28.5714, (float) 90.4762 ),
new CoordRec((float) 33.3333, (float) 95.2381 ),
- new CoordRec((float) 42.8571, (float) 100 ),
- new CoordRec((float) 61.9047, (float) 100 ),
+ new CoordRec((float) 42.8571, 100 ),
+ new CoordRec((float) 61.9047, 100 ),
new CoordRec((float) 71.4285, (float) 95.2381 ),
new CoordRec((float) 76.1905, (float) 90.4762 ),
new CoordRec((float) 80.9524, (float) 80.9524 ),
@@ -742,7 +742,7 @@ static final CoordRec char63_stroke0[] = {
static final CoordRec char63_stroke1[] = {
new CoordRec((float) 52.3809, (float) 9.5238 ),
new CoordRec((float) 47.619, (float) 4.7619 ),
- new CoordRec((float) 52.3809, (float) 0 ),
+ new CoordRec((float) 52.3809, 0 ),
new CoordRec((float) 57.1428, (float) 4.7619 ),
new CoordRec((float) 52.3809, (float) 9.5238 ),
};
@@ -775,14 +775,14 @@ static final CoordRec char64_stroke1[] = {
new CoordRec((float) 78.5714, (float) 61.9048 ),
new CoordRec((float) 69.0476, (float) 71.4286 ),
new CoordRec((float) 54.7619, (float) 76.1905 ),
- new CoordRec((float) 50, (float) 76.1905 ),
+ new CoordRec(50, (float) 76.1905 ),
new CoordRec((float) 35.7143, (float) 71.4286 ),
new CoordRec((float) 26.1905, (float) 61.9048 ),
new CoordRec((float) 21.4286, (float) 47.619 ),
new CoordRec((float) 21.4286, (float) 42.8571 ),
new CoordRec((float) 26.1905, (float) 28.5714 ),
new CoordRec((float) 35.7143, (float) 19.0476 ),
- new CoordRec((float) 50, (float) 14.2857 ),
+ new CoordRec(50, (float) 14.2857 ),
new CoordRec((float) 54.7619, (float) 14.2857 ),
new CoordRec((float) 69.0476, (float) 19.0476 ),
};
@@ -795,13 +795,13 @@ static final StrokeRec char64[] = {
/* char: 65 'A' */
static final CoordRec char65_stroke0[] = {
- new CoordRec((float) 52.3809, (float) 100 ),
- new CoordRec((float) 14.2857, (float) 0 ),
+ new CoordRec((float) 52.3809, 100 ),
+ new CoordRec((float) 14.2857, 0 ),
};
static final CoordRec char65_stroke1[] = {
- new CoordRec((float) 52.3809, (float) 100 ),
- new CoordRec((float) 90.4762, (float) 0 ),
+ new CoordRec((float) 52.3809, 100 ),
+ new CoordRec((float) 90.4762, 0 ),
};
static final CoordRec char65_stroke2[] = {
@@ -818,13 +818,13 @@ static final StrokeRec char65[] = {
/* char: 66 'B' */
static final CoordRec char66_stroke0[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final CoordRec char66_stroke1[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 61.9047, (float) 100 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 61.9047, 100 ),
new CoordRec((float) 76.1905, (float) 95.2381 ),
new CoordRec((float) 80.9524, (float) 90.4762 ),
new CoordRec((float) 85.7143, (float) 80.9524 ),
@@ -843,8 +843,8 @@ static final CoordRec char66_stroke2[] = {
new CoordRec((float) 85.7143, (float) 19.0476 ),
new CoordRec((float) 80.9524, (float) 9.5238 ),
new CoordRec((float) 76.1905, (float) 4.7619 ),
- new CoordRec((float) 61.9047, (float) 0 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 61.9047, 0 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final StrokeRec char66[] = {
@@ -859,8 +859,8 @@ static final CoordRec char67_stroke0[] = {
new CoordRec((float) 88.0952, (float) 76.1905 ),
new CoordRec((float) 83.3334, (float) 85.7143 ),
new CoordRec((float) 73.8096, (float) 95.2381 ),
- new CoordRec((float) 64.2857, (float) 100 ),
- new CoordRec((float) 45.2381, (float) 100 ),
+ new CoordRec((float) 64.2857, 100 ),
+ new CoordRec((float) 45.2381, 100 ),
new CoordRec((float) 35.7143, (float) 95.2381 ),
new CoordRec((float) 26.1905, (float) 85.7143 ),
new CoordRec((float) 21.4286, (float) 76.1905 ),
@@ -869,8 +869,8 @@ static final CoordRec char67_stroke0[] = {
new CoordRec((float) 21.4286, (float) 23.8095 ),
new CoordRec((float) 26.1905, (float) 14.2857 ),
new CoordRec((float) 35.7143, (float) 4.7619 ),
- new CoordRec((float) 45.2381, (float) 0 ),
- new CoordRec((float) 64.2857, (float) 0 ),
+ new CoordRec((float) 45.2381, 0 ),
+ new CoordRec((float) 64.2857, 0 ),
new CoordRec((float) 73.8096, (float) 4.7619 ),
new CoordRec((float) 83.3334, (float) 14.2857 ),
new CoordRec((float) 88.0952, (float) 23.8095 ),
@@ -883,13 +883,13 @@ static final StrokeRec char67[] = {
/* char: 68 'D' */
static final CoordRec char68_stroke0[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final CoordRec char68_stroke1[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 52.3809, (float) 100 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 52.3809, 100 ),
new CoordRec((float) 66.6666, (float) 95.2381 ),
new CoordRec((float) 76.1905, (float) 85.7143 ),
new CoordRec((float) 80.9524, (float) 76.1905 ),
@@ -898,8 +898,8 @@ static final CoordRec char68_stroke1[] = {
new CoordRec((float) 80.9524, (float) 23.8095 ),
new CoordRec((float) 76.1905, (float) 14.2857 ),
new CoordRec((float) 66.6666, (float) 4.7619 ),
- new CoordRec((float) 52.3809, (float) 0 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 52.3809, 0 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final StrokeRec char68[] = {
@@ -910,13 +910,13 @@ static final StrokeRec char68[] = {
/* char: 69 'E' */
static final CoordRec char69_stroke0[] = {
- new CoordRec((float) 21.4286, (float) 100 ),
- new CoordRec((float) 21.4286, (float) 0 ),
+ new CoordRec((float) 21.4286, 100 ),
+ new CoordRec((float) 21.4286, 0 ),
};
static final CoordRec char69_stroke1[] = {
- new CoordRec((float) 21.4286, (float) 100 ),
- new CoordRec((float) 83.3334, (float) 100 ),
+ new CoordRec((float) 21.4286, 100 ),
+ new CoordRec((float) 83.3334, 100 ),
};
static final CoordRec char69_stroke2[] = {
@@ -925,8 +925,8 @@ static final CoordRec char69_stroke2[] = {
};
static final CoordRec char69_stroke3[] = {
- new CoordRec((float) 21.4286, (float) 0 ),
- new CoordRec((float) 83.3334, (float) 0 ),
+ new CoordRec((float) 21.4286, 0 ),
+ new CoordRec((float) 83.3334, 0 ),
};
static final StrokeRec char69[] = {
@@ -939,13 +939,13 @@ static final StrokeRec char69[] = {
/* char: 70 'F' */
static final CoordRec char70_stroke0[] = {
- new CoordRec((float) 21.4286, (float) 100 ),
- new CoordRec((float) 21.4286, (float) 0 ),
+ new CoordRec((float) 21.4286, 100 ),
+ new CoordRec((float) 21.4286, 0 ),
};
static final CoordRec char70_stroke1[] = {
- new CoordRec((float) 21.4286, (float) 100 ),
- new CoordRec((float) 83.3334, (float) 100 ),
+ new CoordRec((float) 21.4286, 100 ),
+ new CoordRec((float) 83.3334, 100 ),
};
static final CoordRec char70_stroke2[] = {
@@ -965,8 +965,8 @@ static final CoordRec char71_stroke0[] = {
new CoordRec((float) 88.0952, (float) 76.1905 ),
new CoordRec((float) 83.3334, (float) 85.7143 ),
new CoordRec((float) 73.8096, (float) 95.2381 ),
- new CoordRec((float) 64.2857, (float) 100 ),
- new CoordRec((float) 45.2381, (float) 100 ),
+ new CoordRec((float) 64.2857, 100 ),
+ new CoordRec((float) 45.2381, 100 ),
new CoordRec((float) 35.7143, (float) 95.2381 ),
new CoordRec((float) 26.1905, (float) 85.7143 ),
new CoordRec((float) 21.4286, (float) 76.1905 ),
@@ -975,8 +975,8 @@ static final CoordRec char71_stroke0[] = {
new CoordRec((float) 21.4286, (float) 23.8095 ),
new CoordRec((float) 26.1905, (float) 14.2857 ),
new CoordRec((float) 35.7143, (float) 4.7619 ),
- new CoordRec((float) 45.2381, (float) 0 ),
- new CoordRec((float) 64.2857, (float) 0 ),
+ new CoordRec((float) 45.2381, 0 ),
+ new CoordRec((float) 64.2857, 0 ),
new CoordRec((float) 73.8096, (float) 4.7619 ),
new CoordRec((float) 83.3334, (float) 14.2857 ),
new CoordRec((float) 88.0952, (float) 23.8095 ),
@@ -996,13 +996,13 @@ static final StrokeRec char71[] = {
/* char: 72 'H' */
static final CoordRec char72_stroke0[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final CoordRec char72_stroke1[] = {
- new CoordRec((float) 85.7143, (float) 100 ),
- new CoordRec((float) 85.7143, (float) 0 ),
+ new CoordRec((float) 85.7143, 100 ),
+ new CoordRec((float) 85.7143, 0 ),
};
static final CoordRec char72_stroke2[] = {
@@ -1019,8 +1019,8 @@ static final StrokeRec char72[] = {
/* char: 73 'I' */
static final CoordRec char73_stroke0[] = {
- new CoordRec((float) 52.381, (float) 100 ),
- new CoordRec((float) 52.381, (float) 0 ),
+ new CoordRec((float) 52.381, 100 ),
+ new CoordRec((float) 52.381, 0 ),
};
static final StrokeRec char73[] = {
@@ -1030,12 +1030,12 @@ static final StrokeRec char73[] = {
/* char: 74 'J' */
static final CoordRec char74_stroke0[] = {
- new CoordRec((float) 76.1905, (float) 100 ),
+ new CoordRec((float) 76.1905, 100 ),
new CoordRec((float) 76.1905, (float) 23.8095 ),
new CoordRec((float) 71.4286, (float) 9.5238 ),
new CoordRec((float) 66.6667, (float) 4.7619 ),
- new CoordRec((float) 57.1429, (float) 0 ),
- new CoordRec((float) 47.6191, (float) 0 ),
+ new CoordRec((float) 57.1429, 0 ),
+ new CoordRec((float) 47.6191, 0 ),
new CoordRec((float) 38.0953, (float) 4.7619 ),
new CoordRec((float) 33.3334, (float) 9.5238 ),
new CoordRec((float) 28.5715, (float) 23.8095 ),
@@ -1049,18 +1049,18 @@ static final StrokeRec char74[] = {
/* char: 75 'K' */
static final CoordRec char75_stroke0[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final CoordRec char75_stroke1[] = {
- new CoordRec((float) 85.7143, (float) 100 ),
+ new CoordRec((float) 85.7143, 100 ),
new CoordRec((float) 19.0476, (float) 33.3333 ),
};
static final CoordRec char75_stroke2[] = {
new CoordRec((float) 42.8571, (float) 57.1429 ),
- new CoordRec((float) 85.7143, (float) 0 ),
+ new CoordRec((float) 85.7143, 0 ),
};
static final StrokeRec char75[] = {
@@ -1072,13 +1072,13 @@ static final StrokeRec char75[] = {
/* char: 76 'L' */
static final CoordRec char76_stroke0[] = {
- new CoordRec((float) 23.8095, (float) 100 ),
- new CoordRec((float) 23.8095, (float) 0 ),
+ new CoordRec((float) 23.8095, 100 ),
+ new CoordRec((float) 23.8095, 0 ),
};
static final CoordRec char76_stroke1[] = {
- new CoordRec((float) 23.8095, (float) 0 ),
- new CoordRec((float) 80.9524, (float) 0 ),
+ new CoordRec((float) 23.8095, 0 ),
+ new CoordRec((float) 80.9524, 0 ),
};
static final StrokeRec char76[] = {
@@ -1089,23 +1089,23 @@ static final StrokeRec char76[] = {
/* char: 77 'M' */
static final CoordRec char77_stroke0[] = {
- new CoordRec((float) 14.2857, (float) 100 ),
- new CoordRec((float) 14.2857, (float) 0 ),
+ new CoordRec((float) 14.2857, 100 ),
+ new CoordRec((float) 14.2857, 0 ),
};
static final CoordRec char77_stroke1[] = {
- new CoordRec((float) 14.2857, (float) 100 ),
- new CoordRec((float) 52.3809, (float) 0 ),
+ new CoordRec((float) 14.2857, 100 ),
+ new CoordRec((float) 52.3809, 0 ),
};
static final CoordRec char77_stroke2[] = {
- new CoordRec((float) 90.4762, (float) 100 ),
- new CoordRec((float) 52.3809, (float) 0 ),
+ new CoordRec((float) 90.4762, 100 ),
+ new CoordRec((float) 52.3809, 0 ),
};
static final CoordRec char77_stroke3[] = {
- new CoordRec((float) 90.4762, (float) 100 ),
- new CoordRec((float) 90.4762, (float) 0 ),
+ new CoordRec((float) 90.4762, 100 ),
+ new CoordRec((float) 90.4762, 0 ),
};
static final StrokeRec char77[] = {
@@ -1118,18 +1118,18 @@ static final StrokeRec char77[] = {
/* char: 78 'N' */
static final CoordRec char78_stroke0[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final CoordRec char78_stroke1[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 85.7143, (float) 0 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 85.7143, 0 ),
};
static final CoordRec char78_stroke2[] = {
- new CoordRec((float) 85.7143, (float) 100 ),
- new CoordRec((float) 85.7143, (float) 0 ),
+ new CoordRec((float) 85.7143, 100 ),
+ new CoordRec((float) 85.7143, 0 ),
};
static final StrokeRec char78[] = {
@@ -1141,7 +1141,7 @@ static final StrokeRec char78[] = {
/* char: 79 'O' */
static final CoordRec char79_stroke0[] = {
- new CoordRec((float) 42.8571, (float) 100 ),
+ new CoordRec((float) 42.8571, 100 ),
new CoordRec((float) 33.3333, (float) 95.2381 ),
new CoordRec((float) 23.8095, (float) 85.7143 ),
new CoordRec((float) 19.0476, (float) 76.1905 ),
@@ -1150,8 +1150,8 @@ static final CoordRec char79_stroke0[] = {
new CoordRec((float) 19.0476, (float) 23.8095 ),
new CoordRec((float) 23.8095, (float) 14.2857 ),
new CoordRec((float) 33.3333, (float) 4.7619 ),
- new CoordRec((float) 42.8571, (float) 0 ),
- new CoordRec((float) 61.9047, (float) 0 ),
+ new CoordRec((float) 42.8571, 0 ),
+ new CoordRec((float) 61.9047, 0 ),
new CoordRec((float) 71.4286, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
new CoordRec((float) 85.7143, (float) 23.8095 ),
@@ -1160,8 +1160,8 @@ static final CoordRec char79_stroke0[] = {
new CoordRec((float) 85.7143, (float) 76.1905 ),
new CoordRec((float) 80.9524, (float) 85.7143 ),
new CoordRec((float) 71.4286, (float) 95.2381 ),
- new CoordRec((float) 61.9047, (float) 100 ),
- new CoordRec((float) 42.8571, (float) 100 ),
+ new CoordRec((float) 61.9047, 100 ),
+ new CoordRec((float) 42.8571, 100 ),
};
static final StrokeRec char79[] = {
@@ -1171,13 +1171,13 @@ static final StrokeRec char79[] = {
/* char: 80 'P' */
static final CoordRec char80_stroke0[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final CoordRec char80_stroke1[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 61.9047, (float) 100 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 61.9047, 100 ),
new CoordRec((float) 76.1905, (float) 95.2381 ),
new CoordRec((float) 80.9524, (float) 90.4762 ),
new CoordRec((float) 85.7143, (float) 80.9524 ),
@@ -1196,7 +1196,7 @@ static final StrokeRec char80[] = {
/* char: 81 'Q' */
static final CoordRec char81_stroke0[] = {
- new CoordRec((float) 42.8571, (float) 100 ),
+ new CoordRec((float) 42.8571, 100 ),
new CoordRec((float) 33.3333, (float) 95.2381 ),
new CoordRec((float) 23.8095, (float) 85.7143 ),
new CoordRec((float) 19.0476, (float) 76.1905 ),
@@ -1205,8 +1205,8 @@ static final CoordRec char81_stroke0[] = {
new CoordRec((float) 19.0476, (float) 23.8095 ),
new CoordRec((float) 23.8095, (float) 14.2857 ),
new CoordRec((float) 33.3333, (float) 4.7619 ),
- new CoordRec((float) 42.8571, (float) 0 ),
- new CoordRec((float) 61.9047, (float) 0 ),
+ new CoordRec((float) 42.8571, 0 ),
+ new CoordRec((float) 61.9047, 0 ),
new CoordRec((float) 71.4286, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
new CoordRec((float) 85.7143, (float) 23.8095 ),
@@ -1215,8 +1215,8 @@ static final CoordRec char81_stroke0[] = {
new CoordRec((float) 85.7143, (float) 76.1905 ),
new CoordRec((float) 80.9524, (float) 85.7143 ),
new CoordRec((float) 71.4286, (float) 95.2381 ),
- new CoordRec((float) 61.9047, (float) 100 ),
- new CoordRec((float) 42.8571, (float) 100 ),
+ new CoordRec((float) 61.9047, 100 ),
+ new CoordRec((float) 42.8571, 100 ),
};
static final CoordRec char81_stroke1[] = {
@@ -1232,13 +1232,13 @@ static final StrokeRec char81[] = {
/* char: 82 'R' */
static final CoordRec char82_stroke0[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final CoordRec char82_stroke1[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 61.9047, (float) 100 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 61.9047, 100 ),
new CoordRec((float) 76.1905, (float) 95.2381 ),
new CoordRec((float) 80.9524, (float) 90.4762 ),
new CoordRec((float) 85.7143, (float) 80.9524 ),
@@ -1251,7 +1251,7 @@ static final CoordRec char82_stroke1[] = {
static final CoordRec char82_stroke2[] = {
new CoordRec((float) 52.3809, (float) 52.381 ),
- new CoordRec((float) 85.7143, (float) 0 ),
+ new CoordRec((float) 85.7143, 0 ),
};
static final StrokeRec char82[] = {
@@ -1265,8 +1265,8 @@ static final StrokeRec char82[] = {
static final CoordRec char83_stroke0[] = {
new CoordRec((float) 85.7143, (float) 85.7143 ),
new CoordRec((float) 76.1905, (float) 95.2381 ),
- new CoordRec((float) 61.9047, (float) 100 ),
- new CoordRec((float) 42.8571, (float) 100 ),
+ new CoordRec((float) 61.9047, 100 ),
+ new CoordRec((float) 42.8571, 100 ),
new CoordRec((float) 28.5714, (float) 95.2381 ),
new CoordRec((float) 19.0476, (float) 85.7143 ),
new CoordRec((float) 19.0476, (float) 76.1905 ),
@@ -1279,8 +1279,8 @@ static final CoordRec char83_stroke0[] = {
new CoordRec((float) 85.7143, (float) 28.5714 ),
new CoordRec((float) 85.7143, (float) 14.2857 ),
new CoordRec((float) 76.1905, (float) 4.7619 ),
- new CoordRec((float) 61.9047, (float) 0 ),
- new CoordRec((float) 42.8571, (float) 0 ),
+ new CoordRec((float) 61.9047, 0 ),
+ new CoordRec((float) 42.8571, 0 ),
new CoordRec((float) 28.5714, (float) 4.7619 ),
new CoordRec((float) 19.0476, (float) 14.2857 ),
};
@@ -1292,13 +1292,13 @@ static final StrokeRec char83[] = {
/* char: 84 'T' */
static final CoordRec char84_stroke0[] = {
- new CoordRec((float) 52.3809, (float) 100 ),
- new CoordRec((float) 52.3809, (float) 0 ),
+ new CoordRec((float) 52.3809, 100 ),
+ new CoordRec((float) 52.3809, 0 ),
};
static final CoordRec char84_stroke1[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 85.7143, (float) 100 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 85.7143, 100 ),
};
static final StrokeRec char84[] = {
@@ -1309,16 +1309,16 @@ static final StrokeRec char84[] = {
/* char: 85 'U' */
static final CoordRec char85_stroke0[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
+ new CoordRec((float) 19.0476, 100 ),
new CoordRec((float) 19.0476, (float) 28.5714 ),
new CoordRec((float) 23.8095, (float) 14.2857 ),
new CoordRec((float) 33.3333, (float) 4.7619 ),
- new CoordRec((float) 47.619, (float) 0 ),
- new CoordRec((float) 57.1428, (float) 0 ),
+ new CoordRec((float) 47.619, 0 ),
+ new CoordRec((float) 57.1428, 0 ),
new CoordRec((float) 71.4286, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
new CoordRec((float) 85.7143, (float) 28.5714 ),
- new CoordRec((float) 85.7143, (float) 100 ),
+ new CoordRec((float) 85.7143, 100 ),
};
static final StrokeRec char85[] = {
@@ -1328,13 +1328,13 @@ static final StrokeRec char85[] = {
/* char: 86 'V' */
static final CoordRec char86_stroke0[] = {
- new CoordRec((float) 14.2857, (float) 100 ),
- new CoordRec((float) 52.3809, (float) 0 ),
+ new CoordRec((float) 14.2857, 100 ),
+ new CoordRec((float) 52.3809, 0 ),
};
static final CoordRec char86_stroke1[] = {
- new CoordRec((float) 90.4762, (float) 100 ),
- new CoordRec((float) 52.3809, (float) 0 ),
+ new CoordRec((float) 90.4762, 100 ),
+ new CoordRec((float) 52.3809, 0 ),
};
static final StrokeRec char86[] = {
@@ -1345,23 +1345,23 @@ static final StrokeRec char86[] = {
/* char: 87 'W' */
static final CoordRec char87_stroke0[] = {
- new CoordRec((float) 4.7619, (float) 100 ),
- new CoordRec((float) 28.5714, (float) 0 ),
+ new CoordRec((float) 4.7619, 100 ),
+ new CoordRec((float) 28.5714, 0 ),
};
static final CoordRec char87_stroke1[] = {
- new CoordRec((float) 52.3809, (float) 100 ),
- new CoordRec((float) 28.5714, (float) 0 ),
+ new CoordRec((float) 52.3809, 100 ),
+ new CoordRec((float) 28.5714, 0 ),
};
static final CoordRec char87_stroke2[] = {
- new CoordRec((float) 52.3809, (float) 100 ),
- new CoordRec((float) 76.1905, (float) 0 ),
+ new CoordRec((float) 52.3809, 100 ),
+ new CoordRec((float) 76.1905, 0 ),
};
static final CoordRec char87_stroke3[] = {
- new CoordRec((float) 100, (float) 100 ),
- new CoordRec((float) 76.1905, (float) 0 ),
+ new CoordRec(100, 100 ),
+ new CoordRec((float) 76.1905, 0 ),
};
static final StrokeRec char87[] = {
@@ -1374,13 +1374,13 @@ static final StrokeRec char87[] = {
/* char: 88 'X' */
static final CoordRec char88_stroke0[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 85.7143, (float) 0 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 85.7143, 0 ),
};
static final CoordRec char88_stroke1[] = {
- new CoordRec((float) 85.7143, (float) 100 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 85.7143, 100 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final StrokeRec char88[] = {
@@ -1391,13 +1391,13 @@ static final StrokeRec char88[] = {
/* char: 89 'Y' */
static final CoordRec char89_stroke0[] = {
- new CoordRec((float) 14.2857, (float) 100 ),
+ new CoordRec((float) 14.2857, 100 ),
new CoordRec((float) 52.3809, (float) 52.381 ),
- new CoordRec((float) 52.3809, (float) 0 ),
+ new CoordRec((float) 52.3809, 0 ),
};
static final CoordRec char89_stroke1[] = {
- new CoordRec((float) 90.4762, (float) 100 ),
+ new CoordRec((float) 90.4762, 100 ),
new CoordRec((float) 52.3809, (float) 52.381 ),
};
@@ -1409,18 +1409,18 @@ static final StrokeRec char89[] = {
/* char: 90 'Z' */
static final CoordRec char90_stroke0[] = {
- new CoordRec((float) 85.7143, (float) 100 ),
- new CoordRec((float) 19.0476, (float) 0 ),
+ new CoordRec((float) 85.7143, 100 ),
+ new CoordRec((float) 19.0476, 0 ),
};
static final CoordRec char90_stroke1[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
- new CoordRec((float) 85.7143, (float) 100 ),
+ new CoordRec((float) 19.0476, 100 ),
+ new CoordRec((float) 85.7143, 100 ),
};
static final CoordRec char90_stroke2[] = {
- new CoordRec((float) 19.0476, (float) 0 ),
- new CoordRec((float) 85.7143, (float) 0 ),
+ new CoordRec((float) 19.0476, 0 ),
+ new CoordRec((float) 85.7143, 0 ),
};
static final StrokeRec char90[] = {
@@ -1461,7 +1461,7 @@ static final StrokeRec char91[] = {
/* char: 92 '\' */
static final CoordRec char92_stroke0[] = {
- new CoordRec((float) 19.0476, (float) 100 ),
+ new CoordRec((float) 19.0476, 100 ),
new CoordRec((float) 85.7143, (float) -14.2857 ),
};
@@ -1518,11 +1518,11 @@ static final StrokeRec char94[] = {
/* char: 95 '_' */
static final CoordRec char95_stroke0[] = {
- new CoordRec((float) 0, (float) -33.3333 ),
+ new CoordRec(0, (float) -33.3333 ),
new CoordRec((float) 104.762, (float) -33.3333 ),
new CoordRec((float) 104.762, (float) -28.5714 ),
- new CoordRec((float) 0, (float) -28.5714 ),
- new CoordRec((float) 0, (float) -33.3333 ),
+ new CoordRec(0, (float) -28.5714 ),
+ new CoordRec(0, (float) -33.3333 ),
};
static final StrokeRec char95[] = {
@@ -1532,12 +1532,12 @@ static final StrokeRec char95[] = {
/* char: 96 '`' */
static final CoordRec char96_stroke0[] = {
- new CoordRec((float) 42.8572, (float) 100 ),
+ new CoordRec((float) 42.8572, 100 ),
new CoordRec((float) 66.6667, (float) 71.4286 ),
};
static final CoordRec char96_stroke1[] = {
- new CoordRec((float) 42.8572, (float) 100 ),
+ new CoordRec((float) 42.8572, 100 ),
new CoordRec((float) 38.0953, (float) 95.2381 ),
new CoordRec((float) 66.6667, (float) 71.4286 ),
};
@@ -1551,7 +1551,7 @@ static final StrokeRec char96[] = {
static final CoordRec char97_stroke0[] = {
new CoordRec((float) 80.9524, (float) 66.6667 ),
- new CoordRec((float) 80.9524, (float) 0 ),
+ new CoordRec((float) 80.9524, 0 ),
};
static final CoordRec char97_stroke1[] = {
@@ -1565,8 +1565,8 @@ static final CoordRec char97_stroke1[] = {
new CoordRec((float) 23.8095, (float) 28.5714 ),
new CoordRec((float) 28.5714, (float) 14.2857 ),
new CoordRec((float) 38.0952, (float) 4.7619 ),
- new CoordRec((float) 47.619, (float) 0 ),
- new CoordRec((float) 61.9047, (float) 0 ),
+ new CoordRec((float) 47.619, 0 ),
+ new CoordRec((float) 61.9047, 0 ),
new CoordRec((float) 71.4285, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
};
@@ -1579,8 +1579,8 @@ static final StrokeRec char97[] = {
/* char: 98 'b' */
static final CoordRec char98_stroke0[] = {
- new CoordRec((float) 23.8095, (float) 100 ),
- new CoordRec((float) 23.8095, (float) 0 ),
+ new CoordRec((float) 23.8095, 100 ),
+ new CoordRec((float) 23.8095, 0 ),
};
static final CoordRec char98_stroke1[] = {
@@ -1594,8 +1594,8 @@ static final CoordRec char98_stroke1[] = {
new CoordRec((float) 80.9524, (float) 28.5714 ),
new CoordRec((float) 76.1905, (float) 14.2857 ),
new CoordRec((float) 66.6666, (float) 4.7619 ),
- new CoordRec((float) 57.1428, (float) 0 ),
- new CoordRec((float) 42.8571, (float) 0 ),
+ new CoordRec((float) 57.1428, 0 ),
+ new CoordRec((float) 42.8571, 0 ),
new CoordRec((float) 33.3333, (float) 4.7619 ),
new CoordRec((float) 23.8095, (float) 14.2857 ),
};
@@ -1618,8 +1618,8 @@ static final CoordRec char99_stroke0[] = {
new CoordRec((float) 23.8095, (float) 28.5714 ),
new CoordRec((float) 28.5714, (float) 14.2857 ),
new CoordRec((float) 38.0952, (float) 4.7619 ),
- new CoordRec((float) 47.619, (float) 0 ),
- new CoordRec((float) 61.9047, (float) 0 ),
+ new CoordRec((float) 47.619, 0 ),
+ new CoordRec((float) 61.9047, 0 ),
new CoordRec((float) 71.4285, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
};
@@ -1631,8 +1631,8 @@ static final StrokeRec char99[] = {
/* char: 100 'd' */
static final CoordRec char100_stroke0[] = {
- new CoordRec((float) 80.9524, (float) 100 ),
- new CoordRec((float) 80.9524, (float) 0 ),
+ new CoordRec((float) 80.9524, 100 ),
+ new CoordRec((float) 80.9524, 0 ),
};
static final CoordRec char100_stroke1[] = {
@@ -1646,8 +1646,8 @@ static final CoordRec char100_stroke1[] = {
new CoordRec((float) 23.8095, (float) 28.5714 ),
new CoordRec((float) 28.5714, (float) 14.2857 ),
new CoordRec((float) 38.0952, (float) 4.7619 ),
- new CoordRec((float) 47.619, (float) 0 ),
- new CoordRec((float) 61.9047, (float) 0 ),
+ new CoordRec((float) 47.619, 0 ),
+ new CoordRec((float) 61.9047, 0 ),
new CoordRec((float) 71.4285, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
};
@@ -1673,8 +1673,8 @@ static final CoordRec char101_stroke0[] = {
new CoordRec((float) 23.8095, (float) 28.5714 ),
new CoordRec((float) 28.5714, (float) 14.2857 ),
new CoordRec((float) 38.0952, (float) 4.7619 ),
- new CoordRec((float) 47.619, (float) 0 ),
- new CoordRec((float) 61.9047, (float) 0 ),
+ new CoordRec((float) 47.619, 0 ),
+ new CoordRec((float) 61.9047, 0 ),
new CoordRec((float) 71.4285, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
};
@@ -1686,11 +1686,11 @@ static final StrokeRec char101[] = {
/* char: 102 'f' */
static final CoordRec char102_stroke0[] = {
- new CoordRec((float) 71.4286, (float) 100 ),
- new CoordRec((float) 61.9048, (float) 100 ),
+ new CoordRec((float) 71.4286, 100 ),
+ new CoordRec((float) 61.9048, 100 ),
new CoordRec((float) 52.381, (float) 95.2381 ),
new CoordRec((float) 47.6191, (float) 80.9524 ),
- new CoordRec((float) 47.6191, (float) 0 ),
+ new CoordRec((float) 47.6191, 0 ),
};
static final CoordRec char102_stroke1[] = {
@@ -1726,8 +1726,8 @@ static final CoordRec char103_stroke1[] = {
new CoordRec((float) 23.8095, (float) 28.5714 ),
new CoordRec((float) 28.5714, (float) 14.2857 ),
new CoordRec((float) 38.0952, (float) 4.7619 ),
- new CoordRec((float) 47.619, (float) 0 ),
- new CoordRec((float) 61.9047, (float) 0 ),
+ new CoordRec((float) 47.619, 0 ),
+ new CoordRec((float) 61.9047, 0 ),
new CoordRec((float) 71.4285, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
};
@@ -1740,18 +1740,18 @@ static final StrokeRec char103[] = {
/* char: 104 'h' */
static final CoordRec char104_stroke0[] = {
- new CoordRec((float) 26.1905, (float) 100 ),
- new CoordRec((float) 26.1905, (float) 0 ),
+ new CoordRec((float) 26.1905, 100 ),
+ new CoordRec((float) 26.1905, 0 ),
};
static final CoordRec char104_stroke1[] = {
new CoordRec((float) 26.1905, (float) 47.619 ),
new CoordRec((float) 40.4762, (float) 61.9048 ),
- new CoordRec((float) 50, (float) 66.6667 ),
+ new CoordRec(50, (float) 66.6667 ),
new CoordRec((float) 64.2857, (float) 66.6667 ),
new CoordRec((float) 73.8095, (float) 61.9048 ),
new CoordRec((float) 78.5715, (float) 47.619 ),
- new CoordRec((float) 78.5715, (float) 0 ),
+ new CoordRec((float) 78.5715, 0 ),
};
static final StrokeRec char104[] = {
@@ -1762,16 +1762,16 @@ static final StrokeRec char104[] = {
/* char: 105 'i' */
static final CoordRec char105_stroke0[] = {
- new CoordRec((float) 47.6191, (float) 100 ),
+ new CoordRec((float) 47.6191, 100 ),
new CoordRec((float) 52.381, (float) 95.2381 ),
- new CoordRec((float) 57.1429, (float) 100 ),
+ new CoordRec((float) 57.1429, 100 ),
new CoordRec((float) 52.381, (float) 104.762 ),
- new CoordRec((float) 47.6191, (float) 100 ),
+ new CoordRec((float) 47.6191, 100 ),
};
static final CoordRec char105_stroke1[] = {
new CoordRec((float) 52.381, (float) 66.6667 ),
- new CoordRec((float) 52.381, (float) 0 ),
+ new CoordRec((float) 52.381, 0 ),
};
static final StrokeRec char105[] = {
@@ -1782,11 +1782,11 @@ static final StrokeRec char105[] = {
/* char: 106 'j' */
static final CoordRec char106_stroke0[] = {
- new CoordRec((float) 57.1429, (float) 100 ),
+ new CoordRec((float) 57.1429, 100 ),
new CoordRec((float) 61.9048, (float) 95.2381 ),
- new CoordRec((float) 66.6667, (float) 100 ),
+ new CoordRec((float) 66.6667, 100 ),
new CoordRec((float) 61.9048, (float) 104.762 ),
- new CoordRec((float) 57.1429, (float) 100 ),
+ new CoordRec((float) 57.1429, 100 ),
};
static final CoordRec char106_stroke1[] = {
@@ -1805,8 +1805,8 @@ static final StrokeRec char106[] = {
/* char: 107 'k' */
static final CoordRec char107_stroke0[] = {
- new CoordRec((float) 26.1905, (float) 100 ),
- new CoordRec((float) 26.1905, (float) 0 ),
+ new CoordRec((float) 26.1905, 100 ),
+ new CoordRec((float) 26.1905, 0 ),
};
static final CoordRec char107_stroke1[] = {
@@ -1816,7 +1816,7 @@ static final CoordRec char107_stroke1[] = {
static final CoordRec char107_stroke2[] = {
new CoordRec((float) 45.2381, (float) 38.0952 ),
- new CoordRec((float) 78.5715, (float) 0 ),
+ new CoordRec((float) 78.5715, 0 ),
};
static final StrokeRec char107[] = {
@@ -1828,8 +1828,8 @@ static final StrokeRec char107[] = {
/* char: 108 'l' */
static final CoordRec char108_stroke0[] = {
- new CoordRec((float) 52.381, (float) 100 ),
- new CoordRec((float) 52.381, (float) 0 ),
+ new CoordRec((float) 52.381, 100 ),
+ new CoordRec((float) 52.381, 0 ),
};
static final StrokeRec char108[] = {
@@ -1839,18 +1839,18 @@ static final StrokeRec char108[] = {
/* char: 109 'm' */
static final CoordRec char109_stroke0[] = {
- new CoordRec((float) 0, (float) 66.6667 ),
- new CoordRec((float) 0, (float) 0 ),
+ new CoordRec(0, (float) 66.6667 ),
+ new CoordRec(0, 0 ),
};
static final CoordRec char109_stroke1[] = {
- new CoordRec((float) 0, (float) 47.619 ),
+ new CoordRec(0, (float) 47.619 ),
new CoordRec((float) 14.2857, (float) 61.9048 ),
new CoordRec((float) 23.8095, (float) 66.6667 ),
new CoordRec((float) 38.0952, (float) 66.6667 ),
new CoordRec((float) 47.619, (float) 61.9048 ),
new CoordRec((float) 52.381, (float) 47.619 ),
- new CoordRec((float) 52.381, (float) 0 ),
+ new CoordRec((float) 52.381, 0 ),
};
static final CoordRec char109_stroke2[] = {
@@ -1858,9 +1858,9 @@ static final CoordRec char109_stroke2[] = {
new CoordRec((float) 66.6667, (float) 61.9048 ),
new CoordRec((float) 76.1905, (float) 66.6667 ),
new CoordRec((float) 90.4762, (float) 66.6667 ),
- new CoordRec((float) 100, (float) 61.9048 ),
+ new CoordRec(100, (float) 61.9048 ),
new CoordRec((float) 104.762, (float) 47.619 ),
- new CoordRec((float) 104.762, (float) 0 ),
+ new CoordRec((float) 104.762, 0 ),
};
static final StrokeRec char109[] = {
@@ -1873,17 +1873,17 @@ static final StrokeRec char109[] = {
static final CoordRec char110_stroke0[] = {
new CoordRec((float) 26.1905, (float) 66.6667 ),
- new CoordRec((float) 26.1905, (float) 0 ),
+ new CoordRec((float) 26.1905, 0 ),
};
static final CoordRec char110_stroke1[] = {
new CoordRec((float) 26.1905, (float) 47.619 ),
new CoordRec((float) 40.4762, (float) 61.9048 ),
- new CoordRec((float) 50, (float) 66.6667 ),
+ new CoordRec(50, (float) 66.6667 ),
new CoordRec((float) 64.2857, (float) 66.6667 ),
new CoordRec((float) 73.8095, (float) 61.9048 ),
new CoordRec((float) 78.5715, (float) 47.619 ),
- new CoordRec((float) 78.5715, (float) 0 ),
+ new CoordRec((float) 78.5715, 0 ),
};
static final StrokeRec char110[] = {
@@ -1901,8 +1901,8 @@ static final CoordRec char111_stroke0[] = {
new CoordRec((float) 21.4286, (float) 28.5714 ),
new CoordRec((float) 26.1905, (float) 14.2857 ),
new CoordRec((float) 35.7143, (float) 4.7619 ),
- new CoordRec((float) 45.2381, (float) 0 ),
- new CoordRec((float) 59.5238, (float) 0 ),
+ new CoordRec((float) 45.2381, 0 ),
+ new CoordRec((float) 59.5238, 0 ),
new CoordRec((float) 69.0476, (float) 4.7619 ),
new CoordRec((float) 78.5714, (float) 14.2857 ),
new CoordRec((float) 83.3334, (float) 28.5714 ),
@@ -1935,8 +1935,8 @@ static final CoordRec char112_stroke1[] = {
new CoordRec((float) 80.9524, (float) 28.5714 ),
new CoordRec((float) 76.1905, (float) 14.2857 ),
new CoordRec((float) 66.6666, (float) 4.7619 ),
- new CoordRec((float) 57.1428, (float) 0 ),
- new CoordRec((float) 42.8571, (float) 0 ),
+ new CoordRec((float) 57.1428, 0 ),
+ new CoordRec((float) 42.8571, 0 ),
new CoordRec((float) 33.3333, (float) 4.7619 ),
new CoordRec((float) 23.8095, (float) 14.2857 ),
};
@@ -1964,8 +1964,8 @@ static final CoordRec char113_stroke1[] = {
new CoordRec((float) 23.8095, (float) 28.5714 ),
new CoordRec((float) 28.5714, (float) 14.2857 ),
new CoordRec((float) 38.0952, (float) 4.7619 ),
- new CoordRec((float) 47.619, (float) 0 ),
- new CoordRec((float) 61.9047, (float) 0 ),
+ new CoordRec((float) 47.619, 0 ),
+ new CoordRec((float) 61.9047, 0 ),
new CoordRec((float) 71.4285, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
};
@@ -1979,7 +1979,7 @@ static final StrokeRec char113[] = {
static final CoordRec char114_stroke0[] = {
new CoordRec((float) 33.3334, (float) 66.6667 ),
- new CoordRec((float) 33.3334, (float) 0 ),
+ new CoordRec((float) 33.3334, 0 ),
};
static final CoordRec char114_stroke1[] = {
@@ -2011,8 +2011,8 @@ static final CoordRec char115_stroke0[] = {
new CoordRec((float) 78.5715, (float) 19.0476 ),
new CoordRec((float) 78.5715, (float) 14.2857 ),
new CoordRec((float) 73.8095, (float) 4.7619 ),
- new CoordRec((float) 59.5238, (float) 0 ),
- new CoordRec((float) 45.2381, (float) 0 ),
+ new CoordRec((float) 59.5238, 0 ),
+ new CoordRec((float) 45.2381, 0 ),
new CoordRec((float) 30.9524, (float) 4.7619 ),
new CoordRec((float) 26.1905, (float) 14.2857 ),
};
@@ -2024,11 +2024,11 @@ static final StrokeRec char115[] = {
/* char: 116 't' */
static final CoordRec char116_stroke0[] = {
- new CoordRec((float) 47.6191, (float) 100 ),
+ new CoordRec((float) 47.6191, 100 ),
new CoordRec((float) 47.6191, (float) 19.0476 ),
new CoordRec((float) 52.381, (float) 4.7619 ),
- new CoordRec((float) 61.9048, (float) 0 ),
- new CoordRec((float) 71.4286, (float) 0 ),
+ new CoordRec((float) 61.9048, 0 ),
+ new CoordRec((float) 71.4286, 0 ),
};
static final CoordRec char116_stroke1[] = {
@@ -2047,15 +2047,15 @@ static final CoordRec char117_stroke0[] = {
new CoordRec((float) 26.1905, (float) 66.6667 ),
new CoordRec((float) 26.1905, (float) 19.0476 ),
new CoordRec((float) 30.9524, (float) 4.7619 ),
- new CoordRec((float) 40.4762, (float) 0 ),
- new CoordRec((float) 54.7619, (float) 0 ),
+ new CoordRec((float) 40.4762, 0 ),
+ new CoordRec((float) 54.7619, 0 ),
new CoordRec((float) 64.2857, (float) 4.7619 ),
new CoordRec((float) 78.5715, (float) 19.0476 ),
};
static final CoordRec char117_stroke1[] = {
new CoordRec((float) 78.5715, (float) 66.6667 ),
- new CoordRec((float) 78.5715, (float) 0 ),
+ new CoordRec((float) 78.5715, 0 ),
};
static final StrokeRec char117[] = {
@@ -2067,12 +2067,12 @@ static final StrokeRec char117[] = {
static final CoordRec char118_stroke0[] = {
new CoordRec((float) 23.8095, (float) 66.6667 ),
- new CoordRec((float) 52.3809, (float) 0 ),
+ new CoordRec((float) 52.3809, 0 ),
};
static final CoordRec char118_stroke1[] = {
new CoordRec((float) 80.9524, (float) 66.6667 ),
- new CoordRec((float) 52.3809, (float) 0 ),
+ new CoordRec((float) 52.3809, 0 ),
};
static final StrokeRec char118[] = {
@@ -2084,22 +2084,22 @@ static final StrokeRec char118[] = {
static final CoordRec char119_stroke0[] = {
new CoordRec((float) 14.2857, (float) 66.6667 ),
- new CoordRec((float) 33.3333, (float) 0 ),
+ new CoordRec((float) 33.3333, 0 ),
};
static final CoordRec char119_stroke1[] = {
new CoordRec((float) 52.3809, (float) 66.6667 ),
- new CoordRec((float) 33.3333, (float) 0 ),
+ new CoordRec((float) 33.3333, 0 ),
};
static final CoordRec char119_stroke2[] = {
new CoordRec((float) 52.3809, (float) 66.6667 ),
- new CoordRec((float) 71.4286, (float) 0 ),
+ new CoordRec((float) 71.4286, 0 ),
};
static final CoordRec char119_stroke3[] = {
new CoordRec((float) 90.4762, (float) 66.6667 ),
- new CoordRec((float) 71.4286, (float) 0 ),
+ new CoordRec((float) 71.4286, 0 ),
};
static final StrokeRec char119[] = {
@@ -2113,12 +2113,12 @@ static final StrokeRec char119[] = {
static final CoordRec char120_stroke0[] = {
new CoordRec((float) 26.1905, (float) 66.6667 ),
- new CoordRec((float) 78.5715, (float) 0 ),
+ new CoordRec((float) 78.5715, 0 ),
};
static final CoordRec char120_stroke1[] = {
new CoordRec((float) 78.5715, (float) 66.6667 ),
- new CoordRec((float) 26.1905, (float) 0 ),
+ new CoordRec((float) 26.1905, 0 ),
};
static final StrokeRec char120[] = {
@@ -2130,12 +2130,12 @@ static final StrokeRec char120[] = {
static final CoordRec char121_stroke0[] = {
new CoordRec((float) 26.1905, (float) 66.6667 ),
- new CoordRec((float) 54.7619, (float) 0 ),
+ new CoordRec((float) 54.7619, 0 ),
};
static final CoordRec char121_stroke1[] = {
new CoordRec((float) 83.3334, (float) 66.6667 ),
- new CoordRec((float) 54.7619, (float) 0 ),
+ new CoordRec((float) 54.7619, 0 ),
new CoordRec((float) 45.2381, (float) -19.0476 ),
new CoordRec((float) 35.7143, (float) -28.5714 ),
new CoordRec((float) 26.1905, (float) -33.3333 ),
@@ -2151,7 +2151,7 @@ static final StrokeRec char121[] = {
static final CoordRec char122_stroke0[] = {
new CoordRec((float) 78.5715, (float) 66.6667 ),
- new CoordRec((float) 26.1905, (float) 0 ),
+ new CoordRec((float) 26.1905, 0 ),
};
static final CoordRec char122_stroke1[] = {
@@ -2160,8 +2160,8 @@ static final CoordRec char122_stroke1[] = {
};
static final CoordRec char122_stroke2[] = {
- new CoordRec((float) 26.1905, (float) 0 ),
- new CoordRec((float) 78.5715, (float) 0 ),
+ new CoordRec((float) 26.1905, 0 ),
+ new CoordRec((float) 78.5715, 0 ),
};
static final StrokeRec char122[] = {
@@ -2175,20 +2175,20 @@ static final StrokeRec char122[] = {
static final CoordRec char123_stroke0[] = {
new CoordRec((float) 64.2857, (float) 119.048 ),
new CoordRec((float) 54.7619, (float) 114.286 ),
- new CoordRec((float) 50, (float) 109.524 ),
- new CoordRec((float) 45.2381, (float) 100 ),
+ new CoordRec(50, (float) 109.524 ),
+ new CoordRec((float) 45.2381, 100 ),
new CoordRec((float) 45.2381, (float) 90.4762 ),
- new CoordRec((float) 50, (float) 80.9524 ),
+ new CoordRec(50, (float) 80.9524 ),
new CoordRec((float) 54.7619, (float) 76.1905 ),
new CoordRec((float) 59.5238, (float) 66.6667 ),
new CoordRec((float) 59.5238, (float) 57.1429 ),
- new CoordRec((float) 50, (float) 47.619 ),
+ new CoordRec(50, (float) 47.619 ),
};
static final CoordRec char123_stroke1[] = {
new CoordRec((float) 54.7619, (float) 114.286 ),
- new CoordRec((float) 50, (float) 104.762 ),
- new CoordRec((float) 50, (float) 95.2381 ),
+ new CoordRec(50, (float) 104.762 ),
+ new CoordRec(50, (float) 95.2381 ),
new CoordRec((float) 54.7619, (float) 85.7143 ),
new CoordRec((float) 59.5238, (float) 80.9524 ),
new CoordRec((float) 64.2857, (float) 71.4286 ),
@@ -2199,21 +2199,21 @@ static final CoordRec char123_stroke1[] = {
new CoordRec((float) 64.2857, (float) 23.8095 ),
new CoordRec((float) 64.2857, (float) 14.2857 ),
new CoordRec((float) 59.5238, (float) 4.7619 ),
- new CoordRec((float) 54.7619, (float) 0 ),
- new CoordRec((float) 50, (float) -9.5238 ),
- new CoordRec((float) 50, (float) -19.0476 ),
+ new CoordRec((float) 54.7619, 0 ),
+ new CoordRec(50, (float) -9.5238 ),
+ new CoordRec(50, (float) -19.0476 ),
new CoordRec((float) 54.7619, (float) -28.5714 ),
};
static final CoordRec char123_stroke2[] = {
- new CoordRec((float) 50, (float) 38.0952 ),
+ new CoordRec(50, (float) 38.0952 ),
new CoordRec((float) 59.5238, (float) 28.5714 ),
new CoordRec((float) 59.5238, (float) 19.0476 ),
new CoordRec((float) 54.7619, (float) 9.5238 ),
- new CoordRec((float) 50, (float) 4.7619 ),
+ new CoordRec(50, (float) 4.7619 ),
new CoordRec((float) 45.2381, (float) -4.7619 ),
new CoordRec((float) 45.2381, (float) -14.2857 ),
- new CoordRec((float) 50, (float) -23.8095 ),
+ new CoordRec(50, (float) -23.8095 ),
new CoordRec((float) 54.7619, (float) -28.5714 ),
new CoordRec((float) 64.2857, (float) -33.3333 ),
};
@@ -2239,22 +2239,22 @@ static final StrokeRec char124[] = {
static final CoordRec char125_stroke0[] = {
new CoordRec((float) 40.4762, (float) 119.048 ),
- new CoordRec((float) 50, (float) 114.286 ),
+ new CoordRec(50, (float) 114.286 ),
new CoordRec((float) 54.7619, (float) 109.524 ),
- new CoordRec((float) 59.5238, (float) 100 ),
+ new CoordRec((float) 59.5238, 100 ),
new CoordRec((float) 59.5238, (float) 90.4762 ),
new CoordRec((float) 54.7619, (float) 80.9524 ),
- new CoordRec((float) 50, (float) 76.1905 ),
+ new CoordRec(50, (float) 76.1905 ),
new CoordRec((float) 45.2381, (float) 66.6667 ),
new CoordRec((float) 45.2381, (float) 57.1429 ),
new CoordRec((float) 54.7619, (float) 47.619 ),
};
static final CoordRec char125_stroke1[] = {
- new CoordRec((float) 50, (float) 114.286 ),
+ new CoordRec(50, (float) 114.286 ),
new CoordRec((float) 54.7619, (float) 104.762 ),
new CoordRec((float) 54.7619, (float) 95.2381 ),
- new CoordRec((float) 50, (float) 85.7143 ),
+ new CoordRec(50, (float) 85.7143 ),
new CoordRec((float) 45.2381, (float) 80.9524 ),
new CoordRec((float) 40.4762, (float) 71.4286 ),
new CoordRec((float) 40.4762, (float) 61.9048 ),
@@ -2264,22 +2264,22 @@ static final CoordRec char125_stroke1[] = {
new CoordRec((float) 40.4762, (float) 23.8095 ),
new CoordRec((float) 40.4762, (float) 14.2857 ),
new CoordRec((float) 45.2381, (float) 4.7619 ),
- new CoordRec((float) 50, (float) 0 ),
+ new CoordRec(50, 0 ),
new CoordRec((float) 54.7619, (float) -9.5238 ),
new CoordRec((float) 54.7619, (float) -19.0476 ),
- new CoordRec((float) 50, (float) -28.5714 ),
+ new CoordRec(50, (float) -28.5714 ),
};
static final CoordRec char125_stroke2[] = {
new CoordRec((float) 54.7619, (float) 38.0952 ),
new CoordRec((float) 45.2381, (float) 28.5714 ),
new CoordRec((float) 45.2381, (float) 19.0476 ),
- new CoordRec((float) 50, (float) 9.5238 ),
+ new CoordRec(50, (float) 9.5238 ),
new CoordRec((float) 54.7619, (float) 4.7619 ),
new CoordRec((float) 59.5238, (float) -4.7619 ),
new CoordRec((float) 59.5238, (float) -14.2857 ),
new CoordRec((float) 54.7619, (float) -23.8095 ),
- new CoordRec((float) 50, (float) -28.5714 ),
+ new CoordRec(50, (float) -28.5714 ),
new CoordRec((float) 40.4762, (float) -33.3333 ),
};
@@ -2327,7 +2327,7 @@ static final StrokeRec char126[] = {
/* char: 127 */
static final CoordRec char127_stroke0[] = {
- new CoordRec((float) 71.4286, (float) 100 ),
+ new CoordRec((float) 71.4286, 100 ),
new CoordRec((float) 33.3333, (float) -33.3333 ),
};
@@ -2339,8 +2339,8 @@ static final CoordRec char127_stroke1[] = {
new CoordRec((float) 19.0476, (float) 23.8095 ),
new CoordRec((float) 23.8095, (float) 14.2857 ),
new CoordRec((float) 33.3333, (float) 4.7619 ),
- new CoordRec((float) 47.619, (float) 0 ),
- new CoordRec((float) 57.1428, (float) 0 ),
+ new CoordRec((float) 47.619, 0 ),
+ new CoordRec((float) 57.1428, 0 ),
new CoordRec((float) 71.4286, (float) 4.7619 ),
new CoordRec((float) 80.9524, (float) 14.2857 ),
new CoordRec((float) 85.7143, (float) 28.5714 ),
@@ -2357,38 +2357,38 @@ static final StrokeRec char127[] = {
};
static final StrokeCharRec chars[] = {
- new StrokeCharRec(0, /* char0 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char1 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char2 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char3 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char4 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char5 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char6 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char7 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char8 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char9 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char10 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char11 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char12 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char13 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char14 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char15 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char16 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char17 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char18 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char19 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char20 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char21 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char22 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char23 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char24 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char25 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char26 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char27 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char28 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char29 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char30 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec(0, /* char31 */ null, (float) 0, (float) 0 ),
+ new StrokeCharRec(0, /* char0 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char1 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char2 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char3 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char4 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char5 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char6 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char7 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char8 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char9 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char10 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char11 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char12 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char13 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char14 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char15 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char16 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char17 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char18 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char19 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char20 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char21 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char22 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char23 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char24 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char25 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char26 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char27 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char28 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char29 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char30 */ null, 0, 0 ),
+ new StrokeCharRec(0, /* char31 */ null, 0, 0 ),
new StrokeCharRec(0, /* char32 */ null, (float) 52.381, (float) 104.762 ),
new StrokeCharRec(2, char33, (float) 52.381, (float) 104.762 ),
new StrokeCharRec(2, char34, (float) 52.381, (float) 104.762 ),
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeRoman.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeRoman.java
index 94fa1c4fd..5b614c64e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeRoman.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeRoman.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -46,14 +46,14 @@ class GLUTStrokeRoman {
/* char: 33 '!' */
static final CoordRec char33_stroke0[] = {
- new CoordRec((float) 13.3819, (float) 100),
+ new CoordRec((float) 13.3819, 100),
new CoordRec((float) 13.3819, (float) 33.3333),
};
static final CoordRec char33_stroke1[] = {
new CoordRec((float) 13.3819, (float) 9.5238),
new CoordRec((float) 8.62, (float) 4.7619),
- new CoordRec((float) 13.3819, (float) 0),
+ new CoordRec((float) 13.3819, 0),
new CoordRec((float) 18.1438, (float) 4.7619),
new CoordRec((float) 13.3819, (float) 9.5238),
};
@@ -66,12 +66,12 @@ static final StrokeRec char33[] = {
/* char: 34 '"' */
static final CoordRec char34_stroke0[] = {
- new CoordRec((float) 4.02, (float) 100),
+ new CoordRec((float) 4.02, 100),
new CoordRec((float) 4.02, (float) 66.6667),
};
static final CoordRec char34_stroke1[] = {
- new CoordRec((float) 42.1152, (float) 100),
+ new CoordRec((float) 42.1152, 100),
new CoordRec((float) 42.1152, (float) 66.6667),
};
@@ -124,8 +124,8 @@ static final CoordRec char36_stroke1[] = {
static final CoordRec char36_stroke2[] = {
new CoordRec((float) 71.4867, (float) 85.7143),
new CoordRec((float) 61.9629, (float) 95.2381),
- new CoordRec((float) 47.6771, (float) 100),
- new CoordRec((float) 28.6295, (float) 100),
+ new CoordRec((float) 47.6771, 100),
+ new CoordRec((float) 28.6295, 100),
new CoordRec((float) 14.3438, (float) 95.2381),
new CoordRec((float) 4.82, (float) 85.7143),
new CoordRec((float) 4.82, (float) 76.1905),
@@ -138,8 +138,8 @@ static final CoordRec char36_stroke2[] = {
new CoordRec((float) 71.4867, (float) 28.5714),
new CoordRec((float) 71.4867, (float) 14.2857),
new CoordRec((float) 61.9629, (float) 4.7619),
- new CoordRec((float) 47.6771, (float) 0),
- new CoordRec((float) 28.6295, (float) 0),
+ new CoordRec((float) 47.6771, 0),
+ new CoordRec((float) 28.6295, 0),
new CoordRec((float) 14.3438, (float) 4.7619),
new CoordRec((float) 4.82, (float) 14.2857),
};
@@ -153,12 +153,12 @@ static final StrokeRec char36[] = {
/* char: 37 '%' */
static final CoordRec char37_stroke0[] = {
- new CoordRec((float) 92.0743, (float) 100),
- new CoordRec((float) 6.36, (float) 0),
+ new CoordRec((float) 92.0743, 100),
+ new CoordRec((float) 6.36, 0),
};
static final CoordRec char37_stroke1[] = {
- new CoordRec((float) 30.1695, (float) 100),
+ new CoordRec((float) 30.1695, 100),
new CoordRec((float) 39.6933, (float) 90.4762),
new CoordRec((float) 39.6933, (float) 80.9524),
new CoordRec((float) 34.9314, (float) 71.4286),
@@ -167,13 +167,13 @@ static final CoordRec char37_stroke1[] = {
new CoordRec((float) 6.36, (float) 76.1905),
new CoordRec((float) 6.36, (float) 85.7143),
new CoordRec((float) 11.1219, (float) 95.2381),
- new CoordRec((float) 20.6457, (float) 100),
- new CoordRec((float) 30.1695, (float) 100),
+ new CoordRec((float) 20.6457, 100),
+ new CoordRec((float) 30.1695, 100),
new CoordRec((float) 39.6933, (float) 95.2381),
new CoordRec((float) 53.979, (float) 90.4762),
new CoordRec((float) 68.2648, (float) 90.4762),
new CoordRec((float) 82.5505, (float) 95.2381),
- new CoordRec((float) 92.0743, (float) 100),
+ new CoordRec((float) 92.0743, 100),
};
static final CoordRec char37_stroke2[] = {
@@ -181,8 +181,8 @@ static final CoordRec char37_stroke2[] = {
new CoordRec((float) 63.5029, (float) 28.5714),
new CoordRec((float) 58.741, (float) 19.0476),
new CoordRec((float) 58.741, (float) 9.5238),
- new CoordRec((float) 68.2648, (float) 0),
- new CoordRec((float) 77.7886, (float) 0),
+ new CoordRec((float) 68.2648, 0),
+ new CoordRec((float) 77.7886, 0),
new CoordRec((float) 87.3124, (float) 4.7619),
new CoordRec((float) 92.0743, (float) 14.2857),
new CoordRec((float) 92.0743, (float) 23.8095),
@@ -208,8 +208,8 @@ static final CoordRec char38_stroke0[] = {
new CoordRec((float) 72.6467, (float) 28.5714),
new CoordRec((float) 63.1229, (float) 14.2857),
new CoordRec((float) 53.599, (float) 4.7619),
- new CoordRec((float) 44.0752, (float) 0),
- new CoordRec((float) 25.0276, (float) 0),
+ new CoordRec((float) 44.0752, 0),
+ new CoordRec((float) 25.0276, 0),
new CoordRec((float) 15.5038, (float) 4.7619),
new CoordRec((float) 10.7419, (float) 9.5238),
new CoordRec((float) 5.98, (float) 19.0476),
@@ -221,7 +221,7 @@ static final CoordRec char38_stroke0[] = {
new CoordRec((float) 58.361, (float) 76.1905),
new CoordRec((float) 58.361, (float) 85.7143),
new CoordRec((float) 53.599, (float) 95.2381),
- new CoordRec((float) 44.0752, (float) 100),
+ new CoordRec((float) 44.0752, 100),
new CoordRec((float) 34.5514, (float) 95.2381),
new CoordRec((float) 29.7895, (float) 85.7143),
new CoordRec((float) 29.7895, (float) 76.1905),
@@ -229,8 +229,8 @@ static final CoordRec char38_stroke0[] = {
new CoordRec((float) 44.0752, (float) 47.619),
new CoordRec((float) 67.8848, (float) 14.2857),
new CoordRec((float) 77.4086, (float) 4.7619),
- new CoordRec((float) 86.9324, (float) 0),
- new CoordRec((float) 96.4562, (float) 0),
+ new CoordRec((float) 86.9324, 0),
+ new CoordRec((float) 96.4562, 0),
new CoordRec((float) 101.218, (float) 4.7619),
new CoordRec((float) 101.218, (float) 9.5238),
};
@@ -242,7 +242,7 @@ static final StrokeRec char38[] = {
/* char: 39 ''' */
static final CoordRec char39_stroke0[] = {
- new CoordRec((float) 4.44, (float) 100),
+ new CoordRec((float) 4.44, 100),
new CoordRec((float) 4.44, (float) 66.6667),
};
@@ -315,7 +315,7 @@ static final StrokeRec char42[] = {
static final CoordRec char43_stroke0[] = {
new CoordRec((float) 48.8371, (float) 85.7143),
- new CoordRec((float) 48.8371, (float) 0),
+ new CoordRec((float) 48.8371, 0),
};
static final CoordRec char43_stroke1[] = {
@@ -332,7 +332,7 @@ static final StrokeRec char43[] = {
static final CoordRec char44_stroke0[] = {
new CoordRec((float) 18.2838, (float) 4.7619),
- new CoordRec((float) 13.5219, (float) 0),
+ new CoordRec((float) 13.5219, 0),
new CoordRec((float) 8.76, (float) 4.7619),
new CoordRec((float) 13.5219, (float) 9.5238),
new CoordRec((float) 18.2838, (float) 4.7619),
@@ -361,7 +361,7 @@ static final StrokeRec char45[] = {
static final CoordRec char46_stroke0[] = {
new CoordRec((float) 13.1019, (float) 9.5238),
new CoordRec((float) 8.34, (float) 4.7619),
- new CoordRec((float) 13.1019, (float) 0),
+ new CoordRec((float) 13.1019, 0),
new CoordRec((float) 17.8638, (float) 4.7619),
new CoordRec((float) 13.1019, (float) 9.5238),
};
@@ -374,7 +374,7 @@ static final StrokeRec char46[] = {
static final CoordRec char47_stroke0[] = {
new CoordRec((float) 7.24, (float) -14.2857),
- new CoordRec((float) 73.9067, (float) 100),
+ new CoordRec((float) 73.9067, 100),
};
static final StrokeRec char47[] = {
@@ -384,23 +384,23 @@ static final StrokeRec char47[] = {
/* char: 48 '0' */
static final CoordRec char48_stroke0[] = {
- new CoordRec((float) 33.5514, (float) 100),
+ new CoordRec((float) 33.5514, 100),
new CoordRec((float) 19.2657, (float) 95.2381),
new CoordRec((float) 9.7419, (float) 80.9524),
new CoordRec((float) 4.98, (float) 57.1429),
new CoordRec((float) 4.98, (float) 42.8571),
new CoordRec((float) 9.7419, (float) 19.0476),
new CoordRec((float) 19.2657, (float) 4.7619),
- new CoordRec((float) 33.5514, (float) 0),
- new CoordRec((float) 43.0752, (float) 0),
+ new CoordRec((float) 33.5514, 0),
+ new CoordRec((float) 43.0752, 0),
new CoordRec((float) 57.361, (float) 4.7619),
new CoordRec((float) 66.8848, (float) 19.0476),
new CoordRec((float) 71.6467, (float) 42.8571),
new CoordRec((float) 71.6467, (float) 57.1429),
new CoordRec((float) 66.8848, (float) 80.9524),
new CoordRec((float) 57.361, (float) 95.2381),
- new CoordRec((float) 43.0752, (float) 100),
- new CoordRec((float) 33.5514, (float) 100),
+ new CoordRec((float) 43.0752, 100),
+ new CoordRec((float) 33.5514, 100),
};
static final StrokeRec char48[] = {
@@ -412,8 +412,8 @@ static final StrokeRec char48[] = {
static final CoordRec char49_stroke0[] = {
new CoordRec((float) 11.82, (float) 80.9524),
new CoordRec((float) 21.3438, (float) 85.7143),
- new CoordRec((float) 35.6295, (float) 100),
- new CoordRec((float) 35.6295, (float) 0),
+ new CoordRec((float) 35.6295, 100),
+ new CoordRec((float) 35.6295, 0),
};
static final StrokeRec char49[] = {
@@ -427,16 +427,16 @@ static final CoordRec char50_stroke0[] = {
new CoordRec((float) 10.1819, (float) 80.9524),
new CoordRec((float) 14.9438, (float) 90.4762),
new CoordRec((float) 19.7057, (float) 95.2381),
- new CoordRec((float) 29.2295, (float) 100),
- new CoordRec((float) 48.2771, (float) 100),
+ new CoordRec((float) 29.2295, 100),
+ new CoordRec((float) 48.2771, 100),
new CoordRec((float) 57.801, (float) 95.2381),
new CoordRec((float) 62.5629, (float) 90.4762),
new CoordRec((float) 67.3248, (float) 80.9524),
new CoordRec((float) 67.3248, (float) 71.4286),
new CoordRec((float) 62.5629, (float) 61.9048),
new CoordRec((float) 53.039, (float) 47.619),
- new CoordRec((float) 5.42, (float) 0),
- new CoordRec((float) 72.0867, (float) 0),
+ new CoordRec((float) 5.42, 0),
+ new CoordRec((float) 72.0867, 0),
};
static final StrokeRec char50[] = {
@@ -446,8 +446,8 @@ static final StrokeRec char50[] = {
/* char: 51 '3' */
static final CoordRec char51_stroke0[] = {
- new CoordRec((float) 14.5238, (float) 100),
- new CoordRec((float) 66.9048, (float) 100),
+ new CoordRec((float) 14.5238, 100),
+ new CoordRec((float) 66.9048, 100),
new CoordRec((float) 38.3333, (float) 61.9048),
new CoordRec((float) 52.619, (float) 61.9048),
new CoordRec((float) 62.1429, (float) 57.1429),
@@ -456,11 +456,11 @@ static final CoordRec char51_stroke0[] = {
new CoordRec((float) 71.6667, (float) 28.5714),
new CoordRec((float) 66.9048, (float) 14.2857),
new CoordRec((float) 57.381, (float) 4.7619),
- new CoordRec((float) 43.0952, (float) 0),
- new CoordRec((float) 28.8095, (float) 0),
+ new CoordRec((float) 43.0952, 0),
+ new CoordRec((float) 28.8095, 0),
new CoordRec((float) 14.5238, (float) 4.7619),
new CoordRec((float) 9.7619, (float) 9.5238),
- new CoordRec((float) 5, (float) 19.0476),
+ new CoordRec(5, (float) 19.0476),
};
static final StrokeRec char51[] = {
@@ -470,14 +470,14 @@ static final StrokeRec char51[] = {
/* char: 52 '4' */
static final CoordRec char52_stroke0[] = {
- new CoordRec((float) 51.499, (float) 100),
+ new CoordRec((float) 51.499, 100),
new CoordRec((float) 3.88, (float) 33.3333),
new CoordRec((float) 75.3086, (float) 33.3333),
};
static final CoordRec char52_stroke1[] = {
- new CoordRec((float) 51.499, (float) 100),
- new CoordRec((float) 51.499, (float) 0),
+ new CoordRec((float) 51.499, 100),
+ new CoordRec((float) 51.499, 0),
};
static final StrokeRec char52[] = {
@@ -488,8 +488,8 @@ static final StrokeRec char52[] = {
/* char: 53 '5' */
static final CoordRec char53_stroke0[] = {
- new CoordRec((float) 62.0029, (float) 100),
- new CoordRec((float) 14.3838, (float) 100),
+ new CoordRec((float) 62.0029, 100),
+ new CoordRec((float) 14.3838, 100),
new CoordRec((float) 9.6219, (float) 57.1429),
new CoordRec((float) 14.3838, (float) 61.9048),
new CoordRec((float) 28.6695, (float) 66.6667),
@@ -500,8 +500,8 @@ static final CoordRec char53_stroke0[] = {
new CoordRec((float) 71.5267, (float) 28.5714),
new CoordRec((float) 66.7648, (float) 14.2857),
new CoordRec((float) 57.241, (float) 4.7619),
- new CoordRec((float) 42.9552, (float) 0),
- new CoordRec((float) 28.6695, (float) 0),
+ new CoordRec((float) 42.9552, 0),
+ new CoordRec((float) 28.6695, 0),
new CoordRec((float) 14.3838, (float) 4.7619),
new CoordRec((float) 9.6219, (float) 9.5238),
new CoordRec((float) 4.86, (float) 19.0476),
@@ -516,16 +516,16 @@ static final StrokeRec char53[] = {
static final CoordRec char54_stroke0[] = {
new CoordRec((float) 62.7229, (float) 85.7143),
new CoordRec((float) 57.961, (float) 95.2381),
- new CoordRec((float) 43.6752, (float) 100),
- new CoordRec((float) 34.1514, (float) 100),
+ new CoordRec((float) 43.6752, 100),
+ new CoordRec((float) 34.1514, 100),
new CoordRec((float) 19.8657, (float) 95.2381),
new CoordRec((float) 10.3419, (float) 80.9524),
new CoordRec((float) 5.58, (float) 57.1429),
new CoordRec((float) 5.58, (float) 33.3333),
new CoordRec((float) 10.3419, (float) 14.2857),
new CoordRec((float) 19.8657, (float) 4.7619),
- new CoordRec((float) 34.1514, (float) 0),
- new CoordRec((float) 38.9133, (float) 0),
+ new CoordRec((float) 34.1514, 0),
+ new CoordRec((float) 38.9133, 0),
new CoordRec((float) 53.199, (float) 4.7619),
new CoordRec((float) 62.7229, (float) 14.2857),
new CoordRec((float) 67.4848, (float) 28.5714),
@@ -546,13 +546,13 @@ static final StrokeRec char54[] = {
/* char: 55 '7' */
static final CoordRec char55_stroke0[] = {
- new CoordRec((float) 72.2267, (float) 100),
- new CoordRec((float) 24.6076, (float) 0),
+ new CoordRec((float) 72.2267, 100),
+ new CoordRec((float) 24.6076, 0),
};
static final CoordRec char55_stroke1[] = {
- new CoordRec((float) 5.56, (float) 100),
- new CoordRec((float) 72.2267, (float) 100),
+ new CoordRec((float) 5.56, 100),
+ new CoordRec((float) 72.2267, 100),
};
static final StrokeRec char55[] = {
@@ -563,7 +563,7 @@ static final StrokeRec char55[] = {
/* char: 56 '8' */
static final CoordRec char56_stroke0[] = {
- new CoordRec((float) 29.4095, (float) 100),
+ new CoordRec((float) 29.4095, 100),
new CoordRec((float) 15.1238, (float) 95.2381),
new CoordRec((float) 10.3619, (float) 85.7143),
new CoordRec((float) 10.3619, (float) 76.1905),
@@ -576,8 +576,8 @@ static final CoordRec char56_stroke0[] = {
new CoordRec((float) 72.2667, (float) 19.0476),
new CoordRec((float) 67.5048, (float) 9.5238),
new CoordRec((float) 62.7429, (float) 4.7619),
- new CoordRec((float) 48.4571, (float) 0),
- new CoordRec((float) 29.4095, (float) 0),
+ new CoordRec((float) 48.4571, 0),
+ new CoordRec((float) 29.4095, 0),
new CoordRec((float) 15.1238, (float) 4.7619),
new CoordRec((float) 10.3619, (float) 9.5238),
new CoordRec((float) 5.6, (float) 19.0476),
@@ -590,8 +590,8 @@ static final CoordRec char56_stroke0[] = {
new CoordRec((float) 67.5048, (float) 76.1905),
new CoordRec((float) 67.5048, (float) 85.7143),
new CoordRec((float) 62.7429, (float) 95.2381),
- new CoordRec((float) 48.4571, (float) 100),
- new CoordRec((float) 29.4095, (float) 100),
+ new CoordRec((float) 48.4571, 100),
+ new CoordRec((float) 29.4095, 100),
};
static final StrokeRec char56[] = {
@@ -612,16 +612,16 @@ static final CoordRec char57_stroke0[] = {
new CoordRec((float) 6.6, (float) 71.4286),
new CoordRec((float) 11.3619, (float) 85.7143),
new CoordRec((float) 20.8857, (float) 95.2381),
- new CoordRec((float) 35.1714, (float) 100),
- new CoordRec((float) 39.9333, (float) 100),
+ new CoordRec((float) 35.1714, 100),
+ new CoordRec((float) 39.9333, 100),
new CoordRec((float) 54.219, (float) 95.2381),
new CoordRec((float) 63.7429, (float) 85.7143),
new CoordRec((float) 68.5048, (float) 66.6667),
new CoordRec((float) 68.5048, (float) 42.8571),
new CoordRec((float) 63.7429, (float) 19.0476),
new CoordRec((float) 54.219, (float) 4.7619),
- new CoordRec((float) 39.9333, (float) 0),
- new CoordRec((float) 30.4095, (float) 0),
+ new CoordRec((float) 39.9333, 0),
+ new CoordRec((float) 30.4095, 0),
new CoordRec((float) 16.1238, (float) 4.7619),
new CoordRec((float) 11.3619, (float) 14.2857),
};
@@ -643,7 +643,7 @@ static final CoordRec char58_stroke0[] = {
static final CoordRec char58_stroke1[] = {
new CoordRec((float) 14.0819, (float) 9.5238),
new CoordRec((float) 9.32, (float) 4.7619),
- new CoordRec((float) 14.0819, (float) 0),
+ new CoordRec((float) 14.0819, 0),
new CoordRec((float) 18.8438, (float) 4.7619),
new CoordRec((float) 14.0819, (float) 9.5238),
};
@@ -665,7 +665,7 @@ static final CoordRec char59_stroke0[] = {
static final CoordRec char59_stroke1[] = {
new CoordRec((float) 17.7238, (float) 4.7619),
- new CoordRec((float) 12.9619, (float) 0),
+ new CoordRec((float) 12.9619, 0),
new CoordRec((float) 8.2, (float) 4.7619),
new CoordRec((float) 12.9619, (float) 9.5238),
new CoordRec((float) 17.7238, (float) 4.7619),
@@ -684,7 +684,7 @@ static final StrokeRec char59[] = {
static final CoordRec char60_stroke0[] = {
new CoordRec((float) 79.2505, (float) 85.7143),
new CoordRec((float) 3.06, (float) 42.8571),
- new CoordRec((float) 79.2505, (float) 0),
+ new CoordRec((float) 79.2505, 0),
};
static final StrokeRec char60[] = {
@@ -713,7 +713,7 @@ static final StrokeRec char61[] = {
static final CoordRec char62_stroke0[] = {
new CoordRec((float) 2.78, (float) 85.7143),
new CoordRec((float) 78.9705, (float) 42.8571),
- new CoordRec((float) 2.78, (float) 0),
+ new CoordRec((float) 2.78, 0),
};
static final StrokeRec char62[] = {
@@ -727,8 +727,8 @@ static final CoordRec char63_stroke0[] = {
new CoordRec((float) 8.42, (float) 80.9524),
new CoordRec((float) 13.1819, (float) 90.4762),
new CoordRec((float) 17.9438, (float) 95.2381),
- new CoordRec((float) 27.4676, (float) 100),
- new CoordRec((float) 46.5152, (float) 100),
+ new CoordRec((float) 27.4676, 100),
+ new CoordRec((float) 46.5152, 100),
new CoordRec((float) 56.039, (float) 95.2381),
new CoordRec((float) 60.801, (float) 90.4762),
new CoordRec((float) 65.5629, (float) 80.9524),
@@ -742,7 +742,7 @@ static final CoordRec char63_stroke0[] = {
static final CoordRec char63_stroke1[] = {
new CoordRec((float) 36.9914, (float) 9.5238),
new CoordRec((float) 32.2295, (float) 4.7619),
- new CoordRec((float) 36.9914, (float) 0),
+ new CoordRec((float) 36.9914, 0),
new CoordRec((float) 41.7533, (float) 4.7619),
new CoordRec((float) 36.9914, (float) 9.5238),
};
@@ -795,13 +795,13 @@ static final StrokeRec char64[] = {
/* char: 65 'A' */
static final CoordRec char65_stroke0[] = {
- new CoordRec((float) 40.5952, (float) 100),
- new CoordRec((float) 2.5, (float) 0),
+ new CoordRec((float) 40.5952, 100),
+ new CoordRec((float) 2.5, 0),
};
static final CoordRec char65_stroke1[] = {
- new CoordRec((float) 40.5952, (float) 100),
- new CoordRec((float) 78.6905, (float) 0),
+ new CoordRec((float) 40.5952, 100),
+ new CoordRec((float) 78.6905, 0),
};
static final CoordRec char65_stroke2[] = {
@@ -818,13 +818,13 @@ static final StrokeRec char65[] = {
/* char: 66 'B' */
static final CoordRec char66_stroke0[] = {
- new CoordRec((float) 11.42, (float) 100),
- new CoordRec((float) 11.42, (float) 0),
+ new CoordRec((float) 11.42, 100),
+ new CoordRec((float) 11.42, 0),
};
static final CoordRec char66_stroke1[] = {
- new CoordRec((float) 11.42, (float) 100),
- new CoordRec((float) 54.2771, (float) 100),
+ new CoordRec((float) 11.42, 100),
+ new CoordRec((float) 54.2771, 100),
new CoordRec((float) 68.5629, (float) 95.2381),
new CoordRec((float) 73.3248, (float) 90.4762),
new CoordRec((float) 78.0867, (float) 80.9524),
@@ -843,8 +843,8 @@ static final CoordRec char66_stroke2[] = {
new CoordRec((float) 78.0867, (float) 19.0476),
new CoordRec((float) 73.3248, (float) 9.5238),
new CoordRec((float) 68.5629, (float) 4.7619),
- new CoordRec((float) 54.2771, (float) 0),
- new CoordRec((float) 11.42, (float) 0),
+ new CoordRec((float) 54.2771, 0),
+ new CoordRec((float) 11.42, 0),
};
static final StrokeRec char66[] = {
@@ -859,8 +859,8 @@ static final CoordRec char67_stroke0[] = {
new CoordRec((float) 78.0886, (float) 76.1905),
new CoordRec((float) 73.3267, (float) 85.7143),
new CoordRec((float) 63.8029, (float) 95.2381),
- new CoordRec((float) 54.279, (float) 100),
- new CoordRec((float) 35.2314, (float) 100),
+ new CoordRec((float) 54.279, 100),
+ new CoordRec((float) 35.2314, 100),
new CoordRec((float) 25.7076, (float) 95.2381),
new CoordRec((float) 16.1838, (float) 85.7143),
new CoordRec((float) 11.4219, (float) 76.1905),
@@ -869,8 +869,8 @@ static final CoordRec char67_stroke0[] = {
new CoordRec((float) 11.4219, (float) 23.8095),
new CoordRec((float) 16.1838, (float) 14.2857),
new CoordRec((float) 25.7076, (float) 4.7619),
- new CoordRec((float) 35.2314, (float) 0),
- new CoordRec((float) 54.279, (float) 0),
+ new CoordRec((float) 35.2314, 0),
+ new CoordRec((float) 54.279, 0),
new CoordRec((float) 63.8029, (float) 4.7619),
new CoordRec((float) 73.3267, (float) 14.2857),
new CoordRec((float) 78.0886, (float) 23.8095),
@@ -883,13 +883,13 @@ static final StrokeRec char67[] = {
/* char: 68 'D' */
static final CoordRec char68_stroke0[] = {
- new CoordRec((float) 11.96, (float) 100),
- new CoordRec((float) 11.96, (float) 0),
+ new CoordRec((float) 11.96, 100),
+ new CoordRec((float) 11.96, 0),
};
static final CoordRec char68_stroke1[] = {
- new CoordRec((float) 11.96, (float) 100),
- new CoordRec((float) 45.2933, (float) 100),
+ new CoordRec((float) 11.96, 100),
+ new CoordRec((float) 45.2933, 100),
new CoordRec((float) 59.579, (float) 95.2381),
new CoordRec((float) 69.1029, (float) 85.7143),
new CoordRec((float) 73.8648, (float) 76.1905),
@@ -898,8 +898,8 @@ static final CoordRec char68_stroke1[] = {
new CoordRec((float) 73.8648, (float) 23.8095),
new CoordRec((float) 69.1029, (float) 14.2857),
new CoordRec((float) 59.579, (float) 4.7619),
- new CoordRec((float) 45.2933, (float) 0),
- new CoordRec((float) 11.96, (float) 0),
+ new CoordRec((float) 45.2933, 0),
+ new CoordRec((float) 11.96, 0),
};
static final StrokeRec char68[] = {
@@ -910,13 +910,13 @@ static final StrokeRec char68[] = {
/* char: 69 'E' */
static final CoordRec char69_stroke0[] = {
- new CoordRec((float) 11.42, (float) 100),
- new CoordRec((float) 11.42, (float) 0),
+ new CoordRec((float) 11.42, 100),
+ new CoordRec((float) 11.42, 0),
};
static final CoordRec char69_stroke1[] = {
- new CoordRec((float) 11.42, (float) 100),
- new CoordRec((float) 73.3248, (float) 100),
+ new CoordRec((float) 11.42, 100),
+ new CoordRec((float) 73.3248, 100),
};
static final CoordRec char69_stroke2[] = {
@@ -925,8 +925,8 @@ static final CoordRec char69_stroke2[] = {
};
static final CoordRec char69_stroke3[] = {
- new CoordRec((float) 11.42, (float) 0),
- new CoordRec((float) 73.3248, (float) 0),
+ new CoordRec((float) 11.42, 0),
+ new CoordRec((float) 73.3248, 0),
};
static final StrokeRec char69[] = {
@@ -939,13 +939,13 @@ static final StrokeRec char69[] = {
/* char: 70 'F' */
static final CoordRec char70_stroke0[] = {
- new CoordRec((float) 11.42, (float) 100),
- new CoordRec((float) 11.42, (float) 0),
+ new CoordRec((float) 11.42, 100),
+ new CoordRec((float) 11.42, 0),
};
static final CoordRec char70_stroke1[] = {
- new CoordRec((float) 11.42, (float) 100),
- new CoordRec((float) 73.3248, (float) 100),
+ new CoordRec((float) 11.42, 100),
+ new CoordRec((float) 73.3248, 100),
};
static final CoordRec char70_stroke2[] = {
@@ -965,8 +965,8 @@ static final CoordRec char71_stroke0[] = {
new CoordRec((float) 78.4886, (float) 76.1905),
new CoordRec((float) 73.7267, (float) 85.7143),
new CoordRec((float) 64.2029, (float) 95.2381),
- new CoordRec((float) 54.679, (float) 100),
- new CoordRec((float) 35.6314, (float) 100),
+ new CoordRec((float) 54.679, 100),
+ new CoordRec((float) 35.6314, 100),
new CoordRec((float) 26.1076, (float) 95.2381),
new CoordRec((float) 16.5838, (float) 85.7143),
new CoordRec((float) 11.8219, (float) 76.1905),
@@ -975,8 +975,8 @@ static final CoordRec char71_stroke0[] = {
new CoordRec((float) 11.8219, (float) 23.8095),
new CoordRec((float) 16.5838, (float) 14.2857),
new CoordRec((float) 26.1076, (float) 4.7619),
- new CoordRec((float) 35.6314, (float) 0),
- new CoordRec((float) 54.679, (float) 0),
+ new CoordRec((float) 35.6314, 0),
+ new CoordRec((float) 54.679, 0),
new CoordRec((float) 64.2029, (float) 4.7619),
new CoordRec((float) 73.7267, (float) 14.2857),
new CoordRec((float) 78.4886, (float) 23.8095),
@@ -996,13 +996,13 @@ static final StrokeRec char71[] = {
/* char: 72 'H' */
static final CoordRec char72_stroke0[] = {
- new CoordRec((float) 11.42, (float) 100),
- new CoordRec((float) 11.42, (float) 0),
+ new CoordRec((float) 11.42, 100),
+ new CoordRec((float) 11.42, 0),
};
static final CoordRec char72_stroke1[] = {
- new CoordRec((float) 78.0867, (float) 100),
- new CoordRec((float) 78.0867, (float) 0),
+ new CoordRec((float) 78.0867, 100),
+ new CoordRec((float) 78.0867, 0),
};
static final CoordRec char72_stroke2[] = {
@@ -1019,8 +1019,8 @@ static final StrokeRec char72[] = {
/* char: 73 'I' */
static final CoordRec char73_stroke0[] = {
- new CoordRec((float) 10.86, (float) 100),
- new CoordRec((float) 10.86, (float) 0),
+ new CoordRec((float) 10.86, 100),
+ new CoordRec((float) 10.86, 0),
};
static final StrokeRec char73[] = {
@@ -1030,12 +1030,12 @@ static final StrokeRec char73[] = {
/* char: 74 'J' */
static final CoordRec char74_stroke0[] = {
- new CoordRec((float) 50.119, (float) 100),
+ new CoordRec((float) 50.119, 100),
new CoordRec((float) 50.119, (float) 23.8095),
new CoordRec((float) 45.3571, (float) 9.5238),
new CoordRec((float) 40.5952, (float) 4.7619),
- new CoordRec((float) 31.0714, (float) 0),
- new CoordRec((float) 21.5476, (float) 0),
+ new CoordRec((float) 31.0714, 0),
+ new CoordRec((float) 21.5476, 0),
new CoordRec((float) 12.0238, (float) 4.7619),
new CoordRec((float) 7.2619, (float) 9.5238),
new CoordRec((float) 2.5, (float) 23.8095),
@@ -1049,18 +1049,18 @@ static final StrokeRec char74[] = {
/* char: 75 'K' */
static final CoordRec char75_stroke0[] = {
- new CoordRec((float) 11.28, (float) 100),
- new CoordRec((float) 11.28, (float) 0),
+ new CoordRec((float) 11.28, 100),
+ new CoordRec((float) 11.28, 0),
};
static final CoordRec char75_stroke1[] = {
- new CoordRec((float) 77.9467, (float) 100),
+ new CoordRec((float) 77.9467, 100),
new CoordRec((float) 11.28, (float) 33.3333),
};
static final CoordRec char75_stroke2[] = {
new CoordRec((float) 35.0895, (float) 57.1429),
- new CoordRec((float) 77.9467, (float) 0),
+ new CoordRec((float) 77.9467, 0),
};
static final StrokeRec char75[] = {
@@ -1072,13 +1072,13 @@ static final StrokeRec char75[] = {
/* char: 76 'L' */
static final CoordRec char76_stroke0[] = {
- new CoordRec((float) 11.68, (float) 100),
- new CoordRec((float) 11.68, (float) 0),
+ new CoordRec((float) 11.68, 100),
+ new CoordRec((float) 11.68, 0),
};
static final CoordRec char76_stroke1[] = {
- new CoordRec((float) 11.68, (float) 0),
- new CoordRec((float) 68.8229, (float) 0),
+ new CoordRec((float) 11.68, 0),
+ new CoordRec((float) 68.8229, 0),
};
static final StrokeRec char76[] = {
@@ -1089,23 +1089,23 @@ static final StrokeRec char76[] = {
/* char: 77 'M' */
static final CoordRec char77_stroke0[] = {
- new CoordRec((float) 10.86, (float) 100),
- new CoordRec((float) 10.86, (float) 0),
+ new CoordRec((float) 10.86, 100),
+ new CoordRec((float) 10.86, 0),
};
static final CoordRec char77_stroke1[] = {
- new CoordRec((float) 10.86, (float) 100),
- new CoordRec((float) 48.9552, (float) 0),
+ new CoordRec((float) 10.86, 100),
+ new CoordRec((float) 48.9552, 0),
};
static final CoordRec char77_stroke2[] = {
- new CoordRec((float) 87.0505, (float) 100),
- new CoordRec((float) 48.9552, (float) 0),
+ new CoordRec((float) 87.0505, 100),
+ new CoordRec((float) 48.9552, 0),
};
static final CoordRec char77_stroke3[] = {
- new CoordRec((float) 87.0505, (float) 100),
- new CoordRec((float) 87.0505, (float) 0),
+ new CoordRec((float) 87.0505, 100),
+ new CoordRec((float) 87.0505, 0),
};
static final StrokeRec char77[] = {
@@ -1118,18 +1118,18 @@ static final StrokeRec char77[] = {
/* char: 78 'N' */
static final CoordRec char78_stroke0[] = {
- new CoordRec((float) 11.14, (float) 100),
- new CoordRec((float) 11.14, (float) 0),
+ new CoordRec((float) 11.14, 100),
+ new CoordRec((float) 11.14, 0),
};
static final CoordRec char78_stroke1[] = {
- new CoordRec((float) 11.14, (float) 100),
- new CoordRec((float) 77.8067, (float) 0),
+ new CoordRec((float) 11.14, 100),
+ new CoordRec((float) 77.8067, 0),
};
static final CoordRec char78_stroke2[] = {
- new CoordRec((float) 77.8067, (float) 100),
- new CoordRec((float) 77.8067, (float) 0),
+ new CoordRec((float) 77.8067, 100),
+ new CoordRec((float) 77.8067, 0),
};
static final StrokeRec char78[] = {
@@ -1141,7 +1141,7 @@ static final StrokeRec char78[] = {
/* char: 79 'O' */
static final CoordRec char79_stroke0[] = {
- new CoordRec((float) 34.8114, (float) 100),
+ new CoordRec((float) 34.8114, 100),
new CoordRec((float) 25.2876, (float) 95.2381),
new CoordRec((float) 15.7638, (float) 85.7143),
new CoordRec((float) 11.0019, (float) 76.1905),
@@ -1150,8 +1150,8 @@ static final CoordRec char79_stroke0[] = {
new CoordRec((float) 11.0019, (float) 23.8095),
new CoordRec((float) 15.7638, (float) 14.2857),
new CoordRec((float) 25.2876, (float) 4.7619),
- new CoordRec((float) 34.8114, (float) 0),
- new CoordRec((float) 53.859, (float) 0),
+ new CoordRec((float) 34.8114, 0),
+ new CoordRec((float) 53.859, 0),
new CoordRec((float) 63.3829, (float) 4.7619),
new CoordRec((float) 72.9067, (float) 14.2857),
new CoordRec((float) 77.6686, (float) 23.8095),
@@ -1160,8 +1160,8 @@ static final CoordRec char79_stroke0[] = {
new CoordRec((float) 77.6686, (float) 76.1905),
new CoordRec((float) 72.9067, (float) 85.7143),
new CoordRec((float) 63.3829, (float) 95.2381),
- new CoordRec((float) 53.859, (float) 100),
- new CoordRec((float) 34.8114, (float) 100),
+ new CoordRec((float) 53.859, 100),
+ new CoordRec((float) 34.8114, 100),
};
static final StrokeRec char79[] = {
@@ -1171,13 +1171,13 @@ static final StrokeRec char79[] = {
/* char: 80 'P' */
static final CoordRec char80_stroke0[] = {
- new CoordRec((float) 12.1, (float) 100),
- new CoordRec((float) 12.1, (float) 0),
+ new CoordRec((float) 12.1, 100),
+ new CoordRec((float) 12.1, 0),
};
static final CoordRec char80_stroke1[] = {
- new CoordRec((float) 12.1, (float) 100),
- new CoordRec((float) 54.9571, (float) 100),
+ new CoordRec((float) 12.1, 100),
+ new CoordRec((float) 54.9571, 100),
new CoordRec((float) 69.2429, (float) 95.2381),
new CoordRec((float) 74.0048, (float) 90.4762),
new CoordRec((float) 78.7667, (float) 80.9524),
@@ -1196,7 +1196,7 @@ static final StrokeRec char80[] = {
/* char: 81 'Q' */
static final CoordRec char81_stroke0[] = {
- new CoordRec((float) 33.8714, (float) 100),
+ new CoordRec((float) 33.8714, 100),
new CoordRec((float) 24.3476, (float) 95.2381),
new CoordRec((float) 14.8238, (float) 85.7143),
new CoordRec((float) 10.0619, (float) 76.1905),
@@ -1205,8 +1205,8 @@ static final CoordRec char81_stroke0[] = {
new CoordRec((float) 10.0619, (float) 23.8095),
new CoordRec((float) 14.8238, (float) 14.2857),
new CoordRec((float) 24.3476, (float) 4.7619),
- new CoordRec((float) 33.8714, (float) 0),
- new CoordRec((float) 52.919, (float) 0),
+ new CoordRec((float) 33.8714, 0),
+ new CoordRec((float) 52.919, 0),
new CoordRec((float) 62.4429, (float) 4.7619),
new CoordRec((float) 71.9667, (float) 14.2857),
new CoordRec((float) 76.7286, (float) 23.8095),
@@ -1215,8 +1215,8 @@ static final CoordRec char81_stroke0[] = {
new CoordRec((float) 76.7286, (float) 76.1905),
new CoordRec((float) 71.9667, (float) 85.7143),
new CoordRec((float) 62.4429, (float) 95.2381),
- new CoordRec((float) 52.919, (float) 100),
- new CoordRec((float) 33.8714, (float) 100),
+ new CoordRec((float) 52.919, 100),
+ new CoordRec((float) 33.8714, 100),
};
static final CoordRec char81_stroke1[] = {
@@ -1232,13 +1232,13 @@ static final StrokeRec char81[] = {
/* char: 82 'R' */
static final CoordRec char82_stroke0[] = {
- new CoordRec((float) 11.68, (float) 100),
- new CoordRec((float) 11.68, (float) 0),
+ new CoordRec((float) 11.68, 100),
+ new CoordRec((float) 11.68, 0),
};
static final CoordRec char82_stroke1[] = {
- new CoordRec((float) 11.68, (float) 100),
- new CoordRec((float) 54.5371, (float) 100),
+ new CoordRec((float) 11.68, 100),
+ new CoordRec((float) 54.5371, 100),
new CoordRec((float) 68.8229, (float) 95.2381),
new CoordRec((float) 73.5848, (float) 90.4762),
new CoordRec((float) 78.3467, (float) 80.9524),
@@ -1251,7 +1251,7 @@ static final CoordRec char82_stroke1[] = {
static final CoordRec char82_stroke2[] = {
new CoordRec((float) 45.0133, (float) 52.381),
- new CoordRec((float) 78.3467, (float) 0),
+ new CoordRec((float) 78.3467, 0),
};
static final StrokeRec char82[] = {
@@ -1265,11 +1265,11 @@ static final StrokeRec char82[] = {
static final CoordRec char83_stroke0[] = {
new CoordRec((float) 74.6667, (float) 85.7143),
new CoordRec((float) 65.1429, (float) 95.2381),
- new CoordRec((float) 50.8571, (float) 100),
- new CoordRec((float) 31.8095, (float) 100),
+ new CoordRec((float) 50.8571, 100),
+ new CoordRec((float) 31.8095, 100),
new CoordRec((float) 17.5238, (float) 95.2381),
- new CoordRec((float) 8, (float) 85.7143),
- new CoordRec((float) 8, (float) 76.1905),
+ new CoordRec(8, (float) 85.7143),
+ new CoordRec(8, (float) 76.1905),
new CoordRec((float) 12.7619, (float) 66.6667),
new CoordRec((float) 17.5238, (float) 61.9048),
new CoordRec((float) 27.0476, (float) 57.1429),
@@ -1279,10 +1279,10 @@ static final CoordRec char83_stroke0[] = {
new CoordRec((float) 74.6667, (float) 28.5714),
new CoordRec((float) 74.6667, (float) 14.2857),
new CoordRec((float) 65.1429, (float) 4.7619),
- new CoordRec((float) 50.8571, (float) 0),
- new CoordRec((float) 31.8095, (float) 0),
+ new CoordRec((float) 50.8571, 0),
+ new CoordRec((float) 31.8095, 0),
new CoordRec((float) 17.5238, (float) 4.7619),
- new CoordRec((float) 8, (float) 14.2857),
+ new CoordRec(8, (float) 14.2857),
};
static final StrokeRec char83[] = {
@@ -1292,13 +1292,13 @@ static final StrokeRec char83[] = {
/* char: 84 'T' */
static final CoordRec char84_stroke0[] = {
- new CoordRec((float) 35.6933, (float) 100),
- new CoordRec((float) 35.6933, (float) 0),
+ new CoordRec((float) 35.6933, 100),
+ new CoordRec((float) 35.6933, 0),
};
static final CoordRec char84_stroke1[] = {
- new CoordRec((float) 2.36, (float) 100),
- new CoordRec((float) 69.0267, (float) 100),
+ new CoordRec((float) 2.36, 100),
+ new CoordRec((float) 69.0267, 100),
};
static final StrokeRec char84[] = {
@@ -1309,16 +1309,16 @@ static final StrokeRec char84[] = {
/* char: 85 'U' */
static final CoordRec char85_stroke0[] = {
- new CoordRec((float) 11.54, (float) 100),
+ new CoordRec((float) 11.54, 100),
new CoordRec((float) 11.54, (float) 28.5714),
new CoordRec((float) 16.3019, (float) 14.2857),
new CoordRec((float) 25.8257, (float) 4.7619),
- new CoordRec((float) 40.1114, (float) 0),
- new CoordRec((float) 49.6352, (float) 0),
+ new CoordRec((float) 40.1114, 0),
+ new CoordRec((float) 49.6352, 0),
new CoordRec((float) 63.921, (float) 4.7619),
new CoordRec((float) 73.4448, (float) 14.2857),
new CoordRec((float) 78.2067, (float) 28.5714),
- new CoordRec((float) 78.2067, (float) 100),
+ new CoordRec((float) 78.2067, 100),
};
static final StrokeRec char85[] = {
@@ -1328,13 +1328,13 @@ static final StrokeRec char85[] = {
/* char: 86 'V' */
static final CoordRec char86_stroke0[] = {
- new CoordRec((float) 2.36, (float) 100),
- new CoordRec((float) 40.4552, (float) 0),
+ new CoordRec((float) 2.36, 100),
+ new CoordRec((float) 40.4552, 0),
};
static final CoordRec char86_stroke1[] = {
- new CoordRec((float) 78.5505, (float) 100),
- new CoordRec((float) 40.4552, (float) 0),
+ new CoordRec((float) 78.5505, 100),
+ new CoordRec((float) 40.4552, 0),
};
static final StrokeRec char86[] = {
@@ -1345,23 +1345,23 @@ static final StrokeRec char86[] = {
/* char: 87 'W' */
static final CoordRec char87_stroke0[] = {
- new CoordRec((float) 2.22, (float) 100),
- new CoordRec((float) 26.0295, (float) 0),
+ new CoordRec((float) 2.22, 100),
+ new CoordRec((float) 26.0295, 0),
};
static final CoordRec char87_stroke1[] = {
- new CoordRec((float) 49.839, (float) 100),
- new CoordRec((float) 26.0295, (float) 0),
+ new CoordRec((float) 49.839, 100),
+ new CoordRec((float) 26.0295, 0),
};
static final CoordRec char87_stroke2[] = {
- new CoordRec((float) 49.839, (float) 100),
- new CoordRec((float) 73.6486, (float) 0),
+ new CoordRec((float) 49.839, 100),
+ new CoordRec((float) 73.6486, 0),
};
static final CoordRec char87_stroke3[] = {
- new CoordRec((float) 97.4581, (float) 100),
- new CoordRec((float) 73.6486, (float) 0),
+ new CoordRec((float) 97.4581, 100),
+ new CoordRec((float) 73.6486, 0),
};
static final StrokeRec char87[] = {
@@ -1374,13 +1374,13 @@ static final StrokeRec char87[] = {
/* char: 88 'X' */
static final CoordRec char88_stroke0[] = {
- new CoordRec((float) 2.5, (float) 100),
- new CoordRec((float) 69.1667, (float) 0),
+ new CoordRec((float) 2.5, 100),
+ new CoordRec((float) 69.1667, 0),
};
static final CoordRec char88_stroke1[] = {
- new CoordRec((float) 69.1667, (float) 100),
- new CoordRec((float) 2.5, (float) 0),
+ new CoordRec((float) 69.1667, 100),
+ new CoordRec((float) 2.5, 0),
};
static final StrokeRec char88[] = {
@@ -1391,13 +1391,13 @@ static final StrokeRec char88[] = {
/* char: 89 'Y' */
static final CoordRec char89_stroke0[] = {
- new CoordRec((float) 1.52, (float) 100),
+ new CoordRec((float) 1.52, 100),
new CoordRec((float) 39.6152, (float) 52.381),
- new CoordRec((float) 39.6152, (float) 0),
+ new CoordRec((float) 39.6152, 0),
};
static final CoordRec char89_stroke1[] = {
- new CoordRec((float) 77.7105, (float) 100),
+ new CoordRec((float) 77.7105, 100),
new CoordRec((float) 39.6152, (float) 52.381),
};
@@ -1409,18 +1409,18 @@ static final StrokeRec char89[] = {
/* char: 90 'Z' */
static final CoordRec char90_stroke0[] = {
- new CoordRec((float) 69.1667, (float) 100),
- new CoordRec((float) 2.5, (float) 0),
+ new CoordRec((float) 69.1667, 100),
+ new CoordRec((float) 2.5, 0),
};
static final CoordRec char90_stroke1[] = {
- new CoordRec((float) 2.5, (float) 100),
- new CoordRec((float) 69.1667, (float) 100),
+ new CoordRec((float) 2.5, 100),
+ new CoordRec((float) 69.1667, 100),
};
static final CoordRec char90_stroke2[] = {
- new CoordRec((float) 2.5, (float) 0),
- new CoordRec((float) 69.1667, (float) 0),
+ new CoordRec((float) 2.5, 0),
+ new CoordRec((float) 69.1667, 0),
};
static final StrokeRec char90[] = {
@@ -1461,7 +1461,7 @@ static final StrokeRec char91[] = {
/* char: 92 '\' */
static final CoordRec char92_stroke0[] = {
- new CoordRec((float) 5.84, (float) 100),
+ new CoordRec((float) 5.84, 100),
new CoordRec((float) 72.5067, (float) -14.2857),
};
@@ -1532,12 +1532,12 @@ static final StrokeRec char95[] = {
/* char: 96 '`' */
static final CoordRec char96_stroke0[] = {
- new CoordRec((float) 33.0219, (float) 100),
+ new CoordRec((float) 33.0219, 100),
new CoordRec((float) 56.8314, (float) 71.4286),
};
static final CoordRec char96_stroke1[] = {
- new CoordRec((float) 33.0219, (float) 100),
+ new CoordRec((float) 33.0219, 100),
new CoordRec((float) 28.26, (float) 95.2381),
new CoordRec((float) 56.8314, (float) 71.4286),
};
@@ -1551,7 +1551,7 @@ static final StrokeRec char96[] = {
static final CoordRec char97_stroke0[] = {
new CoordRec((float) 63.8229, (float) 66.6667),
- new CoordRec((float) 63.8229, (float) 0),
+ new CoordRec((float) 63.8229, 0),
};
static final CoordRec char97_stroke1[] = {
@@ -1565,8 +1565,8 @@ static final CoordRec char97_stroke1[] = {
new CoordRec((float) 6.68, (float) 28.5714),
new CoordRec((float) 11.4419, (float) 14.2857),
new CoordRec((float) 20.9657, (float) 4.7619),
- new CoordRec((float) 30.4895, (float) 0),
- new CoordRec((float) 44.7752, (float) 0),
+ new CoordRec((float) 30.4895, 0),
+ new CoordRec((float) 44.7752, 0),
new CoordRec((float) 54.299, (float) 4.7619),
new CoordRec((float) 63.8229, (float) 14.2857),
};
@@ -1579,8 +1579,8 @@ static final StrokeRec char97[] = {
/* char: 98 'b' */
static final CoordRec char98_stroke0[] = {
- new CoordRec((float) 8.76, (float) 100),
- new CoordRec((float) 8.76, (float) 0),
+ new CoordRec((float) 8.76, 100),
+ new CoordRec((float) 8.76, 0),
};
static final CoordRec char98_stroke1[] = {
@@ -1594,8 +1594,8 @@ static final CoordRec char98_stroke1[] = {
new CoordRec((float) 65.9029, (float) 28.5714),
new CoordRec((float) 61.141, (float) 14.2857),
new CoordRec((float) 51.6171, (float) 4.7619),
- new CoordRec((float) 42.0933, (float) 0),
- new CoordRec((float) 27.8076, (float) 0),
+ new CoordRec((float) 42.0933, 0),
+ new CoordRec((float) 27.8076, 0),
new CoordRec((float) 18.2838, (float) 4.7619),
new CoordRec((float) 8.76, (float) 14.2857),
};
@@ -1618,8 +1618,8 @@ static final CoordRec char99_stroke0[] = {
new CoordRec((float) 5.52, (float) 28.5714),
new CoordRec((float) 10.2819, (float) 14.2857),
new CoordRec((float) 19.8057, (float) 4.7619),
- new CoordRec((float) 29.3295, (float) 0),
- new CoordRec((float) 43.6152, (float) 0),
+ new CoordRec((float) 29.3295, 0),
+ new CoordRec((float) 43.6152, 0),
new CoordRec((float) 53.139, (float) 4.7619),
new CoordRec((float) 62.6629, (float) 14.2857),
};
@@ -1631,8 +1631,8 @@ static final StrokeRec char99[] = {
/* char: 100 'd' */
static final CoordRec char100_stroke0[] = {
- new CoordRec((float) 61.7829, (float) 100),
- new CoordRec((float) 61.7829, (float) 0),
+ new CoordRec((float) 61.7829, 100),
+ new CoordRec((float) 61.7829, 0),
};
static final CoordRec char100_stroke1[] = {
@@ -1646,8 +1646,8 @@ static final CoordRec char100_stroke1[] = {
new CoordRec((float) 4.64, (float) 28.5714),
new CoordRec((float) 9.4019, (float) 14.2857),
new CoordRec((float) 18.9257, (float) 4.7619),
- new CoordRec((float) 28.4495, (float) 0),
- new CoordRec((float) 42.7352, (float) 0),
+ new CoordRec((float) 28.4495, 0),
+ new CoordRec((float) 42.7352, 0),
new CoordRec((float) 52.259, (float) 4.7619),
new CoordRec((float) 61.7829, (float) 14.2857),
};
@@ -1673,8 +1673,8 @@ static final CoordRec char101_stroke0[] = {
new CoordRec((float) 5.72, (float) 28.5714),
new CoordRec((float) 10.4819, (float) 14.2857),
new CoordRec((float) 20.0057, (float) 4.7619),
- new CoordRec((float) 29.5295, (float) 0),
- new CoordRec((float) 43.8152, (float) 0),
+ new CoordRec((float) 29.5295, 0),
+ new CoordRec((float) 43.8152, 0),
new CoordRec((float) 53.339, (float) 4.7619),
new CoordRec((float) 62.8629, (float) 14.2857),
};
@@ -1686,11 +1686,11 @@ static final StrokeRec char101[] = {
/* char: 102 'f' */
static final CoordRec char102_stroke0[] = {
- new CoordRec((float) 38.7752, (float) 100),
- new CoordRec((float) 29.2514, (float) 100),
+ new CoordRec((float) 38.7752, 100),
+ new CoordRec((float) 29.2514, 100),
new CoordRec((float) 19.7276, (float) 95.2381),
new CoordRec((float) 14.9657, (float) 80.9524),
- new CoordRec((float) 14.9657, (float) 0),
+ new CoordRec((float) 14.9657, 0),
};
static final CoordRec char102_stroke1[] = {
@@ -1726,8 +1726,8 @@ static final CoordRec char103_stroke1[] = {
new CoordRec((float) 5.36, (float) 28.5714),
new CoordRec((float) 10.1219, (float) 14.2857),
new CoordRec((float) 19.6457, (float) 4.7619),
- new CoordRec((float) 29.1695, (float) 0),
- new CoordRec((float) 43.4552, (float) 0),
+ new CoordRec((float) 29.1695, 0),
+ new CoordRec((float) 43.4552, 0),
new CoordRec((float) 52.979, (float) 4.7619),
new CoordRec((float) 62.5029, (float) 14.2857),
};
@@ -1740,8 +1740,8 @@ static final StrokeRec char103[] = {
/* char: 104 'h' */
static final CoordRec char104_stroke0[] = {
- new CoordRec((float) 9.6, (float) 100),
- new CoordRec((float) 9.6, (float) 0),
+ new CoordRec((float) 9.6, 100),
+ new CoordRec((float) 9.6, 0),
};
static final CoordRec char104_stroke1[] = {
@@ -1751,7 +1751,7 @@ static final CoordRec char104_stroke1[] = {
new CoordRec((float) 47.6952, (float) 66.6667),
new CoordRec((float) 57.219, (float) 61.9048),
new CoordRec((float) 61.981, (float) 47.619),
- new CoordRec((float) 61.981, (float) 0),
+ new CoordRec((float) 61.981, 0),
};
static final StrokeRec char104[] = {
@@ -1762,16 +1762,16 @@ static final StrokeRec char104[] = {
/* char: 105 'i' */
static final CoordRec char105_stroke0[] = {
- new CoordRec((float) 10.02, (float) 100),
+ new CoordRec((float) 10.02, 100),
new CoordRec((float) 14.7819, (float) 95.2381),
- new CoordRec((float) 19.5438, (float) 100),
+ new CoordRec((float) 19.5438, 100),
new CoordRec((float) 14.7819, (float) 104.762),
- new CoordRec((float) 10.02, (float) 100),
+ new CoordRec((float) 10.02, 100),
};
static final CoordRec char105_stroke1[] = {
new CoordRec((float) 14.7819, (float) 66.6667),
- new CoordRec((float) 14.7819, (float) 0),
+ new CoordRec((float) 14.7819, 0),
};
static final StrokeRec char105[] = {
@@ -1782,11 +1782,11 @@ static final StrokeRec char105[] = {
/* char: 106 'j' */
static final CoordRec char106_stroke0[] = {
- new CoordRec((float) 17.3876, (float) 100),
+ new CoordRec((float) 17.3876, 100),
new CoordRec((float) 22.1495, (float) 95.2381),
- new CoordRec((float) 26.9114, (float) 100),
+ new CoordRec((float) 26.9114, 100),
new CoordRec((float) 22.1495, (float) 104.762),
- new CoordRec((float) 17.3876, (float) 100),
+ new CoordRec((float) 17.3876, 100),
};
static final CoordRec char106_stroke1[] = {
@@ -1805,8 +1805,8 @@ static final StrokeRec char106[] = {
/* char: 107 'k' */
static final CoordRec char107_stroke0[] = {
- new CoordRec((float) 9.6, (float) 100),
- new CoordRec((float) 9.6, (float) 0),
+ new CoordRec((float) 9.6, 100),
+ new CoordRec((float) 9.6, 0),
};
static final CoordRec char107_stroke1[] = {
@@ -1816,7 +1816,7 @@ static final CoordRec char107_stroke1[] = {
static final CoordRec char107_stroke2[] = {
new CoordRec((float) 28.6476, (float) 38.0952),
- new CoordRec((float) 61.981, (float) 0),
+ new CoordRec((float) 61.981, 0),
};
static final StrokeRec char107[] = {
@@ -1828,8 +1828,8 @@ static final StrokeRec char107[] = {
/* char: 108 'l' */
static final CoordRec char108_stroke0[] = {
- new CoordRec((float) 10.02, (float) 100),
- new CoordRec((float) 10.02, (float) 0),
+ new CoordRec((float) 10.02, 100),
+ new CoordRec((float) 10.02, 0),
};
static final StrokeRec char108[] = {
@@ -1840,7 +1840,7 @@ static final StrokeRec char108[] = {
static final CoordRec char109_stroke0[] = {
new CoordRec((float) 9.6, (float) 66.6667),
- new CoordRec((float) 9.6, (float) 0),
+ new CoordRec((float) 9.6, 0),
};
static final CoordRec char109_stroke1[] = {
@@ -1850,7 +1850,7 @@ static final CoordRec char109_stroke1[] = {
new CoordRec((float) 47.6952, (float) 66.6667),
new CoordRec((float) 57.219, (float) 61.9048),
new CoordRec((float) 61.981, (float) 47.619),
- new CoordRec((float) 61.981, (float) 0),
+ new CoordRec((float) 61.981, 0),
};
static final CoordRec char109_stroke2[] = {
@@ -1860,7 +1860,7 @@ static final CoordRec char109_stroke2[] = {
new CoordRec((float) 100.076, (float) 66.6667),
new CoordRec((float) 109.6, (float) 61.9048),
new CoordRec((float) 114.362, (float) 47.619),
- new CoordRec((float) 114.362, (float) 0),
+ new CoordRec((float) 114.362, 0),
};
static final StrokeRec char109[] = {
@@ -1873,7 +1873,7 @@ static final StrokeRec char109[] = {
static final CoordRec char110_stroke0[] = {
new CoordRec((float) 9.18, (float) 66.6667),
- new CoordRec((float) 9.18, (float) 0),
+ new CoordRec((float) 9.18, 0),
};
static final CoordRec char110_stroke1[] = {
@@ -1883,7 +1883,7 @@ static final CoordRec char110_stroke1[] = {
new CoordRec((float) 47.2752, (float) 66.6667),
new CoordRec((float) 56.799, (float) 61.9048),
new CoordRec((float) 61.561, (float) 47.619),
- new CoordRec((float) 61.561, (float) 0),
+ new CoordRec((float) 61.561, 0),
};
static final StrokeRec char110[] = {
@@ -1901,8 +1901,8 @@ static final CoordRec char111_stroke0[] = {
new CoordRec((float) 4.98, (float) 28.5714),
new CoordRec((float) 9.7419, (float) 14.2857),
new CoordRec((float) 19.2657, (float) 4.7619),
- new CoordRec((float) 28.7895, (float) 0),
- new CoordRec((float) 43.0752, (float) 0),
+ new CoordRec((float) 28.7895, 0),
+ new CoordRec((float) 43.0752, 0),
new CoordRec((float) 52.599, (float) 4.7619),
new CoordRec((float) 62.1229, (float) 14.2857),
new CoordRec((float) 66.8848, (float) 28.5714),
@@ -1935,8 +1935,8 @@ static final CoordRec char112_stroke1[] = {
new CoordRec((float) 66.6029, (float) 28.5714),
new CoordRec((float) 61.841, (float) 14.2857),
new CoordRec((float) 52.3171, (float) 4.7619),
- new CoordRec((float) 42.7933, (float) 0),
- new CoordRec((float) 28.5076, (float) 0),
+ new CoordRec((float) 42.7933, 0),
+ new CoordRec((float) 28.5076, 0),
new CoordRec((float) 18.9838, (float) 4.7619),
new CoordRec((float) 9.46, (float) 14.2857),
};
@@ -1964,8 +1964,8 @@ static final CoordRec char113_stroke1[] = {
new CoordRec((float) 4.84, (float) 28.5714),
new CoordRec((float) 9.6019, (float) 14.2857),
new CoordRec((float) 19.1257, (float) 4.7619),
- new CoordRec((float) 28.6495, (float) 0),
- new CoordRec((float) 42.9352, (float) 0),
+ new CoordRec((float) 28.6495, 0),
+ new CoordRec((float) 42.9352, 0),
new CoordRec((float) 52.459, (float) 4.7619),
new CoordRec((float) 61.9829, (float) 14.2857),
};
@@ -1979,7 +1979,7 @@ static final StrokeRec char113[] = {
static final CoordRec char114_stroke0[] = {
new CoordRec((float) 9.46, (float) 66.6667),
- new CoordRec((float) 9.46, (float) 0),
+ new CoordRec((float) 9.46, 0),
};
static final CoordRec char114_stroke1[] = {
@@ -2011,8 +2011,8 @@ static final CoordRec char115_stroke0[] = {
new CoordRec((float) 57.081, (float) 19.0476),
new CoordRec((float) 57.081, (float) 14.2857),
new CoordRec((float) 52.319, (float) 4.7619),
- new CoordRec((float) 38.0333, (float) 0),
- new CoordRec((float) 23.7476, (float) 0),
+ new CoordRec((float) 38.0333, 0),
+ new CoordRec((float) 23.7476, 0),
new CoordRec((float) 9.4619, (float) 4.7619),
new CoordRec((float) 4.7, (float) 14.2857),
};
@@ -2024,11 +2024,11 @@ static final StrokeRec char115[] = {
/* char: 116 't' */
static final CoordRec char116_stroke0[] = {
- new CoordRec((float) 14.8257, (float) 100),
+ new CoordRec((float) 14.8257, 100),
new CoordRec((float) 14.8257, (float) 19.0476),
new CoordRec((float) 19.5876, (float) 4.7619),
- new CoordRec((float) 29.1114, (float) 0),
- new CoordRec((float) 38.6352, (float) 0),
+ new CoordRec((float) 29.1114, 0),
+ new CoordRec((float) 38.6352, 0),
};
static final CoordRec char116_stroke1[] = {
@@ -2047,15 +2047,15 @@ static final CoordRec char117_stroke0[] = {
new CoordRec((float) 9.46, (float) 66.6667),
new CoordRec((float) 9.46, (float) 19.0476),
new CoordRec((float) 14.2219, (float) 4.7619),
- new CoordRec((float) 23.7457, (float) 0),
- new CoordRec((float) 38.0314, (float) 0),
+ new CoordRec((float) 23.7457, 0),
+ new CoordRec((float) 38.0314, 0),
new CoordRec((float) 47.5552, (float) 4.7619),
new CoordRec((float) 61.841, (float) 19.0476),
};
static final CoordRec char117_stroke1[] = {
new CoordRec((float) 61.841, (float) 66.6667),
- new CoordRec((float) 61.841, (float) 0),
+ new CoordRec((float) 61.841, 0),
};
static final StrokeRec char117[] = {
@@ -2067,12 +2067,12 @@ static final StrokeRec char117[] = {
static final CoordRec char118_stroke0[] = {
new CoordRec((float) 1.8, (float) 66.6667),
- new CoordRec((float) 30.3714, (float) 0),
+ new CoordRec((float) 30.3714, 0),
};
static final CoordRec char118_stroke1[] = {
new CoordRec((float) 58.9429, (float) 66.6667),
- new CoordRec((float) 30.3714, (float) 0),
+ new CoordRec((float) 30.3714, 0),
};
static final StrokeRec char118[] = {
@@ -2084,22 +2084,22 @@ static final StrokeRec char118[] = {
static final CoordRec char119_stroke0[] = {
new CoordRec((float) 2.5, (float) 66.6667),
- new CoordRec((float) 21.5476, (float) 0),
+ new CoordRec((float) 21.5476, 0),
};
static final CoordRec char119_stroke1[] = {
new CoordRec((float) 40.5952, (float) 66.6667),
- new CoordRec((float) 21.5476, (float) 0),
+ new CoordRec((float) 21.5476, 0),
};
static final CoordRec char119_stroke2[] = {
new CoordRec((float) 40.5952, (float) 66.6667),
- new CoordRec((float) 59.6429, (float) 0),
+ new CoordRec((float) 59.6429, 0),
};
static final CoordRec char119_stroke3[] = {
new CoordRec((float) 78.6905, (float) 66.6667),
- new CoordRec((float) 59.6429, (float) 0),
+ new CoordRec((float) 59.6429, 0),
};
static final StrokeRec char119[] = {
@@ -2113,12 +2113,12 @@ static final StrokeRec char119[] = {
static final CoordRec char120_stroke0[] = {
new CoordRec((float) 1.66, (float) 66.6667),
- new CoordRec((float) 54.041, (float) 0),
+ new CoordRec((float) 54.041, 0),
};
static final CoordRec char120_stroke1[] = {
new CoordRec((float) 54.041, (float) 66.6667),
- new CoordRec((float) 1.66, (float) 0),
+ new CoordRec((float) 1.66, 0),
};
static final StrokeRec char120[] = {
@@ -2130,12 +2130,12 @@ static final StrokeRec char120[] = {
static final CoordRec char121_stroke0[] = {
new CoordRec((float) 6.5619, (float) 66.6667),
- new CoordRec((float) 35.1333, (float) 0),
+ new CoordRec((float) 35.1333, 0),
};
static final CoordRec char121_stroke1[] = {
new CoordRec((float) 63.7048, (float) 66.6667),
- new CoordRec((float) 35.1333, (float) 0),
+ new CoordRec((float) 35.1333, 0),
new CoordRec((float) 25.6095, (float) -19.0476),
new CoordRec((float) 16.0857, (float) -28.5714),
new CoordRec((float) 6.5619, (float) -33.3333),
@@ -2151,7 +2151,7 @@ static final StrokeRec char121[] = {
static final CoordRec char122_stroke0[] = {
new CoordRec((float) 56.821, (float) 66.6667),
- new CoordRec((float) 4.44, (float) 0),
+ new CoordRec((float) 4.44, 0),
};
static final CoordRec char122_stroke1[] = {
@@ -2160,8 +2160,8 @@ static final CoordRec char122_stroke1[] = {
};
static final CoordRec char122_stroke2[] = {
- new CoordRec((float) 4.44, (float) 0),
- new CoordRec((float) 56.821, (float) 0),
+ new CoordRec((float) 4.44, 0),
+ new CoordRec((float) 56.821, 0),
};
static final StrokeRec char122[] = {
@@ -2176,7 +2176,7 @@ static final CoordRec char123_stroke0[] = {
new CoordRec((float) 31.1895, (float) 119.048),
new CoordRec((float) 21.6657, (float) 114.286),
new CoordRec((float) 16.9038, (float) 109.524),
- new CoordRec((float) 12.1419, (float) 100),
+ new CoordRec((float) 12.1419, 100),
new CoordRec((float) 12.1419, (float) 90.4762),
new CoordRec((float) 16.9038, (float) 80.9524),
new CoordRec((float) 21.6657, (float) 76.1905),
@@ -2199,7 +2199,7 @@ static final CoordRec char123_stroke1[] = {
new CoordRec((float) 31.1895, (float) 23.8095),
new CoordRec((float) 31.1895, (float) 14.2857),
new CoordRec((float) 26.4276, (float) 4.7619),
- new CoordRec((float) 21.6657, (float) 0),
+ new CoordRec((float) 21.6657, 0),
new CoordRec((float) 16.9038, (float) -9.5238),
new CoordRec((float) 16.9038, (float) -19.0476),
new CoordRec((float) 21.6657, (float) -28.5714),
@@ -2241,7 +2241,7 @@ static final CoordRec char125_stroke0[] = {
new CoordRec((float) 9.18, (float) 119.048),
new CoordRec((float) 18.7038, (float) 114.286),
new CoordRec((float) 23.4657, (float) 109.524),
- new CoordRec((float) 28.2276, (float) 100),
+ new CoordRec((float) 28.2276, 100),
new CoordRec((float) 28.2276, (float) 90.4762),
new CoordRec((float) 23.4657, (float) 80.9524),
new CoordRec((float) 18.7038, (float) 76.1905),
@@ -2264,7 +2264,7 @@ static final CoordRec char125_stroke1[] = {
new CoordRec((float) 9.18, (float) 23.8095),
new CoordRec((float) 9.18, (float) 14.2857),
new CoordRec((float) 13.9419, (float) 4.7619),
- new CoordRec((float) 18.7038, (float) 0),
+ new CoordRec((float) 18.7038, 0),
new CoordRec((float) 23.4657, (float) -9.5238),
new CoordRec((float) 23.4657, (float) -19.0476),
new CoordRec((float) 18.7038, (float) -28.5714),
@@ -2327,7 +2327,7 @@ static final StrokeRec char126[] = {
/* char: 127 */
static final CoordRec char127_stroke0[] = {
- new CoordRec((float) 52.381, (float) 100),
+ new CoordRec((float) 52.381, 100),
new CoordRec((float) 14.2857, (float) -33.3333),
};
@@ -2335,12 +2335,12 @@ static final CoordRec char127_stroke1[] = {
new CoordRec((float) 28.5714, (float) 66.6667),
new CoordRec((float) 14.2857, (float) 61.9048),
new CoordRec((float) 4.7619, (float) 52.381),
- new CoordRec((float) 0, (float) 38.0952),
- new CoordRec((float) 0, (float) 23.8095),
+ new CoordRec(0, (float) 38.0952),
+ new CoordRec(0, (float) 23.8095),
new CoordRec((float) 4.7619, (float) 14.2857),
new CoordRec((float) 14.2857, (float) 4.7619),
- new CoordRec((float) 28.5714, (float) 0),
- new CoordRec((float) 38.0952, (float) 0),
+ new CoordRec((float) 28.5714, 0),
+ new CoordRec((float) 38.0952, 0),
new CoordRec((float) 52.381, (float) 4.7619),
new CoordRec((float) 61.9048, (float) 14.2857),
new CoordRec((float) 66.6667, (float) 28.5714),
@@ -2357,38 +2357,38 @@ static final StrokeRec char127[] = {
};
static final StrokeCharRec chars[] = {
- new StrokeCharRec( 0, /* char0 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char1 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char2 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char3 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char4 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char5 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char6 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char7 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char8 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char9 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char10 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char11 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char12 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char13 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char14 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char15 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char16 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char17 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char18 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char19 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char20 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char21 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char22 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char23 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char24 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char25 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char26 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char27 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char28 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char29 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char30 */ null, (float) 0, (float) 0 ),
- new StrokeCharRec( 0, /* char31 */ null, (float) 0, (float) 0 ),
+ new StrokeCharRec( 0, /* char0 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char1 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char2 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char3 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char4 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char5 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char6 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char7 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char8 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char9 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char10 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char11 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char12 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char13 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char14 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char15 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char16 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char17 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char18 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char19 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char20 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char21 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char22 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char23 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char24 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char25 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char26 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char27 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char28 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char29 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char30 */ null, 0, 0 ),
+ new StrokeCharRec( 0, /* char31 */ null, 0, 0 ),
new StrokeCharRec( 0, /* char32 */ null, (float) 52.381, (float) 104.762 ),
new StrokeCharRec( 2, char33, (float) 13.3819, (float) 26.6238 ),
new StrokeCharRec( 2, char34, (float) 23.0676, (float) 51.4352 ),
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeCharRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeCharRec.java
index af3d538ae..59935e358 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeCharRec.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeCharRec.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,8 +41,8 @@ package com.jogamp.opengl.util.gl2;
/* Copyright (c) Mark J. Kilgard, 1994, 1998. */
-/* This program is freely distributable without licensing fees
- and is provided without guarantee or warrantee expressed or
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
class StrokeCharRec {
@@ -51,10 +51,10 @@ class StrokeCharRec {
public float center;
public float right;
- public StrokeCharRec(int num_strokes,
- StrokeRec[] stroke,
- float center,
- float right) {
+ public StrokeCharRec(final int num_strokes,
+ final StrokeRec[] stroke,
+ final float center,
+ final float right) {
this.num_strokes = num_strokes;
this.stroke = stroke;
this.center = center;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeFontRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeFontRec.java
index d3195f24d..5810ac38a 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeFontRec.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeFontRec.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,8 +41,8 @@ package com.jogamp.opengl.util.gl2;
/* Copyright (c) Mark J. Kilgard, 1994, 1998. */
-/* This program is freely distributable without licensing fees
- and is provided without guarantee or warrantee expressed or
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
class StrokeFontRec {
@@ -52,11 +52,11 @@ class StrokeFontRec {
public float top;
public float bottom;
- public StrokeFontRec(String name,
- int num_chars,
- StrokeCharRec[] ch,
- float top,
- float bottom) {
+ public StrokeFontRec(final String name,
+ final int num_chars,
+ final StrokeCharRec[] ch,
+ final float top,
+ final float bottom) {
this.name = name;
this.num_chars = num_chars;
this.ch = ch;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeRec.java
index 8796e8b08..fcb7c912a 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeRec.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeRec.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,16 +41,16 @@ package com.jogamp.opengl.util.gl2;
/* Copyright (c) Mark J. Kilgard, 1994, 1998. */
-/* This program is freely distributable without licensing fees
- and is provided without guarantee or warrantee expressed or
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
class StrokeRec {
public int num_coords;
public CoordRec[] coord;
-
- public StrokeRec(int num_coords,
- CoordRec[] coord) {
+
+ public StrokeRec(final int num_coords,
+ final CoordRec[] coord) {
this.num_coords = num_coords;
this.coord = coord;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/TileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/TileRenderer.java
deleted file mode 100644
index 714c134d4..000000000
--- a/src/jogl/classes/com/jogamp/opengl/util/gl2/TileRenderer.java
+++ /dev/null
@@ -1,601 +0,0 @@
-package com.jogamp.opengl.util.gl2;
-
-import java.awt.Dimension;
-import java.nio.Buffer;
-
-import javax.media.opengl.*;
-import javax.media.opengl.glu.*;
-import javax.media.opengl.glu.gl2.*;
-
-/**
- * A fairly direct port of Brian Paul's tile rendering library, found
- * at <a href = "http://www.mesa3d.org/brianp/TR.html">
- * http://www.mesa3d.org/brianp/TR.html </a> . I've java-fied it, but
- * the functionality is the same.
- *
- * Original code Copyright (C) 1997-2005 Brian Paul. Licensed under
- * BSD-compatible terms with permission of the author. See LICENSE.txt
- * for license information.
- *
- * @author ryanm
- */
-public class TileRenderer
-{
- private static final int DEFAULT_TILE_WIDTH = 256;
-
- private static final int DEFAULT_TILE_HEIGHT = 256;
-
- private static final int DEFAULT_TILE_BORDER = 0;
-
- //
- // Enumeration flags for accessing variables
- //
- // @author ryanm
- //
-
- /**
- * The width of a tile
- */
- public static final int TR_TILE_WIDTH = 0;
- /**
- * The height of a tile
- */
- public static final int TR_TILE_HEIGHT = 1;
- /**
- * The width of the border around the tiles
- */
- public static final int TR_TILE_BORDER = 2;
- /**
- * The width of the final image
- */
- public static final int TR_IMAGE_WIDTH = 3;
- /**
- * The height of the final image
- */
- public static final int TR_IMAGE_HEIGHT = 4;
- /**
- * The number of rows of tiles
- */
- public static final int TR_ROWS = 5;
- /**
- * The number of columns of tiles
- */
- public static final int TR_COLUMNS = 6;
- /**
- * The current row number
- */
- public static final int TR_CURRENT_ROW = 7;
- /**
- * The current column number
- */
- public static final int TR_CURRENT_COLUMN = 8;
- /**
- * The width of the current tile
- */
- public static final int TR_CURRENT_TILE_WIDTH = 9;
- /**
- * The height of the current tile
- */
- public static final int TR_CURRENT_TILE_HEIGHT = 10;
- /**
- * The order that the rows are traversed
- */
- public static final int TR_ROW_ORDER = 11;
-
-
- /**
- * Indicates we are traversing rows from the top to the bottom
- */
- public static final int TR_TOP_TO_BOTTOM = 1;
-
- /**
- * Indicates we are traversing rows from the bottom to the top
- */
- public static final int TR_BOTTOM_TO_TOP = 2;
-
- /* Final image parameters */
- private Dimension imageSize = new Dimension();
-
- private int imageFormat, imageType;
-
- private Buffer imageBuffer;
-
- /* Tile parameters */
- private Dimension tileSize = new Dimension();
-
- private Dimension tileSizeNB = new Dimension();
-
- private int tileBorder;
-
- private int tileFormat, tileType;
-
- private Buffer tileBuffer;
-
- /* Projection parameters */
- private boolean perspective;
-
- private double left;
-
- private double right;
-
- private double bottom;
-
- private double top;
-
- private double near;
-
- private double far;
-
- /* Misc */
- private int rowOrder;
-
- private int rows, columns;
-
- private int currentTile;
-
- private int currentTileWidth, currentTileHeight;
-
- private int currentRow, currentColumn;
-
- private int[] viewportSave = new int[ 4 ];
-
- /**
- * Creates a new TileRenderer object
- */
- public TileRenderer()
- {
- tileSize.width = DEFAULT_TILE_WIDTH;
- tileSize.height = DEFAULT_TILE_HEIGHT;
- tileBorder = DEFAULT_TILE_BORDER;
- rowOrder = TR_BOTTOM_TO_TOP;
- currentTile = -1;
- }
-
- /**
- * Sets up the number of rows and columns needed
- */
- private void setup()
- {
- columns = ( imageSize.width + tileSizeNB.width - 1 ) / tileSizeNB.width;
- rows = ( imageSize.height + tileSizeNB.height - 1 ) / tileSizeNB.height;
- currentTile = 0;
-
- assert columns >= 0;
- assert rows >= 0;
- }
-
- /**
- * Sets the size of the tiles to use in rendering. The actual
- * effective size of the tile depends on the border size, ie (
- * width - 2*border ) * ( height - 2 * border )
- *
- * @param width
- * The width of the tiles. Must not be larger than the GL
- * context
- * @param height
- * The height of the tiles. Must not be larger than the
- * GL context
- * @param border
- * The width of the borders on each tile. This is needed
- * to avoid artifacts when rendering lines or points with
- * thickness > 1.
- */
- public void setTileSize( int width, int height, int border )
- {
- assert ( border >= 0 );
- assert ( width >= 1 );
- assert ( height >= 1 );
- assert ( width >= 2 * border );
- assert ( height >= 2 * border );
-
- tileBorder = border;
- tileSize.width = width;
- tileSize.height = height;
- tileSizeNB.width = width - 2 * border;
- tileSizeNB.height = height - 2 * border;
- setup();
- }
-
- /**
- * Specify a buffer the tiles to be copied to. This is not
- * necessary for the creation of the final image, but useful if you
- * want to inspect each tile in turn.
- *
- * @param format
- * Interpreted as in glReadPixels
- * @param type
- * Interpreted as in glReadPixels
- * @param image
- * The buffer itself. Must be large enough to contain a
- * tile, minus any borders
- */
- public void setTileBuffer( int format, int type, Buffer image )
- {
- tileFormat = format;
- tileType = type;
- tileBuffer = image;
- }
-
- /**
- * Sets the desired size of the final image
- *
- * @param width
- * The width of the final image
- * @param height
- * The height of the final image
- */
- public void setImageSize( int width, int height )
- {
- imageSize.width = width;
- imageSize.height = height;
- setup();
- }
-
- /**
- * Sets the buffer in which to store the final image
- *
- * @param format
- * Interpreted as in glReadPixels
- * @param type
- * Interpreted as in glReadPixels
- * @param image
- * the buffer itself, must be large enough to hold the
- * final image
- */
- public void setImageBuffer( int format, int type, Buffer image )
- {
- imageFormat = format;
- imageType = type;
- imageBuffer = image;
- }
-
- /**
- * Gets the parameters of this TileRenderer object
- *
- * @param param
- * The parameter that is to be retrieved
- * @return the value of the parameter
- */
- public int getParam( int param )
- {
- switch (param) {
- case TR_TILE_WIDTH:
- return tileSize.width;
- case TR_TILE_HEIGHT:
- return tileSize.height;
- case TR_TILE_BORDER:
- return tileBorder;
- case TR_IMAGE_WIDTH:
- return imageSize.width;
- case TR_IMAGE_HEIGHT:
- return imageSize.height;
- case TR_ROWS:
- return rows;
- case TR_COLUMNS:
- return columns;
- case TR_CURRENT_ROW:
- if( currentTile < 0 )
- return -1;
- else
- return currentRow;
- case TR_CURRENT_COLUMN:
- if( currentTile < 0 )
- return -1;
- else
- return currentColumn;
- case TR_CURRENT_TILE_WIDTH:
- return currentTileWidth;
- case TR_CURRENT_TILE_HEIGHT:
- return currentTileHeight;
- case TR_ROW_ORDER:
- return rowOrder;
- default:
- throw new IllegalArgumentException("Invalid enumerant as argument");
- }
- }
-
- /**
- * Sets the order of row traversal
- *
- * @param order
- * The row traversal order, must be
- * eitherTR_TOP_TO_BOTTOM or TR_BOTTOM_TO_TOP
- */
- public void setRowOrder( int order )
- {
- if (order == TR_TOP_TO_BOTTOM || order == TR_BOTTOM_TO_TOP) {
- rowOrder = order;
- } else {
- throw new IllegalArgumentException("Must pass TR_TOP_TO_BOTTOM or TR_BOTTOM_TO_TOP");
- }
- }
-
- /**
- * Sets the context to use an orthographic projection. Must be
- * called before rendering the first tile
- *
- * @param left
- * As in glOrtho
- * @param right
- * As in glOrtho
- * @param bottom
- * As in glOrtho
- * @param top
- * As in glOrtho
- * @param zNear
- * As in glOrtho
- * @param zFar
- * As in glOrtho
- */
- public void trOrtho( double left, double right, double bottom, double top, double zNear,
- double zFar )
- {
- this.perspective = false;
- this.left = left;
- this.right = right;
- this.bottom = bottom;
- this.top = top;
- this.near = zNear;
- this.far = zFar;
- }
-
- /**
- * Sets the perspective projection frustrum. Must be called before
- * rendering the first tile
- *
- * @param left
- * As in glFrustrum
- * @param right
- * As in glFrustrum
- * @param bottom
- * As in glFrustrum
- * @param top
- * As in glFrustrum
- * @param zNear
- * As in glFrustrum
- * @param zFar
- * As in glFrustrum
- */
- public void trFrustum( double left, double right, double bottom, double top, double zNear,
- double zFar )
- {
- this.perspective = true;
- this.left = left;
- this.right = right;
- this.bottom = bottom;
- this.top = top;
- this.near = zNear;
- this.far = zFar;
- }
-
- /**
- * Convenient way to specify a perspective projection
- *
- * @param fovy
- * As in gluPerspective
- * @param aspect
- * As in gluPerspective
- * @param zNear
- * As in gluPerspective
- * @param zFar
- * As in gluPerspective
- */
- public void trPerspective( double fovy, double aspect, double zNear, double zFar )
- {
- double xmin, xmax, ymin, ymax;
- ymax = zNear * Math.tan( fovy * 3.14159265 / 360.0 );
- ymin = -ymax;
- xmin = ymin * aspect;
- xmax = ymax * aspect;
- trFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
- }
-
- /**
- * Begins rendering a tile. The projection matrix stack should be
- * left alone after calling this
- *
- * @param gl
- * The gl context
- */
- public void beginTile( GL2 gl )
- {
- if (currentTile <= 0) {
- setup();
- /*
- * Save user's viewport, will be restored after last tile
- * rendered
- */
- gl.glGetIntegerv( GL2.GL_VIEWPORT, viewportSave, 0 );
- }
-
- /* which tile (by row and column) we're about to render */
- if (rowOrder == TR_BOTTOM_TO_TOP) {
- currentRow = currentTile / columns;
- currentColumn = currentTile % columns;
- } else {
- currentRow = rows - ( currentTile / columns ) - 1;
- currentColumn = currentTile % columns;
- }
- assert ( currentRow < rows );
- assert ( currentColumn < columns );
-
- int border = tileBorder;
-
- int th, tw;
-
- /* Compute actual size of this tile with border */
- if (currentRow < rows - 1) {
- th = tileSize.height;
- } else {
- th = imageSize.height - ( rows - 1 ) * ( tileSizeNB.height ) + 2 * border;
- }
-
- if (currentColumn < columns - 1) {
- tw = tileSize.width;
- } else {
- tw = imageSize.width - ( columns - 1 ) * ( tileSizeNB.width ) + 2 * border;
- }
-
- /* Save tile size, with border */
- currentTileWidth = tw;
- currentTileHeight = th;
-
- gl.glViewport( 0, 0, tw, th );
-
- /* save current matrix mode */
- int[] matrixMode = new int[ 1 ];
- gl.glGetIntegerv( GL2.GL_MATRIX_MODE, matrixMode, 0 );
- gl.glMatrixMode( GL2.GL_PROJECTION );
- gl.glLoadIdentity();
-
- /* compute projection parameters */
- double l =
- left + ( right - left ) * ( currentColumn * tileSizeNB.width - border )
- / imageSize.width;
- double r = l + ( right - left ) * tw / imageSize.width;
- double b =
- bottom + ( top - bottom ) * ( currentRow * tileSizeNB.height - border )
- / imageSize.height;
- double t = b + ( top - bottom ) * th / imageSize.height;
-
- if( perspective ) {
- gl.glFrustum( l, r, b, t, near, far );
- } else {
- gl.glOrtho( l, r, b, t, near, far );
- }
-
- /* restore user's matrix mode */
- gl.glMatrixMode( matrixMode[ 0 ] );
- }
-
- /**
- * Must be called after rendering the scene
- *
- * @param gl
- * the gl context
- * @return true if there are more tiles to be rendered, false if
- * the final image is complete
- */
- public boolean endTile( GL2 gl )
- {
- int[] prevRowLength = new int[ 1 ], prevSkipRows = new int[ 1 ], prevSkipPixels = new int[ 1 ], prevAlignment =
- new int[ 1 ];
-
- assert ( currentTile >= 0 );
-
- // be sure OpenGL rendering is finished
- gl.glFlush();
-
- // save current glPixelStore values
- gl.glGetIntegerv( GL2.GL_PACK_ROW_LENGTH, prevRowLength, 0 );
- gl.glGetIntegerv( GL2.GL_PACK_SKIP_ROWS, prevSkipRows, 0 );
- gl.glGetIntegerv( GL2.GL_PACK_SKIP_PIXELS, prevSkipPixels, 0 );
- gl.glGetIntegerv( GL2.GL_PACK_ALIGNMENT, prevAlignment, 0 );
-
- if( tileBuffer != null ) {
- int srcX = tileBorder;
- int srcY = tileBorder;
- int srcWidth = tileSizeNB.width;
- int srcHeight = tileSizeNB.height;
- gl.glReadPixels( srcX, srcY, srcWidth, srcHeight, tileFormat, tileType, tileBuffer );
- }
-
- if( imageBuffer != null ) {
- int srcX = tileBorder;
- int srcY = tileBorder;
- int srcWidth = currentTileWidth - 2 * tileBorder;
- int srcHeight = currentTileHeight - 2 * tileBorder;
- int destX = tileSizeNB.width * currentColumn;
- int destY = tileSizeNB.height * currentRow;
-
- /* setup pixel store for glReadPixels */
- gl.glPixelStorei( GL2.GL_PACK_ROW_LENGTH, imageSize.width );
- gl.glPixelStorei( GL2.GL_PACK_SKIP_ROWS, destY );
- gl.glPixelStorei( GL2.GL_PACK_SKIP_PIXELS, destX );
- gl.glPixelStorei( GL2.GL_PACK_ALIGNMENT, 1 );
-
- /* read the tile into the final image */
- gl.glReadPixels( srcX, srcY, srcWidth, srcHeight, imageFormat, imageType, imageBuffer );
- }
-
- /* restore previous glPixelStore values */
- gl.glPixelStorei( GL2.GL_PACK_ROW_LENGTH, prevRowLength[ 0 ] );
- gl.glPixelStorei( GL2.GL_PACK_SKIP_ROWS, prevSkipRows[ 0 ] );
- gl.glPixelStorei( GL2.GL_PACK_SKIP_PIXELS, prevSkipPixels[ 0 ] );
- gl.glPixelStorei( GL2.GL_PACK_ALIGNMENT, prevAlignment[ 0 ] );
-
- /* increment tile counter, return 1 if more tiles left to render */
- currentTile++;
- if( currentTile >= rows * columns ) {
- /* restore user's viewport */
- gl.glViewport( viewportSave[ 0 ], viewportSave[ 1 ], viewportSave[ 2 ], viewportSave[ 3 ] );
- currentTile = -1; /* all done */
- return false;
- } else {
- return true;
- }
- }
-
- /**
- * Tile rendering causes problems with using glRasterPos3f, so you
- * should use this replacement instead
- *
- * @param x
- * As in glRasterPos3f
- * @param y
- * As in glRasterPos3f
- * @param z
- * As in glRasterPos3f
- * @param gl
- * The gl context
- * @param glu
- * A GLUgl2 object
- */
- public void trRasterPos3f( float x, float y, float z, GL2 gl, GLUgl2 glu )
- {
- if (currentTile < 0) {
- /* not doing tile rendering right now. Let OpenGL do this. */
- gl.glRasterPos3f( x, y, z );
- } else {
- double[] modelview = new double[ 16 ], proj = new double[ 16 ];
- int[] viewport = new int[ 4 ];
- double[] win = new double[3];
-
- /* Get modelview, projection and viewport */
- gl.glGetDoublev( GL2.GL_MODELVIEW_MATRIX, modelview, 0 );
- gl.glGetDoublev( GL2.GL_PROJECTION_MATRIX, proj, 0 );
- viewport[ 0 ] = 0;
- viewport[ 1 ] = 0;
- viewport[ 2 ] = currentTileWidth;
- viewport[ 3 ] = currentTileHeight;
-
- /* Project object coord to window coordinate */
- if( glu.gluProject( x, y, z, modelview, 0, proj, 0, viewport, 0, win, 0 ) ) {
-
- /* set raster pos to window coord (0,0) */
- gl.glMatrixMode( GL2.GL_MODELVIEW );
- gl.glPushMatrix();
- gl.glLoadIdentity();
- gl.glMatrixMode( GL2.GL_PROJECTION );
- gl.glPushMatrix();
- gl.glLoadIdentity();
- gl.glOrtho( 0.0, currentTileWidth, 0.0, currentTileHeight, 0.0, 1.0 );
- gl.glRasterPos3d( 0.0, 0.0, -win[ 2 ] );
-
- /*
- * Now use empty bitmap to adjust raster position to
- * (winX,winY)
- */
- {
- byte[] bitmap = { 0 };
- gl.glBitmap( 1, 1, 0.0f, 0.0f, ( float ) win[ 0 ], ( float ) win[ 1 ], bitmap , 0 );
- }
-
- /* restore original matrices */
- gl.glPopMatrix(); /* proj */
- gl.glMatrixMode( GL2.GL_MODELVIEW );
- gl.glPopMatrix();
- }
- }
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
index f6b686d7e..3b8706a24 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
@@ -35,6 +35,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.StringReader;
+import java.net.URISyntaxException;
import java.net.URLConnection;
import java.nio.Buffer;
import java.nio.ByteBuffer;
@@ -45,13 +46,18 @@ import java.util.Set;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GL4;
import javax.media.opengl.GLES2;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import jogamp.opengl.Debug;
+import com.jogamp.common.net.Uri;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.VersionNumber;
/**
* Convenient shader code class to use and instantiate vertex or fragment programs.
@@ -59,42 +65,79 @@ import com.jogamp.common.util.IOUtil;
* A documented example of how to use this code is available
* {@link #create(GL2ES2, int, Class, String, String, String, boolean) here} and
* {@link #create(GL2ES2, int, int, Class, String, String[], String, String) here}.
- * </p>
+ * </p>
+ * <p>
+ * Support for {@link GL4#GL_TESS_CONTROL_SHADER} and {@link GL4#GL_TESS_EVALUATION_SHADER}
+ * was added since 2.2.1.
+ * </p>
*/
public class ShaderCode {
- public static final boolean DEBUG = Debug.debug("GLSLCode");
public static final boolean DEBUG_CODE = Debug.isPropertyDefined("jogl.debug.GLSLCode", true);
- /** Unique resource suffix for {@link GL2ES2#GL_VERTEX_SHADER} in source code: <code>vp</code> */
+ /** Unique resource suffix for {@link GL2ES2#GL_VERTEX_SHADER} in source code: <code>{@value}</code> */
public static final String SUFFIX_VERTEX_SOURCE = "vp" ;
-
- /** Unique resource suffix for {@link GL2ES2#GL_VERTEX_SHADER} in binary: <code>bvp</code> */
+
+ /** Unique resource suffix for {@link GL2ES2#GL_VERTEX_SHADER} in binary: <code>{@value}</code> */
public static final String SUFFIX_VERTEX_BINARY = "bvp" ;
-
- /** Unique resource suffix for {@link GL2ES2#GL_FRAGMENT_SHADER} in source code: <code>fp</code> */
+
+ /** Unique resource suffix for {@link GL3#GL_GEOMETRY_SHADER} in source code: <code>{@value}</code> */
+ public static final String SUFFIX_GEOMETRY_SOURCE = "gp" ;
+
+ /** Unique resource suffix for {@link GL3#GL_GEOMETRY_SHADER} in binary: <code>{@value}</code> */
+ public static final String SUFFIX_GEOMETRY_BINARY = "bgp" ;
+
+ /**
+ * Unique resource suffix for {@link GL4#GL_TESS_CONTROL_SHADER} in source code: <code>{@value}</code>
+ * @since 2.2.1
+ */
+ public static final String SUFFIX_TESS_CONTROL_SOURCE = "tcp" ;
+
+ /**
+ * Unique resource suffix for {@link GL4#GL_TESS_CONTROL_SHADER} in binary: <code>{@value}</code>
+ * @since 2.2.1
+ */
+ public static final String SUFFIX_TESS_CONTROL_BINARY = "btcp" ;
+
+ /**
+ * Unique resource suffix for {@link GL4#GL_TESS_EVALUATION_SHADER} in source code: <code>{@value}</code>
+ * @since 2.2.1
+ */
+ public static final String SUFFIX_TESS_EVALUATION_SOURCE = "tep" ;
+
+ /**
+ * Unique resource suffix for {@link GL4#GL_TESS_EVALUATION_SHADER} in binary: <code>{@value}</code>
+ * @since 2.2.1
+ */
+ public static final String SUFFIX_TESS_EVALUATION_BINARY = "btep" ;
+
+ /** Unique resource suffix for {@link GL2ES2#GL_FRAGMENT_SHADER} in source code: <code>{@value}</code> */
public static final String SUFFIX_FRAGMENT_SOURCE = "fp" ;
-
- /** Unique resource suffix for {@link GL2ES2#GL_FRAGMENT_SHADER} in binary: <code>bfp</code> */
+
+ /** Unique resource suffix for {@link GL2ES2#GL_FRAGMENT_SHADER} in binary: <code>{@value}</code> */
public static final String SUFFIX_FRAGMENT_BINARY = "bfp" ;
-
- /** Unique relative path for binary shader resources for {@link GLES2#GL_NVIDIA_PLATFORM_BINARY_NV NVIDIA}: <code>nvidia</code> */
+
+ /** Unique relative path for binary shader resources for {@link GLES2#GL_NVIDIA_PLATFORM_BINARY_NV NVIDIA}: <code>{@value}</code> */
public static final String SUB_PATH_NVIDIA = "nvidia" ;
/**
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER}, {@link GL3#GL_GEOMETRY_SHADER},
+ * {@link GL4#GL_TESS_CONTROL_SHADER} or {@link GL4#GL_TESS_EVALUATION_SHADER}.
* @param count number of shaders
* @param source CharSequence array containing the shader sources, organized as <code>source[count][strings-per-shader]</code>.
* May be either an immutable <code>String</code> - or mutable <code>StringBuilder</code> array.
- *
+ *
* @throws IllegalArgumentException if <code>count</count> and <code>source.length</code> do not match
*/
- public ShaderCode(int type, int count, CharSequence[][] source) {
+ public ShaderCode(final int type, final int count, final CharSequence[][] source) {
if(source.length != count) {
throw new IllegalArgumentException("shader number ("+count+") and sourceFiles array ("+source.length+") of different lenght.");
}
switch (type) {
case GL2ES2.GL_VERTEX_SHADER:
case GL2ES2.GL_FRAGMENT_SHADER:
+ case GL3.GL_GEOMETRY_SHADER:
+ case GL4.GL_TESS_CONTROL_SHADER:
+ case GL4.GL_TESS_EVALUATION_SHADER:
break;
default:
throw new GLException("Unknown shader type: "+type);
@@ -113,14 +156,18 @@ public class ShaderCode {
}
/**
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER}, {@link GL3#GL_GEOMETRY_SHADER},
+ * {@link GL4#GL_TESS_CONTROL_SHADER} or {@link GL4#GL_TESS_EVALUATION_SHADER}.
* @param count number of shaders
- * @param binary binary buffer containing the shader binaries,
+ * @param binary binary buffer containing the shader binaries,
*/
- public ShaderCode(int type, int count, int binFormat, Buffer binary) {
+ public ShaderCode(final int type, final int count, final int binFormat, final Buffer binary) {
switch (type) {
case GL2ES2.GL_VERTEX_SHADER:
case GL2ES2.GL_FRAGMENT_SHADER:
+ case GL3.GL_GEOMETRY_SHADER:
+ case GL4.GL_TESS_CONTROL_SHADER:
+ case GL4.GL_TESS_EVALUATION_SHADER:
break;
default:
throw new GLException("Unknown shader type: "+type);
@@ -136,23 +183,24 @@ public class ShaderCode {
/**
* Creates a complete {@link ShaderCode} object while reading all shader source of <code>sourceFiles</code>,
* which location is resolved using the <code>context</code> class, see {@link #readShaderSource(Class, String)}.
- *
+ *
* @param gl current GL object to determine whether a shader compiler is available. If null, no validation is performed.
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER}, {@link GL3#GL_GEOMETRY_SHADER},
+ * {@link GL4#GL_TESS_CONTROL_SHADER} or {@link GL4#GL_TESS_EVALUATION_SHADER}.
* @param count number of shaders
* @param context class used to help resolving the source location
* @param sourceFiles array of source locations, organized as <code>sourceFiles[count]</code>
* @param mutableStringBuilder if <code>true</code> method returns a mutable <code>StringBuilder</code> instance
- * which can be edited later on at the costs of a String conversion when passing to
+ * which can be edited later on at the costs of a String conversion when passing to
* {@link GL2ES2#glShaderSource(int, int, String[], IntBuffer)}.
* If <code>false</code> method returns an immutable <code>String</code> instance,
* which can be passed to {@link GL2ES2#glShaderSource(int, int, String[], IntBuffer)}
* at no additional costs.
- *
+ *
* @throws IllegalArgumentException if <code>count</count> and <code>sourceFiles.length</code> do not match
* @see #readShaderSource(Class, String)
*/
- public static ShaderCode create(GL2ES2 gl, int type, int count, Class<?> context, String[] sourceFiles, boolean mutableStringBuilder) {
+ public static ShaderCode create(final GL2ES2 gl, final int type, final int count, final Class<?> context, final String[] sourceFiles, final boolean mutableStringBuilder) {
if(null != gl && !ShaderUtil.isShaderCompilerAvailable(gl)) {
return null;
}
@@ -164,7 +212,7 @@ public class ShaderCode {
for(int i=0; i<sourceFiles.length; i++) {
try {
shaderSources[i][0] = readShaderSource(context, sourceFiles[i], mutableStringBuilder);
- } catch (IOException ioe) {
+ } catch (final IOException ioe) {
throw new RuntimeException("readShaderSource("+sourceFiles[i]+") error: ", ioe);
}
if(null == shaderSources[i][0]) {
@@ -181,22 +229,23 @@ public class ShaderCode {
/**
* Creates a complete {@link ShaderCode} object while reading the shader binary of <code>binaryFile</code>,
* which location is resolved using the <code>context</code> class, see {@link #readShaderBinary(Class, String)}.
- *
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ *
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER}, {@link GL3#GL_GEOMETRY_SHADER},
+ * {@link GL4#GL_TESS_CONTROL_SHADER} or {@link GL4#GL_TESS_EVALUATION_SHADER}.
* @param count number of shaders
* @param context class used to help resolving the source location
* @param binFormat a valid native binary format as they can be queried by {@link ShaderUtil#getShaderBinaryFormats(GL)}.
* @param sourceFiles array of source locations, organized as <code>sourceFiles[count]</code>
- *
+ *
* @see #readShaderBinary(Class, String)
* @see ShaderUtil#getShaderBinaryFormats(GL)
- */
- public static ShaderCode create(int type, int count, Class<?> context, int binFormat, String binaryFile) {
+ */
+ public static ShaderCode create(final int type, final int count, final Class<?> context, int binFormat, final String binaryFile) {
ByteBuffer shaderBinary = null;
if(null!=binaryFile && 0<=binFormat) {
try {
shaderBinary = readShaderBinary(context, binaryFile);
- } catch (IOException ioe) {
+ } catch (final IOException ioe) {
throw new RuntimeException("readShaderBinary("+binaryFile+") error: ", ioe);
}
if(null == shaderBinary) {
@@ -214,40 +263,55 @@ public class ShaderCode {
* <ul>
* <li>Source<ul>
* <li>{@link GL2ES2#GL_VERTEX_SHADER vertex}: {@link #SUFFIX_VERTEX_SOURCE}</li>
- * <li>{@link GL2ES2#GL_FRAGMENT_SHADER fragment}: {@link #SUFFIX_FRAGMENT_SOURCE}</li></ul></li>
+ * <li>{@link GL2ES2#GL_FRAGMENT_SHADER fragment}: {@link #SUFFIX_FRAGMENT_SOURCE}</li>
+ * <li>{@link GL3#GL_GEOMETRY_SHADER geometry}: {@link #SUFFIX_GEOMETRY_SOURCE}</li>
+ * <li>{@link GL4#GL_TESS_CONTROL_SHADER tess-ctrl}: {@link #SUFFIX_TESS_CONTROL_SOURCE}</li>
+ * <li>{@link GL4#GL_TESS_EVALUATION_SHADER tess-eval}: {@link #SUFFIX_TESS_EVALUATION_SOURCE}</li>
+ * </ul></li>
* <li>Binary<ul>
* <li>{@link GL2ES2#GL_VERTEX_SHADER vertex}: {@link #SUFFIX_VERTEX_BINARY}</li>
- * <li>{@link GL2ES2#GL_FRAGMENT_SHADER fragment}: {@link #SUFFIX_FRAGMENT_BINARY}</li></ul></li>
- * </ul>
- * @param binary true for a binary resource, false for a source resource
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
- *
+ * <li>{@link GL2ES2#GL_FRAGMENT_SHADER fragment}: {@link #SUFFIX_FRAGMENT_BINARY}</li>
+ * <li>{@link GL3#GL_GEOMETRY_SHADER geometry}: {@link #SUFFIX_GEOMETRY_BINARY}</li>
+ * <li>{@link GL4#GL_TESS_CONTROL_SHADER tess-ctrl}: {@link #SUFFIX_TESS_CONTROL_BINARY}</li>
+ * <li>{@link GL4#GL_TESS_EVALUATION_SHADER tess-eval}: {@link #SUFFIX_TESS_EVALUATION_BINARY}</li>
+ * </ul></li>
+ * </ul>
+ * @param binary true for a binary resource, false for a source resource
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER}, {@link GL3#GL_GEOMETRY_SHADER},
+ * {@link GL4#GL_TESS_CONTROL_SHADER} or {@link GL4#GL_TESS_EVALUATION_SHADER}.
+ *
* @throws GLException if <code>type</code> is not supported
- *
+ *
* @see #create(GL2ES2, int, Class, String, String, String, boolean)
*/
- public static String getFileSuffix(boolean binary, int type) {
+ public static String getFileSuffix(final boolean binary, final int type) {
switch (type) {
case GL2ES2.GL_VERTEX_SHADER:
return binary?SUFFIX_VERTEX_BINARY:SUFFIX_VERTEX_SOURCE;
case GL2ES2.GL_FRAGMENT_SHADER:
return binary?SUFFIX_FRAGMENT_BINARY:SUFFIX_FRAGMENT_SOURCE;
+ case GL3.GL_GEOMETRY_SHADER:
+ return binary?SUFFIX_GEOMETRY_BINARY:SUFFIX_GEOMETRY_SOURCE;
+ case GL4.GL_TESS_CONTROL_SHADER:
+ return binary?SUFFIX_TESS_CONTROL_BINARY:SUFFIX_TESS_CONTROL_SOURCE;
+ case GL4.GL_TESS_EVALUATION_SHADER:
+ return binary?SUFFIX_TESS_EVALUATION_BINARY:SUFFIX_TESS_EVALUATION_SOURCE;
default:
throw new GLException("illegal shader type: "+type);
}
}
- /**
+ /**
* Returns a unique relative path for binary shader resources as follows:
* <ul>
* <li>{@link GLES2#GL_NVIDIA_PLATFORM_BINARY_NV NVIDIA}: {@link #SUB_PATH_NVIDIA}</li>
* </ul>
- *
+ *
* @throws GLException if <code>binFormat</code> is not supported
- *
+ *
* @see #create(GL2ES2, int, Class, String, String, String, boolean)
- */
- public static String getBinarySubPath(int binFormat) {
+ */
+ public static String getBinarySubPath(final int binFormat) {
switch (binFormat) {
case GLES2.GL_NVIDIA_PLATFORM_BINARY_NV:
return SUB_PATH_NVIDIA;
@@ -257,42 +321,42 @@ public class ShaderCode {
}
/**
- * Convenient creation method for instantiating a complete {@link ShaderCode} object
- * either from source code using {@link #create(GL2ES2, int, int, Class, String[])},
+ * Convenient creation method for instantiating a complete {@link ShaderCode} object
+ * either from source code using {@link #create(GL2ES2, int, int, Class, String[])},
* or from a binary code using {@link #create(int, int, Class, int, String)},
* whatever is available first.
* <p>
- * The source and binary location names are expected w/o suffixes which are
+ * The source and binary location names are expected w/o suffixes which are
* resolved and appended using {@link #getFileSuffix(boolean, int)}.
* </p>
* <p>
* Additionally, the binary resource is expected within a subfolder of <code>binRoot</code>
* which reflects the vendor specific binary format, see {@link #getBinarySubPath(int)}.
* All {@link ShaderUtil#getShaderBinaryFormats(GL)} are being iterated
- * using the binary subfolder, the first existing resource is being used.
+ * using the binary subfolder, the first existing resource is being used.
* </p>
- *
+ *
* Example:
* <pre>
* Your std JVM layout (plain or within a JAR):
- *
+ *
* org/test/glsl/MyShaderTest.class
* org/test/glsl/shader/vertex.vp
* org/test/glsl/shader/fragment.fp
* org/test/glsl/shader/bin/nvidia/vertex.bvp
* org/test/glsl/shader/bin/nvidia/fragment.bfp
- *
+ *
* Your Android APK layout:
- *
+ *
* classes.dex
* assets/org/test/glsl/shader/vertex.vp
* assets/org/test/glsl/shader/fragment.fp
* assets/org/test/glsl/shader/bin/nvidia/vertex.bvp
* assets/org/test/glsl/shader/bin/nvidia/fragment.bfp
* ...
- *
+ *
* Your invocation in org/test/glsl/MyShaderTest.java:
- *
+ *
* ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, this.getClass(),
* "shader", new String[] { "vertex" }, "shader/bin", "vertex");
* ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, this.getClass(),
@@ -303,49 +367,56 @@ public class ShaderCode {
* st.attachShaderProgram(gl, sp0, true);
* </pre>
* A simplified entry point is {@link #create(GL2ES2, int, Class, String, String, String, boolean)}.
- *
+ *
* <p>
* The location is finally being resolved using the <code>context</code> class, see {@link #readShaderBinary(Class, String)}.
* </p>
- *
+ *
* @param gl current GL object to determine whether a shader compiler is available (if <code>source</code> is used),
* or to determine the shader binary format (if <code>binary</code> is used).
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER}, {@link GL3#GL_GEOMETRY_SHADER},
+ * {@link GL4#GL_TESS_CONTROL_SHADER} or {@link GL4#GL_TESS_EVALUATION_SHADER}.
* @param count number of shaders
* @param context class used to help resolving the source and binary location
- * @param srcRoot relative <i>root</i> path for <code>srcBasenames</code>
+ * @param srcRoot relative <i>root</i> path for <code>srcBasenames</code> optional
* @param srcBasenames basenames w/o path or suffix relative to <code>srcRoot</code> for the shader's source code
* @param binRoot relative <i>root</i> path for <code>binBasenames</code>
* @param binBasename basename w/o path or suffix relative to <code>binRoot</code> for the shader's binary code
* @param mutableStringBuilder if <code>true</code> method returns a mutable <code>StringBuilder</code> instance
- * which can be edited later on at the costs of a String conversion when passing to
+ * which can be edited later on at the costs of a String conversion when passing to
* {@link GL2ES2#glShaderSource(int, int, String[], IntBuffer)}.
* If <code>false</code> method returns an immutable <code>String</code> instance,
* which can be passed to {@link GL2ES2#glShaderSource(int, int, String[], IntBuffer)}
* at no additional costs.
- *
+ *
* @throws IllegalArgumentException if <code>count</count> and <code>srcBasenames.length</code> do not match
- *
+ *
* @see #create(GL2ES2, int, int, Class, String[])
* @see #create(int, int, Class, int, String)
* @see #readShaderSource(Class, String)
* @see #getFileSuffix(boolean, int)
* @see ShaderUtil#getShaderBinaryFormats(GL)
* @see #getBinarySubPath(int)
- */
- public static ShaderCode create(GL2ES2 gl, int type, int count, Class<?> context,
- String srcRoot, String[] srcBasenames, String binRoot, String binBasename,
- boolean mutableStringBuilder) {
+ */
+ public static ShaderCode create(final GL2ES2 gl, final int type, final int count, final Class<?> context,
+ final String srcRoot, final String[] srcBasenames, final String binRoot, final String binBasename,
+ final boolean mutableStringBuilder) {
ShaderCode res = null;
final String srcPath[];
String srcPathString = null;
String binFileName = null;
- if(null!=srcRoot && null!=srcBasenames && ShaderUtil.isShaderCompilerAvailable(gl)) {
+ if( null!=srcBasenames && ShaderUtil.isShaderCompilerAvailable(gl) ) {
srcPath = new String[srcBasenames.length];
final String srcSuffix = getFileSuffix(false, type);
- for(int i=0; i<srcPath.length; i++) {
- srcPath[i] = srcRoot + '/' + srcBasenames[i] + "." + srcSuffix;
+ if( null != srcRoot && srcRoot.length() > 0 ) {
+ for(int i=0; i<srcPath.length; i++) {
+ srcPath[i] = srcRoot + '/' + srcBasenames[i] + "." + srcSuffix;
+ }
+ } else {
+ for(int i=0; i<srcPath.length; i++) {
+ srcPath[i] = srcBasenames[i] + "." + srcSuffix;
+ }
}
res = create(gl, type, count, context, srcPath, mutableStringBuilder);
if(null!=res) {
@@ -355,12 +426,12 @@ public class ShaderCode {
} else {
srcPath = null;
}
- if(null!=binRoot && null!=binBasename) {
- Set<Integer> binFmts = ShaderUtil.getShaderBinaryFormats(gl);
+ if( null!=binBasename ) {
+ final Set<Integer> binFmts = ShaderUtil.getShaderBinaryFormats(gl);
final String binSuffix = getFileSuffix(true, type);
- for(Iterator<Integer> iter=binFmts.iterator(); iter.hasNext(); ) {
- int bFmt = iter.next().intValue();
- String bFmtPath = getBinarySubPath(bFmt);
+ for(final Iterator<Integer> iter=binFmts.iterator(); iter.hasNext(); ) {
+ final int bFmt = iter.next().intValue();
+ final String bFmtPath = getBinarySubPath(bFmt);
if(null==bFmtPath) continue;
binFileName = binRoot + '/' + bFmtPath + '/' + binBasename + "." + binSuffix;
res = create(type, count, context, bFmt, binFileName);
@@ -374,30 +445,29 @@ public class ShaderCode {
}
/**
- * Simplified variation of {@link #create(GL2ES2, int, int, Class, String, String[], String, String)}.
- * <br>
- *
+ * Simplified variation of {@link #create(GL2ES2, int, int, Class, String, String[], String, String, boolean)}.
+ * <p>
* Example:
* <pre>
* Your std JVM layout (plain or within a JAR):
- *
+ *
* org/test/glsl/MyShaderTest.class
* org/test/glsl/shader/vertex.vp
* org/test/glsl/shader/fragment.fp
* org/test/glsl/shader/bin/nvidia/vertex.bvp
* org/test/glsl/shader/bin/nvidia/fragment.bfp
- *
+ *
* Your Android APK layout:
- *
+ *
* classes.dex
* assets/org/test/glsl/shader/vertex.vp
* assets/org/test/glsl/shader/fragment.fp
* assets/org/test/glsl/shader/bin/nvidia/vertex.bvp
* assets/org/test/glsl/shader/bin/nvidia/fragment.bfp
* ...
- *
+ *
* Your invocation in org/test/glsl/MyShaderTest.java:
- *
+ *
* ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
* "shader", "shader/bin", "vertex");
* ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
@@ -407,31 +477,33 @@ public class ShaderCode {
* sp0.add(gl, fp0, System.err);
* st.attachShaderProgram(gl, sp0, true);
* </pre>
- *
+ * </p>
+ *
* @param gl current GL object to determine whether a shader compiler is available (if <code>source</code> is used),
* or to determine the shader binary format (if <code>binary</code> is used).
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER}, {@link GL3#GL_GEOMETRY_SHADER},
+ * {@link GL4#GL_TESS_CONTROL_SHADER} or {@link GL4#GL_TESS_EVALUATION_SHADER}.
* @param context class used to help resolving the source and binary location
- * @param srcRoot relative <i>root</i> path for <code>basename</code>
+ * @param srcRoot relative <i>root</i> path for <code>basename</code> optional
* @param binRoot relative <i>root</i> path for <code>basename</code>
* @param mutableStringBuilder TODO
* @param basenames basename w/o path or suffix relative to <code>srcRoot</code> and <code>binRoot</code>
* for the shader's source and binary code.
* @param mutableStringBuilder if <code>true</code> method returns a mutable <code>StringBuilder</code> instance
- * which can be edited later on at the costs of a String conversion when passing to
+ * which can be edited later on at the costs of a String conversion when passing to
* {@link GL2ES2#glShaderSource(int, int, String[], IntBuffer)}.
* If <code>false</code> method returns an immutable <code>String</code> instance,
* which can be passed to {@link GL2ES2#glShaderSource(int, int, String[], IntBuffer)}
* at no additional costs.
* @throws IllegalArgumentException if <code>count</count> is not 1
- *
+ *
* @see #create(GL2ES2, int, int, Class, String, String[], String, String)
- */
- public static ShaderCode create(GL2ES2 gl, int type, Class<?> context,
- String srcRoot, String binRoot, String basename, boolean mutableStringBuilder) {
- return create(gl, type, 1, context, srcRoot, new String[] { basename }, binRoot, basename, mutableStringBuilder );
+ */
+ public static ShaderCode create(final GL2ES2 gl, final int type, final Class<?> context,
+ final String srcRoot, final String binRoot, final String basename, final boolean mutableStringBuilder) {
+ return create(gl, type, 1, context, srcRoot, new String[] { basename }, binRoot, basename, mutableStringBuilder );
}
-
+
/**
* returns the uniq shader id as an integer
*/
@@ -440,12 +512,18 @@ public class ShaderCode {
public int shaderType() { return shaderType; }
public String shaderTypeStr() { return shaderTypeStr(shaderType); }
- public static String shaderTypeStr(int type) {
+ public static String shaderTypeStr(final int type) {
switch (type) {
case GL2ES2.GL_VERTEX_SHADER:
return "VERTEX_SHADER";
case GL2ES2.GL_FRAGMENT_SHADER:
return "FRAGMENT_SHADER";
+ case GL3.GL_GEOMETRY_SHADER:
+ return "GEOMETRY_SHADER";
+ case GL4.GL_TESS_CONTROL_SHADER:
+ return "TESS_CONTROL_SHADER";
+ case GL4.GL_TESS_EVALUATION_SHADER:
+ return "TESS_EVALUATION_SHADER";
}
return "UNKNOWN_SHADER";
}
@@ -458,15 +536,16 @@ public class ShaderCode {
public IntBuffer shader() { return shader; }
- public boolean compile(GL2ES2 gl) {
+ public boolean compile(final GL2ES2 gl) {
return compile(gl, null);
}
- public boolean compile(GL2ES2 gl, PrintStream verboseOut) {
+ public boolean compile(final GL2ES2 gl, final PrintStream verboseOut) {
if(isValid()) return true;
// Create & Compile the vertex/fragment shader objects
if(null!=shaderSource) {
if(DEBUG_CODE) {
+ System.err.println("ShaderCode.compile:");
dumpShaderSource(System.err);
}
valid=ShaderUtil.createAndCompileShader(gl, shader, shaderType,
@@ -480,7 +559,7 @@ public class ShaderCode {
return valid;
}
- public void destroy(GL2ES2 gl) {
+ public void destroy(final GL2ES2 gl) {
if(isValid()) {
if(null!=gl) {
ShaderUtil.deleteShader(gl, shader());
@@ -497,18 +576,21 @@ public class ShaderCode {
id=-1;
}
- public boolean equals(Object obj) {
+ @Override
+ public boolean equals(final Object obj) {
if(this==obj) { return true; }
if(obj instanceof ShaderCode) {
return id()==((ShaderCode)obj).id();
}
return false;
}
+ @Override
public int hashCode() {
return id;
}
+ @Override
public String toString() {
- StringBuilder buf = new StringBuilder("ShaderCode[id="+id+", type="+shaderTypeStr()+", valid="+valid+", shader: ");
+ final StringBuilder buf = new StringBuilder("ShaderCode[id="+id+", type="+shaderTypeStr()+", valid="+valid+", shader: ");
for(int i=0; i<shader.remaining(); i++) {
buf.append(" "+shader.get(i));
}
@@ -520,12 +602,12 @@ public class ShaderCode {
return buf.toString();
}
- public void dumpShaderSource(PrintStream out) {
+ public void dumpShaderSource(final PrintStream out) {
if(null==shaderSource) {
out.println("<no shader source>");
return;
}
- final int sourceCount = (null!=shaderSource)?shaderSource.length:0;
+ final int sourceCount = shaderSource.length;
final int shaderCount = (null!=shader)?shader.capacity():0;
for(int i=0; i<shaderCount; i++) {
out.println("");
@@ -534,9 +616,9 @@ public class ShaderCode {
if(i>=sourceCount) {
out.println("<no shader source>");
} else {
- CharSequence[] src = shaderSource[i];
+ final CharSequence[] src = shaderSource[i];
int lineno=0;
-
+
for(int j=0; j<src.length; j++) {
out.printf("%4d: // Segment %d/%d: \n", lineno, j, src.length);
final BufferedReader reader = new BufferedReader(new StringReader(src[j].toString()));
@@ -546,28 +628,28 @@ public class ShaderCode {
lineno++;
out.printf("%4d: %s\n", lineno, line);
}
- } catch (IOException e) { /* impossible .. StringReader */ }
+ } catch (final IOException e) { /* impossible .. StringReader */ }
}
}
out.println("--------------------------------------------------------------");
}
}
-
+
/**
* Adds <code>data</code> after the line containing <code>tag</code>.
* <p>
* Note: The shader source to be edit must be created using a mutable StringBuilder.
* </p>
- *
+ *
* @param shaderIdx the shader index to be used.
* @param tag search string
* @param fromIndex start search <code>tag</code> begininig with this index
* @param data the text to be inserted. Shall end with an EOL '\n' character.
* @return index after the inserted <code>data</code>
- *
+ *
* @throws IllegalStateException if the shader source's CharSequence is immutable, i.e. not of type <code>StringBuilder</code>
*/
- public int insertShaderSource(int shaderIdx, String tag, int fromIndex, CharSequence data) {
+ public int insertShaderSource(final int shaderIdx, final String tag, final int fromIndex, final CharSequence data) {
if(null==shaderSource) {
throw new IllegalStateException("no shader source");
}
@@ -575,10 +657,10 @@ public class ShaderCode {
if(0>shaderIdx || shaderIdx>=shaderCount) {
throw new IndexOutOfBoundsException("shaderIdx not within shader bounds [0.."+(shaderCount-1)+"]: "+shaderIdx);
}
- final int sourceCount = (null!=shaderSource)?shaderSource.length:0;
+ final int sourceCount = shaderSource.length;
if(shaderIdx>=sourceCount) {
throw new IndexOutOfBoundsException("shaderIdx not within source bounds [0.."+(sourceCount-1)+"]: "+shaderIdx);
- }
+ }
final CharSequence[] src = shaderSource[shaderIdx];
int curEndIndex = 0;
for(int j=0; j<src.length; j++) {
@@ -586,8 +668,8 @@ public class ShaderCode {
throw new IllegalStateException("shader source not a mutable StringBuilder, but CharSequence of type: "+src[j].getClass().getName());
}
final StringBuilder sb = (StringBuilder)src[j];
- curEndIndex += sb.length();
- if(fromIndex < curEndIndex) {
+ curEndIndex += sb.length();
+ if(fromIndex < curEndIndex) {
int insertIdx = sb.indexOf(tag, fromIndex);
if(0<=insertIdx) {
insertIdx += tag.length();
@@ -613,18 +695,18 @@ public class ShaderCode {
* Replaces <code>oldName</code> with <code>newName</code> in all shader sources.
* <p>
* In case <code>oldName</code> and <code>newName</code> are equal, no action is performed.
- * </p>
+ * </p>
* <p>
* Note: The shader source to be edit must be created using a mutable StringBuilder.
* </p>
- *
+ *
* @param oldName the to be replace string
* @param newName the replacement string
* @return the number of replacements
- *
+ *
* @throws IllegalStateException if the shader source's CharSequence is immutable, i.e. not of type <code>StringBuilder</code>
*/
- public int replaceInShaderSource(String oldName, String newName) {
+ public int replaceInShaderSource(final String oldName, final String newName) {
if(null==shaderSource) {
throw new IllegalStateException("no shader source");
}
@@ -634,7 +716,7 @@ public class ShaderCode {
final int oldNameLen = oldName.length();
final int newNameLen = newName.length();
int num = 0;
- final int sourceCount = (null!=shaderSource)?shaderSource.length:0;
+ final int sourceCount = shaderSource.length;
for(int shaderIdx = 0; shaderIdx<sourceCount; shaderIdx++) {
final CharSequence[] src = shaderSource[shaderIdx];
for(int j=0; j<src.length; j++) {
@@ -644,9 +726,9 @@ public class ShaderCode {
final StringBuilder sb = (StringBuilder)src[j];
int curPos = 0;
while(curPos<sb.length()-oldNameLen+1) {
- int startIdx = sb.indexOf(oldName, curPos);
+ final int startIdx = sb.indexOf(oldName, curPos);
if(0<=startIdx) {
- int endIdx = startIdx + oldNameLen;
+ final int endIdx = startIdx + oldNameLen;
sb.replace(startIdx, endIdx, newName);
curPos = startIdx + newNameLen;
num++;
@@ -658,21 +740,21 @@ public class ShaderCode {
}
return num;
}
-
+
/**
- * Adds <code>data</code> at <code>offset</code> in shader source for shader <code>shaderIdx</code>.
+ * Adds <code>data</code> at <code>position</code> in shader source for shader <code>shaderIdx</code>.
* <p>
* Note: The shader source to be edit must be created using a mutable StringBuilder.
* </p>
- *
+ *
* @param shaderIdx the shader index to be used.
- * @param position in shader source segments of shader <code>shaderIdx</code>
- * @param data the text to be inserted. Shall end with an EOL '\n' character.
+ * @param position in shader source segments of shader <code>shaderIdx</code>, -1 will append data
+ * @param data the text to be inserted. Shall end with an EOL '\n' character
* @return index after the inserted <code>data</code>
- *
+ *
* @throws IllegalStateException if the shader source's CharSequence is immutable, i.e. not of type <code>StringBuilder</code>
*/
- public int insertShaderSource(int shaderIdx, int position, CharSequence data) {
+ public int insertShaderSource(final int shaderIdx, int position, final CharSequence data) {
if(null==shaderSource) {
throw new IllegalStateException("no shader source");
}
@@ -680,10 +762,10 @@ public class ShaderCode {
if(0>shaderIdx || shaderIdx>=shaderCount) {
throw new IndexOutOfBoundsException("shaderIdx not within shader bounds [0.."+(shaderCount-1)+"]: "+shaderIdx);
}
- final int sourceCount = (null!=shaderSource)?shaderSource.length:0;
+ final int sourceCount = shaderSource.length;
if(shaderIdx>=sourceCount) {
throw new IndexOutOfBoundsException("shaderIdx not within source bounds [0.."+(sourceCount-1)+"]: "+shaderIdx);
- }
+ }
final CharSequence[] src = shaderSource[shaderIdx];
int curEndIndex = 0;
for(int j=0; j<src.length; j++) {
@@ -691,16 +773,50 @@ public class ShaderCode {
throw new IllegalStateException("shader source not a mutable StringBuilder, but CharSequence of type: "+src[j].getClass().getName());
}
final StringBuilder sb = (StringBuilder)src[j];
- curEndIndex += sb.length();
- if(position < curEndIndex) {
+ curEndIndex += sb.length();
+ if( 0 > position && j == src.length - 1 ) {
+ position = curEndIndex;
+ }
+ if(0 <= position && position <= curEndIndex ) {
sb.insert(position, data);
return position+data.length();
}
}
- return -1;
+ return position;
}
- private static int readShaderSource(Class<?> context, URLConnection conn, StringBuilder result, int lineno) throws IOException {
+ /**
+ * Adds shader source located in <code>path</code>,
+ * either relative to the <code>context</code> class or absolute <i>as-is</i>
+ * at <code>position</code> in shader source for shader <code>shaderIdx</code>.
+ * <p>
+ * Final location lookup is performed via {@link ClassLoader#getResource(String)} and {@link ClassLoader#getSystemResource(String)},
+ * see {@link IOUtil#getResource(Class, String)}.
+ * </p>
+ * <p>
+ * Note: The shader source to be edit must be created using a mutable StringBuilder.
+ * </p>
+ *
+ * @param shaderIdx the shader index to be used.
+ * @param position in shader source segments of shader <code>shaderIdx</code>, -1 will append data
+ * @param context class used to help resolve the source location
+ * @param path location of shader source
+ * @return index after the inserted code.
+ * @throws IOException
+ * @throws IllegalStateException if the shader source's CharSequence is immutable, i.e. not of type <code>StringBuilder</code>
+ * @see IOUtil#getResource(Class, String)
+ */
+ public int insertShaderSource(final int shaderIdx, final int position, final Class<?> context, final String path) throws IOException {
+ final CharSequence data = readShaderSource(context, path, true);
+ if( null != data ) {
+ return insertShaderSource(shaderIdx, position, data);
+ } else {
+ return position;
+ }
+ }
+
+ @SuppressWarnings("resource")
+ private static int readShaderSource(final Class<?> context, final URLConnection conn, final StringBuilder result, int lineno) throws IOException {
if(DEBUG_CODE) {
if(0 == lineno) {
result.append("// "+conn.getURL().toExternalForm()+"\n");
@@ -714,14 +830,15 @@ public class ShaderCode {
while ((line = reader.readLine()) != null) {
lineno++;
if (line.startsWith("#include ")) {
- String includeFile = line.substring(9).trim();
+ final String includeFile = line.substring(9).trim();
URLConnection nextConn = null;
-
+
// Try relative of current shader location
- nextConn = IOUtil.openURL(IOUtil.getRelativeOf(conn.getURL(), includeFile), "ShaderCode.relativeOf ");
+ final Uri relUri = Uri.valueOf( conn.getURL() ).getRelativeOf(new Uri.Encoded( includeFile, Uri.PATH_LEGAL ));
+ nextConn = IOUtil.openURL(relUri.toURL(), "ShaderCode.relativeOf ");
if (nextConn == null) {
// Try relative of class and absolute
- nextConn = IOUtil.getResource(context, includeFile);
+ nextConn = IOUtil.getResource(context, includeFile);
}
if (nextConn == null) {
// Fail
@@ -732,6 +849,8 @@ public class ShaderCode {
result.append(line + "\n");
}
}
+ } catch (final URISyntaxException e) {
+ throw new IOException(e);
} finally {
IOUtil.close(reader, false);
}
@@ -739,16 +858,16 @@ public class ShaderCode {
}
/**
- *
+ *
* @param context
* @param conn
* @param result
* @throws IOException
*/
- public static void readShaderSource(Class<?> context, URLConnection conn, StringBuilder result) throws IOException {
+ public static void readShaderSource(final Class<?> context, final URLConnection conn, final StringBuilder result) throws IOException {
readShaderSource(context, conn, result, 0);
}
-
+
/**
* Reads shader source located in <code>path</code>,
* either relative to the <code>context</code> class or absolute <i>as-is</i>.
@@ -756,44 +875,44 @@ public class ShaderCode {
* Final location lookup is performed via {@link ClassLoader#getResource(String)} and {@link ClassLoader#getSystemResource(String)},
* see {@link IOUtil#getResource(Class, String)}.
* </p>
- *
+ *
* @param context class used to help resolve the source location
* @param path location of shader source
* @param mutableStringBuilder if <code>true</code> method returns a mutable <code>StringBuilder</code> instance
- * which can be edited later on at the costs of a String conversion when passing to
+ * which can be edited later on at the costs of a String conversion when passing to
* {@link GL2ES2#glShaderSource(int, int, String[], IntBuffer)}.
* If <code>false</code> method returns an immutable <code>String</code> instance,
* which can be passed to {@link GL2ES2#glShaderSource(int, int, String[], IntBuffer)}
* at no additional costs.
- * @throws IOException
- *
+ * @throws IOException
+ *
* @see IOUtil#getResource(Class, String)
- */
- public static CharSequence readShaderSource(Class<?> context, String path, boolean mutableStringBuilder) throws IOException {
- URLConnection conn = IOUtil.getResource(context, path);
+ */
+ public static CharSequence readShaderSource(final Class<?> context, final String path, final boolean mutableStringBuilder) throws IOException {
+ final URLConnection conn = IOUtil.getResource(context, path);
if (conn == null) {
return null;
}
- StringBuilder result = new StringBuilder();
+ final StringBuilder result = new StringBuilder();
readShaderSource(context, conn, result);
return mutableStringBuilder ? result : result.toString();
}
/**
- * Reads shader binary located in <code>path</code>,
+ * Reads shader binary located in <code>path</code>,
* either relative to the <code>context</code> class or absolute <i>as-is</i>.
* <p>
* Final location lookup is perfomed via {@link ClassLoader#getResource(String)} and {@link ClassLoader#getSystemResource(String)},
* see {@link IOUtil#getResource(Class, String)}.
* </p>
- *
+ *
* @param context class used to help resolve the source location
* @param path location of shader binary
- * @throws IOException
- *
+ * @throws IOException
+ *
* @see IOUtil#getResource(Class, String)
*/
- public static ByteBuffer readShaderBinary(Class<?> context, String path) throws IOException {
+ public static ByteBuffer readShaderBinary(final Class<?> context, final String path) throws IOException {
final URLConnection conn = IOUtil.getResource(context, path);
if (conn == null) {
return null;
@@ -806,6 +925,192 @@ public class ShaderCode {
}
}
+ // Shall we use: #ifdef GL_FRAGMENT_PRECISION_HIGH .. #endif for using highp in fragment shader if avail ?
+ /** Default precision of {@link GL#isGLES2() ES2} for {@link GL2ES2#GL_VERTEX_SHADER vertex-shader}: {@value #es2_default_precision_vp} */
+ public static final String es2_default_precision_vp = "\nprecision highp float;\nprecision highp int;\n/*precision lowp sampler2D;*/\n/*precision lowp samplerCube;*/\n";
+ /** Default precision of {@link GL#isGLES2() ES2} for {@link GL2ES2#GL_FRAGMENT_SHADER fragment-shader}: {@value #es2_default_precision_fp} */
+ public static final String es2_default_precision_fp = "\nprecision mediump float;\nprecision mediump int;\n/*precision lowp sampler2D;*/\n/*precision lowp samplerCube;*/\n";
+
+ /** Default precision of {@link GL#isGLES3() ES3} for {@link GL2ES2#GL_VERTEX_SHADER vertex-shader}: {@value #es3_default_precision_vp} */
+ public static final String es3_default_precision_vp = es2_default_precision_vp;
+ /**
+ * Default precision of {@link GL#isGLES3() ES3} for {@link GL2ES2#GL_FRAGMENT_SHADER fragment-shader}: {@value #es3_default_precision_fp},
+ * same as for {@link GL2ES2#GL_VERTEX_SHADER vertex-shader}, i.e {@link #es3_default_precision_vp},
+ * due to ES 3.x requirements of using same precision for uniforms!
+ */
+ public static final String es3_default_precision_fp = es3_default_precision_vp;
+
+ /** Default precision of GLSL &ge; 1.30 as required until &lt; 1.50 for {@link GL2ES2#GL_VERTEX_SHADER vertex-shader} or {@link GL3#GL_GEOMETRY_SHADER geometry-shader}: {@value #gl3_default_precision_vp_gp}. See GLSL Spec 1.30-1.50 Section 4.5.3. */
+ public static final String gl3_default_precision_vp_gp = "\nprecision highp float;\nprecision highp int;\n";
+ /** Default precision of GLSL &ge; 1.30 as required until &lt; 1.50 for {@link GL2ES2#GL_FRAGMENT_SHADER fragment-shader}: {@value #gl3_default_precision_fp}. See GLSL Spec 1.30-1.50 Section 4.5.3. */
+ public static final String gl3_default_precision_fp = "\nprecision highp float;\nprecision mediump int;\n/*precision mediump sampler2D;*/\n";
+
+ /** <i>Behavior</i> for GLSL extension directive, see {@link #createExtensionDirective(String, String)}, value {@value}. */
+ public static final String REQUIRE = "require";
+ /** <i>Behavior</i> for GLSL extension directive, see {@link #createExtensionDirective(String, String)}, value {@value}. */
+ public static final String ENABLE = "enable";
+ /** <i>Behavior</i> for GLSL extension directive, see {@link #createExtensionDirective(String, String)}, value {@value}. */
+ public static final String DISABLE = "disable";
+ /** <i>Behavior</i> for GLSL extension directive, see {@link #createExtensionDirective(String, String)}, value {@value}. */
+ public static final String WARN = "warn";
+
+ /**
+ * Creates a GLSL extension directive.
+ * <p>
+ * Prefer {@link #ENABLE} over {@link #REQUIRE}, since the latter will force a failure if not supported.
+ * </p>
+ *
+ * @param extensionName
+ * @param behavior shall be either {@link #REQUIRE}, {@link #ENABLE}, {@link #DISABLE} or {@link #WARN}
+ * @return the complete extension directive
+ */
+ public static String createExtensionDirective(final String extensionName, final String behavior) {
+ return "#extension " + extensionName + " : " + behavior + "\n";
+ }
+
+ /**
+ * Add GLSL version at the head of this shader source code.
+ * <p>
+ * Note: The shader source to be edit must be created using a mutable StringBuilder.
+ * </p>
+ * @param gl a GL context, which must have been made current once
+ * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+ */
+ public final int addGLSLVersion(final GL2ES2 gl) {
+ return insertShaderSource(0, 0, gl.getContext().getGLSLVersionString());
+ }
+
+ /**
+ * Adds default precision to source code at given position if required, i.e.
+ * {@link #es2_default_precision_vp}, {@link #es2_default_precision_fp},
+ * {@link #gl3_default_precision_vp_gp}, {@link #gl3_default_precision_fp} or none,
+ * depending on the {@link GLContext#getGLSLVersionNumber() GLSL version} being used.
+ * <p>
+ * Note: The shader source to be edit must be created using a mutable StringBuilder.
+ * </p>
+ * @param gl a GL context, which must have been made current once
+ * @param pos position within this mutable shader source.
+ * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+ */
+ public final int addDefaultShaderPrecision(final GL2ES2 gl, int pos) {
+ final String defaultPrecision;
+ if( gl.isGLES3() ) {
+ switch ( shaderType ) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ defaultPrecision = es3_default_precision_vp; break;
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ defaultPrecision = es3_default_precision_fp; break;
+ default:
+ defaultPrecision = null;
+ break;
+ }
+ } else if( gl.isGLES2() ) {
+ switch ( shaderType ) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ defaultPrecision = es2_default_precision_vp; break;
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ defaultPrecision = es2_default_precision_fp; break;
+ default:
+ defaultPrecision = null;
+ break;
+ }
+ } else if( requiresGL3DefaultPrecision(gl) ) {
+ // GLSL [ 1.30 .. 1.50 [ needs at least fragement float default precision!
+ switch ( shaderType ) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ case GL3.GL_GEOMETRY_SHADER:
+ case GL4.GL_TESS_CONTROL_SHADER:
+ case GL4.GL_TESS_EVALUATION_SHADER:
+ defaultPrecision = gl3_default_precision_vp_gp; break;
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ defaultPrecision = gl3_default_precision_fp; break;
+ default:
+ defaultPrecision = null;
+ break;
+ }
+ } else {
+ defaultPrecision = null;
+ }
+ if( null != defaultPrecision ) {
+ pos = insertShaderSource(0, pos, defaultPrecision);
+ }
+ return pos;
+ }
+
+ /** Returns true, if GLSL version requires default precision, i.e. ES2 or GLSL [1.30 .. 1.50[. */
+ public static final boolean requiresDefaultPrecision(final GL2ES2 gl) {
+ if( gl.isGLES() ) {
+ return true;
+ }
+ return requiresGL3DefaultPrecision(gl);
+ }
+
+ /** Returns true, if GL3 GLSL version requires default precision, i.e. GLSL [1.30 .. 1.50[. */
+ public static final boolean requiresGL3DefaultPrecision(final GL2ES2 gl) {
+ if( gl.isGL3() ) {
+ final VersionNumber glslVersion = gl.getContext().getGLSLVersionNumber();
+ return glslVersion.compareTo(GLContext.Version130) >= 0 && glslVersion.compareTo(GLContext.Version150) < 0 ;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Default customization of this shader source code.
+ * <p>
+ * Note: The shader source to be edit must be created using a mutable StringBuilder.
+ * </p>
+ * @param gl a GL context, which must have been made current once
+ * @param preludeVersion if true {@link GLContext#getGLSLVersionString()} is preluded, otherwise not.
+ * @param addDefaultPrecision if <code>true</code> default precision source code line(s) are added, i.e.
+ * {@link #es2_default_precision_vp}, {@link #es2_default_precision_fp},
+ * {@link #gl3_default_precision_vp_gp}, {@link #gl3_default_precision_fp} or none,
+ * depending on the {@link GLContext#getGLSLVersionNumber() GLSL version} being used.
+ * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+ * @see #addGLSLVersion(GL2ES2)
+ * @see #addDefaultShaderPrecision(GL2ES2, int)
+ */
+ public final int defaultShaderCustomization(final GL2ES2 gl, final boolean preludeVersion, final boolean addDefaultPrecision) {
+ int pos;
+ if( preludeVersion ) {
+ pos = addGLSLVersion(gl);
+ } else {
+ pos = 0;
+ }
+ if( addDefaultPrecision ) {
+ pos = addDefaultShaderPrecision(gl, pos);
+ }
+ return pos;
+ }
+
+ /**
+ * Default customization of this shader source code.
+ * <p>
+ * Note: The shader source to be edit must be created using a mutable StringBuilder.
+ * </p>
+ * @param gl a GL context, which must have been made current once
+ * @param preludeVersion if true {@link GLContext#getGLSLVersionString()} is preluded, otherwise not.
+ * @param esDefaultPrecision optional default precision source code line(s) preluded if not null and if {@link GL#isGLES()}.
+ * You may use {@link #es2_default_precision_fp} for fragment shader and {@link #es2_default_precision_vp} for vertex shader.
+ * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+ * @see #addGLSLVersion(GL2ES2)
+ * @see #addDefaultShaderPrecision(GL2ES2, int)
+ */
+ public final int defaultShaderCustomization(final GL2ES2 gl, final boolean preludeVersion, final String esDefaultPrecision) {
+ int pos;
+ if( preludeVersion ) {
+ pos = addGLSLVersion(gl);
+ } else {
+ pos = 0;
+ }
+ if( gl.isGLES() && null != esDefaultPrecision ) {
+ pos = insertShaderSource(0, pos, esDefaultPrecision);
+ } else {
+ pos = addDefaultShaderPrecision(gl, pos);
+ }
+ return pos;
+ }
+
//----------------------------------------------------------------------
// Internals only below this point
//
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java
index 14ea7d2b8..a9b0bddc6 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java
@@ -37,7 +37,7 @@ import java.util.Iterator;
import java.io.PrintStream;
public class ShaderProgram {
-
+
public ShaderProgram() {
id = getNextID();
}
@@ -50,12 +50,13 @@ public class ShaderProgram {
return programInUse;
}
+ /** Returns the shader program name, which is non zero if valid. */
public int program() { return shaderProgram; }
/**
* returns the uniq shader id as an integer
*/
- public int id() { return id; }
+ public int id() { return id; }
/**
* Detaches all shader codes and deletes the program.
@@ -64,7 +65,7 @@ public class ShaderProgram {
*
* @see #release(GL2ES2, boolean)
*/
- public synchronized void destroy(GL2ES2 gl) {
+ public synchronized void destroy(final GL2ES2 gl) {
release(gl, true);
}
@@ -75,7 +76,7 @@ public class ShaderProgram {
*
* @see #release(GL2ES2, boolean)
*/
- public synchronized void release(GL2ES2 gl) {
+ public synchronized void release(final GL2ES2 gl) {
release(gl, false);
}
@@ -83,10 +84,12 @@ public class ShaderProgram {
* Detaches all shader codes and deletes the program.
* If <code>destroyShaderCode</code> is true it destroys the shader codes as well.
*/
- public synchronized void release(GL2ES2 gl, boolean destroyShaderCode) {
- useProgram(gl, false);
- for(Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) {
- ShaderCode shaderCode = iter.next();
+ public synchronized void release(final GL2ES2 gl, final boolean destroyShaderCode) {
+ if( programLinked ) {
+ useProgram(gl, false);
+ }
+ for(final Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) {
+ final ShaderCode shaderCode = iter.next();
if(attachedShaderCode.remove(shaderCode)) {
ShaderUtil.detachShader(gl, shaderProgram, shaderCode.shader());
}
@@ -96,9 +99,9 @@ public class ShaderProgram {
}
allShaderCode.clear();
attachedShaderCode.clear();
- if(0<=shaderProgram) {
+ if( 0 != shaderProgram ) {
gl.glDeleteProgram(shaderProgram);
- shaderProgram=-1;
+ shaderProgram=0;
}
}
@@ -108,26 +111,26 @@ public class ShaderProgram {
/**
* Adds a new shader to this program.
- *
+ *
* <p>This command does not compile and attach the shader,
* use {@link #add(GL2ES2, ShaderCode)} for this purpose.</p>
*/
- public synchronized void add(ShaderCode shaderCode) throws GLException {
+ public synchronized void add(final ShaderCode shaderCode) throws GLException {
allShaderCode.add(shaderCode);
}
- public synchronized boolean contains(ShaderCode shaderCode) {
+ public synchronized boolean contains(final ShaderCode shaderCode) {
return allShaderCode.contains(shaderCode);
}
-
+
/**
* Warning slow O(n) operation ..
* @param id
* @return
*/
- public synchronized ShaderCode getShader(int id) {
- for(Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) {
- ShaderCode shaderCode = iter.next();
+ public synchronized ShaderCode getShader(final int id) {
+ for(final Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) {
+ final ShaderCode shaderCode = iter.next();
if(shaderCode.id() == id) {
return shaderCode;
}
@@ -140,30 +143,33 @@ public class ShaderProgram {
//
/**
- * Creates the empty GL program object using {@link GL2ES2#glCreateProgram()}
- *
+ * Creates the empty GL program object using {@link GL2ES2#glCreateProgram()},
+ * if not already created.
+ *
* @param gl
+ * @return true if shader program is valid, i.e. not zero
*/
- public synchronized final void init(GL2ES2 gl) {
- if(0>shaderProgram) {
+ public synchronized final boolean init(final GL2ES2 gl) {
+ if( 0 == shaderProgram ) {
shaderProgram = gl.glCreateProgram();
}
+ return 0 != shaderProgram;
}
-
+
/**
* Adds a new shader to a this non running program.
*
* <p>Compiles and attaches the shader, if not done yet.</p>
- *
+ *
* @return true if the shader was successfully added, false if compilation failed.
*/
- public synchronized boolean add(GL2ES2 gl, ShaderCode shaderCode, PrintStream verboseOut) {
- init(gl);
+ public synchronized boolean add(final GL2ES2 gl, final ShaderCode shaderCode, final PrintStream verboseOut) {
+ if( !init(gl) ) { return false; }
if( allShaderCode.add(shaderCode) ) {
- if(!shaderCode.compile(gl, verboseOut)) {
+ if( !shaderCode.compile(gl, verboseOut) ) {
return false;
}
- if(attachedShaderCode.add(shaderCode)) {
+ if( attachedShaderCode.add(shaderCode) ) {
ShaderUtil.attachShader(gl, shaderProgram, shaderCode.shader());
}
}
@@ -173,11 +179,11 @@ public class ShaderProgram {
/**
* Replace a shader in a program and re-links the program.
*
- * @param gl
+ * @param gl
* @param oldShader the to be replace Shader
* @param newShader the new ShaderCode
* @param verboseOut the optional verbose output stream
- *
+ *
* @return true if all steps are valid, shader compilation, attachment and linking; otherwise false.
*
* @see ShaderState#glEnableVertexAttribArray
@@ -189,32 +195,30 @@ public class ShaderProgram {
* @see ShaderState#glResetAllVertexAttributes
* @see ShaderState#glResetAllVertexAttributes
*/
- public synchronized boolean replaceShader(GL2ES2 gl, ShaderCode oldShader, ShaderCode newShader, PrintStream verboseOut) {
- init(gl);
-
- if(!newShader.compile(gl, verboseOut)) {
+ public synchronized boolean replaceShader(final GL2ES2 gl, final ShaderCode oldShader, final ShaderCode newShader, final PrintStream verboseOut) {
+ if(!init(gl) || !newShader.compile(gl, verboseOut)) {
return false;
}
-
- boolean shaderWasInUse = inUse();
+
+ final boolean shaderWasInUse = inUse();
if(shaderWasInUse) {
useProgram(gl, false);
}
-
+
if(null != oldShader && allShaderCode.remove(oldShader)) {
if(attachedShaderCode.remove(oldShader)) {
ShaderUtil.detachShader(gl, shaderProgram, oldShader.shader());
}
}
-
+
add(newShader);
if(attachedShaderCode.add(newShader)) {
ShaderUtil.attachShader(gl, shaderProgram, newShader.shader());
}
-
+
gl.glLinkProgram(shaderProgram);
-
- programLinked = ShaderUtil.isProgramLinkStatusValid(gl, shaderProgram, System.err);
+
+ programLinked = ShaderUtil.isProgramLinkStatusValid(gl, shaderProgram, verboseOut);
if ( programLinked && shaderWasInUse ) {
useProgram(gl, true);
}
@@ -223,23 +227,27 @@ public class ShaderProgram {
/**
* Links the shader code to the program.
- *
+ *
* <p>Compiles and attaches the shader code to the program if not done by yet</p>
- *
+ *
* <p>Within this process, all GL resources (shader and program objects) are created if necessary.</p>
- *
+ *
* @param gl
* @param verboseOut
* @return true if program was successfully linked and is valid, otherwise false
- *
+ *
* @see #init(GL2ES2)
*/
- public synchronized boolean link(GL2ES2 gl, PrintStream verboseOut) {
- init(gl);
+ public synchronized boolean link(final GL2ES2 gl, final PrintStream verboseOut) {
+ if( !init(gl) ) {
+ programLinked = false; // mark unlinked due to user attempt to [re]link
+ return false;
+ }
- for(Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) {
+ for(final Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) {
final ShaderCode shaderCode = iter.next();
if(!shaderCode.compile(gl, verboseOut)) {
+ programLinked = false; // mark unlinked due to user attempt to [re]link
return false;
}
if(attachedShaderCode.add(shaderCode)) {
@@ -250,12 +258,13 @@ public class ShaderProgram {
// Link the program
gl.glLinkProgram(shaderProgram);
- programLinked = ShaderUtil.isProgramLinkStatusValid(gl, shaderProgram, System.err);
+ programLinked = ShaderUtil.isProgramLinkStatusValid(gl, shaderProgram, verboseOut);
return programLinked;
}
- public boolean equals(Object obj) {
+ @Override
+ public boolean equals(final Object obj) {
if(this == obj) { return true; }
if(obj instanceof ShaderProgram) {
return id()==((ShaderProgram)obj).id();
@@ -263,6 +272,7 @@ public class ShaderProgram {
return false;
}
+ @Override
public int hashCode() {
return id;
}
@@ -273,13 +283,14 @@ public class ShaderProgram {
}
sb.append("ShaderProgram[id=").append(id);
sb.append(", linked="+programLinked+", inUse="+programInUse+", program: "+shaderProgram+",");
- for(Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) {
+ for(final Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) {
sb.append(Platform.getNewline()).append(" ").append(iter.next());
}
sb.append("]");
return sb;
}
-
+
+ @Override
public String toString() {
return toString(null).toString();
}
@@ -288,27 +299,33 @@ public class ShaderProgram {
* Performs {@link GL2ES2#glValidateProgram(int)} via {@link ShaderUtil#isProgramExecStatusValid(GL, int, PrintStream)}.
* @see ShaderUtil#isProgramExecStatusValid(GL, int, PrintStream)
**/
- public synchronized boolean validateProgram(GL2ES2 gl, PrintStream verboseOut) {
+ public synchronized boolean validateProgram(final GL2ES2 gl, final PrintStream verboseOut) {
return ShaderUtil.isProgramExecStatusValid(gl, shaderProgram, verboseOut);
}
-
- public synchronized void useProgram(GL2ES2 gl, boolean on) {
+
+ public synchronized void useProgram(final GL2ES2 gl, boolean on) {
if(!programLinked) { throw new GLException("Program is not linked"); }
if(programInUse==on) { return; }
- gl.glUseProgram(on?shaderProgram:0);
+ if( 0 == shaderProgram ) {
+ on = false;
+ }
+ gl.glUseProgram( on ? shaderProgram : 0 );
programInUse = on;
}
+ public synchronized void notifyNotInUse() {
+ programInUse = false;
+ }
- protected boolean programLinked = false;
- protected boolean programInUse = false;
- protected int shaderProgram=-1;
- protected HashSet<ShaderCode> allShaderCode = new HashSet<ShaderCode>();
- protected HashSet<ShaderCode> attachedShaderCode = new HashSet<ShaderCode>();
- protected int id = -1;
+ private boolean programLinked = false;
+ private boolean programInUse = false;
+ private int shaderProgram = 0; // non zero is valid!
+ private final HashSet<ShaderCode> allShaderCode = new HashSet<ShaderCode>();
+ private final HashSet<ShaderCode> attachedShaderCode = new HashSet<ShaderCode>();
+ private final int id;
private static synchronized int getNextID() {
return nextID++;
}
- protected static int nextID = 1;
+ private static int nextID = 1;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
index 62082aacd..d758fc121 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
@@ -35,134 +35,85 @@ import java.util.Iterator;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLArrayData;
-import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLUniformData;
import jogamp.opengl.Debug;
import com.jogamp.common.os.Platform;
-import com.jogamp.common.util.IntObjectHashMap;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.opengl.util.GLArrayDataEditable;
+/**
+ * ShaderState allows to sharing data between shader programs,
+ * while updating the attribute and uniform locations when switching.
+ * <p>
+ * This allows seamless switching of programs using <i>almost</i> same data
+ * but performing different artifacts.
+ * </p>
+ * <p>
+ * A {@link #useProgram(GL2ES2, boolean) used} ShaderState is attached to the current GL context
+ * and can be retrieved via {@link #getShaderState(GL)}.
+ * </p>
+ */
public class ShaderState {
- public static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLSLState", true);
- private static final String currentStateKey = "jogamp.opengl.glsl.ShaderState" ;
-
- public ShaderState() {
- }
-
- public boolean verbose() { return verbose; }
+ public static final boolean DEBUG;
- public void setVerbose(boolean v) { verbose=v; }
-
- /**
- * Fetches the current shader state from this thread (TLS) current GLContext
- *
- * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
- * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL)
- * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL)
- * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
- */
- public static ShaderState getCurrentShaderState() {
- return getShaderState(GLContext.getCurrentGL());
+ static {
+ Debug.initSingleton();
+ DEBUG = PropertyAccess.isPropertyDefined("jogl.debug.GLSLState", true);
}
- /**
- * Gets the shader state attached to the GL object's GLContext
- *
- * @param gl the GL object referencing the GLContext
- *
- * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
- * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL)
- * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL)
- * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
- */
- public static ShaderState getShaderState(GL gl) {
- return (ShaderState) gl.getContext().getAttachedObject(currentStateKey);
+ public ShaderState() {
}
- /**
- * Attaches the shader state to the GL object's GLContext
- *
- * @param gl the GL object referencing the GLContext
- *
- * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
- * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL)
- * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL)
- * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
- */
- public final ShaderState setShaderState(GL gl) {
- return (ShaderState) gl.getContext().attachObject(currentStateKey, this);
- }
+ public boolean verbose() { return verbose; }
+
+ public void setVerbose(final boolean v) { verbose = DEBUG || v; }
/**
* Returns the attached user object for the given name to this ShaderState.
*/
- public final Object getAttachedObject(String name) {
+ public final Object getAttachedObject(final String name) {
return attachedObjectsByString.get(name);
}
/**
* Attach user object for the given name to this ShaderState.
* Returns the previously set object or null.
- *
+ *
* @return the previous mapped object or null if none
*/
- public final Object attachObject(String name, Object obj) {
+ public final Object attachObject(final String name, final Object obj) {
return attachedObjectsByString.put(name, obj);
}
/**
* @param name name of the mapped object to detach
- *
+ *
* @return the previous mapped object or null if none
*/
- public final Object detachObject(String name) {
+ public final Object detachObject(final String name) {
return attachedObjectsByString.remove(name);
- }
-
- /**
- * Returns the attached user object for the given name to this ShaderState.
- */
- public final Object getAttachedObject(int name) {
- return attachedObjectsByInt.get(name);
}
/**
- * Attach user object for the given name to this ShaderState.
- * Returns the previously set object or null.
- */
- public final Object attachObject(int name, Object obj) {
- return attachedObjectsByInt.put(name, obj);
- }
-
- public final Object detachObject(int name) {
- return attachedObjectsByInt.remove(name);
- }
-
- /**
* Turns the shader program on or off.<br>
- * Puts this ShaderState to to the thread local storage (TLS),
- * if <code>on</code> is <code>true</code>.
*
* @throws GLException if no program is attached
*
* @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
- * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL)
- * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
*/
- public synchronized void useProgram(GL2ES2 gl, boolean on) throws GLException {
- if(null==shaderProgram) { throw new GLException("No program is attached"); }
+ public synchronized void useProgram(final GL2ES2 gl, final boolean on) throws GLException {
+ if(null==shaderProgram) { throw new GLException("No program is attached"); }
if(on) {
- setShaderState(gl);
if(shaderProgram.linked()) {
shaderProgram.useProgram(gl, true);
if(resetAllShaderData) {
resetAllAttributes(gl);
resetAllUniforms(gl);
}
- } else {
+ } else {
if(resetAllShaderData) {
setAllAttributes(gl);
}
@@ -174,7 +125,7 @@ public class ShaderState {
resetAllUniforms(gl);
}
}
- resetAllShaderData = false;
+ resetAllShaderData = false;
} else {
shaderProgram.useProgram(gl, false);
}
@@ -191,39 +142,42 @@ public class ShaderState {
/**
* Attach or switch a shader program
*
- * <p>Attaching a shader program the first time,
+ * <p>Attaching a shader program the first time,
* as well as switching to another program on the fly,
* while managing all attribute and uniform data.</p>
- *
+ *
* <p>[Re]sets all data and use program in case of a program switch.</p>
- *
+ *
* <p>Use program, {@link #useProgram(GL2ES2, boolean)},
* if <code>enable</code> is <code>true</code>.</p>
- *
+ *
+ * @return true if shader program was attached, otherwise false (already attached)
+ *
* @throws GLException if program was not linked and linking fails
*/
- public synchronized void attachShaderProgram(GL2ES2 gl, ShaderProgram prog, boolean enable) throws GLException {
- if(DEBUG) {
- int curId = (null!=shaderProgram)?shaderProgram.id():-1;
- int newId = (null!=prog)?prog.id():-1;
- System.err.println("Info: attachShaderProgram: "+curId+" -> "+newId+" (enable: "+enable+")\n\t"+shaderProgram+"\n\t"+prog);
- if(verbose) {
- Throwable tX = new Throwable("Info: attachShaderProgram: Trace");
- tX.printStackTrace();
+ public synchronized boolean attachShaderProgram(final GL2ES2 gl, final ShaderProgram prog, final boolean enable) throws GLException {
+ if(verbose) {
+ final int curId = (null!=shaderProgram)?shaderProgram.id():-1;
+ final int newId = (null!=prog)?prog.id():-1;
+ System.err.println("ShaderState: attachShaderProgram: "+curId+" -> "+newId+" (enable: "+enable+")\n\t"+shaderProgram+"\n\t"+prog);
+ if(DEBUG) {
+ Thread.dumpStack();
}
}
if(null!=shaderProgram) {
if(shaderProgram.equals(prog)) {
- // nothing to do ..
- if(DEBUG) {
- System.err.println("Info: attachShaderProgram: NOP: equal id: "+shaderProgram.id());
+ if(enable) {
+ useProgram(gl, true);
+ }
+ // nothing else to do ..
+ if(verbose) {
+ System.err.println("ShaderState: attachShaderProgram: No switch, equal id: "+shaderProgram.id()+", enabling "+enable);
}
- return;
+ return false;
}
if(shaderProgram.inUse()) {
if(null != prog && enable) {
- // new program will issue glUseProgram(..)
- shaderProgram.programInUse = false;
+ shaderProgram.notifyNotInUse();
} else {
// no new 'enabled' program - disable
useProgram(gl, false);
@@ -236,7 +190,7 @@ public class ShaderState {
shaderProgram = prog;
if(null!=shaderProgram) {
- // [re]set all data and use program if switching program,
+ // [re]set all data and use program if switching program,
// or use program if program is linked
if(resetAllShaderData || enable) {
useProgram(gl, true); // may reset all data
@@ -248,6 +202,7 @@ public class ShaderState {
if(DEBUG) {
System.err.println("Info: attachShaderProgram: END");
}
+ return true;
}
public ShaderProgram shaderProgram() { return shaderProgram; }
@@ -259,10 +214,9 @@ public class ShaderState {
* @see #glReleaseAllUniforms
* @see #release(GL2ES2, boolean, boolean, boolean)
*/
- public synchronized void destroy(GL2ES2 gl) {
+ public synchronized void destroy(final GL2ES2 gl) {
release(gl, true, true, true);
- attachedObjectsByString.clear();
- attachedObjectsByInt.clear();
+ attachedObjectsByString.clear();
}
/**
@@ -272,7 +226,7 @@ public class ShaderState {
* @see #glReleaseAllUniforms
* @see #release(GL2ES2, boolean, boolean, boolean)
*/
- public synchronized void releaseAllData(GL2ES2 gl) {
+ public synchronized void releaseAllData(final GL2ES2 gl) {
release(gl, false, false, false);
}
@@ -281,14 +235,14 @@ public class ShaderState {
* @see #glReleaseAllUniforms
* @see ShaderProgram#release(GL2ES2, boolean)
*/
- public synchronized void release(GL2ES2 gl, boolean destroyBoundAttributes, boolean destroyShaderProgram, boolean destroyShaderCode) {
- if(null!=shaderProgram) {
+ public synchronized void release(final GL2ES2 gl, final boolean destroyBoundAttributes, final boolean destroyShaderProgram, final boolean destroyShaderCode) {
+ if(null!=shaderProgram && shaderProgram.linked() ) {
shaderProgram.useProgram(gl, false);
}
if(destroyBoundAttributes) {
- for(Iterator<GLArrayData> iter = managedAttributes.iterator(); iter.hasNext(); ) {
+ for(final Iterator<GLArrayData> iter = managedAttributes.iterator(); iter.hasNext(); ) {
iter.next().destroy(gl);
- }
+ }
}
releaseAllAttributes(gl);
releaseAllUniforms(gl);
@@ -304,7 +258,7 @@ public class ShaderState {
/**
* Gets the cached location of a shader attribute.
*
- * @return -1 if there is no such attribute available,
+ * @return -1 if there is no such attribute available,
* otherwise >= 0
*
* @see #bindAttribLocation(GL2ES2, int, String)
@@ -312,11 +266,11 @@ public class ShaderState {
* @see #getAttribLocation(GL2ES2, String)
* @see GL2ES2#glGetAttribLocation(int, String)
*/
- public int getCachedAttribLocation(String name) {
- Integer idx = activeAttribLocationMap.get(name);
+ public int getCachedAttribLocation(final String name) {
+ final Integer idx = activeAttribLocationMap.get(name);
return (null!=idx)?idx.intValue():-1;
}
-
+
/**
* Get the previous cached vertex attribute data.
*
@@ -332,28 +286,35 @@ public class ShaderState {
* @see #glResetAllVertexAttributes
* @see ShaderProgram#glReplaceShader
*/
- public GLArrayData getAttribute(String name) {
+ public GLArrayData getAttribute(final String name) {
return activeAttribDataMap.get(name);
}
-
+
+ public boolean isActiveAttribute(final GLArrayData attribute) {
+ return attribute == activeAttribDataMap.get(attribute.getName());
+ }
+
/**
* Binds or unbinds the {@link GLArrayData} lifecycle to this ShaderState.
- *
+ *
* <p>If an attribute location is cached (ie {@link #bindAttribLocation(GL2ES2, int, String)})
* it is promoted to the {@link GLArrayData} instance.</p>
- *
- * <p>The attribute will be destroyed with {@link #destroy(GL2ES2)}
+ *
+ * <p>The attribute will be destroyed with {@link #destroy(GL2ES2)}
* and it's location will be reset when switching shader with {@link #attachShaderProgram(GL2ES2, ShaderProgram)}.</p>
- *
+ *
* <p>The data will not be transfered to the GPU, use {@link #vertexAttribPointer(GL2ES2, GLArrayData)} additionally.</p>
- *
+ *
+ * <p>The data will also be {@link GLArrayData#associate(Object, boolean) associated} with this ShaderState.</p>
+ *
* @param attribute the {@link GLArrayData} which lifecycle shall be managed
* @param own true if <i>owning</i> shall be performs, false if <i>disowning</i>.
- *
+ *
* @see #bindAttribLocation(GL2ES2, int, String)
* @see #getAttribute(String)
+ * @see GLArrayData#associate(Object, boolean)
*/
- public void ownAttribute(GLArrayData attribute, boolean own) {
+ public void ownAttribute(final GLArrayData attribute, final boolean own) {
if(own) {
final int location = getCachedAttribLocation(attribute.getName());
if(0<=location) {
@@ -363,12 +324,13 @@ public class ShaderState {
} else {
managedAttributes.remove(attribute);
}
+ attribute.associate(this, own);
}
-
- public boolean ownsAttribute(GLArrayData attribute) {
+
+ public boolean ownsAttribute(final GLArrayData attribute) {
return managedAttributes.contains(attribute);
}
-
+
/**
* Binds a shader attribute to a location.
* Multiple names can be bound to one location.
@@ -377,16 +339,15 @@ public class ShaderState {
*
* @throws GLException if no program is attached
* @throws GLException if the program is already linked
- *
+ *
* @see javax.media.opengl.GL2ES2#glBindAttribLocation(int, int, String)
* @see #getAttribLocation(GL2ES2, String)
* @see #getCachedAttribLocation(String)
*/
- public void bindAttribLocation(GL2ES2 gl, int location, String name) {
+ public void bindAttribLocation(final GL2ES2 gl, final int location, final String name) {
if(null==shaderProgram) throw new GLException("No program is attached");
- if(shaderProgram.linked()) throw new GLException("Program is already linked");
- final Integer loc = new Integer(location);
- activeAttribLocationMap.put(name, loc);
+ if(shaderProgram.linked()) throw new GLException("Program is already linked");
+ activeAttribLocationMap.put(name, Integer.valueOf(location));
gl.glBindAttribLocation(shaderProgram.program(), location, name);
}
@@ -399,25 +360,28 @@ public class ShaderState {
*
* @throws GLException if no program is attached
* @throws GLException if the program is already linked
- *
+ *
* @see javax.media.opengl.GL2ES2#glBindAttribLocation(int, int, String)
* @see #getAttribLocation(GL2ES2, String)
* @see #getCachedAttribLocation(String)
* @see #getAttribute(String)
*/
- public void bindAttribLocation(GL2ES2 gl, int location, GLArrayData data) {
- bindAttribLocation(gl, location, data.getName());
- data.setLocation(location);
+ public void bindAttribLocation(final GL2ES2 gl, final int location, final GLArrayData data) {
+ if(null==shaderProgram) throw new GLException("No program is attached");
+ if(shaderProgram.linked()) throw new GLException("Program is already linked");
+ final String name = data.getName();
+ activeAttribLocationMap.put(name, Integer.valueOf(location));
+ data.setLocation(gl, shaderProgram.program(), location);
activeAttribDataMap.put(data.getName(), data);
}
/**
- * Gets the location of a shader attribute.<br>
+ * Gets the location of a shader attribute with given <code>name</code>.<br>
* Uses either the cached value {@link #getCachedAttribLocation(String)} if valid,
* or the GLSL queried via {@link GL2ES2#glGetAttribLocation(int, String)}.<br>
* The location will be cached.
*
- * @return -1 if there is no such attribute available,
+ * @return -1 if there is no such attribute available,
* otherwise >= 0
* @throws GLException if no program is attached
* @throws GLException if the program is not linked and no location was cached.
@@ -427,21 +391,22 @@ public class ShaderState {
* @see #bindAttribLocation(GL2ES2, int, String)
* @see GL2ES2#glGetAttribLocation(int, String)
*/
- public int getAttribLocation(GL2ES2 gl, String name) {
+ public int getAttribLocation(final GL2ES2 gl, final String name) {
if(null==shaderProgram) throw new GLException("No program is attached");
int location = getCachedAttribLocation(name);
if(0>location) {
if(!shaderProgram.linked()) throw new GLException("Program is not linked");
location = gl.glGetAttribLocation(shaderProgram.program(), name);
if(0<=location) {
- Integer idx = new Integer(location);
- activeAttribLocationMap.put(name, idx);
+ activeAttribLocationMap.put(name, Integer.valueOf(location));
if(DEBUG) {
- System.err.println("Info: glGetAttribLocation: "+name+", loc: "+location);
+ System.err.println("ShaderState: glGetAttribLocation: "+name+", loc: "+location);
}
} else if(verbose) {
- Throwable tX = new Throwable("Info: glGetAttribLocation failed, no location for: "+name+", loc: "+location);
- tX.printStackTrace();
+ System.err.println("ShaderState: glGetAttribLocation failed, no location for: "+name+", loc: "+location);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
}
}
return location;
@@ -449,14 +414,14 @@ public class ShaderState {
/**
* Validates and returns the location of a shader attribute.<br>
- * Uses either the cached value {@link #getCachedAttribLocation(String)} if valid,
+ * Uses either the cached value {@link #getCachedAttribLocation(String)} if valid,
* or the GLSL queried via {@link GL2ES2#glGetAttribLocation(int, String)}.<br>
- * The location will be cached and set in the
+ * The location will be cached and set in the
* {@link GLArrayData} object.
*
- * @return -1 if there is no such attribute available,
+ * @return -1 if there is no such attribute available,
* otherwise >= 0
- *
+ *
* @throws GLException if no program is attached
* @throws GLException if the program is not linked and no location was cached.
*
@@ -466,13 +431,31 @@ public class ShaderState {
* @see GL2ES2#glGetAttribLocation(int, String)
* @see #getAttribute(String)
*/
- public int getAttribLocation(GL2ES2 gl, GLArrayData data) {
- int location = getAttribLocation(gl, data.getName());
- data.setLocation(location);
+ public int getAttribLocation(final GL2ES2 gl, final GLArrayData data) {
+ if(null==shaderProgram) throw new GLException("No program is attached");
+ final String name = data.getName();
+ int location = getCachedAttribLocation(name);
+ if(0<=location) {
+ data.setLocation(location);
+ } else {
+ if(!shaderProgram.linked()) throw new GLException("Program is not linked");
+ location = data.setLocation(gl, shaderProgram.program());
+ if(0<=location) {
+ activeAttribLocationMap.put(name, Integer.valueOf(location));
+ if(DEBUG) {
+ System.err.println("ShaderState: glGetAttribLocation: "+name+", loc: "+location);
+ }
+ } else if(verbose) {
+ System.err.println("ShaderState: glGetAttribLocation failed, no location for: "+name+", loc: "+location);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ }
+ }
activeAttribDataMap.put(data.getName(), data);
return location;
}
-
+
//
// Enabled Vertex Arrays and its data
//
@@ -480,42 +463,44 @@ public class ShaderState {
/**
* @return true if the named attribute is enable
*/
- public final boolean isVertexAttribArrayEnabled(String name) {
+ public final boolean isVertexAttribArrayEnabled(final String name) {
final Boolean v = activedAttribEnabledMap.get(name);
return null != v && v.booleanValue();
}
-
+
/**
* @return true if the {@link GLArrayData} attribute is enable
*/
- public final boolean isVertexAttribArrayEnabled(GLArrayData data) {
+ public final boolean isVertexAttribArrayEnabled(final GLArrayData data) {
return isVertexAttribArrayEnabled(data.getName());
}
-
- private boolean enableVertexAttribArray(GL2ES2 gl, String name, int location) {
+
+ private boolean enableVertexAttribArray(final GL2ES2 gl, final String name, int location) {
activedAttribEnabledMap.put(name, Boolean.TRUE);
if(0>location) {
location = getAttribLocation(gl, name);
if(0>location) {
if(verbose) {
- Throwable tX = new Throwable("Info: glEnableVertexAttribArray failed, no index for: "+name);
- tX.printStackTrace();
+ System.err.println("ShaderState: glEnableVertexAttribArray failed, no index for: "+name);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
}
return false;
}
}
if(DEBUG) {
- System.err.println("Info: glEnableVertexAttribArray: "+name+", loc: "+location);
+ System.err.println("ShaderState: glEnableVertexAttribArray: "+name+", loc: "+location);
}
gl.glEnableVertexAttribArray(location);
return true;
}
-
+
/**
* Enables a vertex attribute array.
- *
+ *
* This method retrieves the the location via {@link #getAttribLocation(GL2ES2, GLArrayData)}
- * hence {@link #enableVertexAttribArray(GL2ES2, GLArrayData)} shall be preferred.
+ * hence {@link #enableVertexAttribArray(GL2ES2, GLArrayData)} shall be preferred.
*
* Even if the attribute is not found in the current shader,
* it is marked enabled in this state.
@@ -523,16 +508,16 @@ public class ShaderState {
* @return false, if the name is not found, otherwise true
*
* @throws GLException if the program is not linked and no location was cached.
- *
+ *
* @see #glEnableVertexAttribArray
* @see #glDisableVertexAttribArray
* @see #glVertexAttribPointer
* @see #getVertexAttribPointer
*/
- public boolean enableVertexAttribArray(GL2ES2 gl, String name) {
+ public boolean enableVertexAttribArray(final GL2ES2 gl, final String name) {
return enableVertexAttribArray(gl, name, -1);
}
-
+
/**
* Enables a vertex attribute array, usually invoked by {@link GLArrayDataEditable#enableBuffer(GL, boolean)}.
@@ -541,7 +526,7 @@ public class ShaderState {
* and is the preferred alternative to {@link #enableVertexAttribArray(GL2ES2, String)}.
* If data location is unset it will be retrieved via {@link #getAttribLocation(GL2ES2, GLArrayData)} set
* and cached in this state.
- *
+ *
* Even if the attribute is not found in the current shader,
* it is marked enabled in this state.
*
@@ -555,41 +540,43 @@ public class ShaderState {
* @see #getVertexAttribPointer
* @see GLArrayDataEditable#enableBuffer(GL, boolean)
*/
- public boolean enableVertexAttribArray(GL2ES2 gl, GLArrayData data) {
+ public boolean enableVertexAttribArray(final GL2ES2 gl, final GLArrayData data) {
if(0 > data.getLocation()) {
getAttribLocation(gl, data);
} else {
// ensure data is the current bound one
- activeAttribDataMap.put(data.getName(), data);
+ activeAttribDataMap.put(data.getName(), data);
}
return enableVertexAttribArray(gl, data.getName(), data.getLocation());
}
-
- private boolean disableVertexAttribArray(GL2ES2 gl, String name, int location) {
+
+ private boolean disableVertexAttribArray(final GL2ES2 gl, final String name, int location) {
activedAttribEnabledMap.put(name, Boolean.FALSE);
if(0>location) {
location = getAttribLocation(gl, name);
if(0>location) {
if(verbose) {
- Throwable tX = new Throwable("Info: glDisableVertexAttribArray failed, no index for: "+name);
- tX.printStackTrace();
+ System.err.println("ShaderState: glDisableVertexAttribArray failed, no index for: "+name);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
}
return false;
}
}
if(DEBUG) {
- System.err.println("Info: glDisableVertexAttribArray: "+name);
+ System.err.println("ShaderState: glDisableVertexAttribArray: "+name);
}
gl.glDisableVertexAttribArray(location);
return true;
}
-
+
/**
* Disables a vertex attribute array
*
* This method retrieves the the location via {@link #getAttribLocation(GL2ES2, GLArrayData)}
* hence {@link #disableVertexAttribArray(GL2ES2, GLArrayData)} shall be preferred.
- *
+ *
* Even if the attribute is not found in the current shader,
* it is removed from this state enabled list.
*
@@ -603,7 +590,7 @@ public class ShaderState {
* @see #glVertexAttribPointer
* @see #getVertexAttribPointer
*/
- public boolean disableVertexAttribArray(GL2ES2 gl, String name) {
+ public boolean disableVertexAttribArray(final GL2ES2 gl, final String name) {
return disableVertexAttribArray(gl, name, -1);
}
@@ -614,7 +601,7 @@ public class ShaderState {
* and is the preferred alternative to {@link #disableVertexAttribArray(GL2ES2, String)}.
* If data location is unset it will be retrieved via {@link #getAttribLocation(GL2ES2, GLArrayData)} set
* and cached in this state.
- *
+ *
* Even if the attribute is not found in the current shader,
* it is removed from this state enabled list.
*
@@ -628,39 +615,40 @@ public class ShaderState {
* @see #glVertexAttribPointer
* @see #getVertexAttribPointer
*/
- public boolean disableVertexAttribArray(GL2ES2 gl, GLArrayData data) {
+ public boolean disableVertexAttribArray(final GL2ES2 gl, final GLArrayData data) {
if(0 > data.getLocation()) {
getAttribLocation(gl, data);
}
return disableVertexAttribArray(gl, data.getName(), data.getLocation());
}
-
+
/**
- * Set the {@link GLArrayData} vertex attribute data.
- *
- * This method uses the {@link GLArrayData}'s location if set.
- * If data location is unset it will be retrieved via {@link #getAttribLocation(GL2ES2, GLArrayData)}, set
- * and cached in this state.
- *
+ * Set the {@link GLArrayData} vertex attribute data, if it's location is valid, i.e. &ge; 0.
+ * <p>
+ * This method uses the {@link GLArrayData}'s location if valid, i.e. &ge; 0.<br/>
+ * If data's location is invalid, it will be retrieved via {@link #getAttribLocation(GL2ES2, GLArrayData)},
+ * set and cached in this state.
+ * </p>
+ *
* @return false, if the location could not be determined, otherwise true
*
* @throws GLException if no program is attached
* @throws GLException if the program is not linked and no location was cached.
- *
+ *
* @see #glEnableVertexAttribArray
* @see #glDisableVertexAttribArray
* @see #glVertexAttribPointer
* @see #getVertexAttribPointer
*/
- public boolean vertexAttribPointer(GL2ES2 gl, GLArrayData data) {
+ public boolean vertexAttribPointer(final GL2ES2 gl, final GLArrayData data) {
int location = data.getLocation();
if(0 > location) {
location = getAttribLocation(gl, data);
- }
+ }
if(0 <= location) {
// only pass the data, if the attribute exists in the current shader
if(DEBUG) {
- System.err.println("Info: glVertexAttribPointer: "+data);
+ System.err.println("ShaderState: glVertexAttribPointer: "+data);
}
gl.glVertexAttribPointer(data);
return true;
@@ -681,28 +669,28 @@ public class ShaderState {
* @see #glResetAllVertexAttributes
* @see ShaderProgram#glReplaceShader
*/
- public void releaseAllAttributes(GL2ES2 gl) {
+ public void releaseAllAttributes(final GL2ES2 gl) {
if(null!=shaderProgram) {
- for(Iterator<GLArrayData> iter = activeAttribDataMap.values().iterator(); iter.hasNext(); ) {
+ for(final Iterator<GLArrayData> iter = activeAttribDataMap.values().iterator(); iter.hasNext(); ) {
disableVertexAttribArray(gl, iter.next());
}
- for(Iterator<String> iter = activedAttribEnabledMap.keySet().iterator(); iter.hasNext(); ) {
+ for(final Iterator<String> iter = activedAttribEnabledMap.keySet().iterator(); iter.hasNext(); ) {
disableVertexAttribArray(gl, iter.next());
}
}
activeAttribDataMap.clear();
activedAttribEnabledMap.clear();
activeAttribLocationMap.clear();
- managedAttributes.clear();
+ managedAttributes.clear();
}
-
+
/**
* Disables all vertex attribute arrays.
*
* Their enabled stated will be removed from this state only
* if 'removeFromState' is true.
*
- * This method purpose is more for debugging.
+ * This method purpose is more for debugging.
*
* @see #glEnableVertexAttribArray
* @see #glDisableVertexAttribArray
@@ -713,8 +701,8 @@ public class ShaderState {
* @see #glResetAllVertexAttributes
* @see ShaderProgram#glReplaceShader
*/
- public void disableAllVertexAttributeArrays(GL2ES2 gl, boolean removeFromState) {
- for(Iterator<String> iter = activedAttribEnabledMap.keySet().iterator(); iter.hasNext(); ) {
+ public void disableAllVertexAttributeArrays(final GL2ES2 gl, final boolean removeFromState) {
+ for(final Iterator<String> iter = activedAttribEnabledMap.keySet().iterator(); iter.hasNext(); ) {
final String name = iter.next();
if(removeFromState) {
activedAttribEnabledMap.remove(name);
@@ -726,78 +714,91 @@ public class ShaderState {
}
}
- private final void relocateAttribute(GL2ES2 gl, GLArrayData attribute) {
- // get new location ..
+ private final void relocateAttribute(final GL2ES2 gl, final GLArrayData attribute) {
+ // get new location .. note: 'activeAttribLocationMap' is cleared before
final String name = attribute.getName();
- final int loc = getAttribLocation(gl, name);
- attribute.setLocation(loc);
-
+ final int loc = attribute.setLocation(gl, shaderProgram.program());
if(0<=loc) {
+ activeAttribLocationMap.put(name, Integer.valueOf(loc));
+ if(DEBUG) {
+ System.err.println("ShaderState: relocateAttribute: "+name+", loc: "+loc);
+ }
if(isVertexAttribArrayEnabled(name)) {
// enable attrib, VBO and pass location/data
gl.glEnableVertexAttribArray(loc);
}
-
+
if( attribute.isVBO() ) {
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, attribute.getVBOName());
- }
-
- gl.glVertexAttribPointer(attribute);
+ gl.glVertexAttribPointer(attribute);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ } else {
+ gl.glVertexAttribPointer(attribute);
+ }
}
}
-
+
/**
* Reset all previously enabled mapped vertex attribute data.
- *
- * <p>Attribute data is bound to the GL state</p>
- * <p>Attribute location is bound to the program</p>
- *
- * <p>However, since binding an attribute to a location via {@link #bindAttribLocation(GL2ES2, int, GLArrayData)}
- * <i>must</i> happen before linking <b>and</b> we try to promote the attributes to the new program,
- * we have to gather the probably new location etc.</p>
+ *
+ * <p>
+ * Attribute data is bound to the GL state, i.e. VBO data itself will not be updated.
+ * </p>
+ *
+ * <p>
+ * Attribute location and it's data assignment is bound to the program,
+ * hence both are updated.
+ * </p>
+ *
+ * <p>
+ * Note: Such update could only be prevented,
+ * if tracking am attribute/program dirty flag.
+ * </p>
*
* @throws GLException is the program is not linked
*
* @see #attachShaderProgram(GL2ES2, ShaderProgram)
*/
- private final void resetAllAttributes(GL2ES2 gl) {
+ private final void resetAllAttributes(final GL2ES2 gl) {
if(!shaderProgram.linked()) throw new GLException("Program is not linked");
activeAttribLocationMap.clear();
-
- for(Iterator<GLArrayData> iter = managedAttributes.iterator(); iter.hasNext(); ) {
- iter.next().setLocation(-1);
+
+ for(int i=0; i<managedAttributes.size(); i++) {
+ managedAttributes.get(i).setLocation(-1);
}
- for(Iterator<GLArrayData> iter = activeAttribDataMap.values().iterator(); iter.hasNext(); ) {
+ for(final Iterator<GLArrayData> iter = activeAttribDataMap.values().iterator(); iter.hasNext(); ) {
relocateAttribute(gl, iter.next());
}
}
- private final void setAttribute(GL2ES2 gl, GLArrayData attribute) {
+ private final void setAttribute(final GL2ES2 gl, final GLArrayData attribute) {
// get new location ..
final String name = attribute.getName();
final int loc = attribute.getLocation();
if(0<=loc) {
- this.bindAttribLocation(gl, loc, name);
-
+ bindAttribLocation(gl, loc, name);
+
if(isVertexAttribArrayEnabled(name)) {
// enable attrib, VBO and pass location/data
gl.glEnableVertexAttribArray(loc);
}
-
+
if( attribute.isVBO() ) {
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, attribute.getVBOName());
- }
-
- gl.glVertexAttribPointer(attribute);
+ gl.glVertexAttribPointer(attribute);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ } else {
+ gl.glVertexAttribPointer(attribute);
+ }
}
}
-
+
/**
* preserves the attribute location .. (program not linked)
*/
- private final void setAllAttributes(GL2ES2 gl) {
- for(Iterator<GLArrayData> iter = activeAttribDataMap.values().iterator(); iter.hasNext(); ) {
+ private final void setAllAttributes(final GL2ES2 gl) {
+ for(final Iterator<GLArrayData> iter = activeAttribDataMap.values().iterator(); iter.hasNext(); ) {
setAttribute(gl, iter.next());
}
}
@@ -809,48 +810,48 @@ public class ShaderState {
/**
* Gets the cached location of the shader uniform.
*
- * @return -1 if there is no such uniform available,
+ * @return -1 if there is no such uniform available,
* otherwise >= 0
*/
- public final int getCachedUniformLocation(String name) {
- Integer idx = (Integer) activeUniformLocationMap.get(name);
+ public final int getCachedUniformLocation(final String name) {
+ final Integer idx = activeUniformLocationMap.get(name);
return (null!=idx)?idx.intValue():-1;
}
/**
* Bind the {@link GLUniform} lifecycle to this ShaderState.
- *
+ *
* <p>If a uniform location is cached it is promoted to the {@link GLUniformData} instance.</p>
- *
- * <p>The attribute will be destroyed with {@link #destroy(GL2ES2)}
+ *
+ * <p>The attribute will be destroyed with {@link #destroy(GL2ES2)}
* and it's location will be reset when switching shader with {@link #attachShaderProgram(GL2ES2, ShaderProgram)}.</p>
- *
+ *
* <p>The data will not be transfered to the GPU, use {@link #uniform(GL2ES2, GLUniformData)} additionally.</p>
- *
+ *
* @param uniform the {@link GLUniformData} which lifecycle shall be managed
- *
+ *
* @see #getUniform(String)
*/
- public void ownUniform(GLUniformData uniform) {
+ public void ownUniform(final GLUniformData uniform) {
final int location = getCachedUniformLocation(uniform.getName());
if(0<=location) {
uniform.setLocation(location);
- }
+ }
activeUniformDataMap.put(uniform.getName(), uniform);
- managedUniforms.add(uniform);
+ managedUniforms.add(uniform);
}
-
- public boolean ownsUniform(GLUniformData uniform) {
+
+ public boolean ownsUniform(final GLUniformData uniform) {
return managedUniforms.contains(uniform);
}
-
+
/**
- * Gets the location of a shader uniform.<br>
+ * Gets the location of a shader uniform with given <code>name</code>.<br>
* Uses either the cached value {@link #getCachedUniformLocation(String)} if valid,
* or the GLSL queried via {@link GL2ES2#glGetUniformLocation(int, String)}.<br>
* The location will be cached.
* <p>
- * The current shader program ({@link #attachShaderProgram(GL2ES2, ShaderProgram)})
+ * The current shader program ({@link #attachShaderProgram(GL2ES2, ShaderProgram)})
* must be in use ({@link #useProgram(GL2ES2, boolean) }) !</p>
*
* @return -1 if there is no such attribute available,
@@ -863,17 +864,19 @@ public class ShaderState {
* @see #getUniformLocation
* @see ShaderProgram#glReplaceShader
*/
- public final int getUniformLocation(GL2ES2 gl, String name) {
+ public final int getUniformLocation(final GL2ES2 gl, final String name) {
if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
int location = getCachedUniformLocation(name);
if(0>location) {
+ if(!shaderProgram.linked()) throw new GLException("Program is not linked");
location = gl.glGetUniformLocation(shaderProgram.program(), name);
if(0<=location) {
- Integer idx = new Integer(location);
- activeUniformLocationMap.put(name, idx);
+ activeUniformLocationMap.put(name, Integer.valueOf(location));
} else if(verbose) {
- Throwable tX = new Throwable("Info: glUniform failed, no location for: "+name+", index: "+location);
- tX.printStackTrace();
+ System.err.println("ShaderState: glUniform failed, no location for: "+name+", index: "+location);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
}
}
return location;
@@ -883,10 +886,10 @@ public class ShaderState {
* Validates and returns the location of a shader uniform.<br>
* Uses either the cached value {@link #getCachedUniformLocation(String)} if valid,
* or the GLSL queried via {@link GL2ES2#glGetUniformLocation(int, String)}.<br>
- * The location will be cached and set in the
+ * The location will be cached and set in the
* {@link GLUniformData} object.
* <p>
- * The current shader program ({@link #attachShaderProgram(GL2ES2, ShaderProgram)})
+ * The current shader program ({@link #attachShaderProgram(GL2ES2, ShaderProgram)})
* must be in use ({@link #useProgram(GL2ES2, boolean) }) !</p>
*
* @return -1 if there is no such attribute available,
@@ -899,27 +902,37 @@ public class ShaderState {
* @see #getUniformLocation
* @see ShaderProgram#glReplaceShader
*/
- public int getUniformLocation(GL2ES2 gl, GLUniformData data) {
- int location = getUniformLocation(gl, data.getName());
- data.setLocation(location);
- activeUniformDataMap.put(data.getName(), data);
+ public int getUniformLocation(final GL2ES2 gl, final GLUniformData data) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ final String name = data.getName();
+ int location = getCachedUniformLocation(name);
+ if(0<=location) {
+ data.setLocation(location);
+ } else {
+ if(!shaderProgram.linked()) throw new GLException("Program is not linked");
+ location = data.setLocation(gl, shaderProgram.program());
+ if(0<=location) {
+ activeUniformLocationMap.put(name, Integer.valueOf(location));
+ } else if(verbose) {
+ System.err.println("ShaderState: glUniform failed, no location for: "+name+", index: "+location);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ }
+ }
+ activeUniformDataMap.put(name, data);
return location;
}
-
+
/**
- * Set the uniform data.
- *
- * Even if the uniform is not found in the current shader,
- * it is stored in this state.
- *
- * @param data the GLUniforms's name must match the uniform one,
- * it's index will be set with the uniforms's location,
- * if found.
- *
- *
- * @return false, if the name is not found, otherwise true
+ * Set the uniform data, if it's location is valid, i.e. &ge; 0.
+ * <p>
+ * This method uses the {@link GLUniformData}'s location if valid, i.e. &ge; 0.<br/>
+ * If data's location is invalid, it will be retrieved via {@link #getUniformLocation(GL2ES2, GLUniformData)},
+ * set and cached in this state.
+ * </p>
*
- * @throws GLException if the program is not in use
+ * @return false, if the location could not be determined, otherwise true
*
* @see #glGetUniformLocation
* @see javax.media.opengl.GL2ES2#glGetUniformLocation
@@ -927,7 +940,7 @@ public class ShaderState {
* @see #getUniformLocation
* @see ShaderProgram#glReplaceShader
*/
- public boolean uniform(GL2ES2 gl, GLUniformData data) {
+ public boolean uniform(final GL2ES2 gl, final GLUniformData data) {
if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
int location = data.getLocation();
if(0>location) {
@@ -936,11 +949,12 @@ public class ShaderState {
if(0<=location) {
// only pass the data, if the uniform exists in the current shader
if(DEBUG) {
- System.err.println("Info: glUniform: "+data);
+ System.err.println("ShaderState: glUniform: "+data);
}
gl.glUniform(data);
+ return true;
}
- return true;
+ return false;
}
/**
@@ -948,7 +962,7 @@ public class ShaderState {
*
* @return the GLUniformData object, null if not previously set.
*/
- public GLUniformData getUniform(String name) {
+ public GLUniformData getUniform(final String name) {
return activeUniformDataMap.get(name);
}
@@ -956,42 +970,54 @@ public class ShaderState {
* Releases all mapped uniform data
* and loses all indices
*/
- public void releaseAllUniforms(GL2ES2 gl) {
+ public void releaseAllUniforms(final GL2ES2 gl) {
activeUniformDataMap.clear();
activeUniformLocationMap.clear();
managedUniforms.clear();
}
-
+
/**
* Reset all previously mapped uniform data
- *
+ * <p>
* Uniform data and location is bound to the program,
- * hence both are updated here
+ * hence both are updated.
+ * </p>
+ * <p>
+ * Note: Such update could only be prevented,
+ * if tracking a uniform/program dirty flag.
+ * </p>
*
* @throws GLException is the program is not in use
- *
+ *
* @see #attachShaderProgram(GL2ES2, ShaderProgram)
*/
- private final void resetAllUniforms(GL2ES2 gl) {
- if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ private final void resetAllUniforms(final GL2ES2 gl) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
activeUniformLocationMap.clear();
- for(Iterator<GLUniformData> iter = managedUniforms.iterator(); iter.hasNext(); ) {
+ for(final Iterator<GLUniformData> iter = managedUniforms.iterator(); iter.hasNext(); ) {
iter.next().setLocation(-1);
- }
- for(Iterator<GLUniformData> iter = activeUniformDataMap.values().iterator(); iter.hasNext(); ) {
- final GLUniformData uniform = iter.next();
- uniform.setLocation(-1);
- uniform(gl, uniform);
+ }
+ for(final Iterator<GLUniformData> iter = activeUniformDataMap.values().iterator(); iter.hasNext(); ) {
+ final GLUniformData data = iter.next();
+ final int loc = data.setLocation(gl, shaderProgram.program());
+ if( 0 <= loc ) {
+ // only pass the data, if the uniform exists in the current shader
+ activeUniformLocationMap.put(data.getName(), Integer.valueOf(loc));
+ if(DEBUG) {
+ System.err.println("ShaderState: resetAllUniforms: "+data);
+ }
+ gl.glUniform(data);
+ }
}
}
- public StringBuilder toString(StringBuilder sb) {
+ public StringBuilder toString(StringBuilder sb, final boolean alsoUnlocated) {
if(null==sb) {
sb = new StringBuilder();
}
-
+
sb.append("ShaderState[ ");
-
+
sb.append(Platform.getNewline()).append(" ");
if(null != shaderProgram) {
shaderProgram.toString(sb);
@@ -1000,51 +1026,62 @@ public class ShaderState {
}
sb.append(Platform.getNewline()).append(" enabledAttributes [");
{
- Iterator<String> names = activedAttribEnabledMap.keySet().iterator();
- Iterator<Boolean> values = activedAttribEnabledMap.values().iterator();
+ final Iterator<String> names = activedAttribEnabledMap.keySet().iterator();
+ final Iterator<Boolean> values = activedAttribEnabledMap.values().iterator();
while( names.hasNext() ) {
sb.append(Platform.getNewline()).append(" ").append(names.next()).append(": ").append(values.next());
}
}
sb.append(Platform.getNewline()).append(" ],").append(" activeAttributes [");
- for(Iterator<GLArrayData> iter = activeAttribDataMap.values().iterator(); iter.hasNext(); ) {
- sb.append(Platform.getNewline()).append(" ").append(iter.next());
+ for(final Iterator<GLArrayData> iter = activeAttribDataMap.values().iterator(); iter.hasNext(); ) {
+ final GLArrayData ad = iter.next();
+ if( alsoUnlocated || 0 <= ad.getLocation() ) {
+ sb.append(Platform.getNewline()).append(" ").append(ad);
+ }
}
sb.append(Platform.getNewline()).append(" ],").append(" managedAttributes [");
- for(Iterator<GLArrayData> iter = managedAttributes.iterator(); iter.hasNext(); ) {
- sb.append(Platform.getNewline()).append(" ").append(iter.next());
+ for(final Iterator<GLArrayData> iter = managedAttributes.iterator(); iter.hasNext(); ) {
+ final GLArrayData ad = iter.next();
+ if( alsoUnlocated || 0 <= ad.getLocation() ) {
+ sb.append(Platform.getNewline()).append(" ").append(ad);
+ }
}
sb.append(Platform.getNewline()).append(" ],").append(" activeUniforms [");
- for(Iterator<GLUniformData> iter=activeUniformDataMap.values().iterator(); iter.hasNext(); ) {
- sb.append(Platform.getNewline()).append(" ").append(iter.next());
+ for(final Iterator<GLUniformData> iter=activeUniformDataMap.values().iterator(); iter.hasNext(); ) {
+ final GLUniformData ud = iter.next();
+ if( alsoUnlocated || 0 <= ud.getLocation() ) {
+ sb.append(Platform.getNewline()).append(" ").append(ud);
+ }
}
sb.append(Platform.getNewline()).append(" ],").append(" managedUniforms [");
- for(Iterator<GLUniformData> iter = managedUniforms.iterator(); iter.hasNext(); ) {
- sb.append(Platform.getNewline()).append(" ").append(iter.next());
+ for(final Iterator<GLUniformData> iter = managedUniforms.iterator(); iter.hasNext(); ) {
+ final GLUniformData ud = iter.next();
+ if( alsoUnlocated || 0 <= ud.getLocation() ) {
+ sb.append(Platform.getNewline()).append(" ").append(ud);
+ }
}
sb.append(Platform.getNewline()).append(" ]").append(Platform.getNewline()).append("]");
return sb;
}
-
+
@Override
public String toString() {
- return toString(null).toString();
+ return toString(null, DEBUG).toString();
}
-
- private boolean verbose = DEBUG ? true : false;
+
+ private boolean verbose = DEBUG;
private ShaderProgram shaderProgram=null;
-
- private HashMap<String, Boolean> activedAttribEnabledMap = new HashMap<String, Boolean>();
- private HashMap<String, Integer> activeAttribLocationMap = new HashMap<String, Integer>();
- private HashMap<String, GLArrayData> activeAttribDataMap = new HashMap<String, GLArrayData>();
- private ArrayList<GLArrayData> managedAttributes = new ArrayList<GLArrayData>();
-
- private HashMap<String, Integer> activeUniformLocationMap = new HashMap<String, Integer>();
- private HashMap<String, GLUniformData> activeUniformDataMap = new HashMap<String, GLUniformData>();
- private ArrayList<GLUniformData> managedUniforms = new ArrayList<GLUniformData>();
-
- private HashMap<String, Object> attachedObjectsByString = new HashMap<String, Object>();
- private IntObjectHashMap attachedObjectsByInt = new IntObjectHashMap();
+
+ private final HashMap<String, Boolean> activedAttribEnabledMap = new HashMap<String, Boolean>();
+ private final HashMap<String, Integer> activeAttribLocationMap = new HashMap<String, Integer>();
+ private final HashMap<String, GLArrayData> activeAttribDataMap = new HashMap<String, GLArrayData>();
+ private final ArrayList<GLArrayData> managedAttributes = new ArrayList<GLArrayData>();
+
+ private final HashMap<String, Integer> activeUniformLocationMap = new HashMap<String, Integer>();
+ private final HashMap<String, GLUniformData> activeUniformDataMap = new HashMap<String, GLUniformData>();
+ private final ArrayList<GLUniformData> managedUniforms = new ArrayList<GLUniformData>();
+
+ private final HashMap<String, Object> attachedObjectsByString = new HashMap<String, Object>();
private boolean resetAllShaderData = false;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
index 40c052498..06f7d9268 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,7 +28,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.opengl.util.glsl;
@@ -40,51 +40,52 @@ import java.util.*;
import javax.media.opengl.*;
import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.GLExtensions;
public class ShaderUtil {
- public static String getShaderInfoLog(GL _gl, int shaderObj) {
+ public static String getShaderInfoLog(final GL _gl, final int shaderObj) {
final GL2ES2 gl = _gl.getGL2ES2();
- int[] infoLogLength=new int[1];
+ final int[] infoLogLength=new int[1];
gl.glGetShaderiv(shaderObj, GL2ES2.GL_INFO_LOG_LENGTH, infoLogLength, 0);
if(infoLogLength[0]==0) {
return "(no info log)";
}
- int[] charsWritten=new int[1];
- byte[] infoLogBytes = new byte[infoLogLength[0]];
+ final int[] charsWritten=new int[1];
+ final byte[] infoLogBytes = new byte[infoLogLength[0]];
gl.glGetShaderInfoLog(shaderObj, infoLogLength[0], charsWritten, 0, infoLogBytes, 0);
return new String(infoLogBytes, 0, charsWritten[0]);
}
- public static String getProgramInfoLog(GL _gl, int programObj) {
+ public static String getProgramInfoLog(final GL _gl, final int programObj) {
final GL2ES2 gl = _gl.getGL2ES2();
- int[] infoLogLength=new int[1];
+ final int[] infoLogLength=new int[1];
gl.glGetProgramiv(programObj, GL2ES2.GL_INFO_LOG_LENGTH, infoLogLength, 0);
if(infoLogLength[0]==0) {
return "(no info log)";
}
- int[] charsWritten=new int[1];
- byte[] infoLogBytes = new byte[infoLogLength[0]];
+ final int[] charsWritten=new int[1];
+ final byte[] infoLogBytes = new byte[infoLogLength[0]];
gl.glGetProgramInfoLog(programObj, infoLogLength[0], charsWritten, 0, infoLogBytes, 0);
return new String(infoLogBytes, 0, charsWritten[0]);
}
- public static boolean isShaderStatusValid(GL _gl, int shaderObj, int name, PrintStream verboseOut) {
+ public static boolean isShaderStatusValid(final GL _gl, final int shaderObj, final int name, final PrintStream verboseOut) {
final GL2ES2 gl = _gl.getGL2ES2();
- int[] ires = new int[1];
+ final int[] ires = new int[1];
gl.glGetShaderiv(shaderObj, name, ires, 0);
- boolean res = ires[0]==1;
+ final boolean res = ires[0]==1;
if(!res && null!=verboseOut) {
verboseOut.println("Shader status invalid: "+ getShaderInfoLog(gl, shaderObj));
}
return res;
}
- public static boolean isShaderStatusValid(GL _gl, IntBuffer shaders, int name, PrintStream verboseOut) {
+ public static boolean isShaderStatusValid(final GL _gl, final IntBuffer shaders, final int name, final PrintStream verboseOut) {
boolean res = true;
for (int i = shaders.position(); i < shaders.limit(); i++) {
res = isShaderStatusValid(_gl, shaders.get(i), name, verboseOut) && res;
@@ -92,15 +93,15 @@ public class ShaderUtil {
return res;
}
- public static boolean isProgramStatusValid(GL _gl, int programObj, int name) {
+ public static boolean isProgramStatusValid(final GL _gl, final int programObj, final int name) {
final GL2ES2 gl = _gl.getGL2ES2();
- int[] ires = new int[1];
+ final int[] ires = new int[1];
gl.glGetProgramiv(programObj, name, ires, 0);
return ires[0]==1;
}
- public static boolean isProgramLinkStatusValid(GL _gl, int programObj, PrintStream verboseOut) {
+ public static boolean isProgramLinkStatusValid(final GL _gl, final int programObj, final PrintStream verboseOut) {
final GL2ES2 gl = _gl.getGL2ES2();
if(!gl.glIsProgram(programObj)) {
if(null!=verboseOut) {
@@ -116,11 +117,11 @@ public class ShaderUtil {
}
return true;
}
-
+
/**
* Performs {@link GL2ES2#glValidateProgram(int)}
* <p>
- * One shall only call this method while debugging and only if all required
+ * One shall only call this method while debugging and only if all required
* resources by the shader are set.
* </p>
* <p>
@@ -129,7 +130,7 @@ public class ShaderUtil {
* </p>
* @see GL2ES2#glValidateProgram(int)
**/
- public static boolean isProgramExecStatusValid(GL _gl, int programObj, PrintStream verboseOut) {
+ public static boolean isProgramExecStatusValid(final GL _gl, final int programObj, final PrintStream verboseOut) {
final GL2ES2 gl = _gl.getGL2ES2();
gl.glValidateProgram(programObj);
if(!isProgramStatusValid(gl, programObj, GL2ES2.GL_VALIDATE_STATUS)) {
@@ -141,7 +142,7 @@ public class ShaderUtil {
return true;
}
- public static void createShader(GL _gl, int type, IntBuffer shaders) {
+ public static void createShader(final GL _gl, final int type, final IntBuffer shaders) {
final GL2ES2 gl = _gl.getGL2ES2();
for (int i = shaders.position(); i < shaders.limit(); i++) {
shaders.put(i, gl.glCreateShader(type));
@@ -149,25 +150,31 @@ public class ShaderUtil {
}
/**
- * If supported, queries the natively supported shader binary formats using
+ * If supported, queries the natively supported shader binary formats using
* {@link GL2ES2#GL_NUM_SHADER_BINARY_FORMATS} and {@link GL2ES2#GL_SHADER_BINARY_FORMATS}
* via {@link GL2ES2#glGetIntegerv(int, int[], int)}.
*/
- public static Set<Integer> getShaderBinaryFormats(GL _gl) {
+ public static Set<Integer> getShaderBinaryFormats(final GL _gl) {
final GL2ES2 gl = _gl.getGL2ES2();
final ProfileInformation info = getProfileInformation(gl);
if(null == info.shaderBinaryFormats) {
info.shaderBinaryFormats = new HashSet<Integer>();
if (gl.isGLES2Compatible()) {
- final int[] param = new int[1];
- gl.glGetIntegerv(GL2ES2.GL_NUM_SHADER_BINARY_FORMATS, param, 0);
- int numFormats = param[0];
- if(numFormats>0) {
- int[] formats = new int[numFormats];
- gl.glGetIntegerv(GL2ES2.GL_SHADER_BINARY_FORMATS, formats, 0);
- for(int i=0; i<numFormats; i++) {
- info.shaderBinaryFormats.add(new Integer(formats[i]));
+ try {
+ final int[] param = new int[1];
+ gl.glGetIntegerv(GL2ES2.GL_NUM_SHADER_BINARY_FORMATS, param, 0);
+ final int err = gl.glGetError();
+ final int numFormats = GL.GL_NO_ERROR == err ? param[0] : 0;
+ if(numFormats>0) {
+ final int[] formats = new int[numFormats];
+ gl.glGetIntegerv(GL2ES2.GL_SHADER_BINARY_FORMATS, formats, 0);
+ for(int i=0; i<numFormats; i++) {
+ info.shaderBinaryFormats.add(Integer.valueOf(formats[i]));
+ }
}
+ } catch (final GLException gle) {
+ System.err.println("Caught exception on thread "+Thread.currentThread().getName());
+ gle.printStackTrace();
}
}
}
@@ -175,22 +182,33 @@ public class ShaderUtil {
}
/** Returns true if a hader compiler is available, otherwise false. */
- public static boolean isShaderCompilerAvailable(GL _gl) {
+ public static boolean isShaderCompilerAvailable(final GL _gl) {
final GL2ES2 gl = _gl.getGL2ES2();
final ProfileInformation info = getProfileInformation(gl);
if(null==info.shaderCompilerAvailable) {
if(gl.isGLES2()) {
- final byte[] param = new byte[1];
- gl.glGetBooleanv(GL2ES2.GL_SHADER_COMPILER, param, 0);
- boolean v = param[0]!=(byte)0x00;
- if(!v) {
- final Set<Integer> bfs = getShaderBinaryFormats(gl);
- if(bfs.size()==0) {
- // no supported binary formats, hence a compiler must be available!
- v = true;
+ boolean queryOK = false;
+ try {
+ final byte[] param = new byte[1];
+ gl.glGetBooleanv(GL2ES2.GL_SHADER_COMPILER, param, 0);
+ final int err = gl.glGetError();
+ boolean v = GL.GL_NO_ERROR == err && param[0]!=(byte)0x00;
+ if(!v) {
+ final Set<Integer> bfs = getShaderBinaryFormats(gl);
+ if(bfs.size()==0) {
+ // no supported binary formats, hence a compiler must be available!
+ v = true;
+ }
}
+ info.shaderCompilerAvailable = Boolean.valueOf(v);
+ queryOK = true;
+ } catch (final GLException gle) {
+ System.err.println("Caught exception on thread "+Thread.currentThread().getName());
+ gle.printStackTrace();
+ }
+ if(!queryOK) {
+ info.shaderCompilerAvailable = Boolean.valueOf(true);
}
- info.shaderCompilerAvailable = new Boolean(v);
} else if( gl.isGL2ES2() ) {
info.shaderCompilerAvailable = new Boolean(true);
} else {
@@ -200,22 +218,29 @@ public class ShaderUtil {
return info.shaderCompilerAvailable.booleanValue();
}
- public static void shaderSource(GL _gl, int shader, CharSequence[] source)
+ /** Returns true if GeometryShader is supported, i.e. whether GLContext is &ge; 3.2 or ARB_geometry_shader4 extension is available. */
+ public static boolean isGeometryShaderSupported(final GL _gl) {
+ final GLContext ctx = _gl.getContext();
+ return ctx.getGLVersionNumber().compareTo(GLContext.Version320) >= 0 ||
+ ctx.isExtensionAvailable(GLExtensions.ARB_geometry_shader4);
+ }
+
+ public static void shaderSource(final GL _gl, final int shader, final CharSequence[] source)
{
final GL2ES2 gl = _gl.getGL2ES2();
if(!isShaderCompilerAvailable(_gl)) {
throw new GLException("No compiler is available");
}
- int count = (null!=source)?source.length:0;
+ final int count = (null!=source)?source.length:0;
if(count==0) {
throw new GLException("No sources specified");
}
- IntBuffer lengths = Buffers.newDirectIntBuffer(count);
+ final IntBuffer lengths = Buffers.newDirectIntBuffer(count);
for(int i=0; i<count; i++) {
lengths.put(i, source[i].length());
- }
+ }
if(source instanceof String[]) {
// rare case ..
gl.glShaderSource(shader, count, (String[])source, lengths);
@@ -224,10 +249,10 @@ public class ShaderUtil {
for(int i = source.length - 1; i>=0; i--) {
final CharSequence csq = source[i];
if(csq instanceof String) {
- // if ShaderCode.create(.. mutableStringBuffer == false )
+ // if ShaderCode.create(.. mutableStringBuilder == false )
tmp[i] = (String) csq;
} else {
- // if ShaderCode.create(.. mutableStringBuffer == true )
+ // if ShaderCode.create(.. mutableStringBuilder == true )
tmp[i] = source[i].toString();
}
}
@@ -235,10 +260,10 @@ public class ShaderUtil {
}
}
- public static void shaderSource(GL _gl, IntBuffer shaders, CharSequence[][] sources)
+ public static void shaderSource(final GL _gl, final IntBuffer shaders, final CharSequence[][] sources)
{
- int sourceNum = (null!=sources)?sources.length:0;
- int shaderNum = (null!=shaders)?shaders.remaining():0;
+ final int sourceNum = (null!=sources)?sources.length:0;
+ final int shaderNum = (null!=shaders)?shaders.remaining():0;
if(shaderNum<=0 || sourceNum<=0 || shaderNum!=sourceNum) {
throw new GLException("Invalid number of shaders and/or sources: shaders="+
shaderNum+", sources="+sourceNum);
@@ -248,28 +273,28 @@ public class ShaderUtil {
}
}
- public static void shaderBinary(GL _gl, IntBuffer shaders, int binFormat, java.nio.Buffer bin)
+ public static void shaderBinary(final GL _gl, final IntBuffer shaders, final int binFormat, final java.nio.Buffer bin)
{
final GL2ES2 gl = _gl.getGL2ES2();
if(getShaderBinaryFormats(gl).size()<=0) {
throw new GLException("No binary formats are supported");
}
- int shaderNum = shaders.remaining();
+ final int shaderNum = shaders.remaining();
if(shaderNum<=0) {
throw new GLException("No shaders specified");
}
if(null==bin) {
throw new GLException("Null shader binary");
}
- int binLength = bin.remaining();
+ final int binLength = bin.remaining();
if(0>=binLength) {
throw new GLException("Empty shader binary (remaining == 0)");
}
gl.glShaderBinary(shaderNum, shaders, binFormat, bin, binLength);
}
- public static void compileShader(GL _gl, IntBuffer shaders)
+ public static void compileShader(final GL _gl, final IntBuffer shaders)
{
final GL2ES2 gl = _gl.getGL2ES2();
for (int i = shaders.position(); i < shaders.limit(); i++) {
@@ -277,7 +302,7 @@ public class ShaderUtil {
}
}
- public static void attachShader(GL _gl, int program, IntBuffer shaders)
+ public static void attachShader(final GL _gl, final int program, final IntBuffer shaders)
{
final GL2ES2 gl = _gl.getGL2ES2();
for (int i = shaders.position(); i < shaders.limit(); i++) {
@@ -285,7 +310,7 @@ public class ShaderUtil {
}
}
- public static void detachShader(GL _gl, int program, IntBuffer shaders)
+ public static void detachShader(final GL _gl, final int program, final IntBuffer shaders)
{
final GL2ES2 gl = _gl.getGL2ES2();
for (int i = shaders.position(); i < shaders.limit(); i++) {
@@ -293,7 +318,7 @@ public class ShaderUtil {
}
}
- public static void deleteShader(GL _gl, IntBuffer shaders)
+ public static void deleteShader(final GL _gl, final IntBuffer shaders)
{
final GL2ES2 gl = _gl.getGL2ES2();
for (int i = shaders.position(); i < shaders.limit(); i++) {
@@ -302,9 +327,9 @@ public class ShaderUtil {
}
}
- public static boolean createAndLoadShader(GL _gl, IntBuffer shader, int shaderType,
- int binFormat, java.nio.Buffer bin,
- PrintStream verboseOut)
+ public static boolean createAndLoadShader(final GL _gl, final IntBuffer shader, final int shaderType,
+ final int binFormat, final java.nio.Buffer bin,
+ final PrintStream verboseOut)
{
final GL2ES2 gl = _gl.getGL2ES2();
int err = gl.glGetError(); // flush previous errors ..
@@ -313,7 +338,7 @@ public class ShaderUtil {
}
createShader(gl, shaderType, shader);
- err = gl.glGetError();
+ err = gl.glGetError();
if(err!=GL.GL_NO_ERROR) {
throw new GLException("createAndLoadShader: CreateShader failed, GL Error: 0x"+Integer.toHexString(err));
}
@@ -327,9 +352,9 @@ public class ShaderUtil {
return err == GL.GL_NO_ERROR;
}
- public static boolean createAndCompileShader(GL _gl, IntBuffer shader, int shaderType,
- CharSequence[][] sources,
- PrintStream verboseOut)
+ public static boolean createAndCompileShader(final GL _gl, final IntBuffer shader, final int shaderType,
+ final CharSequence[][] sources,
+ final PrintStream verboseOut)
{
final GL2ES2 gl = _gl.getGL2ES2();
int err = gl.glGetError(); // flush previous errors ..
@@ -338,34 +363,34 @@ public class ShaderUtil {
}
createShader(gl, shaderType, shader);
- err = gl.glGetError();
+ err = gl.glGetError();
if(err!=GL.GL_NO_ERROR) {
throw new GLException("createAndCompileShader: CreateShader failed, GL Error: 0x"+Integer.toHexString(err));
}
shaderSource(gl, shader, sources);
- err = gl.glGetError();
+ err = gl.glGetError();
if(err!=GL.GL_NO_ERROR) {
throw new GLException("createAndCompileShader: ShaderSource failed, GL Error: 0x"+Integer.toHexString(err));
}
compileShader(gl, shader);
- err = gl.glGetError();
+ err = gl.glGetError();
if(err!=GL.GL_NO_ERROR && null!=verboseOut) {
verboseOut.println("createAndCompileShader: CompileShader failed, GL Error: 0x"+Integer.toHexString(err));
}
return isShaderStatusValid(gl, shader, GL2ES2.GL_COMPILE_STATUS, verboseOut) && err == GL.GL_NO_ERROR;
}
-
+
private static final String implObjectKey = "com.jogamp.opengl.util.glsl.ShaderUtil" ;
-
+
private static class ProfileInformation {
Boolean shaderCompilerAvailable = null;
Set<Integer> shaderBinaryFormats = null;
- }
+ }
- private static ProfileInformation getProfileInformation(GL gl) {
+ private static ProfileInformation getProfileInformation(final GL gl) {
final GLContext context = gl.getContext();
context.validateCurrent();
ProfileInformation data = (ProfileInformation) context.getAttachedObject(implObjectKey);
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java
index d92a7aa22..1ed875f27 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java
@@ -4,26 +4,45 @@
package com.jogamp.opengl.util.glsl.fixedfunc;
-import javax.media.opengl.*;
-import javax.media.opengl.fixedfunc.*;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.fixedfunc.GLPointerFuncUtil;
+
+import jogamp.opengl.util.glsl.fixedfunc.FixedFuncHook;
+import jogamp.opengl.util.glsl.fixedfunc.FixedFuncImpl;
+import jogamp.opengl.util.glsl.fixedfunc.FixedFuncPipeline;
+
+import com.jogamp.opengl.util.PMVMatrix;
-import jogamp.opengl.util.glsl.fixedfunc.*;
/**
* Tool to pipeline GL2ES2 into a fixed function emulation implementing GL2ES1.
*/
public class FixedFuncUtil {
/**
+ * @param gl
+ * @param mode one of the {@link ShaderSelectionMode}s
+ * @param pmvMatrix optional pass through PMVMatrix for the {@link FixedFuncHook} and {@link FixedFuncPipeline}
* @return If gl is a GL2ES1 and force is false, return the type cast object,
* otherwise create a fixed function emulation pipeline using the given GL2ES2 impl
* and hook it to the GLContext via {@link GLContext#setGL(GL)}.
* @throws GLException if the GL object is neither GL2ES1 nor GL2ES2
+ *
+ * @see ShaderSelectionMode#AUTO
+ * @see ShaderSelectionMode#COLOR
+ * @see ShaderSelectionMode#COLOR_LIGHT_PER_VERTEX
+ * @see ShaderSelectionMode#COLOR_TEXTURE
+ * @see ShaderSelectionMode#COLOR_TEXTURE_LIGHT_PER_VERTEX
*/
- public static final GL2ES1 wrapFixedFuncEmul(GL gl, boolean force) {
+ public static final GL2ES1 wrapFixedFuncEmul(final GL gl, final ShaderSelectionMode mode, final PMVMatrix pmvMatrix, final boolean force, final boolean verbose) {
if(gl.isGL2ES2() && ( !gl.isGL2ES1() || force ) ) {
- GL2ES2 es2 = gl.getGL2ES2();
- FixedFuncHook hook = new FixedFuncHook(es2);
- FixedFuncImpl impl = new FixedFuncImpl(es2, hook);
+ final GL2ES2 es2 = gl.getGL2ES2();
+ final FixedFuncHook hook = new FixedFuncHook(es2, mode, pmvMatrix);
+ hook.setVerbose(verbose);
+ final FixedFuncImpl impl = new FixedFuncImpl(es2, hook);
gl.getContext().setGL(impl);
return impl;
} else if(gl.isGL2ES1()) {
@@ -33,21 +52,30 @@ public class FixedFuncUtil {
}
/**
+ * @param gl
+ * @param mode one of the {@link ShaderSelectionMode}s
+ * @param pmvMatrix optional pass through PMVMatrix for the {@link FixedFuncHook} and {@link FixedFuncPipeline}
* @return If gl is a GL2ES1, return the type cast object,
* otherwise create a fixed function emulation pipeline using the GL2ES2 impl.
* and hook it to the GLContext via {@link GLContext#setGL(GL)}.
* @throws GLException if the GL object is neither GL2ES1 nor GL2ES2
+ *
+ * @see ShaderSelectionMode#AUTO
+ * @see ShaderSelectionMode#COLOR
+ * @see ShaderSelectionMode#COLOR_LIGHT_PER_VERTEX
+ * @see ShaderSelectionMode#COLOR_TEXTURE
+ * @see ShaderSelectionMode#COLOR_TEXTURE_LIGHT_PER_VERTEX
*/
- public static final GL2ES1 wrapFixedFuncEmul(GL gl) {
- return wrapFixedFuncEmul(gl, false);
+ public static final GL2ES1 wrapFixedFuncEmul(final GL gl, final ShaderSelectionMode mode, final PMVMatrix pmvMatrix) {
+ return wrapFixedFuncEmul(gl, mode, null, false, false);
}
/**
- * Mapping fixed function (client) array indices to
+ * Mapping fixed function (client) array indices to
* GLSL array attribute names.
*
* Useful for uniq mapping of canonical array index names as listed.
- *
+ *
* @see #mgl_Vertex
* @see javax.media.opengl.fixedfunc.GLPointerFunc#GL_VERTEX_ARRAY
* @see #mgl_Normal
@@ -62,7 +90,7 @@ public class FixedFuncUtil {
* @see javax.media.opengl.fixedfunc.GLPointerFunc#glNormalPointer
* @see javax.media.opengl.fixedfunc.GLPointerFunc#glTexCoordPointer
*/
- public static String getPredefinedArrayIndexName(int glArrayIndex) {
+ public static String getPredefinedArrayIndexName(final int glArrayIndex) {
return GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex);
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/ShaderSelectionMode.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/ShaderSelectionMode.java
new file mode 100644
index 000000000..426fb0d85
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/ShaderSelectionMode.java
@@ -0,0 +1,27 @@
+package com.jogamp.opengl.util.glsl.fixedfunc;
+
+/**
+ * Shader selection mode
+ *
+ * @see ShaderSelectionMode#AUTO
+ * @see ShaderSelectionMode#COLOR
+ * @see ShaderSelectionMode#COLOR_LIGHT_PER_VERTEX
+ * @see ShaderSelectionMode#COLOR_TEXTURE
+ * @see ShaderSelectionMode#COLOR_TEXTURE_LIGHT_PER_VERTEX
+ */
+public enum ShaderSelectionMode {
+ /** Auto shader selection, based upon FFP states. */
+ AUTO,
+ /** Fixed shader selection: Simple color. */
+ COLOR,
+ /** Fixed shader selection: Multi-Textured color. 2 texture units. */
+ COLOR_TEXTURE2,
+ /** Fixed shader selection: Multi-Textured color. 4 texture units. */
+ COLOR_TEXTURE4,
+ /** Fixed shader selection: Multi-Textured color. 8 texture units. */
+ COLOR_TEXTURE8,
+ /** Fixed shader selection: Color with vertex-lighting. */
+ COLOR_LIGHT_PER_VERTEX,
+ /** Fixed shader selection: Multi-Textured color with vertex-lighting. 8 texture units.*/
+ COLOR_TEXTURE8_LIGHT_PER_VERTEX
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java
index a5b1c6687..1d629131e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java
@@ -30,7 +30,7 @@ public abstract class CompileShader {
public abstract String getFragmentShaderCompiler();
- public void processOneShader(String resourceName)
+ public void processOneShader(final String resourceName)
throws IOException, UnsupportedEncodingException, InterruptedException
{
int type = -1;
@@ -49,31 +49,31 @@ public abstract class CompileShader {
suffixLen = 4;
type = GL2ES2.GL_VERTEX_SHADER;
}
- String justName = basename(resourceName);
+ final String justName = basename(resourceName);
outName = justName.substring(0, justName.length() - suffixLen) +
ShaderCode.getFileSuffix(true, type);
- URL resourceURL = IOUtil.getResource(null, resourceName).getURL();
- String dirName = dirname(resourceURL.getPath());
+ final URL resourceURL = IOUtil.getResource(null, resourceName).getURL();
+ final String dirName = dirname(resourceURL.getPath());
- outName = dirName + File.separator + "bin" + File.separator +
- ShaderCode.getBinarySubPath(getBinaryFormat()) + File.separator +
+ outName = dirName + File.separator + "bin" + File.separator +
+ ShaderCode.getBinarySubPath(getBinaryFormat()) + File.separator +
outName;
processOneShader(resourceName, outName, type);
}
- public void processOneShader(String resourceName, String outName, int type)
+ public void processOneShader(final String resourceName, final String outName, final int type)
throws IOException, UnsupportedEncodingException, InterruptedException
{
- URL resourceURL = IOUtil.getResource(null, resourceName).getURL();
- String dirName = dirname(resourceURL.getPath());
+ final URL resourceURL = IOUtil.getResource(null, resourceName).getURL();
+ final String dirName = dirname(resourceURL.getPath());
- CharSequence shader = ShaderCode.readShaderSource(null, resourceName, false);
+ final CharSequence shader = ShaderCode.readShaderSource(null, resourceName, false);
if(null==shader) {
System.err.println("Can't find shader source " + resourceName + " - ignored");
return;
}
System.err.println("Preprocessing: "+ resourceName+", in dir: "+dirName);
- String justName = basename(resourceName);
+ final String justName = basename(resourceName);
String processor;
switch (type) {
case GL2ES2.GL_VERTEX_SHADER:
@@ -85,38 +85,37 @@ public abstract class CompileShader {
default:
throw new GLException("Unknown shader type: "+type);
}
- File outputFile = new File(outName);
+ final File outputFile = new File(outName);
// Write shader to a file in java.io.tmpdir
- File tmpDir = new File(dirName+File.separator+"tmp");
+ final File tmpDir = new File(dirName+File.separator+"tmp");
tmpDir.mkdirs();
- File tmpFile = new File(tmpDir, justName);
- Writer writer = new BufferedWriter(new FileWriter(tmpFile));
+ final File tmpFile = new File(tmpDir, justName);
+ final Writer writer = new BufferedWriter(new FileWriter(tmpFile));
writer.write(shader.toString(), 0, shader.length());
writer.flush();
writer.close();
System.err.println("Preprocessed: "+ tmpFile.getAbsolutePath());
- File processorDir = getSDKCompilerDir();
+ final File processorDir = getSDKCompilerDir();
System.err.println("SDK: "+ processorDir.getAbsolutePath() + ", compiler: "+processor);
System.err.println("Output: "+ outputFile.getAbsolutePath());
// Run the tool
- Process process = Runtime.getRuntime().exec(new String[] {
+ final Process process = Runtime.getRuntime().exec(new String[] {
processorDir.getAbsolutePath() + File.separator + processor,
tmpFile.getAbsolutePath(),
outputFile.getAbsolutePath()
}); // , null, processorDir);
- new StreamMonitor(process.getInputStream());
- new StreamMonitor(process.getErrorStream());
+ new IOUtil.StreamMonitor( new InputStream[] { process.getInputStream(), process.getErrorStream() }, System.out, null );
process.waitFor();
// Delete the temporary file
// tmpFile.delete();
}
- protected static String basename(String path) {
+ protected static String basename(final String path) {
int lastSlash = path.lastIndexOf("/");
if (lastSlash < 0) {
lastSlash = path.lastIndexOf("\\");
@@ -130,57 +129,27 @@ public abstract class CompileShader {
return basename;
}
- protected static String dirname(String path) {
+ protected static String dirname(final String path) {
int lastSlash = path.lastIndexOf("/");
if (lastSlash < 0) {
lastSlash = path.lastIndexOf("\\");
}
String dirname;
if (lastSlash < 0) {
- dirname = new String();
+ dirname = "";
} else {
dirname = path.substring(0, lastSlash + 1);
}
return dirname;
}
- public void run(String[] args) {
+ public void run(final String[] args) {
try {
for (int i = 0; i < args.length; i++) {
processOneShader(args[i]);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
}
-
- private static class StreamMonitor implements Runnable {
- private InputStream istream;
- public StreamMonitor(InputStream stream) {
- istream = stream;
- new Thread(this, "Output Reader Thread").start();
- }
-
- public void run()
- {
- byte[] buffer = new byte[4096];
- try {
- int numRead = 0;
- do {
- numRead = istream.read(buffer);
- if (numRead > 0) {
- System.out.write(buffer, 0, numRead);
- System.out.flush();
- }
- } while (numRead >= 0);
- }
- catch (IOException e) {
- try {
- istream.close();
- } catch (IOException e2) {
- }
- // Should allow clean exit when process shuts down
- }
- }
- }
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java
index 8eb9ef579..9ff37c7ee 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java
@@ -13,7 +13,7 @@ public class CompileShaderNVidia extends CompileShader {
private static final String NVAPSDK;
static {
- String nvapSDKProp = System.getProperty("NVAPSDK");
+ final String nvapSDKProp = System.getProperty("NVAPSDK");
if (nvapSDKProp != null) {
NVAPSDK = nvapSDKProp;
} else {
@@ -21,10 +21,12 @@ public class CompileShaderNVidia extends CompileShader {
}
}
+ @Override
public int getBinaryFormat() {
return GLES2.GL_NVIDIA_PLATFORM_BINARY_NV;
}
+ @Override
public File getSDKCompilerDir() {
File compilerDir = new File( NVAPSDK + File.separator + "tools" + File.separator );
File compilerFile = new File( compilerDir, getVertexShaderCompiler());
@@ -39,15 +41,17 @@ public class CompileShaderNVidia extends CompileShader {
return compilerDir;
}
+ @Override
public String getVertexShaderCompiler() {
return "glslv.bat";
}
+ @Override
public String getFragmentShaderCompiler() {
return "glslf.bat";
}
- public static void main(String[] args) {
+ public static void main(final String[] args) {
new CompileShaderNVidia().run(args);
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/BackingStoreManager.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/BackingStoreManager.java
index 7b6a1b479..c1b5025f8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/packrect/BackingStoreManager.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/BackingStoreManager.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/Level.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/Level.java
index 5ba3f7330..e694f1b33 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/packrect/Level.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/Level.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -42,29 +42,29 @@ package com.jogamp.opengl.util.packrect;
import java.util.*;
public class Level {
- private int width;
+ private final int width;
private int height;
- private int yPos;
- private LevelSet holder;
+ private final int yPos;
+ private final LevelSet holder;
- private List/*<Rect>*/ rects = new ArrayList/*<Rect>*/();
- private List/*<Rect>*/ freeList;
+ private final List<Rect> rects = new ArrayList<Rect>();
+ private List<Rect> freeList;
private int nextAddX;
- static class RectXComparator implements Comparator {
- public int compare(Object o1, Object o2) {
- Rect r1 = (Rect) o1;
- Rect r2 = (Rect) o2;
+ static class RectXComparator implements Comparator<Rect> {
+ @Override
+ public int compare(final Rect r1, final Rect r2) {
return r1.x() - r2.x();
}
- public boolean equals(Object obj) {
+ @Override
+ public boolean equals(final Object obj) {
return this == obj;
}
}
- private static final Comparator rectXComparator = new RectXComparator();
+ private static final Comparator<Rect> rectXComparator = new RectXComparator();
- public Level(int width, int height, int yPos, LevelSet holder) {
+ public Level(final int width, final int height, final int yPos, final LevelSet holder) {
this.width = width;
this.height = height;
this.yPos = yPos;
@@ -80,7 +80,7 @@ public class Level {
in the RectanglePacker and allocation from the free list. More
disruptive changes like compaction of the level must be
requested explicitly. */
- public boolean add(Rect rect) {
+ public boolean add(final Rect rect) {
if (rect.h() > height) {
// See whether it's worth trying to expand vertically
if (nextAddX + rect.w() > width) {
@@ -108,8 +108,8 @@ public class Level {
// See whether we can add from the free list
if (freeList != null) {
Rect candidate = null;
- for (Iterator iter = freeList.iterator(); iter.hasNext(); ) {
- Rect cur = (Rect) iter.next();
+ for (final Iterator<Rect> iter = freeList.iterator(); iter.hasNext(); ) {
+ final Rect cur = iter.next();
if (cur.canContain(rect)) {
candidate = cur;
break;
@@ -128,7 +128,7 @@ public class Level {
candidate.setSize(candidate.w() - rect.w(), height);
freeList.add(candidate);
}
-
+
coalesceFreeList();
return true;
@@ -139,7 +139,7 @@ public class Level {
}
/** Removes the given Rect from this Level. */
- public boolean remove(Rect rect) {
+ public boolean remove(final Rect rect) {
if (!rects.remove(rect))
return false;
@@ -149,7 +149,7 @@ public class Level {
nextAddX -= rect.w();
} else {
if (freeList == null) {
- freeList = new ArrayList/*<Rect>*/();
+ freeList = new ArrayList<Rect>();
}
freeList.add(new Rect(rect.x(), rect.y(), rect.w(), height, null));
coalesceFreeList();
@@ -165,14 +165,14 @@ public class Level {
/** Indicates whether this Level could satisfy an allocation request
if it were compacted. */
- public boolean couldAllocateIfCompacted(Rect rect) {
+ public boolean couldAllocateIfCompacted(final Rect rect) {
if (rect.h() > height)
return false;
if (freeList == null)
return false;
int freeListWidth = 0;
- for (Iterator iter = freeList.iterator(); iter.hasNext(); ) {
- Rect cur = (Rect) iter.next();
+ for (final Iterator<Rect> iter = freeList.iterator(); iter.hasNext(); ) {
+ final Rect cur = iter.next();
freeListWidth += cur.w();
}
// Add on the remaining space at the end
@@ -180,12 +180,12 @@ public class Level {
return (freeListWidth >= rect.w());
}
- public void compact(Object backingStore, BackingStoreManager manager) {
+ public void compact(final Object backingStore, final BackingStoreManager manager) {
Collections.sort(rects, rectXComparator);
int nextCompactionDest = 0;
manager.beginMovement(backingStore, backingStore);
- for (Iterator iter = rects.iterator(); iter.hasNext(); ) {
- Rect cur = (Rect) iter.next();
+ for (final Iterator<Rect> iter = rects.iterator(); iter.hasNext(); ) {
+ final Rect cur = iter.next();
if (cur.x() != nextCompactionDest) {
manager.move(backingStore, cur,
backingStore, new Rect(nextCompactionDest, cur.y(), cur.w(), cur.h(), null));
@@ -198,14 +198,14 @@ public class Level {
manager.endMovement(backingStore, backingStore);
}
- public Iterator iterator() {
+ public Iterator<Rect> iterator() {
return rects.iterator();
}
/** Visits all Rects contained in this Level. */
- public void visit(RectVisitor visitor) {
- for (Iterator iter = rects.iterator(); iter.hasNext(); ) {
- Rect rect = (Rect) iter.next();
+ public void visit(final RectVisitor visitor) {
+ for (final Iterator<Rect> iter = rects.iterator(); iter.hasNext(); ) {
+ final Rect rect = iter.next();
visitor.visit(rect);
}
}
@@ -216,8 +216,8 @@ public class Level {
original Rects. */
public void updateRectangleReferences() {
for (int i = 0; i < rects.size(); i++) {
- Rect cur = (Rect) rects.get(i);
- Rect next = cur.getNextLocation();
+ final Rect cur = rects.get(i);
+ final Rect next = cur.getNextLocation();
next.setPosition(cur.x(), cur.y());
if (cur.w() != next.w() || cur.h() != next.h())
throw new RuntimeException("Unexpected disparity in rectangle sizes during updateRectangleReferences");
@@ -235,8 +235,8 @@ public class Level {
Collections.sort(freeList, rectXComparator);
int i = 0;
while (i < freeList.size() - 1) {
- Rect r1 = (Rect) freeList.get(i);
- Rect r2 = (Rect) freeList.get(i+1);
+ final Rect r1 = freeList.get(i);
+ final Rect r2 = freeList.get(i+1);
if (r1.maxX() + 1 == r2.x()) {
// Coalesce r1 and r2 into one block
freeList.remove(i+1);
@@ -246,7 +246,7 @@ public class Level {
}
}
// See whether the last block bumps up against the addition point
- Rect last = (Rect) freeList.get(freeList.size() - 1);
+ final Rect last = freeList.get(freeList.size() - 1);
if (last.maxX() + 1 == nextAddX) {
nextAddX -= last.w();
freeList.remove(freeList.size() - 1);
@@ -262,8 +262,8 @@ public class Level {
public void dumpFreeSpace() {
int freeListWidth = 0;
- for (Iterator iter = freeList.iterator(); iter.hasNext(); ) {
- Rect cur = (Rect) iter.next();
+ for (final Iterator<Rect> iter = freeList.iterator(); iter.hasNext(); ) {
+ final Rect cur = iter.next();
System.err.println(" Free rectangle at " + cur);
freeListWidth += cur.w();
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/LevelSet.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/LevelSet.java
index 6783aec3b..803ca28cf 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/packrect/LevelSet.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/LevelSet.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -47,14 +47,14 @@ import java.util.*;
public class LevelSet {
// Maintained in sorted order by increasing Y coordinate
- private List/*<Level>*/ levels = new ArrayList/*<Level>*/();
+ private final List<Level> levels = new ArrayList<Level>();
private int nextAddY;
- private int w;
+ private final int w;
private int h;
/** A LevelSet manages all of the backing store for a region of a
specified width and height. */
- public LevelSet(int w, int h) {
+ public LevelSet(final int w, final int h) {
this.w = w;
this.h = h;
}
@@ -66,14 +66,14 @@ public class LevelSet {
the LevelSet given its current dimensions, false if not. Caller
is responsible for performing compaction, expansion, etc. as a
consequence. */
- public boolean add(Rect rect) {
+ public boolean add(final Rect rect) {
if (rect.w() > w)
return false;
// Go in reverse order through the levels seeing whether we can
// trivially satisfy the allocation request
for (int i = levels.size() - 1; i >= 0; --i) {
- Level level = (Level) levels.get(i);
+ final Level level = levels.get(i);
if (level.add(rect))
return true;
}
@@ -82,7 +82,7 @@ public class LevelSet {
// increases the computational complexity of the addition process,
// but prevents us from expanding unnecessarily.
for (int i = levels.size() - 1; i >= 0; --i) {
- Level level = (Level) levels.get(i);
+ final Level level = levels.get(i);
if (level.couldAllocateIfCompacted(rect))
return false;
}
@@ -92,23 +92,23 @@ public class LevelSet {
if (nextAddY + rect.h() > h)
return false;
- Level newLevel = new Level(w, rect.h(), nextAddY, this);
+ final Level newLevel = new Level(w, rect.h(), nextAddY, this);
levels.add(newLevel);
nextAddY += rect.h();
- boolean res = newLevel.add(rect);
+ final boolean res = newLevel.add(rect);
if (!res)
throw new RuntimeException("Unexpected failure in addition to new Level");
return true;
}
/** Removes the given Rect from this LevelSet. */
- public boolean remove(Rect rect) {
+ public boolean remove(final Rect rect) {
for (int i = levels.size() - 1; i >= 0; --i) {
- Level level = (Level) levels.get(i);
+ final Level level = levels.get(i);
if (level.remove(rect))
return true;
}
-
+
return false;
}
@@ -116,14 +116,14 @@ public class LevelSet {
if necessary. This is the correct fallback path to {@link
#add(Rect)} above. Returns true if allocated successfully, false
otherwise (indicating the need to expand the backing store). */
- public boolean compactAndAdd(Rect rect,
- Object backingStore,
- BackingStoreManager manager) {
+ public boolean compactAndAdd(final Rect rect,
+ final Object backingStore,
+ final BackingStoreManager manager) {
for (int i = levels.size() - 1; i >= 0; --i) {
- Level level = (Level) levels.get(i);
+ final Level level = levels.get(i);
if (level.couldAllocateIfCompacted(rect)) {
level.compact(backingStore, manager);
- boolean res = level.add(rect);
+ final boolean res = level.add(rect);
if (!res)
throw new RuntimeException("Unexpected failure to add after compaction");
return true;
@@ -136,7 +136,7 @@ public class LevelSet {
/** Indicates whether it's legal to trivially increase the height of
the given Level. This is only possible if it's the last Level
added and there's enough room in the backing store. */
- public boolean canExpand(Level level, int height) {
+ public boolean canExpand(final Level level, final int height) {
if (levels.isEmpty())
return false; // Should not happen
if (levels.get(levels.size() - 1) == level &&
@@ -145,7 +145,7 @@ public class LevelSet {
return false;
}
- public void expand(Level level, int oldHeight, int newHeight) {
+ public void expand(final Level level, final int oldHeight, final int newHeight) {
nextAddY += (newHeight - oldHeight);
}
@@ -156,7 +156,7 @@ public class LevelSet {
/** Sets the height of this LevelSet. It is only legal to reduce the
height to greater than or equal to the currently used height. */
- public void setHeight(int height) throws IllegalArgumentException {
+ public void setHeight(final int height) throws IllegalArgumentException {
if (height < getUsedHeight()) {
throw new IllegalArgumentException("May not reduce height below currently used height");
}
@@ -170,11 +170,11 @@ public class LevelSet {
it may be profitable to perform a compaction. */
public float verticalFragmentationRatio() {
int freeHeight = 0;
- int usedHeight = getUsedHeight();
+ final int usedHeight = getUsedHeight();
if (usedHeight == 0)
return 0.0f;
- for (Iterator iter = iterator(); iter.hasNext(); ) {
- Level level = (Level) iter.next();
+ for (final Iterator<Level> iter = iterator(); iter.hasNext(); ) {
+ final Level level = iter.next();
if (level.isEmpty()) {
freeHeight += level.h();
}
@@ -182,14 +182,14 @@ public class LevelSet {
return (float) freeHeight / (float) usedHeight;
}
- public Iterator iterator() {
+ public Iterator<Level> iterator() {
return levels.iterator();
}
/** Visits all Rects contained in this LevelSet. */
- public void visit(RectVisitor visitor) {
- for (Iterator iter = levels.iterator(); iter.hasNext(); ) {
- Level level = (Level) iter.next();
+ public void visit(final RectVisitor visitor) {
+ for (final Iterator<Level> iter = levels.iterator(); iter.hasNext(); ) {
+ final Level level = iter.next();
level.visit(visitor);
}
}
@@ -199,8 +199,8 @@ public class LevelSet {
update the new Rects in a newly laid-out LevelSet with the
original Rects. */
public void updateRectangleReferences() {
- for (Iterator iter = levels.iterator(); iter.hasNext(); ) {
- Level level = (Level) iter.next();
+ for (final Iterator<Level> iter = levels.iterator(); iter.hasNext(); ) {
+ final Level level = iter.next();
level.updateRectangleReferences();
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/Rect.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/Rect.java
index 6206c4a11..cbf6b933c 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/packrect/Rect.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/Rect.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -72,16 +72,16 @@ public class Rect {
// there is no room left due either to fragmentation or just being
// out of space)
private Rect nextLocation;
-
+
public Rect() {
this(null);
}
- public Rect(Object userData) {
+ public Rect(final Object userData) {
this(0, 0, 0, 0, userData);
}
- public Rect(int x, int y, int w, int h, Object userData) {
+ public Rect(final int x, final int y, final int w, final int h, final Object userData) {
setPosition(x, y);
setSize(w, h);
setUserData(userData);
@@ -94,7 +94,7 @@ public class Rect {
public Object getUserData() { return userData; }
public Rect getNextLocation() { return nextLocation; }
- public void setPosition(int x, int y) {
+ public void setPosition(final int x, final int y) {
if (x < 0)
throw new IllegalArgumentException("Negative x");
if (y < 0)
@@ -103,7 +103,7 @@ public class Rect {
this.y = y;
}
- public void setSize(int w, int h) throws IllegalArgumentException {
+ public void setSize(final int w, final int h) throws IllegalArgumentException {
if (w < 0)
throw new IllegalArgumentException("Negative width");
if (h < 0)
@@ -112,8 +112,8 @@ public class Rect {
this.h = h;
}
- public void setUserData(Object obj) { userData = obj; }
- public void setNextLocation(Rect nextLocation) { this.nextLocation = nextLocation; }
+ public void setUserData(final Object obj) { userData = obj; }
+ public void setNextLocation(final Rect nextLocation) { this.nextLocation = nextLocation; }
// Helpers for computations.
@@ -139,11 +139,12 @@ public class Rect {
return y() + h() - 1;
}
- public boolean canContain(Rect other) {
+ public boolean canContain(final Rect other) {
return (w() >= other.w() &&
h() >= other.h());
}
+ @Override
public String toString() {
return "[Rect x: " + x() + " y: " + y() + " w: " + w() + " h: " + h() + "]";
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/RectVisitor.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/RectVisitor.java
index 49cfc82e6..5db216742 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/packrect/RectVisitor.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/RectVisitor.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/RectanglePacker.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/RectanglePacker.java
index 1496a04a6..794ae4493 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/packrect/RectanglePacker.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/RectanglePacker.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -48,34 +48,34 @@ import java.util.*;
backing store, when necessary. */
public class RectanglePacker {
- private BackingStoreManager manager;
+ private final BackingStoreManager manager;
private Object backingStore;
private LevelSet levels;
- private float EXPANSION_FACTOR = 0.5f;
- private float SHRINK_FACTOR = 0.3f;
+ private static final float EXPANSION_FACTOR = 0.5f;
+ private static final float SHRINK_FACTOR = 0.3f;
- private int initialWidth;
- private int initialHeight;
+ private final int initialWidth;
+ private final int initialHeight;
private int maxWidth = -1;
private int maxHeight = -1;
- static class RectHComparator implements Comparator {
- public int compare(Object o1, Object o2) {
- Rect r1 = (Rect) o1;
- Rect r2 = (Rect) o2;
+ static class RectHComparator implements Comparator<Rect> {
+ @Override
+ public int compare(final Rect r1, final Rect r2) {
return r2.h() - r1.h();
}
- public boolean equals(Object obj) {
+ @Override
+ public boolean equals(final Object obj) {
return this == obj;
}
}
- private static final Comparator rectHComparator = new RectHComparator();
+ private static final Comparator<Rect> rectHComparator = new RectHComparator();
- public RectanglePacker(BackingStoreManager manager,
- int initialWidth,
- int initialHeight) {
+ public RectanglePacker(final BackingStoreManager manager,
+ final int initialWidth,
+ final int initialHeight) {
this.manager = manager;
levels = new LevelSet(initialWidth, initialHeight);
this.initialWidth = initialWidth;
@@ -95,7 +95,7 @@ public class RectanglePacker {
necessary. Setting up a maximum width and height introduces the
possibility that additions will fail; these are handled with the
BackingStoreManager's allocationFailed notification. */
- public void setMaxSize(int maxWidth, int maxHeight) {
+ public void setMaxSize(final int maxWidth, final int maxHeight) {
this.maxWidth = maxWidth;
this.maxHeight = maxHeight;
}
@@ -107,7 +107,7 @@ public class RectanglePacker {
BackingStoreManager#preExpand BackingStoreManager.preExpand}
does not clear enough space for the incoming rectangle, then
this method will throw a RuntimeException. */
- public void add(Rect rect) throws RuntimeException {
+ public void add(final Rect rect) throws RuntimeException {
// Allocate backing store if we don't have any yet
if (backingStore == null)
backingStore = manager.allocateBackingStore(levels.w(), levels.h());
@@ -143,12 +143,12 @@ public class RectanglePacker {
}
/** Removes the given rectangle from this RectanglePacker. */
- public void remove(Rect rect) {
+ public void remove(final Rect rect) {
levels.remove(rect);
}
/** Visits all Rects contained in this RectanglePacker. */
- public void visit(RectVisitor visitor) {
+ public void visit(final RectVisitor visitor) {
levels.visit(visitor);
}
@@ -168,7 +168,7 @@ public class RectanglePacker {
}
// The "cause" rect may be null
- private void compactImpl(Rect cause) {
+ private void compactImpl(final Rect cause) {
// Have to either expand, compact or both. Need to figure out what
// direction to go. Prefer to expand vertically. Expand
// horizontally only if rectangle being added is too wide. FIXME:
@@ -203,14 +203,14 @@ public class RectanglePacker {
}
nextLevelSet = new LevelSet(newWidth, newHeight);
-
+
// Make copies of all existing rectangles
- List/*<Rect>*/ newRects = new ArrayList/*<Rect>*/();
- for (Iterator i1 = levels.iterator(); i1.hasNext(); ) {
- Level level = (Level) i1.next();
- for (Iterator i2 = level.iterator(); i2.hasNext(); ) {
- Rect cur = (Rect) i2.next();
- Rect newRect = new Rect(0, 0, cur.w(), cur.h(), null);
+ final List<Rect> newRects = new ArrayList<Rect>();
+ for (final Iterator<Level> i1 = levels.iterator(); i1.hasNext(); ) {
+ final Level level = i1.next();
+ for (final Iterator<Rect> i2 = level.iterator(); i2.hasNext(); ) {
+ final Rect cur = i2.next();
+ final Rect newRect = new Rect(0, 0, cur.w(), cur.h(), null);
cur.setNextLocation(newRect);
// Hook up the reverse mapping too for easier replacement
newRect.setNextLocation(cur);
@@ -222,8 +222,8 @@ public class RectanglePacker {
Collections.sort(newRects, rectHComparator);
// Try putting all of these rectangles into the new level set
done = true;
- for (Iterator iter = newRects.iterator(); iter.hasNext(); ) {
- if (!nextLevelSet.add((Rect) iter.next())) {
+ for (final Iterator<Rect> iter = newRects.iterator(); iter.hasNext(); ) {
+ if (!nextLevelSet.add(iter.next())) {
done = false;
break;
}
@@ -268,13 +268,13 @@ public class RectanglePacker {
// new locations of rectangles on the backing store. Allocate a
// new backing store, move the contents over and deallocate the
// old one.
- Object newBackingStore = manager.allocateBackingStore(nextLevelSet.w(),
+ final Object newBackingStore = manager.allocateBackingStore(nextLevelSet.w(),
nextLevelSet.h());
manager.beginMovement(backingStore, newBackingStore);
- for (Iterator i1 = levels.iterator(); i1.hasNext(); ) {
- Level level = (Level) i1.next();
- for (Iterator i2 = level.iterator(); i2.hasNext(); ) {
- Rect cur = (Rect) i2.next();
+ for (final Iterator<Level> i1 = levels.iterator(); i1.hasNext(); ) {
+ final Level level = i1.next();
+ for (final Iterator<Rect> i2 = level.iterator(); i2.hasNext(); ) {
+ final Rect cur = i2.next();
manager.move(backingStore, cur,
newBackingStore, cur.getNextLocation());
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java
new file mode 100644
index 000000000..075da340b
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.stereo;
+
+import com.jogamp.opengl.math.FovHVHalves;
+
+/**
+ * Constant parameter for one eye.
+ */
+public final class EyeParameter {
+ /** Eye number, <code>0</code> for the left eye and <code>1</code> for the right eye. */
+ public final int number;
+
+ /** float[3] eye position vector used to define eye height in meter relative to <i>actor</i>. */
+ public final float[] positionOffset;
+
+ /** Field of view in both directions, may not be centered, either in radians or tangent. */
+ public final FovHVHalves fovhv;
+
+ /** IPD related horizontal distance from nose to pupil in meter. */
+ public final float distNoseToPupilX;
+
+ /** Vertical distance from middle-line to pupil in meter. */
+ public final float distMiddleToPupilY;
+
+ /** Z-axis eye relief in meter. */
+ public final float eyeReliefZ;
+
+ public EyeParameter(final int number, final float[] positionOffset, final FovHVHalves fovhv,
+ final float distNoseToPupil, final float verticalDelta, final float eyeRelief) {
+ this.number = number;
+ this.positionOffset = new float[3];
+ System.arraycopy(positionOffset, 0, this.positionOffset, 0, 3);
+ this.fovhv = fovhv;
+ this.distNoseToPupilX = distNoseToPupil;
+ this.distMiddleToPupilY = verticalDelta;
+ this.eyeReliefZ = eyeRelief;
+ }
+ public final String toString() {
+ return "EyeParam[num "+number+", posOff["+positionOffset[0]+", "+positionOffset[1]+", "+positionOffset[2]+"], "+fovhv+
+ ", distPupil[noseX "+distNoseToPupilX+", middleY "+distMiddleToPupilY+", reliefZ "+eyeReliefZ+"]]";
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/EyePose.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/EyePose.java
new file mode 100644
index 000000000..aa64ff130
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/EyePose.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.stereo;
+
+import com.jogamp.opengl.math.Quaternion;
+
+/**
+ * Position and orientation of one eye.
+ */
+public final class EyePose {
+ /** Eye number, <code>0</code> for the left eye and <code>1</code> for the right eye. */
+ public final int number;
+
+ /** float[3] eye position vector. */
+ public final float[] position;
+
+ /** Eye orientation */
+ public final Quaternion orientation;
+
+ public EyePose(final int number) {
+ this.number = number;
+ this.position = new float[3];
+ this.orientation = new Quaternion();
+ }
+ public EyePose(final int number, final float[] position, final Quaternion orientation) {
+ this(number);
+ set(position, orientation);
+ }
+
+ /** Set position and orientation of this instance. */
+ public final void set(final float[] position, final Quaternion orientation) {
+ System.arraycopy(position, 0, this.position, 0, 3);
+ this.orientation.set(orientation);
+ }
+ /** Set position and orientation of this instance. */
+ public final void setPosition(final float posX, final float posY, final float posZ) {
+ position[0] = posX;
+ position[1] = posY;
+ position[2] = posZ;
+ }
+ public final String toString() {
+ return "EyePose[num "+number+", pos["+position[0]+", "+position[1]+", "+position[2]+"], "+orientation+"]";
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java
new file mode 100644
index 000000000..f70ebf928
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java
@@ -0,0 +1,262 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.stereo;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+
+import jogamp.opengl.GLDrawableHelper;
+import jogamp.opengl.GLDrawableHelper.GLEventListenerAction;
+
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.FBObject.TextureAttachment;
+import com.jogamp.opengl.FBObject.Attachment.Type;
+import com.jogamp.opengl.util.CustomGLEventListener;
+
+/**
+ * {@link StereoClientRenderer} utilizing {@link StereoDeviceRenderer}
+ * implementing {@link GLEventListener} for convenience.
+ * <p>
+ * See {@link StereoDeviceRenderer} notes about <a href="StereoDeviceRenderer.html#asymFOVRendering">Correct Asymmetric FOV Rendering</a>.
+ * <p>
+ * Implementation renders {@link StereoGLEventListener}
+ * using one or more {@link FBObject} according to {@link StereoDeviceRenderer#getTextureCount()}.
+ * </p>
+ */
+public class StereoClientRenderer implements GLEventListener {
+ private final GLDrawableHelper helper;
+ private final StereoDeviceRenderer deviceRenderer;
+ private final boolean ownsDevice;
+ private final FBObject[] fbos;
+ private final int magFilter;
+ private final int minFilter;
+
+ private int numSamples;
+ private final TextureAttachment[] fboTexs;
+
+ public StereoClientRenderer(final StereoDeviceRenderer deviceRenderer, final boolean ownsDevice,
+ final int magFilter, final int minFilter, final int numSamples) {
+ final int fboCount = deviceRenderer.getTextureCount();
+ if( 0 > fboCount || 2 < fboCount ) {
+ throw new IllegalArgumentException("fboCount must be within [0..2], has "+fboCount+", due to "+deviceRenderer);
+ }
+ this.helper = new GLDrawableHelper();
+ this.deviceRenderer = deviceRenderer;
+ this.ownsDevice = ownsDevice;
+ this.magFilter = magFilter;
+ this.minFilter = minFilter;
+
+ this.numSamples = numSamples;
+
+ this.fbos = new FBObject[fboCount];
+ for(int i=0; i<fboCount; i++) {
+ this.fbos[i] = new FBObject();
+ }
+ this.fboTexs = new TextureAttachment[fboCount];
+ }
+
+ private void initFBOs(final GL gl, final DimensionImmutable size) {
+ for(int i=0; i<fbos.length; i++) {
+ fbos[i].init(gl, size.getWidth(), size.getHeight(), numSamples);
+ if( i>0 && fbos[i-1].getNumSamples() != fbos[i].getNumSamples()) {
+ throw new InternalError("sample size mismatch: \n\t0: "+fbos[i-1]+"\n\t1: "+fbos[i]);
+ }
+ numSamples = fbos[i].getNumSamples();
+
+ if(numSamples>0) {
+ fbos[i].attachColorbuffer(gl, 0, true); // MSAA requires alpha
+ fbos[i].attachRenderbuffer(gl, Type.DEPTH, FBObject.DEFAULT_BITS);
+ final FBObject ssink = new FBObject();
+ {
+ ssink.init(gl, size.getWidth(), size.getHeight(), 0);
+ ssink.attachTexture2D(gl, 0, false, magFilter, minFilter, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS);
+ }
+ fbos[i].setSamplingSink(ssink);
+ fbos[i].resetSamplingSink(gl); // validate
+ fboTexs[i] = fbos[i].getSamplingSink().getTextureAttachment();
+ } else {
+ fboTexs[i] = fbos[i].attachTexture2D(gl, 0, false, magFilter, minFilter, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ fbos[i].attachRenderbuffer(gl, Type.DEPTH, FBObject.DEFAULT_BITS);
+ }
+ fbos[i].unbind(gl);
+ System.err.println("FBO["+i+"]: "+fbos[i]);
+ }
+
+ }
+
+ @SuppressWarnings("unused")
+ private void resetFBOs(final GL gl, final DimensionImmutable size) {
+ for(int i=0; i<fbos.length; i++) {
+ fbos[i].reset(gl, size.getWidth(), size.getHeight(), numSamples);
+ if( i>0 && fbos[i-1].getNumSamples() != fbos[i].getNumSamples()) {
+ throw new InternalError("sample size mismatch: \n\t0: "+fbos[i-1]+"\n\t1: "+fbos[i]);
+ }
+ numSamples = fbos[i].getNumSamples();
+ if(numSamples>0) {
+ fboTexs[i] = fbos[i].getSamplingSink().getTextureAttachment();
+ } else {
+ fboTexs[i] = fbos[i].getColorbuffer(0).getTextureAttachment();
+ }
+ }
+ }
+
+ public final StereoDeviceRenderer getStereoDeviceRenderer() { return deviceRenderer; }
+
+ public final void addGLEventListener(final StereoGLEventListener l) {
+ helper.addGLEventListener(l);
+ }
+ public final void removeGLEventListener(final StereoGLEventListener l) {
+ helper.removeGLEventListener(l);
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ deviceRenderer.init(gl);
+
+ // We will do some offscreen rendering, setup FBO...
+ final DimensionImmutable textureSize = deviceRenderer.getTextureCount() > 1 ? deviceRenderer.getSingleSurfaceSize() : deviceRenderer.getTotalSurfaceSize();
+ initFBOs(gl, textureSize);
+ helper.init(drawable, false);
+
+ gl.setSwapInterval(1);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ helper.disposeAllGLEventListener(drawable, false);
+ for(int i=0; i<fbos.length; i++) {
+ fbos[i].destroy(gl);
+ fboTexs[i] = null;
+ }
+ if( ownsDevice ) {
+ deviceRenderer.dispose(gl);
+ }
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ deviceRenderer.beginFrame(gl);
+
+ if(0 < numSamples) {
+ gl.glEnable(GL.GL_MULTISAMPLE);
+ }
+
+ final int fboCount = fbos.length;
+ final int displayRepeatFlags;
+ if( 1 >= fboCount ) {
+ displayRepeatFlags = CustomGLEventListener.DISPLAY_DONTCLEAR;
+ } else {
+ displayRepeatFlags = 0;
+ }
+
+ final int[] eyeOrder = deviceRenderer.getDevice().getEyeRenderOrder();
+ final int eyeCount = eyeOrder.length;
+
+ // Update eye pos upfront to have same (almost) results
+ for(int eyeNum=0; eyeNum<eyeCount; eyeNum++) {
+ deviceRenderer.updateEyePose(eyeNum);
+ }
+
+ if( 1 == fboCount ) {
+ fbos[0].bind(gl);
+ }
+
+ for(int eyeNum=0; eyeNum<eyeCount; eyeNum++) {
+ final int eyeName = eyeOrder[eyeNum];
+ if( 1 < fboCount ) {
+ fbos[eyeName].bind(gl);
+ }
+
+ final StereoDeviceRenderer.Eye eye = deviceRenderer.getEye(eyeName);
+ final RectangleImmutable viewport = eye.getViewport();
+ gl.glViewport(viewport.getX(), viewport.getY(), viewport.getWidth(), viewport.getHeight());
+
+ final int displayFlags = eyeNum > 0 ? CustomGLEventListener.DISPLAY_REPEAT | displayRepeatFlags : 0;
+ final GLEventListenerAction reshapeDisplayAction = new GLEventListenerAction() {
+ public void run(final GLAutoDrawable drawable, final GLEventListener listener) {
+ final StereoGLEventListener sl = (StereoGLEventListener) listener;
+ sl.reshapeForEye(drawable, viewport.getX(), viewport.getY(), viewport.getWidth(), viewport.getHeight(),
+ eye.getEyeParameter(), eye.getLastEyePose());
+ sl.display(drawable, displayFlags);
+ } };
+ helper.runForAllGLEventListener(drawable, reshapeDisplayAction);
+
+ if( 1 < fboCount ) {
+ fbos[eyeName].unbind(gl);
+ }
+ }
+
+ if( 1 == fboCount ) {
+ fbos[0].unbind(gl);
+ }
+ // restore viewport
+ gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+
+ if( deviceRenderer.ppAvailable() ) {
+ deviceRenderer.ppBegin(gl);
+ if( 1 == fboCount ) {
+ fbos[0].use(gl, fboTexs[0]);
+ for(int eyeNum=0; eyeNum<eyeCount; eyeNum++) {
+ deviceRenderer.ppOneEye(gl, eyeOrder[eyeNum]);
+ }
+ fbos[0].unuse(gl);
+ } else {
+ for(int eyeNum=0; eyeNum<eyeCount; eyeNum++) {
+ final int eyeName = eyeOrder[eyeNum];
+ fbos[eyeName].use(gl, fboTexs[eyeName]);
+ deviceRenderer.ppOneEye(gl, eyeName);
+ fbos[eyeName].unuse(gl);
+ }
+ }
+ deviceRenderer.ppEnd(gl);
+ }
+
+ if( !drawable.getAutoSwapBufferMode() ) {
+ drawable.swapBuffers();
+ }
+ deviceRenderer.endFrame(gl);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ if( !drawable.getAutoSwapBufferMode() ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.glViewport(0, 0, width, height);
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java
new file mode 100644
index 000000000..d32c981a3
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java
@@ -0,0 +1,160 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.stereo;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PointImmutable;
+
+import jogamp.opengl.Debug;
+
+import com.jogamp.opengl.math.FovHVHalves;
+
+/**
+ * Interface describing a native stereoscopic device
+ */
+public interface StereoDevice {
+ public static final boolean DEBUG = Debug.debug("StereoDevice");
+ public static final boolean DUMP_DATA = Debug.isPropertyDefined("jogl.debug.StereoDevice.DumpData", true);
+
+ /** Merely a class providing a type-tag for extensions */
+ public static class Config {
+ // NOP
+ }
+
+ /** Return the factory used to create this device. */
+ public StereoDeviceFactory getFactory();
+
+ /** Disposes this {@link StereoDevice}. */
+ public void dispose();
+
+ /**
+ * If operation within a device spanning virtual desktop,
+ * returns the device position.
+ * <p>
+ * Otherwise simply 0/0.
+ * </p>
+ */
+ public PointImmutable getPosition();
+
+ /**
+ * Returns the required surface size in pixel.
+ */
+ public DimensionImmutable getSurfaceSize();
+
+ /**
+ * Return the device default eye position offset for {@link #createRenderer(int, int, float[], FovHVHalves[], float)}.
+ * <p>
+ * Result is an array of float values for
+ * <ul>
+ * <li><i>right</i> (positive)</li>
+ * <li><i>up</i> (positive)</li>
+ * <li><i>forward</i> (negative)</li>
+ * </ul>
+ * </p>
+ * @return
+ */
+ public float[] getDefaultEyePositionOffset();
+
+ /**
+ * Returns the device default {@link FovHVHalves} for all supported eyes
+ * in natural order, i.e. left and right if supported.
+ * <p>
+ * Monoscopic devices return an array length of one, without the value for the right-eye!
+ * </p>
+ */
+ public FovHVHalves[] getDefaultFOV();
+
+ /** Start or stop sensors. Returns true if action was successful, otherwise false. */
+ public boolean startSensors(boolean start);
+
+ /** Return true if sensors have been started, false otherwise */
+ public boolean getSensorsStarted();
+
+ /**
+ * Returns an array of the preferred eye rendering order.
+ * The array length reflects the supported eye count.
+ * <p>
+ * Monoscopic devices only support one eye, where stereoscopic device two eyes.
+ * </p>
+ */
+ public int[] getEyeRenderOrder();
+
+ /**
+ * Returns the supported distortion compensation by the {@link StereoDeviceRenderer},
+ * e.g. {@link StereoDeviceRenderer#DISTORTION_BARREL}, {@link StereoDeviceRenderer#DISTORTION_CHROMATIC}, etc.
+ * @see StereoDeviceRenderer#getDistortionBits()
+ * @see #createRenderer(int, int, float[], FovHVHalves[], float, int)
+ * @see #getRecommendedDistortionBits()
+ * @see #getMinimumDistortionBits()
+ */
+ public int getSupportedDistortionBits();
+
+ /**
+ * Returns the recommended distortion compensation bits for the {@link StereoDeviceRenderer},
+ * e.g. {@link StereoDeviceRenderer#DISTORTION_BARREL}, {@link StereoDeviceRenderer#DISTORTION_CHROMATIC}
+ * {@link StereoDeviceRenderer#DISTORTION_VIGNETTE}.
+ * <p>
+ * User shall use the recommended distortion compensation to achieve a distortion free view.
+ * </p>
+ * @see StereoDeviceRenderer#getDistortionBits()
+ * @see #createRenderer(int, int, float[], FovHVHalves[], float, int)
+ * @see #getSupportedDistortionBits()
+ * @see #getMinimumDistortionBits()
+ */
+ public int getRecommendedDistortionBits();
+
+ /**
+ * Returns the minimum distortion compensation bits as required by the {@link StereoDeviceRenderer},
+ * e.g. {@link StereoDeviceRenderer#DISTORTION_BARREL} in case the stereoscopic display uses [a]spherical lenses.
+ * <p>
+ * Minimum distortion compensation bits are being enforced by the {@link StereoDeviceRenderer}.
+ * </p>
+ * @see #getSupportedDistortionBits()
+ * @see #getRecommendedDistortionBits()
+ * @see StereoDeviceRenderer#getDistortionBits()
+ * @see #createRenderer(int, int, float[], FovHVHalves[], float, int)
+ */
+ public int getMinimumDistortionBits();
+
+ /**
+ * Create a new {@link StereoDeviceRenderer} instance.
+ *
+ * @param distortionBits {@link StereoDeviceRenderer} distortion bits, e.g. {@link StereoDeviceRenderer#DISTORTION_BARREL}, etc,
+ * see {@link #getRecommendedDistortionBits()}.
+ * @param textureCount desired texture count for post-processing, see {@link StereoDeviceRenderer#getTextureCount()} and {@link StereoDeviceRenderer#ppAvailable()}
+ * @param eyePositionOffset eye position offset, e.g. {@link #getDefaultEyePositionOffset()}.
+ * @param eyeFov FovHVHalves[] field-of-view per eye, e.g. {@link #getDefaultFOV()}. May contain only one value for monoscopic devices,
+ * see {@link #getEyeRenderOrder()}.
+ * @param pixelsPerDisplayPixel
+ * @param textureUnit
+ * @return
+ */
+ public StereoDeviceRenderer createRenderer(final int distortionBits,
+ final int textureCount, final float[] eyePositionOffset,
+ final FovHVHalves[] eyeFov, final float pixelsPerDisplayPixel, final int textureUnit);
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceFactory.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceFactory.java
new file mode 100644
index 000000000..c4180585c
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceFactory.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.stereo;
+
+import com.jogamp.common.util.ReflectionUtil;
+
+/**
+ * Platform agnostic {@link StereoDevice} factory.
+ * <p>
+ * To implement a new {@link StereoDevice}, the following interfaces/classes must be implemented:
+ * <ul>
+ * <li>{@link StereoDeviceFactory}</li>
+ * <li>{@link StereoDevice}</li>
+ * <li>{@link StereoDeviceRenderer}</li>
+ * </ul>
+ * </p>
+ */
+public abstract class StereoDeviceFactory {
+ private static final String OVRStereoDeviceClazzName = "jogamp.opengl.oculusvr.OVRStereoDeviceFactory";
+ private static final String GenericStereoDeviceClazzName = "jogamp.opengl.util.stereo.GenericStereoDeviceFactory";
+ private static final String isAvailableMethodName = "isAvailable";
+
+ /** {@link StereoDevice} type used for {@link StereoDeviceFactory#createFactory(DeviceType) createFactory(type)}. */
+ public static enum DeviceType {
+ /**
+ * Auto selection of device in the following order:
+ * <ol>
+ * <li>{@link DeviceType#OculusVR}</li>
+ * <li>{@link DeviceType#Generic}</li>
+ * </ol>
+ */
+ Default,
+ /**
+ * Generic software implementation.
+ */
+ Generic,
+ /**
+ * OculusVR implementation.
+ */
+ OculusVR
+ };
+
+ public static StereoDeviceFactory createDefaultFactory() {
+ final ClassLoader cl = StereoDeviceFactory.class.getClassLoader();
+ StereoDeviceFactory sink = createFactory(cl, OVRStereoDeviceClazzName);
+ if( null == sink ) {
+ sink = createFactory(cl, GenericStereoDeviceClazzName);
+ }
+ return sink;
+ }
+
+ public static StereoDeviceFactory createFactory(final DeviceType type) {
+ final String className;
+ switch( type ) {
+ case Default: return createDefaultFactory();
+ case Generic: className = GenericStereoDeviceClazzName; break;
+ case OculusVR: className = OVRStereoDeviceClazzName; break;
+ default: throw new InternalError("XXX");
+ }
+ final ClassLoader cl = StereoDeviceFactory.class.getClassLoader();
+ return createFactory(cl, className);
+ }
+
+ public static StereoDeviceFactory createFactory(final ClassLoader cl, final String implName) {
+ try {
+ if(((Boolean)ReflectionUtil.callStaticMethod(implName, isAvailableMethodName, null, null, cl)).booleanValue()) {
+ return (StereoDeviceFactory) ReflectionUtil.createInstance(implName, cl);
+ }
+ } catch (final Throwable t) { if(StereoDevice.DEBUG) { System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage()); t.printStackTrace(); } }
+ return null;
+ }
+
+ public abstract StereoDevice createDevice(final int deviceIndex, final StereoDevice.Config config, final boolean verbose);
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceRenderer.java
new file mode 100644
index 000000000..ab9ba99a1
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDeviceRenderer.java
@@ -0,0 +1,243 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.stereo;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.opengl.GL;
+
+import com.jogamp.opengl.math.FovHVHalves;
+
+/**
+ * Stereoscopic device rendering interface.
+ * <p>
+ * The following pseudo-code describes how to implement a renderer
+ * using a {@link StereoDeviceRenderer}.
+ * See {@link StereoClientRenderer} which implements the following:
+ * <ul>
+ * <li>device.{@link #beginFrame(GL)}</li>
+ * <li>For both eyes:<ul>
+ * <li>device.{@link #updateEyePose(int)}</li>
+ * <li>if device.{@link #ppAvailable()}: Set the render target, e.g. FBO</li>
+ * <li>Set the viewport using {@link Eye#getViewport()}</li>
+ * <li>{@link StereoGLEventListener#reshapeForEye(javax.media.opengl.GLAutoDrawable, int, int, int, int, EyeParameter, EyePose) upstream.reshapeEye(..)}</li>
+ * <li>{@link StereoGLEventListener#display(javax.media.opengl.GLAutoDrawable, int) upstream.display(..)}.</li>
+ * </ul></li>
+ * <li>Reset the viewport</li>
+ * <li>If device.{@link #ppAvailable()}:<ul>
+ * <li>device.{@link #ppBegin(GL)}</li>
+ * <li>Use render target, e.g. FBO's texture</li>
+ * <li>device.{@link #ppBothEyes(GL)} or device.{@link #ppOneEye(GL, int)} for both eyes</li>
+ * <li>device.{@link #ppEnd(GL)}</li>
+ * </ul></li>
+ * <li>device.{@link #endFrame(GL)}</li>
+ * </ul>
+ * </p>
+ * <a name="asymFOVRendering"><h5>Correct {@link FovHVHalves Asymmetric FOV} Rendering</h5></a>
+ * <p>
+ * The {@link StereoClientRenderer} shall render both images for each eye correctly <i>Off-axis</i>
+ * utilizing an asymmetric camera frustum, i.e. by using {@link StereoDevice StereoDevice}'s {@link StereoDevice#getDefaultFOV() default} {@link FovHVHalves}.<br>
+ *
+ * Some references:
+ * <ul>
+ * <li><a href="https://en.wikipedia.org/wiki/Binocular_vision">Wiki: Binocular Vision</a></li>
+ * <li><a href="http://paulbourke.net/stereographics/stereorender/">Paul Burke: Stereo Graphics - Stereo Renderer</a></li>
+ * <li><a href="https://en.wikipedia.org/wiki/Distortion_%28optics%29">Wiki: Distortion (Optics)</a></li>
+ * </ul>
+ * </p>
+ */
+public interface StereoDeviceRenderer {
+ /**
+ * Distortion Bit: Barrel distortion compensating lens pincushion distortion
+ */
+ public static final int DISTORTION_BARREL = 1 << 0;
+
+ /**
+ * Distortion Bit: Chromatic distortion compensating lens chromatic aberration.
+ */
+ public static final int DISTORTION_CHROMATIC = 1 << 1;
+
+ /**
+ * Distortion Bit: Vignette distortion compensating lens chromatic aberration.
+ */
+ public static final int DISTORTION_VIGNETTE = 1 << 2;
+
+ /**
+ * Distortion Bit: Timewarp distortion technique to predict
+ * {@link EyePose} movement to reduce latency.
+ * <p>
+ * FIXME: Explanation needs refinement!
+ * </p>
+ */
+ public static final int DISTORTION_TIMEWARP = 1 << 3;
+
+
+ /** Returns the {@link StereoDevice} of this {@link StereoDeviceRenderer} instance. */
+ public StereoDevice getDevice();
+
+ /**
+ * Interface describing one eye of the stereoscopic device,
+ * see {@link StereoDeviceRenderer#getEye(int)}.
+ */
+ public static interface Eye {
+ /**
+ * Returns the viewport for this eye.
+ */
+ public RectangleImmutable getViewport();
+ /**
+ * Returns the {@link EyeParameter} of this eye.
+ */
+ public EyeParameter getEyeParameter();
+ /**
+ * Returns the last {@link EyePose} of this eye.
+ */
+ public EyePose getLastEyePose();
+ }
+
+ /**
+ * Returns the {@link Eye} instance for the denoted <code>eyeNum</code>.
+ */
+ public Eye getEye(final int eyeNum);
+
+ /**
+ * Updates the {@link Eye#getLastEyePose()}
+ * for the denoted <code>eyeNum</code>.
+ */
+ public EyePose updateEyePose(final int eyeNum);
+
+ /**
+ * Returns used distortion compensation bits, e.g. {@link #DISTORTION_BARREL},
+ * in case the stereoscopic display requires such, i.e. in case lenses are utilized.
+ * <p>
+ * Distortion requires {@link #ppAvailable() post-processing}.
+ * </p>
+ */
+ public int getDistortionBits();
+
+ /**
+ * Method returns <code>true</code> if using <i>side-by-side</i> (SBS)
+ * stereoscopic images, otherwise <code>false</code>.
+ * <p>
+ * SBS requires that both eye's images are presented
+ * <i>side-by-side</i> in the final framebuffer.
+ * </p>
+ * <p>
+ * Either the renderer presents the images <i>side-by-side</i> according to the {@link Eye#getViewport() eye's viewport},
+ * or {@link #ppAvailable() post-processing} is utilized to merge {@link #getTextureCount() textures}
+ * to a <i>side-by-side</i> configuration.
+ * </p>
+ */
+ public boolean usesSideBySideStereo();
+
+ /**
+ * Returns the unified surface size of one eye's a single image in pixel units.
+ */
+ public DimensionImmutable getSingleSurfaceSize();
+
+ /**
+ * Returns the total surface size required for the complete images in pixel units.
+ * <p>
+ * If {@link #usesSideBySideStereo()} the total size spans over both {@link #getSingleSurfaceSize()}, side-by-side.
+ * </p>
+ * <p>
+ * Otherwise the size is equal to {@link #getSingleSurfaceSize()}.
+ * </p>
+ */
+ public DimensionImmutable getTotalSurfaceSize();
+
+ /**
+ * Returns the used texture-image count for post-processing, see {@link #ppAvailable()}.
+ * <p>
+ * In case the renderer does not support multiple textures for post-processing,
+ * or no post-processing at all, method returns zero despite the request
+ * from {@link StereoDevice#createRenderer(int, int, float[], com.jogamp.opengl.math.FovHVHalves[], float)}.
+ * </p>
+ */
+ public int getTextureCount();
+
+ /** Returns the desired texture-image unit for post-processing, see {@link #ppAvailable()}. */
+ public int getTextureUnit();
+
+ /** Initialize OpenGL related resources */
+ public void init(final GL gl);
+
+ /** Release all OpenGL related resources */
+ public void dispose(final GL gl);
+
+ /** Notifying that a new frame is about to start. */
+ public void beginFrame(final GL gl);
+
+ /** Notifying that the frame has been rendered completely. */
+ public void endFrame(final GL gl);
+
+ /**
+ * Returns <code>true</code> if stereoscopic post-processing is required and available,
+ * otherwise <code>false</code>.
+ * <p>
+ * Stereoscopic post-processing is available if:
+ * <ul>
+ * <li>one of the <i>distortion</i> bits are set, see {@link #getDistortionBits()}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * If stereoscopic post-processing is used
+ * the following post-processing methods must be called to before {@link #endFrame()}:
+ * <ul>
+ * <li>{@link #ppBegin(GL)}</li>
+ * <li>{@link #ppOneEye(GL, int)} for both eyes</li>
+ * <li>{@link #ppEnd(GL)}</li>
+ * </ul>
+ * </p>
+ */
+ public boolean ppAvailable();
+
+ /**
+ * Begin stereoscopic post-processing, see {@link #ppAvailable()}.
+ * <p>
+ * {@link #updateEyePose(int)} for both eyes must be called upfront
+ * when rendering upstream {@link StereoGLEventListener}.
+ * </p>
+ *
+ * @param gl
+ */
+ public void ppBegin(final GL gl);
+
+ /**
+ * Performs stereoscopic post-processing for one eye, see {@link #ppAvailable()}.
+ * @param gl
+ * @param eyeNum
+ */
+ public void ppOneEye(final GL gl, final int eyeNum);
+
+ /**
+ * End stereoscopic post-processing, see {@link #ppAvailable()}.
+ * @param gl
+ */
+ public void ppEnd(final GL gl);
+
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoGLEventListener.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoGLEventListener.java
new file mode 100644
index 000000000..ec580cbf9
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoGLEventListener.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.stereo;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.util.CustomGLEventListener;
+
+/**
+ * Extended {@link GLEventListener} and {@link CustomGLEventListener} interface
+ * supporting stereoscopic client rendering.
+ */
+public interface StereoGLEventListener extends CustomGLEventListener {
+ /**
+ * Stereo capable specialization of {@link #reshape(GLAutoDrawable, int, int, int, int)}
+ * for one {@link StereoDeviceRenderer.Eye}.
+ * <p>
+ * Called by the stereo renderer before each {@link #display(GLAutoDrawable)}
+ * or {@link #display(GLAutoDrawable, int)} call.
+ * </p>
+ * <p>
+ * The client can update it's viewport associated data
+ * and view volume of the window appropriately.
+ * </p>
+ * <p>
+ * The client shall also update it's projection- and modelview matrices according
+ * to the given {@link EyeParameter} and {@link EyePose}.
+ * </p>
+ * <p>
+ * For efficiency the GL viewport has already been updated
+ * via <code>glViewport(x, y, width, height)</code> when this method is called.
+ * </p>
+ *
+ * @param drawable the triggering {@link GLAutoDrawable}
+ * @param x viewport x-coord in pixel units
+ * @param y viewport y-coord in pixel units
+ * @param width viewport width in pixel units
+ * @param height viewport height in pixel units
+ * @param eyeParam constant eye parameter, i.e. FOV and IPD
+ * @param eyePose current eye position and orientation
+ * @see FloatUtil#makePerspective(float[], int, boolean, com.jogamp.opengl.math.FloatUtil.FovHVHalves, float, float)
+ */
+ public void reshapeForEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height,
+ final EyeParameter eyeParam, final EyePose eyePose);
+
+
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoUtil.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoUtil.java
new file mode 100644
index 000000000..3031013b8
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoUtil.java
@@ -0,0 +1,125 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.stereo;
+
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.util.CustomGLEventListener;
+import com.jogamp.opengl.util.stereo.StereoDeviceRenderer.Eye;
+
+public class StereoUtil {
+
+ /** See {@link StereoDeviceRenderer#getDistortionBits()}. */
+ public static boolean usesBarrelDistortion(final int distortionBits) { return 0 != ( distortionBits & StereoDeviceRenderer.DISTORTION_BARREL ) ; }
+ /** See {@link StereoDeviceRenderer#getDistortionBits()}. */
+ public static boolean usesTimewarpDistortion(final int distortionBits) { return 0 != ( distortionBits & StereoDeviceRenderer.DISTORTION_TIMEWARP ) ; }
+ /** See {@link StereoDeviceRenderer#getDistortionBits()}. */
+ public static boolean usesChromaticDistortion(final int distortionBits) { return 0 != ( distortionBits & StereoDeviceRenderer.DISTORTION_CHROMATIC ) ; }
+ /** See {@link StereoDeviceRenderer#getDistortionBits()}. */
+ public static boolean usesVignetteDistortion(final int distortionBits) { return 0 != ( distortionBits & StereoDeviceRenderer.DISTORTION_VIGNETTE ) ; }
+
+ /** See {@link StereoDeviceRenderer#getDistortionBits()}. */
+ public static String distortionBitsToString(final int distortionBits) {
+ boolean appendComma = false;
+ final StringBuilder sb = new StringBuilder();
+ if( usesBarrelDistortion(distortionBits) ) {
+ if( appendComma ) { sb.append(", "); };
+ sb.append("barrel"); appendComma=true;
+ }
+ if( usesVignetteDistortion(distortionBits) ) {
+ if( appendComma ) { sb.append(", "); };
+ sb.append("vignette"); appendComma=true;
+ }
+ if( usesChromaticDistortion(distortionBits) ) {
+ if( appendComma ) { sb.append(", "); };
+ sb.append("chroma"); appendComma=true;
+ }
+ if( usesTimewarpDistortion(distortionBits) ) {
+ if( appendComma ) { sb.append(", "); };
+ sb.append("timewarp"); appendComma=true;
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Calculates the <i>Side By Side</i>, SBS, projection- and modelview matrix for one eye.
+ * <p>
+ * {@link #updateEyePose(int)} must be called upfront.
+ * </p>
+ * <p>
+ * This method merely exist as an example implementation to compute the matrices,
+ * which shall be adopted by the
+ * {@link CustomGLEventListener#reshape(javax.media.opengl.GLAutoDrawable, int, int, int, int, EyeParameter, EyePose) upstream client code}.
+ * </p>
+ * @param eyeNum eye denominator
+ * @param zNear frustum near value
+ * @param zFar frustum far value
+ * @param mat4Projection float[16] projection matrix result
+ * @param mat4Modelview float[16] modelview matrix result
+ */
+ public static void getSBSUpstreamPMV(final Eye eye, final float zNear, final float zFar,
+ final float[] mat4Projection, final float[] mat4Modelview) {
+ final float[] mat4Tmp1 = new float[16];
+ final float[] mat4Tmp2 = new float[16];
+ final float[] vec3Tmp1 = new float[3];
+ final float[] vec3Tmp2 = new float[3];
+ final float[] vec3Tmp3 = new float[3];
+
+ final EyeParameter eyeParam = eye.getEyeParameter();
+ final EyePose eyePose = eye.getLastEyePose();
+
+ //
+ // Projection
+ //
+ FloatUtil.makePerspective(mat4Projection, 0, true, eyeParam.fovhv, zNear, zFar);
+
+ //
+ // Modelview
+ //
+ final Quaternion rollPitchYaw = new Quaternion();
+ // private final float eyeYaw = FloatUtil.PI; // 180 degrees in radians
+ // rollPitchYaw.rotateByAngleY(eyeYaw);
+ final float[] shiftedEyePos = rollPitchYaw.rotateVector(vec3Tmp1, 0, eyePose.position, 0);
+ VectorUtil.addVec3(shiftedEyePos, shiftedEyePos, eyeParam.positionOffset);
+
+ rollPitchYaw.mult(eyePose.orientation);
+ final float[] up = rollPitchYaw.rotateVector(vec3Tmp2, 0, VectorUtil.VEC3_UNIT_Y, 0);
+ final float[] forward = rollPitchYaw.rotateVector(vec3Tmp3, 0, VectorUtil.VEC3_UNIT_Z_NEG, 0);
+ final float[] center = VectorUtil.addVec3(forward, shiftedEyePos, forward);
+
+ final float[] mLookAt = FloatUtil.makeLookAt(mat4Tmp2, 0, shiftedEyePos, 0, center, 0, up, 0, mat4Tmp1);
+ final float[] mViewAdjust = FloatUtil.makeTranslation(mat4Modelview, true,
+ eyeParam.distNoseToPupilX,
+ eyeParam.distMiddleToPupilY,
+ eyeParam.eyeReliefZ);
+
+ /* mat4Modelview = */ FloatUtil.multMatrix(mViewAdjust, mLookAt);
+ }
+
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java
new file mode 100644
index 000000000..f5ef5672f
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java
@@ -0,0 +1,190 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.texture;
+
+import java.io.IOException;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.common.util.IOUtil;
+
+/**
+ * Simple {@link TextureSequence} implementation
+ * allowing {@link #addFrame(GL, Texture) existing textures}
+ * or {@link #addFrame(GL, Class, String, String) image streams}
+ * to be used and <i>replayed</i> as {@link TextureSequence.TextureFrame frames}.
+ */
+public class ImageSequence implements TextureSequence {
+ private final int textureUnit;
+ private final boolean useBuildInTexLookup;
+ private final List<TextureSequence.TextureFrame> frames = new ArrayList<TextureSequence.TextureFrame>();
+ private final int[] texMinMagFilter = { GL.GL_NEAREST, GL.GL_NEAREST };
+ private final int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE };
+ private volatile int frameIdx = 0;
+ private volatile boolean manualStepping = false;
+ private int textureFragmentShaderHashCode = 0;
+
+ public ImageSequence(final int textureUnit, final boolean useBuildInTexLookup) {
+ this.textureUnit = textureUnit;
+ this.useBuildInTexLookup = useBuildInTexLookup;
+ }
+
+ public void setParams(final int magFilter, final int minFilter, final int wrapS, final int wrapT) {
+ texMinMagFilter[0] = minFilter;
+ texMinMagFilter[1] = magFilter;
+ texWrapST[0] = wrapS;
+ texWrapST[1] = wrapT;
+ }
+
+ public final void addFrame(final GL gl, final Texture tex) {
+ final TextureSequence.TextureFrame frame = new TextureSequence.TextureFrame(tex);
+ frames.add(frame);
+ tex.bind(gl);
+ gl.glTexParameteri(getTextureTarget(), GL.GL_TEXTURE_MIN_FILTER, texMinMagFilter[0]);
+ gl.glTexParameteri(getTextureTarget(), GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[1]);
+ gl.glTexParameteri(getTextureTarget(), GL.GL_TEXTURE_WRAP_S, texWrapST[0]);
+ gl.glTexParameteri(getTextureTarget(), GL.GL_TEXTURE_WRAP_T, texWrapST[1]);
+ }
+
+ public final void addFrame(final GL gl, final Class<?> context, final String imageResourcePath, final String imageSuffix) throws IOException {
+ final URLConnection urlConn = IOUtil.getResource(context, imageResourcePath);
+ if(null != urlConn) {
+ final TextureData texData = TextureIO.newTextureData(GLProfile.getGL2ES2(), urlConn.getInputStream(), false, imageSuffix);
+ final Texture tex = new Texture(getTextureTarget());
+ tex.updateImage(gl, texData);
+ addFrame(gl, tex);
+ }
+ }
+ public final int getFrameCount() { return frames.size(); }
+ public final int getCurrentIdx() { return frameIdx; }
+ public final void setCurrentIdx(final int idx) throws IndexOutOfBoundsException {
+ if( 0 > idx || idx >= frames.size() ) {
+ throw new IndexOutOfBoundsException("idx shall be within 0 <= "+idx+" < "+frames.size());
+ }
+ frameIdx=idx;
+ }
+ public final void setManualStepping(final boolean v) { manualStepping = v; }
+ public final boolean getManualStepping() { return manualStepping; }
+ public final TextureSequence.TextureFrame getFrame(final int idx) { return frames.get(idx); }
+
+ public void destroy(final GL gl) throws GLException {
+ for(int i=frames.size()-1; i>=0; i--) {
+ frames.get(i).getTexture().destroy(gl);
+ }
+ frames.clear();
+ }
+
+ @Override
+ public int getTextureTarget() {
+ return GL.GL_TEXTURE_2D;
+ }
+
+ @Override
+ public int getTextureUnit() {
+ return textureUnit;
+ }
+
+ @Override
+ public int[] getTextureMinMagFilter() {
+ return texMinMagFilter;
+ }
+
+ @Override
+ public int[] getTextureWrapST() {
+ return texWrapST;
+ }
+
+ @Override
+ public boolean isTextureAvailable() { return frames.size() > 0; }
+
+ @Override
+ public TextureSequence.TextureFrame getLastTexture() throws IllegalStateException {
+ return frames.get(frameIdx); // may return null
+ }
+
+ @Override
+ public TextureSequence.TextureFrame getNextTexture(final GL gl) throws IllegalStateException {
+ if( !manualStepping ) {
+ frameIdx = ( frameIdx + 1 ) % frames.size();
+ }
+ return frames.get(frameIdx);
+ }
+
+ @Override
+ public String getRequiredExtensionsShaderStub() throws IllegalStateException {
+ return "// TextTextureSequence: No extensions required\n";
+ }
+
+ @Override
+ public String getTextureSampler2DType() throws IllegalStateException {
+ return "sampler2D" ;
+ }
+
+ private String textureLookupFunctionName = "myTexture2D";
+
+ @Override
+ public String getTextureLookupFunctionName(final String desiredFuncName) throws IllegalStateException {
+ if(useBuildInTexLookup) {
+ return "texture2D";
+ }
+ if(null != desiredFuncName && desiredFuncName.length()>0) {
+ textureLookupFunctionName = desiredFuncName;
+ }
+ return textureLookupFunctionName;
+ }
+
+ @Override
+ public String getTextureLookupFragmentShaderImpl() throws IllegalStateException {
+ if(useBuildInTexLookup) {
+ return "";
+ }
+ return
+ "\n"+
+ "vec4 "+textureLookupFunctionName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+
+ " return texture2D(image, texCoord);\n"+
+ "}\n\n";
+ }
+
+ @Override
+ public int getTextureFragmentShaderHashCode() {
+ if( !isTextureAvailable() ) {
+ textureFragmentShaderHashCode = 0;
+ return 0;
+ } else if( 0 == textureFragmentShaderHashCode ) {
+ int hash = 31 + getTextureLookupFragmentShaderImpl().hashCode();
+ hash = ((hash << 5) - hash) + getTextureSampler2DType().hashCode();
+ textureFragmentShaderHashCode = hash;
+ }
+ return textureFragmentShaderHashCode;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
index 15dd19ea9..e7693f4a6 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
@@ -1,21 +1,22 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -51,18 +52,32 @@ import com.jogamp.opengl.util.texture.spi.*;
* Represents an OpenGL texture object. Contains convenience routines
* for enabling/disabling OpenGL texture state, binding this texture,
* and computing texture coordinates for both the entire image as well
- * as a sub-image.
- *
+ * as a sub-image.
+ *
+ * <a name="textureCallOrder"><h5>Order of Texture Commands</h5></a>
+ * <p>
+ * Due to many confusions w/ texture usage, following list described the order
+ * and semantics of texture unit selection, binding and enabling.
+ * <ul>
+ * <li><i>Optional:</i> Set active textureUnit via <code>gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit)</code>, <code>0</code> is default.</li>
+ * <li>Bind <code>textureId</code> -> active <code>textureUnit</code>'s <code>textureTarget</code> via <code>gl.glBindTexture(textureTarget, textureId)</code></li>
+ * <li><i>Compatible Context Only:</i> Enable active <code>textureUnit</code>'s <code>textureTarget</code> via <code>glEnable(textureTarget)</code>.
+ * <li><i>Optional:</i> Fiddle with the texture parameters and/or environment settings.</li>
+ * <li>GLSL: Use <code>textureUnit</code> in your shader program, enable shader program.</li>
+ * <li>Issue draw commands</li>
+ * </ul>
+ * </p>
+ *
* <p><a name="nonpow2"><b>Non-power-of-two restrictions</b></a>
* <br> When creating an OpenGL texture object, the Texture class will
- * attempt to leverage the <a
- * href="http://www.opengl.org/registry/specs/ARB/texture_non_power_of_two.txt">GL_ARB_texture_non_power_of_two</a>
- * and <a
- * href="http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt">GL_ARB_texture_rectangle</a>
- * extensions (in that order) whenever possible. If neither extension
- * is available, the Texture class will simply upload a non-pow2-sized
+ * attempt to use <i>non-power-of-two textures</i> (NPOT) if available, see {@link GL#isNPOTTextureAvailable()}.
+ * Further more,
+ * <a href="http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt">GL_ARB_texture_rectangle</a>
+ * (RECT) will be attempted on OSX w/ ATI drivers.
+ * If NPOT is not available or RECT not chosen, the Texture class will simply upload a non-pow2-sized
* image into a standard pow2-sized texture (without any special
- * scaling). Since the choice of extension (or whether one is used at
+ * scaling).
+ * Since the choice of extension (or whether one is used at
* all) depends on the user's machine configuration, developers are
* recommended to use {@link #getImageTexCoords} and {@link
* #getSubImageTexCoords}, as those methods will calculate the
@@ -90,16 +105,24 @@ import com.jogamp.opengl.util.texture.spi.*;
* when switching between textures it is necessary to call {@link
* #bind}, but when drawing many triangles all using the same texture,
* for best performance only one call to {@link #bind} should be made.
+ * User may also utilize multiple texture units,
+ * see <a href="#textureCallOrder"> order of texture commands above</a>.
*
* <p><a name="premult"><b>Alpha premultiplication and blending</b></a>
- * <br> The mathematically correct way to perform blending in OpenGL
- * (with the SrcOver "source over destination" mode, or any other
- * Porter-Duff rule) is to use "premultiplied color components", which
- * means the R/G/ B color components have already been multiplied by
- * the alpha value. To make things easier for developers, the Texture
- * class will automatically convert non-premultiplied image data into
- * premultiplied data when storing it into an OpenGL texture. As a
- * result, it is important to use the correct blending function; for
+ * <p>
+ * <i>Disclaimer: Consider performing alpha premultiplication in shader code, if really desired! Otherwise use RGBA.</i><br/>
+ * </p>
+ * <p>
+ * The Texture class does not convert RGBA image data into
+ * premultiplied data when storing it into an OpenGL texture.
+ * </p>
+ * <p>
+ * The mathematically correct way to perform blending in OpenGL
+ * with the SrcOver "source over destination" mode, or any other
+ * Porter-Duff rule, is to use <i>premultiplied color components</i>,
+ * which means the R/G/ B color components must have been multiplied by
+ * the alpha value. If using <i>premultiplied color components</i>
+ * it is important to use the correct blending function; for
* example, the SrcOver rule is expressed as:
<pre>
gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
@@ -114,7 +137,7 @@ import com.jogamp.opengl.util.texture.spi.*;
float g = g * a;
float b = b * a;
gl.glColor4f(r, g, b, a);
-</pre>
+</pre>
*
* For reference, here is a list of the Porter-Duff compositing rules
* and the associated OpenGL blend functions (source and destination
@@ -137,9 +160,7 @@ import com.jogamp.opengl.util.texture.spi.*;
<TR> <TD> AlphaXor <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_ONE_MINUS_SRC_ALPHA
</TABLE>
</CENTER>
- *
- * @author Chris Campbell
- * @author Kenneth Russell
+ * @author Chris Campbell, Kenneth Russell, et.al.
*/
public class Texture {
/** The GL target type. */
@@ -167,6 +188,13 @@ public class Texture {
/** The texture coordinates corresponding to the entire image. */
private TextureCoords coords;
+ @Override
+ public String toString() {
+ return "Texture[target 0x"+Integer.toHexString(target)+", name "+texID+", "+
+ imgWidth+"/"+texWidth+" x "+imgHeight+"/"+texHeight+", y-flip "+mustFlipVertically+
+ ", "+estimatedMemorySize+" bytes]";
+ }
+
/** An estimate of the amount of texture memory this texture consumes. */
private int estimatedMemorySize;
@@ -177,22 +205,49 @@ public class Texture {
private static final boolean disableNPOT = Debug.isPropertyDefined("jogl.texture.nonpot", true);
private static final boolean disableTexRect = Debug.isPropertyDefined("jogl.texture.notexrect", true);
- public Texture(GL gl, TextureData data) throws GLException {
+ public Texture(final GL gl, final TextureData data) throws GLException {
texID = 0;
updateImage(gl, data);
}
- // Constructor for use when creating e.g. cube maps, where there is
- // no initial texture data
- public Texture(int target) {
+ /**
+ * Constructor for use when creating e.g. cube maps, where there is
+ * no initial texture data
+ * @param target the OpenGL texture target, eg GL.GL_TEXTURE_2D,
+ * GL2.GL_TEXTURE_RECTANGLE
+ */
+ public Texture(final int target) {
texID = 0;
this.target = target;
}
- // Package-private constructor for creating a texture object which wraps
- // an existing texture ID from another package
- Texture(int textureID, int target, int texWidth, int texHeight, int imgWidth, int imgHeight,
- boolean mustFlipVertically) {
+ /**
+ * Constructor to wrap an OpenGL texture ID from an external library and allows
+ * some of the base methods from the Texture class, such as
+ * binding and querying of texture coordinates, to be used with
+ * it. Attempts to update such textures' contents will yield
+ * undefined results.
+ *
+ * @param textureID the OpenGL texture object to wrap
+ * @param target the OpenGL texture target, eg GL.GL_TEXTURE_2D,
+ * GL2.GL_TEXTURE_RECTANGLE
+ * @param texWidth the width of the texture in pixels
+ * @param texHeight the height of the texture in pixels
+ * @param imgWidth the width of the image within the texture in
+ * pixels (if the content is a sub-rectangle in the upper
+ * left corner); otherwise, pass in texWidth
+ * @param imgHeight the height of the image within the texture in
+ * pixels (if the content is a sub-rectangle in the upper
+ * left corner); otherwise, pass in texHeight
+ * @param mustFlipVertically indicates whether the texture
+ * coordinates must be flipped vertically
+ * in order to properly display the
+ * texture
+ */
+ public Texture(final int textureID, final int target,
+ final int texWidth, final int texHeight,
+ final int imgWidth, final int imgHeight,
+ final boolean mustFlipVertically) {
this.texID = textureID;
this.target = target;
this.mustFlipVertically = mustFlipVertically;
@@ -206,12 +261,13 @@ public class Texture {
* Enables this texture's target (e.g., GL_TEXTURE_2D) in the
* given GL context's state. This method is a shorthand equivalent
* of the following OpenGL code:
- <pre>
- gl.glEnable(texture.getTarget());
- </pre>
- *
+ * <pre>
+ * gl.glEnable(texture.getTarget());
+ * </pre>
* <p>
- * Call is ignored if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}.
+ * Call is ignored if the {@link GL} object's context
+ * is using a core profile, see {@link GL#isGLcore()},
+ * or if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}.
* </p>
* <p>
* See the <a href="#perftips">performance tips</a> above for hints
@@ -222,22 +278,23 @@ public class Texture {
* @throws GLException if no OpenGL context was current or if any
* OpenGL-related errors occurred
*/
- public void enable(GL gl) throws GLException {
- if(GLES2.GL_TEXTURE_EXTERNAL_OES != target) {
+ public void enable(final GL gl) throws GLException {
+ if( !gl.isGLcore() && GLES2.GL_TEXTURE_EXTERNAL_OES != target) {
gl.glEnable(target);
}
}
-
+
/**
* Disables this texture's target (e.g., GL_TEXTURE_2D) in the
* given GL state. This method is a shorthand equivalent
* of the following OpenGL code:
- <pre>
- gl.glDisable(texture.getTarget());
- </pre>
- *
+ * <pre>
+ * gl.glDisable(texture.getTarget());
+ * </pre>
* <p>
- * Call is ignored if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}.
+ * Call is ignored if the {@link GL} object's context
+ * is using a core profile, see {@link GL#isGLcore()},
+ * or if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}.
* </p>
* <p>
* See the <a href="#perftips">performance tips</a> above for hints
@@ -248,12 +305,12 @@ public class Texture {
* @throws GLException if no OpenGL context was current or if any
* OpenGL-related errors occurred
*/
- public void disable(GL gl) throws GLException {
- if(GLES2.GL_TEXTURE_EXTERNAL_OES != target) {
+ public void disable(final GL gl) throws GLException {
+ if( !gl.isGLcore() && GLES2.GL_TEXTURE_EXTERNAL_OES != target ) {
gl.glDisable(target);
}
}
-
+
/**
* Binds this texture to the given GL context. This method is a
* shorthand equivalent of the following OpenGL code:
@@ -263,28 +320,22 @@ public class Texture {
*
* See the <a href="#perftips">performance tips</a> above for hints
* on how to maximize performance when using many Texture objects.
- *
+ *
* @param gl the current GL context
* @throws GLException if no OpenGL context was current or if any
* OpenGL-related errors occurred
*/
- public void bind(GL gl) throws GLException {
+ public void bind(final GL gl) throws GLException {
validateTexID(gl, true);
- gl.glBindTexture(target, texID);
- }
-
- /**
- * @deprecated use {@link #destroy(GL)}
- */
- public final void dispose(GL gl) throws GLException {
- destroy(gl);
+ gl.glBindTexture(target, texID);
}
+
/**
* Destroys the native resources used by this texture object.
*
* @throws GLException if any OpenGL-related errors occurred
*/
- public void destroy(GL gl) throws GLException {
+ public void destroy(final GL gl) throws GLException {
if(0!=texID) {
gl.glDeleteTextures(1, new int[] {texID}, 0);
texID = 0;
@@ -312,7 +363,7 @@ public class Texture {
public int getWidth() {
return texWidth;
}
-
+
/**
* Returns the height of the allocated OpenGL texture in pixels.
* Note that the texture height will be greater than or equal to the
@@ -322,9 +373,9 @@ public class Texture {
*/
public int getHeight() {
return texHeight;
- }
-
- /**
+ }
+
+ /**
* Returns the width of the image contained within this texture.
* Note that for non-power-of-two textures in particular this may
* not be equal to the result of {@link #getWidth}. It is
@@ -366,7 +417,7 @@ public class Texture {
* entire image. If the TextureData indicated that the texture
* coordinates must be flipped vertically, the returned
* TextureCoords will take that into account.
- *
+ *
* @return the texture coordinates corresponding to the entire image
*/
public TextureCoords getImageTexCoords() {
@@ -383,10 +434,10 @@ public class Texture {
* flipped vertically, the returned TextureCoords will take that
* into account; this should not be handled by the end user in the
* specification of the y1 and y2 coordinates.
- *
+ *
* @return the texture coordinates corresponding to the specified sub-image
*/
- public TextureCoords getSubImageTexCoords(int x1, int y1, int x2, int y2) {
+ public TextureCoords getSubImageTexCoords(final int x1, final int y1, final int x2, final int y2) {
if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) {
if (mustFlipVertically) {
return new TextureCoords(x1, texHeight - y1, x2, texHeight - y2);
@@ -394,12 +445,12 @@ public class Texture {
return new TextureCoords(x1, y1, x2, y2);
}
} else {
- float tx1 = (float)x1 / (float)texWidth;
- float ty1 = (float)y1 / (float)texHeight;
- float tx2 = (float)x2 / (float)texWidth;
- float ty2 = (float)y2 / (float)texHeight;
+ final float tx1 = (float)x1 / (float)texWidth;
+ final float ty1 = (float)y1 / (float)texHeight;
+ final float tx2 = (float)x2 / (float)texWidth;
+ final float ty2 = (float)y2 / (float)texHeight;
if (mustFlipVertically) {
- float yMax = (float) imgHeight / (float) texHeight;
+ final float yMax = (float) imgHeight / (float) texHeight;
return new TextureCoords(tx1, yMax - ty1, tx2, yMax - ty2);
} else {
return new TextureCoords(tx1, ty1, tx2, ty2);
@@ -408,12 +459,12 @@ public class Texture {
}
/**
- * Updates the entire content area of this texture using the data in
- * the given image.
- *
+ * Updates the entire content area incl. {@link TextureCoords}
+ * of this texture using the data in the given image.
+ *
* @throws GLException if any OpenGL-related errors occurred
*/
- public void updateImage(GL gl, TextureData data) throws GLException {
+ public void updateImage(final GL gl, final TextureData data) throws GLException {
updateImage(gl, data, 0);
}
@@ -430,13 +481,27 @@ public class Texture {
}
/**
- * Updates the content area of the specified target of this texture
+ * Change whether the TextureData requires a vertical flip of
+ * the texture coords.
+ * <p>
+ * No-op if no change, otherwise generates new {@link TextureCoords}.
+ * </p>
+ */
+ public void setMustFlipVertically(final boolean v) {
+ if( v != mustFlipVertically ) {
+ mustFlipVertically = v;
+ updateTexCoords();
+ }
+ }
+
+ /**
+ * Updates the content area incl. {@link TextureCoords} of the specified target of this texture
* using the data in the given image. In general this is intended
* for construction of cube maps.
- *
+ *
* @throws GLException if any OpenGL-related errors occurred
*/
- public void updateImage(GL gl, TextureData data, int targetOverride) throws GLException {
+ public void updateImage(final GL gl, final TextureData data, final int targetOverride) throws GLException {
validateTexID(gl, true);
imgWidth = data.getWidth();
@@ -457,7 +522,7 @@ public class Texture {
data.setHaveGL12(gl.isExtensionAvailable(GLExtensions.VERSION_1_2));
// Indicates whether both width and height are power of two
- boolean isPOT = isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight);
+ final boolean isPOT = isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight);
// Note that automatic mipmap generation doesn't work for
// GL_ARB_texture_rectangle
@@ -569,7 +634,7 @@ public class Texture {
}
if (data.getMipmap() && !haveAutoMipmapGeneration) {
- int[] align = new int[1];
+ final int[] align = new int[1];
gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, align, 0); // save alignment
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, data.getAlignment());
@@ -579,7 +644,7 @@ public class Texture {
try {
// FIXME: may need check for GLUnsupportedException
- GLU glu = GLU.createGLU(gl);
+ final GLU glu = GLU.createGLU(gl);
glu.gluBuild2DMipmaps(texTarget, data.getInternalFormat(),
data.getWidth(), data.getHeight(),
data.getPixelFormat(), data.getPixelType(), data.getBuffer());
@@ -588,7 +653,7 @@ public class Texture {
}
} else {
checkCompressedTextureExtensions(gl, data);
- Buffer[] mipmapData = data.getMipmapData();
+ final Buffer[] mipmapData = data.getMipmapData();
if (mipmapData != null) {
int width = texWidth;
int height = texHeight;
@@ -619,7 +684,7 @@ public class Texture {
texWidth, texHeight, data.getBorder(),
data.getBuffer().capacity(), data.getBuffer());
} else {
- ByteBuffer buf = DDSImage.allocateBlankBuffer(texWidth,
+ final ByteBuffer buf = DDSImage.allocateBlankBuffer(texWidth,
texHeight,
data.getInternalFormat());
gl.glCompressedTexImage2D(texTarget, 0, data.getInternalFormat(),
@@ -645,9 +710,9 @@ public class Texture {
}
}
- int minFilter = (data.getMipmap() ? GL.GL_LINEAR_MIPMAP_LINEAR : GL.GL_LINEAR);
- int magFilter = GL.GL_LINEAR;
- int wrapMode = (gl.isExtensionAvailable(GLExtensions.VERSION_1_2) || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP;
+ final int minFilter = (data.getMipmap() ? GL.GL_LINEAR_MIPMAP_LINEAR : GL.GL_LINEAR);
+ final int magFilter = GL.GL_LINEAR;
+ final int wrapMode = (gl.isExtensionAvailable(GLExtensions.VERSION_1_2) || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP;
// REMIND: figure out what to do for GL_TEXTURE_RECTANGLE_ARB
if (texTarget != GL2.GL_TEXTURE_RECTANGLE_ARB) {
@@ -655,8 +720,8 @@ public class Texture {
gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_MAG_FILTER, magFilter);
gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_WRAP_S, wrapMode);
gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_WRAP_T, wrapMode);
- if (this.target == GL2.GL_TEXTURE_CUBE_MAP) {
- gl.glTexParameteri(texParamTarget, GL2.GL_TEXTURE_WRAP_R, wrapMode);
+ if (this.target == GL.GL_TEXTURE_CUBE_MAP) {
+ gl.glTexParameteri(texParamTarget, GL2ES2.GL_TEXTURE_WRAP_R, wrapMode);
}
}
@@ -693,7 +758,7 @@ public class Texture {
*
* @throws GLException if any OpenGL-related errors occurred
*/
- public void updateSubImage(GL gl, TextureData data, int mipmapLevel, int x, int y) throws GLException {
+ public void updateSubImage(final GL gl, final TextureData data, final int mipmapLevel, final int x, final int y) throws GLException {
if (usingAutoMipmapGeneration && mipmapLevel != 0) {
// When we're using mipmap generation via GL_GENERATE_MIPMAP, we
// don't need to update other mipmap levels
@@ -733,10 +798,10 @@ public class Texture {
* @throws GLException if no OpenGL context was current or if any
* OpenGL-related errors occurred
*/
- public void updateSubImage(GL gl, TextureData data, int mipmapLevel,
- int dstx, int dsty,
- int srcx, int srcy,
- int width, int height) throws GLException {
+ public void updateSubImage(final GL gl, final TextureData data, final int mipmapLevel,
+ final int dstx, final int dsty,
+ final int srcx, final int srcy,
+ final int width, final int height) throws GLException {
if (data.isDataCompressed()) {
throw new GLException("updateSubImage specifying a sub-rectangle is not supported for compressed TextureData");
}
@@ -754,12 +819,12 @@ public class Texture {
* texture's target. This gives control over parameters such as
* GL_TEXTURE_MAX_ANISOTROPY_EXT. Causes this texture to be bound to
* the current texture state.
- *
+ *
* @throws GLException if no OpenGL context was current or if any
* OpenGL-related errors occurred
*/
- public void setTexParameterf(GL gl, int parameterName,
- float value) {
+ public void setTexParameterf(final GL gl, final int parameterName,
+ final float value) {
bind(gl);
gl.glTexParameterf(target, parameterName, value);
}
@@ -768,11 +833,11 @@ public class Texture {
* Sets the OpenGL multi-floating-point texture parameter for the
* texture's target. Causes this texture to be bound to the current
* texture state.
- *
+ *
* @throws GLException if any OpenGL-related errors occurred
*/
- public void setTexParameterfv(GL gl, int parameterName,
- FloatBuffer params) {
+ public void setTexParameterfv(final GL gl, final int parameterName,
+ final FloatBuffer params) {
bind(gl);
gl.glTexParameterfv(target, parameterName, params);
}
@@ -781,11 +846,11 @@ public class Texture {
* Sets the OpenGL multi-floating-point texture parameter for the
* texture's target. Causes this texture to be bound to the current
* texture state.
- *
+ *
* @throws GLException if any OpenGL-related errors occurred
*/
- public void setTexParameterfv(GL gl, int parameterName,
- float[] params, int params_offset) {
+ public void setTexParameterfv(final GL gl, final int parameterName,
+ final float[] params, final int params_offset) {
bind(gl);
gl.glTexParameterfv(target, parameterName, params, params_offset);
}
@@ -797,11 +862,11 @@ public class Texture {
* to GL_CLAMP_TO_EDGE if OpenGL 1.2 is supported on the current
* platform and GL_CLAMP if not. Causes this texture to be bound to
* the current texture state.
- *
+ *
* @throws GLException if any OpenGL-related errors occurred
*/
- public void setTexParameteri(GL gl, int parameterName,
- int value) {
+ public void setTexParameteri(final GL gl, final int parameterName,
+ final int value) {
bind(gl);
gl.glTexParameteri(target, parameterName, value);
}
@@ -810,11 +875,11 @@ public class Texture {
* Sets the OpenGL multi-integer texture parameter for the texture's
* target. Causes this texture to be bound to the current texture
* state.
- *
+ *
* @throws GLException if any OpenGL-related errors occurred
*/
- public void setTexParameteriv(GL gl, int parameterName,
- IntBuffer params) {
+ public void setTexParameteriv(final GL gl, final int parameterName,
+ final IntBuffer params) {
bind(gl);
gl.glTexParameteriv(target, parameterName, params);
}
@@ -823,25 +888,44 @@ public class Texture {
* Sets the OpenGL multi-integer texture parameter for the texture's
* target. Causes this texture to be bound to the current texture
* state.
- *
+ *
* @throws GLException if any OpenGL-related errors occurred
*/
- public void setTexParameteriv(GL gl, int parameterName,
- int[] params, int params_offset) {
+ public void setTexParameteriv(final GL gl, final int parameterName,
+ final int[] params, final int params_offset) {
bind(gl);
gl.glTexParameteriv(target, parameterName, params, params_offset);
}
/**
- * Returns the underlying OpenGL texture object for this texture.
+ * Returns the underlying OpenGL texture object for this texture
+ * and generates it if not done yet.
+ * <p>
* Most applications will not need to access this, since it is
* handled automatically by the bind(GL) and destroy(GL) APIs.
+ * </p>
+ * @param gl required to be valid and current in case the texture object has not been generated yet,
+ * otherwise it may be <code>null</code>.
+ * @see #getTextureObject()
*/
- public int getTextureObject(GL gl) {
+ public int getTextureObject(final GL gl) {
validateTexID(gl, false);
return texID;
}
+ /**
+ * Returns the underlying OpenGL texture object for this texture,
+ * maybe <code>0</code> if not yet generated.
+ * <p>
+ * Most applications will not need to access this, since it is
+ * handled automatically by the bind(GL) and destroy(GL) APIs.
+ * </p>
+ * @see #getTextureObject(GL)
+ */
+ public int getTextureObject() {
+ return texID;
+ }
+
/** Returns an estimate of the amount of texture memory in bytes
this Texture consumes. It should only be treated as an estimate;
most applications should not need to query this but instead let
@@ -873,7 +957,7 @@ public class Texture {
*
* @return true if the given value is a power of two, false otherwise
*/
- private static boolean isPowerOfTwo(int val) {
+ private static boolean isPowerOfTwo(final int val) {
return ((val & (val - 1)) == 0);
}
@@ -885,7 +969,7 @@ public class Texture {
* @param val the value
* @return the next power of two
*/
- private static int nextPowerOfTwo(int val) {
+ private static int nextPowerOfTwo(final int val) {
int ret = 1;
while (ret < val) {
ret <<= 1;
@@ -897,9 +981,12 @@ public class Texture {
* Updates the actual image dimensions; usually only called from
* <code>updateImage</code>.
*/
- private void setImageSize(int width, int height, int target) {
+ private void setImageSize(final int width, final int height, final int target) {
imgWidth = width;
imgHeight = height;
+ updateTexCoords();
+ }
+ private void updateTexCoords() {
if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) {
if (mustFlipVertically) {
coords = new TextureCoords(0, imgHeight, imgWidth, 0);
@@ -908,13 +995,13 @@ public class Texture {
}
} else {
if (mustFlipVertically) {
- coords = new TextureCoords(0, // l
+ coords = new TextureCoords(0, // l
(float) imgHeight / (float) texHeight, // b
(float) imgWidth / (float) texWidth, // r
0 // t
);
} else {
- coords = new TextureCoords(0, // l
+ coords = new TextureCoords(0, // l
0, // b
(float) imgWidth / (float) texWidth, // r
(float) imgHeight / (float) texHeight // t
@@ -923,7 +1010,7 @@ public class Texture {
}
}
- private void updateSubImageImpl(GL gl, TextureData data, int newTarget, int mipmapLevel,
+ private void updateSubImageImpl(final GL gl, final TextureData data, final int newTarget, final int mipmapLevel,
int dstx, int dsty,
int srcx, int srcy, int width, int height) throws GLException {
data.setHaveEXTABGR(gl.isExtensionAvailable(GLExtensions.EXT_abgr));
@@ -994,15 +1081,15 @@ public class Texture {
data.getInternalFormat(),
buffer.remaining(), buffer);
} else {
- int[] align = { 0 };
- int[] rowLength = { 0 };
- int[] skipRows = { 0 };
- int[] skipPixels = { 0 };
+ final int[] align = { 0 };
+ final int[] rowLength = { 0 };
+ final int[] skipRows = { 0 };
+ final int[] skipPixels = { 0 };
gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, align, 0); // save alignment
if(gl.isGL2GL3()) {
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_ROW_LENGTH, rowLength, 0); // save row length
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_SKIP_ROWS, skipRows, 0); // save skipped rows
- gl.glGetIntegerv(GL2GL3.GL_UNPACK_SKIP_PIXELS, skipPixels, 0); // save skipped pixels
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_ROW_LENGTH, rowLength, 0); // save row length
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_ROWS, skipRows, 0); // save skipped rows
+ gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_PIXELS, skipPixels, 0); // save skipped pixels
}
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, data.getAlignment());
if (DEBUG && VERBOSE) {
@@ -1015,9 +1102,9 @@ public class Texture {
System.out.println("height = " + height);
}
if(gl.isGL2GL3()) {
- gl.glPixelStorei(GL2GL3.GL_UNPACK_ROW_LENGTH, rowlen);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_ROWS, srcy);
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_PIXELS, srcx);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, rowlen);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, srcy);
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, srcx);
} else {
if ( rowlen!=0 && rowlen!=width &&
srcy!=0 && srcx!=0 ) {
@@ -1031,14 +1118,14 @@ public class Texture {
buffer);
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, align[0]); // restore alignment
if(gl.isGL2GL3()) {
- gl.glPixelStorei(GL2GL3.GL_UNPACK_ROW_LENGTH, rowLength[0]); // restore row length
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_ROWS, skipRows[0]); // restore skipped rows
- gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_PIXELS, skipPixels[0]); // restore skipped pixels
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, rowLength[0]); // restore row length
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, skipRows[0]); // restore skipped rows
+ gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, skipPixels[0]); // restore skipped pixels
}
}
}
- private void checkCompressedTextureExtensions(GL gl, TextureData data) {
+ private void checkCompressedTextureExtensions(final GL gl, final TextureData data) {
if (data.isDataCompressed()) {
switch (data.getInternalFormat()) {
case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
@@ -1058,10 +1145,10 @@ public class Texture {
}
}
- private boolean validateTexID(GL gl, boolean throwException) {
+ private boolean validateTexID(final GL gl, final boolean throwException) {
if( 0 == texID ) {
if( null != gl ) {
- int[] tmp = new int[1];
+ final int[] tmp = new int[1];
gl.glGenTextures(1, tmp, 0);
texID = tmp[0];
if ( 0 == texID && throwException ) {
@@ -1075,22 +1162,22 @@ public class Texture {
}
// Helper routines for disabling certain codepaths
- private static boolean haveNPOT(GL gl) {
+ private static boolean haveNPOT(final GL gl) {
return !disableNPOT && gl.isNPOTTextureAvailable();
}
- private static boolean haveTexRect(GL gl) {
+ private static boolean haveTexRect(final GL gl) {
return (!disableTexRect &&
TextureIO.isTexRectEnabled() &&
gl.isExtensionAvailable(GLExtensions.ARB_texture_rectangle));
}
- private static boolean preferTexRect(GL gl) {
+ private static boolean preferTexRect(final GL gl) {
// Prefer GL_ARB_texture_rectangle on ATI hardware on Mac OS X
// due to software fallbacks
if (NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
- String vendor = gl.glGetString(GL.GL_VENDOR);
+ final String vendor = gl.glGetString(GL.GL_VENDOR);
if (vendor != null && vendor.startsWith("ATI")) {
return true;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java
index 39647039b..17fcc7016 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java
@@ -1,21 +1,22 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2012 JogAmp Community. All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -47,14 +48,14 @@ package com.jogamp.opengl.util.texture;
public class TextureCoords {
// These represent the lower-left point
- private float left;
- private float bottom;
+ private final float left;
+ private final float bottom;
// These represent the upper-right point
- private float right;
- private float top;
+ private final float right;
+ private final float top;
- public TextureCoords(float left, float bottom,
- float right, float top) {
+ public TextureCoords(final float left, final float bottom,
+ final float right, final float top) {
this.left = left;
this.bottom = bottom;
this.right = right;
@@ -69,14 +70,14 @@ public class TextureCoords {
* right top
* </pre>
*/
- public float[] getST_LB_RB_LT_RT(float[] d, int d_off, float ss, float ts) {
+ public float[] getST_LB_RB_LT_RT(final float[] d, final int d_off, final float ss, final float ts) {
d[0+d_off] = left *ss; d[1+d_off] = bottom*ts;
d[2+d_off] = right *ss; d[3+d_off] = bottom*ts;
d[4+d_off] = left *ss; d[5+d_off] = top *ts;
d[6+d_off] = right *ss; d[7+d_off] = top *ts;
return d;
}
-
+
/** Returns the leftmost (x) texture coordinate of this
rectangle. */
public float left() { return left; }
@@ -92,6 +93,7 @@ public class TextureCoords {
/** Returns the topmost (y) texture coordinate of this
rectangle. */
public float top() { return top; }
-
+
+ @Override
public String toString() { return "TexCoord[h: "+left+" - "+right+", v: "+bottom+" - "+top+"]"; }
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
index 96ee233fd..5b2e4fc00 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
@@ -1,21 +1,22 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -40,7 +41,9 @@ import java.nio.Buffer;
import javax.media.opengl.GLProfile;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.GLBuffers;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
/**
* Represents the data for an OpenGL texture. This is separated from
@@ -54,11 +57,13 @@ import com.jogamp.opengl.util.GLBuffers;
*/
public class TextureData {
+ /** ColorSpace of pixel data. */
+ public static enum ColorSpace { RGB, YCbCr, YCCK, CMYK };
+
protected int width;
protected int height;
private int border;
- protected int pixelFormat;
- protected int pixelType;
+ protected GLPixelAttributes pixelAttributes;
protected int internalFormat; // perhaps inferred from pixelFormat?
protected boolean mipmap; // indicates whether mipmaps should be generated
// (ignored if mipmaps are supplied from the file)
@@ -77,8 +82,9 @@ public class TextureData {
protected boolean haveEXTABGR;
protected boolean haveGL12;
protected GLProfile glProfile;
+ protected ColorSpace pixelCS = ColorSpace.RGB;
- /**
+ /**
* Constructs a new TextureData object with the specified parameters
* and data contained in the given Buffer. The optional Flusher can
* be used to clean up native resources associated with this
@@ -118,18 +124,72 @@ public class TextureData {
* data were invalid, such as requesting mipmap generation for a
* compressed texture
*/
- public TextureData(GLProfile glp,
- int internalFormat,
- int width,
- int height,
- int border,
- int pixelFormat,
- int pixelType,
- boolean mipmap,
- boolean dataIsCompressed,
- boolean mustFlipVertically,
- Buffer buffer,
- Flusher flusher) throws IllegalArgumentException {
+ public TextureData(final GLProfile glp,
+ final int internalFormat,
+ final int width,
+ final int height,
+ final int border,
+ final int pixelFormat,
+ final int pixelType,
+ final boolean mipmap,
+ final boolean dataIsCompressed,
+ final boolean mustFlipVertically,
+ final Buffer buffer,
+ final Flusher flusher) throws IllegalArgumentException {
+ this(glp, internalFormat, width, height, border, new GLPixelAttributes(pixelFormat, pixelType),
+ mipmap, dataIsCompressed, mustFlipVertically, buffer, flusher);
+ }
+
+ /**
+ * Constructs a new TextureData object with the specified parameters
+ * and data contained in the given Buffer. The optional Flusher can
+ * be used to clean up native resources associated with this
+ * TextureData when processing is complete; for example, closing of
+ * memory-mapped files that might otherwise require a garbage
+ * collection to reclaim and close.
+ *
+ * @param glp the OpenGL Profile this texture data should be
+ * created for.
+ * @param internalFormat the OpenGL internal format for the
+ * resulting texture; must be specified, may
+ * not be 0
+ * @param width the width in pixels of the texture
+ * @param height the height in pixels of the texture
+ * @param border the number of pixels of border this texture
+ * data has (0 or 1)
+ * @param pixelAttributes the OpenGL pixel format and type for the
+ * resulting texture; must be specified, may
+ * not be 0
+ * @param mipmap indicates whether mipmaps should be
+ * autogenerated (using GLU) for the resulting
+ * texture. Currently if mipmap is true then
+ * dataIsCompressed may not be true.
+ * @param dataIsCompressed indicates whether the texture data is in
+ * compressed form
+ * (e.g. GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
+ * @param mustFlipVertically indicates whether the texture
+ * coordinates must be flipped vertically
+ * in order to properly display the
+ * texture
+ * @param buffer the buffer containing the texture data
+ * @param flusher optional flusher to perform cleanup tasks
+ * upon call to flush()
+ *
+ * @throws IllegalArgumentException if any parameters of the texture
+ * data were invalid, such as requesting mipmap generation for a
+ * compressed texture
+ */
+ public TextureData(final GLProfile glp,
+ final int internalFormat,
+ final int width,
+ final int height,
+ final int border,
+ final GLPixelAttributes pixelAttributes,
+ final boolean mipmap,
+ final boolean dataIsCompressed,
+ final boolean mustFlipVertically,
+ final Buffer buffer,
+ final Flusher flusher) throws IllegalArgumentException {
if (mipmap && dataIsCompressed) {
throw new IllegalArgumentException("Can not generate mipmaps for compressed textures");
}
@@ -138,8 +198,7 @@ public class TextureData {
this.width = width;
this.height = height;
this.border = border;
- this.pixelFormat = pixelFormat;
- this.pixelType = pixelType;
+ this.pixelAttributes = pixelAttributes;
this.internalFormat = internalFormat;
this.mipmap = mipmap;
this.dataIsCompressed = dataIsCompressed;
@@ -150,7 +209,7 @@ public class TextureData {
estimatedMemorySize = estimatedMemorySize(buffer);
}
- /**
+ /**
* Constructs a new TextureData object with the specified parameters
* and data for multiple mipmap levels contained in the given array
* of Buffers. The optional Flusher can be used to clean up native
@@ -189,27 +248,78 @@ public class TextureData {
* data were invalid, such as requesting mipmap generation for a
* compressed texture
*/
- public TextureData(GLProfile glp,
- int internalFormat,
- int width,
- int height,
- int border,
- int pixelFormat,
- int pixelType,
- boolean dataIsCompressed,
- boolean mustFlipVertically,
- Buffer[] mipmapData,
- Flusher flusher) throws IllegalArgumentException {
+ public TextureData(final GLProfile glp,
+ final int internalFormat,
+ final int width,
+ final int height,
+ final int border,
+ final int pixelFormat,
+ final int pixelType,
+ final boolean dataIsCompressed,
+ final boolean mustFlipVertically,
+ final Buffer[] mipmapData,
+ final Flusher flusher) throws IllegalArgumentException {
+ this(glp, internalFormat, width, height, border, new GLPixelAttributes(pixelFormat, pixelType),
+ dataIsCompressed, mustFlipVertically, mipmapData, flusher);
+ }
+
+ /**
+ * Constructs a new TextureData object with the specified parameters
+ * and data for multiple mipmap levels contained in the given array
+ * of Buffers. The optional Flusher can be used to clean up native
+ * resources associated with this TextureData when processing is
+ * complete; for example, closing of memory-mapped files that might
+ * otherwise require a garbage collection to reclaim and close.
+ *
+ * @param glp the OpenGL Profile this texture data should be
+ * created for.
+ * @param internalFormat the OpenGL internal format for the
+ * resulting texture; must be specified, may
+ * not be 0
+ * @param width the width in pixels of the topmost mipmap
+ * level of the texture
+ * @param height the height in pixels of the topmost mipmap
+ * level of the texture
+ * @param border the number of pixels of border this texture
+ * data has (0 or 1)
+ * @param pixelAttributes the OpenGL pixel format and type for the
+ * resulting texture; must be specified, may
+ * not be 0
+ * @param dataIsCompressed indicates whether the texture data is in
+ * compressed form
+ * (e.g. GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
+ * @param mustFlipVertically indicates whether the texture
+ * coordinates must be flipped vertically
+ * in order to properly display the
+ * texture
+ * @param mipmapData the buffers containing all mipmap levels
+ * of the texture's data
+ * @param flusher optional flusher to perform cleanup tasks
+ * upon call to flush()
+ *
+ * @throws IllegalArgumentException if any parameters of the texture
+ * data were invalid, such as requesting mipmap generation for a
+ * compressed texture
+ */
+ public TextureData(final GLProfile glp,
+ final int internalFormat,
+ final int width,
+ final int height,
+ final int border,
+ final GLPixelAttributes pixelAttributes,
+ final boolean dataIsCompressed,
+ final boolean mustFlipVertically,
+ final Buffer[] mipmapData,
+ final Flusher flusher) throws IllegalArgumentException {
this.glProfile = glp;
this.width = width;
this.height = height;
this.border = border;
- this.pixelFormat = pixelFormat;
- this.pixelType = pixelType;
+ this.pixelAttributes = pixelAttributes;
this.internalFormat = internalFormat;
this.dataIsCompressed = dataIsCompressed;
this.mustFlipVertically = mustFlipVertically;
- this.mipmapData = (Buffer[]) mipmapData.clone();
+ this.mipmapData = mipmapData.clone();
this.flusher = flusher;
alignment = 1; // FIXME: is this correct enough in all situations?
for (int i = 0; i < mipmapData.length; i++) {
@@ -217,41 +327,57 @@ public class TextureData {
}
}
+ /**
+ * Returns the color space of the pixel data.
+ * @see #setColorSpace(ColorSpace)
+ */
+ public ColorSpace getColorSpace() { return pixelCS; }
+
+ /**
+ * Set the color space of the pixel data, which defaults to {@link ColorSpace#RGB}.
+ * @see #getColorSpace()
+ */
+ public void setColorSpace(final ColorSpace cs) { pixelCS = cs; }
+
/** Used only by subclasses */
- protected TextureData(GLProfile glp) { this.glProfile = glp; }
+ protected TextureData(final GLProfile glp) { this.glProfile = glp; this.pixelAttributes = GLPixelAttributes.UNDEF; }
/** Returns the width in pixels of the texture data. */
public int getWidth() { return width; }
/** Returns the height in pixels of the texture data. */
public int getHeight() { return height; }
/** Returns the border in pixels of the texture data. */
- public int getBorder() {
- return border;
+ public int getBorder() {
+ return border;
+ }
+ /** Returns the intended OpenGL {@link GLPixelAttributes} of the texture data, i.e. format and type. */
+ public GLPixelAttributes getPixelAttributes() {
+ return pixelAttributes;
}
- /** Returns the intended OpenGL pixel format of the texture data. */
+ /** Returns the intended OpenGL pixel format of the texture data using {@link #getPixelAttributes()}. */
public int getPixelFormat() {
- return pixelFormat;
+ return pixelAttributes.format;
}
- /** Returns the intended OpenGL pixel type of the texture data. */
+ /** Returns the intended OpenGL pixel type of the texture data using {@link #getPixelAttributes()}. */
public int getPixelType() {
- return pixelType;
+ return pixelAttributes.type;
}
/** Returns the intended OpenGL internal format of the texture data. */
- public int getInternalFormat() {
- return internalFormat;
+ public int getInternalFormat() {
+ return internalFormat;
}
/** Returns whether mipmaps should be generated for the texture data. */
- public boolean getMipmap() {
- return mipmap;
+ public boolean getMipmap() {
+ return mipmap;
}
/** Indicates whether the texture data is in compressed form. */
- public boolean isDataCompressed() {
- return dataIsCompressed;
+ public boolean isDataCompressed() {
+ return dataIsCompressed;
}
/** Indicates whether the texture coordinates must be flipped
vertically for proper display. */
- public boolean getMustFlipVertically() {
- return mustFlipVertically;
+ public boolean getMustFlipVertically() {
+ return mustFlipVertically;
}
/** Returns the texture data, or null if it is specified as a set of mipmaps. */
public Buffer getBuffer() {
@@ -259,61 +385,81 @@ public class TextureData {
}
/** Returns all mipmap levels for the texture data, or null if it is
specified as a single image. */
- public Buffer[] getMipmapData() {
- return mipmapData;
+ public Buffer[] getMipmapData() {
+ return mipmapData;
}
/** Returns the required byte alignment for the texture data. */
- public int getAlignment() {
- return alignment;
+ public int getAlignment() {
+ return alignment;
}
/** Returns the row length needed for correct GL_UNPACK_ROW_LENGTH
specification. This is currently only supported for
non-mipmapped, non-compressed textures. */
- public int getRowLength() {
- return rowLength;
+ public int getRowLength() {
+ return rowLength;
}
/** Sets the width in pixels of the texture data. */
- public void setWidth(int width) { this.width = width; }
+ public void setWidth(final int width) { this.width = width; }
/** Sets the height in pixels of the texture data. */
- public void setHeight(int height) { this.height = height; }
+ public void setHeight(final int height) { this.height = height; }
/** Sets the border in pixels of the texture data. */
- public void setBorder(int border) { this.border = border; }
+ public void setBorder(final int border) { this.border = border; }
/** Sets the intended OpenGL pixel format of the texture data. */
- public void setPixelFormat(int pixelFormat) { this.pixelFormat = pixelFormat; }
- /** Sets the intended OpenGL pixel type of the texture data. */
- public void setPixelType(int pixelType) { this.pixelType = pixelType; }
+ public void setPixelAttributes(final GLPixelAttributes pixelAttributes) { this.pixelAttributes = pixelAttributes; }
+ /**
+ * Sets the intended OpenGL pixel format component of {@link GLPixelAttributes} of the texture data.
+ * <p>
+ * Use {@link #setPixelAttributes(GLPixelAttributes)}, if setting format and type.
+ * </p>
+ */
+ public void setPixelFormat(final int pixelFormat) {
+ if( pixelAttributes.format != pixelFormat ) {
+ pixelAttributes = new GLPixelAttributes(pixelFormat, pixelAttributes.type);
+ }
+ }
+ /**
+ * Sets the intended OpenGL pixel type component of {@link GLPixelAttributes} of the texture data.
+ * <p>
+ * Use {@link #setPixelAttributes(GLPixelAttributes)}, if setting format and type.
+ * </p>
+ */
+ public void setPixelType(final int pixelType) {
+ if( pixelAttributes.type != pixelType) {
+ pixelAttributes = new GLPixelAttributes(pixelAttributes.format, pixelType);
+ }
+ }
/** Sets the intended OpenGL internal format of the texture data. */
- public void setInternalFormat(int internalFormat) { this.internalFormat = internalFormat; }
+ public void setInternalFormat(final int internalFormat) { this.internalFormat = internalFormat; }
/** Sets whether mipmaps should be generated for the texture data. */
- public void setMipmap(boolean mipmap) { this.mipmap = mipmap; }
+ public void setMipmap(final boolean mipmap) { this.mipmap = mipmap; }
/** Sets whether the texture data is in compressed form. */
- public void setIsDataCompressed(boolean compressed) { this.dataIsCompressed = compressed; }
+ public void setIsDataCompressed(final boolean compressed) { this.dataIsCompressed = compressed; }
/** Sets whether the texture coordinates must be flipped vertically
for proper display. */
- public void setMustFlipVertically(boolean mustFlipVertically) { this.mustFlipVertically = mustFlipVertically; }
+ public void setMustFlipVertically(final boolean mustFlipVertically) { this.mustFlipVertically = mustFlipVertically; }
/** Sets the texture data. */
- public void setBuffer(Buffer buffer) {
+ public void setBuffer(final Buffer buffer) {
this.buffer = buffer;
estimatedMemorySize = estimatedMemorySize(buffer);
}
/** Sets the required byte alignment for the texture data. */
- public void setAlignment(int alignment) { this.alignment = alignment; }
+ public void setAlignment(final int alignment) { this.alignment = alignment; }
/** Sets the row length needed for correct GL_UNPACK_ROW_LENGTH
specification. This is currently only supported for
non-mipmapped, non-compressed textures. */
- public void setRowLength(int rowLength) { this.rowLength = rowLength; }
+ public void setRowLength(final int rowLength) { this.rowLength = rowLength; }
/** Indicates to this TextureData whether the GL_EXT_abgr extension
is available. Used for optimization along some code paths to
avoid data copies. */
- public void setHaveEXTABGR(boolean haveEXTABGR) {
+ public void setHaveEXTABGR(final boolean haveEXTABGR) {
this.haveEXTABGR = haveEXTABGR;
}
/** Indicates to this TextureData whether OpenGL version 1.2 is
available. If not, falls back to relatively inefficient code
paths for several input data types (several kinds of packed
pixel formats, in particular). */
- public void setHaveGL12(boolean haveGL12) {
+ public void setHaveGL12(final boolean haveGL12) {
this.haveGL12 = haveGL12;
}
@@ -354,18 +500,20 @@ public class TextureData {
public void flush();
}
+ @Override
public String toString() {
- return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", internFormat 0x"+Integer.toHexString(internalFormat)+", pixelFormat 0x"+Integer.toHexString(pixelFormat)+", pixelType 0x"+Integer.toHexString(pixelType)+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength;
+ return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", internFormat 0x"+Integer.toHexString(internalFormat)+", "+
+ pixelAttributes+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength;
}
//----------------------------------------------------------------------
// Internals only below this point
//
- protected static int estimatedMemorySize(Buffer buffer) {
+ protected static int estimatedMemorySize(final Buffer buffer) {
if (buffer == null) {
return 0;
}
- return buffer.capacity() * GLBuffers.sizeOfBufferElem(buffer);
+ return buffer.capacity() * Buffers.sizeOfBufferElem(buffer);
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
index b878c6002..6011afe7b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2011 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,17 +41,23 @@
package com.jogamp.opengl.util.texture;
import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.net.URL;
import java.nio.Buffer;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2GL3;
@@ -62,9 +68,12 @@ import javax.media.opengl.GLProfile;
import jogamp.opengl.Debug;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.util.GLPixelStorageModes;
+import com.jogamp.opengl.util.PNGPixelRect;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
import com.jogamp.opengl.util.texture.spi.DDSImage;
+import com.jogamp.opengl.util.texture.spi.JPEGImage;
import com.jogamp.opengl.util.texture.spi.NetPbmTextureWriter;
-import com.jogamp.opengl.util.texture.spi.PNGImage;
import com.jogamp.opengl.util.texture.spi.SGIImage;
import com.jogamp.opengl.util.texture.spi.TGAImage;
import com.jogamp.opengl.util.texture.spi.TextureProvider;
@@ -158,11 +167,11 @@ public class TextureIO {
/** Constant which can be used as a file suffix to indicate a PAM
file, NetPbm magic 7 - binary RGB and RGBA. Write support only. */
public static final String PAM = "pam";
-
+
/** Constant which can be used as a file suffix to indicate a PAM
file, NetPbm magic 6 - binary RGB. Write support only. */
public static final String PPM = "ppm";
-
+
private static final boolean DEBUG = Debug.debug("TextureIO");
// For manually disabling the use of the texture rectangle
@@ -201,8 +210,8 @@ public class TextureIO {
* registered texture providers could read the file
* @throws IOException if an error occurred while reading the file
*/
- public static TextureData newTextureData(GLProfile glp, File file,
- boolean mipmap,
+ public static TextureData newTextureData(final GLProfile glp, final File file,
+ final boolean mipmap,
String fileSuffix) throws IOException {
if (fileSuffix == null) {
fileSuffix = IOUtil.getFileSuffix(file);
@@ -231,9 +240,9 @@ public class TextureIO {
* registered texture providers could read the stream
* @throws IOException if an error occurred while reading the stream
*/
- public static TextureData newTextureData(GLProfile glp, InputStream stream,
- boolean mipmap,
- String fileSuffix) throws IOException {
+ public static TextureData newTextureData(final GLProfile glp, final InputStream stream,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
return newTextureDataImpl(glp, stream, 0, 0, mipmap, fileSuffix);
}
@@ -258,8 +267,8 @@ public class TextureIO {
* registered texture providers could read the URL
* @throws IOException if an error occurred while reading the URL
*/
- public static TextureData newTextureData(GLProfile glp, URL url,
- boolean mipmap,
+ public static TextureData newTextureData(final GLProfile glp, final URL url,
+ final boolean mipmap,
String fileSuffix) throws IOException {
if (fileSuffix == null) {
fileSuffix = IOUtil.getFileSuffix(url.getPath());
@@ -306,10 +315,10 @@ public class TextureIO {
* pixelFormat was 0
* @throws IOException if an error occurred while reading the file
*/
- public static TextureData newTextureData(GLProfile glp, File file,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
+ public static TextureData newTextureData(final GLProfile glp, final File file,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
String fileSuffix) throws IOException, IllegalArgumentException {
if ((internalFormat == 0) || (pixelFormat == 0)) {
throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero");
@@ -354,11 +363,11 @@ public class TextureIO {
* pixelFormat was 0
* @throws IOException if an error occurred while reading the stream
*/
- public static TextureData newTextureData(GLProfile glp, InputStream stream,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException, IllegalArgumentException {
+ public static TextureData newTextureData(final GLProfile glp, final InputStream stream,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException, IllegalArgumentException {
if ((internalFormat == 0) || (pixelFormat == 0)) {
throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero");
}
@@ -398,10 +407,10 @@ public class TextureIO {
* pixelFormat was 0
* @throws IOException if an error occurred while reading the URL
*/
- public static TextureData newTextureData(GLProfile glp, URL url,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
+ public static TextureData newTextureData(final GLProfile glp, final URL url,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
String fileSuffix) throws IOException, IllegalArgumentException {
if ((internalFormat == 0) || (pixelFormat == 0)) {
throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero");
@@ -418,7 +427,7 @@ public class TextureIO {
// methods that *do* require a current context
//
- /**
+ /**
* Creates an OpenGL texture object from the specified TextureData
* using the current OpenGL context.
*
@@ -427,11 +436,11 @@ public class TextureIO {
* OpenGL error occurred
* @throws IllegalArgumentException if the passed TextureData was null
*/
- public static Texture newTexture(TextureData data) throws GLException, IllegalArgumentException {
+ public static Texture newTexture(final TextureData data) throws GLException, IllegalArgumentException {
return newTexture(GLContext.getCurrentGL(), data);
}
- /**
+ /**
* Creates an OpenGL texture object from the specified TextureData
* using the given OpenGL context.
*
@@ -440,14 +449,14 @@ public class TextureIO {
* OpenGL error occurred
* @throws IllegalArgumentException if the passed TextureData was null
*/
- public static Texture newTexture(GL gl, TextureData data) throws GLException, IllegalArgumentException {
+ public static Texture newTexture(final GL gl, final TextureData data) throws GLException, IllegalArgumentException {
if (data == null) {
throw new IllegalArgumentException("Null TextureData");
}
return new Texture(gl, data);
}
-
- /**
+
+ /**
* Creates an OpenGL texture object from the specified file using
* the current OpenGL context.
*
@@ -462,16 +471,16 @@ public class TextureIO {
* @throws GLException if no OpenGL context is current or if an
* OpenGL error occurred
*/
- public static Texture newTexture(File file, boolean mipmap) throws IOException, GLException {
- GL gl = GLContext.getCurrentGL();
- GLProfile glp = gl.getGLProfile();
- TextureData data = newTextureData(glp, file, mipmap, IOUtil.getFileSuffix(file));
- Texture texture = newTexture(gl, data);
+ public static Texture newTexture(final File file, final boolean mipmap) throws IOException, GLException {
+ final GL gl = GLContext.getCurrentGL();
+ final GLProfile glp = gl.getGLProfile();
+ final TextureData data = newTextureData(glp, file, mipmap, IOUtil.getFileSuffix(file));
+ final Texture texture = newTexture(gl, data);
data.flush();
return texture;
}
- /**
+ /**
* Creates an OpenGL texture object from the specified stream using
* the current OpenGL context.
*
@@ -491,16 +500,16 @@ public class TextureIO {
* @throws GLException if no OpenGL context is current or if an
* OpenGL error occurred
*/
- public static Texture newTexture(InputStream stream, boolean mipmap, String fileSuffix) throws IOException, GLException {
- GL gl = GLContext.getCurrentGL();
- GLProfile glp = gl.getGLProfile();
- TextureData data = newTextureData(glp, stream, mipmap, fileSuffix);
- Texture texture = newTexture(gl, data);
+ public static Texture newTexture(final InputStream stream, final boolean mipmap, final String fileSuffix) throws IOException, GLException {
+ final GL gl = GLContext.getCurrentGL();
+ final GLProfile glp = gl.getGLProfile();
+ final TextureData data = newTextureData(glp, stream, mipmap, fileSuffix);
+ final Texture texture = newTexture(gl, data);
data.flush();
return texture;
}
- /**
+ /**
* Creates an OpenGL texture object from the specified URL using the
* current OpenGL context.
*
@@ -520,71 +529,32 @@ public class TextureIO {
* @throws GLException if no OpenGL context is current or if an
* OpenGL error occurred
*/
- public static Texture newTexture(URL url, boolean mipmap, String fileSuffix) throws IOException, GLException {
+ public static Texture newTexture(final URL url, final boolean mipmap, String fileSuffix) throws IOException, GLException {
if (fileSuffix == null) {
fileSuffix = IOUtil.getFileSuffix(url.getPath());
}
- GL gl = GLContext.getCurrentGL();
- GLProfile glp = gl.getGLProfile();
- TextureData data = newTextureData(glp, url, mipmap, fileSuffix);
- Texture texture = newTexture(gl, data);
+ final GL gl = GLContext.getCurrentGL();
+ final GLProfile glp = gl.getGLProfile();
+ final TextureData data = newTextureData(glp, url, mipmap, fileSuffix);
+ final Texture texture = newTexture(gl, data);
data.flush();
return texture;
}
- /**
+ /**
* Creates an OpenGL texture object associated with the given OpenGL
* texture target. The texture has
* no initial data. This is used, for example, to construct cube
* maps out of multiple TextureData objects.
*
- * @param target the OpenGL target type, eg GL.GL_TEXTURE_2D,
+ * @param target the OpenGL target type, eg GL.GL_TEXTURE_2D,
* GL.GL_TEXTURE_RECTANGLE_ARB
*/
- public static Texture newTexture(int target) {
+ public static Texture newTexture(final int target) {
return new Texture(target);
}
/**
- * Wraps an OpenGL texture ID from an external library and allows
- * some of the base methods from the Texture class, such as
- * binding and querying of texture coordinates, to be used with
- * it. Attempts to update such textures' contents will yield
- * undefined results.
- *
- * @param textureID the OpenGL texture object to wrap
- * @param target the OpenGL texture target, eg GL.GL_TEXTURE_2D,
- * GL2.GL_TEXTURE_RECTANGLE
- * @param texWidth the width of the texture in pixels
- * @param texHeight the height of the texture in pixels
- * @param imgWidth the width of the image within the texture in
- * pixels (if the content is a sub-rectangle in the upper
- * left corner); otherwise, pass in texWidth
- * @param imgHeight the height of the image within the texture in
- * pixels (if the content is a sub-rectangle in the upper
- * left corner); otherwise, pass in texHeight
- * @param mustFlipVertically indicates whether the texture
- * coordinates must be flipped vertically
- * in order to properly display the
- * texture
- */
- public static Texture newTexture(int textureID,
- int target,
- int texWidth,
- int texHeight,
- int imgWidth,
- int imgHeight,
- boolean mustFlipVertically) {
- return new Texture(textureID,
- target,
- texWidth,
- texHeight,
- imgWidth,
- imgHeight,
- mustFlipVertically);
- }
-
- /**
* Writes the given texture to a file. The type of the file is
* inferred from its suffix. An OpenGL context must be current in
* order to fetch the texture data back from the OpenGL pipeline.
@@ -605,36 +575,40 @@ public class TextureIO {
* when it is written to disk, regardless of whether the underlying
* file format supports multiple mipmaps in a given file.
*
+ * <p>
+ * Method required a {@link GL2GL3} {@link GLProfile#GL2GL3 profile}.
+ * </p>
+ *
* @throws IOException if an error occurred during writing or no
* suitable writer was found
* @throws GLException if no OpenGL context was current or an
* OpenGL-related error occurred
*/
- public static void write(Texture texture, File file) throws IOException, GLException {
+ public static void write(final Texture texture, final File file) throws IOException, GLException {
if (texture.getTarget() != GL.GL_TEXTURE_2D) {
throw new GLException("Only GL_TEXTURE_2D textures are supported");
}
// First fetch the texture data
- GL _gl = GLContext.getCurrentGL();
+ final GL _gl = GLContext.getCurrentGL();
if (!_gl.isGL2GL3()) {
throw new GLException("Implementation only supports GL2GL3 (Use GLReadBufferUtil and the TextureData variant), have: " + _gl);
}
- GL2GL3 gl = _gl.getGL2();
+ final GL2GL3 gl = _gl.getGL2GL3();
texture.bind(gl);
- int internalFormat = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_INTERNAL_FORMAT);
- int width = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_WIDTH);
- int height = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_HEIGHT);
- int border = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_BORDER);
+ final int internalFormat = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2GL3.GL_TEXTURE_INTERNAL_FORMAT);
+ final int width = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2GL3.GL_TEXTURE_WIDTH);
+ final int height = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2GL3.GL_TEXTURE_HEIGHT);
+ final int border = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_BORDER);
TextureData data = null;
if (internalFormat == GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
internalFormat == GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
internalFormat == GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ||
internalFormat == GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) {
// Fetch using glGetCompressedTexImage
- int size = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_COMPRESSED_IMAGE_SIZE);
- ByteBuffer res = ByteBuffer.allocate(size);
+ final int size = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2GL3.GL_TEXTURE_COMPRESSED_IMAGE_SIZE);
+ final ByteBuffer res = ByteBuffer.allocate(size);
gl.glGetCompressedTexImage(GL.GL_TEXTURE_2D, 0, res);
data = new TextureData(gl.getGLProfile(), internalFormat, width, height, border, internalFormat, GL.GL_UNSIGNED_BYTE,
false, true, true, res, null);
@@ -643,7 +617,7 @@ public class TextureIO {
int fetchedFormat = 0;
switch (internalFormat) {
case GL.GL_RGB:
- case GL2.GL_BGR:
+ case GL2GL3.GL_BGR:
case GL.GL_RGB8:
bytesPerPixel = 3;
fetchedFormat = GL.GL_RGB;
@@ -660,19 +634,10 @@ public class TextureIO {
}
// Fetch using glGetTexImage
- int packAlignment = glGetInteger(gl, GL.GL_PACK_ALIGNMENT);
- int packRowLength = glGetInteger(gl, GL2.GL_PACK_ROW_LENGTH);
- int packSkipRows = glGetInteger(gl, GL2.GL_PACK_SKIP_ROWS);
- int packSkipPixels = glGetInteger(gl, GL2.GL_PACK_SKIP_PIXELS);
- int packSwapBytes = glGetInteger(gl, GL2.GL_PACK_SWAP_BYTES);
-
- gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
- gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, 0);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, 0);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, 0);
- gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 0);
-
- ByteBuffer res = ByteBuffer.allocate((width + (2 * border)) *
+ final GLPixelStorageModes psm = new GLPixelStorageModes();
+ psm.setPackAlignment(gl, 1);
+
+ final ByteBuffer res = ByteBuffer.allocate((width + (2 * border)) *
(height + (2 * border)) *
bytesPerPixel);
if (DEBUG) {
@@ -681,12 +646,8 @@ public class TextureIO {
}
gl.glGetTexImage(GL.GL_TEXTURE_2D, 0, fetchedFormat, GL.GL_UNSIGNED_BYTE, res);
- gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, packAlignment);
- gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, packRowLength);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, packSkipRows);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, packSkipPixels);
- gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, packSwapBytes);
-
+ psm.restore(gl);
+
data = new TextureData(gl.getGLProfile(), internalFormat, width, height, border, fetchedFormat, GL.GL_UNSIGNED_BYTE,
false, false, false, res, null);
@@ -698,10 +659,10 @@ public class TextureIO {
write(data, file);
}
-
- public static void write(TextureData data, File file) throws IOException, GLException {
- for (Iterator<TextureWriter> iter = textureWriters.iterator(); iter.hasNext(); ) {
- TextureWriter writer = iter.next();
+
+ public static void write(final TextureData data, final File file) throws IOException, GLException {
+ for (final Iterator<TextureWriter> iter = textureWriters.iterator(); iter.hasNext(); ) {
+ final TextureWriter writer = iter.next();
if (writer.write(file, data)) {
return;
}
@@ -709,23 +670,31 @@ public class TextureIO {
throw new IOException("No suitable texture writer found for "+file.getAbsolutePath());
}
-
+
//----------------------------------------------------------------------
// SPI support
//
- /** Adds a TextureProvider to support reading of a new file
- format. */
- public static void addTextureProvider(TextureProvider provider) {
+ /**
+ * Adds a TextureProvider to support reading of a new file format.
+ * <p>
+ * The last provider added, will be the first provider to be tested.
+ * </p>
+ */
+ public static void addTextureProvider(final TextureProvider provider) {
// Must always add at the front so the ImageIO provider is last,
// so we don't accidentally use it instead of a user's possibly
// more optimal provider
textureProviders.add(0, provider);
}
- /** Adds a TextureWriter to support writing of a new file
- format. */
- public static void addTextureWriter(TextureWriter writer) {
+ /**
+ * Adds a TextureWriter to support writing of a new file format.
+ * <p>
+ * The last provider added, will be the first provider to be tested.
+ * </p>
+ */
+ public static void addTextureWriter(final TextureWriter writer) {
// Must always add at the front so the ImageIO writer is last,
// so we don't accidentally use it instead of a user's possibly
// more optimal writer
@@ -750,7 +719,7 @@ public class TextureIO {
the GL_ARB_texture_rectangle extension to be turned off globally
for this purpose. The default is that the use of the extension
is enabled. */
- public static void setTexRectEnabled(boolean enabled) {
+ public static void setTexRectEnabled(final boolean enabled) {
texRectEnabled = enabled;
}
@@ -773,10 +742,10 @@ public class TextureIO {
if(GLProfile.isAWTAvailable()) {
try {
// Use reflection to avoid compile-time dependencies on AWT-related classes
- TextureProvider provider = (TextureProvider)
+ final TextureProvider provider = (TextureProvider)
Class.forName("com.jogamp.opengl.util.texture.spi.awt.IIOTextureProvider").newInstance();
addTextureProvider(provider);
- } catch (Exception e) {
+ } catch (final Exception e) {
if (DEBUG) {
e.printStackTrace();
}
@@ -787,20 +756,21 @@ public class TextureIO {
addTextureProvider(new DDSTextureProvider());
addTextureProvider(new SGITextureProvider());
addTextureProvider(new TGATextureProvider());
+ addTextureProvider(new JPGTextureProvider());
addTextureProvider(new PNGTextureProvider());
// ImageIO writer, the fall-back, must be the first one added
if(GLProfile.isAWTAvailable()) {
try {
// Use reflection to avoid compile-time dependencies on AWT-related classes
- TextureWriter writer = (TextureWriter)
+ final TextureWriter writer = (TextureWriter)
Class.forName("com.jogamp.opengl.util.texture.spi.awt.IIOTextureWriter").newInstance();
addTextureWriter(writer);
- } catch (Exception e) {
+ } catch (final Exception e) {
if (DEBUG) {
e.printStackTrace();
}
- } catch (Error e) {
+ } catch (final Error e) {
if (DEBUG) {
e.printStackTrace();
}
@@ -816,10 +786,10 @@ public class TextureIO {
}
// Implementation methods
- private static TextureData newTextureDataImpl(GLProfile glp, File file,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
+ private static TextureData newTextureDataImpl(final GLProfile glp, final File file,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
String fileSuffix) throws IOException {
if (file == null) {
throw new IOException("File was null");
@@ -827,9 +797,9 @@ public class TextureIO {
fileSuffix = toLowerCase(fileSuffix);
- for (Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) {
- TextureProvider provider = iter.next();
- TextureData data = provider.newTextureData(glp, file,
+ for (final Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) {
+ final TextureProvider provider = iter.next();
+ final TextureData data = provider.newTextureData(glp, file,
internalFormat,
pixelFormat,
mipmap,
@@ -842,10 +812,10 @@ public class TextureIO {
throw new IOException("No suitable reader for given file "+file.getAbsolutePath());
}
- private static TextureData newTextureDataImpl(GLProfile glp, InputStream stream,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
+ private static TextureData newTextureDataImpl(final GLProfile glp, InputStream stream,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
String fileSuffix) throws IOException {
if (stream == null) {
throw new IOException("Stream was null");
@@ -858,9 +828,9 @@ public class TextureIO {
stream = new BufferedInputStream(stream);
}
- for (Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) {
- TextureProvider provider = iter.next();
- TextureData data = provider.newTextureData(glp, stream,
+ for (final Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) {
+ final TextureProvider provider = iter.next();
+ final TextureData data = provider.newTextureData(glp, stream,
internalFormat,
pixelFormat,
mipmap,
@@ -873,10 +843,10 @@ public class TextureIO {
throw new IOException("No suitable reader for given stream");
}
- private static TextureData newTextureDataImpl(GLProfile glp, URL url,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
+ private static TextureData newTextureDataImpl(final GLProfile glp, final URL url,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
String fileSuffix) throws IOException {
if (url == null) {
throw new IOException("URL was null");
@@ -884,9 +854,9 @@ public class TextureIO {
fileSuffix = toLowerCase(fileSuffix);
- for (Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) {
- TextureProvider provider = iter.next();
- TextureData data = provider.newTextureData(glp, url,
+ for (final Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) {
+ final TextureProvider provider = iter.next();
+ final TextureData data = provider.newTextureData(glp, url,
internalFormat,
pixelFormat,
mipmap,
@@ -902,42 +872,45 @@ public class TextureIO {
//----------------------------------------------------------------------
// DDS provider -- supports files only for now
static class DDSTextureProvider implements TextureProvider {
- public TextureData newTextureData(GLProfile glp, File file,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final File file,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
if (DDS.equals(fileSuffix) ||
DDS.equals(IOUtil.getFileSuffix(file))) {
- DDSImage image = DDSImage.read(file);
+ final DDSImage image = DDSImage.read(file);
return newTextureData(glp, image, internalFormat, pixelFormat, mipmap);
}
return null;
}
- public TextureData newTextureData(GLProfile glp, InputStream stream,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final InputStream stream,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
if (DDS.equals(fileSuffix) ||
DDSImage.isDDSImage(stream)) {
- byte[] data = IOUtil.copyStream2ByteArray(stream);
- ByteBuffer buf = ByteBuffer.wrap(data);
- DDSImage image = DDSImage.read(buf);
+ final byte[] data = IOUtil.copyStream2ByteArray(stream);
+ final ByteBuffer buf = ByteBuffer.wrap(data);
+ final DDSImage image = DDSImage.read(buf);
return newTextureData(glp, image, internalFormat, pixelFormat, mipmap);
}
return null;
}
- public TextureData newTextureData(GLProfile glp, URL url,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
- InputStream stream = new BufferedInputStream(url.openStream());
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final URL url,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
+ final InputStream stream = new BufferedInputStream(url.openStream());
try {
return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix);
} finally {
@@ -945,11 +918,11 @@ public class TextureIO {
}
}
- private TextureData newTextureData(GLProfile glp, final DDSImage image,
+ private TextureData newTextureData(final GLProfile glp, final DDSImage image,
int internalFormat,
int pixelFormat,
boolean mipmap) {
- DDSImage.ImageInfo info = image.getMipMap(0);
+ final DDSImage.ImageInfo info = image.getMipMap(0);
if (pixelFormat == 0) {
switch (image.getPixelFormat()) {
case DDSImage.D3DFMT_R8G8B8:
@@ -986,14 +959,15 @@ public class TextureIO {
break;
}
}
- TextureData.Flusher flusher = new TextureData.Flusher() {
+ final TextureData.Flusher flusher = new TextureData.Flusher() {
+ @Override
public void flush() {
image.close();
}
};
TextureData data;
if (mipmap && image.getNumMipMaps() > 0) {
- Buffer[] mipmapData = new Buffer[image.getNumMipMaps()];
+ final Buffer[] mipmapData = new Buffer[image.getNumMipMaps()];
for (int i = 0; i < image.getNumMipMaps(); i++) {
mipmapData[i] = image.getMipMap(i).getData();
}
@@ -1030,12 +1004,13 @@ public class TextureIO {
//----------------------------------------------------------------------
// Base class for SGI RGB and TGA image providers
static abstract class StreamBasedTextureProvider implements TextureProvider {
- public TextureData newTextureData(GLProfile glp, File file,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
- InputStream inStream = new BufferedInputStream(new FileInputStream(file));
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final File file,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
+ final InputStream inStream = new BufferedInputStream(new FileInputStream(file));
try {
// The SGIImage and TGAImage implementations use InputStreams
// anyway so there isn't much point in having a separate code
@@ -1050,12 +1025,13 @@ public class TextureIO {
}
}
- public TextureData newTextureData(GLProfile glp, URL url,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
- InputStream stream = new BufferedInputStream(url.openStream());
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final URL url,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
+ final InputStream stream = new BufferedInputStream(url.openStream());
try {
return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix);
} finally {
@@ -1067,15 +1043,16 @@ public class TextureIO {
//----------------------------------------------------------------------
// SGI RGB image provider
static class SGITextureProvider extends StreamBasedTextureProvider {
- public TextureData newTextureData(GLProfile glp, InputStream stream,
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final InputStream stream,
int internalFormat,
int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
if (SGI.equals(fileSuffix) ||
SGI_RGB.equals(fileSuffix) ||
SGIImage.isSGIImage(stream)) {
- SGIImage image = SGIImage.read(stream);
+ final SGIImage image = SGIImage.read(stream);
if (pixelFormat == 0) {
pixelFormat = image.getFormat();
}
@@ -1102,18 +1079,19 @@ public class TextureIO {
//----------------------------------------------------------------------
// TGA (Targa) image provider
static class TGATextureProvider extends StreamBasedTextureProvider {
- public TextureData newTextureData(GLProfile glp, InputStream stream,
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final InputStream stream,
int internalFormat,
int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
if (TGA.equals(fileSuffix)) {
- TGAImage image = TGAImage.read(glp, stream);
+ final TGAImage image = TGAImage.read(glp, stream);
if (pixelFormat == 0) {
pixelFormat = image.getGLFormat();
}
if (internalFormat == 0) {
- if(glp.isGL2GL3()) {
+ if(glp.isGL2ES3()) {
internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA8:GL.GL_RGB8;
} else {
internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB;
@@ -1139,18 +1117,59 @@ public class TextureIO {
//----------------------------------------------------------------------
// PNG image provider
static class PNGTextureProvider extends StreamBasedTextureProvider {
- public TextureData newTextureData(GLProfile glp, InputStream stream,
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final InputStream stream,
int internalFormat,
int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
if (PNG.equals(fileSuffix)) {
- PNGImage image = PNGImage.read(/*glp, */ stream);
+ final PNGPixelRect image = PNGPixelRect.read(stream, null, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */);
+ final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp);
+ if ( 0 == pixelFormat ) {
+ pixelFormat = glpa.format;
+ } // else FIXME: Actually not supported w/ preset pixelFormat!
+ if ( 0 == internalFormat ) {
+ final boolean hasAlpha = 4 == glpa.bytesPerPixel;
+ if(glp.isGL2ES3()) {
+ internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ } else {
+ internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB;
+ }
+ }
+ return new TextureData(glp, internalFormat,
+ image.getSize().getWidth(),
+ image.getSize().getHeight(),
+ 0,
+ pixelFormat,
+ glpa.type,
+ mipmap,
+ false,
+ false,
+ image.getPixels(),
+ null);
+ }
+
+ return null;
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // JPEG image provider
+ static class JPGTextureProvider extends StreamBasedTextureProvider {
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final InputStream stream,
+ int internalFormat,
+ int pixelFormat,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
+ if (JPG.equals(fileSuffix)) {
+ final JPEGImage image = JPEGImage.read(/*glp, */ stream);
if (pixelFormat == 0) {
pixelFormat = image.getGLFormat();
}
if (internalFormat == 0) {
- if(glp.isGL2GL3()) {
+ if(glp.isGL2ES3()) {
internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA8:GL.GL_RGB8;
} else {
internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB;
@@ -1177,12 +1196,14 @@ public class TextureIO {
// DDS texture writer
//
static class DDSTextureWriter implements TextureWriter {
- public boolean write(File file,
- TextureData data) throws IOException {
+ @Override
+ public boolean write(final File file,
+ final TextureData data) throws IOException {
if (DDS.equals(IOUtil.getFileSuffix(file))) {
// See whether the DDS writer can handle this TextureData
- int pixelFormat = data.getPixelFormat();
- int pixelType = data.getPixelType();
+ final GLPixelAttributes pixelAttribs = data.getPixelAttributes();
+ final int pixelFormat = pixelAttribs.format;
+ final int pixelType = pixelAttribs.type;
if (pixelType != GL.GL_BYTE &&
pixelType != GL.GL_UNSIGNED_BYTE) {
throw new IOException("DDS writer only supports byte / unsigned byte textures");
@@ -1199,7 +1220,7 @@ public class TextureIO {
case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: d3dFormat = DDSImage.D3DFMT_DXT5; break;
default: throw new IOException("Unsupported pixel format 0x" + Integer.toHexString(pixelFormat) + " by DDS writer");
}
-
+
ByteBuffer[] mipmaps = null;
if (data.getMipmapData() != null) {
mipmaps = new ByteBuffer[data.getMipmapData().length];
@@ -1210,7 +1231,7 @@ public class TextureIO {
mipmaps = new ByteBuffer[] { (ByteBuffer) data.getBuffer() };
}
- DDSImage image = DDSImage.createFromData(d3dFormat,
+ final DDSImage image = DDSImage.createFromData(d3dFormat,
data.getWidth(),
data.getHeight(),
mipmaps);
@@ -1226,19 +1247,21 @@ public class TextureIO {
// SGI (rgb) texture writer
//
static class SGITextureWriter implements TextureWriter {
- public boolean write(File file,
- TextureData data) throws IOException {
- String fileSuffix = IOUtil.getFileSuffix(file);
+ @Override
+ public boolean write(final File file,
+ final TextureData data) throws IOException {
+ final String fileSuffix = IOUtil.getFileSuffix(file);
if (SGI.equals(fileSuffix) ||
SGI_RGB.equals(fileSuffix)) {
// See whether the SGI writer can handle this TextureData
- int pixelFormat = data.getPixelFormat();
- int pixelType = data.getPixelType();
+ final GLPixelAttributes pixelAttribs = data.getPixelAttributes();
+ final int pixelFormat = pixelAttribs.format;
+ final int pixelType = pixelAttribs.type;
if ((pixelFormat == GL.GL_RGB ||
pixelFormat == GL.GL_RGBA) &&
(pixelType == GL.GL_BYTE ||
pixelType == GL.GL_UNSIGNED_BYTE)) {
- ByteBuffer buf = ((data.getBuffer() != null) ?
+ final ByteBuffer buf = ((data.getBuffer() != null) ?
(ByteBuffer) data.getBuffer() :
(ByteBuffer) data.getMipmapData()[0]);
byte[] bytes;
@@ -1251,7 +1274,7 @@ public class TextureIO {
buf.rewind();
}
- SGIImage image = SGIImage.createFromData(data.getWidth(),
+ final SGIImage image = SGIImage.createFromData(data.getWidth(),
data.getHeight(),
(pixelFormat == GL.GL_RGBA),
bytes);
@@ -1268,39 +1291,41 @@ public class TextureIO {
//----------------------------------------------------------------------
// TGA (Targa) texture writer
-
+
static class TGATextureWriter implements TextureWriter {
- public boolean write(File file,
- TextureData data) throws IOException {
+ @Override
+ public boolean write(final File file,
+ final TextureData data) throws IOException {
if (TGA.equals(IOUtil.getFileSuffix(file))) {
// See whether the TGA writer can handle this TextureData
- int pixelFormat = data.getPixelFormat();
- int pixelType = data.getPixelType();
+ final GLPixelAttributes pixelAttribs = data.getPixelAttributes();
+ final int pixelFormat = pixelAttribs.format;
+ final int pixelType = pixelAttribs.type;
if ((pixelFormat == GL.GL_RGB ||
- pixelFormat == GL.GL_RGBA ||
- pixelFormat == GL2.GL_BGR ||
+ pixelFormat == GL.GL_RGBA ||
+ pixelFormat == GL2GL3.GL_BGR ||
pixelFormat == GL.GL_BGRA ) &&
(pixelType == GL.GL_BYTE ||
pixelType == GL.GL_UNSIGNED_BYTE)) {
-
+
ByteBuffer buf = (ByteBuffer) data.getBuffer();
if (null == buf) {
buf = (ByteBuffer) data.getMipmapData()[0];
}
buf.rewind();
-
- if( pixelFormat == GL.GL_RGB || pixelFormat == GL.GL_RGBA ) {
+
+ if( pixelFormat == GL.GL_RGB || pixelFormat == GL.GL_RGBA ) {
// Must reverse order of red and blue channels to get correct results
- int skip = ((pixelFormat == GL.GL_RGB) ? 3 : 4);
+ final int skip = ((pixelFormat == GL.GL_RGB) ? 3 : 4);
for (int i = 0; i < buf.remaining(); i += skip) {
- byte red = buf.get(i + 0);
- byte blue = buf.get(i + 2);
+ final byte red = buf.get(i + 0);
+ final byte blue = buf.get(i + 2);
buf.put(i + 0, blue);
buf.put(i + 2, red);
}
}
- TGAImage image = TGAImage.createFromData(data.getWidth(),
+ final TGAImage image = TGAImage.createFromData(data.getWidth(),
data.getHeight(),
(pixelFormat == GL.GL_RGBA || pixelFormat == GL.GL_BGRA),
false, buf);
@@ -1312,83 +1337,71 @@ public class TextureIO {
}
return false;
- }
+ }
}
//----------------------------------------------------------------------
// PNG texture writer
-
+
static class PNGTextureWriter implements TextureWriter {
- public boolean write(File file, TextureData data) throws IOException {
+ @Override
+ public boolean write(final File file, final TextureData data) throws IOException {
if (PNG.equals(IOUtil.getFileSuffix(file))) {
// See whether the PNG writer can handle this TextureData
- int pixelFormat = data.getPixelFormat();
- int pixelType = data.getPixelType();
- boolean reversedChannels;
- int bytesPerPixel;
- switch(pixelFormat) {
- case GL.GL_LUMINANCE:
- reversedChannels=false;
- bytesPerPixel=1;
- break;
- case GL.GL_RGB:
- reversedChannels=false;
- bytesPerPixel=3;
- break;
- case GL.GL_RGBA:
- reversedChannels=false;
- bytesPerPixel=4;
- break;
- case GL2.GL_BGR:
- reversedChannels=true;
- bytesPerPixel=3;
- break;
- case GL.GL_BGRA:
- reversedChannels=true;
- bytesPerPixel=4;
- break;
- default:
- reversedChannels=false;
- bytesPerPixel=-1;
- break;
- }
+ final GLPixelAttributes pixelAttribs = data.getPixelAttributes();
+ final int pixelFormat = pixelAttribs.format;
+ final int pixelType = pixelAttribs.type;
+ final int bytesPerPixel = pixelAttribs.bytesPerPixel;
+ final PixelFormat pixFmt = pixelAttribs.getPixelFormat();
if ( ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel) &&
- ( pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) {
- ByteBuffer buf = (ByteBuffer) data.getBuffer();
- if (null == buf) {
- buf = (ByteBuffer) data.getMipmapData()[0];
+ ( pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) {
+ Buffer buf0 = data.getBuffer();
+ if (null == buf0) {
+ buf0 = data.getMipmapData()[0];
+ }
+ if( null == buf0 ) {
+ throw new IOException("Pixel storage buffer is null");
+ }
+ final DimensionImmutable size = new Dimension(data.getWidth(), data.getHeight());
+ if( buf0 instanceof ByteBuffer ) {
+ final ByteBuffer buf = (ByteBuffer) buf0;
+ buf.rewind();
+ final PNGPixelRect image = new PNGPixelRect(pixFmt, size,
+ 0 /* stride */, !data.getMustFlipVertically() /* isGLOriented */, buf /* pixels */,
+ -1f, -1f);
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */));
+ image.write(outs, true /* close */);
+ return true;
+ } else if( buf0 instanceof IntBuffer ) {
+ final IntBuffer buf = (IntBuffer) buf0;
+ buf.rewind();
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */));
+ PNGPixelRect.write(pixFmt, size,
+ 0 /* stride */, !data.getMustFlipVertically() /* isGLOriented */, buf /* pixels */,
+ -1f, -1f, outs, true /* closeOutstream */);
+ return true;
+ } else {
+ throw new IOException("PNG writer doesn't support pixel storage buffer of type "+buf0.getClass().getName());
}
- buf.rewind();
-
- PNGImage image = PNGImage.createFromData(data.getWidth(), data.getHeight(), -1f, -1f,
- bytesPerPixel, reversedChannels, buf);
- image.write(file, true);
- return true;
}
throw new IOException("PNG writer doesn't support this pixel format 0x"+Integer.toHexString(pixelFormat)+
" / type 0x"+Integer.toHexString(pixelFormat)+" (only GL_RGB/A, GL_BGR/A + bytes)");
}
return false;
- }
+ }
}
-
+
//----------------------------------------------------------------------
// Helper routines
//
- private static int glGetInteger(GL gl, int pname) {
- int[] tmp = new int[1];
- gl.glGetIntegerv(pname, tmp, 0);
- return tmp[0];
- }
-
- private static int glGetTexLevelParameteri(GL2GL3 gl, int target, int level, int pname) {
- int[] tmp = new int[1];
+ private static int glGetTexLevelParameteri(final GL2GL3 gl, final int target, final int level, final int pname) {
+ final int[] tmp = new int[1];
gl.glGetTexLevelParameteriv(target, 0, pname, tmp, 0);
return tmp[0];
}
- private static String toLowerCase(String arg) {
+ private static String toLowerCase(final String arg) {
if (arg == null) {
return null;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
index 6b41c0bc8..5add4f695 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -28,30 +28,35 @@
package com.jogamp.opengl.util.texture;
import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLRunnable;
+import javax.media.opengl.GLEventListener;
+
+import com.jogamp.opengl.util.TimeFrameI;
/**
* Protocol for texture sequences, like animations, movies, etc.
* <p>
- * Ensure to respect the texture coordinates provided by
+ * Ensure to respect the texture coordinates provided by
* {@link TextureFrame}.{@link TextureFrame#getTexture() getTexture()}.{@link Texture#getImageTexCoords() getImageTexCoords()}.
* </p>
- * The user's shader shall be fitted for this implementation.
+ * The user's shader shall be fitted for this implementation.
* Assuming we use a base shader code w/o headers using </code>ShaderCode</code>.
* (Code copied from unit test / demo <code>TexCubeES2</code>)
* <pre>
- *
+ *
static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
static final String gl2_prelude = "#version 110\n";
static final String shaderBasename = "texsequence_xxx"; // the base shader code w/o headers
- static final String myTextureLookupName = "myTexture2D"; // the desired texture lookup function
-
+ static final String myTextureLookupName = "myTexture2D"; // the desired texture lookup function
+
private void initShader(GL2ES2 gl, TextureSequence texSeq) {
// Create & Compile the shader objects
- ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TexCubeES2.class,
+ ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TexCubeES2.class,
"shader", "shader/bin", shaderBasename, true);
- ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TexCubeES2.class,
+ ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TexCubeES2.class,
"shader", "shader/bin", shaderBasename, true);
-
+
// Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
int rsFpPos;
if(gl.isGLES2()) {
@@ -68,25 +73,25 @@ import javax.media.opengl.GL;
if(gl.isGLES2()) {
// insert ES2 default precision declaration
rsFpPos = rsFp.insertShaderSource(0, rsFpPos, es2_prelude[1]);
- }
+ }
// negotiate the texture lookup function name
final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName);
-
- // in case a fixed lookup function is being chosen, replace the name in our code
+
+ // in case a fixed lookup function is being chosen, replace the name in our code
rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName);
-
- // Cache the TextureSequence shader details in StringBuffer:
+
+ // Cache the TextureSequence shader details in StringBuilder:
final StringBuilder sFpIns = new StringBuilder();
-
+
// .. declaration of the texture sampler using the implementation specific type
sFpIns.append("uniform ").append(texSeq.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n");
-
+
// .. the actual texture lookup function, maybe null in case a built-in function is being used
sFpIns.append(texSeq.getTextureLookupFragmentShaderImpl());
-
+
// Now insert the TextureShader details in our shader after the given tag:
rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns);
-
+
// Create & Link the shader program
ShaderProgram sp = new ShaderProgram();
sp.add(rsVp);
@@ -98,40 +103,70 @@ import javax.media.opengl.GL;
* </pre>
* The above procedure might look complicated, however, it allows most flexibility and
* workarounds to also deal with GLSL bugs.
- *
+ *
*/
public interface TextureSequence {
- public static final String GL_OES_EGL_image_external_Required_Prelude = "#extension GL_OES_EGL_image_external : enable\n";
public static final String samplerExternalOES = "samplerExternalOES";
public static final String sampler2D = "sampler2D";
-
- /**
+
+ /**
* Texture holder interface, maybe specialized by implementation
- * to associated related data.
+ * to associated related data.
*/
- public static class TextureFrame {
- public TextureFrame(Texture t) {
+ public static class TextureFrame extends TimeFrameI {
+ public TextureFrame(final Texture t, final int pts, final int duration) {
+ super(pts, duration);
texture = t;
}
-
+ public TextureFrame(final Texture t) {
+ texture = t;
+ }
+
public final Texture getTexture() { return texture; }
-
+
+ @Override
public String toString() {
- return "TextureFrame[" + texture + "]";
+ return "TextureFrame[pts " + pts + " ms, l " + duration + " ms, texID "+ (null != texture ? texture.getTextureObject() : 0) + "]";
}
protected final Texture texture;
}
+ /**
+ * Event listener to notify users of updates regarding the {@link TextureSequence}.
+ * <p>
+ * Implementations sending events down to all listeners,
+ * while not necessarily making the user's OpenGL context current.
+ * </p>
+ * <p>
+ * Events may be sent from a 3rd-party thread, possibly holding another, maybe shared, OpenGL context current.<br/>
+ * Hence a user shall not issue <i>any</i> OpenGL, time consuming
+ * or {@link TextureSequence} operations directly.<br>
+ * Instead, the user shall:
+ * <ul>
+ * <li>off-load complex or {@link TextureSequence} commands on another thread, or</li>
+ * <li>injecting {@link GLRunnable} objects via {@link GLAutoDrawable#invoke(boolean, GLRunnable)}, or</li>
+ * <li>simply changing a volatile state of their {@link GLEventListener} implementation.</li>
+ * </ul>
+ * </p>
+ * */
public interface TexSeqEventListener<T extends TextureSequence> {
- /**
- * Signaling listeners that {@link TextureSequence#getNextTexture(GL, boolean)} is able to deliver a new frame.
- * @param ts the event source
- * @param when system time in msec.
+ /**
+ * Signaling listeners that a new {@link TextureFrame} is available.
+ * <p>
+ * User shall utilize {@link TextureSequence#getNextTexture(GL)} to dequeue it to maintain
+ * a consistent queue.
+ * </p>
+ * @param ts the event source
+ * @param newFrame the newly enqueued frame
+ * @param when system time in msec.
**/
- public void newFrameAvailable(T ts, long when);
+ public void newFrameAvailable(T ts, TextureFrame newFrame, long when);
}
-
- /** Return the texture unit to be used with this frame. */
+
+ /** Returns the texture target used by implementation. */
+ public int getTextureTarget();
+
+ /** Return the texture unit used to render the current frame. */
public int getTextureUnit();
public int[] getTextureMinMagFilter();
@@ -139,62 +174,68 @@ public interface TextureSequence {
public int[] getTextureWrapST();
/**
+ * Returns true if texture source is ready <i>and</i> a texture is available
+ * via {@link #getNextTexture(GL)} and {@link #getLastTexture()}.
+ */
+ public boolean isTextureAvailable();
+
+ /**
* Returns the last updated texture.
* <p>
* In case the instance is just initialized, it shall return a <code>TextureFrame</code>
- * object with valid attributes. The texture content may be undefined
- * until the first call of {@link #getNextTexture(GL, boolean)}.<br>
- * </p>
+ * object with valid attributes. The texture content may be undefined
+ * until the first call of {@link #getNextTexture(GL)}.<br>
+ * </p>
* Not blocking.
- *
- * @throws IllegalStateException if instance is not initialized
+ *
+ * @throws IllegalStateException if instance is not initialized
*/
public TextureFrame getLastTexture() throws IllegalStateException ;
/**
- * Returns the next texture to be rendered.
+ * Returns the next texture to be rendered.
* <p>
- * Implementation shall block until next frame is available if <code>blocking</code> is <code>true</code>,
- * otherwise it shall return the last frame in case a new frame is not available.
+ * Implementation shall return the next frame if available, may block if a next frame may arrive <i>soon</i>.
+ * Otherwise implementation shall return the last frame.
* </p>
* <p>
- * Shall return <code>null</code> in case <i>no</i> frame is available.
+ * Shall return <code>null</code> in case <i>no</i> next or last frame is available.
* </p>
- *
- * @throws IllegalStateException if instance is not initialized
+ *
+ * @throws IllegalStateException if instance is not initialized
*/
- public TextureFrame getNextTexture(GL gl, boolean blocking) throws IllegalStateException ;
-
+ public TextureFrame getNextTexture(GL gl) throws IllegalStateException ;
+
/**
- * In case a shader extension is required, based on the implementation
+ * In case a shader extension is required, based on the implementation
* and the runtime GL profile, this method returns the preprocessor macros, e.g.:
* <pre>
* #extension GL_OES_EGL_image_external : enable
- * </pre>
- *
- * @throws IllegalStateException if instance is not initialized
+ * </pre>
+ *
+ * @throws IllegalStateException if instance is not initialized
*/
public String getRequiredExtensionsShaderStub() throws IllegalStateException ;
-
- /**
+
+ /**
* Returns either <code>sampler2D</code> or <code>samplerExternalOES</code>
- * depending on {@link #getLastTexture()}.{@link TextureFrame#getTexture() getTexture()}.{@link Texture#getTarget() getTarget()}.
- *
- * @throws IllegalStateException if instance is not initialized
+ * depending on {@link #getLastTexture()}.{@link TextureFrame#getTexture() getTexture()}.{@link Texture#getTarget() getTarget()}.
+ *
+ * @throws IllegalStateException if instance is not initialized
**/
public String getTextureSampler2DType() throws IllegalStateException ;
-
+
/**
* @param desiredFuncName desired lookup function name. If <code>null</code> or ignored by the implementation,
- * a build-in name is returned.
+ * a build-in name is returned.
* @return the final lookup function name
- *
+ *
* @see {@link #getTextureLookupFragmentShaderImpl()}
- *
+ *
* @throws IllegalStateException if instance is not initialized
*/
public String getTextureLookupFunctionName(String desiredFuncName) throws IllegalStateException ;
-
+
/**
* Returns the complete texture2D lookup function code of type
* <pre>
@@ -207,14 +248,33 @@ public interface TextureSequence {
* <i>funcName</i> can be negotiated and queried via {@link #getTextureLookupFunctionName(String)}.
* </p>
* Note: This function may return an empty string in case a build-in lookup
- * function is being chosen. If the implementation desires so,
+ * function is being chosen. If the implementation desires so,
* {@link #getTextureLookupFunctionName(String)} will ignore the desired function name
* and returns the build-in lookup function name.
* </p>
* @see #getTextureLookupFunctionName(String)
* @see #getTextureSampler2DType()
- *
- * @throws IllegalStateException if instance is not initialized
+ *
+ * @throws IllegalStateException if instance is not initialized
+ */
+ public String getTextureLookupFragmentShaderImpl() throws IllegalStateException;
+
+ /**
+ * Returns the hash code of the strings:
+ * <ul>
+ * <li>{@link #getTextureLookupFragmentShaderImpl()}</li>
+ * <li>{@link #getTextureSampler2DType()}</li>
+ * </ul>
+ * <p>
+ * Returns zero if {@link #isTextureAvailable() texture is not available}.
+ * </p>
+ * The returned hash code allows selection of a matching shader program for this {@link TextureSequence} instance.
+ * <p>
+ * </p>
+ * <p>
+ * Implementation shall cache the resulting hash code,
+ * which must be reset to zero if {@link #isTextureAvailable() texture is not available}.
+ * </p>
*/
- public String getTextureLookupFragmentShaderImpl() throws IllegalStateException ;
-} \ No newline at end of file
+ public int getTextureFragmentShaderHashCode();
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java
new file mode 100644
index 000000000..467ab41c5
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java
@@ -0,0 +1,168 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.texture;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GLException;
+
+/**
+ * Preserves a [ texture-unit, texture-target ] state.
+ * <p>
+ * The states keys are the retrieved active texture-unit and the given texture-target
+ * for which the following states are being queried:
+ * <pre>
+ * - texture-object
+ * - GL.GL_TEXTURE_MAG_FILTER
+ * - GL.GL_TEXTURE_MIN_FILTER
+ * - GL.GL_TEXTURE_WRAP_S
+ * - GL.GL_TEXTURE_WRAP_T
+ * </pre>
+ */
+public class TextureState {
+ /**
+ * Returns the <code>pname</code> to query the <code>textureTarget</code> currently bound to the active texture-unit.
+ * <p>
+ * Returns <code>0</code> is <code>textureTarget</code> is not supported.
+ * </p>
+ */
+ public static final int getTextureTargetQueryName(final int textureTarget) {
+ final int texBindQName;
+ switch(textureTarget) {
+ case GL.GL_TEXTURE_2D: texBindQName = GL.GL_TEXTURE_BINDING_2D; break;
+ case GL.GL_TEXTURE_CUBE_MAP: texBindQName = GL.GL_TEXTURE_BINDING_CUBE_MAP; break;
+ case GL2ES2.GL_TEXTURE_3D: texBindQName = GL2ES2.GL_TEXTURE_BINDING_3D; break;
+ case GL2GL3.GL_TEXTURE_1D: texBindQName = GL2GL3.GL_TEXTURE_BINDING_1D; break;
+ case GL2GL3.GL_TEXTURE_1D_ARRAY: texBindQName = GL2GL3.GL_TEXTURE_BINDING_1D_ARRAY; break;
+ case GL.GL_TEXTURE_2D_ARRAY: texBindQName = GL.GL_TEXTURE_BINDING_2D_ARRAY; break;
+ case GL2GL3.GL_TEXTURE_RECTANGLE: texBindQName = GL2GL3.GL_TEXTURE_BINDING_RECTANGLE; break;
+ case GL2GL3.GL_TEXTURE_BUFFER: texBindQName = GL2GL3.GL_TEXTURE_BINDING_BUFFER; break;
+ case GL3.GL_TEXTURE_2D_MULTISAMPLE: texBindQName = GL3.GL_TEXTURE_BINDING_2D_MULTISAMPLE; break;
+ case GL3.GL_TEXTURE_2D_MULTISAMPLE_ARRAY: texBindQName = GL3.GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY; break;
+ default: texBindQName = 0;
+ }
+ return texBindQName;
+ }
+
+ private final int target;
+ /**
+ * <pre>
+ * 0 - unit
+ * 1 - texture object
+ * 2 - GL.GL_TEXTURE_MAG_FILTER
+ * 3 - GL.GL_TEXTURE_MIN_FILTER
+ * 4 - GL.GL_TEXTURE_WRAP_S
+ * 5 - GL.GL_TEXTURE_WRAP_T
+ * </pre>
+ */
+ private final int[] state = new int[] { 0, 0, 0, 0, 0, 0 };
+
+ private static final String toHexString(final int i) { return "0x"+Integer.toHexString(i); }
+
+ private static final int activeTexture(final GL gl) {
+ final int[] vi = { 0 };
+ gl.glGetIntegerv(GL.GL_ACTIVE_TEXTURE, vi, 0);
+ return vi[0];
+ }
+
+ /**
+ * Creates a texture state for the retrieved active texture-unit and the given texture-target.
+ * See {@link TextureState}.
+ * @param gl current GL context's GL object
+ * @param textureTarget
+ * @throws GLException if textureTarget is not supported
+ */
+ public TextureState(final GL gl, final int textureTarget) throws GLException {
+ this(gl, activeTexture(gl), textureTarget);
+ }
+
+ /**
+ * Creates a texture state for the given active texture-unit and the given texture-target.
+ * See {@link TextureState}.
+ * @param gl current GL context's GL object
+ * @param textureUnit of range [ {@link GL#GL_TEXTURE0}.. ]
+ * @param textureTarget
+ * @throws GLException if textureTarget is not supported
+ */
+ public TextureState(final GL gl, final int textureUnit, final int textureTarget) throws GLException {
+ target = textureTarget;
+ state[0] = textureUnit;
+ final int texBindQName = getTextureTargetQueryName(textureTarget);
+ if( 0 == texBindQName ) {
+ throw new GLException("Unsupported textureTarget "+toHexString(textureTarget));
+ }
+ gl.glGetIntegerv(texBindQName, state, 1);
+ gl.glGetTexParameteriv(target, GL.GL_TEXTURE_MAG_FILTER, state, 2);
+ gl.glGetTexParameteriv(target, GL.GL_TEXTURE_MIN_FILTER, state, 3);
+ gl.glGetTexParameteriv(target, GL.GL_TEXTURE_WRAP_S, state, 4);
+ gl.glGetTexParameteriv(target, GL.GL_TEXTURE_WRAP_T, state, 5);
+ }
+
+ /**
+ * Restores the texture-unit's texture-target state.
+ * <p>
+ * First the texture-unit is activated, then all states are restored.
+ * </p>
+ * @param gl current GL context's GL object
+ */
+ public final void restore(final GL gl) {
+ gl.glActiveTexture(state[0]);
+ gl.glBindTexture(target, state[1]);
+ gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, state[2]);
+ gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, state[3]);
+ gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, state[4]);
+ gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, state[5]);
+ }
+
+ /** Returns the texture-unit of this state, key value. Unit is of range [ {@link GL#GL_TEXTURE0}.. ]. */
+ public final int getUnit() { return state[0]; }
+ /** Returns the texture-target of this state, key value. */
+ public final int getTarget() { return target; }
+
+ /** Returns the state's texture-object. */
+ public final int getObject() { return state[1]; }
+ /** Returns the state's mag-filter param. */
+ public final int getMagFilter() { return state[2]; }
+ /** Returns the state's min-filter param. */
+ public final int getMinFilter() { return state[3]; }
+ /** Returns the state's wrap-s param. */
+ public final int getWrapS() { return state[4]; }
+ /** Returns the state's wrap-t param. */
+ public final int getWrapT() { return state[5]; }
+
+
+ @Override
+ public final String toString() {
+ return "TextureState[unit "+(state[0] - GL.GL_TEXTURE0)+", target "+toHexString(target)+
+ ": obj "+toHexString(state[1])+
+ ", filter[mag "+toHexString(state[2])+", min "+toHexString(state[3])+"], "+
+ ": wrap[s "+toHexString(state[4])+", t "+toHexString(state[5])+"]]";
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
index ad96a9939..ccb3ecc3c 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
@@ -1,21 +1,22 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -37,15 +38,36 @@
package com.jogamp.opengl.util.texture.awt;
import java.awt.AlphaComposite;
-import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Transparency;
-import java.awt.color.*;
-import java.awt.image.*;
-import java.nio.*;
+import java.awt.image.BufferedImage;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.ComponentSampleModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferDouble;
+import java.awt.image.DataBufferFloat;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DataBufferShort;
+import java.awt.image.DataBufferUShort;
+import java.awt.image.MultiPixelPackedSampleModel;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.awt.image.WritableRaster;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
-import javax.media.opengl.*;
-import com.jogamp.opengl.util.texture.*;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.texture.TextureData;
public class AWTTextureData extends TextureData {
// Mechanism for lazily converting input BufferedImages with custom
@@ -56,19 +78,19 @@ public class AWTTextureData extends TextureData {
private boolean expectingEXTABGR;
private boolean expectingGL12;
- private static final ColorModel rgbaColorModel =
- new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
- new int[] {8, 8, 8, 8}, true, true,
+ private static final java.awt.image.ColorModel rgbaColorModel =
+ new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB),
+ new int[] {8, 8, 8, 8}, true, true,
Transparency.TRANSLUCENT,
DataBuffer.TYPE_BYTE);
- private static final ColorModel rgbColorModel =
- new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ private static final java.awt.image.ColorModel rgbColorModel =
+ new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB),
new int[] {8, 8, 8, 0}, false, false,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
- /**
+ /**
* Constructs a new TextureData object with the specified parameters
* and data contained in the given BufferedImage. The resulting
* TextureData "wraps" the contents of the BufferedImage, so if a
@@ -91,11 +113,11 @@ public class AWTTextureData extends TextureData {
* texture
* @param image the image containing the texture data
*/
- public AWTTextureData(GLProfile glp,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
- BufferedImage image) {
+ public AWTTextureData(final GLProfile glp,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
+ final BufferedImage image) {
super(glp);
if (internalFormat == 0) {
this.internalFormat = image.getColorModel().hasAlpha() ? GL.GL_RGBA : GL.GL_RGB;
@@ -114,33 +136,38 @@ public class AWTTextureData extends TextureData {
}
}
- /** Returns the intended OpenGL pixel format of the texture data. */
- public int getPixelFormat() {
+ private void validatePixelAttributes() {
if (imageForLazyCustomConversion != null) {
if (!((expectingEXTABGR && haveEXTABGR) ||
(expectingGL12 && haveGL12))) {
- revertPixelFormatAndType();
+ revertPixelAttributes();
}
}
- return pixelFormat;
}
- /** Returns the intended OpenGL pixel type of the texture data. */
+
+ @Override
+ public GLPixelAttributes getPixelAttributes() {
+ validatePixelAttributes();
+ return super.getPixelAttributes();
+ }
+
+ @Override
+ public int getPixelFormat() {
+ validatePixelAttributes();
+ return super.getPixelFormat();
+ }
+ @Override
public int getPixelType() {
- if (imageForLazyCustomConversion != null) {
- if (!((expectingEXTABGR && haveEXTABGR) ||
- (expectingGL12 && haveGL12))) {
- revertPixelFormatAndType();
- }
- }
- return pixelType;
+ validatePixelAttributes();
+ return super.getPixelType();
}
- /** Returns the texture data, or null if it is specified as a set of mipmaps. */
+ @Override
public Buffer getBuffer() {
if (imageForLazyCustomConversion != null) {
if (!((expectingEXTABGR && haveEXTABGR) ||
(expectingGL12 && haveGL12))) {
- revertPixelFormatAndType();
+ revertPixelAttributes();
// Must present the illusion to the end user that we are simply
// wrapping the input BufferedImage
createFromCustom(imageForLazyCustomConversion);
@@ -149,8 +176,8 @@ public class AWTTextureData extends TextureData {
return buffer;
}
- private void createFromImage(GLProfile glp, BufferedImage image) {
- pixelType = 0; // Determine from image
+ private void createFromImage(final GLProfile glp, final BufferedImage image) {
+ pixelAttributes = GLPixelAttributes.UNDEF; // Determine from image
mustFlipVertically = true;
width = image.getWidth();
@@ -158,7 +185,7 @@ public class AWTTextureData extends TextureData {
int scanlineStride;
- SampleModel sm = image.getRaster().getSampleModel();
+ final SampleModel sm = image.getRaster().getSampleModel();
if (sm instanceof SinglePixelPackedSampleModel) {
scanlineStride =
((SinglePixelPackedSampleModel)sm).getScanlineStride();
@@ -180,24 +207,21 @@ public class AWTTextureData extends TextureData {
if (glp.isGL2GL3()) {
switch (image.getType()) {
case BufferedImage.TYPE_INT_RGB:
- pixelFormat = GL.GL_BGRA;
- pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
+ pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
rowLength = scanlineStride;
alignment = 4;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_INT_ARGB_PRE:
- pixelFormat = GL.GL_BGRA;
- pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
+ pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
rowLength = scanlineStride;
alignment = 4;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_INT_BGR:
- pixelFormat = GL.GL_RGBA;
- pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
rowLength = scanlineStride;
alignment = 4;
expectingGL12 = true;
@@ -208,8 +232,7 @@ public class AWTTextureData extends TextureData {
// we can pass the image data directly to OpenGL only if
// we have an integral number of pixels in each scanline
if ((scanlineStride % 3) == 0) {
- pixelFormat = GL2GL3.GL_BGR;
- pixelType = GL.GL_UNSIGNED_BYTE;
+ pixelAttributes = new GLPixelAttributes(GL2GL3.GL_BGR, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 3;
alignment = 1;
} else {
@@ -223,17 +246,16 @@ public class AWTTextureData extends TextureData {
// we can pass the image data directly to OpenGL only if
// we have an integral number of pixels in each scanline
// and only if the GL_EXT_abgr extension is present
-
+
// NOTE: disabling this code path for now as it appears it's
// buggy at least on some NVidia drivers and doesn't perform
// the necessary byte swapping (FIXME: needs more
// investigation)
if ((scanlineStride % 4) == 0 && glp.isGL2() && false) {
- pixelFormat = GL2.GL_ABGR_EXT;
- pixelType = GL.GL_UNSIGNED_BYTE;
+ pixelAttributes = new GLPixelAttributes(GL2.GL_ABGR_EXT, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 4;
alignment = 4;
-
+
// Store a reference to the original image for later in
// case it turns out that we don't have GL_EXT_abgr at the
// time we're going to do the texture upload to OpenGL
@@ -246,30 +268,26 @@ public class AWTTextureData extends TextureData {
}
}
case BufferedImage.TYPE_USHORT_565_RGB:
- pixelFormat = GL.GL_RGB;
- pixelType = GL.GL_UNSIGNED_SHORT_5_6_5;
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
rowLength = scanlineStride;
alignment = 2;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_USHORT_555_RGB:
- pixelFormat = GL.GL_BGRA;
- pixelType = GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV;
+ pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV);
rowLength = scanlineStride;
alignment = 2;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_BYTE_GRAY:
- pixelFormat = GL.GL_LUMINANCE;
- pixelType = GL.GL_UNSIGNED_BYTE;
+ pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride;
alignment = 1;
break;
case BufferedImage.TYPE_USHORT_GRAY:
- pixelFormat = GL.GL_LUMINANCE;
- pixelType = GL.GL_UNSIGNED_SHORT;
+ pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_SHORT);
rowLength = scanlineStride;
alignment = 2;
break;
@@ -282,15 +300,13 @@ public class AWTTextureData extends TextureData {
case BufferedImage.TYPE_BYTE_INDEXED:
case BufferedImage.TYPE_CUSTOM:
default:
- ColorModel cm = image.getColorModel();
+ final java.awt.image.ColorModel cm = image.getColorModel();
if (cm.equals(rgbColorModel)) {
- pixelFormat = GL.GL_RGB;
- pixelType = GL.GL_UNSIGNED_BYTE;
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 3;
alignment = 1;
} else if (cm.equals(rgbaColorModel)) {
- pixelFormat = GL.GL_RGBA;
- pixelType = GL.GL_UNSIGNED_BYTE;
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 4; // FIXME: correct?
alignment = 4;
} else {
@@ -302,8 +318,7 @@ public class AWTTextureData extends TextureData {
} else {
switch (image.getType()) {
case BufferedImage.TYPE_INT_RGB:
- pixelFormat = GL.GL_RGB;
- pixelType = GL.GL_UNSIGNED_BYTE;
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride;
alignment = 3;
expectingGL12 = true;
@@ -318,24 +333,21 @@ public class AWTTextureData extends TextureData {
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
throw new GLException("INT_BGR n.a.");
case BufferedImage.TYPE_USHORT_565_RGB:
- pixelFormat = GL.GL_RGB;
- pixelType = GL.GL_UNSIGNED_SHORT_5_6_5;
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
rowLength = scanlineStride;
alignment = 2;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_USHORT_555_RGB:
- pixelFormat = GL.GL_RGBA;
- pixelType = GL.GL_UNSIGNED_SHORT_5_5_5_1;
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1);
rowLength = scanlineStride;
alignment = 2;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_BYTE_GRAY:
- pixelFormat = GL.GL_LUMINANCE;
- pixelType = GL.GL_UNSIGNED_BYTE;
+ pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride;
alignment = 1;
break;
@@ -350,15 +362,13 @@ public class AWTTextureData extends TextureData {
case BufferedImage.TYPE_BYTE_INDEXED:
case BufferedImage.TYPE_CUSTOM:
default:
- ColorModel cm = image.getColorModel();
+ final java.awt.image.ColorModel cm = image.getColorModel();
if (cm.equals(rgbColorModel)) {
- pixelFormat = GL.GL_RGB;
- pixelType = GL.GL_UNSIGNED_BYTE;
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 3;
alignment = 1;
} else if (cm.equals(rgbaColorModel)) {
- pixelFormat = GL.GL_RGBA;
- pixelType = GL.GL_UNSIGNED_BYTE;
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 4; // FIXME: correct?
alignment = 4;
} else {
@@ -372,9 +382,11 @@ public class AWTTextureData extends TextureData {
createNIOBufferFromImage(image);
}
- private void setupLazyCustomConversion(BufferedImage image) {
+ private void setupLazyCustomConversion(final BufferedImage image) {
imageForLazyCustomConversion = image;
- boolean hasAlpha = image.getColorModel().hasAlpha();
+ final boolean hasAlpha = image.getColorModel().hasAlpha();
+ int pixelFormat = pixelAttributes.format;
+ int pixelType = pixelAttributes.type;
if (pixelFormat == 0) {
pixelFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB;
}
@@ -383,7 +395,7 @@ public class AWTTextureData extends TextureData {
// Allow previously-selected pixelType (if any) to override that
// we can infer from the DataBuffer
- DataBuffer data = image.getRaster().getDataBuffer();
+ final DataBuffer data = image.getRaster().getDataBuffer();
if (data instanceof DataBufferByte || isPackedInt(image)) {
// Don't use GL_UNSIGNED_INT for BufferedImage packed int images
if (pixelType == 0) pixelType = GL.GL_UNSIGNED_BYTE;
@@ -393,7 +405,7 @@ public class AWTTextureData extends TextureData {
if (pixelType == 0) pixelType = GL.GL_FLOAT;
} else if (data instanceof DataBufferInt) {
// FIXME: should we support signed ints?
- if (pixelType == 0) pixelType = GL2GL3.GL_UNSIGNED_INT;
+ if (pixelType == 0) pixelType = GL.GL_UNSIGNED_INT;
} else if (data instanceof DataBufferShort) {
if (pixelType == 0) pixelType = GL.GL_SHORT;
} else if (data instanceof DataBufferUShort) {
@@ -401,15 +413,16 @@ public class AWTTextureData extends TextureData {
} else {
throw new RuntimeException("Unexpected DataBuffer type?");
}
+ pixelAttributes = new GLPixelAttributes(pixelFormat, pixelType);
}
- private void createFromCustom(BufferedImage image) {
- int width = image.getWidth();
- int height = image.getHeight();
+ private void createFromCustom(final BufferedImage image) {
+ final int width = image.getWidth();
+ final int height = image.getHeight();
// create a temporary image that is compatible with OpenGL
- boolean hasAlpha = image.getColorModel().hasAlpha();
- ColorModel cm = null;
+ final boolean hasAlpha = image.getColorModel().hasAlpha();
+ java.awt.image.ColorModel cm = null;
int dataBufferType = image.getRaster().getDataBuffer().getDataType();
// Don't use integer components for packed int images
if (isPackedInt(image)) {
@@ -419,25 +432,25 @@ public class AWTTextureData extends TextureData {
cm = hasAlpha ? rgbaColorModel : rgbColorModel;
} else {
if (hasAlpha) {
- cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ cm = new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB),
null, true, true,
Transparency.TRANSLUCENT,
dataBufferType);
} else {
- cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ cm = new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB),
null, false, false,
Transparency.OPAQUE,
dataBufferType);
}
}
- boolean premult = cm.isAlphaPremultiplied();
- WritableRaster raster =
+ final boolean premult = cm.isAlphaPremultiplied();
+ final WritableRaster raster =
cm.createCompatibleWritableRaster(width, height);
- BufferedImage texImage = new BufferedImage(cm, raster, premult, null);
+ final BufferedImage texImage = new BufferedImage(cm, raster, premult, null);
// copy the source image into the temporary image
- Graphics2D g = texImage.createGraphics();
+ final Graphics2D g = texImage.createGraphics();
g.setComposite(AlphaComposite.Src);
g.drawImage(image, 0, 0, null);
g.dispose();
@@ -446,29 +459,28 @@ public class AWTTextureData extends TextureData {
createNIOBufferFromImage(texImage);
}
- private boolean isPackedInt(BufferedImage image) {
- int imgType = image.getType();
+ private boolean isPackedInt(final BufferedImage image) {
+ final int imgType = image.getType();
return (imgType == BufferedImage.TYPE_INT_RGB ||
imgType == BufferedImage.TYPE_INT_BGR ||
imgType == BufferedImage.TYPE_INT_ARGB ||
imgType == BufferedImage.TYPE_INT_ARGB_PRE);
}
- private void revertPixelFormatAndType() {
+ private void revertPixelAttributes() {
// Knowing we don't have e.g. OpenGL 1.2 functionality available,
// and knowing we're in the process of doing the fallback code
// path, re-infer a vanilla pixel format and type compatible with
// OpenGL 1.1
- pixelFormat = 0;
- pixelType = 0;
+ pixelAttributes = GLPixelAttributes.UNDEF;
setupLazyCustomConversion(imageForLazyCustomConversion);
}
- private void createNIOBufferFromImage(BufferedImage image) {
+ private void createNIOBufferFromImage(final BufferedImage image) {
buffer = wrapImageDataBuffer(image);
}
- private Buffer wrapImageDataBuffer(BufferedImage image) {
+ private Buffer wrapImageDataBuffer(final BufferedImage image) {
//
// Note: Grabbing the DataBuffer will defeat Java2D's image
// management mechanism (as of JDK 5/6, at least). This shouldn't
@@ -478,7 +490,7 @@ public class AWTTextureData extends TextureData {
// it could be.
//
- DataBuffer data = image.getRaster().getDataBuffer();
+ final DataBuffer data = image.getRaster().getDataBuffer();
if (data instanceof DataBufferByte) {
return ByteBuffer.wrap(((DataBufferByte) data).getData());
} else if (data instanceof DataBufferDouble) {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java
index fdd1365f7..c3b3adc75 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -59,8 +59,8 @@ public class AWTTextureIO extends TextureIO {
*
* @see #newTextureData(GLProfile, BufferedImage, boolean)
*/
- public static TextureData newTextureData(GLProfile glp, BufferedImage image,
- boolean mipmap) {
+ public static TextureData newTextureData(final GLProfile glp, final BufferedImage image,
+ final boolean mipmap) {
return newTextureDataImpl(glp, image, 0, 0, mipmap);
}
@@ -89,10 +89,10 @@ public class AWTTextureIO extends TextureIO {
* @throws IllegalArgumentException if either internalFormat or
* pixelFormat was 0
*/
- public static TextureData newTextureData(GLProfile glp, BufferedImage image,
- int internalFormat,
- int pixelFormat,
- boolean mipmap) throws IllegalArgumentException {
+ public static TextureData newTextureData(final GLProfile glp, final BufferedImage image,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap) throws IllegalArgumentException {
if ((internalFormat == 0) || (pixelFormat == 0)) {
throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero");
}
@@ -100,7 +100,7 @@ public class AWTTextureIO extends TextureIO {
return newTextureDataImpl(glp, image, internalFormat, pixelFormat, mipmap);
}
- /**
+ /**
* Creates an OpenGL texture object from the specified BufferedImage
* using the current OpenGL context.
*
@@ -112,18 +112,18 @@ public class AWTTextureIO extends TextureIO {
* @throws GLException if no OpenGL context is current or if an
* OpenGL error occurred
*/
- public static Texture newTexture(GLProfile glp, BufferedImage image, boolean mipmap) throws GLException {
- TextureData data = newTextureData(glp, image, mipmap);
- Texture texture = newTexture(data);
+ public static Texture newTexture(final GLProfile glp, final BufferedImage image, final boolean mipmap) throws GLException {
+ final TextureData data = newTextureData(glp, image, mipmap);
+ final Texture texture = newTexture(data);
data.flush();
return texture;
}
- private static TextureData newTextureDataImpl(GLProfile glp,
- BufferedImage image,
- int internalFormat,
- int pixelFormat,
- boolean mipmap) {
+ private static TextureData newTextureDataImpl(final GLProfile glp,
+ final BufferedImage image,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap) {
return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, image);
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java
index 3f91ae966..20fc92819 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -52,6 +52,7 @@ import java.nio.channels.FileChannel;
import javax.media.opengl.GL;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.IOUtil;
import com.jogamp.opengl.util.GLBuffers;
@@ -67,13 +68,13 @@ public class DDSImage {
that information in another way. */
public static class ImageInfo {
- private ByteBuffer data;
- private int width;
- private int height;
- private boolean isCompressed;
- private int compressionFormat;
+ private final ByteBuffer data;
+ private final int width;
+ private final int height;
+ private final boolean isCompressed;
+ private final int compressionFormat;
- public ImageInfo(ByteBuffer data, int width, int height, boolean compressed, int compressionFormat) {
+ public ImageInfo(final ByteBuffer data, final int width, final int height, final boolean compressed, final int compressionFormat) {
this.data = data; this.width = width; this.height = height;
this.isCompressed = compressed; this.compressionFormat = compressionFormat;
}
@@ -163,10 +164,10 @@ public class DDSImage {
@return DDS image object
@throws java.io.IOException if an I/O exception occurred
*/
- public static DDSImage read(String filename) throws IOException {
+ public static DDSImage read(final String filename) throws IOException {
return read(new File(filename));
}
-
+
/** Reads a DirectDraw surface from the specified file, returning
the resulting DDSImage.
@@ -174,8 +175,8 @@ public class DDSImage {
@return DDS image object
@throws java.io.IOException if an I/O exception occurred
*/
- public static DDSImage read(File file) throws IOException {
- DDSImage image = new DDSImage();
+ public static DDSImage read(final File file) throws IOException {
+ final DDSImage image = new DDSImage();
image.readFromFile(file);
return image;
}
@@ -187,8 +188,8 @@ public class DDSImage {
@return DDS image object
@throws java.io.IOException if an I/O exception occurred
*/
- public static DDSImage read(ByteBuffer buf) throws IOException {
- DDSImage image = new DDSImage();
+ public static DDSImage read(final ByteBuffer buf) throws IOException {
+ final DDSImage image = new DDSImage();
image.readFromBuffer(buf);
return image;
}
@@ -207,12 +208,12 @@ public class DDSImage {
fis = null;
}
buf = null;
- } catch (IOException e) {
+ } catch (final IOException e) {
e.printStackTrace();
}
}
- /**
+ /**
* Creates a new DDSImage from data supplied by the user. The
* resulting DDSImage can be written to disk using the write()
* method.
@@ -228,11 +229,11 @@ public class DDSImage {
* specified arguments
* @return DDS image object
*/
- public static DDSImage createFromData(int d3dFormat,
- int width,
- int height,
- ByteBuffer[] mipmapData) throws IllegalArgumentException {
- DDSImage image = new DDSImage();
+ public static DDSImage createFromData(final int d3dFormat,
+ final int width,
+ final int height,
+ final ByteBuffer[] mipmapData) throws IllegalArgumentException {
+ final DDSImage image = new DDSImage();
image.initFromData(d3dFormat, width, height, mipmapData);
return image;
}
@@ -256,7 +257,7 @@ public class DDSImage {
in.mark(4);
int magic = 0;
for (int i = 0; i < 4; i++) {
- int tmp = in.read();
+ final int tmp = in.read();
if (tmp < 0) {
in.reset();
return false;
@@ -272,7 +273,7 @@ public class DDSImage {
* @param filename File name to write to
* @throws java.io.IOException if an I/O exception occurred
*/
- public void write(String filename) throws IOException {
+ public void write(final String filename) throws IOException {
write(new File(filename));
}
@@ -281,12 +282,12 @@ public class DDSImage {
* @param file File object to write to
* @throws java.io.IOException if an I/O exception occurred
*/
- public void write(File file) throws IOException {
- FileOutputStream stream = IOUtil.getFileOutputStream(file, true);
- FileChannel chan = stream.getChannel();
+ public void write(final File file) throws IOException {
+ final FileOutputStream stream = IOUtil.getFileOutputStream(file, true);
+ final FileChannel chan = stream.getChannel();
// Create ByteBuffer for header in case the start of our
// ByteBuffer isn't actually memory-mapped
- ByteBuffer hdr = ByteBuffer.allocate(Header.writtenSize());
+ final ByteBuffer hdr = ByteBuffer.allocate(Header.writtenSize());
hdr.order(ByteOrder.LITTLE_ENDIAN);
header.write(hdr);
hdr.rewind();
@@ -302,12 +303,12 @@ public class DDSImage {
* @param flag DDSD_* flags set to test
* @return true if flag present or false otherwise
*/
- public boolean isSurfaceDescFlagSet(int flag) {
+ public boolean isSurfaceDescFlagSet(final int flag) {
return ((header.flags & flag) != 0);
}
/** Test for presence/absence of pixel format flags (DDPF_*) */
- public boolean isPixelFormatFlagSet(int flag) {
+ public boolean isPixelFormatFlagSet(final int flag) {
return ((header.pfFlags & flag) != 0);
}
@@ -357,7 +358,7 @@ public class DDSImage {
* @param side Side to test
* @return true if side present or false otherwise
*/
- public boolean isCubemapSidePresent(int side) {
+ public boolean isCubemapSidePresent(final int side) {
return isCubemap() && (header.ddsCaps2 & side) != 0;
}
@@ -402,7 +403,7 @@ public class DDSImage {
* @param map Mipmap index
* @return Image object
*/
- public ImageInfo getMipMap(int map) {
+ public ImageInfo getMipMap(final int map) {
return getMipMap( 0, map );
}
@@ -412,7 +413,7 @@ public class DDSImage {
* @param map Mipmap index
* @return Image object
*/
- public ImageInfo getMipMap(int side, int map) {
+ public ImageInfo getMipMap(final int side, final int map) {
if (!isCubemap() && (side != 0)) {
throw new RuntimeException( "Illegal side for 2D texture: " + side );
}
@@ -434,7 +435,7 @@ public class DDSImage {
}
buf.limit(seek + mipMapSizeInBytes(map));
buf.position(seek);
- ByteBuffer next = buf.slice();
+ final ByteBuffer next = buf.slice();
buf.position(0);
buf.limit(buf.capacity());
return new ImageInfo(next, mipMapWidth(map), mipMapHeight(map), isCompressed(), getCompressionFormat());
@@ -454,12 +455,12 @@ public class DDSImage {
* @param side Cubemap side or 0 for 2D texture
* @return Mipmap image objects set
*/
- public ImageInfo[] getAllMipMaps( int side ) {
+ public ImageInfo[] getAllMipMaps( final int side ) {
int numLevels = getNumMipMaps();
if (numLevels == 0) {
numLevels = 1;
}
- ImageInfo[] result = new ImageInfo[numLevels];
+ final ImageInfo[] result = new ImageInfo[numLevels];
for (int i = 0; i < numLevels; i++) {
result[i] = getMipMap(side, i);
}
@@ -472,9 +473,9 @@ public class DDSImage {
@return String format code
*/
public static String getCompressionFormatName(int compressionFormat) {
- StringBuilder buf = new StringBuilder();
+ final StringBuilder buf = new StringBuilder();
for (int i = 0; i < 4; i++) {
- char c = (char) (compressionFormat & 0xFF);
+ final char c = (char) (compressionFormat & 0xFF);
buf.append(c);
compressionFormat = compressionFormat >> 8;
}
@@ -491,9 +492,9 @@ public class DDSImage {
GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, or
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT.
*/
- public static ByteBuffer allocateBlankBuffer(int width,
- int height,
- int openGLInternalFormat) {
+ public static ByteBuffer allocateBlankBuffer(final int width,
+ final int height,
+ final int openGLInternalFormat) {
int size = width * height;
switch (openGLInternalFormat) {
case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
@@ -511,15 +512,15 @@ public class DDSImage {
}
if (size == 0)
size = 1;
- return GLBuffers.newDirectByteBuffer(size);
+ return Buffers.newDirectByteBuffer(size);
}
public void debugPrint() {
- PrintStream tty = System.err;
+ final PrintStream tty = System.err;
tty.println("Compressed texture: " + isCompressed());
if (isCompressed()) {
- int fmt = getCompressionFormat();
- String name = getCompressionFormatName(fmt);
+ final int fmt = getCompressionFormat();
+ final String name = getCompressionFormatName(fmt);
tty.println("Compression format: 0x" + Integer.toHexString(fmt) + " (" + name + ")");
}
tty.println("Width: " + header.width + " Height: " + header.height);
@@ -567,7 +568,7 @@ public class DDSImage {
tty.println("Raw pixel format flags: 0x" + Integer.toHexString(header.pfFlags));
tty.println("Depth: " + getDepth());
tty.println("Number of mip maps: " + getNumMipMaps());
- int fmt = getPixelFormat();
+ final int fmt = getPixelFormat();
tty.print("Pixel format: ");
switch (fmt) {
case D3DFMT_R8G8B8: tty.println("D3DFMT_R8G8B8"); break;
@@ -629,8 +630,8 @@ public class DDSImage {
int ddsCapsReserved2;
int textureStage; // stage in multitexture cascade
- void read(ByteBuffer buf) throws IOException {
- int magic = buf.getInt();
+ void read(final ByteBuffer buf) throws IOException {
+ final int magic = buf.getInt();
if (magic != MAGIC) {
throw new IOException("Incorrect magic number 0x" +
Integer.toHexString(magic) +
@@ -671,7 +672,7 @@ public class DDSImage {
}
// buf must be in little-endian byte order
- void write(ByteBuffer buf) {
+ void write(final ByteBuffer buf) {
buf.putInt(MAGIC);
buf.putInt(size);
buf.putInt(flags);
@@ -722,15 +723,15 @@ public class DDSImage {
private DDSImage() {
}
- private void readFromFile(File file) throws IOException {
+ private void readFromFile(final File file) throws IOException {
fis = new FileInputStream(file);
chan = fis.getChannel();
- ByteBuffer buf = chan.map(FileChannel.MapMode.READ_ONLY,
+ final ByteBuffer buf = chan.map(FileChannel.MapMode.READ_ONLY,
0, (int) file.length());
readFromBuffer(buf);
}
- private void readFromBuffer(ByteBuffer buf) throws IOException {
+ private void readFromBuffer(final ByteBuffer buf) throws IOException {
this.buf = buf;
buf.order(ByteOrder.LITTLE_ENDIAN);
header = new Header();
@@ -738,10 +739,10 @@ public class DDSImage {
fixupHeader();
}
- private void initFromData(int d3dFormat,
- int width,
- int height,
- ByteBuffer[] mipmapData) throws IllegalArgumentException {
+ private void initFromData(final int d3dFormat,
+ final int width,
+ final int height,
+ final ByteBuffer[] mipmapData) throws IllegalArgumentException {
// Check size of mipmap data compared against format, width and
// height
int topmostMipmapSize = width * height;
@@ -763,9 +764,11 @@ public class DDSImage {
default:
throw new IllegalArgumentException("d3dFormat must be one of the known formats");
}
-
+
// Now check the mipmaps against this size
int curSize = topmostMipmapSize;
+ int mipmapWidth = width;
+ int mipmapHeight = height;
int totalSize = 0;
for (int i = 0; i < mipmapData.length; i++) {
if (mipmapData[i].remaining() != curSize) {
@@ -773,19 +776,22 @@ public class DDSImage {
" didn't match expected data size (expected " + curSize + ", got " +
mipmapData[i].remaining() + ")");
}
- curSize /= 4;
+ // Compute next mipmap size
+ if (mipmapWidth > 1) mipmapWidth /= 2;
+ if (mipmapHeight > 1) mipmapHeight /= 2;
+ curSize = computeBlockSize(mipmapWidth, mipmapHeight, 1, d3dFormat);
totalSize += mipmapData[i].remaining();
}
// OK, create one large ByteBuffer to hold all of the mipmap data
totalSize += Header.writtenSize();
- ByteBuffer buf = ByteBuffer.allocate(totalSize);
+ final ByteBuffer buf = ByteBuffer.allocate(totalSize);
buf.position(Header.writtenSize());
for (int i = 0; i < mipmapData.length; i++) {
buf.put(mipmapData[i]);
}
this.buf = buf;
-
+
// Allocate and initialize a Header
header = new Header();
header.size = Header.size();
@@ -840,10 +846,10 @@ public class DDSImage {
}
}
- private static int computeCompressedBlockSize(int width,
- int height,
- int depth,
- int compressionFormat) {
+ private static int computeCompressedBlockSize(final int width,
+ final int height,
+ final int depth,
+ final int compressionFormat) {
int blockSize = ((width + 3)/4) * ((height + 3)/4) * ((depth + 3)/4);
switch (compressionFormat) {
case D3DFMT_DXT1: blockSize *= 8; break;
@@ -852,7 +858,33 @@ public class DDSImage {
return blockSize;
}
- private int mipMapWidth(int map) {
+ private static int computeBlockSize(final int width,
+ final int height,
+ final int depth,
+ final int pixelFormat) {
+ int blocksize;
+ switch (pixelFormat) {
+ case D3DFMT_R8G8B8:
+ blocksize = width*height*3;
+ break;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ blocksize = width*height*4;
+ break;
+ case D3DFMT_DXT1:
+ case D3DFMT_DXT2:
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT4:
+ case D3DFMT_DXT5:
+ blocksize = computeCompressedBlockSize(width, height, 1, pixelFormat);
+ break;
+ default:
+ throw new IllegalArgumentException("d3dFormat must be one of the known formats");
+ }
+ return blocksize;
+ }
+
+ private int mipMapWidth(final int map) {
int width = getWidth();
for (int i = 0; i < map; i++) {
width >>= 1;
@@ -860,7 +892,7 @@ public class DDSImage {
return Math.max(width, 1);
}
- private int mipMapHeight(int map) {
+ private int mipMapHeight(final int map) {
int height = getHeight();
for (int i = 0; i < map; i++) {
height >>= 1;
@@ -868,11 +900,11 @@ public class DDSImage {
return Math.max(height, 1);
}
- private int mipMapSizeInBytes(int map) {
- int width = mipMapWidth(map);
- int height = mipMapHeight(map);
+ private int mipMapSizeInBytes(final int map) {
+ final int width = mipMapWidth(map);
+ final int height = mipMapHeight(map);
if (isCompressed()) {
- int blockSize = (getCompressionFormat() == D3DFMT_DXT1 ? 8 : 16);
+ final int blockSize = (getCompressionFormat() == D3DFMT_DXT1 ? 8 : 16);
return ((width+3)/4)*((height+3)/4)*blockSize;
} else {
return width * height * (getDepth() / 8);
@@ -893,8 +925,8 @@ public class DDSImage {
return size;
}
- private int sideShiftInBytes(int side) {
- int[] sides = {
+ private int sideShiftInBytes(final int side) {
+ final int[] sides = {
DDSCAPS2_CUBEMAP_POSITIVEX,
DDSCAPS2_CUBEMAP_NEGATIVEX,
DDSCAPS2_CUBEMAP_POSITIVEY,
@@ -904,9 +936,9 @@ public class DDSImage {
};
int shift = 0;
- int sideSize = sideSizeInBytes();
+ final int sideSize = sideSizeInBytes();
for (int i = 0; i < sides.length; i++) {
- int temp = sides[i];
+ final int temp = sides[i];
if ((temp & side) != 0) {
return shift;
}
@@ -917,7 +949,7 @@ public class DDSImage {
throw new RuntimeException("Illegal side: " + side);
}
- private boolean printIfRecognized(PrintStream tty, int flags, int flag, String what) {
+ private boolean printIfRecognized(final PrintStream tty, final int flags, final int flag, final String what) {
if ((flags & flag) != 0) {
tty.println(what);
return true;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java
new file mode 100644
index 000000000..66a486f9b
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java
@@ -0,0 +1,177 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.texture.spi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+import javax.media.opengl.GL;
+
+import jogamp.opengl.Debug;
+import jogamp.opengl.util.jpeg.JPEGDecoder;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.texture.TextureData.ColorSpace;
+
+public class JPEGImage {
+ private static final boolean DEBUG = Debug.debug("JPEGImage");
+
+
+ /**
+ * Reads a JPEG image from the specified InputStream, using the given color space for storage.
+ *
+ * @param in
+ * @param cs Storage color space, either {@link ColorSpace#RGB} or {@link ColorSpace#YCbCr}. {@link ColorSpace#YCCK} and {@link ColorSpace#CMYK} will throw an exception!
+ * @return
+ * @throws IOException
+ */
+ public static JPEGImage read(final InputStream in, final ColorSpace cs) throws IOException {
+ return new JPEGImage(in, cs);
+ }
+
+ /** Reads a JPEG image from the specified InputStream, using the {@link ColorSpace#RGB}. */
+ public static JPEGImage read(final InputStream in) throws IOException {
+ return new JPEGImage(in, ColorSpace.RGB);
+ }
+
+ private static class JPEGColorSink implements JPEGDecoder.ColorSink {
+ int width=0, height=0;
+ int sourceComponents=0;
+ ColorSpace sourceCS = ColorSpace.YCbCr;
+ int storageComponents;
+ final ColorSpace storageCS;
+ ByteBuffer data = null;
+
+ JPEGColorSink(final ColorSpace storageCM) {
+ this.storageCS = storageCM;
+ switch(storageCS) {
+ case RGB:
+ case YCbCr:
+ storageComponents = 3;
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported storage color-space: "+storageCS);
+ }
+ }
+
+ @Override
+ public final ColorSpace allocate(final int width, final int height, final ColorSpace sourceCM, final int sourceComponents) throws RuntimeException {
+ this.width = width;
+ this.height = height;
+ this.sourceComponents = sourceComponents;
+ this.sourceCS = sourceCM;
+ this.data = Buffers.newDirectByteBuffer(width * height * storageComponents);
+ return storageCS;
+ }
+
+ @Override
+ public final void storeRGB(final int x, final int y, final byte r, final byte g, final byte b) {
+ int i = ( ( height - y - 1 ) * width + x ) * storageComponents;
+ data.put(i++, r);
+ data.put(i++, g);
+ data.put(i++, b);
+ // data.put(i++, (byte)0xff);
+ }
+
+ @Override
+ public final void store2(final int x, final int y, final byte c1, final byte c2) {
+ throw new RuntimeException("not supported yet");
+ }
+
+ @Override
+ public final void storeYCbCr(final int x, final int y, final byte Y, final byte Cb, final byte Cr) {
+ int i = ( ( height - y - 1 ) * width + x ) * storageComponents;
+ data.put(i++, Y);
+ data.put(i++, Cb);
+ data.put(i++, Cr);
+ }
+
+ @Override
+ public String toString() {
+ return "JPEGPixels["+width+"x"+height+", sourceComp "+sourceComponents+", sourceCS "+sourceCS+", storageCS "+storageCS+", storageComp "+storageComponents+"]";
+ }
+ };
+
+ private JPEGImage(final InputStream in, final ColorSpace cs) throws IOException {
+ pixelStorage = new JPEGColorSink(cs);
+ final JPEGDecoder decoder = new JPEGDecoder();
+ decoder.parse(in);
+ pixelWidth = decoder.getWidth();
+ pixelHeight = decoder.getHeight();
+ decoder.getPixel(pixelStorage, pixelWidth, pixelHeight);
+ data = pixelStorage.data;
+ final boolean hasAlpha = false;
+
+ bytesPerPixel = 3;
+ glFormat = GL.GL_RGB;
+ reversedChannels = false; // RGB[A]
+ if(DEBUG) {
+ System.err.println("JPEGImage: alpha "+hasAlpha+", bytesPerPixel "+bytesPerPixel+
+ ", pixels "+pixelWidth+"x"+pixelHeight+", glFormat 0x"+Integer.toHexString(glFormat));
+ System.err.println("JPEGImage: "+decoder);
+ System.err.println("JPEGImage: "+pixelStorage);
+ }
+ decoder.clear(null);
+ }
+ private final JPEGColorSink pixelStorage;
+ private final int pixelWidth, pixelHeight, glFormat, bytesPerPixel;
+ private final boolean reversedChannels;
+ private final ByteBuffer data;
+
+ /** Returns the color space of the pixel data */
+ public ColorSpace getColorSpace() { return pixelStorage.storageCS; }
+
+ /** Returns the number of components of the pixel data */
+ public int getComponentCount() { return pixelStorage.storageComponents; }
+
+ /** Returns the width of the image. */
+ public int getWidth() { return pixelWidth; }
+
+ /** Returns the height of the image. */
+ public int getHeight() { return pixelHeight; }
+
+ /** Returns true if data has the channels reversed to BGR or BGRA, otherwise RGB or RGBA is expected. */
+ public boolean getHasReversedChannels() { return reversedChannels; }
+
+ /** Returns the OpenGL format for this texture; e.g. GL.GL_LUMINANCE, GL.GL_RGB or GL.GL_RGBA. */
+ public int getGLFormat() { return glFormat; }
+
+ /** Returns the OpenGL data type: GL.GL_UNSIGNED_BYTE. */
+ public int getGLType() { return GL.GL_UNSIGNED_BYTE; }
+
+ /** Returns the bytes per pixel */
+ public int getBytesPerPixel() { return bytesPerPixel; }
+
+ /** Returns the raw data for this texture in the correct
+ (bottom-to-top) order for calls to glTexImage2D. */
+ public ByteBuffer getData() { return data; }
+
+ @Override
+ public String toString() { return "JPEGImage["+pixelWidth+"x"+pixelHeight+", bytesPerPixel "+bytesPerPixel+", reversedChannels "+reversedChannels+", "+pixelStorage+", "+data+"]"; }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java
index 37dbc54df..772df7279 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -76,118 +76,134 @@ public class LEDataInputStream extends FilterInputStream implements DataInput
*/
DataInputStream dataIn;
- public LEDataInputStream(InputStream in)
+ public LEDataInputStream(final InputStream in)
{
super(in);
dataIn = new DataInputStream(in);
}
+ @Override
public void close() throws IOException
{
dataIn.close(); // better close as we create it.
// this will close underlying as well.
}
- public synchronized final int read(byte b[]) throws IOException
+ @Override
+ public synchronized final int read(final byte b[]) throws IOException
{
return dataIn.read(b, 0, b.length);
}
- public synchronized final int read(byte b[], int off, int len) throws IOException
+ @Override
+ public synchronized final int read(final byte b[], final int off, final int len) throws IOException
{
- int rl = dataIn.read(b, off, len);
+ final int rl = dataIn.read(b, off, len);
return rl;
}
- public final void readFully(byte b[]) throws IOException
+ @Override
+ public final void readFully(final byte b[]) throws IOException
{
dataIn.readFully(b, 0, b.length);
}
- public final void readFully(byte b[], int off, int len) throws IOException
+ @Override
+ public final void readFully(final byte b[], final int off, final int len) throws IOException
{
dataIn.readFully(b, off, len);
}
- public final int skipBytes(int n) throws IOException
+ @Override
+ public final int skipBytes(final int n) throws IOException
{
return dataIn.skipBytes(n);
}
+ @Override
public final boolean readBoolean() throws IOException
{
- int ch = dataIn.read();
+ final int ch = dataIn.read();
if (ch < 0)
throw new EOFException();
return (ch != 0);
}
+ @Override
public final byte readByte() throws IOException
{
- int ch = dataIn.read();
+ final int ch = dataIn.read();
if (ch < 0)
throw new EOFException();
return (byte)(ch);
}
+ @Override
public final int readUnsignedByte() throws IOException
{
- int ch = dataIn.read();
+ final int ch = dataIn.read();
if (ch < 0)
throw new EOFException();
return ch;
}
+ @Override
public final short readShort() throws IOException
{
- int ch1 = dataIn.read();
- int ch2 = dataIn.read();
+ final int ch1 = dataIn.read();
+ final int ch2 = dataIn.read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (short)((ch1 << 0) + (ch2 << 8));
}
+ @Override
public final int readUnsignedShort() throws IOException
- {
- int ch1 = dataIn.read();
- int ch2 = dataIn.read();
+ {
+ final int ch1 = dataIn.read();
+ final int ch2 = dataIn.read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (ch1 << 0) + (ch2 << 8);
}
+ @Override
public final char readChar() throws IOException
{
- int ch1 = dataIn.read();
- int ch2 = dataIn.read();
+ final int ch1 = dataIn.read();
+ final int ch2 = dataIn.read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (char)((ch1 << 0) + (ch2 << 8));
}
+ @Override
public final int readInt() throws IOException
{
- int ch1 = dataIn.read();
- int ch2 = dataIn.read();
- int ch3 = dataIn.read();
- int ch4 = dataIn.read();
+ final int ch1 = dataIn.read();
+ final int ch2 = dataIn.read();
+ final int ch3 = dataIn.read();
+ final int ch4 = dataIn.read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return ((ch1 << 0) + (ch2 << 8) + (ch3 << 16) + (ch4 << 24));
}
+ @Override
public final long readLong() throws IOException
{
- int i1 = readInt();
- int i2 = readInt();
- return ((long)(i1) & 0xFFFFFFFFL) + (i2 << 32);
+ final int i1 = readInt();
+ final int i2 = readInt();
+ return (i1 & 0xFFFFFFFFL) + ((long)i2 << 32);
}
+ @Override
public final float readFloat() throws IOException
{
return Float.intBitsToFloat(readInt());
}
+ @Override
public final double readDouble() throws IOException
{
return Double.longBitsToDouble(readLong());
@@ -195,29 +211,31 @@ public class LEDataInputStream extends FilterInputStream implements DataInput
/**
* dont call this it is not implemented.
- * @return empty new string
+ * @return empty new string
**/
+ @Override
public final String readLine() throws IOException
{
- return new String();
+ return "";
}
/**
* dont call this it is not implemented
- * @return empty new string
+ * @return empty new string
**/
+ @Override
public final String readUTF() throws IOException
{
- return new String();
+ return "";
}
/**
* dont call this it is not implemented
- * @return empty new string
+ * @return empty new string
**/
- public final static String readUTF(DataInput in) throws IOException
+ public final static String readUTF(final DataInput in) throws IOException
{
- return new String();
+ return "";
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java
index e1e1ca924..add177546 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -72,72 +72,84 @@ public class LEDataOutputStream extends FilterOutputStream implements DataOutput
*/
DataOutputStream dataOut;
- public LEDataOutputStream(OutputStream out)
+ public LEDataOutputStream(final OutputStream out)
{
super(out);
dataOut = new DataOutputStream(out);
}
+ @Override
public void close() throws IOException
{
dataOut.close(); // better close as we create it.
// this will close underlying as well.
}
- public synchronized final void write(byte b[]) throws IOException
+ @Override
+ public synchronized final void write(final byte b[]) throws IOException
{
dataOut.write(b, 0, b.length);
}
- public synchronized final void write(byte b[], int off, int len) throws IOException
+ @Override
+ public synchronized final void write(final byte b[], final int off, final int len) throws IOException
{
dataOut.write(b, off, len);
}
- public final void write(int b) throws IOException
+ @Override
+ public final void write(final int b) throws IOException
{
dataOut.write(b);
}
- public final void writeBoolean(boolean v) throws IOException
+ @Override
+ public final void writeBoolean(final boolean v) throws IOException
{
dataOut.writeBoolean(v);
}
- public final void writeByte(int v) throws IOException
+ @Override
+ public final void writeByte(final int v) throws IOException
{
dataOut.writeByte(v);
}
/** Don't call this -- not implemented */
- public final void writeBytes(String s) throws IOException
+ @Override
+ public final void writeBytes(final String s) throws IOException
{
throw new UnsupportedOperationException();
}
- public final void writeChar(int v) throws IOException
+ @Override
+ public final void writeChar(final int v) throws IOException
{
dataOut.writeChar(((v >> 8) & 0xff) |
((v & 0xff) << 8));
}
/** Don't call this -- not implemented */
- public final void writeChars(String s) throws IOException
+ @Override
+ public final void writeChars(final String s) throws IOException
{
throw new UnsupportedOperationException();
}
- public final void writeDouble(double v) throws IOException
+ @Override
+ public final void writeDouble(final double v) throws IOException
{
writeLong(Double.doubleToRawLongBits(v));
}
- public final void writeFloat(float v) throws IOException
+ @Override
+ public final void writeFloat(final float v) throws IOException
{
writeInt(Float.floatToRawIntBits(v));
}
- public final void writeInt(int v) throws IOException
+ @Override
+ public final void writeInt(final int v) throws IOException
{
dataOut.writeInt((v >>> 24) |
((v >>> 8) & 0xff00) |
@@ -145,20 +157,23 @@ public class LEDataOutputStream extends FilterOutputStream implements DataOutput
(v << 24));
}
- public final void writeLong(long v) throws IOException
+ @Override
+ public final void writeLong(final long v) throws IOException
{
writeInt((int) v);
writeInt((int) (v >>> 32));
}
- public final void writeShort(int v) throws IOException
+ @Override
+ public final void writeShort(final int v) throws IOException
{
dataOut.writeShort(((v >> 8) & 0xff) |
((v & 0xff) << 8));
}
/** Don't call this -- not implemented */
- public final void writeUTF(String s) throws IOException
+ @Override
+ public final void writeUTF(final String s) throws IOException
{
throw new UnsupportedOperationException();
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java
index cd42a1157..461ddceb8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -63,7 +63,7 @@ public class NetPbmTextureWriter implements TextureWriter {
* magic 7 - PAM binary RGB or RGBA
* </pre>
*/
- public NetPbmTextureWriter(int magic) {
+ public NetPbmTextureWriter(final int magic) {
switch(magic) {
case 0:
case 6:
@@ -84,11 +84,12 @@ public class NetPbmTextureWriter implements TextureWriter {
public String getSuffix() { return (magic==6)?PPM:PAM; }
- public boolean write(File file, TextureData data) throws IOException {
+ @Override
+ public boolean write(final File file, final TextureData data) throws IOException {
boolean res;
final int magic_old = magic;
-
- // file suffix selection
+
+ // file suffix selection
if (0==magic) {
if (PPM.equals(IOUtil.getFileSuffix(file))) {
magic = 6;
@@ -97,7 +98,7 @@ public class NetPbmTextureWriter implements TextureWriter {
} else {
return false;
}
- }
+ }
try {
res = writeImpl(file, data);
} finally {
@@ -105,30 +106,30 @@ public class NetPbmTextureWriter implements TextureWriter {
}
return res;
}
-
- private boolean writeImpl(File file, TextureData data) throws IOException {
+
+ private boolean writeImpl(final File file, final TextureData data) throws IOException {
int pixelFormat = data.getPixelFormat();
final int pixelType = data.getPixelType();
if ((pixelFormat == GL.GL_RGB ||
pixelFormat == GL.GL_RGBA ||
- pixelFormat == GL2.GL_BGR ||
+ pixelFormat == GL2GL3.GL_BGR ||
pixelFormat == GL.GL_BGRA ) &&
(pixelType == GL.GL_BYTE ||
pixelType == GL.GL_UNSIGNED_BYTE)) {
-
+
ByteBuffer buf = (ByteBuffer) data.getBuffer();
if (null == buf ) {
buf = (ByteBuffer) data.getMipmapData()[0];
}
buf.rewind();
-
- int comps = ( pixelFormat == GL.GL_RGBA || pixelFormat == GL.GL_BGRA ) ? 4 : 3 ;
-
- if( pixelFormat == GL2.GL_BGR || pixelFormat == GL.GL_BGRA ) {
+
+ final int comps = ( pixelFormat == GL.GL_RGBA || pixelFormat == GL.GL_BGRA ) ? 4 : 3 ;
+
+ if( pixelFormat == GL2GL3.GL_BGR || pixelFormat == GL.GL_BGRA ) {
// Must reverse order of red and blue channels to get correct results
for (int i = 0; i < buf.remaining(); i += comps) {
- byte red = buf.get(i + 0);
- byte blue = buf.get(i + 2);
+ final byte red = buf.get(i + 0);
+ final byte blue = buf.get(i + 2);
buf.put(i + 0, blue);
buf.put(i + 2, red);
}
@@ -140,9 +141,9 @@ public class NetPbmTextureWriter implements TextureWriter {
throw new IOException("NetPbmTextureWriter magic 6 (PPM) doesn't RGBA pixel format, use magic 7 (PAM)");
}
- FileOutputStream fos = IOUtil.getFileOutputStream(file, true);
-
- StringBuilder header = new StringBuilder();
+ final FileOutputStream fos = IOUtil.getFileOutputStream(file, true);
+
+ final StringBuilder header = new StringBuilder();
header.append("P");
header.append(magic);
header.append("\n");
@@ -171,8 +172,8 @@ public class NetPbmTextureWriter implements TextureWriter {
}
fos.write(header.toString().getBytes());
-
- FileChannel fosc = fos.getChannel();
+
+ final FileChannel fosc = fos.getChannel();
fosc.write(buf);
fosc.force(true);
fosc.close();
@@ -180,7 +181,7 @@ public class NetPbmTextureWriter implements TextureWriter {
buf.rewind();
return true;
- }
+ }
throw new IOException("NetPbmTextureWriter writer doesn't support this pixel format / type (only GL_RGB/A + bytes)");
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
deleted file mode 100644
index d8d6f7daa..000000000
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
+++ /dev/null
@@ -1,195 +0,0 @@
-package com.jogamp.opengl.util.texture.spi;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-
-import javax.media.opengl.GL;
-
-import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.ImageLine;
-import jogamp.opengl.util.pngj.PngReader;
-import jogamp.opengl.util.pngj.PngWriter;
-import jogamp.opengl.util.pngj.chunks.PngChunkTextVar;
-
-import com.jogamp.common.nio.Buffers;
-import com.jogamp.common.util.IOUtil;
-
-
-public class PNGImage {
- /** Creates a PNGImage from data supplied by the end user. Shares
- data with the passed ByteBuffer. Assumes the data is already in
- the correct byte order for writing to disk, i.e., LUMINANCE, RGB or RGBA bottom-to-top (OpenGL coord). */
- public static PNGImage createFromData(int width, int height, double dpiX, double dpiY,
- int bytesPerPixel, boolean reversedChannels, ByteBuffer data) {
- return new PNGImage(width, height, dpiX, dpiY, bytesPerPixel, reversedChannels, data);
- }
-
- /** Reads a PNG image from the specified InputStream. */
- public static PNGImage read(InputStream in) throws IOException {
- return new PNGImage(in);
- }
-
- /** Reverse read and store, implicitly flip image to GL coords. */
- private static final int getPixelRGBA8(ByteBuffer d, int dOff, ImageLine line, int lineOff, boolean hasAlpha) {
- if(hasAlpha) {
- d.put(dOff--, (byte)line.scanline[lineOff + 3]); // A
- }
- d.put(dOff--, (byte)line.scanline[lineOff + 2]); // B
- d.put(dOff--, (byte)line.scanline[lineOff + 1]); // G
- d.put(dOff--, (byte)line.scanline[lineOff ]); // R
- return dOff;
- }
- /** Reverse read and store, implicitly flip image from GL coords. Handle reversed channels (BGR[A])*/
- private static int setPixelRGBA8(ImageLine line, int lineOff, ByteBuffer d, int dOff, boolean hasAlpha, boolean reversedChannels) {
- if(reversedChannels) {
- line.scanline[lineOff ] = d.get(dOff--); // R, A
- line.scanline[lineOff + 1] = d.get(dOff--); // G, B
- line.scanline[lineOff + 2] = d.get(dOff--); // B, G
- if(hasAlpha) {
- line.scanline[lineOff + 3] = d.get(dOff--);// R
- }
- } else {
- if(hasAlpha) {
- line.scanline[lineOff + 3] = d.get(dOff--); // A
- }
- line.scanline[lineOff + 2] = d.get(dOff--); // B
- line.scanline[lineOff + 1] = d.get(dOff--); // G
- line.scanline[lineOff ] = d.get(dOff--); // R
- }
- return dOff;
- }
-
- private PNGImage(int width, int height, double dpiX, double dpiY, int bytesPerPixel, boolean reversedChannels, ByteBuffer data) {
- pixelWidth=width;
- pixelHeight=height;
- dpi = new double[] { dpiX, dpiY };
- if(4 == bytesPerPixel) {
- glFormat = GL.GL_RGBA;
- } else if (3 == bytesPerPixel) {
- glFormat = GL.GL_RGB;
- } else {
- throw new InternalError("XXX: bytesPerPixel "+bytesPerPixel);
- }
- this.bytesPerPixel = bytesPerPixel;
- this.reversedChannels = reversedChannels;
- this.data = data;
- }
-
- private PNGImage(InputStream in) {
- final PngReader pngr = new PngReader(new BufferedInputStream(in), null);
- final int channels = pngr.imgInfo.channels;
- if ( ! ( 1 == channels || 3 == channels || 4 == channels ) ) {
- throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 channels] images for now. Channels "+channels);
- }
- bytesPerPixel=pngr.imgInfo.bytesPixel;
- if ( ! ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel ) ) {
- throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 bpp] images for now. BytesPerPixel "+bytesPerPixel);
- }
- if(channels != bytesPerPixel) {
- throw new RuntimeException("PNGImage currently only handles Channels [1/3/4] == BytePerPixel [1/3/4], channels: "+channels+", bytesPerPixel "+bytesPerPixel);
- }
- pixelWidth=pngr.imgInfo.cols;
- pixelHeight=pngr.imgInfo.rows;
- dpi = new double[2];
- {
- final double[] dpi2 = pngr.getMetadata().getDpi();
- dpi[0]=dpi2[0];
- dpi[1]=dpi2[1];
- }
- switch(channels) {
- case 1: glFormat = GL.GL_LUMINANCE; break;
- case 3: glFormat = GL.GL_RGB; break;
- case 4: glFormat = GL.GL_RGBA; break;
- default: throw new InternalError("XXX: channels: "+channels+", bytesPerPixel "+bytesPerPixel);
- }
- data = Buffers.newDirectByteBuffer(bytesPerPixel * pixelWidth * pixelHeight);
- reversedChannels = false; // RGB[A]
- final boolean hasAlpha = 4 == channels;
- int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse store
- for (int row = 0; row < pixelHeight; row++) {
- final ImageLine l1 = pngr.readRow(row);
- int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse read
- if(1 == channels) {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- data.put(dataOff--, (byte)l1.scanline[lineOff--]); // Luminance, 1 bytesPerPixel
- }
- } else {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- dataOff = getPixelRGBA8(data, dataOff, l1, lineOff, hasAlpha);
- lineOff -= bytesPerPixel;
- }
- }
- }
- pngr.end();
- }
- private final int pixelWidth, pixelHeight, glFormat, bytesPerPixel;
- private boolean reversedChannels;
- private final double[] dpi;
- private final ByteBuffer data;
-
- /** Returns the width of the image. */
- public int getWidth() { return pixelWidth; }
-
- /** Returns the height of the image. */
- public int getHeight() { return pixelHeight; }
-
- /** Returns true if data has the channels reversed to BGR or BGRA, otherwise RGB or RGBA is expected. */
- public boolean getHasReversedChannels() { return reversedChannels; }
-
- /** Returns the dpi of the image. */
- public double[] getDpi() { return dpi; }
-
- /** Returns the OpenGL format for this texture; e.g. GL.GL_BGR or GL.GL_BGRA. */
- public int getGLFormat() { return glFormat; }
-
- /** Returns the OpenGL data type: GL.GL_UNSIGNED_BYTE. */
- public int getGLType() { return GL.GL_UNSIGNED_BYTE; }
-
- /** Returns the bytes per pixel */
- public int getBytesPerPixel() { return bytesPerPixel; }
-
- /** Returns the raw data for this texture in the correct
- (bottom-to-top) order for calls to glTexImage2D. */
- public ByteBuffer getData() { return data; }
-
- public void write(File out, boolean allowOverwrite) throws IOException {
- final ImageInfo imi = new ImageInfo(pixelWidth, pixelHeight, 8, (4 == bytesPerPixel) ? true : false); // 8 bits per channel, no alpha
- // open image for writing to a output stream
- final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out, allowOverwrite));
- try {
- final PngWriter png = new PngWriter(outs, imi);
- // add some optional metadata (chunks)
- png.getMetadata().setDpi(dpi[0], dpi[1]);
- png.getMetadata().setTimeNow(0); // 0 seconds fron now = now
- png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGImage");
- // png.getMetadata().setText("my key", "my text");
- final boolean hasAlpha = 4 == bytesPerPixel;
- final ImageLine l1 = new ImageLine(imi);
- int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse read
- for (int row = 0; row < pixelHeight; row++) {
- int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse store
- if(1 == bytesPerPixel) {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- l1.scanline[lineOff--] = data.get(dataOff--); // // Luminance, 1 bytesPerPixel
- }
- } else {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha, reversedChannels);
- lineOff -= bytesPerPixel;
- }
- }
- png.writeRow(l1, row);
- }
- png.end();
- } finally {
- IOUtil.close(outs, false);
- }
- }
-
- public String toString() { return "PNGImage["+pixelWidth+"x"+pixelHeight+", dpi "+dpi[0]+" x "+dpi[1]+", bytesPerPixel "+bytesPerPixel+", reversedChannels "+reversedChannels+", "+data+"]"; }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java
index d35330f58..27549dfe3 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java
@@ -1,21 +1,21 @@
/*
* Portions Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -54,7 +54,7 @@ import com.jogamp.common.util.IOUtil;
*/
public class SGIImage {
- private Header header;
+ private final Header header;
private int format;
private byte[] data;
// Used for decoding RLE-compressed images
@@ -72,15 +72,15 @@ public class SGIImage {
byte storage; // Storage format
// 0 for uncompressed
// 1 for RLE compression
- byte bpc; // Number of bytes per pixel channel
+ byte bpc; // Number of bytes per pixel channel
// Legally 1 or 2
short dimension; // Number of dimensions
// Legally 1, 2, or 3
// 1 means a single row, XSIZE long
// 2 means a single 2D image
// 3 means multiple 2D images
- short xsize; // X size in pixels
- short ysize; // Y size in pixels
+ short xsize; // X size in pixels
+ short ysize; // Y size in pixels
short zsize; // Number of channels
// 1 indicates greyscale
// 3 indicates RGB
@@ -105,7 +105,7 @@ public class SGIImage {
magic = MAGIC;
}
- Header(DataInputStream in) throws IOException {
+ Header(final DataInputStream in) throws IOException {
magic = in.readShort();
storage = in.readByte();
bpc = in.readByte();
@@ -116,16 +116,17 @@ public class SGIImage {
pixmin = in.readInt();
pixmax = in.readInt();
dummy = in.readInt();
- byte[] tmpname = new byte[80];
+ final byte[] tmpname = new byte[80];
in.read(tmpname);
int numChars = 0;
while (tmpname[numChars++] != 0);
imagename = new String(tmpname, 0, numChars);
colormap = in.readInt();
- byte[] tmp = new byte[404];
+ final byte[] tmp = new byte[404];
in.read(tmp);
}
+ @Override
public String toString() {
return ("magic: " + magic +
" storage: " + (int) storage +
@@ -141,21 +142,21 @@ public class SGIImage {
}
}
- private SGIImage(Header header) {
+ private SGIImage(final Header header) {
this.header = header;
}
/** Reads an SGI image from the specified file. */
- public static SGIImage read(String filename) throws IOException {
+ public static SGIImage read(final String filename) throws IOException {
return read(new FileInputStream(filename));
}
/** Reads an SGI image from the specified InputStream. */
- public static SGIImage read(InputStream in) throws IOException {
- DataInputStream dIn = new DataInputStream(new BufferedInputStream(in));
+ public static SGIImage read(final InputStream in) throws IOException {
+ final DataInputStream dIn = new DataInputStream(new BufferedInputStream(in));
- Header header = new Header(dIn);
- SGIImage res = new SGIImage(header);
+ final Header header = new Header(dIn);
+ final SGIImage res = new SGIImage(header);
res.decodeImage(dIn);
return res;
}
@@ -163,28 +164,28 @@ public class SGIImage {
/** Writes this SGIImage to the specified file name. If
flipVertically is set, outputs the scanlines from top to bottom
rather than the default bottom to top order. */
- public void write(String filename, boolean flipVertically) throws IOException {
+ public void write(final String filename, final boolean flipVertically) throws IOException {
write(new File(filename), flipVertically);
}
/** Writes this SGIImage to the specified file. If flipVertically is
set, outputs the scanlines from top to bottom rather than the
default bottom to top order. */
- public void write(File file, boolean flipVertically) throws IOException {
+ public void write(final File file, final boolean flipVertically) throws IOException {
writeImage(file, data, header.xsize, header.ysize, header.zsize, flipVertically);
}
/** Creates an SGIImage from the specified data in either RGB or
RGBA format. */
- public static SGIImage createFromData(int width,
- int height,
- boolean hasAlpha,
- byte[] data) {
- Header header = new Header();
+ public static SGIImage createFromData(final int width,
+ final int height,
+ final boolean hasAlpha,
+ final byte[] data) {
+ final Header header = new Header();
header.xsize = (short) width;
header.ysize = (short) height;
header.zsize = (short) (hasAlpha ? 4 : 3);
- SGIImage image = new SGIImage(header);
+ final SGIImage image = new SGIImage(header);
image.data = data;
return image;
}
@@ -200,9 +201,9 @@ public class SGIImage {
if (!in.markSupported()) {
throw new IOException("Can not test non-destructively whether given InputStream is an SGI RGB image");
}
- DataInputStream dIn = new DataInputStream(in);
+ final DataInputStream dIn = new DataInputStream(in);
dIn.mark(4);
- short magic = dIn.readShort();
+ final short magic = dIn.readShort();
dIn.reset();
return (magic == MAGIC);
}
@@ -226,6 +227,7 @@ public class SGIImage {
(bottom-to-top) order for calls to glTexImage2D. */
public byte[] getData() { return data; }
+ @Override
public String toString() {
return header.toString();
}
@@ -233,11 +235,11 @@ public class SGIImage {
//----------------------------------------------------------------------
// Internals only below this point
//
-
- private void decodeImage(DataInputStream in) throws IOException {
+
+ private void decodeImage(final DataInputStream in) throws IOException {
if (header.storage == 1) {
// Read RLE compression data; row starts and sizes
- int x = header.ysize * header.zsize;
+ final int x = header.ysize * header.zsize;
rowStart = new int[x];
rowSize = new int[x];
rleEnd = 4 * 2 * x + 512;
@@ -251,16 +253,16 @@ public class SGIImage {
}
tmpData = readAll(in);
- int xsize = header.xsize;
- int ysize = header.ysize;
- int zsize = header.zsize;
+ final int xsize = header.xsize;
+ final int ysize = header.ysize;
+ final int zsize = header.zsize;
int lptr = 0;
data = new byte[xsize * ysize * 4];
- byte[] rbuf = new byte[xsize];
- byte[] gbuf = new byte[xsize];
- byte[] bbuf = new byte[xsize];
- byte[] abuf = new byte[xsize];
+ final byte[] rbuf = new byte[xsize];
+ final byte[] gbuf = new byte[xsize];
+ final byte[] bbuf = new byte[xsize];
+ final byte[] abuf = new byte[xsize];
for (int y = 0; y < ysize; y++) {
if (zsize >= 4) {
getRow(rbuf, y, 0);
@@ -291,15 +293,15 @@ public class SGIImage {
header.zsize = 4;
}
- private void getRow(byte[] buf, int y, int z) {
+ private void getRow(final byte[] buf, final int y, final int z) {
if (header.storage == 1) {
- int offs = rowStart[y + z * header.ysize] - rleEnd;
+ final int offs = rowStart[y + z * header.ysize] - rleEnd;
System.arraycopy(tmpData, offs, tmpRead, 0, rowSize[y + z * header.ysize]);
int iPtr = 0;
int oPtr = 0;
for (;;) {
byte pixel = tmpRead[iPtr++];
- int count = (int) (pixel & 0x7F);
+ int count = pixel & 0x7F;
if (count == 0) {
return;
}
@@ -315,12 +317,12 @@ public class SGIImage {
}
}
} else {
- int offs = (y * header.xsize) + (z * header.xsize * header.ysize);
+ final int offs = (y * header.xsize) + (z * header.xsize * header.ysize);
System.arraycopy(tmpData, offs, buf, 0, header.xsize);
}
}
- private void bwtorgba(byte[] b, byte[] dest, int lptr) {
+ private void bwtorgba(final byte[] b, final byte[] dest, final int lptr) {
for (int i = 0; i < b.length; i++) {
dest[4 * i + lptr + 0] = b[i];
dest[4 * i + lptr + 1] = b[i];
@@ -329,7 +331,7 @@ public class SGIImage {
}
}
- private void latorgba(byte[] b, byte[] a, byte[] dest, int lptr) {
+ private void latorgba(final byte[] b, final byte[] a, final byte[] dest, final int lptr) {
for (int i = 0; i < b.length; i++) {
dest[4 * i + lptr + 0] = b[i];
dest[4 * i + lptr + 1] = b[i];
@@ -338,7 +340,7 @@ public class SGIImage {
}
}
- private void rgbtorgba(byte[] r, byte[] g, byte[] b, byte[] dest, int lptr) {
+ private void rgbtorgba(final byte[] r, final byte[] g, final byte[] b, final byte[] dest, final int lptr) {
for (int i = 0; i < b.length; i++) {
dest[4 * i + lptr + 0] = r[i];
dest[4 * i + lptr + 1] = g[i];
@@ -347,7 +349,7 @@ public class SGIImage {
}
}
- private void rgbatorgba(byte[] r, byte[] g, byte[] b, byte[] a, byte[] dest, int lptr) {
+ private void rgbatorgba(final byte[] r, final byte[] g, final byte[] b, final byte[] a, final byte[] dest, final int lptr) {
for (int i = 0; i < b.length; i++) {
dest[4 * i + lptr + 0] = r[i];
dest[4 * i + lptr + 1] = g[i];
@@ -356,19 +358,19 @@ public class SGIImage {
}
}
- private static byte imgref(byte[] i,
- int x,
- int y,
- int z,
- int xs,
- int ys,
- int zs) {
+ private static byte imgref(final byte[] i,
+ final int x,
+ final int y,
+ final int z,
+ final int xs,
+ final int ys,
+ final int zs) {
return i[(xs*ys*z)+(xs*y)+x];
}
- private void writeHeader(DataOutputStream stream,
- int xsize, int ysize, int zsize, boolean rle) throws IOException {
+ private void writeHeader(final DataOutputStream stream,
+ final int xsize, final int ysize, final int zsize, final boolean rle) throws IOException {
// effects: outputs the 512-byte IRIS RGB header to STREAM, using xsize,
// ysize, and depth as the dimensions of the image. NOTE that
// the following defaults are used:
@@ -413,14 +415,14 @@ public class SGIImage {
stream.write(0);
}
- private void writeImage(File file,
+ private void writeImage(final File file,
byte[] data,
- int xsize,
- int ysize,
- int zsize,
- boolean yflip) throws IOException {
+ final int xsize,
+ final int ysize,
+ final int zsize,
+ final boolean yflip) throws IOException {
// Input data is in RGBRGBRGB or RGBARGBARGBA format; first unswizzle it
- byte[] tmpData = new byte[xsize * ysize * zsize];
+ final byte[] tmpData = new byte[xsize * ysize * zsize];
int dest = 0;
for (int i = 0; i < zsize; i++) {
for (int j = i; j < (xsize * ysize * zsize); j += zsize) {
@@ -445,8 +447,8 @@ public class SGIImage {
// x axis).
// Build the offset tables
- int[] starttab = new int[ysize * zsize];
- int[] lengthtab = new int[ysize * zsize];
+ final int[] starttab = new int[ysize * zsize];
+ final int[] lengthtab = new int[ysize * zsize];
// Temporary buffer for holding RLE data.
// Note that this makes the assumption that RLE-compressed data will
@@ -457,8 +459,8 @@ public class SGIImage {
// empirical evidence here; the break-even point seems to be a look-
// ahead of 3. (That is, if the three values following this one are all
// the same as the current value, switch to repeat mode.)
- int lookahead = 3;
- byte[] rlebuf = new byte[2 * xsize * ysize * zsize];
+ final int lookahead = 3;
+ final byte[] rlebuf = new byte[2 * xsize * ysize * zsize];
int cur_loc = 0; // current offset location.
int ptr = 0;
@@ -473,20 +475,20 @@ public class SGIImage {
yincr = -1;
}
- boolean DEBUG = false;
+ final boolean DEBUG = false;
for (int z = 0; z < zsize; z++) {
for (int y = ystart; y != yend; y += yincr) {
// RLE-compress each row.
-
+
int x = 0;
byte count = 0;
boolean repeat_mode = false;
boolean should_switch = false;
- int start_ptr = ptr;
+ final int start_ptr = ptr;
int num_ptr = ptr++;
byte repeat_val = 0;
-
+
while (x < xsize) {
// see if we should switch modes
should_switch = false;
@@ -503,7 +505,7 @@ public class SGIImage {
if (DEBUG)
System.err.println("left side was " + ((int) imgref(data, x, y, z, xsize, ysize, zsize)) +
", right side was " + (int)imgref(data, x+i, y, z, xsize, ysize, zsize));
-
+
if (imgref(data, x, y, z, xsize, ysize, zsize) !=
imgref(data, x+i, y, z, xsize, ysize, zsize))
should_switch = false;
@@ -531,7 +533,7 @@ public class SGIImage {
repeat_mode = true;
repeat_val = imgref(data, x, y, z, xsize, ysize, zsize);
}
-
+
if (x > 0) {
// reset the number pointer
num_ptr = ptr++;
@@ -539,7 +541,7 @@ public class SGIImage {
count = 0;
}
}
-
+
// if not in repeat mode, copy element to ptr
if (!repeat_mode) {
rlebuf[ptr++] = imgref(data, x, y, z, xsize, ysize, zsize);
@@ -564,7 +566,7 @@ public class SGIImage {
x++;
}
// output this row's length into the length table
- int rowlen = ptr - start_ptr;
+ final int rowlen = ptr - start_ptr;
if (yflip)
lengthtab[ysize*z+(ysize-y-1)] = rowlen;
else
@@ -581,15 +583,15 @@ public class SGIImage {
// Now we have the offset tables computed, as well as the RLE data.
// Output this information to the file.
total_size = ptr;
-
- if (DEBUG)
+
+ if (DEBUG)
System.err.println("total_size was " + total_size);
- DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(IOUtil.getFileOutputStream(file, true)));
+ final DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(IOUtil.getFileOutputStream(file, true)));
writeHeader(stream, xsize, ysize, zsize, true);
- int SIZEOF_INT = 4;
+ final int SIZEOF_INT = 4;
for (int i = 0; i < (ysize * zsize); i++)
stream.writeInt(starttab[i] + 512 + (2 * ysize * zsize * SIZEOF_INT));
for (int i = 0; i < (ysize * zsize); i++)
@@ -600,18 +602,18 @@ public class SGIImage {
stream.close();
}
- private byte[] readAll(DataInputStream in) throws IOException {
+ private byte[] readAll(final DataInputStream in) throws IOException {
byte[] dest = new byte[16384];
int pos = 0;
int numRead = 0;
-
+
boolean done = false;
do {
numRead = in.read(dest, pos, dest.length - pos);
if (pos == dest.length) {
// Resize destination buffer
- byte[] newDest = new byte[2 * dest.length];
+ final byte[] newDest = new byte[2 * dest.length];
System.arraycopy(dest, 0, newDest, 0, pos);
dest = newDest;
}
@@ -624,7 +626,7 @@ public class SGIImage {
// Trim destination buffer
if (pos != dest.length) {
- byte[] finalDest = new byte[pos];
+ final byte[] finalDest = new byte[pos];
System.arraycopy(dest, 0, finalDest, 0, pos);
dest = finalDest;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java
index e202c59b7..28823abb3 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -71,12 +71,12 @@ import com.jogamp.common.util.IOUtil;
*/
public class TGAImage {
- private Header header;
+ private final Header header;
private int format;
private int bpp;
private ByteBuffer data;
- private TGAImage(Header header) {
+ private TGAImage(final Header header) {
this.header = header;
}
@@ -114,7 +114,7 @@ public class TGAImage {
public final static int I_FOURWAY = 2;
/** Type of this TGA file format */
- private int tgaType;
+ private final int tgaType;
/** initial TGA image data fields */
private int idLength; // byte value
@@ -142,13 +142,13 @@ public class TGAImage {
tgaType = TYPE_OLD; // dont try and get footer.
}
- Header(LEDataInputStream in) throws IOException {
+ Header(final LEDataInputStream in) throws IOException {
tgaType = TYPE_OLD; // dont try and get footer.
// initial header fields
- idLength = in.readUnsignedByte();
+ idLength = in.readUnsignedByte();
colorMapType = in.readUnsignedByte();
- imageType = in.readUnsignedByte();
+ imageType = in.readUnsignedByte();
// color map header fields
firstEntryIndex = in.readUnsignedShort();
@@ -199,6 +199,7 @@ public class TGAImage {
public byte[] imageIDbuf() { return imageIDbuf; }
public String imageID() { return imageID; }
+ @Override
public String toString() {
return "TGA Header " +
" id length: " + idLength +
@@ -219,24 +220,24 @@ public class TGAImage {
public int size() { return 18 + idLength; }
// buf must be in little-endian byte order
- private void write(ByteBuffer buf) {
+ private void write(final ByteBuffer buf) {
buf.put((byte) idLength);
buf.put((byte) colorMapType);
buf.put((byte) imageType);
buf.putShort((short) firstEntryIndex);
buf.putShort((short) colorMapLength);
- buf.put((byte) colorMapEntrySize);
+ buf.put(colorMapEntrySize);
buf.putShort((short) xOrigin);
buf.putShort((short) yOrigin);
buf.putShort((short) width);
buf.putShort((short) height);
- buf.put((byte) pixelDepth);
- buf.put((byte) imageDescriptor);
+ buf.put(pixelDepth);
+ buf.put(imageDescriptor);
if (idLength > 0) {
try {
- byte[] chars = imageID.getBytes("US-ASCII");
+ final byte[] chars = imageID.getBytes("US-ASCII");
buf.put(chars);
- } catch (UnsupportedEncodingException e) {
+ } catch (final UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
@@ -249,7 +250,7 @@ public class TGAImage {
* it into the JimiImage structure. This was taken from the
* prototype and modified for the new Jimi structure
*/
- private void decodeImage(GLProfile glp, LEDataInputStream dIn) throws IOException {
+ private void decodeImage(final GLProfile glp, final LEDataInputStream dIn) throws IOException {
switch (header.imageType()) {
case Header.UCOLORMAPPED:
throw new IOException("TGADecoder Uncompressed Colormapped images not supported");
@@ -273,23 +274,34 @@ public class TGAImage {
throw new IOException("TGADecoder Compressed Colormapped images not supported");
case Header.TRUECOLOR:
- throw new IOException("TGADecoder Compressed True Color images not supported");
+ switch (header.pixelDepth) {
+ case 16:
+ throw new IOException("TGADecoder Compressed 16-bit True Color images not supported");
+
+ case 24:
+ case 32:
+ decodeRGBImageRLE24_32(glp, dIn);
+ break;
+ }
+ break;
case Header.BLACKWHITE:
throw new IOException("TGADecoder Compressed Grayscale images not supported");
}
}
-
+
/**
* This assumes that the body is for a 24 bit or 32 bit for a
* RGB or ARGB image respectively.
*/
- private void decodeRGBImageU24_32(GLProfile glp, LEDataInputStream dIn) throws IOException {
+ private void decodeRGBImageU24_32(final GLProfile glp, final LEDataInputStream dIn) throws IOException {
+ setupImage24_32(glp);
+
int i; // row index
int y; // output row index
- int rawWidth = header.width() * (header.pixelDepth() / 8);
- byte[] rawBuf = new byte[rawWidth];
- byte[] tmpData = new byte[rawWidth * header.height()];
+ final int rawWidth = header.width() * bpp;
+ final byte[] rawBuf = new byte[rawWidth];
+ final byte[] tmpData = new byte[rawWidth * header.height()];
for (i = 0; i < header.height(); ++i) {
dIn.readFully(rawBuf, 0, rawWidth);
@@ -302,34 +314,60 @@ public class TGAImage {
System.arraycopy(rawBuf, 0, tmpData, y * rawWidth, rawBuf.length);
}
- if (header.pixelDepth() == 24) {
- bpp=3;
- if(glp.isGL2GL3()) {
- format = GL2GL3.GL_BGR;
- } else {
- format = GL.GL_RGB;
- swapBGR(tmpData, rawWidth, header.height(), bpp);
- }
- } else {
- assert header.pixelDepth() == 32;
- bpp=4;
+ if(format == GL.GL_RGB || format == GL.GL_RGBA)
+ swapBGR(tmpData, rawWidth, header.height(), bpp);
+ data = ByteBuffer.wrap(tmpData);
+ }
+
+ /**
+ * This assumes that the body is for a 24 bit or 32 bit for a
+ * RGB or ARGB image respectively.
+ */
+ private void decodeRGBImageRLE24_32(final GLProfile glp, final LEDataInputStream dIn) throws IOException {
+ setupImage24_32(glp);
+
+ final byte[] pixel = new byte[bpp];
+ final int rawWidth = header.width() * bpp;
+ final byte[] tmpData = new byte[rawWidth * header.height()];
+ int i = 0, j;
+ int packet, len;
+ while (i < tmpData.length) {
+ packet = dIn.readUnsignedByte();
+ len = (packet & 0x7F) + 1;
+ if ((packet & 0x80) != 0) {
+ dIn.read(pixel);
+ for (j = 0; j < len; ++j)
+ System.arraycopy(pixel, 0, tmpData, i + j * bpp, bpp);
+ } else
+ dIn.read(tmpData, i, len * bpp);
+ i += bpp * len;
+ }
+
+ if(format == GL.GL_RGB || format == GL.GL_RGBA)
+ swapBGR(tmpData, rawWidth, header.height(), bpp);
+ data = ByteBuffer.wrap(tmpData);
+ }
+
+ private void setupImage24_32(final GLProfile glp) {
+ bpp = header.pixelDepth / 8;
+ switch (header.pixelDepth) {
+ case 24:
+ format = glp.isGL2GL3() ? GL2GL3.GL_BGR : GL.GL_RGB;
+ break;
+ case 32:
boolean useBGRA = glp.isGL2GL3();
if(!useBGRA) {
final GLContext ctx = GLContext.getCurrent();
useBGRA = null != ctx && ctx.isTextureFormatBGRA8888Available();
}
- if( useBGRA ) {
- format = GL.GL_BGRA;
- } else {
- format = GL.GL_RGBA;
- swapBGR(tmpData, rawWidth, header.height(), bpp);
- }
+ format = useBGRA ? GL.GL_BGRA : GL.GL_RGBA;
+ break;
+ default:
+ assert false;
}
-
- data = ByteBuffer.wrap(tmpData);
}
- private static void swapBGR(byte[] data, int bWidth, int height, int bpp) {
+ private static void swapBGR(final byte[] data, final int bWidth, final int height, final int bpp) {
byte r,b;
int k;
for(int i=0; i<height; ++i) {
@@ -360,30 +398,30 @@ public class TGAImage {
public ByteBuffer getData() { return data; }
/** Reads a Targa image from the specified file. */
- public static TGAImage read(GLProfile glp, String filename) throws IOException {
+ public static TGAImage read(final GLProfile glp, final String filename) throws IOException {
return read(glp, new FileInputStream(filename));
}
/** Reads a Targa image from the specified InputStream. */
- public static TGAImage read(GLProfile glp, InputStream in) throws IOException {
- LEDataInputStream dIn = new LEDataInputStream(new BufferedInputStream(in));
+ public static TGAImage read(final GLProfile glp, final InputStream in) throws IOException {
+ final LEDataInputStream dIn = new LEDataInputStream(new BufferedInputStream(in));
- Header header = new Header(dIn);
- TGAImage res = new TGAImage(header);
+ final Header header = new Header(dIn);
+ final TGAImage res = new TGAImage(header);
res.decodeImage(glp, dIn);
return res;
}
/** Writes the image in Targa format to the specified file name. */
- public void write(String filename) throws IOException {
+ public void write(final String filename) throws IOException {
write(new File(filename));
}
/** Writes the image in Targa format to the specified file. */
- public void write(File file) throws IOException {
- FileOutputStream stream = IOUtil.getFileOutputStream(file, true);
- FileChannel chan = stream.getChannel();
- ByteBuffer buf = ByteBuffer.allocate(header.size());
+ public void write(final File file) throws IOException {
+ final FileOutputStream stream = IOUtil.getFileOutputStream(file, true);
+ final FileChannel chan = stream.getChannel();
+ final ByteBuffer buf = ByteBuffer.allocate(header.size());
buf.order(ByteOrder.LITTLE_ENDIAN);
header.write(buf);
buf.rewind();
@@ -399,19 +437,19 @@ public class TGAImage {
data with the passed ByteBuffer. Assumes the data is already in
the correct byte order for writing to disk, i.e., BGR or
BGRA. */
- public static TGAImage createFromData(int width,
- int height,
- boolean hasAlpha,
- boolean topToBottom,
- ByteBuffer data) {
- Header header = new Header();
+ public static TGAImage createFromData(final int width,
+ final int height,
+ final boolean hasAlpha,
+ final boolean topToBottom,
+ final ByteBuffer data) {
+ final Header header = new Header();
header.imageType = Header.UTRUECOLOR;
header.width = width;
header.height = height;
header.pixelDepth = (byte) (hasAlpha ? 32 : 24);
header.imageDescriptor = (byte) (topToBottom ? Header.ID_TOPTOBOTTOM : 0);
// Note ID not supported
- TGAImage ret = new TGAImage(header);
+ final TGAImage ret = new TGAImage(header);
ret.data = data;
return ret;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java
index 88018edbe..0299531b1 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java
index 55527cef5..35b8efa72 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java
index 6e2f1b992..4174adf52 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -54,12 +54,13 @@ import com.jogamp.opengl.util.texture.spi.*;
public class IIOTextureProvider implements TextureProvider {
private static final boolean DEBUG = Debug.debug("TextureIO");
- public TextureData newTextureData(GLProfile glp, File file,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
- BufferedImage img = ImageIO.read(file);
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final File file,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
+ final BufferedImage img = ImageIO.read(file);
if (img == null) {
return null;
}
@@ -70,12 +71,13 @@ public class IIOTextureProvider implements TextureProvider {
return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, img);
}
- public TextureData newTextureData(GLProfile glp, InputStream stream,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
- BufferedImage img = ImageIO.read(stream);
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final InputStream stream,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
+ final BufferedImage img = ImageIO.read(stream);
if (img == null) {
return null;
}
@@ -86,12 +88,13 @@ public class IIOTextureProvider implements TextureProvider {
return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, img);
}
- public TextureData newTextureData(GLProfile glp, URL url,
- int internalFormat,
- int pixelFormat,
- boolean mipmap,
- String fileSuffix) throws IOException {
- InputStream stream = url.openStream();
+ @Override
+ public TextureData newTextureData(final GLProfile glp, final URL url,
+ final int internalFormat,
+ final int pixelFormat,
+ final boolean mipmap,
+ final String fileSuffix) throws IOException {
+ final InputStream stream = url.openStream();
try {
return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix);
} finally {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java
index 89d0d20a1..60ac5680e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -53,10 +53,11 @@ import com.jogamp.opengl.util.texture.*;
import com.jogamp.opengl.util.texture.spi.*;
public class IIOTextureWriter implements TextureWriter {
- public boolean write(File file,
- TextureData data) throws IOException {
- int pixelFormat = data.getPixelFormat();
- int pixelType = data.getPixelType();
+ @Override
+ public boolean write(final File file,
+ final TextureData data) throws IOException {
+ final int pixelFormat = data.getPixelFormat();
+ final int pixelType = data.getPixelType();
if ((pixelFormat == GL.GL_RGB ||
pixelFormat == GL.GL_RGBA) &&
(pixelType == GL.GL_BYTE ||
@@ -67,7 +68,7 @@ public class IIOTextureWriter implements TextureWriter {
(pixelFormat == GL.GL_RGB) ?
BufferedImage.TYPE_3BYTE_BGR :
BufferedImage.TYPE_4BYTE_ABGR);
- byte[] imageData = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
+ final byte[] imageData = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
ByteBuffer buf = (ByteBuffer) data.getBuffer();
if (buf == null) {
buf = (ByteBuffer) data.getMipmapData()[0];
@@ -79,17 +80,17 @@ public class IIOTextureWriter implements TextureWriter {
// Swizzle image components to be correct
if (pixelFormat == GL.GL_RGB) {
for (int i = 0; i < imageData.length; i += 3) {
- byte red = imageData[i + 0];
- byte blue = imageData[i + 2];
+ final byte red = imageData[i + 0];
+ final byte blue = imageData[i + 2];
imageData[i + 0] = blue;
imageData[i + 2] = red;
}
} else {
for (int i = 0; i < imageData.length; i += 4) {
- byte red = imageData[i + 0];
- byte green = imageData[i + 1];
- byte blue = imageData[i + 2];
- byte alpha = imageData[i + 3];
+ final byte red = imageData[i + 0];
+ final byte green = imageData[i + 1];
+ final byte blue = imageData[i + 2];
+ final byte alpha = imageData[i + 3];
imageData[i + 0] = alpha;
imageData[i + 1] = blue;
imageData[i + 2] = green;
@@ -103,9 +104,9 @@ public class IIOTextureWriter implements TextureWriter {
// Happened to notice that writing RGBA images to JPEGS is broken
if (TextureIO.JPG.equals(IOUtil.getFileSuffix(file)) &&
image.getType() == BufferedImage.TYPE_4BYTE_ABGR) {
- BufferedImage tmpImage = new BufferedImage(image.getWidth(), image.getHeight(),
+ final BufferedImage tmpImage = new BufferedImage(image.getWidth(), image.getHeight(),
BufferedImage.TYPE_3BYTE_BGR);
- Graphics g = tmpImage.getGraphics();
+ final Graphics g = tmpImage.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
image = tmpImage;
@@ -113,7 +114,7 @@ public class IIOTextureWriter implements TextureWriter {
return ImageIO.write(image, IOUtil.getFileSuffix(file), file);
}
-
+
throw new IOException("ImageIO writer doesn't support this pixel format / type (only GL_RGB/A + bytes)");
}
}
diff --git a/src/jogl/classes/javax/media/opengl/DebugGL2.java b/src/jogl/classes/javax/media/opengl/DebugGL2.java
new file mode 100644
index 000000000..e0d24c4a1
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/DebugGL2.java
@@ -0,0 +1,21 @@
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL2 extends DebugGL4bc {
+ public DebugGL2(final GL2 downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/DebugGL3.java b/src/jogl/classes/javax/media/opengl/DebugGL3.java
new file mode 100644
index 000000000..678e800f6
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/DebugGL3.java
@@ -0,0 +1,21 @@
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL3 extends DebugGL4bc {
+ public DebugGL3(final GL3 downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/DebugGL3bc.java b/src/jogl/classes/javax/media/opengl/DebugGL3bc.java
new file mode 100644
index 000000000..2636e9428
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/DebugGL3bc.java
@@ -0,0 +1,21 @@
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL3bc extends DebugGL4bc {
+ public DebugGL3bc(final GL3bc downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/DebugGL4.java b/src/jogl/classes/javax/media/opengl/DebugGL4.java
new file mode 100644
index 000000000..c4f8764cb
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/DebugGL4.java
@@ -0,0 +1,21 @@
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGL4 extends DebugGL4bc {
+ public DebugGL4(final GL4 downstream) {
+ super((GL4bc)downstream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/DebugGLES2.java b/src/jogl/classes/javax/media/opengl/DebugGLES2.java
new file mode 100644
index 000000000..c4e06f347
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/DebugGLES2.java
@@ -0,0 +1,21 @@
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing error checking after each OpenGL method call. If an error occurs,
+ * causes a {@link GLException} to be thrown at exactly the point of failure.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new DebugGL(drawable.getGL()));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class DebugGLES2 extends DebugGLES3 {
+ public DebugGLES2(final GLES2 downstream) {
+ super((GLES3)downstream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
index b052769ca..412af25e0 100644
--- a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
+++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,9 +41,13 @@
package javax.media.opengl;
import javax.media.nativewindow.NativeWindowException;
+
import java.util.List;
+
import javax.media.nativewindow.CapabilitiesImmutable;
+import com.jogamp.common.util.PropertyAccess;
+
import jogamp.opengl.Debug;
/** <P> The default implementation of the {@link
@@ -85,7 +89,12 @@ import jogamp.opengl.Debug;
*/
public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
- private static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.CapabilitiesChooser", true);
+ private static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = PropertyAccess.isPropertyDefined("jogl.debug.CapabilitiesChooser", true);
+ }
private final static int NO_SCORE = -9999999;
private final static int DOUBLE_BUFFER_MISMATCH_PENALTY = 1000;
@@ -101,7 +110,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
private final static int ACCUM_MISMATCH_PENALTY_SCALE = 1;
private final static int STENCIL_MISMATCH_PENALTY_SCALE = 3;
private final static int MULTISAMPLE_MISMATCH_PENALTY_SCALE = 3;
-
+
@Override
public int chooseCapabilities(final CapabilitiesImmutable desired,
final List<? extends CapabilitiesImmutable> available,
@@ -137,13 +146,13 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
}
// Create score array
- int[] scores = new int[availnum];
-
+ final int[] scores = new int[availnum];
+
for (int i = 0; i < scores.length; i++) {
scores[i] = NO_SCORE;
}
final int gldes_samples = gldes.getNumSamples();
-
+
// Compute score for each
for (int i = 0; i < availnum; i++) {
final GLCapabilitiesImmutable cur = (GLCapabilitiesImmutable) available.get(i);
@@ -160,24 +169,24 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
} */
if (gldes.isPBuffer() && !cur.isPBuffer()) {
continue; // requested pBuffer, but n/a
- }
+ }
if (gldes.isBitmap() && !cur.isBitmap()) {
continue; // requested pBuffer, but n/a
- }
+ }
}
if (gldes.getStereo() != cur.getStereo()) {
continue;
}
final int cur_samples = cur.getNumSamples() ;
int score = 0;
-
+
// Compute difference in color depth
// (Note that this decides the direction of all other penalties)
score += (COLOR_MISMATCH_PENALTY_SCALE *
((cur.getRedBits() + cur.getGreenBits() + cur.getBlueBits() + cur.getAlphaBits()) -
(gldes.getRedBits() + gldes.getGreenBits() + gldes.getBlueBits() + gldes.getAlphaBits())));
// Compute difference in depth buffer depth
- score += (DEPTH_MISMATCH_PENALTY_SCALE * sign(score) *
+ score += (DEPTH_MISMATCH_PENALTY_SCALE * sign(score) *
Math.abs(cur.getDepthBits() - gldes.getDepthBits()));
// Compute difference in accumulation buffer depth
score += (ACCUM_MISMATCH_PENALTY_SCALE * sign(score) *
@@ -213,13 +222,13 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
boolean gotHW = false;
int maxAbsoluteHWScore = 0;
for (int i = 0; i < availnum; i++) {
- int score = scores[i];
+ final int score = scores[i];
if (score == NO_SCORE) {
continue;
}
final GLCapabilitiesImmutable cur = (GLCapabilitiesImmutable) available.get(i);
if (cur.getHardwareAccelerated()) {
- int absScore = Math.abs(score);
+ final int absScore = Math.abs(score);
if (!gotHW ||
(absScore > maxAbsoluteHWScore)) {
gotHW = true;
@@ -256,11 +265,11 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
System.err.println(" ]");
}
- // Ready to select. Choose score closest to 0.
+ // Ready to select. Choose score closest to 0.
int scoreClosestToZero = NO_SCORE;
int chosenIndex = -1;
for (int i = 0; i < availnum; i++) {
- int score = scores[i];
+ final int score = scores[i];
if (score == NO_SCORE) {
continue;
}
@@ -284,7 +293,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser {
return chosenIndex;
}
- private static int sign(int score) {
+ private static int sign(final int score) {
if (score < 0) {
return -1;
}
diff --git a/src/jogl/classes/javax/media/opengl/FPSCounter.java b/src/jogl/classes/javax/media/opengl/FPSCounter.java
index 9c07b58e4..4997258e0 100644
--- a/src/jogl/classes/javax/media/opengl/FPSCounter.java
+++ b/src/jogl/classes/javax/media/opengl/FPSCounter.java
@@ -36,28 +36,28 @@ import java.io.PrintStream;
*/
public interface FPSCounter {
public static final int DEFAULT_FRAMES_PER_INTERVAL = 5*60;
-
+
/**
- * @param frames Update interval in frames.<br> At every rendered <i>frames</i> interval the currentTime and fps values are updated.
+ * @param frames Update interval in frames.<br> At every rendered <i>frames</i> interval the currentTime and fps values are updated.
* If the <i>frames</i> interval is <= 0, no update will be issued, ie the FPSCounter feature is turned off. You may choose {@link #DEFAULT_FRAMES_PER_INTERVAL}.
- * @param out optional print stream where the fps values gets printed if not null at every <i>frames</i> interval
+ * @param out optional print stream where the fps values gets printed if not null at every <i>frames</i> interval
*/
void setUpdateFPSFrames(int frames, PrintStream out);
-
+
/**
* Reset all performance counter (startTime, currentTime, frame number)
*/
void resetFPSCounter();
-
+
/**
* @return update interval in frames
- *
+ *
* @see #setUpdateFPSFrames(int, PrintStream)
*/
int getUpdateFPSFrames();
-
+
/**
- * Returns the time of the first display call in milliseconds after enabling this feature via {@link #setUpdateFPSFrames(int, PrintStream)}.<br>
+ * Returns the time of the first display call in milliseconds after enabling this feature via {@link #setUpdateFPSFrames(int, PrintStream)}.<br>
* This value is reset via {@link #resetFPSCounter()}.
*
* @see #setUpdateFPSFrames(int, PrintStream)
@@ -81,18 +81,18 @@ public interface FPSCounter {
* @see #resetFPSCounter()
*/
long getLastFPSPeriod();
-
+
/**
* @return Last update interval's frames per seconds, {@link #getUpdateFPSFrames()} / {@link #getLastFPSPeriod()}
- *
+ *
* @see #setUpdateFPSFrames(int, PrintStream)
* @see #resetFPSCounter()
*/
- float getLastFPS();
-
+ float getLastFPS();
+
/**
* @return Number of frame rendered since {@link #getFPSStartTime()} up to {@link #getLastFPSUpdateTime()}
- *
+ *
* @see #setUpdateFPSFrames(int, PrintStream)
* @see #resetFPSCounter()
*/
@@ -108,10 +108,10 @@ public interface FPSCounter {
/**
- * @return Total frames per seconds, {@link #getTotalFPSFrames()} / {@link #getTotalFPSDuration()}
- *
+ * @return Total frames per seconds, {@link #getTotalFPSFrames()} / {@link #getTotalFPSDuration()}
+ *
* @see #setUpdateFPSFrames(int, PrintStream)
* @see #resetFPSCounter()
*/
- float getTotalFPS();
+ float getTotalFPS();
}
diff --git a/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java b/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
index 83e9e22c4..d14ada48b 100644
--- a/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
+++ b/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
@@ -29,24 +29,56 @@
package javax.media.opengl;
/**
- * An animator control interface,
+ * An animator control interface,
* which implementation may drive a {@link javax.media.opengl.GLAutoDrawable} animation.
*/
public interface GLAnimatorControl extends FPSCounter {
+ /**
+ * A {@link GLAnimatorControl#setUncaughtExceptionHandler(UncaughtExceptionHandler) registered}
+ * {@link UncaughtExceptionHandler} instance is invoked when an {@link GLAnimatorControl animator} abruptly {@link #stop() stops}
+ * due to an uncaught exception from one of its {@link GLAutoDrawable}s.
+ * @see #uncaughtException(GLAnimatorControl, GLAutoDrawable, Throwable)
+ * @see GLAnimatorControl#setUncaughtExceptionHandler(UncaughtExceptionHandler)
+ * @since 2.2
+ */
+ public static interface UncaughtExceptionHandler {
+ /**
+ * Method invoked when the given {@link GLAnimatorControl} is {@link GLAnimatorControl#stop() stopped} due to the
+ * given uncaught exception happened on the given {@link GLAutoDrawable}.
+ * <p>
+ * The animator thread can still be retrieved via {@link GLAnimatorControl#getThread()}.
+ * </p>
+ * <p>
+ * All {@link GLAnimatorControl} states already reflect its stopped state.
+ * </p>
+ * <p>
+ * After this handler method is called, the {@link GLAnimatorControl} is stopped.
+ * </p>
+ * <p>
+ * Any exception thrown by this method will be ignored.
+ * </p>
+ * @param animator the {@link GLAnimatorControl}
+ * @param drawable the causing {@link GLAutoDrawable}
+ * @param cause the uncaught exception
+ * @see GLAnimatorControl#setUncaughtExceptionHandler(UncaughtExceptionHandler)
+ * @since 2.2
+ */
+ void uncaughtException(final GLAnimatorControl animator, final GLAutoDrawable drawable, final Throwable cause);
+ }
/**
- * Indicates whether this animator is running, ie. has been started and not stopped.
+ * Indicates whether this animator has been {@link #start() started}.
*
* @see #start()
* @see #stop()
+ * @see #isPaused()
* @see #pause()
* @see #resume()
*/
boolean isStarted();
/**
- * Indicates whether this animator is running and animating,<br>
- * the latter is true if it has {@link GLAutoDrawable}s to render and is not paused.
+ * Indicates whether this animator {@link #isStarted() is started} and {@link #isPaused() is not paused}.
*
* @see #start()
* @see #stop()
@@ -56,7 +88,9 @@ public interface GLAnimatorControl extends FPSCounter {
boolean isAnimating();
/**
- * Indicates whether this animator is running and paused.
+ * Indicates whether this animator {@link #isStarted() is started}
+ * and either {@link #pause() manually paused} or paused
+ * automatically due to no {@link #add(GLAutoDrawable) added} {@link GLAutoDrawable}s.
*
* @see #start()
* @see #stop()
@@ -75,30 +109,38 @@ public interface GLAnimatorControl extends FPSCounter {
/**
* Starts this animator, if not running.
- * <P>
+ * <p>
* In most situations this method blocks until
* completion, except when called from the animation thread itself
* or in some cases from an implementation-internal thread like the
* AWT event queue thread.
- * <P>
+ * </p>
+ * <p>
+ * Note that an animator w/o {@link #add(GLAutoDrawable) added drawables}
+ * will be paused automatically.
+ * </p>
+ * <p>
* If started, all counters (time, frames, ..) are reset to zero.
+ * </p>
*
* @return true is started due to this call,
* otherwise false, ie started already or unable to start.
*
* @see #stop()
* @see #isAnimating()
+ * @see #isPaused()
* @see #getThread()
*/
boolean start();
/**
* Stops this animator.
- * <P>
+ * <p>
* In most situations this method blocks until
* completion, except when called from the animation thread itself
* or in some cases from an implementation-internal thread like the
* AWT event queue thread.
+ * </p>
*
* @return true is stopped due to this call,
* otherwise false, ie not started or unable to stop.
@@ -111,13 +153,14 @@ public interface GLAnimatorControl extends FPSCounter {
/**
* Pauses this animator.
- * <P>
+ * <p>
* In most situations this method blocks until
* completion, except when called from the animation thread itself
* or in some cases from an implementation-internal thread like the
* AWT event queue thread.
+ * </p>
*
- * @return false if if not started or already paused, otherwise true
+ * @return false if not started, already paused or failed to pause, otherwise true
*
* @see #resume()
* @see #isAnimating()
@@ -126,15 +169,17 @@ public interface GLAnimatorControl extends FPSCounter {
/**
* Resumes animation if paused.
- * <P>
+ * <p>
* In most situations this method blocks until
* completion, except when called from the animation thread itself
* or in some cases from an implementation-internal thread like the
* AWT event queue thread.
- * <P>
+ * </p>
+ * <p>
* If resumed, all counters (time, frames, ..) are reset to zero.
+ * </p>
*
- * @return false if if not started or not paused, otherwise true
+ * @return false if not started, not paused or unable to resume, otherwise true
*
* @see #pause()
* @see #isAnimating()
@@ -142,13 +187,50 @@ public interface GLAnimatorControl extends FPSCounter {
boolean resume();
/**
- * Removes a drawable from the animator's list of rendering drawables.<br>
+ * Adds a drawable to this animator's list of rendering drawables.
+ * <p>
+ * This allows the animator thread to become {@link #isAnimating() animating},
+ * in case the first drawable is added and the animator {@link #isStarted() is started}.
+ * </p>
+ *
+ * @param drawable the drawable to be added
+ * @throws IllegalArgumentException if drawable was already added to this animator
+ */
+ void add(GLAutoDrawable drawable);
+
+ /**
+ * Removes a drawable from the animator's list of rendering drawables.
+ * <p>
* This method should get called in case a drawable becomes invalid,
- * and will not be recovered.<br>
- * This allows the animator thread to become idle in case the last drawable
- * has reached it's end of life.<br>
- *
- * @param drawable the to be removed drawable
+ * and will not be recovered.
+ * </p>
+ * <p>
+ * This allows the animator thread to become {@link #isAnimating() not animating},
+ * in case the last drawable has been removed.
+ * </p>
+ *
+ * @param drawable the drawable to be removed
+ * @throws IllegalArgumentException if drawable was not added to this animator
*/
void remove(GLAutoDrawable drawable);
+
+ /**
+ * Returns the {@link UncaughtExceptionHandler} invoked when this {@link GLAnimatorControl animator} abruptly {@link #stop() stops}
+ * due to an uncaught exception from one of its {@link GLAutoDrawable}s.
+ * <p>
+ * Default is <code>null</code>.
+ * </p>
+ * @since 2.2
+ */
+ UncaughtExceptionHandler getUncaughtExceptionHandler();
+
+ /**
+ * Set the handler invoked when this {@link GLAnimatorControl animator} abruptly {@link #stop() stops}
+ * due to an uncaught exception from one of its {@link GLAutoDrawable}s.
+ * @param handler the {@link UncaughtExceptionHandler} to use as this {@link GLAnimatorControl animator}'s uncaught exception
+ * handler. Pass <code>null</code> to unset the handler.
+ * @see UncaughtExceptionHandler#uncaughtException(GLAnimatorControl, GLAutoDrawable, Throwable)
+ * @since 2.2
+ */
+ void setUncaughtExceptionHandler(final UncaughtExceptionHandler handler);
}
diff --git a/src/jogl/classes/javax/media/opengl/GLArrayData.java b/src/jogl/classes/javax/media/opengl/GLArrayData.java
index 7c56b53cb..97f58a92a 100644
--- a/src/jogl/classes/javax/media/opengl/GLArrayData.java
+++ b/src/jogl/classes/javax/media/opengl/GLArrayData.java
@@ -30,6 +30,8 @@ package javax.media.opengl;
import java.nio.Buffer;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+
/**
*
* The total number of bytes hold by the referenced buffer is:
@@ -38,6 +40,19 @@ import java.nio.Buffer;
*/
public interface GLArrayData {
/**
+ * Implementation and type dependent object association.
+ * <p>
+ * One currently known use case is to associate a {@link com.jogamp.opengl.util.glsl.ShaderState ShaderState}
+ * to an GLSL aware vertex attribute object, allowing to use the ShaderState to handle it's
+ * data persistence, location and state change.<br/>
+ * This is implicitly done via {@link com.jogamp.opengl.util.glsl.ShaderState#ownAttribute(GLArrayData, boolean) shaderState.ownAttribute(GLArrayData, boolean)}.
+ * </p>
+ * @param obj implementation and type dependent association
+ * @param enable pass true to enable the association and false to disable it.
+ */
+ public void associate(Object obj, boolean enable);
+
+ /**
* Returns true if this data set is intended for a GLSL vertex shader attribute,
* otherwise false, ie intended for fixed function vertex pointer
*/
@@ -47,10 +62,10 @@ public interface GLArrayData {
* The index of the predefined array index, see list below,
* or -1 in case of a shader attribute array.
*
- * @see javax.media.opengl.GL2#GL_VERTEX_ARRAY
- * @see javax.media.opengl.GL2#GL_NORMAL_ARRAY
- * @see javax.media.opengl.GL2#GL_COLOR_ARRAY
- * @see javax.media.opengl.GL2#GL_TEXTURE_COORD_ARRAY
+ * @see GLPointerFunc#GL_VERTEX_ARRAY
+ * @see GLPointerFunc#GL_NORMAL_ARRAY
+ * @see GLPointerFunc#GL_COLOR_ARRAY
+ * @see GLPointerFunc#GL_TEXTURE_COORD_ARRAY
*/
public int getIndex();
@@ -61,6 +76,11 @@ public interface GLArrayData {
/**
* Set a new name for this array.
+ * <p>
+ * This clears the location, i.e. sets it to -1.
+ * </p>
+ * @see #setLocation(int)
+ * @see #setLocation(GL2ES2, int)
*/
public void setName(String newName);
@@ -72,12 +92,35 @@ public interface GLArrayData {
public int getLocation();
/**
- * Sets the determined location of the shader attribute
- * This is usually done within ShaderState.
+ * Sets the given location of the shader attribute
*
+ * @return the given location
* @see com.jogamp.opengl.util.glsl.ShaderState#vertexAttribPointer(GL2ES2, GLArrayData)
*/
- public void setLocation(int v);
+ public int setLocation(int v);
+
+ /**
+ * Retrieves the location of the shader attribute from the linked shader program.
+ * <p>
+ * No validation is performed within the implementation.
+ * </p>
+ * @param gl
+ * @param program
+ * @return &ge;0 denotes a valid attribute location as found and used in the given shader program.
+ * &lt;0 denotes an invalid location, i.e. not found or used in the given shader program.
+ */
+ public int setLocation(GL2ES2 gl, int program);
+
+ /**
+ * Binds the location of the shader attribute to the given location for the unlinked shader program.
+ * <p>
+ * No validation is performed within the implementation.
+ * </p>
+ * @param gl
+ * @param program
+ * @return the given location
+ */
+ public int setLocation(GL2ES2 gl, int program, int location);
/**
* Determines whether the data is server side (VBO) and enabled,
@@ -107,7 +150,7 @@ public interface GLArrayData {
*/
public int getVBOTarget();
-
+
/**
* The Buffer holding the data, may be null if a GPU buffer without client bound data
*/
@@ -136,7 +179,7 @@ public interface GLArrayData {
* In case the buffer's position is 0 (sealed, flipped), it's based on it's limit instead of it's position.
*/
public int getElementCount();
-
+
/**
* The currently used size in bytes.<br>
* In case the buffer's position is 0 (sealed, flipped), it's based on it's limit instead of it's position.
@@ -144,16 +187,21 @@ public interface GLArrayData {
public int getSizeInBytes();
/**
- * True, if GL shall normalize fixed point data while converting
- * them into float
+ * True, if GL shall normalize fixed point data while converting
+ * them into float.
+ * <p>
+ * Default behavior (of the fixed function pipeline) is <code>true</code>
+ * for fixed point data type and <code>false</code> for floating point data types.
+ * </p>
*/
public boolean getNormalized();
- /**
+ /**
* @return the byte offset between consecutive components
- */
+ */
public int getStride();
+ @Override
public String toString();
public void destroy(GL gl);
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
index 38f1746f9..bded88d20 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
@@ -40,33 +40,46 @@
package javax.media.opengl;
+import java.util.List;
+
+import javax.media.nativewindow.NativeSurface;
+
+import com.jogamp.common.util.locks.RecursiveLock;
+
import jogamp.opengl.Debug;
/** A higher-level abstraction than {@link GLDrawable} which supplies
an event based mechanism ({@link GLEventListener}) for performing
OpenGL rendering. A GLAutoDrawable automatically creates a primary
rendering context which is associated with the GLAutoDrawable for
- the lifetime of the object. This context has the {@link
- GLContext#setSynchronized synchronized} property enabled so that
- calls to {@link GLContext#makeCurrent makeCurrent} will block if
- the context is current on another thread. This allows the internal
- GLContext for the GLAutoDrawable to be used both by the event
- based rendering mechanism as well by end users directly.
+ the lifetime of the object.
+ <p>
+ Since the {@link GLContext} {@link GLContext#makeCurrent makeCurrent}
+ implementation is synchronized, i.e. blocks if the context
+ is current on another thread, the internal
+ {@link GLContext} for the GLAutoDrawable can be used for the event
+ based rendering mechanism and by end users directly.
+ </p>
+ <h5><a name="initialization">GLAutoDrawable Initialization</a></h5>
<p>
The implementation shall initialize itself as soon as possible,
- ie if the attached {@link javax.media.nativewindow.NativeSurface NativeSurface} becomes visible/realized.
- The following protocol shall be satisfied:
+ which is only possible <i>after</i> the attached {@link javax.media.nativewindow.NativeSurface NativeSurface} becomes visible and and is realized.<br>
+ The following initialization sequence should be implemented:
<ul>
<li> Create the {@link GLDrawable} with the requested {@link GLCapabilities}</li>
<li> Notify {@link GLDrawable} to validate the {@link GLCapabilities} by calling {@link GLDrawable#setRealized setRealized(true)}.</li>
<li> Create the new {@link GLContext}.</li>
<li> Initialize all OpenGL resources by calling {@link GLEventListener#init init(..)} for all
- registered {@link GLEventListener}s. This can be done immediatly, or with the followup {@link #display display(..)} call.</li>
+ registered {@link GLEventListener}s. This can be done immediately, or with the followup {@link #display display(..)} call.</li>
<li> Send a reshape event by calling {@link GLEventListener#reshape reshape(..)} for all
registered {@link GLEventListener}s. This shall be done after the {@link GLEventListener#init init(..)} calls.</li>
- </ul></P>
+ </ul>
+ Note: The last to {@link GLEventListener} actions shall be also performed, when {@link #addGLEventListener(GLEventListener) adding}
+ a new one to an already initialized {@link GLAutoDrawable}.
+ </p>
+ <h5><a name="reconfiguration">GLAutoDrawable Reconfiguration</a></h5>
<p>
- Another implementation detail is the drawable reconfiguration. One use case is where a window is being
+ Another implementation detail is the {@link GLDrawable} reconfiguration. One use case is where a window is being
dragged to another screen with a different pixel configuration, ie {@link GLCapabilities}. The implementation
shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.<br/>
For example, AWT's {@link java.awt.Canvas} 's {@link java.awt.Canvas#getGraphicsConfiguration getGraphicsConfiguration()}
@@ -103,14 +116,36 @@ import jogamp.opengl.Debug;
mentioned above, the <code>boolean</code> system property <code>jogl.screenchange.action</code> will control the
screen change action as follows:<br/>
<PRE>
- -Djogl.screenchange.action=false Disable the drawable reconfiguration (the default)
- -Djogl.screenchange.action=true Enable the drawable reconfiguration
+ -Djogl.screenchange.action=false Disable the {@link GLDrawable} reconfiguration (the default)
+ -Djogl.screenchange.action=true Enable the {@link GLDrawable} reconfiguration
</PRE>
</p>
+ <h5><a name="locking">GLAutoDrawable Locking</a></h5>
+ GLAutoDrawable implementations perform locking in the following order:
+ <ol>
+ <li> {@link #getUpstreamLock()}.{@link RecursiveLock#lock() lock()}</li>
+ <li> {@link #getNativeSurface()}.{@link NativeSurface#lockSurface() lockSurface()} </li>
+ </ol>
+ and releases the locks accordingly:
+ <ol>
+ <li> {@link #getNativeSurface()}.{@link NativeSurface#unlockSurface() unlockSurface()} </li>
+ <li> {@link #getUpstreamLock()}.{@link RecursiveLock#unlock() unlock()}</li>
+ </ol>
+ Above <i>locking order</i> is mandatory to guarantee
+ atomicity of operation and to avoid race-conditions.
+ A custom implementation or user applications requiring exclusive access
+ shall follow the <i>locking order</i>.
+ See:
+ <ul>
+ <li>{@link #getUpstreamLock()}</li>
+ <li>{@link #invoke(boolean, GLRunnable)}</li>
+ <li>{@link #invoke(boolean, List)}</li>
+ </ul>
+ </p>
*/
public interface GLAutoDrawable extends GLDrawable {
- /** Flag reflecting wheather the drawable reconfiguration will be issued in
- * case a screen device change occured, e.g. in a multihead environment,
+ /** Flag reflecting whether the {@link GLDrawable} reconfiguration will be issued in
+ * case a screen device change occurred, e.g. in a multihead environment,
* where you drag the window to another monitor. */
public static final boolean SCREEN_CHANGE_ACTION_ENABLED = Debug.getBooleanProperty("jogl.screenchange.action", true);
@@ -119,7 +154,7 @@ public interface GLAutoDrawable extends GLDrawable {
* otherwise return <code>this</code> instance.
*/
public GLDrawable getDelegatedDrawable();
-
+
/**
* Returns the context associated with this drawable. The returned
* context will be synchronized.
@@ -128,51 +163,56 @@ public interface GLAutoDrawable extends GLDrawable {
public GLContext getContext();
/**
- * Associate a new context to this drawable and also propagates the context/drawable switch by
- * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
- * <code>drawable</code> might be an inner GLDrawable instance if using a delegation pattern,
- * or this GLAutoDrawable instance.
- * <p>
- * If the old or new context was current on this thread, it is being released before switching the drawable.
- * The new context will be made current afterwards, if it was current before.
- * However the user shall take extra care that no other thread
- * attempts to make this context current.
- * </p>
- * <p>
- * Be aware that the old context is still bound to the drawable,
- * and that one context can only be bound to one drawable at one time!
- * </p>
- * <p>
- * In case you do not intend to use the old context anymore, i.e.
- * not assigning it to another drawable, it shall be
- * destroyed before setting the new context, i.e.:
- * <pre>
- GLContext oldCtx = glad.getContext();
- if(null != oldCtx) {
- oldCtx.destroy();
- }
- glad.setContext(newCtx);
- * </pre>
- * This is required, since a context must have a valid drawable at all times
- * and this API shall not restrict the user in any way.
- * </p>
- *
- * @param newCtx the new context
- * @return the replaced GLContext, maybe <code>null</code>
- *
+ * Associate the new context, <code>newtCtx</code>, to this auto-drawable.
+ * <p>
+ * Remarks:
+ * <ul>
+ * <li>The currently associated context will be destroyed if <code>destroyPrevCtx</code> is <code>true</code>,
+ * otherwise it will be disassociated from this auto-drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) setGLDrawable(null, true);} including {@link GL#glFinish() glFinish()}.</li>
+ * <li>The new context will be associated with this auto-drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.</li>
+ * <li>If the old context was current on this thread, it is being released after disassociating this auto-drawable.</li>
+ * <li>If the new context was current on this thread, it is being released before associating this auto-drawable
+ * and made current afterwards.</li>
+ * <li>Implementation may issue {@link #makeCurrent()} and {@link #release()} while drawable reassociation.</li>
+ * <li>The user shall take extra care of thread synchronization,
+ * i.e. lock the involved {@link GLAutoDrawable auto-drawable's}
+ * {@link GLAutoDrawable#getUpstreamLock() upstream-locks} and {@link GLAutoDrawable#getNativeSurface() surfaces}
+ * to avoid a race condition. See <a href="#locking">GLAutoDrawable Locking</a>.</li>
+ * </ul>
+ * </p>
+ *
+ * @param newCtx the new context, maybe <code>null</code> for dis-association.
+ * @param destroyPrevCtx if <code>true</code>, destroy the previous context if exists
+ * @return the previous GLContext, maybe <code>null</code>
+ *
* @see GLContext#setGLDrawable(GLDrawable, boolean)
* @see GLContext#setGLReadDrawable(GLDrawable)
- * @see jogamp.opengl.GLDrawableHelper#switchContext(GLDrawable, GLContext, GLContext, int)
+ * @see jogamp.opengl.GLDrawableHelper#switchContext(GLDrawable, GLContext, boolean, GLContext, int)
+ */
+ public GLContext setContext(GLContext newCtx, boolean destroyPrevCtx);
+
+ /**
+ * Adds the given {@link GLEventListener listener} to the end of this drawable queue.
+ * The {@link GLEventListener listeners} are notified of events in the order of the queue.
+ * <p>
+ * The newly added listener's {@link GLEventListener#init(GLAutoDrawable) init(..)}
+ * method will be called once before any other of it's callback methods.
+ * See {@link #getGLEventListenerInitState(GLEventListener)} for details.
+ * </p>
+ * @param listener The GLEventListener object to be inserted
*/
- public GLContext setContext(GLContext newCtx);
-
- /** Adds a {@link GLEventListener} to the end of this drawable queue.
- The listeners are notified of events in the order of the queue. */
public void addGLEventListener(GLEventListener listener);
/**
- * Adds a {@link GLEventListener} at the given index of this drawable queue.
- * The listeners are notified of events in the order of the queue.
+ * Adds the given {@link GLEventListener listener} at the given index of this drawable queue.
+ * The {@link GLEventListener listeners} are notified of events in the order of the queue.
+ * <p>
+ * The newly added listener's {@link GLEventListener#init(GLAutoDrawable) init(..)}
+ * method will be called once before any other of it's callback methods.
+ * See {@link #getGLEventListenerInitState(GLEventListener)} for details.
+ * </p>
* @param index Position where the listener will be inserted.
* Should be within (0 <= index && index <= size()).
* An index value of -1 is interpreted as the end of the list, size().
@@ -181,44 +221,140 @@ public interface GLAutoDrawable extends GLDrawable {
*/
public void addGLEventListener(int index, GLEventListener listener) throws IndexOutOfBoundsException;
- /**
- * Removes a {@link GLEventListener} from this drawable.
- * Note that if this is done from within a particular drawable's
- * {@link GLEventListener} handler (reshape, display, etc.) that it is not
- * guaranteed that all other listeners will be evaluated properly
- * during this update cycle.
- * @param listener The GLEventListener object to be removed
- */
- public void removeGLEventListener(GLEventListener listener);
+ /**
+ * Returns the number of {@link GLEventListener} of this drawable queue.
+ * @return The number of GLEventListener objects of this drawable queue.
+ */
+ public int getGLEventListenerCount();
- /**
- * Removes a {@link GLEventListener} at the given index from this drawable.
- * Note that if this is done from within a particular drawable's
- * {@link GLEventListener} handler (reshape, display, etc.) that it is not
- * guaranteed that all other listeners will be evaluated properly
- * during this update cycle.
- * @param index Position of the listener to be removed.
+ /**
+ * Returns true if all added {@link GLEventListener} are initialized, otherwise false.
+ * @since 2.2
+ */
+ boolean areAllGLEventListenerInitialized();
+
+ /**
+ * Returns the {@link GLEventListener} at the given index of this drawable queue.
+ * @param index Position of the listener to be returned.
* Should be within (0 <= index && index < size()).
* An index value of -1 is interpreted as last listener, size()-1.
- * @return The removed GLEventListener object
+ * @return The GLEventListener object at the given index.
* @throws IndexOutOfBoundsException If the index is not within (0 <= index && index < size()), or -1
- */
- public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException;
+ */
+ public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException;
+
+ /**
+ * Retrieves whether the given {@link GLEventListener listener} is initialized or not.
+ * <p>
+ * After {@link #addGLEventListener(GLEventListener) adding} a {@link GLEventListener} it is
+ * marked <i>uninitialized</i> and added to a list of to be initialized {@link GLEventListener}.
+ * If such <i>uninitialized</i> {@link GLEventListener}'s handler methods (reshape, display)
+ * are about to be invoked, it's {@link GLEventListener#init(GLAutoDrawable) init(..)} method is invoked first.
+ * Afterwards the {@link GLEventListener} is marked <i>initialized</i>
+ * and removed from the list of to be initialized {@link GLEventListener}.
+ * </p>
+ * <p>
+ * This methods returns the {@link GLEventListener} initialized state,
+ * i.e. returns <code>false</code> if it is included in the list of to be initialized {@link GLEventListener},
+ * otherwise <code>true</code>.
+ * </p>
+ * @param listener the GLEventListener object to query it's initialized state.
+ */
+ public boolean getGLEventListenerInitState(GLEventListener listener);
+
+ /**
+ * Sets the given {@link GLEventListener listener's} initialized state.
+ * <p>
+ * This methods allows manually setting the {@link GLEventListener} initialized state,
+ * i.e. adding it to, or removing it from the list of to be initialized {@link GLEventListener}.
+ * See {@link #getGLEventListenerInitState(GLEventListener)} for details.
+ * </p>
+ * <p>
+ * <b>Warning:</b> This method does not validate whether the given {@link GLEventListener listener's}
+ * is member of this drawable queue, i.e. {@link #addGLEventListener(GLEventListener) added}.
+ * </p>
+ * <p>
+ * This method is only exposed to allow users full control over the {@link GLEventListener}'s state
+ * and is usually not recommended to change.
+ * </p>
+ * <p>
+ * One use case is moving a {@link GLContext} and their initialized {@link GLEventListener}
+ * from one {@link GLAutoDrawable} to another,
+ * where a subsequent {@link GLEventListener#init(GLAutoDrawable) init(..)} call after adding it
+ * to the new owner is neither required nor desired.
+ * See {@link com.jogamp.opengl.util.GLDrawableUtil#swapGLContextAndAllGLEventListener(GLAutoDrawable, GLAutoDrawable) swapGLContextAndAllGLEventListener(..)}.
+ * </p>
+ * @param listener the GLEventListener object to perform a state change.
+ * @param initialized if <code>true</code>, mark the listener initialized, otherwise uninitialized.
+ */
+ public void setGLEventListenerInitState(GLEventListener listener, boolean initialized);
+
+ /**
+ * Disposes the given {@link GLEventListener listener} via {@link GLEventListener#dispose(GLAutoDrawable) dispose(..)}
+ * if it has been initialized and added to this queue.
+ * <p>
+ * If <code>remove</code> is <code>true</code>, the {@link GLEventListener} is removed from this drawable queue before disposal,
+ * otherwise marked uninitialized.
+ * </p>
+ * <p>
+ * If an {@link GLAnimatorControl} is being attached and the current thread is different
+ * than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+ * </p>
+ * <p>
+ * Note that this is an expensive operation, since {@link GLEventListener#dispose(GLAutoDrawable) dispose(..)}
+ * is decorated by {@link GLContext#makeCurrent()} and {@link GLContext#release()}.
+ * </p>
+ * <p>
+ * Use {@link #removeGLEventListener(GLEventListener) removeGLEventListener(listener)} instead
+ * if you just want to remove the {@link GLEventListener listener} and <i>don't care</i> about the disposal of the it's (OpenGL) resources.
+ * </p>
+ * <p>
+ * Also note that this is done from within a particular drawable's
+ * {@link GLEventListener} handler (reshape, display, etc.), that it is not
+ * guaranteed that all other listeners will be evaluated properly
+ * during this update cycle.
+ * </p>
+ * @param listener The GLEventListener object to be disposed and removed if <code>remove</code> is <code>true</code>
+ * @param remove pass <code>true</code> to have the <code>listener</code> removed from this drawable queue, otherwise pass <code>false</code>
+ * @return the disposed and/or removed GLEventListener, or null if no action was performed, i.e. listener was not added
+ */
+ public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove);
/**
+ * Removes the given {@link GLEventListener listener} from this drawable queue.
+ * <p>
+ * This is an inexpensive operation, since the removed listener's
+ * {@link GLEventListener#dispose(GLAutoDrawable) dispose(..)} method will <i>not</i> be called.
+ * </p>
* <p>
+ * Use {@link #disposeGLEventListener(GLEventListener, boolean) disposeGLEventListener(listener, true)}
+ * instead to ensure disposal of the {@link GLEventListener listener}'s (OpenGL) resources.
+ * </p>
+ * <p>
+ * Note that if this is done from within a particular drawable's
+ * {@link GLEventListener} handler (reshape, display, etc.), that it is not
+ * guaranteed that all other listeners will be evaluated properly
+ * during this update cycle.
+ * </p>
+ * @param listener The GLEventListener object to be removed
+ * @return the removed GLEventListener, or null if listener was not added
+ */
+ public GLEventListener removeGLEventListener(GLEventListener listener);
+
+ /**
* Registers the usage of an animator, an {@link javax.media.opengl.GLAnimatorControl} implementation.
- * The animator will be queried whether it's animating, ie periodically issuing {@link #display()} calls or not.</p><br>
+ * The animator will be queried whether it's animating, ie periodically issuing {@link #display()} calls or not.
* <p>
* This method shall be called by an animator implementation only,<br>
* e.g. {@link com.jogamp.opengl.util.Animator#add(javax.media.opengl.GLAutoDrawable)}, passing it's control implementation,<br>
- * and {@link com.jogamp.opengl.util.Animator#remove(javax.media.opengl.GLAutoDrawable)}, passing <code>null</code>.</p><br>
+ * and {@link com.jogamp.opengl.util.Animator#remove(javax.media.opengl.GLAutoDrawable)}, passing <code>null</code>.
+ * </p>
* <p>
* Impacts {@link #display()} and {@link #invoke(boolean, GLRunnable)} semantics.</p><br>
*
- * @param animator <code>null</code> reference indicates no animator is using
- * this <code>GLAutoDrawable</code>,<br>
- * a valid reference indicates an animator is using this <code>GLAutoDrawable</code>.
+ * @param animatorControl <code>null</code> reference indicates no animator is using
+ * this <code>GLAutoDrawable</code>,<br>
+ * a valid reference indicates an animator is using this <code>GLAutoDrawable</code>.
*
* @throws GLException if an animator is already registered.
* @see #display()
@@ -236,27 +372,66 @@ public interface GLAutoDrawable extends GLDrawable {
public GLAnimatorControl getAnimator();
/**
+ * Dedicates this instance's {@link GLContext} to the given thread.<br/>
+ * The thread will exclusively claim the {@link GLContext} via {@link #display()} and not release it
+ * until {@link #destroy()} or <code>setExclusiveContextThread(null)</code> has been called.
+ * <p>
+ * Default non-exclusive behavior is <i>requested</i> via <code>setExclusiveContextThread(null)</code>,
+ * which will cause the next call of {@link #display()} on the exclusive thread to
+ * release the {@link GLContext}. Only after it's async release, {@link #getExclusiveContextThread()}
+ * will return <code>null</code>.
+ * </p>
+ * <p>
+ * To release a previous made exclusive thread, a user issues <code>setExclusiveContextThread(null)</code>
+ * and may poll {@link #getExclusiveContextThread()} until it returns <code>null</code>,
+ * <i>while</i> the exclusive thread is still running.
+ * </p>
+ * <p>
+ * Note: Setting a new exclusive thread without properly releasing a previous one
+ * will throw an GLException.
+ * </p>
* <p>
+ * Note: Utilizing this feature w/ AWT could lead to an AWT-EDT deadlock, depending on the AWT implementation.
+ * Hence it is advised not to use it with native AWT GLAutoDrawable like GLCanvas.
+ * </p>
+ * <p>
+ * One scenario could be to dedicate the context to the {@link GLAnimatorControl#getThread() animator thread}
+ * and spare redundant context switches, see {@link com.jogamp.opengl.util.AnimatorBase#setExclusiveContext(boolean)}.
+ * </p>
+ * @param t the exclusive thread to claim the context, or <code>null</code> for default operation.
+ * @return previous exclusive context thread
+ * @throws GLException If an exclusive thread is still active but a new one is attempted to be set
+ * @see com.jogamp.opengl.util.AnimatorBase#setExclusiveContext(boolean)
+ */
+ public Thread setExclusiveContextThread(Thread t) throws GLException;
+
+ /**
+ * @see #setExclusiveContextThread(Thread)
+ */
+ public Thread getExclusiveContextThread();
+
+ /**
* Enqueues a one-shot {@link GLRunnable},
* which will be executed within the next {@link #display()} call
* after all registered {@link GLEventListener}s
* {@link GLEventListener#display(GLAutoDrawable) display(GLAutoDrawable)}
- * methods has been called.
- * </p>
+ * methods have been called.
* <p>
* If no {@link GLAnimatorControl} is animating (default),<br>
* or if the current thread is the animator thread,<br>
- * a {@link #display()} call is issued after enqueue the <code>GLRunnable</code>.<br>
- * No extra synchronization is performed in case <code>wait</code> is true, since it is executed in the current thread.</p>
+ * a {@link #display()} call is issued after enqueue the <code>GLRunnable</code>,
+ * hence the {@link GLRunnable} will be executed right away.<br/>
+ * </p>
* <p>
- * If an {@link GLAnimatorControl} is animating,<br>
- * no {@link #display()} call is issued, since the animator thread performs it.<br>
+ * If an {@link GLAnimatorControl animator} is running,<br>
+ * no explicit {@link #display()} call is issued, allowing the {@link GLAnimatorControl animator} to perform at due time.<br>
* </p>
* <p>
* If <code>wait</code> is <code>true</code> the call blocks until the <code>glRunnable</code>
- * has been executed.<p>
+ * has been executed by the {@link GLAnimatorControl animator}, otherwise the method returns immediately.
+ * </p>
* <p>
- * If <code>wait</code> is <code>true</code> <b>and</b>
+ * If <code>wait</code> is <code>true</code> <b>and</b>
* {@link #isRealized()} returns <code>false</code> <i>or</i> {@link #getContext()} returns <code>null</code>,
* the call is ignored and returns <code>false</code>.<br>
* This helps avoiding deadlocking the caller.
@@ -265,16 +440,52 @@ public interface GLAutoDrawable extends GLDrawable {
* The internal queue of {@link GLRunnable}'s is being flushed with {@link #destroy()}
* where all blocked callers are being notified.
* </p>
+ * <p>
+ * To avoid a deadlock situation which causes an {@link IllegalStateException} one should
+ * avoid issuing {@link #invoke(boolean, GLRunnable) invoke} while this <a href="#locking">GLAutoDrawable is being locked</a>.<br>
+ * Detected deadlock situations throwing an {@link IllegalStateException} are:
+ * <ul>
+ * <li>{@link #getAnimator() Animator} is running on another thread and waiting and is locked on current thread, but is not {@link #isThreadGLCapable() GL-Thread}</li>
+ * <li>No {@link #getAnimator() Animator} is running on another thread and is locked on current thread, but is not {@link #isThreadGLCapable() GL-Thread}</li>
+ * </ul>
+ * </p>
*
- * @param wait if <code>true</code> block until execution of <code>glRunnable</code> is finished, otherwise return immediatly w/o waiting
+ * @param wait if <code>true</code> block until execution of <code>glRunnable</code> is finished, otherwise return immediately w/o waiting
* @param glRunnable the {@link GLRunnable} to execute within {@link #display()}
* @return <code>true</code> if the {@link GLRunnable} has been processed or queued, otherwise <code>false</code>.
- *
+ * @throws IllegalStateException in case of a detected deadlock situation ahead, see above.
+ *
* @see #setAnimator(GLAnimatorControl)
* @see #display()
* @see GLRunnable
+ * @see #invoke(boolean, List)
+ * @see #flushGLRunnables()
*/
- public boolean invoke(boolean wait, GLRunnable glRunnable);
+ public boolean invoke(boolean wait, GLRunnable glRunnable) throws IllegalStateException ;
+
+ /**
+ * Extends {@link #invoke(boolean, GLRunnable)} functionality
+ * allowing to inject a list of {@link GLRunnable}s.
+ * @param wait if <code>true</code> block until execution of the last <code>glRunnable</code> is finished, otherwise return immediately w/o waiting
+ * @param glRunnables the {@link GLRunnable}s to execute within {@link #display()}
+ * @return <code>true</code> if the {@link GLRunnable}s has been processed or queued, otherwise <code>false</code>.
+ * @throws IllegalStateException in case of a detected deadlock situation ahead, see {@link #invoke(boolean, GLRunnable)}.
+ * @see #invoke(boolean, GLRunnable)
+ * @see #flushGLRunnables()
+ */
+ public boolean invoke(boolean wait, List<GLRunnable> glRunnables) throws IllegalStateException;
+
+ /**
+ * Flushes all {@link #invoke(boolean, GLRunnable) enqueued} {@link GLRunnable} of this {@link GLAutoDrawable}
+ * including notifying waiting executor.
+ * <p>
+ * The executor which might have been blocked until notified
+ * will be unblocked and all tasks removed from the queue.
+ * </p>
+ * @see #invoke(boolean, GLRunnable)
+ * @since 2.2
+ */
+ public void flushGLRunnables();
/** Destroys all resources associated with this GLAutoDrawable,
inclusive the GLContext.
@@ -348,16 +559,16 @@ public interface GLAutoDrawable extends GLDrawable {
* <p>
* This GLAutoDrawable implementation holds it's own GLContext reference,
* thus created a GLContext using this methods won't replace it implicitly.
- * To replace or set this GLAutoDrawable's GLContext you need to call {@link #setContext(GLContext)}.
+ * To replace or set this GLAutoDrawable's GLContext you need to call {@link #setContext(GLContext, boolean)}.
* </p>
* <p>
- * The GLAutoDrawable implementation shall also set the
- * context creation flags as customized w/ {@link #setContextCreationFlags(int)}.
+ * The GLAutoDrawable implementation shall also set the
+ * context creation flags as customized w/ {@link #setContextCreationFlags(int)}.
* </p>
*/
@Override
public GLContext createContext(GLContext shareWith);
-
+
/** Returns the {@link GL} pipeline object this GLAutoDrawable uses.
If this method is called outside of the {@link
GLEventListener}'s callback methods (init, display, etc.) it may
@@ -376,13 +587,13 @@ public interface GLAutoDrawable extends GLDrawable {
demos for examples.
@return the set GL pipeline or null if not successful */
public GL setGL(GL gl);
-
+
/**
* Method <i>may</i> return the upstream UI toolkit object
* holding this {@link GLAutoDrawable} instance, if exist.
* <p>
* Currently known Java UI toolkits and it's known return types are:
- *
+ *
* <table border="1">
* <tr><td>Toolkit</td> <td>GLAutoDrawable Implementation</td> <td>~</td> <td>Return Type of getUpstreamWidget()</td</tr>
* <tr><td>NEWT</td> <td>{@link com.jogamp.newt.opengl.GLWindow}</td> <td>has a</td> <td>{@link com.jogamp.newt.Window}</td</tr>
@@ -390,15 +601,36 @@ public interface GLAutoDrawable extends GLDrawable {
* <tr><td>AWT</td> <td>{@link javax.media.opengl.awt.GLCanvas}</td> <td>is a</td> <td>{@link java.awt.Canvas}</td</tr>
* <tr><td>AWT</td> <td>{@link javax.media.opengl.awt.GLJPanel}</td> <td>is a</td> <td>{@link javax.swing.JPanel}</td</tr>
* </table>
- * However, the result may be other object types than the listed above
+ * However, the result may be other object types than the listed above
* due to new supported toolkits.
* </p>
* <p>
* This method may also return <code>null</code> if no UI toolkit is being used,
* as common for offscreen rendering.
* </p>
- * @return
*/
public Object getUpstreamWidget();
+ /**
+ * Returns the recursive lock object of the {@link #getUpstreamWidget() upstream widget}
+ * to synchronize multithreaded access on top of {@link NativeSurface#lockSurface()}.
+ * <p>
+ * See <a href="#locking">GLAutoDrawable Locking</a>.
+ * </p>
+ * @since 2.2
+ */
+ public RecursiveLock getUpstreamLock();
+
+ /**
+ * Indicates whether the current thread is capable of
+ * performing OpenGL-related work.
+ * <p>
+ * Implementation utilizes this knowledge to determine
+ * whether {@link #display()} performs the OpenGL commands on the current thread directly
+ * or spawns them on the dedicated OpenGL thread.
+ * </p>
+ * @since 2.2
+ */
+ public boolean isThreadGLCapable();
+
}
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index 9bcee819a..48455c525 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -32,7 +32,7 @@ package javax.media.opengl;
/**
* <P>The base interface from which all GL profiles derive, providing
* checked conversion down to concrete profiles, access to the
- * OpenGL context associated with the GL and extension/function
+ * OpenGL context associated with the GL and extension/function
* availability queries as described below.</P>
*
* <P> While the APIs for vendor extensions are unconditionally
@@ -79,7 +79,7 @@ package javax.media.opengl;
*
*/
public interface GLBase {
-
+
/**
* Indicates whether this GL object conforms to any of the OpenGL profiles.
*/
@@ -88,142 +88,262 @@ public interface GLBase {
/**
* Indicates whether this GL object conforms to the OpenGL &ge; 4.0 compatibility profile.
* The GL4 compatibility profile includes the GL2, GL2ES1, GL2ES2, GL3, GL3bc and GL4 profile.
+ * @see GLContext#isGL4bc()
*/
public boolean isGL4bc();
/**
* Indicates whether this GL object conforms to the OpenGL &ge; 4.0 core profile.
* The GL4 core profile includes the GL2ES2, and GL3 profile.
+ * @see GLContext#isGL4()
*/
public boolean isGL4();
/**
* Indicates whether this GL object conforms to the OpenGL &ge; 3.1 compatibility profile.
* The GL3 compatibility profile includes the GL2, GL2ES1, GL2ES2 and GL3 profile.
+ * @see GLContext#isGL3bc()
*/
public boolean isGL3bc();
/**
* Indicates whether this GL object conforms to the OpenGL &ge; 3.1 core profile.
* The GL3 core profile includes the GL2ES2 profile.
+ * @see GLContext#isGL3()
*/
public boolean isGL3();
/**
* Indicates whether this GL object conforms to the OpenGL &le; 3.0 profile.
* The GL2 profile includes the GL2ES1 and GL2ES2 profile.
+ * @see GLContext#isGL2()
*/
public boolean isGL2();
/**
- * Indicates whether this GL object conforms to the OpenGL ES1 &ge; 1.0 profile.
+ * Indicates whether this GL object conforms to the OpenGL ES &ge; 1.0 profile.
+ * @see GLContext#isGLES1()
*/
public boolean isGLES1();
/**
- * Indicates whether this GL object conforms to the OpenGL ES2 &ge; 2.0 profile.
+ * Indicates whether this GL object conforms to the OpenGL ES &ge; 2.0 profile.
* <p>
* Remark: ES2 compatible desktop profiles are not included.
* To query whether core ES2 functionality is provided, use {@link #isGLES2Compatible()}.
- * </p>
+ * </p>
* @see #isGLES2Compatible()
+ * @see GLContext#isGLES2()
*/
public boolean isGLES2();
/**
+ * Indicates whether this GL object conforms to the OpenGL ES &ge; 3.0 profile.
+ * <p>
+ * Remark: ES3 compatible desktop profiles are not included.
+ * To query whether core ES3 functionality is provided, use {@link #isGLES3Compatible()}.
+ * </p>
+ * @see #isGLES3Compatible()
+ * @see GLContext#isGLES3()
+ */
+ public boolean isGLES3();
+
+ /**
* Indicates whether this GL object conforms to one of the OpenGL ES profiles,
- * see {@link #isGLES1()} and {@link #isGLES2()}.
+ * see {@link #isGLES1()}, {@link #isGLES2()} and {@link #isGLES3()}.
+ * @see GLContext#isGLES()
*/
public boolean isGLES();
/**
* Indicates whether this GL object conforms to a GL2ES1 compatible profile.
+ * @see GLContext#isGL2ES1()
*/
public boolean isGL2ES1();
/**
* Indicates whether this GL object conforms to a GL2ES2 compatible profile.
+ * @see GLContext#isGL2ES2()
*/
public boolean isGL2ES2();
/**
- * Indicates whether this GL object is compatible with the core OpenGL ES2 functionality.
- * @return true if this context is an ES2 context or implements
- * the extension <code>GL_ARB_ES2_compatibility</code>, otherwise false
+ * Indicates whether this GL object conforms to a either a GL2GL3 or GL3ES3 compatible profile.
+ * @see GLContext#isGL2ES3()
*/
- public boolean isGLES2Compatible();
+ public boolean isGL2ES3();
+
+ /**
+ * Indicates whether this GL object conforms to a GL3ES3 compatible profile.
+ * @see GLContext#isGL3ES3()
+ */
+ public boolean isGL3ES3();
+
+ /**
+ * Returns true if this GL object conforms to a GL4ES3 compatible profile, i.e. if {@link #isGLES3Compatible()} returns true.
+ * <p>Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]</p>
+ * @see GLContext#isGL4ES3()
+ */
+ public boolean isGL4ES3();
/**
* Indicates whether this GL object conforms to a GL2GL3 compatible profile.
+ * @see GLContext#isGL2GL3()
*/
public boolean isGL2GL3();
- /** Indicates whether this GL object supports GLSL. */
+ /**
+ * Indicates whether this GL object uses a GL4 core profile. <p>Includes [ GL4 ].</p>
+ * @see GLContext#isGL4core()
+ */
+ public boolean isGL4core();
+
+ /**
+ * Indicates whether this GL object uses a GL3 core profile. <p>Includes [ GL4, GL3 ].</p>
+ * @see GLContext#isGL3core()
+ */
+ public boolean isGL3core();
+
+ /**
+ * Indicates whether this GL object uses a GL core profile. <p>Includes [ GL4, GL3, GLES3, GL2ES2 ].</p>
+ * @see GLContext#isGLcore()
+ */
+ public boolean isGLcore();
+
+ /**
+ * Indicates whether this GL object is compatible with the core OpenGL ES2 functionality.
+ * @return true if this context is an ES2 context or implements
+ * the extension <code>GL_ARB_ES2_compatibility</code>, otherwise false
+ * @see GLContext#isGLES2Compatible()
+ */
+ public boolean isGLES2Compatible();
+
+ /**
+ * Indicates whether this GL object is compatible with the core OpenGL ES3 functionality.
+ * <p>
+ * Return true if the underlying context is an ES3 context or implements
+ * the extension <code>GL_ARB_ES3_compatibility</code>, otherwise false.
+ * </p>
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ * @see GLContext#isGLES3Compatible()
+ */
+ public boolean isGLES3Compatible();
+
+ /**
+ * Indicates whether this GL object supports GLSL.
+ * @see GLContext#hasGLSL()
+ */
public boolean hasGLSL();
/**
+ * Returns the downstream GL instance in case this is a wrapping pipeline, otherwise <code>null</code>.
+ * <p>
+ * See {@link #getRootGL()} for retrieving the implementing root instance.
+ * </p>
+ * @throws GLException if the downstream instance is not null and not a GL implementation
+ * @see #getRootGL()
+ */
+ public GL getDownstreamGL() throws GLException;
+
+ /**
+ * Returns the implementing root instance, considering a wrapped pipelined hierarchy, see {@link #getDownstreamGL()}.
+ * <p>
+ * If this instance is not a wrapping pipeline, i.e. has no downstream instance,
+ * this instance is returned.
+ * </p>
+ * @throws GLException if the root instance is not a GL implementation
+ */
+ public GL getRootGL() throws GLException;
+
+ /**
* Casts this object to the GL interface.
- * @throws GLException if this GLObject is not a GL implementation
+ * @throws GLException if this object is not a GL implementation
*/
public GL getGL() throws GLException;
/**
* Casts this object to the GL4bc interface.
- * @throws GLException if this GLObject is not a GL4bc implementation
+ * @throws GLException if this object is not a GL4bc implementation
*/
public GL4bc getGL4bc() throws GLException;
/**
* Casts this object to the GL4 interface.
- * @throws GLException if this GLObject is not a GL4 implementation
+ * @throws GLException if this object is not a GL4 implementation
*/
public GL4 getGL4() throws GLException;
/**
* Casts this object to the GL3bc interface.
- * @throws GLException if this GLObject is not a GL3bc implementation
+ * @throws GLException if this object is not a GL3bc implementation
*/
public GL3bc getGL3bc() throws GLException;
/**
* Casts this object to the GL3 interface.
- * @throws GLException if this GLObject is not a GL3 implementation
+ * @throws GLException if this object is not a GL3 implementation
*/
public GL3 getGL3() throws GLException;
/**
* Casts this object to the GL2 interface.
- * @throws GLException if this GLObject is not a GL2 implementation
+ * @throws GLException if this object is not a GL2 implementation
*/
public GL2 getGL2() throws GLException;
/**
* Casts this object to the GLES1 interface.
- * @throws GLException if this GLObject is not a GLES1 implementation
+ * @throws GLException if this object is not a GLES1 implementation
*/
public GLES1 getGLES1() throws GLException;
/**
* Casts this object to the GLES2 interface.
- * @throws GLException if this GLObject is not a GLES2 implementation
+ * @throws GLException if this object is not a GLES2 implementation
*/
public GLES2 getGLES2() throws GLException;
/**
+ * Casts this object to the GLES3 interface.
+ * @throws GLException if this object is not a GLES3 implementation
+ */
+ public GLES3 getGLES3() throws GLException;
+
+ /**
* Casts this object to the GL2ES1 interface.
- * @throws GLException if this GLObject is not a GL2ES1 implementation
+ * @throws GLException if this object is not a GL2ES1 implementation
*/
public GL2ES1 getGL2ES1() throws GLException;
/**
* Casts this object to the GL2ES2 interface.
- * @throws GLException if this GLObject is not a GL2ES2 implementation
+ * @throws GLException if this object is not a GL2ES2 implementation
*/
public GL2ES2 getGL2ES2() throws GLException;
/**
+ * Casts this object to the GL2ES3 interface.
+ * @throws GLException if this object is not a GL2ES3 implementation
+ */
+ public GL2ES3 getGL2ES3() throws GLException;
+
+ /**
+ * Casts this object to the GL3ES3 interface.
+ * @throws GLException if this object is not a GL3ES3 implementation
+ */
+ public GL3ES3 getGL3ES3() throws GLException;
+
+ /**
+ * Casts this object to the GL4ES3 interface.
+ * @throws GLException if this object is not a GL4ES3 implementation
+ */
+ public GL4ES3 getGL4ES3() throws GLException;
+
+ /**
* Casts this object to the GL2GL3 interface.
- * @throws GLException if this GLObject is not a GL2GL3 implementation
+ * @throws GLException if this object is not a GL2GL3 implementation
*/
public GL2GL3 getGL2GL3() throws GLException;
@@ -240,14 +360,14 @@ public interface GLBase {
/**
* Returns true if the specified OpenGL core- or extension-function can be
* used successfully through this GL instance given the current host (OpenGL
- * <i>client</i>) and display (OpenGL <i>server</i>) configuration.<P>
- * By "successfully" we mean that the function is both <i>callable</i>
- * on the machine running the program and <i>available</i> on the current
- * display.<P>
+ * <i>client</i>) and display (OpenGL <i>server</i>) configuration.<P>
+ * By "successfully" we mean that the function is both <i>callable</i>
+ * on the machine running the program and <i>available</i> on the current
+ * display.<P>
*
* In order to call a function successfully, the function must be both
- * <i>callable</i> on the machine running the program and <i>available</i> on
- * the display device that is rendering the output (note: on non-networked,
+ * <i>callable</i> on the machine running the program and <i>available</i> on
+ * the display device that is rendering the output (note: on non-networked,
* single-display machines these two conditions are identical; on networked and/or
* multi-display machines this becomes more complicated). These conditions are
* met if the function is either part of the core OpenGL version supported by
@@ -256,7 +376,7 @@ public interface GLBase {
*
* A GL function is <i>callable</i> if it is successfully linked at runtime,
* hence the GLContext must be made current at least once.
- *
+ *
* @param glFunctionName the name of the OpenGL function (e.g., use
* "glBindRenderbufferEXT" or "glBindRenderbuffer" to check if {@link
* GL#glBindRenderbuffer(int,int)} is available).
@@ -266,17 +386,17 @@ public interface GLBase {
/**
* Returns true if the specified OpenGL extension can be
* used successfully through this GL instance given the current host (OpenGL
- * <i>client</i>) and display (OpenGL <i>server</i>) configuration.<P>
+ * <i>client</i>) and display (OpenGL <i>server</i>) configuration.<P>
*
* @param glExtensionName the name of the OpenGL extension (e.g.,
* "GL_ARB_vertex_program").
*/
public boolean isExtensionAvailable(String glExtensionName);
- /**
+ /**
* Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>.
* <p>
- * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= 3.0 [core, compat] or implements the extensions
* <code>GL_ARB_ES2_compatibility</code>, <code>GL_ARB_framebuffer_object</code>, <code>GL_EXT_framebuffer_object</code> or <code>GL_OES_framebuffer_object</code>.
* </p>
* <p>
@@ -287,12 +407,12 @@ public interface GLBase {
*/
public boolean hasBasicFBOSupport();
- /**
+ /**
* Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>.
* <p>
- * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+ * Full FBO is supported if the context is either GL >= core 3.0 [ES, core, compat] or implements the extensions
* <code>ARB_framebuffer_object</code>, or all of
- * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>,
+ * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>,
* <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>.
* </p>
* <p>
@@ -304,7 +424,7 @@ public interface GLBase {
/**
* Returns the maximum number of FBO RENDERBUFFER samples
- * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false.
+ * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false.
* @see GLContext#getMaxRenderbufferSamples()
*/
public int getMaxRenderbufferSamples();
@@ -316,12 +436,11 @@ public interface GLBase {
* NPOT textures are supported in OpenGL >= 3, GLES2 or if the
* 'GL_ARB_texture_non_power_of_two' extension is available.
* </p>
- * @return
*/
public boolean isNPOTTextureAvailable();
public boolean isTextureFormatBGRA8888Available();
-
+
/** Provides a platform-independent way to specify the minimum swap
interval for buffer swaps. An argument of 0 disables
sync-to-vertical-refresh completely, while an argument of 1
@@ -330,7 +449,7 @@ public interface GLBase {
is usually either 0 or 1. This function is not guaranteed to
have an effect, and in particular only affects heavyweight
onscreen components.
-
+
@see #getSwapInterval
@throws GLException if this context is not the current
*/
@@ -339,8 +458,8 @@ public interface GLBase {
/** Provides a platform-independent way to get the swap
interval set by {@link #setSwapInterval}. <br>
- If the interval is not set by {@link #setSwapInterval} yet,
- -1 is returned, indicating that the platforms default
+ If the interval is not set by {@link #setSwapInterval} yet,
+ -1 is returned, indicating that the platforms default
is being used.
@see #setSwapInterval
@@ -379,59 +498,137 @@ public interface GLBase {
*/
public Object getExtension(String extensionName);
- /** Aliased entrypoint of <code> void {@native glClearDepth}(GLclampd depth); </code> and <code> void {@native glClearDepthf}(GLclampf depth); </code>. */
+ /** Aliased entrypoint of <code> void {@native glClearDepth}(GLclampd depth); </code> and <code> void {@native glClearDepthf}(GLclampf depth); </code>. */
public void glClearDepth( double depth );
- /** Aliased entrypoint of <code> void {@native glDepthRange}(GLclampd depth); </code> and <code> void {@native glDepthRangef}(GLclampf depth); </code>. */
+ /** Aliased entrypoint of <code> void {@native glDepthRange}(GLclampd depth); </code> and <code> void {@native glDepthRangef}(GLclampf depth); </code>. */
public void glDepthRange(double zNear, double zFar);
/**
* @param target a GL buffer (VBO) target as used in {@link GL#glBindBuffer(int, int)}, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}, {@link GL#GL_ARRAY_BUFFER}, ..
- * @return the GL buffer (VBO) name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound.
+ * @return the GL buffer name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound.
+ * @see #getBufferStorage(int)
*/
- public int glGetBoundBuffer(int target);
+ public int getBoundBuffer(int target);
/**
- * @param buffer a GL buffer name, generated with {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} for example.
- * @return the size of the given GL buffer
+ * @param bufferName a GL buffer name, generated with e.g. {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)}.
+ * @return the size of the given GL buffer storage, see {@link GLBufferStorage}
+ * @see #getBoundBuffer(int)
*/
- public long glGetBufferSize(int buffer);
+ public GLBufferStorage getBufferStorage(int bufferName);
/**
- * @return true if a VBO is bound to {@link GL.GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ * Returns the {@link GLBufferStorage} instance as mapped via OpenGL's native {@link GL#glMapBuffer(int, int) glMapBuffer(..)} implementation.
+ * <p>
+ * Throws a {@link GLException} if GL-function constraints are not met.
+ * </p>
+ * <p>
+ * {@link GL#glMapBuffer(int, int)} wrapper calls this method and returns {@link GLBufferStorage#getMappedBuffer()}.
+ * </p>
+ * <p>
+ * A zero {@link GLBufferStorage#getSize()} will avoid a native call and returns the unmapped {@link GLBufferStorage}.
+ * </p>
+ * <p>
+ * A null native mapping result indicating an error will
+ * not cause a GLException but returns the unmapped {@link GLBufferStorage}.
+ * This allows the user to handle this case.
+ * </p>
+ * @param target denotes the buffer via it's bound target
+ * @param access the mapping access mode
+ * @throws GLException if buffer is not bound to target
+ * @throws GLException if buffer is not tracked
+ * @throws GLException if buffer is already mapped
+ * @throws GLException if buffer has invalid store size, i.e. less-than zero
*/
- public boolean glIsVBOArrayEnabled();
+ public GLBufferStorage mapBuffer(int target, int access) throws GLException;
/**
- * @return true if a VBO is bound to {@link GL.GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ * Returns the {@link GLBufferStorage} instance as mapped via OpenGL's native {@link GL#glMapBufferRange(int, long, long, int) glMapBufferRange(..)} implementation.
+ * <p>
+ * Throws a {@link GLException} if GL-function constraints are not met.
+ * </p>
+ * <p>
+ * {@link GL#glMapBufferRange(int, long, long, int)} wrapper calls this method and returns {@link GLBufferStorage#getMappedBuffer()}.
+ * </p>
+ * <p>
+ * A zero {@link GLBufferStorage#getSize()} will avoid a native call and returns the unmapped {@link GLBufferStorage}.
+ * </p>
+ * <p>
+ * A null native mapping result indicating an error will
+ * not cause a GLException but returns the unmapped {@link GLBufferStorage}.
+ * This allows the user to handle this case.
+ * </p>
+ * @param target denotes the buffer via it's bound target
+ * @param offset offset of the mapped buffer's storage
+ * @param length length of the mapped buffer's storage
+ * @param access the mapping access mode
+ * @throws GLException if buffer is not bound to target
+ * @throws GLException if buffer is not tracked
+ * @throws GLException if buffer is already mapped
+ * @throws GLException if buffer has invalid store size, i.e. less-than zero
+ * @throws GLException if buffer mapping range does not fit, incl. offset
+ */
+ public GLBufferStorage mapBufferRange(final int target, final long offset, final long length, final int access) throws GLException;
+
+ /**
+ * @return true if a VBO is bound to {@link GL#GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean isVBOArrayBound();
+
+ /**
+ * @return true if a VBO is bound to {@link GL#GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
*/
- public boolean glIsVBOElementArrayEnabled();
+ public boolean isVBOElementArrayBound();
- /**
- * Return the framebuffer name bound to this context,
+ /**
+ * Return the framebuffer name bound to this context,
* see {@link GL#glBindFramebuffer(int, int)}.
*/
public int getBoundFramebuffer(int target);
- /**
+ /**
* Return the default draw framebuffer name.
- * <p>
+ * <p>
* May differ from it's default <code>zero</code>
- * in case an framebuffer object ({@link FBObject}) based drawable
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
* is being used.
- * </p>
+ * </p>
*/
public int getDefaultDrawFramebuffer();
- /**
+ /**
* Return the default read framebuffer name.
- * <p>
+ * <p>
* May differ from it's default <code>zero</code>
- * in case an framebuffer object ({@link FBObject}) based drawable
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
* is being used.
- * </p>
+ * </p>
*/
public int getDefaultReadFramebuffer();
+ /**
+ * Returns the default color buffer within the current bound
+ * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER,
+ * which will be used as the source for pixel reading commands,
+ * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} etc.
+ * <p>
+ * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
+ * otherwise this is {@link GL#GL_FRONT} for single buffer configurations
+ * and {@link GL#GL_BACK} for double buffer configurations.
+ * </p>
+ * <p>
+ * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+ * and {@link GL#GL_BACK} is the default.
+ * </p>
+ * <p>
+ * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i
+ * </p>
+ * <p>
+ * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead}
+ * for read-pixels and swap-buffers implications.
+ * </p>
+ */
+ public int getDefaultReadBuffer();
}
diff --git a/src/jogl/classes/javax/media/opengl/GLBufferStorage.java b/src/jogl/classes/javax/media/opengl/GLBufferStorage.java
new file mode 100644
index 000000000..1101ed31b
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/GLBufferStorage.java
@@ -0,0 +1,160 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package javax.media.opengl;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+/**
+ * OpenGL buffer storage object reflecting it's
+ * <ul>
+ * <li>storage size</li>
+ * <li>storage memory if mapped</li>
+ * <li>mutable usage or immutable flags</li>
+ * </ul>
+ * <p>
+ * Buffer storage is created via:
+ * <ul>
+ * <li><code>glBufferStorage</code> - storage creation with target</li>
+ * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation with target</li>
+ * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li>
+ * </ul>
+ * Note that storage <i>recreation</i> as mentioned above also invalidate a previous storage instance,
+ * i.e. disposed the buffer's current storage if exist and attaches a new storage instance.
+ * </p>
+ * <p>
+ * Buffer storage is disposed via:
+ * <ul>
+ * <li>{@link GL#glDeleteBuffers(int, IntBuffer)} - explicit, direct, via {@link #notifyBuffersDeleted(int, IntBuffer)} or {@link #notifyBuffersDeleted(int, int[], int)}</li>
+ * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation via target</li>
+ * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li>
+ * </ul>
+ * </p>
+ * <p>
+ * GL buffer storage is mapped via
+ * <ul>
+ *
+ * <li>{@link GL#mapBuffer(int, int)}</li>
+ * <li>{@link GL#mapBufferRange(int, long, long, int)}</li>
+ * <li>{@link GL2#mapNamedBuffer(int, int)}</li>
+ * <li>{@link GL2#mapNamedBufferRange(int, long, long, int)}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * GL buffer storage is unmapped via
+ * <ul>
+ * <li>{@link GL#glUnmapBuffer(int)} - explicit via target</li>
+ * <li>{@link GL2#glUnmapNamedBufferEXT(int)} - explicit direct</li>
+ * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation via target</li>
+ * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li>
+ * <li>{@link GL#glDeleteBuffers(int, IntBuffer)} - buffer deletion</li>
+ * </ul>
+ * </p>
+ */
+public abstract class GLBufferStorage {
+ private final int name;
+ private /* final */ long size;
+ private /* final */ int mutableUsage;
+ private /* final */ int immutableFlags;
+ private ByteBuffer mappedBuffer;
+
+ protected GLBufferStorage(final int name, final long size, final int mutableUsage, final int immutableFlags) {
+ this.name = name;
+ this.size = size;
+ this.mutableUsage = mutableUsage;
+ this.immutableFlags = immutableFlags;
+ this.mappedBuffer = null;
+ }
+
+ protected void reset(final long size, final int mutableUsage, final int immutableFlags) {
+ this.size = size;
+ this.mutableUsage = mutableUsage;
+ this.immutableFlags = immutableFlags;
+ this.mappedBuffer = null;
+ }
+ protected void setMappedBuffer(final ByteBuffer buffer) {
+ this.mappedBuffer = buffer;
+ }
+
+ /** Return the buffer name */
+ public final int getName() { return name; }
+
+ /** Return the buffer's storage size. */
+ public final long getSize() { return size; }
+
+ /**
+ * Returns <code>true</code> if buffer's storage is mutable, i.e.
+ * created via {@link GL#glBufferData(int, long, java.nio.Buffer, int)}.
+ * <p>
+ * Returns <code>false</code> if buffer's storage is immutable, i.e.
+ * created via <code>glBufferStorage</code>. FIXME: Add GL 4.4 support!
+ * </p>
+ * @return
+ */
+ public final boolean isMutableStorage() { return 0 != mutableUsage; }
+
+ /**
+ * Returns the mutable storage usage or 0 if storage is not {@link #isMutableStorage() mutable}.
+ */
+ public final int getMutableUsage() { return mutableUsage; }
+
+ /**
+ * Returns the immutable storage flags, invalid if storage is {@link #isMutableStorage() mutable}.
+ */
+ public final int getImmutableFlags() { return immutableFlags; }
+
+ /**
+ * Returns the mapped ByteBuffer, or null if not mapped.
+ * Mapping may occur via:
+ * <ul>
+ * <li>{@link GL#glMapBuffer(int, int)}</li>
+ * <li>{@link GL#glMapBufferRange(int, long, long, int)}</li>
+ * <li>{@link GL2#glMapNamedBufferEXT(int, int)}</li>
+ * <li>{@link GL2#glMapNamedBufferRangeEXT(int, long, long, int)}
+ * </ul>
+ */
+ public final ByteBuffer getMappedBuffer() { return mappedBuffer; }
+
+ public final String toString() {
+ return toString(false);
+ }
+ public final String toString(final boolean skipMappedBuffer) {
+ final String s0;
+ if( isMutableStorage() ) {
+ s0 = String.format("%s[name %s, size %d, mutable usage 0x%X", msgClazzName, name, size, mutableUsage);
+ } else {
+ s0 = String.format("%s[name %s, size %d, immutable flags 0x%X", msgClazzName, name, size, immutableFlags);
+ }
+ if(skipMappedBuffer) {
+ return s0+"]";
+ } else {
+ return s0+", mapped "+mappedBuffer+"]";
+ }
+ }
+ private static final String msgClazzName = "GLBufferStorage";
+}
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java
index 9b004a0af..0d65d35cb 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilities.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java
@@ -50,7 +50,8 @@ import javax.media.nativewindow.CapabilitiesImmutable;
must support, such as the OpenGL profile, color depth and whether stereo is enabled.<br>
The actual capabilites of created {@link GLDrawable}s are then reflected by their own
- GLCapabilites instance, which can be queried with {@link GLDrawable#getGLCapabilities()}.<br>
+ GLCapabilites instance, which can be queried with {@link GLDrawable#getChosenGLCapabilities()}.
+ <br>
It currently contains the minimal number of routines which allow
configuration on all supported window systems. */
@@ -75,16 +76,11 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
private boolean sampleBuffers = false;
private int numSamples = 2;
- // Bits for pbuffer creation
- private boolean pbufferFloatingPointBuffers;
- private boolean pbufferRenderToTexture;
- private boolean pbufferRenderToTextureRectangle;
-
/** Creates a GLCapabilities object. All attributes are in a default state.
* @param glp GLProfile, or null for the default GLProfile
* @throws GLException if no profile is given and no default profile is available for the default device.
*/
- public GLCapabilities(GLProfile glp) throws GLException {
+ public GLCapabilities(final GLProfile glp) throws GLException {
glProfile = (null!=glp)?glp:GLProfile.getDefault(GLProfile.getDefaultDevice());
}
@@ -97,17 +93,17 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
public Object clone() {
try {
return super.clone();
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
throw new GLException(e);
}
}
/**
- * Copies all {@link GLCapabilities} and {@link Capabilities} values
+ * Copies all {@link GLCapabilitiesImmutable} values
* from <code>source</code> into this instance.
* @return this instance
*/
- public GLCapabilities copyFrom(GLCapabilitiesImmutable source) {
+ public GLCapabilities copyFrom(final GLCapabilitiesImmutable source) {
super.copyFrom(source);
glProfile = source.getGLProfile();
isPBuffer = source.isPBuffer();
@@ -122,18 +118,15 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
accumBlueBits = source.getAccumBlueBits();
accumAlphaBits = source.getAccumAlphaBits();
sampleBuffers = source.getSampleBuffers();
- pbufferFloatingPointBuffers = source.getPbufferFloatingPointBuffers();
- pbufferRenderToTexture = source.getPbufferRenderToTexture();
- pbufferRenderToTextureRectangle = source.getPbufferRenderToTextureRectangle();
numSamples = source.getNumSamples();
sampleExtension = source.getSampleExtension();
return this;
}
-
+
@Override
public int hashCode() {
// 31 * x == (x << 5) - x
- int hash = super.hashCode();
+ int hash = super.hashCode();
hash = ((hash << 5) - hash) + this.glProfile.hashCode() ;
hash = ((hash << 5) - hash) + ( this.hardwareAccelerated ? 1 : 0 );
hash = ((hash << 5) - hash) + ( this.stereo ? 1 : 0 );
@@ -148,19 +141,16 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
hash = ((hash << 5) - hash) + this.accumGreenBits;
hash = ((hash << 5) - hash) + this.accumBlueBits;
hash = ((hash << 5) - hash) + this.accumAlphaBits;
- hash = ((hash << 5) - hash) + ( this.pbufferFloatingPointBuffers ? 1 : 0 );
- hash = ((hash << 5) - hash) + ( this.pbufferRenderToTexture ? 1 : 0 );
- hash = ((hash << 5) - hash) + ( this.pbufferRenderToTextureRectangle ? 1 : 0 );
return hash;
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if(this == obj) { return true; }
if(!(obj instanceof GLCapabilitiesImmutable)) {
return false;
}
- GLCapabilitiesImmutable other = (GLCapabilitiesImmutable)obj;
+ final GLCapabilitiesImmutable other = (GLCapabilitiesImmutable)obj;
boolean res = super.equals(obj) &&
other.getGLProfile()==glProfile &&
other.isPBuffer()==isPBuffer &&
@@ -174,10 +164,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
other.getAccumGreenBits()==accumGreenBits &&
other.getAccumBlueBits()==accumBlueBits &&
other.getAccumAlphaBits()==accumAlphaBits &&
- other.getSampleBuffers()==sampleBuffers &&
- other.getPbufferFloatingPointBuffers()==pbufferFloatingPointBuffers &&
- other.getPbufferRenderToTexture()==pbufferRenderToTexture &&
- other.getPbufferRenderToTextureRectangle()==pbufferRenderToTextureRectangle;
+ other.getSampleBuffers()==sampleBuffers;
if(res && sampleBuffers) {
res = other.getNumSamples()==getNumSamples() &&
other.getSampleExtension().equals(sampleExtension) ;
@@ -189,7 +176,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
@Override
public int compareTo(final CapabilitiesImmutable o) {
if ( ! ( o instanceof GLCapabilitiesImmutable ) ) {
- Class<?> c = (null != o) ? o.getClass() : null ;
+ final Class<?> c = (null != o) ? o.getClass() : null ;
throw new ClassCastException("Not a GLCapabilitiesImmutable object, but " + c);
}
final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) o;
@@ -248,10 +235,10 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
}
/** Sets the GL profile you desire */
- public void setGLProfile(GLProfile profile) {
+ public void setGLProfile(final GLProfile profile) {
glProfile=profile;
}
-
+
@Override
public final boolean isPBuffer() {
return isPBuffer;
@@ -260,7 +247,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
/**
* Requesting offscreen pbuffer mode.
* <p>
- * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
+ * If enabled this method also invokes {@link #setOnscreen(boolean) setOnscreen(false)}.
* </p>
* <p>
* Defaults to false.
@@ -268,8 +255,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
* <p>
* Requesting offscreen pbuffer mode disables the offscreen auto selection.
* </p>
- */
- public void setPBuffer(boolean enable) {
+ */
+ public void setPBuffer(final boolean enable) {
if(enable) {
setOnscreen(false);
}
@@ -280,11 +267,11 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
public final boolean isFBO() {
return isFBO;
}
-
+
/**
* Requesting offscreen FBO mode.
* <p>
- * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
+ * If enabled this method also invokes {@link #setOnscreen(boolean) setOnscreen(false)}.
* </p>
* <p>
* Defaults to false.
@@ -293,7 +280,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
* Requesting offscreen FBO mode disables the offscreen auto selection.
* </p>
*/
- public void setFBO(boolean enable) {
+ public void setFBO(final boolean enable) {
if(enable) {
setOnscreen(false);
}
@@ -306,7 +293,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
}
/** Enables or disables double buffering. */
- public void setDoubleBuffered(boolean enable) {
+ public void setDoubleBuffered(final boolean enable) {
doubleBuffered = enable;
}
@@ -316,7 +303,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
}
/** Enables or disables stereo viewing. */
- public void setStereo(boolean enable) {
+ public void setStereo(final boolean enable) {
stereo = enable;
}
@@ -326,7 +313,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
}
/** Enables or disables hardware acceleration. */
- public void setHardwareAccelerated(boolean enable) {
+ public void setHardwareAccelerated(final boolean enable) {
hardwareAccelerated = enable;
}
@@ -336,7 +323,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
}
/** Sets the number of bits requested for the depth buffer. */
- public void setDepthBits(int depthBits) {
+ public void setDepthBits(final int depthBits) {
this.depthBits = depthBits;
}
@@ -346,7 +333,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
}
/** Sets the number of bits requested for the stencil buffer. */
- public void setStencilBits(int stencilBits) {
+ public void setStencilBits(final int stencilBits) {
this.stencilBits = stencilBits;
}
@@ -359,7 +346,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
red component. On some systems only the accumulation buffer
depth, which is the sum of the red, green, and blue bits, is
considered. */
- public void setAccumRedBits(int accumRedBits) {
+ public void setAccumRedBits(final int accumRedBits) {
this.accumRedBits = accumRedBits;
}
@@ -372,7 +359,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
green component. On some systems only the accumulation buffer
depth, which is the sum of the red, green, and blue bits, is
considered. */
- public void setAccumGreenBits(int accumGreenBits) {
+ public void setAccumGreenBits(final int accumGreenBits) {
this.accumGreenBits = accumGreenBits;
}
@@ -385,7 +372,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
blue component. On some systems only the accumulation buffer
depth, which is the sum of the red, green, and blue bits, is
considered. */
- public void setAccumBlueBits(int accumBlueBits) {
+ public void setAccumBlueBits(final int accumBlueBits) {
this.accumBlueBits = accumBlueBits;
}
@@ -398,7 +385,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
component. On some systems only the accumulation buffer depth,
which is the sum of the red, green, and blue bits, is
considered. */
- public void setAccumAlphaBits(int accumAlphaBits) {
+ public void setAccumAlphaBits(final int accumAlphaBits) {
this.accumAlphaBits = accumAlphaBits;
}
@@ -406,7 +393,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
* Sets the desired extension for full-scene antialiasing
* (FSAA), default is {@link #DEFAULT_SAMPLE_EXTENSION}.
*/
- public void setSampleExtension(String se) {
+ public void setSampleExtension(final String se) {
sampleExtension = se;
}
@@ -423,7 +410,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
* If enabled this method also invokes {@link #setAlphaBits(int) setAlphaBits(1)}
* if {@link #getAlphaBits()} == 0.<br>
*/
- public void setSampleBuffers(boolean enable) {
+ public void setSampleBuffers(final boolean enable) {
sampleBuffers = enable;
if(sampleBuffers && getAlphaBits()==0) {
setAlphaBits(1);
@@ -435,12 +422,12 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
return sampleBuffers;
}
- /**
+ /**
* If sample buffers are enabled, indicates the number of buffers
* to be allocated. Defaults to 2.
* @see #getNumSamples()
*/
- public void setNumSamples(int numSamples) {
+ public void setNumSamples(final int numSamples) {
this.numSamples = numSamples;
}
@@ -449,40 +436,6 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
return sampleBuffers ? numSamples : 0;
}
- /** For pbuffers only, indicates whether floating-point buffers
- should be used if available. Defaults to false. */
- public void setPbufferFloatingPointBuffers(boolean enable) {
- pbufferFloatingPointBuffers = enable;
- }
-
- @Override
- public final boolean getPbufferFloatingPointBuffers() {
- return pbufferFloatingPointBuffers;
- }
-
- /** For pbuffers only, indicates whether the render-to-texture
- extension should be used if available. Defaults to false. */
- public void setPbufferRenderToTexture(boolean enable) {
- pbufferRenderToTexture = enable;
- }
-
- @Override
- public final boolean getPbufferRenderToTexture() {
- return pbufferRenderToTexture;
- }
-
- /** For pbuffers only, indicates whether the
- render-to-texture-rectangle extension should be used if
- available. Defaults to false. */
- public void setPbufferRenderToTextureRectangle(boolean enable) {
- pbufferRenderToTextureRectangle = enable;
- }
-
- @Override
- public final boolean getPbufferRenderToTextureRectangle() {
- return pbufferRenderToTextureRectangle;
- }
-
@Override
public StringBuilder toString(StringBuilder sink) {
if(null == sink) {
@@ -493,8 +446,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
super.toString(sink, false);
- sink.append(", accum-rgba ").append(accumRedBits).append("/").append(accumGreenBits).append("/").append(accumBlueBits).append("/").append(accumAlphaBits);
- sink.append(", dp/st/ms: ").append(depthBits).append("/").append(stencilBits).append("/").append(samples);
+ sink.append(", accum-rgba ").append(accumRedBits).append(ESEP).append(accumGreenBits).append(ESEP).append(accumBlueBits).append(ESEP).append(accumAlphaBits);
+ sink.append(", dp/st/ms ").append(depthBits).append(ESEP).append(stencilBits).append(ESEP).append(samples);
if(samples>0) {
sink.append(", sample-ext ").append(sampleExtension);
}
@@ -525,15 +478,12 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
ns = true;
}
if(isPBuffer()) {
- if(ns) { sink.append(", "); }
- sink.append("pbuffer [r2t ").append(pbufferRenderToTexture?1:0)
- .append(", r2tr ").append(pbufferRenderToTextureRectangle?1:0)
- .append(", float ").append(pbufferFloatingPointBuffers?1:0)
- .append("]");
+ if(ns) { sink.append(CSEP); }
+ sink.append("pbuffer");
ns = true;
}
if(isBitmap()) {
- if(ns) { sink.append(", "); }
+ if(ns) { sink.append(CSEP); }
sink.append("bitmap");
ns = true;
}
@@ -541,7 +491,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
if(isOnscreen()) {
sink.append("."); // no additional off-screen modes besides on-screen
} else {
- sink.append("auto-cfg"); // auto-config off-screen mode
+ sink.append("auto-cfg"); // auto-config off-screen mode
}
}
sink.append("]");
@@ -553,7 +503,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
object. */
@Override
public String toString() {
- StringBuilder msg = new StringBuilder();
+ final StringBuilder msg = new StringBuilder();
msg.append("GLCaps[");
toString(msg);
msg.append("]");
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/GLCapabilitiesChooser.java
index 5d575c2ee..2e0bec1f9 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilitiesChooser.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilitiesChooser.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -53,7 +53,7 @@ import javax.media.opengl.GLCapabilitiesImmutable;
the appropriate method of {@link GLDrawableFactory}; the chooser
will be called during the OpenGL context creation process. Note
that this is only a marker interface; its signature is the same as
- {@link CapabilitiesChooser} and the {@link List} of
+ {@link CapabilitiesChooser} and the {@link List} of
objects extending {@link CapabilitiesImmutable}
passed to {@link #chooseCapabilities chooseCapabilities}
is actually a {@link List} of type {@link GLCapabilitiesImmutable}. */
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
index ee261ca01..dc28539a0 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
@@ -37,13 +37,13 @@ import javax.media.nativewindow.CapabilitiesImmutable;
* @see javax.media.nativewindow.CapabilitiesImmutable
*/
public interface GLCapabilitiesImmutable extends CapabilitiesImmutable {
- /**
- * One of the platform's default sample extension
+ /**
+ * One of the platform's default sample extension
* <code>EGL.EGL_SAMPLES, GLX.GLX_SAMPLES, WGLExt.WGL_SAMPLES_ARB</code>
* if available, or any other <i>known</i> fallback one, ie <code>EGLExt.EGL_COVERAGE_SAMPLES_NV</code>
*/
public static final String DEFAULT_SAMPLE_EXTENSION = "default" ;
-
+
/**
* Returns the GL profile you desire or used by the drawable.
*/
@@ -110,10 +110,10 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable {
* </p>
*/
String getSampleExtension();
-
+
/**
* Returns whether sample buffers for full-scene antialiasing
- * (FSAA) should be allocated for this drawable.
+ * (FSAA) should be allocated for this drawable.
* <p>
* Default is false.
* </p>
@@ -130,33 +130,6 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable {
int getNumSamples();
/**
- * For pbuffers only, returns whether floating-point buffers should
- * be used if available.
- * <p>
- * Default is false.
- * </p>
- */
- boolean getPbufferFloatingPointBuffers();
-
- /**
- * For pbuffers only, returns whether the render-to-texture
- * extension should be used if available.
- * <p>
- * Default is false.
- * </p>
- */
- boolean getPbufferRenderToTexture();
-
- /**
- * For pbuffers only, returns whether the render-to-texture
- * extension should be used.
- * <p>
- * Default is false.
- * </p>
- */
- boolean getPbufferRenderToTextureRectangle();
-
- /**
* Returns the number of stencil buffer bits.
* <p>
* Default is 0.
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index a5e639c74..e2498e6f1 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -42,19 +42,25 @@ package javax.media.opengl;
import java.nio.IntBuffer;
import java.util.HashMap;
-import java.util.HashSet;
+import java.util.IdentityHashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
+import jogamp.opengl.GLContextShareSet;
import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.VersionNumberString;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
/** Abstraction for an OpenGL rendering context. In order to perform
OpenGL rendering, a context must be "made current" on the current
@@ -69,10 +75,14 @@ import com.jogamp.opengl.GLExtensions;
abstraction provides a stable object which clients can use to
refer to a given context. */
public abstract class GLContext {
-
- /**
- * If <code>true</code> (default), bootstrapping the available GL profiles
- * will use the highest compatible GL context for each profile,
+
+ public static final boolean DEBUG = Debug.debug("GLContext");
+ public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
+ public static final boolean DEBUG_TRACE_SWITCH = DEBUG || TRACE_SWITCH;
+
+ /**
+ * If <code>true</code> (default), bootstrapping the available GL profiles
+ * will use the highest compatible GL context for each profile,
* hence skipping querying lower profiles if a compatible higher one is found:
* <ul>
* <li>4.2-core -> 4.2-core, 3.3-core</li>
@@ -88,32 +98,69 @@ public abstract class GLContext {
* </ul>
* Using aliasing speeds up initialization about:
* <ul>
- * <li>Linux x86_64 - Nvidia: 28%, 700ms down to 500ms</li>
- * <li>Linux x86_64 - AMD : 40%, 1500ms down to 900ms</li>
+ * <li>Linux x86_64 - Nvidia: 28%, 700ms down to 500ms</li>
+ * <li>Linux x86_64 - AMD : 40%, 1500ms down to 900ms</li>
* <p>
* Can be turned off with property <code>jogl.debug.GLContext.NoProfileAliasing</code>.
* </p>
*/
public static final boolean PROFILE_ALIASING = !Debug.isPropertyDefined("jogl.debug.GLContext.NoProfileAliasing", true);
-
+
protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true);
protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true);
-
- public static final boolean DEBUG = Debug.debug("GLContext");
- public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
+ protected static final boolean FORCE_NO_COLOR_RENDERBUFFER = Debug.isPropertyDefined("jogl.fbo.force.nocolorrenderbuffer", true);
/** Reflects property jogl.debug.DebugGL. If true, the debug pipeline is enabled at context creation. */
public static final boolean DEBUG_GL = Debug.isPropertyDefined("jogl.debug.DebugGL", true);
/** Reflects property jogl.debug.TraceGL. If true, the trace pipeline is enabled at context creation. */
public static final boolean TRACE_GL = Debug.isPropertyDefined("jogl.debug.TraceGL", true);
- /** Indicates that the context was not made current during the last call to {@link #makeCurrent makeCurrent}. */
+ /** Indicates that the context was not made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
public static final int CONTEXT_NOT_CURRENT = 0;
- /** Indicates that the context was made current during the last call to {@link #makeCurrent makeCurrent}. */
+ /** Indicates that the context was made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
public static final int CONTEXT_CURRENT = 1;
- /** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}. */
+ /** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
public static final int CONTEXT_CURRENT_NEW = 2;
+ /** Version 1.00, i.e. GLSL 1.00 for ES 2.0. */
+ public static final VersionNumber Version100 = new VersionNumber(1, 0, 0);
+ /** Version 1.10, i.e. GLSL 1.10 for GL 2.0. */
+ public static final VersionNumber Version110 = new VersionNumber(1, 10, 0);
+ /** Version 1.20, i.e. GLSL 1.20 for GL 2.1. */
+ public static final VersionNumber Version120 = new VersionNumber(1, 20, 0);
+ /** Version 1.30, i.e. GLSL 1.30 for GL 3.0. */
+ public static final VersionNumber Version130 = new VersionNumber(1, 30, 0);
+ /** Version 1.40, i.e. GLSL 1.40 for GL 3.1. */
+ public static final VersionNumber Version140 = new VersionNumber(1, 40, 0);
+ /** Version 1.50, i.e. GLSL 1.50 for GL 3.2. */
+ public static final VersionNumber Version150 = new VersionNumber(1, 50, 0);
+
+ /** Version 3.0. As an OpenGL version, it qualifies for desktop {@link #isGL2()} only, or ES 3.0. Or GLSL 3.00 for ES 3.0. */
+ public static final VersionNumber Version300 = new VersionNumber(3, 0, 0);
+
+ /** Version 3.1. As an OpenGL version, it qualifies for {@link #isGL3core()}, {@link #isGL3bc()} and {@link #isGL3()} */
+ public static final VersionNumber Version310 = new VersionNumber(3, 1, 0);
+
+ /** Version 3.2. As an OpenGL version, it qualifies for geometry shader */
+ public static final VersionNumber Version320 = new VersionNumber(3, 2, 0);
+
+ /** Version 4.3. As an OpenGL version, it qualifies for <code>GL_ARB_ES3_compatibility</code> */
+ public static final VersionNumber Version430 = new VersionNumber(4, 3, 0);
+
+ protected static final VersionNumber Version800 = new VersionNumber(8, 0, 0);
+
+ private static final String S_EMPTY = "";
+
+ //
+ // Cached keys, bits [0..15]
+ //
+
+ /** Context option bits, full bit mask covering 16 bits [0..15], i.e. <code>0x0000FFFF</code>, {@value}. */
+ protected static final int CTX_IMPL_FULL_MASK = 0x0000FFFF;
+
+ /** Context option bits, cached bit mask covering 10 bits [0..9], i.e. <code>0x000003FF</code>, {@value}. Leaving 6 bits for non cached options, i.e. 10:6. */
+ protected static final int CTX_IMPL_CACHE_MASK = 0x000003FF;
+
/** <code>ARB_create_context</code> related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IS_ARB_CREATED = 1 << 0;
/** <code>ARB_create_context</code> related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
@@ -126,79 +173,178 @@ public abstract class GLContext {
protected static final int CTX_OPTION_FORWARD = 1 << 4;
/** <code>ARB_create_context</code> related: flag debug. Cache key value. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
public static final int CTX_OPTION_DEBUG = 1 << 5;
+ /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 6;
+
+ //
+ // Non cached keys, 6 bits [10..15]
+ //
/** <code>GL_ARB_ES2_compatibility</code> implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
- protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
+ protected static final int CTX_IMPL_ES2_COMPAT = 1 << 10;
+
+ /** <code>GL_ARB_ES3_compatibility</code> implementation related: Context is compatible w/ ES3. Not a cache key. See {@link #isGLES3Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IMPL_ES3_COMPAT = 1 << 11;
- /** Context supports basic FBO, details see {@link #hasBasicFBOSupport()}.
+ /**
+ * Context supports basic FBO, details see {@link #hasBasicFBOSupport()}.
* Not a cache key.
* @see #hasBasicFBOSupport()
* @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
*/
- protected static final int CTX_IMPL_FBO = 1 << 9;
+ protected static final int CTX_IMPL_FBO = 1 << 12;
- /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
- protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15;
+ /**
+ * Context supports <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points,
+ * see {@link #hasFP32CompatAPI()}.
+ * Not a cache key.
+ * @see #hasFP32CompatAPI()
+ * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
+ */
+ protected static final int CTX_IMPL_FP32_COMPAT_API = 1 << 13;
private static final ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>();
private final HashMap<String, Object> attachedObjects = new HashMap<String, Object>();
// RecursiveLock maintains a queue of waiting Threads, ensuring the longest waiting thread will be notified at unlock.
- protected final RecursiveLock lock = LockFactory.createRecursiveLock();
+ protected final RecursiveLock lock = LockFactory.createRecursiveLock(); // FIXME: Move to GLContextImpl when incr. minor version (incompatible change)
/** The underlying native OpenGL context */
- protected long contextHandle;
+ protected volatile long contextHandle; // volatile: avoid locking for read-only access
protected GLContext() {
- resetStates();
+ resetStates(true);
}
- protected int ctxMajorVersion;
- protected int ctxMinorVersion;
+ protected VersionNumber ctxVersion;
protected int ctxOptions;
protected String ctxVersionString;
+ protected VersionNumberString ctxVendorVersion;
+ protected VersionNumber ctxGLSLVersion;
private int currentSwapInterval;
+ protected GLRendererQuirks glRendererQuirks;
+
+ /** Did the drawable association changed ? see {@link GLRendererQuirks#NoSetSwapIntervalPostRetarget} */
+ protected boolean drawableRetargeted;
- protected void resetStates() {
+ /**
+ * @param isInit true if called for class initialization, otherwise false (re-init or destruction).
+ */
+ protected void resetStates(final boolean isInit) {
if (DEBUG) {
- System.err.println(getThreadName() + ": GLContext.resetStates()");
+ System.err.println(getThreadName() + ": GLContext.resetStates(isInit "+isInit+")");
// Thread.dumpStack();
}
- ctxMajorVersion=-1;
- ctxMinorVersion=-1;
+ ctxVersion = VersionNumberString.zeroVersion;
+ ctxVendorVersion = VersionNumberString.zeroVersion;
ctxOptions=0;
ctxVersionString=null;
+ ctxGLSLVersion = VersionNumber.zeroVersion;
attachedObjects.clear();
contextHandle=0;
currentSwapInterval = -1;
+ glRendererQuirks = null;
+ drawableRetargeted = false;
+ }
+
+ /** Returns true if this GLContext is shared, otherwise false. */
+ public final boolean isShared() {
+ return GLContextShareSet.isShared(this);
}
/**
- * Sets the read/write drawable for framebuffer operations.
+ * Returns the shared master GLContext of this GLContext if shared, otherwise return <code>null</code>.
* <p>
- * If the context was current on this thread, it is being released before switching the drawable
- * and made current afterwards. However the user shall take extra care that not other thread
- * attempts to make this context current. Otherwise a race condition may happen.
+ * Returns this GLContext, if it is a shared master.
+ * </p>
+ * @since 2.2.1
+ */
+ public final GLContext getSharedMaster() {
+ return GLContextShareSet.getSharedMaster(this);
+ }
+
+ /** Returns a new list of created GLContext shared with this GLContext. */
+ public final List<GLContext> getCreatedShares() {
+ return GLContextShareSet.getCreatedShares(this);
+ }
+
+ /** Returns a new list of destroyed GLContext shared with this GLContext. */
+ public final List<GLContext> getDestroyedShares() {
+ return GLContextShareSet.getDestroyedShares(this);
+ }
+
+ /**
+ * Returns the instance of {@link GLRendererQuirks}, allowing one to determine workarounds.
+ * @return instance of {@link GLRendererQuirks} if context was made current once, otherwise <code>null</code>.
+ */
+ public final GLRendererQuirks getRendererQuirks() { return glRendererQuirks; }
+
+ /**
+ * Returns true if the <code>quirk</code> exist in {@link #getRendererQuirks()}, otherwise false.
+ * <p>
+ * Convenience method for:
+ * <pre>
+ * final GLRendererQuirks glrq = ctx.getRendererQuirks();
+ * boolean hasQuirk = null != glrq ? glrq.exist(quirk) : false ;
+ * </pre>
+ * </p>
+ * @param quirk the quirk to be tested, e.g. {@link GLRendererQuirks#NoDoubleBufferedPBuffer}.
+ * @throws IllegalArgumentException if the quirk is out of range
+ */
+ public final boolean hasRendererQuirk(final int quirk) throws IllegalArgumentException {
+ return null != glRendererQuirks ? glRendererQuirks.exist(quirk) : false ;
+ }
+
+ /**
+ * Sets the read/write drawable for framebuffer operations, i.e. reassociation of the context's drawable.
+ * <p>
+ * If the arguments reflect the current state of this context
+ * this method is a no-operation and returns the old and current {@link GLDrawable}.
+ * </p>
+ * <p>
+ * Remarks:
+ * <ul>
+ * <li>{@link GL#glFinish() glFinish()} is issued if context {@link #isCreated()} and a {@link #getGLDrawable() previous drawable} was bound before disassociation.</li>
+ * <li>If the context was current on this thread, it is being released before drawable reassociation
+ * and made current afterwards.</li>
+ * <li>Implementation may issue {@link #makeCurrent()} and {@link #release()} while drawable reassociation.</li>
+ * <li>The user shall take extra care of thread synchronization,
+ * i.e. lock the involved {@link GLDrawable#getNativeSurface() drawable's} {@link NativeSurface}s
+ * to avoid a race condition. In case {@link GLAutoDrawable auto-drawable's} are used,
+ * their {@link GLAutoDrawable#getUpstreamLock() upstream-lock} must be locked beforehand
+ * see <a href="GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * </ul>
* </p>
- * @param readWrite the read/write drawable for framebuffer operations.
- * @param setWriteOnly if <code>true</code> and if the current read-drawable differs
- * from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}),
- * only change the write-drawable. Otherwise set both drawables.
- * @return the replaced read/write drawable
+ * @param readWrite The read/write drawable for framebuffer operations, maybe <code>null</code> to remove association.
+ * @param setWriteOnly Only change the write-drawable, if <code>setWriteOnly</code> is <code>true</code> and
+ * if the {@link #getGLReadDrawable() read-drawable} differs
+ * from the {@link #getGLDrawable() write-drawable}.
+ * Otherwise set both drawables, read and write.
+ * @return The previous read/write drawable
*
- * @throws GLException in case <code>null</code> is being passed or
+ * @throws GLException in case <code>null</code> is being passed or
* this context is made current on another thread.
*
* @see #isGLReadDrawableAvailable()
+ * @see #setGLReadDrawable(GLDrawable)
* @see #getGLReadDrawable()
- * @see #setGLReadDrawable()
+ * @see #setGLDrawable(GLDrawable, boolean)
* @see #getGLDrawable()
*/
public abstract GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly);
-
+
/**
* Returns the write-drawable this context uses for framebuffer operations.
+ * <p>
+ * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)},
+ * it equals to the write-drawable (default).
+ * </p>
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ * @see #setGLDrawable(GLDrawable, boolean)
+ * @see #setGLReadDrawable(GLDrawable)
*/
public abstract GLDrawable getGLDrawable();
@@ -219,7 +365,7 @@ public abstract class GLContext {
*
* @param read the read-drawable for read framebuffer operations.
* If null is passed, the default write drawable will be set.
- * @return the replaced read-drawable
+ * @return the previous read-drawable
*
* @throws GLException in case a read drawable is not supported or
* this context is made current on another thread.
@@ -234,30 +380,40 @@ public abstract class GLContext {
* <p>
* If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)},
* it equals to the write-drawable (default).
- * </p>
+ * </p>
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
* @see #isGLReadDrawableAvailable()
- * @see #setGLReadDrawable(javax.media.opengl.GLDrawable)
- * @see #getGLDrawable()
+ * @see #setGLReadDrawable(GLDrawable)
+ * @see #getGLReadDrawable()
*/
public abstract GLDrawable getGLReadDrawable();
/**
* Makes this GLContext current on the calling thread.
* <p>
+ * Recursive call to {@link #makeCurrent()} and hence {@link #release()} are supported.
+ * </p>
+ * <p>
* There are two return values that indicate success and one that
- * indicates failure. A return value of CONTEXT_CURRENT_NEW
- * indicates that that context has been made current, and that
- * this is the first time this context has been made current, or
- * that the state of the underlying context or drawable may have
- * changed since the last time this context was made current. In
- * this case, the application may wish to initialize the state. A
- * return value of CONTEXT_CURRENT indicates that the context has
- * been made currrent, with its previous state restored.
+ * indicates failure.
+ * </p>
+ * <p>
+ * A return value of {@link #CONTEXT_CURRENT_NEW}
+ * indicates that that context has been made current for the 1st time,
+ * or that the state of the underlying context or drawable has
+ * changed since the last time this context was current.
+ * In this case, the application may wish to initialize the render state.
+ * </p>
+ * <p>
+ * A return value of {@link #CONTEXT_CURRENT} indicates that the context has
+ * been made current, with its previous state restored.
* </p>
* <p>
* If the context could not be made current (for example, because
* the underlying drawable has not ben realized on the display) ,
- * a value of CONTEXT_NOT_CURRENT is returned.
+ * a value of {@link #CONTEXT_NOT_CURRENT} is returned.
* </p>
* <p>
* This method is blocking, i.e. waits until another thread has
@@ -268,11 +424,11 @@ public abstract class GLContext {
* and unlocked at {@link #release()}
* </p>
*
- * @return CONTEXT_CURRENT if the context was successfully made current
- * @return CONTEXT_CURRENT_NEW if the context was successfully made
- * current, but need to be initialized.
- *
- * @return CONTEXT_NOT_CURRENT if the context could not be made current.
+ * @return <ul>
+ * <li>{@link #CONTEXT_CURRENT_NEW} if the context was successfully made current the 1st time,</li>
+ * <li>{@link #CONTEXT_CURRENT} if the context was successfully made current,</li>
+ * <li>{@link #CONTEXT_NOT_CURRENT} if the context could not be made current.</li>
+ * </ul>
*
* @throws GLException if synchronization is disabled and the
* context is current on another thread, or because the context
@@ -284,6 +440,9 @@ public abstract class GLContext {
/**
* Releases control of this GLContext from the current thread.
* <p>
+ * Recursive call to {@link #release()} and hence {@link #makeCurrent()} are supported.
+ * </p>
+ * <p>
* The drawable's surface is being unlocked at exit,
* assumed to be locked by {@link #makeCurrent()}.
* </p>
@@ -299,7 +458,7 @@ public abstract class GLContext {
* parameter indicates which groups of state variables are to be
* copied. <code>mask</code> contains the bitwise OR of the same
* symbolic names that are passed to the GL command {@link
- * GL#glPushAttrib glPushAttrib}. The single symbolic constant
+ * GL2#glPushAttrib glPushAttrib}. The single symbolic constant
* {@link GL2#GL_ALL_ATTRIB_BITS GL_ALL_ATTRIB_BITS} can be used to
* copy the maximum possible portion of rendering state. <P>
*
@@ -331,7 +490,7 @@ public abstract class GLContext {
* @throws GLException if no context is current
*/
public static GL getCurrentGL() throws GLException {
- GLContext glc = getCurrent();
+ final GLContext glc = getCurrent();
if(null==glc) {
throw new GLException(getThreadName()+": No OpenGL context current on this thread");
}
@@ -365,13 +524,23 @@ public abstract class GLContext {
}
}
+ /** Returns a String representation of the {@link #makeCurrent()} result. */
+ public static final String makeCurrentResultToString(final int res) {
+ switch(res) {
+ case CONTEXT_NOT_CURRENT: return "CONTEXT_NOT_CURRENT";
+ case CONTEXT_CURRENT: return "CONTEXT_CURRENT";
+ case CONTEXT_CURRENT_NEW: return "CONTEXT_NOT_CURRENT";
+ default: return "INVALID_VALUE";
+ }
+ }
+
/**
* Sets the thread-local variable returned by {@link #getCurrent}
* and has no other side-effects. For use by third parties adding
* new GLContext implementations; not for use by end users.
*/
- protected static void setCurrent(GLContext cur) {
- if(TRACE_SWITCH) {
+ protected static void setCurrent(final GLContext cur) {
+ if( TRACE_SWITCH ) {
if(null == cur) {
System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - NULL");
} else {
@@ -392,6 +561,17 @@ public abstract class GLContext {
public abstract void destroy();
/**
+ * Returns the implementing root GL instance of this GLContext's GL object,
+ * considering a wrapped pipelined hierarchy, see {@link GLBase#getDownstreamGL()}.
+ * @throws GLException if the root instance is not a GL implementation
+ * @see GLBase#getRootGL()
+ * @see GLBase#getDownstreamGL()
+ * @see #getGL()
+ * @see #setGL(GL)
+ */
+ public abstract GL getRootGL();
+
+ /**
* Returns the GL pipeline object for this GLContext.
*
* @return the aggregated GL instance, or null if this context was not yet made current.
@@ -406,12 +586,12 @@ public abstract class GLContext {
public abstract GL setGL(GL gl);
/**
- * Returns the native GL context handle
+ * Returns the underlying native OpenGL context handle
*/
public final long getHandle() { return contextHandle; }
/**
- * Indicates whether the underlying OpenGL context has been created.
+ * Indicates whether the underlying native OpenGL context has been created.
*/
public final boolean isCreated() {
return 0 != contextHandle;
@@ -420,7 +600,7 @@ public abstract class GLContext {
/**
* Returns the attached user object for the given name to this GLContext.
*/
- public final Object getAttachedObject(String name) {
+ public final Object getAttachedObject(final String name) {
return attachedObjects.get(name);
}
@@ -428,11 +608,11 @@ public abstract class GLContext {
* Sets the attached user object for the given name to this GLContext.
* Returns the previously set object or null.
*/
- public final Object attachObject(String name, Object obj) {
+ public final Object attachObject(final String name, final Object obj) {
return attachedObjects.put(name, obj);
}
- public final Object detachObject(String name) {
+ public final Object detachObject(final String name) {
return attachedObjects.remove(name);
}
@@ -441,7 +621,7 @@ public abstract class GLContext {
*/
@Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
this.append(sb);
@@ -449,21 +629,22 @@ public abstract class GLContext {
return sb.toString();
}
- public final StringBuilder append(StringBuilder sb) {
- sb.append("OpenGL ");
- sb.append(getGLVersionMajor());
- sb.append(".");
- sb.append(getGLVersionMinor());
- sb.append(", options 0x");
+ public final StringBuilder append(final StringBuilder sb) {
+ sb.append("Version ").append(getGLVersion()).append(" [GL ").append(getGLVersionNumber()).append(", vendor ").append(getGLVendorVersionNumber());
+ sb.append("], options 0x");
sb.append(Integer.toHexString(ctxOptions));
- sb.append(", ");
- sb.append(getGLVersion());
sb.append(", this ");
sb.append(toHexString(hashCode()));
sb.append(", handle ");
sb.append(toHexString(contextHandle));
- sb.append(", ");
+ sb.append(", isShared "+isShared()+", ");
sb.append(getGL());
+ sb.append(",\n\t quirks: ");
+ if(null != glRendererQuirks) {
+ glRendererQuirks.toString(sb);
+ } else {
+ sb.append("n/a");
+ }
if(getGLDrawable()!=getGLReadDrawable()) {
sb.append(",\n\tRead Drawable : ");
sb.append(getGLReadDrawable());
@@ -473,8 +654,6 @@ public abstract class GLContext {
sb.append(",\n\tDrawable: ");
sb.append(getGLDrawable());
}
- sb.append(", lock ");
- sb.append(lock.toString());
return sb;
}
@@ -583,45 +762,167 @@ public abstract class GLContext {
return ctxVersionString;
}
- public final int getGLVersionMajor() { return ctxMajorVersion; }
- public final int getGLVersionMinor() { return ctxMinorVersion; }
+ /**
+ * Returns this context OpenGL version.
+ * @see #getGLSLVersionNumber()
+ **/
+ public final VersionNumber getGLVersionNumber() { return ctxVersion; }
+ /**
+ * Returns the vendor's version, i.e. version number at the end of <code>GL_VERSION</code> not being the GL version.
+ * <p>
+ * In case no such version exists within <code>GL_VERSION</code>,
+ * the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+ * </p>
+ * <p>
+ * The vendor's version is usually the vendor's OpenGL driver version.
+ * </p>
+ */
+ public final VersionNumberString getGLVendorVersionNumber() { return ctxVendorVersion; }
public final boolean isGLCompatibilityProfile() { return ( 0 != ( CTX_PROFILE_COMPAT & ctxOptions ) ); }
public final boolean isGLCoreProfile() { return ( 0 != ( CTX_PROFILE_CORE & ctxOptions ) ); }
+ public final boolean isGLESProfile() { return ( 0 != ( CTX_PROFILE_ES & ctxOptions ) ); }
public final boolean isGLForwardCompatible() { return ( 0 != ( CTX_OPTION_FORWARD & ctxOptions ) ); }
public final boolean isGLDebugEnabled() { return ( 0 != ( CTX_OPTION_DEBUG & ctxOptions ) ); }
public final boolean isCreatedWithARBMethod() { return ( 0 != ( CTX_IS_ARB_CREATED & ctxOptions ) ); }
/**
+ * Returns the matching GLSL version number, queried by this context GL
+ * via {@link GL2ES2#GL_SHADING_LANGUAGE_VERSION} if &ge; ES2.0 or GL2.0,
+ * otherwise a static match is being utilized.
+ * <p>
+ * The context must have been current once,
+ * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+ * </p>
+ * <p>
+ * Examples w/ <code>major.minor</code>:
+ * <pre>
+ * 1.00 (ES 2.0), 3.00 (ES 3.0)
+ * 1.10 (GL 2.0), 1.20 (GL 2.1), 1.50 (GL 3.2),
+ * 3.30 (GL 3.3), 4.00 (GL 4.0), 4.10 (GL 4.1), 4.20 (GL 4.2)
+ * </pre >
+ * </p>
+ * <p>
+ * <i>Matching</i> could also refer to the maximum GLSL version usable by this context
+ * since <i>normal</i> GL implementations are capable of using a lower GLSL version as well.
+ * The latter is not true on OSX w/ a GL3 context.
+ * </p>
+ *
+ * @return GLSL version number if context has been made current at least once,
+ * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+ *
+ * @see #getGLVersionNumber()
+ */
+ public final VersionNumber getGLSLVersionNumber() {
+ return ctxGLSLVersion;
+ }
+
+ /**
+ * Returns the GLSL version string as to be used in a shader program, including a terminating newline '\n',
+ * i.e. for desktop
+ * <pre>
+ * #version 110
+ * ..
+ * #version 150 core
+ * #version 330 compatibility
+ * ...
+ * </pre>
+ * And for ES:
+ * <pre>
+ * #version 100
+ * #version 300 es
+ * ..
+ * </pre>
+ * <p>
+ * If context has not been made current yet, a string of zero length is returned.
+ * </p>
+ * @see #getGLSLVersionNumber()
+ */
+ public final String getGLSLVersionString() {
+ if( ctxGLSLVersion.isZero() ) {
+ return S_EMPTY;
+ }
+ final int minor = ctxGLSLVersion.getMinor();
+ final String profileOpt;
+ if( isGLES() ) {
+ profileOpt = ctxGLSLVersion.compareTo(Version300) >= 0 ? " es" : S_EMPTY;
+ } else if( isGLCoreProfile() ) {
+ profileOpt = ctxGLSLVersion.compareTo(Version150) >= 0 ? " core" : S_EMPTY;
+ } else if( isGLCompatibilityProfile() ) {
+ profileOpt = ctxGLSLVersion.compareTo(Version150) >= 0 ? " compatibility" : S_EMPTY;
+ } else {
+ throw new InternalError("Neither ES, Core nor Compat: "+this); // see validateProfileBits(..)
+ }
+ return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + profileOpt + "\n" ;
+ }
+
+ protected static final VersionNumber getStaticGLSLVersionNumber(final int glMajorVersion, final int glMinorVersion, final int ctxOptions) {
+ if( 0 != ( CTX_PROFILE_ES & ctxOptions ) ) {
+ if( 3 == glMajorVersion ) {
+ return Version300; // ES 3.0 -> GLSL 3.00
+ } else if( 2 == glMajorVersion ) {
+ return Version100; // ES 2.0 -> GLSL 1.00
+ }
+ } else if( 1 == glMajorVersion ) {
+ return Version110; // GL 1.x -> GLSL 1.10
+ } else if( 2 == glMajorVersion ) {
+ switch ( glMinorVersion ) {
+ case 0: return Version110; // GL 2.0 -> GLSL 1.10
+ default: return Version120; // GL 2.1 -> GLSL 1.20
+ }
+ } else if( 3 == glMajorVersion && 2 >= glMinorVersion ) {
+ switch ( glMinorVersion ) {
+ case 0: return Version130; // GL 3.0 -> GLSL 1.30
+ case 1: return Version140; // GL 3.1 -> GLSL 1.40
+ default: return Version150; // GL 3.2 -> GLSL 1.50
+ }
+ }
+ // The new default: GL >= 3.3, ES >= 3.0
+ return new VersionNumber(glMajorVersion, glMinorVersion * 10, 0); // GL M.N -> GLSL M.N
+ }
+
+ /**
* @return true if this context is an ES2 context or implements
- * the extension <code>GL_ARB_ES2_compatibility</code>, otherwise false
+ * the extension <code>GL_ARB_ES3_compatibility</code> or <code>GL_ARB_ES2_compatibility</code>, otherwise false
*/
public final boolean isGLES2Compatible() {
- return 0 != ( ctxOptions & CTX_IMPL_ES2_COMPAT ) ;
+ return 0 != ( ctxOptions & ( CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ) ) ;
}
- /**
+ /**
+ * Return true if this context is an ES3 context or implements
+ * the extension <code>GL_ARB_ES3_compatibility</code>, otherwise false.
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ */
+ public final boolean isGLES3Compatible() {
+ return 0 != ( ctxOptions & CTX_IMPL_ES3_COMPAT ) ;
+ }
+
+ /**
* @return true if impl. is a hardware rasterizer, otherwise false.
* @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile)
- * @see GLProfile#isHardwareRasterizer()
+ * @see GLProfile#isHardwareRasterizer()
*/
public final boolean isHardwareRasterizer() {
return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
}
-
+
/**
- * @return true if context supports GLSL, i.e. is either {@link #isGLES2()}, {@link #isGL3()} or {@link #isGL2()} <i>and</i> major-version > 1.
- * @see GLProfile#hasGLSL()
+ * @return true if context supports GLSL, i.e. is either {@link #isGLES3()}, {@link #isGLES2()}, {@link #isGL3()} or {@link #isGL2()} <i>and</i> major-version > 1.
+ * @see GLProfile#hasGLSL()
*/
public final boolean hasGLSL() {
- return isGLES2() ||
+ return isGLES3() ||
+ isGLES2() ||
isGL3() ||
- isGL2() && ctxMajorVersion>1 ;
+ isGL2() && ctxVersion.getMajor()>1 ;
}
- /**
+ /**
* Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>.
* <p>
- * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= 3.0 [core, compat] or implements the extensions
* <code>GL_ARB_ES2_compatibility</code>, <code>GL_ARB_framebuffer_object</code>, <code>GL_EXT_framebuffer_object</code> or <code>GL_OES_framebuffer_object</code>.
* </p>
* <p>
@@ -634,49 +935,60 @@ public abstract class GLContext {
return 0 != ( ctxOptions & CTX_IMPL_FBO ) ;
}
- /**
+ /**
* Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>.
* <p>
- * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+ * Full FBO is supported if the context is either GL >= 3.0 [ES, core, compat] or implements the extensions
* <code>ARB_framebuffer_object</code>, or all of
- * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>,
+ * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>,
* <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>.
* </p>
* <p>
* Full FBO support includes multiple color attachments and multisampling.
* </p>
*/
- public final boolean hasFullFBOSupport() {
- return !FORCE_MIN_FBO_SUPPORT && hasBasicFBOSupport() &&
- ( isGL3() || // GL >= 3.0
- isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
- ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object*
- isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
- isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
- isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil)
- )
- ) ;
+ public final boolean hasFullFBOSupport() {
+ return hasBasicFBOSupport() && !hasRendererQuirk(GLRendererQuirks.NoFullFBOSupport) &&
+ ( isGL3ES3() || // GL >= 3.0 [ES, core, compat]
+ isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
+ ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object*
+ isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
+ isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
+ isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil)
+ )
+ ) ;
}
-
+
+ /**
+ * Returns <code>true</code> if <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points available,
+ * otherwise <code>false</code>.
+ * @see #CTX_IMPL_FP32_COMPAT_API
+ */
+ public final boolean hasFP32CompatAPI() {
+ return 0 != ( ctxOptions & CTX_IMPL_FP32_COMPAT_API ) ;
+ }
+
/**
* Returns the maximum number of FBO RENDERBUFFER samples
- * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false.
+ * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false.
*/
public final int getMaxRenderbufferSamples() {
if( hasFullFBOSupport() ) {
final GL gl = getGL();
final int[] val = new int[] { 0 } ;
- gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
- final int glerr = gl.glGetError();
- if(GL.GL_NO_ERROR == glerr) {
- return val[0];
- } else if(DEBUG) {
- System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
- }
+ try {
+ gl.glGetIntegerv(GL2ES3.GL_MAX_SAMPLES, val, 0);
+ final int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR == glerr) {
+ return val[0];
+ } else if(DEBUG) {
+ System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
+ }
+ } catch (final GLException gle) { gle.printStackTrace(); }
}
return 0;
}
-
+
/** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns <code>true</code>. */
public boolean isNPOTTextureAvailable() {
return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
@@ -688,87 +1000,248 @@ public abstract class GLContext {
isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ;
}
- /** @see GLProfile#isGL4bc() */
+ /**
+ * Indicates whether this GLContext is capable of GL4bc. <p>Includes [ GL4bc ].</p>
+ * @see GLProfile#isGL4bc()
+ */
public final boolean isGL4bc() {
- return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
+ return 0 != (ctxOptions & CTX_PROFILE_COMPAT) &&
+ ctxVersion.getMajor() >= 4;
}
- /** @see GLProfile#isGL4() */
+ /**
+ * Indicates whether this GLContext is capable of GL4. <p>Includes [ GL4bc, GL4 ].</p>
+ * @see GLProfile#isGL4()
+ */
public final boolean isGL4() {
- return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
+ return 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) &&
+ ctxVersion.getMajor() >= 4;
+ }
+
+ /**
+ * Indicates whether this GLContext uses a GL4 core profile. <p>Includes [ GL4 ].</p>
+ */
+ public final boolean isGL4core() {
+ return 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.getMajor() >= 4;
}
- /** @see GLProfile#isGL3bc() */
+ /**
+ * Indicates whether this GLContext is capable of GL3bc. <p>Includes [ GL4bc, GL3bc ].</p>
+ * @see GLProfile#isGL3bc()
+ */
public final boolean isGL3bc() {
- return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
- && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
+ return 0 != (ctxOptions & CTX_PROFILE_COMPAT) &&
+ ctxVersion.compareTo(Version310) >= 0 ;
}
- /** @see GLProfile#isGL3() */
+ /**
+ * Indicates whether this GLContext is capable of GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3 ].</p>
+ * @see GLProfile#isGL3()
+ */
public final boolean isGL3() {
- return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
- && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
+ return 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) &&
+ ctxVersion.compareTo(Version310) >= 0 ;
+ }
+
+ /**
+ * Indicates whether this GLContext uses a GL3 core profile. <p>Includes [ GL4, GL3 ].</p>
+ */
+ public final boolean isGL3core() {
+ return 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version310) >= 0;
+ }
+
+ /**
+ * Indicates whether this GLContext uses a GL core profile. <p>Includes [ GL4, GL3, GLES3, GLES2 ].</p>
+ */
+ public final boolean isGLcore() {
+ return ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 2 ) ||
+ ( 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version310) >= 0
+ ) ;
+ }
+
+ /**
+ * Indicates whether this GLContext allows CPU data sourcing (indices, vertices ..) as opposed to using a GPU buffer source (VBO),
+ * e.g. {@link GL2#glDrawElements(int, int, int, java.nio.Buffer)}.
+ * <p>Includes [GL2ES1, GLES2] == [ GL4bc, GL3bc, GL2, GLES1, GL2ES1, GLES2 ].</p>
+ * <p>See Bug 852 - https://jogamp.org/bugzilla/show_bug.cgi?id=852 </p>
+ */
+ public final boolean isCPUDataSourcingAvail() {
+ return isGL2ES1() || isGLES2();
+ }
+
+ /**
+ * Indicates whether this GLContext's native profile does not implement a <i>default vertex array object</i> (VAO),
+ * starting w/ OpenGL 3.1 core.
+ * <p>Includes [ GL4, GL3 ].</p>
+ * <pre>
+ Due to GL 3.1 core spec: E.1. DEPRECATED AND REMOVED FEATURES (p 296),
+ GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331)
+ there is no more default VAO buffer 0 bound, hence generating and binding one
+ to avoid INVALID_OPERATION at VertexAttribPointer.
+ More clear is GL 4.3 core spec: 10.4 (p 307).
+ * </pre>
+ * <pre>
+ ES 3.x is <i>not</i> included here.
+ Due to it's ES 2.0 backward compatibility it still supports the following features:
+ <i>client side vertex arrays</i>
+ <i>default vertex array object</i>
+
+ Binding a custom VAO with ES 3.0 would cause <i>client side vertex arrays</i> via {@link GL2ES1#glVertexPointer(int, int, int, java.nio.Buffer) glVertexPointer}
+ to produce <code>GL_INVALID_OPERATION</code>.
+
+ However, they are marked <i>deprecated</i>:
+ GL ES 3.0 spec F.1. Legacy Features (p 322).
+ GL ES 3.1 spec F.1. Legacy Features (p 454).
+ * </pre>
+ * <p>
+ * If no default VAO is implemented in the native OpenGL profile,
+ * an own default VAO is being used, see {@link #getDefaultVAO()}.
+ * </p>
+ * @see #getDefaultVAO()
+ */
+ public final boolean hasNoDefaultVAO() {
+ return // ES 3.x not included, see above. ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 3 ) ||
+ ( 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
+ 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version310) >= 0
+ ) ;
}
-
- /** @see GLProfile#isGL2() */
+
+ /**
+ * If this GLContext does not implement a default VAO, see {@link #hasNoDefaultVAO()},
+ * an <i>own default VAO</i> will be created and bound at context creation.
+ * <p>
+ * If this GLContext does implement a default VAO, i.e. {@link #hasNoDefaultVAO()}
+ * returns <code>false</code>, this method returns <code>0</code>.
+ * </p>
+ * <p>
+ * Otherwise this method returns the VAO object name
+ * representing this GLContext's <i>own default VAO</i>.
+ * </p>
+ * @see #hasNoDefaultVAO()
+ */
+ public abstract int getDefaultVAO();
+
+ /**
+ * Indicates whether this GLContext is capable of GL2. <p>Includes [ GL4bc, GL3bc, GL2 ].</p>
+ * @see GLProfile#isGL2()
+ */
public final boolean isGL2() {
- return ctxMajorVersion>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT);
+ return 0 != ( ctxOptions & CTX_PROFILE_COMPAT ) && ctxVersion.getMajor()>=1 ;
}
- /** @see GLProfile#isGL2GL3() */
+ /**
+ * Indicates whether this GLContext is capable of GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p>
+ * @see GLProfile#isGL2GL3()
+ */
public final boolean isGL2GL3() {
return isGL2() || isGL3();
}
- /** @see GLProfile#isGLES1() */
+ /**
+ * Indicates whether this GLContext is capable of GLES1. <p>Includes [ GLES1 ].</p>
+ * @see GLProfile#isGLES1()
+ */
public final boolean isGLES1() {
- return ctxMajorVersion==1 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
+ return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 1 ;
}
- /** @see GLProfile#isGLES2() */
+ /**
+ * Indicates whether this GLContext is capable of GLES2. <p>Includes [ GLES2, GLES3 ].</p>
+ * @see GLProfile#isGLES2()
+ */
public final boolean isGLES2() {
- return ctxMajorVersion==2 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
+ if( 0 != ( ctxOptions & CTX_PROFILE_ES ) ) {
+ final int major = ctxVersion.getMajor();
+ return 2 == major || 3 == major;
+ }
+ return false;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GLES3. <p>Includes [ GLES3 ].</p>
+ * @see GLProfile#isGLES3()
+ */
+ public final boolean isGLES3() {
+ return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 3 ;
}
- /** @see GLProfile#isGLES() */
+ /**
+ * Indicates whether this GLContext is capable of GLES. <p>Includes [ GLES3, GLES1, GLES2 ].</p>
+ * @see GLProfile#isGLES()
+ */
public final boolean isGLES() {
return 0 != ( CTX_PROFILE_ES & ctxOptions ) ;
}
- /** @see GLProfile#isGL2ES1() */
+ /**
+ * Indicates whether this GLContext is capable of GL2ES1. <p>Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].</p>
+ * @see GLProfile#isGL2ES1()
+ */
public final boolean isGL2ES1() {
- return isGL2() || isGLES1() ;
+ return isGLES1() || isGL2();
}
- /** @see GLProfile#isGL2ES2() */
+ /**
+ * Indicates whether this GLContext is capable of GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GL2GL3, GL2ES2, GLES2 ].</p>
+ * @see GLProfile#isGL2ES2()
+ */
public final boolean isGL2ES2() {
- return isGL2GL3() || isGLES2() ;
+ return isGLES2() || isGL2GL3();
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL2ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL3ES3, GL2, GL2GL3 ].</p>
+ * @see GLProfile#isGL2ES3()
+ * @see #isGL3ES3()
+ * @see #isGL2GL3()
+ */
+ public final boolean isGL2ES3() {
+ return isGL3ES3() || isGL2GL3();
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL3ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3 ].</p>
+ * @see GLProfile#isGL3ES3()
+ */
+ public final boolean isGL3ES3() {
+ return isGL4ES3() || isGL3();
}
/**
- * Set the swap interval if the current context.
- * @param interval Should be &ge; 0. 0 Disables the vertical synchronisation,
+ * Returns true if this profile is capable of GL4ES3, i.e. if {@link #isGLES3Compatible()} returns true.
+ * <p>Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]</p>
+ * @see GLProfile#isGL4ES3()
+ */
+ public final boolean isGL4ES3() {
+ return isGLES3Compatible() ;
+ }
+
+ /**
+ * Set the swap interval of the current context and attached drawable.
+ * @param interval Should be &ge; 0. 0 disables the vertical synchronization,
* where &ge; 1 is the number of vertical refreshes before a swap buffer occurs.
* A value &lt; 0 is ignored.
* @return true if the operation was successful, otherwise false
*
* @throws GLException if the context is not current.
*/
- public final boolean setSwapInterval(int interval) throws GLException {
+ public final boolean setSwapInterval(final int interval) throws GLException {
validateCurrent();
if(0<=interval) {
- if( setSwapIntervalImpl(interval) ) {
- currentSwapInterval = interval;
- return true;
+ if( !drawableRetargeted || !hasRendererQuirk(GLRendererQuirks.NoSetSwapIntervalPostRetarget) ) {
+ if( setSwapIntervalImpl(interval) ) {
+ currentSwapInterval = interval;
+ return true;
+ }
}
}
return false;
}
- protected boolean setSwapIntervalImpl(int interval) {
+ protected boolean setSwapIntervalImpl(final int interval) {
return false;
}
/** Return the current swap interval.
@@ -777,15 +1250,12 @@ public abstract class GLContext {
* the default value <code>-1</code> is returned.
* </p>
* <p>
- * The default value for a valid context is <code>1</code> for
- * an EGL based profile (ES1 or ES2) and <code>-1</code> (undefined)
- * for desktop.
+ * For a valid context the default value is <code>1</code>
+ * in case of an EGL based profile (ES1 or ES2) and <code>-1</code>
+ * (undefined) for desktop.
* </p>
*/
public final int getSwapInterval() {
- if(-1 == currentSwapInterval && this.isGLES()) {
- currentSwapInterval = 1;
- }
return currentSwapInterval;
}
protected final void setDefaultSwapInterval() {
@@ -796,73 +1266,125 @@ public abstract class GLContext {
}
}
- public final boolean queryMaxSwapGroups(int[] maxGroups, int maxGroups_offset,
- int[] maxBarriers, int maxBarriers_offset) {
+ public final boolean queryMaxSwapGroups(final int[] maxGroups, final int maxGroups_offset,
+ final int[] maxBarriers, final int maxBarriers_offset) {
validateCurrent();
return queryMaxSwapGroupsImpl(maxGroups, maxGroups_offset, maxBarriers, maxBarriers_offset);
}
- protected boolean queryMaxSwapGroupsImpl(int[] maxGroups, int maxGroups_offset,
- int[] maxBarriers, int maxBarriers_offset) { return false; }
- public final boolean joinSwapGroup(int group) {
+ protected boolean queryMaxSwapGroupsImpl(final int[] maxGroups, final int maxGroups_offset,
+ final int[] maxBarriers, final int maxBarriers_offset) { return false; }
+ public final boolean joinSwapGroup(final int group) {
validateCurrent();
return joinSwapGroupImpl(group);
}
- protected boolean joinSwapGroupImpl(int group) { /** nop per default .. **/ return false; }
+ protected boolean joinSwapGroupImpl(final int group) { /** nop per default .. **/ return false; }
protected int currentSwapGroup = -1; // default: not set yet ..
public int getSwapGroup() {
return currentSwapGroup;
}
- public final boolean bindSwapBarrier(int group, int barrier) {
+ public final boolean bindSwapBarrier(final int group, final int barrier) {
validateCurrent();
return bindSwapBarrierImpl(group, barrier);
}
- protected boolean bindSwapBarrierImpl(int group, int barrier) { /** nop per default .. **/ return false; }
+ protected boolean bindSwapBarrierImpl(final int group, final int barrier) { /** nop per default .. **/ return false; }
- /**
- * Return the framebuffer name bound to this context,
+ /**
+ * Return the framebuffer name bound to this context,
* see {@link GL#glBindFramebuffer(int, int)}.
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
*/
public abstract int getBoundFramebuffer(int target);
-
- /**
+
+ /**
* Return the default draw framebuffer name.
- * <p>
+ * <p>
* May differ from it's default <code>zero</code>
- * in case an framebuffer object ({@link FBObject}) based drawable
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
* is being used.
- * </p>
+ * </p>
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
*/
public abstract int getDefaultDrawFramebuffer();
-
- /**
+
+ /**
* Return the default read framebuffer name.
- * <p>
+ * <p>
* May differ from it's default <code>zero</code>
- * in case an framebuffer object ({@link FBObject}) based drawable
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
* is being used.
- * </p>
+ * </p>
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
*/
public abstract int getDefaultReadFramebuffer();
-
+
+ /**
+ * Returns the default color buffer within the current bound
+ * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​,
+ * which will be used as the source for pixel reading commands,
+ * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} etc.
+ * <p>
+ * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
+ * otherwise this is {@link GL#GL_FRONT} for single buffer configurations
+ * and {@link GL#GL_BACK} for double buffer configurations.
+ * </p>
+ * <p>
+ * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+ * and {@link GL#GL_BACK} is the default.
+ * </p>
+ * <p>
+ * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i
+ * </p>
+ * <p>
+ * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead}
+ * for read-pixels and swap-buffers implications.
+ * </p>
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ */
+ public abstract int getDefaultReadBuffer();
+
+ /**
+ * Get the default pixel data type, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}.
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ */
+ public abstract int getDefaultPixelDataType();
+
+ /**
+ * Get the default pixel data format, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}.
+ * <p>
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}.
+ * </p>
+ */
+ public abstract int getDefaultPixelDataFormat();
+
/**
* @return The extension implementing the GLDebugOutput feature,
- * either <i>GL_ARB_debug_output</i> or <i>GL_AMD_debug_output</i>.
+ * either {@link GLExtensions#ARB_debug_output} or {@link GLExtensions#AMD_debug_output}.
* If unavailable or called before initialized via {@link #makeCurrent()}, <i>null</i> is returned.
*/
public abstract String getGLDebugMessageExtension();
/**
- * @return the current synchronous debug behavior via
- * @see #setSynchronous(boolean)
+ * @return the current synchronous debug behavior, set via {@link #setGLDebugSynchronous(boolean)}.
*/
public abstract boolean isGLDebugSynchronous();
/**
* Enables or disables the synchronous debug behavior via
- * {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB glEnable/glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB)},
- * if extension is {@link #GL_ARB_debug_output}.
- * There is no equivalent for {@link #GL_AMD_debug_output}.
- * <p> The default is <code>true</code>, ie {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB}.</p>
+ * {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS glEnable/glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS)},
+ * if extension is {@link GLExtensions#ARB_debug_output}.
+ * There is no equivalent for {@link GLExtensions#AMD_debug_output}.
+ * <p> The default is <code>true</code>, ie {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS}.</p>
+ * @link {@link #isGLDebugSynchronous()}
*/
public abstract void setGLDebugSynchronous(boolean synchronous);
@@ -872,8 +1394,8 @@ public abstract class GLContext {
public abstract boolean isGLDebugMessageEnabled();
/**
- * Enables or disables the GLDebugOutput feature of extension <i>GL_ARB_debug_output</i>
- * or <i>GL_AMD_debug_output</i>, if available.
+ * Enables or disables the GLDebugOutput feature of extension {@link GLExtensions#ARB_debug_output}
+ * or {@link GLExtensions#AMD_debug_output}, if available.
*
* <p>To enable the GLDebugOutput feature {@link #enableGLDebugMessage(boolean) enableGLDebugMessage(true)}
* or {@link #setContextCreationFlags(int) setContextCreationFlags}({@link GLContext#CTX_OPTION_DEBUG})
@@ -898,7 +1420,7 @@ public abstract class GLContext {
/**
* Add {@link GLDebugListener}.<br>
*
- * @param listener {@link GLDebugListener} handling {@GLDebugMessage}s
+ * @param listener {@link GLDebugListener} handling {@link GLDebugMessage}s
* @see #enableGLDebugMessage(boolean)
* @see #removeGLDebugListener(GLDebugListener)
*/
@@ -907,28 +1429,28 @@ public abstract class GLContext {
/**
* Remove {@link GLDebugListener}.<br>
*
- * @param listener {@link GLDebugListener} handling {@GLDebugMessage}s
+ * @param listener {@link GLDebugListener} handling {@link GLDebugMessage}s
* @see #enableGLDebugMessage(boolean)
* @see #addGLDebugListener(GLDebugListener)
*/
public abstract void removeGLDebugListener(GLDebugListener listener);
/**
- * Generic entry for {@link GL2GL3#glDebugMessageControlARB(int, int, int, int, IntBuffer, boolean)}
+ * Generic entry for {@link GL2GL3#glDebugMessageControl(int, int, int, int, IntBuffer, boolean)}
* and {@link GL2GL3#glDebugMessageEnableAMD(int, int, int, IntBuffer, boolean)} of the GLDebugOutput feature.
* @see #enableGLDebugMessage(boolean)
*/
public abstract void glDebugMessageControl(int source, int type, int severity, int count, IntBuffer ids, boolean enabled);
/**
- * Generic entry for {@link GL2GL3#glDebugMessageControlARB(int, int, int, int, int[], int, boolean)}
+ * Generic entry for {@link GL2GL3#glDebugMessageControl(int, int, int, int, int[], int, boolean)}
* and {@link GL2GL3#glDebugMessageEnableAMD(int, int, int, int[], int, boolean)} of the GLDebugOutput feature.
* @see #enableGLDebugMessage(boolean)
*/
public abstract void glDebugMessageControl(int source, int type, int severity, int count, int[] ids, int ids_offset, boolean enabled);
/**
- * Generic entry for {@link GL2GL3#glDebugMessageInsertARB(int, int, int, int, int, String)}
+ * Generic entry for {@link GL2GL3#glDebugMessageInsert(int, int, int, int, int, String)}
* and {@link GL2GL3#glDebugMessageInsertAMD(int, int, int, int, String)} of the GLDebugOutput feature.
* @see #enableGLDebugMessage(boolean)
*/
@@ -939,51 +1461,135 @@ public abstract class GLContext {
/* 1.*/ { 0, 1, 2, 3, 4, 5 },
/* 2.*/ { 0, 1 },
/* 3.*/ { 0, 1, 2, 3 },
- /* 4.*/ { 0, 1, 2 } };
+ /* 4.*/ { 0, 1, 2, 3, 4 } };
+
+ public static final int ES_VERSIONS[][] = {
+ /* 0.*/ { -1 },
+ /* 1.*/ { 0, 1 },
+ /* 2.*/ { 0 },
+ /* 3.*/ { 0 } };
- public static final int getMaxMajor() {
- return GL_VERSIONS.length-1;
+ public static final int getMaxMajor(final int ctxProfile) {
+ return ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ? ES_VERSIONS.length-1 : GL_VERSIONS.length-1;
}
- public static final int getMaxMinor(int major) {
- if(1>major || major>=GL_VERSIONS.length) return -1;
- return GL_VERSIONS[major].length-1;
+ public static final int getMaxMinor(final int ctxProfile, final int major) {
+ if( 1>major ) {
+ return -1;
+ }
+ if( ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ) {
+ if( major>=ES_VERSIONS.length ) return -1;
+ return ES_VERSIONS[major].length-1;
+ } else {
+ if( major>=GL_VERSIONS.length ) return -1;
+ return GL_VERSIONS[major].length-1;
+ }
}
- public static final boolean isValidGLVersion(int major, int minor) {
- if(1>major || major>=GL_VERSIONS.length) return false;
- if(0>minor || minor>=GL_VERSIONS[major].length) return false;
+ /**
+ * Returns true, if the major.minor is not inferior to the lowest
+ * valid version and does not exceed the highest known major number by more than one.
+ * <p>
+ * The minor version number is ignored by the upper limit validation
+ * and the major version number may exceed by one.
+ * </p>
+ * <p>
+ * The upper limit check is relaxed since we don't want to cut-off
+ * unforseen new GL version since the release of JOGL.
+ * </p>
+ * <p>
+ * Hence it is important to iterate through GL version from the upper limit
+ * and {@link #decrementGLVersion(int, int[], int[])} until invalid.
+ * </p>
+ */
+ public static final boolean isValidGLVersion(final int ctxProfile, final int major, final int minor) {
+ if( 1>major || 0>minor ) {
+ return false;
+ }
+ if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
+ if( major >= ES_VERSIONS.length + 1 ) return false;
+ } else {
+ if( major>=GL_VERSIONS.length + 1 ) return false;
+ }
return true;
}
- public static final boolean decrementGLVersion(int major[], int minor[]) {
- if(null==major || major.length<1 ||null==minor || minor.length<1) {
- throw new GLException("invalid array arguments");
- }
- int m = major[0];
- int n = minor[0];
- if(!isValidGLVersion(m, n)) return false;
-
- // decrement ..
- n -= 1;
- if(n < 0) {
- m -= 1;
- n = GL_VERSIONS[m].length-1;
+ /**
+ * Clip the given GL version to the maximum known valid version if exceeding.
+ * @return true if clipped, i.e. given value exceeds maximum, otherwise false.
+ */
+ public static final boolean clipGLVersion(final int ctxProfile, final int major[], final int minor[]) {
+ final int m = major[0];
+ final int n = minor[0];
+
+ if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
+ if( m >= ES_VERSIONS.length ) {
+ major[0] = ES_VERSIONS.length - 1;
+ minor[0] = ES_VERSIONS[major[0]].length - 1;
+ return true;
+ }
+ if( n >= ES_VERSIONS[m].length ) {
+ minor[0] = ES_VERSIONS[m].length - 1;
+ return true;
+ }
+ } else if( m >= GL_VERSIONS.length ) { // !isES
+ major[0] = GL_VERSIONS.length - 1;
+ minor[0] = GL_VERSIONS[major[0]].length - 1;
+ return true;
+ } else if( n >= GL_VERSIONS[m].length ) { // !isES
+ minor[0] = GL_VERSIONS[m].length - 1;
+ return true;
}
- if(!isValidGLVersion(m, n)) return false;
- major[0]=m;
- minor[0]=n;
+ return false;
+ }
+ /**
+ * Decrement the given GL version by one
+ * and return true if still valid, otherwise false.
+ * <p>
+ * If the given version exceeds the maximum known valid version,
+ * it is {@link #clipGLVersion(int, int[], int[]) clipped} and
+ * true is returned.
+ * </p>
+ *
+ * @param ctxProfile
+ * @param major
+ * @param minor
+ * @return
+ */
+ public static final boolean decrementGLVersion(final int ctxProfile, final int major[], final int minor[]) {
+ if( !clipGLVersion(ctxProfile, major, minor) ) {
+ int m = major[0];
+ int n = minor[0] - 1;
+ if(n < 0) {
+ if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
+ if( m >= 3 ) {
+ m -= 1;
+ } else {
+ m = 0; // major decr [1,2] -> 0
+ }
+ n = ES_VERSIONS[m].length-1;
+ } else {
+ m -= 1;
+ n = GL_VERSIONS[m].length-1;
+ }
+ }
+ if( !isValidGLVersion(ctxProfile, m, n) ) {
+ return false;
+ }
+ major[0]=m;
+ minor[0]=n;
+ }
return true;
}
- protected static int composeBits(int a8, int b8, int c16) {
+ protected static int composeBits(final int a8, final int b8, final int c16) {
return ( ( a8 & 0x000000FF ) << 24 ) |
( ( b8 & 0x000000FF ) << 16 ) |
( ( c16 & 0x0000FFFF ) ) ;
}
- private static void validateProfileBits(int bits, String argName) {
+ private static void validateProfileBits(final int bits, final String argName) {
int num = 0;
if( 0 != ( CTX_PROFILE_COMPAT & bits ) ) { num++; }
if( 0 != ( CTX_PROFILE_CORE & bits ) ) { num++; }
@@ -1000,12 +1606,12 @@ public abstract class GLContext {
/**
* @see #getDeviceVersionAvailableKey(javax.media.nativewindow.AbstractGraphicsDevice, int, int)
*/
- protected static /*final*/ HashMap<String, Integer> deviceVersionAvailable = new HashMap<String, Integer>();
+ protected static final IdentityHashMap<String, Integer> deviceVersionAvailable = new IdentityHashMap<String, Integer>();
/**
* @see #getUniqueDeviceString(javax.media.nativewindow.AbstractGraphicsDevice)
*/
- private static /*final*/ HashSet<String> deviceVersionsAvailableSet = new HashSet<String>();
+ private static final IdentityHashMap<String, String> deviceVersionsAvailableSet = new IdentityHashMap<String, String>();
/** clears the device/context mappings as well as the GL/GLX proc address tables. */
protected static void shutdown() {
@@ -1014,33 +1620,37 @@ public abstract class GLContext {
GLContextImpl.shutdownImpl(); // well ..
}
- protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+ protected static boolean getAvailableGLVersionsSet(final AbstractGraphicsDevice device) {
synchronized ( deviceVersionsAvailableSet ) {
- return deviceVersionsAvailableSet.contains(device.getUniqueID());
+ return deviceVersionsAvailableSet.containsKey(device.getUniqueID());
}
}
- protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+ protected static void setAvailableGLVersionsSet(final AbstractGraphicsDevice device) {
synchronized ( deviceVersionsAvailableSet ) {
- String devKey = device.getUniqueID();
- if ( deviceVersionsAvailableSet.contains(devKey) ) {
+ final String devKey = device.getUniqueID();
+ if( null != deviceVersionsAvailableSet.put(devKey, devKey) ) {
throw new InternalError("Already set: "+devKey);
}
- deviceVersionsAvailableSet.add(devKey);
if (DEBUG) {
System.err.println(getThreadName() + ": createContextARB: SET mappedVersionsAvailableSet "+devKey);
- System.err.println(GLContext.dumpAvailableGLVersions(null).toString());
+ System.err.println(GLContext.dumpAvailableGLVersions(null).toString());
}
}
}
- protected static String getDeviceVersionAvailableKey(AbstractGraphicsDevice device, int major, int profile) {
- return device.getUniqueID() + "-" + toHexString(composeBits(major, profile, 0));
+ /**
+ * Returns a unique String object using {@link String#intern()} for the given arguments,
+ * which object reference itself can be used as a key.
+ */
+ protected static String getDeviceVersionAvailableKey(final AbstractGraphicsDevice device, final int major, final int profile) {
+ final String r = device.getUniqueID() + "-" + toHexString(composeBits(major, profile, 0));
+ return r.intern();
}
/**
- * Called by {@link jogamp.opengl.GLContextImpl#createContextARBMapVersionsAvailable} not intended to be used by
- * implementations. However, if {@link #createContextARB} is not being used within
+ * Called by {@link jogamp.opengl.GLContextImpl#createContextARBMapVersionsAvailable(int,int)} not intended to be used by
+ * implementations. However, if {@link jogamp.opengl.GLContextImpl#createContextARB(long, boolean)} is not being used within
* {@link javax.media.opengl.GLDrawableFactory#getOrCreateSharedContext(javax.media.nativewindow.AbstractGraphicsDevice)},
* GLProfile has to map the available versions.
*
@@ -1050,8 +1660,8 @@ public abstract class GLContext {
*
* @see #createContextARBMapVersionsAvailable
*/
- protected static Integer mapAvailableGLVersion(AbstractGraphicsDevice device,
- int reqMajor, int profile, int resMajor, int resMinor, int resCtp)
+ protected static Integer mapAvailableGLVersion(final AbstractGraphicsDevice device,
+ final int reqMajor, final int profile, final int resMajor, final int resMinor, int resCtp)
{
validateProfileBits(profile, "profile");
validateProfileBits(resCtp, "resCtp");
@@ -1063,21 +1673,21 @@ public abstract class GLContext {
System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null));
// Thread.dumpStack();
}
- final String key = getDeviceVersionAvailableKey(device, reqMajor, profile);
- final Integer val = new Integer(composeBits(resMajor, resMinor, resCtp));
+ final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, profile);
+ final Integer val = Integer.valueOf(composeBits(resMajor, resMinor, resCtp));
synchronized(deviceVersionAvailable) {
- return deviceVersionAvailable.put( key, val );
+ return deviceVersionAvailable.put( objectKey, val );
}
}
- protected static StringBuffer dumpAvailableGLVersions(StringBuffer sb) {
+ protected static StringBuilder dumpAvailableGLVersions(StringBuilder sb) {
if(null == sb) {
- sb = new StringBuffer();
+ sb = new StringBuilder();
}
synchronized(deviceVersionAvailable) {
final Set<String> keys = deviceVersionAvailable.keySet();
boolean needsSeparator = false;
- for(Iterator<String> i = keys.iterator(); i.hasNext(); ) {
+ for(final Iterator<String> i = keys.iterator(); i.hasNext(); ) {
if(needsSeparator) {
sb.append(Platform.getNewline());
}
@@ -1086,8 +1696,8 @@ public abstract class GLContext {
final Integer valI = deviceVersionAvailable.get(key);
if(null != valI) {
final int bits32 = valI.intValue();
- final int major = ( bits32 & 0xFF000000 ) >> 24 ;
- final int minor = ( bits32 & 0x00FF0000 ) >> 16 ;
+ final int major = ( bits32 & 0xFF000000 ) >>> 24 ;
+ final int minor = ( bits32 & 0x00FF0000 ) >>> 16 ;
final int ctp = ( bits32 & 0x0000FFFF ) ;
sb.append(GLContext.getGLVersion(major, minor, ctp, null));
} else {
@@ -1105,15 +1715,15 @@ public abstract class GLContext {
* @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
* @return the available GL version as encoded with {@link #composeBits(int, int, int), otherwise <code>null</code>
*/
- protected static Integer getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int reqProfile) {
- String key = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
+ protected static Integer getAvailableGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile) {
+ final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
Integer val;
synchronized(deviceVersionAvailable) {
- val = deviceVersionAvailable.get( key );
+ val = deviceVersionAvailable.get( objectKey );
}
return val;
}
-
+
/**
* @param reqMajor Key Value either 1, 2, 3 or 4
* @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
@@ -1121,8 +1731,8 @@ public abstract class GLContext {
* @param minor if not null, returns the used minor version
* @param ctp if not null, returns the used context profile
*/
- protected static boolean getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int reqProfile,
- int[] major, int minor[], int ctp[]) {
+ protected static boolean getAvailableGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile,
+ final int[] major, final int minor[], final int ctp[]) {
final Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
if(null==valI) {
@@ -1132,10 +1742,10 @@ public abstract class GLContext {
final int bits32 = valI.intValue();
if(null!=major) {
- major[0] = ( bits32 & 0xFF000000 ) >> 24 ;
+ major[0] = ( bits32 & 0xFF000000 ) >>> 24 ;
}
if(null!=minor) {
- minor[0] = ( bits32 & 0x00FF0000 ) >> 16 ;
+ minor[0] = ( bits32 & 0x00FF0000 ) >>> 16 ;
}
if(null!=ctp) {
ctp[0] = ( bits32 & 0x0000FFFF ) ;
@@ -1147,7 +1757,7 @@ public abstract class GLContext {
* returns the highest GLProfile string regarding the implementation version and context profile bits.
* @throws GLException if version and context profile bits could not be mapped to a GLProfile
*/
- protected static String getGLProfile(int major, int minor, int ctp)
+ protected static String getGLProfile(final int major, final int minor, final int ctp)
throws GLException {
if(0 != ( CTX_PROFILE_COMPAT & ctp )) {
if(major >= 4) { return GLProfile.GL4bc; }
@@ -1157,7 +1767,8 @@ public abstract class GLContext {
if(major >= 4) { return GLProfile.GL4; }
else if(major == 3 && minor >= 1) { return GLProfile.GL3; }
} else if(0 != ( CTX_PROFILE_ES & ctp )) {
- if(major == 2) { return GLProfile.GLES2; }
+ if(major == 3) { return GLProfile.GLES3; }
+ else if(major == 2) { return GLProfile.GLES2; }
else if(major == 1) { return GLProfile.GLES1; }
}
throw new GLException("Unhandled OpenGL version/profile: "+GLContext.getGLVersion(major, minor, ctp, null));
@@ -1166,11 +1777,11 @@ public abstract class GLContext {
/**
* Returns the GLProfile's major version number at reqMajorCTP[0] and it's context property (CTP) at reqMajorCTP[1] for availability mapping request.
*/
- protected static final void getRequestMajorAndCompat(final GLProfile glp, int[/*2*/] reqMajorCTP) {
+ protected static final void getRequestMajorAndCompat(final GLProfile glp, final int[/*2*/] reqMajorCTP) {
final GLProfile glpImpl = glp.getImpl();
- if(glpImpl.isGL4()) {
+ if( glpImpl.isGL4() ) {
reqMajorCTP[0]=4;
- } else if (glpImpl.isGL3()) {
+ } else if ( glpImpl.isGL3() || glpImpl.isGLES3() ) {
reqMajorCTP[0]=3;
} else if (glpImpl.isGLES1()) {
reqMajorCTP[0]=1;
@@ -1185,7 +1796,7 @@ public abstract class GLContext {
reqMajorCTP[1]=CTX_PROFILE_CORE;
}
}
-
+
/**
* @param device the device the context profile is being requested for
* @param GLProfile the GLProfile the context profile is being requested for
@@ -1194,10 +1805,10 @@ public abstract class GLContext {
protected static final int getAvailableContextProperties(final AbstractGraphicsDevice device, final GLProfile glp) {
final int[] reqMajorCTP = new int[] { 0, 0 };
getRequestMajorAndCompat(glp, reqMajorCTP);
-
- int _major[] = { 0 };
- int _minor[] = { 0 };
- int _ctp[] = { 0 };
+
+ final int _major[] = { 0 };
+ final int _minor[] = { 0 };
+ final int _ctp[] = { 0 };
if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1], _major, _minor, _ctp)) {
return _ctp[0];
}
@@ -1208,15 +1819,27 @@ public abstract class GLContext {
* @param device the device the profile is being requested
* @param major Key Value either 1, 2, 3 or 4
* @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
- * @return the highest GLProfile regarding availability, version and profile bits.
+ * @return the highest GLProfile for the device regarding availability, version and profile bits.
+ */
+ protected static GLProfile getAvailableGLProfile(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)
+ throws GLException {
+ final String glpName = getAvailableGLProfileName(device, reqMajor, reqProfile);
+ return null != glpName ? GLProfile.get(device, glpName) : null;
+ }
+
+ /**
+ * @param device the device the profile is being requested
+ * @param major Key Value either 1, 2, 3 or 4
+ * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ * @return the highest GLProfile name for the device regarding availability, version and profile bits.
*/
- protected static GLProfile getAvailableGLProfile(AbstractGraphicsDevice device, int reqMajor, int reqProfile)
+ /* package */ static String getAvailableGLProfileName(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)
throws GLException {
- int major[] = { 0 };
- int minor[] = { 0 };
- int ctp[] = { 0 };
+ final int major[] = { 0 };
+ final int minor[] = { 0 };
+ final int ctp[] = { 0 };
if(GLContext.getAvailableGLVersion(device, reqMajor, reqProfile, major, minor, ctp)) {
- return GLProfile.get(GLContext.getGLProfile(major[0], minor[0], ctp[0]));
+ return GLContext.getGLProfile(major[0], minor[0], ctp[0]);
}
return null;
}
@@ -1226,10 +1849,10 @@ public abstract class GLContext {
* @param major Key Value either 1, 2, 3 or 4
* @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
*/
- protected static String getAvailableGLVersionAsString(AbstractGraphicsDevice device, int major, int profile) {
- int _major[] = { 0 };
- int _minor[] = { 0 };
- int _ctp[] = { 0 };
+ protected static String getAvailableGLVersionAsString(final AbstractGraphicsDevice device, final int major, final int profile) {
+ final int _major[] = { 0 };
+ final int _minor[] = { 0 };
+ final int _ctp[] = { 0 };
if(getAvailableGLVersion(device, major, profile, _major, _minor, _ctp)) {
return getGLVersion(_major[0], _minor[0], _ctp[0], null);
}
@@ -1240,7 +1863,7 @@ public abstract class GLContext {
* Returns true if it is possible to create an <i>framebuffer object</i> (FBO).
* <p>
* FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
- * </p>
+ * </p>
* <p>
* FBO support is queried as described in {@link #hasBasicFBOSupport()}.
* </p>
@@ -1249,19 +1872,19 @@ public abstract class GLContext {
* @param glp {@link GLProfile} to check for FBO capabilities
* @see GLContext#hasBasicFBOSupport()
*/
- public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) {
+ public static final boolean isFBOAvailable(final AbstractGraphicsDevice device, final GLProfile glp) {
return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) );
}
-
+
/**
- * @return <code>1</code> if using a hardware rasterizer, <code>0</code> if using a software rasterizer and <code>-1</code> if not determined yet.
+ * @return <code>1</code> if using a hardware rasterizer, <code>0</code> if using a software rasterizer and <code>-1</code> if not determined yet.
* @see GLContext#isHardwareRasterizer()
- * @see GLProfile#isHardwareRasterizer()
+ * @see GLProfile#isHardwareRasterizer()
*/
- public static final int isHardwareRasterizer(AbstractGraphicsDevice device, GLProfile glp) {
+ public static final int isHardwareRasterizer(final AbstractGraphicsDevice device, final GLProfile glp) {
final int r;
final int ctp = getAvailableContextProperties(device, glp);
- if(0 == ctp) {
+ if(0 == ctp) {
r = -1;
} else if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
r = 1;
@@ -1270,7 +1893,7 @@ public abstract class GLContext {
}
return r;
}
-
+
/**
* @param device the device to request whether the profile is available for
* @param reqMajor Key Value either 1, 2, 3 or 4
@@ -1278,8 +1901,8 @@ public abstract class GLContext {
* @param isHardware return value of one boolean, whether the profile is a hardware rasterizer or not
* @return true if the requested GL version is available regardless of a software or hardware rasterizer, otherwise false.
*/
- protected static boolean isGLVersionAvailable(AbstractGraphicsDevice device, int reqMajor, int reqProfile, boolean isHardware[]) {
- Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
+ protected static boolean isGLVersionAvailable(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile, final boolean isHardware[]) {
+ final Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
if(null==valI) {
return false;
}
@@ -1287,49 +1910,79 @@ public abstract class GLContext {
return true;
}
- public static boolean isGLES1Available(AbstractGraphicsDevice device, boolean isHardware[]) {
+ public static boolean isGLES1Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
return isGLVersionAvailable(device, 1, GLContext.CTX_PROFILE_ES, isHardware);
}
- public static boolean isGLES2Available(AbstractGraphicsDevice device, boolean isHardware[]) {
+ public static boolean isGLES2Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES, isHardware);
}
- public static boolean isGL4bcAvailable(AbstractGraphicsDevice device, boolean isHardware[]) {
+ public static boolean isGLES3Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 3, GLContext.CTX_PROFILE_ES, isHardware);
+ }
+
+ /**
+ * Returns true if a ES3 compatible profile is available,
+ * i.e. either a &ge; 4.3 context or a &ge; 3.1 context supporting <code>GL_ARB_ES3_compatibility</code>,
+ * otherwise false.
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ */
+ public static final boolean isGLES3CompatibleAvailable(final AbstractGraphicsDevice device) {
+ final int major[] = { 0 };
+ final int minor[] = { 0 };
+ final int ctp[] = { 0 };
+ boolean ok;
+
+ ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_ES, major, minor, ctp);
+ if( !ok ) {
+ ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, major, minor, ctp);
+ }
+ if( !ok ) {
+ GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_COMPAT, major, minor, ctp);
+ }
+ return 0 != ( ctp[0] & CTX_IMPL_ES3_COMPAT );
+ }
+
+ public static boolean isGL4bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[]) {
return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT, isHardware);
}
- public static boolean isGL4Available(AbstractGraphicsDevice device, boolean isHardware[]) {
+ public static boolean isGL4Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
return isGLVersionAvailable(device, 4, CTX_PROFILE_CORE, isHardware);
}
- public static boolean isGL3bcAvailable(AbstractGraphicsDevice device, boolean isHardware[]) {
+ public static boolean isGL3bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[]) {
return isGLVersionAvailable(device, 3, CTX_PROFILE_COMPAT, isHardware);
}
- public static boolean isGL3Available(AbstractGraphicsDevice device, boolean isHardware[]) {
+ public static boolean isGL3Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
return isGLVersionAvailable(device, 3, CTX_PROFILE_CORE, isHardware);
}
- public static boolean isGL2Available(AbstractGraphicsDevice device, boolean isHardware[]) {
+ public static boolean isGL2Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT, isHardware);
}
- protected static String getGLVersion(int major, int minor, int ctp, String gl_version) {
+ protected static String getGLVersion(final int major, final int minor, final int ctp, final String gl_version) {
boolean needColon = false;
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append(major);
sb.append(".");
sb.append(minor);
sb.append(" (");
needColon = appendString(sb, "ES profile", needColon, 0 != ( CTX_PROFILE_ES & ctp ));
- needColon = appendString(sb, "Compatibility profile", needColon, 0 != ( CTX_PROFILE_COMPAT & ctp ));
+ needColon = appendString(sb, "Compat profile", needColon, 0 != ( CTX_PROFILE_COMPAT & ctp ));
needColon = appendString(sb, "Core profile", needColon, 0 != ( CTX_PROFILE_CORE & ctp ));
needColon = appendString(sb, "forward", needColon, 0 != ( CTX_OPTION_FORWARD & ctp ));
needColon = appendString(sb, "arb", needColon, 0 != ( CTX_IS_ARB_CREATED & ctp ));
needColon = appendString(sb, "debug", needColon, 0 != ( CTX_OPTION_DEBUG & ctp ));
- needColon = appendString(sb, "ES2 compatible", needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp ));
+ needColon = appendString(sb, "ES2 compat", needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp ));
+ needColon = appendString(sb, "ES3 compat", needColon, 0 != ( CTX_IMPL_ES3_COMPAT & ctp ));
needColon = appendString(sb, "FBO", needColon, 0 != ( CTX_IMPL_FBO & ctp ));
+ needColon = appendString(sb, "FP32 compat", needColon, 0 != ( CTX_IMPL_FP32_COMPAT_API & ctp ));
if( 0 != ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
needColon = appendString(sb, "software", needColon, true);
} else {
@@ -1347,15 +2000,15 @@ public abstract class GLContext {
// internal string utils
//
- protected static String toHexString(int hex) {
+ protected static String toHexString(final int hex) {
return "0x" + Integer.toHexString(hex);
}
- protected static String toHexString(long hex) {
+ protected static String toHexString(final long hex) {
return "0x" + Long.toHexString(hex);
}
- private static boolean appendString(StringBuilder sb, String string, boolean needColon, boolean condition) {
+ private static boolean appendString(final StringBuilder sb, final String string, boolean needColon, final boolean condition) {
if(condition) {
if(needColon) {
sb.append(", ");
@@ -1366,9 +2019,7 @@ public abstract class GLContext {
return needColon;
}
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
}
diff --git a/src/jogl/classes/javax/media/opengl/GLDebugListener.java b/src/jogl/classes/javax/media/opengl/GLDebugListener.java
index 8887d022a..ec7f7cec1 100644
--- a/src/jogl/classes/javax/media/opengl/GLDebugListener.java
+++ b/src/jogl/classes/javax/media/opengl/GLDebugListener.java
@@ -29,16 +29,16 @@ package javax.media.opengl;
/**
* Listener for {@link GLDebugMessage}s.
- *
+ *
* <p>One can enable GLDebugOutput via {@link GLContext#enableGLDebugMessage(boolean)}
* and add listeners via {@link GLContext#addGLDebugListener(GLDebugListener)}.
*/
public interface GLDebugListener {
- /**
+ /**
* Handle {@link GLDebugMessage} message sent from native GL implementation.
- *
+ *
* <p>Since this method is invoked directly by the GL implementation, it shall
* return as fast as possible.</p>
*/
- void messageSent(GLDebugMessage event);
+ void messageSent(GLDebugMessage event);
}
diff --git a/src/jogl/classes/javax/media/opengl/GLDebugMessage.java b/src/jogl/classes/javax/media/opengl/GLDebugMessage.java
index 3ab0683c6..325345012 100644
--- a/src/jogl/classes/javax/media/opengl/GLDebugMessage.java
+++ b/src/jogl/classes/javax/media/opengl/GLDebugMessage.java
@@ -29,15 +29,19 @@ package javax.media.opengl;
import com.jogamp.common.os.Platform;
+/**
+ * OpenGL debug message generated by the driver
+ * and delivered via {@link GLDebugListener}.
+ */
public class GLDebugMessage {
final GLContext source;
- final long when;
+ final long when;
final int dbgSource;
final int dbgType;
final int dbgId;
final int dbgSeverity;
final String dbgMsg;
-
+
/**
* @param source The source of the event
* @param when The time of the event
@@ -47,7 +51,7 @@ public class GLDebugMessage {
* @param dbgSeverity The ARB severity level
* @param dbgMsg The debug message
*/
- public GLDebugMessage(GLContext source, long when, int dbgSource, int dbgType, int dbgId, int dbgSeverity, String dbgMsg) {
+ public GLDebugMessage(final GLContext source, final long when, final int dbgSource, final int dbgType, final int dbgId, final int dbgSeverity, final String dbgMsg) {
this.source = source;
this.when = when;
this.dbgSource = dbgSource;
@@ -56,9 +60,9 @@ public class GLDebugMessage {
this.dbgSeverity = dbgSeverity;
this.dbgMsg = dbgMsg;
}
-
+
/**
- *
+ *
* @param source
* @param when
* @param dbgId
@@ -67,90 +71,90 @@ public class GLDebugMessage {
* @param dbgMsg
* @return
*/
- public static GLDebugMessage translateAMDEvent(GLContext source, long when, int dbgId, int amdDbgCategory, int dbgSeverity, String dbgMsg) {
+ public static GLDebugMessage translateAMDEvent(final GLContext source, final long when, final int dbgId, final int amdDbgCategory, final int dbgSeverity, final String dbgMsg) {
int dbgSource, dbgType;
-
+
// AMD category == ARB source/type
switch(amdDbgCategory) {
- case GL2GL3.GL_DEBUG_CATEGORY_API_ERROR_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_API_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_ERROR_ARB;
+ case GL2GL3.GL_DEBUG_CATEGORY_API_ERROR_AMD:
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_API;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_ERROR;
break;
//
// def source / other type
//
-
- case GL2GL3.GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER_ARB;
+
+ case GL2GL3.GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD:
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_WINDOW_SYSTEM;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_OTHER;
break;
-
+
case GL2GL3.GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_SHADER_COMPILER_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER_ARB;
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_SHADER_COMPILER;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_OTHER;
break;
-
+
case GL2GL3.GL_DEBUG_CATEGORY_APPLICATION_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_APPLICATION_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER_ARB;
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_APPLICATION;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_OTHER;
break;
-
-
+
+
//
// other source / def type
//
-
+
case GL2GL3.GL_DEBUG_CATEGORY_DEPRECATION_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB;
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR;
break;
-
+
case GL2GL3.GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB;
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR;
break;
-
+
case GL2GL3.GL_DEBUG_CATEGORY_PERFORMANCE_AMD:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_PERFORMANCE_ARB;
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_PERFORMANCE;
break;
-
- case GL2GL3.GL_DEBUG_CATEGORY_OTHER_AMD:
+
+ case GL2GL3.GL_DEBUG_CATEGORY_OTHER_AMD:
default:
- dbgSource = GL2GL3.GL_DEBUG_SOURCE_OTHER_ARB;
- dbgType = GL2GL3.GL_DEBUG_TYPE_OTHER_ARB;
+ dbgSource = GL2ES2.GL_DEBUG_SOURCE_OTHER;
+ dbgType = GL2ES2.GL_DEBUG_TYPE_OTHER;
}
-
- return new GLDebugMessage(source, when, dbgSource, dbgType, dbgId, dbgSeverity, dbgMsg);
+
+ return new GLDebugMessage(source, when, dbgSource, dbgType, dbgId, dbgSeverity, dbgMsg);
}
- public static int translateARB2AMDCategory(int dbgSource, int dbgType) {
+ public static int translateARB2AMDCategory(final int dbgSource, final int dbgType) {
switch (dbgSource) {
- case GL2GL3.GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
- return GL2GL3.GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD;
-
- case GL2GL3.GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
+ case GL2ES2.GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+ return GL2GL3.GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD;
+
+ case GL2ES2.GL_DEBUG_SOURCE_SHADER_COMPILER:
return GL2GL3.GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD;
-
- case GL2GL3.GL_DEBUG_SOURCE_APPLICATION_ARB:
+
+ case GL2ES2.GL_DEBUG_SOURCE_APPLICATION:
return GL2GL3.GL_DEBUG_CATEGORY_APPLICATION_AMD;
}
-
+
switch(dbgType) {
- case GL2GL3.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
+ case GL2ES2.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
return GL2GL3.GL_DEBUG_CATEGORY_DEPRECATION_AMD;
-
- case GL2GL3.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
+
+ case GL2ES2.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
return GL2GL3.GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD;
-
- case GL2GL3.GL_DEBUG_TYPE_PERFORMANCE_ARB:
+
+ case GL2ES2.GL_DEBUG_TYPE_PERFORMANCE:
return GL2GL3.GL_DEBUG_CATEGORY_PERFORMANCE_AMD;
}
-
- return GL2GL3.GL_DEBUG_CATEGORY_OTHER_AMD;
+
+ return GL2GL3.GL_DEBUG_CATEGORY_OTHER_AMD;
}
-
+
public GLContext getSource() {
return source;
}
@@ -158,7 +162,7 @@ public class GLDebugMessage {
public long getWhen() {
return when;
}
-
+
public int getDbgSource() {
return dbgSource;
}
@@ -178,14 +182,14 @@ public class GLDebugMessage {
public String getDbgMsg() {
return dbgMsg;
}
-
+
public StringBuilder toString(StringBuilder sb) {
- final String crtab = Platform.getNewline()+"\t";
+ final String crtab = Platform.getNewline()+"\t";
if(null==sb) {
sb = new StringBuilder();
- }
+ }
sb.append("GLDebugEvent[ id ");
- toHexString(sb, dbgId)
+ toHexString(sb, dbgId)
.append(crtab).append("type ").append(getDbgTypeString(dbgType))
.append(crtab).append("severity ").append(getDbgSeverityString(dbgSeverity))
.append(crtab).append("source ").append(getDbgSourceString(dbgSource))
@@ -195,54 +199,55 @@ public class GLDebugMessage {
sb.append(crtab).append("source ").append(source.getGLVersion()).append(" - hash 0x").append(Integer.toHexString(source.hashCode()));
}
sb.append("]");
- return sb;
+ return sb;
}
+ @Override
public String toString() {
return toString(null).toString();
}
-
- public static String getDbgSourceString(int dbgSource) {
+
+ public static String getDbgSourceString(final int dbgSource) {
switch(dbgSource) {
- case GL2GL3.GL_DEBUG_SOURCE_API_ARB: return "GL API";
- case GL2GL3.GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: return "GLSL or extension compiler";
- case GL2GL3.GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: return "Native Windowing binding";
- case GL2GL3.GL_DEBUG_SOURCE_THIRD_PARTY_ARB: return "Third party";
- case GL2GL3.GL_DEBUG_SOURCE_APPLICATION_ARB: return "Application";
- case GL2GL3.GL_DEBUG_SOURCE_OTHER_ARB: return "generic";
+ case GL2ES2.GL_DEBUG_SOURCE_API: return "GL API";
+ case GL2ES2.GL_DEBUG_SOURCE_SHADER_COMPILER: return "GLSL or extension compiler";
+ case GL2ES2.GL_DEBUG_SOURCE_WINDOW_SYSTEM: return "Native Windowing binding";
+ case GL2ES2.GL_DEBUG_SOURCE_THIRD_PARTY: return "Third party";
+ case GL2ES2.GL_DEBUG_SOURCE_APPLICATION: return "Application";
+ case GL2ES2.GL_DEBUG_SOURCE_OTHER: return "generic";
default: return "Unknown (" + toHexString(dbgSource) + ")";
}
}
-
- public static String getDbgTypeString(int dbgType) {
+
+ public static String getDbgTypeString(final int dbgType) {
switch(dbgType) {
- case GL2GL3.GL_DEBUG_TYPE_ERROR_ARB: return "Error";
- case GL2GL3.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: return "Warning: marked for deprecation";
- case GL2GL3.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: return "Warning: undefined behavior";
- case GL2GL3.GL_DEBUG_TYPE_PERFORMANCE_ARB: return "Warning: implementation dependent performance";
- case GL2GL3.GL_DEBUG_TYPE_PORTABILITY_ARB: return "Warning: vendor-specific extension use";
- case GL2GL3.GL_DEBUG_TYPE_OTHER_ARB: return "Warning: generic";
+ case GL2ES2.GL_DEBUG_TYPE_ERROR: return "Error";
+ case GL2ES2.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "Warning: marked for deprecation";
+ case GL2ES2.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "Warning: undefined behavior";
+ case GL2ES2.GL_DEBUG_TYPE_PERFORMANCE: return "Warning: implementation dependent performance";
+ case GL2ES2.GL_DEBUG_TYPE_PORTABILITY: return "Warning: vendor-specific extension use";
+ case GL2ES2.GL_DEBUG_TYPE_OTHER: return "Warning: generic";
default: return "Unknown (" + toHexString(dbgType) + ")";
}
}
-
- public static String getDbgSeverityString(int dbgSeverity) {
+
+ public static String getDbgSeverityString(final int dbgSeverity) {
switch(dbgSeverity) {
- case GL2GL3.GL_DEBUG_SEVERITY_HIGH_ARB: return "High: dangerous undefined behavior";
- case GL2GL3.GL_DEBUG_SEVERITY_MEDIUM_ARB: return "Medium: Severe performance/deprecation/other warnings";
- case GL2GL3.GL_DEBUG_SEVERITY_LOW_ARB: return "Low: Performance warnings (redundancy/undefined)";
+ case GL2ES2.GL_DEBUG_SEVERITY_HIGH: return "High: dangerous undefined behavior";
+ case GL2ES2.GL_DEBUG_SEVERITY_MEDIUM: return "Medium: Severe performance/deprecation/other warnings";
+ case GL2ES2.GL_DEBUG_SEVERITY_LOW: return "Low: Performance warnings (redundancy/undefined)";
default: return "Unknown (" + toHexString(dbgSeverity) + ")";
}
}
-
- public static StringBuilder toHexString(StringBuilder sb, int i) {
+
+ public static StringBuilder toHexString(StringBuilder sb, final int i) {
if(null==sb) {
sb = new StringBuilder();
}
return sb.append("0x").append(Integer.toHexString(i));
}
- public static String toHexString(int i) {
+ public static String toHexString(final int i) {
return "0x"+Integer.toHexString(i);
- }
-
+ }
+
}
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawable.java b/src/jogl/classes/javax/media/opengl/GLDrawable.java
index 10eea2efc..5c881ab73 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawable.java
@@ -42,6 +42,7 @@ package javax.media.opengl;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeSurfaceHolder;
/** An abstraction for an OpenGL rendering target. A GLDrawable's
@@ -50,44 +51,48 @@ import javax.media.nativewindow.NativeSurface;
create an OpenGL context, but all implementations of {@link
GLAutoDrawable} do so upon creation. */
-public interface GLDrawable {
+public interface GLDrawable extends NativeSurfaceHolder {
/**
* Creates a new context for drawing to this drawable that will
- * optionally share display lists and other server-side OpenGL
- * objects with the specified GLContext. <P>
- *
+ * optionally share buffer objects, textures and other server-side OpenGL
+ * objects with the specified GLContext.
+ * <p>
* The GLContext <code>share</code> need not be associated with this
* GLDrawable and may be null if sharing of display lists and other
* objects is not desired. See the note in the overview
- * documentation on
- * <a href="../../../overview-summary.html#SHARING">context sharing</a>.
+ * documentation
+ * <a href="../../../overview-summary.html#SHARING">context sharing</a>
+ * as well as {@link GLSharedContextSetter}.
+ * </p>
*/
public GLContext createContext(GLContext shareWith);
/**
- * Indicates to on-screen GLDrawable implementations whether the
- * underlying window has been created and can be drawn into. End
- * users do not need to call this method; it is not necessary to
- * call <code>setRealized</code> on a GLCanvas, a GLJPanel, or a
- * GLPbuffer, as these perform the appropriate calls on their
- * underlying GLDrawables internally.
- *
- * <P>
- *
+ * Indicates to GLDrawable implementations whether the
+ * underlying {@link NativeSurface surface} has been created and can be drawn into.
+ * <p>
+ * If realized, the {@link #getHandle() drawable handle} may become
+ * valid while it's {@link NativeSurface surface} is being {@link NativeSurface#lockSurface() locked}.
+ * </p>
+ * <p>
+ * End users do not need to call this method; it is not necessary to
+ * call <code>setRealized</code> on a {@link GLAutoDrawable}
+ * as these perform the appropriate calls on their underlying GLDrawables internally.
+ * </p>
+ * <p>
* Developers implementing new OpenGL components for various window
* toolkits need to call this method against GLDrawables obtained
- * from the GLDrawableFactory via the {@link
- * GLDrawableFactory#getGLDrawable
- * GLDrawableFactory.getGLDrawable()} method. It must typically be
+ * from the GLDrawableFactory via the
+ * {@link GLDrawableFactory#createGLDrawable(NativeSurface)} method.
+ * It must typically be
* called with an argument of <code>true</code> when the component
* associated with the GLDrawable is realized and with an argument
* of <code>false</code> just before the component is unrealized.
* For the AWT, this means calling <code>setRealized(true)</code> in
* the <code>addNotify</code> method and with an argument of
* <code>false</code> in the <code>removeNotify</code> method.
- *
- * <P>
- *
+ * </p>
+ * <p>
* <code>GLDrawable</code> implementations should handle multiple
* cycles of <code>setRealized(true)</code> /
* <code>setRealized(false)</code> calls. Most, if not all, Java
@@ -101,12 +106,11 @@ public interface GLDrawable {
* <code>GLDrawable</code> to re-initialize and destroy any
* associated resources as the component becomes realized and
* unrealized, respectively.
- *
- * <P>
- *
+ * </p>
+ * <p>
* With an argument of <code>true</code>,
* the minimum implementation shall call
- * {@link NativeSurface#lockSurface() NativeSurface's lockSurface()} and if successfull:
+ * {@link NativeSurface#lockSurface() NativeSurface's lockSurface()} and if successful:
* <ul>
* <li> Update the {@link GLCapabilities}, which are associated with
* the attached {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.</li>
@@ -115,25 +119,54 @@ public interface GLDrawable {
* This is important since {@link NativeSurface#lockSurface() NativeSurface's lockSurface()}
* ensures resolving the window/surface handles, and the drawable's {@link GLCapabilities}
* might have changed.
- *
- * <P>
- *
+ * </p>
+ * <p>
* Calling this method has no other effects. For example, if
* <code>removeNotify</code> is called on a Canvas implementation
* for which a GLDrawable has been created, it is also necessary to
* destroy all OpenGL contexts associated with that GLDrawable. This
* is not done automatically by the implementation.
+ * </p>
+ * @see #isRealized()
+ * @see #getHandle()
+ * @see NativeSurface#lockSurface()
*/
public void setRealized(boolean realized);
- /** @return true if this drawable is realized, otherwise false */
+ /**
+ * Returns <code>true</code> if this drawable is realized, otherwise <code>true</code>.
+ * <p>
+ * A drawable can be realized and unrealized via {@link #setRealized(boolean)}.
+ * </p>
+ * @see #setRealized(boolean)
+ */
public boolean isRealized();
- /** Returns the current width of this GLDrawable. */
- public int getWidth();
+ /**
+ * Returns the width of this {@link GLDrawable}'s {@link #getNativeSurface() surface} client area in pixel units.
+ * @see NativeSurface#getSurfaceWidth()
+ */
+ public int getSurfaceWidth();
- /** Returns the current height of this GLDrawable. */
- public int getHeight();
+ /**
+ * Returns the height of this {@link GLDrawable}'s {@link #getNativeSurface() surface} client area in pixel units.
+ * @see NativeSurface#getSurfaceHeight()
+ */
+ public int getSurfaceHeight();
+
+ /**
+ * Returns <code>true</code> if the drawable is rendered in
+ * OpenGL's coordinate system, <i>origin at bottom left</i>.
+ * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
+ * <p>
+ * Default impl. is <code>true</code>, i.e. OpenGL coordinate system.
+ * </p>
+ * <p>
+ * Currently only MS-Windows bitmap offscreen drawable uses a non OpenGL orientation and hence returns <code>false</code>.<br/>
+ * This removes the need of a vertical flip when used in AWT or Windows applications.
+ * </p>
+ */
+ public boolean isGLOriented();
/** Swaps the front and back buffers of this drawable. For {@link
GLAutoDrawable} implementations, when automatic buffer swapping
@@ -142,36 +175,71 @@ public interface GLDrawable {
public void swapBuffers() throws GLException;
/** Fetches the {@link GLCapabilitiesImmutable} corresponding to the chosen
- OpenGL capabilities (pixel format / visual / GLProfile) for this drawable.<br>
+ OpenGL capabilities (pixel format / visual / GLProfile) for this drawable.
+ <p>
+ This query only returns the chosen capabilities if {@link #isRealized()}.
+ </p>
+ <p>
On some platforms, the pixel format is not directly associated
with the drawable; a best attempt is made to return a reasonable
- value in this case. <br>
+ value in this case.
+ </p>
+ <p>
This object shall be directly associated to the attached {@link NativeSurface}'s
{@link AbstractGraphicsConfiguration}, and if changes are necessary,
they should reflect those as well.
- @return A copy of the queried object.
+ </p>
+ @return The immutable queried instance.
+ @see #getRequestedGLCapabilities()
*/
public GLCapabilitiesImmutable getChosenGLCapabilities();
+ /** Fetches the {@link GLCapabilitiesImmutable} corresponding to the user requested
+ OpenGL capabilities (pixel format / visual / GLProfile) for this drawable.
+ <p>
+ If {@link #isRealized() realized}, {@link #getChosenGLCapabilities() the chosen capabilities}
+ reflect the actual selected OpenGL capabilities.
+ </p>
+ @return The immutable queried instance.
+ @see #getChosenGLCapabilities()
+ @since 2.2
+ */
+ public GLCapabilitiesImmutable getRequestedGLCapabilities();
+
/** Fetches the {@link GLProfile} for this drawable.
Returns the GLProfile object, no copy.
*/
public GLProfile getGLProfile();
/**
- * Returns the underlying native surface which surface handle
+ * {@inheritDoc}
+ * <p>
+ * Returns the underlying {@link NativeSurface} which {@link NativeSurface#getSurfaceHandle() native handle}
* represents this OpenGL drawable's native resource.
+ * </p>
*
* @see #getHandle()
*/
+ @Override
public NativeSurface getNativeSurface();
/**
- * This is the GL/Windowing drawable handle.<br>
- * It is usually the {@link javax.media.nativewindow.NativeSurface#getSurfaceHandle()},
- * ie the native surface handle of the underlying windowing toolkit.<br>
- * However, on X11/GLX this reflects a GLXDrawable, which represents a GLXWindow, GLXPixmap, or GLXPbuffer.<br>
- * On EGL, this represents the EGLSurface.<br>
+ * Returns the GL drawable handle,
+ * guaranteed to be valid after {@link #setRealized(boolean) realization}
+ * <i>and</i> while it's {@link NativeSurface surface} is being {@link NativeSurface#lockSurface() locked}.
+ * <p>
+ * It is usually identical to the underlying windowing toolkit {@link NativeSurface surface}'s
+ * {@link javax.media.nativewindow.NativeSurface#getSurfaceHandle() handle}
+ * or an intermediate layer to suite GL, e.g. an EGL surface.
+ * </p>
+ * <p>
+ * On EGL it is represented by the EGLSurface.<br>
+ * On X11/GLX it is represented by either the Window XID, GLXPixmap, or GLXPbuffer.<br>
+ * On Windows it is represented by the HDC, which may change with each {@link NativeSurface#lockSurface()}.<br>
+ * </p>
+ * @see #setRealized(boolean)
+ * @see NativeSurface#lockSurface()
+ * @see NativeSurface#unlockSurface()
*/
public long getHandle();
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index b6e7b0576..71568ee76 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,26 +29,24 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package javax.media.opengl;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
-import com.jogamp.common.JogampRuntimeException;
-
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.GLRendererQuirks;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
@@ -61,10 +59,10 @@ import javax.media.nativewindow.UpstreamSurfaceHook;
import jogamp.opengl.Debug;
-/** <P> Provides a virtual machine- and operating system-independent
- mechanism for creating {@link GLDrawable}s. </P>
-
- <P> The {@link javax.media.opengl.GLCapabilities} objects passed
+/** <p> Provides a virtual machine- and operating system-independent
+ mechanism for creating {@link GLDrawable}s.
+ </p>
+ <p> The {@link javax.media.opengl.GLCapabilities} objects passed
in to the various factory methods are used as a hint for the
properties of the returned drawable. The default capabilities
selection algorithm (equivalent to passing in a null {@link
@@ -74,9 +72,10 @@ import jogamp.opengl.Debug;
GLCapabilitiesChooser} which can select from the available pixel
formats. The GLCapabilitiesChooser mechanism may not be supported
by all implementations or on all platforms, in which case any
- passed GLCapabilitiesChooser will be ignored. </P>
+ passed GLCapabilitiesChooser will be ignored.
+ </p>
- <P> Because of the multithreaded nature of the Java platform's
+ <p> Because of the multithreaded nature of the Java platform's
Abstract Window Toolkit, it is typically not possible to immediately
reject a given {@link GLCapabilities} as being unsupportable by
either returning <code>null</code> from the creation routines or
@@ -85,35 +84,30 @@ import jogamp.opengl.Debug;
implementation will cause a {@link GLException} to be raised
during the first repaint of the {@link javax.media.opengl.awt.GLCanvas} or {@link
javax.media.opengl.awt.GLJPanel} if the capabilities can not be met.<br>
- {@link javax.media.opengl.GLPbuffer} are always
- created immediately and their creation will fail with a
- {@link javax.media.opengl.GLException} if errors occur. </P>
+ {@link GLOffscreenAutoDrawable} are created lazily,
+ see {@link #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int) createOffscreenAutoDrawable(..)}.
+ </p>
- <P> The concrete GLDrawableFactory subclass instantiated by {@link
+ <p> The concrete GLDrawableFactory subclass instantiated by {@link
#getFactory getFactory} can be changed by setting the system
property <code>opengl.factory.class.name</code> to the
- fully-qualified name of the desired class. </P>
+ fully-qualified name of the desired class.
+ </p>
*/
public abstract class GLDrawableFactory {
- static final String macosxFactoryClassNameCGL = "jogamp.opengl.macosx.cgl.MacOSXCGLDrawableFactory";
- static final String macosxFactoryClassNameAWTCGL = "jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLDrawableFactory";
-
+ protected static final boolean DEBUG = Debug.debug("GLDrawable");
+
private static volatile boolean isInit = false;
private static GLDrawableFactory eglFactory;
private static GLDrawableFactory nativeOSFactory;
- protected static ArrayList<GLDrawableFactory> glDrawableFactories = new ArrayList<GLDrawableFactory>();
-
- // Shutdown hook mechanism for the factory
- private static boolean factoryShutdownHookRegistered = false;
- private static Thread factoryShutdownHook = null;
- private static volatile boolean isJVMShuttingDown = false;
+ private static ArrayList<GLDrawableFactory> glDrawableFactories = new ArrayList<GLDrawableFactory>();
/**
* Instantiate singleton factories if available, EGLES1, EGLES2 and the OS native ones.
*/
- public static final void initSingleton() {
+ public static final void initSingleton() {
if (!isInit) { // volatile: ok
synchronized (GLDrawableFactory.class) {
if (!isInit) {
@@ -122,40 +116,42 @@ public abstract class GLDrawableFactory {
}
}
}
- }
+ }
private static final void initSingletonImpl() {
- registerFactoryShutdownHook();
-
+ NativeWindowFactory.initSingleton();
+ NativeWindowFactory.addCustomShutdownHook(false /* head */, new Runnable() {
+ @Override
+ public void run() {
+ shutdown0();
+ }
+ });
+
final String nwt = NativeWindowFactory.getNativeWindowType(true);
GLDrawableFactory tmp = null;
- String factoryClassName = Debug.getProperty("jogl.gldrawablefactory.class.name", true);
- ClassLoader cl = GLDrawableFactory.class.getClassLoader();
+ String factoryClassName = PropertyAccess.getProperty("jogl.gldrawablefactory.class.name", true);
+ final ClassLoader cl = GLDrawableFactory.class.getClassLoader();
if (null == factoryClassName) {
if ( nwt == NativeWindowFactory.TYPE_X11 ) {
factoryClassName = "jogamp.opengl.x11.glx.X11GLXDrawableFactory";
} else if ( nwt == NativeWindowFactory.TYPE_WINDOWS ) {
factoryClassName = "jogamp.opengl.windows.wgl.WindowsWGLDrawableFactory";
} else if ( nwt == NativeWindowFactory.TYPE_MACOSX ) {
- if(ReflectionUtil.isClassAvailable(macosxFactoryClassNameAWTCGL, cl)) {
- factoryClassName = macosxFactoryClassNameAWTCGL;
- } else {
- factoryClassName = macosxFactoryClassNameCGL;
- }
+ factoryClassName = "jogamp.opengl.macosx.cgl.MacOSXCGLDrawableFactory";
} else {
// may use egl*Factory ..
- if (GLProfile.DEBUG) {
+ if (DEBUG || GLProfile.DEBUG) {
System.err.println("GLDrawableFactory.static - No native Windowing Factory for: "+nwt+"; May use EGLDrawableFactory, if available." );
}
}
}
if (null != factoryClassName) {
- if (GLProfile.DEBUG) {
+ if (DEBUG || GLProfile.DEBUG) {
System.err.println("GLDrawableFactory.static - Native OS Factory for: "+nwt+": "+factoryClassName);
}
try {
tmp = (GLDrawableFactory) ReflectionUtil.createInstance(factoryClassName, cl);
- } catch (JogampRuntimeException jre) {
- if (GLProfile.DEBUG) {
+ } catch (final Exception jre) {
+ if (DEBUG || GLProfile.DEBUG) {
System.err.println("Info: GLDrawableFactory.static - Native Platform: "+nwt+" - not available: "+factoryClassName);
jre.printStackTrace();
}
@@ -164,18 +160,22 @@ public abstract class GLDrawableFactory {
if(null != tmp && tmp.isComplete()) {
nativeOSFactory = tmp;
}
-
tmp = null;
- try {
- tmp = (GLDrawableFactory) ReflectionUtil.createInstance("jogamp.opengl.egl.EGLDrawableFactory", cl);
- } catch (JogampRuntimeException jre) {
- if (GLProfile.DEBUG) {
- System.err.println("Info: GLDrawableFactory.static - EGLDrawableFactory - not available");
- jre.printStackTrace();
+
+ if(!GLProfile.disableOpenGLES) {
+ try {
+ tmp = (GLDrawableFactory) ReflectionUtil.createInstance("jogamp.opengl.egl.EGLDrawableFactory", cl);
+ } catch (final Exception jre) {
+ if (DEBUG || GLProfile.DEBUG) {
+ System.err.println("Info: GLDrawableFactory.static - EGLDrawableFactory - not available");
+ jre.printStackTrace();
+ }
}
- }
- if(null != tmp && tmp.isComplete()) {
- eglFactory = tmp;
+ if(null != tmp && tmp.isComplete()) {
+ eglFactory = tmp;
+ }
+ } else if( DEBUG || GLProfile.DEBUG ) {
+ System.err.println("Info: GLDrawableFactory.static - EGLDrawableFactory - disabled!");
}
}
@@ -184,47 +184,46 @@ public abstract class GLDrawableFactory {
synchronized (GLDrawableFactory.class) {
if (isInit) {
isInit=false;
- shutdownImpl();
+ shutdown0();
}
}
}
}
-
- private static void shutdownImpl() {
+
+ private static void shutdown0() {
// Following code will _always_ remain in shutdown hook
// due to special semantics of native utils, i.e. X11Utils.
// The latter requires shutdown at JVM-Shutdown only.
synchronized(glDrawableFactories) {
- for(int i=0; i<glDrawableFactories.size(); i++) {
- glDrawableFactories.get(i).destroy();
+ final int gldfCount = glDrawableFactories.size();
+ if( DEBUG ) {
+ System.err.println("GLDrawableFactory.shutdownAll "+gldfCount+" instances, on thread "+getThreadName());
+ }
+ for(int i=0; i<gldfCount; i++) {
+ final GLDrawableFactory gldf = glDrawableFactories.get(i);
+ if( DEBUG ) {
+ System.err.println("GLDrawableFactory.shutdownAll["+(i+1)+"/"+gldfCount+"]: "+gldf.getClass().getName());
+ }
+ try {
+ gldf.resetAllDisplayGammaNoSync();
+ gldf.shutdownImpl();
+ } catch (final Throwable t) {
+ System.err.println("GLDrawableFactory.shutdownImpl: Caught "+t.getClass().getName()+" during factory shutdown #"+(i+1)+"/"+gldfCount+" "+gldf.getClass().getName());
+ if( DEBUG ) {
+ t.printStackTrace();
+ }
+ }
}
glDrawableFactories.clear();
-
- // both were members of glDrawableFactories and are shutdown already
+
+ // both were members of glDrawableFactories and are shutdown already
nativeOSFactory = null;
eglFactory = null;
}
GLContext.shutdown();
- NativeWindowFactory.shutdown(isJVMShuttingDown);
- }
-
- private static synchronized void registerFactoryShutdownHook() {
- if (factoryShutdownHookRegistered) {
- return;
+ if( DEBUG ) {
+ System.err.println("GLDrawableFactory.shutdownAll.X on thread "+getThreadName());
}
- factoryShutdownHook = new Thread(new Runnable() {
- public void run() {
- isJVMShuttingDown = true;
- GLDrawableFactory.shutdownImpl();
- }
- });
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- Runtime.getRuntime().addShutdownHook(factoryShutdownHook);
- return null;
- }
- });
- factoryShutdownHookRegistered = true;
}
protected GLDrawableFactory() {
@@ -232,14 +231,81 @@ public abstract class GLDrawableFactory {
glDrawableFactories.add(this);
}
}
-
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
+
/** Returns true if this factory is complete, i.e. ready to be used. Otherwise return false. */
protected abstract boolean isComplete();
protected void enterThreadCriticalZone() {};
protected void leaveThreadCriticalZone() {};
- protected abstract void destroy();
+ protected abstract void shutdownImpl();
+
+ /**
+ * Sets the gamma, brightness, and contrast of the display associated with the given <code>surface</code>.
+ * <p>
+ * This functionality is not available on all platforms and
+ * graphics hardware. Returns true if the settings were successfully
+ * changed, false if not. This method may return false for some
+ * values of the incoming arguments even on hardware which does
+ * support the underlying functionality. </p>
+ * <p>
+ * If this method returns true, the display settings will
+ * automatically be reset to their original values upon JVM exit
+ * (assuming the JVM does not crash); if the user wishes to change
+ * the display settings back to normal ahead of time,
+ * use {@link #resetDisplayGamma(NativeSurface)} or {@link #resetAllDisplayGamma()}.
+ * </p>
+ * <p>
+ * It is recommended to call {@link #resetDisplayGamma(NativeSurface)} or {@link #resetAllDisplayGamma()}
+ * before calling e.g. <code>System.exit()</code> from the application rather than
+ * rely on the shutdown hook functionality due to inevitable race
+ * conditions and unspecified behavior during JVM teardown.
+ * </p>
+ * <p>
+ * This method may be called multiple times during the application's
+ * execution, but calling {@link #resetDisplayGamma(NativeSurface)}
+ * will only reset the settings to the values
+ * before the first call to this method. </p>
+ *
+ * @param surface denominates the display device
+ * @param gamma The gamma value, typically > 1.0 (default values vary, but typically roughly 1.0)
+ * @param brightness The brightness value between -1.0 and 1.0, inclusive (default values vary, but typically 0)
+ * @param contrast The contrast, greater than 0.0 (default values vary, but typically 1)
+ *
+ * @return true if gamma settings were successfully changed, false if not
+ * @throws IllegalArgumentException if any of the parameters were out-of-bounds
+ * @see #resetDisplayGamma(NativeSurface)
+ * @see #resetAllDisplayGamma()
+ */
+ public abstract boolean setDisplayGamma(final NativeSurface surface, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException;
+
+ /**
+ * Resets the gamma, brightness and contrast values of the display associated with the given <code>surface</code>
+ * to its original values before {@link #setDisplayGamma(NativeSurface, float, float, float) setDisplayGamma}
+ * was called the first time.
+ * <p>
+ * While it is not explicitly required that this method be called before
+ * exiting manually, calling it is recommended because of the inevitable
+ * unspecified behavior during JVM teardown.
+ * </p>
+ */
+ public abstract void resetDisplayGamma(final NativeSurface surface);
+
+ /**
+ * Resets the gamma, brightness and contrast values of all modified
+ * displays to their original values before {@link #setDisplayGamma(NativeSurface, float, float, float) setDisplayGamma}
+ * was called the first time.
+ * <p>
+ * While it is not explicitly required that this method be called before
+ * exiting manually, calling it is recommended because of the inevitable
+ * unspecified behavior during JVM teardown.
+ * </p>
+ */
+ public abstract void resetAllDisplayGamma();
+
+ protected abstract void resetAllDisplayGammaNoSync();
/**
* Retrieve the default <code>device</code> {@link AbstractGraphicsDevice#getConnection() connection},
@@ -247,7 +313,7 @@ public abstract class GLDrawableFactory {
* The implementation must return a non <code>null</code> default device, which must not be opened, ie. it's native handle is <code>null</code>.
* <p>
* This method shall return the default device if available
- * even if the GLDrawableFactory is not functional and hence not compatible.
+ * even if the GLDrawableFactory is not functional and hence not compatible.
* The latter situation may happen because no native OpenGL implementation is available for the specific implementation.
* </p>
* @return the default shared device for this factory, eg. :0.0 on X11 desktop.
@@ -256,10 +322,10 @@ public abstract class GLDrawableFactory {
public abstract AbstractGraphicsDevice getDefaultDevice();
/**
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
* @return true if the device is compatible with this factory, ie. if it can be used for GLDrawable creation. Otherwise false.
* This implies validation whether the implementation is functional.
- *
+ *
* @see #getDefaultDevice()
*/
public abstract boolean getIsDeviceCompatible(AbstractGraphicsDevice device);
@@ -268,14 +334,14 @@ public abstract class GLDrawableFactory {
if(null==device) {
device = getDefaultDevice();
if(null==device) {
- throw new InternalError("no default device");
+ throw new InternalError("no default device available");
}
if (GLProfile.DEBUG) {
System.err.println("Info: "+getClass().getSimpleName()+".validateDevice: using default device : "+device);
}
}
-
- // Always validate the device,
+
+ // Always validate the device,
// since even the default device may not be used by this factory.
if( !getIsDeviceCompatible(device) ) {
if (GLProfile.DEBUG) {
@@ -287,31 +353,70 @@ public abstract class GLDrawableFactory {
}
/**
- * Validate and start the shared resource runner thread if necessary and
+ * Validate and start the shared resource runner thread if necessary and
* if the implementation uses it.
- *
+ *
* @return the shared resource runner thread, if implementation uses it.
*/
protected abstract Thread getSharedResourceThread();
-
+
/**
* Create the shared resource used internally as a reference for capabilities etc.
* <p>
- * Returns true if a shared resource could be created
+ * Returns true if a shared resource could be created
* for the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}.<br>
* This does not imply a shared resource is mapped (ie. made persistent), but is available in general<br>.
* </p>
*
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
- * @return true if a shared resource could been created, otherwise false.
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @return true if a shared resource could been created, otherwise false.
*/
- protected abstract boolean createSharedResource(AbstractGraphicsDevice device);
-
+ protected final boolean createSharedResource(final AbstractGraphicsDevice device) {
+ return createSharedResourceImpl(device);
+ }
+ protected abstract boolean createSharedResourceImpl(AbstractGraphicsDevice device);
+
+ /**
+ * Returns true if the <code>quirk</code> exist in the shared resource's context {@link GLRendererQuirks}.
+ * <p>
+ * Convenience method for:
+ * <pre>
+ final GLRendererQuirks glrq = factory.getRendererQuirks(device);
+ return null != glrq ? glrq.exist(quirk) : false;
+ * </pre>
+ * </p>
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @param quirk the quirk to be tested, e.g. {@link GLRendererQuirks#NoDoubleBufferedPBuffer}.
+ * @throws IllegalArgumentException if the quirk is out of range
+ * @see #getRendererQuirks(AbstractGraphicsDevice)
+ * @see GLRendererQuirks
+ */
+ public final boolean hasRendererQuirk(final AbstractGraphicsDevice device, final int quirk) {
+ final GLRendererQuirks glrq = getRendererQuirks(device);
+ return null != glrq ? glrq.exist(quirk) : false;
+ }
+
+ /**
+ * Returns the shared resource's context {@link GLRendererQuirks}.
+ * <p>
+ * Implementation calls {@link GLContext#getRendererQuirks()} on the shared resource context.
+ * </p>
+ * <p>
+ * In case no shared device exist yet or the implementation doesn't support tracking quirks,
+ * the result is always <code>null</code>.
+ * </p>
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @see GLContext#getRendererQuirks()
+ * @see GLRendererQuirks
+ */
+ public abstract GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device);
+
/**
* Returns the sole GLDrawableFactory instance for the desktop (X11, WGL, ..) if exist or null
*/
public static GLDrawableFactory getDesktopFactory() {
- GLProfile.initSingleton();
+ GLProfile.initSingleton();
return nativeOSFactory;
}
@@ -319,23 +424,23 @@ public abstract class GLDrawableFactory {
* Returns the sole GLDrawableFactory instance for EGL if exist or null
*/
public static GLDrawableFactory getEGLFactory() {
- GLProfile.initSingleton();
+ GLProfile.initSingleton();
return eglFactory;
}
- /**
- * Returns the sole GLDrawableFactory instance.
- *
- * @param glProfile GLProfile to determine the factory type, ie EGLDrawableFactory,
+ /**
+ * Returns the sole GLDrawableFactory instance.
+ *
+ * @param glProfile GLProfile to determine the factory type, ie EGLDrawableFactory,
* or one of the native GLDrawableFactory's, ie X11/GLX, Windows/WGL or MacOSX/CGL.
*/
- public static GLDrawableFactory getFactory(GLProfile glProfile) throws GLException {
+ public static GLDrawableFactory getFactory(final GLProfile glProfile) throws GLException {
return getFactoryImpl(glProfile.getImplName());
}
- protected static GLDrawableFactory getFactoryImpl(String glProfileImplName) throws GLException {
+ protected static GLDrawableFactory getFactoryImpl(final String glProfileImplName) throws GLException {
if ( GLProfile.usesNativeGLES(glProfileImplName) ) {
- if(null!=eglFactory) {
+ if(null!=eglFactory) {
return eglFactory;
}
} else if(null!=nativeOSFactory) {
@@ -344,7 +449,7 @@ public abstract class GLDrawableFactory {
throw new GLException("No GLDrawableFactory available for profile: "+glProfileImplName);
}
- protected static GLDrawableFactory getFactoryImpl(AbstractGraphicsDevice device) throws GLException {
+ protected static GLDrawableFactory getFactoryImpl(final AbstractGraphicsDevice device) throws GLException {
if(null != nativeOSFactory && nativeOSFactory.getIsDeviceCompatible(device)) {
return nativeOSFactory;
}
@@ -360,13 +465,13 @@ public abstract class GLDrawableFactory {
* The chosen GLProfile statement in the result may not refer to the maximum available profile
* due to implementation constraints, ie using the shared resource.
*
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
* @return A list of {@link javax.media.opengl.GLCapabilitiesImmutable}'s, maybe empty if none is available.
*/
public final List<GLCapabilitiesImmutable> getAvailableCapabilities(AbstractGraphicsDevice device) {
device = validateDevice(device);
if(null!=device) {
- return getAvailableCapabilitiesImpl(device);
+ return getAvailableCapabilitiesImpl(device);
}
return null;
}
@@ -376,7 +481,7 @@ public abstract class GLDrawableFactory {
// Methods to create high-level objects
/**
- * Returns a GLDrawable according to it's chosen {@link GLCapabilitiesImmutable},<br>
+ * Returns an {@link GLDrawable#isRealized() unrealized} GLDrawable according to it's chosen {@link GLCapabilitiesImmutable},<br>
* which determines pixel format, on- and offscreen incl. PBuffer type.
* <p>
* The chosen {@link GLCapabilitiesImmutable} are referenced within the target
@@ -391,36 +496,46 @@ public abstract class GLDrawableFactory {
* </p>
* <p>
* A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+ * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile) canCreateGLPbuffer(device)} is true.
* </p>
* <p>
- * If not onscreen and neither FBO nor Pbuffer is available,
+ * If not onscreen and neither FBO nor Pbuffer is available,
* a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.
* </p>
- *
+ *
* @throws IllegalArgumentException if the passed target is null
* @throws GLException if any window system-specific errors caused
* the creation of the GLDrawable to fail.
*
- * @see #canCreateGLPbuffer(AbstractGraphicsDevice)
+ * @see #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile)
* @see GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile)
* @see javax.media.opengl.GLCapabilities#isOnscreen()
* @see javax.media.opengl.GLCapabilities#isFBO()
* @see javax.media.opengl.GLCapabilities#isPBuffer()
- * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
+ * @see GraphicsConfigurationFactory#chooseGraphicsConfiguration(CapabilitiesImmutable, CapabilitiesImmutable, CapabilitiesChooser, AbstractGraphicsScreen, int)
*/
public abstract GLDrawable createGLDrawable(NativeSurface target)
throws IllegalArgumentException, GLException;
-
+
/**
- * Creates an {@link GLOffscreenAutoDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
+ * Creates a {@link GLDrawable#isRealized() realized} {@link GLOffscreenAutoDrawable}
+ * incl it's offscreen {@link NativeSurface} with the given capabilites and dimensions.
* <p>
- * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is realized and it's {@link GLContext} assigned but not yet made current.
+ * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is {@link GLDrawable#isRealized() realized}
+ * <i>without</i> an assigned {@link GLContext}, hence not initialized completely.<br>
+ *
+ * The {@link GLContext} can be assigned later manually via {@link GLAutoDrawable#setContext(GLContext, boolean) setContext(ctx)}
+ * <i>or</i> it will be created <i>lazily</i> at the 1st {@link GLAutoDrawable#display() display()} method call.<br>
+ *
+ * <i>Lazy</i> {@link GLContext} creation will take a shared {@link GLContext} into account
+ * which has been set {@link GLOffscreenAutoDrawable#setSharedContext(GLContext) directly}
+ * or {@link GLOffscreenAutoDrawable#setSharedAutoDrawable(GLAutoDrawable) via another GLAutoDrawable}.
* </p>
* <p>
* In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
* {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} <code> == true</code>,
- * it is auto-configured. The latter will set offscreen and also FBO <i>or</i> Pbuffer, whichever is available in that order.
+ * it is auto-configured. Auto configuration will set {@link GLCapabilitiesImmutable caps} to offscreen
+ * and FBO <i>or</i> Pbuffer, whichever is available in that order.
* </p>
* <p>
* A FBO based auto drawable, {@link GLOffscreenAutoDrawable.FBO}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()}
@@ -428,32 +543,62 @@ public abstract class GLDrawableFactory {
* </p>
* <p>
* A Pbuffer based auto drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+ * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile) canCreateGLPbuffer(device)} is true.
* </p>
* <p>
- * If neither FBO nor Pbuffer is available,
+ * If neither FBO nor Pbuffer is available,
* a simple pixmap/bitmap auto drawable is created, which is unlikely to be hardware accelerated.
* </p>
+ * <p>
+ * The resulting {@link GLOffscreenAutoDrawable} has it's own independent device instance using <code>device</code> details.
+ * </p>
*
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
* @param caps the requested GLCapabilties
* @param chooser the custom chooser, may be null for default
* @param width the requested offscreen width
* @param height the requested offscreen height
- * @return the created and initialized offscreen {@link GLOffscreenAutoDrawable} instance
+ * @return the created and realized offscreen {@link GLOffscreenAutoDrawable} instance
*
* @throws GLException if any window system-specific errors caused
* the creation of the Offscreen to fail.
- *
+ *
* @see #createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int)
*/
public abstract GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice device,
GLCapabilitiesImmutable caps,
GLCapabilitiesChooser chooser,
- int width, int height,
- GLContext shareWith) throws GLException;
+ int width, int height) throws GLException;
+
+ /**
+ * Creates a {@link GLDrawable#isRealized() realized} <i>dummy</i> {@link GLAutoDrawable}
+ * incl it's <i>dummy, invisible</i> {@link NativeSurface}
+ * as created with {@link #createDummyDrawable(AbstractGraphicsDevice, boolean, GLCapabilitiesImmutable, GLCapabilitiesChooser)}.
+ * <p>
+ * The <i>dummy</i> {@link GLAutoDrawable}'s {@link GLDrawable} is {@link GLDrawable#isRealized() realized}
+ * <i>without</i> an assigned {@link GLContext}, hence not initialized completely.<br>
+ * The {@link GLContext} can be assigned later manually via {@link GLAutoDrawable#setContext(GLContext, boolean) setContext(ctx)}
+ * <i>or</i> it will be created <i>lazily</i> at the 1st {@link GLAutoDrawable#display() display()} method call.<br>
+ * <i>Lazy</i> {@link GLContext} creation will take a shared {@link GLContext} into account
+ * which has been set {@link GLOffscreenAutoDrawable#setSharedContext(GLContext) directly}
+ * or {@link GLOffscreenAutoDrawable#setSharedAutoDrawable(GLAutoDrawable) via another GLAutoDrawable}.
+ * </p>
+ *
+ * @param deviceReq which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+ * @param createNewDevice if <code>true</code> a new independent device instance is created from the <code>deviceReq</code>, otherwise <code>deviceReq</code> is used as-is and must be valid!
+ * @param capsRequested the desired {@link GLCapabilitiesImmutable}, incl. it's {@link GLProfile}.
+ * For shared context, same {@link GLCapabilitiesImmutable#getVisualID(javax.media.nativewindow.VisualIDHolder.VIDType)}
+ * across shared drawables will yield best compatibility.
+ * @param chooser the custom chooser, may be null for default
+ * @return the created and realized <i>dummy</i> {@link GLAutoDrawable} instance
+ *
+ * @see #createDummyDrawable(AbstractGraphicsDevice, boolean, GLCapabilitiesImmutable, GLCapabilitiesChooser)
+ */
+ public abstract GLAutoDrawable createDummyAutoDrawable(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser);
+
/**
- * Creates a offscreen {@link GLDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
+ * Creates an {@link GLDrawable#isRealized() unrealized} offscreen {@link GLDrawable}
+ * incl it's offscreen {@link NativeSurface} with the given capabilites and dimensions.
* <p>
* In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
* {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} <code> == true</code>,
@@ -465,24 +610,27 @@ public abstract class GLDrawableFactory {
* </p>
* <p>
* A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+ * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice, GLProfile) canCreateGLPbuffer(device)} is true.
* </p>
* <p>
- * If neither FBO nor Pbuffer is available,
+ * If neither FBO nor Pbuffer is available,
* a simple pixmap/bitmap drawable is created, which is unlikely to be hardware accelerated.
* </p>
+ * <p>
+ * The resulting {@link GLDrawable} has it's own independent device instance using <code>device</code> details.
+ * </p>
*
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
* @param caps the requested GLCapabilties
* @param chooser the custom chooser, may be null for default
* @param width the requested offscreen width
* @param height the requested offscreen height
*
- * @return the created offscreen {@link GLDrawable}
+ * @return the created unrealized offscreen {@link GLDrawable}
*
* @throws GLException if any window system-specific errors caused
* the creation of the Offscreen to fail.
- *
+ *
* @see #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)
*/
public abstract GLDrawable createOffscreenDrawable(AbstractGraphicsDevice device,
@@ -491,88 +639,85 @@ public abstract class GLDrawableFactory {
int width, int height) throws GLException;
/**
- * Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance.
+ * Creates an {@link GLDrawable#isRealized() unrealized} dummy {@link GLDrawable}.
+ * A dummy drawable is not visible on screen and will not be used to render directly to, it maybe on- or offscreen.
* <p>
- * It's {@link AbstractGraphicsConfiguration} is properly set according to the given
+ * It is used to allow the creation of a {@link GLContext} to query information.
+ * It also allows creation of framebuffer objects which are used for rendering or creating a shared GLContext w/o actually rendering to this dummy drawable's framebuffer.
+ * </p>
+ * @param deviceReq which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+ * @param createNewDevice if <code>true</code> a new independent device instance is created from the <code>deviceReq</code>, otherwise <code>deviceReq</code> is used as-is and must be valid!
+ * @param capsRequested the desired {@link GLCapabilitiesImmutable}, incl. it's {@link GLProfile}.
+ * For shared context, same {@link GLCapabilitiesImmutable#getVisualID(javax.media.nativewindow.VisualIDHolder.VIDType) visual ID}
+ * or {@link GLCapabilitiesImmutable caps}
+ * across shared drawables will yield best compatibility.
+ * @param chooser the custom chooser, may be null for default
+ * @return the created unrealized dummy {@link GLDrawable}
+ */
+ public abstract GLDrawable createDummyDrawable(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser);
+
+ /**
+ * Creates a proxy {@link NativeSurface} w/ defined surface handle,
+ * i.e. a {@link jogamp.nativewindow.WrappedSurface} or {@link jogamp.nativewindow.windows.GDISurface} instance.
+ * <p>
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given
* <code>windowHandle</code>'s native visualID if set or the given {@link GLCapabilitiesImmutable}.
* </p>
* <p>
- * Lifecycle (destruction) of the given surface handle shall be handled by the caller.
+ * Lifecycle (creation and destruction) of the given surface handle shall be handled by the caller
+ * via {@link ProxySurface#createNotify()} and {@link ProxySurface#destroyNotify()}.
* </p>
* <p>
* Such surface can be used to instantiate a GLDrawable. With the help of {@link GLAutoDrawableDelegate}
- * you will be able to implement a new native windowing system binding almost on-the-fly, see {@link com.jogamp.opengl.swt.GLCanvas}.
+ * you will be able to implement a new native windowing system binding almost on-the-fly,
+ * see {@link com.jogamp.opengl.swt.GLCanvas}.
+ * </p>
+ * <p>
+ * The resulting {@link GLOffscreenAutoDrawable} has it's own independent device instance using <code>device</code> details
+ * which may be blocking depending on platform and windowing-toolkit requirements.
* </p>
- *
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
- * Caller has to ensure it is compatible w/ the given <code>windowHandle</code>
+ *
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * Caller has to ensure it is compatible w/ the given <code>windowHandle</code>
* @param screenIdx matching screen index of given <code>windowHandle</code>
* @param windowHandle the native window handle
* @param caps the requested GLCapabilties
* @param chooser the custom chooser, may be null for default
- * @param upstream optional {@link ProxySurface.UpstreamSurfaceHook} allowing control of the {@link ProxySurface}'s lifecycle and data it presents.
+ * @param upstream optional {@link UpstreamSurfaceHook} allowing control of the {@link ProxySurface}'s lifecycle and data it presents.
* @return the created {@link ProxySurface} instance w/ defined surface handle.
*/
public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device,
- int screenIdx,
- long windowHandle,
+ int screenIdx,
+ long windowHandle,
GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
/**
* Returns true if it is possible to create an <i>framebuffer object</i> (FBO).
* <p>
* FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
- * </p>
+ * </p>
* <p>
* FBO support is queried as described in {@link GLContext#hasBasicFBOSupport()}.
* </p>
*
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
* @param glp {@link GLProfile} to check for FBO capabilities
* @see GLContext#hasBasicFBOSupport()
*/
public abstract boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp);
/**
- * Returns true if it is possible to create a GLPbuffer. Some older
- * graphics cards do not have this capability.
- *
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
- */
- public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
-
- /**
- * Creates a GLPbuffer {@link GLAutoDrawable} with the given capabilites and dimensions.
+ * Returns true if it is possible to create an <i>pbuffer surface</i>.
* <p>
- * The GLPbuffer drawable is realized and initialized eagerly.
+ * Some older graphics cards do not have this capability,
+ * as well as some new GL implementation, i.e. OpenGL 3 core on OSX.
* </p>
*
- * See the note in the overview documentation on
- * <a href="../../../overview-summary.html#SHARING">context sharing</a>.
- *
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
- * @param capabilities the requested capabilities
- * @param chooser the custom chooser, may be null for default
- * @param initialWidth initial width of pbuffer
- * @param initialHeight initial height of pbuffer
- * @param shareWith a shared GLContext this GLPbuffer shall use
- *
- * @return the created and initialized {@link GLPbuffer} instance
- *
- * @throws GLException if any window system-specific errors caused
- * the creation of the GLPbuffer to fail.
- *
- * @deprecated {@link GLPbuffer} is deprecated, use {@link #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)}
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @param glp {@link GLProfile} to check for FBO capabilities
*/
- public abstract GLPbuffer createGLPbuffer(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable capabilities,
- GLCapabilitiesChooser chooser,
- int initialWidth,
- int initialHeight,
- GLContext shareWith)
- throws GLException;
+ public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp);
-
//----------------------------------------------------------------------
// Methods for interacting with third-party OpenGL libraries
@@ -605,7 +750,7 @@ public abstract class GLDrawableFactory {
* Returns true if it is possible to create an external GLDrawable
* object via {@link #createExternalGLDrawable}.
*
- * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @param device which {@link AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
*/
public abstract boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device);
diff --git a/src/jogl/classes/javax/media/opengl/GLEventListener.java b/src/jogl/classes/javax/media/opengl/GLEventListener.java
index 15fae4a39..995ca2620 100644
--- a/src/jogl/classes/javax/media/opengl/GLEventListener.java
+++ b/src/jogl/classes/javax/media/opengl/GLEventListener.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -49,7 +49,7 @@ import java.util.EventListener;
public interface GLEventListener extends EventListener {
/** Called by the drawable immediately after the OpenGL context is
initialized. Can be used to perform one-time OpenGL
- initialization per GLContext, such as setup of lights and display lists.<p>
+ initialization per GLContext, such as setup of lights and display lists.<p>
Note that this method may be called more than once if the underlying
OpenGL context for the GLAutoDrawable is destroyed and
@@ -57,7 +57,7 @@ public interface GLEventListener extends EventListener {
hierarchy and later added again.
*/
public void init(GLAutoDrawable drawable);
-
+
/** Notifies the listener to perform the release of all OpenGL
resources per GLContext, such as memory buffers and GLSL programs.<P>
@@ -68,11 +68,11 @@ public interface GLEventListener extends EventListener {
Note that this event does not imply the end of life of the application.
It could be produced with a followup call to {@link #init(GLAutoDrawable)}
- in case the GLContext has been recreated,
+ in case the GLContext has been recreated,
e.g. due to a pixel configuration change in a multihead environment.
*/
public void dispose(GLAutoDrawable drawable);
-
+
/** Called by the drawable to initiate OpenGL rendering by the
client. After all GLEventListeners have been notified of a
display event, the drawable will swap its buffers if {@link
@@ -80,13 +80,23 @@ public interface GLEventListener extends EventListener {
enabled. */
public void display(GLAutoDrawable drawable);
- /** Called by the drawable during the first repaint after the
- component has been resized. The client can update the viewport
- and view volume of the window appropriately, for example by a
- call to {@link javax.media.opengl.GL#glViewport}; note that for
- convenience the component has already called <code>glViewport(x,
- y, width, height)</code> when this method is called, so the
- client may not have to do anything in this method.
- */
+ /**
+ * Called by the drawable during the first repaint after the
+ * component has been resized.
+ * <p>
+ * The client can update it's viewport associated data
+ * and view volume of the window appropriately.
+ * </p>
+ * <p>
+ * For efficiency the GL viewport has already been updated
+ * via <code>glViewport(x, y, width, height)</code> when this method is called.
+ * </p>
+ *
+ * @param drawable the triggering {@link GLAutoDrawable}
+ * @param x viewport x-coord in pixel units
+ * @param y viewport y-coord in pixel units
+ * @param width viewport width in pixel units
+ * @param height viewport height in pixel units
+ */
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height);
}
diff --git a/src/jogl/classes/javax/media/opengl/GLException.java b/src/jogl/classes/javax/media/opengl/GLException.java
index 644042e15..acf7cdec0 100644
--- a/src/jogl/classes/javax/media/opengl/GLException.java
+++ b/src/jogl/classes/javax/media/opengl/GLException.java
@@ -1,21 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2014 JogAmp Community. All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,7 +42,7 @@ package javax.media.opengl;
/** A generic exception for OpenGL errors used throughout the binding
as a substitute for {@link RuntimeException}. */
-
+@SuppressWarnings("serial")
public class GLException extends RuntimeException {
/** Constructs a GLException object. */
public GLException() {
@@ -50,19 +51,28 @@ public class GLException extends RuntimeException {
/** Constructs a GLException object with the specified detail
message. */
- public GLException(String message) {
+ public GLException(final String message) {
super(message);
}
/** Constructs a GLException object with the specified detail
message and root cause. */
- public GLException(String message, Throwable cause) {
+ public GLException(final String message, final Throwable cause) {
super(message, cause);
}
/** Constructs a GLException object with the specified root
cause. */
- public GLException(Throwable cause) {
+ public GLException(final Throwable cause) {
super(cause);
}
+
+ /**
+ * Constructs a GLException object with the specified root
+ * cause with a decorating message including the current thread name.
+ * @since 2.2
+ */
+ public static GLException newGLException(final Throwable t) {
+ return new GLException("Caught "+t.getClass().getSimpleName()+": "+t.getMessage()+" on thread "+Thread.currentThread().getName(), t);
+ }
}
diff --git a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
index 45fd3b686..524c77e9d 100644
--- a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -31,17 +31,22 @@ package javax.media.opengl;
import javax.media.nativewindow.NativeWindowException;
import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Colorbuffer;
+import com.jogamp.opengl.FBObject.ColorAttachment;
import com.jogamp.opengl.FBObject.TextureAttachment;
+import com.jogamp.opengl.GLRendererQuirks;
-/**
+/**
* Platform-independent {@link GLDrawable} specialization,
* exposing {@link FBObject} functionality.
*
* <p>
- * A {@link GLFBODrawable} is uninitialized until a {@link GLContext} is bound
- * and made current the first time.
+ * A {@link GLFBODrawable} is uninitialized until a {@link GLContext} is bound
+ * and made current the first time, hence only then it's capabilities <i>fully</i> reflect expectations,
+ * i.e. color, depth, stencil and MSAA bits will be <i>valid</i> only after the first {@link GLContext#makeCurrent() makeCurrent()} call.
+ * On-/offscreen bits are <i>valid</i> after {@link #setRealized(boolean) setRealized(true)}.
* </p>
- *
+ *
* <p>
* MSAA is used if {@link GLCapabilitiesImmutable#getNumSamples() requested}.
* </p>
@@ -49,7 +54,7 @@ import com.jogamp.opengl.FBObject.TextureAttachment;
* Double buffering is used if {@link GLCapabilitiesImmutable#getDoubleBuffered() requested}.
* </p>
* <p>
- * In MSAA mode, it always uses the implicit 2nd {@link FBObject framebuffer} {@link FBObject#getSamplingSinkFBO() sink}.
+ * In MSAA mode, it always uses the implicit 2nd {@link FBObject framebuffer} {@link FBObject#getSamplingSinkFBO() sink}.
* Hence double buffering is always the case w/ MSAA.
* </p>
* <p>
@@ -59,64 +64,107 @@ import com.jogamp.opengl.FBObject.TextureAttachment;
* This method also allows usage of both textures seperately.
* </p>
* <p>
- * It would be possible to implement double buffering simply using
- * {@link FBObject.TextureAttachment texture attachment}s with one {@link FBObject framebuffer}.
+ * It would be possible to implement double buffering simply using
+ * {@link Colorbuffer}s with one {@link FBObject framebuffer}.
* This would require mode selection and hence complicate the API. Besides, it would
* not support differentiation of read and write framebuffer and hence not be spec compliant.
* </p>
* <p>
- * Actual swapping of the {@link FBObject.TextureAttachment texture}s or {@link FBObject framebuffer}
- * is performed either in the {@link #contextMadeCurrent(boolean) context current hook}
- * or when {@link #swapBuffersImpl(boolean) swapping buffers}, whatever comes first.<br/>
+ * Actual swapping of the {@link Colorbuffer}s and/or {@link FBObject framebuffer}
+ * is performed either in the {@link jogamp.opengl.GLContextImpl#contextMadeCurrent(boolean) context current hook}
+ * or when {@link jogamp.opengl.GLDrawableImpl#swapBuffersImpl(boolean) swapping buffers}, whatever comes first.
* </p>
- */
+ */
public interface GLFBODrawable extends GLDrawable {
// public enum DoubleBufferMode { NONE, TEXTURE, FBO }; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
-
+
+ /** FBO Mode Bit: Use a {@link TextureAttachment} for the {@link #getColorbuffer(int) render colorbuffer}, see {@link #setFBOMode(int)}. */
+ public static final int FBOMODE_USE_TEXTURE = 1 << 0;
+
/**
* @return <code>true</code> if initialized, i.e. a {@link GLContext} is bound and made current once, otherwise <code>false</code>.
*/
public boolean isInitialized();
-
+
+ /**
+ * Set the FBO mode bits used for FBO creation.
+ * <p>
+ * Default value is: {@link #FBOMODE_USE_TEXTURE}.
+ * </p>
+ * <p>
+ * If {@link GLRendererQuirks#BuggyColorRenderbuffer} is set,
+ * {@link #FBOMODE_USE_TEXTURE} is always added at initialization.
+ * </p>
+ *
+ * @param modeBits custom FBO mode bits like {@link #FBOMODE_USE_TEXTURE}.
+ * @throws IllegalStateException if already initialized, see {@link #isInitialized()}.
+ */
+ void setFBOMode(final int modeBits) throws IllegalStateException;
+
+ /**
+ * @return the used FBO mode bits, mutable via {@link #setFBOMode(int)}
+ */
+ int getFBOMode();
+
/**
* Notify this instance about upstream size change
* to reconfigure the {@link FBObject}.
- * @param gl GL context object bound to this drawable, will be made current during operation.
- * A prev. current context will be make current after operation.
+ * @param gl GL context object bound to this drawable, will be made current during operation.
+ * A prev. current context will be make current after operation.
* @throws GLException if resize operation failed
*/
- void resetSize(GL gl) throws GLException;
-
+ void resetSize(final GL gl) throws GLException;
+
/**
* @return the used texture unit
*/
int getTextureUnit();
-
+
/**
- *
+ *
* @param unit the texture unit to be used
*/
- void setTextureUnit(int unit);
-
+ void setTextureUnit(final int unit);
+
/**
- * Set a new sample size
- * @param gl GL context object bound to this drawable, will be made current during operation.
- * A prev. current context will be make current after operation.
+ * Set the number of sample buffers if using MSAA
+ *
+ * @param gl GL context object bound to this drawable, will be made current during operation.
+ * A prev. current context will be make current after operation.
* @param newSamples new sample size
* @throws GLException if resetting the FBO failed
*/
- void setNumSamples(GL gl, int newSamples) throws GLException;
-
+ void setNumSamples(final GL gl, final int newSamples) throws GLException;
+
/**
* @return the number of sample buffers if using MSAA, otherwise 0
*/
int getNumSamples();
-
+
/**
- * @return the used {@link DoubleBufferMode}
+ * Sets the number of buffers (FBO) being used if using {@link GLCapabilities#getDoubleBuffered() double buffering}.
+ * <p>
+ * If {@link GLCapabilities#getDoubleBuffered() double buffering} is not chosen, this is a NOP.
+ * </p>
+ * <p>
+ * Must be called before {@link #isInitialized() initialization}, otherwise an exception is thrown.
+ * </p>
+ * @return the new number of buffers (FBO) used, maybe different than the requested <code>bufferCount</code> (see above)
+ * @throws IllegalStateException if already initialized, see {@link #isInitialized()}.
+ */
+ int setNumBuffers(final int bufferCount) throws IllegalStateException, GLException;
+
+ /**
+ * @return the number of buffers (FBO) being used. 1 if not using {@link GLCapabilities#getDoubleBuffered() double buffering},
+ * otherwise &ge; 2, depending on {@link #setNumBuffers(int)}.
+ */
+ int getNumBuffers();
+
+ /**
+ * @return the used {@link DoubleBufferMode}
*/
// DoubleBufferMode getDoubleBufferMode(); // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
-
+
/**
* Sets the {@link DoubleBufferMode}. Must be called before {@link #isInitialized() initialization},
* otherwise an exception is thrown.
@@ -131,43 +179,49 @@ public interface GLFBODrawable extends GLDrawable {
* @throws GLException if already initialized, see {@link #isInitialized()}.
*/
// void setDoubleBufferMode(DoubleBufferMode mode) throws GLException; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
-
+
/**
* If MSAA is being used and {@link GL#GL_FRONT} is requested,
- * the internal {@link FBObject} {@link FBObject#getSamplingSinkFBO() sample sink} is being returned.
- *
+ * the internal {@link FBObject} {@link FBObject#getSamplingSinkFBO() sample sink} is being returned.
+ *
* @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names
* @return the named {@link FBObject}
* @throws IllegalArgumentException if an illegal buffer name is being used
*/
- FBObject getFBObject(int bufferName) throws IllegalArgumentException;
+ FBObject getFBObject(final int bufferName) throws IllegalArgumentException;
/**
- * Returns the named texture buffer.
+ * Returns the named {@link Colorbuffer} instance.
* <p>
- * If MSAA is being used, only the {@link GL#GL_FRONT} buffer is accessible
+ * If MSAA is being used, only the {@link GL#GL_FRONT} buffer is accessible
* and an exception is being thrown if {@link GL#GL_BACK} is being requested.
* </p>
+ * <p>
+ * Depending on the {@link #setFBOMode(int) fbo mode} the resulting {@link Colorbuffer}
+ * is either a {@link TextureAttachment} if {@link #FBOMODE_USE_TEXTURE} is set,
+ * otherwise a {@link ColorAttachment}.
+ * See {@link Colorbuffer#isTextureAttachment()}.
+ * </p>
* @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names
- * @return the named {@link TextureAttachment}
+ * @return the named {@link Colorbuffer}
* @throws IllegalArgumentException if using MSAA and {@link GL#GL_BACK} is requested or an illegal buffer name is being used
*/
- FBObject.TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException;
+ Colorbuffer getColorbuffer(final int bufferName) throws IllegalArgumentException;
- /** Resizeable {@link GLFBODrawable} specialization */
+ /** Resizeable {@link GLFBODrawable} specialization */
public interface Resizeable extends GLFBODrawable {
/**
- * Resize this drawable.
+ * Resize this {@link GLFBODrawable}'s surface.
* <p>
* This drawable is being locked during operation.
* </p>
- * @param context the {@link GLContext} bound to this drawable, will be made current during operation
- * A prev. current context will be make current after operation.
- * @param newWidth
- * @param newHeight
+ * @param context the {@link GLContext} bound to this drawable, will be made current during operation
+ * A prev. current context will be make current after operation.
+ * @param newWidth new width in pixel units
+ * @param newHeight new width in pixel units
* @throws NativeWindowException in case the surface could no be locked
* @throws GLException in case an error during the resize operation occurred
*/
- void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException;
+ void setSurfaceSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException;
}
}
diff --git a/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java
index 6fe76a3f4..62d10d4cb 100644
--- a/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -32,32 +32,38 @@ import javax.media.nativewindow.NativeWindowException;
import com.jogamp.opengl.FBObject;
-/**
+/**
* Platform-independent {@link GLAutoDrawable} specialization,
* exposing offscreen functionality.
* <p>
* This class distinguishes itself from {@link GLAutoDrawable}
- * with it's {@link #setSize(int, int)} functionality.
+ * with it's {@link #setSurfaceSize(int, int)} functionality.
+ * </p>
+ * <p>
+ * <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a>
+ * To share a {@link GLContext} see the following note in the documentation overview:
+ * <a href="../../../overview-summary.html#SHARING">context sharing</a>
+ * as well as {@link GLSharedContextSetter}.
* </p>
*/
-public interface GLOffscreenAutoDrawable extends GLAutoDrawable {
-
+public interface GLOffscreenAutoDrawable extends GLAutoDrawable, GLSharedContextSetter {
+
/**
- * Resize this auto drawable.
- * @param newWidth
- * @param newHeight
+ * Resize this {@link GLAutoDrawable}'s surface
+ * @param newWidth new width in pixel units
+ * @param newHeight new height in pixel units
* @throws NativeWindowException in case the surface could no be locked
* @throws GLException in case of an error during the resize operation
*/
- void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException;
+ void setSurfaceSize(int newWidth, int newHeight) throws NativeWindowException, GLException;
/**
* Set the upstream UI toolkit object.
* @see #getUpstreamWidget()
*/
void setUpstreamWidget(Object newUpstreamWidget);
-
- /** {@link FBObject} based {@link GLOffscreenAutoDrawable} specialization */
- public interface FBO extends GLOffscreenAutoDrawable, GLFBODrawable {
- }
+
+ /** {@link FBObject} based {@link GLOffscreenAutoDrawable} specialization */
+ public interface FBO extends GLOffscreenAutoDrawable, GLFBODrawable {
+ }
}
diff --git a/src/jogl/classes/javax/media/opengl/GLPbuffer.java b/src/jogl/classes/javax/media/opengl/GLPbuffer.java
deleted file mode 100644
index de7731a3b..000000000
--- a/src/jogl/classes/javax/media/opengl/GLPbuffer.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package javax.media.opengl;
-
-/** Provides offscreen rendering support via pbuffers. The principal
- addition of this interface is a {@link #destroy} method to
- deallocate the pbuffer and its associated resources. It also
- contains experimental methods for accessing the pbuffer's contents
- as a texture map and enabling rendering to floating-point frame
- buffers. These methods are not guaranteed to be supported on all
- platforms and may be deprecated in a future release.
-
- @deprecated Use {@link GLOffscreenAutoDrawable} w/ {@link GLCapabilities#setFBO(boolean)}
- via {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) GLDrawableFactory.createOffscreenAutoDrawable(..)}.
- */
-
-public interface GLPbuffer extends GLAutoDrawable {
- /** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */
- public static final int APPLE_FLOAT = 1;
-
- /** Indicates the GL_ATI_texture_float extension is being used for this pbuffer. */
- public static final int ATI_FLOAT = 2;
-
- /** Indicates the GL_NV_float_buffer extension is being used for this pbuffer. */
- public static final int NV_FLOAT = 3;
-
- /** Binds this pbuffer to its internal texture target. Only valid to
- call if offscreen render-to-texture has been specified in the
- NWCapabilities for this GLPbuffer. If the
- render-to-texture-rectangle capability has also been specified,
- this will use e.g. wglBindTexImageARB as its implementation and
- cause the texture to be bound to e.g. the
- GL_TEXTURE_RECTANGLE_NV state; otherwise, during the display()
- phase the pixels will have been copied into an internal texture
- target and this will cause that to be bound to the GL_TEXTURE_2D
- state. */
- public void bindTexture();
-
- /** Unbinds the pbuffer from its internal texture target. */
- public void releaseTexture();
-
- /** Destroys the native resources associated with this pbuffer. It
- is not valid to call display() or any other routines on this
- pbuffer after it has been destroyed. Before destroying the
- pbuffer, the application must destroy any additional OpenGL
- contexts which have been created for the pbuffer via {@link
- #createContext}. */
- @Override
- public void destroy();
-
- /** Indicates which vendor's extension is being used to support
- floating point channels in this pbuffer if that capability was
- requested in the NWCapabilities during pbuffer creation. Returns
- one of NV_FLOAT, ATI_FLOAT or APPLE_FLOAT, or throws GLException
- if floating-point channels were not requested for this pbuffer.
- This function may only be called once the init method for this
- pbuffer's GLEventListener has been called. */
- public int getFloatingPointMode();
-}
diff --git a/src/jogl/classes/javax/media/opengl/GLPipelineFactory.java b/src/jogl/classes/javax/media/opengl/GLPipelineFactory.java
index 2bfc77d4a..ab12ba17c 100644
--- a/src/jogl/classes/javax/media/opengl/GLPipelineFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLPipelineFactory.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,7 +28,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -49,10 +49,25 @@ import jogamp.opengl.*;
public class GLPipelineFactory {
public static final boolean DEBUG = Debug.debug("GLPipelineFactory");
- /**
+ /**
* Creates a pipelined GL instance using the given downstream <code>downstream</code>
- * and optional arguments <code>additionalArgs</code> for the constructor.<br>
+ * and optional arguments <code>additionalArgs</code> for the constructor.
*
+ * <p>
+ * Sample code which installs a Debug and Trace pipeline
+ * automatic w/ user defined interface, here: GL2ES2:
+ * <pre>
+ * gl = drawable.setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, gl, null) );
+ * gl = drawable.setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, gl, new Object[] { System.err } ) );
+ * </pre>
+ * or automatic w/ automatic defined class:
+ * <pre>
+ * gl = drawable.setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) );
+ * gl = drawable.setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) );
+ * </pre>
+ * </p>
+ *
+ * <p>
* The upstream GL instance is determined as follows:
* <ul>
* <li> Use <code>pipelineClazzBaseName</code> as the class name's full basename, incl. package name</li>
@@ -61,18 +76,19 @@ public class GLPipelineFactory {
* <li> For all <code>downstream</code> class and superclass interfaces, do:</li>
* <ul>
* <li> If <code>reqInterface</code> is not null and the interface is unequal, continue loop.</li>
- * <li> If <code>downstream</code> is not instance of interface, continue loop.</li>
+ * <li> If <code>downstream</code> is not instance of interface, continue loop.</li>
* <li> If upstream class is available use it, end loop.</li>
* </ul>
* </ul>
- * </ul><br>
+ * </ul>
+ * </p>
*
* @param pipelineClazzBaseName the basename of the pipline class name
* @param reqInterface optional requested interface to be used, may be null, in which case the first matching one is used
* @param downstream is always the 1st argument for the upstream constructor
* @param additionalArgs additional arguments for the upstream constructor
*/
- public static final GL create(String pipelineClazzBaseName, Class<?> reqInterface, GL downstream, Object[] additionalArgs) {
+ public static final GL create(final String pipelineClazzBaseName, final Class<?> reqInterface, final GL downstream, final Object[] additionalArgs) {
Class<?> downstreamClazz = downstream.getClass();
Class<?> upstreamClazz = null;
Class<?> interfaceClazz = null;
@@ -85,7 +101,7 @@ public class GLPipelineFactory {
do {
// For all interfaces: right -> left == child -> parent
// It is important that this matches with the gluegen cfg file's 'Implements' clause !
- Class<?>[] clazzes = downstreamClazz.getInterfaces();
+ final Class<?>[] clazzes = downstreamClazz.getInterfaces();
for(int i=clazzes.length-1; null==upstreamClazz && i>=0; i--) {
if(DEBUG) {
System.out.println("GLPipelineFactory: Try "+downstreamClazz.getName()+" Interface["+i+"]: "+clazzes[i].getName());
@@ -100,7 +116,7 @@ public class GLPipelineFactory {
if(DEBUG) {
System.out.println("GLPipelineFactory: "+downstream.getClass().getName() + " is _not_ instance of "+ clazzes[i].getName());
}
- continue; // not a compatible one
+ continue; // not a compatible one
} else {
if(DEBUG) {
System.out.println("GLPipelineFactory: "+downstream.getClass().getName() + " _is_ instance of "+ clazzes[i].getName());
@@ -126,7 +142,7 @@ public class GLPipelineFactory {
System.out.println("GLPipelineFactory: Got : "+ upstreamClazz.getName()+", base interface: "+interfaceClazz.getName());
}
- Class<?>[] cstrArgTypes = new Class<?>[ 1 + ( ( null==additionalArgs ) ? 0 : additionalArgs.length ) ] ;
+ final Class<?>[] cstrArgTypes = new Class<?>[ 1 + ( ( null==additionalArgs ) ? 0 : additionalArgs.length ) ] ;
{
int i = 0;
cstrArgTypes[i++] = interfaceClazz;
@@ -135,10 +151,10 @@ public class GLPipelineFactory {
}
}
// throws exception if cstr not found!
- Constructor<?> cstr = ReflectionUtil.getConstructor(upstreamClazz, cstrArgTypes);
+ final Constructor<?> cstr = ReflectionUtil.getConstructor(upstreamClazz, cstrArgTypes);
Object instance = null;
- try {
- Object[] cstrArgs = new Object[ 1 + ( ( null==additionalArgs ) ? 0 : additionalArgs.length ) ] ;
+ try {
+ final Object[] cstrArgs = new Object[ 1 + ( ( null==additionalArgs ) ? 0 : additionalArgs.length ) ] ;
{
int i = 0;
cstrArgs[i++] = downstream;
@@ -147,7 +163,7 @@ public class GLPipelineFactory {
}
}
instance = cstr.newInstance( cstrArgs ) ;
- } catch (Throwable t) { t.printStackTrace(); }
+ } catch (final Throwable t) { t.printStackTrace(); }
if(null==instance) {
throw new GLException("Error: Couldn't create instance of pipeline: "+upstreamClazz.getName()+
" ( "+getArgsClassNameList(downstreamClazz, additionalArgs) +" )");
@@ -158,8 +174,8 @@ public class GLPipelineFactory {
return (GL) instance;
}
- private static final String getArgsClassNameList(Class<?> arg0, Object[] args) {
- StringBuilder sb = new StringBuilder();
+ private static final String getArgsClassNameList(final Class<?> arg0, final Object[] args) {
+ final StringBuilder sb = new StringBuilder();
sb.append(arg0.getName());
if(args!=null) {
for(int j=0; j<args.length; j++) {
@@ -170,20 +186,20 @@ public class GLPipelineFactory {
return sb.toString();
}
- private static final Class<?> getUpstreamClazz(Class<?> downstreamClazz, String pipelineClazzBaseName) {
- String downstreamClazzName = downstreamClazz.getName();
+ private static final Class<?> getUpstreamClazz(final Class<?> downstreamClazz, final String pipelineClazzBaseName) {
+ final String downstreamClazzName = downstreamClazz.getName();
- StringTokenizer st = new StringTokenizer(downstreamClazzName, ".");
+ final StringTokenizer st = new StringTokenizer(downstreamClazzName, ".");
String downstreamClazzBaseName = downstreamClazzName;
while(st.hasMoreTokens()) {
downstreamClazzBaseName = st.nextToken();
}
- String upstreamClazzName = pipelineClazzBaseName+downstreamClazzBaseName;
+ final String upstreamClazzName = pipelineClazzBaseName+downstreamClazzBaseName;
Class<?> upstreamClazz = null;
try {
upstreamClazz = Class.forName(upstreamClazzName, true, GLPipelineFactory.class.getClassLoader());
- } catch (Throwable e) { e.printStackTrace(); }
+ } catch (final Throwable e) { e.printStackTrace(); }
return upstreamClazz;
}
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index 23d789afd..c7aaca5d3 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -37,20 +37,20 @@
package javax.media.opengl;
-import jogamp.nativewindow.NWJNILibLoader;
import jogamp.opengl.Debug;
-import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.jvm.JNILibLoaderBase;
import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.VersionUtil;
import com.jogamp.common.util.cache.TempJarCache;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveThreadGroupLock;
+import com.jogamp.gluegen.runtime.FunctionAddressResolver;
import com.jogamp.nativewindow.NativeWindowVersion;
import com.jogamp.opengl.JoglVersion;
@@ -58,123 +58,155 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.fixedfunc.GLPointerFunc;
+import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
+import java.util.Map;
/**
* Specifies the the OpenGL profile.
- *
+ *
* This class static singleton initialization queries the availability of all OpenGL Profiles
* and instantiates singleton GLProfile objects for each available profile.
*
- * The platform default profile may be used, using {@link GLProfile#GetProfileDefault()},
+ * The platform default profile may be used, using {@link GLProfile#GetProfileDefault()},
* or more specialized versions using the other static GetProfile methods.
*/
public class GLProfile {
-
- public static final boolean DEBUG = Debug.debug("GLProfile");
-
- /**
- * We have to disable support for ANGLE, the D3D ES2 emulation on Windows provided w/ Firefox and Chrome.
+
+ public static final boolean DEBUG;
+
+ /**
+ * In case no OpenGL ES profiles are required
+ * and if one platform may have a buggy implementation,
+ * setting the property <code>jogl.disable.opengles</code> disables querying possible existing OpenGL ES profiles.
+ */
+ public static final boolean disableOpenGLES;
+
+ /**
+ * In case no native OpenGL core profiles are required
+ * and if one platform may have a buggy implementation,
+ * setting the property <code>jogl.disable.openglcore</code> disables querying possible existing native OpenGL core profiles.
+ * <p>
+ * This exclusion is disabled for {@link Platform.OSType#MACOS}.
+ * </p>
+ */
+ public static final boolean disableOpenGLCore;
+
+ /**
+ * In case the implementation of the <i>ARB_create_context</i>
+ * context creation extension is buggy on one platform,
+ * setting the property <code>jogl.disable.openglarbcontext</code> disables utilizing it.
+ * <p>
+ * This exclusion is disabled for {@link Platform.OSType#MACOS}.
+ * </p>
+ */
+ public static final boolean disableOpenGLARBContext;
+
+ /**
+ * We have to disable support for ANGLE, the D3D ES2 emulation on Windows provided w/ Firefox and Chrome.
* When run in the mentioned browsers, the eglInitialize(..) implementation crashes.
* <p>
* This can be overridden by explicitly enabling ANGLE on Windows by setting the property
* <code>jogl.enable.ANGLE</code>.
- * </p>
- */
- private static final boolean enableANGLE = Debug.isPropertyDefined("jogl.enable.ANGLE", true);
-
- /**
- * In case no OpenGL ES implementation is required
- * and if the running platform may have a buggy implementation,
- * setting the property <code>jogl.disable.opengles</code> disables querying a possible existing OpenGL ES implementation.
+ * </p>
*/
- private static final boolean disableOpenGLES = Debug.isPropertyDefined("jogl.disable.opengles", true);
-
+ public static final boolean enableANGLE;
+
static {
// Also initializes TempJarCache if shall be used.
Platform.initSingleton();
+ final boolean isOSX = Platform.OSType.MACOS == Platform.getOSType();
+
+ DEBUG = Debug.debug("GLProfile");
+ disableOpenGLES = PropertyAccess.isPropertyDefined("jogl.disable.opengles", true);
+ disableOpenGLCore = PropertyAccess.isPropertyDefined("jogl.disable.openglcore", true) && !isOSX;
+ disableOpenGLARBContext = PropertyAccess.isPropertyDefined("jogl.disable.openglarbcontext", true) && !isOSX;
+ enableANGLE = PropertyAccess.isPropertyDefined("jogl.enable.ANGLE", true);
}
-
+
+ /**
+ * @return <code>true</code> if JOGL has been initialized, i.e. manually via {@link #initSingleton()} or implicit,
+ * otherwise returns <code>false</code>.
+ *
+ * @since 2.2.1
+ */
+ public static boolean isInitialized() {
+ initLock.lock();
+ try {
+ return initialized;
+ } finally {
+ initLock.unlock();
+ }
+ }
+
/**
* Static initialization of JOGL.
*
* <p>
* This method shall not need to be called for other reasons than having a defined initialization sequence.
* </p>
- *
+ *
* <P>
* In case this method is not invoked, GLProfile is initialized implicit by
* the first call to {@link #getDefault()}, {@link #get(java.lang.String)}.
* <P>
- *
+ *
* <p>
- * To initialize JOGL at startup ASAP, this method may be invoked in the <i>main class</i>'s
+ * To initialize JOGL at startup ASAP, this method may be invoked in the <i>main class</i>'s
* static initializer block, in the <i>static main() method</i> or in the <i>Applet init() method</i>.
* </p>
- *
+ *
* <p>
* Since JOGL's initialization is complex and involves multi threading, it is <b>not</b> recommended
- * to be have it invoked on the AWT EDT thread. In case all JOGL usage is performed
+ * to be have it invoked on the AWT EDT thread. In case all JOGL usage is performed
* on the AWT EDT, invoke this method outside the AWT EDT - see above.
* </p>
- *
+ *
*/
public static void initSingleton() {
- final boolean justInitialized;
+ final boolean justInitialized;
initLock.lock();
try {
- if(!initialized) { // volatile: ok
+ if(!initialized) {
initialized = true;
justInitialized = true;
if(DEBUG) {
System.err.println("GLProfile.initSingleton() - thread "+Thread.currentThread().getName());
Thread.dumpStack();
}
-
+
+ if(ReflectionUtil.DEBUG_STATS_FORNAME) {
+ ReflectionUtil.resetForNameCount();
+ }
+
// run the whole static initialization privileged to speed up,
// since this skips checking further access
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
Platform.initSingleton();
-
- // Performance hack to trigger classloading of the GL classes impl, which makes up to 12%, 800ms down to 700ms
- new Thread(new Runnable() {
- public void run() {
- final ClassLoader cl = GLProfile.class.getClassLoader();
- try {
- ReflectionUtil.createInstance(getGLImplBaseClassName(GL4bc)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
- } catch (Throwable t) {}
- try {
- ReflectionUtil.createInstance(getGLImplBaseClassName(GLES2)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
- } catch (Throwable t) {}
- try {
- ReflectionUtil.createInstance(getGLImplBaseClassName(GLES1)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
- } catch (Throwable t) {}
- }
- }, "GLProfile-GL_Bootstrapping").start();
-
-
+
if(TempJarCache.isInitialized()) {
final ClassLoader cl = GLProfile.class.getClassLoader();
- // either: [jogl-all.jar, jogl-all-noawt.jar, jogl-all-mobile.jar] -> jogl-all-natives-<os.and.arch>.jar
- // or: nativewindow-core.jar -> nativewindow-natives-<os.and.arch>.jar,
- // jogl-core.jar -> jogl-natives-<os.and.arch>.jar,
- // (newt-core.jar -> newt-natives-<os.and.arch>.jar)? (if available)
- final String newtFactoryClassName = "com.jogamp.newt.NewtFactory";
- final Class<?>[] classesFromJavaJars = new Class<?>[] { NWJNILibLoader.class, GLProfile.class, null };
- if( ReflectionUtil.isClassAvailable(newtFactoryClassName, cl) ) {
- classesFromJavaJars[2] = ReflectionUtil.getClass(newtFactoryClassName, false, cl);
+ final String newtDebugClassName = "jogamp.newt.Debug";
+ final Class<?>[] classesFromJavaJars = new Class<?>[] { jogamp.nativewindow.Debug.class, jogamp.opengl.Debug.class, null };
+ if( ReflectionUtil.isClassAvailable(newtDebugClassName, cl) ) {
+ classesFromJavaJars[2] = ReflectionUtil.getClass(newtDebugClassName, false, cl);
}
- JNILibLoaderBase.addNativeJarLibs(classesFromJavaJars, "-all", new String[] { "-noawt", "-mobile", "-core" } );
+ JNILibLoaderBase.addNativeJarLibsJoglCfg(classesFromJavaJars);
}
initProfilesForDefaultDevices();
return null;
}
});
+ if( ReflectionUtil.DEBUG_STATS_FORNAME ) {
+ if( justInitialized ) {
+ System.err.println(ReflectionUtil.getForNameStats(null).toString());
+ }
+ }
} else {
justInitialized = false;
}
@@ -182,19 +214,19 @@ public class GLProfile {
initLock.unlock();
}
if(DEBUG) {
- if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES2Impl ) ) {
+ if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES3Impl ) ) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true));
}
- }
+ }
}
-
+
/**
* Trigger eager initialization of GLProfiles for the given device,
* in case it isn't done yet.
- *
+ *
* @throws GLException if no profile for the given device is available.
*/
- public static void initProfiles(AbstractGraphicsDevice device) throws GLException {
+ public static void initProfiles(final AbstractGraphicsDevice device) throws GLException {
getProfileMap(device, true);
}
@@ -210,12 +242,12 @@ public class GLProfile {
public static void shutdown() {
initLock.lock();
try {
- if(initialized) { // volatile: ok
+ if(initialized) {
initialized = false;
if(DEBUG) {
System.err.println("GLProfile.shutdown() - thread "+Thread.currentThread().getName());
Thread.dumpStack();
- }
+ }
GLDrawableFactory.shutdown();
}
} finally {
@@ -227,57 +259,57 @@ public class GLProfile {
// Query platform available OpenGL implementation
//
- /**
+ /**
* Returns the availability of a profile on a device.
- *
+ *
* @param device a valid AbstractGraphicsDevice, or <code>null</null> for the default device.
- * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
+ * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
* or <code>[ null, GL ]</code> for the default profile.
* @return true if the profile is available for the device, otherwise false.
*/
- public static boolean isAvailable(AbstractGraphicsDevice device, String profile) {
+ public static boolean isAvailable(final AbstractGraphicsDevice device, final String profile) {
initSingleton();
return isAvailableImpl(getProfileMap(device, false), profile);
}
- private static boolean isAvailableImpl(HashMap<String /*GLProfile_name*/, GLProfile> map, String profile) {
+ private static boolean isAvailableImpl(final HashMap<String /*GLProfile_name*/, GLProfile> map, final String profile) {
return null != map && null != map.get(profile);
}
-
- /**
+
+ /**
* Returns the availability of a profile on the default device.
- *
- * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
+ *
+ * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
* or <code>[ null, GL ]</code> for the default profile.
* @return true if the profile is available for the default device, otherwise false.
*/
- public static boolean isAvailable(String profile) {
+ public static boolean isAvailable(final String profile) {
return isAvailable(null, profile);
}
-
- /**
+
+ /**
* Returns the availability of any profile on the default device.
- *
+ *
* @return true if any profile is available for the default device, otherwise false.
*/
public static boolean isAnyAvailable() {
return isAvailable(null, null);
}
-
- public static String glAvailabilityToString(AbstractGraphicsDevice device) {
+
+ public static String glAvailabilityToString(final AbstractGraphicsDevice device) {
return glAvailabilityToString(device, null).toString();
}
-
- public static StringBuilder glAvailabilityToString(AbstractGraphicsDevice device, StringBuilder sb) {
+
+ public static StringBuilder glAvailabilityToString(final AbstractGraphicsDevice device, final StringBuilder sb) {
return glAvailabilityToString(device, sb, null, 0);
}
- private static StringBuilder doIndent(StringBuilder sb, String indent, int indentCount) {
+ private static StringBuilder doIndent(final StringBuilder sb, final String indent, int indentCount) {
while(indentCount>0) {
sb.append(indent);
indentCount--;
}
return sb;
}
- public static StringBuilder glAvailabilityToString(AbstractGraphicsDevice device, StringBuilder sb, String indent, int indentCount) {
+ public static StringBuilder glAvailabilityToString(AbstractGraphicsDevice device, StringBuilder sb, final String indent, int indentCount) {
boolean avail;
if(null == sb) {
sb = new StringBuilder();
@@ -285,121 +317,183 @@ public class GLProfile {
final boolean useIndent = null != indent;
initSingleton();
-
+
+ int allCount = 0;
+ int nativeCount = 0;
+
if(null==device) {
device = defaultDevice;
}
final HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, false);
-
+
if(useIndent) {
- doIndent(sb, indent, indentCount).append("Native");
+ doIndent(sb, indent, indentCount).append("Natives");
indentCount++;
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL4bc").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL4bc+" ").append(indent);
} else {
- sb.append("Native[GL4bc ");
- }
+ sb.append("Natives["+GL4bc+" ");
+ }
avail=isAvailableImpl(map, GL4bc);
sb.append(avail);
if(avail) {
+ nativeCount++;
glAvailabilityToString(device, sb.append(" "), 4, GLContext.CTX_PROFILE_COMPAT);
}
+ allCount++;
if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL4").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL4+" ").append(indent);
} else {
- sb.append(", GL4 ");
+ sb.append(", "+GL4+" ");
}
avail=isAvailableImpl(map, GL4);
sb.append(avail);
if(avail) {
+ nativeCount++;
glAvailabilityToString(device, sb.append(" "), 4, GLContext.CTX_PROFILE_CORE);
}
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GLES3+" ").append(indent);
+ } else {
+ sb.append(", "+GLES3+" ");
+ }
+ avail=isAvailableImpl(map, GLES3);
+ sb.append(avail);
+ if(avail) {
+ nativeCount++;
+ glAvailabilityToString(device, sb.append(" "), 3, GLContext.CTX_PROFILE_ES);
+ }
+ allCount++;
if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL3bc").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL3bc+" ").append(indent);
} else {
- sb.append(", GL3bc ");
+ sb.append(", "+GL3bc+" ");
}
avail=isAvailableImpl(map, GL3bc);
sb.append(avail);
if(avail) {
+ nativeCount++;
glAvailabilityToString(device, sb.append(" "), 3, GLContext.CTX_PROFILE_COMPAT);
}
+ allCount++;
if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL3").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL3+" ").append(indent);
} else {
- sb.append(", GL3 ");
+ sb.append(", "+GL3+" ");
}
avail=isAvailableImpl(map, GL3);
sb.append(avail);
if(avail) {
+ nativeCount++;
glAvailabilityToString(device, sb.append(" "), 3, GLContext.CTX_PROFILE_CORE);
}
+ allCount++;
if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL2").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2+" ").append(indent);
} else {
- sb.append(", GL2 ");
+ sb.append(", "+GL2+" ");
}
avail=isAvailableImpl(map, GL2);
sb.append(avail);
if(avail) {
+ nativeCount++;
glAvailabilityToString(device, sb.append(" "), 2, GLContext.CTX_PROFILE_COMPAT);
}
+ allCount++;
if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL2ES1").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GLES2+" ").append(indent);
} else {
- sb.append(", GL2ES1 ");
+ sb.append(", "+GLES2+" ");
}
- sb.append(isAvailableImpl(map, GL2ES1));
+ avail=isAvailableImpl(map, GLES2);
+ sb.append(avail);
+ if(avail) {
+ nativeCount++;
+ glAvailabilityToString(device, sb.append(" "), 2, GLContext.CTX_PROFILE_ES);
+ }
+ allCount++;
if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GLES1").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GLES1+" ").append(indent);
} else {
- sb.append(", GLES1 ");
+ sb.append(", "+GLES1+" ");
}
avail=isAvailableImpl(map, GLES1);
sb.append(avail);
if(avail) {
+ nativeCount++;
glAvailabilityToString(device, sb.append(" "), 1, GLContext.CTX_PROFILE_ES);
}
+ allCount++;
if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL2ES2").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Count\t"+nativeCount+" / "+allCount);
+ indentCount--;
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Common");
+ indentCount++;
} else {
- sb.append(", GL2ES2 ");
+ sb.append(", count "+nativeCount+" / "+allCount+"], Common[");
}
- sb.append(isAvailableImpl(map, GL2ES2));
if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GLES2").append(indent);
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL4ES3+" ").append(indent);
} else {
- sb.append(", GLES2 ");
+ sb.append(", "+GL4ES3+" ");
}
- avail=isAvailableImpl(map, GLES2);
- sb.append(avail);
- if(avail) {
- glAvailabilityToString(device, sb.append(" "), 2, GLContext.CTX_PROFILE_ES);
+ sb.append(isAvailableImpl(map, GL4ES3));
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2GL3+" ").append(indent);
+ } else {
+ sb.append(", "+GL2GL3+" ");
+ }
+ sb.append(isAvailableImpl(map, GL2GL3));
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2ES2+" ").append(indent);
+ } else {
+ sb.append(", "+GL2ES2+" ");
}
+ sb.append(isAvailableImpl(map, GL2ES2));
+ allCount++;
+
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2ES1+" ").append(indent);
+ } else {
+ sb.append(", "+GL2ES1+" ");
+ }
+ sb.append(isAvailableImpl(map, GL2ES1));
+ allCount++;
if(useIndent) {
indentCount--;
- doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Profiles");
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Mappings");
indentCount++;
} else {
- sb.append("], Profiles[");
+ sb.append("], Mappings[");
}
-
+
+ int profileCount = 0;
+
if(null != map) {
- for(Iterator<GLProfile> i=map.values().iterator(); i.hasNext(); ) {
- if(useIndent) {
- doIndent(sb.append(Platform.getNewline()), indent, indentCount);
- }
- sb.append(i.next().toString());
- if(!useIndent) {
- sb.append(", ");
+ for (final Map.Entry<String,GLProfile> entry : map.entrySet()) {
+ if( GL_DEFAULT != entry.getKey() ) {
+ if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount);
+ }
+ sb.append(entry.getKey()+(useIndent?" \t":" ")+entry.getValue());
+ if(!useIndent) {
+ sb.append(", ");
+ }
+ profileCount++;
}
}
if(useIndent) {
@@ -409,19 +503,20 @@ public class GLProfile {
}
try {
sb.append(getDefault(device));
- } catch (GLException gle) {
+ } catch (final GLException gle) {
sb.append("n/a");
}
}
if(useIndent) {
+ doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Count\t"+profileCount+" / "+allCount);
sb.append(Platform.getNewline());
} else {
- sb.append("]");
+ sb.append(", count "+profileCount+" / "+allCount+"]");
}
return sb;
}
-
+
/** Uses the default device */
public static String glAvailabilityToString() {
return glAvailabilityToString(null);
@@ -433,115 +528,127 @@ public class GLProfile {
/** The desktop OpenGL compatibility profile 4.x, with x >= 0, ie GL2 plus GL4.<br>
<code>bc</code> stands for backward compatibility. */
- public static final String GL4bc = "GL4bc";
+ public static final String GL4bc = "GL4bc"; // Implicitly intern(), see Bug 1059
/** The desktop OpenGL core profile 4.x, with x >= 0 */
- public static final String GL4 = "GL4";
+ public static final String GL4 = "GL4"; // Implicitly intern(), see Bug 1059
/** The desktop OpenGL compatibility profile 3.x, with x >= 1, ie GL2 plus GL3.<br>
<code>bc</code> stands for backward compatibility. */
- public static final String GL3bc = "GL3bc";
+ public static final String GL3bc = "GL3bc"; // Implicitly intern(), see Bug 1059
/** The desktop OpenGL core profile 3.x, with x >= 1 */
- public static final String GL3 = "GL3";
+ public static final String GL3 = "GL3"; // Implicitly intern(), see Bug 1059
/** The desktop OpenGL profile 1.x up to 3.0 */
- public static final String GL2 = "GL2";
+ public static final String GL2 = "GL2"; // Implicitly intern(), see Bug 1059
/** The embedded OpenGL profile ES 1.x, with x >= 0 */
- public static final String GLES1 = "GLES1";
+ public static final String GLES1 = "GLES1"; // Implicitly intern(), see Bug 1059
/** The embedded OpenGL profile ES 2.x, with x >= 0 */
- public static final String GLES2 = "GLES2";
+ public static final String GLES2 = "GLES2"; // Implicitly intern(), see Bug 1059
+
+ /** The embedded OpenGL profile ES 3.x, with x >= 0 */
+ public static final String GLES3 = "GLES3"; // Implicitly intern(), see Bug 1059
/** The intersection of the desktop GL2 and embedded ES1 profile */
- public static final String GL2ES1 = "GL2ES1";
+ public static final String GL2ES1 = "GL2ES1"; // Implicitly intern(), see Bug 1059
/** The intersection of the desktop GL3, GL2 and embedded ES2 profile */
- public static final String GL2ES2 = "GL2ES2";
+ public static final String GL2ES2 = "GL2ES2"; // Implicitly intern(), see Bug 1059
/** The intersection of the desktop GL3 and GL2 profile */
- public static final String GL2GL3 = "GL2GL3";
+ public static final String GL2GL3 = "GL2GL3"; // Implicitly intern(), see Bug 1059
+
+ /** The intersection of the desktop GL4 and ES3 profile, available only if either ES3 or GL4 w/ <code>GL_ARB_ES3_compatibility</code> is available. */
+ public static final String GL4ES3 = "GL4ES3"; // Implicitly intern(), see Bug 1059
/** The default profile, used for the device default profile map */
- private static final String GL_DEFAULT = "GL_DEFAULT";
+ private static final String GL_DEFAULT = "GL_DEFAULT"; // Implicitly intern(), see Bug 1059
+ /** The default profile, used for the device default profile map */
+ private static final String GL_GL = "GL"; // Implicitly intern(), see Bug 1059
- /**
+ /**
* All GL Profiles in the order of default detection.
* Desktop compatibility profiles (the one with fixed function pipeline) comes first
* from highest to lowest version.
* <p> This includes the generic subset profiles GL2GL3, GL2ES2 and GL2ES1.</p>
*
* <ul>
- * <li> GL4bc
- * <li> GL3bc
- * <li> GL2
- * <li> GL4
- * <li> GL3
- * <li> GL2GL3
- * <li> GLES2
- * <li> GL2ES2
- * <li> GLES1
- * <li> GL2ES1
+ * <li> GL4bc </li>
+ * <li> GL3bc </li>
+ * <li> GL2 </li>
+ * <li> GL4 </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GL4ES3 </li>
+ * <li> GL2GL3 </li>
+ * <li> GLES2 </li>
+ * <li> GL2ES2 </li>
+ * <li> GLES1 </li>
+ * <li> GL2ES1 </li>
* </ul>
*
*/
- public static final String[] GL_PROFILE_LIST_ALL = new String[] { GL4bc, GL3bc, GL2, GL4, GL3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 };
+ public static final String[] GL_PROFILE_LIST_ALL = new String[] { GL4bc, GL3bc, GL2, GL4, GL3, GLES3, GL4ES3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 };
/**
* Order of maximum profiles.
*
* <ul>
- * <li> GL4bc
- * <li> GL4
- * <li> GL3bc
- * <li> GL3
- * <li> GL2
- * <li> GLES2
- * <li> GLES1
+ * <li> GL4bc </li>
+ * <li> GL4 </li>
+ * <li> GL3bc </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GL2 </li>
+ * <li> GLES2 </li>
+ * <li> GLES1 </li>
* </ul>
*
*/
- public static final String[] GL_PROFILE_LIST_MAX = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GLES2, GLES1 };
+ public static final String[] GL_PROFILE_LIST_MAX = new String[] { GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GLES2, GLES1 };
/**
* Order of minimum profiles.
*
* <ul>
- * <li> GLES1
- * <li> GLES2
- * <li> GL2
- * <li> GL3
- * <li> GL3bc
- * <li> GL4
- * <li> GL4bc
+ * <li> GLES1 </li>
+ * <li> GLES2 </li>
+ * <li> GL2 </li>
+ * <li> GLES3 </li>
+ * <li> GL3 </li>
+ * <li> GL3bc </li>
+ * <li> GL4 </li>
+ * <li> GL4bc </li>
* </ul>
*
*/
- public static final String[] GL_PROFILE_LIST_MIN = new String[] { GLES1, GLES2, GL2, GL3, GL3bc, GL4, GL4bc };
-
+ public static final String[] GL_PROFILE_LIST_MIN = new String[] { GLES1, GLES2, GL2, GLES3, GL3, GL3bc, GL4, GL4bc };
+
/**
* Order of minimum original desktop profiles.
*
* <ul>
- * <li> GL2
- * <li> GL3bc
- * <li> GL4bc
- * <li> GL3
- * <li> GL4
+ * <li> GL2 </li>
+ * <li> GL3bc </li>
+ * <li> GL4bc </li>
+ * <li> GL3 </li>
+ * <li> GL4 </li>
* </ul>
*
*/
public static final String[] GL_PROFILE_LIST_MIN_DESKTOP = new String[] { GL2, GL3bc, GL4bc, GL3, GL4 };
-
+
/**
* Order of maximum fixed function profiles
*
* <ul>
- * <li> GL4bc
- * <li> GL3bc
- * <li> GL2
- * <li> GLES1
+ * <li> GL4bc </li>
+ * <li> GL3bc </li>
+ * <li> GL2 </li>
+ * <li> GLES1 </li>
* </ul>
*
*/
@@ -551,16 +658,30 @@ public class GLProfile {
* Order of maximum programmable shader profiles
*
* <ul>
- * <li> GL4bc
- * <li> GL4
- * <li> GL3bc
- * <li> GL3
- * <li> GL2
- * <li> GLES2
+ * <li> GL4bc </li>
+ * <li> GL4 </li>
+ * <li> GL3bc </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GL2 </li>
+ * <li> GLES2 </li>
+ * </ul>
+ *
+ */
+ public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GLES2 };
+
+ /**
+ * Order of maximum programmable shader <i>core only</i> profiles
+ *
+ * <ul>
+ * <li> GL4 </li>
+ * <li> GL3 </li>
+ * <li> GLES3 </li>
+ * <li> GLES2 </li>
* </ul>
*
*/
- public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GLES2 };
+ public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER_CORE = new String[] { GL4, GL3, GLES3, GLES2 };
/** Returns a default GLProfile object, reflecting the best for the running platform.
* It selects the first of the set {@link GLProfile#GL_PROFILE_LIST_ALL}
@@ -568,15 +689,15 @@ public class GLProfile {
* @throws GLException if no profile is available for the device.
* @see #GL_PROFILE_LIST_ALL
*/
- public static GLProfile getDefault(AbstractGraphicsDevice device) {
- GLProfile glp = get(device, GL_DEFAULT);
+ public static GLProfile getDefault(final AbstractGraphicsDevice device) {
+ final GLProfile glp = get(device, GL_DEFAULT);
return glp;
}
/** Returns a default GLProfile object, reflecting the best for the running platform.
* It selects the first of the set {@link GLProfile#GL_PROFILE_LIST_ALL}
* and favors hardware acceleration.
- * <p>Uses the default device.</p>
+ * <p>Uses the default device.</p>
* @throws GLException if no profile is available for the default device.
*/
public static GLProfile getDefault() {
@@ -590,17 +711,17 @@ public class GLProfile {
* @throws GLException if no profile is available for the device.
* @see #GL_PROFILE_LIST_MAX
*/
- public static GLProfile getMaximum(AbstractGraphicsDevice device, boolean favorHardwareRasterizer)
+ public static GLProfile getMaximum(final AbstractGraphicsDevice device, final boolean favorHardwareRasterizer)
throws GLException
{
return get(device, GL_PROFILE_LIST_MAX, favorHardwareRasterizer);
}
- /** Uses the default device
+ /** Uses the default device
* @throws GLException if no profile is available for the default device.
* @see #GL_PROFILE_LIST_MAX
*/
- public static GLProfile getMaximum(boolean favorHardwareRasterizer)
+ public static GLProfile getMaximum(final boolean favorHardwareRasterizer)
throws GLException
{
return get(GL_PROFILE_LIST_MAX, favorHardwareRasterizer);
@@ -613,17 +734,17 @@ public class GLProfile {
* @throws GLException if no desktop profile is available for the device.
* @see #GL_PROFILE_LIST_MIN
*/
- public static GLProfile getMinimum(AbstractGraphicsDevice device, boolean favorHardwareRasterizer)
+ public static GLProfile getMinimum(final AbstractGraphicsDevice device, final boolean favorHardwareRasterizer)
throws GLException
{
return get(device, GL_PROFILE_LIST_MIN, favorHardwareRasterizer);
}
- /** Uses the default device
+ /** Uses the default device
* @throws GLException if no desktop profile is available for the default device.
* @see #GL_PROFILE_LIST_MIN
*/
- public static GLProfile getMinimum(boolean favorHardwareRasterizer)
+ public static GLProfile getMinimum(final boolean favorHardwareRasterizer)
throws GLException
{
return get(GL_PROFILE_LIST_MIN, favorHardwareRasterizer);
@@ -637,17 +758,17 @@ public class GLProfile {
* @throws GLException if no fixed function profile is available for the device.
* @see #GL_PROFILE_LIST_MAX_FIXEDFUNC
*/
- public static GLProfile getMaxFixedFunc(AbstractGraphicsDevice device, boolean favorHardwareRasterizer)
+ public static GLProfile getMaxFixedFunc(final AbstractGraphicsDevice device, final boolean favorHardwareRasterizer)
throws GLException
{
return get(device, GL_PROFILE_LIST_MAX_FIXEDFUNC, favorHardwareRasterizer);
}
- /** Uses the default device
+ /** Uses the default device
* @throws GLException if no fixed function profile is available for the default device.
* @see #GL_PROFILE_LIST_MAX_FIXEDFUNC
*/
- public static GLProfile getMaxFixedFunc(boolean favorHardwareRasterizer)
+ public static GLProfile getMaxFixedFunc(final boolean favorHardwareRasterizer)
throws GLException
{
return get(GL_PROFILE_LIST_MAX_FIXEDFUNC, favorHardwareRasterizer);
@@ -660,23 +781,46 @@ public class GLProfile {
* @throws GLException if no programmable profile is available for the device.
* @see #GL_PROFILE_LIST_MAX_PROGSHADER
*/
- public static GLProfile getMaxProgrammable(AbstractGraphicsDevice device, boolean favorHardwareRasterizer)
+ public static GLProfile getMaxProgrammable(final AbstractGraphicsDevice device, final boolean favorHardwareRasterizer)
throws GLException
{
return get(device, GL_PROFILE_LIST_MAX_PROGSHADER, favorHardwareRasterizer);
}
- /** Uses the default device
+ /** Uses the default device
* @throws GLException if no programmable profile is available for the default device.
* @see #GL_PROFILE_LIST_MAX_PROGSHADER
*/
- public static GLProfile getMaxProgrammable(boolean favorHardwareRasterizer)
+ public static GLProfile getMaxProgrammable(final boolean favorHardwareRasterizer)
throws GLException
{
return get(GL_PROFILE_LIST_MAX_PROGSHADER, favorHardwareRasterizer);
}
- /**
+ /**
+ * Returns the highest profile, implementing the programmable shader <i>core</i> pipeline <i>only</i>.
+ * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX_PROGSHADER_CORE}
+ *
+ * @throws GLException if no programmable core profile is available for the device.
+ * @see #GL_PROFILE_LIST_MAX_PROGSHADER_CORE
+ */
+ public static GLProfile getMaxProgrammableCore(final AbstractGraphicsDevice device, final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(device, GL_PROFILE_LIST_MAX_PROGSHADER_CORE, favorHardwareRasterizer);
+ }
+
+ /** Uses the default device
+ * @throws GLException if no programmable core profile is available for the default device.
+ * @see #GL_PROFILE_LIST_MAX_PROGSHADER_CORE
+ */
+ public static GLProfile getMaxProgrammableCore(final boolean favorHardwareRasterizer)
+ throws GLException
+ {
+ return get(GL_PROFILE_LIST_MAX_PROGSHADER_CORE, favorHardwareRasterizer);
+ }
+
+ /**
* Returns the GL2ES1 profile implementation, hence compatible w/ GL2ES1.<br/>
* It returns:
* <pre>
@@ -689,14 +833,14 @@ public class GLProfile {
* @see #get(AbstractGraphicsDevice, String)
* @see #getImpl()
*/
- public static GLProfile getGL2ES1(AbstractGraphicsDevice device)
+ public static GLProfile getGL2ES1(final AbstractGraphicsDevice device)
throws GLException
{
return get(device, GL2ES1).getImpl();
}
- /**
- * Calls {@link #getGL2ES1(AbstractGraphicsDevice)} using the default device.
+ /**
+ * Calls {@link #getGL2ES1(AbstractGraphicsDevice)} using the default device.
* <p>Selection favors hardware rasterizer.</p>
* @see #getGL2ES1(AbstractGraphicsDevice)
*/
@@ -706,7 +850,7 @@ public class GLProfile {
return get(defaultDevice, GL2ES1).getImpl();
}
- /**
+ /**
* Returns the GL2ES2 profile implementation, hence compatible w/ GL2ES2.<br/>
* It returns:
* <pre>
@@ -719,14 +863,14 @@ public class GLProfile {
* @see #get(AbstractGraphicsDevice, String)
* @see #getImpl()
*/
- public static GLProfile getGL2ES2(AbstractGraphicsDevice device)
+ public static GLProfile getGL2ES2(final AbstractGraphicsDevice device)
throws GLException
{
return get(device, GL2ES2).getImpl();
}
- /**
- * Calls {@link #getGL2ES2(AbstractGraphicsDevice)} using the default device.
+ /**
+ * Calls {@link #getGL2ES2(AbstractGraphicsDevice)} using the default device.
* <p>Selection favors hardware rasterizer.</p>
* @see #getGL2ES2(AbstractGraphicsDevice)
*/
@@ -736,7 +880,37 @@ public class GLProfile {
return get(defaultDevice, GL2ES2).getImpl();
}
- /**
+ /**
+ * Returns the GL4ES3 profile implementation, hence compatible w/ GL4ES3.<br/>
+ * It returns:
+ * <pre>
+ * GLProfile.get(device, GLProfile.GL4ES3).getImpl());
+ * </pre>
+ * <p>Selection favors hardware rasterizer.</p>
+ *
+ * @throws GLException if no GL4ES3 compatible profile is available for the default device.
+ * @see #isGL4ES3()
+ * @see #get(AbstractGraphicsDevice, String)
+ * @see #getImpl()
+ */
+ public static GLProfile getGL4ES3(final AbstractGraphicsDevice device)
+ throws GLException
+ {
+ return get(device, GL4ES3).getImpl();
+ }
+
+ /**
+ * Calls {@link #getGL4ES3(AbstractGraphicsDevice)} using the default device.
+ * <p>Selection favors hardware rasterizer.</p>
+ * @see #getGL4ES3(AbstractGraphicsDevice)
+ */
+ public static GLProfile getGL4ES3()
+ throws GLException
+ {
+ return get(defaultDevice, GL4ES3).getImpl();
+ }
+
+ /**
* Returns the GL2GL3 profile implementation, hence compatible w/ GL2GL3.<br/>
* It returns:
* <pre>
@@ -749,14 +923,14 @@ public class GLProfile {
* @see #get(AbstractGraphicsDevice, String)
* @see #getImpl()
*/
- public static GLProfile getGL2GL3(AbstractGraphicsDevice device)
+ public static GLProfile getGL2GL3(final AbstractGraphicsDevice device)
throws GLException
{
return get(device, GL2GL3).getImpl();
}
- /**
- * Calls {@link #getGL2GL3(AbstractGraphicsDevice)} using the default device.
+ /**
+ * Calls {@link #getGL2GL3(AbstractGraphicsDevice)} using the default device.
* <p>Selection favors hardware rasterizer.</p>
* @see #getGL2GL3(AbstractGraphicsDevice)
*/
@@ -772,14 +946,14 @@ public class GLProfile {
* the default profile.
*
* @param device a valid AbstractGraphicsDevice, or <code>null</null> for the default device.
- * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
+ * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
* or <code>[ null, GL ]</code> for the default profile.
* @throws GLException if the requested profile is not available for the device.
*/
- public static GLProfile get(AbstractGraphicsDevice device, String profile)
+ public static GLProfile get(final AbstractGraphicsDevice device, String profile)
throws GLException
{
- if(null==profile || profile.equals("GL")) {
+ if(null==profile || profile == GL_GL) {
profile = GL_DEFAULT;
}
final HashMap<String /*GLProfile_name*/, GLProfile> glpMap = getProfileMap(device, true);
@@ -790,12 +964,12 @@ public class GLProfile {
return glp;
}
- /** Uses the default device
- * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
+ /** Uses the default device
+ * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
* or <code>[ null, GL ]</code> for the default profile.
* @throws GLException if the requested profile is not available for the default device.
*/
- public static GLProfile get(String profile)
+ public static GLProfile get(final String profile)
throws GLException
{
return get(defaultDevice, profile);
@@ -807,15 +981,15 @@ public class GLProfile {
*
* @param device a valid AbstractGraphicsDevice, or <code>null</null> for the default device.
* @param profiles array of valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..)
- * @param favorHardwareRasterizer set to true, if hardware rasterizer shall be favored, otherwise false.
+ * @param favorHardwareRasterizer set to true, if hardware rasterizer shall be favored, otherwise false.
* @throws GLException if the non of the requested profiles is available for the device.
*/
- public static GLProfile get(AbstractGraphicsDevice device, String[] profiles, boolean favorHardwareRasterizer)
+ public static GLProfile get(final AbstractGraphicsDevice device, final String[] profiles, final boolean favorHardwareRasterizer)
throws GLException
{
GLProfile glProfileAny = null;
-
- HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, true);
+
+ final HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, true);
for(int i=0; i<profiles.length; i++) {
final GLProfile glProfile = map.get(profiles[i]);
if(null!=glProfile) {
@@ -827,42 +1001,49 @@ public class GLProfile {
}
if(null==glProfileAny) {
glProfileAny = glProfile;
- }
+ }
}
}
if(null!=glProfileAny) {
return glProfileAny;
- }
+ }
throw new GLException("Profiles "+array2String(profiles)+" not available on device "+device);
}
- /** Uses the default device
- * @param profiles array of valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..)
- * @param favorHardwareRasterizer set to true, if hardware rasterizer shall be favored, otherwise false.
+ /** Uses the default device
+ * @param profiles array of valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..)
+ * @param favorHardwareRasterizer set to true, if hardware rasterizer shall be favored, otherwise false.
* @throws GLException if the non of the requested profiles is available for the default device.
*/
- public static GLProfile get(String[] profiles, boolean favorHardwareRasterizer)
+ public static GLProfile get(final String[] profiles, final boolean favorHardwareRasterizer)
throws GLException
{
return get(defaultDevice, profiles, favorHardwareRasterizer);
}
-
- /** Indicates whether the native OpenGL ES1 profile is in use.
+
+ /** Indicates whether the native OpenGL ES1 profile is in use.
* This requires an EGL interface.
*/
- public static boolean usesNativeGLES1(String profileImpl) {
- return GLES1.equals(profileImpl);
+ public static boolean usesNativeGLES1(final String profileImpl) {
+ return GLES1 == profileImpl;
+ }
+
+ /** Indicates whether the native OpenGL ES3 or ES2 profile is in use.
+ * This requires an EGL, ES3 or ES2 compatible interface.
+ */
+ public static boolean usesNativeGLES2(final String profileImpl) {
+ return GLES3 == profileImpl || GLES2 == profileImpl;
}
- /** Indicates whether the native OpenGL ES2 profile is in use.
- * This requires an EGL or ES2 compatible interface.
+ /** Indicates whether the native OpenGL ES2 profile is in use.
+ * This requires an EGL, ES3 compatible interface.
*/
- public static boolean usesNativeGLES2(String profileImpl) {
- return GLES2.equals(profileImpl);
+ public static boolean usesNativeGLES3(final String profileImpl) {
+ return GLES3 == profileImpl;
}
/** Indicates whether either of the native OpenGL ES profiles are in use. */
- public static boolean usesNativeGLES(String profileImpl) {
+ public static boolean usesNativeGLES(final String profileImpl) {
return usesNativeGLES2(profileImpl) || usesNativeGLES1(profileImpl);
}
@@ -870,7 +1051,7 @@ public class GLProfile {
JOGL's AWT part */
public static boolean isAWTAvailable() { return isAWTAvailable; }
- public static String getGLTypeName(int type) {
+ public static String getGLTypeName(final int type) {
switch (type) {
case GL.GL_UNSIGNED_BYTE:
return "GL_UNSIGNED_BYTE";
@@ -886,9 +1067,9 @@ public class GLProfile {
return "GL_FIXED";
case javax.media.opengl.GL2ES2.GL_INT:
return "GL_INT";
- case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT:
+ case GL.GL_UNSIGNED_INT:
return "GL_UNSIGNED_INT";
- case javax.media.opengl.GL2.GL_DOUBLE:
+ case javax.media.opengl.GL2GL3.GL_DOUBLE:
return "GL_DOUBLE";
case javax.media.opengl.GL2.GL_2_BYTES:
return "GL_2_BYTES";
@@ -900,7 +1081,7 @@ public class GLProfile {
return null;
}
- public static String getGLArrayName(int array) {
+ public static String getGLArrayName(final int array) {
switch(array) {
case GLPointerFunc.GL_VERTEX_ARRAY:
return "GL_VERTEX_ARRAY";
@@ -917,10 +1098,9 @@ public class GLProfile {
public final String getGLImplBaseClassName() {
return getGLImplBaseClassName(getImplName());
}
-
- private static final String getGLImplBaseClassName(String profileImpl) {
- if( GLES2 == profileImpl ) {
- return "jogamp.opengl.es2.GLES2";
+ private static final String getGLImplBaseClassName(final String profileImpl) {
+ if( GLES2 == profileImpl || GLES3 == profileImpl ) {
+ return "jogamp.opengl.es3.GLES3";
} else if( GLES1 == profileImpl ) {
return "jogamp.opengl.es1.GLES1";
} else if ( GL4bc == profileImpl ||
@@ -933,33 +1113,54 @@ public class GLProfile {
throw new GLException("unsupported profile \"" + profileImpl + "\"");
}
}
-
+
+ public final Constructor<?> getGLCtor(final boolean glObject) {
+ return getGLCtor(getImplName(), glObject);
+ }
+ private static final Constructor<?> getGLCtor(final String profileImpl, final boolean glObject) {
+ if( GLES2 == profileImpl || GLES3 == profileImpl ) {
+ return glObject ? ctorGLES3Impl : ctorGLES3ProcAddr;
+ } else if( GLES1 == profileImpl ) {
+ return glObject ? ctorGLES1Impl : ctorGLES1ProcAddr;
+ } else if ( GL4bc == profileImpl ||
+ GL4 == profileImpl ||
+ GL3bc == profileImpl ||
+ GL3 == profileImpl ||
+ GL2 == profileImpl ) {
+ return glObject ? ctorGL234Impl : ctorGL234ProcAddr;
+ } else {
+ throw new GLException("unsupported profile \"" + profileImpl + "\"");
+ }
+ }
+
/**
* @param o GLProfile object to compare with
* @return true if given Object is a GLProfile and
* if both, profile and profileImpl is equal with this.
*/
- public final boolean equals(Object o) {
+ @Override
+ public final boolean equals(final Object o) {
if(this==o) { return true; }
if(o instanceof GLProfile) {
final GLProfile glp = (GLProfile)o;
- return getName() == glp.getName() && getImplName() == glp.getImplName() ;
+ return getName() == glp.getName() && getImplName() == glp.getImplName() ; // uses .intern()!
}
return false;
}
+ @Override
public int hashCode() {
int hash = 5;
hash = 97 * hash + getImplName().hashCode();
hash = 97 * hash + getName().hashCode();
return hash;
}
-
+
/**
* @param glp GLProfile to compare with
* @throws GLException if given GLProfile and this aren't equal
*/
- public final void verifyEquality(GLProfile glp) throws GLException {
+ public final void verifyEquality(final GLProfile glp) throws GLException {
if(!this.equals(glp)) {
throw new GLException("GLProfiles are not equal: "+this+" != "+glp);
}
@@ -974,14 +1175,14 @@ public class GLProfile {
public final GLProfile getImpl() {
return null != profileImpl ? profileImpl : this;
}
-
+
/** return true if impl. is a hardware rasterizer, otherwise false. */
public final boolean isHardwareRasterizer() {
return isHardwareRasterizer;
}
-
- /**
- * return this profiles implementation name, eg. GL2ES2 -> GL2, or GL3 -> GL3
+
+ /**
+ * return this profiles implementation name, eg. GL2ES2 -> GL2, or GL3 -> GL3
*/
public final String getImplName() {
return null != profileImpl ? profileImpl.getName() : getName();
@@ -1007,7 +1208,7 @@ public class GLProfile {
return isGL4() || isGL3bc() || GL3 == profile;
}
- /** Indicates whether this context is a GL2 context <p>Includes [ GL4bc, GL3bc, GL2 ].</p> */
+ /** Indicates whether this profile is capable of GL2 . <p>Includes [ GL4bc, GL3bc, GL2 ].</p> */
public final boolean isGL2() {
return isGL3bc() || GL2 == profile;
}
@@ -1017,14 +1218,19 @@ public class GLProfile {
return GLES1 == profile;
}
- /** Indicates whether this profile is capable of GLES2. <p>Includes [ GLES2 ].</p> */
+ /** Indicates whether this profile is capable of GLES2. <p>Includes [ GLES2, GLES3 ].</p> */
public final boolean isGLES2() {
- return GLES2 == profile;
+ return isGLES3() || GLES2 == profile;
}
-
- /** Indicates whether this profile is capable of GLES. <p>Includes [ GLES1, GLES2 ].</p> */
+
+ /** Indicates whether this profile is capable of GLES3. <p>Includes [ GLES3 ].</p> */
+ public final boolean isGLES3() {
+ return GLES3 == profile;
+ }
+
+ /** Indicates whether this profile is capable of GLES. <p>Includes [ GLES1, GLES2, GLES3 ].</p> */
public final boolean isGLES() {
- return GLES2 == profile || GLES1 == profile;
+ return GLES3 == profile || GLES2 == profile || GLES1 == profile;
}
/** Indicates whether this profile is capable of GL2ES1. <p>Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].</p> */
@@ -1032,17 +1238,36 @@ public class GLProfile {
return GL2ES1 == profile || isGLES1() || isGL2();
}
- /** Indicates whether this profile is capable os GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p> */
+ /** Indicates whether this profile is capable of GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p> */
public final boolean isGL2GL3() {
return GL2GL3 == profile || isGL3() || isGL2();
}
- /** Indicates whether this profile is capable os GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3, GL2ES2, GLES2 ].</p> */
+ /** Indicates whether this profile is capable of GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GL2GL3, GL2ES2, GLES2 ].</p> */
public final boolean isGL2ES2() {
return GL2ES2 == profile || isGLES2() || isGL2GL3();
}
- /** Indicates whether this profile supports GLSL, ie. {@link #isGL2ES2()}. */
+ /**
+ * Indicates whether this profile is capable of GL2ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL3ES3, GL2, GL2GL3 ].</p>
+ * @see #isGL3ES3()
+ * @see #isGL2GL3()
+ */
+ public final boolean isGL2ES3() {
+ return isGL3ES3() || isGL2GL3();
+ }
+
+ /** Indicates whether this profile is capable of GL3ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3 ].</p> */
+ public final boolean isGL3ES3() {
+ return isGL4ES3() || isGL3();
+ }
+
+ /** Indicates whether this profile is capable of GL4ES3. <p>Includes [ GL4bc, GL4, GLES3 ].</p> */
+ public final boolean isGL4ES3() {
+ return GL4ES3 == profile || isGLES3() || isGL4();
+ }
+
+ /** Indicates whether this profile supports GLSL, i.e. {@link #isGL2ES2()}. */
public final boolean hasGLSL() {
return isGL2ES2() ;
}
@@ -1057,16 +1282,21 @@ public class GLProfile {
return GLES2 == getImplName();
}
+ /** Indicates whether this profile uses the native OpenGL ES3 implementations. */
+ public final boolean usesNativeGLES3() {
+ return GLES3 == getImplName();
+ }
+
/** Indicates whether this profile uses either of the native OpenGL ES implementations. */
public final boolean usesNativeGLES() {
- return usesNativeGLES2() || usesNativeGLES1();
+ return usesNativeGLES3() || usesNativeGLES2() || usesNativeGLES1();
}
- /**
+ /**
* General validation if type is a valid GL data type
* for the current profile
*/
- public boolean isValidDataType(int type, boolean throwException) {
+ public boolean isValidDataType(final int type, final boolean throwException) {
switch(type) {
case GL.GL_UNSIGNED_BYTE:
case GL.GL_BYTE:
@@ -1076,11 +1306,11 @@ public class GLProfile {
case GL.GL_FIXED:
return true;
case javax.media.opengl.GL2ES2.GL_INT:
- case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT:
+ case GL.GL_UNSIGNED_INT:
if( isGL2ES2() ) {
return true;
}
- case javax.media.opengl.GL2.GL_DOUBLE:
+ case javax.media.opengl.GL2GL3.GL_DOUBLE:
if( isGL3() ) {
return true;
}
@@ -1090,17 +1320,17 @@ public class GLProfile {
if( isGL2() ) {
return true;
}
- }
+ }
if(throwException) {
throw new GLException("Illegal data type on profile "+this+": "+type);
}
return false;
}
-
- public boolean isValidArrayDataType(int index, int comps, int type,
- boolean isVertexAttribPointer, boolean throwException) {
- String arrayName = getGLArrayName(index);
- if(isGLES1()) {
+
+ public boolean isValidArrayDataType(final int index, final int comps, final int type,
+ final boolean isVertexAttribPointer, final boolean throwException) {
+ final String arrayName = getGLArrayName(index);
+ if( isGLES1() ) {
if(isVertexAttribPointer) {
if(throwException) {
throw new GLException("Illegal array type for "+arrayName+" on profile GLES1: VertexAttribPointer");
@@ -1116,7 +1346,7 @@ public class GLProfile {
case GL.GL_FIXED:
case GL.GL_FLOAT:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type);
}
@@ -1128,7 +1358,7 @@ public class GLProfile {
case 3:
case 4:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps);
}
@@ -1142,7 +1372,7 @@ public class GLProfile {
case GL.GL_FIXED:
case GL.GL_FLOAT:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type);
}
@@ -1152,7 +1382,7 @@ public class GLProfile {
case 0:
case 3:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps);
}
@@ -1165,7 +1395,7 @@ public class GLProfile {
case GL.GL_FIXED:
case GL.GL_FLOAT:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type);
}
@@ -1175,7 +1405,7 @@ public class GLProfile {
case 0:
case 4:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps);
}
@@ -1183,7 +1413,7 @@ public class GLProfile {
}
break;
}
- } else if(isGLES2()) {
+ } else if( isGLES2() ) {
// simply ignore !isVertexAttribPointer case, since it is simulated anyway ..
switch(type) {
case GL.GL_UNSIGNED_BYTE:
@@ -1193,7 +1423,7 @@ public class GLProfile {
case GL.GL_FLOAT:
case GL.GL_FIXED:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal data type for "+arrayName+" on profile GLES2: "+type);
}
@@ -1207,7 +1437,7 @@ public class GLProfile {
case 3:
case 4:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal component number for "+arrayName+" on profile GLES2: "+comps);
}
@@ -1222,10 +1452,10 @@ public class GLProfile {
case GL.GL_SHORT:
case GL.GL_FLOAT:
case javax.media.opengl.GL2ES2.GL_INT:
- case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT:
- case javax.media.opengl.GL2.GL_DOUBLE:
+ case GL.GL_UNSIGNED_INT:
+ case javax.media.opengl.GL2GL3.GL_DOUBLE:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type);
}
@@ -1238,7 +1468,7 @@ public class GLProfile {
case 3:
case 4:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps);
}
@@ -1251,9 +1481,9 @@ public class GLProfile {
case GL.GL_SHORT:
case GL.GL_FLOAT:
case javax.media.opengl.GL2ES2.GL_INT:
- case javax.media.opengl.GL2.GL_DOUBLE:
+ case javax.media.opengl.GL2GL3.GL_DOUBLE:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type);
}
@@ -1265,7 +1495,7 @@ public class GLProfile {
case 3:
case 4:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps);
}
@@ -1278,9 +1508,9 @@ public class GLProfile {
case GL.GL_SHORT:
case GL.GL_FLOAT:
case javax.media.opengl.GL2ES2.GL_INT:
- case javax.media.opengl.GL2.GL_DOUBLE:
+ case javax.media.opengl.GL2GL3.GL_DOUBLE:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type);
}
@@ -1290,7 +1520,7 @@ public class GLProfile {
case 0:
case 3:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps);
}
@@ -1305,10 +1535,10 @@ public class GLProfile {
case GL.GL_SHORT:
case GL.GL_FLOAT:
case javax.media.opengl.GL2ES2.GL_INT:
- case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT:
- case javax.media.opengl.GL2.GL_DOUBLE:
+ case GL.GL_UNSIGNED_INT:
+ case javax.media.opengl.GL2GL3.GL_DOUBLE:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type);
}
@@ -1319,7 +1549,7 @@ public class GLProfile {
case 3:
case 4:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps);
}
@@ -1331,9 +1561,9 @@ public class GLProfile {
case GL.GL_SHORT:
case GL.GL_FLOAT:
case javax.media.opengl.GL2ES2.GL_INT:
- case javax.media.opengl.GL2.GL_DOUBLE:
+ case javax.media.opengl.GL2GL3.GL_DOUBLE:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type);
}
@@ -1346,7 +1576,7 @@ public class GLProfile {
case 3:
case 4:
break;
- default:
+ default:
if(throwException) {
throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps);
}
@@ -1359,24 +1589,99 @@ public class GLProfile {
return true;
}
+ @Override
public String toString() {
- return "GLProfile[" + getName() + "/" + getImplName() + "."+(this.isHardwareRasterizer?"hw":"sw")+"]";
+ return "GLProfile[" + getName() + "/" + getImplName() + "."+(this.isHardwareRasterizer?"hw":"sw")+(isCustom?".custom":"")+"]";
}
private static /*final*/ boolean isAWTAvailable;
- private static /*final*/ boolean hasDesktopGLFactory;
+ private static /*final*/ boolean hasDesktopGLFactory;
private static /*final*/ boolean hasGL234Impl;
private static /*final*/ boolean hasEGLFactory;
- private static /*final*/ boolean hasGLES2Impl;
+ private static /*final*/ boolean hasGLES3Impl;
private static /*final*/ boolean hasGLES1Impl;
+ private static /*final*/ Constructor<?> ctorGL234Impl;
+ private static /*final*/ Constructor<?> ctorGLES3Impl;
+ private static /*final*/ Constructor<?> ctorGLES1Impl;
+ private static /*final*/ Constructor<?> ctorGL234ProcAddr;
+ private static /*final*/ Constructor<?> ctorGLES3ProcAddr;
+ private static /*final*/ Constructor<?> ctorGLES1ProcAddr;
private static /*final*/ GLDrawableFactoryImpl eglFactory = null;
private static /*final*/ GLDrawableFactoryImpl desktopFactory = null;
private static /*final*/ AbstractGraphicsDevice defaultDevice = null;
- private static volatile boolean initialized = false;
- private static RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock();
+ private static boolean initialized = false;
+ private static final RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock();
+
+ private static final Class<?>[] ctorGLArgs = new Class<?>[] { GLProfile.class, jogamp.opengl.GLContextImpl.class };
+ private static final Class<?>[] ctorProcArgs = new Class<?>[] { FunctionAddressResolver.class };
+ private static final String GL4bcImplClassName = "jogamp.opengl.gl4.GL4bcImpl";
+ private static final String GL4bcProcClassName = "jogamp.opengl.gl4.GL4bcProcAddressTable";
+ private static final String GLES1ImplClassName = "jogamp.opengl.es1.GLES1Impl";
+ private static final String GLES1ProcClassName = "jogamp.opengl.es1.GLES1ProcAddressTable";
+ private static final String GLES3ImplClassName = "jogamp.opengl.es3.GLES3Impl";
+ private static final String GLES3ProcClassName = "jogamp.opengl.es3.GLES3ProcAddressTable";
+
+ private static final Constructor<?> getCtor(final String clazzName, final boolean glObject, final ClassLoader cl) {
+ try {
+ return ReflectionUtil.getConstructor(clazzName, glObject ? ctorGLArgs : ctorProcArgs, false, cl);
+ } catch (final Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Caught: "+t.getMessage());
+ t.printStackTrace();
+ }
+ return null;
+ }
+ }
+
+ private static final void initGLCtorImpl() {
+ final ClassLoader classloader = GLProfile.class.getClassLoader();
+
+ // depends on hasDesktopGLFactory
+ {
+ final Constructor<?> ctorGL = getCtor(GL4bcImplClassName, true, classloader);
+ final Constructor<?> ctorProc = null != ctorGL ? getCtor(GL4bcProcClassName, false, classloader) : null;
+ if( null != ctorProc ) {
+ hasGL234Impl = true;
+ ctorGL234Impl = ctorGL;
+ ctorGL234ProcAddr = ctorProc;
+ } else {
+ hasGL234Impl = false;
+ ctorGL234Impl = null;
+ ctorGL234ProcAddr = null;
+ }
+ }
+
+ // depends on hasEGLFactory
+ {
+ final Constructor<?> ctorGL = getCtor(GLES1ImplClassName, true, classloader);
+ final Constructor<?> ctorProc = null != ctorGL ? getCtor(GLES1ProcClassName, false, classloader) : null;
+ if( null != ctorProc ) {
+ hasGLES1Impl = true;
+ ctorGLES1Impl = ctorGL;
+ ctorGLES1ProcAddr = ctorProc;
+ } else {
+ hasGLES1Impl = false;
+ ctorGLES1Impl = null;
+ ctorGLES1ProcAddr = null;
+ }
+ }
+ {
+ final Constructor<?> ctorGL = getCtor(GLES3ImplClassName, true, classloader);
+ final Constructor<?> ctorProc = null != ctorGL ? getCtor(GLES3ProcClassName, false, classloader) : null;
+ if( null != ctorProc ) {
+ hasGLES3Impl = true;
+ ctorGLES3Impl = ctorGL;
+ ctorGLES3ProcAddr = ctorProc;
+ } else {
+ hasGLES3Impl = false;
+ ctorGLES3Impl = null;
+ ctorGLES3ProcAddr = null;
+ }
+ }
+ }
/**
* Tries the profiles implementation and native libraries.
@@ -1391,18 +1696,13 @@ public class GLProfile {
System.err.println(JoglVersion.getInstance());
}
- ClassLoader classloader = GLProfile.class.getClassLoader();
+ final ClassLoader classloader = GLProfile.class.getClassLoader();
isAWTAvailable = NativeWindowFactory.isAWTAvailable() &&
ReflectionUtil.isClassAvailable("javax.media.opengl.awt.GLCanvas", classloader) ; // JOGL
- // depends on hasDesktopGLFactory
- hasGL234Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.gl4.GL4bcImpl", classloader);
-
- // depends on hasEGLFactory
- hasGLES1Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.es1.GLES1Impl", classloader);
- hasGLES2Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.es2.GLES2Impl", classloader);
-
+ initGLCtorImpl();
+
//
// Iteration of desktop GL availability detection
// utilizing the detected GL version in the shared context.
@@ -1411,22 +1711,22 @@ public class GLProfile {
// which will register at GLContext ..
//
GLDrawableFactory.initSingleton();
-
+
Throwable t=null;
// if successfull it has a shared dummy drawable and context created
try {
desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GL2);
if(null != desktopFactory) {
- DesktopGLDynamicLookupHelper glLookupHelper = (DesktopGLDynamicLookupHelper) desktopFactory.getGLDynamicLookupHelper(0);
+ final DesktopGLDynamicLookupHelper glLookupHelper = (DesktopGLDynamicLookupHelper) desktopFactory.getGLDynamicLookupHelper(0);
if(null!=glLookupHelper) {
hasDesktopGLFactory = glLookupHelper.isLibComplete() && hasGL234Impl;
}
}
- } catch (LinkageError le) {
+ } catch (final LinkageError le) {
t=le;
- } catch (RuntimeException re) {
+ } catch (final RuntimeException re) {
t=re;
- } catch (Throwable tt) {
+ } catch (final Throwable tt) {
t=tt;
}
if(DEBUG) {
@@ -1445,42 +1745,25 @@ public class GLProfile {
}
} else {
defaultDesktopDevice = desktopFactory.getDefaultDevice();
- defaultDevice = defaultDesktopDevice;
- if(DEBUG) {
- System.err.println("Info: GLProfile.init - Default device is desktop derived: "+defaultDevice);
- }
}
- if ( !disableOpenGLES && ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) {
+ if ( ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) {
t=null;
try {
eglFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2);
if(null != eglFactory) {
- final boolean isANGLE = ((jogamp.opengl.egl.EGLDrawableFactory)eglFactory).isANGLE();
- if(isANGLE && !enableANGLE) {
- if(DEBUG) {
- System.err.println("Info: GLProfile.init - EGL/ES2 ANGLE disabled");
- }
- eglFactory.destroy();
- eglFactory = null;
- hasEGLFactory = false;
- } else {
- if(DEBUG && isANGLE) {
- System.err.println("Info: GLProfile.init - EGL/ES2 ANGLE enabled");
- }
- hasEGLFactory = true;
- // update hasGLES1Impl, hasGLES2Impl based on EGL
- hasGLES2Impl = null!=eglFactory.getGLDynamicLookupHelper(2) && hasGLES2Impl;
- hasGLES1Impl = null!=eglFactory.getGLDynamicLookupHelper(1) && hasGLES1Impl;
- }
+ hasEGLFactory = true;
+ // update hasGLES1Impl, hasGLES3Impl based on EGL
+ hasGLES3Impl = null!=eglFactory.getGLDynamicLookupHelper(2) && hasGLES3Impl;
+ hasGLES1Impl = null!=eglFactory.getGLDynamicLookupHelper(1) && hasGLES1Impl;
}
- } catch (LinkageError le) {
+ } catch (final LinkageError le) {
t=le;
- } catch (SecurityException se) {
+ } catch (final SecurityException se) {
t=se;
- } catch (NullPointerException npe) {
+ } catch (final NullPointerException npe) {
t=npe;
- } catch (RuntimeException re) {
+ } catch (final RuntimeException re) {
t=re;
}
if(DEBUG) {
@@ -1490,9 +1773,9 @@ public class GLProfile {
}
}
- final AbstractGraphicsDevice defaultEGLDevice;
+ final AbstractGraphicsDevice defaultEGLDevice;
if(null == eglFactory) {
- hasGLES2Impl = false;
+ hasGLES3Impl = false;
hasGLES1Impl = false;
defaultEGLDevice = null;
if(DEBUG) {
@@ -1500,30 +1783,38 @@ public class GLProfile {
}
} else {
defaultEGLDevice = eglFactory.getDefaultDevice();
- if(null == defaultDevice) {
- defaultDevice = defaultEGLDevice;
- if(DEBUG) {
- System.err.println("Info: GLProfile.init - Default device is EGL derived: "+defaultDevice);
- }
+ }
+
+ if( null != defaultDesktopDevice ) {
+ defaultDevice = defaultDesktopDevice;
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device is desktop derived: "+defaultDevice);
+ }
+ } else if ( null != defaultEGLDevice ) {
+ defaultDevice = defaultEGLDevice;
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device is EGL derived: "+defaultDevice);
}
+ } else {
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device not available");
+ }
+ defaultDevice = null;
}
- /** Should not be required .. but keep it here if simple probe on defaultDevice ain't enough.
- final boolean addedDesktopProfile = initProfilesForDevice(defaultDesktopDevice);
- final boolean addedEGLProfile = initProfilesForDevice(defaultEGLDevice);
- final boolean addedAnyProfile = addedDesktopProfile || addedEGLProfile ;
- */
- final boolean addedAnyProfile = initProfilesForDevice(defaultDevice);
+ // we require to initialize the EGL device 1st, if available
+ final boolean addedEGLProfile = null != defaultEGLDevice ? initProfilesForDevice(defaultEGLDevice) : false;
+ final boolean addedDesktopProfile = null != defaultDesktopDevice ? initProfilesForDevice(defaultDesktopDevice) : false;
+ final boolean addedAnyProfile = addedEGLProfile || addedDesktopProfile ;
if(DEBUG) {
- // System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
- System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
+ System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory);
System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl);
System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory);
System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl);
- System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl);
+ System.err.println("GLProfile.init hasGLES3Impl "+hasGLES3Impl);
System.err.println("GLProfile.init defaultDevice "+defaultDevice);
System.err.println("GLProfile.init defaultDevice Desktop "+defaultDesktopDevice);
System.err.println("GLProfile.init defaultDevice EGL "+defaultEGLDevice);
@@ -1535,13 +1826,13 @@ public class GLProfile {
* @param device the device for which profiles shall be initialized
* @return true if any profile for the device exists, otherwise false
*/
- private static boolean initProfilesForDevice(AbstractGraphicsDevice device) {
+ private static boolean initProfilesForDevice(final AbstractGraphicsDevice device) {
if(null == device) {
return false;
}
initLock.lock();
try {
- GLDrawableFactory factory = GLDrawableFactory.getFactoryImpl(device);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactoryImpl(device);
factory.enterThreadCriticalZone();
try {
return initProfilesForDeviceCritical(device);
@@ -1552,8 +1843,8 @@ public class GLProfile {
initLock.unlock();
}
}
- private static boolean initProfilesForDeviceCritical(AbstractGraphicsDevice device) {
- boolean isSet = GLContext.getAvailableGLVersionsSet(device);
+ private static boolean initProfilesForDeviceCritical(final AbstractGraphicsDevice device) {
+ final boolean isSet = GLContext.getAvailableGLVersionsSet(device);
if(DEBUG) {
System.err.println("Info: GLProfile.initProfilesForDevice: "+device+" ("+device.getClass().getName()+"), isSet "+isSet+", hasDesktopGLFactory "+hasDesktopGLFactory+", hasEGLFactory "+hasEGLFactory);
@@ -1561,7 +1852,7 @@ public class GLProfile {
if(isSet) {
// Avoid recursion and check whether impl. is sane!
final String deviceKey = device.getUniqueID();
- HashMap<String /*GLProfile_name*/, GLProfile> map = deviceConn2ProfileMap.get(deviceKey);
+ final HashMap<String /*GLProfile_name*/, GLProfile> map = deviceConn2ProfileMap.get(deviceKey);
if( null == map ) {
throw new InternalError("GLContext Avail. GLVersion is set - but no profile map for device: "+device);
}
@@ -1571,8 +1862,8 @@ public class GLProfile {
boolean addedDesktopProfile = false;
boolean addedEGLProfile = false;
- final boolean deviceIsDesktopCompatible = hasDesktopGLFactory && desktopFactory.getIsDeviceCompatible(device);
-
+ final boolean deviceIsDesktopCompatible = hasDesktopGLFactory && desktopFactory.getIsDeviceCompatible(device);
+
if( deviceIsDesktopCompatible ) {
// 1st pretend we have all Desktop and EGL profiles ..
computeProfileMap(device, true /* desktopCtxUndef*/, true /* esCtxUndef */);
@@ -1583,7 +1874,7 @@ public class GLProfile {
if(null != sharedResourceThread) {
initLock.addOwner(sharedResourceThread);
}
- boolean desktopSharedCtxAvail = desktopFactory.createSharedResource(device);
+ final boolean desktopSharedCtxAvail = desktopFactory.createSharedResource(device);
if(null != sharedResourceThread) {
initLock.removeOwner(sharedResourceThread);
}
@@ -1597,11 +1888,11 @@ public class GLProfile {
}
addedDesktopProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */);
}
-
+
final boolean deviceIsEGLCompatible = hasEGLFactory && eglFactory.getIsDeviceCompatible(device);
-
- // also test GLES1 and GLES2 on desktop, since we have implementations / emulations available.
- if( deviceIsEGLCompatible && ( hasGLES2Impl || hasGLES1Impl ) ) {
+
+ // also test GLES1, GLES2 and GLES3 on desktop, since we have implementations / emulations available.
+ if( deviceIsEGLCompatible && ( hasGLES3Impl || hasGLES1Impl ) ) {
// 1st pretend we have all EGL profiles ..
computeProfileMap(device, false /* desktopCtxUndef*/, true /* esCtxUndef */);
@@ -1611,16 +1902,16 @@ public class GLProfile {
if(null != sharedResourceThread) {
initLock.addOwner(sharedResourceThread);
}
- boolean eglSharedCtxAvail = eglFactory.createSharedResource(device);
+ final boolean eglSharedCtxAvail = eglFactory.createSharedResource(device);
if(null != sharedResourceThread) {
initLock.removeOwner(sharedResourceThread);
}
if(!eglSharedCtxAvail) {
// Remark: On Windows there is a libEGL.dll delivered w/ Chrome 15.0.874.121m and Firefox 8.0.1
- // but it seems even EGL.eglInitialize(eglDisplay, null, null)
+ // but it seems even EGL.eglInitialize(eglDisplay, null, null)
// fails in some scenarios (eg VirtualBox 4.1.6) w/ EGL error 0x3001 (EGL_NOT_INITIALIZED).
hasEGLFactory = false;
- hasGLES2Impl = false;
+ hasGLES3Impl = false;
hasGLES1Impl = false;
}
if (DEBUG) {
@@ -1638,7 +1929,7 @@ public class GLProfile {
System.err.println("GLProfile: desktoplFactory "+desktopFactory);
System.err.println("GLProfile: eglFactory "+eglFactory);
System.err.println("GLProfile: hasGLES1Impl "+hasGLES1Impl);
- System.err.println("GLProfile: hasGLES2Impl "+hasGLES2Impl);
+ System.err.println("GLProfile: hasGLES3Impl "+hasGLES3Impl);
}
}
@@ -1651,13 +1942,13 @@ public class GLProfile {
System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": "+glAvailabilityToString(device));
if(addedDesktopProfile) {
dumpGLInfo(desktopFactory, device);
- List<GLCapabilitiesImmutable> availCaps = desktopFactory.getAvailableCapabilities(device);
+ final List<GLCapabilitiesImmutable> availCaps = desktopFactory.getAvailableCapabilities(device);
for(int i=0; i<availCaps.size(); i++) {
System.err.println(availCaps.get(i));
}
} else if(addedEGLProfile) {
dumpGLInfo(eglFactory, device);
- List<GLCapabilitiesImmutable> availCaps = eglFactory.getAvailableCapabilities(device);
+ final List<GLCapabilitiesImmutable> availCaps = eglFactory.getAvailableCapabilities(device);
for(int i=0; i<availCaps.size(); i++) {
System.err.println(availCaps.get(i));
}
@@ -1667,8 +1958,8 @@ public class GLProfile {
return addedDesktopProfile || addedEGLProfile;
}
- private static void dumpGLInfo(GLDrawableFactoryImpl factory, AbstractGraphicsDevice device) {
- GLContext ctx = factory.getOrCreateSharedContext(device);
+ private static void dumpGLInfo(final GLDrawableFactoryImpl factory, final AbstractGraphicsDevice device) {
+ final GLContext ctx = factory.getOrCreateSharedContext(device);
if(null != ctx) {
System.err.println("GLProfile.dumpGLInfo: "+ctx);
ctx.makeCurrent();
@@ -1687,8 +1978,8 @@ public class GLProfile {
return defaultDevice;
}
- private static String array2String(String[] list) {
- StringBuilder msg = new StringBuilder();
+ private static String array2String(final String[] list) {
+ final StringBuilder msg = new StringBuilder();
msg.append("[");
for (int i = 0; i < list.length; i++) {
if (i > 0)
@@ -1699,8 +1990,8 @@ public class GLProfile {
return msg.toString();
}
- private static void glAvailabilityToString(AbstractGraphicsDevice device, StringBuilder sb, int major, int profile) {
- String str = GLContext.getAvailableGLVersionAsString(device, major, profile);
+ private static void glAvailabilityToString(final AbstractGraphicsDevice device, final StringBuilder sb, final int major, final int profile) {
+ final String str = GLContext.getAvailableGLVersionAsString(device, major, profile);
if(null==str) {
throw new GLException("Internal Error");
}
@@ -1709,38 +2000,38 @@ public class GLProfile {
sb.append("]");
}
- private static boolean computeProfileMap(AbstractGraphicsDevice device, boolean desktopCtxUndef, boolean esCtxUndef) {
+ private static boolean computeProfileMap(final AbstractGraphicsDevice device, final boolean desktopCtxUndef, final boolean esCtxUndef) {
if (DEBUG) {
System.err.println("GLProfile.init map "+device.getConnection()+", desktopCtxUndef "+desktopCtxUndef+", esCtxUndef "+esCtxUndef);
}
final boolean isHardwareRasterizer[] = new boolean[1];
GLProfile defaultGLProfileAny = null;
GLProfile defaultGLProfileHW = null;
- HashMap<String, GLProfile> _mappedProfiles = new HashMap<String, GLProfile>(GL_PROFILE_LIST_ALL.length + 1 /* default */);
+ final HashMap<String, GLProfile> _mappedProfiles = new HashMap<String, GLProfile>(GL_PROFILE_LIST_ALL.length + 1 /* default */);
for(int i=0; i<GL_PROFILE_LIST_ALL.length; i++) {
- String profile = GL_PROFILE_LIST_ALL[i];
- String profileImpl = computeProfileImpl(device, profile, desktopCtxUndef, esCtxUndef, isHardwareRasterizer);
- if(null!=profileImpl) {
+ final String profile = GL_PROFILE_LIST_ALL[i];
+ final String profileImpl = computeProfileImpl(device, profile, desktopCtxUndef, esCtxUndef, isHardwareRasterizer);
+ if( null != profileImpl ) {
final GLProfile glProfile;
- if(profile.equals(profileImpl)) {
- glProfile = new GLProfile(profile, null, isHardwareRasterizer[0]);
+ if( profile.equals( profileImpl ) ) {
+ glProfile = new GLProfile(profile, null, isHardwareRasterizer[0], false /* custom */);
} else {
- final GLProfile _mglp = _mappedProfiles.get(profileImpl);
- if(null == _mglp) {
- throw new InternalError("XXX0");
+ final GLProfile _mglp = _mappedProfiles.get( profileImpl );
+ if( null == _mglp ) {
+ throw new InternalError("XXX0 profile["+i+"]: "+profile+" -> profileImpl "+profileImpl+" !!! not mapped ");
}
- glProfile = new GLProfile(profile, _mglp, isHardwareRasterizer[0]);
+ glProfile = new GLProfile(profile, _mglp, isHardwareRasterizer[0], false /* custom */);
}
_mappedProfiles.put(profile, glProfile);
if (DEBUG) {
System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection());
}
- if(null==defaultGLProfileHW && isHardwareRasterizer[0]) {
+ if( null == defaultGLProfileHW && isHardwareRasterizer[0] ) {
defaultGLProfileHW=glProfile;
if (DEBUG) {
System.err.println("GLProfile.init map defaultHW "+glProfile+" on device "+device.getConnection());
}
- } else if(null==defaultGLProfileAny) {
+ } else if( null == defaultGLProfileAny ) {
defaultGLProfileAny=glProfile;
if (DEBUG) {
System.err.println("GLProfile.init map defaultAny "+glProfile+" on device "+device.getConnection());
@@ -1752,9 +2043,9 @@ public class GLProfile {
}
}
}
- if(null!=defaultGLProfileHW) {
+ if( null != defaultGLProfileHW ) {
_mappedProfiles.put(GL_DEFAULT, defaultGLProfileHW);
- } else if(null!=defaultGLProfileAny) {
+ } else if( null != defaultGLProfileAny ) {
_mappedProfiles.put(GL_DEFAULT, defaultGLProfileAny);
}
setProfileMap(device, _mappedProfiles);
@@ -1764,106 +2055,178 @@ public class GLProfile {
/**
* Returns the profile implementation
*/
- private static String computeProfileImpl(AbstractGraphicsDevice device, String profile, boolean desktopCtxUndef, boolean esCtxUndef, boolean isHardwareRasterizer[]) {
- // OSX GL3.. doesn't support GLSL<150,
- // hence GL2ES2 and GL2GL3 need to be mapped on GL2 on OSX for GLSL compatibility.
- final boolean isOSX = Platform.OS_TYPE == Platform.OSType.MACOS;
-
- if (GL2ES1.equals(profile)) {
- final boolean es1HardwareRasterizer[] = new boolean[1];
- final boolean gles1Available = hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device, es1HardwareRasterizer) );
- final boolean gles1HWAvailable = gles1Available && es1HardwareRasterizer[0] ;
+ private static String computeProfileImpl(final AbstractGraphicsDevice device, final String profile, final boolean desktopCtxUndef, final boolean esCtxUndef, final boolean isHardwareRasterizer[]) {
+ final boolean hardwareRasterizer[] = new boolean[1];
+ if ( GL2ES1 == profile ) {
+ final boolean gles1Available;
+ final boolean gles1HWAvailable;
+ if( hasGLES1Impl ) {
+ gles1Available = esCtxUndef || GLContext.isGLES1Available(device, hardwareRasterizer);
+ gles1HWAvailable = gles1Available && hardwareRasterizer[0] ;
+ } else {
+ gles1Available = false;
+ gles1HWAvailable = false;
+ }
if(hasGL234Impl) {
- if(GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) {
- if(!gles1HWAvailable || isHardwareRasterizer[0]) {
- return GL4bc;
- }
+ final boolean gl3bcAvailable = GLContext.isGL3bcAvailable(device, hardwareRasterizer);
+ final boolean gl3bcHWAvailable = gl3bcAvailable && hardwareRasterizer[0] ;
+ final boolean gl2Available = GLContext.isGL2Available(device, hardwareRasterizer);
+ final boolean gl2HWAvailable = gl2Available && hardwareRasterizer[0] ;
+ final boolean glAnyHWAvailable = gl3bcHWAvailable || gl2HWAvailable ||
+ gles1HWAvailable ;
+
+ if( GLContext.isGL4bcAvailable(device, isHardwareRasterizer) &&
+ ( isHardwareRasterizer[0] || !glAnyHWAvailable ) ) {
+ return GL4bc;
}
- if(GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) {
- if(!gles1HWAvailable || isHardwareRasterizer[0]) {
- return GL3bc;
- }
+ if( gl3bcAvailable && ( gl3bcHWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl3bcHWAvailable;
+ return GL3bc;
}
- if(desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer)) {
- if(!gles1HWAvailable || isHardwareRasterizer[0]) {
- return GL2;
- }
+ if( ( desktopCtxUndef || gl2Available ) && ( gl2HWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl2HWAvailable;
+ return GL2;
}
}
- if(gles1Available) {
- isHardwareRasterizer[0] = es1HardwareRasterizer[0];
+ if( gles1Available ) {
+ isHardwareRasterizer[0] = gles1HWAvailable;
return GLES1;
}
- } else if (GL2ES2.equals(profile)) {
- final boolean es2HardwareRasterizer[] = new boolean[1];
- final boolean gles2Available = hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device, es2HardwareRasterizer) );
- final boolean gles2HWAvailable = gles2Available && es2HardwareRasterizer[0] ;
- if(hasGL234Impl) {
- if(!isOSX) {
- if(GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) {
- if(!gles2HWAvailable || isHardwareRasterizer[0]) {
- return GL4bc;
- }
- }
- if(GLContext.isGL4Available(device, isHardwareRasterizer)) {
- if(!gles2HWAvailable || isHardwareRasterizer[0]) {
- return GL4;
- }
- }
- if(GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) {
- if(!gles2HWAvailable || isHardwareRasterizer[0]) {
- return GL3bc;
- }
- }
- if(GLContext.isGL3Available(device, isHardwareRasterizer)) {
- if(!gles2HWAvailable || isHardwareRasterizer[0]) {
- return GL3;
- }
- }
+ } else if ( GL2ES2 == profile ) {
+ final boolean gles2Available, gles3Available;
+ final boolean gles2HWAvailable, gles3HWAvailable;
+ if( hasGLES3Impl ) {
+ gles2Available = esCtxUndef || GLContext.isGLES2Available(device, hardwareRasterizer);
+ gles2HWAvailable = gles2Available && hardwareRasterizer[0] ;
+ gles3Available = esCtxUndef || GLContext.isGLES3Available(device, hardwareRasterizer);
+ gles3HWAvailable = gles3Available && hardwareRasterizer[0] ;
+ } else {
+ gles2Available = false;
+ gles2HWAvailable = false;
+ gles3Available = false;
+ gles3HWAvailable = false;
+ }
+ if( hasGL234Impl ) {
+ final boolean gl4bcAvailable = GLContext.isGL4bcAvailable(device, hardwareRasterizer);
+ final boolean gl4bcHWAvailable = gl4bcAvailable && hardwareRasterizer[0] ;
+ final boolean gl3Available = GLContext.isGL3Available(device, hardwareRasterizer);
+ final boolean gl3HWAvailable = gl3Available && hardwareRasterizer[0] ;
+ final boolean gl3bcAvailable = GLContext.isGL3bcAvailable(device, hardwareRasterizer);
+ final boolean gl3bcHWAvailable = gl3bcAvailable && hardwareRasterizer[0] ;
+ final boolean gl2Available = GLContext.isGL2Available(device, hardwareRasterizer);
+ final boolean gl2HWAvailable = gl2Available && hardwareRasterizer[0] ;
+ final boolean glAnyHWAvailable = gl4bcHWAvailable || gl3HWAvailable || gl3bcHWAvailable || gl2HWAvailable ||
+ gles3HWAvailable || gles2HWAvailable ;
+
+ if( GLContext.isGL4Available(device, isHardwareRasterizer) &&
+ ( isHardwareRasterizer[0] || !glAnyHWAvailable ) ) {
+ return GL4;
}
- if(desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer)) {
- if(!gles2HWAvailable || isHardwareRasterizer[0]) {
- return GL2;
- }
+ if( gl4bcAvailable && ( gl4bcHWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl4bcHWAvailable;
+ return GL4bc;
+ }
+ if( gl3Available && ( gl3HWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl3HWAvailable;
+ return GL3;
+ }
+ if( gl3bcAvailable && ( gl3bcHWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl3bcHWAvailable;
+ return GL3bc;
}
+ if( ( desktopCtxUndef || gl2Available ) && ( gl2HWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl2HWAvailable;
+ return GL2;
+ }
+ }
+ if( gles3Available && ( gles3HWAvailable || !gles2HWAvailable ) ) {
+ isHardwareRasterizer[0] = gles3HWAvailable;
+ return GLES3;
}
- if(gles2Available) {
- isHardwareRasterizer[0] = es2HardwareRasterizer[0];
+ if( gles2Available ) {
+ isHardwareRasterizer[0] = gles2HWAvailable;
return GLES2;
}
- } else if(GL2GL3.equals(profile)) {
+ } else if (GL4ES3 == profile) {
+ final boolean gles3CompatAvail = GLContext.isGLES3CompatibleAvailable(device);
+ if( desktopCtxUndef || esCtxUndef || gles3CompatAvail ) {
+ final boolean es3HardwareRasterizer[] = new boolean[1];
+ final boolean gles3Available = hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, es3HardwareRasterizer) );
+ final boolean gles3HWAvailable = gles3Available && es3HardwareRasterizer[0] ;
+ if( hasGL234Impl ) {
+ final boolean gl4bcAvailable = GLContext.isGL4bcAvailable(device, hardwareRasterizer);
+ final boolean gl4bcHWAvailable = gl4bcAvailable && hardwareRasterizer[0] ;
+ final boolean glAnyHWAvailable = gl4bcHWAvailable ||
+ gles3HWAvailable;
+
+ if( GLContext.isGL4Available(device, isHardwareRasterizer) &&
+ ( isHardwareRasterizer[0] || !glAnyHWAvailable ) ) {
+ return GL4;
+ }
+ if( ( desktopCtxUndef || gl4bcAvailable ) && ( gl4bcHWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl4bcHWAvailable;
+ return GL4bc;
+ }
+ }
+ if(gles3Available) {
+ isHardwareRasterizer[0] = es3HardwareRasterizer[0];
+ return GLES3;
+ }
+ }
+ } else if(GL2GL3 == profile) {
if(hasGL234Impl) {
- if(!isOSX && GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) {
+ final boolean gl4Available = GLContext.isGL4Available(device, hardwareRasterizer);
+ final boolean gl4HWAvailable = gl4Available && hardwareRasterizer[0] ;
+ final boolean gl3Available = GLContext.isGL3Available(device, hardwareRasterizer);
+ final boolean gl3HWAvailable = gl3Available && hardwareRasterizer[0] ;
+ final boolean gl3bcAvailable = GLContext.isGL3bcAvailable(device, hardwareRasterizer);
+ final boolean gl3bcHWAvailable = gl3bcAvailable && hardwareRasterizer[0] ;
+ final boolean gl2Available = GLContext.isGL2Available(device, hardwareRasterizer);
+ final boolean gl2HWAvailable = gl2Available && hardwareRasterizer[0] ;
+ final boolean glAnyHWAvailable = gl4HWAvailable || gl3HWAvailable || gl3bcHWAvailable || gl2HWAvailable;
+
+ if( GLContext.isGL4bcAvailable(device, isHardwareRasterizer) &&
+ ( isHardwareRasterizer[0] || !glAnyHWAvailable ) ) {
return GL4bc;
- } else if(!isOSX && GLContext.isGL4Available(device, isHardwareRasterizer)) {
+ }
+ if( gl4Available && ( gl4HWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl4HWAvailable;
return GL4;
- } else if(!isOSX && GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) {
+ }
+ if( gl3bcAvailable && ( gl3bcHWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl3bcHWAvailable;
return GL3bc;
- } else if(!isOSX && GLContext.isGL3Available(device, isHardwareRasterizer)) {
+ }
+ if( gl3Available && ( gl3HWAvailable || !glAnyHWAvailable ) ) {
+ isHardwareRasterizer[0] = gl3HWAvailable;
return GL3;
- } else if(desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer)) {
+ }
+ if( desktopCtxUndef || gl2Available ) {
+ isHardwareRasterizer[0] = gl2HWAvailable;
return GL2;
}
}
- } else if(GL4bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4bcAvailable(device, isHardwareRasterizer))) {
- return GL4bc;
- } else if(GL4.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4Available(device, isHardwareRasterizer))) {
- return GL4;
- } else if(GL3bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3bcAvailable(device, isHardwareRasterizer))) {
- return GL3bc;
- } else if(GL3.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3Available(device, isHardwareRasterizer))) {
- return GL3;
- } else if(GL2.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer))) {
- return GL2;
- } else if(GLES2.equals(profile) && hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device, isHardwareRasterizer))) {
- return GLES2;
- } else if(GLES1.equals(profile) && hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device, isHardwareRasterizer))) {
- return GLES1;
+ } else if(GL4bc == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4bcAvailable(device, isHardwareRasterizer))) {
+ return desktopCtxUndef ? GL4bc : GLContext.getAvailableGLProfileName(device, 4, GLContext.CTX_PROFILE_COMPAT);
+ } else if(GL4 == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4Available(device, isHardwareRasterizer))) {
+ return desktopCtxUndef ? GL4 : GLContext.getAvailableGLProfileName(device, 4, GLContext.CTX_PROFILE_CORE);
+ } else if(GL3bc == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3bcAvailable(device, isHardwareRasterizer))) {
+ return desktopCtxUndef ? GL3bc : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_COMPAT);
+ } else if(GL3 == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3Available(device, isHardwareRasterizer))) {
+ return desktopCtxUndef ? GL3 : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_CORE);
+ } else if(GL2 == profile && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer))) {
+ return desktopCtxUndef ? GL2 : GLContext.getAvailableGLProfileName(device, 2, GLContext.CTX_PROFILE_COMPAT);
+ } else if(GLES3 == profile && hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, isHardwareRasterizer))) {
+ return esCtxUndef ? GLES3 : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_ES);
+ } else if(GLES2 == profile && hasGLES3Impl && ( esCtxUndef || GLContext.isGLES2Available(device, isHardwareRasterizer))) {
+ return esCtxUndef ? GLES2 : GLContext.getAvailableGLProfileName(device, 2, GLContext.CTX_PROFILE_ES);
+ } else if(GLES1 == profile && hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device, isHardwareRasterizer))) {
+ return esCtxUndef ? GLES1 : GLContext.getAvailableGLProfileName(device, 1, GLContext.CTX_PROFILE_ES);
}
return null;
}
- private static /*final*/ HashMap<String /*device_connection*/, HashMap<String /*GLProfile_name*/, GLProfile>> deviceConn2ProfileMap =
+ private static /*final*/ HashMap<String /*device_connection*/, HashMap<String /*GLProfile_name*/, GLProfile>> deviceConn2ProfileMap =
new HashMap<String /*device_connection*/, HashMap<String /*GLProfile_name*/, GLProfile>>();
/**
@@ -1874,22 +2237,22 @@ public class GLProfile {
*
* @param device the key 'device -> GLProfiles-Map'
* @param throwExceptionOnZeroProfile true if <code>GLException</code> shall be thrown in case of no mapped profile, otherwise false.
- * @return the GLProfile HashMap if exists, otherwise null
+ * @return the GLProfile HashMap if exists, otherwise null
* @throws GLException if no profile for the given device is available.
*/
- private static HashMap<String /*GLProfile_name*/, GLProfile> getProfileMap(AbstractGraphicsDevice device, boolean throwExceptionOnZeroProfile)
- throws GLException
+ private static HashMap<String /*GLProfile_name*/, GLProfile> getProfileMap(AbstractGraphicsDevice device, final boolean throwExceptionOnZeroProfile)
+ throws GLException
{
initSingleton();
if(null==defaultDevice) { // avoid NPE and notify of incomplete initialization
throw new GLException("No default device available");
}
-
+
if(null==device) {
device = defaultDevice;
}
-
+
final String deviceKey = device.getUniqueID();
HashMap<String /*GLProfile_name*/, GLProfile> map = deviceConn2ProfileMap.get(deviceKey);
if( null != map ) {
@@ -1909,19 +2272,25 @@ public class GLProfile {
return map;
}
- private static void setProfileMap(AbstractGraphicsDevice device, HashMap<String /*GLProfile_name*/, GLProfile> mappedProfiles) {
+ private static void setProfileMap(final AbstractGraphicsDevice device, final HashMap<String /*GLProfile_name*/, GLProfile> mappedProfiles) {
synchronized ( deviceConn2ProfileMap ) {
deviceConn2ProfileMap.put(device.getUniqueID(), mappedProfiles);
}
}
- private GLProfile(String profile, GLProfile profileImpl, boolean isHardwareRasterizer) {
+ private GLProfile(final String profile, final GLProfile profileImpl, final boolean isHardwareRasterizer, final boolean isCustom) {
this.profile = profile;
this.profileImpl = profileImpl;
this.isHardwareRasterizer = isHardwareRasterizer;
+ this.isCustom = isCustom;
+ }
+
+ public static GLProfile createCustomGLProfile(final String profile, final GLProfile profileImpl) {
+ return new GLProfile(profile, profileImpl, profileImpl.isHardwareRasterizer, true);
}
private final GLProfile profileImpl;
private final String profile;
private final boolean isHardwareRasterizer;
+ private final boolean isCustom;
}
diff --git a/src/jogl/classes/javax/media/opengl/GLRunnable.java b/src/jogl/classes/javax/media/opengl/GLRunnable.java
index 1ae1c9b22..ad68662ce 100644
--- a/src/jogl/classes/javax/media/opengl/GLRunnable.java
+++ b/src/jogl/classes/javax/media/opengl/GLRunnable.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package javax.media.opengl;
/**
@@ -33,8 +33,8 @@ package javax.media.opengl;
* Declares a one-shot OpenGL command usable for injection
* via {@link GLAutoDrawable#invoke(boolean, javax.media.opengl.GLRunnable)}.<br>
* {@link GLAutoDrawable} executes the GLRunnables within it's {@link GLAutoDrawable#display() display()}
- * method after all registered {@link GLEventListener}s
- * {@link GLEventListener#display(GLAutoDrawable) display(GLAutoDrawable)}
+ * method after all registered {@link GLEventListener}s
+ * {@link GLEventListener#display(GLAutoDrawable) display(GLAutoDrawable)}
* methods has been called.
* </p>
* <p>
@@ -44,13 +44,13 @@ package javax.media.opengl;
* This might be useful to inject OpenGL commands from an I/O event listener.
* </p>
*/
-public interface GLRunnable {
+public interface GLRunnable {
/**
* @param drawable the associated drawable and current context for this call
* @return true if the GL [back] framebuffer remains intact by this runnable, otherwise false.
* If returning false {@link GLAutoDrawable} will call
- * {@link GLEventListener#display(GLAutoDrawable) display(GLAutoDrawable)}
- * of all registered {@link GLEventListener}s once more.
+ * {@link GLEventListener#display(GLAutoDrawable) display(GLAutoDrawable)}
+ * of all registered {@link GLEventListener}s once more.
* @see GLRunnable
*/
boolean run(GLAutoDrawable drawable);
diff --git a/src/jogl/classes/javax/media/opengl/GLRunnable2.java b/src/jogl/classes/javax/media/opengl/GLRunnable2.java
new file mode 100644
index 000000000..5f0393257
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/GLRunnable2.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.opengl;
+
+/**
+ * <p>
+ * Declares a one-shot OpenGL command.
+ * </p>
+ */
+public interface GLRunnable2<T,U> {
+ /**
+ * @param gl a current GL object
+ * @param args custom arguments
+ * @return the desired object
+ */
+ T run(GL gl, U args);
+}
+
diff --git a/src/jogl/classes/javax/media/opengl/GLSharedContextSetter.java b/src/jogl/classes/javax/media/opengl/GLSharedContextSetter.java
new file mode 100644
index 000000000..b8aef126b
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/GLSharedContextSetter.java
@@ -0,0 +1,181 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.opengl;
+
+import com.jogamp.opengl.GLRendererQuirks;
+
+/**
+ * Adds capabilities to set a shared {@link GLContext} directly or via an {@link GLAutoDrawable}.
+ * <p>
+ * Sharing of server-side OpenGL objects such as buffer objects, e.g. VBOs,
+ * and textures among OpenGL contexts is supported with this interface.
+ * </p>
+ * <p>
+ * A <i>master</i> {@link GLContext} is the {@link GLContext} which is created first.
+ * Subsequent shared {@link GLContext} w/ the <i>master</i> are referred as <i>slave</i> {@link GLContext}.
+ * </p>
+ * <p>
+ * Implementations of this interface control the <i>slave's</i> {@link GLContext} and {@link GLAutoDrawable} realization,
+ * i.e. the <i>slave</i> {@link GLAutoDrawable} will not be realized before their associated <i>master</i>.
+ * </p>
+ * <p>
+ * Using the nearest or same {@link GLCapabilitiesImmutable#getVisualID(javax.media.nativewindow.VisualIDHolder.VIDType) visual ID}
+ * or {@link GLCapabilitiesImmutable caps} across the shared {@link GLDrawable}s will yield best compatibility.
+ * </p>
+ * <h5><a name="lifecycle">Lifecycle Considerations</a></h5>
+ * <p>
+ * After shared objects are created on the <i>master</i>, the OpenGL pipeline
+ * might need to be synchronized w/ the <i>slaves</i>, e.g. via {@link GL#glFinish()}.
+ * At least this has been experienced w/ OSX 10.9.
+ * </p>
+ * <p>
+ * In general, destroying a <i>master</i> {@link GLContext} before their shared <i>slaves</i>
+ * shall be permissible, i.e. the OpenGL driver needs to handle pending destruction of shared resources.
+ * This is confirmed to work properly on most platform/driver combinations,
+ * see unit test <code>com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT3</code> and similar.
+ * </p>
+ * <p>
+ * However, to avoid scenarios with buggy drivers, users <i>may not</i> destroy the
+ * <i>master</i> {@link GLContext} before its shared <i>slave</i> {@link GLContext} instances
+ * <i>as long as they are using them</i>.<br>
+ * Otherwise the OpenGL driver may crash w/ SIGSEGV, due to using already destroyed shared resources,
+ * if not handling the pending destruction of the latter!<br>
+ * Either proper lifecycle synchronization is implemented, e.g. by notifying the <i>slaves</i> about the loss of the shared resources,
+ * <i>or</i> the <i>slaves</i> validate whether the resources are still valid.
+ * </p>
+ * <p>
+ * To simplify above lifecycle issues, one may use a {@link GLDrawableFactory#createDummyDrawable(javax.media.nativewindow.AbstractGraphicsDevice, boolean, GLCapabilitiesImmutable, GLCapabilitiesChooser) dummy}
+ * {@link GLDrawable} and it's {@link GLContext} as the <i>master</i> of all shared <i>slave</i> {@link GLContext}.
+ * Since this <i>dummy instance</i> does not depend on any native windowing system, it can be controlled easily w/o being <i>in sight</i>.<br>
+ * Below code creates a {@link GLAutoDrawable} based on a <i>dummy GLDrawable</i>:
+ * <pre>
+ // GLProfile and GLCapabilities should be equal across all shared GL drawable/context.
+ final GLCapabilitiesImmutable caps = ... ;
+ final GLProfile glp = caps.getGLProfile();
+ ..
+ final boolean createNewDevice = true; // use 'own' display device!
+ final GLAutoDrawable sharedDrawable = GLDrawableFactory.getFactory(glp).createDummyAutoDrawable(null, createNewDevice, caps, null);
+ sharedDrawable.display(); // triggers GLContext object creation and native realization.
+ ...
+ // Later a shared 'slave' can be created e.g.:
+ GLWindow glad = GLWindow.create(caps); // or any other GLAutoDrawable supporting GLSharedContextSetter
+ glad.setSharedAutoDrawable(sharedDrawable);
+ glad.addGLEventListener(..);
+ glad.setVisible(true); // GLWindow creation ..
+ * </pre>
+ * </p>
+ * <h5><a name="synchronization">GL Object Synchronization</a></h5>
+ * <p>
+ * Usually synchronization of shared GL objects should not be required, if the shared GL objects
+ * are created and immutable before concurrent usage.
+ * </p>
+ * <p>
+ * However, using drivers exposing {@link GLRendererQuirks#NeedSharedObjectSync} always
+ * require the user to synchronize access of shared GL objects.
+ * </p>
+ * <p>
+ * Synchronization can be avoided if accessing the shared GL objects
+ * exclusively via a queue or {@link com.jogamp.common.util.Ringbuffer Ringbuffer}, see GLMediaPlayerImpl as an example.
+ * </p>
+ * </p>
+ * <h5><a name="driverissues">Known Driver Issues</a></h5>
+ * <h7><a name="intelmesa">Intel's Mesa >= 9.1.2 Backend for [Sandybridge/Ivybridge] on GNU/Linux</a></h7>
+ * <p>
+ * <pre>
+ * Error: 'intel_do_flush_locked: No such file or directory'
+ * JogAmp: https://jogamp.org/bugzilla/show_bug.cgi?id=873
+ * freedesktop.org: https://bugs.freedesktop.org/show_bug.cgi?id=41736#c8
+ * </pre>
+ * Shared context seems not to be supported w/ lock-free bound X11 display connections
+ * per OpenGL drawable/context. The error message above is thrown in this case.
+ * Hence the driver bug renders shared context use w/ JOGL impossible.
+ * </p>
+ * <h7><a name="hisilicon">Hisilicon's Immersion.16 on Android</a></h7>
+ * <p>
+ * We failed to create a shared ES2 context on another thread.
+ * </p>
+ */
+public interface GLSharedContextSetter extends GLAutoDrawable {
+ /**
+ * Specifies an {@link GLContext OpenGL context}, which shall be shared by this {@link GLAutoDrawable}'s {@link GLContext}.
+ * <p>
+ * Since the {@link GLDrawable drawable} and {@link GLContext context} is created
+ * at {@link GLAutoDrawable#initialization GLAutoDrawable initialization}
+ * this method shall be called beforehand to have any effect.
+ * </p>
+ * <p>
+ * A set <i>sharedContext</i> will block context creation, i.e. {@link GLAutoDrawable#initialization GLAutoDrawable initialization},
+ * as long it is not {@link GLContext#isCreated() created natively}.
+ * </p>
+ * <p>
+ * The <i>preferred method</i> of assigning a <i>shared context</i> is
+ * to {@link #setSharedAutoDrawable(GLAutoDrawable) set the shared GLAutoDrawable},
+ * since this method also takes the {@link GLEventListener}
+ * {@link GLAutoDrawable#areAllGLEventListenerInitialized() initialization into account}.
+ * </p>
+ * <p>
+ * See <a href="#lifecycle">Lifecycle Considerations</a>.
+ * </p>
+ *
+ * @param sharedContext The OpenGL context to be shared by this {@link GLAutoDrawable}'s {@link GLContext}.
+ * @throws IllegalStateException if a {@link #setSharedContext(GLContext) shared GLContext}
+ * or {@link #setSharedAutoDrawable(GLAutoDrawable) shared GLAutoDrawable} is already set,
+ * the given sharedContext is null or equal to this {@link GLAutoDrawable}'s context.
+ * @see #setSharedAutoDrawable(GLAutoDrawable)
+ */
+ void setSharedContext(GLContext sharedContext) throws IllegalStateException;
+
+ /**
+ * Specifies an {@link GLAutoDrawable}, which {@link GLContext OpenGL context} shall be shared by this {@link GLAutoDrawable}'s {@link GLContext}.
+ * <p>
+ * Since the {@link GLDrawable drawable} and {@link GLContext context} is created
+ * at {@link GLAutoDrawable#initialization GLAutoDrawable initialization}
+ * this method shall be called beforehand to have any effect.
+ * </p>
+ * <p>
+ * A set <i>sharedAutoDrawable</i> will block context creation, i.e. <a href="GLAutoDrawable.html#initialization">initialization</a>
+ * as long it's
+ * <ul>
+ * <li>{@link GLContext} is <code>null</code>, or</li>
+ * <li>{@link GLContext} has not been {@link GLContext#isCreated() created natively}, or</li>
+ * <li>{@link GLEventListener} are <i>not</i> {@link GLAutoDrawable#areAllGLEventListenerInitialized() completely initialized}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * See <a href="#lifecycle">Lifecycle Considerations</a>.
+ * </p>
+ *
+ * @param sharedContext The GLAutoDrawable, which OpenGL context shall be shared by this {@link GLAutoDrawable}'s {@link GLContext}.
+ * @throws IllegalStateException if a {@link #setSharedContext(GLContext) shared GLContext}
+ * or {@link #setSharedAutoDrawable(GLAutoDrawable) shared GLAutoDrawable} is already set,
+ * the given sharedAutoDrawable is null or equal to this GLAutoDrawable.
+ * @see #setSharedContext(GLContext)
+ */
+ void setSharedAutoDrawable(GLAutoDrawable sharedAutoDrawable) throws IllegalStateException;
+}
diff --git a/src/jogl/classes/javax/media/opengl/GLUniformData.java b/src/jogl/classes/javax/media/opengl/GLUniformData.java
index 475ff4546..47f07539b 100644
--- a/src/jogl/classes/javax/media/opengl/GLUniformData.java
+++ b/src/jogl/classes/javax/media/opengl/GLUniformData.java
@@ -3,6 +3,9 @@ package javax.media.opengl;
import java.nio.*;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.math.FloatUtil;
+
public class GLUniformData {
/**
@@ -11,8 +14,8 @@ public class GLUniformData {
* Number of objects is 1
*
*/
- public GLUniformData(String name, int val) {
- init(name, 1, new Integer(val));
+ public GLUniformData(final String name, final int val) {
+ initScalar(name, 1, Integer.valueOf(val));
}
/**
@@ -21,8 +24,8 @@ public class GLUniformData {
* Number of objects is 1
*
*/
- public GLUniformData(String name, float val) {
- init(name, 1, new Float(val));
+ public GLUniformData(final String name, final float val) {
+ initScalar(name, 1, Float.valueOf(val));
}
/**
@@ -32,8 +35,8 @@ public class GLUniformData {
*
* @param components number of elements of one object, ie 4 for GL_FLOAT_VEC4,
*/
- public GLUniformData(String name, int components, IntBuffer data) {
- init(name, components, data);
+ public GLUniformData(final String name, final int components, final IntBuffer data) {
+ initBuffer(name, components, data);
}
/**
@@ -43,8 +46,20 @@ public class GLUniformData {
*
* @param components number of elements of one object, ie 4 for GL_FLOAT_VEC4,
*/
- public GLUniformData(String name, int components, FloatBuffer data) {
- init(name, components, data);
+ public GLUniformData(final String name, final int components, final FloatBuffer data) {
+ initBuffer(name, components, data);
+ }
+
+ private GLUniformData(final int components, final String name) {
+ initBuffer(name, components, null);
+ }
+
+ public static GLUniformData creatEmptyVector(final String name, final int components) {
+ return new GLUniformData(components, name);
+ }
+
+ public static GLUniformData creatEmptyMatrix(final String name, final int rows, final int columns) {
+ return new GLUniformData(name, rows, columns, null);
}
/**
@@ -55,31 +70,51 @@ public class GLUniformData {
* @param rows the matrix rows
* @param column the matrix column
*/
- public GLUniformData(String name, int rows, int columns, FloatBuffer data) {
- init(name, rows, columns, data);
+ public GLUniformData(final String name, final int rows, final int columns, final FloatBuffer data) {
+ initBuffer(name, rows, columns, data);
}
- public GLUniformData setData(int data) { init(new Integer(data)); return this; }
- public GLUniformData setData(float data) { init(new Float(data)); return this; }
- public GLUniformData setData(IntBuffer data) { init(data); return this; }
- public GLUniformData setData(FloatBuffer data) { init(data); return this; }
+ public GLUniformData setData(final int data) { initScalar(Integer.valueOf(data)); return this; }
+ public GLUniformData setData(final float data) { initScalar(Float.valueOf(data)); return this; }
+ public GLUniformData setData(final IntBuffer data) { initBuffer(data); return this; }
+ public GLUniformData setData(final FloatBuffer data) { initBuffer(data); return this; }
public int intValue() { return ((Integer)data).intValue(); };
public float floatValue() { return ((Float)data).floatValue(); };
public IntBuffer intBufferValue() { return (IntBuffer)data; };
public FloatBuffer floatBufferValue() { return (FloatBuffer)data; };
+ public StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("GLUniformData[name ").append(name).
+ append(", location ").append(location).
+ append(", size ").append(rows).append("x").append(columns).
+ append(", count ").append(count).
+ append(", data ");
+ if(isMatrix() && data instanceof FloatBuffer) {
+ sb.append("\n");
+ final FloatBuffer fb = (FloatBuffer)getBuffer();
+ for(int i=0; i<count; i++) {
+ FloatUtil.matrixToString(sb, i+": ", "%10.5f", fb, i*rows*columns, rows, columns, false);
+ sb.append(",\n");
+ }
+ } else if(isBuffer()) {
+ Buffers.toString(sb, null, getBuffer());
+ } else {
+ sb.append(data);
+ }
+ sb.append("]");
+ return sb;
+ }
+
+ @Override
public String toString() {
- return "GLUniformData[name "+name+
- ", location "+location+
- ", size "+rows+"*"+columns+
- ", count "+count+
- ", matrix "+isMatrix+
- ", data "+data+
- "]";
+ return toString(null).toString();
}
- private void init(String name, int rows, int columns, Object data) {
+ private void initBuffer(final String name, final int rows, final int columns, final Buffer buffer) {
if( 2>rows || rows>4 || 2>columns || columns>4 ) {
throw new GLException("rowsXcolumns must be within [2..4]X[2..4], is: "+rows+"X"+columns);
}
@@ -88,10 +123,9 @@ public class GLUniformData {
this.columns=columns;
this.isMatrix=true;
this.location=-1;
- init(data);
+ initBuffer(buffer);
}
-
- private void init(String name, int components, Object data) {
+ private void initScalar(final String name, final int components, final Object data) {
if( 1>components || components>4 ) {
throw new GLException("components must be within [1..4], is: "+components);
}
@@ -100,24 +134,47 @@ public class GLUniformData {
this.rows=1;
this.isMatrix=false;
this.location=-1;
- init(data);
+ initScalar(data);
+ }
+ private void initBuffer(final String name, final int components, final Buffer buffer) {
+ if( 1>components || components>4 ) {
+ throw new GLException("components must be within [1..4], is: "+components);
+ }
+ this.name=name;
+ this.columns=components;
+ this.rows=1;
+ this.isMatrix=false;
+ this.location=-1;
+ initBuffer(buffer);
}
- private void init(Object data) {
+ private void initScalar(final Object data) {
if(data instanceof Buffer) {
+ initBuffer((Buffer)data);
+ } else if( null != data ) {
+ if(isMatrix) {
+ throw new GLException("Atom type not allowed for matrix : "+this);
+ }
+ this.count=1;
+ this.data=data;
+ } else {
+ this.count=0;
+ this.data=data;
+ }
+ }
+
+ private void initBuffer(final Buffer buffer) {
+ if( null != buffer ) {
final int sz = rows*columns;
- final Buffer buffer = (Buffer)data;
if(buffer.remaining()<sz || 0!=buffer.remaining()%sz) {
throw new GLException("remaining data buffer size invalid: buffer: "+buffer.toString()+"\n\t"+this);
}
- this.count=buffer.remaining()/(rows*columns);
+ this.count=buffer.remaining()/sz;
+ this.data=buffer;
} else {
- if(isMatrix) {
- throw new GLException("Atom type not allowed for matrix : "+this);
- }
- this.count=1;
+ this.count=0;
+ this.data=null;
}
- this.data=data;
}
public String getName() { return name; }
@@ -125,9 +182,25 @@ public class GLUniformData {
public int getLocation() { return location; }
/**
- * Sets the determined location of the shader uniform.
+ * Sets the given location of the shader uniform.
+ * @return the given location
*/
- public GLUniformData setLocation(int location) { this.location=location; return this; }
+ public int setLocation(final int location) { this.location=location; return location; }
+
+ /**
+ * Retrieves the location of the shader uniform from the linked shader program.
+ * <p>
+ * No validation is performed within the implementation.
+ * </p>
+ * @param gl
+ * @param program
+ * @return &ge;0 denotes a valid uniform location as found and used in the given shader program.
+ * &lt;0 denotes an invalid location, i.e. not found or used in the given shader program.
+ */
+ public int setLocation(final GL2ES2 gl, final int program) {
+ location = gl.glGetUniformLocation(program, name);
+ return location;
+ }
public Object getObject() {
return data;
diff --git a/src/jogl/classes/javax/media/opengl/Threading.java b/src/jogl/classes/javax/media/opengl/Threading.java
index 4788f9cf6..c8d8d0071 100644
--- a/src/jogl/classes/javax/media/opengl/Threading.java
+++ b/src/jogl/classes/javax/media/opengl/Threading.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -42,7 +42,7 @@ package javax.media.opengl;
import jogamp.opengl.ThreadingImpl;
-/** This API provides access to the threading model for the implementation of
+/** This API provides access to the threading model for the implementation of
the classes in this package.
<P>
@@ -59,12 +59,12 @@ import jogamp.opengl.ThreadingImpl;
Due to these limitations, and due to the inherent multithreading
in the Java platform (in particular, in the Abstract Window
- Toolkit), it is often necessary to limit the multithreading
- occurring in the typical application using the OpenGL API.
+ Toolkit), it is often necessary to limit the multithreading
+ occurring in the typical application using the OpenGL API.
<P>
- In the current reference implementation, for instance, multithreading
+ In the current reference implementation, for instance, multithreading
has been limited by
forcing all OpenGL-related work for GLAutoDrawables on to a single
thread. In other words, if an application uses only the
@@ -93,9 +93,9 @@ import jogamp.opengl.ThreadingImpl;
This class also provides mechanisms for querying whether this
internal serialization of OpenGL work is in effect, and a
- programmatic way of disabling it. In the current reference
- implementation it is enabled by default, although it could be
- disabled in the future if OpenGL drivers become more robust on
+ programmatic way of disabling it. In the current reference
+ implementation it is enabled by default, although it could be
+ disabled in the future if OpenGL drivers become more robust on
all platforms.
<P>
@@ -113,27 +113,53 @@ import jogamp.opengl.ThreadingImpl;
platforms, and also the default behavior older releases)
-Djogl.1thread=worker Enable single-threading of OpenGL work on newly-created worker thread (not suitable for Mac
OS X or X11 platforms, and risky on Windows in applet environments)
- </PRE>
+ </PRE>
*/
public class Threading {
+ public static enum Mode {
+ /**
+ * Full multithreaded OpenGL,
+ * i.e. any {@link Threading#invoke(boolean, Runnable, Object) invoke}
+ * {@link Threading#invokeOnOpenGLThread(boolean, Runnable) commands}
+ * will be issued on the current thread immediately.
+ */
+ MT(0),
+
+ /** Single-Threaded OpenGL on AWT EDT */
+ ST_AWT(1),
+
+ /** Single-Threaded OpenGL on dedicated worker thread. */
+ ST_WORKER(2);
+
+ public final int id;
+
+ Mode(final int id){
+ this.id = id;
+ }
+ }
/** No reason to ever instantiate this class */
private Threading() {}
- /** If an implementation of the javax.media.opengl APIs offers a
- multithreading option but the default behavior is single-threading,
- this API provides a mechanism for end users to disable single-threading
+ /** Returns the threading mode */
+ public static Mode getMode() {
+ return ThreadingImpl.getMode();
+ }
+
+ /** If an implementation of the javax.media.opengl APIs offers a
+ multithreading option but the default behavior is single-threading,
+ this API provides a mechanism for end users to disable single-threading
in this implementation. Users are strongly discouraged from
calling this method unless they are aware of all of the
consequences and are prepared to enforce some amount of
threading restrictions in their applications. Disabling
single-threading, for example, may have unintended consequences
- on GLAutoDrawable implementations such as GLCanvas, GLJPanel and
- GLPbuffer. Currently there is no supported way to re-enable it
+ on GLAutoDrawable implementations such as GLCanvas and GLJPanel.
+ Currently there is no supported way to re-enable it
once disabled, partly to discourage careless use of this
method. This method should be called as early as possible in an
- application. */
+ application. */
public static final void disableSingleThreading() {
ThreadingImpl.disableSingleThreading();
}
@@ -145,15 +171,19 @@ public class Threading {
}
/** Indicates whether the current thread is the designated toolkit thread,
- if such semantics exists. */
+ if such semantics exists. */
public static final boolean isToolkitThread() throws GLException {
return ThreadingImpl.isToolkitThread();
}
-
- /** Indicates whether the current thread is the single thread on
- which this implementation of the javax.media.opengl APIs
- performs all of its OpenGL-related work. This method should only
- be called if the single-thread model is in effect. */
+
+ /**
+ * Indicates whether the current thread is capable of
+ * performing OpenGL-related work.
+ * <p>
+ * Method always returns <code>true</code>
+ * if {@link #getMode()} == {@link Mode#MT} or {@link #isSingleThreaded()} == <code>false</code>.
+ * </p>
+ */
public static final boolean isOpenGLThread() throws GLException {
return ThreadingImpl.isOpenGLThread();
}
@@ -166,27 +196,27 @@ public class Threading {
thread (i.e., if <code>isOpenGLThread()</code> returns
false). It is up to the end user to check to see whether the
current thread is the OpenGL thread and either execute the
- Runnable directly or perform the work inside it.
+ Runnable directly or perform the work inside it.
**/
- public static final void invokeOnOpenGLThread(boolean wait, Runnable r) throws GLException {
+ public static final void invokeOnOpenGLThread(final boolean wait, final Runnable r) throws GLException {
ThreadingImpl.invokeOnOpenGLThread(wait, r);
}
-
+
/**
- * If {@link #isSingleThreaded()} <b>and</b> not {@link #isOpenGLThread()}
+ * If not {@link #isOpenGLThread()}
* <b>and</b> the <code>lock</code> is not being hold by this thread,
* invoke Runnable <code>r</code> on the OpenGL thread via {@link #invokeOnOpenGLThread(boolean, Runnable)}.
* <p>
* Otherwise invoke Runnable <code>r</code> on the current thread.
* </p>
- *
- * @param wait set to true for waiting until Runnable <code>r</code> is finished, otherwise false.
+ *
+ * @param wait set to true for waiting until Runnable <code>r</code> is finished, otherwise false.
* @param r the Runnable to be executed
* @param lock optional lock object to be tested
* @throws GLException
*/
- public static final void invoke(boolean wait, Runnable r, Object lock) throws GLException {
- if ( isSingleThreaded() && !isOpenGLThread() &&
+ public static final void invoke(final boolean wait, final Runnable r, final Object lock) throws GLException {
+ if ( !isOpenGLThread() &&
( null == lock || !Thread.holdsLock(lock) ) ) {
invokeOnOpenGLThread(wait, r);
} else {
diff --git a/src/jogl/classes/javax/media/opengl/TraceGL2.java b/src/jogl/classes/javax/media/opengl/TraceGL2.java
new file mode 100644
index 000000000..94d391d43
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/TraceGL2.java
@@ -0,0 +1,23 @@
+package javax.media.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL2 extends TraceGL4bc {
+ public TraceGL2(final GL2 downstream, final PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/TraceGL3.java b/src/jogl/classes/javax/media/opengl/TraceGL3.java
new file mode 100644
index 000000000..96e655902
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/TraceGL3.java
@@ -0,0 +1,23 @@
+package javax.media.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL3 extends TraceGL4bc {
+ public TraceGL3(final GL3 downstream, final PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/TraceGL3bc.java b/src/jogl/classes/javax/media/opengl/TraceGL3bc.java
new file mode 100644
index 000000000..2a8590236
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/TraceGL3bc.java
@@ -0,0 +1,23 @@
+package javax.media.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL3bc extends TraceGL4bc {
+ public TraceGL3bc(final GL3bc downstream, final PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/TraceGL4.java b/src/jogl/classes/javax/media/opengl/TraceGL4.java
new file mode 100644
index 000000000..d48f9926a
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/TraceGL4.java
@@ -0,0 +1,23 @@
+package javax.media.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGL4 extends TraceGL4bc {
+ public TraceGL4(final GL4 downstream, final PrintStream stream) {
+ super((GL4bc)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/TraceGLES2.java b/src/jogl/classes/javax/media/opengl/TraceGLES2.java
new file mode 100644
index 000000000..b58f169a7
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/TraceGLES2.java
@@ -0,0 +1,23 @@
+package javax.media.opengl;
+
+import java.io.PrintStream;
+
+/**
+ * <p>
+ * Composable pipeline which wraps an underlying {@link GL} implementation,
+ * providing tracing information to a user-specified {@link java.io.PrintStream}
+ * before and after each OpenGL method call.
+ * </p>
+ * <p>
+ * Sample code which installs this pipeline, manual:
+ * <pre>
+ * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));
+ * </pre>
+ * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}.
+ * </p>
+ */
+public class TraceGLES2 extends TraceGLES3 {
+ public TraceGLES2(final GLES2 downstream, final PrintStream stream) {
+ super((GLES3)downstream, stream);
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/awt/ComponentEvents.java b/src/jogl/classes/javax/media/opengl/awt/ComponentEvents.java
index 0c4f63c2d..5feaa5760 100644
--- a/src/jogl/classes/javax/media/opengl/awt/ComponentEvents.java
+++ b/src/jogl/classes/javax/media/opengl/awt/ComponentEvents.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 329cf9e3f..a648e3bf6 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -44,22 +44,26 @@ import java.beans.Beans;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
-
import java.awt.Canvas;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
+import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Rectangle2D;
-
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
+import java.util.List;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.OffscreenLayerOption;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -67,7 +71,6 @@ import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
-
import javax.media.opengl.GL;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
@@ -79,26 +82,33 @@ import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
+import javax.media.opengl.GLSharedContextSetter;
import javax.media.opengl.Threading;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.util.VersionUtil;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.nativewindow.awt.JAWTWindow;
import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.TileRenderer;
-import jogamp.common.awt.AWTEDTExecutor;
+import jogamp.nativewindow.SurfaceScaleUtils;
import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableHelper;
import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.awt.AWTTilePainter;
// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
// context whenever the displayChanged() function is called on our
@@ -110,17 +120,17 @@ import jogamp.opengl.GLDrawableImpl;
interfaces when adding a heavyweight doesn't work either because
of Z-ordering or LayoutManager problems.
*
- * <h5><A NAME="java2dgl">Offscreen Layer Remarks</A></h5>
- *
+ * <h5><a name="offscreenlayer">Offscreen Layer Remarks</a></h5>
+ *
* {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
- * maybe called to use an offscreen drawable (FBO or PBuffer) allowing
+ * maybe called to use an offscreen drawable (FBO or PBuffer) allowing
* the underlying JAWT mechanism to composite the image, if supported.
* <p>
* {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
* is being called if {@link GLCapabilitiesImmutable#isOnscreen()} is <code>false</code>.
* </p>
- *
- * <h5><A NAME="java2dgl">Java2D OpenGL Remarks</A></h5>
+ *
+ * <h5><a name="java2dgl">Java2D OpenGL Remarks</a></h5>
*
* To avoid any conflicts with a potential Java2D OpenGL context,<br>
* you shall consider setting the following JVM properties:<br>
@@ -137,7 +147,7 @@ import jogamp.opengl.GLDrawableImpl;
* <li><pre>sun.java2d.noddraw=true</pre></li>
* </ul>
*
- * <h5><A NAME="backgrounderase">Disable Background Erase</A></h5>
+ * <h5><a name="backgrounderase">Disable Background Erase</a></h5>
*
* GLCanvas tries to disable background erase for the AWT Canvas
* before native peer creation (X11) and after it (Windows), <br>
@@ -146,10 +156,18 @@ import jogamp.opengl.GLDrawableImpl;
* <ul>
* <li><pre>sun.awt.noerasebackground=true</pre></li>
* </ul>
+ *
+ * <p>
+ * <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a>
+ * To share a {@link GLContext} see the following note in the documentation overview:
+ * <a href="../../../../overview-summary.html#SHARING">context sharing</a>
+ * as well as {@link GLSharedContextSetter}.
+ * </p>
*/
@SuppressWarnings("serial")
-public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosingProtocol, OffscreenLayerOption {
+public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosingProtocol, OffscreenLayerOption,
+ AWTPrintLifecycle, GLSharedContextSetter, ScalableSurface {
private static final boolean DEBUG = Debug.debug("GLCanvas");
@@ -158,28 +176,41 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private AWTGraphicsConfiguration awtConfig;
private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
private volatile JAWTWindow jawtWindow; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
- private GLContextImpl context;
+ private volatile GLContextImpl context; // volatile: avoid locking for read-only access
private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking
+ private final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
// copy of the cstr args, mainly for recreation
- private GLCapabilitiesImmutable capsReqUser;
- private GLCapabilitiesChooser chooser;
- private GLContext shareWith;
+ private final GLCapabilitiesImmutable capsReqUser;
+ private final GLCapabilitiesChooser chooser;
private int additionalCtxCreationFlags = 0;
- private GraphicsDevice device;
+ private final GraphicsDevice device;
private boolean shallUseOffscreenLayer = false;
- private AWTWindowClosingProtocol awtWindowClosingProtocol =
+ private volatile boolean isShowing;
+ private final HierarchyListener hierarchyListener = new HierarchyListener() {
+ @Override
+ public void hierarchyChanged(final HierarchyEvent e) {
+ isShowing = GLCanvas.this.isShowing();
+ }
+ };
+
+ private final AWTWindowClosingProtocol awtWindowClosingProtocol =
new AWTWindowClosingProtocol(this, new Runnable() {
@Override
public void run() {
- GLCanvas.this.destroy();
+ GLCanvas.this.destroyImpl( true );
}
- });
+ }, null);
/** Creates a new GLCanvas component with a default set of OpenGL
capabilities, using the default OpenGL capabilities selection
mechanism, on the default screen device.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
* @throws GLException if no default profile is available for the default desktop device.
*/
public GLCanvas() throws GLException {
@@ -189,25 +220,14 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
/** Creates a new GLCanvas component with the requested set of
OpenGL capabilities, using the default OpenGL capabilities
selection mechanism, on the default screen device.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
* @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
* @see GLCanvas#GLCanvas(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, javax.media.opengl.GLContext, java.awt.GraphicsDevice)
*/
- public GLCanvas(GLCapabilitiesImmutable capsReqUser) throws GLException {
- this(capsReqUser, null, null, null);
- }
-
- /** Creates a new GLCanvas component with the requested set of
- OpenGL capabilities, using the default OpenGL capabilities
- selection mechanism, on the default screen device.
- * This constructor variant also supports using a shared GLContext.
- *
- * @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
- * @see GLCanvas#GLCanvas(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, javax.media.opengl.GLContext, java.awt.GraphicsDevice)
- */
- public GLCanvas(GLCapabilitiesImmutable capsReqUser, GLContext shareWith)
- throws GLException
- {
- this(capsReqUser, null, shareWith, null);
+ public GLCanvas(final GLCapabilitiesImmutable capsReqUser) throws GLException {
+ this(capsReqUser, null, null);
}
/** Creates a new GLCanvas component. The passed GLCapabilities
@@ -215,22 +235,19 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
default set of capabilities is used. The GLCapabilitiesChooser
specifies the algorithm for selecting one of the available
GLCapabilities for the component; a DefaultGLCapabilitesChooser
- is used if null is passed for this argument. The passed
- GLContext specifies an OpenGL context with which to share
- textures, display lists and other OpenGL state, and may be null
- if sharing is not desired. See the note in the overview
- documentation on <a
- href="../../../overview-summary.html#SHARING">context
- sharing</a>. The passed GraphicsDevice indicates the screen on
+ is used if null is passed for this argument.
+ The passed GraphicsDevice indicates the screen on
which to create the GLCanvas; the GLDrawableFactory uses the
default screen device of the local GraphicsEnvironment if null
is passed for this argument.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
* @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
*/
- public GLCanvas(GLCapabilitiesImmutable capsReqUser,
- GLCapabilitiesChooser chooser,
- GLContext shareWith,
- GraphicsDevice device)
+ public GLCanvas(final GLCapabilitiesImmutable capsReqUser,
+ final GLCapabilitiesChooser chooser,
+ final GraphicsDevice device)
throws GLException
{
/*
@@ -243,36 +260,56 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
super();
if(null==capsReqUser) {
- capsReqUser = new GLCapabilities(GLProfile.getDefault(GLProfile.getDefaultDevice()));
+ this.capsReqUser = new GLCapabilities(GLProfile.getDefault(GLProfile.getDefaultDevice()));
} else {
// don't allow the user to change data
- capsReqUser = (GLCapabilitiesImmutable) capsReqUser.cloneMutable();
+ this.capsReqUser = (GLCapabilitiesImmutable) capsReqUser.cloneMutable();
}
- if(!capsReqUser.isOnscreen()) {
+ if( !this.capsReqUser.isOnscreen() ) {
setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported
}
if(null==device) {
- GraphicsConfiguration gc = super.getGraphicsConfiguration();
+ final GraphicsConfiguration gc = super.getGraphicsConfiguration();
if(null!=gc) {
- device = gc.getDevice();
+ this.device = gc.getDevice();
+ } else {
+ this.device = null;
}
+ } else {
+ this.device = device;
}
// instantiation will be issued in addNotify()
- this.capsReqUser = capsReqUser;
this.chooser = chooser;
- this.shareWith = shareWith;
- this.device = device;
+
+ this.addHierarchyListener(hierarchyListener);
+ this.isShowing = isShowing();
+ }
+
+ @Override
+ public final void setSharedContext(final GLContext sharedContext) throws IllegalStateException {
+ helper.setSharedContext(this.context, sharedContext);
+ }
+
+ @Override
+ public final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
+ helper.setSharedAutoDrawable(this, sharedAutoDrawable);
}
@Override
public final Object getUpstreamWidget() {
return this;
}
-
+
@Override
- public void setShallUseOffscreenLayer(boolean v) {
+ public final RecursiveLock getUpstreamLock() { return lock; }
+
+ @Override
+ public final boolean isThreadGLCapable() { return Threading.isOpenGLThread(); }
+
+ @Override
+ public void setShallUseOffscreenLayer(final boolean v) {
shallUseOffscreenLayer = v;
}
@@ -311,6 +348,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
* all platforms since the peer hasn't been created.
*/
final GraphicsConfiguration gc = super.getGraphicsConfiguration();
+
+ if( Beans.isDesignTime() ) {
+ return gc;
+ }
+
/*
* chosen is only non-null on platforms where the GLDrawableFactory
* returns a non-null GraphicsConfiguration (in the GLCanvas
@@ -320,7 +362,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
* otherwise it is from an ancestor component that this Canvas is being
* added to, and we go into this block.
*/
- GraphicsConfiguration chosen = awtConfig.getAWTGraphicsConfiguration();
+ GraphicsConfiguration chosen = null != awtConfig ? awtConfig.getAWTGraphicsConfiguration() : null;
if (gc != null && chosen != null && !chosen.equals(gc)) {
/*
@@ -346,11 +388,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
* block, both devices should have the same visual list, and the
* same configuration should be selected here.
*/
- AWTGraphicsConfiguration config = chooseGraphicsConfiguration( (GLCapabilitiesImmutable)awtConfig.getChosenCapabilities(),
+ final AWTGraphicsConfiguration config = chooseGraphicsConfiguration( (GLCapabilitiesImmutable)awtConfig.getChosenCapabilities(),
(GLCapabilitiesImmutable)awtConfig.getRequestedCapabilities(),
chooser, gc.getDevice());
- final GraphicsConfiguration compatible = (null!=config)?config.getAWTGraphicsConfiguration():null;
- boolean equalCaps = config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities());
+ final GraphicsConfiguration compatible = config.getAWTGraphicsConfiguration();
+ final boolean equalCaps = config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities());
if(DEBUG) {
System.err.println(getThreadName()+": Info:");
System.err.println("Created Config (n): HAVE GC "+chosen);
@@ -359,7 +401,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
System.err.println("Created Config (n): HAVE CF "+awtConfig);
System.err.println("Created Config (n): Choosen CF "+config);
System.err.println("Created Config (n): EQUALS CAPS "+equalCaps);
- Thread.dumpStack();
+ // Thread.dumpStack();
}
if (compatible != null) {
@@ -369,10 +411,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
*/
chosen = compatible;
- awtConfig = config;
-
if( !equalCaps && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) {
- dispose(true);
+ // complete destruction!
+ destroyImpl( true );
+ // recreation!
+ awtConfig = config;
+ createJAWTDrawableAndContext();
+ validateGLDrawable();
+ } else {
+ awtConfig = config;
}
}
}
@@ -417,9 +464,37 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
_lock.unlock();
}
}
-
+
+ private final void setRealizedImpl(final boolean realized) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLDrawable _drawable = drawable;
+ if( null == _drawable || realized == _drawable.isRealized() ||
+ realized && ( 0 >= _drawable.getSurfaceWidth() || 0 >= _drawable.getSurfaceHeight() ) ) {
+ return;
+ }
+ _drawable.setRealized(realized);
+ if( realized && _drawable.isRealized() ) {
+ sendReshape=true; // ensure a reshape is being send ..
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ private final Runnable realizeOnEDTAction = new Runnable() {
+ @Override
+ public void run() { setRealizedImpl(true); }
+ };
+ private final Runnable unrealizeOnEDTAction = new Runnable() {
+ @Override
+ public void run() { setRealizedImpl(false); }
+ };
+
@Override
- public void setRealized(boolean realized) {
+ public final void setRealized(final boolean realized) {
+ // Make sure drawable realization happens on AWT-EDT and only there. Consider the AWTTree lock!
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), false /* allowOnNonEDT */, true /* wait */, realized ? realizeOnEDTAction : unrealizeOnEDTAction);
}
@Override
@@ -434,32 +509,45 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
+ public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
return awtWindowClosingProtocol.setDefaultCloseOperation(op);
}
@Override
public void display() {
- Threading.invoke(true, displayOnEDTAction, getTreeLock());
- awtWindowClosingProtocol.addClosingListenerOneShot();
- }
-
- private void dispose(boolean regenerate) {
- disposeRegenerate=regenerate;
- Threading.invoke(true, disposeOnEDTAction, getTreeLock());
+ if( !validateGLDrawable() ) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLCanvas display - skipped GL render, drawable not valid yet");
+ }
+ return; // not yet available ..
+ }
+ if( isShowing && !printActive ) {
+ Threading.invoke(true, displayOnEDTAction, getTreeLock());
+ }
}
/**
* {@inheritDoc}
*
* <p>
- * This impl. calls this class's {@link #removeNotify()} AWT override,
- * where the actual implementation resides.
+ * This impl. only destroys all GL related resources.
+ * </p>
+ * <p>
+ * This impl. does not remove the GLCanvas from it's parent AWT container
+ * so this class's {@link #removeNotify()} AWT override won't get called.
+ * To do so, remove this component from it's parent AWT container.
* </p>
*/
@Override
public void destroy() {
- removeNotify();
+ destroyImpl( false );
+ }
+
+ protected void destroyImpl(final boolean destroyJAWTWindowAndAWTDevice) {
+ Threading.invoke(true, destroyOnEDTAction, getTreeLock());
+ if( destroyJAWTWindowAndAWTDevice ) {
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, disposeJAWTWindowAndAWTDeviceOnEDT);
+ }
}
/** Overridden to cause OpenGL rendering to be performed during
@@ -468,28 +556,26 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
properly.
*/
@Override
- public void paint(Graphics g) {
- if (Beans.isDesignTime()) {
+ public void paint(final Graphics g) {
+ if( Beans.isDesignTime() ) {
// Make GLCanvas behave better in NetBeans GUI builder
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
- FontMetrics fm = g.getFontMetrics();
+ final FontMetrics fm = g.getFontMetrics();
String name = getName();
if (name == null) {
name = getClass().getName();
- int idx = name.lastIndexOf('.');
+ final int idx = name.lastIndexOf('.');
if (idx >= 0) {
name = name.substring(idx + 1);
}
}
- Rectangle2D bounds = fm.getStringBounds(name, g);
+ final Rectangle2D bounds = fm.getStringBounds(name, g);
g.setColor(Color.WHITE);
g.drawString(name,
(int) ((getWidth() - bounds.getWidth()) / 2),
(int) ((getHeight() + bounds.getHeight()) / 2));
- return;
- }
- if( ! this.helper.isAnimatorAnimating() ) {
+ } else if( !this.helper.isAnimatorAnimatingOnOtherThread() ) {
display();
}
}
@@ -506,42 +592,47 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
public void addNotify() {
final RecursiveLock _lock = lock;
_lock.lock();
- try {
+ try {
+ final boolean isBeansDesignTime = Beans.isDesignTime();
+
if(DEBUG) {
- System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds());
- Thread.dumpStack();
- }
-
- /**
- * 'super.addNotify()' determines the GraphicsConfiguration,
- * while calling this class's overriden 'getGraphicsConfiguration()' method
- * after which it creates the native peer.
- * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
- * is being used in getGraphicsConfiguration().
- * This code order also allows recreation, ie re-adding the GLCanvas.
- */
- awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device);
- if(null==awtConfig) {
- throw new GLException("Error: NULL AWTGraphicsConfiguration");
+ System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds()+", isBeansDesignTime "+isBeansDesignTime);
+ // Thread.dumpStack();
}
-
- // before native peer is valid: X11
- disableBackgroundErase();
-
- // issues getGraphicsConfiguration() and creates the native peer
- super.addNotify();
-
- // after native peer is valid: Windows
- disableBackgroundErase();
-
- if (!Beans.isDesignTime()) {
- createDrawableAndContext();
+
+ if( isBeansDesignTime ) {
+ super.addNotify();
+ } else {
+ /**
+ * 'super.addNotify()' determines the GraphicsConfiguration,
+ * while calling this class's overriden 'getGraphicsConfiguration()' method
+ * after which it creates the native peer.
+ * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
+ * is being used in getGraphicsConfiguration().
+ * This code order also allows recreation, ie re-adding the GLCanvas.
+ */
+ awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device);
+ if(null==awtConfig) {
+ throw new GLException("Error: NULL AWTGraphicsConfiguration");
+ }
+
+ // before native peer is valid: X11
+ disableBackgroundErase();
+
+ // issues getGraphicsConfiguration() and creates the native peer
+ super.addNotify();
+
+ // after native peer is valid: Windows
+ disableBackgroundErase();
+
+ createJAWTDrawableAndContext();
+
+ // init drawable by paint/display makes the init sequence more equal
+ // for all launch flavors (applet/javaws/..)
+ // validateGLDrawable();
}
-
- // init drawable by paint/display makes the init sequence more equal
- // for all launch flavors (applet/javaws/..)
- // validateGLDrawable();
-
+ awtWindowClosingProtocol.addClosingListener();
+
if(DEBUG) {
System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer());
}
@@ -550,50 +641,102 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
}
- private void createDrawableAndContext() {
- // no lock required, since this resource ain't available yet
- jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
- jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
- jawtWindow.lockSurface();
- try {
- drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
- context = (GLContextImpl) drawable.createContext(shareWith);
- context.setContextCreationFlags(additionalCtxCreationFlags);
- } finally {
- jawtWindow.unlockSurface();
- }
+ @Override
+ public final void setSurfaceScale(final int[] pixelScale) {
+ SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG ? getClass().getSimpleName() : null);
+ if( isRealized() ) {
+ final ScalableSurface ns = jawtWindow;
+ if( null != ns ) {
+ ns.setSurfaceScale(reqPixelScale);
+ final int hadPixelScaleX = hasPixelScale[0];
+ final int hadPixelScaleY = hasPixelScale[1];
+ ns.getCurrentSurfaceScale(hasPixelScale);
+ if( hadPixelScaleX != hasPixelScale[0] || hadPixelScaleY != hasPixelScale[1] ) {
+ reshapeImpl(getWidth(), getHeight());
+ display();
+ }
+ }
+ }
}
- private boolean validateGLDrawable() {
- final GLDrawable _drawable = drawable;
- if ( null != _drawable ) {
- if( _drawable.isRealized() ) {
- return true;
+ @Override
+ public final int[] getRequestedSurfaceScale(final int[] result) {
+ System.arraycopy(reqPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final int[] getCurrentSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public int[] getNativeSurfaceScale(final int[] result) {
+ System.arraycopy(nativePixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ private void createJAWTDrawableAndContext() {
+ if ( !Beans.isDesignTime() ) {
+ jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
+ jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
+ jawtWindow.setSurfaceScale(reqPixelScale);
+ jawtWindow.lockSurface();
+ try {
+ drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
+ createContextImpl(drawable);
+ jawtWindow.getCurrentSurfaceScale(hasPixelScale);
+ jawtWindow.getNativeSurfaceScale(nativePixelScale);
+ } finally {
+ jawtWindow.unlockSurface();
}
- if (!Beans.isDesignTime() &&
- 0 < _drawable.getWidth() * _drawable.getHeight() ) {
- // make sure drawable realization happens on AWT EDT, due to AWTTree lock
- AWTEDTExecutor.singleton.invoke(getTreeLock(), true, setRealizedOnEDTAction);
- if( _drawable.isRealized() ) {
- sendReshape=true; // ensure a reshape is being send ..
- if(DEBUG) {
- System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString());
- Thread.dumpStack();
- }
- return true;
- }
+ }
+ }
+ private boolean createContextImpl(final GLDrawable drawable) {
+ final GLContext[] shareWith = { null };
+ if( !helper.isSharedGLContextPending(shareWith) ) {
+ context = (GLContextImpl) drawable.createContext(shareWith[0]);
+ context.setContextCreationFlags(additionalCtxCreationFlags);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Context created: has shared "+(null != shareWith[0]));
}
+ return true;
+ } else {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Context !created: pending share");
+ }
+ return false;
}
- return false;
}
- private Runnable setRealizedOnEDTAction = new Runnable() {
- @Override
- public void run() {
- final GLDrawable _drawable = drawable;
- if ( null != _drawable && 0 < _drawable.getWidth() * _drawable.getHeight() ) {
- _drawable.setRealized(true);
+
+ private boolean validateGLDrawable() {
+ if( Beans.isDesignTime() || !isDisplayable() ) {
+ return false; // early out!
+ }
+ final GLDrawable _drawable = drawable;
+ if ( null != _drawable ) {
+ boolean res = _drawable.isRealized();
+ if( !res ) {
+ // re-try drawable creation
+ if( 0 >= _drawable.getSurfaceWidth() || 0 >= _drawable.getSurfaceHeight() ) {
+ return false; // early out!
+ }
+ setRealized(true);
+ res = _drawable.isRealized();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Realized Drawable: isRealized "+res+", "+_drawable.toString());
+ // Thread.dumpStack();
+ }
+ }
+ if( res && null == context ) {
+ // re-try context creation
+ res = createContextImpl(_drawable); // pending creation.
}
- } };
+ return res;
+ }
+ return false;
+ }
/** <p>Overridden to track when this component is removed from a
container. Subclasses which override this method must call
@@ -608,16 +751,16 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
public void removeNotify() {
if(DEBUG) {
System.err.println(getThreadName()+": Info: removeNotify - start");
- Thread.dumpStack();
+ // Thread.dumpStack();
}
awtWindowClosingProtocol.removeClosingListener();
- if (Beans.isDesignTime()) {
+ if( Beans.isDesignTime() ) {
super.removeNotify();
} else {
try {
- dispose(false);
+ destroyImpl( true );
} finally {
super.removeNotify();
}
@@ -636,30 +779,42 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
<DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
@SuppressWarnings("deprecation")
@Override
- public void reshape(int x, int y, int width, int height) {
+ public void reshape(final int x, final int y, final int width, final int height) {
synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape
super.reshape(x, y, width, height);
-
- GLDrawableImpl _drawable = drawable;
- if( null != _drawable ) {
- if(DEBUG) {
- System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
- }
- if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
- final RecursiveLock _lock = lock;
- _lock.lock();
- try {
- final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, width, height);
- if(_drawable != _drawableNew) {
- // write back
- drawable = _drawableNew;
- }
- } finally {
- _lock.unlock();
+ reshapeImpl(width, height);
+ }
+ }
+
+ private void reshapeImpl(final int width, final int height) {
+ final int scaledWidth = width * hasPixelScale[0];
+ final int scaledHeight = height * hasPixelScale[1];
+
+ if(DEBUG) {
+ final NativeSurface ns = getNativeSurface();
+ final long nsH = null != ns ? ns.getSurfaceHandle() : 0;
+ System.err.println(getThreadName()+": GLCanvas.reshape.0 "+this.getName()+" resize"+(printActive?"WithinPrint":"")+
+ " [ this "+getWidth()+"x"+getHeight()+", pixelScale "+getPixelScaleStr()+
+ "] -> "+(printActive?"[skipped] ":"") + width+"x"+height+" * "+getPixelScaleStr()+" -> "+scaledWidth+"x"+scaledHeight+
+ " - surfaceHandle 0x"+Long.toHexString(nsH));
+ // Thread.dumpStack();
+ }
+ if( validateGLDrawable() && !printActive ) {
+ final GLDrawableImpl _drawable = drawable;
+ if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, scaledWidth, scaledHeight);
+ if(_drawable != _drawableNew) {
+ // write back
+ drawable = _drawableNew;
}
+ } finally {
+ _lock.unlock();
}
- sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
}
+ sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
}
}
@@ -668,32 +823,239 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
* canvas from interfering with the OpenGL rendering.
*/
@Override
- public void update(Graphics g) {
+ public void update(final Graphics g) {
paint(g);
}
+ private volatile boolean printActive = false;
+ private GLAnimatorControl printAnimator = null;
+ private GLAutoDrawable printGLAD = null;
+ private AWTTilePainter printAWTTiles = null;
+
@Override
- public void addGLEventListener(GLEventListener listener) {
+ public void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight) {
+ printActive = true;
+ final int componentCount = isOpaque() ? 3 : 4;
+ final TileRenderer printRenderer = new TileRenderer();
+ printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
+ }
+ private final Runnable setupPrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( !validateGLDrawable() ) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, drawable not valid yet");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ if( !isVisible() ) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, canvas not visible");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ sendReshape = false; // clear reshape flag
+ printAnimator = helper.getAnimator();
+ if( null != printAnimator ) {
+ printAnimator.remove(GLCanvas.this);
+ }
+ printGLAD = GLCanvas.this; // _not_ default, shall be replaced by offscreen GLAD
+ final GLCapabilitiesImmutable gladCaps = getChosenGLCapabilities();
+ final int printNumSamples = printAWTTiles.getNumSamples(gladCaps);
+ GLDrawable printDrawable = printGLAD.getDelegatedDrawable();
+ final boolean reqNewGLADSamples = printNumSamples != gladCaps.getNumSamples();
+ final boolean reqNewGLADSize = printAWTTiles.customTileWidth != -1 && printAWTTiles.customTileWidth != printDrawable.getSurfaceWidth() ||
+ printAWTTiles.customTileHeight != -1 && printAWTTiles.customTileHeight != printDrawable.getSurfaceHeight();
+ final boolean reqNewGLADOnscrn = gladCaps.isOnscreen();
+
+ final GLCapabilities newGLADCaps = (GLCapabilities)gladCaps.cloneMutable();
+ newGLADCaps.setDoubleBuffered(false);
+ newGLADCaps.setOnscreen(false);
+ if( printNumSamples != newGLADCaps.getNumSamples() ) {
+ newGLADCaps.setSampleBuffers(0 < printNumSamples);
+ newGLADCaps.setNumSamples(printNumSamples);
+ }
+ final boolean reqNewGLADSafe = GLDrawableUtil.isSwapGLContextSafe(getRequestedGLCapabilities(), gladCaps, newGLADCaps);
+
+ final boolean reqNewGLAD = ( reqNewGLADOnscrn || reqNewGLADSamples || reqNewGLADSize ) && reqNewGLADSafe;
+
+ if( DEBUG ) {
+ System.err.println("AWT print.setup: reqNewGLAD "+reqNewGLAD+"[ onscreen "+reqNewGLADOnscrn+", samples "+reqNewGLADSamples+", size "+reqNewGLADSize+", safe "+reqNewGLADSafe+"], "+
+ ", drawableSize "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+
+ ", customTileSize "+printAWTTiles.customTileWidth+"x"+printAWTTiles.customTileHeight+
+ ", scaleMat "+printAWTTiles.scaleMatX+" x "+printAWTTiles.scaleMatY+
+ ", numSamples "+printAWTTiles.customNumSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
+ }
+ if( reqNewGLAD ) {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(newGLADCaps.getGLProfile());
+ GLOffscreenAutoDrawable offGLAD = null;
+ try {
+ offGLAD = factory.createOffscreenAutoDrawable(null, newGLADCaps, null,
+ printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
+ printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
+ } catch (final GLException gle) {
+ if( DEBUG ) {
+ System.err.println("Caught: "+gle.getMessage());
+ gle.printStackTrace();
+ }
+ }
+ if( null != offGLAD ) {
+ printGLAD = offGLAD;
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(GLCanvas.this, printGLAD);
+ printDrawable = printGLAD.getDelegatedDrawable();
+ }
+ }
+ printAWTTiles.setGLOrientation(printGLAD.isGLOriented(), printGLAD.isGLOriented());
+ printAWTTiles.renderer.setTileSize(printDrawable.getSurfaceWidth(), printDrawable.getSurfaceHeight(), 0);
+ printAWTTiles.renderer.attachAutoDrawable(printGLAD);
+ if( DEBUG ) {
+ System.err.println("AWT print.setup "+printAWTTiles);
+ System.err.println("AWT print.setup AA "+printNumSamples+", "+newGLADCaps);
+ System.err.println("AWT print.setup printGLAD: "+printGLAD.getSurfaceWidth()+"x"+printGLAD.getSurfaceHeight()+", "+printGLAD);
+ System.err.println("AWT print.setup printDraw: "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+", "+printDrawable);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ @Override
+ public void releasePrint() {
+ if( !printActive || null == printGLAD ) {
+ throw new IllegalStateException("setupPrint() not called");
+ }
+ sendReshape = false; // clear reshape flag
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, releasePrintOnEDT);
+ }
+ private final Runnable releasePrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( DEBUG ) {
+ System.err.println("AWT print.release "+printAWTTiles);
+ }
+ printAWTTiles.dispose();
+ printAWTTiles= null;
+ if( printGLAD != GLCanvas.this ) {
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, GLCanvas.this);
+ printGLAD.destroy();
+ }
+ printGLAD = null;
+ if( null != printAnimator ) {
+ printAnimator.add(GLCanvas.this);
+ printAnimator = null;
+ }
+ sendReshape = true; // trigger reshape, i.e. gl-viewport and -listener - this component might got resized!
+ printActive = false;
+ display();
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ @Override
+ public void print(final Graphics graphics) {
+ if( !printActive || null == printGLAD ) {
+ throw new IllegalStateException("setupPrint() not called");
+ }
+ if(DEBUG && !EventQueue.isDispatchThread()) {
+ System.err.println(getThreadName()+": Warning: GLCanvas print - not called from AWT-EDT");
+ // we cannot dispatch print on AWT-EDT due to printing internal locking ..
+ }
+ sendReshape = false; // clear reshape flag
+
+ final Graphics2D g2d = (Graphics2D)graphics;
+ try {
+ printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
+ final TileRenderer tileRenderer = printAWTTiles.renderer;
+ if( DEBUG ) {
+ System.err.println("AWT print.0: "+tileRenderer);
+ }
+ if( !tileRenderer.eot() ) {
+ try {
+ do {
+ if( printGLAD != GLCanvas.this ) {
+ tileRenderer.display();
+ } else {
+ Threading.invoke(true, displayOnEDTAction, getTreeLock());
+ }
+ } while ( !tileRenderer.eot() );
+ if( DEBUG ) {
+ System.err.println("AWT print.1: "+printAWTTiles);
+ }
+ } finally {
+ tileRenderer.reset();
+ printAWTTiles.resetGraphics2D();
+ }
+ }
+ } catch (final NoninvertibleTransformException nte) {
+ System.err.println("Caught: Inversion failed of: "+g2d.getTransform());
+ nte.printStackTrace();
+ }
+ if( DEBUG ) {
+ System.err.println("AWT print.X: "+printAWTTiles);
+ }
+ }
+
+ @Override
+ public void addGLEventListener(final GLEventListener listener) {
helper.addGLEventListener(listener);
}
@Override
- public void addGLEventListener(int index, GLEventListener listener) throws IndexOutOfBoundsException {
+ public void addGLEventListener(final int index, final GLEventListener listener) throws IndexOutOfBoundsException {
helper.addGLEventListener(index, listener);
}
@Override
- public void removeGLEventListener(GLEventListener listener) {
- helper.removeGLEventListener(listener);
+ public int getGLEventListenerCount() {
+ return helper.getGLEventListenerCount();
}
@Override
- public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
- return helper.removeGLEventListener(index);
+ public GLEventListener getGLEventListener(final int index) throws IndexOutOfBoundsException {
+ return helper.getGLEventListener(index);
}
-
+
@Override
- public void setAnimator(GLAnimatorControl animatorControl) {
+ public boolean areAllGLEventListenerInitialized() {
+ return helper.areAllGLEventListenerInitialized();
+ }
+
+ @Override
+ public boolean getGLEventListenerInitState(final GLEventListener listener) {
+ return helper.getGLEventListenerInitState(listener);
+ }
+
+ @Override
+ public void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized) {
+ helper.setGLEventListenerInitState(listener, initialized);
+ }
+
+ @Override
+ public GLEventListener disposeGLEventListener(final GLEventListener listener, final boolean remove) {
+ final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
+ Threading.invoke(true, r, getTreeLock());
+ return r.listener;
+ }
+
+ @Override
+ public GLEventListener removeGLEventListener(final GLEventListener listener) {
+ return helper.removeGLEventListener(listener);
+ }
+
+ @Override
+ public void setAnimator(final GLAnimatorControl animatorControl) {
helper.setAnimator(animatorControl);
}
@@ -703,21 +1065,38 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public boolean invoke(boolean wait, GLRunnable glRunnable) {
+ public final Thread setExclusiveContextThread(final Thread t) throws GLException {
+ return helper.setExclusiveContextThread(t, context);
+ }
+
+ @Override
+ public final Thread getExclusiveContextThread() {
+ return helper.getExclusiveContextThread();
+ }
+
+ @Override
+ public boolean invoke(final boolean wait, final GLRunnable glRunnable) throws IllegalStateException {
return helper.invoke(this, wait, glRunnable);
}
@Override
- public GLContext setContext(GLContext newCtx) {
+ public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) throws IllegalStateException {
+ return helper.invoke(this, wait, glRunnables);
+ }
+
+ @Override
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
+ }
+
+ @Override
+ public GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx) {
final RecursiveLock _lock = lock;
_lock.lock();
try {
final GLContext oldCtx = context;
- final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
- }
return oldCtx;
} finally {
_lock.unlock();
@@ -728,7 +1107,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
public final GLDrawable getDelegatedDrawable() {
return drawable;
}
-
+
@Override
public GLContext getContext() {
return context;
@@ -736,7 +1115,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public GL getGL() {
- if (Beans.isDesignTime()) {
+ if( Beans.isDesignTime() ) {
return null;
}
final GLContext _context = context;
@@ -744,7 +1123,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public GL setGL(GL gl) {
+ public GL setGL(final GL gl) {
final GLContext _context = context;
if (_context != null) {
_context.setGL(gl);
@@ -755,7 +1134,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
- public void setAutoSwapBufferMode(boolean onOrOff) {
+ public void setAutoSwapBufferMode(final boolean onOrOff) {
helper.setAutoSwapBufferMode(onOrOff);
}
@@ -770,7 +1149,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void setContextCreationFlags(int flags) {
+ public void setContextCreationFlags(final int flags) {
additionalCtxCreationFlags = flags;
final GLContext _context = context;
if(null != _context) {
@@ -790,22 +1169,39 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public GLCapabilitiesImmutable getChosenGLCapabilities() {
- if (awtConfig == null) {
+ if( Beans.isDesignTime() ) {
+ return capsReqUser;
+ } else if( null == awtConfig ) {
throw new GLException("No AWTGraphicsConfiguration: "+this);
}
-
return (GLCapabilitiesImmutable)awtConfig.getChosenCapabilities();
}
+ @Override
public GLCapabilitiesImmutable getRequestedGLCapabilities() {
- if (awtConfig == null) {
+ if( null == awtConfig ) {
return capsReqUser;
}
-
return (GLCapabilitiesImmutable)awtConfig.getRequestedCapabilities();
}
@Override
+ public int getSurfaceWidth() {
+ return getWidth() * hasPixelScale[0];
+ }
+
+ @Override
+ public int getSurfaceHeight() {
+ return getHeight() * hasPixelScale[1];
+ }
+
+ @Override
+ public boolean isGLOriented() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.isGLOriented() : true;
+ }
+
+ @Override
public NativeSurface getNativeSurface() {
final GLDrawable _drawable = drawable;
return (null != _drawable) ? _drawable.getNativeSurface() : null;
@@ -826,92 +1222,93 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
@Override
public String toString() {
final GLDrawable _drawable = drawable;
- final int dw = (null!=_drawable) ? _drawable.getWidth() : -1;
- final int dh = (null!=_drawable) ? _drawable.getHeight() : -1;
+ final int dw = (null!=_drawable) ? _drawable.getSurfaceWidth() : -1;
+ final int dh = (null!=_drawable) ? _drawable.getSurfaceHeight() : -1;
return "AWT-GLCanvas[Realized "+isRealized()+
",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+
",\n\tFactory "+getFactory()+
",\n\thandle 0x"+Long.toHexString(getHandle())+
- ",\n\tDrawable size "+dw+"x"+dh+
- ",\n\tAWT pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
- ",\n\tvisible "+isVisible()+
- ",\n\t"+awtConfig+"]";
+ ",\n\tDrawable size "+dw+"x"+dh+" surface["+getSurfaceWidth()+"x"+getSurfaceHeight()+"]"+
+ ",\n\tAWT[pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
+ ",\n\tvisible "+isVisible()+", displayable "+isDisplayable()+", showing "+isShowing+
+ ",\n\t"+awtConfig+"]]";
}
//----------------------------------------------------------------------
// Internals only below this point
//
- private boolean disposeRegenerate;
- private final Runnable postDisposeOnEDTAction = new Runnable() {
- @Override
- public void run() {
- context=null;
- if(null!=drawable) {
- drawable.setRealized(false);
- drawable=null;
- if(null!=jawtWindow) {
- jawtWindow.destroy();
- jawtWindow=null;
- }
- }
-
- if(disposeRegenerate) {
- // Similar process as in addNotify()!
-
- // Recreate GLDrawable/GLContext to reflect it's new graphics configuration
- createDrawableAndContext();
-
- if(DEBUG) {
- System.err.println(getThreadName()+": GLCanvas.dispose(true): new drawable: "+drawable);
- }
- validateGLDrawable(); // immediate attempt to recreate the drawable
- }
- }
- };
+ private final String getPixelScaleStr() { return hasPixelScale[0]+"x"+hasPixelScale[1]; }
- private final Runnable disposeOnEDTAction = new Runnable() {
+ private final Runnable destroyOnEDTAction = new Runnable() {
@Override
public void run() {
final RecursiveLock _lock = lock;
_lock.lock();
- try {
+ try {
final GLAnimatorControl animator = getAnimator();
if(DEBUG) {
- System.err.println(getThreadName()+": Info: dispose("+disposeRegenerate+") - START, hasContext " +
+ System.err.println(getThreadName()+": Info: destroyOnEDTAction() - START, hasContext " +
(null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator);
- Thread.dumpStack();
+ // Thread.dumpStack();
}
-
- if(null!=drawable && null!=context) {
- boolean animatorPaused = false;
- if(null!=animator) {
- // can't remove us from animator for recreational addNotify()
- animatorPaused = animator.pause();
- }
-
- if(context.isCreated()) {
- helper.disposeGL(GLCanvas.this, drawable, context, postDisposeOnEDTAction);
- }
-
- if(animatorPaused) {
- animator.resume();
+
+ final boolean animatorPaused;
+ if(null!=animator) {
+ // can't remove us from animator for recreational addNotify()
+ animatorPaused = animator.pause();
+ } else {
+ animatorPaused = false;
+ }
+
+ GLException exceptionOnDisposeGL = null;
+
+ // OLS will be detached by disposeGL's context destruction below
+ if( null != context ) {
+ if( context.isCreated() ) {
+ try {
+ helper.disposeGL(GLCanvas.this, context, true);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": destroyOnEDTAction() - post ctx: "+context);
+ }
+ } catch (final GLException gle) {
+ exceptionOnDisposeGL = gle;
+ }
}
+ context = null;
}
-
- if(!disposeRegenerate) {
- if(null != awtConfig) {
- AWTEDTExecutor.singleton.invoke(getTreeLock(), true, disposeAbstractGraphicsDeviceActionOnEDT);
+
+ Throwable exceptionOnUnrealize = null;
+ if( null != drawable ) {
+ try {
+ drawable.setRealized(false);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": destroyOnEDTAction() - post drawable: "+drawable);
+ }
+ } catch( final Throwable re ) {
+ exceptionOnUnrealize = re;
}
- awtConfig=null;
+ drawable = null;
}
-
+
+ if(animatorPaused) {
+ animator.resume();
+ }
+
+ // throw exception in order of occurrence ..
+ if( null != exceptionOnDisposeGL ) {
+ throw exceptionOnDisposeGL;
+ }
+ if( null != exceptionOnUnrealize ) {
+ throw GLException.newGLException(exceptionOnUnrealize);
+ }
+
if(DEBUG) {
- System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - END, "+animator);
+ System.err.println(getThreadName()+": dispose() - END, animator "+animator);
}
-
+
} finally {
_lock.unlock();
}
@@ -919,35 +1316,54 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
};
/**
- * Disposes the AbstractGraphicsDevice within EDT,
+ * Disposes the JAWTWindow and AbstractGraphicsDevice within EDT,
* since resources created (X11: Display), must be destroyed in the same thread, where they have been created.
+ * <p>
+ * The drawable and context handle are null'ed as well, assuming {@link #destroy()} has been called already.
+ * </p>
*
* @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice)
*/
- private final Runnable disposeAbstractGraphicsDeviceActionOnEDT = new Runnable() {
+ private final Runnable disposeJAWTWindowAndAWTDeviceOnEDT = new Runnable() {
@Override
public void run() {
- if(null != awtConfig) {
- final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration();
- final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
- final String adeviceMsg;
- if(DEBUG) {
- adeviceMsg = adevice.toString();
- } else {
- adeviceMsg = null;
- }
- boolean closed = adevice.close();
- if(DEBUG) {
- System.err.println(getThreadName()+": GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed);
- }
- }
+ context=null;
+ drawable=null;
+
+ if( null != jawtWindow ) {
+ jawtWindow.destroy();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post JAWTWindow: "+jawtWindow);
+ }
+ jawtWindow=null;
+ }
+ hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+
+ if(null != awtConfig) {
+ final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration();
+ final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
+ final String adeviceMsg;
+ if(DEBUG) {
+ adeviceMsg = adevice.toString();
+ } else {
+ adeviceMsg = null;
+ }
+ final boolean closed = adevice.close();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post GraphicsDevice: "+adeviceMsg+", result: "+closed);
+ }
+ }
+ awtConfig=null;
}
};
-
+
private final Runnable initAction = new Runnable() {
@Override
public void run() {
- helper.init(GLCanvas.this);
+ helper.init(GLCanvas.this, !sendReshape);
}
};
@@ -956,11 +1372,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
public void run() {
if (sendReshape) {
if(DEBUG) {
- System.err.println(getThreadName()+": Reshape: "+getWidth()+"x"+getHeight());
+ System.err.println(getThreadName()+": Reshape: "+getSurfaceWidth()+"x"+getSurfaceHeight());
}
// Note: we ignore the given x and y within the parent component
// since we are drawing directly into this heavyweight component.
- helper.reshape(GLCanvas.this, 0, 0, getWidth(), getHeight());
+ helper.reshape(GLCanvas.this, 0, 0, getSurfaceWidth(), getSurfaceHeight());
sendReshape = false;
}
@@ -968,26 +1384,29 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
};
- private final Runnable swapBuffersAction = new Runnable() {
+ private final Runnable displayOnEDTAction = new Runnable() {
@Override
public void run() {
- drawable.swapBuffers();
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( null != drawable && drawable.isRealized() ) {
+ helper.invokeGL(drawable, context, displayAction, initAction);
+ }
+ } finally {
+ _lock.unlock();
+ }
}
};
- // Workaround for ATI driver bugs related to multithreading issues
- // like simultaneous rendering via Animators to canvases that are
- // being resized on the AWT event dispatch thread
- private final Runnable displayOnEDTAction = new Runnable() {
+ private final Runnable swapBuffersOnEDTAction = new Runnable() {
@Override
public void run() {
final RecursiveLock _lock = lock;
_lock.lock();
- try {
- if( validateGLDrawable() ) {
- helper.invokeGL(drawable, context, displayAction, initAction);
- } else if(DEBUG) {
- System.err.println(getThreadName()+": Info: GLCanvas display - skipped GL render, drawable not valid yet");
+ try {
+ if( null != drawable && drawable.isRealized() ) {
+ drawable.swapBuffers();
}
} finally {
_lock.unlock();
@@ -995,13 +1414,20 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
};
- private final Runnable swapBuffersOnEDTAction = new Runnable() {
+ private class DisposeGLEventListenerAction implements Runnable {
+ GLEventListener listener;
+ private final boolean remove;
+ private DisposeGLEventListenerAction(final GLEventListener listener, final boolean remove) {
+ this.listener = listener;
+ this.remove = remove;
+ }
+
@Override
public void run() {
final RecursiveLock _lock = lock;
_lock.lock();
- try {
- helper.invokeGL(drawable, context, swapBuffersAction, initAction);
+ try {
+ listener = helper.disposeGLEventListener(GLCanvas.this, drawable, context, listener, remove);
} finally {
_lock.unlock();
}
@@ -1029,16 +1455,16 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
clazz.getDeclaredMethod("disableBackgroundErase",
new Class[] { Canvas.class });
disableBackgroundEraseMethod.setAccessible(true);
- } catch (Exception e) {
+ } catch (final Exception e) {
clazz = clazz.getSuperclass();
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
}
return null;
}
});
- } catch (Exception e) {
+ } catch (final Exception e) {
}
disableBackgroundEraseInitialized = true;
if(DEBUG) {
@@ -1050,7 +1476,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
Throwable t=null;
try {
disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this });
- } catch (Exception e) {
+ } catch (final Exception e) {
t = e;
}
if(DEBUG) {
@@ -1069,14 +1495,14 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
* @param device
* @return the chosen AWTGraphicsConfiguration
*
- * @see #disposeAbstractGraphicsDeviceActionOnEDT
+ * @see #disposeJAWTWindowAndAWTDeviceOnEDT
*/
private AWTGraphicsConfiguration chooseGraphicsConfiguration(final GLCapabilitiesImmutable capsChosen,
final GLCapabilitiesImmutable capsRequested,
final GLCapabilitiesChooser chooser,
final GraphicsDevice device) {
// Make GLCanvas behave better in NetBeans GUI builder
- if (Beans.isDesignTime()) {
+ if( Beans.isDesignTime() ) {
return null;
}
@@ -1096,7 +1522,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
- AWTGraphicsConfiguration c = (AWTGraphicsConfiguration)
+ final AWTGraphicsConfiguration c = (AWTGraphicsConfiguration)
GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
capsRequested,
chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
@@ -1104,28 +1530,26 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
});
config = ( bucket.size() > 0 ) ? bucket.get(0) : null ;
- } catch (InvocationTargetException e) {
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
throw new GLException(e);
}
}
- if (config == null) {
+ if ( null == config ) {
throw new GLException("Error: Couldn't fetch AWTGraphicsConfiguration");
}
return config;
}
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
/**
* A most simple JOGL AWT test entry
*/
- public static void main(String args[]) {
+ public static void main(final String args[]) {
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
// System.err.println(NativeWindowVersion.getInstance());
@@ -1142,16 +1566,16 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
glCanvas.addGLEventListener(new GLEventListener() {
@Override
- public void init(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
System.err.println(JoglVersion.getGLInfo(gl, null));
}
@Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
@Override
- public void display(GLAutoDrawable drawable) { }
+ public void display(final GLAutoDrawable drawable) { }
@Override
- public void dispose(GLAutoDrawable drawable) { }
+ public void dispose(final GLAutoDrawable drawable) { }
});
try {
@@ -1160,7 +1584,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
public void run() {
frame.setVisible(true);
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
}
glCanvas.display();
@@ -1170,7 +1594,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
public void run() {
frame.dispose();
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
}
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 6d4a5861f..8d23d79ff 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -44,23 +44,28 @@ import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
+import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.beans.Beans;
-import java.nio.ByteBuffer;
import java.nio.IntBuffer;
+import java.util.List;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ScalableSurface;
+import javax.media.nativewindow.SurfaceUpdatedListener;
import javax.media.nativewindow.WindowClosingProtocol;
-import javax.media.opengl.DefaultGLCapabilitiesChooser;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
@@ -72,131 +77,243 @@ import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
-import javax.media.opengl.GLPbuffer;
+import javax.media.opengl.GLFBODrawable;
+import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
+import javax.media.opengl.GLSharedContextSetter;
import javax.media.opengl.Threading;
import javax.swing.JPanel;
+import jogamp.nativewindow.SurfaceScaleUtils;
+import jogamp.nativewindow.WrappedSurface;
+import jogamp.nativewindow.jawt.JAWTUtil;
import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableHelper;
import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.awt.AWTTilePainter;
import jogamp.opengl.awt.Java2D;
-import jogamp.opengl.awt.Java2DGLContext;
+import jogamp.opengl.util.glsl.GLSLTextureRaster;
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.opengl.FBObject;
-import com.jogamp.opengl.util.GLBuffers;
-
-// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
-// context whenever the displayChanged() function is called on their
-// GLEventListeners
+import com.jogamp.opengl.GLRendererQuirks;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.GLPixelBuffer.SingletonGLPixelBufferProvider;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.GLPixelStorageModes;
+import com.jogamp.opengl.util.TileRenderer;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider;
+import com.jogamp.opengl.util.texture.TextureState;
/** A lightweight Swing component which provides OpenGL rendering
support. Provided for compatibility with Swing user interfaces
when adding a heavyweight doesn't work either because of
Z-ordering or LayoutManager problems.
- <P>
+ <p>
The GLJPanel can be made transparent by creating it with a
GLCapabilities object with alpha bits specified and calling {@link
#setOpaque}(false). Pixels with resulting OpenGL alpha values less
- than 1.0 will be overlaid on any underlying Swing rendering. </P>
- <P>
- Notes specific to the Reference Implementation: This component
- attempts to use hardware-accelerated rendering via pbuffers and
- falls back on to software rendering if problems occur.
- Note that because this component attempts to use pbuffers for
- rendering, and because pbuffers can not be resized, somewhat
- surprising behavior may occur during resize operations; the {@link
- GLEventListener#init} method may be called multiple times as the
- pbuffer is resized to be able to cover the size of the GLJPanel.
- This behavior is correct, as the textures and display lists for
- the GLJPanel will have been lost during the resize operation. The
- application should attempt to make its GLEventListener.init()
- methods as side-effect-free as possible. </P>
+ than 1.0 will be overlaid on any underlying Swing rendering.
+ </p>
+ <p>
+ This component attempts to use hardware-accelerated rendering via FBO or pbuffers and
+ falls back on to software rendering if none of the former are available
+ using {@link GLDrawableFactory#createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int) GLDrawableFactory.createOffscreenDrawable(..)}.<br/>
+ </p>
+ <p>
+ <a name="verticalFlip">A vertical-flip is required</a>, if the drawable {@link #isGLOriented()} and {@link #setSkipGLOrientationVerticalFlip(boolean) vertical flip is not skipped}.<br>
+ In this case this component performs the required vertical flip to bring the content from OpenGL's orientation into AWT's orientation.<br>
+ In case <a href="#fboGLSLVerticalFlip">GLSL based vertical-flip</a> is not available,
+ the CPU intensive {@link System#arraycopy(Object, int, Object, int, int) System.arraycopy(..)} is used line by line.
+ See details about <a href="#fboGLSLVerticalFlip">FBO and GLSL vertical flipping</a>.
+ </p>
+ <p>
+ For performance reasons, as well as for <a href="#bug842">GL state sideeffects</a>,
+ <b>{@link #setSkipGLOrientationVerticalFlip(boolean) skipping vertical flip} is highly recommended</b>!
+ </p>
+ <p>
+ The OpenGL path is concluded by copying the rendered pixels an {@link BufferedImage} via {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
+ for later Java2D composition.
+ </p>
+ <p>
+ Finally the Java2D compositioning takes place via via {@link Graphics#drawImage(java.awt.Image, int, int, int, int, java.awt.image.ImageObserver) Graphics.drawImage(...)}
+ on the prepared {@link BufferedImage} as described above.
+ </p>
<P>
- * Please read <A HREF="GLCanvas.html#java2dgl">Java2D OpenGL Remarks</A>.
+ * Please read <a href="GLCanvas.html#java2dgl">Java2D OpenGL Remarks</a>.
* </P>
+ *
+ <a name="fboGLSLVerticalFlip"><h5>FBO / GLSL Vertical Flip</h5></a>
+ If <a href="#verticalFlip">vertical flip is required</a>,
+ FBO is used, GLSL is available and {@link #setSkipGLOrientationVerticalFlip(boolean) vertical flip is not skipped}, a fragment shader is utilized
+ to flip the FBO texture vertically. This hardware-accelerated step can be disabled via system property <code>jogl.gljpanel.noglsl</code>.
+ <p>
+ The FBO / GLSL code path uses one texture-unit and binds the FBO texture to it's active texture-target,
+ see {@link #setTextureUnit(int)} and {@link #getTextureUnit()}.
+ </p>
+ <p>
+ The active and dedicated texture-unit's {@link GL#GL_TEXTURE_2D} state is preserved via {@link TextureState}.
+ See also {@link Texture#textureCallOrder Order of Texture Commands}.
+ </p>
+ <p>
+ The current gl-viewport is preserved.
+ </p>
+ <p>
+ <a name="bug842"><i>Warning (Bug 842)</i></a>: Certain GL states other than viewport and texture (see above)
+ influencing rendering, will also influence the GLSL vertical flip, e.g. {@link GL#glFrontFace(int) glFrontFace}({@link GL#GL_CCW}).
+ It is recommended to reset those states to default when leaving the {@link GLEventListener#display(GLAutoDrawable)} method!
+ We may change this behavior in the future, i.e. preserve all influencing states.
+ </p>
+ <p>
+ <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a>
+ To share a {@link GLContext} see the following note in the documentation overview:
+ <a href="../../../../overview-summary.html#SHARING">context sharing</a>
+ as well as {@link GLSharedContextSetter}.
+ </p>
*/
-@SuppressWarnings({ "serial", "deprecation" })
-public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol {
- private static final boolean DEBUG = Debug.debug("GLJPanel");
+@SuppressWarnings("serial")
+public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol, AWTPrintLifecycle, GLSharedContextSetter, ScalableSurface {
+ private static final boolean DEBUG;
+ private static final boolean DEBUG_FRAMES;
+ private static final boolean DEBUG_VIEWPORT;
+ private static final boolean USE_GLSL_TEXTURE_RASTERIZER;
+ private static final boolean SKIP_VERTICAL_FLIP_DEFAULT;
+
+ /** Indicates whether the Java 2D OpenGL pipeline is requested by user. */
+ private static final boolean java2dOGLEnabledByProp;
+
+ /** Indicates whether the Java 2D OpenGL pipeline is enabled, resource-compatible and requested by user. */
+ private static final boolean useJava2DGLPipeline;
+
+ /** Indicates whether the Java 2D OpenGL pipeline's usage is error free. */
+ private static boolean java2DGLPipelineOK;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = Debug.debug("GLJPanel");
+ DEBUG_FRAMES = PropertyAccess.isPropertyDefined("jogl.debug.GLJPanel.Frames", true);
+ DEBUG_VIEWPORT = PropertyAccess.isPropertyDefined("jogl.debug.GLJPanel.Viewport", true);
+ USE_GLSL_TEXTURE_RASTERIZER = !PropertyAccess.isPropertyDefined("jogl.gljpanel.noglsl", true);
+ SKIP_VERTICAL_FLIP_DEFAULT = PropertyAccess.isPropertyDefined("jogl.gljpanel.noverticalflip", true);
+ boolean enabled = PropertyAccess.getBooleanProperty("sun.java2d.opengl", false);
+ java2dOGLEnabledByProp = enabled && !PropertyAccess.isPropertyDefined("jogl.gljpanel.noogl", true);
+
+ enabled = false;
+ if( java2dOGLEnabledByProp ) {
+ // Force eager initialization of part of the Java2D class since
+ // otherwise it's likely it will try to be initialized while on
+ // the Queue Flusher Thread, which is not allowed
+ if (Java2D.isOGLPipelineResourceCompatible() && Java2D.isFBOEnabled()) {
+ if( null != Java2D.getShareContext(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()) ) {
+ enabled = true;
+ }
+ }
+ }
+ useJava2DGLPipeline = enabled;
+ java2DGLPipelineOK = enabled;
+ if( DEBUG ) {
+ System.err.println("GLJPanel: DEBUG_VIEWPORT "+DEBUG_VIEWPORT);
+ System.err.println("GLJPanel: USE_GLSL_TEXTURE_RASTERIZER "+USE_GLSL_TEXTURE_RASTERIZER);
+ System.err.println("GLJPanel: SKIP_VERTICAL_FLIP_DEFAULT "+SKIP_VERTICAL_FLIP_DEFAULT);
+ System.err.println("GLJPanel: java2dOGLEnabledByProp "+java2dOGLEnabledByProp);
+ System.err.println("GLJPanel: useJava2DGLPipeline "+useJava2DGLPipeline);
+ System.err.println("GLJPanel: java2DGLPipelineOK "+java2DGLPipelineOK);
+ }
+ }
+
+ private static SingleAWTGLPixelBufferProvider singleAWTGLPixelBufferProvider = null;
+ private static synchronized SingleAWTGLPixelBufferProvider getSingleAWTGLPixelBufferProvider() {
+ if( null == singleAWTGLPixelBufferProvider ) {
+ singleAWTGLPixelBufferProvider = new SingleAWTGLPixelBufferProvider( true /* allowRowStride */ );
+ }
+ return singleAWTGLPixelBufferProvider;
+ }
+
+ private final RecursiveLock lock = LockFactory.createRecursiveLock();
+
+ private final GLDrawableHelper helper;
+ private boolean autoSwapBufferMode;
- private GLDrawableHelper helper = new GLDrawableHelper();
private volatile boolean isInitialized;
+ //
// Data used for either pbuffers or pixmap-based offscreen surfaces
- private GLCapabilitiesImmutable offscreenCaps;
- private GLProfile glProfile;
- private GLDrawableFactoryImpl factory;
- private GLCapabilitiesChooser chooser;
- private GLContext shareWith;
+ //
+ private AWTGLPixelBufferProvider customPixelBufferProvider = null;
+ /** Requested single buffered offscreen caps */
+ private volatile GLCapabilitiesImmutable reqOffscreenCaps;
+ private volatile GLDrawableFactoryImpl factory;
+ private final GLCapabilitiesChooser chooser;
private int additionalCtxCreationFlags = 0;
- // Width of the actual GLJPanel
- private int panelWidth = 0;
- private int panelHeight = 0;
- // Lazy reshape notification
+ // Lazy reshape notification: reshapeWidth -> panelWidth -> backend.width
private boolean handleReshape = false;
private boolean sendReshape = true;
- // The backend in use
- private Backend backend;
+ private final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
- // Used by all backends either directly or indirectly to hook up callbacks
- private Updater updater = new Updater();
-
- // Turns off the pbuffer-based backend (used by default, unless the
- // Java 2D / OpenGL pipeline is in use)
- private static boolean hardwareAccelerationDisabled =
- Debug.isPropertyDefined("jogl.gljpanel.nohw", true);
-
- // Turns off the fallback to software-based rendering from
- // pbuffer-based rendering
- private static boolean softwareRenderingDisabled =
- Debug.isPropertyDefined("jogl.gljpanel.nosw", true);
-
- // Indicates whether the Java 2D OpenGL pipeline is enabled
- private boolean oglPipelineEnabled =
- Java2D.isOGLPipelineActive() &&
- !Debug.isPropertyDefined("jogl.gljpanel.noogl", true);
-
- // For handling reshape events lazily
- // private int reshapeX;
- // private int reshapeY;
+ // For handling reshape events lazily: reshapeWidth -> panelWidth -> backend.width
private int reshapeWidth;
private int reshapeHeight;
+ // Width of the actual GLJPanel: reshapeWidth -> panelWidth -> backend.width
+ private int panelWidth = 0;
+ private int panelHeight = 0;
+
// These are always set to (0, 0) except when the Java2D / OpenGL
// pipeline is active
private int viewportX;
private int viewportY;
- private AWTWindowClosingProtocol awtWindowClosingProtocol =
+ private int requestedTextureUnit = 0; // default
+
+ // The backend in use
+ private volatile Backend backend;
+
+ private boolean skipGLOrientationVerticalFlip = SKIP_VERTICAL_FLIP_DEFAULT;
+
+ // Used by all backends either directly or indirectly to hook up callbacks
+ private final Updater updater = new Updater();
+
+ private boolean oglPipelineUsable() {
+ return null == customPixelBufferProvider && useJava2DGLPipeline && java2DGLPipelineOK;
+ }
+
+ private volatile boolean isShowing;
+ private final HierarchyListener hierarchyListener = new HierarchyListener() {
+ @Override
+ public void hierarchyChanged(final HierarchyEvent e) {
+ isShowing = GLJPanel.this.isShowing();
+ }
+ };
+
+ private final AWTWindowClosingProtocol awtWindowClosingProtocol =
new AWTWindowClosingProtocol(this, new Runnable() {
@Override
public void run() {
GLJPanel.this.destroy();
}
- });
-
- static {
- // Force eager initialization of part of the Java2D class since
- // otherwise it's likely it will try to be initialized while on
- // the Queue Flusher Thread, which is not allowed
- if (Java2D.isOGLPipelineActive() && Java2D.isFBOEnabled()) {
- Java2D.getShareContext(GraphicsEnvironment.
- getLocalGraphicsEnvironment().
- getDefaultScreenDevice());
- }
- }
+ }, null);
/** Creates a new GLJPanel component with a default set of OpenGL
capabilities and using the default OpenGL capabilities selection
mechanism.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
* @throws GLException if no default profile is available for the default desktop device.
*/
public GLJPanel() throws GLException {
@@ -206,10 +323,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
/** Creates a new GLJPanel component with the requested set of
OpenGL capabilities, using the default OpenGL capabilities
selection mechanism.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
* @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
*/
- public GLJPanel(GLCapabilitiesImmutable userCapsRequest) throws GLException {
- this(userCapsRequest, null, null);
+ public GLJPanel(final GLCapabilitiesImmutable userCapsRequest) throws GLException {
+ this(userCapsRequest, null);
}
/** Creates a new GLJPanel component. The passed GLCapabilities
@@ -217,17 +337,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
default set of capabilities is used. The GLCapabilitiesChooser
specifies the algorithm for selecting one of the available
GLCapabilities for the component; a DefaultGLCapabilitesChooser
- is used if null is passed for this argument. The passed
- GLContext specifies an OpenGL context with which to share
- textures, display lists and other OpenGL state, and may be null
- if sharing is not desired. See the note in the overview documentation on
- <a href="../../../overview-summary.html#SHARING">context sharing</a>.
- <P>
- Note: Sharing cannot be enabled using J2D OpenGL FBO sharing,
- since J2D GL Context must be shared and we can only share one context.
+ is used if null is passed for this argument.
+ <p>
+ See details about <a href="#contextSharing">OpenGL context sharing</a>.
+ </p>
* @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
*/
- public GLJPanel(GLCapabilitiesImmutable userCapsRequest, GLCapabilitiesChooser chooser, GLContext shareWith)
+ public GLJPanel(final GLCapabilitiesImmutable userCapsRequest, final GLCapabilitiesChooser chooser)
throws GLException
{
super();
@@ -242,46 +358,124 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
caps = new GLCapabilities(GLProfile.getDefault(GLProfile.getDefaultDevice()));
}
caps.setDoubleBuffered(false);
- offscreenCaps = caps;
+ reqOffscreenCaps = caps;
}
- this.glProfile = offscreenCaps.getGLProfile();
- this.factory = GLDrawableFactoryImpl.getFactoryImpl(glProfile);
- this.chooser = ((chooser != null) ? chooser : new DefaultGLCapabilitiesChooser());
- this.shareWith = shareWith;
+ this.factory = GLDrawableFactoryImpl.getFactoryImpl( reqOffscreenCaps.getGLProfile() ); // pre-fetch, reqOffscreenCaps may changed
+ this.chooser = chooser;
+
+ helper = new GLDrawableHelper();
+ autoSwapBufferMode = helper.getAutoSwapBufferMode();
+
+ this.setFocusable(true); // allow keyboard input!
+ this.addHierarchyListener(hierarchyListener);
+ this.isShowing = isShowing();
+ }
+
+ /**
+ * Attempts to initialize the backend, if not initialized yet.
+ * <p>
+ * If backend is already initialized method returns <code>true</code>.
+ * </p>
+ * <p>
+ * If <code>offthread</code> is <code>true</code>, initialization will kicked off
+ * on a <i>short lived</i> arbitrary thread and method returns immediately.<br/>
+ * If platform supports such <i>arbitrary thread</i> initialization method returns
+ * <code>true</code>, otherwise <code>false</code>.
+ * </p>
+ * <p>
+ * If <code>offthread</code> is <code>false</code>, initialization be performed
+ * on the current thread and method returns after initialization.<br/>
+ * Method returns <code>true</code> if initialization was successful, otherwise <code>false</code>.
+ * <p>
+ * @param offthread
+ */
+ public final boolean initializeBackend(final boolean offthread) {
+ if( offthread ) {
+ new Thread(getThreadName()+"-GLJPanel_Init") {
+ public void run() {
+ if( !isInitialized ) {
+ initializeBackendImpl();
+ }
+ } }.start();
+ return true;
+ } else {
+ if( !isInitialized ) {
+ return initializeBackendImpl();
+ } else {
+ return true;
+ }
+ }
+ }
+
+ @Override
+ public final void setSharedContext(final GLContext sharedContext) throws IllegalStateException {
+ helper.setSharedContext(this.getContext(), sharedContext);
+ }
+
+ @Override
+ public final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
+ helper.setSharedAutoDrawable(this, sharedAutoDrawable);
+ }
+
+ public AWTGLPixelBufferProvider getCustomPixelBufferProvider() { return customPixelBufferProvider; }
+
+ /**
+ * @param custom custom {@link AWTGLPixelBufferProvider}
+ * @throws IllegalArgumentException if <code>custom</code> is <code>null</code>
+ * @throws IllegalStateException if backend is already realized, i.e. this instanced already painted once.
+ */
+ public void setPixelBufferProvider(final AWTGLPixelBufferProvider custom) throws IllegalArgumentException, IllegalStateException {
+ if( null == custom ) {
+ throw new IllegalArgumentException("Null PixelBufferProvider");
+ }
+ if( null != backend ) {
+ throw new IllegalStateException("Backend already realized.");
+ }
+ customPixelBufferProvider = custom;
}
@Override
public final Object getUpstreamWidget() {
return this;
}
-
+
+ @Override
+ public final RecursiveLock getUpstreamLock() { return lock; }
+
+ @Override
+ public final boolean isThreadGLCapable() { return EventQueue.isDispatchThread(); }
+
@Override
public void display() {
- if (EventQueue.isDispatchThread()) {
- // Want display() to be synchronous, so call paintImmediately()
- paintImmediately(0, 0, getWidth(), getHeight());
- } else {
- // Multithreaded redrawing of Swing components is not allowed,
- // so do everything on the event dispatch thread
- try {
- EventQueue.invokeAndWait(paintImmediatelyAction);
- } catch (Exception e) {
- throw new GLException(e);
- }
+ if( isShowing || ( printActive && isVisible() ) ) {
+ if (EventQueue.isDispatchThread()) {
+ // Want display() to be synchronous, so call paintImmediately()
+ paintImmediately(0, 0, getWidth(), getHeight());
+ } else {
+ // Multithreaded redrawing of Swing components is not allowed,
+ // so do everything on the event dispatch thread
+ try {
+ EventQueue.invokeAndWait(paintImmediatelyAction);
+ } catch (final Exception e) {
+ throw new GLException(e);
+ }
+ }
}
}
- protected void dispose() {
+ protected void dispose(final Runnable post) {
if(DEBUG) {
System.err.println(getThreadName()+": GLJPanel.dispose() - start");
// Thread.dumpStack();
}
if (backend != null && backend.getContext() != null) {
- boolean animatorPaused = false;
- GLAnimatorControl animator = getAnimator();
+ final boolean animatorPaused;
+ final GLAnimatorControl animator = getAnimator();
if(null!=animator) {
animatorPaused = animator.pause();
+ } else {
+ animatorPaused = false;
}
if(backend.getContext().isCreated()) {
@@ -292,8 +486,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
backend.destroy();
isInitialized = false;
}
+ if( null != post ) {
+ post.run();
+ }
- if(animatorPaused) {
+ if( animatorPaused ) {
animator.resume();
}
}
@@ -323,16 +520,16 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// Make GLJPanel behave better in NetBeans GUI builder
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
- FontMetrics fm = g.getFontMetrics();
+ final FontMetrics fm = g.getFontMetrics();
String name = getName();
if (name == null) {
name = getClass().getName();
- int idx = name.lastIndexOf('.');
+ final int idx = name.lastIndexOf('.');
if (idx >= 0) {
name = name.substring(idx + 1);
}
}
- Rectangle2D bounds = fm.getStringBounds(name, g);
+ final Rectangle2D bounds = fm.getStringBounds(name, g);
g.setColor(Color.WHITE);
g.drawString(name,
(int) ((getWidth() - bounds.getWidth()) / 2),
@@ -340,27 +537,77 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
return;
}
- if (backend == null || !isInitialized) {
- createAndInitializeBackend();
- }
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( !isInitialized ) {
+ initializeBackendImpl();
+ }
- if (!isInitialized) {
- return;
- }
+ if (!isInitialized || printActive) {
+ return;
+ }
- // NOTE: must do this when the context is not current as it may
- // involve destroying the pbuffer (current context) and
- // re-creating it -- tricky to do properly while the context is
- // current
- if (handleReshape) {
- handleReshape();
+ // NOTE: must do this when the context is not current as it may
+ // involve destroying the pbuffer (current context) and
+ // re-creating it -- tricky to do properly while the context is
+ // current
+ if( !printActive ) {
+ if ( handleReshape ) {
+ handleReshape = false;
+ sendReshape = handleReshape();
+ }
+
+ if( isShowing ) {
+ updater.setGraphics(g);
+ backend.doPaintComponent(g);
+ }
+ }
+ } finally {
+ _lock.unlock();
}
+ }
- updater.setGraphics(g);
+ private final void updateWrappedSurfaceScale(final GLDrawable d) {
+ final NativeSurface s = d.getNativeSurface();
+ if( s instanceof WrappedSurface ) {
+ ((WrappedSurface)s).setSurfaceScale(hasPixelScale);
+ }
+ }
- backend.doPaintComponent(g);
+ @Override
+ public final void setSurfaceScale(final int[] pixelScale) { // HiDPI support
+ SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG ? getClass().getSimpleName() : null);
+ final Backend b = backend;
+ if ( isInitialized && null != b ) {
+ final int hadPixelScaleX = hasPixelScale[0];
+ final int hadPixelScaleY = hasPixelScale[1];
+ SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null);
+ if( hadPixelScaleX != hasPixelScale[0] || hadPixelScaleY != hasPixelScale[1] ) {
+ updateWrappedSurfaceScale(b.getDrawable());
+ reshapeImpl(getWidth(), getHeight());
+ display();
+ }
+ }
}
+ @Override
+ public final int[] getRequestedSurfaceScale(final int[] result) {
+ System.arraycopy(reqPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final int[] getCurrentSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public int[] getNativeSurfaceScale(final int[] result) {
+ System.arraycopy(nativePixelScale, 0, result, 0, 2);
+ return result;
+ }
/** Overridden to track when this component is added to a container.
Subclasses which override this method must call
@@ -371,8 +618,18 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public void addNotify() {
super.addNotify();
+ awtWindowClosingProtocol.addClosingListener();
+
+ // HiDPI support
+ {
+ final int ps = JAWTUtil.getPixelScale(getGraphicsConfiguration());
+ nativePixelScale[0] = ps;
+ nativePixelScale[1] = ps;
+ }
+ SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null);
+
if (DEBUG) {
- System.err.println(getThreadName()+": GLJPanel.addNotify()");
+ System.err.println(getThreadName()+": GLJPanel.addNotify()");
}
}
@@ -386,7 +643,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
public void removeNotify() {
awtWindowClosingProtocol.removeClosingListener();
- dispose();
+ dispose(null);
+ hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+
super.removeNotify();
}
@@ -394,21 +656,252 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
called on all registered {@link GLEventListener}s. Subclasses
which override this method must call super.reshape() in
their reshape() method in order to function properly. <P>
-
- <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
+ *
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("deprecation")
@Override
- public void reshape(int x, int y, int width, int height) {
+ public void reshape(final int x, final int y, final int width, final int height) {
super.reshape(x, y, width, height);
+ reshapeImpl(width, height);
+ }
+
+ private void reshapeImpl(final int width, final int height) {
+ final int scaledWidth = width * hasPixelScale[0];
+ final int scaledHeight = height * hasPixelScale[1];
+ if( !printActive && ( handleReshape || scaledWidth != panelWidth || scaledHeight != panelHeight ) ) {
+ reshapeWidth = scaledWidth;
+ reshapeHeight = scaledHeight;
+ handleReshape = true;
+ }
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": GLJPanel.reshape.0 "+this.getName()+" resize ["+(printActive?"printing":"paint")+
+ "] [ this "+getWidth()+"x"+getHeight()+", pixelScale "+getPixelScaleStr()+
+ ", panel "+panelWidth+"x"+panelHeight +
+ "] -> "+(handleReshape?"":"[skipped] ") + width+"x"+height+" * "+getPixelScaleStr()+
+ " -> "+scaledWidth+"x"+scaledHeight+", reshapeSize "+reshapeWidth+"x"+reshapeHeight);
+ }
+ }
+
+ private volatile boolean printActive = false;
+ private GLAnimatorControl printAnimator = null;
+ private GLAutoDrawable printGLAD = null;
+ private AWTTilePainter printAWTTiles = null;
+
+ @Override
+ public void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight) {
+ printActive = true;
+ if( DEBUG ) {
+ System.err.printf(getThreadName()+": GLJPanel.setupPrint: scale %f / %f, samples %d, tileSz %d x %d%n", scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight);
+ }
+ final int componentCount = isOpaque() ? 3 : 4;
+ final TileRenderer printRenderer = new TileRenderer();
+ printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
+ }
+ private final Runnable setupPrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( !isInitialized ) {
+ initializeBackendImpl();
+ }
+ if (!isInitialized) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, drawable not valid yet");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ if( !isVisible() ) {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, panel not visible");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ sendReshape = false; // clear reshape flag
+ handleReshape = false; // ditto
+ printAnimator = helper.getAnimator();
+ if( null != printAnimator ) {
+ printAnimator.remove(GLJPanel.this);
+ }
+
+ printGLAD = GLJPanel.this; // default: re-use
+ final GLCapabilitiesImmutable gladCaps = getChosenGLCapabilities();
+ final int printNumSamples = printAWTTiles.getNumSamples(gladCaps);
+ GLDrawable printDrawable = printGLAD.getDelegatedDrawable();
+ final boolean reqNewGLADSamples = printNumSamples != gladCaps.getNumSamples();
+ final boolean reqNewGLADSize = printAWTTiles.customTileWidth != -1 && printAWTTiles.customTileWidth != printDrawable.getSurfaceWidth() ||
+ printAWTTiles.customTileHeight != -1 && printAWTTiles.customTileHeight != printDrawable.getSurfaceHeight();
+
+ final GLCapabilities newGLADCaps = (GLCapabilities)gladCaps.cloneMutable();
+ newGLADCaps.setDoubleBuffered(false);
+ newGLADCaps.setOnscreen(false);
+ if( printNumSamples != newGLADCaps.getNumSamples() ) {
+ newGLADCaps.setSampleBuffers(0 < printNumSamples);
+ newGLADCaps.setNumSamples(printNumSamples);
+ }
+ final boolean reqNewGLADSafe = GLDrawableUtil.isSwapGLContextSafe(getRequestedGLCapabilities(), gladCaps, newGLADCaps);
+
+ final boolean reqNewGLAD = ( reqNewGLADSamples || reqNewGLADSize ) && reqNewGLADSafe;
- // reshapeX = x;
- // reshapeY = y;
- reshapeWidth = width;
- reshapeHeight = height;
- handleReshape = true;
+ if( DEBUG ) {
+ System.err.println("AWT print.setup: reqNewGLAD "+reqNewGLAD+"[ samples "+reqNewGLADSamples+", size "+reqNewGLADSize+", safe "+reqNewGLADSafe+"], "+
+ ", drawableSize "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+
+ ", customTileSize "+printAWTTiles.customTileWidth+"x"+printAWTTiles.customTileHeight+
+ ", scaleMat "+printAWTTiles.scaleMatX+" x "+printAWTTiles.scaleMatY+
+ ", numSamples "+printAWTTiles.customNumSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
+ }
+ if( reqNewGLAD ) {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(newGLADCaps.getGLProfile());
+ GLOffscreenAutoDrawable offGLAD = null;
+ try {
+ offGLAD = factory.createOffscreenAutoDrawable(null, newGLADCaps, null,
+ printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
+ printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
+ } catch (final GLException gle) {
+ if( DEBUG ) {
+ System.err.println("Caught: "+gle.getMessage());
+ gle.printStackTrace();
+ }
+ }
+ if( null != offGLAD ) {
+ printGLAD = offGLAD;
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(GLJPanel.this, printGLAD);
+ printDrawable = printGLAD.getDelegatedDrawable();
+ }
+ }
+ printAWTTiles.setGLOrientation( !GLJPanel.this.skipGLOrientationVerticalFlip && printGLAD.isGLOriented(), printGLAD.isGLOriented() );
+ printAWTTiles.renderer.setTileSize(printDrawable.getSurfaceWidth(), printDrawable.getSurfaceHeight(), 0);
+ printAWTTiles.renderer.attachAutoDrawable(printGLAD);
+ if( DEBUG ) {
+ System.err.println("AWT print.setup "+printAWTTiles);
+ System.err.println("AWT print.setup AA "+printNumSamples+", "+newGLADCaps);
+ System.err.println("AWT print.setup printGLAD: "+printGLAD.getSurfaceWidth()+"x"+printGLAD.getSurfaceHeight()+", "+printGLAD);
+ System.err.println("AWT print.setup printDraw: "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+", "+printDrawable);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ @Override
+ public void releasePrint() {
+ if( !printActive ) {
+ throw new IllegalStateException("setupPrint() not called");
+ }
+ sendReshape = false; // clear reshape flag
+ handleReshape = false; // ditto
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, releasePrintOnEDT);
+ }
+
+ private final Runnable releasePrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": GLJPanel.releasePrintOnEDT.0 "+printAWTTiles);
+ }
+ printAWTTiles.dispose();
+ printAWTTiles= null;
+ if( printGLAD != GLJPanel.this ) {
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, GLJPanel.this);
+ printGLAD.destroy();
+ }
+ printGLAD = null;
+ if( null != printAnimator ) {
+ printAnimator.add(GLJPanel.this);
+ printAnimator = null;
+ }
+
+ // trigger reshape, i.e. gl-viewport and -listener - this component might got resized!
+ final int awtWidth = GLJPanel.this.getWidth();
+ final int awtHeight= GLJPanel.this.getHeight();
+ final int scaledAWTWidth = awtWidth * hasPixelScale[0];
+ final int scaledAWTHeight= awtHeight * hasPixelScale[1];
+ final GLDrawable drawable = GLJPanel.this.getDelegatedDrawable();
+ if( scaledAWTWidth != panelWidth || scaledAWTHeight != panelHeight ||
+ drawable.getSurfaceWidth() != panelWidth || drawable.getSurfaceHeight() != panelHeight ) {
+ // -> !( awtSize == panelSize == drawableSize )
+ if ( DEBUG ) {
+ System.err.println(getThreadName()+": GLJPanel.releasePrintOnEDT.0: resize [printing] panel " +panelWidth+"x"+panelHeight + " @ scale "+getPixelScaleStr()+
+ ", draw "+drawable.getSurfaceWidth()+"x"+drawable.getSurfaceHeight()+
+ " -> " + awtWidth+"x"+awtHeight+" * "+getPixelScaleStr()+" -> "+scaledAWTWidth+"x"+scaledAWTHeight);
+ }
+ reshapeWidth = scaledAWTWidth;
+ reshapeHeight = scaledAWTHeight;
+ sendReshape = handleReshape(); // reshapeSize -> panelSize, backend reshape w/ GL reshape
+ } else {
+ sendReshape = true; // only GL reshape
+ }
+ printActive = false;
+ display();
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
+ @Override
+ public void print(final Graphics graphics) {
+ if( !printActive ) {
+ throw new IllegalStateException("setupPrint() not called");
+ }
+ if(DEBUG && !EventQueue.isDispatchThread()) {
+ System.err.println(getThreadName()+": Warning: GLCanvas print - not called from AWT-EDT");
+ // we cannot dispatch print on AWT-EDT due to printing internal locking ..
+ }
+ sendReshape = false; // clear reshape flag
+ handleReshape = false; // ditto
+
+ final Graphics2D g2d = (Graphics2D)graphics;
+ try {
+ printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
+ final TileRenderer tileRenderer = printAWTTiles.renderer;
+ if( DEBUG ) {
+ System.err.println("AWT print.0: "+tileRenderer);
+ }
+ if( !tileRenderer.eot() ) {
+ try {
+ do {
+ if( printGLAD != GLJPanel.this ) {
+ tileRenderer.display();
+ } else {
+ backend.doPlainPaint();
+ }
+ } while ( !tileRenderer.eot() );
+ if( DEBUG ) {
+ System.err.println("AWT print.1: "+printAWTTiles);
+ }
+ } finally {
+ tileRenderer.reset();
+ printAWTTiles.resetGraphics2D();
+ }
+ }
+ } catch (final NoninvertibleTransformException nte) {
+ System.err.println("Caught: Inversion failed of: "+g2d.getTransform());
+ nte.printStackTrace();
+ }
+ if( DEBUG ) {
+ System.err.println("AWT print.X: "+printAWTTiles);
+ }
+ }
+ @Override
+ protected void printComponent(final Graphics g) {
+ if( DEBUG ) {
+ System.err.println("AWT printComponent.X: "+printAWTTiles);
+ }
+ print(g);
}
@Override
- public void setOpaque(boolean opaque) {
+ public void setOpaque(final boolean opaque) {
if (backend != null) {
backend.setOpaque(opaque);
}
@@ -416,27 +909,64 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void addGLEventListener(GLEventListener listener) {
+ public void addGLEventListener(final GLEventListener listener) {
helper.addGLEventListener(listener);
}
@Override
- public void addGLEventListener(int index, GLEventListener listener) {
+ public void addGLEventListener(final int index, final GLEventListener listener) {
helper.addGLEventListener(index, listener);
}
@Override
- public void removeGLEventListener(GLEventListener listener) {
- helper.removeGLEventListener(listener);
+ public int getGLEventListenerCount() {
+ return helper.getGLEventListenerCount();
+ }
+
+ @Override
+ public GLEventListener getGLEventListener(final int index) throws IndexOutOfBoundsException {
+ return helper.getGLEventListener(index);
}
@Override
- public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
- return helper.removeGLEventListener(index);
- }
-
+ public boolean areAllGLEventListenerInitialized() {
+ return helper.areAllGLEventListenerInitialized();
+ }
+
@Override
- public void setAnimator(GLAnimatorControl animatorControl) {
+ public boolean getGLEventListenerInitState(final GLEventListener listener) {
+ return helper.getGLEventListenerInitState(listener);
+ }
+
+ @Override
+ public void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized) {
+ helper.setGLEventListenerInitState(listener, initialized);
+ }
+
+ @Override
+ public GLEventListener disposeGLEventListener(final GLEventListener listener, final boolean remove) {
+ final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
+ if (EventQueue.isDispatchThread()) {
+ r.run();
+ } else {
+ // Multithreaded redrawing of Swing components is not allowed,
+ // so do everything on the event dispatch thread
+ try {
+ EventQueue.invokeAndWait(r);
+ } catch (final Exception e) {
+ throw new GLException(e);
+ }
+ }
+ return r.listener;
+ }
+
+ @Override
+ public GLEventListener removeGLEventListener(final GLEventListener listener) {
+ return helper.removeGLEventListener(listener);
+ }
+
+ @Override
+ public void setAnimator(final GLAnimatorControl animatorControl) {
helper.setAnimator(animatorControl);
}
@@ -446,17 +976,47 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public boolean invoke(boolean wait, GLRunnable glRunnable) {
+ public final Thread setExclusiveContextThread(final Thread t) throws GLException {
+ return helper.setExclusiveContextThread(t, getContext());
+ }
+
+ @Override
+ public final Thread getExclusiveContextThread() {
+ return helper.getExclusiveContextThread();
+ }
+
+ @Override
+ public boolean invoke(final boolean wait, final GLRunnable glRunnable) throws IllegalStateException {
return helper.invoke(this, wait, glRunnable);
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return (null != backend) ? backend.createContext(shareWith) : null;
+ public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) throws IllegalStateException {
+ return helper.invoke(this, wait, glRunnables);
+ }
+
+ @Override
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
+ }
+
+ @Override
+ public GLContext createContext(final GLContext shareWith) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
+ }
+ return b.createContext(shareWith);
+ } finally {
+ _lock.unlock();
+ }
}
@Override
- public void setRealized(boolean realized) {
+ public void setRealized(final boolean realized) {
}
@Override
@@ -465,34 +1025,40 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public GLContext setContext(GLContext newCtx) {
- if (backend == null) {
- return null;
- }
- final GLContext oldCtx = backend.getContext();
- final boolean newCtxCurrent = GLDrawableHelper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags);
- backend.setContext(newCtx);
- if(newCtxCurrent) {
- newCtx.makeCurrent();
- }
- return oldCtx;
+ public GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
+ }
+ final GLContext oldCtx = b.getContext();
+ GLDrawableHelper.switchContext(b.getDrawable(), oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
+ b.setContext(newCtx);
+ return oldCtx;
+ } finally {
+ _lock.unlock();
+ }
}
@Override
public final GLDrawable getDelegatedDrawable() {
- if (backend == null) {
- return null;
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
}
- return backend.getDrawable();
+ return b.getDrawable();
}
-
+
@Override
public GLContext getContext() {
- if (backend == null) {
- return null;
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
}
- return backend.getContext();
+ return b.getContext();
}
@Override
@@ -500,13 +1066,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
if (Beans.isDesignTime()) {
return null;
}
- GLContext context = getContext();
+ final GLContext context = getContext();
return (context == null) ? null : context.getGL();
}
@Override
- public GL setGL(GL gl) {
- GLContext context = getContext();
+ public GL setGL(final GL gl) {
+ final GLContext context = getContext();
if (context != null) {
context.setGL(gl);
return gl;
@@ -515,35 +1081,37 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void setAutoSwapBufferMode(boolean onOrOff) {
- // In the current implementation this is a no-op. Both the pbuffer
- // and pixmap based rendering paths use a single-buffered surface
- // so swapping the buffers doesn't do anything. We also don't
- // currently have the provision to skip copying the data to the
- // Swing portion of the GLJPanel in any of the rendering paths.
+ public void setAutoSwapBufferMode(final boolean enable) {
+ this.autoSwapBufferMode = enable;
+ boolean backendHandlesSwapBuffer = false;
+ if( isInitialized ) {
+ final Backend b = backend;
+ if ( null != b ) {
+ backendHandlesSwapBuffer= b.handlesSwapBuffer();
+ }
+ }
+ if( !backendHandlesSwapBuffer ) {
+ helper.setAutoSwapBufferMode(enable);
+ }
}
@Override
public boolean getAutoSwapBufferMode() {
- // In the current implementation this is a no-op. Both the pbuffer
- // and pixmap based rendering paths use a single-buffered surface
- // so swapping the buffers doesn't do anything. We also don't
- // currently have the provision to skip copying the data to the
- // Swing portion of the GLJPanel in any of the rendering paths.
- return true;
+ return autoSwapBufferMode;
}
@Override
public void swapBuffers() {
- // In the current implementation this is a no-op. Both the pbuffer
- // and pixmap based rendering paths use a single-buffered surface
- // so swapping the buffers doesn't do anything. We also don't
- // currently have the provision to skip copying the data to the
- // Swing portion of the GLJPanel in any of the rendering paths.
+ if( isInitialized ) {
+ final Backend b = backend;
+ if ( null != b ) {
+ b.swapBuffers();
+ }
+ }
}
@Override
- public void setContextCreationFlags(int flags) {
+ public void setContextCreationFlags(final int flags) {
additionalCtxCreationFlags = flags;
}
@@ -565,27 +1133,123 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
to perform OpenGL rendering using the GLJPanel into the same
OpenGL drawable as the Swing implementation uses. */
public boolean shouldPreserveColorBufferIfTranslucent() {
- return oglPipelineEnabled;
+ return oglPipelineUsable();
+ }
+
+ @Override
+ public int getSurfaceWidth() {
+ return panelWidth; // scaled surface width in pixel units, current as-from reshape
+ }
+
+ @Override
+ public int getSurfaceHeight() {
+ return panelHeight; // scaled surface height in pixel units, current as-from reshape
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Method returns a valid value only <i>after</i>
+ * the backend has been initialized, either {@link #initializeBackend(boolean) eagerly}
+ * or manually via the first display call.<br/>
+ * Method always returns a valid value when called from within a {@link GLEventListener}.
+ * </p>
+ */
+ @Override
+ public boolean isGLOriented() {
+ final Backend b = backend;
+ if ( null == b ) {
+ return true;
+ }
+ return b.getDrawable().isGLOriented();
+ }
+
+ /**
+ * Skip {@link #isGLOriented()} based vertical flip,
+ * which usually is required by the offscreen backend,
+ * see details about <a href="#verticalFlip">vertical flip</a>
+ * and <a href="#fboGLSLVerticalFlip">FBO / GLSL vertical flip</a>.
+ * <p>
+ * If set to <code>true</code>, user needs to flip the OpenGL rendered scene
+ * <i>if {@link #isGLOriented()} == true</i>, e.g. via the projection matrix.<br/>
+ * See constraints of {@link #isGLOriented()}.
+ * </p>
+ */
+ public final void setSkipGLOrientationVerticalFlip(final boolean v) {
+ skipGLOrientationVerticalFlip = v;
+ }
+ /** See {@link #setSkipGLOrientationVerticalFlip(boolean)}. */
+ public final boolean getSkipGLOrientationVerticalFlip() {
+ return skipGLOrientationVerticalFlip;
}
@Override
public GLCapabilitiesImmutable getChosenGLCapabilities() {
- return backend.getChosenGLCapabilities();
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
+ }
+ return b.getChosenGLCapabilities();
+ }
+
+ @Override
+ public final GLCapabilitiesImmutable getRequestedGLCapabilities() {
+ return reqOffscreenCaps;
+ }
+
+ /**
+ * Set a new requested {@link GLCapabilitiesImmutable} for this GLJPanel
+ * allowing reconfiguration.
+ * <p>
+ * Method shall be invoked from the {@link #isThreadGLCapable() AWT-EDT thread}.
+ * In case it is not invoked on the AWT-EDT thread, an attempt is made to do so.
+ * </p>
+ * <p>
+ * Method will dispose a previous {@link #isRealized() realized} GLContext and offscreen backend!
+ * </p>
+ * @param caps new capabilities.
+ */
+ public final void setRequestedGLCapabilities(final GLCapabilitiesImmutable caps) {
+ if( null == caps ) {
+ throw new IllegalArgumentException("null caps");
+ }
+ Threading.invoke(true,
+ new Runnable() {
+ @Override
+ public void run() {
+ dispose( new Runnable() {
+ @Override
+ public void run() {
+ // switch to new caps and re-init backend
+ // after actual dispose, but before resume animator
+ reqOffscreenCaps = caps;
+ initializeBackendImpl();
+ } } );
+ }
+ }, getTreeLock());
}
@Override
public final GLProfile getGLProfile() {
- return glProfile;
+ return reqOffscreenCaps.getGLProfile();
}
@Override
public NativeSurface getNativeSurface() {
- throw new GLException("FIXME");
+ final Backend b = backend;
+ if ( null == b ) {
+ return null;
+ }
+ return b.getDrawable().getNativeSurface();
}
@Override
public long getHandle() {
- throw new GLException("FIXME");
+ final Backend b = backend;
+ if ( null == b ) {
+ return 0;
+ }
+ return b.getDrawable().getNativeSurface().getSurfaceHandle();
}
@Override
@@ -593,76 +1257,110 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
return factory;
}
+ /**
+ * Returns the used texture unit, i.e. a value of [0..n], or -1 if non used.
+ * <p>
+ * If implementation uses a texture-unit, it will be known only after the first initialization, i.e. display call.
+ * </p>
+ * <p>
+ * See <a href="#fboGLSLVerticalFlip">FBO / GLSL Vertical Flip</a>.
+ * </p>
+ */
+ public final int getTextureUnit() {
+ final Backend b = backend;
+ if ( null == b ) {
+ return -1;
+ }
+ return b.getTextureUnit();
+ }
+
+ /**
+ * Allows user to request a texture unit to be used,
+ * must be called before the first initialization, i.e. {@link #display()} call.
+ * <p>
+ * Defaults to <code>0</code>.
+ * </p>
+ * <p>
+ * See <a href="#fboGLSLVerticalFlip">FBO / GLSL Vertical Flip</a>.
+ * </p>
+ *
+ * @param v requested texture unit
+ * @see #getTextureUnit()
+ */
+ public final void setTextureUnit(final int v) {
+ requestedTextureUnit = v;
+ }
+
//----------------------------------------------------------------------
// Internals only below this point
//
- private void createAndInitializeBackend() {
- if (panelWidth == 0 ||
- panelHeight == 0) {
- // See whether we have a non-zero size yet and can go ahead with
- // initialization
- if (reshapeWidth == 0 ||
- reshapeHeight == 0) {
- return;
- }
-
- // Pull down reshapeWidth and reshapeHeight into panelWidth and
- // panelHeight eagerly in order to complete initialization, and
- // force a reshape later
- panelWidth = reshapeWidth;
- panelHeight = reshapeHeight;
- }
+ private final Object initSync = new Object();
+ private boolean initializeBackendImpl() {
+ synchronized(initSync) {
+ if( !isInitialized ) {
+ if( handleReshape ) {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.createAndInitializeBackend.1: ["+(printActive?"printing":"paint")+"] "+
+ panelWidth+"x"+panelHeight+" @ scale "+getPixelScaleStr() + " -> " +
+ reshapeWidth+"x"+reshapeHeight+" @ scale "+getPixelScaleStr());
+ }
+ panelWidth = reshapeWidth;
+ panelHeight = reshapeHeight;
+ handleReshape = false;
+ } else {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.createAndInitializeBackend.0: ["+(printActive?"printing":"paint")+"] "+
+ panelWidth+"x"+panelHeight+" @ scale "+getPixelScaleStr());
+ }
+ }
- do {
- if (backend == null) {
- if (oglPipelineEnabled) {
- backend = new J2DOGLBackend();
- } else {
- if (!hardwareAccelerationDisabled &&
- factory.canCreateGLPbuffer(null)) {
- backend = new PbufferBackend();
- } else {
- if (softwareRenderingDisabled) {
- throw new GLException("Fallback to software rendering disabled by user");
+ if ( 0 >= panelWidth || 0 >= panelHeight ) {
+ return false;
}
- backend = new SoftwareBackend();
- }
- }
- }
- if (!isInitialized) {
- backend.initialize();
- }
- // The backend might set itself to null, indicating it punted to
- // a different implementation -- try again
- } while (backend == null);
+ if ( null == backend ) {
+ if ( oglPipelineUsable() ) {
+ backend = new J2DOGLBackend();
+ } else {
+ backend = new OffscreenBackend(customPixelBufferProvider);
+ }
+ isInitialized = false;
+ }
- awtWindowClosingProtocol.addClosingListenerOneShot();
+ if (!isInitialized) {
+ this.factory = GLDrawableFactoryImpl.getFactoryImpl( reqOffscreenCaps.getGLProfile() ); // reqOffscreenCaps may have changed
+ backend.initialize();
+ }
+ return isInitialized;
+ } else {
+ return true;
+ }
+ }
}
+ private final String getPixelScaleStr() { return hasPixelScale[0]+"x"+hasPixelScale[1]; }
+
@Override
public WindowClosingMode getDefaultCloseOperation() {
return awtWindowClosingProtocol.getDefaultCloseOperation();
}
@Override
- public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
+ public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
return awtWindowClosingProtocol.setDefaultCloseOperation(op);
}
- private void handleReshape() {
- panelWidth = reshapeWidth;
- panelHeight = reshapeHeight;
-
+ private boolean handleReshape() {
if (DEBUG) {
- System.err.println(getThreadName()+": GLJPanel.handleReshape: (w,h) = (" +
- panelWidth + "," + panelHeight + ")");
+ System.err.println(getThreadName()+": GLJPanel.handleReshape: "+
+ panelWidth+"x"+panelHeight+" @ scale "+getPixelScaleStr() + " -> " +
+ reshapeWidth+"x"+reshapeHeight+" @ scale "+getPixelScaleStr());
}
+ panelWidth = reshapeWidth;
+ panelHeight = reshapeHeight;
- sendReshape = true;
- backend.handleReshape();
- handleReshape = false;
+ return backend.handleReshape();
}
// This is used as the GLEventListener for the pbuffer-based backend
@@ -670,32 +1368,32 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
class Updater implements GLEventListener {
private Graphics g;
- public void setGraphics(Graphics g) {
+ public void setGraphics(final Graphics g) {
this.g = g;
}
@Override
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
if (!backend.preGL(g)) {
return;
}
- helper.init(GLJPanel.this);
+ helper.init(GLJPanel.this, !sendReshape);
backend.postGL(g, false);
}
@Override
- public void dispose(GLAutoDrawable drawable) {
- helper.dispose(GLJPanel.this);
+ public void dispose(final GLAutoDrawable drawable) {
+ helper.disposeAllGLEventListener(GLJPanel.this, false);
}
@Override
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
if (!backend.preGL(g)) {
return;
}
if (sendReshape) {
if (DEBUG) {
- System.err.println(getThreadName()+": GLJPanel.display: reshape(" + viewportX + "," + viewportY + " " + panelWidth + "x" + panelHeight + ")");
+ System.err.println(getThreadName()+": GLJPanel.display: reshape(" + viewportX + "," + viewportY + " " + panelWidth + "x" + panelHeight + " @ scale "+getPixelScaleStr()+")");
}
helper.reshape(GLJPanel.this, viewportX, viewportY, panelWidth, panelHeight);
sendReshape = false;
@@ -705,35 +1403,64 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
backend.postGL(g, true);
}
- @Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- // This is handled above and dispatched directly to the appropriate context
+ public void plainPaint(final GLAutoDrawable drawable) {
+ helper.display(GLJPanel.this);
}
- public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ // This is handled above and dispatched directly to the appropriate context
}
}
@Override
public String toString() {
- return "AWT-GLJPanel[ "+((null!=backend)?backend.getDrawable().getClass().getName():"null-drawable")+"]";
+ final GLDrawable d = ( null != backend ) ? backend.getDrawable() : null;
+ return "AWT-GLJPanel[ drawableType "+ ( ( null != d ) ? d.getClass().getName() : "null" ) +
+ ", chosenCaps " + getChosenGLCapabilities() +
+ "]";
}
- private final Runnable postDisposeAction = new Runnable() {
- @Override
- public void run() {
- if (backend != null && !backend.isUsingOwnThreadManagment()) {
- backend.destroy();
- backend = null;
- isInitialized = false;
- }
- }
- };
-
private final Runnable disposeAction = new Runnable() {
@Override
public void run() {
- helper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction);
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ if ( null != backend ) {
+ final GLContext _context = backend.getContext();
+ final boolean backendDestroy = !backend.isUsingOwnLifecycle();
+
+ GLException exceptionOnDisposeGL = null;
+ if( null != _context && _context.isCreated() ) {
+ try {
+ helper.disposeGL(GLJPanel.this, _context, !backendDestroy);
+ } catch (final GLException gle) {
+ exceptionOnDisposeGL = gle;
+ }
+ }
+ Throwable exceptionBackendDestroy = null;
+ if ( backendDestroy ) {
+ try {
+ backend.destroy();
+ } catch( final Throwable re ) {
+ exceptionBackendDestroy = re;
+ }
+ backend = null;
+ isInitialized = false;
+ }
+
+ // throw exception in order of occurrence ..
+ if( null != exceptionOnDisposeGL ) {
+ throw exceptionOnDisposeGL;
+ }
+ if( null != exceptionBackendDestroy ) {
+ throw GLException.newGLException(exceptionBackendDestroy);
+ }
+ }
+ } finally {
+ _lock.unlock();
+ }
}
};
@@ -751,6 +1478,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
};
+ private final Runnable updaterPlainDisplayAction = new Runnable() {
+ @Override
+ public void run() {
+ updater.plainPaint(GLJPanel.this);
+ }
+ };
+
private final Runnable paintImmediatelyAction = new Runnable() {
@Override
public void run() {
@@ -758,298 +1492,292 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
};
- private int getNextPowerOf2(int number) {
- // Workaround for problems where 0 width or height are transiently
- // seen during layout
- if (number == 0) {
- return 2;
- }
- return GLBuffers.getNextPowerOf2(number);
- }
+ private class DisposeGLEventListenerAction implements Runnable {
+ GLEventListener listener;
+ private final boolean remove;
+ private DisposeGLEventListenerAction(final GLEventListener listener, final boolean remove) {
+ this.listener = listener;
+ this.remove = remove;
+ }
- private int getGLInteger(GL gl, int which) {
- int[] tmp = new int[1];
+ @Override
+ public void run() {
+ final Backend b = backend;
+ if ( null != b ) {
+ listener = helper.disposeGLEventListener(GLJPanel.this, b.getDrawable(), b.getContext(), listener, remove);
+ }
+ }
+ };
+
+ private int getGLInteger(final GL gl, final int which) {
+ final int[] tmp = new int[1];
gl.glGetIntegerv(which, tmp, 0);
return tmp[0];
}
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
//----------------------------------------------------------------------
// Implementations of the various backends
//
- // Abstraction of the different rendering backends: i.e., pure
- // software / pixmap rendering, pbuffer-based acceleration, Java 2D
- // / JOGL bridge
+ /**
+ * Abstraction of the different rendering backends: i.e., pure
+ * software / pixmap rendering, pbuffer-based acceleration, Java 2D
+ * JOGL bridge
+ */
static interface Backend {
- // Create, Destroy, ..
- public boolean isUsingOwnThreadManagment();
+ /** Create, Destroy, .. */
+ public boolean isUsingOwnLifecycle();
- // Called each time the backend needs to initialize itself
+ /** Called each time the backend needs to initialize itself */
public void initialize();
- // Called when the backend should clean up its resources
+ /** Called when the backend should clean up its resources */
public void destroy();
- // Called when the opacity of the GLJPanel is changed
+ /** Called when the opacity of the GLJPanel is changed */
public void setOpaque(boolean opaque);
- // Called to manually create an additional OpenGL context against
- // this GLJPanel
+ /**
+ * Called to manually create an additional OpenGL context against
+ * this GLJPanel
+ */
public GLContext createContext(GLContext shareWith);
- // Called to set the current backend's GLContext
+ /** Called to set the current backend's GLContext */
public void setContext(GLContext ctx);
- // Called to get the current backend's GLContext
+ /** Called to get the current backend's GLContext */
public GLContext getContext();
- // Called to get the current backend's GLDrawable
+ /** Called to get the current backend's GLDrawable */
public GLDrawable getDrawable();
- // Called to fetch the "real" GLCapabilities for the backend
+ /** Returns the used texture unit, i.e. a value of [0..n], or -1 if non used. */
+ public int getTextureUnit();
+
+ /** Called to fetch the "real" GLCapabilities for the backend */
public GLCapabilitiesImmutable getChosenGLCapabilities();
- // Called to fetch the "real" GLProfile for the backend
+ /** Called to fetch the "real" GLProfile for the backend */
public GLProfile getGLProfile();
- // Called to handle a reshape event. When this is called, the
- // OpenGL context associated with the backend is not current, to
- // make it easier to destroy and re-create pbuffers if necessary.
- public void handleReshape();
-
- // Called before the OpenGL work is done in init() and display().
- // If false is returned, this render is aborted.
+ /**
+ * Called to handle a reshape event. When this is called, the
+ * OpenGL context associated with the backend is not current, to
+ * make it easier to destroy and re-create pbuffers if necessary.
+ */
+ public boolean handleReshape();
+
+ /**
+ * Called before the OpenGL work is done in init() and display().
+ * If false is returned, this render is aborted.
+ */
public boolean preGL(Graphics g);
- // Called after the OpenGL work is done in init() and display().
- // The isDisplay argument indicates whether this was called on
- // behalf of a call to display() rather than init().
+ /**
+ * Return true if backend handles 'swap buffer' itself
+ * and hence the helper's setAutoSwapBuffer(enable) shall not be called.
+ * In this case {@link GLJPanel#autoSwapBufferMode} is being used
+ * in the backend to determine whether to swap buffers or not.
+ */
+ public boolean handlesSwapBuffer();
+
+ /**
+ * Shall invoke underlying drawable's swapBuffer.
+ */
+ public void swapBuffers();
+
+ /**
+ * Called after the OpenGL work is done in init() and display().
+ * The isDisplay argument indicates whether this was called on
+ * behalf of a call to display() rather than init().
+ */
public void postGL(Graphics g, boolean isDisplay);
- // Called from within paintComponent() to initiate the render
+ /** Called from within paintComponent() to initiate the render */
public void doPaintComponent(Graphics g);
+
+ /** Called from print .. no backend update desired onscreen */
+ public void doPlainPaint();
}
// Base class used by both the software (pixmap) and pbuffer
// backends, both of which rely on reading back the OpenGL frame
// buffer and drawing it with a BufferedImage
- abstract class AbstractReadbackBackend implements Backend {
- // This image is exactly the correct size to render into the panel
- protected BufferedImage offscreenImage;
+ class OffscreenBackend implements Backend {
+ private final AWTGLPixelBufferProvider pixelBufferProvider;
+ private final boolean useSingletonBuffer;
+ private AWTGLPixelBuffer pixelBuffer;
+ private BufferedImage alignedImage;
+
// One of these is used to store the read back pixels before storing
// in the BufferedImage
- protected ByteBuffer readBackBytes;
- protected IntBuffer readBackInts;
- protected int readBackWidthInPixels;
- protected int readBackHeightInPixels;
+ protected IntBuffer readBackIntsForCPUVFlip;
+
+ // Implementation using software rendering
+ private volatile GLDrawable offscreenDrawable; // volatile: avoid locking for read-only access
+ private boolean offscreenIsFBO;
+ private FBObject fboFlipped;
+ private GLSLTextureRaster glslTextureRaster;
- private int glFormat;
- private int glType;
+ private volatile GLContextImpl offscreenContext; // volatile: avoid locking for read-only access
+ private boolean flipVertical;
+ private int frameCount = 0;
// For saving/restoring of OpenGL state during ReadPixels
- private int[] swapbytes = new int[1];
- private int[] rowlength = new int[1];
- private int[] skiprows = new int[1];
- private int[] skippixels = new int[1];
- private int[] alignment = new int[1];
+ private final GLPixelStorageModes psm = new GLPixelStorageModes();
- @Override
- public void setOpaque(boolean opaque) {
- if (opaque != isOpaque()) {
- if (offscreenImage != null) {
- offscreenImage.flush();
- offscreenImage = null;
+ OffscreenBackend(final AWTGLPixelBufferProvider custom) {
+ if(null == custom) {
+ pixelBufferProvider = getSingleAWTGLPixelBufferProvider();
+ } else {
+ pixelBufferProvider = custom;
+ }
+ if( pixelBufferProvider instanceof SingletonGLPixelBufferProvider ) {
+ useSingletonBuffer = true;
+ } else {
+ useSingletonBuffer = false;
}
- }
}
@Override
- public boolean preGL(Graphics g) {
- // Empty in this implementation
- return true;
- }
+ public final boolean isUsingOwnLifecycle() { return false; }
@Override
- public void postGL(Graphics g, boolean isDisplay) {
- if (isDisplay) {
- // Must now copy pixels from offscreen context into surface
- if (offscreenImage == null) {
- if (panelWidth > 0 && panelHeight > 0) {
- // It looks like NVidia's drivers (at least the ones on my
- // notebook) are buggy and don't allow a sub-rectangle to be
- // read from a pbuffer...this doesn't really matter because
- // it's the Graphics.drawImage() calls that are the
- // bottleneck
-
- int awtFormat = 0;
-
- // Should be more flexible in these BufferedImage formats;
- // perhaps see what the preferred image types are on the
- // given platform
- if (isOpaque()) {
- awtFormat = BufferedImage.TYPE_INT_RGB;
- } else {
- awtFormat = BufferedImage.TYPE_INT_ARGB;
- }
-
- offscreenImage = new BufferedImage(panelWidth,
- panelHeight,
- awtFormat);
- switch (awtFormat) {
- case BufferedImage.TYPE_3BYTE_BGR:
- glFormat = GL2.GL_BGR;
- glType = GL.GL_UNSIGNED_BYTE;
- readBackBytes = ByteBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels * 3);
- break;
-
- case BufferedImage.TYPE_INT_RGB:
- case BufferedImage.TYPE_INT_ARGB:
- glFormat = GL.GL_BGRA;
- glType = getGLPixelType();
- readBackInts = IntBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels);
- break;
-
- default:
- // FIXME: Support more off-screen image types (current
- // offscreen context implementations don't use others, and
- // some of the OpenGL formats aren't supported in the 1.1
- // headers, which we're currently using)
- throw new GLException("Unsupported offscreen image type " + awtFormat);
- }
+ public final void initialize() {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": OffscreenBackend: initialize() - frameCount "+frameCount);
+ }
+ GLException glException = null;
+ try {
+ final GLContext[] shareWith = { null };
+ if( helper.isSharedGLContextPending(shareWith) ) {
+ return; // pending ..
}
- }
-
- if (offscreenImage != null) {
- GL2 gl = getGL().getGL2();
- // Save current modes
- gl.glGetIntegerv(GL2.GL_PACK_SWAP_BYTES, swapbytes, 0);
- gl.glGetIntegerv(GL2.GL_PACK_ROW_LENGTH, rowlength, 0);
- gl.glGetIntegerv(GL2.GL_PACK_SKIP_ROWS, skiprows, 0);
- gl.glGetIntegerv(GL2.GL_PACK_SKIP_PIXELS, skippixels, 0);
- gl.glGetIntegerv(GL2.GL_PACK_ALIGNMENT, alignment, 0);
-
- gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, GL.GL_FALSE);
- gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, readBackWidthInPixels);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, 0);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, 0);
- gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 1);
-
- // Actually read the pixels.
- gl.glReadBuffer(GL2.GL_FRONT);
- if (readBackBytes != null) {
- gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackBytes);
- } else if (readBackInts != null) {
- gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackInts);
+ offscreenDrawable = factory.createOffscreenDrawable(
+ null /* default platform device */,
+ reqOffscreenCaps,
+ chooser,
+ panelWidth, panelHeight);
+ updateWrappedSurfaceScale(offscreenDrawable);
+ offscreenDrawable.setRealized(true);
+ if( DEBUG_FRAMES ) {
+ offscreenDrawable.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() {
+ @Override
+ public final void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
+ System.err.println(getThreadName()+": OffscreenBackend.swapBuffers - frameCount "+frameCount);
+ } } );
}
- // Restore saved modes.
- gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, swapbytes[0]);
- gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, rowlength[0]);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, skiprows[0]);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, skippixels[0]);
- gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, alignment[0]);
-
- if (readBackBytes != null || readBackInts != null) {
- // Copy temporary data into raster of BufferedImage for faster
- // blitting Note that we could avoid this copy in the cases
- // where !offscreenContext.offscreenImageNeedsVerticalFlip(),
- // but that's the software rendering path which is very slow
- // anyway
- Object src = null;
- Object dest = null;
- int srcIncr = 0;
- int destIncr = 0;
-
- if (readBackBytes != null) {
- src = readBackBytes.array();
- dest = ((DataBufferByte) offscreenImage.getRaster().getDataBuffer()).getData();
- srcIncr = readBackWidthInPixels * 3;
- destIncr = offscreenImage.getWidth() * 3;
- } else {
- src = readBackInts.array();
- dest = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData();
- srcIncr = readBackWidthInPixels;
- destIncr = offscreenImage.getWidth();
- }
+ //
+ // Pre context configuration
+ //
+ flipVertical = !GLJPanel.this.skipGLOrientationVerticalFlip && offscreenDrawable.isGLOriented();
+ offscreenIsFBO = offscreenDrawable.getRequestedGLCapabilities().isFBO();
+ final boolean useGLSLFlip_pre = flipVertical && offscreenIsFBO && reqOffscreenCaps.getGLProfile().isGL2ES2() && USE_GLSL_TEXTURE_RASTERIZER;
+ if( offscreenIsFBO && !useGLSLFlip_pre ) {
+ // Texture attachment only required for GLSL vertical flip, hence simply use a color-renderbuffer attachment.
+ ((GLFBODrawable)offscreenDrawable).setFBOMode(0);
+ }
- if (flipVertically()) {
- int srcPos = 0;
- int destPos = (offscreenImage.getHeight() - 1) * destIncr;
- for (; destPos >= 0; srcPos += srcIncr, destPos -= destIncr) {
- System.arraycopy(src, srcPos, dest, destPos, destIncr);
+ offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith[0]);
+ offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
+ if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
+ isInitialized = true;
+ helper.setAutoSwapBufferMode(false); // we handle swap-buffers, see handlesSwapBuffer()
+
+ final GL gl = offscreenContext.getGL();
+ // Remedy for Bug 1020, i.e. OSX/Nvidia's FBO needs to be cleared before blitting,
+ // otherwise first MSAA frame lacks antialiasing.
+ // Clearing of FBO is performed within GLFBODrawableImpl.initialize(..):
+ // gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+ final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities();
+ final boolean glslCompliant = !offscreenContext.hasRendererQuirk(GLRendererQuirks.GLSLNonCompliant);
+ final boolean useGLSLFlip = useGLSLFlip_pre && gl.isGL2ES2() && glslCompliant;
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": OffscreenBackend.initialize: useGLSLFlip "+useGLSLFlip+
+ " [flip "+flipVertical+", isFBO "+offscreenIsFBO+", isGL2ES2 "+gl.isGL2ES2()+
+ ", noglsl "+!USE_GLSL_TEXTURE_RASTERIZER+", glslNonCompliant "+!glslCompliant+
+ ", isGL2ES2 " + gl.isGL2ES2()+"\n "+offscreenDrawable+"]");
}
- } else {
- int srcPos = 0;
- int destEnd = destIncr * offscreenImage.getHeight();
- for (int destPos = 0; destPos < destEnd; srcPos += srcIncr, destPos += destIncr) {
- System.arraycopy(src, srcPos, dest, destPos, destIncr);
+ if( useGLSLFlip ) {
+ final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable;
+ fboDrawable.setTextureUnit( GLJPanel.this.requestedTextureUnit );
+ try {
+ fboFlipped = new FBObject();
+ fboFlipped.init(gl, panelWidth, panelHeight, 0);
+ fboFlipped.attachColorbuffer(gl, 0, chosenCaps.getAlphaBits()>0);
+ // fboFlipped.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT); // Bug 1020 (see above), cannot do in FBObject due to unknown 'first bind' state.
+ glslTextureRaster = new GLSLTextureRaster(fboDrawable.getTextureUnit(), true);
+ glslTextureRaster.init(gl.getGL2ES2());
+ glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, panelWidth, panelHeight);
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ if(null != glslTextureRaster) {
+ glslTextureRaster.dispose(gl.getGL2ES2());
+ glslTextureRaster = null;
+ }
+ if(null != fboFlipped) {
+ fboFlipped.destroy(gl);
+ fboFlipped = null;
+ }
+ }
+ } else {
+ fboFlipped = null;
+ glslTextureRaster = null;
}
- }
-
- // Note: image will be drawn back in paintComponent() for
- // correctness on all platforms
+ offscreenContext.release();
+ } else {
+ isInitialized = false;
+ }
+ } catch( final GLException gle ) {
+ glException = gle;
+ } finally {
+ if( !isInitialized ) {
+ if(null != offscreenContext) {
+ offscreenContext.destroy();
+ offscreenContext = null;
+ }
+ if(null != offscreenDrawable) {
+ offscreenDrawable.setRealized(false);
+ offscreenDrawable = null;
+ }
+ }
+ if( null != glException ) {
+ throw new GLException("Caught GLException: "+glException.getMessage(), glException);
}
- }
- }
- }
-
- @Override
- public void doPaintComponent(Graphics g) {
- doPaintComponentImpl();
- if (offscreenImage != null) {
- // Draw resulting image in one shot
- g.drawImage(offscreenImage, 0, 0,
- offscreenImage.getWidth(),
- offscreenImage.getHeight(),
- GLJPanel.this);
- }
- }
-
- protected abstract void doPaintComponentImpl();
- protected abstract int getGLPixelType();
- protected abstract boolean flipVertically();
- }
-
- class SoftwareBackend extends AbstractReadbackBackend {
- // Implementation using software rendering
- private GLDrawableImpl offscreenDrawable;
- private GLContextImpl offscreenContext;
-
- @Override
- public boolean isUsingOwnThreadManagment() { return false; }
-
- @Override
- public void initialize() {
- if(DEBUG) {
- System.err.println(getThreadName()+": SoftwareBackend: initialize()");
}
- // Fall-through path: create an offscreen context instead
- offscreenDrawable = (GLDrawableImpl) factory.createOffscreenDrawable(
- null /* default platform device */,
- offscreenCaps,
- chooser,
- Math.max(1, panelWidth),
- Math.max(1, panelHeight));
- offscreenDrawable.setRealized(true);
- offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith);
- offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
-
- isInitialized = true;
}
@Override
- public void destroy() {
+ public final void destroy() {
if(DEBUG) {
- System.err.println(getThreadName()+": SoftwareBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable));
+ System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable)+" - frameCount "+frameCount);
}
- if (offscreenContext != null) {
- offscreenContext.destroy();
- offscreenContext = null;
+ if ( null != offscreenContext && offscreenContext.isCreated() ) {
+ if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
+ try {
+ final GL gl = offscreenContext.getGL();
+ if(null != glslTextureRaster) {
+ glslTextureRaster.dispose(gl.getGL2ES2());
+ }
+ if(null != fboFlipped) {
+ fboFlipped.destroy(gl);
+ }
+ } finally {
+ offscreenContext.destroy();
+ }
+ }
}
+ offscreenContext = null;
+ glslTextureRaster = null;
+ fboFlipped = null;
+ offscreenContext = null;
+
if (offscreenDrawable != null) {
final AbstractGraphicsDevice adevice = offscreenDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
offscreenDrawable.setRealized(false);
@@ -1058,237 +1786,318 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
adevice.close();
}
}
- }
+ offscreenIsFBO = false;
- @Override
- public GLContext createContext(GLContext shareWith) {
- return (null != offscreenDrawable) ? offscreenDrawable.createContext(shareWith) : null;
+ if( null != readBackIntsForCPUVFlip ) {
+ readBackIntsForCPUVFlip.clear();
+ readBackIntsForCPUVFlip = null;
+ }
+ if( null != pixelBuffer ) {
+ if( !useSingletonBuffer ) {
+ pixelBuffer.dispose();
+ }
+ pixelBuffer = null;
+ }
+ alignedImage = null;
}
@Override
- public void setContext(GLContext ctx) {
- offscreenContext=(GLContextImpl)ctx;
+ public final void setOpaque(final boolean opaque) {
+ if ( opaque != isOpaque() && !useSingletonBuffer ) {
+ pixelBuffer.dispose();
+ pixelBuffer = null;
+ alignedImage = null;
+ }
}
@Override
- public GLContext getContext() {
- return offscreenContext;
+ public final boolean preGL(final Graphics g) {
+ // Empty in this implementation
+ return true;
}
@Override
- public GLDrawable getDrawable() {
- return offscreenDrawable;
+ public final boolean handlesSwapBuffer() {
+ return true;
}
@Override
- public GLCapabilitiesImmutable getChosenGLCapabilities() {
- if (offscreenDrawable == null) {
- return null;
- }
- return offscreenDrawable.getChosenGLCapabilities();
+ public final void swapBuffers() {
+ final GLDrawable d = offscreenDrawable;
+ if( null != d ) {
+ d.swapBuffers();
+ }
}
@Override
- public GLProfile getGLProfile() {
- if (offscreenDrawable == null) {
- return null;
- }
- return offscreenDrawable.getGLProfile();
- }
+ public final void postGL(final Graphics g, final boolean isDisplay) {
+ if (isDisplay) {
+ if( DEBUG_FRAMES ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: - frameCount "+frameCount);
+ }
- @Override
- public void handleReshape() {
- destroy();
- initialize();
- readBackWidthInPixels = Math.max(1, panelWidth);
- readBackHeightInPixels = Math.max(1, panelHeight);
-
- if (offscreenImage != null) {
- offscreenImage.flush();
- offscreenImage = null;
- }
- }
+ final GL gl = offscreenContext.getGL();
+
+ //
+ // Save TextureState ASAP, i.e. the user values for the used FBO texture-unit
+ // and the current active texture-unit (if not same)
+ //
+ final TextureState usrTexState, fboTexState;
+ final int fboTexUnit;
+
+ if( offscreenIsFBO ) {
+ fboTexUnit = GL.GL_TEXTURE0 + ((GLFBODrawable)offscreenDrawable).getTextureUnit();
+ usrTexState = new TextureState(gl, GL.GL_TEXTURE_2D);
+ if( fboTexUnit != usrTexState.getUnit() ) {
+ // glActiveTexture(..) + glBindTexture(..) are implicit performed in GLFBODrawableImpl's
+ // swapBuffers/contextMadeCurent -> swapFBOImpl.
+ // We need to cache the texture unit's bound texture-id before it's overwritten.
+ gl.glActiveTexture(fboTexUnit);
+ fboTexState = new TextureState(gl, fboTexUnit, GL.GL_TEXTURE_2D);
+ } else {
+ fboTexState = usrTexState;
+ }
+ } else {
+ fboTexUnit = 0;
+ usrTexState = null;
+ fboTexState = null;
+ }
- @Override
- protected void doPaintComponentImpl() {
- helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
- }
- @Override
- protected int getGLPixelType() {
- return offscreenContext.getOffscreenContextPixelDataType();
- }
+ if( autoSwapBufferMode ) {
+ // Since we only use a single-buffer non-MSAA or double-buffered MSAA offscreenDrawable,
+ // we can always swap!
+ offscreenDrawable.swapBuffers();
+ }
- @Override
- protected boolean flipVertically() {
- return offscreenContext.offscreenImageNeedsVerticalFlip();
- }
- }
+ final int componentCount;
+ final int alignment;
+ if( isOpaque() ) {
+ // w/o alpha
+ componentCount = 3;
+ alignment = 1;
+ } else {
+ // with alpha
+ componentCount = 4;
+ alignment = 4;
+ }
- class PbufferBackend extends AbstractReadbackBackend {
- private GLPbuffer pbuffer;
- private int pbufferWidth = 256;
- private int pbufferHeight = 256;
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
- @Override
- public boolean isUsingOwnThreadManagment() { return false; }
+ if( useSingletonBuffer ) { // attempt to fetch the latest AWTGLPixelBuffer
+ pixelBuffer = (AWTGLPixelBuffer) ((SingletonGLPixelBufferProvider)pixelBufferProvider).getSingleBuffer(pixelAttribs);
+ }
+ if( null != pixelBuffer && pixelBuffer.requiresNewBuffer(gl, panelWidth, panelHeight, 0) ) {
+ pixelBuffer.dispose();
+ pixelBuffer = null;
+ alignedImage = null;
+ }
+ if ( null == pixelBuffer ) {
+ if (0 >= panelWidth || 0 >= panelHeight ) {
+ return;
+ }
+ pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, panelWidth, panelHeight, 1, true, 0);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" pixelBufferProvider isSingletonBufferProvider "+useSingletonBuffer+", 0x"+Integer.toHexString(pixelBufferProvider.hashCode())+", "+pixelBufferProvider.getClass().getSimpleName());
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" pixelBuffer 0x"+Integer.toHexString(pixelBuffer.hashCode())+", "+pixelBuffer+", alignment "+alignment);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" flippedVertical "+flipVertical+", glslTextureRaster "+(null!=glslTextureRaster));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" panelSize "+panelWidth+"x"+panelHeight+" @ scale "+getPixelScaleStr());
+ }
+ }
+ if( offscreenDrawable.getSurfaceWidth() != panelWidth || offscreenDrawable.getSurfaceHeight() != panelHeight ) {
+ throw new InternalError("OffscreenDrawable panelSize mismatch (reshape missed): panelSize "+panelWidth+"x"+panelHeight+" != drawable "+offscreenDrawable.getSurfaceWidth()+"x"+offscreenDrawable.getSurfaceHeight()+", on thread "+getThreadName());
+ }
+ if( null == alignedImage ||
+ panelWidth != alignedImage.getWidth() || panelHeight != alignedImage.getHeight() ||
+ !pixelBuffer.isDataBufferSource(alignedImage) ) {
+ alignedImage = pixelBuffer.getAlignedImage(panelWidth, panelHeight);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" new alignedImage "+alignedImage.getWidth()+"x"+alignedImage.getHeight()+" @ scale "+getPixelScaleStr()+", "+alignedImage+", pixelBuffer "+pixelBuffer.width+"x"+pixelBuffer.height+", "+pixelBuffer);
+ }
+ }
+ final IntBuffer readBackInts;
- @Override
- public void initialize() {
- if (pbuffer != null) {
- throw new InternalError("Creating pbuffer twice without destroying it (memory leak / correctness bug)");
- }
- if(DEBUG) {
- System.err.println(getThreadName()+": PbufferBackend: initialize()");
- }
- try {
- pbuffer = factory.createGLPbuffer(null /* default platform device */,
- offscreenCaps,
- null,
- pbufferWidth,
- pbufferHeight,
- shareWith);
- pbuffer.setContextCreationFlags(additionalCtxCreationFlags);
- pbuffer.addGLEventListener(updater);
- isInitialized = true;
- } catch (GLException e) {
- if (DEBUG) {
- e.printStackTrace();
- System.err.println(getThreadName()+": GLJPanel: Falling back on software rendering because of problems creating pbuffer");
+ if( !flipVertical || null != glslTextureRaster ) {
+ readBackInts = (IntBuffer) pixelBuffer.buffer;
+ } else {
+ if( null == readBackIntsForCPUVFlip || pixelBuffer.width * pixelBuffer.height > readBackIntsForCPUVFlip.remaining() ) {
+ readBackIntsForCPUVFlip = IntBuffer.allocate(pixelBuffer.width * pixelBuffer.height);
+ }
+ readBackInts = readBackIntsForCPUVFlip;
}
- hardwareAccelerationDisabled = true;
- backend = null;
- isInitialized = false;
- createAndInitializeBackend();
- }
- }
- @Override
- public void destroy() {
- if(DEBUG) {
- System.err.println(getThreadName()+": PbufferBackend: destroy() - pbuffer: "+(null!=pbuffer));
- }
- if (pbuffer != null) {
- pbuffer.destroy();
- pbuffer = null;
+ // Must now copy pixels from offscreen context into surface
+ if( DEBUG_FRAMES ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.readPixels: - frameCount "+frameCount);
+ }
+
+ // Save PACK modes, reset them to defaults and set alignment
+ psm.setPackAlignment(gl, alignment);
+ if( gl.isGL2ES3() ) {
+ final GL2ES3 gl2es3 = gl.getGL2ES3();
+ psm.setPackRowLength(gl2es3, panelWidth);
+ gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
+ }
+
+ if(null != glslTextureRaster) { // implies flippedVertical
+ final boolean viewportChange;
+ final int[] usrViewport = new int[] { 0, 0, 0, 0 };
+ gl.glGetIntegerv(GL.GL_VIEWPORT, usrViewport, 0);
+ viewportChange = 0 != usrViewport[0] || 0 != usrViewport[1] ||
+ panelWidth != usrViewport[2] || panelHeight != usrViewport[3];
+ if( DEBUG_VIEWPORT ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL: "+GLJPanel.this.getName()+" Viewport: change "+viewportChange+
+ ", "+usrViewport[0]+"/"+usrViewport[1]+" "+usrViewport[2]+"x"+usrViewport[3]+
+ " -> 0/0 "+panelWidth+"x"+panelHeight);
+ }
+ if( viewportChange ) {
+ gl.glViewport(0, 0, panelWidth, panelHeight);
+ }
+
+ // perform vert-flipping via OpenGL/FBO
+ final GLFBODrawable fboDrawable = (GLFBODrawable)offscreenDrawable;
+ final FBObject.TextureAttachment fboTex = fboDrawable.getColorbuffer(GL.GL_FRONT).getTextureAttachment();
+
+ fboFlipped.bind(gl);
+
+ // gl.glActiveTexture(GL.GL_TEXTURE0 + fboDrawable.getTextureUnit()); // implicit by GLFBODrawableImpl: swapBuffers/contextMadeCurent -> swapFBOImpl
+ gl.glBindTexture(GL.GL_TEXTURE_2D, fboTex.getName());
+ // gl.glClear(GL.GL_DEPTH_BUFFER_BIT); // fboFlipped runs w/o DEPTH!
+
+ glslTextureRaster.display(gl.getGL2ES2());
+ gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
+
+ fboFlipped.unbind(gl);
+ if( viewportChange ) {
+ gl.glViewport(usrViewport[0], usrViewport[1], usrViewport[2], usrViewport[3]);
+ }
+ } else {
+ gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
+
+ if ( flipVertical ) {
+ // Copy temporary data into raster of BufferedImage for faster
+ // blitting Note that we could avoid this copy in the cases
+ // where !offscreenDrawable.isGLOriented(),
+ // but that's the software rendering path which is very slow anyway.
+ final BufferedImage image = alignedImage;
+ final int[] src = readBackInts.array();
+ final int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+ final int incr = panelWidth;
+ int srcPos = 0;
+ int destPos = (panelHeight - 1) * panelWidth;
+ for (; destPos >= 0; srcPos += incr, destPos -= incr) {
+ System.arraycopy(src, srcPos, dest, destPos, incr);
+ }
+ }
+ }
+ if( 0 != fboTexUnit ) { // implies offscreenIsFBO
+ fboTexState.restore(gl);
+ if( fboTexUnit != usrTexState.getUnit() ) {
+ usrTexState.restore(gl);
+ }
+ }
+
+ // Restore saved modes.
+ psm.restore(gl);
+
+ // Note: image will be drawn back in paintComponent() for
+ // correctness on all platforms
}
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return (null != pbuffer) ? pbuffer.createContext(shareWith) : null;
+ public final int getTextureUnit() {
+ if(null != glslTextureRaster && null != offscreenDrawable) { // implies flippedVertical
+ return ((GLFBODrawable)offscreenDrawable).getTextureUnit();
+ }
+ return -1;
}
@Override
- public void setContext(GLContext ctx) {
- if (pbuffer == null || Beans.isDesignTime()) {
- return;
+ public final void doPaintComponent(final Graphics g) {
+ helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
+
+ if ( null != alignedImage ) {
+ if( DEBUG_FRAMES ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.doPaintComponent.drawImage: - frameCount "+frameCount);
+ }
+ // Draw resulting image in one shot
+ g.drawImage(alignedImage, 0, 0, alignedImage.getWidth()/hasPixelScale[0], alignedImage.getHeight()/hasPixelScale[1], null); // Null ImageObserver since image data is ready.
}
- pbuffer.setContext(ctx);
+ frameCount++;
}
@Override
- public GLContext getContext() {
- // Workaround for crashes in NetBeans GUI builder
- if (null == pbuffer || Beans.isDesignTime()) {
- return null;
- }
- return pbuffer.getContext();
+ public final void doPlainPaint() {
+ helper.invokeGL(offscreenDrawable, offscreenContext, updaterPlainDisplayAction, updaterInitAction);
}
@Override
- public GLDrawable getDrawable() {
- return pbuffer;
+ public final boolean handleReshape() {
+ GLDrawableImpl _drawable = (GLDrawableImpl)offscreenDrawable;
+ {
+ final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, offscreenContext, panelWidth, panelHeight);
+ if(_drawable != _drawableNew) {
+ // write back
+ _drawable = _drawableNew;
+ offscreenDrawable = _drawableNew;
+ updateWrappedSurfaceScale(offscreenDrawable);
+ }
+ }
+ if (DEBUG) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.handleReshape: " +panelWidth+"x"+panelHeight + " @ scale "+getPixelScaleStr() + " -> " + _drawable.getSurfaceWidth()+"x"+_drawable.getSurfaceHeight());
+ }
+ panelWidth = _drawable.getSurfaceWidth();
+ panelHeight = _drawable.getSurfaceHeight();
+
+ if( null != glslTextureRaster ) {
+ if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
+ try {
+ final GL gl = offscreenContext.getGL();
+ fboFlipped.reset(gl, panelWidth, panelHeight, 0);
+ glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, panelWidth, panelHeight);
+ } finally {
+ offscreenContext.release();
+ }
+ }
+ }
+ return _drawable.isRealized();
}
@Override
- public GLCapabilitiesImmutable getChosenGLCapabilities() {
- if (pbuffer == null) {
- return null;
- }
- return pbuffer.getChosenGLCapabilities();
+ public final GLContext createContext(final GLContext shareWith) {
+ return (null != offscreenDrawable) ? offscreenDrawable.createContext(shareWith) : null;
}
@Override
- public GLProfile getGLProfile() {
- if (pbuffer == null) {
- return null;
- }
- return pbuffer.getGLProfile();
+ public final void setContext(final GLContext ctx) {
+ offscreenContext=(GLContextImpl)ctx;
}
@Override
- public void handleReshape() {
- // Use factor larger than 2 during shrinks for some hysteresis
- float shrinkFactor = 2.5f;
- if ((panelWidth > pbufferWidth) || (panelHeight > pbufferHeight) ||
- (panelWidth < (pbufferWidth / shrinkFactor)) || (panelHeight < (pbufferHeight / shrinkFactor))) {
- if (DEBUG) {
- System.err.println(getThreadName()+": Resizing pbuffer from (" + pbufferWidth + ", " + pbufferHeight + ") " +
- " to fit (" + panelWidth + ", " + panelHeight + ")");
- }
- // Must destroy and recreate pbuffer to fit
- if (pbuffer != null) {
- // Watch for errors during pbuffer destruction (due to
- // buggy / bad OpenGL drivers, in particular SiS) and fall
- // back to software rendering
- try {
- pbuffer.destroy();
- } catch (GLException e) {
- hardwareAccelerationDisabled = true;
- backend = null;
- isInitialized = false;
- // Just disabled hardware acceleration during this resize operation; do a fixup
- readBackWidthInPixels = Math.max(1, panelWidth);
- readBackHeightInPixels = Math.max(1, panelHeight);
- if (DEBUG) {
- System.err.println(getThreadName()+": Warning: falling back to software rendering due to bugs in OpenGL drivers");
- e.printStackTrace();
- }
- createAndInitializeBackend();
- return;
- }
- }
- pbuffer = null;
- isInitialized = false;
- pbufferWidth = getNextPowerOf2(panelWidth);
- pbufferHeight = getNextPowerOf2(panelHeight);
- if (DEBUG && !hardwareAccelerationDisabled) {
- System.err.println(getThreadName()+": New pbuffer size is (" + pbufferWidth + ", " + pbufferHeight + ")");
- }
- initialize();
- }
-
- // It looks like NVidia's drivers (at least the ones on my
- // notebook) are buggy and don't allow a rectangle of less than
- // the pbuffer's width to be read...this doesn't really matter
- // because it's the Graphics.drawImage() calls that are the
- // bottleneck. Should probably make the size of the offscreen
- // image be the exact size of the pbuffer to save some work on
- // resize operations...
- readBackWidthInPixels = pbufferWidth;
- readBackHeightInPixels = panelHeight;
-
- if (offscreenImage != null) {
- offscreenImage.flush();
- offscreenImage = null;
- }
+ public final GLContext getContext() {
+ return offscreenContext;
}
@Override
- protected void doPaintComponentImpl() {
- pbuffer.display();
+ public final GLDrawable getDrawable() {
+ return offscreenDrawable;
}
@Override
- protected int getGLPixelType() {
- // This seems to be a good choice on all platforms
- return GL2.GL_UNSIGNED_INT_8_8_8_8_REV;
+ public final GLCapabilitiesImmutable getChosenGLCapabilities() {
+ if (offscreenDrawable == null) {
+ return null;
+ }
+ return offscreenDrawable.getChosenGLCapabilities();
}
@Override
- protected boolean flipVertically() {
- return true;
+ public final GLProfile getGLProfile() {
+ if (offscreenDrawable == null) {
+ return null;
+ }
+ return offscreenDrawable.getGLProfile();
}
}
@@ -1308,11 +2117,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private GLContext joglContext;
// State captured from Java2D OpenGL context necessary in order to
// properly render into Java2D back buffer
- private int[] drawBuffer = new int[1];
- private int[] readBuffer = new int[1];
+ private final int[] drawBuffer = new int[1];
+ private final int[] readBuffer = new int[1];
// This is required when the FBO option of the Java2D / OpenGL
// pipeline is active
- private int[] frameBuffer = new int[1];
+ private final int[] frameBuffer = new int[1];
// Current (as of this writing) NVidia drivers have a couple of bugs
// relating to the sharing of framebuffer and renderbuffer objects
// between contexts. It appears we have to (a) reattach the color
@@ -1342,10 +2151,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private GraphicsConfiguration workaroundConfig;
@Override
- public boolean isUsingOwnThreadManagment() { return true; }
+ public final boolean isUsingOwnLifecycle() { return true; }
@Override
- public void initialize() {
+ public final void initialize() {
if(DEBUG) {
System.err.println(getThreadName()+": J2DOGL: initialize()");
}
@@ -1354,7 +2163,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void destroy() {
+ public final void destroy() {
Java2D.invokeWithOGLContextCurrent(null, new Runnable() {
@Override
public void run() {
@@ -1375,12 +2184,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void setOpaque(boolean opaque) {
+ public final void setOpaque(final boolean opaque) {
// Empty in this implementation
}
@Override
- public GLContext createContext(GLContext shareWith) {
+ public final GLContext createContext(final GLContext shareWith) {
if(null != shareWith) {
throw new GLException("J2DOGLBackend cannot create context w/ additional shared context, since it already needs to share the context w/ J2D.");
}
@@ -1388,43 +2197,47 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void setContext(GLContext ctx) {
+ public final void setContext(final GLContext ctx) {
joglContext=ctx;
}
@Override
- public GLContext getContext() {
+ public final GLContext getContext() {
return joglContext;
}
@Override
- public GLDrawable getDrawable() {
+ public final GLDrawable getDrawable() {
return joglDrawable;
}
@Override
- public GLCapabilitiesImmutable getChosenGLCapabilities() {
- // FIXME: should do better than this; is it possible to using only platform-independent code?
+ public final int getTextureUnit() { return -1; }
+
+ @Override
+ public final GLCapabilitiesImmutable getChosenGLCapabilities() {
+ // FIXME: should do better than this; is it possible to query J2D Caps ?
return new GLCapabilities(null);
}
@Override
- public GLProfile getGLProfile() {
- // FIXME: should do better than this; is it possible to using only platform-independent code?
+ public final GLProfile getGLProfile() {
+ // FIXME: should do better than this; is it possible to query J2D's Profile ?
return GLProfile.getDefault(GLProfile.getDefaultDevice());
}
@Override
- public void handleReshape() {
+ public final boolean handleReshape() {
// Empty in this implementation
+ return true;
}
@Override
- public boolean preGL(Graphics g) {
- GL2 gl = joglContext.getGL().getGL2();
+ public final boolean preGL(final Graphics g) {
+ final GL2 gl = joglContext.getGL().getGL2();
// Set up needed state in JOGL context from Java2D context
- gl.glEnable(GL2.GL_SCISSOR_TEST);
- Rectangle r = Java2D.getOGLScissorBox(g);
+ gl.glEnable(GL.GL_SCISSOR_TEST);
+ final Rectangle r = Java2D.getOGLScissorBox(g);
if (r == null) {
if (DEBUG) {
@@ -1437,7 +2250,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
gl.glScissor(r.x, r.y, r.width, r.height);
- Rectangle oglViewport = Java2D.getOGLViewport(g, panelWidth, panelHeight);
+ final Rectangle oglViewport = Java2D.getOGLViewport(g, panelWidth, panelHeight);
// If the viewport X or Y changes, in addition to the panel's
// width or height, we need to send a reshape operation to the
// client
@@ -1462,13 +2275,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// The texture target for Java2D's OpenGL pipeline when using FBOs
// -- either GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB
- int fboTextureTarget = Java2D.getOGLTextureType(g);
+ final int fboTextureTarget = Java2D.getOGLTextureType(g);
if (!checkedForFBObjectWorkarounds) {
checkedForFBObjectWorkarounds = true;
gl.glBindTexture(fboTextureTarget, 0);
- gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBuffer[0]);
- int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
+ gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, frameBuffer[0]);
+ final int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
if (status != GL.GL_FRAMEBUFFER_COMPLETE) {
// Need to do workarounds
fbObjectWorkarounds = true;
@@ -1498,10 +2311,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
gl.glBindTexture(fboTextureTarget, frameBufferTexture[0]);
- int[] width = new int[1];
- int[] height = new int[1];
- gl.glGetTexLevelParameteriv(fboTextureTarget, 0, GL2.GL_TEXTURE_WIDTH, width, 0);
- gl.glGetTexLevelParameteriv(fboTextureTarget, 0, GL2.GL_TEXTURE_HEIGHT, height, 0);
+ final int[] width = new int[1];
+ final int[] height = new int[1];
+ gl.glGetTexLevelParameteriv(fboTextureTarget, 0, GL2GL3.GL_TEXTURE_WIDTH, width, 0);
+ gl.glGetTexLevelParameteriv(fboTextureTarget, 0, GL2GL3.GL_TEXTURE_HEIGHT, height, 0);
gl.glGenRenderbuffers(1, frameBufferDepthBuffer, 0);
if (DEBUG) {
@@ -1511,9 +2324,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, frameBufferDepthBuffer[0]);
// FIXME: may need a loop here like in Java2D
- gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL2GL3.GL_DEPTH_COMPONENT24, width[0], height[0]);
+ gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT24, width[0], height[0]);
- gl.glBindRenderbuffer(GL2.GL_RENDERBUFFER, 0);
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0);
createNewDepthBuffer = false;
}
@@ -1537,7 +2350,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
if (DEBUG) {
- int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
+ final int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
if (status != GL.GL_FRAMEBUFFER_COMPLETE) {
throw new GLException("Error: framebuffer was incomplete: status = 0x" +
Integer.toHexString(status));
@@ -1557,11 +2370,24 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void postGL(Graphics g, boolean isDisplay) {
+ public final boolean handlesSwapBuffer() {
+ return false;
+ }
+
+ @Override
+ public final void swapBuffers() {
+ final GLDrawable d = joglDrawable;
+ if( null != d ) {
+ d.swapBuffers();
+ }
+ }
+
+ @Override
+ public final void postGL(final Graphics g, final boolean isDisplay) {
// Cause OpenGL pipeline to flush its results because
// otherwise it's possible we will buffer up multiple frames'
// rendering results, resulting in apparent mouse lag
- GL gl = getGL();
+ final GL gl = joglContext.getGL();
gl.glFinish();
if (Java2D.isFBOEnabled() &&
@@ -1574,7 +2400,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void doPaintComponent(final Graphics g) {
+ public final void doPaintComponent(final Graphics g) {
// This is a workaround for an issue in the Java 2D / JOGL
// bridge (reported by an end user as JOGL Issue 274) where Java
// 2D can occasionally leave its internal OpenGL context current
@@ -1625,34 +2451,34 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// FIXME: add more checks?
j2dContext.makeCurrent();
- GL gl = j2dContext.getGL();
- if ((getGLInteger(gl, GL.GL_RED_BITS) < offscreenCaps.getRedBits()) ||
- (getGLInteger(gl, GL.GL_GREEN_BITS) < offscreenCaps.getGreenBits()) ||
- (getGLInteger(gl, GL.GL_BLUE_BITS) < offscreenCaps.getBlueBits()) ||
+ final GL gl = j2dContext.getGL();
+ if ((getGLInteger(gl, GL.GL_RED_BITS) < reqOffscreenCaps.getRedBits()) ||
+ (getGLInteger(gl, GL.GL_GREEN_BITS) < reqOffscreenCaps.getGreenBits()) ||
+ (getGLInteger(gl, GL.GL_BLUE_BITS) < reqOffscreenCaps.getBlueBits()) ||
// (getGLInteger(gl, GL.GL_ALPHA_BITS) < offscreenCaps.getAlphaBits()) ||
- (getGLInteger(gl, GL2.GL_ACCUM_RED_BITS) < offscreenCaps.getAccumRedBits()) ||
- (getGLInteger(gl, GL2.GL_ACCUM_GREEN_BITS) < offscreenCaps.getAccumGreenBits()) ||
- (getGLInteger(gl, GL2.GL_ACCUM_BLUE_BITS) < offscreenCaps.getAccumBlueBits()) ||
- (getGLInteger(gl, GL2.GL_ACCUM_ALPHA_BITS) < offscreenCaps.getAccumAlphaBits()) ||
+ (getGLInteger(gl, GL2.GL_ACCUM_RED_BITS) < reqOffscreenCaps.getAccumRedBits()) ||
+ (getGLInteger(gl, GL2.GL_ACCUM_GREEN_BITS) < reqOffscreenCaps.getAccumGreenBits()) ||
+ (getGLInteger(gl, GL2.GL_ACCUM_BLUE_BITS) < reqOffscreenCaps.getAccumBlueBits()) ||
+ (getGLInteger(gl, GL2.GL_ACCUM_ALPHA_BITS) < reqOffscreenCaps.getAccumAlphaBits()) ||
// (getGLInteger(gl, GL2.GL_DEPTH_BITS) < offscreenCaps.getDepthBits()) ||
- (getGLInteger(gl, GL.GL_STENCIL_BITS) < offscreenCaps.getStencilBits())) {
+ (getGLInteger(gl, GL.GL_STENCIL_BITS) < reqOffscreenCaps.getStencilBits())) {
if (DEBUG) {
System.err.println(getThreadName()+": GLJPanel: Falling back to pbuffer-based support because Java2D context insufficient");
System.err.println(" Available Required");
- System.err.println("GL_RED_BITS " + getGLInteger(gl, GL.GL_RED_BITS) + " " + offscreenCaps.getRedBits());
- System.err.println("GL_GREEN_BITS " + getGLInteger(gl, GL.GL_GREEN_BITS) + " " + offscreenCaps.getGreenBits());
- System.err.println("GL_BLUE_BITS " + getGLInteger(gl, GL.GL_BLUE_BITS) + " " + offscreenCaps.getBlueBits());
- System.err.println("GL_ALPHA_BITS " + getGLInteger(gl, GL.GL_ALPHA_BITS) + " " + offscreenCaps.getAlphaBits());
- System.err.println("GL_ACCUM_RED_BITS " + getGLInteger(gl, GL2.GL_ACCUM_RED_BITS) + " " + offscreenCaps.getAccumRedBits());
- System.err.println("GL_ACCUM_GREEN_BITS " + getGLInteger(gl, GL2.GL_ACCUM_GREEN_BITS) + " " + offscreenCaps.getAccumGreenBits());
- System.err.println("GL_ACCUM_BLUE_BITS " + getGLInteger(gl, GL2.GL_ACCUM_BLUE_BITS) + " " + offscreenCaps.getAccumBlueBits());
- System.err.println("GL_ACCUM_ALPHA_BITS " + getGLInteger(gl, GL2.GL_ACCUM_ALPHA_BITS) + " " + offscreenCaps.getAccumAlphaBits());
- System.err.println("GL_DEPTH_BITS " + getGLInteger(gl, GL.GL_DEPTH_BITS) + " " + offscreenCaps.getDepthBits());
- System.err.println("GL_STENCIL_BITS " + getGLInteger(gl, GL.GL_STENCIL_BITS) + " " + offscreenCaps.getStencilBits());
+ System.err.println("GL_RED_BITS " + getGLInteger(gl, GL.GL_RED_BITS) + " " + reqOffscreenCaps.getRedBits());
+ System.err.println("GL_GREEN_BITS " + getGLInteger(gl, GL.GL_GREEN_BITS) + " " + reqOffscreenCaps.getGreenBits());
+ System.err.println("GL_BLUE_BITS " + getGLInteger(gl, GL.GL_BLUE_BITS) + " " + reqOffscreenCaps.getBlueBits());
+ System.err.println("GL_ALPHA_BITS " + getGLInteger(gl, GL.GL_ALPHA_BITS) + " " + reqOffscreenCaps.getAlphaBits());
+ System.err.println("GL_ACCUM_RED_BITS " + getGLInteger(gl, GL2.GL_ACCUM_RED_BITS) + " " + reqOffscreenCaps.getAccumRedBits());
+ System.err.println("GL_ACCUM_GREEN_BITS " + getGLInteger(gl, GL2.GL_ACCUM_GREEN_BITS) + " " + reqOffscreenCaps.getAccumGreenBits());
+ System.err.println("GL_ACCUM_BLUE_BITS " + getGLInteger(gl, GL2.GL_ACCUM_BLUE_BITS) + " " + reqOffscreenCaps.getAccumBlueBits());
+ System.err.println("GL_ACCUM_ALPHA_BITS " + getGLInteger(gl, GL2.GL_ACCUM_ALPHA_BITS) + " " + reqOffscreenCaps.getAccumAlphaBits());
+ System.err.println("GL_DEPTH_BITS " + getGLInteger(gl, GL.GL_DEPTH_BITS) + " " + reqOffscreenCaps.getDepthBits());
+ System.err.println("GL_STENCIL_BITS " + getGLInteger(gl, GL.GL_STENCIL_BITS) + " " + reqOffscreenCaps.getStencilBits());
}
isInitialized = false;
backend = null;
- oglPipelineEnabled = false;
+ java2DGLPipelineOK = false;
handleReshape = true;
j2dContext.destroy();
j2dContext = null;
@@ -1663,7 +2489,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
try {
captureJ2DState(j2dContext.getGL(), g);
- Object curSurface = Java2D.getOGLSurfaceIdentifier(g);
+ final Object curSurface = Java2D.getOGLSurfaceIdentifier(g);
if (curSurface != null) {
if (j2dSurface != curSurface) {
if (joglContext != null) {
@@ -1679,7 +2505,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
j2dSurface = curSurface;
if (DEBUG) {
System.err.print(getThreadName()+": Surface type: ");
- int surfaceType = Java2D.getOGLSurfaceType(g);
+ final int surfaceType = Java2D.getOGLSurfaceType(g);
if (surfaceType == Java2D.UNDEFINED) {
System.err.println("UNDEFINED");
} else if (surfaceType == Java2D.WINDOW) {
@@ -1698,7 +2524,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
}
if (joglContext == null) {
- AbstractGraphicsDevice device = j2dContext.getGLDrawable().getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+ final AbstractGraphicsDevice device = j2dContext.getGLDrawable().getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
if (factory.canCreateExternalGLDrawable(device)) {
joglDrawable = factory.createExternalGLDrawable();
joglContext = joglDrawable.createContext(j2dContext);
@@ -1706,28 +2532,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
System.err.println("-- Created External Drawable: "+joglDrawable);
System.err.println("-- Created Context: "+joglContext);
}
- } else if (factory.canCreateContextOnJava2DSurface(device)) {
- // Mac OS X code path
- joglContext = factory.createContextOnJava2DSurface(g, j2dContext);
- if (DEBUG) {
- System.err.println("-- Created Context: "+joglContext);
- }
}
- /*if (DEBUG) {
- joglContext.setGL(new DebugGL2(joglContext.getGL().getGL2()));
- }*/
-
if (Java2D.isFBOEnabled() &&
Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT &&
fbObjectWorkarounds) {
createNewDepthBuffer = true;
}
}
- if (joglContext instanceof Java2DGLContext) {
- // Mac OS X code path
- ((Java2DGLContext) joglContext).setGraphics(g);
- }
-
helper.invokeGL(joglDrawable, joglContext, updaterDisplayAction, updaterInitAction);
}
} finally {
@@ -1737,9 +2548,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
});
}
- private void captureJ2DState(GL gl, Graphics g) {
- gl.glGetIntegerv(GL2.GL_DRAW_BUFFER, drawBuffer, 0);
- gl.glGetIntegerv(GL2.GL_READ_BUFFER, readBuffer, 0);
+ @Override
+ public final void doPlainPaint() {
+ helper.invokeGL(joglDrawable, joglContext, updaterPlainDisplayAction, updaterInitAction);
+ }
+
+ private final void captureJ2DState(final GL gl, final Graphics g) {
+ gl.glGetIntegerv(GL2GL3.GL_DRAW_BUFFER, drawBuffer, 0);
+ gl.glGetIntegerv(GL2ES3.GL_READ_BUFFER, readBuffer, 0);
if (Java2D.isFBOEnabled() &&
Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT) {
gl.glGetIntegerv(GL.GL_FRAMEBUFFER_BINDING, frameBuffer, 0);
@@ -1773,7 +2589,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
if (!checkedGLVendor) {
checkedGLVendor = true;
- String vendor = gl.glGetString(GL.GL_VENDOR);
+ final String vendor = gl.glGetString(GL.GL_VENDOR);
if ((vendor != null) &&
vendor.startsWith("ATI")) {
diff --git a/src/jogl/classes/javax/media/opengl/fixedfunc/GLMatrixFunc.java b/src/jogl/classes/javax/media/opengl/fixedfunc/GLMatrixFunc.java
index a34d490c0..87a23d12a 100644
--- a/src/jogl/classes/javax/media/opengl/fixedfunc/GLMatrixFunc.java
+++ b/src/jogl/classes/javax/media/opengl/fixedfunc/GLMatrixFunc.java
@@ -31,69 +31,122 @@ package javax.media.opengl.fixedfunc;
import java.nio.*;
+import javax.media.opengl.GL;
+
+/**
+ * Subset of OpenGL fixed function pipeline's matrix operations.
+ */
public interface GLMatrixFunc {
- public static final int GL_MATRIX_MODE = 0x0BA0;
- public static final int GL_MODELVIEW = 0x1700;
- public static final int GL_PROJECTION = 0x1701;
- // public static final int GL_TEXTURE = 0x1702; // Use GL.GL_TEXTURE due to ambiguous GL usage
- public static final int GL_MODELVIEW_MATRIX = 0x0BA6;
- public static final int GL_PROJECTION_MATRIX = 0x0BA7;
- public static final int GL_TEXTURE_MATRIX = 0x0BA8;
-
- /**
- * glGetFloatv
- * @param pname GL_MODELVIEW_MATRIX, GL_PROJECTION_MATRIX or GL_TEXTURE_MATRIX
- * @param params the FloatBuffer's position remains unchanged,
- * which is the same behavior than the native JOGL GL impl
- */
- public void glGetFloatv(int pname, java.nio.FloatBuffer params);
- public void glGetFloatv(int pname, float[] params, int params_offset);
- /**
- * glGetIntegerv
- * @param pname GL_MATRIX_MODE
- * @param params the FloatBuffer's position remains unchanged
- * which is the same behavior than the native JOGL GL impl
- */
- public void glGetIntegerv(int pname, IntBuffer params);
- public void glGetIntegerv(int pname, int[] params, int params_offset);
-
- /**
- * sets the current matrix
- * @param pname GL_MODELVIEW, GL_PROJECTION or GL.GL_TEXTURE
- */
- public void glMatrixMode(int mode) ;
-
- public void glPushMatrix();
- public void glPopMatrix();
-
- public void glLoadIdentity() ;
-
- /**
- * glLoadMatrixf
- * @param params the FloatBuffer's position remains unchanged,
- * which is the same behavior than the native JOGL GL impl
- */
- public void glLoadMatrixf(java.nio.FloatBuffer m) ;
- public void glLoadMatrixf(float[] m, int m_offset);
-
- /**
- * glMultMatrixf
- * @param m the FloatBuffer's position remains unchanged,
- * which is the same behavior than the native JOGL GL impl
- */
- public void glMultMatrixf(java.nio.FloatBuffer m) ;
- public void glMultMatrixf(float[] m, int m_offset);
-
- public void glTranslatef(float x, float y, float z) ;
-
- public void glRotatef(float angle, float x, float y, float z);
-
- public void glScalef(float x, float y, float z) ;
-
- public void glOrthof(float left, float right, float bottom, float top, float zNear, float zFar) ;
-
- public void glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar);
+ public static final int GL_MATRIX_MODE = 0x0BA0;
+ /** Matrix mode modelview */
+ public static final int GL_MODELVIEW = 0x1700;
+ /** Matrix mode projection */
+ public static final int GL_PROJECTION = 0x1701;
+ // public static final int GL_TEXTURE = 0x1702; // Use GL.GL_TEXTURE due to ambiguous GL usage
+ /** Matrix access name for modelview */
+ public static final int GL_MODELVIEW_MATRIX = 0x0BA6;
+ /** Matrix access name for projection */
+ public static final int GL_PROJECTION_MATRIX = 0x0BA7;
+ /** Matrix access name for texture */
+ public static final int GL_TEXTURE_MATRIX = 0x0BA8;
+
+ /**
+ * Copy the named matrix into the given storage.
+ * @param pname {@link #GL_MODELVIEW_MATRIX}, {@link #GL_PROJECTION_MATRIX} or {@link #GL_TEXTURE_MATRIX}
+ * @param params the FloatBuffer's position remains unchanged,
+ * which is the same behavior than the native JOGL GL impl
+ */
+ public void glGetFloatv(int pname, java.nio.FloatBuffer params);
+
+ /**
+ * Copy the named matrix to the given storage at offset.
+ * @param pname {@link #GL_MODELVIEW_MATRIX}, {@link #GL_PROJECTION_MATRIX} or {@link #GL_TEXTURE_MATRIX}
+ * @param params storage
+ * @param params_offset storage offset
+ */
+ public void glGetFloatv(int pname, float[] params, int params_offset);
+
+ /**
+ * glGetIntegerv
+ * @param pname {@link #GL_MATRIX_MODE} to receive the current matrix mode
+ * @param params the FloatBuffer's position remains unchanged
+ * which is the same behavior than the native JOGL GL impl
+ */
+ public void glGetIntegerv(int pname, IntBuffer params);
+ public void glGetIntegerv(int pname, int[] params, int params_offset);
+
+ /**
+ * Sets the current matrix mode.
+ * @param mode {@link #GL_MODELVIEW}, {@link #GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}.
+ */
+ public void glMatrixMode(int mode) ;
+
+ /**
+ * Push the current matrix to it's stack, while preserving it's values.
+ * <p>
+ * There exist one stack per matrix mode, i.e. {@link #GL_MODELVIEW}, {@link #GL_PROJECTION} and {@link GL#GL_TEXTURE GL_TEXTURE}.
+ * </p>
+ */
+ public void glPushMatrix();
+
+ /**
+ * Pop the current matrix from it's stack.
+ * @see #glPushMatrix()
+ */
+ public void glPopMatrix();
+
+ /**
+ * Load the current matrix with the identity matrix
+ */
+ public void glLoadIdentity() ;
+
+ /**
+ * Load the current matrix w/ the provided one.
+ * @param params the FloatBuffer's position remains unchanged,
+ * which is the same behavior than the native JOGL GL impl
+ */
+ public void glLoadMatrixf(java.nio.FloatBuffer m) ;
+ /**
+ * Load the current matrix w/ the provided one.
+ */
+ public void glLoadMatrixf(float[] m, int m_offset);
+
+ /**
+ * Multiply the current matrix: [c] = [c] x [m]
+ * @param m the FloatBuffer's position remains unchanged,
+ * which is the same behavior than the native JOGL GL impl
+ */
+ public void glMultMatrixf(java.nio.FloatBuffer m) ;
+ /**
+ * Multiply the current matrix: [c] = [c] x [m]
+ */
+ public void glMultMatrixf(float[] m, int m_offset);
+
+ /**
+ * Translate the current matrix.
+ */
+ public void glTranslatef(float x, float y, float z) ;
+
+ /**
+ * Rotate the current matrix.
+ */
+ public void glRotatef(float angle, float x, float y, float z);
+
+ /**
+ * Scale the current matrix.
+ */
+ public void glScalef(float x, float y, float z) ;
+
+ /**
+ * {@link #glMultMatrixf(FloatBuffer) Multiply} the current matrix with the orthogonal matrix.
+ */
+ public void glOrthof(float left, float right, float bottom, float top, float zNear, float zFar) ;
+
+ /**
+ * {@link #glMultMatrixf(FloatBuffer) Multiply} the current matrix with the frustum matrix.
+ */
+ public void glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar);
}
diff --git a/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFunc.java b/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFunc.java
index 786835f4d..4aff24b36 100644
--- a/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFunc.java
+++ b/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFunc.java
@@ -31,7 +31,7 @@ package javax.media.opengl.fixedfunc;
import javax.media.opengl.*;
-public interface GLPointerFunc {
+public interface GLPointerFunc {
public static final int GL_VERTEX_ARRAY = 0x8074;
public static final int GL_NORMAL_ARRAY = 0x8075;
public static final int GL_COLOR_ARRAY = 0x8076;
diff --git a/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFuncUtil.java b/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFuncUtil.java
index e52154c7d..3264062e8 100644
--- a/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFuncUtil.java
+++ b/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFuncUtil.java
@@ -28,7 +28,7 @@
package javax.media.opengl.fixedfunc;
-public class GLPointerFuncUtil {
+public class GLPointerFuncUtil {
public static final String mgl_Vertex = "mgl_Vertex";
public static final String mgl_Normal = "mgl_Normal";
public static final String mgl_Color = "mgl_Color";
@@ -37,9 +37,18 @@ public class GLPointerFuncUtil {
/**
* @param glArrayIndex the fixed function array index
- * @return default fixed function array name
+ * @return default fixed function array name
*/
- public static String getPredefinedArrayIndexName(int glArrayIndex) {
+ public static String getPredefinedArrayIndexName(final int glArrayIndex) {
+ return getPredefinedArrayIndexName(glArrayIndex, -1);
+ }
+
+ /**
+ * @param glArrayIndex the fixed function array index
+ * @param multiTexCoordIndex index for multiTexCoordIndex
+ * @return default fixed function array name
+ */
+ public static String getPredefinedArrayIndexName(final int glArrayIndex, final int multiTexCoordIndex) {
switch(glArrayIndex) {
case GLPointerFunc.GL_VERTEX_ARRAY:
return mgl_Vertex;
@@ -48,7 +57,11 @@ public class GLPointerFuncUtil {
case GLPointerFunc.GL_COLOR_ARRAY:
return mgl_Color;
case GLPointerFunc.GL_TEXTURE_COORD_ARRAY:
- return mgl_MultiTexCoord;
+ if(0<=multiTexCoordIndex) {
+ return mgl_MultiTexCoord+multiTexCoordIndex;
+ } else {
+ return mgl_MultiTexCoord+multiTexCoordIndex;
+ }
}
return null;
}
diff --git a/src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallbackAdapter.java b/src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallbackAdapter.java
index bd12dfb9d..c293fbe18 100644
--- a/src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallbackAdapter.java
+++ b/src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallbackAdapter.java
@@ -64,21 +64,33 @@ package javax.media.opengl.glu;
*/
public class GLUtessellatorCallbackAdapter implements GLUtessellatorCallback {
- public void begin(int type) {}
- public void edgeFlag(boolean boundaryEdge) {}
- public void vertex(Object vertexData) {}
+ @Override
+ public void begin(final int type) {}
+ @Override
+ public void edgeFlag(final boolean boundaryEdge) {}
+ @Override
+ public void vertex(final Object vertexData) {}
+ @Override
public void end() {}
// public void mesh(jogamp.opengl.tessellator.GLUmesh mesh) {}
- public void error(int errnum) {}
- public void combine(double[] coords, Object[] data,
- float[] weight, Object[] outData) {}
- public void beginData(int type, Object polygonData) {}
- public void edgeFlagData(boolean boundaryEdge,
- Object polygonData) {}
- public void vertexData(Object vertexData, Object polygonData) {}
- public void endData(Object polygonData) {}
- public void errorData(int errnum, Object polygonData) {}
- public void combineData(double[] coords, Object[] data,
- float[] weight, Object[] outData,
- Object polygonData) {}
+ @Override
+ public void error(final int errnum) {}
+ @Override
+ public void combine(final double[] coords, final Object[] data,
+ final float[] weight, final Object[] outData) {}
+ @Override
+ public void beginData(final int type, final Object polygonData) {}
+ @Override
+ public void edgeFlagData(final boolean boundaryEdge,
+ final Object polygonData) {}
+ @Override
+ public void vertexData(final Object vertexData, final Object polygonData) {}
+ @Override
+ public void endData(final Object polygonData) {}
+ @Override
+ public void errorData(final int errnum, final Object polygonData) {}
+ @Override
+ public void combineData(final double[] coords, final Object[] data,
+ final float[] weight, final Object[] outData,
+ final Object polygonData) {}
}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/RegionFactory.java b/src/jogl/classes/jogamp/graph/curve/opengl/RegionFactory.java
deleted file mode 100755
index 1f59b5805..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/RegionFactory.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package jogamp.graph.curve.opengl;
-
-import com.jogamp.graph.curve.Region;
-import com.jogamp.graph.curve.opengl.GLRegion;
-
-/** RegionFactory to create a Context specific Region implementation.
- *
- * @see GLRegion
- */
-public class RegionFactory {
-
- /**
- * Create a Region using the passed render mode
- *
- * <p> In case {@link Region#VBAA_RENDERING_BIT} is being requested the default texture unit
- * {@link Region#TWO_PASS_DEFAULT_TEXTURE_UNIT} is being used.</p>
- *
- * @param rs the RenderState to be used
- * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, {@link Region#VBAA_RENDERING_BIT}
- */
- public static GLRegion create(int renderModes) {
- if( 0 != ( Region.VBAA_RENDERING_BIT & renderModes ) ){
- return new VBORegion2PES2(renderModes, Region.TWO_PASS_DEFAULT_TEXTURE_UNIT);
- }
- else{
- return new VBORegionSPES2(renderModes);
- }
- }
-
- /** Create a Single Pass Region using the passed render mode
- * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT},
- * {@link Region#VBAA_RENDERING_BIT}
- * @return
- */
- public static GLRegion createSinglePass(int renderModes) {
- return new VBORegionSPES2(renderModes);
- }
-
- /** Create a Two Pass (VBAA) Region using the passed render mode
- * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT},
- * {@link Region#VBAA_RENDERING_BIT}
- * @return
- */
- public static GLRegion createTwoPass(int renderModes, int textureUnit) {
- return new VBORegion2PES2(renderModes, textureUnit);
- }
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/RegionRendererImpl01.java b/src/jogl/classes/jogamp/graph/curve/opengl/RegionRendererImpl01.java
deleted file mode 100755
index c34d1cbeb..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/RegionRendererImpl01.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package jogamp.graph.curve.opengl;
-
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLException;
-
-import jogamp.graph.curve.opengl.shader.AttributeNames;
-
-import com.jogamp.graph.curve.Region;
-import com.jogamp.graph.curve.opengl.GLRegion;
-import com.jogamp.graph.curve.opengl.RegionRenderer;
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.opengl.util.glsl.ShaderCode;
-import com.jogamp.opengl.util.glsl.ShaderProgram;
-import com.jogamp.opengl.util.glsl.ShaderState;
-
-public class RegionRendererImpl01 extends RegionRenderer {
- public RegionRendererImpl01(RenderState rs, int renderModes) {
- super(rs, renderModes);
-
- }
-
- @Override
- protected String getFragmentShaderName(GL2ES2 gl) {
- final String type = Region.isNonUniformWeight(renderModes) ? "02" : "01" ;
- final String pass = Region.isVBAA(renderModes) ? "b" : "a" ;
- return "curverenderer" + type + pass + getShaderGLVersionSuffix(gl);
- }
-
- protected boolean initShaderProgram(GL2ES2 gl) {
- final ShaderState st = rs.getShaderState();
-
- ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RegionRendererImpl01.class, "shader",
- "shader/bin", getVertexShaderName(gl), false);
- ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RegionRendererImpl01.class, "shader",
- "shader/bin", getFragmentShaderName(gl), false);
-
- ShaderProgram sp = new ShaderProgram();
- sp.add(rsVp);
- sp.add(rsFp);
-
- sp.init(gl);
- st.attachShaderProgram(gl, sp, false);
- st.bindAttribLocation(gl, AttributeNames.VERTEX_ATTR_IDX, AttributeNames.VERTEX_ATTR_NAME);
- st.bindAttribLocation(gl, AttributeNames.TEXCOORD_ATTR_IDX, AttributeNames.TEXCOORD_ATTR_NAME);
-
- if(!sp.link(gl, System.err)) {
- throw new GLException("RegionRenderer: Couldn't link program: "+sp);
- }
- st.useProgram(gl, true);
-
- if(DEBUG) {
- System.err.println("RegionRendererImpl01 initialized: " + Thread.currentThread()+" "+st);
- }
- return true;
- }
-
- @Override
- protected void destroyImpl(GL2ES2 gl) {
- super.destroyImpl(gl);
- }
-
- @Override
- protected void drawImpl(GL2ES2 gl, Region region, float[] position, int[] texSize) {
- ((GLRegion)region).draw(gl, rs, vp_width, vp_height, texSize);
- }
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java b/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java
deleted file mode 100644
index 51356ca13..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package jogamp.graph.curve.opengl;
-
-import java.nio.FloatBuffer;
-
-import javax.media.opengl.GLUniformData;
-
-import jogamp.graph.curve.opengl.shader.UniformNames;
-
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.Vertex;
-import com.jogamp.opengl.util.PMVMatrix;
-import com.jogamp.opengl.util.glsl.ShaderState;
-
-public class RenderStateImpl extends RenderState {
- /**
- * weight is equivalent to the
- * global off-curve vertex weight.
- * TODO: change to per vertex
- */
- private final GLUniformData gcu_Weight;
- private final GLUniformData gcu_Alpha;
- private final GLUniformData gcu_ColorStatic;
-
- public RenderStateImpl(ShaderState st, Vertex.Factory<? extends Vertex> pointFactory, PMVMatrix pmvMatrix) {
- super(st, pointFactory, pmvMatrix);
-
- gcu_Weight = new GLUniformData(UniformNames.gcu_Weight, 1.0f);
- st.ownUniform(gcu_PMVMatrix);
- gcu_Alpha = new GLUniformData(UniformNames.gcu_Alpha, 1.0f);
- st.ownUniform(gcu_Alpha);
- gcu_ColorStatic = new GLUniformData(UniformNames.gcu_ColorStatic, 3, FloatBuffer.allocate(3));
- st.ownUniform(gcu_ColorStatic);
-// gcu_Strength = new GLUniformData(UniformNames.gcu_Strength, 3.0f);
-// st.ownUniform(gcu_Strength);
- }
-
- public RenderStateImpl(ShaderState st, Vertex.Factory<? extends Vertex> pointFactory) {
- this(st, pointFactory, new PMVMatrix());
- }
-
- public final GLUniformData getWeight() { return gcu_Weight; }
- public final GLUniformData getAlpha() { return gcu_Alpha; }
- public final GLUniformData getColorStatic() { return gcu_ColorStatic; }
- //public final GLUniformData getStrength() { return gcu_Strength; }
-
-
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/TextRendererImpl01.java b/src/jogl/classes/jogamp/graph/curve/opengl/TextRendererImpl01.java
deleted file mode 100644
index 158f0240a..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/TextRendererImpl01.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package jogamp.graph.curve.opengl;
-
-import javax.media.opengl.GL2ES2;
-import javax.media.opengl.GLException;
-
-import jogamp.graph.curve.opengl.shader.AttributeNames;
-import jogamp.graph.curve.text.GlyphString;
-
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.curve.opengl.TextRenderer;
-import com.jogamp.graph.font.Font;
-import com.jogamp.opengl.util.glsl.ShaderCode;
-import com.jogamp.opengl.util.glsl.ShaderProgram;
-import com.jogamp.opengl.util.glsl.ShaderState;
-
-public class TextRendererImpl01 extends TextRenderer {
- public TextRendererImpl01(RenderState rs, int type) {
- super(rs, type);
- }
-
- @Override
- protected boolean initShaderProgram(GL2ES2 gl){
- final ShaderState st = rs.getShaderState();
-
- ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TextRendererImpl01.class, "shader",
- "shader/bin", getVertexShaderName(gl), false);
- ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TextRendererImpl01.class, "shader",
- "shader/bin", getFragmentShaderName(gl), false);
-
- ShaderProgram sp = new ShaderProgram();
- sp.add(rsVp);
- sp.add(rsFp);
-
- sp.init(gl);
- st.attachShaderProgram(gl, sp, false);
- st.bindAttribLocation(gl, AttributeNames.VERTEX_ATTR_IDX, AttributeNames.VERTEX_ATTR_NAME);
- st.bindAttribLocation(gl, AttributeNames.TEXCOORD_ATTR_IDX, AttributeNames.TEXCOORD_ATTR_NAME);
-
- if(!sp.link(gl, System.err)) {
- throw new GLException("TextRendererImpl01: Couldn't link program: "+sp);
- }
- st.useProgram(gl, true);
-
- if(DEBUG) {
- System.err.println("TextRendererImpl01 initialized: " + Thread.currentThread()+" "+st);
- }
- return true;
- }
-
- @Override
- protected void destroyImpl(GL2ES2 gl) {
- super.destroyImpl(gl);
- }
-
- @Override
- public void drawString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int[/*1*/] texSize) {
- if(!isInitialized()){
- throw new GLException("TextRendererImpl01: not initialized!");
- }
- GlyphString glyphString = getCachedGlyphString(font, str, fontSize);
- if(null == glyphString) {
- glyphString = createString(gl, font, fontSize, str);
- addCachedGlyphString(gl, font, str, fontSize, glyphString);
- }
-
- glyphString.renderString3D(gl, rs, vp_width, vp_height, texSize);
- }
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
deleted file mode 100644
index aabef29b0..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package jogamp.graph.curve.opengl;
-
-import java.nio.FloatBuffer;
-
-import javax.media.opengl.GL2ES2;
-// FIXME: Subsume GL2GL3.GL_DRAW_FRAMEBUFFER -> GL2ES2.GL_DRAW_FRAMEBUFFER !
-import javax.media.opengl.GL;
-import javax.media.opengl.GLUniformData;
-import javax.media.opengl.fixedfunc.GLMatrixFunc;
-
-import jogamp.graph.curve.opengl.shader.AttributeNames;
-import jogamp.graph.curve.opengl.shader.UniformNames;
-
-import com.jogamp.common.nio.Buffers;
-import com.jogamp.graph.geom.Triangle;
-import com.jogamp.graph.geom.Vertex;
-
-import com.jogamp.graph.curve.opengl.GLRegion;
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.opengl.FBObject;
-import com.jogamp.opengl.FBObject.Attachment;
-import com.jogamp.opengl.FBObject.TextureAttachment;
-import com.jogamp.opengl.util.GLArrayDataServer;
-import com.jogamp.opengl.util.PMVMatrix;
-import com.jogamp.opengl.util.glsl.ShaderState;
-
-public class VBORegion2PES2 extends GLRegion {
- private GLArrayDataServer verticeTxtAttr;
- private GLArrayDataServer texCoordTxtAttr;
- private GLArrayDataServer indicesTxt;
- private GLArrayDataServer verticeFboAttr;
- private GLArrayDataServer texCoordFboAttr;
- private GLArrayDataServer indicesFbo;
-
-
- private FBObject fbo;
- private TextureAttachment texA;
- private PMVMatrix fboPMVMatrix;
- GLUniformData mgl_fboPMVMatrix;
-
- private int tex_width_c = 0;
- private int tex_height_c = 0;
- GLUniformData mgl_ActiveTexture;
- GLUniformData mgl_TextureSize; // if GLSL < 1.30
-
- public VBORegion2PES2(int renderModes, int textureEngine) {
- super(renderModes);
- fboPMVMatrix = new PMVMatrix();
- mgl_fboPMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, fboPMVMatrix.glGetPMvMatrixf());
- mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine);
- }
-
- public void update(GL2ES2 gl, RenderState rs) {
- if(!isDirty()) {
- return;
- }
-
- if(null == indicesFbo) {
- final int initialElementCount = 256;
- final ShaderState st = rs.getShaderState();
-
- indicesFbo = GLArrayDataServer.createData(3, GL2ES2.GL_SHORT, initialElementCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
- indicesFbo.puts((short) 0); indicesFbo.puts((short) 1); indicesFbo.puts((short) 3);
- indicesFbo.puts((short) 1); indicesFbo.puts((short) 2); indicesFbo.puts((short) 3);
- indicesFbo.seal(true);
-
- texCoordFboAttr = GLArrayDataServer.createGLSL(AttributeNames.TEXCOORD_ATTR_NAME, 2, GL2ES2.GL_FLOAT,
- false, initialElementCount, GL.GL_STATIC_DRAW);
- st.ownAttribute(texCoordFboAttr, true);
- texCoordFboAttr.putf(5); texCoordFboAttr.putf(5);
- texCoordFboAttr.putf(5); texCoordFboAttr.putf(6);
- texCoordFboAttr.putf(6); texCoordFboAttr.putf(6);
- texCoordFboAttr.putf(6); texCoordFboAttr.putf(5);
- texCoordFboAttr.seal(true);
-
- verticeFboAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL2ES2.GL_FLOAT,
- false, initialElementCount, GL.GL_STATIC_DRAW);
- st.ownAttribute(verticeFboAttr, true);
-
-
- indicesTxt = GLArrayDataServer.createData(3, GL2ES2.GL_SHORT, initialElementCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
-
- verticeTxtAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL2ES2.GL_FLOAT,
- false, initialElementCount, GL.GL_STATIC_DRAW);
- st.ownAttribute(verticeTxtAttr, true);
-
- texCoordTxtAttr = GLArrayDataServer.createGLSL(AttributeNames.TEXCOORD_ATTR_NAME, 2, GL2ES2.GL_FLOAT,
- false, initialElementCount, GL.GL_STATIC_DRAW);
- st.ownAttribute(texCoordTxtAttr, true);
-
- if(DEBUG_INSTANCE) {
- System.err.println("VBORegion2PES2 Create: " + this);
- }
- }
- // process triangles
- indicesTxt.seal(gl, false);
- indicesTxt.rewind();
- for(int i=0; i<triangles.size(); i++) {
- final Triangle t = triangles.get(i);
- final Vertex[] t_vertices = t.getVertices();
-
- if(t_vertices[0].getId() == Integer.MAX_VALUE){
- t_vertices[0].setId(numVertices++);
- t_vertices[1].setId(numVertices++);
- t_vertices[2].setId(numVertices++);
-
- vertices.add(t_vertices[0]);
- vertices.add(t_vertices[1]);
- vertices.add(t_vertices[2]);
-
- indicesTxt.puts((short) t_vertices[0].getId());
- indicesTxt.puts((short) t_vertices[1].getId());
- indicesTxt.puts((short) t_vertices[2].getId());
- } else {
- indicesTxt.puts((short) t_vertices[0].getId());
- indicesTxt.puts((short) t_vertices[1].getId());
- indicesTxt.puts((short) t_vertices[2].getId());
- }
- }
- indicesTxt.seal(gl, true);
- indicesTxt.enableBuffer(gl, false);
-
- // process vertices and update bbox
- box.reset();
- verticeTxtAttr.seal(gl, false);
- verticeTxtAttr.rewind();
- texCoordTxtAttr.seal(gl, false);
- texCoordTxtAttr.rewind();
- for(int i=0; i<vertices.size(); i++) {
- final Vertex v = vertices.get(i);
- verticeTxtAttr.putf(v.getX());
- verticeTxtAttr.putf(v.getY());
- verticeTxtAttr.putf(v.getZ());
- box.resize(v.getX(), v.getY(), v.getZ());
-
- final float[] tex = v.getTexCoord();
- texCoordTxtAttr.putf(tex[0]);
- texCoordTxtAttr.putf(tex[1]);
- }
- texCoordTxtAttr.seal(gl, true);
- texCoordTxtAttr.enableBuffer(gl, false);
- verticeTxtAttr.seal(gl, true);
- verticeTxtAttr.enableBuffer(gl, false);
-
- // update all bbox related data
- verticeFboAttr.seal(gl, false);
- verticeFboAttr.rewind();
- verticeFboAttr.putf(box.getLow()[0]); verticeFboAttr.putf(box.getLow()[1]); verticeFboAttr.putf(box.getLow()[2]);
- verticeFboAttr.putf(box.getLow()[0]); verticeFboAttr.putf(box.getHigh()[1]); verticeFboAttr.putf(box.getLow()[2]);
- verticeFboAttr.putf(box.getHigh()[0]); verticeFboAttr.putf(box.getHigh()[1]); verticeFboAttr.putf(box.getLow()[2]);
- verticeFboAttr.putf(box.getHigh()[0]); verticeFboAttr.putf(box.getLow()[1]); verticeFboAttr.putf(box.getLow()[2]);
- verticeFboAttr.seal(gl, true);
- verticeFboAttr.enableBuffer(gl, false);
-
- fboPMVMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
- fboPMVMatrix.glLoadIdentity();
- fboPMVMatrix.glOrthof(box.getLow()[0], box.getHigh()[0], box.getLow()[1], box.getHigh()[1], -1, 1);
-
- // push data 2 GPU ..
- indicesFbo.seal(gl, true);
- indicesFbo.enableBuffer(gl, false);
-
- setDirty(false);
-
- // the buffers were disabled, since due to real/fbo switching and other vbo usage
- }
-
- int[] maxTexSize = new int[] { -1 } ;
-
- protected void drawImpl(GL2ES2 gl, RenderState rs, int vp_width, int vp_height, int[/*1*/] texWidth) {
- if(vp_width <=0 || vp_height <= 0 || null==texWidth || texWidth[0] <= 0){
- renderRegion(gl);
- } else {
- if(0 > maxTexSize[0]) {
- gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, maxTexSize, 0);
- }
- if(texWidth[0] != tex_width_c) {
- if(texWidth[0] > maxTexSize[0]) {
- texWidth[0] = maxTexSize[0]; // clip to max - write-back user value!
- }
- renderRegion2FBO(gl, rs, texWidth);
- }
- // System.out.println("Scale: " + matrix.glGetMatrixf().get(1+4*3) +" " + matrix.glGetMatrixf().get(2+4*3));
- renderFBO(gl, rs, vp_width, vp_height);
- }
- }
-
- private void renderFBO(GL2ES2 gl, RenderState rs, int width, int hight) {
- final ShaderState st = rs.getShaderState();
-
- gl.glViewport(0, 0, width, hight);
- st.uniform(gl, mgl_ActiveTexture);
- gl.glActiveTexture(GL.GL_TEXTURE0 + mgl_ActiveTexture.intValue());
- fbo.use(gl, texA);
- verticeFboAttr.enableBuffer(gl, true);
- texCoordFboAttr.enableBuffer(gl, true);
- indicesFbo.enableBuffer(gl, true);
-
- gl.glDrawElements(GL2ES2.GL_TRIANGLES, indicesFbo.getElementCount() * indicesFbo.getComponentCount(), GL2ES2.GL_UNSIGNED_SHORT, 0);
-
- verticeFboAttr.enableBuffer(gl, false);
- texCoordFboAttr.enableBuffer(gl, false);
- indicesFbo.enableBuffer(gl, false);
- fbo.unuse(gl);
-
- // setback: gl.glActiveTexture(currentActiveTextureEngine[0]);
- }
-
- private void renderRegion2FBO(GL2ES2 gl, RenderState rs, int[/*1*/] texWidth) {
- final ShaderState st = rs.getShaderState();
-
- if(0>=texWidth[0]) {
- throw new IllegalArgumentException("texWidth must be greater than 0: "+texWidth[0]);
- }
-
- tex_width_c = texWidth[0];
- tex_height_c = (int) ( ( ( tex_width_c * box.getHeight() ) / box.getWidth() ) + 0.5f );
-
- // System.out.println("FBO Size: "+texWidth[0]+" -> "+tex_width_c+"x"+tex_height_c);
- // System.out.println("FBO Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5));
-
- if(null != fbo && fbo.getWidth() != tex_width_c && fbo.getHeight() != tex_height_c ) {
- fbo.reset(gl, tex_width_c, tex_height_c);
- }
-
- if(null == fbo) {
- fbo = new FBObject();
- fbo.reset(gl, tex_width_c, tex_height_c);
- // FIXME: shall not use bilinear, due to own AA ? However, w/o bilinear result is not smooth
- texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- // texA = fbo.attachTexture2D(gl, 0, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
- } else {
- fbo.bind(gl);
- }
-
- //render texture
- gl.glViewport(0, 0, tex_width_c, tex_height_c);
- st.uniform(gl, mgl_fboPMVMatrix); // use orthogonal matrix
-
- gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT);
- renderRegion(gl);
- fbo.unbind(gl);
-
- st.uniform(gl, rs.getPMVMatrix()); // switch back to real PMV matrix
-
- // if( !gl.isGL3() ) {
- // GLSL < 1.30
- if(null == mgl_TextureSize) {
- mgl_TextureSize = new GLUniformData(UniformNames.gcu_TextureSize, 2, Buffers.newDirectFloatBuffer(2));
- }
- final FloatBuffer texSize = (FloatBuffer) mgl_TextureSize.getBuffer();
- texSize.put(0, (float)fbo.getWidth());
- texSize.put(1, (float)fbo.getHeight());
- st.uniform(gl, mgl_TextureSize);
- //}
- }
-
- private void renderRegion(GL2ES2 gl) {
- verticeTxtAttr.enableBuffer(gl, true);
- texCoordTxtAttr.enableBuffer(gl, true);
- indicesTxt.enableBuffer(gl, true);
-
- gl.glDrawElements(GL2ES2.GL_TRIANGLES, indicesTxt.getElementCount() * indicesTxt.getComponentCount(), GL2ES2.GL_UNSIGNED_SHORT, 0);
-
- verticeTxtAttr.enableBuffer(gl, false);
- texCoordTxtAttr.enableBuffer(gl, false);
- indicesTxt.enableBuffer(gl, false);
- }
-
- public void destroy(GL2ES2 gl, RenderState rs) {
- if(DEBUG_INSTANCE) {
- System.err.println("VBORegion2PES2 Destroy: " + this);
- }
- final ShaderState st = rs.getShaderState();
- if(null != fbo) {
- fbo.destroy(gl);
- fbo = null;
- texA = null;
- }
- if(null != verticeTxtAttr) {
- st.ownAttribute(verticeTxtAttr, false);
- verticeTxtAttr.destroy(gl);
- verticeTxtAttr = null;
- }
- if(null != texCoordTxtAttr) {
- st.ownAttribute(texCoordTxtAttr, false);
- texCoordTxtAttr.destroy(gl);
- texCoordTxtAttr = null;
- }
- if(null != indicesTxt) {
- indicesTxt.destroy(gl);
- indicesTxt = null;
- }
- if(null != verticeFboAttr) {
- st.ownAttribute(verticeFboAttr, false);
- verticeFboAttr.destroy(gl);
- verticeFboAttr = null;
- }
- if(null != texCoordFboAttr) {
- st.ownAttribute(texCoordFboAttr, false);
- texCoordFboAttr.destroy(gl);
- texCoordFboAttr = null;
- }
- if(null != indicesFbo) {
- indicesFbo.destroy(gl);
- indicesFbo = null;
- }
- triangles.clear();
- vertices.clear();
- }
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
new file mode 100644
index 000000000..fbd40ebdd
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
@@ -0,0 +1,586 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.graph.curve.opengl;
+
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLUniformData;
+
+import jogamp.graph.curve.opengl.shader.AttributeNames;
+import jogamp.graph.curve.opengl.shader.UniformNames;
+
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
+import com.jogamp.opengl.util.texture.TextureSequence;
+
+public class VBORegion2PMSAAES2 extends GLRegion {
+ private static final boolean DEBUG_FBO_1 = false;
+ private static final boolean DEBUG_FBO_2 = false;
+
+ private final RenderState.ProgramLocal rsLocal;
+
+ // Pass-1:
+ private GLArrayDataServer gca_VerticesAttr;
+ private GLArrayDataServer gca_CurveParamsAttr;
+ private GLArrayDataServer gca_ColorsAttr;
+ private GLArrayDataServer indicesBuffer;
+ private final GLUniformData gcu_ColorTexUnit;
+ private final float[] colorTexBBox; // x0, y0, x1, y1
+ private final GLUniformData gcu_ColorTexBBox;
+ private ShaderProgram spPass1 = null;
+
+ // Pass-2:
+ private GLArrayDataServer gca_FboVerticesAttr;
+ private GLArrayDataServer gca_FboTexCoordsAttr;
+ private GLArrayDataServer indicesFbo;
+ private final GLUniformData gcu_FboTexUnit;
+ private final float[] pmvMatrix02 = new float[2*16]; // P + Mv
+ private final GLUniformData gcu_PMVMatrix02;
+ private ShaderProgram spPass2 = null;
+
+ private FBObject fbo;
+
+ private int fboWidth = 0;
+ private int fboHeight = 0;
+ private boolean fboDirty = true;
+
+ final int[] maxTexSize = new int[] { -1 } ;
+
+ /**
+ * <p>
+ * Since multiple {@link Region}s may share one
+ * {@link ShaderProgram}, the uniform data must always be updated.
+ * </p>
+ *
+ * @param gl
+ * @param renderer
+ * @param renderModes
+ * @param pass1
+ * @param quality
+ * @param sampleCount
+ */
+ public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final boolean pass1, final int quality, final int sampleCount) {
+ final RenderState rs = renderer.getRenderState();
+ final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount, colorTexSeq);
+ final ShaderProgram sp = renderer.getRenderState().getShaderProgram();
+ final boolean updateLocLocal;
+ if( pass1 ) {
+ updateLocLocal = !sp.equals(spPass1);
+ spPass1 = sp;
+ if( DEBUG ) {
+ System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal);
+ }
+ if( updateLocLocal ) {
+ rs.updateAttributeLoc(gl, true, gca_VerticesAttr, true);
+ rs.updateAttributeLoc(gl, true, gca_CurveParamsAttr, true);
+ if( null != gca_ColorsAttr ) {
+ rs.updateAttributeLoc(gl, true, gca_ColorsAttr, true);
+ }
+ }
+ rsLocal.update(gl, rs, updateLocLocal, renderModes, true, true);
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_PMVMatrix02, true);
+ if( null != gcu_ColorTexUnit ) {
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, true);
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexBBox, true);
+ }
+ } else {
+ updateLocLocal = !sp.equals(spPass2);
+ spPass2 = sp;
+ if( DEBUG ) {
+ System.err.println("XXX changedSP.p2 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal);
+ }
+ if( updateLocLocal ) {
+ rs.updateAttributeLoc(gl, true, gca_FboVerticesAttr, true);
+ rs.updateAttributeLoc(gl, true, gca_FboTexCoordsAttr, true);
+ }
+ rsLocal.update(gl, rs, updateLocLocal, renderModes, false, true);
+ rs.updateUniformDataLoc(gl, updateLocLocal, false /* updateData */, gcu_FboTexUnit, true); // FIXME always update if changing tex-unit
+ }
+ }
+
+ public VBORegion2PMSAAES2(final int renderModes, final TextureSequence colorTexSeq, final int pass2TexUnit) {
+ super(renderModes, colorTexSeq);
+
+ rsLocal = new RenderState.ProgramLocal();
+
+ final int initialElementCount = 256;
+
+ // Pass 1:
+ indicesBuffer = GLArrayDataServer.createData(3, GL.GL_SHORT, initialElementCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
+
+ gca_VerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL.GL_FLOAT,
+ false, initialElementCount, GL.GL_STATIC_DRAW);
+
+ gca_CurveParamsAttr = GLArrayDataServer.createGLSL(AttributeNames.CURVEPARAMS_ATTR_NAME, 3, GL.GL_FLOAT,
+ false, initialElementCount, GL.GL_STATIC_DRAW);
+
+ if( hasColorChannel() ) {
+ gca_ColorsAttr = GLArrayDataServer.createGLSL(AttributeNames.COLOR_ATTR_NAME, 4, GL.GL_FLOAT,
+ false, initialElementCount, GL.GL_STATIC_DRAW);
+ } else {
+ gca_ColorsAttr = null;
+ }
+ if( hasColorTexture() ) {
+ gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit());
+ colorTexBBox = new float[4];
+ gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 4, FloatBuffer.wrap(colorTexBBox));
+ } else {
+ gcu_ColorTexUnit = null;
+ colorTexBBox = null;
+ gcu_ColorTexBBox = null;
+ }
+
+ FloatUtil.makeIdentity(pmvMatrix02, 0);
+ FloatUtil.makeIdentity(pmvMatrix02, 16);
+ gcu_PMVMatrix02 = new GLUniformData(UniformNames.gcu_PMVMatrix02, 4, 4, FloatBuffer.wrap(pmvMatrix02));
+
+ // Pass 2:
+ gcu_FboTexUnit = new GLUniformData(UniformNames.gcu_FboTexUnit, pass2TexUnit);
+
+ indicesFbo = GLArrayDataServer.createData(3, GL.GL_SHORT, 2, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
+ indicesFbo.puts((short) 0); indicesFbo.puts((short) 1); indicesFbo.puts((short) 3);
+ indicesFbo.puts((short) 1); indicesFbo.puts((short) 2); indicesFbo.puts((short) 3);
+ indicesFbo.seal(true);
+
+ gca_FboTexCoordsAttr = GLArrayDataServer.createGLSL(AttributeNames.FBO_TEXCOORDS_ATTR_NAME, 2, GL.GL_FLOAT,
+ false, 4, GL.GL_STATIC_DRAW);
+ gca_FboTexCoordsAttr.putf(0); gca_FboTexCoordsAttr.putf(0);
+ gca_FboTexCoordsAttr.putf(0); gca_FboTexCoordsAttr.putf(1);
+ gca_FboTexCoordsAttr.putf(1); gca_FboTexCoordsAttr.putf(1);
+ gca_FboTexCoordsAttr.putf(1); gca_FboTexCoordsAttr.putf(0);
+ gca_FboTexCoordsAttr.seal(true);
+
+ gca_FboVerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.FBO_VERTEX_ATTR_NAME, 3, GL.GL_FLOAT,
+ false, 4, GL.GL_STATIC_DRAW);
+ }
+
+ @Override
+ protected final void clearImpl(final GL2ES2 gl) {
+ if( null != indicesBuffer ) {
+ indicesBuffer.seal(gl, false);
+ indicesBuffer.rewind();
+ }
+ if( null != gca_VerticesAttr ) {
+ gca_VerticesAttr.seal(gl, false);
+ gca_VerticesAttr.rewind();
+ }
+ if( null != gca_CurveParamsAttr ) {
+ gca_CurveParamsAttr.seal(gl, false);
+ gca_CurveParamsAttr.rewind();
+ }
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.seal(gl, false);
+ gca_ColorsAttr.rewind();
+ }
+ fboDirty = true;
+ }
+
+ @Override
+ protected final void pushVertex(final float[] coords, final float[] texParams, final float[] rgba) {
+ gca_VerticesAttr.putf(coords[0]);
+ gca_VerticesAttr.putf(coords[1]);
+ gca_VerticesAttr.putf(coords[2]);
+
+ gca_CurveParamsAttr.putf(texParams[0]);
+ gca_CurveParamsAttr.putf(texParams[1]);
+ gca_CurveParamsAttr.putf(texParams[2]);
+
+ if( null != gca_ColorsAttr ) {
+ if( null != rgba ) {
+ gca_ColorsAttr.putf(rgba[0]);
+ gca_ColorsAttr.putf(rgba[1]);
+ gca_ColorsAttr.putf(rgba[2]);
+ gca_ColorsAttr.putf(rgba[3]);
+ } else {
+ throw new IllegalArgumentException("Null color given for COLOR_CHANNEL rendering mode");
+ }
+ }
+ }
+
+ @Override
+ protected final void pushIndex(final int idx) {
+ indicesBuffer.puts((short)idx);
+ }
+
+ @Override
+ protected void updateImpl(final GL2ES2 gl) {
+ // seal buffers
+ indicesBuffer.seal(gl, true);
+ indicesBuffer.enableBuffer(gl, false);
+ gca_CurveParamsAttr.seal(gl, true);
+ gca_CurveParamsAttr.enableBuffer(gl, false);
+ gca_VerticesAttr.seal(gl, true);
+ gca_VerticesAttr.enableBuffer(gl, false);
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.seal(gl, true);
+ gca_ColorsAttr.enableBuffer(gl, false);
+ }
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+ final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture();
+ final Texture tex = frame.getTexture();
+ final TextureCoords tc = tex.getImageTexCoords();
+ final float tcSx = 1f / ( tc.right() - tc.left() );
+ colorTexBBox[0] = box.getMinX() * tcSx;
+ colorTexBBox[2] = box.getMaxX() * tcSx;
+ if( tex.getMustFlipVertically() ) {
+ final float tcSy = 1f / ( tc.bottom() - tc.top() );
+ colorTexBBox[1] = box.getMaxY() * tcSy;
+ colorTexBBox[3] = box.getMinY() * tcSy;
+ } else {
+ final float tcSy = 1f / ( tc.top() - tc.bottom() );
+ colorTexBBox[1] = box.getMinY() * tcSy;
+ colorTexBBox[3] = box.getMaxY() * tcSy;
+ }
+ }
+ gca_FboVerticesAttr.seal(gl, false);
+ {
+ final FloatBuffer fb = (FloatBuffer)gca_FboVerticesAttr.getBuffer();
+ fb.put( 2, box.getMinZ());
+ fb.put( 5, box.getMinZ());
+ fb.put( 8, box.getMinZ());
+ fb.put(11, box.getMinZ());
+ }
+ // Pending gca_FboVerticesAttr-seal and fboPMVMatrix-setup, follow fboDirty
+
+ // push data 2 GPU ..
+ indicesFbo.seal(gl, true);
+ indicesFbo.enableBuffer(gl, false);
+
+ fboDirty = true;
+ // the buffers were disabled, since due to real/fbo switching and other vbo usage
+ }
+
+ private final AABBox drawWinBox = new AABBox();
+ private final int[] drawView = new int[] { 0, 0, 0, 0 };
+ private final float[] drawVec4Tmp0 = new float[4];
+ private final float[] drawVec4Tmp1 = new float[4];
+ private final float[] drawVec4Tmp2 = new float[4];
+ private final float[] drawMat4PMv = new float[16];
+
+ private static final int border = 2; // surrounding border, i.e. width += 2*border, height +=2*border
+
+ @Override
+ protected void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int[/*1*/] sampleCount) {
+ if( 0 >= indicesBuffer.getElementCount() ) {
+ if(DEBUG_INSTANCE) {
+ System.err.printf("VBORegion2PMSAAES2.drawImpl: Empty%n");
+ }
+ return; // empty!
+ }
+ if( Float.isInfinite(box.getWidth()) || Float.isInfinite(box.getHeight()) ) {
+ if(DEBUG_INSTANCE) {
+ System.err.printf("VBORegion2PMSAAES2.drawImpl: Inf %s%n", box);
+ }
+ return; // inf
+ }
+ final int vpWidth = renderer.getWidth();
+ final int vpHeight = renderer.getHeight();
+ if(vpWidth <=0 || vpHeight <= 0 || null==sampleCount || sampleCount[0] <= 0){
+ renderRegion(gl);
+ } else {
+ if(0 > maxTexSize[0]) {
+ gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, maxTexSize, 0);
+ }
+ final RenderState rs = renderer.getRenderState();
+ final float winWidth, winHeight;
+
+ final float ratioObjWinWidth, ratioObjWinHeight;
+ final float diffObjWidth, diffObjHeight;
+ final float diffObjBorderWidth, diffObjBorderHeight;
+ int targetFboWidth, targetFboHeight;
+ {
+ final float diffWinWidth, diffWinHeight;
+ final int targetWinWidth, targetWinHeight;
+
+ // Calculate perspective pixel width/height for FBO,
+ // considering the sampleCount.
+ drawView[2] = vpWidth;
+ drawView[3] = vpHeight;
+
+ renderer.getMatrix().multPMvMatrixf(drawMat4PMv, 0);
+ box.mapToWindow(drawWinBox, drawMat4PMv, drawView, true /* useCenterZ */,
+ drawVec4Tmp0, drawVec4Tmp1, drawVec4Tmp2);
+
+ winWidth = drawWinBox.getWidth();
+ winHeight = drawWinBox.getHeight();
+ targetWinWidth = (int)Math.ceil(winWidth);
+ targetWinHeight = (int)Math.ceil(winHeight);
+ diffWinWidth = targetWinWidth-winWidth;
+ diffWinHeight = targetWinHeight-winHeight;
+
+ ratioObjWinWidth = box.getWidth() / winWidth;
+ ratioObjWinHeight= box.getHeight() / winHeight;
+ diffObjWidth = diffWinWidth * ratioObjWinWidth;
+ diffObjHeight = diffWinHeight * ratioObjWinHeight;
+ diffObjBorderWidth = border * ratioObjWinWidth;
+ diffObjBorderHeight = border * ratioObjWinHeight;
+
+ targetFboWidth = targetWinWidth+2*border;
+ targetFboHeight = targetWinHeight+2*border;
+
+ if( DEBUG_FBO_2 ) {
+ final float ratioWinWidth, ratioWinHeight;
+ ratioWinWidth = winWidth/targetWinWidth;
+ ratioWinHeight = winHeight/targetWinHeight;
+
+ System.err.printf("XXX.MinMax obj %s%n", box.toString());
+ System.err.printf("XXX.MinMax obj d[%.3f, %.3f], r[%f, %f], b[%f, %f]%n",
+ diffObjWidth, diffObjHeight, ratioObjWinWidth, ratioObjWinWidth, diffObjBorderWidth, diffObjBorderHeight);
+ System.err.printf("XXX.MinMax win %s%n", drawWinBox.toString());
+ System.err.printf("XXX.MinMax view[%d, %d] -> win[%.3f, %.3f], i[%d x %d], d[%.3f, %.3f], r[%f, %f]: FBO i[%d x %d], samples %d%n",
+ drawView[2], drawView[3],
+ winWidth, winHeight, targetWinWidth, targetWinHeight, diffWinWidth,
+ diffWinHeight, ratioWinWidth, ratioWinHeight,
+ targetFboWidth, targetFboHeight,
+ sampleCount[0]);
+ }
+ }
+ if( 0 >= targetFboWidth || 0 >= targetFboHeight ) {
+ // Nothing ..
+ return;
+ }
+ final int deltaFboWidth = Math.abs(targetFboWidth-fboWidth);
+ final int deltaFboHeight = Math.abs(targetFboHeight-fboHeight);
+ final boolean hasDelta = 0!=deltaFboWidth || 0!=deltaFboHeight;
+ if( DEBUG_FBO_2 ) {
+ System.err.printf("XXX.maxDelta: hasDelta %b: %d / %d, %.3f, %.3f%n",
+ hasDelta, deltaFboWidth, deltaFboHeight, (float)deltaFboWidth/fboWidth, (float)deltaFboHeight/fboHeight);
+ System.err.printf("XXX.Scale %d * [%f x %f]: %d x %d%n",
+ sampleCount[0], winWidth, winHeight, targetFboWidth, targetFboHeight);
+ }
+ if( hasDelta || fboDirty || isShapeDirty() || null == fbo || fbo.getNumSamples() != sampleCount[0] ) {
+ // FIXME: rescale
+ final float minX = box.getMinX()-diffObjBorderWidth;
+ final float minY = box.getMinY()-diffObjBorderHeight;
+ final float maxX = box.getMaxX()+diffObjBorderWidth+diffObjWidth;
+ final float maxY = box.getMaxY()+diffObjBorderHeight+diffObjHeight;
+ gca_FboVerticesAttr.seal(false);
+ {
+ final FloatBuffer fb = (FloatBuffer)gca_FboVerticesAttr.getBuffer();
+ fb.put(0, minX); fb.put( 1, minY);
+ fb.put(3, minX); fb.put( 4, maxY);
+ fb.put(6, maxX); fb.put( 7, maxY);
+ fb.put(9, maxX); fb.put(10, minY);
+ fb.position(12);
+ }
+ gca_FboVerticesAttr.seal(true);
+ FloatUtil.makeOrtho(pmvMatrix02, 0, true, minX, maxX, minY, maxY, -1, 1);
+ useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
+ renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount);
+ } else if( isStateDirty() ) {
+ useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
+ renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount);
+ }
+ useShaderProgram(gl, renderer, getRenderModes(), false, getQuality(), sampleCount[0]);
+ renderFBO(gl, rs, vpWidth, vpHeight, sampleCount[0]);
+ }
+ }
+
+ private void renderFBO(final GL2ES2 gl, final RenderState rs, final int width, final int height, final int sampleCount) {
+ gl.glViewport(0, 0, width, height);
+
+ if( rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED | RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED) ) {
+ // RGB is already multiplied w/ alpha via renderRegion2FBO(..)
+ gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+
+ } else if( rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
+ // RGB is already multiplied w/ alpha via renderRegion2FBO(..)
+ gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ gl.glActiveTexture(GL.GL_TEXTURE0 + gcu_FboTexUnit.intValue());
+
+ fbo.use(gl, fbo.getSamplingSink().getTextureAttachment());
+ gca_FboVerticesAttr.enableBuffer(gl, true);
+ gca_FboTexCoordsAttr.enableBuffer(gl, true);
+ indicesFbo.bindBuffer(gl, true); // keeps VBO binding
+
+ gl.glDrawElements(GL.GL_TRIANGLES, indicesFbo.getElementCount() * indicesFbo.getComponentCount(), GL.GL_UNSIGNED_SHORT, 0);
+
+ indicesFbo.bindBuffer(gl, false);
+ gca_FboTexCoordsAttr.enableBuffer(gl, false);
+ gca_FboVerticesAttr.enableBuffer(gl, false);
+ fbo.unuse(gl);
+
+ // setback: gl.glActiveTexture(currentActiveTextureEngine[0]);
+ }
+
+ private void renderRegion2FBO(final GL2ES2 gl, final RenderState rs, final int targetFboWidth, final int targetFboHeight,
+ final int vpWidth, final int vpHeight, final int[] sampleCount) {
+ if( 0 >= targetFboWidth || 0 >= targetFboHeight ) {
+ throw new IllegalArgumentException("fboSize must be greater than 0: "+targetFboWidth+"x"+targetFboHeight);
+ }
+
+ final boolean blendingEnabled = rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED);
+
+ if(null == fbo) {
+ fboWidth = targetFboWidth;
+ fboHeight = targetFboHeight;
+ fbo = new FBObject();
+ fbo.init(gl, fboWidth, fboHeight, sampleCount[0]);
+ sampleCount[0] = fbo.getNumSamples();
+ fbo.attachColorbuffer(gl, 0, true);
+ if( !blendingEnabled ) {
+ // no depth-buffer w/ blending
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS);
+ }
+ final FBObject ssink = new FBObject();
+ {
+ ssink.init(gl, fboWidth, fboHeight, 0);
+ // FIXME: shall not use bilinear (GL_LINEAR), due to MSAA ???
+ // ssink.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
+ ssink.attachTexture2D(gl, 0, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ if( !blendingEnabled ) {
+ // no depth-buffer w/ blending
+ ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS);
+ }
+ }
+ fbo.setSamplingSink(ssink);
+ fbo.resetSamplingSink(gl); // validate
+ if( DEBUG_FBO_1 ) {
+ System.err.printf("XXX.createFBO: blending %b, %dx%d%n%s%n", blendingEnabled, fboWidth, fboHeight, fbo.toString());
+ }
+ } else if( targetFboWidth != fboWidth || targetFboHeight != fboHeight || fbo.getNumSamples() != sampleCount[0] ) {
+ fbo.reset(gl, targetFboWidth, targetFboHeight, sampleCount[0]);
+ sampleCount[0] = fbo.getNumSamples();
+ if( DEBUG_FBO_1 ) {
+ System.err.printf("XXX.resetFBO: %dx%d -> %dx%d%n%s%n", fboWidth, fboHeight, targetFboWidth, targetFboHeight, fbo );
+ }
+ fboWidth = targetFboWidth;
+ fboHeight = targetFboHeight;
+ }
+ fbo.bind(gl);
+
+ //render texture
+ gl.glViewport(0, 0, fboWidth, fboHeight);
+ if( blendingEnabled ) {
+ gl.glClearColor(0f, 0f, 0f, 0.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT); // no depth-buffer w/ blending
+ // For already pre-multiplied alpha values, use:
+ // gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+
+ // Multiply RGB w/ Alpha, preserve alpha for renderFBO(..)
+ gl.glBlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+
+ if( rs.isHintMaskSet(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED) ) {
+ gl.glDisable(GL.GL_DEPTH_TEST);
+ }
+ } else {
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+
+ renderRegion(gl);
+
+ fbo.unbind(gl);
+ fboDirty = false;
+ }
+
+ private void renderRegion(final GL2ES2 gl) {
+ gl.glUniform(gcu_PMVMatrix02);
+ gca_VerticesAttr.enableBuffer(gl, true);
+ gca_CurveParamsAttr.enableBuffer(gl, true);
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.enableBuffer(gl, true);
+ }
+ indicesBuffer.bindBuffer(gl, true); // keeps VBO binding
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+ final TextureSequence.TextureFrame frame = colorTexSeq.getNextTexture(gl);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + colorTexSeq.getTextureUnit());
+ final Texture tex = frame.getTexture();
+ tex.bind(gl);
+ tex.enable(gl); // nop on core
+ gcu_ColorTexUnit.setData(colorTexSeq.getTextureUnit());
+ gl.glUniform(gcu_ColorTexUnit); // Always update, since program maybe used by multiple regions
+ gl.glUniform(gcu_ColorTexBBox); // Always update, since program maybe used by multiple regions
+ gl.glDrawElements(GL.GL_TRIANGLES, indicesBuffer.getElementCount() * indicesBuffer.getComponentCount(), GL.GL_UNSIGNED_SHORT, 0);
+ tex.disable(gl); // nop on core
+ } else {
+ gl.glDrawElements(GL.GL_TRIANGLES, indicesBuffer.getElementCount() * indicesBuffer.getComponentCount(), GL.GL_UNSIGNED_SHORT, 0);
+ }
+
+ indicesBuffer.bindBuffer(gl, false);
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.enableBuffer(gl, false);
+ }
+ gca_CurveParamsAttr.enableBuffer(gl, false);
+ gca_VerticesAttr.enableBuffer(gl, false);
+ }
+
+ @Override
+ protected void destroyImpl(final GL2ES2 gl) {
+ if(DEBUG_INSTANCE) {
+ System.err.println("VBORegion2PES2 Destroy: " + this);
+ }
+ if(null != fbo) {
+ fbo.destroy(gl);
+ fbo = null;
+ }
+ if(null != gca_VerticesAttr) {
+ gca_VerticesAttr.destroy(gl);
+ gca_VerticesAttr = null;
+ }
+ if(null != gca_CurveParamsAttr) {
+ gca_CurveParamsAttr.destroy(gl);
+ gca_CurveParamsAttr = null;
+ }
+ if(null != gca_ColorsAttr) {
+ gca_ColorsAttr.destroy(gl);
+ gca_ColorsAttr = null;
+ }
+ if(null != indicesBuffer) {
+ indicesBuffer.destroy(gl);
+ indicesBuffer = null;
+ }
+ if(null != gca_FboVerticesAttr) {
+ gca_FboVerticesAttr.destroy(gl);
+ gca_FboVerticesAttr = null;
+ }
+ if(null != gca_FboTexCoordsAttr) {
+ gca_FboTexCoordsAttr.destroy(gl);
+ gca_FboTexCoordsAttr = null;
+ }
+ if(null != indicesFbo) {
+ indicesFbo.destroy(gl);
+ indicesFbo = null;
+ }
+ spPass1 = null;
+ spPass2 = null;
+ }
+}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
new file mode 100644
index 000000000..8f1de9157
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
@@ -0,0 +1,700 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.graph.curve.opengl;
+
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLUniformData;
+
+import jogamp.graph.curve.opengl.shader.AttributeNames;
+import jogamp.graph.curve.opengl.shader.UniformNames;
+import jogamp.opengl.Debug;
+
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.FBObject.TextureAttachment;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
+import com.jogamp.opengl.util.texture.TextureSequence;
+
+public class VBORegion2PVBAAES2 extends GLRegion {
+ private static final boolean DEBUG_FBO_1 = false;
+ private static final boolean DEBUG_FBO_2 = false;
+
+ /**
+ * Boundary triggering FBO resize if
+ * <pre>
+ * fbo[Width|Height] - targetFbo[Width|Height] > RESIZE_BOUNDARY.
+ * </pre>
+ * <p>
+ * Increasing the FBO will add RESIZE_BOUNDARY/2.
+ * </p>
+ * <p>
+ * Reducing FBO resize to gain performance.
+ * </p>
+ * <p>
+ * Defaults to disabled since:
+ * - not working properly
+ * - FBO texture rendered > than desired size
+ * - FBO resize itself should be fast enough ?!
+ * </p>
+ */
+ private static final int RESIZE_BOUNDARY;
+
+ static {
+ Debug.initSingleton();
+ final String key = "jogl.debug.graph.curve.vbaa.resizeLowerBoundary";
+ RESIZE_BOUNDARY = Math.max(0, PropertyAccess.getIntProperty(key, true, 0));
+ if( RESIZE_BOUNDARY > 0 ) {
+ System.err.println("key: "+RESIZE_BOUNDARY);
+ }
+ }
+
+
+ private final RenderState.ProgramLocal rsLocal;
+
+ // Pass-1:
+ private GLArrayDataServer gca_VerticesAttr;
+ private GLArrayDataServer gca_CurveParamsAttr;
+ private GLArrayDataServer gca_ColorsAttr;
+ private GLArrayDataServer indicesBuffer;
+ private final GLUniformData gcu_ColorTexUnit;
+ private final float[] colorTexBBox; // x0, y0, x1, y1
+ private final GLUniformData gcu_ColorTexBBox;
+ private ShaderProgram spPass1 = null;
+
+ // Pass-2:
+ private GLArrayDataServer gca_FboVerticesAttr;
+ private GLArrayDataServer gca_FboTexCoordsAttr;
+ private GLArrayDataServer indicesFbo;
+ private final GLUniformData gcu_FboTexUnit;
+ private final GLUniformData gcu_FboTexSize;
+ private final float[] pmvMatrix02 = new float[2*16]; // P + Mv
+ private final GLUniformData gcu_PMVMatrix02;
+ private ShaderProgram spPass2 = null;
+
+ private FBObject fbo;
+ private TextureAttachment texA;
+
+ private int fboWidth = 0;
+ private int fboHeight = 0;
+ private boolean fboDirty = true;
+
+ final int[] maxTexSize = new int[] { -1 } ;
+
+ /**
+ * <p>
+ * Since multiple {@link Region}s may share one
+ * {@link ShaderProgram}, the uniform data must always be updated.
+ * </p>
+ *
+ * @param gl
+ * @param renderer
+ * @param renderModes
+ * @param pass1
+ * @param quality
+ * @param sampleCount
+ */
+ public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final boolean pass1, final int quality, final int sampleCount) {
+ final RenderState rs = renderer.getRenderState();
+ final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount, colorTexSeq);
+ final ShaderProgram sp = renderer.getRenderState().getShaderProgram();
+ final boolean updateLocLocal;
+ if( pass1 ) {
+ updateLocLocal = !sp.equals(spPass1);
+ spPass1 = sp;
+ if( DEBUG ) {
+ System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal);
+ }
+ if( updateLocLocal ) {
+ rs.updateAttributeLoc(gl, true, gca_VerticesAttr, true);
+ rs.updateAttributeLoc(gl, true, gca_CurveParamsAttr, true);
+ if( null != gca_ColorsAttr ) {
+ rs.updateAttributeLoc(gl, true, gca_ColorsAttr, true);
+ }
+ }
+ rsLocal.update(gl, rs, updateLocLocal, renderModes, true, true);
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_PMVMatrix02, true);
+ if( null != gcu_ColorTexUnit ) {
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, true);
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexBBox, true);
+ }
+ } else {
+ updateLocLocal = !sp.equals(spPass2);
+ spPass2 = sp;
+ if( DEBUG ) {
+ System.err.println("XXX changedSP.p2 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal);
+ }
+ if( updateLocLocal ) {
+ rs.updateAttributeLoc(gl, true, gca_FboVerticesAttr, true);
+ rs.updateAttributeLoc(gl, true, gca_FboTexCoordsAttr, true);
+ }
+ rsLocal.update(gl, rs, updateLocLocal, renderModes, false, true);
+ rs.updateUniformDataLoc(gl, updateLocLocal, false /* updateData */, gcu_FboTexUnit, true); // FIXME always update if changing tex-unit
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_FboTexSize, sampleCount > 1); // maybe optimized away for sampleCount <= 1
+ }
+ }
+
+ public VBORegion2PVBAAES2(final int renderModes, final TextureSequence colorTexSeq, final int pass2TexUnit) {
+ super(renderModes, colorTexSeq);
+
+ rsLocal = new RenderState.ProgramLocal();
+
+ final int initialElementCount = 256;
+
+ // Pass 1:
+ indicesBuffer = GLArrayDataServer.createData(3, GL.GL_SHORT, initialElementCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
+
+ gca_VerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL.GL_FLOAT,
+ false, initialElementCount, GL.GL_STATIC_DRAW);
+
+ gca_CurveParamsAttr = GLArrayDataServer.createGLSL(AttributeNames.CURVEPARAMS_ATTR_NAME, 3, GL.GL_FLOAT,
+ false, initialElementCount, GL.GL_STATIC_DRAW);
+ if( hasColorChannel() ) {
+ gca_ColorsAttr = GLArrayDataServer.createGLSL(AttributeNames.COLOR_ATTR_NAME, 4, GL.GL_FLOAT,
+ false, initialElementCount, GL.GL_STATIC_DRAW);
+ } else {
+ gca_ColorsAttr = null;
+ }
+ if( hasColorTexture() ) {
+ gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit());
+ colorTexBBox = new float[4];
+ gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 4, FloatBuffer.wrap(colorTexBBox));
+ } else {
+ gcu_ColorTexUnit = null;
+ colorTexBBox = null;
+ gcu_ColorTexBBox = null;
+ }
+
+ FloatUtil.makeIdentity(pmvMatrix02, 0);
+ FloatUtil.makeIdentity(pmvMatrix02, 16);
+ gcu_PMVMatrix02 = new GLUniformData(UniformNames.gcu_PMVMatrix02, 4, 4, FloatBuffer.wrap(pmvMatrix02));
+
+ // Pass 2:
+ gcu_FboTexUnit = new GLUniformData(UniformNames.gcu_FboTexUnit, pass2TexUnit);
+ gcu_FboTexSize = new GLUniformData(UniformNames.gcu_FboTexSize, 2, FloatBuffer.wrap(new float[2]));
+
+ indicesFbo = GLArrayDataServer.createData(3, GL.GL_SHORT, 2, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
+ indicesFbo.puts((short) 0); indicesFbo.puts((short) 1); indicesFbo.puts((short) 3);
+ indicesFbo.puts((short) 1); indicesFbo.puts((short) 2); indicesFbo.puts((short) 3);
+ indicesFbo.seal(true);
+
+ gca_FboTexCoordsAttr = GLArrayDataServer.createGLSL(AttributeNames.FBO_TEXCOORDS_ATTR_NAME, 2, GL.GL_FLOAT,
+ false, 4, GL.GL_STATIC_DRAW);
+ gca_FboTexCoordsAttr.putf(0); gca_FboTexCoordsAttr.putf(0);
+ gca_FboTexCoordsAttr.putf(0); gca_FboTexCoordsAttr.putf(1);
+ gca_FboTexCoordsAttr.putf(1); gca_FboTexCoordsAttr.putf(1);
+ gca_FboTexCoordsAttr.putf(1); gca_FboTexCoordsAttr.putf(0);
+ gca_FboTexCoordsAttr.seal(true);
+
+ gca_FboVerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.FBO_VERTEX_ATTR_NAME, 3, GL.GL_FLOAT,
+ false, 4, GL.GL_STATIC_DRAW);
+ }
+
+ @Override
+ protected final void clearImpl(final GL2ES2 gl) {
+ if(DEBUG_INSTANCE) {
+ System.err.println("VBORegion2PES2 Clear: " + this);
+ // Thread.dumpStack();
+ }
+ if( null != indicesBuffer ) {
+ indicesBuffer.seal(gl, false);
+ indicesBuffer.rewind();
+ }
+ if( null != gca_VerticesAttr ) {
+ gca_VerticesAttr.seal(gl, false);
+ gca_VerticesAttr.rewind();
+ }
+ if( null != gca_CurveParamsAttr ) {
+ gca_CurveParamsAttr.seal(gl, false);
+ gca_CurveParamsAttr.rewind();
+ }
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.seal(gl, false);
+ gca_ColorsAttr.rewind();
+ }
+ fboDirty = true;
+ }
+
+ @Override
+ protected final void pushVertex(final float[] coords, final float[] texParams, final float[] rgba) {
+ gca_VerticesAttr.putf(coords[0]);
+ gca_VerticesAttr.putf(coords[1]);
+ gca_VerticesAttr.putf(coords[2]);
+
+ gca_CurveParamsAttr.putf(texParams[0]);
+ gca_CurveParamsAttr.putf(texParams[1]);
+ gca_CurveParamsAttr.putf(texParams[2]);
+
+ if( null != gca_ColorsAttr ) {
+ if( null != rgba ) {
+ gca_ColorsAttr.putf(rgba[0]);
+ gca_ColorsAttr.putf(rgba[1]);
+ gca_ColorsAttr.putf(rgba[2]);
+ gca_ColorsAttr.putf(rgba[3]);
+ } else {
+ throw new IllegalArgumentException("Null color given for COLOR_CHANNEL rendering mode");
+ }
+ }
+ }
+
+ @Override
+ protected final void pushIndex(final int idx) {
+ indicesBuffer.puts((short)idx);
+ }
+
+ @Override
+ protected void updateImpl(final GL2ES2 gl) {
+ // seal buffers
+ indicesBuffer.seal(gl, true);
+ indicesBuffer.enableBuffer(gl, false);
+ gca_CurveParamsAttr.seal(gl, true);
+ gca_CurveParamsAttr.enableBuffer(gl, false);
+ gca_VerticesAttr.seal(gl, true);
+ gca_VerticesAttr.enableBuffer(gl, false);
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.seal(gl, true);
+ gca_ColorsAttr.enableBuffer(gl, false);
+ }
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+ final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture();
+ final Texture tex = frame.getTexture();
+ final TextureCoords tc = tex.getImageTexCoords();
+ final float tcSx = 1f / ( tc.right() - tc.left() );
+ colorTexBBox[0] = box.getMinX() * tcSx;
+ colorTexBBox[2] = box.getMaxX() * tcSx;
+ if( tex.getMustFlipVertically() ) {
+ final float tcSy = 1f / ( tc.bottom() - tc.top() );
+ colorTexBBox[1] = box.getMaxY() * tcSy;
+ colorTexBBox[3] = box.getMinY() * tcSy;
+ } else {
+ final float tcSy = 1f / ( tc.top() - tc.bottom() );
+ colorTexBBox[1] = box.getMinY() * tcSy;
+ colorTexBBox[3] = box.getMaxY() * tcSy;
+ }
+ }
+ gca_FboVerticesAttr.seal(gl, false);
+ {
+ final FloatBuffer fb = (FloatBuffer)gca_FboVerticesAttr.getBuffer();
+ fb.put( 2, box.getMinZ());
+ fb.put( 5, box.getMinZ());
+ fb.put( 8, box.getMinZ());
+ fb.put(11, box.getMinZ());
+ }
+ // Pending gca_FboVerticesAttr-seal and fboPMVMatrix-setup, follow fboDirty
+
+ // push data 2 GPU ..
+ indicesFbo.seal(gl, true);
+ indicesFbo.enableBuffer(gl, false);
+
+ fboDirty = true;
+ // the buffers were disabled, since due to real/fbo switching and other vbo usage
+ }
+
+ private final AABBox drawWinBox = new AABBox();
+ private final int[] drawView = new int[] { 0, 0, 0, 0 };
+ private final float[] drawVec4Tmp0 = new float[4];
+ private final float[] drawVec4Tmp1 = new float[4];
+ private final float[] drawVec4Tmp2 = new float[4];
+ private final float[] drawMat4PMv = new float[16];
+ private static final int border = 2; // surrounding border, i.e. width += 2*border, height +=2*border
+
+ @Override
+ protected void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int[/*1*/] sampleCount) {
+ if( 0 >= indicesBuffer.getElementCount() ) {
+ if(DEBUG_INSTANCE) {
+ System.err.printf("VBORegion2PVBAAES2.drawImpl: Empty%n");
+ }
+ return; // empty!
+ }
+ if( Float.isInfinite(box.getWidth()) || Float.isInfinite(box.getHeight()) ) {
+ if(DEBUG_INSTANCE) {
+ System.err.printf("VBORegion2PVBAAES2.drawImpl: Inf %s%n", box);
+ }
+ return; // inf
+ }
+ final int vpWidth = renderer.getWidth();
+ final int vpHeight = renderer.getHeight();
+ if(vpWidth <=0 || vpHeight <= 0 || null==sampleCount || sampleCount[0] <= 0){
+ renderRegion(gl);
+ } else {
+ if(0 > maxTexSize[0]) {
+ gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, maxTexSize, 0);
+ }
+ final RenderState rs = renderer.getRenderState();
+ final float winWidth, winHeight;
+
+ final float ratioObjWinWidth, ratioObjWinHeight;
+ final float diffObjWidth, diffObjHeight;
+ final float diffObjBorderWidth, diffObjBorderHeight;
+ int targetFboWidth, targetFboHeight;
+ {
+ final float diffWinWidth, diffWinHeight;
+ final int targetWinWidth, targetWinHeight;
+
+ // Calculate perspective pixel width/height for FBO,
+ // considering the sampleCount.
+ drawView[2] = vpWidth;
+ drawView[3] = vpHeight;
+
+ renderer.getMatrix().multPMvMatrixf(drawMat4PMv, 0);
+ box.mapToWindow(drawWinBox, drawMat4PMv, drawView, true /* useCenterZ */,
+ drawVec4Tmp0, drawVec4Tmp1, drawVec4Tmp2);
+
+ winWidth = drawWinBox.getWidth();
+ winHeight = drawWinBox.getHeight();
+ targetWinWidth = (int)Math.ceil(winWidth);
+ targetWinHeight = (int)Math.ceil(winHeight);
+ diffWinWidth = targetWinWidth-winWidth;
+ diffWinHeight = targetWinHeight-winHeight;
+
+ ratioObjWinWidth = box.getWidth() / winWidth;
+ ratioObjWinHeight= box.getHeight() / winHeight;
+ diffObjWidth = diffWinWidth * ratioObjWinWidth;
+ diffObjHeight = diffWinHeight * ratioObjWinHeight;
+ diffObjBorderWidth = border * ratioObjWinWidth;
+ diffObjBorderHeight = border * ratioObjWinHeight;
+
+ targetFboWidth = (targetWinWidth+2*border)*sampleCount[0];
+ targetFboHeight = (targetWinHeight+2*border)*sampleCount[0];
+
+ if( DEBUG_FBO_2 ) {
+ final float ratioWinWidth, ratioWinHeight;
+ ratioWinWidth = winWidth/targetWinWidth;
+ ratioWinHeight = winHeight/targetWinHeight;
+ final float renderFboWidth, renderFboHeight;
+ renderFboWidth = (winWidth+2*border)*sampleCount[0];
+ renderFboHeight = (winHeight+2*border)*sampleCount[0];
+ final float ratioFboWidth, ratioFboHeight;
+ ratioFboWidth = renderFboWidth/targetFboWidth;
+ ratioFboHeight = renderFboHeight/targetFboHeight;
+ final float diffFboWidth, diffFboHeight;
+ diffFboWidth = targetFboWidth-renderFboWidth;
+ diffFboHeight = targetFboHeight-renderFboHeight;
+
+ System.err.printf("XXX.MinMax obj %s%n", box.toString());
+ System.err.printf("XXX.MinMax obj d[%.3f, %.3f], r[%f, %f], b[%f, %f]%n",
+ diffObjWidth, diffObjHeight, ratioObjWinWidth, ratioObjWinWidth, diffObjBorderWidth, diffObjBorderHeight);
+ System.err.printf("XXX.MinMax win %s%n", drawWinBox.toString());
+ System.err.printf("XXX.MinMax view[%d, %d] -> win[%.3f, %.3f], i[%d x %d], d[%.3f, %.3f], r[%f, %f]: FBO f[%.3f, %.3f], i[%d x %d], d[%.3f, %.3f], r[%f, %f], samples %d%n",
+ drawView[2], drawView[3],
+ winWidth, winHeight, targetWinWidth, targetWinHeight, diffWinWidth,
+ diffWinHeight, ratioWinWidth, ratioWinHeight,
+ renderFboWidth, renderFboHeight, targetFboWidth, targetFboHeight,
+ diffFboWidth, diffFboHeight, ratioFboWidth, ratioFboHeight,
+ sampleCount[0]);
+ }
+ }
+ if( 0 >= targetFboWidth || 0 >= targetFboHeight ) {
+ // Nothing ..
+ return;
+ }
+ final int deltaFboWidth = Math.abs(targetFboWidth-fboWidth);
+ final int deltaFboHeight = Math.abs(targetFboHeight-fboHeight);
+ final boolean hasDelta = 0!=deltaFboWidth || 0!=deltaFboHeight;
+ if( DEBUG_FBO_2 ) {
+ System.err.printf("XXX.maxDelta: hasDelta %b: %d / %d, %.3f, %.3f%n",
+ hasDelta, deltaFboWidth, deltaFboHeight, (float)deltaFboWidth/fboWidth, (float)deltaFboHeight/fboHeight);
+ System.err.printf("XXX.Scale %d * [%f x %f]: %d x %d%n",
+ sampleCount[0], winWidth, winHeight, targetFboWidth, targetFboHeight);
+ }
+ if( hasDelta || fboDirty || isShapeDirty() || null == fbo ) {
+ final int maxLength = Math.max(targetFboWidth, targetFboHeight);
+ if( maxLength > maxTexSize[0] ) {
+ if( targetFboWidth > targetFboHeight ) {
+ sampleCount[0] = (int)Math.floor(maxTexSize[0] / (winWidth+2*border));
+ } else {
+ sampleCount[0] = (int)Math.floor(maxTexSize[0] / (winHeight+2*border));
+ }
+ final float renderFboWidth, renderFboHeight;
+ renderFboWidth = (winWidth+2*border)*sampleCount[0];
+ renderFboHeight = (winWidth+2*border)*sampleCount[0];
+ targetFboWidth = (int)Math.ceil(renderFboWidth);
+ targetFboHeight = (int)Math.ceil(renderFboHeight);
+ if( DEBUG_FBO_1 ) {
+ System.err.printf("XXX.Rescale (MAX): win[%.3f, %.3f]: FBO f[%.3f, %.3f], i[%d x %d], msaa %d%n",
+ winWidth, winHeight,
+ renderFboWidth, renderFboHeight, targetFboWidth, targetFboHeight, sampleCount[0]);
+ }
+ if( sampleCount[0] <= 0 ) {
+ // Last way out!
+ renderRegion(gl);
+ return;
+ }
+ }
+
+ final int newFboWidth, newFboHeight, resizeCase;
+ if( 0 >= RESIZE_BOUNDARY ) {
+ // Resize w/o optimization
+ newFboWidth = targetFboWidth;
+ newFboHeight = targetFboHeight;
+ resizeCase = 0;
+ } else {
+ if( 0 >= fboWidth || 0 >= fboHeight || null == fbo ) {
+ // Case: New FBO
+ newFboWidth = targetFboWidth;
+ newFboHeight = targetFboHeight;
+ resizeCase = 1;
+ } else if( targetFboWidth > fboWidth || targetFboHeight > fboHeight ) {
+ // Case: Inscrease FBO Size, add boundary/2 if avail
+ newFboWidth = ( targetFboWidth + RESIZE_BOUNDARY/2 < maxTexSize[0] ) ? targetFboWidth + RESIZE_BOUNDARY/2 : targetFboWidth;
+ newFboHeight = ( targetFboHeight+ RESIZE_BOUNDARY/2 < maxTexSize[0] ) ? targetFboHeight + RESIZE_BOUNDARY/2 : targetFboHeight;
+ resizeCase = 2;
+ } else if( targetFboWidth < fboWidth && targetFboHeight < fboHeight &&
+ fboWidth - targetFboWidth < RESIZE_BOUNDARY &&
+ fboHeight - targetFboHeight < RESIZE_BOUNDARY ) {
+ // Case: Decreased FBO Size Request within boundary
+ newFboWidth = fboWidth;
+ newFboHeight = fboHeight;
+ resizeCase = 3;
+ } else {
+ // Case: Decreased-Size-Beyond-Boundary or No-Resize
+ newFboWidth = targetFboWidth;
+ newFboHeight = targetFboHeight;
+ resizeCase = 4;
+ }
+ }
+ final int dResizeWidth = newFboWidth - targetFboWidth;
+ final int dResizeHeight = newFboHeight - targetFboHeight;
+ final float diffObjResizeWidth = dResizeWidth*ratioObjWinWidth;
+ final float diffObjResizeHeight = dResizeHeight*ratioObjWinHeight;
+ if( DEBUG_FBO_1 ) {
+ System.err.printf("XXX.resizeFBO: case %d, has %dx%d > target %dx%d, resize: i[%d x %d], f[%.3f x %.3f] -> %dx%d%n",
+ resizeCase, fboWidth, fboHeight, targetFboWidth, targetFboHeight,
+ dResizeWidth, dResizeHeight, diffObjResizeWidth, diffObjResizeHeight,
+ newFboWidth, newFboHeight);
+ }
+
+ final float minX = box.getMinX()-diffObjBorderWidth;
+ final float minY = box.getMinY()-diffObjBorderHeight;
+ final float maxX = box.getMaxX()+diffObjBorderWidth+diffObjWidth+diffObjResizeWidth;
+ final float maxY = box.getMaxY()+diffObjBorderHeight+diffObjHeight+diffObjResizeHeight;
+ gca_FboVerticesAttr.seal(false);
+ {
+ final FloatBuffer fb = (FloatBuffer)gca_FboVerticesAttr.getBuffer();
+ fb.put(0, minX); fb.put( 1, minY);
+ fb.put(3, minX); fb.put( 4, maxY);
+ fb.put(6, maxX); fb.put( 7, maxY);
+ fb.put(9, maxX); fb.put(10, minY);
+ fb.position(12);
+ }
+ gca_FboVerticesAttr.seal(true);
+ FloatUtil.makeOrtho(pmvMatrix02, 0, true, minX, maxX, minY, maxY, -1, 1);
+ useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
+ renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, newFboWidth, newFboHeight, vpWidth, vpHeight, sampleCount[0]);
+ } else if( isStateDirty() ) {
+ useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
+ renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, fboWidth, fboHeight, vpWidth, vpHeight, sampleCount[0]);
+ }
+ useShaderProgram(gl, renderer, getRenderModes(), false, getQuality(), sampleCount[0]);
+ renderFBO(gl, rs, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount[0]);
+ }
+ }
+
+ private void renderFBO(final GL2ES2 gl, final RenderState rs, final int targetFboWidth, final int targetFboHeight,
+ final int vpWidth, final int vpHeight, final int sampleCount) {
+ gl.glViewport(0, 0, vpWidth, vpHeight);
+
+ if( rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
+ // RGB is already multiplied w/ alpha via renderRegion2FBO(..)
+ gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ gl.glUniform(gcu_FboTexSize);
+
+ gl.glActiveTexture(GL.GL_TEXTURE0 + gcu_FboTexUnit.intValue());
+
+ fbo.use(gl, texA);
+ gca_FboVerticesAttr.enableBuffer(gl, true);
+ gca_FboTexCoordsAttr.enableBuffer(gl, true);
+ indicesFbo.bindBuffer(gl, true); // keeps VBO binding
+
+ gl.glDrawElements(GL.GL_TRIANGLES, indicesFbo.getElementCount() * indicesFbo.getComponentCount(), GL.GL_UNSIGNED_SHORT, 0);
+
+ indicesFbo.bindBuffer(gl, false);
+ gca_FboTexCoordsAttr.enableBuffer(gl, false);
+ gca_FboVerticesAttr.enableBuffer(gl, false);
+ fbo.unuse(gl);
+
+ // setback: gl.glActiveTexture(currentActiveTextureEngine[0]);
+ }
+
+ private void renderRegion2FBO(final GL2ES2 gl, final RenderState rs,
+ final int targetFboWidth, final int targetFboHeight, final int newFboWidth, final int newFboHeight,
+ final int vpWidth, final int vpHeight, final int sampleCount) {
+ if( 0 >= targetFboWidth || 0 >= targetFboHeight ) {
+ throw new IllegalArgumentException("fboSize must be greater than 0: "+targetFboWidth+"x"+targetFboHeight);
+ }
+
+ final boolean blendingEnabled = rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED);
+
+ if(null == fbo) {
+ fboWidth = newFboWidth;
+ fboHeight = newFboHeight;
+ final FloatBuffer fboTexSize = (FloatBuffer) gcu_FboTexSize.getBuffer();
+ {
+ fboTexSize.put(0, fboWidth);
+ fboTexSize.put(1, fboHeight);
+ }
+ fbo = new FBObject();
+ fbo.init(gl, fboWidth, fboHeight, 0);
+ // Shall not use bilinear (GL_LINEAR), due to own VBAA. Result is smooth w/o it now!
+ // FIXME: FXAA requires bilinear filtering!
+ // texA = fbo.attachTexture2D(gl, 0, true, GL.GL_LINEAR, GL.GL_LINEAR, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ texA = fbo.attachTexture2D(gl, 0, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ if( !blendingEnabled ) {
+ // no depth-buffer w/ blending
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS);
+ }
+ if( DEBUG_FBO_1 ) {
+ System.err.printf("XXX.createFBO: %dx%d%n%s%n", fboWidth, fboHeight, fbo.toString());
+ }
+ } else if( newFboWidth != fboWidth || newFboHeight != fboHeight ) {
+ fbo.reset(gl, newFboWidth, newFboHeight, 0);
+ fbo.bind(gl);
+ if( DEBUG_FBO_1 ) {
+ System.err.printf("XXX.resetFBO: %dx%d -> %dx%d, target %dx%d%n", fboWidth, fboHeight, newFboWidth, newFboHeight, targetFboWidth, targetFboHeight);
+ }
+ fboWidth = newFboWidth;
+ fboHeight = newFboHeight;
+ final FloatBuffer fboTexSize = (FloatBuffer) gcu_FboTexSize.getBuffer();
+ {
+ fboTexSize.put(0, fboWidth);
+ fboTexSize.put(1, fboHeight);
+ }
+ } else {
+ fbo.bind(gl);
+ }
+
+ //render texture
+ gl.glViewport(0, 0, fboWidth, fboHeight);
+ if( blendingEnabled ) {
+ gl.glClearColor(0f, 0f, 0f, 0.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT); // no depth-buffer w/ blending
+ // For already pre-multiplied alpha values, use:
+ // gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+
+ // Multiply RGB w/ Alpha, preserve alpha for renderFBO(..)
+ gl.glBlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+
+ renderRegion(gl);
+
+ fbo.unbind(gl);
+ fboDirty = false;
+ }
+
+ private void renderRegion(final GL2ES2 gl) {
+ gl.glUniform(gcu_PMVMatrix02);
+
+ gca_VerticesAttr.enableBuffer(gl, true);
+ gca_CurveParamsAttr.enableBuffer(gl, true);
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.enableBuffer(gl, true);
+ }
+ indicesBuffer.bindBuffer(gl, true); // keeps VBO binding
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+ final TextureSequence.TextureFrame frame = colorTexSeq.getNextTexture(gl);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + colorTexSeq.getTextureUnit());
+ final Texture tex = frame.getTexture();
+ tex.bind(gl);
+ tex.enable(gl); // nop on core
+ gcu_ColorTexUnit.setData(colorTexSeq.getTextureUnit());
+ gl.glUniform(gcu_ColorTexUnit); // Always update, since program maybe used by multiple regions
+ gl.glUniform(gcu_ColorTexBBox); // Always update, since program maybe used by multiple regions
+ gl.glDrawElements(GL.GL_TRIANGLES, indicesBuffer.getElementCount() * indicesBuffer.getComponentCount(), GL.GL_UNSIGNED_SHORT, 0);
+ tex.disable(gl); // nop on core
+ } else {
+ gl.glDrawElements(GL.GL_TRIANGLES, indicesBuffer.getElementCount() * indicesBuffer.getComponentCount(), GL.GL_UNSIGNED_SHORT, 0);
+ }
+
+ indicesBuffer.bindBuffer(gl, false);
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.enableBuffer(gl, false);
+ }
+ gca_CurveParamsAttr.enableBuffer(gl, false);
+ gca_VerticesAttr.enableBuffer(gl, false);
+ }
+
+ @Override
+ protected void destroyImpl(final GL2ES2 gl) {
+ if(DEBUG_INSTANCE) {
+ System.err.println("VBORegion2PES2 Destroy: " + this);
+ // Thread.dumpStack();
+ }
+ if(null != fbo) {
+ fbo.destroy(gl);
+ fbo = null;
+ texA = null;
+ }
+ if(null != gca_VerticesAttr) {
+ gca_VerticesAttr.destroy(gl);
+ gca_VerticesAttr = null;
+ }
+ if(null != gca_CurveParamsAttr) {
+ gca_CurveParamsAttr.destroy(gl);
+ gca_CurveParamsAttr = null;
+ }
+ if(null != gca_ColorsAttr) {
+ gca_ColorsAttr.destroy(gl);
+ gca_ColorsAttr = null;
+ }
+ if(null != indicesBuffer) {
+ indicesBuffer.destroy(gl);
+ indicesBuffer = null;
+ }
+
+ if(null != gca_FboVerticesAttr) {
+ gca_FboVerticesAttr.destroy(gl);
+ gca_FboVerticesAttr = null;
+ }
+ if(null != gca_FboTexCoordsAttr) {
+ gca_FboTexCoordsAttr.destroy(gl);
+ gca_FboTexCoordsAttr = null;
+ }
+ if(null != indicesFbo) {
+ indicesFbo.destroy(gl);
+ indicesFbo = null;
+ }
+ spPass1 = null;
+ spPass2 = null;
+ }
+}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java
index 14ff0380f..46e991866 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java
@@ -27,134 +27,258 @@
*/
package jogamp.graph.curve.opengl;
+import java.nio.FloatBuffer;
+
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLUniformData;
import jogamp.graph.curve.opengl.shader.AttributeNames;
+import jogamp.graph.curve.opengl.shader.UniformNames;
+import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.geom.Triangle;
import com.jogamp.opengl.util.GLArrayDataServer;
-import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
+import com.jogamp.opengl.util.texture.TextureSequence;
public class VBORegionSPES2 extends GLRegion {
- private GLArrayDataServer verticeAttr = null;
- private GLArrayDataServer texCoordAttr = null;
- private GLArrayDataServer indices = null;
+ private final RenderState.ProgramLocal rsLocal;
+
+ private GLArrayDataServer gca_VerticesAttr = null;
+ private GLArrayDataServer gca_CurveParamsAttr = null;
+ private GLArrayDataServer gca_ColorsAttr;
+ private GLArrayDataServer indicesBuffer = null;
+ private final GLUniformData gcu_ColorTexUnit;
+ private final float[] colorTexBBox; // x0, y0, x1, y1
+ private final GLUniformData gcu_ColorTexBBox;
+ private ShaderProgram spPass1 = null;
+
+ public VBORegionSPES2(final int renderModes, final TextureSequence colorTexSeq) {
+ super(renderModes, colorTexSeq);
+
+ rsLocal = new RenderState.ProgramLocal();
+
+ final int initialElementCount = 256;
+ indicesBuffer = GLArrayDataServer.createData(3, GL.GL_SHORT, initialElementCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
+
+ gca_VerticesAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL.GL_FLOAT,
+ false, initialElementCount, GL.GL_STATIC_DRAW);
- protected VBORegionSPES2(int renderModes) {
- super(renderModes);
+ gca_CurveParamsAttr = GLArrayDataServer.createGLSL(AttributeNames.CURVEPARAMS_ATTR_NAME, 3, GL.GL_FLOAT,
+ false, initialElementCount, GL.GL_STATIC_DRAW);
+
+ if( hasColorChannel() ) {
+ gca_ColorsAttr = GLArrayDataServer.createGLSL(AttributeNames.COLOR_ATTR_NAME, 4, GL.GL_FLOAT,
+ false, initialElementCount, GL.GL_STATIC_DRAW);
+ } else {
+ gca_ColorsAttr = null;
+ }
+ if( hasColorTexture() ) {
+ gcu_ColorTexUnit = new GLUniformData(UniformNames.gcu_ColorTexUnit, colorTexSeq.getTextureUnit());
+ colorTexBBox = new float[4];
+ gcu_ColorTexBBox = new GLUniformData(UniformNames.gcu_ColorTexBBox, 4, FloatBuffer.wrap(colorTexBBox));
+ } else {
+ gcu_ColorTexUnit = null;
+ colorTexBBox = null;
+ gcu_ColorTexBBox = null;
+ }
}
- protected void update(GL2ES2 gl, RenderState rs) {
- if(!isDirty()) {
- return;
+ @Override
+ protected final void clearImpl(final GL2ES2 gl) {
+ if(DEBUG_INSTANCE) {
+ System.err.println("VBORegionSPES2 Clear: " + this);
+ }
+ if( null != indicesBuffer ) {
+ indicesBuffer.seal(gl, false);
+ indicesBuffer.rewind();
+ }
+ if( null != gca_VerticesAttr ) {
+ gca_VerticesAttr.seal(gl, false);
+ gca_VerticesAttr.rewind();
}
+ if( null != gca_CurveParamsAttr ) {
+ gca_CurveParamsAttr.seal(gl, false);
+ gca_CurveParamsAttr.rewind();
+ }
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.seal(gl, false);
+ gca_ColorsAttr.rewind();
+ }
+ }
- if(null == indices) {
- final int initialElementCount = 256;
- final ShaderState st = rs.getShaderState();
+ @Override
+ protected final void pushVertex(final float[] coords, final float[] texParams, final float[] rgba) {
+ gca_VerticesAttr.putf(coords[0]);
+ gca_VerticesAttr.putf(coords[1]);
+ gca_VerticesAttr.putf(coords[2]);
- indices = GLArrayDataServer.createData(3, GL2ES2.GL_SHORT, initialElementCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
+ gca_CurveParamsAttr.putf(texParams[0]);
+ gca_CurveParamsAttr.putf(texParams[1]);
+ gca_CurveParamsAttr.putf(texParams[2]);
- verticeAttr = GLArrayDataServer.createGLSL(AttributeNames.VERTEX_ATTR_NAME, 3, GL2ES2.GL_FLOAT,
- false, initialElementCount, GL.GL_STATIC_DRAW);
- st.ownAttribute(verticeAttr, true);
+ if( null != gca_ColorsAttr ) {
+ if( null != rgba ) {
+ gca_ColorsAttr.putf(rgba[0]);
+ gca_ColorsAttr.putf(rgba[1]);
+ gca_ColorsAttr.putf(rgba[2]);
+ gca_ColorsAttr.putf(rgba[3]);
+ } else {
+ throw new IllegalArgumentException("Null color given for COLOR_CHANNEL rendering mode");
+ }
+ }
+ }
- texCoordAttr = GLArrayDataServer.createGLSL(AttributeNames.TEXCOORD_ATTR_NAME, 2, GL2ES2.GL_FLOAT,
- false, initialElementCount, GL.GL_STATIC_DRAW);
- st.ownAttribute(texCoordAttr, true);
+ @Override
+ protected final void pushIndex(final int idx) {
+ indicesBuffer.puts((short)idx);
+ }
- if(DEBUG_INSTANCE) {
- System.err.println("VBORegionSPES2 Create: " + this);
+ @Override
+ protected void updateImpl(final GL2ES2 gl) {
+ // seal buffers
+ gca_VerticesAttr.seal(gl, true);
+ gca_VerticesAttr.enableBuffer(gl, false);
+ gca_CurveParamsAttr.seal(gl, true);
+ gca_CurveParamsAttr.enableBuffer(gl, false);
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.seal(gl, true);
+ gca_ColorsAttr.enableBuffer(gl, false);
+ }
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+ final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture();
+ final Texture tex = frame.getTexture();
+ final TextureCoords tc = tex.getImageTexCoords();
+ final float tcSx = 1f / ( tc.right() - tc.left() );
+ colorTexBBox[0] = box.getMinX() * tcSx;
+ colorTexBBox[2] = box.getMaxX() * tcSx;
+ final float tcSy;
+ if( tex.getMustFlipVertically() ) {
+ tcSy = 1f / ( tc.bottom() - tc.top() );
+ colorTexBBox[1] = box.getMaxY() * tcSy;
+ colorTexBBox[3] = box.getMinY() * tcSy;
+ } else {
+ tcSy = 1f / ( tc.top() - tc.bottom() );
+ colorTexBBox[1] = box.getMinY() * tcSy;
+ colorTexBBox[3] = box.getMaxY() * tcSy;
}
}
+ indicesBuffer.seal(gl, true);
+ indicesBuffer.enableBuffer(gl, false);
+ if(DEBUG_INSTANCE) {
+ System.err.println("VBORegionSPES2 idx "+indicesBuffer);
+ System.err.println("VBORegionSPES2 ver "+gca_VerticesAttr);
+ System.err.println("VBORegionSPES2 tex "+gca_CurveParamsAttr);
+ }
+ }
- // process triangles
- indices.seal(gl, false);
- indices.rewind();
- for(int i=0; i<triangles.size(); i++) {
- final Triangle t = triangles.get(i);
- final Vertex[] t_vertices = t.getVertices();
+ private static final boolean throwOnError = false; // FIXME
+ /**
+ * <p>
+ * Since multiple {@link Region}s may share one
+ * {@link ShaderProgram}, the uniform data must always be updated.
+ * </p>
+ *
+ * @param gl
+ * @param renderer
+ * @param renderModes
+ * @param quality
+ */
+ public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final int quality) {
+ final RenderState rs = renderer.getRenderState();
+ final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, true, quality, 0, colorTexSeq);
+ final ShaderProgram sp = renderer.getRenderState().getShaderProgram();
+ final boolean updateLocLocal = !sp.equals(spPass1);
+ spPass1 = sp;
+ if( DEBUG ) {
+ System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal);
+ }
+ if( updateLocLocal ) {
+ rs.updateAttributeLoc(gl, true, gca_VerticesAttr, throwOnError);
+ rs.updateAttributeLoc(gl, true, gca_CurveParamsAttr, throwOnError);
+ if( null != gca_ColorsAttr ) {
+ rs.updateAttributeLoc(gl, true, gca_ColorsAttr, throwOnError);
+ }
+ }
+ rsLocal.update(gl, rs, updateLocLocal, renderModes, true, throwOnError);
+ if( null != gcu_ColorTexUnit ) {
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, throwOnError);
+ rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexBBox, throwOnError);
+ }
+ }
- if(t_vertices[0].getId() == Integer.MAX_VALUE){
- t_vertices[0].setId(numVertices++);
- t_vertices[1].setId(numVertices++);
- t_vertices[2].setId(numVertices++);
- vertices.add(t_vertices[0]);
- vertices.add(t_vertices[1]);
- vertices.add(t_vertices[2]);
+ @Override
+ protected void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int[/*1*/] sampleCount) {
+ final int renderModes = getRenderModes();
+ useShaderProgram(gl, renderer, renderModes, getQuality());
- indices.puts((short) t_vertices[0].getId());
- indices.puts((short) t_vertices[1].getId());
- indices.puts((short) t_vertices[2].getId());
- } else {
- indices.puts((short) t_vertices[0].getId());
- indices.puts((short) t_vertices[1].getId());
- indices.puts((short) t_vertices[2].getId());
+ if( 0 >= indicesBuffer.getElementCount() ) {
+ if(DEBUG_INSTANCE) {
+ System.err.printf("VBORegionSPES2.drawImpl: Empty%n");
}
+ return; // empty!
}
- indices.seal(gl, true);
- indices.enableBuffer(gl, false);
-
- // process vertices and update bbox
- box.reset();
- verticeAttr.seal(gl, false);
- verticeAttr.rewind();
- texCoordAttr.seal(gl, false);
- texCoordAttr.rewind();
- for(int i=0; i<vertices.size(); i++) {
- final Vertex v = vertices.get(i);
- verticeAttr.putf(v.getX());
- verticeAttr.putf(v.getY());
- verticeAttr.putf(v.getZ());
- box.resize(v.getX(), v.getY(), v.getZ());
-
- final float[] tex = v.getTexCoord();
- texCoordAttr.putf(tex[0]);
- texCoordAttr.putf(tex[1]);
- }
- verticeAttr.seal(gl, true);
- verticeAttr.enableBuffer(gl, false);
- texCoordAttr.seal(gl, true);
- texCoordAttr.enableBuffer(gl, false);
-
- setDirty(false);
- }
+ gca_VerticesAttr.enableBuffer(gl, true);
+ gca_CurveParamsAttr.enableBuffer(gl, true);
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.enableBuffer(gl, true);
+ }
+ indicesBuffer.bindBuffer(gl, true); // keeps VBO binding
- protected void drawImpl(GL2ES2 gl, RenderState rs, int vp_width, int vp_height, int[/*1*/] texWidth) {
- verticeAttr.enableBuffer(gl, true);
- texCoordAttr.enableBuffer(gl, true);
- indices.enableBuffer(gl, true);
+ if( renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
+ gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
+ }
- gl.glDrawElements(GL2ES2.GL_TRIANGLES, indices.getElementCount() * indices.getComponentCount(), GL2ES2.GL_UNSIGNED_SHORT, 0);
+ if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+ final TextureSequence.TextureFrame frame = colorTexSeq.getNextTexture(gl);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + colorTexSeq.getTextureUnit());
+ final Texture tex = frame.getTexture();
+ tex.bind(gl);
+ tex.enable(gl); // nop on core
+ gcu_ColorTexUnit.setData(colorTexSeq.getTextureUnit());
+ gl.glUniform(gcu_ColorTexUnit); // Always update, since program maybe used by multiple regions
+ gl.glUniform(gcu_ColorTexBBox); // Always update, since program maybe used by multiple regions
+ gl.glDrawElements(GL.GL_TRIANGLES, indicesBuffer.getElementCount() * indicesBuffer.getComponentCount(), GL.GL_UNSIGNED_SHORT, 0);
+ tex.disable(gl); // nop on core
+ } else {
+ gl.glDrawElements(GL.GL_TRIANGLES, indicesBuffer.getElementCount() * indicesBuffer.getComponentCount(), GL.GL_UNSIGNED_SHORT, 0);
+ }
- verticeAttr.enableBuffer(gl, false);
- texCoordAttr.enableBuffer(gl, false);
- indices.enableBuffer(gl, false);
- }
+ indicesBuffer.bindBuffer(gl, false);
+ if( null != gca_ColorsAttr ) {
+ gca_ColorsAttr.enableBuffer(gl, false);
+ }
+ gca_CurveParamsAttr.enableBuffer(gl, false);
+ gca_VerticesAttr.enableBuffer(gl, false);
+ }
- public final void destroy(GL2ES2 gl, RenderState rs) {
+ @Override
+ protected void destroyImpl(final GL2ES2 gl) {
if(DEBUG_INSTANCE) {
System.err.println("VBORegionSPES2 Destroy: " + this);
- }
- final ShaderState st = rs.getShaderState();
- if(null != verticeAttr) {
- st.ownAttribute(verticeAttr, false);
- verticeAttr.destroy(gl);
- verticeAttr = null;
- }
- if(null != texCoordAttr) {
- st.ownAttribute(texCoordAttr, false);
- texCoordAttr.destroy(gl);
- texCoordAttr = null;
- }
- if(null != indices) {
- indices.destroy(gl);
- indices = null;
- }
- }
+ }
+ if(null != gca_VerticesAttr) {
+ gca_VerticesAttr.destroy(gl);
+ gca_VerticesAttr = null;
+ }
+ if(null != gca_CurveParamsAttr) {
+ gca_CurveParamsAttr.destroy(gl);
+ gca_CurveParamsAttr = null;
+ }
+ if(null != gca_ColorsAttr) {
+ gca_ColorsAttr.destroy(gl);
+ gca_ColorsAttr = null;
+ }
+ if(null != indicesBuffer) {
+ indicesBuffer.destroy(gl);
+ indicesBuffer = null;
+ }
+ spPass1 = null;
+ }
}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/AttributeNames.java b/src/jogl/classes/jogamp/graph/curve/opengl/shader/AttributeNames.java
index 8a109c34a..dff536645 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/AttributeNames.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/AttributeNames.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -28,18 +28,23 @@
package jogamp.graph.curve.opengl.shader;
public class AttributeNames {
- /** The vertices index in an OGL object
+ /**
+ * The vertices index in an OGL object
*/
- public static final int VERTEX_ATTR_IDX = 0; // FIXME: AMD needs this to be location 0 ? hu ?
public static final String VERTEX_ATTR_NAME = "gca_Vertices";
- /** The Texture Coord index in an OGL object
+ /**
+ * The Texture Coord index in an OGL object
*/
- public static final int TEXCOORD_ATTR_IDX = 1;
- public static final String TEXCOORD_ATTR_NAME = "gca_TexCoords";
-
- /** The color index in an OGL object
+ public static final String CURVEPARAMS_ATTR_NAME = "gca_CurveParams";
+
+ /**
+ * The color index in an OGL object
*/
- public static final int COLOR_ATTR_IDX = 2;
- public static final String COLOR_ATTR_NAME = "gca_Colors";
+ public static final String COLOR_ATTR_NAME = "gca_Colors";
+
+ public static final String FBO_VERTEX_ATTR_NAME = "gca_FboVertices";
+
+ public static final String FBO_TEXCOORDS_ATTR_NAME = "gca_FboTexCoords";
+
}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/UniformNames.java b/src/jogl/classes/jogamp/graph/curve/opengl/shader/UniformNames.java
index ab6e0dc6e..7244851ff 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/UniformNames.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/UniformNames.java
@@ -1,10 +1,13 @@
package jogamp.graph.curve.opengl.shader;
public class UniformNames {
- public static final String gcu_PMVMatrix = "gcu_PMVMatrix"; // gcu_PMVMatrix[3]; // P, Mv, and Mvi
+ public static final String gcu_PMVMatrix01 = "gcu_PMVMatrix01"; // gcu_PMVMatrix[3]; // P, Mv, and Mvi
public static final String gcu_ColorStatic = "gcu_ColorStatic";
- public static final String gcu_Alpha = "gcu_Alpha";
public static final String gcu_Weight = "gcu_Weight";
- public static final String gcu_TextureUnit = "gcu_TextureUnit";
- public static final String gcu_TextureSize = "gcu_TextureSize";
+ public static final String gcu_ColorTexUnit = "gcu_ColorTexUnit";
+ public static final String gcu_ColorTexBBox = "gcu_ColorTexBBox";
+
+ public static final String gcu_PMVMatrix02 = "gcu_PMVMatrix02"; // gcu_PMVMatrix[3]; // P, Mv, and Mvi
+ public static final String gcu_FboTexUnit = "gcu_FboTexUnit";
+ public static final String gcu_FboTexSize = "gcu_FboTexSize";
}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/attributes.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/attributes.glsl
index 108247c9c..b8c68a924 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/attributes.glsl
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/attributes.glsl
@@ -4,8 +4,27 @@
// attribute vec3 gca_Vertices;
attribute vec4 gca_Vertices;
-attribute vec2 gca_TexCoords;
-//attribute vec4 gca_Colors;
+
+/**
+ * CDTriangulator2D.extractBoundaryTriangles(..):
+ * AA line (exp) : z > 0
+ * line : x == 0, y == 0
+ * hole or holeLike: 0 > y
+ * !hole : 0 < y
+ *
+ * 0 == gcv_CurveParams.x : vertex-0 of triangle
+ * 0.5 == gcv_CurveParams.x : vertex-1 of triangle
+ * 1 == gcv_CurveParams.x : vertex-2 of triangle
+ */
+attribute vec3 gca_CurveParams;
+
+attribute vec4 gca_FboVertices;
+attribute vec2 gca_FboTexCoords;
+
+#ifdef USE_COLOR_CHANNEL
+ attribute vec4 gca_Colors;
+#endif
+
//attribute vec3 gca_Normals;
#endif // attributes_glsl
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2-merged.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2-merged.vp
deleted file mode 100644
index 530b24f64..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2-merged.vp
+++ /dev/null
@@ -1,19 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#ifdef GL_ES
- precision lowp float;
- precision lowp int;
-#endif
-
-uniform mat4 gcu_PMVMatrix[3]; // P, Mv, and Mvi
-varying vec2 gcv_TexCoord;
-
-attribute vec4 gca_Vertices;
-attribute vec2 gca_TexCoords;
-
-
-void main(void)
-{
- gl_Position = gcu_PMVMatrix[0] * gcu_PMVMatrix[1] * gca_Vertices;
- gcv_TexCoord = gca_TexCoords;
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2.vp
deleted file mode 100644
index 15ce8cc2b..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2.vp
+++ /dev/null
@@ -1,9 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 100
-
-precision mediump float;
-precision mediump int;
-
-#include curverenderer01-xxx.vp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-gl2.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-gl2.vp
deleted file mode 100644
index 1ac33e8b3..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-gl2.vp
+++ /dev/null
@@ -1,6 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 110
-
-#include curverenderer01-xxx.vp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_lineAA.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_lineAA.glsl
new file mode 100644
index 000000000..79b3dd6fd
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_lineAA.glsl
@@ -0,0 +1,19 @@
+
+ // if( gcv_CurveParam.x == 10.0 && gcv_CurveParam.y == 10.0 ) {
+ if( gcv_CurveParam.z > 0.0 ) {
+ // pass-1: AA Lines
+ #if 1
+ // float dist = sqrt( gcv_CurveParam.x*gcv_CurveParam.x + gcv_CurveParam.y*gcv_CurveParam.y ); // magnitude
+ float dist = sqrt( gcv_CurveParam.y*gcv_CurveParam.y ); // magnitude
+ // float a = 1.0 - smoothstep (gcv_CurveParam.y-gcv_CurveParam.z, gcv_CurveParam.y, dist);
+ float r = gcv_CurveParam.x/3.0;
+ float wa = gcv_CurveParam.x+r;
+ float waHalf = wa/2.0;
+ float a = 1.0 - smoothstep (waHalf-2.0*r, waHalf, dist);
+ // mgl_FragColor = vec4(gcu_ColorStatic.rgb, gcu_ColorStatic.a * a);
+ mgl_FragColor = vec4(0, 0, 1.0, gcu_ColorStatic.a * a);
+ #else
+ mgl_FragColor = vec4(0, 0, 1.0, 1.0);
+ #endif
+ } else
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl
new file mode 100644
index 000000000..447242438
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl
@@ -0,0 +1,36 @@
+
+ if( gcv_CurveParam.x == 0.0 && gcv_CurveParam.y == 0.0 ) {
+ // pass-1: Lines
+#if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
+ mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcv_Color * gcu_ColorStatic;
+#elif defined(USE_COLOR_TEXTURE)
+ mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcu_ColorStatic;
+#elif defined(USE_COLOR_CHANNEL)
+ mgl_FragColor = gcv_Color * gcu_ColorStatic;
+#else
+ mgl_FragColor = gcu_ColorStatic;
+#endif
+ } else {
+ // pass-1: curves
+ vec2 rtex = vec2( abs(gcv_CurveParam.x), abs(gcv_CurveParam.y) - 0.1 );
+
+ vec2 dtx = dFdx(rtex);
+ vec2 dty = dFdy(rtex);
+
+ vec2 f = vec2((dtx.y - dtx.x + 2.0*rtex.x*dtx.x), (dty.y - dty.x + 2.0*rtex.x*dty.x));
+ float position = rtex.y - (rtex.x * (1.0 - rtex.x));
+
+ float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_CurveParam.y), 0.0, 1.0);
+#if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
+ vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+ mgl_FragColor = vec4(t.rgb * gcv_Color.rgb * gcu_ColorStatic.rgb, t.a * gcv_Color.a * gcu_ColorStatic.a * a);
+#elif defined(USE_COLOR_TEXTURE)
+ vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+ mgl_FragColor = vec4(t.rgb * gcu_ColorStatic.rgb, t.a * gcu_ColorStatic.a * a);
+#elif defined(USE_COLOR_CHANNEL)
+ mgl_FragColor = vec4(gcv_Color.rgb * gcu_ColorStatic.rgb, gcv_Color.a * gcu_ColorStatic.a * a);
+#else
+ mgl_FragColor = vec4(gcu_ColorStatic.rgb, gcu_ColorStatic.a * a);
+#endif
+ }
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl
new file mode 100644
index 000000000..fa2608365
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl
@@ -0,0 +1,47 @@
+
+ vec2 rtex = vec2( abs(gcv_CurveParam.x), abs(gcv_CurveParam.y) );
+
+ if( gcv_CurveParam.x == 0.0 && gcv_CurveParam.y == 0.0 ) {
+ // pass-1: Lines
+#if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
+ mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcv_Color * gcu_ColorStatic;
+#elif defined(USE_COLOR_TEXTURE)
+ mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcu_ColorStatic;
+#elif defined(USE_COLOR_CHANNEL)
+ mgl_FragColor = gcv_Color * gcu_ColorStatic;
+#else
+ mgl_FragColor = gcu_ColorStatic;
+#endif
+ } else if ( gcv_CurveParam.x > 0.0 && ( rtex.y > 0.0 || rtex.x == 1.0 ) ) {
+ // pass-1: curves
+ rtex.y -= 0.1;
+
+ if(rtex.y < 0.0 && gcv_CurveParam.y < 0.0) {
+ // discard; // freezes NV tegra2 compiler
+ mgl_FragColor = vec4(0);
+ } else {
+ rtex.y = max(rtex.y, 0.0); // always >= 0
+
+ vec2 dtx = dFdx(rtex);
+ vec2 dty = dFdy(rtex);
+
+ vec2 f = vec2((dtx.y - dtx.x + 2.0*rtex.x*dtx.x), (dty.y - dty.x + 2.0*rtex.x*dty.x));
+ float position = rtex.y - (rtex.x * (1.0 - rtex.x));
+
+ float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_CurveParam.y), 0.0, 1.0);
+#if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
+ vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+ mgl_FragColor = vec4(t.rgb * gcv_Color.rgb * gcu_ColorStatic.rgb, t.a * gcv_Color.a * gcu_ColorStatic.a * a);
+#elif defined(USE_COLOR_TEXTURE)
+ vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+ mgl_FragColor = vec4(t.rgb * gcu_ColorStatic.rgb, t.a * gcu_ColorStatic.a * a);
+#elif defined(USE_COLOR_CHANNEL)
+ mgl_FragColor = vec4(gcv_Color.rgb * gcu_ColorStatic.rgb, gcv_Color.a * gcu_ColorStatic.a * a);
+#else
+ mgl_FragColor = vec4(gcu_ColorStatic.rgb, gcu_ColorStatic.a * a);
+#endif
+ }
+ } else {
+ mgl_FragColor = vec4(0);
+ }
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_weight.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_weight.glsl
new file mode 100644
index 000000000..1620a9532
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_weight.glsl
@@ -0,0 +1,32 @@
+
+ if( gcv_CurveParam.x == 0.0 && gcv_CurveParam.y == 0.0 ) {
+ // pass-1: Lines
+#ifdef USE_COLOR_CHANNEL
+ mgl_FragColor = gcv_Color * gcu_ColorStatic;
+#else
+ mgl_FragColor = gcu_ColorStatic;
+#endif
+ } else {
+ // pass-1: curves
+ vec2 rtex = vec2( abs(gcv_CurveParam.x), abs(gcv_CurveParam.y) - 0.1 );
+
+ vec2 dtx = dFdx(rtex);
+ vec2 dty = dFdy(rtex);
+
+ float w = gcu_Weight;
+ float pd = ((2.0 - (2.0*w))*rtex.x*rtex.x) + 2.0*(w-1.0)*rtex.x + 1.0;
+ float position = rtex.y - ((w*rtex.x*(1.0 - rtex.x))/pd);
+
+ float aph = 2.0 - 2.0*w;
+
+ float gd = (aph*rtex.x*rtex.x + 2.0*rtex.x + 1.0)*(aph*rtex.x*rtex.x + 2.0*rtex.x + 1.0);
+ vec2 f = vec2((dtx.y - (w*dtx.x*(1.0 - 2.0*rtex.x))/gd), (dty.y - (w*dty.x*(1.0 - 2.0*rtex.x))/gd));
+
+ float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_CurveParam.y), 0.0, 1.0);
+#ifdef USE_COLOR_CHANNEL
+ mgl_FragColor = vec4(gcv_Color.rgb * gcu_ColorStatic.rgb, gcv_Color.a * gcu_ColorStatic.a * a);
+#else
+ mgl_FragColor = vec4(gcu_ColorStatic.rgb, gcu_ColorStatic.a * a);
+#endif
+ }
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp
new file mode 100644
index 000000000..c6ed4ca58
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp
@@ -0,0 +1,33 @@
+//Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+#include uniforms.glsl
+#include attributes.glsl
+#include varyings.glsl
+
+void main(void)
+{
+ gl_Position = gcu_PMVMatrix02[0] * gcu_PMVMatrix02[1] * gca_Vertices;
+#if 1
+ gcv_CurveParam = gca_CurveParams;
+#else
+ if( gcv_CurveParams.x <= -10.0 ) {
+ // vec4 tc = gcu_PMVMatrix02[0] * gcu_PMVMatrix02[1] * vec4(gca_CurveParams.xy, gca_Vertices.z, 1);
+ // gcv_CurveParams = vec3(tc.xy, gca_CurveParams.z);
+ gcv_CurveParam = gca_CurveParams;
+ } else {
+ gcv_CurveParam = gca_CurveParams;
+ }
+#endif
+#ifdef USE_COLOR_TEXTURE
+ vec2 dim = vec2(gcu_ColorTexBBox.z - gcu_ColorTexBBox.x, gcu_ColorTexBBox.w - gcu_ColorTexBBox.y);
+ gcv_ColorTexCoord = vec2(gca_Vertices.x - gcu_ColorTexBBox.x, gca_Vertices.y - gcu_ColorTexBBox.y) / dim;
+#endif
+#ifdef USE_COLOR_CHANNEL
+ gcv_Color = gca_Colors;
+#endif
+}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl
new file mode 100644
index 000000000..1872af67f
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl
@@ -0,0 +1,10 @@
+ // Pass-2: Dump Texture
+ vec4 t = texture2D(gcu_FboTexUnit, gcv_FboTexCoord.st);
+ #if 0
+ if( 0.0 == t.a ) {
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_allprop01.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_allprop01.glsl
new file mode 100644
index 000000000..436dd4ed4
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_allprop01.glsl
@@ -0,0 +1,113 @@
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels.
+
+ float sampleCount = gcu_FboTexSize.z;
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ // Not only the poles (NW, SW, ..) but the whole edge!
+ float pixelCount = sampleCount * sampleCount;
+
+ // sampleCount [0, 1, 3, 5, 7] are undefined!
+ float layerCount = ( sampleCount / 2.0 );
+
+ // sum of all integer [layerCount .. 1] -> Gauss
+ float denom = ( layerCount / 2.0 ) * ( layerCount + 1.0 );
+
+ vec2 texCoord = gcv_FboTexCoord.st;
+
+ vec4 t;
+
+ // Layer-1: SampleCount 2 -> 4x
+ t = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, -0.5))); // NW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, 0.5))); // SW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, 0.5))); // SE
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, -0.5))); // NE
+
+ t *= (layerCount - 0.0) / ( denom * 4.0 ); // weight layer 1
+
+ if( sampleCount > 2.0 ) {
+ // Layer-2: SampleCount 4 -> +12x = 16p
+ vec4 tn = vec4(0);
+ tn = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, -1.5))); // NW -> SW Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, -0.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, 0.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, 1.5))); // SW -> SE Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, 1.5))); //
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, 1.5))); //
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, 1.5))); // SE -> NE Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, 0.5))); //
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, -0.5))); //
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, -1.5))); // NE -> NW Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, -1.5))); //
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, -1.5))); // NW - 1 (closed)
+
+ t += tn * (layerCount - 1) / ( denom * 12.0 ); // weight layer 2
+
+ if( sampleCount > 4.0 ) {
+ // Layer-3: SampleCount 6 -> +20x = 36p
+ tn = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, -2.5))); // NW -> SW Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, -1.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, -0.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, 0.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, 1.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, 2.5))); // SW -> SE Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, 2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, 2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, 2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, 2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, 2.5))); // SE -> NE Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, 1.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, 0.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, -0.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, -1.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, -2.5))); // NE -> NW Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, -2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, -2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, -2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, -2.5))); // NW - 1 (closed)
+
+ t += tn * (layerCount - 2) / ( denom * 20.0 ); // weight layer 3
+
+ if( sampleCount > 6.0 ) {
+ // Layer-4: SampleCount 8 -> +28x = 64p
+ tn = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, -3.5))); // NW -> SW Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, -2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, -1.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, -0.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, 0.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, 1.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, 2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, 3.5))); // SW -> SE Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, 3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, 3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, 3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, 3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, 3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, 3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, 3.5))); // SE -> NE Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, 2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, 1.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, 0.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, -0.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, -1.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, -2.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, -3.5))); // NE -> NW Edge
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, -3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, -3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, -3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, -3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, -3.5)));
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, -3.5))); // NW - 1 (closed)
+
+ t += tn * (layerCount - 3) / ( denom * 28.0 ); // weight layer 4
+ }
+ }
+ }
+
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl
new file mode 100644
index 000000000..ba7611a06
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl
@@ -0,0 +1,96 @@
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels.
+
+ // float sample_count = gcu_FboTexSize.z;
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ // Not only the poles (NW, SW, ..) but the whole edge!
+ const float sample_weight = 1.0 / ( sample_count * sample_count );
+
+ // const vec4 tex_weights = vec4(0.075, 0.06, 0.045, 0.025);
+ vec2 texCoord = gcv_FboTexCoord.st;
+
+ vec4 t;
+
+ // SampleCount 2 -> 4x
+ t = texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-0.5, -0.5))*sample_weight; // NW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-0.5, 0.5))*sample_weight; // SW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.5, 0.5))*sample_weight; // SE
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.5, -0.5))*sample_weight; // NE
+ #if SAMPLE_COUNT > 2
+ // SampleCount 4 -> +12x = 16p
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.5, -1.5))*sample_weight; // NW -> SW Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.5, -0.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.5, 0.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.5, 1.5))*sample_weight; // SW -> SE Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-0.5, 1.5))*sample_weight; //
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.5, 1.5))*sample_weight; //
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.5, 1.5))*sample_weight; // SE -> NE Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.5, 0.5))*sample_weight; //
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.5, -0.5))*sample_weight; //
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.5, -1.5))*sample_weight; // NE -> NW Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.5, -1.5))*sample_weight; //
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-0.5, -1.5))*sample_weight; // NW - 1 (closed)
+
+ #if SAMPLE_COUNT > 4
+ // SampleCount 6 -> +20x = 36p
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.5, -2.5))*sample_weight; // NW -> SW Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.5, -1.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.5, -0.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.5, 0.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.5, 1.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.5, 2.5))*sample_weight; // SW -> SE Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.5, 2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-0.5, 2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.5, 2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.5, 2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.5, 2.5))*sample_weight; // SE -> NE Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.5, 1.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.5, 0.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.5, -0.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.5, -1.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.5, -2.5))*sample_weight; // NE -> NW Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.5, -2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.5, -2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-0.5, -2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.5, -2.5))*sample_weight; // NW - 1 (closed)
+ #if SAMPLE_COUNT > 6
+ // SampleCount 8 -> +28x = 64p
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.5, -3.5))*sample_weight; // NW -> SW Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.5, -2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.5, -1.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.5, -0.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.5, 0.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.5, 1.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.5, 2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.5, 3.5))*sample_weight; // SW -> SE Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.5, 3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.5, 3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-0.5, 3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.5, 3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.5, 3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.5, 3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.5, 3.5))*sample_weight; // SE -> NE Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.5, 2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.5, 1.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.5, 0.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.5, -0.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.5, -1.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.5, -2.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.5, -3.5))*sample_weight; // NE -> NW Edge
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.5, -3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.5, -3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.5, -3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-0.5, -3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.5, -3.5))*sample_weight;
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.5, -3.5))*sample_weight; // NW - 1 (closed)
+ #endif
+ #endif
+ #endif
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl
new file mode 100644
index 000000000..7adf111d5
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl
@@ -0,0 +1,87 @@
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels.
+
+ // float sample_count = gcu_FboTexSize.z;
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ // Not only the poles (NW, SW, ..) but the whole edge!
+ const float sample_weight = 1.0 / ( sample_count * sample_count );
+
+ // const vec4 tex_weights = vec4(0.075, 0.06, 0.045, 0.025);
+ vec2 texCoord = gcv_FboTexCoord.st;
+
+ vec4 t;
+
+ // SampleCount 1 -> 1x (raster 1x1)
+ t += texture2D(gcu_FboTexUnit, texCoord)*sample_weight; // CENTER
+
+ #if SAMPLE_COUNT > 1
+ // SampleCount 3 -> +8x = 9p (raster 3x3)
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.0, -1.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.0, -1.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.0, -1.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.0, 0.0))*sample_weight; // Center Left
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.0, 0.0))*sample_weight; // Center Right
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.0, 1.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.0, 1.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.0, 1.0))*sample_weight; // bottom line
+
+ #if SAMPLE_COUNT > 3
+ // SampleCount 5 -> +16x = 25p (raster 5x5)
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.0, -1.0))*sample_weight; // top line - 1
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.0, -1.0))*sample_weight; // top line - 1
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.0, 0.0))*sample_weight; // Center Left
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.0, 0.0))*sample_weight; // Center Right
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.0, 1.0))*sample_weight; // bottom line - 1
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.0, 1.0))*sample_weight; // bottom line - 1
+
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.0, -2.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.0, -2.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.0, -2.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.0, -2.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.0, -2.0))*sample_weight; // top line
+
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.0, 2.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.0, 2.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.0, 2.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.0, 2.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.0, 2.0))*sample_weight; // bottom line
+
+ #if SAMPLE_COUNT > 5
+ // SampleCount 7 -> +24x = 49p (raster 7x7)
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.0, -2.0))*sample_weight; // top line - 1
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.0, -2.0))*sample_weight; // top line - 1
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.0, -1.0))*sample_weight; // top line - 2
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.0, -1.0))*sample_weight; // top line - 2
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.0, 0.0))*sample_weight; // Center Left
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.0, 0.0))*sample_weight; // Center Right
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.0, 1.0))*sample_weight; // bottom line - 2
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.0, 1.0))*sample_weight; // bottom line - 2
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.0, 2.0))*sample_weight; // bottom line - 1
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.0, 2.0))*sample_weight; // bottom line - 1
+
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.0, -3.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.0, -3.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.0, -3.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.0, -3.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.0, -3.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.0, -3.0))*sample_weight; // top line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.0, -3.0))*sample_weight; // top line
+
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-3.0, 3.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-2.0, 3.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2(-1.0, 3.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 0.0, 3.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 1.0, 3.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 2.0, 3.0))*sample_weight; // bottom line
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*vec2( 3.0, 3.0))*sample_weight; // bottom line
+ #endif
+ #endif
+ #endif
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad.glsl
new file mode 100644
index 000000000..3e74fb9a6
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad.glsl
@@ -0,0 +1,41 @@
+
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels, origin is bottom left!
+
+ float sampleCount = gcu_FboTexSize.z;
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ // Just poles (NW, SW, ..)
+ float edge1H = sampleCount / 2.0;
+ float edge1T = sampleCount / 3.0;
+ float edgeTH = edge1H-edge1T;
+
+ vec2 normFragCoord = gl_FragCoord.xy - vec2(0.5, 0.5); // normalize center 0.5/0.5 -> 0/0
+ vec2 modPos = mod(normFragCoord, 2.0);
+ float orient = mod(modPos.x + modPos.y, 2.0); // mirrored on all odd columns, alternating each row (checker-board pattern)
+
+ vec2 texCoord = gcv_FboTexCoord.st;
+ vec4 t;
+
+ if( 0.0 == orient ) {
+ // SWIPE LEFT -> RIGHT
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, -edge1H, edgeTH, 0.0, 0.0)*0.25; // upper-left [p1]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, -edgeTH, -edge1H, 0.0, 0.0)*0.25; // lower-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeTH, edge1H, 0.0, 0.0)*0.25; // upper-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edge1H, -edgeTH, 0.0, 0.0)*0.25; // lower-right [p4]
+ } else {
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, -edge1H, -edgeTH, 0.0, 0.0)*0.25; // lower-left [p4]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, -edgeTH, edge1H, 0.0, 0.0)*0.25; // upper-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeTH, -edge1H, 0.0, 0.0)*0.25; // lower-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edge1H, edgeTH, 0.0, 0.0)*0.25; // upper-right [p1]
+ }
+
+
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad2.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad2.glsl
new file mode 100644
index 000000000..9e31e6bb7
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad2.glsl
@@ -0,0 +1,41 @@
+
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels, origin is bottom left!
+ //
+ // Same as flipquad - but w/ rgss coordinates
+
+ float sampleCount = gcu_FboTexSize.z;
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ vec2 normFragCoord = gl_FragCoord.xy - vec2(0.5, 0.5); // normalize center 0.5/0.5 -> 0/0
+ vec2 modPos = mod(normFragCoord, 2.0);
+ float orient = mod(modPos.x + modPos.y, 2.0); // mirrored on all odd columns, alternating each row (checker-board pattern)
+
+ vec2 texCoord = gcv_FboTexCoord.st;
+ float edge1Q = ( sampleCount / 2.0 ) - 1.0;
+
+ vec4 t;
+
+// #define GetSample(texUnit, texCoord, psize, cx, cy, offX, offY) texture2D(texUnit, texCoord + psize * vec2(cx+offX, cy+offY))
+
+ if( 0.0 == orient ) {
+ // SWIPE LEFT -> RIGHT
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, -edge1Q, 0.0, -0.5, 0.5)*0.25; // upper-left [p1]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edge1Q, -0.5, -0.5)*0.25; // lower-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edge1Q, 0.5, 0.5)*0.25; // upper-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edge1Q, 0.0, 0.5, -0.5)*0.25; // lower-right [p4]
+ } else {
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, -edge1Q, 0.0, -0.5, -0.5)*0.25; // lower-left [p4]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edge1Q, -0.5, 0.5)*0.25; // upper-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edge1Q, 0.5, -0.5)*0.25; // lower-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edge1Q, 0.0, 0.5, 0.5)*0.25; // upper-right [p1]
+ }
+
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl
new file mode 100644
index 000000000..8cc108bd1
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl
@@ -0,0 +1,109 @@
+
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels, origin is bottom left!
+ //
+ // Same as flipquad - but w/ rgss coordinates
+
+ // float sample_count = gcu_FboTexSize.z;
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ vec2 normFragCoord = gl_FragCoord.xy - vec2(0.5, 0.5); // normalize center 0.5/0.5 -> 0/0
+ vec2 modPos = mod(normFragCoord, 2.0);
+ float orient = mod(modPos.x + modPos.y, 2.0); // mirrored on all odd columns, alternating each row (checker-board pattern)
+
+ vec2 texCoord = gcv_FboTexCoord.st;
+ vec4 t;
+
+// #define GetSample(texUnit, texCoord, psize, cx, cy, offX, offY) texture2D(texUnit, texCoord + psize * vec2(cx+offX, cy+offY))
+
+ #if SAMPLE_COUNT == 1
+
+ t = texture2D(gcu_FboTexUnit, texCoord);
+
+ #elif SAMPLE_COUNT < 4
+
+ // SampleCount 2 -> 2p
+ const float weight = 1.0 / 2.0;
+ const float edge = ( sample_count / 2.0 ) - 1.0;
+
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, -edge, edge, -0.5, 0.5)*weight; // center
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edge, -edge, 0.5, -0.5)*weight; // center
+
+ #elif SAMPLE_COUNT < 8
+
+ // SampleCount 4 -> 4p
+ const float weight = 1.0 / 4.0;
+ const float edgeS4_1Q = ( sample_count / 2.0 ) - 1.0;
+
+ if( 0.0 == orient ) {
+ // SWIPE LEFT -> RIGHT
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, -edgeS4_1Q, 0.0, -0.5, 0.5)*weight; // upper-left [p1]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edgeS4_1Q, -0.5, -0.5)*weight; // lower-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edgeS4_1Q, 0.5, 0.5)*weight; // upper-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeS4_1Q, 0.0, 0.5, -0.5)*weight; // lower-right [p4]
+ } else {
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, -edgeS4_1Q, 0.0, -0.5, -0.5)*weight; // lower-left [p4]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edgeS4_1Q, -0.5, 0.5)*weight; // upper-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edgeS4_1Q, 0.5, -0.5)*weight; // lower-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeS4_1Q, 0.0, 0.5, 0.5)*weight; // upper-right [p1]
+ }
+
+ #else
+
+ // SampleCount 8 -> 16p
+ const float weight = 1.0 / 16.0;
+ const float edgeS4_1Q = 1.0;
+
+ if( 0.0 == orient ) {
+ // SWIPE LEFT -> RIGHT
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, -edgeS4_1Q, 0.0, -2.0-0.5, -2.0+0.5)*weight; // upper-left [p1]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edgeS4_1Q, -2.0-0.5, -2.0-0.5)*weight; // lower-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edgeS4_1Q, -2.0-0.5, -2.0-0.5)*weight; // upper-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeS4_1Q, 0.0, -2.0-0.5, -2.0-0.5)*weight; // lower-right [p4]
+
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, -edgeS4_1Q, 0.0, -2.0-0.5, 2.0-0.5)*weight; // lower-left [p4]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edgeS4_1Q, -2.0-0.5, 2.0+0.5)*weight; // upper-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edgeS4_1Q, -2.0+0.5, 2.0-0.5)*weight; // lower-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeS4_1Q, 0.0, -2.0+0.5, 2.0+0.5)*weight; // upper-right [p1]
+
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, -edgeS4_1Q, 0.0, 2.0-0.5, -2.0-0.5)*weight; // lower-left [p4]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edgeS4_1Q, 2.0-0.5, -2.0+0.5)*weight; // upper-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edgeS4_1Q, 2.0+0.5, -2.0-0.5)*weight; // lower-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeS4_1Q, 0.0, 2.0+0.5, -2.0+0.5)*weight; // upper-right [p1]
+
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, -edgeS4_1Q, 0.0, 2.0-0.5, 2.0+0.5)*weight; // upper-left [p1]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edgeS4_1Q, 2.0-0.5, 2.0-0.5)*weight; // lower-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edgeS4_1Q, 2.0-0.5, 2.0-0.5)*weight; // upper-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeS4_1Q, 0.0, 2.0-0.5, 2.0-0.5)*weight; // lower-right [p4]
+ } else {
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, -edgeS4_1Q, 0.0, -2.0-0.5, -2.0-0.5)*weight; // lower-left [p4]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edgeS4_1Q, -2.0-0.5, -2.0+0.5)*weight; // upper-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edgeS4_1Q, -2.0+0.5, -2.0-0.5)*weight; // lower-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeS4_1Q, 0.0, -2.0+0.5, -2.0+0.5)*weight; // upper-right [p1]
+
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, -edgeS4_1Q, 0.0, -2.0-0.5, 2.0+0.5)*weight; // upper-left [p1]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edgeS4_1Q, -2.0-0.5, 2.0-0.5)*weight; // lower-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edgeS4_1Q, -2.0-0.5, 2.0-0.5)*weight; // upper-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeS4_1Q, 0.0, -2.0-0.5, 2.0-0.5)*weight; // lower-right [p4]
+
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, -edgeS4_1Q, 0.0, 2.0-0.5, -2.0+0.5)*weight; // upper-left [p1]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edgeS4_1Q, 2.0-0.5, -2.0-0.5)*weight; // lower-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edgeS4_1Q, 2.0-0.5, -2.0-0.5)*weight; // upper-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeS4_1Q, 0.0, 2.0-0.5, -2.0-0.5)*weight; // lower-right [p4]
+
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, -edgeS4_1Q, 0.0, 2.0-0.5, 2.0-0.5)*weight; // lower-left [p4]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edgeS4_1Q, 2.0-0.5, 2.0+0.5)*weight; // upper-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edgeS4_1Q, 2.0+0.5, 2.0-0.5)*weight; // lower-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeS4_1Q, 0.0, 2.0+0.5, 2.0+0.5)*weight; // upper-right [p1]
+ }
+
+ #endif
+
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_fxaa3.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_fxaa3.glsl
new file mode 100644
index 000000000..015dc1b24
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_fxaa3.glsl
@@ -0,0 +1,56 @@
+
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels.
+
+ if( gcu_FboTexSize.z < 4.0 ) {
+ // FXAA-2
+ const float FXAA_REDUCE_MIN = (1.0/128.0);
+ const float FXAA_REDUCE_MUL = (1.0/8.0);
+ const float FXAA_SPAN_MAX = 8.0;
+
+ float sampleCount = gcu_FboTexSize.z;
+
+ vec2 texCoord = gcv_FboTexCoord.st;
+ const float poff = 1.0;
+ vec2 psize = 1.0 / texCoord; // pixel size
+
+ vec3 rgbNW = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-poff, -poff))).rgb;
+ vec3 rgbSW = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-poff, poff))).rgb;
+ vec3 rgbSE = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( poff, poff))).rgb;
+ vec3 rgbNE = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( poff, -poff))).rgb;
+ vec4 rgbM = texture2D(gcu_FboTexUnit, texCoord);
+
+ const vec3 luma = vec3(0.299, 0.587, 0.114);
+ float lumaNW = dot(rgbNW, luma);
+ float lumaNE = dot(rgbNE, luma);
+ float lumaSW = dot(rgbSW, luma);
+ float lumaSE = dot(rgbSE, luma);
+ float lumaM = dot(rgbM.rgb, luma);
+ float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
+ float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
+ vec2 dir;
+ dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
+ dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
+ float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),FXAA_REDUCE_MIN);
+ float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
+ dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
+ max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),dir * rcpDirMin) ) * psize;
+
+
+ vec3 rgbA = 0.5 * ( texture2D(gcu_FboTexUnit, texCoord + dir * (1.0/3.0 - 0.5)).rgb +
+ texture2D(gcu_FboTexUnit, texCoord + dir * (2.0/3.0 - 0.5)).rgb );
+ vec3 rgbB = rgbA * 0.5 + 0.25 * ( texture2D(gcu_FboTexUnit, texCoord + (dir * - 0.5)).rgb +
+ texture2D(gcu_FboTexUnit, texCoord + (dir * 0.5)).rgb );
+ float lumaB = dot(rgbB, luma);
+ if((lumaB < lumaMin) || (lumaB > lumaMax)) {
+ mgl_FragColor.rgb = rgbA;
+ } else {
+ mgl_FragColor.rgb = rgbB;
+ }
+ mgl_FragColor.a = gcu_Alpha * rgbM.a; // mix(0.0, gcu_Alpha, rgbM.a); // t.a one of [ 0.0, 1.0 ]
+ } else {
+
+#include curverenderer01-pass2-vbaa_poles_equalweight.glsl
+
+ }
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_poles_bilin1.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_poles_bilin1.glsl
new file mode 100644
index 000000000..d634c1f9b
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_poles_bilin1.glsl
@@ -0,0 +1,91 @@
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels.
+
+ vec2 texCoord = gcv_FboTexCoord.st;
+
+ float sampleCount = gcu_FboTexSize.z;
+ vec2 tsize = gcu_FboTexSize.xy; // tex size
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ // mix(x,y,a): x*(1-a) + y*a
+ //
+ // bilinear filtering includes 2 mix:
+ //
+ // pix1 = tex[x0][y0] * ( 1 - u_ratio ) + tex[x1][y0] * u_ratio
+ // pix2 = tex[x0][y1] * ( 1 - u_ratio ) + tex[x1][y1] * u_ratio
+ // fin = pix1 * ( 1 - v_ratio ) + pix2 * v_ratio
+ //
+ // so we can use the build in mix function for these 2 computations ;-)
+ //
+ vec2 uv_ratio = fract(texCoord*tsize); // texCoord*tsize - floor(texCoord*tsize);
+
+ // Just poles (NW, SW, ..)
+ float pixelCount = 2 * sampleCount;
+
+ // sampleCount [0, 1, 3, 5, 7] are undefined!
+ float layerCount = ( sampleCount / 2.0 );
+
+ // sum of all integer [layerCount .. 1] -> Gauss
+ float denom = ( layerCount / 2.0 ) * ( layerCount + 1.0 );
+
+ vec4 t, p1, p2, p3, p4;
+
+ // Layer-1: SampleCount 2 -> 4x
+ p1 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, -0.5))); // NW
+ p2 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, 0.5))); // SW
+ p3 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, 0.5))); // SE
+ p4 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, -0.5))); // NE
+
+ p1 = mix( p1, p4, uv_ratio.x);
+ p2 = mix( p2, p3, uv_ratio.x);
+ t = mix ( p1, p2, uv_ratio.y );
+
+ t *= (layerCount - 0.0) / ( denom ); // weight layer 1
+
+ if( sampleCount > 2.0 ) {
+ // Layer-2: SampleCount 4 -> +4x = 8p
+ p1 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, -1.5))); // NW
+ p2 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, 1.5))); // SW
+ p3 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, 1.5))); // SE
+ p4 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, -1.5))); // NE
+
+ p1 = mix( p1, p4, uv_ratio.x);
+ p2 = mix( p2, p3, uv_ratio.x);
+ p3 = mix ( p1, p2, uv_ratio.y );
+ t += p3 * (layerCount - 1) / ( denom ); // weight layer 2
+
+ if( sampleCount > 4.0 ) {
+ // Layer-3: SampleCount 6 -> +4 = 12p
+ p1 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, -2.5))); // NW
+ p2 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, 2.5))); // SW
+ p3 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, 2.5))); // SE
+ p4 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, -2.5))); // NE
+
+ p1 = mix( p1, p4, uv_ratio.x);
+ p2 = mix( p2, p3, uv_ratio.x);
+ p3 = mix ( p1, p2, uv_ratio.y );
+ t += p3 * (layerCount - 2) / ( denom ); // weight layer 3
+
+ if( sampleCount > 6.0 ) {
+ // Layer-4: SampleCount 8 -> +4 = 16p
+ p1 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, -3.5))); // NW
+ p2 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, 3.5))); // SW
+ p3 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, 3.5))); // SE
+ p4 = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, -3.5))); // NE
+
+ p1 = mix( p1, p4, uv_ratio.x);
+ p2 = mix( p2, p3, uv_ratio.x);
+ p3 = mix ( p1, p2, uv_ratio.y );
+
+ t += p3 * (layerCount - 3) / ( denom ); // weight layer 4
+ }
+ }
+ }
+
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_polesequal.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_polesequal.glsl
new file mode 100644
index 000000000..0e8b6f161
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_polesequal.glsl
@@ -0,0 +1,49 @@
+
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels.
+
+ float sampleCount = gcu_FboTexSize.z;
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ // Just poles (NW, SW, ..)
+ float sample_weight = 1 / ( 2 * sampleCount );
+
+ vec2 texCoord = gcv_FboTexCoord.st;
+
+ vec4 t;
+
+ // SampleCount 2 -> 4x
+ t = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, -0.5)))*sample_weight; // NW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, 0.5)))*sample_weight; // SW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, 0.5)))*sample_weight; // SE
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, -0.5)))*sample_weight; // NE
+ if( sampleCount > 2.0 ) {
+ // SampleCount 4 -> +4 = 8p
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, -1.5)))*sample_weight; // NW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, 1.5)))*sample_weight; // SW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, 1.5)))*sample_weight; // SE
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, -1.5)))*sample_weight; // NE
+
+ if( sampleCount > 4.0 ) {
+ // SampleCount 6 -> +4 = 12p
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, -2.5)))*sample_weight; // NW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, 2.5)))*sample_weight; // SW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, 2.5)))*sample_weight; // SE
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, -2.5)))*sample_weight; // NE
+ if( sampleCount > 6.0 ) {
+ // SampleCount 8 -> +4 = 16p
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, -3.5)))*sample_weight; // NW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, 3.5)))*sample_weight; // SW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, 3.5)))*sample_weight; // SE
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, -3.5)))*sample_weight; // NE
+ }
+ }
+ }
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_polesprop01.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_polesprop01.glsl
new file mode 100644
index 000000000..6c263b9bd
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_polesprop01.glsl
@@ -0,0 +1,65 @@
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels.
+
+ float sampleCount = gcu_FboTexSize.z;
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ // Just poles (NW, SW, ..)
+ float pixelCount = 2 * sampleCount;
+
+ // sampleCount [0, 1, 3, 5, 7] are undefined!
+ float layerCount = ( sampleCount / 2.0 );
+
+ // sum of all integer [layerCount .. 1] -> Gauss
+ float denom = ( layerCount / 2.0 ) * ( layerCount + 1.0 );
+
+ vec2 texCoord = gcv_FboTexCoord.st;
+
+ vec4 t;
+
+ // Layer-1: SampleCount 2 -> 4x
+ t = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, -0.5))); // NW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-0.5, 0.5))); // SW
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, 0.5))); // SE
+ t += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 0.5, -0.5))); // NE
+
+ t *= (layerCount - 0.0) / ( denom * 4.0 ); // weight layer 1
+
+ if( sampleCount > 2.0 ) {
+ // Layer-2: SampleCount 4 -> +4x = 8p
+ vec4 tn = vec4(0);
+ tn = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, -1.5))); // NW
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-1.5, 1.5))); // SW
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, 1.5))); // SE
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 1.5, -1.5))); // NE
+
+ t += tn * (layerCount - 1) / ( denom * 4.0 ); // weight layer 2
+
+ if( sampleCount > 4.0 ) {
+ // Layer-3: SampleCount 6 -> +4 = 12p
+ tn = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, -2.5))); // NW
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-2.5, 2.5))); // SW
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, 2.5))); // SE
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 2.5, -2.5))); // NE
+
+ t += tn * (layerCount - 2) / ( denom * 4.0 ); // weight layer 3
+
+ if( sampleCount > 6.0 ) {
+ // Layer-4: SampleCount 8 -> +4 = 16p
+ tn = texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, -3.5))); // NW
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2(-3.5, 3.5))); // SW
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, 3.5))); // SE
+ tn += texture2D(gcu_FboTexUnit, texCoord + psize*(vec2( 3.5, -3.5))); // NE
+
+ t += tn * (layerCount - 3) / ( denom * 4.0 ); // weight layer 4
+ }
+ }
+ }
+
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_quincunx.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_quincunx.glsl
new file mode 100644
index 000000000..07a9adf46
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_quincunx.glsl
@@ -0,0 +1,28 @@
+
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels, origin is bottom left!
+
+ float sampleCount = gcu_FboTexSize.z;
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ // Just poles (NW, SW, ..)
+ float edgeH = sampleCount / 2.0;
+
+ vec2 texCoord = gcv_FboTexCoord.st;
+
+ vec4 t;
+
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, 0.0, 0.0, 0.0)*0.5; // w1 - center
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, -edgeH, -edgeH, 0.0, 0.0)*0.125; // w2 - sharing
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, -edgeH, edgeH, 0.0, 0.0)*0.125; // w3 - edges
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeH, -edgeH, 0.0, 0.0)*0.125; // w4 - w/ all pixels
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edgeH, edgeH, 0.0, 0.0)*0.125; // w5
+
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_rgss.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_rgss.glsl
new file mode 100644
index 000000000..27a5684a6
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_rgss.glsl
@@ -0,0 +1,25 @@
+
+ // Pass-2: AA on Texture
+ // Note: gcv_FboTexCoord is in center of sample pixels, origin is bottom left!
+
+ float sampleCount = gcu_FboTexSize.z;
+ vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size
+
+ vec2 texCoord = gcv_FboTexCoord.st;
+ float edge1Q = ( sampleCount / 2.0 ) - 1.0;
+
+ vec4 t;
+ // SWIPE LEFT -> RIGHT
+ t = GetSample(gcu_FboTexUnit, texCoord, psize, -edge1Q, 0.0, -0.5, 0.5)*0.25; // upper-left [p1]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, -edge1Q, -0.5, -0.5)*0.25; // lower-left [p3]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, 0.0, edge1Q, 0.5, 0.5)*0.25; // upper-right [p2]
+ t += GetSample(gcu_FboTexUnit, texCoord, psize, edge1Q, 0.0, 0.5, -0.5)*0.25; // lower-right [p4]
+
+ #if 0
+ if(t.w == 0.0){
+ discard; // discard freezes NV tegra2 compiler
+ }
+ #endif
+
+ mgl_FragColor = t;
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp
new file mode 100644
index 000000000..64857c9ce
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp
@@ -0,0 +1,17 @@
+//Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+#include uniforms.glsl
+#include attributes.glsl
+#include varyings.glsl
+
+void main(void)
+{
+ // gl_Position = gcu_PMVMatrix01[0] * gcu_PMVMatrix01[1] * vec4(gca_FboVertices, 1);
+ gl_Position = gcu_PMVMatrix01[0] * gcu_PMVMatrix01[1] * gca_FboVertices;
+ gcv_FboTexCoord = gca_FboTexCoords;
+}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp
new file mode 100644
index 000000000..05407a4e6
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp
@@ -0,0 +1,16 @@
+//Copyright 2010 JogAmp Community. All rights reserved.
+
+//
+// 2-pass shader w/o weight
+//
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+#define GetSample(texUnit, texCoord, psize, cx, cy, offX, offY) texture2D(texUnit, texCoord + psize * vec2(cx+offX, cy+offY))
+
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp
new file mode 100644
index 000000000..14210be39
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp
@@ -0,0 +1,33 @@
+//Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+#include uniforms.glsl
+#include attributes.glsl
+#include varyings.glsl
+
+void main(void)
+{
+ gl_Position = gcu_PMVMatrix01[0] * gcu_PMVMatrix01[1] * gca_Vertices;
+#if 1
+ gcv_CurveParam = gca_CurveParams;
+#else
+ if( gcv_CurveParams.x <= -10.0 ) {
+ // vec4 tc = gcu_PMVMatrix01[0] * gcu_PMVMatrix01[1] * vec4(gca_CurveParams.xy, gca_Vertices.z, 1);
+ // gcv_CurveParams = vec3(tc.xy, gca_CurveParams.z);
+ gcv_CurveParam = gca_CurveParams;
+ } else {
+ gcv_CurveParam = gca_CurveParams;
+ }
+#endif
+#ifdef USE_COLOR_TEXTURE
+ vec2 dim = vec2(gcu_ColorTexBBox.z - gcu_ColorTexBBox.x, gcu_ColorTexBBox.w - gcu_ColorTexBBox.y);
+ gcv_ColorTexCoord = vec2(gca_Vertices.x - gcu_ColorTexBBox.x, gca_Vertices.y - gcu_ColorTexBBox.y) / dim;
+#endif
+#ifdef USE_COLOR_CHANNEL
+ gcv_Color = gca_Colors;
+#endif
+}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-xxx.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-xxx.vp
deleted file mode 100644
index 64a6835ec..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-xxx.vp
+++ /dev/null
@@ -1,12 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#include uniforms.glsl
-#include attributes.glsl
-#include varyings.glsl
-
-void main(void)
-{
- // gl_Position = gcu_PMVMatrix[0] * gcu_PMVMatrix[1] * vec4(gca_Vertices, 1);
- gl_Position = gcu_PMVMatrix[0] * gcu_PMVMatrix[1] * gca_Vertices;
- gcv_TexCoord = gca_TexCoords;
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2-merged.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2-merged.fp
deleted file mode 100644
index da32df51f..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2-merged.fp
+++ /dev/null
@@ -1,52 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#ifdef GL_ES
- precision lowp float;
- precision lowp int;
-#endif
-
-uniform mat4 gcu_PMVMatrix[3]; // P, Mv, and Mvi
-uniform vec3 gcu_ColorStatic;
-uniform float gcu_Alpha;
-
-varying vec2 gcv_TexCoord;
-
-const vec3 b_color = vec3(1.0, 1.0, 1.0);
-
-void main (void)
-{
- vec2 rtex = vec2(abs(gcv_TexCoord.x),abs(gcv_TexCoord.y));
- vec3 c = gcu_ColorStatic;
-
- float alpha = 0.0;
-
- if((gcv_TexCoord.x == 0.0) && (gcv_TexCoord.y == 0.0)) {
- alpha = gcu_Alpha;
- }
- else if ((gcv_TexCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)) {
- vec2 dtx = dFdx(rtex);
- vec2 dty = dFdy(rtex);
-
- rtex.y -= 0.1;
-
- if(rtex.y < 0.0) {
- rtex.y = 0.0;
- }
-
- vec2 f = vec2((dtx.y - dtx.x + 2.0*rtex.x*dtx.x), (dty.y - dty.x + 2.0*rtex.x*dty.x));
- float position = rtex.y - (rtex.x * (1.0 - rtex.x));
- float d = position/(length(f));
-
- float a = (0.5 - d * sign(gcv_TexCoord.y));
-
- if (a >= 1.0) {
- alpha = gcu_Alpha;
- } else if (a <= 0.0) {
- alpha=0.0;
- } else {
- alpha = gcu_Alpha * a;
- }
- }
-
- gl_FragColor = vec4(c, alpha);
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2.fp
deleted file mode 100644
index e693891a6..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2.fp
+++ /dev/null
@@ -1,13 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 100
-
-// we require dFdx/dFdy
-// #extension OES_standard_derivatives : require
-#extension GL_OES_standard_derivatives : enable
-
-precision mediump float;
-precision mediump int;
-
-#include curverenderer01a-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-gl2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-gl2.fp
deleted file mode 100644
index d187fea24..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-gl2.fp
+++ /dev/null
@@ -1,6 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 110
-
-#include curverenderer01a-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-xxx.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-xxx.fp
deleted file mode 100644
index f3a88adef..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-xxx.fp
+++ /dev/null
@@ -1,42 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-//
-// 1-pass shader w/o weight
-//
-
-#include uniforms.glsl
-#include varyings.glsl
-
-void main (void)
-{
- vec2 rtex = vec2(abs(gcv_TexCoord.x),abs(gcv_TexCoord.y));
- vec3 c = gcu_ColorStatic.rgb;
-
- float alpha = 0.0;
-
- if((gcv_TexCoord.x == 0.0) && (gcv_TexCoord.y == 0.0)) {
- alpha = gcu_Alpha;
- }
- else if ((gcv_TexCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)) {
- rtex.y -= 0.1;
-
- if(rtex.y < 0.0 && gcv_TexCoord.y < 0.0) {
- // discard; // freezes NV tegra2 compiler
- alpha = 0.0;
- } else {
- rtex.y = max(rtex.y, 0.0);
-
- vec2 dtx = dFdx(rtex);
- vec2 dty = dFdy(rtex);
-
- vec2 f = vec2((dtx.y - dtx.x + 2.0*rtex.x*dtx.x), (dty.y - dty.x + 2.0*rtex.x*dty.x));
- float position = rtex.y - (rtex.x * (1.0 - rtex.x));
-
- // FIXME: will we ever set gcu_Alpha != 1.0 ? If not, a==alpha!
- float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_TexCoord.y), 0.0, 1.0);
- alpha = gcu_Alpha * a;
- }
- }
-
- gl_FragColor = vec4(c, alpha);
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-es2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-es2.fp
deleted file mode 100644
index 2e709630d..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-es2.fp
+++ /dev/null
@@ -1,14 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 100
-
-// we require dFdx/dFdy
-// #extension OES_standard_derivatives : require
-#extension GL_OES_standard_derivatives : enable
-
-precision mediump float;
-precision mediump int;
-precision mediump sampler2D;
-
-#include curverenderer01b-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-gl2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-gl2.fp
deleted file mode 100644
index 01e08ff30..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-gl2.fp
+++ /dev/null
@@ -1,6 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 110
-
-#include curverenderer01b-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-xxx.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-xxx.fp
deleted file mode 100644
index 879e41e4c..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-xxx.fp
+++ /dev/null
@@ -1,82 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-//
-// 2-pass shader w/o weight
-//
-
-#include uniforms.glsl
-#include varyings.glsl
-
-const vec4 tex_weights = vec4(0.075, 0.06, 0.045, 0.025);
-
-void main (void)
-{
- vec2 rtex = vec2(abs(gcv_TexCoord.x),abs(gcv_TexCoord.y));
- vec3 c = gcu_ColorStatic.rgb;
-
- float alpha = 0.0;
- float enable = 1.0;
-
- if((gcv_TexCoord.x == 0.0) && (gcv_TexCoord.y == 0.0)) {
- alpha = gcu_Alpha;
- }
- else if((gcv_TexCoord.x >= 5.0)) {
- vec2 dfx = dFdx(gcv_TexCoord);
- vec2 dfy = dFdy(gcv_TexCoord);
-
- vec2 size = 1.0/gcu_TextureSize;
-
- rtex -= 5.0;
- vec4 t = texture2D(gcu_TextureUnit, rtex)* 0.18;
-
- t += texture2D(gcu_TextureUnit, rtex + size*(vec2(1, 0)))*tex_weights.x;
- t += texture2D(gcu_TextureUnit, rtex - size*(vec2(1, 0)))*tex_weights.x;
- t += texture2D(gcu_TextureUnit, rtex + size*(vec2(0, 1)))*tex_weights.x;
- t += texture2D(gcu_TextureUnit, rtex - size*(vec2(0, 1)))*tex_weights.x;
-
- t += texture2D(gcu_TextureUnit, rtex + 2.0*size*(vec2(1, 0)))*tex_weights.y;
- t += texture2D(gcu_TextureUnit, rtex - 2.0*size*(vec2(1, 0)))*tex_weights.y;
- t += texture2D(gcu_TextureUnit, rtex + 2.0*size*(vec2(0, 1)))*tex_weights.y;
- t += texture2D(gcu_TextureUnit, rtex - 2.0*size*(vec2(0, 1)))*tex_weights.y;
-
- t += texture2D(gcu_TextureUnit, rtex + 3.0*size*(vec2(1, 0)))*tex_weights.z;
- t += texture2D(gcu_TextureUnit, rtex - 3.0*size*(vec2(1, 0)))*tex_weights.z;
- t += texture2D(gcu_TextureUnit, rtex + 3.0*size*(vec2(0, 1)))*tex_weights.z;
- t += texture2D(gcu_TextureUnit, rtex - 3.0*size*(vec2(0, 1)))*tex_weights.z;
-
- t += texture2D(gcu_TextureUnit, rtex + 4.0*size*(vec2(1, 0)))*tex_weights.w;
- t += texture2D(gcu_TextureUnit, rtex - 4.0*size*(vec2(1, 0)))*tex_weights.w;
- t += texture2D(gcu_TextureUnit, rtex + 4.0*size*(vec2(0, 1)))*tex_weights.w;
- t += texture2D(gcu_TextureUnit, rtex - 4.0*size*(vec2(0, 1)))*tex_weights.w;
-
- /** discard freezes NV tegra2 compiler
- if(t.w == 0.0){
- discard;
- } */
-
- c = t.xyz;
- alpha = gcu_Alpha * t.w;
- }
- else if ((gcv_TexCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)) {
- rtex.y -= 0.1;
-
- if(rtex.y < 0.0 && gcv_TexCoord.y < 0.0) {
- // discard; // freezes NV tegra2 compiler
- alpha = 0.0;
- } else {
- rtex.y = max(rtex.y, 0.0);
-
- vec2 dtx = dFdx(rtex);
- vec2 dty = dFdy(rtex);
-
- vec2 f = vec2((dtx.y - dtx.x + 2.0*rtex.x*dtx.x), (dty.y - dty.x + 2.0*rtex.x*dty.x));
- float position = rtex.y - (rtex.x * (1.0 - rtex.x));
-
- // FIXME: will we ever set gcu_Alpha != 1.0 ? If not, a==alpha!
- float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_TexCoord.y), 0.0, 1.0);
- alpha = gcu_Alpha * a;
- }
- }
-
- gl_FragColor = vec4(c, alpha);
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-es2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-es2.fp
deleted file mode 100644
index b52420350..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-es2.fp
+++ /dev/null
@@ -1,14 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 100
-
-// we require dFdx/dFdy
-// #extension OES_standard_derivatives : require
-#extension GL_OES_standard_derivatives : enable
-
-precision mediump float;
-precision mediump int;
-precision mediump sampler2D;
-
-#include curverenderer02a-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-gl2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-gl2.fp
deleted file mode 100644
index 01715daa5..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-gl2.fp
+++ /dev/null
@@ -1,6 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 110
-
-#include curverenderer02a-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-xxx.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-xxx.fp
deleted file mode 100644
index d31bafb5a..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-xxx.fp
+++ /dev/null
@@ -1,48 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-//
-// 1-pass shader w/ weight
-//
-
-#include uniforms.glsl
-#include varyings.glsl
-
-void main (void)
-{
- vec2 rtex = vec2(abs(gcv_TexCoord.x),abs(gcv_TexCoord.y));
- vec3 c = gcu_ColorStatic.rgb;
-
- float alpha = 0.0;
-
- if((gcv_TexCoord.x == 0.0) && (gcv_TexCoord.y == 0.0)) {
- alpha = gcu_Alpha;
- }
- else if ((gcv_TexCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)) {
- rtex.y -= 0.1;
-
- if(rtex.y < 0.0 && gcv_TexCoord.y < 0.0) {
- // discard; // freezes NV tegra2 compiler
- alpha = 0.0;
- } else {
- rtex.y = max(rtex.y, 0.0);
-
- vec2 dtx = dFdx(rtex);
- vec2 dty = dFdy(rtex);
-
- float w = gcu_Weight;
- float pd = ((2.0 - (2.0*w))*rtex.x*rtex.x) + 2.0*(w-1.0)*rtex.x + 1.0;
- float position = rtex.y - ((w*rtex.x*(1.0 - rtex.x))/pd);
-
- float aph = 2.0 - 2.0*w;
-
- float gd = (aph*rtex.x*rtex.x + 2.0*rtex.x + 1.0)*(aph*rtex.x*rtex.x + 2.0*rtex.x + 1.0);
- vec2 f = vec2((dtx.y - (w*dtx.x*(1.0 - 2.0*rtex.x))/gd), (dty.y - (w*dty.x*(1.0 - 2.0*rtex.x))/gd));
-
- // FIXME: will we ever set gcu_Alpha != 1.0 ? If not, a==alpha!
- float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_TexCoord.y), 0.0, 1.0);
- alpha = gcu_Alpha * a;
- }
- }
-
- gl_FragColor = vec4(c, alpha);
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-es2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-es2.fp
deleted file mode 100644
index e0486dd7b..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-es2.fp
+++ /dev/null
@@ -1,14 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 100
-
-// we require dFdx/dFdy
-// #extension OES_standard_derivatives : require
-#extension GL_OES_standard_derivatives : enable
-
-precision mediump float;
-precision mediump int;
-precision mediump sampler2D;
-
-#include curverenderer02b-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-gl2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-gl2.fp
deleted file mode 100644
index b1cc72188..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-gl2.fp
+++ /dev/null
@@ -1,6 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 110
-
-#include curverenderer02b-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-xxx.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-xxx.fp
deleted file mode 100644
index be738498c..000000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-xxx.fp
+++ /dev/null
@@ -1,88 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-//
-// 2-pass shader w/ weight
-//
-
-#include uniforms.glsl
-#include varyings.glsl
-
-const vec4 tex_weights = vec4(0.075, 0.06, 0.045, 0.025);
-
-void main (void)
-{
- vec2 rtex = vec2(abs(gcv_TexCoord.x),abs(gcv_TexCoord.y));
- vec3 c = gcu_ColorStatic.rgb;
-
- float alpha = 0.0;
-
- if((gcv_TexCoord.x == 0.0) && (gcv_TexCoord.y == 0.0)) {
- alpha = gcu_Alpha;
- }
- else if((gcv_TexCoord.x >= 5.0)) {
- vec2 dfx = dFdx(gcv_TexCoord);
- vec2 dfy = dFdy(gcv_TexCoord);
-
- vec2 size = 1.0/gcu_TextureSize;
-
- rtex -= 5.0;
- vec4 t = texture2D(gcu_TextureUnit, rtex)* 0.18;
-
- t += texture2D(gcu_TextureUnit, rtex + size*(vec2(1, 0)))*tex_weights.x;
- t += texture2D(gcu_TextureUnit, rtex - size*(vec2(1, 0)))*tex_weights.x;
- t += texture2D(gcu_TextureUnit, rtex + size*(vec2(0, 1)))*tex_weights.x;
- t += texture2D(gcu_TextureUnit, rtex - size*(vec2(0, 1)))*tex_weights.x;
-
- t += texture2D(gcu_TextureUnit, rtex + 2.0*size*(vec2(1, 0)))*tex_weights.y;
- t += texture2D(gcu_TextureUnit, rtex - 2.0*size*(vec2(1, 0)))*tex_weights.y;
- t += texture2D(gcu_TextureUnit, rtex + 2.0*size*(vec2(0, 1)))*tex_weights.y;
- t += texture2D(gcu_TextureUnit, rtex - 2.0*size*(vec2(0, 1)))*tex_weights.y;
-
- t += texture2D(gcu_TextureUnit, rtex + 3.0*size*(vec2(1, 0)))*tex_weights.z;
- t += texture2D(gcu_TextureUnit, rtex - 3.0*size*(vec2(1, 0)))*tex_weights.z;
- t += texture2D(gcu_TextureUnit, rtex + 3.0*size*(vec2(0, 1)))*tex_weights.z;
- t += texture2D(gcu_TextureUnit, rtex - 3.0*size*(vec2(0, 1)))*tex_weights.z;
-
- t += texture2D(gcu_TextureUnit, rtex + 4.0*size*(vec2(1, 0)))*tex_weights.w;
- t += texture2D(gcu_TextureUnit, rtex - 4.0*size*(vec2(1, 0)))*tex_weights.w;
- t += texture2D(gcu_TextureUnit, rtex + 4.0*size*(vec2(0, 1)))*tex_weights.w;
- t += texture2D(gcu_TextureUnit, rtex - 4.0*size*(vec2(0, 1)))*tex_weights.w;
-
- /** discard freezes NV tegra2 compiler
- if(t.w == 0.0) {
- discard;
- } */
-
- c = t.xyz;
- alpha = gcu_Alpha * t.w;
- }
- ///////////////////////////////////////////////////////////
- else if ((gcv_TexCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)) {
- rtex.y -= 0.1;
-
- if(rtex.y < 0.0 && gcv_TexCoord.y < 0.0) {
- // discard; // freezes NV tegra2 compiler
- alpha = 0.0;
- } else {
- rtex.y = max(rtex.y, 0.0);
-
- vec2 dtx = dFdx(rtex);
- vec2 dty = dFdy(rtex);
-
- float w = gcu_Weight;
- float pd = ((2.0 - (2.0*w))*rtex.x*rtex.x) + 2.0*(w-1.0)*rtex.x + 1.0;
- float position = rtex.y - ((w*rtex.x*(1.0 - rtex.x))/pd);
-
- float aph = 2.0 - 2.0*w;
-
- float gd = (aph*rtex.x*rtex.x + 2.0*rtex.x + 1.0)*(aph*rtex.x*rtex.x + 2.0*rtex.x + 1.0);
- vec2 f = vec2((dtx.y - (w*dtx.x*(1.0 - 2.0*rtex.x))/gd), (dty.y - (w*dty.x*(1.0 - 2.0*rtex.x))/gd));
-
- // FIXME: will we ever set gcu_Alpha != 1.0 ? If not, a==alpha!
- float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_TexCoord.y), 0.0, 1.0);
- alpha = gcu_Alpha * a;
- }
- }
-
- gl_FragColor = vec4(c, alpha);
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl
index 5bbd5de14..cd014b732 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl
@@ -2,21 +2,20 @@
#ifndef uniforms_glsl
#define uniforms_glsl
-uniform mat4 gcu_PMVMatrix[3]; // P, Mv, and Mvi
-uniform vec3 gcu_ColorStatic;
-uniform float gcu_Alpha;
+uniform mat4 gcu_PMVMatrix01[3]; // P, Mv, and Mvi
+uniform vec4 gcu_ColorStatic;
uniform float gcu_Weight;
-uniform sampler2D gcu_TextureUnit;
-// #if __VERSION__ < 130
-uniform vec2 gcu_TextureSize;
-// #endif
+#ifdef USE_COLOR_TEXTURE
+ uniform vec4 gcu_ColorTexBBox;
+#endif
-// const int MAX_TEXTURE_UNITS = 8; // <= gl_MaxTextureImageUnits
-// const int MAX_LIGHTS = 8;
-// uniform mat3 gcu_NormalMatrix; // transpose(inverse(ModelView)).3x3
-// uniform int gcu_ColorEnabled;
-// uniform int gcu_TexCoordEnabled[MAX_TEXTURE_UNITS];
-// uniform int gcu_CullFace;
+uniform mat4 gcu_PMVMatrix02[3]; // P, Mv, and Mvi
+uniform sampler2D gcu_FboTexUnit;
+
+/**
+ * .x .y : texture-, fbo- or screen-size
+ */
+uniform vec2 gcu_FboTexSize;
#endif // uniforms_glsl
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl
index 7a9bc5a07..265ab6915 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/varyings.glsl
@@ -2,8 +2,17 @@
#ifndef varyings_glsl
#define varyings_glsl
-//varying vec4 gcv_FrontColor;
-varying vec2 gcv_TexCoord;
+varying vec3 gcv_CurveParam;
+
+varying vec2 gcv_FboTexCoord;
+
+#ifdef USE_COLOR_TEXTURE
+ varying vec2 gcv_ColorTexCoord;
+#endif
+
+#ifdef USE_COLOR_CHANNEL
+ varying vec4 gcv_Color;
+#endif
#endif // varyings_glsl
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
index 10b6d6847..4473d040f 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
@@ -29,77 +29,85 @@
package jogamp.graph.curve.tess;
import java.util.ArrayList;
-
+import java.util.List;
import com.jogamp.graph.curve.tess.Triangulator;
import com.jogamp.graph.geom.Outline;
import com.jogamp.graph.geom.Triangle;
import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.math.VectorUtil;
+import com.jogamp.opengl.math.VectorUtil;
import jogamp.opengl.Debug;
-/** Constrained Delaunay Triangulation
+/**
+ * Constrained Delaunay Triangulation
* implementation of a list of Outlines that define a set of
* Closed Regions with optional n holes.
- *
*/
-public class CDTriangulator2D implements Triangulator{
-
- protected static final boolean DEBUG = Debug.debug("Triangulation");
-
- private float sharpness = 0.5f;
- private ArrayList<Loop> loops;
- private ArrayList<Vertex> vertices;
-
- private ArrayList<Triangle> triangles;
- private int maxTriID = 0;
-
-
+public class CDTriangulator2D implements Triangulator {
+
+ protected static final boolean DEBUG = Debug.debug("graph.curve.Triangulation");
+
+ private static final boolean TEST_LINE_AA = Debug.debug("graph.curve.triangulation.LINE_AA");
+ private static final boolean TEST_MARK_LINE = Debug.debug("graph.curve.triangulation.MARK_AA");
+ private static final boolean TEST_ENABLED = TEST_LINE_AA || TEST_MARK_LINE;
+
+ private final ArrayList<Loop> loops = new ArrayList<Loop>();
+
+ private int addedVerticeCount;
+ private int maxTriID;
+
+
/** Constructor for a new Delaunay triangulator
*/
public CDTriangulator2D() {
reset();
}
-
- /** Reset the triangulation to initial state
- * Clearing cached data
- */
- public void reset() {
+
+ @Override
+ public final void reset() {
maxTriID = 0;
- vertices = new ArrayList<Vertex>();
- triangles = new ArrayList<Triangle>(3);
- loops = new ArrayList<Loop>();
+ addedVerticeCount = 0;
+ loops.clear();
+ }
+
+ @Override
+ public final int getAddedVerticeCount() {
+ return addedVerticeCount;
}
-
- public void addCurve(Outline polyline) {
+
+
+ @Override
+ public final void addCurve(final List<Triangle> sink, final Outline polyline, final float sharpness) {
Loop loop = null;
-
+
if(!loops.isEmpty()) {
loop = getContainerLoop(polyline);
}
-
+
if(loop == null) {
- GraphOutline outline = new GraphOutline(polyline);
- GraphOutline innerPoly = extractBoundaryTriangles(outline, false);
- vertices.addAll(polyline.getVertices());
+ final GraphOutline outline = new GraphOutline(polyline);
+ final GraphOutline innerPoly = extractBoundaryTriangles(sink, outline, false, sharpness);
+ // vertices.addAll(polyline.getVertices());
loop = new Loop(innerPoly, VectorUtil.Winding.CCW);
loops.add(loop);
} else {
- GraphOutline outline = new GraphOutline(polyline);
- GraphOutline innerPoly = extractBoundaryTriangles(outline, true);
- vertices.addAll(innerPoly.getVertices());
+ final GraphOutline outline = new GraphOutline(polyline);
+ final GraphOutline innerPoly = extractBoundaryTriangles(sink, outline, true, sharpness);
+ // vertices.addAll(innerPoly.getVertices());
loop.addConstraintCurve(innerPoly);
}
}
-
- public ArrayList<Triangle> generate() {
- for(int i=0;i<loops.size();i++) {
- Loop loop = loops.get(i);
+
+ @Override
+ public final void generate(final List<Triangle> sink) {
+ final int loopsSize = loops.size();
+ for(int i=0;i<loopsSize;i++) {
+ final Loop loop = loops.get(i);
int numTries = 0;
int size = loop.computeLoopSize();
while(!loop.isSimplex()){
- Triangle tri = null;
+ final Triangle tri;
if(numTries > size){
tri = loop.cut(false);
}
@@ -112,90 +120,113 @@ public class CDTriangulator2D implements Triangulator{
numTries = 0;
size--;
tri.setId(maxTriID++);
- triangles.add(tri);
+ sink.add(tri);
if(DEBUG){
- System.err.println(tri);
+ System.err.println("CDTri.gen["+i+"].0: "+tri);
}
}
if(numTries > size*2){
if(DEBUG){
- System.err.println("Triangulation not complete!");
+ System.err.println("CDTri.gen["+i+"].X: Triangulation not complete!");
}
break;
}
}
- Triangle tri = loop.cut(true);
- if(tri != null)
- triangles.add(tri);
+ final Triangle tri = loop.cut(true);
+ if(tri != null) {
+ sink.add(tri);
+ if(DEBUG){
+ System.err.println("CDTri.gen["+i+"].1: "+tri);
+ }
+ }
+ }
+ if( TEST_ENABLED ) {
+ final float[] tempV2 = new float[2];
+ final CDTriangulator2DExpAddOn addOn = new CDTriangulator2DExpAddOn();
+ final int sinkSize = sink.size();
+ if( TEST_MARK_LINE ) {
+ for(int i=0; i<sinkSize; i++) {
+ final Triangle t0 = sink.get(i);
+ addOn.markLineInTriangle(t0, tempV2);
+ }
+ } else if ( TEST_LINE_AA ){
+ for(int i=0; i<sinkSize-1; i+=2) {
+ final Triangle t0 = sink.get(i);
+ final Triangle t1 = sink.get(i+1);
+ /* final float[] rect = */ addOn.processLineAA(i, t0, t1, tempV2);
+ }
+ }
}
- return triangles;
}
- private GraphOutline extractBoundaryTriangles(GraphOutline outline, boolean hole) {
- GraphOutline innerOutline = new GraphOutline();
- ArrayList<GraphVertex> outVertices = outline.getGraphPoint();
- int size = outVertices.size();
+ private GraphOutline extractBoundaryTriangles(final List<Triangle> sink, final GraphOutline outline, final boolean hole, final float sharpness) {
+ final GraphOutline innerOutline = new GraphOutline();
+ final ArrayList<GraphVertex> outVertices = outline.getGraphPoint();
+ final int size = outVertices.size();
for(int i=0; i < size; i++) {
- GraphVertex currentVertex = outVertices.get(i);
- GraphVertex gv0 = outVertices.get((i+size-1)%size);
- GraphVertex gv2 = outVertices.get((i+1)%size);
- GraphVertex gv1 = currentVertex;
-
- if(!currentVertex.getPoint().isOnCurve()) {
- Vertex v0 = gv0.getPoint().clone();
- Vertex v2 = gv2.getPoint().clone();
- Vertex v1 = gv1.getPoint().clone();
-
+ final GraphVertex gv1 = outVertices.get(i); // currentVertex
+ final GraphVertex gv0 = outVertices.get((i+size-1)%size); // -1
+ final GraphVertex gv2 = outVertices.get((i+1)%size); // +1
+
+ if( !gv1.getPoint().isOnCurve() ) {
+ final Vertex v0 = gv0.getPoint().clone();
+ final Vertex v2 = gv2.getPoint().clone();
+ final Vertex v1 = gv1.getPoint().clone();
+ addedVerticeCount += 3;
+ final boolean[] boundaryVertices = { true, true, true };
+
gv0.setBoundaryContained(true);
gv1.setBoundaryContained(true);
gv2.setBoundaryContained(true);
-
+
final Triangle t;
final boolean holeLike;
if(VectorUtil.ccw(v0,v1,v2)) {
holeLike = false;
- t = new Triangle(v0, v1, v2);
+ t = new Triangle(v0, v1, v2, boundaryVertices);
} else {
holeLike = true;
- t = new Triangle(v2, v1, v0);
+ t = new Triangle(v2, v1, v0, boundaryVertices);
}
t.setId(maxTriID++);
- triangles.add(t);
+ sink.add(t);
if(DEBUG){
System.err.println(t);
}
if( hole || holeLike ) {
- v0.setTexCoord(0, -0.1f);
- v2.setTexCoord(1, -0.1f);
- v1.setTexCoord(0.5f, -1*sharpness -0.1f);
- innerOutline.addVertex(currentVertex);
+ v0.setTexCoord(0.0f, -0.1f, 0f);
+ v2.setTexCoord(1.0f, -0.1f, 0f);
+ v1.setTexCoord(0.5f, -sharpness-0.1f, 0f);
+ innerOutline.addVertex(gv1);
} else {
- v0.setTexCoord(0, 0.1f);
- v2.setTexCoord(1, 0.1f);
- v1.setTexCoord(0.5f, sharpness+0.1f);
+ v0.setTexCoord(0.0f, 0.1f, 0f);
+ v2.setTexCoord(1.0f, 0.1f, 0f);
+ v1.setTexCoord(0.5f, sharpness+0.1f, 0f);
}
- }
- else {
- if(!gv2.getPoint().isOnCurve() || !gv0.getPoint().isOnCurve()){
- currentVertex.setBoundaryContained(true);
+ if(DEBUG) {
+ System.err.println("CDTri.ebt["+i+"].0: hole "+(hole || holeLike)+" "+gv1+", "+t);
+ }
+ } else {
+ if( !gv2.getPoint().isOnCurve() || !gv0.getPoint().isOnCurve() ) {
+ gv1.setBoundaryContained(true);
+ }
+ innerOutline.addVertex(gv1);
+ if(DEBUG) {
+ System.err.println("CDTri.ebt["+i+"].1: "+gv1);
}
- innerOutline.addVertex(currentVertex);
}
}
return innerOutline;
}
-
- private Loop getContainerLoop(Outline polyline) {
- ArrayList<Vertex> vertices = polyline.getVertices();
+
+ private Loop getContainerLoop(final Outline polyline) {
+ final ArrayList<Vertex> vertices = polyline.getVertices();
for(int i=0; i < loops.size(); i++) {
- Loop loop = loops.get(i);
- boolean inside = false;
+ final Loop loop = loops.get(i);
for(int j=0; j < vertices.size(); j++) {
- Vertex v = vertices.get(j);
- inside |= loop.checkInside(v);
- }
- if(inside) {
- return loop;
+ if( loop.checkInside( vertices.get(j) ) ) {
+ return loop;
+ }
}
}
return null;
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2DExpAddOn.java b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2DExpAddOn.java
new file mode 100644
index 000000000..a836e2023
--- /dev/null
+++ b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2DExpAddOn.java
@@ -0,0 +1,340 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.graph.curve.tess;
+
+import com.jogamp.graph.geom.Triangle;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.VectorUtil;
+
+/**
+ * Experimental Add-On ..
+ *
+ * Disabled by default
+ */
+public class CDTriangulator2DExpAddOn {
+
+ private final float[] tempV3a = new float[3];
+ private final float[] tempV3b = new float[3];
+
+ protected final void markLineInTriangle(final Triangle tri1, final float[] tempV2) {
+ if( !tri1.isOnCurve() || !tri1.isLine() ) {
+ return;
+ }
+
+ final boolean[] boundVs = tri1.getVerticesBoundary();
+ final Vertex[] triVs = tri1.getVertices();
+ final Vertex v0 = triVs[0];
+ final Vertex v1 = triVs[1];
+ final Vertex v2 = triVs[2];
+
+ int lineSegCount = 0;
+ final boolean v0IsLS, v1IsLS, v2IsLS;
+ if( v0.isOnCurve() && VectorUtil.isVec2Zero(v0.getTexCoord(), 0) && !boundVs[0] ) {
+ v0IsLS = true;
+ lineSegCount++;
+ } else {
+ v0IsLS = false;
+ }
+ if( v1.isOnCurve() && VectorUtil.isVec2Zero(v1.getTexCoord(), 0) && !boundVs[1] ) {
+ v1IsLS = true;
+ lineSegCount++;
+ } else {
+ v1IsLS = false;
+ }
+ if( v2.isOnCurve() && VectorUtil.isVec2Zero(v2.getTexCoord(), 0) && !boundVs[2] ) {
+ v2IsLS = true;
+ lineSegCount++;
+ } else {
+ v2IsLS = false;
+ }
+ if( 2 > lineSegCount ) {
+ return;
+ } else {
+ if(CDTriangulator2D.DEBUG) {
+ System.err.println("CDTri.markLine.1: "+tri1);
+ System.err.println("CDTri.markLine.1: count "+lineSegCount+", v0IsLS "+v0IsLS+", v1IsLS "+v1IsLS+", v2IsLS "+v2IsLS);
+ }
+ final float texZTag = 2f;
+ if( true ) {
+ if( v0IsLS ) {
+ v0.setTexCoord(0f, 0f, texZTag);
+ }
+ if( v1IsLS ) {
+ v1.setTexCoord(0f, 0f, texZTag);
+ }
+ if( v2IsLS ) {
+ v2.setTexCoord(0f, 0f, texZTag);
+ }
+ } else {
+ if( v0IsLS ) {
+ final Vertex v = v0.clone();
+ v.setTexCoord(0f, 0f, texZTag);
+ triVs[0] = v;
+ }
+ if( v1IsLS ) {
+ final Vertex v = v1.clone();
+ v.setTexCoord(0f, 0f, texZTag);
+ triVs[1] = v;
+ }
+ if( v2IsLS ) {
+ final Vertex v = v2.clone();
+ v.setTexCoord(0f, 0f, texZTag);
+ triVs[2] = v;
+ }
+ }
+ if ( false ) {
+ final Vertex vL1, vL2, vL3, vO;
+ if( 3 == lineSegCount ) {
+ vL1 = v0; vL2=v1; vL3=v2; vO=null;
+ } else if( v0IsLS && v1IsLS ) {
+ vL1 = v0; vL2=v1; vL3=null; vO=v2;
+ } else if( v0IsLS && v2IsLS ) {
+ vL1 = v0; vL2=v2; vL3=null; vO=v1;
+ } else if( v1IsLS && v2IsLS ) {
+ vL1 = v1; vL2=v2; vL3=null; vO=v0;
+ } else {
+ return; // unreachable
+ }
+ if( null != vL1 ) {
+ vL1.setTexCoord(texZTag, 0f, 0f);
+ }
+ if( null != vL2 ) {
+ vL2.setTexCoord(texZTag, 0f, 0f);
+ }
+ if( null != vL3 ) {
+ vL3.setTexCoord(texZTag, 0f, 0f);
+ }
+ }
+ }
+ }
+
+ /**
+ * If this and the other triangle compose a rectangle return the
+ * given <code>tempV2</code> array w/ shortest side first.
+ * Otherwise return null;
+ * <p>
+ * Experimental CODE, enabled only if {@link #TEST_LINE_AA} is set .. WIP
+ * </p>
+ * <p>
+ One test uses method: ROESSLER-2012-OGLES <http://www.cg.tuwien.ac.at/research/publications/2012/ROESSLER-2012-OGLES/>
+ * </p>
+ * <p>
+ * However, we would need to tesselate all lines appropriately,
+ * i.e. create 2 triangles sharing the middle actual line using thickness+radius.
+ *
+ * This test simply used our default font w/ a line thickness of 2 pixels,
+ * which produced mentioned rectangles.
+ * This is of course not the case for arbitrary Outline shapes.
+ * </p>
+ * @param tri2
+ * @param checkThisOnCurve
+ * @param tempV2 temp float[2] storage
+ */
+ protected final float[] processLineAA(final int i, final Triangle tri1, final Triangle tri2, final float[] tempV2) {
+ if(CDTriangulator2D.DEBUG){
+ System.err.println("CDTri.genP2["+i+"].1: ? t1 "+tri1);
+ System.err.println("CDTri.genP2["+i+"].1: ? t2 "+tri2);
+ }
+ final float[] rect = processLineAAImpl(tri1, tri2, tempV2);
+ if(CDTriangulator2D.DEBUG){
+ if( null != rect ) {
+ System.err.println("CDTri.genP2["+i+"].1: RECT ["+rect[0]+", "+rect[1]+"]");
+ System.err.println("CDTri.genP2["+i+"].1: RECT t1 "+tri1);
+ System.err.println("CDTri.genP2["+i+"].1: RECT t2 "+tri2);
+ } else {
+ System.err.println("CDTri.genP2["+i+"].1: RECT NOPE, t1 "+tri1);
+ System.err.println("CDTri.genP2["+i+"].1: RECT NOPE, t2 "+tri2);
+ }
+ }
+ return rect;
+ }
+ private final float[] processLineAAImpl(final Triangle tri1, final Triangle tri2, final float[] tempV2) {
+ if( !tri1.isOnCurve() || !tri2.isOnCurve() || !tri1.isLine() || !tri2.isLine() ) {
+ return null;
+ }
+ final float[] rect;
+ int eqCount = 0;
+ final int[] commonIdxA = { -1, -1 };
+ final int[] commonIdxB = { -1, -1 };
+ final Vertex[] verts1 = tri1.getVertices();
+ final Vertex[] verts2 = tri2.getVertices();
+ float[] coord = verts1[0].getCoord();
+ if( VectorUtil.isVec3Equal(coord, 0, verts2[0].getCoord(), 0, FloatUtil.EPSILON) ) {
+ commonIdxA[eqCount] = 0;
+ commonIdxB[eqCount] = 0;
+ eqCount++;
+ } else if( VectorUtil.isVec3Equal(coord, 0, verts2[1].getCoord(), 0, FloatUtil.EPSILON) ) {
+ commonIdxA[eqCount] = 0;
+ commonIdxB[eqCount] = 1;
+ eqCount++;
+ } else if( VectorUtil.isVec3Equal(coord, 0, verts2[2].getCoord(), 0, FloatUtil.EPSILON) ) {
+ commonIdxA[eqCount] = 0;
+ commonIdxB[eqCount] = 2;
+ eqCount++;
+ }
+ coord = verts1[1].getCoord();
+ if( VectorUtil.isVec3Equal(coord, 0, verts2[0].getCoord(), 0, FloatUtil.EPSILON) ) {
+ commonIdxA[eqCount] = 1;
+ commonIdxB[eqCount] = 0;
+ eqCount++;
+ } else if( VectorUtil.isVec3Equal(coord, 0, verts2[1].getCoord(), 0, FloatUtil.EPSILON) ) {
+ commonIdxA[eqCount] = 1;
+ commonIdxB[eqCount] = 1;
+ eqCount++;
+ } else if( VectorUtil.isVec3Equal(coord, 0, verts2[2].getCoord(), 0, FloatUtil.EPSILON) ) {
+ commonIdxA[eqCount] = 1;
+ commonIdxB[eqCount] = 2;
+ eqCount++;
+ }
+ final int otherIdxA;
+ if( 2 == eqCount ) {
+ otherIdxA = 3 - ( commonIdxA[0] + commonIdxA[1] );
+ } else {
+ coord = verts1[2].getCoord();
+ if( VectorUtil.isVec3Equal(coord, 0, verts2[0].getCoord(), 0, FloatUtil.EPSILON) ) {
+ commonIdxA[eqCount] = 2;
+ commonIdxB[eqCount] = 0;
+ eqCount++;
+ } else if( VectorUtil.isVec3Equal(coord, 0, verts2[1].getCoord(), 0, FloatUtil.EPSILON) ) {
+ commonIdxA[eqCount] = 2;
+ commonIdxB[eqCount] = 1;
+ eqCount++;
+ } else if( VectorUtil.isVec3Equal(coord, 0, verts2[2].getCoord(), 0, FloatUtil.EPSILON) ) {
+ commonIdxA[eqCount] = 2;
+ commonIdxB[eqCount] = 2;
+ eqCount++;
+ }
+ if( 2 == eqCount ) {
+ otherIdxA = 3 - ( commonIdxA[0] + commonIdxA[1] );
+ } else {
+ otherIdxA = -1;
+ }
+ }
+ if( 0 <= otherIdxA && commonIdxB[0] != commonIdxB[1] ) {
+ final int otherIdxB = 3 - ( commonIdxB[0] + commonIdxB[1] );
+ // Reference must be equal, i.e. sharing the actual same vertices!
+ if( verts1[commonIdxA[0]] != verts2[commonIdxB[0]] || verts1[commonIdxA[1]] != verts2[commonIdxB[1]] ) {
+ throw new InternalError("XXX: diff shared verts"); // FIXME remove when clear
+ }
+ final Vertex vC0A, vC1A, vOA, vOB;
+ if( false ) {
+ // Fetch only!
+ vC0A = verts1[commonIdxA[0]];
+ vC1A = verts1[commonIdxA[1]];
+ vOA = verts1[otherIdxA];
+ vOB = verts2[otherIdxB];
+ } else {
+ // Fetch and clone, write-back to triangles
+ vC0A = verts1[commonIdxA[0]].clone();
+ verts1[commonIdxA[0]] = vC0A;
+ verts2[commonIdxB[0]] = vC0A;
+ vC1A = verts1[commonIdxA[1]].clone();
+ verts1[commonIdxA[1]] = vC1A;
+ verts2[commonIdxB[1]] = vC1A;
+ vOA = verts1[otherIdxA].clone();
+ verts1[otherIdxA] = vOA;
+ vOB = verts2[otherIdxB].clone();
+ verts2[otherIdxB] = vOB;
+ }
+
+ final float texZTag = 2f;
+ final float[] vOACoords = vOA.getCoord();
+ final float dOC0A = VectorUtil.distVec3(vOACoords, vC0A.getCoord());
+ final float dOC1A = VectorUtil.distVec3(vOACoords, vC1A.getCoord());
+ if( false ) {
+ final float[] vec3Z = { 0f, 0f, -1f };
+ final float[] vecLongSide, vecLineHeight;
+ if( dOC0A < dOC1A ) {
+ tempV2[0] = dOC0A; // line width
+ tempV2[1] = dOC1A; // long side
+ vecLongSide = VectorUtil.normalizeVec3( VectorUtil.subVec2(tempV3a, vOACoords, vC1A.getCoord()) ); // normal long side vector
+ vecLineHeight = VectorUtil.crossVec3(tempV3b, vec3Z, tempV3a); // the line-height vector (normal)
+ vOA.setTexCoord(-1f, -1f, texZTag);
+ vC1A.setTexCoord(1f, -1f, texZTag);
+ vOB.setTexCoord(0f, 1f, texZTag);
+ vC0A.setTexCoord(0f, 1f, texZTag);
+ } else {
+ tempV2[0] = dOC1A; // line width
+ tempV2[1] = dOC0A; // long side
+ vecLongSide = VectorUtil.normalizeVec3( VectorUtil.subVec2(tempV3a, vOACoords, vC0A.getCoord()) ); // normal long side vector
+ vecLineHeight = VectorUtil.crossVec3(tempV3b, vec3Z, tempV3a); // the line-height vector (normal)
+ }
+ if(CDTriangulator2D.DEBUG){
+ System.err.println("RECT.0 : long-side-vec "+vecLongSide[0]+", "+vecLongSide[1]+", "+vecLongSide[2]);
+ System.err.println("RECT.0 : line-height-vec "+vecLineHeight[0]+", "+vecLineHeight[1]+", "+vecLineHeight[2]);
+ }
+
+ } else {
+ /**
+ * Using method: ROESSLER-2012-OGLES <http://www.cg.tuwien.ac.at/research/publications/2012/ROESSLER-2012-OGLES/>
+ *
+ * Arbitrary but consistently pick left/right and set texCoords, FIXME: validate
+ *
+ * Testing w/ fixed line-width 1, and radius 1/3.
+ */
+ final float lineWidth;
+ final Vertex vL1, vL2, vR1, vR2;
+ if( dOC0A < dOC1A ) {
+ lineWidth = dOC0A; // line width
+ tempV2[0] = dOC0A; // line width
+ tempV2[1] = dOC1A; // long side
+ // Left: vOA, vC1A
+ // Right: vOB, vC0A
+ vL1 = vOA; vL2 = vC1A;
+ vR1 = vOB; vR2 = vC0A;
+ } else {
+ lineWidth = dOC1A; // line width
+ tempV2[0] = dOC1A; // line width
+ tempV2[1] = dOC0A; // long side
+ // Left: vOB, vC1A
+ // Right: vOA, vC0A
+ vL1 = vOB; vL2 = vC1A;
+ vR1 = vOA; vR2 = vC0A;
+ }
+ final float r = lineWidth/3f;
+ final float wa = lineWidth + r;
+ final float waHalf = wa / 2f;
+ vL1.setTexCoord(lineWidth, waHalf, texZTag);
+ vL2.setTexCoord(lineWidth, waHalf, texZTag);
+ vR1.setTexCoord(lineWidth, -waHalf, texZTag);
+ vR2.setTexCoord(lineWidth, -waHalf, texZTag);
+ if(CDTriangulator2D.DEBUG){
+ System.err.println("RECT.0 : lineWidth: "+lineWidth+", dim "+dOC0A+" x "+dOC1A+", radius "+r);
+ System.err.println("RECT Left.0: "+vL1+", "+vL2);
+ System.err.println("RECT Right.0: "+vR1+", "+vR2);
+ }
+ }
+ rect = tempV2;
+ } else {
+ rect = null;
+ }
+ return rect;
+ }
+}
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java b/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
index c8251af15..81e6efdad 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
@@ -35,18 +35,18 @@ import com.jogamp.graph.geom.Vertex;
public class GraphOutline {
final private Outline outline;
final private ArrayList<GraphVertex> controlpoints = new ArrayList<GraphVertex>(3);
-
+
public GraphOutline(){
this.outline = new Outline();
}
-
+
/**Create a control polyline of control vertices
- * the curve pieces can be identified by onCurve flag
+ * the curve pieces can be identified by onCurve flag
* of each cp the control polyline is open by default
*/
- public GraphOutline(Outline ol){
+ public GraphOutline(final Outline ol){
this.outline = ol;
- ArrayList<Vertex> vertices = this.outline.getVertices();
+ final ArrayList<Vertex> vertices = this.outline.getVertices();
for(int i = 0; i< vertices.size(); i++){
this.controlpoints.add(new GraphVertex(vertices.get(i)));
}
@@ -59,14 +59,14 @@ public class GraphOutline {
public ArrayList<GraphVertex> getGraphPoint() {
return controlpoints;
}
-
+
public ArrayList<Vertex> getVertices() {
return outline.getVertices();
}
- public void addVertex(GraphVertex v) {
+ public void addVertex(final GraphVertex v) {
controlpoints.add(v);
outline.addVertex(v.getPoint());
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/GraphVertex.java b/src/jogl/classes/jogamp/graph/curve/tess/GraphVertex.java
index 52d02baa5..391e71011 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/GraphVertex.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/GraphVertex.java
@@ -35,23 +35,23 @@ public class GraphVertex {
private Vertex point;
private ArrayList<HEdge> edges = null;
private boolean boundaryContained = false;
-
- public GraphVertex(Vertex point) {
+
+ public GraphVertex(final Vertex point) {
this.point = point;
}
public Vertex getPoint() {
return point;
}
-
+
public float getX(){
return point.getX();
}
-
+
public float getY(){
return point.getY();
}
-
+
public float getZ(){
return point.getZ();
}
@@ -59,7 +59,7 @@ public class GraphVertex {
return point.getCoord();
}
- public void setPoint(Vertex point) {
+ public void setPoint(final Vertex point) {
this.point = point;
}
@@ -67,17 +67,17 @@ public class GraphVertex {
return edges;
}
- public void setEdges(ArrayList<HEdge> edges) {
+ public void setEdges(final ArrayList<HEdge> edges) {
this.edges = edges;
}
-
- public void addEdge(HEdge edge){
+
+ public void addEdge(final HEdge edge){
if(edges == null){
edges = new ArrayList<HEdge>();
}
edges.add(edge);
}
- public void removeEdge(HEdge edge){
+ public void removeEdge(final HEdge edge){
if(edges == null)
return;
edges.remove(edge);
@@ -85,9 +85,9 @@ public class GraphVertex {
edges = null;
}
}
- public HEdge findNextEdge(GraphVertex nextVert){
+ public HEdge findNextEdge(final GraphVertex nextVert){
for(int i=0; i<edges.size(); i++) {
- HEdge e = edges.get(i);
+ final HEdge e = edges.get(i);
if(e.getNext().getGraphPoint() == nextVert){
return e;
}
@@ -96,28 +96,32 @@ public class GraphVertex {
}
public HEdge findBoundEdge(){
for(int i=0; i<edges.size(); i++) {
- HEdge e = edges.get(i);
+ final HEdge e = edges.get(i);
if((e.getType() == HEdge.BOUNDARY) || (e.getType() == HEdge.HOLE)){
return e;
}
}
return null;
}
- public HEdge findPrevEdge(GraphVertex prevVert){
+ public HEdge findPrevEdge(final GraphVertex prevVert){
for(int i=0; i<edges.size(); i++) {
- HEdge e = edges.get(i);
+ final HEdge e = edges.get(i);
if(e.getPrev().getGraphPoint() == prevVert){
return e;
}
}
return null;
}
-
+
public boolean isBoundaryContained() {
return boundaryContained;
}
- public void setBoundaryContained(boolean boundaryContained) {
+ public void setBoundaryContained(final boolean boundaryContained) {
this.boundaryContained = boundaryContained;
}
+
+ public String toString() {
+ return "GraphVertex[contained "+boundaryContained+", "+point+"]";
+ }
}
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/HEdge.java b/src/jogl/classes/jogamp/graph/curve/tess/HEdge.java
index 4d29a81f3..4976fd1fc 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/HEdge.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/HEdge.java
@@ -32,23 +32,23 @@ import com.jogamp.graph.geom.Triangle;
public class HEdge {
- public static int BOUNDARY = 3;
- public static int INNER = 1;
- public static int HOLE = 2;
-
+ public static final int BOUNDARY = 3;
+ public static final int INNER = 1;
+ public static final int HOLE = 2;
+
private GraphVertex vert;
private HEdge prev = null;
private HEdge next = null;
private HEdge sibling = null;
private int type = BOUNDARY;
private Triangle triangle = null;
-
- public HEdge(GraphVertex vert, int type) {
+
+ public HEdge(final GraphVertex vert, final int type) {
this.vert = vert;
this.type = type;
}
- public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type) {
+ public HEdge(final GraphVertex vert, final HEdge prev, final HEdge next, final HEdge sibling, final int type) {
this.vert = vert;
this.prev = prev;
this.next = next;
@@ -56,7 +56,7 @@ public class HEdge {
this.type = type;
}
- public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type, Triangle triangle) {
+ public HEdge(final GraphVertex vert, final HEdge prev, final HEdge next, final HEdge sibling, final int type, final Triangle triangle) {
this.vert = vert;
this.prev = prev;
this.next = next;
@@ -69,7 +69,7 @@ public class HEdge {
return vert;
}
- public void setVert(GraphVertex vert) {
+ public void setVert(final GraphVertex vert) {
this.vert = vert;
}
@@ -77,7 +77,7 @@ public class HEdge {
return prev;
}
- public void setPrev(HEdge prev) {
+ public void setPrev(final HEdge prev) {
this.prev = prev;
}
@@ -85,7 +85,7 @@ public class HEdge {
return next;
}
- public void setNext(HEdge next) {
+ public void setNext(final HEdge next) {
this.next = next;
}
@@ -93,7 +93,7 @@ public class HEdge {
return sibling;
}
- public void setSibling(HEdge sibling) {
+ public void setSibling(final HEdge sibling) {
this.sibling = sibling;
}
@@ -101,7 +101,7 @@ public class HEdge {
return type;
}
- public void setType(int type) {
+ public void setType(final int type) {
this.type = type;
}
@@ -109,22 +109,22 @@ public class HEdge {
return triangle;
}
- public void setTriangle(Triangle triangle) {
+ public void setTriangle(final Triangle triangle) {
this.triangle = triangle;
}
-
- public static <T extends Vertex> void connect(HEdge first, HEdge next){
+
+ public static <T extends Vertex> void connect(final HEdge first, final HEdge next){
first.setNext(next);
next.setPrev(first);
}
-
- public static <T extends Vertex> void makeSiblings(HEdge first, HEdge second){
+
+ public static <T extends Vertex> void makeSiblings(final HEdge first, final HEdge second){
first.setSibling(second);
second.setSibling(first);
}
-
+
public boolean vertexOnCurveVertex(){
return vert.getPoint().isOnCurve();
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
index b4b796b51..6563219cc 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
@@ -30,17 +30,17 @@ package jogamp.graph.curve.tess;
import java.util.ArrayList;
-import com.jogamp.graph.geom.AABBox;
import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.geom.Triangle;
-import com.jogamp.graph.math.VectorUtil;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.math.geom.AABBox;
public class Loop {
private HEdge root = null;
- private AABBox box = new AABBox();
+ private final AABBox box = new AABBox();
private GraphOutline initialOutline = null;
- public Loop(GraphOutline polyline, VectorUtil.Winding winding){
+ public Loop(final GraphOutline polyline, final VectorUtil.Winding winding){
initialOutline = polyline;
this.root = initFromPolyline(initialOutline, winding);
}
@@ -49,27 +49,25 @@ public class Loop {
return root;
}
- public Triangle cut(boolean delaunay){
+ public Triangle cut(final boolean delaunay){
if(isSimplex()){
- Triangle t = new Triangle(root.getGraphPoint().getPoint(), root.getNext().getGraphPoint().getPoint(),
- root.getNext().getNext().getGraphPoint().getPoint());
- t.setVerticesBoundary(checkVerticesBoundary(root));
- return t;
+ return new Triangle(root.getGraphPoint().getPoint(), root.getNext().getGraphPoint().getPoint(),
+ root.getNext().getNext().getGraphPoint().getPoint(), checkVerticesBoundary(root));
}
- HEdge prev = root.getPrev();
- HEdge next1 = root.getNext();
+ final HEdge prev = root.getPrev();
+ final HEdge next1 = root.getNext();
- HEdge next2 = findClosestValidNeighbor(next1.getNext(), delaunay);
+ final HEdge next2 = findClosestValidNeighbor(next1.getNext(), delaunay);
if(next2 == null){
root = root.getNext();
return null;
}
- GraphVertex v1 = root.getGraphPoint();
- GraphVertex v2 = next1.getGraphPoint();
- GraphVertex v3 = next2.getGraphPoint();
+ final GraphVertex v1 = root.getGraphPoint();
+ final GraphVertex v2 = next1.getGraphPoint();
+ final GraphVertex v3 = next2.getGraphPoint();
- HEdge v3Edge = new HEdge(v3, HEdge.INNER);
+ final HEdge v3Edge = new HEdge(v3, HEdge.INNER);
HEdge.connect(v3Edge, root);
HEdge.connect(next1, v3Edge);
@@ -83,7 +81,7 @@ public class Loop {
HEdge.connect(prev, v3EdgeSib);
HEdge.connect(v3EdgeSib, next2);
- Triangle t = createTriangle(v1.getPoint(), v2.getPoint(), v3.getPoint(), root);
+ final Triangle t = createTriangle(v1.getPoint(), v2.getPoint(), v3.getPoint(), root);
this.root = next2;
return t;
}
@@ -96,27 +94,27 @@ public class Loop {
* from the boundary profile
* @param reqWinding requested winding of edges (CCW or CW)
*/
- private HEdge initFromPolyline(GraphOutline outline, VectorUtil.Winding reqWinding){
- ArrayList<GraphVertex> vertices = outline.getGraphPoint();
+ private HEdge initFromPolyline(final GraphOutline outline, final VectorUtil.Winding reqWinding){
+ final ArrayList<GraphVertex> vertices = outline.getGraphPoint();
if(vertices.size()<3) {
throw new IllegalArgumentException("outline's vertices < 3: " + vertices.size());
}
final VectorUtil.Winding hasWinding = VectorUtil.getWinding(
- vertices.get(0).getPoint(),
+ vertices.get(0).getPoint(),
vertices.get(1).getPoint(),
vertices.get(2).getPoint());
//FIXME: handle case when vertices come inverted - Rami
// skips inversion CW -> CCW
final boolean invert = hasWinding != reqWinding &&
reqWinding == VectorUtil.Winding.CW;
-
+
final int max;
final int edgeType = reqWinding == VectorUtil.Winding.CCW ? HEdge.BOUNDARY : HEdge.HOLE ;
int index;
HEdge firstEdge = null;
HEdge lastEdge = null;
-
+
if(!invert) {
max = vertices.size();
index = 0;
@@ -126,10 +124,10 @@ public class Loop {
}
while(index != max){
- GraphVertex v1 = vertices.get(index);
+ final GraphVertex v1 = vertices.get(index);
box.resize(v1.getX(), v1.getY(), v1.getZ());
- HEdge edge = new HEdge(v1, edgeType);
+ final HEdge edge = new HEdge(v1, edgeType);
v1.addEdge(edge);
if(lastEdge != null) {
@@ -157,15 +155,15 @@ public class Loop {
return firstEdge;
}
- public void addConstraintCurve(GraphOutline polyline) {
+ public void addConstraintCurve(final GraphOutline polyline) {
// GraphOutline outline = new GraphOutline(polyline);
/**needed to generate vertex references.*/
- initFromPolyline(polyline, VectorUtil.Winding.CW);
+ initFromPolyline(polyline, VectorUtil.Winding.CW);
- GraphVertex v3 = locateClosestVertex(polyline);
- HEdge v3Edge = v3.findBoundEdge();
- HEdge v3EdgeP = v3Edge.getPrev();
- HEdge crossEdge = new HEdge(root.getGraphPoint(), HEdge.INNER);
+ final GraphVertex v3 = locateClosestVertex(polyline);
+ final HEdge v3Edge = v3.findBoundEdge();
+ final HEdge v3EdgeP = v3Edge.getPrev();
+ final HEdge crossEdge = new HEdge(root.getGraphPoint(), HEdge.INNER);
HEdge.connect(root.getPrev(), crossEdge);
HEdge.connect(crossEdge, v3Edge);
@@ -180,32 +178,32 @@ public class Loop {
HEdge.connect(crossEdgeSib, root);
}
- /** Locates the vertex and update the loops root
- * to have (root + vertex) as closest pair
- * @param polyline the control polyline
+ /** Locates the vertex and update the loops root
+ * to have (root + vertex) as closest pair
+ * @param polyline the control polyline
* to search for closestvertices
* @return the vertex that is closest to the newly set root Hedge.
*/
- private GraphVertex locateClosestVertex(GraphOutline polyline) {
+ private GraphVertex locateClosestVertex(final GraphOutline polyline) {
HEdge closestE = null;
GraphVertex closestV = null;
float minDistance = Float.MAX_VALUE;
boolean inValid = false;
- ArrayList<GraphVertex> initVertices = initialOutline.getGraphPoint();
- ArrayList<GraphVertex> vertices = polyline.getGraphPoint();
+ final ArrayList<GraphVertex> initVertices = initialOutline.getGraphPoint();
+ final ArrayList<GraphVertex> vertices = polyline.getGraphPoint();
for(int i=0; i< initVertices.size()-1; i++){
- GraphVertex v = initVertices.get(i);
- GraphVertex nextV = initVertices.get(i+1);
+ final GraphVertex v = initVertices.get(i);
+ final GraphVertex nextV = initVertices.get(i+1);
for(int pos=0; pos<vertices.size(); pos++) {
- GraphVertex cand = vertices.get(pos);
- float distance = VectorUtil.computeLength(v.getCoord(), cand.getCoord());
+ final GraphVertex cand = vertices.get(pos);
+ final float distance = VectorUtil.distVec3(v.getCoord(), cand.getCoord());
if(distance < minDistance){
- for (GraphVertex vert:vertices){
+ for (final GraphVertex vert:vertices){
if(vert == v || vert == nextV || vert == cand)
continue;
- inValid = VectorUtil.inCircle(v.getPoint(), nextV.getPoint(),
+ inValid = VectorUtil.isInCircleVec2(v.getPoint(), nextV.getPoint(),
cand.getPoint(), vert.getPoint());
if(inValid){
break;
@@ -228,29 +226,29 @@ public class Loop {
return closestV;
}
- private HEdge findClosestValidNeighbor(HEdge edge, boolean delaunay) {
- HEdge next = root.getNext();
+ private HEdge findClosestValidNeighbor(final HEdge edge, final boolean delaunay) {
+ final HEdge next = root.getNext();
if(!VectorUtil.ccw(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(),
edge.getGraphPoint().getPoint())){
return null;
}
- HEdge candEdge = edge;
+ final HEdge candEdge = edge;
boolean inValid = false;
if(delaunay){
- Vertex cand = candEdge.getGraphPoint().getPoint();
+ final Vertex cand = candEdge.getGraphPoint().getPoint();
HEdge e = candEdge.getNext();
while (e != candEdge){
- if(e.getGraphPoint() == root.getGraphPoint()
- || e.getGraphPoint() == next.getGraphPoint()
+ if(e.getGraphPoint() == root.getGraphPoint()
+ || e.getGraphPoint() == next.getGraphPoint()
|| e.getGraphPoint().getPoint() == cand){
e = e.getNext();
continue;
}
- inValid = VectorUtil.inCircle(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(),
- cand, e.getGraphPoint().getPoint());
+ inValid = VectorUtil.isInCircleVec2(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(),
+ cand, e.getGraphPoint().getPoint());
if(inValid){
break;
}
@@ -271,31 +269,25 @@ public class Loop {
* @param root and edge of this triangle
* @return the triangle iff it satisfies, null otherwise
*/
- private Triangle createTriangle(Vertex v1, Vertex v2, Vertex v3, HEdge rootT){
- Triangle t = new Triangle(v1, v2, v3);
- t.setVerticesBoundary(checkVerticesBoundary(rootT));
- return t;
+ private Triangle createTriangle(final Vertex v1, final Vertex v2, final Vertex v3, final HEdge rootT){
+ return new Triangle(v1, v2, v3, checkVerticesBoundary(rootT));
}
- private boolean[] checkVerticesBoundary(HEdge rootT) {
- boolean[] boundary = new boolean[3];
- HEdge e1 = rootT;
- HEdge e2 = rootT.getNext();
- HEdge e3 = rootT.getNext().getNext();
-
- if(e1.getGraphPoint().isBoundaryContained()){
+ private boolean[] checkVerticesBoundary(final HEdge rootT) {
+ final boolean[] boundary = new boolean[3];
+ if(rootT.getGraphPoint().isBoundaryContained()){
boundary[0] = true;
}
- if(e2.getGraphPoint().isBoundaryContained()){
+ if(rootT.getNext().getGraphPoint().isBoundaryContained()){
boundary[1] = true;
}
- if(e3.getGraphPoint().isBoundaryContained()){
+ if(rootT.getNext().getNext().getGraphPoint().isBoundaryContained()){
boundary[2] = true;
}
return boundary;
}
- public boolean checkInside(Vertex v) {
+ public boolean checkInside(final Vertex v) {
if(!box.contains(v.getX(), v.getY(), v.getZ())){
return false;
}
@@ -304,22 +296,22 @@ public class Loop {
HEdge current = root;
HEdge next = root.getNext();
do {
- Vertex v2 = current.getGraphPoint().getPoint();
- Vertex v1 = next.getGraphPoint().getPoint();
+ final Vertex v2 = current.getGraphPoint().getPoint();
+ final Vertex v1 = next.getGraphPoint().getPoint();
if ( ((v1.getY() > v.getY()) != (v2.getY() > v.getY())) &&
(v.getX() < (v2.getX() - v1.getX()) * (v.getY() - v1.getY()) / (v2.getY() - v1.getY()) + v1.getX()) ){
inside = !inside;
}
-
+
current = next;
next = current.getNext();
-
+
} while(current != root);
-
+
return inside;
}
-
+
public int computeLoopSize(){
int size = 0;
HEdge e = root;
diff --git a/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java b/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java
deleted file mode 100644
index 578148699..000000000
--- a/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package jogamp.graph.curve.text;
-
-import java.util.ArrayList;
-
-import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.geom.Triangle;
-import com.jogamp.graph.geom.Vertex.Factory;
-
-import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.math.Quaternion;
-
-public class GlyphShape {
-
- private Quaternion quat= null;
- private OutlineShape shape = null;
-
- /** Create a new Glyph shape
- * based on Parametric curve control polyline
- */
- public GlyphShape(Vertex.Factory<? extends Vertex> factory){
- shape = new OutlineShape(factory);
- }
-
- /** Create a new GlyphShape from a {@link OutlineShape}
- * @param factory vertex impl factory {@link Factory}
- * @param shape {@link OutlineShape} representation of the Glyph
- */
- public GlyphShape(Vertex.Factory<? extends Vertex> factory, OutlineShape shape){
- this(factory);
- this.shape = shape;
- this.shape.transformOutlines(OutlineShape.VerticesState.QUADRATIC_NURBS);
- }
-
- public final Vertex.Factory<? extends Vertex> vertexFactory() { return shape.vertexFactory(); }
-
- public OutlineShape getShape() {
- return shape;
- }
-
- public int getNumVertices() {
- return shape.getVertices().size();
- }
-
- /** Get the rotational Quaternion attached to this Shape
- * @return the Quaternion Object
- */
- public Quaternion getQuat() {
- return quat;
- }
-
- /** Set the Quaternion that shall defien the rotation
- * of this shape.
- * @param quat
- */
- public void setQuat(Quaternion quat) {
- this.quat = quat;
- }
-
- /** Triangluate the glyph shape
- * @return ArrayList of triangles which define this shape
- */
- public ArrayList<Triangle> triangulate(){
- return shape.triangulate();
- }
-
- /** Get the list of Vertices of this Object
- * @return arrayList of Vertices
- */
- public ArrayList<Vertex> getVertices(){
- return shape.getVertices();
- }
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java b/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java
deleted file mode 100644
index f86d02f40..000000000
--- a/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package jogamp.graph.curve.text;
-
-import java.util.ArrayList;
-
-import com.jogamp.graph.font.Font;
-import com.jogamp.graph.geom.AABBox;
-import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.geom.Triangle;
-import com.jogamp.graph.geom.Vertex.Factory;
-import com.jogamp.graph.geom.opengl.SVertex;
-
-import javax.media.opengl.GL2ES2;
-
-import jogamp.graph.curve.opengl.RegionFactory;
-import jogamp.graph.font.FontInt;
-
-import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.curve.Region;
-import com.jogamp.graph.curve.opengl.GLRegion;
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.opengl.util.PMVMatrix;
-
-public class GlyphString {
- /** Static font size for all default font OutlineShape generations via {@link #createString(OutlineShape, Factory, Font, String)}.
- * <p>The actual font size shall be accomplished by the GL PMV matrix.</p>
- */
- public static final int STATIC_FONT_SIZE = 10;
-
- private ArrayList<GlyphShape> glyphs = new ArrayList<GlyphShape>();
- private CharSequence str;
- private String fontname;
- private GLRegion region;
-
- private SVertex origin = new SVertex();
-
- /**
- * <p>Uses {@link #STATIC_FONT_SIZE}.</p>
- * <p>No caching is performed.</p>
- *
- * @param shape is not null, add all {@link GlyphShape}'s {@link Outline} to this instance.
- * @param vertexFactory vertex impl factory {@link Factory}
- * @param font the target {@link Font}
- * @param str string text
- * @return the created {@link GlyphString} instance
- */
- public static GlyphString createString(OutlineShape shape, Factory<? extends Vertex> vertexFactory, Font font, String str) {
- return createString(shape, vertexFactory, font, STATIC_FONT_SIZE, str);
- }
-
- /**
- * <p>No caching is performed.</p>
- *
- * @param shape is not null, add all {@link GlyphShape}'s {@link Outline} to this instance.
- * @param vertexFactory vertex impl factory {@link Factory}
- * @param font the target {@link Font}
- * @param fontSize font size
- * @param str string text
- * @return the created {@link GlyphString} instance
- */
- public static GlyphString createString(OutlineShape shape, Factory<? extends Vertex> vertexFactory, Font font, int fontSize, String str) {
- ArrayList<OutlineShape> shapes = ((FontInt)font).getOutlineShapes(str, fontSize, vertexFactory);
-
- GlyphString glyphString = new GlyphString(font.getName(Font.NAME_UNIQUNAME), str);
- glyphString.createfromOutlineShapes(vertexFactory, shapes);
- if(null != shape) {
- for(int i=0; i<glyphString.glyphs.size(); i++) {
- shape.addOutlineShape(glyphString.glyphs.get(i).getShape());
- }
- }
- return glyphString;
- }
-
- /** Create a new GlyphString object
- * @param fontname the name of the font that this String is
- * associated with
- * @param str the string object
- */
- public GlyphString(String fontname, CharSequence str){
- this.fontname = fontname;
- this.str = str;
- }
-
- public void addGlyphShape(GlyphShape glyph){
- glyphs.add(glyph);
- }
-
- public CharSequence getString(){
- return str;
- }
-
- /**Creates the Curve based Glyphs from a list of {@link OutlineShape}
- * @param vertexFactory vertex impl factory {@link Factory}
- * @param shapes list of {@link OutlineShape}
- */
- public void createfromOutlineShapes(Factory<? extends Vertex> vertexFactory, ArrayList<OutlineShape> shapes) {
- final int numGlyps = shapes.size();
- for (int index=0;index<numGlyps;index++){
- if(shapes.get(index) == null){
- continue;
- }
- GlyphShape glyphShape = new GlyphShape(vertexFactory, shapes.get(index));
-
- if(glyphShape.getNumVertices() < 3) {
- continue;
- }
- addGlyphShape(glyphShape);
- }
- }
-
-
- /** Generate a OGL Region to represent this Object.
- * @param gl the current gl object
- * @param rs the current attached RenderState
- * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, {@link Region#VBAA_RENDERING_BIT}
- */
- public GLRegion createRegion(GL2ES2 gl, int renderModes){
- region = RegionFactory.create(renderModes);
- // region.setFlipped(true);
-
- int numVertices = region.getNumVertices();
-
- for(int i=0; i< glyphs.size(); i++) {
- final GlyphShape glyph = glyphs.get(i);
- ArrayList<Triangle> gtris = glyph.triangulate();
- region.addTriangles(gtris);
-
- final ArrayList<Vertex> gVertices = glyph.getVertices();
- for(int j=0; j<gVertices.size(); j++) {
- final Vertex gVert = gVertices.get(j);
- gVert.setId(numVertices++);
- region.addVertex(gVert);
- }
- }
- return region;
- }
-
- /** Generate a Hashcode for this object
- * @return a string defining the hashcode
- */
- public String getTextHashCode(){
- return "" + fontname.hashCode() + str.hashCode();
- }
-
- /** Render the Object based using the associated Region
- * previously generated.
- */
- public void renderString3D(GL2ES2 gl) {
- region.draw(gl, null, 0, 0, null);
- }
- /** Render the Object based using the associated Region
- * previously generated.
- * @param matrix current {@link PMVMatrix}.
- * @param rs the RenderState to be used
- * @param vp_width current screen width
- * @param vp_height current screen height
- * @param texWidth desired texture width for multipass-rendering.
- * The actual used texture-width is written back when mp rendering is enabled, otherwise the store is untouched.
- */
- public void renderString3D(GL2ES2 gl, RenderState rs, int vp_width, int vp_height, int[/*1*/] texWidth) {
- region.draw(gl, rs, vp_width, vp_height, texWidth);
- }
-
- /** Get the Origin of this GlyphString
- * @return
- */
- public Vertex getOrigin() {
- return origin;
- }
-
- /** Destroy the associated OGL objects
- * @param rs the current attached RenderState
- */
- public void destroy(GL2ES2 gl, RenderState rs) {
- if(null != gl && null != rs) {
- region.destroy(gl, rs);
- region = null;
- } else if(null != region) {
- throw new InternalError("destroy called w/o GL context, but has a region");
- }
- glyphs.clear();
- }
-
- public AABBox getBounds(){
- return region.getBounds();
- }
-}
diff --git a/src/jogl/classes/jogamp/graph/font/FontConstructor.java b/src/jogl/classes/jogamp/graph/font/FontConstructor.java
index b452ae548..2732d07cb 100644
--- a/src/jogl/classes/jogamp/graph/font/FontConstructor.java
+++ b/src/jogl/classes/jogamp/graph/font/FontConstructor.java
@@ -29,11 +29,19 @@ package jogamp.graph.font;
import java.io.File;
import java.io.IOException;
-import java.net.URLConnection;
+import java.io.InputStream;
import com.jogamp.graph.font.Font;
public interface FontConstructor {
- Font create(File file) throws IOException ;
- Font create(URLConnection url) throws IOException ;
+ /**
+ * @param file The font file
+ */
+ Font create(final File file) throws IOException;
+
+ /**
+ * @param istream The font input stream
+ * @param streamLen the length of the font segment in the stream
+ */
+ Font create(final InputStream stream, int streamLen) throws IOException;
}
diff --git a/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java b/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java
index a00e9579c..da651cca9 100644
--- a/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java
+++ b/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java
@@ -27,8 +27,11 @@
*/
package jogamp.graph.font;
+import java.io.BufferedInputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -40,13 +43,16 @@ import com.jogamp.graph.font.FontSet;
import com.jogamp.graph.font.FontFactory;
public class JavaFontLoader implements FontSet {
-
- final static FontSet fontLoader = new JavaFontLoader();
+
+ // FIXME: Add cache size to limit memory usage
+ private static final IntObjectHashMap fontMap = new IntObjectHashMap();
+
+ private static final FontSet fontLoader = new JavaFontLoader();
public static FontSet get() {
return fontLoader;
}
-
+
final static String availableFontFileNames[] =
{
/* 00 */ "LucidaBrightRegular.ttf",
@@ -58,11 +64,12 @@ public class JavaFontLoader implements FontSet {
/* 06 */ "LucidaTypewriterRegular.ttf",
/* 07 */ "LucidaTypewriterBold.ttf",
};
-
+
final String javaFontPath;
-
+
private JavaFontLoader() {
final String javaHome = AccessController.doPrivileged(new PrivilegedAction<String>() {
+ @Override
public String run() {
return System.getProperty("java.home");
}
@@ -74,26 +81,28 @@ public class JavaFontLoader implements FontSet {
}
}
- // FIXME: Add cache size to limit memory usage
- static final IntObjectHashMap fontMap = new IntObjectHashMap();
-
- static boolean is(int bits, int bit) {
+ static boolean is(final int bits, final int bit) {
return 0 != ( bits & bit ) ;
}
-
+
+ @Override
public Font getDefault() throws IOException {
- return get(FAMILY_REGULAR, 0) ; // Sans Serif Regular
+ return get(FAMILY_REGULAR, 0) ; // Sans Serif Regular
}
-
- public Font get(int family, int style) throws IOException {
+
+ @Override
+ public Font get(final int family, final int style) throws IOException {
+ if(null == javaFontPath) {
+ throw new GLException("java font path undefined");
+ }
Font font = (Font)fontMap.get( ( family << 8 ) | style );
if (font != null) {
return font;
}
// 1st process Sans Serif (2 fonts)
- if( is(style, STYLE_SERIF) ) {
- if( is(style, STYLE_BOLD) ) {
+ if( is(style, STYLE_SERIF) ) {
+ if( is(style, STYLE_BOLD) ) {
font = abspath(availableFontFileNames[5], family, style);
} else {
font = abspath(availableFontFileNames[4], family, style);
@@ -103,53 +112,74 @@ public class JavaFontLoader implements FontSet {
}
return font;
}
-
+
// Serif Fonts ..
switch (family) {
case FAMILY_LIGHT:
case FAMILY_MEDIUM:
case FAMILY_CONDENSED:
case FAMILY_REGULAR:
- if( is(style, STYLE_BOLD) ) {
- if( is(style, STYLE_ITALIC) ) {
+ if( is(style, STYLE_BOLD) ) {
+ if( is(style, STYLE_ITALIC) ) {
font = abspath(availableFontFileNames[3], family, style);
} else {
font = abspath(availableFontFileNames[2], family, style);
}
- } else if( is(style, STYLE_ITALIC) ) {
+ } else if( is(style, STYLE_ITALIC) ) {
font = abspath(availableFontFileNames[1], family, style);
} else {
font = abspath(availableFontFileNames[0], family, style);
}
break;
-
+
case FAMILY_MONOSPACED:
- if( is(style, STYLE_BOLD) ) {
+ if( is(style, STYLE_BOLD) ) {
font = abspath(availableFontFileNames[7], family, style);
} else {
font = abspath(availableFontFileNames[6], family, style);
}
- break;
+ break;
}
return font;
}
-
- Font abspath(String fname, int family, int style) throws IOException {
- if(null == javaFontPath) {
- throw new GLException("java font path undefined");
- }
- final String err = "Problem loading font "+fname+", file "+javaFontPath+fname ;
-
+
+ Font abspath(final String fname, final int family, final int style) throws IOException {
try {
- final Font f = FontFactory.get( new File(javaFontPath+fname) );
+ final Font f = abspathImpl(javaFontPath+fname, family, style);
+ if(null != f) {
+ return f;
+ }
+ throw new IOException (String.format("Problem loading font %s, file %s%s", fname, javaFontPath, fname));
+ } catch (final IOException ioe) {
+ throw new IOException(String.format("Problem loading font %s, file %s%s", fname, javaFontPath, fname), ioe);
+ }
+ }
+ private Font abspathImpl(final String fname, final int family, final int style) throws IOException {
+ final Exception[] privErr = { null };
+ final int[] streamLen = { 0 };
+ final InputStream stream = AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
+ @Override
+ public InputStream run() {
+ try {
+ final File file = new File(fname);
+ streamLen[0] = (int) file.length();
+ return new BufferedInputStream(new FileInputStream(file), streamLen[0]);
+ } catch (final Exception e) {
+ privErr[0] = e;
+ return null;
+ }
+ } } );
+ if( null != privErr[0] ) {
+ throw new IOException(privErr[0]);
+ }
+ if(null != stream) {
+ final Font f= FontFactory.get ( stream, streamLen[0], true ) ;
if(null != f) {
fontMap.put( ( family << 8 ) | style, f );
return f;
}
- throw new IOException (err);
- } catch (IOException ioe) {
- throw new IOException(err, ioe);
}
- }
+ return null;
+ }
}
diff --git a/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java b/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java
index 0772cc47f..bbf022657 100644
--- a/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java
+++ b/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java
@@ -28,29 +28,42 @@
package jogamp.graph.font;
import java.io.IOException;
-import javax.media.opengl.GLException;
+import java.io.InputStream;
+import com.jogamp.common.net.Uri;
+import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IntObjectHashMap;
-import com.jogamp.common.util.IOUtil;
-
+import com.jogamp.common.util.JarUtil;
+import com.jogamp.common.util.cache.TempJarCache;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontSet;
import com.jogamp.graph.font.FontFactory;
-import java.net.URLConnection;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
public class UbuntuFontLoader implements FontSet {
-
- final static FontSet fontLoader = new UbuntuFontLoader();
- public static FontSet get() {
+ // FIXME: Add cache size to limit memory usage
+ private static final IntObjectHashMap fontMap = new IntObjectHashMap();
+
+ private static final Uri.Encoded jarSubDir = Uri.Encoded.cast("atomic/");
+ private static final Uri.Encoded jarName = Uri.Encoded.cast("jogl-fonts-p0.jar");
+
+ private static final String relFontPath = "fonts/ubuntu/" ;
+ private static final String absFontPath = "jogamp/graph/font/fonts/ubuntu/" ;
+
+ private static final FontSet fontLoader = new UbuntuFontLoader();
+
+ public static final FontSet get() {
return fontLoader;
}
-
+
final static String availableFontFileNames[] =
{
/* 00 */ "Ubuntu-R.ttf", // regular
/* 01 */ "Ubuntu-RI.ttf", // regular italic
- /* 02 */ "Ubuntu-B.ttf", // bold
+ /* 02 */ "Ubuntu-B.ttf", // bold
/* 03 */ "Ubuntu-BI.ttf", // bold italic
/* 04 */ "Ubuntu-L.ttf", // light
/* 05 */ "Ubuntu-LI.ttf", // light italic
@@ -58,24 +71,21 @@ public class UbuntuFontLoader implements FontSet {
/* 07 */ "Ubuntu-MI.ttf", // medium italic
};
-
- final static String relPath = "fonts/ubuntu/" ;
-
+
private UbuntuFontLoader() {
}
- // FIXME: Add cache size to limit memory usage
- static final IntObjectHashMap fontMap = new IntObjectHashMap();
-
- static boolean is(int bits, int bit) {
+ static boolean is(final int bits, final int bit) {
return 0 != ( bits & bit ) ;
}
-
+
+ @Override
public Font getDefault() throws IOException {
- return get(FAMILY_REGULAR, 0) ; // Sans Serif Regular
+ return get(FAMILY_REGULAR, 0) ; // Sans Serif Regular
}
-
- public Font get(int family, int style) throws IOException {
+
+ @Override
+ public Font get(final int family, final int style) throws IOException {
Font font = (Font)fontMap.get( ( family << 8 ) | style );
if (font != null) {
return font;
@@ -97,7 +107,7 @@ public class UbuntuFontLoader implements FontSet {
font = abspath(availableFontFileNames[0], family, style);
}
break;
-
+
case FAMILY_LIGHT:
if( is(style, STYLE_ITALIC) ) {
font = abspath(availableFontFileNames[5], family, style);
@@ -105,34 +115,83 @@ public class UbuntuFontLoader implements FontSet {
font = abspath(availableFontFileNames[4], family, style);
}
break;
-
+
case FAMILY_MEDIUM:
if( is(style, STYLE_ITALIC) ) {
font = abspath(availableFontFileNames[6], family, style);
} else {
font = abspath(availableFontFileNames[7], family, style);
}
- break;
+ break;
}
return font;
}
-
- Font abspath(String fname, int family, int style) throws IOException {
- final String err = "Problem loading font "+fname+", stream "+relPath+fname;
+
+ private static boolean attemptedJARLoading = false;
+ private static boolean useTempJARCache = false;
+
+ private synchronized Font abspath(final String fname, final int family, final int style) throws IOException {
+ if( !attemptedJARLoading ) {
+ attemptedJARLoading = true;
+ Platform.initSingleton();
+ if( TempJarCache.isInitialized() ) {
+ try {
+ final Uri uri = JarUtil.getRelativeOf(UbuntuFontLoader.class, jarSubDir, jarName);
+ final Exception e0 = AccessController.doPrivileged(new PrivilegedAction<Exception>() {
+ @Override
+ public Exception run() {
+ try {
+ TempJarCache.addResources(UbuntuFontLoader.class, uri);
+ useTempJARCache = true;
+ return null;
+ } catch (final Exception e) {
+ return e;
+ }
+ } } );
+ if( null != e0 ) {
+ throw e0;
+ }
+ } catch(final Exception e1) {
+ System.err.println("Caught "+e1.getMessage());
+ e1.printStackTrace();
+ }
+ }
+ }
+ final String path = useTempJARCache ? absFontPath : relFontPath;
try {
- URLConnection conn = IOUtil.getResource(UbuntuFontLoader.class, relPath+fname);
- if(null == conn) {
- throw new GLException(err);
+ final Font f = abspathImpl(path+fname, family, style);
+ if( null != f ) {
+ return f;
}
- final Font f= FontFactory.get ( conn ) ;
+ throw new IOException(String.format("Problem loading font %s, stream %s%s", fname, path, fname));
+ } catch(final Exception e) {
+ throw new IOException(String.format("Problem loading font %s, stream %s%s", fname, path, fname), e);
+ }
+ }
+ private Font abspathImpl(final String fname, final int family, final int style) throws IOException {
+ final Exception[] privErr = { null };
+ final InputStream stream = AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
+ @Override
+ public InputStream run() {
+ try {
+ final Uri uri = TempJarCache.getResourceUri(fname);
+ return null != uri ? uri.toURL().openConnection().getInputStream() : null;
+ } catch (final Exception e) {
+ privErr[0] = e;
+ return null;
+ }
+ } } );
+ if( null != privErr[0] ) {
+ throw new IOException(privErr[0]);
+ }
+ if(null != stream) {
+ final Font f= FontFactory.get ( stream, true ) ;
if(null != f) {
fontMap.put( ( family << 8 ) | style, f );
return f;
- }
- throw new IOException(err);
- } catch(IOException ioe) {
- throw new IOException(err, ioe);
+ }
}
- }
+ return null;
+ }
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
index 8e465de99..c48ef99ca 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
@@ -27,9 +27,6 @@
*/
package jogamp.graph.font.typecast;
-import java.util.ArrayList;
-
-import jogamp.graph.font.FontInt;
import jogamp.graph.font.typecast.ot.OTFont;
import jogamp.graph.font.typecast.ot.OTFontCollection;
import jogamp.graph.font.typecast.ot.table.CmapFormat;
@@ -38,53 +35,52 @@ import jogamp.graph.font.typecast.ot.table.CmapTable;
import jogamp.graph.font.typecast.ot.table.HdmxTable;
import jogamp.graph.font.typecast.ot.table.ID;
import jogamp.graph.geom.plane.AffineTransform;
-import jogamp.graph.geom.plane.Path2D;
import com.jogamp.common.util.IntObjectHashMap;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
-import com.jogamp.graph.font.Font.Glyph;
-import com.jogamp.graph.geom.AABBox;
+import com.jogamp.graph.geom.SVertex;
import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.opengl.math.geom.AABBox;
-class TypecastFont implements FontInt {
+class TypecastFont implements Font {
static final boolean DEBUG = false;
-
- final OTFontCollection fontset;
- final OTFont font;
- TypecastHMetrics metrics;
- final CmapFormat cmapFormat;
- int cmapentries;
-
- // FIXME: Add cache size to limit memory usage ??
- IntObjectHashMap char2Glyph;
+ private static final Vertex.Factory<SVertex> vertexFactory = SVertex.factory();
+
+ // private final OTFontCollection fontset;
+ /* pp */ final OTFont font;
+ private final CmapFormat cmapFormat;
+ private final int cmapentries;
+ private final IntObjectHashMap char2Glyph;
+ private final TypecastHMetrics metrics;
+ private final float[] tmpV3 = new float[3];
+ // FIXME: Add cache size to limit memory usage ??
- public TypecastFont(OTFontCollection fontset) {
- this.fontset = fontset;
+ public TypecastFont(final OTFontCollection fontset) {
+ // this.fontset = fontset;
this.font = fontset.getFont(0);
-
+
// FIXME: Generic attempt to find the best CmapTable,
// which is assumed to be the one with the most entries (stupid 'eh?)
- CmapTable cmapTable = font.getCmapTable();
- CmapFormat[] _cmapFormatP = { null, null, null, null };
+ final CmapTable cmapTable = font.getCmapTable();
+ final CmapFormat[] _cmapFormatP = { null, null, null, null };
int platform = -1;
int platformLength = -1;
int encoding = -1;
for(int i=0; i<cmapTable.getNumTables(); i++) {
- CmapIndexEntry cmapIdxEntry = cmapTable.getCmapIndexEntry(i);
- int pidx = cmapIdxEntry.getPlatformId();
- CmapFormat cf = cmapIdxEntry.getFormat();
+ final CmapIndexEntry cmapIdxEntry = cmapTable.getCmapIndexEntry(i);
+ final int pidx = cmapIdxEntry.getPlatformId();
+ final CmapFormat cf = cmapIdxEntry.getFormat();
if(DEBUG) {
- System.err.println("CmapFormat["+i+"]: platform " + pidx +
+ System.err.println("CmapFormat["+i+"]: platform " + pidx +
", encoding "+cmapIdxEntry.getEncodingId() + ": "+cf);
}
- if( _cmapFormatP[pidx] == null ||
+ if( _cmapFormatP[pidx] == null ||
_cmapFormatP[pidx].getLength() < cf.getLength() ) {
_cmapFormatP[pidx] = cf;
if( cf.getLength() > platformLength ) {
- platformLength = cf.getLength() ;
+ platformLength = cf.getLength() ;
platform = pidx;
encoding = cmapIdxEntry.getEncodingId();
}
@@ -93,10 +89,10 @@ class TypecastFont implements FontInt {
if(0 <= platform) {
cmapFormat = _cmapFormatP[platform];
if(DEBUG) {
- System.err.println("Selected CmapFormat: platform " + platform +
+ System.err.println("Selected CmapFormat: platform " + platform +
", encoding "+encoding + ": "+cmapFormat);
}
- } else {
+ } else {
CmapFormat _cmapFormat = null;
/*if(null == _cmapFormat) {
platform = ID.platformMacintosh;
@@ -124,58 +120,66 @@ class TypecastFont implements FontInt {
}
}
- cmapentries = 0;
- for (int i = 0; i < cmapFormat.getRangeCount(); ++i) {
- CmapFormat.Range range = cmapFormat.getRange(i);
- cmapentries += range.getEndCode() - range.getStartCode() + 1; // end included
- }
+ {
+ int _cmapentries = 0;
+ for (int i = 0; i < cmapFormat.getRangeCount(); ++i) {
+ final CmapFormat.Range range = cmapFormat.getRange(i);
+ _cmapentries += range.getEndCode() - range.getStartCode() + 1; // end included
+ }
+ cmapentries = _cmapentries;
+ }
if(DEBUG) {
System.err.println("font direction hint: "+font.getHeadTable().getFontDirectionHint());
System.err.println("num glyphs: "+font.getNumGlyphs());
System.err.println("num cmap entries: "+cmapentries);
System.err.println("num cmap ranges: "+cmapFormat.getRangeCount());
-
+
for (int i = 0; i < cmapFormat.getRangeCount(); ++i) {
- CmapFormat.Range range = cmapFormat.getRange(i);
+ final CmapFormat.Range range = cmapFormat.getRange(i);
for (int j = range.getStartCode(); j <= range.getEndCode(); ++j) {
final int code = cmapFormat.mapCharCode(j);
if(code < 15) {
- System.err.println(" char: " + (int)j + " ( " + (char)j +" ) -> " + code);
+ System.err.println(" char: " + j + " ( " + (char)j +" ) -> " + code);
}
}
}
}
char2Glyph = new IntObjectHashMap(cmapentries + cmapentries/4);
+ metrics = new TypecastHMetrics(this);
}
-
- public StringBuilder getName(StringBuilder sb, int nameIndex) {
+
+ @Override
+ public StringBuilder getName(final StringBuilder sb, final int nameIndex) {
return font.getName(nameIndex, sb);
}
- public String getName(int nameIndex) {
+ @Override
+ public String getName(final int nameIndex) {
return getName(null, nameIndex).toString();
}
- public StringBuilder getAllNames(StringBuilder sb, String separator) {
+ @Override
+ public StringBuilder getAllNames(final StringBuilder sb, final String separator) {
return font.getAllNames(sb, separator);
}
+ @Override
public StringBuilder getFullFamilyName(StringBuilder sb) {
sb = getName(sb, Font.NAME_FAMILY).append("-");
getName(sb, Font.NAME_SUBFAMILY);
return sb;
- }
+ }
- public float getAdvanceWidth(int i, float pixelSize) {
- return font.getHmtxTable().getAdvanceWidth(i) * metrics.getScale(pixelSize);
+ @Override
+ public float getAdvanceWidth(final int glyphID, final float pixelSize) {
+ return font.getHmtxTable().getAdvanceWidth(glyphID) * metrics.getScale(pixelSize);
}
-
- public Metrics getMetrics() {
- if (metrics == null) {
- metrics = new TypecastHMetrics(this);
- }
+
+ @Override
+ public final Metrics getMetrics() {
return metrics;
}
- public Glyph getGlyph(char symbol) {
- TypecastGlyph result = (TypecastGlyph) char2Glyph.get(symbol);
+ @Override
+ public Glyph getGlyph(final char symbol) {
+ TypecastGlyph result = (TypecastGlyph) char2Glyph.get(symbol);
if (null == result) {
// final short code = (short) char2Code.get(symbol);
short code = (short) cmapFormat.mapCharCode(symbol);
@@ -187,7 +191,7 @@ class TypecastFont implements FontInt {
default: code = Glyph.ID_UNKNOWN;
}
}
-
+
jogamp.graph.font.typecast.ot.OTGlyph glyph = font.getGlyph(code);
if(null == glyph) {
glyph = font.getGlyph(Glyph.ID_UNKNOWN);
@@ -195,106 +199,162 @@ class TypecastFont implements FontInt {
if(null == glyph) {
throw new RuntimeException("Could not retrieve glyph for symbol: <"+symbol+"> "+(int)symbol+" -> glyph id "+code);
}
- Path2D path = TypecastRenderer.buildPath(glyph);
- result = new TypecastGlyph(this, symbol, code, glyph.getBBox(), glyph.getAdvanceWidth(), path);
+ final OutlineShape shape = TypecastRenderer.buildShape(symbol, glyph, vertexFactory);
+ result = new TypecastGlyph(this, symbol, code, glyph.getBBox(), glyph.getAdvanceWidth(), shape);
if(DEBUG) {
- System.err.println("New glyph: " + (int)symbol + " ( " + (char)symbol +" ) -> " + code + ", contours " + glyph.getPointCount() + ": " + path);
+ System.err.println("New glyph: " + (int)symbol + " ( " + symbol +" ) -> " + code + ", contours " + glyph.getPointCount() + ": " + shape);
}
- final HdmxTable hdmx = font.getHdmxTable();
+ glyph.clearPointData();
+
+ final HdmxTable hdmx = font.getHdmxTable();
if (null!= result && null != hdmx) {
/*if(DEBUG) {
System.err.println("hdmx "+hdmx);
}*/
for (int i=0; i<hdmx.getNumberOfRecords(); i++)
{
- final HdmxTable.DeviceRecord dr = hdmx.getRecord(i);
+ final HdmxTable.DeviceRecord dr = hdmx.getRecord(i);
result.addAdvance(dr.getWidth(code), dr.getPixelSize());
/* if(DEBUG) {
System.err.println("hdmx advance : pixelsize = "+dr.getWidth(code)+" : "+ dr.getPixelSize());
} */
}
- }
+ }
char2Glyph.put(symbol, result);
}
return result;
}
-
- public ArrayList<OutlineShape> getOutlineShapes(CharSequence string, float pixelSize, Factory<? extends Vertex> vertexFactory) {
- AffineTransform transform = new AffineTransform(vertexFactory);
- return TypecastRenderer.getOutlineShapes(this, string, pixelSize, transform, vertexFactory);
+
+ @Override
+ public final float getPixelSize(final float fontSize /* points per inch */, final float resolution) {
+ return fontSize * resolution / ( 72f /* points per inch */ );
}
- public float getStringWidth(CharSequence string, float pixelSize) {
+ @Override
+ public float getLineHeight(final float pixelSize) {
+ final Metrics metrics = getMetrics();
+ final float lineGap = metrics.getLineGap(pixelSize) ; // negative value!
+ final float ascent = metrics.getAscent(pixelSize) ; // negative value!
+ final float descent = metrics.getDescent(pixelSize) ; // positive value!
+ final float advanceY = lineGap - descent + ascent; // negative value!
+ return -advanceY;
+ }
+
+ @Override
+ public float getMetricWidth(final CharSequence string, final float pixelSize) {
float width = 0;
final int len = string.length();
- for (int i=0; i< len; i++)
- {
- char character = string.charAt(i);
+ for (int i=0; i< len; i++) {
+ final char character = string.charAt(i);
if (character == '\n') {
width = 0;
} else {
- Glyph glyph = getGlyph(character);
+ final Glyph glyph = getGlyph(character);
width += glyph.getAdvance(pixelSize, false);
}
}
-
- return (int)(width + 0.5f);
+ return (int)(width + 0.5f);
}
- public float getStringHeight(CharSequence string, float pixelSize) {
+ @Override
+ public float getMetricHeight(final CharSequence string, final float pixelSize, final AABBox tmp) {
int height = 0;
- for (int i=0; i<string.length(); i++)
- {
- char character = string.charAt(i);
- if (character != ' ')
- {
- Glyph glyph = getGlyph(character);
- AABBox bbox = glyph.getBBox(pixelSize);
+ for (int i=0; i<string.length(); i++) {
+ final char character = string.charAt(i);
+ if (character != ' ') {
+ final Glyph glyph = getGlyph(character);
+ final AABBox bbox = glyph.getBBox(tmp, pixelSize, tmpV3);
height = (int)Math.ceil(Math.max(bbox.getHeight(), height));
}
}
- return height;
+ return height;
}
- public AABBox getStringBounds(CharSequence string, float pixelSize) {
+ @Override
+ public AABBox getMetricBounds(final CharSequence string, final float pixelSize) {
if (string == null) {
return new AABBox();
}
- final Metrics metrics = getMetrics();
- final float lineGap = metrics.getLineGap(pixelSize);
- final float ascent = metrics.getAscent(pixelSize);
- final float descent = metrics.getDescent(pixelSize);
- final float advanceY = lineGap - descent + ascent;
+ final int charCount = string.length();
+ final float lineHeight = getLineHeight(pixelSize);
float totalHeight = 0;
float totalWidth = 0;
float curLineWidth = 0;
- for (int i=0; i<string.length(); i++) {
- char character = string.charAt(i);
+ for (int i=0; i<charCount; i++) {
+ final char character = string.charAt(i);
if (character == '\n') {
totalWidth = Math.max(curLineWidth, totalWidth);
curLineWidth = 0;
- totalHeight -= advanceY;
+ totalHeight += lineHeight;
continue;
}
- Glyph glyph = getGlyph(character);
+ final Glyph glyph = getGlyph(character);
curLineWidth += glyph.getAdvance(pixelSize, true);
}
if (curLineWidth > 0) {
- totalHeight -= advanceY;
+ totalHeight += lineHeight;
totalWidth = Math.max(curLineWidth, totalWidth);
}
- return new AABBox(0, 0, 0, totalWidth, totalHeight,0);
+ return new AABBox(0, 0, 0, totalWidth, totalHeight,0);
+ }
+ @Override
+ public AABBox getPointsBounds(final AffineTransform transform, final CharSequence string, final float pixelSize,
+ final AffineTransform temp1, final AffineTransform temp2) {
+ if (string == null) {
+ return new AABBox();
+ }
+ final int charCount = string.length();
+ final float lineHeight = getLineHeight(pixelSize);
+ final float scale = getMetrics().getScale(pixelSize);
+ final AABBox tbox = new AABBox();
+ final AABBox res = new AABBox();
+
+ float y = 0;
+ float advanceTotal = 0;
+
+ for(int i=0; i< charCount; i++) {
+ final char character = string.charAt(i);
+ if( '\n' == character ) {
+ y -= lineHeight;
+ advanceTotal = 0;
+ } else if (character == ' ') {
+ advanceTotal += getAdvanceWidth(Glyph.ID_SPACE, pixelSize);
+ } else {
+ // reset transform
+ if( null != transform ) {
+ temp1.setTransform(transform);
+ } else {
+ temp1.setToIdentity();
+ }
+ temp1.translate(advanceTotal, y, temp2);
+ temp1.scale(scale, scale, temp2);
+ tbox.reset();
+
+ final Font.Glyph glyph = getGlyph(character);
+ res.resize(temp1.transform(glyph.getBBox(), tbox));
+
+ final OutlineShape glyphShape = glyph.getShape();
+ if( null == glyphShape ) {
+ continue;
+ }
+ advanceTotal += glyph.getAdvance(pixelSize, true);
+ }
+ }
+ return res;
}
+ @Override
final public int getNumGlyphs() {
return font.getNumGlyphs();
}
-
- public boolean isPrintableChar( char c ) {
+
+ @Override
+ public boolean isPrintableChar( final char c ) {
return FontFactory.isPrintableChar(c);
}
-
+
+ @Override
public String toString() {
return getFullFamilyName(null).toString();
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
index 0f762e79c..ef7f38e64 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
@@ -29,62 +29,22 @@ package jogamp.graph.font.typecast;
import java.io.File;
import java.io.IOException;
-import java.net.URLConnection;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-import javax.media.opengl.GLException;
+import java.io.InputStream;
import jogamp.graph.font.FontConstructor;
import jogamp.graph.font.typecast.ot.OTFontCollection;
-import com.jogamp.common.util.IOUtil;
import com.jogamp.graph.font.Font;
public class TypecastFontConstructor implements FontConstructor {
+ @Override
public Font create(final File ffile) throws IOException {
- Object o = AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- OTFontCollection fontset;
- try {
- fontset = OTFontCollection.create(ffile);
- return new TypecastFont(fontset);
- } catch (IOException e) {
- return e;
- }
- }
- });
- if(o instanceof Font) {
- return (Font)o;
- }
- if(o instanceof IOException) {
- throw (IOException)o;
- }
- throw new InternalError("Unexpected Object: "+o);
+ return new TypecastFont( OTFontCollection.create(ffile) );
}
-
- public Font create(final URLConnection fconn) throws IOException {
- return AccessController.doPrivileged(new PrivilegedAction<Font>() {
- public Font run() {
- File tf = null;
- int len=0;
- Font f = null;
- try {
- tf = IOUtil.createTempFile( "jogl.font", ".ttf", false, null);
- len = IOUtil.copyURLConn2File(fconn, tf);
- if(len==0) {
- tf.delete();
- throw new GLException("Font of stream "+fconn.getURL()+" was zero bytes");
- }
- f = create(tf);
- tf.delete();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return f;
- }
- });
+
+ @Override
+ public Font create(final InputStream istream, final int streamLen) throws IOException {
+ return new TypecastFont( OTFontCollection.create(istream, streamLen) );
}
-
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
index a1f1a3292..97570d605 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
@@ -27,206 +27,185 @@
*/
package jogamp.graph.font.typecast;
-import java.util.HashMap;
-
-import jogamp.graph.font.FontInt;
-import jogamp.graph.geom.plane.AffineTransform;
-import jogamp.graph.geom.plane.Path2D;
-
+import com.jogamp.common.util.IntIntHashMap;
+import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.font.Font;
-import com.jogamp.graph.geom.AABBox;
+import com.jogamp.opengl.math.geom.AABBox;
-public class TypecastGlyph implements FontInt.GlyphInt {
- public class Advance
+public final class TypecastGlyph implements Font.Glyph {
+ public static final class Advance
{
- final Font font;
- final float advance;
- HashMap<Float, Float> size2advance = new HashMap<Float, Float>();
-
- public Advance(Font font, float advance)
+ private final Font font;
+ private final float advance;
+ private final IntIntHashMap size2advanceI = new IntIntHashMap();
+
+ public Advance(final Font font, final float advance)
{
this.font = font;
this.advance = advance;
+ size2advanceI.setKeyNotFoundValue(0);
}
-
- public void reset() {
- size2advance.clear();
+
+ public final void reset() {
+ size2advanceI.clear();
}
-
- public float getScale(float pixelSize)
+
+ public final Font getFont() { return font; }
+
+ public final float getScale(final float pixelSize)
{
return this.font.getMetrics().getScale(pixelSize);
}
-
- public void add(float advance, float size)
+
+ public final void add(final float advance, final float size)
{
- size2advance.put(size, advance);
+ size2advanceI.put(Float.floatToIntBits(size), Float.floatToIntBits(advance));
}
-
- public float get(float size, boolean useFrationalMetrics)
+
+ public final float get(final float pixelSize, final boolean useFrationalMetrics)
{
- Float fo = size2advance.get(size);
- if(null == fo) {
- float value = (this.advance * getScale(size));
- if (useFrationalMetrics == false) {
- //value = (float)Math.ceil(value);
- // value = (int)value;
- value = (int) ( value + 0.5f ) ; // TODO: check
- }
- size2advance.put(size, value);
- return value;
+ final int sI = Float.floatToIntBits(pixelSize);
+ final int aI = size2advanceI.get(sI);
+ if( 0 != aI ) {
+ return Float.intBitsToFloat(aI);
}
- return fo.floatValue();
+ final float a;
+ if ( useFrationalMetrics ) {
+ a = this.advance * getScale(pixelSize);
+ } else {
+ // a = Math.ceil(this.advance * getScale(pixelSize));
+ a = Math.round(this.advance * getScale(pixelSize)); // TODO: check whether ceil should be used instead?
+ }
+ size2advanceI.put(sI, Float.floatToIntBits(a));
+ return a;
}
-
- public String toString()
+
+ @Override
+ public final String toString()
{
return "\nAdvance:"+
"\n advance: "+this.advance+
- "\n advances: \n"+size2advance;
+ "\n advances: \n"+size2advanceI;
}
}
-
- public class Metrics
+
+ public static final class Metrics
{
- AABBox bbox;
- Advance advance;
-
- public Metrics(Font font, AABBox bbox, float advance)
+ private final AABBox bbox;
+ private final Advance advance;
+
+ public Metrics(final Font font, final AABBox bbox, final float advance)
{
this.bbox = bbox;
this.advance = new Advance(font, advance);
}
-
- public void reset() {
+
+ public final void reset() {
advance.reset();
}
-
- public float getScale(float pixelSize)
+
+ public final Font getFont() { return advance.getFont(); }
+
+ public final float getScale(final float pixelSize)
{
return this.advance.getScale(pixelSize);
}
-
- public AABBox getBBox()
+
+ public final AABBox getBBox()
{
return this.bbox;
}
-
- public void addAdvance(float advance, float size)
+
+ public final void addAdvance(final float advance, final float size)
{
this.advance.add(advance, size);
}
-
- public float getAdvance(float size, boolean useFrationalMetrics)
+
+ public final float getAdvance(final float pixelSize, final boolean useFrationalMetrics)
{
- return this.advance.get(size, useFrationalMetrics);
+ return this.advance.get(pixelSize, useFrationalMetrics);
}
-
- public String toString()
+
+ @Override
+ public final String toString()
{
return "\nMetrics:"+
"\n bbox: "+this.bbox+
this.advance;
}
- }
+ }
public static final short INVALID_ID = (short)((1 << 16) - 1);
public static final short MAX_ID = (short)((1 << 16) - 2);
-
- private final Font font;
-
- char symbol;
- short id;
- int advance;
- Metrics metrics;
-
- protected Path2D path; // in EM units
- protected Path2D pathSized;
- protected float numberSized;
-
- protected TypecastGlyph(Font font, char symbol) {
- this.font = font;
- this.symbol = symbol;
- }
-
- protected TypecastGlyph(Font font,
- char symbol, short id, AABBox bbox, int advance, Path2D path) {
- this.font = font;
+
+ private final char symbol;
+ private final OutlineShape shape; // in EM units
+ private final short id;
+ private final Metrics metrics;
+
+ protected TypecastGlyph(final Font font, final char symbol, final short id, final AABBox bbox, final int advance, final OutlineShape shape) {
this.symbol = symbol;
- this.advance = advance;
-
- init(id, bbox, advance);
-
- this.path = path;
- this.pathSized = null;
- this.numberSized = 0.0f;
- }
-
- void init(short id, AABBox bbox, int advance) {
+ this.shape = shape;
this.id = id;
- this.advance = advance;
- this.metrics = new Metrics(this.font, bbox, this.advance);
+ this.metrics = new Metrics(font, bbox, advance);
}
-
- public void reset(Path2D path) {
- this.path = path;
- this.metrics.reset();
- }
-
- public Font getFont() {
- return this.font;
+
+ @Override
+ public final Font getFont() {
+ return this.metrics.getFont();
}
-
- public char getSymbol() {
+
+ @Override
+ public final char getSymbol() {
return this.symbol;
}
-
- AABBox getBBoxUnsized() {
+
+ final AABBox getBBoxUnsized() {
return this.metrics.getBBox();
}
-
- public AABBox getBBox() {
+
+ @Override
+ public final AABBox getBBox() {
return this.metrics.getBBox();
}
-
- public Metrics getMetrics() {
+
+ public final Metrics getMetrics() {
return this.metrics;
}
-
- public short getID() {
+
+ @Override
+ public final short getID() {
return this.id;
}
-
- public float getScale(float pixelSize) {
+
+ @Override
+ public final float getScale(final float pixelSize) {
return this.metrics.getScale(pixelSize);
}
-
- public AABBox getBBox(float pixelSize) {
- final float size = getScale(pixelSize);
- AABBox newBox = getBBox().clone();
- newBox.scale(size);
- return newBox;
+
+ @Override
+ public final AABBox getBBox(final AABBox dest, final float pixelSize, final float[] tmpV3) {
+ return dest.copy(getBBox()).scale(getScale(pixelSize), tmpV3);
}
-
- protected void addAdvance(float advance, float size) {
+
+ protected final void addAdvance(final float advance, final float size) {
this.metrics.addAdvance(advance, size);
}
-
- public float getAdvance(float pixelSize, boolean useFrationalMetrics) {
+
+ @Override
+ public final float getAdvance(final float pixelSize, final boolean useFrationalMetrics) {
return this.metrics.getAdvance(pixelSize, useFrationalMetrics);
}
-
- public Path2D getPath() {
- return this.path;
+
+ @Override
+ public final OutlineShape getShape() {
+ return this.shape;
+ }
+
+ @Override
+ public final int hashCode() {
+ // 31 * x == (x << 5) - x
+ final int hash = 31 + getFont().getName(Font.NAME_UNIQUNAME).hashCode();
+ return ((hash << 5) - hash) + id;
}
-
- public Path2D getPath(float pixelSize) {
- final float size = getScale(pixelSize);
-
- if (this.numberSized != size) {
- this.numberSized = size;
- this.pathSized = AffineTransform.getScaleInstance(null, size, size).createTransformedShape(getPath());
- }
- return this.pathSized;
- }
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
index 0dd7a6178..d5e30a500 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
@@ -31,11 +31,11 @@ import jogamp.graph.font.typecast.ot.table.HeadTable;
import jogamp.graph.font.typecast.ot.table.HheaTable;
import com.jogamp.graph.font.Font.Metrics;
-import com.jogamp.graph.geom.AABBox;
+import com.jogamp.opengl.math.geom.AABBox;
class TypecastHMetrics implements Metrics {
private final TypecastFont fontImpl;
-
+
// HeadTable
private final HeadTable headTable;
private final float unitsPerEM_Inv;
@@ -44,41 +44,45 @@ class TypecastHMetrics implements Metrics {
private final HheaTable hheaTable;
// VheaTable (for horizontal fonts)
// private final VheaTable vheaTable;
-
- public TypecastHMetrics(TypecastFont fontImpl) {
+
+ public TypecastHMetrics(final TypecastFont fontImpl) {
this.fontImpl = fontImpl;
headTable = this.fontImpl.font.getHeadTable();
- hheaTable = this.fontImpl.font.getHheaTable();
+ hheaTable = this.fontImpl.font.getHheaTable();
// vheaTable = this.fontImpl.font.getVheaTable();
- unitsPerEM_Inv = 1.0f / ( (float) headTable.getUnitsPerEm() );
-
- int maxWidth = headTable.getXMax() - headTable.getXMin();
- int maxHeight = headTable.getYMax() - headTable.getYMin();
- float lowx= headTable.getXMin();
- float lowy = -(headTable.getYMin()+maxHeight);
- float highx = lowx + maxWidth;
- float highy = lowy + maxHeight;
+ unitsPerEM_Inv = 1.0f / ( headTable.getUnitsPerEm() );
+
+ final int maxWidth = headTable.getXMax() - headTable.getXMin();
+ final int maxHeight = headTable.getYMax() - headTable.getYMin();
+ final float lowx= headTable.getXMin();
+ final float lowy = -(headTable.getYMin()+maxHeight);
+ final float highx = lowx + maxWidth;
+ final float highy = lowy + maxHeight;
bbox = new AABBox(lowx, lowy, 0, highx, highy, 0); // invert
}
-
- public final float getAscent(float pixelSize) {
+
+ @Override
+ public final float getAscent(final float pixelSize) {
return getScale(pixelSize) * -hheaTable.getAscender(); // invert
}
- public final float getDescent(float pixelSize) {
+ @Override
+ public final float getDescent(final float pixelSize) {
return getScale(pixelSize) * -hheaTable.getDescender(); // invert
}
- public final float getLineGap(float pixelSize) {
+ @Override
+ public final float getLineGap(final float pixelSize) {
return getScale(pixelSize) * -hheaTable.getLineGap(); // invert
}
- public final float getMaxExtend(float pixelSize) {
+ @Override
+ public final float getMaxExtend(final float pixelSize) {
return getScale(pixelSize) * hheaTable.getXMaxExtent();
}
- public final float getScale(float pixelSize) {
+ @Override
+ public final float getScale(final float pixelSize) {
return pixelSize * unitsPerEM_Inv;
}
- public final AABBox getBBox(float pixelSize) {
- AABBox res = new AABBox(bbox.getLow(), bbox.getHigh());
- res.scale(getScale(pixelSize));
- return res;
+ @Override
+ public final AABBox getBBox(final AABBox dest, final float pixelSize, final float[] tmpV3) {
+ return dest.setSize(bbox.getLow(), bbox.getHigh()).scale(getScale(pixelSize), tmpV3);
}
} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
index f155345aa..f78656b52 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
@@ -27,196 +27,197 @@
*/
package jogamp.graph.font.typecast;
-import java.util.ArrayList;
-
-import jogamp.graph.font.FontInt.GlyphInt;
import jogamp.graph.font.typecast.ot.OTGlyph;
import jogamp.graph.font.typecast.ot.Point;
-import jogamp.graph.geom.plane.AffineTransform;
-import jogamp.graph.geom.plane.Path2D;
-import jogamp.graph.geom.plane.PathIterator;
+import jogamp.opengl.Debug;
import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.font.Font;
-import com.jogamp.graph.font.Font.Glyph;
import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.geom.Vertex.Factory;
/**
- * Factory to build a {@link com.jogamp.graph.geom.Path2D Path2D} from
- * {@link jogamp.graph.font.typecast.ot.OTGlyph Glyph}s.
+ * Factory to build an {@link OutlineShape} from
+ * {@link jogamp.graph.font.typecast.ot.OTGlyph Glyph}s.
+ *
+ * http://www.freetype.org/freetype2/docs/glyphs/glyphs-3.html
+ * http://walon.org/pub/ttf/ttf_glyphs.htm
*/
public class TypecastRenderer {
+ private static final boolean DEBUG = Debug.debug("graph.font.Renderer");
- private static void getPaths(TypecastFont font,
- CharSequence string, float pixelSize, AffineTransform transform, Path2D[] p)
- {
- if (string == null) {
- return;
- }
- Font.Metrics metrics = font.getMetrics();
- float advanceTotal = 0;
- float lineGap = metrics.getLineGap(pixelSize) ;
- float ascent = metrics.getAscent(pixelSize) ;
- float descent = metrics.getDescent(pixelSize) ;
- if (transform == null) {
- transform = new AffineTransform();
- }
- AffineTransform t = new AffineTransform();
-
- float advanceY = lineGap - descent + ascent;
- float y = 0;
- for (int i=0; i<string.length(); i++)
- {
- p[i] = new Path2D();
- p[i].reset();
- t.setTransform(transform);
- char character = string.charAt(i);
- if (character == '\n') {
- y += advanceY;
- advanceTotal = 0;
- continue;
- } else if (character == ' ') {
- advanceTotal += font.getAdvanceWidth(Glyph.ID_SPACE, pixelSize);
- continue;
- }
- Glyph glyph = font.getGlyph(character);
- Path2D gp = ((GlyphInt)glyph).getPath();
- float scale = metrics.getScale(pixelSize);
- t.translate(advanceTotal, y);
- t.scale(scale, scale);
- p[i].append(gp.iterator(t), false);
- advanceTotal += glyph.getAdvance(pixelSize, true);
- }
+ private static void addShapeMoveTo(final OutlineShape shape, final Factory<? extends Vertex> vertexFactory, final Point p1) {
+ if( DEBUG ) { System.err.println("Shape.MoveTo: "+p1); }
+ shape.closeLastOutline(false);
+ shape.addEmptyOutline();
+ shape.addVertex(0, vertexFactory.create(p1.x, p1.y, 0, p1.onCurve));
}
-
- public static ArrayList<OutlineShape> getOutlineShapes(TypecastFont font, CharSequence string, float pixelSize, AffineTransform transform, Factory<? extends Vertex> vertexFactory) {
- Path2D[] paths = new Path2D[string.length()];
- getPaths(font, string, pixelSize, transform, paths);
-
- ArrayList<OutlineShape> shapes = new ArrayList<OutlineShape>();
- final int numGlyps = paths.length;
- for (int index=0;index<numGlyps;index++) {
- if(paths[index] == null){
- continue;
- }
- OutlineShape shape = new OutlineShape(vertexFactory);
- shapes.add(shape);
- PathIterator iterator = paths[index].iterator(transform);
- if(null != iterator){
- while(!iterator.isDone()){
- float[] coords = new float[6];
- int segmentType = iterator.currentSegment(coords);
- addPathVertexToOutline(shape, vertexFactory, coords, segmentType);
- iterator.next();
- }
- }
- }
- return shapes;
+ private static void addShapeLineTo(final OutlineShape shape, final Factory<? extends Vertex> vertexFactory, final Point p1) {
+ if( DEBUG ) { System.err.println("Shape.LineTo: "+p1); }
+ shape.addVertex(0, vertexFactory.create(p1.x, p1.y, 0, p1.onCurve));
}
- private static void addPathVertexToOutline(OutlineShape shape, Factory<? extends Vertex> vertexFactory, float[] coords, int segmentType){
- switch(segmentType) {
- case PathIterator.SEG_MOVETO:
- shape.closeLastOutline();
- shape.addEmptyOutline();
- shape.addVertex(0, vertexFactory.create(coords, 0, 2, true));
- break;
- case PathIterator.SEG_LINETO:
- shape.addVertex(0, vertexFactory.create(coords, 0, 2, true));
- break;
- case PathIterator.SEG_QUADTO:
- shape.addVertex(0, vertexFactory.create(coords, 0, 2, false));
- shape.addVertex(0, vertexFactory.create(coords, 2, 2, true));
- break;
- case PathIterator.SEG_CUBICTO:
- shape.addVertex(0, vertexFactory.create(coords, 0, 2, false));
- shape.addVertex(0, vertexFactory.create(coords, 2, 2, false));
- shape.addVertex(0, vertexFactory.create(coords, 4, 2, true));
- break;
- case PathIterator.SEG_CLOSE:
- shape.closeLastOutline();
- break;
- default:
- throw new IllegalArgumentException("Unhandled Segment Type: "+segmentType);
- }
+ private static void addShapeQuadTo(final OutlineShape shape, final Factory<? extends Vertex> vertexFactory, final Point p1, final Point p2) {
+ if( DEBUG ) { System.err.println("Shape.QuadTo: "+p1+", "+p2); }
+ shape.addVertex(0, vertexFactory.create(p1.x, p1.y, 0, p1.onCurve));
+ shape.addVertex(0, vertexFactory.create(p2.x, p2.y, 0, p2.onCurve));
+ }
+ private static void addShapeQuadTo(final OutlineShape shape, final Factory<? extends Vertex> vertexFactory, final Point p1,
+ final float p2x, final float p2y, final boolean p2OnCurve) {
+ if( DEBUG ) { System.err.println("Shape.QuadTo: "+p1+", p2 "+p2x+", "+p2y+", onCurve "+p2OnCurve); }
+ shape.addVertex(0, vertexFactory.create(p1.x, p1.y, 0, p1.onCurve));
+ shape.addVertex(0, vertexFactory.create(p2x, p2y, 0, p2OnCurve));
}
-
/**
- * Build a {@link com.jogamp.graph.geom.Path2D Path2D} from a
- * {@link jogamp.graph.font.typecast.ot.OTGlyph Glyph}. This glyph path can then
- * be transformed and rendered.
- */
- public static Path2D buildPath(OTGlyph glyph) {
+ private static void addShapeCubicTo(final OutlineShape shape, Factory<? extends Vertex> vertexFactory, Point p1, Point p2, Point p3) {
+ shape.addVertex(0, vertexFactory.create(p1.x, p1.y, 0, p1.onCurve));
+ shape.addVertex(0, vertexFactory.create(p2.x, p2.y, 0, p2.onCurve));
+ shape.addVertex(0, vertexFactory.create(p3.x, p3.y, 0, p3.onCurve));
+ } */
+
+ public static OutlineShape buildShape(final char symbol, final OTGlyph glyph, final Factory<? extends Vertex> vertexFactory) {
+ //
+ // See Typecast: GlyphPathFactory.addContourToPath(..)
+ //
if (glyph == null) {
return null;
}
- Path2D glyphPath = new Path2D();
+ final OutlineShape shape = new OutlineShape(vertexFactory);
+ buildShapeImpl(shape, symbol, glyph, vertexFactory);
+ shape.setIsQuadraticNurbs();
+ return shape;
+ }
+ /**
+ private static void buildShapeImpl02(final OutlineShape shape, char symbol, OTGlyph glyph, Factory<? extends Vertex> vertexFactory) {
// Iterate through all of the points in the glyph. Each time we find a
// contour end point, add the point range to the path.
- int firstIndex = 0;
+ int startIndex = 0;
int count = 0;
for (int i = 0; i < glyph.getPointCount(); i++) {
count++;
- if (glyph.getPoint(i).endOfContour) {
- addContourToPath(glyphPath, glyph, firstIndex, count);
- firstIndex = i + 1;
+ if ( glyph.getPoint(i).endOfContour ) {
+ for(int j=0; j<count; j++) {
+ final Point p = glyph.getPoint(startIndex + j);
+ shape.addVertex(0, vertexFactory.create(p.x, p.y, 0, p.onCurve));
+ }
+ shape.closeLastOutline(false);
+ startIndex = i + 1;
count = 0;
}
}
- return glyphPath;
- }
+ } */
- private static void addContourToPath(Path2D gp, OTGlyph glyph, int startIndex, int count) {
- int offset = 0;
- while (offset < count) {
- Point point = glyph.getPoint(startIndex + offset%count);
- Point point_plus1 = glyph.getPoint(startIndex + (offset+1)%count);
- Point point_plus2 = glyph.getPoint(startIndex + (offset+2)%count);
- if(offset == 0)
- {
- gp.moveTo(point.x, point.y);
- }
+ private static void buildShapeImpl(final OutlineShape shape, final char symbol, final OTGlyph glyph, final Factory<? extends Vertex> vertexFactory) {
+ // Iterate through all of the points in the glyph. Each time we find a
+ // contour end point, add the point range to the path.
+ int startIndex = 0;
+ int count = 0;
+ final int totalPoints = glyph.getPointCount();
+ for (int i = 0; i < totalPoints; i++) {
+ count++;
+ if ( glyph.getPoint(i).endOfContour ) {
+ int offset = 0;
+ while ( offset < count - 1 ) { // require at least +1 point (last one is end-of-contour)
+ final Point p0 = glyph.getPoint(startIndex + offset%count);
+ final Point p1 = glyph.getPoint(startIndex + (offset+1)%count);
+ final Point p2 = glyph.getPoint(startIndex + (offset+2)%count);
+ final Point p3 = offset+3 < count ? glyph.getPoint(startIndex + offset+3) : null;
+ if( DEBUG ) {
+ System.err.println("GlyphShape<"+symbol+">: offset "+offset+" of "+count+"/"+totalPoints+" points");
+ final int pMIdx= (offset==0) ? startIndex+count-1 : startIndex+(offset-1)%count;
+ final Point pM = glyph.getPoint(pMIdx);
+ final int p0Idx = startIndex + offset%count;
+ final int p1Idx = startIndex + (offset+1)%count;
+ final int p2Idx = startIndex + (offset+2)%count;
+ final int p3Idx = startIndex + (offset+3)%count;
+ System.err.println("\t pM["+pMIdx+"] "+pM);
+ System.err.println("\t p0["+p0Idx+"] "+p0);
+ System.err.println("\t p1["+p1Idx+"] "+p1);
+ System.err.println("\t p2["+p2Idx+"] "+p2);
+ System.err.println("\t p3["+p3Idx+"] "+p3);
+ }
+ if(offset == 0) {
+ addShapeMoveTo(shape, vertexFactory, p0);
+ // gp.moveTo(point.x, point.y);
+ }
- if (point.onCurve) {
- if (point_plus1.onCurve) {
- // s = new Line2D.Float(point.x, point.y, point_plus1.x, point_plus1.y);
- gp.lineTo( point_plus1.x, point_plus1.y );
- offset++;
- } else {
- if (point_plus2.onCurve) {
- // s = new QuadCurve2D.Float( point.x, point.y, point_plus1.x, point_plus1.y, point_plus2.x, point_plus2.y);
- gp.quadTo(point_plus1.x, point_plus1.y, point_plus2.x, point_plus2.y);
- offset+=2;
+ if( p0.endOfContour ) {
+ // Branch-0: EOC ** SHALL NEVER HAPPEN **
+ if( DEBUG ) { System.err.println("B0 .. end-of-contour **** EOC"); }
+ shape.closeLastOutline(false);
+ break;
+ } else if (p0.onCurve) {
+ if (p1.onCurve) {
+ // Branch-1: point.onCurve && p1.onCurve
+ if( DEBUG ) { System.err.println("B1 .. line-to p0-p1"); }
+
+ // s = new Line2D.Float(point.x, point.y, p1.x, p1.y);
+ // gp.lineTo( p1.x, p1.y );
+ addShapeLineTo(shape, vertexFactory, p1);
+ offset++;
+ } else {
+ if (p2.onCurve) {
+ // Branch-2: point.onCurve && !p1.onCurve && p2.onCurve
+ if( DEBUG ) { System.err.println("B2 .. quad-to p0-p1-p2"); }
+
+ // s = new QuadCurve2D.Float( point.x, point.y, p1.x, p1.y, p2.x, p2.y);
+ // gp.quadTo(p1.x, p1.y, p2.x, p2.y);
+ addShapeQuadTo(shape, vertexFactory, p1, p2);
+ offset+=2;
+ } else {
+ if (null != p3 && p3.onCurve) {
+ // Branch-3: point.onCurve && !p1.onCurve && !p2.onCurve && p3.onCurve
+ if( DEBUG ) { System.err.println("B3 .. 2-quad p0-p1-p1_2, p1_2-p2-p3 **** 2QUAD"); }
+ // addShapeCubicTo(shape, vertexFactory, p1, p2, p3);
+ addShapeQuadTo(shape, vertexFactory, p1,
+ midValue(p1.x, p2.x),
+ midValue(p1.y, p2.y), true);
+ addShapeQuadTo(shape, vertexFactory, p2, p3);
+ offset+=3;
+ } else {
+ // Branch-4: point.onCurve && !p1.onCurve && !p2.onCurve && !p3.onCurve
+ if( DEBUG ) { System.err.println("B4 .. quad-to p0-p1-p2h **** MID"); }
+
+ // s = new QuadCurve2D.Float(point.x,point.y,p1.x,p1.y,
+ // midValue(p1.x, p2.x), midValue(p1.y, p2.y));
+ // gp.quadTo(p1.x, p1.y, midValue(p1.x, p2.x), midValue(p1.y, p2.y));
+ addShapeQuadTo(shape, vertexFactory, p1,
+ midValue(p1.x, p2.x),
+ midValue(p1.y, p2.y), true);
+ offset+=2; // Skip p2 as done in Typecast
+ }
+ }
+ }
} else {
- // s = new QuadCurve2D.Float(point.x,point.y,point_plus1.x,point_plus1.y,
- // midValue(point_plus1.x, point_plus2.x), midValue(point_plus1.y, point_plus2.y));
- gp.quadTo(point_plus1.x, point_plus1.y, midValue(point_plus1.x, point_plus2.x), midValue(point_plus1.y, point_plus2.y));
- offset+=2;
+ if (!p1.onCurve) {
+ // Branch-5: !point.onCurve && !p1.onCurve
+ if( DEBUG ) { System.err.println("B5 .. quad-to pMh-p0-p1h ***** MID"); }
+ // s = new QuadCurve2D.Float(midValue(pM.x, point.x), midValue(pM.y, point.y),
+ // point.x, point.y,
+ // midValue(point.x, p1.x), midValue(point.y, p1.y));
+ addShapeQuadTo(shape, vertexFactory, p0,
+ midValue(p0.x, p1.x), midValue(p0.y, p1.y), true);
+ offset++;
+ } else {
+ // Branch-6: !point.onCurve && p1.onCurve
+ if( DEBUG ) { System.err.println("B6 .. quad-to pMh-p0-p1"); }
+ // s = new QuadCurve2D.Float(midValue(pM.x, point.x), midValue(pM.y, point.y),
+ // point.x, point.y, p1.x, p1.y);
+ // gp.quadTo(point.x, point.y, p1.x, p1.y);
+ addShapeQuadTo(shape, vertexFactory, p0, p1);
+ offset++;
+ }
}
}
- } else {
- if (point_plus1.onCurve) {
- // s = new QuadCurve2D.Float(midValue(point_minus1.x, point.x), midValue(point_minus1.y, point.y),
- // point.x, point.y, point_plus1.x, point_plus1.y);
- //gp.curve3(point_plus1.x, point_plus1.y, point.x, point.y);
- gp.quadTo(point.x, point.y, point_plus1.x, point_plus1.y);
- offset++;
-
- } else {
- // s = new QuadCurve2D.Float(midValue(point_minus1.x, point.x), midValue(point_minus1.y, point.y), point.x, point.y,
- // midValue(point.x, point_plus1.x), midValue(point.y, point_plus1.y));
- //gp.curve3(midValue(point.x, point_plus1.x), midValue(point.y, point_plus1.y), point.x, point.y);
- gp.quadTo(point.x, point.y, midValue(point.x, point_plus1.x), midValue(point.y, point_plus1.y));
- offset++;
- }
+ shape.closeLastOutline(false);
+ startIndex = i + 1;
+ count = 0;
}
}
}
- private static int midValue(int a, int b) {
- return a + (b - a)/2;
+ private static float midValue(final float a, final float b) {
+ return a + (b - a)/2f;
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/Disassembler.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/Disassembler.java
index b5535758d..181f77ee4 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/Disassembler.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/Disassembler.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot;
@@ -22,7 +22,7 @@ public class Disassembler {
* @param ip The current instruction pointer
* @return The new instruction pointer
*/
- public static int advanceIP(short[] instructions, int ip) {
+ public static int advanceIP(final short[] instructions, int ip) {
// The high word specifies font, cvt, or glyph program
int i = ip & 0xffff;
@@ -46,8 +46,8 @@ public class Disassembler {
return ip;
}
- public static short getPushCount(short[] instructions, int ip) {
- short instr = instructions[ip & 0xffff];
+ public static short getPushCount(final short[] instructions, final int ip) {
+ final short instr = instructions[ip & 0xffff];
if ((Mnemonic.NPUSHB == instr) || (Mnemonic.NPUSHW == instr)) {
return instructions[(ip & 0xffff) + 1];
} else if ((Mnemonic.PUSHB == (instr & 0xf8)) || (Mnemonic.PUSHW == (instr & 0xf8))) {
@@ -56,11 +56,11 @@ public class Disassembler {
return 0;
}
- public static int[] getPushData(short[] instructions, int ip) {
- int count = getPushCount(instructions, ip);
- int[] data = new int[count];
- int i = ip & 0xffff;
- short instr = instructions[i];
+ public static int[] getPushData(final short[] instructions, final int ip) {
+ final int count = getPushCount(instructions, ip);
+ final int[] data = new int[count];
+ final int i = ip & 0xffff;
+ final short instr = instructions[i];
if (Mnemonic.NPUSHB == instr) {
for (int j = 0; j < count; j++) {
data[j] = instructions[i + j + 2];
@@ -81,8 +81,8 @@ public class Disassembler {
return data;
}
- public static String disassemble(short[] instructions, int leadingSpaces) {
- StringBuilder sb = new StringBuilder();
+ public static String disassemble(final short[] instructions, final int leadingSpaces) {
+ final StringBuilder sb = new StringBuilder();
int ip = 0;
while (ip < instructions.length) {
for (int i = 0; i < leadingSpaces; i++) {
@@ -91,7 +91,7 @@ public class Disassembler {
sb.append(ip).append(": ");
sb.append(Mnemonic.getMnemonic(instructions[ip]));
if (getPushCount(instructions, ip) > 0) {
- int[] data = getPushData(instructions, ip);
+ final int[] data = getPushData(instructions, ip);
for(int j = 0; j < data.length; j++) {
if ((instructions[ip] == Mnemonic.PUSHW) ||
(instructions[ip] == Mnemonic.NPUSHW)) {
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/Fixed.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/Fixed.java
index ece0aae4b..14e83814c 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/Fixed.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/Fixed.java
@@ -812,7 +812,7 @@ public class Fixed {
* @param num Input
* @return Output
*/
- public static int arctan( int num ) {
+ public static int arctan( final int num ) {
return 0;
}
@@ -822,7 +822,7 @@ public class Fixed {
* @param num The 26.6 fixed number in question
* @return The resulting square root
*/
- public static int squareRoot(int num) {
+ public static int squareRoot(final int num) {
int n = num;
int divisor = num;
int nSquared;
@@ -840,13 +840,13 @@ public class Fixed {
}
return n;
}
-
- public static float floatValue(long fixed) {
+
+ public static float floatValue(final long fixed) {
return (fixed >> 16) + (float)(fixed & 0xffff) / 0x10000;
}
-
- public static float roundedFloatValue(long fixed, int decimalPlaces) {
- int factor = 10 * decimalPlaces;
+
+ public static float roundedFloatValue(final long fixed, final int decimalPlaces) {
+ final int factor = 10 * decimalPlaces;
return (float)((int)(floatValue(fixed) * factor)) / factor;
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/Mnemonic.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/Mnemonic.java
index 6b3dc1f6f..6df892d4d 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/Mnemonic.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/Mnemonic.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot;
@@ -143,7 +143,7 @@ public class Mnemonic {
* @param opcode The opcode for which the mnemonic is required
* @return The mnemonic, with a description
*/
- public static String getMnemonic(short opcode) {
+ public static String getMnemonic(final short opcode) {
if (opcode >= MIRP) return "MIRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]";
else if (opcode >= MDRP) return "MDRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]";
else if (opcode >= PUSHW) return "PUSHW["+((opcode&7)+1)+"]";
@@ -269,7 +269,7 @@ public class Mnemonic {
else return "????";
}
- public static String getComment(short opcode) {
+ public static String getComment(final short opcode) {
if (opcode >= MIRP) return "MIRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]\t\tMove Indirect Relative Point";
else if (opcode >= MDRP) return "MDRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]\t\tMove Direct Relative Point";
else if (opcode >= PUSHW) return "PUSHW["+((opcode&7)+1)+"]";
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFont.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFont.java
index 8c14b7302..e83a428ed 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFont.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFont.java
@@ -79,7 +79,7 @@ import jogamp.graph.font.typecast.ot.table.VheaTable;
*/
public class OTFont {
- private OTFontCollection _fc;
+ private final OTFontCollection _fc;
private TableDirectory _tableDirectory = null;
private Table[] _tables;
private Os2Table _os2;
@@ -98,17 +98,17 @@ public class OTFont {
/**
* Constructor
*/
- public OTFont(OTFontCollection fc) {
+ public OTFont(final OTFontCollection fc) {
_fc = fc;
}
- public StringBuilder getName(int nameIndex, StringBuilder sb) {
+ public StringBuilder getName(final int nameIndex, StringBuilder sb) {
if(null == sb) {
sb = new StringBuilder();
- }
+ }
return _name.getRecordsRecordString(sb, nameIndex);
}
-
- public StringBuilder getAllNames(StringBuilder sb, String separator) {
+
+ public StringBuilder getAllNames(StringBuilder sb, final String separator) {
if(null != _name) {
if(null == sb) {
sb = new StringBuilder();
@@ -117,10 +117,10 @@ public class OTFont {
_name.getRecord(i).getRecordString(sb).append(separator);
}
}
- return sb;
+ return sb;
}
-
- public Table getTable(int tableType) {
+
+ public Table getTable(final int tableType) {
for (int i = 0; i < _tables.length; i++) {
if ((_tables[i] != null) && (_tables[i].getType() == tableType)) {
return _tables[i];
@@ -132,31 +132,31 @@ public class OTFont {
public Os2Table getOS2Table() {
return _os2;
}
-
+
public CmapTable getCmapTable() {
return _cmap;
}
-
+
public HeadTable getHeadTable() {
return _head;
}
-
+
public HheaTable getHheaTable() {
return _hhea;
}
-
+
public HdmxTable getHdmxTable() {
return _hdmx;
}
-
+
public HmtxTable getHmtxTable() {
return _hmtx;
}
-
+
public LocaTable getLocaTable() {
return _loca;
}
-
+
public MaxpTable getMaxpTable() {
return _maxp;
}
@@ -185,9 +185,9 @@ public class OTFont {
return _maxp.getNumGlyphs();
}
- public OTGlyph getGlyph(int i) {
-
- final GlyfDescript _glyfDescr = _glyf.getDescription(i);
+ public OTGlyph getGlyph(final int i) {
+
+ final GlyfDescript _glyfDescr = _glyf.getDescription(i);
return (null != _glyfDescr)
? new OTGlyph(
_glyfDescr,
@@ -195,17 +195,17 @@ public class OTFont {
_hmtx.getAdvanceWidth(i))
: null;
}
-
+
public TableDirectory getTableDirectory() {
return _tableDirectory;
}
-
+
private Table readTable(
- DataInputStream dis,
- int tablesOrigin,
- int tag) throws IOException {
+ final DataInputStream dis,
+ final int tablesOrigin,
+ final int tag) throws IOException {
dis.reset();
- DirectoryEntry entry = _tableDirectory.getEntryByTag(tag);
+ final DirectoryEntry entry = _tableDirectory.getEntryByTag(tag);
if (entry == null) {
return null;
}
@@ -225,16 +225,16 @@ public class OTFont {
* individual font resource data.
*/
protected void read(
- DataInputStream dis,
- int directoryOffset,
- int tablesOrigin) throws IOException {
-
+ final DataInputStream dis,
+ final int directoryOffset,
+ final int tablesOrigin) throws IOException {
+
// Load the table directory
dis.reset();
dis.skip(directoryOffset);
_tableDirectory = new TableDirectory(dis);
_tables = new Table[_tableDirectory.getNumTables()];
-
+
// Load some prerequisite tables
_head = (HeadTable) readTable(dis, tablesOrigin, Table.head);
_hhea = (HheaTable) readTable(dis, tablesOrigin, Table.hhea);
@@ -252,10 +252,10 @@ public class OTFont {
if (_vhea != null) {
_tables[index++] = _vhea;
}
-
+
// Load all other tables
for (int i = 0; i < _tableDirectory.getNumTables(); i++) {
- DirectoryEntry entry = _tableDirectory.getEntry(i);
+ final DirectoryEntry entry = _tableDirectory.getEntry(i);
if (entry.getTag() == Table.head
|| entry.getTag() == Table.hhea
|| entry.getTag() == Table.maxp
@@ -283,6 +283,7 @@ public class OTFont {
_glyf = (GlyfTable) getTable(Table.glyf);
}
+ @Override
public String toString() {
if (_tableDirectory != null) {
return _tableDirectory.toString();
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java
index 4a041604d..ed07cb30a 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java
@@ -25,6 +25,7 @@ import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
@@ -48,7 +49,7 @@ public class OTFontCollection {
private String _fileName;
private TTCHeader _ttcHeader;
private OTFont[] _fonts;
- private ArrayList<Table> _tables = new ArrayList<Table>();
+ private final ArrayList<Table> _tables = new ArrayList<Table>();
private boolean _resourceFork = false;
/** Creates new FontCollection */
@@ -58,12 +59,22 @@ public class OTFontCollection {
/**
* @param file The OpenType font file
*/
- public static OTFontCollection create(File file) throws IOException {
- OTFontCollection fc = new OTFontCollection();
+ public static OTFontCollection create(final File file) throws IOException {
+ final OTFontCollection fc = new OTFontCollection();
fc.read(file);
return fc;
}
+ /**
+ * @param istream The OpenType font input stream
+ * @param streamLen the length of the OpenType font segment in the stream
+ */
+ public static OTFontCollection create(final InputStream istream, final int streamLen) throws IOException {
+ final OTFontCollection fc = new OTFontCollection();
+ fc.read(istream, streamLen);
+ return fc;
+ }
+
public String getPathName() {
return _pathName;
}
@@ -72,21 +83,21 @@ public class OTFontCollection {
return _fileName;
}
- public OTFont getFont(int i) {
+ public OTFont getFont(final int i) {
return _fonts[i];
}
-
+
public int getFontCount() {
return _fonts.length;
}
-
+
public TTCHeader getTtcHeader() {
return _ttcHeader;
}
- public Table getTable(DirectoryEntry de) {
+ public Table getTable(final DirectoryEntry de) {
for (int i = 0; i < _tables.size(); i++) {
- Table table = _tables.get(i);
+ final Table table = _tables.get(i);
if ((table.getDirectoryEntry().getTag() == de.getTag()) &&
(table.getDirectoryEntry().getOffset() == de.getOffset())) {
return table;
@@ -95,7 +106,7 @@ public class OTFontCollection {
return null;
}
- public void addTable(Table table) {
+ public void addTable(final Table table) {
_tables.add(table);
}
@@ -119,31 +130,59 @@ public class OTFontCollection {
}
_resourceFork = true;
}
+ final int streamLen = (int) file.length();
+ final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file), streamLen);
+ try {
+ readImpl(bis, streamLen);
+ } finally {
+ bis.close();
+ }
+ }
- DataInputStream dis = new DataInputStream(
- new BufferedInputStream(
- new FileInputStream(file), (int) file.length()));
- dis.mark((int) file.length());
+ /**
+ * @param is The OpenType font stream
+ * @param streamLen the length of the OpenType font segment in the stream
+ */
+ protected void read(final InputStream is, final int streamLen) throws IOException {
+ _pathName = "";
+ _fileName = "";
+ final InputStream bis;
+ if( is.markSupported() ) {
+ bis = is;
+ } else {
+ bis = new BufferedInputStream(is, streamLen);
+ }
+ readImpl(bis, streamLen);
+ }
+ /**
+ * @param is The OpenType font stream, must {@link InputStream#markSupported() support mark}!
+ */
+ private void readImpl(final InputStream bis, final int streamLen) throws IOException {
+ if( !bis.markSupported() ) {
+ throw new IllegalArgumentException("stream of type "+bis.getClass().getName()+" doesn't support mark");
+ }
+ bis.mark(streamLen);
+ final DataInputStream dis = new DataInputStream(bis);
if (_resourceFork || _pathName.endsWith(".dfont")) {
// This is a Macintosh font suitcase resource
- ResourceHeader resourceHeader = new ResourceHeader(dis);
+ final ResourceHeader resourceHeader = new ResourceHeader(dis);
// Seek to the map offset and read the map
dis.reset();
dis.skip(resourceHeader.getMapOffset());
- ResourceMap map = new ResourceMap(dis);
+ final ResourceMap map = new ResourceMap(dis);
// Get the 'sfnt' resources
- ResourceType resourceType = map.getResourceType("sfnt");
+ final ResourceType resourceType = map.getResourceType("sfnt");
// Load the font data
_fonts = new OTFont[resourceType.getCount()];
for (int i = 0; i < resourceType.getCount(); i++) {
- ResourceReference resourceReference = resourceType.getReference(i);
+ final ResourceReference resourceReference = resourceType.getReference(i);
_fonts[i] = new OTFont(this);
- int offset = resourceHeader.getDataOffset() +
+ final int offset = resourceHeader.getDataOffset() +
resourceReference.getDataOffset() + 4;
_fonts[i].read(dis, offset, offset);
}
@@ -165,6 +204,5 @@ public class OTFontCollection {
_fonts[0] = new OTFont(this);
_fonts[0].read(dis, 0, 0);
}
- dis.close();
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java
index 5c004246a..8ed450326 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java
@@ -56,7 +56,7 @@ import jogamp.graph.font.typecast.ot.table.GlyfDescript;
import jogamp.graph.font.typecast.ot.table.GlyphDescription;
import jogamp.graph.font.typecast.t2.T2Interpreter;
-import com.jogamp.graph.geom.AABBox;
+import com.jogamp.opengl.math.geom.AABBox;
@@ -65,10 +65,10 @@ import com.jogamp.graph.geom.AABBox;
* @version $Id: Glyph.java,v 1.3 2007-02-21 12:23:54 davidsch Exp $
* @author <a href="mailto:[email protected]">David Schweinsberg</a>, Sven Gothel
*/
-public class OTGlyph {
+public final class OTGlyph {
- protected short _leftSideBearing;
- protected int _advanceWidth;
+ private final short _leftSideBearing;
+ private final int _advanceWidth;
private Point[] _points;
AABBox _bbox;
@@ -79,7 +79,7 @@ public class OTGlyph {
* @param lsb The Left Side Bearing.
* @param advance The advance width.
*/
- public OTGlyph(GlyphDescription gd, short lsb, int advance) {
+ public OTGlyph(final GlyphDescription gd, final short lsb, final int advance) {
_leftSideBearing = lsb;
_advanceWidth = advance;
describe(gd);
@@ -91,47 +91,44 @@ public class OTGlyph {
* @param lsb The Left Side Bearing.
* @param advance The advance width.
*/
- public OTGlyph(Charstring cs, short lsb, int advance) {
+ public OTGlyph(final Charstring cs, final short lsb, final int advance) {
_leftSideBearing = lsb;
_advanceWidth = advance;
if (cs instanceof CharstringType2) {
- T2Interpreter t2i = new T2Interpreter();
+ final T2Interpreter t2i = new T2Interpreter();
_points = t2i.execute((CharstringType2) cs);
} else {
//throw unsupported charstring type
}
}
- public AABBox getBBox() {
- return _bbox;
+ public final void clearPointData() {
+ _points = null;
}
-
- public int getAdvanceWidth() {
+
+ public final AABBox getBBox() {
+ return _bbox;
+ }
+
+ public final int getAdvanceWidth() {
return _advanceWidth;
}
- public short getLeftSideBearing() {
+ public final short getLeftSideBearing() {
return _leftSideBearing;
}
- public Point getPoint(int i) {
+ public final Point getPoint(final int i) {
return _points[i];
}
- public int getPointCount() {
- return _points.length;
- }
-
- /**
- * Resets the glyph to the TrueType table settings
- */
- public void reset() {
+ public final int getPointCount() {
+ return null != _points ? _points.length : 0;
}
/**
* @param factor a 16.16 fixed value
- */
- public void scale(int factor) {
+ public void scale(final int factor) {
for (int i = 0; i < _points.length; i++) {
//points[i].x = ( points[i].x * factor ) >> 6;
//points[i].y = ( points[i].y * factor ) >> 6;
@@ -141,15 +138,16 @@ public class OTGlyph {
_leftSideBearing = (short)(( _leftSideBearing * factor) >> 6);
_advanceWidth = (_advanceWidth * factor) >> 6;
}
+ */
/**
* Set the points of a glyph from the GlyphDescription
*/
- private void describe(GlyphDescription gd) {
+ private final void describe(final GlyphDescription gd) {
int endPtIndex = 0;
_points = new Point[gd.getPointCount() /* + 2 */ ];
for (int i = 0; i < gd.getPointCount(); i++) {
- boolean endPt = gd.getEndPtOfContours(endPtIndex) == i;
+ final boolean endPt = gd.getEndPtOfContours(endPtIndex) == i;
if (endPt) {
endPtIndex++;
}
@@ -163,7 +161,7 @@ public class OTGlyph {
// Append the origin and advanceWidth points (n & n+1)
// _points[gd.getPointCount()] = new Point(0, 0, true, true);
// _points[gd.getPointCount()+1] = new Point(_advanceWidth, 0, true, true);
-
+
_bbox = new AABBox(gd.getXMinimum(), gd.getYMinimum(), 0, gd.getXMaximum(), gd.getYMaximum(), 0);
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/Point.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/Point.java
index f1a090d68..76b0f90f3 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/Point.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/Point.java
@@ -18,12 +18,15 @@ public class Point {
public int y = 0;
public boolean onCurve = true;
public boolean endOfContour = false;
- public boolean touched = false;
- public Point(int x, int y, boolean onCurve, boolean endOfContour) {
+ public Point(final int x, final int y, final boolean onCurve, final boolean endOfContour) {
this.x = x;
this.y = y;
this.onCurve = onCurve;
this.endOfContour = endOfContour;
}
+
+ public String toString() {
+ return "P["+x+"/"+y+", on "+onCurve+", end "+endOfContour+"]";
+ }
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceData.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceData.java
index 433ff6051..709ff9e91 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceData.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceData.java
@@ -30,11 +30,11 @@ import java.io.IOException;
*/
public class ResourceData {
- private byte[] data;
-
+ private final byte[] data;
+
/** Creates new ResourceData */
- public ResourceData(DataInput di) throws IOException {
- int dataLen = di.readInt();
+ public ResourceData(final DataInput di) throws IOException {
+ final int dataLen = di.readInt();
data = new byte[dataLen];
di.readFully(data);
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceFile.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceFile.java
index 2ada22c82..767eafb6b 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceFile.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceFile.java
@@ -31,16 +31,16 @@ import java.io.RandomAccessFile;
*/
public class ResourceFile {
- private ResourceHeader header;
- private ResourceMap map;
-
+ private final ResourceHeader header;
+ private final ResourceMap map;
+
/** Creates new Resource */
- public ResourceFile(RandomAccessFile raf) throws IOException {
+ public ResourceFile(final RandomAccessFile raf) throws IOException {
// Read header at the beginning of the file
raf.seek(0);
header = new ResourceHeader(raf);
-
+
// Seek to the map offset and read the map
raf.seek(header.getMapOffset());
map = new ResourceMap(raf);
@@ -50,27 +50,27 @@ public class ResourceFile {
return map;
}
- public static void main(String[] args) {
+ public static void main(final String[] args) {
try {
//RandomAccessFile raf = new RandomAccessFile("/Library/Fonts/GillSans.dfont", "r");
-
+
// Tests loading a font from a resource fork on Mac OS X
- RandomAccessFile raf = new RandomAccessFile("/Library/Fonts/Georgia/..namedfork/rsrc", "r");
- ResourceFile resource = new ResourceFile(raf);
+ final RandomAccessFile raf = new RandomAccessFile("/Library/Fonts/Georgia/..namedfork/rsrc", "r");
+ final ResourceFile resource = new ResourceFile(raf);
for (int i = 0; i < resource.getResourceMap().getResourceTypeCount(); i++) {
System.out.println(resource.getResourceMap().getResourceType(i).getTypeAsString());
}
-
+
// Get the first 'sfnt' resource
ResourceType type = resource.getResourceMap().getResourceType("sfnt");
ResourceReference reference = type.getReference(0);
-
+
type = resource.getResourceMap().getResourceType("FOND");
for (int i = 0; i < type.getCount(); ++i) {
reference = type.getReference(i);
System.out.println(reference.getName());
}
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceHeader.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceHeader.java
index 8f5224632..dea0b9843 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceHeader.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceHeader.java
@@ -30,13 +30,13 @@ import java.io.IOException;
*/
public class ResourceHeader {
- private int dataOffset;
- private int mapOffset;
- private int dataLen;
- private int mapLen;
+ private final int dataOffset;
+ private final int mapOffset;
+ private final int dataLen;
+ private final int mapLen;
/** Creates new ResourceHeader */
- public ResourceHeader(DataInput di) throws IOException {
+ public ResourceHeader(final DataInput di) throws IOException {
dataOffset = di.readInt();
mapOffset = di.readInt();
dataLen = di.readInt();
@@ -46,15 +46,15 @@ public class ResourceHeader {
public int getDataOffset() {
return dataOffset;
}
-
+
public int getMapOffset() {
return mapOffset;
}
-
+
public int getDataLength() {
return dataLen;
}
-
+
public int getMapLength() {
return mapLen;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceMap.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceMap.java
index 96ba06087..781e0adf3 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceMap.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceMap.java
@@ -30,42 +30,41 @@ import java.io.IOException;
*/
public class ResourceMap {
- private byte[] headerCopy = new byte[16];
- private int nextResourceMap;
- private int fileReferenceNumber;
- private int attributes;
- private ResourceType[] types;
-
+ private final byte[] headerCopy = new byte[16];
+ // private final int nextResourceMap;
+ // private final int fileReferenceNumber;
+ // private final int attributes;
+ private final ResourceType[] types;
+
/** Creates new ResourceMap */
- public ResourceMap(DataInput di) throws IOException {
+ public ResourceMap(final DataInput di) throws IOException {
di.readFully(headerCopy);
- nextResourceMap = di.readInt();
- fileReferenceNumber = di.readUnsignedShort();
- attributes = di.readUnsignedShort();
- int typeOffset = di.readUnsignedShort();
- int nameOffset = di.readUnsignedShort();
- int typeCount = di.readUnsignedShort() + 1;
-
+ /* nextResourceMap = */ di.readInt();
+ /* fileReferenceNumber = */ di.readUnsignedShort();
+ /* attributes = */ di.readUnsignedShort();
+ /* final int typeOffset = */ di.readUnsignedShort();
+ /* final int nameOffset = */ di.readUnsignedShort();
+ final int typeCount = di.readUnsignedShort() + 1;
+
// Read types
types = new ResourceType[typeCount];
for (int i = 0; i < typeCount; i++) {
types[i] = new ResourceType(di);
}
-
+
// Read the references
for (int i = 0; i < typeCount; i++) {
types[i].readRefs(di);
}
-
+
// Read the names
for (int i = 0; i < typeCount; i++) {
types[i].readNames(di);
}
}
- public ResourceType getResourceType(String typeName) {
+ public ResourceType getResourceType(final String typeName) {
for (int i = 0; i < types.length; i++) {
- String s = types[i].getTypeAsString();
if (types[i].getTypeAsString().equals(typeName)) {
return types[i];
}
@@ -73,10 +72,10 @@ public class ResourceMap {
return null;
}
- public ResourceType getResourceType(int i) {
+ public ResourceType getResourceType(final int i) {
return types[i];
}
-
+
public int getResourceTypeCount() {
return types.length;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceReference.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceReference.java
index fd7ec46b2..f76b85cf4 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceReference.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceReference.java
@@ -30,15 +30,15 @@ import java.io.IOException;
*/
public class ResourceReference {
- private int id;
- private short nameOffset;
- private short attributes;
- private int dataOffset;
- private int handle;
+ private final int id;
+ private final short nameOffset;
+ private final short attributes;
+ private final int dataOffset;
+ private final int handle;
private String name;
-
+
/** Creates new ResourceReference */
- protected ResourceReference(DataInput di) throws IOException {
+ protected ResourceReference(final DataInput di) throws IOException {
id = di.readUnsignedShort();
nameOffset = di.readShort();
attributes = (short) di.readUnsignedByte();
@@ -46,10 +46,10 @@ public class ResourceReference {
handle = di.readInt();
}
- protected void readName(DataInput di) throws IOException {
+ protected void readName(final DataInput di) throws IOException {
if (nameOffset > -1) {
- int len = di.readUnsignedByte();
- byte[] buf = new byte[len];
+ final int len = di.readUnsignedByte();
+ final byte[] buf = new byte[len];
di.readFully(buf);
name = new String(buf);
}
@@ -58,23 +58,23 @@ public class ResourceReference {
public int getId() {
return id;
}
-
+
public short getNameOffset() {
return nameOffset;
}
-
+
public short getAttributes() {
return attributes;
}
-
+
public int getDataOffset() {
return dataOffset;
}
-
+
public int getHandle() {
return handle;
}
-
+
public String getName() {
return name;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceType.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceType.java
index 1c7e24c0f..903fe1a48 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceType.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/mac/ResourceType.java
@@ -30,26 +30,26 @@ import java.io.IOException;
*/
public class ResourceType {
- private int type;
- private int count;
- private int offset;
- private ResourceReference[] references;
-
+ private final int type;
+ private final int count;
+ private final int offset;
+ private final ResourceReference[] references;
+
/** Creates new ResourceType */
- protected ResourceType(DataInput di) throws IOException {
+ protected ResourceType(final DataInput di) throws IOException {
type = di.readInt();
count = di.readUnsignedShort() + 1;
offset = di.readUnsignedShort();
references = new ResourceReference[count];
}
-
- protected void readRefs(DataInput di) throws IOException {
+
+ protected void readRefs(final DataInput di) throws IOException {
for (int i = 0; i < count; i++) {
references[i] = new ResourceReference(di);
}
}
- protected void readNames(DataInput di) throws IOException {
+ protected void readNames(final DataInput di) throws IOException {
for (int i = 0; i < count; i++) {
references[i].readName(di);
}
@@ -58,7 +58,7 @@ public class ResourceType {
public int getType() {
return type;
}
-
+
public String getTypeAsString() {
return new StringBuilder()
.append((char)((type>>24)&0xff))
@@ -67,16 +67,16 @@ public class ResourceType {
.append((char)((type)&0xff))
.toString();
}
-
+
public int getCount() {
return count;
}
-
+
public int getOffset() {
return offset;
}
- public ResourceReference getReference(int i) {
+ public ResourceReference getReference(final int i) {
return references[i];
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/BaseTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/BaseTable.java
index ed615eb72..002f83e9b 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/BaseTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/BaseTable.java
@@ -31,98 +31,104 @@ import java.io.IOException;
* @author <a href="mailto:[email protected]">David Schweinsberg</a>
*/
public class BaseTable implements Table {
-
- private abstract class BaseCoord {
- public abstract int getBaseCoordFormat();
-
- public abstract short getCoordinate();
+ abstract class BaseCoord {
+
+ abstract int getBaseCoordFormat();
+
+ abstract short getCoordinate();
}
-
- private class BaseCoordFormat1 extends BaseCoord {
- private short _coordinate;
-
- protected BaseCoordFormat1(DataInput di) throws IOException {
+ class BaseCoordFormat1 extends BaseCoord {
+
+ private final short _coordinate;
+
+ protected BaseCoordFormat1(final DataInput di) throws IOException {
_coordinate = di.readShort();
}
- public int getBaseCoordFormat() {
+ @Override
+ int getBaseCoordFormat() {
return 1;
}
-
- public short getCoordinate() {
+
+ @Override
+ short getCoordinate() {
return _coordinate;
}
-
+
}
-
- private class BaseCoordFormat2 extends BaseCoord {
-
- private short _coordinate;
- private int _referenceGlyph;
- private int _baseCoordPoint;
-
- protected BaseCoordFormat2(DataInput di) throws IOException {
+
+ class BaseCoordFormat2 extends BaseCoord {
+
+ private final short _coordinate;
+ // private final int _referenceGlyph;
+ // private final int _baseCoordPoint;
+
+ protected BaseCoordFormat2(final DataInput di) throws IOException {
_coordinate = di.readShort();
- _referenceGlyph = di.readUnsignedShort();
- _baseCoordPoint = di.readUnsignedShort();
+ /* _referenceGlyph = */ di.readUnsignedShort();
+ /* _baseCoordPoint = */ di.readUnsignedShort();
}
- public int getBaseCoordFormat() {
+ @Override
+ int getBaseCoordFormat() {
return 2;
}
-
- public short getCoordinate() {
+
+ @Override
+ short getCoordinate() {
return _coordinate;
}
-
+
}
-
- private class BaseCoordFormat3 extends BaseCoord {
- private short _coordinate;
- private int _deviceTableOffset;
-
- protected BaseCoordFormat3(DataInput di) throws IOException {
+ class BaseCoordFormat3 extends BaseCoord {
+
+ private final short _coordinate;
+ // private final int _deviceTableOffset;
+
+ protected BaseCoordFormat3(final DataInput di) throws IOException {
_coordinate = di.readShort();
- _deviceTableOffset = di.readUnsignedShort();
+ /* _deviceTableOffset = */ di.readUnsignedShort();
}
- public int getBaseCoordFormat() {
+ @Override
+ int getBaseCoordFormat() {
return 2;
}
-
- public short getCoordinate() {
+
+ @Override
+ short getCoordinate() {
return _coordinate;
}
-
+
}
-
- private class FeatMinMaxRecord {
-
- private int _tag;
- private int _minCoordOffset;
- private int _maxCoordOffset;
-
- protected FeatMinMaxRecord(DataInput di) throws IOException {
- _tag = di.readInt();
- _minCoordOffset = di.readUnsignedShort();
- _maxCoordOffset = di.readUnsignedShort();
+
+ static class FeatMinMaxRecord {
+
+ // private final int _tag;
+ // private final int _minCoordOffset;
+ // private final int _maxCoordOffset;
+
+ protected FeatMinMaxRecord(final DataInput di) throws IOException {
+ /* _tag = */ di.readInt();
+ /* _minCoordOffset = */ di.readUnsignedShort();
+ /* _maxCoordOffset = */ di.readUnsignedShort();
}
}
-
- private class MinMax {
-
- private int _minCoordOffset;
- private int _maxCoordOffset;
- private int _featMinMaxCount;
- private FeatMinMaxRecord[] _featMinMaxRecord;
-
- protected MinMax(int minMaxOffset) throws IOException {
- DataInput di = getDataInputForOffset(minMaxOffset);
- _minCoordOffset = di.readUnsignedShort();
- _maxCoordOffset = di.readUnsignedShort();
+
+ class MinMax {
+
+ // private final int _minCoordOffset;
+ // private final int _maxCoordOffset;
+ private final int _featMinMaxCount;
+ private final FeatMinMaxRecord[] _featMinMaxRecord;
+
+ protected MinMax(final int minMaxOffset) throws IOException {
+ final DataInput di = getDataInputForOffset(minMaxOffset);
+ /* _minCoordOffset = */ di.readUnsignedShort();
+ /* _maxCoordOffset = */ di.readUnsignedShort();
_featMinMaxCount = di.readUnsignedShort();
_featMinMaxRecord = new FeatMinMaxRecord[_featMinMaxCount];
for (int i = 0; i < _featMinMaxCount; ++i) {
@@ -130,17 +136,17 @@ public class BaseTable implements Table {
}
}
}
-
- private class BaseValues {
-
- private int _defaultIndex;
- private int _baseCoordCount;
- private int[] _baseCoordOffset;
- private BaseCoord[] _baseCoords;
-
- protected BaseValues(int baseValuesOffset) throws IOException {
- DataInput di = getDataInputForOffset(baseValuesOffset);
- _defaultIndex = di.readUnsignedShort();
+
+ class BaseValues {
+
+ // private final int _defaultIndex;
+ private final int _baseCoordCount;
+ private final int[] _baseCoordOffset;
+ private final BaseCoord[] _baseCoords;
+
+ protected BaseValues(final int baseValuesOffset) throws IOException {
+ final DataInput di = getDataInputForOffset(baseValuesOffset);
+ /* _defaultIndex = */ di.readUnsignedShort();
_baseCoordCount = di.readUnsignedShort();
_baseCoordOffset = new int[_baseCoordCount];
for (int i = 0; i < _baseCoordCount; ++i) {
@@ -148,7 +154,7 @@ public class BaseTable implements Table {
}
_baseCoords = new BaseCoord[_baseCoordCount];
for (int i = 0; i < _baseCoordCount; ++i) {
- int format = di.readUnsignedShort();
+ final int format = di.readUnsignedShort();
switch (format) {
case 1:
_baseCoords[i] = new BaseCoordFormat1(di);
@@ -163,39 +169,40 @@ public class BaseTable implements Table {
}
}
}
-
- private class BaseLangSysRecord {
-
- private int _baseLangSysTag;
- private int _minMaxOffset;
-
- protected BaseLangSysRecord(DataInput di) throws IOException {
- _baseLangSysTag = di.readInt();
+
+ static class BaseLangSysRecord {
+
+ // private final int _baseLangSysTag;
+ private final int _minMaxOffset;
+
+ protected BaseLangSysRecord(final DataInput di) throws IOException {
+ /* _baseLangSysTag = */ di.readInt();
_minMaxOffset = di.readUnsignedShort();
}
- public int getBaseLangSysTag() {
+ /**
+ int getBaseLangSysTag() {
return _baseLangSysTag;
- }
-
- public int getMinMaxOffset() {
+ } */
+
+ int getMinMaxOffset() {
return _minMaxOffset;
}
}
-
- private class BaseScript {
-
- private int _thisOffset;
- private int _baseValuesOffset;
- private int _defaultMinMaxOffset;
- private int _baseLangSysCount;
- private BaseLangSysRecord[] _baseLangSysRecord;
+
+ class BaseScript {
+
+ private final int _thisOffset;
+ private final int _baseValuesOffset;
+ private final int _defaultMinMaxOffset;
+ private final int _baseLangSysCount;
+ private final BaseLangSysRecord[] _baseLangSysRecord;
private BaseValues _baseValues;
private MinMax[] _minMax;
-
- protected BaseScript(int baseScriptOffset) throws IOException {
+
+ protected BaseScript(final int baseScriptOffset) throws IOException {
_thisOffset = baseScriptOffset;
- DataInput di = getDataInputForOffset(baseScriptOffset);
+ final DataInput di = getDataInputForOffset(baseScriptOffset);
_baseValuesOffset = di.readUnsignedShort();
_defaultMinMaxOffset = di.readUnsignedShort();
_baseLangSysCount = di.readUnsignedShort();
@@ -211,8 +218,9 @@ public class BaseTable implements Table {
}
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder()
+ final StringBuilder sb = new StringBuilder()
.append("\nBaseScript BaseScriptT").append(Integer.toHexString(_thisOffset))
.append("\nBaseValuesT").append(Integer.toHexString(_thisOffset + _baseValuesOffset))
.append("\nMinMaxT").append(Integer.toHexString(_thisOffset + _defaultMinMaxOffset))
@@ -231,36 +239,36 @@ public class BaseTable implements Table {
return sb.toString();
}
}
-
- private class BaseScriptRecord {
-
- private int _baseScriptTag;
- private int _baseScriptOffset;
- protected BaseScriptRecord(DataInput di) throws IOException {
+ static class BaseScriptRecord {
+
+ private final int _baseScriptTag;
+ private final int _baseScriptOffset;
+
+ protected BaseScriptRecord(final DataInput di) throws IOException {
_baseScriptTag = di.readInt();
_baseScriptOffset = di.readUnsignedShort();
}
- public int getBaseScriptTag() {
+ int getBaseScriptTag() {
return _baseScriptTag;
}
-
- public int getBaseScriptOffset() {
+
+ int getBaseScriptOffset() {
return _baseScriptOffset;
}
}
-
- private class BaseScriptList {
-
- private int _thisOffset;
- private int _baseScriptCount;
- private BaseScriptRecord[] _baseScriptRecord;
- private BaseScript[] _baseScripts;
-
- protected BaseScriptList(int baseScriptListOffset) throws IOException {
+
+ class BaseScriptList {
+
+ private final int _thisOffset;
+ private final int _baseScriptCount;
+ private final BaseScriptRecord[] _baseScriptRecord;
+ private final BaseScript[] _baseScripts;
+
+ protected BaseScriptList(final int baseScriptListOffset) throws IOException {
_thisOffset = baseScriptListOffset;
- DataInput di = getDataInputForOffset(baseScriptListOffset);
+ final DataInput di = getDataInputForOffset(baseScriptListOffset);
_baseScriptCount = di.readUnsignedShort();
_baseScriptRecord = new BaseScriptRecord[_baseScriptCount];
for (int i = 0; i < _baseScriptCount; ++i) {
@@ -273,8 +281,9 @@ public class BaseTable implements Table {
}
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder()
+ final StringBuilder sb = new StringBuilder()
.append("\nBaseScriptList BaseScriptListT").append(Integer.toHexString(_thisOffset))
.append("\n").append(Integer.toHexString(_baseScriptCount));
for (int i = 0; i < _baseScriptCount; ++i) {
@@ -288,16 +297,16 @@ public class BaseTable implements Table {
return sb.toString();
}
}
-
- private class BaseTagList {
-
- private int _thisOffset;
- private int _baseTagCount;
- private int[] _baselineTag;
-
- protected BaseTagList(int baseTagListOffset) throws IOException {
+
+ class BaseTagList {
+
+ private final int _thisOffset;
+ private final int _baseTagCount;
+ private final int[] _baselineTag;
+
+ protected BaseTagList(final int baseTagListOffset) throws IOException {
_thisOffset = baseTagListOffset;
- DataInput di = getDataInputForOffset(baseTagListOffset);
+ final DataInput di = getDataInputForOffset(baseTagListOffset);
_baseTagCount = di.readUnsignedShort();
_baselineTag = new int[_baseTagCount];
for (int i = 0; i < _baseTagCount; ++i) {
@@ -305,8 +314,9 @@ public class BaseTable implements Table {
}
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder()
+ final StringBuilder sb = new StringBuilder()
.append("\nBaseTagList BaseTagListT").append(Integer.toHexString(_thisOffset))
.append("\n").append(Integer.toHexString(_baseTagCount));
for (int i = 0; i < _baseTagCount; ++i) {
@@ -315,18 +325,18 @@ public class BaseTable implements Table {
return sb.toString();
}
}
-
- private class Axis {
-
- private int _thisOffset;
- private int _baseTagListOffset;
- private int _baseScriptListOffset;
+
+ class Axis {
+
+ private final int _thisOffset;
+ private final int _baseTagListOffset;
+ private final int _baseScriptListOffset;
private BaseTagList _baseTagList;
private BaseScriptList _baseScriptList;
- protected Axis(int axisOffset) throws IOException {
+ protected Axis(final int axisOffset) throws IOException {
_thisOffset = axisOffset;
- DataInput di = getDataInputForOffset(axisOffset);
+ final DataInput di = getDataInputForOffset(axisOffset);
_baseTagListOffset = di.readUnsignedShort();
_baseScriptListOffset = di.readUnsignedShort();
if (_baseTagListOffset != 0) {
@@ -338,6 +348,7 @@ public class BaseTable implements Table {
}
}
+ @Override
public String toString() {
return new StringBuilder()
.append("\nAxis AxisT").append(Integer.toHexString(_thisOffset))
@@ -348,23 +359,23 @@ public class BaseTable implements Table {
.toString();
}
}
-
- private DirectoryEntry _de;
- private int _version;
- private int _horizAxisOffset;
- private int _vertAxisOffset;
+
+ private final DirectoryEntry _de;
+ private final int _version;
+ private final int _horizAxisOffset;
+ private final int _vertAxisOffset;
private Axis _horizAxis;
private Axis _vertAxis;
private byte[] _buf;
/** Creates a new instance of BaseTable */
- protected BaseTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected BaseTable(final DirectoryEntry de, final DataInput di) throws IOException {
_de = (DirectoryEntry) de.clone();
// Load entire table into a buffer, and create another input stream
_buf = new byte[de.getLength()];
di.readFully(_buf);
- DataInput di2 = getDataInputForOffset(0);
+ final DataInput di2 = getDataInputForOffset(0);
_version = di2.readInt();
_horizAxisOffset = di2.readUnsignedShort();
@@ -375,40 +386,42 @@ public class BaseTable implements Table {
if (_vertAxisOffset != 0) {
_vertAxis = new Axis(_vertAxisOffset);
}
-
+
// Let go of the buffer
_buf = null;
}
-
- private DataInput getDataInputForOffset(int offset) {
+
+ private DataInput getDataInputForOffset(final int offset) {
return new DataInputStream(new ByteArrayInputStream(
_buf, offset,
_de.getLength() - offset));
}
-
+
// private String valueAsShortHex(int value) {
// return String.format("%1$4x", value);
// }
-//
+//
// private String valueAsLongHex(int value) {
// return String.format("%1$8x", value);
// }
-
- static protected String tagAsString(int tag) {
- char[] c = new char[4];
+
+ static protected String tagAsString(final int tag) {
+ final char[] c = new char[4];
c[0] = (char)((tag >> 24) & 0xff);
c[1] = (char)((tag >> 16) & 0xff);
c[2] = (char)((tag >> 8) & 0xff);
c[3] = (char)(tag & 0xff);
return String.valueOf(c);
}
-
+
+ @Override
public int getType() {
return BASE;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder()
+ final StringBuilder sb = new StringBuilder()
.append("; 'BASE' Table - Baseline\n;-------------------------------------\n\n")
.append("BASEHeader BASEHeaderT").append(Integer.toHexString(0))
.append("\n").append(Integer.toHexString(_version))
@@ -422,13 +435,14 @@ public class BaseTable implements Table {
}
return sb.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CffTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CffTable.java
index 966f6e17b..d6643f26d 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CffTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CffTable.java
@@ -36,27 +36,27 @@ import java.util.Hashtable;
* @author <a href="mailto:[email protected]">David Schweinsberg</a>
*/
public class CffTable implements Table {
-
- public class Dict {
-
- private Dictionary<Integer, Object> _entries = new Hashtable<Integer, Object>();
- private int[] _data;
+
+ public static class Dict {
+
+ private final Dictionary<Integer, Object> _entries = new Hashtable<Integer, Object>();
+ private final int[] _data;
private int _index;
-
- protected Dict(int[] data, int offset, int length) {
+
+ protected Dict(final int[] data, final int offset, final int length) {
_data = data;
_index = offset;
while (_index < offset + length) {
addKeyAndValueEntry();
}
}
-
- public Object getValue(int key) {
+
+ public Object getValue(final int key) {
return _entries.get(key);
}
-
+
private boolean addKeyAndValueEntry() {
- ArrayList<Object> operands = new ArrayList<Object>();
+ final ArrayList<Object> operands = new ArrayList<Object>();
Object operand = null;
while (isOperandAtIndex()) {
operand = nextOperand();
@@ -74,9 +74,9 @@ public class CffTable implements Table {
}
return true;
}
-
+
private boolean isOperandAtIndex() {
- int b0 = _data[_index];
+ final int b0 = _data[_index];
if ((32 <= b0 && b0 <= 254)
|| b0 == 28
|| b0 == 29
@@ -87,7 +87,7 @@ public class CffTable implements Table {
}
private boolean isOperatorAtIndex() {
- int b0 = _data[_index];
+ final int b0 = _data[_index];
if (0 <= b0 && b0 <= 21) {
return true;
}
@@ -95,44 +95,44 @@ public class CffTable implements Table {
}
private Object nextOperand() {
- int b0 = _data[_index];
+ final int b0 = _data[_index];
if (32 <= b0 && b0 <= 246) {
-
+
// 1 byte integer
++_index;
- return new Integer(b0 - 139);
+ return Integer.valueOf(b0 - 139);
} else if (247 <= b0 && b0 <= 250) {
-
+
// 2 byte integer
- int b1 = _data[_index + 1];
+ final int b1 = _data[_index + 1];
_index += 2;
- return new Integer((b0 - 247) * 256 + b1 + 108);
+ return Integer.valueOf((b0 - 247) * 256 + b1 + 108);
} else if (251 <= b0 && b0 <= 254) {
-
+
// 2 byte integer
- int b1 = _data[_index + 1];
+ final int b1 = _data[_index + 1];
_index += 2;
- return new Integer(-(b0 - 251) * 256 - b1 - 108);
+ return Integer.valueOf(-(b0 - 251) * 256 - b1 - 108);
} else if (b0 == 28) {
-
+
// 3 byte integer
- int b1 = _data[_index + 1];
- int b2 = _data[_index + 2];
+ final int b1 = _data[_index + 1];
+ final int b2 = _data[_index + 2];
_index += 3;
- return new Integer(b1 << 8 | b2);
+ return Integer.valueOf(b1 << 8 | b2);
} else if (b0 == 29) {
-
+
// 5 byte integer
- int b1 = _data[_index + 1];
- int b2 = _data[_index + 2];
- int b3 = _data[_index + 3];
- int b4 = _data[_index + 4];
+ final int b1 = _data[_index + 1];
+ final int b2 = _data[_index + 2];
+ final int b3 = _data[_index + 3];
+ final int b4 = _data[_index + 4];
_index += 5;
- return new Integer(b1 << 24 | b2 << 16 | b3 << 8 | b4);
+ return Integer.valueOf(b1 << 24 | b2 << 16 | b3 << 8 | b4);
} else if (b0 == 30) {
-
+
// Real number
- StringBuilder fString = new StringBuilder();
+ final StringBuilder fString = new StringBuilder();
int nibble1 = 0;
int nibble2 = 0;
++_index;
@@ -142,14 +142,14 @@ public class CffTable implements Table {
++_index;
fString.append(decodeRealNibble(nibble1));
fString.append(decodeRealNibble(nibble2));
- }
- return new Float(fString.toString());
+ }
+ return Float.valueOf(fString.toString());
} else {
return null;
}
}
-
- private String decodeRealNibble(int nibble) {
+
+ private String decodeRealNibble(final int nibble) {
if (nibble < 0xa) {
return Integer.toString(nibble);
} else if (nibble == 0xa) {
@@ -163,12 +163,13 @@ public class CffTable implements Table {
}
return "";
}
-
+
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
- Enumeration<Integer> keys = _entries.keys();
+ final StringBuilder sb = new StringBuilder();
+ final Enumeration<Integer> keys = _entries.keys();
while (keys.hasMoreElements()) {
- Integer key = keys.nextElement();
+ final Integer key = keys.nextElement();
if ((key.intValue() & 0xc00) == 0xc00) {
sb.append("12 ").append(key.intValue() & 0xff).append(": ");
} else {
@@ -179,15 +180,15 @@ public class CffTable implements Table {
return sb.toString();
}
}
-
+
public class Index {
-
- private int _count;
- private int _offSize;
- private int[] _offset;
- private int[] _data;
-
- protected Index(DataInput di) throws IOException {
+
+ private final int _count;
+ private final int _offSize;
+ private final int[] _offset;
+ private final int[] _data;
+
+ protected Index(final DataInput di) throws IOException {
_count = di.readUnsignedShort();
_offset = new int[_count + 1];
_offSize = di.readUnsignedByte();
@@ -203,25 +204,26 @@ public class CffTable implements Table {
_data[i] = di.readUnsignedByte();
}
}
-
+
public int getCount() {
return _count;
}
-
- public int getOffset(int index) {
+
+ public int getOffset(final int index) {
return _offset[index];
}
-
+
public int getDataLength() {
return _offset[_offset.length - 1] - 1;
}
-
+
public int[] getData() {
return _data;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("DICT\n");
sb.append("count: ").append(_count).append("\n");
sb.append("offSize: ").append(_offSize).append("\n");
@@ -241,42 +243,43 @@ public class CffTable implements Table {
return sb.toString();
}
}
-
+
public class TopDictIndex extends Index {
- protected TopDictIndex(DataInput di) throws IOException {
+ protected TopDictIndex(final DataInput di) throws IOException {
super(di);
}
-
- public Dict getTopDict(int index) {
- int offset = getOffset(index) - 1;
- int len = getOffset(index + 1) - offset - 1;
+
+ public Dict getTopDict(final int index) {
+ final int offset = getOffset(index) - 1;
+ final int len = getOffset(index + 1) - offset - 1;
return new Dict(getData(), offset, len);
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
for (int i = 0; i < getCount(); ++i) {
sb.append(getTopDict(i).toString()).append("\n");
}
return sb.toString();
}
}
-
+
public class NameIndex extends Index {
- protected NameIndex(DataInput di) throws IOException {
+ protected NameIndex(final DataInput di) throws IOException {
super(di);
}
-
- public String getName(int index) {
+
+ public String getName(final int index) {
String name = null;
- int offset = getOffset(index) - 1;
- int len = getOffset(index + 1) - offset - 1;
+ final int offset = getOffset(index) - 1;
+ final int len = getOffset(index + 1) - offset - 1;
// Ensure the name hasn't been deleted
if (getData()[offset] != 0) {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
for (int i = offset; i < offset + len; ++i) {
sb.append((char) getData()[i]);
}
@@ -286,9 +289,10 @@ public class CffTable implements Table {
}
return name;
}
-
+
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
for (int i = 0; i < getCount(); ++i) {
sb.append(getName(i)).append("\n");
}
@@ -298,10 +302,10 @@ public class CffTable implements Table {
public class StringIndex extends Index {
- protected StringIndex(DataInput di) throws IOException {
+ protected StringIndex(final DataInput di) throws IOException {
super(di);
}
-
+
public String getString(int index) {
if (index < CffStandardStrings.standardStrings.length) {
return CffStandardStrings.standardStrings[index];
@@ -310,20 +314,21 @@ public class CffTable implements Table {
if (index >= getCount()) {
return null;
}
- int offset = getOffset(index) - 1;
- int len = getOffset(index + 1) - offset - 1;
+ final int offset = getOffset(index) - 1;
+ final int len = getOffset(index + 1) - offset - 1;
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
for (int i = offset; i < offset + len; ++i) {
sb.append((char) getData()[i]);
}
return sb.toString();
}
}
-
+
+ @Override
public String toString() {
- int nonStandardBase = CffStandardStrings.standardStrings.length;
- StringBuilder sb = new StringBuilder();
+ final int nonStandardBase = CffStandardStrings.standardStrings.length;
+ final StringBuilder sb = new StringBuilder();
for (int i = 0; i < getCount(); ++i) {
sb.append(nonStandardBase + i).append(": ");
sb.append(getString(nonStandardBase + i)).append("\n");
@@ -331,103 +336,107 @@ public class CffTable implements Table {
return sb.toString();
}
}
-
+
private class CharsetRange {
-
+
private int _first;
private int _left;
-
+
public int getFirst() {
return _first;
}
- protected void setFirst(int first) {
+ protected void setFirst(final int first) {
_first = first;
}
-
+
public int getLeft() {
return _left;
}
- protected void setLeft(int left) {
+ protected void setLeft(final int left) {
_left = left;
}
}
private class CharsetRange1 extends CharsetRange {
-
- protected CharsetRange1(DataInput di) throws IOException {
+
+ protected CharsetRange1(final DataInput di) throws IOException {
setFirst(di.readUnsignedShort());
setLeft(di.readUnsignedByte());
}
}
-
+
private class CharsetRange2 extends CharsetRange {
-
- protected CharsetRange2(DataInput di) throws IOException {
+
+ protected CharsetRange2(final DataInput di) throws IOException {
setFirst(di.readUnsignedShort());
setLeft(di.readUnsignedShort());
}
}
-
+
private abstract class Charset {
-
+
public abstract int getFormat();
-
+
public abstract int getSID(int gid);
}
-
+
private class CharsetFormat0 extends Charset {
-
- private int[] _glyph;
-
- protected CharsetFormat0(DataInput di, int glyphCount) throws IOException {
+
+ private final int[] _glyph;
+
+ protected CharsetFormat0(final DataInput di, final int glyphCount) throws IOException {
_glyph = new int[glyphCount - 1]; // minus 1 because .notdef is omitted
for (int i = 0; i < glyphCount - 1; ++i) {
_glyph[i] = di.readUnsignedShort();
}
}
-
+
+ @Override
public int getFormat() {
return 0;
}
- public int getSID(int gid) {
+ @Override
+ public int getSID(final int gid) {
if (gid == 0) {
return 0;
}
return _glyph[gid - 1];
}
}
-
+
private class CharsetFormat1 extends Charset {
-
- private ArrayList<CharsetRange> _charsetRanges = new ArrayList<CharsetRange>();
-
- protected CharsetFormat1(DataInput di, int glyphCount) throws IOException {
+
+ private final ArrayList<CharsetRange> _charsetRanges = new ArrayList<CharsetRange>();
+
+ protected CharsetFormat1(final DataInput di, final int glyphCount) throws IOException {
int glyphsCovered = glyphCount - 1; // minus 1 because .notdef is omitted
while (glyphsCovered > 0) {
- CharsetRange range = new CharsetRange1(di);
+ final CharsetRange range = new CharsetRange1(di);
_charsetRanges.add(range);
glyphsCovered -= range.getLeft() + 1;
}
}
+ @Override
public int getFormat() {
return 1;
}
- public int getSID(int gid) {
+ @Override
+ public int getSID(final int gid) {
if (gid == 0) {
return 0;
}
-
+
// Count through the ranges to find the one of interest
int count = 0;
- for (CharsetRange range : _charsetRanges) {
+ for (final CharsetRange range : _charsetRanges) {
count += range.getLeft();
if (gid < count) {
- int sid = gid - count + range.getFirst();
+ final int sid = gid - count + range.getFirst();
return sid;
}
}
@@ -436,32 +445,34 @@ public class CffTable implements Table {
}
private class CharsetFormat2 extends Charset {
-
- private ArrayList<CharsetRange> _charsetRanges = new ArrayList<CharsetRange>();
-
- protected CharsetFormat2(DataInput di, int glyphCount) throws IOException {
+
+ private final ArrayList<CharsetRange> _charsetRanges = new ArrayList<CharsetRange>();
+
+ protected CharsetFormat2(final DataInput di, final int glyphCount) throws IOException {
int glyphsCovered = glyphCount - 1; // minus 1 because .notdef is omitted
while (glyphsCovered > 0) {
- CharsetRange range = new CharsetRange2(di);
+ final CharsetRange range = new CharsetRange2(di);
_charsetRanges.add(range);
glyphsCovered -= range.getLeft() + 1;
}
}
+ @Override
public int getFormat() {
return 2;
}
- public int getSID(int gid) {
+ @Override
+ public int getSID(final int gid) {
if (gid == 0) {
return 0;
}
-
+
// Count through the ranges to find the one of interest
int count = 0;
- for (CharsetRange range : _charsetRanges) {
+ for (final CharsetRange range : _charsetRanges) {
if (gid < range.getLeft() + count) {
- int sid = gid - count + range.getFirst() - 1;
+ final int sid = gid - count + range.getFirst() - 1;
return sid;
}
count += range.getLeft();
@@ -469,24 +480,24 @@ public class CffTable implements Table {
return 0;
}
}
-
- private DirectoryEntry _de;
- private int _major;
- private int _minor;
- private int _hdrSize;
- private int _offSize;
- private NameIndex _nameIndex;
- private TopDictIndex _topDictIndex;
- private StringIndex _stringIndex;
- private Index _globalSubrIndex;
- private Index _charStringsIndexArray[];
- private Charset[] _charsets;
- private Charstring[][] _charstringsArray;
-
- private byte[] _buf;
+
+ private final DirectoryEntry _de;
+ private final int _major;
+ private final int _minor;
+ private final int _hdrSize;
+ private final int _offSize;
+ private final NameIndex _nameIndex;
+ private final TopDictIndex _topDictIndex;
+ private final StringIndex _stringIndex;
+ private final Index _globalSubrIndex;
+ private final Index _charStringsIndexArray[];
+ private final Charset[] _charsets;
+ private final Charstring[][] _charstringsArray;
+
+ private final byte[] _buf;
/** Creates a new instance of CffTable */
- protected CffTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected CffTable(final DirectoryEntry de, final DataInput di) throws IOException {
_de = (DirectoryEntry) de.clone();
// Load entire table into a buffer, and create another input stream
@@ -499,24 +510,24 @@ public class CffTable implements Table {
_minor = di2.readUnsignedByte();
_hdrSize = di2.readUnsignedByte();
_offSize = di2.readUnsignedByte();
-
+
// Name INDEX
di2 = getDataInputForOffset(_hdrSize);
_nameIndex = new NameIndex(di2);
-
+
// Top DICT INDEX
_topDictIndex = new TopDictIndex(di2);
// String INDEX
_stringIndex = new StringIndex(di2);
-
+
// Global Subr INDEX
_globalSubrIndex = new Index(di2);
-
+
// Encodings go here -- but since this is an OpenType font will this
// not always be a CIDFont? In which case there are no encodings
// within the CFF data.
-
+
// Load each of the fonts
_charStringsIndexArray = new Index[_topDictIndex.getCount()];
_charsets = new Charset[_topDictIndex.getCount()];
@@ -526,15 +537,15 @@ public class CffTable implements Table {
// Charstrings INDEX
// We load this before Charsets because we may need to know the number
// of glyphs
- Integer charStringsOffset = (Integer) _topDictIndex.getTopDict(i).getValue(17);
+ final Integer charStringsOffset = (Integer) _topDictIndex.getTopDict(i).getValue(17);
di2 = getDataInputForOffset(charStringsOffset);
_charStringsIndexArray[i] = new Index(di2);
- int glyphCount = _charStringsIndexArray[i].getCount();
-
+ final int glyphCount = _charStringsIndexArray[i].getCount();
+
// Charsets
- Integer charsetOffset = (Integer) _topDictIndex.getTopDict(i).getValue(15);
+ final Integer charsetOffset = (Integer) _topDictIndex.getTopDict(i).getValue(15);
di2 = getDataInputForOffset(charsetOffset);
- int format = di2.readUnsignedByte();
+ final int format = di2.readUnsignedByte();
switch (format) {
case 0:
_charsets[i] = new CharsetFormat0(di2, glyphCount);
@@ -550,8 +561,8 @@ public class CffTable implements Table {
// Create the charstrings
_charstringsArray[i] = new Charstring[glyphCount];
for (int j = 0; j < glyphCount; ++j) {
- int offset = _charStringsIndexArray[i].getOffset(j) - 1;
- int len = _charStringsIndexArray[i].getOffset(j + 1) - offset - 1;
+ final int offset = _charStringsIndexArray[i].getOffset(j) - 1;
+ final int len = _charStringsIndexArray[i].getOffset(j + 1) - offset - 1;
_charstringsArray[i][j] = new CharstringType2(
i,
_stringIndex.getString(_charsets[i].getSID(j)),
@@ -563,8 +574,8 @@ public class CffTable implements Table {
}
}
}
-
- private DataInput getDataInputForOffset(int offset) {
+
+ private DataInput getDataInputForOffset(final int offset) {
return new DataInputStream(new ByteArrayInputStream(
_buf, offset,
_de.getLength() - offset));
@@ -573,25 +584,27 @@ public class CffTable implements Table {
public NameIndex getNameIndex() {
return _nameIndex;
}
-
- public Charset getCharset(int fontIndex) {
+
+ public Charset getCharset(final int fontIndex) {
return _charsets[fontIndex];
}
- public Charstring getCharstring(int fontIndex, int gid) {
+ public Charstring getCharstring(final int fontIndex, final int gid) {
return _charstringsArray[fontIndex][gid];
}
-
- public int getCharstringCount(int fontIndex) {
+
+ public int getCharstringCount(final int fontIndex) {
return _charstringsArray[fontIndex].length;
}
+ @Override
public int getType() {
return CFF;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'CFF' Table - Compact Font Format\n---------------------------------\n");
sb.append("\nName INDEX\n");
sb.append(_nameIndex.toString());
@@ -607,13 +620,14 @@ public class CffTable implements Table {
}
return sb.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Charstring.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Charstring.java
index d411d1e00..01e2d4934 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Charstring.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Charstring.java
@@ -28,6 +28,6 @@ package jogamp.graph.font.typecast.ot.table;
public abstract class Charstring {
public abstract int getIndex();
-
+
public abstract String getName();
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CharstringType2.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CharstringType2.java
index 9c40a0e5e..d96a5848b 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CharstringType2.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CharstringType2.java
@@ -28,7 +28,7 @@ import jogamp.graph.font.typecast.ot.table.CffTable;
* @author <a href="mailto:[email protected]">David Schweinsberg</a>
*/
public class CharstringType2 extends Charstring {
-
+
private static final String[] _oneByteOperators = {
"-Reserved-",
"hstem",
@@ -105,25 +105,25 @@ public class CharstringType2 extends Charstring {
"flex1",
"-Reserved-"
};
-
- private int _index;
- private String _name;
- private int[] _data;
- private int _offset;
- private int _length;
- private CffTable.Index _localSubrIndex;
- private CffTable.Index _globalSubrIndex;
+
+ private final int _index;
+ private final String _name;
+ private final int[] _data;
+ private final int _offset;
+ private final int _length;
+ private final CffTable.Index _localSubrIndex;
+ private final CffTable.Index _globalSubrIndex;
private int _ip;
/** Creates a new instance of CharstringType2 */
protected CharstringType2(
- int index,
- String name,
- int[] data,
- int offset,
- int length,
- CffTable.Index localSubrIndex,
- CffTable.Index globalSubrIndex) {
+ final int index,
+ final String name,
+ final int[] data,
+ final int offset,
+ final int length,
+ final CffTable.Index localSubrIndex,
+ final CffTable.Index globalSubrIndex) {
_index = index;
_name = name;
_data = data;
@@ -132,16 +132,18 @@ public class CharstringType2 extends Charstring {
_localSubrIndex = localSubrIndex;
_globalSubrIndex = globalSubrIndex;
}
-
+
+ @Override
public int getIndex() {
return _index;
}
+ @Override
public String getName() {
return _name;
}
-
- private void disassemble(StringBuilder sb) {
+
+ private void disassemble(final StringBuilder sb) {
Number operand = null;
while (isOperandAtIndex()) {
operand = nextOperand();
@@ -151,7 +153,7 @@ public class CharstringType2 extends Charstring {
String mnemonic;
if (operator == 12) {
operator = nextByte();
-
+
// Check we're not exceeding the upper limit of our mnemonics
if (operator > 38) {
operator = 38;
@@ -162,13 +164,13 @@ public class CharstringType2 extends Charstring {
}
sb.append(mnemonic);
}
-
+
public void resetIP() {
_ip = _offset;
}
public boolean isOperandAtIndex() {
- int b0 = _data[_ip];
+ final int b0 = _data[_ip];
if ((32 <= b0 && b0 <= 255) || b0 == 28) {
return true;
}
@@ -176,55 +178,56 @@ public class CharstringType2 extends Charstring {
}
public Number nextOperand() {
- int b0 = _data[_ip];
+ final int b0 = _data[_ip];
if (32 <= b0 && b0 <= 246) {
// 1 byte integer
++_ip;
- return new Integer(b0 - 139);
+ return Integer.valueOf(b0 - 139);
} else if (247 <= b0 && b0 <= 250) {
// 2 byte integer
- int b1 = _data[_ip + 1];
+ final int b1 = _data[_ip + 1];
_ip += 2;
- return new Integer((b0 - 247) * 256 + b1 + 108);
+ return Integer.valueOf((b0 - 247) * 256 + b1 + 108);
} else if (251 <= b0 && b0 <= 254) {
// 2 byte integer
- int b1 = _data[_ip + 1];
+ final int b1 = _data[_ip + 1];
_ip += 2;
- return new Integer(-(b0 - 251) * 256 - b1 - 108);
+ return Integer.valueOf(-(b0 - 251) * 256 - b1 - 108);
} else if (b0 == 28) {
// 3 byte integer
- int b1 = _data[_ip + 1];
- int b2 = _data[_ip + 2];
+ final int b1 = _data[_ip + 1];
+ final int b2 = _data[_ip + 2];
_ip += 3;
- return new Integer(b1 << 8 | b2);
+ return Integer.valueOf(b1 << 8 | b2);
} else if (b0 == 255) {
// 16-bit signed integer with 16 bits of fraction
- int b1 = (byte) _data[_ip + 1];
- int b2 = _data[_ip + 2];
- int b3 = _data[_ip + 3];
- int b4 = _data[_ip + 4];
+ final int b1 = (byte) _data[_ip + 1];
+ final int b2 = _data[_ip + 2];
+ final int b3 = _data[_ip + 3];
+ final int b4 = _data[_ip + 4];
_ip += 5;
- return new Float((b1 << 8 | b2) + ((b3 << 8 | b4) / 65536.0));
+ return Float.valueOf((b1 << 8 | b2) + ((b3 << 8 | b4) / 65536f));
} else {
return null;
}
}
-
+
public int nextByte() {
return _data[_ip++];
}
-
+
public boolean moreBytes() {
return _ip < _offset + _length;
}
-
+
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
resetIP();
while (moreBytes()) {
disassemble(sb);
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDef.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDef.java
index 4c2f3decb..a65bcd525 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDef.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDef.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -20,9 +20,9 @@ public abstract class ClassDef {
public abstract int getFormat();
- protected static ClassDef read(RandomAccessFile raf) throws IOException {
+ protected static ClassDef read(final RandomAccessFile raf) throws IOException {
ClassDef c = null;
- int format = raf.readUnsignedShort();
+ final int format = raf.readUnsignedShort();
if (format == 1) {
c = new ClassDefFormat1(raf);
} else if (format == 2) {
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDefFormat1.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDefFormat1.java
index 0c99ad66a..cbc05393f 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDefFormat1.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDefFormat1.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,12 +18,12 @@ import java.io.RandomAccessFile;
*/
public class ClassDefFormat1 extends ClassDef {
- private int startGlyph;
- private int glyphCount;
- private int[] classValues;
+ private final int startGlyph;
+ private final int glyphCount;
+ private final int[] classValues;
/** Creates new ClassDefFormat1 */
- public ClassDefFormat1(RandomAccessFile raf) throws IOException {
+ public ClassDefFormat1(final RandomAccessFile raf) throws IOException {
startGlyph = raf.readUnsignedShort();
glyphCount = raf.readUnsignedShort();
classValues = new int[glyphCount];
@@ -32,6 +32,7 @@ public class ClassDefFormat1 extends ClassDef {
}
}
+ @Override
public int getFormat() {
return 1;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDefFormat2.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDefFormat2.java
index 5b7c4d655..99283f026 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDefFormat2.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ClassDefFormat2.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,11 +18,11 @@ import java.io.RandomAccessFile;
*/
public class ClassDefFormat2 extends ClassDef {
- private int classRangeCount;
- private RangeRecord[] classRangeRecords;
+ private final int classRangeCount;
+ private final RangeRecord[] classRangeRecords;
/** Creates new ClassDefFormat2 */
- public ClassDefFormat2(RandomAccessFile raf) throws IOException {
+ public ClassDefFormat2(final RandomAccessFile raf) throws IOException {
classRangeCount = raf.readUnsignedShort();
classRangeRecords = new RangeRecord[classRangeCount];
for (int i = 0; i < classRangeCount; i++) {
@@ -30,6 +30,7 @@ public class ClassDefFormat2 extends ClassDef {
}
}
+ @Override
public int getFormat() {
return 2;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat.java
index 7ce531cd9..602897382 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat.java
@@ -58,21 +58,21 @@ import java.io.IOException;
* @author <a href="mailto:[email protected]">David Schweinsberg</a>
*/
public abstract class CmapFormat {
-
- public class Range {
-
- private int _startCode;
- private int _endCode;
-
- protected Range(int startCode, int endCode) {
+
+ public static class Range {
+
+ private final int _startCode;
+ private final int _endCode;
+
+ protected Range(final int startCode, final int endCode) {
_startCode = startCode;
_endCode = endCode;
}
-
+
public int getStartCode() {
return _startCode;
}
-
+
public int getEndCode() {
return _endCode;
}
@@ -82,12 +82,12 @@ public abstract class CmapFormat {
protected int _length;
protected int _language;
- protected CmapFormat(DataInput di) throws IOException {
+ protected CmapFormat(final DataInput di) throws IOException {
_length = di.readUnsignedShort();
_language = di.readUnsignedShort();
}
- protected static CmapFormat create(int format, DataInput di)
+ protected static CmapFormat create(final int format, final DataInput di)
throws IOException {
switch(format) {
case 0:
@@ -116,12 +116,13 @@ public abstract class CmapFormat {
}
public abstract int getRangeCount();
-
+
public abstract Range getRange(int index)
throws ArrayIndexOutOfBoundsException;
public abstract int mapCharCode(int charCode);
-
+
+ @Override
public String toString() {
return new StringBuilder()
.append("format: ")
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat0.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat0.java
index e374f82d2..505e8c942 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat0.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat0.java
@@ -61,9 +61,9 @@ import java.io.IOException;
*/
public class CmapFormat0 extends CmapFormat {
- private int[] _glyphIdArray = new int[256];
+ private final int[] _glyphIdArray = new int[256];
- protected CmapFormat0(DataInput di) throws IOException {
+ protected CmapFormat0(final DataInput di) throws IOException {
super(di);
_format = 0;
for (int i = 0; i < 256; i++) {
@@ -71,18 +71,21 @@ public class CmapFormat0 extends CmapFormat {
}
}
+ @Override
public int getRangeCount() {
return 1;
}
-
- public Range getRange(int index) throws ArrayIndexOutOfBoundsException {
+
+ @Override
+ public Range getRange(final int index) throws ArrayIndexOutOfBoundsException {
if (index != 0) {
throw new ArrayIndexOutOfBoundsException();
}
return new Range(0, 255);
}
- public int mapCharCode(int charCode) {
+ @Override
+ public int mapCharCode(final int charCode) {
if (0 <= charCode && charCode < 256) {
return _glyphIdArray[charCode];
} else {
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat2.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat2.java
index 319d8c0d0..743fc93c1 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat2.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat2.java
@@ -60,24 +60,24 @@ import java.io.IOException;
*/
public class CmapFormat2 extends CmapFormat {
- private class SubHeader {
+ static class SubHeader {
int _firstCode;
int _entryCount;
short _idDelta;
int _idRangeOffset;
int _arrayIndex;
}
-
- private int[] _subHeaderKeys = new int[256];
- private SubHeader[] _subHeaders;
- private int[] _glyphIndexArray;
- protected CmapFormat2(DataInput di) throws IOException {
+ private final int[] _subHeaderKeys = new int[256];
+ private final SubHeader[] _subHeaders;
+ private final int[] _glyphIndexArray;
+
+ protected CmapFormat2(final DataInput di) throws IOException {
super(di);
_format = 2;
-
+
int pos = 6;
-
+
// Read the subheader keys, noting the highest value, as this will
// determine the number of subheaders to read.
int highest = 0;
@@ -86,31 +86,31 @@ public class CmapFormat2 extends CmapFormat {
highest = Math.max(highest, _subHeaderKeys[i]);
pos += 2;
}
- int subHeaderCount = highest / 8 + 1;
+ final int subHeaderCount = highest / 8 + 1;
_subHeaders = new SubHeader[subHeaderCount];
-
+
// Read the subheaders, once again noting the highest glyphIndexArray
// index range.
- int indexArrayOffset = 8 * subHeaderCount + 518;
+ final int indexArrayOffset = 8 * subHeaderCount + 518;
highest = 0;
for (int i = 0; i < _subHeaders.length; ++i) {
- SubHeader sh = new SubHeader();
+ final SubHeader sh = new SubHeader();
sh._firstCode = di.readUnsignedShort();
sh._entryCount = di.readUnsignedShort();
sh._idDelta = di.readShort();
sh._idRangeOffset = di.readUnsignedShort();
-
+
// Calculate the offset into the _glyphIndexArray
pos += 8;
sh._arrayIndex =
(pos - 2 + sh._idRangeOffset - indexArrayOffset) / 2;
-
+
// What is the highest range within the glyphIndexArray?
highest = Math.max(highest, sh._arrayIndex + sh._entryCount);
-
+
_subHeaders[i] = sh;
}
-
+
// Read the glyphIndexArray
_glyphIndexArray = new int[highest];
for (int i = 0; i < _glyphIndexArray.length; ++i) {
@@ -118,15 +118,17 @@ public class CmapFormat2 extends CmapFormat {
}
}
+ @Override
public int getRangeCount() {
return _subHeaders.length;
}
-
- public Range getRange(int index) throws ArrayIndexOutOfBoundsException {
+
+ @Override
+ public Range getRange(final int index) throws ArrayIndexOutOfBoundsException {
if (index < 0 || index >= _subHeaders.length) {
throw new ArrayIndexOutOfBoundsException();
}
-
+
// Find the high-byte (if any)
int highByte = 0;
if (index != 0) {
@@ -137,30 +139,31 @@ public class CmapFormat2 extends CmapFormat {
}
}
}
-
+
return new Range(
highByte | _subHeaders[index]._firstCode,
highByte | (_subHeaders[index]._firstCode +
_subHeaders[index]._entryCount - 1));
}
- public int mapCharCode(int charCode) {
-
+ @Override
+ public int mapCharCode(final int charCode) {
+
// Get the appropriate subheader
int index = 0;
- int highByte = charCode >> 8;
+ final int highByte = charCode >> 8;
if (highByte != 0) {
index = _subHeaderKeys[highByte] / 8;
}
- SubHeader sh = _subHeaders[index];
-
+ final SubHeader sh = _subHeaders[index];
+
// Is the charCode out-of-range?
- int lowByte = charCode & 0xff;
+ final int lowByte = charCode & 0xff;
if (lowByte < sh._firstCode ||
lowByte >= (sh._firstCode + sh._entryCount)) {
return 0;
}
-
+
// Now calculate the glyph index
int glyphIndex =
_glyphIndexArray[sh._arrayIndex + (lowByte - sh._firstCode)];
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat4.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat4.java
index c09bdc8c3..c8be6c7fb 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat4.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat4.java
@@ -59,18 +59,18 @@ import java.io.IOException;
*/
public class CmapFormat4 extends CmapFormat {
- private int _segCountX2;
- private int _searchRange;
- private int _entrySelector;
- private int _rangeShift;
- private int[] _endCode;
- private int[] _startCode;
- private int[] _idDelta;
- private int[] _idRangeOffset;
- private int[] _glyphIdArray;
- private int _segCount;
-
- protected CmapFormat4(DataInput di) throws IOException {
+ private final int _segCountX2;
+ private final int _searchRange;
+ private final int _entrySelector;
+ private final int _rangeShift;
+ private final int[] _endCode;
+ private final int[] _startCode;
+ private final int[] _idDelta;
+ private final int[] _idRangeOffset;
+ private final int[] _glyphIdArray;
+ private final int _segCount;
+
+ protected CmapFormat4(final DataInput di) throws IOException {
super(di); // 6
_format = 4;
_segCountX2 = di.readUnsignedShort(); // +2 (8)
@@ -97,12 +97,12 @@ public class CmapFormat4 extends CmapFormat {
} // + 2*segCount (8*segCount + 16)
// Whatever remains of this header belongs in glyphIdArray
- int count = (_length - (8*_segCount + 16)) / 2;
+ final int count = (_length - (8*_segCount + 16)) / 2;
_glyphIdArray = new int[count];
for (int i = 0; i < count; i++) {
_glyphIdArray[i] = di.readUnsignedShort();
} // + 2*count (8*segCount + 2*count + 18)
-
+
// Are there any padding bytes we need to consume?
// int leftover = length - (8*segCount + 2*count + 18);
// if (leftover > 0) {
@@ -110,18 +110,21 @@ public class CmapFormat4 extends CmapFormat {
// }
}
+ @Override
public int getRangeCount() {
return _segCount;
}
-
- public Range getRange(int index) throws ArrayIndexOutOfBoundsException {
+
+ @Override
+ public Range getRange(final int index) throws ArrayIndexOutOfBoundsException {
if (index < 0 || index >= _segCount) {
throw new ArrayIndexOutOfBoundsException();
}
return new Range(_startCode[index], _endCode[index]);
}
- public int mapCharCode(int charCode) {
+ @Override
+ public int mapCharCode(final int charCode) {
try {
for (int i = 0; i < _segCount; i++) {
if (_endCode[i] >= charCode) {
@@ -136,12 +139,13 @@ public class CmapFormat4 extends CmapFormat {
}
}
}
- } catch (ArrayIndexOutOfBoundsException e) {
+ } catch (final ArrayIndexOutOfBoundsException e) {
System.err.println("error: Array out of bounds - " + e.getMessage());
}
return 0;
}
+ @Override
public String toString() {
return new StringBuilder()
.append(super.toString())
@@ -153,13 +157,13 @@ public class CmapFormat4 extends CmapFormat {
.append(_entrySelector)
.append(", rangeShift: ")
.append(_rangeShift)
- .append(", endCode: ")
- .append(_endCode)
- .append(", startCode: ")
- .append(_endCode)
- .append(", idDelta: ")
- .append(_idDelta)
- .append(", idRangeOffset: ")
- .append(_idRangeOffset).toString();
+ .append(", endCodeLen: ")
+ .append(_endCode.length)
+ .append(", startCodeLen: ")
+ .append(_endCode.length)
+ .append(", idDeltaLen: ")
+ .append(_idDelta.length)
+ .append(", idRangeOffsetLen: ")
+ .append(_idRangeOffset.length).toString();
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat6.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat6.java
index a58531d11..eff3d2fb1 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat6.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormat6.java
@@ -64,24 +64,27 @@ public class CmapFormat6 extends CmapFormat {
private short _entryCount;
private short[] _glyphIdArray;
- protected CmapFormat6(DataInput di) throws IOException {
+ protected CmapFormat6(final DataInput di) throws IOException {
super(di);
_format = 6;
-
+
// HACK: As this is not yet implemented, we need to skip over the bytes
// we should be consuming
//di.skipBytes(_length - 4);
}
+ @Override
public int getRangeCount() {
return 0;
}
-
- public Range getRange(int index) throws ArrayIndexOutOfBoundsException {
+
+ @Override
+ public Range getRange(final int index) throws ArrayIndexOutOfBoundsException {
throw new ArrayIndexOutOfBoundsException();
}
- public int mapCharCode(int charCode) {
+ @Override
+ public int mapCharCode(final int charCode) {
return 0;
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormatUnknown.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormatUnknown.java
index 83366b593..e9aa1d4e0 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormatUnknown.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapFormatUnknown.java
@@ -30,25 +30,28 @@ import java.io.IOException;
* @version $Id: CmapFormatUnknown.java,v 1.1 2004-12-21 10:21:23 davidsch Exp $
*/
public class CmapFormatUnknown extends CmapFormat {
-
+
/** Creates a new instance of CmapFormatUnknown */
- protected CmapFormatUnknown(int format, DataInput di) throws IOException {
+ protected CmapFormatUnknown(final int format, final DataInput di) throws IOException {
super(di);
_format = format;
-
+
// We don't know how to handle this data, so we'll just skip over it
di.skipBytes(_length - 4);
}
+ @Override
public int getRangeCount() {
return 0;
}
-
- public Range getRange(int index) throws ArrayIndexOutOfBoundsException {
+
+ @Override
+ public Range getRange(final int index) throws ArrayIndexOutOfBoundsException {
throw new ArrayIndexOutOfBoundsException();
}
- public int mapCharCode(int charCode) {
+ @Override
+ public int mapCharCode(final int charCode) {
return 0;
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapIndexEntry.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapIndexEntry.java
index 85fdf7225..1f2c80286 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapIndexEntry.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapIndexEntry.java
@@ -59,12 +59,12 @@ import java.io.IOException;
*/
public class CmapIndexEntry implements Comparable {
- private int _platformId;
- private int _encodingId;
- private int _offset;
+ private final int _platformId;
+ private final int _encodingId;
+ private final int _offset;
private CmapFormat _format;
- protected CmapIndexEntry(DataInput di) throws IOException {
+ protected CmapIndexEntry(final DataInput di) throws IOException {
_platformId = di.readUnsignedShort();
_encodingId = di.readUnsignedShort();
_offset = di.readInt();
@@ -85,11 +85,12 @@ public class CmapIndexEntry implements Comparable {
public CmapFormat getFormat() {
return _format;
}
-
- public void setFormat(CmapFormat format) {
+
+ public void setFormat(final CmapFormat format) {
_format = format;
}
+ @Override
public String toString() {
return new StringBuilder()
.append("platform id: ")
@@ -104,8 +105,9 @@ public class CmapIndexEntry implements Comparable {
.append(_offset).toString();
}
- public int compareTo(java.lang.Object obj) {
- CmapIndexEntry entry = (CmapIndexEntry) obj;
+ @Override
+ public int compareTo(final java.lang.Object obj) {
+ final CmapIndexEntry entry = (CmapIndexEntry) obj;
if (getOffset() < entry.getOffset()) {
return -1;
} else if (getOffset() > entry.getOffset()) {
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapTable.java
index 0050fdd8e..4623eb5cf 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CmapTable.java
@@ -61,12 +61,12 @@ import java.util.Arrays;
*/
public class CmapTable implements Table {
- private DirectoryEntry _de;
- private int _version;
- private int _numTables;
- private CmapIndexEntry[] _entries;
+ private final DirectoryEntry _de;
+ private final int _version;
+ private final int _numTables;
+ private final CmapIndexEntry[] _entries;
- protected CmapTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected CmapTable(final DirectoryEntry de, final DataInput di) throws IOException {
_de = (DirectoryEntry) de.clone();
_version = di.readUnsignedShort();
_numTables = di.readUnsignedShort();
@@ -94,11 +94,11 @@ public class CmapTable implements Table {
} else if (_entries[i].getOffset() > bytesRead) {
di.skipBytes(_entries[i].getOffset() - (int) bytesRead);
} else if (_entries[i].getOffset() != bytesRead) {
-
+
// Something is amiss
throw new IOException();
}
- int formatType = di.readUnsignedShort();
+ final int formatType = di.readUnsignedShort();
lastFormat = CmapFormat.create(formatType, di);
lastOffset = _entries[i].getOffset();
_entries[i].setFormat(lastFormat);
@@ -109,16 +109,16 @@ public class CmapTable implements Table {
public int getVersion() {
return _version;
}
-
+
public int getNumTables() {
return _numTables;
}
-
- public CmapIndexEntry getCmapIndexEntry(int i) {
+
+ public CmapIndexEntry getCmapIndexEntry(final int i) {
return _entries[i];
}
-
- public CmapFormat getCmapFormat(short platformId, short encodingId) {
+
+ public CmapFormat getCmapFormat(final short platformId, final short encodingId) {
// Find the requested format
for (int i = 0; i < _numTables; i++) {
@@ -130,12 +130,14 @@ public class CmapTable implements Table {
return null;
}
+ @Override
public int getType() {
return cmap;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder().append("cmap\n");
+ final StringBuilder sb = new StringBuilder().append("cmap\n");
// Get each of the index entries
for (int i = 0; i < _numTables; i++) {
@@ -148,13 +150,14 @@ public class CmapTable implements Table {
// }
return sb.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Coverage.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Coverage.java
index e85fadb5e..a6f994f95 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Coverage.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Coverage.java
@@ -68,10 +68,10 @@ public abstract class Coverage {
* can't be found.
*/
public abstract int findGlyph(int glyphId);
-
- protected static Coverage read(DataInput di) throws IOException {
+
+ protected static Coverage read(final DataInput di) throws IOException {
Coverage c = null;
- int format = di.readUnsignedShort();
+ final int format = di.readUnsignedShort();
if (format == 1) {
c = new CoverageFormat1(di);
} else if (format == 2) {
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CoverageFormat1.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CoverageFormat1.java
index 712da54df..3deb60202 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CoverageFormat1.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CoverageFormat1.java
@@ -60,11 +60,11 @@ import java.io.IOException;
*/
public class CoverageFormat1 extends Coverage {
- private int _glyphCount;
- private int[] _glyphIds;
+ private final int _glyphCount;
+ private final int[] _glyphIds;
/** Creates new CoverageFormat1 */
- protected CoverageFormat1(DataInput di) throws IOException {
+ protected CoverageFormat1(final DataInput di) throws IOException {
_glyphCount = di.readUnsignedShort();
_glyphIds = new int[_glyphCount];
for (int i = 0; i < _glyphCount; i++) {
@@ -72,11 +72,13 @@ public class CoverageFormat1 extends Coverage {
}
}
+ @Override
public int getFormat() {
return 1;
}
- public int findGlyph(int glyphId) {
+ @Override
+ public int findGlyph(final int glyphId) {
for (int i = 0; i < _glyphCount; i++) {
if (_glyphIds[i] == glyphId) {
return i;
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CoverageFormat2.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CoverageFormat2.java
index 7196ed595..9397f376d 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CoverageFormat2.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CoverageFormat2.java
@@ -60,11 +60,11 @@ import java.io.IOException;
*/
public class CoverageFormat2 extends Coverage {
- private int _rangeCount;
- private RangeRecord[] _rangeRecords;
+ private final int _rangeCount;
+ private final RangeRecord[] _rangeRecords;
/** Creates new CoverageFormat2 */
- protected CoverageFormat2(DataInput di) throws IOException {
+ protected CoverageFormat2(final DataInput di) throws IOException {
_rangeCount = di.readUnsignedShort();
_rangeRecords = new RangeRecord[_rangeCount];
for (int i = 0; i < _rangeCount; i++) {
@@ -72,13 +72,15 @@ public class CoverageFormat2 extends Coverage {
}
}
+ @Override
public int getFormat() {
return 2;
}
- public int findGlyph(int glyphId) {
+ @Override
+ public int findGlyph(final int glyphId) {
for (int i = 0; i < _rangeCount; i++) {
- int n = _rangeRecords[i].getCoverageIndex(glyphId);
+ final int n = _rangeRecords[i].getCoverageIndex(glyphId);
if (n > -1) {
return n;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CvtTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CvtTable.java
index 963163584..7f62d26ab 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CvtTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/CvtTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -17,18 +17,19 @@ import java.io.IOException;
*/
public class CvtTable implements Table {
- private DirectoryEntry de;
- private short[] values;
+ private final DirectoryEntry de;
+ private final short[] values;
- protected CvtTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected CvtTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
- int len = de.getLength() / 2;
+ final int len = de.getLength() / 2;
values = new short[len];
for (int i = 0; i < len; i++) {
values[i] = di.readShort();
}
}
+ @Override
public int getType() {
return cvt;
}
@@ -37,8 +38,9 @@ public class CvtTable implements Table {
return values;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'cvt ' Table - Control Value Table\n----------------------------------\n");
sb.append("Size = ").append(0).append(" bytes, ").append(values.length).append(" entries\n");
sb.append(" Values\n ------\n");
@@ -47,15 +49,16 @@ public class CvtTable implements Table {
}
return sb.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Device.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Device.java
index 6b4af6908..a0b10e187 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Device.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Device.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,13 +18,13 @@ import java.io.RandomAccessFile;
*/
public class Device extends Object {
- private int startSize;
- private int endSize;
- private int deltaFormat;
- private int[] deltaValues;
+ private final int startSize;
+ private final int endSize;
+ private final int deltaFormat;
+ private final int[] deltaValues;
/** Creates new Device */
- public Device(RandomAccessFile raf) throws IOException {
+ public Device(final RandomAccessFile raf) throws IOException {
startSize = raf.readUnsignedShort();
endSize = raf.readUnsignedShort();
deltaFormat = raf.readUnsignedShort();
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DirectoryEntry.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DirectoryEntry.java
index c98f03fe9..54684b8e9 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DirectoryEntry.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DirectoryEntry.java
@@ -59,22 +59,23 @@ import java.io.IOException;
*/
public class DirectoryEntry implements Cloneable {
- private int _tag;
- private int _checksum;
- private int _offset;
- private int _length;
+ private final int _tag;
+ private final int _checksum;
+ private final int _offset;
+ private final int _length;
- protected DirectoryEntry(DataInput di) throws IOException {
+ protected DirectoryEntry(final DataInput di) throws IOException {
_tag = di.readInt();
_checksum = di.readInt();
_offset = di.readInt();
_length = di.readInt();
}
-
+
+ @Override
public Object clone() {
try {
return super.clone();
- } catch (CloneNotSupportedException e) {
+ } catch (final CloneNotSupportedException e) {
return null;
}
}
@@ -103,7 +104,8 @@ public class DirectoryEntry implements Cloneable {
.append((char)((_tag)&0xff))
.toString();
}
-
+
+ @Override
public String toString() {
return new StringBuilder()
.append("'").append(getTagAsString())
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DsigEntry.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DsigEntry.java
index 4b41f451d..ec7b503f1 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DsigEntry.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DsigEntry.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,12 +18,12 @@ import java.io.DataInput;
*/
public class DsigEntry {
- private int format;
- private int length;
- private int offset;
-
+ private final int format;
+ private final int length;
+ private final int offset;
+
/** Creates new DsigEntry */
- protected DsigEntry(DataInput di) throws IOException {
+ protected DsigEntry(final DataInput di) throws IOException {
format = di.readInt();
length = di.readInt();
offset = di.readInt();
@@ -32,11 +32,11 @@ public class DsigEntry {
public int getFormat() {
return format;
}
-
+
public int getLength() {
return length;
}
-
+
public int getOffset() {
return offset;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DsigTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DsigTable.java
index e2784f9e6..f2b1322c0 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DsigTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/DsigTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,15 +18,15 @@ import java.io.DataInput;
*/
public class DsigTable implements Table {
- private DirectoryEntry de;
- private int version;
- private int numSigs;
- private int flag;
- private DsigEntry[] dsigEntry;
- private SignatureBlock[] sigBlocks;
+ private final DirectoryEntry de;
+ private final int version;
+ private final int numSigs;
+ private final int flag;
+ private final DsigEntry[] dsigEntry;
+ private final SignatureBlock[] sigBlocks;
/** Creates new DsigTable */
- protected DsigTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected DsigTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
version = di.readInt();
numSigs = di.readUnsignedShort();
@@ -45,22 +45,25 @@ public class DsigTable implements Table {
* Get the table type, as a table directory value.
* @return The table type
*/
+ @Override
public int getType() {
return DSIG;
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder().append("DSIG\n");
+ final StringBuilder sb = new StringBuilder().append("DSIG\n");
for (int i = 0; i < numSigs; i++) {
sb.append(sigBlocks[i].toString());
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Feature.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Feature.java
index ee27896a4..c6f912569 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Feature.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Feature.java
@@ -60,12 +60,12 @@ import java.io.IOException;
*/
public class Feature {
- private int _featureParams;
- private int _lookupCount;
- private int[] _lookupListIndex;
+ private final int _featureParams;
+ private final int _lookupCount;
+ private final int[] _lookupListIndex;
/** Creates new Feature */
- protected Feature(DataInput di) throws IOException {
+ protected Feature(final DataInput di) throws IOException {
_featureParams = di.readUnsignedShort();
_lookupCount = di.readUnsignedShort();
_lookupListIndex = new int[_lookupCount];
@@ -78,7 +78,7 @@ public class Feature {
return _lookupCount;
}
- public int getLookupListIndex(int i) {
+ public int getLookupListIndex(final int i) {
return _lookupListIndex[i];
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FeatureList.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FeatureList.java
index 3cfb54a38..933378068 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FeatureList.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FeatureList.java
@@ -60,17 +60,17 @@ import java.io.IOException;
*/
public class FeatureList {
- private int _featureCount;
- private FeatureRecord[] _featureRecords;
- private Feature[] _features;
+ private final int _featureCount;
+ private final FeatureRecord[] _featureRecords;
+ private final Feature[] _features;
/** Creates new FeatureList */
- public FeatureList(DataInputStream dis, int offset) throws IOException {
-
+ public FeatureList(final DataInputStream dis, final int offset) throws IOException {
+
// Ensure we're in the right place
dis.reset();
dis.skipBytes(offset);
-
+
// Start reading
_featureCount = dis.readUnsignedShort();
_featureRecords = new FeatureRecord[_featureCount];
@@ -88,20 +88,20 @@ public class FeatureList {
public int getFeatureCount() {
return _featureCount;
}
-
- public FeatureRecord getFeatureRecord(int i) {
+
+ public FeatureRecord getFeatureRecord(final int i) {
return _featureRecords[i];
}
-
- public Feature getFeature(int i) {
+
+ public Feature getFeature(final int i) {
return _features[i];
}
- public Feature findFeature(LangSys langSys, String tag) {
+ public Feature findFeature(final LangSys langSys, final String tag) {
if (tag.length() != 4) {
return null;
}
- int tagVal = ((tag.charAt(0)<<24)
+ final int tagVal = ((tag.charAt(0)<<24)
| (tag.charAt(1)<<16)
| (tag.charAt(2)<<8)
| tag.charAt(3));
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FeatureRecord.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FeatureRecord.java
index eb610814b..06506904f 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FeatureRecord.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FeatureRecord.java
@@ -60,11 +60,11 @@ import java.io.IOException;
*/
public class FeatureRecord {
- private int _tag;
- private int _offset;
+ private final int _tag;
+ private final int _offset;
/** Creates new FeatureRecord */
- protected FeatureRecord(DataInput di) throws IOException {
+ protected FeatureRecord(final DataInput di) throws IOException {
_tag = di.readInt();
_offset = di.readUnsignedShort();
}
@@ -72,7 +72,7 @@ public class FeatureRecord {
public int getTag() {
return _tag;
}
-
+
public int getOffset() {
return _offset;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FpgmTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FpgmTable.java
index 9a6000156..e44acfa02 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FpgmTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/FpgmTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -19,29 +19,32 @@ import jogamp.graph.font.typecast.ot.Disassembler;
*/
public class FpgmTable extends Program implements Table {
- private DirectoryEntry de;
+ private final DirectoryEntry de;
- protected FpgmTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected FpgmTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
readInstructions(di, de.getLength());
}
+ @Override
public int getType() {
return fpgm;
}
+ @Override
public String toString() {
return Disassembler.disassemble(getInstructions(), 0);
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GaspRange.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GaspRange.java
index 2748406df..cebc51646 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GaspRange.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GaspRange.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -20,18 +20,19 @@ public class GaspRange {
public static final int GASP_GRIDFIT = 1;
public static final int GASP_DOGRAY = 2;
-
- private int rangeMaxPPEM;
- private int rangeGaspBehavior;
-
+
+ private final int rangeMaxPPEM;
+ private final int rangeGaspBehavior;
+
/** Creates new GaspRange */
- protected GaspRange(DataInput di) throws IOException {
+ protected GaspRange(final DataInput di) throws IOException {
rangeMaxPPEM = di.readUnsignedShort();
rangeGaspBehavior = di.readUnsignedShort();
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append(" rangeMaxPPEM: ").append(rangeMaxPPEM)
.append("\n rangeGaspBehavior: 0x").append(rangeGaspBehavior);
if ((rangeGaspBehavior & GASP_GRIDFIT) != 0) {
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GaspTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GaspTable.java
index a83db5bff..7bf7f96cc 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GaspTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GaspTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,13 +18,13 @@ import java.io.IOException;
*/
public class GaspTable implements Table {
- private DirectoryEntry de;
- private int version;
- private int numRanges;
- private GaspRange[] gaspRange;
-
+ private final DirectoryEntry de;
+ private final int version;
+ private final int numRanges;
+ private final GaspRange[] gaspRange;
+
/** Creates new GaspTable */
- protected GaspTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected GaspTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
version = di.readUnsignedShort();
numRanges = di.readUnsignedShort();
@@ -34,12 +34,14 @@ public class GaspTable implements Table {
}
}
+ @Override
public int getType() {
return gasp;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'gasp' Table - Grid-fitting And Scan-conversion Procedure\n---------------------------------------------------------");
sb.append("\n 'gasp' version: ").append(version);
sb.append("\n numRanges: ").append(numRanges);
@@ -49,15 +51,16 @@ public class GaspTable implements Table {
}
return sb.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfCompositeComp.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfCompositeComp.java
index e5c86873e..4db4ddcc2 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfCompositeComp.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfCompositeComp.java
@@ -69,12 +69,12 @@ public class GlyfCompositeComp {
public static final short WE_HAVE_INSTRUCTIONS = 0x0100;
public static final short USE_MY_METRICS = 0x0200;
- private int _firstIndex;
- private int _firstContour;
+ private final int _firstIndex;
+ private final int _firstContour;
private short _argument1;
private short _argument2;
- private int _flags;
- private int _glyphIndex;
+ private final int _flags;
+ private final int _glyphIndex;
private double _xscale = 1.0;
private double _yscale = 1.0;
private double _scale01 = 0.0;
@@ -84,7 +84,7 @@ public class GlyfCompositeComp {
private int _point1 = 0;
private int _point2 = 0;
- protected GlyfCompositeComp(int firstIndex, int firstContour, DataInput di)
+ protected GlyfCompositeComp(final int firstIndex, final int firstContour, final DataInput di)
throws IOException {
_firstIndex = firstIndex;
_firstContour = firstContour;
@@ -96,8 +96,8 @@ public class GlyfCompositeComp {
_argument1 = di.readShort();
_argument2 = di.readShort();
} else {
- _argument1 = (short) di.readByte();
- _argument2 = (short) di.readByte();
+ _argument1 = di.readByte();
+ _argument2 = di.readByte();
}
// Assign the arguments according to the flags
@@ -111,7 +111,7 @@ public class GlyfCompositeComp {
// Get the scale values (if any)
if ((_flags & WE_HAVE_A_SCALE) != 0) {
- int i = di.readShort();
+ final int i = di.readShort();
_xscale = _yscale = (double) i / (double) 0x4000;
} else if ((_flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0) {
short i = di.readShort();
@@ -184,8 +184,8 @@ public class GlyfCompositeComp {
* @param y The y-coordinate of the point to transform
* @return The transformed x-coordinate
*/
- public int scaleX(int x, int y) {
- return (int)((double) x * _xscale + (double) y * _scale10);
+ public int scaleX(final int x, final int y) {
+ return (int)(x * _xscale + y * _scale10);
}
/**
@@ -194,7 +194,7 @@ public class GlyfCompositeComp {
* @param y The y-coordinate of the point to transform
* @return The transformed y-coordinate
*/
- public int scaleY(int x, int y) {
- return (int)((double) x * _scale01 + (double) y * _yscale);
+ public int scaleY(final int x, final int y) {
+ return (int)(x * _scale01 + y * _yscale);
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfCompositeDescript.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfCompositeDescript.java
index 4cf254198..3879da02a 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfCompositeDescript.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfCompositeDescript.java
@@ -65,15 +65,15 @@ import java.util.ArrayList;
*/
public class GlyfCompositeDescript extends GlyfDescript {
- private ArrayList<GlyfCompositeComp> _components =
+ private final ArrayList<GlyfCompositeComp> _components =
new ArrayList<GlyfCompositeComp>();
public GlyfCompositeDescript(
- GlyfTable parentTable,
- int glyphIndex,
- DataInput di) throws IOException {
+ final GlyfTable parentTable,
+ final int glyphIndex,
+ final DataInput di) throws IOException {
super(parentTable, glyphIndex, (short) -1, di);
-
+
// Get all of the composite components
GlyfCompositeComp comp;
int firstIndex = 0;
@@ -81,7 +81,7 @@ public class GlyfCompositeDescript extends GlyfDescript {
try {
do {
_components.add(comp = new GlyfCompositeComp(firstIndex, firstContour, di));
- GlyfDescript desc = parentTable.getDescription(comp.getGlyphIndex());
+ final GlyfDescript desc = parentTable.getDescription(comp.getGlyphIndex());
if (desc != null) {
firstIndex += desc.getPointCount();
firstContour += desc.getContourCount();
@@ -92,38 +92,41 @@ public class GlyfCompositeDescript extends GlyfDescript {
if ((comp.getFlags() & GlyfCompositeComp.WE_HAVE_INSTRUCTIONS) != 0) {
readInstructions(di, di.readShort());
}
- } catch (IOException e) {
+ } catch (final IOException e) {
throw e;
// } catch (Exception e) {
// int foo = 0;
}
}
- public int getEndPtOfContours(int i) {
- GlyfCompositeComp c = getCompositeCompEndPt(i);
+ @Override
+ public int getEndPtOfContours(final int i) {
+ final GlyfCompositeComp c = getCompositeCompEndPt(i);
if (c != null) {
- GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
+ final GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
return gd.getEndPtOfContours(i - c.getFirstContour()) + c.getFirstIndex();
}
return 0;
}
- public byte getFlags(int i) {
- GlyfCompositeComp c = getCompositeComp(i);
+ @Override
+ public byte getFlags(final int i) {
+ final GlyfCompositeComp c = getCompositeComp(i);
if (c != null) {
- GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
+ final GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
return gd.getFlags(i - c.getFirstIndex());
}
return 0;
}
- public short getXCoordinate(int i) {
- GlyfCompositeComp c = getCompositeComp(i);
+ @Override
+ public short getXCoordinate(final int i) {
+ final GlyfCompositeComp c = getCompositeComp(i);
if (c != null) {
- GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
- int n = i - c.getFirstIndex();
- int x = gd.getXCoordinate(n);
- int y = gd.getYCoordinate(n);
+ final GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
+ final int n = i - c.getFirstIndex();
+ final int x = gd.getXCoordinate(n);
+ final int y = gd.getYCoordinate(n);
short x1 = (short) c.scaleX(x, y);
x1 += c.getXTranslate();
return x1;
@@ -131,13 +134,14 @@ public class GlyfCompositeDescript extends GlyfDescript {
return 0;
}
- public short getYCoordinate(int i) {
- GlyfCompositeComp c = getCompositeComp(i);
+ @Override
+ public short getYCoordinate(final int i) {
+ final GlyfCompositeComp c = getCompositeComp(i);
if (c != null) {
- GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
- int n = i - c.getFirstIndex();
- int x = gd.getXCoordinate(n);
- int y = gd.getYCoordinate(n);
+ final GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
+ final int n = i - c.getFirstIndex();
+ final int x = gd.getXCoordinate(n);
+ final int y = gd.getYCoordinate(n);
short y1 = (short) c.scaleY(x, y);
y1 += c.getYTranslate();
return y1;
@@ -145,13 +149,15 @@ public class GlyfCompositeDescript extends GlyfDescript {
return 0;
}
+ @Override
public boolean isComposite() {
return true;
}
+ @Override
public int getPointCount() {
- GlyfCompositeComp c = _components.get(_components.size()-1);
- GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
+ final GlyfCompositeComp c = _components.get(_components.size()-1);
+ final GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
if (gd != null) {
return c.getFirstIndex() + gd.getPointCount();
} else {
@@ -159,12 +165,14 @@ public class GlyfCompositeDescript extends GlyfDescript {
}
}
+ @Override
public int getContourCount() {
- GlyfCompositeComp c = _components.get(_components.size()-1);
- return c.getFirstContour() + _parentTable.getDescription(c.getGlyphIndex()).getContourCount();
+ final GlyfCompositeComp c = _components.get(_components.size()-1);
+ final GlyfDescript d = _parentTable.getDescription(c.getGlyphIndex());
+ return c.getFirstContour() + ( null != d ? d.getContourCount() : 0 );
}
- public int getComponentIndex(int i) {
+ public int getComponentIndex(final int i) {
return _components.get(i).getFirstIndex();
}
@@ -172,15 +180,15 @@ public class GlyfCompositeDescript extends GlyfDescript {
return _components.size();
}
- public GlyfCompositeComp getComponent(int i) {
+ public GlyfCompositeComp getComponent(final int i) {
return _components.get(i);
}
- protected GlyfCompositeComp getCompositeComp(int i) {
+ protected GlyfCompositeComp getCompositeComp(final int i) {
GlyfCompositeComp c;
for (int n = 0; n < _components.size(); n++) {
c = _components.get(n);
- GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
+ final GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
if (c.getFirstIndex() <= i && i < (c.getFirstIndex() + gd.getPointCount())) {
return c;
}
@@ -188,11 +196,11 @@ public class GlyfCompositeDescript extends GlyfDescript {
return null;
}
- protected GlyfCompositeComp getCompositeCompEndPt(int i) {
+ protected GlyfCompositeComp getCompositeCompEndPt(final int i) {
GlyfCompositeComp c;
for (int j = 0; j < _components.size(); j++) {
c = _components.get(j);
- GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
+ final GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex());
if (c.getFirstContour() <= i && i < (c.getFirstContour() + gd.getContourCount())) {
return c;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfDescript.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfDescript.java
index a9342a434..3d2154d5a 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfDescript.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfDescript.java
@@ -69,17 +69,17 @@ public abstract class GlyfDescript extends Program implements GlyphDescription {
protected GlyfTable _parentTable;
private int _glyphIndex;
- private int _numberOfContours;
- private short _xMin;
- private short _yMin;
- private short _xMax;
- private short _yMax;
+ private final int _numberOfContours;
+ private final short _xMin;
+ private final short _yMin;
+ private final short _xMax;
+ private final short _yMax;
protected GlyfDescript(
- GlyfTable parentTable,
- int glyphIndex,
- short numberOfContours,
- DataInput di) throws IOException {
+ final GlyfTable parentTable,
+ final int glyphIndex,
+ final short numberOfContours,
+ final DataInput di) throws IOException {
_parentTable = parentTable;
_numberOfContours = numberOfContours;
_xMin = di.readShort();
@@ -92,26 +92,32 @@ public abstract class GlyfDescript extends Program implements GlyphDescription {
return _numberOfContours;
}
+ @Override
public int getGlyphIndex() {
return _glyphIndex;
}
+ @Override
public short getXMaximum() {
return _xMax;
}
+ @Override
public short getXMinimum() {
return _xMin;
}
+ @Override
public short getYMaximum() {
return _yMax;
}
+ @Override
public short getYMinimum() {
return _yMin;
}
-
+
+ @Override
public String toString() {
return new StringBuilder()
.append(" numberOfContours: ").append(_numberOfContours)
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfSimpleDescript.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfSimpleDescript.java
index c11d2d8ff..041c0f04c 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfSimpleDescript.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfSimpleDescript.java
@@ -61,19 +61,19 @@ import jogamp.graph.font.typecast.ot.Disassembler;
*/
public class GlyfSimpleDescript extends GlyfDescript {
- private int[] _endPtsOfContours;
- private byte[] _flags;
- private short[] _xCoordinates;
- private short[] _yCoordinates;
- private int _count;
+ private final int[] _endPtsOfContours;
+ private final byte[] _flags;
+ private final short[] _xCoordinates;
+ private final short[] _yCoordinates;
+ private final int _count;
public GlyfSimpleDescript(
- GlyfTable parentTable,
- int glyphIndex,
- short numberOfContours,
- DataInput di) throws IOException {
+ final GlyfTable parentTable,
+ final int glyphIndex,
+ final short numberOfContours,
+ final DataInput di) throws IOException {
super(parentTable, glyphIndex, numberOfContours, di);
-
+
// Simple glyph description
_endPtsOfContours = new int[numberOfContours];
for (int i = 0; i < numberOfContours; i++) {
@@ -86,36 +86,43 @@ public class GlyfSimpleDescript extends GlyfDescript {
_xCoordinates = new short[_count];
_yCoordinates = new short[_count];
- int instructionCount = di.readShort();
+ final int instructionCount = di.readShort();
readInstructions(di, instructionCount);
readFlags(_count, di);
readCoords(_count, di);
}
- public int getEndPtOfContours(int i) {
+ @Override
+ public int getEndPtOfContours(final int i) {
return _endPtsOfContours[i];
}
- public byte getFlags(int i) {
+ @Override
+ public byte getFlags(final int i) {
return _flags[i];
}
- public short getXCoordinate(int i) {
+ @Override
+ public short getXCoordinate(final int i) {
return _xCoordinates[i];
}
- public short getYCoordinate(int i) {
+ @Override
+ public short getYCoordinate(final int i) {
return _yCoordinates[i];
}
+ @Override
public boolean isComposite() {
return false;
}
+ @Override
public int getPointCount() {
return _count;
}
+ @Override
public int getContourCount() {
return getNumberOfContours();
}
@@ -131,7 +138,7 @@ public class GlyfSimpleDescript extends GlyfDescript {
/**
* The table is stored as relative values, but we'll store them as absolutes
*/
- private void readCoords(int count, DataInput di) throws IOException {
+ private void readCoords(final int count, final DataInput di) throws IOException {
short x = 0;
short y = 0;
for (int i = 0; i < count; i++) {
@@ -168,25 +175,26 @@ public class GlyfSimpleDescript extends GlyfDescript {
/**
* The flags are run-length encoded
*/
- private void readFlags(int flagCount, DataInput di) throws IOException {
+ private void readFlags(final int flagCount, final DataInput di) throws IOException {
try {
for (int index = 0; index < flagCount; index++) {
_flags[index] = di.readByte();
if ((_flags[index] & repeat) != 0) {
- int repeats = di.readByte();
+ final int repeats = di.readByte();
for (int i = 1; i <= repeats; i++) {
_flags[index + i] = _flags[index];
}
index += repeats;
}
}
- } catch (ArrayIndexOutOfBoundsException e) {
+ } catch (final ArrayIndexOutOfBoundsException e) {
System.out.println("error: array index out of bounds");
}
}
-
+
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append(super.toString());
sb.append("\n\n EndPoints\n ---------");
for (int i = 0; i < _endPtsOfContours.length; i++) {
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfTable.java
index 22fdd8886..6750e9394 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfTable.java
@@ -61,30 +61,30 @@ import java.io.IOException;
*/
public class GlyfTable implements Table {
- private DirectoryEntry _de;
- private GlyfDescript[] _descript;
+ private final DirectoryEntry _de;
+ private final GlyfDescript[] _descript;
protected GlyfTable(
- DirectoryEntry de,
- DataInput di,
- MaxpTable maxp,
- LocaTable loca) throws IOException {
+ final DirectoryEntry de,
+ final DataInput di,
+ final MaxpTable maxp,
+ final LocaTable loca) throws IOException {
_de = (DirectoryEntry) de.clone();
_descript = new GlyfDescript[maxp.getNumGlyphs()];
-
+
// Buffer the whole table so we can randomly access it
- byte[] buf = new byte[de.getLength()];
+ final byte[] buf = new byte[de.getLength()];
di.readFully(buf);
- ByteArrayInputStream bais = new ByteArrayInputStream(buf);
-
+ final ByteArrayInputStream bais = new ByteArrayInputStream(buf);
+
// Process all the simple glyphs
for (int i = 0; i < maxp.getNumGlyphs(); i++) {
- int len = loca.getOffset(i + 1) - loca.getOffset(i);
+ final int len = loca.getOffset(i + 1) - loca.getOffset(i);
if (len > 0) {
bais.reset();
bais.skip(loca.getOffset(i));
- DataInputStream dis = new DataInputStream(bais);
- short numberOfContours = dis.readShort();
+ final DataInputStream dis = new DataInputStream(bais);
+ final short numberOfContours = dis.readShort();
if (numberOfContours >= 0) {
_descript[i] = new GlyfSimpleDescript(this, i, numberOfContours, dis);
}
@@ -95,12 +95,12 @@ public class GlyfTable implements Table {
// Now do all the composite glyphs
for (int i = 0; i < maxp.getNumGlyphs(); i++) {
- int len = loca.getOffset(i + 1) - loca.getOffset(i);
+ final int len = loca.getOffset(i + 1) - loca.getOffset(i);
if (len > 0) {
bais.reset();
bais.skip(loca.getOffset(i));
- DataInputStream dis = new DataInputStream(bais);
- short numberOfContours = dis.readShort();
+ final DataInputStream dis = new DataInputStream(bais);
+ final short numberOfContours = dis.readShort();
if (numberOfContours < 0) {
_descript[i] = new GlyfCompositeDescript(this, i, dis);
}
@@ -108,7 +108,7 @@ public class GlyfTable implements Table {
}
}
- public GlyfDescript getDescription(int i) {
+ public GlyfDescript getDescription(final int i) {
if (i < _descript.length) {
return _descript[i];
} else {
@@ -116,16 +116,18 @@ public class GlyfTable implements Table {
}
}
+ @Override
public int getType() {
return glyf;
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyphDescription.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyphDescription.java
index 106e17917..025778dfc 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyphDescription.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyphDescription.java
@@ -56,29 +56,29 @@ package jogamp.graph.font.typecast.ot.table;
* @author <a href="mailto:[email protected]">David Schweinsberg</a>
*/
public interface GlyphDescription {
-
+
public int getGlyphIndex();
-
+
public int getEndPtOfContours(int i);
-
+
public byte getFlags(int i);
-
+
public short getXCoordinate(int i);
-
+
public short getYCoordinate(int i);
-
+
public short getXMaximum();
-
+
public short getXMinimum();
-
+
public short getYMaximum();
-
+
public short getYMinimum();
-
+
public boolean isComposite();
-
+
public int getPointCount();
-
+
public int getContourCount();
// public int getComponentIndex(int c);
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GposTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GposTable.java
index 91a62362a..ce6f308db 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GposTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GposTable.java
@@ -30,25 +30,27 @@ import java.io.IOException;
*/
public class GposTable implements Table {
- private DirectoryEntry _de;
+ private final DirectoryEntry _de;
- protected GposTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected GposTable(final DirectoryEntry de, final DataInput di) throws IOException {
_de = (DirectoryEntry) de.clone();
// GPOS Header
- int version = di.readInt();
- int scriptList = di.readInt();
- int featureList = di.readInt();
- int lookupList = di.readInt();
+ /* final int version = */ di.readInt();
+ /* final int scriptList = */ di.readInt();
+ /* final int featureList = */ di.readInt();
+ /* final int lookupList = */ di.readInt();
}
/** Get the table type, as a table directory value.
* @return The table type
*/
+ @Override
public int getType() {
return GPOS;
}
-
+
+ @Override
public String toString() {
return "GPOS";
}
@@ -59,8 +61,9 @@ public class GposTable implements Table {
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GsubTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GsubTable.java
index c002de374..3147fc8c5 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GsubTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GsubTable.java
@@ -62,47 +62,48 @@ import java.io.IOException;
*/
public class GsubTable implements Table, LookupSubtableFactory {
- private DirectoryEntry _de;
- private ScriptList _scriptList;
- private FeatureList _featureList;
- private LookupList _lookupList;
-
- protected GsubTable(DirectoryEntry de, DataInput di) throws IOException {
+ private final DirectoryEntry _de;
+ private final ScriptList _scriptList;
+ private final FeatureList _featureList;
+ private final LookupList _lookupList;
+
+ protected GsubTable(final DirectoryEntry de, final DataInput di) throws IOException {
_de = (DirectoryEntry) de.clone();
-
+
// Load into a temporary buffer, and create another input stream
- byte[] buf = new byte[de.getLength()];
+ final byte[] buf = new byte[de.getLength()];
di.readFully(buf);
- DataInputStream dis = new DataInputStream(new ByteArrayInputStream(buf));
+ final DataInputStream dis = new DataInputStream(new ByteArrayInputStream(buf));
// GSUB Header
- int version = dis.readInt();
- int scriptListOffset = dis.readUnsignedShort();
- int featureListOffset = dis.readUnsignedShort();
- int lookupListOffset = dis.readUnsignedShort();
+ /* final int version = */ dis.readInt();
+ final int scriptListOffset = dis.readUnsignedShort();
+ final int featureListOffset = dis.readUnsignedShort();
+ final int lookupListOffset = dis.readUnsignedShort();
// Script List
_scriptList = new ScriptList(dis, scriptListOffset);
// Feature List
_featureList = new FeatureList(dis, featureListOffset);
-
+
// Lookup List
_lookupList = new LookupList(dis, lookupListOffset, this);
}
/**
- * 1 - Single - Replace one glyph with one glyph
- * 2 - Multiple - Replace one glyph with more than one glyph
- * 3 - Alternate - Replace one glyph with one of many glyphs
- * 4 - Ligature - Replace multiple glyphs with one glyph
- * 5 - Context - Replace one or more glyphs in context
+ * 1 - Single - Replace one glyph with one glyph
+ * 2 - Multiple - Replace one glyph with more than one glyph
+ * 3 - Alternate - Replace one glyph with one of many glyphs
+ * 4 - Ligature - Replace multiple glyphs with one glyph
+ * 5 - Context - Replace one or more glyphs in context
* 6 - Chaining - Context Replace one or more glyphs in chained context
*/
+ @Override
public LookupSubtable read(
- int type,
- DataInputStream dis,
- int offset) throws IOException {
+ final int type,
+ final DataInputStream dis,
+ final int offset) throws IOException {
LookupSubtable s = null;
switch (type) {
case 1:
@@ -130,6 +131,7 @@ public class GsubTable implements Table, LookupSubtableFactory {
/** Get the table type, as a table directory value.
* @return The table type
*/
+ @Override
public int getType() {
return GSUB;
}
@@ -146,11 +148,12 @@ public class GsubTable implements Table, LookupSubtableFactory {
return _lookupList;
}
+ @Override
public String toString() {
return "GSUB";
}
- public static String lookupTypeAsString(int type) {
+ public static String lookupTypeAsString(final int type) {
switch (type) {
case 1:
return "Single";
@@ -167,15 +170,16 @@ public class GsubTable implements Table, LookupSubtableFactory {
}
return "Unknown";
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HdmxTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HdmxTable.java
index 5b1fa2020..2bd51c124 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HdmxTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HdmxTable.java
@@ -30,14 +30,14 @@ import java.io.IOException;
* @version $Id: HdmxTable.java,v 1.2 2007-07-26 11:12:30 davidsch Exp $
*/
public class HdmxTable implements Table {
-
- public class DeviceRecord {
-
- private short _pixelSize;
- private short _maxWidth;
- private short[] _widths;
-
- protected DeviceRecord(int numGlyphs, DataInput di) throws IOException {
+
+ public static class DeviceRecord {
+
+ private final short _pixelSize;
+ private final short _maxWidth;
+ private final short[] _widths;
+
+ protected DeviceRecord(final int numGlyphs, final DataInput di) throws IOException {
_pixelSize = di.readByte();
_maxWidth = di.readByte();
_widths = new short[numGlyphs];
@@ -49,36 +49,36 @@ public class HdmxTable implements Table {
public short getPixelSize() {
return _pixelSize;
}
-
+
public short getMaxWidth() {
return _maxWidth;
}
-
+
public short[] getWidths() {
return _widths;
}
- public short getWidth(int glyphidx) {
+ public short getWidth(final int glyphidx) {
return _widths[glyphidx];
}
-
+
}
-
- private DirectoryEntry _de;
- private int _version;
- private short _numRecords;
- private int _sizeDeviceRecords;
- private DeviceRecord[] _records;
+
+ private final DirectoryEntry _de;
+ private final int _version;
+ private final short _numRecords;
+ private final int _sizeDeviceRecords;
+ private final DeviceRecord[] _records;
/** Creates a new instance of HdmxTable */
- protected HdmxTable(DirectoryEntry de, DataInput di, MaxpTable maxp)
+ protected HdmxTable(final DirectoryEntry de, final DataInput di, final MaxpTable maxp)
throws IOException {
_de = (DirectoryEntry) de.clone();
_version = di.readUnsignedShort();
_numRecords = di.readShort();
_sizeDeviceRecords = di.readInt();
_records = new DeviceRecord[_numRecords];
-
+
// Read the device records
for (int i = 0; i < _numRecords; ++i) {
_records[i] = new DeviceRecord(maxp.getNumGlyphs(), di);
@@ -88,17 +88,19 @@ public class HdmxTable implements Table {
public int getNumberOfRecords() {
return _numRecords;
}
-
- public DeviceRecord getRecord(int i) {
+
+ public DeviceRecord getRecord(final int i) {
return _records[i];
}
-
+
+ @Override
public int getType() {
return hdmx;
}
-
+
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'hdmx' Table - Horizontal Device Metrics\n----------------------------------------\n");
sb.append("Size = ").append(_de.getLength()).append(" bytes\n")
.append("\t'hdmx' version: ").append(_version).append("\n")
@@ -124,6 +126,7 @@ public class HdmxTable implements Table {
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HeadTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HeadTable.java
index 9d7fe4251..85158ea3e 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HeadTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HeadTable.java
@@ -62,26 +62,26 @@ import jogamp.graph.font.typecast.ot.Fixed;
*/
public class HeadTable implements Table {
- private DirectoryEntry _de;
- private int _versionNumber;
- private int _fontRevision;
- private int _checkSumAdjustment;
- private int _magicNumber;
- private short _flags;
- private short _unitsPerEm;
- private long _created;
- private long _modified;
- private short _xMin;
- private short _yMin;
- private short _xMax;
- private short _yMax;
- private short _macStyle;
- private short _lowestRecPPEM;
- private short _fontDirectionHint;
- private short _indexToLocFormat;
- private short _glyphDataFormat;
-
- protected HeadTable(DirectoryEntry de, DataInput di) throws IOException {
+ private final DirectoryEntry _de;
+ private final int _versionNumber;
+ private final int _fontRevision;
+ private final int _checkSumAdjustment;
+ private final int _magicNumber;
+ private final short _flags;
+ private final short _unitsPerEm;
+ private final long _created;
+ private final long _modified;
+ private final short _xMin;
+ private final short _yMin;
+ private final short _xMax;
+ private final short _yMax;
+ private final short _macStyle;
+ private final short _lowestRecPPEM;
+ private final short _fontDirectionHint;
+ private final short _indexToLocFormat;
+ private final short _glyphDataFormat;
+
+ protected HeadTable(final DirectoryEntry de, final DataInput di) throws IOException {
this._de = (DirectoryEntry) de.clone();
_versionNumber = di.readInt();
_fontRevision = di.readInt();
@@ -142,6 +142,7 @@ public class HeadTable implements Table {
return _modified;
}
+ @Override
public int getType() {
return head;
}
@@ -170,6 +171,7 @@ public class HeadTable implements Table {
return _yMin;
}
+ @Override
public String toString() {
return new StringBuilder()
.append("'head' Table - Font Header\n--------------------------")
@@ -192,15 +194,16 @@ public class HeadTable implements Table {
.append("\n glyphDataFormat: ").append(_glyphDataFormat)
.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HheaTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HheaTable.java
index 20a21e4d9..e67a03777 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HheaTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HheaTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -19,21 +19,21 @@ import jogamp.graph.font.typecast.ot.Fixed;
*/
public class HheaTable implements Table {
- private DirectoryEntry de;
- private int version;
- private short ascender;
- private short descender;
- private short lineGap;
- private short advanceWidthMax;
- private short minLeftSideBearing;
- private short minRightSideBearing;
- private short xMaxExtent;
- private short caretSlopeRise;
- private short caretSlopeRun;
- private short metricDataFormat;
- private int numberOfHMetrics;
-
- protected HheaTable(DirectoryEntry de, DataInput di) throws IOException {
+ private final DirectoryEntry de;
+ private final int version;
+ private final short ascender;
+ private final short descender;
+ private final short lineGap;
+ private final short advanceWidthMax;
+ private final short minLeftSideBearing;
+ private final short minRightSideBearing;
+ private final short xMaxExtent;
+ private final short caretSlopeRise;
+ private final short caretSlopeRun;
+ private final short metricDataFormat;
+ private final int numberOfHMetrics;
+
+ protected HheaTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
version = di.readInt();
ascender = di.readShort();
@@ -92,6 +92,7 @@ public class HheaTable implements Table {
return numberOfHMetrics;
}
+ @Override
public int getType() {
return hhea;
}
@@ -100,6 +101,7 @@ public class HheaTable implements Table {
return xMaxExtent;
}
+ @Override
public String toString() {
return new StringBuilder()
.append("'hhea' Table - Horizontal Header\n--------------------------------")
@@ -122,15 +124,16 @@ public class HheaTable implements Table {
.append("\n numOf_LongHorMetrics: ").append(numberOfHMetrics)
.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HmtxTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HmtxTable.java
index dacd9e265..3a9672a92 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HmtxTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/HmtxTable.java
@@ -59,15 +59,15 @@ import java.io.IOException;
*/
public class HmtxTable implements Table {
- private DirectoryEntry _de;
+ private final DirectoryEntry _de;
private int[] _hMetrics = null;
private short[] _leftSideBearing = null;
protected HmtxTable(
- DirectoryEntry de,
- DataInput di,
- HheaTable hhea,
- MaxpTable maxp) throws IOException {
+ final DirectoryEntry de,
+ final DataInput di,
+ final HheaTable hhea,
+ final MaxpTable maxp) throws IOException {
_de = (DirectoryEntry) de.clone();
_hMetrics = new int[hhea.getNumberOfHMetrics()];
for (int i = 0; i < hhea.getNumberOfHMetrics(); ++i) {
@@ -77,14 +77,14 @@ public class HmtxTable implements Table {
| di.readUnsignedByte()<<8
| di.readUnsignedByte();
}
- int lsbCount = maxp.getNumGlyphs() - hhea.getNumberOfHMetrics();
+ final int lsbCount = maxp.getNumGlyphs() - hhea.getNumberOfHMetrics();
_leftSideBearing = new short[lsbCount];
for (int i = 0; i < lsbCount; ++i) {
_leftSideBearing[i] = di.readShort();
}
}
- public int getAdvanceWidth(int i) {
+ public int getAdvanceWidth(final int i) {
if (_hMetrics == null) {
return 0;
}
@@ -95,7 +95,7 @@ public class HmtxTable implements Table {
}
}
- public short getLeftSideBearing(int i) {
+ public short getLeftSideBearing(final int i) {
if (_hMetrics == null) {
return 0;
}
@@ -106,12 +106,14 @@ public class HmtxTable implements Table {
}
}
+ @Override
public int getType() {
return hmtx;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'hmtx' Table - Horizontal Metrics\n---------------------------------\n");
sb.append("Size = ").append(_de.getLength()).append(" bytes, ")
.append(_hMetrics.length).append(" entries\n");
@@ -135,6 +137,7 @@ public class HmtxTable implements Table {
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ID.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ID.java
index 9fd66e728..ad7e4e376 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ID.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ID.java
@@ -38,7 +38,7 @@ public abstract class ID {
public static final short encodingUnicode11Semantics = 1;
public static final short encodingISO10646Semantics = 2;
public static final short encodingUnicode20Semantics = 3;
-
+
// Microsoft Encoding IDs
// public static final short encodingUndefined = 0;
// public static final short encodingUGL = 1;
@@ -190,7 +190,7 @@ public abstract class ID {
public static final short nameSampleText = 19;
public static final short namePostScriptCIDFindfontName = 20;
- public static String getPlatformName(short platformId) {
+ public static String getPlatformName(final short platformId) {
switch (platformId) {
case platformUnicode: return "Unicode";
case platformMacintosh: return "Macintosh";
@@ -200,10 +200,10 @@ public abstract class ID {
}
}
- public static String getEncodingName(short platformId, short encodingId) {
+ public static String getEncodingName(final short platformId, final short encodingId) {
if (platformId == platformUnicode) {
-
+
// Unicode specific encodings
switch (encodingId) {
case encodingUnicode10Semantics: return "Unicode 1.0 semantics";
@@ -284,7 +284,7 @@ public abstract class ID {
return "";
}
- public static String getLanguageName(short platformId, short languageId) {
+ public static String getLanguageName(final short platformId, final short languageId) {
if (platformId == platformMacintosh) {
switch (languageId) {
@@ -371,7 +371,7 @@ public abstract class ID {
return "";
}
- public static String getNameName(short nameId) {
+ public static String getNameName(final short nameId) {
switch (nameId) {
case nameCopyrightNotice: return "Copyright notice";
case nameFontFamilyName: return "Font Family name";
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtable.java
index 7a4cccba2..dcf02cb2b 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -21,18 +21,18 @@ public abstract class KernSubtable {
/** Creates new KernSubtable */
protected KernSubtable() {
}
-
+
public abstract int getKerningPairCount();
public abstract KerningPair getKerningPair(int i);
- public static KernSubtable read(DataInput di) throws IOException {
+ public static KernSubtable read(final DataInput di) throws IOException {
KernSubtable table = null;
- int version = di.readUnsignedShort();
- int length = di.readUnsignedShort();
- int coverage = di.readUnsignedShort();
- int format = coverage >> 8;
-
+ /* final int version = */ di.readUnsignedShort();
+ /* final int length = */ di.readUnsignedShort();
+ final int coverage = di.readUnsignedShort();
+ final int format = coverage >> 8;
+
switch (format) {
case 0:
table = new KernSubtableFormat0(di);
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtableFormat0.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtableFormat0.java
index b55bef6d5..2d1acddd5 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtableFormat0.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtableFormat0.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -17,15 +17,15 @@ import java.io.IOException;
* @version $Id: KernSubtableFormat0.java,v 1.1.1.1 2004-12-05 23:14:48 davidsch Exp $
*/
public class KernSubtableFormat0 extends KernSubtable {
-
- private int nPairs;
- private int searchRange;
- private int entrySelector;
- private int rangeShift;
- private KerningPair[] kerningPairs;
+
+ private final int nPairs;
+ private final int searchRange;
+ private final int entrySelector;
+ private final int rangeShift;
+ private final KerningPair[] kerningPairs;
/** Creates new KernSubtableFormat0 */
- protected KernSubtableFormat0(DataInput di) throws IOException {
+ protected KernSubtableFormat0(final DataInput di) throws IOException {
nPairs = di.readUnsignedShort();
searchRange = di.readUnsignedShort();
entrySelector = di.readUnsignedShort();
@@ -36,11 +36,13 @@ public class KernSubtableFormat0 extends KernSubtable {
}
}
+ @Override
public int getKerningPairCount() {
return nPairs;
}
- public KerningPair getKerningPair(int i) {
+ @Override
+ public KerningPair getKerningPair(final int i) {
return kerningPairs[i];
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtableFormat2.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtableFormat2.java
index 60d584ca6..deb56c96d 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtableFormat2.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernSubtableFormat2.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,24 +18,26 @@ import java.io.IOException;
*/
public class KernSubtableFormat2 extends KernSubtable {
- private int rowWidth;
- private int leftClassTable;
- private int rightClassTable;
- private int array;
+ private final int rowWidth;
+ private final int leftClassTable;
+ private final int rightClassTable;
+ private final int array;
/** Creates new KernSubtableFormat2 */
- protected KernSubtableFormat2(DataInput di) throws IOException {
+ protected KernSubtableFormat2(final DataInput di) throws IOException {
rowWidth = di.readUnsignedShort();
leftClassTable = di.readUnsignedShort();
rightClassTable = di.readUnsignedShort();
array = di.readUnsignedShort();
}
+ @Override
public int getKerningPairCount() {
return 0;
}
- public KerningPair getKerningPair(int i) {
+ @Override
+ public KerningPair getKerningPair(final int i) {
return null;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernTable.java
index 70aee70d2..6f1d682e1 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KernTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -17,14 +17,14 @@ import java.io.IOException;
* @version $Id: KernTable.java,v 1.1.1.1 2004-12-05 23:14:48 davidsch Exp $
*/
public class KernTable implements Table {
-
- private DirectoryEntry de;
- private int version;
- private int nTables;
- private KernSubtable[] tables;
+
+ private final DirectoryEntry de;
+ private final int version;
+ private final int nTables;
+ private final KernSubtable[] tables;
/** Creates new KernTable */
- protected KernTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected KernTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
version = di.readUnsignedShort();
nTables = di.readUnsignedShort();
@@ -37,14 +37,15 @@ public class KernTable implements Table {
public int getSubtableCount() {
return nTables;
}
-
- public KernSubtable getSubtable(int i) {
+
+ public KernSubtable getSubtable(final int i) {
return tables[i];
}
/** Get the table type, as a table directory value.
* @return The table type
*/
+ @Override
public int getType() {
return kern;
}
@@ -55,8 +56,9 @@ public class KernTable implements Table {
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KerningPair.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KerningPair.java
index ce7cebc97..dd5d0ba06 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KerningPair.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/KerningPair.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,12 +18,12 @@ import java.io.IOException;
*/
public class KerningPair {
- private int left;
- private int right;
- private short value;
+ private final int left;
+ private final int right;
+ private final short value;
/** Creates new KerningPair */
- protected KerningPair(DataInput di) throws IOException {
+ protected KerningPair(final DataInput di) throws IOException {
left = di.readUnsignedShort();
right = di.readUnsignedShort();
value = di.readShort();
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LangSys.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LangSys.java
index 6759208f5..e12d2e2e7 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LangSys.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LangSys.java
@@ -60,13 +60,13 @@ import java.io.IOException;
*/
public class LangSys {
- private int _lookupOrder;
- private int _reqFeatureIndex;
- private int _featureCount;
- private int[] _featureIndex;
-
+ private final int _lookupOrder;
+ private final int _reqFeatureIndex;
+ private final int _featureCount;
+ private final int[] _featureIndex;
+
/** Creates new LangSys */
- protected LangSys(DataInput di) throws IOException {
+ protected LangSys(final DataInput di) throws IOException {
_lookupOrder = di.readUnsignedShort();
_reqFeatureIndex = di.readUnsignedShort();
_featureCount = di.readUnsignedShort();
@@ -75,24 +75,24 @@ public class LangSys {
_featureIndex[i] = di.readUnsignedShort();
}
}
-
+
public int getLookupOrder() {
return _lookupOrder;
}
-
+
public int getReqFeatureIndex() {
return _reqFeatureIndex;
}
-
+
public int getFeatureCount() {
return _featureCount;
}
-
- public int getFeatureIndex(int i) {
+
+ public int getFeatureIndex(final int i) {
return _featureIndex[i];
}
- protected boolean isFeatureIndexed(int n) {
+ protected boolean isFeatureIndexed(final int n) {
for (int i = 0; i < _featureCount; i++) {
if (_featureIndex[i] == n) {
return true;
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LangSysRecord.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LangSysRecord.java
index 9511f66ba..08ea719f3 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LangSysRecord.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LangSysRecord.java
@@ -60,11 +60,11 @@ import java.io.IOException;
*/
public class LangSysRecord {
- private int _tag;
- private int _offset;
-
+ private final int _tag;
+ private final int _offset;
+
/** Creates new LangSysRecord */
- public LangSysRecord(DataInput di) throws IOException {
+ public LangSysRecord(final DataInput di) throws IOException {
_tag = di.readInt();
_offset = di.readUnsignedShort();
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Ligature.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Ligature.java
index d3e2ad5cd..dfd19e7ac 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Ligature.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Ligature.java
@@ -60,12 +60,12 @@ import java.io.IOException;
*/
public class Ligature {
- private int _ligGlyph;
- private int _compCount;
- private int[] _components;
+ private final int _ligGlyph;
+ private final int _compCount;
+ private final int[] _components;
/** Creates new Ligature */
- public Ligature(DataInput di) throws IOException {
+ public Ligature(final DataInput di) throws IOException {
_ligGlyph = di.readUnsignedShort();
_compCount = di.readUnsignedShort();
_components = new int[_compCount - 1];
@@ -73,12 +73,12 @@ public class Ligature {
_components[i] = di.readUnsignedShort();
}
}
-
+
public int getGlyphCount() {
return _compCount;
}
-
- public int getGlyphId(int i) {
+
+ public int getGlyphId(final int i) {
return (i == 0) ? _ligGlyph : _components[i-1];
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSet.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSet.java
index e261f3a88..8b7738992 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSet.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSet.java
@@ -60,12 +60,12 @@ import java.io.IOException;
*/
public class LigatureSet {
- private int _ligatureCount;
- private int[] _ligatureOffsets;
- private Ligature[] _ligatures;
+ private final int _ligatureCount;
+ private final int[] _ligatureOffsets;
+ private final Ligature[] _ligatures;
/** Creates new LigatureSet */
- public LigatureSet(DataInputStream dis, int offset) throws IOException {
+ public LigatureSet(final DataInputStream dis, final int offset) throws IOException {
dis.reset();
dis.skipBytes(offset);
_ligatureCount = dis.readUnsignedShort();
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSubst.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSubst.java
index c0570cde9..36a44a11e 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSubst.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSubst.java
@@ -60,10 +60,10 @@ import java.io.IOException;
*/
public abstract class LigatureSubst extends LookupSubtable {
- public static LigatureSubst read(DataInputStream dis, int offset) throws IOException {
+ public static LigatureSubst read(final DataInputStream dis, final int offset) throws IOException {
dis.reset();
dis.skipBytes(offset);
- int format = dis.readUnsignedShort();
+ final int format = dis.readUnsignedShort();
if (format == 1) {
return new LigatureSubstFormat1(dis, offset);
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSubstFormat1.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSubstFormat1.java
index a0f42662c..02d4479b3 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSubstFormat1.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LigatureSubstFormat1.java
@@ -60,16 +60,16 @@ import java.io.IOException;
*/
public class LigatureSubstFormat1 extends LigatureSubst {
- private int _coverageOffset;
- private int _ligSetCount;
- private int[] _ligatureSetOffsets;
- private Coverage _coverage;
- private LigatureSet[] _ligatureSets;
+ private final int _coverageOffset;
+ private final int _ligSetCount;
+ private final int[] _ligatureSetOffsets;
+ private final Coverage _coverage;
+ private final LigatureSet[] _ligatureSets;
/** Creates new LigatureSubstFormat1 */
protected LigatureSubstFormat1(
- DataInputStream dis,
- int offset) throws IOException {
+ final DataInputStream dis,
+ final int offset) throws IOException {
_coverageOffset = dis.readUnsignedShort();
_ligSetCount = dis.readUnsignedShort();
_ligatureSetOffsets = new int[_ligSetCount];
@@ -89,7 +89,8 @@ public class LigatureSubstFormat1 extends LigatureSubst {
return 1;
}
+ @Override
public String getTypeAsString() {
return "LigatureSubstFormat1";
- }
+ }
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LocaTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LocaTable.java
index 5eb7c5856..a955ad3e5 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LocaTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LocaTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -17,18 +17,18 @@ import java.io.IOException;
*/
public class LocaTable implements Table {
- private DirectoryEntry _de;
+ private final DirectoryEntry _de;
private int[] _offsets = null;
private short _factor = 0;
protected LocaTable(
- DirectoryEntry de,
- DataInput di,
- HeadTable head,
- MaxpTable maxp) throws IOException {
+ final DirectoryEntry de,
+ final DataInput di,
+ final HeadTable head,
+ final MaxpTable maxp) throws IOException {
_de = (DirectoryEntry) de.clone();
_offsets = new int[maxp.getNumGlyphs() + 1];
- boolean shortEntries = head.getIndexToLocFormat() == 0;
+ final boolean shortEntries = head.getIndexToLocFormat() == 0;
if (shortEntries) {
_factor = 2;
for (int i = 0; i <= maxp.getNumGlyphs(); i++) {
@@ -42,19 +42,21 @@ public class LocaTable implements Table {
}
}
- public int getOffset(int i) {
+ public int getOffset(final int i) {
if (_offsets == null) {
return 0;
}
return _offsets[i] * _factor;
}
+ @Override
public int getType() {
return loca;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'loca' Table - Index To Location Table\n--------------------------------------\n")
.append("Size = ").append(_de.getLength()).append(" bytes, ")
.append(_offsets.length).append(" entries\n");
@@ -64,13 +66,14 @@ public class LocaTable implements Table {
}
return sb.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Lookup.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Lookup.java
index 2899c24d9..b80ebbee4 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Lookup.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Lookup.java
@@ -66,20 +66,20 @@ public class Lookup {
public static final int IGNORE_BASE_MARKS = 0x0008;
public static final int MARK_ATTACHMENT_TYPE = 0xFF00;
- private int _type;
- private int _flag;
- private int _subTableCount;
- private int[] _subTableOffsets;
- private LookupSubtable[] _subTables;
+ private final int _type;
+ private final int _flag;
+ private final int _subTableCount;
+ private final int[] _subTableOffsets;
+ private final LookupSubtable[] _subTables;
/** Creates new Lookup */
- public Lookup(LookupSubtableFactory factory, DataInputStream dis, int offset)
+ public Lookup(final LookupSubtableFactory factory, final DataInputStream dis, final int offset)
throws IOException {
// Ensure we're in the right place
dis.reset();
dis.skipBytes(offset);
-
+
// Start reading
_type = dis.readUnsignedShort();
_flag = dis.readUnsignedShort();
@@ -102,7 +102,7 @@ public class Lookup {
return _subTableCount;
}
- public LookupSubtable getSubtable(int i) {
+ public LookupSubtable getSubtable(final int i) {
return _subTables[i];
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LookupList.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LookupList.java
index a3b71b639..6d8ca2a6c 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LookupList.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LookupList.java
@@ -60,18 +60,18 @@ import java.io.IOException;
*/
public class LookupList {
- private int _lookupCount;
- private int[] _lookupOffsets;
- private Lookup[] _lookups;
+ private final int _lookupCount;
+ private final int[] _lookupOffsets;
+ private final Lookup[] _lookups;
/** Creates new LookupList */
- public LookupList(DataInputStream dis, int offset, LookupSubtableFactory factory)
+ public LookupList(final DataInputStream dis, final int offset, final LookupSubtableFactory factory)
throws IOException {
-
+
// Ensure we're in the right place
dis.reset();
dis.skipBytes(offset);
-
+
// Start reading
_lookupCount = dis.readUnsignedShort();
_lookupOffsets = new int[_lookupCount];
@@ -87,18 +87,18 @@ public class LookupList {
public int getLookupCount() {
return _lookupCount;
}
-
- public int getLookupOffset(int i) {
+
+ public int getLookupOffset(final int i) {
return _lookupOffsets[i];
}
-
- public Lookup getLookup(int i) {
+
+ public Lookup getLookup(final int i) {
return _lookups[i];
}
- public Lookup getLookup(Feature feature, int index) {
+ public Lookup getLookup(final Feature feature, final int index) {
if (feature.getLookupCount() > index) {
- int i = feature.getLookupListIndex(index);
+ final int i = feature.getLookupListIndex(index);
return _lookups[i];
}
return null;
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LookupSubtableFactory.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LookupSubtableFactory.java
index cb4d28d2c..ca67df7fb 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LookupSubtableFactory.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LookupSubtableFactory.java
@@ -47,13 +47,13 @@
Apache Software Foundation, please see <http://www.apache.org/>.
*/
-
+
package jogamp.graph.font.typecast.ot.table;
import java.io.DataInputStream;
import java.io.IOException;
-/**
+/**
*
* @author <a href="mailto:[email protected]">David Schweinsberg</a>
* @version $Id: LookupSubtableFactory.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LtshTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LtshTable.java
index ace3d38b5..efafe7bb6 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LtshTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/LtshTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,13 +18,13 @@ import java.io.IOException;
*/
public class LtshTable implements Table {
- private DirectoryEntry de;
- private int version;
- private int numGlyphs;
- private int[] yPels;
-
+ private final DirectoryEntry de;
+ private final int version;
+ private final int numGlyphs;
+ private final int[] yPels;
+
/** Creates new LtshTable */
- protected LtshTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected LtshTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
version = di.readUnsignedShort();
numGlyphs = di.readUnsignedShort();
@@ -38,12 +38,14 @@ public class LtshTable implements Table {
* Get the table type, as a table directory value.
* @return The table type
*/
+ @Override
public int getType() {
return LTSH;
}
-
+
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'LTSH' Table - Linear Threshold Table\n-------------------------------------")
.append("\n 'LTSH' Version: ").append(version)
.append("\n Number of Glyphs: ").append(numGlyphs)
@@ -54,15 +56,16 @@ public class LtshTable implements Table {
}
return sb.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/MaxpTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/MaxpTable.java
index 0e8ec44c7..0e9a6177f 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/MaxpTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/MaxpTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -19,8 +19,8 @@ import jogamp.graph.font.typecast.ot.Fixed;
*/
public class MaxpTable implements Table {
- private DirectoryEntry de;
- private int versionNumber;
+ private final DirectoryEntry de;
+ private final int versionNumber;
private int numGlyphs;
private int maxPoints;
private int maxContours;
@@ -36,10 +36,10 @@ public class MaxpTable implements Table {
private int maxComponentElements;
private int maxComponentDepth;
- protected MaxpTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected MaxpTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
versionNumber = di.readInt();
-
+
// CFF fonts use version 0.5, TrueType fonts use version 1.0
if (versionNumber == 0x00005000) {
numGlyphs = di.readUnsignedShort();
@@ -121,12 +121,14 @@ public class MaxpTable implements Table {
return numGlyphs;
}
+ @Override
public int getType() {
return maxp;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'maxp' Table - Maximum Profile\n------------------------------")
.append("\n 'maxp' version: ").append(Fixed.floatValue(versionNumber))
.append("\n numGlyphs: ").append(numGlyphs);
@@ -149,15 +151,16 @@ public class MaxpTable implements Table {
}
return sb.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/NameRecord.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/NameRecord.java
index 268d6cfca..5ac9ada29 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/NameRecord.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/NameRecord.java
@@ -59,15 +59,15 @@ import java.io.IOException;
*/
public class NameRecord {
- private short _platformId;
- private short _encodingId;
- private short _languageId;
- private short _nameId;
- private short _stringLength;
- private short _stringOffset;
+ private final short _platformId;
+ private final short _encodingId;
+ private final short _languageId;
+ private final short _nameId;
+ private final short _stringLength;
+ private final short _stringOffset;
private String _record;
- protected NameRecord(DataInput di) throws IOException {
+ protected NameRecord(final DataInput di) throws IOException {
_platformId = di.readShort();
_encodingId = di.readShort();
_languageId = di.readShort();
@@ -75,33 +75,33 @@ public class NameRecord {
_stringLength = di.readShort();
_stringOffset = di.readShort();
}
-
+
public short getEncodingId() {
return _encodingId;
}
-
+
public short getLanguageId() {
return _languageId;
}
-
+
public short getNameId() {
return _nameId;
}
-
+
public short getPlatformId() {
return _platformId;
}
- public StringBuilder getRecordString(StringBuilder sb) {
+ public StringBuilder getRecordString(final StringBuilder sb) {
sb.append(_record);
return sb;
}
- protected void loadString(DataInput di) throws IOException {
- StringBuilder sb = new StringBuilder();
+ protected void loadString(final DataInput di) throws IOException {
+ final StringBuilder sb = new StringBuilder();
di.skipBytes(_stringOffset);
if (_platformId == ID.platformUnicode) {
-
+
// Unicode (big-endian)
for (int i = 0; i < _stringLength/2; i++) {
sb.append(di.readChar());
@@ -113,13 +113,13 @@ public class NameRecord {
sb.append((char) di.readByte());
}
} else if (_platformId == ID.platformISO) {
-
+
// ISO encoding, ASCII
for (int i = 0; i < _stringLength; i++) {
sb.append((char) di.readByte());
}
} else if (_platformId == ID.platformMicrosoft) {
-
+
// Microsoft encoding, Unicode
char c;
for (int i = 0; i < _stringLength/2; i++) {
@@ -130,9 +130,10 @@ public class NameRecord {
_record = sb.toString();
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
-
+ final StringBuilder sb = new StringBuilder();
+
sb.append(" Platform ID: ").append(_platformId)
.append("\n Specific ID: ").append(_encodingId)
.append("\n Language ID: ").append(_languageId)
@@ -140,7 +141,7 @@ public class NameRecord {
.append("\n Length: ").append(_stringLength)
.append("\n Offset: ").append(_stringOffset)
.append("\n\n").append(_record);
-
+
return sb.toString();
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/NameTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/NameTable.java
index 6daf2ad60..ba9292a4b 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/NameTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/NameTable.java
@@ -63,30 +63,30 @@ import java.io.IOException;
* @author <a href="mailto:[email protected]">David Schweinsberg</a>
*/
public class NameTable implements Table {
- private DirectoryEntry _de;
- private short _formatSelector;
- private short _numberOfNameRecords;
- private short _stringStorageOffset;
- private NameRecord[] _records;
-
- protected NameTable(DirectoryEntry de, DataInput di) throws IOException {
+ private final DirectoryEntry _de;
+ private final short _formatSelector;
+ private final short _numberOfNameRecords;
+ private final short _stringStorageOffset;
+ private final NameRecord[] _records;
+
+ protected NameTable(final DirectoryEntry de, final DataInput di) throws IOException {
_de = (DirectoryEntry) de.clone();
_formatSelector = di.readShort();
_numberOfNameRecords = di.readShort();
_stringStorageOffset = di.readShort();
_records = new NameRecord[_numberOfNameRecords];
-
+
// Load the records, which contain the encoding information and string
// offsets
for (int i = 0; i < _numberOfNameRecords; i++) {
_records[i] = new NameRecord(di);
}
-
+
// Load the string data into a buffer so the records can copy out the
// bits they are interested in
- byte[] buffer = new byte[_de.getLength() - _stringStorageOffset];
+ final byte[] buffer = new byte[_de.getLength() - _stringStorageOffset];
di.readFully(buffer);
-
+
// Now let the records get their hands on them
for (int i = 0; i < _numberOfNameRecords; i++) {
_records[i].loadString(
@@ -98,15 +98,15 @@ public class NameTable implements Table {
return _numberOfNameRecords;
}
-
- public NameRecord getRecord(int i) {
+
+ public NameRecord getRecord(final int i) {
if(_numberOfNameRecords > i) {
return _records[i];
}
return null;
}
- public StringBuilder getRecordsRecordString(StringBuilder sb, int i) {
+ public StringBuilder getRecordsRecordString(final StringBuilder sb, final int i) {
if(_numberOfNameRecords > i) {
_records[i].getRecordString(sb);
} else {
@@ -115,7 +115,7 @@ public class NameTable implements Table {
return sb;
}
- public StringBuilder getNamedRecordString(StringBuilder sb, short nameId) {
+ public StringBuilder getNamedRecordString(final StringBuilder sb, final short nameId) {
// Search for the first instance of this name ID
boolean done = false;
for (int i = 0; !done && i < _numberOfNameRecords; i++) {
@@ -130,18 +130,20 @@ public class NameTable implements Table {
return sb;
}
+ @Override
public int getType() {
return name;
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Os2Table.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Os2Table.java
index f4fa76e81..c91127303 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Os2Table.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Os2Table.java
@@ -59,46 +59,46 @@ import java.io.IOException;
*/
public class Os2Table implements Table {
- private DirectoryEntry _de;
- private int _version;
- private short _xAvgCharWidth;
- private int _usWeightClass;
- private int _usWidthClass;
- private short _fsType;
- private short _ySubscriptXSize;
- private short _ySubscriptYSize;
- private short _ySubscriptXOffset;
- private short _ySubscriptYOffset;
- private short _ySuperscriptXSize;
- private short _ySuperscriptYSize;
- private short _ySuperscriptXOffset;
- private short _ySuperscriptYOffset;
- private short _yStrikeoutSize;
- private short _yStrikeoutPosition;
- private short _sFamilyClass;
- private Panose _panose;
- private int _ulUnicodeRange1;
- private int _ulUnicodeRange2;
- private int _ulUnicodeRange3;
- private int _ulUnicodeRange4;
- private int _achVendorID;
- private short _fsSelection;
- private int _usFirstCharIndex;
- private int _usLastCharIndex;
- private short _sTypoAscender;
- private short _sTypoDescender;
- private short _sTypoLineGap;
- private int _usWinAscent;
- private int _usWinDescent;
- private int _ulCodePageRange1;
- private int _ulCodePageRange2;
+ private final DirectoryEntry _de;
+ private final int _version;
+ private final short _xAvgCharWidth;
+ private final int _usWeightClass;
+ private final int _usWidthClass;
+ private final short _fsType;
+ private final short _ySubscriptXSize;
+ private final short _ySubscriptYSize;
+ private final short _ySubscriptXOffset;
+ private final short _ySubscriptYOffset;
+ private final short _ySuperscriptXSize;
+ private final short _ySuperscriptYSize;
+ private final short _ySuperscriptXOffset;
+ private final short _ySuperscriptYOffset;
+ private final short _yStrikeoutSize;
+ private final short _yStrikeoutPosition;
+ private final short _sFamilyClass;
+ private final Panose _panose;
+ private final int _ulUnicodeRange1;
+ private final int _ulUnicodeRange2;
+ private final int _ulUnicodeRange3;
+ private final int _ulUnicodeRange4;
+ private final int _achVendorID;
+ private final short _fsSelection;
+ private final int _usFirstCharIndex;
+ private final int _usLastCharIndex;
+ private final short _sTypoAscender;
+ private final short _sTypoDescender;
+ private final short _sTypoLineGap;
+ private final int _usWinAscent;
+ private final int _usWinDescent;
+ private final int _ulCodePageRange1;
+ private final int _ulCodePageRange2;
private short _sxHeight;
private short _sCapHeight;
private int _usDefaultChar;
private int _usBreakChar;
private int _usMaxContext;
- protected Os2Table(DirectoryEntry de, DataInput di) throws IOException {
+ protected Os2Table(final DirectoryEntry de, final DataInput di) throws IOException {
this._de = (DirectoryEntry) de.clone();
_version = di.readUnsignedShort();
_xAvgCharWidth = di.readShort();
@@ -116,7 +116,7 @@ public class Os2Table implements Table {
_yStrikeoutSize = di.readShort();
_yStrikeoutPosition = di.readShort();
_sFamilyClass = di.readShort();
- byte[] buf = new byte[10];
+ final byte[] buf = new byte[10];
di.readFully(buf);
_panose = new Panose(buf);
_ulUnicodeRange1 = di.readInt();
@@ -134,7 +134,7 @@ public class Os2Table implements Table {
_usWinDescent = di.readUnsignedShort();
_ulCodePageRange1 = di.readInt();
_ulCodePageRange2 = di.readInt();
-
+
// OpenType 1.3
if (_version == 2) {
_sxHeight = di.readShort();
@@ -276,27 +276,29 @@ public class Os2Table implements Table {
public short getXHeight() {
return _sxHeight;
}
-
+
public short getCapHeight() {
return _sCapHeight;
}
-
+
public int getDefaultChar() {
return _usDefaultChar;
}
-
+
public int getBreakChar() {
return _usBreakChar;
}
-
+
public int getMaxContext() {
return _usMaxContext;
}
+ @Override
public int getType() {
return OS_2;
}
+ @Override
public String toString() {
return new StringBuilder()
.append("'OS/2' Table - OS/2 and Windows Metrics\n---------------------------------------")
@@ -335,7 +337,7 @@ public class Os2Table implements Table {
.append("\n CodePage Range 2( Bits 32- 63 ): ").append(Integer.toHexString(_ulCodePageRange2).toUpperCase())
.toString();
}
-
+
private String getVendorIDAsString() {
return new StringBuilder()
.append((char)((_achVendorID>>24)&0xff))
@@ -344,13 +346,14 @@ public class Os2Table implements Table {
.append((char)((_achVendorID)&0xff))
.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Panose.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Panose.java
index 6127140d1..493f43baa 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Panose.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Panose.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -26,7 +26,7 @@ public class Panose {
byte bXHeight = 0;
/** Creates new Panose */
- public Panose(byte[] panose) {
+ public Panose(final byte[] panose) {
bFamilyType = panose[0];
bSerifStyle = panose[1];
bWeight = panose[2];
@@ -42,11 +42,11 @@ public class Panose {
public byte getFamilyType() {
return bFamilyType;
}
-
+
public byte getSerifStyle() {
return bSerifStyle;
}
-
+
public byte getWeight() {
return bWeight;
}
@@ -54,33 +54,34 @@ public class Panose {
public byte getProportion() {
return bProportion;
}
-
+
public byte getContrast() {
return bContrast;
}
-
+
public byte getStrokeVariation() {
return bStrokeVariation;
}
-
+
public byte getArmStyle() {
return bArmStyle;
}
-
+
public byte getLetterForm() {
return bLetterform;
}
-
+
public byte getMidline() {
return bMidline;
}
-
+
public byte getXHeight() {
return bXHeight;
}
-
+
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append(String.valueOf(bFamilyType)).append(" ")
.append(String.valueOf(bSerifStyle)).append(" ")
.append(String.valueOf(bWeight)).append(" ")
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PcltTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PcltTable.java
index f9dcf2ce7..63399cf0e 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PcltTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PcltTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,25 +18,25 @@ import java.io.IOException;
*/
public class PcltTable implements Table {
- private DirectoryEntry de;
- private int version;
- private long fontNumber;
- private int pitch;
- private int xHeight;
- private int style;
- private int typeFamily;
- private int capHeight;
- private int symbolSet;
- private char[] typeface = new char[16];
- private short[] characterComplement = new short[8];
- private char[] fileName = new char[6];
- private short strokeWeight;
- private short widthType;
- private byte serifStyle;
- private byte reserved;
+ private final DirectoryEntry de;
+ private final int version;
+ private final long fontNumber;
+ private final int pitch;
+ private final int xHeight;
+ private final int style;
+ private final int typeFamily;
+ private final int capHeight;
+ private final int symbolSet;
+ private final char[] typeface = new char[16];
+ private final short[] characterComplement = new short[8];
+ private final char[] fileName = new char[6];
+ private final short strokeWeight;
+ private final short widthType;
+ private final byte serifStyle;
+ private final byte reserved;
/** Creates new PcltTable */
- protected PcltTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected PcltTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
version = di.readInt();
fontNumber = di.readInt();
@@ -65,10 +65,12 @@ public class PcltTable implements Table {
* Get the table type, as a table directory value.
* @return The table type
*/
+ @Override
public int getType() {
return PCLT;
}
-
+
+ @Override
public String toString() {
return new StringBuilder()
.append("'PCLT' Table - Printer Command Language Table\n---------------------------------------------")
@@ -91,15 +93,16 @@ public class PcltTable implements Table {
.append("\n reserved: ").append(reserved)
.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PostTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PostTable.java
index c913b4c71..f4dd31465 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PostTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PostTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -284,24 +284,24 @@ public class PostTable implements Table {
"" // 257
};
- private DirectoryEntry de;
- private int version;
- private int italicAngle;
- private short underlinePosition;
- private short underlineThickness;
- private int isFixedPitch;
- private int minMemType42;
- private int maxMemType42;
- private int minMemType1;
- private int maxMemType1;
-
+ private final DirectoryEntry de;
+ private final int version;
+ private final int italicAngle;
+ private final short underlinePosition;
+ private final short underlineThickness;
+ private final int isFixedPitch;
+ private final int minMemType42;
+ private final int maxMemType42;
+ private final int minMemType1;
+ private final int maxMemType1;
+
// v2
private int numGlyphs;
private int[] glyphNameIndex;
private String[] psGlyphName;
/** Creates new PostTable */
- protected PostTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected PostTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
version = di.readInt();
italicAngle = di.readInt();
@@ -312,7 +312,7 @@ public class PostTable implements Table {
maxMemType42 = di.readInt();
minMemType1 = di.readInt();
maxMemType1 = di.readInt();
-
+
if (version == 0x00020000) {
numGlyphs = di.readUnsignedShort();
glyphNameIndex = new int[numGlyphs];
@@ -324,14 +324,14 @@ public class PostTable implements Table {
h -= 257;
psGlyphName = new String[h];
for (int i = 0; i < h; i++) {
- int len = di.readUnsignedByte();
- byte[] buf = new byte[len];
+ final int len = di.readUnsignedByte();
+ final byte[] buf = new byte[len];
di.readFully(buf);
psGlyphName[i] = new String(buf);
}
}
- } else if (version == 0x00025000) {
- } else if (version == 0x00030000) {
+ // } else if (version == 0x00025000) {
+ // } else if (version == 0x00030000) {
}
}
@@ -349,7 +349,7 @@ public class PostTable implements Table {
return high;
}
- public String getGlyphName(int i) {
+ public String getGlyphName(final int i) {
if (version == 0x00020000) {
return (glyphNameIndex[i] > 257)
? psGlyphName[glyphNameIndex[i] - 258]
@@ -359,23 +359,25 @@ public class PostTable implements Table {
}
}
- private boolean isMacGlyphName(int i) {
+ private boolean isMacGlyphName(final int i) {
if (version == 0x00020000) {
return glyphNameIndex[i] <= 257;
} else {
return false;
}
}
-
+
/** Get the table type, as a table directory value.
* @return The table type
*/
+ @Override
public int getType() {
return post;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'post' Table - PostScript Metrics\n---------------------------------\n")
.append("\n 'post' version: ").append(Fixed.floatValue(version))
.append("\n italicAngle: ").append(Fixed.floatValue(italicAngle))
@@ -409,15 +411,16 @@ public class PostTable implements Table {
}
return sb.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PrepTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PrepTable.java
index aac10c539..039789d62 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PrepTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/PrepTable.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -19,29 +19,32 @@ import jogamp.graph.font.typecast.ot.Disassembler;
*/
public class PrepTable extends Program implements Table {
- private DirectoryEntry de;
+ private final DirectoryEntry de;
- public PrepTable(DirectoryEntry de, DataInput di) throws IOException {
+ public PrepTable(final DirectoryEntry de, final DataInput di) throws IOException {
this.de = (DirectoryEntry) de.clone();
readInstructions(di, de.getLength());
}
+ @Override
public int getType() {
return prep;
}
+ @Override
public String toString() {
return Disassembler.disassemble(getInstructions(), 0);
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return de;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Program.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Program.java
index 28c148c2b..c0d2c1b9d 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Program.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Program.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -23,7 +23,7 @@ public abstract class Program {
return instructions;
}
- protected void readInstructions(DataInput di, int count) throws IOException {
+ protected void readInstructions(final DataInput di, final int count) throws IOException {
instructions = new short[count];
for (int i = 0; i < count; i++) {
instructions[i] = (short) di.readUnsignedByte();
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/RangeRecord.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/RangeRecord.java
index 72d703bb4..417779703 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/RangeRecord.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/RangeRecord.java
@@ -61,22 +61,22 @@ import java.io.IOException;
*/
public class RangeRecord {
- private int _start;
- private int _end;
- private int _startCoverageIndex;
+ private final int _start;
+ private final int _end;
+ private final int _startCoverageIndex;
/** Creates new RangeRecord */
- public RangeRecord(DataInput di) throws IOException {
+ public RangeRecord(final DataInput di) throws IOException {
_start = di.readUnsignedShort();
_end = di.readUnsignedShort();
_startCoverageIndex = di.readUnsignedShort();
}
- public boolean isInRange(int glyphId) {
+ public boolean isInRange(final int glyphId) {
return (_start <= glyphId && glyphId <= _end);
}
-
- public int getCoverageIndex(int glyphId) {
+
+ public int getCoverageIndex(final int glyphId) {
if (isInRange(glyphId)) {
return _startCoverageIndex + glyphId - _start;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Script.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Script.java
index eb534b5dd..8846de5f0 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Script.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Script.java
@@ -60,19 +60,19 @@ import java.io.IOException;
*/
public class Script {
- private int _defaultLangSysOffset;
- private int _langSysCount;
+ private final int _defaultLangSysOffset;
+ private final int _langSysCount;
private LangSysRecord[] _langSysRecords;
private LangSys _defaultLangSys;
private LangSys[] _langSys;
-
+
/** Creates new ScriptTable */
- protected Script(DataInputStream dis, int offset) throws IOException {
+ protected Script(final DataInputStream dis, final int offset) throws IOException {
// Ensure we're in the right place
dis.reset();
dis.skipBytes(offset);
-
+
// Start reading
_defaultLangSysOffset = dis.readUnsignedShort();
_langSysCount = dis.readUnsignedShort();
@@ -102,8 +102,8 @@ public class Script {
public int getLangSysCount() {
return _langSysCount;
}
-
- public LangSysRecord getLangSysRecord(int i) {
+
+ public LangSysRecord getLangSysRecord(final int i) {
return _langSysRecords[i];
}
@@ -111,7 +111,7 @@ public class Script {
return _defaultLangSys;
}
- public LangSys getLangSys(int i) {
+ public LangSys getLangSys(final int i) {
return _langSys[i];
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ScriptList.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ScriptList.java
index 4af62b0ee..1c1be0d2b 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ScriptList.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ScriptList.java
@@ -61,16 +61,16 @@ import java.io.IOException;
public class ScriptList {
private int _scriptCount = 0;
- private ScriptRecord[] _scriptRecords;
- private Script[] _scripts;
-
+ private final ScriptRecord[] _scriptRecords;
+ private final Script[] _scripts;
+
/** Creates new ScriptList */
- protected ScriptList(DataInputStream dis, int offset) throws IOException {
-
+ protected ScriptList(final DataInputStream dis, final int offset) throws IOException {
+
// Ensure we're in the right place
dis.reset();
dis.skipBytes(offset);
-
+
// Start reading
_scriptCount = dis.readUnsignedShort();
_scriptRecords = new ScriptRecord[_scriptCount];
@@ -86,20 +86,20 @@ public class ScriptList {
public int getScriptCount() {
return _scriptCount;
}
-
- public ScriptRecord getScriptRecord(int i) {
+
+ public ScriptRecord getScriptRecord(final int i) {
return _scriptRecords[i];
}
-
- public Script getScript(int i) {
+
+ public Script getScript(final int i) {
return _scripts[i];
}
-
- public Script findScript(String tag) {
+
+ public Script findScript(final String tag) {
if (tag.length() != 4) {
return null;
}
- int tagVal = ((tag.charAt(0)<<24)
+ final int tagVal = ((tag.charAt(0)<<24)
| (tag.charAt(1)<<16)
| (tag.charAt(2)<<8)
| tag.charAt(3));
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ScriptRecord.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ScriptRecord.java
index 5da0608dd..18eefe5a7 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ScriptRecord.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/ScriptRecord.java
@@ -60,11 +60,11 @@ import java.io.IOException;
*/
public class ScriptRecord {
- private int _tag;
- private int _offset;
-
+ private final int _tag;
+ private final int _offset;
+
/** Creates new ScriptRecord */
- protected ScriptRecord(DataInput di) throws IOException {
+ protected ScriptRecord(final DataInput di) throws IOException {
_tag = di.readInt();
_offset = di.readUnsignedShort();
}
@@ -72,7 +72,7 @@ public class ScriptRecord {
public int getTag() {
return _tag;
}
-
+
public int getOffset() {
return _offset;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SignatureBlock.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SignatureBlock.java
index 5a5de119f..e6841b94c 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SignatureBlock.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SignatureBlock.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -18,13 +18,13 @@ import java.io.DataInput;
*/
public class SignatureBlock {
- private int reserved1;
- private int reserved2;
- private int signatureLen;
- private byte[] signature;
-
+ private final int reserved1;
+ private final int reserved2;
+ private final int signatureLen;
+ private final byte[] signature;
+
/** Creates new SignatureBlock */
- protected SignatureBlock(DataInput di) throws IOException {
+ protected SignatureBlock(final DataInput di) throws IOException {
reserved1 = di.readUnsignedShort();
reserved2 = di.readUnsignedShort();
signatureLen = di.readInt();
@@ -32,8 +32,9 @@ public class SignatureBlock {
di.readFully(signature);
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
for (int i = 0; i < signatureLen; i += 16) {
if (signatureLen - i >= 16) {
sb.append(new String(signature, i, 16)).append("\n");
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubst.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubst.java
index 8c56a740f..c398b4fbb 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubst.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubst.java
@@ -63,12 +63,12 @@ public abstract class SingleSubst extends LookupSubtable {
public abstract int getFormat();
public abstract int substitute(int glyphId);
-
- public static SingleSubst read(DataInputStream dis, int offset) throws IOException {
+
+ public static SingleSubst read(final DataInputStream dis, final int offset) throws IOException {
SingleSubst s = null;
dis.reset();
dis.skipBytes(offset);
- int format = dis.readUnsignedShort();
+ final int format = dis.readUnsignedShort();
if (format == 1) {
s = new SingleSubstFormat1(dis, offset);
} else if (format == 2) {
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubstFormat1.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubstFormat1.java
index 99b85f35c..b2e65dded 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubstFormat1.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubstFormat1.java
@@ -60,12 +60,12 @@ import java.io.IOException;
*/
public class SingleSubstFormat1 extends SingleSubst {
- private int _coverageOffset;
- private short _deltaGlyphID;
- private Coverage _coverage;
+ private final int _coverageOffset;
+ private final short _deltaGlyphID;
+ private final Coverage _coverage;
/** Creates new SingleSubstFormat1 */
- protected SingleSubstFormat1(DataInputStream dis, int offset) throws IOException {
+ protected SingleSubstFormat1(final DataInputStream dis, final int offset) throws IOException {
_coverageOffset = dis.readUnsignedShort();
_deltaGlyphID = dis.readShort();
dis.reset();
@@ -73,18 +73,21 @@ public class SingleSubstFormat1 extends SingleSubst {
_coverage = Coverage.read(dis);
}
+ @Override
public int getFormat() {
return 1;
}
- public int substitute(int glyphId) {
- int i = _coverage.findGlyph(glyphId);
+ @Override
+ public int substitute(final int glyphId) {
+ final int i = _coverage.findGlyph(glyphId);
if (i > -1) {
return glyphId + _deltaGlyphID;
}
return glyphId;
}
-
+
+ @Override
public String getTypeAsString() {
return "SingleSubstFormat1";
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubstFormat2.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubstFormat2.java
index cd3b6d147..449c14c7a 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubstFormat2.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/SingleSubstFormat2.java
@@ -60,13 +60,13 @@ import java.io.IOException;
*/
public class SingleSubstFormat2 extends SingleSubst {
- private int _coverageOffset;
- private int _glyphCount;
- private int[] _substitutes;
- private Coverage _coverage;
+ private final int _coverageOffset;
+ private final int _glyphCount;
+ private final int[] _substitutes;
+ private final Coverage _coverage;
/** Creates new SingleSubstFormat2 */
- protected SingleSubstFormat2(DataInputStream dis, int offset) throws IOException {
+ protected SingleSubstFormat2(final DataInputStream dis, final int offset) throws IOException {
_coverageOffset = dis.readUnsignedShort();
_glyphCount = dis.readUnsignedShort();
_substitutes = new int[_glyphCount];
@@ -78,20 +78,23 @@ public class SingleSubstFormat2 extends SingleSubst {
_coverage = Coverage.read(dis);
}
+ @Override
public int getFormat() {
return 2;
}
- public int substitute(int glyphId) {
- int i = _coverage.findGlyph(glyphId);
+ @Override
+ public int substitute(final int glyphId) {
+ final int i = _coverage.findGlyph(glyphId);
if (i > -1) {
return _substitutes[i];
}
return glyphId;
}
+ @Override
public String getTypeAsString() {
return "SingleSubstFormat2";
- }
+ }
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TTCHeader.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TTCHeader.java
index b801517f8..a6ec61887 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TTCHeader.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TTCHeader.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -17,19 +17,19 @@ import java.io.IOException;
* @author <a href="mailto:[email protected]">David Schweinsberg</a>
*/
public class TTCHeader {
-
+
public static final int ttcf = 0x74746366;
- private int ttcTag;
- private int version;
- private int directoryCount;
- private int[] tableDirectory;
+ private final int ttcTag;
+ private final int version;
+ private final int directoryCount;
+ private final int[] tableDirectory;
private int dsigTag;
- private int dsigLength;
- private int dsigOffset;
+ private final int dsigLength;
+ private final int dsigOffset;
/** Creates new TTCHeader */
- public TTCHeader(DataInput di) throws IOException {
+ public TTCHeader(final DataInput di) throws IOException {
ttcTag = di.readInt();
version = di.readInt();
directoryCount = di.readInt();
@@ -47,13 +47,13 @@ public class TTCHeader {
public int getDirectoryCount() {
return directoryCount;
}
-
- public int getTableDirectory(int i) {
+
+ public int getTableDirectory(final int i) {
return tableDirectory[i];
}
- public static boolean isTTC(DataInput di) throws IOException {
- int ttcTag = di.readInt();
+ public static boolean isTTC(final DataInput di) throws IOException {
+ final int ttcTag = di.readInt();
return ttcTag == ttcf;
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Table.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Table.java
index 624f47bef..30fd2f457 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Table.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/Table.java
@@ -1,9 +1,9 @@
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
+ * ------------------------------------------------------------------------- *
+ * This software is published under the terms of the Apache Software License *
+ * version 1.1, a copy of which has been included with this distribution in *
+ * the LICENSE file. *
*****************************************************************************/
package jogamp.graph.font.typecast.ot.table;
@@ -51,7 +51,7 @@ public interface Table {
public static final int vmtx = 0x766d7478; // Vertical Metrics
public static final String notAvailable = "n/a";
-
+
/**
* Get the table type, as a table directory value.
* @return The table type
@@ -65,5 +65,5 @@ public interface Table {
* @return A directory entry
*/
public DirectoryEntry getDirectoryEntry();
-
+
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableDirectory.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableDirectory.java
index bacc26d30..b9448cc72 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableDirectory.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableDirectory.java
@@ -66,9 +66,9 @@ public class TableDirectory {
private short _searchRange = 0;
private short _entrySelector = 0;
private short _rangeShift = 0;
- private DirectoryEntry[] _entries;
+ private final DirectoryEntry[] _entries;
- public TableDirectory(DataInput di) throws IOException {
+ public TableDirectory(final DataInput di) throws IOException {
_version = di.readInt();
_numTables = di.readShort();
_searchRange = di.readShort();
@@ -80,11 +80,11 @@ public class TableDirectory {
}
}
- public DirectoryEntry getEntry(int index) {
+ public DirectoryEntry getEntry(final int index) {
return _entries[index];
}
- public DirectoryEntry getEntryByTag(int tag) {
+ public DirectoryEntry getEntryByTag(final int tag) {
for (int i = 0; i < _numTables; i++) {
if (_entries[i].getTag() == tag) {
return _entries[i];
@@ -112,9 +112,10 @@ public class TableDirectory {
public int getVersion() {
return _version;
}
-
+
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder()
+ final StringBuilder sb = new StringBuilder()
.append("Offset Table\n------ -----")
.append("\n sfnt version: ").append(Fixed.floatValue(_version))
.append("\n numTables = ").append(_numTables)
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableException.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableException.java
index 7749ea856..e0433f098 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableException.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableException.java
@@ -26,7 +26,7 @@ package jogamp.graph.font.typecast.ot.table;
* @version $Id: TableException.java,v 1.1.1.1 2004-12-05 23:15:00 davidsch Exp $
*/
public class TableException extends java.lang.Exception {
-
+
private static final long serialVersionUID = 1L;
/**
@@ -34,13 +34,13 @@ public class TableException extends java.lang.Exception {
*/
public TableException() {
}
-
-
+
+
/**
* Constructs an instance of <code>TableException</code> with the specified detail message.
* @param msg the detail message.
*/
- public TableException(String msg) {
+ public TableException(final String msg) {
super(msg);
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableFactory.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableFactory.java
index 998ce08e3..d24f3b3ae 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableFactory.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/TableFactory.java
@@ -47,7 +47,7 @@
Apache Software Foundation, please see <http://www.apache.org/>.
*/
-
+
package jogamp.graph.font.typecast.ot.table;
import java.io.DataInputStream;
@@ -56,7 +56,7 @@ import java.io.IOException;
import jogamp.graph.font.typecast.ot.OTFont;
import jogamp.graph.font.typecast.ot.OTFontCollection;
-/**
+/**
*
* @version $Id: TableFactory.java,v 1.7 2007-02-05 12:39:51 davidsch Exp $
* @author <a href="mailto:[email protected]">David Schweinsberg</a>
@@ -64,12 +64,12 @@ import jogamp.graph.font.typecast.ot.OTFontCollection;
public class TableFactory {
public static Table create(
- OTFontCollection fc,
- OTFont font,
- DirectoryEntry de,
- DataInputStream dis) throws IOException {
+ final OTFontCollection fc,
+ final OTFont font,
+ final DirectoryEntry de,
+ final DataInputStream dis) throws IOException {
Table t = null;
-
+
// First, if we have a font collection, look for the table there
if (fc != null) {
t = fc.getTable(de);
@@ -77,7 +77,7 @@ public class TableFactory {
return t;
}
}
-
+
// Create the table
switch (de.getTag()) {
case Table.BASE:
@@ -175,7 +175,7 @@ public class TableFactory {
t = new VmtxTable(de, dis, font.getVheaTable(), font.getMaxpTable());
break;
}
-
+
// If we have a font collection, add this table to it
if ((fc != null) && (t != null)) {
fc.addTable(t);
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VdmxTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VdmxTable.java
index 80579f5cd..679502e84 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VdmxTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VdmxTable.java
@@ -30,14 +30,14 @@ import java.io.IOException;
*/
public class VdmxTable implements Table {
- private class Ratio {
-
- private byte _bCharSet;
- private byte _xRatio;
- private byte _yStartRatio;
- private byte _yEndRatio;
-
- protected Ratio(DataInput di) throws IOException {
+ static class Ratio {
+
+ private final byte _bCharSet;
+ private final byte _xRatio;
+ private final byte _yStartRatio;
+ private final byte _yEndRatio;
+
+ protected Ratio(final DataInput di) throws IOException {
_bCharSet = di.readByte();
_xRatio = di.readByte();
_yStartRatio = di.readByte();
@@ -47,27 +47,27 @@ public class VdmxTable implements Table {
public byte getBCharSet() {
return _bCharSet;
}
-
+
public byte getXRatio() {
return _xRatio;
}
-
+
public byte getYStartRatio() {
return _yStartRatio;
}
-
+
public byte getYEndRatio() {
return _yEndRatio;
}
}
-
- private class VTableRecord {
-
- private int _yPelHeight;
- private short _yMax;
- private short _yMin;
-
- protected VTableRecord(DataInput di) throws IOException {
+
+ static class VTableRecord {
+
+ private final int _yPelHeight;
+ private final short _yMax;
+ private final short _yMin;
+
+ protected VTableRecord(final DataInput di) throws IOException {
_yPelHeight = di.readUnsignedShort();
_yMax = di.readShort();
_yMin = di.readShort();
@@ -76,24 +76,24 @@ public class VdmxTable implements Table {
public int getYPelHeight() {
return _yPelHeight;
}
-
+
public short getYMax() {
return _yMax;
}
-
+
public short getYMin() {
return _yMin;
}
}
-
- private class Group {
-
- private int _recs;
- private int _startsz;
- private int _endsz;
- private VTableRecord[] _entry;
-
- protected Group(DataInput di) throws IOException {
+
+ static class Group {
+
+ private final int _recs;
+ private final int _startsz;
+ private final int _endsz;
+ private final VTableRecord[] _entry;
+
+ protected Group(final DataInput di) throws IOException {
_recs = di.readUnsignedShort();
_startsz = di.readUnsignedByte();
_endsz = di.readUnsignedByte();
@@ -106,30 +106,30 @@ public class VdmxTable implements Table {
public int getRecs() {
return _recs;
}
-
+
public int getStartSZ() {
return _startsz;
}
-
+
public int getEndSZ() {
return _endsz;
}
-
+
public VTableRecord[] getEntry() {
return _entry;
}
}
-
- private DirectoryEntry _de;
- private int _version;
- private int _numRecs;
- private int _numRatios;
- private Ratio[] _ratRange;
- private int _offset[];
- private Group[] _groups;
-
+
+ private final DirectoryEntry _de;
+ private final int _version;
+ private final int _numRecs;
+ private final int _numRatios;
+ private final Ratio[] _ratRange;
+ private final int _offset[];
+ private final Group[] _groups;
+
/** Creates a new instance of VdmxTable */
- protected VdmxTable(DirectoryEntry de, DataInput di) throws IOException {
+ protected VdmxTable(final DirectoryEntry de, final DataInput di) throws IOException {
_de = (DirectoryEntry) de.clone();
_version = di.readUnsignedShort();
_numRecs = di.readUnsignedShort();
@@ -147,13 +147,15 @@ public class VdmxTable implements Table {
_groups[i] = new Group(di);
}
}
-
+
+ @Override
public int getType() {
return VDMX;
}
-
+
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'VDMX' Table - Precomputed Vertical Device Metrics\n")
.append("--------------------------------------------------\n")
.append(" Version: ").append(_version).append("\n")
@@ -170,7 +172,7 @@ public class VdmxTable implements Table {
sb.append("\n VDMX Height Record Groups\n")
.append(" -------------------------\n");
for (int i = 0; i < _numRecs; ++i) {
- Group group = _groups[i];
+ final Group group = _groups[i];
sb.append(" ").append(i + 1)
.append(". Number of Hgt Records ").append(group.getRecs()).append("\n")
.append(" Starting Y Pel Height ").append(group.getStartSZ()).append("\n")
@@ -191,6 +193,7 @@ public class VdmxTable implements Table {
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VheaTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VheaTable.java
index 19c91765b..cef7b5297 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VheaTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VheaTable.java
@@ -32,21 +32,21 @@ import jogamp.graph.font.typecast.ot.Fixed;
*/
public class VheaTable implements Table {
- private DirectoryEntry _de;
- private int _version;
- private short _ascent;
- private short _descent;
- private short _lineGap;
- private short _advanceHeightMax;
- private short _minTopSideBearing;
- private short _minBottomSideBearing;
- private short _yMaxExtent;
- private short _caretSlopeRise;
- private short _caretSlopeRun;
- private short _metricDataFormat;
- private int _numberOfLongVerMetrics;
-
- protected VheaTable(DirectoryEntry de, DataInput di) throws IOException {
+ private final DirectoryEntry _de;
+ private final int _version;
+ private final short _ascent;
+ private final short _descent;
+ private final short _lineGap;
+ private final short _advanceHeightMax;
+ private final short _minTopSideBearing;
+ private final short _minBottomSideBearing;
+ private final short _yMaxExtent;
+ private final short _caretSlopeRise;
+ private final short _caretSlopeRun;
+ private final short _metricDataFormat;
+ private final int _numberOfLongVerMetrics;
+
+ protected VheaTable(final DirectoryEntry de, final DataInput di) throws IOException {
_de = (DirectoryEntry) de.clone();
_version = di.readInt();
_ascent = di.readShort();
@@ -105,6 +105,7 @@ public class VheaTable implements Table {
return _numberOfLongVerMetrics;
}
+ @Override
public int getType() {
return vhea;
}
@@ -113,6 +114,7 @@ public class VheaTable implements Table {
return _yMaxExtent;
}
+ @Override
public String toString() {
return new StringBuilder()
.append("'vhea' Table - Vertical Header\n------------------------------")
@@ -135,13 +137,14 @@ public class VheaTable implements Table {
.append("\n numOf_LongVerMetrics: ").append(_numberOfLongVerMetrics)
.toString();
}
-
+
/**
* Get a directory entry for this table. This uniquely identifies the
* table in collections where there may be more than one instance of a
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VmtxTable.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VmtxTable.java
index 348405380..b76ed7e15 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VmtxTable.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/VmtxTable.java
@@ -30,15 +30,15 @@ import java.io.IOException;
*/
public class VmtxTable implements Table {
- private DirectoryEntry _de;
+ private final DirectoryEntry _de;
private int[] _vMetrics = null;
private short[] _topSideBearing = null;
protected VmtxTable(
- DirectoryEntry de,
- DataInput di,
- VheaTable vhea,
- MaxpTable maxp) throws IOException {
+ final DirectoryEntry de,
+ final DataInput di,
+ final VheaTable vhea,
+ final MaxpTable maxp) throws IOException {
_de = (DirectoryEntry) de.clone();
_vMetrics = new int[vhea.getNumberOfLongVerMetrics()];
for (int i = 0; i < vhea.getNumberOfLongVerMetrics(); ++i) {
@@ -48,14 +48,14 @@ public class VmtxTable implements Table {
| di.readUnsignedByte()<<8
| di.readUnsignedByte();
}
- int tsbCount = maxp.getNumGlyphs() - vhea.getNumberOfLongVerMetrics();
+ final int tsbCount = maxp.getNumGlyphs() - vhea.getNumberOfLongVerMetrics();
_topSideBearing = new short[tsbCount];
for (int i = 0; i < tsbCount; ++i) {
_topSideBearing[i] = di.readShort();
}
}
- public int getAdvanceHeight(int i) {
+ public int getAdvanceHeight(final int i) {
if (_vMetrics == null) {
return 0;
}
@@ -66,7 +66,7 @@ public class VmtxTable implements Table {
}
}
- public short getTopSideBearing(int i) {
+ public short getTopSideBearing(final int i) {
if (_vMetrics == null) {
return 0;
}
@@ -77,12 +77,14 @@ public class VmtxTable implements Table {
}
}
+ @Override
public int getType() {
return vmtx;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("'vmtx' Table - Vertical Metrics\n-------------------------------\n");
sb.append("Size = ").append(_de.getLength()).append(" bytes, ")
.append(_vMetrics.length).append(" entries\n");
@@ -106,6 +108,7 @@ public class VmtxTable implements Table {
* particular table.
* @return A directory entry
*/
+ @Override
public DirectoryEntry getDirectoryEntry() {
return _de;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/t2/T2Interpreter.java b/src/jogl/classes/jogamp/graph/font/typecast/t2/T2Interpreter.java
index 887f8c34f..80d76a7f8 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/t2/T2Interpreter.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/t2/T2Interpreter.java
@@ -34,32 +34,32 @@ import jogamp.graph.font.typecast.ot.table.CharstringType2;
* @version $Id: T2Interpreter.java,v 1.2 2007-07-26 11:10:18 davidsch Exp $
*/
public class T2Interpreter {
-
+
private static final int ARGUMENT_STACK_LIMIT = 48;
private static final int SUBR_STACK_LIMIT = 10;
private static final int TRANSIENT_ARRAY_ELEMENT_COUNT = 32;
-
- private Number[] _argStack = new Number[ARGUMENT_STACK_LIMIT];
+
+ private final Number[] _argStack = new Number[ARGUMENT_STACK_LIMIT];
private int _argStackIndex = 0;
- private int[] _subrStack = new int[SUBR_STACK_LIMIT];
+ private final int[] _subrStack = new int[SUBR_STACK_LIMIT];
private int _subrStackIndex = 0;
- private Number[] _transientArray = new Number[TRANSIENT_ARRAY_ELEMENT_COUNT];
-
+ private final Number[] _transientArray = new Number[TRANSIENT_ARRAY_ELEMENT_COUNT];
+
private ArrayList<Point> _points;
/** Creates a new instance of T2Interpreter */
public T2Interpreter() {
}
-
+
/**
* Moves the current point to a position at the relative coordinates
* (dx1, dy1).
*/
private void _rmoveto() {
- int dy1 = popArg().intValue();
- int dx1 = popArg().intValue();
+ final int dy1 = popArg().intValue();
+ final int dx1 = popArg().intValue();
clearArg();
- Point lastPoint = getLastPoint();
+ final Point lastPoint = getLastPoint();
moveTo(lastPoint.x + dx1, lastPoint.y + dy1);
}
@@ -67,22 +67,22 @@ public class T2Interpreter {
* Moves the current point dx1 units in the horizontal direction.
*/
private void _hmoveto() {
- int dx1 = popArg().intValue();
+ final int dx1 = popArg().intValue();
clearArg();
- Point lastPoint = getLastPoint();
+ final Point lastPoint = getLastPoint();
moveTo(lastPoint.x + dx1, lastPoint.y);
}
-
+
/**
* Moves the current point dy1 units in the vertical direction.
*/
private void _vmoveto() {
- int dy1 = popArg().intValue();
+ final int dy1 = popArg().intValue();
clearArg();
- Point lastPoint = getLastPoint();
+ final Point lastPoint = getLastPoint();
moveTo(lastPoint.x, lastPoint.y + dy1);
}
-
+
/**
* Appends a line from the current point to a position at the
* relative coordinates dxa, dya. Additional rlineto operations are
@@ -90,20 +90,20 @@ public class T2Interpreter {
* lines is determined from the number of arguments on the stack.
*/
private void _rlineto() {
- int count = getArgCount() / 2;
- int[] dx = new int[count];
- int[] dy = new int[count];
+ final int count = getArgCount() / 2;
+ final int[] dx = new int[count];
+ final int[] dy = new int[count];
for (int i = 0; i < count; ++i) {
dy[count - i - 1] = popArg().intValue();
dx[count - i - 1] = popArg().intValue();
}
for (int i = 0; i < count; ++i) {
- Point lastPoint = getLastPoint();
+ final Point lastPoint = getLastPoint();
lineTo(lastPoint.x + dx[i], lastPoint.y + dy[i]);
}
clearArg();
}
-
+
/**
* Appends a horizontal line of length dx1 to the current point.
* With an odd number of arguments, subsequent argument pairs
@@ -115,13 +115,13 @@ public class T2Interpreter {
* number of arguments on the stack.
*/
private void _hlineto() {
- int count = getArgCount();
- Number[] nums = new Number[count];
+ final int count = getArgCount();
+ final Number[] nums = new Number[count];
for (int i = 0; i < count; ++i) {
nums[count - i - 1] = popArg();
}
for (int i = 0; i < count; ++i) {
- Point lastPoint = getLastPoint();
+ final Point lastPoint = getLastPoint();
if (i % 2 == 0) {
lineTo(lastPoint.x + nums[i].intValue(), lastPoint.y);
} else {
@@ -130,7 +130,7 @@ public class T2Interpreter {
}
clearArg();
}
-
+
/**
* Appends a vertical line of length dy1 to the current point. With
* an odd number of arguments, subsequent argument pairs are
@@ -142,13 +142,13 @@ public class T2Interpreter {
* number of arguments on the stack.
*/
private void _vlineto() {
- int count = getArgCount();
- Number[] nums = new Number[count];
+ final int count = getArgCount();
+ final Number[] nums = new Number[count];
for (int i = 0; i < count; ++i) {
nums[count - i - 1] = popArg();
}
for (int i = 0; i < count; ++i) {
- Point lastPoint = getLastPoint();
+ final Point lastPoint = getLastPoint();
if (i % 2 == 0) {
lineTo(lastPoint.x, lastPoint.y + nums[i].intValue());
} else {
@@ -157,7 +157,7 @@ public class T2Interpreter {
}
clearArg();
}
-
+
/**
* Appends a Bezier curve, defined by dxa...dyc, to the current
* point. For each subsequent set of six arguments, an additional
@@ -167,13 +167,13 @@ public class T2Interpreter {
* stack.
*/
private void _rrcurveto() {
- int count = getArgCount() / 6;
- int[] dxa = new int[count];
- int[] dya = new int[count];
- int[] dxb = new int[count];
- int[] dyb = new int[count];
- int[] dxc = new int[count];
- int[] dyc = new int[count];
+ final int count = getArgCount() / 6;
+ final int[] dxa = new int[count];
+ final int[] dya = new int[count];
+ final int[] dxb = new int[count];
+ final int[] dyb = new int[count];
+ final int[] dxc = new int[count];
+ final int[] dyc = new int[count];
for (int i = 0; i < count; ++i) {
dyc[count - i - 1] = popArg().intValue();
dxc[count - i - 1] = popArg().intValue();
@@ -183,18 +183,18 @@ public class T2Interpreter {
dxa[count - i - 1] = popArg().intValue();
}
for (int i = 0; i < count; ++i) {
- Point lastPoint = getLastPoint();
- int xa = lastPoint.x + dxa[i];
- int ya = lastPoint.y + dya[i];
- int xb = xa + dxb[i];
- int yb = ya + dyb[i];
- int xc = xb + dxc[i];
- int yc = yb + dyc[i];
+ final Point lastPoint = getLastPoint();
+ final int xa = lastPoint.x + dxa[i];
+ final int ya = lastPoint.y + dya[i];
+ final int xb = xa + dxb[i];
+ final int yb = ya + dyb[i];
+ final int xc = xb + dxc[i];
+ final int yc = yb + dyc[i];
curveTo(xa, ya, xb, yb, xc, yc);
}
clearArg();
}
-
+
/**
* Appends one or more Bezier curves, as described by the
* dxa...dxc set of arguments, to the current point. For each curve,
@@ -203,12 +203,12 @@ public class T2Interpreter {
* case). Note the argument order for the odd argument case.
*/
private void _hhcurveto() {
- int count = getArgCount() / 4;
+ final int count = getArgCount() / 4;
int dy1 = 0;
- int[] dxa = new int[count];
- int[] dxb = new int[count];
- int[] dyb = new int[count];
- int[] dxc = new int[count];
+ final int[] dxa = new int[count];
+ final int[] dxb = new int[count];
+ final int[] dyb = new int[count];
+ final int[] dxc = new int[count];
for (int i = 0; i < count; ++i) {
dxc[count - i - 1] = popArg().intValue();
dyb[count - i - 1] = popArg().intValue();
@@ -219,18 +219,18 @@ public class T2Interpreter {
dy1 = popArg().intValue();
}
for (int i = 0; i < count; ++i) {
- Point lastPoint = getLastPoint();
- int xa = lastPoint.x + dxa[i];
- int ya = lastPoint.y + (i == 0 ? dy1 : 0);
- int xb = xa + dxb[i];
- int yb = ya + dyb[i];
- int xc = xb + dxc[i];
- int yc = yb;
+ final Point lastPoint = getLastPoint();
+ final int xa = lastPoint.x + dxa[i];
+ final int ya = lastPoint.y + (i == 0 ? dy1 : 0);
+ final int xb = xa + dxb[i];
+ final int yb = ya + dyb[i];
+ final int xc = xb + dxc[i];
+ final int yc = yb;
curveTo(xa, ya, xb, yb, xc, yc);
}
clearArg();
}
-
+
/**
* Appends one or more Bezier curves to the current point. The
* tangent for the first Bezier must be horizontal, and the second
@@ -243,15 +243,15 @@ public class T2Interpreter {
*/
private void _hvcurveto() {
if (getArgCount() % 8 <= 1) {
- int count = getArgCount() / 8;
- int[] dxa = new int[count];
- int[] dxb = new int[count];
- int[] dyb = new int[count];
- int[] dyc = new int[count];
- int[] dyd = new int[count];
- int[] dxe = new int[count];
- int[] dye = new int[count];
- int[] dxf = new int[count];
+ final int count = getArgCount() / 8;
+ final int[] dxa = new int[count];
+ final int[] dxb = new int[count];
+ final int[] dyb = new int[count];
+ final int[] dyc = new int[count];
+ final int[] dyd = new int[count];
+ final int[] dxe = new int[count];
+ final int[] dye = new int[count];
+ final int[] dxf = new int[count];
int dyf = 0;
if (getArgCount() % 8 == 1) {
dyf = popArg().intValue();
@@ -267,32 +267,32 @@ public class T2Interpreter {
dxa[count - i - 1] = popArg().intValue();
}
for (int i = 0; i < count; ++i) {
- Point lastPoint = getLastPoint();
- int xa = lastPoint.x + dxa[i];
- int ya = lastPoint.y;
- int xb = xa + dxb[i];
- int yb = ya + dyb[i];
- int xc = xb;
- int yc = yb + dyc[i];
- int xd = xc;
- int yd = yc + dyd[i];
- int xe = xd + dxe[i];
- int ye = yd + dye[i];
- int xf = xe + dxf[i];
- int yf = ye + dyf;
+ final Point lastPoint = getLastPoint();
+ final int xa = lastPoint.x + dxa[i];
+ final int ya = lastPoint.y;
+ final int xb = xa + dxb[i];
+ final int yb = ya + dyb[i];
+ final int xc = xb;
+ final int yc = yb + dyc[i];
+ final int xd = xc;
+ final int yd = yc + dyd[i];
+ final int xe = xd + dxe[i];
+ final int ye = yd + dye[i];
+ final int xf = xe + dxf[i];
+ final int yf = ye + dyf;
curveTo(xa, ya, xb, yb, xc, yc);
curveTo(xd, yd, xe, ye, xf, yf);
}
} else {
- int count = getArgCount() / 8;
- int[] dya = new int[count];
- int[] dxb = new int[count];
- int[] dyb = new int[count];
- int[] dxc = new int[count];
- int[] dxd = new int[count];
- int[] dxe = new int[count];
- int[] dye = new int[count];
- int[] dyf = new int[count];
+ final int count = getArgCount() / 8;
+ final int[] dya = new int[count];
+ final int[] dxb = new int[count];
+ final int[] dyb = new int[count];
+ final int[] dxc = new int[count];
+ final int[] dxd = new int[count];
+ final int[] dxe = new int[count];
+ final int[] dye = new int[count];
+ final int[] dyf = new int[count];
int dxf = 0;
if (getArgCount() % 8 == 1) {
dxf = popArg().intValue();
@@ -307,33 +307,43 @@ public class T2Interpreter {
dxb[count - i - 1] = popArg().intValue();
dya[count - i - 1] = popArg().intValue();
}
- int dy3 = popArg().intValue();
- int dy2 = popArg().intValue();
- int dx2 = popArg().intValue();
- int dx1 = popArg().intValue();
+ /**
+ * Not using the 'popped' arguments,
+ * hence simply pop them from stack!
+ *
+ final int dy3 = popArg().intValue();
+ final int dy2 = popArg().intValue();
+ final int dx2 = popArg().intValue();
+ final int dx1 = popArg().intValue();
+ */
+ popArg();
+ popArg();
+ popArg();
+ popArg();
+
for (int i = 0; i < count; ++i) {
- Point lastPoint = getLastPoint();
- int xa = lastPoint.x;
- int ya = lastPoint.y + dya[i];
- int xb = xa + dxb[i];
- int yb = ya + dyb[i];
- int xc = xb + dxc[i];
- int yc = yb;
- int xd = xc + dxd[i];
- int yd = yc;
- int xe = xd + dxe[i];
- int ye = yd + dye[i];
- int xf = xe + dxf;
- int yf = ye + dyf[i];
+ final Point lastPoint = getLastPoint();
+ final int xa = lastPoint.x;
+ final int ya = lastPoint.y + dya[i];
+ final int xb = xa + dxb[i];
+ final int yb = ya + dyb[i];
+ final int xc = xb + dxc[i];
+ final int yc = yb;
+ final int xd = xc + dxd[i];
+ final int yd = yc;
+ final int xe = xd + dxe[i];
+ final int ye = yd + dye[i];
+ final int xf = xe + dxf;
+ final int yf = ye + dyf[i];
curveTo(xa, ya, xb, yb, xc, yc);
curveTo(xd, yd, xe, ye, xf, yf);
-
+
// What on earth do we do with dx1, dx2, dy2 and dy3?
}
}
clearArg();
}
-
+
/**
* Is equivalent to one rrcurveto for each set of six arguments
* dxa...dyc, followed by exactly one rlineto using the dxd, dyd
@@ -341,15 +351,15 @@ public class T2Interpreter {
* on the argument stack.
*/
private void _rcurveline() {
- int count = (getArgCount() - 2) / 6;
- int[] dxa = new int[count];
- int[] dya = new int[count];
- int[] dxb = new int[count];
- int[] dyb = new int[count];
- int[] dxc = new int[count];
- int[] dyc = new int[count];
- int dyd = popArg().intValue();
- int dxd = popArg().intValue();
+ final int count = (getArgCount() - 2) / 6;
+ final int[] dxa = new int[count];
+ final int[] dya = new int[count];
+ final int[] dxb = new int[count];
+ final int[] dyb = new int[count];
+ final int[] dxc = new int[count];
+ final int[] dyc = new int[count];
+ final int dyd = popArg().intValue();
+ final int dxd = popArg().intValue();
for (int i = 0; i < count; ++i) {
dyc[count - i - 1] = popArg().intValue();
dxc[count - i - 1] = popArg().intValue();
@@ -361,11 +371,11 @@ public class T2Interpreter {
int xc = 0;
int yc = 0;
for (int i = 0; i < count; ++i) {
- Point lastPoint = getLastPoint();
- int xa = lastPoint.x + dxa[i];
- int ya = lastPoint.y + dya[i];
- int xb = xa + dxb[i];
- int yb = ya + dyb[i];
+ final Point lastPoint = getLastPoint();
+ final int xa = lastPoint.x + dxa[i];
+ final int ya = lastPoint.y + dya[i];
+ final int xb = xa + dxb[i];
+ final int yb = ya + dyb[i];
xc = xb + dxc[i];
yc = yb + dyc[i];
curveTo(xa, ya, xb, yb, xc, yc);
@@ -373,7 +383,7 @@ public class T2Interpreter {
lineTo(xc + dxd, yc + dyd);
clearArg();
}
-
+
/**
* Is equivalent to one rlineto for each pair of arguments beyond
* the six arguments dxb...dyd needed for the one rrcurveto
@@ -381,15 +391,15 @@ public class T2Interpreter {
* items on the argument stack.
*/
private void _rlinecurve() {
- int count = (getArgCount() - 6) / 2;
- int[] dxa = new int[count];
- int[] dya = new int[count];
- int dyd = popArg().intValue();
- int dxd = popArg().intValue();
- int dyc = popArg().intValue();
- int dxc = popArg().intValue();
- int dyb = popArg().intValue();
- int dxb = popArg().intValue();
+ final int count = (getArgCount() - 6) / 2;
+ final int[] dxa = new int[count];
+ final int[] dya = new int[count];
+ final int dyd = popArg().intValue();
+ final int dxd = popArg().intValue();
+ final int dyc = popArg().intValue();
+ final int dxc = popArg().intValue();
+ final int dyb = popArg().intValue();
+ final int dxb = popArg().intValue();
for (int i = 0; i < count; ++i) {
dya[count - i - 1] = popArg().intValue();
dxa[count - i - 1] = popArg().intValue();
@@ -397,21 +407,21 @@ public class T2Interpreter {
int xa = 0;
int ya = 0;
for (int i = 0; i < count; ++i) {
- Point lastPoint = getLastPoint();
+ final Point lastPoint = getLastPoint();
xa = lastPoint.x + dxa[i];
ya = lastPoint.y + dya[i];
lineTo(xa, ya);
}
- int xb = xa + dxb;
- int yb = ya + dyb;
- int xc = xb + dxc;
- int yc = yb + dyc;
- int xd = xc + dxd;
- int yd = yc + dyd;
+ final int xb = xa + dxb;
+ final int yb = ya + dyb;
+ final int xc = xb + dxc;
+ final int yc = yb + dyc;
+ final int xd = xc + dxd;
+ final int yd = yc + dyd;
curveTo(xb, yb, xc, yc, xd, yd);
clearArg();
}
-
+
/**
* Appends one or more Bezier curves to the current point, where
* the first tangent is vertical and the second tangent is horizontal.
@@ -420,15 +430,15 @@ public class T2Interpreter {
*/
private void _vhcurveto() {
if (getArgCount() % 8 <= 1) {
- int count = getArgCount() / 8;
- int[] dya = new int[count];
- int[] dxb = new int[count];
- int[] dyb = new int[count];
- int[] dxc = new int[count];
- int[] dxd = new int[count];
- int[] dxe = new int[count];
- int[] dye = new int[count];
- int[] dyf = new int[count];
+ final int count = getArgCount() / 8;
+ final int[] dya = new int[count];
+ final int[] dxb = new int[count];
+ final int[] dyb = new int[count];
+ final int[] dxc = new int[count];
+ final int[] dxd = new int[count];
+ final int[] dxe = new int[count];
+ final int[] dye = new int[count];
+ final int[] dyf = new int[count];
int dxf = 0;
if (getArgCount() % 8 == 1) {
dxf = popArg().intValue();
@@ -444,28 +454,28 @@ public class T2Interpreter {
dya[count - i - 1] = popArg().intValue();
}
for (int i = 0; i < count; ++i) {
- Point lastPoint = getLastPoint();
- int xa = lastPoint.x;
- int ya = lastPoint.y + dya[i];
- int xb = xa + dxb[i];
- int yb = ya + dyb[i];
- int xc = xb + dxc[i];
- int yc = yb;
- int xd = xc + dxd[i];
- int yd = yc;
- int xe = xd + dxe[i];
- int ye = yd + dye[i];
- int xf = xe + dxf;
- int yf = ye + dyf[i];
+ final Point lastPoint = getLastPoint();
+ final int xa = lastPoint.x;
+ final int ya = lastPoint.y + dya[i];
+ final int xb = xa + dxb[i];
+ final int yb = ya + dyb[i];
+ final int xc = xb + dxc[i];
+ final int yc = yb;
+ final int xd = xc + dxd[i];
+ final int yd = yc;
+ final int xe = xd + dxe[i];
+ final int ye = yd + dye[i];
+ final int xf = xe + dxf;
+ final int yf = ye + dyf[i];
curveTo(xa, ya, xb, yb, xc, yc);
curveTo(xd, yd, xe, ye, xf, yf);
}
} else {
- int foo = 0;
+ final int foo = 0;
}
clearArg();
}
-
+
/**
* Appends one or more curves to the current point. If the argument
* count is a multiple of four, the curve starts and ends vertical. If
@@ -473,10 +483,10 @@ public class T2Interpreter {
* vertical tangent.
*/
private void _vvcurveto() {
-
+
clearArg();
}
-
+
/**
* Causes two Bezier curves, as described by the arguments (as
* shown in Figure 2 below), to be rendered as a straight line when
@@ -485,10 +495,10 @@ public class T2Interpreter {
* pixels.
*/
private void _flex() {
-
+
clearArg();
}
-
+
/**
* Causes the two curves described by the arguments dx1...dx6 to
* be rendered as a straight line when the flex depth is less than
@@ -496,10 +506,10 @@ public class T2Interpreter {
* flex depth is greater than or equal to 0.5 device pixels.
*/
private void _hflex() {
-
+
clearArg();
}
-
+
/**
* Causes the two curves described by the arguments to be
* rendered as a straight line when the flex depth is less than 0.5
@@ -507,10 +517,10 @@ public class T2Interpreter {
* than or equal to 0.5 device pixels.
*/
private void _hflex1() {
-
+
clearArg();
}
-
+
/**
* Causes the two curves described by the arguments to be
* rendered as a straight line when the flex depth is less than 0.5
@@ -518,10 +528,10 @@ public class T2Interpreter {
* than or equal to 0.5 device pixels.
*/
private void _flex1() {
-
+
clearArg();
}
-
+
/**
* Finishes a charstring outline definition, and must be the
* last operator in a character's outline.
@@ -530,81 +540,81 @@ public class T2Interpreter {
endContour();
clearArg();
}
-
+
private void _hstem() {
-
+
clearArg();
}
-
+
private void _vstem() {
-
+
clearArg();
}
-
+
private void _hstemhm() {
-
+
clearArg();
}
-
+
private void _vstemhm() {
-
+
clearArg();
}
-
+
private void _hintmask() {
-
+
clearArg();
}
-
+
private void _cntrmask() {
-
+
clearArg();
}
-
+
/**
* Returns the absolute value of num.
*/
private void _abs() {
- double num = popArg().doubleValue();
+ final double num = popArg().doubleValue();
pushArg(Math.abs(num));
}
-
+
/**
* Returns the sum of the two numbers num1 and num2.
*/
private void _add() {
- double num2 = popArg().doubleValue();
- double num1 = popArg().doubleValue();
+ final double num2 = popArg().doubleValue();
+ final double num1 = popArg().doubleValue();
pushArg(num1 + num2);
}
-
+
/**
* Returns the result of subtracting num2 from num1.
*/
private void _sub() {
- double num2 = popArg().doubleValue();
- double num1 = popArg().doubleValue();
+ final double num2 = popArg().doubleValue();
+ final double num1 = popArg().doubleValue();
pushArg(num1 - num2);
}
-
+
/**
* Returns the quotient of num1 divided by num2. The result is
* undefined if overflow occurs and is zero for underflow.
*/
private void _div() {
- double num2 = popArg().doubleValue();
- double num1 = popArg().doubleValue();
+ final double num2 = popArg().doubleValue();
+ final double num1 = popArg().doubleValue();
pushArg(num1 / num2);
}
-
+
/**
* Returns the negative of num.
*/
private void _neg() {
- double num = popArg().doubleValue();
+ final double num = popArg().doubleValue();
pushArg(-num);
}
-
+
/**
* Returns a pseudo random number num2 in the range (0,1], that
* is, greater than zero and less than or equal to one.
@@ -612,43 +622,43 @@ public class T2Interpreter {
private void _random() {
pushArg(1.0 - Math.random());
}
-
+
/**
* Returns the product of num1 and num2. If overflow occurs, the
* result is undefined, and zero is returned for underflow.
*/
private void _mul() {
- double num2 = popArg().doubleValue();
- double num1 = popArg().doubleValue();
+ final double num2 = popArg().doubleValue();
+ final double num1 = popArg().doubleValue();
pushArg(num1 * num2);
}
-
+
/**
* Returns the square root of num. If num is negative, the result is
* undefined.
*/
private void _sqrt() {
- double num = popArg().doubleValue();
+ final double num = popArg().doubleValue();
pushArg(Math.sqrt(num));
}
-
+
/**
* Removes the top element num from the Type 2 argument stack.
*/
private void _drop() {
popArg();
}
-
+
/**
* Exchanges the top two elements on the argument stack.
*/
private void _exch() {
- Number num2 = popArg();
- Number num1 = popArg();
+ final Number num2 = popArg();
+ final Number num1 = popArg();
pushArg(num2);
pushArg(num1);
}
-
+
/**
* Retrieves the element i from the top of the argument stack and
* pushes a copy of that element onto that stack. If i is negative,
@@ -656,8 +666,8 @@ public class T2Interpreter {
* undefined.
*/
private void _index() {
- int i = popArg().intValue();
- Number[] nums = new Number[i];
+ final int i = popArg().intValue();
+ final Number[] nums = new Number[i];
for (int j = 0; j < i; ++j) {
nums[j] = popArg();
}
@@ -666,7 +676,7 @@ public class T2Interpreter {
}
pushArg(nums[i]);
}
-
+
/**
* Performs a circular shift of the elements num(Nx1) ... num0 on
* the argument stack by the amount J. Positive J indicates upward
@@ -675,9 +685,9 @@ public class T2Interpreter {
* operation is undefined.
*/
private void _roll() {
- int j = popArg().intValue();
- int n = popArg().intValue();
- Number[] nums = new Number[n];
+ final int j = popArg().intValue();
+ final int n = popArg().intValue();
+ final Number[] nums = new Number[n];
for (int i = 0; i < n; ++i) {
nums[i] = popArg();
}
@@ -685,25 +695,25 @@ public class T2Interpreter {
pushArg(nums[(n + i + j) % n]);
}
}
-
+
/**
* Duplicates the top element on the argument stack.
*/
private void _dup() {
- Number any = popArg();
+ final Number any = popArg();
pushArg(any);
pushArg(any);
}
-
+
/**
* Stores val into the transient array at the location given by i.
*/
private void _put() {
- int i = popArg().intValue();
- Number val = popArg();
+ final int i = popArg().intValue();
+ final Number val = popArg();
_transientArray[i] = val;
}
-
+
/**
* Retrieves the value stored in the transient array at the location
* given by i and pushes the value onto the argument stack. If get
@@ -711,61 +721,61 @@ public class T2Interpreter {
* charstring, the value returned is undefined.
*/
private void _get() {
- int i = popArg().intValue();
+ final int i = popArg().intValue();
pushArg(_transientArray[i]);
}
-
+
/**
* Puts a 1 on the stack if num1 and num2 are both non-zero, and
* puts a 0 on the stack if either argument is zero.
*/
private void _and() {
- double num2 = popArg().doubleValue();
- double num1 = popArg().doubleValue();
+ final double num2 = popArg().doubleValue();
+ final double num1 = popArg().doubleValue();
pushArg((num1!=0.0) && (num2!=0.0) ? 1 : 0);
}
-
+
/**
* Puts a 1 on the stack if either num1 or num2 are non-zero, and
* puts a 0 on the stack if both arguments are zero.
*/
private void _or() {
- double num2 = popArg().doubleValue();
- double num1 = popArg().doubleValue();
+ final double num2 = popArg().doubleValue();
+ final double num1 = popArg().doubleValue();
pushArg((num1!=0.0) || (num2!=0.0) ? 1 : 0);
}
-
+
/**
* Returns a 0 if num1 is non-zero; returns a 1 if num1 is zero.
*/
private void _not() {
- double num1 = popArg().doubleValue();
+ final double num1 = popArg().doubleValue();
pushArg((num1!=0.0) ? 0 : 1);
}
-
+
/**
* Puts a 1 on the stack if num1 equals num2, otherwise a 0 (zero)
* is put on the stack.
*/
private void _eq() {
- double num2 = popArg().doubleValue();
- double num1 = popArg().doubleValue();
+ final double num2 = popArg().doubleValue();
+ final double num1 = popArg().doubleValue();
pushArg(num1 == num2 ? 1 : 0);
}
-
+
/**
* Leaves the value s1 on the stack if v1 ? v2, or leaves s2 on the
* stack if v1 > v2. The value of s1 and s2 is usually the biased
* number of a subroutine.
*/
private void _ifelse() {
- double v2 = popArg().doubleValue();
- double v1 = popArg().doubleValue();
- Number s2 = popArg();
- Number s1 = popArg();
+ final double v2 = popArg().doubleValue();
+ final double v1 = popArg().doubleValue();
+ final Number s2 = popArg();
+ final Number s1 = popArg();
pushArg(v1 <= v2 ? s1 : s2);
}
-
+
/**
* Calls a charstring subroutine with index subr# (actually the subr
* number plus the subroutine bias number, as described in section
@@ -777,26 +787,26 @@ public class T2Interpreter {
* Calling an undefined subr (gsubr) has undefined results.
*/
private void _callsubr() {
-
+
}
-
+
/**
* Operates in the same manner as callsubr except that it calls a
* global subroutine.
*/
private void _callgsubr() {
-
+
}
-
+
/**
* Returns from either a local or global charstring subroutine, and
* continues execution after the corresponding call(g)subr.
*/
private void _return() {
-
+
}
-
- public Point[] execute(CharstringType2 cs) {
+
+ public Point[] execute(final CharstringType2 cs) {
_points = new ArrayList<Point>();
cs.resetIP();
while (cs.moreBytes()) {
@@ -964,7 +974,7 @@ public class T2Interpreter {
}
}
}
- Point[] pointArray = new Point[_points.size()];
+ final Point[] pointArray = new Point[_points.size()];
_points.toArray(pointArray);
return pointArray;
}
@@ -975,7 +985,7 @@ public class T2Interpreter {
private int getArgCount() {
return _argStackIndex;
}
-
+
/**
* Pop a value off the argument stack
*/
@@ -986,10 +996,10 @@ public class T2Interpreter {
/**
* Push a value on to the argument stack
*/
- private void pushArg(Number n) {
+ private void pushArg(final Number n) {
_argStack[_argStackIndex++] = n;
}
-
+
/**
* Pop a value off the subroutine stack
*/
@@ -1000,43 +1010,43 @@ public class T2Interpreter {
/**
* Push a value on to the subroutine stack
*/
- private void pushSubr(int n) {
+ private void pushSubr(final int n) {
_subrStack[_subrStackIndex++] = n;
}
-
+
/**
* Clear the argument stack
*/
private void clearArg() {
_argStackIndex = 0;
}
-
+
private Point getLastPoint() {
- int size = _points.size();
+ final int size = _points.size();
if (size > 0) {
return _points.get(size - 1);
} else {
return new Point(0, 0, true, false);
}
}
-
- private void moveTo(int x, int y) {
+
+ private void moveTo(final int x, final int y) {
endContour();
_points.add(new Point(x, y, true, false));
}
-
- private void lineTo(int x, int y) {
+
+ private void lineTo(final int x, final int y) {
_points.add(new Point(x, y, true, false));
}
-
- private void curveTo(int cx1, int cy1, int cx2, int cy2, int x, int y) {
+
+ private void curveTo(final int cx1, final int cy1, final int cx2, final int cy2, final int x, final int y) {
_points.add(new Point(cx1, cy1, false, false));
_points.add(new Point(cx2, cy2, false, false));
_points.add(new Point(x, y, true, false));
}
-
+
private void endContour() {
- Point lastPoint = getLastPoint();
+ final Point lastPoint = getLastPoint();
if (lastPoint != null) {
lastPoint.endOfContour = true;
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/tt/engine/Interpreter.java b/src/jogl/classes/jogamp/graph/font/typecast/tt/engine/Interpreter.java
index a659a7003..a7408e381 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/tt/engine/Interpreter.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/tt/engine/Interpreter.java
@@ -33,16 +33,16 @@ import jogamp.graph.font.typecast.ot.Point;
public class Interpreter {
private Parser parser = null;
- private GraphicsState gs = new GraphicsState();
- private Point[][] zone = new Point[2][];
+ private final GraphicsState gs = new GraphicsState();
+ private final Point[][] zone = new Point[2][];
private int[] stack = null;
private int[] store = null;
- private int[] cvt = new int[256];
+ private final int[] cvt = new int[256];
private int[] functionMap = null;
private int stackIndex = 0;
private boolean inFuncDef = false;
- public Interpreter(int stackMax, int storeMax, int funcMax) {
+ public Interpreter(final int stackMax, final int storeMax, final int funcMax) {
zone[0] = new Point[256];
zone[1] = new Point[256];
stack = new int[stackMax];
@@ -54,7 +54,7 @@ public class Interpreter {
* ABSolute value
*/
private void _abs() {
- int n = pop();
+ final int n = pop();
if (n >= 0) {
push(n);
} else {
@@ -66,8 +66,8 @@ public class Interpreter {
* ADD
*/
private void _add() {
- int n1 = pop();
- int n2 = pop();
+ final int n1 = pop();
+ final int n2 = pop();
push(n2 + n1);
}
@@ -92,8 +92,8 @@ public class Interpreter {
* logical AND
*/
private void _and() {
- int e2 = pop();
- int e1 = pop();
+ final int e2 = pop();
+ final int e1 = pop();
push(((e1 != 0) && (e2 != 0)) ? 1 : 0);
}
@@ -108,7 +108,7 @@ public class Interpreter {
* CEILING
*/
private void _ceiling() {
- int n = pop();
+ final int n = pop();
if (n >= 0) {
push((n & 0xffc0) + (((n & 0x3f) != 0) ? 0x40 : 0));
} else {
@@ -138,7 +138,7 @@ public class Interpreter {
* DELTA exception C1
*/
private void _deltac1() {
- int n = pop();
+ final int n = pop();
for (int i = 0; i < n; i++) {
pop(); // pn
pop(); // argn
@@ -149,7 +149,7 @@ public class Interpreter {
* DELTA exception C2
*/
private void _deltac2() {
- int n = pop();
+ final int n = pop();
for (int i = 0; i < n; i++) {
pop(); // pn
pop(); // argn
@@ -160,7 +160,7 @@ public class Interpreter {
* DELTA exception C3
*/
private void _deltac3() {
- int n = pop();
+ final int n = pop();
for (int i = 0; i < n; i++) {
pop(); // pn
pop(); // argn
@@ -171,7 +171,7 @@ public class Interpreter {
* DELTA exception P1
*/
private void _deltap1() {
- int n = pop();
+ final int n = pop();
for (int i = 0; i < n; i++) {
pop(); // pn
pop(); // argn
@@ -182,7 +182,7 @@ public class Interpreter {
* DELTA exception P2
*/
private void _deltap2() {
- int n = pop();
+ final int n = pop();
for (int i = 0; i < n; i++) {
pop(); // pn
pop(); // argn
@@ -193,7 +193,7 @@ public class Interpreter {
* DELTA exception P3
*/
private void _deltap3() {
- int n = pop();
+ final int n = pop();
for (int i = 0; i < n; i++) {
pop(); // pn
pop(); // argn
@@ -211,8 +211,8 @@ public class Interpreter {
* DIVide
*/
private void _div() {
- int n1 = pop();
- int n2 = pop();
+ final int n1 = pop();
+ final int n2 = pop();
push((n2 / n1) >> 6);
}
@@ -220,7 +220,7 @@ public class Interpreter {
* DUPlicate top stack element
*/
private void _dup() {
- int n = pop();
+ final int n = pop();
push(n);
push(n);
}
@@ -228,7 +228,7 @@ public class Interpreter {
/**
* ELSE
*/
- private int _else(int instructionIndex) {
+ private int _else(final int instructionIndex) {
return parser.handleElse(instructionIndex);
}
@@ -236,8 +236,8 @@ public class Interpreter {
* EQual
*/
private void _eq() {
- int e2 = pop();
- int e1 = pop();
+ final int e2 = pop();
+ final int e1 = pop();
push((e1 == e2) ? 1 : 0);
}
@@ -249,7 +249,7 @@ public class Interpreter {
/**
* Function DEFinition
*/
- private void _fdef(int instructionIndex) {
+ private void _fdef(final int instructionIndex) {
functionMap[pop()] = instructionIndex;
inFuncDef = true;
}
@@ -275,7 +275,7 @@ public class Interpreter {
*/
private void _flippt() {
while(gs.loop-- > 0) {
- int index = pop();
+ final int index = pop();
zone[gs.zp0][index].onCurve = !zone[gs.zp0][index].onCurve;
}
gs.loop = 1;
@@ -285,8 +285,8 @@ public class Interpreter {
* FLIP RanGe OFF
*/
private void _fliprgoff() {
- int end = pop();
- int start = pop();
+ final int end = pop();
+ final int start = pop();
for (int i = start; i <= end; i++) {
zone[1][i].onCurve = false;
}
@@ -296,8 +296,8 @@ public class Interpreter {
* FLIP RanGe ON
*/
private void _fliprgon() {
- int end = pop();
- int start = pop();
+ final int end = pop();
+ final int start = pop();
for (int i = start; i <= end; i++) {
zone[1][i].onCurve = true;
}
@@ -307,7 +307,7 @@ public class Interpreter {
* FLOOR
*/
private void _floor() {
- int n = pop();
+ final int n = pop();
if (n >= 0) {
push(n & 0xffc0);
} else {
@@ -315,7 +315,7 @@ public class Interpreter {
}
}
- private void _gc(short param) {
+ private void _gc(final short param) {
pop();
push(0);
}
@@ -345,8 +345,8 @@ public class Interpreter {
* Greater Than
*/
private void _gt() {
- int e2 = pop();
- int e1 = pop();
+ final int e2 = pop();
+ final int e1 = pop();
push((e1 > e2) ? 1 : 0);
}
@@ -354,8 +354,8 @@ public class Interpreter {
* Greater Than or EQual
*/
private void _gteq() {
- int e2 = pop();
- int e1 = pop();
+ final int e2 = pop();
+ final int e1 = pop();
push((e1 >= e2) ? 1 : 0);
}
@@ -370,7 +370,7 @@ public class Interpreter {
/**
* IF test
*/
- private int _if(int instructionIndex) {
+ private int _if(final int instructionIndex) {
return parser.handleIf(pop() != 0, instructionIndex);
}
@@ -425,8 +425,8 @@ public class Interpreter {
* will be used in glyph instructions.
*/
private void _instctrl() {
- int s = pop();
- int v = pop();
+ final int s = pop();
+ final int v = pop();
if (s == 1) {
gs.instruction_control |= v;
} else if (s == 2) {
@@ -446,22 +446,22 @@ public class Interpreter {
pop();
}
- private void _iup(short param) {
+ private void _iup(final short param) {
}
/**
* JuMP Relative
*/
- private int _jmpr(int instructionIndex) {
- return instructionIndex += pop() - 1;
+ private int _jmpr(final int instructionIndex) {
+ return instructionIndex + ( pop() - 1 );
}
/**
* Jump Relative On False
*/
private int _jrof(int instructionIndex) {
- boolean test = pop() != 0;
- int offset = pop();
+ final boolean test = pop() != 0;
+ final int offset = pop();
if (!test) {
instructionIndex += offset - 1;
}
@@ -472,8 +472,8 @@ public class Interpreter {
* Jump Relative On True
*/
private int _jrot(int instructionIndex) {
- boolean test = pop() != 0;
- int offset = pop();
+ final boolean test = pop() != 0;
+ final int offset = pop();
if (test) {
instructionIndex += offset - 1;
}
@@ -484,8 +484,8 @@ public class Interpreter {
* LOOP and CALL function
*/
private void _loopcall() {
- int index = pop();
- int count = pop();
+ /* final int index = */ pop();
+ final int count = pop();
for (int i = 0; i < count; i++) {
execute(functionMap[i]);
}
@@ -495,8 +495,8 @@ public class Interpreter {
* Less Than
*/
private void _lt() {
- int e2 = pop();
- int e1 = pop();
+ final int e2 = pop();
+ final int e1 = pop();
push((e1 < e2) ? 1 : 0);
}
@@ -504,8 +504,8 @@ public class Interpreter {
* Less Than or EQual
*/
private void _lteq() {
- int e2 = pop();
- int e1 = pop();
+ final int e2 = pop();
+ final int e1 = pop();
push((e1 <= e2) ? 1 : 0);
}
@@ -513,26 +513,26 @@ public class Interpreter {
* MAXimum of top two stack elements
*/
private void _max() {
- int n1 = pop();
- int n2 = pop();
+ final int n1 = pop();
+ final int n2 = pop();
push((n1 > n2) ? n1 : n2);
}
- private void _md(short param) {
+ private void _md(final short param) {
pop();
pop();
push(0);
}
- private void _mdap(short param) {
+ private void _mdap(final short param) {
pop();
}
- private void _mdrp(short param) {
+ private void _mdrp(final short param) {
pop();
}
- private void _miap(short param) {
+ private void _miap(final short param) {
pop();
pop();
}
@@ -540,8 +540,8 @@ public class Interpreter {
* MINimum of top two stack elements
*/
private void _min() {
- int n1 = pop();
- int n2 = pop();
+ final int n1 = pop();
+ final int n2 = pop();
push((n1 < n2) ? n1 : n2);
}
@@ -550,15 +550,15 @@ public class Interpreter {
*/
private void _mindex() {
// Move the indexed element to stackIndex, and shift the others down
- int k = pop();
- int e = stack[stackIndex - k];
+ final int k = pop();
+ final int e = stack[stackIndex - k];
for (int i = stackIndex - k; i < stackIndex - 1; i++) {
stack[i] = stack[i+1];
}
stack[stackIndex - 1] = e;
}
- private void _mirp(short param) {
+ private void _mirp(final short param) {
pop();
pop();
}
@@ -570,8 +570,8 @@ public class Interpreter {
private void _mps() {
push(0);
}
-
- private void _msirp(short param) {
+
+ private void _msirp(final short param) {
pop();
pop();
}
@@ -580,8 +580,8 @@ public class Interpreter {
* MULtiply
*/
private void _mul() {
- int n1 = pop();
- int n2 = pop();
+ final int n1 = pop();
+ final int n2 = pop();
push((n1 * n2) >> 6);
}
@@ -596,8 +596,8 @@ public class Interpreter {
* Not EQual
*/
private void _neq() {
- int e2 = pop();
- int e1 = pop();
+ final int e2 = pop();
+ final int e1 = pop();
push((e1 != e2) ? 1 : 0);
}
@@ -608,7 +608,7 @@ public class Interpreter {
push((pop() != 0) ? 0 : 1);
}
- private void _nround(short param) {
+ private void _nround(final short param) {
pop();
push(0);
}
@@ -622,8 +622,8 @@ public class Interpreter {
* logical OR
*/
private void _or() {
- int e2 = pop();
- int e1 = pop();
+ final int e2 = pop();
+ final int e1 = pop();
push(((e1 != 0) || (e2 != 0)) ? 1 : 0);
}
@@ -633,7 +633,7 @@ public class Interpreter {
* PUSH Bytes
* PUSH Words
*/
- private void _push(int[] data) {
+ private void _push(final int[] data) {
for (int j = 0; j < data.length; j++) {
push(data[j]);
}
@@ -664,15 +664,15 @@ public class Interpreter {
* ROLL the top three stack elements
*/
private void _roll() {
- int a = pop();
- int b = pop();
- int c = pop();
+ final int a = pop();
+ final int b = pop();
+ final int c = pop();
push(b);
push(a);
push(c);
}
- private void _round(short param) {
+ private void _round(final short param) {
pop();
push(0);
}
@@ -907,7 +907,7 @@ public class Interpreter {
/**
* Set Dual Projection_Vector To Line
*/
- private void _sdpvtl(short param) {
+ private void _sdpvtl(final short param) {
pop();
pop();
}
@@ -930,7 +930,7 @@ public class Interpreter {
/*
* Set Freedom_Vector to Coordinate Axis
*/
- private void _sfvtca(short param) {
+ private void _sfvtca(final short param) {
if (param == 1) {
gs.freedom_vector[0] = 0x4000;
gs.freedom_vector[1] = 0x0000;
@@ -943,16 +943,16 @@ public class Interpreter {
/*
* Set Freedom_Vector To Line
*/
- private void _sfvtl(short param) {
+ private void _sfvtl(final short param) {
pop();
pop();
- if (param == 1) {
+ // if (param == 1) {
gs.freedom_vector[0] = 0x0000;
gs.freedom_vector[1] = 0x0000;
- } else {
- gs.freedom_vector[0] = 0x0000;
- gs.freedom_vector[1] = 0x0000;
- }
+ // } else {
+ // gs.freedom_vector[0] = 0x0000;
+ // gs.freedom_vector[1] = 0x0000;
+ //}
}
/**
@@ -963,7 +963,7 @@ public class Interpreter {
gs.freedom_vector[1] = gs.projection_vector[1];
}
- private void _shc(short param) {
+ private void _shc(final short param) {
pop();
}
@@ -972,7 +972,7 @@ public class Interpreter {
*
* USES: loop
*/
- private void _shp(short param) {
+ private void _shp(final short param) {
while(gs.loop-- > 0) {
pop();
if(param == 0) {
@@ -995,7 +995,7 @@ public class Interpreter {
gs.loop = 1;
}
- private void _shz(short param) {
+ private void _shz(final short param) {
pop();
}
@@ -1024,7 +1024,7 @@ public class Interpreter {
/*
* Set Projection_Vector To Coordinate Axis
*/
- private void _spvtca(short param) {
+ private void _spvtca(final short param) {
if (param == 1) {
gs.projection_vector[0] = 0x4000;
gs.projection_vector[1] = 0x0000;
@@ -1037,21 +1037,26 @@ public class Interpreter {
/**
* Set Projection_Vector To Line
*/
- private void _spvtl(short param) {
+ private void _spvtl(final short param) {
+ // below block is dead code, reduce to pop() calls.
+ pop();
+ pop();
+ /**
// We'll get a copy of the line and normalize it -
// divide the x- and y-coords by the vector's dot product.
- Point p1 = zone[gs.zp2][pop()];
- Point p2 = zone[gs.zp1][pop()];
- int x = p2.x - p1.x;
- int y = p2.y - p1.y;
- if(param == 1) {
- gs.projection_vector[0] = 0x0000;
- gs.projection_vector[1] = 0x0000;
- } else {
+ final Point p1 = zone[gs.zp2][pop()];
+ final Point p2 = zone[gs.zp1][pop()];
+ final int x = p2.x - p1.x;
+ final int y = p2.y - p1.y;
+ */
+ // if(param == 1) {
gs.projection_vector[0] = 0x0000;
gs.projection_vector[1] = 0x0000;
- }
+ // } else {
+ // gs.projection_vector[0] = 0x0000;
+ // gs.projection_vector[1] = 0x0000;
+ // }
}
private void _sround() {
@@ -1097,15 +1102,15 @@ public class Interpreter {
* SUBtract
*/
private void _sub() {
- int n1 = pop();
- int n2 = pop();
+ final int n1 = pop();
+ final int n2 = pop();
push(n2 - n1);
}
/**
* Set freedom and projection Vectors To Coordinate Axis
*/
- private void _svtca(short param) {
+ private void _svtca(final short param) {
if (param == 1) {
gs.projection_vector[0] = 0x4000;
gs.projection_vector[1] = 0x0000;
@@ -1123,8 +1128,8 @@ public class Interpreter {
* SWAP the top two elements on the stack
*/
private void _swap() {
- int n1 = pop();
- int n2 = pop();
+ final int n1 = pop();
+ final int n2 = pop();
push(n1);
push(n2);
}
@@ -1165,7 +1170,7 @@ public class Interpreter {
* Write Control Value Table in FUnits
*/
private void _wcvtf() {
- int value = pop();
+ final int value = pop();
// Conversion of value goes here
cvt[pop()] = value;
}
@@ -1174,7 +1179,7 @@ public class Interpreter {
* Write Control Value Table in Pixel units
*/
private void _wcvtp() {
- int value = pop();
+ final int value = pop();
// Conversion of value goes here
cvt[pop()] = value;
}
@@ -1188,9 +1193,9 @@ public class Interpreter {
public void execute(int ip) {
while (ip < ((ip & 0xffff0000) | parser.getISLength(ip >> 16))) {
- short opcode = parser.getOpcode(ip);
+ final short opcode = parser.getOpcode(ip);
if (inFuncDef) {
-
+
// We're within a function definition, so don't execute the code
if (opcode == Mnemonic.ENDF) {
inFuncDef = false;
@@ -1332,7 +1337,7 @@ public class Interpreter {
return stack[--stackIndex];
}
- private void push(int i) {
+ private void push(final int i) {
stack[stackIndex++] = i;
}
@@ -1351,7 +1356,7 @@ public class Interpreter {
}
}
- public void setParser(Parser p) {
+ public void setParser(final Parser p) {
parser = p;
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/tt/engine/Parser.java b/src/jogl/classes/jogamp/graph/font/typecast/tt/engine/Parser.java
index c5a2b6e87..ff1795a28 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/tt/engine/Parser.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/tt/engine/Parser.java
@@ -28,7 +28,7 @@ import jogamp.graph.font.typecast.ot.Mnemonic;
*/
public class Parser {
- private short[][] instructions = new short[3][];
+ private final short[][] instructions = new short[3][];
/**
* Advance the instruction pointer to the next executable opcode.
@@ -41,7 +41,7 @@ public class Parser {
public int advanceIP(int ip) {
// The high word specifies font, cvt, or glyph program
- int prog = ip >> 16;
+ final int prog = ip >> 16;
int i = ip & 0xffff;
int dataCount;
ip++;
@@ -63,16 +63,16 @@ public class Parser {
return ip;
}
- public int getISLength(int prog) {
+ public int getISLength(final int prog) {
return instructions[prog].length;
}
- public short getOpcode(int ip) {
+ public short getOpcode(final int ip) {
return instructions[ip >> 16][ip & 0xffff];
}
- public short getPushCount(int ip) {
- short instr = instructions[ip >> 16][ip & 0xffff];
+ public short getPushCount(final int ip) {
+ final short instr = instructions[ip >> 16][ip & 0xffff];
if ((Mnemonic.NPUSHB == instr) || (Mnemonic.NPUSHW == instr)) {
return instructions[ip >> 16][(ip & 0xffff) + 1];
} else if ((Mnemonic.PUSHB == (instr & 0xf8)) || (Mnemonic.PUSHW == (instr & 0xf8))) {
@@ -81,12 +81,12 @@ public class Parser {
return 0;
}
- public int[] getPushData(int ip) {
- int count = getPushCount(ip);
- int[] data = new int[count];
- int prog = ip >> 16;
- int i = ip & 0xffff;
- short instr = instructions[prog][i];
+ public int[] getPushData(final int ip) {
+ final int count = getPushCount(ip);
+ final int[] data = new int[count];
+ final int prog = ip >> 16;
+ final int i = ip & 0xffff;
+ final short instr = instructions[prog][i];
if (Mnemonic.NPUSHB == instr) {
for (int j = 0; j < count; j++) {
data[j] = instructions[prog][i + j + 2];
@@ -114,7 +114,7 @@ public class Parser {
return ip;
}
- public int handleIf(boolean test, int ip) {
+ public int handleIf(final boolean test, int ip) {
if (test == false) {
// The TrueType spec says that we merely jump to the *next* ELSE or EIF
// instruction in the instruction stream. So therefore no nesting!
@@ -130,31 +130,32 @@ public class Parser {
/**
* This program is run everytime we scale the font
*/
- public void setCvtProgram(short[] program) {
+ public void setCvtProgram(final short[] program) {
instructions[1] = program;
}
/**
* This program is only run once
*/
- public void setFontProgram(short[] program) {
+ public void setFontProgram(final short[] program) {
instructions[0] = program;
}
/**
* This program is run everytime we scale the glyph
*/
- public void setGlyphProgram(short[] program) {
+ public void setGlyphProgram(final short[] program) {
instructions[2] = program;
}
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
int ip = 0;
while (ip < instructions[0].length) {
sb.append(Mnemonic.getMnemonic(getOpcode(ip)));
if (getPushCount(ip) > 0) {
- int[] data = getPushData(ip);
+ final int[] data = getPushData(ip);
for(int j = 0; j < data.length; j++)
sb.append(" ").append(data[j]);
}
@@ -166,7 +167,7 @@ public class Parser {
while (ip < (0x10000 | instructions[1].length)) {
sb.append(Mnemonic.getMnemonic(getOpcode(ip)));
if(getPushCount(ip) > 0) {
- int[] data = getPushData(ip);
+ final int[] data = getPushData(ip);
for (int j = 0; j < data.length; j++) {
sb.append(" ").append(data[j]);
}
@@ -179,7 +180,7 @@ public class Parser {
while (ip < (0x20000 | instructions[2].length)) {
sb.append(Mnemonic.getMnemonic(getOpcode(ip)));
if (getPushCount(ip) > 0) {
- int[] data = getPushData(ip);
+ final int[] data = getPushData(ip);
for (int j = 0; j < data.length; j++) {
sb.append(" ").append(data[j]);
}
diff --git a/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java b/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
index fc086ebe4..a9978abe5 100644
--- a/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
+++ b/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
@@ -19,21 +19,16 @@
*/
package jogamp.graph.geom.plane;
-import java.io.IOException;
-import java.io.Serializable;
-
-import jogamp.graph.math.MathFloat;
// import jogamp.opengl.util.HashCode;
import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.geom.Vertex.Factory;
-
-public class AffineTransform implements Cloneable, Serializable {
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.geom.AABBox;
- private static final long serialVersionUID = 1330973210523860834L;
+public class AffineTransform implements Cloneable {
static final String determinantIsZero = "Determinant is zero";
-
+
public static final int TYPE_IDENTITY = 0;
public static final int TYPE_TRANSLATION = 1;
public static final int TYPE_UNIFORM_SCALE = 2;
@@ -49,14 +44,12 @@ public class AffineTransform implements Cloneable, Serializable {
* The <code>TYPE_UNKNOWN</code> is an initial type value
*/
static final int TYPE_UNKNOWN = -1;
-
+
/**
- * The min value equivalent to zero. If absolute value less then ZERO it considered as zero.
+ * The min value equivalent to zero. If absolute value less then ZERO it considered as zero.
*/
static final float ZERO = (float) 1E-10;
-
- private final Vertex.Factory<? extends Vertex> pointFactory;
-
+
/**
* The values of transformation matrix
*/
@@ -68,26 +61,15 @@ public class AffineTransform implements Cloneable, Serializable {
float m12;
/**
- * The transformation <code>type</code>
+ * The transformation <code>type</code>
*/
transient int type;
public AffineTransform() {
- pointFactory = null;
- type = TYPE_IDENTITY;
- m00 = m11 = 1.0f;
- m10 = m01 = m02 = m12 = 0.0f;
- }
-
- public AffineTransform(Factory<? extends Vertex> factory) {
- pointFactory = factory;
- type = TYPE_IDENTITY;
- m00 = m11 = 1.0f;
- m10 = m01 = m02 = m12 = 0.0f;
+ setToIdentity();
}
- public AffineTransform(AffineTransform t) {
- this.pointFactory = t.pointFactory;
+ public AffineTransform(final AffineTransform t) {
this.type = t.type;
this.m00 = t.m00;
this.m10 = t.m10;
@@ -97,8 +79,7 @@ public class AffineTransform implements Cloneable, Serializable {
this.m12 = t.m12;
}
- public AffineTransform(Vertex.Factory<? extends Vertex> factory, float m00, float m10, float m01, float m11, float m02, float m12) {
- pointFactory = factory;
+ public AffineTransform(final float m00, final float m10, final float m01, final float m11, final float m02, final float m12) {
this.type = TYPE_UNKNOWN;
this.m00 = m00;
this.m10 = m10;
@@ -108,8 +89,7 @@ public class AffineTransform implements Cloneable, Serializable {
this.m12 = m12;
}
- public AffineTransform(Vertex.Factory<? extends Vertex> factory, float[] matrix) {
- pointFactory = factory;
+ public AffineTransform(final float[] matrix) {
this.type = TYPE_UNKNOWN;
m00 = matrix[0];
m10 = matrix[1];
@@ -123,20 +103,20 @@ public class AffineTransform implements Cloneable, Serializable {
/*
* Method returns type of affine transformation.
- *
+ *
* Transform matrix is
* m00 m01 m02
* m10 m11 m12
- *
- * According analytic geometry new basis vectors are (m00, m01) and (m10, m11),
- * translation vector is (m02, m12). Original basis vectors are (1, 0) and (0, 1).
- * Type transformations classification:
+ *
+ * According analytic geometry new basis vectors are (m00, m01) and (m10, m11),
+ * translation vector is (m02, m12). Original basis vectors are (1, 0) and (0, 1).
+ * Type transformations classification:
* TYPE_IDENTITY - new basis equals original one and zero translation
- * TYPE_TRANSLATION - translation vector isn't zero
+ * TYPE_TRANSLATION - translation vector isn't zero
* TYPE_UNIFORM_SCALE - vectors length of new basis equals
- * TYPE_GENERAL_SCALE - vectors length of new basis doesn't equal
+ * TYPE_GENERAL_SCALE - vectors length of new basis doesn't equal
* TYPE_FLIP - new basis vector orientation differ from original one
- * TYPE_QUADRANT_ROTATION - new basis is rotated by 90, 180, 270, or 360 degrees
+ * TYPE_QUADRANT_ROTATION - new basis is rotated by 90, 180, 270, or 360 degrees
* TYPE_GENERAL_ROTATION - new basis is rotated by arbitrary angle
* TYPE_GENERAL_TRANSFORM - transformation can't be inversed
*/
@@ -164,8 +144,8 @@ public class AffineTransform implements Cloneable, Serializable {
type |= TYPE_FLIP;
}
- float dx = m00 * m00 + m10 * m10;
- float dy = m01 * m01 + m11 * m11;
+ final float dx = m00 * m00 + m10 * m10;
+ final float dy = m01 * m01 + m11 * m11;
if (dx != dy) {
type |= TYPE_GENERAL_SCALE;
} else
@@ -185,35 +165,35 @@ public class AffineTransform implements Cloneable, Serializable {
return type;
}
- public float getScaleX() {
+ public final float getScaleX() {
return m00;
}
- public float getScaleY() {
+ public final float getScaleY() {
return m11;
}
- public float getShearX() {
+ public final float getShearX() {
return m01;
}
- public float getShearY() {
+ public final float getShearY() {
return m10;
}
- public float getTranslateX() {
+ public final float getTranslateX() {
return m02;
}
- public float getTranslateY() {
+ public final float getTranslateY() {
return m12;
}
- public boolean isIdentity() {
+ public final boolean isIdentity() {
return getType() == TYPE_IDENTITY;
}
- public void getMatrix(float[] matrix) {
+ public final void getMatrix(final float[] matrix) {
matrix[0] = m00;
matrix[1] = m10;
matrix[2] = m01;
@@ -224,11 +204,11 @@ public class AffineTransform implements Cloneable, Serializable {
}
}
- public float getDeterminant() {
+ public final float getDeterminant() {
return m00 * m11 - m01 * m10;
}
- public void setTransform(float m00, float m10, float m01, float m11, float m02, float m12) {
+ public final AffineTransform setTransform(final float m00, final float m10, final float m01, final float m11, final float m02, final float m12) {
this.type = TYPE_UNKNOWN;
this.m00 = m00;
this.m10 = m10;
@@ -236,20 +216,23 @@ public class AffineTransform implements Cloneable, Serializable {
this.m11 = m11;
this.m02 = m02;
this.m12 = m12;
+ return this;
}
- public void setTransform(AffineTransform t) {
+ public final AffineTransform setTransform(final AffineTransform t) {
type = t.type;
setTransform(t.m00, t.m10, t.m01, t.m11, t.m02, t.m12);
+ return this;
}
- public void setToIdentity() {
+ public final AffineTransform setToIdentity() {
type = TYPE_IDENTITY;
m00 = m11 = 1.0f;
m10 = m01 = m02 = m12 = 0.0f;
+ return this;
}
- public void setToTranslation(float mx, float my) {
+ public final AffineTransform setToTranslation(final float mx, final float my) {
m00 = m11 = 1.0f;
m01 = m10 = 0.0f;
m02 = mx;
@@ -259,9 +242,10 @@ public class AffineTransform implements Cloneable, Serializable {
} else {
type = TYPE_TRANSLATION;
}
+ return this;
}
- public void setToScale(float scx, float scy) {
+ public final AffineTransform setToScale(final float scx, final float scy) {
m00 = scx;
m11 = scy;
m10 = m01 = m02 = m12 = 0.0f;
@@ -270,9 +254,10 @@ public class AffineTransform implements Cloneable, Serializable {
} else {
type = TYPE_IDENTITY;
}
+ return this;
}
- public void setToShear(float shx, float shy) {
+ public final AffineTransform setToShear(final float shx, final float shy) {
m00 = m11 = 1.0f;
m02 = m12 = 0.0f;
m01 = shx;
@@ -282,16 +267,17 @@ public class AffineTransform implements Cloneable, Serializable {
} else {
type = TYPE_IDENTITY;
}
+ return this;
}
- public void setToRotation(float angle) {
- float sin = MathFloat.sin(angle);
- float cos = MathFloat.cos(angle);
- if (MathFloat.abs(cos) < ZERO) {
+ public final AffineTransform setToRotation(final float angle) {
+ float sin = FloatUtil.sin(angle);
+ float cos = FloatUtil.cos(angle);
+ if (FloatUtil.abs(cos) < ZERO) {
cos = 0.0f;
sin = sin > 0.0f ? 1.0f : -1.0f;
} else
- if (MathFloat.abs(sin) < ZERO) {
+ if (FloatUtil.abs(sin) < ZERO) {
sin = 0.0f;
cos = cos > 0.0f ? 1.0f : -1.0f;
}
@@ -300,98 +286,108 @@ public class AffineTransform implements Cloneable, Serializable {
m10 = sin;
m02 = m12 = 0.0f;
type = TYPE_UNKNOWN;
+ return this;
}
- public void setToRotation(float angle, float px, float py) {
+ public final AffineTransform setToRotation(final float angle, final float px, final float py) {
setToRotation(angle);
m02 = px * (1.0f - m00) + py * m10;
m12 = py * (1.0f - m00) - px * m10;
type = TYPE_UNKNOWN;
+ return this;
}
- public static <T extends Vertex> AffineTransform getTranslateInstance(Vertex.Factory<? extends Vertex> factory, float mx, float my) {
- AffineTransform t = new AffineTransform(factory);
- t.setToTranslation(mx, my);
- return t;
- }
-
- public static <T extends Vertex> AffineTransform getScaleInstance(Vertex.Factory<? extends Vertex> factory, float scx, float scY) {
- AffineTransform t = new AffineTransform(factory);
- t.setToScale(scx, scY);
- return t;
- }
-
- public static <T extends Vertex> AffineTransform getShearInstance(Vertex.Factory<? extends Vertex> factory, float shx, float shy) {
- AffineTransform t = new AffineTransform(factory);
- t.setToShear(shx, shy);
- return t;
- }
-
- public static <T extends Vertex> AffineTransform getRotateInstance(Vertex.Factory<? extends Vertex> factory, float angle) {
- AffineTransform t = new AffineTransform(factory);
- t.setToRotation(angle);
- return t;
- }
-
- public static <T extends Vertex> AffineTransform getRotateInstance(Vertex.Factory<? extends Vertex> factory, float angle, float x, float y) {
- AffineTransform t = new AffineTransform(factory);
- t.setToRotation(angle, x, y);
- return t;
- }
-
- public void translate(float mx, float my) {
- concatenate(AffineTransform.getTranslateInstance(pointFactory, mx, my));
+ public final AffineTransform translate(final float mx, final float my, final AffineTransform tmp) {
+ return concatenate(tmp.setToTranslation(mx, my));
}
- public void scale(float scx, float scy) {
- concatenate(AffineTransform.getScaleInstance(pointFactory, scx, scy));
+ public final AffineTransform scale(final float scx, final float scy, final AffineTransform tmp) {
+ return concatenate(tmp.setToScale(scx, scy));
}
- public void shear(float shx, float shy) {
- concatenate(AffineTransform.getShearInstance(pointFactory, shx, shy));
+ public final AffineTransform shear(final float shx, final float shy, final AffineTransform tmp) {
+ return concatenate(tmp.setToShear(shx, shy));
}
- public void rotate(float angle) {
- concatenate(AffineTransform.getRotateInstance(pointFactory, angle));
+ public final AffineTransform rotate(final float angle, final AffineTransform tmp) {
+ return concatenate(tmp.setToRotation(angle));
}
- public void rotate(float angle, float px, float py) {
- concatenate(AffineTransform.getRotateInstance(pointFactory, angle, px, py));
+ public final AffineTransform rotate(final float angle, final float px, final float py, final AffineTransform tmp) {
+ return concatenate(tmp.setToRotation(angle, px, py));
}
- /**
+ /**
* Multiply matrix of two AffineTransform objects.
- * The first argument's {@link Vertex.Factory} is being used.
- *
- * @param t1 - the AffineTransform object is a multiplicand
- * @param t2 - the AffineTransform object is a multiplier
- * @return an AffineTransform object that is a result of t1 multiplied by matrix t2.
+ * @param tL - the AffineTransform object is a multiplicand (left argument)
+ * @param tR - the AffineTransform object is a multiplier (right argument)
+ *
+ * @return A new AffineTransform object containing the result of [tL] X [tR].
*/
- AffineTransform multiply(AffineTransform t1, AffineTransform t2) {
- return new AffineTransform(t1.pointFactory,
- t1.m00 * t2.m00 + t1.m10 * t2.m01, // m00
- t1.m00 * t2.m10 + t1.m10 * t2.m11, // m01
- t1.m01 * t2.m00 + t1.m11 * t2.m01, // m10
- t1.m01 * t2.m10 + t1.m11 * t2.m11, // m11
- t1.m02 * t2.m00 + t1.m12 * t2.m01 + t2.m02, // m02
- t1.m02 * t2.m10 + t1.m12 * t2.m11 + t2.m12);// m12
- }
-
- public void concatenate(AffineTransform t) {
- setTransform(multiply(t, this));
+ public final static AffineTransform multiply(final AffineTransform tL, final AffineTransform tR) {
+ return new AffineTransform(
+ tR.m00 * tL.m00 + tR.m10 * tL.m01, // m00
+ tR.m00 * tL.m10 + tR.m10 * tL.m11, // m10
+ tR.m01 * tL.m00 + tR.m11 * tL.m01, // m01
+ tR.m01 * tL.m10 + tR.m11 * tL.m11, // m11
+ tR.m02 * tL.m00 + tR.m12 * tL.m01 + tL.m02, // m02
+ tR.m02 * tL.m10 + tR.m12 * tL.m11 + tL.m12);// m12
}
- public void preConcatenate(AffineTransform t) {
- setTransform(multiply(this, t));
+ /**
+ * Concatenates the given matrix to this.
+ * <p>
+ * Implementations performs the matrix multiplication:
+ * <pre>
+ * [this] = [this] X [tR]
+ * </pre>
+ * </p>
+ * @param tR the right-argument of the matrix multiplication
+ * @return this transform for chaining
+ */
+ public final AffineTransform concatenate(final AffineTransform tR) {
+ // setTransform(multiply(this, tR));
+ type = TYPE_UNKNOWN;
+ setTransform(
+ tR.m00 * m00 + tR.m10 * m01, // m00
+ tR.m00 * m10 + tR.m10 * m11, // m10
+ tR.m01 * m00 + tR.m11 * m01, // m01
+ tR.m01 * m10 + tR.m11 * m11, // m11
+ tR.m02 * m00 + tR.m12 * m01 + m02, // m02
+ tR.m02 * m10 + tR.m12 * m11 + m12);// m12
+ return this;
}
- public AffineTransform createInverse() throws NoninvertibleTransformException {
- float det = getDeterminant();
- if (MathFloat.abs(det) < ZERO) {
+ /**
+ * Pre-concatenates the given matrix to this.
+ * <p>
+ * Implementations performs the matrix multiplication:
+ * <pre>
+ * [this] = [tL] X [this]
+ * </pre>
+ * </p>
+ * @param tL the left-argument of the matrix multiplication
+ * @return this transform for chaining
+ */
+ public final AffineTransform preConcatenate(final AffineTransform tL) {
+ // setTransform(multiply(tL, this));
+ type = TYPE_UNKNOWN;
+ setTransform(
+ m00 * tL.m00 + m10 * tL.m01, // m00
+ m00 * tL.m10 + m10 * tL.m11, // m10
+ m01 * tL.m00 + m11 * tL.m01, // m01
+ m01 * tL.m10 + m11 * tL.m11, // m11
+ m02 * tL.m00 + m12 * tL.m01 + tL.m02, // m02
+ m02 * tL.m10 + m12 * tL.m11 + tL.m12);// m12
+ return this;
+ }
+
+ public final AffineTransform createInverse() throws NoninvertibleTransformException {
+ final float det = getDeterminant();
+ if (FloatUtil.abs(det) < ZERO) {
throw new NoninvertibleTransformException(determinantIsZero);
}
return new AffineTransform(
- this.pointFactory,
m11 / det, // m00
-m10 / det, // m10
-m01 / det, // m01
@@ -401,33 +397,67 @@ public class AffineTransform implements Cloneable, Serializable {
);
}
- public Vertex transform(Vertex src, Vertex dst) {
- if (dst == null) {
- dst = pointFactory.create();
- }
-
- float x = src.getX();
- float y = src.getY();
+ /**
+ *
+ * @param src
+ * @param dst
+ * @return dst for chaining
+ */
+ public final AABBox transform(final AABBox src, final AABBox dst) {
+ final float[] srcLo = src.getLow();
+ final float[] srcHi = src.getHigh();
+ dst.setSize(srcLo[0] * m00 + srcLo[1] * m01 + m02, srcLo[0] * m10 + srcLo[1] * m11 + m12, srcLo[2],
+ srcHi[0] * m00 + srcHi[1] * m01 + m02, srcHi[0] * m10 + srcHi[1] * m11 + m12, srcHi[2]);
+ return dst;
+ }
- dst.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12, 0f);
+ /**
+ * @param src
+ * @param dst
+ * @return dst for chaining
+ */
+ public final Vertex transform(final Vertex src, final Vertex dst) {
+ final float x = src.getX();
+ final float y = src.getY();
+ dst.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12, src.getZ());
return dst;
}
- public void transform(Vertex[] src, int srcOff, Vertex[] dst, int dstOff, int length) {
+ public final void transform(final Vertex[] src, int srcOff, final Vertex[] dst, int dstOff, int length) {
while (--length >= 0) {
- Vertex srcPoint = src[srcOff++];
- float x = srcPoint.getX();
- float y = srcPoint.getY();
- Vertex dstPoint = dst[dstOff];
+ final Vertex srcPoint = src[srcOff++];
+ final Vertex dstPoint = dst[dstOff];
if (dstPoint == null) {
throw new IllegalArgumentException("dst["+dstOff+"] is null");
}
- dstPoint.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12, 0f);
+ final float x = srcPoint.getX();
+ final float y = srcPoint.getY();
+ dstPoint.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12, srcPoint.getZ());
dst[dstOff++] = dstPoint;
}
}
-
- public void transform(float[] src, int srcOff, float[] dst, int dstOff, int length) {
+
+ /**
+ * @param src float[2] source of transformation
+ * @param dst float[2] destination of transformation, maybe be equal to <code>src</code>
+ * @return dst for chaining
+ */
+ public final float[] transform(final float[] src, final float[] dst) {
+ final float x = src[0];
+ final float y = src[1];
+ dst[0] = x * m00 + y * m01 + m02;
+ dst[1] = x * m10 + y * m11 + m12;
+ return dst;
+ }
+
+ public final void transform(final float[] src, final int srcOff, final float[] dst, final int dstOff) {
+ final float x = src[srcOff + 0];
+ final float y = src[srcOff + 1];
+ dst[dstOff + 0] = x * m00 + y * m01 + m02;
+ dst[dstOff + 1] = x * m10 + y * m11 + m12;
+ }
+
+ public final void transform(final float[] src, int srcOff, final float[] dst, int dstOff, int length) {
int step = 2;
if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) {
srcOff = srcOff + length * 2 - 2;
@@ -435,83 +465,87 @@ public class AffineTransform implements Cloneable, Serializable {
step = -2;
}
while (--length >= 0) {
- float x = src[srcOff + 0];
- float y = src[srcOff + 1];
+ final float x = src[srcOff + 0];
+ final float y = src[srcOff + 1];
dst[dstOff + 0] = x * m00 + y * m01 + m02;
dst[dstOff + 1] = x * m10 + y * m11 + m12;
srcOff += step;
dstOff += step;
}
}
-
- public Vertex deltaTransform(Vertex src, Vertex dst) {
- if (dst == null) {
- dst = pointFactory.create();
- }
- float x = src.getX();
- float y = src.getY();
-
- dst.setCoord(x * m00 + y * m01, x * m10 + y * m11, 0f);
+ /**
+ *
+ * @param src
+ * @param dst
+ * @return return dst for chaining
+ */
+ public final Vertex deltaTransform(final Vertex src, final Vertex dst) {
+ final float x = src.getX();
+ final float y = src.getY();
+ dst.setCoord(x * m00 + y * m01, x * m10 + y * m11, src.getZ());
return dst;
}
- public void deltaTransform(float[] src, int srcOff, float[] dst, int dstOff, int length) {
+ public final void deltaTransform(final float[] src, int srcOff, final float[] dst, int dstOff, int length) {
while (--length >= 0) {
- float x = src[srcOff++];
- float y = src[srcOff++];
+ final float x = src[srcOff++];
+ final float y = src[srcOff++];
dst[dstOff++] = x * m00 + y * m01;
dst[dstOff++] = x * m10 + y * m11;
}
}
- public Vertex inverseTransform(Vertex src, Vertex dst) throws NoninvertibleTransformException {
- float det = getDeterminant();
- if (MathFloat.abs(det) < ZERO) {
+ /**
+ *
+ * @param src
+ * @param dst
+ * @return return dst for chaining
+ * @throws NoninvertibleTransformException
+ */
+ public final Vertex inverseTransform(final Vertex src, final Vertex dst) throws NoninvertibleTransformException {
+ final float det = getDeterminant();
+ if (FloatUtil.abs(det) < ZERO) {
throw new NoninvertibleTransformException(determinantIsZero);
}
- if (dst == null) {
- dst = pointFactory.create();
- }
-
- float x = src.getX() - m02;
- float y = src.getY() - m12;
-
- dst.setCoord((x * m11 - y * m01) / det, (y * m00 - x * m10) / det, 0f);
+ final float x = src.getX() - m02;
+ final float y = src.getY() - m12;
+ dst.setCoord((x * m11 - y * m01) / det, (y * m00 - x * m10) / det, src.getZ());
return dst;
}
- public void inverseTransform(float[] src, int srcOff, float[] dst, int dstOff, int length)
+ public final void inverseTransform(final float[] src, int srcOff, final float[] dst, int dstOff, int length)
throws NoninvertibleTransformException
{
- float det = getDeterminant();
- if (MathFloat.abs(det) < ZERO) {
- throw new NoninvertibleTransformException(determinantIsZero);
+ final float det = getDeterminant();
+ if (FloatUtil.abs(det) < ZERO) {
+ throw new NoninvertibleTransformException(determinantIsZero);
}
while (--length >= 0) {
- float x = src[srcOff++] - m02;
- float y = src[srcOff++] - m12;
+ final float x = src[srcOff++] - m02;
+ final float y = src[srcOff++] - m12;
dst[dstOff++] = (x * m11 - y * m01) / det;
dst[dstOff++] = (y * m00 - x * m10) / det;
}
}
- public Path2D createTransformedShape(Path2D src) {
+ public final Path2D createTransformedShape(final Path2D src) {
if (src == null) {
return null;
}
- if (src instanceof Path2D) {
- return ((Path2D)src).createTransformedShape(this);
- }
- PathIterator path = src.iterator(this);
- Path2D dst = new Path2D(path.getWindingRule());
- dst.append(path, false);
- return dst;
+ return src.createTransformedShape(this);
+ /**
+ * If !(src instanceof Path2D): (but here it always is)
+ final PathIterator path = src.iterator(this);
+ final Path2D dst = new Path2D(path.getWindingRule());
+ dst.append(path, false);
+ return dst;
+ */
}
@Override
- public String toString() {
+ public final String toString() {
return
getClass().getName() +
"[[" + m00 + ", " + m01 + ", " + m02 + "], [" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
@@ -519,10 +553,10 @@ public class AffineTransform implements Cloneable, Serializable {
}
@Override
- public AffineTransform clone() {
+ public final AffineTransform clone() {
try {
return (AffineTransform) super.clone();
- } catch (CloneNotSupportedException e) {
+ } catch (final CloneNotSupportedException e) {
throw new InternalError();
}
}
@@ -540,12 +574,12 @@ public class AffineTransform implements Cloneable, Serializable {
} */
@Override
- public boolean equals(Object obj) {
+ public final boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof AffineTransform) {
- AffineTransform t = (AffineTransform)obj;
+ final AffineTransform t = (AffineTransform)obj;
return
m00 == t.m00 && m01 == t.m01 &&
m02 == t.m02 && m10 == t.m10 &&
@@ -553,28 +587,9 @@ public class AffineTransform implements Cloneable, Serializable {
}
return false;
}
-
-
- /**
- * Write AffineTrasform object to the output steam.
- * @param stream - the output stream
- * @throws IOException - if there are I/O errors while writing to the output strem
- */
- private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
- stream.defaultWriteObject();
- }
-
-
- /**
- * Read AffineTransform object from the input stream
- * @param stream - the input steam
- * @throws IOException - if there are I/O errors while reading from the input strem
- * @throws ClassNotFoundException - if class could not be found
- */
- private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
- stream.defaultReadObject();
- type = TYPE_UNKNOWN;
+ @Override
+ public final int hashCode() {
+ throw new InternalError("hashCode not designed");
}
-
}
diff --git a/src/jogl/classes/jogamp/graph/math/plane/Crossing.java b/src/jogl/classes/jogamp/graph/geom/plane/Crossing.java
index 9be5978cc..2ae9d1867 100644
--- a/src/jogl/classes/jogamp/graph/math/plane/Crossing.java
+++ b/src/jogl/classes/jogamp/graph/geom/plane/Crossing.java
@@ -17,11 +17,10 @@
/**
* @author Denis M. Kishenko
*/
-package jogamp.graph.math.plane;
+package jogamp.graph.geom.plane;
+
+import com.jogamp.opengl.math.FloatUtil;
-import jogamp.graph.geom.plane.Path2D;
-import jogamp.graph.geom.plane.PathIterator;
-import jogamp.graph.math.MathFloat;
public class Crossing {
@@ -30,17 +29,17 @@ public class Crossing {
* Allowable tolerance for bounds comparison
*/
static final float DELTA = (float) 1E-5;
-
+
/**
* If roots have distance less then <code>ROOT_DELTA</code> they are double
*/
static final float ROOT_DELTA = (float) 1E-10;
-
+
/**
* Rectangle cross segment
*/
public static final int CROSSING = 255;
-
+
/**
* Unknown crossing result
*/
@@ -52,10 +51,10 @@ public class Crossing {
* @param res - the roots of the equation
* @return a number of roots
*/
- public static int solveQuad(float eqn[], float res[]) {
- float a = eqn[2];
- float b = eqn[1];
- float c = eqn[0];
+ public static int solveQuad(final float eqn[], final float res[]) {
+ final float a = eqn[2];
+ final float b = eqn[1];
+ final float c = eqn[0];
int rc = 0;
if (a == 0.0) {
if (b == 0.0) {
@@ -68,7 +67,7 @@ public class Crossing {
if (d < 0.0) {
return 0;
}
- d = MathFloat.sqrt(d);
+ d = FloatUtil.sqrt(d);
res[rc++] = (- b + d) / (a * 2.0f);
// d != 0.0
if (d != 0.0) {
@@ -84,32 +83,32 @@ public class Crossing {
* @param res - the roots of the equation
* @return a number of roots
*/
- public static int solveCubic(float eqn[], float res[]) {
- float d = eqn[3];
+ public static int solveCubic(final float eqn[], final float res[]) {
+ final float d = eqn[3];
if (d == 0) {
return solveQuad(eqn, res);
}
- float a = eqn[2] / d;
- float b = eqn[1] / d;
- float c = eqn[0] / d;
+ final float a = eqn[2] / d;
+ final float b = eqn[1] / d;
+ final float c = eqn[0] / d;
int rc = 0;
- float Q = (a * a - 3.0f * b) / 9.0f;
- float R = (2.0f * a * a * a - 9.0f * a * b + 27.0f * c) / 54.0f;
- float Q3 = Q * Q * Q;
- float R2 = R * R;
- float n = - a / 3.0f;
+ final float Q = (a * a - 3.0f * b) / 9.0f;
+ final float R = (2.0f * a * a * a - 9.0f * a * b + 27.0f * c) / 54.0f;
+ final float Q3 = Q * Q * Q;
+ final float R2 = R * R;
+ final float n = - a / 3.0f;
if (R2 < Q3) {
- float t = MathFloat.acos(R / MathFloat.sqrt(Q3)) / 3.0f;
- float p = 2.0f * MathFloat.PI / 3.0f;
- float m = -2.0f * MathFloat.sqrt(Q);
- res[rc++] = m * MathFloat.cos(t) + n;
- res[rc++] = m * MathFloat.cos(t + p) + n;
- res[rc++] = m * MathFloat.cos(t - p) + n;
+ final float t = FloatUtil.acos(R / FloatUtil.sqrt(Q3)) / 3.0f;
+ final float p = 2.0f * FloatUtil.PI / 3.0f;
+ final float m = -2.0f * FloatUtil.sqrt(Q);
+ res[rc++] = m * FloatUtil.cos(t) + n;
+ res[rc++] = m * FloatUtil.cos(t + p) + n;
+ res[rc++] = m * FloatUtil.cos(t - p) + n;
} else {
// Debug.println("R2 >= Q3 (" + R2 + "/" + Q3 + ")");
- float A = MathFloat.pow(MathFloat.abs(R) + MathFloat.sqrt(R2 - Q3), 1.0f / 3.0f);
+ float A = FloatUtil.pow(FloatUtil.abs(R) + FloatUtil.sqrt(R2 - Q3), 1.0f / 3.0f);
if (R > 0.0) {
A = -A;
}
@@ -117,10 +116,10 @@ public class Crossing {
if (-ROOT_DELTA < A && A < ROOT_DELTA) {
res[rc++] = n;
} else {
- float B = Q / A;
+ final float B = Q / A;
res[rc++] = A + B + n;
// if (R2 == Q3) {
- float delta = R2 - Q3;
+ final float delta = R2 - Q3;
if (-ROOT_DELTA < delta && delta < ROOT_DELTA) {
res[rc++] = - (A + B) / 2.0f + n;
}
@@ -131,12 +130,12 @@ public class Crossing {
}
/**
- * Excludes float roots. Roots are float if they lies enough close with each other.
- * @param res - the roots
+ * Excludes float roots. Roots are float if they lies enough close with each other.
+ * @param res - the roots
* @param rc - the roots count
* @return new roots count
*/
- static int fixRoots(float res[], int rc) {
+ static int fixRoots(final float res[], final int rc) {
int tc = 0;
for(int i = 0; i < rc; i++) {
out: {
@@ -159,7 +158,7 @@ public class Crossing {
float ax, ay, bx, by;
float Ax, Ay, Bx, By;
- public QuadCurve(float x1, float y1, float cx, float cy, float x2, float y2) {
+ public QuadCurve(final float x1, final float y1, final float cx, final float cy, final float x2, final float y2) {
ax = x2 - x1;
ay = y2 - y1;
bx = cx - x1;
@@ -172,11 +171,11 @@ public class Crossing {
Ay = ay - By; // Ay = ay - 2.0 * by
}
- int cross(float res[], int rc, float py1, float py2) {
+ int cross(final float res[], final int rc, final float py1, final float py2) {
int cross = 0;
for (int i = 0; i < rc; i++) {
- float t = res[i];
+ final float t = res[i];
// CURVE-OUTSIDE
if (t < -DELTA || t > 1 + DELTA) {
@@ -191,16 +190,17 @@ public class Crossing {
}
// CURVE-END
if (t > 1 - DELTA) {
+ // FIXME: consider using FloatUtil.isEqual(ax, bx, epsilon), ...
if (py1 < ay && (ax != bx ? ax - bx : bx) > 0.0) {
cross++;
}
continue;
}
// CURVE-INSIDE
- float ry = t * (t * Ay + By);
+ final float ry = t * (t * Ay + By);
// ry = t * t * Ay + t * By
if (ry > py2) {
- float rxt = t * Ax + bx;
+ final float rxt = t * Ax + bx;
// rxt = 2.0 * t * Ax + Bx = 2.0 * t * Ax + 2.0 * bx
if (rxt > -DELTA && rxt < DELTA) {
continue;
@@ -212,12 +212,12 @@ public class Crossing {
return cross;
}
- int solvePoint(float res[], float px) {
- float eqn[] = {-px, Bx, Ax};
+ int solvePoint(final float res[], final float px) {
+ final float eqn[] = {-px, Bx, Ax};
return solveQuad(eqn, res);
}
- int solveExtrem(float res[]) {
+ int solveExtrem(final float res[]) {
int rc = 0;
if (Ax != 0.0) {
res[rc++] = - Bx / (Ax + Ax);
@@ -228,11 +228,11 @@ public class Crossing {
return rc;
}
- int addBound(float bound[], int bc, float res[], int rc, float minX, float maxX, boolean changeId, int id) {
+ int addBound(final float bound[], int bc, final float res[], final int rc, final float minX, final float maxX, final boolean changeId, int id) {
for(int i = 0; i < rc; i++) {
- float t = res[i];
+ final float t = res[i];
if (t > -DELTA && t < 1 + DELTA) {
- float rx = t * (t * Ax + Bx);
+ final float rx = t * (t * Ax + Bx);
if (minX <= rx && rx <= maxX) {
bound[bc++] = t;
bound[bc++] = rx;
@@ -258,7 +258,7 @@ public class Crossing {
float Ax, Ay, Bx, By, Cx, Cy;
float Ax3, Bx2;
- public CubicCurve(float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2) {
+ public CubicCurve(final float x1, final float y1, final float cx1, final float cy1, final float cx2, final float cy2, final float x2, final float y2) {
ax = x2 - x1;
ay = y2 - y1;
bx = cx1 - x1;
@@ -278,10 +278,10 @@ public class Crossing {
Bx2 = Bx + Bx;
}
- int cross(float res[], int rc, float py1, float py2) {
+ int cross(final float res[], final int rc, final float py1, final float py2) {
int cross = 0;
for (int i = 0; i < rc; i++) {
- float t = res[i];
+ final float t = res[i];
// CURVE-OUTSIDE
if (t < -DELTA || t > 1 + DELTA) {
@@ -289,6 +289,7 @@ public class Crossing {
}
// CURVE-START
if (t < DELTA) {
+ // FIXME: consider using FloatUtil.isZero(bx, epsilon), ...
if (py1 < 0.0 && (bx != 0.0 ? bx : (cx != bx ? cx - bx : ax - cx)) < 0.0) {
cross--;
}
@@ -302,7 +303,7 @@ public class Crossing {
continue;
}
// CURVE-INSIDE
- float ry = t * (t * (t * Ay + By) + Cy);
+ final float ry = t * (t * (t * Ay + By) + Cy);
// ry = t * t * t * Ay + t * t * By + t * Cy
if (ry > py2) {
float rxt = t * (t * Ax3 + Bx2) + Cx;
@@ -323,26 +324,26 @@ public class Crossing {
return cross;
}
- int solvePoint(float res[], float px) {
- float eqn[] = {-px, Cx, Bx, Ax};
+ int solvePoint(final float res[], final float px) {
+ final float eqn[] = {-px, Cx, Bx, Ax};
return solveCubic(eqn, res);
}
- int solveExtremX(float res[]) {
- float eqn[] = {Cx, Bx2, Ax3};
+ int solveExtremX(final float res[]) {
+ final float eqn[] = {Cx, Bx2, Ax3};
return solveQuad(eqn, res);
}
- int solveExtremY(float res[]) {
- float eqn[] = {Cy, By + By, Ay + Ay + Ay};
+ int solveExtremY(final float res[]) {
+ final float eqn[] = {Cy, By + By, Ay + Ay + Ay};
return solveQuad(eqn, res);
}
- int addBound(float bound[], int bc, float res[], int rc, float minX, float maxX, boolean changeId, int id) {
+ int addBound(final float bound[], int bc, final float res[], final int rc, final float minX, final float maxX, final boolean changeId, int id) {
for(int i = 0; i < rc; i++) {
- float t = res[i];
+ final float t = res[i];
if (t > -DELTA && t < 1 + DELTA) {
- float rx = t * (t * (t * Ax + Bx) + Cx);
+ final float rx = t * (t * (t * Ax + Bx) + Cx);
if (minX <= rx && rx <= maxX) {
bound[bc++] = t;
bound[bc++] = rx;
@@ -362,7 +363,7 @@ public class Crossing {
/**
* Returns how many times ray from point (x,y) cross line.
*/
- public static int crossLine(float x1, float y1, float x2, float y2, float x, float y) {
+ public static int crossLine(final float x1, final float y1, final float x2, final float y2, final float x, final float y) {
// LEFT/RIGHT/UP/EMPTY
if ((x < x1 && x < x2) ||
@@ -385,12 +386,12 @@ public class Crossing {
// START
if (x == x1) {
- return x1 < x2 ? 0 : -1;
+ return x1 < x2 ? 0 : -1;
}
-
+
// END
if (x == x2) {
- return x1 < x2 ? 1 : 0;
+ return x1 < x2 ? 1 : 0;
}
// INSIDE-DOWN
@@ -400,7 +401,7 @@ public class Crossing {
/**
* Returns how many times ray from point (x,y) cross quard curve
*/
- public static int crossQuad(float x1, float y1, float cx, float cy, float x2, float y2, float x, float y) {
+ public static int crossQuad(final float x1, final float y1, final float cx, final float cy, final float x2, final float y2, final float x, final float y) {
// LEFT/RIGHT/UP/EMPTY
if ((x < x1 && x < cx && x < x2) ||
@@ -420,11 +421,11 @@ public class Crossing {
}
// INSIDE
- QuadCurve c = new QuadCurve(x1, y1, cx, cy, x2, y2);
- float px = x - x1;
- float py = y - y1;
- float res[] = new float[3];
- int rc = c.solvePoint(res, px);
+ final QuadCurve c = new QuadCurve(x1, y1, cx, cy, x2, y2);
+ final float px = x - x1;
+ final float py = y - y1;
+ final float res[] = new float[3];
+ final int rc = c.solvePoint(res, px);
return c.cross(res, rc, py, py);
}
@@ -432,7 +433,7 @@ public class Crossing {
/**
* Returns how many times ray from point (x,y) cross cubic curve
*/
- public static int crossCubic(float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, float x, float y) {
+ public static int crossCubic(final float x1, final float y1, final float cx1, final float cy1, final float cx2, final float cy2, final float x2, final float y2, final float x, final float y) {
// LEFT/RIGHT/UP/EMPTY
if ((x < x1 && x < cx1 && x < cx2 && x < x2) ||
@@ -452,18 +453,18 @@ public class Crossing {
}
// INSIDE
- CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
- float px = x - x1;
- float py = y - y1;
- float res[] = new float[3];
- int rc = c.solvePoint(res, px);
+ final CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
+ final float px = x - x1;
+ final float py = y - y1;
+ final float res[] = new float[3];
+ final int rc = c.solvePoint(res, px);
return c.cross(res, rc, py, py);
}
/**
* Returns how many times ray from point (x,y) cross path
*/
- public static int crossPath(PathIterator p, float x, float y) {
+ public static int crossPath(final PathIterator p, final float x, final float y) {
int cross = 0;
float mx, my, cx, cy;
mx = my = cx = cy = 0.0f;
@@ -494,10 +495,10 @@ public class Crossing {
}
break;
default:
- throw new IllegalArgumentException("Unhandled Segment Type: "+segmentType);
+ throw new IllegalArgumentException("Unhandled Segment Type: "+segmentType);
}
-
- // checks if the point (x,y) is the vertex of shape with PathIterator p
+
+ // checks if the point (x,y) is the vertex of shape with PathIterator p
if (x == cx && y == cy) {
cross = 0;
cy = my;
@@ -514,7 +515,7 @@ public class Crossing {
/**
* Returns how many times ray from point (x,y) cross shape
*/
- public static int crossShape(Path2D s, float x, float y) {
+ public static int crossShape(final Path2D s, final float x, final float y) {
if (!s.getBounds2D().contains(x, y)) {
return 0;
}
@@ -524,14 +525,14 @@ public class Crossing {
/**
* Returns true if value enough small
*/
- public static boolean isZero(float val) {
+ public static boolean isZero(final float val) {
return -DELTA < val && val < DELTA;
}
/**
* Sort bound array
*/
- static void sortBound(float bound[], int bc) {
+ static void sortBound(final float bound[], final int bc) {
for(int i = 0; i < bc - 4; i += 4) {
int k = i;
for(int j = i + 4; j < bc; j += 4) {
@@ -555,11 +556,11 @@ public class Crossing {
}
}
}
-
+
/**
- * Returns are bounds intersect or not intersect rectangle
+ * Returns are bounds intersect or not intersect rectangle
*/
- static int crossBound(float bound[], int bc, float py1, float py2) {
+ static int crossBound(final float bound[], final int bc, final float py1, final float py2) {
// LEFT/RIGHT
if (bc == 0) {
@@ -591,7 +592,7 @@ public class Crossing {
sortBound(bound, bc);
boolean sign = bound[2] > py2;
for(int i = 6; i < bc; i += 4) {
- boolean sign2 = bound[i] > py2;
+ final boolean sign2 = bound[i] > py2;
if (sign != sign2 && bound[i + 1] != bound[i - 3]) {
return CROSSING;
}
@@ -604,7 +605,7 @@ public class Crossing {
/**
* Returns how many times rectangle stripe cross line or the are intersect
*/
- public static int intersectLine(float x1, float y1, float x2, float y2, float rx1, float ry1, float rx2, float ry2) {
+ public static int intersectLine(final float x1, final float y1, final float x2, final float y2, final float rx1, final float ry1, final float rx2, final float ry2) {
// LEFT/RIGHT/UP
if ((rx2 < x1 && rx2 < x2) ||
@@ -632,9 +633,9 @@ public class Crossing {
bx1 = x2 < rx1 ? rx1 : x2;
bx2 = x1 < rx2 ? x1 : rx2;
}
- float k = (y2 - y1) / (x2 - x1);
- float by1 = k * (bx1 - x1) + y1;
- float by2 = k * (bx2 - x1) + y1;
+ final float k = (y2 - y1) / (x2 - x1);
+ final float by1 = k * (bx1 - x1) + y1;
+ final float by2 = k * (bx2 - x1) + y1;
// BOUND-UP
if (by1 < ry1 && by2 < ry1) {
@@ -673,7 +674,7 @@ public class Crossing {
/**
* Returns how many times rectangle stripe cross quad curve or the are intersect
*/
- public static int intersectQuad(float x1, float y1, float cx, float cy, float x2, float y2, float rx1, float ry1, float rx2, float ry2) {
+ public static int intersectQuad(final float x1, final float y1, final float cx, final float cy, final float x2, final float y2, final float rx1, final float ry1, final float rx2, final float ry2) {
// LEFT/RIGHT/UP ------------------------------------------------------
if ((rx2 < x1 && rx2 < cx && rx2 < x2) ||
@@ -692,15 +693,15 @@ public class Crossing {
}
// INSIDE -------------------------------------------------------------
- QuadCurve c = new QuadCurve(x1, y1, cx, cy, x2, y2);
- float px1 = rx1 - x1;
- float py1 = ry1 - y1;
- float px2 = rx2 - x1;
- float py2 = ry2 - y1;
-
- float res1[] = new float[3];
- float res2[] = new float[3];
- int rc1 = c.solvePoint(res1, px1);
+ final QuadCurve c = new QuadCurve(x1, y1, cx, cy, x2, y2);
+ final float px1 = rx1 - x1;
+ final float py1 = ry1 - y1;
+ final float px2 = rx2 - x1;
+ final float py2 = ry2 - y1;
+
+ final float res1[] = new float[3];
+ final float res2[] = new float[3];
+ final int rc1 = c.solvePoint(res1, px1);
int rc2 = c.solvePoint(res2, px2);
// INSIDE-LEFT/RIGHT
@@ -709,9 +710,9 @@ public class Crossing {
}
// Build bound --------------------------------------------------------
- float minX = px1 - DELTA;
- float maxX = px2 + DELTA;
- float bound[] = new float[28];
+ final float minX = px1 - DELTA;
+ final float maxX = px2 + DELTA;
+ final float bound[] = new float[28];
int bc = 0;
// Add roots
bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0);
@@ -734,7 +735,7 @@ public class Crossing {
}
// End build bound ----------------------------------------------------
- int cross = crossBound(bound, bc, py1, py2);
+ final int cross = crossBound(bound, bc, py1, py2);
if (cross != UNKNOWN) {
return cross;
}
@@ -744,7 +745,7 @@ public class Crossing {
/**
* Returns how many times rectangle stripe cross cubic curve or the are intersect
*/
- public static int intersectCubic(float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, float rx1, float ry1, float rx2, float ry2) {
+ public static int intersectCubic(final float x1, final float y1, final float cx1, final float cy1, final float cx2, final float cy2, final float x2, final float y2, final float rx1, final float ry1, final float rx2, final float ry2) {
// LEFT/RIGHT/UP
if ((rx2 < x1 && rx2 < cx1 && rx2 < cx2 && rx2 < x2) ||
@@ -763,15 +764,15 @@ public class Crossing {
}
// INSIDE
- CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
- float px1 = rx1 - x1;
- float py1 = ry1 - y1;
- float px2 = rx2 - x1;
- float py2 = ry2 - y1;
-
- float res1[] = new float[3];
- float res2[] = new float[3];
- int rc1 = c.solvePoint(res1, px1);
+ final CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
+ final float px1 = rx1 - x1;
+ final float py1 = ry1 - y1;
+ final float px2 = rx2 - x1;
+ final float py2 = ry2 - y1;
+
+ final float res1[] = new float[3];
+ final float res2[] = new float[3];
+ final int rc1 = c.solvePoint(res1, px1);
int rc2 = c.solvePoint(res2, px2);
// LEFT/RIGHT
@@ -779,11 +780,11 @@ public class Crossing {
return 0;
}
- float minX = px1 - DELTA;
- float maxX = px2 + DELTA;
+ final float minX = px1 - DELTA;
+ final float maxX = px2 + DELTA;
// Build bound --------------------------------------------------------
- float bound[] = new float[40];
+ final float bound[] = new float[40];
int bc = 0;
// Add roots
bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0);
@@ -808,7 +809,7 @@ public class Crossing {
}
// End build bound ----------------------------------------------------
- int cross = crossBound(bound, bc, py1, py2);
+ final int cross = crossBound(bound, bc, py1, py2);
if (cross != UNKNOWN) {
return cross;
}
@@ -818,7 +819,7 @@ public class Crossing {
/**
* Returns how many times rectangle stripe cross path or the are intersect
*/
- public static int intersectPath(PathIterator p, float x, float y, float w, float h) {
+ public static int intersectPath(final PathIterator p, final float x, final float y, final float w, final float h) {
int cross = 0;
int count;
@@ -826,10 +827,10 @@ public class Crossing {
mx = my = cx = cy = 0.0f;
final float coords[] = new float[6];
- float rx1 = x;
- float ry1 = y;
- float rx2 = x + w;
- float ry2 = y + h;
+ final float rx1 = x;
+ final float ry1 = y;
+ final float rx2 = x + w;
+ final float ry2 = y + h;
while (!p.isDone()) {
count = 0;
@@ -880,8 +881,8 @@ public class Crossing {
/**
* Returns how many times rectangle stripe cross shape or the are intersect
*/
- public static int intersectShape(Path2D s, float x, float y, float w, float h) {
- if (!s.getBounds2D().intersects(x, y, w, h)) {
+ public static int intersectShape(final Path2D s, final float x, final float y, final float w, final float h) {
+ if (!s.getBounds2D().intersects2DRegion(x, y, w, h)) {
return 0;
}
return intersectPath(s.iterator(null), x, y, w, h);
@@ -890,14 +891,14 @@ public class Crossing {
/**
* Returns true if cross count correspond inside location for non zero path rule
*/
- public static boolean isInsideNonZero(int cross) {
+ public static boolean isInsideNonZero(final int cross) {
return cross != 0;
}
/**
* Returns true if cross count correspond inside location for even-odd path rule
*/
- public static boolean isInsideEvenOdd(int cross) {
+ public static boolean isInsideEvenOdd(final int cross) {
return (cross & 1) != 0;
}
}
diff --git a/src/jogl/classes/jogamp/graph/geom/plane/IllegalPathStateException.java b/src/jogl/classes/jogamp/graph/geom/plane/IllegalPathStateException.java
index 55211b3f9..2c18e0834 100644
--- a/src/jogl/classes/jogamp/graph/geom/plane/IllegalPathStateException.java
+++ b/src/jogl/classes/jogamp/graph/geom/plane/IllegalPathStateException.java
@@ -26,7 +26,7 @@ public class IllegalPathStateException extends RuntimeException {
public IllegalPathStateException() {
}
- public IllegalPathStateException(String s) {
+ public IllegalPathStateException(final String s) {
super(s);
}
diff --git a/src/jogl/classes/jogamp/graph/geom/plane/NoninvertibleTransformException.java b/src/jogl/classes/jogamp/graph/geom/plane/NoninvertibleTransformException.java
index 398a03fca..6e49607b7 100644
--- a/src/jogl/classes/jogamp/graph/geom/plane/NoninvertibleTransformException.java
+++ b/src/jogl/classes/jogamp/graph/geom/plane/NoninvertibleTransformException.java
@@ -23,7 +23,7 @@ public class NoninvertibleTransformException extends java.lang.Exception {
private static final long serialVersionUID = 6137225240503990466L;
- public NoninvertibleTransformException(String s) {
+ public NoninvertibleTransformException(final String s) {
super(s);
}
diff --git a/src/jogl/classes/jogamp/graph/geom/plane/Path2D.java b/src/jogl/classes/jogamp/graph/geom/plane/Path2D.java
index 8082fe4e1..191b191b5 100644
--- a/src/jogl/classes/jogamp/graph/geom/plane/Path2D.java
+++ b/src/jogl/classes/jogamp/graph/geom/plane/Path2D.java
@@ -21,11 +21,10 @@ package jogamp.graph.geom.plane;
import java.util.NoSuchElementException;
-import com.jogamp.graph.geom.AABBox;
+import com.jogamp.graph.geom.SVertex;
import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.opengl.math.geom.AABBox;
-import jogamp.graph.math.plane.Crossing;
public final class Path2D implements Cloneable {
@@ -34,12 +33,12 @@ public final class Path2D implements Cloneable {
static final String invalidWindingRuleValue = "Invalid winding rule value";
static final String iteratorOutOfBounds = "Iterator out of bounds";
-
+
/**
* The buffers size
*/
private static final int BUFFER_SIZE = 10;
-
+
/**
* The buffers capacity
*/
@@ -49,24 +48,24 @@ public final class Path2D implements Cloneable {
* The point's types buffer
*/
byte[] types;
-
+
/**
* The points buffer
*/
float[] points;
-
+
/**
* The point's type buffer size
*/
int typeSize;
-
+
/**
* The points buffer size
*/
int pointSize;
-
+
/**
- * The path rule
+ * The path rule
*/
int rule;
@@ -81,25 +80,25 @@ public final class Path2D implements Cloneable {
0}; // CLOSE
/*
- * GeneralPath path iterator
+ * GeneralPath path iterator
*/
- class Iterator implements PathIterator {
+ static class Iterator implements PathIterator {
/**
* The current cursor position in types buffer
*/
int typeIndex;
-
+
/**
* The current cursor position in points buffer
*/
int pointIndex;
-
+
/**
* The source GeneralPath object
*/
Path2D p;
-
+
/**
* The path iterator transformation
*/
@@ -109,7 +108,7 @@ public final class Path2D implements Cloneable {
* Constructs a new GeneralPath.Iterator for given general path
* @param path - the source GeneralPath object
*/
- Iterator(Path2D path) {
+ Iterator(final Path2D path) {
this(path, null);
}
@@ -118,29 +117,33 @@ public final class Path2D implements Cloneable {
* @param path - the source GeneralPath object
* @param at - the AffineTransform object to apply rectangle path
*/
- Iterator(Path2D path, AffineTransform at) {
+ Iterator(final Path2D path, final AffineTransform at) {
this.p = path;
this.t = at;
}
+ @Override
public int getWindingRule() {
return p.getWindingRule();
}
+ @Override
public boolean isDone() {
return typeIndex >= p.typeSize;
}
+ @Override
public void next() {
typeIndex++;
}
- public int currentSegment(float[] coords) {
+ @Override
+ public int currentSegment(final float[] coords) {
if (isDone()) {
throw new NoSuchElementException(iteratorOutOfBounds);
}
- int type = p.types[typeIndex];
- int count = Path2D.pointShift[type];
+ final int type = p.types[typeIndex];
+ final int count = Path2D.pointShift[type];
System.arraycopy(p.points, pointIndex, coords, 0, count);
if (t != null) {
t.transform(coords, 0, coords, 0, count / 2);
@@ -155,24 +158,24 @@ public final class Path2D implements Cloneable {
this(WIND_NON_ZERO, BUFFER_SIZE);
}
- public Path2D(int rule) {
+ public Path2D(final int rule) {
this(rule, BUFFER_SIZE);
}
- public Path2D(int rule, int initialCapacity) {
+ public Path2D(final int rule, final int initialCapacity) {
setWindingRule(rule);
types = new byte[initialCapacity];
points = new float[initialCapacity * 2];
}
- public Path2D(Path2D path) {
+ public Path2D(final Path2D path) {
this(WIND_NON_ZERO, BUFFER_SIZE);
- PathIterator p = path.iterator(null);
+ final PathIterator p = path.iterator(null);
setWindingRule(p.getWindingRule());
append(p, false);
}
- public void setWindingRule(int rule) {
+ public void setWindingRule(final int rule) {
if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) {
throw new NoSuchElementException(invalidWindingRuleValue);
}
@@ -184,26 +187,26 @@ public final class Path2D implements Cloneable {
}
/**
- * Checks points and types buffer size to add pointCount points. If necessary realloc buffers to enlarge size.
+ * Checks points and types buffer size to add pointCount points. If necessary realloc buffers to enlarge size.
* @param pointCount - the point count to be added in buffer
*/
- void checkBuf(int pointCount, boolean checkMove) {
+ void checkBuf(final int pointCount, final boolean checkMove) {
if (checkMove && typeSize == 0) {
throw new IllegalPathStateException("First segment should be SEG_MOVETO type");
}
if (typeSize == types.length) {
- byte tmp[] = new byte[typeSize + BUFFER_CAPACITY];
+ final byte tmp[] = new byte[typeSize + BUFFER_CAPACITY];
System.arraycopy(types, 0, tmp, 0, typeSize);
types = tmp;
}
if (pointSize + pointCount > points.length) {
- float tmp[] = new float[pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)];
+ final float tmp[] = new float[pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)];
System.arraycopy(points, 0, tmp, 0, pointSize);
points = tmp;
}
}
- public void moveTo(float x, float y) {
+ public void moveTo(final float x, final float y) {
if (typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_MOVETO) {
points[pointSize - 2] = x;
points[pointSize - 1] = y;
@@ -215,14 +218,14 @@ public final class Path2D implements Cloneable {
}
}
- public void lineTo(float x, float y) {
+ public void lineTo(final float x, final float y) {
checkBuf(2, true);
types[typeSize++] = PathIterator.SEG_LINETO;
points[pointSize++] = x;
points[pointSize++] = y;
}
- public void quadTo(float x1, float y1, float x2, float y2) {
+ public void quadTo(final float x1, final float y1, final float x2, final float y2) {
checkBuf(4, true);
types[typeSize++] = PathIterator.SEG_QUADTO;
points[pointSize++] = x1;
@@ -231,7 +234,7 @@ public final class Path2D implements Cloneable {
points[pointSize++] = y2;
}
- public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) {
+ public void curveTo(final float x1, final float y1, final float x2, final float y2, final float x3, final float y3) {
checkBuf(6, true);
types[typeSize++] = PathIterator.SEG_CUBICTO;
points[pointSize++] = x1;
@@ -245,28 +248,29 @@ public final class Path2D implements Cloneable {
final public int size() {
return typeSize;
}
-
+
final public boolean isClosed() {
return typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_CLOSE ;
}
-
+
public void closePath() {
if (!isClosed()) {
checkBuf(0, true);
types[typeSize++] = PathIterator.SEG_CLOSE;
}
}
-
+
+ @Override
public String toString() {
return "[size "+size()+", closed "+isClosed()+"]";
}
- public void append(Path2D path, boolean connect) {
- PathIterator p = path.iterator(null);
+ public void append(final Path2D path, final boolean connect) {
+ final PathIterator p = path.iterator(null);
append(p, connect);
}
- public void append(PathIterator path, boolean connect) {
+ public void append(final PathIterator path, boolean connect) {
while (!path.isDone()) {
final float coords[] = new float[6];
final int segmentType = path.currentSegment(coords);
@@ -296,7 +300,7 @@ public final class Path2D implements Cloneable {
closePath();
break;
default:
- throw new IllegalArgumentException("Unhandled Segment Type: "+segmentType);
+ throw new IllegalArgumentException("Unhandled Segment Type: "+segmentType);
}
path.next();
connect = false;
@@ -311,7 +315,7 @@ public final class Path2D implements Cloneable {
if (types[typeSize - 1] == PathIterator.SEG_CLOSE) {
for (int i = typeSize - 2; i > 0; i--) {
- int type = types[i];
+ final int type = types[i];
if (type == PathIterator.SEG_MOVETO) {
break;
}
@@ -326,12 +330,12 @@ public final class Path2D implements Cloneable {
pointSize = 0;
}
- public void transform(AffineTransform t) {
+ public void transform(final AffineTransform t) {
t.transform(points, 0, points, 0, pointSize / 2);
}
- public Path2D createTransformedShape(AffineTransform t) {
- Path2D p = (Path2D)clone();
+ public Path2D createTransformedShape(final AffineTransform t) {
+ final Path2D p = (Path2D)clone();
if (t != null) {
p.transform(t);
}
@@ -347,8 +351,8 @@ public final class Path2D implements Cloneable {
ry1 = ry2 = points[i--];
rx1 = rx2 = points[i--];
while (i > 0) {
- float y = points[i--];
- float x = points[i--];
+ final float y = points[i--];
+ final float x = points[i--];
if (x < rx1) {
rx1 = x;
} else
@@ -367,48 +371,48 @@ public final class Path2D implements Cloneable {
}
/**
- * Checks cross count according to path rule to define is it point inside shape or not.
+ * Checks cross count according to path rule to define is it point inside shape or not.
* @param cross - the point cross count
- * @return true if point is inside path, or false otherwise
+ * @return true if point is inside path, or false otherwise
*/
- boolean isInside(int cross) {
+ boolean isInside(final int cross) {
if (rule == WIND_NON_ZERO) {
return Crossing.isInsideNonZero(cross);
}
return Crossing.isInsideEvenOdd(cross);
}
- public boolean contains(float px, float py) {
+ public boolean contains(final float px, final float py) {
return isInside(Crossing.crossShape(this, px, py));
}
- public boolean contains(float rx, float ry, float rw, float rh) {
- int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
+ public boolean contains(final float rx, final float ry, final float rw, final float rh) {
+ final int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
return cross != Crossing.CROSSING && isInside(cross);
}
- public boolean intersects(float rx, float ry, float rw, float rh) {
- int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
+ public boolean intersects(final float rx, final float ry, final float rw, final float rh) {
+ final int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
return cross == Crossing.CROSSING || isInside(cross);
}
- public boolean contains(Vertex p) {
+ public boolean contains(final Vertex p) {
return contains(p.getX(), p.getY());
}
- public boolean contains(AABBox r) {
- return contains(r);
+ public boolean contains(final AABBox r) {
+ return contains(r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight());
}
- public boolean intersects(AABBox r) {
+ public boolean intersects(final AABBox r) {
return intersects(r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight());
}
public PathIterator iterator() {
- return new Iterator(this);
+ return new Iterator(this);
}
-
- public PathIterator iterator(AffineTransform t) {
+
+ public PathIterator iterator(final AffineTransform t) {
return new Iterator(this, t);
}
@@ -419,11 +423,11 @@ public final class Path2D implements Cloneable {
@Override
public Object clone() {
try {
- Path2D p = (Path2D) super.clone();
+ final Path2D p = (Path2D) super.clone();
p.types = types.clone();
p.points = points.clone();
return p;
- } catch (CloneNotSupportedException e) {
+ } catch (final CloneNotSupportedException e) {
throw new InternalError();
}
}
diff --git a/src/jogl/classes/jogamp/opengl/Debug.java b/src/jogl/classes/jogamp/opengl/Debug.java
index 4287c1960..5bee56d4b 100644
--- a/src/jogl/classes/jogamp/opengl/Debug.java
+++ b/src/jogl/classes/jogamp/opengl/Debug.java
@@ -1,44 +1,36 @@
-/*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
*/
package jogamp.opengl;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
import com.jogamp.common.util.PropertyAccess;
/** Helper routines for logging and debugging. */
@@ -47,40 +39,37 @@ public class Debug extends PropertyAccess {
// Some common properties
private static final boolean verbose;
private static final boolean debugAll;
-
+
static {
- PropertyAccess.addTrustedPrefix("jogl.", Debug.class);
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ PropertyAccess.addTrustedPrefix("jogl.");
+ return null;
+ } } );
+
verbose = isPropertyDefined("jogl.verbose", true);
debugAll = isPropertyDefined("jogl.debug", true);
if (verbose) {
- Package p = Package.getPackage("javax.media.opengl");
+ final Package p = Package.getPackage("javax.media.opengl");
System.err.println("JOGL specification version " + p.getSpecificationVersion());
System.err.println("JOGL implementation version " + p.getImplementationVersion());
System.err.println("JOGL implementation vendor " + p.getImplementationVendor());
}
}
- public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) {
- return PropertyAccess.isPropertyDefined(property, jnlpAlias, null);
- }
-
- public static String getProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getProperty(property, jnlpAlias, null);
- }
-
- public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getBooleanProperty(property, jnlpAlias, null);
- }
-
- public static boolean verbose() {
+ /** Ensures static init block has been issues, i.e. if calling through to {@link PropertyAccess#isPropertyDefined(String, boolean)}. */
+ public static final void initSingleton() {}
+
+ public static final boolean verbose() {
return verbose;
}
- public static boolean debugAll() {
+ public static final boolean debugAll() {
return debugAll;
}
- public static boolean debug(String subcomponent) {
+ public static final boolean debug(final String subcomponent) {
return debugAll() || isPropertyDefined("jogl.debug." + subcomponent, true);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
index f77f1135b..270a65882 100644
--- a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,19 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl;
import java.util.List;
import java.util.ArrayList;
public abstract class DesktopGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
- private static List<String> glueLibNames;
+ private static final List<String> glueLibNames;
static {
glueLibNames = new ArrayList<String>();
@@ -47,11 +47,11 @@ public abstract class DesktopGLDynamicLibraryBundleInfo extends GLDynamicLibrary
public final List<String> getGlueLibNames() {
return glueLibNames;
}
-
+
@Override
- public boolean useToolGetProcAdressFirst(String funcName) {
+ public final boolean useToolGetProcAdressFirst(final String funcName) {
return true;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java
index ff49303ca..6025b45ff 100644
--- a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java
+++ b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl;
import com.jogamp.common.os.NativeLibrary;
@@ -33,16 +33,17 @@ import java.util.*;
public class DesktopGLDynamicLookupHelper extends GLDynamicLookupHelper {
- public DesktopGLDynamicLookupHelper(DesktopGLDynamicLibraryBundleInfo info) {
+ public DesktopGLDynamicLookupHelper(final DesktopGLDynamicLibraryBundleInfo info) {
super(info);
}
- public DesktopGLDynamicLibraryBundleInfo getDesktopGLBundleInfo() { return (DesktopGLDynamicLibraryBundleInfo) getBundleInfo(); }
+ public final DesktopGLDynamicLibraryBundleInfo getDesktopGLBundleInfo() { return (DesktopGLDynamicLibraryBundleInfo) getBundleInfo(); }
- public synchronized boolean loadGLULibrary() {
+ @Override
+ public final synchronized boolean loadGLULibrary() {
/** hacky code .. where all platform GLU libs are tried ..*/
if(null==gluLib) {
- List<String> gluLibNames = new ArrayList<String>();
+ final List<String> gluLibNames = new ArrayList<String>();
gluLibNames.add("/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib"); // osx
gluLibNames.add("libGLU.so"); // unix
gluLibNames.add("GLU32"); // windows
diff --git a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
index 610f08e21..1b33e1a8b 100644
--- a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
+++ b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,20 +29,26 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package jogamp.opengl;
-import javax.media.opengl.*;
+import java.util.HashMap;
+import java.util.StringTokenizer;
-import java.util.*;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLContext;
+
+import com.jogamp.common.util.VersionNumber;
/**
* A utility object intended to be used by implementations to act as a cache
@@ -57,7 +63,7 @@ final class ExtensionAvailabilityCache {
}
/**
- * Flush the cache.
+ * Flush the cache.
*/
final void flush()
{
@@ -72,30 +78,30 @@ final class ExtensionAvailabilityCache {
/**
* Flush and rebuild the cache.
*/
- final void reset(GLContextImpl context) {
+ final void reset(final GLContextImpl context) {
flush();
initAvailableExtensions(context);
}
final boolean isInitialized() {
- return initialized && !availableExtensionCache.isEmpty() ;
+ return initialized;
}
final int getTotalExtensionCount() {
validateInitialization();
return availableExtensionCache.size();
}
-
- final boolean isExtensionAvailable(String glExtensionName) {
+
+ final boolean isExtensionAvailable(final String glExtensionName) {
validateInitialization();
- return availableExtensionCache.contains(glExtensionName);
+ return null != availableExtensionCache.get(glExtensionName);
}
final int getPlatformExtensionCount() {
validateInitialization();
return glXExtensionCount;
}
-
+
final String getPlatformExtensionsString() {
validateInitialization();
return glXExtensions;
@@ -105,7 +111,7 @@ final class ExtensionAvailabilityCache {
validateInitialization();
return glExtensionCount;
}
-
+
final String getGLExtensionsString() {
validateInitialization();
if(DEBUG) {
@@ -119,8 +125,8 @@ final class ExtensionAvailabilityCache {
throw new InternalError("ExtensionAvailabilityCache not initialized!");
}
}
- private final void initAvailableExtensions(GLContextImpl context) {
- GL gl = context.getGL();
+ private final void initAvailableExtensions(final GLContextImpl context) {
+ final GL gl = context.getGL();
// if hash is empty (meaning it was flushed), pre-cache it with the list
// of extensions that are in the GL_EXTENSIONS string
if (isInitialized()) {
@@ -149,89 +155,94 @@ final class ExtensionAvailabilityCache {
", use "+ ( useGetStringi ? "glGetStringi" : "glGetString" ) );
}
- HashSet<String> glExtensionSet = new HashSet<String>(gl.isGLES() ? 50 : 320); // far less gl extension expected on mobile
if(useGetStringi) {
- GL2GL3 gl2gl3 = gl.getGL2GL3();
+ final GL2GL3 gl2gl3 = gl.getGL2GL3();
final int count;
{
- int[] val = { 0 } ;
- gl2gl3.glGetIntegerv(GL2GL3.GL_NUM_EXTENSIONS, val, 0);
+ final int[] val = { 0 } ;
+ gl2gl3.glGetIntegerv(GL2ES3.GL_NUM_EXTENSIONS, val, 0);
count = val[0];
}
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++) {
- if(i > 0) {
- sb.append(" ");
- }
final String ext = gl2gl3.glGetStringi(GL.GL_EXTENSIONS, i);
- glExtensionSet.add(ext);
- sb.append(ext);
+ if( null == availableExtensionCache.put(ext, ext) ) {
+ // new one
+ if( 0 < i ) {
+ sb.append(" ");
+ }
+ sb.append(ext);
+ }
}
if(0==count || sb.length()==0) {
// fall back ..
useGetStringi=false;
} else {
glExtensions = sb.toString();
+ glExtensionCount = count;
}
}
if(!useGetStringi) {
glExtensions = gl.glGetString(GL.GL_EXTENSIONS);
if(null != glExtensions) {
- StringTokenizer tok = new StringTokenizer(glExtensions);
+ final StringTokenizer tok = new StringTokenizer(glExtensions);
+ int count = 0;
while (tok.hasMoreTokens()) {
- glExtensionSet.add(tok.nextToken().trim());
+ final String ext = tok.nextToken().trim();
+ if( null == availableExtensionCache.put(ext, ext) ) {
+ count++;
+ }
}
+ glExtensionCount = count;
}
}
- glExtensionCount = glExtensionSet.size();
if (DEBUG) {
System.err.println(getThreadName() + ":ExtensionAvailabilityCache: GL_EXTENSIONS: "+glExtensionCount+
", used "+ ( useGetStringi ? "glGetStringi" : "glGetString" ) );
}
// Platform Extensions
- HashSet<String> glXExtensionSet = new HashSet<String>(50);
- {
- // unify platform extension .. might have duplicates
- StringTokenizer tok = new StringTokenizer(context.getPlatformExtensionsStringImpl().toString());
- while (tok.hasMoreTokens()) {
- glXExtensionSet.add(tok.nextToken().trim());
- }
+ {
+ // unify platform extension .. might have duplicates
final StringBuilder sb = new StringBuilder();
- for(Iterator<String> iter = glXExtensionSet.iterator(); iter.hasNext(); ) {
- sb.append(iter.next());
- if(iter.hasNext()) {
- sb.append(" ");
+ final StringTokenizer tok = new StringTokenizer(context.getPlatformExtensionsStringImpl().toString());
+ int count = 0;
+ while (tok.hasMoreTokens()) {
+ final String ext = tok.nextToken().trim();
+ if( null == availableExtensionCache.put(ext, ext) ) {
+ // new one
+ if( 0 < count ) {
+ sb.append(" ");
+ }
+ sb.append(ext);
+ count++;
}
}
glXExtensions = sb.toString();
- glXExtensionCount = glXExtensionSet.size();
+ glXExtensionCount = count;
}
- availableExtensionCache.addAll(glExtensionSet);
- availableExtensionCache.addAll(glXExtensionSet);
-
if (DEBUG) {
System.err.println(getThreadName() + ":ExtensionAvailabilityCache: GLX_EXTENSIONS: "+glXExtensionCount);
System.err.println(getThreadName() + ":ExtensionAvailabilityCache: GL vendor: " + gl.glGetString(GL.GL_VENDOR));
System.err.println(getThreadName() + ":ExtensionAvailabilityCache: ALL EXTENSIONS: "+availableExtensionCache.size());
}
- if(!context.isGLES()) {
- int major[] = new int[] { context.getGLVersionMajor() };
- int minor[] = new int[] { context.getGLVersionMinor() };
- while (GLContext.isValidGLVersion(major[0], minor[0])) {
- availableExtensionCache.add("GL_VERSION_" + major[0] + "_" + minor[0]);
- if (DEBUG) {
- System.err.println(getThreadName() + ":ExtensionAvailabilityCache: Added GL_VERSION_" + major[0] + "_" + minor[0] + " to known extensions");
- }
- if(!GLContext.decrementGLVersion(major, minor)) break;
+ final int ctxOptions = context.getCtxOptions();
+ final VersionNumber version = context.getGLVersionNumber();
+ final int major[] = new int[] { version.getMajor() };
+ final int minor[] = new int[] { version.getMinor() };
+ do{
+ final String GL_XX_VERSION = ( context.isGLES() ? "GL_ES_VERSION_" : "GL_VERSION_" ) + major[0] + "_" + minor[0];
+ availableExtensionCache.put(GL_XX_VERSION, GL_XX_VERSION);
+ if (DEBUG) {
+ System.err.println(getThreadName() + ":ExtensionAvailabilityCache: Added "+GL_XX_VERSION+" to known extensions");
}
- }
+ } while( GLContext.decrementGLVersion(ctxOptions, major, minor) );
// put a dummy var in here so that the cache is no longer empty even if
// no extensions are in the GL_EXTENSIONS string
- availableExtensionCache.add("<INTERNAL_DUMMY_PLACEHOLDER>");
+ availableExtensionCache.put("<INTERNAL_DUMMY_PLACEHOLDER>", "<INTERNAL_DUMMY_PLACEHOLDER>");
initialized = true;
}
@@ -245,10 +256,8 @@ final class ExtensionAvailabilityCache {
private int glExtensionCount = 0;
private String glXExtensions = null;
private int glXExtensionCount = 0;
- private HashSet<String> availableExtensionCache = new HashSet<String>(50);
+ private final HashMap<String, String> availableExtensionCache = new HashMap<String, String>(100);
- static String getThreadName() {
- return Thread.currentThread().getName();
- }
+ static String getThreadName() { return Thread.currentThread().getName(); }
}
diff --git a/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java b/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java
index 27569d210..d7ac6eb1e 100644
--- a/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java
+++ b/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java
@@ -41,39 +41,39 @@ public class FPSCounterImpl implements FPSCounter {
private long fpsStartTime, fpsLastUpdateTime, fpsLastPeriod, fpsTotalDuration;
private int fpsTotalFrames;
private float fpsLast, fpsTotal;
-
+
/** Creates a disabled instance */
public FPSCounterImpl() {
setUpdateFPSFrames(0, null);
}
-
+
/**
* Increases total frame count and updates values if feature is enabled and
* update interval is reached.<br>
- *
+ *
* Shall be called by actual FPSCounter implementing renderer, after display a new frame.
- *
+ *
*/
public final synchronized void tickFPS() {
fpsTotalFrames++;
if(fpsUpdateFramesInterval>0 && fpsTotalFrames%fpsUpdateFramesInterval == 0) {
final long now = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
fpsLastPeriod = now - fpsLastUpdateTime;
- fpsLastPeriod = Math.max(fpsLastPeriod, 1); // div 0
- fpsLast = ( (float)fpsUpdateFramesInterval * 1000f ) / ( (float) fpsLastPeriod ) ;
-
+ fpsLastPeriod = Math.max(fpsLastPeriod, 1); // div 0
+ fpsLast = ( fpsUpdateFramesInterval * 1000f ) / ( fpsLastPeriod ) ;
+
fpsTotalDuration = now - fpsStartTime;
fpsTotalDuration = Math.max(fpsTotalDuration, 1); // div 0
- fpsTotal= ( (float)fpsTotalFrames * 1000f ) / ( (float) fpsTotalDuration ) ;
-
+ fpsTotal= ( fpsTotalFrames * 1000f ) / ( fpsTotalDuration ) ;
+
if(null != fpsOutputStream) {
fpsOutputStream.println(toString());
}
-
+
fpsLastUpdateTime = now;
}
}
-
+
public StringBuilder toString(StringBuilder sb) {
if(null==sb) {
sb = new StringBuilder();
@@ -81,59 +81,71 @@ public class FPSCounterImpl implements FPSCounter {
String fpsLastS = String.valueOf(fpsLast);
fpsLastS = fpsLastS.substring(0, fpsLastS.indexOf('.') + 2);
String fpsTotalS = String.valueOf(fpsTotal);
- fpsTotalS = fpsTotalS.substring(0, fpsTotalS.indexOf('.') + 2);
+ fpsTotalS = fpsTotalS.substring(0, fpsTotalS.indexOf('.') + 2);
sb.append(fpsTotalDuration/1000 +" s: "+ fpsUpdateFramesInterval+" f / "+ fpsLastPeriod+" ms, " + fpsLastS+" fps, "+ fpsLastPeriod/fpsUpdateFramesInterval+" ms/f; "+
"total: "+ fpsTotalFrames+" f, "+ fpsTotalS+ " fps, "+ fpsTotalDuration/fpsTotalFrames+" ms/f");
return sb;
}
-
+
+ @Override
public String toString() {
return toString(null).toString();
}
-
- public final synchronized void setUpdateFPSFrames(int frames, PrintStream out) {
+
+ @Override
+ public final synchronized void setUpdateFPSFrames(final int frames, final PrintStream out) {
fpsUpdateFramesInterval = frames;
fpsOutputStream = out;
resetFPSCounter();
}
-
+
+ @Override
public final synchronized void resetFPSCounter() {
fpsStartTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); // overwrite startTime to real init one
fpsLastUpdateTime = fpsStartTime;
fpsLastPeriod = 0;
fpsTotalFrames = 0;
fpsLast = 0f; fpsTotal = 0f;
+ fpsLastPeriod = 0; fpsTotalDuration=0;
}
+ @Override
public final synchronized int getUpdateFPSFrames() {
return fpsUpdateFramesInterval;
}
-
- public final synchronized long getFPSStartTime() {
- return fpsStartTime;
+
+ @Override
+ public final synchronized long getFPSStartTime() {
+ return fpsStartTime;
}
+ @Override
public final synchronized long getLastFPSUpdateTime() {
return fpsLastUpdateTime;
}
+ @Override
public final synchronized long getLastFPSPeriod() {
return fpsLastPeriod;
}
-
+
+ @Override
public final synchronized float getLastFPS() {
return fpsLast;
}
-
- public final synchronized int getTotalFPSFrames() {
- return fpsTotalFrames;
+
+ @Override
+ public final synchronized int getTotalFPSFrames() {
+ return fpsTotalFrames;
}
- public final synchronized long getTotalFPSDuration() {
- return fpsTotalDuration;
+ @Override
+ public final synchronized long getTotalFPSDuration() {
+ return fpsTotalDuration;
}
-
+
+ @Override
public final synchronized float getTotalFPS() {
return fpsTotal;
- }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index 07029f143..8fa4c581a 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,15 +20,16 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl;
import java.io.PrintStream;
+import java.util.List;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
@@ -44,77 +45,207 @@ import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
+import javax.media.opengl.GLSharedContextSetter;
+import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.opengl.GLAutoDrawableDelegate;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.GLStateKeeper;
/**
- * Abstract common code for GLAutoDrawable implementations.
- *
+ * Abstract common code for GLAutoDrawable implementations
+ * utilizing multithreading, i.e. {@link #isThreadGLCapable()} always returns <code>true</code>.
+ *
* @see GLAutoDrawable
+ * @see GLAutoDrawable#getThreadingMode()
* @see GLAutoDrawableDelegate
+ * @see GLOffscreenAutoDrawable
+ * @see GLOffscreenAutoDrawableImpl
* @see GLPBufferImpl
- * @see GLWindow
+ * @see com.jogamp.newt.opengl.GLWindow
*/
-public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
+public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeeper, FPSCounter, GLSharedContextSetter {
public static final boolean DEBUG = GLDrawableImpl.DEBUG;
-
protected final GLDrawableHelper helper = new GLDrawableHelper();
protected final FPSCounterImpl fpsCounter = new FPSCounterImpl();
-
+
protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
- protected GLContextImpl context;
+ protected volatile GLContextImpl context;
+ protected boolean preserveGLELSAtDestroy;
+ protected GLEventListenerState glels;
+ protected GLStateKeeper.Listener glStateKeeperListener;
protected final boolean ownsDevice;
protected int additionalCtxCreationFlags = 0;
protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking
protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking
/**
- * @param drawable upstream {@link GLDrawableImpl} instance, may be null for lazy initialization
- * @param context upstream {@link GLContextImpl} instance, may be null for lazy initialization
+ * <p>
+ * The {@link GLContext} can be assigned later manually via {@link GLAutoDrawable#setContext(GLContext, boolean) setContext(ctx)}
+ * <i>or</i> it will be created <i>lazily</i> at the 1st {@link GLAutoDrawable#display() display()} method call.<br>
+ * <i>Lazy</i> {@link GLContext} creation will take a shared {@link GLContext} into account
+ * which has been set {@link #setSharedContext(GLContext) directly}
+ * or {@link #setSharedAutoDrawable(GLAutoDrawable) via another GLAutoDrawable}.
+ * </p>
+ * @param drawable upstream {@link GLDrawableImpl} instance,
+ * may be <code>null</code> for lazy initialization
+ * @param context upstream {@link GLContextImpl} instance,
+ * may not have been made current (created) yet,
+ * may not be associated w/ <code>drawable<code> yet,
+ * may be <code>null</code> for lazy initialization at 1st {@link #display()}.
* @param ownsDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
* otherwise pass <code>false</code>. Closing the device is required in case
* the drawable is created w/ it's own new instance, e.g. offscreen drawables,
* and no further lifecycle handling is applied.
*/
- public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownsDevice) {
+ public GLAutoDrawableBase(final GLDrawableImpl drawable, final GLContextImpl context, final boolean ownsDevice) {
this.drawable = drawable;
this.context = context;
+ this.preserveGLELSAtDestroy = false;
+ this.glels = null;
+ this.glStateKeeperListener = null;
this.ownsDevice = ownsDevice;
- resetFPSCounter();
+ if(null != context && null != drawable) {
+ context.setGLDrawable(drawable, false);
+ }
+ resetFPSCounter();
+ }
+
+ @Override
+ public final void setSharedContext(final GLContext sharedContext) throws IllegalStateException {
+ helper.setSharedContext(this.context, sharedContext);
+ }
+
+ @Override
+ public final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
+ helper.setSharedAutoDrawable(this, sharedAutoDrawable);
+ }
+
+ @Override
+ public final GLStateKeeper.Listener setGLStateKeeperListener(final Listener l) {
+ final GLStateKeeper.Listener pre = glStateKeeperListener;
+ glStateKeeperListener = l;
+ return pre;
+ }
+
+ @Override
+ public final boolean preserveGLStateAtDestroy(final boolean value) {
+ final boolean res = isGLStatePreservationSupported() ? true : false;
+ if( res ) {
+ if( DEBUG ) {
+ final long surfaceHandle = null != getNativeSurface() ? getNativeSurface().getSurfaceHandle() : 0;
+ System.err.println("GLAutoDrawableBase.setPreserveGLStateAtDestroy: ("+getThreadName()+"): "+preserveGLELSAtDestroy+" -> "+value+" - surfaceHandle 0x"+Long.toHexString(surfaceHandle));
+ }
+ preserveGLELSAtDestroy = value;
+ }
+ return res;
+ }
+
+ @Override
+ public boolean isGLStatePreservationSupported() { return false; }
+
+ @Override
+ public final GLEventListenerState getPreservedGLState() {
+ return glels;
+ }
+
+ @Override
+ public final GLEventListenerState clearPreservedGLState() {
+ final GLEventListenerState r = glels;
+ glels = null;
+ return r;
+ }
+
+ /**
+ * Preserves the {@link GLEventListenerState} from this {@link GLAutoDrawable}.
+ *
+ * @return <code>true</code> if the {@link GLEventListenerState} is preserved successfully from this {@link GLAutoDrawable},
+ * otherwise <code>false</code>.
+ *
+ * @throws IllegalStateException if the {@link GLEventListenerState} is already preserved
+ *
+ * @see #restoreGLEventListenerState()
+ */
+ protected final boolean preserveGLEventListenerState() throws IllegalStateException {
+ if( null != glels ) {
+ throw new IllegalStateException("GLEventListenerState already pulled");
+ }
+ if( null != context && context.isCreated() ) {
+ if( null!= glStateKeeperListener) {
+ glStateKeeperListener.glStatePreserveNotify(this);
+ }
+ glels = GLEventListenerState.moveFrom(this);
+ return null != glels;
+ }
+ return false;
+ }
+
+ /**
+ * Restores a previously {@link #preserveGLEventListenerState() preserved} {@link GLEventListenerState} to this {@link GLAutoDrawable}.
+ *
+ * @return <code>true</code> if the {@link GLEventListenerState} was previously {@link #preserveGLEventListenerState() preserved}
+ * and is moved successfully to this {@link GLAutoDrawable},
+ * otherwise <code>false</code>.
+ *
+ * @see #preserveGLEventListenerState()
+ */
+ protected final boolean restoreGLEventListenerState() {
+ if( null != glels ) {
+ glels.moveTo(this);
+ glels = null;
+ if( null!= glStateKeeperListener) {
+ glStateKeeperListener.glStateRestored(this);
+ }
+ return true;
+ }
+ return false;
}
-
- /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access. */
- protected abstract RecursiveLock getLock();
-
+
/** Default implementation to handle repaint events from the windowing system */
protected final void defaultWindowRepaintOp() {
final GLDrawable _drawable = drawable;
if( null != _drawable && _drawable.isRealized() ) {
- if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) {
+ if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimatingOnOtherThread() ) {
display();
}
}
}
-
- /** Default implementation to handle resize events from the windowing system. All required locks are being claimed. */
- protected final void defaultWindowResizedOp(int newWidth, int newHeight) throws NativeWindowException, GLException {
+
+ /**
+ * Handling resize events from the windowing system.
+ * <p>
+ * Implementation:
+ * <ul>
+ * <li>resizes {@link #getDelegatedDrawable() the GLDrawable}, if offscreen,</li>
+ * <li>triggers a pending {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape events}, and</li>
+ * <li>issues a {@link #display()} call, if no animator is present.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * All required locks are being claimed.
+ * </p>
+ * @param newWidth new width in pixel units
+ * @param newWidth new height in pixel units
+ */
+ protected final void defaultWindowResizedOp(final int newWidth, final int newHeight) throws NativeWindowException, GLException {
GLDrawableImpl _drawable = drawable;
if( null!=_drawable ) {
if(DEBUG) {
- System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+ final long surfaceHandle = null != getNativeSurface() ? getNativeSurface().getSurfaceHandle() : 0;
+ System.err.println("GLAutoDrawableBase.sizeChanged: ("+getThreadName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(surfaceHandle));
}
if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
- final RecursiveLock _lock = getLock();
+ final RecursiveLock _lock = getUpstreamLock();
_lock.lock();
try {
final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, newWidth, newHeight);
if(_drawable != _drawableNew) {
- // write back
+ // write back
_drawable = _drawableNew;
drawable = _drawableNew;
}
@@ -124,21 +255,21 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
if( _drawable.isRealized() ) {
- if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) {
+ if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimatingOnOtherThread() ) {
display();
}
}
}
}
-
- /**
+
+ /**
* Default implementation to handle destroy notifications from the windowing system.
- *
+ *
* <p>
- * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol}
+ * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol}
* or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default),
* a thread safe destruction is being induced.
- * </p>
+ * </p>
*/
protected final void defaultWindowDestroyNotifyOp() {
final NativeSurface ns = getNativeSurface();
@@ -147,22 +278,28 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
shallClose = WindowClosingMode.DISPOSE_ON_CLOSE == ((WindowClosingProtocol)ns).getDefaultCloseOperation();
} else {
shallClose = true;
- }
+ }
if( shallClose ) {
- destroyAvoidAwareOfLocking();
- }
+ try {
+ destroyAvoidAwareOfLocking();
+ } catch( final Throwable t ) {
+ // Intentionally catch and ignore exception,
+ // so the destroy mechanism of the native windowing system is not corrupted!
+ ExceptionUtils.dumpThrowable("ignored", t);
+ }
+ }
}
/**
- * Calls {@link #destroy()}
+ * Calls {@link #destroy()}
* directly if the following requirements are met:
* <ul>
- * <li>An {@link GLAnimatorControl} is bound (see {@link #getAnimator()}) and running on another thread.
+ * <li>An {@link GLAnimatorControl} is bound (see {@link #getAnimator()}) and running on another thread.
* Here we pause the animation while issuing the destruction.</li>
* <li>Surface is not locked by another thread (considered anonymous).</li>
* </ul>
* <p>
- * Otherwise destroy is being flagged to be called within the next
+ * Otherwise destroy is being flagged to be called within the next
* call of display().
* </p>
* <p>
@@ -174,11 +311,11 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
*/
protected final void destroyAvoidAwareOfLocking() {
final NativeSurface ns = getNativeSurface();
-
+
final GLAnimatorControl ctrl = helper.getAnimator();
-
+
// Is an animator thread perform rendering?
- if ( helper.isAnimatorRunningOnOtherThread() ) {
+ if ( helper.isAnimatorStartedOnOtherThread() ) {
// Pause animations before initiating safe destroy.
final boolean isPaused = ctrl.pause();
destroy();
@@ -196,12 +333,12 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
destroy();
}
}
-
+
/**
* Calls {@link #destroyImplInLock()} while claiming the lock.
*/
protected final void defaultDestroy() {
- final RecursiveLock lock = getLock();
+ final RecursiveLock lock = getUpstreamLock();
lock.lock();
try {
destroyImplInLock();
@@ -209,7 +346,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
lock.unlock();
}
}
-
+
/**
* Default implementation to destroys the drawable and context of this GLAutoDrawable:
* <ul>
@@ -222,35 +359,60 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
* In such case call <code>super.destroyImplInLock</code> first.</p>
*/
protected void destroyImplInLock() {
- final GLContext _context = context;
- final GLDrawable _drawable = drawable;
- if( null != _drawable ) {
- if( _drawable.isRealized() ) {
- if( null != _context && _context.isCreated() ) {
- // Catch dispose GLExceptions by GLEventListener, just 'print' them
- // so we can continue with the destruction.
- try {
- helper.disposeGL(this, _drawable, _context, null);
- } catch (GLException gle) {
- gle.printStackTrace();
- }
+ if( preserveGLELSAtDestroy ) {
+ preserveGLStateAtDestroy(false);
+ preserveGLEventListenerState();
+ }
+
+ GLException exceptionOnDisposeGL = null;
+ if( null != context ) {
+ if( context.isCreated() ) {
+ try {
+ helper.disposeGL(this, context, true);
+ } catch (final GLException gle) {
+ exceptionOnDisposeGL = gle;
}
- _drawable.setRealized(false);
}
- if( ownsDevice ) {
- _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close();
+ context = null;
+ }
+
+ Throwable exceptionOnUnrealize = null;
+ Throwable exceptionOnDeviceClose = null;
+ if( null != drawable ) {
+ final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+ try {
+ drawable.setRealized(false);
+ } catch( final Throwable re ) {
+ exceptionOnUnrealize = re;
+ }
+ drawable = null;
+ try {
+ if( ownsDevice ) {
+ device.close();
+ }
+ } catch (final Throwable re) {
+ exceptionOnDeviceClose = re;
}
}
- context = null;
- drawable = null;
+
+ // throw exception in order of occurrence ..
+ if( null != exceptionOnDisposeGL ) {
+ throw exceptionOnDisposeGL;
+ }
+ if( null != exceptionOnUnrealize ) {
+ throw GLException.newGLException(exceptionOnUnrealize);
+ }
+ if( null != exceptionOnDeviceClose ) {
+ throw GLException.newGLException(exceptionOnDeviceClose);
+ }
}
-
+
public final void defaultSwapBuffers() throws GLException {
- final RecursiveLock _lock = getLock();
+ final RecursiveLock _lock = getUpstreamLock();
_lock.lock();
- try {
- if(drawable!=null && context != null) {
- helper.invokeGL(drawable, context, defaultSwapAction, defaultInitAction);
+ try {
+ if(null != drawable) {
+ drawable.swapBuffers();
}
} finally {
_lock.unlock();
@@ -260,12 +422,12 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
//
// GLAutoDrawable
//
-
+
protected final Runnable defaultInitAction = new Runnable() {
@Override
public final void run() {
// Lock: Locked Surface/Window by MakeCurrent/Release
- helper.init(GLAutoDrawableBase.this);
+ helper.init(GLAutoDrawableBase.this, !sendReshape);
resetFPSCounter();
} };
@@ -274,7 +436,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
public final void run() {
// Lock: Locked Surface/Window by display _and_ MakeCurrent/Release
if (sendReshape) {
- helper.reshape(GLAutoDrawableBase.this, 0, 0, getWidth(), getHeight());
+ helper.reshape(GLAutoDrawableBase.this, 0, 0, getSurfaceWidth(), getSurfaceHeight());
sendReshape = false;
}
helper.display(GLAutoDrawableBase.this);
@@ -287,10 +449,28 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
destroy();
return;
}
- final RecursiveLock _lock = getLock();
+ final RecursiveLock _lock = getUpstreamLock();
_lock.lock();
try {
- if( null != context ) {
+ if( null == context ) {
+ boolean contextCreated = false;
+ final GLDrawableImpl _drawable = drawable;
+ if ( null != _drawable && _drawable.isRealized() && 0<_drawable.getSurfaceWidth()*_drawable.getSurfaceHeight() ) {
+ final GLContext[] shareWith = { null };
+ if( !helper.isSharedGLContextPending(shareWith) ) {
+ if( !restoreGLEventListenerState() ) {
+ context = (GLContextImpl) _drawable.createContext(shareWith[0]);
+ context.setContextCreationFlags(additionalCtxCreationFlags);
+ contextCreated = true;
+ // surface is locked/unlocked implicit by context's makeCurrent/release
+ helper.invokeGL(_drawable, context, defaultDisplayAction, defaultInitAction);
+ }
+ }
+ }
+ if(DEBUG) {
+ System.err.println("GLAutoDrawableBase.defaultDisplay: contextCreated "+contextCreated);
+ }
+ } else {
// surface is locked/unlocked implicit by context's makeCurrent/release
helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction);
}
@@ -298,34 +478,35 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
_lock.unlock();
}
}
-
- protected final Runnable defaultSwapAction = new Runnable() {
- @Override
- public final void run() {
- drawable.swapBuffers();
- } } ;
-
+
+ protected final GLEventListener defaultDisposeGLEventListener(final GLEventListener listener, final boolean remove) {
+ final RecursiveLock _lock = getUpstreamLock();
+ _lock.lock();
+ try {
+ return helper.disposeGLEventListener(GLAutoDrawableBase.this, drawable, context, listener, remove);
+ } finally {
+ _lock.unlock();
+ }
+ }
+
@Override
public final GLDrawable getDelegatedDrawable() {
return drawable;
}
-
+
@Override
public final GLContext getContext() {
return context;
}
@Override
- public final GLContext setContext(GLContext newCtx) {
- final RecursiveLock lock = getLock();
+ public final GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx) {
+ final RecursiveLock lock = getUpstreamLock();
lock.lock();
try {
final GLContext oldCtx = context;
- final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
- }
return oldCtx;
} finally {
lock.unlock();
@@ -342,7 +523,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
@Override
- public final GL setGL(GL gl) {
+ public final GL setGL(final GL gl) {
final GLContext _context = context;
if (_context != null) {
_context.setGL(gl);
@@ -352,29 +533,54 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
@Override
- public final void addGLEventListener(GLEventListener listener) {
+ public final void addGLEventListener(final GLEventListener listener) {
helper.addGLEventListener(listener);
}
@Override
- public final void addGLEventListener(int index, GLEventListener listener) throws IndexOutOfBoundsException {
- helper.addGLEventListener(index, listener);
+ public final void addGLEventListener(final int index, final GLEventListener listener) throws IndexOutOfBoundsException {
+ helper.addGLEventListener(index, listener);
+ }
+
+ @Override
+ public int getGLEventListenerCount() {
+ return helper.getGLEventListenerCount();
+ }
+
+ @Override
+ public GLEventListener getGLEventListener(final int index) throws IndexOutOfBoundsException {
+ return helper.getGLEventListener(index);
+ }
+
+ @Override
+ public boolean areAllGLEventListenerInitialized() {
+ return helper.areAllGLEventListenerInitialized();
+ }
+
+ @Override
+ public boolean getGLEventListenerInitState(final GLEventListener listener) {
+ return helper.getGLEventListenerInitState(listener);
}
@Override
- public final void removeGLEventListener(GLEventListener listener) {
- helper.removeGLEventListener(listener);
+ public void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized) {
+ helper.setGLEventListenerInitState(listener, initialized);
}
-
+
@Override
- public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
- return helper.removeGLEventListener(index);
+ public GLEventListener disposeGLEventListener(final GLEventListener listener, final boolean remove) {
+ return defaultDisposeGLEventListener(listener, remove);
}
-
+
+ @Override
+ public final GLEventListener removeGLEventListener(final GLEventListener listener) {
+ return helper.removeGLEventListener(listener);
+ }
+
@Override
- public final void setAnimator(GLAnimatorControl animatorControl)
+ public final void setAnimator(final GLAnimatorControl animatorControl)
throws GLException {
- helper.setAnimator(animatorControl);
+ helper.setAnimator(animatorControl);
}
@Override
@@ -383,13 +589,33 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
@Override
- public final boolean invoke(boolean wait, GLRunnable glRunnable) {
- return helper.invoke(this, wait, glRunnable);
+ public final Thread setExclusiveContextThread(final Thread t) throws GLException {
+ return helper.setExclusiveContextThread(t, context);
+ }
+
+ @Override
+ public final Thread getExclusiveContextThread() {
+ return helper.getExclusiveContextThread();
+ }
+
+ @Override
+ public final boolean invoke(final boolean wait, final GLRunnable glRunnable) throws IllegalStateException {
+ return helper.invoke(this, wait, glRunnable);
+ }
+
+ @Override
+ public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) throws IllegalStateException {
+ return helper.invoke(this, wait, glRunnables);
+ }
+
+ @Override
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
}
@Override
- public final void setAutoSwapBufferMode(boolean enable) {
- helper.setAutoSwapBufferMode(enable);
+ public final void setAutoSwapBufferMode(final boolean enable) {
+ helper.setAutoSwapBufferMode(enable);
}
@Override
@@ -398,8 +624,8 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
@Override
- public final void setContextCreationFlags(int flags) {
- additionalCtxCreationFlags = flags;
+ public final void setContextCreationFlags(final int flags) {
+ additionalCtxCreationFlags = flags;
final GLContext _context = context;
if(null != _context) {
_context.setContextCreationFlags(additionalCtxCreationFlags);
@@ -411,12 +637,21 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
return additionalCtxCreationFlags;
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Implementation always supports multithreading, hence method always returns <code>true</code>.
+ * </p>
+ */
+ @Override
+ public final boolean isThreadGLCapable() { return true; }
+
//
// FPSCounter
//
-
+
@Override
- public final void setUpdateFPSFrames(int frames, PrintStream out) {
+ public final void setUpdateFPSFrames(final int frames, final PrintStream out) {
fpsCounter.setUpdateFPSFrames(frames, out);
}
@@ -464,14 +699,14 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
public final float getTotalFPS() {
return fpsCounter.getTotalFPS();
}
-
+
//
// GLDrawable delegation
//
-
+
@Override
public final GLContext createContext(final GLContext shareWith) {
- final RecursiveLock lock = getLock();
+ final RecursiveLock lock = getUpstreamLock();
lock.lock();
try {
if(drawable != null) {
@@ -486,40 +721,45 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
@Override
+ public final void setRealized(final boolean realized) {
+ final RecursiveLock _lock = getUpstreamLock();
+ _lock.lock();
+ try {
+ final GLDrawable _drawable = drawable;
+ if( null == _drawable || realized && ( 0 >= _drawable.getSurfaceWidth() || 0 >= _drawable.getSurfaceHeight() ) ) {
+ return;
+ }
+ _drawable.setRealized(realized);
+ if( realized && _drawable.isRealized() ) {
+ sendReshape=true; // ensure a reshape is being send ..
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+ @Override
public final boolean isRealized() {
final GLDrawable _drawable = drawable;
return null != _drawable ? _drawable.isRealized() : false;
}
@Override
- public int getWidth() {
+ public int getSurfaceWidth() {
final GLDrawable _drawable = drawable;
- return null != _drawable ? _drawable.getWidth() : 0;
+ return null != _drawable ? _drawable.getSurfaceWidth() : 0;
}
@Override
- public int getHeight() {
+ public int getSurfaceHeight() {
final GLDrawable _drawable = drawable;
- return null != _drawable ? _drawable.getHeight() : 0;
- }
-
- /**
- * @param t the thread for which context release shall be skipped, usually the animation thread,
- * ie. {@link Animator#getThread()}.
- * @deprecated this is an experimental feature,
- * intended for measuring performance in regards to GL context switch
- */
- @Deprecated
- public void setSkipContextReleaseThread(Thread t) {
- helper.setSkipContextReleaseThread(t);
+ return null != _drawable ? _drawable.getSurfaceHeight() : 0;
}
- /**
- * @deprecated see {@link #setSkipContextReleaseThread(Thread)}
- */
- @Deprecated
- public Thread getSkipContextReleaseThread() {
- return helper.getSkipContextReleaseThread();
+ @Override
+ public boolean isGLOriented() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.isGLOriented() : true;
}
@Override
@@ -529,6 +769,12 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
@Override
+ public final GLCapabilitiesImmutable getRequestedGLCapabilities() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getRequestedGLCapabilities() : null;
+ }
+
+ @Override
public final GLProfile getGLProfile() {
final GLDrawable _drawable = drawable;
return null != _drawable ? _drawable.getGLProfile() : null;
@@ -545,7 +791,9 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
final GLDrawable _drawable = drawable;
return null != _drawable ? _drawable.getHandle() : 0;
}
-
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
+
@Override
public String toString() {
return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable +
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java
new file mode 100644
index 000000000..7e49b3464
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java
@@ -0,0 +1,519 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.opengl;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+import javax.media.opengl.*;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IntObjectHashMap;
+import com.jogamp.common.util.PropertyAccess;
+
+/**
+ * Tracking of {@link GLBufferStorage} instances via GL API callbacks.
+ * <p>
+ * See {@link GLBufferStorage} for generic details.
+ * </p>
+ * <p>
+ * Buffer storage is created via
+ * <ul>
+ * <li><code>glBufferStorage</code> - storage creation with target via {@link #createBufferStorage(GLBufferStateTracker, GL, int, long, Buffer, int, int, CreateStorageDispatch, long)}</li>
+ * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation with target via {@link #createBufferStorage(GLBufferStateTracker, GL, int, long, Buffer, int, int, CreateStorageDispatch, long)}</li>
+ * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct, via {@link #createBufferStorage(GL, int, long, Buffer, int, CreateStorageDispatch, long)}</li>
+ * </ul>
+ * Note that storage <i>recreation</i> as mentioned above also invalidate a previous storage instance,
+ * i.e. disposed the buffer's current storage if exist and attaches a new storage instance.
+ * </p>
+ * <p>
+ * Buffers storage is disposed via
+ * <ul>
+ * <li>{@link GL#glDeleteBuffers(int, IntBuffer)} - explicit, direct, via {@link #notifyBuffersDeleted(int, IntBuffer)} or {@link #notifyBuffersDeleted(int, int[], int)}</li>
+ * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation via target</li>
+ * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * Implementation throws a {@link GLException} in all <i>construction</i> methods as listed below,
+ * if GL-function constraints are not met. <code>createBufferStorage</code> also throws an exception
+ * if the native GL-function fails.
+ * <ul>
+ * <li>{@link #createBufferStorage(GLBufferStateTracker, GL, int, long, Buffer, int, int, CreateStorageDispatch, long)}, etc ..</li>
+ * <li>{@link #mapBuffer(GLBufferStateTracker, GL, int, int, MapBufferAllDispatch, long)}, etc ..</li>
+ * </ul>
+ * In <i>destruction</i> and informal methods, i.e. all others, implementation only issues a WARNING debug message, if enabled.
+ * </p>
+ *
+ * <p>
+ * Buffer mapping methods like {@link GL#mapBuffer(int, int)} ...,
+ * require knowledge of the buffer's storage size as determined via it's creation with
+ * {@link GL#glBufferData(int, long, java.nio.Buffer, int)} ....
+ * </p>
+ * <p>
+ * Hence we track the OpenGL buffer's {@link GLBufferStorage} to be able to
+ * access the buffer's storage size. The tracked {@link GLBufferStorage} instances
+ * also allow users to conveniently access details of their created and maybe mapped buffer storage.
+ * </p>
+ * <p>
+ * The {@link GLBufferObjectTracker} and it's tracked {@link GLBufferStorage} instances
+ * maybe shared across multiple OpenGL context, hence this class is thread safe and employs synchronization.
+ * </p>
+ * <p>
+ * Implementation requires and utilizes a local {@link GLBufferStateTracker}
+ * to resolve the actual buffer-name bound to the given target.
+ * </p>
+ * <p>
+ * Note: This tracker requires to be notified about all OpenGL buffer storage operations,
+ * as well as the local {@link GLBufferStateTracker} to be notified about all
+ * OpenGL buffer binding operations.
+ * Hence buffer storage cannot be accessed properly if managed via native code.
+ * </p>
+ */
+public class GLBufferObjectTracker {
+ protected static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = PropertyAccess.isPropertyDefined("jogl.debug.GLBufferObjectTracker", true);
+ }
+
+ static final class GLBufferStorageImpl extends GLBufferStorage {
+ GLBufferStorageImpl(final int name, final long size, final int mutableUsage, final int immutableFlags) {
+ super(name, size, mutableUsage, immutableFlags);
+ }
+ protected final void reset(final long size, final int mutableUsage, final int immutableFlags) {
+ super.reset(size, mutableUsage, immutableFlags);
+ }
+ protected final void setMappedBuffer(final ByteBuffer buffer) {
+ super.setMappedBuffer(buffer);
+ }
+ }
+
+ /**
+ * Map from buffer names to GLBufferObject.
+ */
+ private final IntObjectHashMap bufferName2StorageMap;
+
+ public GLBufferObjectTracker() {
+ bufferName2StorageMap = new IntObjectHashMap();
+ bufferName2StorageMap.setKeyNotFoundValue(null);
+ }
+
+ public static interface CreateStorageDispatch {
+ void create(final int targetOrBufferName, final long size, final Buffer data, final int mutableUsageOrImmutableFlags, final long glProcAddress);
+ }
+
+ /**
+ * Must be called when [re]creating the GL buffer object via <code>glBufferStorage</code> and {@link GL#glBufferData(int, long, java.nio.Buffer, int)},
+ * i.e. implies destruction of the buffer.
+ *
+ * @param bufferStateTracker
+ * @param caller
+ * @param target
+ * @param size
+ * @param mutableUsage <code>glBufferData</code>, <code>glNamedBufferDataEXT</code> usage
+ * @param immutableFlags <code>glBufferStorage</code> flags
+ * @throws GLException if buffer is not bound to target
+ * @throws GLException if size is less-or-eqaul zero for <code>glBufferStorage</code>, or size is less-than zero otherwise
+ * @throws GLException if a native GL-Error occurs
+ */
+ public synchronized final void createBufferStorage(final GLBufferStateTracker bufferStateTracker, final GL caller,
+ final int target, final long size, final Buffer data, final int mutableUsage, final int immutableFlags,
+ final CreateStorageDispatch dispatch, final long glProcAddress) throws GLException {
+ final int glerrPre = caller.glGetError(); // clear
+ if (DEBUG && GL.GL_NO_ERROR != glerrPre) {
+ System.err.printf("%s.%s glerr-pre 0x%X%n", msgClazzName, msgCreateBound, glerrPre);
+ }
+ final int bufferName = bufferStateTracker.getBoundBufferObject(target, caller);
+ if ( 0 == bufferName ) {
+ throw new GLException(String.format("%s: Buffer for target 0x%X not bound", GL_INVALID_OPERATION, target));
+ }
+ final boolean mutableBuffer = 0 != mutableUsage;
+ final boolean invalidSize = ( mutableBuffer && 0 > size ) // glBufferData, glNamedBufferDataEXT
+ || ( !mutableBuffer && 0 >= size ); // glBufferStorage
+ if( invalidSize ) {
+ throw new GLException(String.format("%s: Invalid size %d for buffer %d on target 0x%X", GL_INVALID_VALUE, size, bufferName, target));
+ }
+
+ dispatch.create(target, size, data, mutableBuffer ? mutableUsage : immutableFlags, glProcAddress);
+ final int glerrPost = caller.glGetError(); // be safe, catch failure!
+ if(GL.GL_NO_ERROR != glerrPost) {
+ throw new GLException(String.format("GL-Error 0x%X while creating %s storage for target 0x%X -> buffer %d of size %d with data %s",
+ glerrPost, mutableBuffer ? "mutable" : "immutable", target, bufferName, size, data));
+ }
+ final GLBufferStorageImpl objOld = (GLBufferStorageImpl) bufferName2StorageMap.get(bufferName);
+ if( null != objOld ) {
+ objOld.reset(size, mutableUsage, immutableFlags);
+ if (DEBUG) {
+ System.err.printf("%s.%s target: 0x%X -> reset %d: %s%n", msgClazzName, msgCreateBound, target, bufferName, objOld);
+ }
+ } else {
+ final GLBufferStorageImpl objNew = new GLBufferStorageImpl(bufferName, size, mutableUsage, immutableFlags);
+ bufferName2StorageMap.put(bufferName, objNew);
+ if (DEBUG) {
+ System.err.printf("%s.%s target: 0x%X -> new %d: %s%n", msgClazzName, msgCreateBound, target, bufferName, objNew);
+ }
+ }
+ }
+
+ /**
+ * Must be called when [re]creating the GL buffer object via {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)},
+ * i.e. implies destruction of the buffer.
+ *
+ * @param bufferName
+ * @param size
+ * @param mutableUsage
+ * @throws GLException if size is less-than zero
+ * @throws GLException if a native GL-Error occurs
+ */
+ public synchronized final void createBufferStorage(final GL caller,
+ final int bufferName, final long size, final Buffer data, final int mutableUsage, final int immutableFlags,
+ final CreateStorageDispatch dispatch, final long glProcAddress) throws GLException {
+ final int glerrPre = caller.glGetError(); // clear
+ if (DEBUG && GL.GL_NO_ERROR != glerrPre) {
+ System.err.printf("%s.%s glerr-pre 0x%X%n", msgClazzName, msgCreateNamed, glerrPre);
+ }
+ if ( 0 > size ) { // glBufferData, glNamedBufferDataEXT
+ throw new GLException(String.format("%s: Invalid size %d for buffer %d", GL_INVALID_VALUE, size, bufferName));
+ }
+ final boolean mutableBuffer = 0 != mutableUsage;
+ if( !mutableBuffer ) {
+ throw new InternalError("Immutable glNamedBufferStorageEXT not supported yet");
+ }
+ dispatch.create(bufferName, size, data, mutableUsage, glProcAddress);
+ final int glerrPost = caller.glGetError(); // be safe, catch failure!
+ if(GL.GL_NO_ERROR != glerrPost) {
+ throw new GLException(String.format("GL-Error 0x%X while creating %s storage for buffer %d of size %d with data %s",
+ glerrPost, "mutable", bufferName, size, data));
+ }
+ final GLBufferStorageImpl objOld = (GLBufferStorageImpl) bufferName2StorageMap.get(bufferName);
+ if( null != objOld ) {
+ objOld.reset(size, mutableUsage, immutableFlags);
+ if (DEBUG) {
+ System.err.printf("%s.%s direct: reset %d: %s%n", msgClazzName, msgCreateNamed, bufferName, objOld);
+ }
+ } else {
+ final GLBufferStorageImpl objNew = new GLBufferStorageImpl(bufferName, size, mutableUsage, immutableFlags);
+ bufferName2StorageMap.put(bufferName, objNew);
+ if (DEBUG) {
+ System.err.printf("%s.%s direct: new %d: %s%n", msgClazzName, msgCreateNamed, bufferName, objNew);
+ }
+ }
+ }
+
+ /**
+ * Must be called when deleting GL buffer objects vis <code>glDeleteBuffers</code>.
+ * @param count
+ * @param bufferNames
+ * @param offset
+ */
+ public synchronized final void notifyBuffersDeleted(final int count, final int[] bufferNames, final int offset) {
+ for(int i=0; i<count; i++) {
+ notifyBufferDeleted(bufferNames[i+offset], i, count);
+ }
+ }
+ /**
+ * Must be called when deleting GL buffer objects vis <code>glDeleteBuffers</code>.
+ * @param n
+ * @param bufferNames
+ */
+ public synchronized final void notifyBuffersDeleted(final int n, final IntBuffer bufferNames) {
+ final int offset = bufferNames.position();
+ for(int i=0; i<n; i++) {
+ notifyBufferDeleted(bufferNames.get(i+offset), i, n);
+ }
+ }
+ /**
+ * Must be called when deleting GL buffer objects vis {@link GL#glDeleteBuffers(int, IntBuffer)}.
+ * @param bufferName
+ * @param i
+ * @param count
+ */
+ private synchronized final void notifyBufferDeleted(final int bufferName, final int i, final int count) {
+ final GLBufferStorageImpl objOld = (GLBufferStorageImpl) bufferName2StorageMap.put(bufferName, null);
+ if (DEBUG) {
+ System.err.printf("%s.notifyBuffersDeleted()[%d/%d]: %d: %s -> null%n", msgClazzName, i+1, count, bufferName, objOld);
+ }
+ if( null == objOld ) {
+ if (DEBUG) {
+ System.err.printf("%s: %s.notifyBuffersDeleted()[%d/%d]: Buffer %d not tracked%n", warning, msgClazzName, i+1, count, bufferName);
+ Thread.dumpStack();
+ }
+ return;
+ }
+ objOld.setMappedBuffer(null);
+ }
+
+ public static interface MapBufferDispatch {
+ ByteBuffer allocNioByteBuffer(final long addr, final long length);
+ }
+ public static interface MapBufferRangeDispatch extends MapBufferDispatch {
+ long mapBuffer(final int targetOrBufferName, final long offset, final long length, final int access, final long glProcAddress);
+ }
+ public static interface MapBufferAllDispatch extends MapBufferDispatch {
+ long mapBuffer(final int targetOrBufferName, final int access, final long glProcAddress);
+ }
+
+ private static final String GL_INVALID_OPERATION = "GL_INVALID_OPERATION";
+ private static final String GL_INVALID_VALUE = "GL_INVALID_VALUE";
+
+ /**
+ * Must be called when mapping GL buffer objects via {@link GL#mapBuffer(int, int)}.
+ * @throws GLException if buffer is not bound to target
+ * @throws GLException if buffer is not tracked
+ * @throws GLException if buffer is already mapped
+ * @throws GLException if buffer has invalid store size, i.e. less-than zero
+ */
+ public synchronized final GLBufferStorage mapBuffer(final GLBufferStateTracker bufferStateTracker,
+ final GL caller, final int target, final int access,
+ final MapBufferAllDispatch dispatch, final long glProcAddress) throws GLException {
+ return this.mapBufferImpl(bufferStateTracker, caller, target, false /* useRange */, 0 /* offset */, 0 /* length */, access, dispatch, glProcAddress);
+ }
+ /**
+ * Must be called when mapping GL buffer objects via {@link GL#mapBufferRange(int, long, long, int)}.
+ * @throws GLException if buffer is not bound to target
+ * @throws GLException if buffer is not tracked
+ * @throws GLException if buffer is already mapped
+ * @throws GLException if buffer has invalid store size, i.e. less-than zero
+ * @throws GLException if buffer mapping range does not fit, incl. offset
+ */
+ public synchronized final GLBufferStorage mapBuffer(final GLBufferStateTracker bufferStateTracker,
+ final GL caller, final int target, final long offset, final long length, final int access,
+ final MapBufferRangeDispatch dispatch, final long glProcAddress) throws GLException {
+ return this.mapBufferImpl(bufferStateTracker, caller, target, true /* useRange */, offset, length, access, dispatch, glProcAddress);
+ }
+ /**
+ * Must be called when mapping GL buffer objects via {@link GL2#mapNamedBuffer(int, int)}.
+ * @throws GLException if buffer is not tracked
+ * @throws GLException if buffer is already mapped
+ * @throws GLException if buffer has invalid store size, i.e. less-than zero
+ */
+ public synchronized final GLBufferStorage mapBuffer(final int bufferName, final int access, final MapBufferAllDispatch dispatch,
+ final long glProcAddress) throws GLException {
+ return this.mapBufferImpl(0 /* target */, bufferName, true /* isNamedBuffer */, false /* useRange */, 0 /* offset */, 0 /* length */, access, dispatch, glProcAddress);
+ }
+ /**
+ * Must be called when mapping GL buffer objects via {@link GL2#mapNamedBufferRange(int, long, long, int)}.
+ * @throws GLException if buffer is not tracked
+ * @throws GLException if buffer is already mapped
+ * @throws GLException if buffer has invalid store size, i.e. less-than zero
+ * @throws GLException if buffer mapping range does not fit, incl. offset
+ */
+ public synchronized final GLBufferStorage mapBuffer(final int bufferName, final long offset, final long length, final int access, final MapBufferRangeDispatch dispatch,
+ final long glProcAddress) throws GLException {
+ return this.mapBufferImpl(0 /* target */, bufferName, true /* isNamedBuffer */, true /* useRange */, offset, length, access, dispatch, glProcAddress);
+ }
+ /**
+ * @throws GLException if buffer is not bound to target
+ * @throws GLException if buffer is not tracked
+ * @throws GLException if buffer is already mapped
+ * @throws GLException if buffer has invalid store size, i.e. less-than zero
+ * @throws GLException if buffer mapping range does not fit, incl. optional offset
+ */
+ private synchronized final GLBufferStorage mapBufferImpl(final GLBufferStateTracker bufferStateTracker,
+ final GL caller, final int target, final boolean useRange,
+ final long offset, final long length, final int access,
+ final MapBufferDispatch dispatch, final long glProcAddress) throws GLException {
+ final int bufferName = bufferStateTracker.getBoundBufferObject(target, caller);
+ if( 0 == bufferName ) {
+ throw new GLException(String.format("%s.%s: %s Buffer for target 0x%X not bound", msgClazzName, msgMapBuffer, GL_INVALID_OPERATION, target));
+ }
+ return this.mapBufferImpl(target, bufferName, false /* isNamedBuffer */, useRange, offset, length, access, dispatch, glProcAddress);
+ }
+ /**
+ * <p>
+ * A zero store size will avoid a native call and returns the unmapped {@link GLBufferStorage}.
+ * </p>
+ * <p>
+ * A null native mapping result indicating an error will
+ * not cause a GLException but returns the unmapped {@link GLBufferStorage}.
+ * This allows the user to handle this case.
+ * </p>
+ * @throws GLException if buffer is not tracked
+ * @throws GLException if buffer is already mapped
+ * @throws GLException if buffer has invalid store size, i.e. less-than zero
+ * @throws GLException if buffer mapping range does not fit, incl. optional offset
+ */
+ private synchronized final GLBufferStorage mapBufferImpl(final int target, final int bufferName, final boolean isNamedBuffer, final boolean useRange, long offset,
+ long length, final int access, final MapBufferDispatch dispatch,
+ final long glProcAddress) throws GLException {
+ final GLBufferStorageImpl store = (GLBufferStorageImpl)bufferName2StorageMap.get(bufferName);
+ if ( null == store ) {
+ throw new GLException("Buffer with name "+bufferName+" not tracked");
+ }
+ if( null != store.getMappedBuffer() ) {
+ throw new GLException(String.format("%s.%s: %s Buffer storage of target 0x%X -> %d: %s is already mapped", msgClazzName, msgMapBuffer, GL_INVALID_OPERATION, target, bufferName, store));
+ }
+ final long storeSize = store.getSize();
+ if ( 0 > storeSize ) {
+ throw new GLException(String.format("%s.%s: %s Buffer storage of target 0x%X -> %d: %s is of less-than zero", msgClazzName, msgMapBuffer, GL_INVALID_OPERATION, target, bufferName, store));
+ }
+ if( !useRange ) {
+ length = storeSize;
+ offset = 0;
+ }
+ if( length + offset > storeSize ) {
+ throw new GLException(String.format("%s.%s: %s Out of range: offset %d, length %d, buffer storage of target 0x%X -> %d: %s", msgClazzName, msgMapBuffer, GL_INVALID_VALUE, offset, length, target, bufferName, store));
+ }
+ if( 0 >= length || 0 > offset ) {
+ throw new GLException(String.format("%s.%s: %s Invalid values: offset %d, length %d, buffer storage of target 0x%X -> %d: %s", msgClazzName, msgMapBuffer, GL_INVALID_VALUE, offset, length, target, bufferName, store));
+ }
+ if( 0 == storeSize ) {
+ return store;
+ }
+ final long addr;
+ if( isNamedBuffer ) {
+ if( useRange ) {
+ addr = ((MapBufferRangeDispatch)dispatch).mapBuffer(bufferName, offset, length, access, glProcAddress);
+ } else {
+ addr = ((MapBufferAllDispatch)dispatch).mapBuffer(bufferName, access, glProcAddress);
+ }
+ } else {
+ if( useRange ) {
+ addr = ((MapBufferRangeDispatch)dispatch).mapBuffer(target, offset, length, access, glProcAddress);
+ } else {
+ addr = ((MapBufferAllDispatch)dispatch).mapBuffer(target, access, glProcAddress);
+ }
+ }
+ // GL's map-buffer implementation always returns NULL on error,
+ // user shall validate the result and the corresponding getGLError() value!
+ if ( 0 == addr ) {
+ if( DEBUG ) {
+ System.err.printf("%s.%s: %s MapBuffer null result for target 0x%X -> %d: %s, off %d, len %d, acc 0x%X%n", msgClazzName, msgMapBuffer, warning, target, bufferName, store, offset, length, access);
+ Thread.dumpStack();
+ }
+ // User shall handle the glError !
+ } else {
+ final ByteBuffer buffer = dispatch.allocNioByteBuffer(addr, length);
+ Buffers.nativeOrder(buffer);
+ if( DEBUG ) {
+ System.err.printf("%s.%s: Target 0x%X -> %d: %s, off %d, len %d, acc 0x%X%n", msgClazzName, msgClazzName, target, bufferName, store.toString(false), offset, length, access);
+ }
+ store.setMappedBuffer(buffer);
+ }
+ return store;
+ }
+
+ public static interface UnmapBufferDispatch {
+ boolean unmap(final int targetOrBufferName, final long glProcAddress);
+ }
+
+ /**
+ * Must be called when unmapping GL buffer objects via {@link GL#glUnmapBuffer(int)}.
+ * <p>
+ * Only clear mapped buffer reference of {@link GLBufferStorage}
+ * if native unmapping was successful.
+ * </p>
+ */
+ public synchronized final boolean unmapBuffer(final GLBufferStateTracker bufferStateTracker, final GL caller,
+ final int target,
+ final UnmapBufferDispatch dispatch, final long glProcAddress) {
+ final int bufferName = bufferStateTracker.getBoundBufferObject(target, caller);
+ final GLBufferStorageImpl store;
+ if( 0 == bufferName ) {
+ if (DEBUG) {
+ System.err.printf("%s: %s.%s: Buffer for target 0x%X not bound%n", warning, msgClazzName, msgUnmapped, target);
+ Thread.dumpStack();
+ }
+ store = null;
+ } else {
+ store = (GLBufferStorageImpl) bufferName2StorageMap.get(bufferName);
+ if( DEBUG && null == store ) {
+ System.err.printf("%s: %s.%s: Buffer %d not tracked%n", warning, msgClazzName, msgUnmapped, bufferName);
+ Thread.dumpStack();
+ }
+ }
+ final boolean res = dispatch.unmap(target, glProcAddress);
+ if( res && null != store ) {
+ store.setMappedBuffer(null);
+ }
+ if( DEBUG ) {
+ System.err.printf("%s.%s %s target: 0x%X -> %d: %s%n", msgClazzName, msgUnmapped, res ? "OK" : "Failed", target, bufferName, store.toString(false));
+ if(!res) {
+ Thread.dumpStack();
+ }
+ }
+ return res;
+ }
+ /**
+ * Must be called when unmapping GL buffer objects via {@link GL2#glUnmapNamedBufferEXT(int)}.
+ * <p>
+ * Only clear mapped buffer reference of {@link GLBufferStorage}
+ * if native unmapping was successful.
+ * </p>
+ */
+ public synchronized final boolean unmapBuffer(final int bufferName,
+ final UnmapBufferDispatch dispatch, final long glProcAddress) {
+ final GLBufferStorageImpl store = (GLBufferStorageImpl) bufferName2StorageMap.get(bufferName);
+ if (DEBUG && null == store ) {
+ System.err.printf("%s: %s.%s: Buffer %d not tracked%n", warning, msgClazzName, msgUnmapped, bufferName);
+ Thread.dumpStack();
+ }
+ final boolean res = dispatch.unmap(bufferName, glProcAddress);
+ if( res && null != store ) {
+ store.setMappedBuffer(null);
+ }
+ if (DEBUG) {
+ System.err.printf("%s.%s %s %d: %s%n", msgClazzName, msgUnmapped, res ? "OK" : "Failed", bufferName, store.toString(false));
+ if(!res) {
+ Thread.dumpStack();
+ }
+ }
+ return res;
+ }
+
+ public synchronized final GLBufferStorage getBufferStorage(final int bufferName) {
+ return (GLBufferStorageImpl)bufferName2StorageMap.get(bufferName);
+ }
+
+ /**
+ * Clear all tracked buffer object knowledge.
+ * <p>
+ * Shall only be called at GLContext destruction <i>iff</i>
+ * there are no other shared GLContext instances left.
+ * </p>
+ */
+ public synchronized final void clear() {
+ if (DEBUG) {
+ System.err.printf("%s.clear() - Thread %s%n", msgClazzName, Thread.currentThread().getName());
+ // Thread.dumpStack();
+ }
+ bufferName2StorageMap.clear();
+ }
+
+ private static final String warning = "WARNING";
+ private static final String msgClazzName = "GLBufferObjectTracker";
+ private static final String msgUnmapped = "notifyBufferUnmapped()";
+ private static final String msgCreateBound = "createBoundBufferStorage()";
+ private static final String msgCreateNamed = "createNamedBufferStorage()";
+ private static final String msgMapBuffer = "mapBuffer()";
+}
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java
deleted file mode 100644
index 78ab7cc93..000000000
--- a/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl;
-
-import javax.media.opengl.*;
-import com.jogamp.common.util.IntLongHashMap;
-
-/**
- * Tracks as closely as possible the sizes of allocated OpenGL buffer
- * objects. When glMapBuffer or glMapBufferARB is called, in order to
- * turn the resulting base address into a java.nio.ByteBuffer, we need
- * to know the size in bytes of the allocated OpenGL buffer object.
- * Previously we would compute this size by using
- * glGetBufferParameterivARB with a pname of GL_BUFFER_SIZE, but
- * it appears doing so each time glMapBuffer is called is too costly
- * on at least Apple's new multithreaded OpenGL implementation. <P>
- *
- * Instead we now try to track the sizes of allocated buffer objects.
- * We watch calls to glBindBuffer to see which buffer is bound to
- * which target and to glBufferData to see how large the buffer's
- * allocated size is. When glMapBuffer is called, we consult our table
- * of buffer sizes to see if we can return an answer without a glGet
- * call. <P>
- *
- * We share the GLBufferSizeTracker objects among all GLContexts for
- * which sharing is enabled, because the namespace for buffer objects
- * is the same for these contexts. <P>
- *
- * Tracking the state of which buffer objects are bound is done in the
- * GLBufferStateTracker and is not completely trivial. In the face of
- * calls to glPushClientAttrib / glPopClientAttrib we currently punt
- * and re-fetch the bound buffer object for the state in question;
- * see, for example, glVertexPointer and the calls down to
- * GLBufferStateTracker.getBoundBufferObject(). Note that we currently
- * ignore new binding targets such as GL_TRANSFORM_FEEDBACK_BUFFER_NV;
- * the fact that new binding targets may be added in the future makes
- * it impossible to cache state for these new targets. <P>
- *
- * Ignoring new binding targets, the primary situation in which we may
- * not be able to return a cached answer is in the case of an error,
- * where glBindBuffer may not have been called before trying to call
- * glBufferData. Also, if external native code modifies a buffer
- * object, we may return an incorrect answer. (FIXME: this case
- * requires more thought, and perhaps stochastic and
- * exponential-fallback checking. However, note that it can only occur
- * in the face of external native code which requires that the
- * application be signed anyway, so there is no security risk in this
- * area.)
- */
-
-public class GLBufferSizeTracker {
- // Map from buffer names to sizes.
- // Note: should probably have some way of shrinking this map, but
- // can't just make it a WeakHashMap because nobody holds on to the
- // keys; would have to always track creation and deletion of buffer
- // objects, which is probably sub-optimal. The expected usage
- // pattern of buffer objects indicates that the fact that this map
- // never shrinks is probably not that bad.
- private IntLongHashMap bufferSizeMap;
- protected static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLBufferSizeTracker", true);
-
- public GLBufferSizeTracker() {
- bufferSizeMap = new IntLongHashMap();
- bufferSizeMap.setKeyNotFoundValue(0xFFFFFFFFFFFFFFFFL);
- }
-
- public final void setBufferSize(GLBufferStateTracker bufferStateTracker,
- int target, GL caller, long size) {
- // Need to do some similar queries to getBufferSize below
- int buffer = bufferStateTracker.getBoundBufferObject(target, caller);
- if (buffer != 0) {
- setDirectStateBufferSize(buffer, caller, size);
- }
- // We don't know the current buffer state. Note that the buffer
- // state tracker will have made the appropriate OpenGL query if it
- // didn't know what was going on, so at this point we have nothing
- // left to do except drop this piece of information on the floor.
- }
-
- public final void setDirectStateBufferSize(int buffer, GL caller, long size) {
- bufferSizeMap.put(buffer, size);
- }
-
- public final long getBufferSize(GLBufferStateTracker bufferStateTracker,
- int target,
- GL caller) {
- // See whether we know what buffer is currently bound to the given
- // state
- final int buffer = bufferStateTracker.getBoundBufferObject(target, caller);
- if (0 != buffer) {
- return getBufferSizeImpl(target, buffer, caller);
- }
- // We don't know what's going on in this case; query the GL for an answer
- // FIXME: both functions return 'int' types, which is not suitable,
- // since buffer lenght is 64bit ?
- int[] tmp = new int[1];
- caller.glGetBufferParameteriv(target, GL.GL_BUFFER_SIZE, tmp, 0);
- if (DEBUG) {
- System.err.println("GLBufferSizeTracker.getBufferSize(): no cached buffer information");
- }
- return (long) tmp[0];
- }
-
- public final long getDirectStateBufferSize(int buffer, GL caller) {
- return getBufferSizeImpl(0, buffer, caller);
- }
-
- private final long getBufferSizeImpl(int target, int buffer, GL caller) {
- // See whether we know the size of this buffer object; at this
- // point we almost certainly should if the application is
- // written correctly
- long sz = bufferSizeMap.get(buffer);
- if (0xFFFFFFFFFFFFFFFFL == sz) {
- // For robustness, try to query this value from the GL as we used to
- // FIXME: both functions return 'int' types, which is not suitable,
- // since buffer lenght is 64bit ?
- int[] tmp = new int[1];
- if(0==target) {
- // DirectState ..
- if(caller.isFunctionAvailable("glGetNamedBufferParameterivEXT")) {
- caller.getGL2().glGetNamedBufferParameterivEXT(buffer, GL.GL_BUFFER_SIZE, tmp, 0);
- } else {
- throw new GLException("Error: getDirectStateBufferSize called with unknown state and GL function 'glGetNamedBufferParameterivEXT' n/a to query size");
- }
- } else {
- caller.glGetBufferParameteriv(target, GL.GL_BUFFER_SIZE, tmp, 0);
- }
- if (tmp[0] == 0) {
- // Assume something is wrong rather than silently going along
- throw new GLException("Error: buffer size returned by "+
- ((0==target)?"glGetNamedBufferParameterivEXT":"glGetBufferParameteriv")+
- " was zero; probably application error");
- }
- // Assume we just don't know what's happening
- sz = (long) tmp[0];
- bufferSizeMap.put(buffer, sz);
- if (DEBUG) {
- System.err.println("GLBufferSizeTracker.getBufferSize(): made slow query to cache size " +
- sz +
- " for buffer " +
- buffer);
- }
- }
- return sz;
- }
-
- // This should be called on any major event where we might start
- // producing wrong answers, such as OpenGL context creation and
- // destruction if we don't know whether there are other currently-
- // created contexts that might be keeping the buffer objects alive
- // that we're dealing with
- public final void clearCachedBufferSizes() {
- bufferSizeMap.clear();
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
index 92e27cbd4..825ad0554 100644
--- a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,7 +41,9 @@
package jogamp.opengl;
import javax.media.opengl.*;
+
import com.jogamp.common.util.IntIntHashMap;
+import com.jogamp.common.util.PropertyAccess;
/**
* Tracks as closely as possible which OpenGL buffer object is bound
@@ -49,8 +51,13 @@ import com.jogamp.common.util.IntIntHashMap;
* GLBufferStateTracker objects are allocated on a per-OpenGL-context basis.
* This class is used to verify that e.g. the vertex
* buffer object extension is in use when the glVertexPointer variant
- * taking a long as argument is called. <P>
- *
+ * taking a long as argument is called.
+ * <p>
+ * The buffer binding state is local to it's OpenGL context,
+ * i.e. not shared across multiple OpenGL context.
+ * Hence this code is thread safe due to no multithreading usage.
+ * </p>
+ * <p>
* Note that because the enumerated value used for the binding of a
* buffer object (e.g. GL_ARRAY_BUFFER) is different than that used to
* query the binding using glGetIntegerv (e.g.
@@ -60,50 +67,147 @@ import com.jogamp.common.util.IntIntHashMap;
* to a particular state. It turns out that for some uses, such as
* finding the size of the currently bound buffer, this doesn't
* matter, though of course without knowing the buffer object we can't
- * re-associate the queried size with the buffer object ID. <P>
- *
- * Because the namespace of buffer objects is the unsigned integers
- * with 0 reserved by the GL, and because we have to be able to return
- * both 0 and other integers as valid answers from
- * getBoundBufferObject(), we need a second query, which is to ask
- * whether we know the state of the binding for a given target. For
- * "unknown" targets such as GL_TRANSFORM_FEEDBACK_BUFFER_NV we return
+ * re-associate the queried size with the buffer object ID.
+ * </p>
+ * <p>
+ * For <i>unknown</i> targets such as GL_TRANSFORM_FEEDBACK_BUFFER_NV we return
* false from this, but we also clear the valid bit and later refresh
* the binding state if glPushClientAttrib / glPopClientAttrib are
* called, since we don't want the complexity of tracking stacks of
* these attributes.
- *
+ * </p>
*/
public class GLBufferStateTracker {
- protected static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLBufferStateTracker", true);
+ protected static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = PropertyAccess.isPropertyDefined("jogl.debug.GLBufferStateTracker", true);
+ }
+
// Maps binding targets to buffer objects. A null value indicates
// that the binding is unknown. A zero value indicates that it is
- // known that no buffer is bound to the target, according to the
- // OpenGL specifications.
+ // known that no buffer is bound to the target, according to the
+ // OpenGL specifications.
// http://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml
- private IntIntHashMap bindingMap;
+ private final IntIntHashMap bindingMap;
+ private static final int bindingNotFound = 0xFFFFFFFF;
- private int[] bufTmp = new int[1];
+ private final int[] bufTmp = new int[1];
public GLBufferStateTracker() {
bindingMap = new IntIntHashMap();
- bindingMap.setKeyNotFoundValue(0xFFFFFFFF);
+ bindingMap.setKeyNotFoundValue(bindingNotFound);
// Start with known unbound targets for known keys
+ // setBoundBufferObject(GL2ES3.GL_VERTEX_ARRAY_BINDING, 0); // not using default VAO (removed in GL3 core) - only explicit
setBoundBufferObject(GL.GL_ARRAY_BUFFER, 0);
+ setBoundBufferObject(GL4.GL_DRAW_INDIRECT_BUFFER, 0);
setBoundBufferObject(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
- setBoundBufferObject(GL2.GL_PIXEL_PACK_BUFFER, 0);
- setBoundBufferObject(GL2.GL_PIXEL_UNPACK_BUFFER, 0);
+ setBoundBufferObject(GL2ES3.GL_PIXEL_PACK_BUFFER, 0);
+ setBoundBufferObject(GL2ES3.GL_PIXEL_UNPACK_BUFFER, 0);
}
- public final void setBoundBufferObject(int target, int value) {
- bindingMap.put(target, value);
+
+ /**
+ * GL_ARRAY_BUFFER​,
+ * GL_ATOMIC_COUNTER_BUFFER​,
+ * GL_COPY_READ_BUFFER​,
+ * GL_COPY_WRITE_BUFFER​,
+ * GL_DRAW_INDIRECT_BUFFER​,
+ * GL_DISPATCH_INDIRECT_BUFFER​,
+ * GL_ELEMENT_ARRAY_BUFFER​,
+ * GL_PIXEL_PACK_BUFFER​,
+ * GL_PIXEL_UNPACK_BUFFER​,
+ * GL_SHADER_STORAGE_BUFFER​,
+ * GL_TEXTURE_BUFFER​,
+ * GL_TRANSFORM_FEEDBACK_BUFFER​ or
+ * GL_UNIFORM_BUFFER​.
+ *
+ * GL_VERTEX_ARRAY_BINDING
+ *
+ */
+ private static final int getQueryName(final int target) {
+ switch (target) {
+ case GL.GL_ARRAY_BUFFER: return GL.GL_ARRAY_BUFFER_BINDING;
+ case GL4.GL_ATOMIC_COUNTER_BUFFER: return GL4.GL_ATOMIC_COUNTER_BUFFER_BINDING;
+ case GL2ES3.GL_COPY_READ_BUFFER: return GL2ES3.GL_COPY_READ_BUFFER_BINDING;
+ case GL2ES3.GL_COPY_WRITE_BUFFER: return GL2ES3.GL_COPY_WRITE_BUFFER_BINDING;
+ case GL4.GL_DRAW_INDIRECT_BUFFER: return GL4.GL_DRAW_INDIRECT_BUFFER_BINDING;
+ case GL4.GL_DISPATCH_INDIRECT_BUFFER: return GL4.GL_DISPATCH_INDIRECT_BUFFER_BINDING;
+ case GL.GL_ELEMENT_ARRAY_BUFFER: return GL.GL_ELEMENT_ARRAY_BUFFER_BINDING;
+ case GL2ES3.GL_PIXEL_PACK_BUFFER: return GL2ES3.GL_PIXEL_PACK_BUFFER_BINDING;
+ case GL2ES3.GL_PIXEL_UNPACK_BUFFER: return GL2ES3.GL_PIXEL_UNPACK_BUFFER_BINDING;
+ // FIXME case GL4.GL_QUERY_BUFFER: return GL4.GL_QUERY_BUFFER_BINDING;
+ case GL4.GL_SHADER_STORAGE_BUFFER: return GL4.GL_SHADER_STORAGE_BUFFER_BINDING;
+ case GL2GL3.GL_TEXTURE_BUFFER: return GL2GL3.GL_TEXTURE_BINDING_BUFFER;
+ case GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER: return GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER_BINDING;
+ case GL2ES3.GL_UNIFORM_BUFFER: return GL2ES3.GL_UNIFORM_BUFFER_BINDING;
+
+ case GL2ES3.GL_VERTEX_ARRAY_BINDING: return GL2ES3.GL_VERTEX_ARRAY_BINDING;
+
+ default:
+ throw new GLException(String.format("GL_INVALID_ENUM​: Invalid binding target 0x%X", target));
+ }
+ }
+ private static final void checkTargetName(final int target) {
+ switch (target) {
+ case GL.GL_ARRAY_BUFFER:
+ case GL4.GL_ATOMIC_COUNTER_BUFFER:
+ case GL2ES3.GL_COPY_READ_BUFFER:
+ case GL2ES3.GL_COPY_WRITE_BUFFER:
+ case GL4.GL_DRAW_INDIRECT_BUFFER:
+ case GL4.GL_DISPATCH_INDIRECT_BUFFER:
+ case GL.GL_ELEMENT_ARRAY_BUFFER:
+ case GL2ES3.GL_PIXEL_PACK_BUFFER:
+ case GL2ES3.GL_PIXEL_UNPACK_BUFFER:
+ // FIXME case GL4.GL_QUERY_BUFFER:
+ case GL4.GL_SHADER_STORAGE_BUFFER:
+ case GL2GL3.GL_TEXTURE_BUFFER:
+ case GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER:
+ case GL2ES3.GL_UNIFORM_BUFFER:
+
+ case GL2ES3.GL_VERTEX_ARRAY_BINDING:
+ return;
+
+ default:
+ throw new GLException(String.format("GL_INVALID_ENUM​: Invalid binding target 0x%X", target));
+ }
+ }
+
+ /**
+ * Must be called when binding a buffer, e.g.:
+ * <ul>
+ * <li><code>glBindBuffer</code></li>
+ * <li><code>glBindBufferBase</code></li>
+ * <li><code>glBindBufferRange</code></li>
+ * </ul>
+ * @param target
+ * @param bufferName
+ */
+ public final void setBoundBufferObject(final int target, final int bufferName) {
+ checkTargetName(target);
+ final int oldBufferName = bindingMap.put(target, bufferName);
+ /***
+ * Test for clearing bound buffer states when unbinding VAO,
+ * Bug 692 Comment 5 is invalid, i.e. <https://jogamp.org/bugzilla/show_bug.cgi?id=692#c5>.
+ * However spec doesn't mention such behavior, and rendering w/ CPU sourced data
+ * after unbinding a VAO w/o unbinding the VBOs resulted to no visible image.
+ * Leaving code in here for discussion - in case I am wrong.
+ *
+ final int pre = bindingMap.put(target, bufferName);
+ if( GL2ES3.GL_VERTEX_ARRAY_BINDING == target && keyNotFound != pre && 0 == bufferName ) {
+ // Unbinding a previous bound VAO leads to unbinding of all buffers!
+ bindingMap.put(GL.GL_ARRAY_BUFFER, 0);
+ bindingMap.put(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
+ bindingMap.put(GL2.GL_PIXEL_PACK_BUFFER, 0);
+ bindingMap.put(GL2.GL_PIXEL_UNPACK_BUFFER, 0);
+ bindingMap.put(GL4.GL_DRAW_INDIRECT_BUFFER, 0);
+ } */
if (DEBUG) {
- System.err.println();
- System.err.println("GLBufferStateTracker.setBoundBufferObject() target 0x" +
- Integer.toHexString(target) + " -> mapped bound buffer 0x" +
- Integer.toHexString(value));
+ System.err.println("GLBufferStateTracker.setBoundBufferObject() target " +
+ toHexString(target) + ": " + toHexString(oldBufferName) + " -> " + toHexString(bufferName));
// Thread.dumpStack();
}
}
@@ -112,29 +216,26 @@ public class GLBufferStateTracker {
specified target (e.g. GL_ARRAY_BUFFER) is currently unknown.
You must use isBoundBufferObjectKnown() to see whether the
return value is valid. */
- public final int getBoundBufferObject(int target, GL caller) {
+ public final int getBoundBufferObject(final int target, final GL caller) {
int value = bindingMap.get(target);
- if (0xFFFFFFFF == value) {
+ if (bindingNotFound == value) {
// User probably either called glPushClientAttrib /
// glPopClientAttrib or is querying an unknown target. See
// whether we know how to fetch this state.
- boolean gotQueryTarget = true;
- int queryTarget = 0;
- switch (target) {
- case GL.GL_ARRAY_BUFFER: queryTarget = GL.GL_ARRAY_BUFFER_BINDING; break;
- case GL.GL_ELEMENT_ARRAY_BUFFER: queryTarget = GL.GL_ELEMENT_ARRAY_BUFFER_BINDING; break;
- case GL2.GL_PIXEL_PACK_BUFFER: queryTarget = GL2.GL_PIXEL_PACK_BUFFER_BINDING; break;
- case GL2.GL_PIXEL_UNPACK_BUFFER: queryTarget = GL2.GL_PIXEL_UNPACK_BUFFER_BINDING; break;
- default: gotQueryTarget = false; break;
- }
- if (gotQueryTarget) {
+ final int queryTarget = getQueryName(target);
+ if ( 0 != queryTarget ) {
+ final int glerrPre = caller.glGetError(); // clear
caller.glGetIntegerv(queryTarget, bufTmp, 0);
- value = bufTmp[0];
+ final int glerrPost = caller.glGetError(); // be safe, e.g. GL '3.0 Mesa 8.0.4' may produce an error querying GL_PIXEL_UNPACK_BUFFER_BINDING, ignore value
+ if(GL.GL_NO_ERROR == glerrPost) {
+ value = bufTmp[0];
+ } else {
+ value = 0;
+ }
if (DEBUG) {
- System.err.println();
- System.err.println("GLBufferStateTracker.getBoundBufferObject() [queried value]: target 0x" +
- Integer.toHexString(target) + " / query 0x"+Integer.toHexString(queryTarget)+
- " -> mapped bound buffer 0x" + Integer.toHexString(value));
+ System.err.println("GLBufferStateTracker.getBoundBufferObject() glerr[pre "+toHexString(glerrPre)+", post "+toHexString(glerrPost)+"], [queried value]: target " +
+ toHexString(target) + " / query "+toHexString(queryTarget)+
+ " -> mapped bound buffer " + toHexString(value));
}
setBoundBufferObject(target, value);
return value;
@@ -142,8 +243,7 @@ public class GLBufferStateTracker {
return 0;
}
if (DEBUG) {
- System.err.println();
- System.err.println("GLBufferStateTracker.getBoundBufferObject() [mapped value]: target 0x" +
+ System.err.println("GLBufferStateTracker.getBoundBufferObject() [mapped value]: target 0x" +
Integer.toHexString(target) + " -> mapped bound buffer 0x" +
Integer.toHexString(value));
}
@@ -157,12 +257,12 @@ public class GLBufferStateTracker {
from GLContext.makeCurrent() in the future to possibly increase
the robustness of these caches in the face of external native
code manipulating OpenGL state. */
- public final void clearBufferObjectState() {
+ public final void clear() {
+ if (DEBUG) {
+ System.err.println("GLBufferStateTracker.clear() - Thread "+Thread.currentThread().getName());
+ // Thread.dumpStack();
+ }
bindingMap.clear();
- if (DEBUG) {
- System.err.println();
- System.err.println("GLBufferStateTracker.clearBufferObjectState()");
- //Thread.dumpStack();
- }
}
+ private final String toHexString(final int i) { return Integer.toHexString(i); }
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 050c619fd..a44075e90 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -40,30 +40,40 @@
package jogamp.opengl;
+import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import com.jogamp.common.os.DynamicLookupHelper;
+import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.VersionNumber;
-import com.jogamp.gluegen.runtime.FunctionAddressResolver;
+import com.jogamp.common.util.VersionNumberString;
+import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDebugListener;
import javax.media.opengl.GLDebugMessage;
import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLPipelineFactory;
import javax.media.opengl.GLProfile;
@@ -84,21 +94,33 @@ public abstract class GLContextImpl extends GLContext {
// OpenGL functions.
private ProcAddressTable glProcAddressTable;
+ private String glVendor;
private String glRenderer;
private String glRendererLowerCase;
private String glVersion;
- // Tracks creation and initialization of buffer objects to avoid
+ // Tracks lifecycle of buffer objects to avoid
// repeated glGet calls upon glMapBuffer operations
- private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet
- private final GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker();
+ private final GLBufferObjectTracker bufferObjectTracker;
+ private final GLBufferStateTracker bufferStateTracker;
private final GLStateTracker glStateTracker = new GLStateTracker();
private GLDebugMessageHandler glDebugHandler = null;
private final int[] boundFBOTarget = new int[] { 0, 0 }; // { draw, read }
+ private int defaultVAO = 0;
+ /**
+ * <ul>
+ * <li>[GLAutoDrawable.upstreamLock].lock()</li>
+ * <li>drawable.surface.lock()</li>
+ * <li>contextLock.lock()</li>
+ * </ul>
+ */
protected GLDrawableImpl drawable;
protected GLDrawableImpl drawableRead;
-
+
+ private boolean pixelDataEvaluated;
+ private int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType;
+
protected GL gl;
protected static final Object mappedContextTypeObjectLock;
@@ -119,76 +141,88 @@ public abstract class GLContextImpl extends GLContext {
mappedGLXProcAddress.clear();
}
- public GLContextImpl(GLDrawableImpl drawable, GLContext shareWith) {
+ public GLContextImpl(final GLDrawableImpl drawable, final GLContext shareWith) {
super();
- if (shareWith != null) {
+ if( null == drawable ) {
+ throw new IllegalArgumentException("Null drawable");
+ }
+ bufferStateTracker = new GLBufferStateTracker();
+ if ( null != shareWith ) {
GLContextShareSet.registerSharing(this, shareWith);
+ bufferObjectTracker = ((GLContextImpl)shareWith).getBufferObjectTracker();
+ if( null == bufferObjectTracker ) {
+ throw new InternalError("shared-master context hash null GLBufferObjectTracker: "+toHexString(shareWith.hashCode()));
+ }
+ } else {
+ bufferObjectTracker = new GLBufferObjectTracker();
}
- GLContextShareSet.synchronizeBufferObjectSharing(shareWith, this);
this.drawable = drawable;
- if(null != drawable) {
- drawable.associateContext(this, true);
- }
this.drawableRead = drawable;
this.glDebugHandler = new GLDebugMessageHandler(this);
}
- @Override
- protected void resetStates() {
- // Because we don't know how many other contexts we might be
- // sharing with (and it seems too complicated to implement the
- // GLObjectTracker's ref/unref scheme for the buffer-related
- // optimizations), simply clear the cache of known buffers' sizes
- // when we destroy contexts
- if (bufferSizeTracker != null) {
- bufferSizeTracker.clearCachedBufferSizes();
- }
-
- if (bufferStateTracker != null) { // <init>
- bufferStateTracker.clearBufferObjectState();
+ private final void clearStates() {
+ if( !GLContextShareSet.hasCreatedSharedLeft(this) ) {
+ bufferObjectTracker.clear();
}
+ bufferStateTracker.clear();
+ glStateTracker.setEnabled(false);
+ glStateTracker.clearStates();
+ }
- if (glStateTracker != null) { // <init>
- glStateTracker.clearStates(false);
+ @Override
+ protected void resetStates(final boolean isInit) {
+ if( !isInit ) {
+ clearStates();
}
-
extensionAvailability = null;
glProcAddressTable = null;
gl = null;
contextFQN = null;
additionalCtxCreationFlags = 0;
- glRenderer = "";
+ glVendor = "";
+ glRenderer = glVendor;
glRendererLowerCase = glRenderer;
-
- if (boundFBOTarget != null) { // <init>
+ glVersion = glVendor;
+
+ if ( !isInit && null != boundFBOTarget ) { // <init>: boundFBOTarget is not written yet
boundFBOTarget[0] = 0; // draw
boundFBOTarget[1] = 0; // read
}
- super.resetStates();
+ pixelDataEvaluated = false;
+
+ super.resetStates(isInit);
}
@Override
- public final GLDrawable setGLReadDrawable(GLDrawable read) {
- if(!isGLReadDrawableAvailable()) {
- throw new GLException("Setting read drawable feature not available");
- }
- final boolean lockHeld = lock.isOwner(Thread.currentThread());
- if(lockHeld) {
- release();
- } else if(lock.isLockedByOtherThread()) { // still could glitch ..
- throw new GLException("GLContext current by other thread ("+lock.getOwner()+"), operation not allowed.");
- }
- final GLDrawable old = drawableRead;
- drawableRead = ( null != read ) ? (GLDrawableImpl) read : drawable;
- if(lockHeld) {
- makeCurrent();
- }
- return old;
+ public final GLDrawable setGLReadDrawable(final GLDrawable read) {
+ // Validate constraints first!
+ if(!isGLReadDrawableAvailable()) {
+ throw new GLException("Setting read drawable feature not available");
+ }
+ final Thread currentThread = Thread.currentThread();
+ if( lock.isLockedByOtherThread() ) {
+ throw new GLException("GLContext current by other thread "+lock.getOwner().getName()+", operation not allowed on this thread "+currentThread.getName());
+ }
+ final boolean lockHeld = lock.isOwner(currentThread);
+ if( lockHeld && lock.getHoldCount() > 1 ) {
+ // would need to makeCurrent * holdCount
+ throw new GLException("GLContext is recursively locked - unsupported for setGLDrawable(..)");
+ }
+ if(lockHeld) {
+ release(false);
+ }
+ final GLDrawable old = drawableRead;
+ drawableRead = ( null != read ) ? (GLDrawableImpl) read : drawable;
+ if(lockHeld) {
+ makeCurrent();
+ }
+ return old;
}
@Override
@@ -197,27 +231,47 @@ public abstract class GLContextImpl extends GLContext {
}
@Override
- public final GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly) {
- if(null==readWrite) {
- throw new GLException("Null read/write drawable not allowed");
- }
- final boolean lockHeld = lock.isOwner(Thread.currentThread());
- if(lockHeld) {
- release();
- } else if(lock.isLockedByOtherThread()) { // still could glitch ..
- throw new GLException("GLContext current by other thread ("+lock.getOwner()+"), operation not allowed.");
- }
- if(!setWriteOnly || drawableRead==drawable) { // if !setWriteOnly || !explicitReadDrawable
- drawableRead = (GLDrawableImpl) readWrite;
- }
- final GLDrawableImpl old = drawable;
- old.associateContext(this, false);
- drawable = (GLDrawableImpl) readWrite ;
- drawable.associateContext(this, true);
- if(lockHeld) {
- makeCurrent();
- }
- return old;
+ public final GLDrawable setGLDrawable(final GLDrawable readWrite, final boolean setWriteOnly) {
+ // Validate constraints first!
+ final Thread currentThread = Thread.currentThread();
+ if( lock.isLockedByOtherThread() ) {
+ throw new GLException("GLContext current by other thread "+lock.getOwner().getName()+", operation not allowed on this thread "+currentThread.getName());
+ }
+ final boolean lockHeld = lock.isOwner(currentThread);
+ if( lockHeld && lock.getHoldCount() > 1 ) {
+ // would need to makeCurrent * holdCount
+ throw new GLException("GLContext is recursively locked - unsupported for setGLDrawable(..)");
+ }
+ if( drawable == readWrite && ( setWriteOnly || drawableRead == readWrite ) ) {
+ return drawable; // no change.
+ }
+ final GLDrawableImpl old = drawable;
+ if( isCreated() && null != old && old.isRealized() ) {
+ if(!lockHeld) {
+ makeCurrent();
+ }
+ // sync GL ctx w/ drawable's framebuffer before de-association
+ gl.glFinish();
+ associateDrawable(false);
+ if(!lockHeld) {
+ release(false);
+ }
+ }
+ if(lockHeld) {
+ release(false);
+ }
+ if( !setWriteOnly || drawableRead == drawable ) { // if !setWriteOnly || !explicitReadDrawable
+ drawableRead = (GLDrawableImpl) readWrite;
+ }
+ drawableRetargeted |= null != drawable && readWrite != drawable;
+ drawable = (GLDrawableImpl) readWrite ;
+ if( isCreated() && null != drawable && drawable.isRealized() ) {
+ makeCurrent(true); // implicit: associateDrawable(true)
+ if( !lockHeld ) {
+ release(false);
+ }
+ }
+ return old;
}
@Override
@@ -226,7 +280,18 @@ public abstract class GLContextImpl extends GLContext {
}
public final GLDrawableImpl getDrawableImpl() {
- return (GLDrawableImpl) getGLDrawable();
+ return drawable;
+ }
+
+ @Override
+ public final GL getRootGL() {
+ GL _gl = gl;
+ GL _parent = _gl.getDownstreamGL();
+ while ( null != _parent ) {
+ _gl = _parent;
+ _parent = _gl.getDownstreamGL();
+ }
+ return _gl;
}
@Override
@@ -235,17 +300,22 @@ public abstract class GLContextImpl extends GLContext {
}
@Override
- public GL setGL(GL gl) {
- if(DEBUG) {
- String sgl1 = (null!=this.gl)?this.gl.getClass().getSimpleName()+", "+this.gl.toString():"<null>";
- String sgl2 = (null!=gl)?gl.getClass().getSimpleName()+", "+gl.toString():"<null>";
- Exception e = new Exception("Info: setGL (OpenGL "+getGLVersion()+"): "+Thread.currentThread().getName()+", "+sgl1+" -> "+sgl2);
- e.printStackTrace();
+ public GL setGL(final GL gl) {
+ if( DEBUG ) {
+ final String sgl1 = (null!=this.gl)?this.gl.getClass().getSimpleName()+", "+this.gl.toString():"<null>";
+ final String sgl2 = (null!=gl)?gl.getClass().getSimpleName()+", "+gl.toString():"<null>";
+ System.err.println("Info: setGL (OpenGL "+getGLVersion()+"): "+getThreadName()+", "+sgl1+" -> "+sgl2);
+ Thread.dumpStack();
}
this.gl = gl;
return gl;
}
+ @Override
+ public final int getDefaultVAO() {
+ return defaultVAO;
+ }
+
/**
* Call this method to notify the OpenGL context
* that the drawable has changed (size or position).
@@ -266,82 +336,110 @@ public abstract class GLContextImpl extends GLContext {
public void release() throws GLException {
release(false);
}
- private void release(boolean inDestruction) throws GLException {
- if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - release() - force: "+inDestruction+", "+lock);
- }
- if ( !lock.isOwner(Thread.currentThread()) ) {
- throw new GLException("Context not current on current thread "+Thread.currentThread().getName()+": "+this);
- }
- Throwable drawableContextMadeCurrentException = null;
- final boolean actualRelease = ( inDestruction || lock.getHoldCount() == 1 ) && 0 != contextHandle;
- try {
- if( actualRelease ) {
- if( !inDestruction ) {
- try {
- contextMadeCurrent(false);
- } catch (Throwable t) {
- drawableContextMadeCurrentException = t;
- }
- }
- releaseImpl();
- }
- } finally {
- // exception prone ..
- if( actualRelease ) {
- setCurrent(null);
+ private String getTraceSwitchMsg() {
+ final long drawH = null != drawable ? drawable.getHandle() : 0;
+ return "obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", isShared "+GLContextShareSet.isShared(this)+", surf "+(null!=drawable)+" "+toHexString(drawH)+", "+lock;
+ }
+ private void release(final boolean inDestruction) throws GLException {
+ if( TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[release.0, inDestruction: "+inDestruction+"]: "+getTraceSwitchMsg());
}
- drawable.unlockSurface();
- lock.unlock();
- if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - "+(actualRelease?"switch":"keep ")+" - CONTEXT_RELEASE - "+lock);
+ if ( !lock.isOwner(Thread.currentThread()) ) {
+ final String msg = getThreadName() +": Context not current on thread, inDestruction: "+inDestruction+", "+getTraceSwitchMsg();
+ if( DEBUG_TRACE_SWITCH ) {
+ System.err.println(msg);
+ if( null != lastCtxReleaseStack ) {
+ System.err.print("Last release call: ");
+ lastCtxReleaseStack.printStackTrace();
+ } else {
+ System.err.println("Last release call: NONE");
+ }
+ }
+ throw new GLException(msg);
+ }
+
+ Throwable drawableContextMadeCurrentException = null;
+ final boolean actualRelease = ( inDestruction || lock.getHoldCount() == 1 ) && 0 != contextHandle;
+ try {
+ if( actualRelease ) {
+ if( !inDestruction ) {
+ try {
+ contextMadeCurrent(false);
+ } catch (final Throwable t) {
+ drawableContextMadeCurrentException = t;
+ }
+ }
+ releaseImpl();
+ }
+ } finally {
+ // exception prone ..
+ if( actualRelease ) {
+ setCurrent(null);
+ }
+ lock.unlock();
+ drawable.unlockSurface();
+ if( DEBUG_TRACE_SWITCH ) {
+ final String msg = getThreadName() +": GLContext.ContextSwitch[release.X]: "+(actualRelease?"switch":"keep ")+" - "+getTraceSwitchMsg();
+ lastCtxReleaseStack = new Throwable(msg);
+ if( TRACE_SWITCH ) {
+ System.err.println(msg);
+ // Thread.dumpStack();
+ }
+ }
+ }
+ if(null != drawableContextMadeCurrentException) {
+ throw new GLException("GLContext.release(false) during GLDrawableImpl.contextMadeCurrent(this, false)", drawableContextMadeCurrentException);
}
- }
- if(null != drawableContextMadeCurrentException) {
- throw new GLException("GLContext.release(false) during GLDrawableImpl.contextMadeCurrent(this, false)", drawableContextMadeCurrentException);
- }
-
}
+ private Throwable lastCtxReleaseStack = null;
protected abstract void releaseImpl() throws GLException;
@Override
public final void destroy() {
- if (DEBUG || TRACE_SWITCH) {
- System.err.println(getThreadName() + ": GLContextImpl.destroy.0: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
- ", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
+ if ( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() + ": GLContextImpl.destroy.0: "+getTraceSwitchMsg());
}
- if (contextHandle != 0) {
- int lockRes = drawable.lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
+ if ( 0 != contextHandle ) { // isCreated() ?
+ if ( null == drawable ) {
+ throw new GLException("GLContext created but drawable is null: "+toString());
+ }
+ final int lockRes = drawable.lockSurface();
+ if ( NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes ) {
// this would be odd ..
throw new GLException("Surface not ready to lock: "+drawable);
}
- Throwable drawableContextRealizedException = null;
+ Throwable associateDrawableException = null;
try {
+ if ( !drawable.isRealized() ) {
+ throw new GLException("GLContext created but drawable not realized: "+toString());
+ }
// Must hold the lock around the destroy operation to make sure we
// don't destroy the context while another thread renders to it.
- lock.lock(); // holdCount++ -> 1 - 3 (1: not locked, 2-3: destroy while rendering)
- if ( lock.getHoldCount() > 2 ) {
- final String msg = getThreadName() + ": GLContextImpl.destroy: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle);
- if (DEBUG || TRACE_SWITCH) {
- System.err.println(msg+" - Lock was hold more than once - makeCurrent/release imbalance: "+lock);
+ lock.lock(); // holdCount++ -> 1 - n (1: not locked, 2-n: destroy while rendering)
+ if ( DEBUG_TRACE_SWITCH ) {
+ if ( lock.getHoldCount() > 2 ) {
+ System.err.println(getThreadName() + ": GLContextImpl.destroy: Lock was hold more than once - makeCurrent/release imbalance: "+getTraceSwitchMsg());
Thread.dumpStack();
}
- if ( lock.getHoldCount() > 3 ) {
- throw new GLException(msg+" - Lock was hold more than twice - makeCurrent/release imbalance: "+lock);
- }
}
try {
- // release current context
- if(lock.getHoldCount() == 1) {
- // needs current context to disable debug handler
- makeCurrent();
+ // if not current, makeCurrent(), to call associateDrawable(..) and to disable debug handler
+ if ( lock.getHoldCount() == 1 ) {
+ if ( GLContext.CONTEXT_NOT_CURRENT == makeCurrent() ) {
+ throw new GLException("GLContext.makeCurrent() failed: "+toString());
+ }
}
try {
- contextRealized(false);
- drawable.associateContext(this, false);
- } catch (Throwable t) {
- drawableContextRealizedException = t;
+ associateDrawable(false);
+ } catch (final Throwable t) {
+ associateDrawableException = t;
+ }
+ if ( 0 != defaultVAO ) {
+ final int[] tmp = new int[] { defaultVAO };
+ final GL2ES3 gl2es3 = gl.getRootGL().getGL2ES3();
+ gl2es3.glBindVertexArray(0);
+ gl2es3.glDeleteVertexArrays(1, tmp, 0);
+ defaultVAO = 0;
}
glDebugHandler.enable(false);
if(lock.getHoldCount() > 1) {
@@ -352,29 +450,30 @@ public abstract class GLContextImpl extends GLContext {
contextHandle = 0;
glDebugHandler = null;
// this maybe impl. in a platform specific way to release remaining shared ctx.
- if(GLContextShareSet.contextDestroyed(this) && !GLContextShareSet.hasCreatedSharedLeft(this)) {
+ if( GLContextShareSet.contextDestroyed(this) && !GLContextShareSet.hasCreatedSharedLeft(this) ) {
GLContextShareSet.unregisterSharing(this);
}
+ resetStates(false);
} finally {
lock.unlock();
- if (TRACE_SWITCH) {
- System.err.println(getThreadName() + ": GLContextImpl.destroy.X: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
- ", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
+ if ( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() + ": GLContextImpl.destroy.X: "+getTraceSwitchMsg());
}
}
} finally {
drawable.unlockSurface();
}
- if(null != drawableContextRealizedException) {
- throw new GLException("GLContext.destroy() during GLDrawableImpl.contextRealized(this, false)", drawableContextRealizedException);
+ if( null != associateDrawableException ) {
+ throw new GLException("Exception @ destroy's associateDrawable(false)", associateDrawableException);
}
+ } else {
+ resetStates(false);
}
- resetStates();
}
protected abstract void destroyImpl() throws GLException;
@Override
- public final void copy(GLContext source, int mask) throws GLException {
+ public final void copy(final GLContext source, final int mask) throws GLException {
if (source.getHandle() == 0) {
throw new GLException("Source OpenGL context has not been created");
}
@@ -382,8 +481,8 @@ public abstract class GLContextImpl extends GLContext {
throw new GLException("Destination OpenGL context has not been created");
}
- int lockRes = drawable.lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
+ final int lockRes = drawable.lockSurface();
+ if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
// this would be odd ..
throw new GLException("Surface not ready to lock");
}
@@ -436,103 +535,116 @@ public abstract class GLContextImpl extends GLContext {
* @see #destroyContextARBImpl
*/
@Override
- public int makeCurrent() throws GLException {
- boolean unlockContextAndDrawable = false;
- int res = CONTEXT_NOT_CURRENT;
+ public final int makeCurrent() throws GLException {
+ return makeCurrent(false);
+ }
+
+ protected final int makeCurrent(boolean forceDrawableAssociation) throws GLException {
+ final boolean hasDrawable = null != drawable;
+ if( TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.0]: "+getTraceSwitchMsg());
+ }
+ if( !hasDrawable ) {
+ if( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X0]: NULL Drawable - CONTEXT_NOT_CURRENT - "+getTraceSwitchMsg());
+ }
+ return CONTEXT_NOT_CURRENT;
+ }
// Note: the surface is locked within [makeCurrent .. swap .. release]
- int lockRes = drawable.lockSurface();
+ final int lockRes = drawable.lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
+ if( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X1]: Surface Not Ready - CONTEXT_NOT_CURRENT - "+getTraceSwitchMsg());
+ }
return CONTEXT_NOT_CURRENT;
}
- try {
- if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
- drawable.updateHandle();
- }
- lock.lock();
- try {
- // One context can only be current by one thread,
- // and one thread can only have one context current!
- final GLContext current = getCurrent();
- if (current != null) {
- if (current == this) {
- // Assume we don't need to make this context current again
- // For Mac OS X, however, we need to update the context to track resizes
- drawableUpdatedNotify();
- if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - keep - CONTEXT_CURRENT - "+lock);
- }
- return CONTEXT_CURRENT;
- } else {
- current.release();
- }
- }
- if (0 == drawable.getHandle()) {
+ boolean unlockResources = true; // Must be cleared if successful, otherwise finally block will release context and/or surface!
+ int res = CONTEXT_NOT_CURRENT;
+ try {
+ if ( drawable.isRealized() ) {
+ if ( 0 == drawable.getHandle() ) {
throw new GLException("drawable has invalid handle: "+drawable);
}
- res = makeCurrentWithinLock(lockRes);
- unlockContextAndDrawable = CONTEXT_NOT_CURRENT == res;
-
- /**
- * FIXME: refactor dependence on Java 2D / JOGL bridge
- if ((tracker != null) &&
- (res == CONTEXT_CURRENT_NEW)) {
- // Increase reference count of GLObjectTracker
- tracker.ref();
+ lock.lock();
+ try {
+ // One context can only be current by one thread,
+ // and one thread can only have one context current!
+ final GLContext current = getCurrent();
+ if (current != null) {
+ if (current == this) { // implicit recursive locking!
+ // Assume we don't need to make this context current again
+ // For Mac OS X, however, we need to update the context to track resizes
+ drawableUpdatedNotify();
+ unlockResources = false; // success
+ if( TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X2]: KEEP - CONTEXT_CURRENT - "+getTraceSwitchMsg());
+ }
+ return CONTEXT_CURRENT;
+ } else {
+ current.release();
+ }
}
- */
- } catch (RuntimeException e) {
- unlockContextAndDrawable = true;
- throw e;
- } finally {
- if (unlockContextAndDrawable) {
- lock.unlock();
- }
- }
- } catch (RuntimeException e) {
- unlockContextAndDrawable = true;
+ res = makeCurrentWithinLock(lockRes);
+ unlockResources = CONTEXT_NOT_CURRENT == res; // success ?
+
+ /**
+ * FIXME: refactor dependence on Java 2D / JOGL bridge
+ if ( tracker != null && res == CONTEXT_CURRENT_NEW ) {
+ // Increase reference count of GLObjectTracker
+ tracker.ref();
+ }
+ */
+ } catch (final RuntimeException e) {
+ unlockResources = true;
+ throw e;
+ } finally {
+ if (unlockResources) {
+ if( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.1]: Context lock.unlock() due to error, res "+makeCurrentResultToString(res)+", "+lock);
+ }
+ lock.unlock();
+ }
+ }
+ } /* if ( drawable.isRealized() ) */
+ } catch (final RuntimeException e) {
+ unlockResources = true;
throw e;
} finally {
- if (unlockContextAndDrawable) {
+ if (unlockResources) {
drawable.unlockSurface();
}
}
- if (res == CONTEXT_NOT_CURRENT) {
- if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_NOT_CURRENT - "+lock);
- }
- } else {
+ if (res != CONTEXT_NOT_CURRENT) { // still locked!
setCurrent(this);
if(res == CONTEXT_CURRENT_NEW) {
// check if the drawable's and the GL's GLProfile are equal
// throws an GLException if not
- getGLDrawable().getGLProfile().verifyEquality(gl.getGLProfile());
+ drawable.getGLProfile().verifyEquality(gl.getGLProfile());
glDebugHandler.init( isGL2GL3() && isGLDebugEnabled() );
if(DEBUG_GL) {
- gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) );
+ setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) );
if(glDebugHandler.isEnabled()) {
glDebugHandler.addListener(new GLDebugMessageHandler.StdErrGLDebugListener(true));
}
}
if(TRACE_GL) {
- gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) );
- }
-
- contextRealized(true);
-
- if(DEBUG || TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT_NEW - "+lock);
+ setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) );
}
- } else if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock);
+
+ forceDrawableAssociation = true;
+ }
+
+ if( forceDrawableAssociation ) {
+ associateDrawable(true);
}
contextMadeCurrent(true);
-
+
/* FIXME: refactor dependence on Java 2D / JOGL bridge
// Try cleaning up any stale server-side OpenGL objects
@@ -542,36 +654,66 @@ public abstract class GLContextImpl extends GLContext {
}
*/
}
+ if( TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X3]: SWITCH - "+makeCurrentResultToString(res)+" - stateTracker.on "+glStateTracker.isEnabled()+" - "+getTraceSwitchMsg());
+ }
return res;
}
- private final int makeCurrentWithinLock(int surfaceLockRes) throws GLException {
+ private final GLContextImpl getOtherSharedMaster() {
+ final GLContextImpl sharedMaster = (GLContextImpl) GLContextShareSet.getSharedMaster(this);
+ return this != sharedMaster ? sharedMaster : null;
+ }
+ private final int makeCurrentWithinLock(final int surfaceLockRes) throws GLException {
if (!isCreated()) {
+ if( 0 >= drawable.getSurfaceWidth() || 0 >= drawable.getSurfaceHeight() ) {
+ if ( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() + ": Create GL context REJECTED (zero surface size) for " + getClass().getName()+" - "+getTraceSwitchMsg());
+ System.err.println(drawable.toString());
+ }
+ return CONTEXT_NOT_CURRENT;
+ }
if(DEBUG_GL) {
// only impacts w/ createContextARB(..)
additionalCtxCreationFlags |= GLContext.CTX_OPTION_DEBUG ;
}
- final GLContextImpl shareWith = (GLContextImpl) GLContextShareSet.getShareContext(this);
- if (null != shareWith) {
- shareWith.getDrawableImpl().lockSurface();
- }
final boolean created;
- try {
- created = createImpl(shareWith); // may throws exception if fails!
- } finally {
- if (null != shareWith) {
- shareWith.getDrawableImpl().unlockSurface();
+ final GLContextImpl sharedMaster = getOtherSharedMaster();
+ if ( null != sharedMaster ) {
+ if ( NativeSurface.LOCK_SURFACE_NOT_READY >= sharedMaster.drawable.lockSurface() ) {
+ throw new GLException("GLContextShareSet could not lock sharedMaster surface: "+sharedMaster.drawable);
}
}
- if (DEBUG || TRACE_SWITCH) {
- if(created) {
- System.err.println(getThreadName() + ": Create GL context OK: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) + " for " + getClass().getName()+" - "+getGLVersion());
- // Thread.dumpStack();
+ try {
+ if ( null != sharedMaster ) {
+ final long sharedMasterHandle = sharedMaster.getHandle();
+ if ( 0 == sharedMasterHandle ) {
+ throw new GLException("GLContextShareSet returned an invalid sharedMaster context: "+sharedMaster);
+ }
+ created = createImpl(sharedMasterHandle); // may throws exception if fails
} else {
- System.err.println(getThreadName() + ": Create GL context FAILED obj " + toHexString(hashCode()) + ", for " + getClass().getName());
+ created = createImpl(0); // may throws exception if fails
+ }
+ if( created && hasNoDefaultVAO() ) {
+ final int[] tmp = new int[1];
+ final GL rootGL = gl.getRootGL();
+ if( rootGL.isGL2ES3() ) { // FIXME remove if ES2 == ES3 later
+ final GL2ES3 gl2es3 = rootGL.getGL2ES3();
+ gl2es3.glGenVertexArrays(1, tmp, 0);
+ defaultVAO = tmp[0];
+ gl2es3.glBindVertexArray(defaultVAO);
+ }
+ }
+ } finally {
+ if ( null != sharedMaster ) {
+ sharedMaster.drawable.unlockSurface();
}
}
+ if ( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() + ": Create GL context "+(created?"OK":"FAILED")+": For " + getClass().getName()+" - "+getGLVersion()+" - "+getTraceSwitchMsg());
+ // Thread.dumpStack();
+ }
if(!created) {
return CONTEXT_NOT_CURRENT;
}
@@ -581,28 +723,47 @@ public abstract class GLContextImpl extends GLContext {
final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice device = config.getScreen().getDevice();
- // Non ARB desktop profiles may not have been registered
+ // Non ARB desktop profiles may not have been registered
if( !GLContext.getAvailableGLVersionsSet(device) ) { // not yet set
if( 0 == ( ctxOptions & GLContext.CTX_PROFILE_ES) ) { // not ES profile
final int reqMajor;
final int reqProfile;
- if(ctxMajorVersion<3 || ctxMajorVersion==3 && ctxMinorVersion==0) {
+ if( ctxVersion.compareTo(Version300) <= 0 ) {
reqMajor = 2;
} else {
- reqMajor = ctxMajorVersion;
+ reqMajor = ctxVersion.getMajor();
}
+ final boolean isCompat;
if( 0 != ( ctxOptions & GLContext.CTX_PROFILE_CORE) ) {
reqProfile = GLContext.CTX_PROFILE_CORE;
+ isCompat = false;
} else {
reqProfile = GLContext.CTX_PROFILE_COMPAT;
+ isCompat = true;
+ }
+ GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ // Perform all required profile mappings
+ if( isCompat ) {
+ // COMPAT via non ARB
+ GLContext.mapAvailableGLVersion(device, reqMajor, GLContext.CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ if( reqMajor >= 4 ) {
+ GLContext.mapAvailableGLVersion(device, 3, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ GLContext.mapAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ }
+ if( reqMajor >= 3 ) {
+ GLContext.mapAvailableGLVersion(device, 2, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ }
+ } else {
+ // CORE via non ARB, unlikely, however ..
+ if( reqMajor >= 4 ) {
+ GLContext.mapAvailableGLVersion(device, 3, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ }
}
- GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
- ctxMajorVersion, ctxMinorVersion, ctxOptions);
GLContext.setAvailableGLVersionsSet(device);
-
+
if (DEBUG) {
System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion());
- }
+ }
}
}
}
@@ -615,17 +776,17 @@ public abstract class GLContextImpl extends GLContext {
protected abstract void makeCurrentImpl() throws GLException;
/**
- * @see GLDrawableImpl#contextRealized(GLContext, boolean)
- */
- protected void contextRealized(boolean realized) {
- drawable.contextRealized(this, realized);
+ * Calls {@link GLDrawableImpl#associateContext(GLContext, boolean)}
+ */
+ protected void associateDrawable(final boolean bound) {
+ drawable.associateContext(this, bound);
}
-
+
/**
- * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean)
- */
- protected void contextMadeCurrent(boolean current) {
- drawable.contextMadeCurrent(this, current);
+ * Calls {@link GLDrawableImpl#contextMadeCurrent(GLContext, boolean)}
+ */
+ protected void contextMadeCurrent(final boolean current) {
+ drawable.contextMadeCurrent(this, current);
}
/**
@@ -638,17 +799,17 @@ public abstract class GLContextImpl extends GLContext {
*
* The implementation <b>must</b> leave the context current.<br>
*
- * @param share the shared context or null
- * @return the valid and current context if successful, or null
+ * @param sharedWithHandle the shared context handle or 0
+ * @return true if successful, or false
* @throws GLException
*/
- protected abstract boolean createImpl(GLContextImpl sharedWith) throws GLException ;
+ protected abstract boolean createImpl(long sharedWithHandle) throws GLException ;
/**
* Platform dependent but harmonized implementation of the <code>ARB_create_context</code>
* mechanism to create a context.<br>
*
- * This method is called from {@link #createContextARB}, {@link #createImpl(GLContextImpl)} .. {@link #makeCurrent()} .<br>
+ * This method is called from {@link #createContextARB}, {@link #createImpl(long)} .. {@link #makeCurrent()} .<br>
*
* The implementation shall verify this context with a
* <code>MakeContextCurrent</code> call.<br>
@@ -672,8 +833,7 @@ public abstract class GLContextImpl extends GLContext {
* @see #createContextARBImpl
* @see #destroyContextARBImpl
*/
- protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags,
- int major, int minor);
+ protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags, int major, int minor);
/**
* Destroy the context created by {@link #createContextARBImpl}.
@@ -708,6 +868,9 @@ public abstract class GLContextImpl extends GLContext {
*/
protected final long createContextARB(final long share, final boolean direct)
{
+ if( GLProfile.disableOpenGLARBContext ) {
+ return 0;
+ }
final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice device = config.getScreen().getDevice();
@@ -725,24 +888,32 @@ public abstract class GLContextImpl extends GLContext {
final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
final int[] reqMajorCTP = new int[] { 0, 0 };
- getRequestMajorAndCompat(glCaps.getGLProfile(), reqMajorCTP);
-
- int _major[] = { 0 };
- int _minor[] = { 0 };
- int _ctp[] = { 0 };
+ GLContext.getRequestMajorAndCompat(glCaps.getGLProfile(), reqMajorCTP);
+
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": createContextARB: Requested "+GLContext.getGLVersion(reqMajorCTP[0], 0, reqMajorCTP[0], null));
+ }
+ final int _major[] = { 0 };
+ final int _minor[] = { 0 };
+ final int _ctp[] = { 0 };
long _ctx = 0;
if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1],
_major, _minor, _ctp)) {
_ctp[0] |= additionalCtxCreationFlags;
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": createContextARB: Mapped "+GLContext.getGLVersion(_major[0], _minor[0], _ctp[0], null));
+ }
_ctx = createContextARBImpl(share, direct, _ctp[0], _major[0], _minor[0]);
if(0!=_ctx) {
- setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0]);
+ if( !setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0], false /* strictMatch */, false /* withinGLVersionsMapping */) ) {
+ throw new InternalError("setGLFunctionAvailability !strictMatch failed");
+ }
}
}
return _ctx;
}
-
- private final boolean mapGLVersions(AbstractGraphicsDevice device) {
+
+ private final boolean mapGLVersions(final AbstractGraphicsDevice device) {
synchronized (GLContext.deviceVersionAvailable) {
final long t0 = ( DEBUG ) ? System.nanoTime() : 0;
boolean success = false;
@@ -752,62 +923,102 @@ public abstract class GLContextImpl extends GLContext {
boolean hasGL2 = false;
boolean hasGL4 = false;
boolean hasGL3 = false;
- if(!hasGL4bc) {
+
+ // Even w/ PROFILE_ALIASING, try to use true core GL profiles
+ // ensuring proper user behavior across platforms due to different feature sets!
+ //
+ if( Platform.OSType.MACOS == Platform.getOSType() &&
+ Platform.getOSVersionNumber().compareTo(Platform.OSXVersion.Mavericks) >= 0 ) {
+ /**
+ * OSX 10.9 GLRendererQuirks.GL4NeedsGL3Request, quirk is added as usual @ setRendererQuirks(..)
+ */
+ if( !GLProfile.disableOpenGLCore && !hasGL4 && !hasGL3 ) {
+ hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3
+ success |= hasGL3;
+ if( hasGL3 ) {
+ final boolean isHWAccel = 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions );
+ if( isHWAccel && ctxVersion.getMajor() >= 4 ) {
+ // Gotcha: Creating a '3.2' ctx delivers a >= 4 ctx.
+ GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ hasGL4 = true;
+ if(DEBUG) {
+ System.err.println("Quirk Triggerd: "+GLRendererQuirks.toString(GLRendererQuirks.GL4NeedsGL3Request)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber());
+ }
+ }
+ resetStates(false); // clean this context states, since creation was temporary
+ }
+ }
+ }
+ if( !GLProfile.disableOpenGLCore ) {
+ if( !hasGL4 ) {
+ hasGL4 = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE); // GL4
+ success |= hasGL4;
+ if( hasGL4 ) {
+ if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) {
+ // Map hw-accel GL4 to all lower core profiles: GL3
+ GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ if( PROFILE_ALIASING ) {
+ hasGL3 = true;
+ }
+ }
+ resetStates(false); // clean context states, since creation was temporary
+ }
+ }
+ if( !hasGL3 ) {
+ hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3
+ success |= hasGL3;
+ if( hasGL3 ) {
+ resetStates(false); // clean this context states, since creation was temporary
+ }
+ }
+ }
+ if( !hasGL4bc ) {
hasGL4bc = createContextARBMapVersionsAvailable(4, CTX_PROFILE_COMPAT); // GL4bc
success |= hasGL4bc;
- if(hasGL4bc) {
- // Map all lower compatible profiles: GL3bc, GL2, GL4, GL3
- GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions);
- GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions);
- GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions);
- GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions);
- if(PROFILE_ALIASING) {
- hasGL3bc = true;
- hasGL2 = true;
+ if( hasGL4bc ) {
+ if( !hasGL4 ) { // last chance .. ignore hw-accel
+ GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
hasGL4 = true;
+ }
+ if( !hasGL3 ) { // last chance .. ignore hw-accel
+ GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
hasGL3 = true;
}
- resetStates(); // clean this context states, since creation was temporary
+ if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) {
+ // Map hw-accel GL4bc to all lower compatible profiles: GL3bc, GL2
+ GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ if(PROFILE_ALIASING) {
+ hasGL3bc = true;
+ hasGL2 = true;
+ }
+ }
+ resetStates(false); // clean this context states, since creation was temporary
}
}
- if(!hasGL3bc) {
+ if( !hasGL3bc ) {
hasGL3bc = createContextARBMapVersionsAvailable(3, CTX_PROFILE_COMPAT); // GL3bc
success |= hasGL3bc;
- if(hasGL3bc) {
- // Map all lower compatible profiles: GL2 and GL3
- GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions);
- GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions);
- if(PROFILE_ALIASING) {
- hasGL2 = true;
+ if( hasGL3bc ) {
+ if(!hasGL3) { // last chance .. ignore hw-accel
+ GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
hasGL3 = true;
}
- resetStates(); // clean this context states, since creation was temporary
+ if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) {
+ // Map hw-accel GL3bc to all lower compatible profiles: GL2
+ GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ if(PROFILE_ALIASING) {
+ hasGL2 = true;
+ }
+ }
+ resetStates(false); // clean this context states, since creation was temporary
}
}
- if(!hasGL2) {
+ if( !hasGL2 ) {
hasGL2 = createContextARBMapVersionsAvailable(2, CTX_PROFILE_COMPAT); // GL2
success |= hasGL2;
- if(hasGL2) {
- resetStates(); // clean this context states, since creation was temporary
- }
- }
- if(!hasGL4) {
- hasGL4 = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE); // GL4
- success |= hasGL4;
- if(hasGL4) {
- // Map all lower compatible profiles: GL3
- GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions);
- if(PROFILE_ALIASING) {
- hasGL3 = true;
- }
- resetStates(); // clean this context states, since creation was temporary
- }
- }
- if(!hasGL3) {
- hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3
- success |= hasGL3;
- if(hasGL3) {
- resetStates(); // clean this context states, since creation was temporary
+ if( hasGL2 ) {
+ resetStates(false); // clean this context states, since creation was temporary
}
}
if(success) {
@@ -816,7 +1027,7 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
final long t1 = System.nanoTime();
System.err.println("GLContextImpl.mapGLVersions: "+device+", profileAliasing: "+PROFILE_ALIASING+", total "+(t1-t0)/1e6 +"ms");
- System.err.println(GLContext.dumpAvailableGLVersions(null).toString());
+ System.err.println(GLContext.dumpAvailableGLVersions(null).toString());
}
} else if (DEBUG) {
System.err.println(getThreadName() + ": createContextARB-MapVersions NONE for :"+device);
@@ -825,31 +1036,26 @@ public abstract class GLContextImpl extends GLContext {
}
}
- /**
- * Note: Since context creation is temporary, caller need to issue {@link #resetStates()}, if creation was successful, i.e. returns true.
- * This method does not reset the states, allowing the caller to utilize the state variables.
+ /**
+ * Note: Since context creation is temporary, caller need to issue {@link #resetStates(boolean)}, if creation was successful, i.e. returns true.
+ * This method does not reset the states, allowing the caller to utilize the state variables.
**/
- private final boolean createContextARBMapVersionsAvailable(int reqMajor, int reqProfile) {
+ private final boolean createContextARBMapVersionsAvailable(final int reqMajor, final int reqProfile) {
long _context;
- int ctp = CTX_IS_ARB_CREATED;
- if(CTX_PROFILE_COMPAT == reqProfile) {
- ctp |= CTX_PROFILE_COMPAT ;
- } else {
- ctp |= CTX_PROFILE_CORE ;
- }
+ int ctp = CTX_IS_ARB_CREATED | reqProfile;
// To ensure GL profile compatibility within the JOGL application
// we always try to map against the highest GL version,
// so the user can always cast to the highest available one.
int majorMax, minorMax;
int majorMin, minorMin;
- int major[] = new int[1];
- int minor[] = new int[1];
+ final int major[] = new int[1];
+ final int minor[] = new int[1];
if( 4 == reqMajor ) {
- majorMax=4; minorMax=GLContext.getMaxMinor(majorMax);
+ majorMax=4; minorMax=GLContext.getMaxMinor(ctp, majorMax);
majorMin=4; minorMin=0;
} else if( 3 == reqMajor ) {
- majorMax=3; minorMax=GLContext.getMaxMinor(majorMax);
+ majorMax=3; minorMax=GLContext.getMaxMinor(ctp, majorMax);
majorMin=3; minorMin=1;
} else /* if( glp.isGL2() ) */ {
// our minimum desktop OpenGL runtime requirements are 1.1,
@@ -862,7 +1068,7 @@ public abstract class GLContextImpl extends GLContext {
/* min */ majorMin, minorMin,
/* res */ major, minor);
- if(0==_context && CTX_PROFILE_CORE == reqProfile) {
+ if( 0 == _context && CTX_PROFILE_CORE == reqProfile && !PROFILE_ALIASING ) {
// try w/ FORWARD instead of CORE
ctp &= ~CTX_PROFILE_CORE ;
ctp |= CTX_OPTION_FORWARD ;
@@ -870,7 +1076,7 @@ public abstract class GLContextImpl extends GLContext {
/* max */ majorMax, minorMax,
/* min */ majorMin, minorMin,
/* res */ major, minor);
- if(0==_context) {
+ if( 0 == _context ) {
// Try a compatible one .. even though not requested .. last resort
ctp &= ~CTX_PROFILE_CORE ;
ctp &= ~CTX_OPTION_FORWARD ;
@@ -882,11 +1088,11 @@ public abstract class GLContextImpl extends GLContext {
}
}
final boolean res;
- if(0!=_context) {
- AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+ if( 0 != _context ) {
+ final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
// ctxMajorVersion, ctxMinorVersion, ctxOptions is being set by
// createContextARBVersions(..) -> setGLFunctionAvailbility(..) -> setContextVersion(..)
- GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxMajorVersion, ctxMinorVersion, ctxOptions);
+ GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
destroyContextARBImpl(_context);
if (DEBUG) {
System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable HAVE: " +reqMajor+"."+reqProfile+ " -> "+getGLVersion());
@@ -901,48 +1107,38 @@ public abstract class GLContextImpl extends GLContext {
return res;
}
- private final long createContextARBVersions(long share, boolean direct, int ctxOptionFlags,
- int majorMax, int minorMax,
- int majorMin, int minorMin,
- int major[], int minor[]) {
+ private final long createContextARBVersions(final long share, final boolean direct, final int ctxOptionFlags,
+ final int majorMax, final int minorMax,
+ final int majorMin, final int minorMin,
+ final int major[], final int minor[]) {
major[0]=majorMax;
minor[0]=minorMax;
long _context=0;
- boolean ok = false;
+ int i=0;
- while ( !ok &&
- GLContext.isValidGLVersion(major[0], minor[0]) &&
- ( major[0]>majorMin || major[0]==majorMin && minor[0] >=minorMin ) ) {
+ do {
if (DEBUG) {
- System.err.println(getThreadName() + ": createContextARBVersions: share "+share+", direct "+direct+", version "+major[0]+"."+minor[0]);
+ i++;
+ System.err.println(getThreadName() + ": createContextARBVersions."+i+": share "+share+", direct "+direct+
+ ", version "+major[0]+"."+minor[0]+", major["+majorMin+".."+majorMax+"], minor["+minorMin+".."+minorMax+"]");
}
_context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]);
if(0 != _context) {
- ok = true;
- setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags);
- } else {
- ok = false;
- }
-
- if(ok && major[0]>=3) {
- int[] hasMajor = new int[1]; int[] hasMinor = new int[1];
- gl.glGetIntegerv(GL2GL3.GL_MAJOR_VERSION, hasMajor, 0);
- gl.glGetIntegerv(GL2GL3.GL_MINOR_VERSION, hasMinor, 0);
- ok = hasMajor[0]>major[0] || ( hasMajor[0]==major[0] && hasMinor[0]>=minor[0] ) ;
- if(!ok) {
- removeCachedVersion(major[0], minor[0], ctxOptionFlags);
+ if( setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags, true /* strictMatch */, true /* withinGLVersionsMapping */) ) {
+ break;
+ } else {
destroyContextARBImpl(_context);
_context = 0;
}
- if (DEBUG) {
- System.err.println(getThreadName() + ": createContextARBVersions: version verification - expected "+major[0]+"."+minor[0]+", has "+hasMajor[0]+"."+hasMinor[0]+" == "+ok);
- }
}
- if(!ok) {
- if(!GLContext.decrementGLVersion(major, minor)) break;
- }
+ } while ( ( major[0]>majorMin || major[0]==majorMin && minor[0] >minorMin ) && // #1 check whether version is above lower limit
+ GLContext.decrementGLVersion(ctxOptionFlags, major, minor) // #2 decrement version
+ );
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": createContextARBVersions.X: ctx "+toHexString(_context)+", share "+share+", direct "+direct+
+ ", version "+major[0]+"."+minor[0]+", major["+majorMin+".."+majorMax+"], minor["+minorMin+".."+minorMax+"]");
}
return _context;
}
@@ -956,58 +1152,46 @@ public abstract class GLContextImpl extends GLContext {
* If major > 0 || minor > 0 : Use passed values, determined at creation time
* Otherwise .. don't touch ..
*/
- private final void setContextVersion(int major, int minor, int ctp, boolean setVersionString) {
+ private final void setContextVersion(final int major, final int minor, final int ctp, final VersionNumberString glVendorVersion, final boolean useGL) {
if ( 0 == ctp ) {
throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp));
}
-
- if (!GLContext.isValidGLVersion(major, minor)) {
- throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp));
- }
- ctxMajorVersion = major;
- ctxMinorVersion = minor;
+ ctxVersion = new VersionNumber(major, minor, 0);
+ ctxVersionString = getGLVersion(major, minor, ctp, glVersion);
+ ctxVendorVersion = glVendorVersion;
ctxOptions = ctp;
- if(setVersionString) {
- ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, getGL().glGetString(GL.GL_VERSION));
- }
- }
-
- private static final VersionNumber getGLVersionNumber(int ctp, String glVersionStr) {
- if( null != glVersionStr ) {
- final GLVersionNumber version = new GLVersionNumber(glVersionStr);
- if (version.isValid()) {
- int major = version.getMajor();
- int minor = version.getMinor();
- // We cannot promote a non ARB context to >= 3.1,
- // reduce it to 3.0 then.
- if ( 0 == (ctp & CTX_IS_ARB_CREATED) &&
- ( major > 3 || major == 3 && minor >= 1 ) ) {
- major = 3;
- minor = 0;
+ if(useGL) {
+ ctxGLSLVersion = VersionNumber.zeroVersion;
+ if( hasGLSL() ) { // >= ES2 || GL2.0
+ final String glslVersion = isGLES() ? null : gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) ; // Use static GLSL version for ES to be safe!
+ if( null != glslVersion ) {
+ ctxGLSLVersion = new VersionNumber(glslVersion);
+ if( ctxGLSLVersion.getMajor() < 1 ) {
+ ctxGLSLVersion = VersionNumber.zeroVersion; // failed ..
+ }
}
- if ( GLContext.isValidGLVersion(major, minor) ) {
- return new VersionNumber(major, minor, 0);
+ if( ctxGLSLVersion.isZero() ) {
+ ctxGLSLVersion = getStaticGLSLVersionNumber(major, minor, ctxOptions);
}
}
}
- return null;
}
//----------------------------------------------------------------------
// Helpers for various context implementations
//
- private Object createInstance(GLProfile glp, String suffix, Class<?>[] cstrArgTypes, Object[] cstrArgs) {
- return ReflectionUtil.createInstance(glp.getGLImplBaseClassName()+suffix, cstrArgTypes, cstrArgs, getClass().getClassLoader());
+ private Object createInstance(final GLProfile glp, final boolean glObject, final Object[] cstrArgs) {
+ return ReflectionUtil.createInstance(glp.getGLCtor(glObject), cstrArgs);
}
- private boolean verifyInstance(GLProfile glp, String suffix, Object instance) {
- return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix);
+ private boolean verifyInstance(final GLProfile glp, final String suffix, final Object instance) {
+ return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix);
}
/** Create the GL for this context. */
- protected GL createGL(GLProfile glp) {
- final GL gl = (GL) createInstance(glp, "Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { glp, this } );
+ protected GL createGL(final GLProfile glp) {
+ final GL gl = (GL) createInstance(glp, true, new Object[] { glp, this } );
/* FIXME: refactor dependence on Java 2D / JOGL bridge
if (tracker != null) {
@@ -1017,6 +1201,27 @@ public abstract class GLContextImpl extends GLContext {
return gl;
}
+ /**
+ * Finalizes GL instance initialization after this context has been initialized.
+ * <p>
+ * Method calls 'void finalizeInit()' of instance 'gl' as retrieved by reflection, if exist.
+ * </p>
+ */
+ private void finalizeInit(final GL gl) {
+ Method finalizeInit = null;
+ try {
+ finalizeInit = ReflectionUtil.getMethod(gl.getClass(), "finalizeInit", new Class<?>[]{ });
+ } catch ( final Throwable t ) {
+ if(DEBUG) {
+ System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ if( null != finalizeInit ) {
+ ReflectionUtil.callMethod(gl, finalizeInit, new Object[]{ });
+ }
+ }
+
public final ProcAddressTable getGLProcAddressTable() {
return glProcAddressTable;
}
@@ -1028,29 +1233,29 @@ public abstract class GLContextImpl extends GLContext {
public abstract ProcAddressTable getPlatformExtProcAddressTable();
/**
- * Pbuffer support; given that this is a GLContext associated with a
- * pbuffer, binds this pbuffer to its texture target.
- * @throws GLException if not implemented (default)
- * @deprecated use FBO/GLOffscreenAutoDrawable instead of pbuffer
+ * Part of <code>GL_NV_vertex_array_range</code>.
+ * <p>
+ * Provides platform-independent access to the <code>wglAllocateMemoryNV</code> /
+ * <code>glXAllocateMemoryNV</code>.
+ * </p>
*/
- public void bindPbufferToTexture() { throw new GLException("not implemented"); }
+ public abstract ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, float priority);
/**
- * Pbuffer support; given that this is a GLContext associated with a
- * pbuffer, releases this pbuffer from its texture target.
- * @throws GLException if not implemented (default)
- * @deprecated use FBO/GLOffscreenAutoDrawable instead of pbuffer
+ * Part of <code>GL_NV_vertex_array_range</code>.
+ * <p>
+ * Provides platform-independent access to the <code>wglFreeMemoryNV</code> /
+ * <code>glXFreeMemoryNV</code>.
+ * </p>
*/
- public void releasePbufferFromTexture() { throw new GLException("not implemented"); }
-
- public abstract ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3);
+ public abstract void glFreeMemoryNV(ByteBuffer pointer);
/** Maps the given "platform-independent" function name to a real function
name. Currently this is only used to map "glAllocateMemoryNV" and
associated routines to wglAllocateMemoryNV / glXAllocateMemoryNV. */
- protected final String mapToRealGLFunctionName(String glFunctionName) {
- Map<String, String> map = getFunctionNameMap();
- String lookup = ( null != map ) ? map.get(glFunctionName) : null;
+ protected final String mapToRealGLFunctionName(final String glFunctionName) {
+ final Map<String, String> map = getFunctionNameMap();
+ final String lookup = ( null != map ) ? map.get(glFunctionName) : null;
if (lookup != null) {
return lookup;
}
@@ -1063,9 +1268,9 @@ public abstract class GLContextImpl extends GLContext {
"GL_ARB_pbuffer" to "WGL_ARB_pbuffer/GLX_SGIX_pbuffer" and
"GL_ARB_pixel_format" to "WGL_ARB_pixel_format/n.a."
*/
- protected final String mapToRealGLExtensionName(String glExtensionName) {
- Map<String, String> map = getExtensionNameMap();
- String lookup = ( null != map ) ? map.get(glExtensionName) : null;
+ protected final String mapToRealGLExtensionName(final String glExtensionName) {
+ final Map<String, String> map = getExtensionNameMap();
+ final String lookup = ( null != map ) ? map.get(glExtensionName) : null;
if (lookup != null) {
return lookup;
}
@@ -1075,24 +1280,38 @@ public abstract class GLContextImpl extends GLContext {
/** Helper routine which resets a ProcAddressTable generated by the
GLEmitter by looking up anew all of its function pointers. */
- protected final void resetProcAddressTable(ProcAddressTable table) {
- table.reset(getDrawableImpl().getGLDynamicLookupHelper() );
+ protected final void resetProcAddressTable(final ProcAddressTable table) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ table.reset(getDrawableImpl().getGLDynamicLookupHelper() );
+ return null;
+ }
+ } );
}
private final boolean initGLRendererAndGLVersionStrings() {
final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper();
final long _glGetString = glDynLookupHelper.dynamicLookupFunction("glGetString");
if(0 == _glGetString) {
- // FIXME
- System.err.println("Warning: Entry point to 'glGetString' is NULL.");
+ System.err.println("Error: Entry point to 'glGetString' is NULL.");
if(DEBUG) {
Thread.dumpStack();
}
return false;
} else {
+ final String _glVendor = glGetStringInt(GL.GL_VENDOR, _glGetString);
+ if(null == _glVendor) {
+ if(DEBUG) {
+ System.err.println("Warning: GL_VENDOR is NULL.");
+ Thread.dumpStack();
+ }
+ return false;
+ }
+ glVendor = _glVendor;
+
final String _glRenderer = glGetStringInt(GL.GL_RENDERER, _glGetString);
if(null == _glRenderer) {
- // FIXME
if(DEBUG) {
System.err.println("Warning: GL_RENDERER is NULL.");
Thread.dumpStack();
@@ -1101,7 +1320,7 @@ public abstract class GLContextImpl extends GLContext {
}
glRenderer = _glRenderer;
glRendererLowerCase = glRenderer.toLowerCase();
-
+
final String _glVersion = glGetStringInt(GL.GL_VERSION, _glGetString);
if(null == _glVersion) {
// FIXME
@@ -1112,24 +1331,67 @@ public abstract class GLContextImpl extends GLContext {
return false;
}
glVersion = _glVersion;
+
return true;
}
}
- protected final String getGLVersionString() {
- return glVersion;
+ /**
+ * Returns null if version string is invalid, otherwise a valid instance.
+ * <p>
+ * Note: Non ARB ctx is limited to GL 3.0.
+ * </p>
+ */
+ private static final VersionNumber getGLVersionNumber(final int ctp, final String glVersionStr) {
+ if( null != glVersionStr ) {
+ final GLVersionNumber version = GLVersionNumber.create(glVersionStr);
+ if ( version.isValid() ) {
+ final int[] major = new int[] { version.getMajor() };
+ final int[] minor = new int[] { version.getMinor() };
+ if ( GLContext.isValidGLVersion(ctp, major[0], minor[0]) ) {
+ return new VersionNumber(major[0], minor[0], 0);
+ }
+ }
+ }
+ return null;
}
- protected final String getGLRendererString(boolean lowerCase) {
- return lowerCase ? glRendererLowerCase : glRenderer;
+
+ /**
+ * Returns false if <code>glGetIntegerv</code> is inaccessible, otherwise queries major.minor
+ * version for given arrays.
+ * <p>
+ * If the GL query fails, major will be zero.
+ * </p>
+ */
+ private final boolean getGLIntVersion(final int[] glIntMajor, final int[] glIntMinor) {
+ glIntMajor[0] = 0; // clear
+ final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper();
+ final long _glGetIntegerv = glDynLookupHelper.dynamicLookupFunction("glGetIntegerv");
+ if( 0 == _glGetIntegerv ) {
+ System.err.println("Error: Entry point to 'glGetIntegerv' is NULL.");
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ return false;
+ } else {
+ glGetIntegervInt(GL2ES3.GL_MAJOR_VERSION, glIntMajor, 0, _glGetIntegerv);
+ glGetIntegervInt(GL2ES3.GL_MINOR_VERSION, glIntMinor, 0, _glGetIntegerv);
+ return true;
+ }
}
+ protected final int getCtxOptions() {
+ return ctxOptions;
+ }
+
+
/**
* Sets the OpenGL implementation class and
* the cache of which GL functions are available for calling through this
* context. See {@link #isFunctionAvailable(String)} for more information on
* the definition of "available".
* <br>
- * All ProcaddressTables are being determined, the GL version is being set
+ * All ProcaddressTables are being determined and cached, the GL version is being set
* and the extension cache is determined as well.
*
* @param force force the setting, even if is already being set.
@@ -1137,63 +1399,227 @@ public abstract class GLContextImpl extends GLContext {
* @param major OpenGL major version
* @param minor OpenGL minor version
* @param ctxProfileBits OpenGL context profile and option bits, see {@link javax.media.opengl.GLContext#CTX_OPTION_ANY}
- *
+ * @param strictMatch if <code>true</code> the ctx must
+ * <ul>
+ * <li>be greater or equal than the requested <code>major.minor</code> version, and</li>
+ * <li>match the ctxProfileBits</li>
+ * <li>match ES major versions</li>
+ * </ul>, otherwise method aborts and returns <code>false</code>.<br>
+ * if <code>false</code> no version check is performed.
+ * @param withinGLVersionsMapping if <code>true</code> GL version mapping is in process, i.e. querying avail versions.
+ * Otherwise normal user context creation.
+ * @return returns <code>true</code> if successful, otherwise <code>false</code>.<br>
+ * If <code>strictMatch</code> is <code>false</code> method shall always return <code>true</code> or throw an exception.
+ * If <code>false</code> is returned, no data has been cached or mapped, i.e. ProcAddressTable, Extensions, Version, etc.
* @see #setContextVersion
* @see javax.media.opengl.GLContext#CTX_OPTION_ANY
* @see javax.media.opengl.GLContext#CTX_PROFILE_COMPAT
* @see javax.media.opengl.GLContext#CTX_IMPL_ES2_COMPAT
*/
- protected final void setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits) {
+ protected final boolean setGLFunctionAvailability(final boolean force, int major, int minor, int ctxProfileBits,
+ final boolean strictMatch, final boolean withinGLVersionsMapping) {
if(null!=this.gl && null!=glProcAddressTable && !force) {
- return; // already done and not forced
+ return true; // already done and not forced
+ }
+
+ if ( 0 < major && !GLContext.isValidGLVersion(ctxProfileBits, major, minor) ) {
+ throw new GLException("Invalid GL Version Request "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
}
if(null==this.gl || !verifyInstance(gl.getGLProfile(), "Impl", this.gl)) {
- setGL( createGL( getGLDrawable().getGLProfile() ) );
+ setGL( createGL( drawable.getGLProfile() ) );
}
updateGLXProcAddressTable();
final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
-
+ final int reqCtxProfileBits = ctxProfileBits;
+ final VersionNumber reqGLVersion = new VersionNumber(major, minor, 0);
+ final VersionNumber hasGLVersionByString;
{
final boolean initGLRendererAndGLVersionStringsOK = initGLRendererAndGLVersionStrings();
- if(DEBUG) {
- if( !initGLRendererAndGLVersionStringsOK ) {
- System.err.println("Warning: setGLFunctionAvailability: intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
+ if( !initGLRendererAndGLVersionStringsOK ) {
+ final String errMsg = "Intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null);
+ if( strictMatch ) {
+ // query mode .. simply fail
+ if(DEBUG) {
+ System.err.println("Warning: setGLFunctionAvailability: "+errMsg);
+ }
+ return false;
} else {
- System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Given "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion));
+ // unusable GL context - non query mode - hard fail!
+ throw new GLException(errMsg);
+ }
+ } else {
+ hasGLVersionByString = getGLVersionNumber(ctxProfileBits, glVersion);
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Given "+adevice+
+ " - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)+
+ ", Number(Str) "+hasGLVersionByString);
}
}
}
- if(!isCurrentContextHardwareRasterizer()) {
- ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
+ final boolean isES = 0 != ( CTX_PROFILE_ES & ctxProfileBits );
+
+ //
+ // Validate GL version either by GL-Integer or GL-String
+ //
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Pre version verification - expected "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+", strictMatch "+strictMatch+", glVersionsMapping " +withinGLVersionsMapping);
}
-
- // Pick the version from the GL-version string,
- // if smaller _or_ given major == 0.
- final VersionNumber glVersionNumber;
+
+ final boolean versionGL3IntOK;
{
- final VersionNumber setGLVersionNumber = new VersionNumber(major, minor, 0);
- final VersionNumber strGLVersionNumber = getGLVersionNumber(ctxProfileBits, glVersion);
- if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) <= 0 || 0 == major ) ) {
- glVersionNumber = strGLVersionNumber;
- major = glVersionNumber.getMajor();
- minor = glVersionNumber.getMinor();
+ // Validate the requested version w/ the GL-version from an integer query,
+ // as supported by GL [ES] >= 3.0 implementation.
+ final VersionNumber hasGLVersionByInt;
+ {
+ final int[] glIntMajor = new int[] { 0 }, glIntMinor = new int[] { 0 };
+ final boolean getGLIntVersionOK = getGLIntVersion(glIntMajor, glIntMinor);
+ if( !getGLIntVersionOK ) {
+ final String errMsg = "Fetching GL Integer Version failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null);
+ if( strictMatch ) {
+ // query mode .. simply fail
+ if(DEBUG) {
+ System.err.println("Warning: setGLFunctionAvailability: "+errMsg);
+ }
+ return false;
+ } else {
+ // unusable GL context - non query mode - hard fail!
+ throw new GLException(errMsg);
+ }
+ }
+ hasGLVersionByInt = new VersionNumber(glIntMajor[0], glIntMinor[0], 0);
+ }
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Version verification (Int): String "+glVersion+", Number(Int) "+hasGLVersionByInt);
+ }
+
+ // Only validate integer based version if:
+ // - ctx >= 3.0 is requested _or_ string-version >= 3.0
+ // - _and_ a valid int version was fetched,
+ // otherwise cont. w/ version-string method -> 3.0 > Version || Version > MAX!
+ //
+ if ( ( major >= 3 || hasGLVersionByString.compareTo(Version300) >= 0 ) &&
+ GLContext.isValidGLVersion(ctxProfileBits, hasGLVersionByInt.getMajor(), hasGLVersionByInt.getMinor()) ) {
+ // Strict Match (GLVersionMapping):
+ // Relaxed match for versions ( !isES && major < 3 ) requests, last resort!
+ // Otherwise:
+ // - fail if hasVersion < reqVersion (desktop and ES)
+ // - fail if ES major-version mismatch:
+ // - request 1, >= 3 must be equal
+ // - request 2 must be [2..3]
+ //
+ final int hasMajor = hasGLVersionByInt.getMajor();
+ if( strictMatch &&
+ ( ( ( isES || major >= 3 ) && hasGLVersionByInt.compareTo(reqGLVersion) < 0 ) ||
+ ( isES &&
+ (
+ ( 2 == major && ( 2 > hasMajor || hasMajor > 3 ) ) || // 2 -> [2..3]
+ ( ( 1 == major || 3 <= major ) && major != hasMajor ) // 1,3,.. -> equal
+ )
+ )
+ ) ) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (Int): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+hasGLVersionByInt);
+ }
+ return false;
+ }
+ // Use returned GL version!
+ major = hasGLVersionByInt.getMajor();
+ minor = hasGLVersionByInt.getMinor();
+ versionGL3IntOK = true;
+ } else {
+ versionGL3IntOK = false;
+ }
+ }
+ final boolean versionValidated;
+
+ if( versionGL3IntOK ) {
+ versionValidated = true;
+ } else {
+ // Validate the requested version w/ the GL-version from the version string.
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Version verification (String): String "+glVersion+", Number(Str) "+hasGLVersionByString);
+ }
+
+ // Only validate if a valid string version was fetched -> MIN > Version || Version > MAX!
+ if( null != hasGLVersionByString ) {
+ // Strict Match (GLVersionMapping):
+ // Relaxed match for versions ( !isES && major < 3 ) requests, last resort!
+ // Otherwise:
+ // - fail if hasVersion < reqVersion (desktop and ES)
+ // - fail if ES major-version mismatch:
+ // - request 1, >= 3 must be equal
+ // - request 2 must be [2..3]
+ //
+ final int hasMajor = hasGLVersionByString.getMajor();
+ if( strictMatch &&
+ ( ( ( isES || major >= 3 ) && hasGLVersionByString.compareTo(reqGLVersion) < 0 ) ||
+ ( isES &&
+ (
+ ( 2 == major && ( 2 > hasMajor || hasMajor > 3 ) ) || // 2 -> [2..3]
+ ( ( 1 == major || 3 <= major ) && major != hasMajor ) // 1,3,.. -> equal
+ )
+ )
+ ) ) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (String): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+hasGLVersionByString);
+ }
+ return false;
+ }
+ if( strictMatch && !versionGL3IntOK && major >= 3 ) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL3/ES3 version Int failed, String: "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+hasGLVersionByString);
+ }
+ return false;
+ }
+ // Use returned GL version!
+ major = hasGLVersionByString.getMajor();
+ minor = hasGLVersionByString.getMinor();
+ versionValidated = true;
} else {
- glVersionNumber = setGLVersionNumber;
+ versionValidated = false;
}
}
- if ( !GLContext.isValidGLVersion(major, minor) ) {
- throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctxProfileBits)+", "+glVersion+", "+glVersionNumber);
+ if( strictMatch && !versionValidated ) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, No GL version validation possible: "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion);
+ }
+ return false;
}
- if( 2 > major ) { // there is no ES2-compat for a profile w/ major < 2
- ctxProfileBits &= ~GLContext.CTX_IMPL_ES2_COMPAT;
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Post version verification req "+
+ GLContext.getGLVersion(reqGLVersion.getMajor(), reqGLVersion.getMinor(), reqCtxProfileBits, null)+" -> has "+
+ GLContext.getGLVersion(major, minor, ctxProfileBits, null)+
+ ", strictMatch "+strictMatch+", versionValidated "+versionValidated+", versionGL3IntOK "+versionGL3IntOK);
+ }
+
+ if( major < 2 ) { // there is no ES2/3-compat for a profile w/ major < 2
+ ctxProfileBits &= ~ ( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_ES3_COMPAT ) ;
}
+
+ if(!isCurrentContextHardwareRasterizer()) {
+ ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
+ }
+
+ final VersionNumberString vendorVersion = GLVersionNumber.createVendorVersion(glVersion);
+
+ setRendererQuirks(adevice, getDrawableImpl().getFactoryImpl(),
+ reqGLVersion.getMajor(), reqGLVersion.getMinor(), reqCtxProfileBits,
+ major, minor, ctxProfileBits, vendorVersion, withinGLVersionsMapping);
+
+ if( strictMatch && glRendererQuirks.exist(GLRendererQuirks.GLNonCompliant) ) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL is not compliant: "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)+", "+glRenderer);
+ }
+ return false;
+ }
+
contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits);
if (DEBUG) {
- System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion) + ", "+glVersionNumber);
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion));
}
//
@@ -1213,8 +1639,7 @@ public abstract class GLContextImpl extends GLContext {
System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+") -> "+toHexString(table.hashCode()));
}
} else {
- glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), "ProcAddressTable",
- new Class[] { FunctionAddressResolver.class } ,
+ glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), false,
new Object[] { new GLProcAddressResolver() } );
resetProcAddressTable(getGLProcAddressTable());
synchronized(mappedContextTypeObjectLock) {
@@ -1239,7 +1664,7 @@ public abstract class GLContextImpl extends GLContext {
}
} else {
extensionAvailability = new ExtensionAvailabilityCache();
- setContextVersion(major, minor, ctxProfileBits, false); // pre-set of GL version, required for extension cache usage
+ setContextVersion(major, minor, ctxProfileBits, vendorVersion, false); // pre-set of GL version, required for extension cache usage
extensionAvailability.reset(this);
synchronized(mappedContextTypeObjectLock) {
mappedExtensionAvailabilityCache.put(contextFQN, extensionAvailability);
@@ -1248,47 +1673,394 @@ public abstract class GLContextImpl extends GLContext {
}
}
}
-
- if( ( 0 != ( CTX_PROFILE_ES & ctxProfileBits ) && major >= 2 ) || isExtensionAvailable(GLExtensions.ARB_ES2_compatibility) ) {
+
+ if( isES ) {
+ if( major >= 3 ) {
+ ctxProfileBits |= CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ;
+ ctxProfileBits |= CTX_IMPL_FBO;
+ } else if( major >= 2 ) {
+ ctxProfileBits |= CTX_IMPL_ES2_COMPAT;
+ ctxProfileBits |= CTX_IMPL_FBO;
+ }
+ } else if( ( major > 4 || major == 4 && minor >= 3 ) ||
+ ( ( major > 3 || major == 3 && minor >= 1 ) && isExtensionAvailable( GLExtensions.ARB_ES3_compatibility ) ) ) {
+ // See GLContext.isGLES3CompatibleAvailable(..)/isGLES3Compatible()
+ // Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ ctxProfileBits |= CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ;
+ ctxProfileBits |= CTX_IMPL_FBO;
+ } else if( isExtensionAvailable( GLExtensions.ARB_ES2_compatibility ) ) {
ctxProfileBits |= CTX_IMPL_ES2_COMPAT;
ctxProfileBits |= CTX_IMPL_FBO;
} else if( hasFBOImpl(major, ctxProfileBits, extensionAvailability) ) {
ctxProfileBits |= CTX_IMPL_FBO;
}
-
+
+ if( ( isES && major == 1 ) || isExtensionAvailable(GLExtensions.OES_single_precision) ) {
+ ctxProfileBits |= CTX_IMPL_FP32_COMPAT_API;
+ }
+
if(FORCE_NO_FBO_SUPPORT) {
ctxProfileBits &= ~CTX_IMPL_FBO ;
- }
-
+ }
+
//
// Set GL Version (complete w/ version string)
//
- setContextVersion(major, minor, ctxProfileBits, true);
+ setContextVersion(major, minor, ctxProfileBits, vendorVersion, true);
+
+ finalizeInit(gl);
setDefaultSwapInterval();
-
+
+ final int glErrX = gl.glGetError(); // clear GL error, maybe caused by above operations
+
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: OK "+contextFQN+" - "+GLContext.getGLVersion(ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions, null)+" - glErr "+toHexString(glErrX));
+ }
+ return true;
+ }
+
+ private final void setRendererQuirks(final AbstractGraphicsDevice adevice, final GLDrawableFactoryImpl factory,
+ final int reqMajor, final int reqMinor, final int reqCTP,
+ final int major, final int minor, final int ctp, final VersionNumberString vendorVersion,
+ final boolean withinGLVersionsMapping) {
+ final String MesaSP = "Mesa ";
+ // final String MesaRendererAMDsp = " AMD ";
+ final String MesaRendererIntelsp = "Intel(R)";
+ final boolean hwAccel = 0 == ( ctp & GLContext.CTX_IMPL_ACCEL_SOFT );
+ final boolean compatCtx = 0 != ( ctp & GLContext.CTX_PROFILE_COMPAT );
+ final boolean esCtx = 0 != ( ctp & GLContext.CTX_PROFILE_ES );
+ final boolean isX11 = NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true);
+ final boolean isWindows = Platform.getOSType() == Platform.OSType.WINDOWS;
+ final boolean isDriverMesa = glRenderer.contains(MesaSP) || glRenderer.contains("Gallium ");
+
+ final boolean isDriverATICatalyst;
+ final boolean isDriverNVIDIAGeForce;
+ final boolean isDriverIntel;
+ if( !isDriverMesa ) {
+ isDriverATICatalyst = glVendor.contains("ATI Technologies") || glRenderer.startsWith("ATI ");
+ isDriverNVIDIAGeForce = glVendor.contains("NVIDIA Corporation") || glRenderer.contains("NVIDIA ");
+ isDriverIntel = glVendor.startsWith("Intel");
+ } else {
+ isDriverATICatalyst = false;
+ isDriverNVIDIAGeForce = false;
+ isDriverIntel = false;
+ }
+
+ final GLRendererQuirks quirks = new GLRendererQuirks();
+
+ //
+ // General Quirks
+ //
+ if( esCtx ) {
+ if( 2 == reqMajor && 2 < major ) {
+ final int quirk = GLRendererQuirks.GLES3ViaEGLES2Config;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: ES req "+reqMajor+" and 2 < "+major);
+ }
+ quirks.addQuirk( quirk );
+ if( withinGLVersionsMapping ) {
+ // Thread safe due to single threaded initialization!
+ GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk);
+ } else {
+ // FIXME: Remove when moving EGL/ES to ARB ctx creation
+ synchronized(GLContextImpl.class) {
+ GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk);
+ }
+ }
+ }
+ }
+
+ //
+ // OS related quirks
+ //
+ if( Platform.getOSType() == Platform.OSType.MACOS ) {
+ //
+ // OSX
+ //
+ {
+ final int quirk = GLRendererQuirks.NoOffscreenBitmap;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+ }
+ quirks.addQuirk( quirk );
+ }
+ {
+ final int quirk = GLRendererQuirks.NeedSharedObjectSync;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+ }
+ quirks.addQuirk( quirk );
+ }
+ if( Platform.getOSVersionNumber().compareTo(Platform.OSXVersion.Mavericks) >= 0 && 3==reqMajor && 4==major ) {
+ final int quirk = GLRendererQuirks.GL4NeedsGL3Request;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", req "+reqMajor+"."+reqMinor);
+ }
+ quirks.addQuirk( quirk );
+ if( withinGLVersionsMapping ) {
+ // Thread safe due to single threaded initialization!
+ GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk);
+ }
+ }
+ if( isDriverNVIDIAGeForce ) {
+ final VersionNumber osxVersionNVFlushClean = new VersionNumber(10,7,3); // < OSX 10.7.3 w/ NV needs glFlush
+ if( Platform.getOSVersionNumber().compareTo(osxVersionNVFlushClean) < 0 ) {
+ final int quirk = GLRendererQuirks.GLFlushBeforeRelease;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", Renderer "+glRenderer);
+ }
+ quirks.addQuirk( quirk );
+ }
+ if( Platform.getOSVersionNumber().compareTo(Platform.OSXVersion.Lion) < 0 ) { // < OSX 10.7.0 w/ NV has unstable GLSL
+ final int quirk = GLRendererQuirks.GLSLNonCompliant;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", Renderer "+glRenderer);
+ }
+ quirks.addQuirk( quirk );
+ }
+ }
+ } else if( isWindows ) {
+ //
+ // WINDOWS
+ //
+ {
+ final int quirk = GLRendererQuirks.NoDoubleBufferedBitmap;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+ }
+ quirks.addQuirk( quirk );
+ }
+
+ if( isDriverATICatalyst ) {
+ final VersionNumber winXPVersionNumber = new VersionNumber ( 5, 1, 0);
+ final VersionNumber amdSafeMobilityVersion = new VersionNumber(12, 102, 3);
+
+ if ( vendorVersion.compareTo(amdSafeMobilityVersion) < 0 ) { // includes: vendorVersion.isZero()
+ final int quirk = GLRendererQuirks.NeedCurrCtx4ARBCreateContext;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", [Vendor "+glVendor+" or Renderer "+glRenderer+"], driverVersion "+vendorVersion);
+ }
+ quirks.addQuirk( quirk );
+ }
+
+ if( Platform.getOSVersionNumber().compareTo(winXPVersionNumber) <= 0 ) {
+ final int quirk = GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS-Version "+Platform.getOSType()+" "+Platform.getOSVersionNumber()+", [Vendor "+glVendor+" or Renderer "+glRenderer+"]");
+ }
+ quirks.addQuirk( quirk );
+ }
+
+ if ( vendorVersion.compareTo(VersionNumberString.zeroVersion) == 0 ) {
+ final VersionNumber glVersionNumber = new VersionNumber(glVersion);
+ if ( glVersionNumber.getSub() <= 8787 && glRenderer.equals("ATI Radeon 3100 Graphics") ) { // "old" driver -> sub-minor = vendor version
+ final int quirk = GLRendererQuirks.NoARBCreateContext;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", [Vendor "+glVendor+", Renderer "+glRenderer+" and Version "+glVersion+"]");
+ }
+ quirks.addQuirk( quirk );
+ }
+ }
+ } else if( isDriverIntel && glRenderer.equals("Intel Bear Lake B") ) {
+ final int quirk = GLRendererQuirks.NoPBufferWithAccum;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", [Vendor "+glVendor+" and Renderer "+glRenderer+"]");
+ }
+ quirks.addQuirk( quirk );
+ }
+ } else if( Platform.OSType.ANDROID == Platform.getOSType() ) {
+ //
+ // ANDROID
+ //
+ // Renderer related quirks, may also involve OS
+ if( glRenderer.contains("PowerVR") ) {
+ final int quirk = GLRendererQuirks.NoSetSwapInterval;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + ", Renderer " + glRenderer);
+ }
+ quirks.addQuirk( quirk );
+ }
+ if( glRenderer.contains("Immersion.16") ) {
+ final int quirk = GLRendererQuirks.GLSharedContextBuggy;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + ", Renderer " + glRenderer);
+ }
+ quirks.addQuirk( quirk );
+ }
+ }
+
+ //
+ // Windowing Toolkit related quirks
+ //
+ if( isX11 ) {
+ //
+ // X11
+ //
+ {
+ //
+ // Quirk: DontCloseX11Display
+ //
+ final int quirk = GLRendererQuirks.DontCloseX11Display;
+ if( glRenderer.contains(MesaSP) ) {
+ if ( glRenderer.contains("X11") && vendorVersion.compareTo(Version800) < 0 ) {
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]");
+ }
+ quirks.addQuirk( quirk );
+ }
+ } else if( isDriverATICatalyst ) {
+ {
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer);
+ }
+ quirks.addQuirk( quirk );
+ }
+ } else if( jogamp.nativewindow.x11.X11Util.getMarkAllDisplaysUnclosable() ) {
+ {
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11Util Downstream");
+ }
+ quirks.addQuirk( quirk );
+ }
+ }
+ }
+ }
+
+
+ //
+ // RENDERER related quirks
+ //
+ if( isDriverMesa ) {
+ final VersionNumber mesaSafeFBOVersion = new VersionNumber(8, 0, 0);
+ final VersionNumber mesaIntelBuggySharedCtx921 = new VersionNumber(9, 2, 1);
+
+ {
+ final int quirk = GLRendererQuirks.NoSetSwapIntervalPostRetarget;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
+ }
+ quirks.addQuirk( quirk );
+ }
+ if( hwAccel ) {
+ // hardware-acceleration
+ final int quirk = GLRendererQuirks.NoDoubleBufferedPBuffer;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
+ }
+ quirks.addQuirk( quirk );
+ } else {
+ // software
+ if( vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) { // FIXME: Is it fixed in >= 8.0.0 ?
+ final int quirk = GLRendererQuirks.BuggyColorRenderbuffer;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
+ }
+ quirks.addQuirk( quirk );
+ }
+ }
+ if (compatCtx && (major > 3 || (major == 3 && minor >= 1))) {
+ // FIXME: Apply vendor version constraints!
+ final int quirk = GLRendererQuirks.GLNonCompliant;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
+ }
+ quirks.addQuirk( quirk );
+ }
+ if( glRenderer.contains( MesaRendererIntelsp ) &&
+ vendorVersion.compareTo(mesaIntelBuggySharedCtx921) >= 0 && isX11 ) { // FIXME: When is it fixed ?
+ final int quirk = GLRendererQuirks.GLSharedContextBuggy;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 / Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
+ }
+ quirks.addQuirk( quirk );
+ }
+ if( glVendor.contains( "nouveau" )
+ // FIXME: && vendorVersion.compareTo(nouveauBuggyMSAAFixed) < 0
+ ) {
+ final int quirk = GLRendererQuirks.NoMultiSamplingBuffers;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 / Renderer " + glRenderer + " / Vendor "+glVendor);
+ }
+ quirks.addQuirk( quirk );
+ if( withinGLVersionsMapping ) {
+ // Thread safe due to single threaded initialization!
+ GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk);
+ }
+ }
+ if( isWindows && glRenderer.contains("SVGA3D") && vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) {
+ final int quirk = GLRendererQuirks.NoFullFBOSupport;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
+ }
+ quirks.addQuirk( quirk );
+ }
+ }
+
+ //
+ // Property related quirks
+ //
+ if( FORCE_NO_COLOR_RENDERBUFFER ) {
+ final int quirk = GLRendererQuirks.BuggyColorRenderbuffer;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: property");
+ }
+ quirks.addQuirk( quirk );
+ }
+ if( FORCE_MIN_FBO_SUPPORT || quirks.exist(GLRendererQuirks.BuggyColorRenderbuffer) ) {
+ final int quirk = GLRendererQuirks.NoFullFBOSupport;
+ if(DEBUG) {
+ final String causeProps = FORCE_MIN_FBO_SUPPORT ? "property, " : "";
+ final String causeQuirk = quirks.exist(GLRendererQuirks.BuggyColorRenderbuffer) ? "BuggyColorRenderbuffer" : "";
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: "+causeProps+causeQuirk);
+ }
+ quirks.addQuirk( quirk );
+ }
+
if(DEBUG) {
- System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null));
+ System.err.println("Quirks local.0: "+quirks);
+ }
+ {
+ // Merge sticky quirks, thread safe due to single threaded initialization!
+ GLRendererQuirks.pushStickyDeviceQuirks(adevice, quirks);
+
+ final AbstractGraphicsDevice factoryDefaultDevice = factory.getDefaultDevice();
+ if( !GLRendererQuirks.areSameStickyDevice(factoryDefaultDevice, adevice) ) {
+ GLRendererQuirks.pushStickyDeviceQuirks(factoryDefaultDevice, quirks);
+ }
+ if( esCtx ) {
+ final AbstractGraphicsDevice eglFactoryDefaultDevice = GLDrawableFactory.getEGLFactory().getDefaultDevice();
+ if( !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, adevice) &&
+ !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, factoryDefaultDevice) ) {
+ GLRendererQuirks.pushStickyDeviceQuirks(eglFactoryDefaultDevice, quirks);
+ }
+ }
+ }
+ glRendererQuirks = quirks;
+ if(DEBUG) {
+ System.err.println("Quirks local.X: "+glRendererQuirks);
+ System.err.println("Quirks sticky on "+adevice+": "+GLRendererQuirks.getStickyDeviceQuirks(adevice));
}
}
-
- protected static final boolean hasFBOImpl(int major, int ctp, ExtensionAvailabilityCache extCache) {
- return ( 0 != (ctp & CTX_PROFILE_ES) && major >= 2 ) || // ES >= 2.0
-
- major >= 3 || // any >= 3.0 GL ctx
-
+
+ private static final boolean hasFBOImpl(final int major, final int ctp, final ExtensionAvailabilityCache extCache) {
+ return ( 0 != (ctp & CTX_PROFILE_ES) && major >= 2 ) || // ES >= 2.0
+
+ major >= 3 || // any >= 3.0 GL ctx (core, compat and ES)
+
( null != extCache &&
-
- extCache.isExtensionAvailable(GLExtensions.ARB_ES2_compatibility) || // ES 2.0 compatible
-
- extCache.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
-
- extCache.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) || // EXT_framebuffer_object
-
- extCache.isExtensionAvailable(GLExtensions.OES_framebuffer_object) ) ; // OES_framebuffer_object excluded
- }
-
- protected final void removeCachedVersion(int major, int minor, int ctxProfileBits) {
+ (
+ extCache.isExtensionAvailable(GLExtensions.ARB_ES2_compatibility) || // ES 2.0 compatible
+
+ extCache.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
+
+ extCache.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) || // EXT_framebuffer_object
+
+ extCache.isExtensionAvailable(GLExtensions.OES_framebuffer_object) // OES_framebuffer_object
+ ) );
+ }
+
+ private final void removeCachedVersion(final int major, final int minor, int ctxProfileBits) {
if(!isCurrentContextHardwareRasterizer()) {
ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
}
@@ -1301,16 +2073,18 @@ public abstract class GLContextImpl extends GLContext {
}
synchronized(mappedContextTypeObjectLock) {
- ProcAddressTable table = mappedGLProcAddress.remove( contextFQN );
+ final ProcAddressTable table = mappedGLProcAddress.remove( contextFQN );
if(DEBUG) {
- System.err.println(getThreadName() + ": RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+table.hashCode());
+ final int hc = null != table ? table.hashCode() : 0;
+ System.err.println(getThreadName() + ": RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+toHexString(hc));
}
}
synchronized(mappedContextTypeObjectLock) {
- ExtensionAvailabilityCache eCache = mappedExtensionAvailabilityCache.remove( contextFQN );
+ final ExtensionAvailabilityCache eCache = mappedExtensionAvailabilityCache.remove( contextFQN );
if(DEBUG) {
- System.err.println(getThreadName() + ": RM GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+eCache.hashCode());
+ final int hc = null != eCache ? eCache.hashCode() : 0;
+ System.err.println(getThreadName() + ": RM GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+toHexString(hc));
}
}
}
@@ -1321,8 +2095,8 @@ public abstract class GLContextImpl extends GLContext {
if(!drawable.getChosenGLCapabilities().getHardwareAccelerated()) {
isHardwareRasterizer = false;
} else {
- isHardwareRasterizer = ! ( glRendererLowerCase.contains("software") /* Mesa3D */ ||
- glRendererLowerCase.contains("mesa x11") /* Mesa3D*/ ||
+ isHardwareRasterizer = ! ( glRendererLowerCase.contains("software") /* Mesa3D, Apple */ ||
+ glRendererLowerCase.contains("mesa x11") /* Mesa3D */ ||
glRendererLowerCase.contains("softpipe") /* Gallium */ ||
glRendererLowerCase.contains("llvmpipe") /* Gallium */
);
@@ -1338,45 +2112,42 @@ public abstract class GLContextImpl extends GLContext {
protected abstract StringBuilder getPlatformExtensionsStringImpl();
@Override
- public final boolean isFunctionAvailable(String glFunctionName) {
+ public final boolean isFunctionAvailable(final String glFunctionName) {
// Check GL 1st (cached)
if(null!=glProcAddressTable) { // null if this context wasn't not created
try {
- if(0!=glProcAddressTable.getAddressFor(glFunctionName)) {
+ if( glProcAddressTable.isFunctionAvailable( glFunctionName ) ) {
return true;
}
- } catch (Exception e) {}
+ } catch (final Exception e) {}
}
// Check platform extensions 2nd (cached) - context had to be enabled once
final ProcAddressTable pTable = getPlatformExtProcAddressTable();
if(null!=pTable) {
try {
- if(0!=pTable.getAddressFor(glFunctionName)) {
+ if( pTable.isFunctionAvailable( glFunctionName ) ) {
return true;
}
- } catch (Exception e) {}
+ } catch (final Exception e) {}
}
// dynamic function lookup at last incl name aliasing (not cached)
- DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
- String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true);
- long addr = 0;
- int variants = GLNameResolver.getFuncNamePermutationNumber(tmpBase);
- for(int i = 0; 0==addr && i < variants; i++) {
- String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i);
+ final DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
+ final String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true);
+ boolean res = false;
+ final int variants = GLNameResolver.getFuncNamePermutationNumber(tmpBase);
+ for(int i = 0; !res && i < variants; i++) {
+ final String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i);
try {
- addr = dynLookup.dynamicLookupFunction(tmp);
- } catch (Exception e) { }
- }
- if(0!=addr) {
- return true;
+ res = dynLookup.isFunctionAvailable(tmp);
+ } catch (final Exception e) { }
}
- return false;
+ return res;
}
@Override
- public boolean isExtensionAvailable(String glExtensionName) {
+ public final boolean isExtensionAvailable(final String glExtensionName) {
if(null!=extensionAvailability) {
return extensionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName));
}
@@ -1416,50 +2187,70 @@ public abstract class GLContextImpl extends GLContext {
return false;
}
- protected static String getContextFQN(AbstractGraphicsDevice device, int major, int minor, int ctxProfileBits) {
+ protected static String getContextFQN(final AbstractGraphicsDevice device, final int major, final int minor, int ctxProfileBits) {
// remove non-key values
- ctxProfileBits &= ~( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) ;
+ ctxProfileBits &= CTX_IMPL_CACHE_MASK;
return device.getUniqueID() + "-" + toHexString(composeBits(major, minor, ctxProfileBits));
}
- protected String getContextFQN() {
+ protected final String getContextFQN() {
return contextFQN;
}
- /** Indicates which floating-point pbuffer implementation is in
- use. Returns one of GLPbuffer.APPLE_FLOAT, GLPbuffer.ATI_FLOAT,
- or GLPbuffer.NV_FLOAT. */
- public int getFloatingPointMode() throws GLException {
- throw new GLException("Not supported on non-pbuffer contexts");
+ @Override
+ public int getDefaultPixelDataType() {
+ evalPixelDataType();
+ return pixelDataType;
}
- /** On some platforms the mismatch between OpenGL's coordinate
- system (origin at bottom left) and the window system's
- coordinate system (origin at top left) necessitates a vertical
- flip of pixels read from offscreen contexts. */
- public abstract boolean offscreenImageNeedsVerticalFlip();
-
- /** Only called for offscreen contexts; needed by glReadPixels */
- public abstract int getOffscreenContextPixelDataType();
-
+ @Override
+ public int getDefaultPixelDataFormat() {
+ evalPixelDataType();
+ return pixelDataFormat;
+ }
+
+ private final void evalPixelDataType() {
+ if(!pixelDataEvaluated) { // only valid while context is made current
+ boolean ok = false;
+ /* if(isGL2GL3() && 3 == components) {
+ pixelDataInternalFormat=GL.GL_RGB;
+ pixelDataFormat=GL.GL_RGB;
+ pixelDataType = GL.GL_UNSIGNED_BYTE;
+ ok = true;
+ } else */ if( isGLES2Compatible() || isExtensionAvailable(GLExtensions.OES_read_format) ) {
+ final int[] glImplColorReadVals = new int[] { 0, 0 };
+ gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
+ gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);
+ // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
+ pixelDataFormat = glImplColorReadVals[0];
+ pixelDataType = glImplColorReadVals[1];
+ ok = 0 != pixelDataFormat && 0 != pixelDataType;
+ }
+ if( !ok ) {
+ // RGBA read is safe for all GL profiles
+ // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
+ pixelDataFormat=GL.GL_RGBA;
+ pixelDataType = GL.GL_UNSIGNED_BYTE;
+ }
+ // TODO: Consider:
+ // return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
+ pixelDataEvaluated = true;
+ }
+ }
//----------------------------------------------------------------------
// Helpers for buffer object optimizations
- public void setBufferSizeTracker(GLBufferSizeTracker bufferSizeTracker) {
- this.bufferSizeTracker = bufferSizeTracker;
- }
-
- public GLBufferSizeTracker getBufferSizeTracker() {
- return bufferSizeTracker;
+ public final GLBufferObjectTracker getBufferObjectTracker() {
+ return bufferObjectTracker;
}
- public GLBufferStateTracker getBufferStateTracker() {
+ public final GLBufferStateTracker getBufferStateTracker() {
return bufferStateTracker;
}
- public GLStateTracker getGLStateTracker() {
+ public final GLStateTracker getGLStateTracker() {
return glStateTracker;
}
@@ -1468,25 +2259,51 @@ public abstract class GLContextImpl extends GLContext {
// current on the OpenGL worker thread
//
- public boolean hasWaiters() {
+ /**
+ * Returns true if the given thread is owner, otherwise false.
+ * <p>
+ * Method exists merely for code validation of {@link #isCurrent()}.
+ * </p>
+ */
+ public final boolean isOwner(final Thread thread) {
+ return lock.isOwner(thread);
+ }
+
+ /**
+ * Returns true if there are other threads waiting for this GLContext to {@link #makeCurrent()}, otherwise false.
+ * <p>
+ * Since method does not perform any synchronization, accurate result are returned if lock is hold - only.
+ * </p>
+ */
+ public final boolean hasWaiters() {
return lock.getQueueLength()>0;
}
+ /**
+ * Returns the number of hold locks. See {@link RecursiveLock#getHoldCount()} for semantics.
+ * <p>
+ * Since method does not perform any synchronization, accurate result are returned if lock is hold - only.
+ * </p>
+ */
+ public final int getLockCount() {
+ return lock.getHoldCount();
+ }
+
//---------------------------------------------------------------------------
// Special FBO hook
//
-
+
/**
* Tracks {@link GL#GL_FRAMEBUFFER}, {@link GL2GL3#GL_DRAW_FRAMEBUFFER} and {@link GL2GL3#GL_READ_FRAMEBUFFER}
* to be returned via {@link #getBoundFramebuffer(int)}.
- *
+ *
* <p>Invoked by {@link GL#glBindFramebuffer(int, int)}. </p>
- *
- * <p>Assumes valid <code>framebufferName</code> range of [0..{@link Integer#MAX_VALUE}]</p>
- *
+ *
+ * <p>Assumes valid <code>framebufferName</code> range of [0..{@link Integer#MAX_VALUE}]</p>
+ *
* <p>Does not throw an exception if <code>target</code> is unknown or <code>framebufferName</code> invalid.</p>
*/
- public final void setBoundFramebuffer(int target, int framebufferName) {
+ public final void setBoundFramebuffer(final int target, final int framebufferName) {
if(0 > framebufferName) {
return; // ignore invalid name
}
@@ -1495,33 +2312,35 @@ public abstract class GLContextImpl extends GLContext {
boundFBOTarget[0] = framebufferName; // draw
boundFBOTarget[1] = framebufferName; // read
break;
- case GL2GL3.GL_DRAW_FRAMEBUFFER:
+ case GL2ES3.GL_DRAW_FRAMEBUFFER:
boundFBOTarget[0] = framebufferName; // draw
break;
- case GL2GL3.GL_READ_FRAMEBUFFER:
+ case GL2ES3.GL_READ_FRAMEBUFFER:
boundFBOTarget[1] = framebufferName; // read
break;
default: // ignore untracked target
}
}
@Override
- public final int getBoundFramebuffer(int target) {
+ public final int getBoundFramebuffer(final int target) {
switch(target) {
case GL.GL_FRAMEBUFFER:
- case GL2GL3.GL_DRAW_FRAMEBUFFER:
+ case GL2ES3.GL_DRAW_FRAMEBUFFER:
return boundFBOTarget[0]; // draw
- case GL2GL3.GL_READ_FRAMEBUFFER:
+ case GL2ES3.GL_READ_FRAMEBUFFER:
return boundFBOTarget[1]; // read
default:
throw new InternalError("Invalid FBO target name: "+toHexString(target));
}
}
-
+
@Override
- public final int getDefaultDrawFramebuffer() { return drawable.getDefaultDrawFramebuffer(); }
+ public final int getDefaultDrawFramebuffer() { return drawable.getDefaultDrawFramebuffer(); }
@Override
public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); }
-
+ @Override
+ public final int getDefaultReadBuffer() { return drawable.getDefaultReadBuffer(gl, drawableRead != drawable); }
+
//---------------------------------------------------------------------------
// GL_ARB_debug_output, GL_AMD_debug_output helpers
//
@@ -1542,7 +2361,7 @@ public abstract class GLContextImpl extends GLContext {
}
@Override
- public final void setContextCreationFlags(int flags) {
+ public final void setContextCreationFlags(final int flags) {
if(!isCreated()) {
additionalCtxCreationFlags = flags & GLContext.CTX_OPTION_DEBUG;
}
@@ -1552,12 +2371,12 @@ public abstract class GLContextImpl extends GLContext {
public final boolean isGLDebugSynchronous() { return glDebugHandler.isSynchronous(); }
@Override
- public final void setGLDebugSynchronous(boolean synchronous) {
+ public final void setGLDebugSynchronous(final boolean synchronous) {
glDebugHandler.setSynchronous(synchronous);
}
@Override
- public final void enableGLDebugMessage(boolean enable) throws GLException {
+ public final void enableGLDebugMessage(final boolean enable) throws GLException {
if(!isCreated()) {
if(enable) {
additionalCtxCreationFlags |= GLContext.CTX_OPTION_DEBUG;
@@ -1571,43 +2390,46 @@ public abstract class GLContextImpl extends GLContext {
}
@Override
- public final void addGLDebugListener(GLDebugListener listener) {
+ public final void addGLDebugListener(final GLDebugListener listener) {
glDebugHandler.addListener(listener);
}
@Override
- public final void removeGLDebugListener(GLDebugListener listener) {
+ public final void removeGLDebugListener(final GLDebugListener listener) {
glDebugHandler.removeListener(listener);
}
@Override
- public final void glDebugMessageControl(int source, int type, int severity, int count, IntBuffer ids, boolean enabled) {
+ public final void glDebugMessageControl(final int source, final int type, final int severity, final int count, final IntBuffer ids, final boolean enabled) {
if(glDebugHandler.isExtensionARB()) {
- gl.getGL2GL3().glDebugMessageControlARB(source, type, severity, count, ids, enabled);
+ gl.getGL2GL3().glDebugMessageControl(source, type, severity, count, ids, enabled);
} else if(glDebugHandler.isExtensionAMD()) {
gl.getGL2GL3().glDebugMessageEnableAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, count, ids, enabled);
}
}
@Override
- public final void glDebugMessageControl(int source, int type, int severity, int count, int[] ids, int ids_offset, boolean enabled) {
+ public final void glDebugMessageControl(final int source, final int type, final int severity, final int count, final int[] ids, final int ids_offset, final boolean enabled) {
if(glDebugHandler.isExtensionARB()) {
- gl.getGL2GL3().glDebugMessageControlARB(source, type, severity, count, ids, ids_offset, enabled);
+ gl.getGL2GL3().glDebugMessageControl(source, type, severity, count, ids, ids_offset, enabled);
} else if(glDebugHandler.isExtensionAMD()) {
gl.getGL2GL3().glDebugMessageEnableAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, count, ids, ids_offset, enabled);
}
}
@Override
- public final void glDebugMessageInsert(int source, int type, int id, int severity, String buf) {
+ public final void glDebugMessageInsert(final int source, final int type, final int id, final int severity, final String buf) {
final int len = (null != buf) ? buf.length() : 0;
if(glDebugHandler.isExtensionARB()) {
- gl.getGL2GL3().glDebugMessageInsertARB(source, type, id, severity, len, buf);
+ gl.getGL2GL3().glDebugMessageInsert(source, type, id, severity, len, buf);
} else if(glDebugHandler.isExtensionAMD()) {
gl.getGL2GL3().glDebugMessageInsertAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, id, len, buf);
}
}
/** Internal bootstraping glGetString(GL_RENDERER) */
- protected static native String glGetStringInt(int name, long procAddress);
+ private static native String glGetStringInt(int name, long procAddress);
+
+ /** Internal bootstraping glGetIntegerv(..) for version */
+ private static native void glGetIntegervInt(int pname, int[] params, int params_offset, long procAddress);
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextShareSet.java b/src/jogl/classes/jogamp/opengl/GLContextShareSet.java
index b7acc0dff..aed611edd 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextShareSet.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextShareSet.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2011 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,18 +29,19 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package jogamp.opengl;
-import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -55,94 +56,104 @@ import javax.media.opengl.GLException;
public class GLContextShareSet {
private static final boolean DEBUG = GLContextImpl.DEBUG;
-
+
// This class is implemented using a HashMap which maps from all shared contexts
// to a share set, containing all shared contexts itself.
- private static final Map<GLContext, ShareSet> shareMap = new HashMap<GLContext, ShareSet>();
- private static final Object dummyValue = new Object();
+ private static final Map<GLContext, ShareSet> shareMap = new IdentityHashMap<GLContext, ShareSet>();
private static class ShareSet {
- private Map<GLContext, Object> allShares = new HashMap<GLContext, Object>();
- private Map<GLContext, Object> createdShares = new HashMap<GLContext, Object>();
- private Map<GLContext, Object> destroyedShares = new HashMap<GLContext, Object>();
+ private final Map<GLContext, GLContext> createdShares = new IdentityHashMap<GLContext, GLContext>();
+ private final Map<GLContext, GLContext> destroyedShares = new IdentityHashMap<GLContext, GLContext>();
- public void add(GLContext ctx) {
- if (allShares.put(ctx, dummyValue) == null) {
- if (ctx.isCreated()) {
- createdShares.put(ctx, dummyValue);
+ public final void addNew(final GLContext slave, final GLContext master) {
+ final GLContext preMaster;
+ if ( slave.isCreated() ) {
+ preMaster = createdShares.put(slave, master);
} else {
- destroyedShares.put(ctx, dummyValue);
+ preMaster= destroyedShares.put(slave, master);
+ }
+ if( null != preMaster ) {
+ throw new InternalError("State of ShareSet corrupted: Slave "+toHexString(slave.hashCode())+
+ " is not new w/ master "+toHexString(preMaster.hashCode()));
+ }
+ }
+ public final void addIfNew(final GLContext slave, final GLContext master) {
+ final GLContext preMaster = getMaster(master);
+ if( null == preMaster ) {
+ addNew(slave, master);
}
- }
+ }
+
+ public final GLContext getMaster(final GLContext ctx) {
+ final GLContext c = createdShares.get(ctx);
+ return null != c ? c : destroyedShares.get(ctx);
}
public Set<GLContext> getCreatedShares() {
return createdShares.keySet();
}
-
+
public Set<GLContext> getDestroyedShares() {
return destroyedShares.keySet();
}
-
- public GLContext getCreatedShare(GLContext ignore) {
- for (Iterator<GLContext> iter = createdShares.keySet().iterator(); iter.hasNext(); ) {
- GLContext ctx = iter.next();
- if (ctx != ignore) {
- return ctx;
- }
- }
- return null;
- }
- public void contextCreated(GLContext ctx) {
- Object res = destroyedShares.remove(ctx);
- assert res != null : "State of ShareSet corrupted; thought context " +
- ctx + " should have been in destroyed set but wasn't";
- res = createdShares.put(ctx, dummyValue);
- assert res == null : "State of ShareSet corrupted; thought context " +
- ctx + " shouldn't have been in created set but was";
+ public void contextCreated(final GLContext ctx) {
+ final GLContext ctxMaster = destroyedShares.remove(ctx);
+ if( null == ctxMaster ) {
+ throw new InternalError("State of ShareSet corrupted: Context "+toHexString(ctx.hashCode())+
+ " should have been in destroyed-set");
+ }
+ final GLContext delMaster = createdShares.put(ctx, ctxMaster);
+ if( null != delMaster ) {
+ throw new InternalError("State of ShareSet corrupted: Context "+toHexString(ctx.hashCode())+
+ " shouldn't have been in created-set");
+ }
}
- public void contextDestroyed(GLContext ctx) {
- Object res = createdShares.remove(ctx);
- assert res != null : "State of ShareSet corrupted; thought context " +
- ctx + " should have been in created set but wasn't";
- res = destroyedShares.put(ctx, dummyValue);
- assert res == null : "State of ShareSet corrupted; thought context " +
- ctx + " shouldn't have been in destroyed set but was";
+ public void contextDestroyed(final GLContext ctx) {
+ final GLContext ctxMaster = createdShares.remove(ctx);
+ if( null == ctxMaster ) {
+ throw new InternalError("State of ShareSet corrupted: Context "+toHexString(ctx.hashCode())+
+ " should have been in created-set");
+ }
+ final GLContext delMaster = destroyedShares.put(ctx, ctxMaster);
+ if( null != delMaster ) {
+ throw new InternalError("State of ShareSet corrupted: Context "+toHexString(ctx.hashCode())+
+ " shouldn't have been in destroyed-set");
+ }
}
}
- /** Indicate that contexts <code>share1</code> and
- <code>share2</code> will share textures and display lists. Both
+ /** Indicate that contexts <code>slave</code> and
+ <code>master</code> will share textures and display lists. Both
must be non-null. */
- public static synchronized void registerSharing(GLContext share1, GLContext share2) {
- if (share1 == null || share2 == null) {
- throw new IllegalArgumentException("Both share1 and share2 must be non-null");
- }
- ShareSet share = entryFor(share1);
- if (share == null) {
- share = entryFor(share2);
- }
- if (share == null) {
- share = new ShareSet();
- }
- share.add(share1);
- share.add(share2);
- addEntry(share1, share);
- addEntry(share2, share);
- if (DEBUG) {
- System.err.println("GLContextShareSet: registereSharing: 1: " +
- toHexString(share1.getHandle()) + ", 2: " + toHexString(share2.getHandle()));
- }
+ public static synchronized void registerSharing(final GLContext slave, final GLContext master) {
+ if (slave == null || master == null) {
+ throw new IllegalArgumentException("Both slave and master must be non-null");
+ }
+ ShareSet share = entryFor(slave);
+ if ( null == share ) {
+ share = entryFor(master);
+ }
+ if ( null == share ) {
+ share = new ShareSet();
+ }
+ share.addNew(slave, master);
+ share.addIfNew(master, master); // this master could have a different master shared registered earlier!
+ addEntry(slave, share);
+ addEntry(master, share);
+ if (DEBUG) {
+ System.err.println("GLContextShareSet: registereSharing: 1: " +
+ toHexString(slave.hashCode()) + ", 2: " + toHexString(master.hashCode()));
+ }
}
- public static synchronized void unregisterSharing(GLContext lastContext) {
+ public static synchronized void unregisterSharing(final GLContext lastContext) {
if (lastContext == null) {
throw new IllegalArgumentException("Last context is null");
}
- ShareSet share = entryFor(lastContext);
+ final ShareSet share = entryFor(lastContext);
if (share == null) {
throw new GLException("Last context is unknown: "+lastContext);
}
@@ -155,71 +166,100 @@ public class GLContextShareSet {
throw new GLException("Last context's share set contains no destroyed context");
}
if (DEBUG) {
- System.err.println("GLContextShareSet: unregisterSharing: " +
- toHexString(lastContext.getHandle())+", entries: "+s.size());
- }
- for(Iterator<GLContext> iter = s.iterator() ; iter.hasNext() ; ) {
- GLContext ctx = iter.next();
+ System.err.println("GLContextShareSet: unregisterSharing: " +
+ toHexString(lastContext.hashCode())+", entries: "+s.size());
+ }
+ for(final Iterator<GLContext> iter = s.iterator() ; iter.hasNext() ; ) {
+ final GLContext ctx = iter.next();
if(null == removeEntry(ctx)) {
throw new GLException("Removal of shareSet for context failed");
}
}
}
-
- private static synchronized Set<GLContext> getCreatedSharedImpl(GLContext context) {
+
+ /** Returns true if the given GLContext is shared, otherwise false. */
+ public static synchronized boolean isShared(final GLContext context) {
if (context == null) {
throw new IllegalArgumentException("context is null");
}
final ShareSet share = entryFor(context);
- if (share != null) {
- return share.getCreatedShares();
+ return share != null;
+ }
+
+ /**
+ * Returns the shared master GLContext of the given <code>context</code> if shared, otherwise return <code>null</code>.
+ * <p>
+ * Returns the given <code>context</code>, if it is a shared master.
+ * </p>
+ */
+ public static synchronized GLContext getSharedMaster(final GLContext context) {
+ final ShareSet share = entryFor(context);
+ if (share == null) {
+ return null;
}
- return null;
+ return share.getMaster(context);
}
-
- public static synchronized boolean isShared(GLContext context) {
+
+ private static synchronized Set<GLContext> getCreatedSharesImpl(final GLContext context) {
if (context == null) {
throw new IllegalArgumentException("context is null");
}
final ShareSet share = entryFor(context);
- return share != null;
- }
-
- public static synchronized boolean hasCreatedSharedLeft(GLContext context) {
- final Set<GLContext> s = getCreatedSharedImpl(context);
- return null != s && s.size()>0 ;
- }
-
- /** currently not used ..
- public static synchronized Set<GLContext> getCreatedShared(GLContext context) {
- final Set<GLContext> s = getCreatedSharedImpl(context);
- if (s == null) {
- throw new GLException("context is unknown: "+context);
+ if (share != null) {
+ return share.getCreatedShares();
}
- return s;
+ return null;
}
-
- public static synchronized Set<GLContext> getDestroyedShared(GLContext context) {
+ private static synchronized Set<GLContext> getDestroyedSharesImpl(final GLContext context) {
if (context == null) {
throw new IllegalArgumentException("context is null");
}
- ShareSet share = entryFor(context);
- if (share == null) {
- throw new GLException("context is unknown: "+context);
- }
- return share.getDestroyedShares();
- } */
-
- public static synchronized GLContext getShareContext(GLContext contextToCreate) {
- ShareSet share = entryFor(contextToCreate);
- if (share == null) {
- return null;
+ final ShareSet share = entryFor(context);
+ if (share != null) {
+ return share.getDestroyedShares();
}
- return share.getCreatedShare(contextToCreate);
+ return null;
+ }
+
+ /** Returns true if the given GLContext has shared and created GLContext left including itself, otherwise false. */
+ public static synchronized boolean hasCreatedSharedLeft(final GLContext context) {
+ final Set<GLContext> s = getCreatedSharesImpl(context);
+ return null != s && s.size() > 0;
+ }
+
+ /** Returns a new array-list of created GLContext shared with the given GLContext. */
+ public static synchronized ArrayList<GLContext> getCreatedShares(final GLContext context) {
+ final ArrayList<GLContext> otherShares = new ArrayList<GLContext>();
+ final Set<GLContext> createdShares = getCreatedSharesImpl(context);
+ if( null != createdShares ) {
+ for (final Iterator<GLContext> iter = createdShares.iterator(); iter.hasNext(); ) {
+ final GLContext ctx = iter.next();
+ if (ctx != context) {
+ otherShares.add(ctx);
+ }
+ }
+ }
+ return otherShares;
}
- public static synchronized boolean contextCreated(GLContext context) {
- ShareSet share = entryFor(context);
+ /** Returns a new array-list of destroyed GLContext shared with the given GLContext. */
+ public static synchronized ArrayList<GLContext> getDestroyedShares(final GLContext context) {
+ final ArrayList<GLContext> otherShares = new ArrayList<GLContext>();
+ final Set<GLContext> destroyedShares = getDestroyedSharesImpl(context);
+ if( null != destroyedShares ) {
+ for (final Iterator<GLContext> iter = destroyedShares.iterator(); iter.hasNext(); ) {
+ final GLContext ctx = iter.next();
+ if (ctx != context) {
+ otherShares.add(ctx);
+ }
+ }
+ }
+ return otherShares;
+ }
+
+ /** Mark the given GLContext as being created. */
+ public static synchronized boolean contextCreated(final GLContext context) {
+ final ShareSet share = entryFor(context);
if (share != null) {
share.contextCreated(context);
return true;
@@ -227,8 +267,9 @@ public class GLContextShareSet {
return false;
}
- public static synchronized boolean contextDestroyed(GLContext context) {
- ShareSet share = entryFor(context);
+ /** Mark the given GLContext as being destroyed. */
+ public static synchronized boolean contextDestroyed(final GLContext context) {
+ final ShareSet share = entryFor(context);
if (share != null) {
share.contextDestroyed(context);
return true;
@@ -236,48 +277,24 @@ public class GLContextShareSet {
return false;
}
- /** In order to avoid glGet calls for buffer object checks related
- to glVertexPointer, etc. calls as well as glMapBuffer calls, we
- need to share the same GLBufferSizeTracker object between
- contexts sharing textures and display lists. For now we keep
- this mechanism orthogonal to the GLObjectTracker to hopefully
- keep things easier to understand. (The GLObjectTracker is
- currently only needed in a fairly esoteric case, when the
- Java2D/JOGL bridge is active, but the GLBufferSizeTracker
- mechanism is now always required.) */
- public static void synchronizeBufferObjectSharing(GLContext olderContextOrNull, GLContext newContext) {
- GLContextImpl older = (GLContextImpl) olderContextOrNull;
- GLContextImpl newer = (GLContextImpl) newContext;
- GLBufferSizeTracker tracker = null;
- if (older != null) {
- tracker = older.getBufferSizeTracker();
- assert (tracker != null)
- : "registerForBufferObjectSharing was not called properly for the older context, or has a bug in it";
- }
- if (tracker == null) {
- tracker = new GLBufferSizeTracker();
- }
- newer.setBufferSizeTracker(tracker);
- }
-
//----------------------------------------------------------------------
// Internals only below this point
-
- private static ShareSet entryFor(GLContext context) {
- return (ShareSet) shareMap.get(context);
+
+ private static ShareSet entryFor(final GLContext context) {
+ return shareMap.get(context);
}
- private static void addEntry(GLContext context, ShareSet share) {
+ private static void addEntry(final GLContext context, final ShareSet share) {
if (shareMap.get(context) == null) {
shareMap.put(context, share);
}
}
- private static ShareSet removeEntry(GLContext context) {
- return (ShareSet) shareMap.remove(context);
+ private static ShareSet removeEntry(final GLContext context) {
+ return shareMap.remove(context);
}
-
- protected static String toHexString(long hex) {
+
+ private static String toHexString(final long hex) {
return "0x" + Long.toHexString(hex);
- }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
index 0000e6199..7519d568b 100644
--- a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
+++ b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
@@ -27,75 +27,78 @@
*/
package jogamp.opengl;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLDebugListener;
import javax.media.opengl.GLDebugMessage;
import javax.media.opengl.GLException;
+import jogamp.common.os.PlatformPropsImpl;
+
import com.jogamp.common.os.Platform;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.opengl.GLExtensions;
-import jogamp.opengl.gl4.GL4bcProcAddressTable;
-
/**
* The GLDebugMessageHandler, handling <i>GL_ARB_debug_output</i> or <i>GL_AMD_debug_output</i>
* debug messages.<br>
- *
+ *
* <p>An instance must be bound to the current thread's GLContext to achieve thread safety.</p>
- *
- * <p>A native callback function is registered at {@link #enable(boolean) enable(true)},
- * which forwards received messages to the added {@link GLDebugListener} directly.
+ *
+ * <p>A native callback function is registered at {@link #enable(boolean) enable(true)},
+ * which forwards received messages to the added {@link GLDebugListener} directly.
* Hence the {@link GLDebugListener#messageSent(GLDebugMessage)} implementation shall
* return as fast as possible.</p>
- *
+ *
* <p>In case no <i>GL_ARB_debug_output</i> is available, but <i>GL_AMD_debug_output</i>,
* the messages are translated to <i>ARB</i> {@link GLDebugMessage}, using {@link GLDebugMessage#translateAMDEvent(javax.media.opengl.GLContext, long, int, int, int, String)}.</p>
*/
public class GLDebugMessageHandler {
private static final boolean DEBUG = Debug.debug("GLDebugMessageHandler");
-
+
private static final int EXT_ARB = 1;
- private static final int EXT_AMD = 2;
-
+ private static final int EXT_AMD = 2;
+
static {
if ( !initIDs0() ) {
throw new NativeWindowException("Failed to initialize GLDebugMessageHandler jmethodIDs");
- }
+ }
}
-
- private final GLContextImpl ctx;
+
+ private final GLContextImpl ctx;
private final ListenerSyncedImplStub<GLDebugListener> listenerImpl;
-
+
// licefycle: init - EOL
private String extName;
private int extType;
private long glDebugMessageCallbackProcAddress;
- private boolean extAvailable;
+ private boolean extAvailable;
private boolean synchronous;
-
+
// licefycle: enable - disable/EOL
private long handle;
-
+
/**
* @param ctx the associated GLContext
* @param glDebugExtension chosen extension to use
*/
- public GLDebugMessageHandler(GLContextImpl ctx) {
+ public GLDebugMessageHandler(final GLContextImpl ctx) {
this.ctx = ctx;
- this.listenerImpl = new ListenerSyncedImplStub<GLDebugListener>();
+ this.listenerImpl = new ListenerSyncedImplStub<GLDebugListener>();
this.glDebugMessageCallbackProcAddress = 0;
this.extName = null;
this.extType = 0;
- this.extAvailable = false;
+ this.extAvailable = false;
this.handle = 0;
this.synchronous = true;
}
-
- public void init(boolean enable) {
+
+ public void init(final boolean enable) {
if(DEBUG) {
System.err.println("GLDebugMessageHandler.init("+enable+")");
}
@@ -106,20 +109,33 @@ public class GLDebugMessageHandler {
System.err.println("GLDebugMessageHandler.init("+enable+") .. n/a");
}
}
-
+
+ private final long getAddressFor(final ProcAddressTable table, final String functionName) {
+ return AccessController.doPrivileged(new PrivilegedAction<Long>() {
+ @Override
+ public Long run() {
+ try {
+ return Long.valueOf( table.getAddressFor(functionName) );
+ } catch (final IllegalArgumentException iae) {
+ return Long.valueOf(0);
+ }
+ }
+ } ).longValue();
+ }
+
public void init() {
ctx.validateCurrent();
if( isAvailable()) {
return;
}
-
+
if( !ctx.isGLDebugEnabled() ) {
if(DEBUG) {
System.err.println("GLDebugMessageHandler: GL DEBUG not set in ARB ctx options: "+ctx.getGLVersion());
}
- return;
+ return;
}
- if(Platform.OS_TYPE == Platform.OSType.WINDOWS && Platform.is32Bit()) {
+ if(PlatformPropsImpl.OS_TYPE == Platform.OSType.WINDOWS && Platform.is32Bit()) {
// Currently buggy, ie. throws an exception after leaving the native callback.
// Probably a 32bit on 64bit JVM / OpenGL-driver issue.
if(DEBUG) {
@@ -137,102 +153,102 @@ public class GLDebugMessageHandler {
if(DEBUG) {
System.err.println("GLDebugMessageHandler: Using extension: <"+extName+">");
}
-
+
if(0 == extType) {
if(DEBUG) {
System.err.println("GLDebugMessageHandler: No extension available! "+ctx.getGLVersion());
System.err.println("GL_EXTENSIONS "+ctx.getGLExtensionCount());
- System.err.println(ctx.getGLExtensionsString());
+ System.err.println(ctx.getGLExtensionsString());
}
return;
}
-
+
final ProcAddressTable procAddressTable = ctx.getGLProcAddressTable();
- if( procAddressTable instanceof GL4bcProcAddressTable) {
- final GL4bcProcAddressTable desktopProcAddressTable = (GL4bcProcAddressTable)procAddressTable;
+ if( !ctx.isGLES1() && !ctx.isGLES2() ) {
switch(extType) {
- case EXT_ARB:
- glDebugMessageCallbackProcAddress = desktopProcAddressTable._addressof_glDebugMessageCallbackARB;
+ case EXT_ARB:
+ glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallbackARB");
break;
- case EXT_AMD:
- glDebugMessageCallbackProcAddress = desktopProcAddressTable._addressof_glDebugMessageCallbackAMD;
+ case EXT_AMD:
+ glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallbackAMD");
break;
}
} else {
+ glDebugMessageCallbackProcAddress = 0;
if(DEBUG) {
- System.err.println("Non desktop context not supported");
- }
+ System.err.println("Non desktop context not supported");
+ }
}
extAvailable = 0 < extType && null != extName && 0 != glDebugMessageCallbackProcAddress;
-
+
if(DEBUG) {
System.err.println("GLDebugMessageHandler: extAvailable: "+extAvailable+", glDebugMessageCallback* : 0x"+Long.toHexString(glDebugMessageCallbackProcAddress));
}
-
+
if(!extAvailable) {
glDebugMessageCallbackProcAddress = 0;
}
-
+
handle = 0;
}
public final boolean isAvailable() { return extAvailable; }
-
+
/**
- * @return The extension implementing the GLDebugMessage feature,
- * either {@link #GL_ARB_debug_output} or {@link #GL_AMD_debug_output}.
- * If unavailable <i>null</i> is returned.
+ * @return The extension implementing the GLDebugMessage feature,
+ * either {@link #GL_ARB_debug_output} or {@link #GL_AMD_debug_output}.
+ * If unavailable <i>null</i> is returned.
*/
public final String getExtension() {
return extName;
}
-
+
public final boolean isExtensionARB() {
return extName == GLExtensions.ARB_debug_output;
}
-
+
public final boolean isExtensionAMD() {
return extName == GLExtensions.AMD_debug_output;
}
-
+
/**
- * @see javax.media.opengl.GLContext#isGLDebugSynchronous()
+ * @see javax.media.opengl.GLContext#isGLDebugSynchronous()
*/
public final boolean isSynchronous() { return synchronous; }
-
+
/**
- * @see javax.media.opengl.GLContext#setGLDebugSynchronous(boolean)
+ * @see javax.media.opengl.GLContext#setGLDebugSynchronous(boolean)
*/
- public final void setSynchronous(boolean synchronous) {
+ public final void setSynchronous(final boolean synchronous) {
this.synchronous = synchronous;
if( isEnabled() ) {
setSynchronousImpl();
}
- }
+ }
private final void setSynchronousImpl() {
if(isExtensionARB()) {
if(synchronous) {
- ctx.getGL().glEnable(GL2GL3.GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+ ctx.getGL().glEnable(GL2ES2.GL_DEBUG_OUTPUT_SYNCHRONOUS);
} else {
- ctx.getGL().glDisable(GL2GL3.GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
- }
+ ctx.getGL().glDisable(GL2ES2.GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ }
if(DEBUG) {
System.err.println("GLDebugMessageHandler: synchronous "+synchronous);
}
}
}
-
+
/**
- * @see javax.media.opengl.GLContext#enableGLDebugMessage(boolean)
+ * @see javax.media.opengl.GLContext#enableGLDebugMessage(boolean)
*/
- public final void enable(boolean enable) throws GLException {
+ public final void enable(final boolean enable) throws GLException {
ctx.validateCurrent();
if(!isAvailable()) {
return;
}
enableImpl(enable);
- }
- final void enableImpl(boolean enable) throws GLException {
+ }
+ final void enableImpl(final boolean enable) throws GLException {
if(enable) {
if(0 == handle) {
setSynchronousImpl();
@@ -245,32 +261,32 @@ public class GLDebugMessageHandler {
if(0 != handle) {
unregister0(glDebugMessageCallbackProcAddress, handle);
handle = 0;
- }
+ }
}
if(DEBUG) {
System.err.println("GLDebugMessageHandler: enable("+enable+") -> 0x" + Long.toHexString(handle));
}
}
-
+
public final boolean isEnabled() { return 0 != handle; }
- public final int listenerSize() {
- return listenerImpl.size();
+ public final int listenerSize() {
+ return listenerImpl.size();
}
-
- public final void addListener(GLDebugListener listener) {
+
+ public final void addListener(final GLDebugListener listener) {
listenerImpl.addListener(-1, listener);
}
- public final void addListener(int index, GLDebugListener listener) {
+ public final void addListener(final int index, final GLDebugListener listener) {
listenerImpl.addListener(index, listener);
}
-
- public final void removeListener(GLDebugListener listener) {
+
+ public final void removeListener(final GLDebugListener listener) {
listenerImpl.removeListener(listener);
}
-
- private final void sendMessage(GLDebugMessage msg) {
+
+ private final void sendMessage(final GLDebugMessage msg) {
synchronized(listenerImpl) {
if(DEBUG) {
System.err.println("GLDebugMessageHandler: "+msg);
@@ -281,39 +297,40 @@ public class GLDebugMessageHandler {
}
}
}
-
+
public static class StdErrGLDebugListener implements GLDebugListener {
boolean threadDump;
-
- public StdErrGLDebugListener(boolean threadDump) {
+
+ public StdErrGLDebugListener(final boolean threadDump) {
this.threadDump = threadDump;
}
- public void messageSent(GLDebugMessage event) {
+ @Override
+ public void messageSent(final GLDebugMessage event) {
System.err.println(event);
if(threadDump) {
Thread.dumpStack();
}
- }
+ }
}
-
+
//
// native -> java
//
-
- protected final void glDebugMessageARB(int source, int type, int id, int severity, String msg) {
+
+ protected final void glDebugMessageARB(final int source, final int type, final int id, final int severity, final String msg) {
final GLDebugMessage event = new GLDebugMessage(ctx, System.currentTimeMillis(), source, type, id, severity, msg);
sendMessage(event);
}
- protected final void glDebugMessageAMD(int id, int category, int severity, String msg) {
+ protected final void glDebugMessageAMD(final int id, final int category, final int severity, final String msg) {
final GLDebugMessage event = GLDebugMessage.translateAMDEvent(ctx, System.currentTimeMillis(), id, category, severity, msg);
sendMessage(event);
}
-
+
//
// java -> native
- //
-
+ //
+
private static native boolean initIDs0();
private native long register0(long glDebugMessageCallbackProcAddress, int extType);
private native void unregister0(long glDebugMessageCallbackProcAddress, long handle);
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index 4f965f620..b51f290e9 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -41,14 +41,22 @@
package jogamp.opengl;
import java.nio.Buffer;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.MutableSurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
@@ -57,12 +65,13 @@ import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLFBODrawable;
import javax.media.opengl.GLOffscreenAutoDrawable;
-import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.nativewindow.DelegatedUpstreamSurfaceHookWithSurfaceSize;
import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.GLRendererQuirks;
/** Extends GLDrawableFactory with a few methods for handling
@@ -70,29 +79,68 @@ import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
Independent Bitmaps on Windows, pixmaps on X11). Direct access to
these GLDrawables is not supplied directly to end users, though
they may be instantiated by the GLJPanel implementation. */
-@SuppressWarnings("deprecation")
public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
- protected static final boolean DEBUG = GLDrawableImpl.DEBUG;
+ protected static final boolean DEBUG = GLDrawableFactory.DEBUG; // allow package access
protected GLDrawableFactoryImpl() {
super();
}
/**
- * Returns the shared context mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()},
+ * Returns the shared resource mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()},
* either a pre-existing or newly created, or <code>null</code> if creation failed or not supported.<br>
+ * Creation of the shared resource is tried only once.
+ *
+ * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ */
+ protected final SharedResourceRunner.Resource getOrCreateSharedResource(AbstractGraphicsDevice device) {
+ try {
+ device = validateDevice(device);
+ if( null != device) {
+ return getOrCreateSharedResourceImpl( device );
+ }
+ } catch (final GLException gle) {
+ if(DEBUG) {
+ System.err.println("Caught exception on thread "+getThreadName());
+ gle.printStackTrace();
+ }
+ }
+ return null;
+ }
+ protected abstract SharedResourceRunner.Resource getOrCreateSharedResourceImpl(AbstractGraphicsDevice device);
+
+ /**
+ * Returns the shared context mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()},
+ * either a pre-existing or newly created, or <code>null</code> if creation failed or <b>not supported</b>.<br>
* Creation of the shared context is tried only once.
*
* @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
*/
- public final GLContext getOrCreateSharedContext(AbstractGraphicsDevice device) {
- device = validateDevice(device);
- if(null!=device) {
- return getOrCreateSharedContextImpl(device);
+ public final GLContext getOrCreateSharedContext(final AbstractGraphicsDevice device) {
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.getContext();
+ }
+ return null;
+ }
+
+ @Override
+ protected final boolean createSharedResourceImpl(final AbstractGraphicsDevice device) {
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.isValid();
+ }
+ return false;
+ }
+
+ @Override
+ public final GLRendererQuirks getRendererQuirks(final AbstractGraphicsDevice device) {
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.getRendererQuirks();
}
return null;
}
- protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device);
/**
* Returns the shared device mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()},
@@ -101,24 +149,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
*
* @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
*/
- protected final AbstractGraphicsDevice getOrCreateSharedDevice(AbstractGraphicsDevice device) {
- if(null==device) {
- device = getDefaultDevice();
- if(null==device) {
- throw new InternalError("no default device");
- }
- if (GLProfile.DEBUG) {
- System.err.println("Info: GLDrawableFactoryImpl.getOrCreateSharedContext: using default device : "+device);
- }
- } else if( !getIsDeviceCompatible(device) ) {
- if (GLProfile.DEBUG) {
- System.err.println("Info: GLDrawableFactoryImpl.getOrCreateSharedContext: device not compatible : "+device);
- }
- return null;
+ protected final AbstractGraphicsDevice getOrCreateSharedDevice(final AbstractGraphicsDevice device) {
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.getDevice();
}
- return getOrCreateSharedDeviceImpl(device);
+ return null;
}
- protected abstract AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device);
/**
* Returns the GLDynamicLookupHelper
@@ -131,7 +168,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
// Dispatching GLDrawable construction in respect to the NativeSurface Capabilities
//
@Override
- public GLDrawable createGLDrawable(NativeSurface target) {
+ public final GLDrawable createGLDrawable(final NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
@@ -144,17 +181,17 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
try {
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
if(null != ols) {
+ final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, this, adevice);
+
// layered surface -> Offscreen/[FBO|PBuffer]
- final boolean isPbufferAvailable = canCreateGLPbuffer(adevice) ;
- if(!isPbufferAvailable && !isFBOAvailable) {
- throw new GLException("Neither FBO nor Pbuffer is available for "+target);
+ if( !chosenCapsMod.isFBO() && !chosenCapsMod.isPBuffer() ) {
+ throw new GLException("Neither FBO nor Pbuffer is available for "+chosenCapsMod+", "+target);
}
- final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, isFBOAvailable, isPbufferAvailable);
config.setChosenCapabilities(chosenCapsMod);
ols.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer");
- System.err.println("chosenCaps: "+chosenCaps);
+ System.err.println("chosenCaps: "+chosenCaps);
System.err.println("chosenCapsMod: "+chosenCapsMod);
System.err.println("OffscreenLayerSurface: **** "+ols);
System.err.println("Target: **** "+target);
@@ -162,11 +199,10 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
}
if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
- }
- if( chosenCapsMod.isFBO() && isFBOAvailable ) {
- // target surface is already a native one
+ }
+ if( chosenCapsMod.isFBO() ) {
result = createFBODrawableImpl(target, chosenCapsMod, 0);
- } else {
+ } else {
result = createOffscreenDrawableImpl(target);
}
} else if(chosenCaps.isOnscreen()) {
@@ -187,8 +223,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
throw new IllegalArgumentException("Passed NativeSurface must implement MutableSurface for offscreen: "+target);
}
if( chosenCaps.isFBO() && isFBOAvailable ) {
- // need to hook-up a native dummy surface since source may not have
- final ProxySurface dummySurface = createDummySurfaceImpl(adevice, true, chosenCaps, null, 64, 64);
+ // need to hook-up a native dummy surface since source may not have & use minimum GLCapabilities for it w/ same profile
+ final ProxySurface dummySurface = createDummySurfaceImpl(adevice, false, new GLCapabilities(chosenCaps.getGLProfile()), (GLCapabilitiesImmutable)config.getRequestedCapabilities(), null, 64, 64);
dummySurface.setUpstreamSurfaceHook(new DelegatedUpstreamSurfaceHookWithSurfaceSize(dummySurface.getUpstreamSurfaceHook(), target));
result = createFBODrawableImpl(dummySurface, chosenCaps, 0);
} else {
@@ -215,77 +251,64 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//
// PBuffer Offscreen GLAutoDrawable construction
//
-
- @Override
- public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
@Override
- public GLPbuffer createGLPbuffer(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width,
- int height,
- GLContext shareWith) {
- if(width<=0 || height<=0) {
- throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
- }
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
- if(null == device) {
- throw new GLException("No shared device for requested: "+deviceReq);
- }
- if ( !canCreateGLPbuffer(device) ) {
- throw new GLException("Pbuffer not available with device: "+device);
- }
-
- final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
- GLDrawableImpl drawable = null;
- device.lock();
- try {
- drawable = createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser,
- new UpstreamSurfaceHookMutableSize(width, height) ) );
- if(null != drawable) {
- drawable.setRealized(true);
- }
- } finally {
- device.unlock();
- }
-
- return new GLPbufferImpl( drawable, (GLContextImpl) drawable.createContext(shareWith) );
- }
+ public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp);
//---------------------------------------------------------------------------
//
// Offscreen GLDrawable construction
//
- public final boolean canCreateFBO(AbstractGraphicsDevice deviceReq, GLProfile glp) {
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ @Override
+ public final boolean canCreateFBO(final AbstractGraphicsDevice deviceReq, final GLProfile glp) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- return GLContext.isFBOAvailable(device, glp);
+ return GLContext.isFBOAvailable(device, glp);
}
-
+
@Override
- public GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height,
- GLContext shareWith) {
- final GLDrawable drawable = createOffscreenDrawable( deviceReq, capsRequested, chooser, width, height );
- drawable.setRealized(true);
- final GLContext context = drawable.createContext(shareWith);
+ public final GLOffscreenAutoDrawable createOffscreenAutoDrawable(final AbstractGraphicsDevice deviceReq,
+ final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser,
+ final int width, final int height) {
+ final GLDrawable drawable = createOffscreenDrawable( deviceReq, capsRequested, chooser, width, height );
+ try {
+ drawable.setRealized(true);
+ } catch( final GLException gle) {
+ try {
+ drawable.setRealized(false);
+ } catch( final GLException gle2) { /* ignore */ }
+ throw gle;
+ }
if(drawable instanceof GLFBODrawableImpl) {
- return new GLOffscreenAutoDrawableImpl.FBOImpl( (GLFBODrawableImpl)drawable, context, null, null );
+ return new GLOffscreenAutoDrawableImpl.FBOImpl( (GLFBODrawableImpl)drawable, null, null, null );
}
- return new GLOffscreenAutoDrawableImpl( drawable, context, null, null);
+ return new GLOffscreenAutoDrawableImpl( drawable, null, null, null);
+ }
+
+ @Override
+ public final GLAutoDrawable createDummyAutoDrawable(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser) {
+ final GLDrawable drawable = createDummyDrawable(deviceReq, createNewDevice, capsRequested, chooser);
+ try {
+ drawable.setRealized(true);
+ } catch( final GLException gle) {
+ try {
+ drawable.setRealized(false);
+ } catch( final GLException gle2) { /* ignore */ }
+ throw gle;
+ }
+ final GLAutoDrawable sharedDrawable = new GLAutoDrawableDelegate(drawable, null, null, true /*ownDevice*/, null) { };
+ return sharedDrawable;
}
-
+
@Override
- public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height) {
+ public final GLDrawable createOffscreenDrawable(final AbstractGraphicsDevice deviceReq,
+ final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser,
+ final int width, final int height) {
if(width<=0 || height<=0) {
throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
}
@@ -293,38 +316,45 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
-
- final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested,
- GLContext.isFBOAvailable(device, capsRequested.getGLProfile()),
- canCreateGLPbuffer(device));
+
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, this, device);
if( capsChosen.isFBO() ) {
+ // Use minimum GLCapabilities for the dummy surface w/ same profile
+ final ProxySurface dummySurface = createDummySurfaceImpl(device, true, new GLCapabilities(capsChosen.getGLProfile()), capsRequested, null, width, height);
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
+ return new GLFBODrawableImpl.ResizeableImpl(this, dummyDrawable, dummySurface, capsChosen, 0);
+ }
+ return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser,
+ new UpstreamSurfaceHookMutableSize(width, height) ) );
+ }
+
+ @Override
+ public final GLDrawable createDummyDrawable(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser) {
+ final AbstractGraphicsDevice device = createNewDevice ? getOrCreateSharedDevice(deviceReq) : deviceReq;
+ if(null == device) {
+ throw new GLException("No shared device for requested: "+deviceReq+", createNewDevice "+createNewDevice);
+ }
+ if( !createNewDevice ) {
device.lock();
- try {
- final ProxySurface dummySurface = createDummySurfaceImpl(device, true, capsRequested, null, width, height);
- final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
- return new GLFBODrawableImpl.ResizeableImpl(this, dummyDrawable, dummySurface, capsChosen, 0);
- } finally {
- device.unlock();
- }
}
-
- device.lock();
try {
- return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser,
- new UpstreamSurfaceHookMutableSize(width, height) ) );
+ final ProxySurface dummySurface = createDummySurfaceImpl(device, createNewDevice, capsRequested, capsRequested, chooser, 64, 64);
+ return createOnscreenDrawableImpl(dummySurface);
} finally {
- device.unlock();
+ if( !createNewDevice ) {
+ device.unlock();
+ }
}
}
- /** Creates a platform independent FBO offscreen GLDrawable */
- protected GLFBODrawable createFBODrawableImpl(NativeSurface dummySurface, GLCapabilitiesImmutable fboCaps, int textureUnit) {
+ /** Creates a platform independent unrealized FBO offscreen GLDrawable */
+ protected final GLFBODrawable createFBODrawableImpl(final NativeSurface dummySurface, final GLCapabilitiesImmutable fboCaps, final int textureUnit) {
final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, fboCaps, textureUnit);
}
-
- /** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */
+
+ /** Creates a platform dependent unrealized offscreen pbuffer/pixmap GLDrawable instance */
protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
/**
@@ -336,15 +366,15 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* Lifecycle (destruction) of the TBD surface handle shall be handled by the caller.
* </p>
* @param device a valid platform dependent target device.
- * @param createNewDevice if <code>true</code> a new device instance is created using <code>device</code> details,
+ * @param createNewDevice if <code>true</code> a new independent device instance is created using <code>device</code> details,
* otherwise <code>device</code> instance is used as-is.
* @param capsChosen
* @param capsRequested
* @param chooser the custom chooser, may be null for default
- * @param upstreamHook surface size information and optional control of the surface's lifecycle
+ * @param upstreamHook surface size information and optional control of the surface's lifecycle
* @return the created {@link MutableSurface} instance w/o defined surface handle
*/
- protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook);
@@ -354,59 +384,60 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* it maybe on- or offscreen.
* <p>
* It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information.
- * It also allows creation of framebuffer objects which are used for rendering.
+ * It also allows creation of framebuffer objects which are used for rendering or using a shared GLContext w/o actually rendering to a usable framebuffer.
+ * </p>
+ * <p>
+ * Creates a new independent device instance using <code>deviceReq</code> details.
* </p>
* @param deviceReq which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
* @param requestedCaps
* @param chooser the custom chooser, may be null for default
- * @param width the initial width
- * @param height the initial height
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()}, not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()}, not the actual dummy surface height,
+ * The latter is platform specific and small
*
* @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}.
*/
- public ProxySurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
- int width, int height) {
+ public final ProxySurface createDummySurface(final AbstractGraphicsDevice deviceReq, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser,
+ final int width, final int height) {
final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- device.lock();
- try {
- return createDummySurfaceImpl(device, true, requestedCaps, chooser, width, height);
- } finally {
- device.unlock();
- }
+ return createDummySurfaceImpl(device, true, requestedCaps, requestedCaps, chooser, width, height);
}
-
+
/**
* A dummy surface is not visible on screen and will not be used to render directly to,
* it maybe on- or offscreen.
* <p>
* It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information.
- * It also allows creation of framebuffer objects which are used for rendering.
+ * It also allows creation of framebuffer objects which are used for rendering or using a shared GLContext w/o actually rendering to a usable framebuffer.
* </p>
* @param device a valid platform dependent target device.
* @param createNewDevice if <code>true</code> a new device instance is created using <code>device</code> details,
* otherwise <code>device</code> instance is used as-is.
+ * @param chosenCaps
* @param requestedCaps
* @param chooser the custom chooser, may be null for default
- * @param width the initial width as returned by {@link NativeSurface#getWidth()}, not the actual dummy surface width.
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()}, not the actual dummy surface width.
* The latter is platform specific and small
- * @param height the initial height as returned by {@link NativeSurface#getHeight()}, not the actual dummy surface height,
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()}, not the actual dummy surface height,
* The latter is platform specific and small
* @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}.
*/
- public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
- GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height);
+ public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height);
//---------------------------------------------------------------------------
//
// ProxySurface (Wrapped pre-existing native surface) construction
//
-
+
@Override
- public ProxySurface createProxySurface(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle,
- GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ public ProxySurface createProxySurface(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle,
+ final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) {
final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
@@ -430,7 +461,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* </p>
* @param upstream TODO
*/
- protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle,
+ protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle,
GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
//---------------------------------------------------------------------------
@@ -442,24 +473,14 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
@Override
public GLContext createExternalGLContext() {
- NativeWindowFactory.getDefaultToolkitLock().lock();
- try {
- return createExternalGLContextImpl();
- } finally {
- NativeWindowFactory.getDefaultToolkitLock().unlock();
- }
+ return createExternalGLContextImpl();
}
protected abstract GLDrawable createExternalGLDrawableImpl();
@Override
public GLDrawable createExternalGLDrawable() {
- NativeWindowFactory.getDefaultToolkitLock().lock();
- try {
- return createExternalGLDrawableImpl();
- } finally {
- NativeWindowFactory.getDefaultToolkitLock().unlock();
- }
+ return createExternalGLDrawableImpl();
}
@@ -474,21 +495,10 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* @param glProfile GLProfile to determine the factory type, ie EGLDrawableFactory,
* or one of the native GLDrawableFactory's, ie X11/GLX, Windows/WGL or MacOSX/CGL.
*/
- public static GLDrawableFactoryImpl getFactoryImpl(GLProfile glp) {
+ public static GLDrawableFactoryImpl getFactoryImpl(final GLProfile glp) {
return (GLDrawableFactoryImpl) getFactory(glp);
}
- //---------------------------------------------------------------------------
- // Support for Java2D/JOGL bridge on Mac OS X; the external
- // GLDrawable mechanism in the public API is sufficient to
- // implement this functionality on all other platforms
- //
-
- public abstract boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device);
-
- public abstract GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException;
-
//----------------------------------------------------------------------
// Gamma adjustment support
// Thanks to the LWJGL team for illustrating how to make these
@@ -526,62 +536,99 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
- /**
- * Sets the gamma, brightness, and contrast of the current main
- * display. Returns true if the settings were changed, false if
- * not. If this method returns true, the display settings will
- * automatically be reset upon JVM exit (assuming the JVM does not
- * crash); if the user wishes to change the display settings back to
- * normal ahead of time, use resetDisplayGamma(). Throws
- * IllegalArgumentException if any of the parameters were
- * out-of-bounds.
- *
- * @param gamma The gamma value, typically > 1.0 (default value is
- * 1.0)
- * @param brightness The brightness value between -1.0 and 1.0,
- * inclusive (default value is 0)
- * @param contrast The contrast, greater than 0.0 (default value is 1)
- * @throws IllegalArgumentException if any of the parameters were
- * out-of-bounds
- */
- public boolean setDisplayGamma(float gamma, float brightness, float contrast) throws IllegalArgumentException {
+ @Override
+ public synchronized final boolean setDisplayGamma(final NativeSurface surface, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException {
if ((brightness < -1.0f) || (brightness > 1.0f)) {
throw new IllegalArgumentException("Brightness must be between -1.0 and 1.0");
}
if (contrast < 0) {
throw new IllegalArgumentException("Contrast must be greater than 0.0");
}
- // FIXME: ensure gamma is > 1.0? Are smaller / negative values legal?
- int rampLength = getGammaRampLength();
- if (rampLength == 0) {
- return false;
+ if( NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface() ) {
+ return false;
}
- float[] gammaRamp = new float[rampLength];
- for (int i = 0; i < rampLength; i++) {
- float intensity = (float) i / (float) (rampLength - 1);
- // apply gamma
- float rampEntry = (float) java.lang.Math.pow(intensity, gamma);
- // apply brightness
- rampEntry += brightness;
- // apply contrast
- rampEntry = (rampEntry - 0.5f) * contrast + 0.5f;
- // Clamp entry to [0, 1]
- if (rampEntry > 1.0f)
- rampEntry = 1.0f;
- else if (rampEntry < 0.0f)
- rampEntry = 0.0f;
- gammaRamp[i] = rampEntry;
+ try {
+ // FIXME: ensure gamma is > 1.0? Are smaller / negative values legal?
+ final int rampLength = getGammaRampLength(surface);
+ if (rampLength == 0) {
+ return false;
+ }
+ final float[] gammaRamp = new float[rampLength];
+ for (int i = 0; i < rampLength; i++) {
+ final float intensity = (float) i / (float) (rampLength - 1);
+ // apply gamma
+ float rampEntry = (float) java.lang.Math.pow(intensity, gamma);
+ // apply brightness
+ rampEntry += brightness;
+ // apply contrast
+ rampEntry = (rampEntry - 0.5f) * contrast + 0.5f;
+ // Clamp entry to [0, 1]
+ if (rampEntry > 1.0f)
+ rampEntry = 1.0f;
+ else if (rampEntry < 0.0f)
+ rampEntry = 0.0f;
+ gammaRamp[i] = rampEntry;
+ }
+ final AbstractGraphicsScreen screen = surface.getGraphicsConfiguration().getScreen();
+ final DeviceScreenID deviceScreenID = new DeviceScreenID(screen.getDevice().getConnection(), screen.getIndex());
+ if( null == screen2OrigGammaRamp.get(deviceScreenID) ) {
+ screen2OrigGammaRamp.put(deviceScreenID, getGammaRamp(surface)); // cache original gamma ramp once
+ if( DEBUG ) {
+ System.err.println("DisplayGamma: Stored: "+deviceScreenID);
+ dumpGammaStore();
+ }
+ }
+ return setGammaRamp(surface, gammaRamp);
+ } finally {
+ surface.unlockSurface();
}
- registerGammaShutdownHook();
- return setGammaRamp(gammaRamp);
}
- public synchronized void resetDisplayGamma() {
- if (gammaShutdownHook == null) {
- throw new IllegalArgumentException("Should not call this unless setDisplayGamma called first");
+ @Override
+ public synchronized final void resetDisplayGamma(final NativeSurface surface) {
+ if( NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface() ) {
+ return;
+ }
+ try {
+ final AbstractGraphicsScreen screen = surface.getGraphicsConfiguration().getScreen();
+ final DeviceScreenID deviceScreenID = new DeviceScreenID(screen.getDevice().getConnection(), screen.getIndex());
+ final Buffer originalGammaRamp = screen2OrigGammaRamp.remove(deviceScreenID);
+ if( null != originalGammaRamp ) {
+ resetGammaRamp(surface, originalGammaRamp);
+ }
+ } finally {
+ surface.unlockSurface();
+ }
+ }
+
+ @Override
+ public synchronized final void resetAllDisplayGamma() {
+ resetAllDisplayGammaNoSync();
+ }
+
+ @Override
+ protected final void resetAllDisplayGammaNoSync() {
+ if( DEBUG ) {
+ System.err.println("DisplayGamma: Reset");
+ dumpGammaStore();
+ }
+ final Set<DeviceScreenID> deviceScreenIDs = screen2OrigGammaRamp.keySet();
+ for( final Iterator<DeviceScreenID> i = deviceScreenIDs.iterator(); i.hasNext(); ) {
+ final DeviceScreenID deviceScreenID = i.next();
+ final Buffer originalGammaRamp = screen2OrigGammaRamp.remove(deviceScreenID);
+ if( null != originalGammaRamp ) {
+ resetGammaRamp(deviceScreenID, originalGammaRamp);
+ }
+ }
+ }
+ private void dumpGammaStore() {
+ final Set<DeviceScreenID> deviceScreenIDs = screen2OrigGammaRamp.keySet();
+ int count = 0;
+ for( final Iterator<DeviceScreenID> i = deviceScreenIDs.iterator(); i.hasNext(); count++) {
+ final DeviceScreenID deviceScreenID = i.next();
+ final Buffer originalGammaRamp = screen2OrigGammaRamp.get(deviceScreenID);
+ System.err.printf("%4d/%4d: %s -> %s%n", count, deviceScreenIDs.size(), deviceScreenID, originalGammaRamp);
}
- resetGammaRamp(originalGammaRamp);
- unregisterGammaShutdownHook();
}
//------------------------------------------------------
@@ -589,59 +636,64 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//
/** Returns the length of the computed gamma ramp for this OS and
- hardware. Returns 0 if gamma changes are not supported. */
- protected int getGammaRampLength() {
+ hardware. Returns 0 if gamma changes are not supported.
+ * @param surface TODO*/
+ protected int getGammaRampLength(final NativeSurface surface) {
return 0;
}
/** Sets the gamma ramp for the main screen. Returns false if gamma
- ramp changes were not supported. */
- protected boolean setGammaRamp(float[] ramp) {
+ ramp changes were not supported.
+ * @param surface TODO*/
+ protected boolean setGammaRamp(final NativeSurface surface, final float[] ramp) {
return false;
}
/** Gets the current gamma ramp. This is basically an opaque value
used only on some platforms to reset the gamma ramp to its
- original settings. */
- protected Buffer getGammaRamp() {
+ original settings.
+ * @param surface TODO*/
+ protected Buffer getGammaRamp(final NativeSurface surface) {
return null;
}
/** Resets the gamma ramp, potentially using the specified Buffer as
- data to restore the original values. */
- protected void resetGammaRamp(Buffer originalGammaRamp) {
+ data to restore the original values.
+ * @param surface TODO*/
+ protected void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) {
+ }
+ protected void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) {
}
// Shutdown hook mechanism for resetting gamma
- private boolean gammaShutdownHookRegistered;
- private Thread gammaShutdownHook;
- private Buffer originalGammaRamp;
- private synchronized void registerGammaShutdownHook() {
- if (gammaShutdownHookRegistered)
- return;
- if (gammaShutdownHook == null) {
- gammaShutdownHook = new Thread(new Runnable() {
- @Override
- public void run() {
- synchronized (GLDrawableFactoryImpl.this) {
- resetGammaRamp(originalGammaRamp);
- }
+ public final class DeviceScreenID {
+ public final String deviceConnection;
+ public final int screenIdx;
+ DeviceScreenID(final String deviceConnection, final int screenIdx) {
+ this.deviceConnection = deviceConnection;
+ this.screenIdx = screenIdx;
+ }
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + deviceConnection.hashCode();
+ hash = ((hash << 5) - hash) + screenIdx;
+ return hash;
+ }
+ @Override
+ public boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if (obj instanceof DeviceScreenID) {
+ final DeviceScreenID other = (DeviceScreenID)obj;
+ return this.deviceConnection.equals(other.deviceConnection) &&
+ this.screenIdx == other.screenIdx;
}
- });
- originalGammaRamp = getGammaRamp();
- }
- Runtime.getRuntime().addShutdownHook(gammaShutdownHook);
- gammaShutdownHookRegistered = true;
- }
-
- private synchronized void unregisterGammaShutdownHook() {
- if (!gammaShutdownHookRegistered)
- return;
- if (gammaShutdownHook == null) {
- throw new InternalError("Error in gamma shutdown hook logic");
- }
- Runtime.getRuntime().removeShutdownHook(gammaShutdownHook);
- gammaShutdownHookRegistered = false;
- // Leave the original gamma ramp data alone
+ return false;
+ }
+ @Override
+ public String toString() {
+ return "DeviceScreenID[devCon "+deviceConnection+", screenIdx "+screenIdx+", hash 0x"+Integer.toHexString(hashCode())+"]";
+ }
}
+ private final Map<DeviceScreenID, Buffer> screen2OrigGammaRamp = new HashMap<DeviceScreenID, Buffer>();
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index bdf0b6d74..3847b4042 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,27 +29,29 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package jogamp.opengl;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.List;
import java.util.HashSet;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
+import javax.media.opengl.GL;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
@@ -58,24 +60,37 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLFBODrawable;
import javax.media.opengl.GLRunnable;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.common.ExceptionUtils;
+import com.jogamp.common.util.PropertyAccess;
/** Encapsulates the implementation of most of the GLAutoDrawable's
- methods to be able to share it between GLCanvas and GLJPanel. */
-
+ methods to be able to share it between GLAutoDrawable implementations like GLAutoDrawableBase, GLCanvas and GLJPanel. */
public class GLDrawableHelper {
/** true if property <code>jogl.debug.GLDrawable.PerfStats</code> is defined. */
- private static final boolean PERF_STATS = Debug.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true);
-
+ private static final boolean PERF_STATS;
+
+ static {
+ Debug.initSingleton();
+ PERF_STATS = PropertyAccess.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true);
+ }
+
protected static final boolean DEBUG = GLDrawableImpl.DEBUG;
private final Object listenersLock = new Object();
private final ArrayList<GLEventListener> listeners = new ArrayList<GLEventListener>();
private final HashSet<GLEventListener> listenersToBeInit = new HashSet<GLEventListener>();
private final Object glRunnablesLock = new Object();
- private volatile ArrayList<GLRunnableTask> glRunnables = new ArrayList<GLRunnableTask>();
+ private ArrayList<GLRunnableTask> glRunnables = new ArrayList<GLRunnableTask>();
+ private volatile int glRunnableCount = 0;
private boolean autoSwapBufferMode;
- private Thread skipContextReleaseThread;
+ private volatile Thread exclusiveContextThread;
+ /** -1 release, 0 nop, 1 claim */
+ private volatile int exclusiveContextSwitch;
private GLAnimatorControl animatorCtrl;
+ private static Runnable nop = new Runnable() { @Override public void run() {} };
+
+ private GLContext sharedContext;
+ private GLAutoDrawable sharedAutoDrawable;
+
public GLDrawableHelper() {
reset();
@@ -87,21 +102,77 @@ public class GLDrawableHelper {
listenersToBeInit.clear();
}
autoSwapBufferMode = true;
- skipContextReleaseThread = null;
+ exclusiveContextThread = null;
+ exclusiveContextSwitch = 0;
synchronized(glRunnablesLock) {
+ glRunnableCount = 0;
glRunnables.clear();
}
animatorCtrl = null;
+ sharedContext = null;
+ sharedAutoDrawable = null;
+ }
+
+ public final void setSharedContext(final GLContext thisContext, final GLContext sharedContext) throws IllegalStateException {
+ if( null == sharedContext ) {
+ throw new IllegalStateException("Null shared GLContext");
+ }
+ if( thisContext == sharedContext ) {
+ throw new IllegalStateException("Shared GLContext same as local");
+ }
+ if( null != this.sharedContext ) {
+ throw new IllegalStateException("Shared GLContext already set");
+ }
+ if( null != this.sharedAutoDrawable ) {
+ throw new IllegalStateException("Shared GLAutoDrawable already set");
+ }
+ this.sharedContext = sharedContext;
+ }
+
+ public final void setSharedAutoDrawable(final GLAutoDrawable thisAutoDrawable, final GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
+ if( null == sharedAutoDrawable ) {
+ throw new IllegalStateException("Null shared GLAutoDrawable");
+ }
+ if( thisAutoDrawable == sharedAutoDrawable ) {
+ throw new IllegalStateException("Shared GLAutoDrawable same as this");
+ }
+ if( null != this.sharedContext ) {
+ throw new IllegalStateException("Shared GLContext already set");
+ }
+ if( null != this.sharedAutoDrawable ) {
+ throw new IllegalStateException("Shared GLAutoDrawable already set");
+ }
+ this.sharedAutoDrawable = sharedAutoDrawable;
+ }
+
+ /**
+ * @param shared returns the shared GLContext, based on set shared GLAutoDrawable
+ * or GLContext. Maybe null if none is set.
+ * @return true if initialization is pending due to a set shared GLAutoDrawable or GLContext
+ * which is not ready yet. Otherwise false.
+ */
+ public boolean isSharedGLContextPending(final GLContext[] shared) {
+ final GLContext shareWith;
+ final boolean pending;
+ if ( null != sharedAutoDrawable ) {
+ shareWith = sharedAutoDrawable.getContext();
+ pending = null == shareWith || !shareWith.isCreated() || !sharedAutoDrawable.areAllGLEventListenerInitialized();
+ } else {
+ shareWith = sharedContext;
+ pending = null != shareWith && !shareWith.isCreated();
+ }
+ shared[0] = shareWith;
+ return pending;
}
@Override
public final String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("GLAnimatorControl: "+animatorCtrl+", ");
synchronized(listenersLock) {
sb.append("GLEventListeners num "+listeners.size()+" [");
for (int i=0; i < listeners.size(); i++) {
- Object l = listeners.get(i);
+ final Object l = listeners.get(i);
sb.append(l);
sb.append("[init ");
sb.append( !listenersToBeInit.contains(l) );
@@ -112,49 +183,80 @@ public class GLDrawableHelper {
return sb.toString();
}
+ /** Limit release calls of {@link #forceNativeRelease(GLContext)} to {@value}. */
+ private static final int MAX_RELEASE_ITER = 512;
+
/**
- * Associate a new context to the drawable and also propagates the context/drawable switch by
- * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
- * <p>
- * If the old or new context was current on this thread, it is being released before switching the drawable.
- * </p>
+ * Since GLContext's {@link GLContext#makeCurrent()} and {@link GLContext#release()}
+ * is recursive, a call to {@link GLContext#release()} may not natively release the context.
* <p>
- * Be aware that the old context is still bound to the drawable,
- * and that one context can only bound to one drawable at one time!
+ * This methods continues calling {@link GLContext#release()} until the context has been natively released.
* </p>
+ * @param ctx
+ */
+ public static final void forceNativeRelease(final GLContext ctx) {
+ int releaseCount = 0;
+ do {
+ ctx.release();
+ releaseCount++;
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper.forceNativeRelease() #"+releaseCount+" -- currentThread "+Thread.currentThread()+" -> "+GLContext.getCurrent());
+ }
+ } while( MAX_RELEASE_ITER > releaseCount && ctx.isCurrent() );
+
+ if( ctx.isCurrent() ) {
+ throw new GLException("Context still current after "+MAX_RELEASE_ITER+" releases: "+ctx);
+ }
+ }
+
+ /**
+ * Switch {@link GLContext} / {@link GLDrawable} association.
* <p>
- * No locking is being performed on the drawable, caller is required to take care of it.
+ * Remarks:
+ * <ul>
+ * <li>The <code>oldCtx</code> will be destroyed if <code>destroyPrevCtx</code> is <code>true</code>,
+ * otherwise disassociate <code>oldCtx</code> from <code>drawable</code>
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) oldCtx.setGLDrawable(null, true);} including {@link GL#glFinish() glFinish()}.</li>
+ * <li>Reassociate <code>newCtx</code> with <code>drawable</code>
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.</li>
+ * <li>If the old context was current on this thread, it is being released after disassociating the drawable.</li>
+ * <li>If the new context was current on this thread, it is being released before associating the drawable
+ * and made current afterwards.</li>
+ * <li>Implementation may issue {@link #makeCurrent()} and {@link #release()} while drawable reassociation.</li>
+ * <li>The user shall take extra care of thread synchronization,
+ * i.e. lock the involved {@link GLDrawable#getNativeSurface() drawable's} {@link NativeSurface}s
+ * to avoid a race condition. In case {@link GLAutoDrawable auto-drawable's} are used,
+ * their {@link GLAutoDrawable#getUpstreamLock() upstream-lock} must be locked beforehand
+ * see <a href="../../javax/media/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
+ * </ul>
* </p>
- *
+ *
* @param drawable the drawable which context is changed
- * @param oldCtx the old context
- * @param newCtx the new context
+ * @param oldCtx the old context, maybe <code>null</code>.
+ * @param destroyOldCtx if <code>true</code>, destroy the <code>oldCtx</code>
+ * @param newCtx the new context, maybe <code>null</code> for dis-association.
* @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)}
- * @return true if the new context was current, otherwise false
- *
- * @see GLAutoDrawable#setContext(GLContext)
+ *
+ * @see GLAutoDrawable#setContext(GLContext, boolean)
*/
- public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) {
- if( null != oldCtx && oldCtx.isCurrent() ) {
- oldCtx.release();
+ public static final void switchContext(final GLDrawable drawable, final GLContext oldCtx, final boolean destroyOldCtx, final GLContext newCtx, final int newCtxCreationFlags) {
+ if( null != oldCtx ) {
+ if( destroyOldCtx ) {
+ oldCtx.destroy();
+ } else {
+ oldCtx.setGLDrawable(null, true); // dis-associate old pair
+ }
}
- final boolean newCtxCurrent;
+
if(null!=newCtx) {
- newCtxCurrent = newCtx.isCurrent();
- if(newCtxCurrent) {
- newCtx.release();
- }
newCtx.setContextCreationFlags(newCtxCreationFlags);
- newCtx.setGLDrawable(drawable, true); // propagate context/drawable switch
- } else {
- newCtxCurrent = false;
+ newCtx.setGLDrawable(drawable, true); // re-associate new pair
}
- return newCtxCurrent;
}
-
+
/**
* If the drawable is not realized, OP is a NOP.
- * <ul>
+ * <ul>
* <li>release context if current</li>
* <li>destroy old drawable</li>
* <li>create new drawable</li>
@@ -162,26 +264,30 @@ public class GLDrawableHelper {
* <li>make context current, if it was current</li>
* </ul>
* <p>
- * No locking is being performed, caller is required to take care of it.
+ * Locking is performed via {@link GLContext#makeCurrent()} on the passed <code>context</code>.
* </p>
- *
+ *
* @param drawable
* @param context maybe null
* @return the new drawable
*/
- public static final GLDrawableImpl recreateGLDrawable(GLDrawableImpl drawable, GLContext context) {
+ public static final GLDrawableImpl recreateGLDrawable(GLDrawableImpl drawable, final GLContext context) {
if( ! drawable.isRealized() ) {
return drawable;
}
- final boolean contextCurrent = null != context && context.isCurrent();
+ final GLContext currentContext = GLContext.getCurrent();
final GLDrawableFactory factory = drawable.getFactory();
final NativeSurface surface = drawable.getNativeSurface();
final ProxySurface proxySurface = (surface instanceof ProxySurface) ? (ProxySurface)surface : null;
-
- if(contextCurrent) {
- context.release();
+
+ if( null != context ) {
+ // Ensure to sync GL command stream
+ if( currentContext != context ) {
+ context.makeCurrent();
+ }
+ context.setGLDrawable(null, true); // dis-associate
}
-
+
if(null != proxySurface) {
proxySurface.enableUpstreamSurfaceHookLifecycle(false);
}
@@ -196,20 +302,20 @@ public class GLDrawableHelper {
}
if(null != context) {
- context.setGLDrawable(drawable, true); // re-association
+ context.setGLDrawable(drawable, true); // re-association, implicit glFinish() ctx/drawable sync
}
-
- if(contextCurrent) {
- context.makeCurrent();
+
+ if( null != currentContext ) {
+ currentContext.makeCurrent();
}
return drawable;
}
-
+
/**
* Performs resize operation on the given drawable, assuming it is offscreen.
* <p>
* The {@link GLDrawableImpl}'s {@link NativeSurface} is being locked during operation.
- * In case the holder is an auto drawable or similar, it's lock shall be claimed by the caller.
+ * In case the holder is an auto drawable or similar, it's lock shall be claimed by the caller.
* </p>
* <p>
* May recreate the drawable via {@link #recreateGLDrawable(GLDrawableImpl, GLContext)}
@@ -219,10 +325,10 @@ public class GLDrawableHelper {
* FBO drawables are resized w/o drawable destruction.
* </p>
* <p>
- * Offscreen resize operation is validated w/ drawable size in the end.
+ * Offscreen resize operation is validated w/ drawable size in the end.
* An exception is thrown if not successful.
* </p>
- *
+ *
* @param drawable
* @param context
* @param newWidth the new width, it's minimum is capped to 1
@@ -231,34 +337,42 @@ public class GLDrawableHelper {
* @throws NativeWindowException is drawable is not offscreen or it's surface lock couldn't be claimed
* @throws GLException may be thrown a resize operation
*/
- public static final GLDrawableImpl resizeOffscreenDrawable(GLDrawableImpl drawable, GLContext context, int newWidth, int newHeight)
- throws NativeWindowException, GLException
+ public static final GLDrawableImpl resizeOffscreenDrawable(GLDrawableImpl drawable, final GLContext context, int newWidth, int newHeight)
+ throws NativeWindowException, GLException
{
- if(drawable.getChosenGLCapabilities().isOnscreen()) {
- throw new NativeWindowException("Drawable is not offscreen: "+drawable);
- }
final NativeSurface ns = drawable.getNativeSurface();
final int lockRes = ns.lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
+ if ( NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes ) {
throw new NativeWindowException("Could not lock surface of drawable: "+drawable);
}
+ boolean validateSize = true;
try {
- if(0>=newWidth) { newWidth = 1; }
- if(0>=newHeight) { newHeight = 1; }
- // propagate new size
- if(ns instanceof ProxySurface) {
+ if( ! drawable.isRealized() ) {
+ return drawable;
+ }
+ if( drawable.getChosenGLCapabilities().isOnscreen() ) {
+ throw new NativeWindowException("Drawable is not offscreen: "+drawable);
+ }
+ if( DEBUG && ( 0>=newWidth || 0>=newHeight) ) {
+ System.err.println("WARNING: Odd size detected: "+newWidth+"x"+newHeight+", using safe size 1x1. Drawable "+drawable);
+ Thread.dumpStack();
+ }
+ if( 0 >= newWidth ) { newWidth = 1; validateSize=false; }
+ if( 0 >= newHeight ) { newHeight = 1; validateSize=false; }
+ // propagate new size
+ if( ns instanceof ProxySurface ) {
final ProxySurface ps = (ProxySurface) ns;
final UpstreamSurfaceHook ush = ps.getUpstreamSurfaceHook();
if(ush instanceof UpstreamSurfaceHook.MutableSize) {
- ((UpstreamSurfaceHook.MutableSize)ush).setSize(newWidth, newHeight);
+ ((UpstreamSurfaceHook.MutableSize)ush).setSurfaceSize(newWidth, newHeight);
} else if(DEBUG) { // we have to assume UpstreamSurfaceHook contains the new size already, hence size check @ bottom
System.err.println("GLDrawableHelper.resizeOffscreenDrawable: Drawable's offscreen ProxySurface n.a. UpstreamSurfaceHook.MutableSize, but "+ush.getClass().getName()+": "+ush);
}
} else if(DEBUG) { // we have to assume surface contains the new size already, hence size check @ bottom
System.err.println("GLDrawableHelper.resizeOffscreenDrawable: Drawable's offscreen surface n.a. ProxySurface, but "+ns.getClass().getName()+": "+ns);
}
- if(drawable instanceof GLFBODrawable) {
- if( null != context && context.isCreated() ) {
+ if( drawable instanceof GLFBODrawable ) {
+ if( null != context && context.isCreated() ) {
((GLFBODrawable) drawable).resetSize(context.getGL());
}
} else {
@@ -267,17 +381,17 @@ public class GLDrawableHelper {
} finally {
ns.unlockSurface();
}
- if(drawable.getWidth() != newWidth || drawable.getHeight() != newHeight) {
+ if( validateSize && ( drawable.getSurfaceWidth() != newWidth || drawable.getSurfaceHeight() != newHeight ) ) {
throw new InternalError("Incomplete resize operation: expected "+newWidth+"x"+newHeight+", has: "+drawable);
}
return drawable;
}
-
- public final void addGLEventListener(GLEventListener listener) {
+
+ public final void addGLEventListener(final GLEventListener listener) {
addGLEventListener(-1, listener);
}
- public final void addGLEventListener(int index, GLEventListener listener) {
+ public final void addGLEventListener(int index, final GLEventListener listener) {
synchronized(listenersLock) {
if(0>index) {
index = listeners.size();
@@ -285,159 +399,386 @@ public class GLDrawableHelper {
// GLEventListener may be added after context is created,
// hence we earmark initialization for the next display call.
listenersToBeInit.add(listener);
+
listeners.add(index, listener);
}
}
-
- public final void removeGLEventListener(GLEventListener listener) {
+
+ /**
+ * Note that no {@link GLEventListener#dispose(GLAutoDrawable)} call is being issued
+ * due to the lack of a current context.
+ * Consider calling {@link #disposeGLEventListener(GLAutoDrawable, GLDrawable, GLContext, GLEventListener)}.
+ * @return the removed listener, or null if listener was not added
+ */
+ public final GLEventListener removeGLEventListener(final GLEventListener listener) {
synchronized(listenersLock) {
- listeners.remove(listener);
listenersToBeInit.remove(listener);
+ return listeners.remove(listener) ? listener : null;
}
}
- public final GLEventListener removeGLEventListener(int index)
- throws IndexOutOfBoundsException {
+ public final GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
synchronized(listenersLock) {
if(0>index) {
index = listeners.size()-1;
}
- return listeners.remove(index);
+ final GLEventListener listener = listeners.remove(index);
+ listenersToBeInit.remove(listener);
+ return listener;
+ }
+ }
+
+ public final int getGLEventListenerCount() {
+ synchronized(listenersLock) {
+ return listeners.size();
}
}
-
+
+ public final GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException {
+ synchronized(listenersLock) {
+ if(0>index) {
+ index = listeners.size()-1;
+ }
+ return listeners.get(index);
+ }
+ }
+
+ public final boolean areAllGLEventListenerInitialized() {
+ synchronized(listenersLock) {
+ return 0 == listenersToBeInit.size();
+ }
+ }
+
+ public final boolean getGLEventListenerInitState(final GLEventListener listener) {
+ synchronized(listenersLock) {
+ return !listenersToBeInit.contains(listener);
+ }
+ }
+
+ public final void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized) {
+ synchronized(listenersLock) {
+ if(initialized) {
+ listenersToBeInit.remove(listener);
+ } else {
+ listenersToBeInit.add(listener);
+ }
+ }
+ }
+
/**
- * Issues {@link javax.media.opengl.GLEventListener#dispose(javax.media.opengl.GLAutoDrawable)}
- * to all listeners.
+ * Disposes the given {@link GLEventListener} via {@link GLEventListener#dispose(GLAutoDrawable)}
+ * if it has been initialized and added to this queue.
* <p>
- * Please consider using {@link #disposeGL(GLAutoDrawable, GLDrawable, GLContext, Runnable)}
- * for correctness!
+ * If <code>remove</code> is <code>true</code>, the {@link GLEventListener} is removed from this drawable queue before disposal,
+ * otherwise marked uninitialized.
* </p>
- * @param drawable
+ * <p>
+ * Please consider using {@link #disposeGLEventListener(GLAutoDrawable, GLDrawable, GLContext, GLEventListener)}
+ * for correctness, i.e. encapsulating all calls w/ makeCurrent etc.
+ * </p>
+ * @param autoDrawable
+ * @param remove if true, the listener gets removed
+ * @return the disposed and/or removed listener, otherwise null if neither action is performed
*/
- public final void dispose(GLAutoDrawable drawable) {
+ public final GLEventListener disposeGLEventListener(final GLAutoDrawable autoDrawable, final GLEventListener listener, final boolean remove) {
+ synchronized(listenersLock) {
+ if( remove ) {
+ if( listeners.remove(listener) ) {
+ if( !listenersToBeInit.remove(listener) ) {
+ listener.dispose(autoDrawable);
+ }
+ return listener;
+ }
+ } else {
+ if( listeners.contains(listener) && !listenersToBeInit.contains(listener) ) {
+ listener.dispose(autoDrawable);
+ listenersToBeInit.add(listener);
+ return listener;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Disposes all added initialized {@link GLEventListener}s via {@link GLEventListener#dispose(GLAutoDrawable)}.
+ * <p>
+ * If <code>remove</code> is <code>true</code>, the {@link GLEventListener}s are removed from this drawable queue before disposal,
+ * otherwise maked uninitialized.
+ * </p>
+ * <p>
+ * Please consider using {@link #disposeAllGLEventListener(GLAutoDrawable, GLContext, boolean)}
+ * or {@link #disposeGL(GLAutoDrawable, GLContext, boolean)}
+ * for correctness, i.e. encapsulating all calls w/ makeCurrent etc.
+ * </p>
+ * @param autoDrawable
+ * @return the disposal count
+ * @throws GLException caused by {@link GLEventListener#dispose(GLAutoDrawable)}
+ */
+ public final int disposeAllGLEventListener(final GLAutoDrawable autoDrawable, final boolean remove) throws GLException {
+ Throwable firstCaught = null;
+ int disposeCount = 0;
synchronized(listenersLock) {
- final ArrayList<GLEventListener> _listeners = listeners;
- for (int i=0; i < _listeners.size(); i++) {
- _listeners.get(i).dispose(drawable);
+ if( remove ) {
+ for (int count = listeners.size(); 0 < count && 0 < listeners.size(); count--) {
+ final GLEventListener listener = listeners.remove(0);
+ if( !listenersToBeInit.remove(listener) ) {
+ try {
+ listener.dispose(autoDrawable);
+ } catch (final Throwable t) {
+ if( null == firstCaught ) {
+ firstCaught = t;
+ } else {
+ ExceptionUtils.dumpThrowable("subsequent", t);
+ }
+ }
+ disposeCount++;
+ }
+ }
+ } else {
+ for (int i = 0; i < listeners.size(); i++) {
+ final GLEventListener listener = listeners.get(i);
+ if( !listenersToBeInit.contains(listener) ) {
+ try {
+ listener.dispose(autoDrawable);
+ } catch (final Throwable t) {
+ if( null == firstCaught ) {
+ firstCaught = t;
+ } else {
+ ExceptionUtils.dumpThrowable("subsequent", t);
+ }
+ }
+ listenersToBeInit.add(listener);
+ disposeCount++;
+ }
+ }
}
}
+ if( null != firstCaught ) {
+ flushGLRunnables();
+ throw GLException.newGLException(firstCaught);
+ }
+ return disposeCount;
}
- private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) {
+ /**
+ * Principal helper method which runs {@link #disposeGLEventListener(GLAutoDrawable, GLEventListener, boolean)}
+ * with the context made current.
+ * <p>
+ * If an {@link GLAnimatorControl} is being attached and the current thread is different
+ * than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+ * </p>
+ *
+ * @param autoDrawable
+ * @param context
+ * @param listener
+ * @param initAction
+ */
+ public final GLEventListener disposeGLEventListener(final GLAutoDrawable autoDrawable,
+ final GLDrawable drawable,
+ final GLContext context,
+ final GLEventListener listener,
+ final boolean remove) {
+ synchronized(listenersLock) {
+ // fast path for uninitialized listener
+ if( listenersToBeInit.contains(listener) ) {
+ if( remove ) {
+ listenersToBeInit.remove(listener);
+ return listeners.remove(listener) ? listener : null;
+ }
+ return null;
+ }
+ }
+ final boolean isPaused = isAnimatorAnimatingOnOtherThread() && animatorCtrl.pause();
+ final GLEventListener[] res = new GLEventListener[] { null };
+ final Runnable action = new Runnable() {
+ @Override
+ public void run() {
+ res[0] = disposeGLEventListener(autoDrawable, listener, remove);
+ }
+ };
+ invokeGL(drawable, context, action, nop);
+
+ if(isPaused) {
+ animatorCtrl.resume();
+ }
+ return res[0];
+ }
+
+ /**
+ * Principal helper method which runs {@link #disposeAllGLEventListener(GLAutoDrawable, boolean)}
+ * with the context made current.
+ * <p>
+ * If an {@link GLAnimatorControl} is being attached and the current thread is different
+ * than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+ * </p>
+ *
+ * @param autoDrawable
+ * @param context
+ * @param remove
+ */
+ public final void disposeAllGLEventListener(final GLAutoDrawable autoDrawable,
+ final GLDrawable drawable,
+ final GLContext context,
+ final boolean remove) {
+
+ final boolean isPaused = isAnimatorAnimatingOnOtherThread() && animatorCtrl.pause();
+
+ final Runnable action = new Runnable() {
+ @Override
+ public void run() {
+ disposeAllGLEventListener(autoDrawable, remove);
+ }
+ };
+ invokeGL(drawable, context, action, nop);
+
+ if(isPaused) {
+ animatorCtrl.resume();
+ }
+ }
+
+ private final void init(final GLEventListener l, final GLAutoDrawable drawable, final boolean sendReshape, final boolean setViewport) {
l.init(drawable);
if(sendReshape) {
- reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */);
+ reshape(l, drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), setViewport, false /* checkInit */);
}
}
- /** The default init action to be called once after ctx is being created @ 1st makeCurrent(). */
- public final void init(GLAutoDrawable drawable) {
+ /**
+ * The default init action to be called once after ctx is being created @ 1st makeCurrent().
+ * @param sendReshape set to true if the subsequent display call won't reshape, otherwise false to avoid double reshape.
+ **/
+ public final void init(final GLAutoDrawable drawable, final boolean sendReshape) {
synchronized(listenersLock) {
final ArrayList<GLEventListener> _listeners = listeners;
- for (int i=0; i < _listeners.size(); i++) {
- final GLEventListener listener = _listeners.get(i) ;
-
- // If make ctx current, invoked by invokGL(..), results in a new ctx, init gets called.
- // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window),
- // hence it must be called unconditional, always.
- listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init
- init( listener, drawable, true /* sendReshape */);
+ final int listenerCount = _listeners.size();
+ if( listenerCount > 0 ) {
+ for (int i=0; i < listenerCount; i++) {
+ final GLEventListener listener = _listeners.get(i) ;
+
+ // If make ctx current, invoked by invokGL(..), results in a new ctx, init gets called.
+ // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window),
+ // hence it must be called unconditional, always.
+ listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init
+ init( listener, drawable, sendReshape, 0==i /* setViewport */);
+ }
+ } else {
+ // Expose same GL initialization if not using any GLEventListener
+ drawable.getGL().glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
}
}
}
- public final void display(GLAutoDrawable drawable) {
+ public final void display(final GLAutoDrawable drawable) {
displayImpl(drawable);
- if(!execGLRunnables(drawable)) {
- displayImpl(drawable);
+ // runForAllGLEventListener(drawable, displayAction);
+ if( glRunnableCount > 0 && !execGLRunnables(drawable) ) { // glRunnableCount volatile OK; execGL.. only executed if size > 0
+ displayImpl(drawable);
+ // runForAllGLEventListener(drawable, displayAction);
}
}
- private final void displayImpl(GLAutoDrawable drawable) {
+ private final void displayImpl(final GLAutoDrawable drawable) {
synchronized(listenersLock) {
final ArrayList<GLEventListener> _listeners = listeners;
- for (int i=0; i < _listeners.size(); i++) {
+ final int listenerCount = _listeners.size();
+ for (int i=0; i < listenerCount; i++) {
final GLEventListener listener = _listeners.get(i) ;
- // GLEventListener may need to be init,
+ // GLEventListener may need to be init,
// in case this one is added after the realization of the GLAutoDrawable
if( listenersToBeInit.remove(listener) ) {
- init( listener, drawable, true /* sendReshape */) ;
+ init( listener, drawable, true /* sendReshape */, listenersToBeInit.size() + 1 == listenerCount /* setViewport if 1st init */ );
}
listener.display(drawable);
}
}
}
- private final void reshape(GLEventListener listener, GLAutoDrawable drawable,
- int x, int y, int width, int height, boolean setViewport, boolean checkInit) {
+ public static interface GLEventListenerAction {
+ public void run(final GLAutoDrawable drawable, final GLEventListener listener);
+ }
+ /**
+ private static GLEventListenerAction displayAction = new GLEventListenerAction() {
+ public void run(final GLAutoDrawable drawable, final GLEventListener listener) {
+ listener.display(drawable);
+ } }; */
+
+ public final void runForAllGLEventListener(final GLAutoDrawable drawable, final GLEventListenerAction action) {
+ synchronized(listenersLock) {
+ final ArrayList<GLEventListener> _listeners = listeners;
+ final int listenerCount = _listeners.size();
+ for (int i=0; i < listenerCount; i++) {
+ final GLEventListener listener = _listeners.get(i) ;
+ // GLEventListener may need to be init,
+ // in case this one is added after the realization of the GLAutoDrawable
+ if( listenersToBeInit.remove(listener) ) {
+ init( listener, drawable, true /* sendReshape */, listenersToBeInit.size() + 1 == listenerCount /* setViewport if 1st init */ );
+ }
+ action.run(drawable, listener);
+ }
+ }
+ }
+
+ private final void reshape(final GLEventListener listener, final GLAutoDrawable drawable,
+ final int x, final int y, final int width, final int height, final boolean setViewport, final boolean checkInit) {
if(checkInit) {
- // GLEventListener may need to be init,
+ // GLEventListener may need to be init,
// in case this one is added after the realization of the GLAutoDrawable
synchronized(listenersLock) {
if( listenersToBeInit.remove(listener) ) {
- init( listener, drawable, false /* sendReshape */) ;
+ listener.init(drawable);
}
}
}
if(setViewport) {
+ if( GLContext.DEBUG_GL || DEBUG ) {
+ final int glerr0 = drawable.getGL().glGetError();
+ if( GL.GL_NO_ERROR != glerr0 ) {
+ System.err.println("Info: GLDrawableHelper.reshape: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
+ Thread.dumpStack();
+ }
+ }
drawable.getGL().glViewport(x, y, width, height);
}
listener.reshape(drawable, x, y, width, height);
}
- public final void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public final void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
synchronized(listenersLock) {
for (int i=0; i < listeners.size(); i++) {
- reshape((GLEventListener) listeners.get(i), drawable, x, y, width, height, 0==i, true);
+ reshape(listeners.get(i), drawable, x, y, width, height, 0==i /* setViewport */, true /* checkInit */);
}
}
}
- private final boolean execGLRunnables(GLAutoDrawable drawable) {
- boolean res = true;
- if(glRunnables.size()>0) { // volatile OK
- // swap one-shot list asap
- final ArrayList<GLRunnableTask> _glRunnables;
- synchronized(glRunnablesLock) {
- if(glRunnables.size()>0) {
- _glRunnables = glRunnables;
- glRunnables = new ArrayList<GLRunnableTask>();
- } else {
- _glRunnables = null;
- }
- }
-
- if(null!=_glRunnables) {
- for (int i=0; i < _glRunnables.size(); i++) {
- res = _glRunnables.get(i).run(drawable) && res;
- }
+ private final boolean execGLRunnables(final GLAutoDrawable drawable) { // glRunnables.size()>0
+ // swap one-shot list asap
+ final ArrayList<GLRunnableTask> _glRunnables;
+ synchronized(glRunnablesLock) {
+ if( glRunnables.size() > 0 ) {
+ glRunnableCount = 0;
+ _glRunnables = glRunnables;
+ glRunnables = new ArrayList<GLRunnableTask>();
+ } else {
+ return true;
}
}
+ boolean res = true;
+ for (int i=0; i < _glRunnables.size(); i++) {
+ res = _glRunnables.get(i).run(drawable) && res;
+ }
return res;
}
public final void flushGLRunnables() {
- if(glRunnables.size()>0) { // volatile OK
- // swap one-shot list asap
- final ArrayList<GLRunnableTask> _glRunnables;
- synchronized(glRunnablesLock) {
- if(glRunnables.size()>0) {
- _glRunnables = glRunnables;
- glRunnables = new ArrayList<GLRunnableTask>();
- } else {
- _glRunnables = null;
- }
- }
-
- if(null!=_glRunnables) {
- for (int i=0; i < _glRunnables.size(); i++) {
- _glRunnables.get(i).flush();
- }
+ synchronized(glRunnablesLock) {
+ glRunnableCount = 0;
+ while( glRunnables.size() > 0 ) {
+ glRunnables.remove(0).flush();
}
}
}
-
- public final void setAnimator(GLAnimatorControl animator) throws GLException {
+
+ public final void setAnimator(final GLAnimatorControl animator) throws GLException {
synchronized(glRunnablesLock) {
if(animatorCtrl!=animator && null!=animator && null!=animatorCtrl) {
throw new GLException("Trying to register GLAnimatorControl "+animator+", where "+animatorCtrl+" is already registered. Unregister first.");
@@ -452,15 +793,15 @@ public class GLDrawableHelper {
}
}
- public final boolean isAnimatorRunningOnOtherThread() {
+ public final boolean isAnimatorStartedOnOtherThread() {
return ( null != animatorCtrl ) ? animatorCtrl.isStarted() && animatorCtrl.getThread() != Thread.currentThread() : false ;
}
- public final boolean isAnimatorRunning() {
+ public final boolean isAnimatorStarted() {
return ( null != animatorCtrl ) ? animatorCtrl.isStarted() : false ;
}
- public final boolean isExternalAnimatorAnimating() {
+ public final boolean isAnimatorAnimatingOnOtherThread() {
return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() && animatorCtrl.getThread() != Thread.currentThread() : false ;
}
@@ -468,49 +809,180 @@ public class GLDrawableHelper {
return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() : false ;
}
+ public static final boolean isLockedByOtherThread(final GLAutoDrawable d) {
+ final Thread currentThread = Thread.currentThread();
+ final Thread upstreamLockOwner = d.getUpstreamLock().getOwner();
+ if( null != upstreamLockOwner && currentThread != upstreamLockOwner ) {
+ return true;
+ } else {
+ final NativeSurface s = d.getNativeSurface();
+ final Thread surfaceLockOwner = null != s ? s.getSurfaceLockOwner() : null;
+ return null != surfaceLockOwner && currentThread != surfaceLockOwner;
+ }
+ }
+
+ public static final boolean isLockedByThisThread(final GLAutoDrawable d) {
+ final Thread currentThread = Thread.currentThread();
+ final Thread upstreamLockOwner = d.getUpstreamLock().getOwner();
+ if( currentThread == upstreamLockOwner ) {
+ return true;
+ } else {
+ final NativeSurface s = d.getNativeSurface();
+ final Thread surfaceLockOwner = null != s ? s.getSurfaceLockOwner() : null;
+ return currentThread == surfaceLockOwner;
+ }
+ }
+
/**
* <p>
* If <code>wait</code> is <code>true</code> the call blocks until the <code>glRunnable</code>
* has been executed.<p>
* <p>
- * If <code>wait</code> is <code>true</code> <b>and</b>
+ * If <code>wait</code> is <code>true</code> <b>and</b>
* {@link GLDrawable#isRealized()} returns <code>false</code> <i>or</i> {@link GLAutoDrawable#getContext()} returns <code>null</code>,
* the call is ignored and returns <code>false</code>.<br>
* This helps avoiding deadlocking the caller.
* </p>
+ * <p>
+ * <pre>
+ * 0 == deferredHere && 0 == isGLThread -> display() will issue on GL thread, blocking!
+ *
+ * deferredHere wait isGLThread lockedByThisThread Note
+ * OK 0 x 1 x
+ * OK 0 x 0 0
+ * ERROR 0 x 0 1 Will be deferred on GL thread by display() (blocking),
+ * but locked by this thread -> ERROR
+ *
+ * 1 0 x x All good, due to no wait, non blocking
+ *
+ * 1 1 1 0
+ * 1 1 0 0
+ * SWITCH 1 1 1 1 Run immediately, don't defer since locked by this thread, but isGLThread
+ * ERROR 1 1 0 1 Locked by this thread, but _not_ isGLThread -> ERROR
+ * </pre>
+ * </p>
*
* @param drawable the {@link GLAutoDrawable} to be used
* @param wait if <code>true</code> block until execution of <code>glRunnable</code> is finished, otherwise return immediatly w/o waiting
* @param glRunnable the {@link GLRunnable} to execute within {@link #display()}
* @return <code>true</code> if the {@link GLRunnable} has been processed or queued, otherwise <code>false</code>.
+ * @throws IllegalStateException in case the drawable is locked by this thread, no animator is running on another thread and <code>wait</code> is <code>true</code>.
*/
- public final boolean invoke(GLAutoDrawable drawable, boolean wait, GLRunnable glRunnable) {
+ public final boolean invoke(final GLAutoDrawable drawable, boolean wait, final GLRunnable glRunnable) throws IllegalStateException {
if( null == glRunnable || null == drawable ||
wait && ( !drawable.isRealized() || null==drawable.getContext() ) ) {
return false;
}
-
- Throwable throwable = null;
+
GLRunnableTask rTask = null;
- Object rTaskLock = new Object();
+ final Object rTaskLock = new Object();
+ Throwable throwable = null;
synchronized(rTaskLock) {
- boolean deferred;
+ boolean deferredHere;
synchronized(glRunnablesLock) {
- deferred = isExternalAnimatorAnimating();
- if(!deferred) {
- wait = false; // don't wait if exec immediatly
+ final boolean isGLThread = drawable.isThreadGLCapable();
+ deferredHere = isAnimatorAnimatingOnOtherThread();
+ if( deferredHere ) {
+ if( wait && isLockedByThisThread(drawable) ) {
+ if( isGLThread ) {
+ // Run immediately, don't defer since locked by this thread, but isGLThread
+ deferredHere = false;
+ wait = false;
+ } else {
+ // Locked by this thread, but _not_ isGLThread -> ERROR
+ throw new IllegalStateException("Deferred, wait, isLocked on current and not GL-Thread: thread "+Thread.currentThread());
+ }
+ }
+ } else {
+ if( !isGLThread && isLockedByThisThread(drawable) ) {
+ // Will be deferred on GL thread by display() (blocking), but locked by this thread -> ERROR
+ throw new IllegalStateException("Not deferred, isLocked on current and not GL-Thread: thread "+Thread.currentThread());
+ }
+ wait = false; // don't wait if exec immediately
}
rTask = new GLRunnableTask(glRunnable,
wait ? rTaskLock : null,
wait /* catch Exceptions if waiting for result */);
+ glRunnableCount++;
+ glRunnables.add(rTask);
+ }
+ if( !deferredHere ) {
+ drawable.display();
+ } else if( wait ) {
+ try {
+ rTaskLock.wait(); // free lock, allow execution of rTask
+ } catch (final InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rTask.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @see #invoke(GLAutoDrawable, boolean, GLRunnable)
+ *
+ * @param drawable
+ * @param wait
+ * @param newGLRunnables
+ * @return
+ * @throws IllegalStateException
+ */
+ public final boolean invoke(final GLAutoDrawable drawable, boolean wait, final List<GLRunnable> newGLRunnables) throws IllegalStateException {
+ if( null == newGLRunnables || newGLRunnables.size() == 0 || null == drawable ||
+ wait && ( !drawable.isRealized() || null==drawable.getContext() ) ) {
+ return false;
+ }
+
+ final int count = newGLRunnables.size();
+ GLRunnableTask rTask = null;
+ final Object rTaskLock = new Object();
+ Throwable throwable = null;
+ synchronized(rTaskLock) {
+ boolean deferredHere;
+ synchronized(glRunnablesLock) {
+ final boolean isGLThread = drawable.isThreadGLCapable();
+ deferredHere = isAnimatorAnimatingOnOtherThread();
+ if( deferredHere ) {
+ if( wait && isLockedByThisThread(drawable) ) {
+ if( isGLThread ) {
+ // Run immediately, don't defer since locked by this thread, but isGLThread
+ deferredHere = false;
+ wait = false;
+ } else {
+ // Locked by this thread, but _not_ isGLThread -> ERROR
+ throw new IllegalStateException("Deferred, wait, isLocked on current and not GL-Thread: thread "+Thread.currentThread());
+ }
+ }
+ } else {
+ if( !isGLThread && isLockedByThisThread(drawable) ) {
+ // Will be deferred on GL thread by display() (blocking), but locked by this thread -> ERROR
+ throw new IllegalStateException("Not deferred, isLocked on current and not GL-Thread: thread "+Thread.currentThread());
+ }
+ wait = false; // don't wait if exec immediately
+ }
+ for(int i=0; i<count-1; i++) {
+ glRunnableCount++;
+ glRunnables.add( new GLRunnableTask(newGLRunnables.get(i), null, false) );
+ }
+ rTask = new GLRunnableTask(newGLRunnables.get(count-1),
+ wait ? rTaskLock : null,
+ wait /* catch Exceptions if waiting for result */);
+ glRunnableCount++;
glRunnables.add(rTask);
}
- if( !deferred ) {
+ if( !deferredHere ) {
drawable.display();
} else if( wait ) {
try {
rTaskLock.wait(); // free lock, allow execution of rTask
- } catch (InterruptedException ie) {
+ } catch (final InterruptedException ie) {
throwable = ie;
}
if(null==throwable) {
@@ -524,7 +996,17 @@ public class GLDrawableHelper {
return true;
}
- public final void setAutoSwapBufferMode(boolean enable) {
+ public final void enqueue(final GLRunnable glRunnable) {
+ if( null == glRunnable) {
+ return;
+ }
+ synchronized(glRunnablesLock) {
+ glRunnableCount++;
+ glRunnables.add( new GLRunnableTask(glRunnable, null, false) );
+ }
+ }
+
+ public final void setAutoSwapBufferMode(final boolean enable) {
autoSwapBufferMode = enable;
}
@@ -532,26 +1014,89 @@ public class GLDrawableHelper {
return autoSwapBufferMode;
}
+ private final String getExclusiveContextSwitchString() {
+ return 0 == exclusiveContextSwitch ? "nop" : ( 0 > exclusiveContextSwitch ? "released" : "claimed" ) ;
+ }
+
/**
- * @param t the thread for which context release shall be skipped, usually the animation thread,
- * ie. {@link Animator#getThread()}.
- * @deprecated this is an experimental feature,
- * intended for measuring performance in regards to GL context switch
- * and only being used if {@link #PERF_STATS} is enabled
- * by defining property <code>jogl.debug.GLDrawable.PerfStats</code>.
+ * Dedicates this instance's {@link GLContext} to the given thread.<br/>
+ * The thread will exclusively claim the {@link GLContext} via {@link #display()} and not release it
+ * until {@link #destroy()} or <code>setExclusiveContextThread(null)</code> has been called.
+ * <p>
+ * Default non-exclusive behavior is <i>requested</i> via <code>setExclusiveContextThread(null)</code>,
+ * which will cause the next call of {@link #display()} on the exclusive thread to
+ * release the {@link GLContext}. Only after it's async release, {@link #getExclusiveContextThread()}
+ * will return <code>null</code>.
+ * </p>
+ * <p>
+ * To release a previous made exclusive thread, a user issues <code>setExclusiveContextThread(null)</code>
+ * and may poll {@link #getExclusiveContextThread()} until it returns <code>null</code>,
+ * <i>while</i> the exclusive thread is still running.
+ * </p>
+ * <p>
+ * Note: Setting a new exclusive thread without properly releasing a previous one
+ * will throw an GLException.
+ * </p>
+ * <p>
+ * One scenario could be to dedicate the context to the {@link com.jogamp.opengl.util.AnimatorBase#getThread() animator thread}
+ * and spare redundant context switches.
+ * </p>
+ * @param t the exclusive thread to claim the context, or <code>null</code> for default operation.
+ * @return previous exclusive context thread
+ * @throws GLException If an exclusive thread is still active but a new one is attempted to be set
*/
- public final void setSkipContextReleaseThread(Thread t) {
- skipContextReleaseThread = t;
+ public final Thread setExclusiveContextThread(final Thread t, final GLContext context) throws GLException {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper.setExclusiveContextThread(): START switch "+getExclusiveContextSwitchString()+", thread "+exclusiveContextThread+" -> "+t+" -- currentThread "+Thread.currentThread());
+ }
+ final Thread oldExclusiveContextThread = exclusiveContextThread;
+ if( exclusiveContextThread == t ) {
+ exclusiveContextSwitch = 0; // keep
+ } else if( null == t ) {
+ exclusiveContextSwitch = -1; // release
+ } else {
+ exclusiveContextSwitch = 1; // claim
+ if( null != exclusiveContextThread ) {
+ throw new GLException("Release current exclusive Context Thread "+exclusiveContextThread+" first");
+ }
+ if( null != context && context.isCurrent() ) {
+ try {
+ forceNativeRelease(context);
+ } catch (final Throwable ex) {
+ flushGLRunnables();
+ throw GLException.newGLException(ex);
+ }
+ }
+ exclusiveContextThread = t;
+ }
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper.setExclusiveContextThread(): END switch "+getExclusiveContextSwitchString()+", thread "+exclusiveContextThread+" -- currentThread "+Thread.currentThread());
+ }
+ return oldExclusiveContextThread;
}
/**
- * @deprecated see {@link #setSkipContextReleaseThread(Thread)}
+ * @see #setExclusiveContextThread(Thread, GLContext)
*/
- public final Thread getSkipContextReleaseThread() {
- return skipContextReleaseThread;
+ public final Thread getExclusiveContextThread() {
+ return exclusiveContextThread;
+ }
+
+ private static final ThreadLocal<WeakReference<Runnable>> perThreadInitAction = new ThreadLocal<WeakReference<Runnable>>();
+ private static final Runnable getLastInitAction() {
+ final WeakReference<Runnable> lastInitActionWR = perThreadInitAction.get();
+ if( null != lastInitActionWR ) {
+ final Runnable lastInitAction = lastInitActionWR.get();
+ if( null == lastInitAction ) {
+ perThreadInitAction.set(null);
+ }
+ return lastInitAction;
+ }
+ return null;
+ }
+ private static final void setLastInitAction(final Runnable initAction) {
+ perThreadInitAction.set(new WeakReference<Runnable>(initAction));
}
-
- private static final ThreadLocal<Runnable> perThreadInitAction = new ThreadLocal<Runnable>();
/** Principal helper method which runs a Runnable with the context
made current. This could have been made part of GLContext, but a
@@ -569,209 +1114,332 @@ public class GLDrawableHelper {
* @param runnable
* @param initAction
*/
- public final void invokeGL(GLDrawable drawable,
- GLContext context,
- Runnable runnable,
- Runnable initAction) {
+ public final void invokeGL(final GLDrawable drawable,
+ final GLContext context,
+ final Runnable runnable,
+ final Runnable initAction) {
if(null==context) {
if (DEBUG) {
- Exception e = new GLException(Thread.currentThread().getName()+" Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext");
- e.printStackTrace();
+ ExceptionUtils.dumpThrowable("informal", new GLException("Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"));
}
return;
}
if(PERF_STATS) {
- invokeGLImplStats(drawable, context, runnable, initAction, null);
+ invokeGLImplStats(drawable, context, runnable, initAction);
} else {
- invokeGLImpl(drawable, context, runnable, initAction, null);
+ invokeGLImpl(drawable, context, runnable, initAction);
}
}
- /**
- * Principal helper method which runs {@link #dispose(GLAutoDrawable)} with the context
- * made current and destroys the context afterwards while holding the lock.
- *
+ /**
+ * Principal helper method which runs
+ * {@link #disposeAllGLEventListener(GLAutoDrawable, boolean) disposeAllGLEventListener(autoDrawable, false)}
+ * with the context made current.
+ * <p>
+ * If <code>destroyContext</code> is <code>true</code> the context is destroyed in the end while holding the lock.
+ * </p>
+ * <p>
+ * If <code>destroyContext</code> is <code>false</code> the context is natively released, i.e. released as often as locked before.
+ * </p>
* @param autoDrawable
- * @param drawable
* @param context
- * @param postAction
+ * @param destroyContext destroy context in the end while holding the lock
+ * @throws GLException caused by {@link GLEventListener#dispose(GLAutoDrawable)} or context closing
+ *
*/
- public final void disposeGL(GLAutoDrawable autoDrawable,
- GLDrawable drawable,
- GLContext context,
- Runnable postAction) {
- if(PERF_STATS) {
- invokeGLImplStats(drawable, context, null, null, autoDrawable);
- } else {
- invokeGLImpl(drawable, context, null, null, autoDrawable);
- }
- if(null != postAction) {
- postAction.run();
- }
- }
-
- private final void invokeGLImpl(GLDrawable drawable,
- GLContext context,
- Runnable runnable,
- Runnable initAction,
- GLAutoDrawable disposeAutoDrawable) {
- final Thread currentThread = Thread.currentThread();
-
- final boolean isDisposeAction = null==initAction ;
-
+ public final void disposeGL(final GLAutoDrawable autoDrawable,
+ final GLContext context, final boolean destroyContext) throws GLException {
// Support for recursive makeCurrent() calls as well as calling
// other drawables' display() methods from within another one's
GLContext lastContext = GLContext.getCurrent();
Runnable lastInitAction = null;
if (lastContext != null) {
if (lastContext == context) {
- lastContext = null; // utilize recursive locking
+ lastContext = null;
} else {
- lastInitAction = perThreadInitAction.get();
+ // utilize recursive locking
+ lastInitAction = getLastInitAction();
lastContext.release();
}
}
- int res = GLContext.CONTEXT_NOT_CURRENT;
-
+
+ GLException disposeCaught = null;
+ Throwable contextCloseCaught = null;
+
+ int res;
try {
res = context.makeCurrent();
if (GLContext.CONTEXT_NOT_CURRENT != res) {
- if(!isDisposeAction) {
- perThreadInitAction.set(initAction);
- if (GLContext.CONTEXT_CURRENT_NEW == res) {
- if (DEBUG) {
- System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
- }
- initAction.run();
- }
- runnable.run();
- if (autoSwapBufferMode) {
- drawable.swapBuffers();
- }
- } else {
- if(GLContext.CONTEXT_CURRENT_NEW == res) {
- throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
- }
- if(listeners.size()>0) {
- dispose(disposeAutoDrawable);
+ if(GLContext.CONTEXT_CURRENT_NEW == res) {
+ throw new GLException(GLDrawableHelper.getThreadName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
+ }
+ if( listeners.size() > 0 && null != autoDrawable ) {
+ try {
+ disposeAllGLEventListener(autoDrawable, false);
+ } catch(final GLException t) {
+ disposeCaught = t;
}
}
}
} finally {
try {
- if(isDisposeAction) {
+ if(destroyContext) {
context.destroy();
- flushGLRunnables();
- } else if( GLContext.CONTEXT_NOT_CURRENT != res ) {
- context.release();
+ } else {
+ forceNativeRelease(context);
}
- } catch (Exception e) {
- System.err.println("Catched: "+e.getMessage());
- e.printStackTrace();
+ } catch (final Throwable t) {
+ contextCloseCaught = t;
}
+ flushGLRunnables(); // always flush GLRunnables at dispose
+
if (lastContext != null) {
final int res2 = lastContext.makeCurrent();
if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
lastInitAction.run();
}
}
+ if( null != disposeCaught ) {
+ if( null != contextCloseCaught ) {
+ ExceptionUtils.dumpThrowable("subsequent", contextCloseCaught);
+ }
+ throw disposeCaught;
+ }
+ if( null != contextCloseCaught ) {
+ throw GLException.newGLException(contextCloseCaught);
+ }
}
}
-
- private final void invokeGLImplStats(GLDrawable drawable,
- GLContext context,
- Runnable runnable,
- Runnable initAction,
- GLAutoDrawable disposeAutoDrawable) {
- final Thread currentThread = Thread.currentThread();
-
- final boolean isDisposeAction = null==initAction ;
-
- // Support for recursive makeCurrent() calls as well as calling
- // other drawables' display() methods from within another one's
- int res = GLContext.CONTEXT_NOT_CURRENT;
- GLContext lastContext = GLContext.getCurrent();
- Runnable lastInitAction = null;
- if (lastContext != null) {
- if (lastContext == context) {
- if( currentThread == skipContextReleaseThread ) {
- res = GLContext.CONTEXT_CURRENT;
- } // else: utilize recursive locking
- lastContext = null;
- } else {
- lastInitAction = perThreadInitAction.get();
- lastContext.release();
- }
- }
-
- long t0 = System.currentTimeMillis();
- long tdA = 0; // makeCurrent
- long tdR = 0; // render time
- long tdS = 0; // swapBuffers
- long tdX = 0; // release
- boolean ctxClaimed = false;
- boolean ctxReleased = false;
- boolean ctxDestroyed = false;
- try {
- if (res == GLContext.CONTEXT_NOT_CURRENT) {
- res = context.makeCurrent();
- ctxClaimed = true;
- }
- if (res != GLContext.CONTEXT_NOT_CURRENT) {
- if(!isDisposeAction) {
- perThreadInitAction.set(initAction);
- if (res == GLContext.CONTEXT_CURRENT_NEW) {
- if (DEBUG) {
- System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
- }
- initAction.run();
- }
- tdR = System.currentTimeMillis();
- tdA = tdR - t0; // makeCurrent
- runnable.run();
- tdS = System.currentTimeMillis();
- tdR = tdS - tdR; // render time
- if (autoSwapBufferMode) {
- drawable.swapBuffers();
- tdX = System.currentTimeMillis();
- tdS = tdX - tdS; // swapBuffers
- }
- } else {
- if(res == GLContext.CONTEXT_CURRENT_NEW) {
- throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
- }
- if(listeners.size()>0) {
- dispose(disposeAutoDrawable);
- }
- }
+
+ private final void invokeGLImpl(final GLDrawable drawable,
+ final GLContext context,
+ final Runnable runnable,
+ final Runnable initAction) {
+ final Thread currentThread = Thread.currentThread();
+
+ Throwable glEventListenerCaught = null;
+ Throwable contextReleaseCaught = null;
+
+ // Exclusive Cases:
+ // 1: lock - unlock : default
+ // 2: lock - - : exclusive, not locked yet
+ // 3: - - - : exclusive, already locked
+ // 4: - - unlock : ex-exclusive, already locked
+ final boolean _isExclusiveThread, _releaseExclusiveThread;
+ if( null != exclusiveContextThread) {
+ if( currentThread == exclusiveContextThread ) {
+ _releaseExclusiveThread = 0 > exclusiveContextSwitch;
+ _isExclusiveThread = !_releaseExclusiveThread;
+ exclusiveContextSwitch = 0;
+ } else {
+ // Exclusive thread usage, but on other thread
+ return;
+ }
+ } else {
+ _releaseExclusiveThread = false;
+ _isExclusiveThread = false;
}
- } finally {
+
+ // Support for recursive makeCurrent() calls as well as calling
+ // other drawables' display() methods from within another one's
+ int res = GLContext.CONTEXT_NOT_CURRENT;
+ GLContext lastContext = GLContext.getCurrent();
+ Runnable lastInitAction = null;
+ if (lastContext != null) {
+ if (lastContext == context) {
+ res = GLContext.CONTEXT_CURRENT;
+ lastContext = null;
+ } else {
+ // utilize recursive locking
+ lastInitAction = getLastInitAction();
+ lastContext.release();
+ }
+ }
+
try {
- if(isDisposeAction) {
- context.destroy();
+ final boolean releaseContext;
+ if( GLContext.CONTEXT_NOT_CURRENT == res ) {
+ res = context.makeCurrent();
+ releaseContext = !_isExclusiveThread;
+ } else {
+ releaseContext = _releaseExclusiveThread;
+ }
+ if (GLContext.CONTEXT_NOT_CURRENT != res) {
+ try {
+ setLastInitAction(initAction);
+ if (GLContext.CONTEXT_CURRENT_NEW == res) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
+ }
+ initAction.run();
+ }
+ runnable.run();
+ if ( autoSwapBufferMode ) {
+ drawable.swapBuffers();
+ }
+ } catch (final Throwable t) {
+ glEventListenerCaught = t;
+ } finally {
+ if( _releaseExclusiveThread ) {
+ exclusiveContextThread = null;
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper.invokeGL() - Release ExclusiveContextThread -- currentThread "+Thread.currentThread());
+ }
+ }
+ if( releaseContext ) {
+ try {
+ context.release();
+ } catch (final Throwable t) {
+ contextReleaseCaught = t;
+ }
+ }
+ }
+ }
+ } finally {
+ if (lastContext != null) {
+ final int res2 = lastContext.makeCurrent();
+ if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
+ lastInitAction.run();
+ }
+ }
+ if( null != glEventListenerCaught ) {
+ flushGLRunnables();
+ if( null != contextReleaseCaught ) {
+ ExceptionUtils.dumpThrowable("subsequent", contextReleaseCaught);
+ }
+ throw GLException.newGLException(glEventListenerCaught);
+ }
+ if( null != contextReleaseCaught ) {
flushGLRunnables();
- ctxDestroyed = true;
- } else if( res != GLContext.CONTEXT_NOT_CURRENT &&
- (null == skipContextReleaseThread || currentThread != skipContextReleaseThread) ) {
- context.release();
- ctxReleased = true;
+ throw GLException.newGLException(contextReleaseCaught);
}
- } catch (Exception e) {
- System.err.println("Catched: "+e.getMessage());
- e.printStackTrace();
}
+ }
- tdX = System.currentTimeMillis() - tdX; // release / destroy
+ private final void invokeGLImplStats(final GLDrawable drawable,
+ final GLContext context,
+ final Runnable runnable,
+ final Runnable initAction) {
+ final Thread currentThread = Thread.currentThread();
+
+ Throwable glEventListenerCaught = null;
+ Throwable contextReleaseCaught = null;
+
+ // Exclusive Cases:
+ // 1: lock - unlock : default
+ // 2: lock - - : exclusive, not locked yet
+ // 3: - - - : exclusive, already locked
+ // 4: - - unlock : ex-exclusive, already locked
+ final boolean _isExclusiveThread, _releaseExclusiveThread;
+ if( null != exclusiveContextThread) {
+ if( currentThread == exclusiveContextThread ) {
+ _releaseExclusiveThread = 0 > exclusiveContextSwitch;
+ _isExclusiveThread = !_releaseExclusiveThread;
+ } else {
+ // Exclusive thread usage, but on other thread
+ return;
+ }
+ } else {
+ _releaseExclusiveThread = false;
+ _isExclusiveThread = false;
+ }
+
+ // Support for recursive makeCurrent() calls as well as calling
+ // other drawables' display() methods from within another one's
+ int res = GLContext.CONTEXT_NOT_CURRENT;
+ GLContext lastContext = GLContext.getCurrent();
+ Runnable lastInitAction = null;
if (lastContext != null) {
- final int res2 = lastContext.makeCurrent();
- if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
- lastInitAction.run();
- }
+ if (lastContext == context) {
+ res = GLContext.CONTEXT_CURRENT;
+ lastContext = null;
+ } else {
+ // utilize recursive locking
+ lastInitAction = getLastInitAction();
+ lastContext.release();
+ }
}
- }
- long td = System.currentTimeMillis() - t0;
- System.err.println("td0 "+td+"ms, fps "+(1.0/(td/1000.0))+", td-makeCurrent: "+tdA+"ms, td-render "+tdR+"ms, td-swap "+tdS+"ms, td-release "+tdX+"ms, ctx claimed: "+ctxClaimed+", ctx release: "+ctxReleased+", ctx destroyed "+ctxDestroyed);
+
+ final long t0 = System.currentTimeMillis();
+ long tdA = 0; // makeCurrent
+ long tdR = 0; // render time
+ long tdS = 0; // swapBuffers
+ long tdX = 0; // release
+ boolean ctxClaimed = false;
+ boolean ctxReleased = false;
+ final boolean ctxDestroyed = false;
+ try {
+ final boolean releaseContext;
+ if( GLContext.CONTEXT_NOT_CURRENT == res ) {
+ res = context.makeCurrent();
+ releaseContext = !_isExclusiveThread;
+ ctxClaimed = true;
+ } else {
+ releaseContext = _releaseExclusiveThread;
+ }
+ if (GLContext.CONTEXT_NOT_CURRENT != res) {
+ try {
+ setLastInitAction(initAction);
+ if (GLContext.CONTEXT_CURRENT_NEW == res) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
+ }
+ initAction.run();
+ }
+ tdR = System.currentTimeMillis();
+ tdA = tdR - t0; // makeCurrent
+ runnable.run();
+ tdS = System.currentTimeMillis();
+ tdR = tdS - tdR; // render time
+ if ( autoSwapBufferMode ) {
+ drawable.swapBuffers();
+ tdX = System.currentTimeMillis();
+ tdS = tdX - tdS; // swapBuffers
+ }
+ } catch (final Throwable t) {
+ glEventListenerCaught = t;
+ } finally {
+ if( _releaseExclusiveThread ) {
+ exclusiveContextSwitch = 0;
+ exclusiveContextThread = null;
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper.invokeGL() - Release ExclusiveContextThread -- currentThread "+Thread.currentThread());
+ }
+ }
+ if( releaseContext ) {
+ try {
+ context.release();
+ ctxReleased = true;
+ } catch (final Throwable t) {
+ contextReleaseCaught = t;
+ }
+ }
+ }
+ }
+ } finally {
+ tdX = System.currentTimeMillis() - tdX; // release / destroy
+ if (lastContext != null) {
+ final int res2 = lastContext.makeCurrent();
+ if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
+ lastInitAction.run();
+ }
+ }
+ if( null != glEventListenerCaught ) {
+ flushGLRunnables();
+ if( null != contextReleaseCaught ) {
+ ExceptionUtils.dumpThrowable("subsequent", contextReleaseCaught);
+ }
+ throw GLException.newGLException(glEventListenerCaught);
+ }
+ if( null != contextReleaseCaught ) {
+ flushGLRunnables();
+ throw GLException.newGLException(contextReleaseCaught);
+ }
+ }
+ final long td = System.currentTimeMillis() - t0;
+ System.err.println("td0 "+td+"ms, fps "+(1.0/(td/1000.0))+", td-makeCurrent: "+tdA+"ms, td-render "+tdR+"ms, td-swap "+tdS+"ms, td-release "+tdX+"ms, ctx claimed: "+ctxClaimed+", ctx release: "+ctxReleased+", ctx destroyed "+ctxDestroyed);
}
-
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index 311690f1d..544aaf064 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -52,15 +52,17 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
public abstract class GLDrawableImpl implements GLDrawable {
- protected static final boolean DEBUG = Debug.debug("GLDrawable");
+ protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG;
- protected GLDrawableImpl(GLDrawableFactory factory,
- NativeSurface comp,
- boolean realized) {
+ protected GLDrawableImpl(final GLDrawableFactory factory, final NativeSurface comp, final boolean realized) {
+ this(factory, comp, (GLCapabilitiesImmutable) comp.getGraphicsConfiguration().getRequestedCapabilities(), realized);
+ }
+
+ protected GLDrawableImpl(final GLDrawableFactory factory, final NativeSurface comp, final GLCapabilitiesImmutable requestedCapabilities, final boolean realized) {
this.factory = factory;
this.surface = comp;
this.realized = realized;
- this.requestedCapabilities = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getRequestedCapabilities();
+ this.requestedCapabilities = requestedCapabilities;
}
/**
@@ -74,51 +76,51 @@ public abstract class GLDrawableImpl implements GLDrawable {
@Override
public final void swapBuffers() throws GLException {
- if( !realized ) {
+ if( !realized ) { // volatile OK (locked below)
return; // destroyed already
}
- int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release]
+ final int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release]
if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
return;
}
try {
- if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
- updateHandle();
- }
- final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
- if ( caps.getDoubleBuffered() ) {
- if(!surface.surfaceSwap()) {
- swapBuffersImpl(true);
- }
- } else {
- final GLContext ctx = GLContext.getCurrent();
- if(null!=ctx && ctx.getGLDrawable()==this) {
- ctx.getGL().glFlush();
+ if( realized ) { // volatile OK
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
+ if ( caps.getDoubleBuffered() ) {
+ if(!surface.surfaceSwap()) {
+ swapBuffersImpl(true);
+ }
+ } else {
+ final GLContext ctx = GLContext.getCurrent();
+ if(null!=ctx && ctx.getGLDrawable()==this) {
+ ctx.getGL().glFlush();
+ }
+ swapBuffersImpl(false);
}
- swapBuffersImpl(false);
}
} finally {
unlockSurface();
- }
+ }
surface.surfaceUpdated(this, surface, System.currentTimeMillis());
}
-
+
/**
* Platform and implementation depending surface swap.
* <p>The surface is locked.</p>
* <p>
- * If <code>doubleBuffered</code> is <code>true</code>,
+ * If <code>doubleBuffered</code> is <code>true</code>,
* an actual platform dependent surface swap shall be executed.
* </p>
* <p>
- * If <code>doubleBuffered</code> is <code>false</code>,
- * {@link GL#glFlush()} has been called already and
+ * If <code>doubleBuffered</code> is <code>false</code>,
+ * {@link GL#glFlush()} has been called already and
* the implementation may execute implementation specific code.
* </p>
+ * @param doubleBuffered indicates whether double buffering is enabled, see above.
*/
protected abstract void swapBuffersImpl(boolean doubleBuffered);
- public final static String toHexString(long hex) {
+ public final static String toHexString(final long hex) {
return "0x" + Long.toHexString(hex);
}
@@ -128,10 +130,11 @@ public abstract class GLDrawableImpl implements GLDrawable {
}
@Override
- public GLCapabilitiesImmutable getChosenGLCapabilities() {
+ public final GLCapabilitiesImmutable getChosenGLCapabilities() {
return (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
}
+ @Override
public final GLCapabilitiesImmutable getRequestedGLCapabilities() {
return requestedCapabilities;
}
@@ -141,11 +144,21 @@ public abstract class GLDrawableImpl implements GLDrawable {
return surface;
}
- /** called with locked surface @ setRealized(false) */
+ /**
+ * called with locked surface @ setRealized(false) or @ lockSurface(..) when surface changed
+ * <p>
+ * Must be paired w/ {@link #createHandle()}.
+ * </p>
+ */
protected void destroyHandle() {}
- /** called with locked surface @ setRealized(true) or @ lockSurface(..) when surface changed */
- protected void updateHandle() {}
+ /**
+ * called with locked surface @ setRealized(true) or @ lockSurface(..) when surface changed
+ * <p>
+ * Must be paired w/ {@link #destroyHandle()}.
+ * </p>
+ */
+ protected void createHandle() {}
@Override
public long getHandle() {
@@ -158,37 +171,41 @@ public abstract class GLDrawableImpl implements GLDrawable {
}
@Override
- public final synchronized void setRealized(boolean realizedArg) {
- if ( realized != realizedArg ) {
+ public final void setRealized(final boolean realizedArg) {
+ if ( realized != realizedArg ) { // volatile: OK (locked below)
+ final boolean isProxySurface = surface instanceof ProxySurface;
if(DEBUG) {
- System.err.println(getThreadName() + ": setRealized: "+getClass().getSimpleName()+" "+realized+" -> "+realizedArg);
+ System.err.println(getThreadName() + ": setRealized: drawable "+getClass().getSimpleName()+", surface "+surface.getClass().getSimpleName()+", isProxySurface "+isProxySurface+": "+realized+" -> "+realizedArg);
+ Thread.dumpStack();
}
- realized = realizedArg;
- AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice();
+ final AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice();
if(realizedArg) {
- if(surface instanceof ProxySurface) {
+ if(isProxySurface) {
((ProxySurface)surface).createNotify();
}
- if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) {
+ if(NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface()) {
throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)");
}
} else {
aDevice.lock();
}
try {
- if(realizedArg) {
- setRealizedImpl();
- updateHandle();
- } else {
- destroyHandle();
- setRealizedImpl();
+ if ( realized != realizedArg ) { // volatile: OK
+ realized = realizedArg;
+ if(realizedArg) {
+ setRealizedImpl();
+ createHandle();
+ } else {
+ destroyHandle();
+ setRealizedImpl();
+ }
}
} finally {
if(realizedArg) {
- unlockSurface();
+ surface.unlockSurface();
} else {
aDevice.unlock();
- if(surface instanceof ProxySurface) {
+ if(isProxySurface) {
((ProxySurface)surface).destroyNotify();
}
}
@@ -197,25 +214,34 @@ public abstract class GLDrawableImpl implements GLDrawable {
System.err.println(getThreadName() + ": setRealized: "+getClass().getName()+" "+this.realized+" == "+realizedArg);
}
}
+
/**
- * Platform specific realization of drawable
+ * Platform specific realization of drawable
*/
protected abstract void setRealizedImpl();
- /**
- * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: <code>construct</code>, <code>destroy</code>.
+ /**
+ * Callback for special implementations, allowing
+ * <ul>
+ * <li>to associate bound context to this drawable (bound == true)
+ * or to remove such association (bound == false).</li>
+ * <li>to trigger GLContext/GLDrawable related lifecycle: <code>construct</code>, <code>destroy</code>.</li>
+ * </ul>
* <p>
- * If <code>realized</code> is <code>true</code>, the context has just been created and made current.
+ * If <code>bound</code> is <code>true</code>, the context is current and being newly associated w/ this drawable.
* </p>
* <p>
- * If <code>realized</code> is <code>false</code>, the context is still current and will be released and destroyed after this method returns.
+ * If <code>bound</code> is <code>false</code>, the context is still current and will be unbound (released and destroyed, or simply disassociated).
* </p>
* <p>
- * @see #contextMadeCurrent(GLContext, boolean)
+ * Being called by {@link GLContextImpl#associateDrawable(boolean)}.
+ * </p>
+ * @param ctx the just bounded or unbounded context
+ * @param bound if <code>true</code> create an association, otherwise remove it
*/
- protected void contextRealized(GLContext glc, boolean realized) {}
-
- /**
+ protected void associateContext(final GLContext ctx, final boolean bound) { }
+
+ /**
* Callback for special implementations, allowing GLContext to trigger GL related lifecycle: <code>makeCurrent</code>, <code>release</code>.
* <p>
* If <code>current</code> is <code>true</code>, the context has just been made current.
@@ -224,47 +250,87 @@ public abstract class GLDrawableImpl implements GLDrawable {
* If <code>current</code> is <code>false</code>, the context is still current and will be release after this method returns.
* </p>
* <p>
- * Note: Will also be called after {@link #contextRealized(GLContext, boolean) contextRealized(ctx, true)}
- * but not at context destruction, i.e. {@link #contextRealized(GLContext, boolean) contextRealized(ctx, false)}.
+ * Being called by {@link GLContextImpl#contextMadeCurrent(boolean)}.
* </p>
- * @see #contextRealized(GLContext, boolean)
- */
- protected void contextMadeCurrent(GLContext glc, boolean current) { }
-
- /**
- * Callback for special implementations, allowing to associate bound context to this drawable (bound == true)
- * or to remove such association (bound == false).
- * @param ctx the just bounded or unbounded context
- * @param bound if <code>true</code> create an association, otherwise remove it
+ * @see #associateContext(GLContext, boolean)
*/
- protected void associateContext(GLContext ctx, boolean bound) { }
-
+ protected void contextMadeCurrent(final GLContext glc, final boolean current) { }
+
/** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/
protected int getDefaultDrawFramebuffer() { return 0; }
/** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */
protected int getDefaultReadFramebuffer() { return 0; }
-
+ /** Callback for special implementations, allowing GLContext to fetch a custom default read buffer of current framebuffer. */
+ protected int getDefaultReadBuffer(final GL gl, final boolean hasDedicatedDrawableRead) {
+ if( gl.isGLES() || hasDedicatedDrawableRead || getChosenGLCapabilities().getDoubleBuffered() ) {
+ // Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+ // Note-2: ES3 only supports GL_BACK, GL_NONE or GL_COLOR_ATTACHMENT0+i
+ return GL.GL_BACK;
+ }
+ return GL.GL_FRONT ;
+ }
+
@Override
- public final synchronized boolean isRealized() {
+ public final boolean isRealized() {
return realized;
}
@Override
- public int getWidth() {
- return surface.getWidth();
+ public int getSurfaceWidth() {
+ return surface.getSurfaceWidth();
+ }
+
+ @Override
+ public int getSurfaceHeight() {
+ return surface.getSurfaceHeight();
}
@Override
- public int getHeight() {
- return surface.getHeight();
+ public boolean isGLOriented() {
+ return true;
}
- /** @see NativeSurface#lockSurface() */
+ /**
+ * {@link NativeSurface#lockSurface() Locks} the underlying windowing toolkit's {@link NativeSurface surface}.
+ * <p>
+ * <i>If</i> drawable is {@link #setRealized(boolean) realized},
+ * the {@link #getHandle() drawable handle} is valid after successfully {@link NativeSurface#lockSurface() locking}
+ * it's {@link NativeSurface surface} until being {@link #unlockSurface() unlocked}.
+ * </p>
+ * <p>
+ * In case the {@link NativeSurface surface} has changed as indicated by it's
+ * {@link NativeSurface#lockSurface() lock} result {@link NativeSurface#LOCK_SURFACE_CHANGED},
+ * the implementation is required to update this information as needed within it's implementation.
+ * </p>
+ *
+ * @see NativeSurface#lockSurface()
+ * @see #getHandle()
+ */
public final int lockSurface() throws GLException {
- return surface.lockSurface();
+ final int lockRes = surface.lockSurface();
+ if ( NativeSurface.LOCK_SURFACE_CHANGED == lockRes && realized ) {
+ // Update the drawable handle, in case the surface handle has changed.
+ final long _handle1 = getHandle();
+ destroyHandle();
+ createHandle();
+ final long _handle2 = getHandle();
+ if(DEBUG) {
+ if( _handle1 != _handle2) {
+ System.err.println(getThreadName() + ": Drawable handle changed: "+toHexString(_handle1)+" -> "+toHexString(_handle2));
+ }
+ }
+ }
+ return lockRes;
+
}
- /** @see NativeSurface#unlockSurface() */
+ /**
+ * {@link NativeSurface#unlockSurface() Unlocks} the underlying windowing toolkit {@link NativeSurface surface},
+ * which may render the {@link #getHandle() drawable handle} invalid.
+ *
+ * @see NativeSurface#unlockSurface()
+ * @see #getHandle()
+ */
public final void unlockSurface() {
surface.unlockSurface();
}
@@ -277,13 +343,11 @@ public abstract class GLDrawableImpl implements GLDrawable {
",\n\tSurface "+getNativeSurface()+"]";
}
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
- protected GLDrawableFactory factory;
- protected NativeSurface surface;
- protected GLCapabilitiesImmutable requestedCapabilities;
+ protected final GLDrawableFactory factory;
+ protected final NativeSurface surface;
+ protected final GLCapabilitiesImmutable requestedCapabilities;
// Indicates whether the surface (if an onscreen context) has been
// realized. Plausibly, before the surface is realized the JAWT
@@ -295,6 +359,6 @@ public abstract class GLDrawableImpl implements GLDrawable {
// result of calling show() on the main thread. To work around this
// we prevent any JAWT or OpenGL operations from being done until
// addNotify() is called on the surface.
- protected boolean realized;
+ protected volatile boolean realized;
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java
index 4c82fc2b3..39de3200d 100644
--- a/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl;
import com.jogamp.common.os.DynamicLibraryBundle;
@@ -36,17 +36,31 @@ public abstract class GLDynamicLibraryBundleInfo implements DynamicLibraryBundle
protected GLDynamicLibraryBundleInfo() {
}
- /** default **/
+ /**
+ * Returns <code>true</code>,
+ * since we might load a desktop GL library and allow symbol access to subsequent libs.
+ * <p>
+ * This respects old DRI requirements:
+ * <pre>
+ * http://dri.sourceforge.net/doc/DRIuserguide.html
+ * </pre>
+ * </p>
+ */
@Override
- public boolean shallLinkGlobal() { return false; }
+ public final boolean shallLinkGlobal() { return true; }
- /** default **/
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns <code>false</code>.
+ * </p>
+ */
@Override
public boolean shallLookupGlobal() { return false; }
@Override
- public RunnableExecutor getLibLoaderExecutor() {
+ public final RunnableExecutor getLibLoaderExecutor() {
return DynamicLibraryBundle.getDefaultRunnableExecutor();
- }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java b/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java
index d2dac8148..95e13e26a 100644
--- a/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,23 +20,23 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl;
import com.jogamp.common.os.DynamicLibraryBundle;
public class GLDynamicLookupHelper extends DynamicLibraryBundle {
- public GLDynamicLookupHelper(GLDynamicLibraryBundleInfo info) {
+ public GLDynamicLookupHelper(final GLDynamicLibraryBundleInfo info) {
super(info);
}
- public GLDynamicLibraryBundleInfo getGLBundleInfo() { return (GLDynamicLibraryBundleInfo) getBundleInfo(); }
+ public final GLDynamicLibraryBundleInfo getGLBundleInfo() { return (GLDynamicLibraryBundleInfo) getBundleInfo(); }
/** NOP per default */
public boolean loadGLULibrary() { return false; }
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index de45466f3..991a351e6 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -11,11 +11,15 @@ import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLFBODrawable;
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.VersionUtil;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.GLRendererQuirks;
import com.jogamp.opengl.FBObject.Attachment;
import com.jogamp.opengl.FBObject.Colorbuffer;
import com.jogamp.opengl.FBObject.TextureAttachment;
+import com.jogamp.opengl.JoglVersion;
/**
* {@link FBObject} offscreen GLDrawable implementation, i.e. {@link GLFBODrawable}.
@@ -24,73 +28,172 @@ import com.jogamp.opengl.FBObject.TextureAttachment;
* to initialize the {@link FBObject} instance.
* </p>
* <p>
- * It utilizes the context current hook {@link #contextMadeCurrent(GLContext, boolean) contextMadeCurrent(context, true)}
+ * It utilizes the context current hook {@link #contextMadeCurrent(GLContext, boolean) contextMadeCurrent(context, true)}
* to {@link FBObject#bind(GL) bind} the FBO.
* </p>
* See {@link GLFBODrawable} for double buffering details.
- *
+ *
* @see GLDrawableImpl#contextRealized(GLContext, boolean)
* @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean)
* @see GLDrawableImpl#getDefaultDrawFramebuffer()
* @see GLDrawableImpl#getDefaultReadFramebuffer()
*/
public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
- protected static final boolean DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject");
-
+ protected static final boolean DEBUG;
+ protected static final boolean DEBUG_SWAP;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject");
+ DEBUG_SWAP = PropertyAccess.isPropertyDefined("jogl.debug.FBObject.Swap", true);
+ }
+
private final GLDrawableImpl parent;
-
+ private GLCapabilitiesImmutable origParentChosenCaps;
+
private boolean initialized;
+ private int maxSamples;
+ private int fboModeBits;
private int texUnit;
private int samples;
-
+ private boolean fboResetQuirk;
+
private FBObject[] fbos;
private int fboIBack; // points to GL_BACK buffer
private int fboIFront; // points to GL_FRONT buffer
- private FBObject pendingFBOReset = null;
+ private int pendingFBOReset = -1;
+ /** Indicates whether the FBO is bound. */
private boolean fboBound;
- private static final int bufferCount = 2; // number of FBOs for double buffering. TODO: Possible to configure!
-
+ /** Indicates whether the FBO is swapped, resets to false after makeCurrent -> contextMadeCurrent. */
+ private boolean fboSwapped;
+
+ /** dump fboResetQuirk info only once pre ClassLoader and only in DEBUG mode */
+ private static volatile boolean resetQuirkInfoDumped = false;
+
+ /** number of FBOs for double buffering. TODO: Possible to configure! */
+ private static final int bufferCount = 2;
+
// private DoubleBufferMode doubleBufferMode; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
-
+
private SwapBufferContext swapBufferContext;
-
+
public static interface SwapBufferContext {
public void swapBuffers(boolean doubleBuffered);
}
-
- protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, NativeSurface surface,
- GLCapabilitiesImmutable fboCaps, int textureUnit) {
- super(factory, surface, false);
+
+ /**
+ * @param factory
+ * @param parent
+ * @param surface
+ * @param fboCaps the requested FBO capabilities
+ * @param textureUnit
+ */
+ protected GLFBODrawableImpl(final GLDrawableFactoryImpl factory, final GLDrawableImpl parent, final NativeSurface surface,
+ final GLCapabilitiesImmutable fboCaps, final int textureUnit) {
+ super(factory, surface, fboCaps, false);
this.initialized = false;
+ this.fboModeBits = FBOMODE_USE_TEXTURE;
- // Replace the chosen caps of dummy-surface w/ it's clone and copied values of orig FBO caps request.
- // The dummy-surface has already been configured, hence value replace is OK
- // and due to cloning, the native GLCapability portion is being preserved.
- final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration();
- final GLCapabilities fboCapsNative = (GLCapabilities) msConfig.getChosenCapabilities().cloneMutable();
- fboCapsNative.copyFrom(fboCaps);
- msConfig.setChosenCapabilities(fboCapsNative);
-
this.parent = parent;
+ this.origParentChosenCaps = getChosenGLCapabilities(); // just to avoid null, will be reset at initialize(..)
this.texUnit = textureUnit;
this.samples = fboCaps.getNumSamples();
-
- // default .. // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
- // this.doubleBufferMode = ( samples > 0 || fboCaps.getDoubleBuffered() ) ? DoubleBufferMode.FBO : DoubleBufferMode.NONE ;
-
+ this.fboResetQuirk = false;
this.swapBufferContext = null;
}
-
- private final void initialize(boolean realize, GL gl) {
+
+ private final void setupFBO(final GL gl, final int idx, final int width, final int height, final int samples,
+ final boolean useAlpha, final int depthBits, final int stencilBits,
+ final boolean useTexture, final boolean realUnbind) {
+ final FBObject fbo = new FBObject();
+ fbos[idx] = fbo;
+
+ final boolean useDepth = depthBits > 0;
+ final boolean useStencil = stencilBits > 0;
+
+ fbo.init(gl, width, height, samples);
+ if(fbo.getNumSamples() != samples) {
+ throw new InternalError("Sample number mismatch: "+samples+", fbos["+idx+"] "+fbo);
+ }
+ if(samples > 0 || !useTexture) {
+ fbo.attachColorbuffer(gl, 0, useAlpha);
+ } else {
+ fbo.attachTexture2D(gl, 0, useAlpha);
+ }
+ if( useStencil ) {
+ if( useDepth ) {
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, depthBits);
+ } else {
+ fbo.attachRenderbuffer(gl, Attachment.Type.STENCIL, stencilBits);
+ }
+ } else if( useDepth ) {
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, depthBits);
+ }
+ if(samples > 0) {
+ final FBObject ssink = new FBObject();
+ {
+ ssink.init(gl, width, height, 0);
+ if( !useTexture ) {
+ ssink.attachColorbuffer(gl, 0, useAlpha);
+ } else {
+ ssink.attachTexture2D(gl, 0, useAlpha);
+ }
+ if( useStencil ) {
+ if( useDepth ) {
+ ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, depthBits);
+ } else {
+ ssink.attachRenderbuffer(gl, Attachment.Type.STENCIL, stencilBits);
+ }
+ } else if( useDepth ) {
+ ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, depthBits);
+ }
+ }
+ fbo.setSamplingSink(ssink);
+ fbo.resetSamplingSink(gl); // validate
+ }
+ // Clear the framebuffer allowing defined state not exposing previous content.
+ // Also remedy for Bug 1020, i.e. OSX/Nvidia's FBO needs to be cleared before blitting,
+ // otherwise first MSAA frame lacks antialiasing.
+ fbo.bind(gl);
+ if( useDepth ) {
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ } else {
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ }
+ if( realUnbind ) {
+ fbo.unbind(gl);
+ } else {
+ fbo.markUnbound();
+ }
+ }
+
+ private final void initialize(final boolean realize, final GL gl) {
+ if( !initialized && !realize ) {
+ if( DEBUG ) {
+ System.err.println("GLFBODrawableImpl.initialize(): WARNING - Already unrealized!");
+ Thread.dumpStack();
+ }
+ return; // NOP, no exception for de-init twice or no init!
+ }
+ if( initialized == realize ) {
+ throw new IllegalStateException("initialize already in state "+realize+": "+this);
+ }
if(realize) {
- final int maxSamples = gl.getMaxRenderbufferSamples();
- samples = samples <= maxSamples ? samples : maxSamples;
-
- final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
+ final GLCapabilities chosenFBOCaps = (GLCapabilities) getChosenGLCapabilities(); // cloned at setRealized(true)
+
+ maxSamples = gl.getMaxRenderbufferSamples(); // if > 0 implies fullFBOSupport
+ {
+ final int newSamples = samples <= maxSamples ? samples : maxSamples;
+ if(DEBUG) {
+ System.err.println("GLFBODrawableImpl.initialize(): samples "+samples+" -> "+newSamples+"/"+maxSamples);
+ }
+ samples = newSamples;
+ }
+
final int fbosN;
if(samples > 0) {
fbosN = 1;
- } else if( caps.getDoubleBuffered() ) {
+ } else if( chosenFBOCaps.getDoubleBuffered() ) {
fbosN = bufferCount;
} else {
fbosN = 1;
@@ -99,67 +202,86 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
fbos = new FBObject[fbosN];
fboIBack = 0; // head
fboIFront = fbos.length - 1; // tail
-
+
+ if( 0 == ( FBOMODE_USE_TEXTURE & fboModeBits ) &&
+ gl.getContext().hasRendererQuirk(GLRendererQuirks.BuggyColorRenderbuffer) ) {
+ // GLRendererQuirks.BuggyColorRenderbuffer also disables MSAA, i.e. full FBO support
+ fboModeBits |= FBOMODE_USE_TEXTURE;
+ }
+
+ final boolean useTexture = 0 != ( FBOMODE_USE_TEXTURE & fboModeBits );
+ final boolean useAlpha = chosenFBOCaps.getAlphaBits() > 0;
+ final int width = getSurfaceWidth();
+ final int height = getSurfaceHeight();
+
for(int i=0; i<fbosN; i++) {
- fbos[i] = new FBObject();
- fbos[i].reset(gl, getWidth(), getHeight(), samples);
- if(fbos[i].getNumSamples() != samples) {
- throw new InternalError("Sample number mismatch: "+samples+", fbos["+i+"] "+fbos[i]);
- }
- if(samples > 0) {
- fbos[i].attachColorbuffer(gl, 0, caps.getAlphaBits()>0);
- } else {
- fbos[i].attachTexture2D(gl, 0, caps.getAlphaBits()>0);
- }
- if( caps.getStencilBits() > 0 ) {
- fbos[i].attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24);
- } else {
- fbos[i].attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
- }
+ setupFBO(gl, i, width, height, samples, useAlpha,
+ chosenFBOCaps.getDepthBits(), chosenFBOCaps.getStencilBits(), useTexture, fbosN-1==i);
}
- fbos[fboIFront].syncFramebuffer(gl);
- fboBound = false;
- final GLCapabilities fboCapsNative = (GLCapabilities) surface.getGraphicsConfiguration().getChosenCapabilities();
- fbos[0].formatToGLCapabilities(fboCapsNative);
- fboCapsNative.setDoubleBuffered( fboCapsNative.getDoubleBuffered() || samples > 0 );
-
- initialized = true;
+ fbos[0].formatToGLCapabilities(chosenFBOCaps);
+ chosenFBOCaps.setDoubleBuffered( chosenFBOCaps.getDoubleBuffered() || samples > 0 );
} else {
- initialized = false;
-
for(int i=0; i<fbos.length; i++) {
fbos[i].destroy(gl);
}
fbos=null;
- fboBound = false;
- pendingFBOReset = null;
}
+ fboBound = false;
+ fboSwapped = false;
+ pendingFBOReset = -1;
+ initialized = realize;
+
if(DEBUG) {
System.err.println("GLFBODrawableImpl.initialize("+realize+"): "+this);
Thread.dumpStack();
}
}
-
- public final void setSwapBufferContext(SwapBufferContext sbc) {
+
+ public final void setSwapBufferContext(final SwapBufferContext sbc) {
swapBufferContext = sbc;
}
- private static final void reset(GL gl, FBObject fbo, int fboIdx, int width, int height, int samples) {
- fbo.reset(gl, width, height, samples); // implicit glClear(..)
- if(fbo.getNumSamples() != samples) {
- throw new InternalError("Sample number mismatch: "+samples+", fbos["+fboIdx+"] "+fbo);
- }
+ private final void reset(final GL gl, final int idx, final int width, final int height, final int samples,
+ final boolean useAlpha, final int depthBits, final int stencilBits) {
+ if( !fboResetQuirk ) {
+ try {
+ fbos[idx].reset(gl, width, height, samples);
+ if(fbos[idx].getNumSamples() != samples) {
+ throw new InternalError("Sample number mismatch: "+samples+", fbos["+idx+"] "+fbos[idx]);
+ }
+ return;
+ } catch (final GLException e) {
+ fboResetQuirk = true;
+ if( DEBUG ) {
+ if(!resetQuirkInfoDumped) {
+ resetQuirkInfoDumped = true;
+ System.err.println("GLFBODrawable: FBO Reset failed: "+e.getMessage());
+ System.err.println("GLFBODrawable: Enabling FBOResetQuirk, due to GL driver bug.");
+ final JoglVersion joglVersion = JoglVersion.getInstance();
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println(joglVersion.toString());
+ System.err.println(JoglVersion.getGLInfo(gl, null));
+ e.printStackTrace();
+ }
+ }
+ // 'fallthrough' intended
+ }
+ }
+ // resetQuirk fallback
+ fbos[idx].destroy(gl);
+ final boolean useTexture = 0 != ( FBOMODE_USE_TEXTURE & fboModeBits );
+ setupFBO(gl, idx, width, height, samples, useAlpha, depthBits, stencilBits, useTexture, true);
}
-
- private final void reset(GL gl, int newSamples) throws GLException {
+
+ private final void reset(final GL gl, int newSamples) throws GLException {
if(!initialized) {
// NOP if not yet initializes
return;
}
-
+
final GLContext curContext = GLContext.getCurrent();
final GLContext ourContext = gl.getContext();
- final boolean ctxSwitch = null != curContext && curContext != ourContext;
+ final boolean ctxSwitch = null != curContext && curContext != ourContext;
if(DEBUG) {
System.err.println("GLFBODrawableImpl.reset(newSamples "+newSamples+"): BEGIN - ctxSwitch "+ctxSwitch+", "+this);
Thread.dumpStack();
@@ -167,36 +289,38 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
Throwable tFBO = null;
Throwable tGL = null;
ourContext.makeCurrent();
+ gl.glFinish(); // sync GL command stream
fboBound = false; // clear bound-flag immediatly, caused by contextMadeCurrent(..) - otherwise we would swap @ release
- try {
- final int maxSamples = gl.getMaxRenderbufferSamples();
+ fboSwapped = false;
+ try {
newSamples = newSamples <= maxSamples ? newSamples : maxSamples;
-
+
if(0==samples && 0<newSamples || 0<samples && 0==newSamples) {
// MSAA on/off switch
if(DEBUG) {
- System.err.println("GLFBODrawableImpl.reset(): samples [on/off] reconfig: "+samples+" -> "+newSamples);
+ System.err.println("GLFBODrawableImpl.reset(): samples [on/off] reconfig: "+samples+" -> "+newSamples+"/"+maxSamples);
}
initialize(false, gl);
samples = newSamples;
initialize(true, gl);
- } else {
+ } else {
if(DEBUG) {
- System.err.println("GLFBODrawableImpl.reset(): simple reconfig: "+samples+" -> "+newSamples);
+ System.err.println("GLFBODrawableImpl.reset(): simple reconfig: "+samples+" -> "+newSamples+"/"+maxSamples);
}
- final int nWidth = getWidth();
- final int nHeight = getHeight();
+ final int nWidth = getSurfaceWidth();
+ final int nHeight = getSurfaceHeight();
samples = newSamples;
- pendingFBOReset = ( 1 < fbos.length ) ? fbos[fboIFront] : null; // pending-front reset only w/ double buffering (or zero samples)
+ pendingFBOReset = ( 1 < fbos.length ) ? fboIFront : -1; // pending-front reset only w/ double buffering (or zero samples)
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
for(int i=0; i<fbos.length; i++) {
- if(1 == fbos.length || fboIFront != i) {
- reset(gl, fbos[i], i, nWidth, nHeight, samples);
+ if( pendingFBOReset != i ) {
+ reset(gl, i, nWidth, nHeight, samples, caps.getAlphaBits()>0, caps.getDepthBits(), caps.getStencilBits());
}
}
final GLCapabilities fboCapsNative = (GLCapabilities) surface.getGraphicsConfiguration().getChosenCapabilities();
fbos[0].formatToGLCapabilities(fboCapsNative);
}
- } catch (Throwable t) {
+ } catch (final Throwable t) {
tFBO = t;
} finally {
try {
@@ -204,27 +328,27 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
if(ctxSwitch) {
curContext.makeCurrent();
}
- } catch (Throwable t) {
+ } catch (final Throwable t) {
tGL = t;
}
}
if(null != tFBO) {
- throw new GLException("GLFBODrawableImpl.reset(..) FBObject.reset(..) exception", tFBO);
+ throw GLException.newGLException(tFBO);
}
if(null != tGL) {
- throw new GLException("GLFBODrawableImpl.reset(..) GLContext.release() exception", tGL);
+ throw GLException.newGLException(tGL);
}
if(DEBUG) {
System.err.println("GLFBODrawableImpl.reset(newSamples "+newSamples+"): END "+this);
}
}
-
+
//
// GLDrawable
//
-
+
@Override
- public final GLContext createContext(GLContext shareWith) {
+ public final GLContext createContext(final GLContext shareWith) {
final GLContext ctx = parent.createContext(shareWith);
ctx.setGLDrawable(this, false);
return ctx;
@@ -233,7 +357,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
//
// GLDrawableImpl
//
-
+
@Override
public final GLDynamicLookupHelper getGLDynamicLookupHelper() {
return parent.getGLDynamicLookupHelper();
@@ -241,144 +365,198 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
@Override
protected final int getDefaultDrawFramebuffer() { return initialized ? fbos[fboIBack].getWriteFramebuffer() : 0; }
-
+
@Override
protected final int getDefaultReadFramebuffer() { return initialized ? fbos[fboIFront].getReadFramebuffer() : 0; }
@Override
+ protected final int getDefaultReadBuffer(final GL gl, final boolean hasDedicatedDrawableRead) {
+ return initialized ? fbos[fboIFront].getDefaultReadBuffer() : GL.GL_COLOR_ATTACHMENT0 ;
+ }
+
+ @Override
protected final void setRealizedImpl() {
- parent.setRealized(realized);
+ final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration();
+ if(realized) {
+ parent.setRealized(true);
+ origParentChosenCaps = (GLCapabilitiesImmutable) msConfig.getChosenCapabilities();
+ final GLCapabilities chosenFBOCaps = (GLCapabilities) origParentChosenCaps.cloneMutable(); // incl. <Type>GLCapabilities, e.g. X11GLCapabilities
+ chosenFBOCaps.copyFrom(getRequestedGLCapabilities()); // copy user values
+ msConfig.setChosenCapabilities(chosenFBOCaps);
+ } else {
+ msConfig.setChosenCapabilities(origParentChosenCaps);
+ parent.setRealized(false);
+ }
}
-
+
@Override
- protected final void contextRealized(GLContext glc, boolean realized) {
- initialize(realized, glc.getGL());
+ protected void associateContext(final GLContext glc, final boolean bound) {
+ initialize(bound, glc.getGL());
}
-
+
@Override
- protected final void contextMadeCurrent(GLContext glc, boolean current) {
+ protected final void contextMadeCurrent(final GLContext glc, final boolean current) {
final GL gl = glc.getGL();
if(current) {
+ if( !initialized ) {
+ throw new GLException("Not initialized: "+this);
+ }
fbos[fboIBack].bind(gl);
fboBound = true;
- } else {
- if(fboBound) {
- swapFBOImpl(glc);
- fboBound=false;
- if(DEBUG) {
- System.err.println("Post FBO swap(@release): done");
- }
+ fboSwapped = false;
+ } else if( fboBound && !fboSwapped ) {
+ swapFBOImpl(glc);
+ swapFBOImplPost(glc);
+ fboBound=false;
+ fboSwapped=true;
+ if(DEBUG_SWAP) {
+ System.err.println("Post FBO swap(@release): done");
}
}
}
-
+
@Override
- protected void swapBuffersImpl(boolean doubleBuffered) {
+ protected void swapBuffersImpl(final boolean doubleBuffered) {
final GLContext ctx = GLContext.getCurrent();
- if(null!=ctx && ctx.getGLDrawable()==this) {
- if(fboBound) {
- swapFBOImpl(ctx);
- fboBound=false;
- if(DEBUG) {
- System.err.println("Post FBO swap(@swap): done");
- }
+ boolean doPostSwap;
+ if( null != ctx && ctx.getGLDrawable() == this && fboBound ) {
+ swapFBOImpl(ctx);
+ doPostSwap = true;
+ fboSwapped = true;
+ if(DEBUG_SWAP) {
+ System.err.println("Post FBO swap(@swap): done");
}
+ } else {
+ doPostSwap = false;
}
- if(null != swapBufferContext) {
+ if( null != swapBufferContext ) {
swapBufferContext.swapBuffers(doubleBuffered);
}
+ if(doPostSwap) {
+ swapFBOImplPost(ctx);
+ }
+ }
+
+ private final void swapFBOImplPost(final GLContext glc) {
+ // Safely reset the previous front FBO - after completing propagating swap
+ if(0 <= pendingFBOReset) {
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
+ reset(glc.getGL(), pendingFBOReset, getSurfaceWidth(), getSurfaceHeight(), samples,
+ caps.getAlphaBits()>0, caps.getDepthBits(), caps.getStencilBits());
+ pendingFBOReset = -1;
+ }
}
-
- private final void swapFBOImpl(GLContext glc) {
+
+ private final void swapFBOImpl(final GLContext glc) {
final GL gl = glc.getGL();
fbos[fboIBack].markUnbound(); // fast path, use(gl,..) is called below
- // Safely reset the previous front FBO
- if(null != pendingFBOReset) {
- reset(gl, pendingFBOReset, fboIFront, getWidth(), getHeight(), samples);
- pendingFBOReset = null;
- }
-
if(DEBUG) {
- int _fboIFront = ( fboIFront + 1 ) % fbos.length;
+ final int _fboIFront = ( fboIFront + 1 ) % fbos.length;
if(_fboIFront != fboIBack) { throw new InternalError("XXX: "+_fboIFront+"!="+fboIBack); }
}
fboIFront = fboIBack;
fboIBack = ( fboIBack + 1 ) % fbos.length;
-
+
final Colorbuffer colorbuffer = samples > 0 ? fbos[fboIFront].getSamplingSink() : fbos[fboIFront].getColorbuffer(0);
+ if(null == colorbuffer) {
+ throw new GLException("Front colorbuffer is null: samples "+samples+", "+this);
+ }
final TextureAttachment texAttachment;
- if(colorbuffer instanceof TextureAttachment) {
- texAttachment = (TextureAttachment) colorbuffer;
+ if( colorbuffer.isTextureAttachment() ) {
+ texAttachment = colorbuffer.getTextureAttachment();
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit);
} else {
- if(null == colorbuffer) {
- throw new GLException("Front colorbuffer is null: samples "+samples+", "+this);
- } else {
- throw new GLException("Front colorbuffer is not a texture: "+colorbuffer.getClass().getName()+": samples "+samples+", "+colorbuffer+", "+this);
- }
+ texAttachment = null;
}
- gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit);
fbos[fboIFront].use(gl, texAttachment);
-
- /* Included in above use command:
+
+ /* Included in above use command:
gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, fbos[fboIBack].getDrawFramebuffer());
gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbos[fboIFront].getReadFramebuffer());
} */
-
- if(DEBUG) {
+
+ if(DEBUG_SWAP) {
System.err.println("Post FBO swap(X): fboI back "+fboIBack+", front "+fboIFront+", num "+fbos.length);
}
}
//
// GLFBODrawable
- //
-
+ //
+
@Override
public final boolean isInitialized() {
return initialized;
}
-
+
@Override
- public final void resetSize(GL gl) throws GLException {
+ public final void setFBOMode(final int modeBits) throws IllegalStateException {
+ if( isInitialized() ) {
+ throw new IllegalStateException("Already initialized: "+this);
+ }
+ this.fboModeBits = modeBits;
+ }
+
+ @Override
+ public final int getFBOMode() {
+ return fboModeBits;
+ }
+
+ @Override
+ public final void resetSize(final GL gl) throws GLException {
reset(gl, samples);
- }
-
+ }
+
@Override
public final int getTextureUnit() { return texUnit; }
-
+
@Override
- public final void setTextureUnit(int u) { texUnit = u; }
-
+ public final void setTextureUnit(final int u) { texUnit = u; }
+
@Override
public final int getNumSamples() { return samples; }
-
+
@Override
- public void setNumSamples(GL gl, int newSamples) throws GLException {
+ public void setNumSamples(final GL gl, final int newSamples) throws GLException {
if(samples != newSamples) {
reset(gl, newSamples);
}
}
-
+
+ @Override
+ public final int setNumBuffers(final int bufferCount) throws IllegalStateException, GLException {
+ if( isInitialized() ) {
+ throw new IllegalStateException("Already initialized: "+this);
+ }
+ // FIXME: Implement
+ return GLFBODrawableImpl.bufferCount;
+ }
+
+ @Override
+ public final int getNumBuffers() {
+ return bufferCount;
+ }
+
/** // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
@Override
public final DoubleBufferMode getDoubleBufferMode() {
return doubleBufferMode;
}
-
+
@Override
public final void setDoubleBufferMode(DoubleBufferMode mode) throws GLException {
if(initialized) {
throw new GLException("Not allowed past initialization: "+this);
- }
+ }
final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
if(0 == samples && caps.getDoubleBuffered() && DoubleBufferMode.NONE != mode) {
doubleBufferMode = mode;
}
} */
-
+
@Override
- public FBObject getFBObject(int bufferName) throws IllegalArgumentException {
+ public FBObject getFBObject(final int bufferName) throws IllegalArgumentException {
if(!initialized) {
return null;
}
@@ -394,40 +572,40 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
case GL.GL_BACK:
res = fbos[fboIBack];
break;
- default:
+ default:
throw new IllegalArgumentException(illegalBufferName+toHexString(bufferName));
- }
- return res;
+ }
+ return res;
}
-
+
@Override
- public final TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException {
+ public final Colorbuffer getColorbuffer(final int bufferName) throws IllegalArgumentException {
if(!initialized) {
return null;
}
- final TextureAttachment res;
+ final Colorbuffer res;
switch(bufferName) {
case GL.GL_FRONT:
if( samples > 0 ) {
res = fbos[0].getSamplingSink();
} else {
- res = (TextureAttachment) fbos[fboIFront].getColorbuffer(0);
+ res = fbos[fboIFront].getColorbuffer(0);
}
break;
case GL.GL_BACK:
if( samples > 0 ) {
throw new IllegalArgumentException("Cannot access GL_BACK buffer of MSAA FBO: "+this);
} else {
- res = (TextureAttachment) fbos[fboIBack].getColorbuffer(0);
+ res = fbos[fboIBack].getColorbuffer(0);
}
break;
- default:
+ default:
throw new IllegalArgumentException(illegalBufferName+toHexString(bufferName));
- }
- return res;
+ }
+ return res;
}
private static final String illegalBufferName = "Only GL_FRONT and GL_BACK buffer are allowed, passed ";
-
+
@Override
public String toString() {
return getClass().getSimpleName()+"[Initialized "+initialized+", realized "+isRealized()+", texUnit "+texUnit+", samples "+samples+
@@ -437,31 +615,31 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
",\n\tfboI back "+fboIBack+", front "+fboIFront+", num "+(initialized ? fbos.length : 0)+
",\n\tFBO front read "+getDefaultReadFramebuffer()+", "+getFBObject(GL.GL_FRONT)+
",\n\tFBO back write "+getDefaultDrawFramebuffer()+", "+getFBObject(GL.GL_BACK)+
- ",\n\tSurface "+getNativeSurface()+
+ ",\n\tSurface "+surface+
"]";
}
-
+
public static class ResizeableImpl extends GLFBODrawableImpl implements GLFBODrawable.Resizeable {
- protected ResizeableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, ProxySurface surface,
- GLCapabilitiesImmutable fboCaps, int textureUnit) {
+ protected ResizeableImpl(final GLDrawableFactoryImpl factory, final GLDrawableImpl parent, final ProxySurface surface,
+ final GLCapabilitiesImmutable fboCaps, final int textureUnit) {
super(factory, parent, surface, fboCaps, textureUnit);
}
-
+
@Override
- public final void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException {
+ public final void setSurfaceSize(final GLContext context, final int newWidth, final int newHeight) throws NativeWindowException, GLException {
if(DEBUG) {
- System.err.println("GLFBODrawableImpl.ResizeableImpl setSize: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+ System.err.println("GLFBODrawableImpl.ResizeableImpl setSize: ("+getThreadName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
}
- int lockRes = lockSurface();
+ final int lockRes = lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
throw new NativeWindowException("Could not lock surface: "+this);
}
try {
- // propagate new size
+ // propagate new size
final ProxySurface ps = (ProxySurface) getNativeSurface();
final UpstreamSurfaceHook ush = ps.getUpstreamSurfaceHook();
if(ush instanceof UpstreamSurfaceHook.MutableSize) {
- ((UpstreamSurfaceHook.MutableSize)ush).setSize(newWidth, newHeight);
+ ((UpstreamSurfaceHook.MutableSize)ush).setSurfaceSize(newWidth, newHeight);
} else {
throw new InternalError("GLFBODrawableImpl.ResizableImpl's ProxySurface doesn't hold a UpstreamSurfaceHookMutableSize but "+ush.getClass().getName()+", "+ps+", ush");
}
diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationFactory.java
index 5c6b475b2..90d18eb60 100644
--- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationFactory.java
@@ -37,8 +37,8 @@ import javax.media.opengl.DefaultGLCapabilitiesChooser;
public abstract class GLGraphicsConfigurationFactory extends GraphicsConfigurationFactory {
- protected static int chooseCapabilities(CapabilitiesChooser chooser, CapabilitiesImmutable capsRequested,
- List<? extends CapabilitiesImmutable> availableCaps, int recommendedIndex) {
+ protected static int chooseCapabilities(CapabilitiesChooser chooser, final CapabilitiesImmutable capsRequested,
+ final List<? extends CapabilitiesImmutable> availableCaps, final int recommendedIndex) {
if (null == capsRequested) {
throw new NativeWindowException("Null requested capabilities");
}
@@ -69,7 +69,7 @@ public abstract class GLGraphicsConfigurationFactory extends GraphicsConfigurati
}
return chosenIndex;
}
- } catch (NativeWindowException e) {
+ } catch (final NativeWindowException e) {
if (DEBUG) {
e.printStackTrace();
}
diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
index 13c95b0dd..1fb27cfcf 100644
--- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
+++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
@@ -32,8 +32,10 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLProfile;
-import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.GLRendererQuirks;
public class GLGraphicsConfigurationUtil {
public static final String NV_coverage_sample = "NV_coverage_sample";
@@ -43,7 +45,7 @@ public class GLGraphicsConfigurationUtil {
public static final int FBO_BIT = 1 << 3; // generic bit must be mapped to native one at impl. level
public static final int ALL_BITS = WINDOW_BIT | BITMAP_BIT | PBUFFER_BIT | FBO_BIT ;
- public static final StringBuilder winAttributeBits2String(StringBuilder sb, int winattrbits) {
+ public static final StringBuilder winAttributeBits2String(StringBuilder sb, final int winattrbits) {
if(null==sb) {
sb = new StringBuilder();
}
@@ -83,12 +85,12 @@ public class GLGraphicsConfigurationUtil {
}
if(isFBO) {
winattrbits |= FBO_BIT;
- }
+ }
if(isPBuffer ){
winattrbits |= PBUFFER_BIT;
- }
+ }
if(isBitmap) {
- winattrbits |= BITMAP_BIT;
+ winattrbits |= BITMAP_BIT;
}
return winattrbits;
}
@@ -99,18 +101,17 @@ public class GLGraphicsConfigurationUtil {
/**
* @return bitmask representing the input boolean in exclusive or logic, ie only one bit will be set.
*/
- public static final int getExclusiveWinAttributeBits(boolean isOnscreen, boolean isFBO, boolean isPBuffer, boolean isBitmap) {
- int winattrbits = 0;
+ public static final int getExclusiveWinAttributeBits(final boolean isOnscreen, final boolean isFBO, final boolean isPBuffer, final boolean isBitmap) {
+ final int winattrbits;
if(isOnscreen) {
- winattrbits |= WINDOW_BIT;
+ winattrbits = WINDOW_BIT;
} else if(isFBO) {
- winattrbits |= FBO_BIT;
+ winattrbits = FBO_BIT;
} else if(isPBuffer ){
- winattrbits |= PBUFFER_BIT;
+ winattrbits = PBUFFER_BIT;
} else if(isBitmap) {
- winattrbits |= BITMAP_BIT;
- }
- if(0 == winattrbits) {
+ winattrbits = BITMAP_BIT;
+ } else {
throw new InternalError("Empty bitmask");
}
return winattrbits;
@@ -119,11 +120,11 @@ public class GLGraphicsConfigurationUtil {
/**
* @see #getExclusiveWinAttributeBits(boolean, boolean, boolean, boolean)
*/
- public static final int getExclusiveWinAttributeBits(GLCapabilitiesImmutable caps) {
+ public static final int getExclusiveWinAttributeBits(final GLCapabilitiesImmutable caps) {
return getExclusiveWinAttributeBits(caps.isOnscreen(), caps.isFBO(), caps.isPBuffer(), caps.isBitmap());
}
- public static final GLCapabilities fixWinAttribBitsAndHwAccel(AbstractGraphicsDevice device, int winattrbits, GLCapabilities caps) {
+ public static final GLCapabilities fixWinAttribBitsAndHwAccel(final AbstractGraphicsDevice device, final int winattrbits, final GLCapabilities caps) {
caps.setBitmap ( 0 != ( BITMAP_BIT & winattrbits ) );
caps.setPBuffer ( 0 != ( PBUFFER_BIT & winattrbits ) );
caps.setFBO ( 0 != ( FBO_BIT & winattrbits ) );
@@ -135,22 +136,31 @@ public class GLGraphicsConfigurationUtil {
caps.setHardwareAccelerated(false);
}
- return caps;
+ return caps;
}
-
- public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable)
- {
+
+ /**
+ * Fixes the requested {@link GLCapabilitiesImmutable} according to on- and offscreen usage.
+ * <p>
+ * No modification will be made for onscreen usage, for offscreen usage see
+ * {@link #fixOffscreenGLCapabilities(GLCapabilitiesImmutable, GLDrawableFactory, AbstractGraphicsDevice)}.
+ * </p>
+ * @param capsRequested the requested {@link GLCapabilitiesImmutable}
+ * @param factory the {@link GLDrawableFactory} used to validate the requested capabilities and later used to create the drawable.
+ * @param device the device on which the drawable will be created, maybe null for the {@link GLDrawableFactory#getDefaultDevice() default device}.
+ * @return either the given requested {@link GLCapabilitiesImmutable} instance if no modifications were required, or a modified {@link GLCapabilitiesImmutable} instance.
+ */
+ public static GLCapabilitiesImmutable fixGLCapabilities(final GLCapabilitiesImmutable capsRequested,
+ final GLDrawableFactory factory, final AbstractGraphicsDevice device) {
if( !capsRequested.isOnscreen() ) {
- return fixOffscreenGLCapabilities(capsRequested, fboAvailable, pbufferAvailable);
- } /* we maintain the offscreen mode flags in onscreen mode - else {
- return fixOnscreenGLCapabilities(capsRequested);
- } */
+ return fixOffscreenGLCapabilities(capsRequested, factory, device);
+ }
return capsRequested;
}
- public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(GLCapabilitiesImmutable capsRequested)
+ public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(final GLCapabilitiesImmutable capsRequested)
{
- if( !capsRequested.isOnscreen() || capsRequested.isFBO() || capsRequested.isPBuffer() || capsRequested.isBitmap() ) {
+ if( !capsRequested.isOnscreen() || capsRequested.isFBO() || capsRequested.isPBuffer() || capsRequested.isBitmap() ) {
// fix caps ..
final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setBitmap (false);
@@ -162,33 +172,77 @@ public class GLGraphicsConfigurationUtil {
return capsRequested;
}
- public static boolean isGLCapabilitiesOffscreenAutoSelection(GLCapabilitiesImmutable capsRequested) {
- return !capsRequested.isOnscreen() &&
- !capsRequested.isFBO() && !capsRequested.isPBuffer() && !capsRequested.isBitmap() ;
+ public static GLCapabilitiesImmutable fixOffscreenBitOnly(final GLCapabilitiesImmutable capsRequested)
+ {
+ if( capsRequested.isOnscreen() ) {
+ // fix caps ..
+ final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
+ caps2.setOnscreen(false);
+ return caps2;
+ }
+ return capsRequested;
}
- public static GLCapabilitiesImmutable fixOffscreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable) {
- final boolean auto = !capsRequested.isFBO() && !capsRequested.isPBuffer() && !capsRequested.isBitmap() ;
+ /**
+ * Fixes the requested {@link GLCapabilitiesImmutable} according to:
+ * <ul>
+ * <li>offscreen usage</li>
+ * <li>availability of FBO, PBuffer, Bitmap</li>
+ * <li>{@link GLRendererQuirks}</li>
+ * </ul>
+ * @param capsRequested the requested {@link GLCapabilitiesImmutable}
+ * @param factory the {@link GLDrawableFactory} used to validate the requested capabilities and later used to create the drawable.
+ * @param device the device on which the drawable will be created, maybe null for the {@link GLDrawableFactory#getDefaultDevice() default device}.
+ * @return either the given requested {@link GLCapabilitiesImmutable} instance if no modifications were required, or a modified {@link GLCapabilitiesImmutable} instance.
+ */
+ public static GLCapabilitiesImmutable fixOffscreenGLCapabilities(final GLCapabilitiesImmutable capsRequested,
+ final GLDrawableFactory factory, AbstractGraphicsDevice device) {
+ if(null == device) {
+ device = factory.getDefaultDevice();
+ }
+ final GLProfile glp = capsRequested.getGLProfile();
+ final boolean fboAvailable = GLContext.isFBOAvailable(device, glp);
+ final boolean pbufferAvailable = factory.canCreateGLPbuffer(device, glp);
+
+ final GLRendererQuirks glrq = factory.getRendererQuirks(device);
+ final boolean bitmapAvailable;
+ final boolean doubleBufferAvailable;
+
+ if(null != glrq) {
+ bitmapAvailable = !glrq.exist(GLRendererQuirks.NoOffscreenBitmap);
+ if( capsRequested.getDoubleBuffered() &&
+ ( capsRequested.isPBuffer() && glrq.exist(GLRendererQuirks.NoDoubleBufferedPBuffer) ) ||
+ ( capsRequested.isBitmap() && glrq.exist(GLRendererQuirks.NoDoubleBufferedBitmap) ) ) {
+ doubleBufferAvailable = false;
+ } else {
+ doubleBufferAvailable = true;
+ }
+ } else {
+ bitmapAvailable = true;
+ doubleBufferAvailable = true;
+ }
+
+ final boolean auto = !( fboAvailable && capsRequested.isFBO() ) &&
+ !( pbufferAvailable && capsRequested.isPBuffer() ) &&
+ !( bitmapAvailable && capsRequested.isBitmap() ) ;
+
+ final boolean useFBO = fboAvailable && ( auto || capsRequested.isFBO() ) ;
+ final boolean usePbuffer = !useFBO && pbufferAvailable && ( auto || capsRequested.isPBuffer() ) ;
+ final boolean useBitmap = !useFBO && !usePbuffer && bitmapAvailable && ( auto || capsRequested.isBitmap() ) ;
- final boolean requestedPBuffer = capsRequested.isPBuffer() || Platform.getOSType() == Platform.OSType.MACOS ; // no native bitmap for OSX
-
- final boolean useFBO = fboAvailable && ( auto || capsRequested.isFBO() ) ;
- final boolean usePbuffer = !useFBO && pbufferAvailable && ( auto || requestedPBuffer ) ;
- final boolean useBitmap = !useFBO && !usePbuffer && ( auto || capsRequested.isBitmap() ) ;
-
if( capsRequested.isOnscreen() ||
- useFBO != capsRequested.isFBO() ||
- usePbuffer != capsRequested.isPBuffer() ||
+ useFBO != capsRequested.isFBO() ||
+ usePbuffer != capsRequested.isPBuffer() ||
useBitmap != capsRequested.isBitmap() ||
- useBitmap && capsRequested.getDoubleBuffered() )
+ !doubleBufferAvailable && capsRequested.getDoubleBuffered() )
{
// fix caps ..
final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setOnscreen(false);
- caps2.setFBO( useFBO );
+ caps2.setFBO( useFBO );
caps2.setPBuffer( usePbuffer );
caps2.setBitmap( useBitmap );
- if( useBitmap ) {
+ if( !doubleBufferAvailable ) {
caps2.setDoubleBuffered(false);
}
return caps2;
@@ -196,11 +250,11 @@ public class GLGraphicsConfigurationUtil {
return capsRequested;
}
- public static GLCapabilitiesImmutable fixGLPBufferGLCapabilities(GLCapabilitiesImmutable capsRequested)
+ public static GLCapabilitiesImmutable fixGLPBufferGLCapabilities(final GLCapabilitiesImmutable capsRequested)
{
if( capsRequested.isOnscreen() ||
- !capsRequested.isPBuffer() ||
- capsRequested.isFBO() )
+ !capsRequested.isPBuffer() ||
+ capsRequested.isFBO() )
{
// fix caps ..
final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
@@ -214,7 +268,7 @@ public class GLGraphicsConfigurationUtil {
}
/** Fix opaque setting while preserve alpha bits */
- public static GLCapabilities fixOpaqueGLCapabilities(GLCapabilities capsRequested, boolean isOpaque)
+ public static GLCapabilities fixOpaqueGLCapabilities(final GLCapabilities capsRequested, final boolean isOpaque)
{
if( capsRequested.isBackgroundOpaque() != isOpaque) {
final int alphaBits = capsRequested.getAlphaBits();
@@ -223,9 +277,9 @@ public class GLGraphicsConfigurationUtil {
}
return capsRequested;
}
-
+
/** Fix double buffered setting */
- public static GLCapabilitiesImmutable fixDoubleBufferedGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean doubleBuffered)
+ public static GLCapabilitiesImmutable fixDoubleBufferedGLCapabilities(final GLCapabilitiesImmutable capsRequested, final boolean doubleBuffered)
{
if( capsRequested.getDoubleBuffered() != doubleBuffered) {
final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
@@ -234,4 +288,45 @@ public class GLGraphicsConfigurationUtil {
}
return capsRequested;
}
+
+ public static GLCapabilitiesImmutable clipRGBAGLCapabilities(final GLCapabilitiesImmutable caps, final boolean allowRGB555, final boolean allowAlpha)
+ {
+ final int iR = caps.getRedBits();
+ final int iG = caps.getGreenBits();
+ final int iB = caps.getBlueBits();
+ final int iA = caps.getAlphaBits();
+ final int oR = clipColor(iR, allowRGB555);
+ final int oG = clipColor(iG, allowRGB555);
+ final int oB = clipColor(iB, allowRGB555);
+ final int oA = ( allowAlpha && 0 < iA ) ? oR : 0 ; // align alpha to red if requested and allowed
+ if( iR != oR || iG != oG || iB != oB || iA != oA ) {
+ final GLCapabilities caps2 = (GLCapabilities) caps.cloneMutable();
+ caps2.setRedBits(oR);
+ caps2.setGreenBits(oG);
+ caps2.setBlueBits(oB);
+ caps2.setAlphaBits(oA);
+ return caps2;
+ }
+ return caps;
+ }
+
+ public static int clipColor(final int compIn, final boolean allowRGB555) {
+ final int compOut;
+ if( 5 < compIn || !allowRGB555 ) {
+ compOut = 8;
+ } else {
+ compOut = 5;
+ }
+ return compOut;
+ }
+
+ public static GLCapabilitiesImmutable fixGLProfile(final GLCapabilitiesImmutable caps, final GLProfile glp)
+ {
+ if( caps.getGLProfile() != glp ) {
+ final GLCapabilities caps2 = (GLCapabilities) caps.cloneMutable();
+ caps2.setGLProfile(glp);
+ return caps2;
+ }
+ return caps;
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
index 7701f209f..721dc7384 100644
--- a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -42,33 +42,39 @@ import com.jogamp.opengl.GLAutoDrawableDelegate;
import jogamp.opengl.GLFBODrawableImpl;
public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implements GLOffscreenAutoDrawable {
-
+
/**
- * @param drawable a valid and already realized {@link GLDrawable}
- * @param context a valid {@link GLContext}, may not be made current (created) yet.
+ * @param drawable a valid {@link GLDrawable}, may not be {@link GLDrawable#isRealized() realized} yet.
+ * @param context a valid {@link GLContext},
+ * may not have been made current (created) yet,
+ * may not be associated w/ <code>drawable<code> yet,
+ * may be <code>null</code> for lazy initialization at 1st {@link #display()}.
* @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
* @param lock optional upstream lock, may be null
*/
- public GLOffscreenAutoDrawableImpl(GLDrawable drawable, GLContext context, Object upstreamWidget, RecursiveLock lock) {
+ public GLOffscreenAutoDrawableImpl(final GLDrawable drawable, final GLContext context, final Object upstreamWidget, final RecursiveLock lock) {
super(drawable, context, upstreamWidget, true, lock);
}
-
+
@Override
- public void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException {
+ public void setSurfaceSize(final int newWidth, final int newHeight) throws NativeWindowException, GLException {
this.defaultWindowResizedOp(newWidth, newHeight);
}
-
- public static class FBOImpl extends GLOffscreenAutoDrawableImpl implements GLOffscreenAutoDrawable.FBO {
+
+ public static class FBOImpl extends GLOffscreenAutoDrawableImpl implements GLOffscreenAutoDrawable.FBO {
/**
- * @param drawable a valid and already realized {@link GLDrawable}
- * @param context a valid {@link GLContext}, may not be made current (created) yet.
+ * @param drawable a valid {@link GLDrawable}, may not be {@link GLDrawable#isRealized() realized} yet.
+ * @param context a valid {@link GLContext},
+ * may not have been made current (created) yet,
+ * may not be associated w/ <code>drawable<code> yet,
+ * may be <code>null</code> for lazy initialization
* @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
* @param lock optional upstream lock, may be null
*/
- public FBOImpl(GLFBODrawableImpl drawable, GLContext context, Object upstreamWidget, RecursiveLock lock) {
+ public FBOImpl(final GLFBODrawableImpl drawable, final GLContext context, final Object upstreamWidget, final RecursiveLock lock) {
super(drawable, context, upstreamWidget, lock);
}
-
+
@Override
public boolean isInitialized() {
return ((GLFBODrawableImpl)drawable).isInitialized();
@@ -78,9 +84,9 @@ public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implemen
public final int getTextureUnit() {
return ((GLFBODrawableImpl)drawable).getTextureUnit();
}
-
+
@Override
- public final void setTextureUnit(int unit) {
+ public final void setTextureUnit(final int unit) {
((GLFBODrawableImpl)drawable).setTextureUnit(unit);
}
@@ -88,13 +94,23 @@ public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implemen
public final int getNumSamples() {
return ((GLFBODrawableImpl)drawable).getNumSamples();
}
-
+
@Override
- public final void setNumSamples(GL gl, int newSamples) throws GLException {
+ public final void setNumSamples(final GL gl, final int newSamples) throws GLException {
((GLFBODrawableImpl)drawable).setNumSamples(gl, newSamples);
windowRepaintOp();
}
-
+
+ @Override
+ public final int setNumBuffers(final int bufferCount) throws /* IllegalStateException, */ GLException {
+ return ((GLFBODrawableImpl)drawable).setNumBuffers(bufferCount);
+ }
+
+ @Override
+ public final int getNumBuffers() {
+ return ((GLFBODrawableImpl)drawable).getNumBuffers();
+ }
+
/** // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
@Override
public DoubleBufferMode getDoubleBufferMode() {
@@ -103,21 +119,33 @@ public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implemen
@Override
public void setDoubleBufferMode(DoubleBufferMode mode) throws GLException {
- ((GLFBODrawableImpl)drawable).setDoubleBufferMode(mode);
+ ((GLFBODrawableImpl)drawable).setDoubleBufferMode(mode);
} */
-
+
@Override
- public final FBObject getFBObject(int bufferName) {
+ public final FBObject getFBObject(final int bufferName) {
return ((GLFBODrawableImpl)drawable).getFBObject(bufferName);
}
-
- public final FBObject.TextureAttachment getTextureBuffer(int bufferName) {
- return ((GLFBODrawableImpl)drawable).getTextureBuffer(bufferName);
+
+ @Override
+ public final FBObject.Colorbuffer getColorbuffer(final int bufferName) {
+ return ((GLFBODrawableImpl)drawable).getColorbuffer(bufferName);
}
@Override
- public void resetSize(GL gl) throws GLException {
+ public void resetSize(final GL gl) throws GLException {
((GLFBODrawableImpl)drawable).resetSize(gl);
- }
+ }
+
+ @Override
+ public final void setFBOMode(final int modeBits) throws IllegalStateException {
+ ((GLFBODrawableImpl)drawable).setFBOMode(modeBits);
+
+ }
+
+ @Override
+ public final int getFBOMode() {
+ return ((GLFBODrawableImpl)drawable).getFBOMode();
+ }
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
deleted file mode 100644
index b438131bc..000000000
--- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl;
-
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLPbuffer;
-
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
-
-@SuppressWarnings("deprecation")
-public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
- private int floatMode;
-
- public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContextImpl pbufferContext) {
- super(pbufferDrawable, pbufferContext, true); // drawable := pbufferDrawable, context := pbufferContext
- }
-
- //
- // pbuffer specifics
- //
-
- @Override
- public void bindTexture() {
- // Doesn't make much sense to try to do this on the event dispatch
- // thread given that it has to be called while the context is current
- context.bindPbufferToTexture();
- }
-
- @Override
- public void releaseTexture() {
- // Doesn't make much sense to try to do this on the event dispatch
- // thread given that it has to be called while the context is current
- context.releasePbufferFromTexture();
- }
-
- @Override
- public int getFloatingPointMode() {
- if (floatMode == 0) {
- throw new GLException("Pbuffer not initialized, or floating-point support not requested");
- }
- return floatMode;
- }
-
- //
- // GLDrawable delegation
- //
-
- @Override
- public final void setRealized(boolean realized) {
- }
-
- //
- // GLAutoDrawable completion
- //
- private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock
-
- @Override
- protected final RecursiveLock getLock() { return lock; }
-
- @Override
- public final Object getUpstreamWidget() {
- return null;
- }
-
- @Override
- public void destroy() {
- defaultDestroy();
- }
-
- @Override
- public GLDrawableFactory getFactory() {
- return drawable.getFactory();
- }
-
- @Override
- public final void display() {
- final RecursiveLock _lock = lock;
- _lock.lock(); // sync: context/drawable could been recreated/destroyed while animating
- try {
- if( null != context ) {
- helper.invokeGL(drawable, context, defaultDisplayAction, initAction);
- }
- } finally {
- _lock.unlock();
- }
- }
-
- @Override
- public final void swapBuffers() throws GLException {
- defaultSwapBuffers();
- }
-
- //----------------------------------------------------------------------
- // Internals only below this point
- //
-
- protected final Runnable initAction = new Runnable() {
- @Override
- public final void run() {
- floatMode = context.getFloatingPointMode();
- defaultInitAction.run();
- } };
-
-}
diff --git a/src/jogl/classes/jogamp/opengl/GLRunnableTask.java b/src/jogl/classes/jogamp/opengl/GLRunnableTask.java
index 244a3fd79..ca1c1869e 100644
--- a/src/jogl/classes/jogamp/opengl/GLRunnableTask.java
+++ b/src/jogl/classes/jogamp/opengl/GLRunnableTask.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl;
import javax.media.opengl.GLRunnable;
@@ -44,7 +44,7 @@ public class GLRunnableTask implements GLRunnable {
Throwable runnableException;
- public GLRunnableTask(GLRunnable runnable, Object notifyObject, boolean catchExceptions) {
+ public GLRunnableTask(final GLRunnable runnable, final Object notifyObject, final boolean catchExceptions) {
this.runnable = runnable ;
this.notifyObject = notifyObject ;
this.catchExceptions = catchExceptions;
@@ -52,12 +52,13 @@ public class GLRunnableTask implements GLRunnable {
isFlushed = false;
}
- public boolean run(GLAutoDrawable drawable) {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
boolean res = true;
if(null == notifyObject) {
try {
res = runnable.run(drawable);
- } catch (Throwable t) {
+ } catch (final Throwable t) {
runnableException = t;
if(catchExceptions) {
runnableException.printStackTrace();
@@ -71,7 +72,7 @@ public class GLRunnableTask implements GLRunnable {
synchronized (notifyObject) {
try {
res = runnable.run(drawable);
- } catch (Throwable t) {
+ } catch (final Throwable t) {
runnableException = t;
if(catchExceptions) {
runnableException.printStackTrace();
@@ -86,41 +87,43 @@ public class GLRunnableTask implements GLRunnable {
}
return res;
}
-
- /**
+
+ /**
* Simply flush this task and notify a waiting executor.
+ * <p>
* The executor which might have been blocked until notified
* will be unblocked and the task removed from the queue.
- *
+ * </p>
+ *
* @see #isFlushed()
* @see #isInQueue()
- */
+ */
public void flush() {
if(!isExecuted() && null != notifyObject) {
synchronized (notifyObject) {
isFlushed=true;
- notifyObject.notifyAll();
+ notifyObject.notifyAll();
}
}
}
-
+
/**
* @return !{@link #isExecuted()} && !{@link #isFlushed()}
*/
public boolean isInQueue() { return !isExecuted && !isFlushed; }
-
+
/**
* @return whether this task has been executed.
* @see #isInQueue()
*/
public boolean isExecuted() { return isExecuted; }
-
+
/**
* @return whether this task has been flushed.
* @see #isInQueue()
*/
public boolean isFlushed() { return isFlushed; }
-
+
public Throwable getThrowable() { return runnableException; }
}
diff --git a/src/jogl/classes/jogamp/opengl/GLStateTracker.java b/src/jogl/classes/jogamp/opengl/GLStateTracker.java
index 391f96aed..dc49b35f4 100644
--- a/src/jogl/classes/jogamp/opengl/GLStateTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLStateTracker.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -40,7 +40,9 @@
package jogamp.opengl;
import javax.media.opengl.*;
+
import com.jogamp.common.util.IntIntHashMap;
+
import java.nio.IntBuffer;
import java.util.ArrayList;
@@ -51,68 +53,67 @@ import java.util.ArrayList;
* Currently supported states: PixelStorei
*/
public class GLStateTracker {
-
- /** Minimum value of MAX_CLIENT_ATTRIB_STACK_DEPTH */
+
+ /** Minimum value of MAX_CLIENT_ATTRIB_STACK_DEPTH */
public static final int MIN_CLIENT_ATTRIB_STACK_DEPTH = 16;
-
- /** static size of pixel state map */
- static final int PIXEL_STATE_MAP_SIZE = 16;
+
+ /** static size of pixel state map
+ private static final int PIXEL_STATE_MAP_SIZE = 16;
+ */
/** avoid rehash of static size pixel state map */
- static final int PIXEL_STATE_MAP_CAPACITY = 32;
-
+ private static final int PIXEL_STATE_MAP_CAPACITY = 32;
+
private volatile boolean enabled = true;
private IntIntHashMap pixelStateMap;
private final ArrayList<SavedState> stack;
-
- private static class SavedState {
+
+ static class SavedState {
/**
* Empty pixel-store state
- */
+ */
private IntIntHashMap pixelStateMap;
-
+
/**
* set (client) pixel-store state, deep copy
- */
- private final void setPixelStateMap(IntIntHashMap pixelStateMap) {
+ */
+ final void setPixelStateMap(final IntIntHashMap pixelStateMap) {
this.pixelStateMap = (IntIntHashMap) pixelStateMap.clone();
}
-
+
/**
* get (client) pixel-store state, return reference
- */
- private final IntIntHashMap getPixelStateMap() { return pixelStateMap; }
-
+ */
+ final IntIntHashMap getPixelStateMap() { return pixelStateMap; }
}
-
- public GLStateTracker() {
+
+ public GLStateTracker() {
pixelStateMap = new IntIntHashMap(PIXEL_STATE_MAP_CAPACITY, 0.75f);
pixelStateMap.setKeyNotFoundValue(0xFFFFFFFF);
resetStates();
-
+
stack = new ArrayList<SavedState>(MIN_CLIENT_ATTRIB_STACK_DEPTH);
}
- public final void clearStates(boolean enable) {
- enabled = enable;
+ public final void clearStates() {
pixelStateMap.clear();
}
- public final void setEnabled(boolean on) {
- enabled = on;
+ public final void setEnabled(final boolean on) {
+ enabled = on;
}
public final boolean isEnabled() {
return enabled;
}
- /** @return true if found in our map, otherwise false,
+ /** @return true if found in our map, otherwise false,
* which forces the caller to query GL. */
- public final boolean getInt(int pname, int[] params, int params_offset) {
+ public final boolean getInt(final int pname, final int[] params, final int params_offset) {
if(enabled) {
- int value = pixelStateMap.get(pname);
+ final int value = pixelStateMap.get(pname);
if(0xFFFFFFFF != value) {
params[params_offset] = value;
return true;
@@ -121,11 +122,11 @@ public class GLStateTracker {
return false;
}
- /** @return true if found in our map, otherwise false,
+ /** @return true if found in our map, otherwise false,
* which forces the caller to query GL. */
- public final boolean getInt(int pname, IntBuffer params, int dummy) {
+ public final boolean getInt(final int pname, final IntBuffer params, final int dummy) {
if(enabled) {
- int value = pixelStateMap.get(pname);
+ final int value = pixelStateMap.get(pname);
if(0xFFFFFFFF != value) {
params.put(params.position(), value);
return true;
@@ -134,15 +135,15 @@ public class GLStateTracker {
return false;
}
- public final void setInt(int pname, int param) {
+ public final void setInt(final int pname, final int param) {
if(enabled) {
pixelStateMap.put(pname, param);
}
}
- public final void pushAttrib(int flags) {
+ public final void pushAttrib(final int flags) {
if(enabled) {
- SavedState state = new SavedState(); // empty-slot
+ final SavedState state = new SavedState(); // empty-slot
if( 0 != (flags&GL2.GL_CLIENT_PIXEL_STORE_BIT) ) {
// save client pixel-store state
state.setPixelStateMap(pixelStateMap);
@@ -156,16 +157,17 @@ public class GLStateTracker {
if(stack.isEmpty()) {
throw new GLException("stack contains no elements");
}
- SavedState state = stack.remove(stack.size()-1); // pop
-
+ final SavedState state = stack.remove(stack.size()-1); // pop
+
if(null==state) {
throw new GLException("null stack element (remaining stack size "+stack.size()+")");
}
+ final IntIntHashMap statePixelStateMap = state.getPixelStateMap();
- if ( null != state.getPixelStateMap() ) {
+ if ( null != statePixelStateMap ) {
// use pulled client pixel-store state from stack
- pixelStateMap = state.getPixelStateMap();
- } // else: empty-slot, not pushed by GL_CLIENT_PIXEL_STORE_BIT
+ pixelStateMap = statePixelStateMap;
+ } // else: empty-slot, not pushed by GL_CLIENT_PIXEL_STORE_BIT
}
}
@@ -176,20 +178,20 @@ public class GLStateTracker {
pixelStateMap.put(GL.GL_PACK_ALIGNMENT, 4);
pixelStateMap.put(GL2GL3.GL_PACK_SWAP_BYTES, GL.GL_FALSE);
pixelStateMap.put(GL2GL3.GL_PACK_LSB_FIRST, GL.GL_FALSE);
- pixelStateMap.put(GL2GL3.GL_PACK_ROW_LENGTH, 0);
- pixelStateMap.put(GL2GL3.GL_PACK_SKIP_ROWS, 0);
- pixelStateMap.put(GL2GL3.GL_PACK_SKIP_PIXELS, 0);
+ pixelStateMap.put(GL2ES3.GL_PACK_ROW_LENGTH, 0);
+ pixelStateMap.put(GL2ES3.GL_PACK_SKIP_ROWS, 0);
+ pixelStateMap.put(GL2ES3.GL_PACK_SKIP_PIXELS, 0);
pixelStateMap.put(GL2GL3.GL_PACK_IMAGE_HEIGHT, 0);
pixelStateMap.put(GL2GL3.GL_PACK_SKIP_IMAGES, 0);
pixelStateMap.put(GL.GL_UNPACK_ALIGNMENT, 4);
pixelStateMap.put(GL2GL3.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE);
pixelStateMap.put(GL2GL3.GL_UNPACK_LSB_FIRST, GL.GL_FALSE);
- pixelStateMap.put(GL2GL3.GL_UNPACK_ROW_LENGTH, 0);
- pixelStateMap.put(GL2GL3.GL_UNPACK_SKIP_ROWS, 0);
- pixelStateMap.put(GL2GL3.GL_UNPACK_SKIP_PIXELS, 0);
- pixelStateMap.put(GL2GL3.GL_UNPACK_IMAGE_HEIGHT, 0);
- pixelStateMap.put(GL2GL3.GL_UNPACK_SKIP_IMAGES, 0);
+ pixelStateMap.put(GL2ES2.GL_UNPACK_ROW_LENGTH, 0);
+ pixelStateMap.put(GL2ES2.GL_UNPACK_SKIP_ROWS, 0);
+ pixelStateMap.put(GL2ES2.GL_UNPACK_SKIP_PIXELS, 0);
+ pixelStateMap.put(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, 0);
+ pixelStateMap.put(GL2ES3.GL_UNPACK_SKIP_IMAGES, 0);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
index 5bd008f83..ddcd9626e 100644
--- a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
+++ b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
@@ -28,96 +28,103 @@
package jogamp.opengl;
-import java.util.StringTokenizer;
import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.VersionNumberString;
/**
* A class for storing and comparing OpenGL version numbers.
* This only works for desktop OpenGL at the moment.
*/
-class GLVersionNumber extends VersionNumber {
+public class GLVersionNumber extends VersionNumberString {
- protected boolean valid;
+ private final boolean valid;
- public GLVersionNumber(int majorRev, int minorRev, int subMinorRev) {
- super(majorRev, minorRev, subMinorRev);
- valid = true;
+ private GLVersionNumber(final int[] val, final int strEnd, final short state, final String versionString, final boolean valid) {
+ super(val[0], val[1], val[2], strEnd, state, versionString);
+ this.valid = valid;
}
- public GLVersionNumber(String versionString) {
- super();
- valid = false;
- try {
- if (versionString.startsWith("GL_VERSION_")) {
- StringTokenizer tok = new StringTokenizer(versionString, "_");
- tok.nextToken(); // GL_
- tok.nextToken(); // VERSION_
- if (!tok.hasMoreTokens()) {
- major = 0;
- return;
+ private static java.util.regex.Pattern getUnderscorePattern() {
+ if( null == _Pattern ) { // volatile dbl-checked-locking OK
+ synchronized( VersionNumber.class ) {
+ if( null == _Pattern ) {
+ _Pattern = getVersionNumberPattern("_");
}
- major = Integer.valueOf(tok.nextToken()).intValue();
- if (!tok.hasMoreTokens()) {
- minor = 0;
- return;
- }
- minor = Integer.valueOf(tok.nextToken()).intValue();
- if (!tok.hasMoreTokens()) {
- sub = 0;
- return;
- }
- sub = Integer.valueOf(tok.nextToken()).intValue();
- } else {
- int radix = 10;
- if (versionString.length() > 2) {
- if (Character.isDigit(versionString.charAt(0)) && versionString.charAt(1) == '.' && Character.isDigit(versionString.charAt(2))) {
- major = Character.digit(versionString.charAt(0), radix);
- minor = Character.digit(versionString.charAt(2), radix);
- // See if there's version-specific information which might
- // imply a more recent OpenGL version
- StringTokenizer tok = new StringTokenizer(versionString, " ");
- if (tok.hasMoreTokens()) {
- tok.nextToken();
- if (tok.hasMoreTokens()) {
- String token = tok.nextToken();
- int i = 0;
- while (i < token.length() && !Character.isDigit(token.charAt(i))) {
- i++;
- }
- if (i < token.length() - 2 && Character.isDigit(token.charAt(i)) && token.charAt(i + 1) == '.' && Character.isDigit(token.charAt(i + 2))) {
- int altMajor = Character.digit(token.charAt(i), radix);
- int altMinor = Character.digit(token.charAt(i + 2), radix);
- // Avoid possibly confusing situations by putting some
- // constraints on the upgrades we do to the major and
- // minor versions
- if ((altMajor == major && altMinor > minor) || altMajor == major + 1) {
- major = altMajor;
- minor = altMinor;
- }
- }
- }
- }
- }
+ }
+ }
+ return _Pattern;
+ }
+ private static volatile java.util.regex.Pattern _Pattern = null;
+
+ public static final GLVersionNumber create(final String versionString) {
+ final int[] val = new int[] { 0, 0, 0 };
+ int strEnd = 0;
+ short state = 0;
+ boolean valid = false;
+ if (versionString != null && versionString.length() > 0) {
+ try {
+ final java.util.regex.Pattern versionPattern;
+ if (versionString.startsWith("GL_VERSION_")) {
+ versionPattern = getUnderscorePattern();
+ } else {
+ versionPattern = VersionNumber.getDefaultVersionNumberPattern();
}
+ final VersionNumberString version = new VersionNumberString(versionString, versionPattern);
+ strEnd = version.endOfStringMatch();
+ val[0] = version.getMajor();
+ val[1] = version.getMinor();
+ state = (short) ( ( version.hasMajor() ? VersionNumber.HAS_MAJOR : (short)0 ) |
+ ( version.hasMinor() ? VersionNumber.HAS_MINOR : (short)0 ) );
+ valid = version.hasMajor() && version.hasMinor(); // Requires at least a defined major and minor version component!
+ } catch (final Exception e) {
+ e.printStackTrace();
+ System.err.println("Info: ExtensionAvailabilityCache: FunctionAvailabilityCache.Version.<init>: " + e);
+ val[0] = 1;
+ val[1] = 0;
}
- valid = true;
- } catch (Exception e) {
- e.printStackTrace();
- // FIXME: refactor desktop OpenGL dependencies and make this
- // class work properly for OpenGL ES
- System.err.println("Info: ExtensionAvailabilityCache: FunctionAvailabilityCache.Version.<init>: " + e);
- major = 1;
- minor = 0;
- /*
- throw (IllegalArgumentException)
- new IllegalArgumentException(
- "Illegally formatted version identifier: \"" + versionString + "\"")
- .initCause(e);
- */
}
+ return new GLVersionNumber(val, strEnd, state, versionString, valid);
}
public final boolean isValid() {
return valid;
}
+
+ /**
+ * Returns the optional vendor version at the end of the
+ * <code>GL_VERSION</code> string if exists, otherwise the {@link VersionNumberString#zeroVersion zero version} instance.
+ * <pre>
+ * 2.1 Mesa 7.0.3-rc2 -> 7.0.3 (7.0.3-rc2)
+ * 2.1 Mesa 7.12-devel (git-d6c318e) -> 7.12.0 (7.12-devel)
+ * 4.2.12171 Compatibility Profile Context 9.01.8 -> 9.1.8 (9.01.8)
+ * 4.2.12198 Compatibility Profile Context 12.102.3.0 -> 12.102.3 (12.102.3.0)
+ * 4.3.0 NVIDIA 310.32 -> 310.32 (310.32)
+ * </pre>
+ */
+ public static final VersionNumberString createVendorVersion(final String versionString) {
+ if (versionString == null || versionString.length() <= 0) {
+ return null;
+ }
+
+ // Skip the 1st GL version
+ String str;
+ {
+ final GLVersionNumber glv = create(versionString);
+ str = versionString.substring(glv.endOfStringMatch()).trim();
+ }
+
+ while ( str.length() > 0 ) {
+ final VersionNumberString version = new VersionNumberString(str, getDefaultVersionNumberPattern());
+ final int eosm = version.endOfStringMatch();
+ if( 0 < eosm ) {
+ if( version.hasMajor() && version.hasMinor() ) { // Requires at least a defined major and minor version component!
+ return version;
+ }
+ str = str.substring( eosm ).trim();
+ } else {
+ break; // no match
+ }
+ }
+ return VersionNumberString.zeroVersion;
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java
index f7d59e127..131e6f3ac 100644
--- a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java
+++ b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -67,7 +67,7 @@ public class GLWorkerThread {
private static volatile Runnable work;
// Queue of Runnables to be asynchronously invoked
private static List<Runnable> queue = new ArrayList<Runnable>();
-
+
/** Should only be called by Threading class if creation of the
GLWorkerThread was requested via the opengl.1thread system
property. <br>
@@ -86,7 +86,7 @@ public class GLWorkerThread {
thread.start();
try {
lock.wait();
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
}
}
@@ -149,7 +149,7 @@ public class GLWorkerThread {
}
}
- public static void invoke(boolean wait, Runnable runnable)
+ public static void invoke(final boolean wait, final Runnable runnable)
throws InvocationTargetException, InterruptedException {
if(wait) {
invokeAndWait(runnable);
@@ -157,14 +157,14 @@ public class GLWorkerThread {
invokeLater(runnable);
}
}
-
- public static void invokeAndWait(Runnable runnable)
+
+ public static void invokeAndWait(final Runnable runnable)
throws InvocationTargetException, InterruptedException {
if (!started) {
throw new RuntimeException(getThreadName()+": May not invokeAndWait on worker thread without starting it first");
}
- Object lockTemp = lock;
+ final Object lockTemp = lock;
if (lockTemp == null) {
return; // Terminating
}
@@ -179,19 +179,19 @@ public class GLWorkerThread {
lockTemp.notifyAll();
lockTemp.wait();
if (exception != null) {
- Throwable localException = exception;
+ final Throwable localException = exception;
exception = null;
throw new InvocationTargetException(localException);
}
}
}
- public static void invokeLater(Runnable runnable) {
+ public static void invokeLater(final Runnable runnable) {
if (!started) {
throw new RuntimeException(getThreadName()+": May not invokeLater on worker thread without starting it first");
}
- Object lockTemp = lock;
+ final Object lockTemp = lock;
if (lockTemp == null) {
return; // Terminating
}
@@ -219,11 +219,10 @@ public class GLWorkerThread {
return (Thread.currentThread() == thread);
}
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
-
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
+
static class WorkerRunnable implements Runnable {
+ @Override
public void run() {
// Notify starting thread that we're ready
synchronized (lock) {
@@ -238,7 +237,7 @@ public class GLWorkerThread {
try {
// Avoid race conditions with wanting to release contexts on this thread
lock.wait(1000);
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
}
if (GLContext.getCurrent() != null) {
@@ -246,7 +245,7 @@ public class GLWorkerThread {
break;
}
}
-
+
if (shouldTerminate) {
lock.notifyAll();
thread = null;
@@ -257,7 +256,7 @@ public class GLWorkerThread {
if (work != null) {
try {
work.run();
- } catch (Throwable t) {
+ } catch (final Throwable t) {
exception = t;
} finally {
work = null;
@@ -267,19 +266,19 @@ public class GLWorkerThread {
while (!queue.isEmpty()) {
try {
- Runnable curAsync = queue.remove(0);
+ final Runnable curAsync = queue.remove(0);
curAsync.run();
- } catch (Throwable t) {
+ } catch (final Throwable t) {
System.err.println(getThreadName()+": Exception occurred on JOGL OpenGL worker thread:");
t.printStackTrace();
}
}
// See about releasing current context
- GLContext curContext = GLContext.getCurrent();
+ final GLContext curContext = GLContext.getCurrent();
if (curContext != null &&
(curContext instanceof GLContextImpl)) {
- GLContextImpl impl = (GLContextImpl) curContext;
+ final GLContextImpl impl = (GLContextImpl) curContext;
if (impl.hasWaiters()) {
impl.release();
}
diff --git a/src/jogl/classes/jogamp/opengl/GLXExtensions.java b/src/jogl/classes/jogamp/opengl/GLXExtensions.java
new file mode 100644
index 000000000..9325c6f68
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLXExtensions.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl;
+
+/**
+ * Class holding GLX/WGL/.. extension strings, commonly used by JOGL's implementation.
+ */
+public class GLXExtensions {
+ public static final String GLX_MESA_swap_control = "GLX_MESA_swap_control";
+ public static final String GLX_SGI_swap_control = "GLX_SGI_swap_control";
+ public static final String GLX_NV_swap_group = "GLX_NV_swap_group";
+}
diff --git a/src/jogl/classes/jogamp/opengl/ListenerSyncedImplStub.java b/src/jogl/classes/jogamp/opengl/ListenerSyncedImplStub.java
index 1cde551be..12384ad1e 100644
--- a/src/jogl/classes/jogamp/opengl/ListenerSyncedImplStub.java
+++ b/src/jogl/classes/jogamp/opengl/ListenerSyncedImplStub.java
@@ -33,9 +33,9 @@ import java.util.ArrayList;
/**
* Simple locked listener implementation stub to be used for listener handler,
* synchronized on it's instance.
- *
+ *
* <p>Utilizing simple locking via synchronized.</p>
- *
+ *
* @param <E> The listener type
*/
public class ListenerSyncedImplStub<E> {
@@ -48,7 +48,7 @@ public class ListenerSyncedImplStub<E> {
public synchronized final void reset() {
listeners = new ArrayList<E>();
}
-
+
public synchronized final void destroy() {
listeners.clear();
listeners = null;
@@ -57,23 +57,23 @@ public class ListenerSyncedImplStub<E> {
public synchronized final int size() {
return listeners.size();
}
-
- public synchronized final void addListener(E listener) {
+
+ public synchronized final void addListener(final E listener) {
addListener(-1, listener);
}
- public synchronized final void addListener(int index, E listener) {
+ public synchronized final void addListener(int index, final E listener) {
if(0>index) {
index = listeners.size();
}
listeners.add(index, listener);
}
-
- public synchronized final void removeListener(E listener) {
+
+ public synchronized final void removeListener(final E listener) {
listeners.remove(listener);
}
public final ArrayList<E> getListeners() {
return listeners;
- }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/MemoryObject.java b/src/jogl/classes/jogamp/opengl/MemoryObject.java
deleted file mode 100644
index 292700701..000000000
--- a/src/jogl/classes/jogamp/opengl/MemoryObject.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package jogamp.opengl;
-
-import java.nio.ByteBuffer;
-import java.util.HashMap;
-
-/**
- *
- */
-public class MemoryObject {
- private long addr;
- private long size;
- private int hash32;
- private ByteBuffer buffer=null;
-
- public MemoryObject(long addr, long size) {
- this.addr = addr;
- this.size = size;
- this.hash32 = getHash32(addr, size);
- }
-
- public void setBuffer(ByteBuffer buffer) {
- this.buffer = buffer;
- }
-
- public ByteBuffer getBuffer() {
- return this.buffer;
- }
-
- /**
- * @return the 32bit hash value generated via {@link #getHash32(long, long)}
- */
- public int hashCode() {
- return hash32;
- }
-
- /**
- * Ignores the optional attached <code>ByteBuffer</code> intentionally.<br>
- *
- * @return true of reference is equal or <code>obj</code> is of type <code>MemoryObject</code>
- * and <code>addr</code> and <code>size</code> is equal.<br>
- */
- public boolean equals(Object obj) {
- if(this == obj) { return true; }
- if(obj instanceof MemoryObject) {
- MemoryObject m = (MemoryObject) obj;
- return addr == m.addr && size == m.size ;
- }
- return false;
- }
-
- /**
- * Generates a 32bit hash value by <code>addr</code> and <code>size</code>.<br>
- * Ignores the optional attached <code>ByteBuffer</code> intentionally.<br>
- */
- public static int getHash32(long addr, long size) {
- // avoid xor collisions of eg low/high parts
- // 31 * x == (x << 5) - x
- int hash = 31 + (int) addr ; // lo addr
- hash = ((hash << 5) - hash) + (int) ( addr >>> 32 ) ; // hi addr
- hash = ((hash << 5) - hash) + (int) size ; // lo size
- hash = ((hash << 5) - hash) + (int) ( size >>> 32 ) ; // hi size
-
- return hash;
- }
-
- /**
- * Generates a 64bit hash value by <code>addr</code> and <code>size</code>.<br>
- * Ignores the optional attached <code>ByteBuffer</code> intentionally.<br>
- */
- public static long getHash64(long addr, long size) {
- // 31 * x == (x << 5) - x
- final long hash = 31 + addr;
- return ((hash << 5) - hash) + size;
- }
-
- public String toString() {
- return "MemoryObject[addr 0x"+Long.toHexString(addr)+", size 0x"+Long.toHexString(size)+", hash32: 0x"+Integer.toHexString(hash32)+"]";
- }
-
- /**
- * @param map the identity HashMap, MemoryObject to MemoryObject
- * @param obj0 the MemoryObject
- * @return either the already mapped MemoryObject - not changing the map, or the newly mapped one.
- */
- public static MemoryObject getOrAddSafe(HashMap<MemoryObject,MemoryObject> map, MemoryObject obj0) {
- MemoryObject obj1 = map.get(obj0); // get identity (fast)
- if(null == obj1) {
- map.put(obj0, obj0);
- obj1 = obj0;
- }
- return obj1;
- }
-
-} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/ProjectFloat.java b/src/jogl/classes/jogamp/opengl/ProjectFloat.java
index ce8405f74..5921eb9a9 100644
--- a/src/jogl/classes/jogamp/opengl/ProjectFloat.java
+++ b/src/jogl/classes/jogamp/opengl/ProjectFloat.java
@@ -6,9 +6,9 @@
** this file except in compliance with the License. You may obtain a copy
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
-**
+**
** http://oss.sgi.com/projects/FreeB
-**
+**
** Note that, as provided in the License, the Software is distributed on an
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
@@ -24,13 +24,13 @@
** except that Section 2.2 and 11 are omitted. Any differences between
** the Alternative License and the SGI License are offered solely by Sun
** and not by SGI.
-**
+**
** Original Code. The Original Code is: OpenGL Sample Implementation,
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
** Copyright in any portions created by third parties is as indicated
** elsewhere herein. All Rights Reserved.
-**
+**
** Additional Notice Provisions: The application programming interfaces
** established by SGI in conjunction with the Original Code are The
** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -45,34 +45,34 @@
** $Header$
*/
-/*
+/*
* Copyright (c) 2002-2004 LWJGL Project
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
+ * modification, are permitted provided that the following conditions are
* met:
- *
- * * Redistributions of source code must retain the above copyright
+ *
+ * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * * Neither the name of 'LWJGL' nor the names of
- * its contributors may be used to endorse or promote products derived
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -80,22 +80,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2011 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -108,35 +108,33 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
package jogamp.opengl;
-import java.nio.Buffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
-import com.jogamp.common.nio.Buffers;
-import com.jogamp.opengl.FloatUtil;
+import com.jogamp.opengl.math.FloatUtil;
/**
* ProjectFloat.java
* <p>
* Created 11-jan-2004
* </p>
- *
+ *
* @author Erik Duijs
* @author Kenneth Russell
* @author Sven Gothel
*/
public class ProjectFloat {
- public static final int getRequiredFloatBufferSize() { return 2*16+2*4+3*3; }
-
+ public static final int getRequiredFloatBufferSize() { return 1*16; }
+
// Note that we have cloned parts of the implementation in order to
// support incoming Buffers. The reason for this is to avoid loading
// non-direct buffer subclasses unnecessarily, because doing so can
@@ -145,266 +143,40 @@ public class ProjectFloat {
// simpler) to simply have the array-based entry points delegate to
// the versions taking Buffers by wrapping the arrays.
- // Array-based implementation
- private final float[] matrix = new float[16];
- private final float[][] tempInvertMatrix = new float[4][4];
-
- private final float[] in = new float[4];
- private final float[] out = new float[4];
-
- // Buffer-based implementation
- private FloatBuffer matrixBuf;
- private FloatBuffer tempInvertMatrixBuf;
-
- private FloatBuffer inBuf;
- private FloatBuffer outBuf;
-
- private FloatBuffer forwardBuf;
- private FloatBuffer sideBuf;
- private FloatBuffer upBuf;
+ private final float[] mat4Tmp1 = new float[16];
+ private final float[] mat4Tmp2 = new float[16];
+ private final float[] mat4Tmp3 = new float[16];
public ProjectFloat() {
- this(false);
- }
-
- public ProjectFloat(boolean useBackingArray) {
- this(useBackingArray ? null : Buffers.newDirectByteBuffer(getRequiredFloatBufferSize() * Buffers.SIZEOF_FLOAT),
- useBackingArray ? new float[getRequiredFloatBufferSize()] : null,
- 0);
- }
-
- /**
- * @param floatBuffer source buffer, may be ByteBuffer (recommended) or FloatBuffer or <code>null</code>.
- * If used, shall be &ge; {@link #getRequiredFloatBufferSize()} + floatOffset.
- * Buffer's position is ignored and floatPos is being used.
- * @param floatArray source float array or <code>null</code>.
- * If used, size shall be &ge; {@link #getRequiredFloatBufferSize()} + floatOffset.
- * @param floatOffset Offset for either of the given sources (buffer or array)
- */
- public ProjectFloat(Buffer floatBuffer, float[] floatArray, int floatOffset) {
- int floatPos = floatOffset;
- int floatSize = 16;
- matrixBuf = Buffers.slice2Float(floatBuffer, floatArray, floatPos, floatSize);
- floatPos += floatSize;
- tempInvertMatrixBuf = Buffers.slice2Float(floatBuffer, floatArray, floatPos, floatSize);
- floatPos += floatSize;
- floatSize = 4;
- inBuf = Buffers.slice2Float(floatBuffer, floatArray, floatPos, floatSize);
- floatPos += floatSize;
- outBuf = Buffers.slice2Float(floatBuffer, floatArray, floatPos, floatSize);
- floatPos += floatSize;
- floatSize = 3;
- forwardBuf = Buffers.slice2Float(floatBuffer, floatArray, floatPos, floatSize);
- floatPos += floatSize;
- sideBuf = Buffers.slice2Float(floatBuffer, floatArray, floatPos, floatSize);
- floatPos += floatSize;
- upBuf = Buffers.slice2Float(floatBuffer, floatArray, floatPos, floatSize);
- }
-
- public void destroy() {
- matrixBuf = null;
- tempInvertMatrixBuf = null;
- inBuf = null;
- outBuf = null;
- forwardBuf = null;
- sideBuf = null;
- upBuf = null;
- }
-
- /**
- * @param src
- * @param srcOffset
- * @param inverse
- * @param inverseOffset
- * @return
- */
- public boolean gluInvertMatrixf(float[] src, int srcOffset, float[] inverse, int inverseOffset) {
- int i, j, k, swap;
- float t;
- float[][] temp = tempInvertMatrix;
-
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- temp[i][j] = src[i*4+j+srcOffset];
- }
- }
- FloatUtil.makeIdentityf(inverse, inverseOffset);
-
- for (i = 0; i < 4; i++) {
- //
- // Look for largest element in column
- //
- swap = i;
- for (j = i + 1; j < 4; j++) {
- if (Math.abs(temp[j][i]) > Math.abs(temp[i][i])) {
- swap = j;
- }
- }
-
- if (swap != i) {
- //
- // Swap rows.
- //
- for (k = 0; k < 4; k++) {
- t = temp[i][k];
- temp[i][k] = temp[swap][k];
- temp[swap][k] = t;
-
- t = inverse[i*4+k+inverseOffset];
- inverse[i*4+k+inverseOffset] = inverse[swap*4+k+inverseOffset];
- inverse[swap*4+k+inverseOffset] = t;
- }
- }
-
- if (temp[i][i] == 0) {
- //
- // No non-zero pivot. The matrix is singular, which shouldn't
- // happen. This means the user gave us a bad matrix.
- //
- return false;
- }
-
- t = temp[i][i];
- for (k = 0; k < 4; k++) {
- temp[i][k] /= t;
- inverse[i*4+k+inverseOffset] /= t;
- }
- for (j = 0; j < 4; j++) {
- if (j != i) {
- t = temp[j][i];
- for (k = 0; k < 4; k++) {
- temp[j][k] -= temp[i][k] * t;
- inverse[j*4+k+inverseOffset] -= inverse[i*4+k+inverseOffset]*t;
- }
- }
- }
- }
- return true;
- }
-
- /**
- * @param src
- * @param inverse
- *
- * @return
- */
- public boolean gluInvertMatrixf(FloatBuffer src, FloatBuffer inverse) {
- int i, j, k, swap;
- float t;
-
- int srcPos = src.position();
- int invPos = inverse.position();
-
- FloatBuffer temp = tempInvertMatrixBuf;
-
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- temp.put(i*4+j, src.get(i*4+j + srcPos));
- }
- }
- FloatUtil.makeIdentityf(inverse);
-
- for (i = 0; i < 4; i++) {
- //
- // Look for largest element in column
- //
- swap = i;
- for (j = i + 1; j < 4; j++) {
- if (Math.abs(temp.get(j*4+i)) > Math.abs(temp.get(i*4+i))) {
- swap = j;
- }
- }
-
- if (swap != i) {
- //
- // Swap rows.
- //
- for (k = 0; k < 4; k++) {
- t = temp.get(i*4+k);
- temp.put(i*4+k, temp.get(swap*4+k));
- temp.put(swap*4+k, t);
-
- t = inverse.get(i*4+k + invPos);
- inverse.put(i*4+k + invPos, inverse.get(swap*4+k + invPos));
- inverse.put(swap*4+k + invPos, t);
- }
- }
-
- if (temp.get(i*4+i) == 0) {
- //
- // No non-zero pivot. The matrix is singular, which shouldn't
- // happen. This means the user gave us a bad matrix.
- //
- return false;
- }
-
- t = temp.get(i*4+i);
- for (k = 0; k < 4; k++) {
- temp.put(i*4+k, temp.get(i*4+k) / t);
- inverse.put(i*4+k + invPos, inverse.get(i*4+k + invPos) / t);
- }
- for (j = 0; j < 4; j++) {
- if (j != i) {
- t = temp.get(j*4+i);
- for (k = 0; k < 4; k++) {
- temp.put(j*4+k, temp.get(j*4+k) - temp.get(i*4+k) * t);
- inverse.put(j*4+k + invPos, inverse.get(j*4+k + invPos) - inverse.get(i*4+k + invPos) * t);
- }
- }
- }
- }
- return true;
}
-
/**
* Method gluOrtho2D.
- *
+ *
* @param left
* @param right
* @param bottom
* @param top
*/
- public void gluOrtho2D(GLMatrixFunc gl, float left, float right, float bottom, float top) {
+ public void gluOrtho2D(final GLMatrixFunc gl, final float left, final float right, final float bottom, final float top) {
gl.glOrthof(left, right, bottom, top, -1, 1);
}
/**
* Method gluPerspective.
- *
- * @param fovy
+ *
+ * @param fovy_deg fov angle in degrees
* @param aspect
* @param zNear
* @param zFar
*/
- public void gluPerspective(GLMatrixFunc gl, float fovy, float aspect, float zNear, float zFar) {
- float sine, cotangent, deltaZ;
- float radians = fovy / 2 * (float) Math.PI / 180;
-
- deltaZ = zFar - zNear;
- sine = (float) Math.sin(radians);
-
- if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
- return;
- }
-
- cotangent = (float) Math.cos(radians) / sine;
-
- FloatUtil.makeIdentityf(matrixBuf);
-
- matrixBuf.put(0 * 4 + 0, cotangent / aspect);
- matrixBuf.put(1 * 4 + 1, cotangent);
- matrixBuf.put(2 * 4 + 2, - (zFar + zNear) / deltaZ);
- matrixBuf.put(2 * 4 + 3, -1);
- matrixBuf.put(3 * 4 + 2, -2 * zNear * zFar / deltaZ);
- matrixBuf.put(3 * 4 + 3, 0);
-
- gl.glMultMatrixf(matrixBuf);
+ public void gluPerspective(final GLMatrixFunc gl, final float fovy_deg, final float aspect, final float zNear, final float zFar) {
+ gl.glMultMatrixf(FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy_deg * FloatUtil.PI / 180.0f, aspect, zNear, zFar), 0);
}
/**
* Method gluLookAt
- *
+ *
* @param eyex
* @param eyey
* @param eyez
@@ -415,77 +187,70 @@ public class ProjectFloat {
* @param upy
* @param upz
*/
- public void gluLookAt(GLMatrixFunc gl,
- float eyex, float eyey, float eyez,
- float centerx, float centery, float centerz,
- float upx, float upy, float upz) {
- FloatBuffer forward = this.forwardBuf;
- FloatBuffer side = this.sideBuf;
- FloatBuffer up = this.upBuf;
-
- forward.put(0, centerx - eyex);
- forward.put(1, centery - eyey);
- forward.put(2, centerz - eyez);
-
- up.put(0, upx);
- up.put(1, upy);
- up.put(2, upz);
-
- FloatUtil.normalize(forward);
-
- /* Side = forward x up */
- FloatUtil.cross(forward, up, side);
- FloatUtil.normalize(side);
-
- /* Recompute up as: up = side x forward */
- FloatUtil.cross(side, forward, up);
-
- FloatUtil.makeIdentityf(matrixBuf);
- matrixBuf.put(0 * 4 + 0, side.get(0));
- matrixBuf.put(1 * 4 + 0, side.get(1));
- matrixBuf.put(2 * 4 + 0, side.get(2));
-
- matrixBuf.put(0 * 4 + 1, up.get(0));
- matrixBuf.put(1 * 4 + 1, up.get(1));
- matrixBuf.put(2 * 4 + 1, up.get(2));
-
- matrixBuf.put(0 * 4 + 2, -forward.get(0));
- matrixBuf.put(1 * 4 + 2, -forward.get(1));
- matrixBuf.put(2 * 4 + 2, -forward.get(2));
-
- gl.glMultMatrixf(matrixBuf);
- gl.glTranslatef(-eyex, -eyey, -eyez);
+ public void gluLookAt(final GLMatrixFunc gl,
+ final float eyex, final float eyey, final float eyez,
+ final float centerx, final float centery, final float centerz,
+ final float upx, final float upy, final float upz) {
+ mat4Tmp2[0+0] = eyex;
+ mat4Tmp2[1+0] = eyey;
+ mat4Tmp2[2+0] = eyez;
+ mat4Tmp2[0+4] = centerx;
+ mat4Tmp2[1+4] = centery;
+ mat4Tmp2[2+4] = centerz;
+ mat4Tmp2[0+8] = upx;
+ mat4Tmp2[1+8] = upy;
+ mat4Tmp2[2+8] = upz;
+ gl.glMultMatrixf(
+ FloatUtil.makeLookAt(mat4Tmp1, 0, mat4Tmp2 /* eye */, 0, mat4Tmp2 /* center */, 4, mat4Tmp2 /* up */, 8, mat4Tmp3), 0);
}
/**
- * Method gluProject
- *
+ * Map object coordinates to window coordinates.
+ * <p>
+ * Traditional <code>gluProject</code> implementation.
+ * </p>
+ *
* @param objx
* @param objy
* @param objz
- * @param modelMatrix
- * @param projMatrix
- * @param viewport
- * @param win_pos
- *
- * @return
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param win_pos 3 component window coordinate, the result
+ * @param win_pos_offset
+ * @return true if successful, otherwise false (z is 1)
*/
- public boolean gluProject(float objx, float objy, float objz,
- float[] modelMatrix, int modelMatrix_offset,
- float[] projMatrix, int projMatrix_offset,
- int[] viewport, int viewport_offset,
- float[] win_pos, int win_pos_offset ) {
+ public boolean gluProject(final float objx, final float objy, final float objz,
+ final float[] modelMatrix, final int modelMatrix_offset,
+ final float[] projMatrix, final int projMatrix_offset,
+ final int[] viewport, final int viewport_offset,
+ final float[] win_pos, final int win_pos_offset ) {
+ return FloatUtil.mapObjToWinCoords(objx, objy, objz,
+ modelMatrix, modelMatrix_offset,
+ projMatrix, projMatrix_offset,
+ viewport, viewport_offset,
+ win_pos, win_pos_offset,
+ mat4Tmp1, mat4Tmp2);
+ }
- float[] in = this.in;
- float[] out = this.out;
+ /**
+ * Map object coordinates to window coordinates.
+ */
+ @SuppressWarnings("deprecation")
+ public boolean gluProject(final float objx, final float objy, final float objz,
+ final FloatBuffer modelMatrix,
+ final FloatBuffer projMatrix,
+ final int[] viewport, final int viewport_offset,
+ final float[] win_pos, final int win_pos_offset ) {
+ final float[] in = this.mat4Tmp1;
+ final float[] out = this.mat4Tmp2;
in[0] = objx;
in[1] = objy;
in[2] = objz;
in[3] = 1.0f;
- FloatUtil.multMatrixVecf(modelMatrix, modelMatrix_offset, in, 0, out);
- FloatUtil.multMatrixVecf(projMatrix, projMatrix_offset, out, 0, in);
+ FloatUtil.multMatrixVec(modelMatrix, in, out);
+ FloatUtil.multMatrixVec(projMatrix, out, in);
if (in[3] == 0.0f) {
return false;
@@ -506,45 +271,9 @@ public class ProjectFloat {
return true;
}
- public boolean gluProject(float objx, float objy, float objz,
- FloatBuffer modelMatrix,
- FloatBuffer projMatrix,
- int[] viewport, int viewport_offset,
- float[] win_pos, int win_pos_offset ) {
-
- FloatBuffer in = this.inBuf;
- FloatBuffer out = this.outBuf;
-
- in.put(0, objx);
- in.put(1, objy);
- in.put(2, objz);
- in.put(3, 1.0f);
-
- FloatUtil.multMatrixVecf(modelMatrix, in, out);
- FloatUtil.multMatrixVecf(projMatrix, out, in);
-
- if (in.get(3) == 0.0f) {
- return false;
- }
-
- in.put(3, (1.0f / in.get(3)) * 0.5f);
-
- // Map x, y and z to range 0-1
- in.put(0, in.get(0) * in.get(3) + 0.5f);
- in.put(1, in.get(1) * in.get(3) + 0.5f);
- in.put(2, in.get(2) * in.get(3) + 0.5f);
-
- // Map x,y to viewport
- win_pos[0+win_pos_offset] = in.get(0) * viewport[2+viewport_offset] + viewport[0+viewport_offset];
- win_pos[1+win_pos_offset] = in.get(1) * viewport[3+viewport_offset] + viewport[1+viewport_offset];
- win_pos[2+win_pos_offset] = in.get(2);
-
- return true;
- }
-
/**
- * Method gluProject
- *
+ * Map object coordinates to window coordinates.
+ *
* @param objx
* @param objy
* @param objz
@@ -552,151 +281,140 @@ public class ProjectFloat {
* @param projMatrix
* @param viewport
* @param win_pos
- *
+ *
* @return
*/
- public boolean gluProject(float objx, float objy, float objz,
- FloatBuffer modelMatrix,
- FloatBuffer projMatrix,
- IntBuffer viewport,
- FloatBuffer win_pos) {
+ @SuppressWarnings("deprecation")
+ public boolean gluProject(final float objx, final float objy, final float objz,
+ final FloatBuffer modelMatrix,
+ final FloatBuffer projMatrix,
+ final IntBuffer viewport,
+ final FloatBuffer win_pos) {
- FloatBuffer in = this.inBuf;
- FloatBuffer out = this.outBuf;
+ final float[] in = this.mat4Tmp1;
+ final float[] out = this.mat4Tmp2;
- in.put(0, objx);
- in.put(1, objy);
- in.put(2, objz);
- in.put(3, 1.0f);
+ in[0] = objx;
+ in[1] = objy;
+ in[2] = objz;
+ in[3] = 1.0f;
- FloatUtil.multMatrixVecf(modelMatrix, in, out);
- FloatUtil.multMatrixVecf(projMatrix, out, in);
+ FloatUtil.multMatrixVec(modelMatrix, in, out);
+ FloatUtil.multMatrixVec(projMatrix, out, in);
- if (in.get(3) == 0.0f) {
+ if (in[3] == 0.0f) {
return false;
}
- in.put(3, (1.0f / in.get(3)) * 0.5f);
+ in[3] = (1.0f / in[3]) * 0.5f;
// Map x, y and z to range 0-1
- in.put(0, in.get(0) * in.get(3) + 0.5f);
- in.put(1, in.get(1) * in.get(3) + 0.5f);
- in.put(2, in.get(2) * in.get(3) + 0.5f);
+ in[0] = in[0] * in[3] + 0.5f;
+ in[1] = in[1] * in[3] + 0.5f;
+ in[2] = in[2] * in[3] + 0.5f;
// Map x,y to viewport
- int vPos = viewport.position();
- int wPos = win_pos.position();
- win_pos.put(0+wPos, in.get(0) * viewport.get(2+vPos) + viewport.get(0+vPos));
- win_pos.put(1+wPos, in.get(1) * viewport.get(3+vPos) + viewport.get(1+vPos));
- win_pos.put(2+wPos, in.get(2));
+ final int vPos = viewport.position();
+ final int wPos = win_pos.position();
+ win_pos.put(0+wPos, in[0] * viewport.get(2+vPos) + viewport.get(0+vPos));
+ win_pos.put(1+wPos, in[1] * viewport.get(3+vPos) + viewport.get(1+vPos));
+ win_pos.put(2+wPos, in[2]);
return true;
}
/**
- * Method gluUnproject
- *
+ * Map window coordinates to object coordinates.
+ * <p>
+ * Traditional <code>gluUnProject</code> implementation.
+ * </p>
+ *
+ * @param winx
+ * @param winy
+ * @param winz
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
+ * @param obj_pos 3 component object coordinate, the result
+ * @param obj_pos_offset
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
+ */
+ public boolean gluUnProject(final float winx, final float winy, final float winz,
+ final float[] modelMatrix, final int modelMatrix_offset,
+ final float[] projMatrix, final int projMatrix_offset,
+ final int[] viewport, final int viewport_offset,
+ final float[] obj_pos, final int obj_pos_offset) {
+ return FloatUtil.mapWinToObjCoords(winx, winy, winz,
+ modelMatrix, modelMatrix_offset,
+ projMatrix, projMatrix_offset,
+ viewport, viewport_offset,
+ obj_pos, obj_pos_offset,
+ mat4Tmp1, mat4Tmp2);
+ }
+
+
+ /**
+ * Map window coordinates to object coordinates.
+ *
* @param winx
* @param winy
* @param winz
* @param modelMatrix
* @param projMatrix
* @param viewport
+ * @param viewport_offset
* @param obj_pos
- *
- * @return
+ * @param obj_pos_offset
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
*/
- public boolean gluUnProject(float winx, float winy, float winz,
- float[] modelMatrix, int modelMatrix_offset,
- float[] projMatrix, int projMatrix_offset,
- int[] viewport, int viewport_offset,
- float[] obj_pos, int obj_pos_offset) {
- float[] in = this.in;
- float[] out = this.out;
-
- FloatUtil.multMatrixf(projMatrix, projMatrix_offset, modelMatrix, modelMatrix_offset, matrix, 0);
-
- if (!gluInvertMatrixf(matrix, 0, matrix, 0)) {
+ @SuppressWarnings("deprecation")
+ public boolean gluUnProject(final float winx, final float winy, final float winz,
+ final FloatBuffer modelMatrix,
+ final FloatBuffer projMatrix,
+ final int[] viewport, final int viewport_offset,
+ final float[] obj_pos, final int obj_pos_offset) {
+ // mat4Tmp1 = P x M
+ FloatUtil.multMatrix(projMatrix, modelMatrix, mat4Tmp1);
+
+ // mat4Tmp1 = Inv(P x M)
+ if ( null == FloatUtil.invertMatrix(mat4Tmp1, mat4Tmp1) ) {
return false;
}
- in[0] = winx;
- in[1] = winy;
- in[2] = winz;
- in[3] = 1.0f;
+ mat4Tmp2[0] = winx;
+ mat4Tmp2[1] = winy;
+ mat4Tmp2[2] = winz;
+ mat4Tmp2[3] = 1.0f;
// Map x and y from window coordinates
- in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset];
- in[1] = (in[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset];
+ mat4Tmp2[0] = (mat4Tmp2[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset];
+ mat4Tmp2[1] = (mat4Tmp2[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset];
// Map to range -1 to 1
- in[0] = in[0] * 2 - 1;
- in[1] = in[1] * 2 - 1;
- in[2] = in[2] * 2 - 1;
+ mat4Tmp2[0] = mat4Tmp2[0] * 2 - 1;
+ mat4Tmp2[1] = mat4Tmp2[1] * 2 - 1;
+ mat4Tmp2[2] = mat4Tmp2[2] * 2 - 1;
- FloatUtil.multMatrixVecf(matrix, in, out);
+ final int raw_off = 4;
+ // object raw coords = Inv(P x M) * winPos -> mat4Tmp2
+ FloatUtil.multMatrixVec(mat4Tmp1, 0, mat4Tmp2, 0, mat4Tmp2, raw_off);
- if (out[3] == 0.0) {
+ if (mat4Tmp2[3+raw_off] == 0.0) {
return false;
}
- out[3] = 1.0f / out[3];
+ mat4Tmp2[3+raw_off] = 1.0f / mat4Tmp2[3+raw_off];
- obj_pos[0+obj_pos_offset] = out[0] * out[3];
- obj_pos[1+obj_pos_offset] = out[1] * out[3];
- obj_pos[2+obj_pos_offset] = out[2] * out[3];
+ obj_pos[0+obj_pos_offset] = mat4Tmp2[0+raw_off] * mat4Tmp2[3+raw_off];
+ obj_pos[1+obj_pos_offset] = mat4Tmp2[1+raw_off] * mat4Tmp2[3+raw_off];
+ obj_pos[2+obj_pos_offset] = mat4Tmp2[2+raw_off] * mat4Tmp2[3+raw_off];
return true;
}
-
- public boolean gluUnProject(float winx, float winy, float winz,
- FloatBuffer modelMatrix,
- FloatBuffer projMatrix,
- int[] viewport, int viewport_offset,
- float[] obj_pos, int obj_pos_offset) {
- FloatBuffer in = this.inBuf;
- FloatBuffer out = this.outBuf;
-
- FloatUtil.multMatrixf(projMatrix, modelMatrix, matrixBuf);
-
- if (!gluInvertMatrixf(matrixBuf, matrixBuf)) {
- return false;
- }
-
- in.put(0, winx);
- in.put(1, winy);
- in.put(2, winz);
- in.put(3, 1.0f);
-
- // Map x and y from window coordinates
- in.put(0, (in.get(0) - viewport[0+viewport_offset]) / viewport[2+viewport_offset]);
- in.put(1, (in.get(1) - viewport[1+viewport_offset]) / viewport[3+viewport_offset]);
-
- // Map to range -1 to 1
- in.put(0, in.get(0) * 2 - 1);
- in.put(1, in.get(1) * 2 - 1);
- in.put(2, in.get(2) * 2 - 1);
-
- FloatUtil.multMatrixVecf(matrixBuf, in, out);
-
- if (out.get(3) == 0.0f) {
- return false;
- }
-
- out.put(3, 1.0f / out.get(3));
-
- obj_pos[0+obj_pos_offset] = out.get(0) * out.get(3);
- obj_pos[1+obj_pos_offset] = out.get(1) * out.get(3);
- obj_pos[2+obj_pos_offset] = out.get(2) * out.get(3);
-
- return true;
- }
-
/**
- * Method gluUnproject
- *
+ * Map window coordinates to object coordinates.
+ *
* @param winx
* @param winy
* @param winz
@@ -704,123 +422,98 @@ public class ProjectFloat {
* @param projMatrix
* @param viewport
* @param obj_pos
- *
- * @return
+ *
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
*/
- public boolean gluUnProject(float winx, float winy, float winz,
- FloatBuffer modelMatrix,
- FloatBuffer projMatrix,
- IntBuffer viewport,
- FloatBuffer obj_pos) {
- FloatBuffer in = this.inBuf;
- FloatBuffer out = this.outBuf;
-
- FloatUtil.multMatrixf(projMatrix, modelMatrix, matrixBuf);
-
- if (!gluInvertMatrixf(matrixBuf, matrixBuf)) {
+ @SuppressWarnings("deprecation")
+ public boolean gluUnProject(final float winx, final float winy, final float winz,
+ final FloatBuffer modelMatrix,
+ final FloatBuffer projMatrix,
+ final IntBuffer viewport,
+ final FloatBuffer obj_pos) {
+ final int vPos = viewport.position();
+ final int oPos = obj_pos.position();
+
+ // mat4Tmp1 = P x M
+ FloatUtil.multMatrix(projMatrix, modelMatrix, mat4Tmp1);
+
+ // mat4Tmp1 = Inv(P x M)
+ if ( null == FloatUtil.invertMatrix(mat4Tmp1, mat4Tmp1) ) {
return false;
}
- in.put(0, winx);
- in.put(1, winy);
- in.put(2, winz);
- in.put(3, 1.0f);
+ mat4Tmp2[0] = winx;
+ mat4Tmp2[1] = winy;
+ mat4Tmp2[2] = winz;
+ mat4Tmp2[3] = 1.0f;
// Map x and y from window coordinates
- int vPos = viewport.position();
- int oPos = obj_pos.position();
- in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos));
- in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos));
+ mat4Tmp2[0] = (mat4Tmp2[0] - viewport.get(0+vPos)) / viewport.get(2+vPos);
+ mat4Tmp2[1] = (mat4Tmp2[1] - viewport.get(1+vPos)) / viewport.get(3+vPos);
// Map to range -1 to 1
- in.put(0, in.get(0) * 2 - 1);
- in.put(1, in.get(1) * 2 - 1);
- in.put(2, in.get(2) * 2 - 1);
+ mat4Tmp2[0] = mat4Tmp2[0] * 2 - 1;
+ mat4Tmp2[1] = mat4Tmp2[1] * 2 - 1;
+ mat4Tmp2[2] = mat4Tmp2[2] * 2 - 1;
- FloatUtil.multMatrixVecf(matrixBuf, in, out);
+ final int raw_off = 4;
+ // object raw coords = Inv(P x M) * winPos -> mat4Tmp2
+ FloatUtil.multMatrixVec(mat4Tmp1, 0, mat4Tmp2, 0, mat4Tmp2, raw_off);
- if (out.get(3) == 0.0f) {
+ if (mat4Tmp2[3+raw_off] == 0.0) {
return false;
}
- out.put(3, 1.0f / out.get(3));
+ mat4Tmp2[3+raw_off] = 1.0f / mat4Tmp2[3+raw_off];
- obj_pos.put(0+oPos, out.get(0) * out.get(3));
- obj_pos.put(1+oPos, out.get(1) * out.get(3));
- obj_pos.put(2+oPos, out.get(2) * out.get(3));
+ obj_pos.put(0+oPos, mat4Tmp2[0+raw_off] * mat4Tmp2[3+raw_off]);
+ obj_pos.put(1+oPos, mat4Tmp2[1+raw_off] * mat4Tmp2[3+raw_off]);
+ obj_pos.put(2+oPos, mat4Tmp2[2+raw_off] * mat4Tmp2[3+raw_off]);
return true;
}
/**
- * Method gluUnproject4
- *
+ * Map window coordinates to object coordinates.
+ * <p>
+ * Traditional <code>gluUnProject4</code> implementation.
+ * </p>
+ *
* @param winx
* @param winy
* @param winz
* @param clipw
- * @param modelMatrix
- * @param projMatrix
- * @param viewport
+ * @param modelMatrix 4x4 modelview matrix
+ * @param modelMatrix_offset
+ * @param projMatrix 4x4 projection matrix
+ * @param projMatrix_offset
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
* @param near
* @param far
- * @param obj_pos
- *
- * @return
+ * @param obj_pos 4 component object coordinate, the result
+ * @param obj_pos_offset
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
*/
- public boolean gluUnProject4(float winx,
- float winy,
- float winz,
- float clipw,
- float[] modelMatrix,
- int modelMatrix_offset,
- float[] projMatrix,
- int projMatrix_offset,
- int[] viewport,
- int viewport_offset,
- float near,
- float far,
- float[] obj_pos,
- int obj_pos_offset ) {
- float[] in = this.in;
- float[] out = this.out;
-
- FloatUtil.multMatrixf(projMatrix, projMatrix_offset, modelMatrix, modelMatrix_offset, matrix, 0);
-
- if (!gluInvertMatrixf(matrix, 0, matrix, 0))
- return false;
-
- in[0] = winx;
- in[1] = winy;
- in[2] = winz;
- in[3] = clipw;
-
- // Map x and y from window coordinates
- in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset];
- in[1] = (in[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset];
- in[2] = (in[2] - near) / (far - near);
-
- // Map to range -1 to 1
- in[0] = in[0] * 2 - 1;
- in[1] = in[1] * 2 - 1;
- in[2] = in[2] * 2 - 1;
-
- FloatUtil.multMatrixVecf(matrix, in, out);
-
- if (out[3] == 0.0f)
- return false;
-
- obj_pos[0+obj_pos_offset] = out[0];
- obj_pos[1+obj_pos_offset] = out[1];
- obj_pos[2+obj_pos_offset] = out[2];
- obj_pos[3+obj_pos_offset] = out[3];
- return true;
+ public boolean gluUnProject4(final float winx, final float winy, final float winz, final float clipw,
+ final float[] modelMatrix, final int modelMatrix_offset,
+ final float[] projMatrix, final int projMatrix_offset,
+ final int[] viewport, final int viewport_offset,
+ final float near, final float far,
+ final float[] obj_pos, final int obj_pos_offset ) {
+ return FloatUtil.mapWinToObjCoords(winx, winy, winz, clipw,
+ modelMatrix, modelMatrix_offset,
+ projMatrix, projMatrix_offset,
+ viewport, viewport_offset,
+ near, far,
+ obj_pos, obj_pos_offset,
+ mat4Tmp1, mat4Tmp2);
}
/**
- * Method gluUnproject4
- *
+ * Map window coordinates to object coordinates.
+ *
* @param winx
* @param winy
* @param winz
@@ -831,78 +524,75 @@ public class ProjectFloat {
* @param near
* @param far
* @param obj_pos
- *
- * @return
+ *
+ * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
*/
- public boolean gluUnProject4(float winx,
- float winy,
- float winz,
- float clipw,
- FloatBuffer modelMatrix,
- FloatBuffer projMatrix,
- IntBuffer viewport,
- float near,
- float far,
- FloatBuffer obj_pos) {
- FloatBuffer in = this.inBuf;
- FloatBuffer out = this.outBuf;
-
- FloatUtil.multMatrixf(projMatrix, modelMatrix, matrixBuf);
-
- if (!gluInvertMatrixf(matrixBuf, matrixBuf))
+ @SuppressWarnings("deprecation")
+ public boolean gluUnProject4(final float winx, final float winy, final float winz, final float clipw,
+ final FloatBuffer modelMatrix, final FloatBuffer projMatrix,
+ final IntBuffer viewport,
+ final float near, final float far,
+ final FloatBuffer obj_pos) {
+ FloatUtil.multMatrix(projMatrix, modelMatrix, mat4Tmp1);
+
+ if ( null == FloatUtil.invertMatrix(mat4Tmp1, mat4Tmp1) ) {
return false;
+ }
- in.put(0, winx);
- in.put(1, winy);
- in.put(2, winz);
- in.put(3, clipw);
+ mat4Tmp2[0] = winx;
+ mat4Tmp2[1] = winy;
+ mat4Tmp2[2] = winz;
+ mat4Tmp2[3] = clipw;
// Map x and y from window coordinates
- int vPos = viewport.position();
- in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos));
- in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos));
- in.put(2, (in.get(2) - near) / (far - near));
+ final int vPos = viewport.position();
+ mat4Tmp2[0] = (mat4Tmp2[0] - viewport.get(0+vPos)) / viewport.get(2+vPos);
+ mat4Tmp2[1] = (mat4Tmp2[1] - viewport.get(1+vPos)) / viewport.get(3+vPos);
+ mat4Tmp2[2] = (mat4Tmp2[2] - near) / (far - near);
// Map to range -1 to 1
- in.put(0, in.get(0) * 2 - 1);
- in.put(1, in.get(1) * 2 - 1);
- in.put(2, in.get(2) * 2 - 1);
+ mat4Tmp2[0] = mat4Tmp2[0] * 2 - 1;
+ mat4Tmp2[1] = mat4Tmp2[1] * 2 - 1;
+ mat4Tmp2[2] = mat4Tmp2[2] * 2 - 1;
- FloatUtil.multMatrixVecf(matrixBuf, in, out);
+ final int raw_off = 4;
+ FloatUtil.multMatrixVec(mat4Tmp1, 0, mat4Tmp2, 0, mat4Tmp2, raw_off);
- if (out.get(3) == 0.0f)
+ if (mat4Tmp2[3+raw_off] == 0.0f) {
return false;
+ }
- int oPos = obj_pos.position();
- obj_pos.put(0+oPos, out.get(0));
- obj_pos.put(1+oPos, out.get(1));
- obj_pos.put(2+oPos, out.get(2));
- obj_pos.put(3+oPos, out.get(3));
+ final int oPos = obj_pos.position();
+ obj_pos.put(0+oPos, mat4Tmp2[0+raw_off]);
+ obj_pos.put(1+oPos, mat4Tmp2[1+raw_off]);
+ obj_pos.put(2+oPos, mat4Tmp2[2+raw_off]);
+ obj_pos.put(3+oPos, mat4Tmp2[3+raw_off]);
return true;
}
/**
- * Method gluPickMatrix
- *
+ * Make given matrix the <i>pick</i> matrix based on given parameters.
+ * <p>
+ * Traditional <code>gluPickMatrix</code> implementation.
+ * </p>
* @param x
* @param y
* @param deltaX
* @param deltaY
- * @param viewport
+ * @param viewport 4 component viewport vector
+ * @param viewport_offset
*/
- public void gluPickMatrix(GLMatrixFunc gl,
- float x,
- float y,
- float deltaX,
- float deltaY,
- IntBuffer viewport) {
+ public void gluPickMatrix(final GLMatrixFunc gl,
+ final float x, final float y,
+ final float deltaX, final float deltaY,
+ final IntBuffer viewport) {
if (deltaX <= 0 || deltaY <= 0) {
return;
}
/* Translate and scale the picked region to the entire window */
- int vPos = viewport.position();
+ final int vPos = viewport.position();
gl.glTranslatef((viewport.get(2+vPos) - 2 * (x - viewport.get(0+vPos))) / deltaX,
(viewport.get(3+vPos) - 2 * (y - viewport.get(1+vPos))) / deltaY,
0);
@@ -910,31 +600,24 @@ public class ProjectFloat {
}
/**
- * Method gluPickMatrix
- *
+ * Make given matrix the <i>pick</i> matrix based on given parameters.
+ * <p>
+ * Traditional <code>gluPickMatrix</code> implementation.
+ * </p>
* @param x
* @param y
* @param deltaX
* @param deltaY
- * @param viewport
+ * @param viewport 4 component viewport vector
* @param viewport_offset
*/
- public void gluPickMatrix(GLMatrixFunc gl,
- float x,
- float y,
- float deltaX,
- float deltaY,
- int[] viewport,
- int viewport_offset) {
- if (deltaX <= 0 || deltaY <= 0) {
- return;
+ public void gluPickMatrix(final GLMatrixFunc gl,
+ final float x, final float y,
+ final float deltaX, final float deltaY,
+ final int[] viewport, final int viewport_offset) {
+ if( null != FloatUtil.makePick(mat4Tmp1, 0, x, y, deltaX, deltaY, viewport, viewport_offset, mat4Tmp2) ) {
+ gl.glMultMatrixf(mat4Tmp1, 0);
}
-
- /* Translate and scale the picked region to the entire window */
- gl.glTranslatef((viewport[2+viewport_offset] - 2 * (x - viewport[0+viewport_offset])) / deltaX,
- (viewport[3+viewport_offset] - 2 * (y - viewport[1+viewport_offset])) / deltaY,
- 0);
- gl.glScalef(viewport[2+viewport_offset] / deltaX, viewport[3+viewport_offset] / deltaY, 1.0f);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
index 0528d3060..93a4eb32e 100644
--- a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
+++ b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
@@ -33,27 +33,49 @@ import java.util.Iterator;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
+import com.jogamp.opengl.GLRendererQuirks;
+
public class SharedResourceRunner implements Runnable {
protected static final boolean DEBUG = GLDrawableImpl.DEBUG;
public static interface Resource {
+ boolean isValid();
AbstractGraphicsDevice getDevice();
AbstractGraphicsScreen getScreen();
GLDrawableImpl getDrawable();
GLContextImpl getContext();
+ GLRendererQuirks getRendererQuirks();
}
public static interface Implementation {
/**
- * @param connection for creation a {@link AbstractGraphicsDevice} instance.
- * @return A new shared resource instance
+ * <p>
+ * Called within synchronized block.
+ * </p>
+ * @param connection for creation a {@link AbstractGraphicsDevice} instance.
+ * @return <code>true</code> if the device supports all protocols required for the implementation, otherwise <code>false</code>.
+ */
+ boolean isDeviceSupported(String connection);
+
+ /**
+ * <p>
+ * Called within synchronized block.
+ * </p>
+ * @param connection for creation a {@link AbstractGraphicsDevice} instance.
+ * @return A new shared resource instance
*/
Resource createSharedResource(String connection);
+
+ /** Called within synchronized block. */
void releaseSharedResource(Resource shared);
+ /** Called within synchronized block. */
void clear();
+ /** Called within synchronized block. */
Resource mapPut(String connection, Resource resource);
+ /** Called within synchronized block. */
Resource mapGet(String connection);
+ /** Called within synchronized block. */
Collection<Resource> mapValues();
}
@@ -61,144 +83,154 @@ public class SharedResourceRunner implements Runnable {
final Implementation impl;
Thread thread;
+ boolean running;
boolean ready;
- boolean released;
boolean shouldRelease;
String initConnection;
String releaseConnection;
- private boolean getDeviceTried(String connection) {
- synchronized (devicesTried) {
- return devicesTried.contains(connection);
- }
+ private boolean getDeviceTried(final String connection) { // synchronized call
+ return devicesTried.contains(connection);
}
- private void addDeviceTried(String connection) {
- synchronized (devicesTried) {
- devicesTried.add(connection);
- }
+ private void addDeviceTried(final String connection) { // synchronized call
+ devicesTried.add(connection);
}
- private void removeDeviceTried(String connection) {
- synchronized (devicesTried) {
- devicesTried.remove(connection);
- }
+ private void removeDeviceTried(final String connection) { // synchronized call
+ devicesTried.remove(connection);
}
- public SharedResourceRunner(Implementation impl) {
+ public SharedResourceRunner(final Implementation impl) {
this.impl = impl;
resetState();
}
-
- private void resetState() {
+
+ private void resetState() { // synchronized call
devicesTried.clear();
thread = null;
ready = false;
- released = false;
+ running = false;
shouldRelease = false;
initConnection = null;
releaseConnection = null;
}
- /**
+ /**
* Start the shared resource runner thread, if not running.
* <p>
* Validate the thread upfront and release all related resource if it was killed.
* </p>
- *
+ *
* @return the shared resource runner thread.
*/
public Thread start() {
- if(null != thread && !thread.isAlive()) {
- // thread was killed unrecognized ..
- if (DEBUG) {
- System.err.println("SharedResourceRunner.start() - dead-old-thread cleanup - "+Thread.currentThread().getName());
+ synchronized (this) {
+ if(null != thread && !thread.isAlive()) {
+ // thread was killed unrecognized ..
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.start() - dead-old-thread cleanup - "+getThreadName());
+ }
+ releaseSharedResources();
+ thread = null;
+ running = false;
}
- releaseSharedResources();
- thread = null;
- }
- if(null == thread) {
- if (DEBUG) {
- System.err.println("SharedResourceRunner.start() - start new Thread - "+Thread.currentThread().getName());
+ if( null == thread ) {
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.start() - start new Thread - "+getThreadName());
+ }
+ resetState();
+ thread = new Thread(this, getThreadName()+"-SharedResourceRunner");
+ thread.setDaemon(true); // Allow JVM to exit, even if this one is running
+ thread.start();
+ while (!running) {
+ try {
+ this.wait();
+ } catch (final InterruptedException ex) { }
+ }
}
- resetState();
- thread = new Thread(this, Thread.currentThread().getName()+"-SharedResourceRunner");
- thread.setDaemon(true); // Allow JVM to exit, even if this one is running
- thread.start();
}
return thread;
}
-
+
public void stop() {
- if(null != thread) {
- if (DEBUG) {
- System.err.println("SharedResourceRunner.stop() - "+Thread.currentThread().getName());
- }
- synchronized (this) {
- shouldRelease = true;
- this.notifyAll();
-
- while (!released) {
- try {
- this.wait();
- } catch (InterruptedException ex) {
+ synchronized (this) {
+ if(null != thread) {
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.stop() - "+getThreadName());
+ }
+ synchronized (this) {
+ shouldRelease = true;
+ this.notifyAll();
+
+ while (running) {
+ try {
+ this.wait();
+ } catch (final InterruptedException ex) { }
}
}
}
}
}
-
- public SharedResourceRunner.Resource getOrCreateShared(AbstractGraphicsDevice device) {
+
+ public SharedResourceRunner.Resource getOrCreateShared(final AbstractGraphicsDevice device) {
SharedResourceRunner.Resource sr = null;
if(null != device) {
- start();
- final String connection = device.getConnection();
- sr = impl.mapGet(connection);
- if (null == sr && !getDeviceTried(connection)) {
- addDeviceTried(connection);
- if (DEBUG) {
- System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": trying - "+Thread.currentThread().getName());
- }
- doAndWait(connection, null);
+ synchronized (this) {
+ start();
+ final String connection = device.getConnection();
sr = impl.mapGet(connection);
- if (DEBUG) {
- System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) +" - "+Thread.currentThread().getName());
+ if (null == sr) {
+ if ( !getDeviceTried(connection) ) {
+ addDeviceTried(connection);
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": trying - "+getThreadName());
+ }
+ if ( impl.isDeviceSupported(connection) ) {
+ doAndWait(connection, null);
+ sr = impl.mapGet(connection);
+ }
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) +" - "+getThreadName());
+ }
+ }
}
}
}
return sr;
}
- public SharedResourceRunner.Resource releaseShared(AbstractGraphicsDevice device) {
+ public SharedResourceRunner.Resource releaseShared(final AbstractGraphicsDevice device) {
SharedResourceRunner.Resource sr = null;
if(null != device) {
- String connection = device.getConnection();
- sr = impl.mapGet(connection);
- if (null != sr) {
- removeDeviceTried(connection);
- if (DEBUG) {
- System.err.println("SharedResourceRunner.releaseShared() " + connection + ": trying - "+Thread.currentThread().getName());
- }
- doAndWait(null, connection);
- if (DEBUG) {
- System.err.println("SharedResourceRunner.releaseShared() " + connection + ": done - "+Thread.currentThread().getName());
+ synchronized (this) {
+ final String connection = device.getConnection();
+ sr = impl.mapGet(connection);
+ if (null != sr) {
+ removeDeviceTried(connection);
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.releaseShared() " + connection + ": trying - "+getThreadName());
+ }
+ doAndWait(null, connection);
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.releaseShared() " + connection + ": done - "+getThreadName());
+ }
}
}
}
return sr;
}
- private final void doAndWait(String initConnection, String releaseConnection) {
- // wait until thread becomes ready to init new device,
- // pass the device and release the sync
- final String threadName = Thread.currentThread().getName();
- if (DEBUG) {
- System.err.println("SharedResourceRunner.doAndWait() START init: " + initConnection + ", release: "+releaseConnection+" - "+threadName);
- }
+ private final void doAndWait(final String initConnection, final String releaseConnection) {
synchronized (this) {
- while (!ready) {
+ // wait until thread becomes ready to init new device,
+ // pass the device and release the sync
+ final String threadName = getThreadName();
+ if (DEBUG) {
+ System.err.println("SharedResourceRunner.doAndWait() START init: " + initConnection + ", release: "+releaseConnection+" - "+threadName);
+ }
+ while (!ready && running) {
try {
this.wait();
- } catch (InterruptedException ex) {
- }
+ } catch (final InterruptedException ex) { }
}
if (DEBUG) {
System.err.println("SharedResourceRunner.doAndWait() set command: " + initConnection + ", release: "+releaseConnection+" - "+threadName);
@@ -208,11 +240,10 @@ public class SharedResourceRunner implements Runnable {
this.notifyAll();
// wait until thread has init/released the device
- while (!ready || null != this.initConnection || null != this.releaseConnection) {
+ while ( running && ( !ready || null != this.initConnection || null != this.releaseConnection ) ) {
try {
this.wait();
- } catch (InterruptedException ex) {
- }
+ } catch (final InterruptedException ex) { }
}
if (DEBUG) {
System.err.println("SharedResourceRunner.initializeAndWait END init: " + initConnection + ", release: "+releaseConnection+" - "+threadName);
@@ -221,14 +252,17 @@ public class SharedResourceRunner implements Runnable {
// done
}
+ @Override
public final void run() {
- final String threadName = Thread.currentThread().getName();
+ final String threadName = getThreadName();
if (DEBUG) {
System.err.println("SharedResourceRunner.run(): STARTED - " + threadName);
}
synchronized (this) {
+ running = true;
+
while (!shouldRelease) {
try {
// wait for stop or init
@@ -238,10 +272,10 @@ public class SharedResourceRunner implements Runnable {
}
notifyAll();
this.wait();
- } catch (InterruptedException ex) {
+ } catch (final InterruptedException ex) {
shouldRelease = true;
if(DEBUG) {
- System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+Thread.currentThread().getName());
+ System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+threadName);
ex.printStackTrace();
}
}
@@ -259,10 +293,8 @@ public class SharedResourceRunner implements Runnable {
Resource sr = null;
try {
sr = impl.createSharedResource(initConnection);
- } catch (Exception e) {
- if(DEBUG) {
- e.printStackTrace();
- }
+ } catch (final Exception e) {
+ e.printStackTrace();
}
if (null != sr) {
impl.mapPut(initConnection, sr);
@@ -272,15 +304,15 @@ public class SharedResourceRunner implements Runnable {
if (DEBUG) {
System.err.println("SharedResourceRunner.run(): release Shared for: " + releaseConnection + " - " + threadName);
}
- Resource sr = impl.mapGet(releaseConnection);
+ final Resource sr = impl.mapGet(releaseConnection);
if (null != sr) {
try {
impl.releaseSharedResource(sr);
impl.mapPut(releaseConnection, null);
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
- }
+ }
}
}
initConnection = null;
@@ -298,25 +330,25 @@ public class SharedResourceRunner implements Runnable {
}
shouldRelease = false;
- released = true;
+ running = false;
thread = null;
notifyAll();
}
}
- private void releaseSharedResources() {
- synchronized (devicesTried) {
- devicesTried.clear();
- }
- Collection<Resource> sharedResources = impl.mapValues();
- for (Iterator<Resource> iter = sharedResources.iterator(); iter.hasNext();) {
+ private void releaseSharedResources() { // synchronized call
+ devicesTried.clear();
+ final Collection<Resource> sharedResources = impl.mapValues();
+ for (final Iterator<Resource> iter = sharedResources.iterator(); iter.hasNext();) {
try {
impl.releaseSharedResource(iter.next());
- } catch (Throwable t) {
- System.err.println("Catched Exception: "+t.getStackTrace()+" - "+Thread.currentThread().getName());
+ } catch (final Throwable t) {
+ System.err.println("Caught exception on thread "+getThreadName());
t.printStackTrace();
}
}
impl.clear();
}
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
}
diff --git a/src/jogl/classes/jogamp/opengl/SystemUtil.java b/src/jogl/classes/jogamp/opengl/SystemUtil.java
index befe1a315..e7f078079 100644
--- a/src/jogl/classes/jogamp/opengl/SystemUtil.java
+++ b/src/jogl/classes/jogamp/opengl/SystemUtil.java
@@ -5,11 +5,11 @@ public class SystemUtil {
private static volatile boolean getenvSupported = true;
/** Wrapper for System.getenv(), which doesn't work on platforms
earlier than JDK 5 */
- public static String getenv(String variableName) {
+ public static String getenv(final String variableName) {
if (getenvSupported) {
try {
return System.getenv(variableName);
- } catch (Error e) {
+ } catch (final Error e) {
getenvSupported = false;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/ThreadingImpl.java b/src/jogl/classes/jogamp/opengl/ThreadingImpl.java
index d55a2c976..7b405e524 100644
--- a/src/jogl/classes/jogamp/opengl/ThreadingImpl.java
+++ b/src/jogl/classes/jogamp/opengl/ThreadingImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.opengl;
@@ -41,23 +41,15 @@ import java.security.PrivilegedAction;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import javax.media.opengl.Threading.Mode;
import com.jogamp.common.JogampRuntimeException;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
/** Implementation of the {@link javax.media.opengl.Threading} class. */
public class ThreadingImpl {
- public enum Mode {
- MT(0), ST_AWT(1), ST_WORKER(2);
-
- public final int id;
-
- Mode(int id){
- this.id = id;
- }
- }
-
protected static final boolean DEBUG = Debug.debug("Threading");
private static boolean singleThreaded;
@@ -68,17 +60,18 @@ public class ThreadingImpl {
private static boolean _isX11;
private static final ToolkitThreadingPlugin threadingPlugin;
-
+
static {
threadingPlugin =
AccessController.doPrivileged(new PrivilegedAction<ToolkitThreadingPlugin>() {
+ @Override
public ToolkitThreadingPlugin run() {
final String singleThreadProp;
{
- final String w = Debug.getProperty("jogl.1thread", true);
+ final String w = PropertyAccess.getProperty("jogl.1thread", true);
singleThreadProp = null != w ? w.toLowerCase() : null;
}
- ClassLoader cl = ThreadingImpl.class.getClassLoader();
+ final ClassLoader cl = ThreadingImpl.class.getClassLoader();
// Default to using the AWT thread on all platforms except
// Windows. On OS X there is instability apparently due to
// using the JAWT on non-AWT threads. On X11 platforms there
@@ -91,36 +84,31 @@ public class ThreadingImpl {
_isX11 = NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false);
- // default setting
- singleThreaded = true;
- mode = ( hasAWT ? Mode.ST_AWT : Mode.ST_WORKER );
-
if (singleThreadProp != null) {
if (singleThreadProp.equals("true") ||
singleThreadProp.equals("auto")) {
- singleThreaded = true;
- mode = ( hasAWT ? Mode.ST_AWT : Mode.ST_WORKER );
+ mode = ( hasAWT ? Mode.ST_AWT : Mode.MT );
} else if (singleThreadProp.equals("worker")) {
- singleThreaded = true;
mode = Mode.ST_WORKER;
} else if (hasAWT && singleThreadProp.equals("awt")) {
- singleThreaded = true;
mode = Mode.ST_AWT;
} else if (singleThreadProp.equals("false")) {
- singleThreaded = false;
mode = Mode.MT;
} else {
throw new RuntimeException("Unsupported value for property jogl.1thread: "+singleThreadProp+", should be [true/auto, worker, awt or false]");
}
+ } else {
+ mode = ( hasAWT ? Mode.ST_AWT : Mode.MT );
}
-
+ singleThreaded = Mode.MT != mode;
+
ToolkitThreadingPlugin threadingPlugin=null;
if(hasAWT) {
// try to fetch the AWTThreadingPlugin
Exception error=null;
try {
threadingPlugin = (ToolkitThreadingPlugin) ReflectionUtil.createInstance("jogamp.opengl.awt.AWTThreadingPlugin", cl);
- } catch (JogampRuntimeException jre) { error = jre; }
+ } catch (final JogampRuntimeException jre) { error = jre; }
if( Mode.ST_AWT == mode && null==threadingPlugin ) {
throw new GLException("Mode is AWT, but class 'jogamp.opengl.awt.AWTThreadingPlugin' is not available", error);
}
@@ -139,9 +127,9 @@ public class ThreadingImpl {
public static boolean isX11() { return _isX11; }
public static Mode getMode() { return mode; }
- /** If an implementation of the javax.media.opengl APIs offers a
- multithreading option but the default behavior is single-threading,
- this API provides a mechanism for end users to disable single-threading
+ /** If an implementation of the javax.media.opengl APIs offers a
+ multithreading option but the default behavior is single-threading,
+ this API provides a mechanism for end users to disable single-threading
in this implementation. Users are strongly discouraged from
calling this method unless they are aware of all of the
consequences and are prepared to enforce some amount of
@@ -151,11 +139,13 @@ public class ThreadingImpl {
GLPbuffer. Currently there is no supported way to re-enable it
once disabled, partly to discourage careless use of this
method. This method should be called as early as possible in an
- application. */
+ application. */
public static final void disableSingleThreading() {
- singleThreaded = false;
- if (Debug.verbose()) {
- System.err.println("Application forced disabling of single-threading of javax.media.opengl implementation");
+ if( Mode.MT != mode ) {
+ singleThreaded = false;
+ if (Debug.verbose()) {
+ System.err.println("Application forced disabling of single-threading of javax.media.opengl implementation");
+ }
}
}
@@ -165,25 +155,31 @@ public class ThreadingImpl {
return singleThreaded;
}
- /** Indicates whether the current thread is the single thread on
- which this implementation of the javax.media.opengl APIs
- performs all of its OpenGL-related work. This method should only
- be called if the single-thread model is in effect. */
+ /**
+ * Indicates whether the current thread is capable of
+ * performing OpenGL-related work.
+ * <p>
+ * Method always returns <code>true</code>
+ * if {@link #getMode()} == {@link Mode#MT} or {@link #isSingleThreaded()} == <code>false</code>.
+ * </p>
+ */
public static final boolean isOpenGLThread() throws GLException {
- if(null!=threadingPlugin) {
+ if( Mode.MT == mode || !singleThreaded ) {
+ return true;
+ } else if( null != threadingPlugin ) {
return threadingPlugin.isOpenGLThread();
- }
-
- switch (mode) {
- case ST_AWT:
- throw new InternalError();
- case ST_WORKER:
- return GLWorkerThread.isWorkerThread();
- default:
- throw new InternalError("Illegal single-threading mode " + mode);
+ } else {
+ switch (mode) {
+ case ST_AWT:
+ throw new InternalError();
+ case ST_WORKER:
+ return GLWorkerThread.isWorkerThread();
+ default:
+ throw new InternalError("Illegal single-threading mode " + mode);
+ }
}
}
-
+
public static final boolean isToolkitThread() throws GLException {
if(null!=threadingPlugin) {
return threadingPlugin.isToolkitThread();
@@ -200,7 +196,7 @@ public class ThreadingImpl {
false). It is up to the end user to check to see whether the
current thread is the OpenGL thread and either execute the
Runnable directly or perform the work inside it. */
- public static final void invokeOnOpenGLThread(boolean wait, Runnable r) throws GLException {
+ public static final void invokeOnOpenGLThread(final boolean wait, final Runnable r) throws GLException {
if(null!=threadingPlugin) {
threadingPlugin.invokeOnOpenGLThread(wait, r);
return;
@@ -211,19 +207,23 @@ public class ThreadingImpl {
invokeOnWorkerThread(wait, r);
break;
+ case MT:
+ r.run();
+ break;
+
default:
throw new InternalError("Illegal single-threading mode " + mode);
}
}
-
- public static final void invokeOnWorkerThread(boolean wait, Runnable r) throws GLException {
+
+ public static final void invokeOnWorkerThread(final boolean wait, final Runnable r) throws GLException {
GLWorkerThread.start(); // singleton start via volatile-dbl-checked-locking
try {
GLWorkerThread.invoke(wait, r);
- } catch (InvocationTargetException e) {
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
throw new GLException(e);
- }
+ }
}
}
diff --git a/src/jogl/classes/jogamp/opengl/ToolkitThreadingPlugin.java b/src/jogl/classes/jogamp/opengl/ToolkitThreadingPlugin.java
index 22972953a..06fb0fe91 100644
--- a/src/jogl/classes/jogamp/opengl/ToolkitThreadingPlugin.java
+++ b/src/jogl/classes/jogamp/opengl/ToolkitThreadingPlugin.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -46,7 +46,7 @@ public interface ToolkitThreadingPlugin {
/** Indicates whether the current thread is the designated toolkit thread,
if such semantics exists. */
public boolean isToolkitThread() throws GLException;
-
+
/** Indicates whether the current thread is the thread on
which this implementation of the javax.media.opengl APIs
performs all of its OpenGL-related work. This method should only
diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
index 23f9161d4..495887e0f 100644
--- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
+++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -28,18 +28,27 @@
package jogamp.opengl.android.av;
import java.io.IOException;
+import java.util.List;
import javax.media.opengl.GL;
import javax.media.opengl.GLES2;
+import javax.media.opengl.GLException;
+import com.jogamp.common.os.AndroidVersion;
+import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.util.TimeFrameI;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureSequence;
+import jogamp.common.os.PlatformPropsImpl;
import jogamp.common.os.android.StaticContext;
import jogamp.opengl.util.av.GLMediaPlayerImpl;
-
import android.graphics.SurfaceTexture;
import android.graphics.SurfaceTexture.OnFrameAvailableListener;
+import android.hardware.Camera;
import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.view.Surface;
@@ -47,6 +56,11 @@ import android.view.Surface;
* Android implementation utilizes API level 14 (4.0.? ICS) features
* as listed below.
* <p>
+ * Implementation is single threaded only, since we are not able to utilize multiple textures.
+ * We would need to add an implementation for API level 16 using MediaCodec/MediaExtractor
+ * to expose multithreading on multiple surface/textures.
+ * </p>
+ * <p>
* We utilize the {@link MediaPlayer} with direct to texture streaming.
* The MediaPlayer uses <code>libstagefright</code> to access the OpenMAX AL implementation
* for hardware decoding.
@@ -55,49 +69,65 @@ import android.view.Surface;
* <li>Android API Level 14: {@link MediaPlayer#setSurface(Surface)}</li>
* <li>Android API Level 14: {@link Surface#Surface(android.graphics.SurfaceTexture)}</li>
* </ul>
+ * <p>
+ * Since the MediaPlayer API can only deal w/ <i>one</i> SurfaceTexture,
+ * we enforce <code>textureCount</code> = 2 via {@link #validateTextureCount(int)}
+ * and duplicate the single texture via {@link #createTexFrames(GL, int)} .. etc.
+ * Two instanceds of TextureFrame are required due our framework implementation w/ Ringbuffer and 'lastFrame' access.
+ * </p>
*/
public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
static final boolean available;
-
+
static {
- available = true; // default .. TODO: May restrict availability ?
+ boolean _avail = false;
+ if(PlatformPropsImpl.OS_TYPE.equals(Platform.OSType.ANDROID)) {
+ if(AndroidVersion.SDK_INT >= 14) {
+ _avail = true;
+ }
+ }
+ available = _avail;
}
-
+
public static final boolean isAvailable() { return available; }
-
- MediaPlayer mp;
- volatile boolean updateSurface = false;
- Object updateSurfaceLock = new Object();
- TextureSequence.TextureFrame lastTexFrame = null;
+
+ private MediaPlayer mp;
+ private Camera cam;
+ private long playStart = 0;
+ private volatile boolean updateSurface = false;
+ private final Object updateSurfaceLock = new Object();
+ private SurfaceTextureFrame singleSTexFrame = null;
+ private int sTexFrameCount = 0;
+ private boolean sTexFrameAttached = false;
+ private volatile boolean eos = false;
/**
private static String toString(MediaPlayer m) {
if(null == m) return "<nil>";
return "MediaPlayer[playing "+m.isPlaying()+", pos "+m.getCurrentPosition()/1000.0f+"s, "+m.getVideoWidth()+"x"+m.getVideoHeight()+"]";
} */
-
+
public AndroidGLMediaPlayerAPI14() {
super();
if(!available) {
throw new RuntimeException("AndroidGLMediaPlayerAPI14 not available");
}
this.setTextureTarget(GLES2.GL_TEXTURE_EXTERNAL_OES);
- this.setTextureCount(1);
- mp = new MediaPlayer();
}
@Override
- protected boolean setPlaySpeedImpl(float rate) {
+ protected final boolean setPlaySpeedImpl(final float rate) {
+ // FIXME
return false;
}
@Override
- protected boolean startImpl() {
- if(null != mp) {
+ protected final boolean setAudioVolumeImpl(final float v) {
+ if(null != mp) {
try {
- mp.start();
+ mp.setVolume(v, v);
return true;
- } catch (IllegalStateException ise) {
+ } catch (final IllegalStateException ise) {
if(DEBUG) {
ise.printStackTrace();
}
@@ -107,13 +137,26 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
}
@Override
- protected boolean pauseImpl() {
+ protected final boolean playImpl() {
+ playStart = Platform.currentTimeMillis();
if(null != mp) {
- wakeUp(false);
try {
- mp.pause();
+ mp.start();
+ eos = false;
+ mp.setOnCompletionListener(onCompletionListener);
+ return true;
+ } catch (final IllegalStateException ise) {
+ if(DEBUG) {
+ ise.printStackTrace();
+ }
+ }
+ } else if( null != cam ) {
+ try {
+ if( sTexFrameAttached ) {
+ cam.startPreview();
+ }
return true;
- } catch (IllegalStateException ise) {
+ } catch (final IllegalStateException ise) {
if(DEBUG) {
ise.printStackTrace();
}
@@ -123,13 +166,23 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
}
@Override
- protected boolean stopImpl() {
+ protected final boolean pauseImpl() {
if(null != mp) {
wakeUp(false);
try {
- mp.stop();
+ mp.pause();
return true;
- } catch (IllegalStateException ise) {
+ } catch (final IllegalStateException ise) {
+ if(DEBUG) {
+ ise.printStackTrace();
+ }
+ }
+ } else if( null != cam ) {
+ wakeUp(false);
+ try {
+ cam.stopPreview();
+ return true;
+ } catch (final IllegalStateException ise) {
if(DEBUG) {
ise.printStackTrace();
}
@@ -137,9 +190,9 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
}
return false;
}
-
+
@Override
- protected int seekImpl(int msec) {
+ protected final int seekImpl(final int msec) {
if(null != mp) {
mp.seekTo(msec);
return mp.getCurrentPosition();
@@ -147,41 +200,7 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
return 0;
}
- @Override
- protected TextureSequence.TextureFrame getLastTextureImpl() {
- return lastTexFrame;
- }
-
- @Override
- protected TextureSequence.TextureFrame getNextTextureImpl(GL gl, boolean blocking) {
- if(null != stex && null != mp) {
- // Only block once, no while-loop.
- // This relaxes locking code of non crucial resources/events.
- boolean update = updateSurface;
- if(!update && blocking) {
- synchronized(updateSurfaceLock) {
- if(!updateSurface) { // volatile OK.
- try {
- updateSurfaceLock.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- updateSurface = false;
- update = true;
- }
- }
- if(update) {
- stex.updateTexImage();
- // stex.getTransformMatrix(atex.getSTMatrix());
- lastTexFrame=texFrames[0];
- }
-
- }
- return lastTexFrame;
- }
-
- private void wakeUp(boolean newFrame) {
+ private void wakeUp(final boolean newFrame) {
synchronized(updateSurfaceLock) {
if(newFrame) {
updateSurface = true;
@@ -189,74 +208,287 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
updateSurfaceLock.notifyAll();
}
}
-
+
@Override
- protected int getCurrentPositionImpl() {
- return null != mp ? mp.getCurrentPosition() : 0;
- }
+ protected final int getAudioPTSImpl() { return null != mp ? mp.getCurrentPosition() : 0; }
@Override
- protected void destroyImpl(GL gl) {
+ protected final void destroyImpl(final GL gl) {
if(null != mp) {
wakeUp(false);
+ try {
+ mp.stop();
+ } catch (final IllegalStateException ise) {
+ if(DEBUG) {
+ ise.printStackTrace();
+ }
+ }
mp.release();
mp = null;
}
+ if( null != cam ) {
+ wakeUp(false);
+ try {
+ cam.stopPreview();
+ } catch (final IllegalStateException ise) {
+ if(DEBUG) {
+ ise.printStackTrace();
+ }
+ }
+ cam.release();
+ cam = null;
+ }
}
-
- SurfaceTexture stex = null;
-
+
+ public static class SurfaceTextureFrame extends TextureSequence.TextureFrame {
+ public SurfaceTextureFrame(final Texture t, final SurfaceTexture stex) {
+ super(t);
+ this.surfaceTex = stex;
+ }
+
+ public String toString() {
+ return "SurfaceTextureFrame[pts " + pts + " ms, l " + duration + " ms, texID "+ texture.getTextureObject() + ", " + surfaceTex + "]";
+ }
+ public final SurfaceTexture surfaceTex;
+ }
+
@Override
- protected void initGLStreamImpl(GL gl, int[] texNames) throws IOException {
- if(null!=mp && null!=urlConn) {
+ protected final void initStreamImpl(final int vid, final int aid) throws IOException {
+ if( null == getUri() ) {
+ return;
+ }
+ if( null == mp && null == cam ) {
+ if( null == cameraPath ) {
+ mp = new MediaPlayer();
+ } else {
+ int cameraId = 0;
+ try {
+ cameraId = Integer.parseInt(cameraPath.decode());
+ } catch (final NumberFormatException nfe) {}
+ if( 0 <= cameraId && cameraId < Camera.getNumberOfCameras() ) {
+ cam = Camera.open(cameraId);
+ } else {
+ cam = Camera.open();
+ }
+ }
+ }
+
+ if(null!=mp) {
+ if( GLMediaPlayer.STREAM_ID_NONE == aid ) {
+ mp.setVolume(0f, 0f);
+ // FIXME: Disable audio handling
+ } // else FIXME: Select aid !
+ // Note: Both FIXMEs seem to be n/a via Android's MediaPlayer -> Switch to API level 16 MediaCodec/MediaExtractor ..
try {
- final Uri uri = Uri.parse(urlConn.getURL().toExternalForm());
- mp.setDataSource(StaticContext.getContext(), uri);
- } catch (IllegalArgumentException e) {
+ final Uri _uri = Uri.parse(getUri().toString());
+ mp.setDataSource(StaticContext.getContext(), _uri);
+ } catch (final IllegalArgumentException e) {
throw new RuntimeException(e);
- } catch (SecurityException e) {
+ } catch (final SecurityException e) {
throw new RuntimeException(e);
- } catch (IllegalStateException e) {
+ } catch (final IllegalStateException e) {
throw new RuntimeException(e);
}
- stex = new SurfaceTexture(texNames[0]); // only 1 texture
- stex.setOnFrameAvailableListener(onFrameAvailableListener);
- final Surface surf = new Surface(stex);
- mp.setSurface(surf);
- surf.release();
+ mp.setSurface(null);
try {
mp.prepare();
- } catch (IOException ioe) {
- throw new IOException("MediaPlayer failed to process stream <"+urlConn.getURL().toExternalForm()+">: "+ioe.getMessage(), ioe);
+ } catch (final IOException ioe) {
+ throw new IOException("MediaPlayer failed to process stream <"+getUri().toString()+">: "+ioe.getMessage(), ioe);
}
- updateAttributes(mp.getVideoWidth(), mp.getVideoHeight(),
- 0, 0, 0,
- 0f, 0, mp.getDuration(),
- null, null);
+ final int r_aid = GLMediaPlayer.STREAM_ID_NONE == aid ? GLMediaPlayer.STREAM_ID_NONE : 1 /* fake */;
+ final String icodec = "android";
+ updateAttributes(0 /* fake */, r_aid,
+ mp.getVideoWidth(), mp.getVideoHeight(), 0,
+ 0, 0, 0f,
+ 0, 0, mp.getDuration(), icodec, icodec);
+ /**
+ mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(final MediaPlayer mp) {
+ final int r_aid = GLMediaPlayer.STREAM_ID_NONE == aid ? GLMediaPlayer.STREAM_ID_NONE : 1; // fake
+ final String icodec = "android";
+ updateAttributes(0, r_aid, // fake
+ mp.getVideoWidth(), mp.getVideoHeight(), 0,
+ 0, 0, 0f,
+ 0, 0, mp.getDuration(), icodec, icodec);
+ }
+ });
+ mp.prepareAsync();
+ *
+ */
+ } else if( null != cam ) {
+ final String icodec = "android";
+ final int[] fpsRange = { 0, 0 };
+ final Camera.Parameters p = cam.getParameters();
+ p.getPreviewFpsRange(fpsRange);
+ final Camera.Size size = p.getPreviewSize();
+ if( DEBUG ) {
+ final int picFmt = p.getPictureFormat();
+ final Camera.Size prefSize = p.getPreferredPreviewSizeForVideo();
+ System.err.println("MediaPlayer.Camera: fps "+fpsRange[0]+".."+fpsRange[1]+", size[pref "+camSz2Str(prefSize)+", cur "+camSz2Str(size)+"], fmt "+picFmt);
+ final List<Camera.Size> supSizes = p.getSupportedVideoSizes();
+ if( null != supSizes ) {
+ for(int i=0; i<supSizes.size(); i++) {
+ System.err.println("size #"+i+": "+camSz2Str(supSizes.get(i)));
+ }
+ }
+ }
+ updateAttributes(0 /* fake */, GLMediaPlayer.STREAM_ID_NONE,
+ size.width, size.height,
+ 0, 0, 0,
+ fpsRange[1]/1000f,
+ 0, 0, 0, icodec, icodec);
+ }
+ }
+ private static String camSz2Str(final Camera.Size csize) {
+ if( null != csize ) {
+ return csize.width+"x"+csize.height;
+ } else {
+ return "n/a";
}
}
-
@Override
- protected TextureSequence.TextureFrame createTexImage(GL gl, int idx, int[] tex) {
- lastTexFrame = new TextureSequence.TextureFrame( createTexImageImpl(gl, idx, tex, width, height, true) );
- return lastTexFrame;
+ protected final void initGLImpl(final GL gl) throws IOException, GLException {
+ // NOP
}
-
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns {@link #TEXTURE_COUNT_MIN}, using a single texture
+ * </p>
+ */
@Override
- protected void destroyTexImage(GL gl, TextureSequence.TextureFrame imgTex) {
- if(null != stex) {
- stex.release();
- stex = null;
+ protected int validateTextureCount(final int desiredTextureCount) {
+ return TEXTURE_COUNT_MIN;
+ }
+
+ @Override
+ protected final int getNextTextureImpl(final GL gl, final TextureFrame nextFrame) {
+ int pts = TimeFrameI.INVALID_PTS;
+ if(null != mp || null != cam) {
+ final SurfaceTextureFrame sTexFrame = null != nextFrame ? (SurfaceTextureFrame) nextFrame : singleSTexFrame;
+ final SurfaceTexture surfTex = sTexFrame.surfaceTex;
+ if( !sTexFrameAttached ) {
+ sTexFrameAttached = true;
+ final Surface surface;
+ if( null != mp ) {
+ surface = new Surface(sTexFrame.surfaceTex);
+ mp.setSurface(surface);
+ } else {
+ surface = null;
+ try {
+ cam.setPreviewTexture(sTexFrame.surfaceTex);
+ cam.startPreview();
+ } catch (final IOException ioe) {
+ throw new RuntimeException("MediaPlayer failed to process stream <"+getUri().toString()+">: "+ioe.getMessage(), ioe);
+ }
+ }
+ if( null != surface ) {
+ surface.release();
+ }
+ surfTex.setOnFrameAvailableListener(onFrameAvailableListener);
+ }
+ if( eos || (null != mp && !mp.isPlaying() ) ) {
+ eos = true;
+ pts = TimeFrameI.END_OF_STREAM_PTS;
+ } else {
+ // Only block once, no while-loop.
+ // This relaxes locking code of non crucial resources/events.
+ boolean update = updateSurface;
+ if( !update ) {
+ synchronized(updateSurfaceLock) {
+ if(!updateSurface) { // volatile OK.
+ try {
+ updateSurfaceLock.wait();
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ update = updateSurface;
+ updateSurface = false;
+ }
+ }
+ if(update) {
+ surfTex.updateTexImage();
+ // nextFrame.setPTS( (int) ( nextSTex.getTimestamp() / 1000000L ) ); // nano -9 -> milli -3
+ if( null != mp ) {
+ pts = mp.getCurrentPosition();
+ } else {
+ pts = (int) ( Platform.currentTimeMillis() - playStart );
+ }
+ // stex.getTransformMatrix(atex.getSTMatrix());
+ }
+ }
+ sTexFrame.setPTS( pts );
+ }
+ return pts;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Creates only one single texture and duplicated content to 2 TextureFrames
+ * </p>
+ */
+ @Override
+ protected TextureFrame[] createTexFrames(final GL gl, final int count) {
+ final int[] texNames = new int[1];
+ gl.glGenTextures(1, texNames, 0);
+ final int err = gl.glGetError();
+ if( GL.GL_NO_ERROR != err ) {
+ throw new RuntimeException("TextureNames creation failed (num: 1/"+count+"): err "+toHexString(err));
+ }
+ final TextureFrame[] texFrames = new TextureFrame[count];
+ for(int i=0; i<count; i++) {
+ texFrames[i] = createTexImage(gl, texNames[0]);
}
- lastTexFrame = null;
- super.destroyTexImage(gl, imgTex);
+ return texFrames;
}
-
- protected OnFrameAvailableListener onFrameAvailableListener = new OnFrameAvailableListener() {
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns the single texture, which is created at 1st call.
+ * </p>
+ */
+ @Override
+ protected final TextureSequence.TextureFrame createTexImage(final GL gl, final int texName) {
+ sTexFrameCount++;
+ if( 1 == sTexFrameCount ) {
+ singleSTexFrame = new SurfaceTextureFrame( createTexImageImpl(gl, texName, getWidth(), getHeight()), new SurfaceTexture(texName) );
+ }
+ return singleSTexFrame;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Destroys the single texture at last call.
+ * </p>
+ */
+ @Override
+ protected final void destroyTexFrame(final GL gl, final TextureSequence.TextureFrame frame) {
+ sTexFrameCount--;
+ if( 0 == sTexFrameCount ) {
+ singleSTexFrame = null;
+ sTexFrameAttached = false;
+ final SurfaceTextureFrame sFrame = (SurfaceTextureFrame) frame;
+ sFrame.surfaceTex.release();
+ super.destroyTexFrame(gl, frame);
+ }
+ }
+
+ private final OnFrameAvailableListener onFrameAvailableListener = new OnFrameAvailableListener() {
@Override
- public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+ public void onFrameAvailable(final SurfaceTexture surfaceTexture) {
wakeUp(true);
- AndroidGLMediaPlayerAPI14.this.newFrameAvailable();
- }
- };
+ }
+ };
+
+ private final OnCompletionListener onCompletionListener = new OnCompletionListener() {
+ @Override
+ public void onCompletion(final MediaPlayer mp) {
+ eos = true;
+ }
+ };
}
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
index 983f11133..3f8910fb5 100644
--- a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
+++ b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -44,7 +44,8 @@ import java.awt.EventQueue;
import javax.media.opengl.GLException;
-import jogamp.common.awt.AWTEDTExecutor;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+
import jogamp.opengl.GLWorkerThread;
import jogamp.opengl.ThreadingImpl;
import jogamp.opengl.ToolkitThreadingPlugin;
@@ -53,10 +54,12 @@ public class AWTThreadingPlugin implements ToolkitThreadingPlugin {
public AWTThreadingPlugin() {}
+ @Override
public final boolean isToolkitThread() throws GLException {
return EventQueue.isDispatchThread();
}
-
+
+ @Override
public final boolean isOpenGLThread() throws GLException {
switch (ThreadingImpl.getMode()) {
case ST_AWT:
@@ -82,7 +85,8 @@ public class AWTThreadingPlugin implements ToolkitThreadingPlugin {
}
}
- public final void invokeOnOpenGLThread(boolean wait, Runnable r) throws GLException {
+ @Override
+ public final void invokeOnOpenGLThread(final boolean wait, final Runnable r) throws GLException {
switch (ThreadingImpl.getMode()) {
case ST_AWT:
// FIXME: ideally should run all OpenGL work on the Java2D QFT
@@ -94,11 +98,7 @@ public class AWTThreadingPlugin implements ToolkitThreadingPlugin {
// QFT which is not allowed. For now, on X11 platforms,
// continue to perform this work on the EDT.
if (wait && Java2D.isOGLPipelineActive() && !ThreadingImpl.isX11()) {
- if(wait) {
- Java2D.invokeWithOGLContextCurrent(null, r);
- } else {
-
- }
+ Java2D.invokeWithOGLContextCurrent(null, r);
} else {
AWTEDTExecutor.singleton.invoke(wait, r);
}
@@ -108,6 +108,10 @@ public class AWTThreadingPlugin implements ToolkitThreadingPlugin {
ThreadingImpl.invokeOnWorkerThread(wait, r);
break;
+ case MT:
+ r.run();
+ break;
+
default:
throw new InternalError("Illegal single-threading mode " + ThreadingImpl.getMode());
}
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java
new file mode 100644
index 000000000..a5f5b4702
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java
@@ -0,0 +1,400 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.awt;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.imageio.ImageIO;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+
+import jogamp.opengl.Debug;
+
+import com.jogamp.opengl.util.TileRenderer;
+import com.jogamp.opengl.util.TileRendererBase;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
+
+/**
+ * Implementing AWT {@link Graphics2D} based {@link TileRenderer} <i>painter</i>.
+ * <p>
+ * Maybe utilized for AWT printing.
+ * </p>
+ */
+public class AWTTilePainter {
+ private static final boolean DEBUG_TILES = Debug.debug("TileRenderer.PNG");
+
+ public final TileRenderer renderer;
+ public final int componentCount;
+ public final double scaleMatX, scaleMatY;
+ public final int customTileWidth, customTileHeight, customNumSamples;
+ public final boolean verbose;
+
+ /** Default for OpenGL: True */
+ public boolean flipVertical;
+ /** Default for OpenGL: True */
+ public boolean originBottomLeft;
+ private AWTGLPixelBuffer tBuffer = null;
+ private BufferedImage vFlipImage = null;
+ private Graphics2D g2d = null;
+ private AffineTransform saveAT = null;
+
+ public static void dumpHintsAndScale(final Graphics2D g2d) {
+ final RenderingHints rHints = g2d.getRenderingHints();
+ final Set<Entry<Object, Object>> rEntries = rHints.entrySet();
+ int count = 0;
+ for(final Iterator<Entry<Object, Object>> rEntryIter = rEntries.iterator(); rEntryIter.hasNext(); count++) {
+ final Entry<Object, Object> rEntry = rEntryIter.next();
+ System.err.println("Hint["+count+"]: "+rEntry.getKey()+" -> "+rEntry.getValue());
+ }
+ final AffineTransform aTrans = g2d.getTransform();
+ if( null != aTrans ) {
+ System.err.println(" type "+aTrans.getType());
+ System.err.println(" scale "+aTrans.getScaleX()+" x "+aTrans.getScaleY());
+ System.err.println(" move "+aTrans.getTranslateX()+" x "+aTrans.getTranslateY());
+ System.err.println(" mat "+aTrans);
+ } else {
+ System.err.println(" null transform");
+ }
+ }
+
+ /**
+ * @return resulting number of samples by comparing w/ {@link #customNumSamples} and the caps-config, 0 if disabled
+ */
+ public int getNumSamples(final GLCapabilitiesImmutable caps) {
+ if( 0 > customNumSamples ) {
+ return 0;
+ } else if( 0 < customNumSamples ) {
+ if ( !caps.getGLProfile().isGL2ES3() ) {
+ return 0;
+ }
+ return Math.max(caps.getNumSamples(), customNumSamples);
+ } else {
+ return caps.getNumSamples();
+ }
+ }
+
+ /**
+ * Assumes a configured {@link TileRenderer}, i.e.
+ * an {@link TileRenderer#attachAutoDrawable(GLAutoDrawable) attached}
+ * {@link GLAutoDrawable} with {@link TileRenderer#setTileSize(int, int, int) set tile size}.
+ * <p>
+ * Sets the renderer to {@link TileRenderer#TR_TOP_TO_BOTTOM} row order.
+ * </p>
+ * <p>
+ * <code>componentCount</code> reflects opaque, i.e. 4 if non opaque.
+ * </p>
+ * @param renderer
+ * @param componentCount
+ * @param scaleMatX {@link Graphics2D} {@link Graphics2D#scale(double, double) scaling factor}, i.e. rendering 1/scaleMatX * width pixels
+ * @param scaleMatY {@link Graphics2D} {@link Graphics2D#scale(double, double) scaling factor}, i.e. rendering 1/scaleMatY * height pixels
+ * @param numSamples custom multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples
+ * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param verbose
+ */
+ public AWTTilePainter(final TileRenderer renderer, final int componentCount, final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight, final boolean verbose) {
+ this.renderer = renderer;
+ this.renderer.setGLEventListener(preTileGLEL, postTileGLEL);
+ this.componentCount = componentCount;
+ this.scaleMatX = scaleMatX;
+ this.scaleMatY = scaleMatY;
+ this.customNumSamples = numSamples;
+ this.customTileWidth= tileWidth;
+ this.customTileHeight = tileHeight;
+ this.verbose = verbose;
+ this.flipVertical = true;
+ }
+
+ @Override
+ public String toString() {
+ return "AWTTilePainter[flipVertical "+flipVertical+", startFromBottom "+originBottomLeft+", "+
+ renderer.toString()+"]";
+ }
+
+ /**
+ * @param flipVertical if <code>true</code>, the image will be flipped vertically (Default for OpenGL).
+ * @param originBottomLeft if <code>true</code>, the image's origin is on the bottom left (Default for OpenGL).
+ */
+ public void setGLOrientation(final boolean flipVertical, final boolean originBottomLeft) {
+ this.flipVertical = flipVertical;
+ this.originBottomLeft = originBottomLeft;
+ }
+
+ private static Rectangle2D getClipBounds2D(final Graphics2D g) {
+ final Shape shape = g.getClip();
+ return null != shape ? shape.getBounds2D() : null;
+ }
+ private static Rectangle2D clipNegative(final Rectangle2D in) {
+ if( null == in ) { return null; }
+ double x=in.getX(), y=in.getY(), width=in.getWidth(), height=in.getHeight();
+ if( 0 > x ) {
+ width += x;
+ x = 0;
+ }
+ if( 0 > y ) {
+ height += y;
+ y = 0;
+ }
+ return new Rectangle2D.Double(x, y, width, height);
+ }
+
+ /**
+ * Caches the {@link Graphics2D} instance for rendering.
+ * <p>
+ * Copies the current {@link Graphics2D} {@link AffineTransform}
+ * and scales {@link Graphics2D} w/ <code>scaleMatX</code> x <code>scaleMatY</code>.<br>
+ * After rendering, the {@link AffineTransform} should be reset via {@link #resetGraphics2D()}.
+ * </p>
+ * <p>
+ * Sets the {@link TileRenderer}'s {@link TileRenderer#setImageSize(int, int) image size}
+ * and {@link TileRenderer#setTileOffset(int, int) tile offset} according the
+ * the {@link Graphics2D#getClipBounds() graphics clip bounds}.
+ * </p>
+ * @param g2d Graphics2D instance used for transform and clipping
+ * @param width width of the AWT component in case clipping is null
+ * @param height height of the AWT component in case clipping is null
+ * @throws NoninvertibleTransformException if the {@link Graphics2D}'s {@link AffineTransform} {@link AffineTransform#invert() inversion} fails.
+ * Since inversion is tested before scaling the given {@link Graphics2D}, caller shall ignore the whole <i>term</i>.
+ */
+ public void setupGraphics2DAndClipBounds(final Graphics2D g2d, final int width, final int height) throws NoninvertibleTransformException {
+ this.g2d = g2d;
+ saveAT = g2d.getTransform();
+ if( null == saveAT ) {
+ saveAT = new AffineTransform(); // use identity
+ }
+ // We use double precision for scaling
+ //
+ // Setup original rectangles
+ final Rectangle2D dClipOrigR = getClipBounds2D(g2d);
+ final Rectangle2D dClipOrig = clipNegative(dClipOrigR);
+ final Rectangle2D dImageSizeOrig = new Rectangle2D.Double(0, 0, width, height);
+
+ // Retrieve scaled image-size and clip-bounds
+ // Note: Clip bounds lie within image-size!
+ final Rectangle2D dImageSizeScaled, dClipScaled;
+ {
+ final AffineTransform scaledATI;
+ {
+ final AffineTransform scaledAT = new AffineTransform(saveAT);
+ scaledAT.scale(scaleMatX, scaleMatY);
+ scaledATI = scaledAT.createInverse(); // -> NoninvertibleTransformException
+ }
+ Shape s0 = saveAT.createTransformedShape(dImageSizeOrig); // user in
+ dImageSizeScaled = scaledATI.createTransformedShape(s0).getBounds2D(); // scaled out
+ if( null == dClipOrig ) {
+ dClipScaled = (Rectangle2D) dImageSizeScaled.clone();
+ } else {
+ s0 = saveAT.createTransformedShape(dClipOrig); // user in
+ dClipScaled = scaledATI.createTransformedShape(s0).getBounds2D(); // scaled out
+ }
+ }
+ final Rectangle iClipScaled = dClipScaled.getBounds();
+ final Rectangle iImageSizeScaled = dImageSizeScaled.getBounds();
+ renderer.setImageSize(iImageSizeScaled.width, iImageSizeScaled.height);
+ renderer.clipImageSize(iClipScaled.width, iClipScaled.height);
+ final int clipH = Math.min(iImageSizeScaled.height, iClipScaled.height);
+ // Clip bounds lie within image-size!
+ // GL y-offset is lower-left origin, AWT y-offset upper-left.
+ scaledYOffset = iClipScaled.y;
+ renderer.setTileOffset(iClipScaled.x, iImageSizeScaled.height - ( iClipScaled.y + clipH ));
+
+ // Scale actual Grahics2D matrix
+ g2d.scale(scaleMatX, scaleMatY);
+
+ if( verbose ) {
+ System.err.println("AWT print.0: image "+dImageSizeOrig + " -> " + dImageSizeScaled + " -> " + iImageSizeScaled);
+ System.err.println("AWT print.0: clip "+dClipOrigR + " -> " + dClipOrig + " -> " + dClipScaled + " -> " + iClipScaled);
+ System.err.println("AWT print.0: "+renderer);
+ }
+ }
+ private int scaledYOffset;
+
+ /** See {@ #setupGraphics2DAndClipBounds(Graphics2D)}. */
+ public void resetGraphics2D() {
+ g2d.setTransform(saveAT);
+ }
+
+ /**
+ * Disposes resources and {@link TileRenderer#detachAutoDrawable() detaches}
+ * the {@link TileRenderer}'s {@link GLAutoDrawable}.
+ */
+ public void dispose() {
+ renderer.detachAutoDrawable(); // tile-renderer -> printGLAD
+ g2d = null;
+ if( null != tBuffer ) {
+ tBuffer.dispose();
+ tBuffer = null;
+ }
+ if( null != vFlipImage ) {
+ vFlipImage.flush();
+ vFlipImage = null;
+ }
+ }
+
+ final GLEventListener preTileGLEL = new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {}
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ if( null == tBuffer ) {
+ final int tWidth = renderer.getParam(TileRenderer.TR_TILE_WIDTH);
+ final int tHeight = renderer.getParam(TileRenderer.TR_TILE_HEIGHT);
+ final AWTGLPixelBufferProvider printBufferProvider = new AWTGLPixelBufferProvider( true /* allowRowStride */ );
+ final GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, componentCount);
+ tBuffer = printBufferProvider.allocate(gl, pixelAttribs, tWidth, tHeight, 1, true, 0);
+ renderer.setTileBuffer(tBuffer);
+ if( flipVertical ) {
+ vFlipImage = new BufferedImage(tBuffer.width, tBuffer.height, tBuffer.image.getType());
+ } else {
+ vFlipImage = null;
+ }
+ }
+ if( verbose ) {
+ System.err.println("XXX tile-pre "+renderer);
+ }
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ };
+ static int _counter = 0;
+ final GLEventListener postTileGLEL = new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final DimensionImmutable cis = renderer.getClippedImageSize();
+ final int tWidth = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH);
+ final int tHeight = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT);
+ final int tY = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_Y_POS);
+ final int tYOff = renderer.getParam(TileRenderer.TR_TILE_Y_OFFSET);
+ final int imgYOff = originBottomLeft ? 0 : renderer.getParam(TileRenderer.TR_TILE_HEIGHT) - tHeight; // imgYOff will be cut-off via sub-image
+ final int pX = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS); // tileX == pX
+ final int pY = cis.getHeight() - ( tY - tYOff + tHeight ) + scaledYOffset;
+
+ // Copy temporary data into raster of BufferedImage for faster
+ // blitting Note that we could avoid this copy in the cases
+ // where !offscreenDrawable.isGLOriented(),
+ // but that's the software rendering path which is very slow anyway.
+ final BufferedImage dstImage;
+ if( DEBUG_TILES ) {
+ final String fname = String.format("file_%03d_0_tile_[%02d][%02d]_sz_%03dx%03d_pos0_%03d_%03d_yOff_%03d_pos1_%03d_%03d.png",
+ _counter,
+ renderer.getParam(TileRenderer.TR_CURRENT_COLUMN), renderer.getParam(TileRenderer.TR_CURRENT_ROW),
+ tWidth, tHeight,
+ pX, tY, tYOff, pX, pY).replace(' ', '_');
+ System.err.println("XXX file "+fname);
+ final File fout = new File(fname);
+ try {
+ ImageIO.write(tBuffer.image, "png", fout);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if( flipVertical ) {
+ final BufferedImage srcImage = tBuffer.image;
+ dstImage = vFlipImage;
+ final int[] src = ((DataBufferInt) srcImage.getRaster().getDataBuffer()).getData();
+ final int[] dst = ((DataBufferInt) dstImage.getRaster().getDataBuffer()).getData();
+ if( DEBUG_TILES ) {
+ Arrays.fill(dst, 0x55);
+ }
+ final int incr = tBuffer.width;
+ int srcPos = 0;
+ int destPos = (tHeight - 1) * tBuffer.width;
+ for (; destPos >= 0; srcPos += incr, destPos -= incr) {
+ System.arraycopy(src, srcPos, dst, destPos, incr);
+ }
+ } else {
+ dstImage = tBuffer.image;
+ }
+ if( DEBUG_TILES ) {
+ final String fname = String.format("file_%03d_1_tile_[%02d][%02d]_sz_%03dx%03d_pos0_%03d_%03d_yOff_%03d_pos1_%03d_%03d.png",
+ _counter,
+ renderer.getParam(TileRenderer.TR_CURRENT_COLUMN), renderer.getParam(TileRenderer.TR_CURRENT_ROW),
+ tWidth, tHeight,
+ pX, tY, tYOff, pX, pY).replace(' ', '_');
+ System.err.println("XXX file "+fname);
+ final File fout = new File(fname);
+ try {
+ ImageIO.write(dstImage, "png", fout);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ _counter++;
+ }
+ // Draw resulting image in one shot
+ final BufferedImage outImage = dstImage.getSubimage(0, imgYOff, tWidth, tHeight);
+ final boolean drawDone = g2d.drawImage(outImage, pX, pY, null); // Null ImageObserver since image data is ready.
+ if( verbose ) {
+ final Shape oClip = g2d.getClip();
+ System.err.println("XXX tile-post.X tile 0 / "+imgYOff+" "+tWidth+"x"+tHeight+", clippedImgSize "+cis);
+ System.err.println("XXX tile-post.X pYf "+cis.getHeight()+" - ( "+tY+" - "+tYOff+" + "+tHeight+" ) "+scaledYOffset+" = "+ pY);
+ System.err.println("XXX tile-post.X clip "+oClip+" + "+pX+" / [pY "+tY+", pYOff "+tYOff+", pYf "+pY+"] -> "+g2d.getClip());
+ g2d.setColor(Color.BLACK);
+ g2d.drawRect(pX, pY, tWidth, tHeight);
+ if( null != oClip ) {
+ final Rectangle r = oClip.getBounds();
+ g2d.setColor(Color.YELLOW);
+ g2d.drawRect(r.x, r.y, r.width, r.height);
+ }
+ System.err.println("XXX tile-post.X "+renderer);
+ System.err.println("XXX tile-post.X dst-img "+dstImage.getWidth()+"x"+dstImage.getHeight());
+ System.err.println("XXX tile-post.X out-img "+outImage.getWidth()+"x"+outImage.getHeight());
+ System.err.println("XXX tile-post.X y-flip "+flipVertical+", originBottomLeft "+originBottomLeft+" -> "+pX+"/"+pY+", drawDone "+drawDone);
+ }
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ };
+}
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTUtil.java b/src/jogl/classes/jogamp/opengl/awt/AWTUtil.java
index e15e538c2..e34ec18b6 100644
--- a/src/jogl/classes/jogamp/opengl/awt/AWTUtil.java
+++ b/src/jogl/classes/jogamp/opengl/awt/AWTUtil.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -59,7 +59,7 @@ public class AWTUtil {
isOGLPipelineActive = j2dClazz.getMethod("isOGLPipelineActive", (Class[])null);
isQueueFlusherThread = j2dClazz.getMethod("isQueueFlusherThread", (Class[])null);
j2dOk = true;
- } catch (Exception e) {}
+ } catch (final Exception e) {}
}
}
@@ -84,8 +84,8 @@ public class AWTUtil {
!((Boolean)isQueueFlusherThread.invoke(null, (Object[])null)).booleanValue() ) {
NativeWindowFactory.getAWTToolkitLock().lock();
}
- } catch (Exception e) { j2dOk=false; }
- }
+ } catch (final Exception e) { j2dOk=false; }
+ }
if(!j2dOk) {
NativeWindowFactory.getAWTToolkitLock().lock();
}
@@ -107,8 +107,8 @@ public class AWTUtil {
!((Boolean)isQueueFlusherThread.invoke(null, (Object[])null)).booleanValue() ) {
NativeWindowFactory.getAWTToolkitLock().unlock();
}
- } catch (Exception e) { j2dOk=false; }
- }
+ } catch (final Exception e) { j2dOk=false; }
+ }
if(!j2dOk) {
NativeWindowFactory.getAWTToolkitLock().unlock();
}
diff --git a/src/jogl/classes/jogamp/opengl/awt/Java2D.java b/src/jogl/classes/jogamp/opengl/awt/Java2D.java
index 3dbfefb19..55212025d 100644
--- a/src/jogl/classes/jogamp/opengl/awt/Java2D.java
+++ b/src/jogl/classes/jogamp/opengl/awt/Java2D.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -59,6 +59,7 @@ import javax.media.opengl.GLProfile;
import com.jogamp.common.os.Platform;
+import jogamp.common.os.PlatformPropsImpl;
import jogamp.opengl.Debug;
@@ -69,6 +70,7 @@ public class Java2D {
private static boolean DEBUG = Debug.debug("Java2D");
private static boolean isHeadless;
private static boolean isOGLPipelineActive;
+ private static boolean isOGLPipelineResourceCompatible;
private static Method invokeWithOGLContextCurrentMethod;
private static Method isQueueFlusherThreadMethod;
private static Method getOGLViewportMethod;
@@ -115,32 +117,51 @@ public class Java2D {
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
if (DEBUG) {
System.err.println("Checking for Java2D/OpenGL support");
}
- Throwable catched = null;
+ Throwable caught = null;
try {
isHeadless = true;
// Figure out whether the default graphics configuration is an
// OpenGL graphics configuration
- GraphicsConfiguration cfg =
- GraphicsEnvironment.getLocalGraphicsEnvironment().
- getDefaultScreenDevice().
- getDefaultConfiguration();
+ final GraphicsConfiguration cfg;
+ final String cfgName;
+ final boolean java2dOGLDisabledByOS = PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS;
+ final boolean java2dOGLDisabledByProp;
+ {
+ boolean enabled = true;
+ final String sVal = System.getProperty("sun.java2d.opengl");
+ if( null != sVal ) {
+ enabled = Boolean.valueOf(sVal);
+ }
+ java2dOGLDisabledByProp = !enabled;
+ }
+ if( !java2dOGLDisabledByProp && !java2dOGLDisabledByOS ) {
+ cfg = GraphicsEnvironment.getLocalGraphicsEnvironment().
+ getDefaultScreenDevice().getDefaultConfiguration();
+ cfgName = cfg.getClass().getName();
+ } else {
+ if (DEBUG) {
+ System.err.println("Java2D support disabled: by Property "+java2dOGLDisabledByProp+", by OS "+java2dOGLDisabledByOS);
+ }
+ cfg = null;
+ cfgName = "nil";
+ }
// If we get here, we aren't running in headless mode
isHeadless = false;
- String name = cfg.getClass().getName();
if (DEBUG) {
- System.err.println("Java2D support: default GraphicsConfiguration = " + name);
+ System.err.println("Java2D support: default GraphicsConfiguration = " + cfgName);
}
- isOGLPipelineActive = Platform.OS_TYPE != Platform.OSType.MACOS &&
- (name.startsWith("sun.java2d.opengl"));
+ isOGLPipelineActive = cfgName.startsWith("sun.java2d.opengl");
+ isOGLPipelineResourceCompatible = isOGLPipelineActive;
if (isOGLPipelineActive) {
try {
// Try to get methods we need to integrate
- Class<?> utils = Class.forName("sun.java2d.opengl.OGLUtilities");
+ final Class<?> utils = Class.forName("sun.java2d.opengl.OGLUtilities");
invokeWithOGLContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLContextCurrent",
new Class[] {
Graphics.class,
@@ -152,120 +173,123 @@ public class Java2D {
new Class[] {});
isQueueFlusherThreadMethod.setAccessible(true);
- getOGLViewportMethod = utils.getDeclaredMethod("getOGLViewport",
- new Class[] {
- Graphics.class,
- Integer.TYPE,
- Integer.TYPE
- });
- getOGLViewportMethod.setAccessible(true);
-
- getOGLScissorBoxMethod = utils.getDeclaredMethod("getOGLScissorBox",
- new Class[] {
- Graphics.class
- });
- getOGLScissorBoxMethod.setAccessible(true);
-
- getOGLSurfaceIdentifierMethod = utils.getDeclaredMethod("getOGLSurfaceIdentifier",
+ if( isOGLPipelineResourceCompatible ) {
+ getOGLViewportMethod = utils.getDeclaredMethod("getOGLViewport",
+ new Class[] {
+ Graphics.class,
+ Integer.TYPE,
+ Integer.TYPE
+ });
+ getOGLViewportMethod.setAccessible(true);
+
+ getOGLScissorBoxMethod = utils.getDeclaredMethod("getOGLScissorBox",
+ new Class[] {
+ Graphics.class
+ });
+ getOGLScissorBoxMethod.setAccessible(true);
+
+ getOGLSurfaceIdentifierMethod = utils.getDeclaredMethod("getOGLSurfaceIdentifier",
+ new Class[] {
+ Graphics.class
+ });
+ getOGLSurfaceIdentifierMethod.setAccessible(true);
+
+ // Try to get additional methods required for proper FBO support
+ fbObjectSupportInitialized = true;
+ try {
+ invokeWithOGLSharedContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLSharedContextCurrent",
+ new Class[] {
+ GraphicsConfiguration.class,
+ Runnable.class
+ });
+ invokeWithOGLSharedContextCurrentMethod.setAccessible(true);
+
+ getOGLSurfaceTypeMethod = utils.getDeclaredMethod("getOGLSurfaceType",
new Class[] {
Graphics.class
});
- getOGLSurfaceIdentifierMethod.setAccessible(true);
-
- // Try to get additional methods required for proper FBO support
- fbObjectSupportInitialized = true;
- try {
- invokeWithOGLSharedContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLSharedContextCurrent",
- new Class[] {
- GraphicsConfiguration.class,
- Runnable.class
- });
- invokeWithOGLSharedContextCurrentMethod.setAccessible(true);
-
- getOGLSurfaceTypeMethod = utils.getDeclaredMethod("getOGLSurfaceType",
- new Class[] {
- Graphics.class
- });
- getOGLSurfaceTypeMethod.setAccessible(true);
- } catch (Exception e) {
- fbObjectSupportInitialized = false;
- if (DEBUG) {
- e.printStackTrace();
- System.err.println("Info: Disabling Java2D/JOGL FBO support");
- }
- }
-
- // Try to get an additional method for FBO support in recent Mustang builds
- try {
- getOGLTextureTypeMethod = utils.getDeclaredMethod("getOGLTextureType",
- new Class[] {
- Graphics.class
- });
- getOGLTextureTypeMethod.setAccessible(true);
- } catch (Exception e) {
- if (DEBUG) {
- e.printStackTrace();
- System.err.println("Info: GL_ARB_texture_rectangle FBO support disabled");
- }
- }
-
- // Try to set up APIs for enabling the bridge on OS X,
- // where it isn't possible to create generalized
- // external GLDrawables
- Class<?> cglSurfaceData = null;
- try {
- cglSurfaceData = Class.forName("sun.java2d.opengl.CGLSurfaceData");
- } catch (Exception e) {
- if (DEBUG) {
- e.printStackTrace();
- System.err.println("Info: Unable to find class sun.java2d.opengl.CGLSurfaceData for OS X");
- }
- }
- if (cglSurfaceData != null) {
- // FIXME: for now, assume that FBO support is not enabled on OS X
- fbObjectSupportInitialized = false;
-
- // We need to find these methods in order to make the bridge work on OS X
- createOGLContextOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("createOGLContextOnSurface",
- new Class[] {
- Graphics.class,
- Long.TYPE
- });
- createOGLContextOnSurfaceMethod.setAccessible(true);
-
- makeOGLContextCurrentOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("makeOGLContextCurrentOnSurface",
- new Class[] {
- Graphics.class,
- Long.TYPE
- });
- makeOGLContextCurrentOnSurfaceMethod.setAccessible(true);
-
- destroyOGLContextMethod = cglSurfaceData.getDeclaredMethod("destroyOGLContext",
- new Class[] {
- Long.TYPE
- });
- destroyOGLContextMethod.setAccessible(true);
+ getOGLSurfaceTypeMethod.setAccessible(true);
+ } catch (final Exception e) {
+ fbObjectSupportInitialized = false;
+ if (DEBUG) {
+ e.printStackTrace();
+ System.err.println("Info: Disabling Java2D/JOGL FBO support");
+ }
+ }
+
+ // Try to get an additional method for FBO support in recent Mustang builds
+ try {
+ getOGLTextureTypeMethod = utils.getDeclaredMethod("getOGLTextureType",
+ new Class[] {
+ Graphics.class
+ });
+ getOGLTextureTypeMethod.setAccessible(true);
+ } catch (final Exception e) {
+ if (DEBUG) {
+ e.printStackTrace();
+ System.err.println("Info: GL_ARB_texture_rectangle FBO support disabled");
+ }
+ }
+
+ // Try to set up APIs for enabling the bridge on OS X,
+ // where it isn't possible to create generalized
+ // external GLDrawables
+ Class<?> cglSurfaceData = null;
+ try {
+ cglSurfaceData = Class.forName("sun.java2d.opengl.CGLSurfaceData");
+ } catch (final Exception e) {
+ if (DEBUG) {
+ e.printStackTrace();
+ System.err.println("Info: Unable to find class sun.java2d.opengl.CGLSurfaceData for OS X");
+ }
+ }
+ if (cglSurfaceData != null) {
+ // FIXME: for now, assume that FBO support is not enabled on OS X
+ fbObjectSupportInitialized = false;
+
+ // We need to find these methods in order to make the bridge work on OS X
+ createOGLContextOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("createOGLContextOnSurface",
+ new Class[] {
+ Graphics.class,
+ Long.TYPE
+ });
+ createOGLContextOnSurfaceMethod.setAccessible(true);
+
+ makeOGLContextCurrentOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("makeOGLContextCurrentOnSurface",
+ new Class[] {
+ Graphics.class,
+ Long.TYPE
+ });
+ makeOGLContextCurrentOnSurfaceMethod.setAccessible(true);
+
+ destroyOGLContextMethod = cglSurfaceData.getDeclaredMethod("destroyOGLContext",
+ new Class[] {
+ Long.TYPE
+ });
+ destroyOGLContextMethod.setAccessible(true);
+ }
}
- } catch (Exception e) {
- catched = e;
+ } catch (final Exception e) {
+ caught = e;
if (DEBUG) {
System.err.println("Info: Disabling Java2D/JOGL integration");
}
isOGLPipelineActive = false;
+ isOGLPipelineResourceCompatible = false;
}
}
- } catch (HeadlessException e) {
+ } catch (final HeadlessException e) {
// The AWT is running in headless mode, so the Java 2D / JOGL bridge is clearly disabled
- } catch (Error e) {
+ } catch (final Error e) {
// issued on OSX Java7: java.lang.Error: Could not find class: sun.awt.HeadlessGraphicsEnvironment
- catched = e;
+ caught = e;
}
if (DEBUG) {
- if(null != catched) {
- catched.printStackTrace();
+ if(null != caught) {
+ caught.printStackTrace();
}
- System.err.println("JOGL/Java2D integration " + (isOGLPipelineActive ? "enabled" : "disabled"));
+ System.err.println("JOGL/Java2D OGL Pipeline active " + isOGLPipelineActive + ", resourceCompatible "+isOGLPipelineResourceCompatible);
}
return null;
}
@@ -276,6 +300,10 @@ public class Java2D {
return isOGLPipelineActive;
}
+ public static boolean isOGLPipelineResourceCompatible() {
+ return isOGLPipelineResourceCompatible;
+ }
+
public static boolean isFBOEnabled() {
return fbObjectSupportInitialized;
}
@@ -285,17 +313,17 @@ public class Java2D {
try {
return ((Boolean) isQueueFlusherThreadMethod.invoke(null, (Object[])null)).booleanValue();
- } catch (InvocationTargetException e) {
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
-
+
/** Makes current the OpenGL context associated with the passed
Graphics object and runs the given Runnable on the Queue
Flushing Thread in one atomic action. */
- public static void invokeWithOGLContextCurrent(Graphics g, Runnable r) throws GLException {
+ public static void invokeWithOGLContextCurrent(final Graphics g, final Runnable r) throws GLException {
checkActive();
try {
@@ -314,9 +342,9 @@ public class Java2D {
} finally {
AWTUtil.unlockToolkit();
}
- } catch (InvocationTargetException e) {
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
@@ -329,8 +357,8 @@ public class Java2D {
JOGL must share textures and display lists with it. Returns
false if the passed GraphicsConfiguration was not an OpenGL
GraphicsConfiguration. */
- public static boolean invokeWithOGLSharedContextCurrent(GraphicsConfiguration g, Runnable r) throws GLException {
- checkActive();
+ public static boolean invokeWithOGLSharedContextCurrent(final GraphicsConfiguration g, final Runnable r) throws GLException {
+ checkCompatible();
try {
AWTUtil.lockToolkit();
@@ -339,9 +367,9 @@ public class Java2D {
} finally {
AWTUtil.unlockToolkit();
}
- } catch (InvocationTargetException e) {
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
@@ -352,18 +380,18 @@ public class Java2D {
call glViewport() with the returned rectangle's bounds in order
to get correct rendering results. Should only be called from the
Queue Flusher Thread. */
- public static Rectangle getOGLViewport(Graphics g,
- int componentWidth,
- int componentHeight) {
- checkActive();
+ public static Rectangle getOGLViewport(final Graphics g,
+ final int componentWidth,
+ final int componentHeight) {
+ checkCompatible();
try {
return (Rectangle) getOGLViewportMethod.invoke(null, new Object[] {g,
- new Integer(componentWidth),
- new Integer(componentHeight)});
- } catch (InvocationTargetException e) {
+ Integer.valueOf(componentWidth),
+ Integer.valueOf(componentHeight)});
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
@@ -374,14 +402,14 @@ public class Java2D {
method should be called and the resulting rectangle's bounds
passed to a call to glScissor(). Should only be called from the
Queue Flusher Thread. */
- public static Rectangle getOGLScissorBox(Graphics g) {
- checkActive();
+ public static Rectangle getOGLScissorBox(final Graphics g) {
+ checkCompatible();
try {
return (Rectangle) getOGLScissorBoxMethod.invoke(null, new Object[] {g});
- } catch (InvocationTargetException e) {
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
@@ -392,14 +420,14 @@ public class Java2D {
changed and a new external GLDrawable and GLContext should be
created (and the old ones destroyed). Should only be called from
the Queue Flusher Thread.*/
- public static Object getOGLSurfaceIdentifier(Graphics g) {
- checkActive();
+ public static Object getOGLSurfaceIdentifier(final Graphics g) {
+ checkCompatible();
try {
return getOGLSurfaceIdentifierMethod.invoke(null, new Object[] {g});
- } catch (InvocationTargetException e) {
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
@@ -407,8 +435,8 @@ public class Java2D {
/** Returns the underlying surface type for the given Graphics
object. This indicates, in particular, whether Java2D is
currently rendering into a pbuffer or FBO. */
- public static int getOGLSurfaceType(Graphics g) {
- checkActive();
+ public static int getOGLSurfaceType(final Graphics g) {
+ checkCompatible();
try {
// FIXME: fallback path for pre-b73 (?) Mustang builds -- remove
@@ -418,9 +446,9 @@ public class Java2D {
}
return ((Integer) getOGLSurfaceTypeMethod.invoke(null, new Object[] { g })).intValue();
- } catch (InvocationTargetException e) {
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
@@ -428,8 +456,8 @@ public class Java2D {
/** Returns the underlying texture target of the given Graphics
object assuming it is rendering to an FBO. Returns either
GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB. */
- public static int getOGLTextureType(Graphics g) {
- checkActive();
+ public static int getOGLTextureType(final Graphics g) {
+ checkCompatible();
if (getOGLTextureTypeMethod == null) {
return GL.GL_TEXTURE_2D;
@@ -437,9 +465,9 @@ public class Java2D {
try {
return ((Integer) getOGLTextureTypeMethod.invoke(null, new Object[] { g })).intValue();
- } catch (InvocationTargetException e) {
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
@@ -450,7 +478,7 @@ public class Java2D {
used for rendering. FIXME: may need to alter the API in the
future to indicate which GraphicsDevice the source context is
associated with. */
- public static GLContext filterShareContext(GLContext shareContext) {
+ public static GLContext filterShareContext(final GLContext shareContext) {
if (isHeadless)
return shareContext;
@@ -468,7 +496,7 @@ public class Java2D {
context", with which all contexts created by JOGL must share
textures and display lists when the FBO option is enabled for
the Java2D/OpenGL pipeline. */
- public static GLContext getShareContext(GraphicsDevice device) {
+ public static GLContext getShareContext(final GraphicsDevice device) {
initFBOShareContext(device);
// FIXME: for full generality probably need to have multiple of
// these, one per GraphicsConfiguration seen?
@@ -482,41 +510,41 @@ public class Java2D {
/** (Mac OS X-specific) Creates a new OpenGL context on the surface
associated with the given Graphics object, sharing textures and
display lists with the specified (CGLContextObj) share context. */
- public static long createOGLContextOnSurface(Graphics g, long shareCtx) {
- checkActive();
+ public static long createOGLContextOnSurface(final Graphics g, final long shareCtx) {
+ checkCompatible();
try {
- return ((Long) createOGLContextOnSurfaceMethod.invoke(null, new Object[] { g, new Long(shareCtx) })).longValue();
- } catch (InvocationTargetException e) {
+ return ((Long) createOGLContextOnSurfaceMethod.invoke(null, new Object[] { g, Long.valueOf(shareCtx) })).longValue();
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
/** (Mac OS X-specific) Makes the given OpenGL context current on
the surface associated with the given Graphics object. */
- public static boolean makeOGLContextCurrentOnSurface(Graphics g, long ctx) {
- checkActive();
+ public static boolean makeOGLContextCurrentOnSurface(final Graphics g, final long ctx) {
+ checkCompatible();
try {
- return ((Boolean) makeOGLContextCurrentOnSurfaceMethod.invoke(null, new Object[] { g, new Long(ctx) })).booleanValue();
- } catch (InvocationTargetException e) {
+ return ((Boolean) makeOGLContextCurrentOnSurfaceMethod.invoke(null, new Object[] { g, Long.valueOf(ctx) })).booleanValue();
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
/** (Mac OS X-specific) Destroys the given OpenGL context. */
- public static void destroyOGLContext(long ctx) {
- checkActive();
+ public static void destroyOGLContext(final long ctx) {
+ checkCompatible();
try {
- destroyOGLContextMethod.invoke(null, new Object[] { new Long(ctx) });
- } catch (InvocationTargetException e) {
+ destroyOGLContextMethod.invoke(null, new Object[] { Long.valueOf(ctx) });
+ } catch (final InvocationTargetException e) {
throw new GLException(e.getTargetException());
- } catch (Exception e) {
+ } catch (final Exception e) {
throw (InternalError) new InternalError().initCause(e);
}
}
@@ -527,19 +555,26 @@ public class Java2D {
private static void checkActive() {
if (!isOGLPipelineActive()) {
- throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)");
+ throw new GLException("Java2D OpenGL pipeline not active");
+ }
+ }
+
+ private static void checkCompatible() {
+ if ( !isOGLPipelineResourceCompatible() ) {
+ throw new GLException("Java2D OpenGL pipeline not resource compatible");
}
}
private static int getOGLUtilitiesIntField(final String name) {
- Integer i = AccessController.doPrivileged(new PrivilegedAction<Integer>() {
+ final Integer i = AccessController.doPrivileged(new PrivilegedAction<Integer>() {
+ @Override
public Integer run() {
try {
- Class<?> utils = Class.forName("sun.java2d.opengl.OGLUtilities");
- Field f = utils.getField(name);
+ final Class<?> utils = Class.forName("sun.java2d.opengl.OGLUtilities");
+ final Field f = utils.getField(name);
f.setAccessible(true);
return (Integer) f.get(null);
- } catch (Exception e) {
+ } catch (final Exception e) {
if (DEBUG) {
e.printStackTrace();
}
@@ -562,7 +597,7 @@ public class Java2D {
// Note 2: the first execution of this method must not be from the
// Java2D Queue Flusher Thread.
- if (isOGLPipelineActive() &&
+ if (isOGLPipelineResourceCompatible() &&
isFBOEnabled() &&
!initializedJ2DFBOShareContext) {
@@ -576,6 +611,7 @@ public class Java2D {
System.err.println("Starting initialization of J2D FBO share context");
}
invokeWithOGLSharedContextCurrent(device.getDefaultConfiguration(), new Runnable() {
+ @Override
public void run() {
j2dFBOShareContext = GLDrawableFactory.getFactory(GLProfile.getDefault(GLProfile.getDefaultDevice())).createExternalGLContext();
}
diff --git a/src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java b/src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java
deleted file mode 100644
index 4a5b1db54..000000000
--- a/src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.awt;
-
-import jogamp.opengl.*;
-import java.awt.Graphics;
-
-/** Provides a construct by which the shared GLJPanel code can
- * interact with a few methods in the Mac OS X-specific Java2D/JOGL
- * bridge implementation.
- */
-
-public interface Java2DGLContext {
- public void setGraphics(Graphics g);
-}
diff --git a/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java b/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java
index 55fb3f9a2..2f87f01a9 100644
--- a/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java
+++ b/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java
@@ -31,18 +31,18 @@ public class VersionApplet extends Applet {
TextArea tareaCaps;
GLCanvas canvas;
- public static void main(String[] args) {
- Frame frame = new Frame("JOGL Version Applet");
+ public static void main(final String[] args) {
+ final Frame frame = new Frame("JOGL Version Applet");
frame.setSize(800, 600);
frame.setLayout(new BorderLayout());
- VersionApplet va = new VersionApplet();
+ final VersionApplet va = new VersionApplet();
frame.addWindowListener(new ClosingWindowAdapter(frame, va));
va.init();
frame.add(va, BorderLayout.CENTER);
frame.validate();
-
+
frame.setVisible(true);
va.start();
}
@@ -50,11 +50,12 @@ public class VersionApplet extends Applet {
static class ClosingWindowAdapter extends WindowAdapter {
Frame f;
VersionApplet va;
- public ClosingWindowAdapter(Frame f, VersionApplet va) {
+ public ClosingWindowAdapter(final Frame f, final VersionApplet va) {
this.f = f;
this.va = va;
}
- public void windowClosing(WindowEvent ev) {
+ @Override
+ public void windowClosing(final WindowEvent ev) {
f.setVisible(false);
va.stop();
va.destroy();
@@ -68,9 +69,9 @@ public class VersionApplet extends Applet {
if(null != canvas) { return; }
setEnabled(true);
-
- GLProfile glp = GLProfile.getDefault();
- GLCapabilities glcaps = new GLCapabilities(glp);
+
+ final GLProfile glp = GLProfile.getDefault();
+ final GLCapabilities glcaps = new GLCapabilities(glp);
setLayout(new BorderLayout());
String s;
@@ -87,7 +88,7 @@ public class VersionApplet extends Applet {
/*
s = NativeWindowVersion.getInstance().toString();
System.err.println(s);
- tareaVersion.append(NativeWindowVersion.getInstance().toString());
+ tareaVersion.append(NativeWindowVersion.getInstance().toString());
*/
s = JoglVersion.getInstance().toString();
@@ -95,16 +96,16 @@ public class VersionApplet extends Applet {
tareaVersion.append(s);
tareaCaps = new TextArea(120, 20);
- GLDrawableFactory factory = GLDrawableFactory.getFactory(glp);
- List<GLCapabilitiesImmutable> availCaps = factory.getAvailableCapabilities(null);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp);
+ final List<GLCapabilitiesImmutable> availCaps = factory.getAvailableCapabilities(null);
for(int i=0; i<availCaps.size(); i++) {
- s = ((GLCapabilitiesImmutable) availCaps.get(i)).toString();
+ s = availCaps.get(i).toString();
System.err.println(s);
tareaCaps.append(s);
tareaCaps.append(Platform.getNewline());
}
- Container grid = new Container();
+ final Container grid = new Container();
grid.setLayout(new GridLayout(2, 1));
grid.add(tareaVersion);
grid.add(tareaCaps);
@@ -129,24 +130,28 @@ public class VersionApplet extends Applet {
}
}
+ @Override
public void init() {
System.err.println("VersionApplet: init() - begin");
my_init();
System.err.println("VersionApplet: init() - end");
}
+ @Override
public void start() {
System.err.println("VersionApplet: start() - begin");
canvas.setVisible(true);
System.err.println("VersionApplet: start() - end");
}
+ @Override
public void stop() {
System.err.println("VersionApplet: stop() - begin");
canvas.setVisible(false);
System.err.println("VersionApplet: stop() - end");
}
+ @Override
public void destroy() {
System.err.println("VersionApplet: destroy() - start");
my_release();
@@ -154,20 +159,24 @@ public class VersionApplet extends Applet {
}
class GLInfo implements GLEventListener {
- public void init(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
- String s = JoglVersion.getGLInfo(gl, null).toString();
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ final String s = JoglVersion.getGLInfo(gl, null).toString();
System.err.println(s);
tareaVersion.append(s);
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
}
- public void display(GLAutoDrawable drawable) {
+ @Override
+ public void display(final GLAutoDrawable drawable) {
}
- public void dispose(GLAutoDrawable drawable) {
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
}
}
diff --git a/src/jogl/classes/jogamp/opengl/cg/CgPackagePlaceholder.java b/src/jogl/classes/jogamp/opengl/cg/CgPackagePlaceholder.java
new file mode 100644
index 000000000..7a7e1aec0
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/cg/CgPackagePlaceholder.java
@@ -0,0 +1,5 @@
+package jogamp.opengl.cg;
+
+public class CgPackagePlaceholder {
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java
index cddd142e9..8c6091273 100644
--- a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl.egl;
import java.util.*;
@@ -36,8 +36,8 @@ import jogamp.opengl.*;
* Implementation of the DynamicLookupHelper for Desktop ES2 (AMD, ..)
* where EGL and ES2 functions reside within the desktop OpenGL library.
*/
-public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
- static List<String> glueLibNames;
+public final class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
+ static final List<String> glueLibNames;
static {
glueLibNames = new ArrayList<String>();
glueLibNames.add("jogl_mobile");
@@ -47,35 +47,29 @@ public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleIn
super();
}
- /**
- * Might be a desktop GL library, and might need to allow symbol access to subsequent libs.
- *
- * This respects old DRI requirements:<br>
- * <pre>
- * http://dri.sourceforge.net/doc/DRIuserguide.html
- * </pre>
- */
- public boolean shallLinkGlobal() { return true; }
-
+ @Override
public final List<String> getToolGetProcAddressFuncNameList() {
- List<String> res = new ArrayList<String>();
+ final List<String> res = new ArrayList<String>();
res.add("eglGetProcAddress");
return res;
}
- public final long toolGetProcAddress(long toolGetProcAddressHandle, String funcName) {
+ @Override
+ public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) {
return EGL.eglGetProcAddress(toolGetProcAddressHandle, funcName);
}
- public final boolean useToolGetProcAdressFirst(String funcName) {
+ @Override
+ public final boolean useToolGetProcAdressFirst(final String funcName) {
return true;
}
-
- public List<List<String>> getToolLibNames() {
+
+ @Override
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsGL = new ArrayList<String>();
-
- // Be aware that on DRI systems, eg ATI fglrx, etc,
+
+ // Be aware that on DRI systems, eg ATI fglrx, etc,
// you have to set LIBGL_DRIVERS_PATH env variable.
// Eg on Ubuntu 64bit systems this is:
// export LIBGL_DRIVERS_PATH=/usr/lib/fglrx/dri:/usr/lib32/fglrx/dri
@@ -92,15 +86,16 @@ public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleIn
// OSX (guess ES2 on OSX will never happen)
libsGL.add("/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib");
-
+
// last but not least .. the generic one
libsGL.add("GL");
-
+
libsList.add(libsGL);
return libsList;
- }
-
+ }
+
+ @Override
public final List<String> getGlueLibNames() {
return glueLibNames;
- }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
index 06953a8e1..964401244 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
@@ -44,6 +44,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
@@ -51,11 +52,12 @@ import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableImpl;
import com.jogamp.common.nio.Buffers;
-import com.jogamp.common.os.Platform;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+import com.jogamp.opengl.GLRendererQuirks;
-public abstract class EGLContext extends GLContextImpl {
+public class EGLContext extends GLContextImpl {
private boolean eglQueryStringInitialized;
private boolean eglQueryStringAvailable;
private EGLExt _eglExt;
@@ -63,18 +65,18 @@ public abstract class EGLContext extends GLContextImpl {
// EGL extension functions.
private EGLExtProcAddressTable eglExtProcAddressTable;
- EGLContext(GLDrawableImpl drawable,
- GLContext shareWith) {
+ EGLContext(final GLDrawableImpl drawable,
+ final GLContext shareWith) {
super(drawable, shareWith);
}
@Override
- protected void resetStates() {
+ protected void resetStates(final boolean isInit) {
eglQueryStringInitialized = false;
eglQueryStringAvailable = false;
eglExtProcAddressTable = null;
// no inner state _eglExt = null;
- super.resetStates();
+ super.resetStates(isInit);
}
@Override
@@ -112,9 +114,14 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected void makeCurrentImpl() throws GLException {
if (EGL.eglGetCurrentContext() != contextHandle) {
- if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
- throw new GLException("Error making context 0x" +
- Long.toHexString(contextHandle) + " current: error code 0x" + Integer.toHexString(EGL.eglGetError()));
+ final long dpy = drawable.getNativeSurface().getDisplayHandle();
+ if (!EGL.eglMakeCurrent(dpy, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+ throw new GLException("Error making context " + toHexString(contextHandle) +
+ " current on Thread " + getThreadName() +
+ " with display " + toHexString(dpy) +
+ ", drawableWrite " + toHexString(drawable.getHandle()) +
+ ", drawableRead "+ toHexString(drawableRead.getHandle()) +
+ " - Error code " + toHexString(EGL.eglGetError()) + ", " + this);
}
}
}
@@ -122,39 +129,39 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected void releaseImpl() throws GLException {
if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT)) {
- throw new GLException("Error freeing OpenGL context 0x" +
- Long.toHexString(contextHandle) + ": error code 0x" + Integer.toHexString(EGL.eglGetError()));
+ throw new GLException("Error freeing OpenGL context " + toHexString(contextHandle) +
+ ": error code " + toHexString(EGL.eglGetError()));
}
}
@Override
protected void destroyImpl() throws GLException {
- if (!EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), contextHandle)) {
- final int eglError = EGL.eglGetError();
- if(EGL.EGL_SUCCESS != eglError) { /* oops, Mesa EGL impl. may return false, but has no EGL error */
- throw new GLException("Error destroying OpenGL context 0x" +
- Long.toHexString(contextHandle) + ": error code 0x" + Integer.toHexString(eglError));
- }
- }
+ destroyContextARBImpl(contextHandle);
}
@Override
- protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) {
+ protected long createContextARBImpl(final long share, final boolean direct, final int ctp, final int major, final int minor) {
return 0; // FIXME
}
@Override
- protected void destroyContextARBImpl(long _context) {
- // FIXME
+ protected void destroyContextARBImpl(final long _context) {
+ if (!EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), _context)) {
+ final int eglError = EGL.eglGetError();
+ if(EGL.EGL_SUCCESS != eglError) { /* oops, Mesa EGL impl. may return false, but has no EGL error */
+ throw new GLException("Error destroying OpenGL context " + toHexString(_context) +
+ ": error code " + toHexString(eglError));
+ }
+ }
}
@Override
- protected boolean createImpl(GLContextImpl shareWith) throws GLException {
+ protected boolean createImpl(final long shareWithHandle) throws GLException {
final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
final long eglDisplay = config.getScreen().getDevice().getHandle();
final GLProfile glProfile = drawable.getGLProfile();
final long eglConfig = config.getNativeConfig();
- long shareWithHandle = EGL.EGL_NO_CONTEXT;
+ // 0 == EGL.EGL_NO_CONTEXT;
if ( 0 == eglDisplay ) {
throw new GLException("Error: attempted to create an OpenGL context without a display connection");
@@ -165,35 +172,38 @@ public abstract class EGLContext extends GLContextImpl {
try {
// might be unavailable on EGL < 1.2
- if(!EGL.eglBindAPI(EGL.EGL_OPENGL_ES_API)) {
- throw new GLException("Catched: eglBindAPI to ES failed , error 0x"+Integer.toHexString(EGL.eglGetError()));
+ if( !EGL.eglBindAPI(EGL.EGL_OPENGL_ES_API) ) {
+ throw new GLException("Caught: eglBindAPI to ES failed , error "+toHexString(EGL.eglGetError()));
}
- } catch (GLException glex) {
+ } catch (final GLException glex) {
if (DEBUG) {
glex.printStackTrace();
}
}
- if (shareWith != null) {
- shareWithHandle = shareWith.getHandle();
- if (shareWithHandle == 0) {
- throw new GLException("GLContextShareSet returned an invalid OpenGL context");
- }
- }
+ // Cannot check extension 'EGL_KHR_create_context' before having one current!
final IntBuffer contextAttrsNIO;
+ final int contextVersionReq, contextVersionAttr;
{
- final int[] contextAttrs = new int[] {
- EGL.EGL_CONTEXT_CLIENT_VERSION, -1,
- EGL.EGL_NONE
- };
- if (glProfile.usesNativeGLES2()) {
- contextAttrs[1] = 2;
- } else if (glProfile.usesNativeGLES1()) {
- contextAttrs[1] = 1;
+ if ( glProfile.usesNativeGLES3() ) {
+ contextVersionReq = 3;
+ if( GLRendererQuirks.existStickyDeviceQuirk( GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) {
+ contextVersionAttr = 2;
+ } else {
+ contextVersionAttr = 3;
+ }
+ } else if ( glProfile.usesNativeGLES2() ) {
+ contextVersionReq = 2;
+ contextVersionAttr = 2;
+ } else if ( glProfile.usesNativeGLES1() ) {
+ contextVersionReq = 1;
+ contextVersionAttr = 1;
} else {
throw new GLException("Error creating OpenGL context - invalid GLProfile: "+glProfile);
}
+ // EGLExt.EGL_CONTEXT_MAJOR_VERSION_KHR == EGL.EGL_CONTEXT_CLIENT_VERSION
+ final int[] contextAttrs = new int[] { EGL.EGL_CONTEXT_CLIENT_VERSION, contextVersionAttr, EGL.EGL_NONE };
contextAttrsNIO = Buffers.newDirectIntBuffer(contextAttrs);
}
contextHandle = EGL.eglCreateContext(eglDisplay, eglConfig, shareWithHandle, contextAttrsNIO);
@@ -213,8 +223,19 @@ public abstract class EGLContext extends GLContextImpl {
throw new GLException("Error making context " +
toHexString(contextHandle) + " current: error code " + toHexString(EGL.eglGetError()));
}
- setGLFunctionAvailability(true, glProfile.usesNativeGLES2() ? 2 : 1, 0, CTX_PROFILE_ES);
- return true;
+ if( !setGLFunctionAvailability(true, contextVersionReq, 0, CTX_PROFILE_ES,
+ true /* strictMatch */, // always req. strict match
+ false /* withinGLVersionsMapping */) ) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": createImpl: setGLFunctionAvailability FAILED delete "+toHexString(contextHandle));
+ }
+ EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT);
+ EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), contextHandle);
+ contextHandle = 0;
+ return false;
+ } else {
+ return true;
+ }
}
@Override
@@ -251,10 +272,9 @@ public abstract class EGLContext extends GLContextImpl {
@Override
protected final StringBuilder getPlatformExtensionsStringImpl() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
if (!eglQueryStringInitialized) {
- eglQueryStringAvailable =
- getDrawableImpl().getGLDynamicLookupHelper().dynamicLookupFunction("eglQueryString") != 0;
+ eglQueryStringAvailable = getDrawableImpl().getGLDynamicLookupHelper().isFunctionAvailable("eglQueryString");
eglQueryStringInitialized = true;
}
if (eglQueryStringAvailable) {
@@ -268,15 +288,8 @@ public abstract class EGLContext extends GLContextImpl {
}
@Override
- protected boolean setSwapIntervalImpl(int interval) {
- // FIXME !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- // eglSwapInterval(..) issued:
- // Android 4.0.3 / Pandaboard ES / PowerVR SGX 540: crashes
- // FIXME !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- if( Platform.OSType.ANDROID == Platform.getOSType() && getGLRendererString(true).contains("powervr") ) {
- if(DEBUG) {
- System.err.println("Ignored: eglSwapInterval("+interval+") - cause: OS "+Platform.getOSType() + " / Renderer " + getGLRendererString(false));
- }
+ protected boolean setSwapIntervalImpl(final int interval) {
+ if( hasRendererQuirk(GLRendererQuirks.NoSetSwapInterval) ) {
return false;
}
return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval);
@@ -285,57 +298,59 @@ public abstract class EGLContext extends GLContextImpl {
//
// Accessible ..
//
-
- /**
- * If context is an ES profile, map it to the given device
- * via {@link GLContext#mapAvailableGLVersion(AbstractGraphicsDevice, int, int, int, int, int)}.
- * <p>
- * We intentionally override a non native EGL device ES profile mapping,
- * i.e. this will override/modify an already 'set' X11/WGL/.. mapping.
- * </p>
- *
- * @param device
- */
- protected void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) {
- mapCurrentAvailableGLVersionImpl(device, ctxMajorVersion, ctxMinorVersion, ctxOptions);
- }
- protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps) {
+
+ /* pp */ void mapCurrentAvailableGLVersion(final AbstractGraphicsDevice device) {
+ mapStaticGLVersion(device, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ }
+ /* pp */ int getContextOptions() { return ctxOptions; }
+ /* pp */ static void mapStaticGLESVersion(final AbstractGraphicsDevice device, final GLCapabilitiesImmutable caps) {
final GLProfile glp = caps.getGLProfile();
final int[] reqMajorCTP = new int[2];
GLContext.getRequestMajorAndCompat(glp, reqMajorCTP);
- if(glp.isGLES() && reqMajorCTP[0] >= 2) {
- reqMajorCTP[1] |= GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ;
+ if( glp.isGLES() ) {
+ if( reqMajorCTP[0] >= 3 ) {
+ reqMajorCTP[1] |= GLContext.CTX_IMPL_ES3_COMPAT | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ;
+ } else if( reqMajorCTP[0] >= 2 ) {
+ reqMajorCTP[1] |= GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ;
+ }
}
- if(!caps.getHardwareAccelerated()) {
+ if( !caps.getHardwareAccelerated() ) {
reqMajorCTP[1] |= GLContext.CTX_IMPL_ACCEL_SOFT;
}
- mapCurrentAvailableGLVersionImpl(device, reqMajorCTP[0], 0, reqMajorCTP[1]);
+ mapStaticGLVersion(device, reqMajorCTP[0], 0, reqMajorCTP[1]);
}
- protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) {
- int ctp = ( 2 == major ) ? ( GLContext.CTX_PROFILE_ES | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) : ( GLContext.CTX_PROFILE_ES );
- mapCurrentAvailableGLVersionImpl(device, major, 0, ctp);
- }
- private static void mapCurrentAvailableGLVersionImpl(AbstractGraphicsDevice device, int major, int minor, int ctp) {
+ /* pp */ static void mapStaticGLVersion(final AbstractGraphicsDevice device, final int major, final int minor, final int ctp) {
if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) {
- // ES1 or ES2
- final int reqMajor = major;
- final int reqProfile = GLContext.CTX_PROFILE_ES;
- GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
- major, minor, ctp);
+ // ES1, ES2, ES3, ..
+ mapStaticGLVersion(device, major /* reqMajor */, major, minor, ctp);
+ if( 3 == major ) {
+ // map ES2 -> ES3
+ mapStaticGLVersion(device, 2 /* reqMajor */, major, minor, ctp);
+ }
}
}
-
- protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+ private static void mapStaticGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int major, final int minor, final int ctp) {
+ GLContext.mapAvailableGLVersion(device, reqMajor, GLContext.CTX_PROFILE_ES, major, minor, ctp);
+ if(! ( device instanceof EGLGraphicsDevice ) ) {
+ final EGLGraphicsDevice eglDevice = new EGLGraphicsDevice(device.getHandle(), EGL.EGL_NO_DISPLAY, device.getConnection(), device.getUnitID(), null);
+ GLContext.mapAvailableGLVersion(eglDevice, reqMajor, GLContext.CTX_PROFILE_ES, major, minor, ctp);
+ }
+ }
+ protected static String getGLVersion(final int major, final int minor, final int ctp, final String gl_version) {
+ return GLContext.getGLVersion(major, minor, ctp, gl_version);
+ }
+
+ protected static boolean getAvailableGLVersionsSet(final AbstractGraphicsDevice device) {
return GLContext.getAvailableGLVersionsSet(device);
}
- protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+ protected static void setAvailableGLVersionsSet(final AbstractGraphicsDevice device) {
GLContext.setAvailableGLVersionsSet(device);
}
-
- protected static String toHexString(int hex) {
+
+ protected static String toHexString(final int hex) {
return GLContext.toHexString(hex);
}
- protected static String toHexString(long hex) {
+ protected static String toHexString(final long hex) {
return GLContext.toHexString(hex);
}
@@ -344,23 +359,17 @@ public abstract class EGLContext extends GLContextImpl {
//
@Override
- protected void copyImpl(GLContext source, int mask) throws GLException {
+ protected void copyImpl(final GLContext source, final int mask) throws GLException {
throw new GLException("Not yet implemented");
}
-
- @Override
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
- throw new GLException("Should not call this");
- }
-
@Override
- public boolean offscreenImageNeedsVerticalFlip() {
+ public final ByteBuffer glAllocateMemoryNV(final int size, final float readFrequency, final float writeFrequency, final float priority) {
throw new GLException("Should not call this");
}
@Override
- public int getOffscreenContextPixelDataType() {
+ public final void glFreeMemoryNV(final ByteBuffer pointer) {
throw new GLException("Should not call this");
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
index ce2e824f5..9499c70f4 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -34,155 +34,220 @@ import java.util.Iterator;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.ToolkitLock;
import javax.media.opengl.GLException;
import jogamp.opengl.Debug;
-import com.jogamp.common.util.LongIntHashMap;
+import com.jogamp.common.util.LongObjectHashMap;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
-/**
- * This implementation provides recursive calls to
+/**
+ * This implementation provides recursive calls to
* {@link EGL#eglInitialize(long, IntBuffer, IntBuffer)} and {@link EGL#eglTerminate(long)},
* where <code>eglInitialize(..)</code> is issued only for the 1st call per <code>eglDisplay</code>
* and <code>eglTerminate(..)</code> is issued only for the last call.
* <p>
* This class is required, due to implementation bugs within EGL where {@link EGL#eglTerminate(long)}
- * does not mark the resource for deletion when still in use, bug releases them immediatly.
+ * does not mark the resource for deletion when still in use, bug releases them immediately.
* </p>
*/
public class EGLDisplayUtil {
- protected static final boolean DEBUG = Debug.debug("EGLDisplayUtil");
-
- static LongIntHashMap eglDisplayCounter;
-
+ private static final boolean DEBUG = Debug.debug("EGLDisplayUtil");
+ private static boolean useSingletonEGLDisplay = false;
+ private static EGLDisplayRef singletonEGLDisplay = null;
+
+ private static class EGLDisplayRef {
+ final long eglDisplay;
+ final Throwable createdStack;
+ int initRefCount;
+
+ /**
+ * Returns an already opened {@link EGLDisplayRef} or opens a new {@link EGLDisplayRef}.
+ * <p>
+ * Opened {@link EGLDisplayRef}s are mapped against their <code>eglDisplay</code> handle.
+ * </p>
+ * <p>
+ * Method utilizes {@link EGLDisplayRef}'s reference counter, i.e. increases it.
+ * </p>
+ * <p>
+ * An {@link EGLDisplayRef} is <i>opened</i> via {@link EGL#eglInitialize(long, IntBuffer, IntBuffer)}.
+ * </p>
+ */
+ static EGLDisplayRef getOrCreateOpened(final long eglDisplay, final IntBuffer major, final IntBuffer minor) {
+ final EGLDisplayRef o = (EGLDisplayRef) openEGLDisplays.get(eglDisplay);
+ if( null == o ) {
+ if( EGL.eglInitialize(eglDisplay, major, minor) ) {
+ final EGLDisplayRef n = new EGLDisplayRef(eglDisplay);
+ openEGLDisplays.put(eglDisplay, n);
+ n.initRefCount++;
+ if( null == singletonEGLDisplay ) {
+ singletonEGLDisplay = n;
+ }
+ return n;
+ } else {
+ return null;
+ }
+ } else {
+ o.initRefCount++;
+ return o;
+ }
+ }
+
+ /**
+ * Closes an already opened {@link EGLDisplayRef}.
+ * <p>
+ * Method decreases a reference counter and closes the {@link EGLDisplayRef} if it reaches zero.
+ * </p>
+ * <p>
+ * An {@link EGLDisplayRef} is <i>closed</i> via {@link EGL#eglTerminate(long)}.
+ * </p>
+ */
+ static EGLDisplayRef closeOpened(final long eglDisplay, final boolean[] res) {
+ final EGLDisplayRef o = (EGLDisplayRef) openEGLDisplays.get(eglDisplay);
+ res[0] = true;
+ if( null != o ) {
+ if( 0 < o.initRefCount ) { // no negative refCount
+ o.initRefCount--;
+ if( 0 == o.initRefCount ) {
+ res[0] = EGL.eglTerminate(eglDisplay);
+ if( o == singletonEGLDisplay ) {
+ singletonEGLDisplay = null;
+ }
+ }
+ }
+ if( 0 >= o.initRefCount ) {
+ openEGLDisplays.remove(eglDisplay);
+ }
+ }
+ return o;
+ }
+
+ private EGLDisplayRef(final long eglDisplay) {
+ this.eglDisplay = eglDisplay;
+ this.initRefCount = 0;
+ this.createdStack = DEBUG ? new Throwable() : null;
+ }
+
+ @Override
+ public String toString() {
+ return "EGLDisplayRef[0x"+Long.toHexString(eglDisplay)+": refCnt "+initRefCount+"]";
+ }
+ }
+ private static final LongObjectHashMap openEGLDisplays;
+
static {
- eglDisplayCounter = new LongIntHashMap();
- eglDisplayCounter.setKeyNotFoundValue(0);
+ openEGLDisplays = new LongObjectHashMap();
+ openEGLDisplays.setKeyNotFoundValue(null);
}
- /**
+ /**
* @return number of unclosed EGL Displays.<br>
*/
- public static int shutdown(boolean verbose) {
- if(DEBUG || verbose || eglDisplayCounter.size() > 0 ) {
- System.err.println("EGLDisplayUtil.EGLDisplays: Shutdown (open: "+eglDisplayCounter.size()+")");
+ public static int shutdown(final boolean verbose) {
+ if(DEBUG || verbose || openEGLDisplays.size() > 0 ) {
+ System.err.println("EGLDisplayUtil.EGLDisplays: Shutdown (open: "+openEGLDisplays.size()+")");
if(DEBUG) {
Thread.dumpStack();
}
- if( eglDisplayCounter.size() > 0) {
- EGLDisplayUtil.dumpOpenDisplayConnections();
+ if( openEGLDisplays.size() > 0) {
+ dumpOpenDisplayConnections();
}
}
-
- return eglDisplayCounter.size();
+ return openEGLDisplays.size();
}
-
+
public static void dumpOpenDisplayConnections() {
- System.err.println("EGLDisplayUtil: Open EGL Display Connections: "+eglDisplayCounter.size());
+ System.err.println("EGLDisplayUtil: Open EGL Display Connections: "+openEGLDisplays.size());
int i=0;
- for(Iterator<LongIntHashMap.Entry> iter = eglDisplayCounter.iterator(); iter.hasNext(); i++) {
- final LongIntHashMap.Entry e = iter.next();
- System.err.println("EGLDisplayUtil: Open["+i+"]: 0x"+Long.toHexString(e.key)+": refCnt "+e.value);
+ for(final Iterator<LongObjectHashMap.Entry> iter = openEGLDisplays.iterator(); iter.hasNext(); i++) {
+ final LongObjectHashMap.Entry e = iter.next();
+ final EGLDisplayRef v = (EGLDisplayRef) e.value;
+ System.err.println("EGLDisplayUtil: Open["+i+"]: 0x"+Long.toHexString(e.key)+": "+v);
+ if(null != v.createdStack) {
+ v.createdStack.printStackTrace();
+ }
}
}
-
- public static long eglGetDisplay(long nativeDisplay_id) {
+
+ /* pp */ static synchronized void setSingletonEGLDisplayOnly(final boolean v) { useSingletonEGLDisplay = v; }
+
+ private static synchronized long eglGetDisplay(final long nativeDisplay_id) {
+ if( useSingletonEGLDisplay && null != singletonEGLDisplay ) {
+ if(DEBUG) {
+ System.err.println("EGLDisplayUtil.eglGetDisplay.s: eglDisplay("+EGLContext.toHexString(nativeDisplay_id)+"): "+
+ EGLContext.toHexString(singletonEGLDisplay.eglDisplay)+
+ ", "+((EGL.EGL_NO_DISPLAY != singletonEGLDisplay.eglDisplay)?"OK":"Failed")+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")");
+ }
+ return singletonEGLDisplay.eglDisplay;
+ }
final long eglDisplay = EGL.eglGetDisplay(nativeDisplay_id);
if(DEBUG) {
- System.err.println("EGLDisplayUtil.eglGetDisplay(): eglDisplay("+EGLContext.toHexString(nativeDisplay_id)+"): "+
+ System.err.println("EGLDisplayUtil.eglGetDisplay.X: eglDisplay("+EGLContext.toHexString(nativeDisplay_id)+"): "+
EGLContext.toHexString(eglDisplay)+
- ", "+((EGL.EGL_NO_DISPLAY != eglDisplay)?"OK":"Failed"));
+ ", "+((EGL.EGL_NO_DISPLAY != eglDisplay)?"OK":"Failed")+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")");
}
return eglDisplay;
}
-
- /**
- * @param eglDisplay
- * @param major
- * @param minor
- * @return true if the eglDisplay is valid and it's reference counter becomes one and {@link EGL#eglInitialize(long, int[], int, int[], int)} was successful, otherwise false
- *
- * @see EGL#eglInitialize(long, int[], int, int[], int)}
- */
- public static synchronized boolean eglInitialize(long eglDisplay, int[] major, int major_offset, int[] minor, int minor_offset) {
- final boolean res;
- final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init
- if(1==refCnt) {
- res = EGL.eglInitialize(eglDisplay, major, major_offset, minor, minor_offset);
- } else {
- res = true;
- }
- eglDisplayCounter.put(eglDisplay, refCnt);
- if(DEBUG) {
- System.err.println("EGLDisplayUtil.eglInitialize1("+EGLContext.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res);
- // Thread.dumpStack();
- }
- return res;
- }
-
+
/**
* @param eglDisplay
* @param major
* @param minor
* @return true if the eglDisplay is valid and it's reference counter becomes one and {@link EGL#eglInitialize(long, IntBuffer, IntBuffer)} was successful, otherwise false
- *
+ *
* @see EGL#eglInitialize(long, IntBuffer, IntBuffer)
*/
- public static synchronized boolean eglInitialize(long eglDisplay, IntBuffer major, IntBuffer minor) {
+ private static synchronized boolean eglInitialize(final long eglDisplay, final IntBuffer major, final IntBuffer minor) {
if( EGL.EGL_NO_DISPLAY == eglDisplay) {
return false;
}
- final boolean res;
- final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init
- if(1==refCnt) { // only initialize once
- res = EGL.eglInitialize(eglDisplay, major, minor);
- } else {
- res = true;
- }
- if(res) { // map if successfully initialized, only
- eglDisplayCounter.put(eglDisplay, refCnt);
- }
+ final EGLDisplayRef d = EGLDisplayRef.getOrCreateOpened(eglDisplay, major, minor);
if(DEBUG) {
- System.err.println("EGLDisplayUtil.eglInitialize2("+EGLContext.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res);
+ System.err.println("EGLDisplayUtil.eglInitialize("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+(null != d)+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")");
// Thread.dumpStack();
}
- return res;
+ return null != d;
}
-
+
/**
* @param nativeDisplayID
* @param eglDisplay array of size 1 holding return value if successful, otherwise {@link EGL#EGL_NO_DISPLAY}.
- * @param eglErr array of size 1 holding the EGL error value as retrieved by {@link EGL#eglGetError()} if not successful.
+ * @param eglErr array of size 1 holding the EGL error value as retrieved by {@link EGL#eglGetError()} if not successful.
* @param major
* @param minor
- * @return {@link EGL#EGL_SUCCESS} if successful, otherwise {@link EGL#EGL_BAD_DISPLAY} if {@link #eglGetDisplay(long)} failed
+ * @return {@link EGL#EGL_SUCCESS} if successful, otherwise {@link EGL#EGL_BAD_DISPLAY} if {@link #eglGetDisplay(long)} failed
* or {@link EGL#EGL_NOT_INITIALIZED} if {@link #eglInitialize(long, IntBuffer, IntBuffer)} failed.
- *
+ *
* @see #eglGetDisplay(long)
* @see #eglInitialize(long, IntBuffer, IntBuffer)
*/
- public static synchronized int eglGetDisplayAndInitialize(long nativeDisplayID, long[] eglDisplay, int[] eglErr, IntBuffer major, IntBuffer minor) {
+ private static synchronized int eglGetDisplayAndInitialize(final long nativeDisplayID, final long[] eglDisplay, final int[] eglErr, final IntBuffer major, final IntBuffer minor) {
eglDisplay[0] = EGL.EGL_NO_DISPLAY;
- final long _eglDisplay = EGLDisplayUtil.eglGetDisplay( nativeDisplayID );
+ final long _eglDisplay = eglGetDisplay( nativeDisplayID );
if ( EGL.EGL_NO_DISPLAY == _eglDisplay ) {
eglErr[0] = EGL.eglGetError();
return EGL.EGL_BAD_DISPLAY;
}
- if ( !EGLDisplayUtil.eglInitialize( _eglDisplay, major, minor) ) {
+ if ( !eglInitialize( _eglDisplay, major, minor) ) {
eglErr[0] = EGL.eglGetError();
return EGL.EGL_NOT_INITIALIZED;
}
eglDisplay[0] = _eglDisplay;
return EGL.EGL_SUCCESS;
}
-
+
/**
+ * Attempts to {@link #eglGetDisplayAndInitialize(long, long[], int[], IntBuffer, IntBuffer)} with given <code>nativeDisplayID</code>.
+ * If this fails, method retries with <code>nativeDisplayID</code> {@link EGL#EGL_DEFAULT_DISPLAY} - the fallback mechanism.
+ * The actual used <code>nativeDisplayID</code> is returned in it's in/out array.
+ *
+ * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails incl fallback
* @param nativeDisplayID in/out array of size 1, passing the requested nativeVisualID, may return a different revised nativeVisualID handle
* @return the initialized EGL display ID
* @throws GLException if not successful
*/
- public static synchronized long eglGetDisplayAndInitialize(long[] nativeDisplayID) {
+ private static synchronized long eglGetDisplayAndInitialize(final long[] nativeDisplayID) {
final long[] eglDisplay = new long[1];
final int[] eglError = new int[1];
int eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(nativeDisplayID[0], eglDisplay, eglError, null, null);
@@ -201,62 +266,66 @@ public class EGLDisplayUtil {
}
throw new GLException("Failed to created/initialize EGL display incl. fallback default: native "+EGLContext.toHexString(nativeDisplayID[0])+", error "+EGLContext.toHexString(eglRes)+"/"+EGLContext.toHexString(eglError[0]));
}
-
+
/**
* @param eglDisplay the EGL display handle
* @return true if the eglDisplay is valid and it's reference counter becomes zero and {@link EGL#eglTerminate(long)} was successful, otherwise false
*/
- public static synchronized boolean eglTerminate(long eglDisplay) {
+ private static synchronized boolean eglTerminate(final long eglDisplay) {
if( EGL.EGL_NO_DISPLAY == eglDisplay) {
return false;
}
- final boolean res;
- final int refCnt = eglDisplayCounter.get(eglDisplay) - 1; // 1 - 1 = 0 -> final terminate
- if(0==refCnt) { // no terminate if still in use or already terminated
- res = EGL.eglTerminate(eglDisplay);
- eglDisplayCounter.remove(eglDisplay);
- } else {
- if(0 < refCnt) { // no negative refCount
- eglDisplayCounter.put(eglDisplay, refCnt);
- }
- res = true;
- }
+ final boolean[] res = new boolean[1];
+ final EGLDisplayRef d = EGLDisplayRef.closeOpened(eglDisplay, res);
if(DEBUG) {
- System.err.println("EGLDisplayUtil.eglTerminate("+EGLContext.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res);
+ System.err.println("EGLDisplayUtil.eglTerminate.X("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+res[0]+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")");
// Thread.dumpStack();
}
- return res;
+ return res[0];
}
-
- public static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() {
- public long eglGetAndInitDisplay(long[] nativeDisplayID) {
+
+ private static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() {
+ @Override
+ public long eglGetAndInitDisplay(final long[] nativeDisplayID) {
return eglGetDisplayAndInitialize(nativeDisplayID);
}
- public void eglTerminate(long eglDisplayHandle) {
+ @Override
+ public void eglTerminate(final long eglDisplayHandle) {
EGLDisplayUtil.eglTerminate(eglDisplayHandle);
}
};
-
+
/**
+ * Returns an uninitialized {@link EGLGraphicsDevice}. User needs to issue {@link EGLGraphicsDevice#open()} before usage.
+ * <p>
+ * Using {@link #eglGetDisplayAndInitialize(long[])} for the {@link EGLGraphicsDevice#open()} implementation
+ * and {@link #eglTerminate(long)} for {@link EGLGraphicsDevice#close()}.
+ * </p>
+ * <p>
+ * Using the default {@link ToolkitLock}, via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}.
+ * </p>
* @param nativeDisplayID
* @param connection
* @param unitID
- * @return an initialized EGLGraphicsDevice
- * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails
- * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLDisplayLifecycleCallback)
+ * @return an uninitialized {@link EGLGraphicsDevice}
*/
- public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID) {
- final EGLGraphicsDevice eglDisplay = new EGLGraphicsDevice(nativeDisplayID, EGL.EGL_NO_DISPLAY, connection, unitID, eglLifecycleCallback);
- eglDisplay.open();
- return eglDisplay;
+ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(final long nativeDisplayID, final String connection, final int unitID) {
+ return new EGLGraphicsDevice(nativeDisplayID, EGL.EGL_NO_DISPLAY, connection, unitID, eglLifecycleCallback);
}
-
+
/**
+ * Returns an uninitialized {@link EGLGraphicsDevice}. User needs to issue {@link EGLGraphicsDevice#open()} before usage.
+ * <p>
+ * Using {@link #eglGetDisplayAndInitialize(long[])} for the {@link EGLGraphicsDevice#open()} implementation
+ * and {@link #eglTerminate(long)} for {@link EGLGraphicsDevice#close()}.
+ * </p>
+ * <p>
+ * Using the default {@link ToolkitLock}, via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}.
+ * </p>
* @param surface
- * @return an initialized EGLGraphicsDevice
- * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails incl fallback
+ * @return an uninitialized EGLGraphicsDevice
*/
- public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(NativeSurface surface) {
+ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(final NativeSurface surface) {
final long nativeDisplayID;
if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ) {
nativeDisplayID = surface.getSurfaceHandle(); // don't even ask ..
@@ -264,8 +333,6 @@ public class EGLDisplayUtil {
nativeDisplayID = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY
}
final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice();
- final EGLGraphicsDevice eglDevice = new EGLGraphicsDevice(nativeDisplayID, EGL.EGL_NO_DISPLAY, adevice.getConnection(), adevice.getUnitID(), eglLifecycleCallback);
- eglDevice.open();
- return eglDevice;
+ return new EGLGraphicsDevice(nativeDisplayID, EGL.EGL_NO_DISPLAY, adevice.getConnection(), adevice.getUnitID(), eglLifecycleCallback);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
index 167eebf3a..bacf9f18e 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
@@ -52,22 +52,22 @@ import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
public abstract class EGLDrawable extends GLDrawableImpl {
- protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException {
+ protected EGLDrawable(final EGLDrawableFactory factory, final NativeSurface component) throws GLException {
super(factory, component, false);
}
@Override
public abstract GLContext createContext(GLContext shareWith);
- protected abstract long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle);
+ protected abstract long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle);
private final long createEGLSurface() {
final EGLWrappedSurface eglws = (EGLWrappedSurface) surface;
- final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) eglws.getGraphicsConfiguration();
+ final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) eglws.getGraphicsConfiguration();
final NativeSurface upstreamSurface = eglws.getUpstreamSurface();
-
- long eglSurface = createSurface(eglConfig, eglws.getWidth(), eglws.getHeight(), upstreamSurface.getSurfaceHandle());
-
+
+ long eglSurface = createSurface(eglConfig, eglws.getSurfaceWidth(), eglws.getSurfaceHeight(), upstreamSurface.getSurfaceHandle());
+
int eglError0;
if (EGL.EGL_NO_SURFACE == eglSurface) {
eglError0 = EGL.eglGetError();
@@ -80,7 +80,7 @@ public abstract class EGLDrawable extends GLDrawableImpl {
if(DEBUG) {
System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle");
}
- eglSurface = createSurface(eglConfig, eglws.getWidth(), eglws.getHeight(), nw.getWindowHandle());
+ eglSurface = createSurface(eglConfig, eglws.getSurfaceWidth(), eglws.getSurfaceHeight(), nw.getWindowHandle());
if (EGL.EGL_NO_SURFACE == eglSurface) {
eglError0 = EGL.eglGetError();
}
@@ -100,11 +100,11 @@ public abstract class EGLDrawable extends GLDrawableImpl {
}
@Override
- protected final void updateHandle() {
+ protected final void createHandle() {
final EGLWrappedSurface eglws = (EGLWrappedSurface) surface;
if(DEBUG) {
- System.err.println(getThreadName() + ": updateHandle of "+eglws);
- }
+ System.err.println(getThreadName() + ": createHandle of "+eglws);
+ }
if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
if( EGL.EGL_NO_SURFACE != eglws.getSurfaceHandle() ) {
throw new InternalError("Set surface but claimed to be invalid: "+eglws);
@@ -114,12 +114,13 @@ public abstract class EGLDrawable extends GLDrawableImpl {
throw new InternalError("Nil surface but claimed to be valid: "+eglws);
}
}
-
- protected void destroyHandle() {
+
+ @Override
+ protected void destroyHandle() {
final EGLWrappedSurface eglws = (EGLWrappedSurface) surface;
if(DEBUG) {
System.err.println(getThreadName() + ": destroyHandle of "+eglws);
- }
+ }
if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) {
throw new InternalError("Nil surface but claimed to be valid: "+eglws);
}
@@ -130,11 +131,11 @@ public abstract class EGLDrawable extends GLDrawableImpl {
}
}
- protected static boolean isValidEGLSurface(long eglDisplayHandle, long surfaceHandle) {
+ protected static boolean isValidEGLSurface(final long eglDisplayHandle, final long surfaceHandle) {
if( 0 == surfaceHandle ) {
return false;
}
- final IntBuffer val = Buffers.newDirectIntBuffer(1);
+ final IntBuffer val = Buffers.newDirectIntBuffer(1);
final boolean eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surfaceHandle, EGL.EGL_CONFIG_ID, val);
if( !eglSurfaceValid ) {
final int eglErr = EGL.eglGetError();
@@ -144,7 +145,7 @@ public abstract class EGLDrawable extends GLDrawableImpl {
}
return eglSurfaceValid;
}
-
+
@Override
protected final void setRealizedImpl() {
if(DEBUG) {
@@ -153,7 +154,7 @@ public abstract class EGLDrawable extends GLDrawableImpl {
}
@Override
- protected final void swapBuffersImpl(boolean doubleBuffered) {
+ protected final void swapBuffersImpl(final boolean doubleBuffered) {
if(doubleBuffered) {
final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
// single-buffer is already filtered out @ GLDrawableImpl#swapBuffers()
@@ -165,7 +166,9 @@ public abstract class EGLDrawable extends GLDrawableImpl {
@Override
public GLDynamicLookupHelper getGLDynamicLookupHelper() {
- if (getGLProfile().usesNativeGLES2()) {
+ if (getGLProfile().usesNativeGLES3()) {
+ return getFactoryImpl().getGLDynamicLookupHelper(3);
+ } else if (getGLProfile().usesNativeGLES2()) {
return getFactoryImpl().getGLDynamicLookupHelper(2);
} else if (getGLProfile().usesNativeGLES1()) {
return getFactoryImpl().getGLDynamicLookupHelper(1);
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index e98d69140..2edb22314 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -43,6 +43,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -64,41 +65,53 @@ import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import jogamp.common.os.PlatformPropsImpl;
import jogamp.nativewindow.WrappedSurface;
import jogamp.opengl.Debug;
+import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
import jogamp.opengl.GLGraphicsConfigurationUtil;
+import jogamp.opengl.SharedResourceRunner;
-import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+import com.jogamp.opengl.GLRendererQuirks;
public class EGLDrawableFactory extends GLDrawableFactoryImpl {
- protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG;
-
- /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true);
- /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true);
-
+ protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG; // allow package access
+
+ /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK;
+
+ static {
+ Debug.initSingleton();
+ QUERY_EGL_ES_NATIVE_TK = PropertyAccess.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true);
+ }
+
private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null;
private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null;
- private static boolean isANGLE = false;
-
- private static final boolean isANGLE(GLDynamicLookupHelper dl) {
- if(Platform.OSType.WINDOWS == Platform.OS_TYPE) {
- final boolean r = 0 != dl.dynamicLookupFunction("eglQuerySurfacePointerANGLE") ||
- 0 != dl.dynamicLookupFunction("glBlitFramebufferANGLE") ||
- 0 != dl.dynamicLookupFunction("glRenderbufferStorageMultisampleANGLE");
- return r;
+
+ private static final boolean isANGLE(final GLDynamicLookupHelper dl) {
+ if(Platform.OSType.WINDOWS == PlatformPropsImpl.OS_TYPE) {
+ return dl.isFunctionAvailable("eglQuerySurfacePointerANGLE") ||
+ dl.isFunctionAvailable("glBlitFramebufferANGLE") ||
+ dl.isFunctionAvailable("glRenderbufferStorageMultisampleANGLE");
} else {
return false;
}
}
+ private static final boolean includesES1(final GLDynamicLookupHelper dl) {
+ return dl.isFunctionAvailable("glLoadIdentity") &&
+ dl.isFunctionAvailable("glEnableClientState") &&
+ dl.isFunctionAvailable("glColorPointer");
+ }
+
public EGLDrawableFactory() {
super();
@@ -108,48 +121,24 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
// Check for other underlying stuff ..
if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true)) {
+ hasX11 = true;
try {
ReflectionUtil.createInstance("jogamp.opengl.x11.glx.X11GLXGraphicsConfigurationFactory", EGLDrawableFactory.class.getClassLoader());
- } catch (JogampRuntimeException jre) { /* n/a .. */ }
+ } catch (final Exception jre) { /* n/a .. */ }
}
- defaultDevice = new EGLGraphicsDevice();
-
// FIXME: Probably need to move EGL from a static model
// to a dynamic one, where there can be 2 instances
// for each ES profile with their own ProcAddressTable.
synchronized(EGLDrawableFactory.class) {
- /**
- * Currently AMD's EGL impl. crashes at eglGetDisplay(EGL_DEFAULT_DISPLAY)
- *
- // Check Desktop ES2 Availability first (AMD, ..)
- if(null==eglES2DynamicLookupHelper) {
- GLDynamicLookupHelper tmp=null;
- try {
- tmp = new GLDynamicLookupHelper(new DesktopES2DynamicLibraryBundleInfo());
- } catch (GLException gle) {
- if(DEBUG) {
- gle.printStackTrace();
- }
- }
- if(null!=tmp && tmp.isLibComplete()) {
- eglES2DynamicLookupHelper = tmp;
- EGL.resetProcAddressTable(eglES2DynamicLookupHelper);
- if (GLProfile.DEBUG) {
- System.err.println("Info: EGLDrawableFactory: Desktop ES2 - OK");
- }
- } else if (GLProfile.DEBUG) {
- System.err.println("Info: EGLDrawableFactory: Desktop ES2 - NOPE");
- }
- } */
final boolean hasDesktopES2 = null != eglES2DynamicLookupHelper;
if(!hasDesktopES2 && null==eglES1DynamicLookupHelper) {
GLDynamicLookupHelper tmp=null;
try {
tmp = new GLDynamicLookupHelper(new EGLES1DynamicLibraryBundleInfo());
- } catch (GLException gle) {
+ } catch (final GLException gle) {
if(DEBUG) {
gle.printStackTrace();
}
@@ -159,18 +148,18 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
EGL.resetProcAddressTable(eglES1DynamicLookupHelper);
final boolean isANGLEES1 = isANGLE(eglES1DynamicLookupHelper);
isANGLE |= isANGLEES1;
- if (GLProfile.DEBUG) {
+ if (DEBUG || GLProfile.DEBUG) {
System.err.println("Info: EGLDrawableFactory: EGL ES1 - OK, isANGLE: "+isANGLEES1);
}
- } else if (GLProfile.DEBUG) {
- System.err.println("Info: EGLDrawableFactory: EGL ES1 - NOPE");
+ } else if (DEBUG || GLProfile.DEBUG) {
+ System.err.println("Info: EGLDrawableFactory: EGL ES1 - NOPE (ES1 lib)");
}
}
if(!hasDesktopES2 && null==eglES2DynamicLookupHelper) {
GLDynamicLookupHelper tmp=null;
try {
tmp = new GLDynamicLookupHelper(new EGLES2DynamicLibraryBundleInfo());
- } catch (GLException gle) {
+ } catch (final GLException gle) {
if(DEBUG) {
gle.printStackTrace();
}
@@ -178,18 +167,36 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
if(null!=tmp && tmp.isLibComplete()) {
eglES2DynamicLookupHelper = tmp;
EGL.resetProcAddressTable(eglES2DynamicLookupHelper);
+ final boolean includesES1 = null == eglES1DynamicLookupHelper && includesES1(eglES2DynamicLookupHelper);
+ if(includesES1) {
+ eglES1DynamicLookupHelper = tmp;
+ }
final boolean isANGLEES2 = isANGLE(eglES2DynamicLookupHelper);
isANGLE |= isANGLEES2;
- if (GLProfile.DEBUG) {
- System.err.println("Info: EGLDrawableFactory: EGL ES2 - OK, isANGLE: "+isANGLEES2);
+ if (DEBUG || GLProfile.DEBUG) {
+ System.err.println("Info: EGLDrawableFactory: EGL ES2 - OK (includesES1 "+includesES1+", isANGLE: "+isANGLEES2+")");
+ if(includesES1) {
+ System.err.println("Info: EGLDrawableFactory: EGL ES1 - OK (ES2 lib)");
+ }
}
- } else if (GLProfile.DEBUG) {
+ } else if (DEBUG || GLProfile.DEBUG) {
System.err.println("Info: EGLDrawableFactory: EGL ES2 - NOPE");
}
}
- if(null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper) {
- sharedMap = new HashMap<String /*connection*/, SharedResource>();
- sharedMapCreateAttempt = new HashSet<String>();
+ if( null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper ) {
+ if(isANGLE && !GLProfile.enableANGLE) {
+ if(DEBUG || GLProfile.DEBUG) {
+ System.err.println("Info: EGLDrawableFactory.init - EGL/ES2 ANGLE disabled");
+ }
+ } else {
+ if( isANGLE && ( DEBUG || GLProfile.DEBUG ) ) {
+ System.err.println("Info: EGLDrawableFactory.init - EGL/ES2 ANGLE enabled");
+ }
+ sharedMap = new HashMap<String /*uniqueKey*/, SharedResource>();
+ sharedMapCreateAttempt = new HashSet<String>();
+ // FIXME: defaultDevice.open() triggers eglInitialize(..) which crashed on Windows w/ Chrome/ANGLE, FF/ANGLE!
+ defaultDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ }
}
}
}
@@ -198,16 +205,22 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
protected final boolean isComplete() {
return null != sharedMap; // null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper;
}
-
-
+
+
@Override
- protected final void destroy() {
+ protected final void shutdownImpl() {
+ if( DEBUG ) {
+ System.err.println("EGLDrawableFactory.shutdown");
+ }
if(null != sharedMap) {
- Collection<SharedResource> srl = sharedMap.values();
- for(Iterator<SharedResource> sri = srl.iterator(); sri.hasNext(); ) {
- SharedResource sr = sri.next();
+ if(DEBUG) {
+ dumpMap();
+ }
+ final Collection<SharedResource> srl = sharedMap.values();
+ for(final Iterator<SharedResource> sri = srl.iterator(); sri.hasNext(); ) {
+ final SharedResource sr = sri.next();
if(DEBUG) {
- System.err.println("EGLDrawableFactory.destroy(): "+sr.device.toString());
+ System.err.println("EGLDrawableFactory.shutdown: "+sr.device.toString());
}
sr.device.close();
}
@@ -216,7 +229,13 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
sharedMap = null;
sharedMapCreateAttempt = null;
}
- defaultDevice = null;
+ if(null != defaultSharedResource) {
+ defaultSharedResource = null;
+ }
+ if(null != defaultDevice) {
+ defaultDevice.close();
+ defaultDevice = null;
+ }
/**
* Pulling away the native library may cause havoc ..
*/
@@ -232,42 +251,89 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
EGLDisplayUtil.shutdown(DEBUG);
}
- private HashMap<String /*connection*/, SharedResource> sharedMap = null;
- private HashSet<String> sharedMapCreateAttempt = null;
+ private void dumpMap() {
+ synchronized(sharedMap) {
+ System.err.println("EGLDrawableFactory.map "+sharedMap.size());
+ int i=0;
+ final Set<String> keys = sharedMap.keySet();
+ for(final Iterator<String> keyI = keys.iterator(); keyI.hasNext(); i++) {
+ final String key = keyI.next();
+ final SharedResource sr = sharedMap.get(key);
+ System.err.println("EGLDrawableFactory.map["+i+"] "+key+" -> "+sr.getDevice()+", "+
+ "es1 [avail "+sr.wasES1ContextCreated+", pbuffer "+sr.hasPBufferES1+", quirks "+sr.rendererQuirksES1+", ctp "+EGLContext.getGLVersion(1, 0, sr.ctpES1, null)+"], "+
+ "es2/3 [es2 "+sr.wasES2ContextCreated+", es3 "+sr.wasES3ContextCreated+", [pbuffer "+sr.hasPBufferES3ES2+", quirks "+sr.rendererQuirksES3ES2+", ctp "+EGLContext.getGLVersion(2, 0, sr.ctpES3ES2, null)+"]]");
+ }
+ ;
+ }
+ }
- private EGLGraphicsDevice defaultDevice;
+ private HashMap<String /*uniqueKey*/, SharedResource> sharedMap = null;
+ private HashSet<String> sharedMapCreateAttempt = null;
+ private EGLGraphicsDevice defaultDevice = null;
+ private SharedResource defaultSharedResource = null;
+ private boolean isANGLE = false;
+ private boolean hasX11 = false;
- static class SharedResource {
+ static class SharedResource implements SharedResourceRunner.Resource {
private final EGLGraphicsDevice device;
- // private final EGLDrawable drawable;
// private final EGLContext contextES1;
// private final EGLContext contextES2;
+ // private final EGLContext contextES3;
private final boolean wasES1ContextCreated;
private final boolean wasES2ContextCreated;
+ private final boolean wasES3ContextCreated;
+ private final GLRendererQuirks rendererQuirksES1;
+ private final GLRendererQuirks rendererQuirksES3ES2;
+ private final int ctpES1;
+ private final int ctpES3ES2;
private final boolean hasPBufferES1;
- private final boolean hasPBufferES2;
+ private final boolean hasPBufferES3ES2;
- SharedResource(EGLGraphicsDevice dev,
- boolean wasContextES1Created, boolean hasPBufferES1,
- boolean wasContextES2Created, boolean hasPBufferES2
- /*EGLDrawable draw, EGLContext ctxES1, EGLContext ctxES2 */) {
+ SharedResource(final EGLGraphicsDevice dev,
+ final boolean wasContextES1Created, final boolean hasPBufferES1, final GLRendererQuirks rendererQuirksES1, final int ctpES1,
+ final boolean wasContextES2Created, final boolean wasContextES3Created,
+ final boolean hasPBufferES3ES2, final GLRendererQuirks rendererQuirksES3ES2, final int ctpES3ES2) {
this.device = dev;
- // this.drawable = draw;
// this.contextES1 = ctxES1;
- // this.contextES2 = ctxES2;
this.wasES1ContextCreated = wasContextES1Created;
- this.wasES2ContextCreated = wasContextES2Created;
this.hasPBufferES1= hasPBufferES1;
- this.hasPBufferES2= hasPBufferES2;
+ this.rendererQuirksES1 = rendererQuirksES1;
+ this.ctpES1 = ctpES1;
+
+ // this.contextES2 = ctxES2;
+ // this.contextES3 = ctxES3;
+ this.wasES2ContextCreated = wasContextES2Created;
+ this.wasES3ContextCreated = wasContextES3Created;
+ this.hasPBufferES3ES2= hasPBufferES3ES2;
+ this.rendererQuirksES3ES2 = rendererQuirksES3ES2;
+ this.ctpES3ES2 = ctpES3ES2;
+ }
+ @Override
+ public final boolean isValid() {
+ return wasES1ContextCreated || wasES2ContextCreated || wasES3ContextCreated;
}
- final EGLGraphicsDevice getDevice() { return device; }
- // final EGLDrawable getDrawable() { return drawable; }
+ @Override
+ public final EGLGraphicsDevice getDevice() { return device; }
// final EGLContext getContextES1() { return contextES1; }
// final EGLContext getContextES2() { return contextES2; }
- final boolean wasES1ContextAvailable() { return wasES1ContextCreated; }
- final boolean wasES2ContextAvailable() { return wasES2ContextCreated; }
- final boolean hasES1PBuffer() { return hasPBufferES1; }
- final boolean hasES2PBuffer() { return hasPBufferES2; }
+ // final EGLContext getContextES3() { return contextES3; }
+
+ @Override
+ public AbstractGraphicsScreen getScreen() {
+ return null;
+ }
+ @Override
+ public GLDrawableImpl getDrawable() {
+ return null;
+ }
+ @Override
+ public GLContextImpl getContext() {
+ return null;
+ }
+ @Override
+ public GLRendererQuirks getRendererQuirks() {
+ return null != rendererQuirksES3ES2 ? rendererQuirksES3ES2 : rendererQuirksES1 ;
+ }
}
@Override
@@ -276,79 +342,171 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) {
+ public final boolean getIsDeviceCompatible(final AbstractGraphicsDevice device) {
// via mappings (X11/WGL/.. -> EGL) we shall be able to handle all types.
return null != sharedMap ; // null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper;
}
- private static List<GLCapabilitiesImmutable> getAvailableEGLConfigs(EGLGraphicsDevice eglDisplay, GLCapabilitiesImmutable caps) {
+ private static List<GLCapabilitiesImmutable> getAvailableEGLConfigs(final EGLGraphicsDevice eglDisplay, final GLCapabilitiesImmutable caps) {
final IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
if(!EGL.eglGetConfigs(eglDisplay.getHandle(), null, 0, numConfigs)) {
throw new GLException("EGLDrawableFactory.getAvailableEGLConfigs: Get maxConfigs (eglGetConfigs) call failed, error "+EGLContext.toHexString(EGL.eglGetError()));
}
if(0 < numConfigs.get(0)) {
final PointerBuffer configs = PointerBuffer.allocateDirect(numConfigs.get(0));
- final IntBuffer attrs = Buffers.newDirectIntBuffer(EGLGraphicsConfiguration.GLCapabilities2AttribList(caps));
+ final IntBuffer attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(caps);
final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(caps);
if( EGL.eglChooseConfig(eglDisplay.getHandle(), attrs, configs, configs.capacity(), numConfigs) && numConfigs.get(0) > 0) {
- return EGLGraphicsConfigurationFactory.eglConfigs2GLCaps(eglDisplay, caps.getGLProfile(), configs, numConfigs.get(0), winattrmask, false /* forceTransparentFlag */);
+ return EGLGraphicsConfigurationFactory.eglConfigs2GLCaps(eglDisplay, caps.getGLProfile(), configs, numConfigs.get(0), winattrmask, false /* forceTransparentFlag */, false /* onlyFirstValid */);
}
}
return new ArrayList<GLCapabilitiesImmutable>(0);
}
-
- private boolean mapAvailableEGLESConfig(AbstractGraphicsDevice adevice, EGLGraphicsDevice sharedEGLDevice, String profileString, boolean[] hasPBuffer) {
- if( !GLProfile.isAvailable(adevice, profileString) ) {
+
+ private static void dumpEGLInfo(final String prefix, final long eglDisplay) {
+ final String eglVendor = EGL.eglQueryString(eglDisplay, EGL.EGL_VENDOR);
+ final String eglClientAPIs = EGL.eglQueryString(eglDisplay, EGL.EGL_CLIENT_APIS);
+ final String eglVersion = EGL.eglQueryString(eglDisplay, EGL.EGL_VERSION);
+ System.err.println(prefix+"EGL vendor "+eglVendor+", version "+eglVersion+", clientAPIs "+eglClientAPIs);
+ }
+
+ private boolean mapAvailableEGLESConfig(final AbstractGraphicsDevice adevice, final int[] esProfile,
+ final boolean[] hasPBuffer, final GLRendererQuirks[] rendererQuirks, final int[] ctp) {
+ final String profileString;
+ switch( esProfile[0] ) {
+ case 3:
+ profileString = GLProfile.GLES3; break;
+ case 2:
+ profileString = GLProfile.GLES2; break;
+ case 1:
+ profileString = GLProfile.GLES1; break;
+ default:
+ throw new GLException("Invalid ES profile number "+esProfile[0]);
+ }
+ if ( !GLProfile.isAvailable(adevice, profileString) ) {
+ if( DEBUG ) {
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" n/a on "+adevice);
+ }
return false;
}
final GLProfile glp = GLProfile.get(adevice, profileString) ;
final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory();
+ final boolean initDefaultDevice = 0 == defaultDevice.getHandle(); // Note: GLProfile always triggers EGL device initialization first!
+ final boolean mapsADeviceToDefaultDevice = !QUERY_EGL_ES_NATIVE_TK || initDefaultDevice ||
+ null == desktopFactory || adevice instanceof EGLGraphicsDevice ;
+ if( DEBUG ) {
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" ( "+esProfile[0]+" ), "+
+ "defaultSharedResourceSet "+(null!=defaultSharedResource)+", mapsADeviceToDefaultDevice "+mapsADeviceToDefaultDevice+
+ " (QUERY_EGL_ES_NATIVE_TK "+QUERY_EGL_ES_NATIVE_TK+", hasDesktopFactory "+(null != desktopFactory)+
+ ", isEGLGraphicsDevice "+(adevice instanceof EGLGraphicsDevice)+")");
+ }
+
EGLGraphicsDevice eglDevice = null;
NativeSurface surface = null;
ProxySurface upstreamSurface = null; // X11, GLX, ..
+ ProxySurface downstreamSurface = null; // EGL
boolean success = false;
- boolean deviceFromUpstreamSurface = false;
- try {
+ try {
final GLCapabilities reqCapsAny = new GLCapabilities(glp);
reqCapsAny.setRedBits(5); reqCapsAny.setGreenBits(5); reqCapsAny.setBlueBits(5); reqCapsAny.setAlphaBits(0);
reqCapsAny.setDoubleBuffered(false);
- final GLCapabilitiesImmutable reqCapsPBuffer = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(reqCapsAny);
- final List<GLCapabilitiesImmutable> availablePBufferCapsL = getAvailableEGLConfigs(sharedEGLDevice, reqCapsPBuffer);
- hasPBuffer[0] = availablePBufferCapsL.size() > 0;
-
- if(adevice instanceof EGLGraphicsDevice || null == desktopFactory || !QUERY_EGL_ES_NATIVE_TK) {
- eglDevice = sharedEGLDevice; // reuse
+
+ if( mapsADeviceToDefaultDevice ) {
+ // In this branch, any non EGL device is mapped to EGL default shared resources (default behavior).
+ // Only one default shared resource instance is ever be created.
+ if( initDefaultDevice ) {
+ defaultDevice.open();
+
+ // Probe for GLRendererQuirks.SingletonEGLDisplayOnly
+ final long secondEGLDisplay = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
+ if ( EGL.EGL_NO_DISPLAY == secondEGLDisplay ) {
+ final int[] quirks = { GLRendererQuirks.SingletonEGLDisplayOnly };
+ GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, 0, 1);
+ EGLDisplayUtil.setSingletonEGLDisplayOnly(true);
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirks[0])+": cause: Second eglGetDisplay(EGL_DEFAULT_DISPLAY) failed");
+ }
+ }
+ }
+ if( DEBUG ) {
+ dumpEGLInfo("EGLDrawableFactory.mapAvailableEGLESConfig: ", defaultDevice.getHandle());
+ }
+
+ final GLCapabilitiesImmutable reqCapsPBuffer = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(reqCapsAny);
+ final List<GLCapabilitiesImmutable> availablePBufferCapsL = getAvailableEGLConfigs(defaultDevice, reqCapsPBuffer);
+ hasPBuffer[0] = availablePBufferCapsL.size() > 0;
+
+ // 1st case: adevice is not the EGL default device, map default shared resources
+ if( adevice != defaultDevice ) {
+ if(null == defaultSharedResource) {
+ return false;
+ }
+ switch(esProfile[0]) {
+ case 3:
+ if( !defaultSharedResource.wasES3ContextCreated ) {
+ return false;
+ }
+ rendererQuirks[0] = defaultSharedResource.rendererQuirksES3ES2;
+ ctp[0] = defaultSharedResource.ctpES3ES2;
+ break;
+ case 2:
+ if( !defaultSharedResource.wasES2ContextCreated ) {
+ return false;
+ }
+ rendererQuirks[0] = defaultSharedResource.rendererQuirksES3ES2;
+ ctp[0] = defaultSharedResource.ctpES3ES2;
+ break;
+ case 1:
+ if( !defaultSharedResource.wasES1ContextCreated ) {
+ return false;
+ }
+ rendererQuirks[0] = defaultSharedResource.rendererQuirksES1;
+ ctp[0] = defaultSharedResource.ctpES1;
+ break;
+ }
+ if( null != rendererQuirks[0] ) {
+ GLRendererQuirks.addStickyDeviceQuirks(adevice, rendererQuirks[0]);
+ }
+ EGLContext.mapStaticGLVersion(adevice, esProfile[0], 0, ctp[0]);
+ return true;
+ }
+
+ // attempt to created the default shared resources ..
+
if( hasPBuffer[0] ) {
- surface = createDummySurfaceImpl(eglDevice, false, reqCapsPBuffer, null, 64, 64); // egl pbuffer offscreen
- upstreamSurface = (ProxySurface)surface;
- upstreamSurface.createNotify();
- deviceFromUpstreamSurface = false;
+ // 2nd case create defaultDevice shared resource using pbuffer surface
+ downstreamSurface = createDummySurfaceImpl(defaultDevice, false, reqCapsPBuffer, reqCapsPBuffer, null, 64, 64); // egl pbuffer offscreen
+ if( null != downstreamSurface ) {
+ downstreamSurface.createNotify();
+ surface = downstreamSurface;
+ }
} else {
- final List<GLCapabilitiesImmutable> capsAnyL = getAvailableEGLConfigs(eglDevice, reqCapsAny);
+ // 3rd case fake creation of defaultDevice shared resource, no pbuffer available
+ final List<GLCapabilitiesImmutable> capsAnyL = getAvailableEGLConfigs(defaultDevice, reqCapsAny);
if(capsAnyL.size() > 0) {
final GLCapabilitiesImmutable chosenCaps = capsAnyL.get(0);
- EGLContext.mapStaticGLESVersion(eglDevice, chosenCaps);
- if(eglDevice != adevice) {
- EGLContext.mapStaticGLESVersion(adevice, chosenCaps);
- }
- final EGLGraphicsDevice adeviceEGLDevice = new EGLGraphicsDevice(adevice.getHandle(), EGL.EGL_NO_DISPLAY, adevice.getConnection(), adevice.getUnitID(), null);
- EGLContext.mapStaticGLESVersion(adeviceEGLDevice, chosenCaps);
+ EGLContext.mapStaticGLESVersion(defaultDevice, chosenCaps);
success = true;
}
if(DEBUG) {
- System.err.println("EGLDrawableFactory.isEGLContextAvailable() no pbuffer config available, detected !pbuffer config: "+success);
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig() no pbuffer config available, detected !pbuffer config: "+success);
EGLGraphicsConfigurationFactory.printCaps("!PBufferCaps", capsAnyL, System.err);
- }
- }
+ }
+ }
+ eglDevice = defaultDevice; // reuse
} else {
- surface = desktopFactory.createDummySurface(adevice, reqCapsAny, null, 64, 64); // X11, WGL, .. dummy window
- upstreamSurface = ( surface instanceof ProxySurface ) ? (ProxySurface)surface : null ;
+ // 4th case always creates a true mapping of given device to EGL
+ upstreamSurface = desktopFactory.createDummySurface(adevice, reqCapsAny, null, 64, 64); // X11, WGL, .. dummy window
if(null != upstreamSurface) {
upstreamSurface.createNotify();
- }
- eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface);
- deviceFromUpstreamSurface = true;
- hasPBuffer[0] = true;
+ eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface);
+ eglDevice.open();
+ if( DEBUG ) {
+ dumpEGLInfo("EGLDrawableFactory.mapAvailableEGLESConfig: ", eglDevice.getHandle());
+ }
+ hasPBuffer[0] = true;
+ surface = upstreamSurface;
+ }
}
if(null != surface) {
@@ -360,25 +518,26 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
context.makeCurrent(); // could cause exception
if(context.isCurrent()) {
final String glVersion = context.getGL().glGetString(GL.GL_VERSION);
- if(null != glVersion) {
+ if(null != glVersion) {
context.mapCurrentAvailableGLVersion(eglDevice);
if(eglDevice != adevice) {
context.mapCurrentAvailableGLVersion(adevice);
}
- final EGLGraphicsDevice adeviceEGLDevice = new EGLGraphicsDevice(adevice.getHandle(), EGL.EGL_NO_DISPLAY, adevice.getConnection(), adevice.getUnitID(), null);
- context.mapCurrentAvailableGLVersion(adeviceEGLDevice);
+ rendererQuirks[0] = context.getRendererQuirks();
+ ctp[0] = context.getContextOptions();
+ esProfile[0] = context.getGLVersionNumber().getMajor();
success = true;
} else {
// Oops .. something is wrong
if(DEBUG) {
- System.err.println("EGLDrawableFactory.isEGLContextAvailable: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!");
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!");
}
}
}
- } catch (GLException gle) {
+ } catch (final Throwable t) {
if (DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: INFO: context create/makeCurrent failed");
- gle.printStackTrace();
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: INFO: context create/makeCurrent failed");
+ t.printStackTrace();
}
} finally {
context.destroy();
@@ -386,143 +545,163 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
drawable.setRealized(false);
}
- } catch (Throwable t) {
+ } catch (final Throwable t) {
if(DEBUG) {
- System.err.println("Catched Exception:");
+ System.err.println("Caught exception on thread "+getThreadName());
t.printStackTrace();
}
success = false;
} finally {
- if(eglDevice == sharedEGLDevice) {
- if(null != upstreamSurface) {
- upstreamSurface.destroyNotify();
- }
- } else if( deviceFromUpstreamSurface ) {
+ if(null != downstreamSurface) {
+ downstreamSurface.destroyNotify();
+ }
+ if( defaultDevice != eglDevice ) { // don't close default device
if(null != eglDevice) {
eglDevice.close();
}
if(null != upstreamSurface) {
upstreamSurface.destroyNotify();
}
- } else {
- if(null != upstreamSurface) {
- upstreamSurface.destroyNotify();
- }
- if(null != eglDevice) {
- eglDevice.close();
- }
}
}
return success;
}
- /* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) {
- if(null == sharedMap) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper
- return null;
- }
- final String connection = adevice.getConnection();
- SharedResource sr;
- boolean createAttempted;
+ private final boolean needsToCreateSharedResource(final String key, final SharedResource[] existing) {
synchronized(sharedMap) {
- sr = sharedMap.get(connection);
+ final SharedResource sr = sharedMap.get(key);
if( null == sr ) {
- createAttempted = sharedMapCreateAttempt.contains(connection);
+ final boolean createAttempted = sharedMapCreateAttempt.contains(key);
if(!createAttempted) {
- sharedMapCreateAttempt.add(connection);
+ sharedMapCreateAttempt.add(key);
}
+ return !createAttempted;
} else {
- createAttempted = true;
+ if(null != existing) {
+ existing[0] = sr;
+ }
+ return false;
}
}
- if(null==sr && !createAttempted) {
- final boolean madeCurrentES1;
- final boolean madeCurrentES2;
- final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
- boolean[] hasPBufferES1 = new boolean[1];
- boolean[] hasPBufferES2 = new boolean[1];
-
- if(QUERY_EGL_ES) {
- madeCurrentES1 = mapAvailableEGLESConfig(adevice, sharedDevice, GLProfile.GLES1, hasPBufferES1);
- madeCurrentES2 = mapAvailableEGLESConfig(adevice, sharedDevice, GLProfile.GLES2, hasPBufferES2);
- } else {
- madeCurrentES1 = true;
- madeCurrentES2 = true;
- hasPBufferES1[0] = true;
- hasPBufferES2[0] = true;
- EGLContext.mapStaticGLESVersion(sharedDevice, 1);
- if(sharedDevice != adevice) {
- EGLContext.mapStaticGLESVersion(adevice, 1);
- }
- EGLContext.mapStaticGLESVersion(sharedDevice, 2);
- if(sharedDevice != adevice) {
- EGLContext.mapStaticGLESVersion(adevice, 2);
- }
+ }
+
+ @Override
+ protected final SharedResource getOrCreateSharedResourceImpl(final AbstractGraphicsDevice adevice) {
+ if(null == sharedMap) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper
+ return null;
+ }
+
+ if( needsToCreateSharedResource(defaultDevice.getUniqueID(), null) ) {
+ if (DEBUG) {
+ System.err.println("EGLDrawableFactory.createShared: (defaultDevice): req. device: "+adevice+", defaultDevice "+defaultDevice);
+ Thread.dumpStack();
}
-
- if( !EGLContext.getAvailableGLVersionsSet(adevice) ) {
- // Even though we override the non EGL native mapping intentionally,
- // avoid exception due to double 'set' - carefull exception of the rule.
- EGLContext.setAvailableGLVersionsSet(adevice);
+ if(null != defaultSharedResource) {
+ dumpMap();
+ throw new InternalError("defaultSharedResource already exist: "+defaultSharedResource);
}
- sr = new SharedResource(sharedDevice, madeCurrentES1, hasPBufferES1[0], madeCurrentES2, hasPBufferES2[0]);
-
- synchronized(sharedMap) {
- sharedMap.put(connection, sr);
- if(adevice != sharedDevice) {
- sharedMap.put(sharedDevice.getConnection(), sr);
- }
+ defaultSharedResource = createEGLSharedResourceImpl(defaultDevice);
+ }
+
+ final String key = adevice.getUniqueID();
+ if( defaultDevice.getUniqueID().equals(key) ) {
+ return defaultSharedResource;
+ } else {
+ if( null == defaultSharedResource) { // defaultDevice must be initialized before host-device
+ dumpMap();
+ throw new InternalError("defaultSharedResource does not exist");
}
- if (DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: devices: queried " + QUERY_EGL_ES + "[nativeTK "+QUERY_EGL_ES_NATIVE_TK+"], " + adevice + ", " + sharedDevice);
- System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1 + ", hasPBuffer "+hasPBufferES1[0]);
- System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2 + ", hasPBuffer "+hasPBufferES2[0]);
+ final SharedResource[] existing = new SharedResource[] { null };
+ if ( !needsToCreateSharedResource(key, existing) ) {
+ return existing[0];
}
+ return createEGLSharedResourceImpl(adevice);
}
- return sr;
}
- @Override
- protected final Thread getSharedResourceThread() {
- return null;
- }
+ private SharedResource createEGLSharedResourceImpl(final AbstractGraphicsDevice adevice) {
+ final boolean madeCurrentES1;
+ final boolean[] hasPBufferES1 = new boolean[] { false };
+ final boolean[] hasPBufferES3ES2 = new boolean[] { false };
+ // EGLContext[] eglCtxES1 = new EGLContext[] { null };
+ // EGLContext[] eglCtxES2 = new EGLContext[] { null };
+ final GLRendererQuirks[] rendererQuirksES1 = new GLRendererQuirks[] { null };
+ final GLRendererQuirks[] rendererQuirksES3ES2 = new GLRendererQuirks[] { null };
+ final int[] ctpES1 = new int[] { -1 };
+ final int[] ctpES3ES2 = new int[] { -1 };
- @Override
- protected final boolean createSharedResource(AbstractGraphicsDevice device) {
- try {
- SharedResource sr = getOrCreateEGLSharedResource(device);
- if(null!=sr) {
- return sr.wasES1ContextAvailable() || sr.wasES2ContextAvailable();
- }
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("Catched Exception while EGL Shared Resource initialization");
- gle.printStackTrace();
+
+ if (DEBUG) {
+ System.err.println("EGLDrawableFactory.createShared(): device "+adevice);
+ }
+
+ if( null != eglES1DynamicLookupHelper ) {
+ final int[] esProfile = { 1 };
+ madeCurrentES1 = mapAvailableEGLESConfig(adevice, esProfile, hasPBufferES1, rendererQuirksES1, ctpES1) && 1 == esProfile[0];
+ } else {
+ madeCurrentES1 = false;
+ }
+ boolean madeCurrentES2 = false;
+ boolean madeCurrentES3 = false;
+ if( null != eglES2DynamicLookupHelper ) {
+ // ES3 Query
+ final int[] esProfile = { 3 };
+ madeCurrentES3 = mapAvailableEGLESConfig(adevice, esProfile, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2) && 3 == esProfile[0];
+ if( !madeCurrentES3 ) {
+ // ES2 Query, may result in ES3
+ esProfile[0] = 2;
+ if( mapAvailableEGLESConfig(adevice, esProfile, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2) ) {
+ switch( esProfile[0] ) {
+ case 2: madeCurrentES2 = true; break;
+ case 3: madeCurrentES3 = true; break;
+ default: throw new InternalError("XXXX Got "+esProfile[0]);
+ }
+ }
}
}
- return false;
+ if( !EGLContext.getAvailableGLVersionsSet(adevice) ) {
+ // Even though we override the non EGL native mapping intentionally,
+ // avoid exception due to double 'set' - carefull exception of the rule.
+ EGLContext.setAvailableGLVersionsSet(adevice);
+ }
+ if( hasX11 ) {
+ handleDontCloseX11DisplayQuirk(rendererQuirksES1[0]);
+ handleDontCloseX11DisplayQuirk(rendererQuirksES3ES2[0]);
+ }
+ final SharedResource sr = new SharedResource(defaultDevice, madeCurrentES1, hasPBufferES1[0], rendererQuirksES1[0], ctpES1[0],
+ madeCurrentES2, madeCurrentES3, hasPBufferES3ES2[0], rendererQuirksES3ES2[0], ctpES3ES2[0]);
+
+ synchronized(sharedMap) {
+ sharedMap.put(adevice.getUniqueID(), sr);
+ }
+ if (DEBUG) {
+ System.err.println("EGLDrawableFactory.createShared: devices: queried nativeTK "+QUERY_EGL_ES_NATIVE_TK+", adevice " + adevice + ", defaultDevice " + defaultDevice);
+ System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1 + ", hasPBuffer "+hasPBufferES1[0]+", quirks "+rendererQuirksES1[0]);
+ System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2 + ", hasPBuffer "+hasPBufferES3ES2[0]+", quirks "+rendererQuirksES3ES2[0]);
+ System.err.println("EGLDrawableFactory.createShared: context ES3: " + madeCurrentES3 + ", hasPBuffer "+hasPBufferES3ES2[0]+", quirks "+rendererQuirksES3ES2[0]);
+ dumpMap();
+ }
+ return sr;
}
- @Override
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- return null; // n/a for EGL .. since we don't keep the resources
+ private void handleDontCloseX11DisplayQuirk(final GLRendererQuirks quirks) {
+ if( null != quirks && quirks.exist( GLRendererQuirks.DontCloseX11Display ) ) {
+ jogamp.nativewindow.x11.X11Util.markAllDisplaysUnclosable();
+ }
}
@Override
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResource sr = getOrCreateEGLSharedResource(device);
- if(null!=sr) {
- return sr.getDevice();
- }
+ protected final Thread getSharedResourceThread() {
return null;
}
- public boolean isANGLE() {
+ public final boolean isANGLE() {
return isANGLE;
}
@Override
- public GLDynamicLookupHelper getGLDynamicLookupHelper(int esProfile) {
- if (2==esProfile) {
+ public GLDynamicLookupHelper getGLDynamicLookupHelper(final int esProfile) {
+ if ( 2==esProfile || 3==esProfile ) {
return eglES2DynamicLookupHelper;
} else if (1==esProfile) {
return eglES1DynamicLookupHelper;
@@ -532,7 +711,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
+ protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(final AbstractGraphicsDevice device) {
if(null == sharedMap) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper
return new ArrayList<GLCapabilitiesImmutable>(); // null
}
@@ -540,22 +719,20 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) {
+ protected GLDrawableImpl createOnscreenDrawableImpl(final NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
return new EGLOnscreenDrawable(this, EGLWrappedSurface.get(target));
}
-
- static String getThreadName() { return Thread.currentThread().getName(); }
@Override
- protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) {
+ protected GLDrawableImpl createOffscreenDrawableImpl(final NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
- AbstractGraphicsConfiguration config = target.getGraphicsConfiguration();
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final AbstractGraphicsConfiguration config = target.getGraphicsConfiguration();
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
if(!caps.isPBuffer()) {
throw new GLException("Non pbuffer not yet implemented");
}
@@ -564,22 +741,23 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
+ public boolean canCreateGLPbuffer(final AbstractGraphicsDevice device, final GLProfile glp) {
// SharedResource sr = getOrCreateEGLSharedResource(device);
// return sr.hasES1PBuffer() || sr.hasES2PBuffer();
return true;
}
@Override
- protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
- GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) {
+ protected ProxySurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstreamHook) {
final boolean ownDevice;
final EGLGraphicsDevice device;
- if(createNewDevice || ! ( deviceReq instanceof EGLGraphicsDevice ) ) {
+ if( createNewDevice || ! (deviceReq instanceof EGLGraphicsDevice) ) {
final long nativeDisplayID = ( deviceReq instanceof EGLGraphicsDevice) ?
( (EGLGraphicsDevice) deviceReq ).getNativeDisplayID() : deviceReq.getHandle() ;
device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(nativeDisplayID, deviceReq.getConnection(), deviceReq.getUnitID());
+ device.open();
ownDevice = true;
} else {
device = (EGLGraphicsDevice) deviceReq;
@@ -588,30 +766,28 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
if(null == config) {
- throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
- }
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ }
return new WrappedSurface(config, 0, upstreamHook, ownDevice);
}
-
+
@Override
- public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
- GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
- final GLCapabilitiesImmutable chosenCaps =
- GLGraphicsConfigurationUtil.fixDoubleBufferedGLCapabilities(
- GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq)), false);
+ public final ProxySurface createDummySurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) {
+ chosenCaps = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(chosenCaps); // complete validation in EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(..) above
return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new EGLDummyUpstreamSurfaceHook(width, height));
}
-
+
/**
- * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface.
- * It will also hold the resulting pbuffer surface handle.
+ * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface.
+ * It will also hold the resulting pbuffer surface handle.
* @param useTexture
* @return the passed {@link MutableSurface} which now has the EGL pbuffer surface set as it's handle
*/
- protected static MutableSurface createPBufferSurfaceImpl(MutableSurface ms, boolean useTexture) {
+ protected static MutableSurface createPBufferSurfaceImpl(final MutableSurface ms, final boolean useTexture) {
return null;
}
- protected static long createPBufferSurfaceImpl(EGLGraphicsConfiguration config, int width, int height, boolean useTexture) {
+ protected static long createPBufferSurfaceImpl(final EGLGraphicsConfiguration config, final int width, final int height, final boolean useTexture) {
final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice();
final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
final int texFormat;
@@ -626,8 +802,8 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
System.out.println("Pbuffer config: " + config);
}
- final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(width, height, texFormat);
- final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs, 0);
+ final IntBuffer attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(width, height, texFormat);
+ final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs);
if (EGL.EGL_NO_SURFACE==surf) {
throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+width+"x"+height+", "+eglDevice+", "+config+", error 0x"+Integer.toHexString(EGL.eglGetError()));
} else if(DEBUG) {
@@ -637,9 +813,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ protected ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) {
final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq;
final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID());
+ device.open();
final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
return new WrappedSurface(cfg, windowHandle, upstream, true);
@@ -647,12 +824,12 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
@Override
protected GLContext createExternalGLContextImpl() {
- AbstractGraphicsScreen absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_EGL);
+ final AbstractGraphicsScreen absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_EGL);
return new EGLExternalContext(absScreen);
}
@Override
- public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) {
+ public boolean canCreateExternalGLDrawable(final AbstractGraphicsDevice device) {
return false;
}
@@ -660,15 +837,4 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
protected GLDrawable createExternalGLDrawableImpl() {
throw new GLException("Not yet implemented");
}
-
- @Override
- public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- @Override
- public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("Unimplemented on this platform");
- }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java
index b172d4f35..f00d7059d 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java
@@ -7,43 +7,54 @@ import javax.media.nativewindow.UpstreamSurfaceHook;
import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+/** Uses a PBuffer offscreen surface */
public class EGLDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
/**
- * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
- * not the actual dummy surface width.
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)},
+ * not the actual dummy surface width.
* The latter is platform specific and small
- * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)},
* not the actual dummy surface height,
* The latter is platform specific and small
*/
- public EGLDummyUpstreamSurfaceHook(int width, int height) {
+ public EGLDummyUpstreamSurfaceHook(final int width, final int height) {
super(width, height);
}
-
+
@Override
- public final void create(ProxySurface s) {
+ public final void create(final ProxySurface s) {
final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice();
- if(0 == eglDevice.getHandle()) {
- eglDevice.open();
- s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
- }
- if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) {
- s.setSurfaceHandle( EGLDrawableFactory.createPBufferSurfaceImpl((EGLGraphicsConfiguration)s.getGraphicsConfiguration(), 64, 64, false) );
- s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ eglDevice.lock();
+ try {
+ if(0 == eglDevice.getHandle()) {
+ eglDevice.open();
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) {
+ s.setSurfaceHandle( EGLDrawableFactory.createPBufferSurfaceImpl((EGLGraphicsConfiguration)s.getGraphicsConfiguration(), 64, 64, false) );
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ } finally {
+ eglDevice.unlock();
}
- s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
}
-
+
@Override
- public final void destroy(ProxySurface s) {
+ public final void destroy(final ProxySurface s) {
if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice();
if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) {
throw new InternalError("Owns upstream surface, but no EGL surface: "+s);
}
- EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle());
- s.setSurfaceHandle(EGL.EGL_NO_SURFACE);
- s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ eglDevice.lock();
+ try {
+ EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle());
+ s.setSurfaceHandle(EGL.EGL_NO_SURFACE);
+ s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ } finally {
+ eglDevice.unlock();
+ }
}
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java
index fe9d7573d..05dae0b9d 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,28 +20,30 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl.egl;
import com.jogamp.common.os.AndroidVersion;
+import com.jogamp.common.os.Platform;
import java.util.*;
+import jogamp.common.os.PlatformPropsImpl;
import jogamp.opengl.*;
/**
* Abstract implementation of the DynamicLookupHelper for EGL,
* which decouples it's dependencies to EGLDrawable.
*
- * Currently two implementations exist, one for ES1 and one for ES2.
+ * Currently two implementations exist, one for ES1 and one for ES3 and ES2.
*/
public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
- static List<String> glueLibNames;
+ static final List<String> glueLibNames;
static {
glueLibNames = new ArrayList<String>();
glueLibNames.add("jogl_mobile");
@@ -51,41 +53,37 @@ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundle
super();
}
- /**
- * Might be a desktop GL library, and might need to allow symbol access to subsequent libs.
- *
- * This respects old DRI requirements:<br>
- * <pre>
- * http://dri.sourceforge.net/doc/DRIuserguide.html
- * </pre>
+ /**
+ * Returns <code>true</code> on <code>Android</code>,
+ * and <code>false</code> otherwise.
+ * <p>
+ * {@inheritDoc}
+ * </p>
*/
@Override
- public boolean shallLinkGlobal() { return true; }
-
- @Override
- public boolean shallLookupGlobal() {
- if ( AndroidVersion.isAvailable ) {
+ public final boolean shallLookupGlobal() {
+ if ( Platform.OSType.ANDROID == PlatformPropsImpl.OS_TYPE ) {
// Android requires global symbol lookup
return true;
}
// default behavior for other platforms
return false;
}
-
+
@Override
public final List<String> getToolGetProcAddressFuncNameList() {
- List<String> res = new ArrayList<String>();
+ final List<String> res = new ArrayList<String>();
res.add("eglGetProcAddress");
return res;
}
@Override
- public final long toolGetProcAddress(long toolGetProcAddressHandle, String funcName) {
+ public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) {
return EGL.eglGetProcAddress(toolGetProcAddressHandle, funcName);
}
@Override
- public final boolean useToolGetProcAdressFirst(String funcName) {
+ public final boolean useToolGetProcAdressFirst(final String funcName) {
if ( AndroidVersion.isAvailable ) {
// Android requires global dlsym lookup
return false;
@@ -93,26 +91,26 @@ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundle
return true;
}
}
-
- protected List<String> getEGLLibNamesList() {
- List<String> eglLibNames = new ArrayList<String>();
-
- // this is the default EGL lib name, according to the spec
+
+ protected final List<String> getEGLLibNamesList() {
+ final List<String> eglLibNames = new ArrayList<String>();
+
+ // this is the default EGL lib name, according to the spec
eglLibNames.add("libEGL.so.1");
-
+
// try these as well, if spec fails
eglLibNames.add("libEGL.so");
eglLibNames.add("EGL");
-
- // for windows distributions using the 'unlike' lib prefix,
+
+ // for windows distributions using the 'unlike' lib prefix,
// where our tool does not add it.
eglLibNames.add("libEGL");
-
+
return eglLibNames;
}
@Override
public final List<String> getGlueLibNames() {
return glueLibNames;
- }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java
index 0a373eb7f..361ec26ff 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,48 +20,49 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl.egl;
import java.util.*;
-public class EGLES1DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
+public final class EGLES1DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
protected EGLES1DynamicLibraryBundleInfo() {
super();
}
- public List<List<String>> getToolLibNames() {
+ @Override
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
{
final List<String> libsGL = new ArrayList<String>();
-
- // this is the default lib name, according to the spec
+
+ // this is the default lib name, according to the spec
libsGL.add("libGLESv1_CM.so.2");
-
+
// try these as well, if spec fails
libsGL.add("libGLESv1_CM.so");
- libsGL.add("GLESv1_CM");
+ libsGL.add("GLESv1_CM");
// alternative names
libsGL.add("GLES_CM");
libsGL.add("GLES_CL");
-
- // for windows distributions using the 'unlike' lib prefix,
+
+ // for windows distributions using the 'unlike' lib prefix,
// where our tool does not add it.
libsGL.add("libGLESv1_CM");
libsGL.add("libGLES_CM");
libsGL.add("libGLES_CL");
-
+
libsList.add(libsGL);
}
libsList.add(getEGLLibNamesList());
-
+
return libsList;
- }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java
index d4ee852b1..74738463f 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,49 +20,70 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl.egl;
import java.util.*;
-public class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
+/**
+ * <p>
+ * Covering ES3 and ES2.
+ * </p>
+ */
+public final class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
protected EGLES2DynamicLibraryBundleInfo() {
super();
}
- public List<List<String>> getToolLibNames() {
+ @Override
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
{
final List<String> libsGL = new ArrayList<String>();
-
- // this is the default lib name, according to the spec
+
+ // ES3: This is the default lib name, according to the spec
+ libsGL.add("libGLESv3.so.3");
+
+ // ES3: Try these as well, if spec fails
+ libsGL.add("libGLESv3.so");
+ libsGL.add("GLESv3");
+
+ // ES3: Alternative names
+ libsGL.add("GLES30");
+
+ // ES3: For windows distributions using the 'unlike' lib prefix
+ // where our tool does not add it.
+ libsGL.add("libGLESv3");
+ libsGL.add("libGLES30");
+
+ // ES2: This is the default lib name, according to the spec
libsGL.add("libGLESv2.so.2");
-
- // try these as well, if spec fails
- libsGL.add("libGLESv2.so");
+
+ // ES2: Try these as well, if spec fails
+ libsGL.add("libGLESv2.so");
libsGL.add("GLESv2");
- // alternative names
+ // ES2: Alternative names
libsGL.add("GLES20");
libsGL.add("GLESv2_CM");
- // for windows distributions using the 'unlike' lib prefix
+ // ES2: For windows distributions using the 'unlike' lib prefix
// where our tool does not add it.
libsGL.add("libGLESv2");
libsGL.add("libGLESv2_CM");
- libsGL.add("libGLES20");
-
+ libsGL.add("libGLES20");
+
libsList.add(libsGL);
}
libsList.add(getEGLLibNamesList());
-
+
return libsList;
- }
-
+ }
+
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java
index 84bd705db..babea4240 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java
@@ -36,40 +36,20 @@
package jogamp.opengl.egl;
import javax.media.opengl.*;
+
import jogamp.opengl.*;
+
import javax.media.nativewindow.*;
public class EGLExternalContext extends EGLContext {
- private GLContext lastContext;
- public EGLExternalContext(AbstractGraphicsScreen screen) {
+ public EGLExternalContext(final AbstractGraphicsScreen screen) {
super(null, null);
GLContextShareSet.contextCreated(this);
- setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES);
- getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
- }
-
- @Override
- public int makeCurrent() throws GLException {
- // Save last context if necessary to allow external GLContexts to
- // talk to other GLContexts created by this library
- GLContext cur = getCurrent();
- if (cur != null && cur != this) {
- lastContext = cur;
- setCurrent(null);
+ if( !setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION
+ throw new InternalError("setGLFunctionAvailability !strictMatch failed");
}
- return super.makeCurrent();
- }
-
- @Override
- public void release() throws GLException {
- super.release();
- setCurrent(lastContext);
- lastContext = null;
- }
-
- @Override
- protected void makeCurrentImpl() throws GLException {
+ getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
index f857c6b5c..a8dd7d5c8 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
@@ -52,7 +52,7 @@ public class EGLGLCapabilities extends GLCapabilities {
*
* May throw GLException if given GLProfile is not compatible w/ renderableType
*/
- public EGLGLCapabilities(long eglcfg, int eglcfgid, int visualID, GLProfile glp, int renderableType) {
+ public EGLGLCapabilities(final long eglcfg, final int eglcfgid, final int visualID, final GLProfile glp, final int renderableType) {
super( glp );
this.eglcfg = eglcfg;
this.eglcfgid = eglcfgid;
@@ -73,19 +73,19 @@ public class EGLGLCapabilities extends GLCapabilities {
public Object clone() {
try {
return super.clone();
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
throw new GLException(e);
}
}
- final protected void setEGLConfig(long v) { eglcfg=v; }
+ final protected void setEGLConfig(final long v) { eglcfg=v; }
final public long getEGLConfig() { return eglcfg; }
final public int getEGLConfigID() { return eglcfgid; }
final public int getRenderableType() { return renderableType; }
final public int getNativeVisualID() { return nativeVisualID; }
@Override
- final public int getVisualID(VIDType type) throws NativeWindowException {
+ final public int getVisualID(final VIDType type) throws NativeWindowException {
switch(type) {
case INTRINSIC:
case EGL_CONFIG:
@@ -97,23 +97,29 @@ public class EGLGLCapabilities extends GLCapabilities {
}
}
- public static boolean isCompatible(GLProfile glp, int renderableType) {
+ public static boolean isCompatible(final GLProfile glp, final int renderableType) {
if(null == glp) {
return true;
}
- if(0 != (renderableType & EGL.EGL_OPENGL_ES_BIT) && glp.usesNativeGLES1()) {
+ if(0 != (renderableType & EGLExt.EGL_OPENGL_ES3_BIT_KHR) && glp.usesNativeGLES3()) {
return true;
}
if(0 != (renderableType & EGL.EGL_OPENGL_ES2_BIT) && glp.usesNativeGLES2()) {
return true;
}
+ if(0 != (renderableType & EGL.EGL_OPENGL_ES_BIT) && glp.usesNativeGLES1()) {
+ return true;
+ }
if(0 != (renderableType & EGL.EGL_OPENGL_BIT) && !glp.usesNativeGLES()) {
return true;
}
return false;
}
- public static GLProfile getCompatible(EGLGraphicsDevice device, int renderableType) {
+ public static GLProfile getCompatible(final EGLGraphicsDevice device, final int renderableType) {
+ if(0 != (renderableType & EGLExt.EGL_OPENGL_ES3_BIT_KHR) && GLProfile.isAvailable(device, GLProfile.GLES3)) {
+ return GLProfile.get(device, GLProfile.GLES3);
+ }
if(0 != (renderableType & EGL.EGL_OPENGL_ES2_BIT) && GLProfile.isAvailable(device, GLProfile.GLES2)) {
return GLProfile.get(device, GLProfile.GLES2);
}
@@ -126,7 +132,7 @@ public class EGLGLCapabilities extends GLCapabilities {
return null;
}
- public static StringBuilder renderableTypeToString(StringBuilder sink, int renderableType) {
+ public static StringBuilder renderableTypeToString(StringBuilder sink, final int renderableType) {
if(null == sink) {
sink = new StringBuilder();
}
@@ -141,6 +147,9 @@ public class EGLGLCapabilities extends GLCapabilities {
if(0 != (renderableType & EGL.EGL_OPENGL_ES2_BIT)) {
if(!first) sink.append(", "); sink.append("GLES2"); first=false;
}
+ if(0 != (renderableType & EGLExt.EGL_OPENGL_ES3_BIT_KHR)) {
+ if(!first) sink.append(", "); sink.append("GLES3"); first=false;
+ }
if(0 != (renderableType & EGL.EGL_OPENVG_API)) {
if(!first) sink.append(", "); sink.append("VG"); first=false;
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
index 7bf201238..1d90e63af 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -46,6 +46,7 @@ import javax.media.nativewindow.VisualIDHolder;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
@@ -55,9 +56,14 @@ import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+import com.jogamp.opengl.GLRendererQuirks;
public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {
-
+
+ private static final String dbgCfgFailIntro = "Info: EGLConfig could not retrieve ";
+ private static final String dbgCfgFailForConfig = " for config ";
+ private static final String dbgCfgFailError = ", error ";
+
public final long getNativeConfig() {
return ((EGLGLCapabilities)capabilitiesChosen).getEGLConfig();
}
@@ -66,13 +72,20 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
return ((EGLGLCapabilities)capabilitiesChosen).getEGLConfigID();
}
- EGLGraphicsConfiguration(AbstractGraphicsScreen absScreen,
- EGLGLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
+ EGLGraphicsConfiguration(final AbstractGraphicsScreen absScreen,
+ final EGLGLCapabilities capsChosen, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser) {
super(absScreen, capsChosen, capsRequested);
this.chooser = chooser;
}
- public static EGLGraphicsConfiguration create(GLCapabilitiesImmutable capsRequested, AbstractGraphicsScreen absScreen, int cfgID) {
+ /**
+ * @param capsRequested
+ * @param absScreen
+ * @param eglConfigID {@link EGL#EGL_CONFIG_ID} for which the config is being created for.
+ * @return
+ * @throws GLException if invalid EGL display.
+ */
+ public static EGLGraphicsConfiguration create(final GLCapabilitiesImmutable capsRequested, final AbstractGraphicsScreen absScreen, final int eglConfigID) {
final AbstractGraphicsDevice absDevice = absScreen.getDevice();
if(null==absDevice || !(absDevice instanceof EGLGraphicsDevice)) {
throw new GLException("GraphicsDevice must be a valid EGLGraphicsDevice");
@@ -81,10 +94,11 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
if (dpy == EGL.EGL_NO_DISPLAY) {
throw new GLException("Invalid EGL display: "+absDevice);
}
- final long cfg = EGLConfigId2EGLConfig(dpy, cfgID);
+ final long cfg = EGLConfigId2EGLConfig(dpy, eglConfigID);
if(0 < cfg) {
+ final GLRendererQuirks defaultQuirks = GLRendererQuirks.getStickyDeviceQuirks( GLDrawableFactory.getEGLFactory().getDefaultDevice() );
final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsRequested);
- final EGLGLCapabilities caps = EGLConfig2Capabilities((EGLGraphicsDevice)absDevice, capsRequested.getGLProfile(), cfg, winattrmask, false);
+ final EGLGLCapabilities caps = EGLConfig2Capabilities(defaultQuirks, (EGLGraphicsDevice)absDevice, capsRequested.getGLProfile(), cfg, winattrmask, false);
return new EGLGraphicsConfiguration(absScreen, caps, capsRequested, new DefaultGLCapabilitiesChooser());
}
return null;
@@ -94,10 +108,10 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
public Object clone() {
return super.clone();
}
-
+
void updateGraphicsConfiguration() {
- CapabilitiesImmutable capsChosen = getChosenCapabilities();
- EGLGraphicsConfiguration newConfig = (EGLGraphicsConfiguration)
+ final CapabilitiesImmutable capsChosen = getChosenCapabilities();
+ final EGLGraphicsConfiguration newConfig = (EGLGraphicsConfiguration)
GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), capsChosen).chooseGraphicsConfiguration(
capsChosen, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED);
if(null!=newConfig) {
@@ -109,36 +123,36 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
}
}
- public static long EGLConfigId2EGLConfig(long display, int configID) {
- int[] attrs = new int[] {
+ public static long EGLConfigId2EGLConfig(final long display, final int configID) {
+ final IntBuffer attrs = Buffers.newDirectIntBuffer(new int[] {
EGL.EGL_CONFIG_ID, configID,
EGL.EGL_NONE
- };
- PointerBuffer configs = PointerBuffer.allocateDirect(1);
- int[] numConfigs = new int[1];
+ });
+ final PointerBuffer configs = PointerBuffer.allocateDirect(1);
+ final IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
if (!EGL.eglChooseConfig(display,
- attrs, 0,
+ attrs,
configs, 1,
- numConfigs, 0)) {
+ numConfigs)) {
return 0;
}
- if (numConfigs[0] == 0) {
+ if (numConfigs.get(0) == 0) {
return 0;
}
return configs.get(0);
}
- public static boolean isEGLConfigValid(long display, long config) {
+ public static boolean isEGLConfigValid(final long display, final long config) {
if(0 == config) {
return false;
}
final IntBuffer val = Buffers.newDirectIntBuffer(1);
-
+
// get the configID
if(!EGL.eglGetConfigAttrib(display, config, EGL.EGL_CONFIG_ID, val)) {
final int eglErr = EGL.eglGetError();
if(DEBUG) {
- System.err.println("Info: Couldn't retrieve EGL ConfigID for config "+toHexString(config)+", error "+toHexString(eglErr));
+ System.err.println(dbgCfgFailIntro+"EGL_CONFIG_ID"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(eglErr));
}
return false;
}
@@ -148,25 +162,27 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
static int EGLConfigDrawableTypeBits(final EGLGraphicsDevice device, final long config) {
int val = 0;
- int[] stype = new int[1];
- if(! EGL.eglGetConfigAttrib(device.getHandle(), config, EGL.EGL_SURFACE_TYPE, stype, 0)) {
+ final IntBuffer stype = Buffers.newDirectIntBuffer(1);
+ if(! EGL.eglGetConfigAttrib(device.getHandle(), config, EGL.EGL_SURFACE_TYPE, stype)) {
throw new GLException("Could not determine EGL_SURFACE_TYPE");
}
- if ( 0 != ( stype[0] & EGL.EGL_WINDOW_BIT ) ) {
+ final int _stype = stype.get(0);
+ if ( 0 != ( _stype & EGL.EGL_WINDOW_BIT ) ) {
val |= GLGraphicsConfigurationUtil.WINDOW_BIT;
}
- if ( 0 != ( stype[0] & EGL.EGL_PIXMAP_BIT ) ) {
+ if ( 0 != ( _stype & EGL.EGL_PIXMAP_BIT ) ) {
val |= GLGraphicsConfigurationUtil.BITMAP_BIT;
}
- if ( 0 != ( stype[0] & EGL.EGL_PBUFFER_BIT ) ) {
+ if ( 0 != ( _stype & EGL.EGL_PBUFFER_BIT ) ) {
val |= GLGraphicsConfigurationUtil.PBUFFER_BIT |
- GLGraphicsConfigurationUtil.FBO_BIT;
+ GLGraphicsConfigurationUtil.FBO_BIT;
}
return val;
}
/**
+ * @param defaultQuirks GLRendererQuirks of the EGLDrawableFactory's defaultDevice
* @param device
* @param glp desired GLProfile, may be null
* @param config
@@ -174,39 +190,71 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
* @param forceTransparentFlag
* @return
*/
- public static EGLGLCapabilities EGLConfig2Capabilities(EGLGraphicsDevice device, GLProfile glp, long config,
- int winattrmask, boolean forceTransparentFlag) {
+ public static EGLGLCapabilities EGLConfig2Capabilities(final GLRendererQuirks defaultQuirks, final EGLGraphicsDevice device, GLProfile glp,
+ final long config, final int winattrmask, final boolean forceTransparentFlag) {
final long display = device.getHandle();
- final IntBuffer val = Buffers.newDirectIntBuffer(1);
final int cfgID;
final int rType;
final int visualID;
-
+
+ final int _attributes[] = {
+ EGL.EGL_CONFIG_ID, // 0
+ EGL.EGL_RENDERABLE_TYPE,
+ EGL.EGL_NATIVE_VISUAL_ID,
+ EGL.EGL_CONFIG_CAVEAT,
+ EGL.EGL_RED_SIZE, // 4
+ EGL.EGL_GREEN_SIZE,
+ EGL.EGL_BLUE_SIZE,
+ EGL.EGL_ALPHA_SIZE, // 7
+ EGL.EGL_STENCIL_SIZE, // 8
+ EGL.EGL_DEPTH_SIZE,
+ EGL.EGL_TRANSPARENT_TYPE, // 10
+ EGL.EGL_TRANSPARENT_RED_VALUE,
+ EGL.EGL_TRANSPARENT_GREEN_VALUE,
+ EGL.EGL_TRANSPARENT_BLUE_VALUE,
+ EGL.EGL_SAMPLES, // 14
+ EGLExt.EGL_COVERAGE_BUFFERS_NV, // 15
+ EGLExt.EGL_COVERAGE_SAMPLES_NV
+ };
+ final IntBuffer attributes = Buffers.newDirectIntBuffer(_attributes);
+ final IntBuffer values = Buffers.newDirectIntBuffer(attributes.remaining());
+ EGL.eglGetConfigAttributes(display, config, attributes, values);
+
// get the configID
- if(!EGL.eglGetConfigAttrib(display, config, EGL.EGL_CONFIG_ID, val)) {
+ if( EGL.EGL_CONFIG_ID != attributes.get(0) ) {
if(DEBUG) {
// FIXME: this happens on a ATI PC Emulation ..
- System.err.println("EGL couldn't retrieve ConfigID for config "+toHexString(config)+", error "+toHexString(EGL.eglGetError()));
+ System.err.println(dbgCfgFailIntro+"ConfigID"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
}
return null;
}
- cfgID = val.get(0);
-
- if(!EGL.eglGetConfigAttrib(display, config, EGL.EGL_RENDERABLE_TYPE, val)) {
+ cfgID = values.get(0);
+
+ if( EGL.EGL_RENDERABLE_TYPE != attributes.get(1) ) {
if(DEBUG) {
- System.err.println("EGL couldn't retrieve EGL_RENDERABLE_TYPE for config "+toHexString(config)+", error "+toHexString(EGL.eglGetError()));
+ System.err.println(dbgCfgFailIntro+"EGL_RENDERABLE_TYPE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
}
return null;
}
- rType = val.get(0);
+ {
+ final int rTypeOrig = values.get(1);
+ if( defaultQuirks.exist(GLRendererQuirks.GLES3ViaEGLES2Config) && 0 != ( EGL.EGL_OPENGL_ES2_BIT & rTypeOrig ) ) {
+ rType = rTypeOrig | EGLExt.EGL_OPENGL_ES3_BIT_KHR;
+ } else {
+ rType = rTypeOrig;
+ }
+ }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_NATIVE_VISUAL_ID, val)) {
- visualID = val.get(0);
+ if( EGL.EGL_NATIVE_VISUAL_ID == attributes.get(2) ) {
+ visualID = values.get(2);
} else {
+ if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_NATIVE_VISUAL_ID"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
+ }
visualID = VisualIDHolder.VID_UNDEFINED;
}
-
- EGLGLCapabilities caps = null;
+
+ EGLGLCapabilities caps = null;
try {
if(null == glp) {
glp = EGLGLCapabilities.getCompatible(device, rType);
@@ -214,98 +262,133 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
if(!EGLGLCapabilities.isCompatible(glp, rType)) {
if(DEBUG) {
System.err.println("config "+toHexString(config)+": Requested GLProfile "+glp+
- " not compatible with EGL-RenderableType["+EGLGLCapabilities.renderableTypeToString(null, rType)+"]");
+ " with quirks "+defaultQuirks+" not compatible with EGL-RenderableType["+EGLGLCapabilities.renderableTypeToString(null, rType)+"]");
}
return null;
}
caps = new EGLGLCapabilities(config, cfgID, visualID, glp, rType);
- } catch (GLException gle) {
+ } catch (final GLException gle) {
if(DEBUG) {
System.err.println("config "+toHexString(config)+": "+gle);
}
return null;
- }
-
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_CONFIG_CAVEAT, val)) {
- if( EGL.EGL_SLOW_CONFIG == val.get(0) ) {
- caps.setHardwareAccelerated(false);
- }
}
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_SAMPLES, val)) {
- caps.setSampleBuffers(val.get(0)>0?true:false);
- caps.setNumSamples(val.get(0));
- }
- if(!caps.getSampleBuffers()) {
- // try NV_coverage_sample extension
- if(EGL.eglGetConfigAttrib(display, config, EGLExt.EGL_COVERAGE_BUFFERS_NV, val)) {
- if(val.get(0)>0 &&
- EGL.eglGetConfigAttrib(display, config, EGLExt.EGL_COVERAGE_SAMPLES_NV, val)) {
- caps.setSampleExtension(GLGraphicsConfigurationUtil.NV_coverage_sample);
- caps.setSampleBuffers(true);
- caps.setNumSamples(val.get(0));
- }
+
+ if( EGL.EGL_CONFIG_CAVEAT == attributes.get(3) ) {
+ if( EGL.EGL_SLOW_CONFIG == values.get(3) ) {
+ caps.setHardwareAccelerated(false);
}
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_CONFIG_CAVEAT"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
}
- if(forceTransparentFlag) {
+ // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
+ if( EGL.EGL_RED_SIZE == attributes.get(4) ) {
+ caps.setRedBits(values.get(4));
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_RED_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
+ }
+ if( EGL.EGL_GREEN_SIZE == attributes.get(5) ) {
+ caps.setGreenBits(values.get(5));
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_GREEN_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
+ }
+ if( EGL.EGL_BLUE_SIZE == attributes.get(6) ) {
+ caps.setBlueBits(values.get(6));
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_BLUE_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
+ }
+ if( EGL.EGL_ALPHA_SIZE == attributes.get(7) ) {
+ caps.setAlphaBits(values.get(7));
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_ALPHA_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
+ }
+ if( EGL.EGL_STENCIL_SIZE == attributes.get(8) ) {
+ caps.setStencilBits(values.get(8));
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_STENCIL_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
+ }
+ if( EGL.EGL_DEPTH_SIZE == attributes.get(9) ) {
+ caps.setDepthBits(values.get(9));
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_DEPTH_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
+ }
+ if( forceTransparentFlag ) {
caps.setBackgroundOpaque(false);
- } else if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_TYPE, val)) {
- caps.setBackgroundOpaque(val.get(0) != EGL.EGL_TRANSPARENT_RGB);
+ } else if( EGL.EGL_TRANSPARENT_TYPE == attributes.get(10) ) {
+ caps.setBackgroundOpaque(values.get(10) != EGL.EGL_TRANSPARENT_RGB);
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_TRANSPARENT_TYPE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
}
if(!caps.isBackgroundOpaque()) {
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_RED_VALUE, val)) {
- caps.setTransparentRedValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0));
+ if( EGL.EGL_TRANSPARENT_RED_VALUE == attributes.get(11) ) {
+ final int v = values.get(11);
+ caps.setTransparentRedValue(EGL.EGL_DONT_CARE==v?-1:v);
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_TRANSPARENT_RED_VALUE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
}
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_GREEN_VALUE, val)) {
- caps.setTransparentGreenValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0));
+ if( EGL.EGL_TRANSPARENT_GREEN_VALUE == attributes.get(12) ) {
+ final int v = values.get(12);
+ caps.setTransparentGreenValue(EGL.EGL_DONT_CARE==v?-1:v);
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_TRANSPARENT_GREEN_VALUE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
}
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_BLUE_VALUE, val)) {
- caps.setTransparentBlueValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0));
+ if( EGL.EGL_TRANSPARENT_BLUE_VALUE == attributes.get(13) ) {
+ final int v = values.get(13);
+ caps.setTransparentBlueValue(EGL.EGL_DONT_CARE==v?-1:v);
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_TRANSPARENT_BLUE_VALUE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
}
- /** Not defined in EGL
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_ALPHA_VALUE, val)) {
- caps.setTransparentAlphaValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0));
+ /** Not defined in EGL
+ if( EGL.EGL_TRANSPARENT_ALPHA_VALUE == attributes.get(??) ) {
+ final int v = values.get(??);
+ caps.setTransparentAlphaValue(EGL.EGL_DONT_CARE==v?-1:v);
+ } else if(DEBUG) {
+ System.err.println(dbgStr01+"EGL_TRANSPARENT_ALPHA_VALUE"+dbgStr02+toHexString(config)+dbgEGLCfgFailError+toHexString(EGL.eglGetError()));
} */
}
- // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val)) {
- caps.setRedBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val)) {
- caps.setGreenBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val)) {
- caps.setBlueBits(val.get(0));
+ if( EGL.EGL_SAMPLES == attributes.get(14) ) {
+ final int numSamples = values.get(14);
+ caps.setSampleBuffers(numSamples>0?true:false);
+ caps.setNumSamples(numSamples);
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_SAMPLES"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
}
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val)) {
- caps.setAlphaBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val)) {
- caps.setStencilBits(val.get(0));
- }
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val)) {
- caps.setDepthBits(val.get(0));
+ if(!caps.getSampleBuffers()) {
+ // try NV_coverage_sample extension
+ if( EGLExt.EGL_COVERAGE_BUFFERS_NV == attributes.get(15) ) {
+ final boolean enabled = values.get(15) > 0;
+ if( enabled && EGLExt.EGL_COVERAGE_SAMPLES_NV == attributes.get(16) ) {
+ caps.setSampleExtension(GLGraphicsConfigurationUtil.NV_coverage_sample);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(values.get(16));
+ } else if(DEBUG) {
+ System.err.println(dbgCfgFailIntro+"EGL_COVERAGE_SAMPLES_NV"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
+ }
+ } /** else if(DEBUG) { // Not required - vendor extension - don't be verbose!
+ System.err.println(dbgCfgFailIntro+"EGL_COVERAGE_BUFFERS_NV"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError()));
+ } */
}
- // Since the passed GLProfile may be null,
+ // Since the passed GLProfile may be null,
// we use EGL_RENDERABLE_TYPE derived profile as created in the EGLGLCapabilities constructor.
- final int availableTypeBits = EGLConfigDrawableTypeBits(device, config);
+ final int availableTypeBits = EGLConfigDrawableTypeBits(device, config);
final int drawableTypeBits = winattrmask & availableTypeBits;
if( 0 == drawableTypeBits ) {
return null;
}
-
- return (EGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, caps);
+
+ return (EGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, caps);
}
- public static int[] GLCapabilities2AttribList(GLCapabilitiesImmutable caps) {
- int[] attrs = new int[32];
+ public static IntBuffer GLCapabilities2AttribList(final GLCapabilitiesImmutable caps) {
+ final IntBuffer attrs = Buffers.newDirectIntBuffer(32);
int idx=0;
- attrs[idx++] = EGL.EGL_SURFACE_TYPE;
+ attrs.put(idx++, EGL.EGL_SURFACE_TYPE);
final int surfaceType;
if( caps.isOnscreen() ) {
- surfaceType = EGL.EGL_WINDOW_BIT;
+ surfaceType = EGL.EGL_WINDOW_BIT;
} else if( caps.isFBO() ) {
surfaceType = EGL.EGL_PBUFFER_BIT; // native replacement!
} else if( caps.isPBuffer() ) {
@@ -315,99 +398,105 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
} else {
throw new GLException("no surface type set in caps: "+caps);
}
- attrs[idx++] = surfaceType;
+ attrs.put(idx++, surfaceType);
- attrs[idx++] = EGL.EGL_RED_SIZE;
- attrs[idx++] = caps.getRedBits();
+ attrs.put(idx++, EGL.EGL_RED_SIZE);
+ attrs.put(idx++, caps.getRedBits());
- attrs[idx++] = EGL.EGL_GREEN_SIZE;
- attrs[idx++] = caps.getGreenBits();
+ attrs.put(idx++, EGL.EGL_GREEN_SIZE);
+ attrs.put(idx++, caps.getGreenBits());
- attrs[idx++] = EGL.EGL_BLUE_SIZE;
- attrs[idx++] = caps.getBlueBits();
+ attrs.put(idx++, EGL.EGL_BLUE_SIZE);
+ attrs.put(idx++, caps.getBlueBits());
if(caps.getAlphaBits()>0) {
- attrs[idx++] = EGL.EGL_ALPHA_SIZE;
- attrs[idx++] = caps.getAlphaBits();
+ attrs.put(idx++, EGL.EGL_ALPHA_SIZE);
+ attrs.put(idx++, caps.getAlphaBits());
}
-
+
if(caps.getStencilBits()>0) {
- attrs[idx++] = EGL.EGL_STENCIL_SIZE;
- attrs[idx++] = caps.getStencilBits();
+ attrs.put(idx++, EGL.EGL_STENCIL_SIZE);
+ attrs.put(idx++, caps.getStencilBits());
}
- attrs[idx++] = EGL.EGL_DEPTH_SIZE;
- attrs[idx++] = caps.getDepthBits();
+ attrs.put(idx++, EGL.EGL_DEPTH_SIZE);
+ attrs.put(idx++, caps.getDepthBits());
if(caps.getSampleBuffers()) {
if(caps.getSampleExtension().equals(GLGraphicsConfigurationUtil.NV_coverage_sample)) {
- attrs[idx++] = EGLExt.EGL_COVERAGE_BUFFERS_NV;
- attrs[idx++] = 1;
- attrs[idx++] = EGLExt.EGL_COVERAGE_SAMPLES_NV;
- attrs[idx++] = caps.getNumSamples();
+ attrs.put(idx++, EGLExt.EGL_COVERAGE_BUFFERS_NV);
+ attrs.put(idx++, 1);
+ attrs.put(idx++, EGLExt.EGL_COVERAGE_SAMPLES_NV);
+ attrs.put(idx++, caps.getNumSamples());
} else {
// try default ..
- attrs[idx++] = EGL.EGL_SAMPLE_BUFFERS;
- attrs[idx++] = 1;
- attrs[idx++] = EGL.EGL_SAMPLES;
- attrs[idx++] = caps.getNumSamples();
+ attrs.put(idx++, EGL.EGL_SAMPLE_BUFFERS);
+ attrs.put(idx++, 1);
+ attrs.put(idx++, EGL.EGL_SAMPLES);
+ attrs.put(idx++, caps.getNumSamples());
}
}
- attrs[idx++] = EGL.EGL_TRANSPARENT_TYPE;
- attrs[idx++] = caps.isBackgroundOpaque() ? EGL.EGL_NONE : EGL.EGL_TRANSPARENT_TYPE;
+ attrs.put(idx++, EGL.EGL_TRANSPARENT_TYPE);
+ attrs.put(idx++, caps.isBackgroundOpaque() ? EGL.EGL_NONE : EGL.EGL_TRANSPARENT_TYPE);
// 22
if(!caps.isBackgroundOpaque()) {
- attrs[idx++] = EGL.EGL_TRANSPARENT_RED_VALUE;
- attrs[idx++] = caps.getTransparentRedValue()>=0?caps.getTransparentRedValue():EGL.EGL_DONT_CARE;
+ attrs.put(idx++, EGL.EGL_TRANSPARENT_RED_VALUE);
+ attrs.put(idx++, caps.getTransparentRedValue()>=0?caps.getTransparentRedValue():EGL.EGL_DONT_CARE);
- attrs[idx++] = EGL.EGL_TRANSPARENT_GREEN_VALUE;
- attrs[idx++] = caps.getTransparentGreenValue()>=0?caps.getTransparentGreenValue():EGL.EGL_DONT_CARE;
+ attrs.put(idx++, EGL.EGL_TRANSPARENT_GREEN_VALUE);
+ attrs.put(idx++, caps.getTransparentGreenValue()>=0?caps.getTransparentGreenValue():EGL.EGL_DONT_CARE);
- attrs[idx++] = EGL.EGL_TRANSPARENT_BLUE_VALUE;
- attrs[idx++] = caps.getTransparentBlueValue()>=0?caps.getTransparentBlueValue():EGL.EGL_DONT_CARE;
+ attrs.put(idx++, EGL.EGL_TRANSPARENT_BLUE_VALUE);
+ attrs.put(idx++, caps.getTransparentBlueValue()>=0?caps.getTransparentBlueValue():EGL.EGL_DONT_CARE);
/** Not define in EGL
- attrs[idx++] = EGL.EGL_TRANSPARENT_ALPHA_VALUE;
- attrs[idx++] = caps.getTransparentAlphaValue()>=0?caps.getTransparentAlphaValue():EGL.EGL_DONT_CARE; */
+ attrs.put(idx++, EGL.EGL_TRANSPARENT_ALPHA_VALUE;
+ attrs.put(idx++, caps.getTransparentAlphaValue()>=0?caps.getTransparentAlphaValue():EGL.EGL_DONT_CARE; */
}
- // 28
- attrs[idx++] = EGL.EGL_RENDERABLE_TYPE;
+ // 28
+ attrs.put(idx++, EGL.EGL_RENDERABLE_TYPE);
if(caps.getGLProfile().usesNativeGLES1()) {
- attrs[idx++] = EGL.EGL_OPENGL_ES_BIT;
+ attrs.put(idx++, EGL.EGL_OPENGL_ES_BIT);
} else if(caps.getGLProfile().usesNativeGLES2()) {
- attrs[idx++] = EGL.EGL_OPENGL_ES2_BIT;
+ attrs.put(idx++, EGL.EGL_OPENGL_ES2_BIT);
+ } else if(caps.getGLProfile().usesNativeGLES3()) {
+ if( GLRendererQuirks.existStickyDeviceQuirk(GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) {
+ attrs.put(idx++, EGL.EGL_OPENGL_ES2_BIT);
+ } else {
+ attrs.put(idx++, EGLExt.EGL_OPENGL_ES3_BIT_KHR);
+ }
} else {
- attrs[idx++] = EGL.EGL_OPENGL_BIT;
+ attrs.put(idx++, EGL.EGL_OPENGL_BIT);
}
// 30
- attrs[idx++] = EGL.EGL_NONE;
+ attrs.put(idx++, EGL.EGL_NONE);
return attrs;
}
- public static int[] CreatePBufferSurfaceAttribList(int width, int height, int texFormat) {
- int[] attrs = new int[16];
+ public static IntBuffer CreatePBufferSurfaceAttribList(final int width, final int height, final int texFormat) {
+ final IntBuffer attrs = Buffers.newDirectIntBuffer(16);
int idx=0;
- attrs[idx++] = EGL.EGL_WIDTH;
- attrs[idx++] = width;
+ attrs.put(idx++, EGL.EGL_WIDTH);
+ attrs.put(idx++, width);
- attrs[idx++] = EGL.EGL_HEIGHT;
- attrs[idx++] = height;
+ attrs.put(idx++, EGL.EGL_HEIGHT);
+ attrs.put(idx++, height);
- attrs[idx++] = EGL.EGL_TEXTURE_FORMAT;
- attrs[idx++] = texFormat;
+ attrs.put(idx++, EGL.EGL_TEXTURE_FORMAT);
+ attrs.put(idx++, texFormat);
- attrs[idx++] = EGL.EGL_TEXTURE_TARGET;
- attrs[idx++] = EGL.EGL_NO_TEXTURE==texFormat ? EGL.EGL_NO_TEXTURE : EGL.EGL_TEXTURE_2D;
+ attrs.put(idx++, EGL.EGL_TEXTURE_TARGET);
+ attrs.put(idx++, EGL.EGL_NO_TEXTURE==texFormat ? EGL.EGL_NO_TEXTURE : EGL.EGL_TEXTURE_2D);
- attrs[idx++] = EGL.EGL_NONE;
+ attrs.put(idx++, EGL.EGL_NONE);
return attrs;
}
@@ -422,6 +511,6 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
}
- private GLCapabilitiesChooser chooser;
+ private final GLCapabilitiesChooser chooser;
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
index e72255108..d4e5e7d62 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -42,7 +42,6 @@ import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.nativewindow.NativeWindowFactory;
-
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
@@ -54,6 +53,7 @@ import javax.media.opengl.GLDrawableFactory;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+import com.jogamp.opengl.GLRendererQuirks;
import jogamp.opengl.GLGraphicsConfigurationFactory;
import jogamp.opengl.GLGraphicsConfigurationUtil;
@@ -75,10 +75,10 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
static GraphicsConfigurationFactory nativeGraphicsConfigurationFactory = null;
static GraphicsConfigurationFactory kdeglGraphicsConfigurationFactory = null;
static GraphicsConfigurationFactory fallbackGraphicsConfigurationFactory = null;
-
+
static void registerFactory() {
- GraphicsConfigurationFactory eglFactory = new EGLGraphicsConfigurationFactory();
-
+ final GraphicsConfigurationFactory eglFactory = new EGLGraphicsConfigurationFactory();
+
// become the pre-selector for X11/.. to match the native visual id w/ EGL, if native ES is selected
final String nwType = NativeWindowFactory.getNativeWindowType(false);
if(NativeWindowFactory.TYPE_X11 == nwType) {
@@ -86,38 +86,39 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
if(null != nativeGraphicsConfigurationFactory) {
fallbackGraphicsConfigurationFactory = nativeGraphicsConfigurationFactory;
} else {
- fallbackGraphicsConfigurationFactory = GraphicsConfigurationFactory.getFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class);
+ fallbackGraphicsConfigurationFactory = GraphicsConfigurationFactory.getFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class);
}
} /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) {
nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, eglFactory);
- } else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
+ } else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
} */
-
+
// become the selector for KD/EGL ..
- kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory);
+ kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory);
}
-
+
static void unregisterFactory() {
final String nwType = NativeWindowFactory.getNativeWindowType(false);
if(NativeWindowFactory.TYPE_X11 == nwType) {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, nativeGraphicsConfigurationFactory);
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, nativeGraphicsConfigurationFactory);
} /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) {
GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, nativeGraphicsConfigurationFactory);
- } else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
+ } else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) {
} */
nativeGraphicsConfigurationFactory = null;
fallbackGraphicsConfigurationFactory = null;
-
+
GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, kdeglGraphicsConfigurationFactory);
kdeglGraphicsConfigurationFactory = null;
}
-
+
private EGLGraphicsConfigurationFactory() {
}
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl (
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser, final AbstractGraphicsScreen absScreen, final int nativeVisualID) {
if (absScreen == null) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only AbstractGraphicsDevice objects");
}
@@ -136,24 +137,24 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects");
}
- AbstractGraphicsDevice absDevice = absScreen.getDevice();
+ final AbstractGraphicsDevice absDevice = absScreen.getDevice();
if(null==absDevice) {
throw new GLException("Null AbstractGraphicsDevice");
- }
-
+ }
+
AbstractGraphicsConfiguration cfg = null;
-
+
if( absDevice instanceof EGLGraphicsDevice ) {
cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen,
(GLCapabilitiesImmutable) capsRequested,
(GLCapabilitiesChooser) chooser,
- absScreen, nativeVisualID, false);
+ absScreen, nativeVisualID, false);
} else {
- // handle non native cases (X11, ..)
+ // handle non native cases (X11, ..)
if(null == fallbackGraphicsConfigurationFactory) {
throw new InternalError("Native fallback GraphicsConfigurationFactory is null, but call issued for device: "+absDevice+" of type "+absDevice.getClass().getSimpleName());
}
-
+
if(glCapsChosen.getGLProfile().usesNativeGLES()) {
if(DEBUG) {
System.err.println("EGLGraphicsConfigurationFactory.choose..: Handle native device "+absDevice.getClass().getSimpleName());
@@ -175,24 +176,23 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
System.err.println("EGLGraphicsConfigurationFactory.choose..: Delegate to "+fallbackGraphicsConfigurationFactory.getClass().getSimpleName());
}
cfg = fallbackGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen, nativeVisualID);
- }
+ }
}
return cfg;
}
- protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(EGLDrawableFactory factory, AbstractGraphicsDevice device) {
- EGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateEGLSharedResource(device);
+ protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(final EGLDrawableFactory factory, final AbstractGraphicsDevice device) {
+ final EGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
- EGLGraphicsDevice eglDevice = sharedResource.getDevice();
- long eglDisplay = eglDevice.getHandle();
+ final EGLGraphicsDevice eglDevice = sharedResource.getDevice();
+ final long eglDisplay = eglDevice.getHandle();
if(0 == eglDisplay) {
throw new GLException("null eglDisplay");
}
-
List<GLCapabilitiesImmutable> availableCaps = null;
- IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
+ final IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
if(!EGL.eglGetConfigs(eglDisplay, null, 0, numConfigs)) {
throw new GLException("Graphics configuration get maxConfigs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
@@ -201,26 +201,25 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
throw new GLException("Graphics configuration get maxConfigs (eglGetConfigs) no configs");
}
- PointerBuffer configs = PointerBuffer.allocateDirect(numConfigs.get(0));
+ final PointerBuffer configs = PointerBuffer.allocateDirect(numConfigs.get(0));
if(!EGL.eglGetConfigs(eglDisplay, configs, configs.capacity(), numConfigs)) {
throw new GLException("Graphics configuration get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
}
if (numConfigs.get(0) > 0) {
- availableCaps = eglConfigs2GLCaps(eglDevice, null, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, false);
+ availableCaps = eglConfigs2GLCaps(eglDevice, null, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, false /* forceTransparentFlag */, false /* onlyFirstValid */);
if( null != availableCaps && availableCaps.size() > 1) {
Collections.sort(availableCaps, EglCfgIDComparator);
}
}
-
return availableCaps;
}
public static EGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
- GLCapabilitiesImmutable capsReq,
- GLCapabilitiesChooser chooser,
- AbstractGraphicsScreen absScreen, int nativeVisualID,
- boolean forceTransparentFlag) {
+ final GLCapabilitiesImmutable capsReq,
+ final GLCapabilitiesChooser chooser,
+ final AbstractGraphicsScreen absScreen, final int nativeVisualID,
+ final boolean forceTransparentFlag) {
if (capsChosen == null) {
capsChosen = new GLCapabilities(null);
}
@@ -228,11 +227,11 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
if(null==absScreen) {
throw new GLException("Null AbstractGraphicsScreen");
}
- AbstractGraphicsDevice absDevice = absScreen.getDevice();
+ final AbstractGraphicsDevice absDevice = absScreen.getDevice();
if(null==absDevice) {
throw new GLException("Null AbstractGraphicsDevice");
}
-
+
final EGLGraphicsDevice eglDevice;
final boolean ownEGLDisplay;
if( absDevice instanceof EGLGraphicsDevice ) {
@@ -243,19 +242,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
ownEGLDisplay = false;
} else {
eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(absDevice.getHandle(), absDevice.getConnection(), absDevice.getUnitID());
+ eglDevice.open();
ownEGLDisplay = true;
}
final GLProfile glp = capsChosen.getGLProfile();
- final EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory();
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(absDevice, glp), factory.canCreateGLPbuffer(absDevice) );
-
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLDrawableFactory.getEGLFactory(), absDevice);
EGLGraphicsConfiguration res = eglChooseConfig(eglDevice, capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag);
if(null==res) {
if(DEBUG) {
System.err.println("eglChooseConfig failed with given capabilities "+capsChosen);
}
-
+
// Last try .. add a fixed embedded profile [ATI, Nokia, Intel, ..]
//
// rgb888 - d16, s4
@@ -270,7 +268,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
fixedCaps.setOnscreen(false);
fixedCaps.setPBuffer(capsChosen.isPBuffer());
fixedCaps.setFBO(capsChosen.isFBO());
- }
+ }
if(DEBUG) {
System.err.println("trying fixed caps (1): "+fixedCaps);
}
@@ -288,7 +286,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
fixedCaps.setOnscreen(false);
fixedCaps.setPBuffer(capsChosen.isPBuffer());
fixedCaps.setFBO(capsChosen.isFBO());
- }
+ }
if(DEBUG) {
System.err.println("trying fixed caps (2): "+fixedCaps);
}
@@ -308,7 +306,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
fixedCaps.setOnscreen(false);
fixedCaps.setPBuffer(capsChosen.isPBuffer());
fixedCaps.setFBO(capsChosen.isFBO());
- }
+ }
if(DEBUG) {
System.err.println("trying fixed caps (3): "+fixedCaps);
}
@@ -324,19 +322,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
return res;
}
-
- static EGLGraphicsConfiguration eglChooseConfig(EGLGraphicsDevice device,
- GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- AbstractGraphicsScreen absScreen,
- int nativeVisualID, boolean forceTransparentFlag) {
+
+ static EGLGraphicsConfiguration eglChooseConfig(final EGLGraphicsDevice device,
+ final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser,
+ final AbstractGraphicsScreen absScreen,
+ final int nativeVisualID, final boolean forceTransparentFlag) {
final long eglDisplay = device.getHandle();
final GLProfile glp = capsChosen.getGLProfile();
final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen);
List<GLCapabilitiesImmutable> availableCaps = null;
int recommendedIndex = -1;
- long recommendedEGLConfig = -1;
- IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
+ final IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
if(!EGL.eglGetConfigs(eglDisplay, null, 0, numConfigs)) {
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: Get maxConfigs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
@@ -344,52 +341,70 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
if(0 == numConfigs.get(0)) {
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: Get maxConfigs (eglGetConfigs) no configs");
}
+ final int numEGLConfigs = numConfigs.get(0);
if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig eglDisplay "+toHexString(eglDisplay)+
", nativeVisualID "+toHexString(nativeVisualID)+
", capsChosen "+capsChosen+", winbits "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrmask).toString()+
", fboAvail "+GLContext.isFBOAvailable(device, glp)+
", device "+device+", "+device.getUniqueID()+
- ", numConfigs "+numConfigs.get(0));
+ ", numEGLConfigs "+numEGLConfigs);
}
- final IntBuffer attrs = Buffers.newDirectIntBuffer(EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen));
- PointerBuffer configs = PointerBuffer.allocateDirect(numConfigs.get(0));
+ final IntBuffer attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen);
+ final PointerBuffer configs = PointerBuffer.allocateDirect(numConfigs.get(0));
- // 1st choice: get GLCapabilities based on users GLCapabilities
+ // 1st choice: get GLCapabilities based on users GLCapabilities
// setting recommendedIndex as preferred choice
// skipped if nativeVisualID is given
- if( VisualIDHolder.VID_UNDEFINED != nativeVisualID || !EGL.eglChooseConfig(eglDisplay, attrs, configs, configs.capacity(), numConfigs) ) {
+ final boolean hasEGLChosenCaps;
+ if( VisualIDHolder.VID_UNDEFINED == nativeVisualID ) {
+ if( !EGL.eglChooseConfig(eglDisplay, attrs, configs, configs.capacity(), numConfigs) ) {
+ if(DEBUG) {
+ System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: false");
+ }
+ numConfigs.put(0, 0);
+ hasEGLChosenCaps = false;
+ } else {
+ hasEGLChosenCaps = numConfigs.get(0)>0;
+ }
+ } else {
if(DEBUG) {
- System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: false");
+ System.err.println("EGLGraphicsConfiguration.eglChooseConfig: Skipped due to given visualID: "+toHexString(nativeVisualID));
}
- } else if (numConfigs.get(0) > 0) {
- availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);
+ hasEGLChosenCaps = false;
+ }
+ final boolean useRecommendedIndex = hasEGLChosenCaps && !forceTransparentFlag && capsChosen.isBackgroundOpaque(); // only use recommended idx if not translucent
+ final boolean skipCapsChooser = null == chooser && useRecommendedIndex; // fast path: skip choosing if using recommended idx and null chooser is used
+ if( hasEGLChosenCaps ) {
+ availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), winattrmask, forceTransparentFlag, skipCapsChooser /* onlyFirsValid */);
if(availableCaps.size() > 0) {
- recommendedEGLConfig = configs.get(0);
+ final long recommendedEGLConfig = configs.get(0);
recommendedIndex = 0;
if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: recommended fbcfg " + toHexString(recommendedEGLConfig) + ", idx " + recommendedIndex);
+ System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 useRecommendedIndex "+useRecommendedIndex+", skipCapsChooser "+skipCapsChooser);
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 fbcfg caps " + availableCaps.get(recommendedIndex));
}
} else if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: no caps for recommended fbcfg " + toHexString(configs.get(0)));
+ System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 useRecommendedIndex "+useRecommendedIndex+", skipCapsChooser "+skipCapsChooser);
}
} else if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: no configs");
+ System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 useRecommendedIndex "+useRecommendedIndex+", skipCapsChooser "+skipCapsChooser);
}
// 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available
if( null == availableCaps || 0 == availableCaps.size() ) {
// reset ..
- recommendedEGLConfig = -1;
recommendedIndex = -1;
if(!EGL.eglGetConfigs(eglDisplay, configs, configs.capacity(), numConfigs)) {
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: #2 Get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
}
if (numConfigs.get(0) > 0) {
- availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);
+ availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), winattrmask, forceTransparentFlag, false /* onlyFirsValid */);
}
}
@@ -397,12 +412,12 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
if(DEBUG) {
// FIXME: this happens on a ATI PC Emulation ..
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #2 Graphics configuration 1st choice and 2nd choice failed - no configs");
- availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag);
+ availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag, false /* onlyFirsValid */);
printCaps("AllCaps", availableCaps, System.err);
}
return null;
}
-
+
if(DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: got configs: "+availableCaps.size());
for(int i=0; i<availableCaps.size(); i++) {
@@ -410,11 +425,16 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
}
}
- if( VisualIDHolder.VID_UNDEFINED != nativeVisualID ) {
- List<GLCapabilitiesImmutable> removedCaps = new ArrayList<GLCapabilitiesImmutable>();
+ if( VisualIDHolder.VID_UNDEFINED != nativeVisualID ) { // implies !hasEGLChosenCaps
+ final List<GLCapabilitiesImmutable> removedCaps = new ArrayList<GLCapabilitiesImmutable>();
for(int i=0; i<availableCaps.size(); ) {
- VisualIDHolder vidh = (VisualIDHolder) availableCaps.get(i);
- if(vidh.getVisualID(VIDType.NATIVE) != nativeVisualID) {
+ final GLCapabilitiesImmutable aCap = availableCaps.get(i);
+ if(aCap.getVisualID(VIDType.NATIVE) != nativeVisualID) {
+ if(DEBUG) { System.err.println("Remove["+i+"] (mismatch VisualID): "+aCap); }
+ removedCaps.add(availableCaps.remove(i));
+ } else if( 0 == aCap.getDepthBits() && 0 < capsChosen.getDepthBits() ) {
+ // Hack for HiSilicon/Vivante/Immersion.16 Renderer ..
+ if(DEBUG) { System.err.println("Remove["+i+"] (mismatch depth-bits): "+aCap); }
removedCaps.add(availableCaps.remove(i));
} else {
i++;
@@ -427,10 +447,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
}
} else if(DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: post filter nativeVisualID "+toHexString(nativeVisualID)+" got configs: "+availableCaps.size());
+ for(int i=0; i<availableCaps.size(); i++) {
+ System.err.println(i+": "+availableCaps.get(i));
+ }
}
}
- final int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
+ final int chosenIndex;
+ if( skipCapsChooser && 0 <= recommendedIndex ) {
+ chosenIndex = recommendedIndex;
+ } else {
+ chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
+ }
if ( 0 > chosenIndex ) {
if (DEBUG) {
System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #2 chooseCapabilities failed");
@@ -445,18 +473,22 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
return res;
}
- static List<GLCapabilitiesImmutable> eglConfigs2GLCaps(EGLGraphicsDevice device, GLProfile glp, PointerBuffer configs, int num, int winattrmask, boolean forceTransparentFlag) {
- List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(num);
+ static List<GLCapabilitiesImmutable> eglConfigs2GLCaps(final EGLGraphicsDevice device, final GLProfile glp, final PointerBuffer configs, final int num, final int winattrmask, final boolean forceTransparentFlag, final boolean onlyFirstValid) {
+ final GLRendererQuirks defaultQuirks = GLRendererQuirks.getStickyDeviceQuirks( GLDrawableFactory.getEGLFactory().getDefaultDevice() );
+ final List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(num);
for(int i=0; i<num; i++) {
- final GLCapabilitiesImmutable caps = EGLGraphicsConfiguration.EGLConfig2Capabilities(device, glp, configs.get(i), winattrmask, forceTransparentFlag);
+ final GLCapabilitiesImmutable caps = EGLGraphicsConfiguration.EGLConfig2Capabilities(defaultQuirks, device, glp, configs.get(i), winattrmask, forceTransparentFlag);
if(null != caps) {
bucket.add(caps);
+ if(onlyFirstValid) {
+ break;
+ }
}
}
return bucket;
}
- static void printCaps(String prefix, List<GLCapabilitiesImmutable> caps, PrintStream out) {
+ static void printCaps(final String prefix, final List<GLCapabilitiesImmutable> caps, final PrintStream out) {
for(int i=0; i<caps.size(); i++) {
out.println(prefix+"["+i+"] "+caps.get(i));
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java
deleted file mode 100644
index 325ad6142..000000000
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.egl;
-
-import javax.media.opengl.*;
-
-public class EGLOnscreenContext extends EGLContext {
- public EGLOnscreenContext(EGLOnscreenDrawable drawable, GLContext shareWith) {
- super(drawable, shareWith);
- }
-}
-
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
index 6440cf1e5..4c018fe25 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
@@ -44,18 +44,18 @@ import javax.media.opengl.*;
import javax.media.nativewindow.*;
public class EGLOnscreenDrawable extends EGLDrawable {
- protected EGLOnscreenDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException {
+ protected EGLOnscreenDrawable(final EGLDrawableFactory factory, final NativeSurface component) throws GLException {
super(factory, component);
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new EGLOnscreenContext(this, shareWith);
+ public GLContext createContext(final GLContext shareWith) {
+ return new EGLContext(this, shareWith);
}
@Override
- protected long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle) {
+ protected long createSurface(final EGLGraphicsConfiguration config, final int width, final int height, final long nativeSurfaceHandle) {
return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), config.getNativeConfig(), nativeSurfaceHandle, null);
- }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java
deleted file mode 100644
index bb9eeb892..000000000
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.egl;
-
-import javax.media.opengl.*;
-
-public class EGLPbufferContext extends EGLContext {
- public EGLPbufferContext(EGLPbufferDrawable drawable, GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public int getFloatingPointMode() {
- return 0; // FIXME ??
- }
-}
-
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
index eb7e320c8..8842edbc0 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
@@ -41,24 +41,23 @@
package jogamp.opengl.egl;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GLContext;
public class EGLPbufferDrawable extends EGLDrawable {
protected static final boolean useTexture = false; // No yet ..
- protected EGLPbufferDrawable(EGLDrawableFactory factory, NativeSurface target) {
+ protected EGLPbufferDrawable(final EGLDrawableFactory factory, final NativeSurface target) {
super(factory, target);
}
@Override
- protected long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle) {
+ protected long createSurface(final EGLGraphicsConfiguration config, final int width, final int height, final long nativeSurfaceHandle) {
return EGLDrawableFactory.createPBufferSurfaceImpl(config, width, height, false);
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new EGLPbufferContext(this, shareWith);
+ public GLContext createContext(final GLContext shareWith) {
+ return new EGLContext(this, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
index 342c4c417..cc15f0cd6 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
@@ -13,12 +13,19 @@ import javax.media.opengl.GLException;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+/**
+ * <pre>
+ * EGLWrappedSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a
+ * EGLUpstreamSurfaceHook [ is_a -> UpstreamSurfaceHook.MutableSize -> UpstreamSurfaceHook ] has_a
+ * NativeSurface (e.g. native X11 surface)
+ * </pre>
+ */
public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
protected static final boolean DEBUG = EGLDrawableFactory.DEBUG;
private final NativeSurface upstreamSurface;
- private final UpstreamSurfaceHook.MutableSize upstreamSurfaceHookMutableSize;
-
- public EGLUpstreamSurfaceHook(NativeSurface upstream) {
+ private final UpstreamSurfaceHook.MutableSize upstreamSurfaceHookMutableSize;
+
+ public EGLUpstreamSurfaceHook(final NativeSurface upstream) {
upstreamSurface = upstream;
if(upstreamSurface instanceof ProxySurface) {
final UpstreamSurfaceHook ush = ((ProxySurface)upstreamSurface).getUpstreamSurfaceHook();
@@ -32,32 +39,40 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
upstreamSurfaceHookMutableSize = null;
}
}
-
- public final NativeSurface getUpstreamSurface() { return upstreamSurface; }
-
+
static String getThreadName() { return Thread.currentThread().getName(); }
-
- public final void setSize(int width, int height) {
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns the actual upstream {@link NativeSurface}, e.g. native X11 surface.
+ * </p>
+ */
+ @Override
+ public final NativeSurface getUpstreamSurface() { return upstreamSurface; }
+
+ @Override
+ public final void setSurfaceSize(final int width, final int height) {
if(null != upstreamSurfaceHookMutableSize) {
- upstreamSurfaceHookMutableSize.setSize(width, height);
- }
+ upstreamSurfaceHookMutableSize.setSurfaceSize(width, height);
+ }
}
-
+
@Override
- public final void create(ProxySurface surface) {
+ public final void create(final ProxySurface surface) {
final String dbgPrefix;
if(DEBUG) {
- dbgPrefix = getThreadName() + ": EGLUpstreamSurfaceHook.create("+surface.getClass().getSimpleName()+"): ";
- System.err.println(dbgPrefix+this);
+ dbgPrefix = getThreadName() + ": EGLUpstreamSurfaceHook.create( up "+upstreamSurface.getClass().getSimpleName()+" -> this "+surface.getClass().getSimpleName()+" ): ";
+ System.err.println(dbgPrefix+this);
} else {
dbgPrefix = null;
}
-
+
if(upstreamSurface instanceof ProxySurface) {
- // propagate createNotify(..) so upstreamSurface will be created
+ // propagate createNotify(..) so upstreamSurface will be created
((ProxySurface)upstreamSurface).createNotify();
}
-
+
// lock upstreamSurface, so it can be used in case EGLDisplay is derived from it!
if(NativeSurface.LOCK_SURFACE_NOT_READY >= upstreamSurface.lockSurface()) {
throw new GLException("Could not lock: "+upstreamSurface);
@@ -66,42 +81,70 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
evalUpstreamSurface(dbgPrefix, surface);
} finally {
upstreamSurface.unlockSurface();
- }
+ }
}
-
- private final void evalUpstreamSurface(String dbgPrefix, ProxySurface surface) {
+
+ private final void evalUpstreamSurface(final String dbgPrefix, final ProxySurface surface) {
//
// evaluate nature of upstreamSurface, may create EGL instances if required
//
-
+
boolean isEGLSurfaceValid = true; // assume yes
-
- final AbstractGraphicsConfiguration aConfig = upstreamSurface.getGraphicsConfiguration();
- final AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice();
-
+
final EGLGraphicsDevice eglDevice;
- if( aDevice instanceof EGLGraphicsDevice ) {
- eglDevice = (EGLGraphicsDevice) aDevice;
+ final AbstractGraphicsConfiguration aConfig;
+ {
+ final AbstractGraphicsConfiguration surfaceConfig = surface.getGraphicsConfiguration();
+ final AbstractGraphicsDevice surfaceDevice = null != surfaceConfig ? surfaceConfig.getScreen().getDevice() : null;
if(DEBUG) {
- System.err.println(dbgPrefix+"Reusing eglDevice: "+eglDevice);
+ System.err.println(dbgPrefix+"SurfaceDevice: "+surfaceDevice.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(surfaceDevice.hashCode())+", "+surfaceDevice);
+ System.err.println(dbgPrefix+"SurfaceConfig: "+surfaceConfig.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(surfaceConfig.hashCode())+", "+surfaceConfig);
}
- if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
+
+ final AbstractGraphicsConfiguration upstreamConfig = upstreamSurface.getGraphicsConfiguration();
+ final AbstractGraphicsDevice upstreamDevice = upstreamConfig.getScreen().getDevice();
+ if(DEBUG) {
+ System.err.println(dbgPrefix+"UpstreamDevice: "+upstreamDevice.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(upstreamDevice.hashCode())+", "+upstreamDevice);
+ System.err.println(dbgPrefix+"UpstreamConfig: "+upstreamConfig.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(upstreamConfig.hashCode())+", "+upstreamConfig);
+ }
+
+ if( surfaceDevice instanceof EGLGraphicsDevice ) {
+ eglDevice = (EGLGraphicsDevice) surfaceDevice;
+ aConfig = surfaceConfig;
+ if(DEBUG) {
+ System.err.println(dbgPrefix+"Reusing this eglDevice: "+eglDevice+", using this config "+aConfig.getClass().getSimpleName()+" "+aConfig);
+ }
+ if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
+ eglDevice.open();
+ isEGLSurfaceValid = false;
+ surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ } else if( upstreamDevice instanceof EGLGraphicsDevice ) {
+ eglDevice = (EGLGraphicsDevice) upstreamDevice;
+ aConfig = upstreamConfig;
+ if(DEBUG) {
+ System.err.println(dbgPrefix+"Reusing upstream eglDevice: "+eglDevice+", using upstream config "+aConfig.getClass().getSimpleName()+" "+aConfig);
+ }
+ if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
+ eglDevice.open();
+ isEGLSurfaceValid = false;
+ surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ } else {
+ eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface);
eglDevice.open();
+ aConfig = upstreamConfig;
isEGLSurfaceValid = false;
surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
}
- } else {
- eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface);
- isEGLSurfaceValid = false;
- surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
}
-
+
final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
final EGLGraphicsConfiguration eglConfig;
if( aConfig instanceof EGLGraphicsConfiguration ) {
// Config is already in EGL type - reuse ..
final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities();
- if( !isEGLSurfaceValid || !EGLGraphicsConfiguration.isEGLConfigValid(eglDevice.getHandle(), capsChosen.getEGLConfig()) ) {
+ if( !isEGLSurfaceValid || !EGLGraphicsConfiguration.isEGLConfigValid(eglDevice.getHandle(), capsChosen.getEGLConfig()) ) {
// 'refresh' the native EGLConfig handle
capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID()));
if( 0 == capsChosen.getEGLConfig() ) {
@@ -122,7 +165,7 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
} else {
final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex());
eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false);
+ capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false /* forceTransparencyFlag */);
if (null == eglConfig) {
throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen);
@@ -132,7 +175,7 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
isEGLSurfaceValid = false;
}
surface.setGraphicsConfiguration(eglConfig);
-
+
if(isEGLSurfaceValid) {
isEGLSurfaceValid = EGLDrawable.isValidEGLSurface(eglDevice.getHandle(), upstreamSurface.getSurfaceHandle());
}
@@ -148,34 +191,44 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
if(DEBUG) {
System.err.println(dbgPrefix+"Fin: EGL surface n/a - TBD: "+upstreamSurface);
}
- }
+ }
}
@Override
- public final void destroy(ProxySurface surface) {
+ public final void destroy(final ProxySurface surface) {
if(EGLDrawableFactory.DEBUG) {
- System.err.println("EGLUpstreamSurfaceHook.destroy("+surface.getClass().getSimpleName()+"): "+this);
+ System.err.println("EGLUpstreamSurfaceHook.destroy("+surface.getClass().getSimpleName()+"): "+this);
}
- surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
if(upstreamSurface instanceof ProxySurface) {
((ProxySurface)upstreamSurface).destroyNotify();
}
}
@Override
- public final int getWidth(ProxySurface s) {
- return upstreamSurface.getWidth();
+ public final int getSurfaceWidth(final ProxySurface s) {
+ return upstreamSurface.getSurfaceWidth();
}
@Override
- public final int getHeight(ProxySurface s) {
- return upstreamSurface.getHeight();
+ public final int getSurfaceHeight(final ProxySurface s) {
+ return upstreamSurface.getSurfaceHeight();
}
-
+
@Override
public String toString() {
- final String us_s = null != upstreamSurface ? ( upstreamSurface.getClass().getName() + ": 0x" + Long.toHexString(upstreamSurface.getSurfaceHandle()) ) : "nil";
- return "EGLUpstreamSurfaceHook[ "+ upstreamSurface.getWidth() + "x" + upstreamSurface.getHeight() + ", " + us_s+ "]";
+ final String us_s;
+ final int sw, sh;
+ if( null != upstreamSurface ) {
+ us_s = upstreamSurface.getClass().getName() + ": 0x" + Long.toHexString(upstreamSurface.getSurfaceHandle());
+ sw = upstreamSurface.getSurfaceWidth();
+ sh = upstreamSurface.getSurfaceHeight();
+ } else {
+ us_s = "nil";
+ sw = -1;
+ sh = -1;
+ }
+ return "EGLUpstreamSurfaceHook[ "+ sw + "x" + sh + ", " + us_s+ "]";
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java
index b36303392..89024eed3 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java
@@ -4,23 +4,27 @@ import javax.media.nativewindow.NativeSurface;
import jogamp.nativewindow.WrappedSurface;
+/**
+ * <pre>
+ * EGLWrappedSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a
+ * EGLUpstreamSurfaceHook [ is_a -> UpstreamSurfaceHook.MutableSize -> UpstreamSurfaceHook ] has_a
+ * NativeSurface (i.e. native X11 surface)
+ * </pre>
+ */
public class EGLWrappedSurface extends WrappedSurface {
- public static EGLWrappedSurface get(NativeSurface surface) {
+ public static EGLWrappedSurface get(final NativeSurface surface) {
if(surface instanceof EGLWrappedSurface) {
return (EGLWrappedSurface)surface;
}
return new EGLWrappedSurface(surface);
}
-
- public EGLWrappedSurface(NativeSurface surface) {
+
+ public EGLWrappedSurface(final NativeSurface surface) {
super(surface.getGraphicsConfiguration(), EGL.EGL_NO_SURFACE, new EGLUpstreamSurfaceHook(surface), false /* tbd in UpstreamSurfaceHook */);
if(EGLDrawableFactory.DEBUG) {
- System.err.println("EGLWrappedSurface.ctor(): "+this);
+ System.err.println("EGLWrappedSurface.ctor(): "+this);
}
}
- public final NativeSurface getUpstreamSurface() {
- return ((EGLUpstreamSurfaceHook)super.getUpstreamSurfaceHook()).getUpstreamSurface();
- }
}
diff --git a/src/jogl/classes/jogamp/opengl/gl2/ProjectDouble.java b/src/jogl/classes/jogamp/opengl/gl2/ProjectDouble.java
index 9165dbc4b..f0922644b 100644
--- a/src/jogl/classes/jogamp/opengl/gl2/ProjectDouble.java
+++ b/src/jogl/classes/jogamp/opengl/gl2/ProjectDouble.java
@@ -6,9 +6,9 @@
** this file except in compliance with the License. You may obtain a copy
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
-**
+**
** http://oss.sgi.com/projects/FreeB
-**
+**
** Note that, as provided in the License, the Software is distributed on an
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
@@ -24,13 +24,13 @@
** except that Section 2.2 and 11 are omitted. Any differences between
** the Alternative License and the SGI License are offered solely by Sun
** and not by SGI.
-**
+**
** Original Code. The Original Code is: OpenGL Sample Implementation,
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
** Copyright in any portions created by third parties is as indicated
** elsewhere herein. All Rights Reserved.
-**
+**
** Additional Notice Provisions: The application programming interfaces
** established by SGI in conjunction with the Original Code are The
** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -45,56 +45,56 @@
** $Header$
*/
-/*
+/*
* Copyright (c) 2002-2004 LWJGL Project
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
+ * modification, are permitted provided that the following conditions are
* met:
- *
- * * Redistributions of source code must retain the above copyright
+ *
+ * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * * Neither the name of 'LWJGL' nor the names of
- * its contributors may be used to endorse or promote products derived
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -107,17 +107,18 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
package jogamp.opengl.gl2;
-import java.nio.*;
+import java.nio.DoubleBuffer;
+import java.nio.IntBuffer;
+
+import javax.media.opengl.GL2;
-import javax.media.opengl.*;
-import jogamp.opengl.*;
import com.jogamp.common.nio.Buffers;
/**
@@ -125,7 +126,7 @@ import com.jogamp.common.nio.Buffers;
* <p/>
* <p/>
* Created 11-jan-2004
- *
+ *
* @author Erik Duijs
* @author Kenneth Russell
*/
@@ -152,12 +153,7 @@ public class ProjectDouble {
private final double[] in = new double[4];
private final double[] out = new double[4];
- private final double[] forward = new double[3];
- private final double[] side = new double[3];
- private final double[] up = new double[3];
-
// Buffer-based implementation
- private DoubleBuffer locbuf;
private final DoubleBuffer matrixBuf;
private final DoubleBuffer tempMatrixBuf;
@@ -174,7 +170,7 @@ public class ProjectDouble {
// Slice up one big buffer because some NIO implementations
// allocate a huge amount of memory to back even the smallest of
// buffers.
- DoubleBuffer locbuf = Buffers.newDirectDoubleBuffer(128);
+ final DoubleBuffer locbuf = Buffers.newDirectDoubleBuffer(128);
int pos = 0;
int sz = 16;
matrixBuf = slice(locbuf, pos, sz);
@@ -194,14 +190,7 @@ public class ProjectDouble {
upBuf = slice(locbuf, pos, sz);
}
- public void destroy() {
- if(locbuf!=null) {
- locbuf.clear();
- locbuf=null;
- }
- }
-
- private static DoubleBuffer slice(DoubleBuffer buf, int pos, int len) {
+ private static DoubleBuffer slice(final DoubleBuffer buf, final int pos, final int len) {
buf.position(pos);
buf.limit(pos + len);
return buf.slice();
@@ -210,8 +199,8 @@ public class ProjectDouble {
/**
* Make matrix an identity matrix
*/
- private void __gluMakeIdentityd(DoubleBuffer m) {
- int oldPos = m.position();
+ private void __gluMakeIdentityd(final DoubleBuffer m) {
+ final int oldPos = m.position();
m.put(IDENTITY_MATRIX);
m.position(oldPos);
}
@@ -219,7 +208,7 @@ public class ProjectDouble {
/**
* Make matrix an identity matrix
*/
- private void __gluMakeIdentityd(double[] m) {
+ private void __gluMakeIdentityd(final double[] m) {
for (int i = 0; i < 16; i++) {
m[i] = IDENTITY_MATRIX[i];
}
@@ -227,12 +216,12 @@ public class ProjectDouble {
/**
* Method __gluMultMatrixVecd
- *
+ *
* @param matrix
* @param in
* @param out
*/
- private void __gluMultMatrixVecd(double[] matrix, int matrix_offset, double[] in, double[] out) {
+ private void __gluMultMatrixVecd(final double[] matrix, final int matrix_offset, final double[] in, final double[] out) {
for (int i = 0; i < 4; i++) {
out[i] =
in[0] * matrix[0*4+i+matrix_offset] +
@@ -244,15 +233,15 @@ public class ProjectDouble {
/**
* Method __gluMultMatrixVecd
- *
+ *
* @param matrix
* @param in
* @param out
*/
- private void __gluMultMatrixVecd(DoubleBuffer matrix, DoubleBuffer in, DoubleBuffer out) {
- int inPos = in.position();
- int outPos = out.position();
- int matrixPos = matrix.position();
+ private void __gluMultMatrixVecd(final DoubleBuffer matrix, final DoubleBuffer in, final DoubleBuffer out) {
+ final int inPos = in.position();
+ final int outPos = out.position();
+ final int matrixPos = matrix.position();
for (int i = 0; i < 4; i++) {
out.put(i + outPos,
in.get(0+inPos) * matrix.get(0*4+i+matrixPos) +
@@ -265,13 +254,13 @@ public class ProjectDouble {
/**
* @param src
* @param inverse
- *
+ *
* @return
*/
- private boolean __gluInvertMatrixd(double[] src, double[] inverse) {
+ private boolean __gluInvertMatrixd(final double[] src, final double[] inverse) {
int i, j, k, swap;
double t;
- double[][] temp = tempMatrix;
+ final double[][] temp = tempMatrix;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
@@ -335,17 +324,17 @@ public class ProjectDouble {
/**
* @param src
* @param inverse
- *
+ *
* @return
*/
- private boolean __gluInvertMatrixd(DoubleBuffer src, DoubleBuffer inverse) {
+ private boolean __gluInvertMatrixd(final DoubleBuffer src, final DoubleBuffer inverse) {
int i, j, k, swap;
double t;
- int srcPos = src.position();
- int invPos = inverse.position();
+ final int srcPos = src.position();
+ final int invPos = inverse.position();
- DoubleBuffer temp = tempMatrixBuf;
+ final DoubleBuffer temp = tempMatrixBuf;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
@@ -412,7 +401,7 @@ public class ProjectDouble {
* @param b
* @param r
*/
- private void __gluMultMatricesd(double[] a, int a_offset, double[] b, int b_offset, double[] r) {
+ private void __gluMultMatricesd(final double[] a, final int a_offset, final double[] b, final int b_offset, final double[] r) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
r[i*4+j] =
@@ -430,10 +419,10 @@ public class ProjectDouble {
* @param b
* @param r
*/
- private void __gluMultMatricesd(DoubleBuffer a, DoubleBuffer b, DoubleBuffer r) {
- int aPos = a.position();
- int bPos = b.position();
- int rPos = r.position();
+ private void __gluMultMatricesd(final DoubleBuffer a, final DoubleBuffer b, final DoubleBuffer r) {
+ final int aPos = a.position();
+ final int bPos = b.position();
+ final int rPos = r.position();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
@@ -451,31 +440,10 @@ public class ProjectDouble {
*
* @param v
*/
- private static void normalize(double[] v) {
- double r;
-
- r = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
- if ( r == 0.0 )
- return;
-
- r = 1.0 / r;
-
- v[0] *= r;
- v[1] *= r;
- v[2] *= r;
-
- return;
- }
-
- /**
- * Normalize vector
- *
- * @param v
- */
- private static void normalize(DoubleBuffer v) {
+ private static void normalize(final DoubleBuffer v) {
double r;
- int vPos = v.position();
+ final int vPos = v.position();
r = Math.sqrt(v.get(0+vPos) * v.get(0+vPos) +
v.get(1+vPos) * v.get(1+vPos) +
@@ -500,23 +468,10 @@ public class ProjectDouble {
* @param v2
* @param result
*/
- private static void cross(double[] v1, double[] v2, double[] result) {
- result[0] = v1[1] * v2[2] - v1[2] * v2[1];
- result[1] = v1[2] * v2[0] - v1[0] * v2[2];
- result[2] = v1[0] * v2[1] - v1[1] * v2[0];
- }
-
- /**
- * Calculate cross-product
- *
- * @param v1
- * @param v2
- * @param result
- */
- private static void cross(DoubleBuffer v1, DoubleBuffer v2, DoubleBuffer result) {
- int v1Pos = v1.position();
- int v2Pos = v2.position();
- int rPos = result.position();
+ private static void cross(final DoubleBuffer v1, final DoubleBuffer v2, final DoubleBuffer result) {
+ final int v1Pos = v1.position();
+ final int v2Pos = v2.position();
+ final int rPos = result.position();
result.put(0+rPos, v1.get(1+v1Pos) * v2.get(2+v2Pos) - v1.get(2+v1Pos) * v2.get(1+v2Pos));
result.put(1+rPos, v1.get(2+v1Pos) * v2.get(0+v2Pos) - v1.get(0+v1Pos) * v2.get(2+v2Pos));
@@ -525,27 +480,27 @@ public class ProjectDouble {
/**
* Method gluOrtho2D.
- *
+ *
* @param left
* @param right
* @param bottom
* @param top
*/
- public void gluOrtho2D(GL2 gl, double left, double right, double bottom, double top) {
+ public void gluOrtho2D(final GL2 gl, final double left, final double right, final double bottom, final double top) {
gl.glOrtho(left, right, bottom, top, -1, 1);
}
/**
* Method gluPerspective.
- *
+ *
* @param fovy
* @param aspect
* @param zNear
* @param zFar
*/
- public void gluPerspective(GL2 gl, double fovy, double aspect, double zNear, double zFar) {
+ public void gluPerspective(final GL2 gl, final double fovy, final double aspect, final double zNear, final double zFar) {
double sine, cotangent, deltaZ;
- double radians = fovy / 2 * Math.PI / 180;
+ final double radians = fovy / 2 * Math.PI / 180;
deltaZ = zFar - zNear;
sine = Math.sin(radians);
@@ -570,7 +525,7 @@ public class ProjectDouble {
/**
* Method gluLookAt
- *
+ *
* @param eyex
* @param eyey
* @param eyez
@@ -581,19 +536,19 @@ public class ProjectDouble {
* @param upy
* @param upz
*/
- public void gluLookAt(GL2 gl,
- double eyex,
- double eyey,
- double eyez,
- double centerx,
- double centery,
- double centerz,
- double upx,
- double upy,
- double upz) {
- DoubleBuffer forward = this.forwardBuf;
- DoubleBuffer side = this.sideBuf;
- DoubleBuffer up = this.upBuf;
+ public void gluLookAt(final GL2 gl,
+ final double eyex,
+ final double eyey,
+ final double eyez,
+ final double centerx,
+ final double centery,
+ final double centerz,
+ final double upx,
+ final double upy,
+ final double upz) {
+ final DoubleBuffer forward = this.forwardBuf;
+ final DoubleBuffer side = this.sideBuf;
+ final DoubleBuffer up = this.upBuf;
forward.put(0, centerx - eyex);
forward.put(1, centery - eyey);
@@ -631,7 +586,7 @@ public class ProjectDouble {
/**
* Method gluProject
- *
+ *
* @param objx
* @param objy
* @param objz
@@ -639,23 +594,23 @@ public class ProjectDouble {
* @param projMatrix
* @param viewport
* @param win_pos
- *
+ *
* @return
*/
- public boolean gluProject(double objx,
- double objy,
- double objz,
- double[] modelMatrix,
- int modelMatrix_offset,
- double[] projMatrix,
- int projMatrix_offset,
- int[] viewport,
- int viewport_offset,
- double[] win_pos,
- int win_pos_offset ) {
-
- double[] in = this.in;
- double[] out = this.out;
+ public boolean gluProject(final double objx,
+ final double objy,
+ final double objz,
+ final double[] modelMatrix,
+ final int modelMatrix_offset,
+ final double[] projMatrix,
+ final int projMatrix_offset,
+ final int[] viewport,
+ final int viewport_offset,
+ final double[] win_pos,
+ final int win_pos_offset ) {
+
+ final double[] in = this.in;
+ final double[] out = this.out;
in[0] = objx;
in[1] = objy;
@@ -685,7 +640,7 @@ public class ProjectDouble {
/**
* Method gluProject
- *
+ *
* @param objx
* @param objy
* @param objz
@@ -693,19 +648,19 @@ public class ProjectDouble {
* @param projMatrix
* @param viewport
* @param win_pos
- *
+ *
* @return
*/
- public boolean gluProject(double objx,
- double objy,
- double objz,
- DoubleBuffer modelMatrix,
- DoubleBuffer projMatrix,
- IntBuffer viewport,
- DoubleBuffer win_pos) {
+ public boolean gluProject(final double objx,
+ final double objy,
+ final double objz,
+ final DoubleBuffer modelMatrix,
+ final DoubleBuffer projMatrix,
+ final IntBuffer viewport,
+ final DoubleBuffer win_pos) {
- DoubleBuffer in = this.inBuf;
- DoubleBuffer out = this.outBuf;
+ final DoubleBuffer in = this.inBuf;
+ final DoubleBuffer out = this.outBuf;
in.put(0, objx);
in.put(1, objy);
@@ -726,8 +681,8 @@ public class ProjectDouble {
in.put(2, in.get(2) * in.get(3) + 0.5f);
// Map x,y to viewport
- int vPos = viewport.position();
- int wPos = win_pos.position();
+ final int vPos = viewport.position();
+ final int wPos = win_pos.position();
win_pos.put(0+wPos, in.get(0) * viewport.get(2+vPos) + viewport.get(0+vPos));
win_pos.put(1+wPos, in.get(1) * viewport.get(3+vPos) + viewport.get(1+vPos));
win_pos.put(2+wPos, in.get(2));
@@ -738,7 +693,7 @@ public class ProjectDouble {
/**
* Method gluUnproject
- *
+ *
* @param winx
* @param winy
* @param winz
@@ -746,22 +701,22 @@ public class ProjectDouble {
* @param projMatrix
* @param viewport
* @param obj_pos
- *
+ *
* @return
*/
- public boolean gluUnProject(double winx,
- double winy,
- double winz,
- double[] modelMatrix,
- int modelMatrix_offset,
- double[] projMatrix,
- int projMatrix_offset,
- int[] viewport,
- int viewport_offset,
- double[] obj_pos,
- int obj_pos_offset) {
- double[] in = this.in;
- double[] out = this.out;
+ public boolean gluUnProject(final double winx,
+ final double winy,
+ final double winz,
+ final double[] modelMatrix,
+ final int modelMatrix_offset,
+ final double[] projMatrix,
+ final int projMatrix_offset,
+ final int[] viewport,
+ final int viewport_offset,
+ final double[] obj_pos,
+ final int obj_pos_offset) {
+ final double[] in = this.in;
+ final double[] out = this.out;
__gluMultMatricesd(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix);
@@ -799,7 +754,7 @@ public class ProjectDouble {
/**
* Method gluUnproject
- *
+ *
* @param winx
* @param winy
* @param winz
@@ -807,18 +762,18 @@ public class ProjectDouble {
* @param projMatrix
* @param viewport
* @param obj_pos
- *
+ *
* @return
*/
- public boolean gluUnProject(double winx,
- double winy,
- double winz,
- DoubleBuffer modelMatrix,
- DoubleBuffer projMatrix,
- IntBuffer viewport,
- DoubleBuffer obj_pos) {
- DoubleBuffer in = this.inBuf;
- DoubleBuffer out = this.outBuf;
+ public boolean gluUnProject(final double winx,
+ final double winy,
+ final double winz,
+ final DoubleBuffer modelMatrix,
+ final DoubleBuffer projMatrix,
+ final IntBuffer viewport,
+ final DoubleBuffer obj_pos) {
+ final DoubleBuffer in = this.inBuf;
+ final DoubleBuffer out = this.outBuf;
__gluMultMatricesd(modelMatrix, projMatrix, matrixBuf);
@@ -831,8 +786,8 @@ public class ProjectDouble {
in.put(3, 1.0);
// Map x and y from window coordinates
- int vPos = viewport.position();
- int oPos = obj_pos.position();
+ final int vPos = viewport.position();
+ final int oPos = obj_pos.position();
in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos));
in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos));
@@ -858,7 +813,7 @@ public class ProjectDouble {
/**
* Method gluUnproject4
- *
+ *
* @param winx
* @param winy
* @param winz
@@ -869,25 +824,25 @@ public class ProjectDouble {
* @param near
* @param far
* @param obj_pos
- *
+ *
* @return
*/
- public boolean gluUnProject4(double winx,
- double winy,
- double winz,
- double clipw,
- double[] modelMatrix,
- int modelMatrix_offset,
- double[] projMatrix,
- int projMatrix_offset,
- int[] viewport,
- int viewport_offset,
- double near,
- double far,
- double[] obj_pos,
- int obj_pos_offset ) {
- double[] in = this.in;
- double[] out = this.out;
+ public boolean gluUnProject4(final double winx,
+ final double winy,
+ final double winz,
+ final double clipw,
+ final double[] modelMatrix,
+ final int modelMatrix_offset,
+ final double[] projMatrix,
+ final int projMatrix_offset,
+ final int[] viewport,
+ final int viewport_offset,
+ final double near,
+ final double far,
+ final double[] obj_pos,
+ final int obj_pos_offset ) {
+ final double[] in = this.in;
+ final double[] out = this.out;
__gluMultMatricesd(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix);
@@ -923,7 +878,7 @@ public class ProjectDouble {
/**
* Method gluUnproject4
- *
+ *
* @param winx
* @param winy
* @param winz
@@ -934,21 +889,21 @@ public class ProjectDouble {
* @param near
* @param far
* @param obj_pos
- *
+ *
* @return
*/
- public boolean gluUnProject4(double winx,
- double winy,
- double winz,
- double clipw,
- DoubleBuffer modelMatrix,
- DoubleBuffer projMatrix,
- IntBuffer viewport,
- double near,
- double far,
- DoubleBuffer obj_pos) {
- DoubleBuffer in = this.inBuf;
- DoubleBuffer out = this.outBuf;
+ public boolean gluUnProject4(final double winx,
+ final double winy,
+ final double winz,
+ final double clipw,
+ final DoubleBuffer modelMatrix,
+ final DoubleBuffer projMatrix,
+ final IntBuffer viewport,
+ final double near,
+ final double far,
+ final DoubleBuffer obj_pos) {
+ final DoubleBuffer in = this.inBuf;
+ final DoubleBuffer out = this.outBuf;
__gluMultMatricesd(modelMatrix, projMatrix, matrixBuf);
@@ -961,7 +916,7 @@ public class ProjectDouble {
in.put(3, clipw);
// Map x and y from window coordinates
- int vPos = viewport.position();
+ final int vPos = viewport.position();
in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos));
in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos));
in.put(2, (in.get(2) - near) / (far - near));
@@ -976,7 +931,7 @@ public class ProjectDouble {
if (out.get(3) == 0.0)
return false;
- int oPos = obj_pos.position();
+ final int oPos = obj_pos.position();
obj_pos.put(0+oPos, out.get(0));
obj_pos.put(1+oPos, out.get(1));
obj_pos.put(2+oPos, out.get(2));
@@ -987,25 +942,25 @@ public class ProjectDouble {
/**
* Method gluPickMatrix
- *
+ *
* @param x
* @param y
* @param deltaX
* @param deltaY
* @param viewport
*/
- public void gluPickMatrix(GL2 gl,
- double x,
- double y,
- double deltaX,
- double deltaY,
- IntBuffer viewport) {
+ public void gluPickMatrix(final GL2 gl,
+ final double x,
+ final double y,
+ final double deltaX,
+ final double deltaY,
+ final IntBuffer viewport) {
if (deltaX <= 0 || deltaY <= 0) {
return;
}
/* Translate and scale the picked region to the entire window */
- int vPos = viewport.position();
+ final int vPos = viewport.position();
gl.glTranslated((viewport.get(2+vPos) - 2 * (x - viewport.get(0+vPos))) / deltaX,
(viewport.get(3+vPos) - 2 * (y - viewport.get(1+vPos))) / deltaY,
0);
@@ -1014,7 +969,7 @@ public class ProjectDouble {
/**
* Method gluPickMatrix
- *
+ *
* @param x
* @param y
* @param deltaX
@@ -1022,13 +977,13 @@ public class ProjectDouble {
* @param viewport
* @param viewport_offset
*/
- public void gluPickMatrix(GL2 gl,
- double x,
- double y,
- double deltaX,
- double deltaY,
- int[] viewport,
- int viewport_offset) {
+ public void gluPickMatrix(final GL2 gl,
+ final double x,
+ final double y,
+ final double deltaX,
+ final double deltaY,
+ final int[] viewport,
+ final int viewport_offset) {
if (deltaX <= 0 || deltaY <= 0) {
return;
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java b/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java
index 3f8a76535..c91a045ae 100644
--- a/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java
+++ b/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java
@@ -6,15 +6,15 @@
** this file except in compliance with the License. You may obtain a copy
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
-**
+**
** http://oss.sgi.com/projects/FreeB
-**
+**
** Note that, as provided in the License, the Software is distributed on an
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
-**
+**
** NOTE: The Original Code (as defined below) has been licensed to Sun
** Microsystems, Inc. ("Sun") under the SGI Free Software License B
** (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
** Copyright in any portions created by third parties is as indicated
** elsewhere herein. All Rights Reserved.
-**
+**
** Additional Notice Provisions: The application programming interfaces
** established by SGI in conjunction with the Original Code are The
** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -45,56 +45,56 @@
** $Header$
*/
-/*
+/*
* Copyright (c) 2002-2004 LWJGL Project
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
+ * modification, are permitted provided that the following conditions are
* met:
- *
- * * Redistributions of source code must retain the above copyright
+ *
+ * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * * Neither the name of 'LWJGL' nor the names of
- * its contributors may be used to endorse or promote products derived
+ * * Neither the name of 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -107,7 +107,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -115,22 +115,25 @@
package jogamp.opengl.glu;
-import javax.media.opengl.*;
-import javax.media.opengl.glu.*;
+import javax.media.opengl.GL;
+import javax.media.opengl.glu.GLU;
+import javax.media.opengl.glu.GLUquadric;
+
+import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.util.ImmModeSink;
-import java.nio.*;
+import com.jogamp.opengl.util.glsl.ShaderState;
/**
* GLUquadricImpl.java
- *
- *
+ *
+ *
* Created 22-dec-2003 (originally Quadric.java)
* @author Erik Duijs
* @author Kenneth Russell, Sven Gothel
*/
public class GLUquadricImpl implements GLUquadric {
- private boolean useGLSL;
+ private final boolean useGLSL;
private int drawStyle;
private int orientation;
private boolean textureFlag;
@@ -139,26 +142,31 @@ public class GLUquadricImpl implements GLUquadric {
private boolean immModeSinkImmediate;
public int normalType;
public GL gl;
+ public ShaderState shaderState;
+ public int shaderProgram;
public static final boolean USE_NORM = true;
public static final boolean USE_TEXT = false;
private ImmModeSink immModeSink=null;
- public GLUquadricImpl(GL gl, boolean useGLSL) {
+ public GLUquadricImpl(final GL gl, final boolean useGLSL, final ShaderState st, final int shaderProgram) {
this.gl=gl;
this.useGLSL = useGLSL;
- drawStyle = GLU.GLU_FILL;
- orientation = GLU.GLU_OUTSIDE;
- textureFlag = false;
- normals = GLU.GLU_SMOOTH;
- normalType = gl.isGLES1()?GL.GL_BYTE:GL.GL_FLOAT;
- immModeSinkImmediate=true;
- immModeSinkEnabled=!gl.isGL2();
+ this.drawStyle = GLU.GLU_FILL;
+ this.orientation = GLU.GLU_OUTSIDE;
+ this.textureFlag = false;
+ this.normals = GLU.GLU_SMOOTH;
+ this.normalType = gl.isGLES1()?GL.GL_BYTE:GL.GL_FLOAT;
+ this.immModeSinkImmediate=true;
+ this.immModeSinkEnabled=!gl.isGL2();
+ this.shaderState = st;
+ this.shaderProgram = shaderProgram;
replaceImmModeSink();
}
- public void enableImmModeSink(boolean val) {
+ @Override
+ public void enableImmModeSink(final boolean val) {
if(gl.isGL2()) {
immModeSinkEnabled=val;
} else {
@@ -169,11 +177,13 @@ public class GLUquadricImpl implements GLUquadric {
}
}
+ @Override
public boolean isImmModeSinkEnabled() {
return immModeSinkEnabled;
}
- public void setImmMode(boolean val) {
+ @Override
+ public void setImmMode(final boolean val) {
if(immModeSinkEnabled) {
immModeSinkImmediate=val;
} else {
@@ -181,38 +191,52 @@ public class GLUquadricImpl implements GLUquadric {
}
}
+ @Override
public boolean getImmMode() {
return immModeSinkImmediate;
}
+ @Override
public ImmModeSink replaceImmModeSink() {
if(!immModeSinkEnabled) return null;
- ImmModeSink res = immModeSink;
+ final ImmModeSink res = immModeSink;
if(useGLSL) {
- immModeSink = ImmModeSink.createGLSL (gl, GL.GL_STATIC_DRAW, 32,
- 3, GL.GL_FLOAT, // vertex
- 0, GL.GL_FLOAT, // color
- USE_NORM?3:0, normalType,// normal
- USE_TEXT?2:0, GL.GL_FLOAT); // texture
+ if(null != shaderState) {
+ immModeSink = ImmModeSink.createGLSL (32,
+ 3, GL.GL_FLOAT, // vertex
+ 0, GL.GL_FLOAT, // color
+ USE_NORM?3:0, normalType, // normal
+ USE_TEXT?2:0, GL.GL_FLOAT, // texCoords
+ GL.GL_STATIC_DRAW, shaderState);
+ } else {
+ immModeSink = ImmModeSink.createGLSL (32,
+ 3, GL.GL_FLOAT, // vertex
+ 0, GL.GL_FLOAT, // color
+ USE_NORM?3:0, normalType, // normal
+ USE_TEXT?2:0, GL.GL_FLOAT, // texCoords
+ GL.GL_STATIC_DRAW, shaderProgram);
+ }
} else {
- immModeSink = ImmModeSink.createFixed(gl, GL.GL_STATIC_DRAW, 32,
- 3, GL.GL_FLOAT, // vertex
- 0, GL.GL_FLOAT, // color
- USE_NORM?3:0, normalType,// normal
- USE_TEXT?2:0, GL.GL_FLOAT); // texture
+ immModeSink = ImmModeSink.createFixed(32,
+ 3, GL.GL_FLOAT, // vertex
+ 0, GL.GL_FLOAT, // color
+ USE_NORM?3:0, normalType, // normal
+ USE_TEXT?2:0, GL.GL_FLOAT, // texCoords
+ GL.GL_STATIC_DRAW);
}
return res;
}
- public void resetImmModeSink(GL gl) {
+ @Override
+ public void resetImmModeSink(final GL gl) {
if(immModeSinkEnabled) {
immModeSink.reset(gl);
}
}
/**
- * specifies the draw style for quadrics.
+ * specifies the draw style for quadrics.
*
* The legal values are as follows:
*
@@ -226,10 +250,10 @@ public class GLUquadricImpl implements GLUquadric {
* separating coplanar faces will not be drawn.
*
* GLU.POINT: Quadrics are rendered as a set of points.
- *
+ *
* @param drawStyle The drawStyle to set
*/
- public void setDrawStyle(int drawStyle) {
+ public void setDrawStyle(final int drawStyle) {
this.drawStyle = drawStyle;
}
@@ -243,10 +267,10 @@ public class GLUquadricImpl implements GLUquadric {
*
* GLU.SMOOTH: One normal is generated for every vertex of a quadric. This
* is the default.
- *
+ *
* @param normals The normals to set
*/
- public void setNormals(int normals) {
+ public void setNormals(final int normals) {
this.normals = normals;
}
@@ -260,10 +284,10 @@ public class GLUquadricImpl implements GLUquadric {
*
* Note that the interpretation of outward and inward depends on the quadric
* being drawn.
- *
+ *
* @param orientation The orientation to set
*/
- public void setOrientation(int orientation) {
+ public void setOrientation(final int orientation) {
this.orientation = orientation;
}
@@ -275,10 +299,10 @@ public class GLUquadricImpl implements GLUquadric {
*
* The manner in which texture coordinates are generated depends upon the
* specific quadric rendered.
- *
+ *
* @param textureFlag The textureFlag to set
*/
- public void setTextureFlag(boolean textureFlag) {
+ public void setTextureFlag(final boolean textureFlag) {
this.textureFlag = textureFlag;
}
@@ -340,7 +364,7 @@ public class GLUquadricImpl implements GLUquadric {
* @param slices Specifies the number of subdivisions around the z axis.
* @param stacks Specifies the number of subdivisions along the z axis.
*/
- public void drawCylinder(GL gl, float baseRadius, float topRadius, float height, int slices, int stacks) {
+ public void drawCylinder(final GL gl, final float baseRadius, final float topRadius, final float height, final int slices, final int stacks) {
float da, r, dr, dz;
float x, y, z, nz, nsign;
@@ -352,7 +376,7 @@ public class GLUquadricImpl implements GLUquadric {
nsign = 1.0f;
}
- da = 2.0f * PI / slices;
+ da = PI_2 / slices;
dr = (topRadius - baseRadius) / stacks;
dz = height / stacks;
nz = (baseRadius - topRadius) / height;
@@ -423,14 +447,14 @@ public class GLUquadricImpl implements GLUquadric {
}
glEnd(gl);
} else if (drawStyle == GLU.GLU_FILL) {
- float ds = 1.0f / slices;
- float dt = 1.0f / stacks;
+ final float ds = 1.0f / slices;
+ final float dt = 1.0f / stacks;
float t = 0.0f;
z = 0.0f;
r = baseRadius;
for (j = 0; j < stacks; j++) {
float s = 0.0f;
- glBegin(gl, immModeSink.GL_QUAD_STRIP);
+ glBegin(gl, ImmModeSink.GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
if (i == slices) {
x = sin(0.0f);
@@ -439,21 +463,21 @@ public class GLUquadricImpl implements GLUquadric {
x = sin((i * da));
y = cos((i * da));
}
- if (nsign == 1.0f) {
+ // if (nsign == 1.0f) {
normal3f(gl, (x * nsign), (y * nsign), (nz * nsign));
TXTR_COORD(gl, s, t);
glVertex3f(gl, (x * r), (y * r), z);
normal3f(gl, (x * nsign), (y * nsign), (nz * nsign));
TXTR_COORD(gl, s, t + dt);
glVertex3f(gl, (x * (r + dr)), (y * (r + dr)), (z + dz));
- } else {
+ /* } else {
normal3f(gl, x * nsign, y * nsign, nz * nsign);
TXTR_COORD(gl, s, t);
glVertex3f(gl, (x * r), (y * r), z);
normal3f(gl, x * nsign, y * nsign, nz * nsign);
TXTR_COORD(gl, s, t + dt);
glVertex3f(gl, (x * (r + dr)), (y * (r + dr)), (z + dz));
- }
+ } */
s += ds;
} // for slices
glEnd(gl);
@@ -482,7 +506,7 @@ public class GLUquadricImpl implements GLUquadric {
* (1, 0.5), at (0, r, 0) it is (0.5, 1), at (-r, 0, 0) it is (0, 0.5), and at
* (0, -r, 0) it is (0.5, 0).
*/
- public void drawDisk(GL gl, float innerRadius, float outerRadius, int slices, int loops)
+ public void drawDisk(final GL gl, final float innerRadius, final float outerRadius, final int slices, final int loops)
{
float da, dr;
@@ -495,10 +519,10 @@ public class GLUquadricImpl implements GLUquadric {
glNormal3f(gl, 0.0f, 0.0f, -1.0f);
}
}
-
- da = 2.0f * PI / slices;
+
+ da = PI_2 / slices;
dr = (outerRadius - innerRadius) / loops;
-
+
switch (drawStyle) {
case GLU.GLU_FILL:
{
@@ -506,15 +530,15 @@ public class GLUquadricImpl implements GLUquadric {
* x, y in [-outerRadius, +outerRadius]; s, t in [0, 1]
* (linear mapping)
*/
- float dtc = 2.0f * outerRadius;
+ final float dtc = 2.0f * outerRadius;
float sa, ca;
float r1 = innerRadius;
int l;
for (l = 0; l < loops; l++) {
- float r2 = r1 + dr;
+ final float r2 = r1 + dr;
if (orientation == GLU.GLU_OUTSIDE) {
int s;
- glBegin(gl, immModeSink.GL_QUAD_STRIP);
+ glBegin(gl, ImmModeSink.GL_QUAD_STRIP);
for (s = 0; s <= slices; s++) {
float a;
if (s == slices)
@@ -532,7 +556,7 @@ public class GLUquadricImpl implements GLUquadric {
}
else {
int s;
- glBegin(gl, immModeSink.GL_QUAD_STRIP);
+ glBegin(gl, ImmModeSink.GL_QUAD_STRIP);
for (s = slices; s >= 0; s--) {
float a;
if (s == slices)
@@ -557,22 +581,22 @@ public class GLUquadricImpl implements GLUquadric {
int l, s;
/* draw loops */
for (l = 0; l <= loops; l++) {
- float r = innerRadius + l * dr;
+ final float r = innerRadius + l * dr;
glBegin(gl, GL.GL_LINE_LOOP);
for (s = 0; s < slices; s++) {
- float a = s * da;
+ final float a = s * da;
glVertex2f(gl, r * sin(a), r * cos(a));
}
glEnd(gl);
}
/* draw spokes */
for (s = 0; s < slices; s++) {
- float a = s * da;
- float x = sin(a);
- float y = cos(a);
+ final float a = s * da;
+ final float x = sin(a);
+ final float y = cos(a);
glBegin(gl, GL.GL_LINE_STRIP);
for (l = 0; l <= loops; l++) {
- float r = innerRadius + l * dr;
+ final float r = innerRadius + l * dr;
glVertex2f(gl, r * x, r * y);
}
glEnd(gl);
@@ -584,12 +608,12 @@ public class GLUquadricImpl implements GLUquadric {
int s;
glBegin(gl, GL.GL_POINTS);
for (s = 0; s < slices; s++) {
- float a = s * da;
- float x = sin(a);
- float y = cos(a);
+ final float a = s * da;
+ final float x = sin(a);
+ final float y = cos(a);
int l;
for (l = 0; l <= loops; l++) {
- float r = innerRadius * l * dr;
+ final float r = innerRadius * l * dr;
glVertex2f(gl, r * x, r * y);
}
}
@@ -601,9 +625,9 @@ public class GLUquadricImpl implements GLUquadric {
if (innerRadius != 0.0) {
float a;
glBegin(gl, GL.GL_LINE_LOOP);
- for (a = 0.0f; a < 2.0 * PI; a += da) {
- float x = innerRadius * sin(a);
- float y = innerRadius * cos(a);
+ for (a = 0.0f; a < PI_2; a += da) {
+ final float x = innerRadius * sin(a);
+ final float y = innerRadius * cos(a);
glVertex2f(gl, x, y);
}
glEnd(gl);
@@ -611,9 +635,9 @@ public class GLUquadricImpl implements GLUquadric {
{
float a;
glBegin(gl, GL.GL_LINE_LOOP);
- for (a = 0; a < 2.0f * PI; a += da) {
- float x = outerRadius * sin(a);
- float y = outerRadius * cos(a);
+ for (a = 0; a < PI_2; a += da) {
+ final float x = outerRadius * sin(a);
+ final float y = outerRadius * cos(a);
glVertex2f(gl, x, y);
}
glEnd(gl);
@@ -631,35 +655,34 @@ public class GLUquadricImpl implements GLUquadric {
* through startAngle + sweepAngle is included (where 0 degrees is along
* the +y axis, 90 degrees along the +x axis, 180 along the -y axis, and
* 270 along the -x axis).
- *
+ *
* The partial disk has a radius of outerRadius, and contains a concentric
* circular hole with a radius of innerRadius. If innerRadius is zero, then
* no hole is generated. The partial disk is subdivided around the z axis
* into slices (like pizza slices), and also about the z axis into rings
* (as specified by slices and loops, respectively).
- *
+ *
* With respect to orientation, the +z side of the partial disk is
* considered to be outside (see gluQuadricOrientation). This means that if
* the orientation is set to GLU.GLU_OUTSIDE, then any normals generated point
* along the +z axis. Otherwise, they point along the -z axis.
- *
+ *
* If texturing is turned on (with gluQuadricTexture), texture coordinates
* are generated linearly such that where r=outerRadius, the value at (r, 0, 0)
* is (1, 0.5), at (0, r, 0) it is (0.5, 1), at (-r, 0, 0) it is (0, 0.5),
* and at (0, -r, 0) it is (0.5, 0).
*/
- public void drawPartialDisk(GL gl,
- float innerRadius,
- float outerRadius,
+ public void drawPartialDisk(final GL gl,
+ final float innerRadius,
+ final float outerRadius,
int slices,
- int loops,
+ final int loops,
float startAngle,
float sweepAngle) {
- int i, j, max;
- float[] sinCache = new float[CACHE_SIZE];
- float[] cosCache = new float[CACHE_SIZE];
+ int i, j;
+ final float[] sinCache = new float[CACHE_SIZE];
+ final float[] cosCache = new float[CACHE_SIZE];
float angle;
- float x, y;
float sintemp, costemp;
float deltaRadius;
float radiusLow, radiusHigh;
@@ -770,7 +793,7 @@ public class GLUquadricImpl implements GLUquadric {
texHigh = radiusHigh / outerRadius / 2;
}
- glBegin(gl, immModeSink.GL_QUAD_STRIP);
+ glBegin(gl, ImmModeSink.GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
if (orientation == GLU.GLU_OUTSIDE) {
if (textureFlag) {
@@ -930,7 +953,7 @@ public class GLUquadricImpl implements GLUquadric {
* 0.0 at the +y axis, to 0.25 at the +x axis, to 0.5 at the -y axis, to 0.75
* at the -x axis, and back to 1.0 at the +y axis.
*/
- public void drawSphere(GL gl, float radius, int slices, int stacks) {
+ public void drawSphere(final GL gl, final float radius, final int slices, final int stacks) {
// TODO
float rho, drho, theta, dtheta;
@@ -949,7 +972,7 @@ public class GLUquadricImpl implements GLUquadric {
}
drho = PI / stacks;
- dtheta = 2.0f * PI / slices;
+ dtheta = PI_2 / slices;
if (drawStyle == GLU.GLU_FILL) {
if (!textureFlag) {
@@ -984,7 +1007,7 @@ public class GLUquadricImpl implements GLUquadric {
// draw intermediate stacks as quad strips
for (i = imin; i < imax; i++) {
rho = i * drho;
- glBegin(gl, immModeSink.GL_QUAD_STRIP);
+ glBegin(gl, ImmModeSink.GL_QUAD_STRIP);
s = 0.0f;
for (j = 0; j <= slices; j++) {
theta = (j == slices) ? 0.0f : j * dtheta;
@@ -1096,10 +1119,11 @@ public class GLUquadricImpl implements GLUquadric {
// Internals only below this point
//
- private static final float PI = (float)Math.PI;
+ private static final float PI = FloatUtil.PI;
+ private static final float PI_2 = 2f * PI;
private static final int CACHE_SIZE = 240;
- private final void glBegin(GL gl, int mode) {
+ private final void glBegin(final GL gl, final int mode) {
if(immModeSinkEnabled) {
immModeSink.glBegin(mode);
} else {
@@ -1107,7 +1131,7 @@ public class GLUquadricImpl implements GLUquadric {
}
}
- private final void glEnd(GL gl) {
+ private final void glEnd(final GL gl) {
if(immModeSinkEnabled) {
immModeSink.glEnd(gl, immModeSinkImmediate);
} else {
@@ -1115,7 +1139,7 @@ public class GLUquadricImpl implements GLUquadric {
}
}
- private final void glVertex2f(GL gl, float x, float y) {
+ private final void glVertex2f(final GL gl, final float x, final float y) {
if(immModeSinkEnabled) {
immModeSink.glVertex2f(x, y);
} else {
@@ -1123,7 +1147,7 @@ public class GLUquadricImpl implements GLUquadric {
}
}
- private final void glVertex3f(GL gl, float x, float y, float z) {
+ private final void glVertex3f(final GL gl, final float x, final float y, final float z) {
if(immModeSinkEnabled) {
immModeSink.glVertex3f(x, y, z);
} else {
@@ -1131,10 +1155,10 @@ public class GLUquadricImpl implements GLUquadric {
}
}
- private final void glNormal3f_s(GL gl, float x, float y, float z) {
- short a=(short)(x*0xFFFF);
- short b=(short)(y*0xFFFF);
- short c=(short)(z*0xFFFF);
+ private final void glNormal3f_s(final GL gl, final float x, final float y, final float z) {
+ final short a=(short)(x*0xFFFF);
+ final short b=(short)(y*0xFFFF);
+ final short c=(short)(z*0xFFFF);
if(immModeSinkEnabled) {
immModeSink.glNormal3s(a, b, c);
} else {
@@ -1142,10 +1166,10 @@ public class GLUquadricImpl implements GLUquadric {
}
}
- private final void glNormal3f_b(GL gl, float x, float y, float z) {
- byte a=(byte)(x*0xFF);
- byte b=(byte)(y*0xFF);
- byte c=(byte)(z*0xFF);
+ private final void glNormal3f_b(final GL gl, final float x, final float y, final float z) {
+ final byte a=(byte)(x*0xFF);
+ final byte b=(byte)(y*0xFF);
+ final byte c=(byte)(z*0xFF);
if(immModeSinkEnabled) {
immModeSink.glNormal3b(a, b, c);
} else {
@@ -1153,7 +1177,7 @@ public class GLUquadricImpl implements GLUquadric {
}
}
- private final void glNormal3f(GL gl, float x, float y, float z) {
+ private final void glNormal3f(final GL gl, final float x, final float y, final float z) {
switch(normalType) {
case GL.GL_FLOAT:
if(immModeSinkEnabled) {
@@ -1171,7 +1195,7 @@ public class GLUquadricImpl implements GLUquadric {
}
}
- private final void glTexCoord2f(GL gl, float x, float y) {
+ private final void glTexCoord2f(final GL gl, final float x, final float y) {
if(immModeSinkEnabled) {
immModeSink.glTexCoord2f(x, y);
} else {
@@ -1186,9 +1210,9 @@ public class GLUquadricImpl implements GLUquadric {
* @param y
* @param z
*/
- private void normal3f(GL gl, float x, float y, float z) {
+ private void normal3f(final GL gl, float x, float y, float z) {
float mag;
-
+
mag = (float)Math.sqrt(x * x + y * y + z * z);
if (mag > 0.00001F) {
x /= mag;
@@ -1198,15 +1222,15 @@ public class GLUquadricImpl implements GLUquadric {
glNormal3f(gl, x, y, z);
}
- private final void TXTR_COORD(GL gl, float x, float y) {
+ private final void TXTR_COORD(final GL gl, final float x, final float y) {
if (textureFlag) glTexCoord2f(gl, x,y);
}
- private float sin(float r) {
+ private float sin(final float r) {
return (float)Math.sin(r);
}
- private float cos(float r) {
+ private float cos(final float r) {
return (float)Math.cos(r);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/Glue.java b/src/jogl/classes/jogamp/opengl/glu/Glue.java
index 636d17f29..fc85b137f 100644
--- a/src/jogl/classes/jogamp/opengl/glu/Glue.java
+++ b/src/jogl/classes/jogamp/opengl/glu/Glue.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -89,15 +89,15 @@ public class Glue {
"null control point reference",
"duplicate point on piecewise linear trimming curve"
} ;
-
+
/** Creates a new instance of Glue */
public Glue() {
}
-
- public static String __gluNURBSErrorString( int errno ) {
+
+ public static String __gluNURBSErrorString( final int errno ) {
return( __gluNurbsErrors[ errno ] );
}
-
+
private static String[] __gluTessErrors = {
" ",
"gluTessBeginPolygon() must precede a gluTessEndPolygon",
@@ -107,8 +107,8 @@ public class Glue {
"a coordinate is too large",
"need combine callback"
};
-
- public static String __gluTessErrorString( int errno ) {
+
+ public static String __gluTessErrorString( final int errno ) {
return( __gluTessErrors[ errno ] );
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/error/Error.java b/src/jogl/classes/jogamp/opengl/glu/error/Error.java
index 2f49db9a4..235c59717 100644
--- a/src/jogl/classes/jogamp/opengl/glu/error/Error.java
+++ b/src/jogl/classes/jogamp/opengl/glu/error/Error.java
@@ -6,9 +6,9 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
@@ -24,13 +24,13 @@
* except that Section 2.2 and 11 are omitted. Any differences between
* the Alternative License and the SGI License are offered solely by Sun
* and not by SGI.
- *
+ *
* Original Code. The Original Code is: OpenGL Sample Implementation,
* Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -53,7 +53,7 @@ import jogamp.opengl.glu.Glue;
* @author Administrator
*/
public class Error {
-
+
private static String[] glErrorStrings = {
"invalid enumerant",
"invalid value",
@@ -63,7 +63,7 @@ public class Error {
"out of memory",
"invalid framebuffer operation"
};
-
+
private static String[] gluErrorStrings = {
"invalid enumerant",
"invalid value",
@@ -71,12 +71,12 @@ public class Error {
"",
"invalid operation"
};
-
+
/** Creates a new instance of Error */
public Error() {
}
-
- public static String gluErrorString( int errorCode ) {
+
+ public static String gluErrorString( final int errorCode ) {
if( errorCode == 0 ) {
return( "no error" );
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2CurveEvaluator.java b/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2CurveEvaluator.java
index 2ef4468e5..96da49a80 100644
--- a/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2CurveEvaluator.java
+++ b/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2CurveEvaluator.java
@@ -1,42 +1,9 @@
package jogamp.opengl.glu.gl2.nurbs;
import jogamp.opengl.glu.nurbs.*;
-/*
- ** License Applicability. Except to the extent portions of this file are
- ** made subject to an alternative license as permitted in the SGI Free
- ** Software License B, Version 2.0 (the "License"), the contents of this
- ** file are subject only to the provisions of the License. You may not use
- ** this file except in compliance with the License. You may obtain a copy
- ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
- ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- **
- ** http://oss.sgi.com/projects/FreeB
- **
- ** Note that, as provided in the License, the Software is distributed on an
- ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
- ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
- ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
- ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- **
- ** Original Code. The Original Code is: OpenGL Sample Implementation,
- ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
- ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
- ** Copyright in any portions created by third parties is as indicated
- ** elsewhere herein. All Rights Reserved.
- **
- ** Additional Notice Provisions: The application programming interfaces
- ** established by SGI in conjunction with the Original Code are The
- ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
- ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
- ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
- ** Window System(R) (Version 1.3), released October 19, 1998. This software
- ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
- ** published by SGI, but has not been independently verified as being
- ** compliant with the OpenGL(R) version 1.2.1 Specification.
- */
-
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
+import javax.media.opengl.GL2GL3;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.gl2.GLUgl2;
@@ -48,14 +15,14 @@ import javax.media.opengl.glu.gl2.GLUgl2;
class GL2CurveEvaluator implements CurveEvaluator {
/**
- * Output triangles (for callback) or render curve
+ * Output triangles (for callback) or render curve
*/
private boolean output_triangles;
/**
* OpenGL object
*/
- private GL2 gl;
+ private final GL2 gl;
/**
* Not used
@@ -92,6 +59,7 @@ class GL2CurveEvaluator implements CurveEvaluator {
/**
* Pushes eval bit
*/
+ @Override
public void bgnmap1f() {
// DONE
if (output_triangles) {
@@ -108,6 +76,7 @@ class GL2CurveEvaluator implements CurveEvaluator {
/**
* Pops all OpenGL attributes
*/
+ @Override
public void endmap1f() {
// DONE
if (output_triangles) {
@@ -127,8 +96,9 @@ class GL2CurveEvaluator implements CurveEvaluator {
* @param order curve order
* @param ps control points
*/
- public void map1f(int type, float ulo, float uhi, int stride, int order,
- CArrayOfFloats ps) {
+ @Override
+ public void map1f(final int type, final float ulo, final float uhi, final int stride, final int order,
+ final CArrayOfFloats ps) {
if (output_triangles) {
// TODO code for callback (output_triangles probably indicates callback)
// System.out.println("TODO curveevaluator.map1f-output_triangles");
@@ -153,7 +123,8 @@ class GL2CurveEvaluator implements CurveEvaluator {
* Calls opengl enable
* @param type what to enable
*/
- public void enable(int type) {
+ @Override
+ public void enable(final int type) {
// DONE
gl.glEnable(type);
}
@@ -164,7 +135,8 @@ class GL2CurveEvaluator implements CurveEvaluator {
* @param u1 low u
* @param u2 high u
*/
- public void mapgrid1f(int nu, float u1, float u2) {
+ @Override
+ public void mapgrid1f(final int nu, final float u1, final float u2) {
if (output_triangles) {
// System.out.println("TODO curveevaluator.mapgrid1f");
} else
@@ -179,7 +151,8 @@ class GL2CurveEvaluator implements CurveEvaluator {
* @param from lowest param
* @param to highest param
*/
- public void mapmesh1f(int style, int from, int to) {
+ @Override
+ public void mapmesh1f(final int style, final int from, final int to) {
/* //DEBUG drawing control points
this.poradi++;
if (poradi % 2 == 0)
@@ -194,10 +167,10 @@ class GL2CurveEvaluator implements CurveEvaluator {
switch (style) {
case Backend.N_MESHFILL:
case Backend.N_MESHLINE:
- gl.glEvalMesh1(GL2.GL_LINE, from, to);
+ gl.glEvalMesh1(GL2GL3.GL_LINE, from, to);
break;
case Backend.N_MESHPOINT:
- gl.glEvalMesh1(GL2.GL_POINT, from, to);
+ gl.glEvalMesh1(GL2GL3.GL_POINT, from, to);
break;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2SurfaceEvaluator.java b/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2SurfaceEvaluator.java
index 155c4f9a9..e5cb715ab 100644
--- a/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2SurfaceEvaluator.java
+++ b/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2SurfaceEvaluator.java
@@ -1,42 +1,9 @@
package jogamp.opengl.glu.gl2.nurbs;
import jogamp.opengl.glu.nurbs.*;
-/*
- ** License Applicability. Except to the extent portions of this file are
- ** made subject to an alternative license as permitted in the SGI Free
- ** Software License B, Version 2.0 (the "License"), the contents of this
- ** file are subject only to the provisions of the License. You may not use
- ** this file except in compliance with the License. You may obtain a copy
- ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
- ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- **
- ** http://oss.sgi.com/projects/FreeB
- **
- ** Note that, as provided in the License, the Software is distributed on an
- ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
- ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
- ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
- ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- **
- ** Original Code. The Original Code is: OpenGL Sample Implementation,
- ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
- ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
- ** Copyright in any portions created by third parties is as indicated
- ** elsewhere herein. All Rights Reserved.
- **
- ** Additional Notice Provisions: The application programming interfaces
- ** established by SGI in conjunction with the Original Code are The
- ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
- ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
- ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
- ** Window System(R) (Version 1.3), released October 19, 1998. This software
- ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
- ** published by SGI, but has not been independently verified as being
- ** compliant with the OpenGL(R) version 1.2.1 Specification.
- */
-
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
+import javax.media.opengl.GL2GL3;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.gl2.GLUgl2;
@@ -50,7 +17,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
/**
* JOGL OpenGL object
*/
- private GL2 gl;
+ private final GL2 gl;
/**
* Output triangles (callback)
@@ -72,6 +39,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
/**
* Pushes eval bit
*/
+ @Override
public void bgnmap2f() {
if (output_triangles) {
@@ -88,18 +56,19 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* Sets glPolygonMode
* @param style polygon mode (N_MESHFILL/N_MESHLINE/N_MESHPOINT)
*/
- public void polymode(int style) {
+ @Override
+ public void polymode(final int style) {
if (!output_triangles) {
switch (style) {
default:
case NurbsConsts.N_MESHFILL:
- gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL);
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
break;
case NurbsConsts.N_MESHLINE:
- gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
break;
case NurbsConsts.N_MESHPOINT:
- gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_POINT);
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_POINT);
break;
}
}
@@ -109,6 +78,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
/**
* Pops all attributes
*/
+ @Override
public void endmap2f() {
// TODO Auto-generated method stub
if (output_triangles) {
@@ -126,7 +96,8 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* @param vlo
* @param vhi
*/
- public void domain2f(float ulo, float uhi, float vlo, float vhi) {
+ @Override
+ public void domain2f(final float ulo, final float uhi, final float vlo, final float vhi) {
// DONE
}
@@ -139,7 +110,8 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* @param v0 lowest v
* @param v1 highest v
*/
- public void mapgrid2f(int nu, float u0, float u1, int nv, float v0, float v1) {
+ @Override
+ public void mapgrid2f(final int nu, final float u0, final float u1, final int nv, final float v0, final float v1) {
if (output_triangles) {
// System.out.println("TODO openglsurfaceavaluator.mapgrid2f output_triangles");
@@ -157,7 +129,8 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* @param vmin minimum V
* @param vmax maximum V
*/
- public void mapmesh2f(int style, int umin, int umax, int vmin, int vmax) {
+ @Override
+ public void mapmesh2f(final int style, final int umin, final int umax, final int vmin, final int vmax) {
if (output_triangles) {
// System.out.println("TODO openglsurfaceavaluator.mapmesh2f output_triangles");
} else {
@@ -170,13 +143,13 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
*/
switch (style) {
case NurbsConsts.N_MESHFILL:
- gl.glEvalMesh2(GL2.GL_FILL, umin, umax, vmin, vmax);
+ gl.glEvalMesh2(GL2GL3.GL_FILL, umin, umax, vmin, vmax);
break;
case NurbsConsts.N_MESHLINE:
- gl.glEvalMesh2(GL2.GL_LINE, umin, umax, vmin, vmax);
+ gl.glEvalMesh2(GL2GL3.GL_LINE, umin, umax, vmin, vmax);
break;
case NurbsConsts.N_MESHPOINT:
- gl.glEvalMesh2(GL2.GL_POINT, umin, umax, vmin, vmax);
+ gl.glEvalMesh2(GL2GL3.GL_POINT, umin, umax, vmin, vmax);
break;
}
}
@@ -195,8 +168,9 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* @param vorder surface order in v direction
* @param pts control points
*/
- public void map2f(int type, float ulo, float uhi, int ustride, int uorder,
- float vlo, float vhi, int vstride, int vorder, CArrayOfFloats pts) {
+ @Override
+ public void map2f(final int type, final float ulo, final float uhi, final int ustride, final int uorder,
+ final float vlo, final float vhi, final int vstride, final int vorder, final CArrayOfFloats pts) {
// TODO Auto-generated method stub
if (output_triangles) {
// System.out.println("TODO openglsurfaceevaluator.map2f output_triangles");
@@ -210,7 +184,8 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* Calls opengl enable
* @param type what to enable
*/
- public void enable(int type) {
+ @Override
+ public void enable(final int type) {
//DONE
gl.glEnable(type);
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GLUgl2nurbsImpl.java b/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GLUgl2nurbsImpl.java
index 58b565484..a4507b767 100644
--- a/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GLUgl2nurbsImpl.java
+++ b/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GLUgl2nurbsImpl.java
@@ -37,15 +37,14 @@ import jogamp.opengl.glu.nurbs.*;
import java.lang.reflect.Method;
-import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.glu.GLUnurbs;
/**
* Base object for working with NURBS curves and surfaces
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class GLUgl2nurbsImpl implements GLUnurbs {
@@ -67,17 +66,17 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Matrixes autoloading
*/
- private boolean autoloadmode;
+ private final boolean autoloadmode;
/**
* Using callback
+ * private final int callBackFlag;
*/
- private int callBackFlag;
/**
* Object for error call backs
+ * private final Object errorCallback;
*/
- private Object errorCallback;
/**
* List of map definitions
@@ -116,33 +115,33 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Is curve modified
+ * private int isCurveModified;
*/
- private int isCurveModified;
/**
* Object holding rendering settings
*/
- private Renderhints renderhints;
+ private final Renderhints renderhints;
/**
* Display list
+ * private DisplayList dl;
*/
- private DisplayList dl;
/**
* Object for subdividing curves and surfaces
*/
- private Subdivider subdivider;
+ private final Subdivider subdivider;
/**
* Object responsible for rendering
+ * private Backend backend;
*/
- private Backend backend;
/**
* Next picewise linear curve in linked list
+ * private O_pwlcurve nextPwlcurve;
*/
- private O_pwlcurve nextPwlcurve;
/**
* Next trimming NURBS curve in linked list
@@ -156,13 +155,13 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Are there any changes in trimming
+ * private boolean isTrimModified;
*/
- private boolean isTrimModified;
/**
* Are there any changes in surface data
+ * private boolean isDataSurfaceModified;
*/
- private boolean isDataSurfaceModified;
/**
* Nurber of trmims of processed surface
@@ -181,20 +180,20 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Nextr surface in linked list
+ * private O_nurbssurface nextNurbssurface;
*/
- private O_nurbssurface nextNurbssurface;
/**
* Are there any changes in surface
+ * private boolean isSurfaceModified;
*/
- private boolean isSurfaceModified;
/**
* Initializes default GLUgl2nurbs object
*/
public GLUgl2nurbsImpl() {
// DONE
- maplist = new Maplist(backend);
+ maplist = new Maplist();
renderhints = new Renderhints();
subdivider = new Subdivider();
// original code
@@ -221,13 +220,13 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
defineMap(GL2.GL_MAP1_INDEX, 0, 1);
setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_SAMPLINGMETHOD,
- (float) NurbsConsts.N_PATHLENGTH);
+ NurbsConsts.N_PATHLENGTH);
setnurbsproperty(GL2.GL_MAP1_VERTEX_4, NurbsConsts.N_SAMPLINGMETHOD,
- (float) NurbsConsts.N_PATHLENGTH);
+ NurbsConsts.N_PATHLENGTH);
setnurbsproperty(GL2.GL_MAP2_VERTEX_3, NurbsConsts.N_SAMPLINGMETHOD,
- (float) NurbsConsts.N_PATHLENGTH);
+ NurbsConsts.N_PATHLENGTH);
setnurbsproperty(GL2.GL_MAP2_VERTEX_4, NurbsConsts.N_SAMPLINGMETHOD,
- (float) NurbsConsts.N_PATHLENGTH);
+ NurbsConsts.N_PATHLENGTH);
setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_PIXEL_TOLERANCE,
(float) 50.0);
@@ -265,29 +264,29 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
this.autoloadmode = true;
- this.callBackFlag = 0;
+ // this.callBackFlag = 0;
- this.errorCallback = null;
+ // this.errorCallback = null;
}
/**
* Sets domain distance for dom.dist. sampling in u direction
- *
+ *
* @param d
* distance
*/
- private void set_domain_distance_u_rate(double d) {
+ private void set_domain_distance_u_rate(final double d) {
// DONE
subdivider.set_domain_distance_u_rate(d);
}
/**
* Sets domain distance for dom.dist. sampling in v direction
- *
+ *
* @param d
* distance
*/
- private void set_domain_distance_v_rate(double d) {
+ private void set_domain_distance_v_rate(final double d) {
// DONE
subdivider.set_domain_distance_v_rate(d);
}
@@ -297,31 +296,31 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
*/
public void bgncurve() {
// DONE
- O_curve o_curve = new O_curve();
+ final O_curve o_curve = new O_curve();
thread("do_bgncurve", o_curve);
}
/**
* Calls a method with given name and passes argumet
- *
+ *
* @param name
* name of a method to be called
* @param arg
* parameter to be passed to called method
*/
- private void thread(String name, Object arg) {
+ private void thread(final String name, final Object arg) {
// DONE
- Class partype[] = new Class[1];
+ final Class<?> partype[] = new Class[1];
partype[0] = arg.getClass();
Method m;
try {
m = this.getClass().getMethod(name, partype);
- if (dl != null) {
+ /* if (dl != null) {
dl.append(this, m, arg);
- } else {
+ } else */ {
m.invoke(this, new Object[] { arg });
}
- } catch (Throwable e) {
+ } catch (final Throwable e) {
e.printStackTrace();
}
@@ -329,31 +328,31 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Calls a method with given name
- *
+ *
* @param name
* name of a method to be called
*/
- private void thread2(String name) {
+ private void thread2(final String name) {
// DONE
try {
- Method m = this.getClass().getMethod(name, (Class[]) null);
- if (dl != null) {
+ final Method m = this.getClass().getMethod(name, (Class[]) null);
+ /* if (dl != null) {
dl.append(this, m, null);
- } else {
+ } else */ {
m.invoke(this, (Object[]) null);
}
- } catch (Throwable e) {
+ } catch (final Throwable e) {
e.printStackTrace();
}
}
/**
* Begins a NURBS curve
- *
+ *
* @param o_curve
* curve object
*/
- public void do_bgncurve(O_curve o_curve) {
+ public void do_bgncurve(final O_curve o_curve) {
if (inCurve > 0) {
do_nurbserror(6);
endcurve();
@@ -365,7 +364,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
if (inTrim) {
if (!nextCurve.equals(o_curve)) {
- isCurveModified = 1;
+ // isCurveModified = 1;
nextCurve = o_curve;
}
} else {
@@ -375,17 +374,17 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
}
nextCurve = o_curve.next;
// kind of solution of union
- nextPwlcurve = o_curve.o_pwlcurve;
+ // nextPwlcurve = o_curve.o_pwlcurve;
nextNurbscurve = o_curve.o_nurbscurve;
}
/**
* Begins new surface
- *
+ *
* @param o_surface
* surface object
*/
- public void do_bgnsurface(O_surface o_surface) {
+ public void do_bgnsurface(final O_surface o_surface) {
// DONE
if (inSurface > 0) {
do_nurbserror(27);
@@ -395,13 +394,13 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
if (!playBack)
bgnrender();
- isTrimModified = false;
- isDataSurfaceModified = false;
+ // isTrimModified = false;
+ // isDataSurfaceModified = false;
isDataValid = 1;
numTrims = 0;
currentSurface = o_surface;
nextTrim = o_surface.o_trim;
- nextNurbssurface = o_surface.o_nurbssurface;
+ // nextNurbssurface = o_surface.o_nurbssurface;
}
/**
@@ -429,14 +428,14 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
inSurface = 0;
- nextNurbssurface = null;
+ // nextNurbssurface = null;
if (isDataValid <= 0) {
return;
}
if (nextTrim != null) {
- isTrimModified = true;
+ // isTrimModified = true;
nextTrim = null;
}
@@ -503,11 +502,11 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Method for handling error codes
- *
+ *
* @param i
* error code
*/
- private void do_nurbserror(int i) {
+ private void do_nurbserror(final int i) {
// TODO nurberror
// System.out.println("TODO nurbserror " + i);
}
@@ -539,7 +538,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Make a NURBS curve
- *
+ *
* @param nknots
* number of knots in knot vector
* @param knot
@@ -553,10 +552,10 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
* @param realType
* type of the curve
*/
- public void nurbscurve(int nknots, float[] knot, int stride,
- float[] ctlarray, int order, int realType) {
+ public void nurbscurve(final int nknots, final float[] knot, final int stride,
+ final float[] ctlarray, final int order, final int realType) {
// DONE
- Mapdesc mapdesc = maplist.locate(realType);
+ final Mapdesc mapdesc = maplist.locate(realType);
if (mapdesc == null) {
do_nurbserror(35);
isDataValid = 0;
@@ -572,14 +571,14 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
isDataValid = 0;
return;
}
- Knotvector knots = new Knotvector(nknots, stride, order, knot);
+ final Knotvector knots = new Knotvector(nknots, stride, order, knot);
if (!do_check_knots(knots, "curve"))
return;
- O_nurbscurve o_nurbscurve = new O_nurbscurve(realType);
+ final O_nurbscurve o_nurbscurve = new O_nurbscurve(realType);
o_nurbscurve.bezier_curves = new Quilt(mapdesc);
- CArrayOfFloats ctrlcarr = new CArrayOfFloats(ctlarray);
+ final CArrayOfFloats ctrlcarr = new CArrayOfFloats(ctlarray);
o_nurbscurve.bezier_curves.toBezier(knots, ctrlcarr, mapdesc
.getNCoords());
thread("do_nurbscurve", o_nurbscurve);
@@ -587,16 +586,16 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Check knot vector specification
- *
+ *
* @param knots
* knot vector
* @param msg
* error message
* @return knot vector is / is not valid
*/
- public boolean do_check_knots(Knotvector knots, String msg) {
+ public boolean do_check_knots(final Knotvector knots, final String msg) {
// DONE
- int status = knots.validate();
+ final int status = knots.validate();
if (status > 0) {
do_nurbserror(status);
if (renderhints.errorchecking != NurbsConsts.N_NOMSG)
@@ -607,11 +606,11 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Draw a curve
- *
+ *
* @param o_nurbscurve
* NURBS curve object
*/
- public void do_nurbscurve(O_nurbscurve o_nurbscurve) {
+ public void do_nurbscurve(final O_nurbscurve o_nurbscurve) {
// DONE
if (inCurve <= 0) {
@@ -638,7 +637,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
// if(!o_nurbscurve.equals(nextNurbscurve)){
if (!o_nurbscurve.equals(currentCurve.o_nurbscurve)) {
- isCurveModified = 1;
+ // isCurveModified = 1;
currentCurve.o_nurbscurve = o_nurbscurve;
// nextNurbscurve=o_nurbscurve;
@@ -647,24 +646,28 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
nextNurbscurve = o_nurbscurve.next;
if (!currentCurve.equals(o_nurbscurve.owner)) {
- isCurveModified = 1;
+ // isCurveModified = 1;
o_nurbscurve.owner = currentCurve;
}
- if (o_nurbscurve.owner == null)
+
+ /**
+ if (o_nurbscurve.owner == null) {
isCurveModified = 1;
+ } */
- if (inCurve == 2)
+ if (inCurve == 2) {
endcurve();
+ }
}
/**
* Draw NURBS surface
- *
+ *
* @param o_nurbssurface
* NURBS surface object
*/
- public void do_nurbssurface(O_nurbssurface o_nurbssurface) {
+ public void do_nurbssurface(final O_nurbssurface o_nurbssurface) {
// DONE
if (inSurface <= 0) {
bgnsurface();
@@ -677,18 +680,18 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
} else
o_nurbssurface.used = true;
- if (!o_nurbssurface.equals(nextNurbscurve)) {
- isSurfaceModified = true;
+ // Always true, instances of diff classes are compared: if (!o_nurbssurface.equals(nextNurbscurve)) {
+ // isSurfaceModified = true;
// nextNurbssurface=o_nurbssurface;
currentSurface.o_nurbssurface = o_nurbssurface;
- }
+ // }
if (!currentSurface.equals(o_nurbssurface.owner)) {
- isSurfaceModified = true;
+ // isSurfaceModified = true;
o_nurbssurface.owner = currentSurface;
}
- nextNurbssurface = o_nurbssurface.next;
+ // nextNurbssurface = o_nurbssurface.next;
if (inSurface == 2)
endsurface();
@@ -704,7 +707,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Define a map of given properties
- *
+ *
* @param type
* map type
* @param rational
@@ -712,14 +715,14 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
* @param ncoords
* number of control point coordinates
*/
- public void defineMap(int type, int rational, int ncoords) {
+ public void defineMap(final int type, final int rational, final int ncoords) {
// DONE
maplist.define(type, rational, ncoords);
}
/**
* Set NURBS property
- *
+ *
* @param type
* property type
* @param tag
@@ -727,9 +730,9 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
* @param value
* property value
*/
- public void setnurbsproperty(int type, int tag, float value) {
+ public void setnurbsproperty(final int type, final int tag, final float value) {
// DONE
- Mapdesc mapdesc = maplist.locate(type);
+ final Mapdesc mapdesc = maplist.locate(type);
if (mapdesc == null) {
do_nurbserror(35);
return;
@@ -738,28 +741,28 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
do_nurbserror(26);
return;
}
- Property prop = new Property(type, tag, value);
+ final Property prop = new Property(type, tag, value);
thread("do_setnurbsproperty2", prop);
}
/**
* Set parameters of existing property
- *
+ *
* @param prop
* property
*/
- public void do_setnurbsproperty2(Property prop) {
- Mapdesc mapdesc = maplist.find(prop.type);
+ public void do_setnurbsproperty2(final Property prop) {
+ final Mapdesc mapdesc = maplist.find(prop.type);
mapdesc.setProperty(prop.tag, prop.value);
}
/**
* Set given property to rendering hints
- *
+ *
* @param prop
* property to be set
*/
- public void do_setnurbsproperty(Property prop) {
+ public void do_setnurbsproperty(final Property prop) {
// DONE
renderhints.setProperty(prop);
// TODO freeproperty?
@@ -767,11 +770,11 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Sets wheteher we use domain distance sampling
- *
+ *
* @param i
* domain distance sampling flag
*/
- public void set_is_domain_distance_sampling(int i) {
+ public void set_is_domain_distance_sampling(final int i) {
// DONE
subdivider.set_is_domain_distance_sampling(i);
}
@@ -781,7 +784,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
*/
public void bgnsurface() {
// DONE
- O_surface o_surface = new O_surface();
+ final O_surface o_surface = new O_surface();
// TODO nuid
// System.out.println("TODO glunurbs.bgnsurface nuid");
thread("do_bgnsurface", o_surface);
@@ -805,7 +808,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Make NURBS surface
- *
+ *
* @param sknot_count
* number of knots in s direction
* @param sknot
@@ -827,11 +830,11 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
* @param type
* NURBS surface type (rational,...)
*/
- public void nurbssurface(int sknot_count, float[] sknot, int tknot_count,
- float[] tknot, int s_stride, int t_stride, float[] ctlarray,
- int sorder, int torder, int type) {
+ public void nurbssurface(final int sknot_count, final float[] sknot, final int tknot_count,
+ final float[] tknot, final int s_stride, final int t_stride, final float[] ctlarray,
+ final int sorder, final int torder, final int type) {
// DONE
- Mapdesc mapdesc = maplist.locate(type);
+ final Mapdesc mapdesc = maplist.locate(type);
if (mapdesc == null) {
do_nurbserror(35);
isDataValid = 0;
@@ -842,19 +845,19 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
isDataValid = 0;
return;
}
- Knotvector sknotvector = new Knotvector(sknot_count, s_stride, sorder,
+ final Knotvector sknotvector = new Knotvector(sknot_count, s_stride, sorder,
sknot);
if (!do_check_knots(sknotvector, "surface"))
return;
- Knotvector tknotvector = new Knotvector(tknot_count, t_stride, torder,
+ final Knotvector tknotvector = new Knotvector(tknot_count, t_stride, torder,
tknot);
if (!do_check_knots(tknotvector, "surface"))
return;
- O_nurbssurface o_nurbssurface = new O_nurbssurface(type);
+ final O_nurbssurface o_nurbssurface = new O_nurbssurface(type);
o_nurbssurface.bezier_patches = new Quilt(mapdesc);
- CArrayOfFloats ctrlarr = new CArrayOfFloats(ctlarray);
+ final CArrayOfFloats ctrlarr = new CArrayOfFloats(ctlarray);
o_nurbssurface.bezier_patches.toBezier(sknotvector, tknotvector,
ctrlarr, mapdesc.getNCoords());
thread("do_nurbssurface", o_nurbssurface);
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java
index f5fe17a7b..337d93b80 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -46,9 +46,15 @@ package jogamp.opengl.glu.mipmap;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GL2GL3;
import javax.media.opengl.glu.GLU;
+
import jogamp.opengl.Debug;
+
import com.jogamp.common.nio.Buffers;
+
import java.nio.*;
import java.io.*;
@@ -64,10 +70,10 @@ public class BuildMipmap {
/** Creates a new instance of BuildMipmap */
public BuildMipmap() {
}
-
- public static int gluBuild1DMipmapLevelsCore( GL gl, int target, int internalFormat,
- int width, int widthPowerOf2, int format, int type, int userLevel,
- int baseLevel, int maxLevel, ByteBuffer data ) {
+
+ public static int gluBuild1DMipmapLevelsCore( final GL gl, final int target, final int internalFormat,
+ final int width, final int widthPowerOf2, final int format, final int type, final int userLevel,
+ final int baseLevel, final int maxLevel, final ByteBuffer data ) {
int newwidth;
int level, levels;
ShortBuffer newImage = null;
@@ -75,55 +81,55 @@ public class BuildMipmap {
ShortBuffer otherImage = null;
ShortBuffer imageTemp = null;
int memReq;
- int maxsize;
+ final int maxsize;
int cmpts;
- PixelStorageModes psm = new PixelStorageModes();
-
+ final PixelStorageModes psm = new PixelStorageModes();
+
assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 );
assert( width >= 1 );
-
+
newwidth = widthPowerOf2;
levels = Mipmap.computeLog( newwidth );
-
+
levels += userLevel;
-
+
Mipmap.retrieveStoreModes( gl, psm );
try {
- newImage = Buffers.newDirectByteBuffer( Mipmap.image_size( width, 1, format,
- GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
- } catch( OutOfMemoryError ome ) {
+ newImage = Buffers.newDirectByteBuffer( Mipmap.image_size( width, 1, format,
+ GL.GL_UNSIGNED_SHORT ) ).asShortBuffer();
+ } catch( final OutOfMemoryError ome ) {
return( GLU.GLU_OUT_OF_MEMORY );
}
newImage_width = width;
-
+
Image.fill_image( psm, width, 1, format, type, Mipmap.is_index( format ), data, newImage );
cmpts = Mipmap.elements_per_group( format, type );
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 2 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 );
-
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, 2 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, 0 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, 0 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, 0 );
+
// if swap_bytes was set, swapping occurred in fill_image
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
-
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE );
+
for( level = userLevel; level <= levels; level++ ) {
if( newImage_width == newwidth ) {
// user newimage for this level
if( baseLevel <= level && level <= maxLevel ) {
gl.getGL2().glTexImage1D( target, level, internalFormat, newImage_width, 0, format,
- GL2.GL_UNSIGNED_SHORT, newImage );
+ GL.GL_UNSIGNED_SHORT, newImage );
}
} else {
if( otherImage == null ) {
- memReq = Mipmap.image_size( newwidth, 1, format, GL2.GL_UNSIGNED_SHORT );
+ memReq = Mipmap.image_size( newwidth, 1, format, GL.GL_UNSIGNED_SHORT );
try {
otherImage = Buffers.newDirectByteBuffer( memReq ).asShortBuffer();
- } catch( OutOfMemoryError ome ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+ } catch( final OutOfMemoryError ome ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
return( GLU.GLU_OUT_OF_MEMORY );
}
}
@@ -132,30 +138,30 @@ public class BuildMipmap {
imageTemp = otherImage;
otherImage = newImage;
newImage = imageTemp;
-
+
newImage_width = newwidth;
if( baseLevel <= level && level <= maxLevel ) {
- gl.getGL2().glTexImage1D( target, level, internalFormat, newImage_width, 0,
- format, GL2.GL_UNSIGNED_SHORT, newImage );
+ gl.getGL2().glTexImage1D( target, level, internalFormat, newImage_width, 0,
+ format, GL.GL_UNSIGNED_SHORT, newImage );
}
}
if( newwidth > 1 ) {
newwidth /= 2;
}
}
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
-
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+
return( 0 );
}
-
- public static int bitmapBuild2DMipmaps( GL gl, int target, int internalFormat,
- int width, int height, int format, int type, ByteBuffer data ) {
- int newwidth[] = new int[1];
- int newheight[] = new int[1];
+
+ public static int bitmapBuild2DMipmaps( final GL gl, final int target, final int internalFormat,
+ final int width, final int height, final int format, final int type, final ByteBuffer data ) {
+ final int newwidth[] = new int[1];
+ final int newheight[] = new int[1];
int level, levels;
ShortBuffer newImage = null;
int newImage_width;
@@ -163,71 +169,71 @@ public class BuildMipmap {
ShortBuffer otherImage = null;
ShortBuffer tempImage = null;
int memReq;
- int maxsize;
+ final int maxsize;
int cmpts;
- PixelStorageModes psm = new PixelStorageModes();
-
+ final PixelStorageModes psm = new PixelStorageModes();
+
Mipmap.retrieveStoreModes( gl, psm );
-
+
Mipmap.closestFit( gl, target, width, height, internalFormat, format, type, newwidth, newheight );
-
+
levels = Mipmap.computeLog( newwidth[0] );
level = Mipmap.computeLog( newheight[0] );
if( level > levels ) {
levels = level;
}
-
+
try {
- newImage = Buffers.newDirectByteBuffer( Mipmap.image_size( width, height,
- format, GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
- } catch( OutOfMemoryError ome ) {
+ newImage = Buffers.newDirectByteBuffer( Mipmap.image_size( width, height,
+ format, GL.GL_UNSIGNED_SHORT ) ).asShortBuffer();
+ } catch( final OutOfMemoryError ome ) {
return( GLU.GLU_OUT_OF_MEMORY );
}
newImage_width = width;
newImage_height = height;
-
+
Image.fill_image( psm, width, height, format, type, Mipmap.is_index( format ), data, newImage );
-
+
cmpts = Mipmap.elements_per_group( format, type );
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 2 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 );
-
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, 2 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, 0 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, 0 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, 0 );
+
// if swap_bytes is set, swapping occurred in fill_image
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
-
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE );
+
for( level = 0; level < levels; level++ ) {
if( newImage_width == newwidth[0] && newImage_height == newheight[0] ) {
newImage.rewind();
gl.glTexImage2D( target, level, internalFormat, newImage_width,
- newImage_height, 0, format, GL2.GL_UNSIGNED_SHORT, newImage );
+ newImage_height, 0, format, GL.GL_UNSIGNED_SHORT, newImage );
} else {
if( otherImage == null ) {
- memReq = Mipmap.image_size( newwidth[0], newheight[0], format, GL2.GL_UNSIGNED_SHORT );
+ memReq = Mipmap.image_size( newwidth[0], newheight[0], format, GL.GL_UNSIGNED_SHORT );
try {
otherImage = Buffers.newDirectByteBuffer( memReq ).asShortBuffer();
- } catch( OutOfMemoryError ome ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+ } catch( final OutOfMemoryError ome ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
return( GLU.GLU_OUT_OF_MEMORY );
}
}
- ScaleInternal.scale_internal( cmpts, newImage_width, newImage_height,
+ ScaleInternal.scale_internal( cmpts, newImage_width, newImage_height,
newImage, newwidth[0], newheight[0], otherImage );
// swap newImage and otherImage
tempImage = otherImage;
otherImage = newImage;
newImage = tempImage;
-
+
newImage_width = newwidth[0];
newImage_height = newheight[0];
newImage.rewind();
gl.glTexImage2D( target, level, internalFormat, newImage_width, newImage_height,
- 0, format, GL2.GL_UNSIGNED_SHORT, newImage );
+ 0, format, GL.GL_UNSIGNED_SHORT, newImage );
}
if( newheight[0] > 1 ) {
newwidth[0] /= 2;
@@ -236,46 +242,46 @@ public class BuildMipmap {
newheight[0] /= 2;
}
}
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
-
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+
return( 0 );
}
-
- public static int gluBuild2DMipmapLevelsCore( GL gl, int target, int internalFormat,
- int width, int height, int widthPowerOf2, int heightPowerOf2,
- int format, int type, int userLevel, int baseLevel, int maxLevel,
- ByteBuffer data ) { // PointerWrapper data
+
+ public static int gluBuild2DMipmapLevelsCore( final GL gl, final int target, final int internalFormat,
+ final int width, final int height, final int widthPowerOf2, final int heightPowerOf2,
+ final int format, final int type, final int userLevel, final int baseLevel, final int maxLevel,
+ final ByteBuffer data ) { // PointerWrapper data
int newwidth;
int newheight;
int level, levels;
- int usersImage;
+ final int usersImage;
ByteBuffer srcImage = null;
ByteBuffer dstImage = null;
ByteBuffer tempImage = null;
- int newImage_width;
- int newImage_height;
- short[] SWAP_IMAGE = null;
+ final int newImage_width;
+ final int newImage_height;
+ final short[] SWAP_IMAGE = null;
int memReq;
- int maxsize;
+ final int maxsize;
int cmpts;
int mark=-1;
-
+
boolean myswap_bytes;
int groups_per_line, element_size, group_size;
int rowsize, padding;
- PixelStorageModes psm = new PixelStorageModes();
-
+ final PixelStorageModes psm = new PixelStorageModes();
+
assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 );
assert( width >= 1 && height >= 1 );
-
+
if( type == GL2.GL_BITMAP ) {
return( bitmapBuild2DMipmaps( gl, target, internalFormat, width, height, format, type, data ) );
}
-
+
newwidth = widthPowerOf2;
newheight = heightPowerOf2;
levels = Mipmap.computeLog( newwidth );
@@ -283,9 +289,9 @@ public class BuildMipmap {
if( level > levels ) {
levels = level;
}
-
+
levels += userLevel;
-
+
Mipmap.retrieveStoreModes( gl, psm );
myswap_bytes = psm.getUnpackSwapBytes();
cmpts = Mipmap.elements_per_group( format, type );
@@ -294,28 +300,28 @@ public class BuildMipmap {
} else {
groups_per_line = width;
}
-
+
element_size = Mipmap.bytes_per_element( type );
group_size = element_size * cmpts;
if( element_size == 1 ) {
myswap_bytes = false;
}
-
+
rowsize = groups_per_line * group_size;
padding = ( rowsize % psm.getUnpackAlignment() );
if( padding != 0 ) {
rowsize += psm.getUnpackAlignment() - padding;
}
-
+
mark = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size;
data.position( mark );
-
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 );
-
+
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, 0 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, 0 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, 0 );
+
level = userLevel;
-
+
// already power of two square
if( width == newwidth && height == newheight ) {
// use usersImage for level userLevel
@@ -324,16 +330,16 @@ public class BuildMipmap {
gl.glTexImage2D( target, level, internalFormat, width, height, 0, format, type, data );
}
if( levels == 0 ) { /* we're done. clean up and return */
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
return( 0 );
}
int nextWidth = newwidth / 2;
int nextHeight = newheight / 2;
-
+
// clamp to 1
if( nextWidth < 1 ) {
nextWidth = 1;
@@ -342,100 +348,100 @@ public class BuildMipmap {
nextHeight = 1;
}
memReq = Mipmap.image_size( nextWidth, nextHeight, format, type );
-
+
try {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
- case( GL2.GL_BYTE ):
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_INT ):
- case( GL2.GL_FLOAT ):
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL.GL_UNSIGNED_BYTE ):
+ case( GL.GL_BYTE ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_FLOAT ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
dstImage = Buffers.newDirectByteBuffer( memReq );
break;
default:
return( GLU.GLU_INVALID_ENUM );
}
- } catch( OutOfMemoryError ome ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+ } catch( final OutOfMemoryError ome ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
return( GLU.GLU_OUT_OF_MEMORY );
}
if( dstImage != null ) {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
+ case( GL.GL_UNSIGNED_BYTE ):
HalveImage.halveImage_ubyte( cmpts, width, height, data, dstImage, element_size, rowsize, group_size );
break;
- case( GL2.GL_BYTE ):
+ case( GL.GL_BYTE ):
HalveImage.halveImage_byte( cmpts, width, height, data, dstImage, element_size, rowsize, group_size );
break;
- case( GL2.GL_UNSIGNED_SHORT ):
+ case( GL.GL_UNSIGNED_SHORT ):
HalveImage.halveImage_ushort( cmpts, width, height, data, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_SHORT ):
+ case( GL.GL_SHORT ):
HalveImage.halveImage_short( cmpts, width, height, data, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT ):
+ case( GL.GL_UNSIGNED_INT ):
HalveImage.halveImage_uint( cmpts, width, height, data, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_INT ):
+ case( GL2ES2.GL_INT ):
HalveImage.halveImage_int( cmpts, width, height, data, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_FLOAT ):
+ case( GL.GL_FLOAT ):
HalveImage.halveImage_float( cmpts, width, height, data, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- assert( format == GL2.GL_RGB );
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ assert( format == GL.GL_RGB );
HalveImage.halveImagePackedPixel( 3, new Extract332(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- assert( format == GL2.GL_RGB );
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ assert( format == GL.GL_RGB );
HalveImage.halveImagePackedPixel( 3, new Extract233rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
HalveImage.halveImagePackedPixel( 3, new Extract565(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
HalveImage.halveImagePackedPixel( 3, new Extract565rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
HalveImage.halveImagePackedPixel( 4, new Extract4444(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
HalveImage.halveImagePackedPixel( 4, new Extract4444rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
HalveImage.halveImagePackedPixel( 4, new Extract5551(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
HalveImage.halveImagePackedPixel( 4, new Extract1555rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
HalveImage.halveImagePackedPixel( 4, new Extract8888(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
HalveImage.halveImagePackedPixel( 4, new Extract8888rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
HalveImage.halveImagePackedPixel( 4, new Extract1010102(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
HalveImage.halveImagePackedPixel( 4, new Extract2101010rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
break;
default:
@@ -452,7 +458,7 @@ public class BuildMipmap {
if( newheight < 1 ) {
newheight = 1;
}
-
+
myswap_bytes = false;
rowsize = newwidth * group_size;
memReq = Mipmap.image_size( newwidth, newheight, format, type );
@@ -462,151 +468,151 @@ public class BuildMipmap {
dstImage = tempImage;
try {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
- case( GL2.GL_BYTE ):
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_INT ):
- case( GL2.GL_FLOAT ):
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL.GL_UNSIGNED_BYTE ):
+ case( GL.GL_BYTE ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_FLOAT ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
dstImage = Buffers.newDirectByteBuffer( memReq );
break;
default:
return( GLU.GLU_INVALID_ENUM );
}
- } catch( OutOfMemoryError ome ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+ } catch( final OutOfMemoryError ome ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
return( GLU.GLU_OUT_OF_MEMORY );
}
// level userLevel+1 is in srcImage; level userLevel already saved
level = userLevel + 1;
} else { // user's image is not nice powerof2 size square
memReq = Mipmap.image_size( newwidth, newheight, format, type );
- try {
+ try {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
- case( GL2.GL_BYTE ):
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_INT ):
- case( GL2.GL_FLOAT ):
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL.GL_UNSIGNED_BYTE ):
+ case( GL.GL_BYTE ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_FLOAT ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
dstImage = Buffers.newDirectByteBuffer( memReq );
break;
default:
return( GLU.GLU_INVALID_ENUM );
}
- } catch( OutOfMemoryError ome ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+ } catch( final OutOfMemoryError ome ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
return( GLU.GLU_OUT_OF_MEMORY );
}
data.position( mark );
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
- ScaleInternal.scale_internal_ubyte( cmpts, width, height, data,
+ case( GL.GL_UNSIGNED_BYTE ):
+ ScaleInternal.scale_internal_ubyte( cmpts, width, height, data,
newwidth, newheight, dstImage, element_size, rowsize, group_size );
break;
- case( GL2.GL_BYTE ):
- ScaleInternal.scale_internal_byte( cmpts, width, height, data, newwidth,
+ case( GL.GL_BYTE ):
+ ScaleInternal.scale_internal_byte( cmpts, width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, group_size );
break;
- case( GL2.GL_UNSIGNED_SHORT ):
- ScaleInternal.scale_internal_ushort( cmpts, width, height, data, newwidth,
+ case( GL.GL_UNSIGNED_SHORT ):
+ ScaleInternal.scale_internal_ushort( cmpts, width, height, data, newwidth,
newheight, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_SHORT ):
+ case( GL.GL_SHORT ):
ScaleInternal.scale_internal_ushort( cmpts, width, height, data, newwidth,
newheight, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT ):
+ case( GL.GL_UNSIGNED_INT ):
ScaleInternal.scale_internal_uint( cmpts, width, height, data, newwidth,
newheight, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_INT ):
+ case( GL2ES2.GL_INT ):
ScaleInternal.scale_internal_int( cmpts, width, height, data, newwidth,
newheight, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_FLOAT ):
+ case( GL.GL_FLOAT ):
ScaleInternal.scale_internal_float( cmpts, width, height, data, newwidth,
newheight, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
ScaleInternal.scaleInternalPackedPixel( 3, new Extract332(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
ScaleInternal.scaleInternalPackedPixel( 3, new Extract233rev(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
ScaleInternal.scaleInternalPackedPixel( 3, new Extract565(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
ScaleInternal.scaleInternalPackedPixel( 3, new Extract565rev(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
ScaleInternal.scaleInternalPackedPixel( 4, new Extract4444(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
ScaleInternal.scaleInternalPackedPixel( 4, new Extract4444rev(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
ScaleInternal.scaleInternalPackedPixel( 4, new Extract5551(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
ScaleInternal.scaleInternalPackedPixel( 4, new Extract1555rev(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
ScaleInternal.scaleInternalPackedPixel( 4, new Extract8888(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
ScaleInternal.scaleInternalPackedPixel( 4, new Extract8888rev(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
ScaleInternal.scaleInternalPackedPixel( 4, new Extract1010102(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
ScaleInternal.scaleInternalPackedPixel( 4, new Extract2101010rev(), width, height, data, newwidth,
newheight, dstImage, element_size, rowsize, myswap_bytes );
break;
@@ -620,7 +626,7 @@ public class BuildMipmap {
tempImage = srcImage;
srcImage = dstImage;
dstImage = tempImage;
-
+
if( levels != 0 ) { // use as little memory as possible
int nextWidth = newwidth / 2;
int nextHeight = newheight / 2;
@@ -630,48 +636,48 @@ public class BuildMipmap {
if( nextHeight < 1 ) {
nextHeight = 1;
}
-
+
memReq = Mipmap.image_size( nextWidth, nextHeight, format, type );
try {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
- case( GL2.GL_BYTE ):
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_INT ):
- case( GL2.GL_FLOAT ):
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL.GL_UNSIGNED_BYTE ):
+ case( GL.GL_BYTE ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_FLOAT ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
dstImage = Buffers.newDirectByteBuffer( memReq );
break;
default:
return( GLU.GLU_INVALID_ENUM );
}
- } catch( OutOfMemoryError ome ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+ } catch( final OutOfMemoryError ome ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
return( GLU.GLU_OUT_OF_MEMORY );
}
}
// level userLevel is in srcImage; nothing saved yet
level = userLevel;
}
-
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
+
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE );
if( baseLevel <= level && level <= maxLevel ) {
srcImage.rewind();
gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage );
@@ -685,81 +691,81 @@ public class BuildMipmap {
}
}
}
-
+
level++; // update current level for the loop
for( ; level <= levels; level++ ) {
srcImage.rewind();
dstImage.rewind();
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
+ case( GL.GL_UNSIGNED_BYTE ):
HalveImage.halveImage_ubyte( cmpts, newwidth, newheight, srcImage, dstImage, element_size, rowsize, group_size );
break;
- case( GL2.GL_BYTE ):
+ case( GL.GL_BYTE ):
HalveImage.halveImage_byte( cmpts, newwidth, newheight, srcImage, dstImage, element_size, rowsize, group_size );
break;
- case( GL2.GL_UNSIGNED_SHORT ):
+ case( GL.GL_UNSIGNED_SHORT ):
HalveImage.halveImage_ushort( cmpts, newwidth, newheight, srcImage, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_SHORT ):
+ case( GL.GL_SHORT ):
HalveImage.halveImage_short( cmpts, newwidth, newheight, srcImage, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT ):
+ case( GL.GL_UNSIGNED_INT ):
HalveImage.halveImage_uint( cmpts, newwidth, newheight, srcImage, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_INT ):
+ case( GL2ES2.GL_INT ):
HalveImage.halveImage_int( cmpts, newwidth, newheight, srcImage, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_FLOAT ):
+ case( GL.GL_FLOAT ):
HalveImage.halveImage_float( cmpts, newwidth, newheight, srcImage, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- assert( format == GL2.GL_RGB );
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ assert( format == GL.GL_RGB );
HalveImage.halveImagePackedPixel( 3, new Extract332(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- assert( format == GL2.GL_RGB );
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ assert( format == GL.GL_RGB );
HalveImage.halveImagePackedPixel( 3, new Extract233rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
HalveImage.halveImagePackedPixel( 3, new Extract565(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
HalveImage.halveImagePackedPixel( 3, new Extract565rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
HalveImage.halveImagePackedPixel( 4, new Extract4444(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
HalveImage.halveImagePackedPixel( 4, new Extract4444rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
HalveImage.halveImagePackedPixel( 4, new Extract5551(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
HalveImage.halveImagePackedPixel( 4, new Extract1555rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
HalveImage.halveImagePackedPixel( 4, new Extract8888(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
HalveImage.halveImagePackedPixel( 4, new Extract8888rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
HalveImage.halveImagePackedPixel( 4, new Extract1010102(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
HalveImage.halveImagePackedPixel( 4, new Extract2101010rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
break;
default:
assert( false );
break;
}
-
+
// swap dstImage and srcImage
tempImage = srcImage;
srcImage = dstImage;
dstImage = tempImage;
-
+
if( newwidth > 1 ) {
newwidth /= 2;
rowsize /= 2;
@@ -768,8 +774,8 @@ public class BuildMipmap {
newheight /= 2;
}
// compute amount to pad per row if any
- int rowPad = rowsize % psm.getUnpackAlignment();
-
+ final int rowPad = rowsize % psm.getUnpackAlignment();
+
// should row be padded
if( rowPad == 0 ) {
// call teximage with srcImage untouched since its not padded
@@ -788,21 +794,21 @@ public class BuildMipmap {
}
} else {
// compute length of new row in bytes, including padding
- int newRowLength = rowsize + psm.getUnpackAlignment() - rowPad;
+ final int newRowLength = rowsize + psm.getUnpackAlignment() - rowPad;
int ii, jj;
- int dstTrav;
- int srcTrav;
-
+ final int dstTrav;
+ final int srcTrav;
+
// allocate new image for mipmap of size newRowLength x newheight
ByteBuffer newMipmapImage = null;
try {
newMipmapImage = ByteBuffer.allocateDirect( newRowLength * newheight );
- } catch( OutOfMemoryError ome ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+ } catch( final OutOfMemoryError ome ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
return( GLU.GLU_OUT_OF_MEMORY );
}
srcImage.rewind();
@@ -813,7 +819,7 @@ public class BuildMipmap {
newMipmapImage.put( srcImage.get() );
}
}
-
+
// and use this new image for mipmapping instead
if( baseLevel <= level && level <= maxLevel ) {
newMipmapImage.rewind();
@@ -828,19 +834,19 @@ public class BuildMipmap {
}
}
}
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
-
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+
return( 0 );
}
-
- public static int fastBuild2DMipmaps( GL gl, PixelStorageModes psm, int target,
- int components, int width, int height, int format, int type, ByteBuffer data ) {
- int[] newwidth = new int[1];
- int[] newheight = new int[1];
+
+ public static int fastBuild2DMipmaps( final GL gl, final PixelStorageModes psm, final int target,
+ final int components, final int width, final int height, final int format, final int type, final ByteBuffer data ) {
+ final int[] newwidth = new int[1];
+ final int[] newheight = new int[1];
int level, levels;
ByteBuffer newImage;
int newImage_width;
@@ -848,24 +854,24 @@ public class BuildMipmap {
ByteBuffer otherImage;
ByteBuffer imageTemp;
int memReq;
- int maxsize;
+ final int maxsize;
int cmpts;
-
- Mipmap.closestFit( gl, target, width, height, components, format, type, newwidth,
+
+ Mipmap.closestFit( gl, target, width, height, components, format, type, newwidth,
newheight );
-
+
levels = Mipmap.computeLog( newwidth[0] );
level = Mipmap.computeLog( newheight[0] );
if( level > levels ) {
levels = level;
}
-
+
cmpts = Mipmap.elements_per_group( format, type );
-
+
otherImage = null;
// No need to copy the user data if its packed correctly.
// Make sure that later routines don't change that data.
-
+
if( psm.getUnpackSkipRows() == 0 && psm.getUnpackSkipPixels() == 0 ) {
newImage = data;
newImage_width = width;
@@ -876,12 +882,12 @@ public class BuildMipmap {
int elements_per_line;
int start;
int iter;
- int iter2;
+ final int iter2;
int i, j;
-
+
try {
- newImage = Buffers.newDirectByteBuffer( Mipmap.image_size(width, height, format, GL2.GL_UNSIGNED_BYTE ) );
- } catch( OutOfMemoryError err ) {
+ newImage = Buffers.newDirectByteBuffer( Mipmap.image_size(width, height, format, GL.GL_UNSIGNED_BYTE ) );
+ } catch( final OutOfMemoryError err ) {
return( GLU.GLU_OUT_OF_MEMORY );
}
newImage_width = width;
@@ -896,7 +902,7 @@ public class BuildMipmap {
rowsize = group_per_line * cmpts;
elements_per_line = width * cmpts;
start = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * cmpts;
-
+
for( i = 0; i < height; i++ ) {
iter = start;
data.position( iter );
@@ -906,30 +912,30 @@ public class BuildMipmap {
start += rowsize;
}
}
-
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 1 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
-
+
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, 1 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, 0 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, 0 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, 0 );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE );
+
for( level = 0; level <= levels; level++ ) {
if( newImage_width == newwidth[0] && newImage_height == newheight[0] ) {
// use newImage for this level
newImage.rewind();
gl.glTexImage2D( target, level, components, newImage_width, newImage_height,
- 0, format, GL2.GL_UNSIGNED_BYTE, newImage );
+ 0, format, GL.GL_UNSIGNED_BYTE, newImage );
} else {
if( otherImage == null ) {
- memReq = Mipmap.image_size( newwidth[0], newheight[0], format, GL2.GL_UNSIGNED_BYTE );
+ memReq = Mipmap.image_size( newwidth[0], newheight[0], format, GL.GL_UNSIGNED_BYTE );
try {
otherImage = Buffers.newDirectByteBuffer( memReq );
- } catch( OutOfMemoryError err ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, ( psm.getUnpackSwapBytes() ? 1 : 0 ) ) ;
+ } catch( final OutOfMemoryError err ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, ( psm.getUnpackSwapBytes() ? 1 : 0 ) ) ;
return( GLU.GLU_OUT_OF_MEMORY );
}
}
@@ -937,12 +943,12 @@ public class BuildMipmap {
imageTemp = otherImage;
otherImage = newImage;
newImage = imageTemp;
-
+
newImage_width = newwidth[0];
newImage_height = newheight[0];
newImage.rewind();
gl.glTexImage2D( target, level, components, newImage_width, newImage_height,
- 0, format, GL2.GL_UNSIGNED_BYTE, newImage );
+ 0, format, GL.GL_UNSIGNED_BYTE, newImage );
}
if( newwidth[0] > 1 ) {
newwidth[0] /= 2;
@@ -951,45 +957,45 @@ public class BuildMipmap {
newheight[0] /= 2;
}
}
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, ( psm.getUnpackSwapBytes() ? 1 : 0 ) ) ;
-
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, ( psm.getUnpackSwapBytes() ? 1 : 0 ) ) ;
+
return( 0 );
}
-
- public static int gluBuild3DMipmapLevelsCore( GL gl, int target, int internalFormat,
- int width, int height, int depth, int widthPowerOf2, int heightPowerOf2,
- int depthPowerOf2, int format, int type, int userLevel, int baseLevel,
- int maxLevel, ByteBuffer data ) {
+
+ public static int gluBuild3DMipmapLevelsCore( final GL gl, final int target, final int internalFormat,
+ final int width, final int height, final int depth, final int widthPowerOf2, final int heightPowerOf2,
+ final int depthPowerOf2, final int format, final int type, final int userLevel, final int baseLevel,
+ final int maxLevel, final ByteBuffer data ) {
int newWidth;
int newHeight;
int newDepth;
int level, levels;
ByteBuffer usersImage;
ByteBuffer srcImage, dstImage, tempImage;
- int newImageWidth;
- int newImageHeight;
- int newImageDepth;
+ final int newImageWidth;
+ final int newImageHeight;
+ final int newImageDepth;
int memReq;
- int maxSize;
+ final int maxSize;
int cmpts;
int mark=-1;
-
+
boolean myswapBytes;
int groupsPerLine, elementSize, groupSize;
int rowsPerImage, imageSize;
int rowSize, padding;
- PixelStorageModes psm = new PixelStorageModes();
-
+ final PixelStorageModes psm = new PixelStorageModes();
+
assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 );
assert( width >= 1 && height >= 1 && depth >= 1 );
assert( type != GL2.GL_BITMAP );
-
+
srcImage = dstImage = null;
-
+
newWidth = widthPowerOf2;
newHeight = heightPowerOf2;
newDepth = depthPowerOf2;
@@ -1002,9 +1008,9 @@ public class BuildMipmap {
if( level > levels ) {
levels = level;
}
-
+
levels += userLevel;
-
+
Mipmap.retrieveStoreModes3D( gl, psm );
myswapBytes = psm.getUnpackSwapBytes();
cmpts = Mipmap.elements_per_group( format, type );
@@ -1013,42 +1019,42 @@ public class BuildMipmap {
} else {
groupsPerLine = width;
}
-
+
elementSize = Mipmap.bytes_per_element( type );
groupSize = elementSize * cmpts;
if( elementSize == 1 ) {
myswapBytes = false;
}
-
+
// 3dstuff
if( psm.getUnpackImageHeight() > 0 ) {
rowsPerImage = psm.getUnpackImageHeight();
} else {
rowsPerImage = height;
}
-
+
rowSize = groupsPerLine * groupSize;
padding = ( rowSize % psm.getUnpackAlignment() );
if( padding != 0 ) {
rowSize += psm.getUnpackAlignment() - padding;
}
-
+
imageSize = rowsPerImage * rowSize;
-
+
usersImage = ByteBuffer.wrap(data.array());
mark = psm.getUnpackSkipRows() * rowSize +
psm.getUnpackSkipPixels() * groupSize +
psm.getUnpackSkipImages() * imageSize;
usersImage.position( mark );
-
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, 0 );
-
+
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, 0 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, 0 );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, 0 );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_SKIP_IMAGES, 0 );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_IMAGE_HEIGHT, 0 );
+
level = userLevel;
-
+
if( width == newWidth && height == newHeight && depth == newDepth ) {
// use usersImage for level userlevel
if( baseLevel <= level && level <= maxLevel ) {
@@ -1056,19 +1062,19 @@ public class BuildMipmap {
0, format, type, usersImage );
}
if( levels == 0 ) { /* we're done. clean up and return */
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
- gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
return( 0 );
}
int nextWidth = newWidth / 2;
int nextHeight = newHeight / 2;
int nextDepth = newDepth / 2;
-
+
// clamp to one
if( nextWidth < 1 ) {
nextWidth = 1;
@@ -1082,54 +1088,54 @@ public class BuildMipmap {
memReq = Mipmap.imageSize3D( nextWidth, nextHeight, nextDepth, format, type );
try {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
- case( GL2.GL_BYTE ):
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_INT ):
- case( GL2.GL_FLOAT ):
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL.GL_UNSIGNED_BYTE ):
+ case( GL.GL_BYTE ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_FLOAT ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
dstImage = Buffers.newDirectByteBuffer( memReq );
break;
default:
return( GLU.GLU_INVALID_ENUM );
}
- } catch( OutOfMemoryError err ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
- gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+ } catch( final OutOfMemoryError err ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
return( GLU.GLU_OUT_OF_MEMORY );
}
-
+
if( dstImage != null ) {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
+ case( GL.GL_UNSIGNED_BYTE ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractUByte(), width, height, depth,
- usersImage, dstImage, elementSize,
+ usersImage, dstImage, elementSize,
groupSize, rowSize, imageSize, myswapBytes );
} else {
HalveImage.halveImage_ubyte( cmpts, width, height, usersImage,
dstImage, elementSize, rowSize, groupSize );
}
break;
- case( GL2.GL_BYTE ):
+ case( GL.GL_BYTE ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractSByte(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1139,17 +1145,17 @@ public class BuildMipmap {
dstImage, elementSize, rowSize, groupSize );
}
break;
- case( GL2.GL_UNSIGNED_SHORT ):
+ case( GL.GL_UNSIGNED_SHORT ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractUShort(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
imageSize, myswapBytes );
} else {
- HalveImage.halveImage_ushort( cmpts, width, height, usersImage,
+ HalveImage.halveImage_ushort( cmpts, width, height, usersImage,
dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes );
}
break;
- case( GL2.GL_SHORT ):
+ case( GL.GL_SHORT ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractSShort(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1159,7 +1165,7 @@ public class BuildMipmap {
dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes );
}
break;
- case( GL2.GL_UNSIGNED_INT ):
+ case( GL.GL_UNSIGNED_INT ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractUInt(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1169,7 +1175,7 @@ public class BuildMipmap {
dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes );
}
break;
- case( GL2.GL_INT ):
+ case( GL2ES2.GL_INT ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractSInt(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1179,7 +1185,7 @@ public class BuildMipmap {
dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes );
}
break;
- case( GL2.GL_FLOAT ):
+ case( GL.GL_FLOAT ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractFloat(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1189,53 +1195,53 @@ public class BuildMipmap {
dstImage.asFloatBuffer(), elementSize, rowSize, groupSize, myswapBytes );
}
break;
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- assert( format == GL2.GL_RGB );
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ assert( format == GL.GL_RGB );
HalveImage.halveImagePackedPixel3D( 3, new Extract332(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- assert( format == GL2.GL_RGB );
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ assert( format == GL.GL_RGB );
HalveImage.halveImagePackedPixel3D( 3, new Extract233rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
HalveImage.halveImagePackedPixel3D( 3, new Extract565(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
HalveImage.halveImagePackedPixel3D( 3, new Extract565rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
HalveImage.halveImagePackedPixel3D( 4, new Extract4444(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
HalveImage.halveImagePackedPixel3D( 4, new Extract4444rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
HalveImage.halveImagePackedPixel3D( 4, new Extract5551(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
HalveImage.halveImagePackedPixel3D( 4, new Extract1555rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
HalveImage.halveImagePackedPixel3D( 4, new Extract8888(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
HalveImage.halveImagePackedPixel3D( 4, new Extract8888rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
HalveImage.halveImagePackedPixel3D( 4, new Extract1010102(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
HalveImage.halveImagePackedPixel3D( 4, new Extract2101010rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
@@ -1257,7 +1263,7 @@ public class BuildMipmap {
if( newDepth < 1 ) {
newDepth = 1;
}
-
+
myswapBytes = false;
rowSize = newWidth * groupSize;
imageSize = rowSize * newHeight;
@@ -1268,85 +1274,85 @@ public class BuildMipmap {
dstImage = tempImage;
try {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
- case( GL2.GL_BYTE ):
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_INT ):
- case( GL2.GL_FLOAT ):
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL.GL_UNSIGNED_BYTE ):
+ case( GL.GL_BYTE ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_FLOAT ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
dstImage = Buffers.newDirectByteBuffer( memReq );
break;
default:
return( GLU.GLU_INVALID_ENUM );
}
- } catch( OutOfMemoryError err ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
- gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+ } catch( final OutOfMemoryError err ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
return( GLU.GLU_OUT_OF_MEMORY );
}
-
+
// level userLevel + 1 is in srcImage; level userLevel already saved
level = userLevel + 1;
} else {
memReq = Mipmap.imageSize3D( newWidth, newHeight, newDepth, format, type );
try {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
- case( GL2.GL_BYTE ):
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_INT ):
- case( GL2.GL_FLOAT ):
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL.GL_UNSIGNED_BYTE ):
+ case( GL.GL_BYTE ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_FLOAT ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
dstImage = Buffers.newDirectByteBuffer( memReq );
break;
default:
return( GLU.GLU_INVALID_ENUM );
}
- } catch( OutOfMemoryError err ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
- gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+ } catch( final OutOfMemoryError err ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
return( GLU.GLU_OUT_OF_MEMORY );
}
-
+
ScaleInternal.gluScaleImage3D( gl, format, width, height, depth, type,
usersImage, newWidth, newHeight, newDepth, type, dstImage );
-
+
myswapBytes = false;
rowSize = newWidth * groupSize;
imageSize = rowSize * newHeight;
@@ -1354,7 +1360,7 @@ public class BuildMipmap {
tempImage = srcImage;
srcImage = dstImage;
dstImage = tempImage;
-
+
if( levels != 0 ) {
int nextWidth = newWidth / 2;
int nextHeight = newHeight / 2;
@@ -1371,46 +1377,46 @@ public class BuildMipmap {
memReq = Mipmap.imageSize3D( nextWidth, nextHeight, nextDepth, format, type );
try {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
- case( GL2.GL_BYTE ):
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_INT ):
- case( GL2.GL_FLOAT ):
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL.GL_UNSIGNED_BYTE ):
+ case( GL.GL_BYTE ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_FLOAT ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
dstImage = Buffers.newDirectByteBuffer( memReq );
break;
default:
return( GLU.GLU_INVALID_ENUM );
}
- } catch( OutOfMemoryError err ) {
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
- gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+ } catch( final OutOfMemoryError err ) {
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
return( GLU.GLU_OUT_OF_MEMORY );
}
}
// level userLevel is in srcImage; nothing saved yet
level = userLevel;
}
-
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
+
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE );
if( baseLevel <= level && level <= maxLevel ) {
usersImage.position( mark );
gl.getGL2().glTexImage3D( target, level, internalFormat, width, height, depth,
@@ -1419,7 +1425,7 @@ public class BuildMipmap {
level++;
for( ; level <= levels; level++ ) {
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
+ case( GL.GL_UNSIGNED_BYTE ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractUByte(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1429,7 +1435,7 @@ public class BuildMipmap {
dstImage, elementSize, rowSize, groupSize );
}
break;
- case( GL2.GL_BYTE ):
+ case( GL.GL_BYTE ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractSByte(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1439,7 +1445,7 @@ public class BuildMipmap {
dstImage, elementSize, rowSize, groupSize );
}
break;
- case( GL2.GL_UNSIGNED_SHORT ):
+ case( GL.GL_UNSIGNED_SHORT ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractUShort(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1449,7 +1455,7 @@ public class BuildMipmap {
dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes );
}
break;
- case( GL2.GL_SHORT ):
+ case( GL.GL_SHORT ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractSShort(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1459,7 +1465,7 @@ public class BuildMipmap {
dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes );
}
break;
- case( GL2.GL_UNSIGNED_INT ):
+ case( GL.GL_UNSIGNED_INT ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractUInt(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1469,7 +1475,7 @@ public class BuildMipmap {
dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes );
}
break;
- case( GL2.GL_INT ):
+ case( GL2ES2.GL_INT ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractSInt(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1479,7 +1485,7 @@ public class BuildMipmap {
dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes );
}
break;
- case( GL2.GL_FLOAT ):
+ case( GL.GL_FLOAT ):
if( depth > 1 ) {
HalveImage.halveImage3D( cmpts, new ExtractFloat(), width, height, depth,
usersImage, dstImage, elementSize, groupSize, rowSize,
@@ -1489,51 +1495,51 @@ public class BuildMipmap {
dstImage.asFloatBuffer(), elementSize, rowSize, groupSize, myswapBytes );
}
break;
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
HalveImage.halveImagePackedPixel3D( 3, new Extract332(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
HalveImage.halveImagePackedPixel3D( 3, new Extract233rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
HalveImage.halveImagePackedPixel3D( 3, new Extract565(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
HalveImage.halveImagePackedPixel3D( 3, new Extract565rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
HalveImage.halveImagePackedPixel3D( 4, new Extract4444(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
HalveImage.halveImagePackedPixel3D( 4, new Extract4444rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
HalveImage.halveImagePackedPixel3D( 4, new Extract5551(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
HalveImage.halveImagePackedPixel3D( 4, new Extract1555rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
HalveImage.halveImagePackedPixel3D( 4, new Extract8888(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
HalveImage.halveImagePackedPixel3D( 4, new Extract8888rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
HalveImage.halveImagePackedPixel3D( 4, new Extract1010102(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
HalveImage.halveImagePackedPixel3D( 4, new Extract2101010rev(), width, height, depth, usersImage,
dstImage, elementSize, rowSize, imageSize, myswapBytes );
break;
@@ -1541,11 +1547,11 @@ public class BuildMipmap {
assert( false );
break;
}
-
+
tempImage = srcImage;
srcImage = dstImage;
dstImage = tempImage;
-
+
if( newWidth > 1 ) {
newWidth /= 2;
rowSize /= 2;
@@ -1563,22 +1569,22 @@ public class BuildMipmap {
0, format, type, usersImage );
}
}
- gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
- gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
- gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
- gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
- gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+ gl.glPixelStorei( GL.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+ gl.glPixelStorei( GL2ES2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+ gl.glPixelStorei( GL2GL3.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+ gl.glPixelStorei( GL2ES3.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
return( 0 );
}
private static final int TARGA_HEADER_SIZE = 18;
- private static void writeTargaFile(String filename, ByteBuffer data,
- int width, int height) {
+ private static void writeTargaFile(final String filename, final ByteBuffer data,
+ final int width, final int height) {
try {
- FileOutputStream fos = new FileOutputStream(new File(filename));
- ByteBuffer header = ByteBuffer.allocateDirect(TARGA_HEADER_SIZE);
+ final FileOutputStream fos = new FileOutputStream(new File(filename));
+ final ByteBuffer header = ByteBuffer.allocateDirect(TARGA_HEADER_SIZE);
header.put(0, (byte) 0).put(1, (byte) 0);
header.put(2, (byte) 2); // uncompressed type
header.put(12, (byte) (width & 0xFF)); // width
@@ -1590,7 +1596,7 @@ public class BuildMipmap {
fos.write(data.array());
data.clear();
fos.close();
- } catch (IOException e) {
+ } catch (final IOException e) {
e.printStackTrace();
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract.java
index a564269fb..0eee9bf32 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1010102.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1010102.java
index 10ea1d729..fe9c15e60 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1010102.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1010102.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,42 +51,44 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class Extract1010102 implements Extract {
-
+
/** Creates a new instance of Extract1010102 */
public Extract1010102() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
long uint = 0;
-
+
if( isSwap ) {
uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() );
} else {
uint = 0x00000000FFFFFFFF & packedPixel.getInt();
}
-
+
// 11111111,11000000,00000000,00000000 == 0xFFC00000
// 00000000,00111111,11110000,00000000 == 0x003F0000
// 00000000,00000000,00001111,11111100 == 0x00000FFC
// 00000000,00000000,00000000,00000011 == 0x00000003
-
- extractComponents[0] = (float)( ( uint & 0xFFC00000 ) >> 22 ) / 1023.0f;
- extractComponents[1] = (float)( ( uint & 0x003FF000 ) >> 12 ) / 1023.0f;
- extractComponents[2] = (float)( ( uint & 0x00000FFC ) >> 2 ) / 1023.0f;
- extractComponents[3] = (float)( ( uint & 0x00000003 ) ) / 3.0f;
+
+ extractComponents[0] = ( ( uint & 0xFFC00000 ) >> 22 ) / 1023.0f;
+ extractComponents[1] = ( ( uint & 0x003FF000 ) >> 12 ) / 1023.0f;
+ extractComponents[2] = ( ( uint & 0x00000FFC ) >> 2 ) / 1023.0f;
+ extractComponents[3] = ( ( uint & 0x00000003 ) ) / 3.0f;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 11110000,00000000 == 0xF000
// 00001111,00000000 == 0x0F00
// 00000000,11110000 == 0x00F0
// 00000000,00001111 == 0x000F
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
long uint = (((int)((shoveComponents[0] * 1023) + 0.5f) << 22) & 0xFFC00000 );
uint |= (((int)((shoveComponents[1] * 1023) + 0.5f) << 12) & 0x003FF000 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1555rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1555rev.java
index 1234da5f8..d619502be 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1555rev.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1555rev.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,42 +51,44 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class Extract1555rev implements Extract {
-
+
/** Creates a new instance of Extract1555rev */
public Extract1555rev() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
int ushort = 0;
-
+
if( isSwap ) {
ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
} else {
ushort = 0x0000FFFF & packedPixel.getShort();
}
-
+
// 00000000,00011111 == 0x001F
// 00000011,11100000 == 0x03E0
// 01111100,00000000 == 0x7C00
// 10000000,00000000 == 0x8000
-
- extractComponents[0] = (float)( ( ushort & 0x001F ) ) / 31.0f;
- extractComponents[1] = (float)( ( ushort & 0x003E ) >> 5 ) / 31.0f;
- extractComponents[2] = (float)( ( ushort & 0x7C00 ) >> 10) / 31.0f;
- extractComponents[3] = (float)( ( ushort & 0x8000 ) >> 15);
+
+ extractComponents[0] = ( ( ushort & 0x001F ) ) / 31.0f;
+ extractComponents[1] = ( ( ushort & 0x003E ) >> 5 ) / 31.0f;
+ extractComponents[2] = ( ( ushort & 0x7C00 ) >> 10) / 31.0f;
+ extractComponents[3] = ( ushort & 0x8000 ) >> 15;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 00000000,00011111 == 0x001F
// 00000011,11100000 == 0x03E0
// 01111100,00000000 == 0x7C00
// 10000000,00000000 == 0x8000
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) ) & 0x0000001F );
ushort |= (((int)((shoveComponents[1] * 31) + 0.5f) << 5) & 0x000003E0 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract2101010rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract2101010rev.java
index 226254f99..9d00badcb 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract2101010rev.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract2101010rev.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,42 +51,44 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class Extract2101010rev implements Extract {
-
+
/** Creates a new instance of Extract2101010 */
public Extract2101010rev() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
long uint = 0;
-
+
if( isSwap ) {
uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() );
} else {
uint = 0x00000000FFFFFFFF & packedPixel.getInt();
}
-
+
// 11111111,11000000,00000000,00000000 == 0xFFC00000
// 00000000,00111111,11110000,00000000 == 0x003F0000
// 00000000,00000000,00001111,11111100 == 0x00000FFC
// 00000000,00000000,00000000,00000011 == 0x00000003
-
- extractComponents[0] = (float)( ( uint & 0x000003FF ) ) / 1023.0f;
- extractComponents[1] = (float)( ( uint & 0x000FFC00 ) >> 10 ) / 1023.0f;
- extractComponents[2] = (float)( ( uint & 0x3FF00000 ) >> 20 ) / 1023.0f;
- extractComponents[3] = (float)( ( uint & 0xC0000000 ) >> 30 ) / 3.0f;
+
+ extractComponents[0] = ( ( uint & 0x000003FF ) ) / 1023.0f;
+ extractComponents[1] = ( ( uint & 0x000FFC00 ) >> 10 ) / 1023.0f;
+ extractComponents[2] = ( ( uint & 0x3FF00000 ) >> 20 ) / 1023.0f;
+ extractComponents[3] = ( ( uint & 0xC0000000 ) >> 30 ) / 3.0f;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 11110000,00000000 == 0xF000
// 00001111,00000000 == 0x0F00
// 00000000,11110000 == 0x00F0
// 00000000,00001111 == 0x000F
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
long uint = (((int)((shoveComponents[0] * 1023) + 0.5f) ) & 0x000003FF );
uint |= (((int)((shoveComponents[1] * 1023) + 0.5f) << 10) & 0x000FFC00 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract233rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract233rev.java
index 9fa2a3a54..3bc797518 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract233rev.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract233rev.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,30 +51,32 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class Extract233rev implements Extract {
-
+
/** Creates a new instance of Extract223rev */
public Extract233rev() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
// 11100000 == 0xe0
// 00011100 == 0x1c
// 00000011 == 0x03
- byte ubyte = packedPixel.get();
- extractComponents[0] = (float)((ubyte & 0x07) ) / 7.0f;
- extractComponents[1] = (float)((ubyte & 0x38) >> 3) / 7.0f;
- extractComponents[2] = (float)((ubyte & 0xC0) >> 6) / 3.0f;
+ final byte ubyte = packedPixel.get();
+ extractComponents[0] = ((ubyte & 0x07) ) / 7.0f;
+ extractComponents[1] = ((ubyte & 0x38) >> 3) / 7.0f;
+ extractComponents[2] = ((ubyte & 0xC0) >> 6) / 3.0f;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 11100000 == 0xE0
// 00011100 == 0x1C
// 00000011 == 0x03
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
byte b = (byte)( ( (int)( ( shoveComponents[0] * 7 ) + 0.5f ) ) & 0x07 );
b |= (byte)( ( (int)( ( shoveComponents[1] * 7 ) + 0.5f ) << 3 ) & 0x38 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract332.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract332.java
index 92d141be5..93983f1d7 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract332.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract332.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,30 +51,32 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class Extract332 implements Extract {
-
+
/** Creates a new instance of Extract332 */
public Extract332() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
// 11100000 == 0xe0
// 00011100 == 0x1c
// 00000011 == 0x03
- byte ubyte = packedPixel.get();
- extractComponents[0] = (float)((ubyte & 0xe0) >> 5) / 7.0f;
- extractComponents[1] = (float)((ubyte & 0x1c) >> 2) / 7.0f;
- extractComponents[2] = (float)((ubyte & 0x03)) / 3.0f;
+ final byte ubyte = packedPixel.get();
+ extractComponents[0] = ((ubyte & 0xe0) >> 5) / 7.0f;
+ extractComponents[1] = ((ubyte & 0x1c) >> 2) / 7.0f;
+ extractComponents[2] = ((ubyte & 0x03)) / 3.0f;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 11100000 == 0xE0
// 00011100 == 0x1C
// 00000011 == 0x03
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
byte b = (byte)( ( (int)( ( shoveComponents[0] * 7 ) + 0.5f ) << 5 ) & 0xE0 );
b |= (byte)( ( (int)( ( shoveComponents[1] * 7 ) + 0.5f ) << 2 ) & 0x1C );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444.java
index af99d154c..323ca7f1a 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,41 +51,43 @@ import java.nio.*;
* @author Administrator
*/
public class Extract4444 implements Extract {
-
+
/** Creates a new instance of Extract4444 */
public Extract4444() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
int ushort = 0;
-
+
if( isSwap ) {
ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
} else {
ushort = 0x0000FFFF & packedPixel.getShort();
}
-
+
// 11110000,00000000 == 0xF000
// 00001111,00000000 == 0x0F00
// 00000000,11110000 == 0x00F0
// 00000000,00001111 == 0x000F
-
- extractComponents[0] = (float)( ( ushort & 0xF000 ) >> 12 ) / 15.0f;
- extractComponents[1] = (float)( ( ushort & 0x0F00 ) >> 8 ) / 15.0f;
- extractComponents[2] = (float)( ( ushort & 0x00F0 ) >> 4 ) / 15.0f;
- extractComponents[3] = (float)( ( ushort & 0x000F ) ) / 15.0f;
+
+ extractComponents[0] = ( ( ushort & 0xF000 ) >> 12 ) / 15.0f;
+ extractComponents[1] = ( ( ushort & 0x0F00 ) >> 8 ) / 15.0f;
+ extractComponents[2] = ( ( ushort & 0x00F0 ) >> 4 ) / 15.0f;
+ extractComponents[3] = ( ( ushort & 0x000F ) ) / 15.0f;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 11110000,00000000 == 0xF000
// 00001111,00000000 == 0x0F00
// 00000000,11110000 == 0x00F0
// 00000000,00001111 == 0x000F
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
int ushort = (((int)((shoveComponents[0] * 15) + 0.5f) << 12) & 0x0000F000 );
ushort |= (((int)((shoveComponents[1] * 15) + 0.5f) << 8) & 0x00000F00 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444rev.java
index e5bce60d8..267286519 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444rev.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444rev.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,42 +51,44 @@ import java.nio.*;
* @author Administrator
*/
public class Extract4444rev implements Extract {
-
+
/** Creates a new instance of Extract4444rev */
public Extract4444rev() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
int ushort = 0;
-
+
if( isSwap ) {
ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
} else {
ushort = 0x0000FFFF & packedPixel.getShort();
}
-
+
// 00000000,00001111 == 0x000F
// 00000000,11110000 == 0x00F0
// 00001111,00000000 == 0x0F00
// 11110000,00000000 == 0xF000
-
- extractComponents[0] = (float)( ( ushort & 0x000F ) ) / 15.0f;
- extractComponents[1] = (float)( ( ushort & 0x00F0 ) >> 4 ) / 15.0f;
- extractComponents[2] = (float)( ( ushort & 0x0F00 ) >> 8 ) / 15.0f;
- extractComponents[3] = (float)( ( ushort & 0xF000 ) >> 12 ) / 15.0f;
+
+ extractComponents[0] = ( ( ushort & 0x000F ) ) / 15.0f;
+ extractComponents[1] = ( ( ushort & 0x00F0 ) >> 4 ) / 15.0f;
+ extractComponents[2] = ( ( ushort & 0x0F00 ) >> 8 ) / 15.0f;
+ extractComponents[3] = ( ( ushort & 0xF000 ) >> 12 ) / 15.0f;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 11110000,00000000 == 0xF000
// 00001111,00000000 == 0x0F00
// 00000000,11110000 == 0x00F0
// 00000000,00001111 == 0x000F
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
int ushort = (((int)((shoveComponents[0] * 15) + 0.5f) ) & 0x0000000F );
ushort |= (((int)((shoveComponents[1] * 15) + 0.5f) << 4) & 0x000000F0 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract5551.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract5551.java
index 5c383103e..ee33ca7c1 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract5551.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract5551.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,42 +51,44 @@ import java.nio.*;
* @author Administrator
*/
public class Extract5551 implements Extract {
-
+
/** Creates a new instance of Extract5551 */
public Extract5551() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
int ushort = 0;
-
+
if( isSwap ) {
ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
} else {
ushort = 0x0000FFFF & packedPixel.getShort();
}
-
+
// 11111000,00000000 == 0xF800
// 00000111,11000000 == 0x07C0
// 00000000,00111110 == 0x003E
// 00000000,00000001 == 0x0001
-
- extractComponents[0] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f;
- extractComponents[1] = (float)( ( ushort & 0x00F0 ) >> 6 ) / 31.0f;
- extractComponents[2] = (float)( ( ushort & 0x0F00 ) >> 1 ) / 31.0f;
- extractComponents[3] = (float)( ( ushort & 0xF000 ) );
+
+ extractComponents[0] = ( ( ushort & 0xF800 ) >> 11 ) / 31.0f;
+ extractComponents[1] = ( ( ushort & 0x00F0 ) >> 6 ) / 31.0f;
+ extractComponents[2] = ( ( ushort & 0x0F00 ) >> 1 ) / 31.0f;
+ extractComponents[3] = ( ( ushort & 0xF000 ) );
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 11110000,00000000 == 0xF000
// 00001111,00000000 == 0x0F00
// 00000000,11110000 == 0x00F0
// 00000000,00001111 == 0x000F
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) << 11) & 0x0000F800 );
ushort |= (((int)((shoveComponents[1] * 31) + 0.5f) << 6) & 0x000007C0 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565.java
index f6193dd2d..d63943a2e 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,38 +51,40 @@ import java.nio.*;
* @author Administrator
*/
public class Extract565 implements Extract {
-
+
/** Creates a new instance of Extract565 */
public Extract565() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
int ushort = 0;
-
+
if( isSwap ) {
ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
} else {
ushort = 0x0000FFFF & packedPixel.getShort();
}
-
+
// 11111000,00000000 == 0xF800
// 00000111,11100000 == 0x07E0
// 00000000,00111111 == 0x001F
-
- extractComponents[0] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f;
- extractComponents[1] = (float)( ( ushort & 0x07E0 ) >> 5 ) / 63.0f;
- extractComponents[2] = (float)( ( ushort & 0x001F ) ) / 31.0f;
+
+ extractComponents[0] = ( ( ushort & 0xF800 ) >> 11 ) / 31.0f;
+ extractComponents[1] = ( ( ushort & 0x07E0 ) >> 5 ) / 63.0f;
+ extractComponents[2] = ( ( ushort & 0x001F ) ) / 31.0f;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 11111000,00000000 == 0xF800
// 00000111,11100000 == 0x07E0
// 00000000,00111111 == 0x001F
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) << 11) & 0x0000F800 );
ushort |= (((int)((shoveComponents[1] * 63) + 0.5f) << 5) & 0x000007E0 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565rev.java
index 2e455adfa..cfea71487 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565rev.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565rev.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,38 +51,40 @@ import java.nio.*;
* @author Administrator
*/
public class Extract565rev implements Extract {
-
+
/** Creates a new instance of Extract565rev */
public Extract565rev() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
int ushort = 0;
-
+
if( isSwap ) {
ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
} else {
ushort = 0x0000FFFF & packedPixel.getShort();
}
-
+
// 00000000,00011111 == 0x001F
// 00000111,11100000 == 0x07E0
// 11111000,00000000 == 0xF800
-
- extractComponents[0] = (float)( ( ushort & 0x001F ) ) / 31.0f;
- extractComponents[1] = (float)( ( ushort & 0x07E0 ) >> 5 ) / 63.0f;
- extractComponents[2] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f;
+
+ extractComponents[0] = ( ( ushort & 0x001F ) ) / 31.0f;
+ extractComponents[1] = ( ( ushort & 0x07E0 ) >> 5 ) / 63.0f;
+ extractComponents[2] = ( ( ushort & 0xF800 ) >> 11 ) / 31.0f;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 00000000,00111111 == 0x001F
// 00000111,11100000 == 0x07E0
// 11111000,00000000 == 0xF800
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) ) & 0x0000001F );
ushort |= (((int)((shoveComponents[1] * 63) + 0.5f) << 5) & 0x000007E0 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888.java
index 137fa3c21..f6fe92c82 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,42 +51,44 @@ import java.nio.*;
* @author Administrator
*/
public class Extract8888 implements Extract {
-
+
/** Creates a new instance of Extract8888 */
public Extract8888() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
long uint = 0;
-
+
if( isSwap ) {
uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() );
} else {
uint = 0x00000000FFFFFFFF & packedPixel.getInt();
}
-
+
// 11111000,00000000 == 0xF800
// 00000111,11000000 == 0x07C0
// 00000000,00111110 == 0x003E
// 00000000,00000001 == 0x0001
-
- extractComponents[0] = (float)( ( uint & 0xFF000000 ) >> 24 ) / 255.0f;
- extractComponents[1] = (float)( ( uint & 0x00FF0000 ) >> 16 ) / 255.0f;
- extractComponents[2] = (float)( ( uint & 0x0000FF00 ) >> 8 ) / 255.0f;
- extractComponents[3] = (float)( ( uint & 0x000000FF ) ) / 255.0f;
+
+ extractComponents[0] = ( ( uint & 0xFF000000 ) >> 24 ) / 255.0f;
+ extractComponents[1] = ( ( uint & 0x00FF0000 ) >> 16 ) / 255.0f;
+ extractComponents[2] = ( ( uint & 0x0000FF00 ) >> 8 ) / 255.0f;
+ extractComponents[3] = ( ( uint & 0x000000FF ) ) / 255.0f;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 11110000,00000000 == 0xF000
// 00001111,00000000 == 0x0F00
// 00000000,11110000 == 0x00F0
// 00000000,00001111 == 0x000F
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
long uint = (((int)((shoveComponents[0] * 255) + 0.5f) << 24) & 0xFF000000 );
uint |= (((int)((shoveComponents[1] * 255) + 0.5f) << 16) & 0x00FF0000 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888rev.java
index 2ac942c84..942f6d88a 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888rev.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888rev.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,42 +51,44 @@ import java.nio.*;
* @author Administrator
*/
public class Extract8888rev implements Extract {
-
+
/** Creates a new instance of Extract8888rev */
public Extract8888rev() {
}
-
- public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+
+ @Override
+ public void extract( final boolean isSwap, final ByteBuffer packedPixel, final float[] extractComponents ) {
long uint = 0;
-
+
if( isSwap ) {
uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() );
} else {
uint = 0x00000000FFFFFFFF & packedPixel.getInt();
}
-
+
// 11111000,00000000 == 0xF800
// 00000111,11000000 == 0x07C0
// 00000000,00111110 == 0x003E
// 00000000,00000001 == 0x0001
-
- extractComponents[0] = (float)( ( uint & 0x000000FF ) ) / 255.0f;
- extractComponents[1] = (float)( ( uint & 0x0000FF00 ) >> 8 ) / 255.0f;
- extractComponents[2] = (float)( ( uint & 0x00FF0000 ) >> 16 ) / 255.0f;
- extractComponents[3] = (float)( ( uint & 0xFF000000 ) >> 24 ) / 255.0f;
+
+ extractComponents[0] = ( ( uint & 0x000000FF ) ) / 255.0f;
+ extractComponents[1] = ( ( uint & 0x0000FF00 ) >> 8 ) / 255.0f;
+ extractComponents[2] = ( ( uint & 0x00FF0000 ) >> 16 ) / 255.0f;
+ extractComponents[3] = ( ( uint & 0xFF000000 ) >> 24 ) / 255.0f;
}
-
- public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+
+ @Override
+ public void shove( final float[] shoveComponents, final int index, final ByteBuffer packedPixel ) {
// 11110000,00000000 == 0xF000
// 00001111,00000000 == 0x0F00
// 00000000,11110000 == 0x00F0
// 00000000,00001111 == 0x000F
-
+
assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
-
+
// due to limited precision, need to round before shoving
long uint = (((int)((shoveComponents[0] * 255) + 0.5f) ) & 0x000000FF );
uint |= (((int)((shoveComponents[1] * 255) + 0.5f) << 8) & 0x0000FF00 );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractFloat.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractFloat.java
index 52c2191b9..09d70e492 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractFloat.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractFloat.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,12 +51,13 @@ import java.nio.*;
* @author Administrator
*/
public class ExtractFloat implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractFloat */
public ExtractFloat() {
}
-
- public double extract( boolean isSwap, ByteBuffer data ) {
+
+ @Override
+ public double extract( final boolean isSwap, final ByteBuffer data ) {
float f = 0;
if( isSwap ) {
f = Mipmap.GLU_SWAP_4_BYTES( data.getInt() );
@@ -66,8 +67,9 @@ public class ExtractFloat implements ExtractPrimitive {
assert( f <= 1.0f );
return( f );
}
-
- public void shove( double value, int index, ByteBuffer data ) {
+
+ @Override
+ public void shove( final double value, final int index, final ByteBuffer data ) {
assert(0.0 <= value && value < 1.0);
data.asFloatBuffer().put( index, (float)value );
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractPrimitive.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractPrimitive.java
index 926096649..a44fb9508 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractPrimitive.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractPrimitive.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSByte.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSByte.java
index 2e1a9a0a6..76c34330f 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSByte.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSByte.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,18 +51,18 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class ExtractSByte implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractUByte */
public ExtractSByte() {
}
-
- public double extract( boolean isSwap, ByteBuffer sbyte ) {
- byte b = sbyte.get();
- assert( b <= 127 );
- return( b );
+
+ @Override
+ public double extract( final boolean isSwap, final ByteBuffer sbyte ) {
+ return sbyte.get(); // <= 127
}
-
- public void shove( double value, int index, ByteBuffer data ) {
+
+ @Override
+ public void shove( final double value, final int index, final ByteBuffer data ) {
data.position( index );
data.put( (byte)value );
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSInt.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSInt.java
index ca80747c4..9532fdade 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSInt.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSInt.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,12 +51,13 @@ import java.nio.*;
* @author Administrator
*/
public class ExtractSInt implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractSInt */
public ExtractSInt() {
}
-
- public double extract( boolean isSwap, ByteBuffer uint ) {
+
+ @Override
+ public double extract( final boolean isSwap, final ByteBuffer uint ) {
int i = 0;
if( isSwap ) {
i = Mipmap.GLU_SWAP_4_BYTES( uint.getInt() );
@@ -66,10 +67,11 @@ public class ExtractSInt implements ExtractPrimitive {
assert( i <= 0x7FFFFFFF );
return( i );
}
-
- public void shove( double value, int index, ByteBuffer data ) {
+
+ @Override
+ public void shove( final double value, final int index, final ByteBuffer data ) {
assert(0.0 <= value && value < Integer.MAX_VALUE);
- IntBuffer ib = data.asIntBuffer();
+ final IntBuffer ib = data.asIntBuffer();
ib.position( index );
ib.put( (int)value );
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java
index 979c3b449..6e14f89c0 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,12 +51,13 @@ import java.nio.*;
* @author Administrator
*/
public class ExtractSShort implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractSShort */
public ExtractSShort() {
}
-
- public double extract( boolean isSwap, ByteBuffer ushort ) {
+
+ @Override
+ public double extract( final boolean isSwap, final ByteBuffer ushort ) {
short s = 0;
if( isSwap ) {
s = Mipmap.GLU_SWAP_2_BYTES( ushort.getShort() );
@@ -66,10 +67,11 @@ public class ExtractSShort implements ExtractPrimitive {
assert( s <= 32767 );
return( s );
}
-
- public void shove( double value, int index, ByteBuffer data ) {
+
+ @Override
+ public void shove( final double value, final int index, final ByteBuffer data ) {
assert(0.0 <= value && value < 32768.0);
- ShortBuffer sb = data.asShortBuffer();
+ final ShortBuffer sb = data.asShortBuffer();
sb.position( index );
sb.put( (short)value );
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java
index 4d14212ab..d9db0019b 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,18 +51,20 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class ExtractUByte implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractUByte */
public ExtractUByte() {
}
-
- public double extract( boolean isSwap, ByteBuffer ubyte ) {
- int i = 0x000000FF & ubyte.get();
+
+ @Override
+ public double extract( final boolean isSwap, final ByteBuffer ubyte ) {
+ final int i = 0x000000FF & ubyte.get();
assert( i <= 255 );
return( i );
}
-
- public void shove( double value, int index, ByteBuffer data ) {
+
+ @Override
+ public void shove( final double value, final int index, final ByteBuffer data ) {
assert(0.0 <= value && value < 256.0);
data.position( index );
data.put( (byte)value );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java
index c088ca301..3e4ad41c2 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,12 +51,13 @@ import java.nio.*;
* @author Administrator
*/
public class ExtractUInt implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractUInt */
public ExtractUInt() {
}
-
- public double extract( boolean isSwap, ByteBuffer uint ) {
+
+ @Override
+ public double extract( final boolean isSwap, final ByteBuffer uint ) {
long i = 0;
if( isSwap ) {
i = 0xFFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( uint.getInt() );
@@ -66,10 +67,11 @@ public class ExtractUInt implements ExtractPrimitive {
assert( i <= 0xFFFFFFFF );
return( i );
}
-
- public void shove( double value, int index, ByteBuffer data ) {
+
+ @Override
+ public void shove( final double value, final int index, final ByteBuffer data ) {
assert(0.0 <= value && value < 0xFFFFFFFF);
- IntBuffer ib = data.asIntBuffer();
+ final IntBuffer ib = data.asIntBuffer();
ib.position( index );
ib.put( (int)value );
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java
index 81db60f0f..b121c1054 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,12 +51,13 @@ import java.nio.*;
* @author Administrator
*/
public class ExtractUShort implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtracUShort */
public ExtractUShort() {
}
-
- public double extract( boolean isSwap, ByteBuffer ushort ) {
+
+ @Override
+ public double extract( final boolean isSwap, final ByteBuffer ushort ) {
int i = 0;
if( isSwap ) {
i = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( ushort.getShort() );
@@ -66,10 +67,11 @@ public class ExtractUShort implements ExtractPrimitive {
assert( i <= 65535 );
return( i );
}
-
- public void shove( double value, int index, ByteBuffer data ) {
+
+ @Override
+ public void shove( final double value, final int index, final ByteBuffer data ) {
assert(0.0 <= value && value < 65536.0);
- ShortBuffer sb = data.asShortBuffer();
+ final ShortBuffer sb = data.asShortBuffer();
sb.position( index );
sb.put( (short)value );
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java
index 7549044ba..95ce86a5b 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -52,23 +52,23 @@ import java.nio.*;
* @author Administrator
*/
public class HalveImage {
-
+
private static final int BOX2 = 2;
private static final int BOX4 = 4;
private static final int BOX8 = 8;
-
- public static void halveImage( int components, int width, int height,
- ShortBuffer datain, ShortBuffer dataout ) {
+
+ public static void halveImage( final int components, final int width, final int height,
+ final ShortBuffer datain, final ShortBuffer dataout ) {
int i, j, k;
int newwidth, newheight;
int delta;
int t = 0;
short temp = 0;
-
+
newwidth = width / 2;
newheight = height /2;
delta = width * components;
-
+
// Piece of cake
for( i = 0; i < newheight; i++ ) {
for( j = 0; j < newwidth; j++ ) {
@@ -91,27 +91,27 @@ public class HalveImage {
t += delta;
}
}
-
- public static void halveImage_ubyte( int components, int width, int height,
- ByteBuffer datain, ByteBuffer dataout,
- int element_size, int ysize, int group_size ) {
+
+ public static void halveImage_ubyte( final int components, final int width, final int height,
+ final ByteBuffer datain, final ByteBuffer dataout,
+ final int element_size, final int ysize, final int group_size ) {
int i, j, k;
int newwidth, newheight;
int s;
int t;
-
+
// Handle case where there is only 1 column/row
if( width == 1 || height == 1 ) {
assert( !( width == 1 && height == 1 ) ); // can't be 1x1
halve1Dimage_ubyte( components, width, height, datain, dataout, element_size, ysize, group_size );
return;
}
-
+
newwidth = width / 2;
newheight = height / 2;
s = 0;
t = 0;
-
+
int temp = 0;
// piece of cake
for( i = 0; i < newheight; i++ ) {
@@ -133,24 +133,24 @@ public class HalveImage {
t += ysize;
}
}
-
- public static void halve1Dimage_ubyte( int components, int width, int height,
- ByteBuffer datain, ByteBuffer dataout,
- int element_size, int ysize, int group_size ) {
+
+ public static void halve1Dimage_ubyte( final int components, final int width, final int height,
+ final ByteBuffer datain, final ByteBuffer dataout,
+ final int element_size, final int ysize, final int group_size ) {
int halfWidth = width / 2;
int halfHeight = height / 2;
int src = 0;
int dest = 0;
int jj;
int temp = 0;
-
+
assert( width == 1 || height == 1 ); // Must be 1D
assert( width != height ); // can't be square
-
+
if( height == 1 ) { // 1 row
assert( width != 1 ); // widthxheight can't be 1x1
halfHeight = 1;
-
+
for( jj = 0; jj < halfWidth; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
@@ -161,7 +161,7 @@ public class HalveImage {
temp /= 2;
dataout.put( (byte)temp );
/*
- dataout.setByte( (byte)(((0x000000FF & datain.setIndexInBytes(src).getByte()) +
+ dataout.setByte( (byte)(((0x000000FF & datain.setIndexInBytes(src).getByte()) +
(0x000000FF & datain.setIndexInBytes( src + group_size ).getByte())) / 2 ) );
*/
src += element_size;
@@ -170,10 +170,10 @@ public class HalveImage {
}
src += group_size; // skip to next 2
}
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
src += padBytes; // for assertion only
} else if( width == 1 ) { // 1 column
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
assert( height != 1 );
halfWidth = 1;
// one vertical column with possible pad bytes per row
@@ -188,7 +188,7 @@ public class HalveImage {
temp /= 2;
dataout.put( (byte)temp );
/*
- dataout.setByte( (byte)(((0x000000FF & datain.setIndexInBytes(src).getByte()) +
+ dataout.setByte( (byte)(((0x000000FF & datain.setIndexInBytes(src).getByte()) +
(0x000000FF & datain.setIndexInBytes(src + ysize).getByte()) ) / 2 ) );
*/
src += element_size;
@@ -202,16 +202,16 @@ public class HalveImage {
assert( src == ysize * height );
assert( dest == components * element_size * halfWidth * halfHeight );
}
-
- public static void halveImage_byte( int components, int width, int height,
- ByteBuffer datain, ByteBuffer dataout, int element_size,
- int ysize, int group_size ) {
+
+ public static void halveImage_byte( final int components, final int width, final int height,
+ final ByteBuffer datain, final ByteBuffer dataout, final int element_size,
+ final int ysize, final int group_size ) {
int i, j, k;
int newwidth, newheight;
- int s = 0;
+ final int s = 0;
int t = 0;
byte temp = (byte)0;
-
+
// handle case where there is only 1 column
if( width == 1 || height == 1 ) {
assert( !( width == 1 && height == 1 ) );
@@ -219,10 +219,10 @@ public class HalveImage {
ysize, group_size );
return;
}
-
+
newwidth = width / 2;
newheight = height / 2;
-
+
for( i = 0; i < newheight; i++ ) {
for( j = 0; j < newwidth; j++ ) {
for( k = 0; k < components; k++ ) {
@@ -244,24 +244,24 @@ public class HalveImage {
t += ysize;
}
}
-
- public static void halve1Dimage_byte( int components, int width, int height,
- ByteBuffer datain, ByteBuffer dataout,
- int element_size, int ysize, int group_size ) {
+
+ public static void halve1Dimage_byte( final int components, final int width, final int height,
+ final ByteBuffer datain, final ByteBuffer dataout,
+ final int element_size, final int ysize, final int group_size ) {
int halfWidth = width / 2;
int halfHeight = width / 2;
int src = 0;
int dest = 0;
int jj;
byte temp = (byte)0;
-
+
assert( width == 1 || height == 1 ); // must be 1D
assert( width != height ); // can't be square
-
+
if( height == 1 ) { // 1 row
assert( width != 1 ); // widthxheight can't be 1
halfHeight = 1;
-
+
for( jj = 0; jj < halfWidth; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
@@ -276,15 +276,15 @@ public class HalveImage {
}
src += group_size; // skip to next 2
}
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
src += padBytes; // for assert only
} else if( width == 1 ) { // 1 column
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
assert( height != 1 ); // widthxheight can't be 1
halfWidth = 1;
// one vertical column with possible pad bytes per row
// average two at a time
-
+
for( jj = 0; jj < halfHeight; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
@@ -303,13 +303,14 @@ public class HalveImage {
}
assert( dest == components * element_size * halfWidth * halfHeight );
}
-
- public static void halveImage_ushort( int components, int width, int height,
- ByteBuffer datain, ShortBuffer dataout, int element_size,
- int ysize, int group_size, boolean myswap_bytes ) {
- int i, j, k, l;
+
+ public static void halveImage_ushort( final int components, final int width, final int height,
+ final ByteBuffer datain, final ShortBuffer dataout, final int element_size,
+ final int ysize, final int group_size, final boolean myswap_bytes ) {
+ int i, j, k;
+ final int l;
int newwidth, newheight;
- int s = 0;
+ final int s = 0;
int t = 0;
int temp = 0;
// handle case where there is only 1 column/row
@@ -319,10 +320,10 @@ public class HalveImage {
ysize, group_size, myswap_bytes );
return;
}
-
+
newwidth = width / 2;
newheight = height / 2;
-
+
// Piece of cake
if( !myswap_bytes ) {
for( i = 0; i < newheight; i++ ) {
@@ -364,27 +365,27 @@ public class HalveImage {
}
}
}
-
- public static void halve1Dimage_ushort( int components, int width, int height,
- ByteBuffer datain, ShortBuffer dataout, int element_size,
- int ysize, int group_size, boolean myswap_bytes ) {
+
+ public static void halve1Dimage_ushort( final int components, final int width, final int height,
+ final ByteBuffer datain, final ShortBuffer dataout, final int element_size,
+ final int ysize, final int group_size, final boolean myswap_bytes ) {
int halfWidth = width / 2;
int halfHeight = height / 2;
int src = 0;
int dest = 0;
int jj;
-
+
assert( width == 1 || height == 1 ); // must be 1D
assert( width != height ); // can't be square
-
+
if( height == 1 ) { // 1 row
assert( width != 1 ); // widthxheight can't be 1
halfHeight = 1;
-
+
for( jj = 0; jj < halfWidth; jj++ ) {
int kk;
for( kk = 0; kk < halfHeight; kk++ ) {
- int[] ushort = new int[BOX2];
+ final int[] ushort = new int[BOX2];
if( myswap_bytes ) {
datain.position( src );
ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) );
@@ -402,19 +403,19 @@ public class HalveImage {
}
src += group_size; // skip to next 2
}
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
src += padBytes; // for assertion only
} else if( width == 1 ) { // 1 column
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
assert( height != 1 ); // widthxheight can't be 1
halfWidth = 1;
// one vertical column with possible pad bytes per row
// average two at a time
-
+
for( jj = 0; jj < halfHeight; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
- int[] ushort = new int[BOX2];
+ final int[] ushort = new int[BOX2];
if( myswap_bytes ) {
datain.position( src );
ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) );
@@ -437,13 +438,14 @@ public class HalveImage {
}
assert( dest == components * element_size * halfWidth * halfHeight );
}
-
- public static void halveImage_short( int components, int width, int height,
- ByteBuffer datain, ShortBuffer dataout, int element_size,
- int ysize, int group_size, boolean myswap_bytes ) {
- int i, j, k, l;
+
+ public static void halveImage_short( final int components, final int width, final int height,
+ final ByteBuffer datain, final ShortBuffer dataout, final int element_size,
+ final int ysize, final int group_size, final boolean myswap_bytes ) {
+ int i, j, k;
+ final int l;
int newwidth, newheight;
- int s = 0;
+ final int s = 0;
int t = 0;
short temp = (short)0;
// handle case where there is only 1 column/row
@@ -453,10 +455,10 @@ public class HalveImage {
ysize, group_size, myswap_bytes );
return;
}
-
+
newwidth = width / 2;
newheight = height / 2;
-
+
// Piece of cake
if( !myswap_bytes ) {
for( i = 0; i < newheight; i++ ) {
@@ -472,7 +474,7 @@ public class HalveImage {
temp += datain.getShort();
temp += 2;
temp /= 4;
- dataout.put( (short)temp );
+ dataout.put( temp );
t += element_size;
}
t += group_size;
@@ -483,8 +485,8 @@ public class HalveImage {
for( i = 0; i < newheight; i++ ) {
for( j = 0; j < newwidth; j++ ) {
for( k = 0; k < components; k++ ) {
- short b;
- int buf;
+ final short b;
+ final int buf;
datain.position( t );
temp = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
datain.position( t + group_size );
@@ -504,27 +506,27 @@ public class HalveImage {
}
}
}
-
- public static void halve1Dimage_short( int components, int width, int height,
- ByteBuffer datain, ShortBuffer dataout, int element_size, int ysize,
- int group_size, boolean myswap_bytes ) {
+
+ public static void halve1Dimage_short( final int components, final int width, final int height,
+ final ByteBuffer datain, final ShortBuffer dataout, final int element_size, final int ysize,
+ final int group_size, final boolean myswap_bytes ) {
int halfWidth = width / 2;
int halfHeight = height / 2;
int src = 0;
int dest = 0;
int jj;
-
+
assert( width == 1 || height == 1 ); // must be 1D
assert( width != height ); // can't be square
-
+
if( height == 1 ) { // 1 row
assert( width != 1 ); // can't be 1x1
halfHeight = 1;
-
+
for( jj = 0; jj < halfWidth; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
- short[] sshort = new short[BOX2];
+ final short[] sshort = new short[BOX2];
if( myswap_bytes ) {
datain.position( src );
sshort[0] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
@@ -542,19 +544,19 @@ public class HalveImage {
}
src += group_size; // skip to next 2
}
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
src += padBytes; // for assertion only
} else if( width == 1 ) {
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
assert( height != 1 );
halfWidth = 1;
// one vertical column with possible pad bytes per row
// average two at a time
-
+
for( jj = 0; jj < halfHeight; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
- short[] sshort = new short[BOX2];
+ final short[] sshort = new short[BOX2];
if( myswap_bytes ) {
datain.position( src );
sshort[0] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
@@ -577,16 +579,17 @@ public class HalveImage {
}
assert( dest == ( components * element_size * halfWidth * halfHeight ) );
}
-
- public static void halveImage_uint( int components, int width, int height,
- ByteBuffer datain, IntBuffer dataout, int element_size,
- int ysize, int group_size, boolean myswap_bytes ) {
- int i, j, k, l;
+
+ public static void halveImage_uint( final int components, final int width, final int height,
+ final ByteBuffer datain, final IntBuffer dataout, final int element_size,
+ final int ysize, final int group_size, final boolean myswap_bytes ) {
+ int i, j, k;
+ final int l;
int newwidth, newheight;
- int s = 0;
+ final int s = 0;
int t = 0;
double temp = 0;
-
+
// handle case where there is only 1 column/row
if( width == 1 || height == 1 ) {
assert( !( width == 1 && height == 1 ) ); // can't be 1x1
@@ -594,10 +597,10 @@ public class HalveImage {
ysize, group_size, myswap_bytes );
return;
}
-
+
newwidth = width / 2;
newheight = height / 2;
-
+
// Piece of cake
if( !myswap_bytes ) {
for( i = 0; i < newheight; i++ ) {
@@ -643,27 +646,27 @@ public class HalveImage {
}
}
}
-
- public static void halve1Dimage_uint( int components, int width, int height,
- ByteBuffer datain, IntBuffer dataout, int element_size, int ysize,
- int group_size, boolean myswap_bytes ) {
+
+ public static void halve1Dimage_uint( final int components, final int width, final int height,
+ final ByteBuffer datain, final IntBuffer dataout, final int element_size, final int ysize,
+ final int group_size, final boolean myswap_bytes ) {
int halfWidth = width / 2;
int halfHeight = height / 2;
int src = 0;
int dest = 0;
int jj;
-
+
assert( width == 1 || height == 1 ); // must be 1D
assert( width != height ); // can't be square
-
+
if( height == 1 ) { // 1 row
assert( width != 1 ); // widthxheight can't be 1
halfHeight = 1;
-
+
for( jj = 0; jj < halfWidth; jj++ ) {
int kk;
for( kk = 0; kk < halfHeight; kk++ ) {
- long[] uint = new long[BOX2];
+ final long[] uint = new long[BOX2];
if( myswap_bytes ) {
datain.position( src );
uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
@@ -681,19 +684,19 @@ public class HalveImage {
}
src += group_size; // skip to next 2
}
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
src += padBytes; // for assertion only
} else if( width == 1 ) { // 1 column
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
assert( height != 1 ); // widthxheight can't be 1
halfWidth = 1;
// one vertical column with possible pad bytes per row
// average two at a time
-
+
for( jj = 0; jj < halfHeight; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
- long[] uint = new long[BOX2];
+ final long[] uint = new long[BOX2];
if( myswap_bytes ) {
datain.position( src );
uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
@@ -716,16 +719,17 @@ public class HalveImage {
}
assert( dest == components * element_size * halfWidth * halfHeight );
}
-
- public static void halveImage_int( int components, int width, int height,
- ByteBuffer datain, IntBuffer dataout, int element_size,
- int ysize, int group_size, boolean myswap_bytes ) {
- int i, j, k, l;
+
+ public static void halveImage_int( final int components, final int width, final int height,
+ final ByteBuffer datain, final IntBuffer dataout, final int element_size,
+ final int ysize, final int group_size, final boolean myswap_bytes ) {
+ int i, j, k;
+ final int l;
int newwidth, newheight;
- int s = 0;
+ final int s = 0;
int t = 0;
int temp = 0;
-
+
// handle case where there is only 1 column/row
if( width == 1 || height == 1 ) {
assert( !( width == 1 && height == 1 ) ); // can't be 1x1
@@ -733,10 +737,10 @@ public class HalveImage {
ysize, group_size, myswap_bytes );
return;
}
-
+
newwidth = width / 2;
newheight = height / 2;
-
+
// Piece of cake
if( !myswap_bytes ) {
for( i = 0; i < newheight; i++ ) {
@@ -785,27 +789,27 @@ public class HalveImage {
}
}
}
-
- public static void halve1Dimage_int( int components, int width, int height,
- ByteBuffer datain, IntBuffer dataout, int element_size, int ysize,
- int group_size, boolean myswap_bytes ) {
+
+ public static void halve1Dimage_int( final int components, final int width, final int height,
+ final ByteBuffer datain, final IntBuffer dataout, final int element_size, final int ysize,
+ final int group_size, final boolean myswap_bytes ) {
int halfWidth = width / 2;
int halfHeight = height / 2;
int src = 0;
int dest = 0;
int jj;
-
+
assert( width == 1 || height == 1 ); // must be 1D
assert( width != height ); // can't be square
-
+
if( height == 1 ) { // 1 row
assert( width != 1 ); // can't be 1x1
halfHeight = 1;
-
+
for( jj = 0; jj < halfWidth; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
- long[] uint = new long[BOX2];
+ final long[] uint = new long[BOX2];
if( myswap_bytes ) {
datain.position( src );
uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
@@ -823,19 +827,19 @@ public class HalveImage {
}
src += group_size; // skip to next 2
}
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
src += padBytes; // for assertion only
} else if( width == 1 ) {
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
assert( height != 1 );
halfWidth = 1;
// one vertical column with possible pad bytes per row
// average two at a time
-
+
for( jj = 0; jj < halfHeight; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
- long[] uint = new long[BOX2];
+ final long[] uint = new long[BOX2];
if( myswap_bytes ) {
datain.position( src );
uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
@@ -858,13 +862,14 @@ public class HalveImage {
}
assert( dest == ( components * element_size * halfWidth * halfHeight ) );
}
-
- public static void halveImage_float( int components, int width, int height,
- ByteBuffer datain, FloatBuffer dataout, int element_size,
- int ysize, int group_size, boolean myswap_bytes ) {
- int i, j, k, l;
+
+ public static void halveImage_float( final int components, final int width, final int height,
+ final ByteBuffer datain, final FloatBuffer dataout, final int element_size,
+ final int ysize, final int group_size, final boolean myswap_bytes ) {
+ int i, j, k;
+ final int l;
int newwidth, newheight;
- int s = 0;
+ final int s = 0;
int t = 0;
float temp = 0.0f;
// handle case where there is only 1 column/row
@@ -874,10 +879,10 @@ public class HalveImage {
ysize, group_size, myswap_bytes );
return;
}
-
+
newwidth = width / 2;
newheight = height / 2;
-
+
// Piece of cake
if( !myswap_bytes ) {
for( i = 0; i < newheight; i++ ) {
@@ -920,27 +925,27 @@ public class HalveImage {
}
}
}
-
- public static void halve1Dimage_float( int components, int width, int height,
- ByteBuffer datain, FloatBuffer dataout, int element_size, int ysize,
- int group_size, boolean myswap_bytes ) {
+
+ public static void halve1Dimage_float( final int components, final int width, final int height,
+ final ByteBuffer datain, final FloatBuffer dataout, final int element_size, final int ysize,
+ final int group_size, final boolean myswap_bytes ) {
int halfWidth = width / 2;
int halfHeight = height / 2;
int src = 0;
int dest = 0;
int jj;
-
+
assert( width == 1 || height == 1 ); // must be 1D
assert( width != height ); // can't be square
-
+
if( height == 1 ) { // 1 row
assert( width != 1 ); // can't be 1x1
halfHeight = 1;
-
+
for( jj = 0; jj < halfWidth; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
- float[] sfloat = new float[BOX2];
+ final float[] sfloat = new float[BOX2];
if( myswap_bytes ) {
datain.position( src );
sfloat[0] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
@@ -958,19 +963,19 @@ public class HalveImage {
}
src += group_size; // skip to next 2
}
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
src += padBytes; // for assertion only
} else if( width == 1 ) {
- int padBytes = ysize - ( width * group_size );
+ final int padBytes = ysize - ( width * group_size );
assert( height != 1 );
halfWidth = 1;
// one vertical column with possible pad bytes per row
// average two at a time
-
+
for( jj = 0; jj < halfHeight; jj++ ) {
int kk;
for( kk = 0; kk < components; kk++ ) {
- float[] sfloat = new float[BOX2];
+ final float[] sfloat = new float[BOX2];
if( myswap_bytes ) {
datain.position( src );
sfloat[0] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
@@ -993,10 +998,10 @@ public class HalveImage {
}
assert( dest == ( components * element_size * halfWidth * halfHeight ) );
}
-
- public static void halveImagePackedPixel( int components, Extract extract, int width,
- int height, ByteBuffer datain, ByteBuffer dataout,
- int pixelSizeInBytes, int rowSizeInBytes, boolean isSwap ) {
+
+ public static void halveImagePackedPixel( final int components, final Extract extract, final int width,
+ final int height, final ByteBuffer datain, final ByteBuffer dataout,
+ final int pixelSizeInBytes, final int rowSizeInBytes, final boolean isSwap ) {
if( width == 1 || height == 1 ) {
assert( !( width == 1 && height == 1 ) );
halve1DimagePackedPixel( components, extract, width, height, datain, dataout,
@@ -1004,19 +1009,19 @@ public class HalveImage {
return;
}
int ii, jj;
-
- int halfWidth = width / 2;
- int halfHeight = height / 2;
+
+ final int halfWidth = width / 2;
+ final int halfHeight = height / 2;
int src = 0;
- int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
+ final int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
int outIndex = 0;
-
+
for( ii = 0; ii < halfHeight; ii++ ) {
for( jj = 0; jj < halfWidth; jj++ ) {
- float totals[] = new float[4];
- float extractTotals[][] = new float[BOX4][4];
+ final float totals[] = new float[4];
+ final float extractTotals[][] = new float[BOX4][4];
int cc;
-
+
datain.position( src );
extract.extract( isSwap, datain, extractTotals[0] );
datain.position( src + pixelSizeInBytes );
@@ -1045,31 +1050,31 @@ public class HalveImage {
assert( src == rowSizeInBytes * height );
assert( outIndex == halfWidth * halfHeight );
}
-
- public static void halve1DimagePackedPixel( int components, Extract extract, int width,
- int height, ByteBuffer datain, ByteBuffer dataout,
- int pixelSizeInBytes, int rowSizeInBytes, boolean isSwap ) {
+
+ public static void halve1DimagePackedPixel( final int components, final Extract extract, final int width,
+ final int height, final ByteBuffer datain, final ByteBuffer dataout,
+ final int pixelSizeInBytes, final int rowSizeInBytes, final boolean isSwap ) {
int halfWidth = width / 2;
int halfHeight = height / 2;
int src = 0;
int jj;
-
+
assert( width == 1 || height == 1 );
assert( width != height );
-
+
if( height == 1 ) {
int outIndex = 0;
-
+
assert( width != 1 );
halfHeight = 1;
-
+
// one horizontal row with possible pad bytes
-
+
for( jj = 0; jj < halfWidth; jj++ ) {
- float[] totals = new float[4];
- float[][] extractTotals = new float[BOX2][4];
+ final float[] totals = new float[4];
+ final float[][] extractTotals = new float[BOX2][4];
int cc;
-
+
datain.position( src );
extract.extract( isSwap, datain, extractTotals[0] );
datain.position( src + pixelSizeInBytes );
@@ -1088,22 +1093,22 @@ public class HalveImage {
// skip over to next group of 2
src += pixelSizeInBytes + pixelSizeInBytes;
}
- int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
+ final int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
src += padBytes;
-
+
assert( src == rowSizeInBytes );
assert( outIndex == halfWidth * halfHeight );
} else if( width == 1 ) {
int outIndex = 0;
-
+
assert( height != 1 );
halfWidth = 1;
// one vertical volumn with possible pad bytes per row
// average two at a time
-
+
for( jj = 0; jj < halfHeight; jj++ ) {
- float[] totals = new float[4];
- float[][] extractTotals = new float[BOX2][4];
+ final float[] totals = new float[4];
+ final float[][] extractTotals = new float[BOX2][4];
int cc;
// average two at a time, instead of four
datain.position( src );
@@ -1128,38 +1133,38 @@ public class HalveImage {
assert( outIndex == halfWidth * halfHeight );
}
}
-
- public static void halveImagePackedPixelSlice( int components, Extract extract,
- int width, int height, int depth, ByteBuffer dataIn,
- ByteBuffer dataOut, int pixelSizeInBytes, int rowSizeInBytes,
- int imageSizeInBytes, boolean isSwap ) {
+
+ public static void halveImagePackedPixelSlice( final int components, final Extract extract,
+ final int width, final int height, final int depth, final ByteBuffer dataIn,
+ final ByteBuffer dataOut, final int pixelSizeInBytes, final int rowSizeInBytes,
+ final int imageSizeInBytes, final boolean isSwap ) {
int ii, jj;
- int halfWidth = width / 2;
- int halfHeight = height / 2;
- int halfDepth = depth / 2;
+ final int halfWidth = width / 2;
+ // final int halfHeight = height / 2;
+ final int halfDepth = depth / 2;
int src = 0;
- int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
+ // final int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
int outIndex = 0;
-
+
assert( (width == 1 || height == 1) && depth >= 2 );
-
+
if( width == height ) {
assert( width == 1 && height == 1 );
assert( depth >= 2 );
-
+
for( ii = 0; ii < halfDepth; ii++ ) {
- float totals[] = new float[4];
- float extractTotals[][] = new float[BOX2][4];
+ final float totals[] = new float[4];
+ final float extractTotals[][] = new float[BOX2][4];
int cc;
-
+
dataIn.position( src );
extract.extract( isSwap, dataIn, extractTotals[0] );
dataIn.position( src + imageSizeInBytes );
extract.extract( isSwap, dataIn, extractTotals[1] );
-
+
for( cc = 0; cc < components; cc++ ) {
int kk;
-
+
// average only 2 pixels since a column
totals[cc]= 0.0f;
for( kk = 0; kk < BOX2; kk++ ) {
@@ -1167,7 +1172,7 @@ public class HalveImage {
}
totals[cc] /= BOX2;
} // for cc
-
+
extract.shove( totals, outIndex, dataOut );
outIndex++;
// skip over to next group of 2
@@ -1175,13 +1180,13 @@ public class HalveImage {
} // for ii
} else if( height == 1 ) {
assert( width != 1 );
-
+
for( ii = 0; ii < halfDepth; ii++ ) {
for( jj = 0; jj < halfWidth; jj++ ) {
- float totals[] = new float[4];
- float extractTotals[][] = new float[BOX4][4];
+ final float totals[] = new float[4];
+ final float extractTotals[][] = new float[BOX4][4];
int cc;
-
+
dataIn.position( src );
extract.extract( isSwap, dataIn, extractTotals[0] );
dataIn.position( src + pixelSizeInBytes );
@@ -1190,16 +1195,16 @@ public class HalveImage {
extract.extract( isSwap, dataIn, extractTotals[2] );
dataIn.position( src + pixelSizeInBytes + imageSizeInBytes );
extract.extract( isSwap, dataIn, extractTotals[3] );
-
+
for( cc = 0; cc < components; cc++ ) {
int kk;
-
+
// grab 4 pixels to average
totals[cc] = 0.0f;
for( kk = 0; kk < BOX4; kk++ ) {
totals[cc]+= extractTotals[kk][cc];
}
- totals[cc]/= (float)BOX4;
+ totals[cc]/= BOX4;
}
extract.shove( totals, outIndex, dataOut );
outIndex++;
@@ -1209,13 +1214,13 @@ public class HalveImage {
}
} else if( width == 1 ) {
assert( height != 1 );
-
+
for( ii = 0; ii < halfDepth; ii++ ) {
for( jj = 0; jj < halfWidth; jj++ ) {
- float totals[] = new float[4];
- float extractTotals[][] = new float[BOX4][4];
+ final float totals[] = new float[4];
+ final float extractTotals[][] = new float[BOX4][4];
int cc;
-
+
dataIn.position( src );
extract.extract( isSwap, dataIn, extractTotals[0] );
dataIn.position( src + rowSizeInBytes );
@@ -1224,16 +1229,16 @@ public class HalveImage {
extract.extract( isSwap, dataIn, extractTotals[2] );
dataIn.position( src + rowSizeInBytes + imageSizeInBytes );
extract.extract( isSwap, dataIn, extractTotals[3] );
-
+
for( cc = 0; cc < components; cc++ ) {
int kk;
-
+
// grab 4 pixels to average
totals[cc] = 0.0f;
for( kk = 0; kk < BOX4; kk++ ) {
totals[cc]+= extractTotals[kk][cc];
}
- totals[cc]/= (float)BOX4;
+ totals[cc]/= BOX4;
}
extract.shove( totals, outIndex, dataOut );
outIndex++;
@@ -1243,37 +1248,37 @@ public class HalveImage {
}
}
}
-
- public static void halveImageSlice( int components, ExtractPrimitive extract, int width,
- int height, int depth, ByteBuffer dataIn, ByteBuffer dataOut,
- int elementSizeInBytes, int groupSizeInBytes, int rowSizeInBytes,
- int imageSizeInBytes, boolean isSwap ) {
+
+ public static void halveImageSlice( final int components, final ExtractPrimitive extract, final int width,
+ final int height, final int depth, final ByteBuffer dataIn, final ByteBuffer dataOut,
+ final int elementSizeInBytes, final int groupSizeInBytes, final int rowSizeInBytes,
+ final int imageSizeInBytes, final boolean isSwap ) {
int ii, jj;
- int halfWidth = width / 2;
- int halfHeight = height / 2;
- int halfDepth = depth / 2;
+ final int halfWidth = width / 2;
+ final int halfHeight = height / 2;
+ final int halfDepth = depth / 2;
int src = 0;
- int padBytes = rowSizeInBytes - ( width * groupSizeInBytes );
+ final int padBytes = rowSizeInBytes - ( width * groupSizeInBytes );
int outIndex = 0;
-
+
assert( (width == 1 || height == 1) && depth >= 2 );
-
+
if( width == height ) {
assert( width == 1 && height == 1 );
assert( depth >= 2 );
-
+
for( ii = 0; ii < halfDepth; ii++ ) {
int cc;
for( cc = 0; cc < components; cc++ ) {
- double[] totals = new double[4];
- double[][] extractTotals = new double[BOX2][4];
+ final double[] totals = new double[4];
+ final double[][] extractTotals = new double[BOX2][4];
int kk;
-
+
dataIn.position( src );
extractTotals[0][cc] = extract.extract( isSwap, dataIn );
dataIn.position( src + imageSizeInBytes );
extractTotals[1][cc] = extract.extract( isSwap, dataIn );
-
+
// average 2 pixels since only a column
totals[cc] = 0.0f;
// totals[red] = extractTotals[0][red] + extractTotals[1][red];
@@ -1281,8 +1286,8 @@ public class HalveImage {
for( kk = 0; kk < BOX2; kk++ ) {
totals[cc] += extractTotals[kk][cc];
}
- totals[cc] /= (double)BOX2;
-
+ totals[cc] /= BOX2;
+
extract.shove( totals[cc], outIndex, dataOut );
outIndex++;
src += elementSizeInBytes;
@@ -1290,20 +1295,20 @@ public class HalveImage {
// skip over next group of 2
src += rowSizeInBytes;
} // for ii
-
+
assert( src == rowSizeInBytes * height * depth );
assert( outIndex == halfDepth * components );
} else if( height == 1 ) {
assert( width != 1 );
-
+
for( ii = 0; ii < halfDepth; ii++ ) {
for( jj = 0; jj < halfWidth; jj++ ) {
int cc;
for( cc = 0; cc < components; cc++ ) {
int kk;
- double totals[] = new double[4];
- double extractTotals[][] = new double[BOX4][4];
-
+ final double totals[] = new double[4];
+ final double extractTotals[][] = new double[BOX4][4];
+
dataIn.position( src );
extractTotals[0][cc] = extract.extract( isSwap, dataIn );
dataIn.position( src + groupSizeInBytes );
@@ -1312,7 +1317,7 @@ public class HalveImage {
extractTotals[2][cc] = extract.extract( isSwap, dataIn );
dataIn.position( src + imageSizeInBytes + groupSizeInBytes );
extractTotals[3][cc] = extract.extract( isSwap, dataIn );
-
+
// grab 4 pixels to average
totals[cc] = 0.0f;
// totals[red] = extractTotals[0][red] + extractTotals[1][red] +
@@ -1321,8 +1326,8 @@ public class HalveImage {
for( kk = 0; kk < BOX4; kk++ ) {
totals[cc] += extractTotals[kk][cc];
}
- totals[cc] /= (double)BOX4;
-
+ totals[cc] /= BOX4;
+
extract.shove( totals[cc], outIndex, dataOut );
outIndex++;
src += elementSizeInBytes;
@@ -1337,15 +1342,15 @@ public class HalveImage {
assert( outIndex == halfWidth * halfDepth * components );
} else if( width == 1 ) {
assert( height != 1 );
-
+
for( ii = 0; ii < halfDepth; ii++ ) {
for( jj = 0; jj < halfHeight; jj++ ) {
int cc;
for( cc = 0; cc < components; cc++ ) {
int kk;
- double totals[] = new double[4];
- double extractTotals[][] = new double[BOX4][4];
-
+ final double totals[] = new double[4];
+ final double extractTotals[][] = new double[BOX4][4];
+
dataIn.position( src );
extractTotals[0][cc] = extract.extract( isSwap, dataIn );
dataIn.position( src + rowSizeInBytes );
@@ -1354,8 +1359,8 @@ public class HalveImage {
extractTotals[2][cc] = extract.extract( isSwap, dataIn );
dataIn.position( src + imageSizeInBytes + groupSizeInBytes );
extractTotals[3][cc] = extract.extract( isSwap, dataIn );
-
-
+
+
// grab 4 pixels to average
totals[cc] = 0.0f;
// totals[red] = extractTotals[0][red] + extractTotals[1][red] +
@@ -1364,8 +1369,8 @@ public class HalveImage {
for( kk = 0; kk < BOX4; kk++ ) {
totals[cc] += extractTotals[kk][cc];
}
- totals[cc] /= (double)BOX4;
-
+ totals[cc] /= BOX4;
+
extract.shove( totals[cc], outIndex, dataOut );
outIndex++;
src += elementSizeInBytes;
@@ -1380,41 +1385,41 @@ public class HalveImage {
assert( outIndex == halfWidth * halfDepth * components );
}
}
-
- public static void halveImage3D( int components, ExtractPrimitive extract,
- int width, int height, int depth, ByteBuffer dataIn, ByteBuffer dataOut,
- int elementSizeInBytes, int groupSizeInBytes, int rowSizeInBytes,
- int imageSizeInBytes, boolean isSwap ) {
+
+ public static void halveImage3D( final int components, final ExtractPrimitive extract,
+ final int width, final int height, final int depth, final ByteBuffer dataIn, final ByteBuffer dataOut,
+ final int elementSizeInBytes, final int groupSizeInBytes, final int rowSizeInBytes,
+ final int imageSizeInBytes, final boolean isSwap ) {
assert( depth > 1 );
-
+
// horizontal/vertical/onecolumn slice viewed from top
if( width == 1 || height == 1 ) {
assert( 1 <= depth );
-
+
halveImageSlice( components, extract, width, height, depth, dataIn, dataOut,
elementSizeInBytes, groupSizeInBytes, rowSizeInBytes, imageSizeInBytes,
isSwap );
return;
}
-
+
int ii, jj, dd;
-
- int halfWidth = width / 2;
- int halfHeight = height / 2;
- int halfDepth = depth / 2;
+
+ final int halfWidth = width / 2;
+ final int halfHeight = height / 2;
+ final int halfDepth = depth / 2;
int src = 0;
- int padBytes = rowSizeInBytes - ( width * groupSizeInBytes );
+ final int padBytes = rowSizeInBytes - ( width * groupSizeInBytes );
int outIndex = 0;
-
+
for( dd = 0; dd < halfDepth; dd++ ) {
for( ii = 0; ii < halfHeight; ii++ ) {
for( jj = 0; jj < halfWidth; jj++ ) {
int cc;
for( cc = 0; cc < components; cc++ ) {
int kk;
- double totals[] = new double[4];
- double extractTotals[][] = new double[BOX8][4];
-
+ final double totals[] = new double[4];
+ final double extractTotals[][] = new double[BOX8][4];
+
dataIn.position( src );
extractTotals[0][cc] = extract.extract( isSwap, dataIn );
dataIn.position( src + groupSizeInBytes );
@@ -1431,17 +1436,17 @@ public class HalveImage {
extractTotals[6][cc] = extract.extract( isSwap, dataIn );
dataIn.position( src + rowSizeInBytes + imageSizeInBytes + groupSizeInBytes );
extractTotals[7][cc] = extract.extract( isSwap, dataIn );
-
+
totals[cc] = 0.0f;
-
+
for( kk = 0; kk < BOX8; kk++ ) {
totals[cc] += extractTotals[kk][cc];
}
- totals[cc] /= (double)BOX8;
-
+ totals[cc] /= BOX8;
+
extract.shove( totals[cc], outIndex, dataOut );
outIndex++;
-
+
src += elementSizeInBytes;
} // for cc
// skip over to next square of 4
@@ -1456,40 +1461,40 @@ public class HalveImage {
assert( src == rowSizeInBytes * height * depth );
assert( outIndex == halfWidth * halfHeight * halfDepth * components );
}
-
- public static void halveImagePackedPixel3D( int components, Extract extract,
- int width, int height, int depth, ByteBuffer dataIn,
- ByteBuffer dataOut, int pixelSizeInBytes, int rowSizeInBytes,
- int imageSizeInBytes, boolean isSwap ) {
+
+ public static void halveImagePackedPixel3D( final int components, final Extract extract,
+ final int width, final int height, final int depth, final ByteBuffer dataIn,
+ final ByteBuffer dataOut, final int pixelSizeInBytes, final int rowSizeInBytes,
+ final int imageSizeInBytes, final boolean isSwap ) {
if( depth == 1 ) {
assert( 1 <= width && 1 <= height );
-
+
halveImagePackedPixel( components, extract, width, height, dataIn, dataOut,
pixelSizeInBytes, rowSizeInBytes, isSwap );
return;
} else if( width == 1 || height == 1 ) { // a horizontal or vertical slice viewed from top
assert( 1 <= depth );
-
+
halveImagePackedPixelSlice( components, extract, width, height, depth, dataIn,
dataOut, pixelSizeInBytes, rowSizeInBytes, imageSizeInBytes, isSwap );
return;
}
int ii, jj, dd;
-
- int halfWidth = width / 2;
- int halfHeight = height / 2;
- int halfDepth = depth / 2;
+
+ final int halfWidth = width / 2;
+ final int halfHeight = height / 2;
+ final int halfDepth = depth / 2;
int src = 0;
- int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
+ final int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
int outIndex = 0;
-
+
for( dd = 0; dd < halfDepth; dd++ ) {
for( ii = 0; ii < halfHeight; ii++ ) {
for( jj = 0; jj < halfWidth; jj++ ) {
- float totals[] = new float[4]; // 4 is max components
- float extractTotals[][] = new float[BOX8][4];
+ final float totals[] = new float[4]; // 4 is max components
+ final float extractTotals[][] = new float[BOX8][4];
int cc;
-
+
dataIn.position( src );
extract.extract( isSwap, dataIn, extractTotals[0] );
dataIn.position( src + pixelSizeInBytes );
@@ -1506,7 +1511,7 @@ public class HalveImage {
extract.extract( isSwap, dataIn, extractTotals[6] );
dataIn.position( src + rowSizeInBytes + pixelSizeInBytes + imageSizeInBytes );
extract.extract( isSwap, dataIn, extractTotals[7] );
-
+
for( cc = 0; cc < components; cc++ ) {
int kk;
// grab 8 pixels to average
@@ -1514,7 +1519,7 @@ public class HalveImage {
for( kk = 0; kk < BOX8; kk++ ) {
totals[cc] += extractTotals[kk][cc];
}
- totals[cc] /= (float)BOX8;
+ totals[cc] /= BOX8;
}
extract.shove( totals, outIndex, dataOut );
outIndex++;
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java
index b610ce86b..ef77f3555 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -46,6 +46,9 @@ package jogamp.opengl.glu.mipmap;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+
import java.nio.*;
/**
@@ -53,19 +56,19 @@ import java.nio.*;
* @author Administrator
*/
public class Image {
-
+
/** Creates a new instance of Image */
public Image() {
}
-
- public static short getShortFromByteArray( byte[] array, int index ) {
+
+ public static short getShortFromByteArray( final byte[] array, final int index ) {
short s;
s = (short)(array[index] << 8 );
s |= (short)(0x00FF & array[index+1]);
return( s );
}
-
- public static int getIntFromByteArray( byte[] array, int index ) {
+
+ public static int getIntFromByteArray( final byte[] array, final int index ) {
int i;
i = ( array[index] << 24 ) & 0xFF000000;
i |= ( array[index+1] << 16 ) & 0x00FF0000;
@@ -73,19 +76,19 @@ public class Image {
i |= ( array[index+3] ) & 0x000000FF;
return( i );
}
-
- public static float getFloatFromByteArray( byte[] array, int index ) {
- int i = getIntFromByteArray( array, index );
+
+ public static float getFloatFromByteArray( final byte[] array, final int index ) {
+ final int i = getIntFromByteArray( array, index );
return( Float.intBitsToFloat(i) );
}
-
+
/*
* Extract array from user's data applying all pixel store modes.
* The internal format used is an array of unsigned shorts.
*/
- public static void fill_image( PixelStorageModes psm, int width, int height,
- int format, int type, boolean index_format, ByteBuffer userdata,
- ShortBuffer newimage ) {
+ public static void fill_image( final PixelStorageModes psm, final int width, final int height,
+ final int format, final int type, final boolean index_format, final ByteBuffer userdata,
+ final ShortBuffer newimage ) {
int components;
int element_size;
int rowsize;
@@ -98,48 +101,48 @@ public class Image {
int iter2;
int i, j, k;
boolean myswap_bytes;
-
+
// Create a Extract interface object
Extract extract = null;
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
extract = new Extract332();
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
extract = new Extract233rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
extract = new Extract565();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
extract = new Extract565rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
extract = new Extract4444();
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
extract = new Extract4444rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
extract = new Extract5551();
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
extract = new Extract1555rev();
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
extract = new Extract8888();
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
extract = new Extract8888rev();
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
extract = new Extract1010102();
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
extract = new Extract2101010rev();
break;
}
-
+
myswap_bytes = psm.getUnpackSwapBytes();
components = Mipmap.elements_per_group( format, type );
if( psm.getUnpackRowLength() > 0 ) {
@@ -147,12 +150,12 @@ public class Image {
} else {
groups_per_line = width;
}
-
+
// All formats except GL_BITMAP fall out trivially
if( type == GL2.GL_BITMAP ) {
int bit_offset;
int current_bit;
-
+
rowsize = ( groups_per_line * components + 7 ) / 8;
padding = ( rowsize % psm.getUnpackAlignment() );
if( padding != 0 ) {
@@ -200,7 +203,7 @@ public class Image {
if( element_size == 1 ) {
myswap_bytes = false;
}
-
+
rowsize = groups_per_line * group_size;
padding = ( rowsize % psm.getUnpackAlignment() );
if( padding != 0 ) {
@@ -208,80 +211,80 @@ public class Image {
}
start = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size;
elements_per_line = width * components;
-
+
iter2 = 0;
for( i = 0; i < height; i++ ) {
iter = start;
userdata.position( iter ); //***************************************
for( j = 0; j < elements_per_line; j++ ) {
- Type_Widget widget = new Type_Widget();
- float[] extractComponents = new float[4];
+ final Type_Widget widget = new Type_Widget();
+ final float[] extractComponents = new float[4];
userdata.position( iter );
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
extract.extract( false, userdata /*userdata[iter]*/, extractComponents );
for( k = 0; k < 3; k++ ) {
newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
extract.extract( false, userdata /*userdata[iter]*/, extractComponents );
for( k = 0; k < 3; k++ ) {
newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_BYTE ):
+ case( GL.GL_UNSIGNED_BYTE ):
if( index_format ) {
newimage.put( iter2++, (short)( 0x000000FF & userdata.get() ) );//userdata[iter];
} else {
newimage.put( iter2++, (short)( 0x000000FF & userdata.get()/*userdata[iter]*/ * 257 ) );
}
break;
- case( GL2.GL_BYTE ):
+ case( GL.GL_BYTE ):
if( index_format ) {
newimage.put( iter2++, userdata.get() ); //userdata[iter];
} else {
newimage.put( iter2++, (short)(userdata.get()/*userdata[iter]*/ * 516 ) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
extract.extract( myswap_bytes, userdata/*userdata[iter]*/, extractComponents );
for( k = 0; k < 3; k++ ) {
newimage.put( iter2++, (short)(extractComponents[k] * 65535) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
extract.extract( myswap_bytes, userdata, extractComponents );
for( k = 0; k < 3; k++ ) {
newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
extract.extract( myswap_bytes, userdata, extractComponents );
for( k = 0; k < 4; k++ ) {
newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
extract.extract( myswap_bytes, userdata, extractComponents );
for( k = 0; k < 4; k++ ) {
newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
extract.extract( myswap_bytes, userdata, extractComponents );
for( k = 0; k < 4; k++ ) {
newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
extract.extract( myswap_bytes, userdata, extractComponents );
for( k = 0; k < 4; k++ ) {
newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
if( myswap_bytes ) {
widget.setUB1( userdata.get() );
widget.setUB0( userdata.get() );
@@ -289,7 +292,7 @@ public class Image {
widget.setUB0( userdata.get() );
widget.setUB1( userdata.get() );
}
- if( type == GL2.GL_SHORT ) {
+ if( type == GL.GL_SHORT ) {
if( index_format ) {
newimage.put( iter2++, widget.getS0() );
} else {
@@ -299,33 +302,33 @@ public class Image {
newimage.put( iter2++, widget.getUS0() );
}
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
extract.extract( myswap_bytes, userdata, extractComponents );
for( k = 0; k < 4; k++ ) {
newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
extract.extract( myswap_bytes, userdata, extractComponents );
for( k = 0; k < 4; k++ ) {
newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
extract.extract( myswap_bytes, userdata, extractComponents );
for( k = 0; k < 4; k++ ) {
newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
extract.extract( myswap_bytes, userdata, extractComponents );
for( k = 0; k < 4; k++ ) {
newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_INT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_FLOAT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL.GL_FLOAT ):
if( myswap_bytes ) {
widget.setUB3( userdata.get() );
widget.setUB2( userdata.get() );
@@ -337,13 +340,13 @@ public class Image {
widget.setUB2( userdata.get() );
widget.setUB3( userdata.get() );
}
- if( type == GL2.GL_FLOAT ) {
+ if( type == GL.GL_FLOAT ) {
if( index_format ) {
newimage.put( iter2++, (short)widget.getF() );
} else {
newimage.put( iter2++, (short)(widget.getF() * 65535 ) );
}
- } else if( type == GL2.GL_UNSIGNED_INT ) {
+ } else if( type == GL.GL_UNSIGNED_INT ) {
if( index_format ) {
newimage.put( iter2++, (short)( widget.getUI() ) );
} else {
@@ -364,7 +367,7 @@ public class Image {
// want iter pointing at start, not within, row for assertion purposes
iter = start;
} // for i
-
+
// iterators should be one byte past end
if( !Mipmap.isTypePackedPixel( type ) ) {
assert( iter2 == ( width * height * components ) );
@@ -374,16 +377,16 @@ public class Image {
assert( iter == ( rowsize * height + psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size ) );
}
}
-
+
/*
* Insert array into user's data applying all pixel store modes.
* Theinternal format is an array of unsigned shorts.
* empty_image() because it is the opposet of fill_image().
*/
- public static void empty_image( PixelStorageModes psm, int width, int height,
- int format, int type, boolean index_format,
- ShortBuffer oldimage, ByteBuffer userdata ) {
-
+ public static void empty_image( final PixelStorageModes psm, final int width, final int height,
+ final int format, final int type, final boolean index_format,
+ final ShortBuffer oldimage, final ByteBuffer userdata ) {
+
int components;
int element_size;
int rowsize;
@@ -396,48 +399,48 @@ public class Image {
int iter2;
int i, j, k;
boolean myswap_bytes;
-
+
// Create a Extract interface object
Extract extract = null;
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
extract = new Extract332();
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
extract = new Extract233rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
extract = new Extract565();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
extract = new Extract565rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
extract = new Extract4444();
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
extract = new Extract4444rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
extract = new Extract5551();
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
extract = new Extract1555rev();
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
extract = new Extract8888();
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
extract = new Extract8888rev();
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
extract = new Extract1010102();
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
extract = new Extract2101010rev();
break;
}
-
+
myswap_bytes = psm.getPackSwapBytes();
components = Mipmap.elements_per_group( format, type );
if( psm.getPackRowLength() > 0 ) {
@@ -445,12 +448,12 @@ public class Image {
} else {
groups_per_line = width;
}
-
+
// all formats except GL_BITMAP fall out trivially
if( type == GL2.GL_BITMAP ) {
int bit_offset;
int current_bit;
-
+
rowsize = ( groups_per_line * components + 7 ) / 8;
padding = ( rowsize % psm.getPackAlignment() );
if( padding != 0 ) {
@@ -472,7 +475,7 @@ public class Image {
current_bit = 0;
}
}
-
+
if( current_bit != 0 ) {
if( psm.getPackLsbFirst() ) {
userdata.put( iter, (byte)( ( userdata.get( iter ) | ( 1 << bit_offset ) ) ) );
@@ -488,7 +491,7 @@ public class Image {
userdata.put( iter, (byte)( ( userdata.get( iter ) & ~( 7 - bit_offset ) ) ) );
}
}
-
+
bit_offset++;
if( bit_offset == 8 ) {
bit_offset = 0;
@@ -499,14 +502,14 @@ public class Image {
start += rowsize;
}
} else {
- float shoveComponents[] = new float[4];
-
+ final float shoveComponents[] = new float[4];
+
element_size = Mipmap.bytes_per_element( type );
group_size = element_size * components;
if( element_size == 1 ) {
myswap_bytes = false;
}
-
+
rowsize = groups_per_line * group_size;
padding = ( rowsize % psm.getPackAlignment() );
if( padding != 0 ) {
@@ -514,27 +517,27 @@ public class Image {
}
start = psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * group_size;
elements_per_line = width * components;
-
+
iter2 = 0;
for( i = 0; i < height; i++ ) {
iter = start;
for( j = 0; j < elements_per_line; j++ ) {
- Type_Widget widget = new Type_Widget();
-
+ final Type_Widget widget = new Type_Widget();
+
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
for( k = 0; k < 3; k++ ) {
shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
}
extract.shove( shoveComponents, 0, userdata );
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
for( k = 0; k < 3; k++ ) {
shoveComponents[k] = oldimage.get(iter2++) / 65535.0f;
}
extract.shove( shoveComponents, 0, userdata );
break;
- case( GL2.GL_UNSIGNED_BYTE ):
+ case( GL.GL_UNSIGNED_BYTE ):
if( index_format ) {
//userdata[iter] = (byte)oldimage[iter2++];
userdata.put( iter, (byte)oldimage.get(iter2++) );
@@ -543,7 +546,7 @@ public class Image {
userdata.put( iter, (byte)( oldimage.get(iter2++) ) );
}
break;
- case( GL2.GL_BYTE ):
+ case( GL.GL_BYTE ):
if( index_format ) {
//userdata[iter] = (byte)oldimage[iter2++];
userdata.put( iter, (byte)oldimage.get(iter2++) );
@@ -552,7 +555,7 @@ public class Image {
userdata.put( iter, (byte)( oldimage.get(iter2++) ) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
for( k = 0; k < 3; k++ ) {
shoveComponents[k] = oldimage.get(iter2++) / 65535.0f;
}
@@ -569,7 +572,7 @@ public class Image {
userdata.put( iter + 1, widget.getUB1() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
for( k = 0; k < 3; k++ ) {
shoveComponents[k] = oldimage.get(iter2++) / 65535.0f;
}
@@ -586,7 +589,7 @@ public class Image {
userdata.put( iter, widget.getUB1() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldimage.get(iter2++) / 65535.0f;
}
@@ -603,7 +606,7 @@ public class Image {
userdata.put( iter + 1, widget.getUB1() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
}
@@ -620,7 +623,7 @@ public class Image {
userdata.put( iter + 1, widget.getUB1() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
}
@@ -637,7 +640,7 @@ public class Image {
userdata.put( iter + 1, widget.getUB1() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
}
@@ -654,9 +657,9 @@ public class Image {
userdata.put( iter + 1, widget.getUB1() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
- if( type == GL2.GL_SHORT ) {
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
+ if( type == GL.GL_SHORT ) {
if( index_format ) {
widget.setS0( oldimage.get( iter2++ ) );
} else {
@@ -677,7 +680,7 @@ public class Image {
userdata.put( iter + 1, widget.getUB1() );
}
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
}
@@ -695,7 +698,7 @@ public class Image {
userdata.putInt( iter, widget.getUI() );
}
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
}
@@ -713,7 +716,7 @@ public class Image {
userdata.putInt( iter, widget.getUI() );
}
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
}
@@ -731,7 +734,7 @@ public class Image {
userdata.putInt( iter, widget.getUI() );
}
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
}
@@ -749,16 +752,16 @@ public class Image {
userdata.putInt( iter, widget.getUI() );
}
break;
- case( GL2.GL_INT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_FLOAT ):
- if( type == GL2.GL_FLOAT ) {
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL.GL_FLOAT ):
+ if( type == GL.GL_FLOAT ) {
if( index_format ) {
widget.setF( oldimage.get( iter2++ ) );
} else {
widget.setF( oldimage.get( iter2++ ) / 65535.0f );
}
- } else if( type == GL2.GL_UNSIGNED_INT ) {
+ } else if( type == GL.GL_UNSIGNED_INT ) {
if( index_format ) {
widget.setUI( oldimage.get( iter2++ ) );
} else {
@@ -799,10 +802,10 @@ public class Image {
assert( iter == rowsize * height + psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * group_size );
}
}
-
- public static void fillImage3D( PixelStorageModes psm, int width, int height,
- int depth, int format, int type, boolean indexFormat, ByteBuffer userImage,
- ShortBuffer newImage ) {
+
+ public static void fillImage3D( final PixelStorageModes psm, final int width, final int height,
+ final int depth, final int format, final int type, final boolean indexFormat, final ByteBuffer userImage,
+ final ShortBuffer newImage ) {
boolean myswapBytes;
int components;
int groupsPerLine;
@@ -817,50 +820,50 @@ public class Image {
int iter = 0;
int iter2 = 0;
int ww, hh, dd, k;
- Type_Widget widget = new Type_Widget();
- float extractComponents[] = new float[4];
-
+ final Type_Widget widget = new Type_Widget();
+ final float extractComponents[] = new float[4];
+
// Create a Extract interface object
Extract extract = null;
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
extract = new Extract332();
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
extract = new Extract233rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
extract = new Extract565();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
extract = new Extract565rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
extract = new Extract4444();
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
extract = new Extract4444rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
extract = new Extract5551();
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
extract = new Extract1555rev();
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
extract = new Extract8888();
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
extract = new Extract8888rev();
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
extract = new Extract1010102();
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
extract = new Extract2101010rev();
break;
}
-
+
myswapBytes = psm.getUnpackSwapBytes();
components = Mipmap.elements_per_group( format, type );
if( psm.getUnpackRowLength() > 0 ) {
@@ -873,7 +876,7 @@ public class Image {
if( elementSize == 1 ) {
myswapBytes = false;
}
-
+
// 3dstuff begin
if( psm.getUnpackImageHeight() > 0 ) {
rowsPerImage = psm.getUnpackImageHeight();
@@ -881,100 +884,100 @@ public class Image {
rowsPerImage = height;
}
// 3dstuff end
-
+
rowSize = groupsPerLine * groupSize;
padding = rowSize % psm.getUnpackAlignment();
if( padding != 0 ) {
rowSize += psm.getUnpackAlignment() - padding;
}
-
+
imageSize = rowsPerImage * rowSize; // 3dstuff
-
- start = psm.getUnpackSkipRows() * rowSize +
- psm.getUnpackSkipPixels() * groupSize +
+
+ start = psm.getUnpackSkipRows() * rowSize +
+ psm.getUnpackSkipPixels() * groupSize +
psm.getUnpackSkipImages() * imageSize;
elementsPerLine = width * components;
-
+
iter2 = 0;
for( dd = 0; dd < depth; dd++ ) {
rowStart = start;
for( hh = 0; hh < height; hh++ ) {
iter = rowStart;
for( ww = 0; ww < elementsPerLine; ww++ ) {
-
+
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
+ case( GL.GL_UNSIGNED_BYTE ):
if( indexFormat ) {
newImage.put( iter2++, (short)(0x000000FF & userImage.get( iter ) ) );
} else {
newImage.put( iter2++, (short)((0x000000FF & userImage.get( iter ) ) * 257 ) );
}
break;
- case( GL2.GL_BYTE ):
+ case( GL.GL_BYTE ):
if( indexFormat ) {
newImage.put( iter2++, userImage.get( iter ) );
} else {
newImage.put( iter2++, (short)(userImage.get( iter ) * 516 ) );
}
break;
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
userImage.position( iter );
extract.extract( false, userImage, extractComponents );
for( k = 0; k < 3; k++ ) {
newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
}
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
userImage.position( iter );
extract.extract( false, userImage, extractComponents );
for( k = 0; k < 3; k++ ) {
newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
userImage.position( iter );
extract.extract( myswapBytes, userImage, extractComponents );
for( k = 0; k < 4; k++ ) {
newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
userImage.position( iter );
extract.extract( myswapBytes, userImage, extractComponents );
for( k = 0; k < 4; k++ ) {
newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
userImage.position( iter );
extract.extract( myswapBytes, userImage, extractComponents );
for( k = 0; k < 4; k++ ) {
newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
userImage.position( iter );
extract.extract( myswapBytes, userImage, extractComponents );
for( k = 0; k < 4; k++ ) {
newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
userImage.position( iter );
extract.extract( myswapBytes, userImage, extractComponents );
for( k = 0; k < 4; k++ ) {
newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
userImage.position( iter );
extract.extract( myswapBytes, userImage, extractComponents );
for( k = 0; k < 4; k++ ) {
newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
}
break;
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
if( myswapBytes ) {
widget.setUB0( userImage.get( iter + 1 ) );
widget.setUB1( userImage.get( iter ) );
@@ -982,7 +985,7 @@ public class Image {
widget.setUB0( userImage.get( iter ) );
widget.setUB1( userImage.get( iter + 1 ) );
}
- if( type == GL2.GL_SHORT ) {
+ if( type == GL.GL_SHORT ) {
if( indexFormat ) {
newImage.put( iter2++, widget.getUS0() );
} else {
@@ -992,36 +995,36 @@ public class Image {
newImage.put( iter2++, widget.getUS0() );
}
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
userImage.position( iter );
extract.extract( myswapBytes, userImage, extractComponents );
for( k = 0; k < 4; k++ ) {
newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
userImage.position( iter );
extract.extract( myswapBytes, userImage, extractComponents );
for( k = 0; k < 4; k++ ) {
newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
userImage.position( iter );
extract.extract( myswapBytes, userImage, extractComponents );
for( k = 0; k < 4; k++ ) {
newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
extract.extract( myswapBytes, userImage, extractComponents );
for( k = 0; k < 4; k++ ) {
newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
}
break;
- case( GL2.GL_INT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_FLOAT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL.GL_FLOAT ):
if( myswapBytes ) {
widget.setUB0( userImage.get( iter + 3 ) );
widget.setUB1( userImage.get( iter + 2 ) );
@@ -1033,13 +1036,13 @@ public class Image {
widget.setUB2( userImage.get( iter + 2 ) );
widget.setUB3( userImage.get( iter + 3 ) );
}
- if( type == GL2.GL_FLOAT ) {
+ if( type == GL.GL_FLOAT ) {
if( indexFormat ) {
newImage.put( iter2++, (short)widget.getF() );
} else {
newImage.put( iter2++, (short)( widget.getF() * 65535.0f ) );
}
- } else if( type == GL2.GL_UNSIGNED_INT ) {
+ } else if( type == GL.GL_UNSIGNED_INT ) {
if( indexFormat ) {
newImage.put( iter2++, (short)widget.getUI() );
} else {
@@ -1063,20 +1066,20 @@ public class Image {
} // for hh
start += imageSize;
}// for dd
-
+
// iterators should be one byte past end
if( !Mipmap.isTypePackedPixel( type ) ) {
assert( iter2 == width * height * depth * components );
} else {
assert( iter2 == width * height * depth * Mipmap.elements_per_group( format, 0 ) );
}
- assert( iter == rowSize * height * depth + psm.getUnpackSkipRows() * rowSize +
+ assert( iter == rowSize * height * depth + psm.getUnpackSkipRows() * rowSize +
psm.getUnpackSkipPixels() * groupSize +
psm.getUnpackSkipImages() * imageSize );
}
-
- public static void emptyImage3D( PixelStorageModes psm, int width, int height, int depth,
- int format, int type, boolean indexFormat, ShortBuffer oldImage, ByteBuffer userImage ) {
+
+ public static void emptyImage3D( final PixelStorageModes psm, final int width, final int height, final int depth,
+ final int format, final int type, final boolean indexFormat, final ShortBuffer oldImage, final ByteBuffer userImage ) {
boolean myswapBytes;
int components;
int groupsPerLine;
@@ -1090,52 +1093,52 @@ public class Image {
int ii, jj, dd, k;
int rowsPerImage;
int imageSize;
- Type_Widget widget = new Type_Widget();
- float[] shoveComponents = new float[4];
-
+ final Type_Widget widget = new Type_Widget();
+ final float[] shoveComponents = new float[4];
+
// Create a Extract interface object
Extract extract = null;
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
extract = new Extract332();
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
extract = new Extract233rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
extract = new Extract565();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
extract = new Extract565rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
extract = new Extract4444();
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
extract = new Extract4444rev();
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
extract = new Extract5551();
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
extract = new Extract1555rev();
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
extract = new Extract8888();
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
extract = new Extract8888rev();
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
extract = new Extract1010102();
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
extract = new Extract2101010rev();
break;
}
-
+
iter = 0;
-
+
myswapBytes = psm.getPackSwapBytes();
components = Mipmap.elements_per_group( format, type );
if( psm.getPackRowLength() > 0 ) {
@@ -1143,72 +1146,72 @@ public class Image {
} else {
groupsPerLine = width;
}
-
+
elementSize = Mipmap.bytes_per_element( type );
groupSize = elementSize * components;
if( elementSize == 1 ) {
myswapBytes = false;
}
-
+
// 3dstuff begin
if( psm.getPackImageHeight() > 0 ) {
rowsPerImage = psm.getPackImageHeight();
} else {
rowsPerImage = height;
}
-
+
// 3dstuff end
-
+
rowSize = groupsPerLine * groupSize;
padding = rowSize % psm.getPackAlignment();
if( padding != 0 ) {
rowSize += psm.getPackAlignment() - padding;
}
-
+
imageSize = rowsPerImage * rowSize;
-
+
start = psm.getPackSkipRows() * rowSize +
psm.getPackSkipPixels() * groupSize +
psm.getPackSkipImages() * imageSize;
elementsPerLine = width * components;
-
+
iter2 = 0;
for( dd = 0; dd < depth; dd++ ) {
rowStart = start;
-
+
for( ii = 0; ii < height; ii++ ) {
iter = rowStart;
-
+
for( jj = 0; jj < elementsPerLine; jj++ ) {
-
+
switch( type ) {
- case( GL2.GL_UNSIGNED_BYTE ):
+ case( GL.GL_UNSIGNED_BYTE ):
if( indexFormat ) {
userImage.put( iter, (byte)(oldImage.get( iter2++ ) ) );
} else {
userImage.put( iter, (byte)(oldImage.get( iter2++ ) >> 8 ) );
}
break;
- case( GL2.GL_BYTE ):
+ case( GL.GL_BYTE ):
if( indexFormat ) {
userImage.put( iter, (byte)(oldImage.get(iter2++) ) );
} else {
userImage.put( iter, (byte)(oldImage.get(iter2++) >> 9) );
}
break;
- case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
for( k = 0; k < 3; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
extract.shove( shoveComponents, 0, userImage );
break;
- case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+ case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
for( k = 0; k < 3; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
extract.shove( shoveComponents, 0, userImage );
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
@@ -1220,7 +1223,7 @@ public class Image {
userImage.putShort( iter, widget.getUS0() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
@@ -1232,7 +1235,7 @@ public class Image {
userImage.putShort( iter, widget.getUS0() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
@@ -1244,7 +1247,7 @@ public class Image {
userImage.putShort( iter, widget.getUS0() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
@@ -1256,7 +1259,7 @@ public class Image {
userImage.putShort( iter, widget.getUS0() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
@@ -1268,7 +1271,7 @@ public class Image {
userImage.putShort( iter, widget.getUS0() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+ case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
@@ -1280,16 +1283,16 @@ public class Image {
userImage.putShort( iter, widget.getUS0() );
}
break;
- case( GL2.GL_UNSIGNED_SHORT ):
- case( GL2.GL_SHORT ):
- if( type == GL2.GL_SHORT ) {
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_SHORT ):
+ if( type == GL.GL_SHORT ) {
if( indexFormat ) {
- widget.setS0( (short)oldImage.get( iter2++ ) );
+ widget.setS0( oldImage.get( iter2++ ) );
} else {
widget.setS0( (short)(oldImage.get( iter2++ ) >> 1) );
}
} else {
- widget.setUS0( (short)oldImage.get( iter2++ ) );
+ widget.setUS0( oldImage.get( iter2++ ) );
}
if( myswapBytes ) {
userImage.put( iter, widget.getUB1() );
@@ -1299,7 +1302,7 @@ public class Image {
userImage.put( iter + 1, widget.getUB1() );
}
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
@@ -1313,7 +1316,7 @@ public class Image {
userImage.putInt( iter, widget.getUI() );
}
break;
- case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+ case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
@@ -1327,7 +1330,7 @@ public class Image {
userImage.putInt( iter, widget.getUI() );
}
break;
- case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
@@ -1341,7 +1344,7 @@ public class Image {
userImage.putInt( iter, widget.getUI() );
}
break;
- case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
for( k = 0; k < 4; k++ ) {
shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
}
@@ -1355,16 +1358,16 @@ public class Image {
userImage.putInt( iter, widget.getUI() );
}
break;
- case( GL2.GL_INT ):
- case( GL2.GL_UNSIGNED_INT ):
- case( GL2.GL_FLOAT ):
- if( type == GL2.GL_FLOAT ) {
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL.GL_FLOAT ):
+ if( type == GL.GL_FLOAT ) {
if( indexFormat ) {
widget.setF( oldImage.get( iter2++ ) );
} else {
widget.setF( oldImage.get( iter2++ ) / 65535.0f );
}
- } else if( type == GL2.GL_UNSIGNED_INT ) {
+ } else if( type == GL.GL_UNSIGNED_INT ) {
if( indexFormat ) {
widget.setUI( oldImage.get( iter2++ ) );
} else {
@@ -1392,20 +1395,20 @@ public class Image {
default:
assert( false );
}
-
+
iter += elementSize;
} // for jj
rowStart += rowSize;
} // for ii
start += imageSize;
} // for dd
-
+
if( !Mipmap.isTypePackedPixel( type ) ) {
assert( iter2 == width * height * depth * components );
} else {
assert( iter2 == width * height * depth * Mipmap.elements_per_group( format, 0 ) );
}
- assert( iter == rowSize * height * depth +
+ assert( iter == rowSize * height * depth +
psm.getUnpackSkipRows() * rowSize +
psm.getUnpackSkipPixels() * groupSize +
psm.getUnpackSkipImages() * imageSize );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java
index b74d0a6b8..51d8ca6fe 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -46,10 +46,15 @@ package jogamp.opengl.glu.mipmap;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLContext;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.GLException;
+
import java.nio.*;
+
import com.jogamp.common.nio.Buffers;
/**
@@ -57,11 +62,11 @@ import com.jogamp.common.nio.Buffers;
* @author Administrator
*/
public class Mipmap {
-
+
/** Creates a new instance of Mipmap */
public Mipmap() {
}
-
+
public static int computeLog( int value ) {
int i = 0;
// Error
@@ -79,7 +84,7 @@ public class Mipmap {
i++;
}
}
-
+
/* Compute the nearest power of 2 number. This algorithm is a little strange
* but it works quite well.
*/
@@ -99,7 +104,7 @@ public class Mipmap {
i *= 2;
}
}
-
+
public static short GLU_SWAP_2_BYTES( short s ) {
byte b = 0;
b = (byte)( s >>> 8 );
@@ -107,26 +112,26 @@ public class Mipmap {
s = (short)( s | (0x00FF & b) );
return( s );
}
-
- public static int GLU_SWAP_4_BYTES( int i ) {
+
+ public static int GLU_SWAP_4_BYTES( final int i ) {
int t = i << 24;
t |= 0x00FF0000 & ( i << 8 );
t |= 0x0000FF00 & ( i >>> 8 );
t |= 0x000000FF & ( i >>> 24 );
return( t );
}
-
- public static float GLU_SWAP_4_BYTES( float f ) {
- int i = Float.floatToRawIntBits( f );
- float temp = Float.intBitsToFloat( i );
+
+ public static float GLU_SWAP_4_BYTES( final float f ) {
+ final int i = Float.floatToRawIntBits( f );
+ final float temp = Float.intBitsToFloat( i );
return( temp );
}
-
- public static int checkMipmapArgs( int internalFormat, int format, int type ) {
+
+ public static int checkMipmapArgs( final int internalFormat, final int format, final int type ) {
if( !legalFormat( format ) || !legalType( type ) ) {
return( GLU.GLU_INVALID_ENUM );
}
- if( format == GL2GL3.GL_STENCIL_INDEX ) {
+ if( format == GL2ES2.GL_STENCIL_INDEX ) {
return( GLU.GLU_INVALID_ENUM );
}
if( !isLegalFormatForPackedPixelType( format, type ) ) {
@@ -134,20 +139,20 @@ public class Mipmap {
}
return( 0 );
}
-
- public static boolean legalFormat( int format ) {
+
+ public static boolean legalFormat( final int format ) {
switch( format ) {
case( GL2.GL_COLOR_INDEX ):
- case( GL2GL3.GL_STENCIL_INDEX ):
- case( GL2GL3.GL_DEPTH_COMPONENT ):
- case( GL2GL3.GL_RED ):
- case( GL2GL3.GL_GREEN ):
- case( GL2GL3.GL_BLUE ):
- case( GL2GL3.GL_ALPHA ):
- case( GL2GL3.GL_RGB ):
- case( GL2GL3.GL_RGBA ):
- case( GL2GL3.GL_LUMINANCE ):
- case( GL2GL3.GL_LUMINANCE_ALPHA ):
+ case( GL2ES2.GL_STENCIL_INDEX ):
+ case( GL2ES2.GL_DEPTH_COMPONENT ):
+ case( GL2ES2.GL_RED ):
+ case( GL2ES3.GL_GREEN ):
+ case( GL2ES3.GL_BLUE ):
+ case( GL.GL_ALPHA ):
+ case( GL.GL_RGB ):
+ case( GL.GL_RGBA ):
+ case( GL.GL_LUMINANCE ):
+ case( GL.GL_LUMINANCE_ALPHA ):
case( GL2GL3.GL_BGR ):
case( GL.GL_BGRA ):
return( true );
@@ -155,93 +160,93 @@ public class Mipmap {
return( false );
}
}
-
- public static boolean legalType( int type ) {
+
+ public static boolean legalType( final int type ) {
switch( type ) {
case( GL2.GL_BITMAP ):
- case( GL2GL3.GL_BYTE ):
- case( GL2GL3.GL_UNSIGNED_BYTE ):
- case( GL2GL3.GL_SHORT ):
- case( GL2GL3.GL_UNSIGNED_SHORT ):
- case( GL2GL3.GL_INT ):
- case( GL2GL3.GL_UNSIGNED_INT ):
- case( GL2GL3.GL_FLOAT ):
+ case( GL.GL_BYTE ):
+ case( GL.GL_UNSIGNED_BYTE ):
+ case( GL.GL_SHORT ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_UNSIGNED_INT ):
+ case( GL.GL_FLOAT ):
case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
- case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
- case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
- case( GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
- case( GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ):
- case( GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
return( true );
default:
return( false );
}
}
-
- public static boolean isTypePackedPixel( int type ) {
+
+ public static boolean isTypePackedPixel( final int type ) {
assert( legalType( type ) );
-
+
if( type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ||
type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ||
- type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ||
+ type == GL.GL_UNSIGNED_SHORT_5_6_5 ||
type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ||
- type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ||
+ type == GL.GL_UNSIGNED_SHORT_4_4_4_4 ||
type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ||
- type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ||
+ type == GL.GL_UNSIGNED_SHORT_5_5_5_1 ||
type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ||
type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ||
type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ||
- type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ||
- type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) {
+ type == GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ||
+ type == GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ) {
return( true );
}
return( false );
}
-
- public static boolean isLegalFormatForPackedPixelType( int format, int type ) {
+
+ public static boolean isLegalFormatForPackedPixelType( final int format, final int type ) {
// if not a packed pixel type then return true
if( isTypePackedPixel( type ) ) {
return( true );
}
-
+
// 3_3_2/2_3_3_REV & 5_6_5/5_6_5_REV are only compatible with RGB
if( (type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 || type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ||
- type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 || type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV )
- & format != GL2GL3.GL_RGB ) {
+ type == GL.GL_UNSIGNED_SHORT_5_6_5 || type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV )
+ & format != GL.GL_RGB ) {
return( false );
}
-
+
// 4_4_4_4/4_4_4_4_REV & 5_5_5_1/1_5_5_5_REV & 8_8_8_8/8_8_8_8_REV &
// 10_10_10_2/2_10_10_10_REV are only campatible with RGBA, BGRA & ARGB_EXT
- if( ( type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ||
+ if( ( type == GL.GL_UNSIGNED_SHORT_4_4_4_4 ||
type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ||
- type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ||
+ type == GL.GL_UNSIGNED_SHORT_5_5_5_1 ||
type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ||
type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ||
type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ||
- type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ||
- type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) &&
+ type == GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ||
+ type == GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ) &&
(format != GL.GL_RGBA && format != GL.GL_BGRA) ) {
return( false );
}
return( true );
}
-
- public static boolean isLegalLevels( int userLevel, int baseLevel, int maxLevel,
- int totalLevels ) {
+
+ public static boolean isLegalLevels( final int userLevel, final int baseLevel, final int maxLevel,
+ final int totalLevels ) {
if( (baseLevel < 0) || (baseLevel < userLevel) || (maxLevel < baseLevel) ||
(totalLevels < maxLevel) ) {
return( false );
}
return( true );
}
-
+
/* Given user requested textures size, determine if it fits. If it doesn't then
* halve both sides and make the determination again until it does fit ( for
* IR only ).
@@ -249,15 +254,15 @@ public class Mipmap {
* advertise the texture extension.
* Note that proxy textures are implemented but not according to spec in IMPACT*
*/
- public static void closestFit( GL gl, int target, int width, int height, int internalFormat,
- int format, int type, int[] newWidth, int[] newHeight ) {
- // Use proxy textures if OpenGL version >= 1.1
- if( Double.parseDouble( gl.glGetString( GL.GL_VERSION ).trim().substring( 0, 3 ) ) >= 1.1 ) {
+ public static void closestFit( final GL gl, final int target, final int width, final int height, final int internalFormat,
+ final int format, final int type, final int[] newWidth, final int[] newHeight ) {
+ // Use proxy textures if OpenGL GL2/GL3 version >= 1.1
+ if( gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version110) >= 0 ) {
int widthPowerOf2 = nearestPower( width );
int heightPowerOf2 = nearestPower( height );
- int[] proxyWidth = new int[1];
+ final int[] proxyWidth = new int[1];
boolean noProxyTextures = false;
-
+
// Some drivers (in particular, ATI's) seem to set a GL error
// when proxy textures are used even though this is in violation
// of the spec. Guard against this and interactions with the
@@ -265,31 +270,31 @@ public class Mipmap {
try {
do {
// compute level 1 width & height, clamping each at 1
- int widthAtLevelOne = ( ( width > 1 ) ? (widthPowerOf2 >> 1) : widthPowerOf2 );
- int heightAtLevelOne = ( ( height > 1 ) ? (heightPowerOf2 >> 1) : heightPowerOf2 );
+ final int widthAtLevelOne = ( ( width > 1 ) ? (widthPowerOf2 >> 1) : widthPowerOf2 );
+ final int heightAtLevelOne = ( ( height > 1 ) ? (heightPowerOf2 >> 1) : heightPowerOf2 );
int proxyTarget;
-
+
assert( widthAtLevelOne > 0 );
assert( heightAtLevelOne > 0 );
-
+
// does width x height at level 1 & all their mipmaps fit?
- if( target == GL2GL3.GL_TEXTURE_2D || target == GL2GL3.GL_PROXY_TEXTURE_2D ) {
+ if( target == GL.GL_TEXTURE_2D || target == GL2GL3.GL_PROXY_TEXTURE_2D ) {
proxyTarget = GL2GL3.GL_PROXY_TEXTURE_2D;
gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne,
heightAtLevelOne, 0, format, type, null );
- } else if( (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_X) ||
- (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_X) ||
- (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_Y) ||
- (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ||
- (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_Z) ||
- (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ) {
+ } else if( (target == GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X) ||
+ (target == GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_X) ||
+ (target == GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Y) ||
+ (target == GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ||
+ (target == GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Z) ||
+ (target == GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ) {
proxyTarget = GL2GL3.GL_PROXY_TEXTURE_CUBE_MAP;
gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne,
heightAtLevelOne, 0, format, type, null );
} else {
assert( target == GL2GL3.GL_TEXTURE_1D || target == GL2GL3.GL_PROXY_TEXTURE_1D );
proxyTarget = GL2GL3.GL_PROXY_TEXTURE_1D;
- gl.getGL2GL3().glTexImage1D( proxyTarget, 1, internalFormat, widthAtLevelOne,
+ gl.getGL2GL3().glTexImage1D( proxyTarget, 1, internalFormat, widthAtLevelOne,
0, format, type, null );
}
if(gl.isGL2GL3()) {
@@ -313,7 +318,7 @@ public class Mipmap {
}
// else it does fit
} while( proxyWidth[0] == 0 );
- } catch (GLException e) {
+ } catch (final GLException e) {
noProxyTextures = true;
}
// loop must terminate
@@ -324,8 +329,8 @@ public class Mipmap {
return;
}
}
- int[] maxsize = new int[1];
- gl.glGetIntegerv( GL2GL3.GL_MAX_TEXTURE_SIZE, maxsize , 0);
+ final int[] maxsize = new int[1];
+ gl.glGetIntegerv( GL.GL_MAX_TEXTURE_SIZE, maxsize , 0);
// clamp user's texture sizes to maximum sizes, if necessary
newWidth[0] = nearestPower( width );
if( newWidth[0] > maxsize[0] ) {
@@ -336,27 +341,27 @@ public class Mipmap {
newHeight[0] = maxsize[0];
}
}
-
- public static void closestFit3D( GL gl, int target, int width, int height, int depth,
- int internalFormat, int format, int type, int[] newWidth, int[] newHeight,
- int[] newDepth ) {
+
+ public static void closestFit3D( final GL gl, final int target, final int width, final int height, final int depth,
+ final int internalFormat, final int format, final int type, final int[] newWidth, final int[] newHeight,
+ final int[] newDepth ) {
int widthPowerOf2 = nearestPower( width );
int heightPowerOf2 = nearestPower( height );
int depthPowerOf2 = nearestPower( depth );
- int[] proxyWidth = new int[1];
-
+ final int[] proxyWidth = new int[1];
+
do {
// compute level 1 width & height & depth, clamping each at 1
- int widthAtLevelOne = (widthPowerOf2 > 1) ? widthPowerOf2 >> 1 : widthPowerOf2;
- int heightAtLevelOne = (heightPowerOf2 > 1) ? heightPowerOf2 >> 1 : heightPowerOf2;
- int depthAtLevelOne = (depthPowerOf2 > 1) ? depthPowerOf2 >> 1 : depthPowerOf2;
+ final int widthAtLevelOne = (widthPowerOf2 > 1) ? widthPowerOf2 >> 1 : widthPowerOf2;
+ final int heightAtLevelOne = (heightPowerOf2 > 1) ? heightPowerOf2 >> 1 : heightPowerOf2;
+ final int depthAtLevelOne = (depthPowerOf2 > 1) ? depthPowerOf2 >> 1 : depthPowerOf2;
int proxyTarget = 0;
assert( widthAtLevelOne > 0 );
assert( heightAtLevelOne > 0 );
assert( depthAtLevelOne > 0 );
-
+
// does width x height x depth at level 1 & all their mipmaps fit?
- if( target == GL2GL3.GL_TEXTURE_3D || target == GL2GL3.GL_PROXY_TEXTURE_3D ) {
+ if( target == GL2ES2.GL_TEXTURE_3D || target == GL2GL3.GL_PROXY_TEXTURE_3D ) {
proxyTarget = GL2GL3.GL_PROXY_TEXTURE_3D;
gl.getGL2GL3().glTexImage3D( proxyTarget, 1, internalFormat, widthAtLevelOne,
heightAtLevelOne, depthAtLevelOne, 0, format, type, null );
@@ -378,38 +383,38 @@ public class Mipmap {
}
} while( proxyWidth[0] == 0 );
// loop must terminate
-
+
// return the width & height at level 0 that fits
newWidth[0] = widthPowerOf2;
newHeight[0] = heightPowerOf2;
newDepth[0] = depthPowerOf2;
}
-
- public static int elements_per_group( int format, int type ) {
+
+ public static int elements_per_group( final int format, final int type ) {
// Return the number of elements per grtoup of a specified gromat
-
+
// If the type is packedpixels then answer is 1
if( type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ||
type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ||
- type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ||
+ type == GL.GL_UNSIGNED_SHORT_5_6_5 ||
type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ||
- type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ||
+ type == GL.GL_UNSIGNED_SHORT_4_4_4_4 ||
type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ||
- type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ||
+ type == GL.GL_UNSIGNED_SHORT_5_5_5_1 ||
type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ||
type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ||
type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ||
- type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ||
- type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) {
+ type == GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ||
+ type == GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ) {
return( 1 );
}
-
+
// Types are not packed pixels so get elements per group
switch( format ) {
- case( GL2GL3.GL_RGB ):
+ case( GL.GL_RGB ):
case( GL2GL3.GL_BGR ):
return( 3 );
- case( GL2GL3.GL_LUMINANCE_ALPHA ):
+ case( GL.GL_LUMINANCE_ALPHA ):
return( 2 );
case( GL.GL_RGBA ):
case( GL.GL_BGRA ):
@@ -418,49 +423,49 @@ public class Mipmap {
return( 1 );
}
}
-
- public static int bytes_per_element( int type ) {
+
+ public static int bytes_per_element( final int type ) {
// return the number of bytes per element, based on the element type
-
+
switch( type ) {
case( GL2.GL_BITMAP ):
- case( GL2GL3.GL_BYTE ):
- case( GL2GL3.GL_UNSIGNED_BYTE ):
+ case( GL.GL_BYTE ):
+ case( GL.GL_UNSIGNED_BYTE ):
case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
return( 1 );
- case( GL2GL3.GL_SHORT ):
- case( GL2GL3.GL_UNSIGNED_SHORT ):
- case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ):
+ case( GL.GL_SHORT ):
+ case( GL.GL_UNSIGNED_SHORT ):
+ case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
- case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ):
+ case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
- case( GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ):
+ case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
return( 2 );
- case( GL2GL3.GL_INT ):
- case( GL2GL3.GL_UNSIGNED_INT ):
+ case( GL2ES2.GL_INT ):
+ case( GL.GL_UNSIGNED_INT ):
case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
- case( GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ):
- case( GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ):
- case( GL2GL3.GL_FLOAT ):
+ case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
+ case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+ case( GL.GL_FLOAT ):
return( 4 );
default:
return( 4 );
}
}
-
- public static boolean is_index( int format ) {
- return( format == GL2.GL_COLOR_INDEX || format == GL2GL3.GL_STENCIL_INDEX );
+
+ public static boolean is_index( final int format ) {
+ return( format == GL2.GL_COLOR_INDEX || format == GL2ES2.GL_STENCIL_INDEX );
}
-
+
/* Compute memory required for internal packed array of data of given type and format. */
-
- public static int image_size( int width, int height, int format, int type ) {
+
+ public static int image_size( final int width, final int height, final int format, final int type ) {
int bytes_per_row;
int components;
-
+
assert( width > 0 );
assert( height > 0 );
components = elements_per_group( format, type );
@@ -471,72 +476,72 @@ public class Mipmap {
}
return( bytes_per_row * height * components );
}
-
- public static int imageSize3D( int width, int height, int depth, int format, int type ) {
- int components = elements_per_group( format, type );
- int bytes_per_row = bytes_per_element( type ) * width;
-
+
+ public static int imageSize3D( final int width, final int height, final int depth, final int format, final int type ) {
+ final int components = elements_per_group( format, type );
+ final int bytes_per_row = bytes_per_element( type ) * width;
+
assert( width > 0 && height > 0 && depth > 0 );
assert( type != GL2.GL_BITMAP );
-
+
return( bytes_per_row * height * depth * components );
}
-
- public static void retrieveStoreModes( GL gl, PixelStorageModes psm ) {
- int[] a = new int[1];
- gl.glGetIntegerv( GL2GL3.GL_UNPACK_ALIGNMENT, a, 0);
+
+ public static void retrieveStoreModes( final GL gl, final PixelStorageModes psm ) {
+ final int[] a = new int[1];
+ gl.glGetIntegerv( GL.GL_UNPACK_ALIGNMENT, a, 0);
psm.setUnpackAlignment( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_UNPACK_ROW_LENGTH, a, 0);
+ gl.glGetIntegerv( GL2ES2.GL_UNPACK_ROW_LENGTH, a, 0);
psm.setUnpackRowLength( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_ROWS, a, 0);
+ gl.glGetIntegerv( GL2ES2.GL_UNPACK_SKIP_ROWS, a, 0);
psm.setUnpackSkipRows( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_PIXELS, a, 0);
+ gl.glGetIntegerv( GL2ES2.GL_UNPACK_SKIP_PIXELS, a, 0);
psm.setUnpackSkipPixels( a[0] );
gl.glGetIntegerv( GL2GL3.GL_UNPACK_LSB_FIRST, a, 0);
psm.setUnpackLsbFirst( ( a[0] == 1 ) );
gl.glGetIntegerv( GL2GL3.GL_UNPACK_SWAP_BYTES, a, 0);
psm.setUnpackSwapBytes( ( a[0] == 1 ) );
-
- gl.glGetIntegerv( GL2GL3.GL_PACK_ALIGNMENT, a, 0);
+
+ gl.glGetIntegerv( GL.GL_PACK_ALIGNMENT, a, 0);
psm.setPackAlignment( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_PACK_ROW_LENGTH, a, 0);
+ gl.glGetIntegerv( GL2ES3.GL_PACK_ROW_LENGTH, a, 0);
psm.setPackRowLength( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_ROWS, a, 0);
+ gl.glGetIntegerv( GL2ES3.GL_PACK_SKIP_ROWS, a, 0);
psm.setPackSkipRows( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_PIXELS, a, 0);
+ gl.glGetIntegerv( GL2ES3.GL_PACK_SKIP_PIXELS, a, 0);
psm.setPackSkipPixels( a[0] );
gl.glGetIntegerv( GL2GL3.GL_PACK_LSB_FIRST, a, 0);
psm.setPackLsbFirst( ( a[0] == 1 ) );
gl.glGetIntegerv( GL2GL3.GL_PACK_SWAP_BYTES, a, 0);
psm.setPackSwapBytes( ( a[0] == 1 ) );
}
-
- public static void retrieveStoreModes3D( GL gl, PixelStorageModes psm ) {
- int[] a = new int[1];
- gl.glGetIntegerv( GL2GL3.GL_UNPACK_ALIGNMENT, a, 0);
+
+ public static void retrieveStoreModes3D( final GL gl, final PixelStorageModes psm ) {
+ final int[] a = new int[1];
+ gl.glGetIntegerv( GL.GL_UNPACK_ALIGNMENT, a, 0);
psm.setUnpackAlignment( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_UNPACK_ROW_LENGTH, a, 0);
+ gl.glGetIntegerv( GL2ES2.GL_UNPACK_ROW_LENGTH, a, 0);
psm.setUnpackRowLength( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_ROWS, a, 0);
+ gl.glGetIntegerv( GL2ES2.GL_UNPACK_SKIP_ROWS, a, 0);
psm.setUnpackSkipRows( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_PIXELS, a, 0);
+ gl.glGetIntegerv( GL2ES2.GL_UNPACK_SKIP_PIXELS, a, 0);
psm.setUnpackSkipPixels( a[0] );
gl.glGetIntegerv( GL2GL3.GL_UNPACK_LSB_FIRST, a, 0);
psm.setUnpackLsbFirst( ( a[0] == 1 ) );
gl.glGetIntegerv( GL2GL3.GL_UNPACK_SWAP_BYTES, a, 0);
psm.setUnpackSwapBytes( ( a[0] == 1 ) );
- gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_IMAGES, a, 0);
+ gl.glGetIntegerv( GL2ES3.GL_UNPACK_SKIP_IMAGES, a, 0);
psm.setUnpackSkipImages( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_UNPACK_IMAGE_HEIGHT, a, 0);
+ gl.glGetIntegerv( GL2ES3.GL_UNPACK_IMAGE_HEIGHT, a, 0);
psm.setUnpackImageHeight( a[0] );
-
- gl.glGetIntegerv( GL2GL3.GL_PACK_ALIGNMENT, a, 0);
+
+ gl.glGetIntegerv( GL.GL_PACK_ALIGNMENT, a, 0);
psm.setPackAlignment( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_PACK_ROW_LENGTH, a, 0);
+ gl.glGetIntegerv( GL2ES3.GL_PACK_ROW_LENGTH, a, 0);
psm.setPackRowLength( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_ROWS, a, 0);
+ gl.glGetIntegerv( GL2ES3.GL_PACK_SKIP_ROWS, a, 0);
psm.setPackSkipRows( a[0] );
- gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_PIXELS, a, 0 );
+ gl.glGetIntegerv( GL2ES3.GL_PACK_SKIP_PIXELS, a, 0 );
psm.setPackSkipPixels( a[0] );
gl.glGetIntegerv( GL2GL3.GL_PACK_LSB_FIRST, a, 0 );
psm.setPackLsbFirst( ( a[0] == 1 ) );
@@ -547,19 +552,19 @@ public class Mipmap {
gl.glGetIntegerv( GL2GL3.GL_PACK_IMAGE_HEIGHT, a, 0 );
psm.setPackImageHeight( a[0] );
}
-
- public static int gluScaleImage( GL gl, int format, int widthin, int heightin,
- int typein, ByteBuffer datain, int widthout, int heightout,
- int typeout, ByteBuffer dataout ) {
- int datainPos = datain.position();
- int dataoutPos = dataout.position();
+
+ public static int gluScaleImage( final GL gl, final int format, final int widthin, final int heightin,
+ final int typein, final ByteBuffer datain, final int widthout, final int heightout,
+ final int typeout, final ByteBuffer dataout ) {
+ final int datainPos = datain.position();
+ final int dataoutPos = dataout.position();
try {
int components;
ByteBuffer beforeimage;
ByteBuffer afterimage;
- PixelStorageModes psm = new PixelStorageModes();
-
+ final PixelStorageModes psm = new PixelStorageModes();
+
if( (widthin == 0) || (heightin == 0) || (widthout == 0) || (heightout == 0) ) {
return( 0 );
}
@@ -575,138 +580,139 @@ public class Mipmap {
if( !isLegalFormatForPackedPixelType( format, typeout ) ) {
return( GLU.GLU_INVALID_OPERATION );
}
- beforeimage = Buffers.newDirectByteBuffer( image_size( widthin, heightin, format, GL2GL3.GL_UNSIGNED_SHORT ) );
- afterimage = Buffers.newDirectByteBuffer( image_size( widthout, heightout, format, GL2GL3.GL_UNSIGNED_SHORT ) );
+ beforeimage = Buffers.newDirectByteBuffer( image_size( widthin, heightin, format, GL.GL_UNSIGNED_SHORT ) );
+ afterimage = Buffers.newDirectByteBuffer( image_size( widthout, heightout, format, GL.GL_UNSIGNED_SHORT ) );
if( beforeimage == null || afterimage == null ) {
return( GLU.GLU_OUT_OF_MEMORY );
}
-
+
retrieveStoreModes( gl, psm );
Image.fill_image( psm, widthin, heightin, format, typein, is_index( format ), datain, beforeimage.asShortBuffer() );
components = elements_per_group( format, 0 );
ScaleInternal.scale_internal( components, widthin, heightin, beforeimage.asShortBuffer(), widthout, heightout, afterimage.asShortBuffer() );
Image.empty_image( psm, widthout, heightout, format, typeout, is_index( format ), afterimage.asShortBuffer(), dataout );
-
+
return( 0 );
} finally {
datain.position(datainPos);
dataout.position(dataoutPos);
}
}
-
- public static int gluBuild1DMipmapLevels( GL gl, int target, int internalFormat,
- int width, int format, int type, int userLevel, int baseLevel,
- int maxLevel, ByteBuffer data ) {
- int dataPos = data.position();
+
+ public static int gluBuild1DMipmapLevels( final GL gl, final int target, final int internalFormat,
+ final int width, final int format, final int type, final int userLevel, final int baseLevel,
+ final int maxLevel, final ByteBuffer data ) {
+ final int dataPos = data.position();
try {
int levels;
-
- int rc = checkMipmapArgs( internalFormat, format, type );
+
+ final int rc = checkMipmapArgs( internalFormat, format, type );
if( rc != 0 ) {
return( rc );
}
-
+
if( width < 1 ) {
return( GLU.GLU_INVALID_VALUE );
}
-
+
levels = computeLog( width );
-
+
levels += userLevel;
if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) {
return( GLU.GLU_INVALID_VALUE );
}
-
+
return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat, width,
width, format, type, userLevel, baseLevel, maxLevel, data ) );
} finally {
data.position(dataPos);
}
}
-
- public static int gluBuild1DMipmaps( GL gl, int target, int internalFormat, int width,
- int format, int type, ByteBuffer data ) {
- int dataPos = data.position();
+
+ public static int gluBuild1DMipmaps( final GL gl, final int target, final int internalFormat, final int width,
+ final int format, final int type, final ByteBuffer data ) {
+ final int dataPos = data.position();
try {
- int[] widthPowerOf2 = new int[1];
+ final int[] widthPowerOf2 = new int[1];
int levels;
- int[] dummy = new int[1];
-
- int rc = checkMipmapArgs( internalFormat, format, type );
+ final int[] dummy = new int[1];
+
+ final int rc = checkMipmapArgs( internalFormat, format, type );
if( rc != 0 ) {
return( rc );
}
-
+
if( width < 1 ) {
return( GLU.GLU_INVALID_VALUE );
}
-
+
closestFit( gl, target, width, 1, internalFormat, format, type, widthPowerOf2, dummy );
levels = computeLog( widthPowerOf2[0] );
-
- return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat,
+
+ return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat,
width, widthPowerOf2[0], format, type, 0, 0, levels, data ) );
} finally {
data.position(dataPos);
}
}
-
- public static int gluBuild2DMipmapLevels( GL gl, int target, int internalFormat,
- int width, int height, int format, int type, int userLevel,
- int baseLevel, int maxLevel, Object data ) {
- int dataPos = 0;
+ public static int gluBuild2DMipmapLevels( final GL gl, final int target, final int internalFormat,
+ final int width, final int height, final int format, final int type, final int userLevel,
+ final int baseLevel, final int maxLevel, final Object data ) {
int level, levels;
-
- int rc = checkMipmapArgs( internalFormat, format, type );
+
+ final int rc = checkMipmapArgs( internalFormat, format, type );
if( rc != 0 ) {
return( rc );
}
-
+
if( width < 1 || height < 1 ) {
return( GLU.GLU_INVALID_VALUE );
}
-
+
levels = computeLog( width );
level = computeLog( height );
if( level > levels ) {
levels = level;
}
-
+
levels += userLevel;
if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) {
return( GLU.GLU_INVALID_VALUE );
}
-
+
//PointerWrapper pointer = PointerWrapperFactory.getPointerWrapper( data );
- ByteBuffer buffer = null;
+ final ByteBuffer buffer;
if( data instanceof ByteBuffer ) {
buffer = (ByteBuffer)data;
- dataPos = buffer.position();
} else if( data instanceof byte[] ) {
- byte[] array = (byte[])data;
- buffer = ByteBuffer.allocateDirect(array.length);
- buffer.put(array);
+ final byte[] array = (byte[])data;
+ buffer = ByteBuffer.allocateDirect(array.length);
+ buffer.put(array);
+ buffer.flip();
} else if( data instanceof short[] ) {
- short[] array = (short[])data;
+ final short[] array = (short[])data;
buffer = ByteBuffer.allocateDirect( array.length * 2 );
- ShortBuffer sb = buffer.asShortBuffer();
+ final ShortBuffer sb = buffer.asShortBuffer();
sb.put( array );
} else if( data instanceof int[] ) {
- int[] array = (int[])data;
+ final int[] array = (int[])data;
buffer = ByteBuffer.allocateDirect( array.length * 4 );
- IntBuffer ib = buffer.asIntBuffer();
+ final IntBuffer ib = buffer.asIntBuffer();
ib.put( array );
} else if( data instanceof float[] ) {
- float[] array = (float[])data;
+ final float[] array = (float[])data;
buffer = ByteBuffer.allocateDirect( array.length * 4 );
- FloatBuffer fb = buffer.asFloatBuffer();
+ final FloatBuffer fb = buffer.asFloatBuffer();
fb.put( array );
+ } else {
+ throw new IllegalArgumentException("Unhandled data type: "+data.getClass().getName());
}
-
+
+ final int dataPos = buffer.position();
try {
return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat,
width, height, width, height, format, type, userLevel, baseLevel,
@@ -716,95 +722,96 @@ public class Mipmap {
}
}
-
- public static int gluBuild2DMipmaps( GL gl, int target, int internalFormat,
- int width, int height, int format, int type, Object data ) {
- int dataPos = 0;
- int[] widthPowerOf2 = new int[1];
- int[] heightPowerOf2 = new int[1];
+ public static int gluBuild2DMipmaps( final GL gl, final int target, final int internalFormat,
+ final int width, final int height, final int format, final int type, final Object data ) {
+ final int[] widthPowerOf2 = new int[1];
+ final int[] heightPowerOf2 = new int[1];
int level, levels;
-
- int rc = checkMipmapArgs( internalFormat, format, type );
+
+ final int rc = checkMipmapArgs( internalFormat, format, type );
if( rc != 0 ) {
return( rc );
}
-
+
if( width < 1 || height < 1 ) {
return( GLU.GLU_INVALID_VALUE );
}
-
- closestFit( gl, target, width, height, internalFormat, format, type,
+
+ closestFit( gl, target, width, height, internalFormat, format, type,
widthPowerOf2, heightPowerOf2 );
-
+
levels = computeLog( widthPowerOf2[0] );
level = computeLog( heightPowerOf2[0] );
if( level > levels ) {
levels = level;
}
-
+
//PointerWrapper pointer = PointerWrapperFactory.getPointerWrapper( data );
- ByteBuffer buffer = null;
+ final ByteBuffer buffer;
if( data instanceof ByteBuffer ) {
buffer = (ByteBuffer)data;
- dataPos = buffer.position();
} else if( data instanceof byte[] ) {
- byte[] array = (byte[])data;
- buffer = ByteBuffer.allocateDirect(array.length);
- buffer.put(array);
+ final byte[] array = (byte[])data;
+ buffer = ByteBuffer.allocateDirect(array.length);
+ buffer.put(array);
+ buffer.flip();
} else if( data instanceof short[] ) {
- short[] array = (short[])data;
+ final short[] array = (short[])data;
buffer = ByteBuffer.allocateDirect( array.length * 2 );
- ShortBuffer sb = buffer.asShortBuffer();
+ final ShortBuffer sb = buffer.asShortBuffer();
sb.put( array );
} else if( data instanceof int[] ) {
- int[] array = (int[])data;
+ final int[] array = (int[])data;
buffer = ByteBuffer.allocateDirect( array.length * 4 );
- IntBuffer ib = buffer.asIntBuffer();
+ final IntBuffer ib = buffer.asIntBuffer();
ib.put( array );
} else if( data instanceof float[] ) {
- float[] array = (float[])data;
+ final float[] array = (float[])data;
buffer = ByteBuffer.allocateDirect( array.length * 4 );
- FloatBuffer fb = buffer.asFloatBuffer();
+ final FloatBuffer fb = buffer.asFloatBuffer();
fb.put( array );
+ } else {
+ throw new IllegalArgumentException("Unhandled data type: "+data.getClass().getName());
}
-
+
+ final int dataPos = buffer.position();
try {
- return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat,
- width, height, widthPowerOf2[0], heightPowerOf2[0], format, type, 0,
+ return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat,
+ width, height, widthPowerOf2[0], heightPowerOf2[0], format, type, 0,
0, levels, buffer ) );
} finally {
buffer.position(dataPos);
}
}
-
-
- public static int gluBuild3DMipmaps( GL gl, int target, int internalFormat,
- int width, int height, int depth, int format, int type, ByteBuffer data ) {
- int dataPos = data.position();
+
+
+ public static int gluBuild3DMipmaps( final GL gl, final int target, final int internalFormat,
+ final int width, final int height, final int depth, final int format, final int type, final ByteBuffer data ) {
+ final int dataPos = data.position();
try {
- int[] widthPowerOf2 = new int[1];
- int[] heightPowerOf2 = new int[1];
- int[] depthPowerOf2 = new int[1];
+ final int[] widthPowerOf2 = new int[1];
+ final int[] heightPowerOf2 = new int[1];
+ final int[] depthPowerOf2 = new int[1];
int level, levels;
-
- int rc = checkMipmapArgs( internalFormat, format, type );
+
+ final int rc = checkMipmapArgs( internalFormat, format, type );
if( rc != 0 ) {
return( rc );
}
-
+
if( width < 1 || height < 1 || depth < 1 ) {
return( GLU.GLU_INVALID_VALUE );
}
-
+
if( type == GL2.GL_BITMAP ) {
return( GLU.GLU_INVALID_ENUM );
}
-
+
closestFit3D( gl, target, width, height, depth, internalFormat, format,
type, widthPowerOf2, heightPowerOf2, depthPowerOf2 );
-
+
levels = computeLog( widthPowerOf2[0] );
level = computeLog( heightPowerOf2[0] );
if( level > levels ) {
@@ -814,7 +821,7 @@ public class Mipmap {
if( level > levels ) {
levels = level;
}
-
+
return( BuildMipmap.gluBuild3DMipmapLevelsCore( gl, target, internalFormat, width,
height, depth, widthPowerOf2[0], heightPowerOf2[0], depthPowerOf2[0],
format, type, 0, 0, levels, data ) );
@@ -822,27 +829,27 @@ public class Mipmap {
data.position(dataPos);
}
}
-
- public static int gluBuild3DMipmapLevels( GL gl, int target, int internalFormat,
- int width, int height, int depth, int format, int type, int userLevel,
- int baseLevel, int maxLevel, ByteBuffer data ) {
- int dataPos = data.position();
+
+ public static int gluBuild3DMipmapLevels( final GL gl, final int target, final int internalFormat,
+ final int width, final int height, final int depth, final int format, final int type, final int userLevel,
+ final int baseLevel, final int maxLevel, final ByteBuffer data ) {
+ final int dataPos = data.position();
try {
int level, levels;
-
- int rc = checkMipmapArgs( internalFormat, format, type );
+
+ final int rc = checkMipmapArgs( internalFormat, format, type );
if( rc != 0 ) {
return( rc );
}
-
+
if( width < 1 || height < 1 || depth < 1 ) {
return( GLU.GLU_INVALID_VALUE );
}
-
+
if( type == GL2.GL_BITMAP ) {
return( GLU.GLU_INVALID_ENUM );
}
-
+
levels = computeLog( width );
level = computeLog( height );
if( level > levels ) {
@@ -852,12 +859,12 @@ public class Mipmap {
if( level > levels ) {
levels = level;
}
-
+
levels += userLevel;
if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) {
return( GLU.GLU_INVALID_VALUE );
}
-
+
return( BuildMipmap.gluBuild3DMipmapLevelsCore( gl, target, internalFormat, width,
height, depth, width, height, depth, format, type, userLevel,
baseLevel, maxLevel, data ) );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/PixelStorageModes.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/PixelStorageModes.java
index 0b1af8323..9b26647a8 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/PixelStorageModes.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/PixelStorageModes.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -129,7 +129,7 @@ public class PixelStorageModes {
* Holds value of property unpackImageHeight.
*/
private int unpackImageHeight;
-
+
/** Creates a new instance of PixelStorageModes */
public PixelStorageModes() {
}
@@ -147,7 +147,7 @@ public class PixelStorageModes {
* Setter for property packAlignment.
* @param packAlignment New value of property packAlignment.
*/
- public void setPackAlignment(int packAlignment) {
+ public void setPackAlignment(final int packAlignment) {
this.packAlignment = packAlignment;
}
@@ -165,7 +165,7 @@ public class PixelStorageModes {
* Setter for property packRowLength.
* @param packRowLength New value of property packRowLength.
*/
- public void setPackRowLength(int packRowLength) {
+ public void setPackRowLength(final int packRowLength) {
this.packRowLength = packRowLength;
}
@@ -183,7 +183,7 @@ public class PixelStorageModes {
* Setter for property packSkipRows.
* @param packSkipRows New value of property packSkipRows.
*/
- public void setPackSkipRows(int packSkipRows) {
+ public void setPackSkipRows(final int packSkipRows) {
this.packSkipRows = packSkipRows;
}
@@ -201,7 +201,7 @@ public class PixelStorageModes {
* Setter for property packSkipPixels.
* @param packSkipPixels New value of property packSkipPixels.
*/
- public void setPackSkipPixels(int packSkipPixels) {
+ public void setPackSkipPixels(final int packSkipPixels) {
this.packSkipPixels = packSkipPixels;
}
@@ -219,7 +219,7 @@ public class PixelStorageModes {
* Setter for property packLsbFirst.
* @param packLsbFirst New value of property packLsbFirst.
*/
- public void setPackLsbFirst(boolean packLsbFirst) {
+ public void setPackLsbFirst(final boolean packLsbFirst) {
this.packLsbFirst = packLsbFirst;
}
@@ -237,7 +237,7 @@ public class PixelStorageModes {
* Setter for property packSwapBytes.
* @param packSwapBytes New value of property packSwapBytes.
*/
- public void setPackSwapBytes(boolean packSwapBytes) {
+ public void setPackSwapBytes(final boolean packSwapBytes) {
this.packSwapBytes = packSwapBytes;
}
@@ -255,7 +255,7 @@ public class PixelStorageModes {
* Setter for property packSkipImages.
* @param packSkipImages New value of property packSkipImages.
*/
- public void setPackSkipImages(int packSkipImages) {
+ public void setPackSkipImages(final int packSkipImages) {
this.packSkipImages = packSkipImages;
}
@@ -273,7 +273,7 @@ public class PixelStorageModes {
* Setter for property packImageHeight.
* @param packImageHeight New value of property packImageHeight.
*/
- public void setPackImageHeight(int packImageHeight) {
+ public void setPackImageHeight(final int packImageHeight) {
this.packImageHeight = packImageHeight;
}
@@ -291,7 +291,7 @@ public class PixelStorageModes {
* Setter for property unpackAlignment.
* @param unpackAlignment New value of property unpackAlignment.
*/
- public void setUnpackAlignment(int unpackAlignment) {
+ public void setUnpackAlignment(final int unpackAlignment) {
this.unpackAlignment = unpackAlignment;
}
@@ -309,7 +309,7 @@ public class PixelStorageModes {
* Setter for property unpackRowLength.
* @param unpackRowLength New value of property unpackRowLength.
*/
- public void setUnpackRowLength(int unpackRowLength) {
+ public void setUnpackRowLength(final int unpackRowLength) {
this.unpackRowLength = unpackRowLength;
}
@@ -327,7 +327,7 @@ public class PixelStorageModes {
* Setter for property unpackSkipRows.
* @param unpackSkipRows New value of property unpackSkipRows.
*/
- public void setUnpackSkipRows(int unpackSkipRows) {
+ public void setUnpackSkipRows(final int unpackSkipRows) {
this.unpackSkipRows = unpackSkipRows;
}
@@ -345,7 +345,7 @@ public class PixelStorageModes {
* Setter for property unpackSkipPixels.
* @param unpackSkipPixels New value of property unpackSkipPixels.
*/
- public void setUnpackSkipPixels(int unpackSkipPixels) {
+ public void setUnpackSkipPixels(final int unpackSkipPixels) {
this.unpackSkipPixels = unpackSkipPixels;
}
@@ -363,7 +363,7 @@ public class PixelStorageModes {
* Setter for property unpackLsbFirst.
* @param unpackLsbFirst New value of property unpackLsbFirst.
*/
- public void setUnpackLsbFirst(boolean unpackLsbFirst) {
+ public void setUnpackLsbFirst(final boolean unpackLsbFirst) {
this.unpackLsbFirst = unpackLsbFirst;
}
@@ -381,7 +381,7 @@ public class PixelStorageModes {
* Setter for property unpackSwapBytes.
* @param unpackSwapBytes New value of property unpackSwapBytes.
*/
- public void setUnpackSwapBytes(boolean unpackSwapBytes) {
+ public void setUnpackSwapBytes(final boolean unpackSwapBytes) {
this.unpackSwapBytes = unpackSwapBytes;
}
@@ -399,7 +399,7 @@ public class PixelStorageModes {
* Setter for property unpackSkipImages.
* @param unpackSkipImages New value of property unpackSkipImages.
*/
- public void setUnpackSkipImages(int unpackSkipImages) {
+ public void setUnpackSkipImages(final int unpackSkipImages) {
this.unpackSkipImages = unpackSkipImages;
}
@@ -417,10 +417,10 @@ public class PixelStorageModes {
* Setter for property unpackImageHeight.
* @param unpackImageHeight New value of property unpackImageHeight.
*/
- public void setUnpackImageHeight(int unpackImageHeight) {
+ public void setUnpackImageHeight(final int unpackImageHeight) {
this.unpackImageHeight = unpackImageHeight;
}
-
-
+
+
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ScaleInternal.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ScaleInternal.java
index 5f086ceff..ccb75091c 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/ScaleInternal.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ScaleInternal.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -55,21 +55,21 @@ import com.jogamp.common.nio.Buffers;
* @author Administrator
*/
public class ScaleInternal {
-
- public static final float UINT_MAX = (float)(0x00000000FFFFFFFF);
-
- public static void scale_internal( int components, int widthin, int heightin,
- ShortBuffer datain, int widthout, int heightout, ShortBuffer dataout ) {
+
+ public static final float UINT_MAX = (0x00000000FFFFFFFF);
+
+ public static void scale_internal( final int components, final int widthin, final int heightin,
+ final ShortBuffer datain, final int widthout, final int heightout, final ShortBuffer dataout ) {
float x, lowx, highx, convx, halfconvx;
float y, lowy, highy, convy, halfconvy;
float xpercent, ypercent;
float percent;
// Max components in a format is 4, so...
- float[] totals = new float[4];
+ final float[] totals = new float[4];
float area;
int i, j, k, yint, xint, xindex, yindex;
int temp;
-
+
if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
HalveImage.halveImage( components, widthin, heightin, datain, dataout );
return;
@@ -101,7 +101,7 @@ public class ScaleInternal {
// data.
totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
area = 0.0f;
-
+
y = lowy;
yint = (int)Math.floor( y );
while( y < highy ) {
@@ -111,10 +111,10 @@ public class ScaleInternal {
} else {
ypercent = yint + 1 - y;
}
-
+
x = lowx;
xint = (int)Math.floor( x );
-
+
while( x < highx ) {
xindex = ( xint + widthin ) % widthin;
if( highx < xint + 1 ) {
@@ -122,21 +122,21 @@ public class ScaleInternal {
} else {
xpercent = xint + 1 - x;
}
-
+
percent = xpercent * ypercent;
area += percent;
temp = ( xindex + ( yindex * widthin) ) * components;
for( k = 0; k < components; k++ ) {
- totals[k] += datain.get( temp + k ) * percent;
+ totals[k] += datain.get( temp + k ) * percent;
}
-
+
xint++;
x = xint;
}
yint++;
y = yint;
}
-
+
temp = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
// totals[] should be rounded in the case of enlarging an RGB
@@ -146,22 +146,24 @@ public class ScaleInternal {
}
}
}
-
- public static void scale_internal_ubyte( int components, int widthin, int heightin,
- ByteBuffer datain, int widthout, int heightout,
- ByteBuffer dataout, int element_size, int ysize, int group_size ) {
- float x, convx;
- float y, convy;
+
+ public static void scale_internal_ubyte( final int components, final int widthin, final int heightin,
+ final ByteBuffer datain, final int widthout, final int heightout,
+ final ByteBuffer dataout, final int element_size, final int ysize, final int group_size ) {
+ final float x;
+ float convx;
+ final float y;
+ float convy;
float percent;
// Max components in a format is 4, so...
- float[] totals = new float[4];
+ final float[] totals = new float[4];
float area;
int i, j, k, xindex;
-
+
int temp, temp0;
int temp_index;
int outindex;
-
+
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
@@ -169,9 +171,9 @@ public class ScaleInternal {
int convy_int, convx_int;
int l, m;
int left, right;
-
+
if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
- HalveImage.halveImage_ubyte( components, widthin, heightin, datain, dataout,
+ HalveImage.halveImage_ubyte( components, widthin, heightin, datain, dataout,
element_size, ysize, group_size );
return;
}
@@ -181,35 +183,42 @@ public class ScaleInternal {
convy_float = convy - convy_int;
convx_int = (int)Math.floor( convx );
convx_float = convx - convx_int;
-
+
area = convx * convy;
-
+
lowy_int = 0;
lowy_float = 0.0f;
highy_int = convy_int;
highy_float = convy_float;
-
+
for( i = 0; i < heightout; i++ ) {
// Clamp here to be sure we don't read beyond input buffer.
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0.0f;
- highx_int = convx_int;
- highx_float = convx_float;
-
+ // If we have a single column, fix the max width values
+ // to prevent buffer overflow
+ if (widthin == 1 && widthout == 1) {
+ highx_int = 0;
+ highx_float = 0.0f;
+ } else {
+ highx_int = convx_int;
+ highx_float = convx_float;
+ }
+
for( j = 0; j < widthout; j++ ) {
-
+
// Ok, now apply box filter to box that goes from (lowx, lowy)
// to (highx, highy) on input data into this pixel on output
// data.
totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
-
+
// caulate the value for pixels in the 1st row
xindex = lowx_int * group_size;
if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
-
+
y_percent = 1 - lowy_float;
temp = xindex + lowy_int * ysize;
percent = y_percent * ( 1 - lowx_float );
@@ -232,7 +241,7 @@ public class ScaleInternal {
datain.position( temp_index );
totals[k] += ( 0x000000FF & datain.get() ) * percent;
}
-
+
// calculate the value for pixels in the last row
y_percent = highy_float;
percent = y_percent * ( 1 - lowx_float );
@@ -254,7 +263,7 @@ public class ScaleInternal {
datain.position( temp_index );
totals[k] += ( 0x000000FF & datain.get() ) * percent;
}
-
+
// calculate the value for the pixels in the 1st and last column
for( m = lowy_int + 1; m < highy_int; m++ ) {
left += ysize;
@@ -332,7 +341,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -349,7 +358,7 @@ public class ScaleInternal {
// Clamp to make sure we don't run off the right edge
if (highx_int > widthin - 1) {
- int delta = (highx_int - widthin + 1);
+ final int delta = (highx_int - widthin + 1);
lowx_int -= delta;
highx_int -= delta;
}
@@ -364,23 +373,25 @@ public class ScaleInternal {
}
}
}
-
- public static void scale_internal_byte( int components, int widthin, int heightin,
- ByteBuffer datain, int widthout, int heightout,
- ByteBuffer dataout, int element_size, int ysize,
- int group_size ) {
- float x, convx;
- float y, convy;
+
+ public static void scale_internal_byte( final int components, final int widthin, final int heightin,
+ final ByteBuffer datain, final int widthout, final int heightout,
+ final ByteBuffer dataout, final int element_size, final int ysize,
+ final int group_size ) {
+ final float x;
+ float convx;
+ final float y;
+ float convy;
float percent;
// Max components in a format is 4, so...
- float[] totals = new float[4];
+ final float[] totals = new float[4];
float area;
int i, j, k, xindex;
-
+
int temp, temp0;
int temp_index;
int outindex;
-
+
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
@@ -388,9 +399,9 @@ public class ScaleInternal {
int convy_int, convx_int;
int l, m;
int left, right;
-
+
if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
- HalveImage.halveImage_byte( components, widthin, heightin, datain, dataout,
+ HalveImage.halveImage_byte( components, widthin, heightin, datain, dataout,
element_size, ysize, group_size );
return;
}
@@ -400,34 +411,41 @@ public class ScaleInternal {
convy_float = convy - convy_int;
convx_int = (int)Math.floor( convx );
convx_float = convx - convx_int;
-
+
area = convx * convy;
-
+
lowy_int = 0;
lowy_float = 0.0f;
highy_int = convy_int;
highy_float = convy_float;
-
+
for( i = 0; i < heightout; i++ ) {
// Clamp here to be sure we don't read beyond input buffer.
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0.0f;
- highx_int = convx_int;
- highx_float = convx_float;
-
+ // If we have a single column, fix the max width values
+ // to prevent buffer overflow
+ if (widthin == 1 && widthout == 1) {
+ highx_int = 0;
+ highx_float = 0.0f;
+ } else {
+ highx_int = convx_int;
+ highx_float = convx_float;
+ }
+
for( j = 0; j < widthout; j++ ) {
-
+
// Ok, now apply box filter to box that goes from (lowx, lowy)
// to (highx, highy) on input data into this pixel on output
// data.
totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
-
+
// caulate the value for pixels in the 1st row
xindex = lowx_int * group_size;
if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
-
+
y_percent = 1 - lowy_float;
temp = xindex + lowy_int * ysize;
percent = y_percent * ( 1 - lowx_float );
@@ -450,7 +468,7 @@ public class ScaleInternal {
datain.position( temp_index );
totals[k] += datain.get() * percent;
}
-
+
// calculate the value for pixels in the last row
y_percent = highy_float;
percent = y_percent * ( 1 - lowx_float );
@@ -472,7 +490,7 @@ public class ScaleInternal {
datain.position( temp_index );
totals[k] += datain.get() * percent;
}
-
+
// calculate the value for the pixels in the 1st and last column
for( m = lowy_int + 1; m < highy_int; m++ ) {
left += ysize;
@@ -536,7 +554,7 @@ public class ScaleInternal {
totals[k] += datain.get() * percent;
}
}
-
+
// this is for the pixels in the body
temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
for( m = lowy_int + 1; m < highy_int; m++ ) {
@@ -550,7 +568,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -567,7 +585,7 @@ public class ScaleInternal {
// Clamp to make sure we don't run off the right edge
if (highx_int > widthin - 1) {
- int delta = (highx_int - widthin + 1);
+ final int delta = (highx_int - widthin + 1);
lowx_int -= delta;
highx_int -= delta;
}
@@ -582,23 +600,25 @@ public class ScaleInternal {
}
}
}
-
- public static void scale_internal_ushort( int components, int widthin, int heightin,
- ByteBuffer datain, int widthout, int heightout,
- ShortBuffer dataout, int element_size, int ysize,
- int group_size, boolean myswap_bytes ) {
- float x, convx;
- float y, convy;
+
+ public static void scale_internal_ushort( final int components, final int widthin, final int heightin,
+ final ByteBuffer datain, final int widthout, final int heightout,
+ final ShortBuffer dataout, final int element_size, final int ysize,
+ final int group_size, final boolean myswap_bytes ) {
+ final float x;
+ float convx;
+ final float y;
+ float convy;
float percent;
// Max components in a format is 4, so...
- float[] totals = new float[4];
+ final float[] totals = new float[4];
float area;
int i, j, k, xindex;
-
+
int temp, temp0;
int temp_index;
int outindex;
-
+
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
@@ -606,9 +626,9 @@ public class ScaleInternal {
int convy_int, convx_int;
int l, m;
int left, right;
-
+
if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
- HalveImage.halveImage_ushort( components, widthin, heightin, datain, dataout,
+ HalveImage.halveImage_ushort( components, widthin, heightin, datain, dataout,
element_size, ysize, group_size, myswap_bytes );
return;
}
@@ -618,41 +638,48 @@ public class ScaleInternal {
convy_float = convy - convy_int;
convx_int = (int)Math.floor( convx );
convx_float = convx - convx_int;
-
+
area = convx * convy;
-
+
lowy_int = 0;
lowy_float = 0.0f;
highy_int = convy_int;
highy_float = convy_float;
-
+
for( i = 0; i < heightout; i++ ) {
// Clamp here to be sure we don't read beyond input buffer.
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0.0f;
- highx_int = convx_int;
- highx_float = convx_float;
-
+ // If we have a single column, fix the max width values
+ // to prevent buffer overflow
+ if (widthin == 1 && widthout == 1) {
+ highx_int = 0;
+ highx_float = 0.0f;
+ } else {
+ highx_int = convx_int;
+ highx_float = convx_float;
+ }
+
for( j = 0; j < widthout; j++ ) {
-
+
// Ok, now apply box filter to box that goes from (lowx, lowy)
// to (highx, highy) on input data into this pixel on output
// data.
totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
-
+
// caulate the value for pixels in the 1st row
xindex = lowx_int * group_size;
if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
-
+
y_percent = 1 - lowy_float;
temp = xindex + lowy_int * ysize;
percent = y_percent * ( 1 - lowx_float );
for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
datain.position( temp_index );
if( myswap_bytes ) {
- totals[k] += ( 0x0000FFFF & ((int)Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * percent;
+ totals[k] += ( 0x0000FFFF & (Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * percent;
} else {
totals[k] += ( 0x0000FFFF & datain.getShort() ) * percent;
}
@@ -663,7 +690,7 @@ public class ScaleInternal {
for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
datain.position( temp_index );
if( myswap_bytes ) {
- totals[k] += ( 0x0000FFFF & ((int)Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * y_percent;
+ totals[k] += ( 0x0000FFFF & (Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * y_percent;
} else {
totals[k] += ( 0x0000FFFF & datain.getShort()) * y_percent;
}
@@ -680,7 +707,7 @@ public class ScaleInternal {
totals[k] += ( 0x0000FFFF & datain.getShort()) * percent;
}
}
-
+
// calculate the value for pixels in the last row
y_percent = highy_float;
percent = y_percent * ( 1 - lowx_float );
@@ -714,7 +741,7 @@ public class ScaleInternal {
totals[k] += ( 0x0000FFFF & datain.getShort()) * percent;
}
}
-
+
// calculate the value for the pixels in the 1st and last column
for( m = lowy_int + 1; m < highy_int; m++ ) {
left += ysize;
@@ -813,7 +840,7 @@ public class ScaleInternal {
}
}
}
-
+
// this is for the pixels in the body
temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
for( m = lowy_int + 1; m < highy_int; m++ ) {
@@ -831,7 +858,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -848,7 +875,7 @@ public class ScaleInternal {
// Clamp to make sure we don't run off the right edge
if (highx_int > widthin - 1) {
- int delta = (highx_int - widthin + 1);
+ final int delta = (highx_int - widthin + 1);
lowx_int -= delta;
highx_int -= delta;
}
@@ -863,23 +890,25 @@ public class ScaleInternal {
}
}
}
-
- public static void scale_internal_short( int components, int widthin, int heightin,
- ByteBuffer datain, int widthout, int heightout,
- ShortBuffer dataout, int element_size, int ysize,
- int group_size, boolean myswap_bytes ) {
- float x, convx;
- float y, convy;
+
+ public static void scale_internal_short( final int components, final int widthin, final int heightin,
+ final ByteBuffer datain, final int widthout, final int heightout,
+ final ShortBuffer dataout, final int element_size, final int ysize,
+ final int group_size, final boolean myswap_bytes ) {
+ final float x;
+ float convx;
+ final float y;
+ float convy;
float percent;
// Max components in a format is 4, so...
- float[] totals = new float[4];
+ final float[] totals = new float[4];
float area;
int i, j, k, xindex;
-
+
int temp, temp0;
int temp_index;
int outindex;
-
+
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
@@ -887,11 +916,11 @@ public class ScaleInternal {
int convy_int, convx_int;
int l, m;
int left, right;
-
+
int swapbuf; // unsigned buffer
-
+
if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
- HalveImage.halveImage_short( components, widthin, heightin, datain, dataout,
+ HalveImage.halveImage_short( components, widthin, heightin, datain, dataout,
element_size, ysize, group_size, myswap_bytes );
return;
}
@@ -901,34 +930,41 @@ public class ScaleInternal {
convy_float = convy - convy_int;
convx_int = (int)Math.floor( convx );
convx_float = convx - convx_int;
-
+
area = convx * convy;
-
+
lowy_int = 0;
lowy_float = 0.0f;
highy_int = convy_int;
highy_float = convy_float;
-
+
for( i = 0; i < heightout; i++ ) {
// Clamp here to be sure we don't read beyond input buffer.
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0.0f;
- highx_int = convx_int;
- highx_float = convx_float;
-
+ // If we have a single column, fix the max width values
+ // to prevent buffer overflow
+ if (widthin == 1 && widthout == 1) {
+ highx_int = 0;
+ highx_float = 0.0f;
+ } else {
+ highx_int = convx_int;
+ highx_float = convx_float;
+ }
+
for( j = 0; j < widthout; j++ ) {
-
+
// Ok, now apply box filter to box that goes from (lowx, lowy)
// to (highx, highy) on input data into this pixel on output
// data.
totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
-
+
// caulate the value for pixels in the 1st row
xindex = lowx_int * group_size;
if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
-
+
y_percent = 1 - lowy_float;
temp = xindex + lowy_int * ysize;
percent = y_percent * ( 1 - lowx_float );
@@ -966,7 +1002,7 @@ public class ScaleInternal {
totals[k] += datain.getShort() * percent;
}
}
-
+
// calculate the value for pixels in the last row
y_percent = highy_float;
percent = y_percent * ( 1 - lowx_float );
@@ -1003,7 +1039,7 @@ public class ScaleInternal {
totals[k] += datain.getShort() * percent;
}
}
-
+
// calculate the value for the pixels in the 1st and last column
for( m = lowy_int + 1; m < highy_int; m++ ) {
left += ysize;
@@ -1109,7 +1145,7 @@ public class ScaleInternal {
}
}
}
-
+
// this is for the pixels in the body
temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
for( m = lowy_int + 1; m < highy_int; m++ ) {
@@ -1128,7 +1164,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -1145,7 +1181,7 @@ public class ScaleInternal {
// Clamp to make sure we don't run off the right edge
if (highx_int > widthin - 1) {
- int delta = (highx_int - widthin + 1);
+ final int delta = (highx_int - widthin + 1);
lowx_int -= delta;
highx_int -= delta;
}
@@ -1160,23 +1196,25 @@ public class ScaleInternal {
}
}
}
-
- public static void scale_internal_uint( int components, int widthin, int heightin,
- ByteBuffer datain, int widthout, int heightout,
- IntBuffer dataout, int element_size, int ysize,
- int group_size, boolean myswap_bytes ) {
- float x, convx;
- float y, convy;
+
+ public static void scale_internal_uint( final int components, final int widthin, final int heightin,
+ final ByteBuffer datain, final int widthout, final int heightout,
+ final IntBuffer dataout, final int element_size, final int ysize,
+ final int group_size, final boolean myswap_bytes ) {
+ final float x;
+ float convx;
+ final float y;
+ float convy;
float percent;
// Max components in a format is 4, so...
- float[] totals = new float[4];
+ final float[] totals = new float[4];
float area;
int i, j, k, xindex;
-
+
int temp, temp0;
int temp_index;
int outindex;
-
+
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
@@ -1184,9 +1222,9 @@ public class ScaleInternal {
int convy_int, convx_int;
int l, m;
int left, right;
-
+
if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
- HalveImage.halveImage_uint( components, widthin, heightin, datain, dataout,
+ HalveImage.halveImage_uint( components, widthin, heightin, datain, dataout,
element_size, ysize, group_size, myswap_bytes );
return;
}
@@ -1196,34 +1234,41 @@ public class ScaleInternal {
convy_float = convy - convy_int;
convx_int = (int)Math.floor( convx );
convx_float = convx - convx_int;
-
+
area = convx * convy;
-
+
lowy_int = 0;
lowy_float = 0.0f;
highy_int = convy_int;
highy_float = convy_float;
-
+
for( i = 0; i < heightout; i++ ) {
// Clamp here to be sure we don't read beyond input buffer.
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0.0f;
- highx_int = convx_int;
- highx_float = convx_float;
-
+ // If we have a single column, fix the max width values
+ // to prevent buffer overflow
+ if (widthin == 1 && widthout == 1) {
+ highx_int = 0;
+ highx_float = 0.0f;
+ } else {
+ highx_int = convx_int;
+ highx_float = convx_float;
+ }
+
for( j = 0; j < widthout; j++ ) {
-
+
// Ok, now apply box filter to box that goes from (lowx, lowy)
// to (highx, highy) on input data into this pixel on output
// data.
totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
-
+
// caulate the value for pixels in the 1st row
xindex = lowx_int * group_size;
if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
-
+
y_percent = 1 - lowy_float;
temp = xindex + lowy_int * ysize;
percent = y_percent * ( 1 - lowx_float );
@@ -1258,7 +1303,7 @@ public class ScaleInternal {
totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
}
}
-
+
// calculate the value for pixels in the last row
y_percent = highy_float;
percent = y_percent * ( 1 - lowx_float );
@@ -1292,7 +1337,7 @@ public class ScaleInternal {
totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
}
}
-
+
// calculate the value for the pixels in the 1st and last column
for( m = lowy_int + 1; m < highy_int; m++ ) {
left += ysize;
@@ -1381,9 +1426,9 @@ public class ScaleInternal {
percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float );
temp = xindex + (lowy_int * ysize);
for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
- long tempInt0 = ( 0xFFFFFFFFL & datain.getInt( temp_index ) );
+ final long tempInt0 = ( 0xFFFFFFFFL & datain.getInt( temp_index ) );
datain.position( temp_index );
- long tempInt1 = ( 0xFFFFFFFFL & datain.getInt() );
+ final long tempInt1 = ( 0xFFFFFFFFL & datain.getInt() );
datain.position( temp_index );
if( myswap_bytes ) {
totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent;
@@ -1392,7 +1437,7 @@ public class ScaleInternal {
}
}
}
-
+
// this is for the pixels in the body
temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
for( m = lowy_int + 1; m < highy_int; m++ ) {
@@ -1410,7 +1455,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
float value = 0.0f;
for( k = 0; k < components; k++ ) {
@@ -1433,7 +1478,7 @@ public class ScaleInternal {
// Clamp to make sure we don't run off the right edge
if (highx_int > widthin - 1) {
- int delta = (highx_int - widthin + 1);
+ final int delta = (highx_int - widthin + 1);
lowx_int -= delta;
highx_int -= delta;
}
@@ -1448,23 +1493,25 @@ public class ScaleInternal {
}
}
}
-
- public static void scale_internal_int( int components, int widthin, int heightin,
- ByteBuffer datain, int widthout, int heightout,
- IntBuffer dataout, int element_size, int ysize,
- int group_size, boolean myswap_bytes ) {
- float x, convx;
- float y, convy;
+
+ public static void scale_internal_int( final int components, final int widthin, final int heightin,
+ final ByteBuffer datain, final int widthout, final int heightout,
+ final IntBuffer dataout, final int element_size, final int ysize,
+ final int group_size, final boolean myswap_bytes ) {
+ final float x;
+ float convx;
+ final float y;
+ float convy;
float percent;
// Max components in a format is 4, so...
- float[] totals = new float[4];
+ final float[] totals = new float[4];
float area;
int i, j, k, xindex;
-
+
int temp, temp0;
int temp_index;
int outindex;
-
+
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
@@ -1472,11 +1519,11 @@ public class ScaleInternal {
int convy_int, convx_int;
int l, m;
int left, right;
-
+
long swapbuf; // unsigned buffer
-
+
if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
- HalveImage.halveImage_int( components, widthin, heightin, datain, dataout,
+ HalveImage.halveImage_int( components, widthin, heightin, datain, dataout,
element_size, ysize, group_size, myswap_bytes );
return;
}
@@ -1486,34 +1533,41 @@ public class ScaleInternal {
convy_float = convy - convy_int;
convx_int = (int)Math.floor( convx );
convx_float = convx - convx_int;
-
+
area = convx * convy;
-
+
lowy_int = 0;
lowy_float = 0.0f;
highy_int = convy_int;
highy_float = convy_float;
-
+
for( i = 0; i < heightout; i++ ) {
// Clamp here to be sure we don't read beyond input buffer.
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0.0f;
- highx_int = convx_int;
- highx_float = convx_float;
-
+ // If we have a single column, fix the max width values
+ // to prevent buffer overflow
+ if (widthin == 1 && widthout == 1) {
+ highx_int = 0;
+ highx_float = 0.0f;
+ } else {
+ highx_int = convx_int;
+ highx_float = convx_float;
+ }
+
for( j = 0; j < widthout; j++ ) {
-
+
// Ok, now apply box filter to box that goes from (lowx, lowy)
// to (highx, highy) on input data into this pixel on output
// data.
totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
-
+
// caulate the value for pixels in the 1st row
xindex = lowx_int * group_size;
if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
-
+
y_percent = 1 - lowy_float;
temp = xindex + lowy_int * ysize;
percent = y_percent * ( 1 - lowx_float );
@@ -1551,7 +1605,7 @@ public class ScaleInternal {
totals[k] += datain.getInt() * percent;
}
}
-
+
// calculate the value for pixels in the last row
y_percent = highy_float;
percent = y_percent * ( 1 - lowx_float );
@@ -1588,7 +1642,7 @@ public class ScaleInternal {
totals[k] += datain.getInt() * percent;
}
}
-
+
// calculate the value for the pixels in the 1st and last column
for( m = lowy_int + 1; m < highy_int; m++ ) {
left += ysize;
@@ -1694,7 +1748,7 @@ public class ScaleInternal {
}
}
}
-
+
// this is for the pixels in the body
temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
for( m = lowy_int + 1; m < highy_int; m++ ) {
@@ -1713,7 +1767,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -1730,7 +1784,7 @@ public class ScaleInternal {
// Clamp to make sure we don't run off the right edge
if (highx_int > widthin - 1) {
- int delta = (highx_int - widthin + 1);
+ final int delta = (highx_int - widthin + 1);
lowx_int -= delta;
highx_int -= delta;
}
@@ -1745,23 +1799,25 @@ public class ScaleInternal {
}
}
}
-
- public static void scale_internal_float( int components, int widthin, int heightin,
- ByteBuffer datain, int widthout, int heightout,
- FloatBuffer dataout, int element_size, int ysize,
- int group_size, boolean myswap_bytes ) {
- float x, convx;
- float y, convy;
+
+ public static void scale_internal_float( final int components, final int widthin, final int heightin,
+ final ByteBuffer datain, final int widthout, final int heightout,
+ final FloatBuffer dataout, final int element_size, final int ysize,
+ final int group_size, final boolean myswap_bytes ) {
+ final float x;
+ float convx;
+ final float y;
+ float convy;
float percent;
// Max components in a format is 4, so...
- float[] totals = new float[4];
+ final float[] totals = new float[4];
float area;
int i, j, k, xindex;
-
+
int temp, temp0;
int temp_index;
int outindex;
-
+
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
@@ -1769,11 +1825,11 @@ public class ScaleInternal {
int convy_int, convx_int;
int l, m;
int left, right;
-
+
float swapbuf; // unsigned buffer
-
+
if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
- HalveImage.halveImage_float( components, widthin, heightin, datain, dataout,
+ HalveImage.halveImage_float( components, widthin, heightin, datain, dataout,
element_size, ysize, group_size, myswap_bytes );
return;
}
@@ -1783,34 +1839,41 @@ public class ScaleInternal {
convy_float = convy - convy_int;
convx_int = (int)Math.floor( convx );
convx_float = convx - convx_int;
-
+
area = convx * convy;
-
+
lowy_int = 0;
lowy_float = 0.0f;
highy_int = convy_int;
highy_float = convy_float;
-
+
for( i = 0; i < heightout; i++ ) {
// Clamp here to be sure we don't read beyond input buffer.
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0.0f;
- highx_int = convx_int;
- highx_float = convx_float;
-
+ // If we have a single column, fix the max width values
+ // to prevent buffer overflow
+ if (widthin == 1 && widthout == 1) {
+ highx_int = 0;
+ highx_float = 0.0f;
+ } else {
+ highx_int = convx_int;
+ highx_float = convx_float;
+ }
+
for( j = 0; j < widthout; j++ ) {
-
+
// Ok, now apply box filter to box that goes from (lowx, lowy)
// to (highx, highy) on input data into this pixel on output
// data.
totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
-
+
// caulate the value for pixels in the 1st row
xindex = lowx_int * group_size;
if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
-
+
y_percent = 1 - lowy_float;
temp = xindex + lowy_int * ysize;
percent = y_percent * ( 1 - lowx_float );
@@ -1848,7 +1911,7 @@ public class ScaleInternal {
totals[k] += datain.getFloat() * percent;
}
}
-
+
// calculate the value for pixels in the last row
y_percent = highy_float;
percent = y_percent * ( 1 - lowx_float );
@@ -1885,7 +1948,7 @@ public class ScaleInternal {
totals[k] += datain.getFloat() * percent;
}
}
-
+
// calculate the value for the pixels in the 1st and last column
for( m = lowy_int + 1; m < highy_int; m++ ) {
left += ysize;
@@ -1991,7 +2054,7 @@ public class ScaleInternal {
}
}
}
-
+
// this is for the pixels in the body
temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
for( m = lowy_int + 1; m < highy_int; m++ ) {
@@ -2010,7 +2073,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -2027,7 +2090,7 @@ public class ScaleInternal {
// Clamp to make sure we don't run off the right edge
if (highx_int > widthin - 1) {
- int delta = (highx_int - widthin + 1);
+ final int delta = (highx_int - widthin + 1);
lowx_int -= delta;
highx_int -= delta;
}
@@ -2042,28 +2105,30 @@ public class ScaleInternal {
}
}
}
-
- public static void scaleInternalPackedPixel( int components, Extract extract,
- int widthIn, int heightIn, ByteBuffer dataIn, int widthOut,
- int heightOut, ByteBuffer dataOut, int pixelSizeInBytes,
- int rowSizeInBytes, boolean isSwap ) {
- float x, convx;
- float y, convy;
+
+ public static void scaleInternalPackedPixel( final int components, final Extract extract,
+ final int widthIn, final int heightIn, final ByteBuffer dataIn, final int widthOut,
+ final int heightOut, final ByteBuffer dataOut, final int pixelSizeInBytes,
+ final int rowSizeInBytes, final boolean isSwap ) {
+ final float x;
+ float convx;
+ final float y;
+ float convy;
float percent;
-
+
// max components in a format is 4, so
- float[] totals = new float[4];
- float[] extractTotals = new float[4];
- float[] extractMoreTotals = new float[4];
- float[] shoveTotals = new float[4];
-
+ final float[] totals = new float[4];
+ final float[] extractTotals = new float[4];
+ final float[] extractMoreTotals = new float[4];
+ final float[] shoveTotals = new float[4];
+
float area;
int i, j, k, xindex;
-
+
int temp, temp0;
- int temp_index;
+ final int temp_index;
int outIndex = 0;
-
+
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
@@ -2071,7 +2136,7 @@ public class ScaleInternal {
int convy_int, convx_int;
int l, m;
int left, right;
-
+
if( widthIn == widthOut * 2 && heightIn == heightOut * 2 ) {
HalveImage.halveImagePackedPixel( components, extract, widthIn, heightIn, dataIn, dataOut,
pixelSizeInBytes, rowSizeInBytes, isSwap );
@@ -2083,14 +2148,14 @@ public class ScaleInternal {
convy_float = convy - convy_int;
convx_int = (int)Math.floor( convx );
convx_float = convx - convx_int;
-
+
area = convx * convy;
-
+
lowy_int = 0;
lowy_float = 0.0f;
highy_int = convy_int;
highy_float = convx_float;
-
+
for( i = 0; i < heightOut; i++ ) {
// Clamp here to be sure we don't read beyond input buffer.
if (highy_int >= heightIn)
@@ -2099,16 +2164,16 @@ public class ScaleInternal {
lowx_float = 0.0f;
highx_int = convx_int;
highx_float = convx_float;
-
+
for( j = 0; j < widthOut; j++ ) {
// ok now apply box filter to box that goes from( lowx, lowy )
// to ( highx, highy ) on input data into this pixel on output data
totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
-
+
// calculate that value for pixels in the 1st row
xindex = lowx_int * pixelSizeInBytes;
if( (highy_int > lowy_int) && (highx_int > lowx_int) ) {
-
+
y_percent = 1 - lowy_float;
temp = xindex + lowy_int * rowSizeInBytes;
percent = y_percent * ( 1 - lowx_float );
@@ -2135,7 +2200,7 @@ public class ScaleInternal {
totals[k] += extractTotals[k] * percent;
}
// calculate the value for pixels in the last row
-
+
y_percent = highy_float;
percent = y_percent * ( 1 - lowx_float );
temp = xindex + highy_int * rowSizeInBytes;
@@ -2158,7 +2223,7 @@ public class ScaleInternal {
for( k = 0; k < components; k++ ) {
totals[k] += extractTotals[k] * percent;
}
-
+
// calculate the value for pixels in the 1st and last column
for( m = lowy_int + 1; m < highy_int; m++ ) {
left += rowSizeInBytes;
@@ -2228,7 +2293,7 @@ public class ScaleInternal {
totals[k] += extractTotals[k] * percent;
}
}
-
+
// this is for the pixels in the body
temp0 = xindex + pixelSizeInBytes + ( lowy_int + 1 ) * rowSizeInBytes;
for( m = lowy_int + 1; m < highy_int; m++ ) {
@@ -2243,7 +2308,7 @@ public class ScaleInternal {
}
temp0 += rowSizeInBytes;
}
-
+
outIndex = ( j + ( i * widthOut ) );
for( k = 0; k < components; k++ ) {
shoveTotals[k] = totals[k] / area;
@@ -2260,7 +2325,7 @@ public class ScaleInternal {
// Clamp to make sure we don't run off the right edge
if (highx_int > widthIn - 1) {
- int delta = (highx_int - widthIn + 1);
+ final int delta = (highx_int - widthIn + 1);
lowx_int -= delta;
highx_int -= delta;
}
@@ -2276,23 +2341,23 @@ public class ScaleInternal {
}
assert( outIndex == ( widthOut * heightOut - 1) );
}
-
- public static void scaleInternal3D( int components, int widthIn, int heightIn,
- int depthIn, ShortBuffer dataIn, int widthOut, int heightOut,
- int depthOut, ShortBuffer dataOut ) {
+
+ public static void scaleInternal3D( final int components, final int widthIn, final int heightIn,
+ final int depthIn, final ShortBuffer dataIn, final int widthOut, final int heightOut,
+ final int depthOut, final ShortBuffer dataOut ) {
float x, lowx, highx, convx, halfconvx;
float y, lowy, highy, convy, halfconvy;
float z, lowz, highz, convz, halfconvz;
float xpercent, ypercent, zpercent;
float percent;
// max compnents in a format is 4
- float[] totals = new float[4];
+ final float[] totals = new float[4];
float volume;
int i, j, d, k, zint, yint, xint, xindex, yindex, zindex;
int temp;
-
+
lowy = highy = lowx = highx = 0.0f;
-
+
convz = (float)depthIn / depthOut;
convy = (float)heightIn / heightOut;
convx = (float)widthIn / widthOut;
@@ -2326,13 +2391,13 @@ public class ScaleInternal {
highz = x + 0.5f;
lowz = x - 0.5f;
}
-
+
// Ok, now apply box filter to box that goes from ( lowx, lowy, lowz )
// to ( highx, highy, highz ) on input data into this pixel on output data
-
+
totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
volume = 0.0f;
-
+
z = lowz;
zint = (int)(Math.floor( z ) );
while( z < highz ) {
@@ -2342,7 +2407,7 @@ public class ScaleInternal {
} else {
zpercent = zint + 1 - z;
}
-
+
y = lowy;
yint = (int)(Math.floor( y ) );
while( y < highy ) {
@@ -2352,10 +2417,10 @@ public class ScaleInternal {
} else {
ypercent = yint + 1 - y;
}
-
+
x = lowx;
xint = (int)(Math.floor( x ) );
-
+
while( x < highx ) {
xindex = (xint + widthIn ) % widthIn;
if( highx < xint + 1 ) {
@@ -2363,10 +2428,10 @@ public class ScaleInternal {
} else {
xpercent = xint + 1 - x;
}
-
+
percent = xpercent * ypercent * zpercent;
volume += percent;
-
+
temp = (xindex + ( yindex *widthIn) + (zindex * widthIn *heightIn)) * components;
for( k = 0; k < components; k++ ) {
assert( 0 <= (temp+k) && (temp+k) < (widthIn * heightIn * depthIn * components) );
@@ -2381,7 +2446,7 @@ public class ScaleInternal {
zint++;
z = zint;
} // while z
-
+
temp = ( j + ( i * widthOut ) + (d * widthOut * heightOut ) ) * components;
for( k = 0; k < components; k++ ) {
// totals should be rounded in the case of enlarging an rgb ramp when the type is 332 or 4444
@@ -2392,48 +2457,48 @@ public class ScaleInternal {
}
}
}
-
- public static int gluScaleImage3D( GL gl, int format, int widthIn, int heightIn,
- int depthIn, int typeIn, ByteBuffer dataIn, int widthOut, int heightOut,
- int depthOut, int typeOut, ByteBuffer dataOut ) {
+
+ public static int gluScaleImage3D( final GL gl, final int format, final int widthIn, final int heightIn,
+ final int depthIn, final int typeIn, final ByteBuffer dataIn, final int widthOut, final int heightOut,
+ final int depthOut, final int typeOut, final ByteBuffer dataOut ) {
int components;
ShortBuffer beforeImage, afterImage;
- PixelStorageModes psm = new PixelStorageModes();
-
+ final PixelStorageModes psm = new PixelStorageModes();
+
if( widthIn == 0 || heightIn == 0 || depthIn == 0 ||
widthOut == 0 || heightOut == 0 || depthOut == 0 ) {
return( 0 );
}
-
+
if( widthIn < 0 || heightIn < 0 || depthIn < 0 ||
widthOut < 0 || heightOut < 0 || depthOut < 0 ) {
return( GLU.GLU_INVALID_VALUE );
}
-
- if( !Mipmap.legalFormat(format) || !Mipmap.legalType(typeIn) ||
+
+ if( !Mipmap.legalFormat(format) || !Mipmap.legalType(typeIn) ||
!Mipmap.legalType(typeOut) || typeIn == GL2.GL_BITMAP ||
typeOut == GL2.GL_BITMAP ) {
return( GLU.GLU_INVALID_ENUM );
}
-
+
if( !Mipmap.isLegalFormatForPackedPixelType( format, typeIn ) ) {
return( GLU.GLU_INVALID_OPERATION );
}
-
+
if( !Mipmap.isLegalFormatForPackedPixelType( format, typeOut ) ) {
return( GLU.GLU_INVALID_OPERATION );
}
-
+
try {
- beforeImage = Buffers.newDirectByteBuffer( Mipmap.imageSize3D( widthIn,
- heightIn, depthIn, format, GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
- afterImage = Buffers.newDirectByteBuffer( Mipmap.imageSize3D( widthIn,
- heightIn, depthIn, format, GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
- } catch( OutOfMemoryError err ) {
+ beforeImage = Buffers.newDirectByteBuffer( Mipmap.imageSize3D( widthIn,
+ heightIn, depthIn, format, GL.GL_UNSIGNED_SHORT ) ).asShortBuffer();
+ afterImage = Buffers.newDirectByteBuffer( Mipmap.imageSize3D( widthIn,
+ heightIn, depthIn, format, GL.GL_UNSIGNED_SHORT ) ).asShortBuffer();
+ } catch( final OutOfMemoryError err ) {
return( GLU.GLU_OUT_OF_MEMORY );
}
Mipmap.retrieveStoreModes3D( gl, psm );
-
+
Image.fillImage3D( psm, widthIn, heightIn, depthIn, format, typeIn,
Mipmap.is_index( format ), dataIn, beforeImage );
components = Mipmap.elements_per_group( format, 0 );
@@ -2441,7 +2506,7 @@ public class ScaleInternal {
beforeImage, widthOut, heightOut, depthOut, afterImage );
Image.emptyImage3D( psm, widthOut, heightOut, depthOut, format, typeOut,
Mipmap.is_index( format ), afterImage, dataOut );
-
+
return( 0 );
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Type_Widget.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Type_Widget.java
index 38113f601..8683f75ac 100644
--- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Type_Widget.java
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Type_Widget.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,176 +51,176 @@ import java.nio.*;
* @author Administrator
*/
public class Type_Widget {
-
+
ByteBuffer buffer;
-
+
/** Creates a new instance of Type_Widget */
public Type_Widget() {
// can't make this direct, because JVM doesn't allocate small direct buffers efficiently
// see https://jogamp.org/bugzilla/show_bug.cgi?id=463 for details
buffer = ByteBuffer.allocate( 4 );
}
-
- public void setUB0( byte b ) {
+
+ public void setUB0( final byte b ) {
buffer.position( 0 );
buffer.put( b );
}
-
+
public byte getUB0() {
buffer.position( 0 );
return( buffer.get() );
}
-
- public void setUB1( byte b ) {
+
+ public void setUB1( final byte b ) {
buffer.position( 1 );
buffer.put( b );
}
-
+
public byte getUB1() {
buffer.position( 1 );
return( buffer.get() );
}
-
- public void setUB2( byte b ) {
+
+ public void setUB2( final byte b ) {
buffer.position( 2 );
buffer.put( b );
}
-
+
public byte getUB2() {
buffer.position( 2 );
return( buffer.get() );
}
-
- public void setUB3( byte b ) {
+
+ public void setUB3( final byte b ) {
buffer.position( 3 );
buffer.put( b );
}
-
+
public byte getUB3() {
buffer.position( 3 );
return( buffer.get() );
}
-
- public void setUS0( short s ) {
+
+ public void setUS0( final short s ) {
buffer.position( 0 );
buffer.putShort( s );
}
-
+
public short getUS0() {
buffer.position( 0 );
return( buffer.getShort() );
}
-
- public void setUS1( short s ) {
+
+ public void setUS1( final short s ) {
buffer.position( 2 );
buffer.putShort( s );
}
-
+
public short getUS1() {
buffer.position( 2 );
return( buffer.getShort() );
}
-
- public void setUI( int i ) {
+
+ public void setUI( final int i ) {
buffer.position( 0 );
buffer.putInt( i );
}
-
+
public int getUI() {
buffer.position( 0 );
return( buffer.getInt() );
}
-
- public void setB0( byte b ) {
+
+ public void setB0( final byte b ) {
buffer.position( 0 );
buffer.put( b );
}
-
+
public byte getB0() {
buffer.position( 0 );
return( buffer.get() );
}
-
- public void setB1( byte b ) {
+
+ public void setB1( final byte b ) {
buffer.position( 1 );
buffer.put( b );
}
-
+
public byte getB1() {
buffer.position( 1 );
return( buffer.get() );
}
-
- public void setB2( byte b ) {
+
+ public void setB2( final byte b ) {
buffer.position( 2 );
buffer.put( b );
}
-
+
public byte getB2() {
buffer.position( 2 );
return( buffer.get() );
}
-
- public void setB3( byte b ) {
+
+ public void setB3( final byte b ) {
buffer.position( 3 );
buffer.put( b );
}
-
+
public byte getB3() {
buffer.position( 3 );
return( buffer.get() );
}
-
- public void setS0( short s ) {
+
+ public void setS0( final short s ) {
buffer.position( 0 );
buffer.putShort( s );
}
-
+
public short getS0() {
buffer.position( 0 );
return( buffer.getShort() );
}
-
- public void setS1( short s ) {
+
+ public void setS1( final short s ) {
buffer.position( 2 );
buffer.putShort( s );
}
-
+
public short getS1() {
buffer.position( 2 );
return( buffer.getShort() );
}
-
- public void setI( int i ) {
+
+ public void setI( final int i ) {
buffer.position( 0 );
buffer.putInt( i );
}
-
+
public int getI() {
buffer.position( 0 );
return( buffer.getInt() );
}
-
- public void setF( float f ) {
+
+ public void setF( final float f ) {
buffer.position( 0 );
buffer.putFloat( f );
}
-
+
public float getF() {
buffer.position( 0 );
return( buffer.getFloat() );
}
-
+
public ByteBuffer getBuffer() {
buffer.rewind();
return( buffer );
}
-
- public static void main( String args[] ) {
- Type_Widget t = new Type_Widget();
+
+ public static void main( final String args[] ) {
+ final Type_Widget t = new Type_Widget();
t.setI( 1000000 );
-
+
System.out.println("int: " + Integer.toHexString( t.getI() ) );
-
+
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Arc.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Arc.java
index 422f8d4df..2194eb672 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Arc.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Arc.java
@@ -68,15 +68,15 @@ public class Arc {
/**
* Corresponding berizer type arc
*/
- private BezierArc bezierArc;
+ private final BezierArc bezierArc;
/**
* Makes new arc at specified side
- *
+ *
* @param side
* which side doeas this arc form
*/
- public Arc(int side) {
+ public Arc(final int side) {
bezierArc = null;
pwlArc = null;
type = 0;
@@ -86,11 +86,11 @@ public class Arc {
/**
* Sets side the arc is at
- *
+ *
* @param side
* arc side
*/
- private void setside(int side) {
+ private void setside(final int side) {
// DONE
clearside();
type |= side << 8;
@@ -104,7 +104,7 @@ public class Arc {
type &= ~(0x7 << 8);
}
- // this one replaces enum arc_side
+ // this one replaces enum arc_side
/**
* Side not specified
*/
@@ -147,12 +147,12 @@ public class Arc {
/**
* Appends arc to the list
- *
+ *
* @param jarc
* arc to be append
* @return this
*/
- public Arc append(Arc jarc) {
+ public Arc append(final Arc jarc) {
// DONE
if (jarc != null) {
next = jarc.next;
@@ -169,7 +169,7 @@ public class Arc {
/**
* Unused
- *
+ *
* @return true
*/
public boolean check() {
@@ -187,7 +187,7 @@ public class Arc {
/**
* Returns tail of linked list coords
- *
+ *
* @return tail coords
*/
public float[] tail() {
@@ -197,7 +197,7 @@ public class Arc {
/**
* Returns head of linked list coords
- *
+ *
* @return head coords
*/
public float[] head() {
@@ -207,7 +207,7 @@ public class Arc {
/**
* Returns whether arc is marked with arc_tag
- *
+ *
* @return is arc marked with arc_tag
*/
public boolean ismarked() {
@@ -241,7 +241,7 @@ public class Arc {
/**
* Returns whether arc is marked tail
- *
+ *
* @return is tail
*/
public boolean getitail() {
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcSdirSorter.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcSdirSorter.java
index f4ad70193..68263b90d 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcSdirSorter.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcSdirSorter.java
@@ -44,8 +44,8 @@ public class ArcSdirSorter {
/**
* Makes new ArcSdirSorter with Subdivider
* @param subdivider subdivider
- */
- public ArcSdirSorter(Subdivider subdivider) {
+ */
+ public ArcSdirSorter(final Subdivider subdivider) {
//TODO
// System.out.println("TODO arcsdirsorter.constructor");
}
@@ -55,7 +55,7 @@ public class ArcSdirSorter {
* @param list arc list to be sorted
* @param count size of list
*/
- public void qsort(CArrayOfArcs list, int count) {
+ public void qsort(final CArrayOfArcs list, final int count) {
// TODO
// System.out.println("TODO arcsdirsorter.qsort");
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTdirSorter.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTdirSorter.java
index be72c53d2..dcd7d9fdc 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTdirSorter.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTdirSorter.java
@@ -43,8 +43,8 @@ public class ArcTdirSorter {
/**
* Makes new ArcSdirSorter with Subdivider
* @param subdivider subdivider
- */
- public ArcTdirSorter(Subdivider subdivider) {
+ */
+ public ArcTdirSorter(final Subdivider subdivider) {
// TODO Auto-generated constructor stub
// System.out.println("TODO arcTsorter.konstruktor");
}
@@ -53,7 +53,7 @@ public class ArcTdirSorter {
* @param list arc list to be sorted
* @param count size of list
*/
- public void qsort(CArrayOfArcs list, int count) {
+ public void qsort(final CArrayOfArcs list, final int count) {
// TODO Auto-generated method stub
// System.out.println("TODO arcTsorter.qsort");
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTesselator.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTesselator.java
index bd6311414..119ccbc81 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTesselator.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTesselator.java
@@ -49,9 +49,9 @@ public class ArcTesselator {
* @param t1 minimum t param
* @param t2 maximum s param
*/
- public void bezier(Arc arc, float s1, float s2, float t1, float t2) {
+ public void bezier(final Arc arc, final float s1, final float s2, final float t1, final float t2) {
// DONE
- TrimVertex[] p = new TrimVertex[2];
+ final TrimVertex[] p = new TrimVertex[2];
p[0] = new TrimVertex();
p[1] = new TrimVertex();
arc.pwlArc = new PwlArc(2, p);
@@ -70,7 +70,7 @@ public class ArcTesselator {
* @param t1 third tail
* @param f stepsize
*/
- public void pwl_right(Arc newright, float s, float t1, float t2, float f) {
+ public void pwl_right(final Arc newright, final float s, final float t1, final float t2, final float f) {
// TODO Auto-generated method stub
// System.out.println("TODO arctesselator.pwl_right");
}
@@ -83,7 +83,7 @@ public class ArcTesselator {
* @param t1 third tail
* @param f stepsize
*/
- public void pwl_left(Arc newright, float s, float t2, float t1, float f) {
+ public void pwl_left(final Arc newright, final float s, final float t2, final float t1, final float f) {
// TODO Auto-generated method stub
// System.out.println("TODO arctesselator.pwl_left");
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Backend.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Backend.java
index 610a19556..bde1e2cbb 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Backend.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Backend.java
@@ -67,7 +67,7 @@ public abstract class Backend {
protected SurfaceEvaluator surfaceEvaluator;
/**
- * Makes new backend
+ * Makes new backend
*/
public Backend() {
// curveEvaluator = new OpenGLCurveEvaluator();
@@ -101,8 +101,8 @@ public abstract class Backend {
* @param ulo smallest u
* @param uhi highest u
*/
- public void curvpts(int type, CArrayOfFloats ps, int stride, int order,
- float ulo, float uhi) {
+ public void curvpts(final int type, final CArrayOfFloats ps, final int stride, final int order,
+ final float ulo, final float uhi) {
// DONE
curveEvaluator.map1f(type, ulo, uhi, stride, order, ps);
curveEvaluator.enable(type);
@@ -114,7 +114,7 @@ public abstract class Backend {
* @param u2 highest u
* @param nu number of pieces
*/
- public void curvgrid(float u1, float u2, int nu) {
+ public void curvgrid(final float u1, final float u2, final int nu) {
// DONE
curveEvaluator.mapgrid1f(nu, u1, u2);
@@ -125,7 +125,7 @@ public abstract class Backend {
* @param from low param
* @param n step
*/
- public void curvmesh(int from, int n) {
+ public void curvmesh(final int from, final int n) {
// DONE
curveEvaluator.mapmesh1f(N_MESHFILL, from, from + n);
}
@@ -135,7 +135,7 @@ public abstract class Backend {
* @param wiretris use triangles
* @param wirequads use quads
*/
- public void bgnsurf(int wiretris, int wirequads) {
+ public void bgnsurf(final int wiretris, final int wirequads) {
// DONE
surfaceEvaluator.bgnmap2f();
@@ -160,7 +160,7 @@ public abstract class Backend {
* @param vlo low v param
* @param vhi high v param
*/
- public void patch(float ulo, float uhi, float vlo, float vhi) {
+ public void patch(final float ulo, final float uhi, final float vlo, final float vhi) {
// DONE
surfaceEvaluator.domain2f(ulo, uhi, vlo, vhi);
}
@@ -174,7 +174,7 @@ public abstract class Backend {
* @param v1 highest v
* @param nv number of pieces in v direction
*/
- public void surfgrid(float u0, float u1, int nu, float v0, float v1, int nv) {
+ public void surfgrid(final float u0, final float u1, final int nu, final float v0, final float v1, final int nv) {
// DONE
surfaceEvaluator.mapgrid2f(nu, u0, u1, nv, v0, v1);
@@ -187,7 +187,7 @@ public abstract class Backend {
* @param n step in u direction
* @param m step in v direction
*/
- public void surfmesh(int u, int v, int n, int m) {
+ public void surfmesh(final int u, final int v, final int n, final int m) {
// System.out.println("TODO backend.surfmesh wireframequads");
// TODO wireframequads
surfaceEvaluator.mapmesh2f(NurbsConsts.N_MESHFILL, u, u + n, v, v + m);
@@ -206,8 +206,8 @@ public abstract class Backend {
* @param vlo lowest v
* @param vhi hightest v
*/
- public void surfpts(int type, CArrayOfFloats pts, int ustride, int vstride,
- int uorder, int vorder, float ulo, float uhi, float vlo, float vhi) {
+ public void surfpts(final int type, final CArrayOfFloats pts, final int ustride, final int vstride,
+ final int uorder, final int vorder, final float ulo, final float uhi, final float vlo, final float vhi) {
// DONE
surfaceEvaluator.map2f(type, ulo, uhi, ustride, uorder, vlo, vhi,
vstride, vorder, pts);
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Bin.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Bin.java
index df8b16ab5..638b018c9 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Bin.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Bin.java
@@ -64,7 +64,7 @@ public class Bin {
* Adds and arc to linked list
* @param jarc added arc
*/
- public void addarc(Arc jarc) {
+ public void addarc(final Arc jarc) {
// DONE
// if (head == null)
// head = jarc;
@@ -93,7 +93,7 @@ public class Bin {
*/
public Arc removearc() {
// DONE
- Arc jarc = head;
+ final Arc jarc = head;
if (jarc != null)
head = jarc.link;
return jarc;
@@ -143,11 +143,11 @@ public class Bin {
/**
* Returns next arc in linked list
* @return next arc
- *
+ *
*/
private Arc nextarc() {
// DONE
- Arc jarc = current;
+ final Arc jarc = current;
if (jarc != null)
current = jarc.link;
return jarc;
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Breakpt.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Breakpt.java
index f45571dac..f84640d28 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Breakpt.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Breakpt.java
@@ -36,9 +36,9 @@ package jogamp.opengl.glu.nurbs;
/**
* Class holding break point parameters
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class Breakpt {
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfArcs.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfArcs.java
index aaa8cb5f2..6d2ab362b 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfArcs.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfArcs.java
@@ -2,9 +2,9 @@ package jogamp.opengl.glu.nurbs;
/**
* Class replacing C language pointer
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class CArrayOfArcs {
/**
@@ -20,17 +20,17 @@ public class CArrayOfArcs {
/**
* Don't check for array borders?
*/
- private boolean noCheck = true;
+ private final boolean noCheck = true;
/**
* Makes new CArray
- *
+ *
* @param array
* underlaying array
* @param pointer
* pointer (index) to array
*/
- public CArrayOfArcs(Arc[] array, int pointer) {
+ public CArrayOfArcs(final Arc[] array, final int pointer) {
this.array = array;
// this.pointer=pointer;
setPointer(pointer);
@@ -38,11 +38,11 @@ public class CArrayOfArcs {
/**
* Makes new CArray from other CArray
- *
+ *
* @param carray
* reference array
*/
- public CArrayOfArcs(CArrayOfArcs carray) {
+ public CArrayOfArcs(final CArrayOfArcs carray) {
this.array = carray.array;
// this.pointer=carray.pointer;
setPointer(carray.pointer);
@@ -50,18 +50,18 @@ public class CArrayOfArcs {
/**
* Makes new CArray with pointer set to 0
- *
+ *
* @param ctlarray
* underlaying array
*/
- public CArrayOfArcs(Arc[] ctlarray) {
+ public CArrayOfArcs(final Arc[] ctlarray) {
this.array = ctlarray;
this.pointer = 0;
}
/**
* Returns element at pointer
- *
+ *
* @return element at pointer
*/
public Arc get() {
@@ -78,63 +78,63 @@ public class CArrayOfArcs {
/**
* Sets element at pointer
- *
+ *
* @param f
* desired value
*/
- public void set(Arc f) {
+ public void set(final Arc f) {
array[pointer] = f;
}
/**
* Returns array element at specified index
- *
+ *
* @param i
* array index
* @return element at index
*/
- public Arc get(int i) {
+ public Arc get(final int i) {
return array[i];
}
/**
* Returns array element at specified index relatively to pointer
- *
+ *
* @param i
* relative index
* @return element at relative index
*/
- public Arc getRelative(int i) {
+ public Arc getRelative(final int i) {
return array[pointer + i];
}
/**
* Sets value of element at specified index relatively to pointer
- *
+ *
* @param i
* relative index
* @param value
* value to be set
*/
- public void setRelative(int i, Arc value) {
+ public void setRelative(final int i, final Arc value) {
array[pointer + i] = value;
}
/**
* Lessens pointer by value
- *
+ *
* @param i
* lessen by
*/
- public void lessenPointerBy(int i) {
+ public void lessenPointerBy(final int i) {
// pointer-=i;
setPointer(pointer - i);
}
/**
* Returns pointer value
- *
+ *
* @return pointer value
*/
public int getPointer() {
@@ -143,11 +143,11 @@ public class CArrayOfArcs {
/**
* Sets ponter value
- *
+ *
* @param pointer
* pointer value to be set
*/
- public void setPointer(int pointer) {
+ public void setPointer(final int pointer) {
if (!noCheck && pointer > array.length)
throw new IllegalArgumentException("Pointer " + pointer
+ " out of bounds " + array.length);
@@ -156,11 +156,11 @@ public class CArrayOfArcs {
/**
* Raises pointer by value
- *
+ *
* @param i
* raise by
*/
- public void raisePointerBy(int i) {
+ public void raisePointerBy(final int i) {
// pointer+=i;
setPointer(pointer + i);
}
@@ -175,7 +175,7 @@ public class CArrayOfArcs {
/**
* Returns underlaying array
- *
+ *
* @return underlaying array
*/
public Arc[] getArray() {
@@ -184,11 +184,11 @@ public class CArrayOfArcs {
/**
* Sets underlaying array
- *
+ *
* @param array
* underlaying array
*/
- public void setArray(Arc[] array) {
+ public void setArray(final Arc[] array) {
this.array = array;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfBreakpts.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfBreakpts.java
index 5112b07fc..1c80289a3 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfBreakpts.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfBreakpts.java
@@ -2,15 +2,15 @@ package jogamp.opengl.glu.nurbs;
/**
* Class replacing C language pointer
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class CArrayOfBreakpts {
/**
* Underlaying array
*/
- private Breakpt[] pole;
+ private final Breakpt[] pole;
/**
* Pointer to array member
@@ -19,31 +19,31 @@ public class CArrayOfBreakpts {
/**
* Makes new CArray
- *
+ *
* @param array
* underlaying array
* @param pointer
* pointer (index) to array
*/
- public CArrayOfBreakpts(Breakpt[] array, int pointer) {
+ public CArrayOfBreakpts(final Breakpt[] array, final int pointer) {
this.pole = array;
this.pointer = pointer;
}
/**
* Makes new CArray from other CArray
- *
+ *
* @param carray
* reference array
*/
- public CArrayOfBreakpts(CArrayOfBreakpts carray) {
+ public CArrayOfBreakpts(final CArrayOfBreakpts carray) {
this.pole = carray.pole;
this.pointer = carray.pointer;
}
/**
* Returns element at pointer
- *
+ *
* @return element at pointer
*/
public Breakpt get() {
@@ -59,40 +59,40 @@ public class CArrayOfBreakpts {
/**
* Sets element at pointer
- *
+ *
* @param f
* desired value
*/
- public void set(Breakpt f) {
+ public void set(final Breakpt f) {
pole[pointer] = f;
}
/**
* Returns array element at specified index
- *
+ *
* @param i
* array index
* @return element at index
*/
- public Breakpt get(int i) {
+ public Breakpt get(final int i) {
return pole[i];
}
/**
* Lessens pointer by value
- *
+ *
* @param i
* lessen by
*/
- public void lessenPointerBy(int i) {
+ public void lessenPointerBy(final int i) {
pointer -= i;
}
/**
* Returns pointer value
- *
+ *
* @return pointer value
*/
public int getPointer() {
@@ -101,21 +101,21 @@ public class CArrayOfBreakpts {
/**
* Sets ponter value
- *
+ *
* @param pointer
* pointer value to be set
*/
- public void setPointer(int pointer) {
+ public void setPointer(final int pointer) {
this.pointer = pointer;
}
/**
* Raises pointer by value
- *
+ *
* @param i
* raise by
*/
- public void raisePointerBy(int i) {
+ public void raisePointerBy(final int i) {
pointer += i;
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfFloats.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfFloats.java
index 39ef841ec..c9d6a59ad 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfFloats.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfFloats.java
@@ -2,9 +2,9 @@ package jogamp.opengl.glu.nurbs;
/**
* Class replacing C language pointer
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class CArrayOfFloats {
@@ -21,17 +21,17 @@ public class CArrayOfFloats {
/**
* Don't check for array borders?
*/
- private boolean noCheck = true;
+ private final boolean noCheck = true;
/**
* Makes new CArray
- *
+ *
* @param array
* underlaying array
* @param pointer
* pointer (index) to array
*/
- public CArrayOfFloats(float[] array, int pointer) {
+ public CArrayOfFloats(final float[] array, final int pointer) {
this.array = array;
// this.pointer=pointer;
setPointer(pointer);
@@ -39,11 +39,11 @@ public class CArrayOfFloats {
/**
* Makes new CArray from other CArray
- *
+ *
* @param carray
* reference array
*/
- public CArrayOfFloats(CArrayOfFloats carray) {
+ public CArrayOfFloats(final CArrayOfFloats carray) {
this.array = carray.array;
// this.pointer=carray.pointer;
setPointer(carray.pointer);
@@ -51,18 +51,18 @@ public class CArrayOfFloats {
/**
* Makes new CArray with pointer set to 0
- *
+ *
* @param ctlarray
* underlaying array
*/
- public CArrayOfFloats(float[] ctlarray) {
+ public CArrayOfFloats(final float[] ctlarray) {
this.array = ctlarray;
this.pointer = 0;
}
/**
* Returns element at pointer
- *
+ *
* @return element at pointer
*/
public float get() {
@@ -79,63 +79,63 @@ public class CArrayOfFloats {
/**
* Sets element at pointer
- *
+ *
* @param f
* desired value
*/
- public void set(float f) {
+ public void set(final float f) {
array[pointer] = f;
}
/**
* Returns array element at specified index
- *
+ *
* @param i
* array index
* @return element at index
*/
- public float get(int i) {
+ public float get(final int i) {
return array[i];
}
/**
* Returns array element at specified index relatively to pointer
- *
+ *
* @param i
* relative index
* @return element at relative index
*/
- public float getRelative(int i) {
+ public float getRelative(final int i) {
return array[pointer + i];
}
/**
* Sets value of element at specified index relatively to pointer
- *
+ *
* @param i
* relative index
* @param value
* value to be set
*/
- public void setRelative(int i, float value) {
+ public void setRelative(final int i, final float value) {
array[pointer + i] = value;
}
/**
* Lessens pointer by value
- *
+ *
* @param i
* lessen by
*/
- public void lessenPointerBy(int i) {
+ public void lessenPointerBy(final int i) {
// pointer-=i;
setPointer(pointer - i);
}
/**
* Returns pointer value
- *
+ *
* @return pointer value
*/
public int getPointer() {
@@ -144,11 +144,11 @@ public class CArrayOfFloats {
/**
* Sets ponter value
- *
+ *
* @param pointer
* pointer value to be set
*/
- public void setPointer(int pointer) {
+ public void setPointer(final int pointer) {
if (!noCheck && pointer > array.length)
throw new IllegalArgumentException("Pointer " + pointer
+ " out of bounds " + array.length);
@@ -157,11 +157,11 @@ public class CArrayOfFloats {
/**
* Raises pointer by value
- *
+ *
* @param i
* raise by
*/
- public void raisePointerBy(int i) {
+ public void raisePointerBy(final int i) {
// pointer+=i;
setPointer(pointer + i);
}
@@ -176,7 +176,7 @@ public class CArrayOfFloats {
/**
* Returns underlaying array
- *
+ *
* @return underlaying array
*/
public float[] getArray() {
@@ -185,11 +185,11 @@ public class CArrayOfFloats {
/**
* Sets underlaying array
- *
+ *
* @param array
* underlaying array
*/
- public void setArray(float[] array) {
+ public void setArray(final float[] array) {
this.array = array;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfQuiltspecs.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfQuiltspecs.java
index 4b21f2d50..0d769004a 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfQuiltspecs.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfQuiltspecs.java
@@ -2,9 +2,9 @@ package jogamp.opengl.glu.nurbs;
/**
* Class replacing C language pointer
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class CArrayOfQuiltspecs {
/**
@@ -19,42 +19,42 @@ public class CArrayOfQuiltspecs {
/**
* Makes new CArray
- *
+ *
* @param array
* underlaying array
* @param pointer
* pointer (index) to array
*/
- public CArrayOfQuiltspecs(Quiltspec[] array, int pointer) {
+ public CArrayOfQuiltspecs(final Quiltspec[] array, final int pointer) {
this.array = array;
this.pointer = pointer;
}
/**
* Makes new CArray from other CArray
- *
+ *
* @param carray
* reference array
*/
- public CArrayOfQuiltspecs(CArrayOfQuiltspecs carray) {
+ public CArrayOfQuiltspecs(final CArrayOfQuiltspecs carray) {
this.array = carray.array;
this.pointer = carray.pointer;
}
/**
* Makes new CArray with pointer set to 0
- *
+ *
* @param array
* underlaying array
*/
- public CArrayOfQuiltspecs(Quiltspec[] array) {
+ public CArrayOfQuiltspecs(final Quiltspec[] array) {
this.array = array;
this.pointer = 0;
}
/**
* Returns element at pointer
- *
+ *
* @return element at pointer
*/
public Quiltspec get() {
@@ -70,40 +70,40 @@ public class CArrayOfQuiltspecs {
/**
* Sets element at pointer
- *
+ *
* @param f
* desired value
*/
- public void set(Quiltspec f) {
+ public void set(final Quiltspec f) {
array[pointer] = f;
}
/**
* Returns array element at specified index
- *
+ *
* @param i
* array index
* @return element at index
*/
- public Quiltspec get(int i) {
+ public Quiltspec get(final int i) {
return array[i];
}
/**
* Lessens pointer by value
- *
+ *
* @param i
* lessen by
*/
- public void lessenPointerBy(int i) {
+ public void lessenPointerBy(final int i) {
pointer -= i;
}
/**
* Returns pointer value
- *
+ *
* @return pointer value
*/
public int getPointer() {
@@ -112,21 +112,21 @@ public class CArrayOfQuiltspecs {
/**
* Sets ponter value
- *
+ *
* @param pointer
* pointer value to be set
*/
- public void setPointer(int pointer) {
+ public void setPointer(final int pointer) {
this.pointer = pointer;
}
/**
* Raises pointer by value
- *
+ *
* @param i
* raise by
*/
- public void raisePointerBy(int i) {
+ public void raisePointerBy(final int i) {
pointer += i;
}
@@ -141,7 +141,7 @@ public class CArrayOfQuiltspecs {
/**
* Returns underlaying array
- *
+ *
* @return underlaying array
*/
public Quiltspec[] getArray() {
@@ -150,11 +150,11 @@ public class CArrayOfQuiltspecs {
/**
* Sets underlaying array
- *
+ *
* @param array
* underlaying array
*/
- public void setArray(Quiltspec[] array) {
+ public void setArray(final Quiltspec[] array) {
this.array = array;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Curve.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Curve.java
index 786781723..ce0387bff 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Curve.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Curve.java
@@ -59,32 +59,32 @@ public class Curve {
/**
* OpenGL maps
*/
- private Mapdesc mapdesc;
+ private final Mapdesc mapdesc;
/**
* Does the curve need sampling
*/
- private boolean needsSampling;
+ private final boolean needsSampling;
/**
* Culling
*/
- private int cullval;
+ private final int cullval;
/**
* Number of coords
*/
- private int stride;
+ private final int stride;
/**
* Curve order
*/
- private int order;
+ private final int order;
/**
* Holds conversion range borders
*/
- private float[] range;
+ private final float[] range;
/**
* Subdivision stepsize
@@ -103,14 +103,14 @@ public class Curve {
/**
* Makes new Curve
- *
+ *
* @param geo
* @param pta
* @param ptb
* @param c
* next curve in linked list
*/
- public Curve(Quilt geo, float[] pta, float[] ptb, Curve c) {
+ public Curve(final Quilt geo, final float[] pta, final float[] ptb, final Curve c) {
spts = new float[MAXORDER * MAXCOORDS];
@@ -125,8 +125,8 @@ public class Curve {
stride = MAXCOORDS;
// CArrayOfFloats ps = geo.cpts;
- CArrayOfFloats ps = new CArrayOfFloats(geo.cpts.getArray(), 0);
- CArrayOfQuiltspecs qs = geo.qspec;
+ final CArrayOfFloats ps = new CArrayOfFloats(geo.cpts.getArray(), 0);
+ final CArrayOfQuiltspecs qs = geo.qspec;
ps.raisePointerBy(qs.get().offset);
ps.raisePointerBy(qs.get().index * qs.get().order * qs.get().stride);
@@ -143,7 +143,7 @@ public class Curve {
range[0] = qs.get().breakpoints[qs.get().index];
range[1] = qs.get().breakpoints[qs.get().index + 1];
range[2] = range[1] - range[0];
- // TODO it is necessary to solve problem with "this" pointer here
+ // TODO it is necessary to solve problem with "this" pointer here
if (range[0] != pta[0]) {
// System.out.println("TODO curve.Curve-range0");
// Curve lower=new Curve(this,pta,0);
@@ -182,27 +182,31 @@ public class Curve {
} else {
assert (order <= MAXORDER);
- float tmp[][] = new float[MAXORDER][MAXCOORDS];
+ setstepsize(mapdesc.maxrate);
+
+ /***
+ final float tmp[][] = new float[MAXORDER][MAXCOORDS];
- int tstride = (MAXORDER);
+ final int tstride = (MAXORDER);
- int val = 0;
- // mapdesc.project(spts,stride,tmp,tstride,order);
+ final int val = 0;
+ // mapdesc.project(spts,stride,tmp,tstride,order);
- // System.out.println("TODO curve.getsptepsize mapdesc.project");
+ // System.out.println("TODO curve.getsptepsize mapdesc.project");
- if (val == 0) {
- setstepsize(mapdesc.maxrate);
- } else {
- float t = mapdesc.getProperty(NurbsConsts.N_PIXEL_TOLERANCE);
- if (mapdesc.isParametricDistanceSampling()) {
- // System.out.println("TODO curve.getstepsize - parametric");
- } else if (mapdesc.isPathLengthSampling()) {
- // System.out.println("TODO curve.getstepsize - pathlength");
- } else {
- setstepsize(mapdesc.maxrate);
- }
- }
+ if (val == 0) {
+ setstepsize(mapdesc.maxrate);
+ } else {
+ final float t = mapdesc.getProperty(NurbsConsts.N_PIXEL_TOLERANCE);
+ if (mapdesc.isParametricDistanceSampling()) {
+ // System.out.println("TODO curve.getstepsize - parametric");
+ } else if (mapdesc.isPathLengthSampling()) {
+ // System.out.println("TODO curve.getstepsize - pathlength");
+ } else {
+ setstepsize(mapdesc.maxrate);
+ }
+ }
+ */
}
@@ -212,7 +216,7 @@ public class Curve {
* Sets maximum subdivision step size
* @param max maximum subdivision step size
*/
- private void setstepsize(float max) {
+ private void setstepsize(final float max) {
// DONE
stepsize = (max >= 1) ? (range[2] / max) : range[2];
minstepsize = stepsize;
@@ -229,7 +233,7 @@ public class Curve {
/**
* Tells whether curve needs subdivision
- *
+ *
* @return curve needs subdivison
*/
public boolean needsSamplingSubdivision() {
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Curvelist.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Curvelist.java
index 80baf207b..96081a8ec 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Curvelist.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Curvelist.java
@@ -67,7 +67,7 @@ public class Curvelist {
* @param pta range start
* @param ptb range end
*/
- public Curvelist(Quilt qlist, float[] pta, float[] ptb) {
+ public Curvelist(final Quilt qlist, final float[] pta, final float[] ptb) {
// DONE
curve = null;
range = new float[3];
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/DisplayList.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/DisplayList.java
index d9d012606..e1b4cb2bb 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/DisplayList.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/DisplayList.java
@@ -49,7 +49,7 @@ public class DisplayList {
* @param m invoked method
* @param arg method argument
*/
- public void append(Object src, Method m, Object arg) {
+ public void append(final Object src, final Method m, final Object arg) {
// TODO Auto-generated method stub
// System.out.println("TODO displaylist append");
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Flist.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Flist.java
index 6983691d9..30f52d5cc 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Flist.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Flist.java
@@ -45,12 +45,12 @@ public class Flist {
/**
* Data elements end index
- *
+ *
*/
public int end;
/**
- *Data elements start index
+ *Data elements start index
*/
public int start;
@@ -68,7 +68,7 @@ public class Flist {
* Grows list
* @param maxpts maximum desired size
*/
- public void grow(int maxpts) {
+ public void grow(final int maxpts) {
// DONE
if (npts < maxpts) {
// npts=2*maxpts;
@@ -80,7 +80,7 @@ public class Flist {
}
/**
- * Removes duplicate array elemnts
+ * Removes duplicate array elemnts
*/
public void filter() {
// INFO the aim of this method is to remove duplicates from array
@@ -106,7 +106,7 @@ public class Flist {
* @param from start from
* @param to end at
*/
- public void taper(float from, float to) {
+ public void taper(final float from, final float to) {
// DONE
while (pts[start] != from) {
@@ -123,7 +123,7 @@ public class Flist {
* Adds breakpoint value
* @param f value
*/
- public void add(float f) {
+ public void add(final float f) {
//DONE
pts[end++] = f;
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Knotspec.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Knotspec.java
index 114832a1c..b7fa722ec 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Knotspec.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Knotspec.java
@@ -36,9 +36,9 @@ package jogamp.opengl.glu.nurbs;
/**
* Knot vector specification
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class Knotspec {
@@ -175,7 +175,7 @@ public class Knotspec {
break;
}
- CArrayOfFloats k = new CArrayOfFloats(kfirst);
+ final CArrayOfFloats k = new CArrayOfFloats(kfirst);
k.mm();
for (; k.getPointer() >= inkbegin.getPointer(); k.mm())
@@ -183,7 +183,7 @@ public class Knotspec {
break;
k.pp();
- Breakpt[] bbeginArray = new Breakpt[(klast.getPointer() - kfirst
+ final Breakpt[] bbeginArray = new Breakpt[(klast.getPointer() - kfirst
.getPointer()) + 1];
for (int i = 0; i < bbeginArray.length; i++)
bbeginArray[i] = new Breakpt();
@@ -218,7 +218,7 @@ public class Knotspec {
*/
private void factors() {
// DONE
- CArrayOfFloats mid = new CArrayOfFloats(outkend.getArray(), (outkend
+ final CArrayOfFloats mid = new CArrayOfFloats(outkend.getArray(), (outkend
.getPointer() - 1)
- order + bend.get().multi);
@@ -226,18 +226,18 @@ public class Knotspec {
if (sbegin != null)
fptr = new CArrayOfFloats(sbegin);
- for (CArrayOfBreakpts bpt = new CArrayOfBreakpts(bend); bpt
+ for (final CArrayOfBreakpts bpt = new CArrayOfBreakpts(bend); bpt
.getPointer() >= bbegin.getPointer(); bpt.mm()) {
mid.lessenPointerBy(bpt.get().multi);
- int def = bpt.get().def - 1;
+ final int def = bpt.get().def - 1;
if (def < 0)
continue;
- float kv = bpt.get().value;
+ final float kv = bpt.get().value;
- CArrayOfFloats kf = new CArrayOfFloats(mid.getArray(), (mid
+ final CArrayOfFloats kf = new CArrayOfFloats(mid.getArray(), (mid
.getPointer() - def)
+ (order - 1));
- for (CArrayOfFloats kl = new CArrayOfFloats(kf.getArray(), kf
+ for (final CArrayOfFloats kl = new CArrayOfFloats(kf.getArray(), kf
.getPointer()
+ def); kl.getPointer() != kf.getPointer(); kl.mm()) {
CArrayOfFloats kh, kt;
@@ -257,10 +257,10 @@ public class Knotspec {
*/
private void knots() {
// DONE
- CArrayOfFloats inkpt = new CArrayOfFloats(kleft.getArray(), kleft
+ final CArrayOfFloats inkpt = new CArrayOfFloats(kleft.getArray(), kleft
.getPointer()
- order);
- CArrayOfFloats inkend = new CArrayOfFloats(kright.getArray(), kright
+ final CArrayOfFloats inkend = new CArrayOfFloats(kright.getArray(), kright
.getPointer()
+ bend.get().def);
@@ -279,8 +279,8 @@ public class Knotspec {
*/
private void breakpoints() {
// DONE
- CArrayOfBreakpts ubpt = new CArrayOfBreakpts(bbegin);
- CArrayOfBreakpts ubend = new CArrayOfBreakpts(bend);
+ final CArrayOfBreakpts ubpt = new CArrayOfBreakpts(bbegin);
+ final CArrayOfBreakpts ubend = new CArrayOfBreakpts(bend);
int nfactors = 0;
ubpt.get().value = ubend.get().value;
@@ -314,19 +314,19 @@ public class Knotspec {
/**
* Copies control points
- *
+ *
* @param _inpt
* input control points
* @param _outpt
* output control points
*/
- public void copy(CArrayOfFloats _inpt, CArrayOfFloats _outpt) {
- CArrayOfFloats inpt = new CArrayOfFloats(_inpt);
- CArrayOfFloats outpt = new CArrayOfFloats(_outpt);
+ public void copy(final CArrayOfFloats _inpt, final CArrayOfFloats _outpt) {
+ final CArrayOfFloats inpt = new CArrayOfFloats(_inpt);
+ final CArrayOfFloats outpt = new CArrayOfFloats(_outpt);
inpt.raisePointerBy(preoffset);
if (next != null) {
- for (CArrayOfFloats lpt = new CArrayOfFloats(outpt.getArray(),
+ for (final CArrayOfFloats lpt = new CArrayOfFloats(outpt.getArray(),
outpt.getPointer() + prewidth); outpt.getPointer() != lpt
.getPointer(); outpt.raisePointerBy(poststride)) {
next.copy(inpt, outpt);
@@ -334,7 +334,7 @@ public class Knotspec {
}
} else {
- for (CArrayOfFloats lpt = new CArrayOfFloats(outpt.getArray(),
+ for (final CArrayOfFloats lpt = new CArrayOfFloats(outpt.getArray(),
outpt.getPointer() + prewidth); outpt.getPointer() != lpt
.getPointer(); outpt.raisePointerBy(poststride)) {
pt_io_copy(outpt, inpt);
@@ -346,13 +346,13 @@ public class Knotspec {
/**
* Copies one control point to other
- *
+ *
* @param topt
* source control point
* @param frompt
* destination control point
*/
- private void pt_io_copy(CArrayOfFloats topt, CArrayOfFloats frompt) {
+ private void pt_io_copy(final CArrayOfFloats topt, final CArrayOfFloats frompt) {
// DONE
switch (ncoords) {
case 4:
@@ -374,12 +374,12 @@ public class Knotspec {
/**
* Inserts a knot
- *
+ *
* @param _p
* inserted knot
*/
- public void transform(CArrayOfFloats _p) {
- CArrayOfFloats p = new CArrayOfFloats(_p);
+ public void transform(final CArrayOfFloats _p) {
+ final CArrayOfFloats p = new CArrayOfFloats(_p);
// DONE
if (next != null) {//surface code
if (this.equals(kspectotrans)) {
@@ -387,13 +387,13 @@ public class Knotspec {
} else {
if (istransformed) {
p.raisePointerBy(postoffset);
- for (CArrayOfFloats pend = new CArrayOfFloats(p.getArray(),
+ for (final CArrayOfFloats pend = new CArrayOfFloats(p.getArray(),
p.getPointer() + postwidth); p.getPointer() != pend
.getPointer(); p.raisePointerBy(poststride))
next.transform(p);
} else {
- CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), p
+ final CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), p
.getPointer()
+ prewidth);
for (; p.getPointer() != pend.getPointer(); p
@@ -402,19 +402,19 @@ public class Knotspec {
}
}
- } else {//code for curve
+ } else {//code for curve
if (this.equals(kspectotrans)) {
insert(p);
} else {
if (istransformed) {
p.raisePointerBy(postoffset);
- for (CArrayOfFloats pend = new CArrayOfFloats(p.getArray(),
+ for (final CArrayOfFloats pend = new CArrayOfFloats(p.getArray(),
p.getPointer() + postwidth); p.getPointer() != pend
.getPointer(); p.raisePointerBy(poststride)) {
kspectotrans.insert(p);
}
} else {
- CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), p
+ final CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), p
.getPointer()
+ prewidth);
for (; p.getPointer() != pend.getPointer(); p
@@ -428,31 +428,31 @@ public class Knotspec {
/**
* Inserts a knot and computes new control points
- *
+ *
* @param p
* inserted knot
*/
- private void insert(CArrayOfFloats p) {
+ private void insert(final CArrayOfFloats p) {
// DONE
CArrayOfFloats fptr = null;
if (sbegin != null)
fptr = new CArrayOfFloats(sbegin);
- CArrayOfFloats srcpt = new CArrayOfFloats(p.getArray(), p.getPointer()
+ final CArrayOfFloats srcpt = new CArrayOfFloats(p.getArray(), p.getPointer()
+ prewidth - poststride);
// CArrayOfFloats srcpt = new CArrayOfFloats(p.getArray(), prewidth -
// poststride);
- CArrayOfFloats dstpt = new CArrayOfFloats(p.getArray(), p.getPointer()
+ final CArrayOfFloats dstpt = new CArrayOfFloats(p.getArray(), p.getPointer()
+ postwidth + postoffset - poststride);
// CArrayOfFloats dstpt = new CArrayOfFloats(p.getArray(), postwidth +
// postoffset - poststride);
- CArrayOfBreakpts bpt = new CArrayOfBreakpts(bend);
+ final CArrayOfBreakpts bpt = new CArrayOfBreakpts(bend);
- for (CArrayOfFloats pend = new CArrayOfFloats(srcpt.getArray(), srcpt
+ for (final CArrayOfFloats pend = new CArrayOfFloats(srcpt.getArray(), srcpt
.getPointer()
- poststride * bpt.get().def); srcpt.getPointer() != pend
.getPointer(); pend.raisePointerBy(poststride)) {
- CArrayOfFloats p1 = new CArrayOfFloats(srcpt);
- for (CArrayOfFloats p2 = new CArrayOfFloats(srcpt.getArray(), srcpt
+ final CArrayOfFloats p1 = new CArrayOfFloats(srcpt);
+ for (final CArrayOfFloats p2 = new CArrayOfFloats(srcpt.getArray(), srcpt
.getPointer()
- poststride); p2.getPointer() != pend.getPointer(); p1
.setPointer(p2.getPointer()), p2
@@ -469,15 +469,15 @@ public class Knotspec {
dstpt.lessenPointerBy(poststride);
srcpt.lessenPointerBy(poststride);
}
- for (CArrayOfFloats pend = new CArrayOfFloats(srcpt.getArray(),
+ for (final CArrayOfFloats pend = new CArrayOfFloats(srcpt.getArray(),
srcpt.getPointer() - poststride * bpt.get().def); srcpt
.getPointer() != pend.getPointer(); pend
.raisePointerBy(poststride), dstpt
.lessenPointerBy(poststride)) {
pt_oo_copy(dstpt, srcpt);
- CArrayOfFloats p1 = new CArrayOfFloats(srcpt);
+ final CArrayOfFloats p1 = new CArrayOfFloats(srcpt);
- for (CArrayOfFloats p2 = new CArrayOfFloats(srcpt.getArray(),
+ for (final CArrayOfFloats p2 = new CArrayOfFloats(srcpt.getArray(),
srcpt.getPointer() - poststride); p2.getPointer() != pend
.getPointer(); p1.setPointer(p2.getPointer()), p2
.lessenPointerBy(poststride)) {
@@ -490,13 +490,13 @@ public class Knotspec {
/**
* Copies one control point to another
- *
+ *
* @param topt
* source ctrl point
* @param frompt
* distance ctrl point
*/
- private void pt_oo_copy(CArrayOfFloats topt, CArrayOfFloats frompt) {
+ private void pt_oo_copy(final CArrayOfFloats topt, final CArrayOfFloats frompt) {
// DONE
// this is a "trick" with case - "break" is omitted so it comes through all cases
switch (ncoords) {
@@ -519,7 +519,7 @@ public class Knotspec {
/**
* Computes new control point
- *
+ *
* @param x
* first point
* @param y
@@ -531,8 +531,8 @@ public class Knotspec {
* @param b
* 1 - alpha
*/
- private void pt_oo_sum(CArrayOfFloats x, CArrayOfFloats y,
- CArrayOfFloats z, float a, double b) {
+ private void pt_oo_sum(final CArrayOfFloats x, final CArrayOfFloats y,
+ final CArrayOfFloats z, final float a, final double b) {
// DONE
switch (ncoords) {
case 4:
@@ -549,7 +549,7 @@ public class Knotspec {
* z.getRelative(0)));
break;
default:
- //no need of default - see previous method and its case statement
+ //no need of default - see previous method and its case statement
// System.out.println("TODO pt_oo_sum default");
break;
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Knotvector.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Knotvector.java
index aac4dfc52..76b59231c 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Knotvector.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Knotvector.java
@@ -36,9 +36,9 @@ package jogamp.opengl.glu.nurbs;
/**
* Knot vector used in curve specification
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class Knotvector {
@@ -75,7 +75,7 @@ public class Knotvector {
/**
* Makes new knotvector
- *
+ *
* @param nknots
* number of knots
* @param stride
@@ -85,14 +85,14 @@ public class Knotvector {
* @param knot
* knots
*/
- public Knotvector(int nknots, int stride, int order, float[] knot) {
+ public Knotvector(final int nknots, final int stride, final int order, final float[] knot) {
// DONE
init(nknots, stride, order, knot);
}
/**
* Initializes knotvector
- *
+ *
* @param nknots
* number of knots
* @param stride
@@ -102,7 +102,7 @@ public class Knotvector {
* @param knot
* knots
*/
- public void init(int nknots, int stride, int order, float[] knot) {
+ public void init(final int nknots, final int stride, final int order, final float[] knot) {
// DONE
this.knotcount = nknots;
this.stride = stride;
@@ -116,7 +116,7 @@ public class Knotvector {
/**
* Validates knot vector parameters
- *
+ *
* @return knot vector validity
*/
public int validate() {
@@ -154,11 +154,11 @@ public class Knotvector {
/**
* Show specified message
- *
+ *
* @param msg
* message to be shown
*/
- public void show(String msg) {
+ public void show(final String msg) {
// TODO Auto-generated method stub
// System.out.println("TODO knotvector.show");
@@ -166,14 +166,14 @@ public class Knotvector {
/**
* Compares two knots for equality
- *
+ *
* @param a
* first knot
* @param b
* second knot
* @return knots are/are not equal
*/
- public static boolean identical(float a, float b) {
+ public static boolean identical(final float a, final float b) {
return ((a - b) < TOLERANCE) ? true : false;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Mapdesc.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Mapdesc.java
index bd5d2db98..b6e83d94c 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Mapdesc.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Mapdesc.java
@@ -64,22 +64,22 @@ public class Mapdesc {
/**
* Map type
*/
- private int type;
+ private final int type;
/**
* Number of homogenous coords
*/
- private int hcoords;
+ private final int hcoords;
/**
* Number of inhomogenous coords
*/
- private int inhcoords;
+ private final int inhcoords;
/**
* Not used
*/
- private int mask;
+ private final int mask;
/**
* Value of N_PIXEL_TOLERANCE property
@@ -112,7 +112,7 @@ public class Mapdesc {
float clampfactor;
/**
- * Value of N_MINSAVINGS property
+ * Value of N_MINSAVINGS property
*/
private float minsavings;
@@ -144,31 +144,30 @@ public class Mapdesc {
/**
* Not used
*/
- private float[][] bmat;
+ private final float[][] bmat;
/**
* Sampling matrix
*/
- private float[][] smat;
+ private final float[][] smat;
/**
* Not used
*/
- private float[][] cmat;
+ private final float[][] cmat;
/**
* Not used
*/
- private float[] bboxsize;
+ private final float[] bboxsize;
/**
- * Makes new mapdesc
+ * Makes new mapdesc
* @param type map type
* @param rational is rational
* @param ncoords number of control points coords
- * @param backend backend object
*/
- public Mapdesc(int type, int rational, int ncoords, Backend backend) {
+ public Mapdesc(final int type, final int rational, final int ncoords) {
// DONE
this.type = type;
this.isrational = rational;
@@ -210,7 +209,7 @@ public class Mapdesc {
* Make matrix identity matrix
* @param arr matrix
*/
- private void identify(float[][] arr) {
+ private void identify(final float[][] arr) {
// DONE
for (int i = 0; i < MAXCOORDS; i++)
for (int j = 0; j < MAXCOORDS; j++)
@@ -225,7 +224,7 @@ public class Mapdesc {
* @param tag property tag
* @return is/is not property
*/
- public boolean isProperty(int tag) {
+ public boolean isProperty(final int tag) {
boolean ret;
switch (tag) {
case NurbsConsts.N_PIXEL_TOLERANCE:
@@ -318,7 +317,7 @@ public class Mapdesc {
}
/**
- * Tells whether map is culling
+ * Tells whether map is culling
* @return is map culling
*/
public boolean isCulling() {
@@ -327,7 +326,7 @@ public class Mapdesc {
}
/**
- * Tells whether map is constantly sampling
+ * Tells whether map is constantly sampling
* @return is map constant sampling
*/
public boolean isConstantSampling() {
@@ -335,7 +334,7 @@ public class Mapdesc {
}
/**
- * Tells whether map is domain sampling
+ * Tells whether map is domain sampling
* @return is map domain sampling
*/
public boolean isDomainSampling() {
@@ -343,11 +342,11 @@ public class Mapdesc {
}
/**
- * Returns property of specified tag value
+ * Returns property of specified tag value
* @param tag property tag
* @return property value
*/
- public float getProperty(int tag) {
+ public float getProperty(final int tag) {
// TODO Auto-generated method stub
// System.out.println("TODO mapdesc.getproperty");
return 0;
@@ -358,7 +357,7 @@ public class Mapdesc {
* @param tag property tag
* @param value desired value
*/
- public void setProperty(int tag, float value) {
+ public void setProperty(final int tag, float value) {
// TODO Auto-generated method stub
switch (tag) {
case NurbsConsts.N_PIXEL_TOLERANCE:
@@ -412,8 +411,8 @@ public class Mapdesc {
* @param sp breakpoints
* @param outstride output number of control points' coordinates
*/
- public void xformSampling(CArrayOfFloats pts, int order, int stride,
- float[] sp, int outstride) {
+ public void xformSampling(final CArrayOfFloats pts, final int order, final int stride,
+ final float[] sp, final int outstride) {
// DONE
xFormMat(smat, pts, order, stride, sp, outstride);
}
@@ -427,8 +426,8 @@ public class Mapdesc {
* @param cp breakpoints
* @param outstride output number of control points' coordinates
*/
- private void xFormMat(float[][] mat, CArrayOfFloats pts, int order,
- int stride, float[] cp, int outstride) {
+ private void xFormMat(final float[][] mat, final CArrayOfFloats pts, final int order,
+ final int stride, final float[] cp, final int outstride) {
// TODO Auto-generated method stub
// System.out.println("TODO mapdsc.xformmat ; change cp from float[] to carrayoffloats");
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Maplist.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Maplist.java
index af8024109..2cb92aeef 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Maplist.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Maplist.java
@@ -47,15 +47,14 @@ public class Maplist {
/**
* Backend class
+ * private final Backend backend;
*/
- private Backend backend;
/**
* Makes new Maplist
- * @param backend Backend class
*/
- public Maplist(Backend backend) {
- this.backend = backend;
+ public Maplist(/* final Backend backend */) {
+ // this.backend = backend;
}
/**
@@ -72,9 +71,9 @@ public class Maplist {
* @param rational is map rational
* @param ncoords number of coords
*/
- public void define(int type, int rational, int ncoords) {
+ public void define(final int type, final int rational, final int ncoords) {
// DONE
- Mapdesc m = locate(type);
+ final Mapdesc m = locate(type);
assert (m == null || (m.isrational == rational && m.ncoords == ncoords));
add(type, rational, ncoords);
@@ -86,9 +85,9 @@ public class Maplist {
* @param rational is map rational
* @param ncoords number of coords
*/
- private void add(int type, int rational, int ncoords) {
+ private void add(final int type, final int rational, final int ncoords) {
// DONE
- Mapdesc map = new Mapdesc(type, rational, ncoords, backend);
+ final Mapdesc map = new Mapdesc(type, rational, ncoords);
if (maps == null) {
maps = map;
} else {
@@ -102,7 +101,7 @@ public class Maplist {
* @param type map type
* @return Mapdesc of type or null if there is no such map
*/
- public Mapdesc locate(int type) {
+ public Mapdesc locate(final int type) {
// DONE
Mapdesc m = null;
for (m = maps; m != null; m = m.next)
@@ -116,7 +115,7 @@ public class Maplist {
* @param type maptype
* @return Mapdesc of type or null if there is no such map
*/
- public Mapdesc find(int type) {
+ public Mapdesc find(final int type) {
return locate(type);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbscurve.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbscurve.java
index 05c89ebcf..a957c21a8 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbscurve.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbscurve.java
@@ -68,9 +68,9 @@ public class O_nurbscurve {
/**
* Makes new O_nurbscurve
- * @param realType type of curve
+ * @param realType type of curve
*/
- public O_nurbscurve(int realType) {
+ public O_nurbscurve(final int realType) {
// DONE
this.type = realType;
this.owner = null;
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbssurface.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbssurface.java
index 867f43657..4df3c14ca 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbssurface.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbssurface.java
@@ -64,13 +64,13 @@ public class O_nurbssurface {
/**
* Surface type
*/
- private int type;
+ private final int type;
/**
* Makes new O_nurbssurface of type
* @param type surface type
*/
- public O_nurbssurface(int type) {
+ public O_nurbssurface(final int type) {
this.type = type;
this.owner = null;
this.next = null;
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Patch.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Patch.java
index a44f2451c..0fd4baa81 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Patch.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Patch.java
@@ -48,7 +48,7 @@ public class Patch {
* @param ptb
* @param patch
*/
- public Patch(Quilt q, float[] pta, float[] ptb, Patch patch) {
+ public Patch(final Quilt q, final float[] pta, final float[] ptb, final Patch patch) {
// System.out.println("TODO patch.constructor");
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Patchlist.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Patchlist.java
index f1e499a28..68b01d8d0 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Patchlist.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Patchlist.java
@@ -52,17 +52,18 @@ public class Patchlist {
private Patch patch;
/**
- * Makes new list of patches
+ * Makes new list of patches
* @param quilts list of quilts
* @param pta low border
* @param ptb high border
*/
- public Patchlist(Quilt quilts, float[] pta, float[] ptb) {
+ public Patchlist(final Quilt quilts, final float[] pta, final float[] ptb) {
// DONE
patch = null;
for (Quilt q = quilts; q != null; q = q.next)
patch = new Patch(q, pta, ptb, patch);
+ pspec = new Pspec[2];
pspec[0] = new Pspec();
pspec[0].range[0] = pta[0];
pspec[0].range[1] = ptb[0];
@@ -80,7 +81,7 @@ public class Patchlist {
* @param param
* @param mid
*/
- public Patchlist(Patchlist patchlist, int param, float mid) {
+ public Patchlist(final Patchlist patchlist, final int param, final float mid) {
// TODO Auto-generated constructor stub
// System.out.println("TODO patchlist.konstruktor 2");
}
@@ -119,7 +120,7 @@ public class Patchlist {
* @param i
* @return false
*/
- public boolean needsSubdivision(int i) {
+ public boolean needsSubdivision(final int i) {
// TODO Auto-generated method stub
// System.out.println("TODO patchlist.needsSubdivision");
return false;
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Property.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Property.java
index 25b4dc441..155549bce 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Property.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Property.java
@@ -36,9 +36,9 @@ package jogamp.opengl.glu.nurbs;
/**
* Class representing property
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class Property {
@@ -59,7 +59,7 @@ public class Property {
/**
* Makes new property with given parameters
- *
+ *
* @param type
* property type
* @param tag
@@ -67,7 +67,7 @@ public class Property {
* @param value
* property value
*/
- public Property(int type, int tag, float value) {
+ public Property(final int type, final int tag, final float value) {
this.type = type;
this.tag = tag;
this.value = value;
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/PwlArc.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/PwlArc.java
index bcbd20a16..8e04baf88 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/PwlArc.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/PwlArc.java
@@ -44,7 +44,7 @@ public class PwlArc {
/**
* Number of points
*/
- private int npts;
+ private final int npts;
/**
* Vertexes
@@ -54,14 +54,14 @@ public class PwlArc {
/**
* Arc type
*/
- private int type;
+ private final int type;
/**
* Makes new trimming arc
* @param i num ber of vertexes
* @param p trimming vertexes array
*/
- public PwlArc(int i, TrimVertex[] p) {
+ public PwlArc(final int i, final TrimVertex[] p) {
// DONE
this.npts = i;
this.pts = p;
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Quilt.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Quilt.java
index 6bea4928c..2e2532a35 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Quilt.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Quilt.java
@@ -74,10 +74,10 @@ public class Quilt {
* Makes new quilt with mapdesc
* @param mapdesc map description
*/
- public Quilt(Mapdesc mapdesc) {
+ public Quilt(final Mapdesc mapdesc) {
// DONE
this.mapdesc = mapdesc;
- Quiltspec[] tmpquilts = new Quiltspec[MAXDIM];
+ final Quiltspec[] tmpquilts = new Quiltspec[MAXDIM];
for (int i = 0; i < tmpquilts.length; i++)
tmpquilts[i] = new Quiltspec();
this.qspec = new CArrayOfQuiltspecs(tmpquilts);
@@ -91,9 +91,9 @@ public class Quilt {
* @param ctrlarr control points
* @param coords control points coords
*/
- public void toBezier(Knotvector sknotvector, Knotvector tknotvector,
- CArrayOfFloats ctrlarr, int coords) {
- Splinespec spline = new Splinespec(2);
+ public void toBezier(final Knotvector sknotvector, final Knotvector tknotvector,
+ final CArrayOfFloats ctrlarr, final int coords) {
+ final Splinespec spline = new Splinespec(2);
spline.kspecinit(sknotvector, tknotvector);
spline.select();
spline.layout(coords);
@@ -108,9 +108,9 @@ public class Quilt {
* @param ctlarray control points
* @param ncoords number of coordinates
*/
- public void toBezier(Knotvector knots, CArrayOfFloats ctlarray, int ncoords) {
+ public void toBezier(final Knotvector knots, final CArrayOfFloats ctlarray, final int ncoords) {
// DONE
- Splinespec spline = new Splinespec(1);
+ final Splinespec spline = new Splinespec(1);
spline.kspecinit(knots);
spline.select();
spline.layout(ncoords);
@@ -125,7 +125,7 @@ public class Quilt {
* @param ptb high border
* @param backend Backend
*/
- public void downloadAll(float[] pta, float[] ptb, Backend backend) {
+ public void downloadAll(final float[] pta, final float[] ptb, final Backend backend) {
// DONE
for (Quilt m = this; m != null; m = m.next) {
m.select(pta, ptb);
@@ -138,11 +138,11 @@ public class Quilt {
* Renders arcs/patches
* @param backend Backend for rendering
*/
- private void download(Backend backend) {
+ private void download(final Backend backend) {
// DONE
if (getDimension() == 2) {
- CArrayOfFloats ps = new CArrayOfFloats(cpts);
+ final CArrayOfFloats ps = new CArrayOfFloats(cpts);
ps.raisePointerBy(qspec.get(0).offset);
ps.raisePointerBy(qspec.get(1).offset);
ps.raisePointerBy(qspec.get(0).index * qspec.get(0).order
@@ -159,7 +159,7 @@ public class Quilt {
} else {// code for curves
// CArrayOfFloats ps=new CArrayOfFloats(cpts);
- CArrayOfFloats ps = new CArrayOfFloats(cpts.getArray(), 0);
+ final CArrayOfFloats ps = new CArrayOfFloats(cpts.getArray(), 0);
ps.raisePointerBy(qspec.get(0).offset);
ps.raisePointerBy(qspec.get(0).index * qspec.get(0).order
* qspec.get(0).stride);
@@ -185,9 +185,9 @@ public class Quilt {
* @param pta range
* @param ptb range
*/
- private void select(float[] pta, float[] ptb) {
+ private void select(final float[] pta, final float[] ptb) {
// DONE
- int dim = eqspec.getPointer() - qspec.getPointer();
+ final int dim = eqspec.getPointer() - qspec.getPointer();
int i, j;
for (i = 0; i < dim; i++) {
for (j = qspec.get(i).width - 1; j >= 0; j--)
@@ -205,7 +205,7 @@ public class Quilt {
* @param to high param
* @param bpts breakpoints
*/
- public void getRange(float[] from, float[] to, Flist bpts) {
+ public void getRange(final float[] from, final float[] to, final Flist bpts) {
// DONE
getRange(from, to, 0, bpts);
@@ -218,9 +218,9 @@ public class Quilt {
* @param i from/to array index
* @param list breakpoints
*/
- private void getRange(float[] from, float[] to, int i, Flist list) {
+ private void getRange(final float[] from, final float[] to, final int i, final Flist list) {
// DONE
- Quilt maps = this;
+ final Quilt maps = this;
from[i] = maps.qspec.get(i).breakpoints[0];
to[i] = maps.qspec.get(i).breakpoints[maps.qspec.get(i).width];
int maxpts = 0;
@@ -262,7 +262,7 @@ public class Quilt {
* @param slist u direction breakpoints
* @param tlist v direction breakpoints
*/
- public void getRange(float[] from, float[] to, Flist slist, Flist tlist) {
+ public void getRange(final float[] from, final float[] to, final Flist slist, final Flist tlist) {
// DONE
getRange(from, to, 0, slist);
getRange(from, to, 1, tlist);
@@ -275,7 +275,7 @@ public class Quilt {
* @param tbrkpts
* @param rate
*/
- public void findRates(Flist sbrkpts, Flist tbrkpts, float[] rate) {
+ public void findRates(final Flist sbrkpts, final Flist tbrkpts, final float[] rate) {
// TODO Auto-generated method stub
// System.out.println("TODO quilt.findrates");
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Renderhints.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Renderhints.java
index 4729e2421..5c180f345 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Renderhints.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Renderhints.java
@@ -35,7 +35,7 @@ package jogamp.opengl.glu.nurbs;
*/
/**
- * Class holding rendering params
+ * Class holding rendering params
* @author Tomas Hrasky
*
*/
@@ -85,7 +85,7 @@ public class Renderhints {
* Set property value
* @param prop property
*/
- public void setProperty(Property prop) {
+ public void setProperty(final Property prop) {
switch (prop.type) {
case NurbsConsts.N_DISPLAY:
display_method = (int) prop.value;
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Splinespec.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Splinespec.java
index f1c779c2f..5e44c3259 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Splinespec.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Splinespec.java
@@ -44,7 +44,7 @@ public class Splinespec {
/**
* Dimension
*/
- private int dim;
+ private final int dim;
/**
* Knot vector specs
@@ -60,7 +60,7 @@ public class Splinespec {
* Makes new Splinespec with given dimension
* @param i dimension
*/
- public Splinespec(int i) {
+ public Splinespec(final int i) {
// DONE
this.dim = i;
}
@@ -69,7 +69,7 @@ public class Splinespec {
* Initializes knotspec according to knotvector
* @param knotvector basic knotvector
*/
- public void kspecinit(Knotvector knotvector) {
+ public void kspecinit(final Knotvector knotvector) {
// DONE
this.kspec = new Knotspec();
kspec.inkbegin = new CArrayOfFloats(knotvector.knotlist, 0);
@@ -85,10 +85,10 @@ public class Splinespec {
* @param sknotvector knotvector in u dir
* @param tknotvector knotvector in v dir
*/
- public void kspecinit(Knotvector sknotvector, Knotvector tknotvector) {
+ public void kspecinit(final Knotvector sknotvector, final Knotvector tknotvector) {
// DONE
this.kspec = new Knotspec();
- Knotspec tkspec = new Knotspec();
+ final Knotspec tkspec = new Knotspec();
kspec.inkbegin = new CArrayOfFloats(sknotvector.knotlist, 0);
kspec.inkend = new CArrayOfFloats(sknotvector.knotlist,
@@ -121,7 +121,7 @@ public class Splinespec {
* Prepares for conversion
* @param ncoords number of coords
*/
- public void layout(int ncoords) {
+ public void layout(final int ncoords) {
// DONE
int stride = ncoords;
for (Knotspec knotspec = kspec; knotspec != null; knotspec = knotspec.next) {
@@ -143,9 +143,9 @@ public class Splinespec {
* Prepares quilt for conversion
* @param quilt quilt to work with
*/
- public void setupquilt(Quilt quilt) {
+ public void setupquilt(final Quilt quilt) {
// DONE
- CArrayOfQuiltspecs qspec = new CArrayOfQuiltspecs(quilt.qspec);
+ final CArrayOfQuiltspecs qspec = new CArrayOfQuiltspecs(quilt.qspec);
quilt.eqspec = new CArrayOfQuiltspecs(qspec.getArray(), dim);
for (Knotspec knotspec = kspec; knotspec != null;) {
qspec.get().stride = knotspec.poststride;
@@ -159,8 +159,8 @@ public class Splinespec {
qspec.get().bdry[1] = (knotspec.kright.getPointer() == knotspec.klast
.getPointer()) ? 1 : 0;
qspec.get().breakpoints = new float[qspec.get().width + 1];
- CArrayOfFloats k = new CArrayOfFloats(qspec.get().breakpoints, 0);
- for (CArrayOfBreakpts bk = new CArrayOfBreakpts(knotspec.bbegin); bk
+ final CArrayOfFloats k = new CArrayOfFloats(qspec.get().breakpoints, 0);
+ for (final CArrayOfBreakpts bk = new CArrayOfBreakpts(knotspec.bbegin); bk
.getPointer() <= knotspec.bend.getPointer(); bk.pp()) {
k.set(bk.get().value);
k.pp();
@@ -177,7 +177,7 @@ public class Splinespec {
* Copies array of control points to output array
* @param ctlarray control points array
*/
- public void copy(CArrayOfFloats ctlarray) {
+ public void copy(final CArrayOfFloats ctlarray) {
// DONE
kspec.copy(ctlarray, outcpts);
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Subdivider.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Subdivider.java
index 37774f811..573c7df11 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Subdivider.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Subdivider.java
@@ -41,7 +41,7 @@ package jogamp.opengl.glu.nurbs;
*/
public class Subdivider {
/**
- * Cull type
+ * Cull type
*/
public static final int CULL_TRIVIAL_REJECT = 0;
@@ -76,7 +76,7 @@ public class Subdivider {
private int subdivisions;
/**
- * U step when using domain distance sampling
+ * U step when using domain distance sampling
*/
private float domain_distance_u_rate;
@@ -133,12 +133,12 @@ public class Subdivider {
/**
* Breakpoints
*/
- private Flist smbrkpts;
+ private final Flist smbrkpts = new Flist();
/**
* Not used
+ * private float[] stepsizes;
*/
- private float[] stepsizes;
/**
* Domain distance in V direction
@@ -148,7 +148,7 @@ public class Subdivider {
/**
* Initializes quilt list
*/
- public void beginQuilts(Backend backend) {
+ public void beginQuilts(final Backend backend) {
// DONE
qlist = null;
renderhints = new Renderhints();
@@ -162,7 +162,7 @@ public class Subdivider {
* Adds quilt to linked list
* @param quilt added quilt
*/
- public void addQuilt(Quilt quilt) {
+ public void addQuilt(final Quilt quilt) {
// DONE
if (qlist == null)
qlist = quilt;
@@ -198,8 +198,8 @@ public class Subdivider {
}
}
- float[] from = new float[2];
- float[] to = new float[2];
+ final float[] from = new float[2];
+ final float[] to = new float[2];
spbrkpts = new Flist();
tpbrkpts = new Flist();
@@ -215,7 +215,7 @@ public class Subdivider {
makeBorderTrim(from, to);
}
} else {
- float[] rate = new float[2];
+ final float[] rate = new float[2];
qlist.findRates(spbrkpts, tpbrkpts, rate);
// System.out.println("subdivider.drawsurfaces decompose");
}
@@ -231,8 +231,8 @@ public class Subdivider {
int num_v_steps;
for (i = spbrkpts.start; i < spbrkpts.end - 1; i++) {
for (j = tpbrkpts.start; j < tpbrkpts.end - 1; j++) {
- float[] pta = new float[2];
- float[] ptb = new float[2];
+ final float[] pta = new float[2];
+ final float[] ptb = new float[2];
pta[0] = spbrkpts.pts[i];
ptb[0] = spbrkpts.pts[i + 1];
@@ -266,7 +266,7 @@ public class Subdivider {
* Empty method
* @param initialbin2
*/
- private void freejarcs(Bin initialbin2) {
+ private void freejarcs(final Bin initialbin2) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.freejarcs");
}
@@ -275,7 +275,7 @@ public class Subdivider {
* Subdivide in U direction
* @param source Trimming arcs source
*/
- private void subdivideInS(Bin source) {
+ private void subdivideInS(final Bin source) {
// DONE
if (renderhints.display_method == NurbsConsts.N_OUTLINE_PARAM) {
outline(source);
@@ -294,13 +294,13 @@ public class Subdivider {
* @param start breakpoints start
* @param end breakpoints end
*/
- private void splitInS(Bin source, int start, int end) {
+ private void splitInS(final Bin source, final int start, final int end) {
// DONE
if (source.isnonempty()) {
if (start != end) {
- int i = start + (end - start) / 2;
- Bin left = new Bin();
- Bin right = new Bin();
+ final int i = start + (end - start) / 2;
+ final Bin left = new Bin();
+ final Bin right = new Bin();
split(source, left, right, 0, spbrkpts.pts[i]);
splitInS(left, start, i);
@@ -329,15 +329,15 @@ public class Subdivider {
* @param start
* @param end
*/
- private void splitInT(Bin source, int start, int end) {
+ private void splitInT(final Bin source, final int start, final int end) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.splitint");
if (source.isnonempty()) {
if (start != end) {
- int i = start + (end - start) / 2;
- Bin left = new Bin();
- Bin right = new Bin();
+ final int i = start + (end - start) / 2;
+ final Bin left = new Bin();
+ final Bin right = new Bin();
split(source, left, right, 1, tpbrkpts.pts[i + 1]);
splitInT(left, start, i);
splitInT(right, i + 1, end);
@@ -352,8 +352,8 @@ public class Subdivider {
setArcTypeBezier();
setDegenerate();
- float[] pta = new float[2];
- float[] ptb = new float[2];
+ final float[] pta = new float[2];
+ final float[] ptb = new float[2];
pta[0] = spbrkpts.pts[s_index - 1];
pta[1] = tpbrkpts.pts[t_index - 1];
@@ -362,7 +362,7 @@ public class Subdivider {
ptb[1] = tpbrkpts.pts[t_index];
qlist.downloadAll(pta, ptb, backend);
- Patchlist patchlist = new Patchlist(qlist, pta, ptb);
+ final Patchlist patchlist = new Patchlist(qlist, pta, ptb);
samplingSplit(source, patchlist,
renderhints.maxsubdivisions, 0);
@@ -375,14 +375,14 @@ public class Subdivider {
}
/**
- * Sample
+ * Sample
* @param source
* @param patchlist
* @param subdivisions
* @param param
*/
- private void samplingSplit(Bin source, Patchlist patchlist,
- int subdivisions, int param) {
+ private void samplingSplit(final Bin source, final Patchlist patchlist,
+ final int subdivisions, int param) {
// DONE
if (!source.isnonempty())
return;
@@ -408,13 +408,13 @@ public class Subdivider {
else
param = 1 - param;
- Bin left = new Bin();
- Bin right = new Bin();
+ final Bin left = new Bin();
+ final Bin right = new Bin();
- float mid = (float) ((patchlist.pspec[param].range[0] + patchlist.pspec[param].range[1]) * .5);
+ final float mid = (float) ((patchlist.pspec[param].range[0] + patchlist.pspec[param].range[1]) * .5);
split(source, left, right, param, mid);
- Patchlist subpatchlist = new Patchlist(patchlist, param, mid);
+ final Patchlist subpatchlist = new Patchlist(patchlist, param, mid);
samplingSplit(left, subpatchlist, subdivisions - 1, param);
samplingSplit(right, subpatchlist, subdivisions - 1, param);
} else {
@@ -433,18 +433,18 @@ public class Subdivider {
* @param subdivisions
* @param param
*/
- private void nonSamplingSplit(Bin source, Patchlist patchlist,
- int subdivisions, int param) {
+ private void nonSamplingSplit(final Bin source, final Patchlist patchlist,
+ final int subdivisions, int param) {
// DONE
if (patchlist.needsNonSamplingSubdivision() && subdivisions > 0) {
param = 1 - param;
- Bin left = new Bin();
- Bin right = new Bin();
+ final Bin left = new Bin();
+ final Bin right = new Bin();
- float mid = (float) ((patchlist.pspec[param].range[0] + patchlist.pspec[param].range[1]) * .5);
+ final float mid = (float) ((patchlist.pspec[param].range[0] + patchlist.pspec[param].range[1]) * .5);
split(source, left, right, param, mid);
- Patchlist subpatchlist = new Patchlist(patchlist, param, mid);
+ final Patchlist subpatchlist = new Patchlist(patchlist, param, mid);
if (left.isnonempty()) {
if (subpatchlist.cullCheck() == CULL_TRIVIAL_REJECT)
freejarcs(left);
@@ -483,7 +483,7 @@ public class Subdivider {
* @param start
* @param end
*/
- private void monosplitInS(Bin source, int start, int end) {
+ private void monosplitInS(final Bin source, final int start, final int end) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.monosplitins");
}
@@ -492,7 +492,7 @@ public class Subdivider {
* Not used
* @param source
*/
- private void findIrregularS(Bin source) {
+ private void findIrregularS(final Bin source) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.findIrregularS");
}
@@ -510,7 +510,7 @@ public class Subdivider {
* @param source
* @param patchlist
*/
- private void tesselation(Bin source, Patchlist patchlist) {
+ private void tesselation(final Bin source, final Patchlist patchlist) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.tesselation");
}
@@ -531,19 +531,19 @@ public class Subdivider {
* @param param
* @param value
*/
- private void split(Bin bin, Bin left, Bin right, int param, float value) {
+ private void split(final Bin bin, final Bin left, final Bin right, final int param, final float value) {
// DONE
- Bin intersections = new Bin();
- Bin unknown = new Bin();
+ final Bin intersections = new Bin();
+ final Bin unknown = new Bin();
partition(bin, left, intersections, right, unknown, param, value);
- int count = intersections.numarcs();
+ final int count = intersections.numarcs();
// TODO jumpbuffer ??
if (count % 2 == 0) {
- Arc[] arclist = new Arc[MAXARCS];
+ final Arc[] arclist = new Arc[MAXARCS];
CArrayOfArcs list;
if (count >= MAXARCS) {
list = new CArrayOfArcs(new Arc[count]);
@@ -559,7 +559,7 @@ public class Subdivider {
last.set(jarc);
if (param == 0) {// sort into incrasing t order
- ArcSdirSorter sorter = new ArcSdirSorter(this);
+ final ArcSdirSorter sorter = new ArcSdirSorter(this);
sorter.qsort(list, count);
for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last
@@ -578,7 +578,7 @@ public class Subdivider {
}
} else {// sort into decreasing s order
- ArcTdirSorter sorter = new ArcTdirSorter(this);
+ final ArcTdirSorter sorter = new ArcTdirSorter(this);
sorter.qsort(list, count);
for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last
@@ -609,7 +609,7 @@ public class Subdivider {
* @param arc
* @param relative
*/
- private void join_t(Bin left, Bin right, Arc arc, Arc relative) {
+ private void join_t(final Bin left, final Bin right, final Arc arc, final Arc relative) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.join_t");
}
@@ -619,7 +619,7 @@ public class Subdivider {
* @param arc
* @param relative
*/
- private void check_t(Arc arc, Arc relative) {
+ private void check_t(final Arc arc, final Arc relative) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.check_t");
}
@@ -631,28 +631,28 @@ public class Subdivider {
* @param jarc1
* @param jarc2
*/
- private void join_s(Bin left, Bin right, Arc jarc1, Arc jarc2) {
+ private void join_s(final Bin left, final Bin right, Arc jarc1, Arc jarc2) {
// DONE
if (!jarc1.getitail())
jarc1 = jarc1.next;
if (!jarc2.getitail())
jarc2 = jarc2.next;
- float s = jarc1.tail()[0];
- float t1 = jarc1.tail()[1];
- float t2 = jarc2.tail()[1];
+ final float s = jarc1.tail()[0];
+ final float t1 = jarc1.tail()[1];
+ final float t2 = jarc2.tail()[1];
if (t1 == t2) {
simplelink(jarc1, jarc2);
} else {
- Arc newright = new Arc(Arc.ARC_RIGHT);
- Arc newleft = new Arc(Arc.ARC_LEFT);
+ final Arc newright = new Arc(Arc.ARC_RIGHT);
+ final Arc newleft = new Arc(Arc.ARC_LEFT);
if (isBezierArcType()) {
arctesselator.bezier(newright, s, s, t1, t2);
arctesselator.bezier(newleft, s, s, t2, t1);
} else {
- arctesselator.pwl_right(newright, s, t1, t2, stepsizes[0]);
- arctesselator.pwl_left(newright, s, t2, t1, stepsizes[2]);
+ arctesselator.pwl_right(newright, s, t1, t2, 0 /* stepsizes[0] */);
+ arctesselator.pwl_left(newright, s, t2, t1, 0 /* stepsizes[2] */);
}
link(jarc1, jarc2, newright, newleft);
left.addarc(newright);
@@ -668,7 +668,7 @@ public class Subdivider {
* @param newright
* @param newleft
*/
- private void link(Arc jarc1, Arc jarc2, Arc newright, Arc newleft) {
+ private void link(final Arc jarc1, final Arc jarc2, final Arc newright, final Arc newleft) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.link");
}
@@ -688,7 +688,7 @@ public class Subdivider {
* @param jarc1
* @param jarc2
*/
- private void simplelink(Arc jarc1, Arc jarc2) {
+ private void simplelink(final Arc jarc1, final Arc jarc2) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.simplelink");
}
@@ -698,7 +698,7 @@ public class Subdivider {
* @param arc
* @param relative
*/
- private void check_s(Arc arc, Arc relative) {
+ private void check_s(final Arc arc, final Arc relative) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.check_s");
@@ -714,17 +714,17 @@ public class Subdivider {
* @param param
* @param value
*/
- private void partition(Bin bin, Bin left, Bin intersections, Bin right,
- Bin unknown, int param, float value) {
+ private void partition(final Bin bin, final Bin left, final Bin intersections, final Bin right,
+ final Bin unknown, final int param, final float value) {
- Bin headonleft = new Bin();
- Bin headonright = new Bin();
- Bin tailonleft = new Bin();
- Bin tailonright = new Bin();
+ final Bin headonleft = new Bin();
+ final Bin headonright = new Bin();
+ final Bin tailonleft = new Bin();
+ final Bin tailonright = new Bin();
for (Arc jarc = bin.removearc(); jarc != null; jarc = bin.removearc()) {
- float tdiff = jarc.tail()[param] - value;
- float hdiff = jarc.head()[param] - value;
+ final float tdiff = jarc.tail()[param] - value;
+ final float hdiff = jarc.head()[param] - value;
if (tdiff > 0) {
if (hdiff > 0) {
@@ -732,7 +732,6 @@ public class Subdivider {
} else if (hdiff == 0) {
tailonright.addarc(jarc);
} else {
- Arc jtemp;
switch (arc_split(jarc, param, value, 0)) {
case 2:
tailonright.addarc(jarc);
@@ -785,8 +784,8 @@ public class Subdivider {
* @param right
* @param value
*/
- private void classify_tailonright_t(Bin tailonright, Bin intersections,
- Bin right, float value) {
+ private void classify_tailonright_t(final Bin tailonright, final Bin intersections,
+ final Bin right, final float value) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.classify_tailonright_t");
@@ -799,14 +798,14 @@ public class Subdivider {
* @param out
* @param val
*/
- private void classify_tailonleft_s(Bin bin, Bin in, Bin out, float val) {
+ private void classify_tailonleft_s(final Bin bin, final Bin in, final Bin out, final float val) {
// DONE
Arc j;
while ((j = bin.removearc()) != null) {
j.clearitail();
- float diff = j.next.head()[0] - val;
+ final float diff = j.next.head()[0] - val;
if (diff > 0) {
in.addarc(j);
} else if (diff < 0) {
@@ -831,13 +830,13 @@ public class Subdivider {
* @param out
* @param val
*/
- private void classify_headonright_s(Bin bin, Bin in, Bin out, float val) {
+ private void classify_headonright_s(final Bin bin, final Bin in, final Bin out, final float val) {
// DONE
Arc j;
while ((j = bin.removearc()) != null) {
j.setitail();
- float diff = j.prev.tail()[0] - val;
+ final float diff = j.prev.tail()[0] - val;
if (diff > 0) {
if (ccwTurn_sr(j.prev, j))
out.addarc(j);
@@ -860,7 +859,7 @@ public class Subdivider {
* @param j
* @return false
*/
- private boolean ccwTurn_sr(Arc prev, Arc j) {
+ private boolean ccwTurn_sr(final Arc prev, final Arc j) {
// TODO Auto-generated method stub
// System.out.println("TODO ccwTurn_sr");
return false;
@@ -873,8 +872,8 @@ public class Subdivider {
* @param right
* @param value
*/
- private void classify_headonright_t(Bin headonright, Bin intersections,
- Bin right, float value) {
+ private void classify_headonright_t(final Bin headonright, final Bin intersections,
+ final Bin right, final float value) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.classify_headonright_t");
}
@@ -886,8 +885,8 @@ public class Subdivider {
* @param left
* @param value
*/
- private void classify_tailonleft_t(Bin tailonleft, Bin intersections,
- Bin left, float value) {
+ private void classify_tailonleft_t(final Bin tailonleft, final Bin intersections,
+ final Bin left, final float value) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.classify_tailonleft_t");
}
@@ -899,13 +898,13 @@ public class Subdivider {
* @param out
* @param val
*/
- private void classify_headonleft_t(Bin bin, Bin in, Bin out, float val) {
+ private void classify_headonleft_t(final Bin bin, final Bin in, final Bin out, final float val) {
// DONE
Arc j;
while ((j = bin.removearc()) != null) {
j.setitail();
- float diff = j.prev.tail()[1] - val;
+ final float diff = j.prev.tail()[1] - val;
if (diff > 0) {
out.addarc(j);
} else if (diff < 0) {
@@ -928,7 +927,7 @@ public class Subdivider {
* @param j
* @return false
*/
- private boolean ccwTurn_tl(Arc prev, Arc j) {
+ private boolean ccwTurn_tl(final Arc prev, final Arc j) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.ccwTurn_tl");
return false;
@@ -941,13 +940,13 @@ public class Subdivider {
* @param out
* @param val
*/
- private void classify_tailonright_s(Bin bin, Bin in, Bin out, float val) {
+ private void classify_tailonright_s(final Bin bin, final Bin in, final Bin out, final float val) {
// DONE
Arc j;
while ((j = bin.removearc()) != null) {
j.clearitail();
- float diff = j.next.head()[0] - val;
+ final float diff = j.next.head()[0] - val;
if (diff > 0) {
if (ccwTurn_sr(j, j.next))
out.addarc(j);
@@ -972,13 +971,13 @@ public class Subdivider {
* @param out
* @param val
*/
- private void classify_headonleft_s(Bin bin, Bin in, Bin out, float val) {
+ private void classify_headonleft_s(final Bin bin, final Bin in, final Bin out, final float val) {
// DONE
Arc j;
while ((j = bin.removearc()) != null) {
j.setitail();
- float diff = j.prev.tail()[0] - val;
+ final float diff = j.prev.tail()[0] - val;
if (diff > 0) {
out.addarc(j);
} else if (diff < 0) {
@@ -1002,7 +1001,7 @@ public class Subdivider {
* @param j
* @return false
*/
- private boolean ccwTurn_sl(Arc prev, Arc j) {
+ private boolean ccwTurn_sl(final Arc prev, final Arc j) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.ccwTurn_sl");
return false;
@@ -1016,7 +1015,7 @@ public class Subdivider {
* @param i
* @return 0
*/
- private int arc_split(Arc jarc, int param, float value, int i) {
+ private int arc_split(final Arc jarc, final int param, final float value, final int i) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.arc_split");
return 0;
@@ -1043,7 +1042,7 @@ public class Subdivider {
* Not used
* @param source
*/
- private void outline(Bin source) {
+ private void outline(final Bin source) {
// TODO Auto-generated method stub
// System.out.println("TODO subdivider.outline");
}
@@ -1053,13 +1052,13 @@ public class Subdivider {
* @param from range beginnings
* @param to range ends
*/
- private void makeBorderTrim(float[] from, float[] to) {
+ private void makeBorderTrim(final float[] from, final float[] to) {
// DONE
- float smin = from[0];
- float smax = to[0];
+ final float smin = from[0];
+ final float smax = to[0];
- float tmin = from[1];
- float tmax = to[1];
+ final float tmin = from[1];
+ final float tmax = to[1];
pjarc = null;
Arc jarc = null;
@@ -1092,10 +1091,10 @@ public class Subdivider {
*/
public void drawCurves() {
// DONE
- float[] from = new float[1];
- float[] to = new float[1];
+ final float[] from = new float[1];
+ final float[] to = new float[1];
- Flist bpts = new Flist();
+ final Flist bpts = new Flist();
qlist.getRange(from, to, bpts);
renderhints.init();
@@ -1103,13 +1102,13 @@ public class Subdivider {
backend.bgncurv();
for (int i = bpts.start; i < bpts.end - 1; i++) {
- float[] pta = new float[1];
- float[] ptb = new float[1];
+ final float[] pta = new float[1];
+ final float[] ptb = new float[1];
pta[0] = bpts.pts[i];
ptb[0] = bpts.pts[i + 1];
qlist.downloadAll(pta, ptb, backend);
- Curvelist curvelist = new Curvelist(qlist, pta, ptb);
+ final Curvelist curvelist = new Curvelist(qlist, pta, ptb);
samplingSplit(curvelist, renderhints.maxsubdivisions);
}
backend.endcurv();
@@ -1120,7 +1119,7 @@ public class Subdivider {
* @param curvelist list of curves
* @param maxsubdivisions maximum number of subdivisions
*/
- private void samplingSplit(Curvelist curvelist, int maxsubdivisions) {
+ private void samplingSplit(final Curvelist curvelist, final int maxsubdivisions) {
if (curvelist.cullCheck() == CULL_TRIVIAL_REJECT)
return;
@@ -1130,7 +1129,7 @@ public class Subdivider {
// TODO kód
// System.out.println("TODO subdivider-needsSamplingSubdivision");
} else {
- int nu = (int) (1 + curvelist.range[2] / curvelist.stepsize);
+ final int nu = (int) (1 + curvelist.range[2] / curvelist.stepsize);
backend.curvgrid(curvelist.range[0], curvelist.range[1], nu);
backend.curvmesh(0, nu);
}
@@ -1142,7 +1141,7 @@ public class Subdivider {
* @param d new domain_distance_u_rate value
*/
- public void set_domain_distance_u_rate(double d) {
+ public void set_domain_distance_u_rate(final double d) {
// DONE
domain_distance_u_rate = (float) d;
}
@@ -1151,7 +1150,7 @@ public class Subdivider {
* Sets new domain_distance_v_rate value
* @param d new domain_distance_v_rate value
*/
- public void set_domain_distance_v_rate(double d) {
+ public void set_domain_distance_v_rate(final double d) {
// DONE
domain_distance_v_rate = (float) d;
}
@@ -1160,7 +1159,7 @@ public class Subdivider {
* Sets new is_domain_distance_sampling value
* @param i new is_domain_distance_sampling value
*/
- public void set_is_domain_distance_sampling(int i) {
+ public void set_is_domain_distance_sampling(final int i) {
// DONE
this.is_domain_distance_sampling = i;
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/TrimVertex.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/TrimVertex.java
index e88d69709..1025afb7c 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/TrimVertex.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/TrimVertex.java
@@ -36,9 +36,9 @@ package jogamp.opengl.glu.nurbs;
/**
* Holds vertex used in trim
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class TrimVertex {
diff --git a/src/jogl/classes/jogamp/opengl/glu/registry/Registry.java b/src/jogl/classes/jogamp/opengl/glu/registry/Registry.java
index 3d669d9bb..5cae679a2 100644
--- a/src/jogl/classes/jogamp/opengl/glu/registry/Registry.java
+++ b/src/jogl/classes/jogamp/opengl/glu/registry/Registry.java
@@ -6,15 +6,15 @@
* this file except in compliance with the License. You may obtain a copy
* of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
* Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
- *
+ *
* http://oss.sgi.com/projects/FreeB
- *
+ *
* Note that, as provided in the License, the Software is distributed on an
* "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
* DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
* CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
* PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
- *
+ *
* NOTE: The Original Code (as defined below) has been licensed to Sun
* Microsystems, Inc. ("Sun") under the SGI Free Software License B
* (Version 1.1), shown above ("SGI License"). Pursuant to Section
@@ -30,7 +30,7 @@
* Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
* Copyright in any portions created by third parties is as indicated
* elsewhere herein. All Rights Reserved.
- *
+ *
* Additional Notice Provisions: The application programming interfaces
* established by SGI in conjunction with the Original Code are The
* OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
@@ -51,12 +51,12 @@ import javax.media.opengl.glu.GLU;
* @author Administrator
*/
public class Registry {
-
+
/** Creates a new instance of Registry */
public Registry() {
}
-
- public static String gluGetString(int name) {
+
+ public static String gluGetString(final int name) {
if( name == GLU.GLU_VERSION ) {
return( "1.3" );
} else if( name == GLU.GLU_EXTENSIONS ) {
@@ -64,8 +64,8 @@ public class Registry {
}
return( null );
}
-
- public static boolean gluCheckExtension( String extName, String extString ) {
+
+ public static boolean gluCheckExtension( final String extName, final String extString ) {
if( extName == null || extString == null ) {
return( false );
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/Dict.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/Dict.java
index 3ac9df67a..3bb759359 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/Dict.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/Dict.java
@@ -60,8 +60,8 @@ class Dict {
private Dict() {
}
- static Dict dictNewDict(Object frame, DictLeq leq) {
- Dict dict = new Dict();
+ static Dict dictNewDict(final Object frame, final DictLeq leq) {
+ final Dict dict = new Dict();
dict.head = new DictNode();
dict.head.key = null;
@@ -74,22 +74,22 @@ class Dict {
return dict;
}
- static void dictDeleteDict(Dict dict) {
+ static void dictDeleteDict(final Dict dict) {
dict.head = null;
dict.frame = null;
dict.leq = null;
}
- static DictNode dictInsert(Dict dict, Object key) {
+ static DictNode dictInsert(final Dict dict, final Object key) {
return dictInsertBefore(dict, dict.head, key);
}
- static DictNode dictInsertBefore(Dict dict, DictNode node, Object key) {
+ static DictNode dictInsertBefore(final Dict dict, DictNode node, final Object key) {
do {
node = node.prev;
} while (node.key != null && !dict.leq.leq(dict.frame, node.key, key));
- DictNode newNode = new DictNode();
+ final DictNode newNode = new DictNode();
newNode.key = key;
newNode.next = node.next;
node.next.prev = newNode;
@@ -99,32 +99,32 @@ class Dict {
return newNode;
}
- static Object dictKey(DictNode aNode) {
+ static Object dictKey(final DictNode aNode) {
return aNode.key;
}
- static DictNode dictSucc(DictNode aNode) {
+ static DictNode dictSucc(final DictNode aNode) {
return aNode.next;
}
- static DictNode dictPred(DictNode aNode) {
+ static DictNode dictPred(final DictNode aNode) {
return aNode.prev;
}
- static DictNode dictMin(Dict aDict) {
+ static DictNode dictMin(final Dict aDict) {
return aDict.head.next;
}
- static DictNode dictMax(Dict aDict) {
+ static DictNode dictMax(final Dict aDict) {
return aDict.head.prev;
}
- static void dictDelete(Dict dict, DictNode node) {
+ static void dictDelete(final Dict dict, final DictNode node) {
node.next.prev = node.prev;
node.prev.next = node.next;
}
- static DictNode dictSearch(Dict dict, Object key) {
+ static DictNode dictSearch(final Dict dict, final Object key) {
DictNode node = dict.head;
do {
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/GLUhalfEdge.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/GLUhalfEdge.java
index 29944f9b2..a849058c8 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/GLUhalfEdge.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/GLUhalfEdge.java
@@ -65,7 +65,7 @@ class GLUhalfEdge {
public int winding; /* change in winding number when crossing */
public boolean first;
- public GLUhalfEdge(boolean first) {
+ public GLUhalfEdge(final boolean first) {
this.first = first;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/GLUtessellatorImpl.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/GLUtessellatorImpl.java
index d594cb3eb..f2a9c78fa 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/GLUtessellatorImpl.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/GLUtessellatorImpl.java
@@ -177,11 +177,11 @@ public class GLUtessellatorImpl implements GLUtessellator {
mesh = null;
}
- private void requireState(int newState) {
+ private void requireState(final int newState) {
if (state != newState) gotoState(newState);
}
- private void gotoState(int newState) {
+ private void gotoState(final int newState) {
while (state != newState) {
/* We change the current state one level at a time, to get to
* the desired state.
@@ -211,7 +211,7 @@ public class GLUtessellatorImpl implements GLUtessellator {
requireState(TessState.T_DORMANT);
}
- public void gluTessProperty(int which, double value) {
+ public void gluTessProperty(final int which, final double value) {
switch (which) {
case GLU.GLU_TESS_TOLERANCE:
if (value < 0.0 || value > 1.0) break;
@@ -219,7 +219,7 @@ public class GLUtessellatorImpl implements GLUtessellator {
return;
case GLU.GLU_TESS_WINDING_RULE:
- int windingRule = (int) value;
+ final int windingRule = (int) value;
if (windingRule != value) break; /* not an integer */
switch (windingRule) {
@@ -250,7 +250,7 @@ public class GLUtessellatorImpl implements GLUtessellator {
}
/* Returns tessellator property */
- public void gluGetTessProperty(int which, double[] value, int value_offset) {
+ public void gluGetTessProperty(final int which, final double[] value, final int value_offset) {
switch (which) {
case GLU.GLU_TESS_TOLERANCE:
/* tolerance should be in range [0..1] */
@@ -279,13 +279,13 @@ public class GLUtessellatorImpl implements GLUtessellator {
}
} /* gluGetTessProperty() */
- public void gluTessNormal(double x, double y, double z) {
+ public void gluTessNormal(final double x, final double y, final double z) {
normal[0] = x;
normal[1] = y;
normal[2] = z;
}
- public void gluTessCallback(int which, GLUtessellatorCallback aCallback) {
+ public void gluTessCallback(final int which, final GLUtessellatorCallback aCallback) {
switch (which) {
case GLU.GLU_TESS_BEGIN:
callBegin = aCallback == null ? NULL_CB : aCallback;
@@ -340,7 +340,7 @@ public class GLUtessellatorImpl implements GLUtessellator {
}
}
- private boolean addVertex(double[] coords, Object vertexData) {
+ private boolean addVertex(final double[] coords, final Object vertexData) {
GLUhalfEdge e;
e = lastEdge;
@@ -354,7 +354,7 @@ public class GLUtessellatorImpl implements GLUtessellator {
/* Create a new vertex and edge which immediately follow e
* in the ordering around the left face.
*/
- if (Mesh.__gl_meshSplitEdge(e) == null) return false;
+ Mesh.__gl_meshSplitEdge(e);
e = e.Lnext;
}
@@ -377,12 +377,12 @@ public class GLUtessellatorImpl implements GLUtessellator {
return true;
}
- private void cacheVertex(double[] coords, Object vertexData) {
+ private void cacheVertex(final double[] coords, final Object vertexData) {
if (cache[cacheCount] == null) {
cache[cacheCount] = new CachedVertex();
}
- CachedVertex v = cache[cacheCount];
+ final CachedVertex v = cache[cacheCount];
v.data = vertexData;
v.coords[0] = coords[0];
@@ -393,14 +393,15 @@ public class GLUtessellatorImpl implements GLUtessellator {
private boolean flushCache() {
- CachedVertex[] v = cache;
+ final CachedVertex[] v = cache;
mesh = Mesh.__gl_meshNewMesh();
- if (mesh == null) return false;
for (int i = 0; i < cacheCount; i++) {
- CachedVertex vertex = v[i];
- if (!addVertex(vertex.coords, vertex.data)) return false;
+ final CachedVertex vertex = v[i];
+ if (!addVertex(vertex.coords, vertex.data)) {
+ return false;
+ }
}
cacheCount = 0;
flushCacheOnNextVertex = false;
@@ -408,11 +409,11 @@ public class GLUtessellatorImpl implements GLUtessellator {
return true;
}
- public void gluTessVertex(double[] coords, int coords_offset, Object vertexData) {
+ public void gluTessVertex(final double[] coords, final int coords_offset, final Object vertexData) {
int i;
boolean tooLarge = false;
double x;
- double[] clamped = new double[3];
+ final double[] clamped = new double[3];
requireState(TessState.T_IN_CONTOUR);
@@ -456,7 +457,7 @@ public class GLUtessellatorImpl implements GLUtessellator {
}
- public void gluTessBeginPolygon(Object data) {
+ public void gluTessBeginPolygon(final Object data) {
requireState(TessState.T_DORMANT);
state = TessState.T_IN_POLYGON;
@@ -573,7 +574,7 @@ public class GLUtessellatorImpl implements GLUtessellator {
Mesh.__gl_meshDeleteMesh(mesh);
polygonData = null;
mesh = null;
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY);
}
@@ -590,7 +591,7 @@ public class GLUtessellatorImpl implements GLUtessellator {
/*ARGSUSED*/
- public void gluNextContour(int type) {
+ public void gluNextContour(final int type) {
gluTessEndContour();
gluTessBeginContour();
}
@@ -601,21 +602,21 @@ public class GLUtessellatorImpl implements GLUtessellator {
gluTessEndPolygon();
}
- void callBeginOrBeginData(int a) {
+ void callBeginOrBeginData(final int a) {
if (callBeginData != NULL_CB)
callBeginData.beginData(a, polygonData);
else
callBegin.begin(a);
}
- void callVertexOrVertexData(Object a) {
+ void callVertexOrVertexData(final Object a) {
if (callVertexData != NULL_CB)
callVertexData.vertexData(a, polygonData);
else
callVertex.vertex(a);
}
- void callEdgeFlagOrEdgeFlagData(boolean a) {
+ void callEdgeFlagOrEdgeFlagData(final boolean a) {
if (callEdgeFlagData != NULL_CB)
callEdgeFlagData.edgeFlagData(a, polygonData);
else
@@ -629,14 +630,14 @@ public class GLUtessellatorImpl implements GLUtessellator {
callEnd.end();
}
- void callCombineOrCombineData(double[] coords, Object[] vertexData, float[] weights, Object[] outData) {
+ void callCombineOrCombineData(final double[] coords, final Object[] vertexData, final float[] weights, final Object[] outData) {
if (callCombineData != NULL_CB)
callCombineData.combineData(coords, vertexData, weights, outData, polygonData);
else
callCombine.combine(coords, vertexData, weights, outData);
}
- void callErrorOrErrorData(int a) {
+ void callErrorOrErrorData(final int a) {
if (callErrorData != NULL_CB)
callErrorData.errorData(a, polygonData);
else
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/Geom.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/Geom.java
index 3da2d267e..493052f79 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/Geom.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/Geom.java
@@ -66,7 +66,7 @@ class Geom {
* let r be the negated result (this evaluates (uw)(v->s)), then
* r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t).
*/
- static double EdgeEval(GLUvertex u, GLUvertex v, GLUvertex w) {
+ static double EdgeEval(final GLUvertex u, final GLUvertex v, final GLUvertex w) {
double gapL, gapR;
assert (VertLeq(u, v) && VertLeq(v, w));
@@ -85,7 +85,7 @@ class Geom {
return 0;
}
- static double EdgeSign(GLUvertex u, GLUvertex v, GLUvertex w) {
+ static double EdgeSign(final GLUvertex u, final GLUvertex v, final GLUvertex w) {
double gapL, gapR;
assert (VertLeq(u, v) && VertLeq(v, w));
@@ -105,7 +105,7 @@ class Geom {
* Define versions of EdgeSign, EdgeEval with s and t transposed.
*/
- static double TransEval(GLUvertex u, GLUvertex v, GLUvertex w) {
+ static double TransEval(final GLUvertex u, final GLUvertex v, final GLUvertex w) {
/* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w),
* evaluates the t-coord of the edge uw at the s-coord of the vertex v.
* Returns v->s - (uw)(v->t), ie. the signed distance from uw to v.
@@ -134,7 +134,7 @@ class Geom {
return 0;
}
- static double TransSign(GLUvertex u, GLUvertex v, GLUvertex w) {
+ static double TransSign(final GLUvertex u, final GLUvertex v, final GLUvertex w) {
/* Returns a number whose sign matches TransEval(u,v,w) but which
* is cheaper to evaluate. Returns > 0, == 0 , or < 0
* as v is above, on, or below the edge uw.
@@ -154,7 +154,7 @@ class Geom {
}
- static boolean VertCCW(GLUvertex u, GLUvertex v, GLUvertex w) {
+ static boolean VertCCW(final GLUvertex u, final GLUvertex v, final GLUvertex w) {
/* For almost-degenerate situations, the results are not reliable.
* Unless the floating-point arithmetic can be performed without
* rounding errors, *any* implementation will give incorrect results
@@ -172,7 +172,7 @@ class Geom {
* MIN(x,y) <= r <= MAX(x,y), and the results are very accurate
* even when a and b differ greatly in magnitude.
*/
- static double Interpolate(double a, double x, double b, double y) {
+ static double Interpolate(double a, final double x, double b, final double y) {
a = (a < 0) ? 0 : a;
b = (b < 0) ? 0 : b;
if (a <= b) {
@@ -188,7 +188,7 @@ class Geom {
static void EdgeIntersect(GLUvertex o1, GLUvertex d1,
GLUvertex o2, GLUvertex d2,
- GLUvertex v)
+ final GLUvertex v)
/* Given edges (o1,d1) and (o2,d2), compute their point of intersection.
* The computed point is guaranteed to lie in the intersection of the
* bounding rectangles defined by each edge.
@@ -204,12 +204,12 @@ class Geom {
*/
if (!VertLeq(o1, d1)) {
- GLUvertex temp = o1;
+ final GLUvertex temp = o1;
o1 = d1;
d1 = temp;
}
if (!VertLeq(o2, d2)) {
- GLUvertex temp = o2;
+ final GLUvertex temp = o2;
o2 = d2;
d2 = temp;
}
@@ -248,12 +248,12 @@ class Geom {
/* Now repeat the process for t */
if (!TransLeq(o1, d1)) {
- GLUvertex temp = o1;
+ final GLUvertex temp = o1;
o1 = d1;
d1 = temp;
}
if (!TransLeq(o2, d2)) {
- GLUvertex temp = o2;
+ final GLUvertex temp = o2;
o2 = d2;
d2 = temp;
}
@@ -290,29 +290,29 @@ class Geom {
}
}
- static boolean VertEq(GLUvertex u, GLUvertex v) {
+ static boolean VertEq(final GLUvertex u, final GLUvertex v) {
return u.s == v.s && u.t == v.t;
}
- static boolean VertLeq(GLUvertex u, GLUvertex v) {
+ static boolean VertLeq(final GLUvertex u, final GLUvertex v) {
return u.s < v.s || (u.s == v.s && u.t <= v.t);
}
/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */
- static boolean TransLeq(GLUvertex u, GLUvertex v) {
+ static boolean TransLeq(final GLUvertex u, final GLUvertex v) {
return u.t < v.t || (u.t == v.t && u.s <= v.s);
}
- static boolean EdgeGoesLeft(GLUhalfEdge e) {
+ static boolean EdgeGoesLeft(final GLUhalfEdge e) {
return VertLeq(e.Sym.Org, e.Org);
}
- static boolean EdgeGoesRight(GLUhalfEdge e) {
+ static boolean EdgeGoesRight(final GLUhalfEdge e) {
return VertLeq(e.Org, e.Sym.Org);
}
- static double VertL1dist(GLUvertex u, GLUvertex v) {
+ static double VertL1dist(final GLUvertex u, final GLUvertex v) {
return Math.abs(u.s - v.s) + Math.abs(u.t - v.t);
}
@@ -320,13 +320,13 @@ class Geom {
// Compute the cosine of the angle between the edges between o and
// v1 and between o and v2
- static double EdgeCos(GLUvertex o, GLUvertex v1, GLUvertex v2) {
- double ov1s = v1.s - o.s;
- double ov1t = v1.t - o.t;
- double ov2s = v2.s - o.s;
- double ov2t = v2.t - o.t;
+ static double EdgeCos(final GLUvertex o, final GLUvertex v1, final GLUvertex v2) {
+ final double ov1s = v1.s - o.s;
+ final double ov1t = v1.t - o.t;
+ final double ov2s = v2.s - o.s;
+ final double ov2t = v2.t - o.t;
double dotp = ov1s * ov2s + ov1t * ov2t;
- double len = Math.sqrt(ov1s * ov1s + ov1t * ov1t) * Math.sqrt(ov2s * ov2s + ov2t * ov2t);
+ final double len = Math.sqrt(ov1s * ov1s + ov1t * ov1t) * Math.sqrt(ov2s * ov2s + ov2t * ov2t);
if (len > 0.0) {
dotp /= len;
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/Mesh.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/Mesh.java
index eb48aa5a4..e855a5531 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/Mesh.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/Mesh.java
@@ -115,9 +115,9 @@ class Mesh {
* depending on whether a and b belong to different face or vertex rings.
* For more explanation see __gl_meshSplice() below.
*/
- static void Splice(jogamp.opengl.glu.tessellator.GLUhalfEdge a, jogamp.opengl.glu.tessellator.GLUhalfEdge b) {
- jogamp.opengl.glu.tessellator.GLUhalfEdge aOnext = a.Onext;
- jogamp.opengl.glu.tessellator.GLUhalfEdge bOnext = b.Onext;
+ static void Splice(final jogamp.opengl.glu.tessellator.GLUhalfEdge a, final jogamp.opengl.glu.tessellator.GLUhalfEdge b) {
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge aOnext = a.Onext;
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge bOnext = b.Onext;
aOnext.Sym.Lnext = b;
bOnext.Sym.Lnext = a;
@@ -131,11 +131,11 @@ class Mesh {
* the new vertex *before* vNext so that algorithms which walk the vertex
* list will not see the newly created vertices.
*/
- static void MakeVertex(jogamp.opengl.glu.tessellator.GLUvertex newVertex,
- jogamp.opengl.glu.tessellator.GLUhalfEdge eOrig, jogamp.opengl.glu.tessellator.GLUvertex vNext) {
+ static void MakeVertex(final jogamp.opengl.glu.tessellator.GLUvertex newVertex,
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge eOrig, final jogamp.opengl.glu.tessellator.GLUvertex vNext) {
jogamp.opengl.glu.tessellator.GLUhalfEdge e;
jogamp.opengl.glu.tessellator.GLUvertex vPrev;
- jogamp.opengl.glu.tessellator.GLUvertex vNew = newVertex;
+ final jogamp.opengl.glu.tessellator.GLUvertex vNew = newVertex;
assert (vNew != null);
@@ -164,10 +164,10 @@ class Mesh {
* the new face *before* fNext so that algorithms which walk the face
* list will not see the newly created faces.
*/
- static void MakeFace(jogamp.opengl.glu.tessellator.GLUface newFace, jogamp.opengl.glu.tessellator.GLUhalfEdge eOrig, jogamp.opengl.glu.tessellator.GLUface fNext) {
+ static void MakeFace(final jogamp.opengl.glu.tessellator.GLUface newFace, final jogamp.opengl.glu.tessellator.GLUhalfEdge eOrig, final jogamp.opengl.glu.tessellator.GLUface fNext) {
jogamp.opengl.glu.tessellator.GLUhalfEdge e;
jogamp.opengl.glu.tessellator.GLUface fPrev;
- jogamp.opengl.glu.tessellator.GLUface fNew = newFace;
+ final jogamp.opengl.glu.tessellator.GLUface fNew = newFace;
assert (fNew != null);
@@ -218,8 +218,9 @@ class Mesh {
/* KillVertex( vDel ) destroys a vertex and removes it from the global
* vertex list. It updates the vertex loop to point to a given new vertex.
*/
- static void KillVertex(jogamp.opengl.glu.tessellator.GLUvertex vDel, jogamp.opengl.glu.tessellator.GLUvertex newOrg) {
- jogamp.opengl.glu.tessellator.GLUhalfEdge e, eStart = vDel.anEdge;
+ static void KillVertex(final jogamp.opengl.glu.tessellator.GLUvertex vDel, final jogamp.opengl.glu.tessellator.GLUvertex newOrg) {
+ jogamp.opengl.glu.tessellator.GLUhalfEdge e;
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge eStart = vDel.anEdge;
jogamp.opengl.glu.tessellator.GLUvertex vPrev, vNext;
/* change the origin of all affected edges */
@@ -239,8 +240,9 @@ class Mesh {
/* KillFace( fDel ) destroys a face and removes it from the global face
* list. It updates the face loop to point to a given new face.
*/
- static void KillFace(jogamp.opengl.glu.tessellator.GLUface fDel, jogamp.opengl.glu.tessellator.GLUface newLface) {
- jogamp.opengl.glu.tessellator.GLUhalfEdge e, eStart = fDel.anEdge;
+ static void KillFace(final jogamp.opengl.glu.tessellator.GLUface fDel, final jogamp.opengl.glu.tessellator.GLUface newLface) {
+ jogamp.opengl.glu.tessellator.GLUhalfEdge e;
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge eStart = fDel.anEdge;
jogamp.opengl.glu.tessellator.GLUface fPrev, fNext;
/* change the left face of all affected edges */
@@ -263,10 +265,10 @@ class Mesh {
/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face).
* The loop consists of the two new half-edges.
*/
- public static jogamp.opengl.glu.tessellator.GLUhalfEdge __gl_meshMakeEdge(jogamp.opengl.glu.tessellator.GLUmesh mesh) {
- jogamp.opengl.glu.tessellator.GLUvertex newVertex1 = new jogamp.opengl.glu.tessellator.GLUvertex();
- jogamp.opengl.glu.tessellator.GLUvertex newVertex2 = new jogamp.opengl.glu.tessellator.GLUvertex();
- jogamp.opengl.glu.tessellator.GLUface newFace = new jogamp.opengl.glu.tessellator.GLUface();
+ public static jogamp.opengl.glu.tessellator.GLUhalfEdge __gl_meshMakeEdge(final jogamp.opengl.glu.tessellator.GLUmesh mesh) {
+ final jogamp.opengl.glu.tessellator.GLUvertex newVertex1 = new jogamp.opengl.glu.tessellator.GLUvertex();
+ final jogamp.opengl.glu.tessellator.GLUvertex newVertex2 = new jogamp.opengl.glu.tessellator.GLUvertex();
+ final jogamp.opengl.glu.tessellator.GLUface newFace = new jogamp.opengl.glu.tessellator.GLUface();
jogamp.opengl.glu.tessellator.GLUhalfEdge e;
e = MakeEdge(mesh.eHead);
@@ -302,7 +304,7 @@ class Mesh {
* If eDst == eOrg->Onext, the new vertex will have a single edge.
* If eDst == eOrg->Oprev, the old vertex will have a single edge.
*/
- public static boolean __gl_meshSplice(jogamp.opengl.glu.tessellator.GLUhalfEdge eOrg, jogamp.opengl.glu.tessellator.GLUhalfEdge eDst) {
+ public static boolean __gl_meshSplice(final jogamp.opengl.glu.tessellator.GLUhalfEdge eOrg, final jogamp.opengl.glu.tessellator.GLUhalfEdge eDst) {
boolean joiningLoops = false;
boolean joiningVertices = false;
@@ -323,7 +325,7 @@ class Mesh {
Splice(eDst, eOrg);
if (!joiningVertices) {
- jogamp.opengl.glu.tessellator.GLUvertex newVertex = new jogamp.opengl.glu.tessellator.GLUvertex();
+ final jogamp.opengl.glu.tessellator.GLUvertex newVertex = new jogamp.opengl.glu.tessellator.GLUvertex();
/* We split one vertex into two -- the new vertex is eDst.Org.
* Make sure the old vertex points to a valid half-edge.
@@ -332,7 +334,7 @@ class Mesh {
eOrg.Org.anEdge = eOrg;
}
if (!joiningLoops) {
- jogamp.opengl.glu.tessellator.GLUface newFace = new jogamp.opengl.glu.tessellator.GLUface();
+ final jogamp.opengl.glu.tessellator.GLUface newFace = new jogamp.opengl.glu.tessellator.GLUface();
/* We split one loop into two -- the new loop is eDst.Lface.
* Make sure the old face points to a valid half-edge.
@@ -355,8 +357,8 @@ class Mesh {
* plus a few calls to memFree, but this would allocate and delete
* unnecessary vertices and faces.
*/
- static boolean __gl_meshDelete(jogamp.opengl.glu.tessellator.GLUhalfEdge eDel) {
- jogamp.opengl.glu.tessellator.GLUhalfEdge eDelSym = eDel.Sym;
+ static boolean __gl_meshDelete(final jogamp.opengl.glu.tessellator.GLUhalfEdge eDel) {
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge eDelSym = eDel.Sym;
boolean joiningLoops = false;
/* First step: disconnect the origin vertex eDel.Org. We make all
@@ -377,7 +379,7 @@ class Mesh {
Splice(eDel, eDel.Sym.Lnext);
if (!joiningLoops) {
- jogamp.opengl.glu.tessellator.GLUface newFace = new jogamp.opengl.glu.tessellator.GLUface();
+ final jogamp.opengl.glu.tessellator.GLUface newFace = new jogamp.opengl.glu.tessellator.GLUface();
/* We are splitting one loop into two -- create a new loop for eDel. */
MakeFace(newFace, eDel, eDel.Lface);
@@ -415,9 +417,9 @@ class Mesh {
* eNew == eOrg.Lnext, and eNew.Dst is a newly created vertex.
* eOrg and eNew will have the same left face.
*/
- static jogamp.opengl.glu.tessellator.GLUhalfEdge __gl_meshAddEdgeVertex(jogamp.opengl.glu.tessellator.GLUhalfEdge eOrg) {
+ static jogamp.opengl.glu.tessellator.GLUhalfEdge __gl_meshAddEdgeVertex(final jogamp.opengl.glu.tessellator.GLUhalfEdge eOrg) {
jogamp.opengl.glu.tessellator.GLUhalfEdge eNewSym;
- jogamp.opengl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg);
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg);
eNewSym = eNew.Sym;
@@ -427,7 +429,7 @@ class Mesh {
/* Set the vertex and face information */
eNew.Org = eOrg.Sym.Org;
{
- jogamp.opengl.glu.tessellator.GLUvertex newVertex = new jogamp.opengl.glu.tessellator.GLUvertex();
+ final jogamp.opengl.glu.tessellator.GLUvertex newVertex = new jogamp.opengl.glu.tessellator.GLUvertex();
MakeVertex(newVertex, eNewSym, eNew.Org);
}
@@ -441,9 +443,9 @@ class Mesh {
* such that eNew == eOrg.Lnext. The new vertex is eOrg.Sym.Org == eNew.Org.
* eOrg and eNew will have the same left face.
*/
- public static jogamp.opengl.glu.tessellator.GLUhalfEdge __gl_meshSplitEdge(jogamp.opengl.glu.tessellator.GLUhalfEdge eOrg) {
+ public static jogamp.opengl.glu.tessellator.GLUhalfEdge __gl_meshSplitEdge(final jogamp.opengl.glu.tessellator.GLUhalfEdge eOrg) {
jogamp.opengl.glu.tessellator.GLUhalfEdge eNew;
- jogamp.opengl.glu.tessellator.GLUhalfEdge tempHalfEdge = __gl_meshAddEdgeVertex(eOrg);
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge tempHalfEdge = __gl_meshAddEdgeVertex(eOrg);
eNew = tempHalfEdge.Sym;
@@ -472,10 +474,10 @@ class Mesh {
* If (eOrg.Lnext == eDst), the old face is reduced to a single edge.
* If (eOrg.Lnext.Lnext == eDst), the old face is reduced to two edges.
*/
- static jogamp.opengl.glu.tessellator.GLUhalfEdge __gl_meshConnect(jogamp.opengl.glu.tessellator.GLUhalfEdge eOrg, jogamp.opengl.glu.tessellator.GLUhalfEdge eDst) {
+ static jogamp.opengl.glu.tessellator.GLUhalfEdge __gl_meshConnect(final jogamp.opengl.glu.tessellator.GLUhalfEdge eOrg, final jogamp.opengl.glu.tessellator.GLUhalfEdge eDst) {
jogamp.opengl.glu.tessellator.GLUhalfEdge eNewSym;
boolean joiningLoops = false;
- jogamp.opengl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg);
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg);
eNewSym = eNew.Sym;
@@ -498,7 +500,7 @@ class Mesh {
eOrg.Lface.anEdge = eNewSym;
if (!joiningLoops) {
- jogamp.opengl.glu.tessellator.GLUface newFace = new jogamp.opengl.glu.tessellator.GLUface();
+ final jogamp.opengl.glu.tessellator.GLUface newFace = new jogamp.opengl.glu.tessellator.GLUface();
/* We split one loop into two -- the new loop is eNew.Lface */
MakeFace(newFace, eNew, eOrg.Lface);
@@ -516,8 +518,8 @@ class Mesh {
* An entire mesh can be deleted by zapping its faces, one at a time,
* in any order. Zapped faces cannot be used in further mesh operations!
*/
- static void __gl_meshZapFace(jogamp.opengl.glu.tessellator.GLUface fZap) {
- jogamp.opengl.glu.tessellator.GLUhalfEdge eStart = fZap.anEdge;
+ static void __gl_meshZapFace(final jogamp.opengl.glu.tessellator.GLUface fZap) {
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge eStart = fZap.anEdge;
jogamp.opengl.glu.tessellator.GLUhalfEdge e, eNext, eSym;
jogamp.opengl.glu.tessellator.GLUface fPrev, fNext;
@@ -566,7 +568,7 @@ class Mesh {
jogamp.opengl.glu.tessellator.GLUface f;
jogamp.opengl.glu.tessellator.GLUhalfEdge e;
jogamp.opengl.glu.tessellator.GLUhalfEdge eSym;
- jogamp.opengl.glu.tessellator.GLUmesh mesh = new jogamp.opengl.glu.tessellator.GLUmesh();
+ final jogamp.opengl.glu.tessellator.GLUmesh mesh = new jogamp.opengl.glu.tessellator.GLUmesh();
v = mesh.vHead;
f = mesh.fHead;
@@ -609,13 +611,13 @@ class Mesh {
/* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
* both meshes, and returns the new mesh (the old meshes are destroyed).
*/
- static jogamp.opengl.glu.tessellator.GLUmesh __gl_meshUnion(jogamp.opengl.glu.tessellator.GLUmesh mesh1, jogamp.opengl.glu.tessellator.GLUmesh mesh2) {
- jogamp.opengl.glu.tessellator.GLUface f1 = mesh1.fHead;
- jogamp.opengl.glu.tessellator.GLUvertex v1 = mesh1.vHead;
- jogamp.opengl.glu.tessellator.GLUhalfEdge e1 = mesh1.eHead;
- jogamp.opengl.glu.tessellator.GLUface f2 = mesh2.fHead;
- jogamp.opengl.glu.tessellator.GLUvertex v2 = mesh2.vHead;
- jogamp.opengl.glu.tessellator.GLUhalfEdge e2 = mesh2.eHead;
+ static jogamp.opengl.glu.tessellator.GLUmesh __gl_meshUnion(final jogamp.opengl.glu.tessellator.GLUmesh mesh1, final jogamp.opengl.glu.tessellator.GLUmesh mesh2) {
+ final jogamp.opengl.glu.tessellator.GLUface f1 = mesh1.fHead;
+ final jogamp.opengl.glu.tessellator.GLUvertex v1 = mesh1.vHead;
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge e1 = mesh1.eHead;
+ final jogamp.opengl.glu.tessellator.GLUface f2 = mesh2.fHead;
+ final jogamp.opengl.glu.tessellator.GLUvertex v2 = mesh2.vHead;
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge e2 = mesh2.eHead;
/* Add the faces, vertices, and edges of mesh2 to those of mesh1 */
if (f2.next != f2) {
@@ -645,8 +647,8 @@ class Mesh {
/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
*/
- static void __gl_meshDeleteMeshZap(jogamp.opengl.glu.tessellator.GLUmesh mesh) {
- jogamp.opengl.glu.tessellator.GLUface fHead = mesh.fHead;
+ static void __gl_meshDeleteMeshZap(final jogamp.opengl.glu.tessellator.GLUmesh mesh) {
+ final jogamp.opengl.glu.tessellator.GLUface fHead = mesh.fHead;
while (fHead.next != fHead) {
__gl_meshZapFace(fHead.next);
@@ -656,7 +658,7 @@ class Mesh {
/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
*/
- public static void __gl_meshDeleteMesh(jogamp.opengl.glu.tessellator.GLUmesh mesh) {
+ public static void __gl_meshDeleteMesh(final jogamp.opengl.glu.tessellator.GLUmesh mesh) {
jogamp.opengl.glu.tessellator.GLUface f, fNext;
jogamp.opengl.glu.tessellator.GLUvertex v, vNext;
jogamp.opengl.glu.tessellator.GLUhalfEdge e, eNext;
@@ -677,10 +679,10 @@ class Mesh {
/* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
*/
- public static void __gl_meshCheckMesh(jogamp.opengl.glu.tessellator.GLUmesh mesh) {
- jogamp.opengl.glu.tessellator.GLUface fHead = mesh.fHead;
- jogamp.opengl.glu.tessellator.GLUvertex vHead = mesh.vHead;
- jogamp.opengl.glu.tessellator.GLUhalfEdge eHead = mesh.eHead;
+ public static void __gl_meshCheckMesh(final jogamp.opengl.glu.tessellator.GLUmesh mesh) {
+ final jogamp.opengl.glu.tessellator.GLUface fHead = mesh.fHead;
+ final jogamp.opengl.glu.tessellator.GLUvertex vHead = mesh.vHead;
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge eHead = mesh.eHead;
jogamp.opengl.glu.tessellator.GLUface f, fPrev;
jogamp.opengl.glu.tessellator.GLUvertex v, vPrev;
jogamp.opengl.glu.tessellator.GLUhalfEdge e, ePrev;
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/Normal.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/Normal.java
index 196e6cf27..44668a943 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/Normal.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/Normal.java
@@ -83,11 +83,11 @@ class Normal {
}
}
- private static double Dot(double[] u, double[] v) {
+ private static double Dot(final double[] u, final double[] v) {
return (u[0] * v[0] + u[1] * v[1] + u[2] * v[2]);
}
- static void Normalize(double[] v) {
+ static void Normalize(final double[] v) {
double len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
assert (len > 0);
@@ -97,7 +97,7 @@ class Normal {
v[2] /= len;
}
- static int LongAxis(double[] v) {
+ static int LongAxis(final double[] v) {
int i = 0;
if (Math.abs(v[1]) > Math.abs(v[0])) {
@@ -109,12 +109,12 @@ class Normal {
return i;
}
- static void ComputeNormal(GLUtessellatorImpl tess, double[] norm) {
+ static void ComputeNormal(final GLUtessellatorImpl tess, final double[] norm) {
jogamp.opengl.glu.tessellator.GLUvertex v, v1, v2;
double c, tLen2, maxLen2;
double[] maxVal, minVal, d1, d2, tNorm;
jogamp.opengl.glu.tessellator.GLUvertex[] maxVert, minVert;
- jogamp.opengl.glu.tessellator.GLUvertex vHead = tess.mesh.vHead;
+ final jogamp.opengl.glu.tessellator.GLUvertex vHead = tess.mesh.vHead;
int i;
maxVal = new double[3];
@@ -192,10 +192,12 @@ class Normal {
}
}
- static void CheckOrientation(GLUtessellatorImpl tess) {
+ static void CheckOrientation(final GLUtessellatorImpl tess) {
double area;
- jogamp.opengl.glu.tessellator.GLUface f, fHead = tess.mesh.fHead;
- jogamp.opengl.glu.tessellator.GLUvertex v, vHead = tess.mesh.vHead;
+ jogamp.opengl.glu.tessellator.GLUface f;
+ final jogamp.opengl.glu.tessellator.GLUface fHead = tess.mesh.fHead;
+ jogamp.opengl.glu.tessellator.GLUvertex v;
+ final jogamp.opengl.glu.tessellator.GLUvertex vHead = tess.mesh.vHead;
jogamp.opengl.glu.tessellator.GLUhalfEdge e;
/* When we compute the normal automatically, we choose the orientation
@@ -224,10 +226,11 @@ class Normal {
/* Determine the polygon normal and project vertices onto the plane
* of the polygon.
*/
- public static void __gl_projectPolygon(GLUtessellatorImpl tess) {
- jogamp.opengl.glu.tessellator.GLUvertex v, vHead = tess.mesh.vHead;
+ public static void __gl_projectPolygon(final GLUtessellatorImpl tess) {
+ jogamp.opengl.glu.tessellator.GLUvertex v;
+ final jogamp.opengl.glu.tessellator.GLUvertex vHead = tess.mesh.vHead;
double w;
- double[] norm = new double[3];
+ final double[] norm = new double[3];
double[] sUnit, tUnit;
int i;
boolean computedNormal = false;
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQ.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQ.java
index 25405ad64..1f9b9e5ed 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQ.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQ.java
@@ -75,11 +75,11 @@ abstract class PriorityQ {
// #else
/* Violates modularity, but a little faster */
// #include "geom.h"
- public static boolean LEQ(Leq leq, Object x, Object y) {
+ public static boolean LEQ(final Leq leq, final Object x, final Object y) {
return jogamp.opengl.glu.tessellator.Geom.VertLeq((jogamp.opengl.glu.tessellator.GLUvertex) x, (jogamp.opengl.glu.tessellator.GLUvertex) y);
}
- static PriorityQ pqNewPriorityQ(Leq leq) {
+ static PriorityQ pqNewPriorityQ(final Leq leq) {
return new PriorityQSort(leq);
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQHeap.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQHeap.java
index 474056cc3..fa29db8dc 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQHeap.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQHeap.java
@@ -61,7 +61,7 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
jogamp.opengl.glu.tessellator.PriorityQ.Leq leq;
/* really __gl_pqHeapNewPriorityQ */
- public PriorityQHeap(jogamp.opengl.glu.tessellator.PriorityQ.Leq leq) {
+ public PriorityQHeap(final jogamp.opengl.glu.tessellator.PriorityQ.Leq leq) {
size = 0;
max = jogamp.opengl.glu.tessellator.PriorityQ.INIT_SIZE;
nodes = new jogamp.opengl.glu.tessellator.PriorityQ.PQnode[jogamp.opengl.glu.tessellator.PriorityQ.INIT_SIZE + 1];
@@ -81,14 +81,15 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqHeapDeletePriorityQ */
+ @Override
void pqDeletePriorityQ() {
handles = null;
nodes = null;
}
void FloatDown(int curr) {
- jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] n = nodes;
- jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles;
+ final jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] n = nodes;
+ final jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles;
int hCurr, hChild;
int child;
@@ -116,8 +117,8 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
void FloatUp(int curr) {
- jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] n = nodes;
- jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles;
+ final jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] n = nodes;
+ final jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles;
int hCurr, hParent;
int parent;
@@ -137,6 +138,7 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqHeapInit */
+ @Override
boolean pqInit() {
int i;
@@ -152,40 +154,43 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
/* really __gl_pqHeapInsert */
/* returns LONG_MAX iff out of memory */
- int pqInsert(Object keyNew) {
+ @Override
+ int pqInsert(final Object keyNew) {
int curr;
int free;
curr = ++size;
if ((curr * 2) > max) {
- jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] saveNodes = nodes;
- jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] saveHandles = handles;
+ final jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] saveNodes = nodes;
+ final jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] saveHandles = handles;
/* If the heap overflows, double its size. */
max <<= 1;
// pq->nodes = (PQnode *)memRealloc( pq->nodes, (size_t) ((pq->max + 1) * sizeof( pq->nodes[0] )));
- PriorityQ.PQnode[] pqNodes = new PriorityQ.PQnode[max + 1];
+ final PriorityQ.PQnode[] pqNodes = new PriorityQ.PQnode[max + 1];
System.arraycopy( nodes, 0, pqNodes, 0, nodes.length );
for (int i = nodes.length; i < pqNodes.length; i++) {
pqNodes[i] = new PQnode();
}
nodes = pqNodes;
+ /** Cannot be null
if (nodes == null) {
- nodes = saveNodes; /* restore ptr to free upon return */
+ nodes = saveNodes; // restore ptr to free upon return
return Integer.MAX_VALUE;
- }
+ } */
// pq->handles = (PQhandleElem *)memRealloc( pq->handles,(size_t)((pq->max + 1) * sizeof( pq->handles[0] )));
- PriorityQ.PQhandleElem[] pqHandles = new PriorityQ.PQhandleElem[max + 1];
+ final PriorityQ.PQhandleElem[] pqHandles = new PriorityQ.PQhandleElem[max + 1];
System.arraycopy( handles, 0, pqHandles, 0, handles.length );
for (int i = handles.length; i < pqHandles.length; i++) {
pqHandles[i] = new PQhandleElem();
}
handles = pqHandles;
+ /** cannot be null
if (handles == null) {
- handles = saveHandles; /* restore ptr to free upon return */
+ handles = saveHandles; // restore ptr to free upon return
return Integer.MAX_VALUE;
- }
+ } */
}
if (freeList == 0) {
@@ -207,11 +212,12 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqHeapExtractMin */
+ @Override
Object pqExtractMin() {
- jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] n = nodes;
- jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles;
- int hMin = n[1].handle;
- Object min = h[hMin].key;
+ final jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] n = nodes;
+ final jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles;
+ final int hMin = n[1].handle;
+ final Object min = h[hMin].key;
if (size > 0) {
n[1].handle = n[size].handle;
@@ -229,9 +235,10 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqHeapDelete */
- void pqDelete(int hCurr) {
- jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] n = nodes;
- jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles;
+ @Override
+ void pqDelete(final int hCurr) {
+ final jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] n = nodes;
+ final jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles;
int curr;
assert (hCurr >= 1 && hCurr <= max && h[hCurr].key != null);
@@ -252,10 +259,12 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
freeList = hCurr;
}
+ @Override
Object pqMinimum() {
return handles[nodes[1].handle].key;
}
+ @Override
boolean pqIsEmpty() {
return size == 0;
}
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQSort.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQSort.java
index f9e0225e3..d88f584cf 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQSort.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQSort.java
@@ -59,7 +59,7 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
boolean initialized;
jogamp.opengl.glu.tessellator.PriorityQ.Leq leq;
- public PriorityQSort(jogamp.opengl.glu.tessellator.PriorityQ.Leq leq) {
+ public PriorityQSort(final jogamp.opengl.glu.tessellator.PriorityQ.Leq leq) {
heap = new jogamp.opengl.glu.tessellator.PriorityQHeap(leq);
keys = new Object[jogamp.opengl.glu.tessellator.PriorityQ.INIT_SIZE];
@@ -71,23 +71,24 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqSortDeletePriorityQ */
+ @Override
void pqDeletePriorityQ() {
if (heap != null) heap.pqDeletePriorityQ();
order = null;
keys = null;
}
- private static boolean LT(jogamp.opengl.glu.tessellator.PriorityQ.Leq leq, Object x, Object y) {
- return (!jogamp.opengl.glu.tessellator.PriorityQHeap.LEQ(leq, y, x));
+ private static boolean LT(final jogamp.opengl.glu.tessellator.PriorityQ.Leq leq, final Object x, final Object y) {
+ return (!PriorityQ.LEQ(leq, y, x));
}
- private static boolean GT(jogamp.opengl.glu.tessellator.PriorityQ.Leq leq, Object x, Object y) {
- return (!jogamp.opengl.glu.tessellator.PriorityQHeap.LEQ(leq, x, y));
+ private static boolean GT(final jogamp.opengl.glu.tessellator.PriorityQ.Leq leq, final Object x, final Object y) {
+ return (!PriorityQ.LEQ(leq, x, y));
}
- private static void Swap(int[] array, int a, int b) {
+ private static void Swap(final int[] array, final int a, final int b) {
if (true) {
- int tmp = array[a];
+ final int tmp = array[a];
array[a] = array[b];
array[b] = tmp;
} else {
@@ -100,10 +101,11 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqSortInit */
+ @Override
boolean pqInit() {
int p, r, i, j;
int piv;
- Stack[] stack = new Stack[50];
+ final Stack[] stack = new Stack[50];
for (int k = 0; k < stack.length; k++) {
stack[k] = new Stack();
}
@@ -191,7 +193,8 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
/* really __gl_pqSortInsert */
/* returns LONG_MAX iff out of memory */
- int pqInsert(Object keyNew) {
+ @Override
+ int pqInsert(final Object keyNew) {
int curr;
if (initialized) {
@@ -199,18 +202,19 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
}
curr = size;
if (++size >= max) {
- Object[] saveKey = keys;
+ // final Object[] saveKey = keys;
/* If the heap overflows, double its size. */
max <<= 1;
// pq->keys = (PQHeapKey *)memRealloc( pq->keys,(size_t)(pq->max * sizeof( pq->keys[0] )));
- Object[] pqKeys = new Object[max];
+ final Object[] pqKeys = new Object[max];
System.arraycopy( keys, 0, pqKeys, 0, keys.length );
keys = pqKeys;
+ /** Cannot be null
if (keys == null) {
- keys = saveKey; /* restore ptr to free upon return */
+ keys = saveKey; // restore ptr to free upon return
return Integer.MAX_VALUE;
- }
+ } */
}
assert curr != Integer.MAX_VALUE;
keys[curr] = keyNew;
@@ -220,6 +224,7 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqSortExtractMin */
+ @Override
Object pqExtractMin() {
Object sortMin, heapMin;
@@ -240,6 +245,7 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqSortMinimum */
+ @Override
Object pqMinimum() {
Object sortMin, heapMin;
@@ -249,7 +255,7 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
sortMin = keys[order[size - 1]];
if (!heap.pqIsEmpty()) {
heapMin = heap.pqMinimum();
- if (jogamp.opengl.glu.tessellator.PriorityQHeap.LEQ(leq, heapMin, sortMin)) {
+ if (PriorityQ.LEQ(leq, heapMin, sortMin)) {
return heapMin;
}
}
@@ -257,11 +263,13 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqSortIsEmpty */
+ @Override
boolean pqIsEmpty() {
return (size == 0) && heap.pqIsEmpty();
}
/* really __gl_pqSortDelete */
+ @Override
void pqDelete(int curr) {
if (curr >= 0) {
heap.pqDelete(curr);
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/Render.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/Render.java
index 1801e1c59..6325de8d2 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/Render.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/Render.java
@@ -73,7 +73,7 @@ class Render {
public FaceCount() {
}
- public FaceCount(long size, jogamp.opengl.glu.tessellator.GLUhalfEdge eStart, renderCallBack render) {
+ public FaceCount(final long size, final jogamp.opengl.glu.tessellator.GLUhalfEdge eStart, final renderCallBack render) {
this.size = size;
this.eStart = eStart;
this.render = render;
@@ -97,7 +97,7 @@ class Render {
*
* The rendering output is provided as callbacks (see the api).
*/
- public static void __gl_renderMesh(GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUmesh mesh) {
+ public static void __gl_renderMesh(final GLUtessellatorImpl tess, final jogamp.opengl.glu.tessellator.GLUmesh mesh) {
jogamp.opengl.glu.tessellator.GLUface f;
/* Make a list of separate triangles so we can render them all at once */
@@ -124,7 +124,7 @@ class Render {
}
- static void RenderMaximumFaceGroup(GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUface fOrig) {
+ static void RenderMaximumFaceGroup(final GLUtessellatorImpl tess, final jogamp.opengl.glu.tessellator.GLUface fOrig) {
/* We want to find the largest triangle fan or strip of unmarked faces
* which includes the given face fOrig. There are 3 possible fans
* passing through fOrig (one centered at each vertex), and 3 possible
@@ -132,7 +132,7 @@ class Render {
* is to try all of these, and take the primitive which uses the most
* triangles (a greedy approach).
*/
- jogamp.opengl.glu.tessellator.GLUhalfEdge e = fOrig.anEdge;
+ final jogamp.opengl.glu.tessellator.GLUhalfEdge e = fOrig.anEdge;
FaceCount max = new FaceCount();
FaceCount newFace = new FaceCount();
@@ -178,11 +178,11 @@ class Render {
* more complicated, and we need a general tracking method like the
* one here.
*/
- private static boolean Marked(jogamp.opengl.glu.tessellator.GLUface f) {
+ private static boolean Marked(final jogamp.opengl.glu.tessellator.GLUface f) {
return !f.inside || f.marked;
}
- private static GLUface AddToTrail(jogamp.opengl.glu.tessellator.GLUface f, jogamp.opengl.glu.tessellator.GLUface t) {
+ private static GLUface AddToTrail(final jogamp.opengl.glu.tessellator.GLUface f, final jogamp.opengl.glu.tessellator.GLUface t) {
f.trail = t;
f.marked = true;
return f;
@@ -199,12 +199,12 @@ class Render {
}
}
- static FaceCount MaximumFan(jogamp.opengl.glu.tessellator.GLUhalfEdge eOrig) {
+ static FaceCount MaximumFan(final jogamp.opengl.glu.tessellator.GLUhalfEdge eOrig) {
/* eOrig.Lface is the face we want to render. We want to find the size
* of a maximal fan around eOrig.Org. To do this we just walk around
* the origin vertex as far as possible in both directions.
*/
- FaceCount newFace = new FaceCount(0, null, renderFan);
+ final FaceCount newFace = new FaceCount(0, null, renderFan);
jogamp.opengl.glu.tessellator.GLUface trail = null;
jogamp.opengl.glu.tessellator.GLUhalfEdge e;
@@ -223,11 +223,11 @@ class Render {
}
- private static boolean IsEven(long n) {
+ private static boolean IsEven(final long n) {
return (n & 0x1L) == 0;
}
- static FaceCount MaximumStrip(jogamp.opengl.glu.tessellator.GLUhalfEdge eOrig) {
+ static FaceCount MaximumStrip(final jogamp.opengl.glu.tessellator.GLUhalfEdge eOrig) {
/* Here we are looking for a maximal strip that contains the vertices
* eOrig.Org, eOrig.Dst, eOrig.Lnext.Dst (in that order or the
* reverse, such that all triangles are oriented CCW).
@@ -238,7 +238,7 @@ class Render {
* We walk the strip starting on a side with an even number of triangles;
* if both side have an odd number, we are forced to shorten one side.
*/
- FaceCount newFace = new FaceCount(0, null, renderStrip);
+ final FaceCount newFace = new FaceCount(0, null, renderStrip);
long headSize = 0, tailSize = 0;
jogamp.opengl.glu.tessellator.GLUface trail = null;
jogamp.opengl.glu.tessellator.GLUhalfEdge e, eTail, eHead;
@@ -279,7 +279,8 @@ class Render {
}
private static class RenderTriangle implements renderCallBack {
- public void render(GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUhalfEdge e, long size) {
+ @Override
+ public void render(final GLUtessellatorImpl tess, final jogamp.opengl.glu.tessellator.GLUhalfEdge e, final long size) {
/* Just add the triangle to a triangle list, so we can render all
* the separate triangles at once.
*/
@@ -289,7 +290,7 @@ class Render {
}
- static void RenderLonelyTriangles(GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUface f) {
+ static void RenderLonelyTriangles(final GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUface f) {
/* Now we render all the separate triangles which could not be
* grouped into a triangle fan or strip.
*/
@@ -323,7 +324,8 @@ class Render {
}
private static class RenderFan implements renderCallBack {
- public void render(GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUhalfEdge e, long size) {
+ @Override
+ public void render(final GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUhalfEdge e, long size) {
/* Render as many CCW triangles as possible in a fan starting from
* edge "e". The fan *should* contain exactly "size" triangles
* (otherwise we've goofed up somewhere).
@@ -345,7 +347,8 @@ class Render {
}
private static class RenderStrip implements renderCallBack {
- public void render(GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUhalfEdge e, long size) {
+ @Override
+ public void render(final GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUhalfEdge e, long size) {
/* Render as many CCW triangles as possible in a strip starting from
* edge "e". The strip *should* contain exactly "size" triangles
* (otherwise we've goofed up somewhere).
@@ -378,7 +381,7 @@ class Render {
* contour for each face marked "inside". The rendering output is
* provided as callbacks (see the api).
*/
- public static void __gl_renderBoundary(GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUmesh mesh) {
+ public static void __gl_renderBoundary(final GLUtessellatorImpl tess, final jogamp.opengl.glu.tessellator.GLUmesh mesh) {
jogamp.opengl.glu.tessellator.GLUface f;
jogamp.opengl.glu.tessellator.GLUhalfEdge e;
@@ -400,7 +403,7 @@ class Render {
private static final int SIGN_INCONSISTENT = 2;
- static int ComputeNormal(GLUtessellatorImpl tess, double[] norm, boolean check)
+ static int ComputeNormal(final GLUtessellatorImpl tess, final double[] norm, final boolean check)
/*
* If check==false, we compute the polygon normal and place it in norm[].
* If check==true, we check that each triangle in the fan from v0 has a
@@ -409,13 +412,13 @@ class Render {
* are degenerate return 0; otherwise (no consistent orientation) return
* SIGN_INCONSISTENT.
*/ {
- jogamp.opengl.glu.tessellator.CachedVertex[] v = tess.cache;
+ final jogamp.opengl.glu.tessellator.CachedVertex[] v = tess.cache;
// CachedVertex vn = v0 + tess.cacheCount;
- int vn = tess.cacheCount;
+ final int vn = tess.cacheCount;
// CachedVertex vc;
int vc;
double dot, xc, yc, zc, xp, yp, zp;
- double[] n = new double[3];
+ final double[] n = new double[3];
int sign = 0;
/* Find the polygon normal. It is important to get a reasonable
@@ -487,13 +490,13 @@ class Render {
* Returns true if the polygon was successfully rendered. The rendering
* output is provided as callbacks (see the api).
*/
- public static boolean __gl_renderCache(GLUtessellatorImpl tess) {
- jogamp.opengl.glu.tessellator.CachedVertex[] v = tess.cache;
+ public static boolean __gl_renderCache(final GLUtessellatorImpl tess) {
+ final jogamp.opengl.glu.tessellator.CachedVertex[] v = tess.cache;
// CachedVertex vn = v0 + tess.cacheCount;
- int vn = tess.cacheCount;
+ final int vn = tess.cacheCount;
// CachedVertex vc;
int vc;
- double[] norm = new double[3];
+ final double[] norm = new double[3];
int sign;
if (tess.cacheCount < 3) {
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/Sweep.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/Sweep.java
index b4a400c1c..b6c60058f 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/Sweep.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/Sweep.java
@@ -62,7 +62,7 @@ class Sweep {
// #ifdef FOR_TRITE_TEST_PROGRAM
// extern void DebugEvent( GLUtessellator *tess );
// #else
- private static void DebugEvent(GLUtessellatorImpl tess) {
+ private static void DebugEvent(final GLUtessellatorImpl tess) {
}
// #endif
@@ -100,21 +100,21 @@ class Sweep {
/* When we merge two edges into one, we need to compute the combined
* winding of the new edge.
*/
- private static void AddWinding(GLUhalfEdge eDst, GLUhalfEdge eSrc) {
+ private static void AddWinding(final GLUhalfEdge eDst, final GLUhalfEdge eSrc) {
eDst.winding += eSrc.winding;
eDst.Sym.winding += eSrc.Sym.winding;
}
- private static ActiveRegion RegionBelow(ActiveRegion r) {
+ private static ActiveRegion RegionBelow(final ActiveRegion r) {
return ((ActiveRegion) Dict.dictKey(Dict.dictPred(r.nodeUp)));
}
- private static ActiveRegion RegionAbove(ActiveRegion r) {
+ private static ActiveRegion RegionAbove(final ActiveRegion r) {
return ((ActiveRegion) Dict.dictKey(Dict.dictSucc(r.nodeUp)));
}
- static boolean EdgeLeq(GLUtessellatorImpl tess, ActiveRegion reg1, ActiveRegion reg2)
+ static boolean EdgeLeq(final GLUtessellatorImpl tess, final ActiveRegion reg1, final ActiveRegion reg2)
/*
* Both edges must be directed from right to left (this is the canonical
* direction for the upper edge of each region).
@@ -126,7 +126,7 @@ class Sweep {
* Special case: if both edge destinations are at the sweep event,
* we sort the edges by slope (they would otherwise compare equally).
*/ {
- GLUvertex event = tess.event;
+ final GLUvertex event = tess.event;
GLUhalfEdge e1, e2;
double t1, t2;
@@ -156,7 +156,7 @@ class Sweep {
}
- static void DeleteRegion(GLUtessellatorImpl tess, ActiveRegion reg) {
+ static void DeleteRegion(final GLUtessellatorImpl tess, final ActiveRegion reg) {
if (reg.fixUpperEdge) {
/* It was created with zero winding number, so it better be
* deleted with zero winding number (ie. it better not get merged
@@ -169,7 +169,7 @@ class Sweep {
}
- static boolean FixUpperEdge(ActiveRegion reg, GLUhalfEdge newEdge)
+ static boolean FixUpperEdge(final ActiveRegion reg, final GLUhalfEdge newEdge)
/*
* Replace an upper edge which needs fixing (see ConnectRightVertex).
*/ {
@@ -183,7 +183,7 @@ class Sweep {
}
static ActiveRegion TopLeftRegion(ActiveRegion reg) {
- GLUvertex org = reg.eUp.Org;
+ final GLUvertex org = reg.eUp.Org;
GLUhalfEdge e;
/* Find the region above the uppermost edge with the same origin */
@@ -204,7 +204,7 @@ class Sweep {
}
static ActiveRegion TopRightRegion(ActiveRegion reg) {
- GLUvertex dst = reg.eUp.Sym.Org;
+ final GLUvertex dst = reg.eUp.Sym.Org;
/* Find the region above the uppermost edge with the same destination */
do {
@@ -213,16 +213,16 @@ class Sweep {
return reg;
}
- static ActiveRegion AddRegionBelow(GLUtessellatorImpl tess,
- ActiveRegion regAbove,
- GLUhalfEdge eNewUp)
+ static ActiveRegion AddRegionBelow(final GLUtessellatorImpl tess,
+ final ActiveRegion regAbove,
+ final GLUhalfEdge eNewUp)
/*
* Add a new active region to the sweep line, *somewhere* below "regAbove"
* (according to where the new edge belongs in the sweep-line dictionary).
* The upper edge of the new region will be "eNewUp".
* Winding number and "inside" flag are not updated.
*/ {
- ActiveRegion regNew = new ActiveRegion();
+ final ActiveRegion regNew = new ActiveRegion();
if (regNew == null) throw new RuntimeException();
regNew.eUp = eNewUp;
@@ -237,7 +237,7 @@ class Sweep {
return regNew;
}
- static boolean IsWindingInside(GLUtessellatorImpl tess, int n) {
+ static boolean IsWindingInside(final GLUtessellatorImpl tess, final int n) {
switch (tess.windingRule) {
case GLU.GLU_TESS_WINDING_ODD:
return (n & 1) != 0;
@@ -257,13 +257,13 @@ class Sweep {
}
- static void ComputeWinding(GLUtessellatorImpl tess, ActiveRegion reg) {
+ static void ComputeWinding(final GLUtessellatorImpl tess, final ActiveRegion reg) {
reg.windingNumber = RegionAbove(reg).windingNumber + reg.eUp.winding;
reg.inside = IsWindingInside(tess, reg.windingNumber);
}
- static void FinishRegion(GLUtessellatorImpl tess, ActiveRegion reg)
+ static void FinishRegion(final GLUtessellatorImpl tess, final ActiveRegion reg)
/*
* Delete a region from the sweep line. This happens when the upper
* and lower chains of a region meet (at a vertex on the sweep line).
@@ -271,8 +271,8 @@ class Sweep {
* not do this before -- since the structure of the mesh is always
* changing, this face may not have even existed until now).
*/ {
- GLUhalfEdge e = reg.eUp;
- GLUface f = e.Lface;
+ final GLUhalfEdge e = reg.eUp;
+ final GLUface f = e.Lface;
f.inside = reg.inside;
f.anEdge = e; /* optimization for __gl_meshTessellateMonoRegion() */
@@ -280,8 +280,8 @@ class Sweep {
}
- static GLUhalfEdge FinishLeftRegions(GLUtessellatorImpl tess,
- ActiveRegion regFirst, ActiveRegion regLast)
+ static GLUhalfEdge FinishLeftRegions(final GLUtessellatorImpl tess,
+ final ActiveRegion regFirst, final ActiveRegion regLast)
/*
* We are given a vertex with one or more left-going edges. All affected
* edges should be in the edge dictionary. Starting at regFirst.eUp,
@@ -335,9 +335,9 @@ class Sweep {
}
- static void AddRightEdges(GLUtessellatorImpl tess, ActiveRegion regUp,
- GLUhalfEdge eFirst, GLUhalfEdge eLast, GLUhalfEdge eTopLeft,
- boolean cleanUp)
+ static void AddRightEdges(final GLUtessellatorImpl tess, final ActiveRegion regUp,
+ final GLUhalfEdge eFirst, final GLUhalfEdge eLast, GLUhalfEdge eTopLeft,
+ final boolean cleanUp)
/*
* Purpose: insert right-going edges into the edge dictionary, and update
* winding numbers and mesh connectivity appropriately. All right-going
@@ -406,16 +406,16 @@ class Sweep {
}
- static void CallCombine(GLUtessellatorImpl tess, GLUvertex isect,
- Object[] data, float[] weights, boolean needed) {
- double[] coords = new double[3];
+ static void CallCombine(final GLUtessellatorImpl tess, final GLUvertex isect,
+ final Object[] data, final float[] weights, final boolean needed) {
+ final double[] coords = new double[3];
/* Copy coord data in case the callback changes it. */
coords[0] = isect.coords[0];
coords[1] = isect.coords[1];
coords[2] = isect.coords[2];
- Object[] outData = new Object[1];
+ final Object[] outData = new Object[1];
tess.callCombineOrCombineData(coords, data, weights, outData);
isect.data = outData[0];
if (isect.data == null) {
@@ -432,14 +432,14 @@ class Sweep {
}
}
- static void SpliceMergeVertices(GLUtessellatorImpl tess, GLUhalfEdge e1,
- GLUhalfEdge e2)
+ static void SpliceMergeVertices(final GLUtessellatorImpl tess, final GLUhalfEdge e1,
+ final GLUhalfEdge e2)
/*
* Two vertices with idential coordinates are combined into one.
* e1.Org is kept, while e2.Org is discarded.
*/ {
- Object[] data = new Object[4];
- float[] weights = new float[]{0.5f, 0.5f, 0.0f, 0.0f};
+ final Object[] data = new Object[4];
+ final float[] weights = new float[]{0.5f, 0.5f, 0.0f, 0.0f};
data[0] = e1.Org.data;
data[1] = e2.Org.data;
@@ -447,8 +447,8 @@ class Sweep {
if (!Mesh.__gl_meshSplice(e1, e2)) throw new RuntimeException();
}
- static void VertexWeights(GLUvertex isect, GLUvertex org, GLUvertex dst,
- float[] weights)
+ static void VertexWeights(final GLUvertex isect, final GLUvertex org, final GLUvertex dst,
+ final float[] weights)
/*
* Find some weights which describe how the intersection vertex is
* a linear combination of "org" and "dest". Each of the two edges
@@ -456,8 +456,8 @@ class Sweep {
* splits the weight between its org and dst according to the
* relative distance to "isect".
*/ {
- double t1 = Geom.VertL1dist(org, isect);
- double t2 = Geom.VertL1dist(dst, isect);
+ final double t1 = Geom.VertL1dist(org, isect);
+ final double t2 = Geom.VertL1dist(dst, isect);
weights[0] = (float) (0.5 * t2 / (t1 + t2));
weights[1] = (float) (0.5 * t1 / (t1 + t2));
@@ -467,18 +467,18 @@ class Sweep {
}
- static void GetIntersectData(GLUtessellatorImpl tess, GLUvertex isect,
- GLUvertex orgUp, GLUvertex dstUp,
- GLUvertex orgLo, GLUvertex dstLo)
+ static void GetIntersectData(final GLUtessellatorImpl tess, final GLUvertex isect,
+ final GLUvertex orgUp, final GLUvertex dstUp,
+ final GLUvertex orgLo, final GLUvertex dstLo)
/*
* We've computed a new intersection point, now we need a "data" pointer
* from the user so that we can refer to this new vertex in the
* rendering callbacks.
*/ {
- Object[] data = new Object[4];
- float[] weights = new float[4];
- float[] weights1 = new float[2];
- float[] weights2 = new float[2];
+ final Object[] data = new Object[4];
+ final float[] weights = new float[4];
+ final float[] weights1 = new float[2];
+ final float[] weights2 = new float[2];
data[0] = orgUp.data;
data[1] = dstUp.data;
@@ -494,7 +494,7 @@ class Sweep {
CallCombine(tess, isect, data, weights, true);
}
- static boolean CheckForRightSplice(GLUtessellatorImpl tess, ActiveRegion regUp)
+ static boolean CheckForRightSplice(final GLUtessellatorImpl tess, final ActiveRegion regUp)
/*
* Check the upper and lower edge of "regUp", to make sure that the
* eUp.Org is above eLo, or eLo.Org is below eUp (depending on which
@@ -520,9 +520,9 @@ class Sweep {
* This is a guaranteed solution, no matter how degenerate things get.
* Basically this is a combinatorial solution to a numerical problem.
*/ {
- ActiveRegion regLo = RegionBelow(regUp);
- GLUhalfEdge eUp = regUp.eUp;
- GLUhalfEdge eLo = regLo.eUp;
+ final ActiveRegion regLo = RegionBelow(regUp);
+ final GLUhalfEdge eUp = regUp.eUp;
+ final GLUhalfEdge eLo = regLo.eUp;
if (Geom.VertLeq(eUp.Org, eLo.Org)) {
if (Geom.EdgeSign(eLo.Sym.Org, eUp.Org, eLo.Org) > 0) return false;
@@ -550,7 +550,7 @@ class Sweep {
return true;
}
- static boolean CheckForLeftSplice(GLUtessellatorImpl tess, ActiveRegion regUp)
+ static boolean CheckForLeftSplice(final GLUtessellatorImpl tess, final ActiveRegion regUp)
/*
* Check the upper and lower edge of "regUp", to make sure that the
* eUp.Sym.Org is above eLo, or eLo.Sym.Org is below eUp (depending on which
@@ -569,9 +569,9 @@ class Sweep {
* We fix the problem by just splicing the offending vertex into the
* other edge.
*/ {
- ActiveRegion regLo = RegionBelow(regUp);
- GLUhalfEdge eUp = regUp.eUp;
- GLUhalfEdge eLo = regLo.eUp;
+ final ActiveRegion regLo = RegionBelow(regUp);
+ final GLUhalfEdge eUp = regUp.eUp;
+ final GLUhalfEdge eLo = regLo.eUp;
GLUhalfEdge e;
assert (!Geom.VertEq(eUp.Sym.Org, eLo.Sym.Org));
@@ -599,7 +599,7 @@ class Sweep {
}
- static boolean CheckForIntersect(GLUtessellatorImpl tess, ActiveRegion regUp)
+ static boolean CheckForIntersect(final GLUtessellatorImpl tess, ActiveRegion regUp)
/*
* Check the upper and lower edges of the given region to see if
* they intersect. If so, create the intersection and add it
@@ -612,12 +612,12 @@ class Sweep {
ActiveRegion regLo = RegionBelow(regUp);
GLUhalfEdge eUp = regUp.eUp;
GLUhalfEdge eLo = regLo.eUp;
- GLUvertex orgUp = eUp.Org;
- GLUvertex orgLo = eLo.Org;
- GLUvertex dstUp = eUp.Sym.Org;
- GLUvertex dstLo = eLo.Sym.Org;
+ final GLUvertex orgUp = eUp.Org;
+ final GLUvertex orgLo = eLo.Org;
+ final GLUvertex dstUp = eUp.Sym.Org;
+ final GLUvertex dstLo = eLo.Sym.Org;
double tMinUp, tMaxLo;
- GLUvertex isect = new GLUvertex();
+ final GLUvertex isect = new GLUvertex();
GLUvertex orgMin;
GLUhalfEdge e;
@@ -742,7 +742,7 @@ class Sweep {
eUp.Org.s = isect.s;
eUp.Org.t = isect.t;
eUp.Org.pqHandle = tess.pq.pqInsert(eUp.Org); /* __gl_pqSortInsert */
- if (eUp.Org.pqHandle == Long.MAX_VALUE) {
+ if (eUp.Org.pqHandle == Integer.MAX_VALUE) {
tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */
tess.pq = null;
throw new RuntimeException();
@@ -752,7 +752,7 @@ class Sweep {
return false;
}
- static void WalkDirtyRegions(GLUtessellatorImpl tess, ActiveRegion regUp)
+ static void WalkDirtyRegions(final GLUtessellatorImpl tess, ActiveRegion regUp)
/*
* When the upper or lower edge of any region changes, the region is
* marked "dirty". This routine walks through all the dirty regions
@@ -837,7 +837,7 @@ class Sweep {
}
- static void ConnectRightVertex(GLUtessellatorImpl tess, ActiveRegion regUp,
+ static void ConnectRightVertex(final GLUtessellatorImpl tess, ActiveRegion regUp,
GLUhalfEdge eBottomLeft)
/*
* Purpose: connect a "right" vertex vEvent (one where all edges go left)
@@ -872,9 +872,9 @@ class Sweep {
*/ {
GLUhalfEdge eNew;
GLUhalfEdge eTopLeft = eBottomLeft.Onext;
- ActiveRegion regLo = RegionBelow(regUp);
- GLUhalfEdge eUp = regUp.eUp;
- GLUhalfEdge eLo = regLo.eUp;
+ final ActiveRegion regLo = RegionBelow(regUp);
+ final GLUhalfEdge eUp = regUp.eUp;
+ final GLUhalfEdge eLo = regLo.eUp;
boolean degenerate = false;
if (eUp.Sym.Org != eLo.Sym.Org) {
@@ -930,8 +930,8 @@ class Sweep {
*/
private static final boolean TOLERANCE_NONZERO = false;
- static void ConnectLeftDegenerate(GLUtessellatorImpl tess,
- ActiveRegion regUp, GLUvertex vEvent)
+ static void ConnectLeftDegenerate(final GLUtessellatorImpl tess,
+ ActiveRegion regUp, final GLUvertex vEvent)
/*
* The event vertex lies exacty on an already-processed edge or vertex.
* Adding the new vertex involves splicing it into the already-processed
@@ -989,7 +989,7 @@ class Sweep {
}
- static void ConnectLeftVertex(GLUtessellatorImpl tess, GLUvertex vEvent)
+ static void ConnectLeftVertex(final GLUtessellatorImpl tess, final GLUvertex vEvent)
/*
* Purpose: connect a "left" vertex (one where both edges go right)
* to the processed portion of the mesh. Let R be the active region
@@ -1007,7 +1007,7 @@ class Sweep {
*/ {
ActiveRegion regUp, regLo, reg;
GLUhalfEdge eUp, eLo, eNew;
- ActiveRegion tmp = new ActiveRegion();
+ final ActiveRegion tmp = new ActiveRegion();
/* assert ( vEvent.anEdge.Onext.Onext == vEvent.anEdge ); */
@@ -1035,7 +1035,7 @@ class Sweep {
eNew = Mesh.__gl_meshConnect(vEvent.anEdge.Sym, eUp.Lnext);
if (eNew == null) throw new RuntimeException();
} else {
- GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(eLo.Sym.Onext.Sym, vEvent.anEdge);
+ final GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(eLo.Sym.Onext.Sym, vEvent.anEdge);
if (tempHalfEdge == null) throw new RuntimeException();
eNew = tempHalfEdge.Sym;
@@ -1055,7 +1055,7 @@ class Sweep {
}
- static void SweepEvent(GLUtessellatorImpl tess, GLUvertex vEvent)
+ static void SweepEvent(final GLUtessellatorImpl tess, final GLUvertex vEvent)
/*
* Does everything necessary when the sweep line crosses a vertex.
* Updates the mesh and the edge dictionary.
@@ -1114,13 +1114,13 @@ class Sweep {
*/
private static final double SENTINEL_COORD = (4.0 * GLU.GLU_TESS_MAX_COORD);
- static void AddSentinel(GLUtessellatorImpl tess, double t)
+ static void AddSentinel(final GLUtessellatorImpl tess, final double t)
/*
* We add two sentinel edges above and below all other edges,
* to avoid special cases at the top and bottom.
*/ {
GLUhalfEdge e;
- ActiveRegion reg = new ActiveRegion();
+ final ActiveRegion reg = new ActiveRegion();
if (reg == null) throw new RuntimeException();
e = Mesh.__gl_meshMakeEdge(tess.mesh);
@@ -1150,7 +1150,8 @@ class Sweep {
*/ {
/* __gl_dictListNewDict */
tess.dict = Dict.dictNewDict(tess, new Dict.DictLeq() {
- public boolean leq(Object frame, Object key1, Object key2) {
+ @Override
+ public boolean leq(final Object frame, final Object key1, final Object key2) {
return EdgeLeq(tess, (ActiveRegion) key1, (ActiveRegion) key2);
}
});
@@ -1161,7 +1162,7 @@ class Sweep {
}
- static void DoneEdgeDict(GLUtessellatorImpl tess) {
+ static void DoneEdgeDict(final GLUtessellatorImpl tess) {
ActiveRegion reg;
int fixedEdges = 0;
@@ -1184,12 +1185,12 @@ class Sweep {
}
- static void RemoveDegenerateEdges(GLUtessellatorImpl tess)
+ static void RemoveDegenerateEdges(final GLUtessellatorImpl tess)
/*
* Remove zero-length edges, and contours with fewer than 3 vertices.
*/ {
GLUhalfEdge e, eNext, eLnext;
- GLUhalfEdge eHead = tess.mesh.eHead;
+ final GLUhalfEdge eHead = tess.mesh.eHead;
/*LINTED*/
for (e = eHead.next; e != eHead; e = eNext) {
@@ -1221,7 +1222,7 @@ class Sweep {
}
}
- static boolean InitPriorityQ(GLUtessellatorImpl tess)
+ static boolean InitPriorityQ(final GLUtessellatorImpl tess)
/*
* Insert all vertices into the priority queue which determines the
* order in which vertices cross the sweep line.
@@ -1231,16 +1232,16 @@ class Sweep {
/* __gl_pqSortNewPriorityQ */
pq = tess.pq = PriorityQ.pqNewPriorityQ(new PriorityQ.Leq() {
- public boolean leq(Object key1, Object key2) {
+ @Override
+ public boolean leq(final Object key1, final Object key2) {
return Geom.VertLeq(((GLUvertex) key1), (GLUvertex) key2);
}
});
- if (pq == null) return false;
vHead = tess.mesh.vHead;
for (v = vHead.next; v != vHead; v = v.next) {
v.pqHandle = pq.pqInsert(v); /* __gl_pqSortInsert */
- if (v.pqHandle == Long.MAX_VALUE) break;
+ if (v.pqHandle == Integer.MAX_VALUE) break;
}
if (v != vHead || !pq.pqInit()) { /* __gl_pqSortInit */
tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */
@@ -1252,12 +1253,12 @@ class Sweep {
}
- static void DonePriorityQ(GLUtessellatorImpl tess) {
+ static void DonePriorityQ(final GLUtessellatorImpl tess) {
tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */
}
- static boolean RemoveDegenerateFaces(GLUmesh mesh)
+ static boolean RemoveDegenerateFaces(final GLUmesh mesh)
/*
* Delete any degenerate faces with only two edges. WalkDirtyRegions()
* will catch almost all of these, but it won't catch degenerate faces
@@ -1290,7 +1291,7 @@ class Sweep {
return true;
}
- public static boolean __gl_computeInterior(GLUtessellatorImpl tess)
+ public static boolean __gl_computeInterior(final GLUtessellatorImpl tess)
/*
* __gl_computeInterior( tess ) computes the planar arrangement specified
* by the given contours, and further subdivides this arrangement
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/TessMono.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/TessMono.java
index 5db543c80..63994ba82 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/TessMono.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/TessMono.java
@@ -80,7 +80,7 @@ class TessMono {
* to the fan is a simple orientation test. By making the fan as large
* as possible, we restore the invariant (check it yourself).
*/
- static boolean __gl_meshTessellateMonoRegion(GLUface face, boolean avoidDegenerateTris) {
+ static boolean __gl_meshTessellateMonoRegion(final GLUface face, final boolean avoidDegenerateTris) {
GLUhalfEdge up, lo;
/* All edges are oriented CCW around the boundary of the region.
@@ -135,7 +135,7 @@ class TessMono {
*/
while (lo.Lnext != up && (Geom.EdgeGoesLeft(lo.Lnext)
|| Geom.EdgeSign(lo.Org, lo.Sym.Org, lo.Lnext.Sym.Org) <= 0)) {
- GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo);
+ final GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo);
mustConnect = false;
if (tempHalfEdge == null) return false;
lo = tempHalfEdge.Sym;
@@ -145,7 +145,7 @@ class TessMono {
/* lo.Org is on the left. We can make CCW triangles from up.Sym.Org. */
while (lo.Lnext != up && (Geom.EdgeGoesRight(up.Onext.Sym)
|| Geom.EdgeSign(up.Sym.Org, up.Org, up.Onext.Sym.Org) >= 0)) {
- GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(up, up.Onext.Sym);
+ final GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(up, up.Onext.Sym);
mustConnect = false;
if (tempHalfEdge == null) return false;
up = tempHalfEdge.Sym;
@@ -159,7 +159,7 @@ class TessMono {
*/
assert (lo.Lnext != up);
while (lo.Lnext.Lnext != up) {
- GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo);
+ final GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo);
if (tempHalfEdge == null) return false;
lo = tempHalfEdge.Sym;
}
@@ -172,7 +172,7 @@ class TessMono {
* the mesh which is marked "inside" the polygon. Each such region
* must be monotone.
*/
- public static boolean __gl_meshTessellateInterior(GLUmesh mesh, boolean avoidDegenerateTris) {
+ public static boolean __gl_meshTessellateInterior(final GLUmesh mesh, final boolean avoidDegenerateTris) {
GLUface f, next;
/*LINTED*/
@@ -193,7 +193,7 @@ class TessMono {
* on NULL faces are not allowed, the main purpose is to clean up the
* mesh so that exterior loops are not represented in the data structure.
*/
- public static void __gl_meshDiscardExterior(GLUmesh mesh) {
+ public static void __gl_meshDiscardExterior(final GLUmesh mesh) {
GLUface f, next;
/*LINTED*/
@@ -216,7 +216,7 @@ class TessMono {
* If keepOnlyBoundary is TRUE, it also deletes all edges which do not
* separate an interior region from an exterior one.
*/
- public static boolean __gl_meshSetWindingNumber(GLUmesh mesh, int value, boolean keepOnlyBoundary) {
+ public static boolean __gl_meshSetWindingNumber(final GLUmesh mesh, final int value, final boolean keepOnlyBoundary) {
GLUhalfEdge e, eNext;
for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) {
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index e04955d87..cb691a7ab 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -41,6 +41,7 @@
package jogamp.opengl.macosx.cgl;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import java.util.Map;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
@@ -50,11 +51,15 @@ import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.ProxySurface;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL3ES3;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.opengl.GLContextImpl;
@@ -63,14 +68,19 @@ import jogamp.opengl.GLFBODrawableImpl;
import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
-import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
-public abstract class MacOSXCGLContext extends GLContextImpl
+public class MacOSXCGLContext extends GLContextImpl
{
// Abstract interface for implementation of this context (either
// NSOpenGL-based or CGL-based)
@@ -78,7 +88,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
boolean isNSContext();
long create(long share, int ctp, int major, int minor);
boolean destroy(long ctx);
- boolean contextRealized(boolean realized);
+ void associateDrawable(boolean bound);
boolean copyImpl(long src, int mask);
boolean makeCurrent(long ctx);
boolean release(long ctx);
@@ -89,47 +99,97 @@ public abstract class MacOSXCGLContext extends GLContextImpl
/* package */ static final boolean isTigerOrLater;
/* package */ static final boolean isLionOrLater;
+ /* package */ static final boolean isMavericksOrLater;
static {
final VersionNumber osvn = Platform.getOSVersionNumber();
- isTigerOrLater = osvn.getMajor() > 10 || ( osvn.getMajor() == 10 && osvn.getMinor() >= 4 );
- isLionOrLater = osvn.getMajor() > 10 || ( osvn.getMajor() == 10 && osvn.getMinor() >= 7 );
+ isTigerOrLater = osvn.compareTo(Platform.OSXVersion.Tiger) >= 0;
+ isLionOrLater = osvn.compareTo(Platform.OSXVersion.Lion) >= 0;
+ isMavericksOrLater = osvn.compareTo(Platform.OSXVersion.Mavericks) >= 0;
}
- static boolean isGLProfileSupported(int ctp, int major, int minor) {
- boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ;
- boolean ctCore = 0 != ( CTX_PROFILE_CORE & ctp ) ;
+ static boolean isGLProfileSupported(final int ctp, final int major, final int minor) {
+ final boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ;
+ final boolean ctCore = 0 != ( CTX_PROFILE_CORE & ctp ) ;
// We exclude 3.0, since we would map it's core to GL2. Hence we force mapping 2.1 to GL2
- if(3==major && 1<=minor && minor<=2) {
- // [3.1..3.2] -> GL3*
+ if( 3 < major || 3 == major && 1 <= minor ) {
+ if(ctBwdCompat || !ctCore) {
+ // No compatibility profile on OS X
+ // Only core is supported
+ return false;
+ }
if(!isLionOrLater) {
- // no GL3* on pre lion
+ // no GL Profile >= GL3 core on pre lion
return false;
}
- if(ctBwdCompat) {
- // no compatibility profile on OS X
+ if(3 < major && !isMavericksOrLater) {
+ // no GL Profile >= GL4 core on pre mavericks
return false;
}
- return ctCore;
- } else if(major<3) {
+ // [3.1..3.x] -> GL3
+ // [4.0..4.x] -> GL4
+ return true;
+ } else if( major < 3 ) {
// < 3.0 -> GL2
return true;
}
return false; // 3.0 && > 3.2
}
- static int GLProfile2CGLOGLProfileValue(int ctp, int major, int minor) {
+ static int GLProfile2CGLOGLProfileValue(final AbstractGraphicsDevice device, final int ctp, final int major, final int minor) {
if(!MacOSXCGLContext.isGLProfileSupported(ctp, major, minor)) {
throw new GLException("OpenGL profile not supported: "+getGLVersion(major, minor, ctp, "@GLProfile2CGLOGLProfileVersion"));
}
- boolean ctCore = 0 != ( CTX_PROFILE_CORE & ctp ) ;
- if( major == 3 && minor >= 1 && ctCore ) {
- return CGL.kCGLOGLPVersion_3_2_Core;
+ final boolean ctCore = 0 != ( CTX_PROFILE_CORE & ctp ) ;
+
+ if( major == 4 && ctCore ) {
+ if( GLRendererQuirks.existStickyDeviceQuirk(device, GLRendererQuirks.GL4NeedsGL3Request) ) {
+ // Thread safe GLRendererQuirks sticky access, since we are only interested of the result _after_ GL version mapping,
+ // i.e. after single threaded initialization!
+ return CGL.kCGLOGLPVersion_GL3_Core;
+ } else {
+ return CGL.kCGLOGLPVersion_GL4_Core;
+ }
+ } else if( major == 3 && minor >= 1 && ctCore ) {
+ return CGL.kCGLOGLPVersion_GL3_Core;
} else {
return CGL.kCGLOGLPVersion_Legacy;
}
}
+ private static final String shaderBasename = "texture01_xxx";
+
+ private static ShaderProgram createCALayerShader(final GL3ES3 gl) {
+ // Create & Link the shader program
+ final ShaderProgram sp = new ShaderProgram();
+ final ShaderCode vp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MacOSXCGLContext.class,
+ "../../shader", "../../shader/bin", shaderBasename, true);
+ final ShaderCode fp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MacOSXCGLContext.class,
+ "../../shader", "../../shader/bin", shaderBasename, true);
+ vp.defaultShaderCustomization(gl, true, true);
+ fp.defaultShaderCustomization(gl, true, true);
+ sp.add(vp);
+ sp.add(fp);
+ if(!sp.link(gl, System.err)) {
+ throw new GLException("Couldn't link program: "+sp);
+ }
+ sp.useProgram(gl, true);
+
+ // setup mgl_PMVMatrix
+ final PMVMatrix pmvMatrix = new PMVMatrix();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
+ pmvMatrixUniform.setLocation(gl, sp.program());
+ gl.glUniform(pmvMatrixUniform);
+
+ sp.useProgram(gl, false);
+ return sp;
+ }
+
+
private boolean haveSetOpenGLMode = false;
private GLBackendType openGLMode = GLBackendType.NSOPENGL;
@@ -141,17 +201,20 @@ public abstract class MacOSXCGLContext extends GLContextImpl
// CGL extension functions.
private CGLExtProcAddressTable cglExtProcAddressTable;
- protected MacOSXCGLContext(GLDrawableImpl drawable,
- GLContext shareWith) {
+ private long updateHandle = 0;
+ private int lastWidth, lastHeight;
+
+ protected MacOSXCGLContext(final GLDrawableImpl drawable,
+ final GLContext shareWith) {
super(drawable, shareWith);
initOpenGLImpl(getOpenGLMode());
}
@Override
- protected void resetStates() {
+ protected void resetStates(final boolean isInit) {
// no inner state _cglExt = null;
cglExtProcAddressTable = null;
- super.resetStates();
+ super.resetStates(isInit);
}
@Override
@@ -186,7 +249,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
protected Map<String, String> getExtensionNameMap() { return null; }
@Override
- protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) {
+ protected long createContextARBImpl(final long share, final boolean direct, final int ctp, final int major, final int minor) {
if(!isGLProfileSupported(ctp, major, minor)) {
if(DEBUG) {
System.err.println(getThreadName() + ": createContextARBImpl: Not supported "+getGLVersion(major, minor, ctp, "@creation on OSX "+Platform.getOSVersionNumber()));
@@ -214,7 +277,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
@Override
- protected void destroyContextARBImpl(long _context) {
+ protected void destroyContextARBImpl(final long _context) {
impl.release(_context);
impl.destroy(_context);
}
@@ -224,50 +287,33 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return false;
}
- protected long createImplPreset(GLContextImpl shareWith) throws GLException {
- long share = 0;
- if (shareWith != null) {
- // Change our OpenGL mode to match that of any share context before we create ourselves
- setOpenGLMode(((MacOSXCGLContext)shareWith).getOpenGLMode());
- share = shareWith.getHandle();
- if (share == 0) {
- throw new GLException("GLContextShareSet returned a NULL OpenGL context");
- }
- }
-
- MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
- GLCapabilitiesImmutable capabilitiesChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
- if (capabilitiesChosen.getPbufferFloatingPointBuffers() && !isTigerOrLater) {
- throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later");
- }
- GLProfile glp = capabilitiesChosen.getGLProfile();
- if(glp.isGLES1() || glp.isGLES2() || glp.isGL4() || glp.isGL3() && !isLionOrLater) {
+ @Override
+ protected boolean createImpl(final long shareWithHandle) throws GLException {
+ final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
+ final GLCapabilitiesImmutable capabilitiesChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final GLProfile glp = capabilitiesChosen.getGLProfile();
+ if( glp.isGLES() ||
+ ( glp.isGL3() && !isLionOrLater ) || ( glp.isGL4() && !isMavericksOrLater ) ) {
throw new GLException("OpenGL profile not supported on MacOSX "+Platform.getOSVersionNumber()+": "+glp);
}
-
- if (DEBUG) {
- System.err.println("Share context is " + toHexString(share) + " for " + this);
+ if( 0 != shareWithHandle && GLBackendType.NSOPENGL != getOpenGLMode() ) {
+ throw new GLException("Context sharing only supported in mode "+GLBackendType.NSOPENGL+": "+this);
}
- return share;
- }
-
- @Override
- protected boolean createImpl(GLContextImpl shareWith) throws GLException {
- long share = createImplPreset(shareWith);
- contextHandle = createContextARB(share, true);
+ contextHandle = createContextARB(shareWithHandle, true);
return 0 != contextHandle;
}
@Override
protected void makeCurrentImpl() throws GLException {
/** FIXME: won't work w/ special drawables (like FBO) - check for CGL mode regressions!
- *
+ *
if (getOpenGLMode() != ((MacOSXCGLDrawable)drawable).getOpenGLMode()) {
setOpenGLMode(((MacOSXCGLDrawable)drawable).getOpenGLMode());
} */
if (!impl.makeCurrent(contextHandle)) {
throw new GLException("Error making Context current: "+this);
}
+ drawableUpdatedNotify();
}
@Override
@@ -279,20 +325,72 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
protected void destroyImpl() throws GLException {
+ releaseUpdateHandle();
if(!impl.destroy(contextHandle)) {
throw new GLException("Error destroying OpenGL Context: "+this);
}
}
-
+
+ private final long getUpdateHandle() {
+ if( 0 == updateHandle ) {
+ lastWidth = -1;
+ lastHeight = -1;
+ if( isCreated() && drawable.getChosenGLCapabilities().isOnscreen() && isNSContext() ) {
+ final boolean incompleteView;
+ final NativeSurface surface = drawable.getNativeSurface();
+ if( surface instanceof ProxySurface ) {
+ incompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
+ } else {
+ incompleteView = false;
+ }
+ if(!incompleteView) {
+ updateHandle = CGL.updateContextRegister(contextHandle, drawable.getHandle());
+ if(0 == updateHandle) {
+ throw new InternalError("XXX2");
+ }
+ }
+ }
+ }
+ return updateHandle;
+ }
+
+ private final void releaseUpdateHandle() {
+ if ( 0 != updateHandle ) {
+ CGL.updateContextUnregister(updateHandle);
+ updateHandle = 0;
+ }
+ }
+
+ @Override
+ protected void drawableUpdatedNotify() throws GLException {
+ if( drawable.getChosenGLCapabilities().isOnscreen() ) {
+ final long _updateHandle = getUpdateHandle();
+ final int w = drawable.getSurfaceWidth();
+ final int h = drawable.getSurfaceHeight();
+ final boolean updateContext = ( 0!=_updateHandle && CGL.updateContextNeedsUpdate(_updateHandle) ) ||
+ w != lastWidth || h != lastHeight;
+ if(updateContext) {
+ lastWidth = w;
+ lastHeight = h;
+ if (contextHandle == 0) {
+ throw new GLException("Context not created");
+ }
+ CGL.updateContext(contextHandle);
+ }
+ }
+ }
+
@Override
- protected void contextRealized(boolean realized) {
+ protected void associateDrawable(final boolean bound) {
// context stuff depends on drawable stuff
- if(realized) {
- super.contextRealized(true); // 1) init drawable stuff
- impl.contextRealized(true); // 2) init context stuff
+ if(bound) {
+ super.associateDrawable(true); // 1) init drawable stuff
+ impl.associateDrawable(true); // 2) init context stuff
+ getUpdateHandle();
} else {
- impl.contextRealized(false); // 1) free context stuff
- super.contextRealized(false); // 2) free drawable stuff
+ releaseUpdateHandle();
+ impl.associateDrawable(false); // 1) free context stuff
+ super.associateDrawable(false); // 2) free drawable stuff
}
}
@@ -300,9 +398,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
impl.detachPBuffer();
}
-
+
@Override
- protected void copyImpl(GLContext source, int mask) throws GLException {
+ protected void copyImpl(final GLContext source, final int mask) throws GLException {
if( isNSContext() != ((MacOSXCGLContext)source).isNSContext() ) {
throw new GLException("Source/Destination OpenGL Context tyoe mismatch: source "+source+", dest: "+this);
}
@@ -319,12 +417,18 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
@Override
- protected boolean setSwapIntervalImpl(int interval) {
+ protected boolean setSwapIntervalImpl(final int interval) {
return impl.setSwapInterval(interval);
}
@Override
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
+ public final ByteBuffer glAllocateMemoryNV(final int size, final float readFrequency, final float writeFrequency, final float priority) {
+ // FIXME: apparently the Apple extension doesn't require a custom memory allocator
+ throw new GLException("Not yet implemented");
+ }
+
+ @Override
+ public final void glFreeMemoryNV(final ByteBuffer pointer) {
// FIXME: apparently the Apple extension doesn't require a custom memory allocator
throw new GLException("Not yet implemented");
}
@@ -363,31 +467,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return new StringBuilder();
}
- @Override
- public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals(GLExtensions.ARB_pbuffer) ||
- glExtensionName.equals(GLExtensions.ARB_pixel_format)) {
- return true;
- }
- return super.isExtensionAvailable(glExtensionName);
- }
-
- @Override
- public int getOffscreenContextPixelDataType() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextReadBuffer() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- throw new GLException("Should not call this");
- }
-
// Support for "mode switching" as described in MacOSXCGLDrawable
- public void setOpenGLMode(GLBackendType mode) {
+ public void setOpenGLMode(final GLBackendType mode) {
if (mode == openGLMode) {
return;
}
@@ -405,7 +486,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
public final GLBackendType getOpenGLMode() { return openGLMode; }
- protected void initOpenGLImpl(GLBackendType backend) {
+ protected void initOpenGLImpl(final GLBackendType backend) {
switch (backend) {
case NSOPENGL:
impl = new NSOpenGLImpl();
@@ -420,7 +501,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
super.append(sb);
@@ -433,87 +514,113 @@ public abstract class MacOSXCGLContext extends GLContextImpl
// NSOpenGLContext-based implementation
class NSOpenGLImpl implements GLBackendImpl {
private OffscreenLayerSurface backingLayerHost = null;
- private long nsOpenGLLayer = 0;
- private long nsOpenGLLayerPFmt = 0;
- private float screenVSyncTimeout; // microSec
- private int vsyncTimeout; // microSec - for nsOpenGLLayer mode
+ /** lifecycle: [create - destroy] */
+ private long pixelFormat = 0;
+ /** microSec - defaults to 1/60s */
+ private int screenVSyncTimeout = 16666;
+ /** microSec - for nsOpenGLLayer mode - defaults to 1/60s + 1ms */
+ private volatile int vsyncTimeout = 16666 + 1000;
private int lastWidth=0, lastHeight=0; // allowing to detect size change
- private long lastPBufferHandle = 0; // allowing to detect pbuffer recreation
+ private boolean needsSetContextPBuffer = false;
+ private ShaderProgram gl3ShaderProgram = null;
@Override
public boolean isNSContext() { return true; }
- @Override
- public long create(long share, int ctp, int major, int minor) {
- long ctx = 0;
- final NativeSurface surface = drawable.getNativeSurface();
- final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration();
- final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+
+ /** Only returns a valid NSView. If !NSView, return null and mark either pbuffer and FBO. */
+ private long getNSViewHandle(final boolean[] isPBuffer, final boolean[] isFBO) {
final long nsViewHandle;
- final boolean isPBuffer;
- final boolean isFBO;
if(drawable instanceof GLFBODrawableImpl) {
nsViewHandle = 0;
- isPBuffer = false;
- isFBO = true;
+ isPBuffer[0] = false;
+ isFBO[0] = true;
if(DEBUG) {
- System.err.println("NS create GLFBODrawableImpl drawable: isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
- }
- } else if(drawable instanceof MacOSXCGLDrawable) {
- // we allow null here! (special pbuffer case)
- nsViewHandle = ((MacOSXCGLDrawable)MacOSXCGLContext.this.drawable).getNSViewHandle();
- isPBuffer = CGL.isNSOpenGLPixelBuffer(drawable.getHandle());
- isFBO = false;
- if(DEBUG) {
- System.err.println("NS create MacOSXCGLDrawable drawable handle isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
+ System.err.println("NS viewHandle.1: GLFBODrawableImpl drawable: isFBO "+isFBO[0]+", isPBuffer "+isPBuffer[0]+", "+drawable.getClass().getName()+",\n\t"+drawable);
}
} else {
- // we only allow a valid NSView here
final long drawableHandle = drawable.getHandle();
final boolean isNSView = OSXUtil.isNSView(drawableHandle);
final boolean isNSWindow = OSXUtil.isNSWindow(drawableHandle);
- isPBuffer = CGL.isNSOpenGLPixelBuffer(drawableHandle);
- isFBO = false;
+ isPBuffer[0] = CGL.isNSOpenGLPixelBuffer(drawableHandle);
+ isFBO[0] = false;
- if(DEBUG) {
- System.err.println("NS create Anonymous drawable handle "+toHexString(drawableHandle)+": isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
- }
if( isNSView ) {
nsViewHandle = drawableHandle;
} else if( isNSWindow ) {
nsViewHandle = OSXUtil.GetNSView(drawableHandle);
- } else if( isPBuffer ) {
+ } else if( isPBuffer[0] ) {
nsViewHandle = 0;
} else {
- throw new RuntimeException("Anonymous drawable instance's handle neither NSView, NSWindow nor PBuffer: "+toHexString(drawableHandle)+", "+drawable.getClass().getName()+",\n\t"+drawable);
+ throw new RuntimeException("Drawable's handle neither NSView, NSWindow nor PBuffer: drawableHandle "+toHexString(drawableHandle)+", isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO[0]+", isPBuffer "+isPBuffer[0]+", "+drawable.getClass().getName()+",\n\t"+drawable);
}
+ if(DEBUG) {
+ System.err.println("NS viewHandle.2: drawableHandle "+toHexString(drawableHandle)+" -> nsViewHandle "+toHexString(nsViewHandle)+": isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO[0]+", isPBuffer "+isPBuffer[0]+", "+drawable.getClass().getName()+",\n\t"+drawable);
+ }
+ }
+ needsSetContextPBuffer = isPBuffer[0];
+ return nsViewHandle;
+ }
+
+ @Override
+ public long create(final long share, final int ctp, final int major, final int minor) {
+ long ctx = 0;
+ final NativeSurface surface = drawable.getNativeSurface();
+ final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration();
+ final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final long nsViewHandle;
+ final boolean isPBuffer;
+ final boolean isFBO;
+ {
+ final boolean[] _isPBuffer = { false };
+ final boolean[] _isFBO = { false };
+ nsViewHandle = getNSViewHandle(_isPBuffer, _isFBO);
+ isPBuffer = _isPBuffer[0];
+ isFBO = _isFBO[0];
}
- backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
+ final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
boolean incompleteView = null != backingLayerHost;
if( !incompleteView && surface instanceof ProxySurface ) {
incompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
}
- long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps, ctp, major, minor);
+ {
+ final GLCapabilitiesImmutable targetCaps;
+ if( isFBO ) {
+ // Use minimum GLCapabilities for the target surface w/ same profile
+ targetCaps = new GLCapabilities( chosenCaps.getGLProfile() );
+ } else {
+ targetCaps = chosenCaps;
+ }
+ pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(config.getScreen().getDevice(), targetCaps, ctp, major, minor);
+ }
if (pixelFormat == 0) {
if(DEBUG) {
System.err.println("Unable to allocate pixel format with requested GLCapabilities: "+chosenCaps);
}
return 0;
}
- GLCapabilities fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat);
- if(chosenCaps.isOnscreen() || !fixedCaps.isPBuffer()) {
- // not handled, so copy them
- fixedCaps.setFBO(chosenCaps.isFBO());
- fixedCaps.setPBuffer(chosenCaps.isPBuffer());
- fixedCaps.setBitmap(chosenCaps.isBitmap());
- fixedCaps.setOnscreen(chosenCaps.isOnscreen());
- }
- fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque());
- int sRefreshRate = OSXUtil.GetScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex());
- screenVSyncTimeout = 1000000f / sRefreshRate;
+ final GLCapabilitiesImmutable fixedCaps;
+ if( isFBO ) {
+ // pixelformat of target doesn't affect caps w/ FBO
+ fixedCaps = chosenCaps;
+ } else {
+ final GLCapabilities _fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat);
+ if( !_fixedCaps.isPBuffer() && isPBuffer ) {
+ throw new InternalError("handle is PBuffer, fixedCaps not: "+drawable);
+ }
+ // determine on-/offscreen caps, since pformat is ambiguous
+ _fixedCaps.setPBuffer( isPBuffer ); // exclusive
+ _fixedCaps.setBitmap( false ); // n/a in our OSX impl.
+ _fixedCaps.setOnscreen( !isFBO && !isPBuffer );
+ fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(_fixedCaps, chosenCaps.isBackgroundOpaque());
+ }
+ final int sRefreshRate = OSXUtil.GetScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex());
+ if( 0 < sRefreshRate ) {
+ screenVSyncTimeout = 1000000 / sRefreshRate;
+ }
if(DEBUG) {
- System.err.println("NS create OSX>=lion "+isLionOrLater);
+ System.err.println("NS create OSX>=lion "+isLionOrLater+", OSX>=mavericks "+isMavericksOrLater);
System.err.println("NS create incompleteView: "+incompleteView);
System.err.println("NS create backingLayerHost: "+backingLayerHost);
System.err.println("NS create share: "+share);
@@ -527,170 +634,319 @@ public abstract class MacOSXCGLContext extends GLContextImpl
System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros");
// Thread.dumpStack();
}
- if(fixedCaps.isPBuffer()) {
- if(!isPBuffer) {
- throw new InternalError("fixedCaps is PBuffer, handle not: "+drawable);
- }
- } else {
- if(isPBuffer) {
- throw new InternalError("handle is PBuffer, fixedCaps not: "+drawable);
- }
- }
config.setChosenCapabilities(fixedCaps);
- /**
- if(null != backingLayerHost) {
- backingLayerHost.setChosenCapabilities(fixedCaps);
- } */
-
- try {
- int[] viewNotReady = new int[1];
- // Try to allocate a context with this
- ctx = CGL.createContext(share,
- nsViewHandle, incompleteView,
- pixelFormat,
- chosenCaps.isBackgroundOpaque(),
- viewNotReady, 0);
- if (0 == ctx) {
- if(DEBUG) {
- System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady[0]));
- }
- return 0;
- }
- if(null != backingLayerHost) {
- nsOpenGLLayerPFmt = pixelFormat;
- pixelFormat = 0;
- }
-
- if (chosenCaps.isOnscreen() && !chosenCaps.isBackgroundOpaque()) {
- // Set the context opacity
- CGL.setContextOpacity(ctx, 0);
- }
- } finally {
- if(0!=pixelFormat) {
- CGL.deletePixelFormat(pixelFormat);
- pixelFormat = 0;
+ final IntBuffer viewNotReady = Buffers.newDirectIntBuffer(1);
+ // Try to allocate a context with this
+ ctx = CGL.createContext(share, nsViewHandle, incompleteView,
+ pixelFormat, chosenCaps.isBackgroundOpaque(), viewNotReady);
+ if (0 == ctx) {
+ if(DEBUG) {
+ System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady.get(0)));
}
+ return 0;
+ }
+
+ if (chosenCaps.isOnscreen() && !chosenCaps.isBackgroundOpaque()) {
+ // Set the context opacity
+ CGL.setContextOpacity(ctx, 0);
}
return ctx;
}
@Override
- public boolean destroy(long ctx) {
- lastPBufferHandle = 0;
+ public boolean destroy(final long ctx) {
+ if(0!=pixelFormat) {
+ CGL.deletePixelFormat(pixelFormat);
+ pixelFormat = 0;
+ }
return CGL.deleteContext(ctx, true);
}
+ /**
+ * NSOpenGLLayer creation and it's attachment is performed on the main-thread w/o [infinite] blocking.
+ * <p>
+ * Since NSOpenGLLayer creation requires this context for it's shared context creation,
+ * this method attempts to acquire the surface and context lock with {@link #screenVSyncTimeout}/2 maximum wait time.
+ * If the surface and context lock could not be acquired, this runnable is being re-queued for later execution.
+ * </p>
+ * <p>
+ * Hence this method blocks the main-thread only for a short period of time.
+ * </p>
+ */
+ class AttachGLLayerCmd implements Runnable {
+ final OffscreenLayerSurface ols;
+ final long ctx;
+ final int shaderProgram;
+ final long pfmt;
+ final long pbuffer;
+ final int texID;
+ final boolean isOpaque;
+ final int texWidth;
+ final int texHeight;
+ final int winWidth;
+ final int winHeight;
+ /** Synchronized by instance's monitor */
+ long nsOpenGLLayer;
+ /** Synchronized by instance's monitor */
+ boolean valid;
+
+ AttachGLLayerCmd(final OffscreenLayerSurface ols, final long ctx, final int shaderProgram, final long pfmt, final long pbuffer, final int texID,
+ final boolean isOpaque, final int texWidth, final int texHeight, final int winWidth, final int winHeight) {
+ this.ols = ols;
+ this.ctx = ctx;
+ this.shaderProgram = shaderProgram;
+ this.pfmt = pfmt;
+ this.pbuffer = pbuffer;
+ this.texID = texID;
+ this.isOpaque = isOpaque;
+ this.texWidth = texWidth;
+ this.texHeight = texHeight;
+ this.winWidth = winWidth;
+ this.winHeight = winHeight;
+ this.valid = false;
+ this.nsOpenGLLayer = 0;
+ }
+
+ public final String contentToString() {
+ return "valid "+valid+", size tex["+texWidth+"x"+texHeight+"], win["+winWidth+"x"+winHeight+"], ctx "+toHexString(ctx)+", opaque "+isOpaque+", texID "+texID+", pbuffer "+toHexString(pbuffer)+", nsOpenGLLayer "+toHexString(nsOpenGLLayer);
+ }
+
+ @Override
+ public final String toString() {
+ return "AttachGLLayerCmd["+contentToString()+"]";
+ }
+
+ @Override
+ public void run() {
+ synchronized(this) {
+ if( !valid ) {
+ try {
+ final int maxwait = screenVSyncTimeout/2000; // TO 1/2 of current screen-vsync in [ms]
+ final RecursiveLock surfaceLock = ols.getLock();
+ if( surfaceLock.tryLock( maxwait ) ) {
+ try {
+ if( MacOSXCGLContext.this.lock.tryLock( maxwait ) ) {
+ try {
+ nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, shaderProgram, pfmt, pbuffer, texID, isOpaque,
+ texWidth, texHeight, winWidth, winHeight);
+ ols.attachSurfaceLayer(nsOpenGLLayer);
+ final int currentInterval = MacOSXCGLContext.this.getSwapInterval();
+ final int interval = 0 <= currentInterval ? currentInterval : 1;
+ setSwapIntervalImpl(nsOpenGLLayer, interval); // enabled per default in layered surface
+ valid = true;
+ if (DEBUG) {
+ System.err.println("NSOpenGLLayer.Attach: OK, layer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(pbuffer)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", drawableHandle "+toHexString(drawable.getHandle())+" - "+getThreadName());
+ }
+ } finally {
+ MacOSXCGLContext.this.lock.unlock();
+ }
+ }
+ } finally {
+ surfaceLock.unlock();
+ }
+ }
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ if( !valid ) {
+ // could not acquire lock, re-queue
+ if (DEBUG) {
+ System.err.println("NSOpenGLLayer.Attach: Re-Queue, drawableHandle "+toHexString(drawable.getHandle())+" - "+getThreadName());
+ }
+ OSXUtil.RunLater(true /* onMain */, this, 1);
+ }
+ }
+ }
+ }
+ }
+ AttachGLLayerCmd attachGLLayerCmd = null;
+
+ class DetachGLLayerCmd implements Runnable {
+ final AttachGLLayerCmd cmd;
+
+ DetachGLLayerCmd(final AttachGLLayerCmd cmd) {
+ this.cmd = cmd;
+ }
+
+ @Override
+ public final String toString() {
+ return "DetachGLLayerCmd["+cmd.contentToString()+"]";
+ }
+
+ @Override
+ public void run() {
+ synchronized( cmd ) {
+ if( cmd.valid ) {
+ // still having a valid OLS attached to surface (parent OLS could have been removed)
+ try {
+ final OffscreenLayerSurface ols = cmd.ols;
+ final long l = ols.getAttachedSurfaceLayer();
+ if( 0 != l ) {
+ ols.detachSurfaceLayer();
+ }
+ } catch(final Throwable t) {
+ System.err.println("Caught exception on thread "+getThreadName());
+ t.printStackTrace();
+ }
+ CGL.releaseNSOpenGLLayer(cmd.nsOpenGLLayer);
+ if(DEBUG) {
+ System.err.println("NSOpenGLLayer.Detach: OK, layer "+toHexString(cmd.nsOpenGLLayer)+" - "+getThreadName());
+ }
+ cmd.nsOpenGLLayer = 0;
+ cmd.valid = false;
+ } else if(DEBUG) {
+ System.err.println("NSOpenGLLayer.Detach: Skipped "+toHexString(cmd.nsOpenGLLayer)+" - "+getThreadName());
+ }
+ }
+ }
+ }
+
@Override
- public boolean contextRealized(boolean realized) {
- if( realized ) {
+ public void associateDrawable(final boolean bound) {
+ backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(drawable.getNativeSurface(), true);
+
+ if(DEBUG) {
+ System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable: "+bound+", ctx "+toHexString(contextHandle)+
+ ", hasBackingLayerHost "+(null!=backingLayerHost)+", attachGLLayerCmd "+attachGLLayerCmd);
+ // Thread.dumpStack();
+ }
+
+ if( bound ) {
if( null != backingLayerHost ) {
+ final GLCapabilitiesImmutable chosenCaps;
+ final long ctx;
+ final int texID;
+ final long pbufferHandle;
+ final int gl3ShaderProgramName;
+
//
// handled layered surface
//
- final GLCapabilitiesImmutable chosenCaps = drawable.getChosenGLCapabilities();
- final long ctx = MacOSXCGLContext.this.getHandle();
- final int texID;
+ chosenCaps = drawable.getChosenGLCapabilities();
+ ctx = MacOSXCGLContext.this.getHandle();
final long drawableHandle = drawable.getHandle();
if(drawable instanceof GLFBODrawableImpl) {
final GLFBODrawableImpl fbod = (GLFBODrawableImpl)drawable;
- texID = fbod.getTextureBuffer(GL.GL_FRONT).getName();
+ texID = fbod.getColorbuffer(GL.GL_FRONT).getName();
+ pbufferHandle = 0;
fbod.setSwapBufferContext(new GLFBODrawableImpl.SwapBufferContext() {
- public void swapBuffers(boolean doubleBuffered) {
- MacOSXCGLContext.NSOpenGLImpl.this.swapBuffers();
- } } ) ;
- lastPBufferHandle = 0;
- } else if( chosenCaps.isPBuffer() && CGL.isNSOpenGLPixelBuffer(drawableHandle) ) {
+ @Override
+ public void swapBuffers(final boolean doubleBuffered) {
+ MacOSXCGLContext.NSOpenGLImpl.this.swapBuffers();
+ } } ) ;
+ } else if( CGL.isNSOpenGLPixelBuffer(drawableHandle) ) {
texID = 0;
- lastPBufferHandle = drawableHandle;
+ pbufferHandle = drawableHandle;
if(0 != drawableHandle) { // complete 'validatePBufferConfig(..)' procedure
- CGL.setContextPBuffer(ctx, drawableHandle);
+ CGL.setContextPBuffer(ctx, pbufferHandle);
+ needsSetContextPBuffer = false;
}
} else {
throw new GLException("BackingLayerHost w/ unknown handle (!FBO, !PBuffer): "+drawable);
}
- lastWidth = drawable.getWidth();
- lastHeight = drawable.getHeight();
+ lastWidth = drawable.getSurfaceWidth();
+ lastHeight = drawable.getSurfaceHeight();
if(0>=lastWidth || 0>=lastHeight || !drawable.isRealized()) {
throw new GLException("Drawable not realized yet or invalid texture size, texSize "+lastWidth+"x"+lastHeight+", "+drawable);
}
- nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, lastPBufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight);
- if (DEBUG) {
- System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(lastPBufferHandle)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", "+drawable);
+ if( MacOSXCGLContext.this.isGL3core() ) {
+ if( null == gl3ShaderProgram) {
+ gl3ShaderProgram = createCALayerShader(MacOSXCGLContext.this.gl.getGL3ES3());
+ }
+ gl3ShaderProgramName = gl3ShaderProgram.program();
+ } else {
+ gl3ShaderProgramName = 0;
}
- backingLayerHost.attachSurfaceLayer(nsOpenGLLayer);
- setSwapInterval(1); // enabled per default in layered surface
- } else {
- lastWidth = drawable.getWidth();
- lastHeight = drawable.getHeight();
+
+ // All CALayer lifecycle ops are deferred on main-thread
+ final int[] winSize = drawable.getNativeSurface().convertToWindowUnits(new int[]{ lastWidth, lastHeight });
+ attachGLLayerCmd = new AttachGLLayerCmd(
+ backingLayerHost, ctx, gl3ShaderProgramName, pixelFormat, pbufferHandle, texID,
+ chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight, winSize[0], winSize[1] );
+ if(DEBUG) {
+ System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable(true): "+attachGLLayerCmd);
+ }
+ OSXUtil.RunOnMainThread(false, false /* kickNSApp */, attachGLLayerCmd);
+ } else { // -> null == backingLayerHost
+ lastWidth = drawable.getSurfaceWidth();
+ lastHeight = drawable.getSurfaceHeight();
+ final boolean[] isPBuffer = { false };
+ final boolean[] isFBO = { false };
+ CGL.setContextView(contextHandle, getNSViewHandle(isPBuffer, isFBO));
}
- } else {
- if( 0 != nsOpenGLLayer ) {
- final NativeSurface surface = drawable.getNativeSurface();
- if (DEBUG) {
- System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", "+drawable);
+ } else { // -> !bound
+ if( null != backingLayerHost ) {
+ final AttachGLLayerCmd cmd = attachGLLayerCmd;
+ attachGLLayerCmd = null;
+ if( null == cmd ) {
+ throw new GLException("Null attachGLLayerCmd: "+drawable);
}
- final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
- if(null != ols && ols.isSurfaceLayerAttached()) {
- // still having a valid OLS attached to surface (parent OLS could have been removed)
- ols.detachSurfaceLayer();
+ if( 0 != cmd.pbuffer ) {
+ CGL.setContextPBuffer(contextHandle, 0);
+ }
+ synchronized(cmd) {
+ if( !cmd.valid ) {
+ cmd.valid = true; // skip pending creation
+ } else {
+ // All CALayer lifecycle ops are deferred on main-thread
+ final DetachGLLayerCmd dCmd = new DetachGLLayerCmd(cmd);
+ if(DEBUG) {
+ System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable(false): "+dCmd);
+ }
+ OSXUtil.RunOnMainThread(false, true /* kickNSApp */, dCmd);
+ if( null != gl3ShaderProgram ) {
+ gl3ShaderProgram.destroy(MacOSXCGLContext.this.gl.getGL3());
+ gl3ShaderProgram = null;
+ }
+ }
}
- CGL.releaseNSOpenGLLayer(nsOpenGLLayer);
- nsOpenGLLayer = 0;
- }
- if(0 != nsOpenGLLayerPFmt) {
- CGL.deletePixelFormat(nsOpenGLLayerPFmt);
- nsOpenGLLayerPFmt = 0;
}
- lastPBufferHandle = 0;
+ CGL.clearDrawable(contextHandle);
+ backingLayerHost = null;
}
- backingLayerHost = null;
- return true;
}
- private final void validatePBufferConfig(long ctx) {
- final GLCapabilitiesImmutable chosenCaps = drawable.getChosenGLCapabilities();
+ private final void validatePBufferConfig(final long ctx) {
final long drawableHandle = drawable.getHandle();
- if( chosenCaps.isPBuffer() && lastPBufferHandle != drawableHandle && CGL.isNSOpenGLPixelBuffer(drawableHandle) ) {
+ if( needsSetContextPBuffer && 0 != drawableHandle && CGL.isNSOpenGLPixelBuffer(drawableHandle) ) {
// Must associate the pbuffer with our newly-created context
- lastPBufferHandle = drawableHandle;
- if(0 != drawableHandle) {
- CGL.setContextPBuffer(ctx, drawableHandle);
- }
+ needsSetContextPBuffer = false;
+ CGL.setContextPBuffer(ctx, drawableHandle);
if(DEBUG) {
- System.err.println("NS.validateDrawableConfig bind pbuffer "+toHexString(drawableHandle)+" -> ctx "+toHexString(ctx));
+ System.err.println("NS.validateDrawableConfig bind pbuffer "+toHexString(drawableHandle)+" -> ctx "+toHexString(ctx));
}
}
}
-
+
/** Returns true if size has been updated, otherwise false (same size). */
- private final boolean validateDrawableSizeConfig(long ctx) {
- final int width = drawable.getWidth();
- final int height = drawable.getHeight();
+ private final boolean validateDrawableSizeConfig(final long ctx) {
+ final int width = drawable.getSurfaceWidth();
+ final int height = drawable.getSurfaceHeight();
if( lastWidth != width || lastHeight != height ) {
- lastWidth = drawable.getWidth();
- lastHeight = drawable.getHeight();
+ lastWidth = drawable.getSurfaceWidth();
+ lastHeight = drawable.getSurfaceHeight();
if(DEBUG) {
- System.err.println("NS.validateDrawableConfig size changed");
+ System.err.println("NS.validateDrawableConfig size changed");
}
return true;
}
return false;
}
-
+
@Override
- public boolean copyImpl(long src, int mask) {
+ public boolean copyImpl(final long src, final int mask) {
CGL.copyContext(contextHandle, src, mask);
return true;
}
@Override
- public boolean makeCurrent(long ctx) {
+ public boolean makeCurrent(final long ctx) {
final long cglCtx = CGL.getCGLContext(ctx);
if(0 == cglCtx) {
throw new InternalError("Null CGLContext for: "+this);
}
- int err = CGL.CGLLockContext(cglCtx);
+ final int err = CGL.CGLLockContext(cglCtx);
if(CGL.kCGLNoError == err) {
validatePBufferConfig(ctx); // required to handle pbuffer change ASAP
return CGL.makeCurrentContext(ctx);
@@ -701,12 +957,14 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
@Override
- public boolean release(long ctx) {
+ public boolean release(final long ctx) {
try {
- gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze
- } catch (GLException gle) {
+ if( hasRendererQuirk(GLRendererQuirks.GLFlushBeforeRelease) && null != MacOSXCGLContext.this.getGLProcAddressTable() ) {
+ gl.glFlush();
+ }
+ } catch (final GLException gle) {
if(DEBUG) {
- System.err.println("MacOSXCGLContext.NSOpenGLImpl.release: INFO: glFlush() catched exception:");
+ System.err.println("MacOSXCGLContext.NSOpenGLImpl.release: INFO: glFlush() caught exception:");
gle.printStackTrace();
}
}
@@ -724,68 +982,140 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean detachPBuffer() {
- if(0 != lastPBufferHandle) {
- lastPBufferHandle = 0;
- if(0 != nsOpenGLLayer) {
- CGL.flushNSOpenGLLayerPBuffer(nsOpenGLLayer); // notify invalid pbuffer
+ needsSetContextPBuffer = true;
+ // CGL.setContextPBuffer(contextHandle, 0); // doesn't work, i.e. not taking nil
+ return true;
+ }
+
+ @Override
+ public boolean setSwapInterval(final int interval) {
+ final AttachGLLayerCmd cmd = attachGLLayerCmd;
+ if(null != cmd) {
+ synchronized(cmd) {
+ if( cmd.valid && 0 != cmd.nsOpenGLLayer) {
+ setSwapIntervalImpl(cmd.nsOpenGLLayer, interval);
+ return true;
+ }
}
- // CGL.setContextPBuffer(contextHandle, 0); // doesn't work, i.e. not taking nil
}
+ setSwapIntervalImpl(0, interval);
return true;
}
-
- @Override
- public boolean setSwapInterval(int interval) {
- if(0 != nsOpenGLLayer) {
- CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval);
- vsyncTimeout = interval * (int)screenVSyncTimeout + 1000; // +1ms
- if(DEBUG) { System.err.println("NS setSwapInterval: "+vsyncTimeout+" micros"); }
+
+ private void setSwapIntervalImpl(final long l, final int interval) {
+ if( 0 != l ) {
+ CGL.setNSOpenGLLayerSwapInterval(l, interval);
+ if( 0 < interval ) {
+ vsyncTimeout = interval * screenVSyncTimeout + 1000; // +1ms
+ } else {
+ vsyncTimeout = 1 * screenVSyncTimeout + 1000; // +1ms
+ }
+ if(DEBUG) { System.err.println("NS setSwapInterval: "+interval+" -> "+vsyncTimeout+" micros"); }
}
+ if(DEBUG) { System.err.println("CGL setSwapInterval: "+interval); }
CGL.setSwapInterval(contextHandle, interval);
- return true;
}
private int skipSync=0;
-
+ /** TODO: Remove after discussion
+ private boolean perfIterReset = false;
+ private int perfIter = 0;
+ private long waitGLS = 0;
+ private long finishGLS = 0;
+ private long frameXS = 0;
+ private long lastFrameStart = 0;
+ */
+
@Override
public boolean swapBuffers() {
- final boolean res;
- if( 0 != nsOpenGLLayer ) {
- if( validateDrawableSizeConfig(contextHandle) ) {
- // skip wait-for-vsync for a few frames if size has changed,
- // allowing to update the texture IDs ASAP.
- skipSync = 10;
- }
-
- final int texID;
- final boolean valid;
- if(drawable instanceof GLFBODrawableImpl) {
- texID = ((GLFBODrawableImpl)drawable).getTextureBuffer(GL.GL_FRONT).getName();
- valid = 0 != texID;
- } else {
- texID = 0;
- valid = 0 != lastPBufferHandle;
- }
- if(valid) {
- if(0 == skipSync) {
- // If v-sync is disabled, frames will be drawn as quickly as possible
- // w/o delay but in sync w/ CALayer. Otherwise wait until next swap interval (v-sync).
- CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, vsyncTimeout);
- } else {
- skipSync--;
- }
- res = CGL.flushBuffer(contextHandle);
- if(res) {
- // trigger CALayer to update incl. possible surface change
- CGL.setNSOpenGLLayerNeedsDisplay(nsOpenGLLayer, lastPBufferHandle, texID, lastWidth, lastHeight);
+ final AttachGLLayerCmd cmd = attachGLLayerCmd;
+ if(null != cmd) {
+ synchronized(cmd) {
+ if( cmd.valid && 0 != cmd.nsOpenGLLayer) {
+ if( validateDrawableSizeConfig(contextHandle) ) {
+ // skip wait-for-vsync for a few frames if size has changed,
+ // allowing to update the texture IDs ASAP.
+ skipSync = 10;
+ }
+
+ final boolean res;
+ final int texID;
+ final boolean valid;
+ final boolean isFBO = drawable instanceof GLFBODrawableImpl;
+ if( isFBO ){
+ texID = ((GLFBODrawableImpl)drawable).getColorbuffer(GL.GL_FRONT).getName();
+ valid = 0 != texID;
+ } else {
+ texID = 0;
+ valid = 0 != drawable.getHandle();
+ }
+ if(valid) {
+ res = CGL.flushBuffer(contextHandle);
+ if(res) {
+ if(0 == skipSync) {
+ /** TODO: Remove after discussion
+ perfIter++;
+ if( !perfIterReset && 100 == perfIter ) {
+ perfIterReset = true;
+ perfIter = 1;
+ waitGLS = 0;
+ finishGLS = 0;
+ frameXS = 0;
+ }
+ final long lastFramePeriod0 = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+ gl.glFinish(); // Require to finish previous GL rendering to give CALayer proper result
+ final long lastFramePeriod1 = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+
+ // If v-sync is disabled, frames will be drawn as quickly as possible w/o delay,
+ // while still synchronizing w/ CALayer.
+ // If v-sync is enabled wait until next swap interval (v-sync).
+ CGL.waitUntilNSOpenGLLayerIsReady(cmd.nsOpenGLLayer, vsyncTimeout);
+ final long lastFramePeriodX = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+
+ final long finishGL = lastFramePeriod1 - lastFramePeriod0;
+ final long waitGL = lastFramePeriodX - lastFramePeriod1;
+ finishGLS += finishGL;
+ waitGLS += waitGL;
+ frameXS += lastFramePeriodX;
+
+ System.err.println("XXX["+perfIter+"] TO "+vsyncTimeout/1000+" ms, "+
+ "lFrame0 "+lastFramePeriod0/1000+" ms, "+
+ "lFrameX "+lastFramePeriodX/1000+" / "+frameXS/1000+" ~"+(frameXS/perfIter)/1000.0+" ms, "+
+ "finishGL "+finishGL/1000+" / "+finishGLS/1000+" ~"+(finishGLS/perfIter)/1000.0+" ms, "+
+ "waitGL "+waitGL/1000+" / "+waitGLS/1000+" ~"+(waitGLS/perfIter)/1000.0+" ms");
+ */
+ //
+ // Required(?) to finish previous GL rendering to give CALayer proper result,
+ // i.e. synchronize both threads each w/ their GLContext sharing same resources.
+ //
+ // FIXME: IMHO this synchronization should be implicitly performed via 'CGL.flushBuffer(contextHandle)' above,
+ // in case this will be determined a driver bug - use a QUIRK entry in GLRendererQuirks!
+ gl.glFinish();
+
+ // If v-sync is disabled, frames will be drawn as quickly as possible w/o delay,
+ // while still synchronizing w/ CALayer.
+ // If v-sync is enabled wait until next swap interval (v-sync).
+ CGL.waitUntilNSOpenGLLayerIsReady(cmd.nsOpenGLLayer, vsyncTimeout);
+ } else {
+ skipSync--;
+ }
+ if(isFBO) {
+ // trigger CALayer to update incl. possible surface change (texture)
+ CGL.setNSOpenGLLayerNeedsDisplayFBO(cmd.nsOpenGLLayer, texID);
+ } else {
+ // trigger CALayer to update incl. possible surface change (new pbuffer handle)
+ CGL.setNSOpenGLLayerNeedsDisplayPBuffer(cmd.nsOpenGLLayer, drawable.getHandle());
+ }
+ // lastFrameStart = TimeUnit.NANOSECONDS.toMicros(System.nanoTime());
+ }
+ } else {
+ res = true;
+ }
+ return res;
}
- } else {
- res = true;
}
- } else {
- res = CGL.flushBuffer(contextHandle);
}
- return res;
+ return CGL.flushBuffer(contextHandle);
}
}
@@ -795,17 +1125,18 @@ public abstract class MacOSXCGLContext extends GLContextImpl
public boolean isNSContext() { return false; }
@Override
- public long create(long share, int ctp, int major, int minor) {
+ public long create(final long share, final int ctp, final int major, final int minor) {
long ctx = 0;
- MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
- GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
- long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2CGLPixelFormat(chosenCaps, ctp, major, minor);
+ final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
+ final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
+ final long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2CGLPixelFormat(config.getScreen().getDevice(),
+ chosenCaps, ctp, major, minor);
if (pixelFormat == 0) {
throw new GLException("Unable to allocate pixel format with requested GLCapabilities");
}
try {
// Create new context
- PointerBuffer ctxPB = PointerBuffer.allocateDirect(1);
+ final PointerBuffer ctxPB = PointerBuffer.allocateDirect(1);
if (DEBUG) {
System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share));
}
@@ -818,13 +1149,12 @@ public abstract class MacOSXCGLContext extends GLContextImpl
if (0 != ctx) {
GLCapabilities fixedCaps = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(pixelFormat);
fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque());
- if(chosenCaps.isOnscreen() || !fixedCaps.isPBuffer()) {
- // not handled, so copy them
- fixedCaps.setFBO(chosenCaps.isFBO());
- fixedCaps.setPBuffer(chosenCaps.isPBuffer());
- fixedCaps.setBitmap(chosenCaps.isBitmap());
- fixedCaps.setOnscreen(chosenCaps.isOnscreen());
- }
+ { // determine on-/offscreen caps, since pformat is ambiguous
+ fixedCaps.setFBO( false ); // n/a for CGLImpl
+ fixedCaps.setPBuffer( fixedCaps.isPBuffer() && !chosenCaps.isOnscreen() );
+ fixedCaps.setBitmap( false ); // n/a in our OSX impl.
+ fixedCaps.setOnscreen( !fixedCaps.isPBuffer() );
+ }
config.setChosenCapabilities(fixedCaps);
if(DEBUG) {
System.err.println("CGL create fixedCaps: "+fixedCaps);
@@ -835,7 +1165,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
if (res != CGL.kCGLNoError) {
throw new GLException("Error code " + res + " while attaching context to pbuffer");
}
- }
+ }
}
} finally {
CGL.CGLDestroyPixelFormat(pixelFormat);
@@ -844,23 +1174,22 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
@Override
- public boolean destroy(long ctx) {
+ public boolean destroy(final long ctx) {
return CGL.CGLDestroyContext(ctx) == CGL.kCGLNoError;
}
@Override
- public boolean contextRealized(boolean realized) {
- return true;
+ public void associateDrawable(final boolean bound) {
}
@Override
- public boolean copyImpl(long src, int mask) {
+ public boolean copyImpl(final long src, final int mask) {
CGL.CGLCopyContext(src, contextHandle, mask);
return true;
}
@Override
- public boolean makeCurrent(long ctx) {
+ public boolean makeCurrent(final long ctx) {
int err = CGL.CGLLockContext(ctx);
if(CGL.kCGLNoError == err) {
err = CGL.CGLSetCurrentContext(ctx);
@@ -876,20 +1205,22 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
@Override
- public boolean release(long ctx) {
+ public boolean release(final long ctx) {
try {
- gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze
- } catch (GLException gle) {
+ if( hasRendererQuirk(GLRendererQuirks.GLFlushBeforeRelease) && null != MacOSXCGLContext.this.getGLProcAddressTable() ) {
+ gl.glFlush();
+ }
+ } catch (final GLException gle) {
if(DEBUG) {
- System.err.println("MacOSXCGLContext.CGLImpl.release: INFO: glFlush() catched exception:");
+ System.err.println("MacOSXCGLContext.CGLImpl.release: INFO: glFlush() caught exception:");
gle.printStackTrace();
}
}
- int err = CGL.CGLSetCurrentContext(0);
+ final int err = CGL.CGLSetCurrentContext(0);
if(DEBUG && CGL.kCGLNoError != err) {
System.err.println("CGL: Could not release current context: err 0x"+Integer.toHexString(err)+": "+this);
}
- int err2 = CGL.CGLUnlockContext(ctx);
+ final int err2 = CGL.CGLUnlockContext(ctx);
if(DEBUG && CGL.kCGLNoError != err2) {
System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err2)+": "+this);
}
@@ -905,11 +1236,12 @@ public abstract class MacOSXCGLContext extends GLContextImpl
} */
return true;
}
-
+
@Override
- public boolean setSwapInterval(int interval) {
- int[] lval = new int[] { interval } ;
- CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0);
+ public boolean setSwapInterval(final int interval) {
+ final IntBuffer lval = Buffers.newDirectIntBuffer(1);
+ lval.put(0, interval);
+ CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval);
return true;
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
index cc727c8e1..8ea84a32d 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
@@ -84,11 +84,14 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
// GLPbuffer, a GLJPanel and a GLCanvas simultaneously) but should
// be enough to get things off the ground.
public enum GLBackendType {
- NSOPENGL(0), CGL(1);
+ /** Default OpenGL Backend */
+ NSOPENGL(0),
+ /** Alternative OpenGL Backend, only used for external context! */
+ CGL(1);
public final int id;
- GLBackendType(int id){
+ GLBackendType(final int id){
this.id = id;
}
}
@@ -97,7 +100,7 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
private boolean haveSetOpenGLMode = false;
private GLBackendType openGLMode = GLBackendType.NSOPENGL;
- public MacOSXCGLDrawable(GLDrawableFactory factory, NativeSurface comp, boolean realized) {
+ public MacOSXCGLDrawable(final GLDrawableFactory factory, final NativeSurface comp, final boolean realized) {
super(factory, comp, realized);
initOpenGLImpl(getOpenGLMode());
}
@@ -105,40 +108,35 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
@Override
protected void setRealizedImpl() {
}
-
- protected long getNSViewHandle() {
- return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0;
- }
@Override
- protected void associateContext(GLContext ctx, boolean bound) {
+ protected void associateContext(final GLContext ctx, final boolean bound) {
// NOTE: we need to keep track of the created contexts in order to
// implement swapBuffers() because of how Mac OS X implements its
// OpenGL window interface
synchronized (createdContexts) {
if(bound) {
- createdContexts.add(new WeakReference<MacOSXCGLContext>((MacOSXCGLContext)ctx));
+ final MacOSXCGLContext osxCtx = (MacOSXCGLContext)ctx;
+ createdContexts.add(new WeakReference<MacOSXCGLContext>(osxCtx));
} else {
for(int i=0; i<createdContexts.size(); ) {
- final WeakReference<MacOSXCGLContext> ref = createdContexts.get(i);
- final MacOSXCGLContext _ctx = ref.get();
+ final MacOSXCGLContext _ctx = createdContexts.get(i).get();
if( _ctx == null || _ctx == ctx) {
createdContexts.remove(i);
} else {
i++;
}
- }
+ }
}
- }
+ }
}
-
+
@Override
- protected final void swapBuffersImpl(boolean doubleBuffered) {
- if(doubleBuffered) {
+ protected final void swapBuffersImpl(final boolean doubleBuffered) {
+ if(doubleBuffered) {
synchronized (createdContexts) {
for(int i=0; i<createdContexts.size(); ) {
- final WeakReference<MacOSXCGLContext> ref = createdContexts.get(i);
- final MacOSXCGLContext ctx = ref.get();
+ final MacOSXCGLContext ctx = createdContexts.get(i).get();
if (ctx != null) {
ctx.swapBuffers();
i++;
@@ -155,12 +153,8 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
return getFactoryImpl().getGLDynamicLookupHelper(0);
}
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
-
// Support for "mode switching" as described in MacOSXCGLDrawable
- public void setOpenGLMode(GLBackendType mode) {
+ public void setOpenGLMode(final GLBackendType mode) {
if (mode == openGLMode) {
return;
}
@@ -177,6 +171,6 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
}
public final GLBackendType getOpenGLMode() { return openGLMode; }
- protected void initOpenGLImpl(GLBackendType backend) { /* nop */ }
+ protected void initOpenGLImpl(final GLBackendType backend) { /* nop */ }
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index e174d38f4..045abca4c 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -41,11 +41,12 @@
package jogamp.opengl.macosx.cgl;
import java.nio.Buffer;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.DefaultGraphicsScreen;
@@ -69,12 +70,14 @@ import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
import jogamp.opengl.GLGraphicsConfigurationUtil;
+import jogamp.opengl.SharedResourceRunner;
-import com.jogamp.common.JogampRuntimeException;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
private static DesktopGLDynamicLookupHelper macOSXCGLDynamicLookupHelper = null;
@@ -87,7 +90,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
DesktopGLDynamicLookupHelper tmp = null;
try {
tmp = new DesktopGLDynamicLookupHelper(new MacOSXCGLDynamicLibraryBundleInfo());
- } catch (GLException gle) {
+ } catch (final GLException gle) {
if(DEBUG) {
gle.printStackTrace();
}
@@ -111,7 +114,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
try {
ReflectionUtil.callStaticMethod("jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLGraphicsConfigurationFactory",
"registerFactory", null, null, getClass().getClassLoader());
- } catch (JogampRuntimeException jre) { /* n/a .. */ }
+ } catch (final Exception jre) { /* n/a .. */ }
}
sharedMap = new HashMap<String, SharedResource>();
@@ -122,9 +125,12 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
protected final boolean isComplete() {
return null != macOSXCGLDynamicLookupHelper;
}
-
+
@Override
- protected final void destroy() {
+ protected final void shutdownImpl() {
+ if( DEBUG ) {
+ System.err.println("MacOSXCGLDrawableFactory.shutdown");
+ }
if(null != sharedMap) {
sharedMap.clear();
sharedMap = null;
@@ -139,38 +145,61 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) {
+ public GLDynamicLookupHelper getGLDynamicLookupHelper(final int profile) {
return macOSXCGLDynamicLookupHelper;
}
private HashMap<String, SharedResource> sharedMap = new HashMap<String, SharedResource>();
private MacOSXGraphicsDevice defaultDevice;
- static class SharedResource {
+ static class SharedResource implements SharedResourceRunner.Resource {
// private MacOSXCGLDrawable drawable;
// private MacOSXCGLContext context;
+ private final GLRendererQuirks glRendererQuirks;
MacOSXGraphicsDevice device;
- boolean wasContextCreated;
+ boolean valid;
boolean hasNPOTTextures;
boolean hasRECTTextures;
boolean hasAppleFloatPixels;
- SharedResource(MacOSXGraphicsDevice device, boolean wasContextCreated,
- boolean hasNPOTTextures, boolean hasRECTTextures, boolean hasAppletFloatPixels
- /* MacOSXCGLDrawable draw, MacOSXCGLContext ctx */) {
+ SharedResource(final MacOSXGraphicsDevice device, final boolean valid,
+ final boolean hasNPOTTextures, final boolean hasRECTTextures, final boolean hasAppletFloatPixels
+ /* MacOSXCGLDrawable draw, MacOSXCGLContext ctx */, final GLRendererQuirks glRendererQuirks) {
// drawable = draw;
- // context = ctx;
+ // this.context = ctx;
+ this.glRendererQuirks = glRendererQuirks;
this.device = device;
- this.wasContextCreated = wasContextCreated;
+ this.valid = valid;
this.hasNPOTTextures = hasNPOTTextures;
this.hasRECTTextures = hasRECTTextures;
this.hasAppleFloatPixels = hasAppletFloatPixels;
}
- final MacOSXGraphicsDevice getDevice() { return device; }
- final boolean wasContextAvailable() { return wasContextCreated; }
+ @Override
+ public final boolean isValid() {
+ return valid;
+ }
+ @Override
+ public final MacOSXGraphicsDevice getDevice() { return device; }
+ // final MacOSXCGLContext getContext() { return context; }
final boolean isNPOTTextureAvailable() { return hasNPOTTextures; }
final boolean isRECTTextureAvailable() { return hasRECTTextures; }
final boolean isAppleFloatPixelsAvailable() { return hasAppleFloatPixels; }
+ @Override
+ public final AbstractGraphicsScreen getScreen() {
+ return null;
+ }
+ @Override
+ public final GLDrawableImpl getDrawable() {
+ return null;
+ }
+ @Override
+ public GLContextImpl getContext() {
+ return null;
+ }
+ @Override
+ public GLRendererQuirks getRendererQuirks() {
+ return glRendererQuirks;
+ }
}
@Override
@@ -179,32 +208,33 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) {
+ public final boolean getIsDeviceCompatible(final AbstractGraphicsDevice device) {
if(null!=macOSXCGLDynamicLookupHelper && device instanceof MacOSXGraphicsDevice) {
return true;
}
return false;
}
- private HashSet<String> devicesTried = new HashSet<String>();
+ private final HashSet<String> devicesTried = new HashSet<String>();
- private boolean getDeviceTried(String connection) {
+ private boolean getDeviceTried(final String connection) {
synchronized (devicesTried) {
return devicesTried.contains(connection);
}
}
- private void addDeviceTried(String connection) {
+ private void addDeviceTried(final String connection) {
synchronized (devicesTried) {
devicesTried.add(connection);
}
}
- private void removeDeviceTried(String connection) {
+ private void removeDeviceTried(final String connection) {
synchronized (devicesTried) {
devicesTried.remove(connection);
}
}
- /* package */ SharedResource getOrCreateOSXSharedResource(AbstractGraphicsDevice adevice) {
+ @Override
+ protected final SharedResource getOrCreateSharedResourceImpl(final AbstractGraphicsDevice adevice) {
final String connection = adevice.getConnection();
SharedResource sr;
synchronized(sharedMap) {
@@ -213,58 +243,61 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
if(null==sr && !getDeviceTried(connection)) {
addDeviceTried(connection);
final MacOSXGraphicsDevice sharedDevice = new MacOSXGraphicsDevice(adevice.getUnitID());
- boolean madeCurrent = false;
+ GLRendererQuirks glRendererQuirks = null;
+ boolean isValid = false;
boolean hasNPOTTextures = false;
boolean hasRECTTextures = false;
boolean hasAppleFloatPixels = false;
{
- GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
+ final GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
if (null == glp) {
throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
}
- final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64));
+ final GLCapabilitiesImmutable caps = new GLCapabilities(glp);
+ final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, caps, caps, null, 64, 64));
sharedDrawable.setRealized(true);
-
- final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null);
+
+ final MacOSXCGLContext sharedContext = (MacOSXCGLContext) sharedDrawable.createContext(null);
if (null == sharedContext) {
throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
}
-
+
try {
sharedContext.makeCurrent(); // could cause exception
- madeCurrent = sharedContext.isCurrent();
- if(madeCurrent) {
- GL gl = sharedContext.getGL();
+ isValid = sharedContext.isCurrent();
+ if(isValid) {
+ final GL gl = sharedContext.getGL();
hasNPOTTextures = gl.isNPOTTextureAvailable();
hasRECTTextures = gl.isExtensionAvailable(GLExtensions.EXT_texture_rectangle);
hasAppleFloatPixels = gl.isExtensionAvailable(GLExtensions.APPLE_float_pixels);
+ glRendererQuirks = sharedContext.getRendererQuirks();
}
- } catch (GLException gle) {
+ } catch (final GLException gle) {
if (DEBUG) {
- System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent catched exception:");
+ System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent caught exception:");
gle.printStackTrace();
}
} finally {
try {
sharedContext.destroy();
- } catch (GLException gle) {
+ } catch (final GLException gle) {
if (DEBUG) {
- System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: destroy catched exception:");
+ System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: destroy caught exception:");
gle.printStackTrace();
}
}
}
sharedDrawable.setRealized(false);
}
- sr = new SharedResource(sharedDevice, madeCurrent, hasNPOTTextures, hasRECTTextures, hasAppleFloatPixels);
+ sr = new SharedResource(sharedDevice, isValid, hasNPOTTextures, hasRECTTextures, hasAppleFloatPixels, glRendererQuirks);
synchronized(sharedMap) {
sharedMap.put(connection, sr);
}
removeDeviceTried(connection);
if (DEBUG) {
System.err.println("MacOSXCGLDrawableFactory.createShared: device: " + sharedDevice);
- System.err.println("MacOSXCGLDrawableFactory.createShared: context: madeCurrent " + madeCurrent + ", NPOT "+hasNPOTTextures+
- ", RECT "+hasRECTTextures+", FloatPixels "+hasAppleFloatPixels);
+ System.err.println("MacOSXCGLDrawableFactory.createShared: context: madeCurrent " + isValid + ", NPOT "+hasNPOTTextures+
+ ", RECT "+hasRECTTextures+", FloatPixels "+hasAppleFloatPixels+", "+glRendererQuirks);
}
}
return sr;
@@ -276,43 +309,12 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final boolean createSharedResource(AbstractGraphicsDevice device) {
- try {
- SharedResource sr = getOrCreateOSXSharedResource(device);
- if(null!=sr) {
- return sr.wasContextAvailable();
- }
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("Catched Exception while MaxOSXCGL Shared Resource initialization:");
- gle.printStackTrace();
- }
- }
- return false;
- }
-
- @Override
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- // FIXME: not implemented .. needs a dummy OSX surface
- return null;
- }
-
- @Override
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResource sr = getOrCreateOSXSharedResource(device);
- if(null!=sr) {
- return sr.getDevice();
- }
- return null;
- }
-
- @Override
- protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
+ protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(final AbstractGraphicsDevice device) {
return MacOSXCGLGraphicsConfiguration.getAvailableCapabilities(this, device);
}
@Override
- protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) {
+ protected GLDrawableImpl createOnscreenDrawableImpl(final NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
@@ -320,7 +322,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) {
+ protected GLDrawableImpl createOffscreenDrawableImpl(final NativeSurface target) {
final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration();
final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
if(!caps.isPBuffer()) {
@@ -335,16 +337,21 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
- return true;
+ public boolean canCreateGLPbuffer(final AbstractGraphicsDevice device, final GLProfile glp) {
+ if( glp.isGL2() ) {
+ // OSX only supports pbuffer w/ compatible, non-core, context.
+ return true;
+ } else {
+ return false;
+ }
}
@Override
- protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
- GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) {
+ protected ProxySurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstreamHook) {
final MacOSXGraphicsDevice device;
- if(createNewDevice) {
+ if( createNewDevice || !(deviceReq instanceof MacOSXGraphicsDevice) ) {
device = new MacOSXGraphicsDevice(deviceReq.getUnitID());
} else {
device = (MacOSXGraphicsDevice)deviceReq;
@@ -352,24 +359,24 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
final MacOSXCGLGraphicsConfiguration config = MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, true);
if(null == config) {
- throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
- }
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ }
return new WrappedSurface(config, 0, upstreamHook, createNewDevice);
}
@Override
- public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
- GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
- final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
- return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser,
- new OSXDummyUpstreamSurfaceHook(width, height));
- }
-
+ public final ProxySurface createDummySurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) {
+ chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps);
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser,
+ new OSXDummyUpstreamSurfaceHook(width, height));
+ }
+
@Override
- protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ protected ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) {
final MacOSXGraphicsDevice device = new MacOSXGraphicsDevice(deviceReq.getUnitID());
final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
- final MacOSXCGLGraphicsConfiguration config = MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true);
+ final MacOSXCGLGraphicsConfiguration config = MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true);
return new WrappedSurface(config, windowHandle, upstream, true);
}
@@ -379,7 +386,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) {
+ public boolean canCreateExternalGLDrawable(final AbstractGraphicsDevice device) {
return false;
}
@@ -389,17 +396,6 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
throw new GLException("Not yet implemented");
}
- @Override
- public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- @Override
- public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("not supported in non AWT enviroment");
- }
-
//------------------------------------------------------
// Gamma-related functionality
//
@@ -409,25 +405,29 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
/** Returns the length of the computed gamma ramp for this OS and
hardware. Returns 0 if gamma changes are not supported. */
@Override
- protected int getGammaRampLength() {
+ protected int getGammaRampLength(final NativeSurface surface) {
return GAMMA_RAMP_LENGTH;
}
@Override
- protected boolean setGammaRamp(float[] ramp) {
- return CGL.setGammaRamp(ramp.length,
- ramp, 0,
- ramp, 0,
- ramp, 0);
+ protected boolean setGammaRamp(final NativeSurface surface, final float[] ramp) {
+ final FloatBuffer rampNIO = Buffers.newDirectFloatBuffer(ramp);
+ return CGL.setGammaRamp(ramp.length, rampNIO, rampNIO, rampNIO);
}
@Override
- protected Buffer getGammaRamp() {
- return null;
+ protected Buffer getGammaRamp(final NativeSurface surface) {
+ return ShortBuffer.allocate(0); // return a dummy gamma ramp default for reset
}
@Override
- protected void resetGammaRamp(Buffer originalGammaRamp) {
+ protected void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) {
CGL.resetGammaRamp();
}
+
+ @Override
+ protected final void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) {
+ CGL.resetGammaRamp();
+ }
+
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
index 03ec94db6..3ec40ffce 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,35 +20,35 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl.macosx.cgl;
import jogamp.opengl.*;
import java.util.*;
-public class MacOSXCGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
+public final class MacOSXCGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
protected MacOSXCGLDynamicLibraryBundleInfo() {
super();
}
@Override
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsGL = new ArrayList<String>();
libsGL.add("/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib");
libsGL.add("GL");
- libsList.add(libsGL);
+ libsList.add(libsGL);
return libsList;
}
-
+
@Override
public final List<String> getToolGetProcAddressFuncNameList() {
- return null;
+ return null;
/** OSX manual says: NSImage use is discouraged
List res = new ArrayList();
res.add("GetProcAddress"); // dummy
@@ -56,10 +56,10 @@ public class MacOSXCGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBu
}
@Override
- public final long toolGetProcAddress(long toolGetProcAddressHandle, String funcName) {
+ public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) {
return 0;
/** OSX manual says: NSImage use is discouraged
- return CGL.getProcAddress(glFuncName); // manual implementation
+ return CGL.getProcAddress(glFuncName); // manual implementation
*/
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
index 8866c7ce6..cd89ad526 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,13 +29,14 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package jogamp.opengl.macosx.cgl;
+import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
@@ -46,33 +47,34 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
-
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {
- MacOSXCGLGraphicsConfiguration(AbstractGraphicsScreen screen,
- GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested) {
+ MacOSXCGLGraphicsConfiguration(final AbstractGraphicsScreen screen,
+ final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested) {
super(screen, capsChosen, capsRequested);
}
+ @Override
public Object clone() {
return super.clone();
}
- protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(MacOSXCGLDrawableFactory factory, AbstractGraphicsDevice device) {
- MacOSXCGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateOSXSharedResource(device);
+ protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(final MacOSXCGLDrawableFactory factory, final AbstractGraphicsDevice device) {
+ final MacOSXCGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
// MacOSXGraphicsDevice osxDevice = sharedResource.getDevice();
return new ArrayList<GLCapabilitiesImmutable>(0);
}
-
- static final int[] cglInternalAttributeToken = new int[] {
+
+ static final IntBuffer cglInternalAttributeToken = Buffers.newDirectIntBuffer(new int[] {
CGL.kCGLPFAOpenGLProfile, // >= lion
- CGL.NSOpenGLPFAAccelerated, // query only (prefer accelerated, but allow non accelerated), ignored for createPixelformat
+ CGL.NSOpenGLPFAAccelerated, // query only (prefer accelerated, but allow non accelerated), ignored for createPixelformat
CGL.NSOpenGLPFANoRecovery,
CGL.kCGLPFAColorFloat,
CGL.NSOpenGLPFAPixelBuffer,
@@ -84,70 +86,66 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
CGL.NSOpenGLPFAAccumSize,
CGL.NSOpenGLPFAStencilSize,
CGL.NSOpenGLPFASampleBuffers,
- CGL.NSOpenGLPFASamples };
+ CGL.NSOpenGLPFASamples });
- static int[] GLCapabilities2NSAttribList(GLCapabilitiesImmutable caps, int ctp, int major, int minor) {
- int len = cglInternalAttributeToken.length;
- int off = 0;
- if ( !MacOSXCGLContext.isLionOrLater ) {
- // no OpenGLProfile
- off++;
- len--;
- }
- int[] ivalues = new int[len];
+ static IntBuffer GLCapabilities2NSAttribList(final AbstractGraphicsDevice device, final IntBuffer attrToken, final GLCapabilitiesImmutable caps, final int ctp, final int major, final int minor) {
+ final int len = attrToken.remaining();
+ final int off = attrToken.position();
+ final IntBuffer ivalues = Buffers.newDirectIntBuffer(len);
for (int idx = 0; idx < len; idx++) {
- final int attr = cglInternalAttributeToken[idx+off];
+ final int attr = attrToken.get(idx+off);
switch (attr) {
- case CGL.kCGLPFAOpenGLProfile:
- ivalues[idx] = MacOSXCGLContext.GLProfile2CGLOGLProfileValue(ctp, major, minor);
+ case CGL.kCGLPFAOpenGLProfile:
+ ivalues.put(idx, MacOSXCGLContext.GLProfile2CGLOGLProfileValue(device, ctp, major, minor));
break;
case CGL.NSOpenGLPFANoRecovery:
- ivalues[idx] = caps.getHardwareAccelerated() ? 1 : 0;
+ ivalues.put(idx, caps.getHardwareAccelerated() ? 1 : 0);
break;
-
+
case CGL.kCGLPFAColorFloat:
- ivalues[idx] = ( !caps.isOnscreen() && caps.isPBuffer() && caps.getPbufferFloatingPointBuffers() ) ? 1 : 0;
+ // ivalues.put(idx, ( !caps.isOnscreen() && caps.isPBuffer() && caps.getPbufferFloatingPointBuffers() ) ? 1 : 0);
+ ivalues.put(idx, 0);
break;
case CGL.NSOpenGLPFAPixelBuffer:
- ivalues[idx] = ( !caps.isOnscreen() && caps.isPBuffer() ) ? 1 : 0;
+ ivalues.put(idx, ( !caps.isOnscreen() && caps.isPBuffer() ) ? 1 : 0);
break;
case CGL.NSOpenGLPFADoubleBuffer:
- ivalues[idx] = (caps.getDoubleBuffered() ? 1 : 0);
+ ivalues.put(idx, (caps.getDoubleBuffered() ? 1 : 0));
break;
case CGL.NSOpenGLPFAStereo:
- ivalues[idx] = (caps.getStereo() ? 1 : 0);
+ ivalues.put(idx, (caps.getStereo() ? 1 : 0));
break;
case CGL.NSOpenGLPFAColorSize:
- ivalues[idx] = (caps.getRedBits() + caps.getGreenBits() + caps.getBlueBits());
+ ivalues.put(idx, (caps.getRedBits() + caps.getGreenBits() + caps.getBlueBits()));
break;
case CGL.NSOpenGLPFAAlphaSize:
- ivalues[idx] = caps.getAlphaBits();
+ ivalues.put(idx, caps.getAlphaBits());
break;
case CGL.NSOpenGLPFADepthSize:
- ivalues[idx] = caps.getDepthBits();
+ ivalues.put(idx, caps.getDepthBits());
break;
case CGL.NSOpenGLPFAAccumSize:
- ivalues[idx] = (caps.getAccumRedBits() + caps.getAccumGreenBits() + caps.getAccumBlueBits() + caps.getAccumAlphaBits());
+ ivalues.put(idx, (caps.getAccumRedBits() + caps.getAccumGreenBits() + caps.getAccumBlueBits() + caps.getAccumAlphaBits()));
break;
case CGL.NSOpenGLPFAStencilSize:
- ivalues[idx] = caps.getStencilBits();
+ ivalues.put(idx, caps.getStencilBits());
break;
case CGL.NSOpenGLPFASampleBuffers:
- ivalues[idx] = caps.getSampleBuffers() ? 1 : 0;
+ ivalues.put(idx, caps.getSampleBuffers() ? 1 : 0);
break;
case CGL.NSOpenGLPFASamples:
- ivalues[idx] = caps.getNumSamples() ;
+ ivalues.put(idx, caps.getNumSamples());
break;
default:
@@ -157,117 +155,124 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
return ivalues;
}
- static long GLCapabilities2NSPixelFormat(GLCapabilitiesImmutable caps, int ctp, int major, int minor) {
- int len = cglInternalAttributeToken.length;
- int off = 0;
+ static long GLCapabilities2NSPixelFormat(final AbstractGraphicsDevice device, final GLCapabilitiesImmutable caps, final int ctp, final int major, final int minor) {
+ final IntBuffer attrToken = cglInternalAttributeToken.duplicate();
if ( !MacOSXCGLContext.isLionOrLater ) {
// no OpenGLProfile
- off++;
- len--;
- }
- int[] ivalues = GLCapabilities2NSAttribList(caps, ctp, major, minor);
- return CGL.createPixelFormat(cglInternalAttributeToken, off, len, ivalues, 0);
+ attrToken.position(1);
+ }
+ final IntBuffer ivalues = GLCapabilities2NSAttribList(device, attrToken, caps, ctp, major, minor);
+ return CGL.createPixelFormat(attrToken, attrToken.remaining(), ivalues);
}
- static GLCapabilities NSPixelFormat2GLCapabilities(GLProfile glp, long pixelFormat) {
+ static GLCapabilities NSPixelFormat2GLCapabilities(final GLProfile glp, final long pixelFormat) {
return PixelFormat2GLCapabilities(glp, pixelFormat, true);
}
- static long GLCapabilities2CGLPixelFormat(GLCapabilitiesImmutable caps, int ctp, int major, int minor) {
+ static long GLCapabilities2CGLPixelFormat(final AbstractGraphicsDevice device, final GLCapabilitiesImmutable caps, final int ctp, final int major, final int minor) {
// Set up pixel format attributes
- int[] attrs = new int[256];
+ final IntBuffer attrs = Buffers.newDirectIntBuffer(256);
int i = 0;
if(MacOSXCGLContext.isLionOrLater) {
- attrs[i++] = CGL.kCGLPFAOpenGLProfile;
- attrs[i++] = MacOSXCGLContext.GLProfile2CGLOGLProfileValue(ctp, major, minor);
+ attrs.put(i++, CGL.kCGLPFAOpenGLProfile);
+ attrs.put(i++, MacOSXCGLContext.GLProfile2CGLOGLProfileValue(device, ctp, major, minor));
}
+ /**
if(!caps.isOnscreen() && caps.isPBuffer()) {
- attrs[i++] = CGL.kCGLPFAPBuffer;
+ attrs.put(i++, CGL.kCGLPFAPBuffer);
if (caps.getPbufferFloatingPointBuffers()) {
- attrs[i++] = CGL.kCGLPFAColorFloat;
+ attrs.put(i++, CGL.kCGLPFAColorFloat);
}
- }
+ } */
if (caps.getDoubleBuffered()) {
- attrs[i++] = CGL.kCGLPFADoubleBuffer;
+ attrs.put(i++, CGL.kCGLPFADoubleBuffer);
}
if (caps.getStereo()) {
- attrs[i++] = CGL.kCGLPFAStereo;
+ attrs.put(i++, CGL.kCGLPFAStereo);
}
- attrs[i++] = CGL.kCGLPFAColorSize;
- attrs[i++] = (caps.getRedBits() +
- caps.getGreenBits() +
- caps.getBlueBits());
- attrs[i++] = CGL.kCGLPFAAlphaSize;
- attrs[i++] = caps.getAlphaBits();
- attrs[i++] = CGL.kCGLPFADepthSize;
- attrs[i++] = caps.getDepthBits();
+ attrs.put(i++, CGL.kCGLPFAColorSize);
+ attrs.put(i++, ( caps.getRedBits() +
+ caps.getGreenBits() +
+ caps.getBlueBits() ) );
+ attrs.put(i++, CGL.kCGLPFAAlphaSize);
+ attrs.put(i++, caps.getAlphaBits());
+ attrs.put(i++, CGL.kCGLPFADepthSize);
+ attrs.put(i++, caps.getDepthBits());
// FIXME: should validate stencil size as is done in MacOSXWindowSystemInterface.m
- attrs[i++] = CGL.kCGLPFAStencilSize;
- attrs[i++] = caps.getStencilBits();
- attrs[i++] = CGL.kCGLPFAAccumSize;
- attrs[i++] = (caps.getAccumRedBits() +
- caps.getAccumGreenBits() +
- caps.getAccumBlueBits() +
- caps.getAccumAlphaBits());
+ attrs.put(i++, CGL.kCGLPFAStencilSize);
+ attrs.put(i++, caps.getStencilBits());
+ attrs.put(i++, CGL.kCGLPFAAccumSize);
+ attrs.put(i++, ( caps.getAccumRedBits() +
+ caps.getAccumGreenBits() +
+ caps.getAccumBlueBits() +
+ caps.getAccumAlphaBits() ) );
if (caps.getSampleBuffers()) {
- attrs[i++] = CGL.kCGLPFASampleBuffers;
- attrs[i++] = 1;
- attrs[i++] = CGL.kCGLPFASamples;
- attrs[i++] = caps.getNumSamples();
+ attrs.put(i++, CGL.kCGLPFASampleBuffers);
+ attrs.put(i++, 1);
+ attrs.put(i++, CGL.kCGLPFASamples);
+ attrs.put(i++, caps.getNumSamples());
}
// Use attribute array to select pixel format
- PointerBuffer fmt = PointerBuffer.allocateDirect(1);
- int[] numScreens = new int[1];
- int res = CGL.CGLChoosePixelFormat(attrs, 0, fmt, numScreens, 0);
+ final PointerBuffer fmt = PointerBuffer.allocateDirect(1);
+ final IntBuffer numScreens = Buffers.newDirectIntBuffer(1);
+ final int res = CGL.CGLChoosePixelFormat(attrs, fmt, numScreens);
if (res != CGL.kCGLNoError) {
throw new GLException("Error code " + res + " while choosing pixel format");
}
return fmt.get(0);
}
-
- static GLCapabilities CGLPixelFormat2GLCapabilities(long pixelFormat) {
+
+ static GLCapabilities CGLPixelFormat2GLCapabilities(final long pixelFormat) {
return PixelFormat2GLCapabilities(null, pixelFormat, false);
}
- private static GLCapabilities PixelFormat2GLCapabilities(GLProfile glp, long pixelFormat, boolean nsUsage) {
- int len = cglInternalAttributeToken.length;
- int off = 0;
+ private static GLCapabilities PixelFormat2GLCapabilities(GLProfile glp, final long pixelFormat, final boolean nsUsage) {
+ final IntBuffer attrToken = cglInternalAttributeToken.duplicate();
+ final int off;
if ( !MacOSXCGLContext.isLionOrLater ) {
// no OpenGLProfile
- off++;
- len--;
- }
- int[] ivalues = new int[len];
+ off = 1;
+ } else {
+ off = 0;
+ }
+ attrToken.position(off);
+ final int len = attrToken.remaining();
+ final IntBuffer ivalues = Buffers.newDirectIntBuffer(len);
// On this platform the pixel format is associated with the
// context and not the drawable. However it's a reasonable
// approximation to just store the chosen pixel format up in the
- // NativeSurface's AbstractGraphicsConfiguration,
+ // NativeSurface's AbstractGraphicsConfiguration,
// since the public API doesn't provide for a different GLCapabilities per context.
// Note: These restrictions of the platform's API might be considered as a bug anyways.
// Figure out what attributes we really got
if(nsUsage) {
- CGL.queryPixelFormat(pixelFormat, cglInternalAttributeToken, off, len, ivalues, 0);
+ CGL.queryPixelFormat(pixelFormat, attrToken, len, ivalues);
} else {
- CGL.CGLQueryPixelFormat(pixelFormat, cglInternalAttributeToken, off, len, ivalues, 0);
+ CGL.CGLQueryPixelFormat(pixelFormat, attrToken, len, ivalues);
}
+
if(null == glp && MacOSXCGLContext.isLionOrLater) {
// pre-scan for OpenGL Profile
for (int i = 0; i < len; i++) {
- if(CGL.kCGLPFAOpenGLProfile == cglInternalAttributeToken[i+off]) {
- switch(ivalues[i]) {
- case CGL.kCGLOGLPVersion_3_2_Core:
+ final int ivalue = ivalues.get(i);
+ if(CGL.kCGLPFAOpenGLProfile == attrToken.get(i+off)) {
+ switch(ivalue) {
+ case CGL.kCGLOGLPVersion_GL4_Core:
+ glp = GLProfile.get(GLProfile.GL4);
+ break;
+ case CGL.kCGLOGLPVersion_GL3_Core:
glp = GLProfile.get(GLProfile.GL3);
break;
case CGL.kCGLOGLPVersion_Legacy:
glp = GLProfile.get(GLProfile.GL2);
- break;
+ break;
default:
- throw new RuntimeException("Unhandled OSX OpenGL Profile: 0x"+Integer.toHexString(ivalues[i]));
+ throw new RuntimeException("Unhandled OSX OpenGL Profile: 0x"+Integer.toHexString(ivalue));
}
- }
+ }
}
}
if(null == glp) {
@@ -276,34 +281,32 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
final GLCapabilities caps = new GLCapabilities(glp);
int alphaBits = 0;
for (int i = 0; i < len; i++) {
- int attr = cglInternalAttributeToken[i+off];
+ final int attr = attrToken.get(i+off);
+ final int ivalue = ivalues.get(i);
switch (attr) {
case CGL.NSOpenGLPFAAccelerated:
- caps.setHardwareAccelerated(ivalues[i] != 0);
+ caps.setHardwareAccelerated(ivalue != 0);
break;
-
+
case CGL.kCGLPFAColorFloat:
- caps.setPbufferFloatingPointBuffers(ivalues[i] != 0);
+ // caps.setPbufferFloatingPointBuffers(ivalue != 0);
break;
case CGL.NSOpenGLPFAPixelBuffer:
- caps.setPBuffer(ivalues[i] != 0);
+ caps.setPBuffer(ivalue != 0);
break;
case CGL.NSOpenGLPFADoubleBuffer:
- caps.setDoubleBuffered(ivalues[i] != 0);
+ caps.setDoubleBuffered(ivalue != 0);
break;
case CGL.NSOpenGLPFAStereo:
- caps.setStereo(ivalues[i] != 0);
+ caps.setStereo(ivalue != 0);
break;
case CGL.NSOpenGLPFAColorSize:
{
- int bitSize = ivalues[i];
- if (bitSize == 32)
- bitSize = 24;
- bitSize /= 3;
+ final int bitSize = ( 32 == ivalue ? 24 : ivalue ) / 3;
caps.setRedBits(bitSize);
caps.setGreenBits(bitSize);
caps.setBlueBits(bitSize);
@@ -312,16 +315,16 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
case CGL.NSOpenGLPFAAlphaSize:
// ALPHA shall be set at last - due to it's auto setting by !opaque / samples
- alphaBits = ivalues[i];
+ alphaBits = ivalue;
break;
case CGL.NSOpenGLPFADepthSize:
- caps.setDepthBits(ivalues[i]);
+ caps.setDepthBits(ivalue);
break;
case CGL.NSOpenGLPFAAccumSize:
{
- int bitSize = ivalues[i] / 4;
+ final int bitSize = ivalue / 4;
caps.setAccumRedBits(bitSize);
caps.setAccumGreenBits(bitSize);
caps.setAccumBlueBits(bitSize);
@@ -330,15 +333,15 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
break;
case CGL.NSOpenGLPFAStencilSize:
- caps.setStencilBits(ivalues[i]);
+ caps.setStencilBits(ivalue);
break;
case CGL.NSOpenGLPFASampleBuffers:
- caps.setSampleBuffers(ivalues[i] != 0);
+ caps.setSampleBuffers(ivalue != 0);
break;
case CGL.NSOpenGLPFASamples:
- caps.setNumSamples(ivalues[i]);
+ caps.setNumSamples(ivalue);
break;
default:
@@ -346,7 +349,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
}
}
caps.setAlphaBits(alphaBits);
-
+
return caps;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java
index 43a9d0d1a..50de70227 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -35,7 +35,6 @@ package jogamp.opengl.macosx.cgl;
import jogamp.opengl.GLGraphicsConfigurationFactory;
import jogamp.opengl.GLGraphicsConfigurationUtil;
-import jogamp.opengl.x11.glx.X11GLXDrawableFactory;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -45,7 +44,6 @@ import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
-import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
@@ -58,13 +56,14 @@ public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurati
static void registerFactory() {
GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice.class, GLCapabilitiesImmutable.class, new MacOSXCGLGraphicsConfigurationFactory());
}
- private MacOSXCGLGraphicsConfigurationFactory() {
+ private MacOSXCGLGraphicsConfigurationFactory() {
}
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
-
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser, final AbstractGraphicsScreen absScreen, final int nativeVisualID) {
+
if (absScreen == null) {
throw new IllegalArgumentException("AbstractGraphicsScreen is null");
}
@@ -80,22 +79,20 @@ public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurati
if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects");
}
-
+
return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, (GLCapabilitiesChooser)chooser, absScreen, false);
}
static MacOSXCGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
- GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- AbstractGraphicsScreen absScreen, boolean usePBuffer) {
+ final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser,
+ final AbstractGraphicsScreen absScreen, final boolean usePBuffer) {
if (absScreen == null) {
throw new IllegalArgumentException("AbstractGraphicsScreen is null");
}
- final MacOSXCGLDrawableFactory factory = (MacOSXCGLDrawableFactory) GLDrawableFactory.getDesktopFactory();
final AbstractGraphicsDevice device = absScreen.getDevice();
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLDrawableFactory.getDesktopFactory(), device);
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(device, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(device) );
-
- return new MacOSXCGLGraphicsConfiguration(absScreen, (GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested);
+ return new MacOSXCGLGraphicsConfiguration(absScreen, capsChosen, capsRequested);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
index 65ed5fc15..c17ed7d59 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
@@ -49,32 +49,31 @@ import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
-
import jogamp.nativewindow.WrappedSurface;
-import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLContextShareSet;
import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType;
public class MacOSXExternalCGLContext extends MacOSXCGLContext {
- private GLContext lastContext;
- private MacOSXExternalCGLContext(Drawable drawable, boolean isNSContext, long handle) {
+ private MacOSXExternalCGLContext(final Drawable drawable, final boolean isNSContext, final long handle) {
super(drawable, null);
setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL );
this.contextHandle = handle;
GLContextShareSet.contextCreated(this);
- setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT);
+ if( !setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION
+ throw new InternalError("setGLFunctionAvailability !strictMatch failed");
+ }
getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
}
- protected static MacOSXExternalCGLContext create(GLDrawableFactory factory) {
+ protected static MacOSXExternalCGLContext create(final GLDrawableFactory factory) {
long pixelFormat = 0;
long currentDrawable = 0;
long contextHandle = CGL.getCurrentContext(); // Check: MacOSX 10.3 ..
- boolean isNSContext = 0 != contextHandle;
+ final boolean isNSContext = 0 != contextHandle;
if( isNSContext ) {
- long ctx = CGL.getCGLContext(contextHandle);
+ final long ctx = CGL.getCGLContext(contextHandle);
if (ctx == 0) {
throw new GLException("Error: NULL Context (CGL) of Context (NS) 0x" +Long.toHexString(contextHandle));
}
@@ -101,47 +100,28 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext {
if (0 == pixelFormat) {
throw new GLException("Error: current pixelformat of current Context 0x"+Long.toHexString(contextHandle)+" is null");
}
- GLCapabilitiesImmutable caps = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(pixelFormat);
+ final GLCapabilitiesImmutable caps = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(pixelFormat);
if(DEBUG) {
System.err.println("MacOSXExternalCGLContext Create "+caps);
}
- AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_MACOSX);
- MacOSXCGLGraphicsConfiguration cfg = new MacOSXCGLGraphicsConfiguration(aScreen, caps, caps);
+ final AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_MACOSX);
+ final MacOSXCGLGraphicsConfiguration cfg = new MacOSXCGLGraphicsConfiguration(aScreen, caps, caps);
if(0 == currentDrawable) {
// set a fake marker stating a valid drawable
currentDrawable = 1;
}
- WrappedSurface ns = new WrappedSurface(cfg, currentDrawable, 64, 64, true);
+ final WrappedSurface ns = new WrappedSurface(cfg, currentDrawable, 64, 64, true);
return new MacOSXExternalCGLContext(new Drawable(factory, ns), isNSContext, contextHandle);
}
@Override
- protected boolean createImpl(GLContextImpl shareWith) throws GLException {
+ protected boolean createImpl(final long shareWithHandle) throws GLException {
return true;
}
@Override
- public int makeCurrent() throws GLException {
- // Save last context if necessary to allow external GLContexts to
- // talk to other GLContexts created by this library
- GLContext cur = getCurrent();
- if (cur != null && cur != this) {
- lastContext = cur;
- setCurrent(null);
- }
- return super.makeCurrent();
- }
-
- @Override
- public void release() throws GLException {
- super.release();
- setCurrent(lastContext);
- lastContext = null;
- }
-
- @Override
protected void makeCurrentImpl() throws GLException {
}
@@ -155,26 +135,26 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext {
// Need to provide the display connection to extension querying APIs
static class Drawable extends MacOSXCGLDrawable {
- Drawable(GLDrawableFactory factory, NativeSurface comp) {
+ Drawable(final GLDrawableFactory factory, final NativeSurface comp) {
super(factory, comp, true);
}
@Override
- public GLContext createContext(GLContext shareWith) {
+ public GLContext createContext(final GLContext shareWith) {
throw new GLException("Should not call this");
}
@Override
- public int getWidth() {
+ public int getSurfaceWidth() {
throw new GLException("Should not call this");
}
@Override
- public int getHeight() {
+ public int getSurfaceHeight() {
throw new GLException("Should not call this");
}
- public void setSize(int width, int height) {
+ public void setSize(final int width, final int height) {
throw new GLException("Should not call this");
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
deleted file mode 100644
index 7b13ce22e..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.macosx.cgl;
-
-import javax.media.opengl.*;
-
-public class MacOSXOffscreenCGLContext extends MacOSXPbufferCGLContext
-{
- public MacOSXOffscreenCGLContext(MacOSXPbufferCGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public int getOffscreenContextPixelDataType() {
- GL gl = getGL();
- return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
- }
-
- @Override
- public int getOffscreenContextReadBuffer() {
- return GL.GL_FRONT;
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- return true;
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java
index 4f9005504..c613efa63 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java
@@ -46,13 +46,13 @@ import javax.media.opengl.GLDrawableFactory;
public class MacOSXOffscreenCGLDrawable extends MacOSXPbufferCGLDrawable {
- public MacOSXOffscreenCGLDrawable(GLDrawableFactory factory,
- NativeSurface target) {
+ public MacOSXOffscreenCGLDrawable(final GLDrawableFactory factory,
+ final NativeSurface target) {
super(factory, target);
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new MacOSXOffscreenCGLContext(this, shareWith);
+ public GLContext createContext(final GLContext shareWith) {
+ return new MacOSXCGLContext(this, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
deleted file mode 100644
index 447d18f68..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.macosx.cgl;
-
-import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.ProxySurface;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
-
-import jogamp.opengl.GLContextImpl;
-
-public class MacOSXOnscreenCGLContext extends MacOSXCGLContext {
-
- public MacOSXOnscreenCGLContext(MacOSXOnscreenCGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- protected void makeCurrentImpl() throws GLException {
- super.makeCurrentImpl();
- drawableUpdatedNotify();
- }
-
- @Override
- protected void drawableUpdatedNotify() throws GLException {
- final int w = drawable.getWidth();
- final int h = drawable.getHeight();
- final boolean updateContext = ( 0!=updateHandle && CGL.updateContextNeedsUpdate(updateHandle) ) ||
- w != lastWidth || h != lastHeight;
- if(updateContext) {
- lastWidth = w;
- lastHeight = h;
- if (contextHandle == 0) {
- throw new GLException("Context not created");
- }
- CGL.updateContext(contextHandle);
- }
- }
-
- @Override
- protected boolean createImpl(GLContextImpl sharedWith) {
- boolean res = super.createImpl(sharedWith);
- lastWidth = -1;
- lastHeight = -1;
- if(res && isNSContext()) {
- if(0 != updateHandle) {
- throw new InternalError("XXX1");
- }
- final boolean incompleteView;
- final NativeSurface surface = drawable.getNativeSurface();
- if( surface instanceof ProxySurface ) {
- incompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
- } else {
- incompleteView = false;
- }
- if(!incompleteView) {
- updateHandle = CGL.updateContextRegister(contextHandle, drawable.getHandle());
- if(0 == updateHandle) {
- throw new InternalError("XXX2");
- }
- }
- }
- return res;
- }
-
- @Override
- protected void destroyImpl() throws GLException {
- if ( 0 != updateHandle ) {
- CGL.updateContextUnregister(updateHandle);
- updateHandle = 0;
- }
- super.destroyImpl();
- }
-
- private long updateHandle = 0;
- private int lastWidth, lastHeight;
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java
index ec9628004..e9ea2ff61 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java
@@ -46,13 +46,13 @@ import javax.media.opengl.GLDrawableFactory;
public class MacOSXOnscreenCGLDrawable extends MacOSXCGLDrawable {
- protected MacOSXOnscreenCGLDrawable(GLDrawableFactory factory, NativeSurface component) {
+ protected MacOSXOnscreenCGLDrawable(final GLDrawableFactory factory, final NativeSurface component) {
super(factory, component, false);
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new MacOSXOnscreenCGLContext(this, shareWith);
+ public GLContext createContext(final GLContext shareWith) {
+ return new MacOSXCGLContext(this, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java
deleted file mode 100644
index 7e2d8cf10..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- */
-
-package jogamp.opengl.macosx.cgl;
-
-import javax.media.opengl.GL;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLPbuffer;
-
-import jogamp.opengl.GLContextImpl;
-
-@SuppressWarnings("deprecation")
-public class MacOSXPbufferCGLContext extends MacOSXCGLContext {
-
- // State for render-to-texture and render-to-texture-rectangle support
- private int texture; // actual texture object
-
- public MacOSXPbufferCGLContext(MacOSXPbufferCGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public void bindPbufferToTexture() {
- GL gl = getGL();
- gl.glBindTexture(((MacOSXPbufferCGLDrawable)drawable).getTextureTarget(), texture);
- // FIXME: not clear whether this is really necessary, but since
- // the API docs seem to imply it is and since it doesn't seem to
- // impact performance, leaving it in
- CGL.setContextTextureImageToPBuffer(contextHandle, drawable.getHandle(), GL.GL_FRONT);
- }
-
- @Override
- public void releasePbufferFromTexture() {
- }
-
- @Override
- protected boolean createImpl(GLContextImpl shareWith) {
- boolean res = super.createImpl(shareWith);
- if(res) {
- // Initialize render-to-texture support if requested
- final GL gl = getGL();
- final MacOSXPbufferCGLDrawable osxPDrawable = (MacOSXPbufferCGLDrawable)drawable;
- final int textureTarget = osxPDrawable.getTextureTarget();
-
- int[] tmp = new int[1];
- gl.glGenTextures(1, tmp, 0);
- texture = tmp[0];
- gl.glBindTexture(textureTarget, texture);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
- gl.glTexImage2D(textureTarget, 0, GL.GL_RGB, osxPDrawable.getTextureWidth(), osxPDrawable.getTextureHeight(),
- 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, null);
- gl.glCopyTexSubImage2D(textureTarget, 0, 0, 0, 0, 0, drawable.getWidth(), drawable.getHeight());
- }
- return res;
- }
-
- @Override
- public int getFloatingPointMode() {
- return GLPbuffer.APPLE_FLOAT;
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
index 668e463a2..bc88d9ca9 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
@@ -46,13 +46,9 @@ import javax.media.nativewindow.DefaultGraphicsConfiguration;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GL;
-import javax.media.opengl.GL2;
-import javax.media.opengl.GL2GL3;
-import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.opengl.util.GLBuffers;
@@ -74,7 +70,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
protected int pBufferTexTarget, pBufferTexWidth, pBufferTexHeight;
- public MacOSXPbufferCGLDrawable(GLDrawableFactory factory, NativeSurface target) {
+ public MacOSXPbufferCGLDrawable(final GLDrawableFactory factory, final NativeSurface target) {
super(factory, target, false);
}
@@ -88,14 +84,8 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new MacOSXPbufferCGLContext(this, shareWith);
- }
-
- @Override
- protected long getNSViewHandle() {
- // pbuffer handle is NSOpenGLPixelBuffer
- return 0;
+ public GLContext createContext(final GLContext shareWith) {
+ return new MacOSXCGLContext(this, shareWith);
}
protected int getTextureTarget() { return pBufferTexTarget; }
@@ -108,7 +98,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
if (0 != pBuffer) {
synchronized (createdContexts) {
for(int i=0; i<createdContexts.size(); ) {
- final WeakReference<MacOSXCGLContext> ref = createdContexts.get(i);
+ final WeakReference<MacOSXCGLContext> ref = createdContexts.get(i);
final MacOSXCGLContext ctx = ref.get();
if (ctx != null) {
ctx.detachPBuffer();
@@ -126,12 +116,10 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
private void createPbuffer() {
final MutableSurface ms = (MutableSurface) getNativeSurface();
final DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ms.getGraphicsConfiguration();
- final GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities();
- final GLProfile glProfile = capabilities.getGLProfile();
- MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateOSXSharedResource(config.getScreen().getDevice());
+ final MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateSharedResourceImpl(config.getScreen().getDevice());
if (DEBUG) {
- System.out.println("Pbuffer config: " + config);
+ System.out.println(getThreadName()+": Pbuffer config: " + config);
if(null != sr) {
System.out.println("Pbuffer NPOT Texure avail: "+sr.isNPOTTextureAvailable());
System.out.println("Pbuffer RECT Texture avail: "+sr.isRECTTextureAvailable());
@@ -140,35 +128,20 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
}
}
- if ( capabilities.getPbufferRenderToTextureRectangle() && null!=sr && sr.isRECTTextureAvailable() ) {
- pBufferTexTarget = GL2GL3.GL_TEXTURE_RECTANGLE;
- } else {
- pBufferTexTarget = GL.GL_TEXTURE_2D;
- }
- if ( GL2GL3.GL_TEXTURE_RECTANGLE == pBufferTexTarget || ( null!=sr && sr.isNPOTTextureAvailable() ) ) {
- pBufferTexWidth = getWidth();
- pBufferTexHeight = getHeight();
+ pBufferTexTarget = GL.GL_TEXTURE_2D;
+ if ( null!=sr && sr.isNPOTTextureAvailable() ) {
+ pBufferTexWidth = getSurfaceWidth();
+ pBufferTexHeight = getSurfaceHeight();
} else {
- pBufferTexWidth = GLBuffers.getNextPowerOf2(getWidth());
- pBufferTexHeight = GLBuffers.getNextPowerOf2(getHeight());
- }
-
- int internalFormat = GL.GL_RGBA;
- if (capabilities.getPbufferFloatingPointBuffers()) {
- if(!glProfile.isGL2GL3() || null==sr || sr.isAppleFloatPixelsAvailable()) {
- throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available");
- }
- switch (capabilities.getRedBits()) {
- case 16: internalFormat = GL2.GL_RGBA_FLOAT16_APPLE; break;
- case 32: internalFormat = GL2.GL_RGBA_FLOAT32_APPLE; break;
- default: throw new GLException("Invalid floating-point bit depth (only 16 and 32 supported)");
- }
+ pBufferTexWidth = GLBuffers.getNextPowerOf2(getSurfaceWidth());
+ pBufferTexHeight = GLBuffers.getNextPowerOf2(getSurfaceHeight());
}
- final long pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight());
+ final int internalFormat = GL.GL_RGBA;
+ final long pBuffer = impl.create(pBufferTexTarget, internalFormat, getSurfaceWidth(), getSurfaceHeight());
if(DEBUG) {
System.err.println("MacOSXPbufferCGLDrawable tex: target "+toHexString(pBufferTexTarget)+
- ", pbufferSize "+getWidth()+"x"+getHeight()+
+ ", pbufferSize "+getSurfaceWidth()+"x"+getSurfaceHeight()+
", texSize "+pBufferTexWidth+"x"+pBufferTexHeight+
", internal-fmt "+toHexString(internalFormat));
System.err.println("MacOSXPbufferCGLDrawable pBuffer: "+toHexString(pBuffer));
@@ -182,13 +155,13 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
}
@Override
- public void setOpenGLMode(GLBackendType mode) {
+ public void setOpenGLMode(final GLBackendType mode) {
super.setOpenGLMode(mode);
createPbuffer(); // recreate
}
@Override
- protected void initOpenGLImpl(GLBackendType backend) {
+ protected void initOpenGLImpl(final GLBackendType backend) {
switch (backend) {
case NSOPENGL:
impl = new NSOpenGLImpl();
@@ -202,24 +175,24 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
}
// NSOpenGLPixelBuffer implementation
- class NSOpenGLImpl implements GLBackendImpl {
+ static class NSOpenGLImpl implements GLBackendImpl {
@Override
- public long create(int renderTarget, int internalFormat, int width, int height) {
+ public long create(final int renderTarget, final int internalFormat, final int width, final int height) {
return CGL.createPBuffer(renderTarget, internalFormat, width, height);
}
@Override
- public void destroy(long pbuffer) {
+ public void destroy(final long pbuffer) {
CGL.destroyPBuffer(pbuffer);
}
}
// CGL implementation
- class CGLImpl implements GLBackendImpl {
+ static class CGLImpl implements GLBackendImpl {
@Override
- public long create(int renderTarget, int internalFormat, int width, int height) {
- PointerBuffer pbuffer = PointerBuffer.allocateDirect(1);
- int res = CGL.CGLCreatePBuffer(width, height, renderTarget, internalFormat, 0, pbuffer);
+ public long create(final int renderTarget, final int internalFormat, final int width, final int height) {
+ final PointerBuffer pbuffer = PointerBuffer.allocateDirect(1);
+ final int res = CGL.CGLCreatePBuffer(width, height, renderTarget, internalFormat, 0, pbuffer);
if (res != CGL.kCGLNoError) {
throw new GLException("Error creating CGL-based pbuffer: error code " + res);
}
@@ -227,8 +200,8 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
}
@Override
- public void destroy(long pbuffer) {
- int res = CGL.CGLDestroyPBuffer(pbuffer);
+ public void destroy(final long pbuffer) {
+ final int res = CGL.CGLDestroyPBuffer(pbuffer);
if (res != CGL.kCGLNoError) {
throw new GLException("Error destroying CGL-based pbuffer: error code " + res);
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java
deleted file mode 100644
index fe60710f0..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.macosx.cgl.awt;
-
-import javax.media.nativewindow.*;
-import javax.media.opengl.*;
-import jogamp.opengl.macosx.cgl.*;
-
-public class MacOSXAWTCGLDrawableFactory extends MacOSXCGLDrawableFactory {
-
- public MacOSXAWTCGLDrawableFactory() {
- super();
- }
-
- public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return true;
- }
-
- public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- return new MacOSXJava2DCGLContext(shareWith);
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java
index edf9b7c84..01300b005 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -59,13 +59,14 @@ import jogamp.opengl.macosx.cgl.MacOSXCGLGraphicsConfiguration;
public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
public static void registerFactory() {
GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, GLCapabilitiesImmutable.class, new MacOSXAWTCGLGraphicsConfigurationFactory());
- }
+ }
private MacOSXAWTCGLGraphicsConfigurationFactory() {
}
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, final int nativeVisualID) {
GraphicsDevice device = null;
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
@@ -75,7 +76,7 @@ public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigur
if(null==absScreen) {
absScreen = AWTGraphicsScreen.createDefault();
}
- AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen;
+ final AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen;
device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice();
if ( !(capsChosen instanceof GLCapabilitiesImmutable) ) {
@@ -95,14 +96,14 @@ public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigur
System.err.println("MacOSXAWTCGLGraphicsConfigurationFactory: got "+absScreen);
}
- MacOSXGraphicsDevice macDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
- DefaultGraphicsScreen macScreen = new DefaultGraphicsScreen(macDevice, awtScreen.getIndex());
+ final MacOSXGraphicsDevice macDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+ final DefaultGraphicsScreen macScreen = new DefaultGraphicsScreen(macDevice, awtScreen.getIndex());
if(DEBUG) {
System.err.println("MacOSXAWTCGLGraphicsConfigurationFactory: made "+macScreen);
}
- GraphicsConfiguration gc = device.getDefaultConfiguration();
- MacOSXCGLGraphicsConfiguration macConfig = (MacOSXCGLGraphicsConfiguration)
+ final GraphicsConfiguration gc = device.getDefaultConfiguration();
+ final MacOSXCGLGraphicsConfiguration macConfig = (MacOSXCGLGraphicsConfiguration)
GraphicsConfigurationFactory.getFactory(macDevice, capsChosen).chooseGraphicsConfiguration(capsChosen,
capsRequested,
chooser, macScreen, nativeVisualID);
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java
deleted file mode 100644
index f41400d83..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.macosx.cgl.awt;
-
-import java.awt.Graphics;
-
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
-
-import jogamp.opengl.GLContextImpl;
-import jogamp.opengl.awt.Java2D;
-import jogamp.opengl.awt.Java2DGLContext;
-import jogamp.opengl.macosx.cgl.MacOSXCGLContext;
-import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType;
-
-
-/** MacOSXCGLContext implementation supporting the Java2D/JOGL bridge
- * on Mac OS X. The external GLDrawable mechanism does not work on Mac
- * OS X due to how drawables and contexts are operated upon on this
- * platform, so it is necessary to supply an alternative means to
- * create, make current, and destroy contexts on the Java2D "drawable"
- * on the Mac platform.
- */
-
-public class MacOSXJava2DCGLContext extends MacOSXCGLContext implements Java2DGLContext {
- private Graphics graphics;
-
- // FIXME: ignoring context sharing for the time being; will need to
- // rethink this in particular if using FBOs to implement the
- // Java2D/OpenGL pipeline on Mac OS X
-
- MacOSXJava2DCGLContext(GLContext shareWith) {
- super(null, shareWith);
- }
-
- public void setGraphics(Graphics g) {
- this.graphics = g;
- }
-
- protected void makeCurrentImpl() throws GLException {
- if (!Java2D.makeOGLContextCurrentOnSurface(graphics, contextHandle)) {
- throw new GLException("Error making context current");
- }
- }
-
- protected boolean createImpl(GLContextImpl shareWith) {
- long share = createImplPreset(shareWith);
-
- long ctx = Java2D.createOGLContextOnSurface(graphics, share);
- if (ctx == 0) {
- if(DEBUG) {
- System.err.println("Error creating current: "+this);
- }
- return false;
- }
- if (!Java2D.makeOGLContextCurrentOnSurface(graphics, contextHandle)) {
- Java2D.destroyOGLContext(ctx);
- if(DEBUG) {
- System.err.println("Error making created context current: "+this);
- }
- return false;
- }
- setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
- contextHandle = ctx;
- return true;
- }
-
- protected void releaseImpl() throws GLException {
- // FIXME: would need another primitive in the Java2D class in
- // order to implement this; hopefully should not matter for
- // correctness
- }
-
- protected void destroyImpl() throws GLException {
- Java2D.destroyOGLContext(contextHandle);
- }
-
- public void setOpenGLMode(GLBackendType mode) {
- if (mode != GLBackendType.CGL) {
- throw new GLException("OpenGL mode switching not supported for Java2D GLContexts");
- }
- super.setOpenGLMode(mode);
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java
new file mode 100644
index 000000000..003b9148e
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java
@@ -0,0 +1,980 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.openal.av;
+
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import jogamp.opengl.Debug;
+
+import com.jogamp.common.util.LFRingbuffer;
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.Ringbuffer;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.openal.AL;
+import com.jogamp.openal.ALC;
+import com.jogamp.openal.ALCConstants;
+import com.jogamp.openal.ALCcontext;
+import com.jogamp.openal.ALCdevice;
+import com.jogamp.openal.ALConstants;
+import com.jogamp.openal.ALExt;
+import com.jogamp.openal.ALFactory;
+import com.jogamp.openal.util.ALHelpers;
+import com.jogamp.opengl.util.av.AudioSink;
+
+/***
+ * OpenAL Audio Sink
+ */
+public class ALAudioSink implements AudioSink {
+
+ private static final String AL_SOFT_buffer_samples = "AL_SOFT_buffer_samples";
+ private static final String ALC_EXT_thread_local_context = "ALC_EXT_thread_local_context";
+ private static final boolean DEBUG_TRACE;
+ private static final ALC alc;
+ private static final AL al;
+ private static final ALExt alExt;
+ private static final boolean staticAvailable;
+
+ private String deviceSpecifier;
+ private ALCdevice device;
+ private boolean hasSOFTBufferSamples;
+ private boolean hasALC_thread_local_context;
+ private AudioFormat preferredAudioFormat;
+ private ALCcontext context;
+ private final RecursiveLock lock = LockFactory.createRecursiveLock();
+
+ /** Playback speed, range [0.5 - 2.0], default 1.0. */
+ private float playSpeed;
+ private float volume = 1.0f;
+
+ static class ALAudioFrame extends AudioFrame {
+ private final int alBuffer;
+
+ ALAudioFrame(final int alBuffer) {
+ this.alBuffer = alBuffer;
+ }
+ public ALAudioFrame(final int alBuffer, final int pts, final int duration, final int dataSize) {
+ super(pts, duration, dataSize);
+ this.alBuffer = alBuffer;
+ }
+
+ /** Get this frame's OpenAL buffer name */
+ public final int getALBuffer() { return alBuffer; }
+
+ public String toString() {
+ return "ALAudioFrame[pts " + pts + " ms, l " + duration + " ms, " + byteSize + " bytes, buffer "+alBuffer+"]";
+ }
+ }
+
+ // private ALAudioFrame[] alFrames = null;
+ private int[] alBufferNames = null;
+ private int frameGrowAmount = 0;
+ private int frameLimit = 0;
+
+ private Ringbuffer<ALAudioFrame> alFramesAvail = null;
+ private Ringbuffer<ALAudioFrame> alFramesPlaying = null;
+ private volatile int alBufferBytesQueued = 0;
+ private volatile int playingPTS = AudioFrame.INVALID_PTS;
+ private volatile int enqueuedFrameCount;
+
+ private int[] alSource = null;
+ private AudioFormat chosenFormat;
+ private int alChannelLayout;
+ private int alSampleType;
+ private int alFormat;
+ private boolean initialized;
+
+ private volatile boolean playRequested = false;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_TRACE = PropertyAccess.isPropertyDefined("jogl.debug.AudioSink.trace", true);
+
+ ALC _alc = null;
+ AL _al = null;
+ ALExt _alExt = null;
+ try {
+ _alc = ALFactory.getALC();
+ _al = ALFactory.getAL();
+ _alExt = ALFactory.getALExt();
+ } catch(final Throwable t) {
+ if( DEBUG ) {
+ System.err.println("ALAudioSink: Caught "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ alc = _alc;
+ al = _al;
+ alExt = _alExt;
+ staticAvailable = null != alc && null != al && null != alExt;
+ }
+
+ private void clearPreALError(final String prefix) {
+ checkALError(prefix);
+ }
+ private boolean checkALError(final String prefix) {
+ final int alcErr = alc.alcGetError(device);
+ final int alErr = al.alGetError();
+ final boolean ok = ALCConstants.ALC_NO_ERROR == alcErr && ALConstants.AL_NO_ERROR == alErr;
+ if( DEBUG ) {
+ System.err.println("ALAudioSink."+prefix+": ok "+ok+", err [alc "+toHexString(alcErr)+", al "+toHexString(alErr)+"]");
+ }
+ return ok;
+ }
+
+ public ALAudioSink() {
+ initialized = false;
+ chosenFormat = null;
+
+ if( !staticAvailable ) {
+ return;
+ }
+ synchronized(ALAudioSink.class) {
+ try {
+ // Get handle to default device.
+ device = alc.alcOpenDevice(null);
+ if (device == null) {
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error opening default OpenAL device");
+ }
+ int checkErrIter = 1;
+
+ clearPreALError("init."+checkErrIter++);
+
+ // Get the device specifier.
+ deviceSpecifier = alc.alcGetString(device, ALCConstants.ALC_DEVICE_SPECIFIER);
+ if (deviceSpecifier == null) {
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error getting specifier for default OpenAL device");
+ }
+
+ // Create audio context.
+ // final int[] attrs = new int[] { ALC.ALC_FREQUENCY, DefaultFormat.sampleRate, 0 };
+ // context = alc.alcCreateContext(device, attrs, 0);
+ context = alc.alcCreateContext(device, null);
+ if (context == null) {
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error creating OpenAL context for "+deviceSpecifier);
+ }
+
+ lockContext();
+ try {
+ // Check for an error.
+ if ( alc.alcGetError(device) != ALCConstants.ALC_NO_ERROR ) {
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error making OpenAL context current");
+ }
+
+ hasSOFTBufferSamples = al.alIsExtensionPresent(AL_SOFT_buffer_samples);
+ hasALC_thread_local_context = alc.alcIsExtensionPresent(null, ALC_EXT_thread_local_context) ||
+ alc.alcIsExtensionPresent(device, ALC_EXT_thread_local_context) ;
+ clearPreALError("init."+checkErrIter++);
+ preferredAudioFormat = new AudioFormat(querySampleRate(), DefaultFormat.sampleSize, DefaultFormat.channelCount, DefaultFormat.signed, DefaultFormat.fixedP, DefaultFormat.planar, DefaultFormat.littleEndian);
+ if( DEBUG ) {
+ System.out.println("ALAudioSink: OpenAL Extensions:"+al.alGetString(ALConstants.AL_EXTENSIONS));
+ clearPreALError("init."+checkErrIter++);
+ System.out.println("ALAudioSink: Null device OpenAL Extensions:"+alc.alcGetString(null, ALCConstants.ALC_EXTENSIONS));
+ clearPreALError("init."+checkErrIter++);
+ System.out.println("ALAudioSink: Device "+deviceSpecifier+" OpenAL Extensions:"+alc.alcGetString(device, ALCConstants.ALC_EXTENSIONS));
+ System.out.println("ALAudioSink: hasSOFTBufferSamples "+hasSOFTBufferSamples);
+ System.out.println("ALAudioSink: hasALC_thread_local_context "+hasALC_thread_local_context);
+ System.out.println("ALAudioSink: preferredAudioFormat "+preferredAudioFormat);
+ clearPreALError("init."+checkErrIter++);
+ }
+
+ // Create source
+ {
+ alSource = new int[1];
+ al.alGenSources(1, alSource, 0);
+ final int err = al.alGetError();
+ if( ALConstants.AL_NO_ERROR != err ) {
+ alSource = null;
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error generating Source: 0x"+Integer.toHexString(err));
+ }
+ }
+
+ if( DEBUG ) {
+ System.err.println("ALAudioSink: Using device: " + deviceSpecifier);
+ }
+ initialized = true;
+ } finally {
+ unlockContext();
+ }
+ return;
+ } catch ( final Exception e ) {
+ if( DEBUG ) {
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ }
+ destroy();
+ }
+ }
+ }
+
+ private final int querySampleRate() {
+ final int sampleRate;
+ final int[] value = new int[1];
+ alc.alcGetIntegerv(device, ALCConstants.ALC_FREQUENCY, 1, value, 0);
+ final int alcErr = alc.alcGetError(device);
+ final int alErr = al.alGetError();
+ if ( ALCConstants.ALC_NO_ERROR == alcErr && ALConstants.AL_NO_ERROR == alErr && 0 != value[0] ) {
+ sampleRate = value[0];
+ } else {
+ sampleRate = DefaultFormat.sampleRate;
+ }
+ if( DEBUG ) {
+ System.err.println("ALAudioSink.querySampleRate: err [alc "+toHexString(alcErr)+", al "+toHexString(alErr)+"], freq: "+value[0]+" -> "+sampleRate);
+ }
+ return sampleRate;
+ }
+
+ private final void lockContext() {
+ lock.lock();
+ if( hasALC_thread_local_context ) {
+ alExt.alcSetThreadContext(context);
+ } else {
+ alc.alcMakeContextCurrent(context);
+ }
+ final int alcErr = alc.alcGetError(null);
+ if( ALCConstants.ALC_NO_ERROR != alcErr ) {
+ final String err = getThreadName()+": ALCError "+toHexString(alcErr)+" while makeCurrent. "+this;
+ System.err.println(err);
+ Thread.dumpStack();
+ lock.unlock();
+ throw new RuntimeException(err);
+ }
+ final int alErr = al.alGetError();
+ if( ALCConstants.ALC_NO_ERROR != alErr ) {
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": Prev - ALError "+toHexString(alErr)+" @ makeCurrent. "+this);
+ Thread.dumpStack();
+ }
+ }
+ }
+ private final void unlockContext() {
+ if( hasALC_thread_local_context ) {
+ alExt.alcSetThreadContext(null);
+ } else {
+ alc.alcMakeContextCurrent(null);
+ }
+ lock.unlock();
+ }
+ private final void destroyContext() {
+ lock.lock();
+ try {
+ if( null != context ) {
+ try {
+ alc.alcDestroyContext(context);
+ } catch (final Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ context = null;
+ }
+ // unroll lock !
+ while(lock.getHoldCount() > 1) {
+ lock.unlock();
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public final String toString() {
+ final int alSrcName = null != alSource ? alSource[0] : 0;
+ final int alBuffersLen = null != alBufferNames ? alBufferNames.length : 0;
+ final int ctxHash = context != null ? context.hashCode() : 0;
+ return "ALAudioSink[init "+initialized+", playRequested "+playRequested+", device "+deviceSpecifier+", ctx "+toHexString(ctxHash)+", alSource "+alSrcName+
+ ", chosen "+chosenFormat+
+ ", al[chan "+ALHelpers.alChannelLayoutName(alChannelLayout)+", type "+ALHelpers.alSampleTypeName(alSampleType)+
+ ", fmt "+toHexString(alFormat)+", soft "+hasSOFTBufferSamples+
+ "], playSpeed "+playSpeed+", buffers[total "+alBuffersLen+", avail "+alFramesAvail.size()+", "+
+ "queued["+alFramesPlaying.size()+", apts "+getPTS()+", "+getQueuedTime() + " ms, " + alBufferBytesQueued+" bytes], "+
+ "queue[g "+frameGrowAmount+", l "+frameLimit+"]";
+ }
+
+ private final String shortString() {
+ final int alSrcName = null != alSource ? alSource[0] : 0;
+ final int ctxHash = context != null ? context.hashCode() : 0;
+ return "[ctx "+toHexString(ctxHash)+", playReq "+playRequested+", alSrc "+alSrcName+
+ ", queued["+alFramesPlaying.size()+", " + alBufferBytesQueued+" bytes], "+
+ "queue[g "+frameGrowAmount+", l "+frameLimit+"]";
+ }
+
+ public final String getPerfString() {
+ final int alBuffersLen = null != alBufferNames ? alBufferNames.length : 0;
+ return "Play [buffer "+alFramesPlaying.size()+"/"+alBuffersLen+", apts "+getPTS()+", "+getQueuedTime() + " ms, " + alBufferBytesQueued+" bytes]";
+ }
+
+ @Override
+ public final AudioFormat getPreferredFormat() {
+ if( !staticAvailable ) {
+ return null;
+ }
+ return preferredAudioFormat;
+ }
+
+ @Override
+ public final int getMaxSupportedChannels() {
+ if( !staticAvailable ) {
+ return 0;
+ }
+ return hasSOFTBufferSamples ? 8 : 2;
+ }
+
+ @Override
+ public final boolean isSupported(final AudioFormat format) {
+ if( !staticAvailable ) {
+ return false;
+ }
+ if( format.planar || !format.littleEndian ) {
+ // FIXME big-endian supported w/ SOFT where it's native format!
+ return false;
+ }
+ final int alChannelLayout = ALHelpers.getDefaultALChannelLayout(format.channelCount);
+ if( ALConstants.AL_NONE != alChannelLayout ) {
+ final int alSampleType = ALHelpers.getALSampleType(format.sampleSize, format.signed, format.fixedP);
+ if( ALConstants.AL_NONE != alSampleType ) {
+ lockContext();
+ try {
+ final int alFormat = ALHelpers.getALFormat(alChannelLayout, alSampleType, hasSOFTBufferSamples, al, alExt);
+ return ALConstants.AL_NONE != alFormat;
+ } finally {
+ unlockContext();
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public final boolean init(final AudioFormat requestedFormat, final float frameDuration, final int initialQueueSize, final int queueGrowAmount, final int queueLimit) {
+ if( !staticAvailable ) {
+ return false;
+ }
+ alChannelLayout = ALHelpers.getDefaultALChannelLayout(requestedFormat.channelCount);
+ alSampleType = ALHelpers.getALSampleType(requestedFormat.sampleSize, requestedFormat.signed, requestedFormat.fixedP);
+ lockContext();
+ try {
+ if( ALConstants.AL_NONE != alChannelLayout && ALConstants.AL_NONE != alSampleType ) {
+ alFormat = ALHelpers.getALFormat(alChannelLayout, alSampleType, hasSOFTBufferSamples, al, alExt);
+ } else {
+ alFormat = ALConstants.AL_NONE;
+ }
+ if( ALConstants.AL_NONE == alFormat ) {
+ // not supported
+ return false;
+ }
+ // Allocate buffers
+ destroyBuffers();
+ {
+ final float useFrameDuration = frameDuration > 1f ? frameDuration : AudioSink.DefaultFrameDuration;
+ final int initialFrameCount = requestedFormat.getFrameCount(
+ initialQueueSize > 0 ? initialQueueSize : AudioSink.DefaultInitialQueueSize, useFrameDuration);
+ // frameDuration, int initialQueueSize, int queueGrowAmount, int queueLimit) {
+ alBufferNames = new int[initialFrameCount];
+ al.alGenBuffers(initialFrameCount, alBufferNames, 0);
+ final int err = al.alGetError();
+ if( ALConstants.AL_NO_ERROR != err ) {
+ alBufferNames = null;
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error generating Buffers: 0x"+Integer.toHexString(err));
+ }
+ final ALAudioFrame[] alFrames = new ALAudioFrame[initialFrameCount];
+ for(int i=0; i<initialFrameCount; i++) {
+ alFrames[i] = new ALAudioFrame(alBufferNames[i]);
+ }
+
+ alFramesAvail = new LFRingbuffer<ALAudioFrame>(alFrames);
+ alFramesPlaying = new LFRingbuffer<ALAudioFrame>(ALAudioFrame[].class, initialFrameCount);
+ this.frameGrowAmount = requestedFormat.getFrameCount(
+ queueGrowAmount > 0 ? queueGrowAmount : AudioSink.DefaultQueueGrowAmount, useFrameDuration);
+ this.frameLimit = requestedFormat.getFrameCount(
+ queueLimit > 0 ? queueLimit : AudioSink.DefaultQueueLimitWithVideo, useFrameDuration);
+ if( DEBUG_TRACE ) {
+ alFramesAvail.dump(System.err, "Avail-init");
+ alFramesPlaying.dump(System.err, "Playi-init");
+ }
+ }
+ } finally {
+ unlockContext();
+ }
+
+ chosenFormat = requestedFormat;
+ return true;
+ }
+
+ @Override
+ public final AudioFormat getChosenFormat() {
+ return chosenFormat;
+ }
+
+ private static int[] concat(final int[] first, final int[] second) {
+ final int[] result = Arrays.copyOf(first, first.length + second.length);
+ System.arraycopy(second, 0, result, first.length, second.length);
+ return result;
+ }
+ /**
+ private static <T> T[] concat(T[] first, T[] second) {
+ final T[] result = Arrays.copyOf(first, first.length + second.length);
+ System.arraycopy(second, 0, result, first.length, second.length);
+ return result;
+ } */
+
+ private boolean growBuffers() {
+ if( !alFramesAvail.isEmpty() || !alFramesPlaying.isFull() ) {
+ throw new InternalError("Buffers: Avail is !empty "+alFramesAvail+" or Playing is !full "+alFramesPlaying);
+ }
+ if( alFramesAvail.capacity() >= frameLimit || alFramesPlaying.capacity() >= frameLimit ) {
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": ALAudioSink.growBuffers: Frame limit "+frameLimit+" reached: Avail "+alFramesAvail+", Playing "+alFramesPlaying);
+ }
+ return false;
+ }
+
+ final int[] newALBufferNames = new int[frameGrowAmount];
+ al.alGenBuffers(frameGrowAmount, newALBufferNames, 0);
+ final int err = al.alGetError();
+ if( ALConstants.AL_NO_ERROR != err ) {
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": ALAudioSink.growBuffers: Error generating "+frameGrowAmount+" new Buffers: 0x"+Integer.toHexString(err));
+ }
+ return false;
+ }
+ alBufferNames = concat(alBufferNames, newALBufferNames);
+
+ final ALAudioFrame[] newALBuffers = new ALAudioFrame[frameGrowAmount];
+ for(int i=0; i<frameGrowAmount; i++) {
+ newALBuffers[i] = new ALAudioFrame(newALBufferNames[i]);
+ }
+ // alFrames = concat(alFrames , newALBuffers);
+
+ alFramesAvail.growEmptyBuffer(newALBuffers);
+ alFramesPlaying.growFullBuffer(frameGrowAmount);
+ if( alFramesAvail.isEmpty() || alFramesPlaying.isFull() ) {
+ throw new InternalError("Buffers: Avail is empty "+alFramesAvail+" or Playing is full "+alFramesPlaying);
+ }
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": ALAudioSink: Buffer grown "+frameGrowAmount+": Avail "+alFramesAvail+", playing "+alFramesPlaying);
+ }
+ if( DEBUG_TRACE ) {
+ alFramesAvail.dump(System.err, "Avail-grow");
+ alFramesPlaying.dump(System.err, "Playi-grow");
+ }
+ return true;
+ }
+
+ private void destroyBuffers() {
+ if( !staticAvailable ) {
+ return;
+ }
+ if( null != alBufferNames ) {
+ try {
+ al.alDeleteBuffers(alBufferNames.length, alBufferNames, 0);
+ } catch (final Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ alFramesAvail.clear();
+ alFramesAvail = null;
+ alFramesPlaying.clear();
+ alFramesPlaying = null;
+ alBufferBytesQueued = 0;
+ // alFrames = null;
+ alBufferNames = null;
+ }
+ }
+
+ @Override
+ public final void destroy() {
+ initialized = false;
+ if( !staticAvailable ) {
+ return;
+ }
+ if( null != context ) {
+ lockContext();
+ }
+ try {
+ stopImpl(true);
+ if( null != alSource ) {
+ try {
+ al.alDeleteSources(1, alSource, 0);
+ } catch (final Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ alSource = null;
+ }
+
+ destroyBuffers();
+ } finally {
+ destroyContext();
+ }
+ if( null != device ) {
+ try {
+ alc.alcCloseDevice(device);
+ } catch (final Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ device = null;
+ }
+ chosenFormat = null;
+ }
+
+ @Override
+ public final boolean isInitialized() {
+ return initialized;
+ }
+
+ private final int dequeueBuffer(final boolean wait, final boolean ignoreBufferInconsistency) {
+ int alErr = ALConstants.AL_NO_ERROR;
+ final int releaseBufferCount;
+ if( alBufferBytesQueued > 0 ) {
+ final int releaseBufferLimes = Math.max(1, alFramesPlaying.size() / 4 );
+ final int[] val=new int[1];
+ int i=0;
+ do {
+ al.alGetSourcei(alSource[0], ALConstants.AL_BUFFERS_PROCESSED, val, 0);
+ alErr = al.alGetError();
+ if( ALConstants.AL_NO_ERROR != alErr ) {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while quering processed buffers at source. "+this);
+ }
+ if( wait && val[0] < releaseBufferLimes ) {
+ i++;
+ // clip wait at [2 .. 100] ms
+ final int avgBufferDura = chosenFormat.getBytesDuration( alBufferBytesQueued / alFramesPlaying.size() );
+ final int sleep = Math.max(2, Math.min(100, releaseBufferLimes * avgBufferDura));
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": ALAudioSink: Dequeue.wait["+i+"]: avgBufferDura "+avgBufferDura+", releaseBufferLimes "+releaseBufferLimes+", sleep "+sleep+" ms, playImpl "+(ALConstants.AL_PLAYING == getSourceState(false))+", processed "+val[0]+", "+this);
+ }
+ unlockContext();
+ try {
+ Thread.sleep( sleep - 1 );
+ } catch (final InterruptedException e) {
+ } finally {
+ lockContext();
+ }
+ }
+ } while ( wait && val[0] < releaseBufferLimes && alBufferBytesQueued > 0 );
+ releaseBufferCount = val[0];
+ } else {
+ releaseBufferCount = 0;
+ }
+
+ if( releaseBufferCount > 0 ) {
+ final int[] buffers = new int[releaseBufferCount];
+ al.alSourceUnqueueBuffers(alSource[0], releaseBufferCount, buffers, 0);
+ alErr = al.alGetError();
+ if( ALConstants.AL_NO_ERROR != alErr ) {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while dequeueing "+releaseBufferCount+" buffers. "+this);
+ }
+ for ( int i=0; i<releaseBufferCount; i++ ) {
+ final ALAudioFrame releasedBuffer = alFramesPlaying.get();
+ if( null == releasedBuffer ) {
+ if( !ignoreBufferInconsistency ) {
+ throw new InternalError("Internal Error: "+this);
+ }
+ } else {
+ if(DEBUG_TRACE) {
+ System.err.println("< [al "+buffers[i]+", q "+releasedBuffer.alBuffer+"] <- "+shortString()+" @ "+getThreadName());
+ }
+ if( releasedBuffer.alBuffer != buffers[i] ) {
+ if( !ignoreBufferInconsistency ) {
+ alFramesAvail.dump(System.err, "Avail-deq02-post");
+ alFramesPlaying.dump(System.err, "Playi-deq02-post");
+ throw new InternalError("Buffer name mismatch: dequeued: "+buffers[i]+", released "+releasedBuffer+", "+this);
+ }
+ }
+ alBufferBytesQueued -= releasedBuffer.getByteSize();
+ if( !alFramesAvail.put(releasedBuffer) ) {
+ throw new InternalError("Internal Error: "+this);
+ }
+ if(DEBUG_TRACE) {
+ System.err.println("<< [al "+buffers[i]+", q "+releasedBuffer.alBuffer+"] <- "+shortString()+" @ "+getThreadName());
+ }
+ }
+ }
+ }
+ return releaseBufferCount;
+ }
+ private final void dequeueForceAll() {
+ if(DEBUG_TRACE) {
+ System.err.println("< _FLUSH_ <- "+shortString()+" @ "+getThreadName());
+ }
+ final int[] val=new int[1];
+ al.alSourcei(alSource[0], ALConstants.AL_BUFFER, 0); // explicit force zero buffer!
+ if(DEBUG_TRACE) {
+ al.alGetSourcei(alSource[0], ALConstants.AL_BUFFERS_PROCESSED, val, 0);
+ }
+ final int alErr = al.alGetError();
+ while ( !alFramesPlaying.isEmpty() ) {
+ final ALAudioFrame releasedBuffer = alFramesPlaying.get();
+ if( null == releasedBuffer ) {
+ throw new InternalError("Internal Error: "+this);
+ }
+ alBufferBytesQueued -= releasedBuffer.getByteSize();
+ if( !alFramesAvail.put(releasedBuffer) ) {
+ throw new InternalError("Internal Error: "+this);
+ }
+ }
+ alBufferBytesQueued = 0;
+ if(DEBUG_TRACE) {
+ System.err.println("<< _FLUSH_ [al "+val[0]+", err "+toHexString(alErr)+"] <- "+shortString()+" @ "+getThreadName());
+ Thread.dumpStack();
+ }
+ }
+
+ private final int dequeueBuffer(final boolean wait, final int inPTS, final int inDuration) {
+ final int dequeuedBufferCount = dequeueBuffer( wait, false /* ignoreBufferInconsistency */ );
+ final ALAudioFrame currentBuffer = alFramesPlaying.peek();
+ if( null != currentBuffer ) {
+ playingPTS = currentBuffer.getPTS();
+ } else {
+ playingPTS = inPTS;
+ }
+ if( DEBUG ) {
+ if( dequeuedBufferCount > 0 ) {
+ System.err.println(getThreadName()+": ALAudioSink: Write "+inPTS+", "+inDuration+" ms, dequeued "+dequeuedBufferCount+", wait "+wait+", "+getPerfString());
+ }
+ }
+ return dequeuedBufferCount;
+ }
+
+ @Override
+ public final AudioFrame enqueueData(final int pts, final ByteBuffer bytes, final int byteCount) {
+ if( !initialized || null == chosenFormat ) {
+ return null;
+ }
+ final ALAudioFrame alFrame;
+
+ // OpenAL consumes buffers in the background
+ // we first need to initialize the OpenAL buffers then
+ // start continuous playback.
+ lockContext();
+ try {
+ final int duration = chosenFormat.getBytesDuration(byteCount);
+ final boolean dequeueDone;
+ if( alFramesAvail.isEmpty() ) {
+ // try to dequeue first
+ dequeueDone = dequeueBuffer(false, pts, duration) > 0;
+ if( alFramesAvail.isEmpty() ) {
+ // try to grow
+ growBuffers();
+ }
+ } else {
+ dequeueDone = false;
+ }
+ if( !dequeueDone && alFramesPlaying.size() > 0 ) { // dequeue only possible if playing ..
+ final boolean wait = isPlayingImpl0() && alFramesAvail.isEmpty(); // possible if grow failed or already exceeds it's limit!
+ dequeueBuffer(wait, pts, duration);
+ }
+
+ alFrame = alFramesAvail.get();
+ if( null == alFrame ) {
+ alFramesAvail.dump(System.err, "Avail");
+ throw new InternalError("Internal Error: avail.get null "+alFramesAvail+", "+this);
+ }
+ alFrame.setPTS(pts);
+ alFrame.setDuration(duration);
+ alFrame.setByteSize(byteCount);
+ if( !alFramesPlaying.put( alFrame ) ) {
+ throw new InternalError("Internal Error: "+this);
+ }
+ final int[] alBufferNames = new int[] { alFrame.alBuffer };
+ if( hasSOFTBufferSamples ) {
+ final int samplesPerChannel = chosenFormat.getBytesSampleCount(byteCount) / chosenFormat.channelCount;
+ // final int samplesPerChannel = ALHelpers.bytesToSampleCount(byteCount, alChannelLayout, alSampleType);
+ alExt.alBufferSamplesSOFT(alFrame.alBuffer, chosenFormat.sampleRate, alFormat,
+ samplesPerChannel, alChannelLayout, alSampleType, bytes);
+ } else {
+ al.alBufferData(alFrame.alBuffer, alFormat, bytes, byteCount, chosenFormat.sampleRate);
+ }
+
+ if(DEBUG_TRACE) {
+ System.err.println("> "+alFrame.alBuffer+" -> "+shortString()+" @ "+getThreadName());
+ }
+
+ al.alSourceQueueBuffers(alSource[0], 1, alBufferNames, 0);
+ final int alErr = al.alGetError();
+ if( ALConstants.AL_NO_ERROR != alErr ) {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while queueing buffer "+toHexString(alBufferNames[0])+". "+this);
+ }
+ alBufferBytesQueued += byteCount;
+ enqueuedFrameCount++; // safe: only written-to while locked!
+
+ if(DEBUG_TRACE) {
+ System.err.println(">> "+alFrame.alBuffer+" -> "+shortString()+" @ "+getThreadName());
+ }
+
+ playImpl(); // continue playing, fixes issue where we ran out of enqueued data!
+ } finally {
+ unlockContext();
+ }
+ return alFrame;
+ }
+
+ @Override
+ public final boolean isPlaying() {
+ if( !initialized || null == chosenFormat ) {
+ return false;
+ }
+ if( playRequested ) {
+ lockContext();
+ try {
+ return isPlayingImpl0();
+ } finally {
+ unlockContext();
+ }
+ } else {
+ return false;
+ }
+ }
+ private final boolean isPlayingImpl0() {
+ if( playRequested ) {
+ return ALConstants.AL_PLAYING == getSourceState(false);
+ } else {
+ return false;
+ }
+ }
+ private final int getSourceState(final boolean ignoreError) {
+ final int[] val = new int[1];
+ al.alGetSourcei(alSource[0], ALConstants.AL_SOURCE_STATE, val, 0);
+ final int alErr = al.alGetError();
+ if( ALConstants.AL_NO_ERROR != alErr ) {
+ final String msg = getThreadName()+": ALError "+toHexString(alErr)+" while querying SOURCE_STATE. "+this;
+ if( ignoreError ) {
+ if( DEBUG ) {
+ System.err.println(msg);
+ }
+ } else {
+ throw new RuntimeException(msg);
+ }
+ }
+ return val[0];
+ }
+
+ @Override
+ public final void play() {
+ if( !initialized || null == chosenFormat ) {
+ return;
+ }
+ playRequested = true;
+ lockContext();
+ try {
+ playImpl();
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": ALAudioSink: PLAY playImpl "+(ALConstants.AL_PLAYING == getSourceState(false))+", "+this);
+ }
+ } finally {
+ unlockContext();
+ }
+ }
+ private final void playImpl() {
+ if( playRequested && ALConstants.AL_PLAYING != getSourceState(false) ) {
+ al.alSourcePlay(alSource[0]);
+ final int alErr = al.alGetError();
+ if( ALConstants.AL_NO_ERROR != alErr ) {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while start playing. "+this);
+ }
+ }
+ }
+
+ @Override
+ public final void pause() {
+ if( !initialized || null == chosenFormat ) {
+ return;
+ }
+ if( playRequested ) {
+ lockContext();
+ try {
+ pauseImpl();
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": ALAudioSink: PAUSE playImpl "+(ALConstants.AL_PLAYING == getSourceState(false))+", "+this);
+ }
+ } finally {
+ unlockContext();
+ }
+ }
+ }
+ private final void pauseImpl() {
+ if( isPlayingImpl0() ) {
+ playRequested = false;
+ al.alSourcePause(alSource[0]);
+ final int alErr = al.alGetError();
+ if( ALConstants.AL_NO_ERROR != alErr ) {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while pausing. "+this);
+ }
+ }
+ }
+ private final void stopImpl(final boolean ignoreError) {
+ if( ALConstants.AL_STOPPED != getSourceState(ignoreError) ) {
+ playRequested = false;
+ al.alSourceStop(alSource[0]);
+ final int alErr = al.alGetError();
+ if( ALConstants.AL_NO_ERROR != alErr ) {
+ final String msg = "ALError "+toHexString(alErr)+" while stopping. "+this;
+ if( ignoreError ) {
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": "+msg);
+ }
+ } else {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while stopping. "+this);
+ }
+ }
+ }
+ }
+
+ @Override
+ public final float getPlaySpeed() { return playSpeed; }
+
+ @Override
+ public final boolean setPlaySpeed(float rate) {
+ if( !initialized || null == chosenFormat ) {
+ return false;
+ }
+ lockContext();
+ try {
+ if( Math.abs(1.0f - rate) < 0.01f ) {
+ rate = 1.0f;
+ }
+ if( 0.5f <= rate && rate <= 2.0f ) { // OpenAL limits
+ playSpeed = rate;
+ al.alSourcef(alSource[0], ALConstants.AL_PITCH, playSpeed);
+ return true;
+ }
+ } finally {
+ unlockContext();
+ }
+ return false;
+ }
+
+ @Override
+ public final float getVolume() {
+ return volume;
+ }
+
+ @Override
+ public final boolean setVolume(float v) {
+ if( !initialized || null == chosenFormat ) {
+ return false;
+ }
+ lockContext();
+ try {
+ if( Math.abs(v) < 0.01f ) {
+ v = 0.0f;
+ } else if( Math.abs(1.0f - v) < 0.01f ) {
+ v = 1.0f;
+ }
+ if( 0.0f <= v && v <= 1.0f ) { // OpenAL limits
+ volume = v;
+ al.alSourcef(alSource[0], ALConstants.AL_GAIN, v);
+ return true;
+ }
+ } finally {
+ unlockContext();
+ }
+ return false;
+ }
+
+ @Override
+ public final void flush() {
+ if( !initialized || null == chosenFormat ) {
+ return;
+ }
+ lockContext();
+ try {
+ // pauseImpl();
+ stopImpl(false);
+ // Redundant: dequeueBuffer( false /* wait */, true /* ignoreBufferInconsistency */);
+ dequeueForceAll();
+ if( alBufferNames.length != alFramesAvail.size() || alFramesPlaying.size() != 0 ) {
+ throw new InternalError("XXX: "+this);
+ }
+ if( DEBUG ) {
+ System.err.println(getThreadName()+": ALAudioSink: FLUSH playImpl "+(ALConstants.AL_PLAYING == getSourceState(false))+", "+this);
+ }
+ } finally {
+ unlockContext();
+ }
+ }
+
+ @Override
+ public final int getEnqueuedFrameCount() {
+ return enqueuedFrameCount;
+ }
+
+ @Override
+ public final int getFrameCount() {
+ return null != alBufferNames ? alBufferNames.length : 0;
+ }
+
+ @Override
+ public final int getQueuedFrameCount() {
+ if( !initialized || null == chosenFormat ) {
+ return 0;
+ }
+ return alFramesPlaying.size();
+ }
+
+ @Override
+ public final int getFreeFrameCount() {
+ if( !initialized || null == chosenFormat ) {
+ return 0;
+ }
+ return alFramesAvail.size();
+ }
+
+ @Override
+ public final int getQueuedByteCount() {
+ if( !initialized || null == chosenFormat ) {
+ return 0;
+ }
+ return alBufferBytesQueued;
+ }
+
+ @Override
+ public final int getQueuedTime() {
+ if( !initialized || null == chosenFormat ) {
+ return 0;
+ }
+ return chosenFormat.getBytesDuration(alBufferBytesQueued);
+ }
+
+ @Override
+ public final int getPTS() { return playingPTS; }
+
+ private static final String toHexString(final int v) { return "0x"+Integer.toHexString(v); }
+ private static final String getThreadName() { return Thread.currentThread().getName(); }
+}
diff --git a/src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java b/src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java
new file mode 100644
index 000000000..4f585937d
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java
@@ -0,0 +1,16 @@
+package jogamp.opengl.openal.av;
+
+import com.jogamp.openal.AL;
+import com.jogamp.openal.JoalVersion;
+
+/**
+ * Demo JOAL usage w/ av dependency, i.e. FFMPEGMediaPlayer ..
+ */
+public class ALDummyUsage {
+ static AL al;
+
+ public static void main(final String args[]) {
+ System.err.println("JOGL> Hello JOAL");
+ System.err.println("JOAL: "+JoalVersion.getInstance().toString());
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.fp b/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.fp
new file mode 100644
index 000000000..8b30b65f9
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.fp
@@ -0,0 +1,19 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+varying vec2 mgl_texCoord;
+
+uniform sampler2D mgl_Texture0;
+
+void main (void)
+{
+ mgl_FragColor = texture2D(mgl_Texture0, mgl_texCoord);
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.vp b/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.vp
new file mode 100644
index 000000000..d9ef6b493
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.vp
@@ -0,0 +1,19 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform mat4 mgl_PMVMatrix[2];
+
+attribute vec4 mgl_Vertex;
+attribute vec4 mgl_MultiTexCoord;
+
+varying vec2 mgl_texCoord;
+
+void main(void)
+{
+ mgl_texCoord = mgl_MultiTexCoord.st;
+ gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java
index 22690b06d..810a9286b 100644
--- a/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java
+++ b/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java
@@ -31,41 +31,52 @@ package jogamp.opengl.util;
import javax.media.opengl.*;
/**
- * Handles consistency of buffer data and array state.
- * Implementations shall consider buffer types (VBO, ..), interleaved, etc.
- * They also need to consider array state types, i.e. fixed function or GLSL.
+ * Handles consistency of buffer data and array state.<br/>
+ * Implementations shall consider buffer types (VBO, ..), interleaved, etc.<br/>
+ * They also need to consider array state types, i.e. fixed function or GLSL.<br/>
*/
public interface GLArrayHandler {
+
/**
- * Implementation shall associate the data with the array
- * and synchronize the data with the GPU.
- *
+ * if <code>bind</code> is true and the data uses VBO,
+ * the latter will be bound and data written to the GPU if required.
+ * <p>
+ * If <code>bind</code> is false and the data uses VBO,
+ * the latter will be unbound.
+ * </p>
+ *
* @param gl current GL object
- * @param enable true if array data shall be valid, otherwise false.
- * @param ext extension object allowing passing of an implementation detail
+ * @param bind true if VBO shall be bound and data written,
+ * otherwise clear VBO binding.
+ * @return true if data uses VBO and action was performed, otherwise false
*/
- public void syncData(GL gl, boolean enable, Object ext);
-
+ public boolean bindBuffer(GL gl, boolean bind);
+
/**
* Implementation shall enable or disable the array state.
- *
+ * <p>
+ * Before enabling the array state,
+ * implementation shall synchronize the data with the GPU
+ * and associate the data with the array.
+ * </p>
+ *
* @param gl current GL object
* @param enable true if array shall be enabled, otherwise false.
- * @param ext extension object allowing passing of an implementation detail
+ * @param ext extension object allowing passing of an implementation detail
*/
public void enableState(GL gl, boolean enable, Object ext);
-
+
/**
- * Supporting interleaved arrays, where sub handlers may handle
+ * Supporting interleaved arrays, where sub handlers may handle
* the array state and the <i>master</i> handler the buffer consistency.
- *
+ *
* @param handler the sub handler
* @throws UnsupportedOperationException if this array handler does not support interleaved arrays
*/
public void addSubHandler(GLArrayHandlerFlat handler) throws UnsupportedOperationException;
public void setSubArrayVBOName(int vboName);
-
+
}
diff --git a/src/jogl/classes/jogamp/opengl/util/GLArrayHandlerFlat.java b/src/jogl/classes/jogamp/opengl/util/GLArrayHandlerFlat.java
index dca9129ad..179142fee 100644
--- a/src/jogl/classes/jogamp/opengl/util/GLArrayHandlerFlat.java
+++ b/src/jogl/classes/jogamp/opengl/util/GLArrayHandlerFlat.java
@@ -39,23 +39,21 @@ public interface GLArrayHandlerFlat {
/**
* Implementation shall associate the data with the array
- *
+ *
* @param gl current GL object
- * @param enable true if array data shall be valid, otherwise false.
- * @param force true force data association, bypassing optimization
- * @param ext extension object allowing passing of an implementation detail
+ * @param ext extension object allowing passing of an implementation detail
*/
- public void syncData(GL gl, boolean enable, boolean force, Object ext);
-
+ public void syncData(GL gl, Object ext);
+
/**
* Implementation shall enable or disable the array state.
- *
+ *
* @param gl current GL object
* @param enable true if array shall be enabled, otherwise false.
- * @param ext extension object allowing passing of an implementation detail
+ * @param ext extension object allowing passing of an implementation detail
*/
- public void enableState(GL gl, boolean enable, Object ext);
-
+ public void enableState(GL gl, boolean enable, Object ext);
+
public GLArrayDataWrapper getData();
}
diff --git a/src/jogl/classes/jogamp/opengl/util/GLArrayHandlerInterleaved.java b/src/jogl/classes/jogamp/opengl/util/GLArrayHandlerInterleaved.java
index d31b41582..3119b96ca 100644
--- a/src/jogl/classes/jogamp/opengl/util/GLArrayHandlerInterleaved.java
+++ b/src/jogl/classes/jogamp/opengl/util/GLArrayHandlerInterleaved.java
@@ -28,8 +28,6 @@
package jogamp.opengl.util;
-
-import java.nio.Buffer;
import java.util.ArrayList;
import java.util.List;
@@ -38,61 +36,46 @@ import javax.media.opengl.GL;
import com.jogamp.opengl.util.GLArrayDataEditable;
/**
- * Interleaved fixed function arrays, i.e. where this buffer data
- * represents many arrays.
+ * Interleaved fixed function arrays, i.e. where this buffer data
+ * represents many arrays.
*/
-public class GLArrayHandlerInterleaved implements GLArrayHandler {
- private GLArrayDataEditable ad;
- private List<GLArrayHandlerFlat> subArrays = new ArrayList<GLArrayHandlerFlat>();
+public class GLArrayHandlerInterleaved extends GLVBOArrayHandler {
+ private final List<GLArrayHandlerFlat> subArrays = new ArrayList<GLArrayHandlerFlat>();
- public GLArrayHandlerInterleaved(GLArrayDataEditable ad) {
- this.ad = ad;
+ public GLArrayHandlerInterleaved(final GLArrayDataEditable ad) {
+ super(ad);
}
-
- public final void setSubArrayVBOName(int vboName) {
+
+ @Override
+ public final void setSubArrayVBOName(final int vboName) {
for(int i=0; i<subArrays.size(); i++) {
subArrays.get(i).getData().setVBOName(vboName);
- }
+ }
}
-
- public final void addSubHandler(GLArrayHandlerFlat handler) {
+
+ @Override
+ public final void addSubHandler(final GLArrayHandlerFlat handler) {
subArrays.add(handler);
}
- private final void syncSubData(GL gl, boolean enable, boolean force, Object ext) {
+ private final void syncSubData(final GL gl, final Object ext) {
for(int i=0; i<subArrays.size(); i++) {
- subArrays.get(i).syncData(gl, enable, force, ext);
- }
- }
-
- public final void syncData(GL gl, boolean enable, Object ext) {
- if(enable) {
- final Buffer buffer = ad.getBuffer();
+ subArrays.get(i).syncData(gl, ext);
+ }
+ }
- if(ad.isVBO()) {
- // always bind and refresh the VBO mgr,
- // in case more than one gl*Pointer objects are in use
- gl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
- if(!ad.isVBOWritten()) {
- if(null!=buffer) {
- gl.glBufferData(ad.getVBOTarget(), buffer.limit() * ad.getComponentSizeInBytes(), buffer, ad.getVBOUsage());
- }
- ad.setVBOWritten(true);
- }
- }
- syncSubData(gl, true, true, ext);
- } else {
- syncSubData(gl, false, true, ext);
- if(ad.isVBO()) {
- gl.glBindBuffer(ad.getVBOTarget(), 0);
+ @Override
+ public final void enableState(final GL gl, final boolean enable, final Object ext) {
+ if(enable) {
+ final boolean vboBound = bindBuffer(gl, true);
+ syncSubData(gl, ext);
+ if(vboBound) {
+ bindBuffer(gl, false);
}
}
- }
-
- public final void enableState(GL gl, boolean enable, Object ext) {
for(int i=0; i<subArrays.size(); i++) {
subArrays.get(i).enableState(gl, enable, ext);
- }
+ }
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/GLDataArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/GLDataArrayHandler.java
index 6c8e2e762..66be98215 100644
--- a/src/jogl/classes/jogamp/opengl/util/GLDataArrayHandler.java
+++ b/src/jogl/classes/jogamp/opengl/util/GLDataArrayHandler.java
@@ -28,55 +28,43 @@
package jogamp.opengl.util;
-import javax.media.opengl.*;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLException;
-import com.jogamp.opengl.util.*;
+import com.jogamp.opengl.util.GLArrayDataEditable;
-import java.nio.*;
/**
- * Used for pure VBO data arrays, i.e. where the buffer data
- * does not represents a specific array name.
+ * Used for pure VBO data arrays, i.e. where the buffer data
+ * does not represents a specific array name.
*/
-public class GLDataArrayHandler implements GLArrayHandler {
- private GLArrayDataEditable ad;
+public class GLDataArrayHandler extends GLVBOArrayHandler {
- public GLDataArrayHandler(GLArrayDataEditable ad) {
- this.ad = ad;
+ public GLDataArrayHandler(final GLArrayDataEditable ad) {
+ super(ad);
}
- public final void setSubArrayVBOName(int vboName) {
+ @Override
+ public final void setSubArrayVBOName(final int vboName) {
throw new UnsupportedOperationException();
}
-
- public final void addSubHandler(GLArrayHandlerFlat handler) {
+
+ @Override
+ public final void addSubHandler(final GLArrayHandlerFlat handler) {
throw new UnsupportedOperationException();
}
-
- public final void syncData(GL gl, boolean enable, Object ext) {
- if(!ad.isVBO()) {
- // makes no sense otherwise
- throw new GLException("GLDataArrayHandler can only handle VBOs.");
- }
- if(enable) {
- Buffer buffer = ad.getBuffer();
- // always bind and refresh the VBO mgr,
- // in case more than one gl*Pointer objects are in use
- gl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
- if(!ad.isVBOWritten()) {
- if(null!=buffer) {
- gl.glBufferData(ad.getVBOTarget(), buffer.limit() * ad.getComponentSizeInBytes(), buffer, ad.getVBOUsage());
- }
- ad.setVBOWritten(true);
+ @Override
+ public final void enableState(final GL gl, final boolean enable, final Object ext) {
+ if(enable) {
+ if(!ad.isVBO()) {
+ // makes no sense otherwise
+ throw new GLException("GLDataArrayHandler can only handle VBOs.");
}
- } else {
- gl.glBindBuffer(ad.getVBOTarget(), 0);
- }
- }
-
- public final void enableState(GL gl, boolean enable, Object ext) {
- // no array association
+ bindBuffer(gl, true);
+ bindBuffer(gl, false);
+ }
+ // no array association
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandler.java
index d8939dc0f..f5869c6ba 100644
--- a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandler.java
+++ b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandler.java
@@ -28,47 +28,36 @@
package jogamp.opengl.util;
-import javax.media.opengl.*;
-import javax.media.opengl.fixedfunc.*;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLException;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
import com.jogamp.opengl.util.GLArrayDataEditable;
-import java.nio.*;
-
/**
- * Used for 1:1 fixed function arrays, i.e. where the buffer data
- * represents this array only.
+ * Used for 1:1 fixed function arrays, i.e. where the buffer data
+ * represents this array only.
*/
-public class GLFixedArrayHandler implements GLArrayHandler {
- private GLArrayDataEditable ad;
-
- public GLFixedArrayHandler(GLArrayDataEditable ad) {
- this.ad = ad;
+public class GLFixedArrayHandler extends GLVBOArrayHandler {
+ public GLFixedArrayHandler(final GLArrayDataEditable ad) {
+ super(ad);
}
-
- public final void setSubArrayVBOName(int vboName) {
+
+ @Override
+ public final void setSubArrayVBOName(final int vboName) {
throw new UnsupportedOperationException();
}
-
- public final void addSubHandler(GLArrayHandlerFlat handler) {
+
+ @Override
+ public final void addSubHandler(final GLArrayHandlerFlat handler) {
throw new UnsupportedOperationException();
}
-
- public final void syncData(GL gl, boolean enable, Object ext) {
+
+ @Override
+ public final void enableState(final GL gl, final boolean enable, final Object ext) {
+ final GLPointerFunc glp = gl.getGL2ES1();
if(enable) {
- final Buffer buffer = ad.getBuffer();
- if(ad.isVBO()) {
- // always bind and refresh the VBO mgr,
- // in case more than one gl*Pointer objects are in use
- gl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
- if(!ad.isVBOWritten()) {
- if(null!=buffer) {
- gl.glBufferData(ad.getVBOTarget(), buffer.limit() * ad.getComponentSizeInBytes(), buffer, ad.getVBOUsage());
- }
- ad.setVBOWritten(true);
- }
- }
- final GLPointerFunc glp = gl.getGL2ES1();
+ final boolean vboBound = bindBuffer(gl, true);
switch(ad.getIndex()) {
case GLPointerFunc.GL_VERTEX_ARRAY:
glp.glVertexPointer(ad);
@@ -83,17 +72,12 @@ public class GLFixedArrayHandler implements GLArrayHandler {
glp.glTexCoordPointer(ad);
break;
default:
- throw new GLException("invalid glArrayIndex: "+ad.getIndex()+":\n\t"+ad);
+ throw new GLException("invalid glArrayIndex: "+ad.getIndex()+":\n\t"+ad);
}
- } else if(ad.isVBO()) {
- gl.glBindBuffer(ad.getVBOTarget(), 0);
- }
- }
-
- public final void enableState(GL gl, boolean enable, Object ext) {
- final GLPointerFunc glp = gl.getGL2ES1();
- if(enable) {
- glp.glEnableClientState(ad.getIndex());
+ if(vboBound) {
+ bindBuffer(gl, false);
+ }
+ glp.glEnableClientState(ad.getIndex());
} else {
glp.glDisableClientState(ad.getIndex());
}
diff --git a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java
index 2937cc720..b5fa2f0e5 100644
--- a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java
+++ b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java
@@ -35,46 +35,47 @@ import javax.media.opengl.fixedfunc.GLPointerFunc;
import com.jogamp.opengl.util.GLArrayDataWrapper;
/**
- * Used for interleaved fixed function arrays, i.e. where the buffer data itself is handled
+ * Used for interleaved fixed function arrays, i.e. where the buffer data itself is handled
* separately and interleaves many arrays.
*/
public class GLFixedArrayHandlerFlat implements GLArrayHandlerFlat {
- private GLArrayDataWrapper ad;
+ private final GLArrayDataWrapper ad;
- public GLFixedArrayHandlerFlat(GLArrayDataWrapper ad) {
+ public GLFixedArrayHandlerFlat(final GLArrayDataWrapper ad) {
this.ad = ad;
}
+ @Override
public GLArrayDataWrapper getData() {
return ad;
}
-
- public final void syncData(GL gl, boolean enable, boolean force, Object ext) {
- if(enable) {
- final GLPointerFunc glp = gl.getGL2ES1();
- switch(ad.getIndex()) {
- case GLPointerFunc.GL_VERTEX_ARRAY:
- glp.glVertexPointer(ad);
- break;
- case GLPointerFunc.GL_NORMAL_ARRAY:
- glp.glNormalPointer(ad);
- break;
- case GLPointerFunc.GL_COLOR_ARRAY:
- glp.glColorPointer(ad);
- break;
- case GLPointerFunc.GL_TEXTURE_COORD_ARRAY:
- glp.glTexCoordPointer(ad);
- break;
- default:
- throw new GLException("invalid glArrayIndex: "+ad.getIndex()+":\n\t"+ad);
- }
+
+ @Override
+ public final void syncData(final GL gl, final Object ext) {
+ final GLPointerFunc glp = gl.getGL2ES1();
+ switch(ad.getIndex()) {
+ case GLPointerFunc.GL_VERTEX_ARRAY:
+ glp.glVertexPointer(ad);
+ break;
+ case GLPointerFunc.GL_NORMAL_ARRAY:
+ glp.glNormalPointer(ad);
+ break;
+ case GLPointerFunc.GL_COLOR_ARRAY:
+ glp.glColorPointer(ad);
+ break;
+ case GLPointerFunc.GL_TEXTURE_COORD_ARRAY:
+ glp.glTexCoordPointer(ad);
+ break;
+ default:
+ throw new GLException("invalid glArrayIndex: "+ad.getIndex()+":\n\t"+ad);
}
}
- public final void enableState(GL gl, boolean enable, Object ext) {
+ @Override
+ public final void enableState(final GL gl, final boolean enable, final Object ext) {
final GLPointerFunc glp = gl.getGL2ES1();
if(enable) {
- glp.glEnableClientState(ad.getIndex());
+ glp.glEnableClientState(ad.getIndex());
} else {
glp.glDisableClientState(ad.getIndex());
}
diff --git a/src/jogl/classes/jogamp/opengl/util/GLVBOArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/GLVBOArrayHandler.java
new file mode 100644
index 000000000..7bc1ef1ef
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/GLVBOArrayHandler.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.opengl.util;
+
+import java.nio.Buffer;
+
+import javax.media.opengl.GL;
+
+import com.jogamp.opengl.util.GLArrayDataEditable;
+
+/**
+ * Interleaved fixed function arrays, i.e. where this buffer data
+ * represents many arrays.
+ */
+public abstract class GLVBOArrayHandler implements GLArrayHandler {
+ protected GLArrayDataEditable ad;
+
+ public GLVBOArrayHandler(final GLArrayDataEditable ad) {
+ this.ad = ad;
+ }
+
+ @Override
+ public final boolean bindBuffer(final GL gl, final boolean bind) {
+ if( !ad.isVBO() ) {
+ return false;
+ }
+ if(bind) {
+ // always bind and refresh the VBO mgr,
+ // in case more than one gl*Pointer objects are in use
+ gl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
+ if(!ad.isVBOWritten()) {
+ final Buffer buffer = ad.getBuffer();
+ if(null!=buffer) {
+ gl.glBufferData(ad.getVBOTarget(), buffer.limit() * ad.getComponentSizeInBytes(), buffer, ad.getVBOUsage());
+ }
+ ad.setVBOWritten(true);
+ }
+ } else {
+ gl.glBindBuffer(ad.getVBOTarget(), 0);
+ }
+ return true;
+ }
+
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/av/AudioSampleFormat.java b/src/jogl/classes/jogamp/opengl/util/av/AudioSampleFormat.java
new file mode 100644
index 000000000..4c48b90e8
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/AudioSampleFormat.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.av;
+
+/** FFMPEG/libAV compatible audio sample formats */
+public enum AudioSampleFormat {
+ // NONE = -1,
+ U8, ///< unsigned 8 bits
+ S16, ///< signed 16 bits
+ S32, ///< signed 32 bits
+ FLT, ///< float
+ DBL, ///< double
+
+ U8P, ///< unsigned 8 bits, planar
+ S16P, ///< signed 16 bits, planar
+ S32P, ///< signed 32 bits, planar
+ FLTP, ///< float, planar
+ DBLP, ///< double, planar
+
+ COUNT; ///< Number of sample formats.
+
+ /**
+ * Returns the matching SampleFormat value corresponding to the given SampleFormat's integer ordinal.
+ * <pre>
+ * given:
+ * ordinal = enumValue.ordinal()
+ * reverse:
+ * enumValue = EnumClass.values()[ordinal]
+ * </pre>
+ * @throws IllegalArgumentException if the given ordinal is out of range, i.e. not within [ 0 .. SampleFormat.values().length-1 ]
+ */
+ public static AudioSampleFormat valueOf(final int ordinal) throws IllegalArgumentException {
+ final AudioSampleFormat[] all = AudioSampleFormat.values();
+ if( 0 <= ordinal && ordinal < all.length ) {
+ return all[ordinal];
+ }
+ throw new IllegalArgumentException("Ordinal "+ordinal+" out of range of SampleFormat.values()[0.."+(all.length-1)+"]");
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java
index 6bf8839af..f9df9153f 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -44,72 +44,69 @@ import jogamp.opengl.egl.EGLExt;
public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
final protected TextureType texType;
final protected boolean useKHRSync;
-
+
public enum TextureType {
- GL(0), KHRImage(1);
-
+ GL(0), KHRImage(1);
+
public final int id;
- TextureType(int id){
+ TextureType(final int id){
this.id = id;
}
- }
-
+ }
+
public static class EGLTextureFrame extends TextureSequence.TextureFrame {
-
- public EGLTextureFrame(Buffer clientBuffer, Texture t, long khrImage, long khrSync) {
+
+ public EGLTextureFrame(final Buffer clientBuffer, final Texture t, final long khrImage, final long khrSync) {
super(t);
this.clientBuffer = clientBuffer;
this.image = khrImage;
this.sync = khrSync;
}
-
+
public final Buffer getClientBuffer() { return clientBuffer; }
- public final long getImage() { return image; }
+ public final long getImage() { return image; }
public final long getSync() { return sync; }
-
+
+ @Override
public String toString() {
- return "EGLTextureFrame[" + texture + ", img "+ image + ", sync "+ sync+", clientBuffer "+clientBuffer+"]";
+ return "EGLTextureFrame[pts " + pts + " ms, l " + duration + " ms, texID "+ texture.getTextureObject() + ", img "+ image + ", sync "+ sync+", clientBuffer "+clientBuffer+"]";
}
protected final Buffer clientBuffer;
protected final long image;
protected final long sync;
}
-
- protected EGLMediaPlayerImpl() {
- this(TextureType.GL, false);
- }
-
- protected EGLMediaPlayerImpl(TextureType texType, boolean useKHRSync) {
+
+ protected EGLMediaPlayerImpl(final TextureType texType, final boolean useKHRSync) {
super();
this.texType = texType;
this.useKHRSync = useKHRSync;
}
@Override
- protected TextureSequence.TextureFrame createTexImage(GL gl, int idx, int[] tex) {
- final Texture texture = super.createTexImageImpl(gl, idx, tex, width, height, false);
+ protected TextureSequence.TextureFrame createTexImage(final GL gl, final int texName) {
+ final Texture texture = super.createTexImageImpl(gl, texName, getWidth(), getHeight());
final Buffer clientBuffer;
final long image;
final long sync;
- final boolean eglUsage = TextureType.KHRImage == texType || useKHRSync ;
+ final boolean eglUsage = TextureType.KHRImage == texType || useKHRSync ;
final EGLContext eglCtx;
final EGLExt eglExt;
final EGLDrawable eglDrawable;
-
+
if(eglUsage) {
eglCtx = (EGLContext) gl.getContext();
eglExt = eglCtx.getEGLExt();
- eglDrawable = (EGLDrawable) eglCtx.getGLDrawable();
+ eglDrawable = (EGLDrawable) eglCtx.getGLDrawable();
} else {
eglCtx = null;
eglExt = null;
eglDrawable = null;
}
-
+
if(TextureType.KHRImage == texType) {
- IntBuffer nioTmp = Buffers.newDirectIntBuffer(1);
+ final IntBuffer nioTmp = Buffers.newDirectIntBuffer(1);
// create EGLImage from texture
clientBuffer = null; // FIXME
nioTmp.put(0, EGL.EGL_NONE);
@@ -117,7 +114,7 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
EGLExt.EGL_GL_TEXTURE_2D_KHR,
clientBuffer, nioTmp);
if (0==image) {
- throw new RuntimeException("EGLImage creation failed: "+EGL.eglGetError()+", ctx "+eglCtx+", tex "+tex[idx]+", err "+toHexString(EGL.eglGetError()));
+ throw new RuntimeException("EGLImage creation failed: "+EGL.eglGetError()+", ctx "+eglCtx+", tex "+texName+", err "+toHexString(EGL.eglGetError()));
}
} else {
clientBuffer = null;
@@ -125,12 +122,12 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
}
if(useKHRSync) {
- int[] tmp = new int[1];
+ final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
// Create sync object so that we can be sure that gl has finished
// rendering the EGLImage texture before we tell OpenMAX to fill
// it with a new frame.
- tmp[0] = EGL.EGL_NONE;
- sync = eglExt.eglCreateSyncKHR(eglDrawable.getNativeSurface().getDisplayHandle(), EGLExt.EGL_SYNC_FENCE_KHR, tmp, 0);
+ tmp.put(0, EGL.EGL_NONE);
+ sync = eglExt.eglCreateSyncKHR(eglDrawable.getNativeSurface().getDisplayHandle(), EGLExt.EGL_SYNC_FENCE_KHR, tmp);
if (0==sync) {
throw new RuntimeException("EGLSync creation failed: "+EGL.eglGetError()+", ctx "+eglCtx+", err "+toHexString(EGL.eglGetError()));
}
@@ -139,31 +136,31 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
}
return new EGLTextureFrame(clientBuffer, texture, image, sync);
}
-
+
@Override
- protected void destroyTexImage(GL gl, TextureSequence.TextureFrame imgTex) {
- final boolean eglUsage = TextureType.KHRImage == texType || useKHRSync ;
+ protected void destroyTexFrame(final GL gl, final TextureSequence.TextureFrame frame) {
+ final boolean eglUsage = TextureType.KHRImage == texType || useKHRSync ;
final EGLContext eglCtx;
final EGLExt eglExt;
final EGLDrawable eglDrawable;
-
+
if(eglUsage) {
eglCtx = (EGLContext) gl.getContext();
eglExt = eglCtx.getEGLExt();
- eglDrawable = (EGLDrawable) eglCtx.getGLDrawable();
+ eglDrawable = (EGLDrawable) eglCtx.getGLDrawable();
} else {
eglCtx = null;
eglExt = null;
eglDrawable = null;
}
- final EGLTextureFrame eglTex = (EGLTextureFrame) imgTex;
-
+ final EGLTextureFrame eglTex = (EGLTextureFrame) frame;
+
if(0!=eglTex.getImage()) {
eglExt.eglDestroyImageKHR(eglDrawable.getNativeSurface().getDisplayHandle(), eglTex.getImage());
}
if(0!=eglTex.getSync()) {
eglExt.eglDestroySyncKHR(eglDrawable.getNativeSurface().getDisplayHandle(), eglTex.getSync());
}
- super.destroyTexImage(gl, imgTex);
+ super.destroyTexFrame(gl, frame);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
index 27c926704..0969199c6 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -28,336 +28,688 @@
package jogamp.opengl.util.av;
import java.io.IOException;
-import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.GL;
-import javax.media.opengl.GL2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLES2;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import jogamp.opengl.Debug;
+import com.jogamp.common.net.UriQueryProps;
+import com.jogamp.common.net.Uri;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.LFRingbuffer;
+import com.jogamp.common.util.Ringbuffer;
+import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.util.TimeFrameI;
+import com.jogamp.opengl.util.av.AudioSink;
import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureSequence;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
/**
* After object creation an implementation may customize the behavior:
* <ul>
- * <li>{@link #setTextureCount(int)}</li>
+ * <li>{@link #setDesTextureCount(int)}</li>
* <li>{@link #setTextureTarget(int)}</li>
* <li>{@link EGLMediaPlayerImpl#setEGLTexImageAttribs(boolean, boolean)}.</li>
* </ul>
- *
+ *
* <p>
* See {@link GLMediaPlayer}.
* </p>
*/
public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
+ private static final int STREAM_WORKER_DELAY = Debug.getIntProperty("jogl.debug.GLMediaPlayer.StreamWorker.delay", false, 0);
+
+ private static final String unknown = "unknown";
+
+ private volatile State state;
+ private final Object stateLock = new Object();
+
+ private int textureCount;
+ private int textureTarget;
+ private int textureFormat;
+ private int textureInternalFormat;
+ private int textureType;
+ private int texUnit;
+
+ private int textureFragmentShaderHashCode;
+
+ private final int[] texMinMagFilter = { GL.GL_NEAREST, GL.GL_NEAREST };
+ private final int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE };
+
+ /** User requested URI stream location. */
+ private Uri streamLoc = null;
+
+ /**
+ * In case {@link #streamLoc} is a {@link GLMediaPlayer#CameraInputScheme},
+ * {@link #cameraPath} holds the URI's path portion
+ * as parsed in {@link #initStream(Uri, int, int, int)}.
+ * @see #cameraProps
+ */
+ protected Uri.Encoded cameraPath = null;
+ /** Optional camera properties, see {@link #cameraPath}. */
+ protected Map<String, String> cameraProps = null;
+
+ private volatile float playSpeed = 1.0f;
+ private float audioVolume = 1.0f;
+
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private int vid = GLMediaPlayer.STREAM_ID_AUTO;
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private int aid = GLMediaPlayer.STREAM_ID_AUTO;
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private int width = 0;
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private int height = 0;
+ /** Video avg. fps. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private float fps = 0;
+ /** Video avg. frame duration in ms. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private float frame_duration = 0f;
+ /** Stream bps. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private int bps_stream = 0;
+ /** Video bps. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private int bps_video = 0;
+ /** Audio bps. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private int bps_audio = 0;
+ /** In frames. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private int videoFrames = 0;
+ /** In frames. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private int audioFrames = 0;
+ /** In ms. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private int duration = 0;
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private String acodec = unknown;
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ private String vcodec = unknown;
+
+ private volatile int decodedFrameCount = 0;
+ private int presentedFrameCount = 0;
+ private int displayedFrameCount = 0;
+ private volatile int video_pts_last = 0;
+
+ /**
+ * Help detect EOS, limit is {@link #MAX_FRAMELESS_MS_UNTIL_EOS}.
+ * To be used either by getNextTexture(..) or StreamWorker for audio-only.
+ */
+ private int nullFrameCount = 0;
+ private int maxNullFrameCountUntilEOS = 0;
+ /**
+ * Help detect EOS, limit {@value} milliseconds without a valid frame.
+ */
+ private static final int MAX_FRAMELESS_MS_UNTIL_EOS = 5000;
+ private static final int MAX_FRAMELESS_UNTIL_EOS_DEFAULT = MAX_FRAMELESS_MS_UNTIL_EOS / 30; // default value assuming 30fps
+
+ /** See {@link #getAudioSink()}. Set by implementation if used from within {@link #initStreamImpl(int, int)}! */
+ protected AudioSink audioSink = null;
+ protected boolean audioSinkPlaySpeedSet = false;
- protected static final String unknown = "unknown";
-
- protected State state;
- protected int textureCount;
- protected int textureTarget;
- protected int textureFormat;
- protected int textureInternalFormat;
- protected int textureType;
- protected int texUnit;
-
-
- protected int[] texMinMagFilter = { GL.GL_NEAREST, GL.GL_NEAREST };
- protected int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE };
-
- protected URLConnection urlConn = null;
-
- protected float playSpeed = 1.0f;
-
- /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
- protected int width = 0;
- /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
- protected int height = 0;
- /** Video fps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
- protected float fps = 0;
- /** Stream bps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
- protected int bps_stream = 0;
- /** Video bps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
- protected int bps_video = 0;
- /** Audio bps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
- protected int bps_audio = 0;
- /** In frames. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
- protected int totalFrames = 0;
- /** In ms. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
- protected int duration = 0;
- /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
- protected String acodec = unknown;
- /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
- protected String vcodec = unknown;
-
- protected int frameNumber = 0;
-
- protected TextureSequence.TextureFrame[] texFrames = null;
- protected HashMap<Integer, TextureSequence.TextureFrame> texFrameMap = new HashMap<Integer, TextureSequence.TextureFrame>();
- private ArrayList<GLMediaEventListener> eventListeners = new ArrayList<GLMediaEventListener>();
+ /** System Clock Reference (SCR) of first audio PTS at start time. */
+ private long audio_scr_t0 = 0;
+ private boolean audioSCR_reset = true;
+
+ /** System Clock Reference (SCR) of first video frame at start time. */
+ private long video_scr_t0 = 0;
+ /** System Clock Reference (SCR) PTS offset, i.e. first video PTS at start time. */
+ private int video_scr_pts = 0;
+ /** Cumulative video pts diff. */
+ private float video_dpts_cum = 0;
+ /** Cumulative video frames. */
+ private int video_dpts_count = 0;
+ /** Number of min frame count required for video cumulative sync. */
+ private static final int VIDEO_DPTS_NUM = 20;
+ /** Cumulative coefficient, value {@value}. */
+ private static final float VIDEO_DPTS_COEFF = 0.7943282f; // (float) Math.exp(Math.log(0.01) / VIDEO_DPTS_NUM);
+ /** Maximum valid video pts diff. */
+ private static final int VIDEO_DPTS_MAX = 5000; // 5s max diff
+ /** Trigger video PTS reset with given cause as bitfield. */
+ private boolean videoSCR_reset = false;
+
+ private TextureFrame[] videoFramesOrig = null;
+ private Ringbuffer<TextureFrame> videoFramesFree = null;
+ private Ringbuffer<TextureFrame> videoFramesDecoded = null;
+ private volatile TextureFrame lastFrame = null;
+ /**
+ * @see #isGLOriented()
+ */
+ private boolean isInGLOrientation = false;
+
+ private final ArrayList<GLMediaEventListener> eventListeners = new ArrayList<GLMediaEventListener>();
protected GLMediaPlayerImpl() {
- this.textureCount=3;
+ this.textureCount=0;
this.textureTarget=GL.GL_TEXTURE_2D;
this.textureFormat = GL.GL_RGBA;
this.textureInternalFormat = GL.GL_RGBA;
- this.textureType = GL.GL_UNSIGNED_BYTE;
+ this.textureType = GL.GL_UNSIGNED_BYTE;
this.texUnit = 0;
+ this.textureFragmentShaderHashCode = 0;
this.state = State.Uninitialized;
}
@Override
- public void setTextureUnit(int u) { texUnit = u; }
-
+ public final void setTextureUnit(final int u) { texUnit = u; }
+
+ @Override
+ public final int getTextureUnit() { return texUnit; }
+
@Override
- public int getTextureUnit() { return texUnit; }
-
- protected final void setTextureCount(int textureCount) {
- this.textureCount=textureCount;
- }
+ public final int getTextureTarget() { return textureTarget; }
+
+ protected final int getTextureFormat() { return textureFormat; }
+
+ protected final int getTextureType() { return textureType; }
+
@Override
public final int getTextureCount() { return textureCount; }
-
- protected final void setTextureTarget(int target) { textureTarget=target; }
- protected final void setTextureFormat(int internalFormat, int format) {
- textureInternalFormat=internalFormat;
- textureFormat=format;
- }
- protected final void setTextureType(int t) { textureType=t; }
-
- public final void setTextureMinMagFilter(int[] minMagFilter) { texMinMagFilter[0] = minMagFilter[0]; texMinMagFilter[1] = minMagFilter[1];}
+
+ protected final void setTextureTarget(final int target) { textureTarget=target; }
+ protected final void setTextureFormat(final int internalFormat, final int format) {
+ textureInternalFormat=internalFormat;
+ textureFormat=format;
+ }
+ protected final void setTextureType(final int t) { textureType=t; }
+
+ @Override
+ public final void setTextureMinMagFilter(final int[] minMagFilter) { texMinMagFilter[0] = minMagFilter[0]; texMinMagFilter[1] = minMagFilter[1];}
+ @Override
public final int[] getTextureMinMagFilter() { return texMinMagFilter; }
-
- public final void setTextureWrapST(int[] wrapST) { texWrapST[0] = wrapST[0]; texWrapST[1] = wrapST[1];}
- public final int[] getTextureWrapST() { return texWrapST; }
@Override
- public final TextureSequence.TextureFrame getLastTexture() throws IllegalStateException {
- if(State.Uninitialized == state) {
- throw new IllegalStateException("Instance not initialized: "+this);
- }
- return getLastTextureImpl();
- }
- protected abstract TextureSequence.TextureFrame getLastTextureImpl();
-
+ public final void setTextureWrapST(final int[] wrapST) { texWrapST[0] = wrapST[0]; texWrapST[1] = wrapST[1];}
@Override
- public final synchronized TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking) throws IllegalStateException {
- if(State.Uninitialized == state) {
- throw new IllegalStateException("Instance not initialized: "+this);
- }
- if(State.Playing == state) {
- final TextureSequence.TextureFrame f = getNextTextureImpl(gl, blocking);
- return f;
+ public final int[] getTextureWrapST() { return texWrapST; }
+
+ private final void checkGLInit() {
+ if(State.Uninitialized == state || State.Initialized == state ) {
+ throw new IllegalStateException("GL not initialized: "+this);
}
- return getLastTextureImpl();
}
- protected abstract TextureSequence.TextureFrame getNextTextureImpl(GL gl, boolean blocking);
-
+
@Override
public String getRequiredExtensionsShaderStub() throws IllegalStateException {
- if(State.Uninitialized == state) {
- throw new IllegalStateException("Instance not initialized: "+this);
- }
+ checkGLInit();
if(GLES2.GL_TEXTURE_EXTERNAL_OES == textureTarget) {
- return TextureSequence.GL_OES_EGL_image_external_Required_Prelude;
+ return ShaderCode.createExtensionDirective(GLExtensions.OES_EGL_image_external, ShaderCode.ENABLE);
}
return "";
}
-
+
@Override
public String getTextureSampler2DType() throws IllegalStateException {
- if(State.Uninitialized == state) {
- throw new IllegalStateException("Instance not initialized: "+this);
- }
+ checkGLInit();
switch(textureTarget) {
case GL.GL_TEXTURE_2D:
- case GL2.GL_TEXTURE_RECTANGLE:
+ case GL2GL3.GL_TEXTURE_RECTANGLE:
return TextureSequence.sampler2D;
case GLES2.GL_TEXTURE_EXTERNAL_OES:
return TextureSequence.samplerExternalOES;
default:
- throw new GLException("Unsuported texture target: "+toHexString(textureTarget));
+ throw new GLException("Unsuported texture target: "+toHexString(textureTarget));
}
}
-
+
/**
* {@inheritDoc}
- *
+ *
* This implementation simply returns the build-in function name of <code>texture2D</code>,
* if not overridden by specialization.
*/
@Override
- public String getTextureLookupFunctionName(String desiredFuncName) throws IllegalStateException {
- if(State.Uninitialized == state) {
- throw new IllegalStateException("Instance not initialized: "+this);
- }
+ public String getTextureLookupFunctionName(final String desiredFuncName) throws IllegalStateException {
+ checkGLInit();
return "texture2D";
}
-
+
/**
* {@inheritDoc}
- *
- * This implementation simply returns an empty string since it's using
+ *
+ * This implementation simply returns an empty string since it's using
* the build-in function <code>texture2D</code>,
* if not overridden by specialization.
*/
@Override
public String getTextureLookupFragmentShaderImpl() throws IllegalStateException {
- if(State.Uninitialized == state) {
- throw new IllegalStateException("Instance not initialized: "+this);
- }
- return "";
+ checkGLInit();
+ return "";
}
-
+
@Override
- public final synchronized float getPlaySpeed() {
- return playSpeed;
+ public final int getTextureFragmentShaderHashCode() {
+ if( !isTextureAvailable() ) {
+ textureFragmentShaderHashCode = 0;
+ return 0;
+ } else if( 0 == textureFragmentShaderHashCode ) {
+ int hash = 31 + getTextureLookupFragmentShaderImpl().hashCode();
+ hash = ((hash << 5) - hash) + getTextureSampler2DType().hashCode();
+ textureFragmentShaderHashCode = hash;
+ }
+ return textureFragmentShaderHashCode;
}
-
+
@Override
- public final synchronized void setPlaySpeed(float rate) {
- if(State.Uninitialized != state && setPlaySpeedImpl(rate)) {
- playSpeed = rate;
+ public final int getDecodedFrameCount() { return decodedFrameCount; }
+
+ @Override
+ public final int getPresentedFrameCount() { return presentedFrameCount; }
+
+ @Override
+ public final int getVideoPTS() { return video_pts_last; }
+
+ @Override
+ public final int getAudioPTS() {
+ if( State.Uninitialized != state ) {
+ return getAudioPTSImpl();
}
- if(DEBUG) { System.err.println("SetPlaySpeed: "+toString()); }
+ return 0;
}
- protected abstract boolean setPlaySpeedImpl(float rate);
-
- public final State start() {
- switch(state) {
- case Stopped:
- case Paused:
- if(startImpl()) {
- state = State.Playing;
- }
+ /** Override if not using audioSink! */
+ protected int getAudioPTSImpl() {
+ if( null != audioSink ) {
+ return audioSink.getPTS();
+ } else {
+ return 0;
}
- if(DEBUG) { System.err.println("Start: "+toString()); }
- return state;
}
- protected abstract boolean startImpl();
-
- public final State pause() {
- if(State.Playing == state && pauseImpl()) {
- state = State.Paused;
+
+ @Override
+ public final State getState() { return state; }
+
+ protected final void setState(final State s) { state=s; }
+
+ @Override
+ public final State play() {
+ synchronized( stateLock ) {
+ final State preState = state;
+ switch( state ) {
+ case Paused:
+ if( playImpl() ) {
+ resetAVPTS();
+ if( null != audioSink ) {
+ audioSink.play(); // cont. w/ new data
+ }
+ if( null != streamWorker ) {
+ streamWorker.doResume();
+ }
+ changeState(0, State.Playing);
+ }
+ default:
+ }
+ if(DEBUG) { System.err.println("Play: "+preState+" -> "+state+", "+toString()); }
+ return state;
}
- if(DEBUG) { System.err.println("Pause: "+toString()); }
- return state;
}
- protected abstract boolean pauseImpl();
-
- public final State stop() {
- switch(state) {
- case Playing:
- case Paused:
- if(stopImpl()) {
- state = State.Stopped;
+ protected abstract boolean playImpl();
+
+ @Override
+ public final State pause(final boolean flush) {
+ return pauseImpl(flush, 0);
+ }
+ private final State pauseImpl(final boolean flush, int event_mask) {
+ synchronized( stateLock ) {
+ final State preState = state;
+ if( State.Playing == state ) {
+ event_mask = addStateEventMask(event_mask, GLMediaPlayer.State.Paused);
+ setState( State.Paused );
+ if( null != streamWorker ) {
+ streamWorker.doPause();
}
+ if( flush ) {
+ resetAVPTSAndFlush();
+ } else if( null != audioSink ) {
+ audioSink.pause();
+ }
+ attributesUpdated( event_mask );
+ if( !pauseImpl() ) {
+ play();
+ }
+ }
+ if(DEBUG) { System.err.println("Pause: "+preState+" -> "+state+", "+toString()); }
+ return state;
}
- if(DEBUG) { System.err.println("Stop: "+toString()); }
- return state;
}
- protected abstract boolean stopImpl();
-
+ protected abstract boolean pauseImpl();
+
@Override
- public final int getCurrentPosition() {
- if(State.Uninitialized != state) {
- return getCurrentPositionImpl();
+ public final State destroy(final GL gl) {
+ return destroyImpl(gl, 0);
+ }
+ private final State destroyImpl(final GL gl, final int event_mask) {
+ synchronized( stateLock ) {
+ if( null != streamWorker ) {
+ streamWorker.doStop();
+ streamWorker = null;
+ }
+ destroyImpl(gl);
+ removeAllTextureFrames(gl);
+ textureCount=0;
+ changeState(event_mask, State.Uninitialized);
+ attachedObjects.clear();
+ return state;
}
- return 0;
}
- protected abstract int getCurrentPositionImpl();
-
+ protected abstract void destroyImpl(GL gl);
+
+ @Override
public final int seek(int msec) {
- final int cp;
- switch(state) {
- case Stopped:
- case Playing:
- case Paused:
- cp = seekImpl(msec);
- break;
- default:
- cp = 0;
+ synchronized( stateLock ) {
+ final State preState = state;
+ final int pts1;
+ switch(state) {
+ case Playing:
+ case Paused:
+ final State _state = state;
+ setState( State.Paused );
+ if( null != streamWorker ) {
+ streamWorker.doPause();
+ }
+ // Adjust target ..
+ if( msec >= duration ) {
+ msec = duration - (int)Math.floor(frame_duration);
+ } else if( msec < 0 ) {
+ msec = 0;
+ }
+ pts1 = seekImpl(msec);
+ resetAVPTSAndFlush();
+ if( null != audioSink && State.Playing == _state ) {
+ audioSink.play(); // cont. w/ new data
+ }
+ if(DEBUG) {
+ System.err.println("Seek("+msec+"): "+getPerfString());
+ }
+ if( null != streamWorker ) {
+ streamWorker.doResume();
+ }
+ setState( _state );
+ break;
+ default:
+ pts1 = 0;
+ }
+ if(DEBUG) { System.err.println("Seek("+msec+"): "+preState+" -> "+state+", "+toString()); }
+ return pts1;
}
- if(DEBUG) { System.err.println("Seek("+msec+"): "+toString()); }
- return cp;
}
protected abstract int seekImpl(int msec);
-
- public final State getState() { return state; }
-
- @Override
- public final State initGLStream(GL gl, URLConnection urlConn) throws IllegalStateException, GLException, IOException {
- if(State.Uninitialized != state) {
- throw new IllegalStateException("Instance not in state "+State.Uninitialized+", but "+state+", "+this);
- }
- this.urlConn = urlConn;
- if (this.urlConn != null) {
- try {
- if(null != gl) {
- if(null!=texFrames) {
- // re-init ..
- removeAllImageTextures(gl);
- } else {
- texFrames = new TextureSequence.TextureFrame[textureCount];
- }
- final int[] tex = new int[textureCount];
- {
- gl.glGenTextures(textureCount, tex, 0);
- final int err = gl.glGetError();
- if( GL.GL_NO_ERROR != err ) {
- throw new RuntimeException("TextureNames creation failed (num: "+textureCount+"): err "+toHexString(err));
- }
+
+ @Override
+ public final float getPlaySpeed() { return playSpeed; }
+
+ @Override
+ public final boolean setPlaySpeed(float rate) {
+ synchronized( stateLock ) {
+ final float preSpeed = playSpeed;
+ boolean res = false;
+ if(State.Uninitialized != state ) {
+ if( rate > 0.01f ) {
+ if( Math.abs(1.0f - rate) < 0.01f ) {
+ rate = 1.0f;
}
- initGLStreamImpl(gl, tex);
-
- for(int i=0; i<textureCount; i++) {
- final TextureSequence.TextureFrame tf = createTexImage(gl, i, tex);
- texFrames[i] = tf;
- texFrameMap.put(tex[i], tf);
+ if( setPlaySpeedImpl(rate) ) {
+ resetAVPTS();
+ playSpeed = rate;
+ res = true;
}
}
- state = State.Stopped;
- return state;
- } catch (Throwable t) {
- throw new GLException("Error initializing GL resources", t);
}
+ if(DEBUG) { System.err.println("setPlaySpeed("+rate+"): "+state+", "+preSpeed+" -> "+playSpeed+", "+toString()); }
+ return res;
+ }
+ }
+ /**
+ * Override if not using AudioSink, or AudioSink's {@link AudioSink#setPlaySpeed(float)} is not sufficient!
+ * <p>
+ * AudioSink shall respect <code>!audioSinkPlaySpeedSet</code> to determine data_size
+ * at {@link AudioSink#enqueueData(com.jogamp.opengl.util.av.AudioSink.AudioFrame)}.
+ * </p>
+ */
+ protected boolean setPlaySpeedImpl(final float rate) {
+ if( null != audioSink ) {
+ audioSinkPlaySpeedSet = audioSink.setPlaySpeed(rate);
}
- return state;
+ // still true, even if audioSink rejects command since we deal w/ video sync
+ // and AudioSink w/ audioSinkPlaySpeedSet at enqueueData(..).
+ return true;
+ }
+
+ @Override
+ public final float getAudioVolume() {
+ getAudioVolumeImpl();
+ return audioVolume;
}
-
/**
- * Implementation shall set the following set of data here
- * @param gl TODO
- * @param texNames TODO
+ * Override if not using AudioSink, or AudioSink's {@link AudioSink#getVolume()} is not sufficient!
+ */
+ protected void getAudioVolumeImpl() {
+ if( null != audioSink ) {
+ audioVolume = audioSink.getVolume();
+ }
+ }
+
+ @Override
+ public boolean setAudioVolume(float v) {
+ synchronized( stateLock ) {
+ final float preVolume = audioVolume;
+ boolean res = false;
+ if(State.Uninitialized != state ) {
+ if( Math.abs(v) < 0.01f ) {
+ v = 0.0f;
+ } else if( Math.abs(1.0f - v) < 0.01f ) {
+ v = 1.0f;
+ }
+ if( setAudioVolumeImpl(v) ) {
+ audioVolume = v;
+ res = true;
+ }
+ }
+ if(DEBUG) { System.err.println("setAudioVolume("+v+"): "+state+", "+preVolume+" -> "+audioVolume+", "+toString()); }
+ return res;
+ }
+ }
+ /**
+ * Override if not using AudioSink, or AudioSink's {@link AudioSink#setVolume(float)} is not sufficient!
+ */
+ protected boolean setAudioVolumeImpl(final float v) {
+ if( null != audioSink ) {
+ return audioSink.setVolume(v);
+ }
+ // still true, even if audioSink rejects command ..
+ return true;
+ }
+
+ @Override
+ public final void initStream(final Uri streamLoc, final int vid, final int aid, final int reqTextureCount) throws IllegalStateException, IllegalArgumentException {
+ synchronized( stateLock ) {
+ if(State.Uninitialized != state) {
+ throw new IllegalStateException("Instance not in state unintialized: "+this);
+ }
+ if(null == streamLoc) {
+ throw new IllegalArgumentException("streamLock is null");
+ }
+ if( STREAM_ID_NONE != vid ) {
+ textureCount = validateTextureCount(reqTextureCount);
+ if( textureCount < TEXTURE_COUNT_MIN ) {
+ throw new InternalError("Validated texture count < "+TEXTURE_COUNT_MIN+": "+textureCount);
+ }
+ } else {
+ textureCount = 0;
+ }
+ decodedFrameCount = 0;
+ presentedFrameCount = 0;
+ displayedFrameCount = 0;
+ nullFrameCount = 0;
+ maxNullFrameCountUntilEOS = MAX_FRAMELESS_UNTIL_EOS_DEFAULT;
+ this.streamLoc = streamLoc;
+
+ // Pre-parse for camera-input scheme
+ cameraPath = null;
+ cameraProps = null;
+ final Uri.Encoded streamLocScheme = streamLoc.scheme;
+ if( null != streamLocScheme && streamLocScheme.equals(CameraInputScheme) ) {
+ final Uri.Encoded rawPath = streamLoc.path;
+ if( null != rawPath && rawPath.length() > 0 ) {
+ // cut-off root fwd-slash
+ cameraPath = rawPath.substring(1);
+ final UriQueryProps props = UriQueryProps.create(streamLoc, ';');
+ cameraProps = props.getProperties();
+ } else {
+ throw new IllegalArgumentException("Camera path is empty: "+streamLoc.toString());
+ }
+ }
+
+ this.vid = vid;
+ this.aid = aid;
+ new Thread() {
+ public void run() {
+ try {
+ // StreamWorker may be used, see API-doc of StreamWorker
+ initStreamImpl(vid, aid);
+ } catch (final Throwable t) {
+ streamErr = new StreamException(t.getClass().getSimpleName()+" while initializing: "+GLMediaPlayerImpl.this.toString(), t);
+ changeState(GLMediaEventListener.EVENT_CHANGE_ERR, GLMediaPlayer.State.Uninitialized);
+ } // also initializes width, height, .. etc
+ }
+ }.start();
+ }
+ }
+ /**
+ * Implementation shall set the following set of data here
+ * @see #vid
+ * @see #aid
* @see #width
* @see #height
* @see #fps
* @see #bps_stream
- * @see #totalFrames
+ * @see #videoFrames
+ * @see #audioFrames
* @see #acodec
* @see #vcodec
*/
- protected abstract void initGLStreamImpl(GL gl, int[] texNames) throws IOException;
-
- protected TextureSequence.TextureFrame createTexImage(GL gl, int idx, int[] tex) {
- return new TextureSequence.TextureFrame( createTexImageImpl(gl, idx, tex, width, height, false) );
+ protected abstract void initStreamImpl(int vid, int aid) throws Exception;
+
+ @Override
+ public final StreamException getStreamException() {
+ final StreamException e;
+ synchronized( stateLock ) {
+ e = streamErr;
+ streamErr = null;
+ }
+ return e;
+ }
+
+ @Override
+ public final void initGL(final GL gl) throws IllegalStateException, StreamException, GLException {
+ synchronized( stateLock ) {
+ if(State.Initialized != state ) {
+ throw new IllegalStateException("Stream not in state initialized: "+this);
+ }
+ if( null != streamWorker ) {
+ final StreamException streamInitErr = getStreamException();
+ if( null != streamInitErr ) {
+ streamWorker = null; // already terminated!
+ destroy(null);
+ throw streamInitErr;
+ }
+ }
+ try {
+ if( STREAM_ID_NONE != vid ) {
+ removeAllTextureFrames(gl);
+ initGLImpl(gl);
+ if(DEBUG) {
+ System.err.println("initGLImpl.X "+this);
+ }
+ videoFramesOrig = createTexFrames(gl, textureCount);
+ if( TEXTURE_COUNT_MIN == textureCount ) {
+ videoFramesFree = null;
+ videoFramesDecoded = null;
+ lastFrame = videoFramesOrig[0];
+ } else {
+ videoFramesFree = new LFRingbuffer<TextureFrame>(videoFramesOrig);
+ videoFramesDecoded = new LFRingbuffer<TextureFrame>(TextureFrame[].class, textureCount);
+ lastFrame = videoFramesFree.getBlocking( );
+ }
+ if( null != streamWorker ) {
+ streamWorker.initGL(gl);
+ }
+ } else {
+ removeAllTextureFrames(null);
+ initGLImpl(null);
+ setTextureFormat(-1, -1);
+ setTextureType(-1);
+ videoFramesOrig = null;
+ videoFramesFree = null;
+ videoFramesDecoded = null;
+ lastFrame = null;
+ }
+ changeState(0, State.Paused);
+ } catch (final Throwable t) {
+ destroyImpl(gl, GLMediaEventListener.EVENT_CHANGE_ERR); // -> GLMediaPlayer.State.Uninitialized
+ throw new GLException("Error initializing GL resources", t);
+ }
+ }
+ }
+ /**
+ * Shall initialize all GL related resources, if not audio-only.
+ * <p>
+ * Shall also take care of {@link AudioSink} initialization if appropriate.
+ * </p>
+ * @param gl null for audio-only, otherwise a valid and current GL object.
+ * @throws IOException
+ * @throws GLException
+ */
+ protected abstract void initGLImpl(GL gl) throws IOException, GLException;
+
+ /**
+ * Returns the validated number of textures to be handled.
+ * <p>
+ * Default is {@link #TEXTURE_COUNT_DEFAULT} minimum textures, if <code>desiredTextureCount</code>
+ * is < {@link #TEXTURE_COUNT_MIN}, {@link #TEXTURE_COUNT_MIN} is returned.
+ * </p>
+ * <p>
+ * Implementation must at least return a texture count of {@link #TEXTURE_COUNT_MIN}, <i>two</i>, the last texture and the decoding texture.
+ * </p>
+ */
+ protected int validateTextureCount(final int desiredTextureCount) {
+ return desiredTextureCount < TEXTURE_COUNT_MIN ? TEXTURE_COUNT_MIN : desiredTextureCount;
+ }
+
+ protected TextureFrame[] createTexFrames(final GL gl, final int count) {
+ final int[] texNames = new int[count];
+ gl.glGenTextures(count, texNames, 0);
+ final int err = gl.glGetError();
+ if( GL.GL_NO_ERROR != err ) {
+ throw new RuntimeException("TextureNames creation failed (num: "+count+"): err "+toHexString(err));
+ }
+ final TextureFrame[] texFrames = new TextureFrame[count];
+ for(int i=0; i<count; i++) {
+ texFrames[i] = createTexImage(gl, texNames[i]);
+ }
+ return texFrames;
}
-
- protected Texture createTexImageImpl(GL gl, int idx, int[] tex, int tWidth, int tHeight, boolean mustFlipVertically) {
- if( 0 > tex[idx] ) {
- throw new RuntimeException("TextureName "+toHexString(tex[idx])+" invalid.");
+ protected abstract TextureFrame createTexImage(GL gl, int texName);
+
+ protected final Texture createTexImageImpl(final GL gl, final int texName, final int tWidth, final int tHeight) {
+ if( 0 > texName ) {
+ throw new RuntimeException("TextureName "+toHexString(texName)+" invalid.");
}
gl.glActiveTexture(GL.GL_TEXTURE0+getTextureUnit());
- gl.glBindTexture(textureTarget, tex[idx]);
+ gl.glBindTexture(textureTarget, texName);
{
final int err = gl.glGetError();
if( GL.GL_NO_ERROR != err ) {
- throw new RuntimeException("Couldn't bind textureName "+toHexString(tex[idx])+" to 2D target, err "+toHexString(err));
+ throw new RuntimeException("Couldn't bind textureName "+toHexString(texName)+" to 2D target, err "+toHexString(err));
}
}
@@ -376,55 +728,696 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
{
final int err = gl.glGetError();
if( GL.GL_NO_ERROR != err ) {
- throw new RuntimeException("Couldn't create TexImage2D RGBA "+tWidth+"x"+tHeight+", err "+toHexString(err));
+ throw new RuntimeException("Couldn't create TexImage2D RGBA "+tWidth+"x"+tHeight+", target "+toHexString(textureTarget)+
+ ", ifmt "+toHexString(textureInternalFormat)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType)+
+ ", err "+toHexString(err));
}
}
if(DEBUG) {
System.err.println("Created TexImage2D RGBA "+tWidth+"x"+tHeight+", target "+toHexString(textureTarget)+
- ", ifmt "+toHexString(GL.GL_RGBA)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType));
+ ", ifmt "+toHexString(textureInternalFormat)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType));
}
}
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, texMinMagFilter[0]);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[1]);
+ gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[1]);
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, texWrapST[0]);
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, texWrapST[1]);
-
- return com.jogamp.opengl.util.texture.TextureIO.newTexture(tex[idx],
- textureTarget,
- tWidth, tHeight,
- width, height,
- mustFlipVertically);
- }
-
- protected void destroyTexImage(GL gl, TextureSequence.TextureFrame imgTex) {
- imgTex.getTexture().destroy(gl);
- }
-
- protected void removeAllImageTextures(GL gl) {
- if(null != texFrames) {
- for(int i=0; i<textureCount; i++) {
- final TextureSequence.TextureFrame imgTex = texFrames[i];
- if(null != imgTex) {
- destroyTexImage(gl, imgTex);
+
+ return new Texture(texName, textureTarget,
+ tWidth, tHeight, width, height, !isInGLOrientation);
+ }
+
+ protected void destroyTexFrame(final GL gl, final TextureFrame frame) {
+ frame.getTexture().destroy(gl);
+ }
+
+ @Override
+ public final boolean isTextureAvailable() {
+ return State.Paused == state || State.Playing == state;
+ }
+
+ @Override
+ public final TextureFrame getLastTexture() throws IllegalStateException {
+ if( State.Paused != state && State.Playing != state ) {
+ throw new IllegalStateException("Instance not paused or playing: "+this);
+ }
+ return lastFrame;
+ }
+
+ private final void removeAllTextureFrames(final GL gl) {
+ final TextureFrame[] texFrames = videoFramesOrig;
+ videoFramesOrig = null;
+ videoFramesFree = null;
+ videoFramesDecoded = null;
+ lastFrame = null;
+ if( null != texFrames ) {
+ for(int i=0; i<texFrames.length; i++) {
+ final TextureFrame frame = texFrames[i];
+ if(null != frame) {
+ if( null != gl ) {
+ destroyTexFrame(gl, frame);
+ }
texFrames[i] = null;
}
+ if( DEBUG ) {
+ System.err.println(Thread.currentThread().getName()+"> Clear TexFrame["+i+"]: "+frame+" -> null");
+ }
}
}
- texFrameMap.clear();
}
- protected final void updateAttributes(int width, int height, int bps_stream, int bps_video, int bps_audio,
- float fps, int totalFrames, int duration,
- String vcodec, String acodec) {
+ private TextureFrame cachedFrame = null;
+ private long lastTimeMillis = 0;
+
+ private final boolean[] stGotVFrame = { false };
+
+ @Override
+ public final TextureFrame getNextTexture(final GL gl) throws IllegalStateException {
+ synchronized( stateLock ) {
+ if( State.Paused != state && State.Playing != state ) {
+ throw new IllegalStateException("Instance not paused or playing: "+this);
+ }
+ if(State.Playing == state) {
+ boolean dropFrame = false;
+ try {
+ do {
+ final boolean droppedFrame;
+ if( dropFrame ) {
+ presentedFrameCount--;
+ dropFrame = false;
+ droppedFrame = true;
+ } else {
+ droppedFrame = false;
+ }
+ final boolean playCached = null != cachedFrame;
+ final int video_pts;
+ final boolean hasVideoFrame;
+ TextureFrame nextFrame;
+ if( playCached ) {
+ nextFrame = cachedFrame;
+ cachedFrame = null;
+ presentedFrameCount--;
+ video_pts = nextFrame.getPTS();
+ hasVideoFrame = true;
+ } else {
+ if( null != videoFramesDecoded ) {
+ // multi-threaded and video available
+ nextFrame = videoFramesDecoded.get();
+ if( null != nextFrame ) {
+ video_pts = nextFrame.getPTS();
+ hasVideoFrame = true;
+ } else {
+ video_pts = TimeFrameI.INVALID_PTS;
+ hasVideoFrame = false;
+ }
+ } else {
+ // single-threaded or audio-only
+ video_pts = getNextSingleThreaded(gl, lastFrame, stGotVFrame);
+ nextFrame = lastFrame;
+ hasVideoFrame = stGotVFrame[0];
+ }
+ }
+ final long currentTimeMillis = Platform.currentTimeMillis();
+
+ if( TimeFrameI.END_OF_STREAM_PTS == video_pts ||
+ ( duration > 0 && duration <= video_pts ) || maxNullFrameCountUntilEOS <= nullFrameCount )
+ {
+ // EOS
+ if( DEBUG ) {
+ System.err.println( "AV-EOS (getNextTexture): EOS_PTS "+(TimeFrameI.END_OF_STREAM_PTS == video_pts)+", "+this);
+ }
+ pauseImpl(true, GLMediaEventListener.EVENT_CHANGE_EOS);
+
+ } else if( TimeFrameI.INVALID_PTS == video_pts ) { // no audio or video frame
+ if( null == videoFramesDecoded || !videoFramesDecoded.isEmpty() ) {
+ nullFrameCount++;
+ }
+ if( DEBUG ) {
+ final int audio_pts = getAudioPTSImpl();
+ final int audio_scr = (int) ( ( currentTimeMillis - audio_scr_t0 ) * playSpeed );
+ final int d_apts;
+ if( audio_pts != TimeFrameI.INVALID_PTS ) {
+ d_apts = audio_pts - audio_scr;
+ } else {
+ d_apts = 0;
+ }
+ final int video_scr = video_scr_pts + (int) ( ( currentTimeMillis - video_scr_t0 ) * playSpeed );
+ final int d_vpts = video_pts - video_scr;
+ System.err.println( "AV~: dT "+(currentTimeMillis-lastTimeMillis)+", nullFrames "+nullFrameCount+
+ getPerfStringImpl( video_scr, video_pts, d_vpts, audio_scr, audio_pts, d_apts, 0 ) + ", droppedFrame "+droppedFrame);
+ }
+ } else { // valid pts: has audio or video frame
+ nullFrameCount=0;
+
+ if( hasVideoFrame ) { // has video frame
+ presentedFrameCount++;
+
+ final int audio_pts = getAudioPTSImpl();
+ final int audio_scr = (int) ( ( currentTimeMillis - audio_scr_t0 ) * playSpeed );
+ final int d_apts;
+ if( audio_pts != TimeFrameI.INVALID_PTS ) {
+ d_apts = audio_pts - audio_scr;
+ } else {
+ d_apts = 0;
+ }
+
+ final int frame_period_last = video_pts - video_pts_last; // rendering loop interrupted ?
+ if( videoSCR_reset || frame_period_last > frame_duration*10 ) {
+ videoSCR_reset = false;
+ video_scr_t0 = currentTimeMillis;
+ video_scr_pts = video_pts;
+ }
+ final int video_scr = video_scr_pts + (int) ( ( currentTimeMillis - video_scr_t0 ) * playSpeed );
+ final int d_vpts = video_pts - video_scr;
+ // final int d_avpts = d_vpts - d_apts;
+ if( -VIDEO_DPTS_MAX > d_vpts || d_vpts > VIDEO_DPTS_MAX ) {
+ // if( -VIDEO_DPTS_MAX > d_avpts || d_avpts > VIDEO_DPTS_MAX ) {
+ if( DEBUG ) {
+ System.err.println( "AV*: dT "+(currentTimeMillis-lastTimeMillis)+", "+
+ getPerfStringImpl( video_scr, video_pts, d_vpts, audio_scr, audio_pts, d_apts, 0 ) + ", "+nextFrame+", playCached " + playCached+ ", dropFrame "+dropFrame);
+ }
+ } else {
+ final int dpy_den = displayedFrameCount > 0 ? displayedFrameCount : 1;
+ final int avg_dpy_duration = ( (int) ( currentTimeMillis - video_scr_t0 ) ) / dpy_den ; // ms/f
+ final int maxVideoDelay = Math.min(avg_dpy_duration, MAXIMUM_VIDEO_ASYNC);
+ video_dpts_count++;
+ // video_dpts_cum = d_avpts + VIDEO_DPTS_COEFF * video_dpts_cum;
+ video_dpts_cum = d_vpts + VIDEO_DPTS_COEFF * video_dpts_cum;
+ final int video_dpts_avg_diff = video_dpts_count >= VIDEO_DPTS_NUM ? getVideoDPTSAvg() : 0;
+ final int dt = (int) ( video_dpts_avg_diff / playSpeed + 0.5f );
+ // final int dt = (int) ( d_vpts / playSpeed + 0.5f );
+ // final int dt = (int) ( d_avpts / playSpeed + 0.5f );
+ final TextureFrame _nextFrame = nextFrame;
+ if( dt > maxVideoDelay ) {
+ cachedFrame = nextFrame;
+ nextFrame = null;
+ } else if ( !droppedFrame && dt < -maxVideoDelay && null != videoFramesDecoded && videoFramesDecoded.size() > 0 ) {
+ // only drop if prev. frame has not been dropped and
+ // frame is too late and one decoded frame is already available.
+ dropFrame = true;
+ }
+ video_pts_last = video_pts;
+ if( DEBUG ) {
+ System.err.println( "AV_: dT "+(currentTimeMillis-lastTimeMillis)+", "+
+ getPerfStringImpl( video_scr, video_pts, d_vpts,
+ audio_scr, audio_pts, d_apts,
+ video_dpts_avg_diff ) +
+ ", avg dpy-fps "+avg_dpy_duration+" ms/f, maxD "+maxVideoDelay+" ms, "+_nextFrame+", playCached " + playCached + ", dropFrame "+dropFrame);
+ }
+ }
+ } // has video frame
+ } // has audio or video frame
+
+ if( null != videoFramesFree && null != nextFrame ) {
+ // Had frame and not single threaded ? (TEXTURE_COUNT_MIN < textureCount)
+ final TextureFrame _lastFrame = lastFrame;
+ lastFrame = nextFrame;
+ if( null != _lastFrame ) {
+ videoFramesFree.putBlocking(_lastFrame);
+ }
+ }
+ lastTimeMillis = currentTimeMillis;
+ } while( dropFrame );
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ displayedFrameCount++;
+ return lastFrame;
+ }
+ }
+ protected void preNextTextureImpl(final GL gl) {}
+ protected void postNextTextureImpl(final GL gl) {}
+ /**
+ * Process stream until the next video frame, i.e. {@link TextureFrame}, has been reached.
+ * Audio frames, i.e. {@link AudioSink.AudioFrame}, shall be handled in the process.
+ * <p>
+ * Video frames shall be ignored, if {@link #getVID()} is {@link #STREAM_ID_NONE}.
+ * </p>
+ * <p>
+ * Audio frames shall be ignored, if {@link #getAID()} is {@link #STREAM_ID_NONE}.
+ * </p>
+ * <p>
+ * Method may be invoked on the <a href="#streamworker"><i>StreamWorker</i> decoding thread</a>.
+ * </p>
+ * <p>
+ * Implementation shall care of OpenGL synchronization as required, e.g. glFinish()/glFlush()!
+ * </p>
+ * @param gl valid and current GL instance, shall be <code>null</code> for audio only.
+ * @param nextFrame the {@link TextureFrame} to store the video PTS and texture data,
+ * shall be <code>null</code> for audio only.
+ * @return the last processed video PTS value, maybe {@link TimeFrameI#INVALID_PTS} if video frame is invalid or n/a.
+ * Will be {@link TimeFrameI#END_OF_STREAM_PTS} if end of stream reached.
+ */
+ protected abstract int getNextTextureImpl(GL gl, TextureFrame nextFrame);
+
+ protected final int getNextSingleThreaded(final GL gl, final TextureFrame nextFrame, final boolean[] gotVFrame) throws InterruptedException {
+ final int pts;
+ if( STREAM_ID_NONE != vid ) {
+ preNextTextureImpl(gl);
+ pts = getNextTextureImpl(gl, nextFrame);
+ postNextTextureImpl(gl);
+ if( TimeFrameI.INVALID_PTS != pts ) {
+ newFrameAvailable(nextFrame, Platform.currentTimeMillis());
+ gotVFrame[0] = true;
+ } else {
+ gotVFrame[0] = false;
+ }
+ } else {
+ // audio only
+ pts = getNextTextureImpl(null, null);
+ gotVFrame[0] = false;
+ }
+ return pts;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Note: All {@link AudioSink} operations are performed from {@link GLMediaPlayerImpl},
+ * i.e. {@link #play()}, {@link #pause(boolean)}, {@link #seek(int)}, {@link #setPlaySpeed(float)}, {@link #getAudioPTS()}.
+ * </p>
+ * <p>
+ * Implementations using an {@link AudioSink} shall write it's instance to {@link #audioSink}
+ * from within their {@link #initStreamImpl(int, int)} implementation.
+ * </p>
+ */
+ @Override
+ public final AudioSink getAudioSink() { return audioSink; }
+
+ /**
+ * To be called from implementation at 1st PTS after start
+ * w/ current pts value in milliseconds.
+ * @param audio_scr_t0
+ */
+ protected void setFirstAudioPTS2SCR(final int pts) {
+ if( audioSCR_reset ) {
+ audio_scr_t0 = Platform.currentTimeMillis() - pts;
+ audioSCR_reset = false;
+ }
+ }
+ private void flushAllVideoFrames() {
+ if( null != videoFramesFree ) {
+ videoFramesFree.resetFull(videoFramesOrig);
+ lastFrame = videoFramesFree.get();
+ if( null == lastFrame ) { throw new InternalError("XXX"); }
+ videoFramesDecoded.clear();
+ }
+ cachedFrame = null;
+ }
+ private void resetAVPTSAndFlush() {
+ video_dpts_cum = 0;
+ video_dpts_count = 0;
+ resetAVPTS();
+ flushAllVideoFrames();
+ if( null != audioSink ) {
+ audioSink.flush();
+ }
+ }
+ private void resetAVPTS() {
+ nullFrameCount = 0;
+ presentedFrameCount = 0;
+ displayedFrameCount = 0;
+ decodedFrameCount = 0;
+ audioSCR_reset = true;
+ videoSCR_reset = true;
+ }
+ private final int getVideoDPTSAvg() {
+ return (int) ( video_dpts_cum * (1.0f - VIDEO_DPTS_COEFF) + 0.5f );
+ }
+
+ private final void newFrameAvailable(final TextureFrame frame, final long currentTimeMillis) {
+ decodedFrameCount++; // safe: only written-to either from stream-worker or user thread
+ if( 0 == frame.getDuration() ) { // patch frame duration if not set already
+ frame.setDuration( (int) frame_duration );
+ }
+ synchronized(eventListenersLock) {
+ for(final Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) {
+ i.next().newFrameAvailable(this, frame, currentTimeMillis);
+ }
+ }
+ }
+
+ /**
+ * After {@link GLMediaPlayerImpl#initStreamImpl(int, int) initStreamImpl(..)} is completed via
+ * {@link GLMediaPlayerImpl#updateAttributes(int, int, int, int, int, int, int, float, int, int, int, String, String) updateAttributes(..)},
+ * the latter decides whether StreamWorker is being used.
+ */
+ class StreamWorker extends Thread {
+ private volatile boolean isRunning = false;
+ private volatile boolean isActive = false;
+ private volatile boolean isBlocked = false;
+
+ private volatile boolean shallPause = true;
+ private volatile boolean shallStop = false;
+
+ private volatile GLContext sharedGLCtx = null;
+ private boolean sharedGLCtxCurrent = false;
+ private GLDrawable dummyDrawable = null;
+
+ /**
+ * Starts this daemon thread,
+ * <p>
+ * This thread pauses after it's started!
+ * </p>
+ **/
+ StreamWorker() {
+ setDaemon(true);
+ synchronized(this) {
+ start();
+ while( !isRunning ) {
+ this.notifyAll(); // wake-up startup-block
+ try {
+ this.wait(); // wait until started
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private void makeCurrent(final GLContext ctx) {
+ if( GLContext.CONTEXT_NOT_CURRENT >= ctx.makeCurrent() ) {
+ throw new GLException("Couldn't make ctx current: "+ctx);
+ }
+ }
+
+ private void destroySharedGL() {
+ if( null != sharedGLCtx ) {
+ if( sharedGLCtx.isCreated() ) {
+ // Catch dispose GLExceptions by GLEventListener, just 'print' them
+ // so we can continue with the destruction.
+ try {
+ sharedGLCtx.destroy();
+ } catch (final GLException gle) {
+ gle.printStackTrace();
+ }
+ }
+ sharedGLCtx = null;
+ }
+ if( null != dummyDrawable ) {
+ final AbstractGraphicsDevice device = dummyDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+ dummyDrawable.setRealized(false);
+ dummyDrawable = null;
+ device.close();
+ }
+ }
+
+ public final synchronized void initGL(final GL gl) {
+ final GLContext glCtx = gl.getContext();
+ final boolean glCtxCurrent = glCtx.isCurrent();
+ final GLProfile glp = gl.getGLProfile();
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp);
+ final AbstractGraphicsDevice device = glCtx.getGLDrawable().getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+ dummyDrawable = factory.createDummyDrawable(device, true, glCtx.getGLDrawable().getChosenGLCapabilities(), null); // own device!
+ dummyDrawable.setRealized(true);
+ sharedGLCtx = dummyDrawable.createContext(glCtx);
+ makeCurrent(sharedGLCtx);
+ if( glCtxCurrent ) {
+ makeCurrent(glCtx);
+ } else {
+ sharedGLCtx.release();
+ }
+ }
+ public final synchronized void doPause() {
+ if( isActive ) {
+ shallPause = true;
+ if( Thread.currentThread() != this ) {
+ if( isBlocked && isActive ) {
+ this.interrupt();
+ }
+ while( isActive && isRunning ) {
+ try {
+ this.wait(); // wait until paused
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ public final synchronized void doResume() {
+ if( isRunning && !isActive ) {
+ shallPause = false;
+ if( Thread.currentThread() != this ) {
+ while( !isActive && !shallPause && isRunning ) {
+ this.notifyAll(); // wake-up pause-block
+ try {
+ this.wait(); // wait until resumed
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ public final synchronized void doStop() {
+ if( isRunning ) {
+ shallStop = true;
+ if( Thread.currentThread() != this ) {
+ if( isBlocked && isRunning ) {
+ this.interrupt();
+ }
+ while( isRunning ) {
+ this.notifyAll(); // wake-up pause-block (opt)
+ try {
+ this.wait(); // wait until stopped
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ public final boolean isRunning() { return isRunning; }
+ public final boolean isActive() { return isActive; }
+
+ @Override
+ public final void run() {
+ setName(getName()+"-StreamWorker_"+StreamWorkerInstanceId);
+ StreamWorkerInstanceId++;
+
+ synchronized ( this ) {
+ isRunning = true;
+ this.notifyAll(); // wake-up ctor()
+ }
+
+ while( !shallStop ){
+ if( shallPause ) {
+ synchronized ( this ) {
+ if( sharedGLCtxCurrent ) {
+ postNextTextureImpl(sharedGLCtx.getGL());
+ sharedGLCtx.release();
+ }
+ while( shallPause && !shallStop ) {
+ isActive = false;
+ this.notifyAll(); // wake-up doPause()
+ try {
+ this.wait(); // wait until resumed
+ } catch (final InterruptedException e) {
+ if( !shallPause ) {
+ e.printStackTrace();
+ }
+ }
+ }
+ if( sharedGLCtxCurrent ) {
+ makeCurrent(sharedGLCtx);
+ preNextTextureImpl(sharedGLCtx.getGL());
+ }
+ isActive = true;
+ this.notifyAll(); // wake-up doResume()
+ }
+ }
+ if( !sharedGLCtxCurrent && null != sharedGLCtx ) {
+ synchronized ( this ) {
+ if( null != sharedGLCtx ) {
+ makeCurrent( sharedGLCtx );
+ preNextTextureImpl(sharedGLCtx.getGL());
+ sharedGLCtxCurrent = true;
+ }
+ if( null == videoFramesFree ) {
+ throw new InternalError("XXX videoFramesFree is null");
+ }
+ }
+ }
+
+ if( !shallStop ) {
+ TextureFrame nextFrame = null;
+ try {
+ isBlocked = true;
+ final GL gl;
+ if( STREAM_ID_NONE != vid ) {
+ nextFrame = videoFramesFree.getBlocking();
+ nextFrame.setPTS( TimeFrameI.INVALID_PTS ); // mark invalid until processed!
+ gl = sharedGLCtx.getGL();
+ } else {
+ gl = null;
+ }
+ isBlocked = false;
+ final int vPTS = getNextTextureImpl(gl, nextFrame);
+ boolean audioEOS = false;
+ if( TimeFrameI.INVALID_PTS != vPTS ) {
+ if( null != nextFrame ) {
+ if( STREAM_WORKER_DELAY > 0 ) {
+ Thread.sleep(STREAM_WORKER_DELAY);
+ }
+ if( !videoFramesDecoded.put(nextFrame) ) {
+ throw new InternalError("XXX: free "+videoFramesFree+", decoded "+videoFramesDecoded+", "+GLMediaPlayerImpl.this);
+ }
+ newFrameAvailable(nextFrame, Platform.currentTimeMillis());
+ nextFrame = null;
+ } else {
+ // audio only
+ if( TimeFrameI.END_OF_STREAM_PTS == vPTS || ( duration > 0 && duration < vPTS ) ) {
+ audioEOS = true;
+ } else {
+ nullFrameCount = 0;
+ }
+ }
+ } else if( null == nextFrame ) {
+ // audio only
+ audioEOS = maxNullFrameCountUntilEOS <= nullFrameCount;
+ if( null == audioSink || 0 == audioSink.getEnqueuedFrameCount() ) {
+ nullFrameCount++;
+ }
+ }
+ if( audioEOS ) {
+ // state transition incl. notification
+ synchronized ( this ) {
+ shallPause = true;
+ isActive = false;
+ this.notifyAll(); // wake-up potential do*()
+ }
+ if( DEBUG ) {
+ System.err.println( "AV-EOS (StreamWorker): EOS_PTS "+(TimeFrameI.END_OF_STREAM_PTS == vPTS)+", "+GLMediaPlayerImpl.this);
+ }
+ pauseImpl(true, GLMediaEventListener.EVENT_CHANGE_EOS);
+ }
+ } catch (final InterruptedException e) {
+ isBlocked = false;
+ if( !shallStop && !shallPause ) {
+ streamErr = new StreamException("InterruptedException while decoding: "+GLMediaPlayerImpl.this.toString(), e);
+ }
+ } catch (final Throwable t) {
+ streamErr = new StreamException(t.getClass().getSimpleName()+" while decoding: "+GLMediaPlayerImpl.this.toString(), t);
+ } finally {
+ if( null != nextFrame ) { // put back
+ videoFramesFree.put(nextFrame);
+ }
+ if( null != streamErr ) {
+ if( DEBUG ) {
+ final Throwable t = null != streamErr.getCause() ? streamErr.getCause() : streamErr;
+ System.err.println("Caught StreamException: "+t.getMessage());
+ t.printStackTrace();
+ }
+ // state transition incl. notification
+ synchronized ( this ) {
+ shallPause = true;
+ isActive = false;
+ this.notifyAll(); // wake-up potential do*()
+ }
+ pauseImpl(true, GLMediaEventListener.EVENT_CHANGE_ERR);
+ }
+ }
+ }
+ }
+ synchronized ( this ) {
+ if( sharedGLCtxCurrent ) {
+ postNextTextureImpl(sharedGLCtx.getGL());
+ }
+ destroySharedGL();
+ isRunning = false;
+ isActive = false;
+ this.notifyAll(); // wake-up doStop()
+ }
+ }
+ }
+ static int StreamWorkerInstanceId = 0;
+ private volatile StreamWorker streamWorker = null;
+ private volatile StreamException streamErr = null;
+
+ protected final int addStateEventMask(int event_mask, final State newState) {
+ if( state != newState ) {
+ switch( newState ) {
+ case Uninitialized:
+ event_mask |= GLMediaEventListener.EVENT_CHANGE_UNINIT;
+ break;
+ case Initialized:
+ event_mask |= GLMediaEventListener.EVENT_CHANGE_INIT;
+ break;
+ case Playing:
+ event_mask |= GLMediaEventListener.EVENT_CHANGE_PLAY;
+ break;
+ case Paused:
+ event_mask |= GLMediaEventListener.EVENT_CHANGE_PAUSE;
+ break;
+ }
+ }
+ return event_mask;
+ }
+
+ protected final void attributesUpdated(final int event_mask) {
+ if( 0 != event_mask ) {
+ final long now = Platform.currentTimeMillis();
+ synchronized(eventListenersLock) {
+ for(final Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) {
+ i.next().attributesChanged(this, event_mask, now);
+ }
+ }
+ }
+ }
+
+ protected final void changeState(int event_mask, final State newState) {
+ event_mask = addStateEventMask(event_mask, newState);
+ if( 0 != event_mask ) {
+ setState( newState );
+ if( !isTextureAvailable() ) {
+ textureFragmentShaderHashCode = 0;
+ }
+ attributesUpdated( event_mask );
+ }
+ }
+
+ protected final void updateAttributes(int vid, final int aid, final int width, final int height, final int bps_stream,
+ final int bps_video, final int bps_audio, final float fps,
+ final int videoFrames, final int audioFrames, final int duration, final String vcodec, final String acodec) {
int event_mask = 0;
+ final boolean wasUninitialized = state == State.Uninitialized;
+
+ if( wasUninitialized ) {
+ event_mask |= GLMediaEventListener.EVENT_CHANGE_INIT;
+ setState( State.Initialized );
+ }
+ if( STREAM_ID_AUTO == vid ) {
+ vid = STREAM_ID_NONE;
+ }
+ if( this.vid != vid ) {
+ event_mask |= GLMediaEventListener.EVENT_CHANGE_VID;
+ this.vid = vid;
+ }
+ if( STREAM_ID_AUTO == vid ) {
+ vid = STREAM_ID_NONE;
+ }
+ if( this.aid != aid ) {
+ event_mask |= GLMediaEventListener.EVENT_CHANGE_AID;
+ this.aid = aid;
+ }
if( this.width != width || this.height != height ) {
event_mask |= GLMediaEventListener.EVENT_CHANGE_SIZE;
this.width = width;
this.height = height;
- }
+ }
if( this.fps != fps ) {
event_mask |= GLMediaEventListener.EVENT_CHANGE_FPS;
this.fps = fps;
+ if( 0 != fps ) {
+ this.frame_duration = 1000f / fps;
+ this.maxNullFrameCountUntilEOS = MAX_FRAMELESS_MS_UNTIL_EOS / (int)this.frame_duration;
+ } else {
+ this.frame_duration = 0;
+ this.maxNullFrameCountUntilEOS = MAX_FRAMELESS_UNTIL_EOS_DEFAULT;
+ }
}
if( this.bps_stream != bps_stream || this.bps_video != bps_video || this.bps_audio != bps_audio ) {
event_mask |= GLMediaEventListener.EVENT_CHANGE_BPS;
@@ -432,12 +1425,13 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
this.bps_video = bps_video;
this.bps_audio = bps_audio;
}
- if( this.totalFrames != totalFrames || this.duration != duration ) {
+ if( this.videoFrames != videoFrames || this.audioFrames != audioFrames || this.duration != duration ) {
event_mask |= GLMediaEventListener.EVENT_CHANGE_LENGTH;
- this.totalFrames = totalFrames;
+ this.videoFrames = videoFrames;
+ this.audioFrames = audioFrames;
this.duration = duration;
}
- if( (null!=acodec && acodec.length()>0 && !this.acodec.equals(acodec)) ) {
+ if( (null!=acodec && acodec.length()>0 && !this.acodec.equals(acodec)) ) {
event_mask |= GLMediaEventListener.EVENT_CHANGE_CODEC;
this.acodec = acodec;
}
@@ -448,101 +1442,132 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
if(0==event_mask) {
return;
}
- attributesUpdated(event_mask);
- }
-
- protected final void attributesUpdated(int event_mask) {
- synchronized(eventListenersLock) {
- for(Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) {
- i.next().attributesChanges(this, event_mask, System.currentTimeMillis());
+ if( wasUninitialized ) {
+ if( null != streamWorker ) {
+ throw new InternalError("XXX: StreamWorker not null - "+this);
+ }
+ if( TEXTURE_COUNT_MIN < textureCount || STREAM_ID_NONE == vid ) { // Enable StreamWorker for 'audio only' as well (Bug 918).
+ streamWorker = new StreamWorker();
+ }
+ if( DEBUG ) {
+ System.err.println("XXX Initialize @ updateAttributes: "+this);
}
}
+ attributesUpdated(event_mask);
}
- protected final void newFrameAvailable() {
- frameNumber++;
- synchronized(eventListenersLock) {
- for(Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) {
- i.next().newFrameAvailable(this, System.currentTimeMillis());
+
+ protected void setIsGLOriented(final boolean isGLOriented) {
+ if( isInGLOrientation != isGLOriented ) {
+ if( DEBUG ) {
+ System.err.println("XXX gl-orient "+isInGLOrientation+" -> "+isGLOriented);
+ }
+ isInGLOrientation = isGLOriented;
+ if( null != videoFramesOrig ) {
+ for(int i=0; i<videoFramesOrig.length; i++) {
+ videoFramesOrig[i].getTexture().setMustFlipVertically(!isGLOriented);
+ }
+ attributesUpdated(GLMediaEventListener.EVENT_CHANGE_SIZE);
}
}
}
-
+
@Override
- public final synchronized State destroy(GL gl) {
- destroyImpl(gl);
- removeAllImageTextures(gl);
- state = State.Uninitialized;
- return state;
- }
- protected abstract void destroyImpl(GL gl);
+ public final Uri getUri() { return streamLoc; }
@Override
- public final synchronized URLConnection getURLConnection() {
- return urlConn;
- }
+ public final int getVID() { return vid; }
@Override
- public final synchronized String getVideoCodec() {
- return vcodec;
- }
+ public final int getAID() { return aid; }
@Override
- public final synchronized String getAudioCodec() {
- return acodec;
- }
+ public final String getVideoCodec() { return vcodec; }
@Override
- public final synchronized long getTotalFrames() {
- return totalFrames;
- }
+ public final String getAudioCodec() { return acodec; }
@Override
- public final synchronized int getDuration() {
- return duration;
- }
-
+ public final int getVideoFrames() { return videoFrames; }
+
@Override
- public final synchronized long getStreamBitrate() {
- return bps_stream;
- }
+ public final int getAudioFrames() { return audioFrames; }
@Override
- public final synchronized int getVideoBitrate() {
- return bps_video;
- }
-
+ public final int getDuration() { return duration; }
+
@Override
- public final synchronized int getAudioBitrate() {
- return bps_audio;
- }
-
+ public final long getStreamBitrate() { return bps_stream; }
+
@Override
- public final synchronized float getFramerate() {
- return fps;
- }
+ public final int getVideoBitrate() { return bps_video; }
@Override
- public final synchronized int getWidth() {
- return width;
- }
+ public final int getAudioBitrate() { return bps_audio; }
+
+ @Override
+ public final float getFramerate() { return fps; }
+
+ @Override
+ public final boolean isGLOriented() { return isInGLOrientation; }
+
+ @Override
+ public final int getWidth() { return width; }
@Override
- public final synchronized int getHeight() {
- return height;
+ public final int getHeight() { return height; }
+
+ @Override
+ public final String toString() {
+ final float tt = getDuration() / 1000.0f;
+ final String loc = ( null != streamLoc ) ? streamLoc.toString() : "<undefined stream>" ;
+ final int freeVideoFrames = null != videoFramesFree ? videoFramesFree.size() : 0;
+ final int decVideoFrames = null != videoFramesDecoded ? videoFramesDecoded.size() : 0;
+ final int video_scr = video_scr_pts + (int) ( ( Platform.currentTimeMillis() - video_scr_t0 ) * playSpeed );
+ final String camPath = null != cameraPath ? ", camera: "+cameraPath : "";
+ return "GLMediaPlayer["+state+", vSCR "+video_scr+", frames[p "+presentedFrameCount+", d "+decodedFrameCount+", t "+videoFrames+" ("+tt+" s), z "+nullFrameCount+" / "+maxNullFrameCountUntilEOS+"], "+
+ "speed "+playSpeed+", "+bps_stream+" bps, hasSW "+(null!=streamWorker)+
+ ", Texture[count "+textureCount+", free "+freeVideoFrames+", dec "+decVideoFrames+", tagt "+toHexString(textureTarget)+", ifmt "+toHexString(textureInternalFormat)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType)+"], "+
+ "Video[id "+vid+", <"+vcodec+">, "+width+"x"+height+", glOrient "+isInGLOrientation+", "+fps+" fps, "+frame_duration+" fdur, "+bps_video+" bps], "+
+ "Audio[id "+aid+", <"+acodec+">, "+bps_audio+" bps, "+audioFrames+" frames], uri "+loc+camPath+"]";
}
@Override
- public final synchronized String toString() {
- final float ct = getCurrentPosition() / 1000.0f, tt = getDuration() / 1000.0f;
- final String loc = ( null != urlConn ) ? urlConn.getURL().toExternalForm() : "<undefined stream>" ;
- return "GLMediaPlayer["+state+", "+frameNumber+"/"+totalFrames+" frames, "+ct+"/"+tt+"s, speed "+playSpeed+", "+bps_stream+" bps, "+
- "Texture[count "+textureCount+", target "+toHexString(textureTarget)+", format "+toHexString(textureFormat)+", type "+toHexString(textureType)+"], "+
- "Stream[Video[<"+vcodec+">, "+width+"x"+height+", "+fps+" fps, "+bps_video+" bsp], "+
- "Audio[<"+acodec+">, "+bps_audio+" bsp]], "+loc+"]";
+ public final String getPerfString() {
+ final long currentTimeMillis = Platform.currentTimeMillis();
+ final int video_scr = video_scr_pts + (int) ( ( currentTimeMillis - video_scr_t0 ) * playSpeed );
+ final int d_vpts = video_pts_last - video_scr;
+ final int audio_scr = (int) ( ( currentTimeMillis - audio_scr_t0 ) * playSpeed );
+ final int audio_pts = getAudioPTSImpl();
+ final int d_apts = audio_pts - audio_scr;
+ return getPerfStringImpl( video_scr, video_pts_last, d_vpts, audio_scr, audio_pts, d_apts, getVideoDPTSAvg() );
+ }
+ private final String getPerfStringImpl(final int video_scr, final int video_pts, final int d_vpts,
+ final int audio_scr, final int audio_pts, final int d_apts,
+ final int video_dpts_avg_diff) {
+ final float tt = getDuration() / 1000.0f;
+ final String audioSinkInfo;
+ final AudioSink audioSink = getAudioSink();
+ if( null != audioSink ) {
+ audioSinkInfo = "AudioSink[frames [p "+audioSink.getEnqueuedFrameCount()+", q "+audioSink.getQueuedFrameCount()+", f "+audioSink.getFreeFrameCount()+", c "+audioSink.getFrameCount()+"], time "+audioSink.getQueuedTime()+", bytes "+audioSink.getQueuedByteCount()+"]";
+ } else {
+ audioSinkInfo = "";
+ }
+ final int freeVideoFrames, decVideoFrames;
+ if( null != videoFramesFree ) {
+ freeVideoFrames = videoFramesFree.size();
+ decVideoFrames = videoFramesDecoded.size();
+ } else {
+ freeVideoFrames = 0;
+ decVideoFrames = 0;
+ }
+ return state+", frames[(p "+presentedFrameCount+", d "+decodedFrameCount+") / "+videoFrames+", "+tt+" s, z "+nullFrameCount+" / "+maxNullFrameCountUntilEOS+"], "+
+ "speed " + playSpeed+", dAV "+( d_vpts - d_apts )+", vSCR "+video_scr+", vpts "+video_pts+", dSCR["+d_vpts+", avrg "+video_dpts_avg_diff+"], "+
+ "aSCR "+audio_scr+", apts "+audio_pts+" ( "+d_apts+" ), "+audioSinkInfo+
+ ", Texture[count "+textureCount+", free "+freeVideoFrames+", dec "+decVideoFrames+"]";
}
@Override
- public final void addEventListener(GLMediaEventListener l) {
+ public final void addEventListener(final GLMediaEventListener l) {
if(l == null) {
return;
}
@@ -552,7 +1577,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
@Override
- public final void removeEventListener(GLMediaEventListener l) {
+ public final void removeEventListener(final GLMediaEventListener l) {
if (l == null) {
return;
}
@@ -562,19 +1587,46 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
}
@Override
- public final synchronized GLMediaEventListener[] getEventListeners() {
+ public final GLMediaEventListener[] getEventListeners() {
synchronized(eventListenersLock) {
return eventListeners.toArray(new GLMediaEventListener[eventListeners.size()]);
}
}
- private Object eventListenersLock = new Object();
+ private final Object eventListenersLock = new Object();
+
+ @Override
+ public final Object getAttachedObject(final String name) {
+ return attachedObjects.get(name);
+ }
- protected static final String toHexString(long v) {
+ @Override
+ public final Object attachObject(final String name, final Object obj) {
+ return attachedObjects.put(name, obj);
+ }
+
+ @Override
+ public final Object detachObject(final String name) {
+ return attachedObjects.remove(name);
+ }
+
+ private final HashMap<String, Object> attachedObjects = new HashMap<String, Object>();
+
+ protected static final String toHexString(final long v) {
return "0x"+Long.toHexString(v);
}
- protected static final String toHexString(int v) {
+ protected static final String toHexString(final int v) {
return "0x"+Integer.toHexString(v);
}
-
-} \ No newline at end of file
+ protected static final int getPropIntVal(final Map<String, String> props, final String key) {
+ final String val = props.get(key);
+ try {
+ return Integer.parseInt(val);
+ } catch (final NumberFormatException nfe) {
+ if(DEBUG) {
+ System.err.println("Not a valid integer for <"+key+">: <"+val+">");
+ }
+ }
+ return 0;
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/JavaSoundAudioSink.java b/src/jogl/classes/jogamp/opengl/util/av/JavaSoundAudioSink.java
new file mode 100644
index 000000000..117be5489
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/JavaSoundAudioSink.java
@@ -0,0 +1,228 @@
+package jogamp.opengl.util.av;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.SourceDataLine;
+
+import com.jogamp.opengl.util.av.AudioSink;
+
+/***
+ * JavaSound Audio Sink
+ * <p>
+ * FIXME: Parameterize .. all configs .. best via an init-method, passing requested
+ * audio capabilities
+ * </p>
+ */
+public class JavaSoundAudioSink implements AudioSink {
+
+ // Chunk of audio processed at one time
+ public static final int BUFFER_SIZE = 1000;
+ public static final int SAMPLES_PER_BUFFER = BUFFER_SIZE / 2;
+ private static final boolean staticAvailable;
+
+ // Sample time values
+ // public static final double SAMPLE_TIME_IN_SECS = 1.0 / DEFAULT_SAMPLE_RATE;
+ // public static final double BUFFER_TIME_IN_SECS = SAMPLE_TIME_IN_SECS * SAMPLES_PER_BUFFER;
+
+ private javax.sound.sampled.AudioFormat format;
+ private DataLine.Info info;
+ private SourceDataLine auline;
+ private int bufferCount;
+ private final byte [] sampleData = new byte[BUFFER_SIZE];
+ private boolean initialized = false;
+ private AudioSink.AudioFormat chosenFormat = null;
+
+ private volatile boolean playRequested = false;
+ private float volume = 1.0f;
+
+ static {
+ boolean ok = false;
+ try {
+ AudioSystem.getAudioFileTypes();
+ ok = true;
+ } catch (final Throwable t) {
+
+ }
+ staticAvailable=ok;
+ }
+
+ @Override
+ public String toString() {
+ return "JavaSoundSink[init "+initialized+", dataLine "+info+", source "+auline+", bufferCount "+bufferCount+
+ ", chosen "+chosenFormat+", jsFormat "+format;
+ }
+
+ @Override
+ public final float getPlaySpeed() { return 1.0f; } // FIXME
+
+ @Override
+ public final boolean setPlaySpeed(final float rate) {
+ return false; // FIXME
+ }
+
+ @Override
+ public final float getVolume() {
+ // FIXME
+ return volume;
+ }
+
+ @Override
+ public final boolean setVolume(final float v) {
+ // FIXME
+ volume = v;
+ return true;
+ }
+
+ @Override
+ public AudioSink.AudioFormat getPreferredFormat() {
+ return DefaultFormat;
+ }
+
+ @Override
+ public final int getMaxSupportedChannels() {
+ return 2;
+ }
+
+ @Override
+ public final boolean isSupported(final AudioSink.AudioFormat format) {
+ return true;
+ }
+
+ @Override
+ public boolean init(final AudioSink.AudioFormat requestedFormat, final float frameDuration, final int initialQueueSize, final int queueGrowAmount, final int queueLimit) {
+ if( !staticAvailable ) {
+ return false;
+ }
+ // Create the audio format we wish to use
+ format = new javax.sound.sampled.AudioFormat(requestedFormat.sampleRate, requestedFormat.sampleSize, requestedFormat.channelCount, requestedFormat.signed, !requestedFormat.littleEndian);
+
+ // Create dataline info object describing line format
+ info = new DataLine.Info(SourceDataLine.class, format);
+
+ // Clear buffer initially
+ Arrays.fill(sampleData, (byte) 0);
+ try{
+ // Get line to write data to
+ auline = (SourceDataLine) AudioSystem.getLine(info);
+ auline.open(format);
+ auline.start();
+ System.out.println("JavaSound audio sink");
+ initialized=true;
+ chosenFormat = requestedFormat;
+ } catch (final Exception e) {
+ initialized=false;
+ }
+ return true;
+ }
+
+ @Override
+ public final AudioFormat getChosenFormat() {
+ return chosenFormat;
+ }
+
+ @Override
+ public boolean isPlaying() {
+ return playRequested && auline.isRunning();
+ }
+
+ @Override
+ public void play() {
+ if( null != auline ) {
+ playRequested = true;
+ playImpl();
+ }
+ }
+ private void playImpl() {
+ if( playRequested && !auline.isRunning() ) {
+ auline.start();
+ }
+ }
+
+ @Override
+ public void pause() {
+ if( null != auline ) {
+ playRequested = false;
+ auline.stop();
+ }
+ }
+
+ @Override
+ public void flush() {
+ if( null != auline ) {
+ playRequested = false;
+ auline.stop();
+ auline.flush();
+ }
+ }
+
+ @Override
+ public final int getEnqueuedFrameCount() {
+ return 0; // FIXME
+ }
+
+ @Override
+ public int getFrameCount() {
+ return 1;
+ }
+
+ @Override
+ public int getQueuedFrameCount() {
+ return 0;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ @Override
+ public void destroy() {
+ initialized = false;
+ chosenFormat = null;
+ // FIXEM: complete code!
+ }
+
+ @Override
+ public AudioFrame enqueueData(final int pts, final ByteBuffer byteBuffer, final int byteCount) {
+ final byte[] bytes = new byte[byteCount];
+ final int p = byteBuffer.position();
+ byteBuffer.get(bytes, 0, byteCount);
+ byteBuffer.position(p);
+
+ int written = 0;
+ int len;
+ int bytesLeft = byteCount;
+ while (bytesLeft > 0) {
+ len = auline.write(bytes, written, byteCount);
+ bytesLeft -= len;
+ written += len;
+ }
+ playImpl();
+ return new AudioDataFrame(pts, chosenFormat.getBytesDuration(byteCount), byteBuffer, byteCount);
+ }
+
+ @Override
+ public int getQueuedByteCount() {
+ return auline.getBufferSize() - auline.available();
+ }
+
+ @Override
+ public int getFreeFrameCount() {
+ return auline.available();
+ }
+
+ @Override
+ public int getQueuedTime() {
+ return getQueuedTimeImpl( getQueuedByteCount() );
+ }
+ private final int getQueuedTimeImpl(final int byteCount) {
+ final int bytesPerSample = chosenFormat.sampleSize >>> 3; // /8
+ return byteCount / ( chosenFormat.channelCount * bytesPerSample * ( chosenFormat.sampleRate / 1000 ) );
+ }
+
+ @Override
+ public final int getPTS() { return 0; } // FIXME
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/NullAudioSink.java b/src/jogl/classes/jogamp/opengl/util/av/NullAudioSink.java
new file mode 100644
index 000000000..7e27f17c3
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/NullAudioSink.java
@@ -0,0 +1,181 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.av;
+
+import java.nio.ByteBuffer;
+
+import com.jogamp.opengl.util.av.AudioSink;
+
+public class NullAudioSink implements AudioSink {
+
+ private volatile float playSpeed = 1.0f;
+ private volatile boolean playRequested = false;
+ private volatile int playingPTS = AudioFrame.INVALID_PTS;
+ private float volume = 1.0f;
+
+ private AudioFormat chosenFormat;
+ private boolean initialized;
+
+ public NullAudioSink() {
+ initialized = true;
+ chosenFormat = null;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ @Override
+ public final float getPlaySpeed() { return playSpeed; }
+
+ @Override
+ public final boolean setPlaySpeed(float rate) {
+ if( Math.abs(1.0f - rate) < 0.01f ) {
+ rate = 1.0f;
+ }
+ playSpeed = rate;
+ return true;
+ }
+
+ @Override
+ public final float getVolume() {
+ // FIXME
+ return volume;
+ }
+
+ @Override
+ public final boolean setVolume(final float v) {
+ // FIXME
+ volume = v;
+ return true;
+ }
+
+ @Override
+ public AudioFormat getPreferredFormat() {
+ return DefaultFormat;
+ }
+
+ @Override
+ public final int getMaxSupportedChannels() {
+ return 8;
+ }
+
+ @Override
+ public final boolean isSupported(final AudioFormat format) {
+ /**
+ * If we like to emulate constraints ..
+ *
+ if( format.planar || !format.littleEndian ) {
+ return false;
+ }
+ if( format.sampleRate != DefaultFormat.sampleRate ) {
+ return false;
+ }
+ */
+ return true;
+ }
+
+ @Override
+ public boolean init(final AudioFormat requestedFormat, final float frameDuration, final int initialQueueSize, final int queueGrowAmount, final int queueLimit) {
+ chosenFormat = requestedFormat;
+ return true;
+ }
+
+ @Override
+ public final AudioFormat getChosenFormat() {
+ return chosenFormat;
+ }
+
+ @Override
+ public boolean isPlaying() {
+ return playRequested;
+ }
+
+ @Override
+ public void play() {
+ playRequested = true;
+ }
+
+ @Override
+ public void pause() {
+ playRequested = false;
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void destroy() {
+ initialized = false;
+ chosenFormat = null;
+ }
+
+ @Override
+ public final int getEnqueuedFrameCount() {
+ return 0;
+ }
+
+ @Override
+ public int getFrameCount() {
+ return 0;
+ }
+
+ @Override
+ public int getQueuedFrameCount() {
+ return 0;
+ }
+
+ @Override
+ public int getQueuedByteCount() {
+ return 0;
+ }
+
+ @Override
+ public int getQueuedTime() {
+ return 0;
+ }
+
+ @Override
+ public final int getPTS() { return playingPTS; }
+
+ @Override
+ public int getFreeFrameCount() {
+ return 1;
+ }
+
+ @Override
+ public AudioFrame enqueueData(final int pts, final ByteBuffer bytes, final int byteCount) {
+ if( !initialized || null == chosenFormat ) {
+ return null;
+ }
+ playingPTS = pts;
+ return null;
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java
index cd48c3962..4a15c7422 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -32,12 +32,15 @@ import java.net.URLConnection;
import java.nio.ByteBuffer;
import javax.media.opengl.GL;
+import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import jogamp.opengl.util.av.GLMediaPlayerImpl;
import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureIO;
@@ -49,114 +52,126 @@ import com.jogamp.opengl.util.texture.TextureSequence;
*/
public class NullGLMediaPlayer extends GLMediaPlayerImpl {
private TextureData texData = null;
- private TextureSequence.TextureFrame frame = null;
private int pos_ms = 0;
- private int pos_start = 0;
-
+ private long pos_start = 0;
+
public NullGLMediaPlayer() {
super();
- this.setTextureCount(1);
+
}
@Override
- protected boolean setPlaySpeedImpl(float rate) {
+ protected final boolean setPlaySpeedImpl(final float rate) {
return false;
}
@Override
- protected boolean startImpl() {
- pos_start = (int)System.currentTimeMillis();
+ protected final boolean playImpl() {
+ pos_start = Platform.currentTimeMillis();
return true;
}
@Override
- protected boolean pauseImpl() {
+ protected final boolean pauseImpl() {
return true;
}
@Override
- protected boolean stopImpl() {
- return true;
- }
-
- @Override
- protected int seekImpl(int msec) {
+ protected final int seekImpl(final int msec) {
pos_ms = msec;
validatePos();
return pos_ms;
}
-
- @Override
- protected TextureSequence.TextureFrame getLastTextureImpl() {
- return frame;
- }
@Override
- protected TextureSequence.TextureFrame getNextTextureImpl(GL gl, boolean blocking) {
- return frame;
+ protected final int getNextTextureImpl(final GL gl, final TextureFrame nextFrame) {
+ final int pts = getAudioPTSImpl();
+ nextFrame.setPTS( pts );
+ return pts;
}
-
+
@Override
- protected int getCurrentPositionImpl() {
- pos_ms = (int)System.currentTimeMillis() - pos_start;
+ protected final int getAudioPTSImpl() {
+ pos_ms = (int) ( Platform.currentTimeMillis() - pos_start );
validatePos();
return pos_ms;
}
@Override
- protected void destroyImpl(GL gl) {
+ protected final void destroyImpl(final GL gl) {
+ if(null != texData) {
+ texData.destroy();
+ texData = null;
+ }
}
-
- @Override
- protected void initGLStreamImpl(GL gl, int[] texNames) throws IOException {
+
+ public final static TextureData createTestTextureData() {
+ TextureData res = null;
try {
- URLConnection urlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-160x90.png", this.getClass().getClassLoader());
+ final URLConnection urlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-28x16.png", NullGLMediaPlayer.class.getClassLoader());
if(null != urlConn) {
- texData = TextureIO.newTextureData(GLProfile.getGL2ES2(), urlConn.getInputStream(), false, TextureIO.PNG);
+ res = TextureIO.newTextureData(GLProfile.getGL2ES2(), urlConn.getInputStream(), false, TextureIO.PNG);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
- if(null != texData) {
- width = texData.getWidth();
- height = texData.getHeight();
- } else {
- width = 640;
- height = 480;
- ByteBuffer buffer = Buffers.newDirectByteBuffer(width*height*4);
+ if(null == res) {
+ final int w = 160;
+ final int h = 90;
+ final ByteBuffer buffer = Buffers.newDirectByteBuffer(w*h*4);
while(buffer.hasRemaining()) {
buffer.put((byte) 0xEA); buffer.put((byte) 0xEA); buffer.put((byte) 0xEA); buffer.put((byte) 0xEA);
}
buffer.rewind();
- texData = new TextureData(GLProfile.getGL2ES2(),
- GL.GL_RGBA, width, height, 0,
- GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, false,
+ res = new TextureData(GLProfile.getGL2ES2(),
+ GL.GL_RGBA, w, h, 0,
+ GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, false,
false, false, buffer, null);
}
- fps = 24f;
- duration = 10*60*1000; // msec
- totalFrames = (int) ( (duration/1000)*fps );
- vcodec = "png-static";
+ return res;
+ }
+
+ @Override
+ protected final void initStreamImpl(final int vid, final int aid) throws IOException {
+ texData = createTestTextureData();
+ final float _fps = 24f;
+ final int _duration = 10*60*1000; // msec
+ final int _totalFrames = (int) ( (_duration/1000)*_fps );
+ updateAttributes(0 /* fake */, GLMediaPlayer.STREAM_ID_NONE,
+ texData.getWidth(), texData.getHeight(), 0,
+ 0, 0, _fps,
+ _totalFrames, 0, _duration, "png-static", null);
+ }
+ @Override
+ protected final void initGLImpl(final GL gl) throws IOException, GLException {
+ setIsGLOriented(true);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns {@link GLMediaPlayer#TEXTURE_COUNT_MIN}.
+ * </p>
+ */
+ @Override
+ protected int validateTextureCount(final int desiredTextureCount) {
+ return TEXTURE_COUNT_MIN;
}
-
+
@Override
- protected TextureSequence.TextureFrame createTexImage(GL gl, int idx, int[] tex) {
- Texture texture = super.createTexImageImpl(gl, idx, tex, width, height, false);
+ protected final TextureSequence.TextureFrame createTexImage(final GL gl, final int texName) {
+ final Texture texture = super.createTexImageImpl(gl, texName, getWidth(), getHeight());
if(null != texData) {
texture.updateImage(gl, texData);
- texData.destroy();
- texData = null;
- }
- frame = new TextureSequence.TextureFrame( texture );
- return frame;
+ }
+ return new TextureSequence.TextureFrame( texture );
}
-
+
@Override
- protected void destroyTexImage(GL gl, TextureSequence.TextureFrame imgTex) {
- frame = null;
- super.destroyTexImage(gl, imgTex);
+ protected final void destroyTexFrame(final GL gl, final TextureSequence.TextureFrame frame) {
+ super.destroyTexFrame(gl, frame);
}
-
+
private void validatePos() {
boolean considerPausing = false;
if( 0 > pos_ms) {
@@ -166,8 +181,8 @@ public class NullGLMediaPlayer extends GLMediaPlayerImpl {
pos_ms = getDuration();
considerPausing = true;
}
- if(considerPausing && state == State.Playing) {
- state = State.Paused;
+ if( considerPausing && State.Playing == getState() ) {
+ setState(State.Paused);
}
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/VideoPixelFormat.java b/src/jogl/classes/jogamp/opengl/util/av/VideoPixelFormat.java
new file mode 100644
index 000000000..44d83e78d
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/VideoPixelFormat.java
@@ -0,0 +1,191 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.av;
+
+/** FFMPEG/libAV compatible video pixel format */
+public enum VideoPixelFormat {
+ // NONE= -1,
+ /** planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) */
+ YUV420P,
+ /** packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr ( sharing Cb and Cr w/ 2 pixels )*/
+ YUYV422,
+ /** packed RGB 8:8:8, 24bpp, RGBRGB... */
+ RGB24,
+ /** packed RGB 8:8:8, 24bpp, BGRBGR... */
+ BGR24,
+ /** planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) */
+ YUV422P,
+ /** planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) */
+ YUV444P,
+ /** planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) */
+ YUV410P,
+ /** planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) */
+ YUV411P,
+ /** Y, 8bpp */
+ GRAY8,
+ /** Y, 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb */
+ MONOWHITE,
+ /** Y, 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb */
+ MONOBLACK,
+ /** 8 bit with RGB32 palette */
+ PAL8,
+ /** planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of YUV420P and setting color_range */
+ YUVJ420P,
+ /** planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of YUV422P and setting color_range */
+ YUVJ422P,
+ /** planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of YUV444P and setting color_range */
+ YUVJ444P,
+ /** XVideo Motion Acceleration via common packet passing */
+ XVMC_MPEG2_MC,
+ /** */
+ XVMC_MPEG2_IDCT,
+ /** packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 */
+ UYVY422,
+ /** packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 */
+ UYYVYY411,
+ /** packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) */
+ BGR8,
+ /** packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits */
+ BGR4,
+ /** packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) */
+ BGR4_BYTE,
+ /** packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb) */
+ RGB8,
+ /** packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits */
+ RGB4,
+ /** packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) */
+ RGB4_BYTE,
+ /** planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) */
+ NV12,
+ /** as above, but U and V bytes are swapped */
+ NV21,
+
+ /** packed ARGB 8:8:8:8, 32bpp, ARGBARGB... */
+ ARGB,
+ /** packed RGBA 8:8:8:8, 32bpp, RGBARGBA... */
+ RGBA,
+ /** packed ABGR 8:8:8:8, 32bpp, ABGRABGR... */
+ ABGR,
+ /** packed BGRA 8:8:8:8, 32bpp, BGRABGRA... */
+ BGRA,
+
+ /** Y, 16bpp, big-endian */
+ GRAY16BE,
+ /** Y , 16bpp, little-endian */
+ GRAY16LE,
+ /** planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) */
+ YUV440P,
+ /** planar YUV 4:4:0 full scale (JPEG), deprecated in favor of YUV440P and setting color_range */
+ YUVJ440P,
+ /** planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) */
+ YUVA420P,
+ /** H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers */
+ VDPAU_H264,
+ /** MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers */
+ VDPAU_MPEG1,
+ /** MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers */
+ VDPAU_MPEG2,
+ /** WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers */
+ VDPAU_WMV3,
+ /** VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers */
+ VDPAU_VC1,
+ /** packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian */
+ RGB48BE,
+ /** packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian */
+ RGB48LE,
+
+ RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
+ RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
+ RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0
+ RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0
+
+ BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
+ BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
+ BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1
+ BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1
+
+ VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
+ VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers
+ VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+
+ YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+ YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
+
+ RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0
+ RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0
+ BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1
+ BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1
+ Y400A, ///< 8bit gray, 8bit alpha
+ BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian
+ BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian
+ YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+ YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+ YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+ YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+ YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+ YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+ VDA_VLD, ///< hardware decoding through VDA
+ GBRP, ///< planar GBR 4:4:4 24bpp
+ GBRP9BE, ///< planar GBR 4:4:4 27bpp, big endian
+ GBRP9LE, ///< planar GBR 4:4:4 27bpp, little endian
+ GBRP10BE, ///< planar GBR 4:4:4 30bpp, big endian
+ GBRP10LE, ///< planar GBR 4:4:4 30bpp, little endian
+ GBRP16BE, ///< planar GBR 4:4:4 48bpp, big endian
+ GBRP16LE, ///< planar GBR 4:4:4 48bpp, little endian
+ COUNT ///< number of pixel formats in this list
+ ;
+ /**
+ * Returns the matching PixelFormat value corresponding to the given PixelFormat's integer ordinal.
+ * <pre>
+ * given:
+ * ordinal = enumValue.ordinal()
+ * reverse:
+ * enumValue = EnumClass.values()[ordinal]
+ * </pre>
+ * @throws IllegalArgumentException if the given ordinal is out of range, i.e. not within [ 0 .. PixelFormat.values().length-1 ]
+ */
+ public static VideoPixelFormat valueOf(final int ordinal) throws IllegalArgumentException {
+ final VideoPixelFormat[] all = VideoPixelFormat.values();
+ if( 0 <= ordinal && ordinal < all.length ) {
+ return all[ordinal];
+ }
+ throw new IllegalArgumentException("Ordinal "+ordinal+" out of range of PixelFormat.values()[0.."+(all.length-1)+"]");
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
index 32c863553..42a908f93 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,20 +20,20 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl.util.av.impl;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import javax.media.opengl.GLProfile;
@@ -41,225 +41,380 @@ import javax.media.opengl.GLProfile;
import com.jogamp.common.os.DynamicLibraryBundle;
import com.jogamp.common.os.DynamicLibraryBundleInfo;
import com.jogamp.common.util.RunnableExecutor;
+import com.jogamp.common.util.VersionNumber;
/**
- * FIXME: We need native structure access methods to deal with API changes
- * in the libav headers, which break binary compatibility!
- * Currently we are binary compatible w/ [0.6 ?, ] 0.7 and 0.8 but not w/ trunk.
- *
- * ChangeList for trunk:
- * Thu Jan 12 11:21:02 2012 a17479dfce67fbea2d0a1bf303010dce1e79059f major 53 -> 54
- * Mon Feb 27 22:40:11 2012 ee42df8a35c2b795f524c856834d0823dbd4e75d reorder AVStream and AVFormatContext
- * Tue Feb 28 12:07:53 2012 322537478b63c6bc01e640643550ff539864d790 minor 1 -> 2
+ * See {@link FFMPEGMediaPlayer#compatibility}.
*/
class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
- private static List<String> glueLibNames = new ArrayList<String>(); // none
-
- private static final int symbolCount = 31;
- private static String[] symbolNames = {
- "avcodec_version",
+ private static final boolean DEBUG = FFMPEGMediaPlayer.DEBUG || DynamicLibraryBundleInfo.DEBUG;
+
+ private static final List<String> glueLibNames = new ArrayList<String>(); // none
+
+ private static final int symbolCount = 65;
+ private static final String[] symbolNames = {
+ "avutil_version",
"avformat_version",
-/* 3 */ "avutil_version",
-
+ "avcodec_version",
+ "avresample_version",
+/* 5 */ "swresample_version",
+
// libavcodec
- "avcodec_close",
- "avcodec_string",
- "avcodec_find_decoder",
- "avcodec_open2", // 53.6.0 (opt)
- "avcodec_open",
- "avcodec_alloc_frame",
- "avcodec_default_get_buffer",
- "avcodec_default_release_buffer",
- "av_free_packet",
+ "avcodec_register_all",
+ "avcodec_close",
+ "avcodec_string",
+ "avcodec_find_decoder",
+ "avcodec_open2", // 53.6.0 (opt)
+ "avcodec_alloc_frame",
+ "avcodec_get_frame_defaults",
+ "avcodec_free_frame", // 54.28.0 (opt)
+ "avcodec_default_get_buffer", // <= 54 (opt), else sp_avcodec_default_get_buffer2
+ "avcodec_default_release_buffer", // <= 54 (opt), else sp_av_frame_unref
+ "avcodec_default_get_buffer2", // 55 (opt)
+ "avcodec_get_edge_width",
+ "av_image_fill_linesizes",
+ "avcodec_align_dimensions",
+ "avcodec_align_dimensions2",
+ "avcodec_flush_buffers",
+ "av_init_packet",
+ "av_new_packet",
+ "av_destruct_packet",
+ "av_free_packet",
"avcodec_decode_audio4", // 53.25.0 (opt)
- "avcodec_decode_audio3", // 52.23.0
-/* 15 */ "avcodec_decode_video2", // 52.23.0
-
+/* 27 */ "avcodec_decode_video2", // 52.23.0
+
// libavutil
- "av_pix_fmt_descriptors",
- "av_free",
-/* 18 */ "av_get_bits_per_pixel",
-
+ "av_pix_fmt_descriptors",
+ "av_frame_unref", // 55.0.0 (opt)
+ "av_realloc",
+ "av_free",
+ "av_get_bits_per_pixel",
+ "av_samples_get_buffer_size",
+ "av_get_bytes_per_sample", // 51.4.0
+ "av_opt_set_int", // 51.12.0
+ "av_dict_get",
+ "av_dict_count", // 54.* (opt)
+ "av_dict_set",
+/* 28 */ "av_dict_free",
+
// libavformat
"avformat_alloc_context",
"avformat_free_context", // 52.96.0 (opt)
"avformat_close_input", // 53.17.0 (opt)
- "av_close_input_file",
- "av_register_all",
- "avformat_open_input",
- "av_dump_format",
+ "av_register_all",
+ "av_find_input_format",
+ "avformat_open_input",
+ "av_dump_format",
"av_read_frame",
"av_seek_frame",
+ "avformat_seek_file", // ??? (opt)
+ "av_read_play",
+ "av_read_pause",
"avformat_network_init", // 53.13.0 (opt)
"avformat_network_deinit", // 53.13.0 (opt)
- "avformat_find_stream_info", // 53.3.0 (opt)
-/* 29 */ "av_find_stream_info",
- };
-
- // alternate symbol names
- private static String[][] altSymbolNames = {
- { "avcodec_open", "avcodec_open2" }, // old, 53.6.0
- { "avcodec_decode_audio3", "avcodec_decode_audio4" }, // old, 53.25.0
- { "av_close_input_file", "avformat_close_input" }, // old, 53.17.0
- { "av_find_stream_info", "avformat_find_stream_info" }, // old, 53.3.0
+/* 54 */ "avformat_find_stream_info", // 53.3.0 (opt)
+
+ // libavdevice
+/* 55 */ "avdevice_register_all", // ???
+
+ // libavresample
+ "avresample_alloc_context", // 1.0.1
+ "avresample_open",
+ "avresample_close",
+ "avresample_free",
+/* 60 */ "avresample_convert",
+
+ // libavresample
+ "av_opt_set_sample_fmt", // actually lavu .. but exist only w/ swresample!
+ "swr_alloc",
+ "swr_init",
+ "swr_free",
+/* 65 */ "swr_convert",
+
};
-
+
// optional symbol names
- private static String[] optionalSymbolNames = {
- "avformat_free_context", // 52.96.0 (opt)
- "avformat_network_init", // 53.13.0 (opt)
- "avformat_network_deinit", // 53.13.0 (opt)
+ private static final String[] optionalSymbolNames = {
+ "avformat_seek_file", // ??? (opt)
+ "avcodec_free_frame", // 54.28.0 (opt)
+ "av_frame_unref", // 55.0.0 (opt)
+ "av_dict_count", // 54.* (opt)
+ "avcodec_default_get_buffer", // <= 54 (opt), else sp_avcodec_default_get_buffer2
+ "avcodec_default_release_buffer", // <= 54 (opt), else sp_av_frame_unref
+ "avcodec_default_get_buffer2", // 55 (opt)
+
+ // libavdevice
+ "avdevice_register_all", // 53.0.0 (opt)
+
+ // libavresample
+ "avresample_version", // 1.0.1
+ "avresample_alloc_context", // 1.0.1
+ "avresample_open",
+ "avresample_close",
+ "avresample_free",
+ "avresample_convert",
+
+ // libavresample
+ "av_opt_set_sample_fmt", // actually lavu .. but exist only w/ swresample!
+ "swresample_version", // 0
+ "swr_alloc",
+ "swr_init",
+ "swr_free",
+ "swr_convert",
};
-
- private static long[] symbolAddr;
+
+ private static final long[] symbolAddr = new long[symbolCount];
private static final boolean ready;
-
+ private static final boolean libsUFCLoaded;
+ private static final boolean avresampleLoaded; // optional
+ private static final boolean swresampleLoaded; // optional
+ private static final boolean avdeviceLoaded; // optional
+ static final VersionNumber avCodecVersion;
+ static final VersionNumber avFormatVersion;
+ static final VersionNumber avUtilVersion;
+ static final VersionNumber avResampleVersion;
+ static final VersionNumber swResampleVersion;
+ private static final FFMPEGNatives natives;
+
+ private static final int LIB_IDX_UTI = 0;
+ private static final int LIB_IDX_FMT = 1;
+ private static final int LIB_IDX_COD = 2;
+ private static final int LIB_IDX_DEV = 3;
+ private static final int LIB_IDX_AVR = 4;
+ private static final int LIB_IDX_SWR = 5;
+
static {
- // native ffmpeg media player implementation is included in jogl_desktop and jogl_mobile
+ // native ffmpeg media player implementation is included in jogl_desktop and jogl_mobile
GLProfile.initSingleton();
boolean _ready = false;
+ /** util, format, codec, device, avresample, swresample */
+ final boolean[] _loaded= new boolean[6];
+ /** util, format, codec, avresample, swresample */
+ final VersionNumber[] _versions = new VersionNumber[5];
try {
- _ready = initSymbols();
- } catch (Throwable t) {
+ _ready = initSymbols(_loaded, _versions);
+ } catch (final Throwable t) {
t.printStackTrace();
}
- ready = _ready;
- if(!ready) {
- System.err.println("FFMPEG: Not Available");
+ libsUFCLoaded = _loaded[LIB_IDX_UTI] && _loaded[LIB_IDX_FMT] && _loaded[LIB_IDX_COD];
+ avdeviceLoaded = _loaded[LIB_IDX_DEV];
+ avresampleLoaded = _loaded[LIB_IDX_AVR];
+ swresampleLoaded = _loaded[LIB_IDX_SWR];
+ avUtilVersion = _versions[0];
+ avFormatVersion = _versions[1];
+ avCodecVersion = _versions[2];
+ avResampleVersion = _versions[3];
+ swResampleVersion = _versions[4];
+ if(!libsUFCLoaded) {
+ System.err.println("LIB_AV Not Available: lavu, lavc, lavu");
+ natives = null;
+ ready = false;
+ } else if(!_ready) {
+ System.err.println("LIB_AV Not Matching");
+ natives = null;
+ ready = false;
+ } else {
+ final int avCodecMajor = avCodecVersion.getMajor();
+ final int avFormatMajor = avFormatVersion.getMajor();
+ final int avUtilMajor = avUtilVersion.getMajor();
+ if( avCodecMajor == 53 && avFormatMajor == 53 && avUtilMajor == 51 ) {
+ // lavc53.lavf53.lavu51
+ natives = new FFMPEGv08Natives();
+ } else if( avCodecMajor == 54 && avFormatMajor == 54 && avUtilMajor == 52 ) {
+ // lavc54.lavf54.lavu52.lavr01
+ natives = new FFMPEGv09Natives();
+ } else if( avCodecMajor == 55 && avFormatMajor == 55 && ( avUtilMajor == 52 || avUtilMajor == 53 ) ) {
+ // lavc55.lavf55.lavu52.lavr01 (ffmpeg) or lavc55.lavf55.lavu53.lavr01 (libav)
+ natives = new FFMPEGv10Natives();
+ } else {
+ System.err.println("LIB_AV No Version/Native-Impl Match");
+ natives = null;
+ }
+ if( null != natives && FFMPEGStaticNatives.initIDs0() ) {
+ ready = natives.initSymbols0(symbolAddr, symbolCount);
+ } else {
+ ready = false;
+ }
}
}
-
+
+ static boolean libsLoaded() { return libsUFCLoaded; }
+ static boolean avDeviceLoaded() { return avdeviceLoaded; }
+ static boolean avResampleLoaded() { return avresampleLoaded; }
+ static boolean swResampleLoaded() { return swresampleLoaded; }
+ static FFMPEGNatives getNatives() { return natives; }
static boolean initSingleton() { return ready; }
-
- private static boolean initSymbols() {
- final DynamicLibraryBundle dl = new DynamicLibraryBundle(new FFMPEGDynamicLibraryBundleInfo());
- final boolean avutilLoaded = dl.isToolLibLoaded(0);
- final boolean avformatLoaded = dl.isToolLibLoaded(1);
- final boolean avcodecLoaded = dl.isToolLibLoaded(2);
- if(!avutilLoaded || !avformatLoaded || !avcodecLoaded) {
- throw new RuntimeException("FFMPEG Tool library incomplete: [ avutil "+avutilLoaded+", avformat "+avformatLoaded+", avcodec "+avcodecLoaded+"]");
- }
- if(!dl.isToolLibComplete()) {
- throw new RuntimeException("FFMPEG Tool libraries incomplete");
+
+ /**
+ * @param loaded 6: util, format, codec, device, avresample, swresample
+ * @param versions 5: util, format, codec, avresample, swresample
+ * @return
+ */
+ private static final boolean initSymbols(final boolean[] loaded, final VersionNumber[] versions) {
+ for(int i=0; i<6; i++) {
+ loaded[i] = false;
+ }
+ final DynamicLibraryBundle dl = AccessController.doPrivileged(new PrivilegedAction<DynamicLibraryBundle>() {
+ @Override
+ public DynamicLibraryBundle run() {
+ return new DynamicLibraryBundle(new FFMPEGDynamicLibraryBundleInfo());
+ } } );
+ dl.toString();
+ for(int i=0; i<6; i++) {
+ loaded[i] = dl.isToolLibLoaded(i);
+ }
+ if( !loaded[LIB_IDX_UTI] || !loaded[LIB_IDX_FMT] || !loaded[LIB_IDX_COD] ) {
+ throw new RuntimeException("FFMPEG Tool library incomplete: [ avutil "+loaded[LIB_IDX_UTI]+", avformat "+loaded[LIB_IDX_FMT]+", avcodec "+loaded[LIB_IDX_COD]+"]");
}
if(symbolNames.length != symbolCount) {
throw new InternalError("XXX0 "+symbolNames.length+" != "+symbolCount);
}
- symbolAddr = new long[symbolCount];
-
+
// optional symbol name set
final Set<String> optionalSymbolNameSet = new HashSet<String>();
optionalSymbolNameSet.addAll(Arrays.asList(optionalSymbolNames));
-
- // alternate symbol name mapping to indexed array
- final Map<String, Integer> mAltSymbolNames = new HashMap<String, Integer>();
- final int[][] iAltSymbolNames = new int[altSymbolNames.length][];
- {
- final List<String> symbolNameList = Arrays.asList(symbolNames);
- for(int i=0; i<altSymbolNames.length; i++) {
- iAltSymbolNames[i] = new int[altSymbolNames[i].length];
- for(int j=0; j<altSymbolNames[i].length; j++) {
- mAltSymbolNames.put(altSymbolNames[i][j], new Integer(i));
- iAltSymbolNames[i][j] = symbolNameList.indexOf(altSymbolNames[i][j]);
- }
- }
- }
-
+
// lookup
- for(int i = 0; i<symbolCount; i++) {
- symbolAddr[i] = dl.dynamicLookupFunction(symbolNames[i]);
- }
-
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ for(int i = 0; i<symbolCount; i++) {
+ symbolAddr[i] = dl.dynamicLookupFunction(symbolNames[i]);
+ }
+ return null;
+ } } );
+
// validate results
+ boolean res = true;
for(int i = 0; i<symbolCount; i++) {
if( 0 == symbolAddr[i] ) {
// no symbol, check optional and alternative symbols
final String symbol = symbolNames[i];
if ( !optionalSymbolNameSet.contains(symbol) ) {
- // check for API changed symbols
- boolean ok = false;
- final Integer cI = mAltSymbolNames.get(symbol);
- if ( null != cI ) {
- // check whether alternative symbol is available
- final int ci = cI.intValue();
- for(int j=0; !ok && j<iAltSymbolNames[ci].length; j++) {
- final int si = iAltSymbolNames[ci][j];
- ok = 0 != symbolAddr[si];
- if(ok && (true || DEBUG )) { // keep it verbose per default for now ..
- System.err.println("OK: Unresolved symbol <"+symbol+">, but has alternative <"+symbolNames[si]+">");
- }
- }
- }
- if(!ok) {
- System.err.println("Fail: Could not resolve symbol <"+symbolNames[i]+">: not optional, no alternatives.");
- return false;
- }
- } else if(true || DEBUG ) { // keep it verbose per default for now ..
+ System.err.println("Fail: Could not resolve symbol <"+symbolNames[i]+">: not optional, no alternatives.");
+ res = false;
+ } else if(DEBUG) {
System.err.println("OK: Unresolved optional symbol <"+symbolNames[i]+">");
}
}
}
- return initSymbols0(symbolAddr, symbolCount);
+ versions[0] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[0]));
+ versions[1] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[1]));
+ versions[2] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[2]));
+ versions[3] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[3]));
+ versions[4] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[4]));
+
+ return res;
}
-
+
protected FFMPEGDynamicLibraryBundleInfo() {
}
@Override
- public boolean shallLinkGlobal() { return true; }
+ public final boolean shallLinkGlobal() { return true; }
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns <code>true</code>.
+ * </p>
+ */
@Override
- public boolean shallLookupGlobal() { return true; }
-
+ public final boolean shallLookupGlobal() {
+ return true;
+ }
+
@Override
public final List<String> getGlueLibNames() {
return glueLibNames;
}
@Override
- public List<List<String>> getToolLibNames() {
- List<List<String>> libsList = new ArrayList<List<String>>();
+ public final List<List<String>> getToolLibNames() {
+ final List<List<String>> libsList = new ArrayList<List<String>>();
+
+ // 6: util, format, codec, device, avresample, swresample
final List<String> avutil = new ArrayList<String>();
avutil.add("avutil"); // default
- avutil.add("libavutil.so.52"); // dummy future proof
+ avutil.add("libavutil.so.53"); // dummy future proof
+ avutil.add("libavutil.so.52"); // ffmpeg 1.2 + 2 / libav 9 + 10
avutil.add("libavutil.so.51"); // 0.8
avutil.add("libavutil.so.50"); // 0.7
-
- avutil.add("avutil-52"); // dummy future proof
+
+ avutil.add("avutil-53"); // dummy future proof
+ avutil.add("avutil-52"); // ffmpeg 1.2 + 2 / libav 9 + 10
avutil.add("avutil-51"); // 0.8
avutil.add("avutil-50"); // 0.7
libsList.add(avutil);
-
+
final List<String> avformat = new ArrayList<String>();
avformat.add("avformat"); // default
- avformat.add("libavformat.so.55"); // dummy future proof
- avformat.add("libavformat.so.54"); // 0.?
+ avformat.add("libavformat.so.56"); // dummy future proof
+ avformat.add("libavformat.so.55"); // ffmpeg 2 / libav 10
+ avformat.add("libavformat.so.54"); // ffmpeg 1.2 / libav 9
avformat.add("libavformat.so.53"); // 0.8
avformat.add("libavformat.so.52"); // 0.7
-
- avformat.add("avformat-55"); // dummy future proof
- avformat.add("avformat-54"); // 0.?
+
+ avformat.add("avformat-56"); // dummy future proof
+ avformat.add("avformat-55"); // ffmpeg 2 / libav 10
+ avformat.add("avformat-54"); // ffmpeg 1.2 / libav 9
avformat.add("avformat-53"); // 0.8
avformat.add("avformat-52"); // 0.7
libsList.add(avformat);
-
+
final List<String> avcodec = new ArrayList<String>();
avcodec.add("avcodec"); // default
- avcodec.add("libavcodec.so.55"); // dummy future proof
- avcodec.add("libavcodec.so.54"); // 0.?
+ avcodec.add("libavcodec.so.56"); // dummy future proof
+ avcodec.add("libavcodec.so.55"); // ffmpeg 2/ libav 10
+ avcodec.add("libavcodec.so.54"); // ffmpeg 1.2 / libav 9
avcodec.add("libavcodec.so.53"); // 0.8
- avcodec.add("libavcodec.so.52"); // 0.7
-
- avcodec.add("avcodec-55"); // dummy future proof
- avcodec.add("avcodec-54"); // 0.?
+ avcodec.add("libavcodec.so.52"); // 0.7
+
+ avcodec.add("avcodec-56"); // dummy future proof
+ avcodec.add("avcodec-55"); // ffmpeg 2/ libav 10
+ avcodec.add("avcodec-54"); // ffmpeg 1.2 / libav 9
avcodec.add("avcodec-53"); // 0.8
avcodec.add("avcodec-52"); // 0.7
libsList.add(avcodec);
-
+
+ final List<String> avdevice = new ArrayList<String>();
+ avdevice.add("avdevice"); // default
+
+ avdevice.add("libavdevice.so.56"); // dummy future proof
+ avdevice.add("libavdevice.so.55"); // ffmpeg 2
+ avdevice.add("libavdevice.so.54"); // ffmpeg 1.2 / libav 10
+ avdevice.add("libavdevice.so.53"); // 0.8 && libav 9
+
+ avdevice.add("avdevice-56"); // dummy future proof
+ avdevice.add("avdevice-55"); // ffmpeg 2
+ avdevice.add("avdevice-54"); // ffmpeg 1.2 / libav 10
+ avdevice.add("avdevice-53"); // 0.8 && libav 9
+ libsList.add(avdevice);
+
+ final List<String> avresample = new ArrayList<String>();
+ avresample.add("avresample"); // default
+
+ avresample.add("libavresample.so.2"); // dummy future proof
+ avresample.add("libavresample.so.1"); // libav 9 + 10
+
+ avresample.add("avresample-2"); // dummy future proof
+ avresample.add("avresample-1"); // libav 9 + 10
+ libsList.add(avresample);
+
+ final List<String> swresample = new ArrayList<String>();
+ swresample.add("swresample"); // default
+
+ swresample.add("libswresample.so.1"); // dummy future proof
+ swresample.add("libswresample.so.0"); // ffmpeg 1.2 + 2.x
+
+ swresample.add("swresample-1"); // dummy future proof
+ swresample.add("swresample-0"); // ffmpeg 1.2 + 2.x
+ libsList.add(swresample);
+
return libsList;
}
@@ -269,19 +424,17 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
@Override
- public final long toolGetProcAddress(long toolGetProcAddressHandle, String funcName) {
+ public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) {
return 0;
}
@Override
- public boolean useToolGetProcAdressFirst(String funcName) {
+ public final boolean useToolGetProcAdressFirst(final String funcName) {
return false;
}
@Override
- public RunnableExecutor getLibLoaderExecutor() {
+ public final RunnableExecutor getLibLoaderExecutor() {
return DynamicLibraryBundle.getDefaultRunnableExecutor();
- }
-
- private static native boolean initSymbols0(long[] symbols, int count);
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
index 4be2bcb58..4601df67d 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -29,514 +29,806 @@
package jogamp.opengl.util.av.impl;
import java.io.IOException;
-import java.nio.Buffer;
import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLException;
+import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.gluegen.runtime.ProcAddressTable;
+import com.jogamp.opengl.util.TimeFrameI;
import com.jogamp.opengl.util.GLPixelStorageModes;
+import com.jogamp.opengl.util.av.AudioSink;
+import com.jogamp.opengl.util.av.AudioSink.AudioFormat;
+import com.jogamp.opengl.util.av.AudioSinkFactory;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
import com.jogamp.opengl.util.texture.Texture;
-import com.jogamp.opengl.util.texture.TextureSequence;
+import jogamp.common.os.PlatformPropsImpl;
import jogamp.opengl.GLContextImpl;
-import jogamp.opengl.es1.GLES1ProcAddressTable;
-import jogamp.opengl.es2.GLES2ProcAddressTable;
-import jogamp.opengl.gl4.GL4bcProcAddressTable;
-import jogamp.opengl.util.av.EGLMediaPlayerImpl;
+import jogamp.opengl.util.av.AudioSampleFormat;
+import jogamp.opengl.util.av.GLMediaPlayerImpl;
+import jogamp.opengl.util.av.VideoPixelFormat;
/***
* Implementation utilizes <a href="http://libav.org/">Libav</a>
- * or <a href="http://ffmpeg.org/">FFmpeg</a> which is ubiquitous
- * available and usually pre-installed on Unix platforms. Due to legal
- * reasons we cannot deploy binaries of it, which contains patented codecs.
+ * or <a href="http://ffmpeg.org/">FFmpeg</a> which are ubiquitous
+ * available and usually pre-installed on Unix platforms.
+ * <p>
+ * Due to legal reasons we cannot deploy binaries of it, which contains patented codecs.
+ * </p>
+ * <p>
* Besides the default BSD/Linux/.. repositories and installations,
- * precompiled binaries can be found at the listed location below.
+ * precompiled binaries can be found at the
+ * <a href="#libavavail">listed location below</a>.
+ * </p>
+ *
+ * <a name="implspecifics"><h5>Implementation specifics</h5></a>
* <p>
- * Implements YUV420P to RGB fragment shader conversion
- * and the usual packed RGB formats.
- * The decoded video frame is written directly into an OpenGL texture
- * on the GPU in it's native format. A custom fragment shader converts
- * the native pixelformat to a usable RGB format if required.
- * Hence only 1 copy is required before bloating the picture
- * from YUV to RGB, for example.
- * </p>
+ * The decoded video frame is written directly into an OpenGL texture
+ * on the GPU in it's native format. A custom fragment shader converts
+ * the native pixelformat to a usable <i>RGB</i> format if required.
+ * Hence only 1 copy is required before bloating the picture
+ * from <i>YUV*</i> to <i>RGB</i>, for example.
+ * </p>
* <p>
- * Utilizes a slim dynamic and native binding to the Lib_av
+ * Implements pixel format conversion to <i>RGB</i> via
+ * fragment shader texture-lookup functions:
+ * <ul>
+ * <li>{@link VideoPixelFormat#YUV420P}</li>
+ * <li>{@link VideoPixelFormat#YUVJ420P}</li>
+ * <li>{@link VideoPixelFormat#YUV422P}</li>
+ * <li>{@link VideoPixelFormat#YUVJ422P}</li>
+ * <li>{@link VideoPixelFormat#YUYV422}</li>
+ * <li>{@link VideoPixelFormat#BGR24}</li>
+ * </ul>
+ * </p>
+ * <p>
+ *
+ * <a name="libavspecifics"><h5>Libav Specifics</h5></a>
+ * <p>
+ * Utilizes a slim dynamic and native binding to the Lib_av
* libraries:
* <ul>
- * <li>libavutil</li>
- * <li>libavformat</li>
* <li>libavcodec</li>
- * </ul>
+ * <li>libavformat</li>
+ * <li>libavutil</li>
+ * <li>libavresample (opt)</li>
+ * <li>libavdevice (opt)</li>
+ * </ul>
+ * </p>
+ *
+ * <a name="compatibility"><h5>LibAV Compatibility</h5></a>
+ * <p>
+ * Currently we are binary compatible w/:
+ * <table border="1">
+ * <tr><th>libav / ffmpeg</th><th>lavc</th><th>lavf</th><th>lavu</th><th>lavr</th> <th>FFMPEG* class</th></tr>
+ * <tr><td>0.8</td> <td>53</td> <td>53</td> <td>51</td> <td></td> <td>FFMPEGv08</td></tr>
+ * <tr><td>9.0 / 1.2</td> <td>54</td> <td>54</td> <td>52</td> <td>01/00</td> <td>FFMPEGv09</td></tr>
+ * <tr><td>10 / 2</td> <td>55</td> <td>55</td> <td>53/52</td> <td>01/00</td> <td>FFMPEGv10</td></tr>
+ * </table>
* </p>
* <p>
- * http://libav.org/
+ * See http://upstream-tracker.org/versions/libav.html
* </p>
- * <p>
- * Check tag 'FIXME: Add more planar formats !'
+ * <p>
+ * Check tag 'FIXME: Add more planar formats !'
* here and in the corresponding native code
- * <code>jogl/src/jogl/native/ffmpeg/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c</code>
+ * <code>jogl/src/jogl/native/libav/ffmpeg_impl_template.c</code>
* </p>
+ *
+ *
+ * <a name="todo"><h5>TODO:</h5></a>
* <p>
- * TODO:
* <ul>
- * <li>Audio Output</li>
- * <li>Off thread <i>next frame</i> processing using multiple target textures</li>
- * <li>better pts sync handling</li>
- * <li>fix seek</li>
- * </ul>
+ * <li>better audio synchronization handling? (video is synchronized)</li>
+ * </ul>
* </p>
- * Pre-compiled Libav / FFmpeg packages:
+ *
+ * <a name="libavavail"><h5>FFMPEG / LibAV Availability</h5></a>
+ * <p>
* <ul>
- * <li>Windows: http://ffmpeg.zeranoe.com/builds/</li>
- * <li>MacOSX: http://www.ffmpegx.com/</li>
+ * <li>GNU/Linux: ffmpeg or libav are deployed in most distributions.</li>
+ * <li>Windows:
+ * <ul>
+ * <li>http://ffmpeg.zeranoe.com/builds/ (ffmpeg) <i>recommended, works w/ dshow</i></li>
+ * <li>http://win32.libav.org/releases/ (libav)</li>
+ * </ul></li>
+ * <li>MacOSX using Homebrew
+ * <ul>
+ * <li>https://github.com/Homebrew/homebrew/wiki/Installation</li>
+ * <li>https://trac.ffmpeg.org/wiki/CompilationGuide/MacOSX</li>
+ * </ul></li>
* <li>OpenIndiana/Solaris:<pre>
* pkg set-publisher -p http://pkg.openindiana.org/sfe-encumbered.
* pkt install pkg:/video/ffmpeg
* </pre></li>
- * </ul>
+ * </ul>
+ * </p>
*/
-public class FFMPEGMediaPlayer extends EGLMediaPlayerImpl {
- public static final VersionNumber avUtilVersion;
- public static final VersionNumber avFormatVersion;
- public static final VersionNumber avCodecVersion;
- static final boolean available;
-
+public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
+
+ /** POSIX ENOSYS {@value}: Function not implemented. FIXME: Move to GlueGen ?!*/
+ private static final int ENOSYS = 38;
+
+ // Instance data
+ private static final FFMPEGNatives natives;
+ private static final int avUtilMajorVersionCC;
+ private static final int avFormatMajorVersionCC;
+ private static final int avCodecMajorVersionCC;
+ private static final int avResampleMajorVersionCC;
+ private static final int swResampleMajorVersionCC;
+ private static final boolean available;
+
static {
- if(FFMPEGDynamicLibraryBundleInfo.initSingleton()) {
- avUtilVersion = getAVVersion(getAvUtilVersion0());
- avFormatVersion = getAVVersion(getAvFormatVersion0());
- avCodecVersion = getAVVersion(getAvCodecVersion0());
- System.err.println("LIB_AV Util : "+avUtilVersion);
- System.err.println("LIB_AV Format: "+avFormatVersion);
- System.err.println("LIB_AV Codec : "+avCodecVersion);
- available = initIDs0();
+ final boolean libAVGood = FFMPEGDynamicLibraryBundleInfo.initSingleton();
+ final boolean libAVVersionGood;
+ if( FFMPEGDynamicLibraryBundleInfo.libsLoaded() ) {
+ natives = FFMPEGDynamicLibraryBundleInfo.getNatives();
+ if( null != natives ) {
+ avCodecMajorVersionCC = natives.getAvCodecMajorVersionCC0();
+ avFormatMajorVersionCC = natives.getAvFormatMajorVersionCC0();
+ avUtilMajorVersionCC = natives.getAvUtilMajorVersionCC0();
+ avResampleMajorVersionCC = natives.getAvResampleMajorVersionCC0();
+ swResampleMajorVersionCC = natives.getSwResampleMajorVersionCC0();
+ } else {
+ avUtilMajorVersionCC = 0;
+ avFormatMajorVersionCC = 0;
+ avCodecMajorVersionCC = 0;
+ avResampleMajorVersionCC = 0;
+ swResampleMajorVersionCC = 0;
+ }
+ final VersionNumber avCodecVersion = FFMPEGDynamicLibraryBundleInfo.avCodecVersion;
+ final VersionNumber avFormatVersion = FFMPEGDynamicLibraryBundleInfo.avFormatVersion;
+ final VersionNumber avUtilVersion = FFMPEGDynamicLibraryBundleInfo.avUtilVersion;
+ final VersionNumber avResampleVersion = FFMPEGDynamicLibraryBundleInfo.avResampleVersion;
+ final boolean avResampleLoaded = FFMPEGDynamicLibraryBundleInfo.avResampleLoaded();
+ final VersionNumber swResampleVersion = FFMPEGDynamicLibraryBundleInfo.swResampleVersion;
+ final boolean swResampleLoaded = FFMPEGDynamicLibraryBundleInfo.swResampleLoaded();
+ if( DEBUG ) {
+ System.err.println("LIB_AV Codec : "+avCodecVersion+" [cc "+avCodecMajorVersionCC+"]");
+ System.err.println("LIB_AV Format : "+avFormatVersion+" [cc "+avFormatMajorVersionCC+"]");
+ System.err.println("LIB_AV Util : "+avUtilVersion+" [cc "+avUtilMajorVersionCC+"]");
+ System.err.println("LIB_AV Resample: "+avResampleVersion+" [cc "+avResampleMajorVersionCC+", loaded "+avResampleLoaded+"]");
+ System.err.println("LIB_SW Resample: "+swResampleVersion+" [cc "+swResampleMajorVersionCC+", loaded "+swResampleLoaded+"]");
+ System.err.println("LIB_AV Device : [loaded "+FFMPEGDynamicLibraryBundleInfo.avDeviceLoaded()+"]");
+ System.err.println("LIB_AV Class : "+(null!= natives ? natives.getClass().getSimpleName() : "n/a"));
+ }
+ final int avCodecMajor = avCodecVersion.getMajor();
+ final int avFormatMajor = avFormatVersion.getMajor();
+ final int avUtilMajor = avUtilVersion.getMajor();
+ libAVVersionGood = avCodecMajorVersionCC == avCodecMajor &&
+ avFormatMajorVersionCC == avFormatMajor &&
+ ( avUtilMajorVersionCC == avUtilMajor ||
+ 55 == avCodecMajorVersionCC && 53 == avUtilMajorVersionCC && 52 == avUtilMajor /* ffmpeg 2.x */
+ ) &&
+ ( !avResampleLoaded || avResampleMajorVersionCC < 0 || avResampleMajorVersionCC == avResampleVersion.getMajor() ) &&
+ ( !swResampleLoaded || swResampleMajorVersionCC < 0 || swResampleMajorVersionCC == swResampleVersion.getMajor() ) ;
+ if( !libAVVersionGood ) {
+ System.err.println("LIB_AV Not Matching Compile-Time / Runtime Major-Version");
+ }
} else {
- avUtilVersion = null;
- avFormatVersion = null;
- avCodecVersion = null;
- available = false;
+ natives = null;
+ avUtilMajorVersionCC = 0;
+ avFormatMajorVersionCC = 0;
+ avCodecMajorVersionCC = 0;
+ avResampleMajorVersionCC = 0;
+ swResampleMajorVersionCC = 0;
+ libAVVersionGood = false;
}
+ available = libAVGood && libAVVersionGood && null != natives;
}
-
+
public static final boolean isAvailable() { return available; }
- private static VersionNumber getAVVersion(int vers) {
- return new VersionNumber( ( vers >> 16 ) & 0xFF,
- ( vers >> 8 ) & 0xFF,
- ( vers >> 0 ) & 0xFF );
- }
-
- protected long moviePtr = 0;
- protected long procAddrGLTexSubImage2D = 0;
- protected EGLMediaPlayerImpl.EGLTextureFrame lastTex = null;
- protected GLPixelStorageModes psm;
- protected PixelFormat vPixelFmt = null;
- protected int vPlanes = 0;
- protected int vBitsPerPixel = 0;
- protected int vBytesPerPixelPerPlane = 0;
- protected int[] vLinesize = { 0, 0, 0 }; // per plane
- protected int[] vTexWidth = { 0, 0, 0 }; // per plane
- protected int texWidth, texHeight; // overall (stuffing planes in one texture)
- protected ByteBuffer texCopy;
+ //
+ // General
+ //
+
+ private long moviePtr = 0;
+
+ //
+ // Video
+ //
+
+ private String texLookupFuncName = "ffmpegTexture2D";
+ private boolean usesTexLookupShader = false;
+ private VideoPixelFormat vPixelFmt = null;
+ private int vPlanes = 0;
+ private int vBitsPerPixel = 0;
+ private int vBytesPerPixelPerPlane = 0;
+ private int texWidth, texHeight; // overall (stuffing planes in one texture)
+ private String singleTexComp = "r";
+ private final GLPixelStorageModes psm;
+
+ //
+ // Audio
+ //
+
+ private AudioSink.AudioFormat avChosenAudioFormat;
+ private int audioSamplesPerFrameAndChannel = 0;
public FFMPEGMediaPlayer() {
- super(TextureType.GL, false);
if(!available) {
throw new RuntimeException("FFMPEGMediaPlayer not available");
}
- setTextureCount(1);
- moviePtr = createInstance0(true);
+ moviePtr = natives.createInstance0(this, DEBUG_NATIVE);
if(0==moviePtr) {
throw new GLException("Couldn't create FFMPEGInstance");
}
psm = new GLPixelStorageModes();
+ audioSink = null;
}
-
+
@Override
- protected TextureSequence.TextureFrame createTexImage(GL gl, int idx, int[] tex) {
- if(TextureType.GL == texType) {
- final Texture texture = super.createTexImageImpl(gl, idx, tex, texWidth, texHeight, true);
- lastTex = new EGLTextureFrame(null, texture, 0, 0);
- } else {
- throw new InternalError("n/a");
+ protected final void destroyImpl(final GL gl) {
+ if (moviePtr != 0) {
+ natives.destroyInstance0(moviePtr);
+ moviePtr = 0;
}
- return lastTex;
+ destroyAudioSink();
}
-
- @Override
- protected void destroyTexImage(GL gl, TextureSequence.TextureFrame imgTex) {
- lastTex = null;
- super.destroyTexImage(gl, imgTex);
+ private final void destroyAudioSink() {
+ final AudioSink _audioSink = audioSink;
+ if( null != _audioSink ) {
+ audioSink = null;
+ _audioSink.destroy();
+ }
}
-
+
+ public static final String dev_video_linux = "/dev/video";
+
@Override
- protected void destroyImpl(GL gl) {
- if (moviePtr != 0) {
- destroyInstance0(moviePtr);
- moviePtr = 0;
+ protected final void initStreamImpl(final int vid, final int aid) throws IOException {
+ if(0==moviePtr) {
+ throw new GLException("FFMPEG native instance null");
}
+ if(DEBUG) {
+ System.err.println("initStream: p1 "+this);
+ }
+
+ final String streamLocS = IOUtil.getUriFilePathOrASCII(getUri());
+ destroyAudioSink();
+ if( GLMediaPlayer.STREAM_ID_NONE == aid ) {
+ audioSink = AudioSinkFactory.createNull();
+ } else {
+ audioSink = AudioSinkFactory.createDefault();
+ }
+ final AudioFormat preferredAudioFormat = audioSink.getPreferredFormat();
+ if(DEBUG) {
+ System.err.println("initStream: p2 preferred "+preferredAudioFormat+", "+this);
+ }
+
+ final boolean isCameraInput = null != cameraPath;
+ final String resStreamLocS;
+ // int rw=640, rh=480, rr=15;
+ int rw=-1, rh=-1, rr=-1;
+ String sizes = null;
+ if( isCameraInput ) {
+ switch(PlatformPropsImpl.OS_TYPE) {
+ case ANDROID:
+ // ??
+ case FREEBSD:
+ case HPUX:
+ case LINUX:
+ case SUNOS:
+ resStreamLocS = dev_video_linux + cameraPath.decode();
+ break;
+ case WINDOWS:
+ resStreamLocS = cameraPath.decode();
+ break;
+ case MACOS:
+ case OPENKODE:
+ default:
+ resStreamLocS = streamLocS; // FIXME: ??
+ break;
+ }
+ if( null != cameraProps ) {
+ sizes = cameraProps.get(CameraPropSizeS);
+ int v = getPropIntVal(cameraProps, CameraPropWidth);
+ if( v > 0 ) { rw = v; }
+ v = getPropIntVal(cameraProps, CameraPropHeight);
+ if( v > 0 ) { rh = v; }
+ v = getPropIntVal(cameraProps, CameraPropRate);
+ if( v > 0 ) { rr = v; }
+ }
+ } else {
+ resStreamLocS = streamLocS;
+ }
+ final int aMaxChannelCount = audioSink.getMaxSupportedChannels();
+ final int aPrefSampleRate = preferredAudioFormat.sampleRate;
+ // setStream(..) issues updateAttributes*(..), and defines avChosenAudioFormat, vid, aid, .. etc
+ if(DEBUG) {
+ System.err.println("initStream: p3 cameraPath "+cameraPath+", isCameraInput "+isCameraInput);
+ System.err.println("initStream: p3 stream "+getUri()+" -> "+streamLocS+" -> "+resStreamLocS);
+ System.err.println("initStream: p3 vid "+vid+", sizes "+sizes+", reqVideo "+rw+"x"+rh+"@"+rr+", aid "+aid+", aMaxChannelCount "+aMaxChannelCount+", aPrefSampleRate "+aPrefSampleRate);
+ }
+ natives.setStream0(moviePtr, resStreamLocS, isCameraInput, vid, sizes, rw, rh, rr, aid, aMaxChannelCount, aPrefSampleRate);
}
-
+
@Override
- protected void initGLStreamImpl(GL gl, int[] texNames) throws IOException {
+ protected final void initGLImpl(final GL gl) throws IOException, GLException {
if(0==moviePtr) {
throw new GLException("FFMPEG native instance null");
}
- final String urlS=urlConn.getURL().toExternalForm();
-
- System.out.println("setURL: p1 "+this);
- setStream0(moviePtr, urlS, -1, -1);
- System.out.println("setURL: p2 "+this);
- int tf, tif=GL.GL_RGBA; // texture format and internal format
- switch(vBytesPerPixelPerPlane) {
- case 1: tf = GL2ES2.GL_ALPHA; tif=GL.GL_ALPHA; break;
- case 3: tf = GL2ES2.GL_RGB; tif=GL.GL_RGB; break;
- case 4: tf = GL2ES2.GL_RGBA; tif=GL.GL_RGBA; break;
- default: throw new RuntimeException("Unsupported bytes-per-pixel / plane "+vBytesPerPixelPerPlane);
- }
- setTextureFormat(tif, tf);
- setTextureType(GL.GL_UNSIGNED_BYTE);
- GLContextImpl ctx = (GLContextImpl)gl.getContext();
- ProcAddressTable pt = ctx.getGLProcAddressTable();
- if(pt instanceof GLES2ProcAddressTable) {
- procAddrGLTexSubImage2D = ((GLES2ProcAddressTable)pt)._addressof_glTexSubImage2D;
- } else if(pt instanceof GLES1ProcAddressTable) {
- procAddrGLTexSubImage2D = ((GLES1ProcAddressTable)pt)._addressof_glTexSubImage2D;
- } else if(pt instanceof GL4bcProcAddressTable) {
- procAddrGLTexSubImage2D = ((GL4bcProcAddressTable)pt)._addressof_glTexSubImage2D;
+ if(null == audioSink) {
+ throw new GLException("AudioSink null");
+ }
+ final int audioQueueLimit;
+ if( null != gl && STREAM_ID_NONE != getVID() ) {
+ final GLContextImpl ctx = (GLContextImpl)gl.getContext();
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ final ProcAddressTable pt = ctx.getGLProcAddressTable();
+ final long procAddrGLTexSubImage2D = pt.getAddressFor("glTexSubImage2D");
+ final long procAddrGLGetError = pt.getAddressFor("glGetError");
+ final long procAddrGLFlush = pt.getAddressFor("glFlush");
+ final long procAddrGLFinish = pt.getAddressFor("glFinish");
+ natives.setGLFuncs0(moviePtr, procAddrGLTexSubImage2D, procAddrGLGetError, procAddrGLFlush, procAddrGLFinish);
+ return null;
+ } } );
+ audioQueueLimit = AudioSink.DefaultQueueLimitWithVideo;
+ } else {
+ audioQueueLimit = AudioSink.DefaultQueueLimitAudioOnly;
+ }
+ if(DEBUG) {
+ System.err.println("initGL: p3 avChosen "+avChosenAudioFormat);
+ }
+
+ if( STREAM_ID_NONE == getAID() ) {
+ audioSink.destroy();
+ audioSink = AudioSinkFactory.createNull();
+ audioSink.init(AudioSink.DefaultFormat, 0, AudioSink.DefaultInitialQueueSize, AudioSink.DefaultQueueGrowAmount, audioQueueLimit);
} else {
- throw new InternalError("Unknown ProcAddressTable: "+pt.getClass().getName()+" of "+ctx.getClass().getName());
+ final float frameDuration;
+ if( audioSamplesPerFrameAndChannel > 0 ) {
+ frameDuration= avChosenAudioFormat.getSamplesDuration(audioSamplesPerFrameAndChannel);
+ } else {
+ frameDuration = AudioSink.DefaultFrameDuration;
+ }
+ final boolean audioSinkOK = audioSink.init(avChosenAudioFormat, frameDuration, AudioSink.DefaultInitialQueueSize, AudioSink.DefaultQueueGrowAmount, audioQueueLimit);
+ if( !audioSinkOK ) {
+ System.err.println("AudioSink "+audioSink.getClass().getName()+" does not support "+avChosenAudioFormat+", using Null");
+ audioSink.destroy();
+ audioSink = AudioSinkFactory.createNull();
+ audioSink.init(avChosenAudioFormat, 0, AudioSink.DefaultInitialQueueSize, AudioSink.DefaultQueueGrowAmount, audioQueueLimit);
+ }
+ }
+ if(DEBUG) {
+ System.err.println("initGL: p4 chosen "+avChosenAudioFormat);
+ System.err.println("initGL: p4 chosen "+audioSink);
+ }
+
+ if( null != gl && STREAM_ID_NONE != getVID() ) {
+ int tf, tif=GL.GL_RGBA; // texture format and internal format
+ final int tt = GL.GL_UNSIGNED_BYTE;
+ switch(vBytesPerPixelPerPlane) {
+ case 1:
+ if( gl.isGL3ES3() ) {
+ // RED is supported on ES3 and >= GL3 [core]; ALPHA is deprecated on core
+ tf = GL2ES2.GL_RED; tif=GL2ES2.GL_RED; singleTexComp = "r";
+ } else {
+ // ALPHA is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
+ tf = GL.GL_ALPHA; tif=GL.GL_ALPHA; singleTexComp = "a";
+ }
+ break;
+
+ case 2: if( vPixelFmt == VideoPixelFormat.YUYV422 ) {
+ // YUYV422: // < packed YUV 4:2:2, 2x 16bpp, Y0 Cb Y1 Cr
+ // Stuffed into RGBA half width texture
+ tf = GL.GL_RGBA; tif=GL.GL_RGBA; break;
+ } else {
+ tf = GL2ES2.GL_RG; tif=GL2ES2.GL_RG; break;
+ }
+ case 3: tf = GL.GL_RGB; tif=GL.GL_RGB; break;
+ case 4: if( vPixelFmt == VideoPixelFormat.BGRA ) {
+ tf = GL.GL_BGRA; tif=GL.GL_RGBA; break;
+ } else {
+ tf = GL.GL_RGBA; tif=GL.GL_RGBA; break;
+ }
+ default: throw new RuntimeException("Unsupported bytes-per-pixel / plane "+vBytesPerPixelPerPlane);
+ }
+ setTextureFormat(tif, tf);
+ setTextureType(tt);
+ if(DEBUG) {
+ System.err.println("initGL: p5: video "+vPixelFmt+", planes "+vPlanes+", bpp "+vBitsPerPixel+"/"+vBytesPerPixelPerPlane+
+ ", tex "+texWidth+"x"+texHeight+", usesTexLookupShader "+usesTexLookupShader);
+ }
}
}
- private void updateAttributes2(int pixFmt, int planes, int bitsPerPixel, int bytesPerPixelPerPlane,
- int lSz0, int lSz1, int lSz2,
- int tWd0, int tWd1, int tWd2) {
- vPixelFmt = PixelFormat.valueOf(pixFmt);
- vPlanes = planes;
- vBitsPerPixel = bitsPerPixel;
- vBytesPerPixelPerPlane = bytesPerPixelPerPlane;
- vLinesize[0] = lSz0; vLinesize[1] = lSz1; vLinesize[2] = lSz2;
- vTexWidth[0] = tWd0; vTexWidth[1] = tWd1; vTexWidth[2] = tWd2;
-
- switch(vPixelFmt) {
- case YUV420P:
- // YUV420P: Adding U+V on right side of fixed height texture,
- // since width is already aligned by decoder.
- // Y=w*h, Y=w/2*h/2, U=w/2*h/2
- // w*h + 2 ( w/2 * h/2 )
- // w*h + w*h/2
- // 2*w/2 * h
- texWidth = vTexWidth[0] + vTexWidth[1]; texHeight = height;
+ @Override
+ protected final TextureFrame createTexImage(final GL gl, final int texName) {
+ return new TextureFrame( createTexImageImpl(gl, texName, texWidth, texHeight) );
+ }
+
+ /**
+ * @param sampleRate sample rate in Hz (1/s)
+ * @param sampleSize sample size in bits
+ * @param channelCount number of channels
+ * @param signed true if signed number, false for unsigned
+ * @param fixedP true for fixed point value, false for unsigned floating point value with a sampleSize of 32 (float) or 64 (double)
+ * @param planar true for planar data package (each channel in own data buffer), false for packed data channels interleaved in one buffer.
+ * @param littleEndian true for little-endian, false for big endian
+ * @return
+ */
+
+ /**
+ * Native callback
+ * Converts the given libav/ffmpeg values to {@link AudioFormat} and returns {@link AudioSink#isSupported(AudioFormat)}.
+ * @param audioSampleFmt ffmpeg/libav audio-sample-format, see {@link AudioSampleFormat}.
+ * @param audioSampleRate sample rate in Hz (1/s)
+ * @param audioChannels number of channels
+ */
+ final boolean isAudioFormatSupported(final int audioSampleFmt, final int audioSampleRate, final int audioChannels) {
+ final AudioSampleFormat avFmt = AudioSampleFormat.valueOf(audioSampleFmt);
+ final AudioFormat audioFormat = avAudioFormat2Local(avFmt, audioSampleRate, audioChannels);
+ final boolean res = audioSink.isSupported(audioFormat);
+ if( DEBUG ) {
+ System.err.println("AudioSink.isSupported: "+res+": av[fmt "+avFmt+", rate "+audioSampleRate+", chan "+audioChannels+"] -> "+audioFormat);
+ }
+ return res;
+ }
+
+ /**
+ * Returns {@link AudioFormat} as converted from the given libav/ffmpeg values.
+ * @param audioSampleFmt ffmpeg/libav audio-sample-format, see {@link AudioSampleFormat}.
+ * @param audioSampleRate sample rate in Hz (1/s)
+ * @param audioChannels number of channels
+ */
+ private final AudioFormat avAudioFormat2Local(final AudioSampleFormat audioSampleFmt, final int audioSampleRate, final int audioChannels) {
+ final int sampleSize;
+ boolean planar = true;
+ boolean fixedP = true;
+ final boolean signed;
+ switch( audioSampleFmt ) {
+ case S32:
+ planar = false;
+ case S32P:
+ sampleSize = 32;
+ signed = true;
+ break;
+ case S16:
+ planar = false;
+ case S16P:
+ sampleSize = 16;
+ signed = true;
+ break;
+ case U8:
+ planar = false;
+ case U8P:
+ sampleSize = 8;
+ signed = false;
+ break;
+ case DBL:
+ planar = false;
+ case DBLP:
+ sampleSize = 64;
+ signed = true;
+ fixedP = false;
break;
- // case PIX_FMT_YUYV422:
- case RGB24:
- case BGR24:
- case ARGB:
- case RGBA:
- case ABGR:
- case BGRA:
- texWidth = vTexWidth[0]; texHeight = height;
+ case FLT:
+ planar = false;
+ case FLTP:
+ sampleSize = 32;
+ signed = true;
+ fixedP = false;
break;
- default: // FIXME: Add more planar formats !
- throw new RuntimeException("Unsupported pixelformat: "+vPixelFmt);
+ default: // FIXME: Add more formats !
+ throw new IllegalArgumentException("Unsupported sampleformat: "+audioSampleFmt);
+ }
+ return new AudioFormat(audioSampleRate, sampleSize, audioChannels, signed, fixedP, planar, true /* littleEndian */);
+ }
+
+ /**
+ * Native callback
+ * @param vid
+ * @param pixFmt
+ * @param planes
+ * @param bitsPerPixel
+ * @param bytesPerPixelPerPlane
+ * @param tWd0
+ * @param tWd1
+ * @param tWd2
+ * @param aid
+ * @param audioSampleFmt
+ * @param audioSampleRate
+ * @param audioChannels
+ * @param audioSamplesPerFrameAndChannel in audio samples per frame and channel
+ */
+ void setupFFAttributes(final int vid, final int pixFmt, final int planes, final int bitsPerPixel, final int bytesPerPixelPerPlane,
+ final int tWd0, final int tWd1, final int tWd2, final int vW, final int vH,
+ final int aid, final int audioSampleFmt, final int audioSampleRate,
+ final int audioChannels, final int audioSamplesPerFrameAndChannel) {
+ // defaults ..
+ vPixelFmt = null;
+ vPlanes = 0;
+ vBitsPerPixel = 0;
+ vBytesPerPixelPerPlane = 0;
+ usesTexLookupShader = false;
+ texWidth = 0; texHeight = 0;
+
+ final int[] vTexWidth = { 0, 0, 0 }; // per plane
+
+ if( STREAM_ID_NONE != vid ) {
+ vPixelFmt = VideoPixelFormat.valueOf(pixFmt);
+ vPlanes = planes;
+ vBitsPerPixel = bitsPerPixel;
+ vBytesPerPixelPerPlane = bytesPerPixelPerPlane;
+ vTexWidth[0] = tWd0; vTexWidth[1] = tWd1; vTexWidth[2] = tWd2;
+
+ switch(vPixelFmt) {
+ case YUVJ420P:
+ case YUV420P: // < planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
+ usesTexLookupShader = true;
+ // YUV420P: Adding U+V on right side of fixed height texture,
+ // since width is already aligned by decoder.
+ // Splitting texture to 4 quadrants:
+ // Y covers left top/low quadrant
+ // U on top-right quadrant.
+ // V on low-right quadrant.
+ // Y=w*h, U=w/2*h/2, V=w/2*h/2
+ // w*h + 2 ( w/2 * h/2 )
+ // w*h + w*h/2
+ texWidth = vTexWidth[0] + vTexWidth[1]; texHeight = vH;
+ break;
+ case YUVJ422P:
+ case YUV422P:
+ usesTexLookupShader = true;
+ // YUV422P: Adding U+V on right side of fixed height texture,
+ // since width is already aligned by decoder.
+ // Splitting texture to 4 columns
+ // Y covers columns 1+2
+ // U covers columns 3
+ // V covers columns 4
+ texWidth = vTexWidth[0] + vTexWidth[1] + vTexWidth[2]; texHeight = vH;
+ break;
+ case YUYV422: // < packed YUV 4:2:2, 2x 16bpp, Y0 Cb Y1 Cr - stuffed into RGBA half width texture
+ case BGR24:
+ usesTexLookupShader = true;
+ texWidth = vTexWidth[0]; texHeight = vH;
+ break;
+
+ case RGB24:
+ case ARGB:
+ case RGBA:
+ case ABGR:
+ case BGRA:
+ usesTexLookupShader = false;
+ texWidth = vTexWidth[0]; texHeight = vH;
+ break;
+ default: // FIXME: Add more formats !
+ throw new RuntimeException("Unsupported pixelformat: "+vPixelFmt);
+ }
}
+
+ // defaults ..
+ final AudioSampleFormat aSampleFmt;
+ avChosenAudioFormat = null;;
+ this.audioSamplesPerFrameAndChannel = 0;
+
+ if( STREAM_ID_NONE != aid ) {
+ aSampleFmt = AudioSampleFormat.valueOf(audioSampleFmt);
+ avChosenAudioFormat = avAudioFormat2Local(aSampleFmt, audioSampleRate, audioChannels);
+ this.audioSamplesPerFrameAndChannel = audioSamplesPerFrameAndChannel;
+ } else {
+ aSampleFmt = null;
+ }
+
if(DEBUG) {
- System.err.println("XXX0: fmt "+vPixelFmt+", planes "+vPlanes+", bpp "+vBitsPerPixel+"/"+vBytesPerPixelPerPlane);
+ System.err.println("audio: id "+aid+", fmt "+aSampleFmt+", "+avChosenAudioFormat+", aFrameSize/fc "+audioSamplesPerFrameAndChannel);
+ System.err.println("video: id "+vid+", fmt "+vW+"x"+vH+", "+vPixelFmt+", planes "+vPlanes+", bpp "+vBitsPerPixel+"/"+vBytesPerPixelPerPlane+", usesTexLookupShader "+usesTexLookupShader);
for(int i=0; i<3; i++) {
- System.err.println("XXX0 "+i+": "+vTexWidth[i]+"/"+vLinesize[i]);
+ System.err.println("video: p["+i+"]: "+vTexWidth[i]);
}
- System.err.println("XXX0 total tex "+texWidth+"x"+texHeight);
+ System.err.println("video: total tex "+texWidth+"x"+texHeight);
+ System.err.println(this.toString());
}
}
-
+
+ /**
+ * Native callback
+ * @param isInGLOrientation
+ * @param pixFmt
+ * @param planes
+ * @param bitsPerPixel
+ * @param bytesPerPixelPerPlane
+ * @param tWd0
+ * @param tWd1
+ * @param tWd2
+ */
+ void updateVidAttributes(final boolean isInGLOrientation, final int pixFmt, final int planes, final int bitsPerPixel, final int bytesPerPixelPerPlane,
+ final int tWd0, final int tWd1, final int tWd2, final int vW, final int vH) {
+ }
+
/**
* {@inheritDoc}
- *
+ *
* If this implementation generates a specialized shader,
* it allows the user to override the default function name <code>ffmpegTexture2D</code>.
* Otherwise the call is delegated to it's super class.
*/
@Override
- public String getTextureLookupFunctionName(String desiredFuncName) throws IllegalStateException {
- if(State.Uninitialized == state) {
+ public final String getTextureLookupFunctionName(final String desiredFuncName) throws IllegalStateException {
+ if( State.Uninitialized == getState() ) {
throw new IllegalStateException("Instance not initialized: "+this);
}
- if(PixelFormat.YUV420P == vPixelFmt) {
+ if( usesTexLookupShader ) {
if(null != desiredFuncName && desiredFuncName.length()>0) {
- textureLookupFunctionName = desiredFuncName;
+ texLookupFuncName = desiredFuncName;
}
- return textureLookupFunctionName;
+ return texLookupFuncName;
}
- return super.getTextureLookupFunctionName(desiredFuncName);
+ return super.getTextureLookupFunctionName(desiredFuncName);
}
- private String textureLookupFunctionName = "ffmpegTexture2D";
-
+
/**
* {@inheritDoc}
- *
+ *
* Depending on the pixelformat, a specific conversion shader is being created,
- * e.g. YUV420P to RGB. Otherwise the call is delegated to it's super class.
- */
+ * e.g. YUV420P to RGB. Otherwise the call is delegated to it's super class.
+ */
@Override
- public String getTextureLookupFragmentShaderImpl() throws IllegalStateException {
- if(State.Uninitialized == state) {
+ public final String getTextureLookupFragmentShaderImpl() throws IllegalStateException {
+ if( State.Uninitialized == getState() ) {
throw new IllegalStateException("Instance not initialized: "+this);
}
+ if( !usesTexLookupShader ) {
+ return super.getTextureLookupFragmentShaderImpl();
+ }
final float tc_w_1 = (float)getWidth() / (float)texWidth;
switch(vPixelFmt) {
- case YUV420P:
- return
- "vec4 "+textureLookupFunctionName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+
- " vec2 u_off = vec2("+tc_w_1+", 0.0);\n"+
- " vec2 v_off = vec2("+tc_w_1+", 0.5);\n"+
+ case YUVJ420P:
+ case YUV420P: // < planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
+ return
+ "vec4 "+texLookupFuncName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+
+ " const vec2 u_off = vec2("+tc_w_1+", 0.0);\n"+
+ " const vec2 v_off = vec2("+tc_w_1+", 0.5);\n"+
" vec2 tc_half = texCoord*0.5;\n"+
" float y,u,v,r,g,b;\n"+
- " y = texture2D(image, texCoord).a;\n"+
- " u = texture2D(image, u_off+tc_half).a;\n"+
- " v = texture2D(image, v_off+tc_half).a;\n"+
+ " y = texture2D(image, texCoord)."+singleTexComp+";\n"+
+ " u = texture2D(image, u_off+tc_half)."+singleTexComp+";\n"+
+ " v = texture2D(image, v_off+tc_half)."+singleTexComp+";\n"+
" y = 1.1643*(y-0.0625);\n"+
" u = u-0.5;\n"+
" v = v-0.5;\n"+
" r = y+1.5958*v;\n"+
" g = y-0.39173*u-0.81290*v;\n"+
- " b = y+2.017*u;\n"+
+ " b = y+2.017*u;\n"+
" return vec4(r, g, b, 1);\n"+
"}\n"
- ;
- default: // FIXME: Add more planar formats !
- return super.getTextureLookupFragmentShaderImpl();
- }
- }
-
- @Override
- protected synchronized int getCurrentPositionImpl() {
- return 0!=moviePtr ? getVideoPTS0(moviePtr) : 0;
- }
+ ;
- @Override
- protected synchronized boolean setPlaySpeedImpl(float rate) {
- return true;
+ case YUVJ422P:
+ case YUV422P: ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
+ return
+ "vec4 "+texLookupFuncName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+
+ " const vec2 u_off = vec2("+tc_w_1+" , 0.0);\n"+
+ " const vec2 v_off = vec2("+tc_w_1+" * 1.5, 0.0);\n"+
+ " vec2 tc_halfw = vec2(texCoord.x*0.5, texCoord.y);\n"+
+ " float y,u,v,r,g,b;\n"+
+ " y = texture2D(image, texCoord)."+singleTexComp+";\n"+
+ " u = texture2D(image, u_off+tc_halfw)."+singleTexComp+";\n"+
+ " v = texture2D(image, v_off+tc_halfw)."+singleTexComp+";\n"+
+ " y = 1.1643*(y-0.0625);\n"+
+ " u = u-0.5;\n"+
+ " v = v-0.5;\n"+
+ " r = y+1.5958*v;\n"+
+ " g = y-0.39173*u-0.81290*v;\n"+
+ " b = y+2.017*u;\n"+
+ " return vec4(r, g, b, 1);\n"+
+ "}\n"
+ ;
+
+ case YUYV422: // < packed YUV 4:2:2, 2 x 16bpp, [Y0 Cb] [Y1 Cr]
+ // Stuffed into RGBA half width texture
+ return
+ "vec4 "+texLookupFuncName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+
+ " "+
+ " float y1,u,y2,v,y,r,g,b;\n"+
+ " vec2 tc_halfw = vec2(texCoord.x*0.5, texCoord.y);\n"+
+ " vec4 yuyv = texture2D(image, tc_halfw).rgba;\n"+
+ " y1 = yuyv.r;\n"+
+ " u = yuyv.g;\n"+
+ " y2 = yuyv.b;\n"+
+ " v = yuyv.a;\n"+
+ " y = mix( y1, y2, mod(gl_FragCoord.x, 2) ); /* avoid branching! */\n"+
+ " y = 1.1643*(y-0.0625);\n"+
+ " u = u-0.5;\n"+
+ " v = v-0.5;\n"+
+ " r = y+1.5958*v;\n"+
+ " g = y-0.39173*u-0.81290*v;\n"+
+ " b = y+2.017*u;\n"+
+ " return vec4(r, g, b, 1);\n"+
+ "}\n"
+ ;
+ case BGR24:
+ return
+ "vec4 "+texLookupFuncName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+
+ " "+
+ " vec3 bgr = texture2D(image, texCoord).rgb;\n"+
+ " return vec4(bgr.b, bgr.g, bgr.r, 1);\n"+ /* just swizzle */
+ "}\n"
+ ;
+
+ default: // FIXME: Add more formats !
+ throw new InternalError("Add proper mapping of: vPixelFmt "+vPixelFmt+", usesTexLookupShader "+usesTexLookupShader);
+ }
}
@Override
- public synchronized boolean startImpl() {
+ public final boolean playImpl() {
if(0==moviePtr) {
return false;
}
+ final int errno = natives.play0(moviePtr);
+ if( DEBUG_NATIVE && errno != 0 && errno != -ENOSYS) {
+ System.err.println("libav play err: "+errno);
+ }
return true;
}
- /** @return time position after issuing the command */
@Override
- public synchronized boolean pauseImpl() {
+ public final boolean pauseImpl() {
if(0==moviePtr) {
return false;
}
+ final int errno = natives.pause0(moviePtr);
+ if( DEBUG_NATIVE && errno != 0 && errno != -ENOSYS) {
+ System.err.println("libav pause err: "+errno);
+ }
return true;
}
- /** @return time position after issuing the command */
@Override
- public synchronized boolean stopImpl() {
+ protected final synchronized int seekImpl(final int msec) {
if(0==moviePtr) {
- return false;
+ throw new GLException("FFMPEG native instance null");
}
- return true;
+ return natives.seek0(moviePtr, msec);
}
- /** @return time position after issuing the command */
@Override
- protected synchronized int seekImpl(int msec) {
- if(0==moviePtr) {
- throw new GLException("FFMPEG native instance null");
- }
- int pts0 = getVideoPTS0(moviePtr);
- int pts1 = seek0(moviePtr, msec);
- System.err.println("Seek: "+pts0+" -> "+msec+" : "+pts1);
- return pts1;
+ protected void preNextTextureImpl(final GL gl) {
+ psm.setUnpackAlignment(gl, 1); // RGBA ? 4 : 1
+ gl.glActiveTexture(GL.GL_TEXTURE0+getTextureUnit());
}
@Override
- protected TextureSequence.TextureFrame getLastTextureImpl() {
- return lastTex;
+ protected void postNextTextureImpl(final GL gl) {
+ psm.restore(gl);
}
-
- private long lastVideoTime = 0;
- private int lastVideoPTS = 0;
- private static final int dt_d = 9;
-
+
@Override
- protected TextureSequence.TextureFrame getNextTextureImpl(GL gl, boolean blocking) {
+ protected final int getNextTextureImpl(final GL gl, final TextureFrame nextFrame) {
if(0==moviePtr) {
throw new GLException("FFMPEG native instance null");
- }
- if(null != lastTex) {
- psm.setUnpackAlignment(gl, 1); // RGBA ? 4 : 1
- try {
- final Texture tex = lastTex.getTexture();
- gl.glActiveTexture(GL.GL_TEXTURE0+getTextureUnit());
- tex.enable(gl);
- tex.bind(gl);
- readNextPacket0(moviePtr, procAddrGLTexSubImage2D, textureTarget, textureFormat, textureType);
- } finally {
- psm.restore(gl);
- }
- final int pts = getVideoPTS0(moviePtr); // this frame
- if(blocking) {
- // poor mans video sync .. TODO: off thread 'readNextPackage0(..)' on shared GLContext and multi textures/unit!
- final long now = System.currentTimeMillis();
- final long now_d = now - lastVideoTime;
- final long pts_d = pts - lastVideoPTS;
- final long dt = (long) ( (float) ( pts_d - now_d ) / getPlaySpeed() ) ;
- lastVideoTime = now;
- // System.err.println("s: pts-v "+pts+", pts-d "+pts_d+", now_d "+now_d+", dt "+dt);
- if(dt>dt_d) {
- try {
- Thread.sleep(dt-dt_d);
- } catch (InterruptedException e) { }
- } /* else if(0>pts_d) {
- System.err.println("s: pts-v "+pts+", pts-d "+pts_d+", now_d "+now_d+", dt "+dt);
- } */
- }
- lastVideoPTS = pts;
}
- return lastTex;
- }
-
- private void consumeAudio(int len) {
-
+ int vPTS = TimeFrameI.INVALID_PTS;
+ if( null != gl ) {
+ final Texture tex = nextFrame.getTexture();
+ tex.enable(gl);
+ tex.bind(gl);
+ }
+
+ /** Try decode up to 10 packets to find one containing video. */
+ for(int i=0; TimeFrameI.INVALID_PTS == vPTS && 10 > i; i++) {
+ vPTS = natives.readNextPacket0(moviePtr, getTextureTarget(), getTextureFormat(), getTextureType());
+ }
+ if( null != nextFrame ) {
+ nextFrame.setPTS(vPTS);
+ }
+ return vPTS;
}
-
- private static native int getAvUtilVersion0();
- private static native int getAvFormatVersion0();
- private static native int getAvCodecVersion0();
- private static native boolean initIDs0();
- private native long createInstance0(boolean verbose);
- private native void destroyInstance0(long moviePtr);
-
- private native void setStream0(long moviePtr, String url, int vid, int aid);
-
- private native int getVideoPTS0(long moviePtr);
-
- private native int getAudioPTS0(long moviePtr);
- private native Buffer getAudioBuffer0(long moviePtr, int plane);
-
- private native int readNextPacket0(long moviePtr, long procAddrGLTexSubImage2D, int texTarget, int texFmt, int texType);
-
- private native int seek0(long moviePtr, int position);
-
- public static enum PixelFormat {
- // NONE= -1,
- YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
- YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
- RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB...
- BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR...
- YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
- YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
- YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
- YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
- GRAY8, ///< Y , 8bpp
- MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb
- MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb
- PAL8, ///< 8 bit with RGB32 palette
- YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of YUV420P and setting color_range
- YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of YUV422P and setting color_range
- YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of YUV444P and setting color_range
- XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing
- XVMC_MPEG2_IDCT,
- UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
- UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
- BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
- BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
- BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
- RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
- RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
- RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb)
- NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)
- NV21, ///< as above, but U and V bytes are swapped
-
- ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
- RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
- ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
- BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
-
- GRAY16BE, ///< Y , 16bpp, big-endian
- GRAY16LE, ///< Y , 16bpp, little-endian
- YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
- YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of YUV440P and setting color_range
- YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
- VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
- VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
- VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
- VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
- VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
- RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian
- RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian
-
- RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
- RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
- RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0
- RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0
-
- BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
- BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
- BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1
- BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1
-
- VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
- VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers
- VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
-
- YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
- YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
- YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
- YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
- YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
- YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
- VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
- DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
-
- RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0
- RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0
- BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1
- BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1
- Y400A, ///< 8bit gray, 8bit alpha
- BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian
- BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian
- YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
- YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
- YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
- YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
- YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
- YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
- YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
- YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
- YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
- YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
- YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
- YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
- VDA_VLD, ///< hardware decoding through VDA
- GBRP, ///< planar GBR 4:4:4 24bpp
- GBRP9BE, ///< planar GBR 4:4:4 27bpp, big endian
- GBRP9LE, ///< planar GBR 4:4:4 27bpp, little endian
- GBRP10BE, ///< planar GBR 4:4:4 30bpp, big endian
- GBRP10LE, ///< planar GBR 4:4:4 30bpp, little endian
- GBRP16BE, ///< planar GBR 4:4:4 48bpp, big endian
- GBRP16LE, ///< planar GBR 4:4:4 48bpp, little endian
- COUNT ///< number of pixel formats in this list
- ;
- public static PixelFormat valueOf(int i) {
- for (PixelFormat fmt : PixelFormat.values()) {
- if(fmt.ordinal() == i) {
- return fmt;
- }
- }
- return null;
+
+ final void pushSound(final ByteBuffer sampleData, final int data_size, final int audio_pts) {
+ setFirstAudioPTS2SCR( audio_pts );
+ if( 1.0f == getPlaySpeed() || audioSinkPlaySpeedSet ) {
+ audioSink.enqueueData( audio_pts, sampleData, data_size);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
new file mode 100644
index 000000000..8fd439082
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.av.impl;
+
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+/* pp */ abstract class FFMPEGNatives {
+
+ private static final Object mutex_avcodec_openclose_jni = new Object();
+
+ final boolean initSymbols0(final long[] symbols, final int count) {
+ return initSymbols0(mutex_avcodec_openclose_jni, symbols, count);
+ }
+ abstract boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
+ abstract int getAvUtilMajorVersionCC0();
+ abstract int getAvFormatMajorVersionCC0();
+ abstract int getAvCodecMajorVersionCC0();
+ abstract int getAvResampleMajorVersionCC0();
+ abstract int getSwResampleMajorVersionCC0();
+
+ abstract long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+ abstract void destroyInstance0(long moviePtr);
+
+ /**
+ * Issues {@link #updateAttributes(int, int, int, int, int, int, int, float, int, int, String, String)}
+ * and {@link #updateAttributes2(int, int, int, int, int, int, int, int, int, int)}.
+ *
+ * @param moviePtr
+ * @param url
+ * @param vid
+ * @param sizes requested video size as string, i.e. 'hd720'. May be null to favor vWidth and vHeight.
+ * @param vWidth requested video width (for camera mode)
+ * @param vHeight requested video width (for camera mode)
+ * @param vRate requested video framerate (for camera mode)
+ * @param aid
+ * @param aPrefSampleRate
+ * @param aPrefChannelCount
+ */
+ abstract void setStream0(long moviePtr, String url, boolean isCameraInput,
+ int vid, String sizes, int vWidth, int vHeight,
+ int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+
+ abstract void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+
+ abstract int getVideoPTS0(long moviePtr);
+
+ abstract int getAudioPTS0(long moviePtr);
+
+ /**
+ * @return resulting current video PTS, or {@link TextureFrame#INVALID_PTS}
+ */
+ abstract int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+
+ abstract int play0(long moviePtr);
+ abstract int pause0(long moviePtr);
+ abstract int seek0(long moviePtr, int position);
+} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java
new file mode 100644
index 000000000..65a7e3618
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.av.impl;
+
+import com.jogamp.common.util.VersionNumber;
+
+class FFMPEGStaticNatives {
+ static VersionNumber getAVVersion(final int vers) {
+ return new VersionNumber( ( vers >> 16 ) & 0xFF,
+ ( vers >> 8 ) & 0xFF,
+ ( vers >> 0 ) & 0xFF );
+ }
+ static native boolean initIDs0();
+
+ static native int getAvVersion0(long func);
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
new file mode 100644
index 000000000..6bab23f25
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.av.impl;
+
+class FFMPEGv08Natives extends FFMPEGNatives {
+ @Override
+ native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
+
+ @Override
+ native int getAvUtilMajorVersionCC0();
+
+ @Override
+ native int getAvFormatMajorVersionCC0();
+
+ @Override
+ native int getAvCodecMajorVersionCC0();
+
+ @Override
+ native int getAvResampleMajorVersionCC0();
+
+ @Override
+ native int getSwResampleMajorVersionCC0();
+
+ @Override
+ native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+
+ @Override
+ native void destroyInstance0(long moviePtr);
+
+ @Override
+ native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+
+ @Override
+ native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+
+ @Override
+ native int getVideoPTS0(long moviePtr);
+
+ @Override
+ native int getAudioPTS0(long moviePtr);
+
+ @Override
+ native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+
+ @Override
+ native int play0(long moviePtr);
+
+ @Override
+ native int pause0(long moviePtr);
+
+ @Override
+ native int seek0(long moviePtr, int position);
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
new file mode 100644
index 000000000..a48b5f21f
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.av.impl;
+
+class FFMPEGv09Natives extends FFMPEGNatives {
+ @Override
+ native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
+
+ @Override
+ native int getAvUtilMajorVersionCC0();
+
+ @Override
+ native int getAvFormatMajorVersionCC0();
+
+ @Override
+ native int getAvCodecMajorVersionCC0();
+
+ @Override
+ native int getAvResampleMajorVersionCC0();
+
+ @Override
+ native int getSwResampleMajorVersionCC0();
+
+ @Override
+ native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+
+ @Override
+ native void destroyInstance0(long moviePtr);
+
+ @Override
+ native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+
+ @Override
+ native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+
+ @Override
+ native int getVideoPTS0(long moviePtr);
+
+ @Override
+ native int getAudioPTS0(long moviePtr);
+
+ @Override
+ native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+
+ @Override
+ native int play0(long moviePtr);
+
+ @Override
+ native int pause0(long moviePtr);
+
+ @Override
+ native int seek0(long moviePtr, int position);
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java
new file mode 100644
index 000000000..f35fb29dc
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.av.impl;
+
+class FFMPEGv10Natives extends FFMPEGNatives {
+ @Override
+ native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
+
+ @Override
+ native int getAvUtilMajorVersionCC0();
+
+ @Override
+ native int getAvFormatMajorVersionCC0();
+
+ @Override
+ native int getAvCodecMajorVersionCC0();
+
+ @Override
+ native int getAvResampleMajorVersionCC0();
+
+ @Override
+ native int getSwResampleMajorVersionCC0();
+
+ @Override
+ native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+
+ @Override
+ native void destroyInstance0(long moviePtr);
+
+ @Override
+ native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+
+ @Override
+ native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+
+ @Override
+ native int getVideoPTS0(long moviePtr);
+
+ @Override
+ native int getAudioPTS0(long moviePtr);
+
+ @Override
+ native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+
+ @Override
+ native int play0(long moviePtr);
+
+ @Override
+ native int pause0(long moviePtr);
+
+ @Override
+ native int seek0(long moviePtr, int position);
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
index aef98fcde..5baf9e543 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -29,11 +29,9 @@
package jogamp.opengl.util.av.impl;
import java.io.IOException;
-import java.net.URL;
import javax.media.opengl.GL;
import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
import com.jogamp.opengl.util.texture.TextureSequence;
@@ -47,18 +45,18 @@ import jogamp.opengl.util.av.EGLMediaPlayerImpl;
*/
public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
static final boolean available;
-
+
static {
- // OMX binding is included in jogl_desktop and jogl_mobile
+ available = false;
+ /** FIXME!
+ // OMX binding is included in jogl_desktop and jogl_mobile
GLProfile.initSingleton();
- available = initIDs0();
+ available = initIDs0(); */
}
-
+
public static final boolean isAvailable() { return available; }
-
+
protected long moviePtr = 0;
-
- protected TextureSequence.TextureFrame lastTex = null;
public OMXGLMediaPlayer() {
super(TextureType.KHRImage, true);
@@ -72,56 +70,65 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
moviePtr = _createInstance();
if(0==moviePtr) {
throw new GLException("Couldn't create OMXInstance");
- }
+ }
}
-
+
@Override
- protected TextureSequence.TextureFrame createTexImage(GL gl, int idx, int[] tex) {
- final EGLTextureFrame eglTex = (EGLTextureFrame) super.createTexImage(gl, idx, tex);
- _setStreamEGLImageTexture2D(moviePtr, idx, tex[idx], eglTex.getImage(), eglTex.getSync());
- lastTex = eglTex;
+ protected TextureSequence.TextureFrame createTexImage(final GL gl, final int texName) {
+ final EGLTextureFrame eglTex = (EGLTextureFrame) super.createTexImage(gl, texName);
+ _setStreamEGLImageTexture2D(moviePtr, texName, eglTex.getImage(), eglTex.getSync());
return eglTex;
}
-
+
@Override
- protected void destroyTexImage(GL gl, TextureSequence.TextureFrame imgTex) {
- lastTex = null;
- super.destroyTexImage(gl, imgTex);
+ protected void destroyTexFrame(final GL gl, final TextureSequence.TextureFrame imgTex) {
+ super.destroyTexFrame(gl, imgTex);
}
-
+
@Override
- protected void destroyImpl(GL gl) {
- _detachVideoRenderer(moviePtr);
+ protected void destroyImpl(final GL gl) {
if (moviePtr != 0) {
+ _stop(moviePtr);
+ _detachVideoRenderer(moviePtr);
_destroyInstance(moviePtr);
moviePtr = 0;
}
}
-
+
@Override
- protected void initGLStreamImpl(GL gl, int[] texNames) throws IOException {
+ protected void initStreamImpl(final int vid, final int aid) throws IOException {
if(0==moviePtr) {
throw new GLException("OMX native instance null");
}
- final URL url = urlConn.getURL();
- if(!url.getProtocol().equals("file")) {
- throw new IOException("Only file URLs are allowed: "+url);
+ if( !getUri().isFileScheme() ) {
+ throw new IOException("Only file schemes are allowed: "+getUri());
+ }
+ final String path=getUri().path.decode();
+ if(DEBUG) {
+ System.out.println("initGLStream: clean path "+path);
+ }
+
+ if(DEBUG) {
+ System.out.println("initGLStream: p1 "+this);
+ }
+ _setStream(moviePtr, getTextureCount(), path);
+ if(DEBUG) {
+ System.out.println("initGLStream: p2 "+this);
}
- final String path=url.getPath();
- System.out.println("setURL: clean path "+path);
-
- System.out.println("setURL: p1 "+this);
- _setStream(moviePtr, textureCount, path);
- System.out.println("setURL: p2 "+this);
}
-
@Override
- protected int getCurrentPositionImpl() {
+ protected final void initGLImpl(final GL gl) throws IOException, GLException {
+ // NOP
+ setIsGLOriented(true);
+ }
+
+ @Override
+ protected int getAudioPTSImpl() {
return 0!=moviePtr ? _getCurrentPosition(moviePtr) : 0;
}
@Override
- protected boolean setPlaySpeedImpl(float rate) {
+ protected boolean setPlaySpeedImpl(final float rate) {
if(0==moviePtr) {
throw new GLException("OMX native instance null");
}
@@ -130,7 +137,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
}
@Override
- public synchronized boolean startImpl() {
+ public synchronized boolean playImpl() {
if(0==moviePtr) {
return false;
}
@@ -150,17 +157,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
/** @return time position after issuing the command */
@Override
- public synchronized boolean stopImpl() {
- if(0==moviePtr) {
- return false;
- }
- _stop(moviePtr);
- return true;
- }
-
- /** @return time position after issuing the command */
- @Override
- protected int seekImpl(int msec) {
+ protected int seekImpl(final int msec) {
if(0==moviePtr) {
throw new GLException("OMX native instance null");
}
@@ -168,39 +165,36 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
}
@Override
- protected TextureSequence.TextureFrame getLastTextureImpl() {
- return lastTex;
- }
-
- @Override
- protected TextureSequence.TextureFrame getNextTextureImpl(GL gl, boolean blocking) {
+ protected int getNextTextureImpl(final GL gl, final TextureFrame nextFrame) {
if(0==moviePtr) {
throw new GLException("OMX native instance null");
}
- final int nextTex = _getNextTextureID(moviePtr, blocking);
+ final int nextTex = _getNextTextureID(moviePtr, true);
if(0 < nextTex) {
- final TextureSequence.TextureFrame eglImgTex = texFrameMap.get(new Integer(_getNextTextureID(moviePtr, blocking)));
+ // FIXME set pts !
+ /* FIXME
+ final TextureSequence.TextureFrame eglImgTex =
+ texFrameMap.get(new Integer(_getNextTextureID(moviePtr, blocking)));
if(null!=eglImgTex) {
lastTex = eglImgTex;
- }
+ } */
}
- return lastTex;
+ return 0; // FIXME: return pts
}
-
- private String replaceAll(String orig, String search, String repl) {
- String dest=null;
+
+ private String replaceAll(final String orig, final String search, final String repl) {
+ final StringBuilder dest = new StringBuilder();
// In case replaceAll / java.util.regex.* is not supported (-> CVM)
int i=0,j;
- dest = new String();
while((j=orig.indexOf(search, i))>=0) {
- dest=dest.concat(orig.substring(i, j));
- dest=dest.concat(repl);
+ dest.append(orig.substring(i, j));
+ dest.append(repl);
i=j+1;
}
- return dest.concat(orig.substring(i, orig.length()));
+ return dest.append(orig.substring(i, orig.length())).toString();
}
- private void errorCheckEGL(String s) {
+ private void errorCheckEGL(final String s) {
int e;
if( (e=EGL.eglGetError()) != EGL.EGL_SUCCESS ) {
System.out.println("EGL Error: ("+s+"): 0x"+Integer.toHexString(e));
@@ -208,15 +202,15 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
}
private static native boolean initIDs0();
- private native long _createInstance();
+ private native long _createInstance();
private native void _destroyInstance(long moviePtr);
-
+
private native void _detachVideoRenderer(long moviePtr); // stop before
private native void _attachVideoRenderer(long moviePtr); // detach before
private native void _setStream(long moviePtr, int textureNum, String path);
private native void _activateStream(long moviePtr);
-
- private native void _setStreamEGLImageTexture2D(long moviePtr, int i, int tex, long image, long sync);
+
+ private native void _setStreamEGLImageTexture2D(long moviePtr, int tex, long image, long sync);
private native int _seek(long moviePtr, int position);
private native void _setPlaySpeed(long moviePtr, float rate);
private native void _play(long moviePtr);
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java
index 602d283d6..5a78f514d 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java
@@ -33,40 +33,49 @@ import java.nio.Buffer;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
-import jogamp.opengl.util.GLArrayHandler;
import jogamp.opengl.util.GLArrayHandlerFlat;
+import jogamp.opengl.util.GLVBOArrayHandler;
import com.jogamp.opengl.util.GLArrayDataEditable;
import com.jogamp.opengl.util.glsl.ShaderState;
/**
- * Used for 1:1 GLSL arrays, i.e. where the buffer data
- * represents this array only.
+ * Used for 1:1 GLSL arrays, i.e. where the buffer data
+ * represents this array only.
*/
-public class GLSLArrayHandler implements GLArrayHandler {
- private GLArrayDataEditable ad;
+public class GLSLArrayHandler extends GLVBOArrayHandler {
- public GLSLArrayHandler(GLArrayDataEditable ad) {
- this.ad = ad;
+ public GLSLArrayHandler(final GLArrayDataEditable ad) {
+ super(ad);
}
-
- public final void setSubArrayVBOName(int vboName) {
+
+ @Override
+ public final void setSubArrayVBOName(final int vboName) {
throw new UnsupportedOperationException();
}
-
- public final void addSubHandler(GLArrayHandlerFlat handler) {
+
+ @Override
+ public final void addSubHandler(final GLArrayHandlerFlat handler) {
throw new UnsupportedOperationException();
}
-
- public final void syncData(GL gl, boolean enable, Object ext) {
+
+ @Override
+ public final void enableState(final GL gl, final boolean enable, final Object ext) {
final GL2ES2 glsl = gl.getGL2ES2();
- final ShaderState st = (ShaderState) ext;
-
+ if( null != ext ) {
+ enableShaderState(glsl, enable, (ShaderState)ext);
+ } else {
+ enableSimple(glsl, enable);
+ }
+ }
+
+ private final int[] tempI = new int[1];
+
+ private final void enableShaderState(final GL2ES2 glsl, final boolean enable, final ShaderState st) {
if(enable) {
- final Buffer buffer = ad.getBuffer();
/*
* This would be the non optimized code path:
- *
+ *
if(ad.isVBO()) {
glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
if(!ad.isVBOWritten()) {
@@ -78,6 +87,7 @@ public class GLSLArrayHandler implements GLArrayHandler {
}
st.vertexAttribPointer(glsl, ad);
*/
+ final Buffer buffer = ad.getBuffer();
if(ad.isVBO()) {
// bind and refresh the VBO / vertex-attr only if necessary
if(!ad.isVBOWritten()) {
@@ -87,34 +97,76 @@ public class GLSLArrayHandler implements GLArrayHandler {
}
ad.setVBOWritten(true);
st.vertexAttribPointer(glsl, ad);
+ glsl.glBindBuffer(ad.getVBOTarget(), 0);
} else if(st.getAttribLocation(glsl, ad) >= 0) {
// didn't experience a performance hit on this query ..
// (using ShaderState's location query above to validate the location)
- final int[] qi = new int[1];
- glsl.glGetVertexAttribiv(ad.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0);
- if(ad.getVBOName() != qi[0]) {
+ glsl.glGetVertexAttribiv(ad.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, tempI, 0);
+ if(ad.getVBOName() != tempI[0]) {
glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
st.vertexAttribPointer(glsl, ad);
+ glsl.glBindBuffer(ad.getVBOTarget(), 0);
}
}
} else if(null!=buffer) {
st.vertexAttribPointer(glsl, ad);
}
- } else if(ad.isVBO()) {
- glsl.glBindBuffer(ad.getVBOTarget(), 0);
- }
- }
-
- public final void enableState(GL gl, boolean enable, Object ext) {
- final GL2ES2 glsl = gl.getGL2ES2();
- final ShaderState st = (ShaderState) ext;
-
- if(enable) {
+
st.enableVertexAttribArray(glsl, ad);
} else {
st.disableVertexAttribArray(glsl, ad);
}
}
+ private final void enableSimple(final GL2ES2 glsl, final boolean enable) {
+ final int location = ad.getLocation();
+ if( 0 > location ) {
+ return;
+ }
+ if(enable) {
+ /*
+ * This would be the non optimized code path:
+ *
+ if(ad.isVBO()) {
+ glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
+ if(!ad.isVBOWritten()) {
+ if(null!=buffer) {
+ glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage());
+ }
+ ad.setVBOWritten(true);
+ }
+ }
+ st.vertexAttribPointer(glsl, ad);
+ */
+ final Buffer buffer = ad.getBuffer();
+ if(ad.isVBO()) {
+ // bind and refresh the VBO / vertex-attr only if necessary
+ if(!ad.isVBOWritten()) {
+ glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
+ if(null!=buffer) {
+ glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage());
+ }
+ ad.setVBOWritten(true);
+ glsl.glVertexAttribPointer(ad);
+ glsl.glBindBuffer(ad.getVBOTarget(), 0);
+ } else {
+ // didn't experience a performance hit on this query ..
+ // (using ShaderState's location query above to validate the location)
+ glsl.glGetVertexAttribiv(location, GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, tempI, 0);
+ if(ad.getVBOName() != tempI[0]) {
+ glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
+ glsl.glVertexAttribPointer(ad);
+ glsl.glBindBuffer(ad.getVBOTarget(), 0);
+ }
+ }
+ } else if(null!=buffer) {
+ glsl.glVertexAttribPointer(ad);
+ }
+
+ glsl.glEnableVertexAttribArray(location);
+ } else {
+ glsl.glDisableVertexAttribArray(location);
+ }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java
index c4b761b13..85fcabdd9 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java
@@ -37,53 +37,67 @@ import com.jogamp.opengl.util.GLArrayDataWrapper;
import com.jogamp.opengl.util.glsl.ShaderState;
/**
- * Used for interleaved GLSL arrays, i.e. where the buffer data itself is handled
+ * Used for interleaved GLSL arrays, i.e. where the buffer data itself is handled
* separately and interleaves many arrays.
*/
public class GLSLArrayHandlerFlat implements GLArrayHandlerFlat {
- private GLArrayDataWrapper ad;
+ private final GLArrayDataWrapper ad;
- public GLSLArrayHandlerFlat(GLArrayDataWrapper ad) {
+ public GLSLArrayHandlerFlat(final GLArrayDataWrapper ad) {
this.ad = ad;
}
+ @Override
public GLArrayDataWrapper getData() {
return ad;
}
-
- public final void syncData(GL gl, boolean enable, boolean force, Object ext) {
- if(enable) {
- final GL2ES2 glsl = gl.getGL2ES2();
- final ShaderState st = (ShaderState) ext;
+ @Override
+ public final void syncData(final GL gl, final Object ext) {
+ final GL2ES2 glsl = gl.getGL2ES2();
+ if( null != ext ) {
+ ((ShaderState)ext).vertexAttribPointer(glsl, ad);
+ } else {
+ if( 0 <= ad.getLocation() ) {
+ glsl.glVertexAttribPointer(ad);
+ }
+ }
+ /**
+ * Due to probable application VBO switching, this might not make any sense ..
+ *
+ if(!written) {
st.vertexAttribPointer(glsl, ad);
- /**
- * Due to probable application VBO switching, this might not make any sense ..
- *
- if(force) {
+ } else if(st.getAttribLocation(glsl, ad) >= 0) {
+ final int[] qi = new int[1];
+ glsl.glGetVertexAttribiv(ad.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0);
+ if(ad.getVBOName() != qi[0]) {
+ System.err.println("XXX1: "+ad.getName()+", vbo ad "+ad.getVBOName()+", gl "+qi[0]+", "+ad);
st.vertexAttribPointer(glsl, ad);
- } else if(st.getAttribLocation(glsl, ad) >= 0) {
- final int[] qi = new int[1];
- glsl.glGetVertexAttribiv(ad.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0);
- if(ad.getVBOName() != qi[0]) {
- System.err.println("XXX1: "+ad.getName()+", vbo ad "+ad.getVBOName()+", gl "+qi[0]+", "+ad);
- st.vertexAttribPointer(glsl, ad);
- } else {
- System.err.println("XXX0: "+ad.getName()+", vbo ad "+ad.getVBOName()+", gl "+qi[0]+", "+ad);
- }
- }*/
- }
+ } else {
+ System.err.println("XXX0: "+ad.getName()+", vbo ad "+ad.getVBOName()+", gl "+qi[0]+", "+ad);
+ }
+ }*/
}
- public final void enableState(GL gl, boolean enable, Object ext) {
+ @Override
+ public final void enableState(final GL gl, final boolean enable, final Object ext) {
final GL2ES2 glsl = gl.getGL2ES2();
- final ShaderState st = (ShaderState) ext;
-
- if(enable) {
- st.enableVertexAttribArray(glsl, ad);
+ if( null != ext ) {
+ final ShaderState st = (ShaderState)ext;
+ if(enable) {
+ st.enableVertexAttribArray(glsl, ad);
+ } else {
+ st.disableVertexAttribArray(glsl, ad);
+ }
} else {
- st.disableVertexAttribArray(glsl, ad);
+ final int location = ad.getLocation();
+ if( 0 <= location ) {
+ if(enable) {
+ glsl.glEnableVertexAttribArray(location);
+ } else {
+ glsl.glDisableVertexAttribArray(location);
+ }
+ }
}
- }
+ }
}
-
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java
index f50429623..0169b0747 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java
@@ -28,75 +28,59 @@
package jogamp.opengl.util.glsl;
-import java.nio.Buffer;
import java.util.ArrayList;
import java.util.List;
import javax.media.opengl.GL;
-import jogamp.opengl.util.GLArrayHandler;
import jogamp.opengl.util.GLArrayHandlerFlat;
+import jogamp.opengl.util.GLVBOArrayHandler;
import com.jogamp.opengl.util.GLArrayDataEditable;
/**
- * Interleaved fixed function arrays, i.e. where this buffer data
- * represents many arrays.
+ * Interleaved fixed function arrays, i.e. where this buffer data
+ * represents many arrays.
*/
-public class GLSLArrayHandlerInterleaved implements GLArrayHandler {
- private GLArrayDataEditable ad;
- private List<GLArrayHandlerFlat> subArrays = new ArrayList<GLArrayHandlerFlat>();
+public class GLSLArrayHandlerInterleaved extends GLVBOArrayHandler {
+ private final List<GLArrayHandlerFlat> subArrays = new ArrayList<GLArrayHandlerFlat>();
- public GLSLArrayHandlerInterleaved(GLArrayDataEditable ad) {
- this.ad = ad;
+ public GLSLArrayHandlerInterleaved(final GLArrayDataEditable ad) {
+ super(ad);
}
-
- public final void setSubArrayVBOName(int vboName) {
+
+ @Override
+ public final void setSubArrayVBOName(final int vboName) {
for(int i=0; i<subArrays.size(); i++) {
subArrays.get(i).getData().setVBOName(vboName);
- }
+ }
}
-
- public final void addSubHandler(GLArrayHandlerFlat handler) {
+
+ @Override
+ public final void addSubHandler(final GLArrayHandlerFlat handler) {
subArrays.add(handler);
}
- private final void syncSubData(GL gl, boolean enable, boolean force, Object ext) {
+ private final void syncSubData(final GL gl, final Object ext) {
for(int i=0; i<subArrays.size(); i++) {
- subArrays.get(i).syncData(gl, enable, force, ext);
- }
- }
-
- public final void syncData(GL gl, boolean enable, Object ext) {
- if(!ad.isVBO()) {
- throw new InternalError("Interleaved handle is not VBO: "+ad);
- }
-
+ subArrays.get(i).syncData(gl, ext);
+ }
+ }
+
+ @Override
+ public final void enableState(final GL gl, final boolean enable, final Object ext) {
if(enable) {
- final Buffer buffer = ad.getBuffer();
- final boolean vboWritten = ad.isVBOWritten();
-
- // always bind and refresh the VBO mgr,
- // in case more than one gl*Pointer objects are in use
- gl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
- if(!vboWritten) {
- if(null!=buffer) {
- gl.glBufferData(ad.getVBOTarget(), buffer.limit() * ad.getComponentSizeInBytes(), buffer, ad.getVBOUsage());
- }
- ad.setVBOWritten(true);
+ if(!ad.isVBO()) {
+ throw new InternalError("Interleaved handle is not VBO: "+ad);
}
- // sub data will decide weather to update the vertex attrib pointer
- syncSubData(gl, true, !vboWritten, ext);
- } else {
- // NOP on GLSL: syncSubData(gl, false, ext);
- gl.glBindBuffer(ad.getVBOTarget(), 0);
+ bindBuffer(gl, true);
+ // sub data will decide whether to update the vertex attrib pointer
+ syncSubData(gl, ext);
+ bindBuffer(gl, false);
}
- }
-
- public final void enableState(GL gl, boolean enable, Object ext) {
for(int i=0; i<subArrays.size(); i++) {
subArrays.get(i).enableState(gl, enable, ext);
- }
+ }
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
new file mode 100644
index 000000000..d5d0020c5
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
@@ -0,0 +1,192 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.opengl.util.glsl;
+
+import java.nio.FloatBuffer;
+
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLArrayData;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+public class GLSLTextureRaster {
+ private final boolean textureVertFlipped;
+ private final int textureUnit;
+
+ private ShaderProgram sp;
+ private PMVMatrix pmvMatrix;
+ private GLUniformData pmvMatrixUniform;
+ private GLUniformData activeTexUniform;
+ private GLArrayDataServer interleavedVBO;
+
+ public GLSLTextureRaster(final int textureUnit, final boolean textureVertFlipped) {
+ this.textureVertFlipped = textureVertFlipped;
+ this.textureUnit = textureUnit;
+ }
+
+ public int getTextureUnit() { return textureUnit; }
+
+ static final String shaderBasename = "texture01_xxx";
+ static final String shaderSrcPath = "../../shader";
+ static final String shaderBinPath = "../../shader/bin";
+
+ public void init(final GL2ES2 gl) {
+ // Create & Compile the shader objects
+ final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
+ shaderSrcPath, shaderBinPath, shaderBasename, true);
+ final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
+ shaderSrcPath, shaderBinPath, shaderBasename, true);
+ rsVp.defaultShaderCustomization(gl, true, true);
+ rsFp.defaultShaderCustomization(gl, true, true);
+
+ // Create & Link the shader program
+ sp = new ShaderProgram();
+ sp.add(rsVp);
+ sp.add(rsFp);
+ if(!sp.link(gl, System.err)) {
+ throw new GLException("Couldn't link program: "+sp);
+ }
+ sp.useProgram(gl, true);
+
+ // setup mgl_PMVMatrix
+ pmvMatrix = new PMVMatrix();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
+ if( pmvMatrixUniform.setLocation(gl, sp.program()) < 0 ) {
+ throw new GLException("Couldn't locate "+pmvMatrixUniform+" in shader: "+sp);
+ }
+ gl.glUniform(pmvMatrixUniform);
+
+ activeTexUniform = new GLUniformData("mgl_Texture0", textureUnit);
+ if( activeTexUniform.setLocation(gl, sp.program()) < 0 ) {
+ throw new GLException("Couldn't locate "+activeTexUniform+" in shader: "+sp);
+ }
+ gl.glUniform(activeTexUniform);
+
+ final float[] s_quadTexCoords;
+ if( textureVertFlipped ) {
+ s_quadTexCoords = s_quadTexCoords01;
+ } else {
+ s_quadTexCoords = s_quadTexCoords00;
+ }
+
+ interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+2, GL.GL_FLOAT, false, 2*4, GL.GL_STATIC_DRAW);
+ {
+ final GLArrayData vArrayData = interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ if( vArrayData.setLocation(gl, sp.program()) < 0 ) {
+ throw new GLException("Couldn't locate "+vArrayData+" in shader: "+sp);
+ }
+ final GLArrayData tArrayData = interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
+ if( tArrayData.setLocation(gl, sp.program()) < 0 ) {
+ throw new GLException("Couldn't locate "+tArrayData+" in shader: "+sp);
+ }
+ final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
+ for(int i=0; i<4; i++) {
+ ib.put(s_quadVertices, i*3, 3);
+ ib.put(s_quadTexCoords, i*2, 2);
+ }
+ }
+ interleavedVBO.seal(gl, true);
+ interleavedVBO.enableBuffer(gl, false);
+
+ sp.useProgram(gl, false);
+ }
+
+ public void reshape(final GL2ES2 gl, final int x, final int y, final int width, final int height) {
+ if(null != sp) {
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+
+ sp.useProgram(gl, true);
+ gl.glUniform(pmvMatrixUniform);
+ sp.useProgram(gl, false);
+ }
+ }
+
+ public void dispose(final GL2ES2 gl) {
+ if(null != pmvMatrixUniform) {
+ pmvMatrixUniform = null;
+ }
+ pmvMatrix=null;
+ if(null != interleavedVBO) {
+ interleavedVBO.destroy(gl);
+ interleavedVBO=null;
+ }
+ if(null != sp) {
+ sp.destroy(gl);
+ sp=null;
+ }
+ }
+
+ public void display(final GL2ES2 gl) {
+ if(null != sp) {
+ sp.useProgram(gl, true);
+ interleavedVBO.enableBuffer(gl, true);
+
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+
+ interleavedVBO.enableBuffer(gl, false);
+ sp.useProgram(gl, false);
+ }
+ }
+
+ private static final float[] s_quadVertices = {
+ -1f, -1f, 0f, // LB
+ 1f, -1f, 0f, // RB
+ -1f, 1f, 0f, // LT
+ 1f, 1f, 0f // RT
+ };
+ private static final float[] s_quadTexCoords00 = {
+ 0f, 0f, // LB
+ 1f, 0f, // RB
+ 0f, 1f, // LT
+ 1f, 1f // RT
+ };
+ private static final float[] s_quadTexCoords01 = {
+ 0f, 1f, // LB
+ 1f, 1f, // RB
+ 0f, 0f, // LT
+ 1f, 0f // RT
+ };
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
index 897967f8b..2dde27b1d 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
@@ -29,109 +29,159 @@
package jogamp.opengl.util.glsl.fixedfunc;
-import javax.media.opengl.*;
-import javax.media.opengl.fixedfunc.*;
-import com.jogamp.common.nio.Buffers;
-import com.jogamp.opengl.util.*;
+import java.nio.Buffer;
+import java.nio.IntBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLArrayData;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
-import java.nio.*;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.ValueConv;
+import com.jogamp.opengl.util.GLArrayDataWrapper;
+import com.jogamp.opengl.util.GLBuffers;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode;
public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFunc {
public static final int MAX_TEXTURE_UNITS = 8;
- protected FixedFuncPipeline fixedFunction=null;
- protected PMVMatrix pmvMatrix=null;
- protected GL2ES2 gl=null;
+ protected final GLProfile gl2es1GLProfile;
+ protected FixedFuncPipeline fixedFunction;
+ protected PMVMatrix pmvMatrix;
+ protected boolean ownsPMVMatrix;
+ protected GL2ES2 gl;
- public FixedFuncHook (GL2ES2 gl) {
- this(gl, null);
+ /**
+ * @param gl
+ * @param mode TODO
+ * @param pmvMatrix optional pass through PMVMatrix for the {@link FixedFuncHook} and {@link FixedFuncPipeline}
+ */
+ public FixedFuncHook (final GL2ES2 gl, final ShaderSelectionMode mode, final PMVMatrix pmvMatrix) {
+ this.gl2es1GLProfile = GLProfile.createCustomGLProfile(GLProfile.GL2ES1, gl.getGLProfile().getImpl());
+ this.gl = gl;
+ if(null != pmvMatrix) {
+ this.ownsPMVMatrix = false;
+ this.pmvMatrix = pmvMatrix;
+ } else {
+ this.ownsPMVMatrix = true;
+ this.pmvMatrix = new PMVMatrix();
+ }
+ fixedFunction = new FixedFuncPipeline(this.gl, mode, this.pmvMatrix);
}
- public FixedFuncHook (GL2ES2 gl, PMVMatrix matrix) {
+ /**
+ * @param gl
+ * @param mode TODO
+ * @param pmvMatrix optional pass through PMVMatrix for the {@link FixedFuncHook} and {@link FixedFuncPipeline}
+ */
+ public FixedFuncHook(final GL2ES2 gl, final ShaderSelectionMode mode, final PMVMatrix pmvMatrix,
+ final Class<?> shaderRootClass, final String shaderSrcRoot, final String shaderBinRoot,
+ final String vertexColorFile, final String vertexColorLightFile,
+ final String fragmentColorFile, final String fragmentColorTextureFile) {
+ this.gl2es1GLProfile = GLProfile.createCustomGLProfile(GLProfile.GL2ES1, gl.getGLProfile().getImpl());
this.gl = gl;
- pmvMatrix = (null!=matrix)?matrix:new PMVMatrix();
+ if(null != pmvMatrix) {
+ this.ownsPMVMatrix = false;
+ this.pmvMatrix = pmvMatrix;
+ } else {
+ this.ownsPMVMatrix = true;
+ this.pmvMatrix = new PMVMatrix();
+ }
- fixedFunction = new FixedFuncPipeline(gl, pmvMatrix);
+ fixedFunction = new FixedFuncPipeline(this.gl, mode, this.pmvMatrix, shaderRootClass, shaderSrcRoot,
+ shaderBinRoot, vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile);
}
- public FixedFuncHook(GL2ES2 gl, PMVMatrix matrix,
- Class<?> shaderRootClass, String shaderSrcRoot, String shaderBinRoot,
- String vertexColorFile,
- String vertexColorLightFile,
- String fragmentColorFile,
- String fragmentColorTextureFile) {
- this.gl = gl;
- pmvMatrix = matrix;
+ public boolean verbose() { return fixedFunction.verbose(); }
- fixedFunction = new FixedFuncPipeline(gl, pmvMatrix,
- shaderRootClass, shaderSrcRoot, shaderBinRoot,
- vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile);
- }
+ public void setVerbose(final boolean v) { fixedFunction.setVerbose(v); }
public void destroy() {
fixedFunction.destroy(gl);
fixedFunction = null;
+ pmvMatrix=null;
+ gl=null;
}
public PMVMatrix getMatrix() { return pmvMatrix; }
//
- // FixedFuncHookIf - hooks
+ // FixedFuncHookIf - hooks
//
- public void glDrawArrays(int mode, int first, int count) {
- fixedFunction.validate(gl);
- gl.glDrawArrays(mode, first, count);
+ public final boolean isGL4core() {
+ return false;
+ }
+ public final boolean isGL3core() {
+ return false;
+ }
+ public final boolean isGLcore() {
+ return false;
+ }
+ public final boolean isGLES2Compatible() {
+ return false;
}
- public void glDrawElements(int mode, int count, int type, java.nio.Buffer indices) {
- fixedFunction.validate(gl);
- gl.glDrawElements(mode, count, type, indices);
+ public final boolean isGLES3Compatible() {
+ return false;
}
- public void glDrawElements(int mode, int count, int type, long indices_buffer_offset) {
- fixedFunction.validate(gl);
- gl.glDrawElements(mode, count, type, indices_buffer_offset);
+ public final GLProfile getGLProfile() {
+ return gl2es1GLProfile;
+ }
+ public void glDrawArrays(final int mode, final int first, final int count) {
+ fixedFunction.glDrawArrays(gl, mode, first, count);
+ }
+ public void glDrawElements(final int mode, final int count, final int type, final java.nio.Buffer indices) {
+ fixedFunction.glDrawElements(gl, mode, count, type, indices);
+ }
+ public void glDrawElements(final int mode, final int count, final int type, final long indices_buffer_offset) {
+ fixedFunction.glDrawElements(gl, mode, count, type, indices_buffer_offset);
}
- public void glActiveTexture(int texture) {
- fixedFunction.glActiveTexture(gl, texture);
+ public void glActiveTexture(final int texture) {
+ fixedFunction.glActiveTexture(texture);
gl.glActiveTexture(texture);
}
- public void glEnable(int cap) {
- if(fixedFunction.glEnable(gl, cap, true)) {
+ public void glEnable(final int cap) {
+ if(fixedFunction.glEnable(cap, true)) {
gl.glEnable(cap);
}
}
- public void glDisable(int cap) {
- if(fixedFunction.glEnable(gl, cap, false)) {
+ public void glDisable(final int cap) {
+ if(fixedFunction.glEnable(cap, false)) {
gl.glDisable(cap);
}
}
- public void glCullFace(int faceName) {
- fixedFunction.glCullFace(gl, faceName);
- gl.glCullFace(faceName);
- }
-
- public void glGetFloatv(int pname, java.nio.FloatBuffer params) {
+ @Override
+ public void glGetFloatv(final int pname, final java.nio.FloatBuffer params) {
if(PMVMatrix.isMatrixGetName(pname)) {
pmvMatrix.glGetFloatv(pname, params);
return;
}
gl.glGetFloatv(pname, params);
}
- public void glGetFloatv(int pname, float[] params, int params_offset) {
+ @Override
+ public void glGetFloatv(final int pname, final float[] params, final int params_offset) {
if(PMVMatrix.isMatrixGetName(pname)) {
pmvMatrix.glGetFloatv(pname, params, params_offset);
return;
}
gl.glGetFloatv(pname, params, params_offset);
}
- public void glGetIntegerv(int pname, IntBuffer params) {
+ @Override
+ public void glGetIntegerv(final int pname, final IntBuffer params) {
if(PMVMatrix.isMatrixGetName(pname)) {
pmvMatrix.glGetIntegerv(pname, params);
return;
}
gl.glGetIntegerv(pname, params);
}
- public void glGetIntegerv(int pname, int[] params, int params_offset) {
+ @Override
+ public void glGetIntegerv(final int pname, final int[] params, final int params_offset) {
if(PMVMatrix.isMatrixGetName(pname)) {
pmvMatrix.glGetIntegerv(pname, params, params_offset);
return;
@@ -139,95 +189,193 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
gl.glGetIntegerv(pname, params, params_offset);
}
- //
+ public void glTexEnvi(final int target, final int pname, final int value) {
+ fixedFunction.glTexEnvi(target, pname, value);
+ }
+ public void glGetTexEnviv(final int target, final int pname, final IntBuffer params) {
+ fixedFunction.glGetTexEnviv(target, pname, params);
+ }
+ public void glGetTexEnviv(final int target, final int pname, final int[] params, final int params_offset) {
+ fixedFunction.glGetTexEnviv(target, pname, params, params_offset);
+ }
+ public void glBindTexture(final int target, final int texture) {
+ fixedFunction.glBindTexture(target, texture);
+ gl.glBindTexture(target, texture);
+ }
+ public void glTexImage2D(final int target, final int level, int internalformat, final int width, final int height, final int border,
+ final int format, final int type, final Buffer pixels) {
+ // align internalformat w/ format, an ES2 requirement
+ switch(internalformat) {
+ case 3: internalformat= ( GL.GL_RGBA == format ) ? GL.GL_RGBA : GL.GL_RGB; break;
+ case 4: internalformat= ( GL.GL_RGB == format ) ? GL.GL_RGB : GL.GL_RGBA; break;
+ }
+ fixedFunction.glTexImage2D(target, /* level, */ internalformat, /*width, height, border, */ format /*, type, pixels*/);
+ gl.glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+ }
+ public void glTexImage2D(final int target, final int level, int internalformat, final int width, final int height, final int border,
+ final int format, final int type, final long pixels_buffer_offset) {
+ // align internalformat w/ format, an ES2 requirement
+ switch(internalformat) {
+ case 3: internalformat= ( GL.GL_RGBA == format ) ? GL.GL_RGBA : GL.GL_RGB; break;
+ case 4: internalformat= ( GL.GL_RGB == format ) ? GL.GL_RGB : GL.GL_RGBA; break;
+ }
+ fixedFunction.glTexImage2D(target, /* level, */ internalformat, /*width, height, border, */ format /*, type, pixels*/);
+ gl.glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels_buffer_offset);
+ }
+
+ public void glPointSize(final float size) {
+ fixedFunction.glPointSize(size);
+ }
+ public void glPointParameterf(final int pname, final float param) {
+ fixedFunction.glPointParameterf(pname, param);
+ }
+ public void glPointParameterfv(final int pname, final float[] params, final int params_offset) {
+ fixedFunction.glPointParameterfv(pname, params, params_offset);
+ }
+ public void glPointParameterfv(final int pname, final java.nio.FloatBuffer params) {
+ fixedFunction.glPointParameterfv(pname, params);
+ }
+
+ //
// MatrixIf
//
public int glGetMatrixMode() {
return pmvMatrix.glGetMatrixMode();
}
- public void glMatrixMode(int mode) {
+ @Override
+ public void glMatrixMode(final int mode) {
pmvMatrix.glMatrixMode(mode);
}
- public void glLoadMatrixf(java.nio.FloatBuffer m) {
+ @Override
+ public void glLoadMatrixf(final java.nio.FloatBuffer m) {
pmvMatrix.glLoadMatrixf(m);
}
- public void glLoadMatrixf(float[] m, int m_offset) {
- glLoadMatrixf(GLBuffers.newDirectFloatBuffer(m, m_offset));
+ @Override
+ public void glLoadMatrixf(final float[] m, final int m_offset) {
+ glLoadMatrixf(Buffers.newDirectFloatBuffer(m, m_offset));
}
+ @Override
public void glPopMatrix() {
pmvMatrix.glPopMatrix();
}
+ @Override
public void glPushMatrix() {
pmvMatrix.glPushMatrix();
}
+ @Override
public void glLoadIdentity() {
pmvMatrix.glLoadIdentity();
}
- public void glMultMatrixf(java.nio.FloatBuffer m) {
+ @Override
+ public void glMultMatrixf(final java.nio.FloatBuffer m) {
pmvMatrix.glMultMatrixf(m);
}
- public void glMultMatrixf(float[] m, int m_offset) {
- glMultMatrixf(GLBuffers.newDirectFloatBuffer(m, m_offset));
+ @Override
+ public void glMultMatrixf(final float[] m, final int m_offset) {
+ glMultMatrixf(Buffers.newDirectFloatBuffer(m, m_offset));
}
- public void glTranslatef(float x, float y, float z) {
+ @Override
+ public void glTranslatef(final float x, final float y, final float z) {
pmvMatrix.glTranslatef(x, y, z);
}
- public void glRotatef(float angdeg, float x, float y, float z) {
+ @Override
+ public void glRotatef(final float angdeg, final float x, final float y, final float z) {
pmvMatrix.glRotatef(angdeg, x, y, z);
}
- public void glScalef(float x, float y, float z) {
+ @Override
+ public void glScalef(final float x, final float y, final float z) {
pmvMatrix.glScalef(x, y, z);
}
- public void glOrthof(float left, float right, float bottom, float top, float zNear, float zFar) {
+ public void glOrtho(final double left, final double right, final double bottom, final double top, final double near_val, final double far_val) {
+ glOrthof((float) left, (float) right, (float) bottom, (float) top, (float) near_val, (float) far_val);
+ }
+ @Override
+ public void glOrthof(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) {
pmvMatrix.glOrthof(left, right, bottom, top, zNear, zFar);
}
- public void glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar) {
+ public void glFrustum(final double left, final double right, final double bottom, final double top, final double zNear, final double zFar) {
+ glFrustumf((float) left, (float) right, (float) bottom, (float) top, (float) zNear, (float) zFar);
+ }
+ @Override
+ public void glFrustumf(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) {
pmvMatrix.glFrustumf(left, right, bottom, top, zNear, zFar);
}
- //
+ //
// LightingIf
//
- public void glColor4f(float red, float green, float blue, float alpha) {
- fixedFunction.glColor4fv(gl, GLBuffers.newDirectFloatBuffer(new float[] { red, green, blue, alpha }));
+ @Override
+ public void glColor4f(final float red, final float green, final float blue, final float alpha) {
+ fixedFunction.glColor4f(gl, red, green, blue, alpha);
}
- public void glLightfv(int light, int pname, java.nio.FloatBuffer params) {
+ public void glColor4ub(final byte red, final byte green, final byte blue, final byte alpha) {
+ glColor4f(ValueConv.byte_to_float(red, false),
+ ValueConv.byte_to_float(green, false),
+ ValueConv.byte_to_float(blue, false),
+ ValueConv.byte_to_float(alpha, false) );
+ }
+ @Override
+ public void glLightfv(final int light, final int pname, final java.nio.FloatBuffer params) {
fixedFunction.glLightfv(gl, light, pname, params);
}
- public void glLightfv(int light, int pname, float[] params, int params_offset) {
- glLightfv(light, pname, GLBuffers.newDirectFloatBuffer(params, params_offset));
+ @Override
+ public void glLightfv(final int light, final int pname, final float[] params, final int params_offset) {
+ glLightfv(light, pname, Buffers.newDirectFloatBuffer(params, params_offset));
}
- public void glMaterialfv(int face, int pname, java.nio.FloatBuffer params) {
+ @Override
+ public void glMaterialfv(final int face, final int pname, final java.nio.FloatBuffer params) {
fixedFunction.glMaterialfv(gl, face, pname, params);
}
- public void glMaterialfv(int face, int pname, float[] params, int params_offset) {
- glMaterialfv(face, pname, GLBuffers.newDirectFloatBuffer(params, params_offset));
+ @Override
+ public void glMaterialfv(final int face, final int pname, final float[] params, final int params_offset) {
+ glMaterialfv(face, pname, Buffers.newDirectFloatBuffer(params, params_offset));
}
- public void glMaterialf(int face, int pname, float param) {
- glMaterialfv(face, pname, GLBuffers.newDirectFloatBuffer(new float[] { param }));
+ @Override
+ public void glMaterialf(final int face, final int pname, final float param) {
+ glMaterialfv(face, pname, Buffers.newDirectFloatBuffer(new float[] { param }));
}
- public void glShadeModel(int mode) {
+
+ //
+ // Misc Simple States
+ //
+ @Override
+ public void glShadeModel(final int mode) {
fixedFunction.glShadeModel(gl, mode);
}
+ public void glAlphaFunc(final int func, final float ref) {
+ fixedFunction.glAlphaFunc(func, ref);
+ }
+
+ /** ES2 supports CullFace implicit
+ public void glCullFace(int faceName) {
+ fixedFunction.glCullFace(faceName);
+ gl.glCullFace(faceName);
+ } */
//
// PointerIf
//
- public void glEnableClientState(int glArrayIndex) {
+ public void glClientActiveTexture(final int textureUnit) {
+ fixedFunction.glClientActiveTexture(textureUnit);
+ }
+ @Override
+ public void glEnableClientState(final int glArrayIndex) {
fixedFunction.glEnableClientState(gl, glArrayIndex);
}
- public void glDisableClientState(int glArrayIndex) {
+ @Override
+ public void glDisableClientState(final int glArrayIndex) {
fixedFunction.glDisableClientState(gl, glArrayIndex);
}
- public void glVertexPointer(GLArrayData array) {
+ @Override
+ public void glVertexPointer(final GLArrayData array) {
if(array.isVBO()) {
- if(!gl.glIsVBOArrayEnabled()) {
+ if(!gl.isVBOArrayBound()) {
throw new GLException("VBO array is not enabled: "+array);
}
} else {
- if(gl.glIsVBOArrayEnabled()) {
+ if(gl.isVBOArrayBound()) {
throw new GLException("VBO array is not disabled: "+array);
}
Buffers.rangeCheck(array.getBuffer(), 1);
@@ -237,25 +385,29 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
fixedFunction.glVertexPointer(gl, array);
}
- public void glVertexPointer(int size, int type, int stride, java.nio.Buffer pointer) {
- glVertexPointer(GLArrayDataWrapper.createFixed(GL_VERTEX_ARRAY, size, type, false, stride, pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER));
+ @Override
+ public void glVertexPointer(final int size, final int type, final int stride, final java.nio.Buffer pointer) {
+ glVertexPointer(GLArrayDataWrapper.createFixed(GL_VERTEX_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride,
+ pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER));
}
- public void glVertexPointer(int size, int type, int stride, long pointer_buffer_offset) {
- int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER);
+ @Override
+ public void glVertexPointer(final int size, final int type, final int stride, final long pointer_buffer_offset) {
+ final int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER);
if(vboName==0) {
throw new GLException("no GL_ARRAY_BUFFER VBO bound");
}
- glVertexPointer(GLArrayDataWrapper.createFixed(GL_VERTEX_ARRAY, size, type, false, stride,
+ glVertexPointer(GLArrayDataWrapper.createFixed(GL_VERTEX_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride,
null, vboName, pointer_buffer_offset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER));
}
- public void glColorPointer(GLArrayData array) {
+ @Override
+ public void glColorPointer(final GLArrayData array) {
if(array.isVBO()) {
- if(!gl.glIsVBOArrayEnabled()) {
+ if(!gl.isVBOArrayBound()) {
throw new GLException("VBO array is not enabled: "+array);
}
} else {
- if(gl.glIsVBOArrayEnabled()) {
+ if(gl.isVBOArrayBound()) {
throw new GLException("VBO array is not disabled: "+array);
}
Buffers.rangeCheck(array.getBuffer(), 1);
@@ -264,29 +416,32 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
}
fixedFunction.glColorPointer(gl, array);
}
- public void glColorPointer(int size, int type, int stride, java.nio.Buffer pointer) {
- glColorPointer(GLArrayDataWrapper.createFixed(GL_COLOR_ARRAY, size, type, false, stride,
+ @Override
+ public void glColorPointer(final int size, final int type, final int stride, final java.nio.Buffer pointer) {
+ glColorPointer(GLArrayDataWrapper.createFixed(GL_COLOR_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride,
pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER));
}
- public void glColorPointer(int size, int type, int stride, long pointer_buffer_offset) {
- int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER);
+ @Override
+ public void glColorPointer(final int size, final int type, final int stride, final long pointer_buffer_offset) {
+ final int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER);
if(vboName==0) {
throw new GLException("no GL_ARRAY_BUFFER VBO bound");
}
- glColorPointer(GLArrayDataWrapper.createFixed(GL_COLOR_ARRAY, size, type, false, stride,
+ glColorPointer(GLArrayDataWrapper.createFixed(GL_COLOR_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride,
null, vboName, pointer_buffer_offset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER));
}
- public void glNormalPointer(GLArrayData array) {
+ @Override
+ public void glNormalPointer(final GLArrayData array) {
if(array.getComponentCount()!=3) {
throw new GLException("Only 3 components per normal allowed");
}
if(array.isVBO()) {
- if(!gl.glIsVBOArrayEnabled()) {
+ if(!gl.isVBOArrayBound()) {
throw new GLException("VBO array is not enabled: "+array);
}
} else {
- if(gl.glIsVBOArrayEnabled()) {
+ if(gl.isVBOArrayBound()) {
throw new GLException("VBO array is not disabled: "+array);
}
Buffers.rangeCheck(array.getBuffer(), 1);
@@ -295,26 +450,29 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
}
fixedFunction.glNormalPointer(gl, array);
}
- public void glNormalPointer(int type, int stride, java.nio.Buffer pointer) {
- glNormalPointer(GLArrayDataWrapper.createFixed(GL_NORMAL_ARRAY, 3, type, false, stride,
+ @Override
+ public void glNormalPointer(final int type, final int stride, final java.nio.Buffer pointer) {
+ glNormalPointer(GLArrayDataWrapper.createFixed(GL_NORMAL_ARRAY, 3, type, GLBuffers.isGLTypeFixedPoint(type), stride,
pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER));
}
- public void glNormalPointer(int type, int stride, long pointer_buffer_offset) {
- int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER);
+ @Override
+ public void glNormalPointer(final int type, final int stride, final long pointer_buffer_offset) {
+ final int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER);
if(vboName==0) {
throw new GLException("no GL_ARRAY_BUFFER VBO bound");
}
- glNormalPointer(GLArrayDataWrapper.createFixed(GL_NORMAL_ARRAY, 3, type, false, stride,
+ glNormalPointer(GLArrayDataWrapper.createFixed(GL_NORMAL_ARRAY, 3, type, GLBuffers.isGLTypeFixedPoint(type), stride,
null, vboName, pointer_buffer_offset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER));
}
- public void glTexCoordPointer(GLArrayData array) {
+ @Override
+ public void glTexCoordPointer(final GLArrayData array) {
if(array.isVBO()) {
- if(!gl.glIsVBOArrayEnabled()) {
+ if(!gl.isVBOArrayBound()) {
throw new GLException("VBO array is not enabled: "+array);
}
} else {
- if(gl.glIsVBOArrayEnabled()) {
+ if(gl.isVBOArrayBound()) {
throw new GLException("VBO array is not disabled: "+array);
}
Buffers.rangeCheck(array.getBuffer(), 1);
@@ -323,25 +481,29 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
}
fixedFunction.glTexCoordPointer(gl, array);
}
- public void glTexCoordPointer(int size, int type, int stride, java.nio.Buffer pointer) {
+ @Override
+ public void glTexCoordPointer(final int size, final int type, final int stride, final java.nio.Buffer pointer) {
glTexCoordPointer(
- GLArrayDataWrapper.createFixed(GL_TEXTURE_COORD_ARRAY, size, type, false, stride, pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER));
+ GLArrayDataWrapper.createFixed(GL_TEXTURE_COORD_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride,
+ pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER));
}
- public void glTexCoordPointer(int size, int type, int stride, long pointer_buffer_offset) {
- int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER);
+ @Override
+ public void glTexCoordPointer(final int size, final int type, final int stride, final long pointer_buffer_offset) {
+ final int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER);
if(vboName==0) {
throw new GLException("no GL_ARRAY_BUFFER VBO bound");
}
glTexCoordPointer(
- GLArrayDataWrapper.createFixed(GL_TEXTURE_COORD_ARRAY, size, type, false, stride,
+ GLArrayDataWrapper.createFixed(GL_TEXTURE_COORD_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride,
null, vboName, pointer_buffer_offset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER) );
}
+ @Override
public final String toString() {
- StringBuilder buf = new StringBuilder();
+ final StringBuilder buf = new StringBuilder();
buf.append(getClass().getName()+" (");
if(null!=pmvMatrix) {
- buf.append(", matrixDirty: "+pmvMatrix.isDirty());
+ buf.append(", matrixDirty: "+ (0 != pmvMatrix.getModifiedBits(false)));
}
buf.append("\n\t, FixedFunction: "+fixedFunction);
buf.append(gl);
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
index bfe2e13c2..7371b0f3b 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
@@ -29,33 +29,88 @@
package jogamp.opengl.util.glsl.fixedfunc;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLArrayData;
+import javax.media.opengl.GLES2;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLRunnable2;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+import javax.media.opengl.fixedfunc.GLPointerFuncUtil;
+
+import jogamp.opengl.Debug;
+
import com.jogamp.common.nio.Buffers;
-import javax.media.opengl.*;
-import javax.media.opengl.fixedfunc.*;
-import com.jogamp.opengl.util.*;
-import com.jogamp.opengl.util.glsl.*;
-import java.nio.*;
+import com.jogamp.common.util.IntIntHashMap;
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode;
+/**
+ *
+ * <p>
+ * Note: Certain GL FFP state values (e.g.: alphaTestFunc and cullFace)
+ * are mapped to a lower number range so they can be stored in low precision storage,
+ * i.e. in a 'lowp int' (GL ES2).
+ * </p>
+ */
public class FixedFuncPipeline {
+ protected static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = PropertyAccess.isPropertyDefined("jogl.debug.FixedFuncPipeline", true);
+ }
+
+ /** The maximum texture units which could be used, depending on {@link ShaderSelectionMode}. */
public static final int MAX_TEXTURE_UNITS = 8;
public static final int MAX_LIGHTS = 8;
- public FixedFuncPipeline(GL2ES2 gl, PMVMatrix pmvMatrix) {
- init(gl, pmvMatrix, FixedFuncPipeline.class, shaderSrcRootDef, shaderBinRootDef,
- vertexColorFileDef, vertexColorLightFileDef, fragmentColorFileDef, fragmentColorTextureFileDef);
+ public FixedFuncPipeline(final GL2ES2 gl, final ShaderSelectionMode mode, final PMVMatrix pmvMatrix) {
+ shaderRootClass = FixedFuncPipeline.class;
+ shaderSrcRoot = shaderSrcRootDef;
+ shaderBinRoot = shaderBinRootDef;
+ vertexColorFile = vertexColorFileDef;
+ vertexColorLightFile = vertexColorLightFileDef;
+ fragmentColorFile = fragmentColorFileDef;
+ fragmentColorTextureFile = fragmentColorTextureFileDef;
+ init(gl, mode, pmvMatrix);
}
- public FixedFuncPipeline(GL2ES2 gl, PMVMatrix pmvMatrix, Class shaderRootClass, String shaderSrcRoot, String shaderBinRoot,
- String vertexColorFile,
- String vertexColorLightFile,
- String fragmentColorFile,
- String fragmentColorTextureFile) {
- init(gl, pmvMatrix, shaderRootClass, shaderSrcRoot, shaderBinRoot,
- vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile);
+ public FixedFuncPipeline(final GL2ES2 gl, final ShaderSelectionMode mode, final PMVMatrix pmvMatrix,
+ final Class<?> shaderRootClass, final String shaderSrcRoot,
+ final String shaderBinRoot,
+ final String vertexColorFile, final String vertexColorLightFile,
+ final String fragmentColorFile, final String fragmentColorTextureFile) {
+ this.shaderRootClass = shaderRootClass;
+ this.shaderSrcRoot = shaderSrcRoot;
+ this.shaderBinRoot = shaderBinRoot;
+ this.vertexColorFile = vertexColorFile;
+ this.vertexColorLightFile = vertexColorLightFile;
+ this.fragmentColorFile = fragmentColorFile;
+ this.fragmentColorTextureFile = fragmentColorTextureFile;
+ init(gl, mode, pmvMatrix);
}
+ public ShaderSelectionMode getShaderSelectionMode() { return requestedShaderSelectionMode; }
+ public void setShaderSelectionMode(final ShaderSelectionMode mode) { requestedShaderSelectionMode=mode; }
+ public ShaderSelectionMode getCurrentShaderSelectionMode() { return currentShaderSelectionMode; }
+
public boolean verbose() { return verbose; }
- public void setVerbose(boolean v) { verbose=v; }
+ public void setVerbose(final boolean v) { verbose = DEBUG || v; }
public boolean isValid() {
return shaderState.linked();
@@ -69,80 +124,326 @@ public class FixedFuncPipeline {
return activeTextureUnit;
}
- public String getArrayIndexName(int glArrayIndex) {
- String name = GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex);
- switch(glArrayIndex) {
- case GLPointerFunc.GL_VERTEX_ARRAY:
- case GLPointerFunc.GL_NORMAL_ARRAY:
- case GLPointerFunc.GL_COLOR_ARRAY:
- break;
- case GLPointerFunc.GL_TEXTURE_COORD_ARRAY:
- name = name + activeTextureUnit;
- }
- return name;
- }
-
- public void destroy(GL2ES2 gl) {
- shaderProgramColor.release(gl, true);
- shaderProgramColorLight.release(gl, true);
- shaderProgramColorTexture.release(gl, true);
- shaderProgramColorTextureLight.release(gl, true);
+ public void destroy(final GL2ES2 gl) {
+ if(null != shaderProgramColor) {
+ shaderProgramColor.release(gl, true);
+ }
+ if(null != shaderProgramColorLight) {
+ shaderProgramColorLight.release(gl, true);
+ }
+ if(null != shaderProgramColorTexture2) {
+ shaderProgramColorTexture2.release(gl, true);
+ }
+ if(null != shaderProgramColorTexture4) {
+ shaderProgramColorTexture4.release(gl, true);
+ }
+ if(null != shaderProgramColorTexture4) {
+ shaderProgramColorTexture4.release(gl, true);
+ }
+ if(null != shaderProgramColorTexture8Light) {
+ shaderProgramColorTexture8Light.release(gl, true);
+ }
shaderState.destroy(gl);
}
- public void glEnableClientState(GL2ES2 gl, int glArrayIndex) {
- shaderState.useProgram(gl, true);
+ //
+ // Simple Globals
+ //
+ public void glColor4f(final GL2ES2 gl, final float red, final float green, final float blue, final float alpha) {
+ colorStatic.put(0, red);
+ colorStatic.put(1, green);
+ colorStatic.put(2, blue);
+ colorStatic.put(3, alpha);
- shaderState.enableVertexAttribArray(gl, getArrayIndexName(glArrayIndex));
- // textureCoordsEnabled |= (1 << activeTextureUnit);
- if ( textureCoordsEnabled.get(activeTextureUnit) != 1 ) {
- textureCoordsEnabled.put(activeTextureUnit, 1);
- textureCoordsEnabledDirty = true;
+ shaderState.useProgram(gl, true);
+ final GLUniformData ud = shaderState.getUniform(mgl_ColorStatic);
+ if(null!=ud) {
+ // same data object ..
+ shaderState.uniform(gl, ud);
+ } else {
+ throw new GLException("Failed to update: mgl_ColorStatic");
}
}
- public void glDisableClientState(GL2ES2 gl, int glArrayIndex) {
- shaderState.useProgram(gl, true);
+ //
+ // Arrays / States
+ //
+
+ public void glEnableClientState(final GL2ES2 gl, final int glArrayIndex) {
+ glToggleClientState(gl, glArrayIndex, true);
+ }
+
+ public void glDisableClientState(final GL2ES2 gl, final int glArrayIndex) {
+ glToggleClientState(gl, glArrayIndex, false);
+ }
- shaderState.disableVertexAttribArray(gl, getArrayIndexName(glArrayIndex));
- // textureCoordsEnabled &= ~(1 << activeTextureUnit);
- if ( textureCoordsEnabled.get(activeTextureUnit) != 0 ) {
- textureCoordsEnabled.put(activeTextureUnit, 0);
- textureCoordsEnabledDirty = true;
+ private void glToggleClientState(final GL2ES2 gl, final int glArrayIndex, final boolean enable) {
+ final String arrayName = GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex, clientActiveTextureUnit);
+ if(null == arrayName) {
+ throw new GLException("arrayIndex "+toHexString(glArrayIndex)+" unknown");
+ }
+ shaderState.useProgram(gl, true);
+ if(enable) {
+ shaderState.enableVertexAttribArray(gl, arrayName );
+ } else {
+ shaderState.disableVertexAttribArray(gl, arrayName );
+ }
+ switch( glArrayIndex ) {
+ case GLPointerFunc.GL_TEXTURE_COORD_ARRAY:
+ final int enableV = enable ? 1 : 0;
+ // enable-bitwise: textureCoordsEnabled |= (1 << clientActiveTextureUnit);
+ // disable-bitwise: textureCoordsEnabled &= ~(1 << clientActiveTextureUnit);
+ if ( textureCoordEnabled.get(clientActiveTextureUnit) != enableV) {
+ textureCoordEnabled.put(clientActiveTextureUnit, enableV);
+ textureCoordEnabledDirty = true;
+ }
+ break;
+ case GLPointerFunc.GL_COLOR_ARRAY:
+ colorVAEnabledDirty = true;
+ break;
}
}
- public void glVertexPointer(GL2ES2 gl, GLArrayData data) {
+ public void glVertexPointer(final GL2ES2 gl, final GLArrayData data) {
shaderState.useProgram(gl, true);
shaderState.vertexAttribPointer(gl, data);
}
- public void glColorPointer(GL2ES2 gl, GLArrayData data) {
+ public void glColorPointer(final GL2ES2 gl, final GLArrayData data) {
shaderState.useProgram(gl, true);
shaderState.vertexAttribPointer(gl, data);
}
- public void glColor4fv(GL2ES2 gl, FloatBuffer data ) {
+ public void glNormalPointer(final GL2ES2 gl, final GLArrayData data) {
shaderState.useProgram(gl, true);
- GLUniformData ud = shaderState.getUniform(mgl_ColorStatic);
- if(null!=ud) {
- ud.setData(data);
- shaderState.uniform(gl, ud);
+ shaderState.vertexAttribPointer(gl, data);
+ }
+
+ //
+ // MULTI-TEXTURE
+ //
+
+ /** Enables/Disables the named texture unit (if changed), returns previous state */
+ private boolean glEnableTexture(final boolean enable, final int unit) {
+ final boolean isEnabled = 0 != ( textureEnabledBits & ( 1 << activeTextureUnit ) );
+ if( isEnabled != enable ) {
+ if(enable) {
+ textureEnabledBits |= ( 1 << unit );
+ textureEnabled.put(unit, 1);
+ } else {
+ textureEnabledBits &= ~( 1 << unit );
+ textureEnabled.put(unit, 0);
+ }
+ textureEnabledDirty=true;
}
+ return isEnabled;
}
- public void glNormalPointer(GL2ES2 gl, GLArrayData data) {
- shaderState.useProgram(gl, true);
- shaderState.vertexAttribPointer(gl, data);
+ public void glClientActiveTexture(int textureUnit) {
+ textureUnit -= GL.GL_TEXTURE0;
+ if(0 <= textureUnit && textureUnit<MAX_TEXTURE_UNITS) {
+ clientActiveTextureUnit = textureUnit;
+ } else {
+ throw new GLException("glClientActiveTexture textureUnit not within GL_TEXTURE0 + [0.."+MAX_TEXTURE_UNITS+"]: "+textureUnit);
+ }
}
- public void glTexCoordPointer(GL2ES2 gl, GLArrayData data) {
+ public void glActiveTexture(int textureUnit) {
+ textureUnit -= GL.GL_TEXTURE0;
+ if(0 <= textureUnit && textureUnit<MAX_TEXTURE_UNITS) {
+ activeTextureUnit = textureUnit;
+ } else {
+ throw new GLException("glActivateTexture textureUnit not within GL_TEXTURE0 + [0.."+MAX_TEXTURE_UNITS+"]: "+textureUnit);
+ }
+ }
+
+ public void glTexCoordPointer(final GL2ES2 gl, final GLArrayData data) {
+ if( GLPointerFunc.GL_TEXTURE_COORD_ARRAY != data.getIndex() ) {
+ throw new GLException("Invalid GLArrayData Index "+toHexString(data.getIndex())+", "+data);
+ }
shaderState.useProgram(gl, true);
- data.setName( getArrayIndexName(data.getIndex()) );
+ data.setName( GLPointerFuncUtil.getPredefinedArrayIndexName(data.getIndex(), clientActiveTextureUnit) ) ;
shaderState.vertexAttribPointer(gl, data);
}
- public void glLightfv(GL2ES2 gl, int light, int pname, java.nio.FloatBuffer params) {
+ public void glBindTexture(final int target, final int texture) {
+ if(GL.GL_TEXTURE_2D == target) {
+ if( texture != boundTextureObject[activeTextureUnit] ) {
+ boundTextureObject[activeTextureUnit] = texture;
+ textureFormatDirty = true;
+ }
+ } else {
+ System.err.println("FixedFuncPipeline: Unimplemented glBindTexture for target "+toHexString(target)+". Texture name "+toHexString(texture));
+ }
+ }
+
+ public void glTexImage2D(final int target, /* int level, */ final int internalformat, /*, int width, int height, int border, */
+ final int format /*, int type, Buffer pixels */) {
+ final int ifmt;
+ if(GL.GL_TEXTURE_2D == target) {
+ switch(internalformat) {
+ case 3:
+ case GL.GL_RGB:
+ case GL.GL_RGB565:
+ case GL.GL_RGB8:
+ case GL.GL_RGB10:
+ ifmt = 3;
+ break;
+ case 4:
+ case GL.GL_RGBA:
+ case GL.GL_RGB5_A1:
+ case GL.GL_RGBA4:
+ case GL.GL_RGBA8:
+ case GL.GL_RGB10_A2:
+ ifmt = 4;
+ break;
+ default:
+ System.err.println("FixedFuncPipeline: glTexImage2D TEXTURE_2D: Unimplemented internalformat "+toHexString(internalformat));
+ ifmt = 4;
+ break;
+ }
+ if( ifmt != texID2Format.put(boundTextureObject[activeTextureUnit], ifmt) ) {
+ textureFormatDirty = true;
+ // System.err.println("glTexImage2D TEXTURE_2D: internalformat ifmt "+toHexString(internalformat)+" fmt "+toHexString(format)+" -> "+toHexString(ifmt));
+ }
+ } else {
+ System.err.println("FixedFuncPipeline: Unimplemented glTexImage2D: target "+toHexString(target)+", internalformat "+toHexString(internalformat));
+ }
+ }
+ /*
+ public void glTexImage2D(int target, int level, int internalformat, int width, int height, int border,
+ int format, int type, long pixels_buffer_offset) {
+ textureFormat.put(activeTextureUnit, internalformat);
+ textureFormatDirty = true;
+ }*/
+
+ public void glTexEnvi(final int target, final int pname, final int value) {
+ if(GL2ES1.GL_TEXTURE_ENV == target && GL2ES1.GL_TEXTURE_ENV_MODE == pname) {
+ final int mode;
+ switch( value ) {
+ case GL2ES1.GL_ADD:
+ mode = 1;
+ break;
+ case GL2ES1.GL_MODULATE:
+ mode = 2;
+ break;
+ case GL2ES1.GL_DECAL:
+ mode = 3;
+ break;
+ case GL.GL_BLEND:
+ mode = 4;
+ break;
+ case GL.GL_REPLACE:
+ mode = 5;
+ break;
+ case GL2ES1.GL_COMBINE:
+ mode = 2; // FIXME
+ System.err.println("FixedFuncPipeline: glTexEnv GL_TEXTURE_ENV_MODE: unimplemented mode: "+toHexString(value));
+ break;
+ default:
+ throw new GLException("glTexEnv GL_TEXTURE_ENV_MODE: invalid mode: "+toHexString(value));
+ }
+ setTextureEnvMode(mode);
+ } else if(verbose) {
+ System.err.println("FixedFuncPipeline: Unimplemented TexEnv: target "+toHexString(target)+", pname "+toHexString(pname)+", mode: "+toHexString(value));
+ }
+ }
+ private void setTextureEnvMode(final int value) {
+ if( value != textureEnvMode.get(activeTextureUnit) ) {
+ textureEnvMode.put(activeTextureUnit, value);
+ textureEnvModeDirty = true;
+ }
+ }
+ public void glGetTexEnviv(final int target, final int pname, final IntBuffer params) { // FIXME
+ System.err.println("FixedFuncPipeline: Unimplemented glGetTexEnviv: target "+toHexString(target)+", pname "+toHexString(pname));
+ }
+ public void glGetTexEnviv(final int target, final int pname, final int[] params, final int params_offset) { // FIXME
+ System.err.println("FixedFuncPipeline: Unimplemented glGetTexEnviv: target "+toHexString(target)+", pname "+toHexString(pname));
+ }
+
+ //
+ // Point Sprites
+ //
+ public void glPointSize(final float size) {
+ pointParams.put(0, size);
+ pointParamsDirty = true;
+ }
+ public void glPointParameterf(final int pname, final float param) {
+ switch(pname) {
+ case GL2ES1.GL_POINT_SIZE_MIN:
+ pointParams.put(2, param);
+ break;
+ case GL2ES1.GL_POINT_SIZE_MAX:
+ pointParams.put(3, param);
+ break;
+ case GL.GL_POINT_FADE_THRESHOLD_SIZE:
+ pointParams.put(4+3, param);
+ break;
+ }
+ pointParamsDirty = true;
+ }
+ public void glPointParameterfv(final int pname, final float[] params, final int params_offset) {
+ switch(pname) {
+ case GL2ES1.GL_POINT_DISTANCE_ATTENUATION:
+ pointParams.put(4+0, params[params_offset + 0]);
+ pointParams.put(4+1, params[params_offset + 1]);
+ pointParams.put(4+2, params[params_offset + 2]);
+ break;
+ }
+ pointParamsDirty = true;
+ }
+ public void glPointParameterfv(final int pname, final java.nio.FloatBuffer params) {
+ final int o = params.position();
+ switch(pname) {
+ case GL2ES1.GL_POINT_DISTANCE_ATTENUATION:
+ pointParams.put(4+0, params.get(o + 0));
+ pointParams.put(4+1, params.get(o + 1));
+ pointParams.put(4+2, params.get(o + 2));
+ break;
+ }
+ pointParamsDirty = true;
+ }
+
+ // private int[] pointTexObj = new int[] { 0 };
+
+ private void glDrawPoints(final GL2ES2 gl, final GLRunnable2<Object,Object> glDrawAction, final Object args) {
+ if(gl.isGL2GL3()) {
+ gl.glEnable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
+ }
+ if(gl.isGL2ES1()) {
+ gl.glEnable(GL2ES1.GL_POINT_SPRITE);
+ }
+ loadShaderPoints(gl);
+ shaderState.attachShaderProgram(gl, shaderProgramPoints, true);
+ validate(gl, false); // sync uniforms
+
+ glDrawAction.run(gl, args);
+
+ if(gl.isGL2ES1()) {
+ gl.glDisable(GL2ES1.GL_POINT_SPRITE);
+ }
+ if(gl.isGL2GL3()) {
+ gl.glDisable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
+ }
+ shaderState.attachShaderProgram(gl, selectShaderProgram(gl, currentShaderSelectionMode), true);
+ }
+ private static final GLRunnable2<Object, Object> glDrawArraysAction = new GLRunnable2<Object,Object>() {
+ @Override
+ public Object run(final GL gl, final Object args) {
+ final int[] _args = (int[])args;
+ gl.glDrawArrays(GL.GL_POINTS, _args[0], _args[1]);
+ return null;
+ }
+ };
+ private final void glDrawPointArrays(final GL2ES2 gl, final int first, final int count) {
+ glDrawPoints(gl, glDrawArraysAction, new int[] { first, count });
+ }
+
+ //
+ // Lighting
+ //
+
+ public void glLightfv(final GL2ES2 gl, int light, final int pname, final java.nio.FloatBuffer params) {
shaderState.useProgram(gl, true);
light -=GLLightingFunc.GL_LIGHT0;
if(0 <= light && light < MAX_LIGHTS) {
@@ -179,21 +480,18 @@ public class FixedFuncPipeline {
ud = shaderState.getUniform(mgl_LightSource+"["+light+"].quadraticAttenuation");
break;
default:
- if(verbose) {
- System.err.println("glLightfv pname not within [GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_POSITION GL_SPOT_DIRECTION]: "+pname);
- }
- return;
+ throw new GLException("glLightfv invalid pname: "+toHexString(pname));
}
if(null!=ud) {
ud.setData(params);
shaderState.uniform(gl, ud);
}
- } else if(verbose) {
- System.err.println("glLightfv light not within [0.."+MAX_LIGHTS+"]: "+light);
+ } else {
+ throw new GLException("glLightfv light not within [0.."+MAX_LIGHTS+"]: "+light);
}
}
- public void glMaterialfv(GL2ES2 gl, int face, int pname, java.nio.FloatBuffer params) {
+ public void glMaterialfv(final GL2ES2 gl, final int face, final int pname, final java.nio.FloatBuffer params) {
shaderState.useProgram(gl, true);
switch (face) {
@@ -201,10 +499,8 @@ public class FixedFuncPipeline {
case GL.GL_FRONT_AND_BACK:
break;
case GL.GL_BACK:
- if(verbose) {
- System.err.println("glMaterialfv face GL_BACK currently not supported");
- }
- break;
+ System.err.println("FixedFuncPipeline: Unimplemented glMaterialfv GL_BACK face");
+ return;
default:
}
@@ -214,7 +510,13 @@ public class FixedFuncPipeline {
ud = shaderState.getUniform(mgl_FrontMaterial+".ambient");
break;
case GLLightingFunc.GL_AMBIENT_AND_DIFFUSE:
- glMaterialfv(gl, face, GLLightingFunc.GL_AMBIENT, params);
+ {
+ ud = shaderState.getUniform(mgl_FrontMaterial+".ambient");
+ if(null!=ud) {
+ ud.setData(params);
+ shaderState.uniform(gl, ud);
+ }
+ }
// fall through intended ..
case GLLightingFunc.GL_DIFFUSE:
ud = shaderState.getUniform(mgl_FrontMaterial+".diffuse");
@@ -229,69 +531,161 @@ public class FixedFuncPipeline {
ud = shaderState.getUniform(mgl_FrontMaterial+".shininess");
break;
default:
- if(verbose) {
- System.err.println("glMaterialfv pname not within [GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_EMISSION GL_SHININESS]: "+pname);
- }
- return;
+ throw new GLException("glMaterialfv invalid pname: "+toHexString(pname));
}
if(null!=ud) {
ud.setData(params);
shaderState.uniform(gl, ud);
+ } else if(verbose) {
+
}
}
- public void glShadeModel(GL2ES2 gl, int mode) {
+ //
+ // Misc States
+ //
+
+ public void glShadeModel(final GL2ES2 gl, final int mode) {
shaderState.useProgram(gl, true);
- GLUniformData ud = shaderState.getUniform(mgl_ShadeModel);
+ final GLUniformData ud = shaderState.getUniform(mgl_ShadeModel);
if(null!=ud) {
ud.setData(mode);
shaderState.uniform(gl, ud);
}
}
- public void glActiveTexture(GL2ES2 gl, int textureUnit) {
- textureUnit -= GL.GL_TEXTURE0;
- if(0 <= textureUnit && textureUnit<MAX_TEXTURE_UNITS) {
- shaderState.useProgram(gl, true);
- GLUniformData ud;
- ud = shaderState.getUniform(mgl_ActiveTexture);
- if(null!=ud) {
- ud.setData(textureUnit);
- shaderState.uniform(gl, ud);
+ /** ES2 supports CullFace implicit
+ public void glCullFace(int faceName) {
+ int _cullFace;
+ switch(faceName) {
+ case GL.GL_FRONT:
+ _cullFace = 1;
+ break;
+ case GL.GL_BACK:
+ _cullFace = 2;
+ break;
+ case GL.GL_FRONT_AND_BACK:
+ _cullFace = 3;
+ break;
+ default:
+ throw new GLException("glCullFace invalid faceName: "+toHexString(faceName));
+ }
+ if(0 < _cullFace) {
+ if(0>cullFace) {
+ _cullFace *= -1;
}
- ud = shaderState.getUniform(mgl_ActiveTextureIdx);
- if(null!=ud) {
- ud.setData(textureUnit);
- shaderState.uniform(gl, ud);
+ if(cullFace != _cullFace) {
+ cullFace = _cullFace;
+ cullFaceDirty=true;
+ }
+ }
+ } */
+
+ public void glAlphaFunc(final int func, final float ref) {
+ int _func;
+ switch(func) {
+ case GL.GL_NEVER:
+ _func = 1;
+ break;
+ case GL.GL_LESS:
+ _func = 2;
+ break;
+ case GL.GL_EQUAL:
+ _func = 3;
+ break;
+ case GL.GL_LEQUAL:
+ _func = 4;
+ break;
+ case GL.GL_GREATER:
+ _func = 5;
+ break;
+ case GL.GL_NOTEQUAL:
+ _func = 6;
+ break;
+ case GL.GL_GEQUAL:
+ _func = 7;
+ break;
+ case GL.GL_ALWAYS:
+ _func = 8;
+ break;
+ default:
+ throw new GLException("glAlphaFunc invalid func: "+toHexString(func));
+ }
+ if(0 < _func) {
+ if(0>alphaTestFunc) {
+ _func *= -1;
+ }
+ if( alphaTestFunc != _func || alphaTestRef != ref ) {
+ alphaTestFunc = _func;
+ alphaTestRef = ref;
+ alphaTestDirty=true;
}
- activeTextureUnit = textureUnit;
- } else {
- throw new GLException("glActivateTexture textureUnit not within GL_TEXTURE0 + [0.."+MAX_TEXTURE_UNITS+"]: "+textureUnit);
}
}
/**
- * @return false if digested in regard to GL2ES2 spec,
+ * @return false if digested in regard to GL2ES2 spec,
* eg this call must not be passed to an underlying ES2 implementation.
* true if this call shall be passed to an underlying GL2ES2/ES2 implementation as well.
*/
- public boolean glEnable(GL2ES2 gl, int cap, boolean enable) {
+ public boolean glEnable(final int cap, final boolean enable) {
switch(cap) {
- case GL.GL_TEXTURE_2D:
- textureEnabled=enable;
+ case GL.GL_BLEND:
+ case GL.GL_DEPTH_TEST:
+ case GL.GL_DITHER:
+ case GL.GL_POLYGON_OFFSET_FILL:
+ case GL.GL_SAMPLE_ALPHA_TO_COVERAGE:
+ case GL.GL_SAMPLE_COVERAGE:
+ case GL.GL_SCISSOR_TEST:
+ case GL.GL_STENCIL_TEST:
return true;
+
+ case GL.GL_CULL_FACE:
+ /** ES2 supports CullFace implicit
+ final int _cullFace;
+ if(0>cullFace && enable || 0<cullFace && !enable) {
+ _cullFace = cullFace * -1;
+ } else {
+ _cullFace = cullFace;
+ }
+ if(_cullFace != cullFace) {
+ cullFaceDirty=true;
+ cullFace=_cullFace;
+ } */
+ return true;
+
+ case GL.GL_TEXTURE_2D:
+ glEnableTexture(enable, activeTextureUnit);
+ return false;
+
case GLLightingFunc.GL_LIGHTING:
lightingEnabled=enable;
return false;
- case GL.GL_CULL_FACE:
- cullFace=Math.abs(cullFace);
- if(!enable) {
- cullFace*=-1;
+
+ case GL2ES1.GL_ALPHA_TEST:
+ final int _alphaTestFunc;
+ if(0>alphaTestFunc && enable || 0<alphaTestFunc && !enable) {
+ _alphaTestFunc = alphaTestFunc * -1;
+ } else {
+ _alphaTestFunc = alphaTestFunc;
}
- return true;
+ if(_alphaTestFunc != alphaTestFunc) {
+ alphaTestDirty=true;
+ alphaTestFunc=_alphaTestFunc;
+ }
+ return false;
+
+ case GL2ES1.GL_POINT_SMOOTH:
+ pointParams.put(1, enable ? 1.0f : 0.0f);
+ pointParamsDirty = true;
+ return false;
+
+ case GL2ES1.GL_POINT_SPRITE:
+ // gl_PointCoord always enabled
+ return false;
}
- int light = cap - GLLightingFunc.GL_LIGHT0;
+ final int light = cap - GLLightingFunc.GL_LIGHT0;
if(0 <= light && light < MAX_LIGHTS) {
if ( (lightsEnabled.get(light)==1) != enable ) {
lightsEnabled.put(light, enable?1:0);
@@ -299,157 +693,422 @@ public class FixedFuncPipeline {
return false;
}
}
- return true; // pass it on ..
+ System.err.println("FixedFunctionPipeline: "+(enable ? "glEnable" : "glDisable")+" "+toHexString(cap)+" not handled in emulation and not supported in ES2");
+ return false; // ignore!
}
- public void glCullFace(GL2ES2 gl, int faceName) {
- switch(faceName) {
- case GL.GL_FRONT:
- faceName = 1; break;
- case GL.GL_BACK:
- faceName = 2; break;
- case GL.GL_FRONT_AND_BACK:
- faceName = 3; break;
+ //
+ // Draw
+ //
+
+ public void glDrawArrays(final GL2ES2 gl, int mode, final int first, final int count) {
+ switch(mode) {
+ case GL2.GL_QUAD_STRIP:
+ mode=GL.GL_TRIANGLE_STRIP;
+ break;
+ case GL2.GL_POLYGON:
+ mode=GL.GL_TRIANGLE_FAN;
+ break;
+ case GL.GL_POINTS:
+ glDrawPointArrays(gl, first, count);
+ return;
}
- if(0>cullFace) {
- faceName *= -1;
+ validate(gl, true);
+ if ( GL2GL3.GL_QUADS == mode && !gl.isGL2() ) {
+ for (int j = first; j < count - 3; j += 4) {
+ gl.glDrawArrays(GL.GL_TRIANGLE_FAN, j, 4);
+ }
+ } else {
+ gl.glDrawArrays(mode, first, count);
}
- cullFace = faceName;
}
+ public void glDrawElements(final GL2ES2 gl, final int mode, final int count, final int type, final java.nio.Buffer indices) {
+ validate(gl, true);
+ if ( GL2GL3.GL_QUADS == mode && !gl.isGL2() ) {
+ final int idx0 = indices.position();
+
+ if( GL.GL_UNSIGNED_BYTE == type ) {
+ final ByteBuffer b = (ByteBuffer) indices;
+ for (int j = 0; j < count; j++) {
+ gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 0x000000ff & b.get(idx0+j), 4);
+ }
+ } else if( GL.GL_UNSIGNED_SHORT == type ){
+ final ShortBuffer b = (ShortBuffer) indices;
+ for (int j = 0; j < count; j++) {
+ gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 0x0000ffff & b.get(idx0+j), 4);
+ }
+ } else {
+ final IntBuffer b = (IntBuffer) indices;
+ for (int j = 0; j < count; j++) {
+ gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 0xffffffff & b.get(idx0+j), 4);
+ }
+ }
+ } else {
+ // FIXME: Impl. VBO usage .. or unroll (see above)!
+ if( !gl.getContext().isCPUDataSourcingAvail() ) {
+ throw new GLException("CPU data sourcing n/a w/ "+gl.getContext());
+ }
+ // if( GL.GL_POINTS != mode ) {
+ ((GLES2)gl).glDrawElements(mode, count, type, indices);
+ /* } else {
+ // FIXME GL_POINTS !
+ ((GLES2)gl).glDrawElements(mode, count, type, indices);
+ } */
+ }
+ }
+ public void glDrawElements(final GL2ES2 gl, final int mode, final int count, final int type, final long indices_buffer_offset) {
+ validate(gl, true);
+ if ( GL2GL3.GL_QUADS == mode && !gl.isGL2() ) {
+ throw new GLException("Cannot handle indexed QUADS on !GL2 w/ VBO due to lack of CPU index access");
+ } else /* if( GL.GL_POINTS != mode ) */ {
+ gl.glDrawElements(mode, count, type, indices_buffer_offset);
+ } /* else {
+ // FIXME GL_POINTS !
+ gl.glDrawElements(mode, count, type, indices_buffer_offset);
+ } */
+ }
+
+ private final int textureEnabledCount() {
+ int n=0;
+ for(int i=MAX_TEXTURE_UNITS-1; i>=0; i--) {
+ if( 0 != textureEnabled.get(i) ) {
+ n++;
+ }
+ }
+ return n;
+ }
+
+ public void validate(final GL2ES2 gl, final boolean selectShader) {
+ if( selectShader ) {
+ if( ShaderSelectionMode.AUTO == requestedShaderSelectionMode) {
+ final ShaderSelectionMode newMode;
+
+ // pre-validate shader switch
+ if( 0 != textureEnabledBits ) {
+ if(lightingEnabled) {
+ newMode = ShaderSelectionMode.COLOR_TEXTURE8_LIGHT_PER_VERTEX;
+ } else {
+ final int n = textureEnabledCount();
+ if( 4 < n ) {
+ newMode = ShaderSelectionMode.COLOR_TEXTURE8;
+ } else if ( 2 < n ) {
+ newMode = ShaderSelectionMode.COLOR_TEXTURE4;
+ } else {
+ newMode = ShaderSelectionMode.COLOR_TEXTURE2;
+ }
+ }
+ } else {
+ if(lightingEnabled) {
+ newMode = ShaderSelectionMode.COLOR_LIGHT_PER_VERTEX;
+ } else {
+ newMode = ShaderSelectionMode.COLOR;
+ }
+ }
+ shaderState.attachShaderProgram(gl, selectShaderProgram(gl, newMode), true); // enables shader-program implicit
+ } else {
+ shaderState.useProgram(gl, true);
+ }
+ }
- public void validate(GL2ES2 gl) {
- shaderState.useProgram(gl, true);
GLUniformData ud;
- if(pmvMatrix.update()) {
+ if( pmvMatrix.update() ) {
ud = shaderState.getUniform(mgl_PMVMatrix);
if(null!=ud) {
+ final FloatBuffer m;
+ if(ShaderSelectionMode.COLOR_TEXTURE8_LIGHT_PER_VERTEX == currentShaderSelectionMode ||
+ ShaderSelectionMode.COLOR_LIGHT_PER_VERTEX== currentShaderSelectionMode ) {
+ m = pmvMatrix.glGetPMvMvitMatrixf();
+ } else {
+ m = pmvMatrix.glGetPMvMatrixf();
+ }
+ if(m != ud.getBuffer()) {
+ ud.setData(m);
+ }
// same data object ..
shaderState.uniform(gl, ud);
} else {
throw new GLException("Failed to update: mgl_PMVMatrix");
}
}
- ud = shaderState.getUniform(mgl_ColorEnabled);
- if(null!=ud) {
- int ca = (shaderState.isVertexAttribArrayEnabled(GLPointerFuncUtil.mgl_Color)==true)?1:0;
- if(ca!=ud.intValue()) {
- ud.setData(ca);
- shaderState.uniform(gl, ud);
+ if(colorVAEnabledDirty) {
+ ud = shaderState.getUniform(mgl_ColorEnabled);
+ if(null!=ud) {
+ final int ca = true == shaderState.isVertexAttribArrayEnabled(GLPointerFuncUtil.mgl_Color) ? 1 : 0 ;
+ if(ca!=ud.intValue()) {
+ ud.setData(ca);
+ shaderState.uniform(gl, ud);
+ }
+ } else {
+ throw new GLException("Failed to update: mgl_ColorEnabled");
}
+ colorVAEnabledDirty = false;
}
- ud = shaderState.getUniform(mgl_CullFace);
- if(null!=ud) {
- if(cullFace!=ud.intValue()) {
+ /** ES2 supports CullFace implicit
+ if(cullFaceDirty) {
+ ud = shaderState.getUniform(mgl_CullFace);
+ if(null!=ud) {
ud.setData(cullFace);
shaderState.uniform(gl, ud);
}
+ cullFaceDirty = false;
+ } */
+
+ if(alphaTestDirty) {
+ ud = shaderState.getUniform(mgl_AlphaTestFunc);
+ if(null!=ud) {
+ ud.setData(alphaTestFunc);
+ shaderState.uniform(gl, ud);
+ }
+ ud = shaderState.getUniform(mgl_AlphaTestRef);
+ if(null!=ud) {
+ ud.setData(alphaTestRef);
+ shaderState.uniform(gl, ud);
+ }
+ alphaTestDirty = false;
+ }
+ if(pointParamsDirty) {
+ ud = shaderState.getUniform(mgl_PointParams);
+ if(null!=ud) {
+ // same data object
+ shaderState.uniform(gl, ud);
+ }
+ pointParamsDirty = false;
}
if(lightsEnabledDirty) {
ud = shaderState.getUniform(mgl_LightsEnabled);
if(null!=ud) {
- // same data object
+ // same data object
shaderState.uniform(gl, ud);
}
lightsEnabledDirty=false;
}
- if(textureCoordsEnabledDirty) {
+ if(textureCoordEnabledDirty) {
ud = shaderState.getUniform(mgl_TexCoordEnabled);
if(null!=ud) {
- // same data object
+ // same data object
shaderState.uniform(gl, ud);
}
- textureCoordsEnabledDirty=false;
+ textureCoordEnabledDirty=false;
}
- if(textureEnabled) {
- if(lightingEnabled) {
- shaderState.attachShaderProgram(gl, shaderProgramColorTextureLight, true);
- } else {
- shaderState.attachShaderProgram(gl, shaderProgramColorTexture, true);
+ if(textureEnvModeDirty) {
+ ud = shaderState.getUniform(mgl_TexEnvMode);
+ if(null!=ud) {
+ // same data object
+ shaderState.uniform(gl, ud);
}
- } else {
- if(lightingEnabled) {
- shaderState.attachShaderProgram(gl, shaderProgramColorLight, true);
- } else {
- shaderState.attachShaderProgram(gl, shaderProgramColor, true);
+ textureEnvModeDirty = false;
+ }
+
+ if(textureFormatDirty) {
+ for(int i = 0; i<MAX_TEXTURE_UNITS; i++) {
+ textureFormat.put(i, texID2Format.get(boundTextureObject[i]));
}
+ ud = shaderState.getUniform(mgl_TexFormat);
+ if(null!=ud) {
+ // same data object
+ shaderState.uniform(gl, ud);
+ }
+ textureFormatDirty = false;
}
- if(DEBUG) {
- System.err.println("validate: "+this);
+ if(textureEnabledDirty) {
+ ud = shaderState.getUniform(mgl_TextureEnabled);
+ if(null!=ud) {
+ // same data object
+ shaderState.uniform(gl, ud);
+ }
+ textureEnabledDirty=false;
+ }
+
+ if(verbose) {
+ System.err.println("validate: "+toString(null, DEBUG).toString());
}
}
- public String toString() {
- return "FixedFuncPipeline[pmv: "+pmvMatrix+
- ", textureEnabled: "+textureEnabled+
- ", textureCoordsEnabled: "+textureCoordsEnabled+
- ", lightingEnabled: "+lightingEnabled+
- ", lightsEnabled: "+lightsEnabled+
- "\n\t, shaderProgramColor: "+shaderProgramColor+
- "\n\t, shaderProgramColorTexture: "+shaderProgramColorTexture+
- "\n\t, shaderProgramColorLight: "+shaderProgramColorLight+
- "\n\t, shaderProgramColorTextureLight: "+shaderProgramColorTextureLight+
- "\n\t, ShaderState: "+shaderState+
- "]";
- }
-
- protected void init(GL2ES2 gl, PMVMatrix pmvMatrix, Class shaderRootClass, String shaderSrcRoot, String shaderBinRoot,
- String vertexColorFile,
- String vertexColorLightFile,
- String fragmentColorFile,
- String fragmentColorTextureFile)
- {
- if(null==pmvMatrix) {
- throw new GLException("PMVMatrix is null");
+ public StringBuilder toString(StringBuilder sb, final boolean alsoUnlocated) {
+ if(null == sb) {
+ sb = new StringBuilder();
}
- this.pmvMatrix=pmvMatrix;
- this.shaderState=new ShaderState();
- this.shaderState.setVerbose(verbose);
- ShaderCode vertexColor, vertexColorLight, fragmentColor, fragmentColorTexture;
+ sb.append("FixedFuncPipeline[");
+ sb.append(", textureEnabled: "+toHexString(textureEnabledBits)+", "); Buffers.toString(sb, null, textureEnabled);
+ sb.append("\n\t, textureCoordEnabled: "); Buffers.toString(sb, null, textureCoordEnabled);
+ sb.append("\n\t lightingEnabled: "+lightingEnabled);
+ sb.append(", lightsEnabled: "); Buffers.toString(sb, null, lightsEnabled);
+ sb.append("\n\t, shaderProgramColor: "+shaderProgramColor);
+ sb.append("\n\t, shaderProgramColorTexture2: "+shaderProgramColorTexture2);
+ sb.append("\n\t, shaderProgramColorTexture4: "+shaderProgramColorTexture4);
+ sb.append("\n\t, shaderProgramColorTexture8: "+shaderProgramColorTexture8);
+ sb.append("\n\t, shaderProgramColorLight: "+shaderProgramColorLight);
+ sb.append("\n\t, shaderProgramColorTexture8Light: "+shaderProgramColorTexture8Light);
+ sb.append("\n\t, ShaderState: ");
+ shaderState.toString(sb, alsoUnlocated);
+ sb.append("]");
+ return sb;
+ }
+ @Override
+ public String toString() {
+ return toString(null, DEBUG).toString();
+ }
- vertexColor = ShaderCode.create( gl, gl.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot,
- shaderBinRoot, vertexColorFile, false);
+ private static final String constMaxTextures0 = "#define MAX_TEXTURE_UNITS 0\n";
+ private static final String constMaxTextures2 = "#define MAX_TEXTURE_UNITS 2\n";
+ private static final String constMaxTextures4 = "#define MAX_TEXTURE_UNITS 4\n";
+ private static final String constMaxTextures8 = "#define MAX_TEXTURE_UNITS 8\n";
- vertexColorLight = ShaderCode.create( gl, gl.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot,
- shaderBinRoot, vertexColorLightFile, false);
+ private final void customizeShader(final GL2ES2 gl, final ShaderCode vp, final ShaderCode fp, final String maxTextureDefine) {
+ final int rsVpPos = vp.defaultShaderCustomization(gl, true, true);
+ final int rsFpPos = fp.defaultShaderCustomization(gl, true, true);
+ vp.insertShaderSource(0, rsVpPos, maxTextureDefine);
+ fp.insertShaderSource(0, rsFpPos, maxTextureDefine);
+ }
- fragmentColor = ShaderCode.create( gl, gl.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot,
- shaderBinRoot, fragmentColorFile, false);
+ private final void loadShaderPoints(final GL2ES2 gl) {
+ if( null != shaderProgramPoints ) {
+ return;
+ }
- fragmentColorTexture = ShaderCode.create( gl, gl.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot,
- shaderBinRoot, fragmentColorTextureFile, false);
+ final ShaderCode vp = ShaderCode.create( gl, GL2ES2.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot,
+ shaderBinRoot, shaderPointFileDef, true);
+ final ShaderCode fp = ShaderCode.create( gl, GL2ES2.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot,
+ shaderBinRoot, shaderPointFileDef, true);
+ customizeShader(gl, vp, fp, constMaxTextures2);
+ shaderProgramPoints = new ShaderProgram();
+ shaderProgramPoints.add(vp);
+ shaderProgramPoints.add(fp);
+ if(!shaderProgramPoints.link(gl, System.err)) {
+ throw new GLException("Couldn't link VertexColor program: "+shaderProgramPoints);
+ }
+ }
+
+ private final void loadShader(final GL2ES2 gl, final ShaderSelectionMode mode) {
+ final boolean loadColor = ShaderSelectionMode.COLOR == mode;
+ final boolean loadColorTexture2 = ShaderSelectionMode.COLOR_TEXTURE2 == mode;
+ final boolean loadColorTexture4 = ShaderSelectionMode.COLOR_TEXTURE4 == mode;
+ final boolean loadColorTexture8 = ShaderSelectionMode.COLOR_TEXTURE8 == mode;
+ final boolean loadColorTexture = loadColorTexture2 || loadColorTexture4 || loadColorTexture8 ;
+ final boolean loadColorLightPerVertex = ShaderSelectionMode.COLOR_LIGHT_PER_VERTEX == mode;
+ final boolean loadColorTexture8LightPerVertex = ShaderSelectionMode.COLOR_TEXTURE8_LIGHT_PER_VERTEX == mode;
- shaderProgramColor = new ShaderProgram();
- shaderProgramColor.add(vertexColor);
- shaderProgramColor.add(fragmentColor);
- if(!shaderProgramColor.link(gl, System.err)) {
- throw new GLException("Couldn't link VertexColor program: "+shaderProgramColor);
+ if( null != shaderProgramColor && loadColor ||
+ null != shaderProgramColorTexture2 && loadColorTexture2 ||
+ null != shaderProgramColorTexture4 && loadColorTexture4 ||
+ null != shaderProgramColorTexture8 && loadColorTexture8 ||
+ null != shaderProgramColorLight && loadColorLightPerVertex ||
+ null != shaderProgramColorTexture8Light && loadColorTexture8LightPerVertex ) {
+ return;
}
- shaderProgramColorTexture = new ShaderProgram();
- shaderProgramColorTexture.add(vertexColor);
- shaderProgramColorTexture.add(fragmentColorTexture);
- if(!shaderProgramColorTexture.link(gl, System.err)) {
- throw new GLException("Couldn't link VertexColorTexture program: "+shaderProgramColorTexture);
+ if( loadColor ) {
+ final ShaderCode vp = ShaderCode.create( gl, GL2ES2.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot,
+ shaderBinRoot, vertexColorFile, true);
+ final ShaderCode fp = ShaderCode.create( gl, GL2ES2.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot,
+ shaderBinRoot, fragmentColorFile, true);
+ customizeShader(gl, vp, fp, constMaxTextures0);
+ shaderProgramColor = new ShaderProgram();
+ shaderProgramColor.add(vp);
+ shaderProgramColor.add(fp);
+ if(!shaderProgramColor.link(gl, System.err)) {
+ throw new GLException("Couldn't link VertexColor program: "+shaderProgramColor);
+ }
+ } else if( loadColorTexture ) {
+ final ShaderCode vp = ShaderCode.create( gl, GL2ES2.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot, shaderBinRoot, vertexColorFile, true);
+ final ShaderCode fp = ShaderCode.create( gl, GL2ES2.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot,
+ shaderBinRoot, fragmentColorTextureFile, true);
+
+ if( loadColorTexture2 ) {
+ customizeShader(gl, vp, fp, constMaxTextures2);
+ shaderProgramColorTexture2 = new ShaderProgram();
+ shaderProgramColorTexture2.add(vp);
+ shaderProgramColorTexture2.add(fp);
+ if(!shaderProgramColorTexture2.link(gl, System.err)) {
+ throw new GLException("Couldn't link VertexColorTexture2 program: "+shaderProgramColorTexture2);
+ }
+ } else if( loadColorTexture4 ) {
+ customizeShader(gl, vp, fp, constMaxTextures4);
+ shaderProgramColorTexture4 = new ShaderProgram();
+ shaderProgramColorTexture4.add(vp);
+ shaderProgramColorTexture4.add(fp);
+ if(!shaderProgramColorTexture4.link(gl, System.err)) {
+ throw new GLException("Couldn't link VertexColorTexture4 program: "+shaderProgramColorTexture4);
+ }
+ } else if( loadColorTexture8 ) {
+ customizeShader(gl, vp, fp, constMaxTextures8);
+ shaderProgramColorTexture8 = new ShaderProgram();
+ shaderProgramColorTexture8.add(vp);
+ shaderProgramColorTexture8.add(fp);
+ if(!shaderProgramColorTexture8.link(gl, System.err)) {
+ throw new GLException("Couldn't link VertexColorTexture8 program: "+shaderProgramColorTexture8);
+ }
+ }
+ } else if( loadColorLightPerVertex ) {
+ final ShaderCode vp = ShaderCode.create( gl, GL2ES2.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot,
+ shaderBinRoot, vertexColorLightFile, true);
+ final ShaderCode fp = ShaderCode.create( gl, GL2ES2.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot,
+ shaderBinRoot, fragmentColorFile, true);
+ customizeShader(gl, vp, fp, constMaxTextures0);
+ shaderProgramColorLight = new ShaderProgram();
+ shaderProgramColorLight.add(vp);
+ shaderProgramColorLight.add(fp);
+ if(!shaderProgramColorLight.link(gl, System.err)) {
+ throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorLight);
+ }
+ } else if( loadColorTexture8LightPerVertex ) {
+ final ShaderCode vp = ShaderCode.create( gl, GL2ES2.GL_VERTEX_SHADER, shaderRootClass, shaderSrcRoot,
+ shaderBinRoot, vertexColorLightFile, true);
+ final ShaderCode fp = ShaderCode.create( gl, GL2ES2.GL_FRAGMENT_SHADER, shaderRootClass, shaderSrcRoot,
+ shaderBinRoot, fragmentColorTextureFile, true);
+ customizeShader(gl, vp, fp, constMaxTextures8);
+ shaderProgramColorTexture8Light = new ShaderProgram();
+ shaderProgramColorTexture8Light.add(vp);
+ shaderProgramColorTexture8Light.add(fp);
+ if(!shaderProgramColorTexture8Light.link(gl, System.err)) {
+ throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorTexture8Light);
+ }
}
+ }
- shaderProgramColorLight = new ShaderProgram();
- shaderProgramColorLight.add(vertexColorLight);
- shaderProgramColorLight.add(fragmentColor);
- if(!shaderProgramColorLight.link(gl, System.err)) {
- throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorLight);
+ private ShaderProgram selectShaderProgram(final GL2ES2 gl, ShaderSelectionMode newMode) {
+ if(ShaderSelectionMode.AUTO == newMode) {
+ newMode = ShaderSelectionMode.COLOR;
}
+ loadShader(gl, newMode);
+ final ShaderProgram sp;
+ switch(newMode) {
+ case COLOR_LIGHT_PER_VERTEX:
+ sp = shaderProgramColorLight;
+ break;
+ case COLOR_TEXTURE2:
+ sp = shaderProgramColorTexture2;
+ break;
+ case COLOR_TEXTURE4:
+ sp = shaderProgramColorTexture4;
+ break;
+ case COLOR_TEXTURE8:
+ sp = shaderProgramColorTexture8;
+ break;
+ case COLOR_TEXTURE8_LIGHT_PER_VERTEX:
+ sp = shaderProgramColorTexture8Light;
+ break;
+ case COLOR:
+ default:
+ sp = shaderProgramColor;
+ }
+ currentShaderSelectionMode = newMode;
+ return sp;
+ }
- shaderProgramColorTextureLight = new ShaderProgram();
- shaderProgramColorTextureLight.add(vertexColorLight);
- shaderProgramColorTextureLight.add(fragmentColorTexture);
- if(!shaderProgramColorTextureLight.link(gl, System.err)) {
- throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorTextureLight);
+ private void init(final GL2ES2 gl, final ShaderSelectionMode mode, final PMVMatrix pmvMatrix) {
+ if(null==pmvMatrix) {
+ throw new GLException("PMVMatrix is null");
}
+ this.pmvMatrix=pmvMatrix;
+ this.requestedShaderSelectionMode = mode;
+ this.shaderState=new ShaderState();
+ this.shaderState.setVerbose(verbose);
- shaderState.attachShaderProgram(gl, shaderProgramColor, true);
+ shaderState.attachShaderProgram(gl, selectShaderProgram(gl, requestedShaderSelectionMode), true);
// mandatory ..
if(!shaderState.uniform(gl, new GLUniformData(mgl_PMVMatrix, 4, 4, pmvMatrix.glGetPMvMvitMatrixf()))) {
@@ -457,16 +1116,26 @@ public class FixedFuncPipeline {
}
shaderState.uniform(gl, new GLUniformData(mgl_ColorEnabled, 0));
- shaderState.uniform(gl, new GLUniformData(mgl_ColorStatic, 4, zero4f));
- shaderState.uniform(gl, new GLUniformData(mgl_TexCoordEnabled, 1, textureCoordsEnabled));
- shaderState.uniform(gl, new GLUniformData(mgl_ActiveTexture, activeTextureUnit));
- shaderState.uniform(gl, new GLUniformData(mgl_ActiveTextureIdx, activeTextureUnit));
+ shaderState.uniform(gl, new GLUniformData(mgl_ColorStatic, 4, colorStatic));
+
+ texID2Format.setKeyNotFoundValue(0);
+ shaderState.uniform(gl, new GLUniformData(mgl_TexCoordEnabled, 1, textureCoordEnabled));
+ shaderState.uniform(gl, new GLUniformData(mgl_TexEnvMode, 1, textureEnvMode));
+ shaderState.uniform(gl, new GLUniformData(mgl_TexFormat, 1, textureFormat));
+ shaderState.uniform(gl, new GLUniformData(mgl_TextureEnabled, 1, textureEnabled));
+ for(int i=0; i<MAX_TEXTURE_UNITS; i++) {
+ shaderState.uniform(gl, new GLUniformData(mgl_Texture+i, i));
+ }
shaderState.uniform(gl, new GLUniformData(mgl_ShadeModel, 0));
- shaderState.uniform(gl, new GLUniformData(mgl_CullFace, cullFace));
+ /** ES2 supports CullFace implicit
+ shaderState.uniform(gl, new GLUniformData(mgl_CullFace, cullFace)); */
+ shaderState.uniform(gl, new GLUniformData(mgl_AlphaTestFunc, alphaTestFunc));
+ shaderState.uniform(gl, new GLUniformData(mgl_AlphaTestRef, alphaTestRef));
+ shaderState.uniform(gl, new GLUniformData(mgl_PointParams, 4, pointParams));
for(int i=0; i<MAX_LIGHTS; i++) {
shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].ambient", 4, defAmbient));
- shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].diffuse", 4, defDiffuse));
- shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].specular", 4, defSpecular));
+ shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].diffuse", 4, 0==i ? one4f : defDiffuseN));
+ shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].specular", 4, 0==i ? one4f : defSpecularN));
shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].position", 4, defPosition));
shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].spotDirection", 3, defSpotDir));
shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].spotExponent", defSpotExponent));
@@ -475,6 +1144,7 @@ public class FixedFuncPipeline {
shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].linearAttenuation", defLinearAtten));
shaderState.uniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].quadraticAttenuation", defQuadraticAtten));
}
+ shaderState.uniform(gl, new GLUniformData(mgl_LightModel+".ambient", 4, defLightModelAmbient));
shaderState.uniform(gl, new GLUniformData(mgl_LightsEnabled, 1, lightsEnabled));
shaderState.uniform(gl, new GLUniformData(mgl_FrontMaterial+".ambient", 4, defMatAmbient));
shaderState.uniform(gl, new GLUniformData(mgl_FrontMaterial+".diffuse", 4, defMatDiffuse));
@@ -483,70 +1153,121 @@ public class FixedFuncPipeline {
shaderState.uniform(gl, new GLUniformData(mgl_FrontMaterial+".shininess", defMatShininess));
shaderState.useProgram(gl, false);
+ if(verbose) {
+ System.err.println("init: "+toString(null, DEBUG).toString());
+ }
}
- protected static final boolean DEBUG=false;
- protected boolean verbose=false;
+ private String toHexString(final int i) {
+ return "0x"+Integer.toHexString(i);
+ }
+
+ protected boolean verbose = DEBUG;
+
+ private final FloatBuffer colorStatic = Buffers.copyFloatBuffer(one4f);
+
+ private int activeTextureUnit=0;
+ private int clientActiveTextureUnit=0;
+ private final IntIntHashMap texID2Format = new IntIntHashMap();
+ private final int[] boundTextureObject = new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }; // per unit
+ private int textureEnabledBits = 0;
+ private final IntBuffer textureEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); // per unit
+ private boolean textureEnabledDirty = false;
+ private final IntBuffer textureCoordEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); // per unit
+ private boolean textureCoordEnabledDirty = false;
+ // textureEnvMode: 1 GL_ADD, 2 GL_MODULATE (default), 3 GL_DECAL, 4 GL_BLEND, 5 GL_REPLACE, 6 GL_COMBINE
+ private final IntBuffer textureEnvMode = Buffers.newDirectIntBuffer(new int[] { 2, 2, 2, 2, 2, 2, 2, 2 });
+ private boolean textureEnvModeDirty = false;
+ private final IntBuffer textureFormat = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); // per unit
+ private boolean textureFormatDirty = false;
+
+ /** ES2 supports CullFace implicit
+ private int cullFace=-2; // <=0 disabled, 1 GL_FRONT, 2 GL_BACK (default) and 3 GL_FRONT_AND_BACK
+ private boolean cullFaceDirty = false;
+ private static final String mgl_CullFace = "mgl_CullFace"; // 1i (lowp int) */
- protected boolean textureEnabled=false;
- protected IntBuffer textureCoordsEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 });
- protected boolean textureCoordsEnabledDirty = false;
- protected int activeTextureUnit=0;
+ private boolean colorVAEnabledDirty = false;
+ private boolean lightingEnabled=false;
+ private final IntBuffer lightsEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 });
+ private boolean lightsEnabledDirty = false;
- protected int cullFace=-2; // <=0 disabled, 1: front, 2: back (default, but disabled), 3: front & back
+ private boolean alphaTestDirty=false;
+ private int alphaTestFunc=-8; // <=0 disabled; 1 GL_NEVER, 2 GL_LESS, 3 GL_EQUAL, 4 GL_LEQUAL, 5 GL_GREATER, 6 GL_NOTEQUAL, 7 GL_GEQUAL, and 8 GL_ALWAYS (default)
+ private float alphaTestRef=0f;
- protected boolean lightingEnabled=false;
- protected IntBuffer lightsEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 });
- protected boolean lightsEnabledDirty = false;
+ private boolean pointParamsDirty = false;
+ /** ( pointSize, pointSmooth, attn. pointMinSize, attn. pointMaxSize ) , ( attenuation coefficients 1f 0f 0f, attenuation fade theshold 1f ) */
+ private final FloatBuffer pointParams = Buffers.newDirectFloatBuffer(new float[] { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f });
- protected PMVMatrix pmvMatrix;
- protected ShaderState shaderState;
- protected ShaderProgram shaderProgramColor;
- protected ShaderProgram shaderProgramColorTexture;
- protected ShaderProgram shaderProgramColorLight;
- protected ShaderProgram shaderProgramColorTextureLight;
+ private PMVMatrix pmvMatrix;
+ private ShaderState shaderState;
+ private ShaderProgram shaderProgramColor;
+ private ShaderProgram shaderProgramColorTexture2, shaderProgramColorTexture4, shaderProgramColorTexture8;
+ private ShaderProgram shaderProgramColorLight;
+ private ShaderProgram shaderProgramColorTexture8Light;
+ private ShaderProgram shaderProgramPoints;
+
+ private ShaderSelectionMode requestedShaderSelectionMode = ShaderSelectionMode.AUTO;
+ private ShaderSelectionMode currentShaderSelectionMode = requestedShaderSelectionMode;
// uniforms ..
- protected static final String mgl_PMVMatrix = "mgl_PMVMatrix"; // m4fv[4] - P, Mv, Mvi and Mvit
- protected static final String mgl_ColorEnabled = "mgl_ColorEnabled"; // 1i
- protected static final String mgl_ColorStatic = "mgl_ColorStatic"; // 4fv
-
- protected static final String mgl_LightSource = "mgl_LightSource"; // struct mgl_LightSourceParameters[MAX_LIGHTS]
- protected static final String mgl_FrontMaterial = "mgl_FrontMaterial"; // struct mgl_MaterialParameters
- protected static final String mgl_LightsEnabled = "mgl_LightsEnabled"; // int mgl_LightsEnabled[MAX_LIGHTS];
-
- protected static final String mgl_ShadeModel = "mgl_ShadeModel"; // 1i
-
- protected static final String mgl_TexCoordEnabled = "mgl_TexCoordEnabled"; // int mgl_TexCoordEnabled[MAX_TEXTURE_UNITS];
- protected static final String mgl_ActiveTexture = "mgl_ActiveTexture"; // 1i
- protected static final String mgl_ActiveTextureIdx = "mgl_ActiveTextureIdx";// 1i
-
- protected static final String mgl_CullFace = "mgl_CullFace"; // 1i
-
- protected static final FloatBuffer zero4f = Buffers.newDirectFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f, 0.0f });
-
- public static final FloatBuffer defAmbient = Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 0f, 1f });
- public static final FloatBuffer defDiffuse = zero4f;
- public static final FloatBuffer defSpecular= zero4f;
- public static final FloatBuffer defPosition= Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 1f, 0f });
- public static final FloatBuffer defSpotDir = Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, -1f });
- public static final float defSpotExponent = 0f;
- public static final float defSpotCutoff = 180f;
- public static final float defConstantAtten = 1f;
- public static final float defLinearAtten = 0f;
- public static final float defQuadraticAtten= 0f;
-
- public static final FloatBuffer defMatAmbient = Buffers.newDirectFloatBuffer(new float[] { 0.2f, 0.2f, 0.2f, 1.0f });
- public static final FloatBuffer defMatDiffuse = Buffers.newDirectFloatBuffer(new float[] { 0.8f, 0.8f, 0.8f, 1.0f });
- public static final FloatBuffer defMatSpecular= Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 0f, 1f});
- public static final FloatBuffer defMatEmission= Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 0f, 1f});
+ private static final String mgl_PMVMatrix = "mgl_PMVMatrix"; // m4fv[4] - P, Mv, Mvi and Mvit
+ private static final String mgl_ColorEnabled = "mgl_ColorEnabled"; // 1i
+ private static final String mgl_ColorStatic = "mgl_ColorStatic"; // 4fv
+
+ private static final String mgl_LightModel = "mgl_LightModel"; // struct mgl_LightModelParameters
+ private static final String mgl_LightSource = "mgl_LightSource"; // struct mgl_LightSourceParameters[MAX_LIGHTS]
+ private static final String mgl_FrontMaterial = "mgl_FrontMaterial"; // struct mgl_MaterialParameters
+ private static final String mgl_LightsEnabled = "mgl_LightsEnabled"; // int mgl_LightsEnabled[MAX_LIGHTS];
+
+ private static final String mgl_AlphaTestFunc = "mgl_AlphaTestFunc"; // 1i (lowp int)
+ private static final String mgl_AlphaTestRef = "mgl_AlphaTestRef"; // 1f
+ private static final String mgl_ShadeModel = "mgl_ShadeModel"; // 1i
+ private static final String mgl_PointParams = "mgl_PointParams"; // vec4[2]: { (sz, smooth, attnMinSz, attnMaxSz), (attnCoeff(3), attnFadeTs) }
+
+ private static final String mgl_TextureEnabled = "mgl_TextureEnabled"; // int mgl_TextureEnabled[MAX_TEXTURE_UNITS];
+ private static final String mgl_Texture = "mgl_Texture"; // sampler2D mgl_Texture<0..7>
+ private static final String mgl_TexCoordEnabled = "mgl_TexCoordEnabled"; // int mgl_TexCoordEnabled[MAX_TEXTURE_UNITS];
+ private static final String mgl_TexEnvMode = "mgl_TexEnvMode"; // int mgl_TexEnvMode[MAX_TEXTURE_UNITS];
+ private static final String mgl_TexFormat = "mgl_TexFormat"; // int mgl_TexFormat[MAX_TEXTURE_UNITS];
+
+ // private static final FloatBuffer zero4f = Buffers.newDirectFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f, 0.0f });
+ private static final FloatBuffer neut4f = Buffers.newDirectFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f, 1.0f });
+ private static final FloatBuffer one4f = Buffers.newDirectFloatBuffer(new float[] { 1.0f, 1.0f, 1.0f, 1.0f });
+
+ public static final FloatBuffer defAmbient = neut4f;
+ public static final FloatBuffer defDiffuseN = neut4f;
+ public static final FloatBuffer defSpecularN = neut4f;
+ public static final FloatBuffer defPosition = Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 1f, 0f });
+ public static final FloatBuffer defSpotDir = Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, -1f });
+ public static final float defSpotExponent = 0f;
+ public static final float defSpotCutoff = 180f;
+ public static final float defConstantAtten = 1f;
+ public static final float defLinearAtten = 0f;
+ public static final float defQuadraticAtten = 0f;
+
+ public static final FloatBuffer defLightModelAmbient = Buffers.newDirectFloatBuffer(new float[] { 0.2f, 0.2f, 0.2f, 1.0f });
+
+ public static final FloatBuffer defMatAmbient = Buffers.newDirectFloatBuffer(new float[] { 0.2f, 0.2f, 0.2f, 1.0f });
+ public static final FloatBuffer defMatDiffuse = Buffers.newDirectFloatBuffer(new float[] { 0.8f, 0.8f, 0.8f, 1.0f });
+ public static final FloatBuffer defMatSpecular = neut4f;
+ public static final FloatBuffer defMatEmission = neut4f;
public static final float defMatShininess = 0f;
- protected static final String vertexColorFileDef = "FixedFuncColor";
- protected static final String vertexColorLightFileDef = "FixedFuncColorLight";
- protected static final String fragmentColorFileDef = "FixedFuncColor";
- protected static final String fragmentColorTextureFileDef = "FixedFuncColorTexture";
- protected static final String shaderSrcRootDef = "shaders" ;
- protected static final String shaderBinRootDef = "shaders/bin" ;
+ private static final String vertexColorFileDef = "FixedFuncColor";
+ private static final String vertexColorLightFileDef = "FixedFuncColorLight";
+ private static final String fragmentColorFileDef = "FixedFuncColor";
+ private static final String fragmentColorTextureFileDef = "FixedFuncColorTexture";
+ private static final String shaderPointFileDef = "FixedFuncPoints";
+ private static final String shaderSrcRootDef = "shaders" ;
+ private static final String shaderBinRootDef = "shaders/bin" ;
+
+ private final Class<?> shaderRootClass;
+ private final String shaderSrcRoot;
+ private final String shaderBinRoot;
+ private final String vertexColorFile;
+ private final String vertexColorLightFile;
+ private final String fragmentColorFile;
+ private final String fragmentColorTextureFile;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp
index 408ff7251..22dd1e61a 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.fp
@@ -1,16 +1,32 @@
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
#include es_precision.glsl
#include mgl_uniform.glsl
#include mgl_varying.glsl
+#include mgl_alphatest.fp
+
void main (void)
{
- if( mgl_CullFace > 0 &&
- ( ( mgl_CullFace == 1 && gl_FrontFacing ) ||
- ( mgl_CullFace == 2 && !gl_FrontFacing ) ||
- ( mgl_CullFace == 3 ) ) ) {
- discard;
+ vec4 color = frontColor;
+
+ /** ES2 supports CullFace implicit ..
+ if( mgl_CullFace > 0 &&
+ ( ( MGL_FRONT == mgl_CullFace && gl_FrontFacing ) ||
+ ( MGL_BACK == mgl_CullFace && !gl_FrontFacing ) ||
+ ( MGL_FRONT_AND_BACK == mgl_CullFace ) ) ) {
+ DISCARD(color);
+ } */
+ if( mgl_AlphaTestFunc > 0 ) {
+ alphaTest(color);
}
- gl_FragColor = frontColor;
+ mgl_FragColor = color;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.vp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.vp
index 346e40196..f39fcfbd0 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.vp
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColor.vp
@@ -1,3 +1,9 @@
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
#include es_precision.glsl
#include mgl_const.glsl
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorLight.vp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorLight.vp
index 7ce1eedcf..942a540af 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorLight.vp
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorLight.vp
@@ -1,3 +1,9 @@
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
#include es_precision.glsl
#include mgl_lightdef.glsl
@@ -50,16 +56,18 @@ void main(void)
}
}
}
- ambient *= mgl_FrontMaterial.ambient;
- diffuse *= mgl_FrontMaterial.diffuse;
- specular *= mgl_FrontMaterial.specular;
-
if(mgl_ColorEnabled>0) {
frontColor=mgl_Color;
} else {
frontColor=mgl_ColorStatic;
}
if( lightEnabled ) {
+ // light-ambient + global-ambient
+ // ( mgl_LightSource[0..n].ambient * mgl_FrontMaterial.ambient ) + ( mgl_LightModel.ambient * mgl_FrontMaterial.ambient )
+ ambient = ( ambient + mgl_LightModel.ambient ) * mgl_FrontMaterial.ambient;
+ diffuse *= mgl_FrontMaterial.diffuse;
+ specular *= mgl_FrontMaterial.specular;
+
frontColor *= ambient + diffuse + specular;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp
index 86e6ace73..130711e19 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncColorTexture.fp
@@ -1,4 +1,13 @@
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+
#include es_precision.glsl
#include mgl_lightdef.glsl
@@ -6,42 +15,103 @@
#include mgl_uniform.glsl
#include mgl_varying.glsl
-vec4 getTexColor(in sampler2D tex, in int idx) {
- vec4 coord;
- if(idx==0) {
- coord= mgl_TexCoords[0];
- } else if(idx==1) {
- coord= mgl_TexCoords[1];
- } else if(idx==2) {
- coord= mgl_TexCoords[2];
- } else if(idx==3) {
- coord= mgl_TexCoords[3];
- } else if(idx==4) {
- coord= mgl_TexCoords[4];
- } else if(idx==5) {
- coord= mgl_TexCoords[5];
- } else if(idx==6) {
- coord= mgl_TexCoords[6];
- } else {
- coord= mgl_TexCoords[7];
+#include mgl_alphatest.fp
+
+const float gamma = 1.5; // FIXME
+const vec3 igammav = vec3(1.0 / gamma); // FIXME
+const vec4 texEnvColor = vec4(0.0); // FIXME
+
+const vec4 zerov4 = vec4(0.0);
+const vec4 onev4 = vec4(1.0);
+
+void calcTexColor(inout vec4 color, vec4 texColor, in int texFormat, in int texEnvMode) {
+ if(MGL_MODULATE == texEnvMode) { // default
+ if( 4 == texFormat ) {
+ color *= texColor;
+ } else {
+ color.rgb *= texColor.rgb;
+ }
+ } else if(MGL_REPLACE == texEnvMode) {
+ if( 4 == texFormat ) {
+ color = texColor;
+ } else {
+ color.rgb = texColor.rgb;
+ }
+ } else if(MGL_ADD == texEnvMode) {
+ if( 4 == texFormat ) {
+ color += texColor;
+ } else {
+ color.rgb += texColor.rgb;
+ }
+ } else if(MGL_BLEND == texEnvMode) {
+ color.rgb = mix(color.rgb, texEnvColor.rgb, texColor.rgb);
+ if( 4 == texFormat ) {
+ color.a *= texColor.a;
+ }
+ } else if(MGL_DECAL == texEnvMode) {
+ if( 4 == texFormat ) {
+ color.rgb = mix(color.rgb, texColor.rgb, texColor.a);
+ } else {
+ color.rgb = texColor.rgb;
+ }
}
- return texture2D(tex, coord.st);
+ color = clamp(color, zerov4, onev4);
}
void main (void)
-{
- if( mgl_CullFace > 0 &&
- ( ( mgl_CullFace == 1 && gl_FrontFacing ) ||
- ( mgl_CullFace == 2 && !gl_FrontFacing ) ||
- ( mgl_CullFace == 3 ) ) ) {
- discard;
- }
-
- vec4 texColor = getTexColor(mgl_ActiveTexture,mgl_ActiveTextureIdx);
-
- if(length(texColor.rgb)>0.0) {
- gl_FragColor = vec4(frontColor.rgb*texColor.rgb, frontColor.a) ;
+{
+ vec4 color = frontColor;
+
+ /** ES2 supports CullFace implicit ..
+ if( mgl_CullFace > 0 &&
+ ( ( MGL_FRONT == mgl_CullFace && gl_FrontFacing ) ||
+ ( MGL_BACK == mgl_CullFace && !gl_FrontFacing ) ||
+ ( MGL_FRONT_AND_BACK == mgl_CullFace ) ) ) {
+ DISCARD(color);
+ } else { */
+ #if MAX_TEXTURE_UNITS >= 2
+ if( 0 != mgl_TextureEnabled[0] ) {
+ calcTexColor(color, texture2D(mgl_Texture0, mgl_TexCoords[0].st), mgl_TexFormat[0], mgl_TexEnvMode[0]);
+ }
+ if( 0 != mgl_TextureEnabled[1] ) {
+ calcTexColor(color, texture2D(mgl_Texture1, mgl_TexCoords[1].st), mgl_TexFormat[1], mgl_TexEnvMode[1]);
+ }
+ #endif
+ #if MAX_TEXTURE_UNITS >= 4
+ if( 0 != mgl_TextureEnabled[2] ) {
+ calcTexColor(color, texture2D(mgl_Texture2, mgl_TexCoords[2].st), mgl_TexFormat[2], mgl_TexEnvMode[2]);
+ }
+ if( 0 != mgl_TextureEnabled[3] ) {
+ calcTexColor(color, texture2D(mgl_Texture3, mgl_TexCoords[3].st), mgl_TexFormat[3], mgl_TexEnvMode[3]);
+ }
+ #endif
+ #if MAX_TEXTURE_UNITS >= 8
+ if( 0 != mgl_TextureEnabled[4] ) {
+ calcTexColor(color, texture2D(mgl_Texture4, mgl_TexCoords[4].st), mgl_TexFormat[4], mgl_TexEnvMode[4]);
+ }
+ if( 0 != mgl_TextureEnabled[5] ) {
+ calcTexColor(color, texture2D(mgl_Texture5, mgl_TexCoords[5].st), mgl_TexFormat[5], mgl_TexEnvMode[5]);
+ }
+ if( 0 != mgl_TextureEnabled[6] ) {
+ calcTexColor(color, texture2D(mgl_Texture6, mgl_TexCoords[6].st), mgl_TexFormat[6], mgl_TexEnvMode[6]);
+ }
+ if( 0 != mgl_TextureEnabled[7] ) {
+ calcTexColor(color, texture2D(mgl_Texture7, mgl_TexCoords[7].st), mgl_TexFormat[7], mgl_TexEnvMode[7]);
+ }
+ #endif
+ if( mgl_AlphaTestFunc > 0 ) {
+ alphaTest(color);
+ }
+ // } /* CullFace */
+
+ mgl_FragColor = color;
+ /**
+ // simple alpha check
+ if (color.a != 0.0) {
+ mgl_FragColor = vec4(pow(color.rgb, igammav), color.a);
} else {
- gl_FragColor = frontColor;
- }
+ // discard; // freezes NV tegra2 compiler
+ mgl_FragColor = color;
+ } */
}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.fp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.fp
new file mode 100644
index 000000000..2d58f2320
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.fp
@@ -0,0 +1,47 @@
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+
+#include es_precision.glsl
+#include mgl_lightdef.glsl
+
+#include mgl_const.glsl
+#include mgl_uniform.glsl
+#include mgl_varying.glsl
+
+// #define TEST 1
+
+void main (void)
+{
+ mgl_FragColor = frontColor;
+
+ if( pointSmooth > 0.5 ) {
+ // smooth (AA)
+ const float border = 0.90; // take/give 10% for AA
+
+ // origin to 0/0, [-1/-1 .. 1/1]
+ vec2 pointPos = 2.0 * gl_PointCoord - 1.0 ;
+ float r = length( pointPos ); // one-circle sqrt(x * x + y * y), range: in-circle [0..1], out >1
+ float r1 = 1.0 - ( step(border, r) * 10.0 * ( r - border ) ) ; // [0..1]
+ #ifndef TEST
+ if( r1 < 0.0 ) {
+ discard;
+ }
+ #endif
+
+ #ifndef TEST
+ mgl_FragColor.a *= r1;
+ #else
+ mgl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ mgl_FragColor.r = r1 < 0.0 ? 1.0 : 0.0;
+ mgl_FragColor.g = r > 1.0 ? 1.0 : 0.0;
+ mgl_FragColor.b = r > border ? 1.0 : 0.0;
+ #endif
+ }
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.vp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.vp
new file mode 100644
index 000000000..4a5d93a3d
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/FixedFuncPoints.vp
@@ -0,0 +1,40 @@
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+#include es_precision.glsl
+
+#include mgl_const.glsl
+#include mgl_uniform.glsl
+#include mgl_attribute.glsl
+#include mgl_varying.glsl
+
+#include mgl_settexcoord.vp
+
+void main(void)
+{
+ if( mgl_ColorEnabled > 0 ) {
+ frontColor = mgl_Color;
+ } else {
+ frontColor = mgl_ColorStatic;
+ }
+
+ vec4 eyeCoord = mgl_PMVMatrix[1] * mgl_Vertex;
+ gl_Position = mgl_PMVMatrix[0] * eyeCoord;
+
+ float dist = distance(eyeCoord, vec4(0.0, 0.0, 0.0, 1.0));
+ float atten = sqrt( 1.0 / ( pointDistanceConstantAtten +
+ ( pointDistanceLinearAtten +
+ pointDistanceQuadraticAtten * dist
+ ) * dist
+ )
+ );
+ float size = clamp(pointSize * atten, pointSizeMin, pointSizeMax);
+ gl_PointSize = max(size, pointFadeThresholdSize);
+
+ float fade = min(size, pointFadeThresholdSize) / pointFadeThresholdSize;
+ frontColor.a *= fade * fade;
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_alphatest.fp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_alphatest.fp
new file mode 100644
index 000000000..2b64cdeb8
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_alphatest.fp
@@ -0,0 +1,33 @@
+
+void alphaTest(inout vec4 color) {
+ if( MGL_GREATER == mgl_AlphaTestFunc ) {
+ if ( color.a <= mgl_AlphaTestRef ) {
+ DISCARD(color);
+ }
+ } else if( MGL_LESS == mgl_AlphaTestFunc ) {
+ if ( color.a >= mgl_AlphaTestRef ) {
+ DISCARD(color);
+ }
+ } else if( MGL_LEQUAL == mgl_AlphaTestFunc ) {
+ if ( color.a > mgl_AlphaTestRef ) {
+ DISCARD(color);
+ }
+ } else if( MGL_GEQUAL == mgl_AlphaTestFunc ) {
+ if ( color.a < mgl_AlphaTestRef ) {
+ DISCARD(color);
+ }
+ } else if( MGL_EQUAL == mgl_AlphaTestFunc ) {
+ if ( abs( color.a - mgl_AlphaTestRef ) > EPSILON ) {
+ DISCARD(color);
+ }
+ } else if( MGL_NOTEQUAL == mgl_AlphaTestFunc ) {
+ if ( abs( color.a - mgl_AlphaTestRef ) <= EPSILON ) {
+ DISCARD(color);
+ }
+ } else if( MGL_NEVER == mgl_AlphaTestFunc ) {
+ DISCARD(color);
+ } /* else if( MGL_ALWAYS == mgl_AlphaTestFunc ) {
+ // NOP
+ } */
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_attribute.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_attribute.glsl
index 09a11ec95..f670f7b77 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_attribute.glsl
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_attribute.glsl
@@ -4,16 +4,22 @@
#include es_precision.glsl
-attribute HIGHP vec4 mgl_Vertex;
-attribute HIGHP vec4 mgl_Normal;
-attribute HIGHP vec4 mgl_Color;
-attribute HIGHP vec4 mgl_MultiTexCoord0;
-attribute HIGHP vec4 mgl_MultiTexCoord1;
-attribute HIGHP vec4 mgl_MultiTexCoord2;
-attribute HIGHP vec4 mgl_MultiTexCoord3;
-attribute HIGHP vec4 mgl_MultiTexCoord4;
-attribute HIGHP vec4 mgl_MultiTexCoord5;
-attribute HIGHP vec4 mgl_MultiTexCoord6;
-attribute HIGHP vec4 mgl_MultiTexCoord7;
+attribute vec4 mgl_Vertex;
+attribute vec4 mgl_Normal;
+attribute vec4 mgl_Color;
+#if MAX_TEXTURE_UNITS >= 2
+attribute vec4 mgl_MultiTexCoord0;
+attribute vec4 mgl_MultiTexCoord1;
+#endif
+#if MAX_TEXTURE_UNITS >= 4
+attribute vec4 mgl_MultiTexCoord2;
+attribute vec4 mgl_MultiTexCoord3;
+#endif
+#if MAX_TEXTURE_UNITS >= 8
+attribute vec4 mgl_MultiTexCoord4;
+attribute vec4 mgl_MultiTexCoord5;
+attribute vec4 mgl_MultiTexCoord6;
+attribute vec4 mgl_MultiTexCoord7;
+#endif
#endif // mgl_attribute_glsl
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_const.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_const.glsl
index 1a464a1cb..4f97292e3 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_const.glsl
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_const.glsl
@@ -4,7 +4,36 @@
#include es_precision.glsl
-const LOWP int MAX_TEXTURE_UNITS = 8; // <=gl_MaxTextureImageUnits
+// will be defined at runtime: MAX_TEXTURE_UNITS [0|2|4|8]
const LOWP int MAX_LIGHTS = 8;
+const float EPSILON = 0.0000001; // FIXME: determine proper hw-precision
+
+// discard freezes NV tegra2 compiler (STILL TRUE?)
+// #define DISCARD(c) (c.a = 0.0)
+#define DISCARD(c) discard
+
+// Texture Environment / Multi Texturing
+#define MGL_ADD 1
+#define MGL_MODULATE 2
+#define MGL_DECAL 3
+#define MGL_BLEND 4
+#define MGL_REPLACE 5
+#define MGL_COMBINE 6
+
+// Alpha Test
+#define MGL_NEVER 1
+#define MGL_LESS 2
+#define MGL_EQUAL 3
+#define MGL_LEQUAL 4
+#define MGL_GREATER 5
+#define MGL_NOTEQUAL 6
+#define MGL_GEQUAL 7
+#define MGL_ALWAYS 8
+
+// Cull Face
+#define MGL_FRONT 1
+#define MGL_BACK 2
+#define MGL_FRONT_AND_BACK 3
+
#endif // mgl_const_glsl
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_lightdef.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_lightdef.glsl
index 98e214139..deaf95408 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_lightdef.glsl
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_lightdef.glsl
@@ -1,6 +1,9 @@
#ifndef mgl_lightdef_glsl
#define mgl_lightdef_glsl
+struct mgl_LightModelParameters {
+ vec4 ambient;
+};
struct mgl_LightSourceParameters {
vec4 ambient;
vec4 diffuse;
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_settexcoord.vp b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_settexcoord.vp
index 1efe328d0..cbf0db642 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_settexcoord.vp
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_settexcoord.vp
@@ -22,14 +22,20 @@ void setTexCoord(in vec4 defpos) {
mgl_TexCoords[7] = ( 0 != (mgl_TexCoordEnabled & 128) ) ? mgl_MultiTexCoord7 : defpos;
*/
+ #if MAX_TEXTURE_UNITS >= 2
mgl_TexCoords[0] = ( 0 != mgl_TexCoordEnabled[0] ) ? mgl_MultiTexCoord0 : defpos;
mgl_TexCoords[1] = ( 0 != mgl_TexCoordEnabled[1] ) ? mgl_MultiTexCoord1 : defpos;
+ #endif
+ #if MAX_TEXTURE_UNITS >= 4
mgl_TexCoords[2] = ( 0 != mgl_TexCoordEnabled[2] ) ? mgl_MultiTexCoord2 : defpos;
mgl_TexCoords[3] = ( 0 != mgl_TexCoordEnabled[3] ) ? mgl_MultiTexCoord3 : defpos;
+ #endif
+ #if MAX_TEXTURE_UNITS >= 8
mgl_TexCoords[4] = ( 0 != mgl_TexCoordEnabled[4] ) ? mgl_MultiTexCoord4 : defpos;
mgl_TexCoords[5] = ( 0 != mgl_TexCoordEnabled[5] ) ? mgl_MultiTexCoord5 : defpos;
mgl_TexCoords[6] = ( 0 != mgl_TexCoordEnabled[6] ) ? mgl_MultiTexCoord6 : defpos;
mgl_TexCoords[7] = ( 0 != mgl_TexCoordEnabled[7] ) ? mgl_MultiTexCoord7 : defpos;
+ #endif
}
#endif // mgl_settexcoord_vp
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform.glsl
index 4c4000dfa..5029e4bd8 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform.glsl
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform.glsl
@@ -6,12 +6,45 @@
#include mgl_const.glsl
-uniform HIGHP mat4 mgl_PMVMatrix[4]; // P, Mv, Mvi and Mvit (transpose(inverse(ModelView)) == normalMatrix)
+uniform mat4 mgl_PMVMatrix[4]; // P, Mv, Mvi and Mvit (transpose(inverse(ModelView)) == normalMatrix)
uniform LOWP int mgl_ColorEnabled;
-uniform HIGHP vec4 mgl_ColorStatic;
+uniform vec4 mgl_ColorStatic;
+uniform LOWP int mgl_AlphaTestFunc;
+uniform float mgl_AlphaTestRef;
+
+// [0].rgba: size, smooth, attnMinSz, attnMaxSz
+// [1].rgba: attnCoeff(3), attnFadeTs
+uniform MEDIUMP vec4 mgl_PointParams[2];
+
+#define pointSize (mgl_PointParams[0].r)
+#define pointSmooth (mgl_PointParams[0].g)
+#define pointSizeMin (mgl_PointParams[0].b)
+#define pointSizeMax (mgl_PointParams[0].a)
+#define pointDistanceConstantAtten (mgl_PointParams[1].r)
+#define pointDistanceLinearAtten (mgl_PointParams[1].g)
+#define pointDistanceQuadraticAtten (mgl_PointParams[1].b)
+#define pointFadeThresholdSize (mgl_PointParams[1].a)
+
+// uniform LOWP int mgl_CullFace; // ES2 supports CullFace implicit ..
+#if MAX_TEXTURE_UNITS > 0
+uniform LOWP int mgl_TextureEnabled[MAX_TEXTURE_UNITS];
uniform LOWP int mgl_TexCoordEnabled[MAX_TEXTURE_UNITS];
-uniform sampler2D mgl_ActiveTexture;
-uniform LOWP int mgl_ActiveTextureIdx;
-uniform LOWP int mgl_CullFace;
+uniform LOWP int mgl_TexEnvMode[MAX_TEXTURE_UNITS];
+uniform LOWP int mgl_TexFormat[MAX_TEXTURE_UNITS];
+#if MAX_TEXTURE_UNITS >= 2
+uniform sampler2D mgl_Texture0;
+uniform sampler2D mgl_Texture1;
+#endif
+#if MAX_TEXTURE_UNITS >= 4
+uniform sampler2D mgl_Texture2;
+uniform sampler2D mgl_Texture3;
+#endif
+#if MAX_TEXTURE_UNITS >= 8
+uniform sampler2D mgl_Texture4;
+uniform sampler2D mgl_Texture5;
+uniform sampler2D mgl_Texture6;
+uniform sampler2D mgl_Texture7;
+#endif
+#endif
#endif // mgl_uniform_glsl
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform_light.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform_light.glsl
index 0dedb5d5d..5b34fd9cf 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform_light.glsl
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_uniform_light.glsl
@@ -9,6 +9,7 @@
uniform LOWP int mgl_LightsEnabled[MAX_LIGHTS];
+uniform mgl_LightModelParameters mgl_LightModel;
uniform mgl_LightSourceParameters mgl_LightSource[MAX_LIGHTS];
uniform mgl_MaterialParameters mgl_FrontMaterial;
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_varying.glsl b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_varying.glsl
index fc9f735d1..599ac4a53 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_varying.glsl
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/shaders/mgl_varying.glsl
@@ -7,6 +7,8 @@
#include mgl_const.glsl
varying vec4 frontColor;
+#if MAX_TEXTURE_UNITS > 0
varying vec4 mgl_TexCoords[MAX_TEXTURE_UNITS];
+#endif
#endif // mgl_varying_glsl
diff --git a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
new file mode 100644
index 000000000..e3e43b30c
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
@@ -0,0 +1,1520 @@
+/**
+ * Original JavaScript code from <https://github.com/notmasteryet/jpgjs/blob/master/jpg.js>,
+ * ported to Java for JogAmp Community.
+ *
+ * Enhancements:
+ * * InputStream instead of memory buffer
+ * * User provided memory handler
+ * * Fixed JPEG Component ID/Index mapping
+ * * Color space conversion (YCCK, CMYK -> RGB)
+ * * More error tolerant
+ *
+ * *****************
+ *
+ * Copyright 2011 notmasteryet
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************
+ *
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.opengl.util.jpeg;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import jogamp.opengl.Debug;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.Bitstream;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureData.ColorSpace;
+
+/**
+ *
+ * <ul>
+ * <li> The JPEG specification can be found in the ITU CCITT Recommendation T.81
+ * (www.w3.org/Graphics/JPEG/itu-t81.pdf) </li>
+ * <li> The JFIF specification can be found in the JPEG File Interchange Format
+ * (www.w3.org/Graphics/JPEG/jfif3.pdf)</li>
+ * <li> The Adobe Application-Specific JPEG markers in the Supporting the DCT Filters
+ * in PostScript Level 2, Technical Note #5116
+ * (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)</li>
+ * <li> http://halicery.com/jpeg/huffman.html </li>
+ * <li> https://en.wikipedia.org/wiki/Jpg#Syntax_and_structure </li>
+ * <li> http://www.cs.sfu.ca/CourseCentral/365/mark/material/notes/Chap4/Chap4.2/Chap4.2.html </li>
+ * <li> https://github.com/notmasteryet/jpgjs/blob/master/jpg.js </li>
+ * </ul>
+ */
+public class JPEGDecoder {
+ private static final boolean DEBUG = Debug.debug("JPEGImage");
+ private static final boolean DEBUG_IN = false;
+
+ /** Allows user to hook a {@link ColorSink} to another toolkit to produce {@link TextureData}. */
+ public static interface ColorSink {
+ /**
+ * @param width
+ * @param height
+ * @param sourceCS the color-space of the decoded JPEG
+ * @param sourceComponents number of components used for the given source color-space
+ * @return Either {@link TextureData.ColorSpace#RGB} or {@link TextureData.ColorSpace#YCbCr}. {@link TextureData.ColorSpace#YCCK} and {@link TextureData.ColorSpace#CMYK} will throw an exception!
+ * @throws RuntimeException
+ */
+ public TextureData.ColorSpace allocate(int width, int height, TextureData.ColorSpace sourceCS, int sourceComponents) throws RuntimeException;
+ public void store2(int x, int y, byte c1, byte c2);
+ public void storeRGB(int x, int y, byte r, byte g, byte b);
+ public void storeYCbCr(int x, int y, byte Y, byte Cb, byte Cr);
+ }
+
+ public static class JFIF {
+ final VersionNumber version;
+ final int densityUnits;
+ final int xDensity;
+ final int yDensity;
+ final int thumbWidth;
+ final int thumbHeight;
+ final byte[] thumbData;
+
+ private JFIF(final byte data[]) {
+ version = new VersionNumber(data[5], data[6], 0);
+ densityUnits = data[7];
+ xDensity = ((data[ 8] << 8) & 0xff00) | (data[ 9] & 0xff);
+ yDensity = ((data[10] << 8) & 0xff00) | (data[11] & 0xff);
+ thumbWidth = data[12];
+ thumbHeight = data[13];
+ if( 0 < thumbWidth && 0 < thumbHeight ) {
+ final int len = 14 + 3 * thumbWidth * thumbHeight;
+ thumbData = new byte[len];
+ System.arraycopy(data, 14, thumbData, 0, len);
+ } else {
+ thumbData = null;
+ }
+ }
+
+ public static final JFIF get(final byte[] data) throws RuntimeException {
+ if ( data[0] == (byte)0x4A && data[1] == (byte)0x46 && data[2] == (byte)0x49 &&
+ data[3] == (byte)0x46 && data[4] == (byte)0x0) { // 'JFIF\x00'
+ final JFIF r = new JFIF(data);
+ return r;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public final String toString() {
+ return "JFIF[ver "+version+", density[units "+densityUnits+", "+xDensity+"x"+yDensity+"], thumb "+thumbWidth+"x"+thumbHeight+"]";
+ }
+ }
+
+ public static class Adobe {
+ final short version;
+ final short flags0;
+ final short flags1;
+ final short colorCode;
+ final ColorSpace colorSpace;
+
+ private Adobe(final byte[] data) {
+ version = data[6];
+ flags0 = (short)(((data[7] << 8) & 0xff00) | (data[ 8] & 0xff));
+ flags1 = (short)(((data[9] << 8) & 0xff00) | (data[10] & 0xff));
+ colorCode = data[11];
+ switch( colorCode ) {
+ case 2: colorSpace = ColorSpace.YCCK; break;
+ case 1: colorSpace = ColorSpace.YCbCr; break;
+ default: colorSpace = ColorSpace.CMYK; break;
+ }
+ }
+ public static final Adobe get(final byte[] data) throws RuntimeException {
+ if (data[0] == (byte)0x41 && data[1] == (byte)0x64 && data[2] == (byte)0x6F &&
+ data[3] == (byte)0x62 && data[4] == (byte)0x65 && data[5] == (byte)0) { // 'Adobe\x00'
+ final Adobe r = new Adobe(data);
+ return r;
+ } else {
+ return null;
+ }
+ }
+ @Override
+ public final String toString() {
+ return "Adobe[ver "+version+", flags["+toHexString(flags0)+", "+toHexString(flags1)+"], colorSpace/Code "+colorSpace+"/"+toHexString(colorCode)+"]";
+ }
+ }
+ /** TODO */
+ public static class EXIF {
+ private EXIF(final byte data[]) {
+ }
+
+ public static final EXIF get(final byte[] data) throws RuntimeException {
+ if ( data[0] == (byte)0x45 && data[1] == (byte)0x78 && data[2] == (byte)0x69 &&
+ data[3] == (byte)0x66 && data[4] == (byte)0x0) { // 'Exif\x00'
+ final EXIF r = new EXIF(data);
+ return r;
+ } else {
+ return null;
+ }
+ }
+ @Override
+ public final String toString() {
+ return "EXIF[]";
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class CodecException extends RuntimeException {
+ CodecException(final String message) {
+ super(message);
+ }
+ }
+ @SuppressWarnings("serial")
+ public static class MarkerException extends CodecException {
+ final int marker;
+ MarkerException(final int marker, final String message) {
+ super(message+" - Marker "+toHexString(marker));
+ this.marker = marker;
+ }
+ public int getMarker() { return marker; }
+ }
+
+ /** Start of Image */
+ private static final int M_SOI = 0xFFD8;
+ /** End of Image */
+ private static final int M_EOI = 0xFFD9;
+ /** Start of Frame - Baseline DCT */
+ private static final int M_SOF0 = 0xFFC0;
+ /** Start of Frame - Extended sequential DCT */
+ // private static final int M_SOF1 = 0xFFC1;
+ /** Start of Frame - Progressive DCT */
+ private static final int M_SOF2 = 0xFFC2;
+ /** DHT (Define Huffman Tables) */
+ private static final int M_DHT = 0xFFC4;
+ // private static final int M_DAC = 0xFFCC;
+ /** SOS (Start of Scan) */
+ private static final int M_SOS = 0xFFDA;
+ /** DQT (Define Quantization Tables) */
+ private static final int M_QTT = 0xFFDB;
+ /** DRI (Define Restart Interval) */
+ private static final int M_DRI = 0xFFDD;
+ /** APP0 (Application Specific) - JFIF Header */
+ private static final int M_APP00 = 0xFFE0;
+ /** APP1 (Application Specific) - Exif Header */
+ private static final int M_APP01 = 0xFFE1;
+ /** APP2 (Application Specific) */
+ private static final int M_APP02 = 0xFFE2;
+ /** APP3 (Application Specific) */
+ private static final int M_APP03 = 0xFFE3;
+ /** APP4 (Application Specific) */
+ private static final int M_APP04 = 0xFFE4;
+ /** APP5 (Application Specific) */
+ private static final int M_APP05 = 0xFFE5;
+ /** APP6 (Application Specific) */
+ private static final int M_APP06 = 0xFFE6;
+ /** APP7 (Application Specific) */
+ private static final int M_APP07 = 0xFFE7;
+ /** APP8 (Application Specific) */
+ private static final int M_APP08 = 0xFFE8;
+ /** APP9 (Application Specific) */
+ private static final int M_APP09 = 0xFFE9;
+ /** APP10 (Application Specific) */
+ private static final int M_APP10 = 0xFFEA;
+ /** APP11 (Application Specific) */
+ private static final int M_APP11 = 0xFFEB;
+ /** APP12 (Application Specific) */
+ private static final int M_APP12 = 0xFFEC;
+ /** APP13 (Application Specific) */
+ private static final int M_APP13 = 0xFFED;
+ /** APP14 (Application Specific) - ADOBE Header */
+ private static final int M_APP14 = 0xFFEE;
+ /** APP15 (Application Specific) */
+ private static final int M_APP15 = 0xFFEF;
+
+ /** Annotation / Comment */
+ private static final int M_ANO = 0xFFFE;
+
+ static final int[] dctZigZag = new int[] {
+ 0,
+ 1, 8,
+ 16, 9, 2,
+ 3, 10, 17, 24,
+ 32, 25, 18, 11, 4,
+ 5, 12, 19, 26, 33, 40,
+ 48, 41, 34, 27, 20, 13, 6,
+ 7, 14, 21, 28, 35, 42, 49, 56,
+ 57, 50, 43, 36, 29, 22, 15,
+ 23, 30, 37, 44, 51, 58,
+ 59, 52, 45, 38, 31,
+ 39, 46, 53, 60,
+ 61, 54, 47,
+ 55, 62,
+ 63
+ };
+
+ static final int dctCos1 = 4017; // cos(pi/16)
+ static final int dctSin1 = 799; // sin(pi/16)
+ static final int dctCos3 = 3406; // cos(3*pi/16)
+ static final int dctSin3 = 2276; // sin(3*pi/16)
+ static final int dctCos6 = 1567; // cos(6*pi/16)
+ static final int dctSin6 = 3784; // sin(6*pi/16)
+ static final int dctSqrt2 = 5793; // sqrt(2)
+ static final int dctSqrt1d2 = 2896; // sqrt(2) / 2
+
+ static class Frame {
+ final boolean progressive;
+ final int precision;
+ final int scanLines;
+ final int samplesPerLine;
+ private final ArrayHashSet<Integer> compIDs;
+ private final ComponentIn[] comps;
+ private final int compCount;
+ /** quantization tables */
+ final int[][] qtt;
+ int maxCompID;
+ int maxH;
+ int maxV;
+ int mcusPerLine;
+ int mcusPerColumn;
+
+ Frame(final boolean progressive, final int precision, final int scanLines, final int samplesPerLine, final int componentsCount, final int[][] qtt) {
+ this.progressive = progressive;
+ this.precision = precision;
+ this.scanLines = scanLines;
+ this.samplesPerLine = samplesPerLine;
+ compIDs = new ArrayHashSet<Integer>(componentsCount);
+ comps = new ComponentIn[componentsCount];
+ this.compCount = componentsCount;
+ this.qtt = qtt;
+ }
+
+ private final void checkBounds(final int idx) {
+ if( 0 > idx || idx >= compCount ) {
+ throw new CodecException("Idx out of bounds "+idx+", "+this);
+ }
+ }
+ public final void validateComponents() {
+ for(int i=0; i<compCount; i++) {
+ final ComponentIn c = comps[i];
+ if( null == c ) {
+ throw new CodecException("Component["+i+"] null");
+ }
+ if( null == this.qtt[c.qttIdx] ) {
+ throw new CodecException("Component["+i+"].qttIdx -> null QTT");
+ }
+ }
+ }
+
+ public final int getCompCount() { return compCount; }
+ public final int getMaxCompID() { return maxCompID; }
+
+ public final void putOrdered(final int compID, final ComponentIn component) {
+ if( maxCompID < compID ) {
+ maxCompID = compID;
+ }
+ final int idx = compIDs.size();
+ checkBounds(idx);
+ compIDs.add(compID);
+ comps[idx] = component;
+ }
+ public final ComponentIn getCompByIndex(final int i) {
+ checkBounds(i);
+ return comps[i];
+ }
+ public final ComponentIn getCompByID(final int componentID) {
+ return getCompByIndex( compIDs.indexOf(componentID) );
+ }
+ public final int getCompID(final int idx) {
+ return compIDs.get(idx);
+ }
+ public final boolean hasCompID(final int componentID) {
+ return compIDs.contains(componentID);
+ }
+ @Override
+ public final String toString() {
+ return "Frame[progressive "+progressive+", precision "+precision+", scanLines "+scanLines+", samplesPerLine "+samplesPerLine+
+ ", components[count "+compCount+", maxID "+maxCompID+", componentIDs "+compIDs+", comps "+Arrays.asList(comps)+"]]";
+ }
+ }
+
+ /** The JPEG encoded components */
+ static class ComponentIn {
+ final int h, v;
+ /** index to frame.qtt[] */
+ final int qttIdx;
+ int blocksPerColumn;
+ int blocksPerColumnForMcu;
+ int blocksPerLine;
+ int blocksPerLineForMcu;
+ /** [blocksPerColumnForMcu][blocksPerLineForMcu][64]; */
+ int[][][] blocks;
+ int pred;
+ BinObj huffmanTableAC;
+ BinObj huffmanTableDC;
+
+ ComponentIn(final int h, final int v, final int qttIdx) {
+ this.h = h;
+ this.v = v;
+ this.qttIdx = qttIdx;
+ }
+
+ public final void allocateBlocks(final int blocksPerColumn, final int blocksPerColumnForMcu, final int blocksPerLine, final int blocksPerLineForMcu) {
+ this.blocksPerColumn = blocksPerColumn;
+ this.blocksPerColumnForMcu = blocksPerColumnForMcu;
+ this.blocksPerLine = blocksPerLine;
+ this.blocksPerLineForMcu = blocksPerLineForMcu;
+ this.blocks = new int[blocksPerColumnForMcu][blocksPerLineForMcu][64];
+ }
+ public final int[] getBlock(final int row, final int col) {
+ if( row >= blocksPerColumnForMcu || col >= blocksPerLineForMcu ) {
+ throw new CodecException("Out of bounds given ["+row+"]["+col+"] - "+this);
+ }
+ return blocks[row][col];
+ }
+
+ @Override
+ public final String toString() {
+ return "CompIn[h "+h+", v "+v+", qttIdx "+qttIdx+", blocks["+blocksPerColumn+", mcu "+blocksPerColumnForMcu+"]["+blocksPerLine+", mcu "+blocksPerLineForMcu+"][64]]";
+ }
+ }
+
+ /** The decoded components */
+ static class ComponentOut {
+ private final ArrayList<byte[]> lines;
+ final float scaleX;
+ final float scaleY;
+
+ ComponentOut(final ArrayList<byte[]> lines, final float scaleX, final float scaleY) {
+ this.lines = lines;
+ this.scaleX = scaleX;
+ this.scaleY = scaleY;
+ }
+
+ /** Safely returning a line, if index exceeds number of lines, last line is returned. */
+ public final byte[] getLine(final int i) {
+ final int sz = lines.size();
+ return lines.get( i < sz ? i : sz - 1);
+ }
+
+ @Override
+ public final String toString() {
+ return "CompOut[lines "+lines.size()+", scale "+scaleX+"x"+scaleY+"]";
+ }
+ }
+
+ @Override
+ public String toString() {
+ final String jfifS = null != jfif ? jfif.toString() : "JFIF nil";
+ final String exifS = null != exif ? exif.toString() : "Exif nil";
+ final String adobeS = null != adobe ? adobe.toString() : "Adobe nil";
+ final String compOuts = null != components ? Arrays.asList(components).toString() : "nil";
+ return "JPEG[size "+width+"x"+height+", compOut "+compOuts+", "+jfifS+", "+exifS+", "+adobeS+"]";
+ }
+
+ private final Bitstream<InputStream> bstream = new Bitstream<InputStream>(new Bitstream.ByteInputStream(null), false /* outputMode */);
+
+ private int width = 0;
+ private int height = 0;
+ private JFIF jfif = null;
+ private EXIF exif = null;
+ private Adobe adobe = null;
+ private ComponentOut[] components = null;
+
+ public final JFIF getJFIFHeader() { return jfif; }
+ public final EXIF getEXIFHeader() { return exif; }
+ public final Adobe getAdobeHeader() { return adobe; }
+ public final int getWidth() { return width; }
+ public final int getHeight() { return height; }
+
+ private final void setStream(final InputStream is) {
+ try {
+ bstream.setStream(is, false /* outputMode */);
+ } catch (final Exception e) {
+ throw new RuntimeException(e); // should not happen, no flush()
+ }
+ }
+
+ private final int readUInt8() throws IOException {
+ return bstream.readUInt8(true /* msbFirst */);
+ }
+
+ private final int readUInt16() throws IOException {
+ return bstream.readUInt16(true /* msbFirst */, true /* bigEndian */);
+ }
+
+ private final int readNumber() throws IOException {
+ final int len=readUInt16();
+ if(len!=4){
+ throw new CodecException("ERROR: Define number format error [Len!=4, but "+len+"]");
+ }
+ return readUInt16();
+ }
+
+ private final byte[] readDataBlock() throws IOException {
+ int count=0, i=0;
+ final int len=readUInt16(); count+=2;
+ final byte[] data = new byte[len-2];
+ while(count<len){
+ data[i++] = (byte)readUInt8(); count++;
+ }
+ if(DEBUG_IN) { System.err.println("JPEG.readDataBlock: net-len "+(len-2)+", "+this); dumpData(data, 0, len-2); }
+ return data;
+ }
+ static final void dumpData(final byte[] data, final int offset, final int len) {
+ for(int i=0; i<len; ) {
+ System.err.print(i%8+": ");
+ for(int j=0; j<8 && i<len; j++, i++) {
+ System.err.print(toHexString(0x000000FF & data[offset+i])+", ");
+ }
+ System.err.println("");
+ }
+ }
+
+ public synchronized void clear(final InputStream inputStream) {
+ setStream(inputStream);
+ width = 0;
+ height = 0;
+ jfif = null;
+ exif = null;
+ adobe = null;
+ components = null;
+ }
+ public synchronized JPEGDecoder parse(final InputStream inputStream) throws IOException {
+ clear(inputStream);
+
+ final int[][] quantizationTables = new int[0x0F][]; // 4 bits
+ final BinObj[] huffmanTablesAC = new BinObj[0x0F]; // Huffman table spec - 4 bits
+ final BinObj[] huffmanTablesDC = new BinObj[0x0F]; // Huffman table spec - 4 bits
+ // final ArrayList<Frame> frames = new ArrayList<Frame>(); // JAU: max 1-frame
+
+ Frame frame = null;
+ int resetInterval = 0;
+ int fileMarker = readUInt16();
+ if ( fileMarker != M_SOI ) {
+ throw new CodecException("SOI not found, but has marker "+toHexString(fileMarker));
+ }
+
+ fileMarker = readUInt16();
+ while (fileMarker != M_EOI) {
+ if(DEBUG) { System.err.println("JPG.parse got marker "+toHexString(fileMarker)); }
+ switch(fileMarker) {
+ case M_APP00:
+ case M_APP01:
+ case M_APP02:
+ case M_APP03:
+ case M_APP04:
+ case M_APP05:
+ case M_APP06:
+ case M_APP07:
+ case M_APP08:
+ case M_APP09:
+ case M_APP10:
+ case M_APP11:
+ case M_APP12:
+ case M_APP13:
+ case M_APP14:
+ case M_APP15:
+ case M_ANO: {
+ final byte[] appData = readDataBlock();
+
+ if ( fileMarker == M_APP00 ) {
+ jfif = JFIF.get( appData );
+ }
+ if ( fileMarker == M_APP01 ) {
+ exif = EXIF.get(appData);
+ }
+ if (fileMarker == M_APP14) {
+ adobe = Adobe.get(appData);
+ }
+ fileMarker = 0; // consumed and get-next
+ }
+ break;
+
+ case M_QTT: {
+ int count = 0;
+ final int quantizationTablesLength = readUInt16(); count+=2;
+ while( count < quantizationTablesLength ) {
+ final int quantizationTableSpec = readUInt8(); count++;
+ final int precisionID = quantizationTableSpec >> 4;
+ final int tableIdx = quantizationTableSpec & 0x0F;
+ final int[] tableData = new int[64];
+ if ( precisionID == 0 ) { // 8 bit values
+ for (int j = 0; j < 64; j++) {
+ final int z = dctZigZag[j];
+ tableData[z] = readUInt8(); count++;
+ }
+ } else if ( precisionID == 1) { //16 bit
+ for (int j = 0; j < 64; j++) {
+ final int z = dctZigZag[j];
+ tableData[z] = readUInt16(); count+=2;
+ }
+ } else {
+ throw new CodecException("DQT: invalid table precision "+precisionID+", quantizationTableSpec "+quantizationTableSpec+", idx "+tableIdx);
+ }
+ quantizationTables[tableIdx] = tableData;
+ if( DEBUG ) {
+ System.err.println("JPEG.parse.QTT["+tableIdx+"]: spec "+quantizationTableSpec+", precision "+precisionID+", data "+count+"/"+quantizationTablesLength);
+ }
+ }
+ if(count!=quantizationTablesLength){
+ throw new CodecException("ERROR: QTT format error [count!=Length]: "+count+"/"+quantizationTablesLength);
+ }
+ fileMarker = 0; // consumed and get-next
+ }
+ break;
+
+ case M_SOF0:
+ case M_SOF2: {
+ if( null != frame ) { // JAU: max 1-frame
+ throw new CodecException("only single frame JPEGs supported");
+ }
+ int count = 0;
+ final int sofLen = readUInt16(); count+=2; // header length;
+ final int componentsCount;
+ {
+ final boolean progressive = (fileMarker == M_SOF2);
+ final int precision = readUInt8(); count++;
+ final int scanLines = readUInt16(); count+=2;
+ final int samplesPerLine = readUInt16(); count+=2;
+ componentsCount = readUInt8(); count++;
+ frame = new Frame(progressive, precision, scanLines, samplesPerLine, componentsCount, quantizationTables);
+ width = frame.samplesPerLine;
+ height = frame.scanLines;
+ }
+ for (int i = 0; i < componentsCount; i++) {
+ final int componentId = readUInt8(); count++;
+ final int temp = readUInt8(); count++;
+ final int h = temp >> 4;
+ final int v = temp & 0x0F;
+ final int qttIdx = readUInt8(); count++;
+ final ComponentIn compIn = new ComponentIn(h, v, qttIdx);
+ frame.putOrdered(componentId, compIn);
+ }
+ if(count!=sofLen){
+ throw new CodecException("ERROR: SOF format error [count!=Length]");
+ }
+ prepareComponents(frame);
+ // frames.add(frame); // JAU: max 1-frame
+ if(DEBUG) { System.err.println("JPG.parse.SOF[02]: Got frame "+frame); }
+ fileMarker = 0; // consumed and get-next
+ }
+ break;
+
+ case M_DHT: {
+ int count = 0;
+ final int huffmanLength = readUInt16(); count+=2;
+ int i=count, codeLengthTotal = 0;
+ while( i < huffmanLength ) {
+ final int huffmanTableSpec = readUInt8(); count++;
+ final int[] codeLengths = new int[16];
+ int codeLengthSum = 0;
+ for (int j = 0; j < 16; j++) {
+ codeLengthSum += (codeLengths[j] = readUInt8()); count++;
+ }
+ final byte[] huffmanValues = new byte[codeLengthSum];
+ for (int j = 0; j < codeLengthSum; j++) {
+ huffmanValues[j] = (byte)readUInt8(); count++;
+ }
+ codeLengthTotal += codeLengthSum;
+ i += 17 + codeLengthSum;
+ final BinObj[] table = ( huffmanTableSpec >> 4 ) == 0 ? huffmanTablesDC : huffmanTablesAC;
+ table[huffmanTableSpec & 0x0F] = buildHuffmanTable(codeLengths, huffmanValues);
+ }
+ if(count!=huffmanLength || i!=count){
+ throw new CodecException("ERROR: Huffman table format error [count!=Length]");
+ }
+ if(DEBUG) { System.err.println("JPG.parse.DHT: Got Huffman CodeLengthTotal "+codeLengthTotal); }
+ fileMarker = 0; // consumed and get-next
+ }
+ break;
+
+ case M_DRI:
+ resetInterval = readNumber();
+ if(DEBUG) { System.err.println("JPG.parse.DRI: Got Reset Interval "+resetInterval); }
+ fileMarker = 0; // consumed and get-next
+ break;
+
+ case M_SOS: {
+ int count = 0;
+ final int sosLen = readUInt16(); count+=2;
+ final int selectorsCount = readUInt8(); count++;
+ final ArrayList<ComponentIn> components = new ArrayList<ComponentIn>();
+ if(DEBUG) { System.err.println("JPG.parse.SOS: selectorCount [0.."+(selectorsCount-1)+"]: "+frame); }
+ for (int i = 0; i < selectorsCount; i++) {
+ final int compID = readUInt8(); count++;
+ final ComponentIn component = frame.getCompByID(compID);
+ final int tableSpec = readUInt8(); count++;
+ component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
+ component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
+ components.add(component);
+ }
+ final int spectralStart = readUInt8(); count++;
+ final int spectralEnd = readUInt8(); count++;
+ final int successiveApproximation = readUInt8(); count++;
+ if(count!=sosLen){
+ throw new CodecException("ERROR: scan header format error [count!=Length]");
+ }
+ fileMarker = decoder.decodeScan(frame, components, resetInterval,
+ spectralStart, spectralEnd,
+ successiveApproximation >> 4, successiveApproximation & 15);
+ if(DEBUG) { System.err.println("JPG.parse.SOS.decode result "+toHexString(fileMarker)); }
+ }
+ break;
+ default:
+ /**
+ if (data[offset - 3] == 0xFF &&
+ data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) {
+ // could be incorrect encoding -- last 0xFF byte of the previous
+ // block was eaten by the encoder
+ offset -= 3;
+ break;
+ } */
+ throw new CodecException("unknown JPEG marker " + toHexString(fileMarker) + ", " + bstream);
+ }
+ if( 0 == fileMarker ) {
+ fileMarker = readUInt16();
+ }
+ }
+ if(DEBUG) { System.err.println("JPG.parse.2: End of parsing input "+this); }
+ /** // JAU: max 1-frame
+ if ( frames.size() != 1 ) {
+ throw new CodecException("only single frame JPEGs supported "+this);
+ } */
+ if( null == frame ) {
+ throw new CodecException("no single frame found in stream "+this);
+ }
+ frame.validateComponents();
+
+ final int compCount = frame.getCompCount();
+ this.components = new ComponentOut[compCount];
+ for (int i = 0; i < compCount; i++) {
+ final ComponentIn component = frame.getCompByIndex(i);
+ // System.err.println("JPG.parse.buildComponentData["+i+"]: "+component); // JAU
+ // System.err.println("JPG.parse.buildComponentData["+i+"]: "+frame); // JAU
+ this.components[i] = new ComponentOut( output.buildComponentData(frame, component),
+ (float)component.h / (float)frame.maxH,
+ (float)component.v / (float)frame.maxV );
+ }
+ if(DEBUG) { System.err.println("JPG.parse.X: End of processing input "+this); }
+ return this;
+ }
+
+ private void prepareComponents(final Frame frame) {
+ int maxH = 0, maxV = 0;
+ // for (componentId in frame.components) {
+ final int compCount = frame.getCompCount();
+ for (int i=0; i<compCount; i++) {
+ final ComponentIn component = frame.getCompByIndex(i);
+ if (maxH < component.h) maxH = component.h;
+ if (maxV < component.v) maxV = component.v;
+ }
+ final int mcusPerLine = (int) Math.ceil(frame.samplesPerLine / 8f / maxH);
+ final int mcusPerColumn = (int) Math.ceil(frame.scanLines / 8f / maxV);
+ // for (componentId in frame.components) {
+ for (int i=0; i<compCount; i++) {
+ final ComponentIn component = frame.getCompByIndex(i);
+ final int blocksPerLine = (int) Math.ceil(Math.ceil(frame.samplesPerLine / 8f) * component.h / maxH);
+ final int blocksPerColumn = (int) Math.ceil(Math.ceil(frame.scanLines / 8f) * component.v / maxV);
+ final int blocksPerLineForMcu = mcusPerLine * component.h;
+ final int blocksPerColumnForMcu = mcusPerColumn * component.v;
+ component.allocateBlocks(blocksPerColumn, blocksPerColumnForMcu, blocksPerLine, blocksPerLineForMcu);
+ }
+ frame.maxH = maxH;
+ frame.maxV = maxV;
+ frame.mcusPerLine = mcusPerLine;
+ frame.mcusPerColumn = mcusPerColumn;
+ }
+
+ static class BinObjIdxed {
+ final BinObj children;
+ byte index;
+ BinObjIdxed() {
+ this.children = new BinObj();
+ this.index = 0;
+ }
+ }
+ static class BinObj {
+ final boolean isValue;
+ final BinObj[] tree;
+ final byte b;
+
+ BinObj(final byte b) {
+ this.isValue= true;
+ this.b = b;
+ this.tree = null;
+ }
+ BinObj() {
+ this.isValue= false;
+ this.b = (byte)0;
+ this.tree = new BinObj[2];
+ }
+ final byte getValue() { return b; }
+ final BinObj get(final int i) { return tree[i]; }
+ final void set(final byte i, final byte v) { tree[i] = new BinObj(v); }
+ final void set(final byte i, final BinObj v) { tree[i] = v; }
+ }
+
+ private BinObj buildHuffmanTable(final int[] codeLengths, final byte[] values) {
+ int k = 0;
+ int length = 16;
+ final ArrayList<BinObjIdxed> code = new ArrayList<BinObjIdxed>();
+ while (length > 0 && 0==codeLengths[length - 1]) {
+ length--;
+ }
+ code.add(new BinObjIdxed());
+ BinObjIdxed p = code.get(0), q;
+ for (int i = 0; i < length; i++) {
+ for (int j = 0; j < codeLengths[i]; j++) {
+ p = code.remove(code.size()-1);
+ p.children.set(p.index, values[k]);
+ while (p.index > 0) {
+ p = code.remove(code.size()-1);
+ }
+ p.index++;
+ code.add(p);
+ while (code.size() <= i) {
+ q = new BinObjIdxed();
+ code.add(q);
+ p.children.set(p.index, q.children);
+ p = q;
+ }
+ k++;
+ }
+ if (i + 1 < length) {
+ // p here points to last code
+ q = new BinObjIdxed();
+ code.add(q);
+ p.children.set(p.index, q.children);
+ p = q;
+ }
+ }
+ return code.get(0).children;
+ }
+
+ private final Output output = new Output();
+ static class Output {
+ private int blocksPerLine;
+ private int blocksPerColumn;
+ private int samplesPerLine;
+
+ private ArrayList<byte[]> buildComponentData(final Frame frame, final ComponentIn component) {
+ final ArrayList<byte[]> lines = new ArrayList<byte[]>();
+ blocksPerLine = component.blocksPerLine;
+ blocksPerColumn = component.blocksPerColumn;
+ samplesPerLine = blocksPerLine << 3;
+ final int[] R = new int[64];
+ final byte[] r = new byte[64];
+
+ for (int blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
+ final int scanLine = blockRow << 3;
+ // System.err.println("JPG.buildComponentData: row "+blockRow+"/"+blocksPerColumn+" -> scanLine "+scanLine); // JAU
+ for (int i = 0; i < 8; i++) {
+ lines.add(new byte[samplesPerLine]);
+ }
+ for (int blockCol = 0; blockCol < blocksPerLine; blockCol++) {
+ // System.err.println("JPG.buildComponentData: col "+blockCol+"/"+blocksPerLine+", comp.qttIdx "+component.qttIdx+", qtt "+frame.qtt[component.qttIdx]); // JAU
+ quantizeAndInverse(component.getBlock(blockRow, blockCol), r, R, frame.qtt[component.qttIdx]);
+
+ final int sample = blockCol << 3;
+ int offset = 0;
+ for (int j = 0; j < 8; j++) {
+ final byte[] line = lines.get(scanLine + j);
+ for (int i = 0; i < 8; i++)
+ line[sample + i] = r[offset++];
+ }
+ }
+ }
+ return lines;
+ }
+
+ // A port of poppler's IDCT method which in turn is taken from:
+ // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
+ // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
+ // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
+ // 988-991.
+ private void quantizeAndInverse(final int[] zz, final byte[] dataOut, final int[] dataIn, final int[] qt) {
+ int v0, v1, v2, v3, v4, v5, v6, v7, t;
+ final int[] p = dataIn;
+ int i;
+
+ // dequant
+ for (i = 0; i < 64; i++) {
+ p[i] = zz[i] * qt[i];
+ }
+
+ // inverse DCT on rows
+ for (i = 0; i < 8; ++i) {
+ final int row = 8 * i;
+
+ // check for all-zero AC coefficients
+ if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 &&
+ p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 &&
+ p[7 + row] == 0) {
+ t = (dctSqrt2 * p[0 + row] + 512) >> 10;
+ p[0 + row] = t;
+ p[1 + row] = t;
+ p[2 + row] = t;
+ p[3 + row] = t;
+ p[4 + row] = t;
+ p[5 + row] = t;
+ p[6 + row] = t;
+ p[7 + row] = t;
+ continue;
+ }
+
+ // stage 4
+ v0 = (dctSqrt2 * p[0 + row] + 128) >> 8;
+ v1 = (dctSqrt2 * p[4 + row] + 128) >> 8;
+ v2 = p[2 + row];
+ v3 = p[6 + row];
+ v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8;
+ v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8;
+ v5 = p[3 + row] << 4;
+ v6 = p[5 + row] << 4;
+
+ // stage 3
+ t = (v0 - v1+ 1) >> 1;
+ v0 = (v0 + v1 + 1) >> 1;
+ v1 = t;
+ t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
+ v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
+ v3 = t;
+ t = (v4 - v6 + 1) >> 1;
+ v4 = (v4 + v6 + 1) >> 1;
+ v6 = t;
+ t = (v7 + v5 + 1) >> 1;
+ v5 = (v7 - v5 + 1) >> 1;
+ v7 = t;
+
+ // stage 2
+ t = (v0 - v3 + 1) >> 1;
+ v0 = (v0 + v3 + 1) >> 1;
+ v3 = t;
+ t = (v1 - v2 + 1) >> 1;
+ v1 = (v1 + v2 + 1) >> 1;
+ v2 = t;
+ t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
+ v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
+ v7 = t;
+ t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
+ v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
+ v6 = t;
+
+ // stage 1
+ p[0 + row] = v0 + v7;
+ p[7 + row] = v0 - v7;
+ p[1 + row] = v1 + v6;
+ p[6 + row] = v1 - v6;
+ p[2 + row] = v2 + v5;
+ p[5 + row] = v2 - v5;
+ p[3 + row] = v3 + v4;
+ p[4 + row] = v3 - v4;
+ }
+
+ // inverse DCT on columns
+ for (i = 0; i < 8; ++i) {
+ final int col = i;
+
+ // check for all-zero AC coefficients
+ if (p[1*8 + col] == 0 && p[2*8 + col] == 0 && p[3*8 + col] == 0 &&
+ p[4*8 + col] == 0 && p[5*8 + col] == 0 && p[6*8 + col] == 0 &&
+ p[7*8 + col] == 0) {
+ t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
+ p[0*8 + col] = t;
+ p[1*8 + col] = t;
+ p[2*8 + col] = t;
+ p[3*8 + col] = t;
+ p[4*8 + col] = t;
+ p[5*8 + col] = t;
+ p[6*8 + col] = t;
+ p[7*8 + col] = t;
+ continue;
+ }
+
+ // stage 4
+ v0 = (dctSqrt2 * p[0*8 + col] + 2048) >> 12;
+ v1 = (dctSqrt2 * p[4*8 + col] + 2048) >> 12;
+ v2 = p[2*8 + col];
+ v3 = p[6*8 + col];
+ v4 = (dctSqrt1d2 * (p[1*8 + col] - p[7*8 + col]) + 2048) >> 12;
+ v7 = (dctSqrt1d2 * (p[1*8 + col] + p[7*8 + col]) + 2048) >> 12;
+ v5 = p[3*8 + col];
+ v6 = p[5*8 + col];
+
+ // stage 3
+ t = (v0 - v1 + 1) >> 1;
+ v0 = (v0 + v1 + 1) >> 1;
+ v1 = t;
+ t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
+ v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
+ v3 = t;
+ t = (v4 - v6 + 1) >> 1;
+ v4 = (v4 + v6 + 1) >> 1;
+ v6 = t;
+ t = (v7 + v5 + 1) >> 1;
+ v5 = (v7 - v5 + 1) >> 1;
+ v7 = t;
+
+ // stage 2
+ t = (v0 - v3 + 1) >> 1;
+ v0 = (v0 + v3 + 1) >> 1;
+ v3 = t;
+ t = (v1 - v2 + 1) >> 1;
+ v1 = (v1 + v2 + 1) >> 1;
+ v2 = t;
+ t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
+ v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
+ v7 = t;
+ t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
+ v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
+ v6 = t;
+
+ // stage 1
+ p[0*8 + col] = v0 + v7;
+ p[7*8 + col] = v0 - v7;
+ p[1*8 + col] = v1 + v6;
+ p[6*8 + col] = v1 - v6;
+ p[2*8 + col] = v2 + v5;
+ p[5*8 + col] = v2 - v5;
+ p[3*8 + col] = v3 + v4;
+ p[4*8 + col] = v3 - v4;
+ }
+
+ // convert to 8-bit integers
+ for (i = 0; i < 64; ++i) {
+ final int sample = 128 + ((p[i] + 8) >> 4);
+ dataOut[i] = (byte) ( sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample );
+ }
+ }
+ }
+
+ static interface DecoderFunction {
+ void decode(ComponentIn component, int[] zz) throws IOException;
+ }
+
+ class Decoder {
+ // private int precision;
+ // private int samplesPerLine;
+ // private int scanLines;
+ private int mcusPerLine;
+ private boolean progressive;
+ // private int maxH, maxV;
+ private int spectralStart, spectralEnd;
+ private int successive;
+ private int eobrun;
+ private int successiveACState, successiveACNextValue;
+
+ private int decodeScan(final Frame frame, final ArrayList<ComponentIn> components, int resetInterval,
+ final int spectralStart, final int spectralEnd, final int successivePrev, final int successive) throws IOException {
+ // this.precision = frame.precision;
+ // this.samplesPerLine = frame.samplesPerLine;
+ // this.scanLines = frame.scanLines;
+ this.mcusPerLine = frame.mcusPerLine;
+ this.progressive = frame.progressive;
+ // this.maxH = frame.maxH;
+ // this.maxV = frame.maxV;
+ bstream.skip( bstream.getBitCount() ); // align to next byte
+ this.spectralStart = spectralStart;
+ this.spectralEnd = spectralEnd;
+ this.successive = successive;
+
+ final int componentsLength = components.size();
+
+ final DecoderFunction decodeFn;
+ if (progressive) {
+ if (spectralStart == 0) {
+ decodeFn = successivePrev == 0 ? decodeDCFirst : decodeDCSuccessive;
+ } else {
+ decodeFn = successivePrev == 0 ? decodeACFirst : decodeACSuccessive;
+ }
+ } else {
+ decodeFn = decodeBaseline;
+ }
+
+ int mcu = 0;
+ int mcuExpected;
+ if (componentsLength == 1) {
+ final ComponentIn c = components.get(0);
+ mcuExpected = c.blocksPerLine * c.blocksPerColumn;
+ } else {
+ mcuExpected = mcusPerLine * frame.mcusPerColumn;
+ }
+ if (0 == resetInterval) {
+ resetInterval = mcuExpected;
+ }
+ if(DEBUG) {
+ System.err.println("JPEG.decodeScan.1 resetInterval "+resetInterval+", mcuExpected "+mcuExpected+", sA "+spectralStart+", sP "+successivePrev+", sE "+spectralEnd+", suc "+successive+", decodeFn "+decodeFn.getClass().getSimpleName());
+ }
+ int marker = 0;
+ while ( /* untilMarker || */ mcu < mcuExpected) {
+ // reset interval stuff
+ for (int i = 0; i < componentsLength; i++) {
+ components.get(i).pred = 0;
+ }
+ eobrun = 0;
+
+ try {
+ if (componentsLength == 1) {
+ final ComponentIn component = components.get(0);
+ for (int n = 0; n < resetInterval; n++) {
+ decodeBlock(component, decodeFn, mcu);
+ mcu++;
+ }
+ } else {
+ for (int n = 0; n < resetInterval; n++) {
+ for (int i = 0; i < componentsLength; i++) {
+ final ComponentIn component = components.get(i);
+ final int h = component.h;
+ final int v = component.v;
+ for (int j = 0; j < v; j++) {
+ for (int k = 0; k < h; k++) {
+ decodeMcu(component, decodeFn, mcu, j, k);
+ }
+ }
+ }
+ mcu++;
+ }
+ }
+ } catch (final MarkerException markerException) {
+ if(DEBUG) { System.err.println("JPEG.decodeScan: Marker exception: "+markerException.getMessage()); markerException.printStackTrace(); }
+ return markerException.getMarker();
+ } catch (final CodecException codecException) {
+ if(DEBUG) { System.err.println("JPEG.decodeScan: Codec exception: "+codecException.getMessage()); codecException.printStackTrace(); }
+ bstream.skip( bstream.getBitCount() ); // align to next byte
+ return M_EOI; // force end !
+ }
+
+ // find marker
+ bstream.skip( bstream.getBitCount() ); // align to next byte
+ bstream.mark(2);
+ marker = readUInt16();
+ if( marker < 0xFF00 ) {
+ bstream.reset();
+ throw new CodecException("marker not found @ mcu "+mcu+"/"+mcuExpected+", u16: "+toHexString(marker));
+ }
+ final boolean isRSTx = 0xFFD0 <= marker && marker <= 0xFFD7; // !RSTx
+ if(DEBUG) {
+ System.err.println("JPEG.decodeScan: MCUs "+mcu+"/"+mcuExpected+", u16 "+toHexString(marker)+", RSTx "+isRSTx+", "+frame);
+ }
+ if ( !isRSTx ) {
+ break; // handle !RSTx marker in caller
+ }
+ }
+ return marker;
+ }
+
+ private final int readBit() throws MarkerException, IOException {
+ final int bit = bstream.readBit(true /* msbFirst */);
+ if( Bitstream.EOS == bit || 7 != bstream.getBitCount() ) {
+ return bit;
+ }
+ // new byte read, i.e. bitCount == 7
+ final int bitsData = bstream.getBitBuffer(); // peek for marker
+ if ( 0xFF == bitsData ) { // marker prefix
+ final int nextByte = bstream.getStream().read(); // snoop marker signature, will be dropped!
+ if( -1 == nextByte ) {
+ throw new CodecException("marked prefix 0xFF, then EOF");
+ }
+ if (0 != nextByte) {
+ final int marker = (bitsData << 8) | nextByte;
+ throw new MarkerException(marker, "Marker at readBit pos " + bstream);
+ }
+ // unstuff 0
+ }
+ return bit;
+ }
+
+ private int decodeHuffman(final BinObj tree) throws IOException {
+ BinObj node = tree;
+ int bit;
+ while ( ( bit = readBit() ) != -1 ) {
+ node = node.get(bit);
+ if ( node.isValue ) {
+ return 0x000000FF & node.getValue();
+ }
+ }
+ throw new CodecException("EOF reached at "+bstream);
+ }
+ private int receive(int length) throws IOException {
+ int n = 0;
+ while (length > 0) {
+ final int bit = readBit();
+ if (bit == -1) {
+ return -1;
+ }
+ n = (n << 1) | bit;
+ length--;
+ }
+ return n;
+ }
+ private int receiveAndExtend(final int length) throws IOException {
+ final int n = receive(length);
+ if (n >= 1 << (length - 1)) {
+ return n;
+ }
+ return n + (-1 << length) + 1;
+ }
+
+ final DecoderFunction decodeBaseline = new BaselineDecoder();
+ final DecoderFunction decodeDCFirst = new DCFirstDecoder();
+ final DecoderFunction decodeDCSuccessive = new DCSuccessiveDecoder();
+ final DecoderFunction decodeACFirst = new ACFirstDecoder();
+ final DecoderFunction decodeACSuccessive = new ACSuccessiveDecoder();
+
+ class BaselineDecoder implements DecoderFunction {
+ @Override
+ public void decode(final ComponentIn component, final int[] zz) throws IOException {
+ final int t = decodeHuffman(component.huffmanTableDC);
+ final int diff = ( t == 0 ) ? 0 : receiveAndExtend(t);
+ zz[0] = ( component.pred += diff );
+ int k = 1;
+ while (k < 64) {
+ final int rs = decodeHuffman(component.huffmanTableAC);
+ final int s = rs & 15, r = rs >> 4;
+ if (s == 0) {
+ if (r < 15) {
+ break;
+ }
+ k += 16;
+ continue;
+ }
+ k += r;
+ final int z = dctZigZag[k];
+ zz[z] = receiveAndExtend(s);
+ k++;
+ }
+ }
+ }
+ class DCFirstDecoder implements DecoderFunction {
+ @Override
+ public void decode(final ComponentIn component, final int[] zz) throws IOException {
+ final int t = decodeHuffman(component.huffmanTableDC);
+ final int diff = ( t == 0 ) ? 0 : (receiveAndExtend(t) << successive);
+ zz[0] = ( component.pred += diff );
+ }
+ }
+ class DCSuccessiveDecoder implements DecoderFunction {
+ @Override
+ public void decode(final ComponentIn component, final int[] zz) throws IOException {
+ zz[0] |= readBit() << successive;
+ }
+ }
+
+ class ACFirstDecoder implements DecoderFunction {
+ @Override
+ public void decode(final ComponentIn component, final int[] zz) throws IOException {
+ if (eobrun > 0) {
+ eobrun--;
+ return;
+ }
+ int k = spectralStart;
+ final int e = spectralEnd;
+ while (k <= e) {
+ final int rs = decodeHuffman(component.huffmanTableAC);
+ final int s = rs & 15, r = rs >> 4;
+ if (s == 0) {
+ if (r < 15) {
+ eobrun = receive(r) + (1 << r) - 1;
+ break;
+ }
+ k += 16;
+ continue;
+ }
+ k += r;
+ final int z = dctZigZag[k];
+ zz[z] = receiveAndExtend(s) * (1 << successive);
+ k++;
+ }
+ }
+ }
+ class ACSuccessiveDecoder implements DecoderFunction {
+ @Override
+ public void decode(final ComponentIn component, final int[] zz) throws IOException {
+ int k = spectralStart;
+ final int e = spectralEnd;
+ int r = 0;
+ while (k <= e) {
+ final int z = dctZigZag[k];
+ switch (successiveACState) {
+ case 0: // initial state
+ final int rs = decodeHuffman(component.huffmanTableAC);
+ final int s = rs & 15;
+ r = rs >> 4;
+ if (s == 0) {
+ if (r < 15) {
+ eobrun = receive(r) + (1 << r);
+ successiveACState = 4;
+ } else {
+ r = 16;
+ successiveACState = 1;
+ }
+ } else {
+ // if (s !== 1) {
+ if (s != 1) {
+ throw new CodecException("invalid ACn encoding");
+ }
+ successiveACNextValue = receiveAndExtend(s);
+ successiveACState = r != 0 ? 2 : 3;
+ }
+ continue;
+ case 1: // skipping r zero items
+ case 2:
+ if ( zz[z] != 0 ) {
+ zz[z] += (readBit() << successive);
+ } else {
+ r--;
+ if (r == 0) {
+ successiveACState = successiveACState == 2 ? 3 : 0;
+ }
+ }
+ break;
+ case 3: // set value for a zero item
+ if ( zz[z] != 0 ) {
+ zz[z] += (readBit() << successive);
+ } else {
+ zz[z] = successiveACNextValue << successive;
+ successiveACState = 0;
+ }
+ break;
+ case 4: // eob
+ if ( zz[z] != 0 ) {
+ zz[z] += (readBit() << successive);
+ }
+ break;
+ }
+ k++;
+ }
+ if (successiveACState == 4) {
+ eobrun--;
+ if (eobrun == 0) {
+ successiveACState = 0;
+ }
+ }
+ }
+ }
+ void decodeMcu(final ComponentIn component, final DecoderFunction decoder, final int mcu, final int row, final int col) throws IOException {
+ final int mcuRow = (mcu / mcusPerLine) | 0;
+ final int mcuCol = mcu % mcusPerLine;
+ final int blockRow = mcuRow * component.v + row;
+ final int blockCol = mcuCol * component.h + col;
+ decoder.decode(component, component.getBlock(blockRow, blockCol));
+ }
+ void decodeBlock(final ComponentIn component, final DecoderFunction decoder, final int mcu) throws IOException {
+ final int blockRow = (mcu / component.blocksPerLine) | 0;
+ final int blockCol = mcu % component.blocksPerLine;
+ decoder.decode(component, component.getBlock(blockRow, blockCol));
+ }
+ }
+
+ private final Decoder decoder = new Decoder();
+
+ /** wrong color space ..
+ private final void storeYCbCr2BGR(final PixelStorage pixelStorage, int x, int y, int Y, final int Cb, final int Cr)
+ {
+ if(Y<0) Y=0;
+ int B = Y + ( ( 116130 * Cb ) >> 16 ) ;
+ if(B<0) B=0;
+ else if(B>255) B=255;
+
+ int G = Y - ( ( 22554 * Cb + 46802 * Cr ) >> 16 ) ;
+ if(G<0) G=0;
+ else if(G>255) G=255;
+
+ int R = Y + ( ( 91881 * Cr ) >> 16 );
+ if(R<0) R=0;
+ else if(R>255) R=255;
+
+ pixelStorage.storeRGB(x, y, (byte)R, (byte)G, (byte)B);
+ } */
+
+ public synchronized void getPixel(final JPEGDecoder.ColorSink pixelStorage, final int width, final int height) {
+ final int scaleX = this.width / width, scaleY = this.height / height;
+
+ final int componentCount = this.components.length;
+ final ColorSpace sourceCS = ( null != adobe ) ? adobe.colorSpace : ColorSpace.YCbCr;
+ final ColorSpace storageCS = pixelStorage.allocate(width, height, sourceCS, componentCount);
+ if( ColorSpace.RGB != storageCS && ColorSpace.YCbCr != storageCS ) {
+ throw new IllegalArgumentException("Unsupported storage color space: "+storageCS);
+ }
+
+ switch (componentCount) {
+ case 1: {
+ // Grayscale
+ final ComponentOut component1 = this.components[0];
+ for (int y = 0; y < height; y++) {
+ final byte[] component1Line = component1.getLine((int)(y * component1.scaleY * scaleY));
+ for (int x = 0; x < width; x++) {
+ final byte Y = component1Line[(int)(x * component1.scaleX * scaleX)];
+ if( ColorSpace.YCbCr == storageCS ) {
+ pixelStorage.storeYCbCr(x, y, Y, (byte)0, (byte)0);
+ } else {
+ pixelStorage.storeRGB(x, y, Y, Y, Y);
+ }
+ }
+ }
+ }
+ break;
+ case 2: {
+ // PDF might compress two component data in custom colorspace
+ final ComponentOut component1 = this.components[0];
+ final ComponentOut component2 = this.components[1];
+ for (int y = 0; y < height; y++) {
+ final int ys = y * scaleY;
+ final byte[] component1Line = component1.getLine((int)(ys * component1.scaleY));
+ final byte[] component2Line = component1.getLine((int)(ys * component2.scaleY));
+ for (int x = 0; x < width; x++) {
+ final int xs = x * scaleX;
+ final byte Y1 = component1Line[(int)(xs * component1.scaleX)];
+ final byte Y2 = component2Line[(int)(xs * component2.scaleX)];
+ pixelStorage.store2(x, y, Y1, Y2);
+ }
+ }
+ }
+ break;
+ case 3: {
+ if (ColorSpace.YCbCr != sourceCS) {
+ throw new CodecException("Unsupported source color space w 3 components: "+sourceCS);
+ }
+ final ComponentOut component1 = this.components[0];
+ final ComponentOut component2 = this.components[1];
+ final ComponentOut component3 = this.components[2];
+ for (int y = 0; y < height; y++) {
+ final int ys = y * scaleY;
+ final byte[] component1Line = component1.getLine((int)(ys * component1.scaleY));
+ final byte[] component2Line = component2.getLine((int)(ys * component2.scaleY));
+ final byte[] component3Line = component3.getLine((int)(ys * component3.scaleY));
+ if( ColorSpace.YCbCr == storageCS ) {
+ for (int x = 0; x < width; x++) {
+ final int xs = x * scaleX;
+ final byte Y = component1Line[(int)(xs * component1.scaleX)];
+ final byte Cb = component2Line[(int)(xs * component2.scaleX)];
+ final byte Cr = component3Line[(int)(xs * component3.scaleX)];
+ pixelStorage.storeYCbCr(x, y, Y, Cb, Cr);
+ }
+ } else {
+ for (int x = 0; x < width; x++) {
+ final int xs = x * scaleX;
+ final int Y = 0x000000FF & component1Line[(int)(xs * component1.scaleX)];
+ final int Cb = 0x000000FF & component2Line[(int)(xs * component2.scaleX)];
+ final int Cr = 0x000000FF & component3Line[(int)(xs * component3.scaleX)];
+ // storeYCbCr2BGR(pixelStorage, x, y, Y, Cb, Cr);
+ final byte R = clampTo8bit(Y + 1.402f * (Cr - 128f));
+ final byte G = clampTo8bit(Y - 0.3441363f * (Cb - 128f) - 0.71413636f * (Cr - 128f));
+ final byte B = clampTo8bit(Y + 1.772f * (Cb - 128f));
+ pixelStorage.storeRGB(x, y, R, G, B);
+ }
+ }
+ }
+ }
+ break;
+ case 4: {
+ if (ColorSpace.YCCK != sourceCS && ColorSpace.CMYK != sourceCS) {
+ throw new CodecException("Unsupported source color space w 4 components: "+sourceCS);
+ }
+ final ComponentOut component1 = this.components[0];
+ final ComponentOut component2 = this.components[1];
+ final ComponentOut component3 = this.components[2];
+ final ComponentOut component4 = this.components[3];
+ for (int y = 0; y < height; y++) {
+ final int ys = y * scaleY;
+ final byte[] component1Line = component1.getLine((int)(ys * component1.scaleY));
+ final byte[] component2Line = component2.getLine((int)(ys * component2.scaleY));
+ final byte[] component3Line = component3.getLine((int)(ys * component3.scaleY));
+ final byte[] component4Line = component4.getLine((int)(ys * component4.scaleY));
+ if( ColorSpace.YCbCr == storageCS ) {
+ if (ColorSpace.YCCK != sourceCS) {
+ throw new CodecException("Unsupported storage color space "+storageCS+" with source color space "+sourceCS);
+ }
+ for (int x = 0; x < width; x++) {
+ final int xs = x * scaleX;
+ final byte Y1 = component1Line[(int)(xs * component1.scaleX)];
+ final byte C1 = component2Line[(int)(xs * component2.scaleX)];
+ final byte C2 = component3Line[(int)(xs * component3.scaleX)];
+ // final byte K = component4Line[(int)(xs * component4.scaleX)];
+ // FIXME: YCCK is not really YCbCr, since K (black) is missing!
+ pixelStorage.storeYCbCr(x, y, Y1, C1, C2);
+ }
+ } else {
+ if (ColorSpace.CMYK == sourceCS) {
+ for (int x = 0; x < width; x++) {
+ final int xs = x * scaleX;
+ final int cC = 0x000000FF & component1Line[(int)(xs * component1.scaleX)];
+ final int cM = 0x000000FF & component2Line[(int)(xs * component2.scaleX)];
+ final int cY = 0x000000FF & component3Line[(int)(xs * component3.scaleX)];
+ final int cK = 0x000000FF & component4Line[(int)(xs * component4.scaleX)];
+ // CMYK -> RGB
+ final byte R = clampTo8bit( ( cC * cK ) / 255f );
+ final byte G = clampTo8bit( ( cM * cK ) / 255f );
+ final byte B = clampTo8bit( ( cY * cK ) / 255f );
+ pixelStorage.storeRGB(x, y, R, G, B);
+ }
+ } else { // ColorModel.YCCK == sourceCM
+ for (int x = 0; x < width; x++) {
+ final int xs = x * scaleX;
+ final int Y = 0x000000FF & component1Line[(int)(xs * component1.scaleX)];
+ final int Cb = 0x000000FF & component2Line[(int)(xs * component2.scaleX)];
+ final int Cr = 0x000000FF & component3Line[(int)(xs * component3.scaleX)];
+ final int cK = 0x000000FF & component4Line[(int)(xs * component4.scaleX)];
+ // YCCK -> 255f - [ R'G'B' ] -> CMYK
+ final float cC = 255f - ( Y + 1.402f * (Cr - 128f) );
+ final float cM = 255f - ( Y - 0.3441363f * (Cb - 128f) - 0.71413636f * (Cr - 128f) );
+ final float cY = 255f - ( Y + 1.772f * (Cb - 128f) );
+ // CMYK -> RGB
+ final byte R = clampTo8bit( ( cC * cK ) / 255f );
+ final byte G = clampTo8bit( ( cM * cK ) / 255f );
+ final byte B = clampTo8bit( ( cY * cK ) / 255f );
+ pixelStorage.storeRGB(x, y, R, G, B);
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+ throw new CodecException("Unsupported color model: Space "+sourceCS+", components "+componentCount);
+ }
+ }
+
+ private static byte clampTo8bit(final float a) {
+ return (byte) ( a < 0f ? 0 : a > 255f ? 255 : a );
+ }
+
+ private static String toHexString(final int v) {
+ return "0x"+Integer.toHexString(v);
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java b/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java
index a34f73ab2..c577c4fd5 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java
@@ -1,8 +1,10 @@
package jogamp.opengl.util.pngj;
+import java.util.HashMap;
+
/**
* Internal PNG predictor filter, or strategy to select it.
- *
+ *
*/
public enum FilterType {
/**
@@ -26,69 +28,46 @@ public enum FilterType {
*/
FILTER_PAETH(4),
/**
- * Default strategy: select one of the above filters depending on global image parameters
+ * Default strategy: select one of the above filters depending on global
+ * image parameters
*/
FILTER_DEFAULT(-1),
/**
- * Aggresive strategy: select one of the above filters trying each of the filters (this is done every 8 rows)
+ * Aggressive strategy: select one of the above filters trying each of the
+ * filters (every 8 rows)
*/
FILTER_AGGRESSIVE(-2),
/**
+ * Very aggressive strategy: select one of the above filters trying each of
+ * the filters (for every row!)
+ */
+ FILTER_VERYAGGRESSIVE(-3),
+ /**
* Uses all fiters, one for lines, cyciclally. Only for tests.
*/
- FILTER_ALTERNATE(-3),
+ FILTER_CYCLIC(-50),
+
/**
- * Aggresive strategy: select one of the above filters trying each of the filters (this is done for every row!)
+ * Not specified, placeholder for unknown or NA filters.
*/
- FILTER_VERYAGGRESSIVE(-4), ;
+ FILTER_UNKNOWN(-100), ;
public final int val;
- private FilterType(int val) {
+ private FilterType(final int val) {
this.val = val;
}
- public static FilterType getByVal(int i) {
- for (FilterType ft : values()) {
- if (ft.val == i)
- return ft;
- }
- return null;
- }
-
- public static int unfilterRowNone(int r) {
- return (int) (r & 0xFF);
- }
-
- public static int unfilterRowSub(int r, int left) {
- return ((int) (r + left) & 0xFF);
- }
+ private static HashMap<Integer, FilterType> byVal;
- public static int unfilterRowUp(int r, int up) {
- return ((int) (r + up) & 0xFF);
- }
-
- public static int unfilterRowAverage(int r, int left, int up) {
- return (r + (left + up) / 2) & 0xFF;
+ static {
+ byVal = new HashMap<Integer, FilterType>();
+ for (final FilterType ft : values()) {
+ byVal.put(ft.val, ft);
+ }
}
- public static int unfilterRowPaeth(int r, int a, int b, int c) { // a = left, b = above, c = upper left
- return (r + filterPaethPredictor(a, b, c)) & 0xFF;
+ public static FilterType getByVal(final int i) {
+ return byVal.get(i);
}
- public static int filterPaethPredictor(int a, int b, int c) {
- // from http://www.libpng.org/pub/png/spec/1.2/PNG-Filters.html
- // a = left, b = above, c = upper left
- final int p = a + b - c;// ; initial estimate
- final int pa = p >= a ? p - a : a - p;
- final int pb = p >= b ? p - b : b - p;
- final int pc = p >= c ? p - c : c - p;
- // ; return nearest of a,b,c,
- // ; breaking ties in order a,b,c.
- if (pa <= pb && pa <= pc)
- return a;
- else if (pb <= pc)
- return b;
- else
- return c;
- }
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/FilterWriteStrategy.java b/src/jogl/classes/jogamp/opengl/util/pngj/FilterWriteStrategy.java
index 27586b292..63f456347 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/FilterWriteStrategy.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/FilterWriteStrategy.java
@@ -1,7 +1,7 @@
package jogamp.opengl.util.pngj;
/**
- * Manages the writer strategy for selecting the internal png "filter"
+ * Manages the writer strategy for selecting the internal png predictor filter
*/
class FilterWriteStrategy {
private static final int COMPUTE_STATS_EVERY_N_LINES = 8;
@@ -11,15 +11,15 @@ class FilterWriteStrategy {
private FilterType currentType; // 0-4
private int lastRowTested = -1000000;
// performance of each filter (less is better) (can be negative)
- private double[] lastSums = new double[5];
+ private final double[] lastSums = new double[5];
// performance of each filter (less is better) (can be negative)
- private double[] lastEntropies = new double[5];
+ private final double[] lastEntropies = new double[5];
// a priori preference (NONE SUB UP AVERAGE PAETH)
private double[] preference = new double[] { 1.1, 1.1, 1.1, 1.1, 1.2 };
private int discoverEachLines = -1;
- private double[] histogram1 = new double[256];
+ private final double[] histogram1 = new double[256];
- FilterWriteStrategy(ImageInfo imgInfo, FilterType configuredType) {
+ FilterWriteStrategy(final ImageInfo imgInfo, final FilterType configuredType) {
this.imgInfo = imgInfo;
this.configuredType = configuredType;
if (configuredType.val < 0) { // first guess
@@ -36,7 +36,7 @@ class FilterWriteStrategy {
discoverEachLines = 1;
}
- boolean shouldTestAll(int rown) {
+ boolean shouldTestAll(final int rown) {
if (discoverEachLines > 0 && lastRowTested + discoverEachLines <= rown) {
currentType = null;
return true;
@@ -44,7 +44,7 @@ class FilterWriteStrategy {
return false;
}
- public void setPreference(double none, double sub, double up, double ave, double paeth) {
+ public void setPreference(final double none, final double sub, final double up, final double ave, final double paeth) {
preference = new double[] { none, sub, up, ave, paeth };
}
@@ -52,7 +52,7 @@ class FilterWriteStrategy {
return (discoverEachLines > 0);
}
- void fillResultsForFilter(int rown, FilterType type, double sum, int[] histo, boolean tentative) {
+ void fillResultsForFilter(final int rown, final FilterType type, final double sum, final int[] histo, final boolean tentative) {
lastRowTested = rown;
lastSums[type.val] = sum;
if (histo != null) {
@@ -72,7 +72,7 @@ class FilterWriteStrategy {
}
}
- FilterType gimmeFilterType(int rown, boolean useEntropy) {
+ FilterType gimmeFilterType(final int rown, final boolean useEntropy) {
if (currentType == null) { // get better
if (rown == 0)
currentType = FilterType.FILTER_SUB;
@@ -89,7 +89,7 @@ class FilterWriteStrategy {
}
}
}
- if (configuredType == FilterType.FILTER_ALTERNATE) {
+ if (configuredType == FilterType.FILTER_CYCLIC) {
currentType = FilterType.getByVal((currentType.val + 1) % 5);
}
return currentType;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java
index 2f6b89e9c..cdd17a291 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java
@@ -3,7 +3,8 @@ package jogamp.opengl.util.pngj;
/**
* Simple immutable wrapper for basic image info.
* <p>
- * Some parameters are redundant, but the constructor receives an 'orthogonal' subset.
+ * Some parameters are redundant, but the constructor receives an 'orthogonal'
+ * subset.
* <p>
* ref: http://www.w3.org/TR/PNG/#11IHDR
*/
@@ -13,24 +14,25 @@ public class ImageInfo {
private static final int MAX_COLS_ROWS_VAL = 1000000;
/**
- * Image width, in pixels.
+ * Cols= Image width, in pixels.
*/
public final int cols;
/**
- * Image height, in pixels
+ * Rows= Image height, in pixels
*/
public final int rows;
/**
- * Bits per sample (per channel) in the buffer (1-2-4-8-16). This is 8-16 for RGB/ARGB images, 1-2-4-8 for
- * grayscale. For indexed images, number of bits per palette index (1-2-4-8)
+ * Bits per sample (per channel) in the buffer (1-2-4-8-16). This is 8-16
+ * for RGB/ARGB images, 1-2-4-8 for grayscale. For indexed images, number of
+ * bits per palette index (1-2-4-8)
*/
public final int bitDepth;
/**
- * Number of channels, as used internally. This is 3 for RGB, 4 for RGBA, 2 for GA (gray with alpha), 1 for
- * grayscales or indexed.
+ * Number of channels, as used internally: 3 for RGB, 4 for RGBA, 2 for GA
+ * (gray with alpha), 1 for grayscale or indexed.
*/
public final int channels;
@@ -50,7 +52,8 @@ public class ImageInfo {
public final boolean indexed;
/**
- * Flag: true if image internally uses less than one byte per sample (bit depth 1-2-4)
+ * Flag: true if image internally uses less than one byte per sample (bit
+ * depth 1-2-4)
*/
public final boolean packed;
@@ -75,27 +78,34 @@ public class ImageInfo {
public final int samplesPerRow;
/**
- * For internal use only. Samples available for our packed scanline. Equals samplesPerRow if not packed. Elsewhere,
- * it's lower
+ * Amount of "packed samples" : when several samples are stored in a single
+ * byte (bitdepth 1,2 4) they are counted as one "packed sample". This is
+ * less that samplesPerRow only when bitdepth is 1-2-4 (flag packed = true)
+ * <p>
+ * This equals the number of elements in the scanline array if working with
+ * packedMode=true
+ * <p>
+ * For internal use, client code should rarely access this.
*/
- final int samplesPerRowP;
+ public final int samplesPerRowPacked;
/**
* Short constructor: assumes truecolor (RGB/RGBA)
*/
- public ImageInfo(int cols, int rows, int bitdepth, boolean alpha) {
+ public ImageInfo(final int cols, final int rows, final int bitdepth, final boolean alpha) {
this(cols, rows, bitdepth, alpha, false, false);
}
/**
* Full constructor
- *
+ *
* @param cols
* Width in pixels
* @param rows
* Height in pixels
* @param bitdepth
- * Bits per sample, in the buffer : 8-16 for RGB true color and greyscale
+ * Bits per sample, in the buffer : 8-16 for RGB true color and
+ * greyscale
* @param alpha
* Flag: has an alpha channel (RGBA or GA)
* @param grayscale
@@ -103,7 +113,7 @@ public class ImageInfo {
* @param indexed
* Flag: has palette
*/
- public ImageInfo(int cols, int rows, int bitdepth, boolean alpha, boolean grayscale, boolean indexed) {
+ public ImageInfo(final int cols, final int rows, final int bitdepth, final boolean alpha, final boolean grayscale, final boolean indexed) {
this.cols = cols;
this.rows = rows;
this.alpha = alpha;
@@ -119,7 +129,7 @@ public class ImageInfo {
this.bytesPixel = (bitspPixel + 7) / 8;
this.bytesPerRow = (bitspPixel * cols + 7) / 8;
this.samplesPerRow = channels * this.cols;
- this.samplesPerRowP = packed ? bytesPerRow : samplesPerRow;
+ this.samplesPerRowPacked = packed ? bytesPerRow : samplesPerRow;
// several checks
switch (this.bitDepth) {
case 1:
@@ -147,7 +157,7 @@ public class ImageInfo {
public String toString() {
return "ImageInfo [cols=" + cols + ", rows=" + rows + ", bitDepth=" + bitDepth + ", channels=" + channels
+ ", bitspPixel=" + bitspPixel + ", bytesPixel=" + bytesPixel + ", bytesPerRow=" + bytesPerRow
- + ", samplesPerRow=" + samplesPerRow + ", samplesPerRowP=" + samplesPerRowP + ", alpha=" + alpha
+ + ", samplesPerRow=" + samplesPerRow + ", samplesPerRowP=" + samplesPerRowPacked + ", alpha=" + alpha
+ ", greyscale=" + greyscale + ", indexed=" + indexed + ", packed=" + packed + "]";
}
@@ -157,38 +167,27 @@ public class ImageInfo {
int result = 1;
result = prime * result + (alpha ? 1231 : 1237);
result = prime * result + bitDepth;
- result = prime * result + bitspPixel;
- result = prime * result + bytesPerRow;
- result = prime * result + bytesPixel;
result = prime * result + channels;
result = prime * result + cols;
result = prime * result + (greyscale ? 1231 : 1237);
result = prime * result + (indexed ? 1231 : 1237);
- result = prime * result + (packed ? 1231 : 1237);
result = prime * result + rows;
- result = prime * result + samplesPerRow;
return result;
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
- ImageInfo other = (ImageInfo) obj;
+ final ImageInfo other = (ImageInfo) obj;
if (alpha != other.alpha)
return false;
if (bitDepth != other.bitDepth)
return false;
- if (bitspPixel != other.bitspPixel)
- return false;
- if (bytesPerRow != other.bytesPerRow)
- return false;
- if (bytesPixel != other.bytesPixel)
- return false;
if (channels != other.channels)
return false;
if (cols != other.cols)
@@ -197,12 +196,9 @@ public class ImageInfo {
return false;
if (indexed != other.indexed)
return false;
- if (packed != other.packed)
- return false;
if (rows != other.rows)
return false;
- if (samplesPerRow != other.samplesPerRow)
- return false;
return true;
}
+
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java
index bfbb35b7c..5ad2e4409 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java
@@ -1,11 +1,12 @@
package jogamp.opengl.util.pngj;
-import java.util.Arrays;
+import jogamp.opengl.util.pngj.ImageLineHelper.ImageLineStats;
/**
* Lightweight wrapper for an image scanline, used for read and write.
* <p>
- * This object can be (usually it is) reused while iterating over the image lines.
+ * This object can be (usually it is) reused while iterating over the image
+ * lines.
* <p>
* See <code>scanline</code> field, to understand the format.
*/
@@ -18,28 +19,97 @@ public class ImageLine {
private int rown = 0;
/**
- * The 'scanline' is an array of integers, corresponds to an image line (row).
+ * The 'scanline' is an array of integers, corresponds to an image line
+ * (row).
* <p>
- * Except for 'packed' formats (gray/indexed with 1-2-4 bitdepth) each int is a "sample" (one for channel), (0-255
- * or 0-65535) in the respective PNG sequence sequence : (R G B R G B...) or (R G B A R G B A...) or (g g g ...) or
- * ( i i i) (palette index)
+ * Except for 'packed' formats (gray/indexed with 1-2-4 bitdepth) each
+ * <code>int</code> is a "sample" (one for channel), (0-255 or 0-65535) in
+ * the corresponding PNG sequence: <code>R G B R G B...</code> or
+ * <code>R G B A R G B A...</tt>
+ * or <code>g g g ...</code> or <code>i i i</code> (palette index)
* <p>
- * For bitdepth 1/2/4 , each element is a PACKED byte! To get an unpacked copy, see <code>tf_pack()</code> and its
- * inverse <code>tf_unpack()</code>
+ * For bitdepth=1/2/4 , and if samplesUnpacked=false, each value is a PACKED
+ * byte!
* <p>
- * To convert a indexed line to RGB balues, see <code>ImageLineHelper.tf_palIdx2RGB()</code> (can't do the reverse)
+ * To convert a indexed line to RGB balues, see
+ * <code>ImageLineHelper.palIdx2RGB()</code> (you can't do the reverse)
*/
- public final int[] scanline; // see explanation above!!
+ public final int[] scanline;
+ /**
+ * Same as {@link #scanline}, but with one byte per sample. Only one of
+ * scanline and scanlineb is valid - this depends on {@link #sampleType}
+ */
+ public final byte[] scanlineb;
protected FilterType filterUsed; // informational ; only filled by the reader
- public final int channels; // copied from imgInfo, more handy
- public final int bitDepth; // copied from imgInfo, more handy
+ final int channels; // copied from imgInfo, more handy
+ final int bitDepth; // copied from imgInfo, more handy
+ final int elementsPerRow; // = imgInfo.samplePerRowPacked, if packed:imgInfo.samplePerRow elswhere
+
+ public enum SampleType {
+ INT, // 4 bytes per sample
+ // SHORT, // 2 bytes per sample
+ BYTE // 1 byte per sample
+ }
+
+ /**
+ * tells if we are using BYTE or INT to store the samples.
+ */
+ public final SampleType sampleType;
+
+ /**
+ * true: each element of the scanline array represents a sample always, even
+ * for internally packed PNG formats
+ *
+ * false: if the original image was of packed type (bit depth less than 8)
+ * we keep samples packed in a single array element
+ */
+ public final boolean samplesUnpacked;
+
+ /**
+ * default mode: INT packed
+ */
+ public ImageLine(final ImageInfo imgInfo) {
+ this(imgInfo, SampleType.INT, false);
+ }
+
+ /**
+ *
+ * @param imgInfo
+ * Inmutable ImageInfo, basic parameter of the image we are
+ * reading or writing
+ * @param stype
+ * INT or BYTE : this determines which scanline is the really
+ * used one
+ * @param unpackedMode
+ * If true, we use unpacked format, even for packed original
+ * images
+ *
+ */
+ public ImageLine(final ImageInfo imgInfo, final SampleType stype, final boolean unpackedMode) {
+ this(imgInfo, stype, unpackedMode, null, null);
+ }
- public ImageLine(ImageInfo imgInfo) {
+ /**
+ * If a preallocated array is passed, the copy is shallow
+ */
+ ImageLine(final ImageInfo imgInfo, final SampleType stype, final boolean unpackedMode, final int[] sci, final byte[] scb) {
this.imgInfo = imgInfo;
channels = imgInfo.channels;
- scanline = new int[imgInfo.samplesPerRowP];
- this.bitDepth = imgInfo.bitDepth;
+ bitDepth = imgInfo.bitDepth;
+ filterUsed = FilterType.FILTER_UNKNOWN;
+ this.sampleType = stype;
+ this.samplesUnpacked = unpackedMode || !imgInfo.packed;
+ elementsPerRow = this.samplesUnpacked ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked;
+ if (stype == SampleType.INT) {
+ scanline = sci != null ? sci : new int[elementsPerRow];
+ scanlineb = null;
+ } else if (stype == SampleType.BYTE) {
+ scanlineb = scb != null ? scb : new byte[elementsPerRow];
+ scanline = null;
+ } else
+ throw new PngjExceptionInternal("bad ImageLine initialization");
+ this.rown = -1;
}
/** This row number inside the image (0 is top) */
@@ -47,129 +117,217 @@ public class ImageLine {
return rown;
}
- /** Increments row number */
- public void incRown() {
- this.rown++;
- }
-
- /** Sets row number */
- public void setRown(int n) {
+ /** Sets row number (0 : Rows-1) */
+ public void setRown(final int n) {
this.rown = n;
}
- /** Sets scanline, making copy from passed array */
- public void setScanLine(int[] b) {
- System.arraycopy(b, 0, scanline, 0, scanline.length);
+ /*
+ * Unpacks scanline (for bitdepth 1-2-4)
+ *
+ * Arrays must be prealocated. src : samplesPerRowPacked dst : samplesPerRow
+ *
+ * This usually works in place (with src==dst and length=samplesPerRow)!
+ *
+ * If not, you should only call this only when necesary (bitdepth <8)
+ *
+ * If <code>scale==true<code>, it scales the value (just a bit shift) towards 0-255.
+ */
+ static void unpackInplaceInt(final ImageInfo iminfo, final int[] src, final int[] dst, final boolean scale) {
+ final int bitDepth = iminfo.bitDepth;
+ if (bitDepth >= 8)
+ return; // nothing to do
+ final int mask0 = ImageLineHelper.getMaskForPackedFormatsLs(bitDepth);
+ final int scalefactor = 8 - bitDepth;
+ final int offset0 = 8 * iminfo.samplesPerRowPacked - bitDepth * iminfo.samplesPerRow;
+ int mask, offset, v;
+ if (offset0 != 8) {
+ mask = mask0 << offset0;
+ offset = offset0; // how many bits to shift the mask to the right to recover mask0
+ } else {
+ mask = mask0;
+ offset = 0;
+ }
+ for (int j = iminfo.samplesPerRow - 1, i = iminfo.samplesPerRowPacked - 1; j >= 0; j--) {
+ v = (src[i] & mask) >> offset;
+ if (scale)
+ v <<= scalefactor;
+ dst[j] = v;
+ mask <<= bitDepth;
+ offset += bitDepth;
+ if (offset == 8) {
+ mask = mask0;
+ offset = 0;
+ i--;
+ }
+ }
}
- /**
- * Returns a copy from scanline, in byte array.
- *
- * You can (OPTIONALLY) pass an preallocated array to use.
- **/
- public int[] getScanLineCopy(int[] b) {
- if (b == null || b.length < scanline.length)
- b = new int[scanline.length];
- System.arraycopy(scanline, 0, b, 0, scanline.length);
- return b;
+ /*
+ * Unpacks scanline (for bitdepth 1-2-4)
+ *
+ * Arrays must be prealocated. src : samplesPerRow dst : samplesPerRowPacked
+ *
+ * This usually works in place (with src==dst and length=samplesPerRow)! If not, you should only call this only when
+ * necesary (bitdepth <8)
+ *
+ * The trailing elements are trash
+ *
+ *
+ * If <code>scale==true<code>, it scales the value (just a bit shift) towards 0-255.
+ */
+ static void packInplaceInt(final ImageInfo iminfo, final int[] src, final int[] dst, final boolean scaled) {
+ final int bitDepth = iminfo.bitDepth;
+ if (bitDepth >= 8)
+ return; // nothing to do
+ final int mask0 = ImageLineHelper.getMaskForPackedFormatsLs(bitDepth);
+ final int scalefactor = 8 - bitDepth;
+ final int offset0 = 8 - bitDepth;
+ int v, v0;
+ int offset = 8 - bitDepth;
+ v0 = src[0]; // first value is special for in place
+ dst[0] = 0;
+ if (scaled)
+ v0 >>= scalefactor;
+ v0 = ((v0 & mask0) << offset);
+ for (int i = 0, j = 0; j < iminfo.samplesPerRow; j++) {
+ v = src[j];
+ if (scaled)
+ v >>= scalefactor;
+ dst[i] |= ((v & mask0) << offset);
+ offset -= bitDepth;
+ if (offset < 0) {
+ offset = offset0;
+ i++;
+ dst[i] = 0;
+ }
+ }
+ dst[0] |= v0;
}
- /**
- * Unpacks scanline (for bitdepth 1-2-4) into buffer.
- * <p>
- * You can (OPTIONALLY) pass an preallocated array to use.
- * <p>
- * If scale==TRUE scales the value (just a bit shift).
- */
- public int[] tf_unpack(int[] buf, boolean scale) {
- int len = scanline.length;
- if (bitDepth == 1)
- len *= 8;
- else if (bitDepth == 2)
- len *= 4;
- else if (bitDepth == 4)
- len *= 2;
- if (buf == null)
- buf = new int[len];
+ static void unpackInplaceByte(final ImageInfo iminfo, final byte[] src, final byte[] dst, final boolean scale) {
+ final int bitDepth = iminfo.bitDepth;
if (bitDepth >= 8)
- System.arraycopy(scanline, 0, buf, 0, scanline.length);
- else {
- int mask, offset, v;
- int mask0 = getMaskForPackedFormats();
- int offset0 = 8 - bitDepth;
+ return; // nothing to do
+ final int mask0 = ImageLineHelper.getMaskForPackedFormatsLs(bitDepth);
+ final int scalefactor = 8 - bitDepth;
+ final int offset0 = 8 * iminfo.samplesPerRowPacked - bitDepth * iminfo.samplesPerRow;
+ int mask, offset, v;
+ if (offset0 != 8) {
+ mask = mask0 << offset0;
+ offset = offset0; // how many bits to shift the mask to the right to recover mask0
+ } else {
mask = mask0;
- offset = offset0;
- for (int i = 0, j = 0; i < len; i++) {
- v = (scanline[j] & mask) >> offset;
- if (scale)
- v <<= offset0;
- buf[i] = v;
- mask = mask >> bitDepth;
- offset -= bitDepth;
- if (mask == 0) { // new byte in source
- mask = mask0;
- offset = offset0;
- j++;
- }
+ offset = 0;
+ }
+ for (int j = iminfo.samplesPerRow - 1, i = iminfo.samplesPerRowPacked - 1; j >= 0; j--) {
+ v = (src[i] & mask) >> offset;
+ if (scale)
+ v <<= scalefactor;
+ dst[j] = (byte) v;
+ mask <<= bitDepth;
+ offset += bitDepth;
+ if (offset == 8) {
+ mask = mask0;
+ offset = 0;
+ i--;
}
}
- return buf;
}
/**
- * Packs scanline (for bitdepth 1-2-4) from buffer.
- * <p>
- * If scale==TRUE scales the value (just a bit shift).
- */
- public void tf_pack(int[] buf, boolean scale) { // writes scanline
- int len = scanline.length;
- if (bitDepth == 1)
- len *= 8;
- else if (bitDepth == 2)
- len *= 4;
- else if (bitDepth == 4)
- len *= 2;
+ * size original: samplesPerRow sizeFinal: samplesPerRowPacked (trailing
+ * elements are trash!)
+ **/
+ static void packInplaceByte(final ImageInfo iminfo, final byte[] src, final byte[] dst, final boolean scaled) {
+ final int bitDepth = iminfo.bitDepth;
if (bitDepth >= 8)
- System.arraycopy(buf, 0, scanline, 0, scanline.length);
- else {
- int offset0 = 8 - bitDepth;
- int mask0 = getMaskForPackedFormats() >> offset0;
- int offset, v;
- offset = offset0;
- Arrays.fill(scanline, 0);
- for (int i = 0, j = 0; i < len; i++) {
- v = buf[i];
- if (scale)
- v >>= offset0;
- v = (v & mask0) << offset;
- scanline[j] |= v;
- offset -= bitDepth;
- if (offset < 0) { // new byte in scanline
- offset = offset0;
- j++;
- }
+ return; // nothing to do
+ final int mask0 = ImageLineHelper.getMaskForPackedFormatsLs(bitDepth);
+ final int scalefactor = 8 - bitDepth;
+ final int offset0 = 8 - bitDepth;
+ int v, v0;
+ int offset = 8 - bitDepth;
+ v0 = src[0]; // first value is special
+ dst[0] = 0;
+ if (scaled)
+ v0 >>= scalefactor;
+ v0 = ((v0 & mask0) << offset);
+ for (int i = 0, j = 0; j < iminfo.samplesPerRow; j++) {
+ v = src[j];
+ if (scaled)
+ v >>= scalefactor;
+ dst[i] |= ((v & mask0) << offset);
+ offset -= bitDepth;
+ if (offset < 0) {
+ offset = offset0;
+ i++;
+ dst[i] = 0;
}
}
+ dst[0] |= v0;
}
- private int getMaskForPackedFormats() { // Utility function for pacj/unpack
- if (bitDepth == 1)
- return 0x80;
- if (bitDepth == 2)
- return 0xc0;
- if (bitDepth == 4)
- return 0xf0;
- throw new RuntimeException("?");
+ /**
+ * Creates a new ImageLine similar to this, but unpacked
+ *
+ * The caller must be sure that the original was really packed
+ */
+ public ImageLine unpackToNewImageLine() {
+ final ImageLine newline = new ImageLine(imgInfo, sampleType, true);
+ if (sampleType == SampleType.INT)
+ unpackInplaceInt(imgInfo, scanline, newline.scanline, false);
+ else
+ unpackInplaceByte(imgInfo, scanlineb, newline.scanlineb, false);
+ return newline;
+ }
+
+ /**
+ * Creates a new ImageLine similar to this, but packed
+ *
+ * The caller must be sure that the original was really unpacked
+ */
+ public ImageLine packToNewImageLine() {
+ final ImageLine newline = new ImageLine(imgInfo, sampleType, false);
+ if (sampleType == SampleType.INT)
+ packInplaceInt(imgInfo, scanline, newline.scanline, false);
+ else
+ packInplaceByte(imgInfo, scanlineb, newline.scanlineb, false);
+ return newline;
}
public FilterType getFilterUsed() {
return filterUsed;
}
+ public void setFilterUsed(final FilterType ft) {
+ filterUsed = ft;
+ }
+
+ public int[] getScanlineInt() {
+ return scanline;
+ }
+
+ public byte[] getScanlineByte() {
+ return scanlineb;
+ }
+
/**
* Basic info
*/
+ @Override
public String toString() {
return "row=" + rown + " cols=" + imgInfo.cols + " bpc=" + imgInfo.bitDepth + " size=" + scanline.length;
}
+
+ /**
+ * Prints some statistics - just for debugging
+ */
+ public static void showLineInfo(final ImageLine line) {
+ System.out.println(line);
+ final ImageLineStats stats = new ImageLineHelper.ImageLineStats(line);
+ System.out.println(stats);
+ System.out.println(ImageLineHelper.infoFirstLastPixels(line));
+ }
+
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java
new file mode 100644
index 000000000..616ccd560
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java
@@ -0,0 +1,329 @@
+package jogamp.opengl.util.pngj;
+
+import jogamp.opengl.util.pngj.ImageLine.SampleType;
+import jogamp.opengl.util.pngj.chunks.PngChunkPLTE;
+import jogamp.opengl.util.pngj.chunks.PngChunkTRNS;
+
+/**
+ * Bunch of utility static methods to process/analyze an image line at the pixel
+ * level.
+ * <p>
+ * Not essential at all, some methods are probably to be removed if future
+ * releases.
+ * <p>
+ * WARNING: most methods for getting/setting values work currently only for
+ * integer base imageLines
+ */
+public class ImageLineHelper {
+
+ private final static double BIG_VALUE = Double.MAX_VALUE * 0.5;
+
+ private final static double BIG_VALUE_NEG = Double.MAX_VALUE * (-0.5);
+
+ /**
+ * Given an indexed line with a palette, unpacks as a RGB array, or RGBA if
+ * a non nul PngChunkTRNS chunk is passed
+ *
+ * @param line
+ * ImageLine as returned from PngReader
+ * @param pal
+ * Palette chunk
+ * @param buf
+ * Preallocated array, optional
+ * @return R G B (A), one sample 0-255 per array element. Ready for
+ * pngw.writeRowInt()
+ */
+ public static int[] palette2rgb(ImageLine line, final PngChunkPLTE pal, final PngChunkTRNS trns, int[] buf) {
+ final boolean isalpha = trns != null;
+ final int channels = isalpha ? 4 : 3;
+ final int nsamples = line.imgInfo.cols * channels;
+ if (buf == null || buf.length < nsamples)
+ buf = new int[nsamples];
+ if (!line.samplesUnpacked)
+ line = line.unpackToNewImageLine();
+ final boolean isbyte = line.sampleType == SampleType.BYTE;
+ final int nindexesWithAlpha = trns != null ? trns.getPalletteAlpha().length : 0;
+ for (int c = 0; c < line.imgInfo.cols; c++) {
+ final int index = isbyte ? (line.scanlineb[c] & 0xFF) : line.scanline[c];
+ pal.getEntryRgb(index, buf, c * channels);
+ if (isalpha) {
+ final int alpha = index < nindexesWithAlpha ? trns.getPalletteAlpha()[index] : 255;
+ buf[c * channels + 3] = alpha;
+ }
+ }
+ return buf;
+ }
+
+ public static int[] palette2rgb(final ImageLine line, final PngChunkPLTE pal, final int[] buf) {
+ return palette2rgb(line, pal, null, buf);
+ }
+
+ /**
+ * what follows is pretty uninteresting/untested/obsolete, subject to change
+ */
+ /**
+ * Just for basic info or debugging. Shows values for first and last pixel.
+ * Does not include alpha
+ */
+ public static String infoFirstLastPixels(final ImageLine line) {
+ return line.imgInfo.channels == 1 ? String.format("first=(%d) last=(%d)", line.scanline[0],
+ line.scanline[line.scanline.length - 1]) : String.format("first=(%d %d %d) last=(%d %d %d)",
+ line.scanline[0], line.scanline[1], line.scanline[2], line.scanline[line.scanline.length
+ - line.imgInfo.channels], line.scanline[line.scanline.length - line.imgInfo.channels + 1],
+ line.scanline[line.scanline.length - line.imgInfo.channels + 2]);
+ }
+
+ public static String infoFull(final ImageLine line) {
+ final ImageLineStats stats = new ImageLineStats(line);
+ return "row=" + line.getRown() + " " + stats.toString() + "\n " + infoFirstLastPixels(line);
+ }
+
+ /**
+ * Computes some statistics for the line. Not very efficient or elegant,
+ * mainly for tests. Only for RGB/RGBA Outputs values as doubles (0.0 - 1.0)
+ */
+ static class ImageLineStats {
+ public double[] prom = { 0.0, 0.0, 0.0, 0.0 }; // channel averages
+ public double[] maxv = { BIG_VALUE_NEG, BIG_VALUE_NEG, BIG_VALUE_NEG, BIG_VALUE_NEG }; // maximo
+ public double[] minv = { BIG_VALUE, BIG_VALUE, BIG_VALUE, BIG_VALUE };
+ public double promlum = 0.0; // maximum global (luminance)
+ public double maxlum = BIG_VALUE_NEG; // max luminance
+ public double minlum = BIG_VALUE;
+ public double[] maxdif = { BIG_VALUE_NEG, BIG_VALUE_NEG, BIG_VALUE_NEG, BIG_VALUE }; // maxima
+ public final int channels; // diferencia
+
+ @Override
+ public String toString() {
+ return channels == 3 ? String.format(
+ "prom=%.1f (%.1f %.1f %.1f) max=%.1f (%.1f %.1f %.1f) min=%.1f (%.1f %.1f %.1f)", promlum, prom[0],
+ prom[1], prom[2], maxlum, maxv[0], maxv[1], maxv[2], minlum, minv[0], minv[1], minv[2])
+ + String.format(" maxdif=(%.1f %.1f %.1f)", maxdif[0], maxdif[1], maxdif[2]) : String.format(
+ "prom=%.1f (%.1f %.1f %.1f %.1f) max=%.1f (%.1f %.1f %.1f %.1f) min=%.1f (%.1f %.1f %.1f %.1f)",
+ promlum, prom[0], prom[1], prom[2], prom[3], maxlum, maxv[0], maxv[1], maxv[2], maxv[3], minlum,
+ minv[0], minv[1], minv[2], minv[3])
+ + String.format(" maxdif=(%.1f %.1f %.1f %.1f)", maxdif[0], maxdif[1], maxdif[2], maxdif[3]);
+ }
+
+ public ImageLineStats(final ImageLine line) {
+ this.channels = line.channels;
+ if (line.channels < 3)
+ throw new PngjException("ImageLineStats only works for RGB - RGBA");
+ int ch = 0;
+ double lum, x, d;
+ for (int i = 0; i < line.imgInfo.cols; i++) {
+ lum = 0;
+ for (ch = channels - 1; ch >= 0; ch--) {
+ x = int2double(line, line.scanline[i * channels]);
+ if (ch < 3)
+ lum += x;
+ prom[ch] += x;
+ if (x > maxv[ch])
+ maxv[ch] = x;
+ if (x < minv[ch])
+ minv[ch] = x;
+ if (i >= channels) {
+ d = Math.abs(x - int2double(line, line.scanline[i - channels]));
+ if (d > maxdif[ch])
+ maxdif[ch] = d;
+ }
+ }
+ promlum += lum;
+ if (lum > maxlum)
+ maxlum = lum;
+ if (lum < minlum)
+ minlum = lum;
+ }
+ for (ch = 0; ch < channels; ch++) {
+ prom[ch] /= line.imgInfo.cols;
+ }
+ promlum /= (line.imgInfo.cols * 3.0);
+ maxlum /= 3.0;
+ minlum /= 3.0;
+ }
+ }
+
+ /**
+ * integer packed R G B only for bitdepth=8! (does not check!)
+ *
+ **/
+ public static int getPixelRGB8(final ImageLine line, final int column) {
+ final int offset = column * line.channels;
+ return (line.scanline[offset] << 16) + (line.scanline[offset + 1] << 8) + (line.scanline[offset + 2]);
+ }
+
+ public static int getPixelARGB8(final ImageLine line, final int column) {
+ final int offset = column * line.channels;
+ return (line.scanline[offset + 3] << 24) + (line.scanline[offset] << 16) + (line.scanline[offset + 1] << 8)
+ + (line.scanline[offset + 2]);
+ }
+
+ public static void setPixelsRGB8(final ImageLine line, final int[] rgb) {
+ for (int i = 0, j = 0; i < line.imgInfo.cols; i++) {
+ line.scanline[j++] = ((rgb[i] >> 16) & 0xFF);
+ line.scanline[j++] = ((rgb[i] >> 8) & 0xFF);
+ line.scanline[j++] = ((rgb[i] & 0xFF));
+ }
+ }
+
+ public static void setPixelRGB8(final ImageLine line, int col, final int r, final int g, final int b) {
+ col *= line.channels;
+ line.scanline[col++] = r;
+ line.scanline[col++] = g;
+ line.scanline[col] = b;
+ }
+
+ public static void setPixelRGB8(final ImageLine line, final int col, final int rgb) {
+ setPixelRGB8(line, col, (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
+ }
+
+ public static void setPixelsRGBA8(final ImageLine line, final int[] rgb) {
+ for (int i = 0, j = 0; i < line.imgInfo.cols; i++) {
+ line.scanline[j++] = ((rgb[i] >> 16) & 0xFF);
+ line.scanline[j++] = ((rgb[i] >> 8) & 0xFF);
+ line.scanline[j++] = ((rgb[i] & 0xFF));
+ line.scanline[j++] = ((rgb[i] >> 24) & 0xFF);
+ }
+ }
+
+ public static void setPixelRGBA8(final ImageLine line, int col, final int r, final int g, final int b, final int a) {
+ col *= line.channels;
+ line.scanline[col++] = r;
+ line.scanline[col++] = g;
+ line.scanline[col++] = b;
+ line.scanline[col] = a;
+ }
+
+ public static void setPixelRGBA8(final ImageLine line, final int col, final int rgb) {
+ setPixelRGBA8(line, col, (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF, (rgb >> 24) & 0xFF);
+ }
+
+ public static void setValD(final ImageLine line, final int i, final double d) {
+ line.scanline[i] = double2int(line, d);
+ }
+
+ public static int interpol(final int a, final int b, final int c, final int d, final double dx, final double dy) {
+ // a b -> x (0-1)
+ // c d
+ //
+ final double e = a * (1.0 - dx) + b * dx;
+ final double f = c * (1.0 - dx) + d * dx;
+ return (int) (e * (1 - dy) + f * dy + 0.5);
+ }
+
+ public static double int2double(final ImageLine line, final int p) {
+ return line.bitDepth == 16 ? p / 65535.0 : p / 255.0;
+ // TODO: replace my multiplication? check for other bitdepths
+ }
+
+ public static double int2doubleClamped(final ImageLine line, final int p) {
+ // TODO: replace my multiplication?
+ final double d = line.bitDepth == 16 ? p / 65535.0 : p / 255.0;
+ return d <= 0.0 ? 0 : (d >= 1.0 ? 1.0 : d);
+ }
+
+ public static int double2int(final ImageLine line, double d) {
+ d = d <= 0.0 ? 0 : (d >= 1.0 ? 1.0 : d);
+ return line.bitDepth == 16 ? (int) (d * 65535.0 + 0.5) : (int) (d * 255.0 + 0.5); //
+ }
+
+ public static int double2intClamped(final ImageLine line, double d) {
+ d = d <= 0.0 ? 0 : (d >= 1.0 ? 1.0 : d);
+ return line.bitDepth == 16 ? (int) (d * 65535.0 + 0.5) : (int) (d * 255.0 + 0.5); //
+ }
+
+ public static int clampTo_0_255(final int i) {
+ return i > 255 ? 255 : (i < 0 ? 0 : i);
+ }
+
+ public static int clampTo_0_65535(final int i) {
+ return i > 65535 ? 65535 : (i < 0 ? 0 : i);
+ }
+
+ public static int clampTo_128_127(final int x) {
+ return x > 127 ? 127 : (x < -128 ? -128 : x);
+ }
+
+ /**
+ * Unpacks scanline (for bitdepth 1-2-4) into a array <code>int[]</code>
+ * <p>
+ * You can (OPTIONALLY) pass an preallocated array, that will be filled and
+ * returned. If null, it will be allocated
+ * <p>
+ * If
+ * <code>scale==true<code>, it scales the value (just a bit shift) towards 0-255.
+ * <p>
+ * You probably should use {@link ImageLine#unpackToNewImageLine()}
+ *
+ */
+ public static int[] unpack(final ImageInfo imgInfo, final int[] src, int[] dst, final boolean scale) {
+ final int len1 = imgInfo.samplesPerRow;
+ final int len0 = imgInfo.samplesPerRowPacked;
+ if (dst == null || dst.length < len1)
+ dst = new int[len1];
+ if (imgInfo.packed)
+ ImageLine.unpackInplaceInt(imgInfo, src, dst, scale);
+ else
+ System.arraycopy(src, 0, dst, 0, len0);
+ return dst;
+ }
+
+ public static byte[] unpack(final ImageInfo imgInfo, final byte[] src, byte[] dst, final boolean scale) {
+ final int len1 = imgInfo.samplesPerRow;
+ final int len0 = imgInfo.samplesPerRowPacked;
+ if (dst == null || dst.length < len1)
+ dst = new byte[len1];
+ if (imgInfo.packed)
+ ImageLine.unpackInplaceByte(imgInfo, src, dst, scale);
+ else
+ System.arraycopy(src, 0, dst, 0, len0);
+ return dst;
+ }
+
+ /**
+ * Packs scanline (for bitdepth 1-2-4) from array into the scanline
+ * <p>
+ * If <code>scale==true<code>, it scales the value (just a bit shift).
+ *
+ * You probably should use {@link ImageLine#packToNewImageLine()}
+ */
+ public static int[] pack(final ImageInfo imgInfo, final int[] src, int[] dst, final boolean scale) {
+ final int len0 = imgInfo.samplesPerRowPacked;
+ if (dst == null || dst.length < len0)
+ dst = new int[len0];
+ if (imgInfo.packed)
+ ImageLine.packInplaceInt(imgInfo, src, dst, scale);
+ else
+ System.arraycopy(src, 0, dst, 0, len0);
+ return dst;
+ }
+
+ public static byte[] pack(final ImageInfo imgInfo, final byte[] src, byte[] dst, final boolean scale) {
+ final int len0 = imgInfo.samplesPerRowPacked;
+ if (dst == null || dst.length < len0)
+ dst = new byte[len0];
+ if (imgInfo.packed)
+ ImageLine.packInplaceByte(imgInfo, src, dst, scale);
+ else
+ System.arraycopy(src, 0, dst, 0, len0);
+ return dst;
+ }
+
+ static int getMaskForPackedFormats(final int bitDepth) { // Utility function for pack/unpack
+ if (bitDepth == 4)
+ return 0xf0;
+ else if (bitDepth == 2)
+ return 0xc0;
+ else
+ return 0x80; // bitDepth == 1
+ }
+
+ static int getMaskForPackedFormatsLs(final int bitDepth) { // Utility function for pack/unpack
+ if (bitDepth == 4)
+ return 0x0f;
+ else if (bitDepth == 2)
+ return 0x03;
+ else
+ return 0x01; // bitDepth == 1
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java
new file mode 100644
index 000000000..8f6216ab2
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java
@@ -0,0 +1,107 @@
+package jogamp.opengl.util.pngj;
+
+import jogamp.opengl.util.pngj.ImageLine.SampleType;
+
+/**
+ * Wraps in a matrix a set of image rows, not necessarily contiguous - but
+ * equispaced.
+ *
+ * The fields mirrors those of {@link ImageLine}, and you can access each row as
+ * a ImageLine backed by the matrix row, see
+ * {@link #getImageLineAtMatrixRow(int)}
+ */
+public class ImageLines {
+
+ public final ImageInfo imgInfo;
+ public final int channels;
+ public final int bitDepth;
+ public final SampleType sampleType;
+ public final boolean samplesUnpacked;
+ public final int elementsPerRow;
+ public final int rowOffset;
+ public final int nRows;
+ public final int rowStep;
+ public final int[][] scanlines;
+ public final byte[][] scanlinesb;
+
+ /**
+ * Allocates a matrix to store {@code nRows} image rows. See
+ * {@link ImageLine} and {@link PngReader#readRowsInt()}
+ * {@link PngReader#readRowsByte()}
+ *
+ * @param imgInfo
+ * @param stype
+ * @param unpackedMode
+ * @param rowOffset
+ * @param nRows
+ * @param rowStep
+ */
+ public ImageLines(final ImageInfo imgInfo, final SampleType stype, final boolean unpackedMode, final int rowOffset, final int nRows, final int rowStep) {
+ this.imgInfo = imgInfo;
+ channels = imgInfo.channels;
+ bitDepth = imgInfo.bitDepth;
+ this.sampleType = stype;
+ this.samplesUnpacked = unpackedMode || !imgInfo.packed;
+ elementsPerRow = unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked;
+ this.rowOffset = rowOffset;
+ this.nRows = nRows;
+ this.rowStep = rowStep;
+ if (stype == SampleType.INT) {
+ scanlines = new int[nRows][elementsPerRow];
+ scanlinesb = null;
+ } else if (stype == SampleType.BYTE) {
+ scanlinesb = new byte[nRows][elementsPerRow];
+ scanlines = null;
+ } else
+ throw new PngjExceptionInternal("bad ImageLine initialization");
+ }
+
+ /**
+ * Warning: this always returns a valid matrix row (clamping on 0 : nrows-1,
+ * and rounding down) Eg: rowOffset=4,rowStep=2 imageRowToMatrixRow(17)
+ * returns 6 , imageRowToMatrixRow(1) returns 0
+ */
+ public int imageRowToMatrixRow(final int imrow) {
+ final int r = (imrow - rowOffset) / rowStep;
+ return r < 0 ? 0 : (r < nRows ? r : nRows - 1);
+ }
+
+ /**
+ * Same as imageRowToMatrixRow, but returns negative if invalid
+ */
+ public int imageRowToMatrixRowStrict(int imrow) {
+ imrow -= rowOffset;
+ final int mrow = imrow >= 0 && imrow % rowStep == 0 ? imrow / rowStep : -1;
+ return mrow < nRows ? mrow : -1;
+ }
+
+ /**
+ * Converts from matrix row number (0 : nRows-1) to image row number
+ *
+ * @param mrow
+ * Matrix row number
+ * @return Image row number. Invalid only if mrow is invalid
+ */
+ public int matrixRowToImageRow(final int mrow) {
+ return mrow * rowStep + rowOffset;
+ }
+
+ /**
+ * Returns a ImageLine is backed by the matrix, no allocation done
+ *
+ * @param mrow
+ * Matrix row, from 0 to nRows This is not necessarily the image
+ * row, see {@link #imageRowToMatrixRow(int)} and
+ * {@link #matrixRowToImageRow(int)}
+ * @return A new ImageLine, backed by the matrix, with the correct ('real')
+ * rownumber
+ */
+ public ImageLine getImageLineAtMatrixRow(final int mrow) {
+ if (mrow < 0 || mrow > nRows)
+ throw new PngjException("Bad row " + mrow + ". Should be positive and less than " + nRows);
+ final ImageLine imline = sampleType == SampleType.INT ? new ImageLine(imgInfo, sampleType, samplesUnpacked,
+ scanlines[mrow], null) : new ImageLine(imgInfo, sampleType, samplesUnpacked, null, scanlinesb[mrow]);
+ imline.setRown(matrixRowToImageRow(mrow));
+ return imline;
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngDeinterlacer.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngDeinterlacer.java
new file mode 100644
index 000000000..436821cf7
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngDeinterlacer.java
@@ -0,0 +1,277 @@
+package jogamp.opengl.util.pngj;
+
+import java.util.Random;
+
+// you really dont' want to peek inside this
+class PngDeinterlacer {
+ private final ImageInfo imi;
+ private int pass; // 1-7
+ private int rows, cols, dY, dX, oY, oX, oXsamples, dXsamples; // at current pass
+ // current row in the virtual subsampled image; this incrementes from 0 to cols/dy 7 times
+ private int currRowSubimg = -1;
+ // in the real image, this will cycle from 0 to im.rows in different steps, 7 times
+ private int currRowReal = -1;
+
+ private final int packedValsPerPixel;
+ private final int packedMask;
+ private final int packedShift;
+
+ private int[][] imageInt; // FULL image -only used for PngWriter as temporary storage
+ private short[][] imageShort;
+ private byte[][] imageByte;
+
+ PngDeinterlacer(final ImageInfo iminfo) {
+ this.imi = iminfo;
+ pass = 0;
+ if (imi.packed) {
+ packedValsPerPixel = 8 / imi.bitDepth;
+ packedShift = imi.bitDepth;
+ if (imi.bitDepth == 1)
+ packedMask = 0x80;
+ else if (imi.bitDepth == 2)
+ packedMask = 0xc0;
+ else
+ packedMask = 0xf0;
+ } else {
+ packedMask = packedShift = packedValsPerPixel = 1;// dont care
+ }
+ setPass(1);
+ setRow(0);
+ }
+
+ /** this refers to the row currRowSubimg */
+ void setRow(final int n) {
+ currRowSubimg = n;
+ currRowReal = n * dY + oY;
+ if (currRowReal < 0 || currRowReal >= imi.rows)
+ throw new PngjExceptionInternal("bad row - this should not happen");
+ }
+
+ void setPass(final int p) {
+ if (this.pass == p)
+ return;
+ pass = p;
+ switch (pass) {
+ case 1:
+ dY = dX = 8;
+ oX = oY = 0;
+ break;
+ case 2:
+ dY = dX = 8;
+ oX = 4;
+ oY = 0;
+ break;
+ case 3:
+ dX = 4;
+ dY = 8;
+ oX = 0;
+ oY = 4;
+ break;
+ case 4:
+ dX = dY = 4;
+ oX = 2;
+ oY = 0;
+ break;
+ case 5:
+ dX = 2;
+ dY = 4;
+ oX = 0;
+ oY = 2;
+ break;
+ case 6:
+ dX = dY = 2;
+ oX = 1;
+ oY = 0;
+ break;
+ case 7:
+ dX = 1;
+ dY = 2;
+ oX = 0;
+ oY = 1;
+ break;
+ default:
+ throw new PngjExceptionInternal("bad interlace pass" + pass);
+ }
+ rows = (imi.rows - oY) / dY + 1;
+ if ((rows - 1) * dY + oY >= imi.rows)
+ rows--; // can be 0
+ cols = (imi.cols - oX) / dX + 1;
+ if ((cols - 1) * dX + oX >= imi.cols)
+ cols--; // can be 0
+ if (cols == 0)
+ rows = 0; // really...
+ dXsamples = dX * imi.channels;
+ oXsamples = oX * imi.channels;
+ }
+
+ // notice that this is a "partial" deinterlace, it will be called several times for the same row!
+ void deinterlaceInt(final int[] src, final int[] dst, final boolean readInPackedFormat) {
+ if (!(imi.packed && readInPackedFormat))
+ for (int i = 0, j = oXsamples; i < cols * imi.channels; i += imi.channels, j += dXsamples)
+ for (int k = 0; k < imi.channels; k++)
+ dst[j + k] = src[i + k];
+ else
+ deinterlaceIntPacked(src, dst);
+ }
+
+ // interlaced+packed = monster; this is very clumsy!
+ private void deinterlaceIntPacked(final int[] src, final int[] dst) {
+ int spos, smod, smask; // source byte position, bits to shift to left (01,2,3,4
+ int tpos, tmod, p, d;
+ spos = 0;
+ smask = packedMask;
+ smod = -1;
+ // can this really work?
+ for (int i = 0, j = oX; i < cols; i++, j += dX) {
+ spos = i / packedValsPerPixel;
+ smod += 1;
+ if (smod >= packedValsPerPixel)
+ smod = 0;
+ smask >>= packedShift; // the source mask cycles
+ if (smod == 0)
+ smask = packedMask;
+ tpos = j / packedValsPerPixel;
+ tmod = j % packedValsPerPixel;
+ p = src[spos] & smask;
+ d = tmod - smod;
+ if (d > 0)
+ p >>= (d * packedShift);
+ else if (d < 0)
+ p <<= ((-d) * packedShift);
+ dst[tpos] |= p;
+ }
+ }
+
+ // yes, duplication of code is evil, normally
+ void deinterlaceByte(final byte[] src, final byte[] dst, final boolean readInPackedFormat) {
+ if (!(imi.packed && readInPackedFormat))
+ for (int i = 0, j = oXsamples; i < cols * imi.channels; i += imi.channels, j += dXsamples)
+ for (int k = 0; k < imi.channels; k++)
+ dst[j + k] = src[i + k];
+ else
+ deinterlacePackedByte(src, dst);
+ }
+
+ private void deinterlacePackedByte(final byte[] src, final byte[] dst) {
+ int spos, smod, smask; // source byte position, bits to shift to left (01,2,3,4
+ int tpos, tmod, p, d;
+ // what the heck are you reading here? I told you would not enjoy this. Try Dostoyevsky or Simone Weil instead
+ spos = 0;
+ smask = packedMask;
+ smod = -1;
+ // Arrays.fill(dst, 0);
+ for (int i = 0, j = oX; i < cols; i++, j += dX) {
+ spos = i / packedValsPerPixel;
+ smod += 1;
+ if (smod >= packedValsPerPixel)
+ smod = 0;
+ smask >>= packedShift; // the source mask cycles
+ if (smod == 0)
+ smask = packedMask;
+ tpos = j / packedValsPerPixel;
+ tmod = j % packedValsPerPixel;
+ p = src[spos] & smask;
+ d = tmod - smod;
+ if (d > 0)
+ p >>= (d * packedShift);
+ else if (d < 0)
+ p <<= ((-d) * packedShift);
+ dst[tpos] |= p;
+ }
+ }
+
+ /**
+ * Is current row the last row for the lass pass??
+ */
+ boolean isAtLastRow() {
+ return pass == 7 && currRowSubimg == rows - 1;
+ }
+
+ /**
+ * current row number inside the "sub image"
+ */
+ int getCurrRowSubimg() {
+ return currRowSubimg;
+ }
+
+ /**
+ * current row number inside the "real image"
+ */
+ int getCurrRowReal() {
+ return currRowReal;
+ }
+
+ /**
+ * current pass number (1-7)
+ */
+ int getPass() {
+ return pass;
+ }
+
+ /**
+ * How many rows has the current pass?
+ **/
+ int getRows() {
+ return rows;
+ }
+
+ /**
+ * How many columns (pixels) are there in the current row
+ */
+ int getCols() {
+ return cols;
+ }
+
+ public int getPixelsToRead() {
+ return getCols();
+ }
+
+ int[][] getImageInt() {
+ return imageInt;
+ }
+
+ void setImageInt(final int[][] imageInt) {
+ this.imageInt = imageInt;
+ }
+
+ short[][] getImageShort() {
+ return imageShort;
+ }
+
+ void setImageShort(final short[][] imageShort) {
+ this.imageShort = imageShort;
+ }
+
+ byte[][] getImageByte() {
+ return imageByte;
+ }
+
+ void setImageByte(final byte[][] imageByte) {
+ this.imageByte = imageByte;
+ }
+
+ static void test() {
+ final Random rand = new Random();
+ final PngDeinterlacer ih = new PngDeinterlacer(new ImageInfo(rand.nextInt(35) + 1, rand.nextInt(52) + 1, 8, true));
+ int np = ih.imi.cols * ih.imi.rows;
+ System.out.println(ih.imi);
+ for (int p = 1; p <= 7; p++) {
+ ih.setPass(p);
+ for (int row = 0; row < ih.getRows(); row++) {
+ ih.setRow(row);
+ final int b = ih.getCols();
+ np -= b;
+ System.out.printf("Read %d pixels. Pass:%d Realline:%d cols=%d dX=%d oX=%d last:%b\n", b, ih.pass,
+ ih.currRowReal, ih.cols, ih.dX, ih.oX, ih.isAtLastRow());
+
+ }
+ }
+ if (np != 0)
+ throw new PngjExceptionInternal("wtf??" + ih.imi);
+ }
+
+ public static void main(final String[] args) {
+ test();
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngHelper.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngHelper.java
deleted file mode 100644
index 1016b1b64..000000000
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngHelper.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package jogamp.opengl.util.pngj;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.zip.CRC32;
-
-/**
- * Some utility static methods.
- * <p>
- * See also <code>FileHelper</code> (if not sandboxed).
- * <p>
- * Client code should rarely need these methods.
- */
-public class PngHelper {
- /**
- * Default charset, used internally by PNG for several things
- */
- public static Charset charsetLatin1 = Charset.forName("ISO-8859-1");
- public static Charset charsetUTF8 = Charset.forName("UTF-8"); // only for some chunks
-
- static boolean DEBUG = false;
-
- public static int readByte(InputStream is) {
- try {
- return is.read();
- } catch (IOException e) {
- throw new PngjOutputException(e);
- }
- }
-
- /**
- * -1 if eof
- *
- * PNG uses "network byte order"
- */
- public static int readInt2(InputStream is) {
- try {
- int b1 = is.read();
- int b2 = is.read();
- if (b1 == -1 || b2 == -1)
- return -1;
- return (b1 << 8) + b2;
- } catch (IOException e) {
- throw new PngjInputException("error reading readInt2", e);
- }
- }
-
- /**
- * -1 if eof
- */
- public static int readInt4(InputStream is) {
- try {
- int b1 = is.read();
- int b2 = is.read();
- int b3 = is.read();
- int b4 = is.read();
- if (b1 == -1 || b2 == -1 || b3 == -1 || b4 == -1)
- return -1;
- return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
- } catch (IOException e) {
- throw new PngjInputException("error reading readInt4", e);
- }
- }
-
- public static int readInt1fromByte(byte[] b, int offset) {
- return (b[offset] & 0xff);
- }
-
- public static int readInt2fromBytes(byte[] b, int offset) {
- return ((b[offset] & 0xff) << 16) | ((b[offset + 1] & 0xff));
- }
-
- public static int readInt4fromBytes(byte[] b, int offset) {
- return ((b[offset] & 0xff) << 24) | ((b[offset + 1] & 0xff) << 16) | ((b[offset + 2] & 0xff) << 8)
- | (b[offset + 3] & 0xff);
- }
-
- public static void writeByte(OutputStream os, byte b) {
- try {
- os.write(b);
- } catch (IOException e) {
- throw new PngjOutputException(e);
- }
- }
-
- public static void writeInt2(OutputStream os, int n) {
- byte[] temp = { (byte) ((n >> 8) & 0xff), (byte) (n & 0xff) };
- writeBytes(os, temp);
- }
-
- public static void writeInt4(OutputStream os, int n) {
- byte[] temp = new byte[4];
- writeInt4tobytes(n, temp, 0);
- writeBytes(os, temp);
- }
-
- public static void writeInt2tobytes(int n, byte[] b, int offset) {
- b[offset] = (byte) ((n >> 8) & 0xff);
- b[offset + 1] = (byte) (n & 0xff);
- }
-
- public static void writeInt4tobytes(int n, byte[] b, int offset) {
- b[offset] = (byte) ((n >> 24) & 0xff);
- b[offset + 1] = (byte) ((n >> 16) & 0xff);
- b[offset + 2] = (byte) ((n >> 8) & 0xff);
- b[offset + 3] = (byte) (n & 0xff);
- }
-
- /**
- * guaranteed to read exactly len bytes. throws error if it cant
- */
- public static void readBytes(InputStream is, byte[] b, int offset, int len) {
- if (len == 0)
- return;
- try {
- int read = 0;
- while (read < len) {
- int n = is.read(b, offset + read, len - read);
- if (n < 1)
- throw new RuntimeException("error reading bytes, " + n + " !=" + len);
- read += n;
- }
- } catch (IOException e) {
- throw new PngjInputException("error reading", e);
- }
- }
-
- public static void writeBytes(OutputStream os, byte[] b) {
- try {
- os.write(b);
- } catch (IOException e) {
- throw new PngjOutputException(e);
- }
- }
-
- public static void writeBytes(OutputStream os, byte[] b, int offset, int n) {
- try {
- os.write(b, offset, n);
- } catch (IOException e) {
- throw new PngjOutputException(e);
- }
- }
-
- public static void logdebug(String msg) {
- if (DEBUG)
- System.out.println(msg);
- }
-
- public static Set<String> asSet(String... values) {
- return new HashSet<String>(java.util.Arrays.asList(values));
- }
-
- public static Set<String> unionSets(Set<String> set1, Set<String> set2) {
- Set<String> s = new HashSet<String>();
- s.addAll(set1);
- s.addAll(set2);
- return s;
- }
-
- public static Set<String> unionSets(Set<String> set1, Set<String> set2, Set<String> set3) {
- Set<String> s = new HashSet<String>();
- s.addAll(set1);
- s.addAll(set2);
- s.addAll(set3);
- return s;
- }
-
- private static final ThreadLocal<CRC32> crcProvider = new ThreadLocal<CRC32>() {
- protected CRC32 initialValue() {
- return new CRC32();
- }
- };
-
- /** thread-singleton crc engine */
- public static CRC32 getCRC() {
- return crcProvider.get();
- }
-
- static final byte[] pngIdBytes = { -119, 80, 78, 71, 13, 10, 26, 10 }; // png magic
-
- public static double resMetersToDpi(long res) {
- return (double) res * 0.0254;
- }
-
- public static long resDpiToMeters(double dpi) {
- return (long) (dpi / 0.0254 + 0.5);
- }
-
- public static int doubleToInt100000(double d) {
- return (int) (d * 100000.0 + 0.5);
- }
-
- public static double intToDouble100000(int i) {
- return i / 100000.0;
- }
-
- public static int clampTo_0_255(int i) {
- return i > 255 ? 255 : (i < 0 ? 0 : i);
- }
-
- public static int clampTo_0_65535(int i) {
- return i > 65535 ? 65535 : (i < 0 ? 0 : i);
- }
-
- public static int clampTo_128_127(int x) {
- return x > 127 ? 127 : (x < -128 ? -128 : x);
- }
-
-}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java
new file mode 100644
index 000000000..48e5e8517
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java
@@ -0,0 +1,270 @@
+package jogamp.opengl.util.pngj;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.zip.CRC32;
+
+/**
+ * Some utility static methods for internal use.
+ * <p>
+ * Client code should not normally use this class
+ * <p>
+ */
+public class PngHelperInternal {
+ /**
+ * Default charset, used internally by PNG for several things
+ */
+ public static final Charset charsetLatin1 = Charset.forName("ISO-8859-1");
+ /**
+ * UTF-8 is only used for some chunks
+ */
+ public static final Charset charsetUTF8 = Charset.forName("UTF-8");
+
+ static final boolean DEBUG = false;
+
+ /**
+ * PNG magic bytes
+ */
+ public static byte[] getPngIdSignature() {
+ return new byte[] { -119, 80, 78, 71, 13, 10, 26, 10 };
+ }
+
+ public static int doubleToInt100000(final double d) {
+ return (int) (d * 100000.0 + 0.5);
+ }
+
+ public static double intToDouble100000(final int i) {
+ return i / 100000.0;
+ }
+
+ public static int readByte(final InputStream is) {
+ try {
+ return is.read();
+ } catch (final IOException e) {
+ throw new PngjInputException("error reading byte", e);
+ }
+ }
+
+ /**
+ * -1 if eof
+ *
+ * PNG uses "network byte order"
+ */
+ public static int readInt2(final InputStream is) {
+ try {
+ final int b1 = is.read();
+ final int b2 = is.read();
+ if (b1 == -1 || b2 == -1)
+ return -1;
+ return (b1 << 8) + b2;
+ } catch (final IOException e) {
+ throw new PngjInputException("error reading readInt2", e);
+ }
+ }
+
+ /**
+ * -1 if eof
+ */
+ public static int readInt4(final InputStream is) {
+ try {
+ final int b1 = is.read();
+ final int b2 = is.read();
+ final int b3 = is.read();
+ final int b4 = is.read();
+ if (b1 == -1 || b2 == -1 || b3 == -1 || b4 == -1)
+ return -1;
+ return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
+ } catch (final IOException e) {
+ throw new PngjInputException("error reading readInt4", e);
+ }
+ }
+
+ public static int readInt1fromByte(final byte[] b, final int offset) {
+ return (b[offset] & 0xff);
+ }
+
+ public static int readInt2fromBytes(final byte[] b, final int offset) {
+ return ((b[offset] & 0xff) << 16) | ((b[offset + 1] & 0xff));
+ }
+
+ public static int readInt4fromBytes(final byte[] b, final int offset) {
+ return ((b[offset] & 0xff) << 24) | ((b[offset + 1] & 0xff) << 16) | ((b[offset + 2] & 0xff) << 8)
+ | (b[offset + 3] & 0xff);
+ }
+
+ public static void writeByte(final OutputStream os, final byte b) {
+ try {
+ os.write(b);
+ } catch (final IOException e) {
+ throw new PngjOutputException(e);
+ }
+ }
+
+ public static void writeInt2(final OutputStream os, final int n) {
+ final byte[] temp = { (byte) ((n >> 8) & 0xff), (byte) (n & 0xff) };
+ writeBytes(os, temp);
+ }
+
+ public static void writeInt4(final OutputStream os, final int n) {
+ final byte[] temp = new byte[4];
+ writeInt4tobytes(n, temp, 0);
+ writeBytes(os, temp);
+ }
+
+ public static void writeInt2tobytes(final int n, final byte[] b, final int offset) {
+ b[offset] = (byte) ((n >> 8) & 0xff);
+ b[offset + 1] = (byte) (n & 0xff);
+ }
+
+ public static void writeInt4tobytes(final int n, final byte[] b, final int offset) {
+ b[offset] = (byte) ((n >> 24) & 0xff);
+ b[offset + 1] = (byte) ((n >> 16) & 0xff);
+ b[offset + 2] = (byte) ((n >> 8) & 0xff);
+ b[offset + 3] = (byte) (n & 0xff);
+ }
+
+ /**
+ * guaranteed to read exactly len bytes. throws error if it can't
+ */
+ public static void readBytes(final InputStream is, final byte[] b, final int offset, final int len) {
+ if (len == 0)
+ return;
+ try {
+ int read = 0;
+ while (read < len) {
+ final int n = is.read(b, offset + read, len - read);
+ if (n < 1)
+ throw new PngjInputException("error reading bytes, " + n + " !=" + len);
+ read += n;
+ }
+ } catch (final IOException e) {
+ throw new PngjInputException("error reading", e);
+ }
+ }
+
+ public static void skipBytes(final InputStream is, long len) {
+ try {
+ while (len > 0) {
+ final long n1 = is.skip(len);
+ if (n1 > 0) {
+ len -= n1;
+ } else if (n1 == 0) { // should we retry? lets read one byte
+ if (is.read() == -1) // EOF
+ break;
+ else
+ len--;
+ } else
+ // negative? this should never happen but...
+ throw new IOException("skip() returned a negative value ???");
+ }
+ } catch (final IOException e) {
+ throw new PngjInputException(e);
+ }
+ }
+
+ public static void writeBytes(final OutputStream os, final byte[] b) {
+ try {
+ os.write(b);
+ } catch (final IOException e) {
+ throw new PngjOutputException(e);
+ }
+ }
+
+ public static void writeBytes(final OutputStream os, final byte[] b, final int offset, final int n) {
+ try {
+ os.write(b, offset, n);
+ } catch (final IOException e) {
+ throw new PngjOutputException(e);
+ }
+ }
+
+ public static void logdebug(final String msg) {
+ if (DEBUG)
+ System.out.println(msg);
+ }
+
+ private static final ThreadLocal<CRC32> crcProvider = new ThreadLocal<CRC32>() {
+ @Override
+ protected CRC32 initialValue() {
+ return new CRC32();
+ }
+ };
+
+ /** thread-singleton crc engine */
+ public static CRC32 getCRC() {
+ return crcProvider.get();
+ }
+
+ // / filters
+ public static int filterRowNone(final int r) {
+ return r & 0xFF;
+ }
+
+ public static int filterRowSub(final int r, final int left) {
+ return (r - left & 0xFF);
+ }
+
+ public static int filterRowUp(final int r, final int up) {
+ return (r - up & 0xFF);
+ }
+
+ public static int filterRowAverage(final int r, final int left, final int up) {
+ return (r - (left + up) / 2) & 0xFF;
+ }
+
+ public static int filterRowPaeth(final int r, final int left, final int up, final int upleft) { // a = left, b = above, c = upper left
+ return (r - filterPaethPredictor(left, up, upleft)) & 0xFF;
+ }
+
+ public static int unfilterRowNone(final int r) {
+ return r & 0xFF;
+ }
+
+ public static int unfilterRowSub(final int r, final int left) {
+ return (r + left & 0xFF);
+ }
+
+ public static int unfilterRowUp(final int r, final int up) {
+ return (r + up & 0xFF);
+ }
+
+ public static int unfilterRowAverage(final int r, final int left, final int up) {
+ return (r + (left + up) / 2) & 0xFF;
+ }
+
+ public static int unfilterRowPaeth(final int r, final int left, final int up, final int upleft) { // a = left, b = above, c = upper left
+ return (r + filterPaethPredictor(left, up, upleft)) & 0xFF;
+ }
+
+ final static int filterPaethPredictor(final int a, final int b, final int c) { // a = left, b = above, c = upper
+ // left
+ // from http://www.libpng.org/pub/png/spec/1.2/PNG-Filters.html
+
+ final int p = a + b - c;// ; initial estimate
+ final int pa = p >= a ? p - a : a - p;
+ final int pb = p >= b ? p - b : b - p;
+ final int pc = p >= c ? p - c : c - p;
+ // ; return nearest of a,b,c,
+ // ; breaking ties in order a,b,c.
+ if (pa <= pb && pa <= pc)
+ return a;
+ else if (pb <= pc)
+ return b;
+ else
+ return c;
+ }
+
+ /*
+ * we put this methods here so as to not pollute the public interface of PngReader
+ */
+ public final static void initCrcForTests(final PngReader pngr) {
+ pngr.initCrctest();
+ }
+
+ public final static long getCrctestVal(final PngReader pngr) {
+ return pngr.getCrctestVal();
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java
index 66c4b49f0..cde4b517e 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java
@@ -11,23 +11,24 @@ import jogamp.opengl.util.pngj.chunks.ChunkHelper;
/**
- * Reads IDAT chunks
+ * Reads a sequence of contiguous IDAT chunks
*/
class PngIDatChunkInputStream extends InputStream {
private final InputStream inputStream;
private final CRC32 crcEngine;
+ private boolean checkCrc = true;
private int lenLastChunk;
- private byte[] idLastChunk = new byte[4];
+ private final byte[] idLastChunk = new byte[4];
private int toReadThisChunk = 0;
private boolean ended = false;
- private long offset; // offset inside inputstream
+ private long offset; // offset inside whole inputstream (counting bytes before IDAT)
// just informational
static class IdatChunkInfo {
public final int len;
- public final int offset;
+ public final long offset;
- private IdatChunkInfo(int len, int offset) {
+ private IdatChunkInfo(final int len, final long offset) {
this.len = len;
this.offset = offset;
}
@@ -36,18 +37,20 @@ class PngIDatChunkInputStream extends InputStream {
List<IdatChunkInfo> foundChunksInfo = new ArrayList<IdatChunkInfo>();
/**
- * Constructor must be called just after reading length and id of first IDAT chunk
+ * Constructor must be called just after reading length and id of first IDAT
+ * chunk
**/
- PngIDatChunkInputStream(InputStream iStream, int lenFirstChunk, int offset) {
- this.offset = (long) offset;
+ PngIDatChunkInputStream(final InputStream iStream, final int lenFirstChunk, final long offset) {
+ this.offset = offset;
inputStream = iStream;
- crcEngine = new CRC32();
this.lenLastChunk = lenFirstChunk;
toReadThisChunk = lenFirstChunk;
// we know it's a IDAT
System.arraycopy(ChunkHelper.b_IDAT, 0, idLastChunk, 0, 4);
+ crcEngine = new CRC32();
crcEngine.update(idLastChunk, 0, 4);
foundChunksInfo.add(new IdatChunkInfo(lenLastChunk, offset - 8));
+
// PngHelper.logdebug("IDAT Initial fragment: len=" + lenLastChunk);
if (this.lenLastChunk == 0)
endChunkGoForNext(); // rare, but...
@@ -58,31 +61,33 @@ class PngIDatChunkInputStream extends InputStream {
*/
@Override
public void close() throws IOException {
- super.close(); // nothing
+ super.close(); // thsi does nothing
}
private void endChunkGoForNext() {
- // Called after readging the last byte of chunk
+ // Called after readging the last byte of one IDAT chunk
// Checks CRC, and read ID from next CHUNK
// Those values are left in idLastChunk / lenLastChunk
// Skips empty IDATS
do {
- int crc = PngHelper.readInt4(inputStream); //
+ final int crc = PngHelperInternal.readInt4(inputStream); //
offset += 4;
- int crccalc = (int) crcEngine.getValue();
- if (lenLastChunk > 0 && crc != crccalc)
- throw new PngjBadCrcException("error reading idat; offset: " + offset);
- crcEngine.reset();
- lenLastChunk = PngHelper.readInt4(inputStream);
- if (lenLastChunk < 0)
- throw new PngjInputException("invalid len for chunk: " + lenLastChunk);
+ if (checkCrc) {
+ final int crccalc = (int) crcEngine.getValue();
+ if (lenLastChunk > 0 && crc != crccalc)
+ throw new PngjBadCrcException("error reading idat; offset: " + offset);
+ crcEngine.reset();
+ }
+ lenLastChunk = PngHelperInternal.readInt4(inputStream);
toReadThisChunk = lenLastChunk;
- PngHelper.readBytes(inputStream, idLastChunk, 0, 4);
+ PngHelperInternal.readBytes(inputStream, idLastChunk, 0, 4);
offset += 8;
+ // found a NON IDAT chunk? this stream is ended
ended = !Arrays.equals(idLastChunk, ChunkHelper.b_IDAT);
if (!ended) {
- foundChunksInfo.add(new IdatChunkInfo(lenLastChunk, (int) (offset - 8)));
- crcEngine.update(idLastChunk, 0, 4);
+ foundChunksInfo.add(new IdatChunkInfo(lenLastChunk, offset - 8));
+ if (checkCrc)
+ crcEngine.update(idLastChunk, 0, 4);
}
// PngHelper.logdebug("IDAT ended. next len= " + lenLastChunk + " idat?" +
// (!ended));
@@ -91,27 +96,33 @@ class PngIDatChunkInputStream extends InputStream {
}
/**
- * sometimes last row read does not fully consumes the chunk here we read the reamaing dummy bytes
+ * sometimes last row read does not fully consumes the chunk here we read
+ * the reamaing dummy bytes
*/
void forceChunkEnd() {
if (!ended) {
- byte[] dummy = new byte[toReadThisChunk];
- PngHelper.readBytes(inputStream, dummy, 0, toReadThisChunk);
- crcEngine.update(dummy, 0, toReadThisChunk);
+ final byte[] dummy = new byte[toReadThisChunk];
+ PngHelperInternal.readBytes(inputStream, dummy, 0, toReadThisChunk);
+ if (checkCrc)
+ crcEngine.update(dummy, 0, toReadThisChunk);
endChunkGoForNext();
}
}
/**
- * This can return less than len, but never 0 Returns -1 if "pseudo file" ended prematurely. That is our error.
+ * This can return less than len, but never 0 Returns -1 if "pseudo file"
+ * ended prematurely. That is our error.
*/
@Override
- public int read(byte[] b, int off, int len) throws IOException {
+ public int read(final byte[] b, final int off, final int len) throws IOException {
+ if (ended)
+ return -1; // can happen only when raw reading, see Pngreader.readAndSkipsAllRows()
if (toReadThisChunk == 0)
- throw new RuntimeException("this should not happen");
- int n = inputStream.read(b, off, len >= toReadThisChunk ? toReadThisChunk : len);
+ throw new PngjExceptionInternal("this should not happen");
+ final int n = inputStream.read(b, off, len >= toReadThisChunk ? toReadThisChunk : len);
if (n > 0) {
- crcEngine.update(b, off, n);
+ if (checkCrc)
+ crcEngine.update(b, off, n);
this.offset += n;
toReadThisChunk -= n;
}
@@ -122,7 +133,7 @@ class PngIDatChunkInputStream extends InputStream {
}
@Override
- public int read(byte[] b) throws IOException {
+ public int read(final byte[] b) throws IOException {
return this.read(b, 0, b.length);
}
@@ -130,8 +141,8 @@ class PngIDatChunkInputStream extends InputStream {
public int read() throws IOException {
// PngHelper.logdebug("read() should go here");
// inneficient - but this should be used rarely
- byte[] b1 = new byte[1];
- int r = this.read(b1, 0, 1);
+ final byte[] b1 = new byte[1];
+ final int r = this.read(b1, 0, 1);
return r < 0 ? -1 : (int) b1[0];
}
@@ -150,4 +161,11 @@ class PngIDatChunkInputStream extends InputStream {
boolean isEnded() {
return ended;
}
+
+ /**
+ * Disables CRC checking. This can make reading faster
+ */
+ void disableCrcCheck() {
+ checkCrc = false;
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java
index 8b9fa5dae..38b500cd3 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java
@@ -7,24 +7,24 @@ import jogamp.opengl.util.pngj.chunks.ChunkRaw;
/**
- * outputs the stream for IDAT chunk , fragmented at fixed size (16384 default).
+ * outputs the stream for IDAT chunk , fragmented at fixed size (32k default).
*/
class PngIDatChunkOutputStream extends ProgressiveOutputStream {
- private static final int SIZE_DEFAULT = 16384;
+ private static final int SIZE_DEFAULT = 32768; // 32k
private final OutputStream outputStream;
- PngIDatChunkOutputStream(OutputStream outputStream) {
- this(outputStream, SIZE_DEFAULT);
+ PngIDatChunkOutputStream(final OutputStream outputStream) {
+ this(outputStream, 0);
}
- PngIDatChunkOutputStream(OutputStream outputStream, int size) {
- super(size);
+ PngIDatChunkOutputStream(final OutputStream outputStream, final int size) {
+ super(size > 0 ? size : SIZE_DEFAULT);
this.outputStream = outputStream;
}
@Override
- public final void flushBuffer(byte[] b, int len) {
- ChunkRaw c = new ChunkRaw(len, ChunkHelper.b_IDAT, false);
+ protected final void flushBuffer(final byte[] b, final int len) {
+ final ChunkRaw c = new ChunkRaw(len, ChunkHelper.b_IDAT, false);
c.data = b;
c.writeChunk(outputStream);
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java
index 7343893b6..f77d4f4e0 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java
@@ -1,415 +1,1001 @@
-package jogamp.opengl.util.pngj;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.zip.InflaterInputStream;
-
-import jogamp.opengl.util.pngj.PngIDatChunkInputStream.IdatChunkInfo;
-import jogamp.opengl.util.pngj.chunks.ChunkHelper;
-import jogamp.opengl.util.pngj.chunks.ChunkList;
-import jogamp.opengl.util.pngj.chunks.ChunkLoadBehaviour;
-import jogamp.opengl.util.pngj.chunks.ChunkRaw;
-import jogamp.opengl.util.pngj.chunks.PngChunk;
-import jogamp.opengl.util.pngj.chunks.PngChunkIHDR;
-import jogamp.opengl.util.pngj.chunks.PngMetadata;
-
-
-/**
- * Reads a PNG image, line by line
- */
-public class PngReader {
- /**
- * Basic image info - final and inmutable.
- */
- public final ImageInfo imgInfo;
- protected final String filename; // not necesarily a file, can be a description - merely informative
-
- private static int MAX_BYTES_CHUNKS_TO_LOAD = 640000;
- private ChunkLoadBehaviour chunkLoadBehaviour = ChunkLoadBehaviour.LOAD_CHUNK_ALWAYS;
-
- private final InputStream is;
- private InflaterInputStream idatIstream;
- private PngIDatChunkInputStream iIdatCstream;
-
- protected int currentChunkGroup = -1;
- protected int rowNum = -1; // current row number
- private int offset = 0;
- private int bytesChunksLoaded; // bytes loaded from anciallary chunks
-
- protected ImageLine imgLine;
-
- // line as bytes, counting from 1 (index 0 is reserved for filter type)
- protected byte[] rowb = null;
- protected byte[] rowbprev = null; // rowb previous
- protected byte[] rowbfilter = null; // current line 'filtered': exactly as in uncompressed stream
-
- /**
- * All chunks loaded. Criticals are included, except that all IDAT chunks appearance are replaced by a single
- * dummy-marker IDAT chunk. These might be copied to the PngWriter
- */
- private final ChunkList chunksList;
- private final PngMetadata metadata; // this a wrapper over chunks
-
- /**
- * Constructs a PngReader from an InputStream.
- * <p>
- * See also <code>FileHelper.createPngReader(File f)</code> if available.
- *
- * Reads only the signature and first chunk (IDHR)
- *
- * @param filenameOrDescription
- * : Optional, can be a filename or a description. Just for error/debug messages
- *
- */
- public PngReader(InputStream inputStream, String filenameOrDescription) {
- this.filename = filenameOrDescription == null ? "" : filenameOrDescription;
- this.is = inputStream;
- this.chunksList = new ChunkList(null);
- this.metadata = new PngMetadata(chunksList, true);
- // reads header (magic bytes)
- byte[] pngid = new byte[PngHelper.pngIdBytes.length];
- PngHelper.readBytes(is, pngid, 0, pngid.length);
- offset += pngid.length;
- if (!Arrays.equals(pngid, PngHelper.pngIdBytes))
- throw new PngjInputException("Bad PNG signature");
- // reads first chunk
- currentChunkGroup = ChunkList.CHUNK_GROUP_0_IDHR;
- int clen = PngHelper.readInt4(is);
- offset += 4;
- if (clen != 13)
- throw new RuntimeException("IDHR chunk len != 13 ?? " + clen);
- byte[] chunkid = new byte[4];
- PngHelper.readBytes(is, chunkid, 0, 4);
- if (!Arrays.equals(chunkid, ChunkHelper.b_IHDR))
- throw new PngjInputException("IHDR not found as first chunk??? [" + ChunkHelper.toString(chunkid) + "]");
- offset += 4;
- ChunkRaw chunk = new ChunkRaw(clen, chunkid, true);
- String chunkids = ChunkHelper.toString(chunkid);
- offset += chunk.readChunkData(is);
- PngChunkIHDR ihdr = (PngChunkIHDR) addChunkToList(chunk);
- boolean alpha = (ihdr.getColormodel() & 0x04) != 0;
- boolean palette = (ihdr.getColormodel() & 0x01) != 0;
- boolean grayscale = (ihdr.getColormodel() == 0 || ihdr.getColormodel() == 4);
- imgInfo = new ImageInfo(ihdr.getCols(), ihdr.getRows(), ihdr.getBitspc(), alpha, grayscale, palette);
- imgLine = new ImageLine(imgInfo);
- if (ihdr.getInterlaced() != 0)
- throw new PngjUnsupportedException("PNG interlaced not supported by this library");
- if (ihdr.getFilmeth() != 0 || ihdr.getCompmeth() != 0)
- throw new PngjInputException("compmethod o filtermethod unrecognized");
- if (ihdr.getColormodel() < 0 || ihdr.getColormodel() > 6 || ihdr.getColormodel() == 1
- || ihdr.getColormodel() == 5)
- throw new PngjInputException("Invalid colormodel " + ihdr.getColormodel());
- if (ihdr.getBitspc() != 1 && ihdr.getBitspc() != 2 && ihdr.getBitspc() != 4 && ihdr.getBitspc() != 8
- && ihdr.getBitspc() != 16)
- throw new PngjInputException("Invalid bit depth " + ihdr.getBitspc());
- // allocation: one extra byte for filter type one pixel
- rowbfilter = new byte[imgInfo.bytesPerRow + 1];
- rowb = new byte[imgInfo.bytesPerRow + 1];
- rowbprev = new byte[rowb.length];
- }
-
- private static class FoundChunkInfo {
- public final String id;
- public final int len;
- public final int offset;
- public final boolean loaded;
-
- private FoundChunkInfo(String id, int len, int offset, boolean loaded) {
- this.id = id;
- this.len = len;
- this.offset = offset;
- this.loaded = loaded;
- }
-
- public String toString() {
- return "chunk " + id + " len=" + len + " offset=" + offset + (this.loaded ? " " : " X ");
- }
- }
-
- private PngChunk addChunkToList(ChunkRaw chunk) {
- // this requires that the currentChunkGroup is ok
- PngChunk chunkType = PngChunk.factory(chunk, imgInfo);
- if (!chunkType.crit) {
- bytesChunksLoaded += chunk.len;
- }
- if (bytesChunksLoaded > MAX_BYTES_CHUNKS_TO_LOAD) {
- throw new PngjInputException("Chunk exceeded available space (" + MAX_BYTES_CHUNKS_TO_LOAD + ") chunk: "
- + chunk + " See PngReader.MAX_BYTES_CHUNKS_TO_LOAD\n");
- }
- chunksList.appendReadChunk(chunkType, currentChunkGroup);
- return chunkType;
- }
-
- /**
- * Reads chunks before first IDAT. Position before: after IDHR (crc included) Position after: just after the first
- * IDAT chunk id
- *
- * This can be called several times (tentatively), it does nothing if already run
- *
- * (Note: when should this be called? in the constructor? hardly, because we loose the opportunity to call
- * setChunkLoadBehaviour() and perhaps other settings before reading the first row? but sometimes we want to access
- * some metadata (plte, phys) before. Because of this, this method can be called explicitly but is also called
- * implicititly in some methods (getMetatada(), getChunks())
- *
- **/
- public void readFirstChunks() {
- if (!firstChunksNotYetRead())
- return;
- int clen = 0;
- boolean found = false;
- byte[] chunkid = new byte[4]; // it's important to reallocate in each iteration
- currentChunkGroup = ChunkList.CHUNK_GROUP_1_AFTERIDHR;
- while (!found) {
- clen = PngHelper.readInt4(is);
- offset += 4;
- if (clen < 0)
- break;
- PngHelper.readBytes(is, chunkid, 0, 4);
- offset += 4;
- if (Arrays.equals(chunkid, ChunkHelper.b_IDAT)) {
- found = true;
- currentChunkGroup = ChunkList.CHUNK_GROUP_4_IDAT;
- // add dummy idat chunk to list
- ChunkRaw chunk = new ChunkRaw(0, chunkid, false);
- addChunkToList(chunk);
- break;
- } else if (Arrays.equals(chunkid, ChunkHelper.b_IEND)) {
- throw new PngjInputException("END chunk found before image data (IDAT) at offset=" + offset);
- }
- ChunkRaw chunk = new ChunkRaw(clen, chunkid, true);
- String chunkids = ChunkHelper.toString(chunkid);
- boolean loadchunk = ChunkHelper.shouldLoad(chunkids, chunkLoadBehaviour);
- offset += chunk.readChunkData(is);
- if (chunkids.equals(ChunkHelper.PLTE))
- currentChunkGroup = ChunkList.CHUNK_GROUP_2_PLTE;
- if (loadchunk)
- addChunkToList(chunk);
- if (chunkids.equals(ChunkHelper.PLTE))
- currentChunkGroup = ChunkList.CHUNK_GROUP_3_AFTERPLTE;
- }
- int idatLen = found ? clen : -1;
- if (idatLen < 0)
- throw new PngjInputException("first idat chunk not found!");
- iIdatCstream = new PngIDatChunkInputStream(is, idatLen, offset);
- idatIstream = new InflaterInputStream(iIdatCstream);
- }
-
- /**
- * Reads (and processes) chunks after last IDAT.
- **/
- private void readLastChunks() {
- // PngHelper.logdebug("idat ended? " + iIdatCstream.isEnded());
- currentChunkGroup = ChunkList.CHUNK_GROUP_5_AFTERIDAT;
- if (!iIdatCstream.isEnded())
- iIdatCstream.forceChunkEnd();
- int clen = iIdatCstream.getLenLastChunk();
- byte[] chunkid = iIdatCstream.getIdLastChunk();
- boolean endfound = false;
- boolean first = true;
- boolean ignore = false;
- while (!endfound) {
- ignore = false;
- if (!first) {
- clen = PngHelper.readInt4(is);
- offset += 4;
- if (clen < 0)
- throw new PngjInputException("bad len " + clen);
- PngHelper.readBytes(is, chunkid, 0, 4);
- offset += 4;
- }
- first = false;
- if (Arrays.equals(chunkid, ChunkHelper.b_IDAT)) {
- // PngHelper.logdebug("extra IDAT chunk len - ignoring : ");
- ignore = true;
- } else if (Arrays.equals(chunkid, ChunkHelper.b_IEND)) {
- currentChunkGroup = ChunkList.CHUNK_GROUP_6_END;
- endfound = true;
- }
- ChunkRaw chunk = new ChunkRaw(clen, chunkid, true);
- String chunkids = ChunkHelper.toString(chunkid);
- boolean loadchunk = ChunkHelper.shouldLoad(chunkids, chunkLoadBehaviour);
- offset += chunk.readChunkData(is);
- if (loadchunk && !ignore) {
- addChunkToList(chunk);
- }
- }
- if (!endfound)
- throw new PngjInputException("end chunk not found - offset=" + offset);
- // PngHelper.logdebug("end chunk found ok offset=" + offset);
- }
-
- /**
- * Calls <code>readRow(int[] buffer, int nrow)</code> using internal ImageLine as buffer. This doesn't allocate or
- * copy anything.
- *
- * @return The ImageLine that also is available inside this object.
- */
- public ImageLine readRow(int nrow) {
- readRow(imgLine.scanline, nrow);
- imgLine.filterUsed = FilterType.getByVal(rowbfilter[0]);
- imgLine.setRown(nrow);
- return imgLine;
- }
-
- /**
- * Reads a line and returns it as a int[] array.
- *
- * You can pass (optionally) a prealocatted buffer.
- *
- * @param buffer
- * Prealocated buffer, or null.
- * @param nrow
- * Row number (0 is top). This is mostly for checking, because this library reads rows in sequence.
- *
- * @return The scanline in the same passwd buffer if it was allocated, a newly allocated one otherwise
- */
- public int[] readRow(int[] buffer, int nrow) {
- if (nrow < 0 || nrow >= imgInfo.rows)
- throw new PngjInputException("invalid line");
- if (nrow != rowNum + 1)
- throw new PngjInputException("invalid line (expected: " + (rowNum + 1));
- if (nrow == 0 && firstChunksNotYetRead())
- readFirstChunks();
- rowNum++;
- if (buffer == null || buffer.length < imgInfo.samplesPerRowP)
- buffer = new int[imgInfo.samplesPerRowP];
- // swap
- byte[] tmp = rowb;
- rowb = rowbprev;
- rowbprev = tmp;
- // loads in rowbfilter "raw" bytes, with filter
- PngHelper.readBytes(idatIstream, rowbfilter, 0, rowbfilter.length);
- rowb[0] = 0;
- unfilterRow();
- rowb[0] = rowbfilter[0];
- convertRowFromBytes(buffer);
- return buffer;
- }
-
- /**
- * This should be called after having read the last line. It reads extra chunks after IDAT, if present.
- */
- public void end() {
- offset = (int) iIdatCstream.getOffset();
- try {
- idatIstream.close();
- } catch (Exception e) {
- }
- readLastChunks();
- try {
- is.close();
- } catch (Exception e) {
- throw new PngjInputException("error closing input stream!", e);
- }
- }
-
- private void convertRowFromBytes(int[] buffer) {
- // http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html
- int i, j;
- if (imgInfo.bitDepth <= 8) {
- for (i = 0, j = 1; i < imgInfo.samplesPerRowP; i++) {
- buffer[i] = (rowb[j++] & 0xFF);
- }
- } else { // 16 bitspc
- for (i = 0, j = 1; i < imgInfo.samplesPerRowP; i++) {
- buffer[i] = ((rowb[j++] & 0xFF) << 8) + (rowb[j++] & 0xFF);
- }
- }
- }
-
- private void unfilterRow() {
- int ftn = rowbfilter[0];
- FilterType ft = FilterType.getByVal(ftn);
- if (ft == null)
- throw new PngjInputException("Filter type " + ftn + " invalid");
- switch (ft) {
- case FILTER_NONE:
- unfilterRowNone();
- break;
- case FILTER_SUB:
- unfilterRowSub();
- break;
- case FILTER_UP:
- unfilterRowUp();
- break;
- case FILTER_AVERAGE:
- unfilterRowAverage();
- break;
- case FILTER_PAETH:
- unfilterRowPaeth();
- break;
- default:
- throw new PngjInputException("Filter type " + ftn + " not implemented");
- }
- }
-
- private void unfilterRowNone() {
- for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
- rowb[i] = (byte) (rowbfilter[i]);
- }
- }
-
- private void unfilterRowSub() {
- int i, j;
- for (i = 1; i <= imgInfo.bytesPixel; i++) {
- rowb[i] = (byte) (rowbfilter[i]);
- }
- for (j = 1, i = imgInfo.bytesPixel + 1; i <= imgInfo.bytesPerRow; i++, j++) {
- rowb[i] = (byte) (rowbfilter[i] + rowb[j]);
- }
- }
-
- private void unfilterRowUp() {
- for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
- rowb[i] = (byte) (rowbfilter[i] + rowbprev[i]);
- }
- }
-
- private void unfilterRowAverage() {
- int i, j, x;
- for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imgInfo.bytesPerRow; i++, j++) {
- x = j > 0 ? (rowb[j] & 0xff) : 0;
- rowb[i] = (byte) (rowbfilter[i] + (x + (rowbprev[i] & 0xFF)) / 2);
- }
- }
-
- private void unfilterRowPaeth() {
- int i, j, x, y;
- for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imgInfo.bytesPerRow; i++, j++) {
- x = j > 0 ? (rowb[j] & 0xFF) : 0;
- y = j > 0 ? (rowbprev[j] & 0xFF) : 0;
- rowb[i] = (byte) (rowbfilter[i] + FilterType.filterPaethPredictor(x, rowbprev[i] & 0xFF, y));
- }
- }
-
- public ChunkLoadBehaviour getChunkLoadBehaviour() {
- return chunkLoadBehaviour;
- }
-
- public void setChunkLoadBehaviour(ChunkLoadBehaviour chunkLoadBehaviour) {
- this.chunkLoadBehaviour = chunkLoadBehaviour;
- }
-
- private boolean firstChunksNotYetRead() {
- return currentChunkGroup < ChunkList.CHUNK_GROUP_1_AFTERIDHR;
- }
-
- public ChunkList getChunksList() {
- if (firstChunksNotYetRead())
- readFirstChunks();
- return chunksList;
- }
-
- public PngMetadata getMetadata() {
- if (firstChunksNotYetRead())
- readFirstChunks();
- return metadata;
- }
-
- public String toString() { // basic info
- return "filename=" + filename + " " + imgInfo.toString();
- }
-
-}
+package jogamp.opengl.util.pngj;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.zip.CRC32;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
+import jogamp.opengl.util.pngj.ImageLine.SampleType;
+import jogamp.opengl.util.pngj.chunks.ChunkHelper;
+import jogamp.opengl.util.pngj.chunks.ChunkLoadBehaviour;
+import jogamp.opengl.util.pngj.chunks.ChunkRaw;
+import jogamp.opengl.util.pngj.chunks.ChunksList;
+import jogamp.opengl.util.pngj.chunks.PngChunk;
+import jogamp.opengl.util.pngj.chunks.PngChunkIDAT;
+import jogamp.opengl.util.pngj.chunks.PngChunkIHDR;
+import jogamp.opengl.util.pngj.chunks.PngChunkSkipped;
+import jogamp.opengl.util.pngj.chunks.PngMetadata;
+
+/**
+ * Reads a PNG image, line by line.
+ * <p>
+ * The reading sequence is as follows: <br>
+ * 1. At construction time, the header and IHDR chunk are read (basic image
+ * info) <br>
+ * 2. Afterwards you can set some additional global options. Eg.
+ * {@link #setUnpackedMode(boolean)}, {@link #setCrcCheckDisabled()}.<br>
+ * 3. Optional: If you call getMetadata() or getChunksLisk() before start
+ * reading the rows, all the chunks before IDAT are automatically loaded and
+ * available <br>
+ * 4a. The rows are read onen by one of the <tt>readRowXXX</tt> methods:
+ * {@link #readRowInt(int)}, {@link PngReader#readRowByte(int)}, etc, in order,
+ * from 0 to nrows-1 (you can skip or repeat rows, but not go backwards)<br>
+ * 4b. Alternatively, you can read all rows, or a subset, in a single call:
+ * {@link #readRowsInt()}, {@link #readRowsByte()} ,etc. In general this
+ * consumes more memory, but for interlaced images this is equally efficient,
+ * and more so if reading a small subset of rows.<br>
+ * 5. Read of the last row auyomatically loads the trailing chunks, and ends the
+ * reader.<br>
+ * 6. end() forcibly finishes/aborts the reading and closes the stream
+ */
+public class PngReader {
+
+ /**
+ * Basic image info - final and inmutable.
+ */
+ public final ImageInfo imgInfo;
+ /**
+ * not necesarily a filename, can be a description - merely informative
+ */
+ protected final String filename;
+ private ChunkLoadBehaviour chunkLoadBehaviour = ChunkLoadBehaviour.LOAD_CHUNK_ALWAYS; // see setter/getter
+ private boolean shouldCloseStream = true; // true: closes stream after ending - see setter/getter
+ // some performance/defensive limits
+ private long maxTotalBytesRead = 200 * 1024 * 1024; // 200MB
+ private int maxBytesMetadata = 5 * 1024 * 1024; // for ancillary chunks - see setter/getter
+ private int skipChunkMaxSize = 2 * 1024 * 1024; // chunks exceeding this size will be skipped (nor even CRC checked)
+ private String[] skipChunkIds = { "fdAT" }; // chunks with these ids will be skipped (nor even CRC checked)
+ private HashSet<String> skipChunkIdsSet; // lazily created from skipChunksById
+ protected final PngMetadata metadata; // this a wrapper over chunks
+ protected final ChunksList chunksList;
+ protected ImageLine imgLine;
+ // line as bytes, counting from 1 (index 0 is reserved for filter type)
+ protected final int buffersLen; // nominal length is imgInfo.bytesPerRow + 1 but it can be larger
+ protected byte[] rowb = null;
+ protected byte[] rowbprev = null; // rowb previous
+ protected byte[] rowbfilter = null; // current line 'filtered': exactly as in uncompressed stream
+ // only set for interlaced PNG
+ private final boolean interlaced;
+ private final PngDeinterlacer deinterlacer;
+ private boolean crcEnabled = true;
+ // this only influences the 1-2-4 bitdepth format
+ private boolean unpackedMode = false;
+ private Inflater inflater = null; // can be reused among several objects. see reuseBuffersFrom()
+ /**
+ * Current chunk group, (0-6) already read or reading
+ * <p>
+ * see {@link ChunksList}
+ */
+ protected int currentChunkGroup = -1;
+ protected int rowNum = -1; // last read row number, starting from 0
+ private long offset = 0; // offset in InputStream = bytes read
+ private int bytesChunksLoaded; // bytes loaded from anciallary chunks
+ protected final InputStream inputStream;
+ protected InflaterInputStream idatIstream;
+ protected PngIDatChunkInputStream iIdatCstream;
+ protected CRC32 crctest; // If set to non null, it gets a CRC of the unfiltered bytes, to check for images equality
+
+ /**
+ * Constructs a PngReader from an InputStream.
+ * <p>
+ * See also <code>FileHelper.createPngReader(File f)</code> if available.
+ *
+ * Reads only the signature and first chunk (IDHR)
+ *
+ * @param filenameOrDescription
+ * : Optional, can be a filename or a description. Just for
+ * error/debug messages
+ *
+ */
+ public PngReader(final InputStream inputStream, final String filenameOrDescription) {
+ this.filename = filenameOrDescription == null ? "" : filenameOrDescription;
+ this.inputStream = inputStream;
+ this.chunksList = new ChunksList(null);
+ this.metadata = new PngMetadata(chunksList);
+ // starts reading: signature
+ final byte[] pngid = new byte[8];
+ PngHelperInternal.readBytes(inputStream, pngid, 0, pngid.length);
+ offset += pngid.length;
+ if (!Arrays.equals(pngid, PngHelperInternal.getPngIdSignature()))
+ throw new PngjInputException("Bad PNG signature");
+ // reads first chunk
+ currentChunkGroup = ChunksList.CHUNK_GROUP_0_IDHR;
+ final int clen = PngHelperInternal.readInt4(inputStream);
+ offset += 4;
+ if (clen != 13)
+ throw new PngjInputException("IDHR chunk len != 13 ?? " + clen);
+ final byte[] chunkid = new byte[4];
+ PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
+ if (!Arrays.equals(chunkid, ChunkHelper.b_IHDR))
+ throw new PngjInputException("IHDR not found as first chunk??? [" + ChunkHelper.toString(chunkid) + "]");
+ offset += 4;
+ final PngChunkIHDR ihdr = (PngChunkIHDR) readChunk(chunkid, clen, false);
+ final boolean alpha = (ihdr.getColormodel() & 0x04) != 0;
+ final boolean palette = (ihdr.getColormodel() & 0x01) != 0;
+ final boolean grayscale = (ihdr.getColormodel() == 0 || ihdr.getColormodel() == 4);
+ // creates ImgInfo and imgLine, and allocates buffers
+ imgInfo = new ImageInfo(ihdr.getCols(), ihdr.getRows(), ihdr.getBitspc(), alpha, grayscale, palette);
+ interlaced = ihdr.getInterlaced() == 1;
+ deinterlacer = interlaced ? new PngDeinterlacer(imgInfo) : null;
+ buffersLen = imgInfo.bytesPerRow + 1;
+ // some checks
+ if (ihdr.getFilmeth() != 0 || ihdr.getCompmeth() != 0 || (ihdr.getInterlaced() & 0xFFFE) != 0)
+ throw new PngjInputException("compression method o filter method or interlaced unrecognized ");
+ if (ihdr.getColormodel() < 0 || ihdr.getColormodel() > 6 || ihdr.getColormodel() == 1
+ || ihdr.getColormodel() == 5)
+ throw new PngjInputException("Invalid colormodel " + ihdr.getColormodel());
+ if (ihdr.getBitspc() != 1 && ihdr.getBitspc() != 2 && ihdr.getBitspc() != 4 && ihdr.getBitspc() != 8
+ && ihdr.getBitspc() != 16)
+ throw new PngjInputException("Invalid bit depth " + ihdr.getBitspc());
+ }
+
+ private boolean firstChunksNotYetRead() {
+ return currentChunkGroup < ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+ }
+
+ private void allocateBuffers() { // only if needed
+ if (rowbfilter == null || rowbfilter.length < buffersLen) {
+ rowbfilter = new byte[buffersLen];
+ rowb = new byte[buffersLen];
+ rowbprev = new byte[buffersLen];
+ }
+ }
+
+ /**
+ * Reads last Internally called after having read the last line. It reads
+ * extra chunks after IDAT, if present.
+ */
+ private void readLastAndClose() {
+ // offset = iIdatCstream.getOffset();
+ if (currentChunkGroup < ChunksList.CHUNK_GROUP_5_AFTERIDAT) {
+ try {
+ idatIstream.close();
+ } catch (final Exception e) {
+ }
+ readLastChunks();
+ }
+ close();
+ }
+
+ private void close() {
+ if (currentChunkGroup < ChunksList.CHUNK_GROUP_6_END) { // this could only happen if forced close
+ try {
+ idatIstream.close();
+ } catch (final Exception e) {
+ }
+ currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
+ }
+ if (shouldCloseStream) {
+ try {
+ inputStream.close();
+ } catch (final Exception e) {
+ throw new PngjInputException("error closing input stream!", e);
+ }
+ }
+ }
+
+ // nbytes: NOT including the filter byte. leaves result in rowb
+ private void unfilterRow(final int nbytes) {
+ final int ftn = rowbfilter[0];
+ final FilterType ft = FilterType.getByVal(ftn);
+ if (ft == null)
+ throw new PngjInputException("Filter type " + ftn + " invalid");
+ switch (ft) {
+ case FILTER_NONE:
+ unfilterRowNone(nbytes);
+ break;
+ case FILTER_SUB:
+ unfilterRowSub(nbytes);
+ break;
+ case FILTER_UP:
+ unfilterRowUp(nbytes);
+ break;
+ case FILTER_AVERAGE:
+ unfilterRowAverage(nbytes);
+ break;
+ case FILTER_PAETH:
+ unfilterRowPaeth(nbytes);
+ break;
+ default:
+ throw new PngjInputException("Filter type " + ftn + " not implemented");
+ }
+ if (crctest != null)
+ crctest.update(rowb, 1, buffersLen - 1);
+ }
+
+ private void unfilterRowAverage(final int nbytes) {
+ int i, j, x;
+ for (j = 1 - imgInfo.bytesPixel, i = 1; i <= nbytes; i++, j++) {
+ x = j > 0 ? (rowb[j] & 0xff) : 0;
+ rowb[i] = (byte) (rowbfilter[i] + (x + (rowbprev[i] & 0xFF)) / 2);
+ }
+ }
+
+ private void unfilterRowNone(final int nbytes) {
+ for (int i = 1; i <= nbytes; i++) {
+ rowb[i] = (rowbfilter[i]);
+ }
+ }
+
+ private void unfilterRowPaeth(final int nbytes) {
+ int i, j, x, y;
+ for (j = 1 - imgInfo.bytesPixel, i = 1; i <= nbytes; i++, j++) {
+ x = j > 0 ? (rowb[j] & 0xFF) : 0;
+ y = j > 0 ? (rowbprev[j] & 0xFF) : 0;
+ rowb[i] = (byte) (rowbfilter[i] + PngHelperInternal.filterPaethPredictor(x, rowbprev[i] & 0xFF, y));
+ }
+ }
+
+ private void unfilterRowSub(final int nbytes) {
+ int i, j;
+ for (i = 1; i <= imgInfo.bytesPixel; i++) {
+ rowb[i] = (rowbfilter[i]);
+ }
+ for (j = 1, i = imgInfo.bytesPixel + 1; i <= nbytes; i++, j++) {
+ rowb[i] = (byte) (rowbfilter[i] + rowb[j]);
+ }
+ }
+
+ private void unfilterRowUp(final int nbytes) {
+ for (int i = 1; i <= nbytes; i++) {
+ rowb[i] = (byte) (rowbfilter[i] + rowbprev[i]);
+ }
+ }
+
+ /**
+ * Reads chunks before first IDAT. Normally this is called automatically
+ * <p>
+ * Position before: after IDHR (crc included) Position after: just after the
+ * first IDAT chunk id
+ * <P>
+ * This can be called several times (tentatively), it does nothing if
+ * already run
+ * <p>
+ * (Note: when should this be called? in the constructor? hardly, because we
+ * loose the opportunity to call setChunkLoadBehaviour() and perhaps other
+ * settings before reading the first row? but sometimes we want to access
+ * some metadata (plte, phys) before. Because of this, this method can be
+ * called explicitly but is also called implicititly in some methods
+ * (getMetatada(), getChunksList())
+ */
+ private final void readFirstChunks() {
+ if (!firstChunksNotYetRead())
+ return;
+ int clen = 0;
+ boolean found = false;
+ final byte[] chunkid = new byte[4]; // it's important to reallocate in each iteration
+ currentChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+ while (!found) {
+ clen = PngHelperInternal.readInt4(inputStream);
+ offset += 4;
+ if (clen < 0)
+ break;
+ PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
+ offset += 4;
+ if (Arrays.equals(chunkid, ChunkHelper.b_IDAT)) {
+ found = true;
+ currentChunkGroup = ChunksList.CHUNK_GROUP_4_IDAT;
+ // add dummy idat chunk to list
+ chunksList.appendReadChunk(new PngChunkIDAT(imgInfo, clen, offset - 8), currentChunkGroup);
+ break;
+ } else if (Arrays.equals(chunkid, ChunkHelper.b_IEND)) {
+ throw new PngjInputException("END chunk found before image data (IDAT) at offset=" + offset);
+ }
+ if (Arrays.equals(chunkid, ChunkHelper.b_PLTE))
+ currentChunkGroup = ChunksList.CHUNK_GROUP_2_PLTE;
+ readChunk(chunkid, clen, false);
+ if (Arrays.equals(chunkid, ChunkHelper.b_PLTE))
+ currentChunkGroup = ChunksList.CHUNK_GROUP_3_AFTERPLTE;
+ }
+ final int idatLen = found ? clen : -1;
+ if (idatLen < 0)
+ throw new PngjInputException("first idat chunk not found!");
+ iIdatCstream = new PngIDatChunkInputStream(inputStream, idatLen, offset);
+ if(inflater == null) {
+ inflater = new Inflater();
+ } else {
+ inflater.reset();
+ }
+ idatIstream = new InflaterInputStream(iIdatCstream, inflater);
+ if (!crcEnabled)
+ iIdatCstream.disableCrcCheck();
+ }
+
+ /**
+ * Reads (and processes) chunks after last IDAT.
+ **/
+ void readLastChunks() {
+ // PngHelper.logdebug("idat ended? " + iIdatCstream.isEnded());
+ currentChunkGroup = ChunksList.CHUNK_GROUP_5_AFTERIDAT;
+ if (!iIdatCstream.isEnded())
+ iIdatCstream.forceChunkEnd();
+ int clen = iIdatCstream.getLenLastChunk();
+ final byte[] chunkid = iIdatCstream.getIdLastChunk();
+ boolean endfound = false;
+ boolean first = true;
+ boolean skip = false;
+ while (!endfound) {
+ skip = false;
+ if (!first) {
+ clen = PngHelperInternal.readInt4(inputStream);
+ offset += 4;
+ if (clen < 0)
+ throw new PngjInputException("bad chuck len " + clen);
+ PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
+ offset += 4;
+ }
+ first = false;
+ if (Arrays.equals(chunkid, ChunkHelper.b_IDAT)) {
+ skip = true; // extra dummy (empty?) idat chunk, it can happen, ignore it
+ } else if (Arrays.equals(chunkid, ChunkHelper.b_IEND)) {
+ currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
+ endfound = true;
+ }
+ readChunk(chunkid, clen, skip);
+ }
+ if (!endfound)
+ throw new PngjInputException("end chunk not found - offset=" + offset);
+ // PngHelper.logdebug("end chunk found ok offset=" + offset);
+ }
+
+ /**
+ * Reads chunkd from input stream, adds to ChunksList, and returns it. If
+ * it's skipped, a PngChunkSkipped object is created
+ */
+ private PngChunk readChunk(final byte[] chunkid, final int clen, final boolean skipforced) {
+ if (clen < 0)
+ throw new PngjInputException("invalid chunk lenght: " + clen);
+ // skipChunksByIdSet is created lazyly, if fist IHDR has already been read
+ if (skipChunkIdsSet == null && currentChunkGroup > ChunksList.CHUNK_GROUP_0_IDHR)
+ skipChunkIdsSet = new HashSet<String>(Arrays.asList(skipChunkIds));
+ final String chunkidstr = ChunkHelper.toString(chunkid);
+ final boolean critical = ChunkHelper.isCritical(chunkidstr);
+ PngChunk pngChunk = null;
+ boolean skip = skipforced;
+ if (maxTotalBytesRead > 0 && clen + offset > maxTotalBytesRead)
+ throw new PngjInputException("Maximum total bytes to read exceeeded: " + maxTotalBytesRead + " offset:"
+ + offset + " clen=" + clen);
+ // an ancillary chunks can be skipped because of several reasons:
+ if (currentChunkGroup > ChunksList.CHUNK_GROUP_0_IDHR && !critical)
+ skip = skip || (skipChunkMaxSize > 0 && clen >= skipChunkMaxSize) || skipChunkIdsSet.contains(chunkidstr)
+ || (maxBytesMetadata > 0 && clen > maxBytesMetadata - bytesChunksLoaded)
+ || !ChunkHelper.shouldLoad(chunkidstr, chunkLoadBehaviour);
+ if (skip) {
+ PngHelperInternal.skipBytes(inputStream, clen);
+ PngHelperInternal.readInt4(inputStream); // skip - we dont call PngHelperInternal.skipBytes(inputStream,
+ // clen + 4) for risk of overflow
+ pngChunk = new PngChunkSkipped(chunkidstr, imgInfo, clen);
+ } else {
+ final ChunkRaw chunk = new ChunkRaw(clen, chunkid, true);
+ chunk.readChunkData(inputStream, crcEnabled || critical);
+ pngChunk = PngChunk.factory(chunk, imgInfo);
+ if (!pngChunk.crit)
+ bytesChunksLoaded += chunk.len;
+ }
+ pngChunk.setOffset(offset - 8L);
+ chunksList.appendReadChunk(pngChunk, currentChunkGroup);
+ offset += clen + 4L;
+ return pngChunk;
+ }
+
+ /**
+ * Logs/prints a warning.
+ * <p>
+ * The default behaviour is print to stderr, but it can be overriden.
+ * <p>
+ * This happens rarely - most errors are fatal.
+ */
+ protected void logWarn(final String warn) {
+ System.err.println(warn);
+ }
+
+ /**
+ * @see #setChunkLoadBehaviour(ChunkLoadBehaviour)
+ */
+ public ChunkLoadBehaviour getChunkLoadBehaviour() {
+ return chunkLoadBehaviour;
+ }
+
+ /**
+ * Determines which ancillary chunks (metada) are to be loaded
+ *
+ * @param chunkLoadBehaviour
+ * {@link ChunkLoadBehaviour}
+ */
+ public void setChunkLoadBehaviour(final ChunkLoadBehaviour chunkLoadBehaviour) {
+ this.chunkLoadBehaviour = chunkLoadBehaviour;
+ }
+
+ /**
+ * All loaded chunks (metada). If we have not yet end reading the image,
+ * this will include only the chunks before the pixels data (IDAT)
+ * <p>
+ * Critical chunks are included, except that all IDAT chunks appearance are
+ * replaced by a single dummy-marker IDAT chunk. These might be copied to
+ * the PngWriter
+ * <p>
+ *
+ * @see #getMetadata()
+ */
+ public ChunksList getChunksList() {
+ if (firstChunksNotYetRead())
+ readFirstChunks();
+ return chunksList;
+ }
+
+ int getCurrentChunkGroup() {
+ return currentChunkGroup;
+ }
+
+ /**
+ * High level wrapper over chunksList
+ *
+ * @see #getChunksList()
+ */
+ public PngMetadata getMetadata() {
+ if (firstChunksNotYetRead())
+ readFirstChunks();
+ return metadata;
+ }
+
+ /**
+ * If called for first time, calls readRowInt. Elsewhere, it calls the
+ * appropiate readRowInt/readRowByte
+ * <p>
+ * In general, specifying the concrete readRowInt/readRowByte is preferrable
+ *
+ * @see #readRowInt(int) {@link #readRowByte(int)}
+ */
+ public ImageLine readRow(final int nrow) {
+ if (imgLine == null)
+ imgLine = new ImageLine(imgInfo, SampleType.INT, unpackedMode);
+ return imgLine.sampleType != SampleType.BYTE ? readRowInt(nrow) : readRowByte(nrow);
+ }
+
+ /**
+ * Reads the row as INT, storing it in the {@link #imgLine} property and
+ * returning it.
+ *
+ * The row must be greater or equal than the last read row.
+ *
+ * @param nrow
+ * Row number, from 0 to rows-1. Increasing order.
+ * @return ImageLine object, also available as field. Data is in
+ * {@link ImageLine#scanline} (int) field.
+ */
+ public ImageLine readRowInt(final int nrow) {
+ if (imgLine == null)
+ imgLine = new ImageLine(imgInfo, SampleType.INT, unpackedMode);
+ if (imgLine.getRown() == nrow) // already read
+ return imgLine;
+ readRowInt(imgLine.scanline, nrow);
+ imgLine.setFilterUsed(FilterType.getByVal(rowbfilter[0]));
+ imgLine.setRown(nrow);
+ return imgLine;
+ }
+
+ /**
+ * Reads the row as BYTES, storing it in the {@link #imgLine} property and
+ * returning it.
+ *
+ * The row must be greater or equal than the last read row. This method
+ * allows to pass the same row that was last read.
+ *
+ * @param nrow
+ * Row number, from 0 to rows-1. Increasing order.
+ * @return ImageLine object, also available as field. Data is in
+ * {@link ImageLine#scanlineb} (byte) field.
+ */
+ public ImageLine readRowByte(final int nrow) {
+ if (imgLine == null)
+ imgLine = new ImageLine(imgInfo, SampleType.BYTE, unpackedMode);
+ if (imgLine.getRown() == nrow) // already read
+ return imgLine;
+ readRowByte(imgLine.scanlineb, nrow);
+ imgLine.setFilterUsed(FilterType.getByVal(rowbfilter[0]));
+ imgLine.setRown(nrow);
+ return imgLine;
+ }
+
+ /**
+ * @see #readRowInt(int[], int)
+ */
+ public final int[] readRow(final int[] buffer, final int nrow) {
+ return readRowInt(buffer, nrow);
+ }
+
+ /**
+ * Reads a line and returns it as a int[] array.
+ * <p>
+ * You can pass (optionally) a prealocatted buffer.
+ * <p>
+ * If the bitdepth is less than 8, the bytes are packed - unless
+ * {@link #unpackedMode} is true.
+ *
+ * @param buffer
+ * Prealocated buffer, or null.
+ * @param nrow
+ * Row number (0 is top). Most be strictly greater than the last
+ * read row.
+ *
+ * @return The scanline in the same passwd buffer if it was allocated, a
+ * newly allocated one otherwise
+ */
+ public final int[] readRowInt(int[] buffer, final int nrow) {
+ if (buffer == null)
+ buffer = new int[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+ if (!interlaced) {
+ if (nrow <= rowNum)
+ throw new PngjInputException("rows must be read in increasing order: " + nrow);
+ int bytesread = 0;
+ while (rowNum < nrow)
+ bytesread = readRowRaw(rowNum + 1); // read rows, perhaps skipping if necessary
+ decodeLastReadRowToInt(buffer, bytesread);
+ } else { // interlaced
+ if (deinterlacer.getImageInt() == null)
+ deinterlacer.setImageInt(readRowsInt().scanlines); // read all image and store it in deinterlacer
+ System.arraycopy(deinterlacer.getImageInt()[nrow], 0, buffer, 0, unpackedMode ? imgInfo.samplesPerRow
+ : imgInfo.samplesPerRowPacked);
+ }
+ return buffer;
+ }
+
+ /**
+ * Reads a line and returns it as a byte[] array.
+ * <p>
+ * You can pass (optionally) a prealocatted buffer.
+ * <p>
+ * If the bitdepth is less than 8, the bytes are packed - unless
+ * {@link #unpackedMode} is true. <br>
+ * If the bitdepth is 16, the least significant byte is lost.
+ * <p>
+ *
+ * @param buffer
+ * Prealocated buffer, or null.
+ * @param nrow
+ * Row number (0 is top). Most be strictly greater than the last
+ * read row.
+ *
+ * @return The scanline in the same passwd buffer if it was allocated, a
+ * newly allocated one otherwise
+ */
+ public final byte[] readRowByte(byte[] buffer, final int nrow) {
+ if (buffer == null)
+ buffer = new byte[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+ if (!interlaced) {
+ if (nrow <= rowNum)
+ throw new PngjInputException("rows must be read in increasing order: " + nrow);
+ int bytesread = 0;
+ while (rowNum < nrow)
+ bytesread = readRowRaw(rowNum + 1); // read rows, perhaps skipping if necessary
+ decodeLastReadRowToByte(buffer, bytesread);
+ } else { // interlaced
+ if (deinterlacer.getImageByte() == null)
+ deinterlacer.setImageByte(readRowsByte().scanlinesb); // read all image and store it in deinterlacer
+ System.arraycopy(deinterlacer.getImageByte()[nrow], 0, buffer, 0, unpackedMode ? imgInfo.samplesPerRow
+ : imgInfo.samplesPerRowPacked);
+ }
+ return buffer;
+ }
+
+ /**
+ * @param nrow
+ * @deprecated Now {@link #readRow(int)} implements the same funcion. This
+ * method will be removed in future releases
+ */
+ public ImageLine getRow(final int nrow) {
+ return readRow(nrow);
+ }
+
+ private void decodeLastReadRowToInt(final int[] buffer, final int bytesRead) {
+ if (imgInfo.bitDepth <= 8)
+ for (int i = 0, j = 1; i < bytesRead; i++)
+ buffer[i] = (rowb[j++] & 0xFF); // http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html
+ else
+ for (int i = 0, j = 1; j <= bytesRead; i++)
+ buffer[i] = ((rowb[j++] & 0xFF) << 8) + (rowb[j++] & 0xFF); // 16 bitspc
+ if (imgInfo.packed && unpackedMode)
+ ImageLine.unpackInplaceInt(imgInfo, buffer, buffer, false);
+ }
+
+ private void decodeLastReadRowToByte(final byte[] buffer, final int bytesRead) {
+ if (imgInfo.bitDepth <= 8)
+ System.arraycopy(rowb, 1, buffer, 0, bytesRead);
+ else
+ for (int i = 0, j = 1; j < bytesRead; i++, j += 2)
+ buffer[i] = rowb[j];// 16 bits in 1 byte: this discards the LSB!!!
+ if (imgInfo.packed && unpackedMode)
+ ImageLine.unpackInplaceByte(imgInfo, buffer, buffer, false);
+ }
+
+ /**
+ * Reads a set of lines and returns it as a ImageLines object, which wraps
+ * matrix. Internally it reads all lines, but decodes and stores only the
+ * wanted ones. This starts and ends the reading, and cannot be combined
+ * with other reading methods.
+ * <p>
+ * This it's more efficient (speed an memory) that doing calling
+ * readRowInt() for each desired line only if the image is interlaced.
+ * <p>
+ * Notice that the columns in the matrix is not the pixel width of the
+ * image, but rather pixels x channels
+ *
+ * @see #readRowInt(int) to read about the format of each row
+ *
+ * @param rowOffset
+ * Number of rows to be skipped
+ * @param nRows
+ * Total number of rows to be read. -1: read all available
+ * @param rowStep
+ * Row increment. If 1, we read consecutive lines; if 2, we read
+ * even/odd lines, etc
+ * @return Set of lines as a ImageLines, which wraps a matrix
+ */
+ public ImageLines readRowsInt(final int rowOffset, int nRows, final int rowStep) {
+ if (nRows < 0)
+ nRows = (imgInfo.rows - rowOffset) / rowStep;
+ if (rowStep < 1 || rowOffset < 0 || nRows * rowStep + rowOffset > imgInfo.rows)
+ throw new PngjInputException("bad args");
+ final ImageLines imlines = new ImageLines(imgInfo, SampleType.INT, unpackedMode, rowOffset, nRows, rowStep);
+ if (!interlaced) {
+ for (int j = 0; j < imgInfo.rows; j++) {
+ final int bytesread = readRowRaw(j); // read and perhaps discards
+ final int mrow = imlines.imageRowToMatrixRowStrict(j);
+ if (mrow >= 0)
+ decodeLastReadRowToInt(imlines.scanlines[mrow], bytesread);
+ }
+ } else { // and now, for something completely different (interlaced)
+ final int[] buf = new int[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+ for (int p = 1; p <= 7; p++) {
+ deinterlacer.setPass(p);
+ for (int i = 0; i < deinterlacer.getRows(); i++) {
+ final int bytesread = readRowRaw(i);
+ final int j = deinterlacer.getCurrRowReal();
+ final int mrow = imlines.imageRowToMatrixRowStrict(j);
+ if (mrow >= 0) {
+ decodeLastReadRowToInt(buf, bytesread);
+ deinterlacer.deinterlaceInt(buf, imlines.scanlines[mrow], !unpackedMode);
+ }
+ }
+ }
+ }
+ end();
+ return imlines;
+ }
+
+ /**
+ * Same as readRowsInt(0, imgInfo.rows, 1)
+ *
+ * @see #readRowsInt(int, int, int)
+ */
+ public ImageLines readRowsInt() {
+ return readRowsInt(0, imgInfo.rows, 1);
+ }
+
+ /**
+ * Reads a set of lines and returns it as a ImageLines object, which wrapas
+ * a byte[][] matrix. Internally it reads all lines, but decodes and stores
+ * only the wanted ones. This starts and ends the reading, and cannot be
+ * combined with other reading methods.
+ * <p>
+ * This it's more efficient (speed an memory) that doing calling
+ * readRowByte() for each desired line only if the image is interlaced.
+ * <p>
+ * Notice that the columns in the matrix is not the pixel width of the
+ * image, but rather pixels x channels
+ *
+ * @see #readRowByte(int) to read about the format of each row. Notice that
+ * if the bitdepth is 16 this will lose information
+ *
+ * @param rowOffset
+ * Number of rows to be skipped
+ * @param nRows
+ * Total number of rows to be read. -1: read all available
+ * @param rowStep
+ * Row increment. If 1, we read consecutive lines; if 2, we read
+ * even/odd lines, etc
+ * @return Set of lines as a matrix
+ */
+ public ImageLines readRowsByte(final int rowOffset, int nRows, final int rowStep) {
+ if (nRows < 0)
+ nRows = (imgInfo.rows - rowOffset) / rowStep;
+ if (rowStep < 1 || rowOffset < 0 || nRows * rowStep + rowOffset > imgInfo.rows)
+ throw new PngjInputException("bad args");
+ final ImageLines imlines = new ImageLines(imgInfo, SampleType.BYTE, unpackedMode, rowOffset, nRows, rowStep);
+ if (!interlaced) {
+ for (int j = 0; j < imgInfo.rows; j++) {
+ final int bytesread = readRowRaw(j); // read and perhaps discards
+ final int mrow = imlines.imageRowToMatrixRowStrict(j);
+ if (mrow >= 0)
+ decodeLastReadRowToByte(imlines.scanlinesb[mrow], bytesread);
+ }
+ } else { // and now, for something completely different (interlaced)
+ final byte[] buf = new byte[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+ for (int p = 1; p <= 7; p++) {
+ deinterlacer.setPass(p);
+ for (int i = 0; i < deinterlacer.getRows(); i++) {
+ final int bytesread = readRowRaw(i);
+ final int j = deinterlacer.getCurrRowReal();
+ final int mrow = imlines.imageRowToMatrixRowStrict(j);
+ if (mrow >= 0) {
+ decodeLastReadRowToByte(buf, bytesread);
+ deinterlacer.deinterlaceByte(buf, imlines.scanlinesb[mrow], !unpackedMode);
+ }
+ }
+ }
+ }
+ end();
+ return imlines;
+ }
+
+ /**
+ * Same as readRowsByte(0, imgInfo.rows, 1)
+ *
+ * @see #readRowsByte(int, int, int)
+ */
+ public ImageLines readRowsByte() {
+ return readRowsByte(0, imgInfo.rows, 1);
+ }
+
+ /*
+ * For the interlaced case, nrow indicates the subsampled image - the pass must be set already.
+ *
+ * This must be called in strict order, both for interlaced or no interlaced.
+ *
+ * Updates rowNum.
+ *
+ * Leaves raw result in rowb
+ *
+ * Returns bytes actually read (not including the filter byte)
+ */
+ private int readRowRaw(final int nrow) {
+ if (nrow == 0) {
+ if (firstChunksNotYetRead())
+ readFirstChunks();
+ allocateBuffers();
+ if (interlaced)
+ Arrays.fill(rowb, (byte) 0); // new subimage: reset filters: this is enough, see the swap that happens lines
+ }
+ // below
+ int bytesRead = imgInfo.bytesPerRow; // NOT including the filter byte
+ if (interlaced) {
+ if (nrow < 0 || nrow > deinterlacer.getRows() || (nrow != 0 && nrow != deinterlacer.getCurrRowSubimg() + 1))
+ throw new PngjInputException("invalid row in interlaced mode: " + nrow);
+ deinterlacer.setRow(nrow);
+ bytesRead = (imgInfo.bitspPixel * deinterlacer.getPixelsToRead() + 7) / 8;
+ if (bytesRead < 1)
+ throw new PngjExceptionInternal("wtf??");
+ } else { // check for non interlaced
+ if (nrow < 0 || nrow >= imgInfo.rows || nrow != rowNum + 1)
+ throw new PngjInputException("invalid row: " + nrow);
+ }
+ rowNum = nrow;
+ // swap buffers
+ final byte[] tmp = rowb;
+ rowb = rowbprev;
+ rowbprev = tmp;
+ // loads in rowbfilter "raw" bytes, with filter
+ PngHelperInternal.readBytes(idatIstream, rowbfilter, 0, bytesRead + 1);
+ offset = iIdatCstream.getOffset();
+ if (offset < 0)
+ throw new PngjExceptionInternal("bad offset ??" + offset);
+ if (maxTotalBytesRead > 0 && offset >= maxTotalBytesRead)
+ throw new PngjInputException("Reading IDAT: Maximum total bytes to read exceeeded: " + maxTotalBytesRead
+ + " offset:" + offset);
+ rowb[0] = 0;
+ unfilterRow(bytesRead);
+ rowb[0] = rowbfilter[0];
+ if ((rowNum == imgInfo.rows - 1 && !interlaced) || (interlaced && deinterlacer.isAtLastRow()))
+ readLastAndClose();
+ return bytesRead;
+ }
+
+ /**
+ * Reads all the (remaining) file, skipping the pixels data. This is much
+ * more efficient that calling readRow(), specially for big files (about 10
+ * times faster!), because it doesn't even decompress the IDAT stream and
+ * disables CRC check Use this if you are not interested in reading
+ * pixels,only metadata.
+ */
+ public void readSkippingAllRows() {
+ if (firstChunksNotYetRead())
+ readFirstChunks();
+ // we read directly from the compressed stream, we dont decompress nor chec CRC
+ iIdatCstream.disableCrcCheck();
+ allocateBuffers();
+ try {
+ int r;
+ do {
+ r = iIdatCstream.read(rowbfilter, 0, buffersLen);
+ } while (r >= 0);
+ } catch (final IOException e) {
+ throw new PngjInputException("error in raw read of IDAT", e);
+ }
+ offset = iIdatCstream.getOffset();
+ if (offset < 0)
+ throw new PngjExceptionInternal("bad offset ??" + offset);
+ if (maxTotalBytesRead > 0 && offset >= maxTotalBytesRead)
+ throw new PngjInputException("Reading IDAT: Maximum total bytes to read exceeeded: " + maxTotalBytesRead
+ + " offset:" + offset);
+ readLastAndClose();
+ }
+
+ /**
+ * Set total maximum bytes to read (0: unlimited; default: 200MB). <br>
+ * These are the bytes read (not loaded) in the input stream. If exceeded,
+ * an exception will be thrown.
+ */
+ public void setMaxTotalBytesRead(final long maxTotalBytesToRead) {
+ this.maxTotalBytesRead = maxTotalBytesToRead;
+ }
+
+ /**
+ * @return Total maximum bytes to read.
+ */
+ public long getMaxTotalBytesRead() {
+ return maxTotalBytesRead;
+ }
+
+ /**
+ * Set total maximum bytes to load from ancillary chunks (0: unlimited;
+ * default: 5Mb).<br>
+ * If exceeded, some chunks will be skipped
+ */
+ public void setMaxBytesMetadata(final int maxBytesChunksToLoad) {
+ this.maxBytesMetadata = maxBytesChunksToLoad;
+ }
+
+ /**
+ * @return Total maximum bytes to load from ancillary ckunks.
+ */
+ public int getMaxBytesMetadata() {
+ return maxBytesMetadata;
+ }
+
+ /**
+ * Set maximum size in bytes for individual ancillary chunks (0: unlimited;
+ * default: 2MB). <br>
+ * Chunks exceeding this length will be skipped (the CRC will not be
+ * checked) and the chunk will be saved as a PngChunkSkipped object. See
+ * also setSkipChunkIds
+ */
+ public void setSkipChunkMaxSize(final int skipChunksBySize) {
+ this.skipChunkMaxSize = skipChunksBySize;
+ }
+
+ /**
+ * @return maximum size in bytes for individual ancillary chunks.
+ */
+ public int getSkipChunkMaxSize() {
+ return skipChunkMaxSize;
+ }
+
+ /**
+ * Chunks ids to be skipped. <br>
+ * These chunks will be skipped (the CRC will not be checked) and the chunk
+ * will be saved as a PngChunkSkipped object. See also setSkipChunkMaxSize
+ */
+ public void setSkipChunkIds(final String[] skipChunksById) {
+ this.skipChunkIds = skipChunksById == null ? new String[] {} : skipChunksById;
+ }
+
+ /**
+ * @return Chunk-IDs to be skipped.
+ */
+ public String[] getSkipChunkIds() {
+ return skipChunkIds;
+ }
+
+ /**
+ * if true, input stream will be closed after ending read
+ * <p>
+ * default=true
+ */
+ public void setShouldCloseStream(final boolean shouldCloseStream) {
+ this.shouldCloseStream = shouldCloseStream;
+ }
+
+ /**
+ * Normally this does nothing, but it can be used to force a premature
+ * closing. Its recommended practice to call it after reading the image
+ * pixels.
+ */
+ public void end() {
+ if (currentChunkGroup < ChunksList.CHUNK_GROUP_6_END)
+ close();
+ }
+
+ /**
+ * Interlaced PNG is accepted -though not welcomed- now...
+ */
+ public boolean isInterlaced() {
+ return interlaced;
+ }
+
+ /**
+ * set/unset "unpackedMode"<br>
+ * If false (default) packed types (bitdepth=1,2 or 4) will keep several
+ * samples packed in one element (byte or int) <br>
+ * If true, samples will be unpacked on reading, and each element in the
+ * scanline will be sample. This implies more processing and memory, but
+ * it's the most efficient option if you intend to read individual pixels. <br>
+ * This option should only be set before start reading.
+ *
+ * @param unPackedMode
+ */
+ public void setUnpackedMode(final boolean unPackedMode) {
+ this.unpackedMode = unPackedMode;
+ }
+
+ /**
+ * @see PngReader#setUnpackedMode(boolean)
+ */
+ public boolean isUnpackedMode() {
+ return unpackedMode;
+ }
+
+ /**
+ * Tries to reuse the allocated buffers from other already used PngReader
+ * object. This will have no effect if the buffers are smaller than necessary.
+ * It also reuses the inflater.
+ *
+ * @param other A PngReader that has already finished reading pixels. Can be null.
+ */
+ public void reuseBuffersFrom(final PngReader other) {
+ if(other==null) return;
+ if (other.currentChunkGroup < ChunksList.CHUNK_GROUP_5_AFTERIDAT)
+ throw new PngjInputException("PngReader to be reused have not yet ended reading pixels");
+ if (other.rowbfilter != null && other.rowbfilter.length >= buffersLen) {
+ rowbfilter = other.rowbfilter;
+ rowb = other.rowb;
+ rowbprev = other.rowbprev;
+ }
+ inflater = other.inflater;
+ }
+
+ /**
+ * Disables the CRC integrity check in IDAT chunks and ancillary chunks,
+ * this gives a slight increase in reading speed for big files
+ */
+ public void setCrcCheckDisabled() {
+ crcEnabled = false;
+ }
+
+ /**
+ * Just for testing. TO be called after ending reading, only if
+ * initCrctest() was called before start
+ *
+ * @return CRC of the raw pixels values
+ */
+ long getCrctestVal() {
+ return crctest.getValue();
+ }
+
+ /**
+ * Inits CRC object and enables CRC calculation
+ */
+ void initCrctest() {
+ this.crctest = new CRC32();
+ }
+
+ /**
+ * Basic info, for debugging.
+ */
+ @Override
+ public String toString() { // basic info
+ return "filename=" + filename + " " + imgInfo.toString();
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java
index ee8472bf0..ed5dd7d69 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java
@@ -7,54 +7,88 @@ import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
+import jogamp.opengl.util.pngj.ImageLine.SampleType;
import jogamp.opengl.util.pngj.chunks.ChunkCopyBehaviour;
import jogamp.opengl.util.pngj.chunks.ChunkHelper;
-import jogamp.opengl.util.pngj.chunks.ChunkList;
+import jogamp.opengl.util.pngj.chunks.ChunksList;
+import jogamp.opengl.util.pngj.chunks.ChunksListForWrite;
import jogamp.opengl.util.pngj.chunks.PngChunk;
import jogamp.opengl.util.pngj.chunks.PngChunkIEND;
import jogamp.opengl.util.pngj.chunks.PngChunkIHDR;
+import jogamp.opengl.util.pngj.chunks.PngChunkSkipped;
import jogamp.opengl.util.pngj.chunks.PngChunkTextVar;
import jogamp.opengl.util.pngj.chunks.PngMetadata;
-
/**
- * Writes a PNG image, line by line.
+ * Writes a PNG image
*/
public class PngWriter {
public final ImageInfo imgInfo;
- protected int compLevel = 6; // zip compression level 0 - 9
- private int deflaterStrategy = Deflater.FILTERED;
- protected FilterWriteStrategy filterStrat;
+ private final String filename; // optional, can be a description
+
+ /**
+ * last read row number, starting from 0
+ */
+ protected int rowNum = -1;
+ private final ChunksListForWrite chunksList;
+
+ private final PngMetadata metadata; // high level wrapper over chunkList
+
+ /**
+ * Current chunk grounp, (0-6) already read or reading
+ * <p>
+ * see {@link ChunksList}
+ */
protected int currentChunkGroup = -1;
- protected int rowNum = -1; // current line number
- // current line, one (packed) sample per element (layout differnt from rowb!)
- protected int[] scanline = null;
- protected byte[] rowb = null; // element 0 is filter type!
- protected byte[] rowbprev = null; // rowb prev
- protected byte[] rowbfilter = null; // current line with filter
+ /**
+ * PNG filter strategy
+ */
+ protected FilterWriteStrategy filterStrat;
- protected final OutputStream os;
- protected final String filename; // optional, can be a description
+ /**
+ * zip compression level 0 - 9
+ */
+ private int compLevel = 6;
+ private boolean shouldCloseStream = true; // true: closes stream after ending write
private PngIDatChunkOutputStream datStream;
+
private DeflaterOutputStream datStreamDeflated;
- private final ChunkList chunkList;
- private final PngMetadata metadata; // high level wrapper over chunkList
+ /**
+ * Deflate algortithm compression strategy
+ */
+ private int deflaterStrategy = Deflater.FILTERED;
+
+ private final int[] histox = new int[256]; // auxiliar buffer, only used by reportResultsForFilter
+
+ private int idatMaxSize = 0; // 0=use default (PngIDatChunkOutputStream 32768)
+
+ private final OutputStream os;
+
+ protected byte[] rowb = null; // element 0 is filter type!
+ protected byte[] rowbfilter = null; // current line with filter
+
+ protected byte[] rowbprev = null; // rowb prev
- public PngWriter(OutputStream outputStream, ImageInfo imgInfo) {
+ // this only influences the 1-2-4 bitdepth format - and if we pass a ImageLine to writeRow, this is ignored
+ private boolean unpackedMode = false;
+
+ public PngWriter(final OutputStream outputStream, final ImageInfo imgInfo) {
this(outputStream, imgInfo, "[NO FILENAME AVAILABLE]");
}
/**
- * Constructs a new PngWriter from a output stream.
+ * Constructs a new PngWriter from a output stream. After construction
+ * nothing is writen yet. You still can set some parameters (compression,
+ * filters) and queue chunks before start writing the pixels.
* <p>
* See also <code>FileHelper.createPngWriter()</code> if available.
- *
+ *
* @param outputStream
* Opened stream for binary writing
* @param imgInfo
@@ -62,179 +96,164 @@ public class PngWriter {
* @param filenameOrDescription
* Optional, just for error/debug messages
*/
- public PngWriter(OutputStream outputStream, ImageInfo imgInfo, String filenameOrDescription) {
+ public PngWriter(final OutputStream outputStream, final ImageInfo imgInfo, final String filenameOrDescription) {
this.filename = filenameOrDescription == null ? "" : filenameOrDescription;
this.os = outputStream;
this.imgInfo = imgInfo;
// prealloc
- scanline = new int[imgInfo.samplesPerRowP];
rowb = new byte[imgInfo.bytesPerRow + 1];
rowbprev = new byte[rowb.length];
rowbfilter = new byte[rowb.length];
- datStream = new PngIDatChunkOutputStream(this.os);
- chunkList = new ChunkList(imgInfo);
- metadata = new PngMetadata(chunkList, false);
- filterStrat = new FilterWriteStrategy(imgInfo, FilterType.FILTER_DEFAULT);
+ chunksList = new ChunksListForWrite(imgInfo);
+ metadata = new PngMetadata(chunksList);
+ filterStrat = new FilterWriteStrategy(imgInfo, FilterType.FILTER_DEFAULT); // can be changed
}
- /**
- * Write id signature and also "IHDR" chunk
- */
- private void writeSignatureAndIHDR() {
- currentChunkGroup = ChunkList.CHUNK_GROUP_0_IDHR;
- if (datStreamDeflated == null) {
- Deflater def = new Deflater(compLevel);
- def.setStrategy(deflaterStrategy);
- datStreamDeflated = new DeflaterOutputStream(datStream, def, 8192);
+ private void init() {
+ datStream = new PngIDatChunkOutputStream(this.os, idatMaxSize);
+ final Deflater def = new Deflater(compLevel);
+ def.setStrategy(deflaterStrategy);
+ datStreamDeflated = new DeflaterOutputStream(datStream, def);
+ writeSignatureAndIHDR();
+ writeFirstChunks();
+ }
+
+ private void reportResultsForFilter(final int rown, final FilterType type, final boolean tentative) {
+ Arrays.fill(histox, 0);
+ int s = 0, v;
+ for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
+ v = rowbfilter[i];
+ if (v < 0)
+ s -= v;
+ else
+ s += v;
+ histox[v & 0xFF]++;
}
- PngHelper.writeBytes(os, PngHelper.pngIdBytes); // signature
- PngChunkIHDR ihdr = new PngChunkIHDR(imgInfo);
- // http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
- ihdr.setCols(imgInfo.cols);
- ihdr.setRows(imgInfo.rows);
- ihdr.setBitspc(imgInfo.bitDepth);
- int colormodel = 0;
- if (imgInfo.alpha)
- colormodel += 0x04;
- if (imgInfo.indexed)
- colormodel += 0x01;
- if (!imgInfo.greyscale)
- colormodel += 0x02;
- ihdr.setColormodel(colormodel);
- ihdr.setCompmeth(0); // compression method 0=deflate
- ihdr.setFilmeth(0); // filter method (0)
- ihdr.setInterlaced(0); // we never interlace
- ihdr.createChunk().writeChunk(os);
+ filterStrat.fillResultsForFilter(rown, type, s, histox, tentative);
+ }
+ private void writeEndChunk() {
+ final PngChunkIEND c = new PngChunkIEND(imgInfo);
+ c.createRawChunk().writeChunk(os);
}
private void writeFirstChunks() {
int nw = 0;
- currentChunkGroup = ChunkList.CHUNK_GROUP_1_AFTERIDHR;
- nw = chunkList.writeChunks(os, currentChunkGroup);
- currentChunkGroup = ChunkList.CHUNK_GROUP_2_PLTE;
- nw = chunkList.writeChunks(os, currentChunkGroup);
+ currentChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+ nw = chunksList.writeChunks(os, currentChunkGroup);
+ currentChunkGroup = ChunksList.CHUNK_GROUP_2_PLTE;
+ nw = chunksList.writeChunks(os, currentChunkGroup);
if (nw > 0 && imgInfo.greyscale)
throw new PngjOutputException("cannot write palette for this format");
if (nw == 0 && imgInfo.indexed)
throw new PngjOutputException("missing palette");
- currentChunkGroup = ChunkList.CHUNK_GROUP_3_AFTERPLTE;
- nw = chunkList.writeChunks(os, currentChunkGroup);
- currentChunkGroup = ChunkList.CHUNK_GROUP_4_IDAT;
+ currentChunkGroup = ChunksList.CHUNK_GROUP_3_AFTERPLTE;
+ nw = chunksList.writeChunks(os, currentChunkGroup);
+ currentChunkGroup = ChunksList.CHUNK_GROUP_4_IDAT;
}
private void writeLastChunks() { // not including end
- currentChunkGroup = ChunkList.CHUNK_GROUP_5_AFTERIDAT;
- chunkList.writeChunks(os, currentChunkGroup);
+ currentChunkGroup = ChunksList.CHUNK_GROUP_5_AFTERIDAT;
+ chunksList.writeChunks(os, currentChunkGroup);
// should not be unwriten chunks
- List<PngChunk> pending = chunkList.getQueuedChunks();
+ final List<PngChunk> pending = chunksList.getQueuedChunks();
if (!pending.isEmpty())
throw new PngjOutputException(pending.size() + " chunks were not written! Eg: " + pending.get(0).toString());
- currentChunkGroup = ChunkList.CHUNK_GROUP_6_END;
- }
-
- private void writeEndChunk() {
- PngChunkIEND c = new PngChunkIEND(imgInfo);
- c.createChunk().writeChunk(os);
+ currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
}
/**
- * Writes a full image row. This must be called sequentially from n=0 to n=rows-1 One integer per sample , in the
- * natural order: R G B R G B ... (or R G B A R G B A... if has alpha) The values should be between 0 and 255 for 8
- * bitspc images, and between 0- 65535 form 16 bitspc images (this applies also to the alpha channel if present) The
- * array can be reused.
- *
- * @param newrow
- * Array of pixel values
- * @param rown
- * Row number, from 0 (top) to rows-1 (bottom). This is just used as a check. Pass -1 if you want to
- * autocompute it
+ * Write id signature and also "IHDR" chunk
*/
- public void writeRow(int[] newrow, int rown) {
- if (rown == 0) {
- writeSignatureAndIHDR();
- writeFirstChunks();
- }
- if (rown < -1 || rown > imgInfo.rows)
- throw new RuntimeException("invalid value for row " + rown);
- rowNum++;
- if (rown >= 0 && rowNum != rown)
- throw new RuntimeException("rows must be written in strict consecutive order: tried to write row " + rown
- + ", expected=" + rowNum);
- scanline = newrow;
- // swap
- byte[] tmp = rowb;
- rowb = rowbprev;
- rowbprev = tmp;
- convertRowToBytes();
- filterRow(rown);
- try {
- datStreamDeflated.write(rowbfilter, 0, imgInfo.bytesPerRow + 1);
- } catch (IOException e) {
- throw new PngjOutputException(e);
- }
- }
+ private void writeSignatureAndIHDR() {
+ currentChunkGroup = ChunksList.CHUNK_GROUP_0_IDHR;
- /**
- * Same as writeRow(int[] newrow, int rown), but does not check row number
- *
- * @param newrow
- */
- public void writeRow(int[] newrow) {
- writeRow(newrow, -1);
- }
+ PngHelperInternal.writeBytes(os, PngHelperInternal.getPngIdSignature()); // signature
+ final PngChunkIHDR ihdr = new PngChunkIHDR(imgInfo);
+ // http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
+ ihdr.setCols(imgInfo.cols);
+ ihdr.setRows(imgInfo.rows);
+ ihdr.setBitspc(imgInfo.bitDepth);
+ int colormodel = 0;
+ if (imgInfo.alpha)
+ colormodel += 0x04;
+ if (imgInfo.indexed)
+ colormodel += 0x01;
+ if (!imgInfo.greyscale)
+ colormodel += 0x02;
+ ihdr.setColormodel(colormodel);
+ ihdr.setCompmeth(0); // compression method 0=deflate
+ ihdr.setFilmeth(0); // filter method (0)
+ ihdr.setInterlaced(0); // we never interlace
+ ihdr.createRawChunk().writeChunk(os);
- /**
- * Writes line. See writeRow(int[] newrow, int rown)
- */
- public void writeRow(ImageLine imgline, int rownumber) {
- writeRow(imgline.scanline, rownumber);
}
- /**
- * Writes line, checks that the row number is consistent with that of the ImageLine See writeRow(int[] newrow, int
- * rown)
- *
- * @deprecated Better use writeRow(ImageLine imgline, int rownumber)
- */
- public void writeRow(ImageLine imgline) {
- writeRow(imgline.scanline, imgline.getRown());
- }
+ protected void encodeRowFromByte(final byte[] row) {
+ if (row.length == imgInfo.samplesPerRowPacked) {
+ // some duplication of code - because this case is typical and it works faster this way
+ int j = 1;
+ if (imgInfo.bitDepth <= 8) {
+ for (final byte x : row) { // optimized
+ rowb[j++] = x;
+ }
+ } else { // 16 bitspc
+ for (final byte x : row) { // optimized
+ rowb[j] = x;
+ j += 2;
+ }
+ }
+ } else {
+ // perhaps we need to pack?
+ if (row.length >= imgInfo.samplesPerRow && unpackedMode)
+ ImageLine.packInplaceByte(imgInfo, row, row, false); // row is packed in place!
+ if (imgInfo.bitDepth <= 8) {
+ for (int i = 0, j = 1; i < imgInfo.samplesPerRowPacked; i++) {
+ rowb[j++] = row[i];
+ }
+ } else { // 16 bitspc
+ for (int i = 0, j = 1; i < imgInfo.samplesPerRowPacked; i++) {
+ rowb[j++] = row[i];
+ rowb[j++] = 0;
+ }
+ }
- /**
- * Finalizes the image creation and closes the stream. This MUST be called after writing the lines.
- */
- public void end() {
- if (rowNum != imgInfo.rows - 1)
- throw new PngjOutputException("all rows have not been written");
- try {
- datStreamDeflated.finish();
- datStream.flush();
- writeLastChunks();
- writeEndChunk();
- os.close();
- } catch (IOException e) {
- throw new PngjOutputException(e);
}
}
- private int[] histox = new int[256]; // auxiliar buffer, only used by reportResultsForFilter
-
- private void reportResultsForFilter(int rown, FilterType type, boolean tentative) {
- Arrays.fill(histox, 0);
- int s = 0, v;
- for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
- v = rowbfilter[i];
- if (v < 0)
- s -= (int) v;
- else
- s += (int) v;
- histox[v & 0xFF]++;
+ protected void encodeRowFromInt(final int[] row) {
+ // http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html
+ if (row.length == imgInfo.samplesPerRowPacked) {
+ // some duplication of code - because this case is typical and it works faster this way
+ int j = 1;
+ if (imgInfo.bitDepth <= 8) {
+ for (final int x : row) { // optimized
+ rowb[j++] = (byte) x;
+ }
+ } else { // 16 bitspc
+ for (final int x : row) { // optimized
+ rowb[j++] = (byte) (x >> 8);
+ rowb[j++] = (byte) (x);
+ }
+ }
+ } else {
+ // perhaps we need to pack?
+ if (row.length >= imgInfo.samplesPerRow && unpackedMode)
+ ImageLine.packInplaceInt(imgInfo, row, row, false); // row is packed in place!
+ if (imgInfo.bitDepth <= 8) {
+ for (int i = 0, j = 1; i < imgInfo.samplesPerRowPacked; i++) {
+ rowb[j++] = (byte) (row[i]);
+ }
+ } else { // 16 bitspc
+ for (int i = 0, j = 1; i < imgInfo.samplesPerRowPacked; i++) {
+ rowb[j++] = (byte) (row[i] >> 8);
+ rowb[j++] = (byte) (row[i]);
+ }
+ }
}
- filterStrat.fillResultsForFilter(rown, type, s, histox, tentative);
}
- private void filterRow(int rown) {
+ private void filterRow(final int rown) {
// warning: filters operation rely on: "previos row" (rowbprev) is
// initialized to 0 the first time
if (filterStrat.shouldTestAll(rown)) {
@@ -249,7 +268,7 @@ public class PngWriter {
filterRowPaeth();
reportResultsForFilter(rown, FilterType.FILTER_PAETH, true);
}
- FilterType filterType = filterStrat.gimmeFilterType(rown, true);
+ final FilterType filterType = filterStrat.gimmeFilterType(rown, true);
rowbfilter[0] = (byte) filterType.val;
switch (filterType) {
case FILTER_NONE:
@@ -268,123 +287,98 @@ public class PngWriter {
filterRowPaeth();
break;
default:
- throw new PngjOutputException("Filter type " + filterType + " not implemented");
+ throw new PngjUnsupportedException("Filter type " + filterType + " not implemented");
}
reportResultsForFilter(rown, filterType, false);
}
- protected int sumRowbfilter() { // sums absolute value
- int s = 0;
- for (int i = 1; i <= imgInfo.bytesPerRow; i++)
- if (rowbfilter[i] < 0)
- s -= (int) rowbfilter[i];
- else
- s += (int) rowbfilter[i];
- return s;
+ private void prepareEncodeRow(final int rown) {
+ if (datStream == null)
+ init();
+ rowNum++;
+ if (rown >= 0 && rowNum != rown)
+ throw new PngjOutputException("rows must be written in order: expected:" + rowNum + " passed:" + rown);
+ // swap
+ final byte[] tmp = rowb;
+ rowb = rowbprev;
+ rowbprev = tmp;
}
- protected void filterRowNone() {
- for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
- rowbfilter[i] = (byte) rowb[i];
+ private void filterAndSend(final int rown) {
+ filterRow(rown);
+ try {
+ datStreamDeflated.write(rowbfilter, 0, imgInfo.bytesPerRow + 1);
+ } catch (final IOException e) {
+ throw new PngjOutputException(e);
}
}
- protected void filterRowSub() {
- int i, j;
- for (i = 1; i <= imgInfo.bytesPixel; i++)
- rowbfilter[i] = (byte) rowb[i];
- for (j = 1, i = imgInfo.bytesPixel + 1; i <= imgInfo.bytesPerRow; i++, j++) {
- rowbfilter[i] = (byte) (rowb[i] - rowb[j]);
+ protected void filterRowAverage() {
+ int i, j, imax;
+ imax = imgInfo.bytesPerRow;
+ for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imax; i++, j++) {
+ rowbfilter[i] = (byte) (rowb[i] - ((rowbprev[i] & 0xFF) + (j > 0 ? (rowb[j] & 0xFF) : 0)) / 2);
}
}
- protected void filterRowUp() {
+ protected void filterRowNone() {
for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
- rowbfilter[i] = (byte) (rowb[i] - rowbprev[i]);
- }
- }
-
- protected void filterRowAverage() {
- int i, j;
- for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imgInfo.bytesPerRow; i++, j++) {
- rowbfilter[i] = (byte) (rowb[i] - ((rowbprev[i] & 0xFF) + (j > 0 ? (rowb[j] & 0xFF) : 0)) / 2);
+ rowbfilter[i] = rowb[i];
}
}
protected void filterRowPaeth() {
- int i, j;
- for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imgInfo.bytesPerRow; i++, j++) {
- rowbfilter[i] = (byte) (rowb[i] - FilterType.filterPaethPredictor(j > 0 ? (rowb[j] & 0xFF) : 0,
- rowbprev[i] & 0xFF, j > 0 ? (rowbprev[j] & 0xFF) : 0));
+ int i, j, imax;
+ imax = imgInfo.bytesPerRow;
+ for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imax; i++, j++) {
+ // rowbfilter[i] = (byte) (rowb[i] - PngHelperInternal.filterPaethPredictor(j > 0 ? (rowb[j] & 0xFF) : 0,
+ // rowbprev[i] & 0xFF, j > 0 ? (rowbprev[j] & 0xFF) : 0));
+ rowbfilter[i] = (byte) PngHelperInternal.filterRowPaeth(rowb[i], j > 0 ? (rowb[j] & 0xFF) : 0,
+ rowbprev[i] & 0xFF, j > 0 ? (rowbprev[j] & 0xFF) : 0);
}
}
- protected void convertRowToBytes() {
- // http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html
+ protected void filterRowSub() {
int i, j;
- if (imgInfo.bitDepth <= 8) {
- for (i = 0, j = 1; i < imgInfo.samplesPerRowP; i++) {
- rowb[j++] = (byte) (scanline[i]);
- }
- } else { // 16 bitspc
- for (i = 0, j = 1; i < imgInfo.samplesPerRowP; i++) {
- // x = (int) (scanline[i]) & 0xFFFF;
- rowb[j++] = (byte) (scanline[i] >> 8);
- rowb[j++] = (byte) (scanline[i]);
- }
+ for (i = 1; i <= imgInfo.bytesPixel; i++)
+ rowbfilter[i] = rowb[i];
+ for (j = 1, i = imgInfo.bytesPixel + 1; i <= imgInfo.bytesPerRow; i++, j++) {
+ // !!! rowbfilter[i] = (byte) (rowb[i] - rowb[j]);
+ rowbfilter[i] = (byte) PngHelperInternal.filterRowSub(rowb[i], rowb[j]);
}
}
- // /// several getters / setters - all this setters are optional
-
- /**
- * Filename or description, from the optional constructor argument.
- */
- public String getFilename() {
- return filename;
+ protected void filterRowUp() {
+ for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
+ // rowbfilter[i] = (byte) (rowb[i] - rowbprev[i]); !!!
+ rowbfilter[i] = (byte) PngHelperInternal.filterRowUp(rowb[i], rowbprev[i]);
+ }
}
- /**
- * Sets internal prediction filter type, or strategy to choose it.
- * <p>
- * This must be called just after constructor, before starting writing.
- * <p>
- * See also setCompLevel()
- *
- * @param filterType
- * One of the five prediction types or strategy to choose it (see <code>PngFilterType</code>) Recommended
- * values: DEFAULT (default) or AGGRESIVE
- */
- public void setFilterType(FilterType filterType) {
- filterStrat = new FilterWriteStrategy(imgInfo, filterType);
+ protected int sumRowbfilter() { // sums absolute value
+ int s = 0;
+ for (int i = 1; i <= imgInfo.bytesPerRow; i++)
+ if (rowbfilter[i] < 0)
+ s -= rowbfilter[i];
+ else
+ s += rowbfilter[i];
+ return s;
}
/**
- * Sets compression level of ZIP algorithm.
+ * copy chunks from reader - copy_mask : see ChunksToWrite.COPY_XXX
* <p>
- * This must be called just after constructor, before starting writing.
+ * If we are after idat, only considers those chunks after IDAT in PngReader
* <p>
- * See also setFilterType()
- *
- * @param compLevel
- * between 0 and 9 (default:6 , recommended: 6 or more)
+ * TODO: this should be more customizable
*/
- public void setCompLevel(int compLevel) {
- if (compLevel < 0 || compLevel > 9)
- throw new PngjException("Compression level invalid (" + compLevel + ") Must be 0..9");
- this.compLevel = compLevel;
- }
-
- /**
- * copy chunks from reader - copy_mask : see ChunksToWrite.COPY_XXX
- *
- * If we are after idat, only considers those chunks after IDAT in PngReader TODO: this should be more customizable
- */
- private void copyChunks(PngReader reader, int copy_mask, boolean onlyAfterIdat) {
- boolean idatDone = currentChunkGroup >= ChunkList.CHUNK_GROUP_4_IDAT;
- for (PngChunk chunk : reader.getChunksList().getChunks()) {
- int group = chunk.getChunkGroup();
- if (group < ChunkList.CHUNK_GROUP_4_IDAT && idatDone)
+ private void copyChunks(final PngReader reader, final int copy_mask, final boolean onlyAfterIdat) {
+ final boolean idatDone = currentChunkGroup >= ChunksList.CHUNK_GROUP_4_IDAT;
+ if (onlyAfterIdat && reader.getCurrentChunkGroup() < ChunksList.CHUNK_GROUP_6_END)
+ throw new PngjExceptionInternal("tried to copy last chunks but reader has not ended");
+ for (final PngChunk chunk : reader.getChunksList().getChunks()) {
+ final int group = chunk.getChunkGroup();
+ if (group < ChunksList.CHUNK_GROUP_4_IDAT && idatDone)
continue;
boolean copy = false;
if (chunk.crit) {
@@ -395,8 +389,8 @@ public class PngWriter {
copy = true;
}
} else { // ancillary
- boolean text = (chunk instanceof PngChunkTextVar);
- boolean safe = chunk.safe;
+ final boolean text = (chunk instanceof PngChunkTextVar);
+ final boolean safe = chunk.safe;
// notice that these if are not exclusive
if (ChunkHelper.maskMatch(copy_mask, ChunkCopyBehaviour.COPY_ALL))
copy = true;
@@ -413,9 +407,11 @@ public class PngWriter {
&& !(ChunkHelper.isUnknown(chunk) || text || chunk.id.equals(ChunkHelper.hIST) || chunk.id
.equals(ChunkHelper.tIME)))
copy = true;
+ if (chunk instanceof PngChunkSkipped)
+ copy = false;
}
if (copy) {
- chunkList.queueChunk(PngChunk.cloneChunk(chunk, imgInfo), !chunk.allowsMultiple(), false);
+ chunksList.queue(PngChunk.cloneChunk(chunk, imgInfo));
}
}
}
@@ -423,40 +419,271 @@ public class PngWriter {
/**
* Copies first (pre IDAT) ancillary chunks from a PngReader.
* <p>
- * Should be called when creating an image from another, before starting writing lines, to copy relevant chunks.
+ * Should be called when creating an image from another, before starting
+ * writing lines, to copy relevant chunks.
* <p>
- *
+ *
* @param reader
* : PngReader object, already opened.
* @param copy_mask
- * : Mask bit (OR), see <code>ChunksToWrite.COPY_XXX</code> constants
+ * : Mask bit (OR), see <code>ChunksToWrite.COPY_XXX</code>
+ * constants
*/
- public void copyChunksFirst(PngReader reader, int copy_mask) {
+ public void copyChunksFirst(final PngReader reader, final int copy_mask) {
copyChunks(reader, copy_mask, false);
}
/**
* Copies last (post IDAT) ancillary chunks from a PngReader.
* <p>
- * Should be called when creating an image from another, after writing all lines, before closing the writer, to copy
- * additional chunks.
+ * Should be called when creating an image from another, after writing all
+ * lines, before closing the writer, to copy additional chunks.
* <p>
- *
+ *
* @param reader
* : PngReader object, already opened and fully read.
* @param copy_mask
- * : Mask bit (OR), see <code>ChunksToWrite.COPY_XXX</code> constants
+ * : Mask bit (OR), see <code>ChunksToWrite.COPY_XXX</code>
+ * constants
*/
- public void copyChunksLast(PngReader reader, int copy_mask) {
+ public void copyChunksLast(final PngReader reader, final int copy_mask) {
copyChunks(reader, copy_mask, true);
}
- public ChunkList getChunkList() {
- return chunkList;
+ /**
+ * Computes compressed size/raw size, approximate.
+ * <p>
+ * Actually: compressed size = total size of IDAT data , raw size =
+ * uncompressed pixel bytes = rows * (bytesPerRow + 1).
+ *
+ * This must be called after pngw.end()
+ */
+ public double computeCompressionRatio() {
+ if (currentChunkGroup < ChunksList.CHUNK_GROUP_6_END)
+ throw new PngjOutputException("must be called after end()");
+ final double compressed = datStream.getCountFlushed();
+ final double raw = (imgInfo.bytesPerRow + 1) * imgInfo.rows;
+ return compressed / raw;
+ }
+
+ /**
+ * Finalizes the image creation and closes the stream. This MUST be called
+ * after writing the lines.
+ */
+ public void end() {
+ if (rowNum != imgInfo.rows - 1)
+ throw new PngjOutputException("all rows have not been written");
+ try {
+ datStreamDeflated.finish();
+ datStream.flush();
+ writeLastChunks();
+ writeEndChunk();
+ if (shouldCloseStream)
+ os.close();
+ } catch (final IOException e) {
+ throw new PngjOutputException(e);
+ }
+ }
+
+ /**
+ * returns the chunks list (queued and writen chunks)
+ */
+ public ChunksListForWrite getChunksList() {
+ return chunksList;
}
+ /**
+ * Filename or description, from the optional constructor argument.
+ */
+ public String getFilename() {
+ return filename;
+ }
+
+ /**
+ * High level wrapper over chunksList for metadata handling
+ */
public PngMetadata getMetadata() {
return metadata;
}
+ /**
+ * Sets compression level of ZIP algorithm.
+ * <p>
+ * This must be called just after constructor, before starting writing.
+ * <p>
+ * See also setFilterType()
+ *
+ * @param compLevel
+ * between 0 and 9 (default:6 , recommended: 6 or more)
+ */
+ public void setCompLevel(final int compLevel) {
+ if (compLevel < 0 || compLevel > 9)
+ throw new PngjOutputException("Compression level invalid (" + compLevel + ") Must be 0..9");
+ this.compLevel = compLevel;
+ }
+
+ /**
+ * Sets internal prediction filter type, or strategy to choose it.
+ * <p>
+ * This must be called just after constructor, before starting writing.
+ * <p>
+ * See also setCompLevel()
+ *
+ * @param filterType
+ * One of the five prediction types or strategy to choose it (see
+ * <code>PngFilterType</code>) Recommended values: DEFAULT
+ * (default) or AGGRESIVE
+ */
+ public void setFilterType(final FilterType filterType) {
+ filterStrat = new FilterWriteStrategy(imgInfo, filterType);
+ }
+
+ /**
+ * Sets maximum size of IDAT fragments. This has little effect on
+ * performance you should rarely call this
+ * <p>
+ *
+ * @param idatMaxSize
+ * default=0 : use defaultSize (32K)
+ */
+ public void setIdatMaxSize(final int idatMaxSize) {
+ this.idatMaxSize = idatMaxSize;
+ }
+
+ /**
+ * if true, input stream will be closed after ending write
+ * <p>
+ * default=true
+ */
+ public void setShouldCloseStream(final boolean shouldCloseStream) {
+ this.shouldCloseStream = shouldCloseStream;
+ }
+
+ /**
+ * Deflater strategy: one of Deflater.FILTERED Deflater.HUFFMAN_ONLY
+ * Deflater.DEFAULT_STRATEGY
+ * <p>
+ * Default: Deflater.FILTERED . This should be changed very rarely.
+ */
+ public void setDeflaterStrategy(final int deflaterStrategy) {
+ this.deflaterStrategy = deflaterStrategy;
+ }
+
+ /**
+ * Writes line, checks that the row number is consistent with that of the
+ * ImageLine See writeRow(int[] newrow, int rown)
+ *
+ * @deprecated Better use writeRow(ImageLine imgline, int rownumber)
+ */
+ public void writeRow(final ImageLine imgline) {
+ writeRow(imgline.scanline, imgline.getRown());
+ }
+
+ /**
+ * Writes line. See writeRow(int[] newrow, int rown)
+ *
+ * The <tt>packed</tt> flag of the imageline is honoured!
+ *
+ * @see #writeRowInt(int[], int)
+ */
+ public void writeRow(final ImageLine imgline, final int rownumber) {
+ unpackedMode = imgline.samplesUnpacked;
+ if (imgline.sampleType == SampleType.INT)
+ writeRowInt(imgline.scanline, rownumber);
+ else
+ writeRowByte(imgline.scanlineb, rownumber);
+ }
+
+ /**
+ * Same as writeRow(int[] newrow, int rown), but does not check row number
+ *
+ * @param newrow
+ */
+ public void writeRow(final int[] newrow) {
+ writeRow(newrow, -1);
+ }
+
+ /**
+ * Alias to writeRowInt
+ *
+ * @see #writeRowInt(int[], int)
+ */
+ public void writeRow(final int[] newrow, final int rown) {
+ writeRowInt(newrow, rown);
+ }
+
+ /**
+ * Writes a full image row.
+ * <p>
+ * This must be called sequentially from n=0 to n=rows-1 One integer per
+ * sample , in the natural order: R G B R G B ... (or R G B A R G B A... if
+ * has alpha) The values should be between 0 and 255 for 8 bitspc images,
+ * and between 0- 65535 form 16 bitspc images (this applies also to the
+ * alpha channel if present) The array can be reused.
+ * <p>
+ * Warning: the array might be modified in some cases (unpacked row with low
+ * bitdepth)
+ * <p>
+ *
+ * @param newrow
+ * Array of pixel values. Warning: the array size should be exact
+ * (samplesPerRowP)
+ * @param rown
+ * Row number, from 0 (top) to rows-1 (bottom). This is just used
+ * as a check. Pass -1 if you want to autocompute it
+ */
+ public void writeRowInt(final int[] newrow, final int rown) {
+ prepareEncodeRow(rown);
+ encodeRowFromInt(newrow);
+ filterAndSend(rown);
+ }
+
+ /**
+ * Same semantics as writeRowInt but using bytes. Each byte is still a
+ * sample. If 16bitdepth, we are passing only the most significant byte (and
+ * hence losing some info)
+ *
+ * @see PngWriter#writeRowInt(int[], int)
+ */
+ public void writeRowByte(final byte[] newrow, final int rown) {
+ prepareEncodeRow(rown);
+ encodeRowFromByte(newrow);
+ filterAndSend(rown);
+ }
+
+ /**
+ * Writes all the pixels, calling writeRowInt() for each image row
+ */
+ public void writeRowsInt(final int[][] image) {
+ for (int i = 0; i < imgInfo.rows; i++)
+ writeRowInt(image[i], i);
+ }
+
+ /**
+ * Writes all the pixels, calling writeRowByte() for each image row
+ */
+ public void writeRowsByte(final byte[][] image) {
+ for (int i = 0; i < imgInfo.rows; i++)
+ writeRowByte(image[i], i);
+ }
+
+ public boolean isUnpackedMode() {
+ return unpackedMode;
+ }
+
+ /**
+ * If false (default), and image has bitdepth 1-2-4, the scanlines passed
+ * are assumed to be already packed.
+ * <p>
+ * If true, each element is a sample, the writer will perform the packing if
+ * necessary.
+ * <p>
+ * Warning: when using {@link #writeRow(ImageLine, int)} (recommended) the
+ * <tt>packed</tt> flag of the ImageLine object overrides (and overwrites!)
+ * this field.
+ */
+ public void setUseUnPackedMode(final boolean useUnpackedMode) {
+ this.unpackedMode = useUnpackedMode;
+ }
+
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngjBadCrcException.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngjBadCrcException.java
index 3b74f862f..032b2ed3a 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngjBadCrcException.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngjBadCrcException.java
@@ -6,15 +6,15 @@ package jogamp.opengl.util.pngj;
public class PngjBadCrcException extends PngjInputException {
private static final long serialVersionUID = 1L;
- public PngjBadCrcException(String message, Throwable cause) {
+ public PngjBadCrcException(final String message, final Throwable cause) {
super(message, cause);
}
- public PngjBadCrcException(String message) {
+ public PngjBadCrcException(final String message) {
super(message);
}
- public PngjBadCrcException(Throwable cause) {
+ public PngjBadCrcException(final Throwable cause) {
super(cause);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngjException.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngjException.java
index 4a45cb5bf..3d05589b1 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngjException.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngjException.java
@@ -2,22 +2,22 @@ package jogamp.opengl.util.pngj;
/**
* Generic exception
- *
+ *
* @author Hernan J Gonzalez
- *
+ *
*/
public class PngjException extends RuntimeException {
private static final long serialVersionUID = 1L;
- public PngjException(String message, Throwable cause) {
+ public PngjException(final String message, final Throwable cause) {
super(message, cause);
}
- public PngjException(String message) {
+ public PngjException(final String message) {
super(message);
}
- public PngjException(Throwable cause) {
+ public PngjException(final Throwable cause) {
super(cause);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java
new file mode 100644
index 000000000..9484abf5e
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java
@@ -0,0 +1,24 @@
+package jogamp.opengl.util.pngj;
+
+/**
+ * Exception for anomalous internal problems (sort of asserts) that point to
+ * some issue with the library
+ *
+ * @author Hernan J Gonzalez
+ *
+ */
+public class PngjExceptionInternal extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public PngjExceptionInternal(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ public PngjExceptionInternal(final String message) {
+ super(message);
+ }
+
+ public PngjExceptionInternal(final Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngjInputException.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngjInputException.java
index 5cc36b99a..c92d80b2c 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngjInputException.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngjInputException.java
@@ -6,15 +6,15 @@ package jogamp.opengl.util.pngj;
public class PngjInputException extends PngjException {
private static final long serialVersionUID = 1L;
- public PngjInputException(String message, Throwable cause) {
+ public PngjInputException(final String message, final Throwable cause) {
super(message, cause);
}
- public PngjInputException(String message) {
+ public PngjInputException(final String message) {
super(message);
}
- public PngjInputException(Throwable cause) {
+ public PngjInputException(final Throwable cause) {
super(cause);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngjOutputException.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngjOutputException.java
index c8cd36acb..4e9cdc950 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngjOutputException.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngjOutputException.java
@@ -6,15 +6,15 @@ package jogamp.opengl.util.pngj;
public class PngjOutputException extends PngjException {
private static final long serialVersionUID = 1L;
- public PngjOutputException(String message, Throwable cause) {
+ public PngjOutputException(final String message, final Throwable cause) {
super(message, cause);
}
- public PngjOutputException(String message) {
+ public PngjOutputException(final String message) {
super(message);
}
- public PngjOutputException(Throwable cause) {
+ public PngjOutputException(final Throwable cause) {
super(cause);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java
index 0801e33bb..e68b153ac 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java
@@ -1,7 +1,8 @@
package jogamp.opengl.util.pngj;
/**
- * Exception thrown because of some valid feature of PNG standard that this library does not support
+ * Exception thrown because of some valid feature of PNG standard that this
+ * library does not support
*/
public class PngjUnsupportedException extends RuntimeException {
private static final long serialVersionUID = 1L;
@@ -10,15 +11,15 @@ public class PngjUnsupportedException extends RuntimeException {
super();
}
- public PngjUnsupportedException(String message, Throwable cause) {
+ public PngjUnsupportedException(final String message, final Throwable cause) {
super(message, cause);
}
- public PngjUnsupportedException(String message) {
+ public PngjUnsupportedException(final String message) {
super(message);
}
- public PngjUnsupportedException(Throwable cause) {
+ public PngjUnsupportedException(final Throwable cause) {
super(cause);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java b/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
index bbec247fb..248472298 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
@@ -4,12 +4,14 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
- * stream that outputs to memory and allows to flush fragments every 'size' bytes to some other destination
+ * stream that outputs to memory and allows to flush fragments every 'size'
+ * bytes to some other destination
*/
abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
private final int size;
+ private long countFlushed = 0;
- public ProgressiveOutputStream(int size) {
+ public ProgressiveOutputStream(final int size) {
this.size = size;
}
@@ -26,19 +28,19 @@ abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
}
@Override
- public final void write(byte[] b, int off, int len) {
+ public final void write(final byte[] b, final int off, final int len) {
super.write(b, off, len);
checkFlushBuffer(false);
}
@Override
- public final void write(byte[] b) throws IOException {
+ public final void write(final byte[] b) throws IOException {
super.write(b);
checkFlushBuffer(false);
}
@Override
- public final void write(int arg0) {
+ public final void write(final int arg0) {
super.write(arg0);
checkFlushBuffer(false);
}
@@ -49,10 +51,10 @@ abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
}
/**
- * if it's time to flush data (or if forced==true) calls abstract method flushBuffer() and cleans those bytes from
- * own buffer
+ * if it's time to flush data (or if forced==true) calls abstract method
+ * flushBuffer() and cleans those bytes from own buffer
*/
- private final void checkFlushBuffer(boolean forced) {
+ private final void checkFlushBuffer(final boolean forced) {
while (forced || count >= size) {
int nb = size;
if (nb > count)
@@ -60,12 +62,17 @@ abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
if (nb == 0)
return;
flushBuffer(buf, nb);
- int bytesleft = count - nb;
+ countFlushed += nb;
+ final int bytesleft = count - nb;
count = bytesleft;
if (bytesleft > 0)
System.arraycopy(buf, nb, buf, 0, bytesleft);
}
}
- public abstract void flushBuffer(byte[] b, int n);
+ protected abstract void flushBuffer(byte[] b, int n);
+
+ public long getCountFlushed() {
+ return countFlushed;
+ }
} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkCopyBehaviour.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkCopyBehaviour.java
index 43c0cb135..a2d976fac 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkCopyBehaviour.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkCopyBehaviour.java
@@ -1,8 +1,9 @@
package jogamp.opengl.util.pngj.chunks;
/**
- * Chunk copy policy to apply when copyng from a pngReader to a pngWriter http://www.w3.org/TR/PNG/#14
+ * Chunk copy policy to apply when copyng from a pngReader to a pngWriter.
* <p>
+ * http://www.w3.org/TR/PNG/#14 <br>
* These are masks, can be OR-ed
**/
public class ChunkCopyBehaviour {
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java
index 26dafd4eb..b8cfd8691 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java
@@ -1,134 +1,299 @@
-package jogamp.opengl.util.pngj.chunks;
-
-// see http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
-// http://www.w3.org/TR/PNG/#5Chunk-naming-conventions
-// http://www.w3.org/TR/PNG/#table53
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Set;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.InflaterInputStream;
-
-import jogamp.opengl.util.pngj.PngHelper;
-import jogamp.opengl.util.pngj.PngjException;
-
-
-public class ChunkHelper {
- public static final String IHDR = "IHDR";
- public static final String PLTE = "PLTE";
- public static final String IDAT = "IDAT";
- public static final String IEND = "IEND";
- public static final byte[] b_IHDR = toBytes(IHDR);
- public static final byte[] b_PLTE = toBytes(PLTE);
- public static final byte[] b_IDAT = toBytes(IDAT);
- public static final byte[] b_IEND = toBytes(IEND);
-
- public static final String cHRM = "cHRM";
- public static final String gAMA = "gAMA";
- public static final String iCCP = "iCCP";
- public static final String sBIT = "sBIT";
- public static final String sRGB = "sRGB";
- public static final String bKGD = "bKGD";
- public static final String hIST = "hIST";
- public static final String tRNS = "tRNS";
- public static final String pHYs = "pHYs";
- public static final String sPLT = "sPLT";
- public static final String tIME = "tIME";
- public static final String iTXt = "iTXt";
- public static final String tEXt = "tEXt";
- public static final String zTXt = "zTXt";
-
- public static Set<String> KNOWN_CHUNKS_CRITICAL = PngHelper.asSet(IHDR, PLTE, IDAT, IEND);
-
- public static byte[] toBytes(String x) {
- return x.getBytes(PngHelper.charsetLatin1);
- }
-
- public static String toString(byte[] x) {
- return new String(x, PngHelper.charsetLatin1);
- }
-
- public static boolean isCritical(String id) { // critical chunk ?
- // first letter is uppercase
- return (Character.isUpperCase(id.charAt(0)));
- }
-
- public static boolean isPublic(String id) { // public chunk?
- // second letter is uppercase
- return (Character.isUpperCase(id.charAt(1)));
- }
-
- /**
- * "Unknown" just means that our chunk factory (even when it has been augmented by client code) did not recognize its id
- */
- public static boolean isUnknown(PngChunk c) {
- return c instanceof PngChunkUNKNOWN;
- }
-
- public static boolean isSafeToCopy(String id) { // safe to copy?
- // fourth letter is lower case
- return (!Character.isUpperCase(id.charAt(3)));
- }
-
- public static int posNullByte(byte[] b) {
- for (int i = 0; i < b.length; i++)
- if (b[i] == 0)
- return i;
- return -1;
- }
-
- public static boolean shouldLoad(String id, ChunkLoadBehaviour behav) {
- if (isCritical(id))
- return true;
- boolean kwown = PngChunk.isKnown(id);
- switch (behav) {
- case LOAD_CHUNK_ALWAYS:
- return true;
- case LOAD_CHUNK_IF_SAFE:
- return kwown || isSafeToCopy(id);
- case LOAD_CHUNK_KNOWN:
- return kwown;
- case LOAD_CHUNK_NEVER:
- return false;
- }
- return false; // should not reach here
- }
-
- public final static byte[] compressBytes(byte[] ori, boolean compress) {
- return compressBytes(ori, 0, ori.length, compress);
- }
-
- public static byte[] compressBytes(byte[] ori, int offset, int len, boolean compress) {
- try {
- ByteArrayInputStream inb = new ByteArrayInputStream(ori, offset, len);
- InputStream in = compress ? inb : new InflaterInputStream(inb);
- ByteArrayOutputStream outb = new ByteArrayOutputStream();
- OutputStream out = compress ? new DeflaterOutputStream(outb) : outb;
- shovelInToOut(in, out);
- in.close();
- out.close();
- return outb.toByteArray();
- } catch (Exception e) {
- throw new PngjException(e);
- }
- }
-
- /**
- * Shovels all data from an input stream to an output stream.
- */
- private static void shovelInToOut(InputStream in, OutputStream out) throws IOException {
- byte[] buffer = new byte[1024];
- int len;
- while ((len = in.read(buffer)) > 0) {
- out.write(buffer, 0, len);
- }
- }
-
- public static boolean maskMatch(int v, int mask) {
- return (v & mask) != 0;
- }
-
-}
+package jogamp.opengl.util.pngj.chunks;
+
+
+// see http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
+// http://www.w3.org/TR/PNG/#5Chunk-naming-conventions
+// http://www.w3.org/TR/PNG/#table53
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
+import jogamp.opengl.util.pngj.PngHelperInternal;
+import jogamp.opengl.util.pngj.PngjException;
+
+
+public class ChunkHelper {
+ public static final String IHDR = "IHDR";
+ public static final String PLTE = "PLTE";
+ public static final String IDAT = "IDAT";
+ public static final String IEND = "IEND";
+ public static final byte[] b_IHDR = toBytes(IHDR);
+ public static final byte[] b_PLTE = toBytes(PLTE);
+ public static final byte[] b_IDAT = toBytes(IDAT);
+ public static final byte[] b_IEND = toBytes(IEND);
+
+ public static final String cHRM = "cHRM";
+ public static final String gAMA = "gAMA";
+ public static final String iCCP = "iCCP";
+ public static final String sBIT = "sBIT";
+ public static final String sRGB = "sRGB";
+ public static final String bKGD = "bKGD";
+ public static final String hIST = "hIST";
+ public static final String tRNS = "tRNS";
+ public static final String pHYs = "pHYs";
+ public static final String sPLT = "sPLT";
+ public static final String tIME = "tIME";
+ public static final String iTXt = "iTXt";
+ public static final String tEXt = "tEXt";
+ public static final String zTXt = "zTXt";
+
+ private static final ThreadLocal<Inflater> inflaterProvider = new ThreadLocal<Inflater>() {
+ @Override
+ protected Inflater initialValue() {
+ return new Inflater();
+ }
+ };
+
+ private static final ThreadLocal<Deflater> deflaterProvider = new ThreadLocal<Deflater>() {
+ @Override
+ protected Deflater initialValue() {
+ return new Deflater();
+ }
+ };
+
+ /*
+ * static auxiliary buffer. any method that uses this should synchronize against this
+ */
+ private static byte[] tmpbuffer = new byte[4096];
+
+ /**
+ * Converts to bytes using Latin1 (ISO-8859-1)
+ */
+ public static byte[] toBytes(final String x) {
+ return x.getBytes(PngHelperInternal.charsetLatin1);
+ }
+
+ /**
+ * Converts to String using Latin1 (ISO-8859-1)
+ */
+ public static String toString(final byte[] x) {
+ return new String(x, PngHelperInternal.charsetLatin1);
+ }
+
+ /**
+ * Converts to String using Latin1 (ISO-8859-1)
+ */
+ public static String toString(final byte[] x, final int offset, final int len) {
+ return new String(x, offset, len, PngHelperInternal.charsetLatin1);
+ }
+
+ /**
+ * Converts to bytes using UTF-8
+ */
+ public static byte[] toBytesUTF8(final String x) {
+ return x.getBytes(PngHelperInternal.charsetUTF8);
+ }
+
+ /**
+ * Converts to string using UTF-8
+ */
+ public static String toStringUTF8(final byte[] x) {
+ return new String(x, PngHelperInternal.charsetUTF8);
+ }
+
+ /**
+ * Converts to string using UTF-8
+ */
+ public static String toStringUTF8(final byte[] x, final int offset, final int len) {
+ return new String(x, offset, len, PngHelperInternal.charsetUTF8);
+ }
+
+ /**
+ * critical chunk : first letter is uppercase
+ */
+ public static boolean isCritical(final String id) {
+ return (Character.isUpperCase(id.charAt(0)));
+ }
+
+ /**
+ * public chunk: second letter is uppercase
+ */
+ public static boolean isPublic(final String id) { //
+ return (Character.isUpperCase(id.charAt(1)));
+ }
+
+ /**
+ * Safe to copy chunk: fourth letter is lower case
+ */
+ public static boolean isSafeToCopy(final String id) {
+ return (!Character.isUpperCase(id.charAt(3)));
+ }
+
+ /**
+ * "Unknown" just means that our chunk factory (even when it has been
+ * augmented by client code) did not recognize its id
+ */
+ public static boolean isUnknown(final PngChunk c) {
+ return c instanceof PngChunkUNKNOWN;
+ }
+
+ /**
+ * Finds position of null byte in array
+ *
+ * @param b
+ * @return -1 if not found
+ */
+ public static int posNullByte(final byte[] b) {
+ for (int i = 0; i < b.length; i++)
+ if (b[i] == 0)
+ return i;
+ return -1;
+ }
+
+ /**
+ * Decides if a chunk should be loaded, according to a ChunkLoadBehaviour
+ *
+ * @param id
+ * @param behav
+ * @return true/false
+ */
+ public static boolean shouldLoad(final String id, final ChunkLoadBehaviour behav) {
+ if (isCritical(id))
+ return true;
+ final boolean kwown = PngChunk.isKnown(id);
+ switch (behav) {
+ case LOAD_CHUNK_ALWAYS:
+ return true;
+ case LOAD_CHUNK_IF_SAFE:
+ return kwown || isSafeToCopy(id);
+ case LOAD_CHUNK_KNOWN:
+ return kwown;
+ case LOAD_CHUNK_NEVER:
+ return false;
+ }
+ return false; // should not reach here
+ }
+
+ public final static byte[] compressBytes(final byte[] ori, final boolean compress) {
+ return compressBytes(ori, 0, ori.length, compress);
+ }
+
+ public static byte[] compressBytes(final byte[] ori, final int offset, final int len, final boolean compress) {
+ try {
+ final ByteArrayInputStream inb = new ByteArrayInputStream(ori, offset, len);
+ final InputStream in = compress ? inb : new InflaterInputStream(inb, getInflater());
+ final ByteArrayOutputStream outb = new ByteArrayOutputStream();
+ final OutputStream out = compress ? new DeflaterOutputStream(outb) : outb;
+ shovelInToOut(in, out);
+ in.close();
+ out.close();
+ return outb.toByteArray();
+ } catch (final Exception e) {
+ throw new PngjException(e);
+ }
+ }
+
+ /**
+ * Shovels all data from an input stream to an output stream.
+ */
+ private static void shovelInToOut(final InputStream in, final OutputStream out) throws IOException {
+ synchronized (tmpbuffer) {
+ int len;
+ while ((len = in.read(tmpbuffer)) > 0) {
+ out.write(tmpbuffer, 0, len);
+ }
+ }
+ }
+
+ public static boolean maskMatch(final int v, final int mask) {
+ return (v & mask) != 0;
+ }
+
+ /**
+ * Returns only the chunks that "match" the predicate
+ *
+ * See also trimList()
+ */
+ public static List<PngChunk> filterList(final List<PngChunk> target, final ChunkPredicate predicateKeep) {
+ final List<PngChunk> result = new ArrayList<PngChunk>();
+ for (final PngChunk element : target) {
+ if (predicateKeep.match(element)) {
+ result.add(element);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Remove (in place) the chunks that "match" the predicate
+ *
+ * See also filterList
+ */
+ public static int trimList(final List<PngChunk> target, final ChunkPredicate predicateRemove) {
+ final Iterator<PngChunk> it = target.iterator();
+ int cont = 0;
+ while (it.hasNext()) {
+ final PngChunk c = it.next();
+ if (predicateRemove.match(c)) {
+ it.remove();
+ cont++;
+ }
+ }
+ return cont;
+ }
+
+ /**
+ * MY adhoc criteria: two chunks are "equivalent" ("practically equal") if
+ * they have same id and (perhaps, if multiple are allowed) if the match
+ * also in some "internal key" (eg: key for string values, palette for sPLT,
+ * etc)
+ *
+ * Notice that the use of this is optional, and that the PNG standard allows
+ * Text chunks that have same key
+ *
+ * @return true if "equivalent"
+ */
+ public static final boolean equivalent(final PngChunk c1, final PngChunk c2) {
+ if (c1 == c2)
+ return true;
+ if (c1 == null || c2 == null || !c1.id.equals(c2.id))
+ return false;
+ // same id
+ if (c1.getClass() != c2.getClass())
+ return false; // should not happen
+ if (!c2.allowsMultiple())
+ return true;
+ if (c1 instanceof PngChunkTextVar) {
+ return ((PngChunkTextVar) c1).getKey().equals(((PngChunkTextVar) c2).getKey());
+ }
+ if (c1 instanceof PngChunkSPLT) {
+ return ((PngChunkSPLT) c1).getPalName().equals(((PngChunkSPLT) c2).getPalName());
+ }
+ // unknown chunks that allow multiple? consider they don't match
+ return false;
+ }
+
+ public static boolean isText(final PngChunk c) {
+ return c instanceof PngChunkTextVar;
+ }
+
+ /**
+ * thread-local inflater, just reset : this should be only used for short
+ * individual chunks compression
+ */
+ public static Inflater getInflater() {
+ final Inflater inflater = inflaterProvider.get();
+ inflater.reset();
+ return inflater;
+ }
+
+ /**
+ * thread-local deflater, just reset : this should be only used for short
+ * individual chunks decompression
+ */
+ public static Deflater getDeflater() {
+ final Deflater deflater = deflaterProvider.get();
+ deflater.reset();
+ return deflater;
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkList.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkList.java
deleted file mode 100644
index badbbd0e8..000000000
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkList.java
+++ /dev/null
@@ -1,282 +0,0 @@
-package jogamp.opengl.util.pngj.chunks;
-
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngjException;
-
-
-/**
- * All chunks that form an image, read or to be written
- *
- * chunks include all chunks, but IDAT is a single pseudo chunk without data
- **/
-public class ChunkList {
- // ref: http://www.w3.org/TR/PNG/#table53
- public static final int CHUNK_GROUP_0_IDHR = 0; // required - single
- public static final int CHUNK_GROUP_1_AFTERIDHR = 1; // optional - multiple
- public static final int CHUNK_GROUP_2_PLTE = 2; // optional - single
- public static final int CHUNK_GROUP_3_AFTERPLTE = 3; // optional - multple
- public static final int CHUNK_GROUP_4_IDAT = 4; // required (single pseudo chunk)
- public static final int CHUNK_GROUP_5_AFTERIDAT = 5; // optional - multple
- public static final int CHUNK_GROUP_6_END = 6; // only 1 chunk - requried
-
- /**
- * All chunks, read, written (does not include IHDR, IDAT, END for written)
- */
- private List<PngChunk> chunks = new ArrayList<PngChunk>();
-
- /**
- * chunks not yet writen - does not include IHDR, IDAT, END, perhaps yes PLTE
- */
- private Set<PngChunk> queuedChunks = new LinkedHashSet<PngChunk>();
-
- final ImageInfo imageInfo; // only required for writing
-
- public ChunkList(ImageInfo imfinfo) {
- this.imageInfo = imfinfo;
- }
-
- /**
- * Adds chunk in next position. This is used when reading
- */
- public void appendReadChunk(PngChunk chunk, int chunkGroup) {
- chunk.setChunkGroup(chunkGroup);
- chunks.add(chunk);
- }
-
- public List<PngChunk> getById(String id, boolean includeQueued, boolean includeProcessed) {
- List<PngChunk> list = new ArrayList<PngChunk>();
- if (includeQueued)
- for (PngChunk c : queuedChunks)
- if (c.id.equals(id))
- list.add(c);
- if (includeProcessed)
- for (PngChunk c : chunks)
- if (c.id.equals(id))
- list.add(c);
- return list;
- }
-
- /**
- * Remove Chunk: only from queued
- */
- public boolean removeChunk(PngChunk c) {
- return queuedChunks.remove(c);
- }
-
- /**
- * add chunk to write queue
- */
- public void queueChunk(PngChunk chunk, boolean replace, boolean priority) {
- chunk.setPriority(priority);
- if (replace) {
- List<PngChunk> current = getById(chunk.id, true, false);
- for (PngChunk chunk2 : current)
- removeChunk(chunk2);
- }
- queuedChunks.add(chunk);
- }
-
- /**
- * this should be called only for ancillary chunks and PLTE (groups 1 - 3 - 5)
- **/
- private static boolean shouldWrite(PngChunk c, int currentGroup) {
- if (currentGroup == CHUNK_GROUP_2_PLTE)
- return c.id.equals(ChunkHelper.PLTE);
- if (currentGroup % 2 == 0)
- throw new RuntimeException("?");
- int minChunkGroup, maxChunkGroup;
- if (c.mustGoBeforePLTE())
- minChunkGroup = maxChunkGroup = ChunkList.CHUNK_GROUP_1_AFTERIDHR;
- else if (c.mustGoBeforeIDAT()) {
- maxChunkGroup = ChunkList.CHUNK_GROUP_3_AFTERPLTE;
- minChunkGroup = c.mustGoAfterPLTE() ? ChunkList.CHUNK_GROUP_3_AFTERPLTE : ChunkList.CHUNK_GROUP_1_AFTERIDHR;
- } else {
- maxChunkGroup = ChunkList.CHUNK_GROUP_5_AFTERIDAT;
- minChunkGroup = ChunkList.CHUNK_GROUP_1_AFTERIDHR;
- }
-
- int preferred = maxChunkGroup;
- if (c.isWritePriority())
- preferred = minChunkGroup;
- if (ChunkHelper.isUnknown(c) && c.getChunkGroup() > 0)
- preferred = c.getChunkGroup();
- if (currentGroup == preferred)
- return true;
- if (currentGroup > preferred && currentGroup <= maxChunkGroup)
- return true;
- return false;
- }
-
- public int writeChunks(OutputStream os, int currentGroup) {
- int cont = 0;
- Iterator<PngChunk> it = queuedChunks.iterator();
- while (it.hasNext()) {
- PngChunk c = it.next();
- if (!shouldWrite(c, currentGroup))
- continue;
- c.write(os);
- chunks.add(c);
- c.setChunkGroup(currentGroup);
- it.remove();
- cont++;
- }
- return cont;
- }
-
- /**
- * returns a copy of processed (read or writen) chunks
- */
- public List<PngChunk> getChunks() {
- return new ArrayList<PngChunk>(chunks);
- }
-
- public List<String> getChunksUnkown() {
- List<String> l = new ArrayList<String>();
- for (PngChunk chunk : chunks)
- if (ChunkHelper.isUnknown(chunk))
- l.add(chunk.id);
- return l;
- }
-
- /**
- * returns a copy of queued (for write) chunks
- */
- public List<PngChunk> getQueuedChunks() {
- return new ArrayList<PngChunk>(queuedChunks);
- }
-
- /**
- * behaviour:
- *
- * a chunk already processed matches : exception a chunk queued matches and overwrite=true: replace it , return true
- * a chunk queued matches and overwrite=false: do nothing, return false no matching: set it, return true
- *
- * @param c
- * @param overwriteIfPresent
- * @return true if added chunk
- */
- public boolean setChunk(PngChunk c, boolean overwriteIfPresent) {
- List<PngChunk> list = getMatching(c, false, true); // processed
- if (!list.isEmpty())
- throw new PngjException("chunk " + c.id + " already set ");
- list = getMatching(c, true, false); // queued
- if (!list.isEmpty()) {
- if (overwriteIfPresent) {
- for (PngChunk cx : list)
- removeChunk(cx);
- queueChunk(c, false, false);
- return true;
- }
- return false;
- }
- queueChunk(c, false, false);
- return true;
- }
-
- /**
- * returns only one chunk or null if nothing found - does not include queued
- *
- * If innerid!=null , the chunk is assumed to be PngChunkTextVar or PngChunkSPLT, and filtered by that id
- *
- * If more than one chunk (after filtering by inner id) is found, then an exception is thrown (failifMultiple=true)
- * or the last one is returned (failifMultiple=false)
- **/
- public PngChunk getChunk1(String id, String innerid, boolean failIfMultiple) {
- List<PngChunk> list = getChunks(id);
- if (list.isEmpty())
- return null;
- if (innerid != null) {
- List<PngChunk> list2 = new ArrayList<PngChunk>();
- for (PngChunk c : list) {
- if (c instanceof PngChunkTextVar)
- if (((PngChunkTextVar) c).getKey().equals(innerid))
- list2.add(c);
- if (c instanceof PngChunkSPLT)
- if (((PngChunkSPLT) c).getPalName().equals(innerid))
- list2.add(c);
- }
- list = list2;
- }
- if (list.isEmpty())
- return null;
- if (list.size() > 1 && failIfMultiple)
- throw new PngjException("unexpected multiple chunks id=" + id);
- return list.get(list.size() - 1);
- }
-
- public PngChunk getChunk1(String id) {
- return getChunk1(id, null, true);
- }
-
- public List<PngChunk> getChunks(String id) { // not including queued
- return getById(id, false, true);
- }
-
- private List<PngChunk> getMatching(PngChunk cnew, boolean includeQueued, boolean includeProcessed) {
- List<PngChunk> list = new ArrayList<PngChunk>();
- if (includeQueued)
- for (PngChunk c : getQueuedChunks())
- if (matches(cnew, c))
- list.add(c);
- if (includeProcessed)
- for (PngChunk c : getChunks())
- if (matches(cnew, c))
- list.add(c);
- return list;
- }
-
- /**
- * MY adhoc criteria: two chunks "match" if they have same id and (perhaps, if multiple are allowed) if the match
- * also in some "internal key" (eg: key for string values, palette for sPLT, etc)
- *
- * @return true if "matches"
- */
- public static boolean matches(PngChunk c2, PngChunk c1) {
- if (c1 == null || c2 == null || !c1.id.equals(c2.id))
- return false;
- // same id
- if (c1.getClass() != c2.getClass())
- return false; // should not happen
- if (!c2.allowsMultiple())
- return true;
- if (c1 instanceof PngChunkTextVar) {
- return ((PngChunkTextVar) c1).getKey().equals(((PngChunkTextVar) c2).getKey());
- }
- if (c1 instanceof PngChunkSPLT) {
- return ((PngChunkSPLT) c1).getPalName().equals(((PngChunkSPLT) c2).getPalName());
- }
- // unknown chunks that allow multiple? consider they don't match
- return false;
- }
-
- public String toString() {
- return "ChunkList: processed: " + chunks.size() + " queue: " + queuedChunks.size();
- }
-
- /**
- * for debugging
- */
- public String toStringFull() {
- StringBuilder sb = new StringBuilder(toString());
- sb.append("\n Processed:\n");
- for (PngChunk chunk : chunks) {
- sb.append(chunk).append(" G=" + chunk.getChunkGroup() + "\n");
- }
- if (!queuedChunks.isEmpty()) {
- sb.append(" Queued:\n");
- for (PngChunk chunk : chunks) {
- sb.append(chunk).append("\n");
- }
-
- }
- return sb.toString();
- }
-
-}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java
index a3f85355c..1fa00380a 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java
@@ -1,10 +1,28 @@
package jogamp.opengl.util.pngj.chunks;
+/**
+ * Defines gral strategy about what to do with ancillary (non-critical) chunks
+ * when reading
+ */
public enum ChunkLoadBehaviour {
- // what to do with non critical chunks when reading?
- LOAD_CHUNK_NEVER, /* ignore non-critical chunks */
- LOAD_CHUNK_KNOWN, /* load chunk if 'known' */
- LOAD_CHUNK_IF_SAFE, /* load chunk if 'known' or safe to copy */
- LOAD_CHUNK_ALWAYS /* load chunk always */
- ;
+ /**
+ * All non-critical chunks are skipped
+ */
+ LOAD_CHUNK_NEVER,
+ /**
+ * Ancillary chunks are loaded only if 'known' (registered with the
+ * factory).
+ */
+ LOAD_CHUNK_KNOWN,
+ /**
+ *
+ * Load chunk if "known" or "safe to copy".
+ */
+ LOAD_CHUNK_IF_SAFE,
+ /**
+ * Load all chunks. <br>
+ * Notice that other restrictions might apply, see
+ * PngReader.skipChunkMaxSize PngReader.skipChunkIds
+ */
+ LOAD_CHUNK_ALWAYS;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkPredicate.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkPredicate.java
new file mode 100644
index 000000000..4695ccf44
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkPredicate.java
@@ -0,0 +1,14 @@
+package jogamp.opengl.util.pngj.chunks;
+
+/**
+ * Decides if another chunk "matches", according to some criterion
+ */
+public interface ChunkPredicate {
+ /**
+ * The other chunk matches with this one
+ *
+ * @param chunk
+ * @return true if match
+ */
+ boolean match(PngChunk chunk);
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
index 6770d5e95..0ac2dc6a0 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
@@ -5,79 +5,112 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.CRC32;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjBadCrcException;
import jogamp.opengl.util.pngj.PngjOutputException;
/**
- * Wraps the raw chunk data Short lived object, to be created while serialing/deserializing Do not reuse it for
- * different chunks
- *
- * see http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
+ * Raw (physical) chunk.
+ * <p>
+ * Short lived object, to be created while serialing/deserializing Do not reuse
+ * it for different chunks. <br>
+ * See http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html
*/
public class ChunkRaw {
+ /**
+ * The length counts only the data field, not itself, the chunk type code,
+ * or the CRC. Zero is a valid length. Although encoders and decoders should
+ * treat the length as unsigned, its value must not exceed 231-1 bytes.
+ */
public final int len;
- public final byte[] idbytes = new byte[4]; // 4 bytes
- public byte[] data = null; // crc not included
+
+ /**
+ * A 4-byte chunk type code. uppercase and lowercase ASCII letters
+ */
+ public final byte[] idbytes = new byte[4];
+
+ /**
+ * The data bytes appropriate to the chunk type, if any. This field can be
+ * of zero length. Does not include crc
+ */
+ public byte[] data = null;
+ /**
+ * A 4-byte CRC (Cyclic Redundancy Check) calculated on the preceding bytes
+ * in the chunk, including the chunk type code and chunk data fields, but
+ * not including the length field.
+ */
private int crcval = 0;
- // public int offset=-1; // only for read chunks - informational
- public ChunkRaw(int len, byte[] idbytes, boolean alloc) {
+ /**
+ * @param len
+ * : data len
+ * @param idbytes
+ * : chunk type (deep copied)
+ * @param alloc
+ * : it true, the data array will be allocced
+ */
+ public ChunkRaw(final int len, final byte[] idbytes, final boolean alloc) {
this.len = len;
System.arraycopy(idbytes, 0, this.idbytes, 0, 4);
if (alloc)
allocData();
}
- public void writeChunk(OutputStream os) {
- if (idbytes.length != 4)
- throw new PngjOutputException("bad chunkid [" + ChunkHelper.toString(idbytes) + "]");
- computeCrc();
- PngHelper.writeInt4(os, len);
- PngHelper.writeBytes(os, idbytes);
- if (len > 0)
- PngHelper.writeBytes(os, data, 0, len);
- // System.err.println("writing chunk " + this.toString() + "crc=" + crcval);
-
- PngHelper.writeInt4(os, crcval);
+ private void allocData() {
+ if (data == null || data.length < len)
+ data = new byte[len];
}
/**
- * called after setting data, before writing to os
+ * this is called after setting data, before writing to os
*/
- private void computeCrc() {
- CRC32 crcengine = PngHelper.getCRC();
+ private int computeCrc() {
+ final CRC32 crcengine = PngHelperInternal.getCRC();
crcengine.reset();
crcengine.update(idbytes, 0, 4);
if (len > 0)
crcengine.update(data, 0, len); //
- crcval = (int) crcengine.getValue();
+ return (int) crcengine.getValue();
}
- public String toString() {
- return "chunkid=" + ChunkHelper.toString(idbytes) + " len=" + len;
+ /**
+ * Computes the CRC and writes to the stream. If error, a
+ * PngjOutputException is thrown
+ */
+ public void writeChunk(final OutputStream os) {
+ if (idbytes.length != 4)
+ throw new PngjOutputException("bad chunkid [" + ChunkHelper.toString(idbytes) + "]");
+ crcval = computeCrc();
+ PngHelperInternal.writeInt4(os, len);
+ PngHelperInternal.writeBytes(os, idbytes);
+ if (len > 0)
+ PngHelperInternal.writeBytes(os, data, 0, len);
+ PngHelperInternal.writeInt4(os, crcval);
}
/**
- * position before: just after chunk id. positon after: after crc Data should be already allocated. Checks CRC
- * Return number of byte read.
+ * position before: just after chunk id. positon after: after crc Data
+ * should be already allocated. Checks CRC Return number of byte read.
*/
- public int readChunkData(InputStream is) {
- PngHelper.readBytes(is, data, 0, len);
- int crcori = PngHelper.readInt4(is);
- computeCrc();
- if (crcori != crcval)
- throw new PngjBadCrcException("crc invalid for chunk " + toString() + " calc=" + crcval + " read=" + crcori);
+ public int readChunkData(final InputStream is, final boolean checkCrc) {
+ PngHelperInternal.readBytes(is, data, 0, len);
+ crcval = PngHelperInternal.readInt4(is);
+ if (checkCrc) {
+ final int crc = computeCrc();
+ if (crc != crcval)
+ throw new PngjBadCrcException("chunk: " + this + " crc calc=" + crc + " read=" + crcval);
+ }
return len + 4;
}
- public ByteArrayInputStream getAsByteStream() { // only the data
+ ByteArrayInputStream getAsByteStream() { // only the data
return new ByteArrayInputStream(data);
}
- private void allocData() {
- if (data == null || data.length < len)
- data = new byte[len];
+ @Override
+ public String toString() {
+ return "chunkid=" + ChunkHelper.toString(idbytes) + " len=" + len;
}
+
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java
new file mode 100644
index 000000000..f5a920e73
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java
@@ -0,0 +1,181 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngjException;
+
+/**
+ * All chunks that form an image, read or to be written.
+ * <p>
+ * chunks include all chunks, but IDAT is a single pseudo chunk without data
+ **/
+public class ChunksList {
+ // ref: http://www.w3.org/TR/PNG/#table53
+ public static final int CHUNK_GROUP_0_IDHR = 0; // required - single
+ public static final int CHUNK_GROUP_1_AFTERIDHR = 1; // optional - multiple
+ public static final int CHUNK_GROUP_2_PLTE = 2; // optional - single
+ public static final int CHUNK_GROUP_3_AFTERPLTE = 3; // optional - multple
+ public static final int CHUNK_GROUP_4_IDAT = 4; // required (single pseudo chunk)
+ public static final int CHUNK_GROUP_5_AFTERIDAT = 5; // optional - multple
+ public static final int CHUNK_GROUP_6_END = 6; // only 1 chunk - requried
+
+ /**
+ * All chunks, read (or written)
+ *
+ * But IDAT is a single pseudo chunk without data
+ */
+ protected List<PngChunk> chunks = new ArrayList<PngChunk>();
+
+ final ImageInfo imageInfo; // only required for writing
+
+ public ChunksList(final ImageInfo imfinfo) {
+ this.imageInfo = imfinfo;
+ }
+
+ /**
+ * Keys of processed (read or writen) chunks
+ *
+ * @return key:chunk id, val: number of occurrences
+ */
+ public HashMap<String, Integer> getChunksKeys() {
+ final HashMap<String, Integer> ck = new HashMap<String, Integer>();
+ for (final PngChunk c : chunks) {
+ ck.put(c.id, ck.containsKey(c.id) ? ck.get(c.id) + 1 : 1);
+ }
+ return ck;
+ }
+
+ /**
+ * Returns a copy of the list (but the chunks are not copied) <b> This
+ * should not be used for general metadata handling
+ */
+ public ArrayList<PngChunk> getChunks() {
+ return new ArrayList<PngChunk>(chunks);
+ }
+
+ protected static List<PngChunk> getXById(final List<PngChunk> list, final String id, final String innerid) {
+ if (innerid == null)
+ return ChunkHelper.filterList(list, new ChunkPredicate() {
+ @Override
+ public boolean match(final PngChunk c) {
+ return c.id.equals(id);
+ }
+ });
+ else
+ return ChunkHelper.filterList(list, new ChunkPredicate() {
+ @Override
+ public boolean match(final PngChunk c) {
+ if (!c.id.equals(id))
+ return false;
+ if (c instanceof PngChunkTextVar && !((PngChunkTextVar) c).getKey().equals(innerid))
+ return false;
+ if (c instanceof PngChunkSPLT && !((PngChunkSPLT) c).getPalName().equals(innerid))
+ return false;
+ return true;
+ }
+ });
+ }
+
+ /**
+ * Adds chunk in next position. This is used onyl by the pngReader
+ */
+ public void appendReadChunk(final PngChunk chunk, final int chunkGroup) {
+ chunk.setChunkGroup(chunkGroup);
+ chunks.add(chunk);
+ }
+
+ /**
+ * All chunks with this ID
+ *
+ * @param id
+ * @return List, empty if none
+ */
+ public List<? extends PngChunk> getById(final String id) {
+ return getById(id, null);
+ }
+
+ /**
+ * If innerid!=null and the chunk is PngChunkTextVar or PngChunkSPLT, it's
+ * filtered by that id
+ *
+ * @param id
+ * @return innerid Only used for text and SPLT chunks
+ * @return List, empty if none
+ */
+ public List<? extends PngChunk> getById(final String id, final String innerid) {
+ return getXById(chunks, id, innerid);
+ }
+
+ /**
+ * Returns only one chunk
+ *
+ * @param id
+ * @return First chunk found, null if not found
+ */
+ public PngChunk getById1(final String id) {
+ return getById1(id, false);
+ }
+
+ /**
+ * Returns only one chunk or null if nothing found - does not include queued
+ * <p>
+ * If more than one chunk is found, then an exception is thrown
+ * (failifMultiple=true or chunk is single) or the last one is returned
+ * (failifMultiple=false)
+ **/
+ public PngChunk getById1(final String id, final boolean failIfMultiple) {
+ return getById1(id, null, failIfMultiple);
+ }
+
+ /**
+ * Returns only one chunk or null if nothing found - does not include queued
+ * <p>
+ * If more than one chunk (after filtering by inner id) is found, then an
+ * exception is thrown (failifMultiple=true or chunk is single) or the last
+ * one is returned (failifMultiple=false)
+ **/
+ public PngChunk getById1(final String id, final String innerid, final boolean failIfMultiple) {
+ final List<? extends PngChunk> list = getById(id, innerid);
+ if (list.isEmpty())
+ return null;
+ if (list.size() > 1 && (failIfMultiple || !list.get(0).allowsMultiple()))
+ throw new PngjException("unexpected multiple chunks id=" + id);
+ return list.get(list.size() - 1);
+ }
+
+ /**
+ * Finds all chunks "equivalent" to this one
+ *
+ * @param c2
+ * @return Empty if nothing found
+ */
+ public List<PngChunk> getEquivalent(final PngChunk c2) {
+ return ChunkHelper.filterList(chunks, new ChunkPredicate() {
+ @Override
+ public boolean match(final PngChunk c) {
+ return ChunkHelper.equivalent(c, c2);
+ }
+ });
+ }
+
+ @Override
+ public String toString() {
+ return "ChunkList: read: " + chunks.size();
+ }
+
+ /**
+ * for debugging
+ */
+ public String toStringFull() {
+ final StringBuilder sb = new StringBuilder(toString());
+ sb.append("\n Read:\n");
+ for (final PngChunk chunk : chunks) {
+ sb.append(chunk).append(" G=" + chunk.getChunkGroup() + "\n");
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java
new file mode 100644
index 000000000..6ad61f8e2
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java
@@ -0,0 +1,176 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngjException;
+import jogamp.opengl.util.pngj.PngjOutputException;
+
+public class ChunksListForWrite extends ChunksList {
+
+ /**
+ * chunks not yet writen - does not include IHDR, IDAT, END, perhaps yes
+ * PLTE
+ */
+ private final List<PngChunk> queuedChunks = new ArrayList<PngChunk>();
+
+ // redundant, just for eficciency
+ private final HashMap<String, Integer> alreadyWrittenKeys = new HashMap<String, Integer>();
+
+ public ChunksListForWrite(final ImageInfo imfinfo) {
+ super(imfinfo);
+ }
+
+ /**
+ * Same as getById(), but looking in the queued chunks
+ */
+ public List<? extends PngChunk> getQueuedById(final String id) {
+ return getQueuedById(id, null);
+ }
+
+ /**
+ * Same as getById(), but looking in the queued chunks
+ */
+ public List<? extends PngChunk> getQueuedById(final String id, final String innerid) {
+ return getXById(queuedChunks, id, innerid);
+ }
+
+ /**
+ * Same as getById1(), but looking in the queued chunks
+ **/
+ public PngChunk getQueuedById1(final String id, final String innerid, final boolean failIfMultiple) {
+ final List<? extends PngChunk> list = getQueuedById(id, innerid);
+ if (list.isEmpty())
+ return null;
+ if (list.size() > 1 && (failIfMultiple || !list.get(0).allowsMultiple()))
+ throw new PngjException("unexpected multiple chunks id=" + id);
+ return list.get(list.size() - 1);
+ }
+
+ /**
+ * Same as getById1(), but looking in the queued chunks
+ **/
+ public PngChunk getQueuedById1(final String id, final boolean failIfMultiple) {
+ return getQueuedById1(id, null, failIfMultiple);
+ }
+
+ /**
+ * Same as getById1(), but looking in the queued chunks
+ **/
+ public PngChunk getQueuedById1(final String id) {
+ return getQueuedById1(id, false);
+ }
+
+ /**
+ * Remove Chunk: only from queued
+ *
+ * WARNING: this depends on c.equals() implementation, which is
+ * straightforward for SingleChunks. For MultipleChunks, it will normally
+ * check for reference equality!
+ */
+ public boolean removeChunk(final PngChunk c) {
+ return queuedChunks.remove(c);
+ }
+
+ /**
+ * Adds chunk to queue
+ *
+ * Does not check for duplicated or anything
+ *
+ * @param c
+ */
+ public boolean queue(final PngChunk c) {
+ queuedChunks.add(c);
+ return true;
+ }
+
+ /**
+ * this should be called only for ancillary chunks and PLTE (groups 1 - 3 -
+ * 5)
+ **/
+ private static boolean shouldWrite(final PngChunk c, final int currentGroup) {
+ if (currentGroup == CHUNK_GROUP_2_PLTE)
+ return c.id.equals(ChunkHelper.PLTE);
+ if (currentGroup % 2 == 0)
+ throw new PngjOutputException("bad chunk group?");
+ int minChunkGroup, maxChunkGroup;
+ if (c.getOrderingConstraint().mustGoBeforePLTE())
+ minChunkGroup = maxChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+ else if (c.getOrderingConstraint().mustGoBeforeIDAT()) {
+ maxChunkGroup = ChunksList.CHUNK_GROUP_3_AFTERPLTE;
+ minChunkGroup = c.getOrderingConstraint().mustGoAfterPLTE() ? ChunksList.CHUNK_GROUP_3_AFTERPLTE
+ : ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+ } else {
+ maxChunkGroup = ChunksList.CHUNK_GROUP_5_AFTERIDAT;
+ minChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+ }
+
+ int preferred = maxChunkGroup;
+ if (c.hasPriority())
+ preferred = minChunkGroup;
+ if (ChunkHelper.isUnknown(c) && c.getChunkGroup() > 0)
+ preferred = c.getChunkGroup();
+ if (currentGroup == preferred)
+ return true;
+ if (currentGroup > preferred && currentGroup <= maxChunkGroup)
+ return true;
+ return false;
+ }
+
+ public int writeChunks(final OutputStream os, final int currentGroup) {
+ int cont = 0;
+ final Iterator<PngChunk> it = queuedChunks.iterator();
+ while (it.hasNext()) {
+ final PngChunk c = it.next();
+ if (!shouldWrite(c, currentGroup))
+ continue;
+ if (ChunkHelper.isCritical(c.id) && !c.id.equals(ChunkHelper.PLTE))
+ throw new PngjOutputException("bad chunk queued: " + c);
+ if (alreadyWrittenKeys.containsKey(c.id) && !c.allowsMultiple())
+ throw new PngjOutputException("duplicated chunk does not allow multiple: " + c);
+ c.write(os);
+ chunks.add(c);
+ alreadyWrittenKeys.put(c.id, alreadyWrittenKeys.containsKey(c.id) ? alreadyWrittenKeys.get(c.id) + 1 : 1);
+ c.setChunkGroup(currentGroup);
+ it.remove();
+ cont++;
+ }
+ return cont;
+ }
+
+ /**
+ * warning: this is NOT a copy, do not modify
+ */
+ public List<PngChunk> getQueuedChunks() {
+ return queuedChunks;
+ }
+
+ @Override
+ public String toString() {
+ return "ChunkList: written: " + chunks.size() + " queue: " + queuedChunks.size();
+ }
+
+ /**
+ * for debugging
+ */
+ @Override
+ public String toStringFull() {
+ final StringBuilder sb = new StringBuilder(toString());
+ sb.append("\n Written:\n");
+ for (final PngChunk chunk : chunks) {
+ sb.append(chunk).append(" G=" + chunk.getChunkGroup() + "\n");
+ }
+ if (!queuedChunks.isEmpty()) {
+ sb.append(" Queued:\n");
+ for (final PngChunk chunk : queuedChunks) {
+ sb.append(chunk).append("\n");
+ }
+
+ }
+ return sb.toString();
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java
index 2df9fd1f3..eba218fe3 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java
@@ -6,26 +6,91 @@ import java.util.HashMap;
import java.util.Map;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngjException;
+import jogamp.opengl.util.pngj.PngjExceptionInternal;
-
-// see http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
+/**
+ * Represents a instance of a PNG chunk.
+ * <p>
+ * See <a
+ * href="http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html">http://www
+ * .libpng.org/pub/png/spec/1.2/PNG-Chunks .html</a> </a>
+ * <p>
+ * Concrete classes should extend {@link PngChunkSingle} or
+ * {@link PngChunkMultiple}
+ * <p>
+ * Note that some methods/fields are type-specific (getOrderingConstraint(),
+ * allowsMultiple()),<br>
+ * some are 'almost' type-specific (id,crit,pub,safe; the exception is
+ * PngUKNOWN), <br>
+ * and the rest are instance-specific
+ */
public abstract class PngChunk {
- public final String id; // 4 letters
+ /**
+ * Chunk-id: 4 letters
+ */
+ public final String id;
+ /**
+ * Autocomputed at creation time
+ */
public final boolean crit, pub, safe;
- private int lenori = -1; // merely informational, for read chunks
- private boolean writePriority = false; // for queued chunks
protected final ImageInfo imgInfo;
- private int chunkGroup = -1; // chunk group where it was read or writen
+ /**
+ * Possible ordering constraint for a PngChunk type -only relevant for
+ * ancillary chunks. Theoretically, there could be more general constraints,
+ * but these cover the constraints for standard chunks.
+ */
+ public enum ChunkOrderingConstraint {
+ /**
+ * no ordering constraint
+ */
+ NONE,
+ /**
+ * Must go before PLTE (and hence, also before IDAT)
+ */
+ BEFORE_PLTE_AND_IDAT,
+ /**
+ * Must go after PLTE but before IDAT
+ */
+ AFTER_PLTE_BEFORE_IDAT,
+ /**
+ * Must before IDAT (before or after PLTE)
+ */
+ BEFORE_IDAT,
+ /**
+ * Does not apply
+ */
+ NA;
+
+ public boolean mustGoBeforePLTE() {
+ return this == BEFORE_PLTE_AND_IDAT;
+ }
+
+ public boolean mustGoBeforeIDAT() {
+ return this == BEFORE_IDAT || this == BEFORE_PLTE_AND_IDAT || this == AFTER_PLTE_BEFORE_IDAT;
+ }
+
+ public boolean mustGoAfterPLTE() {
+ return this == AFTER_PLTE_BEFORE_IDAT;
+ }
+ }
+
+ private boolean priority = false; // For writing. Queued chunks with high priority will be written as soon as
+ // possible
+
+ protected int chunkGroup = -1; // chunk group where it was read or writen
+ protected int length = -1; // merely informational, for read chunks
+ protected long offset = 0; // merely informational, for read chunks
/**
- * This static map defines which PngChunk class correspond to which ChunkID The client can add other chunks to this
- * map statically, before reading
+ * This static map defines which PngChunk class correspond to which ChunkID
+ * <p>
+ * The client can add other chunks to this map statically, before reading an
+ * image, calling PngChunk.factoryRegister(id,class)
*/
- public final static Map<String, Class<? extends PngChunk>> factoryMap = new HashMap<String, Class<? extends PngChunk>>();
+ private final static Map<String, Class<? extends PngChunk>> factoryMap = new HashMap<String, Class<? extends PngChunk>>();
static {
factoryMap.put(ChunkHelper.IDAT, PngChunkIDAT.class);
factoryMap.put(ChunkHelper.IHDR, PngChunkIHDR.class);
@@ -45,9 +110,38 @@ public abstract class PngChunk {
factoryMap.put(ChunkHelper.sRGB, PngChunkSRGB.class);
factoryMap.put(ChunkHelper.hIST, PngChunkHIST.class);
factoryMap.put(ChunkHelper.sPLT, PngChunkSPLT.class);
+ // extended
+ factoryMap.put(PngChunkOFFS.ID, PngChunkOFFS.class);
+ factoryMap.put(PngChunkSTER.ID, PngChunkSTER.class);
+ }
+
+ /**
+ * Registers a chunk-id (4 letters) to be associated with a PngChunk class
+ * <p>
+ * This method should be called by user code that wants to add some chunks
+ * (not implmemented in this library) to the factory, so that the PngReader
+ * knows about it.
+ */
+ public static void factoryRegister(final String chunkId, final Class<? extends PngChunk> chunkClass) {
+ factoryMap.put(chunkId, chunkClass);
}
- protected PngChunk(String id, ImageInfo imgInfo) {
+ /**
+ * True if the chunk-id type is known.
+ * <p>
+ * A chunk is known if we recognize its class, according with
+ * <code>factoryMap</code>
+ * <p>
+ * This is not necessarily the same as being "STANDARD", or being
+ * implemented in this library
+ * <p>
+ * Unknown chunks will be parsed as instances of {@link PngChunkUNKNOWN}
+ */
+ public static boolean isKnown(final String id) {
+ return factoryMap.containsKey(id);
+ }
+
+ protected PngChunk(final String id, final ImageInfo imgInfo) {
this.id = id;
this.imgInfo = imgInfo;
this.crit = ChunkHelper.isCritical(id);
@@ -55,98 +149,136 @@ public abstract class PngChunk {
this.safe = ChunkHelper.isSafeToCopy(id);
}
- public abstract ChunkRaw createChunk();
-
- public abstract void parseFromChunk(ChunkRaw c);
-
- // override to make deep copy from read data to write
- public abstract void cloneDataFromRead(PngChunk other);
-
- @SuppressWarnings("unchecked")
- public static <T extends PngChunk> T cloneChunk(T chunk, ImageInfo info) {
- PngChunk cn = factoryFromId(chunk.id, info);
- if (cn.getClass() != chunk.getClass())
- throw new PngjException("bad class cloning chunk: " + cn.getClass() + " " + chunk.getClass());
- cn.cloneDataFromRead(chunk);
- return (T) cn;
- }
-
- public static PngChunk factory(ChunkRaw chunk, ImageInfo info) {
- PngChunk c = factoryFromId(ChunkHelper.toString(chunk.idbytes), info);
- c.lenori = chunk.len;
- c.parseFromChunk(chunk);
+ /**
+ * This factory creates the corresponding chunk and parses the raw chunk.
+ * This is used when reading.
+ */
+ public static PngChunk factory(final ChunkRaw chunk, final ImageInfo info) {
+ final PngChunk c = factoryFromId(ChunkHelper.toString(chunk.idbytes), info);
+ c.length = chunk.len;
+ c.parseFromRaw(chunk);
return c;
}
- public static PngChunk factoryFromId(String cid, ImageInfo info) {
+ /**
+ * Creates one new blank chunk of the corresponding type, according to
+ * factoryMap (PngChunkUNKNOWN if not known)
+ */
+ public static PngChunk factoryFromId(final String cid, final ImageInfo info) {
PngChunk chunk = null;
try {
- Class<? extends PngChunk> cla = factoryMap.get(cid);
+ final Class<? extends PngChunk> cla = factoryMap.get(cid);
if (cla != null) {
- Constructor<? extends PngChunk> constr = cla.getConstructor(ImageInfo.class);
+ final Constructor<? extends PngChunk> constr = cla.getConstructor(ImageInfo.class);
chunk = constr.newInstance(info);
}
- } catch (Exception e) {
- // this can happend for unkown chunks
+ } catch (final Exception e) {
+ // this can happen for unkown chunks
}
if (chunk == null)
chunk = new PngChunkUNKNOWN(cid, info);
return chunk;
}
- protected ChunkRaw createEmptyChunk(int len, boolean alloc) {
- ChunkRaw c = new ChunkRaw(len, ChunkHelper.toBytes(id), alloc);
+ protected final ChunkRaw createEmptyChunk(final int len, final boolean alloc) {
+ final ChunkRaw c = new ChunkRaw(len, ChunkHelper.toBytes(id), alloc);
return c;
}
- @Override
- public String toString() {
- return "chunk id= " + id + " (" + lenori + ") c=" + getClass().getSimpleName();
+ /**
+ * Makes a clone (deep copy) calling {@link #cloneDataFromRead(PngChunk)}
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends PngChunk> T cloneChunk(final T chunk, final ImageInfo info) {
+ final PngChunk cn = factoryFromId(chunk.id, info);
+ if (cn.getClass() != chunk.getClass())
+ throw new PngjExceptionInternal("bad class cloning chunk: " + cn.getClass() + " " + chunk.getClass());
+ cn.cloneDataFromRead(chunk);
+ return (T) cn;
}
- void setPriority(boolean highPrioriy) {
- writePriority = highPrioriy;
+ /**
+ * In which "chunkGroup" (see {@link ChunksList}for definition) this chunks
+ * instance was read or written.
+ * <p>
+ * -1 if not read or written (eg, queued)
+ */
+ final public int getChunkGroup() {
+ return chunkGroup;
}
- void write(OutputStream os) {
- ChunkRaw c = createChunk();
- if (c == null)
- throw new PngjException("null chunk ! creation failed for " + this);
- c.writeChunk(os);
+ /**
+ * @see #getChunkGroup()
+ */
+ final public void setChunkGroup(final int chunkGroup) {
+ this.chunkGroup = chunkGroup;
}
- public boolean isWritePriority() {
- return writePriority;
+ public boolean hasPriority() {
+ return priority;
}
- /** must be overriden - only relevant for ancillary chunks */
- public boolean allowsMultiple() {
- return false; // override if allows multiple ocurrences
+ public void setPriority(final boolean priority) {
+ this.priority = priority;
}
- /** mustGoBeforeXX/After must be overriden - only relevant for ancillary chunks */
- public boolean mustGoBeforeIDAT() {
- return false;
+ final void write(final OutputStream os) {
+ final ChunkRaw c = createRawChunk();
+ if (c == null)
+ throw new PngjExceptionInternal("null chunk ! creation failed for " + this);
+ c.writeChunk(os);
}
- public boolean mustGoBeforePLTE() {
- return false;
+ public int getLength() {
+ return length;
}
- public boolean mustGoAfterPLTE() {
- return false;
- }
+ /*
+ * public void setLength(int length) { this.length = length; }
+ */
- static boolean isKnown(String id) {
- return factoryMap.containsKey(id);
+ public long getOffset() {
+ return offset;
}
- public int getChunkGroup() {
- return chunkGroup;
+ public void setOffset(final long offset) {
+ this.offset = offset;
}
- public void setChunkGroup(int chunkGroup) {
- this.chunkGroup = chunkGroup;
+ /**
+ * Creates the physical chunk. This is used when writing (serialization).
+ * Each particular chunk class implements its own logic.
+ *
+ * @return A newly allocated and filled raw chunk
+ */
+ public abstract ChunkRaw createRawChunk();
+
+ /**
+ * Parses raw chunk and fill inside data. This is used when reading
+ * (deserialization). Each particular chunk class implements its own logic.
+ */
+ public abstract void parseFromRaw(ChunkRaw c);
+
+ /**
+ * Makes a copy of the chunk.
+ * <p>
+ * This is used when copying chunks from a reader to a writer
+ * <p>
+ * It should normally be a deep copy, and after the cloning
+ * this.equals(other) should return true
+ */
+ public abstract void cloneDataFromRead(PngChunk other);
+
+ public abstract boolean allowsMultiple(); // this is implemented in PngChunkMultiple/PngChunSingle
+
+ /**
+ * see {@link ChunkOrderingConstraint}
+ */
+ public abstract ChunkOrderingConstraint getOrderingConstraint();
+
+ @Override
+ public String toString() {
+ return "chunk id= " + id + " (len=" + length + " offset=" + offset + ") c=" + getClass().getSimpleName();
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java
index 51bbcb832..191278dbc 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java
@@ -1,67 +1,66 @@
package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
-/*
+/**
+ * bKGD Chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11bKGD
+ * <p>
+ * this chunk structure depends on the image type
*/
-public class PngChunkBKGD extends PngChunk {
- // http://www.w3.org/TR/PNG/#11bKGD
- // this chunk structure depends on the image type
+public class PngChunkBKGD extends PngChunkSingle {
+ public final static String ID = ChunkHelper.bKGD;
// only one of these is meaningful
private int gray;
private int red, green, blue;
private int paletteIndex;
- public PngChunkBKGD(ImageInfo info) {
+ public PngChunkBKGD(final ImageInfo info) {
super(ChunkHelper.bKGD, info);
}
@Override
- public boolean mustGoBeforeIDAT() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;
}
@Override
- public boolean mustGoAfterPLTE() {
- return true;
- }
-
- @Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
ChunkRaw c = null;
if (imgInfo.greyscale) {
c = createEmptyChunk(2, true);
- PngHelper.writeInt2tobytes(gray, c.data, 0);
+ PngHelperInternal.writeInt2tobytes(gray, c.data, 0);
} else if (imgInfo.indexed) {
c = createEmptyChunk(1, true);
c.data[0] = (byte) paletteIndex;
} else {
c = createEmptyChunk(6, true);
- PngHelper.writeInt2tobytes(red, c.data, 0);
- PngHelper.writeInt2tobytes(green, c.data, 0);
- PngHelper.writeInt2tobytes(blue, c.data, 0);
+ PngHelperInternal.writeInt2tobytes(red, c.data, 0);
+ PngHelperInternal.writeInt2tobytes(green, c.data, 0);
+ PngHelperInternal.writeInt2tobytes(blue, c.data, 0);
}
return c;
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
if (imgInfo.greyscale) {
- gray = PngHelper.readInt2fromBytes(c.data, 0);
+ gray = PngHelperInternal.readInt2fromBytes(c.data, 0);
} else if (imgInfo.indexed) {
- paletteIndex = (int) (c.data[0] & 0xff);
+ paletteIndex = c.data[0] & 0xff;
} else {
- red = PngHelper.readInt2fromBytes(c.data, 0);
- green = PngHelper.readInt2fromBytes(c.data, 2);
- blue = PngHelper.readInt2fromBytes(c.data, 4);
+ red = PngHelperInternal.readInt2fromBytes(c.data, 0);
+ green = PngHelperInternal.readInt2fromBytes(c.data, 2);
+ blue = PngHelperInternal.readInt2fromBytes(c.data, 4);
}
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkBKGD otherx = (PngChunkBKGD) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkBKGD otherx = (PngChunkBKGD) other;
gray = otherx.gray;
red = otherx.red;
green = otherx.red;
@@ -71,10 +70,10 @@ public class PngChunkBKGD extends PngChunk {
/**
* Set gray value (0-255 if bitdept=8)
- *
+ *
* @param gray
*/
- public void setGray(int gray) {
+ public void setGray(final int gray) {
if (!imgInfo.greyscale)
throw new PngjException("only gray images support this");
this.gray = gray;
@@ -88,9 +87,9 @@ public class PngChunkBKGD extends PngChunk {
/**
* Set pallette index
- *
+ *
*/
- public void setPaletteIndex(int i) {
+ public void setPaletteIndex(final int i) {
if (!imgInfo.indexed)
throw new PngjException("only indexed (pallete) images support this");
this.paletteIndex = i;
@@ -104,9 +103,9 @@ public class PngChunkBKGD extends PngChunk {
/**
* Set rgb values
- *
+ *
*/
- public void setRGB(int r, int g, int b) {
+ public void setRGB(final int r, final int g, final int b) {
if (imgInfo.greyscale || imgInfo.indexed)
throw new PngjException("only rgb or rgba images support this");
red = r;
@@ -119,4 +118,5 @@ public class PngChunkBKGD extends PngChunk {
throw new PngjException("only rgb or rgba images support this");
return new int[] { red, green, blue };
}
+
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java
index 4380761c7..8bdd7b4c0 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java
@@ -1,64 +1,64 @@
package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
-/*
+/**
+ * cHRM chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11cHRM
*/
-public class PngChunkCHRM extends PngChunk {
+public class PngChunkCHRM extends PngChunkSingle {
+ public final static String ID = ChunkHelper.cHRM;
+
// http://www.w3.org/TR/PNG/#11cHRM
private double whitex, whitey;
private double redx, redy;
private double greenx, greeny;
private double bluex, bluey;
- public PngChunkCHRM(ImageInfo info) {
- super(ChunkHelper.cHRM, info);
- }
-
- @Override
- public boolean mustGoBeforeIDAT() {
- return true;
+ public PngChunkCHRM(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public boolean mustGoBeforePLTE() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
ChunkRaw c = null;
c = createEmptyChunk(32, true);
- PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(whitex), c.data, 0);
- PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(whitey), c.data, 4);
- PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(redx), c.data, 8);
- PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(redy), c.data, 12);
- PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(greenx), c.data, 16);
- PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(greeny), c.data, 20);
- PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(bluex), c.data, 24);
- PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(bluey), c.data, 28);
+ PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(whitex), c.data, 0);
+ PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(whitey), c.data, 4);
+ PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(redx), c.data, 8);
+ PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(redy), c.data, 12);
+ PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(greenx), c.data, 16);
+ PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(greeny), c.data, 20);
+ PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(bluex), c.data, 24);
+ PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(bluey), c.data, 28);
return c;
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
if (c.len != 32)
throw new PngjException("bad chunk " + c);
- whitex = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 0));
- whitey = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 4));
- redx = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 8));
- redy = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 12));
- greenx = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 16));
- greeny = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 20));
- bluex = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 24));
- bluey = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 28));
+ whitex = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 0));
+ whitey = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 4));
+ redx = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 8));
+ redy = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 12));
+ greenx = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 16));
+ greeny = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 20));
+ bluex = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 24));
+ bluey = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 28));
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkCHRM otherx = (PngChunkCHRM) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkCHRM otherx = (PngChunkCHRM) other;
whitex = otherx.whitex;
whitey = otherx.whitex;
redx = otherx.redx;
@@ -69,8 +69,8 @@ public class PngChunkCHRM extends PngChunk {
bluey = otherx.bluey;
}
- public void setChromaticities(double whitex, double whitey, double redx, double redy, double greenx, double greeny,
- double bluex, double bluey) {
+ public void setChromaticities(final double whitex, final double whitey, final double redx, final double redy, final double greenx, final double greeny,
+ final double bluex, final double bluey) {
this.whitex = whitex;
this.redx = redx;
this.greenx = greenx;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java
index 184ee9ffa..6b627326c 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java
@@ -1,47 +1,47 @@
package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
-/*
+/**
+ * gAMA chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11gAMA
*/
-public class PngChunkGAMA extends PngChunk {
+public class PngChunkGAMA extends PngChunkSingle {
+ public final static String ID = ChunkHelper.gAMA;
+
// http://www.w3.org/TR/PNG/#11gAMA
private double gamma;
- public PngChunkGAMA(ImageInfo info) {
- super(ChunkHelper.gAMA, info);
- }
-
- @Override
- public boolean mustGoBeforeIDAT() {
- return true;
+ public PngChunkGAMA(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public boolean mustGoBeforePLTE() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT;
}
@Override
- public ChunkRaw createChunk() {
- ChunkRaw c = createEmptyChunk(4, true);
- int g = (int) (gamma * 100000 + 0.5);
- PngHelper.writeInt4tobytes(g, c.data, 0);
+ public ChunkRaw createRawChunk() {
+ final ChunkRaw c = createEmptyChunk(4, true);
+ final int g = (int) (gamma * 100000 + 0.5);
+ PngHelperInternal.writeInt4tobytes(g, c.data, 0);
return c;
}
@Override
- public void parseFromChunk(ChunkRaw chunk) {
+ public void parseFromRaw(final ChunkRaw chunk) {
if (chunk.len != 4)
throw new PngjException("bad chunk " + chunk);
- int g = PngHelper.readInt4fromBytes(chunk.data, 0);
- gamma = ((double) g) / 100000.0;
+ final int g = PngHelperInternal.readInt4fromBytes(chunk.data, 0);
+ gamma = (g) / 100000.0;
}
@Override
- public void cloneDataFromRead(PngChunk other) {
+ public void cloneDataFromRead(final PngChunk other) {
gamma = ((PngChunkGAMA) other).gamma;
}
@@ -49,7 +49,7 @@ public class PngChunkGAMA extends PngChunk {
return gamma;
}
- public void setGamma(double gamma) {
+ public void setGamma(final double gamma) {
this.gamma = gamma;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java
index b0f02ea37..4a4832d3b 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java
@@ -1,57 +1,55 @@
package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
-/*
+/**
+ * hIST chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11hIST <br>
+ * only for palette images
*/
-public class PngChunkHIST extends PngChunk {
- // http://www.w3.org/TR/PNG/#11hIST
- // only for palette images
+public class PngChunkHIST extends PngChunkSingle {
+ public final static String ID = ChunkHelper.hIST;
private int[] hist = new int[0]; // should have same lenght as palette
- public PngChunkHIST(ImageInfo info) {
- super(ChunkHelper.hIST, info);
+ public PngChunkHIST(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public boolean mustGoBeforeIDAT() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;
}
@Override
- public boolean mustGoAfterPLTE() {
- return true;
- }
-
- @Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
if (!imgInfo.indexed)
throw new PngjException("only indexed images accept a HIST chunk");
- int nentries = c.data.length / 2;
+ final int nentries = c.data.length / 2;
hist = new int[nentries];
for (int i = 0; i < hist.length; i++) {
- hist[i] = PngHelper.readInt2fromBytes(c.data, i * 2);
+ hist[i] = PngHelperInternal.readInt2fromBytes(c.data, i * 2);
}
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
if (!imgInfo.indexed)
throw new PngjException("only indexed images accept a HIST chunk");
ChunkRaw c = null;
c = createEmptyChunk(hist.length * 2, true);
for (int i = 0; i < hist.length; i++) {
- PngHelper.writeInt2tobytes(hist[i], c.data, i * 2);
+ PngHelperInternal.writeInt2tobytes(hist[i], c.data, i * 2);
}
return c;
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkHIST otherx = (PngChunkHIST) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkHIST otherx = (PngChunkHIST) other;
hist = new int[otherx.hist.length];
System.arraycopy(otherx.hist, 0, hist, 0, otherx.hist.length);
}
@@ -60,7 +58,7 @@ public class PngChunkHIST extends PngChunk {
return hist;
}
- public void setHist(int[] hist) {
+ public void setHist(final int[] hist) {
this.hist = hist;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java
index db1c1ba64..17f69861c 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java
@@ -1,32 +1,33 @@
package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
+import jogamp.opengl.util.pngj.PngjException;
-/*
+/**
+ * iCCP chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11iCCP
*/
-public class PngChunkICCP extends PngChunk {
+public class PngChunkICCP extends PngChunkSingle {
+ public final static String ID = ChunkHelper.iCCP;
+
// http://www.w3.org/TR/PNG/#11iCCP
private String profileName;
private byte[] compressedProfile; // copmression/decopmresion is done in getter/setter
- public PngChunkICCP(ImageInfo info) {
- super(ChunkHelper.iCCP, info);
- }
-
- @Override
- public boolean mustGoBeforeIDAT() {
- return true;
+ public PngChunkICCP(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public boolean mustGoBeforePLTE() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT;
}
@Override
- public ChunkRaw createChunk() {
- ChunkRaw c = createEmptyChunk(profileName.length() + compressedProfile.length + 2, true);
+ public ChunkRaw createRawChunk() {
+ final ChunkRaw c = createEmptyChunk(profileName.length() + compressedProfile.length + 2, true);
System.arraycopy(ChunkHelper.toBytes(profileName), 0, c.data, 0, profileName.length());
c.data[profileName.length()] = 0;
c.data[profileName.length() + 1] = 0;
@@ -35,20 +36,20 @@ public class PngChunkICCP extends PngChunk {
}
@Override
- public void parseFromChunk(ChunkRaw chunk) {
- int pos0 = ChunkHelper.posNullByte(chunk.data);
- profileName = new String(chunk.data, 0, pos0, PngHelper.charsetLatin1);
- int comp = (chunk.data[pos0 + 1] & 0xff);
+ public void parseFromRaw(final ChunkRaw chunk) {
+ final int pos0 = ChunkHelper.posNullByte(chunk.data);
+ profileName = new String(chunk.data, 0, pos0, PngHelperInternal.charsetLatin1);
+ final int comp = (chunk.data[pos0 + 1] & 0xff);
if (comp != 0)
- throw new RuntimeException("bad compression for ChunkTypeICCP");
- int compdatasize = chunk.data.length - (pos0 + 2);
+ throw new PngjException("bad compression for ChunkTypeICCP");
+ final int compdatasize = chunk.data.length - (pos0 + 2);
compressedProfile = new byte[compdatasize];
System.arraycopy(chunk.data, pos0 + 2, compressedProfile, 0, compdatasize);
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkICCP otherx = (PngChunkICCP) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkICCP otherx = (PngChunkICCP) other;
profileName = otherx.profileName;
compressedProfile = new byte[otherx.compressedProfile.length];
System.arraycopy(otherx.compressedProfile, 0, compressedProfile, 0, otherx.compressedProfile.length); // deep
@@ -58,13 +59,13 @@ public class PngChunkICCP extends PngChunk {
/**
* The profile should be uncompressed bytes
*/
- public void setProfileNameAndContent(String name, byte[] profile) {
+ public void setProfileNameAndContent(final String name, final byte[] profile) {
profileName = name;
compressedProfile = ChunkHelper.compressBytes(profile, true);
}
- public void setProfileNameAndContent(String name, String profile) {
- setProfileNameAndContent(name, profile.getBytes(PngHelper.charsetLatin1));
+ public void setProfileNameAndContent(final String name, final String profile) {
+ setProfileNameAndContent(name, profile.getBytes(PngHelperInternal.charsetLatin1));
}
public String getProfileName() {
@@ -79,7 +80,7 @@ public class PngChunkICCP extends PngChunk {
}
public String getProfileAsString() {
- return new String(getProfile(), PngHelper.charsetLatin1);
+ return new String(getProfile(), PngHelperInternal.charsetLatin1);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
index a7cb95dbf..f7bee4b11 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
@@ -2,24 +2,39 @@ package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-public class PngChunkIDAT extends PngChunk {
+/**
+ * IDAT chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11IDAT
+ * <p>
+ * This is dummy placeholder - we write/read this chunk (actually several) by
+ * special code.
+ */
+public class PngChunkIDAT extends PngChunkMultiple {
+ public final static String ID = ChunkHelper.IDAT;
+
// http://www.w3.org/TR/PNG/#11IDAT
- // This is dummy placeholder - we write/read this chunk (actually several)
- // by special code.
- public PngChunkIDAT(ImageInfo i) {
- super(ChunkHelper.IDAT, i);
+ public PngChunkIDAT(final ImageInfo i, final int len, final long offset) {
+ super(ID, i);
+ this.length = len;
+ this.offset = offset;
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NA;
}
@Override
- public ChunkRaw createChunk() {// does nothing
+ public ChunkRaw createRawChunk() {// does nothing
return null;
}
@Override
- public void parseFromChunk(ChunkRaw c) { // does nothing
+ public void parseFromRaw(final ChunkRaw c) { // does nothing
}
@Override
- public void cloneDataFromRead(PngChunk other) {
+ public void cloneDataFromRead(final PngChunk other) {
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java
index 0d5b266da..3f6e47b09 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java
@@ -2,25 +2,37 @@ package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-public class PngChunkIEND extends PngChunk {
+/**
+ * IEND chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11IEND
+ */
+public class PngChunkIEND extends PngChunkSingle {
+ public final static String ID = ChunkHelper.IEND;
+
// http://www.w3.org/TR/PNG/#11IEND
// this is a dummy placeholder
- public PngChunkIEND(ImageInfo info) {
- super(ChunkHelper.IEND, info);
+ public PngChunkIEND(final ImageInfo info) {
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NA;
}
@Override
- public ChunkRaw createChunk() {
- ChunkRaw c = new ChunkRaw(0, ChunkHelper.b_IEND, false);
+ public ChunkRaw createRawChunk() {
+ final ChunkRaw c = new ChunkRaw(0, ChunkHelper.b_IEND, false);
return c;
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
// this is not used
}
@Override
- public void cloneDataFromRead(PngChunk other) {
+ public void cloneDataFromRead(final PngChunk other) {
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIHDR.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIHDR.java
index fcb4150ff..71e0ec90e 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIHDR.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIHDR.java
@@ -3,14 +3,20 @@ package jogamp.opengl.util.pngj.chunks;
import java.io.ByteArrayInputStream;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
/**
- * this is a special chunk!
+ * IHDR chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11IHDR
+ * <p>
+ * This is a special critical Chunk.
*/
-public class PngChunkIHDR extends PngChunk {
+public class PngChunkIHDR extends PngChunkSingle {
+ public final static String ID = ChunkHelper.IHDR;
+
private int cols;
private int rows;
private int bitspc;
@@ -21,17 +27,22 @@ public class PngChunkIHDR extends PngChunk {
// http://www.w3.org/TR/PNG/#11IHDR
//
- public PngChunkIHDR(ImageInfo info) {
- super(ChunkHelper.IHDR, info);
+ public PngChunkIHDR(final ImageInfo info) {
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NA;
}
@Override
- public ChunkRaw createChunk() {
- ChunkRaw c = new ChunkRaw(13, ChunkHelper.b_IHDR, true);
+ public ChunkRaw createRawChunk() {
+ final ChunkRaw c = new ChunkRaw(13, ChunkHelper.b_IHDR, true);
int offset = 0;
- PngHelper.writeInt4tobytes(cols, c.data, offset);
+ PngHelperInternal.writeInt4tobytes(cols, c.data, offset);
offset += 4;
- PngHelper.writeInt4tobytes(rows, c.data, offset);
+ PngHelperInternal.writeInt4tobytes(rows, c.data, offset);
offset += 4;
c.data[offset++] = (byte) bitspc;
c.data[offset++] = (byte) colormodel;
@@ -42,23 +53,23 @@ public class PngChunkIHDR extends PngChunk {
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
if (c.len != 13)
throw new PngjException("Bad IDHR len " + c.len);
- ByteArrayInputStream st = c.getAsByteStream();
- cols = PngHelper.readInt4(st);
- rows = PngHelper.readInt4(st);
+ final ByteArrayInputStream st = c.getAsByteStream();
+ cols = PngHelperInternal.readInt4(st);
+ rows = PngHelperInternal.readInt4(st);
// bit depth: number of bits per channel
- bitspc = PngHelper.readByte(st);
- colormodel = PngHelper.readByte(st);
- compmeth = PngHelper.readByte(st);
- filmeth = PngHelper.readByte(st);
- interlaced = PngHelper.readByte(st);
+ bitspc = PngHelperInternal.readByte(st);
+ colormodel = PngHelperInternal.readByte(st);
+ compmeth = PngHelperInternal.readByte(st);
+ filmeth = PngHelperInternal.readByte(st);
+ interlaced = PngHelperInternal.readByte(st);
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkIHDR otherx = (PngChunkIHDR) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkIHDR otherx = (PngChunkIHDR) other;
cols = otherx.cols;
rows = otherx.rows;
bitspc = otherx.bitspc;
@@ -72,7 +83,7 @@ public class PngChunkIHDR extends PngChunk {
return cols;
}
- public void setCols(int cols) {
+ public void setCols(final int cols) {
this.cols = cols;
}
@@ -80,7 +91,7 @@ public class PngChunkIHDR extends PngChunk {
return rows;
}
- public void setRows(int rows) {
+ public void setRows(final int rows) {
this.rows = rows;
}
@@ -88,7 +99,7 @@ public class PngChunkIHDR extends PngChunk {
return bitspc;
}
- public void setBitspc(int bitspc) {
+ public void setBitspc(final int bitspc) {
this.bitspc = bitspc;
}
@@ -96,7 +107,7 @@ public class PngChunkIHDR extends PngChunk {
return colormodel;
}
- public void setColormodel(int colormodel) {
+ public void setColormodel(final int colormodel) {
this.colormodel = colormodel;
}
@@ -104,7 +115,7 @@ public class PngChunkIHDR extends PngChunk {
return compmeth;
}
- public void setCompmeth(int compmeth) {
+ public void setCompmeth(final int compmeth) {
this.compmeth = compmeth;
}
@@ -112,7 +123,7 @@ public class PngChunkIHDR extends PngChunk {
return filmeth;
}
- public void setFilmeth(int filmeth) {
+ public void setFilmeth(final int filmeth) {
this.filmeth = filmeth;
}
@@ -120,7 +131,7 @@ public class PngChunkIHDR extends PngChunk {
return interlaced;
}
- public void setInterlaced(int interlaced) {
+ public void setInterlaced(final int interlaced) {
this.interlaced = interlaced;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java
index 4e5c7c74a..738f92471 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java
@@ -4,56 +4,59 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
/**
- * UNTESTED!
+ * iTXt chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11iTXt
*/
public class PngChunkITXT extends PngChunkTextVar {
+ public final static String ID = ChunkHelper.iTXt;
private boolean compressed = false;
private String langTag = "";
private String translatedTag = "";
// http://www.w3.org/TR/PNG/#11iTXt
- public PngChunkITXT(ImageInfo info) {
- super(ChunkHelper.iTXt, info);
+ public PngChunkITXT(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public ChunkRaw createChunk() {
- if (val.isEmpty() || key.isEmpty())
- return null;
+ public ChunkRaw createRawChunk() {
+ if (key.isEmpty())
+ throw new PngjException("Text chunk key must be non empty");
try {
- ByteArrayOutputStream ba = new ByteArrayOutputStream();
- ba.write(key.getBytes(PngHelper.charsetLatin1));
+ final ByteArrayOutputStream ba = new ByteArrayOutputStream();
+ ba.write(ChunkHelper.toBytes(key));
ba.write(0); // separator
ba.write(compressed ? 1 : 0);
ba.write(0); // compression method (always 0)
- ba.write(langTag.getBytes(PngHelper.charsetUTF8));
+ ba.write(ChunkHelper.toBytes(langTag));
ba.write(0); // separator
- ba.write(translatedTag.getBytes(PngHelper.charsetUTF8));
+ ba.write(ChunkHelper.toBytesUTF8(translatedTag));
ba.write(0); // separator
- byte[] textbytes = val.getBytes(PngHelper.charsetUTF8);
+ byte[] textbytes = ChunkHelper.toBytesUTF8(val);
if (compressed) {
textbytes = ChunkHelper.compressBytes(textbytes, true);
}
ba.write(textbytes);
- byte[] b = ba.toByteArray();
- ChunkRaw chunk = createEmptyChunk(b.length, false);
+ final byte[] b = ba.toByteArray();
+ final ChunkRaw chunk = createEmptyChunk(b.length, false);
chunk.data = b;
return chunk;
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new PngjException(e);
}
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
int nullsFound = 0;
- int[] nullsIdx = new int[3];
+ final int[] nullsIdx = new int[3];
for (int i = 0; i < c.data.length; i++) {
if (c.data[i] != 0)
continue;
@@ -66,26 +69,27 @@ public class PngChunkITXT extends PngChunkTextVar {
}
if (nullsFound != 3)
throw new PngjException("Bad formed PngChunkITXT chunk");
- key = new String(c.data, 0, nullsIdx[0], PngHelper.charsetLatin1);
+ key = ChunkHelper.toString(c.data, 0, nullsIdx[0]);
int i = nullsIdx[0] + 1;
compressed = c.data[i] == 0 ? false : true;
i++;
if (compressed && c.data[i] != 0)
throw new PngjException("Bad formed PngChunkITXT chunk - bad compression method ");
- langTag = new String(c.data, i, nullsIdx[1] - i, PngHelper.charsetLatin1);
- translatedTag = new String(c.data, nullsIdx[1] + 1, nullsIdx[2] - nullsIdx[1] - 1, PngHelper.charsetUTF8);
+ langTag = new String(c.data, i, nullsIdx[1] - i, PngHelperInternal.charsetLatin1);
+ translatedTag = new String(c.data, nullsIdx[1] + 1, nullsIdx[2] - nullsIdx[1] - 1,
+ PngHelperInternal.charsetUTF8);
i = nullsIdx[2] + 1;
if (compressed) {
- byte[] bytes = ChunkHelper.compressBytes(c.data, i, c.data.length - i, false);
- val = new String(bytes, PngHelper.charsetUTF8);
+ final byte[] bytes = ChunkHelper.compressBytes(c.data, i, c.data.length - i, false);
+ val = ChunkHelper.toStringUTF8(bytes);
} else {
- val = new String(c.data, i, c.data.length - i, PngHelper.charsetUTF8);
+ val = ChunkHelper.toStringUTF8(c.data, i, c.data.length - i);
}
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkITXT otherx = (PngChunkITXT) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkITXT otherx = (PngChunkITXT) other;
key = otherx.key;
val = otherx.val;
compressed = otherx.compressed;
@@ -97,7 +101,7 @@ public class PngChunkITXT extends PngChunkTextVar {
return compressed;
}
- public void setCompressed(boolean compressed) {
+ public void setCompressed(final boolean compressed) {
this.compressed = compressed;
}
@@ -105,7 +109,7 @@ public class PngChunkITXT extends PngChunkTextVar {
return langTag;
}
- public void setLangtag(String langtag) {
+ public void setLangtag(final String langtag) {
this.langTag = langtag;
}
@@ -113,7 +117,7 @@ public class PngChunkITXT extends PngChunkTextVar {
return translatedTag;
}
- public void setTranslatedTag(String translatedTag) {
+ public void setTranslatedTag(final String translatedTag) {
this.translatedTag = translatedTag;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java
new file mode 100644
index 000000000..5a7bee98c
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java
@@ -0,0 +1,28 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+
+/**
+ * PNG chunk type (abstract) that allows multiple instances in same image.
+ */
+public abstract class PngChunkMultiple extends PngChunk {
+
+ protected PngChunkMultiple(final String id, final ImageInfo imgInfo) {
+ super(id, imgInfo);
+ }
+
+ @Override
+ public final boolean allowsMultiple() {
+ return true;
+ }
+
+ /**
+ * NOTE: this chunk uses the default Object's equals() hashCode()
+ * implementation.
+ *
+ * This is the right thing to do, normally.
+ *
+ * This is important, eg see ChunkList.removeFromList()
+ */
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkOFFS.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkOFFS.java
new file mode 100644
index 000000000..2217a59b4
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkOFFS.java
@@ -0,0 +1,89 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngHelperInternal;
+import jogamp.opengl.util.pngj.PngjException;
+
+/**
+ * oFFs chunk.
+ * <p>
+ * see http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.oFFs
+ */
+public class PngChunkOFFS extends PngChunkSingle {
+ public final static String ID = "oFFs";
+
+ // http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.oFFs
+ private long posX;
+ private long posY;
+ private int units; // 0: pixel 1:micrometer
+
+ public PngChunkOFFS(final ImageInfo info) {
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_IDAT;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
+ final ChunkRaw c = createEmptyChunk(9, true);
+ PngHelperInternal.writeInt4tobytes((int) posX, c.data, 0);
+ PngHelperInternal.writeInt4tobytes((int) posY, c.data, 4);
+ c.data[8] = (byte) units;
+ return c;
+ }
+
+ @Override
+ public void parseFromRaw(final ChunkRaw chunk) {
+ if (chunk.len != 9)
+ throw new PngjException("bad chunk length " + chunk);
+ posX = PngHelperInternal.readInt4fromBytes(chunk.data, 0);
+ if (posX < 0)
+ posX += 0x100000000L;
+ posY = PngHelperInternal.readInt4fromBytes(chunk.data, 4);
+ if (posY < 0)
+ posY += 0x100000000L;
+ units = PngHelperInternal.readInt1fromByte(chunk.data, 8);
+ }
+
+ @Override
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkOFFS otherx = (PngChunkOFFS) other;
+ this.posX = otherx.posX;
+ this.posY = otherx.posY;
+ this.units = otherx.units;
+ }
+
+ /**
+ * 0: pixel, 1:micrometer
+ */
+ public int getUnits() {
+ return units;
+ }
+
+ /**
+ * 0: pixel, 1:micrometer
+ */
+ public void setUnits(final int units) {
+ this.units = units;
+ }
+
+ public long getPosX() {
+ return posX;
+ }
+
+ public void setPosX(final long posX) {
+ this.posX = posX;
+ }
+
+ public long getPosY() {
+ return posY;
+ }
+
+ public void setPosY(final long posY) {
+ this.posY = posY;
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java
index 47e2c492c..fc647273e 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java
@@ -1,49 +1,55 @@
package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
+/**
+ * pHYs chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11pHYs
+ */
+public class PngChunkPHYS extends PngChunkSingle {
+ public final static String ID = ChunkHelper.pHYs;
-public class PngChunkPHYS extends PngChunk {
// http://www.w3.org/TR/PNG/#11pHYs
private long pixelsxUnitX;
private long pixelsxUnitY;
private int units; // 0: unknown 1:metre
- public PngChunkPHYS(ImageInfo info) {
- super(ChunkHelper.pHYs, info);
+ public PngChunkPHYS(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public boolean mustGoBeforeIDAT() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_IDAT;
}
@Override
- public ChunkRaw createChunk() {
- ChunkRaw c = createEmptyChunk(9, true);
- PngHelper.writeInt4tobytes((int) pixelsxUnitX, c.data, 0);
- PngHelper.writeInt4tobytes((int) pixelsxUnitY, c.data, 4);
+ public ChunkRaw createRawChunk() {
+ final ChunkRaw c = createEmptyChunk(9, true);
+ PngHelperInternal.writeInt4tobytes((int) pixelsxUnitX, c.data, 0);
+ PngHelperInternal.writeInt4tobytes((int) pixelsxUnitY, c.data, 4);
c.data[8] = (byte) units;
return c;
}
@Override
- public void parseFromChunk(ChunkRaw chunk) {
+ public void parseFromRaw(final ChunkRaw chunk) {
if (chunk.len != 9)
throw new PngjException("bad chunk length " + chunk);
- pixelsxUnitX = PngHelper.readInt4fromBytes(chunk.data, 0);
+ pixelsxUnitX = PngHelperInternal.readInt4fromBytes(chunk.data, 0);
if (pixelsxUnitX < 0)
pixelsxUnitX += 0x100000000L;
- pixelsxUnitY = PngHelper.readInt4fromBytes(chunk.data, 4);
+ pixelsxUnitY = PngHelperInternal.readInt4fromBytes(chunk.data, 4);
if (pixelsxUnitY < 0)
pixelsxUnitY += 0x100000000L;
- units = PngHelper.readInt1fromByte(chunk.data, 8);
+ units = PngHelperInternal.readInt1fromByte(chunk.data, 8);
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkPHYS otherx = (PngChunkPHYS) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkPHYS otherx = (PngChunkPHYS) other;
this.pixelsxUnitX = otherx.pixelsxUnitX;
this.pixelsxUnitY = otherx.pixelsxUnitY;
this.units = otherx.units;
@@ -53,7 +59,7 @@ public class PngChunkPHYS extends PngChunk {
return pixelsxUnitX;
}
- public void setPixelsxUnitX(long pixelsxUnitX) {
+ public void setPixelsxUnitX(final long pixelsxUnitX) {
this.pixelsxUnitX = pixelsxUnitX;
}
@@ -61,7 +67,7 @@ public class PngChunkPHYS extends PngChunk {
return pixelsxUnitY;
}
- public void setPixelsxUnitY(long pixelsxUnitY) {
+ public void setPixelsxUnitY(final long pixelsxUnitY) {
this.pixelsxUnitY = pixelsxUnitY;
}
@@ -69,7 +75,7 @@ public class PngChunkPHYS extends PngChunk {
return units;
}
- public void setUnits(int units) {
+ public void setUnits(final int units) {
this.units = units;
}
@@ -81,7 +87,7 @@ public class PngChunkPHYS extends PngChunk {
public double getAsDpi() {
if (units != 1 || pixelsxUnitX != pixelsxUnitY)
return -1;
- return ((double) pixelsxUnitX) * 0.0254;
+ return (pixelsxUnitX) * 0.0254;
}
/**
@@ -90,16 +96,16 @@ public class PngChunkPHYS extends PngChunk {
public double[] getAsDpi2() {
if (units != 1)
return new double[] { -1, -1 };
- return new double[] { ((double) pixelsxUnitX) * 0.0254, ((double) pixelsxUnitY) * 0.0254 };
+ return new double[] { (pixelsxUnitX) * 0.0254, (pixelsxUnitY) * 0.0254 };
}
- public void setAsDpi(double dpi) {
+ public void setAsDpi(final double dpi) {
units = 1;
pixelsxUnitX = (long) (dpi / 0.0254 + 0.5);
pixelsxUnitY = pixelsxUnitX;
}
- public void setAsDpi2(double dpix, double dpiy) {
+ public void setAsDpi2(final double dpix, final double dpiy) {
units = 1;
pixelsxUnitX = (long) (dpix / 0.0254 + 0.5);
pixelsxUnitY = (long) (dpiy / 0.0254 + 0.5);
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPLTE.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPLTE.java
index 123080bb3..0f135d1ed 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPLTE.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPLTE.java
@@ -3,10 +3,16 @@ package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
import jogamp.opengl.util.pngj.PngjException;
-/*
- * Palette chunk *this is critical*
+/**
+ * PLTE chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11PLTE
+ * <p>
+ * Critical chunk
*/
-public class PngChunkPLTE extends PngChunk {
+public class PngChunkPLTE extends PngChunkSingle {
+ public final static String ID = ChunkHelper.PLTE;
+
// http://www.w3.org/TR/PNG/#11PLTE
private int nentries = 0;
/**
@@ -14,15 +20,20 @@ public class PngChunkPLTE extends PngChunk {
*/
private int[] entries;
- public PngChunkPLTE(ImageInfo info) {
- super(ChunkHelper.PLTE, info);
+ public PngChunkPLTE(final ImageInfo info) {
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NA;
}
@Override
- public ChunkRaw createChunk() {
- int len = 3 * nentries;
- int[] rgb = new int[3];
- ChunkRaw c = createEmptyChunk(len, true);
+ public ChunkRaw createRawChunk() {
+ final int len = 3 * nentries;
+ final int[] rgb = new int[3];
+ final ChunkRaw c = createEmptyChunk(len, true);
for (int n = 0, i = 0; n < nentries; n++) {
getEntryRgb(n, rgb);
c.data[i++] = (byte) rgb[0];
@@ -33,21 +44,21 @@ public class PngChunkPLTE extends PngChunk {
}
@Override
- public void parseFromChunk(ChunkRaw chunk) {
+ public void parseFromRaw(final ChunkRaw chunk) {
setNentries(chunk.len / 3);
for (int n = 0, i = 0; n < nentries; n++) {
- setEntry(n, (int) (chunk.data[i++] & 0xff), (int) (chunk.data[i++] & 0xff), (int) (chunk.data[i++] & 0xff));
+ setEntry(n, chunk.data[i++] & 0xff, chunk.data[i++] & 0xff, chunk.data[i++] & 0xff);
}
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkPLTE otherx = (PngChunkPLTE) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkPLTE otherx = (PngChunkPLTE) other;
this.setNentries(otherx.getNentries());
System.arraycopy(otherx.entries, 0, entries, 0, nentries);
}
- public void setNentries(int n) {
+ public void setNentries(final int n) {
nentries = n;
if (nentries < 1 || nentries > 256)
throw new PngjException("invalid pallette - nentries=" + nentries);
@@ -60,20 +71,20 @@ public class PngChunkPLTE extends PngChunk {
return nentries;
}
- public void setEntry(int n, int r, int g, int b) {
+ public void setEntry(final int n, final int r, final int g, final int b) {
entries[n] = ((r << 16) | (g << 8) | b);
}
- public int getEntry(int n) {
+ public int getEntry(final int n) {
return entries[n];
}
- public void getEntryRgb(int n, int[] rgb) {
+ public void getEntryRgb(final int n, final int[] rgb) {
getEntryRgb(n, rgb, 0);
}
- public void getEntryRgb(int n, int[] rgb, int offset) {
- int v = entries[n];
+ public void getEntryRgb(final int n, final int[] rgb, final int offset) {
+ final int v = entries[n];
rgb[offset + 0] = ((v & 0xff0000) >> 16);
rgb[offset + 1] = ((v & 0xff00) >> 8);
rgb[offset + 2] = (v & 0xff);
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSBIT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSBIT.java
index 6850d260d..53858da83 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSBIT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSBIT.java
@@ -1,31 +1,31 @@
package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
-/*
+/**
+ * sBIT chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11sBIT
+ * <p>
+ * this chunk structure depends on the image type
*/
-public class PngChunkSBIT extends PngChunk {
+public class PngChunkSBIT extends PngChunkSingle {
+ public final static String ID = ChunkHelper.sBIT;
// http://www.w3.org/TR/PNG/#11sBIT
- // this chunk structure depends on the image type
// significant bits
private int graysb, alphasb;
private int redsb, greensb, bluesb;
- public PngChunkSBIT(ImageInfo info) {
- super(ChunkHelper.sBIT, info);
+ public PngChunkSBIT(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public boolean mustGoBeforeIDAT() {
- return true;
- }
-
- @Override
- public boolean mustGoBeforePLTE() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT;
}
private int getLen() {
@@ -36,24 +36,24 @@ public class PngChunkSBIT extends PngChunk {
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
if (c.len != getLen())
throw new PngjException("bad chunk length " + c);
if (imgInfo.greyscale) {
- graysb = PngHelper.readInt1fromByte(c.data, 0);
+ graysb = PngHelperInternal.readInt1fromByte(c.data, 0);
if (imgInfo.alpha)
- alphasb = PngHelper.readInt1fromByte(c.data, 1);
+ alphasb = PngHelperInternal.readInt1fromByte(c.data, 1);
} else {
- redsb = PngHelper.readInt1fromByte(c.data, 0);
- greensb = PngHelper.readInt1fromByte(c.data, 1);
- bluesb = PngHelper.readInt1fromByte(c.data, 2);
+ redsb = PngHelperInternal.readInt1fromByte(c.data, 0);
+ greensb = PngHelperInternal.readInt1fromByte(c.data, 1);
+ bluesb = PngHelperInternal.readInt1fromByte(c.data, 2);
if (imgInfo.alpha)
- alphasb = PngHelper.readInt1fromByte(c.data, 3);
+ alphasb = PngHelperInternal.readInt1fromByte(c.data, 3);
}
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
ChunkRaw c = null;
c = createEmptyChunk(getLen(), true);
if (imgInfo.greyscale) {
@@ -71,8 +71,8 @@ public class PngChunkSBIT extends PngChunk {
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkSBIT otherx = (PngChunkSBIT) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkSBIT otherx = (PngChunkSBIT) other;
graysb = otherx.graysb;
redsb = otherx.redsb;
greensb = otherx.greensb;
@@ -80,7 +80,7 @@ public class PngChunkSBIT extends PngChunk {
alphasb = otherx.alphasb;
}
- public void setGraysb(int gray) {
+ public void setGraysb(final int gray) {
if (!imgInfo.greyscale)
throw new PngjException("only greyscale images support this");
graysb = gray;
@@ -92,7 +92,7 @@ public class PngChunkSBIT extends PngChunk {
return graysb;
}
- public void setAlphasb(int a) {
+ public void setAlphasb(final int a) {
if (!imgInfo.alpha)
throw new PngjException("only images with alpha support this");
alphasb = a;
@@ -106,9 +106,9 @@ public class PngChunkSBIT extends PngChunk {
/**
* Set rgb values
- *
+ *
*/
- public void setRGB(int r, int g, int b) {
+ public void setRGB(final int r, final int g, final int b) {
if (imgInfo.greyscale || imgInfo.indexed)
throw new PngjException("only rgb or rgba images support this");
redsb = r;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java
index 953adb7d9..44ff249ac 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java
@@ -4,59 +4,60 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
+/**
+ * sPLT chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11sPLT
+ */
+public class PngChunkSPLT extends PngChunkMultiple {
+ public final static String ID = ChunkHelper.sPLT;
-public class PngChunkSPLT extends PngChunk {
// http://www.w3.org/TR/PNG/#11sPLT
private String palName;
private int sampledepth; // 8/16
private int[] palette; // 5 elements per entry
- public PngChunkSPLT(ImageInfo info) {
- super(ChunkHelper.sPLT, info);
+ public PngChunkSPLT(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public boolean allowsMultiple() {
- return true; // allows multiple, but pallete name should be different
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_IDAT;
}
@Override
- public boolean mustGoBeforeIDAT() {
- return true;
- }
-
- @Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
try {
- ByteArrayOutputStream ba = new ByteArrayOutputStream();
- ba.write(palName.getBytes(PngHelper.charsetLatin1));
+ final ByteArrayOutputStream ba = new ByteArrayOutputStream();
+ ba.write(palName.getBytes(PngHelperInternal.charsetLatin1));
ba.write(0); // separator
ba.write((byte) sampledepth);
- int nentries = getNentries();
+ final int nentries = getNentries();
for (int n = 0; n < nentries; n++) {
for (int i = 0; i < 4; i++) {
if (sampledepth == 8)
- PngHelper.writeByte(ba, (byte) palette[n * 5 + i]);
+ PngHelperInternal.writeByte(ba, (byte) palette[n * 5 + i]);
else
- PngHelper.writeInt2(ba, palette[n * 5 + i]);
+ PngHelperInternal.writeInt2(ba, palette[n * 5 + i]);
}
- PngHelper.writeInt2(ba, palette[n * 5 + 4]);
+ PngHelperInternal.writeInt2(ba, palette[n * 5 + 4]);
}
- byte[] b = ba.toByteArray();
- ChunkRaw chunk = createEmptyChunk(b.length, false);
+ final byte[] b = ba.toByteArray();
+ final ChunkRaw chunk = createEmptyChunk(b.length, false);
chunk.data = b;
return chunk;
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new PngjException(e);
}
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
int t = -1;
for (int i = 0; i < c.data.length; i++) { // look for first zero
if (c.data[i] == 0) {
@@ -66,30 +67,30 @@ public class PngChunkSPLT extends PngChunk {
}
if (t <= 0 || t > c.data.length - 2)
throw new PngjException("bad sPLT chunk: no separator found");
- palName = new String(c.data, 0, t, PngHelper.charsetLatin1);
- sampledepth = PngHelper.readInt1fromByte(c.data, t + 1);
+ palName = new String(c.data, 0, t, PngHelperInternal.charsetLatin1);
+ sampledepth = PngHelperInternal.readInt1fromByte(c.data, t + 1);
t += 2;
- int nentries = (c.data.length - t) / (sampledepth == 8 ? 6 : 10);
+ final int nentries = (c.data.length - t) / (sampledepth == 8 ? 6 : 10);
palette = new int[nentries * 5];
int r, g, b, a, f, ne;
ne = 0;
for (int i = 0; i < nentries; i++) {
if (sampledepth == 8) {
- r = PngHelper.readInt1fromByte(c.data, t++);
- g = PngHelper.readInt1fromByte(c.data, t++);
- b = PngHelper.readInt1fromByte(c.data, t++);
- a = PngHelper.readInt1fromByte(c.data, t++);
+ r = PngHelperInternal.readInt1fromByte(c.data, t++);
+ g = PngHelperInternal.readInt1fromByte(c.data, t++);
+ b = PngHelperInternal.readInt1fromByte(c.data, t++);
+ a = PngHelperInternal.readInt1fromByte(c.data, t++);
} else {
- r = PngHelper.readInt2fromBytes(c.data, t);
+ r = PngHelperInternal.readInt2fromBytes(c.data, t);
t += 2;
- g = PngHelper.readInt2fromBytes(c.data, t);
+ g = PngHelperInternal.readInt2fromBytes(c.data, t);
t += 2;
- b = PngHelper.readInt2fromBytes(c.data, t);
+ b = PngHelperInternal.readInt2fromBytes(c.data, t);
t += 2;
- a = PngHelper.readInt2fromBytes(c.data, t);
+ a = PngHelperInternal.readInt2fromBytes(c.data, t);
t += 2;
}
- f = PngHelper.readInt2fromBytes(c.data, t);
+ f = PngHelperInternal.readInt2fromBytes(c.data, t);
t += 2;
palette[ne++] = r;
palette[ne++] = g;
@@ -100,8 +101,8 @@ public class PngChunkSPLT extends PngChunk {
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkSPLT otherx = (PngChunkSPLT) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkSPLT otherx = (PngChunkSPLT) other;
palName = otherx.palName;
sampledepth = otherx.sampledepth;
palette = new int[otherx.palette.length];
@@ -116,7 +117,7 @@ public class PngChunkSPLT extends PngChunk {
return palName;
}
- public void setPalName(String palName) {
+ public void setPalName(final String palName) {
this.palName = palName;
}
@@ -124,7 +125,7 @@ public class PngChunkSPLT extends PngChunk {
return sampledepth;
}
- public void setSampledepth(int sampledepth) {
+ public void setSampledepth(final int sampledepth) {
this.sampledepth = sampledepth;
}
@@ -132,7 +133,7 @@ public class PngChunkSPLT extends PngChunk {
return palette;
}
- public void setPalette(int[] palette) {
+ public void setPalette(final int[] palette) {
this.palette = palette;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSRGB.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSRGB.java
index 774558785..19504b917 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSRGB.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSRGB.java
@@ -1,12 +1,17 @@
package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
-/*
+/**
+ * sRGB chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11sRGB
*/
-public class PngChunkSRGB extends PngChunk {
+public class PngChunkSRGB extends PngChunkSingle {
+ public final static String ID = ChunkHelper.sRGB;
+
// http://www.w3.org/TR/PNG/#11sRGB
public static final int RENDER_INTENT_Perceptual = 0;
@@ -16,29 +21,24 @@ public class PngChunkSRGB extends PngChunk {
private int intent;
- public PngChunkSRGB(ImageInfo info) {
- super(ChunkHelper.sRGB, info);
- }
-
- @Override
- public boolean mustGoBeforeIDAT() {
- return true;
+ public PngChunkSRGB(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public boolean mustGoBeforePLTE() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT;
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
if (c.len != 1)
throw new PngjException("bad chunk length " + c);
- intent = PngHelper.readInt1fromByte(c.data, 0);
+ intent = PngHelperInternal.readInt1fromByte(c.data, 0);
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
ChunkRaw c = null;
c = createEmptyChunk(1, true);
c.data[0] = (byte) intent;
@@ -46,8 +46,8 @@ public class PngChunkSRGB extends PngChunk {
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkSRGB otherx = (PngChunkSRGB) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkSRGB otherx = (PngChunkSRGB) other;
intent = otherx.intent;
}
@@ -55,7 +55,7 @@ public class PngChunkSRGB extends PngChunk {
return intent;
}
- public void setIntent(int intent) {
+ public void setIntent(final int intent) {
this.intent = intent;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSTER.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSTER.java
new file mode 100644
index 000000000..52037b396
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSTER.java
@@ -0,0 +1,60 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngjException;
+
+/**
+ * sTER chunk.
+ * <p>
+ * see http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.sTER
+ */
+public class PngChunkSTER extends PngChunkSingle {
+ public final static String ID = "sTER";
+
+ // http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.sTER
+ private byte mode; // 0: cross-fuse layout 1: diverging-fuse layout
+
+ public PngChunkSTER(final ImageInfo info) {
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_IDAT;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
+ final ChunkRaw c = createEmptyChunk(1, true);
+ c.data[0] = mode;
+ return c;
+ }
+
+ @Override
+ public void parseFromRaw(final ChunkRaw chunk) {
+ if (chunk.len != 1)
+ throw new PngjException("bad chunk length " + chunk);
+ mode = chunk.data[0];
+ }
+
+ @Override
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkSTER otherx = (PngChunkSTER) other;
+ this.mode = otherx.mode;
+ }
+
+ /**
+ * 0: cross-fuse layout 1: diverging-fuse layout
+ */
+ public byte getMode() {
+ return mode;
+ }
+
+ /**
+ * 0: cross-fuse layout 1: diverging-fuse layout
+ */
+ public void setMode(final byte mode) {
+ this.mode = mode;
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java
new file mode 100644
index 000000000..c5e9407b1
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java
@@ -0,0 +1,45 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+
+/**
+ * PNG chunk type (abstract) that does not allow multiple instances in same
+ * image.
+ */
+public abstract class PngChunkSingle extends PngChunk {
+
+ protected PngChunkSingle(final String id, final ImageInfo imgInfo) {
+ super(id, imgInfo);
+ }
+
+ @Override
+ public final boolean allowsMultiple() {
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final PngChunkSingle other = (PngChunkSingle) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ return true;
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSkipped.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSkipped.java
new file mode 100644
index 000000000..02a18816b
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSkipped.java
@@ -0,0 +1,41 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngjException;
+
+/**
+ * Pseudo chunk type, for chunks that were skipped on reading
+ */
+public class PngChunkSkipped extends PngChunk {
+
+ public PngChunkSkipped(final String id, final ImageInfo info, final int clen) {
+ super(id, info);
+ this.length = clen;
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NONE;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
+ throw new PngjException("Non supported for a skipped chunk");
+ }
+
+ @Override
+ public void parseFromRaw(final ChunkRaw c) {
+ throw new PngjException("Non supported for a skipped chunk");
+ }
+
+ @Override
+ public void cloneDataFromRead(final PngChunk other) {
+ throw new PngjException("Non supported for a skipped chunk");
+ }
+
+ @Override
+ public boolean allowsMultiple() {
+ return true;
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java
index c535fe34a..634d0cd12 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java
@@ -1,33 +1,45 @@
package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
+import jogamp.opengl.util.pngj.PngjException;
+/**
+ * tEXt chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11tEXt
+ */
public class PngChunkTEXT extends PngChunkTextVar {
- public PngChunkTEXT(ImageInfo info) {
- super(ChunkHelper.tEXt, info);
+ public final static String ID = ChunkHelper.tEXt;
+
+ public PngChunkTEXT(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public ChunkRaw createChunk() {
- if (val.isEmpty() || key.isEmpty())
- return null;
- byte[] b = (key + "\0" + val).getBytes(PngHelper.charsetLatin1);
- ChunkRaw chunk = createEmptyChunk(b.length, false);
+ public ChunkRaw createRawChunk() {
+ if (key.isEmpty())
+ throw new PngjException("Text chunk key must be non empty");
+ final byte[] b = (key + "\0" + val).getBytes(PngHelperInternal.charsetLatin1);
+ final ChunkRaw chunk = createEmptyChunk(b.length, false);
chunk.data = b;
return chunk;
}
@Override
- public void parseFromChunk(ChunkRaw c) {
- String[] k = (new String(c.data, PngHelper.charsetLatin1)).split("\0");
- key = k[0];
- val = k[1];
+ public void parseFromRaw(final ChunkRaw c) {
+ int i;
+ for (i = 0; i < c.data.length; i++)
+ if (c.data[i] == 0)
+ break;
+ key = new String(c.data, 0, i, PngHelperInternal.charsetLatin1);
+ i++;
+ val = i < c.data.length ? new String(c.data, i, c.data.length - i, PngHelperInternal.charsetLatin1) : "";
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkTEXT otherx = (PngChunkTEXT) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkTEXT otherx = (PngChunkTEXT) other;
key = otherx.key;
val = otherx.val;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTIME.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTIME.java
index 37e617acb..850fb649f 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTIME.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTIME.java
@@ -3,22 +3,33 @@ package jogamp.opengl.util.pngj.chunks;
import java.util.Calendar;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
+/**
+ * tIME chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11tIME
+ */
+public class PngChunkTIME extends PngChunkSingle {
+ public final static String ID = ChunkHelper.tIME;
-public class PngChunkTIME extends PngChunk {
// http://www.w3.org/TR/PNG/#11tIME
private int year, mon, day, hour, min, sec;
- public PngChunkTIME(ImageInfo info) {
- super(ChunkHelper.tIME, info);
+ public PngChunkTIME(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public ChunkRaw createChunk() {
- ChunkRaw c = createEmptyChunk(7, true);
- PngHelper.writeInt2tobytes(year, c.data, 0);
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NONE;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
+ final ChunkRaw c = createEmptyChunk(7, true);
+ PngHelperInternal.writeInt2tobytes(year, c.data, 0);
c.data[2] = (byte) mon;
c.data[3] = (byte) day;
c.data[4] = (byte) hour;
@@ -28,20 +39,20 @@ public class PngChunkTIME extends PngChunk {
}
@Override
- public void parseFromChunk(ChunkRaw chunk) {
+ public void parseFromRaw(final ChunkRaw chunk) {
if (chunk.len != 7)
throw new PngjException("bad chunk " + chunk);
- year = PngHelper.readInt2fromBytes(chunk.data, 0);
- mon = PngHelper.readInt1fromByte(chunk.data, 2);
- day = PngHelper.readInt1fromByte(chunk.data, 3);
- hour = PngHelper.readInt1fromByte(chunk.data, 4);
- min = PngHelper.readInt1fromByte(chunk.data, 5);
- sec = PngHelper.readInt1fromByte(chunk.data, 6);
+ year = PngHelperInternal.readInt2fromBytes(chunk.data, 0);
+ mon = PngHelperInternal.readInt1fromByte(chunk.data, 2);
+ day = PngHelperInternal.readInt1fromByte(chunk.data, 3);
+ hour = PngHelperInternal.readInt1fromByte(chunk.data, 4);
+ min = PngHelperInternal.readInt1fromByte(chunk.data, 5);
+ sec = PngHelperInternal.readInt1fromByte(chunk.data, 6);
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkTIME x = (PngChunkTIME) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkTIME x = (PngChunkTIME) other;
year = x.year;
mon = x.mon;
day = x.day;
@@ -50,8 +61,8 @@ public class PngChunkTIME extends PngChunk {
sec = x.sec;
}
- public void setNow(int secsAgo) {
- Calendar d = Calendar.getInstance();
+ public void setNow(final int secsAgo) {
+ final Calendar d = Calendar.getInstance();
d.setTimeInMillis(System.currentTimeMillis() - 1000 * (long) secsAgo);
year = d.get(Calendar.YEAR);
mon = d.get(Calendar.MONTH) + 1;
@@ -61,7 +72,7 @@ public class PngChunkTIME extends PngChunk {
sec = d.get(Calendar.SECOND);
}
- public void setYMDHMS(int yearx, int monx, int dayx, int hourx, int minx, int secx) {
+ public void setYMDHMS(final int yearx, final int monx, final int dayx, final int hourx, final int minx, final int secx) {
year = yearx;
mon = monx;
day = dayx;
@@ -69,15 +80,14 @@ public class PngChunkTIME extends PngChunk {
min = minx;
sec = secx;
}
+
public int[] getYMDHMS() {
return new int[] { year, mon, day, hour, min, sec };
}
/** format YYYY/MM/DD HH:mm:SS */
public String getAsString() {
- return String.format("%04/%02d/%02d %02d:%02d:%02d", year, mon, day, hour, min, sec);
+ return String.format("%04d/%02d/%02d %02d:%02d:%02d", year, mon, day, hour, min, sec);
}
-
-
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java
index 9365e5e8e..5e10c041b 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java
@@ -1,129 +1,141 @@
-package jogamp.opengl.util.pngj.chunks;
-
-import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
-import jogamp.opengl.util.pngj.PngjException;
-
-/*
- */
-public class PngChunkTRNS extends PngChunk {
- // http://www.w3.org/TR/PNG/#11tRNS
- // this chunk structure depends on the image type
- // only one of these is meaningful
- private int gray;
- private int red, green, blue;
- private int[] paletteAlpha = new int[] {};
-
- public PngChunkTRNS(ImageInfo info) {
- super(ChunkHelper.tRNS, info);
- }
-
- @Override
- public boolean mustGoBeforeIDAT() {
- return true;
- }
-
- @Override
- public boolean mustGoAfterPLTE() {
- return true;
- }
-
- @Override
- public ChunkRaw createChunk() {
- ChunkRaw c = null;
- if (imgInfo.greyscale) {
- c = createEmptyChunk(2, true);
- PngHelper.writeInt2tobytes(gray, c.data, 0);
- } else if (imgInfo.indexed) {
- c = createEmptyChunk(paletteAlpha.length, true);
- for (int n = 0; n < c.len; n++) {
- c.data[n] = (byte) paletteAlpha[n];
- }
- } else {
- c = createEmptyChunk(6, true);
- PngHelper.writeInt2tobytes(red, c.data, 0);
- PngHelper.writeInt2tobytes(green, c.data, 0);
- PngHelper.writeInt2tobytes(blue, c.data, 0);
- }
- return c;
- }
-
- @Override
- public void parseFromChunk(ChunkRaw c) {
- if (imgInfo.greyscale) {
- gray = PngHelper.readInt2fromBytes(c.data, 0);
- } else if (imgInfo.indexed) {
- int nentries = c.data.length;
- paletteAlpha = new int[nentries];
- for (int n = 0; n < nentries; n++) {
- paletteAlpha[n] = (int) (c.data[n] & 0xff);
- }
- } else {
- red = PngHelper.readInt2fromBytes(c.data, 0);
- green = PngHelper.readInt2fromBytes(c.data, 2);
- blue = PngHelper.readInt2fromBytes(c.data, 4);
- }
- }
-
- @Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkTRNS otherx = (PngChunkTRNS) other;
- gray = otherx.gray;
- red = otherx.red;
- green = otherx.red;
- blue = otherx.red;
- if (otherx.paletteAlpha != null) {
- paletteAlpha = new int[otherx.paletteAlpha.length];
- System.arraycopy(otherx.paletteAlpha, 0, paletteAlpha, 0, paletteAlpha.length);
- }
- }
-
- /**
- * Set rgb values
- *
- */
- public void setRGB(int r, int g, int b) {
- if (imgInfo.greyscale || imgInfo.indexed)
- throw new PngjException("only rgb or rgba images support this");
- red = r;
- green = g;
- blue = b;
- }
-
- public int[] getRGB() {
- if (imgInfo.greyscale || imgInfo.indexed)
- throw new PngjException("only rgb or rgba images support this");
- return new int[] { red, green, blue };
- }
-
- public void setGray(int g) {
- if (!imgInfo.greyscale)
- throw new PngjException("only grayscale images support this");
- gray = g;
- }
-
- public int getGray() {
- if (!imgInfo.greyscale)
- throw new PngjException("only grayscale images support this");
- return gray;
- }
-
- /**
- * WARNING: non deep copy
- */
- public void setPalletteAlpha(int[] palAlpha) {
- if (!imgInfo.indexed)
- throw new PngjException("only indexed images support this");
- paletteAlpha = palAlpha;
- }
-
- /**
- * WARNING: non deep copy
- */
- public int[] getPalletteAlpha() {
- if (!imgInfo.indexed)
- throw new PngjException("only indexed images support this");
- return paletteAlpha;
- }
-
-}
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngHelperInternal;
+import jogamp.opengl.util.pngj.PngjException;
+
+/**
+ * tRNS chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11tRNS
+ * <p>
+ * this chunk structure depends on the image type
+ */
+public class PngChunkTRNS extends PngChunkSingle {
+ public final static String ID = ChunkHelper.tRNS;
+
+ // http://www.w3.org/TR/PNG/#11tRNS
+
+ // only one of these is meaningful, depending on the image type
+ private int gray;
+ private int red, green, blue;
+ private int[] paletteAlpha = new int[] {};
+
+ public PngChunkTRNS(final ImageInfo info) {
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
+ ChunkRaw c = null;
+ if (imgInfo.greyscale) {
+ c = createEmptyChunk(2, true);
+ PngHelperInternal.writeInt2tobytes(gray, c.data, 0);
+ } else if (imgInfo.indexed) {
+ c = createEmptyChunk(paletteAlpha.length, true);
+ for (int n = 0; n < c.len; n++) {
+ c.data[n] = (byte) paletteAlpha[n];
+ }
+ } else {
+ c = createEmptyChunk(6, true);
+ PngHelperInternal.writeInt2tobytes(red, c.data, 0);
+ PngHelperInternal.writeInt2tobytes(green, c.data, 0);
+ PngHelperInternal.writeInt2tobytes(blue, c.data, 0);
+ }
+ return c;
+ }
+
+ @Override
+ public void parseFromRaw(final ChunkRaw c) {
+ if (imgInfo.greyscale) {
+ gray = PngHelperInternal.readInt2fromBytes(c.data, 0);
+ } else if (imgInfo.indexed) {
+ final int nentries = c.data.length;
+ paletteAlpha = new int[nentries];
+ for (int n = 0; n < nentries; n++) {
+ paletteAlpha[n] = c.data[n] & 0xff;
+ }
+ } else {
+ red = PngHelperInternal.readInt2fromBytes(c.data, 0);
+ green = PngHelperInternal.readInt2fromBytes(c.data, 2);
+ blue = PngHelperInternal.readInt2fromBytes(c.data, 4);
+ }
+ }
+
+ @Override
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkTRNS otherx = (PngChunkTRNS) other;
+ gray = otherx.gray;
+ red = otherx.red;
+ green = otherx.green;
+ blue = otherx.blue;
+ if (otherx.paletteAlpha != null) {
+ paletteAlpha = new int[otherx.paletteAlpha.length];
+ System.arraycopy(otherx.paletteAlpha, 0, paletteAlpha, 0, paletteAlpha.length);
+ }
+ }
+
+ /**
+ * Set rgb values
+ *
+ */
+ public void setRGB(final int r, final int g, final int b) {
+ if (imgInfo.greyscale || imgInfo.indexed)
+ throw new PngjException("only rgb or rgba images support this");
+ red = r;
+ green = g;
+ blue = b;
+ }
+
+ public int[] getRGB() {
+ if (imgInfo.greyscale || imgInfo.indexed)
+ throw new PngjException("only rgb or rgba images support this");
+ return new int[] { red, green, blue };
+ }
+
+ public void setGray(final int g) {
+ if (!imgInfo.greyscale)
+ throw new PngjException("only grayscale images support this");
+ gray = g;
+ }
+
+ public int getGray() {
+ if (!imgInfo.greyscale)
+ throw new PngjException("only grayscale images support this");
+ return gray;
+ }
+
+ /**
+ * WARNING: non deep copy
+ */
+ public void setPalletteAlpha(final int[] palAlpha) {
+ if (!imgInfo.indexed)
+ throw new PngjException("only indexed images support this");
+ paletteAlpha = palAlpha;
+ }
+
+ /**
+ * to use when only one pallete index is set as totally transparent
+ */
+ public void setIndexEntryAsTransparent(final int palAlphaIndex) {
+ if (!imgInfo.indexed)
+ throw new PngjException("only indexed images support this");
+ paletteAlpha = new int[] { palAlphaIndex + 1 };
+ for (int i = 0; i < palAlphaIndex; i++)
+ paletteAlpha[i] = 255;
+ paletteAlpha[palAlphaIndex] = 0;
+ }
+
+ /**
+ * WARNING: non deep copy
+ */
+ public int[] getPalletteAlpha() {
+ return paletteAlpha;
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTextVar.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTextVar.java
index 3d92a806f..d00c29971 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTextVar.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTextVar.java
@@ -3,11 +3,9 @@ package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
/**
- * superclass for three textual chunks (TEXT, ITXT, ZTXT)
- *
- * @author Hernan J Gonzalez
+ * Superclass (abstract) for three textual chunks (TEXT, ITXT, ZTXT)
*/
-public abstract class PngChunkTextVar extends PngChunk {
+public abstract class PngChunkTextVar extends PngChunkMultiple {
protected String key; // key/val: only for tEXt. lazy computed
protected String val;
@@ -23,13 +21,13 @@ public abstract class PngChunkTextVar extends PngChunk {
public final static String KEY_Source = "Source"; // Device used to create the image
public final static String KEY_Comment = "Comment"; // Miscellaneous comment
- protected PngChunkTextVar(String id, ImageInfo info) {
+ protected PngChunkTextVar(final String id, final ImageInfo info) {
super(id, info);
}
@Override
- public boolean allowsMultiple() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NONE;
}
public static class PngTxtInfo {
@@ -53,7 +51,7 @@ public abstract class PngChunkTextVar extends PngChunk {
return val;
}
- public void setKeyVal(String key, String val) {
+ public void setKeyVal(final String key, final String val) {
this.key = key;
this.val = val;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java
index 15a35935a..693729e9b 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java
@@ -2,33 +2,38 @@ package jogamp.opengl.util.pngj.chunks;
import jogamp.opengl.util.pngj.ImageInfo;
-public class PngChunkUNKNOWN extends PngChunk { // unkown, custom or not
+/**
+ * Placeholder for UNKNOWN (custom or not) chunks.
+ * <p>
+ * For PngReader, a chunk is unknown if it's not registered in the chunk factory
+ */
+public class PngChunkUNKNOWN extends PngChunkMultiple { // unkown, custom or not
private byte[] data;
- public PngChunkUNKNOWN(String id, ImageInfo info) {
+ public PngChunkUNKNOWN(final String id, final ImageInfo info) {
super(id, info);
}
- @Override
- public boolean allowsMultiple() {
- return true;
- }
-
- private PngChunkUNKNOWN(PngChunkUNKNOWN c, ImageInfo info) {
+ private PngChunkUNKNOWN(final PngChunkUNKNOWN c, final ImageInfo info) {
super(c.id, info);
System.arraycopy(c.data, 0, data, 0, c.data.length);
}
@Override
- public ChunkRaw createChunk() {
- ChunkRaw p = createEmptyChunk(data.length, false);
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NONE;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
+ final ChunkRaw p = createEmptyChunk(data.length, false);
p.data = this.data;
return p;
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
data = c.data;
}
@@ -38,14 +43,14 @@ public class PngChunkUNKNOWN extends PngChunk { // unkown, custom or not
}
/* does not copy! */
- public void setData(byte[] data) {
+ public void setData(final byte[] data) {
this.data = data;
}
@Override
- public void cloneDataFromRead(PngChunk other) {
+ public void cloneDataFromRead(final PngChunk other) {
// THIS SHOULD NOT BE CALLED IF ALREADY CLONED WITH COPY CONSTRUCTOR
- PngChunkUNKNOWN c = (PngChunkUNKNOWN) other;
+ final PngChunkUNKNOWN c = (PngChunkUNKNOWN) other;
data = c.data; // not deep copy
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java
index fd6c08273..c1dfdeb33 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java
@@ -4,38 +4,44 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
-
+/**
+ * zTXt chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11zTXt
+ */
public class PngChunkZTXT extends PngChunkTextVar {
+ public final static String ID = ChunkHelper.zTXt;
+
// http://www.w3.org/TR/PNG/#11zTXt
- public PngChunkZTXT(ImageInfo info) {
- super(ChunkHelper.zTXt, info);
+ public PngChunkZTXT(final ImageInfo info) {
+ super(ID, info);
}
@Override
- public ChunkRaw createChunk() {
- if (val.isEmpty() || key.isEmpty())
- return null;
+ public ChunkRaw createRawChunk() {
+ if (key.isEmpty())
+ throw new PngjException("Text chunk key must be non empty");
try {
- ByteArrayOutputStream ba = new ByteArrayOutputStream();
- ba.write(key.getBytes(PngHelper.charsetLatin1));
+ final ByteArrayOutputStream ba = new ByteArrayOutputStream();
+ ba.write(key.getBytes(PngHelperInternal.charsetLatin1));
ba.write(0); // separator
ba.write(0); // compression method: 0
- byte[] textbytes = ChunkHelper.compressBytes(val.getBytes(PngHelper.charsetLatin1), true);
+ final byte[] textbytes = ChunkHelper.compressBytes(val.getBytes(PngHelperInternal.charsetLatin1), true);
ba.write(textbytes);
- byte[] b = ba.toByteArray();
- ChunkRaw chunk = createEmptyChunk(b.length, false);
+ final byte[] b = ba.toByteArray();
+ final ChunkRaw chunk = createEmptyChunk(b.length, false);
chunk.data = b;
return chunk;
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new PngjException(e);
}
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(final ChunkRaw c) {
int nullsep = -1;
for (int i = 0; i < c.data.length; i++) { // look for first zero
if (c.data[i] != 0)
@@ -45,17 +51,17 @@ public class PngChunkZTXT extends PngChunkTextVar {
}
if (nullsep < 0 || nullsep > c.data.length - 2)
throw new PngjException("bad zTXt chunk: no separator found");
- key = new String(c.data, 0, nullsep, PngHelper.charsetLatin1);
- int compmet = (int) c.data[nullsep + 1];
+ key = new String(c.data, 0, nullsep, PngHelperInternal.charsetLatin1);
+ final int compmet = c.data[nullsep + 1];
if (compmet != 0)
throw new PngjException("bad zTXt chunk: unknown compression method");
- byte[] uncomp = ChunkHelper.compressBytes(c.data, nullsep + 2, c.data.length - nullsep - 2, false); // uncompress
- val = new String(uncomp, PngHelper.charsetLatin1);
+ final byte[] uncomp = ChunkHelper.compressBytes(c.data, nullsep + 2, c.data.length - nullsep - 2, false); // uncompress
+ val = new String(uncomp, PngHelperInternal.charsetLatin1);
}
@Override
- public void cloneDataFromRead(PngChunk other) {
- PngChunkZTXT otherx = (PngChunkZTXT) other;
+ public void cloneDataFromRead(final PngChunk other) {
+ final PngChunkZTXT otherx = (PngChunkZTXT) other;
key = otherx.key;
val = otherx.val;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
index a82754588..bba2b3e7c 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
@@ -1,106 +1,150 @@
package jogamp.opengl.util.pngj.chunks;
-import jogamp.opengl.util.pngj.PngHelper;
+import java.util.ArrayList;
+import java.util.List;
+
+import jogamp.opengl.util.pngj.PngHelperInternal;
import jogamp.opengl.util.pngj.PngjException;
/**
- * We consider "image metadata" every info inside the image except for the most basic image info (IHDR chunk - ImageInfo
- * class) and the pixels values.
- *
+ * We consider "image metadata" every info inside the image except for the most
+ * basic image info (IHDR chunk - ImageInfo class) and the pixels values.
+ * <p>
* This includes the palette (if present) and all the ancillary chunks
- *
- * This class provides a wrapper over the collection of chunks of a image (read or to write) and provides some high
- * level methods to access them
- *
+ * <p>
+ * This class provides a wrapper over the collection of chunks of a image (read
+ * or to write) and provides some high level methods to access them
*/
public class PngMetadata {
- private final ChunkList chunkList;
+ private final ChunksList chunkList;
private final boolean readonly;
- public PngMetadata(ChunkList chunks, boolean readonly) {
+ public PngMetadata(final ChunksList chunks) {
this.chunkList = chunks;
- this.readonly = readonly;
+ if (chunks instanceof ChunksListForWrite) {
+ this.readonly = false;
+ } else {
+ this.readonly = true;
+ }
}
/**
* Queues the chunk at the writer
+ * <p>
+ * lazyOverwrite: if true, checks if there is a queued "equivalent" chunk
+ * and if so, overwrites it. However if that not check for already written
+ * chunks.
*/
- public boolean setChunk(PngChunk c, boolean overwriteIfPresent) {
+ public void queueChunk(final PngChunk c, final boolean lazyOverwrite) {
+ final ChunksListForWrite cl = getChunkListW();
if (readonly)
throw new PngjException("cannot set chunk : readonly metadata");
- return chunkList.setChunk(c, overwriteIfPresent);
+ if (lazyOverwrite) {
+ ChunkHelper.trimList(cl.getQueuedChunks(), new ChunkPredicate() {
+ @Override
+ public boolean match(final PngChunk c2) {
+ return ChunkHelper.equivalent(c, c2);
+ }
+ });
+ }
+ cl.queue(c);
}
-
- /**
- * Returns only one chunk or null if nothing found - does not include queued chunks
- *
- * If more than one chunk (after filtering by inner id) is found, then an exception is thrown (failifMultiple=true)
- * or the last one is returned (failifMultiple=false)
- *
- * @param id Chunk id
- * @param innerid if not null, the chunk is assumed to be PngChunkTextVar or PngChunkSPLT, and filtered by that 'internal id'
- * @param failIfMultiple throw exception if more that one
- * @return chunk (not cloned)
- */
- public PngChunk getChunk1(String id, String innerid, boolean failIfMultiple) {
- return chunkList.getChunk1(id, innerid, failIfMultiple);
+ public void queueChunk(final PngChunk c) {
+ queueChunk(c, true);
}
- /**
- * Same as getChunk1(id, innerid=null, failIfMultiple=true);
- */
- public PngChunk getChunk1(String id) {
- return chunkList.getChunk1(id);
+ private ChunksListForWrite getChunkListW() {
+ return (ChunksListForWrite) chunkList;
}
// ///// high level utility methods follow ////////////
// //////////// DPI
- /**
- * returns -1 if not found or dimension unknown
- **/
+ /**
+ * returns -1 if not found or dimension unknown
+ */
public double[] getDpi() {
- PngChunk c = getChunk1(ChunkHelper.pHYs, null, true);
+ final PngChunk c = chunkList.getById1(ChunkHelper.pHYs, true);
if (c == null)
return new double[] { -1, -1 };
else
return ((PngChunkPHYS) c).getAsDpi2();
}
- public void setDpi(double x) {
+ public void setDpi(final double x) {
setDpi(x, x);
}
- public void setDpi(double x, double y) {
- PngChunkPHYS c = new PngChunkPHYS(chunkList.imageInfo);
+ public void setDpi(final double x, final double y) {
+ final PngChunkPHYS c = new PngChunkPHYS(chunkList.imageInfo);
c.setAsDpi2(x, y);
- setChunk(c, true);
+ queueChunk(c);
}
// //////////// TIME
- public void setTimeNow(int secsAgo) {
- PngChunkTIME c = new PngChunkTIME(chunkList.imageInfo);
+ /**
+ * Creates a time chunk with current time, less secsAgo seconds
+ * <p>
+ *
+ * @return Returns the created-queued chunk, just in case you want to
+ * examine or modify it
+ */
+ public PngChunkTIME setTimeNow(final int secsAgo) {
+ final PngChunkTIME c = new PngChunkTIME(chunkList.imageInfo);
c.setNow(secsAgo);
- setChunk(c, true);
+ queueChunk(c);
+ return c;
+ }
+
+ public PngChunkTIME setTimeNow() {
+ return setTimeNow(0);
}
- public void setTimeYMDHMS(int yearx, int monx, int dayx, int hourx, int minx, int secx) {
- PngChunkTIME c = new PngChunkTIME(chunkList.imageInfo);
+ /**
+ * Creates a time chunk with diven date-time
+ * <p>
+ *
+ * @return Returns the created-queued chunk, just in case you want to
+ * examine or modify it
+ */
+ public PngChunkTIME setTimeYMDHMS(final int yearx, final int monx, final int dayx, final int hourx, final int minx, final int secx) {
+ final PngChunkTIME c = new PngChunkTIME(chunkList.imageInfo);
c.setYMDHMS(yearx, monx, dayx, hourx, minx, secx);
- setChunk(c, true);
+ queueChunk(c, true);
+ return c;
+ }
+
+ /**
+ * null if not found
+ */
+ public PngChunkTIME getTime() {
+ return (PngChunkTIME) chunkList.getById1(ChunkHelper.tIME);
}
public String getTimeAsString() {
- PngChunk c = getChunk1(ChunkHelper.tIME, null, true);
- return c != null ? ((PngChunkTIME) c).getAsString() : "";
+ final PngChunkTIME c = getTime();
+ return c == null ? "" : c.getAsString();
}
// //////////// TEXT
- public void setText(String k, String val, boolean useLatin1, boolean compress) {
+ /**
+ * Creates a text chunk and queue it.
+ * <p>
+ *
+ * @param k
+ * : key (latin1)
+ * @param val
+ * (arbitrary, should be latin1 if useLatin1)
+ * @param useLatin1
+ * @param compress
+ * @return Returns the created-queued chunks, just in case you want to
+ * examine, touch it
+ */
+ public PngChunkTextVar setText(final String k, final String val, final boolean useLatin1, final boolean compress) {
if (compress && !useLatin1)
throw new PngjException("cannot compress non latin text");
PngChunkTextVar c;
@@ -115,21 +159,84 @@ public class PngMetadata {
((PngChunkITXT) c).setLangtag(k); // we use the same orig tag (this is not quite right)
}
c.setKeyVal(k, val);
- setChunk(c, true);
+ queueChunk(c, true);
+ return c;
}
- public void setText(String k, String val) {
- setText(k, val, false, val.length() > 400);
+ public PngChunkTextVar setText(final String k, final String val) {
+ return setText(k, val, false, false);
}
- /** tries all text chunks - returns null if not found */
- public String getTxtForKey(String k) {
- PngChunk c = getChunk1(ChunkHelper.tEXt, k, true);
- if (c == null)
- c = getChunk1(ChunkHelper.zTXt, k, true);
- if (c == null)
- c = getChunk1(ChunkHelper.iTXt, k, true);
- return c != null ? ((PngChunkTextVar) c).getVal() : null;
+ /**
+ * gets all text chunks with a given key
+ * <p>
+ * returns null if not found
+ * <p>
+ * Warning: this does not check the "lang" key of iTxt
+ */
+ @SuppressWarnings("unchecked")
+ public List<? extends PngChunkTextVar> getTxtsForKey(final String k) {
+ @SuppressWarnings("rawtypes")
+ final
+ List c = new ArrayList();
+ c.addAll(chunkList.getById(ChunkHelper.tEXt, k));
+ c.addAll(chunkList.getById(ChunkHelper.zTXt, k));
+ c.addAll(chunkList.getById(ChunkHelper.iTXt, k));
+ return c;
+ }
+
+ /**
+ * Returns empty if not found, concatenated (with newlines) if multiple! -
+ * and trimmed
+ * <p>
+ * Use getTxtsForKey() if you don't want this behaviour
+ */
+ public String getTxtForKey(final String k) {
+ final List<? extends PngChunkTextVar> li = getTxtsForKey(k);
+ if (li.isEmpty())
+ return "";
+ final StringBuilder t = new StringBuilder();
+ for (final PngChunkTextVar c : li)
+ t.append(c.getVal()).append("\n");
+ return t.toString().trim();
+ }
+
+ /**
+ * Returns the palette chunk, if present
+ *
+ * @return null if not present
+ */
+ public PngChunkPLTE getPLTE() {
+ return (PngChunkPLTE) chunkList.getById1(PngChunkPLTE.ID);
+ }
+
+ /**
+ * Creates a new empty palette chunk, queues it for write and return it to
+ * the caller, who should fill its entries
+ */
+ public PngChunkPLTE createPLTEChunk() {
+ final PngChunkPLTE plte = new PngChunkPLTE(chunkList.imageInfo);
+ queueChunk(plte);
+ return plte;
+ }
+
+ /**
+ * Returns the TRNS chunk, if present
+ *
+ * @return null if not present
+ */
+ public PngChunkTRNS getTRNS() {
+ return (PngChunkTRNS) chunkList.getById1(PngChunkTRNS.ID);
+ }
+
+ /**
+ * Creates a new empty TRNS chunk, queues it for write and return it to the
+ * caller, who should fill its entries
+ */
+ public PngChunkTRNS createTRNSChunk() {
+ final PngChunkTRNS trns = new PngChunkTRNS(chunkList.imageInfo);
+ queueChunk(trns);
+ return trns;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/package.html b/src/jogl/classes/jogamp/opengl/util/pngj/package.html
index 209b39c59..0b0e2c8c1 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/package.html
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/package.html
@@ -1,11 +1,10 @@
<html>
<body bgcolor="white">
<p>
-Contains the main classes for the PNGJ library.<p>
-Client code should rarely need more than the public members of this package.
+PNGJ main package
</p>
<p>
-See also the <code>nosandbox</code> package if available.
+Client code should rarely need more than the public members of this package.
</p>
</body>
</html>
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/DistortionMesh.java b/src/jogl/classes/jogamp/opengl/util/stereo/DistortionMesh.java
new file mode 100644
index 000000000..7a2483121
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/DistortionMesh.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.stereo;
+
+import com.jogamp.opengl.util.stereo.EyeParameter;
+
+public class DistortionMesh {
+ public static interface Producer {
+ /** Initialize */
+ void init(final GenericStereoDevice.Config deviceConfig, final float[] eyeReliefInMeters);
+
+ /** Distortion Mesh Producer */
+ DistortionMesh create(final EyeParameter eyeParam, final int distortionBits);
+ }
+ public static class DistortionVertex {
+ /** {@value} */
+ public static final int def_pos_size = 2;
+ /** {@value} */
+ public static final int def_vignetteFactor_size = 1;
+ /** {@value} */
+ public static final int def_timewarpFactor_size = 1;
+ /** {@value} */
+ public static final int def_texR_size = 2;
+ /** {@value} */
+ public static final int def_texG_size = 2;
+ /** {@value} */
+ public static final int def_texB_size = 2;
+
+ /** {@value} */
+ public static final int def_total_size = def_pos_size + def_vignetteFactor_size + def_timewarpFactor_size +
+ def_texR_size + def_texG_size + def_texB_size;
+
+ public DistortionVertex(final float[] data, final int pos_size,
+ final int vignetteFactor_size, final int timewarpFactor_size, final int texR_size,
+ final int texG_size, final int texB_size) {
+ this.data = data;
+ this.pos_size = pos_size;
+ this.vignetteFactor_size = vignetteFactor_size;
+ this.timewarpFactor_size = timewarpFactor_size;
+ this.texR_size = texR_size;
+ this.texG_size = texG_size;
+ this.texB_size = texB_size;
+ }
+ final float[] data;
+
+ /** Usually {@link #def_pos_size} */
+ final int pos_size;
+ /** Usually {@link #def_vignetteFactor_size} */
+ final int vignetteFactor_size;
+ /** Usually {@link #def_timewarpFactor_size} */
+ final int timewarpFactor_size;
+ /** Usually {@link #def_texR_size} */
+ final int texR_size;
+ /** Usually {@link #def_texG_size} */
+ final int texG_size;
+ /** Usually {@link #def_texB_size} */
+ final int texB_size;
+ }
+ public DistortionMesh(final DistortionMesh.DistortionVertex[] vertices, final int vertexCount,
+ final short[] indices, final int indexCount) {
+ this.vertices = vertices;
+ this.vertexCount = vertexCount;
+ this.indices = indices;
+ this.indexCount = indexCount;
+ }
+ final DistortionMesh.DistortionVertex[] vertices;
+ final int vertexCount;
+ final short[] indices;
+ final int indexCount;
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDevice.java b/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDevice.java
new file mode 100644
index 000000000..36e8bc5a5
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDevice.java
@@ -0,0 +1,468 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.stereo;
+
+import java.util.Arrays;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.FovHVHalves;
+import com.jogamp.opengl.util.stereo.EyeParameter;
+import com.jogamp.opengl.util.stereo.StereoDevice;
+import com.jogamp.opengl.util.stereo.StereoDeviceFactory;
+import com.jogamp.opengl.util.stereo.StereoDeviceRenderer;
+import com.jogamp.opengl.util.stereo.StereoUtil;
+
+public class GenericStereoDevice implements StereoDevice {
+ public static enum ShutterType {
+ Global, RollingLeftToRight, RollingRightToLeft, RollingTopToBottom
+ }
+ public static class Config extends StereoDevice.Config {
+ public Config(final String name,
+ final ShutterType shutterType,
+ final DimensionImmutable surfaceSizeInPixels,
+ final float[] screenSizeInMeters,
+ final DimensionImmutable eyeTextureSize,
+ final float pupilCenterFromScreenTopInMeters,
+ final float interpupillaryDistanceInMeters,
+ final int[] eyeRenderOrder,
+ final EyeParameter[] defaultEyeParam,
+ final DistortionMesh.Producer distortionMeshProducer,
+ final int supportedDistortionBits,
+ final int recommendedDistortionBits,
+ final int minimumDistortionBits
+ ) {
+ this.name = name;
+ this.shutterType = shutterType;
+ this.surfaceSizeInPixels = surfaceSizeInPixels;
+ this.screenSizeInMeters = screenSizeInMeters;
+ this.eyeTextureSize = eyeTextureSize;
+ this.pupilCenterFromScreenTopInMeters = pupilCenterFromScreenTopInMeters;
+ this.interpupillaryDistanceInMeters = interpupillaryDistanceInMeters;
+ this.eyeRenderOrder = eyeRenderOrder;
+ this.defaultEyeParam = defaultEyeParam;
+ this.distortionMeshProducer = distortionMeshProducer;
+ this.supportedDistortionBits = supportedDistortionBits;
+ this.recommendedDistortionBits = recommendedDistortionBits;
+ this.minimumDistortionBits = minimumDistortionBits;
+ this.pupilCenterFromTopLeft = new float[2][2];
+ calcPupilCenterFromTopLeft();
+ }
+ /** A variation w/ different surface/screen specs */
+ public Config(final Config source,
+ final DimensionImmutable surfaceSizeInPixels,
+ final float[] screenSizeInMeters,
+ final DimensionImmutable eyeTextureSize) {
+ this.name = source.name;
+ this.shutterType = source.shutterType;
+ this.surfaceSizeInPixels = surfaceSizeInPixels;
+ this.screenSizeInMeters = screenSizeInMeters;
+ this.eyeTextureSize = eyeTextureSize;
+ this.pupilCenterFromScreenTopInMeters = source.pupilCenterFromScreenTopInMeters;
+ this.interpupillaryDistanceInMeters = source.interpupillaryDistanceInMeters;
+ this.eyeRenderOrder = source.eyeRenderOrder;
+ this.defaultEyeParam = source.defaultEyeParam;
+ this.distortionMeshProducer = source.distortionMeshProducer;
+ this.supportedDistortionBits = source.supportedDistortionBits;
+ this.recommendedDistortionBits = source.recommendedDistortionBits;
+ this.minimumDistortionBits = source.minimumDistortionBits;
+ this.pupilCenterFromTopLeft = new float[2][2];
+ calcPupilCenterFromTopLeft();
+ }
+ private void calcPupilCenterFromTopLeft() {
+ final float visibleWidthOfOneEye = 0.5f * screenSizeInMeters[0];
+ final float leftPupilCenterFromLeftInMeters = ( screenSizeInMeters[0] - interpupillaryDistanceInMeters ) * 0.5f;
+ final float rightPupilCenterFromMiddleInMeters = leftPupilCenterFromLeftInMeters + interpupillaryDistanceInMeters - visibleWidthOfOneEye;
+ pupilCenterFromTopLeft[0][0] = leftPupilCenterFromLeftInMeters / visibleWidthOfOneEye;
+ pupilCenterFromTopLeft[0][1] = pupilCenterFromScreenTopInMeters / screenSizeInMeters[1];
+ pupilCenterFromTopLeft[1][0] = rightPupilCenterFromMiddleInMeters / visibleWidthOfOneEye;
+ pupilCenterFromTopLeft[1][1] = pupilCenterFromTopLeft[0][1];
+ }
+
+ /**
+ * Return the vertical pupil center from the screen top in the range [0..1].
+ * @param screenHeightInMeters
+ * @param pupilCenterFromScreenTopInMeters
+ */
+ public static float getVertPupilCenterFromTop(final float screenHeightInMeters, final float pupilCenterFromScreenTopInMeters) {
+ return pupilCenterFromScreenTopInMeters / screenHeightInMeters;
+ }
+
+ /**
+ * Return the horizontal pupil center from the left side for both eyes in the range [0..1].
+ * <pre>
+ <-------------left eye------------->| |<-----------right eye-------------->
+ <------------------------------------screenSizeInMeters.Width----------------------------------->
+ <------interpupillaryDistanceInMeters------>
+ <--centerFromLeftInMeters->
+ ^
+ center of pupil
+ * </pre>
+ *
+ * @param screenWidthInMeters
+ * @param interpupillaryDistanceInMeters
+ */
+ public static float[] getHorizPupilCenterFromLeft(final float screenWidthInMeters, final float interpupillaryDistanceInMeters) {
+ final float visibleWidthOfOneEye = 0.5f * screenWidthInMeters;
+ final float leftPupilCenterFromLeftInMeters = ( screenWidthInMeters - interpupillaryDistanceInMeters ) * 0.5f;
+ final float rightPupilCenterFromMiddleInMeters = leftPupilCenterFromLeftInMeters + interpupillaryDistanceInMeters - visibleWidthOfOneEye;
+ return new float[] { leftPupilCenterFromLeftInMeters / visibleWidthOfOneEye,
+ rightPupilCenterFromMiddleInMeters / visibleWidthOfOneEye };
+ }
+
+ void init() {
+ final float[] eyeReliefInMeters = new float[defaultEyeParam.length];
+ if( 0 < defaultEyeParam.length ) {
+ eyeReliefInMeters[0] = defaultEyeParam[0].eyeReliefZ;
+ }
+ if( 1 < defaultEyeParam.length ) {
+ eyeReliefInMeters[1] = defaultEyeParam[1].eyeReliefZ;
+ }
+ if( null != distortionMeshProducer ) {
+ distortionMeshProducer.init(this, eyeReliefInMeters);
+ }
+ }
+
+ @Override
+ public String toString() { return "StereoConfig["+name+", shutter "+shutterType+", surfaceSize "+surfaceSizeInPixels+
+ ", screenSize "+screenSizeInMeters[0]+" x "+screenSizeInMeters[0]+
+ " [m], eyeTexSize "+eyeTextureSize+", IPD "+interpupillaryDistanceInMeters+
+ " [m], eyeParam "+Arrays.toString(defaultEyeParam)+
+ ", distortionBits[supported ["+StereoUtil.distortionBitsToString(supportedDistortionBits)+
+ "], recommended ["+StereoUtil.distortionBitsToString(recommendedDistortionBits)+
+ "], minimum ["+StereoUtil.distortionBitsToString(minimumDistortionBits)+"]]]";
+ }
+
+ /** Configuration Name */
+ public final String name;
+ public final ShutterType shutterType;
+
+ public final DimensionImmutable surfaceSizeInPixels;
+ public final float[] screenSizeInMeters;
+ /** Texture size per eye */
+ public final DimensionImmutable eyeTextureSize;
+
+ /** Vertical distance from pupil to screen-top in meters */
+ public final float pupilCenterFromScreenTopInMeters;
+ /** Horizontal interpupillary distance (IPD) in meters */
+ public final float interpupillaryDistanceInMeters;
+ /**
+ * Pupil center from top left per eye, ranging from [0..1], maybe used to produce FovHVHalves,
+ * see {@link #getHorizPupilCenterFromLeft(float, float)} and {@link #getVertPupilCenterFromTop(float, float)}.
+ */
+ public final float[/*per-eye*/][/*xy*/] pupilCenterFromTopLeft;
+ public final int[] eyeRenderOrder;
+ public final EyeParameter[] defaultEyeParam;
+ public final DistortionMesh.Producer distortionMeshProducer;
+
+ public final int supportedDistortionBits;
+ public final int recommendedDistortionBits;
+ public final int minimumDistortionBits;
+ }
+
+ /** A mono view configuration, only one eye is supported */
+ public static final Config config01Mono01;
+
+ /** A default stereo SBS view configuration */
+ public static final Config config02StereoSBS01;
+
+ /** A default stereo SBS lense view configuration, utilizing similar settings as OculusVR DK1 */
+ public static final Config config03StereoSBSLense01;
+
+ private static final Config[] configs;
+
+ static {
+ final float[] DEFAULT_EYE_POSITION_OFFSET_STEREO_LENSES = { 0.0f, 1.6f, -5.0f }; // 1.6 up, 5 forward
+ final float[] DEFAULT_EYE_POSITION_OFFSET_STEREO = { 0.0f, 0.3f, 3.0f }; // 0.3 up, 3 back
+ final float[] DEFAULT_EYE_POSITION_OFFSET_MONO = { 0.0f, 0.0f, 3.0f }; // 3 back
+
+ final DimensionImmutable surfaceSizeInPixel = new Dimension(1280, 800);
+ final float[] screenSizeInMeters = new float[] { 0.1498f, 0.0936f };
+ final float interpupillaryDistanceInMeters = 0.0635f;
+ final float pupilCenterFromScreenTopInMeters = screenSizeInMeters[1] / 2f;
+ final float d2r = FloatUtil.PI / 180.0f;
+ {
+ config01Mono01 = new Config(
+ "Def01Mono01",
+ ShutterType.RollingTopToBottom,
+ surfaceSizeInPixel, // resolution
+ screenSizeInMeters, // screenSize [m]
+ surfaceSizeInPixel, // eye textureSize
+ pupilCenterFromScreenTopInMeters, // pupilCenterFromScreenTop [m]
+ interpupillaryDistanceInMeters, // IPD [m]
+ new int[] { 0 }, // eye order
+ new EyeParameter[] {
+ new EyeParameter(0, DEFAULT_EYE_POSITION_OFFSET_MONO,
+ // degrees: 45/2 l, 45/2 r, 45/2 * aspect t, 45/2 * aspect b
+ FovHVHalves.byFovyRadianAndAspect(45f*d2r, 1280f / 800f),
+ 0f /* distNoseToPupil */, 0f /* verticalDelta */, 0f /* eyeReliefInMeters */) },
+ null, // mash producer distortion bits
+ 0, // supported distortion bits
+ 0, // recommended distortion bits
+ 0 // minimum distortion bits
+ );
+ }
+
+ {
+ final DimensionImmutable eyeTextureSize = new Dimension(surfaceSizeInPixel.getWidth()/2, surfaceSizeInPixel.getHeight());
+ final float[] horizPupilCenterFromLeft = Config.getHorizPupilCenterFromLeft(screenSizeInMeters[0], interpupillaryDistanceInMeters);
+ final float vertPupilCenterFromTop = Config.getVertPupilCenterFromTop(screenSizeInMeters[1], pupilCenterFromScreenTopInMeters);
+ final float fovy = 45f;
+ final float aspect = (float)eyeTextureSize.getWidth() / (float)eyeTextureSize.getHeight();
+ final FovHVHalves defaultSBSEyeFovLeft = FovHVHalves.byFovyRadianAndAspect(fovy * d2r, vertPupilCenterFromTop, aspect, horizPupilCenterFromLeft[0]);
+ final FovHVHalves defaultSBSEyeFovRight = FovHVHalves.byFovyRadianAndAspect(fovy * d2r, vertPupilCenterFromTop, aspect, horizPupilCenterFromLeft[1]);
+
+ config02StereoSBS01 = new Config(
+ "Def02StereoSBS01",
+ ShutterType.RollingTopToBottom,
+ surfaceSizeInPixel, // resolution
+ screenSizeInMeters, // screenSize [m]
+ eyeTextureSize, // eye textureSize
+ pupilCenterFromScreenTopInMeters, // pupilCenterFromScreenTop [m]
+ interpupillaryDistanceInMeters, // IPD [m]
+ new int[] { 0, 1 }, // eye order
+ new EyeParameter[] {
+ new EyeParameter(0, DEFAULT_EYE_POSITION_OFFSET_STEREO, defaultSBSEyeFovLeft,
+ 0.032f /* distNoseToPupil */, 0f /* verticalDelta */, 0.010f /* eyeReliefInMeters */),
+ new EyeParameter(1, DEFAULT_EYE_POSITION_OFFSET_STEREO, defaultSBSEyeFovRight,
+ -0.032f /* distNoseToPupil */, 0f /* verticalDelta */, 0.010f /* eyeReliefInMeters */) },
+ null, // mash producer distortion bits
+ 0, // supported distortion bits
+ 0, // recommended distortion bits
+ 0 // minimum distortion bits
+ );
+ }
+
+ {
+ DistortionMesh.Producer lenseDistMeshProduce = null;
+ try {
+ lenseDistMeshProduce =
+ (DistortionMesh.Producer)
+ ReflectionUtil.createInstance("jogamp.opengl.oculusvr.stereo.lense.DistortionMeshProducer", GenericStereoDevice.class.getClassLoader());
+ } catch (final Throwable t) {
+ if(StereoDevice.DEBUG) { System.err.println("Caught: "+t.getMessage()); t.printStackTrace(); }
+ }
+
+ final DimensionImmutable eyeTextureSize = new Dimension(1122, 1553);
+ final float[] horizPupilCenterFromLeft = Config.getHorizPupilCenterFromLeft(screenSizeInMeters[0], interpupillaryDistanceInMeters);
+ final float vertPupilCenterFromTop = Config.getVertPupilCenterFromTop(screenSizeInMeters[1], pupilCenterFromScreenTopInMeters);
+ final float fovy = 129f;
+ final float aspect = (float)eyeTextureSize.getWidth() / (float)eyeTextureSize.getHeight();
+ final FovHVHalves defaultSBSEyeFovLenseLeft = FovHVHalves.byFovyRadianAndAspect(fovy * d2r, vertPupilCenterFromTop, aspect, horizPupilCenterFromLeft[0]);
+ final FovHVHalves defaultSBSEyeFovLenseRight = FovHVHalves.byFovyRadianAndAspect(fovy * d2r, vertPupilCenterFromTop, aspect, horizPupilCenterFromLeft[1]);
+
+ config03StereoSBSLense01 = null == lenseDistMeshProduce ? null :
+ new Config(
+ "Def03StereoSBSLense01",
+ ShutterType.RollingTopToBottom,
+ surfaceSizeInPixel, // resolution
+ screenSizeInMeters, // screenSize [m]
+ eyeTextureSize, // eye textureSize
+ pupilCenterFromScreenTopInMeters, // pupilCenterFromScreenTop [m]
+ interpupillaryDistanceInMeters, // IPD [m]
+ new int[] { 0, 1 }, // eye order
+ new EyeParameter[] {
+ new EyeParameter(0, DEFAULT_EYE_POSITION_OFFSET_STEREO_LENSES, defaultSBSEyeFovLenseLeft,
+ 0.032f /* distNoseToPupil */, 0f /* verticalDelta */, 0.010f /* eyeReliefInMeters */),
+ new EyeParameter(1, DEFAULT_EYE_POSITION_OFFSET_STEREO_LENSES, defaultSBSEyeFovLenseRight,
+ -0.032f /* distNoseToPupil */, 0f /* verticalDelta */, 0.010f /* eyeReliefInMeters */) },
+ lenseDistMeshProduce,
+ // supported distortion bits
+ StereoDeviceRenderer.DISTORTION_BARREL | StereoDeviceRenderer.DISTORTION_CHROMATIC | StereoDeviceRenderer.DISTORTION_VIGNETTE,
+ // recommended distortion bits
+ StereoDeviceRenderer.DISTORTION_BARREL | StereoDeviceRenderer.DISTORTION_CHROMATIC | StereoDeviceRenderer.DISTORTION_VIGNETTE,
+ // minimum distortion bits
+ StereoDeviceRenderer.DISTORTION_BARREL
+ );
+ }
+ configs = new Config[] { config01Mono01, config02StereoSBS01, config03StereoSBSLense01 };
+ }
+
+ private final StereoDeviceFactory factory;
+ public final int deviceIndex;
+ public final Config config;
+
+ public final Point surfacePos;
+ private final FovHVHalves[] defaultEyeFov;
+
+ private boolean sensorsStarted = false;
+
+ public GenericStereoDevice(final StereoDeviceFactory factory, final int deviceIndex, final StereoDevice.Config customConfig) {
+ this.factory = factory;
+ this.deviceIndex = deviceIndex;
+
+ if( customConfig instanceof GenericStereoDevice.Config) {
+ this.config = (GenericStereoDevice.Config) customConfig;
+ } else {
+ final int cfgIdx = Math.min(deviceIndex % 10, configs.length-1);
+ this.config = null != configs[cfgIdx] ? configs[cfgIdx] : config02StereoSBS01;
+ }
+ config.init();
+
+ this.surfacePos = new Point(0, 0);
+
+ defaultEyeFov = new FovHVHalves[config.defaultEyeParam.length];
+ for(int i=0; i<defaultEyeFov.length; i++) {
+ defaultEyeFov[i] = config.defaultEyeParam[i].fovhv;
+ }
+ }
+
+ @Override
+ public final StereoDeviceFactory getFactory() { return factory; }
+
+ @Override
+ public String toString() {
+ return "GenericStereoDevice["+config+", surfacePos "+surfacePos+"]";
+ }
+
+ public void setSurfacePosition(final int x, final int y) {
+ surfacePos.set(x, y);
+ }
+
+ @Override
+ public final void dispose() {
+ // NOP
+ }
+
+ @Override
+ public final PointImmutable getPosition() {
+ return surfacePos;
+ }
+
+ @Override
+ public final DimensionImmutable getSurfaceSize() {
+ return config.surfaceSizeInPixels;
+ }
+
+ @Override
+ public float[] getDefaultEyePositionOffset() {
+ return config.defaultEyeParam[0].positionOffset;
+ }
+
+ @Override
+ public final FovHVHalves[] getDefaultFOV() {
+ return defaultEyeFov;
+ }
+
+ @Override
+ public final boolean startSensors(final boolean start) {
+ if( start && !sensorsStarted ) {
+ if( startSensorsImpl(true) ) {
+ sensorsStarted = true;
+ return true;
+ } else {
+ sensorsStarted = false;
+ return false;
+ }
+ } else if( sensorsStarted ) {
+ if( startSensorsImpl(false) ) {
+ sensorsStarted = false;
+ return true;
+ } else {
+ sensorsStarted = true;
+ return false;
+ }
+ } else {
+ // No state change -> Success
+ return true;
+ }
+ }
+ private boolean startSensorsImpl(final boolean start) { return start; }
+
+ @Override
+ public boolean getSensorsStarted() { return sensorsStarted; }
+
+ @Override
+ public int[] getEyeRenderOrder() { return config.eyeRenderOrder; }
+
+ @Override
+ public int getSupportedDistortionBits() {
+ return config.supportedDistortionBits;
+ };
+
+ @Override
+ public int getRecommendedDistortionBits() {
+ return config.recommendedDistortionBits;
+ }
+
+ @Override
+ public int getMinimumDistortionBits() {
+ return config.minimumDistortionBits;
+ }
+
+ @Override
+ public final StereoDeviceRenderer createRenderer(final int distortionBits,
+ final int textureCount, final float[] eyePositionOffset,
+ final FovHVHalves[] eyeFov, final float pixelsPerDisplayPixel, final int textureUnit) {
+ final EyeParameter[] eyeParam = new EyeParameter[eyeFov.length];
+ for(int i=0; i<eyeParam.length; i++) {
+ final EyeParameter defaultEyeParam = config.defaultEyeParam[i];
+ eyeParam[i] = new EyeParameter(i, eyePositionOffset, eyeFov[i],
+ defaultEyeParam.distNoseToPupilX, defaultEyeParam.distMiddleToPupilY, defaultEyeParam.eyeReliefZ);
+ }
+
+ final boolean usePP = null != config.distortionMeshProducer && 0 != distortionBits; // use post-processing
+
+ final RectangleImmutable[] eyeViewports = new RectangleImmutable[eyeParam.length];
+ final DimensionImmutable eyeTextureSize = config.eyeTextureSize;
+ final DimensionImmutable totalTextureSize;
+ if( 1 < eyeParam.length ) {
+ // Stereo SBS
+ totalTextureSize = new Dimension(eyeTextureSize.getWidth()*2, eyeTextureSize.getHeight());
+
+ if( 1 == textureCount ) { // validated in ctor below!
+ eyeViewports[0] = new Rectangle(0, 0,
+ eyeTextureSize.getWidth(), eyeTextureSize.getHeight());
+
+ eyeViewports[1] = new Rectangle(eyeTextureSize.getWidth(), 0,
+ eyeTextureSize.getWidth(), eyeTextureSize.getHeight());
+ } else {
+ eyeViewports[0] = new Rectangle(0, 0, eyeTextureSize.getWidth(), eyeTextureSize.getHeight());
+ if( usePP ) {
+ eyeViewports[1] = eyeViewports[0];
+ } else {
+ eyeViewports[1] = new Rectangle(eyeTextureSize.getWidth(), 0,
+ eyeTextureSize.getWidth(), eyeTextureSize.getHeight());
+ }
+ }
+ } else {
+ // Mono
+ totalTextureSize = eyeTextureSize;
+ eyeViewports[0] = new Rectangle(0, 0, eyeTextureSize.getWidth(), eyeTextureSize.getHeight());
+ }
+ return new GenericStereoDeviceRenderer(this, distortionBits, textureCount, eyePositionOffset, eyeParam, pixelsPerDisplayPixel, textureUnit,
+ eyeTextureSize, totalTextureSize, eyeViewports);
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceFactory.java b/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceFactory.java
new file mode 100644
index 000000000..f2fa74743
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceFactory.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.stereo;
+
+import com.jogamp.opengl.util.stereo.StereoDevice;
+import com.jogamp.opengl.util.stereo.StereoDeviceFactory;
+
+public class GenericStereoDeviceFactory extends StereoDeviceFactory {
+
+ public static boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public final StereoDevice createDevice(final int deviceIndex, final StereoDevice.Config config, final boolean verbose) {
+ return new GenericStereoDevice(this, deviceIndex, config);
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceRenderer.java b/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceRenderer.java
new file mode 100644
index 000000000..d957bd4e7
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/GenericStereoDeviceRenderer.java
@@ -0,0 +1,605 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.stereo;
+
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLArrayData;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+
+import jogamp.common.os.PlatformPropsImpl;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.stereo.EyeParameter;
+import com.jogamp.opengl.util.stereo.EyePose;
+import com.jogamp.opengl.util.stereo.StereoDevice;
+import com.jogamp.opengl.util.stereo.StereoDeviceRenderer;
+import com.jogamp.opengl.util.stereo.StereoUtil;
+
+/**
+ * Generic Stereo Device Distortion and OpenGL Renderer Utility
+ */
+public class GenericStereoDeviceRenderer implements StereoDeviceRenderer {
+ private static final String shaderPrefix01 = "dist01";
+ private static final String shaderTimewarpSuffix = "_timewarp";
+ private static final String shaderChromaSuffix = "_chroma";
+ private static final String shaderPlainSuffix = "_plain";
+
+ public static class GenericEye implements StereoDeviceRenderer.Eye {
+ private final int eyeName;
+ private final int distortionBits;
+ private final int vertexCount;
+ private final int indexCount;
+ private final RectangleImmutable viewport;
+
+ private final GLUniformData eyeToSourceUVScale;
+ private final GLUniformData eyeToSourceUVOffset;
+ private final GLUniformData eyeRotationStart;
+ private final GLUniformData eyeRotationEnd;
+
+ /** 2+2+2+2+2: { vec2 position, vec2 color, vec2 texCoordR, vec2 texCoordG, vec2 texCoordB } */
+ private final GLArrayDataServer iVBO;
+ private final GLArrayData vboPos, vboParams, vboTexCoordsR, vboTexCoordsG, vboTexCoordsB;
+ private final GLArrayDataServer indices;
+
+ private final EyeParameter eyeParameter;
+
+ private final EyePose eyePose;
+
+ @Override
+ public final RectangleImmutable getViewport() { return viewport; }
+
+ @Override
+ public final EyeParameter getEyeParameter() { return eyeParameter; }
+
+ @Override
+ public final EyePose getLastEyePose() { return eyePose; }
+
+ private GenericEye(final GenericStereoDevice device, final int distortionBits,
+ final float[] eyePositionOffset, final EyeParameter eyeParam,
+ final DimensionImmutable textureSize, final RectangleImmutable eyeViewport) {
+ this.eyeName = eyeParam.number;
+ this.distortionBits = distortionBits;
+ this.viewport = eyeViewport;
+
+ final boolean usePP = null != device.config.distortionMeshProducer && 0 != distortionBits;
+
+ final boolean usesTimewarp = usePP && StereoUtil.usesTimewarpDistortion(distortionBits);
+ final FloatBuffer fstash = Buffers.newDirectFloatBuffer( 2 + 2 + ( usesTimewarp ? 16 + 16 : 0 ) ) ;
+
+ if( usePP ) {
+ eyeToSourceUVScale = new GLUniformData("svr_EyeToSourceUVScale", 2, Buffers.slice2Float(fstash, 0, 2));
+ eyeToSourceUVOffset = new GLUniformData("svr_EyeToSourceUVOffset", 2, Buffers.slice2Float(fstash, 2, 2));
+ } else {
+ eyeToSourceUVScale = null;
+ eyeToSourceUVOffset = null;
+ }
+
+ if( usesTimewarp ) {
+ eyeRotationStart = new GLUniformData("svr_EyeRotationStart", 4, 4, Buffers.slice2Float(fstash, 4, 16));
+ eyeRotationEnd = new GLUniformData("svr_EyeRotationEnd", 4, 4, Buffers.slice2Float(fstash, 20, 16));
+ } else {
+ eyeRotationStart = null;
+ eyeRotationEnd = null;
+ }
+
+ this.eyeParameter = eyeParam;
+
+ this.eyePose = new EyePose(eyeName);
+
+ updateEyePose(device); // 1st init
+
+ // Setup: eyeToSourceUVScale, eyeToSourceUVOffset
+ if( usePP ) {
+ final ScaleAndOffset2D textureScaleAndOffset = new ScaleAndOffset2D(eyeParam.fovhv, textureSize, eyeViewport);
+ if( StereoDevice.DEBUG ) {
+ System.err.println("XXX."+eyeName+": eyeParam "+eyeParam);
+ System.err.println("XXX."+eyeName+": uvScaleOffset "+textureScaleAndOffset);
+ System.err.println("XXX."+eyeName+": textureSize "+textureSize);
+ System.err.println("XXX."+eyeName+": viewport "+eyeViewport);
+ }
+ final FloatBuffer eyeToSourceUVScaleFB = eyeToSourceUVScale.floatBufferValue();
+ eyeToSourceUVScaleFB.put(0, textureScaleAndOffset.scale[0]);
+ eyeToSourceUVScaleFB.put(1, textureScaleAndOffset.scale[1]);
+ final FloatBuffer eyeToSourceUVOffsetFB = eyeToSourceUVOffset.floatBufferValue();
+ eyeToSourceUVOffsetFB.put(0, textureScaleAndOffset.offset[0]);
+ eyeToSourceUVOffsetFB.put(1, textureScaleAndOffset.offset[1]);
+ } else {
+ vertexCount = 0;
+ indexCount = 0;
+ iVBO = null;
+ vboPos = null;
+ vboParams = null;
+ vboTexCoordsR = null;
+ vboTexCoordsG = null;
+ vboTexCoordsB = null;
+ indices = null;
+ if( StereoDevice.DEBUG ) {
+ System.err.println("XXX."+eyeName+": "+this);
+ }
+ return;
+ }
+ final DistortionMesh meshData = device.config.distortionMeshProducer.create(eyeParam, distortionBits);
+ if( null == meshData ) {
+ throw new GLException("Failed to create meshData for eye "+eyeParam+", and "+StereoUtil.distortionBitsToString(distortionBits));
+ }
+
+ vertexCount = meshData.vertexCount;
+ indexCount = meshData.indexCount;
+
+ /** 2+2+2+2+2: { vec2 position, vec2 color, vec2 texCoordR, vec2 texCoordG, vec2 texCoordB } */
+ final boolean useChromatic = StereoUtil.usesChromaticDistortion(distortionBits);
+ final boolean useVignette = StereoUtil.usesVignetteDistortion(distortionBits);
+
+ final int compsPerElement = 2+2+2+( useChromatic ? 2+2 /* texCoordG + texCoordB */: 0 );
+ iVBO = GLArrayDataServer.createGLSLInterleaved(compsPerElement, GL.GL_FLOAT, false, vertexCount, GL.GL_STATIC_DRAW);
+ vboPos = iVBO.addGLSLSubArray("svr_Position", 2, GL.GL_ARRAY_BUFFER);
+ vboParams = iVBO.addGLSLSubArray("svr_Params", 2, GL.GL_ARRAY_BUFFER);
+ vboTexCoordsR = iVBO.addGLSLSubArray("svr_TexCoordR", 2, GL.GL_ARRAY_BUFFER);
+ if( useChromatic ) {
+ vboTexCoordsG = iVBO.addGLSLSubArray("svr_TexCoordG", 2, GL.GL_ARRAY_BUFFER);
+ vboTexCoordsB = iVBO.addGLSLSubArray("svr_TexCoordB", 2, GL.GL_ARRAY_BUFFER);
+ } else {
+ vboTexCoordsG = null;
+ vboTexCoordsB = null;
+ }
+ indices = GLArrayDataServer.createData(1, GL.GL_SHORT, indexCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
+
+ /** 2+2+2+2+2: { vec2 position, vec2 color, vec2 texCoordR, vec2 texCoordG, vec2 texCoordB } */
+ final FloatBuffer iVBOFB = (FloatBuffer)iVBO.getBuffer();
+
+ for ( int vertNum = 0; vertNum < vertexCount; vertNum++ ) {
+ final DistortionMesh.DistortionVertex v = meshData.vertices[vertNum];
+ int dataIdx = 0;
+
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": START VERTEX "+vertNum+" / "+vertexCount);
+ }
+ // pos
+ if( v.pos_size >= 2 ) {
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": pos ["+v.data[dataIdx]+", "+v.data[dataIdx+1]+"]");
+ }
+ iVBOFB.put(v.data[dataIdx]);
+ iVBOFB.put(v.data[dataIdx+1]);
+ } else {
+ iVBOFB.put(0f);
+ iVBOFB.put(0f);
+ }
+ dataIdx += v.pos_size;
+
+ // params
+ if( v.vignetteFactor_size >= 1 && useVignette ) {
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": vignette "+v.data[dataIdx]);
+ }
+ iVBOFB.put(v.data[dataIdx]);
+ } else {
+ iVBOFB.put(1.0f);
+ }
+ dataIdx += v.vignetteFactor_size;
+
+ if( v.timewarpFactor_size >= 1 ) {
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": timewarp "+v.data[dataIdx]);
+ }
+ iVBOFB.put(v.data[dataIdx]);
+ } else {
+ iVBOFB.put(1.0f);
+ }
+ dataIdx += v.timewarpFactor_size;
+
+ // texCoordR
+ if( v.texR_size >= 2 ) {
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": texR ["+v.data[dataIdx]+", "+v.data[dataIdx+1]+"]");
+ }
+ iVBOFB.put(v.data[dataIdx]);
+ iVBOFB.put(v.data[dataIdx+1]);
+ } else {
+ iVBOFB.put(1f);
+ iVBOFB.put(1f);
+ }
+ dataIdx += v.texR_size;
+
+ if( useChromatic ) {
+ // texCoordG
+ if( v.texG_size >= 2 ) {
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": texG ["+v.data[dataIdx]+", "+v.data[dataIdx+1]+"]");
+ }
+ iVBOFB.put(v.data[dataIdx]);
+ iVBOFB.put(v.data[dataIdx+1]);
+ } else {
+ iVBOFB.put(1f);
+ iVBOFB.put(1f);
+ }
+ dataIdx += v.texG_size;
+
+ // texCoordB
+ if( v.texB_size >= 2 ) {
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": texB ["+v.data[dataIdx]+", "+v.data[dataIdx+1]+"]");
+ }
+ iVBOFB.put(v.data[dataIdx]);
+ iVBOFB.put(v.data[dataIdx+1]);
+ } else {
+ iVBOFB.put(1f);
+ iVBOFB.put(1f);
+ }
+ dataIdx += v.texB_size;
+ } else {
+ dataIdx += v.texG_size;
+ dataIdx += v.texB_size;
+ }
+ }
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": iVBO "+iVBO);
+ }
+ {
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": idx "+indices+", count "+indexCount);
+ for(int i=0; i< indexCount; i++) {
+ if( 0 == i % 16 ) {
+ System.err.printf("%n%5d: ", i);
+ }
+ System.err.printf("%5d, ", (int)meshData.indices[i]);
+ }
+ System.err.println();
+ }
+ final ShortBuffer out = (ShortBuffer) indices.getBuffer();
+ out.put(meshData.indices, 0, meshData.indexCount);
+ }
+ if( StereoDevice.DEBUG ) {
+ System.err.println("XXX."+eyeName+": "+this);
+ }
+ }
+
+ private void linkData(final GL2ES2 gl, final ShaderProgram sp) {
+ if( null == iVBO ) return;
+
+ if( 0 > vboPos.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+vboPos);
+ }
+ if( 0 > vboParams.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+vboParams);
+ }
+ if( 0 > vboTexCoordsR.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+vboTexCoordsR);
+ }
+ if( StereoUtil.usesChromaticDistortion(distortionBits) ) {
+ if( 0 > vboTexCoordsG.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+vboTexCoordsG);
+ }
+ if( 0 > vboTexCoordsB.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+vboTexCoordsB);
+ }
+ }
+ if( 0 > eyeToSourceUVScale.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+eyeToSourceUVScale);
+ }
+ if( 0 > eyeToSourceUVOffset.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+eyeToSourceUVOffset);
+ }
+ if( StereoUtil.usesTimewarpDistortion(distortionBits) ) {
+ if( 0 > eyeRotationStart.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+eyeRotationStart);
+ }
+ if( 0 > eyeRotationEnd.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+eyeRotationEnd);
+ }
+ }
+ iVBO.seal(gl, true);
+ iVBO.enableBuffer(gl, false);
+ indices.seal(gl, true);
+ indices.enableBuffer(gl, false);
+ }
+
+ private void dispose(final GL2ES2 gl) {
+ if( null == iVBO ) return;
+ iVBO.destroy(gl);
+ indices.destroy(gl);
+ }
+ private void enableVBO(final GL2ES2 gl, final boolean enable) {
+ if( null == iVBO ) return;
+ iVBO.enableBuffer(gl, enable);
+ indices.bindBuffer(gl, enable); // keeps VBO binding if enable:=true
+ }
+
+ private void updateUniform(final GL2ES2 gl, final ShaderProgram sp) {
+ if( null == iVBO ) return;
+ gl.glUniform(eyeToSourceUVScale);
+ gl.glUniform(eyeToSourceUVOffset);
+ if( StereoUtil.usesTimewarpDistortion(distortionBits) ) {
+ gl.glUniform(eyeRotationStart);
+ gl.glUniform(eyeRotationEnd);
+ }
+ }
+
+ /**
+ * Updates {@link #ovrEyePose} and it's extracted
+ * {@link #eyeRenderPoseOrientation} and {@link #eyeRenderPosePosition}.
+ * @param hmdCtx used get the {@link #ovrEyePose} via {@link OVR#ovrHmd_GetEyePose(OvrHmdContext, int)}
+ */
+ private EyePose updateEyePose(final GenericStereoDevice hmdCtx) {
+ return eyePose;
+ }
+
+ @Override
+ public String toString() {
+ final String ppTxt = null == iVBO ? ", no post-processing" :
+ ", uvScale["+eyeToSourceUVScale.floatBufferValue().get(0)+", "+eyeToSourceUVScale.floatBufferValue().get(1)+
+ "], uvOffset["+eyeToSourceUVOffset.floatBufferValue().get(0)+", "+eyeToSourceUVOffset.floatBufferValue().get(1)+"]";
+
+ return "Eye["+eyeName+", viewport "+viewport+
+ ", "+eyeParameter+
+ ", vertices "+vertexCount+", indices "+indexCount+
+ ppTxt+
+ ", desc"+eyeParameter+", "+eyePose+"]";
+ }
+ }
+
+ private final GenericStereoDevice device;
+ private final GenericEye[] eyes;
+ private final int distortionBits;
+ private final int textureCount;
+ private final DimensionImmutable singleTextureSize;
+ private final DimensionImmutable totalTextureSize;
+ /** if texUnit0 is null: no post-processing */
+ private final GLUniformData texUnit0;
+
+ private ShaderProgram sp;
+ private long frameStart = 0;
+
+ @Override
+ public String toString() {
+ return "GenericStereo[distortion["+StereoUtil.distortionBitsToString(distortionBits)+
+ "], singleSize "+singleTextureSize+
+ ", sbsSize "+totalTextureSize+
+ ", texCount "+textureCount+", texUnit "+(null != texUnit0 ? texUnit0.intValue() : "n/a")+
+ ", "+PlatformPropsImpl.NEWLINE+" "+(0 < eyes.length ? eyes[0] : "none")+
+ ", "+PlatformPropsImpl.NEWLINE+" "+(1 < eyes.length ? eyes[1] : "none")+"]";
+ }
+
+
+ private static final DimensionImmutable zeroSize = new Dimension(0, 0);
+
+ /* pp */ GenericStereoDeviceRenderer(final GenericStereoDevice context, final int distortionBits,
+ final int textureCount, final float[] eyePositionOffset,
+ final EyeParameter[] eyeParam, final float pixelsPerDisplayPixel, final int textureUnit,
+ final DimensionImmutable singleTextureSize, final DimensionImmutable totalTextureSize,
+ final RectangleImmutable[] eyeViewports) {
+ this.device = context;
+ this.eyes = new GenericEye[eyeParam.length];
+ this.distortionBits = ( distortionBits | context.getMinimumDistortionBits() ) & context.getSupportedDistortionBits();
+ final boolean usePP = null != device.config.distortionMeshProducer && 0 != this.distortionBits;
+ final DimensionImmutable textureSize;
+
+ if( usePP ) {
+ if( 1 > textureCount || 2 < textureCount ) {
+ this.textureCount = 2;
+ } else {
+ this.textureCount = textureCount;
+ }
+ this.singleTextureSize = singleTextureSize;
+ this.totalTextureSize = totalTextureSize;
+ textureSize = 1 == textureCount ? totalTextureSize : singleTextureSize;
+ texUnit0 = new GLUniformData("svr_Texture0", textureUnit);
+ } else {
+ this.textureCount = 0;
+ this.singleTextureSize = zeroSize;
+ this.totalTextureSize = zeroSize;
+ textureSize = zeroSize;
+ texUnit0 = null;
+ }
+ for(int i=0; i<eyeParam.length; i++) {
+ eyes[i] = new GenericEye(context, this.distortionBits, eyePositionOffset, eyeParam[i], textureSize, eyeViewports[i]);
+ }
+ sp = null;
+ }
+
+ @Override
+ public StereoDevice getDevice() { return device; }
+
+ @Override
+ public final int getDistortionBits() { return distortionBits; }
+
+ @Override
+ public final boolean usesSideBySideStereo() { return true; }
+
+ @Override
+ public final DimensionImmutable getSingleSurfaceSize() { return singleTextureSize; }
+
+ @Override
+ public final DimensionImmutable getTotalSurfaceSize() { return totalTextureSize; }
+
+ @Override
+ public final int getTextureCount() { return textureCount; }
+
+ @Override
+ public final int getTextureUnit() { return ppAvailable() ? texUnit0.intValue() : 0; }
+
+ @Override
+ public final boolean ppAvailable() { return null != texUnit0; }
+
+ @Override
+ public final void init(final GL gl) {
+ if( StereoDevice.DEBUG ) {
+ System.err.println(JoglVersion.getGLInfo(gl, null).toString());
+ }
+ if( null != sp ) {
+ throw new IllegalStateException("Already initialized");
+ }
+ if( !ppAvailable() ) {
+ return;
+ }
+ final GL2ES2 gl2es2 = gl.getGL2ES2();
+
+ final String vertexShaderBasename;
+ final String fragmentShaderBasename;
+ {
+ final boolean usesTimewarp = StereoUtil.usesTimewarpDistortion(distortionBits);
+ final boolean usesChromatic = StereoUtil.usesChromaticDistortion(distortionBits);
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append(shaderPrefix01);
+ if( !usesChromatic && !usesTimewarp ) {
+ sb.append(shaderPlainSuffix);
+ } else if( usesChromatic && !usesTimewarp ) {
+ sb.append(shaderChromaSuffix);
+ } else if( usesTimewarp ) {
+ sb.append(shaderTimewarpSuffix);
+ if( usesChromatic ) {
+ sb.append(shaderChromaSuffix);
+ }
+ }
+ vertexShaderBasename = sb.toString();
+ sb.setLength(0);
+ sb.append(shaderPrefix01);
+ if( usesChromatic ) {
+ sb.append(shaderChromaSuffix);
+ } else {
+ sb.append(shaderPlainSuffix);
+ }
+ fragmentShaderBasename = sb.toString();
+ }
+ final ShaderCode vp0 = ShaderCode.create(gl2es2, GL2ES2.GL_VERTEX_SHADER, GenericStereoDeviceRenderer.class, "shader",
+ "shader/bin", vertexShaderBasename, true);
+ final ShaderCode fp0 = ShaderCode.create(gl2es2, GL2ES2.GL_FRAGMENT_SHADER, GenericStereoDeviceRenderer.class, "shader",
+ "shader/bin", fragmentShaderBasename, true);
+ vp0.defaultShaderCustomization(gl2es2, true, true);
+ fp0.defaultShaderCustomization(gl2es2, true, true);
+
+ sp = new ShaderProgram();
+ sp.add(gl2es2, vp0, System.err);
+ sp.add(gl2es2, fp0, System.err);
+ if(!sp.link(gl2es2, System.err)) {
+ throw new GLException("could not link program: "+sp);
+ }
+ sp.useProgram(gl2es2, true);
+ if( 0 > texUnit0.setLocation(gl2es2, sp.program()) ) {
+ throw new GLException("Couldn't locate "+texUnit0);
+ }
+ for(int i=0; i<eyes.length; i++) {
+ eyes[i].linkData(gl2es2, sp);
+ }
+ sp.useProgram(gl2es2, false);
+ }
+
+ @Override
+ public final void dispose(final GL gl) {
+ final GL2ES2 gl2es2 = gl.getGL2ES2();
+ if( null != sp ) {
+ sp.useProgram(gl2es2, false);
+ }
+ for(int i=0; i<eyes.length; i++) {
+ eyes[i].dispose(gl2es2);
+ }
+ if( null != sp ) {
+ sp.destroy(gl2es2);
+ }
+ }
+
+ @Override
+ public final Eye getEye(final int eyeNum) {
+ return eyes[eyeNum];
+ }
+
+ @Override
+ public final EyePose updateEyePose(final int eyeNum) {
+ return eyes[eyeNum].updateEyePose(device);
+ }
+
+ @Override
+ public final void beginFrame(final GL gl) {
+ frameStart = Platform.currentTimeMillis();
+ }
+
+ @Override
+ public final void endFrame(final GL gl) {
+ if( 0 == frameStart ) {
+ throw new IllegalStateException("beginFrame not called");
+ }
+ frameStart = 0;
+ }
+
+ @Override
+ public final void ppBegin(final GL gl) {
+ if( null == sp ) {
+ throw new IllegalStateException("Not initialized");
+ }
+ if( 0 == frameStart ) {
+ throw new IllegalStateException("beginFrame not called");
+ }
+ final GL2ES2 gl2es2 = gl.getGL2ES2();
+
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + getTextureUnit());
+
+ gl2es2.glDisable(GL.GL_CULL_FACE);
+ gl2es2.glDisable(GL.GL_DEPTH_TEST);
+ gl2es2.glDisable(GL.GL_BLEND);
+
+ if( !gl2es2.isGLcore() ) {
+ gl2es2.glEnable(GL.GL_TEXTURE_2D);
+ }
+
+ sp.useProgram(gl2es2, true);
+
+ gl2es2.glUniform(texUnit0);
+ }
+
+ @Override
+ public final void ppOneEye(final GL gl, final int eyeNum) {
+ final GenericEye eye = eyes[eyeNum];
+ final GL2ES2 gl2es2 = gl.getGL2ES2();
+
+ eye.updateUniform(gl2es2, sp);
+ eye.enableVBO(gl2es2, true);
+ gl2es2.glDrawElements(GL.GL_TRIANGLES, eye.indexCount, GL.GL_UNSIGNED_SHORT, 0);
+ eyes[eyeNum].enableVBO(gl2es2, false);
+ }
+
+ @Override
+ public final void ppEnd(final GL gl) {
+ sp.useProgram(gl.getGL2ES2(), false);
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/ScaleAndOffset2D.java b/src/jogl/classes/jogamp/opengl/util/stereo/ScaleAndOffset2D.java
new file mode 100644
index 000000000..ce154e03e
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/ScaleAndOffset2D.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.stereo;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import com.jogamp.opengl.math.FovHVHalves;
+import com.jogamp.opengl.math.VectorUtil;
+
+/**
+ * 2D scale and offset NDC class,
+ * providing conversion from {@link FovHVHalves} in tangent to NDC space.
+ * <p>
+ * See <a href="https://www.opengl.org/wiki/Compute_eye_space_from_window_space">OpenGL.org: Compute eye space from window space</a>
+ * </p>
+ */
+public final class ScaleAndOffset2D {
+ /** Scale for x- and y-component. */
+ final float[] scale;
+ /** Offset for x- and y-component. */
+ final float[] offset;
+
+ private static final float[] vec2Half = new float[] { 0.5f, 0.5f };
+
+ public String toString() {
+ return "[offset "+offset[0]+" / "+offset[1]+", scale "+scale[0]+" x "+scale[1]+"]";
+ }
+
+ public ScaleAndOffset2D(final float[] scale, final float[] offset) {
+ this.scale = scale;
+ this.offset = offset;
+ }
+
+ /**
+ * Create the <i>Normalized Device Coordinate Space</i> (NDC) [-1,+1] instance
+ * from the given <code>fovHVHalves</code>.
+ */
+ public ScaleAndOffset2D(final FovHVHalves fovHVHalves) {
+ final FovHVHalves tanFovHVHalves = fovHVHalves.toTangents();
+ final float projXScale = 2.0f / ( tanFovHVHalves.left+ tanFovHVHalves.right);
+ final float projYScale = 2.0f / ( tanFovHVHalves.top + tanFovHVHalves.bottom );
+ final float projXOffset = ( tanFovHVHalves.left - tanFovHVHalves.right ) * projXScale * 0.5f;
+ final float projYOffset = ( tanFovHVHalves.top - tanFovHVHalves.bottom ) * projYScale * 0.5f;
+
+ this.scale = new float[] { projXScale, projYScale };
+ this.offset = new float[] { projXOffset, projYOffset };
+ }
+
+ /**
+ * Create the <i>Normalized Device Coordinate Space</i> (NDC) [-1,+1] instance
+ * from the given <code>fovHVHalves</code>, for the subsection of the <code>render-viewport</code> within the <code>rendertarget-size</code>.
+ */
+ public ScaleAndOffset2D(final FovHVHalves fovHVHalves, final DimensionImmutable rendertargetSize, final RectangleImmutable renderViewport) {
+ final ScaleAndOffset2D eyeToSourceNDC = new ScaleAndOffset2D(fovHVHalves);
+ final float[] vec2Tmp1 = new float[2];
+ final float[] vec2Tmp2 = new float[2];
+ final float[] scale = VectorUtil.scaleVec2(vec2Tmp1, eyeToSourceNDC.scale, 0.5f);
+ final float[] offset = VectorUtil.addVec2(vec2Tmp2, VectorUtil.scaleVec2(vec2Tmp2, eyeToSourceNDC.offset, 0.5f), vec2Half);
+
+ final float[] scale2 = new float[] { (float)renderViewport.getWidth() / (float)rendertargetSize.getWidth(),
+ (float)renderViewport.getHeight() / (float)rendertargetSize.getHeight() };
+
+ final float[] offset2 = new float[] { (float)renderViewport.getX() / (float)rendertargetSize.getWidth(),
+ (float)renderViewport.getY() / (float)rendertargetSize.getHeight() };
+
+ VectorUtil.scaleVec2(scale, scale, scale2);
+ VectorUtil.addVec2(offset, VectorUtil.scaleVec2(offset, offset, scale2), offset2);
+
+ this.scale = scale;
+ this.offset = offset;
+ }
+
+ /**
+ * Return the <i>tangent FOV space</i> of this <i>eye to source NDC</i> instance.
+ */
+ public final float[] convertToTanFovSpace(final float[] rendertargetNDC) {
+ final float[] vec2Tmp1 = new float[2];
+ return VectorUtil.divVec2(vec2Tmp1, VectorUtil.subVec2(vec2Tmp1, rendertargetNDC, this.offset), this.scale);
+ }
+
+} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.fp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.fp
new file mode 100644
index 000000000..4ac404729
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.fp
@@ -0,0 +1,26 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 svr_FragColor;
+ #define texture2D texture
+#else
+ #define svr_FragColor gl_FragColor
+#endif
+
+uniform sampler2D svr_Texture0;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+varying vec2 svv_TexCoordG;
+varying vec2 svv_TexCoordB;
+
+void main (void)
+{
+ // 3 samples for fixing chromatic aberrations
+ vec3 color = vec3(texture2D(svr_Texture0, svv_TexCoordR).r,
+ texture2D(svr_Texture0, svv_TexCoordG).g,
+ texture2D(svr_Texture0, svv_TexCoordB).b);
+ svr_FragColor = vec4(svv_Fade * color, 1.0); // include vignetteFade
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.vp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.vp
new file mode 100644
index 000000000..d4ab585d5
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.vp
@@ -0,0 +1,33 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 svr_EyeToSourceUVScale;
+uniform vec2 svr_EyeToSourceUVOffset;
+
+attribute vec2 svr_Position;
+attribute vec2 svr_Params;
+attribute vec2 svr_TexCoordR;
+attribute vec2 svr_TexCoordG;
+attribute vec2 svr_TexCoordB;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+varying vec2 svv_TexCoordG;
+varying vec2 svv_TexCoordB;
+
+void main(void)
+{
+ gl_Position = vec4(svr_Position.xy, 0.5, 1.0);
+ svv_Fade = vec3(svr_Params.r); // vignetteFade
+
+ svv_TexCoordR = svr_TexCoordR * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordR.y = 1.0-svv_TexCoordR.y;
+ svv_TexCoordG = svr_TexCoordG * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordG.y = 1.0-svv_TexCoordG.y;
+ svv_TexCoordB = svr_TexCoordB * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordB.y = 1.0-svv_TexCoordB.y;
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.fp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.fp
new file mode 100644
index 000000000..2df890648
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.fp
@@ -0,0 +1,22 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 svr_FragColor;
+ #define texture2D texture
+#else
+ #define svr_FragColor gl_FragColor
+#endif
+
+uniform sampler2D svr_Texture0;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+
+void main (void)
+{
+ // 3 samples for fixing chromatic aberrations
+ vec3 color = texture2D(svr_Texture0, svv_TexCoordR).rgb;
+ svr_FragColor = vec4(svv_Fade * color, 1.0); // include vignetteFade
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.vp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.vp
new file mode 100644
index 000000000..335d3f0f6
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.vp
@@ -0,0 +1,27 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 svr_EyeToSourceUVScale;
+uniform vec2 svr_EyeToSourceUVOffset;
+
+attribute vec2 svr_Position;
+attribute vec2 svr_Params;
+attribute vec2 svr_TexCoordR;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+
+void main(void)
+{
+ gl_Position = vec4(svr_Position.xy, 0.5, 1.0);
+ svv_Fade = vec3(svr_Params.r); // vignetteFade
+
+ // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+ // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+ svv_TexCoordR = svr_TexCoordR * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordR.y = 1.0-svv_TexCoordR.y;
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp.vp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp.vp
new file mode 100644
index 000000000..c4461ec3e
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp.vp
@@ -0,0 +1,44 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 svr_EyeToSourceUVScale;
+uniform vec2 svr_EyeToSourceUVOffset;
+uniform mat4 svr_EyeRotationStart;
+uniform mat4 svr_EyeRotationEnd;
+
+attribute vec2 svr_Position;
+attribute vec2 svr_Params;
+attribute vec2 svr_TexCoordR;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+
+void main(void)
+{
+ gl_Position = vec4(svr_Position.xy, 0.0, 1.0);
+ svv_Fade = vec3(svr_Params.r); // vignetteFade
+
+ // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+ // These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
+ vec3 TanEyeAngle = vec3 ( svr_TexCoordR, 1.0 );
+
+ // Accurate time warp lerp vs. faster
+ // Apply the two 3x3 timewarp rotations to these vectors.
+ vec3 TransformedStart = (svr_EyeRotationStart * vec4(TanEyeAngle, 0)).xyz;
+ vec3 TransformedEnd = (svr_EyeRotationEnd * vec4(TanEyeAngle, 0)).xyz;
+ // And blend between them.
+ vec3 Transformed = mix ( TransformedStart, TransformedEnd, svr_Params.g /* timewarpLerpFactor */ );
+
+ // Project them back onto the Z=1 plane of the rendered images.
+ float RecipZ = 1.0 / Transformed.z;
+ vec2 Flattened = vec2 ( Transformed.x * RecipZ, Transformed.y * RecipZ );
+
+ // These are now still in TanEyeAngle space.
+ // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+ svv_TexCoordR = Flattened * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordR.y = 1.0-svv_TexCoordR.y;
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp_chroma.vp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp_chroma.vp
new file mode 100644
index 000000000..c08ed3113
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp_chroma.vp
@@ -0,0 +1,65 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 svr_EyeToSourceUVScale;
+uniform vec2 svr_EyeToSourceUVOffset;
+uniform mat4 svr_EyeRotationStart;
+uniform mat4 svr_EyeRotationEnd;
+
+attribute vec2 svr_Position;
+attribute vec2 svr_Params;
+attribute vec2 svr_TexCoordR;
+attribute vec2 svr_TexCoordG;
+attribute vec2 svr_TexCoordB;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+varying vec2 svv_TexCoordG;
+varying vec2 svv_TexCoordB;
+
+void main(void)
+{
+ gl_Position = vec4(svr_Position.xy, 0.0, 1.0);
+ svv_Fade = vec3(svr_Params.r); // vignetteFade
+
+ // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+ // These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
+ vec3 TanEyeAngleR = vec3 ( svr_TexCoordR, 1.0 );
+ vec3 TanEyeAngleG = vec3 ( svr_TexCoordG, 1.0 );
+ vec3 TanEyeAngleB = vec3 ( svr_TexCoordB, 1.0 );
+
+ // Accurate time warp lerp vs. faster
+ // Apply the two 3x3 timewarp rotations to these vectors.
+ vec3 TransformedRStart = (svr_EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;
+ vec3 TransformedGStart = (svr_EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;
+ vec3 TransformedBStart = (svr_EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;
+ vec3 TransformedREnd = (svr_EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;
+ vec3 TransformedGEnd = (svr_EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;
+ vec3 TransformedBEnd = (svr_EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;
+
+ // And blend between them.
+ vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, svr_Params.g /* timewarpLerpFactor */ );
+ vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, svr_Params.g /* timewarpLerpFactor */ );
+ vec3 TransformedB = mix ( TransformedBStart, TransformedBEnd, svr_Params.g /* timewarpLerpFactor */ );
+
+ // Project them back onto the Z=1 plane of the rendered images.
+ float RecipZR = 1.0 / TransformedR.z;
+ float RecipZG = 1.0 / TransformedG.z;
+ float RecipZB = 1.0 / TransformedB.z;
+ vec2 FlattenedR = vec2 ( TransformedR.x * RecipZR, TransformedR.y * RecipZR );
+ vec2 FlattenedG = vec2 ( TransformedG.x * RecipZG, TransformedG.y * RecipZG );
+ vec2 FlattenedB = vec2 ( TransformedB.x * RecipZB, TransformedB.y * RecipZB );
+
+ // These are now still in TanEyeAngle space.
+ // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+ svv_TexCoordR = FlattenedR * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordR.y = 1.0-svv_TexCoordR.y;
+ svv_TexCoordG = FlattenedG * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordG.y = 1.0-svv_TexCoordG.y;
+ svv_TexCoordB = FlattenedB * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordB.y = 1.0-svv_TexCoordB.y;
+}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
index 6a4ce5a4e..25b73a2a6 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
@@ -28,6 +28,8 @@
package jogamp.opengl.windows.wgl;
+import java.nio.IntBuffer;
+
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
@@ -42,7 +44,7 @@ public class WGLGLCapabilities extends GLCapabilities {
final private int pfdID;
private int arb_pixelformat; // -1 PFD, 0 NOP, 1 ARB
- public WGLGLCapabilities(PIXELFORMATDESCRIPTOR pfd, int pfdID, GLProfile glp) {
+ public WGLGLCapabilities(final PIXELFORMATDESCRIPTOR pfd, final int pfdID, final GLProfile glp) {
super(glp);
this.pfd = pfd;
this.pfdID = pfdID;
@@ -56,17 +58,18 @@ public class WGLGLCapabilities extends GLCapabilities {
setRedBits(pfd.getCRedBits());
setGreenBits(pfd.getCGreenBits());
setBlueBits(pfd.getCBlueBits());
- setAlphaBits(pfd.getCAlphaBits());
+ setAlphaBits(pfd.getCAlphaBits());
setAccumRedBits(pfd.getCAccumRedBits());
setAccumGreenBits(pfd.getCAccumGreenBits());
setAccumBlueBits(pfd.getCAccumBlueBits());
setAccumAlphaBits(pfd.getCAccumAlphaBits());
setDepthBits(pfd.getCDepthBits());
setStencilBits(pfd.getCStencilBits());
- setDoubleBuffered((pfd.getDwFlags() & GDI.PFD_DOUBLEBUFFER) != 0);
- setStereo((pfd.getDwFlags() & GDI.PFD_STEREO) != 0);
- setHardwareAccelerated((pfd.getDwFlags() & GDI.PFD_GENERIC_FORMAT) == 0
- || (pfd.getDwFlags() & GDI.PFD_GENERIC_ACCELERATED) != 0);
+ final int dwFlags = pfd.getDwFlags();
+ setDoubleBuffered((dwFlags & GDI.PFD_DOUBLEBUFFER) != 0);
+ setStereo((dwFlags & GDI.PFD_STEREO) != 0);
+ setHardwareAccelerated((dwFlags & GDI.PFD_GENERIC_FORMAT) == 0
+ || (dwFlags & GDI.PFD_GENERIC_ACCELERATED) != 0);
// n/a with non ARB/GDI method:
// multisample
// opaque
@@ -75,12 +78,49 @@ public class WGLGLCapabilities extends GLCapabilities {
return true;
}
- public boolean setValuesByARB(final int[] iattribs, final int niattribs, final int[] iresults) {
+ public static final String PFD2String(final PIXELFORMATDESCRIPTOR pfd, final int pfdID) {
+ final int dwFlags = pfd.getDwFlags();
+ final StringBuilder sb = new StringBuilder();
+ boolean sep = false;
+
+ if( 0 != (GDI.PFD_DRAW_TO_WINDOW & dwFlags ) ) {
+ sep = true;
+ sb.append("window");
+ }
+ if( 0 != (GDI.PFD_DRAW_TO_BITMAP & dwFlags ) ) {
+ if(sep) { sb.append(CSEP); } sep=true;
+ sb.append("bitmap");
+ }
+ if( 0 != (GDI.PFD_SUPPORT_OPENGL & dwFlags ) ) {
+ if(sep) { sb.append(CSEP); } sep=true;
+ sb.append("opengl");
+ }
+ if( 0 != (GDI.PFD_DOUBLEBUFFER & dwFlags ) ) {
+ if(sep) { sb.append(CSEP); } sep=true;
+ sb.append("dblbuf");
+ }
+ if( 0 != (GDI.PFD_STEREO & dwFlags ) ) {
+ if(sep) { sb.append(CSEP); } sep=true;
+ sb.append("stereo");
+ }
+ if( 0 == (GDI.PFD_GENERIC_FORMAT & dwFlags ) || 0 == (GDI.PFD_GENERIC_ACCELERATED & dwFlags ) ) {
+ if(sep) { sb.append(CSEP); } sep=true;
+ sb.append("hw-accel");
+ }
+ return "PFD[id = "+pfdID+" (0x"+Integer.toHexString(pfdID)+
+ "), colorBits "+pfd.getCColorBits()+", rgba "+pfd.getCRedBits()+ESEP+pfd.getCGreenBits()+ESEP+pfd.getCBlueBits()+ESEP+pfd.getCAlphaBits()+
+ ", accum-rgba "+pfd.getCAccumRedBits()+ESEP+pfd.getCAccumGreenBits()+ESEP+pfd.getCAccumBlueBits()+ESEP+pfd.getCAccumAlphaBits()+
+ ", dp/st/ms: "+pfd.getCDepthBits()+ESEP+pfd.getCStencilBits()+ESEP+"0"+
+ ", flags: "+sb.toString();
+ }
+
+ public boolean setValuesByARB(final IntBuffer iattribs, final int niattribs, final IntBuffer iresults) {
arb_pixelformat = 1;
int alphaBits = 0;
for (int i = 0; i < niattribs; i++) {
- int attr = iattribs[i];
+ final int attr = iattribs.get(i);
+ final int res = iresults.get(i);
switch (attr) {
case WGLExt.WGL_DRAW_TO_WINDOW_ARB:
case WGLExt.WGL_DRAW_TO_BITMAP_ARB:
@@ -88,93 +128,87 @@ public class WGLGLCapabilities extends GLCapabilities {
break;
case WGLExt.WGL_ACCELERATION_ARB:
- setHardwareAccelerated(iresults[i] == WGLExt.WGL_FULL_ACCELERATION_ARB);
+ setHardwareAccelerated(res == WGLExt.WGL_FULL_ACCELERATION_ARB);
break;
case WGLExt.WGL_SUPPORT_OPENGL_ARB:
- if (iresults[i] != GL.GL_TRUE) {
+ if (res != GL.GL_TRUE) {
return false;
}
break;
case WGLExt.WGL_DEPTH_BITS_ARB:
- setDepthBits(iresults[i]);
+ setDepthBits(res);
break;
case WGLExt.WGL_STENCIL_BITS_ARB:
- setStencilBits(iresults[i]);
+ setStencilBits(res);
break;
case WGLExt.WGL_DOUBLE_BUFFER_ARB:
- setDoubleBuffered(iresults[i] == GL.GL_TRUE);
+ setDoubleBuffered(res == GL.GL_TRUE);
break;
case WGLExt.WGL_STEREO_ARB:
- setStereo(iresults[i] == GL.GL_TRUE);
+ setStereo(res == GL.GL_TRUE);
break;
case WGLExt.WGL_PIXEL_TYPE_ARB:
- if(iresults[i] == WGLExt.WGL_TYPE_COLORINDEX_ARB) {
+ if(res == WGLExt.WGL_TYPE_COLORINDEX_ARB) {
return false; // color index not supported
}
- if (iresults[i] == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) {
- setPbufferFloatingPointBuffers(true);
+ if (res == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) {
+ return false; // not supported
}
// normal RGBA FB: WGLExt.WGL_TYPE_RGBA_ARB
// ignore unknown results here
break;
- case WGLExt.WGL_FLOAT_COMPONENTS_NV:
- if (iresults[i] != 0) {
- setPbufferFloatingPointBuffers(true);
- }
- break;
-
case WGLExt.WGL_RED_BITS_ARB:
- setRedBits(iresults[i]);
+ setRedBits(res);
break;
case WGLExt.WGL_GREEN_BITS_ARB:
- setGreenBits(iresults[i]);
+ setGreenBits(res);
break;
case WGLExt.WGL_BLUE_BITS_ARB:
- setBlueBits(iresults[i]);
+ setBlueBits(res);
break;
case WGLExt.WGL_ALPHA_BITS_ARB:
// ALPHA shall be set at last - due to it's auto setting by !opaque / samples
- alphaBits = iresults[i];
+ alphaBits = res;
break;
case WGLExt.WGL_ACCUM_RED_BITS_ARB:
- setAccumRedBits(iresults[i]);
+ setAccumRedBits(res);
break;
case WGLExt.WGL_ACCUM_GREEN_BITS_ARB:
- setAccumGreenBits(iresults[i]);
+ setAccumGreenBits(res);
break;
case WGLExt.WGL_ACCUM_BLUE_BITS_ARB:
- setAccumBlueBits(iresults[i]);
+ setAccumBlueBits(res);
break;
case WGLExt.WGL_ACCUM_ALPHA_BITS_ARB:
- setAccumAlphaBits(iresults[i]);
+ setAccumAlphaBits(res);
break;
case WGLExt.WGL_SAMPLE_BUFFERS_ARB:
- setSampleBuffers(iresults[i] != 0);
+ setSampleBuffers(res != 0);
break;
case WGLExt.WGL_SAMPLES_ARB:
- setNumSamples(iresults[i]);
+ setNumSamples(res);
break;
default:
- throw new GLException("Unknown pixel format attribute " + iattribs[i]);
+ throw new GLException("Unknown pixel format attribute " + attr);
}
}
setAlphaBits(alphaBits);
@@ -190,7 +224,7 @@ public class WGLGLCapabilities extends GLCapabilities {
public Object clone() {
try {
return super.clone();
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
throw new GLException(e);
}
}
@@ -203,7 +237,7 @@ public class WGLGLCapabilities extends GLCapabilities {
final public boolean isSet() { return 0 != arb_pixelformat; }
@Override
- final public int getVisualID(VIDType type) throws NativeWindowException {
+ final public int getVisualID(final VIDType type) throws NativeWindowException {
switch(type) {
case INTRINSIC:
case NATIVE:
@@ -219,7 +253,7 @@ public class WGLGLCapabilities extends GLCapabilities {
if(null == sink) {
sink = new StringBuilder();
}
- sink.append("wgl vid 0x").append(Integer.toHexString(pfdID)).append(" ");
+ sink.append("wgl vid ").append(pfdID).append(" ");
switch (arb_pixelformat) {
case -1:
sink.append("gdi");
@@ -236,4 +270,4 @@ public class WGLGLCapabilities extends GLCapabilities {
sink.append(": ");
return super.toString(sink);
}
-} \ No newline at end of file
+}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java
index f1598d580..08ff0e05b 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java
@@ -27,21 +27,23 @@
*/
package jogamp.opengl.windows.wgl;
+import com.jogamp.common.util.PropertyAccess;
+
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
import jogamp.opengl.Debug;
public class WGLUtil {
/**
- * Switch to use the <code>wgl</code> variants of {@link jogamp.opengl.windows.wgl.WGL}
+ * Switch to use the <code>wgl</code> variants of {@link jogamp.opengl.windows.wgl.WGL}
* to replace the following 5 GDI based functions (see below).
* <p>
* Disabled per default.
- * </p>
+ * </p>
* <p>
* You can enable it by defining the property <code>jogl.windows.useWGLVersionOf5WGLGDIFuncSet</code>.
* </p>
- *
+ *
* @see jogamp.nativewindow.windows.GDI#ChoosePixelFormat(long, PIXELFORMATDESCRIPTOR)
* @see jogamp.nativewindow.windows.GDI#DescribePixelFormat(long, int, int, PIXELFORMATDESCRIPTOR)
* @see jogamp.nativewindow.windows.GDI#GetPixelFormat(long)
@@ -49,47 +51,48 @@ public class WGLUtil {
* @see jogamp.nativewindow.windows.GDI#SwapBuffers(long)
*/
public static final boolean USE_WGLVersion_Of_5WGLGDIFuncSet;
-
+
static {
- USE_WGLVersion_Of_5WGLGDIFuncSet = Debug.isPropertyDefined("jogl.windows.useWGLVersionOf5WGLGDIFuncSet", true);
+ Debug.initSingleton();
+ USE_WGLVersion_Of_5WGLGDIFuncSet = PropertyAccess.isPropertyDefined("jogl.windows.useWGLVersionOf5WGLGDIFuncSet", true);
if(USE_WGLVersion_Of_5WGLGDIFuncSet) {
System.err.println("Use WGL version of 5 WGL/GDI functions.");
}
}
- public static int ChoosePixelFormat(long hdc, PIXELFORMATDESCRIPTOR pfd) {
+ public static int ChoosePixelFormat(final long hdc, final PIXELFORMATDESCRIPTOR pfd) {
if(USE_WGLVersion_Of_5WGLGDIFuncSet) {
return WGL.wglChoosePixelFormat(hdc, pfd);
} else {
return GDI.ChoosePixelFormat(hdc, pfd);
- }
+ }
}
- public static int DescribePixelFormat(long hdc, int pfdid, int pfdSize, PIXELFORMATDESCRIPTOR pfd) {
+ public static int DescribePixelFormat(final long hdc, final int pfdid, final int pfdSize, final PIXELFORMATDESCRIPTOR pfd) {
if(USE_WGLVersion_Of_5WGLGDIFuncSet) {
return WGL.wglDescribePixelFormat(hdc, pfdid, pfdSize, pfd);
} else {
return GDI.DescribePixelFormat(hdc, pfdid, pfdSize, pfd);
- }
+ }
}
- public static int GetPixelFormat(long hdc) {
+ public static int GetPixelFormat(final long hdc) {
if(USE_WGLVersion_Of_5WGLGDIFuncSet) {
return WGL.wglGetPixelFormat(hdc);
} else {
return GDI.GetPixelFormat(hdc);
- }
+ }
}
- public static boolean SetPixelFormat(long hdc, int pfdid, PIXELFORMATDESCRIPTOR pfd) {
+ public static boolean SetPixelFormat(final long hdc, final int pfdid, final PIXELFORMATDESCRIPTOR pfd) {
if(USE_WGLVersion_Of_5WGLGDIFuncSet) {
return WGL.wglSetPixelFormat(hdc, pfdid, pfd);
} else {
return GDI.SetPixelFormat(hdc, pfdid, pfd);
- }
+ }
}
- public static boolean SwapBuffers(long hdc) {
+ public static boolean SwapBuffers(final long hdc) {
if(USE_WGLVersion_Of_5WGLGDIFuncSet) {
return WGL.wglSwapBuffers(hdc);
} else {
return GDI.SwapBuffers(hdc);
- }
+ }
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
deleted file mode 100644
index 51341a098..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.windows.wgl;
-
-import javax.media.opengl.*;
-
-public class WindowsBitmapWGLContext extends WindowsWGLContext {
- public WindowsBitmapWGLContext(WindowsBitmapWGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public int getOffscreenContextPixelDataType() {
- return GL.GL_UNSIGNED_BYTE;
- }
-
- @Override
- public int getOffscreenContextReadBuffer() {
- // On Windows these contexts are always single-buffered
- return GL.GL_FRONT;
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- // We can take care of this in the DIB creation (see below)
- return false;
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
index cf6f43b1c..0878f186c 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
@@ -40,16 +40,19 @@
package jogamp.opengl.windows.wgl;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
import jogamp.nativewindow.windows.BITMAPINFO;
import jogamp.nativewindow.windows.BITMAPINFOHEADER;
import jogamp.nativewindow.windows.GDI;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
import com.jogamp.common.nio.PointerBuffer;
@@ -57,8 +60,28 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
private long origbitmap;
private long hbitmap;
- protected WindowsBitmapWGLDrawable(GLDrawableFactory factory, NativeSurface target) {
- super(factory, target, false);
+ private WindowsBitmapWGLDrawable(final GLDrawableFactory factory, final NativeSurface comp) {
+ super(factory, comp, false);
+ }
+
+ protected static WindowsBitmapWGLDrawable create(final GLDrawableFactory factory, final NativeSurface comp) {
+ final WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)comp.getGraphicsConfiguration();
+ final AbstractGraphicsDevice aDevice = config.getScreen().getDevice();
+ if( !GLProfile.isAvailable(aDevice, GLProfile.GL2) ) {
+ throw new GLException("GLProfile GL2 n/a on "+aDevice+" but required for Windows BITMAP");
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilitiesImmutable capsChosen0 = (GLCapabilitiesImmutable)config.getChosenCapabilities();
+ // RGB555 and also alpha channel is experienced to fail on some Windows machines
+ final GLCapabilitiesImmutable capsChosen1 = GLGraphicsConfigurationUtil.clipRGBAGLCapabilities(capsChosen0, false /* allowRGB555 */, false /* allowAlpha */);
+ final GLCapabilitiesImmutable capsChosen2 = GLGraphicsConfigurationUtil.fixGLProfile(capsChosen1, glp);
+ if( capsChosen0 != capsChosen2 ) {
+ config.setChosenCapabilities(capsChosen2);
+ if(DEBUG) {
+ System.err.println("WindowsBitmapWGLDrawable: "+capsChosen0+" -> "+capsChosen2);
+ }
+ }
+ return new WindowsBitmapWGLDrawable(factory, comp);
}
@Override
@@ -71,35 +94,43 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new WindowsBitmapWGLContext(this, shareWith);
+ public GLContext createContext(final GLContext shareWith) {
+ return new WindowsWGLContext(this, shareWith);
+ }
+
+ @Override
+ public boolean isGLOriented() {
+ return false;
}
private void createBitmap() {
int werr;
- NativeSurface ns = getNativeSurface();
+ final NativeSurface ns = getNativeSurface();
if(DEBUG) {
- System.err.println("WindowsBitmapWGLDrawable (1): "+ns);
+ System.err.println(getThreadName()+": WindowsBitmapWGLDrawable (1): "+ns);
}
- WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
- GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getRequestedCapabilities();
- int width = getWidth();
- int height = getHeight();
+ final WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
+ final GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable)config.getChosenCapabilities();
+ final int width = getSurfaceWidth();
+ final int height = getSurfaceHeight();
//
// 1. Create DIB Section
//
- BITMAPINFO info = BITMAPINFO.create();
- BITMAPINFOHEADER header = info.getBmiHeader();
- int bitsPerPixel = (capabilities.getRedBits() +
- capabilities.getGreenBits() +
- capabilities.getBlueBits() +
- capabilities.getAlphaBits());
+ final BITMAPINFO info = BITMAPINFO.create();
+ final BITMAPINFOHEADER header = info.getBmiHeader();
+ final int bitsPerPixelIn = capsChosen.getRedBits() +
+ capsChosen.getGreenBits() +
+ capsChosen.getBlueBits();
+ final int bitsPerPixel;
+ // Note: For BITMAP 32 bpp, the high-byte is _not_ used and hence maximum color is RGB888!
+ // Note: For BITAMP a biBitCount value other than 24 (RGB888) usually does not work!
+ bitsPerPixel = 24; // RGB888 only!
header.setBiSize(BITMAPINFOHEADER.size());
header.setBiWidth(width);
- // NOTE: negating the height causes the DIB to be in top-down row
- // order rather than bottom-up; ends up being correct during pixel
- // readback
+ // NOTE: Positive height causes the DIB's origin at bottom-left (OpenGL),
+ // a negative height causes the DIB's origin at top-left (Java AWT, Windows, ..).
+ // We use !OpenGL origin to remove the need for vertical flip, see 'isGLOriented()' above.
header.setBiHeight(-1 * height);
header.setBiPlanes((short) 1);
header.setBiBitCount((short) bitsPerPixel);
@@ -108,21 +139,21 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
header.setBiClrUsed(0);
header.setBiClrImportant(0);
header.setBiCompression(GDI.BI_RGB);
- int byteNum = width * height * ( bitsPerPixel >> 3 ) ;
+ final int byteNum = width * height * ( bitsPerPixel >> 3 ) ;
header.setBiSizeImage(byteNum);
- PointerBuffer pb = PointerBuffer.allocateDirect(1);
+ final PointerBuffer pb = PointerBuffer.allocateDirect(1);
hbitmap = GDI.CreateDIBSection(0, info, GDI.DIB_RGB_COLORS, pb, 0, 0);
werr = GDI.GetLastError();
if(DEBUG) {
- long p = ( pb.capacity() > 0 ) ? pb.get(0) : 0;
+ final long p = ( pb.capacity() > 0 ) ? pb.get(0) : 0;
System.err.println("WindowsBitmapWGLDrawable: pb sz/ptr "+pb.capacity() + ", "+toHexString(p));
System.err.println("WindowsBitmapWGLDrawable: " + width+"x"+height +
- ", bpp " + bitsPerPixel +
+ ", bpp " + bitsPerPixelIn + " -> " + bitsPerPixel +
", bytes " + byteNum +
", header sz " + BITMAPINFOHEADER.size() +
", DIB ptr num " + pb.capacity()+
- ", "+capabilities+
+ ", "+capsChosen+
", werr "+werr);
}
if (hbitmap == 0) {
@@ -141,7 +172,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
}
((MutableSurface)ns).setSurfaceHandle(hdc);
if(DEBUG) {
- System.err.println("WindowsBitmapWGLDrawable (2): "+ns);
+ System.err.println(getThreadName()+": WindowsBitmapWGLDrawable (2): "+ns);
}
if ((origbitmap = GDI.SelectObject(hdc, hbitmap)) == 0) {
@@ -156,7 +187,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
}
protected void destroyBitmap() {
- NativeSurface ns = getNativeSurface();
+ final NativeSurface ns = getNativeSurface();
if (ns.getSurfaceHandle() != 0) {
// Must destroy bitmap and device context
GDI.SelectObject(ns.getSurfaceHandle(), origbitmap);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
index f6cc2956d..4cebc6357 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
@@ -50,26 +50,26 @@ import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
-
import jogamp.nativewindow.WrappedSurface;
import jogamp.nativewindow.windows.GDI;
import jogamp.opengl.GLContextShareSet;
public class WindowsExternalWGLContext extends WindowsWGLContext {
- private GLContext lastContext;
- private WindowsExternalWGLContext(Drawable drawable, long ctx, WindowsWGLGraphicsConfiguration cfg) {
+ private WindowsExternalWGLContext(final Drawable drawable, final long ctx, final WindowsWGLGraphicsConfiguration cfg) {
super(drawable, null);
this.contextHandle = ctx;
if (DEBUG) {
System.err.println(getThreadName() + ": Created external OpenGL context " + toHexString(ctx) + " for " + this);
}
GLContextShareSet.contextCreated(this);
- setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+ if( !setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION
+ throw new InternalError("setGLFunctionAvailability !strictMatch failed");
+ }
getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
}
- protected static WindowsExternalWGLContext create(GLDrawableFactory factory, GLProfile glp) {
+ protected static WindowsExternalWGLContext create(final GLDrawableFactory factory, final GLProfile glp) {
if(DEBUG) {
System.err.println("WindowsExternalWGLContext 0: werr: " + GDI.GetLastError());
}
@@ -83,7 +83,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
if (0 == hdc) {
throw new GLException("Error: attempted to make an external GLDrawable without a drawable current, werr " + GDI.GetLastError());
}
- AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
+ final AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
WindowsWGLGraphicsConfiguration cfg;
final int pfdID = WGLUtil.GetPixelFormat(hdc);
if (0 == pfdID) {
@@ -106,25 +106,6 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
}
@Override
- public int makeCurrent() throws GLException {
- // Save last context if necessary to allow external GLContexts to
- // talk to other GLContexts created by this library
- GLContext cur = getCurrent();
- if (cur != null && cur != this) {
- lastContext = cur;
- setCurrent(null);
- }
- return super.makeCurrent();
- }
-
- @Override
- public void release() throws GLException {
- super.release();
- setCurrent(lastContext);
- lastContext = null;
- }
-
- @Override
protected void makeCurrentImpl() throws GLException {
}
@@ -138,26 +119,26 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
// Need to provide the display connection to extension querying APIs
static class Drawable extends WindowsWGLDrawable {
- Drawable(GLDrawableFactory factory, NativeSurface comp) {
+ Drawable(final GLDrawableFactory factory, final NativeSurface comp) {
super(factory, comp, true);
}
@Override
- public GLContext createContext(GLContext shareWith) {
+ public GLContext createContext(final GLContext shareWith) {
throw new GLException("Should not call this");
}
@Override
- public int getWidth() {
+ public int getSurfaceWidth() {
throw new GLException("Should not call this");
}
@Override
- public int getHeight() {
+ public int getSurfaceHeight() {
throw new GLException("Should not call this");
}
- public void setSize(int width, int height) {
+ public void setSize(final int width, final int height) {
throw new GLException("Should not call this");
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java
index f8c237c9e..1378bcf3e 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java
@@ -51,21 +51,20 @@ import javax.media.opengl.GLProfile;
import jogamp.nativewindow.WrappedSurface;
import jogamp.nativewindow.windows.GDI;
-import jogamp.nativewindow.windows.GDIUtil;
public class WindowsExternalWGLDrawable extends WindowsWGLDrawable {
- private WindowsExternalWGLDrawable(GLDrawableFactory factory, NativeSurface component) {
+ private WindowsExternalWGLDrawable(final GLDrawableFactory factory, final NativeSurface component) {
super(factory, component, true);
}
- protected static WindowsExternalWGLDrawable create(GLDrawableFactory factory, GLProfile glp) {
- long hdc = WGL.wglGetCurrentDC();
+ protected static WindowsExternalWGLDrawable create(final GLDrawableFactory factory, final GLProfile glp) {
+ final long hdc = WGL.wglGetCurrentDC();
if (0==hdc) {
throw new GLException("Error: attempted to make an external GLDrawable without a drawable current, werr " + GDI.GetLastError());
}
- int pfdID = WGLUtil.GetPixelFormat(hdc);
+ final int pfdID = WGLUtil.GetPixelFormat(hdc);
if (pfdID == 0) {
throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat, werr " + GDI.GetLastError());
}
@@ -77,21 +76,21 @@ public class WindowsExternalWGLDrawable extends WindowsWGLDrawable {
@Override
- public GLContext createContext(GLContext shareWith) {
+ public GLContext createContext(final GLContext shareWith) {
return new WindowsWGLContext(this, shareWith);
}
- public void setSize(int newWidth, int newHeight) {
+ public void setSize(final int newWidth, final int newHeight) {
throw new GLException("Should not call this");
}
@Override
- public int getWidth() {
+ public int getSurfaceWidth() {
throw new GLException("Should not call this");
}
@Override
- public int getHeight() {
+ public int getSurfaceHeight() {
throw new GLException("Should not call this");
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java
deleted file mode 100644
index aef55efc6..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.windows.wgl;
-
-import javax.media.opengl.*;
-
-public class WindowsOnscreenWGLContext extends WindowsWGLContext {
- public WindowsOnscreenWGLContext(WindowsOnscreenWGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java
index ddbb29d51..0d0681df9 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java
@@ -45,13 +45,13 @@ import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
public class WindowsOnscreenWGLDrawable extends WindowsWGLDrawable {
- protected WindowsOnscreenWGLDrawable(GLDrawableFactory factory, NativeSurface component) {
+ protected WindowsOnscreenWGLDrawable(final GLDrawableFactory factory, final NativeSurface component) {
super(factory, component, false);
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new WindowsOnscreenWGLContext(this, shareWith);
+ public GLContext createContext(final GLContext shareWith) {
+ return new WindowsWGLContext(this, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
deleted file mode 100644
index 7dda6a1f1..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.windows.wgl;
-
-import javax.media.opengl.*;
-
-import com.jogamp.opengl.GLExtensions;
-
-import jogamp.opengl.GLContextImpl;
-
-public class WindowsPbufferWGLContext extends WindowsWGLContext {
- // State for render-to-texture and render-to-texture-rectangle support
- private boolean rtt; // render-to-texture?
- private boolean hasRTT; // render-to-texture extension available?
- private boolean rect; // render-to-texture-rectangle?
- private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV
- private int texture; // actual texture object
-
- protected WindowsPbufferWGLContext(WindowsPbufferWGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public void bindPbufferToTexture() {
- if (!rtt) {
- throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " +
- "specified in its GLCapabilities");
- }
- GL gl = getGL();
- WGLExt wglExt = getWGLExt();
- gl.glBindTexture(textureTarget, texture);
- if (rtt && hasRTT) {
- if (!wglExt.wglBindTexImageARB(((WindowsPbufferWGLDrawable)drawable).getPbufferHandle(), WGLExt.WGL_FRONT_LEFT_ARB)) {
- throw new GLException("Binding of pbuffer to texture failed: " + wglGetLastError());
- }
- }
- // FIXME: comment is wrong now
- // Note that if the render-to-texture extension is not supported,
- // we perform a glCopyTexImage2D in swapBuffers().
- }
-
- @Override
- public void releasePbufferFromTexture() {
- if (!rtt) {
- throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " +
- "specified in its GLCapabilities");
- }
- if (rtt && hasRTT) {
- WGLExt wglExt = getWGLExt();
- if (!wglExt.wglReleaseTexImageARB(((WindowsPbufferWGLDrawable)drawable).getPbufferHandle(), WGLExt.WGL_FRONT_LEFT_ARB)) {
- throw new GLException("Releasing of pbuffer from texture failed: " + wglGetLastError());
- }
- }
- }
-
- @Override
- protected boolean createImpl(GLContextImpl shareWith) {
- boolean res = super.createImpl(shareWith);
- if(res) {
- GLCapabilitiesImmutable capabilities = drawable.getChosenGLCapabilities();
-
- // Initialize render-to-texture support if requested
- GL gl = getGL();
- rtt = capabilities.getPbufferRenderToTexture();
- rect = gl.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle();
-
- if (rtt) {
- if (DEBUG) {
- System.err.println("Initializing render-to-texture support");
- }
-
- if (!gl.isExtensionAvailable("WGL_ARB_render_texture")) {
- System.err.println("WindowsPbufferWGLContext: WARNING: WGL_ARB_render_texture extension not " +
- "supported; implementing render_to_texture support using slow texture readback");
- } else {
- hasRTT = true;
-
- if (rect && !gl.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) {
- System.err.println("WindowsPbufferWGLContext: WARNING: GL_NV_texture_rectangle extension not " +
- "supported; skipping requested render_to_texture_rectangle support for pbuffer");
- rect = false;
- }
- if (rect) {
- if (DEBUG) {
- System.err.println(" Using render-to-texture-rectangle");
- }
- textureTarget = GL2GL3.GL_TEXTURE_RECTANGLE_ARB;
- } else {
- if (DEBUG) {
- System.err.println(" Using vanilla render-to-texture");
- }
- textureTarget = GL.GL_TEXTURE_2D;
- }
- int[] tmp = new int[1];
- gl.glGenTextures(1, tmp, 0);
- texture = tmp[0];
- gl.glBindTexture(textureTarget, texture);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
- gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0);
- }
- }
- }
- return res;
- }
-
- @Override
- public int getFloatingPointMode() {
- return ((WindowsPbufferWGLDrawable)drawable).getFloatingPointMode();
- }
-
- private static String wglGetLastError() {
- return WindowsWGLDrawableFactory.wglGetLastError();
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
index 75c1c4441..775e2936c 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
@@ -40,31 +40,32 @@
package jogamp.opengl.windows.wgl;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.MutableSurface;
-import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import com.jogamp.common.nio.Buffers;
+
import jogamp.nativewindow.windows.GDI;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.windows.wgl.WindowsWGLDrawableFactory.SharedResource;
-// import javax.media.opengl.GLPbuffer;
public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
private WGLExt cachedWGLExt; // cached WGLExt instance from parent GLCanvas,
// needed to destroy pbuffer
private long buffer; // pbuffer handle
- private int floatMode;
-
- protected WindowsPbufferWGLDrawable(GLDrawableFactory factory, NativeSurface target) {
+ protected WindowsPbufferWGLDrawable(final GLDrawableFactory factory, final NativeSurface target) {
super(factory, target, false);
}
@@ -78,14 +79,14 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new WindowsPbufferWGLContext(this, shareWith);
+ public GLContext createContext(final GLContext shareWith) {
+ return new WindowsWGLContext(this, shareWith);
}
protected void destroyPbuffer() {
- NativeSurface ns = getNativeSurface();
+ final NativeSurface ns = getNativeSurface();
if(0!=buffer) {
- WGLExt wglExt = cachedWGLExt;
+ final WGLExt wglExt = cachedWGLExt;
if (ns.getSurfaceHandle() != 0) {
// Must release DC and pbuffer
// NOTE that since the context is not current, glGetError() can
@@ -110,30 +111,26 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
return buffer;
}
- public int getFloatingPointMode() {
- return floatMode;
- }
-
private void createPbuffer() {
- WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration();
- SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(config.getScreen().getDevice());
- NativeSurface sharedSurface = sharedResource.getDrawable().getNativeSurface();
+ final WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration();
+ final SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResourceImpl(config.getScreen().getDevice());
+ final NativeSurface sharedSurface = sharedResource.getDrawable().getNativeSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY >= sharedSurface.lockSurface()) {
throw new NativeWindowException("Could not lock (sharedSurface): "+this);
}
try {
- long sharedHdc = sharedSurface.getSurfaceHandle();
- WGLExt wglExt = ((WindowsWGLContext)sharedResource.getContext()).getWGLExt();
+ final long sharedHdc = sharedSurface.getSurfaceHandle();
+ final WGLExt wglExt = ((WindowsWGLContext)sharedResource.getContext()).getWGLExt();
if (DEBUG) {
- System.out.println("Pbuffer config: " + config);
+ System.err.println(getThreadName()+": Pbuffer config: " + config);
}
final int winattrPbuffer = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(false /* onscreen */, false /* fbo */, true /* pbuffer */, false /* bitmap */);
-
- int[] iattributes = new int [2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS];
- float[] fattributes = new float[1];
- int[] floatModeTmp = new int[1];
+
+ final IntBuffer iattributes = Buffers.newDirectIntBuffer(2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS);
+ final FloatBuffer fattributes = Buffers.newDirectFloatBuffer(1);
+ final int[] floatModeTmp = new int[1];
int niattribs = 0;
final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
@@ -141,38 +138,23 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
final AbstractGraphicsDevice device = config.getScreen().getDevice();
if (DEBUG) {
- System.out.println("Pbuffer parentHdc = " + toHexString(sharedHdc));
- System.out.println("Pbuffer chosenCaps: " + chosenCaps);
+ System.err.println(getThreadName()+": Pbuffer parentHdc = " + toHexString(sharedHdc));
+ System.err.println(getThreadName()+": Pbuffer chosenCaps: " + chosenCaps);
}
- if(!WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(chosenCaps,
- iattributes, sharedResource, -1, floatModeTmp)){
+ if( !WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList( sharedResource, chosenCaps,
+ iattributes, -1, floatModeTmp) ) {
throw new GLException("Pbuffer-related extensions not supported");
}
- floatMode = floatModeTmp[0];
- boolean rtt = chosenCaps.getPbufferRenderToTexture();
- boolean rect = chosenCaps.getPbufferRenderToTextureRectangle();
- boolean useFloat = chosenCaps.getPbufferFloatingPointBuffers();
- // boolean ati = false;
-
- /**
- if (useFloat) {
- ati = (floatMode == GLPbuffer.ATI_FLOAT);
- } */
-
- int[] pformats = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS];
- int nformats;
- int[] nformatsTmp = new int[1];
+ final IntBuffer pformats = Buffers.newDirectIntBuffer(WindowsWGLGraphicsConfiguration.MAX_PFORMATS);
+ final IntBuffer nformatsTmp = Buffers.newDirectIntBuffer(1);
if (!wglExt.wglChoosePixelFormatARB(sharedHdc,
- iattributes, 0,
- fattributes, 0,
- WindowsWGLGraphicsConfiguration.MAX_PFORMATS,
- pformats, 0,
- nformatsTmp, 0)) {
+ iattributes, fattributes, WindowsWGLGraphicsConfiguration.MAX_PFORMATS,
+ pformats, nformatsTmp)) {
throw new GLException("pbuffer creation error: wglChoosePixelFormat() failed");
}
- nformats = nformatsTmp[0];
+ final int nformats = Math.min(nformatsTmp.get(0), WindowsWGLGraphicsConfiguration.MAX_PFORMATS);
if (nformats <= 0) {
throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format");
}
@@ -180,9 +162,9 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
if (DEBUG) {
System.err.println("" + nformats + " suitable pixel formats found");
for (int i = 0; i < nformats; i++) {
- WGLGLCapabilities dbgCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, device, glProfile,
- sharedHdc, pformats[i], winattrPbuffer);
- System.err.println("pixel format " + pformats[i] + " (index " + i + "): " + dbgCaps);
+ final WGLGLCapabilities dbgCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilitiesNoCheck(sharedResource, device, glProfile,
+ sharedHdc, pformats.get(i), winattrPbuffer);
+ System.err.println("pixel format " + pformats.get(i) + " (index " + i + "): " + dbgCaps);
}
}
@@ -192,32 +174,14 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
int whichFormat;
// Loop is a workaround for bugs in NVidia's recent drivers
for (whichFormat = 0; whichFormat < nformats; whichFormat++) {
- int format = pformats[whichFormat];
+ final int format = pformats.get(whichFormat);
// Create the p-buffer.
niattribs = 0;
- if (rtt) {
- iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FORMAT_ARB;
- if (useFloat) {
- iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FLOAT_RGB_NV;
- } else {
- iattributes[niattribs++] = WGLExt.WGL_TEXTURE_RGBA_ARB;
- }
-
- iattributes[niattribs++] = WGLExt.WGL_TEXTURE_TARGET_ARB;
- iattributes[niattribs++] = rect ? WGLExt.WGL_TEXTURE_RECTANGLE_NV : WGLExt.WGL_TEXTURE_2D_ARB;
-
- iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB;
- iattributes[niattribs++] = GL.GL_FALSE;
-
- iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; // exact
- iattributes[niattribs++] = GL.GL_FALSE;
- }
-
- iattributes[niattribs++] = 0;
+ iattributes.put(niattribs++, 0);
- tmpBuffer = wglExt.wglCreatePbufferARB(sharedHdc, format, getWidth(), getHeight(), iattributes, 0);
+ tmpBuffer = wglExt.wglCreatePbufferARB(sharedHdc, format, getSurfaceWidth(), getSurfaceHeight(), iattributes);
if (tmpBuffer != 0) {
// Done
break;
@@ -228,16 +192,16 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
throw new GLException("pbuffer creation error: wglCreatePbuffer() failed: tried " + nformats +
" pixel formats, last error was: " + wglGetLastError());
}
- pfdid = pformats[whichFormat];
+ pfdid = pformats.get(whichFormat);
}
// Get the device context.
- long tmpHdc = wglExt.wglGetPbufferDCARB(tmpBuffer);
+ final long tmpHdc = wglExt.wglGetPbufferDCARB(tmpBuffer);
if (tmpHdc == 0) {
throw new GLException("pbuffer creation error: wglGetPbufferDC() failed");
}
- NativeSurface ns = getNativeSurface();
+ final NativeSurface ns = getNativeSurface();
// Set up instance variables
buffer = tmpBuffer;
((MutableSurface)ns).setSurfaceHandle(tmpHdc);
@@ -245,7 +209,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
// Re-query chosen pixel format
{
- WGLGLCapabilities newCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, device, glProfile,
+ final WGLGLCapabilities newCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, device, glProfile,
sharedHdc, pfdid, winattrPbuffer);
if(null == newCaps) {
throw new GLException("pbuffer creation error: unable to re-query chosen PFD ID: " + pfdid + ", hdc " + GLDrawableImpl.toHexString(tmpHdc));
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index 8825bad0a..ebd107c47 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
@@ -41,6 +41,7 @@
package jogamp.opengl.windows.wgl;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;
@@ -50,10 +51,13 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
import jogamp.nativewindow.windows.GDI;
import jogamp.opengl.GLContextImpl;
@@ -84,13 +88,13 @@ public class WindowsWGLContext extends GLContextImpl {
}
// FIXME: figure out how to hook back in the Java 2D / JOGL bridge
- WindowsWGLContext(GLDrawableImpl drawable,
- GLContext shareWith) {
+ WindowsWGLContext(final GLDrawableImpl drawable,
+ final GLContext shareWith) {
super(drawable, shareWith);
}
@Override
- protected void resetStates() {
+ protected void resetStates(final boolean isInit) {
wglGetExtensionsStringEXTInitialized=false;
wglGetExtensionsStringEXTAvailable=false;
wglGLReadDrawableAvailableSet=false;
@@ -99,7 +103,7 @@ public class WindowsWGLContext extends GLContextImpl {
wglExtProcAddressTable=null;
hasSwapIntervalSGI = 0;
hasSwapGroupNV = 0;
- super.resetStates();
+ super.resetStates(isInit);
}
@Override
@@ -120,9 +124,9 @@ public class WindowsWGLContext extends GLContextImpl {
@Override
public final boolean isGLReadDrawableAvailable() {
if(!wglGLReadDrawableAvailableSet && null != getWGLExtProcAddressTable()) {
- WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl();
- AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
- AbstractGraphicsDevice device = config.getScreen().getDevice();
+ final WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl();
+ final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
switch( factory.isReadDrawableAvailable(device) ) {
case 1:
wglGLReadDrawableAvailable = true;
@@ -137,7 +141,7 @@ public class WindowsWGLContext extends GLContextImpl {
return wglGLReadDrawableAvailable;
}
- private final boolean wglMakeContextCurrent(long hDrawDC, long hReadDC, long ctx) {
+ private final boolean wglMakeContextCurrent(final long hDrawDC, final long hReadDC, final long ctx) {
boolean ok = false;
if(wglGLReadDrawableAvailable) {
// needs initilized WGL ProcAddress table
@@ -148,9 +152,9 @@ public class WindowsWGLContext extends GLContextImpl {
// should not happen due to 'isGLReadDrawableAvailable()' query in GLContextImpl
throw new InternalError("Given readDrawable but no driver support");
}
- int werr = ( !ok ) ? GDI.GetLastError() : GDI.ERROR_SUCCESS;
+ final int werr = ( !ok ) ? GDI.GetLastError() : GDI.ERROR_SUCCESS;
if(DEBUG && !ok) {
- Throwable t = new Throwable ("Info: wglMakeContextCurrent draw "+
+ final Throwable t = new Throwable ("Info: wglMakeContextCurrent draw "+
GLContext.toHexString(hDrawDC) + ", read " + GLContext.toHexString(hReadDC) +
", ctx " + GLContext.toHexString(ctx) + ", werr " + werr);
t.printStackTrace();
@@ -179,26 +183,26 @@ public class WindowsWGLContext extends GLContextImpl {
protected Map<String, String> getExtensionNameMap() { return extensionNameMap; }
@Override
- protected void destroyContextARBImpl(long context) {
+ protected void destroyContextARBImpl(final long context) {
WGL.wglMakeCurrent(0, 0);
WGL.wglDeleteContext(context);
}
@Override
- protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) {
+ protected long createContextARBImpl(final long share, final boolean direct, final int ctp, final int major, final int minor) {
if( null == getWGLExtProcAddressTable()) {
updateGLXProcAddressTable();
}
- WGLExt _wglExt = getWGLExt();
+ final WGLExt _wglExt = getWGLExt();
if(DEBUG) {
System.err.println(getThreadName()+" - WindowWGLContext.createContextARBImpl: "+getGLVersion(major, minor, ctp, "@creation") +
", handle "+toHexString(drawable.getHandle()) + ", share "+toHexString(share)+", direct "+direct+
", wglCreateContextAttribsARB: "+toHexString(wglExtProcAddressTable._addressof_wglCreateContextAttribsARB));
}
- boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ;
- boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ;
- boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ;
+ final boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ;
+ final boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ;
+ final boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ;
long ctx=0;
@@ -207,7 +211,7 @@ public class WindowsWGLContext extends GLContextImpl {
/* WGLExt.WGL_CONTEXT_LAYER_PLANE_ARB, WGLExt.WGL_CONTEXT_LAYER_PLANE_ARB, */
- int attribs[] = {
+ final int attribs[] = {
/* 0 */ WGLExt.WGL_CONTEXT_MAJOR_VERSION_ARB, major,
/* 2 */ WGLExt.WGL_CONTEXT_MINOR_VERSION_ARB, minor,
/* 4 */ WGLExt.WGL_CONTEXT_FLAGS_ARB, 0,
@@ -216,7 +220,6 @@ public class WindowsWGLContext extends GLContextImpl {
};
if ( major > 3 || major == 3 && minor >= 2 ) {
- // FIXME: Verify with a None drawable binding (default framebuffer)
attribs[idx_profile+0] = WGLExt.WGL_CONTEXT_PROFILE_MASK_ARB;
if( ctBwdCompat ) {
attribs[idx_profile+1] = WGLExt.WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
@@ -235,10 +238,11 @@ public class WindowsWGLContext extends GLContextImpl {
}
try {
- ctx = _wglExt.wglCreateContextAttribsARB(drawable.getHandle(), share, attribs, 0);
- } catch (RuntimeException re) {
+ final IntBuffer attribsNIO = Buffers.newDirectIntBuffer(attribs);
+ ctx = _wglExt.wglCreateContextAttribsARB(drawable.getHandle(), share, attribsNIO);
+ } catch (final RuntimeException re) {
if(DEBUG) {
- Throwable t = new Throwable("Info: WindowWGLContext.createContextARBImpl wglCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re);
+ final Throwable t = new Throwable("Info: WindowWGLContext.createContextARBImpl wglCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re);
t.printStackTrace();
}
}
@@ -265,74 +269,93 @@ public class WindowsWGLContext extends GLContextImpl {
* called by {@link #makeCurrentImpl()}.
*/
@Override
- protected boolean createImpl(GLContextImpl shareWith) {
- AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
- AbstractGraphicsDevice device = config.getScreen().getDevice();
- WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl();
- WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device);
- GLCapabilitiesImmutable glCaps = drawable.getChosenGLCapabilities();
+ protected boolean createImpl(long shareWithHandle) {
+ final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
+ final WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl();
+ final WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContext(device);
+ final GLCapabilitiesImmutable glCaps = drawable.getChosenGLCapabilities();
isGLReadDrawableAvailable(); // trigger setup wglGLReadDrawableAvailable
- // Windows can set up sharing of display lists after creation time
- long share = 0;
- if (null != shareWith) {
- share = shareWith.getHandle();
- if (share == 0) {
- throw new GLException("GLContextShareSet returned an invalid OpenGL context");
- }
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": createImpl: START "+glCaps+", share "+toHexString(shareWithHandle));
}
boolean createContextARBTried = false;
- // utilize the shared context's GLXExt in case it was using the ARB method and it already exists
- if( null!=sharedContext && sharedContext.isCreatedWithARBMethod() ) {
- contextHandle = createContextARB(share, true);
+ // utilize the shared context's GLXExt in case it was using the ARB method and it already exists ; exclude BITMAP
+ if( null != sharedContext && sharedContext.isCreatedWithARBMethod() && !glCaps.isBitmap() ) {
+ if ( sharedContext.getRendererQuirks().exist( GLRendererQuirks.NeedCurrCtx4ARBCreateContext ) ) {
+ if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
+ throw new GLException("Could not make Shared Context current: "+sharedContext);
+ }
+ contextHandle = createContextARB(shareWithHandle, true);
+ sharedContext.release();
+ if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+ throw new GLException("Cannot make previous verified context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError());
+ }
+ } else {
+ contextHandle = createContextARB(shareWithHandle, true);
+ }
createContextARBTried = true;
- if (DEBUG && 0!=contextHandle) {
- System.err.println(getThreadName() + ": createImpl: OK (ARB, using sharedContext) share "+share);
+ if ( DEBUG && 0 != contextHandle ) {
+ System.err.println(getThreadName() + ": createImpl: OK (ARB, using sharedContext) share "+toHexString(shareWithHandle));
}
}
- long temp_ctx = 0;
- if(0==contextHandle) {
+ final long temp_ctx;
+ if( 0 == contextHandle ) {
// To use WGL_ARB_create_context, we have to make a temp context current,
// so we are able to use GetProcAddress
temp_ctx = WGL.wglCreateContext(drawable.getHandle());
- if (temp_ctx == 0) {
+ if ( 0 == temp_ctx ) {
throw new GLException("Unable to create temp OpenGL context for device context " + toHexString(drawable.getHandle()));
}
- if (!WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx)) {
+ if ( !WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx) ) {
throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: "+GDI.GetLastError());
}
- setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+ if( !setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, null == sharedContext /* withinGLVersionsMapping */) ) { // use GL_VERSION
+ throw new InternalError("setGLFunctionAvailability !strictMatch failed");
+ }
WGL.wglMakeCurrent(0, 0); // release temp context
- if( !createContextARBTried) {
+ if( !createContextARBTried ) {
// is*Available calls are valid since setGLFunctionAvailability(..) was called
- final boolean isProcCreateContextAttribsARBAvailable = isFunctionAvailable("wglCreateContextAttribsARB");
- final boolean isExtARBCreateContextAvailable = isExtensionAvailable("WGL_ARB_create_context");
- if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable ) {
+ final boolean isProcCreateContextAttribsARBAvailable;
+ final boolean isExtARBCreateContextAvailable;
+ if( !glCaps.isBitmap() ) { // exclude ARB if BITMAP
+ isProcCreateContextAttribsARBAvailable = isFunctionAvailable("wglCreateContextAttribsARB");
+ isExtARBCreateContextAvailable = isExtensionAvailable("WGL_ARB_create_context");
+ } else {
+ isProcCreateContextAttribsARBAvailable = false;
+ isExtARBCreateContextAvailable = false;
+ }
+ if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable && !GLProfile.disableOpenGLARBContext && !getRendererQuirks().exist( GLRendererQuirks.NoARBCreateContext ) ) {
// initial ARB context creation
- contextHandle = createContextARB(share, true);
+ contextHandle = createContextARB(shareWithHandle, true);
createContextARBTried=true;
if (DEBUG) {
- if(0!=contextHandle) {
- System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+share);
+ if( 0 != contextHandle ) {
+ System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+toHexString(shareWithHandle));
} else {
- System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+share);
+ System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+toHexString(shareWithHandle));
}
}
} else if (DEBUG) {
- System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+share+
- ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable);
+ System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+toHexString(shareWithHandle)+
+ ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+
+ ", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable+
+ ", disableOpenGLARBContext "+GLProfile.disableOpenGLARBContext);
}
}
+ } else {
+ temp_ctx = 0;
}
- if(0!=contextHandle) {
- share = 0; // mark as shared thx to the ARB create method
- if(0!=temp_ctx) {
+ if( 0 != contextHandle ) {
+ shareWithHandle = 0; // mark as shared thx to the ARB create method
+ if( 0 != temp_ctx ) {
WGL.wglMakeCurrent(0, 0);
WGL.wglDeleteContext(temp_ctx);
if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
@@ -340,32 +363,35 @@ public class WindowsWGLContext extends GLContextImpl {
}
}
} else {
- if(glCaps.getGLProfile().isGL3()) {
- WGL.wglMakeCurrent(0, 0);
- WGL.wglDeleteContext(temp_ctx);
- throw new GLException("WindowsWGLContext.createContext ctx !ARB, context > GL2 requested "+getGLVersion());
+ if( glCaps.getGLProfile().isGL3() && createContextARBTried ) {
+ // We shall not allow context creation >= GL3 w/ non ARB methods if ARB is used,
+ // otherwise context of similar profile but different creation method may not be share-able.
+ WGL.wglMakeCurrent(0, 0);
+ WGL.wglDeleteContext(temp_ctx);
+ throw new GLException(getThreadName()+": WindowsWGLContex.createContextImpl ctx !ARB but ARB is used, profile > GL2 requested (OpenGL >= 3.0.1). Requested: "+glCaps.getGLProfile()+", current: "+getGLVersion());
}
if(DEBUG) {
- System.err.println("WindowsWGLContext.createContext failed, fall back to !ARB context "+getGLVersion());
+ System.err.println("WindowsWGLContext.createContext ARB not used, fall back to !ARB context "+getGLVersion());
}
- // continue with temp context for GL < 3.0
+ // continue with temp context
contextHandle = temp_ctx;
- if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+ if ( !wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
WGL.wglMakeCurrent(0, 0);
WGL.wglDeleteContext(contextHandle);
throw new GLException("Error making old context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError());
}
- if(0!=share) {
+ if( 0 != shareWithHandle ) {
+ // Windows can set up sharing of display lists after creation time if using GDI
// Only utilize the classic GDI 'wglShareLists' shared context method
// for traditional non ARB context.
- if (!WGL.wglShareLists(share, contextHandle)) {
- throw new GLException("wglShareLists(" + toHexString(share) +
+ if ( !WGL.wglShareLists(shareWithHandle, contextHandle) ) {
+ throw new GLException("wglShareLists(" + toHexString(shareWithHandle) +
", " + toHexString(contextHandle) + ") failed: werr " + GDI.GetLastError());
}
}
if (DEBUG) {
- System.err.println(getThreadName() + ": createImpl: OK (old) share "+share);
+ System.err.println(getThreadName() + ": createImpl: OK (old) share "+toHexString(shareWithHandle));
}
}
@@ -376,7 +402,11 @@ public class WindowsWGLContext extends GLContextImpl {
protected void makeCurrentImpl() throws GLException {
if (WGL.wglGetCurrentContext() != contextHandle) {
if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
- throw new GLException("Error making context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError() + ", " + this);
+ throw new GLException("Error making context " + toHexString(contextHandle) +
+ " current on Thread " + getThreadName() +
+ ", drawableWrite " + toHexString(drawable.getHandle()) +
+ ", drawableRead "+ toHexString(drawableRead.getHandle()) +
+ ", werr: " + GDI.GetLastError() + ", " + this);
}
}
}
@@ -397,7 +427,7 @@ public class WindowsWGLContext extends GLContextImpl {
}
@Override
- protected void copyImpl(GLContext source, int mask) throws GLException {
+ protected void copyImpl(final GLContext source, final int mask) throws GLException {
if (!WGL.wglCopyContext(source.getHandle(), getHandle(), mask)) {
throw new GLException("wglCopyContext failed");
}
@@ -439,7 +469,7 @@ public class WindowsWGLContext extends GLContextImpl {
@Override
protected final StringBuilder getPlatformExtensionsStringImpl() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
if (!wglGetExtensionsStringEXTInitialized) {
wglGetExtensionsStringEXTAvailable = (WGL.wglGetProcAddress("wglGetExtensionsStringEXT") != 0);
@@ -452,26 +482,26 @@ public class WindowsWGLContext extends GLContextImpl {
}
@Override
- protected boolean setSwapIntervalImpl(int interval) {
- WGLExt wglExt = getWGLExt();
+ protected boolean setSwapIntervalImpl(final int interval) {
+ final WGLExt wglExt = getWGLExt();
if(0==hasSwapIntervalSGI) {
try {
hasSwapIntervalSGI = wglExt.isExtensionAvailable("WGL_EXT_swap_control")?1:-1;
- } catch (Throwable t) { hasSwapIntervalSGI=1; }
+ } catch (final Throwable t) { hasSwapIntervalSGI=1; }
}
if (hasSwapIntervalSGI>0) {
try {
return wglExt.wglSwapIntervalEXT(interval);
- } catch (Throwable t) { hasSwapIntervalSGI=-1; }
+ } catch (final Throwable t) { hasSwapIntervalSGI=-1; }
}
return false;
}
- private final int initSwapGroupImpl(WGLExt wglExt) {
+ private final int initSwapGroupImpl(final WGLExt wglExt) {
if(0==hasSwapGroupNV) {
try {
hasSwapGroupNV = wglExt.isExtensionAvailable("WGL_NV_swap_group")?1:-1;
- } catch (Throwable t) { hasSwapGroupNV=1; }
+ } catch (final Throwable t) { hasSwapGroupNV=1; }
if(DEBUG) {
System.err.println("initSwapGroupImpl: hasSwapGroupNV: "+hasSwapGroupNV);
}
@@ -480,79 +510,63 @@ public class WindowsWGLContext extends GLContextImpl {
}
@Override
- protected final boolean queryMaxSwapGroupsImpl(int[] maxGroups, int maxGroups_offset,
- int[] maxBarriers, int maxBarriers_offset) {
+ protected final boolean queryMaxSwapGroupsImpl(final int[] maxGroups, final int maxGroups_offset,
+ final int[] maxBarriers, final int maxBarriers_offset) {
boolean res = false;
- WGLExt wglExt = getWGLExt();
+ final WGLExt wglExt = getWGLExt();
if (initSwapGroupImpl(wglExt)>0) {
final NativeSurface ns = drawable.getNativeSurface();
try {
- if( wglExt.wglQueryMaxSwapGroupsNV(ns.getDisplayHandle(),
- maxGroups, maxGroups_offset,
- maxBarriers, maxBarriers_offset) ) {
+ final IntBuffer maxGroupsNIO = Buffers.newDirectIntBuffer(maxGroups.length - maxGroups_offset);
+ final IntBuffer maxBarriersNIO = Buffers.newDirectIntBuffer(maxBarriers.length - maxBarriers_offset);
+
+ if( wglExt.wglQueryMaxSwapGroupsNV(ns.getDisplayHandle(), maxGroupsNIO, maxBarriersNIO) ) {
+ maxGroupsNIO.get(maxGroups, maxGroups_offset, maxGroupsNIO.remaining());
+ maxBarriersNIO.get(maxGroups, maxGroups_offset, maxBarriersNIO.remaining());
res = true;
}
- } catch (Throwable t) { hasSwapGroupNV=-1; }
+ } catch (final Throwable t) { hasSwapGroupNV=-1; }
}
return res;
}
@Override
- protected final boolean joinSwapGroupImpl(int group) {
+ protected final boolean joinSwapGroupImpl(final int group) {
boolean res = false;
- WGLExt wglExt = getWGLExt();
+ final WGLExt wglExt = getWGLExt();
if (initSwapGroupImpl(wglExt)>0) {
try {
if( wglExt.wglJoinSwapGroupNV(drawable.getHandle(), group) ) {
currentSwapGroup = group;
res = true;
}
- } catch (Throwable t) { hasSwapGroupNV=-1; }
+ } catch (final Throwable t) { hasSwapGroupNV=-1; }
}
return res;
}
@Override
- protected final boolean bindSwapBarrierImpl(int group, int barrier) {
+ protected final boolean bindSwapBarrierImpl(final int group, final int barrier) {
boolean res = false;
- WGLExt wglExt = getWGLExt();
+ final WGLExt wglExt = getWGLExt();
if (initSwapGroupImpl(wglExt)>0) {
try {
if( wglExt.wglBindSwapBarrierNV(group, barrier) ) {
res = true;
}
- } catch (Throwable t) { hasSwapGroupNV=-1; }
+ } catch (final Throwable t) { hasSwapGroupNV=-1; }
}
return res;
}
@Override
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
- return getWGLExt().wglAllocateMemoryNV(arg0, arg1, arg2, arg3);
- }
-
- @Override
- public int getOffscreenContextPixelDataType() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextReadBuffer() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public void bindPbufferToTexture() {
- throw new GLException("Should not call this");
+ public final ByteBuffer glAllocateMemoryNV(final int size, final float readFrequency, final float writeFrequency, final float priority) {
+ return getWGLExt().wglAllocateMemoryNV(size, readFrequency, writeFrequency, priority);
}
@Override
- public void releasePbufferFromTexture() {
- throw new GLException("Should not call this");
+ public final void glFreeMemoryNV(final ByteBuffer pointer) {
+ getWGLExt().wglFreeMemoryNV(pointer);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java
index 3b3f0c123..00b048e38 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java
@@ -44,6 +44,8 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
+import com.jogamp.common.util.PropertyAccess;
+
import jogamp.nativewindow.windows.GDI;
import jogamp.opengl.Debug;
import jogamp.opengl.GLDrawableImpl;
@@ -51,29 +53,35 @@ import jogamp.opengl.GLDynamicLookupHelper;
public abstract class WindowsWGLDrawable extends GLDrawableImpl {
- private static final boolean PROFILING = Debug.isPropertyDefined("jogl.debug.GLDrawable.profiling", true);
+ private static final boolean PROFILING;
+
+ static {
+ Debug.initSingleton();
+ PROFILING = PropertyAccess.isPropertyDefined("jogl.debug.GLDrawable.profiling", true);
+ }
+
private static final int PROFILING_TICKS = 200;
private int profilingSwapBuffersTicks;
private long profilingSwapBuffersTime;
- public WindowsWGLDrawable(GLDrawableFactory factory, NativeSurface comp, boolean realized) {
+ public WindowsWGLDrawable(final GLDrawableFactory factory, final NativeSurface comp, final boolean realized) {
super(factory, comp, realized);
}
@Override
protected void setRealizedImpl() {
if(realized) {
- NativeSurface ns = getNativeSurface();
- WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
+ final NativeSurface ns = getNativeSurface();
+ final WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
config.updateGraphicsConfiguration(getFactory(), ns, null);
if (DEBUG) {
- System.err.println("WindowsWGLDrawable.setRealized(true): "+config);
+ System.err.println(getThreadName()+": WindowsWGLDrawable.setRealized(true): "+config);
}
}
}
@Override
- protected final void swapBuffersImpl(boolean doubleBuffered) {
+ protected final void swapBuffersImpl(final boolean doubleBuffered) {
if(doubleBuffered) {
final long t0;
if (PROFILING) {
@@ -81,11 +89,11 @@ public abstract class WindowsWGLDrawable extends GLDrawableImpl {
} else {
t0 = 0;
}
-
+
if (!WGLUtil.SwapBuffers(getHandle()) && (GDI.GetLastError() != GDI.ERROR_SUCCESS)) {
throw new GLException("Error swapping buffers");
}
-
+
if (PROFILING) {
profilingSwapBuffersTime += System.currentTimeMillis() - t0;
if (++profilingSwapBuffersTicks == PROFILING_TICKS) {
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index 91d5c225a..fa052d784 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -42,6 +42,8 @@ package jogamp.opengl.windows.wgl;
import java.nio.Buffer;
import java.nio.ShortBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -53,7 +55,6 @@ import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
-import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
@@ -67,6 +68,7 @@ import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.GDIDummyUpstreamSurfaceHook;
import jogamp.nativewindow.windows.GDISurface;
import jogamp.nativewindow.windows.RegisteredClassFactory;
+import jogamp.opengl.Debug;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
@@ -75,34 +77,101 @@ import jogamp.opengl.GLDynamicLookupHelper;
import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.SharedResourceRunner;
-import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.nio.PointerBuffer;
-import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
-import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
+ /**
+ * Bug 1036: NVidia Windows Driver 'Threaded optimization' workaround.
+ * <p>
+ * https://jogamp.org/bugzilla/show_bug.cgi?id=1036
+ * </p>
+ * <p>
+ * Since NV driver 260.99 from 2010-12-11 a 'Threaded optimization' feature has been introduced.
+ * The driver spawns off a dedicated thread to off-load certain OpenGL tasks from the calling thread
+ * to perform them async and off-thread.
+ * </p>
+ * <p>
+ * If 'Threaded optimization' is manually enabled 'on', the driver may crash with JOGL's consistent
+ * multi-threaded usage - this is a driver bug.
+ * </p>
+ * <p>
+ * If 'Threaded optimization' is manually disabled 'off', the driver always works correctly.
+ * </p>
+ * <p>
+ * 'Threaded optimization' default setting is 'auto' and the driver may crash without this workaround.
+ * </p>
+ * <p>
+ * If setting the process affinity to '1' (1st CPU) while initialization and launching
+ * the {@link SharedResourceRunner}, the driver does not crash anymore in 'auto' mode.
+ * This might be either because the driver does not enable 'Threaded optimization'
+ * or because the driver's worker thread is bound to the same CPU.
+ * </p>
+ * <p>
+ * Property integer value <code>jogl.windows.cpu_affinity_mode</code>:
+ * <ul>
+ * <li>0 - none (no affinity, may cause driver crash with 'Threaded optimization' = ['auto', 'on'])</li>
+ * <li>1 - process affinity (default, workaround for driver crash for 'Threaded optimization' = 'auto', still crashes if set to 'on')</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Test case reproducing the crash reliable is: com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyNEWT<br>
+ * (don't ask why ..)
+ * </p>
+ */
+ private static final int CPU_AFFINITY_MODE;
+
+ static {
+ Debug.initSingleton();
+ CPU_AFFINITY_MODE = PropertyAccess.getIntProperty("jogl.windows.cpu_affinity_mode", true, 1);
+ }
+
private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null;
+ private final CPUAffinity cpuAffinity;
+
public WindowsWGLDrawableFactory() {
super();
+ switch( CPU_AFFINITY_MODE ) {
+ case 0:
+ cpuAffinity = new NopCPUAffinity();
+ break;
+ /**
+ * Doesn't work !
+ case 2:
+ cpuAffinity = new WindowsThreadAffinity();
+ break;
+ */
+ default:
+ cpuAffinity = new WindowsProcessAffinity();
+ break;
+ }
+
synchronized(WindowsWGLDrawableFactory.class) {
- if(null==windowsWGLDynamicLookupHelper) {
- DesktopGLDynamicLookupHelper tmp = null;
- try {
- tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo());
- } catch (GLException gle) {
- if(DEBUG) {
- gle.printStackTrace();
+ if( null == windowsWGLDynamicLookupHelper ) {
+ windowsWGLDynamicLookupHelper = AccessController.doPrivileged(new PrivilegedAction<DesktopGLDynamicLookupHelper>() {
+ @Override
+ public DesktopGLDynamicLookupHelper run() {
+ DesktopGLDynamicLookupHelper tmp;
+ try {
+ tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo());
+ if(null!=tmp && tmp.isLibComplete()) {
+ WGL.getWGLProcAddressTable().reset(tmp);
+ }
+ } catch (final Exception ex) {
+ tmp = null;
+ if(DEBUG) {
+ ex.printStackTrace();
+ }
+ }
+ return tmp;
}
- }
- if(null!=tmp && tmp.isLibComplete()) {
- windowsWGLDynamicLookupHelper = tmp;
- WGL.getWGLProcAddressTable().reset(windowsWGLDynamicLookupHelper);
- }
+ } );
}
}
@@ -116,7 +185,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
try {
ReflectionUtil.callStaticMethod("jogamp.opengl.windows.wgl.awt.WindowsAWTWGLGraphicsConfigurationFactory",
"registerFactory", null, null, getClass().getClassLoader());
- } catch (JogampRuntimeException jre) { /* n/a .. */ }
+ } catch (final Exception jre) { /* n/a .. */ }
}
sharedMap = new HashMap<String, SharedResourceRunner.Resource>();
@@ -132,10 +201,13 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
protected final boolean isComplete() {
return null != windowsWGLDynamicLookupHelper;
}
-
-
+
+
@Override
- protected final void destroy() {
+ protected final void shutdownImpl() {
+ if( DEBUG ) {
+ System.err.println("WindowsWGLDrawableFactory.shutdown");
+ }
if(null != sharedResourceRunner) {
sharedResourceRunner.stop();
sharedResourceRunner = null;
@@ -156,74 +228,42 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) {
+ public GLDynamicLookupHelper getGLDynamicLookupHelper(final int profile) {
return windowsWGLDynamicLookupHelper;
}
+ /* pp */ static String toHexString(final long l) { return "0x"+Long.toHexString(l); }
+
private WindowsGraphicsDevice defaultDevice;
private SharedResourceRunner sharedResourceRunner;
private HashMap<String /*connection*/, SharedResourceRunner.Resource> sharedMap;
- private long processAffinityChanges = 0;
- private PointerBuffer procMask = PointerBuffer.allocateDirect(1);
- private PointerBuffer sysMask = PointerBuffer.allocateDirect(1);
-
@Override
protected void enterThreadCriticalZone() {
- synchronized (sysMask) {
- if( 0 == processAffinityChanges) {
- long pid = GDI.GetCurrentProcess();
- if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) {
- if(DEBUG) {
- System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName());
- // Thread.dumpStack();
- }
- processAffinityChanges = pid;
- GDI.SetProcessAffinityMask(pid, 1);
- }
- }
+ synchronized (cpuAffinity) {
+ cpuAffinity.set(1);
}
}
@Override
protected void leaveThreadCriticalZone() {
- synchronized (sysMask) {
- if( 0 != processAffinityChanges) {
- long pid = GDI.GetCurrentProcess();
- if( pid != processAffinityChanges) {
- throw new GLException("PID doesn't match: set PID 0x" + Long.toHexString(processAffinityChanges) +
- " this PID 0x" + Long.toHexString(pid) );
- }
- if(DEBUG) {
- System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName());
- }
- GDI.SetProcessAffinityMask(pid, sysMask.get(0));
- }
+ synchronized (cpuAffinity) {
+ cpuAffinity.reset();
}
}
- /**
- * http://msdn.microsoft.com/en-us/library/ms724832%28v=vs.85%29.aspx
- * Windows XP 5.1
- */
- static final VersionNumber winXPVersionNumber = new VersionNumber ( 5, 1, 0);
-
static class SharedResource implements SharedResourceRunner.Resource {
+ private final boolean hasARBPixelFormat;
+ private final boolean hasARBMultisample;
+ private final boolean hasARBPBuffer;
+ private final boolean hasARBReadDrawable;
private WindowsGraphicsDevice device;
private AbstractGraphicsScreen screen;
private GLDrawableImpl drawable;
private GLContextImpl context;
- private boolean hasARBPixelFormat;
- private boolean hasARBMultisample;
- private boolean hasARBPBuffer;
- private boolean hasARBReadDrawable;
- private String vendor;
- private boolean isVendorATI;
- private boolean isVendorNVIDIA;
- private boolean needsCurrenContext4ARBPFDQueries;
-
- SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, GLDrawableImpl draw, GLContextImpl ctx,
- boolean arbPixelFormat, boolean arbMultisample, boolean arbPBuffer, boolean arbReadDrawable, String glVendor) {
+
+ SharedResource(final WindowsGraphicsDevice dev, final AbstractGraphicsScreen scrn, final GLDrawableImpl draw, final GLContextImpl ctx,
+ final boolean arbPixelFormat, final boolean arbMultisample, final boolean arbPBuffer, final boolean arbReadDrawable) {
device = dev;
screen = scrn;
drawable = draw;
@@ -232,28 +272,13 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
hasARBMultisample = arbMultisample;
hasARBPBuffer = arbPBuffer;
hasARBReadDrawable = arbReadDrawable;
- vendor = glVendor;
- if(null != vendor) {
- isVendorNVIDIA = vendor.startsWith("NVIDIA") ;
- isVendorATI = vendor.startsWith("ATI") ;
- }
-
- if ( isVendorATI() ) {
- final VersionNumber winVersion = Platform.getOSVersionNumber();
- final boolean isWinXPOrLess = winVersion.compareTo(winXPVersionNumber) <= 0;
- if(DEBUG) {
- System.err.println("needsCurrenContext4ARBPFDQueries: "+winVersion+" <= "+winXPVersionNumber+" = "+isWinXPOrLess+" - "+Platform.getOSVersion());
- }
- needsCurrenContext4ARBPFDQueries = isWinXPOrLess;
- } else {
- if(DEBUG) {
- System.err.println("needsCurrenContext4ARBPFDQueries: false");
- }
- needsCurrenContext4ARBPFDQueries = false;
- }
}
@Override
+ public final boolean isValid() {
+ return null != context;
+ }
+ @Override
final public AbstractGraphicsDevice getDevice() { return device; }
@Override
final public AbstractGraphicsScreen getScreen() { return screen; }
@@ -261,45 +286,29 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
final public GLDrawableImpl getDrawable() { return drawable; }
@Override
final public GLContextImpl getContext() { return context; }
+ @Override
+ public GLRendererQuirks getRendererQuirks() {
+ return null != context ? context.getRendererQuirks() : null;
+ }
final boolean hasARBPixelFormat() { return hasARBPixelFormat; }
final boolean hasARBMultisample() { return hasARBMultisample; }
final boolean hasARBPBuffer() { return hasARBPBuffer; }
final boolean hasReadDrawable() { return hasARBReadDrawable; }
-
- final String vendor() { return vendor; }
- final boolean isVendorATI() { return isVendorATI; }
- final boolean isVendorNVIDIA() { return isVendorNVIDIA; }
-
- /**
- * Solves bug #480
- *
- * TODO: Validate if bug is actually relates to the 'old' ATI Windows driver for old GPU's like X300 etc
- * and unrelated to the actual Windows version !
- *
- * @return true if GL_VENDOR is ATI _and_ platform is Windows version XP or less!
- */
- final boolean needsCurrentContext4ARBPFDQueries() { return needsCurrenContext4ARBPFDQueries; }
}
class SharedResourceImplementation implements SharedResourceRunner.Implementation {
@Override
public void clear() {
- synchronized(sharedMap) {
- sharedMap.clear();
- }
+ sharedMap.clear();
}
@Override
- public SharedResourceRunner.Resource mapPut(String connection, SharedResourceRunner.Resource resource) {
- synchronized(sharedMap) {
- return sharedMap.put(connection, resource);
- }
+ public SharedResourceRunner.Resource mapPut(final String connection, final SharedResourceRunner.Resource resource) {
+ return sharedMap.put(connection, resource);
}
@Override
- public SharedResourceRunner.Resource mapGet(String connection) {
- synchronized(sharedMap) {
- return sharedMap.get(connection);
- }
+ public SharedResourceRunner.Resource mapGet(final String connection) {
+ return sharedMap.get(connection);
}
@Override
public Collection<SharedResourceRunner.Resource> mapValues() {
@@ -309,7 +318,12 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public SharedResourceRunner.Resource createSharedResource(String connection) {
+ public boolean isDeviceSupported(final String connection) {
+ return true;
+ }
+
+ @Override
+ public SharedResourceRunner.Resource createSharedResource(final String connection) {
final WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT);
sharedDevice.lock();
try {
@@ -318,9 +332,10 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
if (null == glp) {
throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
}
- final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64));
+ final GLCapabilitiesImmutable caps = new GLCapabilities(glp);
+ final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, caps, caps, null, 64, 64));
sharedDrawable.setRealized(true);
-
+
final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null);
if (null == sharedContext) {
throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
@@ -329,7 +344,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
boolean hasARBMultisample;
boolean hasARBPBuffer;
boolean hasARBReadDrawableAvailable;
- String vendor;
sharedContext.makeCurrent();
try {
hasARBPixelFormat = sharedContext.isExtensionAvailable(WGL_ARB_pixel_format);
@@ -337,7 +351,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
hasARBPBuffer = sharedContext.isExtensionAvailable(GLExtensions.ARB_pbuffer);
hasARBReadDrawableAvailable = sharedContext.isExtensionAvailable(WGL_ARB_make_current_read) &&
sharedContext.isFunctionAvailable(wglMakeContextCurrent);
- vendor = sharedContext.getGL().glGetString(GL.GL_VENDOR);
} finally {
sharedContext.release();
}
@@ -349,12 +362,11 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
System.err.println("multisample: " + hasARBMultisample);
System.err.println("pbuffer: " + hasARBPBuffer);
System.err.println("readDrawable: " + hasARBReadDrawableAvailable);
- System.err.println("vendor: " + vendor);
}
return new SharedResource(sharedDevice, absScreen, sharedDrawable, sharedContext,
hasARBPixelFormat, hasARBMultisample,
- hasARBPBuffer, hasARBReadDrawableAvailable, vendor);
- } catch (Throwable t) {
+ hasARBPBuffer, hasARBReadDrawableAvailable);
+ } catch (final Throwable t) {
throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+connection, t);
} finally {
sharedDevice.unlock();
@@ -362,8 +374,8 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public void releaseSharedResource(SharedResourceRunner.Resource shared) {
- SharedResource sr = (SharedResource) shared;
+ public void releaseSharedResource(final SharedResourceRunner.Resource shared) {
+ final SharedResource sr = (SharedResource) shared;
if (DEBUG) {
System.err.println("Shutdown Shared:");
System.err.println("Device : " + sr.device);
@@ -374,6 +386,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
if (null != sr.context) {
// may cause JVM SIGSEGV: sharedContext.destroy();
+ sr.context.destroy(); // will also pull the dummy MutableSurface
sr.context = null;
}
@@ -399,7 +412,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) {
+ public final boolean getIsDeviceCompatible(final AbstractGraphicsDevice device) {
if(null!=windowsWGLDynamicLookupHelper && device instanceof WindowsGraphicsDevice) {
return true;
}
@@ -419,58 +432,25 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final boolean createSharedResource(AbstractGraphicsDevice device) {
- try {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return null != sr.getContext();
- }
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("Catched Exception while WindowsWGL Shared Resource initialization");
- gle.printStackTrace();
- }
- }
- return false;
- }
-
- @Override
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getContext();
- }
- return null;
- }
-
- @Override
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getDevice();
- }
- return null;
+ protected final SharedResource getOrCreateSharedResourceImpl(final AbstractGraphicsDevice device) {
+ return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
}
- protected WindowsWGLDrawable getOrCreateSharedDrawable(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
+ protected final WindowsWGLDrawable getOrCreateSharedDrawable(final AbstractGraphicsDevice device) {
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResourceImpl(device);
if(null!=sr) {
return (WindowsWGLDrawable) sr.getDrawable();
}
return null;
}
- SharedResource getOrCreateSharedResource(AbstractGraphicsDevice device) {
- return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
- }
-
@Override
- protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
+ protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(final AbstractGraphicsDevice device) {
return WindowsWGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device);
}
@Override
- protected final GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) {
+ protected final GLDrawableImpl createOnscreenDrawableImpl(final NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
@@ -482,10 +462,10 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
- AbstractGraphicsConfiguration config = target.getGraphicsConfiguration();
- GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final AbstractGraphicsConfiguration config = target.getGraphicsConfiguration();
+ final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
if(!chosenCaps.isPBuffer()) {
- return new WindowsBitmapWGLDrawable(this, target);
+ return WindowsBitmapWGLDrawable.create(this, target);
}
// PBuffer GLDrawable Creation
@@ -496,9 +476,9 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
* Similar to ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277,
* we need to have a context current on the same Display to create a PBuffer.
*/
- final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
+ final SharedResource sr = getOrCreateSharedResourceImpl(device);
if(null!=sr) {
- GLContext lastContext = GLContext.getCurrent();
+ final GLContext lastContext = GLContext.getCurrent();
if (lastContext != null) {
lastContext.release();
}
@@ -521,8 +501,8 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
* @return 1 if read drawable extension is available, 0 if not
* and -1 if undefined yet, ie no shared device exist at this point.
*/
- public final int isReadDrawableAvailable(AbstractGraphicsDevice device) {
- SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice);
+ public final int isReadDrawableAvailable(final AbstractGraphicsDevice device) {
+ final SharedResource sr = getOrCreateSharedResourceImpl( ( null != device ) ? device : defaultDevice );
if(null!=sr) {
return sr.hasReadDrawable() ? 1 : 0 ;
}
@@ -530,8 +510,8 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
- SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice);
+ public final boolean canCreateGLPbuffer(final AbstractGraphicsDevice device, final GLProfile glp) {
+ final SharedResource sr = getOrCreateSharedResourceImpl( ( null != device ) ? device : defaultDevice );
if(null!=sr) {
return sr.hasARBPBuffer();
}
@@ -539,11 +519,11 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
- GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) {
+ protected final ProxySurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstreamHook) {
final WindowsGraphicsDevice device;
- if(createNewDevice) {
+ if(createNewDevice || !(deviceReq instanceof WindowsGraphicsDevice)) {
device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
} else {
device = (WindowsGraphicsDevice)deviceReq;
@@ -551,31 +531,31 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
final WindowsWGLGraphicsConfiguration config = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen);
if(null == config) {
- throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
- }
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ }
return new WrappedSurface(config, 0, upstreamHook, createNewDevice);
}
@Override
- public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
- GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ public final ProxySurface createDummySurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) {
final WindowsGraphicsDevice device;
- if(createNewDevice) {
+ if( createNewDevice || !(deviceReq instanceof WindowsGraphicsDevice) ) {
device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
} else {
device = (WindowsGraphicsDevice)deviceReq;
}
final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps);
final WindowsWGLGraphicsConfiguration config = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(chosenCaps, requestedCaps, chooser, screen);
- if(null == config) {
- throw new GLException("Choosing GraphicsConfiguration failed w/ "+requestedCaps+" on "+screen);
- }
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+chosenCaps+" on "+screen);
+ }
return new GDISurface(config, 0, new GDIDummyUpstreamSurfaceHook(width, height), createNewDevice);
- }
-
+ }
+
@Override
- protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ protected final ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) {
final WindowsGraphicsDevice device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
final WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen);
@@ -588,7 +568,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) {
+ public final boolean canCreateExternalGLDrawable(final AbstractGraphicsDevice device) {
return true;
}
@@ -598,7 +578,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
static String wglGetLastError() {
- long err = GDI.GetLastError();
+ final long err = GDI.GetLastError();
String detail = null;
switch ((int) err) {
case GDI.ERROR_SUCCESS: detail = "ERROR_SUCCESS"; break;
@@ -612,17 +592,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return detail;
}
- @Override
- public final boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- @Override
- public final GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("Unimplemented on this platform");
- }
-
//------------------------------------------------------
// Gamma-related functionality
//
@@ -630,32 +599,40 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
private static final int GAMMA_RAMP_LENGTH = 256;
@Override
- protected final int getGammaRampLength() {
+ protected final int getGammaRampLength(final NativeSurface surface) {
return GAMMA_RAMP_LENGTH;
}
@Override
- protected final boolean setGammaRamp(float[] ramp) {
- short[] rampData = new short[3 * GAMMA_RAMP_LENGTH];
+ protected final boolean setGammaRamp(final NativeSurface surface, final float[] ramp) {
+ final short[] rampData = new short[3 * GAMMA_RAMP_LENGTH];
for (int i = 0; i < GAMMA_RAMP_LENGTH; i++) {
- short scaledValue = (short) (ramp[i] * 65535);
+ final short scaledValue = (short) (ramp[i] * 65535);
rampData[i] = scaledValue;
rampData[i + GAMMA_RAMP_LENGTH] = scaledValue;
rampData[i + 2 * GAMMA_RAMP_LENGTH] = scaledValue;
}
- long screenDC = GDI.GetDC(0);
- boolean res = GDI.SetDeviceGammaRamp(screenDC, ShortBuffer.wrap(rampData));
- GDI.ReleaseDC(0, screenDC);
+ final long hDC = surface.getSurfaceHandle();
+ if( 0 == hDC ) {
+ return false;
+ }
+ // final long screenDC = GDI.GetDC(0);
+ final boolean res = GDI.SetDeviceGammaRamp(hDC, ShortBuffer.wrap(rampData));
+ // GDI.ReleaseDC(0, screenDC);
return res;
}
@Override
- protected final Buffer getGammaRamp() {
- ShortBuffer rampData = ShortBuffer.wrap(new short[3 * GAMMA_RAMP_LENGTH]);
- long screenDC = GDI.GetDC(0);
- boolean res = GDI.GetDeviceGammaRamp(screenDC, rampData);
- GDI.ReleaseDC(0, screenDC);
+ protected final Buffer getGammaRamp(final NativeSurface surface) {
+ final ShortBuffer rampData = ShortBuffer.wrap(new short[3 * GAMMA_RAMP_LENGTH]);
+ final long hDC = surface.getSurfaceHandle();
+ if( 0 == hDC ) {
+ return null;
+ }
+ // final long screenDC = GDI.GetDC(0);
+ final boolean res = GDI.GetDeviceGammaRamp(hDC, rampData);
+ // GDI.ReleaseDC(0, screenDC);
if (!res) {
return null;
}
@@ -663,13 +640,167 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final void resetGammaRamp(Buffer originalGammaRamp) {
+ protected final void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) {
+ if (originalGammaRamp == null) {
+ // getGammaRamp failed earlier
+ return;
+ }
+ final long hDC = surface.getSurfaceHandle();
+ if( 0 == hDC ) {
+ return;
+ }
+ // final long screenDC = GDI.GetDC(0);
+ GDI.SetDeviceGammaRamp(hDC, originalGammaRamp);
+ // GDI.ReleaseDC(0, hDC);
+ }
+
+ @Override
+ protected final void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) {
if (originalGammaRamp == null) {
// getGammaRamp failed earlier
return;
}
- long screenDC = GDI.GetDC(0);
+ final long screenDC = GDI.GetDC(0);
GDI.SetDeviceGammaRamp(screenDC, originalGammaRamp);
GDI.ReleaseDC(0, screenDC);
}
+
+
+ static interface CPUAffinity {
+ boolean set(final int newAffinity);
+ boolean reset();
+ }
+ static final class WindowsThreadAffinity implements CPUAffinity {
+ private long threadHandle;
+ private long threadOrigAffinity;
+ private long threadNewAffinity;
+ public WindowsThreadAffinity() {
+ threadHandle = 0;
+ threadOrigAffinity = 0;
+ threadNewAffinity = 0;
+ }
+ @Override
+ public boolean set(final int newAffinity) {
+ final long tid = GDI.GetCurrentThread();
+ if( 0 != threadHandle ) {
+ throw new IllegalStateException("Affinity already set");
+ }
+ final long threadLastAffinity = GDI.SetThreadAffinityMask(tid, newAffinity);
+ final int werr = GDI.GetLastError();
+ final boolean res;
+ if( 0 != threadLastAffinity ) {
+ res = true;
+ this.threadHandle = tid;
+ this.threadNewAffinity = newAffinity;
+ this.threadOrigAffinity = threadLastAffinity;
+ } else {
+ res = false;
+ }
+ if(DEBUG) {
+ System.err.println("WindowsThreadAffinity.set() - tid " + toHexString(tid) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+werr+"), Affinity: "+toHexString(threadOrigAffinity) + " -> " + toHexString(newAffinity));
+ }
+ return res;
+ }
+ @Override
+ public boolean reset() {
+ if( 0 == threadHandle ) {
+ return true;
+ }
+ final long tid = GDI.GetCurrentThread();
+ if( tid != threadHandle) {
+ throw new IllegalStateException("TID doesn't match: set TID " + toHexString(threadHandle) +
+ " this TID " + toHexString(tid) );
+ }
+ final long preThreadAffinity = GDI.SetThreadAffinityMask(threadHandle, threadOrigAffinity);
+ final boolean res = 0 != preThreadAffinity;
+ if(DEBUG) {
+ System.err.println("WindowsThreadAffinity.reset() - tid " + toHexString(threadHandle) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+GDI.GetLastError()+"), Affinity: "+toHexString(threadNewAffinity)+" -> orig "+ toHexString(threadOrigAffinity));
+ }
+ this.threadHandle = 0;
+ this.threadNewAffinity = this.threadOrigAffinity;
+ return res;
+ }
+ }
+ static final class WindowsProcessAffinity implements CPUAffinity {
+ private long processHandle;
+ private long newAffinity;
+ private final PointerBuffer procMask;
+ private final PointerBuffer sysMask;
+
+ public WindowsProcessAffinity() {
+ processHandle = 0;
+ newAffinity = 0;
+ procMask = PointerBuffer.allocateDirect(1);
+ sysMask = PointerBuffer.allocateDirect(1);
+ }
+ @Override
+ public boolean set(final int newAffinity) {
+ if( 0 != processHandle ) {
+ throw new IllegalStateException("Affinity already set");
+ }
+ final long pid = GDI.GetCurrentProcess();
+ final boolean res;
+ if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) {
+ if( GDI.SetProcessAffinityMask(pid, newAffinity) ) {
+ this.processHandle = pid;
+ this.newAffinity = newAffinity;
+ res = true;
+ } else {
+ res = false;
+ }
+ if(DEBUG) {
+ System.err.println("WindowsProcessAffinity.set() - pid " + toHexString(pid) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+GDI.GetLastError()+"), Affinity: procMask "+ toHexString(procMask.get(0)) + ", sysMask "+ toHexString(sysMask.get(0)) +
+ " -> "+toHexString(newAffinity));
+ }
+ } else {
+ if(DEBUG) {
+ System.err.println("WindowsProcessAffinity.set() - pid " + toHexString(pid) + " - " + getThreadName() +
+ ": Error, could not GetProcessAffinityMask, werr "+GDI.GetLastError());
+ }
+ res = false;
+ }
+ return res;
+ }
+ @Override
+ public boolean reset() {
+ if( 0 == processHandle ) {
+ return true;
+ }
+ final long pid = GDI.GetCurrentProcess();
+ if( pid != processHandle) {
+ throw new IllegalStateException("PID doesn't match: set PID " + toHexString(processHandle) +
+ " this PID " + toHexString(pid) );
+ }
+ final long origProcAffinity = procMask.get(0);
+ final boolean res = GDI.SetProcessAffinityMask(processHandle, origProcAffinity);
+ if(DEBUG) {
+ final int werr = GDI.GetLastError();
+ System.err.println("WindowsProcessAffinity.reset() - pid " + toHexString(processHandle) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+werr+"), Affinity: "+toHexString(newAffinity)+" -> procMask "+ toHexString(origProcAffinity));
+ }
+ this.processHandle = 0;
+ this.newAffinity = origProcAffinity;
+ return res;
+ }
+ }
+ static final class NopCPUAffinity implements CPUAffinity {
+ public NopCPUAffinity() { }
+ @Override
+ public boolean set(final int newAffinity) {
+ if(DEBUG) {
+ System.err.println("NopCPUAffinity.set() - " + getThreadName());
+ }
+ return false;
+ }
+ @Override
+ public boolean reset() {
+ if(DEBUG) {
+ System.err.println("NopCPUAffinity.reset() - " + getThreadName());
+ }
+ return false;
+ }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java
index a553bd4c2..2285ae996 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,40 +20,40 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl.windows.wgl;
import jogamp.opengl.*;
import java.util.*;
-public class WindowsWGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
+public final class WindowsWGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
protected WindowsWGLDynamicLibraryBundleInfo() {
super();
}
@Override
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsGL = new ArrayList<String>();
libsGL.add("OpenGL32");
- libsList.add(libsGL);
+ libsList.add(libsGL);
return libsList;
}
-
+
@Override
public final List<String> getToolGetProcAddressFuncNameList() {
- List<String> res = new ArrayList<String>();
+ final List<String> res = new ArrayList<String>();
res.add("wglGetProcAddress");
return res;
}
@Override
- public final long toolGetProcAddress(long toolGetProcAddressHandle, String funcName) {
+ public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) {
return WGL.wglGetProcAddress(toolGetProcAddressHandle, funcName);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
index 058f4e336..5785f8041 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -33,6 +33,8 @@
package jogamp.opengl.windows.wgl;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
@@ -44,46 +46,45 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
-import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
-import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
import jogamp.nativewindow.windows.DWM_BLURBEHIND;
import jogamp.nativewindow.windows.GDI;
+import jogamp.nativewindow.windows.GDIUtil;
import jogamp.nativewindow.windows.MARGINS;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
-import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLGraphicsConfigurationUtil;
-@SuppressWarnings("deprecation")
-public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {
+public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {
protected static final int MAX_PFORMATS = 256;
protected static final int MAX_ATTRIBS = 256;
- private GLCapabilitiesChooser chooser;
+ private final GLCapabilitiesChooser chooser;
private boolean isDetermined = false;
private boolean isExternal = false;
- WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen,
- GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser) {
+ WindowsWGLGraphicsConfiguration(final AbstractGraphicsScreen screen,
+ final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser) {
super(screen, capsChosen, capsRequested);
this.chooser=chooser;
this.isDetermined = false;
}
- WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen,
- WGLGLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested) {
+ WindowsWGLGraphicsConfiguration(final AbstractGraphicsScreen screen,
+ final WGLGLCapabilities capsChosen, final GLCapabilitiesImmutable capsRequested) {
super(screen, capsChosen, capsRequested);
setCapsPFD(capsChosen);
this.chooser=null;
}
- static WindowsWGLGraphicsConfiguration createFromExternal(GLDrawableFactory _factory, long hdc, int pfdID,
- GLProfile glp, AbstractGraphicsScreen screen, boolean onscreen)
+ static WindowsWGLGraphicsConfiguration createFromExternal(final GLDrawableFactory _factory, final long hdc, final int pfdID,
+ GLProfile glp, final AbstractGraphicsScreen screen, final boolean onscreen)
{
if(_factory==null) {
throw new GLException("Null factory");
@@ -97,10 +98,10 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
if(null==glp) {
glp = GLProfile.getDefault(screen.getDevice());
}
- WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory;
- AbstractGraphicsDevice device = screen.getDevice();
- WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
- boolean hasARB = null != sharedResource && sharedResource.hasARBPixelFormat();
+ final WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory;
+ final AbstractGraphicsDevice device = screen.getDevice();
+ final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
+ final boolean hasARB = null != sharedResource && sharedResource.hasARBPixelFormat();
WGLGLCapabilities caps = null;
@@ -114,11 +115,12 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
", pfdID "+pfdID+", onscreen "+onscreen+", hasARB "+hasARB);
}
- WindowsWGLGraphicsConfiguration cfg = new WindowsWGLGraphicsConfiguration(screen, caps, caps);
+ final WindowsWGLGraphicsConfiguration cfg = new WindowsWGLGraphicsConfiguration(screen, caps, caps);
cfg.markExternal();
return cfg;
}
+ @Override
public Object clone() {
return super.clone();
}
@@ -135,7 +137,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
* @see #isDetermined()
* @see #isExternal()
*/
- public final void updateGraphicsConfiguration(GLDrawableFactory factory, NativeSurface ns, int[] pfIDs) {
+ public final void updateGraphicsConfiguration(final GLDrawableFactory factory, final NativeSurface ns, final int[] pfIDs) {
WindowsWGLGraphicsConfigurationFactory.updateGraphicsConfiguration(chooser, factory, ns, pfIDs);
}
@@ -149,32 +151,32 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
*
* @see #isDetermined()
*/
- public final void preselectGraphicsConfiguration(GLDrawableFactory factory, int[] pfdIDs) {
- AbstractGraphicsDevice device = getScreen().getDevice();
+ public final void preselectGraphicsConfiguration(final GLDrawableFactory factory, final int[] pfdIDs) {
+ final AbstractGraphicsDevice device = getScreen().getDevice();
WindowsWGLGraphicsConfigurationFactory.preselectGraphicsConfiguration(chooser, factory, device, this, pfdIDs);
}
/**
* Sets the hdc's PixelFormat, this configuration's capabilities and marks it as determined.
*/
- final void setPixelFormat(long hdc, WGLGLCapabilities caps) {
+ final void setPixelFormat(final long hdc, final WGLGLCapabilities caps) {
if (0 == hdc) {
throw new GLException("Error: HDC is null");
}
-
+
if (!WGLUtil.SetPixelFormat(hdc, caps.getPFDID(), caps.getPFD())) {
throw new GLException("Unable to set pixel format " + caps.getPFDID() + " of " + caps +
" for device context " + toHexString(hdc) +
": error code " + GDI.GetLastError());
}
- if(!caps.isBackgroundOpaque()) {
+ if( !caps.isBackgroundOpaque() ) {
final long hwnd = GDI.WindowFromDC(hdc);
- DWM_BLURBEHIND bb = DWM_BLURBEHIND.create();
- bb.setDwFlags(GDI.DWM_BB_ENABLE);
- bb.setFEnable(1);
+ final DWM_BLURBEHIND bb = DWM_BLURBEHIND.create();
+ bb.setDwFlags(GDI.DWM_BB_ENABLE| GDI.DWM_BB_TRANSITIONONMAXIMIZED);
+ bb.setFEnable( 1 );
boolean ok = GDI.DwmEnableBlurBehindWindow(hwnd, bb);
- if(ok) {
- MARGINS m = MARGINS.create();
+ if( ok ) {
+ final MARGINS m = MARGINS.create();
m.setCxLeftWidth(-1);
m.setCxRightWidth(-1);
m.setCyBottomHeight(-1);
@@ -182,7 +184,9 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
ok = GDI.DwmExtendFrameIntoClientArea(hwnd, m);
}
if(DEBUG) {
- System.err.println("translucency enabled on wnd: 0x"+Long.toHexString(hwnd)+" - ok: "+ok);
+ final boolean isUndecorated = GDIUtil.IsUndecorated(hwnd);
+ final boolean isChild = GDIUtil.IsChild(hwnd);
+ System.err.println("translucency enabled on wnd: 0x"+Long.toHexString(hwnd)+" - isUndecorated "+isUndecorated+", isChild "+isChild+", ok: "+ok);
}
}
if (DEBUG) {
@@ -190,12 +194,12 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
setCapsPFD(caps);
}
-
+
/**
* Only sets this configuration's capabilities and marks it as determined,
* the actual pixelformat is not set.
*/
- final void setCapsPFD(WGLGLCapabilities caps) {
+ final void setCapsPFD(final WGLGLCapabilities caps) {
setChosenCapabilities(caps);
this.isDetermined = true;
if (DEBUG) {
@@ -207,90 +211,81 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
* External configuration's HDC pixelformat shall not be modified
*/
public final boolean isExternal() { return isExternal; }
-
+
final void markExternal() {
this.isExternal=true;
}
-
+
/**
* Determined configuration states set target capabilties via {@link #setCapsPFD(WGLGLCapabilities)},
* but does not imply a set pixelformat.
- *
- * @see #setPixelFormat(long, WGLGLCapabilities)
+ *
+ * @see #setPixelFormat(long, WGLGLCapabilities)
* @see #setCapsPFD(WGLGLCapabilities)
*/
public final boolean isDetermined() { return isDetermined; }
-
+
public final PIXELFORMATDESCRIPTOR getPixelFormat() { return isDetermined ? ((WGLGLCapabilities)capabilitiesChosen).getPFD() : null; }
public final int getPixelFormatID() { return isDetermined ? ((WGLGLCapabilities)capabilitiesChosen).getPFDID() : 0; }
public final boolean isChoosenByARB() { return isDetermined ? ((WGLGLCapabilities)capabilitiesChosen).isSetByARB() : false; }
- static int fillAttribsForGeneralWGLARBQuery(WindowsWGLDrawableFactory.SharedResource sharedResource, int[] iattributes) {
+ static int fillAttribsForGeneralWGLARBQuery(final WindowsWGLDrawableFactory.SharedResource sharedResource, final IntBuffer iattributes) {
int niattribs = 0;
- iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB;
+ iattributes.put(niattribs++, WGLExt.WGL_DRAW_TO_WINDOW_ARB);
if(sharedResource.hasARBPBuffer()) {
- iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB;
- }
- iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_BITMAP_ARB;
- iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB;
- iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB;
- iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB;
- iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB;
- iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB;
- iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB;
- iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB;
- iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB;
- iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB;
- iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB;
- iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB;
- iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB;
- iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB;
- iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB;
- iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB;
+ iattributes.put(niattribs++, WGLExt.WGL_DRAW_TO_PBUFFER_ARB);
+ }
+ iattributes.put(niattribs++, WGLExt.WGL_DRAW_TO_BITMAP_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_ACCELERATION_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_SUPPORT_OPENGL_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_DEPTH_BITS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_STENCIL_BITS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_DOUBLE_BUFFER_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_STEREO_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_PIXEL_TYPE_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_RED_BITS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_GREEN_BITS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_BLUE_BITS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_ALPHA_BITS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_ACCUM_RED_BITS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_ACCUM_GREEN_BITS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_ACCUM_BLUE_BITS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_ACCUM_ALPHA_BITS_ARB);
if(sharedResource.hasARBMultisample()) {
- iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB;
- iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB;
+ iattributes.put(niattribs++, WGLExt.WGL_SAMPLE_BUFFERS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_SAMPLES_ARB);
}
-
- if(sharedResource.hasARBPBuffer()) {
- GLContextImpl sharedCtx = sharedResource.getContext();
- if(null != sharedCtx && sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer)) {
- // pbo float buffer
- iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; // nvidia
- }
- }
-
return niattribs;
}
-
- static boolean wglARBPFIDValid(WindowsWGLContext sharedCtx, long hdc, int pfdID) {
- int[] in = new int[1];
- int[] out = new int[1];
- in[0] = WGLExt.WGL_COLOR_BITS_ARB;
- if (!sharedCtx.getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, 1, in, 0, out, 0)) {
+
+ static boolean wglARBPFIDValid(final WindowsWGLContext sharedCtx, final long hdc, final int pfdID) {
+ final IntBuffer out = Buffers.newDirectIntBuffer(1);
+ final IntBuffer in = Buffers.newDirectIntBuffer(1);
+ in.put(0, WGLExt.WGL_COLOR_BITS_ARB);
+ if (!sharedCtx.getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, 1, in, out)) {
// Some GPU's falsely fails with a zero error code (success)
return GDI.GetLastError() == GDI.ERROR_SUCCESS ;
}
return true;
}
- static int wglARBPFDIDCount(WindowsWGLContext sharedCtx, long hdc) {
- int[] iattributes = new int[1];
- int[] iresults = new int[1];
+ static int wglARBPFDIDCount(final WindowsWGLContext sharedCtx, final long hdc) {
+ final IntBuffer iresults = Buffers.newDirectIntBuffer(1);
+ final IntBuffer iattributes = Buffers.newDirectIntBuffer(1);
+ iattributes.put(0, WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB);
- WGLExt wglExt = sharedCtx.getWGLExt();
- iattributes[0] = WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB;
+ final WGLExt wglExt = sharedCtx.getWGLExt();
// pfdID shall be ignored here (spec), however, pass a valid pdf index '1' below (possible driver bug)
- if (!wglExt.wglGetPixelFormatAttribivARB(hdc, 1 /* pfdID */, 0, 1, iattributes, 0, iresults, 0)) {
+ if (!wglExt.wglGetPixelFormatAttribivARB(hdc, 1 /* pfdID */, 0, 1, iattributes, iresults)) {
if(DEBUG) {
System.err.println("GetPixelFormatAttribivARB: Failed - HDC 0x" + Long.toHexString(hdc) +
- ", value "+iresults[0]+
+ ", value "+iresults.get(0)+
", LastError: " + GDI.GetLastError());
Thread.dumpStack();
}
return 0;
}
- final int pfdIDCount = iresults[0];
+ final int pfdIDCount = iresults.get(0);
if(0 == pfdIDCount) {
if(DEBUG) {
System.err.println("GetPixelFormatAttribivARB: No formats - HDC 0x" + Long.toHexString(hdc) +
@@ -300,42 +295,60 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
return pfdIDCount;
}
-
- static int[] wglAllARBPFDIDs(int pfdIDCount) {
- int[] pfdIDs = new int[pfdIDCount];
+
+ static int[] wglAllARBPFDIDs(final int pfdIDCount) {
+ final int[] pfdIDs = new int[pfdIDCount];
for (int i = 0; i < pfdIDCount; i++) {
pfdIDs[i] = 1 + i;
}
return pfdIDs;
}
-
- static WGLGLCapabilities wglARBPFID2GLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource,
- AbstractGraphicsDevice device, GLProfile glp,
- long hdc, int pfdID, int winattrbits) {
+
+ static WGLGLCapabilities wglARBPFID2GLCapabilities(final WindowsWGLDrawableFactory.SharedResource sharedResource,
+ final AbstractGraphicsDevice device, final GLProfile glp,
+ final long hdc, final int pfdID, final int winattrbits) {
if (!sharedResource.hasARBPixelFormat()) {
return null;
}
- int[] iattributes = new int [2*MAX_ATTRIBS];
- int[] iresults = new int [2*MAX_ATTRIBS];
-
- int niattribs = fillAttribsForGeneralWGLARBQuery(sharedResource, iattributes);
+ final IntBuffer iattributes = Buffers.newDirectIntBuffer(2*MAX_ATTRIBS);
+ final IntBuffer iresults = Buffers.newDirectIntBuffer(2*MAX_ATTRIBS);
+ final int niattribs = fillAttribsForGeneralWGLARBQuery(sharedResource, iattributes);
- if (!((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, 0, iresults, 0)) {
- throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format " + pfdID +
+ if ( !( (WindowsWGLContext)sharedResource.getContext()).getWGLExt()
+ .wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, iresults) ) {
+ throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format " + pfdID +
" of device context " + toHexString(hdc) + ", werr " + GDI.GetLastError());
}
return AttribList2GLCapabilities(device, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits);
}
- static int[] wglChoosePixelFormatARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device,
- GLCapabilitiesImmutable capabilities,
- long hdc, int[] iattributes, int accelerationMode, float[] fattributes)
+ static WGLGLCapabilities wglARBPFID2GLCapabilitiesNoCheck(final WindowsWGLDrawableFactory.SharedResource sharedResource,
+ final AbstractGraphicsDevice device, final GLProfile glp,
+ final long hdc, final int pfdID, final int winattrbits) {
+ if (!sharedResource.hasARBPixelFormat()) {
+ return null;
+ }
+
+ final IntBuffer iattributes = Buffers.newDirectIntBuffer(2 * MAX_ATTRIBS);
+ final IntBuffer iresults = Buffers.newDirectIntBuffer(2 * MAX_ATTRIBS);
+ final int niattribs = fillAttribsForGeneralWGLARBQuery(sharedResource, iattributes);
+
+ if ( !( (WindowsWGLContext)sharedResource.getContext()).getWGLExt()
+ .wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, iresults) ) {
+ throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format "
+ + pfdID + " of device context " + toHexString(hdc) + ", werr " + GDI.GetLastError());
+ }
+ return AttribList2GLCapabilitiesNoCheck(device, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits);
+ }
+
+ static int[] wglChoosePixelFormatARB(final WindowsWGLDrawableFactory.SharedResource sharedResource,
+ final AbstractGraphicsDevice device, final GLCapabilitiesImmutable capabilities,
+ final long hdc, final IntBuffer iattributes, final int accelerationMode,
+ final FloatBuffer fattributes)
{
-
- if ( !WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities,
- iattributes, sharedResource, accelerationMode, null))
- {
+ if ( !WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList( sharedResource, capabilities,
+ iattributes, accelerationMode, null) ) {
if (DEBUG) {
System.err.println("wglChoosePixelFormatARB: GLCapabilities2AttribList failed: " + GDI.GetLastError());
Thread.dumpStack();
@@ -343,62 +356,74 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
return null;
}
- int[] pformatsTmp = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS];
- int[] numFormatsTmp = new int[1];
- if ( !((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglChoosePixelFormatARB(hdc, iattributes, 0,
- fattributes, 0,
- WindowsWGLGraphicsConfiguration.MAX_PFORMATS,
- pformatsTmp, 0, numFormatsTmp, 0))
- {
+ final WGLExt wglExt = ((WindowsWGLContext)sharedResource.getContext()).getWGLExt();
+ final IntBuffer pformatsTmp = Buffers.newDirectIntBuffer(WindowsWGLGraphicsConfiguration.MAX_PFORMATS);
+ final IntBuffer numFormatsTmp = Buffers.newDirectIntBuffer(1);
+
+ if ( !wglExt.wglChoosePixelFormatARB(hdc, iattributes, fattributes,
+ WindowsWGLGraphicsConfiguration.MAX_PFORMATS,
+ pformatsTmp, numFormatsTmp) ) {
if (DEBUG) {
System.err.println("wglChoosePixelFormatARB: wglChoosePixelFormatARB failed: " + GDI.GetLastError());
Thread.dumpStack();
}
return null;
}
- int numFormats = numFormatsTmp[0];
- int[] pformats = null;
+ final int numFormats = Math.min(numFormatsTmp.get(0), WindowsWGLGraphicsConfiguration.MAX_PFORMATS);
+ final int[] pformats;
if( 0 < numFormats ) {
pformats = new int[numFormats];
- System.arraycopy(pformatsTmp, 0, pformats, 0, numFormats);
+ pformatsTmp.get(pformats, 0, numFormats);
+ } else {
+ pformats = null;
}
if (DEBUG) {
System.err.println("wglChoosePixelFormatARB: NumFormats (wglChoosePixelFormatARB) accelMode 0x"
+ Integer.toHexString(accelerationMode) + ": " + numFormats);
for (int i = 0; i < numFormats; i++) {
- WGLGLCapabilities dbgCaps0 = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(
- sharedResource, device, capabilities.getGLProfile(), hdc, pformats[i], GLGraphicsConfigurationUtil.ALL_BITS);
+ final WGLGLCapabilities dbgCaps0 = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(
+ sharedResource, device, capabilities.getGLProfile(), hdc,
+ pformats[i], GLGraphicsConfigurationUtil.ALL_BITS);
System.err.println("pixel format " + pformats[i] + " (index " + i + "): " + dbgCaps0);
}
}
return pformats;
}
- static List <GLCapabilitiesImmutable> wglARBPFIDs2GLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource,
- AbstractGraphicsDevice device, GLProfile glp, long hdc, int[] pfdIDs, int winattrbits) {
+ static List <GLCapabilitiesImmutable> wglARBPFIDs2GLCapabilities(final WindowsWGLDrawableFactory.SharedResource sharedResource,
+ final AbstractGraphicsDevice device, final GLProfile glp,
+ final long hdc, final int[] pfdIDs, final int winattrbits,
+ final boolean onlyFirstValid) {
if (!sharedResource.hasARBPixelFormat()) {
return null;
}
final int numFormats = pfdIDs.length;
- int[] iattributes = new int [2*MAX_ATTRIBS];
- int[] iresults = new int [2*MAX_ATTRIBS];
- int niattribs = fillAttribsForGeneralWGLARBQuery(sharedResource, iattributes);
+ final IntBuffer iattributes = Buffers.newDirectIntBuffer(2*MAX_ATTRIBS);
+ final IntBuffer iresults = Buffers.newDirectIntBuffer(2*MAX_ATTRIBS);
+ final int niattribs = fillAttribsForGeneralWGLARBQuery(sharedResource, iattributes);
- ArrayList<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>();
+ final ArrayList<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>();
for(int i = 0; i<numFormats; i++) {
if ( pfdIDs[i] >= 1 &&
- ((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) {
- final GLCapabilitiesImmutable caps = AttribList2GLCapabilities(device, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits);
+ ((WindowsWGLContext)sharedResource.getContext()).getWGLExt()
+ .wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, iresults) ) {
+ final GLCapabilitiesImmutable caps =
+ AttribList2GLCapabilities(device, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits);
if(null != caps) {
bucket.add(caps);
if(DEBUG) {
- final int j = bucket.size() - 1;
+ final int j = bucket.size() - 1;
System.err.println("wglARBPFIDs2GLCapabilities: bucket["+i+" -> "+j+"]: "+caps);
}
+ if( onlyFirstValid ) {
+ break;
+ }
} else if(DEBUG) {
- GLCapabilitiesImmutable skipped = AttribList2GLCapabilities(device, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, GLGraphicsConfigurationUtil.ALL_BITS);
+ final GLCapabilitiesImmutable skipped =
+ AttribList2GLCapabilitiesNoCheck(device, glp, hdc, pfdIDs[i],
+ iattributes, niattribs, iresults, GLGraphicsConfigurationUtil.ALL_BITS);
System.err.println("wglARBPFIDs2GLCapabilities: bucket["+i+" -> skip]: pfdID "+pfdIDs[i]+", "+skipped+", winattr "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString());
}
} else if (DEBUG) {
@@ -413,29 +438,29 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
return bucket;
}
- static boolean GLCapabilities2AttribList(GLCapabilitiesImmutable caps,
- int[] iattributes,
- WindowsWGLDrawableFactory.SharedResource sharedResource,
- int accelerationValue,
- int[] floatMode) throws GLException {
+ static boolean GLCapabilities2AttribList(final WindowsWGLDrawableFactory.SharedResource sharedResource,
+ final GLCapabilitiesImmutable caps,
+ final IntBuffer iattributes,
+ final int accelerationValue,
+ final int[] floatMode) throws GLException {
if (!sharedResource.hasARBPixelFormat()) {
return false;
}
int niattribs = 0;
- iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
+ iattributes.put(niattribs++, WGLExt.WGL_SUPPORT_OPENGL_ARB);
+ iattributes.put(niattribs++, GL.GL_TRUE);
if(accelerationValue>0) {
- iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB;
- iattributes[niattribs++] = accelerationValue;
+ iattributes.put(niattribs++, WGLExt.WGL_ACCELERATION_ARB);
+ iattributes.put(niattribs++, accelerationValue);
}
final boolean usePBuffer = caps.isPBuffer() && sharedResource.hasARBPBuffer() ;
-
+
final int surfaceType;
if( caps.isOnscreen() ) {
- surfaceType = WGLExt.WGL_DRAW_TO_WINDOW_ARB;
+ surfaceType = WGLExt.WGL_DRAW_TO_WINDOW_ARB;
} else if( caps.isFBO() ) {
surfaceType = WGLExt.WGL_DRAW_TO_WINDOW_ARB; // native replacement!
} else if( usePBuffer ) {
@@ -445,169 +470,96 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
} else {
throw new GLException("no surface type set in caps: "+caps);
}
- iattributes[niattribs++] = surfaceType;
- iattributes[niattribs++] = GL.GL_TRUE;
-
- iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB;
+ iattributes.put(niattribs++, surfaceType);
+ iattributes.put(niattribs++, GL.GL_TRUE);
+
+ iattributes.put(niattribs++, WGLExt.WGL_DOUBLE_BUFFER_ARB);
if (caps.getDoubleBuffered()) {
- iattributes[niattribs++] = GL.GL_TRUE;
+ iattributes.put(niattribs++, GL.GL_TRUE);
} else {
- iattributes[niattribs++] = GL.GL_FALSE;
+ iattributes.put(niattribs++, GL.GL_FALSE);
}
- iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB;
+ iattributes.put(niattribs++, WGLExt.WGL_STEREO_ARB);
if (caps.getStereo()) {
- iattributes[niattribs++] = GL.GL_TRUE;
+ iattributes.put(niattribs++, GL.GL_TRUE);
} else {
- iattributes[niattribs++] = GL.GL_FALSE;
- }
-
- iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB;
- iattributes[niattribs++] = caps.getRedBits();
- iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB;
- iattributes[niattribs++] = caps.getGreenBits();
- iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB;
- iattributes[niattribs++] = caps.getBlueBits();
+ iattributes.put(niattribs++, GL.GL_FALSE);
+ }
+
+ iattributes.put(niattribs++, WGLExt.WGL_RED_BITS_ARB);
+ iattributes.put(niattribs++, caps.getRedBits());
+ iattributes.put(niattribs++, WGLExt.WGL_GREEN_BITS_ARB);
+ iattributes.put(niattribs++, caps.getGreenBits());
+ iattributes.put(niattribs++, WGLExt.WGL_BLUE_BITS_ARB);
+ iattributes.put(niattribs++, caps.getBlueBits());
if(caps.getAlphaBits()>0) {
- iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB;
- iattributes[niattribs++] = caps.getAlphaBits();
+ iattributes.put(niattribs++, WGLExt.WGL_ALPHA_BITS_ARB);
+ iattributes.put(niattribs++, caps.getAlphaBits());
}
if(caps.getStencilBits()>0) {
- iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB;
- iattributes[niattribs++] = caps.getStencilBits();
+ iattributes.put(niattribs++, WGLExt.WGL_STENCIL_BITS_ARB);
+ iattributes.put(niattribs++, caps.getStencilBits());
}
- iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB;
- iattributes[niattribs++] = caps.getDepthBits();
- if (caps.getAccumRedBits() > 0 ||
+ iattributes.put(niattribs++, WGLExt.WGL_DEPTH_BITS_ARB);
+ iattributes.put(niattribs++, caps.getDepthBits());
+
+ if( caps.getAccumRedBits() > 0 ||
caps.getAccumGreenBits() > 0 ||
caps.getAccumBlueBits() > 0 ||
- caps.getAccumAlphaBits() > 0) {
- iattributes[niattribs++] = WGLExt.WGL_ACCUM_BITS_ARB;
- iattributes[niattribs++] = (caps.getAccumRedBits() +
- caps.getAccumGreenBits() +
- caps.getAccumBlueBits() +
- caps.getAccumAlphaBits());
- iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB;
- iattributes[niattribs++] = caps.getAccumRedBits();
- iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB;
- iattributes[niattribs++] = caps.getAccumGreenBits();
- iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB;
- iattributes[niattribs++] = caps.getAccumBlueBits();
- iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB;
- iattributes[niattribs++] = caps.getAccumAlphaBits();
+ caps.getAccumAlphaBits() > 0 ) {
+ final GLRendererQuirks sharedQuirks = sharedResource.getRendererQuirks();
+ if ( !usePBuffer || null==sharedQuirks || !sharedQuirks.exist(GLRendererQuirks.NoPBufferWithAccum) ) {
+ iattributes.put(niattribs++, WGLExt.WGL_ACCUM_BITS_ARB);
+ iattributes.put(niattribs++, ( caps.getAccumRedBits() +
+ caps.getAccumGreenBits() +
+ caps.getAccumBlueBits() +
+ caps.getAccumAlphaBits() ) );
+ iattributes.put(niattribs++, WGLExt.WGL_ACCUM_RED_BITS_ARB);
+ iattributes.put(niattribs++, caps.getAccumRedBits());
+ iattributes.put(niattribs++, WGLExt.WGL_ACCUM_GREEN_BITS_ARB);
+ iattributes.put(niattribs++, caps.getAccumGreenBits());
+ iattributes.put(niattribs++, WGLExt.WGL_ACCUM_BLUE_BITS_ARB);
+ iattributes.put(niattribs++, caps.getAccumBlueBits());
+ iattributes.put(niattribs++, WGLExt.WGL_ACCUM_ALPHA_BITS_ARB);
+ iattributes.put(niattribs++, caps.getAccumAlphaBits());
+ }
}
if (caps.getSampleBuffers() && sharedResource.hasARBMultisample()) {
- iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
- iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB;
- iattributes[niattribs++] = caps.getNumSamples();
- }
-
- boolean rtt = caps.getPbufferRenderToTexture();
- boolean rect = caps.getPbufferRenderToTextureRectangle();
- boolean useFloat = caps.getPbufferFloatingPointBuffers();
- boolean ati = false;
- boolean nvidia = false;
- if ( usePBuffer ) {
- // Check some invariants and set up some state
- if (rect && !rtt) {
- throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified");
- }
-
- GLContextImpl sharedCtx = sharedResource.getContext();
- if (rect) {
- if (!sharedCtx.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) {
- throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension");
- }
- }
-
- if (useFloat) {
- // Prefer NVidia extension over ATI
- nvidia = sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer);
- if(nvidia) {
- floatMode[0] = GLPbuffer.NV_FLOAT;
- } else {
- ati = sharedCtx.isExtensionAvailable("WGL_ATI_pixel_format_float");
- if(ati) {
- floatMode[0] = GLPbuffer.ATI_FLOAT;
- } else {
- throw new GLException("Floating-point pbuffers not supported by this hardware");
- }
- }
-
- if (DEBUG) {
- System.err.println("Using " + (ati ? "ATI" : ( nvidia ? "NVidia" : "NONE" ) ) + " floating-point extension");
- }
- }
-
- // See whether we need to change the pixel type to support ATI's
- // floating-point pbuffers
- if (useFloat && ati) {
- if (rtt) {
- throw new GLException("Render-to-floating-point-texture not supported on ATI hardware");
- } else {
- iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB;
- iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_FLOAT_ARB;
- }
- } else {
- if (!rtt) {
- // Currently we don't support non-truecolor visuals in the
- // GLCapabilities, so we don't offer the option of making
- // color-index pbuffers.
- iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB;
- iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB;
- }
- }
-
- if (useFloat && nvidia) {
- iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV;
- iattributes[niattribs++] = GL.GL_TRUE;
- }
-
- if (rtt) {
- if (useFloat) {
- assert(!ati);
- assert(nvidia);
- if (!rect) {
- throw new GLException("Render-to-floating-point-texture only supported on NVidia hardware with render-to-texture-rectangle");
- }
- iattributes[niattribs++] = WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV;
- iattributes[niattribs++] = GL.GL_TRUE;
- } else {
- iattributes[niattribs++] = rect ? WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : WGLExt.WGL_BIND_TO_TEXTURE_RGB_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
- }
- }
- } else {
- iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB;
- iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB;
+ iattributes.put(niattribs++, WGLExt.WGL_SAMPLE_BUFFERS_ARB);
+ iattributes.put(niattribs++, GL.GL_TRUE);
+ iattributes.put(niattribs++, WGLExt.WGL_SAMPLES_ARB);
+ iattributes.put(niattribs++, caps.getNumSamples());
}
- iattributes[niattribs++] = 0;
+
+ iattributes.put(niattribs++, WGLExt.WGL_PIXEL_TYPE_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_TYPE_RGBA_ARB);
+ iattributes.put(niattribs++, 0);
return true;
}
- static int AttribList2DrawableTypeBits(final int[] iattribs,
- final int niattribs, final int[] iresults) {
+ static int AttribList2DrawableTypeBits(final IntBuffer iattribs,
+ final int niattribs, final IntBuffer iresults) {
int val = 0;
for (int i = 0; i < niattribs; i++) {
- int attr = iattribs[i];
+ final int attr = iattribs.get(i);
switch (attr) {
case WGLExt.WGL_DRAW_TO_WINDOW_ARB:
- if(iresults[i] == GL.GL_TRUE) {
+ if(iresults.get(i) == GL.GL_TRUE) {
val |= GLGraphicsConfigurationUtil.WINDOW_BIT |
GLGraphicsConfigurationUtil.FBO_BIT;
}
break;
case WGLExt.WGL_DRAW_TO_BITMAP_ARB:
- if(iresults[i] == GL.GL_TRUE) {
+ if(iresults.get(i) == GL.GL_TRUE) {
val |= GLGraphicsConfigurationUtil.BITMAP_BIT;
}
break;
case WGLExt.WGL_DRAW_TO_PBUFFER_ARB:
- if(iresults[i] == GL.GL_TRUE) {
+ if(iresults.get(i) == GL.GL_TRUE) {
val |= GLGraphicsConfigurationUtil.PBUFFER_BIT;
}
break;
@@ -616,20 +568,23 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
return val;
}
- static WGLGLCapabilities AttribList2GLCapabilities(final AbstractGraphicsDevice device,
+ static WGLGLCapabilities AttribList2GLCapabilities(final AbstractGraphicsDevice device,
final GLProfile glp, final long hdc, final int pfdID,
- final int[] iattribs, final int niattribs, final int[] iresults, final int winattrmask) {
+ final IntBuffer iattribs, final int niattribs, final IntBuffer iresults,
+ final int winattrmask) {
final int allDrawableTypeBits = AttribList2DrawableTypeBits(iattribs, niattribs, iresults);
int drawableTypeBits = winattrmask & allDrawableTypeBits;
if( 0 == drawableTypeBits ) {
return null;
}
- PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor();
+ final PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor();
- if (WGLUtil.DescribePixelFormat(hdc, pfdID, PIXELFORMATDESCRIPTOR.size(), pfd) == 0) {
+ if ( WGLUtil.DescribePixelFormat(hdc, pfdID, PIXELFORMATDESCRIPTOR.size(), pfd) == 0 ) {
// remove displayable bits, since pfdID is non displayable
- drawableTypeBits = drawableTypeBits & ~(GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.BITMAP_BIT | GLGraphicsConfigurationUtil.FBO_BIT );
+ drawableTypeBits = drawableTypeBits & ~( GLGraphicsConfigurationUtil.WINDOW_BIT |
+ GLGraphicsConfigurationUtil.BITMAP_BIT |
+ GLGraphicsConfigurationUtil.FBO_BIT );
if( 0 == drawableTypeBits ) {
return null;
}
@@ -637,30 +592,50 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp);
res.setValuesByARB(iattribs, niattribs, iresults);
- return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
+ return (WGLGLCapabilities) GLGraphicsConfigurationUtil
+ .fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
}
+ static WGLGLCapabilities AttribList2GLCapabilitiesNoCheck(final AbstractGraphicsDevice device, final GLProfile glp,
+ final long hdc, final int pfdID,
+ final IntBuffer iattribs, final int niattribs,
+ final IntBuffer iresults, final int winattrmask) {
+ final int allDrawableTypeBits = AttribList2DrawableTypeBits(iattribs, niattribs, iresults);
+ final int drawableTypeBits = winattrmask & allDrawableTypeBits;
+
+ if (0 == drawableTypeBits) {
+ return null;
+ }
+ final PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor();
+
+ WGLUtil.DescribePixelFormat(hdc, pfdID, PIXELFORMATDESCRIPTOR.size(), pfd);
+ final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp);
+ res.setValuesByARB(iattribs, niattribs, iresults);
+ return (WGLGLCapabilities) GLGraphicsConfigurationUtil
+ .fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
+ }
+
//
// GDI PIXELFORMAT
//
- static int[] wglAllGDIPFIDs(long hdc) {
- int numFormats = WGLUtil.DescribePixelFormat(hdc, 1, 0, null);
+ static int[] wglAllGDIPFIDs(final long hdc) {
+ final int numFormats = WGLUtil.DescribePixelFormat(hdc, 1, 0, null);
if (numFormats == 0) {
throw new GLException("DescribePixelFormat: No formats - HDC 0x" + Long.toHexString(hdc) +
", LastError: " + GDI.GetLastError());
}
- int[] pfdIDs = new int[numFormats];
+ final int[] pfdIDs = new int[numFormats];
for (int i = 0; i < numFormats; i++) {
pfdIDs[i] = 1 + i;
}
return pfdIDs;
}
- static int PFD2DrawableTypeBits(PIXELFORMATDESCRIPTOR pfd) {
+ static int PFD2DrawableTypeBits(final PIXELFORMATDESCRIPTOR pfd) {
int val = 0;
- int dwFlags = pfd.getDwFlags();
+ final int dwFlags = pfd.getDwFlags();
if( 0 != (GDI.PFD_DRAW_TO_WINDOW & dwFlags ) ) {
val |= GLGraphicsConfigurationUtil.WINDOW_BIT |
@@ -672,43 +647,59 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
return val;
}
- static WGLGLCapabilities PFD2GLCapabilities(AbstractGraphicsDevice device, final GLProfile glp, final long hdc, final int pfdID, final int winattrmask) {
- PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID);
+ static WGLGLCapabilities PFD2GLCapabilities(final AbstractGraphicsDevice device, final GLProfile glp,
+ final long hdc, final int pfdID, final int winattrmask) {
+ final PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID);
if(null == pfd) {
return null;
}
- if ((pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) {
+ if ( (pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) {
return null;
}
final int allDrawableTypeBits = PFD2DrawableTypeBits(pfd);
final int drawableTypeBits = winattrmask & allDrawableTypeBits;
if( 0 == drawableTypeBits ) {
+ if(DEBUG) {
+ System.err.println("Drop [drawableType mismatch]: " + WGLGLCapabilities.PFD2String(pfd, pfdID));
+ }
return null;
}
+ if( GLGraphicsConfigurationUtil.BITMAP_BIT == drawableTypeBits ) {
+ // BITMAP exclusive PFD SafeGuard: Only accept BITMAP compatible color formats!
+ final int pfdColorBits = pfd.getCColorBits();
+ if ( pfdColorBits != 24 || 0 < pfd.getCAlphaBits() ) { // Allowed: RGB888 && !alpha
+ if(DEBUG) {
+ System.err.println("Drop [color bits excl BITMAP]: " + WGLGLCapabilities.PFD2String(pfd, pfdID));
+ }
+ return null;
+ }
+ }
final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp);
res.setValuesByGDI();
- return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
+ return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
}
- static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(AbstractGraphicsDevice device, final GLProfile glp, final long hdc, final int pfdID) {
- PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID);
+ static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(final AbstractGraphicsDevice device, final GLProfile glp,
+ final long hdc, final int pfdID) {
+ final PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID);
return PFD2GLCapabilitiesNoCheck(device, glp, pfd, pfdID);
}
-
- static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(AbstractGraphicsDevice device, GLProfile glp, PIXELFORMATDESCRIPTOR pfd, int pfdID) {
+
+ static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(final AbstractGraphicsDevice device, final GLProfile glp,
+ final PIXELFORMATDESCRIPTOR pfd, final int pfdID) {
if(null == pfd) {
return null;
}
final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp);
res.setValuesByGDI();
-
- return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, PFD2DrawableTypeBits(pfd), res);
+
+ return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, PFD2DrawableTypeBits(pfd), res);
}
-
- static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(GLCapabilitiesImmutable caps, PIXELFORMATDESCRIPTOR pfd) {
- int colorDepth = (caps.getRedBits() +
+
+ static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(final GLCapabilitiesImmutable caps, final PIXELFORMATDESCRIPTOR pfd) {
+ final int colorDepth = (caps.getRedBits() +
caps.getGreenBits() +
caps.getBlueBits());
if (colorDepth < 15) {
@@ -735,7 +726,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
pfdFlags |= GDI.PFD_DOUBLEBUFFER;
}
}
-
+
if (caps.getStereo()) {
pfdFlags |= GDI.PFD_STEREO;
}
@@ -746,7 +737,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
pfd.setCGreenBits((byte) caps.getGreenBits());
pfd.setCBlueBits ((byte) caps.getBlueBits());
pfd.setCAlphaBits((byte) caps.getAlphaBits());
- int accumDepth = (caps.getAccumRedBits() +
+ final int accumDepth = (caps.getAccumRedBits() +
caps.getAccumGreenBits() +
caps.getAccumBlueBits());
pfd.setCAccumBits ((byte) accumDepth);
@@ -765,8 +756,8 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
return pfd;
}
- static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor(long hdc, int pfdID) {
- PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create();
+ static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor(final long hdc, final int pfdID) {
+ final PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create();
pfd.setNSize((short) PIXELFORMATDESCRIPTOR.size());
pfd.setNVersion((short) 1);
if(0 != hdc && 1 <= pfdID) {
@@ -785,6 +776,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
return createPixelFormatDescriptor(0, 0);
}
+ @Override
public String toString() {
return "WindowsWGLGraphicsConfiguration["+getScreen()+", pfdID " + getPixelFormatID() + ", ARB-Choosen " + isChoosenByARB() +
",\n\trequested " + getRequestedCapabilities() +
@@ -792,4 +784,3 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
"]";
}
}
-
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
index d2d1dafc8..ea9b86712 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -50,12 +50,17 @@ import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.GLRendererQuirks;
+
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLGraphicsConfigurationFactory;
import jogamp.opengl.GLGraphicsConfigurationUtil;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -69,13 +74,17 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
static VisualIDHolder.VIDComparator PfdIDComparator = new VisualIDHolder.VIDComparator(VisualIDHolder.VIDType.WIN32_PFD);
static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.windows.WindowsGraphicsDevice.class, GLCapabilitiesImmutable.class, new WindowsWGLGraphicsConfigurationFactory());
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.windows.WindowsGraphicsDevice.class,
+ GLCapabilitiesImmutable.class, new WindowsWGLGraphicsConfigurationFactory());
}
private WindowsWGLGraphicsConfigurationFactory() {
}
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested, final CapabilitiesChooser chooser,
+ final AbstractGraphicsScreen absScreen, final int nativeVisualID)
+ {
if (! (capsChosen instanceof GLCapabilitiesImmutable) ) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - chosen");
@@ -88,65 +97,71 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects");
}
-
- return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, (GLCapabilitiesChooser)chooser, absScreen);
+
+ return chooseGraphicsConfigurationStatic(
+ (GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, (GLCapabilitiesChooser)chooser, absScreen);
}
- static WindowsWGLGraphicsConfiguration createDefaultGraphicsConfiguration(GLCapabilitiesImmutable caps,
- AbstractGraphicsScreen absScreen) {
+ static WindowsWGLGraphicsConfiguration createDefaultGraphicsConfiguration(final GLCapabilitiesImmutable caps,
+ final AbstractGraphicsScreen absScreen) {
return chooseGraphicsConfigurationStatic(caps, caps, null, absScreen);
}
static WindowsWGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
- GLCapabilitiesImmutable capsReq,
- GLCapabilitiesChooser chooser,
+ final GLCapabilitiesImmutable capsReq,
+ final GLCapabilitiesChooser chooser,
AbstractGraphicsScreen absScreen) {
if(null==absScreen) {
absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
}
final AbstractGraphicsDevice absDevice = absScreen.getDevice();
- final GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory();
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities(
- capsChosen, GLContext.isFBOAvailable(absDevice, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(absDevice) );
-
- return new WindowsWGLGraphicsConfiguration( absScreen, capsChosen, capsReq, (GLCapabilitiesChooser)chooser );
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLDrawableFactory.getDesktopFactory(), absDevice);
+ return new WindowsWGLGraphicsConfiguration( absScreen, capsChosen, capsReq, chooser );
}
- protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(WindowsWGLDrawableFactory factory, AbstractGraphicsDevice device) {
- final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(final WindowsWGLDrawableFactory factory,
+ final AbstractGraphicsDevice device) {
+ final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
final GLDrawableImpl sharedDrawable = sharedResource.getDrawable();
- final GLContext sharedContext = sharedResource.getContext();
final GLProfile glp = GLProfile.getDefault(device);
List<GLCapabilitiesImmutable> availableCaps = null;
-
- if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) {
+
+ final GLContext sharedContext;
+ if ( factory.hasRendererQuirk(device, GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries) ) {
+ sharedContext = sharedResource.getContext();
if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
throw new GLException("Could not make Shared Context current: "+device);
}
} else {
+ sharedContext = null;
sharedDrawable.lockSurface();
}
try {
- long hdc = sharedDrawable.getHandle();
+ final long hdc = sharedDrawable.getHandle();
if (0 == hdc) {
throw new GLException("Error: HDC is null");
}
if (sharedResource.hasARBPixelFormat()) {
- availableCaps = WindowsWGLGraphicsConfigurationFactory.getAvailableGLCapabilitiesARB(sharedResource, sharedResource.getDevice(), glp, hdc);
+ availableCaps = WindowsWGLGraphicsConfigurationFactory.getAvailableGLCapabilitiesARB(
+ sharedResource, sharedResource.getDevice(), glp, hdc);
}
- if( null == availableCaps || availableCaps.isEmpty() ) {
- availableCaps = getAvailableGLCapabilitiesGDI(device, glp, hdc);
+ final boolean hasARBCaps = null != availableCaps && !availableCaps.isEmpty() ;
+ final List<GLCapabilitiesImmutable> availableCapsGDI = getAvailableGLCapabilitiesGDI(device, glp, hdc, hasARBCaps);
+ if( !hasARBCaps ) {
+ availableCaps = availableCapsGDI;
+ } else {
+ availableCaps.addAll(availableCapsGDI);
}
} finally {
- if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) {
- sharedContext.release();
+ if ( null != sharedContext ) {
+ sharedContext.release();
} else {
sharedDrawable.unlockSurface();
- }
+ }
}
if( null != availableCaps && availableCaps.size() > 1 ) {
@@ -155,18 +170,25 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
return availableCaps;
}
- static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, GLProfile glProfile, long hdc) {
+ private static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesARB(
+ final WindowsWGLDrawableFactory.SharedResource sharedResource,
+ final AbstractGraphicsDevice device, final GLProfile glProfile, final long hdc)
+ {
final int pfdIDCount = WindowsWGLGraphicsConfiguration.wglARBPFDIDCount((WindowsWGLContext)sharedResource.getContext(), hdc);
final int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFDIDs(pfdIDCount);
- return WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedResource, device, glProfile, hdc, pformats, GLGraphicsConfigurationUtil.ALL_BITS);
+ return WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedResource, device, glProfile, hdc, pformats,
+ GLGraphicsConfigurationUtil.ALL_BITS & ~GLGraphicsConfigurationUtil.BITMAP_BIT, false); // w/o BITMAP
}
- static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesGDI(AbstractGraphicsDevice device, GLProfile glProfile, long hdc) {
- int[] pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc);
- int numFormats = pformats.length;
- List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(numFormats);
+ private static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesGDI(
+ final AbstractGraphicsDevice device, final GLProfile glProfile, final long hdc, final boolean bitmapOnly)
+ {
+ final int[] pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc);
+ final int numFormats = pformats.length;
+ final List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(numFormats);
for (int i = 0; i < numFormats; i++) {
- final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], GLGraphicsConfigurationUtil.ALL_BITS);
+ final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i],
+ bitmapOnly ? GLGraphicsConfigurationUtil.BITMAP_BIT : GLGraphicsConfigurationUtil.ALL_BITS );
if(null != caps) {
bucket.add(caps);
}
@@ -181,8 +203,8 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
* @param ns
* @param pfIDs optional pool of preselected PixelFormat IDs, maybe null for unrestricted selection
*/
- static void updateGraphicsConfiguration(CapabilitiesChooser chooser,
- GLDrawableFactory factory, NativeSurface ns, int[] pfdIDs) {
+ static void updateGraphicsConfiguration(final CapabilitiesChooser chooser,
+ final GLDrawableFactory factory, final NativeSurface ns, final int[] pfdIDs) {
if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects");
}
@@ -197,11 +219,11 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
throw new GLException("Surface not ready (lockSurface)");
}
try {
- long hdc = ns.getSurfaceHandle();
+ final long hdc = ns.getSurfaceHandle();
if (0 == hdc) {
throw new GLException("Error: HDC is null");
}
- WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) ns.getGraphicsConfiguration();
+ final WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) ns.getGraphicsConfiguration();
if( !config.isExternal() ) {
if( !config.isDetermined() ) {
@@ -216,7 +238,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
" for device context " + toHexString(hdc) +
": error code " + GDI.GetLastError());
}
- set = true;
+ set = true;
}
if (DEBUG) {
System.err.println("setPixelFormat (post): hdc "+toHexString(hdc) +", "+pfdID+" -> "+config.getPixelFormatID()+", set: "+set);
@@ -228,9 +250,9 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
}
- static void preselectGraphicsConfiguration(CapabilitiesChooser chooser,
- GLDrawableFactory _factory, AbstractGraphicsDevice device,
- WindowsWGLGraphicsConfiguration config, int[] pfdIDs) {
+ static void preselectGraphicsConfiguration(final CapabilitiesChooser chooser,
+ final GLDrawableFactory _factory, final AbstractGraphicsDevice device,
+ final WindowsWGLGraphicsConfiguration config, final int[] pfdIDs) {
if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects");
}
@@ -243,8 +265,8 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if ( !(_factory instanceof WindowsWGLDrawableFactory) ) {
throw new GLException("GLDrawableFactory is not a WindowsWGLDrawableFactory, but: "+_factory.getClass().getSimpleName());
}
- WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory;
- WindowsWGLDrawable sharedDrawable = factory.getOrCreateSharedDrawable(device);
+ final WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory;
+ final WindowsWGLDrawable sharedDrawable = factory.getOrCreateSharedDrawable(device);
if(null == sharedDrawable) {
throw new IllegalArgumentException("Shared Drawable is null");
}
@@ -253,7 +275,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
throw new GLException("Shared Surface not ready (lockSurface): "+device+" -> "+sharedDrawable);
}
try {
- long hdc = sharedDrawable.getHandle();
+ final long hdc = sharedDrawable.getHandle();
if (0 == hdc) {
throw new GLException("Error: HDC is null");
}
@@ -263,8 +285,9 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
}
- private static void updateGraphicsConfiguration(WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser,
- GLDrawableFactory factory, long hdc, boolean extHDC, int[] pfdIDs) {
+ private static void updateGraphicsConfiguration(final WindowsWGLGraphicsConfiguration config, final CapabilitiesChooser chooser,
+ final GLDrawableFactory factory, final long hdc, final boolean extHDC,
+ final int[] pfdIDs) {
if (DEBUG) {
if(extHDC) {
System.err.println("updateGraphicsConfiguration(using shared): hdc "+toHexString(hdc));
@@ -273,17 +296,24 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
System.err.println("user chosen caps " + config.getChosenCapabilities());
}
- AbstractGraphicsDevice device = config.getScreen().getDevice();
- WindowsWGLDrawableFactory.SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(device);
- GLContext sharedContext = null;
- if (null != sharedResource && sharedResource.needsCurrentContext4ARBPFDQueries()) {
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
+ final WindowsWGLDrawableFactory.SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResourceImpl(device);
+ final GLContext sharedContext;
+ if ( factory.hasRendererQuirk(device, GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries) ) {
sharedContext = sharedResource.getContext();
if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
throw new GLException("Could not make Shared Context current: "+device);
}
+ } else {
+ sharedContext = null;
}
try {
- if( !updateGraphicsConfigurationARB((WindowsWGLDrawableFactory)factory, config, chooser, hdc, extHDC, pfdIDs) ) {
+ final GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ boolean done = false;
+ if( capsChosen.getHardwareAccelerated() && !capsChosen.isBitmap() ) {
+ done = updateGraphicsConfigurationARB((WindowsWGLDrawableFactory)factory, config, chooser, hdc, extHDC, pfdIDs);
+ }
+ if( !done ) {
updateGraphicsConfigurationGDI(config, chooser, hdc, extHDC, pfdIDs);
}
} finally {
@@ -293,10 +323,11 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
}
- private static boolean updateGraphicsConfigurationARB(WindowsWGLDrawableFactory factory, WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser,
- long hdc, boolean extHDC, int[] pformats) {
+ private static boolean updateGraphicsConfigurationARB(final WindowsWGLDrawableFactory factory,
+ final WindowsWGLGraphicsConfiguration config, final CapabilitiesChooser chooser,
+ final long hdc, final boolean extHDC, int[] pformats) {
final AbstractGraphicsDevice device = config.getScreen().getDevice();
- final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if (null == sharedResource) {
if (DEBUG) {
@@ -313,14 +344,17 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
final GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
final boolean isOpaque = capsChosen.isBackgroundOpaque() && GDI.DwmIsCompositionEnabled();
- final int winattrbits = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen);
+ final int winattrbits = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen)
+ & ~GLGraphicsConfigurationUtil.BITMAP_BIT; // w/o BITMAP
final GLProfile glProfile = capsChosen.getGLProfile();
-
+
final int pfdIDCount = WindowsWGLGraphicsConfiguration.wglARBPFDIDCount((WindowsWGLContext)sharedResource.getContext(), hdc);
-
+
if(DEBUG) {
System.err.println("updateGraphicsConfigurationARB: hdc "+toHexString(hdc)+", pfdIDCount(hdc) "+pfdIDCount+", capsChosen "+capsChosen+", "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString());
- System.err.println("isOpaque "+isOpaque+" (translucency requested: "+(!capsChosen.isBackgroundOpaque())+", compositioning enabled: "+GDI.DwmIsCompositionEnabled()+")");
+ System.err.println("\tisOpaque "+isOpaque+" (translucency requested: "+(!capsChosen.isBackgroundOpaque())+", compositioning enabled: "+GDI.DwmIsCompositionEnabled()+")");
+ final int pformatsNum = null != pformats ? pformats.length : -1;
+ System.err.println("\textHDC "+extHDC+", chooser "+(null!=chooser)+", pformatsNum "+pformatsNum);
}
if(0 >= pfdIDCount) {
@@ -329,7 +363,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
return false;
}
-
+
WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps
boolean pixelFormatSet = false; // indicates a preset PFD ID [caps]
final int presetPFDID = extHDC ? -1 : WGLUtil.GetPixelFormat(hdc) ;
@@ -343,17 +377,17 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
+ ", pixelformat " + presetPFDID);
}
pixelFormatSet = true;
- pixelFormatCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, device, glProfile, hdc, presetPFDID, winattrbits);
+ pixelFormatCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, device, glProfile,
+ hdc, presetPFDID, winattrbits);
pixelFormatCaps = (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(pixelFormatCaps, isOpaque);
} else {
int recommendedIndex = -1; // recommended index
-
if(null == pformats) {
// No given PFD IDs
//
// 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice
- int[] iattributes = new int[2 * WindowsWGLGraphicsConfiguration.MAX_ATTRIBS];
- float[] fattributes = new float[1];
+ final IntBuffer iattributes = Buffers.newDirectIntBuffer(2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS);
+ final FloatBuffer fattributes = Buffers.newDirectFloatBuffer(1);
int accelerationMode = WGLExt.WGL_FULL_ACCELERATION_ARB;
pformats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(sharedResource, device, capsChosen,
hdc, iattributes, accelerationMode, fattributes);
@@ -388,10 +422,12 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
return false;
}
}
+ final boolean skipCapsChooser = 0 <= recommendedIndex && null == chooser && capsChosen.isBackgroundOpaque(); // fast path: skip choosing if using recommended idx and null chooser is used and if not translucent
+
+ final List<GLCapabilitiesImmutable> availableCaps =
+ WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedResource, device, glProfile,
+ hdc, pformats, winattrbits, skipCapsChooser /* onlyFirstValid */);
- List<GLCapabilitiesImmutable> availableCaps =
- WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedResource, device, glProfile, hdc, pformats, winattrbits);
-
if( null == availableCaps || 0 == availableCaps.size() ) {
if (DEBUG) {
System.err.println("updateGraphicsConfigurationARB: wglARBPFIDs2GLCapabilities failed with " + pformats.length + " pfd ids");
@@ -402,14 +438,19 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if (DEBUG) {
System.err.println("updateGraphicsConfigurationARB: " + pformats.length +
- " pfd ids, " + GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString() + ", " + availableCaps.size() + " glcaps");
+ " pfd ids, skipCapsChooser " + skipCapsChooser + ", " + GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString() + ", " + availableCaps.size() + " glcaps");
if(0 <= recommendedIndex) {
System.err.println("updateGraphicsConfigurationARB: Used wglChoosePixelFormatARB to recommend pixel format " +
pformats[recommendedIndex] + ", idx " + recommendedIndex +", "+availableCaps.get(recommendedIndex));
}
}
- int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
+ final int chosenIndex;
+ if( skipCapsChooser ) {
+ chosenIndex = recommendedIndex;
+ } else {
+ chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
+ }
if ( 0 > chosenIndex ) {
if (DEBUG) {
Thread.dumpStack();
@@ -420,12 +461,12 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if( null == pixelFormatCaps) {
throw new GLException("Null Capabilities with "+
" chosen pfdID: native recommended "+ (recommendedIndex+1) +
- " chosen idx "+chosenIndex);
+ " chosen idx "+chosenIndex+", skipCapsChooser "+skipCapsChooser);
}
pixelFormatCaps = (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(pixelFormatCaps, isOpaque);
if (DEBUG) {
System.err.println("chosen pfdID (ARB): native recommended "+ (recommendedIndex+1) +
- " chosen "+pixelFormatCaps);
+ " chosen "+pixelFormatCaps+", skipCapsChooser "+skipCapsChooser);
}
}
@@ -437,9 +478,9 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
return true;
}
- private static boolean updateGraphicsConfigurationGDI(WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser, long hdc,
- boolean extHDC, int[] pformats) {
- GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ private static boolean updateGraphicsConfigurationGDI(final WindowsWGLGraphicsConfiguration config, final CapabilitiesChooser chooser,
+ final long hdc, final boolean extHDC, int[] pformats) {
+ final GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
if( !capsChosen.isOnscreen() && capsChosen.isPBuffer() ) {
if (DEBUG) {
System.err.println("updateGraphicsConfigurationGDI: no pbuffer supported on GDI: " + capsChosen);
@@ -450,29 +491,30 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
// final boolean useFBO = capsChosen.isFBO();
final GLProfile glProfile = capsChosen.getGLProfile();
final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen);
-
+
if(DEBUG) {
- System.err.println("updateGraphicsConfigurationGDI: capsChosen "+capsChosen+", "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrmask).toString());
+ System.err.println("updateGraphicsConfigurationGDI: hdc "+toHexString(hdc)+", capsChosen "+capsChosen+", "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrmask).toString());
+ final int pformatsNum = null != pformats ? pformats.length : -1;
+ System.err.println("\textHDC "+extHDC+", chooser "+(null!=chooser)+", pformatsNum "+pformatsNum);
}
-
- AbstractGraphicsDevice device = config.getScreen().getDevice();
- int pfdID; // chosen or preset PFD ID
+
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps
boolean pixelFormatSet = false; // indicates a preset PFD ID [caps]
-
- if ( !extHDC && 1 <= ( pfdID = WGLUtil.GetPixelFormat(hdc) ) ) {
+ final int presetPFDID = extHDC ? -1 : WGLUtil.GetPixelFormat(hdc) ;
+ if ( 1 <= presetPFDID ) {
// Pixelformat already set by either
// - a previous preselectGraphicsConfiguration() call on the same HDC,
// - the graphics driver, copying the HDC's pixelformat to the new one,
// - or the Java2D/OpenGL pipeline's configuration
if (DEBUG) {
System.err.println("updateGraphicsConfigurationGDI: NOTE: pixel format already chosen for HDC: " + toHexString(hdc)
- + ", pixelformat " + pfdID);
+ + ", pixelformat " + presetPFDID);
}
pixelFormatSet = true;
- pixelFormatCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pfdID, winattrmask);
+ pixelFormatCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, presetPFDID, winattrmask);
if(null == pixelFormatCaps) {
- throw new GLException("Could not map PFD2GLCaps w/ already chosen pfdID "+pfdID);
+ throw new GLException("Could not map PFD2GLCaps w/ already chosen pfdID "+presetPFDID);
}
} else {
final boolean givenPFormats = null != pformats;
@@ -480,43 +522,84 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc);
}
- List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
- for (int i = 0; i < pformats.length; i++) {
- final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], winattrmask);
- if(null != caps) {
- availableCaps.add(caps);
- if(DEBUG) {
- final int j = availableCaps.size() - 1;
- System.err.println("updateGraphicsConfigurationGDI: availableCaps["+i+" -> "+j+"]: "+caps);
- }
- } else if(DEBUG) {
- GLCapabilitiesImmutable skipped = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(device, glProfile, hdc, pformats[i]);
- System.err.println("updateGraphicsConfigurationGDI: availableCaps["+i+" -> skip]: pfdID "+pformats[i]+", "+skipped);
- }
- }
-
// 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice
+ final List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor();
pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(capsChosen, pfd);
- pfdID = WGLUtil.ChoosePixelFormat(hdc, pfd);
+ int chosenPFDID = WGLUtil.ChoosePixelFormat(hdc, pfd);
int recommendedIndex = -1 ;
- if( 1 <= pfdID ) {
+ final boolean skipCapsChooser;
+ if( 1 <= chosenPFDID ) {
+ // _skipCapsChooser: fast path: skip choosing if using recommended idx and null chooser is used and if not translucent
+ final boolean _skipCapsChooser = null == chooser && capsChosen.isBackgroundOpaque();
// seek index .. in all formats _or_ in given formats!
- for (recommendedIndex = availableCaps.size() - 1 ;
- 0 <= recommendedIndex && pfdID != ((WGLGLCapabilities) availableCaps.get(recommendedIndex)).getPFDID();
- recommendedIndex--)
- { /* nop */ }
- if(DEBUG && 0 > recommendedIndex) {
- final GLCapabilitiesImmutable reqPFDCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(device, glProfile, pfd, pfdID);
- final GLCapabilitiesImmutable chosenCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pfdID, winattrmask);
- System.err.println("Chosen PFDID "+pfdID+", but not found in available caps (use given pfdIDs "+givenPFormats+", reqPFDCaps "+reqPFDCaps+", chosenCaps: "+chosenCaps);
+ int chosenIdx;
+ for (chosenIdx = pformats.length - 1 ; 0 <= chosenIdx && chosenPFDID != pformats[chosenIdx]; chosenIdx--) { /* nop */ }
+ if( 0 <= chosenIdx ) {
+ if( _skipCapsChooser ) {
+ final WGLGLCapabilities caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc,
+ chosenPFDID, winattrmask);
+ if(null != caps) {
+ availableCaps.add(caps);
+ recommendedIndex = 0;
+ skipCapsChooser = true;
+ } else {
+ skipCapsChooser = false;
+ }
+ } else {
+ skipCapsChooser = false;
+ }
+ if( DEBUG ) {
+ System.err.println("Chosen PFDID "+chosenPFDID+" (idx "+chosenIdx+") -> recommendedIndex "+recommendedIndex+", skipCapsChooser "+skipCapsChooser);
+ }
+ } else {
+ if(DEBUG) {
+ final GLCapabilitiesImmutable reqPFDCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(device, glProfile, pfd, chosenPFDID);
+ final GLCapabilitiesImmutable chosenCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, chosenPFDID, winattrmask);
+ System.err.println("Chosen PFDID "+chosenPFDID+" (idx "+chosenIdx+"), but not found in available caps (use given pfdIDs "+givenPFormats+", reqPFDCaps "+reqPFDCaps+", chosenCaps: "+chosenCaps);
+ }
+ chosenPFDID = 0; // not found in pformats -> clear
+ skipCapsChooser = false;
}
+ } else {
+ skipCapsChooser = false;
}
if (DEBUG) {
- System.err.println("updateGraphicsConfigurationGDI: ChoosePixelFormat(HDC " + toHexString(hdc) + ") = pfdID " + pfdID + ", idx " + recommendedIndex + " (LastError: " + GDI.GetLastError() + ")");
+ System.err.println("updateGraphicsConfigurationGDI: ChoosePixelFormat(HDC " + toHexString(hdc) + ") = pfdID " + chosenPFDID + ", skipCapsChooser "+skipCapsChooser+", idx " + recommendedIndex + " (LastError: " + GDI.GetLastError() + ")");
+ }
+
+ if( !skipCapsChooser ) {
+ for (int i = 0; i < pformats.length; i++) {
+ final int pfdid = pformats[i];
+ final WGLGLCapabilities caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile,
+ hdc, pfdid, winattrmask);
+ if(null != caps) {
+ availableCaps.add(caps);
+ if(DEBUG) {
+ final int j = availableCaps.size() - 1;
+ System.err.println("updateGraphicsConfigurationGDI: availableCaps["+i+" -> "+j+"]: "+caps);
+ }
+ } else if(DEBUG) {
+ final GLCapabilitiesImmutable skipped = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(device, glProfile, hdc, pformats[i]);
+ System.err.println("updateGraphicsConfigurationGDI: availableCaps["+i+" -> skip]: pfdID "+pformats[i]+", "+skipped);
+ }
+ }
+ // seek recommendedIndex in all _or_ given formats!
+ if( 1 <= chosenPFDID && 0 > recommendedIndex) {
+ for (recommendedIndex = availableCaps.size() - 1 ;
+ 0 <= recommendedIndex && chosenPFDID != ((WGLGLCapabilities) availableCaps.get(recommendedIndex)).getPFDID();
+ recommendedIndex--)
+ { /* nop */ }
+ }
}
+
// 2nd choice: if no preferred recommendedIndex available
- int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
+ final int chosenIndex;
+ if( skipCapsChooser ) {
+ chosenIndex = recommendedIndex;
+ } else {
+ chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
+ }
if ( 0 > chosenIndex ) {
if (DEBUG) {
System.err.println("updateGraphicsConfigurationGDI: failed, return false");
@@ -526,7 +609,8 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
pixelFormatCaps = (WGLGLCapabilities) availableCaps.get(chosenIndex);
if (DEBUG) {
- System.err.println("chosen pfdID (GDI): chosenIndex "+ chosenIndex + ", caps " + pixelFormatCaps);
+ System.err.println("chosen pfdID (GDI): recommendedIndex "+recommendedIndex+" -> chosenIndex "+ chosenIndex + ", skipCapsChooser "+skipCapsChooser+", caps " + pixelFormatCaps +
+ " (" + WGLGLCapabilities.PFD2String(pixelFormatCaps.getPFD(), pixelFormatCaps.getPFDID()) +")");
}
}
@@ -538,4 +622,3 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
return true;
}
}
-
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java
index 3b2ff133a..9e784ad73 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -65,12 +65,13 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
public static void registerFactory() {
GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, GLCapabilitiesImmutable.class, new WindowsAWTWGLGraphicsConfigurationFactory());
}
- private WindowsAWTWGLGraphicsConfigurationFactory() {
+ private WindowsAWTWGLGraphicsConfigurationFactory() {
}
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, final int nativeVisualID) {
GraphicsDevice device = null;
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
@@ -83,7 +84,7 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: creating default device: "+absScreen);
}
}
- AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen;
+ final AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen;
device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice();
if ( !(capsChosen instanceof GLCapabilitiesImmutable) ) {
@@ -103,10 +104,10 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: got "+absScreen);
}
- WindowsGraphicsDevice winDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
- DefaultGraphicsScreen winScreen = new DefaultGraphicsScreen(winDevice, awtScreen.getIndex());
- GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice, capsChosen);
- WindowsWGLGraphicsConfiguration winConfig = (WindowsWGLGraphicsConfiguration)
+ final WindowsGraphicsDevice winDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+ final DefaultGraphicsScreen winScreen = new DefaultGraphicsScreen(winDevice, awtScreen.getIndex());
+ final GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice, capsChosen);
+ final WindowsWGLGraphicsConfiguration winConfig = (WindowsWGLGraphicsConfiguration)
configFactory.chooseGraphicsConfiguration(capsChosen,
capsRequested,
chooser, winScreen, nativeVisualID);
@@ -114,7 +115,7 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+winScreen);
}
- GLDrawableFactory drawableFactory = GLDrawableFactory.getFactory(((GLCapabilitiesImmutable)capsChosen).getGLProfile());
+ final GLDrawableFactory drawableFactory = GLDrawableFactory.getFactory(((GLCapabilitiesImmutable)capsChosen).getGLProfile());
GraphicsConfiguration chosenGC = null;
if ( drawableFactory instanceof WindowsWGLDrawableFactory ) {
@@ -132,13 +133,13 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: Found new AWT PFD ID "+winConfig.getPixelFormatID()+" -> "+winConfig);
}
}
- } catch (GLException gle0) {
+ } catch (final GLException gle0) {
if(DEBUG) {
gle0.printStackTrace();
}
// go on ..
}
-
+
if( null == chosenGC ) {
// 2nd Choice: Choose and match the GL Visual with AWT:
// - collect all AWT PFDs
@@ -147,15 +148,15 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
// The resulting GraphicsConfiguration has to be 'forced' on the AWT native peer,
// ie. returned by GLCanvas's getGraphicsConfiguration() befor call by super.addNotify().
//
-
+
// collect all available PFD IDs
- GraphicsConfiguration[] configs = device.getConfigurations();
- int[] pfdIDs = new int[configs.length];
- ArrayHashSet<Integer> pfdIDOSet = new ArrayHashSet<Integer>();
+ final GraphicsConfiguration[] configs = device.getConfigurations();
+ final int[] pfdIDs = new int[configs.length];
+ final ArrayHashSet<Integer> pfdIDOSet = new ArrayHashSet<Integer>();
for (int i = 0; i < configs.length; i++) {
- GraphicsConfiguration gc = configs[i];
+ final GraphicsConfiguration gc = configs[i];
pfdIDs[i] = Win32SunJDKReflection.graphicsConfigurationGetPixelFormatID(gc);
- pfdIDOSet.add(new Integer(pfdIDs[i]));
+ pfdIDOSet.add( Integer.valueOf(pfdIDs[i]) );
if(DEBUG) {
System.err.println("AWT pfd["+i+"] "+pfdIDs[i]);
}
@@ -164,18 +165,18 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: PFD IDs: "+pfdIDs.length+", unique: "+pfdIDOSet.size());
}
winConfig.preselectGraphicsConfiguration(drawableFactory, pfdIDs);
- int gcIdx = pfdIDOSet.indexOf(new Integer(winConfig.getPixelFormatID()));
+ final int gcIdx = pfdIDOSet.indexOf(Integer.valueOf(winConfig.getPixelFormatID()));
if( 0 > gcIdx ) {
chosenGC = configs[gcIdx];
if(DEBUG) {
System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: Found matching AWT PFD ID "+winConfig.getPixelFormatID()+" -> "+winConfig);
}
}
- }
+ }
} else {
chosenGC = device.getDefaultConfiguration();
}
-
+
if ( null == chosenGC ) {
throw new GLException("Unable to determine GraphicsConfiguration: "+winConfig);
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/GLXUtil.java b/src/jogl/classes/jogamp/opengl/x11/glx/GLXUtil.java
index 7cc2d0f2e..195096110 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/GLXUtil.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/GLXUtil.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -33,66 +33,103 @@
package jogamp.opengl.x11.glx;
+import java.nio.IntBuffer;
+
import javax.media.opengl.GLException;
import jogamp.opengl.Debug;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
public class GLXUtil {
public static final boolean DEBUG = Debug.debug("GLXUtil");
-
- public static synchronized boolean isGLXAvailableOnServer(X11GraphicsDevice x11Device) {
+
+ public static synchronized boolean isGLXAvailableOnServer(final X11GraphicsDevice x11Device) {
if(null == x11Device) {
throw new IllegalArgumentException("null X11GraphicsDevice");
}
if(0 == x11Device.getHandle()) {
throw new IllegalArgumentException("null X11GraphicsDevice display handle");
- }
+ }
boolean glXAvailable = false;
+ x11Device.lock();
+ try {
+ glXAvailable = GLX.glXQueryExtension(x11Device.getHandle(), null, null);
+ } catch (final Throwable t) { /* n/a */
+ } finally {
+ x11Device.unlock();
+ }
+ return glXAvailable;
+ }
+
+ public static String getGLXClientString(final X11GraphicsDevice x11Device, final int name) {
+ x11Device.lock();
+ try {
+ return GLX.glXGetClientString(x11Device.getHandle(), name);
+ } finally {
+ x11Device.unlock();
+ }
+ }
+ public static String queryGLXServerString(final X11GraphicsDevice x11Device, final int screen_idx, final int name) {
+ x11Device.lock();
try {
- glXAvailable = GLX.glXQueryExtension(x11Device.getHandle(), null, 0, null, 0);
- } catch (Throwable t) { /* n/a */ }
- return glXAvailable;
+ return GLX.glXQueryServerString(x11Device.getHandle(), screen_idx, name);
+ } finally {
+ x11Device.unlock();
+ }
}
-
- public static VersionNumber getGLXServerVersionNumber(long display) {
- int[] major = new int[1];
- int[] minor = new int[1];
-
- if (!GLX.glXQueryVersion(display, major, 0, minor, 0)) {
- throw new GLException("glXQueryVersion failed");
+ public static String queryGLXExtensionsString(final X11GraphicsDevice x11Device, final int screen_idx) {
+ x11Device.lock();
+ try {
+ return GLX.glXQueryExtensionsString(x11Device.getHandle(), screen_idx);
+ } finally {
+ x11Device.unlock();
}
+ }
- // Work around bugs in ATI's Linux drivers where they report they
- // only implement GLX version 1.2 on the server side
- if (major[0] == 1 && minor[0] == 2) {
- String str = GLX.glXGetClientString(display, GLX.GLX_VERSION);
- try {
- // e.g. "1.3"
- major[0] = Integer.valueOf(str.substring(0, 1)).intValue();
- minor[0] = Integer.valueOf(str.substring(2, 3)).intValue();
- } catch (Exception e) {
- major[0] = 1;
- minor[0] = 2;
- }
- }
- return new VersionNumber(major[0], minor[0], 0);
+ public static VersionNumber getGLXServerVersionNumber(final X11GraphicsDevice x11Device) {
+ final IntBuffer major = Buffers.newDirectIntBuffer(1);
+ final IntBuffer minor = Buffers.newDirectIntBuffer(1);
+
+ x11Device.lock();
+ try {
+ if (!GLX.glXQueryVersion(x11Device.getHandle(), major, minor)) {
+ throw new GLException("glXQueryVersion failed");
+ }
+
+ // Work around bugs in ATI's Linux drivers where they report they
+ // only implement GLX version 1.2 on the server side
+ if (major.get(0) == 1 && minor.get(0) == 2) {
+ final String str = GLX.glXGetClientString(x11Device.getHandle(), GLX.GLX_VERSION);
+ try {
+ // e.g. "1.3"
+ major.put(0, Integer.parseInt(str.substring(0, 1)));
+ minor.put(0, Integer.parseInt(str.substring(2, 3)));
+ } catch (final Exception e) {
+ major.put(0, 1);
+ minor.put(0, 2);
+ }
+ }
+ } finally {
+ x11Device.unlock();
+ }
+ return new VersionNumber(major.get(0), minor.get(0), 0);
}
-
- public static boolean isMultisampleAvailable(String extensions) {
+
+ public static boolean isMultisampleAvailable(final String extensions) {
if (extensions != null) {
return (extensions.indexOf("GLX_ARB_multisample") >= 0);
}
return false;
}
- public static boolean isVendorNVIDIA(String vendor) {
+ public static boolean isVendorNVIDIA(final String vendor) {
return vendor != null && vendor.startsWith("NVIDIA") ;
}
- public static boolean isVendorATI(String vendor) {
+ public static boolean isVendorATI(final String vendor) {
return vendor != null && vendor.startsWith("ATI") ;
}
@@ -105,8 +142,8 @@ public class GLXUtil {
public static VersionNumber getClientVersionNumber() {
return clientVersionNumber;
}
-
- public static synchronized void initGLXClientDataSingleton(X11GraphicsDevice x11Device) {
+
+ public static synchronized void initGLXClientDataSingleton(final X11GraphicsDevice x11Device) {
if(null != clientVendorName) {
return; // already initialized
}
@@ -115,18 +152,18 @@ public class GLXUtil {
}
if(0 == x11Device.getHandle()) {
throw new IllegalArgumentException("null X11GraphicsDevice display handle");
- }
+ }
clientMultisampleAvailable = isMultisampleAvailable(GLX.glXGetClientString(x11Device.getHandle(), GLX.GLX_EXTENSIONS));
clientVendorName = GLX.glXGetClientString(x11Device.getHandle(), GLX.GLX_VENDOR);
-
- int[] major = new int[1];
- int[] minor = new int[1];
+
+ final int[] major = new int[1];
+ final int[] minor = new int[1];
final String str = GLX.glXGetClientString(x11Device.getHandle(), GLX.GLX_VERSION);
try {
// e.g. "1.3"
- major[0] = Integer.valueOf(str.substring(0, 1)).intValue();
- minor[0] = Integer.valueOf(str.substring(2, 3)).intValue();
- } catch (Exception e) {
+ major[0] = Integer.parseInt(str.substring(0, 1));
+ minor[0] = Integer.parseInt(str.substring(2, 3));
+ } catch (final Exception e) {
major[0] = 1;
minor[0] = 2;
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
index 03a0eefbf..7040621be 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
@@ -40,6 +40,8 @@
package jogamp.opengl.x11.glx;
+import java.nio.IntBuffer;
+
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.opengl.GLCapabilities;
@@ -49,60 +51,61 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import jogamp.nativewindow.WrappedSurface;
-import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLContextShareSet;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
public class X11ExternalGLXContext extends X11GLXContext {
- private GLContext lastContext;
- private X11ExternalGLXContext(Drawable drawable, long ctx) {
+ private X11ExternalGLXContext(final Drawable drawable, final long ctx) {
super(drawable, null);
this.contextHandle = ctx;
GLContextShareSet.contextCreated(this);
- setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT);
+ if( !setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION
+ throw new InternalError("setGLFunctionAvailability !strictMatch failed");
+ }
getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
}
- protected static X11ExternalGLXContext create(GLDrawableFactory factory, GLProfile glp) {
- long ctx = GLX.glXGetCurrentContext();
+ protected static X11ExternalGLXContext create(final GLDrawableFactory factory, final GLProfile glp) {
+ final long ctx = GLX.glXGetCurrentContext();
if (ctx == 0) {
throw new GLException("Error: current context null");
}
- long display = GLX.glXGetCurrentDisplay();
+ final long display = GLX.glXGetCurrentDisplay();
if (display == 0) {
throw new GLException("Error: current display null");
}
- long drawable = GLX.glXGetCurrentDrawable();
+ final long drawable = GLX.glXGetCurrentDrawable();
if (drawable == 0) {
throw new GLException("Error: attempted to make an external GLDrawable without a drawable/context current");
- }
- int[] val = new int[1];
-
+ }
+ final IntBuffer val = Buffers.newDirectIntBuffer(1);
+
int w, h;
- GLX.glXQueryDrawable(display, drawable, GLX.GLX_WIDTH, val, 0);
- w=val[0];
- GLX.glXQueryDrawable(display, drawable, GLX.GLX_HEIGHT, val, 0);
- h=val[0];
-
- GLX.glXQueryContext(display, ctx, GLX.GLX_SCREEN, val, 0);
- X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0], false);
-
- GLX.glXQueryContext(display, ctx, GLX.GLX_FBCONFIG_ID, val, 0);
+ GLX.glXQueryDrawable(display, drawable, GLX.GLX_WIDTH, val);
+ w=val.get(0);
+ GLX.glXQueryDrawable(display, drawable, GLX.GLX_HEIGHT, val);
+ h=val.get(0);
+
+ GLX.glXQueryContext(display, ctx, GLX.GLX_SCREEN, val);
+ final X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val.get(0), false);
+
+ GLX.glXQueryContext(display, ctx, GLX.GLX_FBCONFIG_ID, val);
X11GLXGraphicsConfiguration cfg = null;
// sometimes glXQueryContext on an external context gives us a framebuffer config ID
// of 0, which doesn't work in a subsequent call to glXChooseFBConfig; if this happens,
// create and use a default config (this has been observed when running on CentOS 5.5 inside
// of VMWare Server 2.0 with the Mesa 6.5.1 drivers)
- if( VisualIDHolder.VID_UNDEFINED == val[0] || !X11GLXGraphicsConfiguration.GLXFBConfigIDValid(display, x11Screen.getIndex(), val[0]) ) {
- GLCapabilities glcapsDefault = new GLCapabilities(GLProfile.getDefault());
+ if( VisualIDHolder.VID_UNDEFINED == val.get(0) || !X11GLXGraphicsConfiguration.GLXFBConfigIDValid(display, x11Screen.getIndex(), val.get(0)) ) {
+ final GLCapabilities glcapsDefault = new GLCapabilities(GLProfile.getDefault());
cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(glcapsDefault, glcapsDefault, null, x11Screen, VisualIDHolder.VID_UNDEFINED);
if(DEBUG) {
- System.err.println("X11ExternalGLXContext invalid FBCONFIG_ID "+val[0]+", using default cfg: " + cfg);
+ System.err.println("X11ExternalGLXContext invalid FBCONFIG_ID "+val.get(0)+", using default cfg: " + cfg);
}
} else {
- cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]);
+ cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val.get(0));
}
final WrappedSurface ns = new WrappedSurface(cfg, drawable, w, h, true);
@@ -110,30 +113,11 @@ public class X11ExternalGLXContext extends X11GLXContext {
}
@Override
- protected boolean createImpl(GLContextImpl shareWith) {
+ protected boolean createImpl(final long shareWithHandle) {
return true;
}
@Override
- public int makeCurrent() throws GLException {
- // Save last context if necessary to allow external GLContexts to
- // talk to other GLContexts created by this library
- GLContext cur = getCurrent();
- if (cur != null && cur != this) {
- lastContext = cur;
- setCurrent(null);
- }
- return super.makeCurrent();
- }
-
- @Override
- public void release() throws GLException {
- super.release();
- setCurrent(lastContext);
- lastContext = null;
- }
-
- @Override
protected void makeCurrentImpl() throws GLException {
}
@@ -147,26 +131,26 @@ public class X11ExternalGLXContext extends X11GLXContext {
// Need to provide the display connection to extension querying APIs
static class Drawable extends X11GLXDrawable {
- Drawable(GLDrawableFactory factory, NativeSurface comp) {
+ Drawable(final GLDrawableFactory factory, final NativeSurface comp) {
super(factory, comp, true);
}
@Override
- public GLContext createContext(GLContext shareWith) {
+ public GLContext createContext(final GLContext shareWith) {
throw new GLException("Should not call this");
}
@Override
- public int getWidth() {
+ public int getSurfaceWidth() {
throw new GLException("Should not call this");
}
@Override
- public int getHeight() {
+ public int getSurfaceHeight() {
throw new GLException("Should not call this");
}
- public void setSize(int width, int height) {
+ public void setSize(final int width, final int height) {
throw new GLException("Should not call this");
}
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java
index ac78c6f4a..d2f967a5c 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java
@@ -39,6 +39,8 @@
package jogamp.opengl.x11.glx;
+import java.nio.IntBuffer;
+
import javax.media.nativewindow.NativeSurface;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
@@ -47,61 +49,63 @@ import javax.media.opengl.GLProfile;
import jogamp.nativewindow.WrappedSurface;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
public class X11ExternalGLXDrawable extends X11GLXDrawable {
- private X11ExternalGLXDrawable(GLDrawableFactory factory, NativeSurface surface) {
+ private X11ExternalGLXDrawable(final GLDrawableFactory factory, final NativeSurface surface) {
super(factory, surface, true);
}
- protected static X11ExternalGLXDrawable create(GLDrawableFactory factory, GLProfile glp) {
- long context = GLX.glXGetCurrentContext();
+ protected static X11ExternalGLXDrawable create(final GLDrawableFactory factory, final GLProfile glp) {
+ final long context = GLX.glXGetCurrentContext();
if (context == 0) {
throw new GLException("Error: current context null");
}
- long display = GLX.glXGetCurrentDisplay();
+ final long display = GLX.glXGetCurrentDisplay();
if (display == 0) {
throw new GLException("Error: current display null");
}
- long drawable = GLX.glXGetCurrentDrawable();
+ final long drawable = GLX.glXGetCurrentDrawable();
if (drawable == 0) {
throw new GLException("Error: attempted to make an external GLDrawable without a drawable current");
}
- int[] val = new int[1];
- GLX.glXQueryContext(display, context, GLX.GLX_SCREEN, val, 0);
- X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0], false);
+ final IntBuffer val = Buffers.newDirectIntBuffer(1);
+
+ GLX.glXQueryContext(display, context, GLX.GLX_SCREEN, val);
+ final X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val.get(0), false);
- GLX.glXQueryContext(display, context, GLX.GLX_FBCONFIG_ID, val, 0);
- X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]);
+ GLX.glXQueryContext(display, context, GLX.GLX_FBCONFIG_ID, val);
+ final X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val.get(0));
int w, h;
- GLX.glXQueryDrawable(display, drawable, GLX.GLX_WIDTH, val, 0);
- w=val[0];
- GLX.glXQueryDrawable(display, drawable, GLX.GLX_HEIGHT, val, 0);
- h=val[0];
+ GLX.glXQueryDrawable(display, drawable, GLX.GLX_WIDTH, val);
+ w=val.get(0);
+ GLX.glXQueryDrawable(display, drawable, GLX.GLX_HEIGHT, val);
+ h=val.get(0);
- GLX.glXQueryContext(display, context, GLX.GLX_RENDER_TYPE, val, 0);
- if ((val[0] & GLX.GLX_RGBA_TYPE) == 0) {
+ GLX.glXQueryContext(display, context, GLX.GLX_RENDER_TYPE, val);
+ if ((val.get(0) & GLX.GLX_RGBA_TYPE) == 0) {
if (DEBUG) {
- System.err.println("X11ExternalGLXDrawable: WARNING: forcing GLX_RGBA_TYPE for newly created contexts (current 0x"+Integer.toHexString(val[0])+")");
+ System.err.println("X11ExternalGLXDrawable: WARNING: forcing GLX_RGBA_TYPE for newly created contexts (current 0x"+Integer.toHexString(val.get(0))+")");
}
}
return new X11ExternalGLXDrawable(factory, new WrappedSurface(cfg, drawable, w, h, true));
}
@Override
- public GLContext createContext(GLContext shareWith) {
+ public GLContext createContext(final GLContext shareWith) {
return new Context(this, shareWith);
}
- public void setSize(int newWidth, int newHeight) {
+ public void setSize(final int newWidth, final int newHeight) {
throw new GLException("Should not call this");
}
- class Context extends X11GLXContext {
- Context(X11GLXDrawable drawable, GLContext shareWith) {
+ static class Context extends X11GLXContext {
+ Context(final X11GLXDrawable drawable, final GLContext shareWith) {
super(drawable, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java
index e0b69ffd4..36e791641 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java
@@ -41,14 +41,14 @@ public class X11GLCapabilities extends GLCapabilities {
final private long fbcfg;
final private int fbcfgid;
- public X11GLCapabilities(XVisualInfo xVisualInfo, long fbcfg, int fbcfgid, GLProfile glp) {
+ public X11GLCapabilities(final XVisualInfo xVisualInfo, final long fbcfg, final int fbcfgid, final GLProfile glp) {
super(glp);
this.xVisualInfo = xVisualInfo;
this.fbcfg = fbcfg;
this.fbcfgid = fbcfgid;
}
- public X11GLCapabilities(XVisualInfo xVisualInfo, GLProfile glp) {
+ public X11GLCapabilities(final XVisualInfo xVisualInfo, final GLProfile glp) {
super(glp);
this.xVisualInfo = xVisualInfo;
this.fbcfg = 0;
@@ -64,7 +64,7 @@ public class X11GLCapabilities extends GLCapabilities {
public Object clone() {
try {
return super.clone();
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
throw new GLException(e);
}
}
@@ -78,7 +78,7 @@ public class X11GLCapabilities extends GLCapabilities {
final public boolean hasFBConfig() { return 0!=fbcfg && fbcfgid!=VisualIDHolder.VID_UNDEFINED; }
@Override
- final public int getVisualID(VIDType type) throws NativeWindowException {
+ final public int getVisualID(final VIDType type) throws NativeWindowException {
switch(type) {
case INTRINSIC:
case NATIVE:
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index e1e25be67..9631dbb5b 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -57,26 +57,32 @@ import jogamp.nativewindow.x11.X11Lib;
import jogamp.nativewindow.x11.X11Util;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.GLXExtensions;
import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.VersionNumber;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.opengl.GLExtensions;
-public abstract class X11GLXContext extends GLContextImpl {
+public class X11GLXContext extends GLContextImpl {
private static final Map<String, String> functionNameMap;
private static final Map<String, String> extensionNameMap;
private GLXExt _glXExt;
// Table that holds the addresses of the native C-language entry points for
// GLX extension functions.
private GLXExtProcAddressTable glXExtProcAddressTable;
- private int hasSwapIntervalSGI = 0;
+ /** 1 MESA, 2 SGI, 0 undefined, -1 none */
+ private int hasSwapInterval = 0;
private int hasSwapGroupNV = 0;
// This indicates whether the context we have created is indirect
// and therefore requires the toolkit to be locked around all GL
// calls rather than just all GLX calls
protected boolean isDirect;
+ protected volatile VersionNumber glXServerVersion;
+ protected volatile boolean isGLXVersionGreaterEqualOneThree;
static {
functionNameMap = new HashMap<String, String>();
@@ -88,19 +94,21 @@ public abstract class X11GLXContext extends GLContextImpl {
extensionNameMap.put(GLExtensions.ARB_pixel_format, X11GLXDrawableFactory.GLX_SGIX_pbuffer); // good enough
}
- X11GLXContext(GLDrawableImpl drawable,
- GLContext shareWith) {
+ X11GLXContext(final GLDrawableImpl drawable,
+ final GLContext shareWith) {
super(drawable, shareWith);
}
@Override
- protected void resetStates() {
+ protected void resetStates(final boolean isInit) {
// no inner state _glXExt=null;
glXExtProcAddressTable = null;
- hasSwapIntervalSGI = 0;
+ hasSwapInterval = 0;
hasSwapGroupNV = 0;
isDirect = false;
- super.resetStates();
+ glXServerVersion = null;
+ isGLXVersionGreaterEqualOneThree = false;
+ super.resetStates(isInit);
}
@Override
@@ -130,8 +138,20 @@ public abstract class X11GLXContext extends GLContextImpl {
@Override
protected Map<String, String> getExtensionNameMap() { return extensionNameMap; }
- protected final boolean isGLXVersionGreaterEqualOneThree() {
- return ((X11GLXDrawableFactory)drawable.getFactoryImpl()).isGLXVersionGreaterEqualOneThree(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice());
+ protected final boolean isGLXVersionGreaterEqualOneThree() { // fast-path: use cached boolean
+ if(null != glXServerVersion) {
+ return isGLXVersionGreaterEqualOneThree;
+ }
+ glXServerVersion = ((X11GLXDrawableFactory)drawable.getFactoryImpl()).getGLXVersionNumber(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice());
+ isGLXVersionGreaterEqualOneThree = null != glXServerVersion ? glXServerVersion.compareTo(X11GLXDrawableFactory.versionOneThree) >= 0 : false;
+ return isGLXVersionGreaterEqualOneThree;
+ }
+ protected final void forceGLXVersionOneOne() {
+ glXServerVersion = X11GLXDrawableFactory.versionOneOne;
+ isGLXVersionGreaterEqualOneThree = false;
+ if(DEBUG) {
+ System.err.println("X11GLXContext.forceGLXVersionNumber: "+glXServerVersion);
+ }
}
@Override
@@ -139,20 +159,22 @@ public abstract class X11GLXContext extends GLContextImpl {
return isGLXVersionGreaterEqualOneThree();
}
- private final boolean glXMakeContextCurrent(long dpy, long writeDrawable, long readDrawable, long ctx) {
+ private final boolean glXMakeContextCurrent(final long dpy, final long writeDrawable, final long readDrawable, final long ctx) {
boolean res = false;
try {
if ( isGLXVersionGreaterEqualOneThree() ) {
+ // System.err.println(getThreadName() +": X11GLXContext.makeCurrent: obj " + toHexString(hashCode()) + " / ctx "+toHexString(contextHandle)+": ctx "+toHexString(ctx)+", [write "+toHexString(writeDrawable)+", read "+toHexString(readDrawable)+"] - switch");
res = GLX.glXMakeContextCurrent(dpy, writeDrawable, readDrawable, ctx);
} else if ( writeDrawable == readDrawable ) {
+ // System.err.println(getThreadName() +": X11GLXContext.makeCurrent: obj " + toHexString(hashCode()) + " / ctx "+toHexString(contextHandle)+": ctx "+toHexString(ctx)+", [write "+toHexString(writeDrawable)+"] - switch");
res = GLX.glXMakeCurrent(dpy, writeDrawable, ctx);
} else {
// should not happen due to 'isGLReadDrawableAvailable()' query in GLContextImpl
throw new InternalError("Given readDrawable but no driver support");
}
- } catch (RuntimeException re) {
- if(DEBUG || TRACE_SWITCH) {
+ } catch (final RuntimeException re) {
+ if( DEBUG_TRACE_SWITCH ) {
System.err.println(getThreadName()+": Warning: X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+
"dpy "+toHexString(dpy)+
", write "+toHexString(writeDrawable)+
@@ -165,14 +187,12 @@ public abstract class X11GLXContext extends GLContextImpl {
}
@Override
- protected void destroyContextARBImpl(long ctx) {
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
- long display = config.getScreen().getDevice().getHandle();
+ protected void destroyContextARBImpl(final long ctx) {
+ final long display = drawable.getNativeSurface().getDisplayHandle();
glXMakeContextCurrent(display, 0, 0, 0);
GLX.glXDestroyContext(display, ctx);
}
-
private static final int ctx_arb_attribs_idx_major = 0;
private static final int ctx_arb_attribs_idx_minor = 2;
private static final int ctx_arb_attribs_idx_flags = 6;
@@ -187,22 +207,22 @@ public abstract class X11GLXContext extends GLContextImpl {
};
@Override
- protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) {
+ protected long createContextARBImpl(final long share, final boolean direct, final int ctp, final int major, final int minor) {
updateGLXProcAddressTable();
- GLXExt _glXExt = getGLXExt();
+ final GLXExt _glXExt = getGLXExt();
if(DEBUG) {
System.err.println(getThreadName()+": X11GLXContext.createContextARBImpl: "+getGLVersion(major, minor, ctp, "@creation") +
", handle "+toHexString(drawable.getHandle()) + ", share "+toHexString(share)+", direct "+direct+
", glXCreateContextAttribsARB: "+toHexString(glXExtProcAddressTable._addressof_glXCreateContextAttribsARB));
}
- boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ;
- boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ;
- boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ;
+ final boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ;
+ final boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ;
+ final boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ;
long ctx=0;
- IntBuffer attribs = Buffers.newDirectIntBuffer(ctx_arb_attribs_rom);
+ final IntBuffer attribs = Buffers.newDirectIntBuffer(ctx_arb_attribs_rom);
attribs.put(ctx_arb_attribs_idx_major + 1, major);
attribs.put(ctx_arb_attribs_idx_minor + 1, minor);
@@ -226,22 +246,23 @@ public abstract class X11GLXContext extends GLContextImpl {
attribs.put(ctx_arb_attribs_idx_flags + 1, flags);
}
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
- AbstractGraphicsDevice device = config.getScreen().getDevice();
- long display = device.getHandle();
+ final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
+ final long display = device.getHandle();
try {
// critical path, a remote display might not support this command,
// hence we need to catch the X11 Error within this block.
+ X11Util.setX11ErrorHandler(true, DEBUG ? false : true); // make sure X11 error handler is set
X11Lib.XSync(display, false);
ctx = _glXExt.glXCreateContextAttribsARB(display, config.getFBConfig(), share, direct, attribs);
- X11Lib.XSync(display, false);
- } catch (RuntimeException re) {
+ } catch (final RuntimeException re) {
if(DEBUG) {
- Throwable t = new Throwable(getThreadName()+": Info: X11GLXContext.createContextARBImpl glXCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re);
+ final Throwable t = new Throwable(getThreadName()+": Info: X11GLXContext.createContextARBImpl glXCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re);
t.printStackTrace();
}
}
+
if(0!=ctx) {
if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), ctx)) {
if(DEBUG) {
@@ -262,54 +283,42 @@ public abstract class X11GLXContext extends GLContextImpl {
}
@Override
- protected boolean createImpl(GLContextImpl shareWith) {
- // covers the whole context creation loop incl createContextARBImpl and destroyContextARBImpl
- X11Util.setX11ErrorHandler(true, DEBUG ? false : true);
- try {
- return createImplRaw(shareWith);
- } finally {
- X11Util.setX11ErrorHandler(false, false);
- }
- }
-
- private boolean createImplRaw(GLContextImpl shareWith) {
+ protected boolean createImpl(final long shareWithHandle) {
boolean direct = true; // try direct always
isDirect = false; // fall back
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl();
final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice device = config.getScreen().getDevice();
- final X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContextImpl(device);
- long display = device.getHandle();
-
- long share = 0;
- if (shareWith != null) {
- share = shareWith.getHandle();
- if (share == 0) {
- throw new GLException("GLContextShareSet returned an invalid OpenGL context");
- }
- direct = GLX.glXIsDirect(display, share);
+ final X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContext(device);
+ final long display = device.getHandle();
+
+ if ( 0 != shareWithHandle ) {
+ direct = GLX.glXIsDirect(display, shareWithHandle);
}
- GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
- GLProfile glp = glCaps.getGLProfile();
+ final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final GLProfile glp = glCaps.getGLProfile();
- if(config.getFBConfigID()<0) {
- // not able to use FBConfig
- if(glp.isGL3()) {
- throw new GLException(getThreadName()+": Unable to create OpenGL >= 3.1 context");
+ if( !config.hasFBConfig() ) {
+ // not able to use FBConfig -> GLX 1.1
+ forceGLXVersionOneOne();
+ if( glp.isGL3() ) {
+ throw new GLException(getThreadName()+": Unable to create OpenGL >= 3.1 context w/o FBConfig");
}
- contextHandle = GLX.glXCreateContext(display, config.getXVisualInfo(), share, direct);
- if (contextHandle == 0) {
+ contextHandle = GLX.glXCreateContext(display, config.getXVisualInfo(), shareWithHandle, direct);
+ if ( 0 == contextHandle ) {
throw new GLException(getThreadName()+": Unable to create context(0)");
}
- if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+ if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
throw new GLException(getThreadName()+": Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
}
- setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+ if( !setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, null == sharedContext /* withinGLVersionsMapping */) ) { // use GL_VERSION
+ throw new InternalError("setGLFunctionAvailability !strictMatch failed");
+ }
isDirect = GLX.glXIsDirect(display, contextHandle);
if (DEBUG) {
- System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+share+", direct "+isDirect+"/"+direct);
+ System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+toHexString(shareWithHandle)+", direct "+isDirect+"/"+direct);
}
return true;
}
@@ -317,76 +326,83 @@ public abstract class X11GLXContext extends GLContextImpl {
boolean createContextARBTried = false;
// utilize the shared context's GLXExt in case it was using the ARB method and it already exists
- if(null!=sharedContext && sharedContext.isCreatedWithARBMethod()) {
- contextHandle = createContextARB(share, direct);
+ if( null != sharedContext && sharedContext.isCreatedWithARBMethod() ) {
+ contextHandle = createContextARB(shareWithHandle, direct);
createContextARBTried = true;
- if (DEBUG && 0!=contextHandle) {
- System.err.println(getThreadName() + ": createContextImpl: OK (ARB, using sharedContext) share "+share);
+ if ( DEBUG && 0 != contextHandle ) {
+ System.err.println(getThreadName() + ": createContextImpl: OK (ARB, using sharedContext) share "+toHexString(shareWithHandle));
}
}
- long temp_ctx = 0;
- if(0==contextHandle) {
+ final long temp_ctx;
+ if( 0 == contextHandle ) {
// To use GLX_ARB_create_context, we have to make a temp context current,
// so we are able to use GetProcAddress
- temp_ctx = GLX.glXCreateNewContext(display, config.getFBConfig(), GLX.GLX_RGBA_TYPE, share, direct);
- if (temp_ctx == 0) {
+ temp_ctx = GLX.glXCreateNewContext(display, config.getFBConfig(), GLX.GLX_RGBA_TYPE, shareWithHandle, direct);
+ if ( 0 == temp_ctx ) {
throw new GLException(getThreadName()+": Unable to create temp OpenGL context(1)");
}
- if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx)) {
- throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable);
+ if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx) ) {
+ throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable);
}
- setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+ setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, null == sharedContext /* withinGLVersionsMapping */); // use GL_VERSION
glXMakeContextCurrent(display, 0, 0, 0); // release temp context
if( !createContextARBTried ) {
// is*Available calls are valid since setGLFunctionAvailability(..) was called
final boolean isProcCreateContextAttribsARBAvailable = isFunctionAvailable("glXCreateContextAttribsARB");
final boolean isExtARBCreateContextAvailable = isExtensionAvailable("GLX_ARB_create_context");
- if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable ) {
+ if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable && !GLProfile.disableOpenGLARBContext ) {
// initial ARB context creation
- contextHandle = createContextARB(share, direct);
+ contextHandle = createContextARB(shareWithHandle, direct);
createContextARBTried=true;
if (DEBUG) {
- if(0!=contextHandle) {
- System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+share);
+ if( 0 != contextHandle ) {
+ System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+toHexString(shareWithHandle));
} else {
- System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+share);
+ System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+toHexString(shareWithHandle));
}
}
- } else if (DEBUG) {
- System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+share+
- ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable);
+ } else if( DEBUG ) {
+ System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+toHexString(shareWithHandle)+
+ ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+
+ ", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable+
+ ", disableOpenGLARBContext "+GLProfile.disableOpenGLARBContext);
}
}
+ } else {
+ temp_ctx = 0;
}
- if(0!=contextHandle) {
- if(0!=temp_ctx) {
+ if( 0 != contextHandle ) {
+ if( 0 != temp_ctx ) {
glXMakeContextCurrent(display, 0, 0, 0);
GLX.glXDestroyContext(display, temp_ctx);
- if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+ if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
throw new GLException(getThreadName()+": Cannot make previous verified context current");
}
}
} else {
- if(glp.isGL3()) {
- glXMakeContextCurrent(display, 0, 0, 0);
- GLX.glXDestroyContext(display, temp_ctx);
- throw new GLException(getThreadName()+": X11GLXContext.createContextImpl ctx !ARB, context > GL2 requested - requested: "+glp+", current: "+getGLVersion()+", ");
+ if( glp.isGL3() && createContextARBTried ) {
+ // We shall not allow context creation >= GL3 w/ non ARB methods if ARB is used,
+ // otherwise context of similar profile but different creation method may not be share-able.
+ glXMakeContextCurrent(display, 0, 0, 0);
+ GLX.glXDestroyContext(display, temp_ctx);
+ throw new GLException(getThreadName()+": X11GLXContext.createContextImpl ctx !ARB but ARB is used, profile > GL2 requested (OpenGL >= 3.0.1). Requested: "+glp+", current: "+getGLVersion());
}
+
if(DEBUG) {
- System.err.println(getThreadName()+": X11GLXContext.createContextImpl failed, fall back to !ARB context "+getGLVersion());
+ System.err.println(getThreadName()+": X11GLXContext.createContextImpl ARB not used, fall back to !ARB context "+getGLVersion());
}
- // continue with temp context for GL <= 3.0
+ // continue with temp context
contextHandle = temp_ctx;
- if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
- glXMakeContextCurrent(display, 0, 0, 0);
- GLX.glXDestroyContext(display, temp_ctx);
- throw new GLException(getThreadName()+": Error making context(1) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
+ if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
+ glXMakeContextCurrent(display, 0, 0, 0);
+ GLX.glXDestroyContext(display, temp_ctx);
+ throw new GLException(getThreadName()+": Error making context(1) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
}
if (DEBUG) {
- System.err.println(getThreadName() + ": createContextImpl: OK (old-2) share "+share);
+ System.err.println(getThreadName() + ": createContextImpl: OK (old-2) share "+toHexString(shareWithHandle));
}
}
isDirect = GLX.glXIsDirect(display, contextHandle);
@@ -399,43 +415,38 @@ public abstract class X11GLXContext extends GLContextImpl {
@Override
protected void makeCurrentImpl() throws GLException {
- long dpy = drawable.getNativeSurface().getDisplayHandle();
+ final long dpy = drawable.getNativeSurface().getDisplayHandle();
if (GLX.glXGetCurrentContext() != contextHandle) {
- X11Util.setX11ErrorHandler(true, DEBUG ? false : true);
- try {
- if (!glXMakeContextCurrent(dpy, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
- throw new GLException(getThreadName()+": Error making context current: "+this);
- }
- } finally {
- X11Util.setX11ErrorHandler(false, false);
+ if (!glXMakeContextCurrent(dpy, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+ throw new GLException("Error making context " + toHexString(contextHandle) +
+ " current on Thread " + getThreadName() +
+ " with display " + toHexString(dpy) +
+ ", drawableWrite " + toHexString(drawable.getHandle()) +
+ ", drawableRead "+ toHexString(drawableRead.getHandle()) +
+ " - " + this);
}
}
}
@Override
protected void releaseImpl() throws GLException {
- long display = drawable.getNativeSurface().getDisplayHandle();
- X11Util.setX11ErrorHandler(true, DEBUG ? false : true);
- try {
- if (!glXMakeContextCurrent(display, 0, 0, 0)) {
- throw new GLException(getThreadName()+": Error freeing OpenGL context");
- }
- } finally {
- X11Util.setX11ErrorHandler(false, false);
+ final long display = drawable.getNativeSurface().getDisplayHandle();
+ if (!glXMakeContextCurrent(display, 0, 0, 0)) {
+ throw new GLException(getThreadName()+": Error freeing OpenGL context");
}
}
@Override
protected void destroyImpl() throws GLException {
- GLX.glXDestroyContext(drawable.getNativeSurface().getDisplayHandle(), contextHandle);
+ destroyContextARBImpl(contextHandle);
}
@Override
- protected void copyImpl(GLContext source, int mask) throws GLException {
- long dst = getHandle();
- long src = source.getHandle();
- long display = drawable.getNativeSurface().getDisplayHandle();
+ protected void copyImpl(final GLContext source, final int mask) throws GLException {
+ final long dst = getHandle();
+ final long src = source.getHandle();
+ final long display = drawable.getNativeSurface().getDisplayHandle();
if (0 == display) {
throw new GLException(getThreadName()+": Connection to X display not yet set up");
}
@@ -474,160 +485,156 @@ public abstract class X11GLXContext extends GLContextImpl {
@Override
protected final StringBuilder getPlatformExtensionsStringImpl() {
- StringBuilder sb = new StringBuilder();
- if (DEBUG) {
- System.err.println("GLX Version client version "+ GLXUtil.getClientVersionNumber()+
- ", server: "+
- ((X11GLXDrawableFactory)drawable.getFactoryImpl()).getGLXVersionNumber(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice()));
- }
final NativeSurface ns = drawable.getNativeSurface();
- if(((X11GLXDrawableFactory)drawable.getFactoryImpl()).isGLXVersionGreaterEqualOneOne(ns.getGraphicsConfiguration().getScreen().getDevice())) {
- {
- final String ret = GLX.glXGetClientString(ns.getDisplayHandle(), GLX.GLX_EXTENSIONS);
- if (DEBUG) {
- System.err.println("GLX extensions (glXGetClientString): " + ret);
- }
- sb.append(ret).append(" ");
+ final X11GraphicsDevice x11Device = (X11GraphicsDevice) ns.getGraphicsConfiguration().getScreen().getDevice();
+ final StringBuilder sb = new StringBuilder();
+ x11Device.lock();
+ try{
+ if (DEBUG) {
+ System.err.println("GLX Version client version "+ GLXUtil.getClientVersionNumber()+
+ ", server: "+ GLXUtil.getGLXServerVersionNumber(x11Device));
}
- {
- final String ret = GLX.glXQueryExtensionsString(ns.getDisplayHandle(), ns.getScreenIndex());
- if (DEBUG) {
- System.err.println("GLX extensions (glXQueryExtensionsString): " + ret);
+ if(((X11GLXDrawableFactory)drawable.getFactoryImpl()).isGLXVersionGreaterEqualOneOne(x11Device)) {
+ {
+ final String ret = GLX.glXGetClientString(x11Device.getHandle(), GLX.GLX_EXTENSIONS);
+ if (DEBUG) {
+ System.err.println("GLX extensions (glXGetClientString): " + ret);
+ }
+ sb.append(ret).append(" ");
}
- sb.append(ret).append(" ");
- }
- {
- final String ret = GLX.glXQueryServerString(ns.getDisplayHandle(), ns.getScreenIndex(), GLX.GLX_EXTENSIONS);
- if (DEBUG) {
- System.err.println("GLX extensions (glXQueryServerString): " + ret);
+ {
+ final String ret = GLX.glXQueryExtensionsString(x11Device.getHandle(), ns.getScreenIndex());
+ if (DEBUG) {
+ System.err.println("GLX extensions (glXQueryExtensionsString): " + ret);
+ }
+ sb.append(ret).append(" ");
+ }
+ {
+ final String ret = GLX.glXQueryServerString(x11Device.getHandle(), ns.getScreenIndex(), GLX.GLX_EXTENSIONS);
+ if (DEBUG) {
+ System.err.println("GLX extensions (glXQueryServerString): " + ret);
+ }
+ sb.append(ret).append(" ");
}
- sb.append(ret).append(" ");
}
+ } finally {
+ x11Device.unlock();
}
return sb;
}
@Override
- public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals(GLExtensions.ARB_pbuffer) ||
- glExtensionName.equals(GLExtensions.ARB_pixel_format)) {
- return getGLDrawable().getFactory().canCreateGLPbuffer(
- drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice() );
- }
- return super.isExtensionAvailable(glExtensionName);
- }
-
- @Override
- protected boolean setSwapIntervalImpl(int interval) {
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
- GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
- if(!glCaps.isOnscreen()) { return false; }
+ protected boolean setSwapIntervalImpl(final int interval) {
+ if( !drawable.getChosenGLCapabilities().isOnscreen() ) { return false; }
- GLXExt glXExt = getGLXExt();
- if(0==hasSwapIntervalSGI) {
+ final GLXExt glXExt = getGLXExt();
+ if(0==hasSwapInterval) {
try {
- hasSwapIntervalSGI = glXExt.isExtensionAvailable("GLX_SGI_swap_control")?1:-1;
- } catch (Throwable t) { hasSwapIntervalSGI=1; }
+ /** Same impl. ..
+ if( glXExt.isExtensionAvailable(GLXExtensions.GLX_MESA_swap_control) ) {
+ if(DEBUG) { System.err.println("X11GLXContext.setSwapInterval using: "+GLXExtensions.GLX_MESA_swap_control); }
+ hasSwapInterval = 1;
+ } else */
+ if ( glXExt.isExtensionAvailable(GLXExtensions.GLX_SGI_swap_control) ) {
+ if(DEBUG) { System.err.println("X11GLXContext.setSwapInterval using: "+GLXExtensions.GLX_SGI_swap_control); }
+ hasSwapInterval = 2;
+ } else {
+ hasSwapInterval = -1;
+ }
+ } catch (final Throwable t) { hasSwapInterval=-1; }
}
- if (hasSwapIntervalSGI>0) {
+ /* try {
+ switch( hasSwapInterval ) {
+ case 1:
+ return 0 == glXExt.glXSwapIntervalMESA(interval);
+ case 2:
+ return 0 == glXExt.glXSwapIntervalSGI(interval);
+ }
+ } catch (Throwable t) { hasSwapInterval = -1; } */
+ if (2 == hasSwapInterval) {
try {
return 0 == glXExt.glXSwapIntervalSGI(interval);
- } catch (Throwable t) { hasSwapIntervalSGI=-1; }
+ } catch (final Throwable t) { hasSwapInterval=-1; }
}
return false;
}
- private final int initSwapGroupImpl(GLXExt glXExt) {
+ private final int initSwapGroupImpl(final GLXExt glXExt) {
if(0==hasSwapGroupNV) {
try {
- hasSwapGroupNV = glXExt.isExtensionAvailable("GLX_NV_swap_group")?1:-1;
- } catch (Throwable t) { hasSwapGroupNV=1; }
+ hasSwapGroupNV = glXExt.isExtensionAvailable(GLXExtensions.GLX_NV_swap_group)?1:-1;
+ } catch (final Throwable t) { hasSwapGroupNV=1; }
if(DEBUG) {
- System.err.println("initSwapGroupImpl: hasSwapGroupNV: "+hasSwapGroupNV);
+ System.err.println("initSwapGroupImpl: "+GLXExtensions.GLX_NV_swap_group+": "+hasSwapGroupNV);
}
}
return hasSwapGroupNV;
}
@Override
- protected final boolean queryMaxSwapGroupsImpl(int[] maxGroups, int maxGroups_offset,
- int[] maxBarriers, int maxBarriers_offset) {
+ protected final boolean queryMaxSwapGroupsImpl(final int[] maxGroups, final int maxGroups_offset,
+ final int[] maxBarriers, final int maxBarriers_offset) {
boolean res = false;
- GLXExt glXExt = getGLXExt();
+ final GLXExt glXExt = getGLXExt();
if (initSwapGroupImpl(glXExt)>0) {
final NativeSurface ns = drawable.getNativeSurface();
try {
+ final IntBuffer maxGroupsNIO = Buffers.newDirectIntBuffer(maxGroups.length - maxGroups_offset);
+ final IntBuffer maxBarriersNIO = Buffers.newDirectIntBuffer(maxBarriers.length - maxBarriers_offset);
+
if( glXExt.glXQueryMaxSwapGroupsNV(ns.getDisplayHandle(), ns.getScreenIndex(),
- maxGroups, maxGroups_offset,
- maxBarriers, maxBarriers_offset) ) {
+ maxGroupsNIO, maxBarriersNIO) ) {
+ maxGroupsNIO.get(maxGroups, maxGroups_offset, maxGroupsNIO.remaining());
+ maxBarriersNIO.get(maxGroups, maxGroups_offset, maxBarriersNIO.remaining());
res = true;
}
- } catch (Throwable t) { hasSwapGroupNV=-1; }
+ } catch (final Throwable t) { hasSwapGroupNV=-1; }
}
return res;
}
@Override
- protected final boolean joinSwapGroupImpl(int group) {
+ protected final boolean joinSwapGroupImpl(final int group) {
boolean res = false;
- GLXExt glXExt = getGLXExt();
+ final GLXExt glXExt = getGLXExt();
if (initSwapGroupImpl(glXExt)>0) {
try {
if( glXExt.glXJoinSwapGroupNV(drawable.getNativeSurface().getDisplayHandle(), drawable.getHandle(), group) ) {
currentSwapGroup = group;
res = true;
}
- } catch (Throwable t) { hasSwapGroupNV=-1; }
+ } catch (final Throwable t) { hasSwapGroupNV=-1; }
}
return res;
}
@Override
- protected final boolean bindSwapBarrierImpl(int group, int barrier) {
+ protected final boolean bindSwapBarrierImpl(final int group, final int barrier) {
boolean res = false;
- GLXExt glXExt = getGLXExt();
+ final GLXExt glXExt = getGLXExt();
if (initSwapGroupImpl(glXExt)>0) {
try {
if( glXExt.glXBindSwapBarrierNV(drawable.getNativeSurface().getDisplayHandle(), group, barrier) ) {
res = true;
}
- } catch (Throwable t) { hasSwapGroupNV=-1; }
+ } catch (final Throwable t) { hasSwapGroupNV=-1; }
}
return res;
}
@Override
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
- return getGLXExt().glXAllocateMemoryNV(arg0, arg1, arg2, arg3);
- }
-
- @Override
- public int getOffscreenContextPixelDataType() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextReadBuffer() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public void bindPbufferToTexture() {
- throw new GLException("Should not call this");
+ public final ByteBuffer glAllocateMemoryNV(final int size, final float readFrequency, final float writeFrequency, final float priority) {
+ return getGLXExt().glXAllocateMemoryNV(size, readFrequency, writeFrequency, priority);
}
@Override
- public void releasePbufferFromTexture() {
- throw new GLException("Should not call this");
+ public final void glFreeMemoryNV(final ByteBuffer pointer) {
+ getGLXExt().glXFreeMemoryNV(pointer);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
super.append(sb);
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java
index 8c642777d..c29bc3bc3 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java
@@ -47,7 +47,7 @@ import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
public abstract class X11GLXDrawable extends GLDrawableImpl {
- protected X11GLXDrawable(GLDrawableFactory factory, NativeSurface comp, boolean realized) {
+ protected X11GLXDrawable(final GLDrawableFactory factory, final NativeSurface comp, final boolean realized) {
super(factory, comp, realized);
}
@@ -59,17 +59,17 @@ public abstract class X11GLXDrawable extends GLDrawableImpl {
@Override
protected void setRealizedImpl() {
if(realized) {
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
+ final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
config.updateGraphicsConfiguration();
if (DEBUG) {
- System.err.println("X11GLXDrawable.setRealized(true): "+config);
+ System.err.println(getThreadName()+": X11GLXDrawable.setRealized(true): "+config);
}
}
}
@Override
- protected final void swapBuffersImpl(boolean doubleBuffered) {
+ protected final void swapBuffersImpl(final boolean doubleBuffered) {
if(doubleBuffered) {
GLX.glXSwapBuffers(getNativeSurface().getDisplayHandle(), getHandle());
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index ca5cd424b..60e4438d0 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -39,6 +39,8 @@ package jogamp.opengl.x11.glx;
import java.nio.Buffer;
import java.nio.ShortBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -47,7 +49,6 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
import javax.media.nativewindow.VisualIDHolder;
@@ -71,9 +72,11 @@ import jogamp.opengl.GLDynamicLookupHelper;
import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.SharedResourceRunner;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+import com.jogamp.opengl.GLRendererQuirks;
public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
@@ -84,26 +87,32 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
public static final VersionNumber versionOneFour = new VersionNumber(1, 4, 0);
static final String GLX_SGIX_pbuffer = "GLX_SGIX_pbuffer";
-
+
private static DesktopGLDynamicLookupHelper x11GLXDynamicLookupHelper = null;
public X11GLXDrawableFactory() {
super();
synchronized(X11GLXDrawableFactory.class) {
- if(null==x11GLXDynamicLookupHelper) {
- DesktopGLDynamicLookupHelper tmp = null;
- try {
- tmp = new DesktopGLDynamicLookupHelper(new X11GLXDynamicLibraryBundleInfo());
- } catch (GLException gle) {
- if(DEBUG) {
- gle.printStackTrace();
+ if( null == x11GLXDynamicLookupHelper ) {
+ x11GLXDynamicLookupHelper = AccessController.doPrivileged(new PrivilegedAction<DesktopGLDynamicLookupHelper>() {
+ @Override
+ public DesktopGLDynamicLookupHelper run() {
+ DesktopGLDynamicLookupHelper tmp;
+ try {
+ tmp = new DesktopGLDynamicLookupHelper(new X11GLXDynamicLibraryBundleInfo());
+ if(null!=tmp && tmp.isLibComplete()) {
+ GLX.getGLXProcAddressTable().reset(tmp);
+ }
+ } catch (final Exception ex) {
+ tmp = null;
+ if(DEBUG) {
+ ex.printStackTrace();
+ }
+ }
+ return tmp;
}
- }
- if(null!=tmp && tmp.isLibComplete()) {
- x11GLXDynamicLookupHelper = tmp;
- GLX.getGLXProcAddressTable().reset(x11GLXDynamicLookupHelper);
- }
+ } );
}
}
@@ -127,9 +136,12 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
protected final boolean isComplete() {
return null != x11GLXDynamicLookupHelper;
}
-
+
@Override
- protected final void destroy() {
+ protected final void shutdownImpl() {
+ if( DEBUG ) {
+ System.err.println("X11GLXDrawableFactory.shutdown");
+ }
if(null != sharedResourceRunner) {
sharedResourceRunner.stop();
sharedResourceRunner = null;
@@ -148,7 +160,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) {
+ public final GLDynamicLookupHelper getGLDynamicLookupHelper(final int profile) {
return x11GLXDynamicLookupHelper;
}
@@ -157,21 +169,21 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
private HashMap<String /* connection */, SharedResourceRunner.Resource> sharedMap;
static class SharedResource implements SharedResourceRunner.Resource {
+ private final String glXServerVendorName;
+ private final boolean isGLXServerVendorATI;
+ private final boolean isGLXServerVendorNVIDIA;
+ private final VersionNumber glXServerVersion;
+ private final boolean glXServerVersionOneOneCapable;
+ private final boolean glXServerVersionOneThreeCapable;
+ private final boolean glXMultisampleAvailable;
X11GraphicsDevice device;
X11GraphicsScreen screen;
GLDrawableImpl drawable;
GLContextImpl context;
- String glXServerVendorName;
- boolean isGLXServerVendorATI;
- boolean isGLXServerVendorNVIDIA;
- VersionNumber glXServerVersion;
- boolean glXServerVersionOneOneCapable;
- boolean glXServerVersionOneThreeCapable;
- boolean glXMultisampleAvailable;
-
- SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn,
- GLDrawableImpl draw, GLContextImpl ctx,
- VersionNumber glXServerVer, String glXServerVendor, boolean glXServerMultisampleAvail) {
+
+ SharedResource(final X11GraphicsDevice dev, final X11GraphicsScreen scrn,
+ final GLDrawableImpl draw, final GLContextImpl ctx,
+ final VersionNumber glXServerVer, final String glXServerVendor, final boolean glXServerMultisampleAvail) {
device = dev;
screen = scrn;
drawable = draw;
@@ -185,6 +197,10 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
glXMultisampleAvailable = glXServerMultisampleAvail;
}
@Override
+ public final boolean isValid() {
+ return null != context;
+ }
+ @Override
final public AbstractGraphicsDevice getDevice() { return device; }
@Override
final public AbstractGraphicsScreen getScreen() { return screen; }
@@ -192,6 +208,10 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
final public GLDrawableImpl getDrawable() { return drawable; }
@Override
final public GLContextImpl getContext() { return context; }
+ @Override
+ public GLRendererQuirks getRendererQuirks() {
+ return null != context ? context.getRendererQuirks() : null;
+ }
final String getGLXVendorName() { return glXServerVendorName; }
final boolean isGLXVendorATI() { return isGLXServerVendorATI; }
@@ -205,65 +225,70 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
class SharedResourceImplementation implements SharedResourceRunner.Implementation {
@Override
public void clear() {
- synchronized(sharedMap) {
- sharedMap.clear();
- }
+ sharedMap.clear();
}
@Override
- public SharedResourceRunner.Resource mapPut(String connection, SharedResourceRunner.Resource resource) {
- synchronized(sharedMap) {
- return sharedMap.put(connection, resource);
- }
+ public SharedResourceRunner.Resource mapPut(final String connection, final SharedResourceRunner.Resource resource) {
+ return sharedMap.put(connection, resource);
}
@Override
- public SharedResourceRunner.Resource mapGet(String connection) {
- synchronized(sharedMap) {
- return sharedMap.get(connection);
- }
+ public SharedResourceRunner.Resource mapGet(final String connection) {
+ return sharedMap.get(connection);
}
@Override
public Collection<SharedResourceRunner.Resource> mapValues() {
- synchronized(sharedMap) {
- return sharedMap.values();
+ return sharedMap.values();
+ }
+
+ @Override
+ public boolean isDeviceSupported(final String connection) {
+ final boolean res;
+ final X11GraphicsDevice x11Device = new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
+ x11Device.lock();
+ try {
+ res = GLXUtil.isGLXAvailableOnServer(x11Device);
+ } finally {
+ x11Device.unlock();
+ x11Device.close();
+ }
+ if(DEBUG) {
+ System.err.println("GLX "+(res ? "is" : "not")+" available on device/server: "+x11Device);
}
+ return res;
}
@Override
- public SharedResourceRunner.Resource createSharedResource(String connection) {
- final X11GraphicsDevice sharedDevice =
- new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT,
- true); // own non-shared display connection, w/ locking
- // new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT,
- // NativeWindowFactory.getNullToolkitLock(), true); // own non-shared display connection, w/o locking
+ public SharedResourceRunner.Resource createSharedResource(final String connection) {
+ final X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
sharedDevice.lock();
try {
final X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, sharedDevice.getDefaultScreen());
-
- if(!GLXUtil.isGLXAvailableOnServer(sharedDevice)) {
- throw new GLException("GLX not available on device/server: "+sharedDevice);
- }
+
GLXUtil.initGLXClientDataSingleton(sharedDevice);
final String glXServerVendorName = GLX.glXQueryServerString(sharedDevice.getHandle(), 0, GLX.GLX_VENDOR);
- final VersionNumber glXServerVersion = GLXUtil.getGLXServerVersionNumber(sharedDevice.getHandle());
final boolean glXServerMultisampleAvailable = GLXUtil.isMultisampleAvailable(GLX.glXQueryServerString(sharedDevice.getHandle(), 0, GLX.GLX_EXTENSIONS));
- if(X11Util.ATI_HAS_XCLOSEDISPLAY_BUG && GLXUtil.isVendorATI(glXServerVendorName)) {
- X11Util.setMarkAllDisplaysUnclosable(true);
- X11Util.markDisplayUncloseable(sharedDevice.getHandle());
- }
-
+
final GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
if (null == glp) {
throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice);
}
-
- final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64));
+
+ final GLCapabilitiesImmutable caps = new GLCapabilities(glp);
+ final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, caps, caps, null, 64, 64));
sharedDrawable.setRealized(true);
-
+ final X11GLCapabilities chosenCaps = (X11GLCapabilities) sharedDrawable.getChosenGLCapabilities();
+ final boolean glxForcedOneOne = !chosenCaps.hasFBConfig();
+ final VersionNumber glXServerVersion;
+ if( glxForcedOneOne ) {
+ glXServerVersion = versionOneOne;
+ } else {
+ glXServerVersion = GLXUtil.getGLXServerVersionNumber(sharedDevice);
+ }
final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null);
if (null == sharedContext) {
throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
}
-
+
boolean madeCurrent = false;
sharedContext.makeCurrent();
try {
@@ -271,12 +296,15 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
} finally {
sharedContext.release();
}
+ if( sharedContext.hasRendererQuirk( GLRendererQuirks.DontCloseX11Display ) ) {
+ X11Util.markAllDisplaysUnclosable();
+ }
if (DEBUG) {
System.err.println("SharedDevice: " + sharedDevice);
System.err.println("SharedScreen: " + sharedScreen);
System.err.println("SharedContext: " + sharedContext + ", madeCurrent " + madeCurrent);
System.err.println("GLX Server Vendor: " + glXServerVendorName);
- System.err.println("GLX Server Version: " + glXServerVersion);
+ System.err.println("GLX Server Version: " + glXServerVersion + ", forced "+glxForcedOneOne);
System.err.println("GLX Server Multisample: " + glXServerMultisampleAvailable);
System.err.println("GLX Client Vendor: " + GLXUtil.getClientVendorName());
System.err.println("GLX Client Version: " + GLXUtil.getClientVersionNumber());
@@ -285,7 +313,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext,
glXServerVersion, glXServerVendorName,
glXServerMultisampleAvailable && GLXUtil.isClientMultisampleAvailable());
- } catch (Throwable t) {
+ } catch (final Throwable t) {
throw new GLException("X11GLXDrawableFactory - Could not initialize shared resources for "+connection, t);
} finally {
sharedDevice.unlock();
@@ -293,8 +321,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public void releaseSharedResource(SharedResourceRunner.Resource shared) {
- SharedResource sr = (SharedResource) shared;
+ public void releaseSharedResource(final SharedResourceRunner.Resource shared) {
+ final SharedResource sr = (SharedResource) shared;
if (DEBUG) {
System.err.println("Shutdown Shared:");
System.err.println("Device : " + sr.device);
@@ -305,8 +333,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
if (null != sr.context) {
- // may cause JVM SIGSEGV:
- sr.context.destroy(); // will also pull the dummy MutuableSurface
+ // may cause JVM SIGSEGV, or freeze (ATI fglrx 3-6-beta2 32on64 shared ctx):
+ sr.context.destroy(); // will also pull the dummy MutableSurface
sr.context = null;
}
@@ -334,7 +362,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) {
+ public final boolean getIsDeviceCompatible(final AbstractGraphicsDevice device) {
if(null != x11GLXDynamicLookupHelper && device instanceof X11GraphicsDevice) {
return true;
}
@@ -347,58 +375,25 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final boolean createSharedResource(AbstractGraphicsDevice device) {
- try {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return null != sr.getContext();
- }
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("Catched Exception while X11GLX Shared Resource initialization");
- gle.printStackTrace();
- }
- }
- return false;
- }
-
- @Override
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getContext();
- }
- return null;
- }
-
- @Override
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getDevice();
- }
- return null;
+ protected final SharedResource getOrCreateSharedResourceImpl(final AbstractGraphicsDevice device) {
+ return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
}
- protected final long getOrCreateSharedDpy(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
+ protected final long getOrCreateSharedDpy(final AbstractGraphicsDevice device) {
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
if(null!=sr) {
return sr.getDevice().getHandle();
}
return 0;
}
- SharedResource getOrCreateSharedResource(AbstractGraphicsDevice device) {
- return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
- }
-
@Override
- protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
+ protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(final AbstractGraphicsDevice device) {
return X11GLXGraphicsConfigurationFactory.getAvailableCapabilities(this, device);
}
@Override
- protected final GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) {
+ protected final GLDrawableImpl createOnscreenDrawableImpl(final NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
@@ -406,19 +401,19 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) {
+ protected final GLDrawableImpl createOffscreenDrawableImpl(final NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
- AbstractGraphicsConfiguration config = target.getGraphicsConfiguration();
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final AbstractGraphicsConfiguration config = target.getGraphicsConfiguration();
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
if(!caps.isPBuffer()) {
return new X11PixmapGLXDrawable(this, target);
}
// PBuffer GLDrawable Creation
GLDrawableImpl pbufferDrawable;
- AbstractGraphicsDevice device = config.getScreen().getDevice();
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
/**
* Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277,
@@ -426,7 +421,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
* The dummy context shall also use the same Display,
* since switching Display in this regard is another ATI bug.
*/
- SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
+ final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
if( null!=sr && sr.isGLXVendorATI() && null == GLContext.getCurrent() ) {
sr.getContext().makeCurrent();
try {
@@ -440,9 +435,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return pbufferDrawable;
}
- public final boolean isGLXMultisampleAvailable(AbstractGraphicsDevice device) {
+ public final boolean isGLXMultisampleAvailable(final AbstractGraphicsDevice device) {
if(null != device) {
- SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
+ final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
if(null!=sr) {
return sr.isGLXMultisampleAvailable();
}
@@ -450,41 +445,41 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return false;
}
- public final VersionNumber getGLXVersionNumber(AbstractGraphicsDevice device) {
+ public final VersionNumber getGLXVersionNumber(final AbstractGraphicsDevice device) {
if(null != device) {
- SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
+ final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
if(null!=sr) {
return sr.getGLXVersion();
}
if( device instanceof X11GraphicsDevice ) {
- return GLXUtil.getGLXServerVersionNumber(device.getHandle());
+ return GLXUtil.getGLXServerVersionNumber((X11GraphicsDevice)device);
}
}
return null;
}
- public final boolean isGLXVersionGreaterEqualOneOne(AbstractGraphicsDevice device) {
+ public final boolean isGLXVersionGreaterEqualOneOne(final AbstractGraphicsDevice device) {
if(null != device) {
- SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
+ final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
if(null!=sr) {
return sr.isGLXVersionGreaterEqualOneOne();
}
if( device instanceof X11GraphicsDevice ) {
- final VersionNumber glXServerVersion = GLXUtil.getGLXServerVersionNumber(device.getHandle());
+ final VersionNumber glXServerVersion = GLXUtil.getGLXServerVersionNumber((X11GraphicsDevice)device);
return glXServerVersion.compareTo(versionOneOne) >= 0;
}
}
return false;
}
- public final boolean isGLXVersionGreaterEqualOneThree(AbstractGraphicsDevice device) {
+ public final boolean isGLXVersionGreaterEqualOneThree(final AbstractGraphicsDevice device) {
if(null != device) {
- SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
+ final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
if(null!=sr) {
return sr.isGLXVersionGreaterEqualOneThree();
}
if( device instanceof X11GraphicsDevice ) {
- final VersionNumber glXServerVersion = GLXUtil.getGLXServerVersionNumber(device.getHandle());
+ final VersionNumber glXServerVersion = GLXUtil.getGLXServerVersionNumber((X11GraphicsDevice)device);
return glXServerVersion.compareTo(versionOneThree) >= 0;
}
}
@@ -492,9 +487,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
+ public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device, final GLProfile glp) {
if(null == device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(defaultDevice);
+ final SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(defaultDevice);
if(null!=sr) {
device = sr.getDevice();
}
@@ -503,35 +498,34 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
- GLCapabilitiesImmutable capsChosen,
- GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) {
+ protected final ProxySurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ final GLCapabilitiesImmutable capsChosen,
+ final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstreamHook) {
final X11GraphicsDevice device;
- if(createNewDevice) {
- // Null X11 locking, due to private non-shared Display handle
- device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), NativeWindowFactory.getNullToolkitLock(), true);
+ if( createNewDevice || !(deviceReq instanceof X11GraphicsDevice) ) {
+ device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), true /* owner */);
} else {
- device = (X11GraphicsDevice)deviceReq;
+ device = (X11GraphicsDevice) deviceReq;
}
final X11GraphicsScreen screen = new X11GraphicsScreen(device, device.getDefaultScreen());
final X11GLXGraphicsConfiguration config = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED);
if(null == config) {
- throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
}
return new WrappedSurface(config, 0, upstreamHook, createNewDevice);
}
@Override
- public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
- GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
- final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
- return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new X11DummyUpstreamSurfaceHook(width, height));
- }
-
+ public final ProxySurface createDummySurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) {
+ chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps);
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new X11DummyUpstreamSurfaceHook(width, height));
+ }
+
@Override
- protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
- final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), NativeWindowFactory.getNullToolkitLock(), true);
+ protected final ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) {
+ final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), true /* owner */);
final X11GraphicsScreen screen = new X11GraphicsScreen(device, screenIdx);
final int xvisualID = X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle);
if(VisualIDHolder.VID_UNDEFINED == xvisualID) {
@@ -553,8 +547,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- public final boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) {
- return canCreateGLPbuffer(device);
+ public final boolean canCreateExternalGLDrawable(final AbstractGraphicsDevice device) {
+ return canCreateGLPbuffer(device, null /* GLProfile not used for query on X11 */);
}
@Override
@@ -562,17 +556,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return X11ExternalGLXDrawable.create(this, null);
}
- @Override
- public final boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- @Override
- public final GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("Unimplemented on this platform");
- }
-
//----------------------------------------------------------------------
// Gamma-related functionality
//
@@ -580,71 +563,87 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
private boolean gotGammaRampLength;
private int gammaRampLength;
@Override
- protected final synchronized int getGammaRampLength() {
+ protected final synchronized int getGammaRampLength(final NativeSurface surface) {
if (gotGammaRampLength) {
return gammaRampLength;
}
-
- long display = getOrCreateSharedDpy(defaultDevice);
+ final long display = surface.getDisplayHandle();
if(0 == display) {
return 0;
}
+ final int screenIdx = surface.getScreenIndex();
- int[] size = new int[1];
- boolean res = X11Lib.XF86VidModeGetGammaRampSize(display,
- X11Lib.DefaultScreen(display),
- size, 0);
+ final int[] size = new int[1];
+ final boolean res = X11Lib.XF86VidModeGetGammaRampSize(display, screenIdx, size, 0);
if (!res) {
return 0;
}
gotGammaRampLength = true;
gammaRampLength = size[0];
+ System.err.println("XXX: Gamma ramp size: "+gammaRampLength);
return gammaRampLength;
}
@Override
- protected final boolean setGammaRamp(float[] ramp) {
- long display = getOrCreateSharedDpy(defaultDevice);
+ protected final boolean setGammaRamp(final NativeSurface surface, final float[] ramp) {
+ final long display = surface.getDisplayHandle();
if(0 == display) {
return false;
}
+ final int screenIdx = surface.getScreenIndex();
- int len = ramp.length;
- short[] rampData = new short[len];
+ final int len = ramp.length;
+ final short[] rampData = new short[len];
for (int i = 0; i < len; i++) {
rampData[i] = (short) (ramp[i] * 65535);
}
- boolean res = X11Lib.XF86VidModeSetGammaRamp(display,
- X11Lib.DefaultScreen(display),
+ final boolean res = X11Lib.XF86VidModeSetGammaRamp(display, screenIdx,
rampData.length,
rampData, 0,
rampData, 0,
rampData, 0);
+ if( DEBUG ) {
+ dumpRamp("SET__", rampData.length, rampData, rampData, rampData);
+ }
return res;
}
+ private static void dumpRamp(final String prefix, final int size, final ShortBuffer r, final ShortBuffer g, final ShortBuffer b) {
+ for(int i=0; i<size; i++) {
+ if( 0 == i % 4 ) {
+ System.err.printf("%n%4d/%4d %s: ", i, size, prefix);
+ }
+ System.err.printf(" [%04X %04X %04X], ", r.get(i), g.get(i), b.get(i));
+ }
+ System.err.println();
+ }
+ private static void dumpRamp(final String prefix, final int size, final short[] r, final short[] g, final short[] b) {
+ for(int i=0; i<size; i++) {
+ if( 0 == i % 4 ) {
+ System.err.printf("%n%4d/%4d %s: ", i, size, prefix);
+ }
+ System.err.printf(" [%04X %04X %04X], ", r[i], g[i], b[i]);
+ }
+ System.err.println();
+ }
+
@Override
- protected final Buffer getGammaRamp() {
- long display = getOrCreateSharedDpy(defaultDevice);
+ protected final Buffer getGammaRamp(final NativeSurface surface) {
+ final long display = surface.getDisplayHandle();
if(0 == display) {
return null;
}
+ final int screenIdx = surface.getScreenIndex();
+
+ final int size = getGammaRampLength(surface);
- int size = getGammaRampLength();
- ShortBuffer rampData = ShortBuffer.wrap(new short[3 * size]);
- rampData.position(0);
- rampData.limit(size);
- ShortBuffer redRampData = rampData.slice();
- rampData.position(size);
- rampData.limit(2 * size);
- ShortBuffer greenRampData = rampData.slice();
- rampData.position(2 * size);
- rampData.limit(3 * size);
- ShortBuffer blueRampData = rampData.slice();
-
- boolean res = X11Lib.XF86VidModeGetGammaRamp(display,
- X11Lib.DefaultScreen(display),
+ final ShortBuffer rampData = Buffers.newDirectShortBuffer(3 * size);
+ final ShortBuffer redRampData = Buffers.slice(rampData, 0 * size, size);
+ final ShortBuffer greenRampData = Buffers.slice(rampData, 1 * size, size);
+ final ShortBuffer blueRampData = Buffers.slice(rampData, 2 * size, size);
+
+ final boolean res = X11Lib.XF86VidModeGetGammaRamp(display, screenIdx,
size,
redRampData,
greenRampData,
@@ -652,40 +651,62 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
if (!res) {
return null;
}
+ if( DEBUG ) {
+ dumpRamp("GET__", size, redRampData, greenRampData, blueRampData);
+ }
return rampData;
}
@Override
- protected final void resetGammaRamp(Buffer originalGammaRamp) {
+ protected final void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) {
if (originalGammaRamp == null) {
return; // getGammaRamp failed originally
}
- long display = getOrCreateSharedDpy(defaultDevice);
+ final long display = surface.getDisplayHandle();
if(0 == display) {
return;
}
+ final int screenIdx = surface.getScreenIndex();
- ShortBuffer rampData = (ShortBuffer) originalGammaRamp;
- int capacity = rampData.capacity();
+ resetGammaRamp(display, screenIdx, originalGammaRamp);
+ }
+
+ @Override
+ protected final void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) {
+ if (originalGammaRamp == null) {
+ return; // getGammaRamp failed originally
+ }
+ final long display = X11Util.openDisplay(deviceScreenID.deviceConnection);
+ if( 0 == display ) {
+ return;
+ }
+ try {
+ resetGammaRamp(display, deviceScreenID.screenIdx, originalGammaRamp);
+ } finally {
+ X11Util.closeDisplay(display);
+ }
+ }
+
+ private static final void resetGammaRamp(final long display, final int screenIdx, final Buffer originalGammaRamp) {
+ final ShortBuffer rampData = (ShortBuffer) originalGammaRamp;
+ final int capacity = rampData.capacity();
if ((capacity % 3) != 0) {
throw new IllegalArgumentException("Must not be the original gamma ramp");
}
- int size = capacity / 3;
- rampData.position(0);
- rampData.limit(size);
- ShortBuffer redRampData = rampData.slice();
- rampData.position(size);
- rampData.limit(2 * size);
- ShortBuffer greenRampData = rampData.slice();
- rampData.position(2 * size);
- rampData.limit(3 * size);
- ShortBuffer blueRampData = rampData.slice();
-
- X11Lib.XF86VidModeSetGammaRamp(display,
- X11Lib.DefaultScreen(display),
- size,
- redRampData,
- greenRampData,
- blueRampData);
+ final int size = capacity / 3;
+
+ final ShortBuffer redRampData = Buffers.slice(rampData, 0 * size, size);
+ final ShortBuffer greenRampData = Buffers.slice(rampData, 1 * size, size);
+ final ShortBuffer blueRampData = Buffers.slice(rampData, 2 * size, size);
+ if( DEBUG ) {
+ dumpRamp("RESET", size, redRampData, greenRampData, blueRampData);
+ }
+
+ X11Lib.XF86VidModeSetGammaRamp(display, screenIdx,
+ size,
+ redRampData,
+ greenRampData,
+ blueRampData);
}
+
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java
index 108c157a8..0e91a6a65 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,28 +20,28 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.opengl.x11.glx;
import jogamp.opengl.*;
import java.util.*;
-public class X11GLXDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
+public final class X11GLXDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo {
protected X11GLXDynamicLibraryBundleInfo() {
super();
}
@Override
- public List<List<String>> getToolLibNames() {
+ public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsGL = new ArrayList<String>();
-
- // Be aware that on DRI systems, eg ATI fglrx, etc,
+
+ // Be aware that on DRI systems, eg ATI fglrx, etc,
// you have to set LIBGL_DRIVERS_PATH env variable.
// Eg on Ubuntu 64bit systems this is:
// export LIBGL_DRIVERS_PATH=/usr/lib/fglrx/dri:/usr/lib32/fglrx/dri
@@ -55,30 +55,21 @@ public class X11GLXDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundl
// last but not least .. the generic one
libsGL.add("GL");
-
- libsList.add(libsGL);
+
+ libsList.add(libsGL);
return libsList;
- }
-
- /**
- * This respects old DRI requirements:<br>
- * <pre>
- * http://dri.sourceforge.net/doc/DRIuserguide.html
- * </pre>
- */
- @Override
- public boolean shallLinkGlobal() { return true; }
+ }
@Override
public final List<String> getToolGetProcAddressFuncNameList() {
- List<String> res = new ArrayList<String>();
+ final List<String> res = new ArrayList<String>();
res.add("glXGetProcAddressARB");
res.add("glXGetProcAddress");
return res;
}
@Override
- public final long toolGetProcAddress(long toolGetProcAddressHandle, String funcName) {
+ public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) {
return GLX.glXGetProcAddress(toolGetProcAddressHandle, funcName);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
index 96c3c4123..5f6a6b344 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -33,6 +33,10 @@
package jogamp.opengl.x11.glx;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.VisualIDHolder;
@@ -51,6 +55,7 @@ import jogamp.nativewindow.x11.XRenderPictFormat;
import jogamp.nativewindow.x11.XVisualInfo;
import jogamp.opengl.GLGraphicsConfigurationUtil;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.nativewindow.x11.X11GraphicsConfiguration;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
@@ -58,14 +63,15 @@ import com.jogamp.nativewindow.x11.X11GraphicsScreen;
public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implements Cloneable {
public static final int MAX_ATTRIBS = 128;
- private GLCapabilitiesChooser chooser;
+ private final GLCapabilitiesChooser chooser;
- X11GLXGraphicsConfiguration(X11GraphicsScreen screen,
- X11GLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
+ X11GLXGraphicsConfiguration(final X11GraphicsScreen screen,
+ final X11GLCapabilities capsChosen, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser) {
super(screen, capsChosen, capsRequested, capsChosen.getXVisualInfo());
this.chooser=chooser;
}
+ @Override
public Object clone() {
return super.clone();
}
@@ -76,12 +82,15 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
public final int getFBConfigID() {
return ((X11GLCapabilities)capabilitiesChosen).getFBConfigID();
}
+ public final boolean hasFBConfig() {
+ return ((X11GLCapabilities)capabilitiesChosen).hasFBConfig();
+ }
void updateGraphicsConfiguration() {
final CapabilitiesImmutable aChosenCaps = getChosenCapabilities();
if( !(aChosenCaps instanceof X11GLCapabilities) || VisualIDHolder.VID_UNDEFINED == aChosenCaps.getVisualID(VIDType.X11_XVISUAL) ) {
- // This case is actually quite impossible, since on X11 the visualID and hence GraphicsConfiguration
- // must be determined _before_ window creation!
+ // This case is actually quite impossible, since on X11 the visualID and hence GraphicsConfiguration
+ // must be determined _before_ window creation!
final X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration)
GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), aChosenCaps).chooseGraphicsConfiguration(
aChosenCaps, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED);
@@ -100,7 +109,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
}
- static X11GLXGraphicsConfiguration create(GLProfile glp, X11GraphicsScreen x11Screen, int fbcfgID) {
+ static X11GLXGraphicsConfiguration create(GLProfile glp, final X11GraphicsScreen x11Screen, final int fbcfgID) {
final X11GraphicsDevice device = (X11GraphicsDevice) x11Screen.getDevice();
final long display = device.getHandle();
if(0==display) {
@@ -115,29 +124,29 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
glp = GLProfile.getDefault(x11Screen.getDevice());
}
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- final X11GLCapabilities caps = GLXFBConfig2GLCapabilities(device, glp, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, factory.isGLXMultisampleAvailable(device));
+ final X11GLCapabilities caps = GLXFBConfig2GLCapabilities(device, glp, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, factory.isGLXMultisampleAvailable(device));
if(null==caps) {
throw new GLException("GLCapabilities null of "+toHexString(fbcfg));
}
return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser());
}
- static int[] GLCapabilities2AttribList(GLCapabilitiesImmutable caps,
- boolean forFBAttr, boolean isMultisampleAvailable,
- long display, int screen)
+ static IntBuffer GLCapabilities2AttribList(final GLCapabilitiesImmutable caps,
+ final boolean forFBAttr, final boolean isMultisampleAvailable,
+ final long display, final int screen)
{
- int colorDepth = (caps.getRedBits() +
+ final int colorDepth = (caps.getRedBits() +
caps.getGreenBits() +
caps.getBlueBits());
if (colorDepth < 15) {
throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported");
}
- int[] res = new int[MAX_ATTRIBS];
+ final IntBuffer res = Buffers.newDirectIntBuffer(MAX_ATTRIBS);
int idx = 0;
if (forFBAttr) {
- res[idx++] = GLX.GLX_DRAWABLE_TYPE;
-
+ res.put(idx++, GLX.GLX_DRAWABLE_TYPE);
+
final int surfaceType;
if( caps.isOnscreen() ) {
surfaceType = GLX.GLX_WINDOW_BIT;
@@ -150,103 +159,92 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
} else {
throw new GLException("no surface type set in caps: "+caps);
}
- res[idx++] = surfaceType;
-
- res[idx++] = GLX.GLX_RENDER_TYPE;
- res[idx++] = GLX.GLX_RGBA_BIT;
+ res.put(idx++, surfaceType);
+
+ res.put(idx++, GLX.GLX_RENDER_TYPE);
+ res.put(idx++, GLX.GLX_RGBA_BIT);
} else {
- res[idx++] = GLX.GLX_RGBA;
+ res.put(idx++, GLX.GLX_RGBA);
}
// FIXME: Still a bug is Mesa: PBUFFER && GLX_STEREO==GL_FALSE ?
if (forFBAttr) {
- res[idx++] = GLX.GLX_DOUBLEBUFFER;
- res[idx++] = caps.getDoubleBuffered()?GL.GL_TRUE:GL.GL_FALSE;
- res[idx++] = GLX.GLX_STEREO;
- res[idx++] = caps.getStereo()?GL.GL_TRUE:GL.GL_FALSE;
- res[idx++] = GLX.GLX_TRANSPARENT_TYPE;
- res[idx++] = GLX.GLX_NONE;
+ res.put(idx++, GLX.GLX_DOUBLEBUFFER);
+ res.put(idx++, caps.getDoubleBuffered()?GL.GL_TRUE:GL.GL_FALSE);
+ res.put(idx++, GLX.GLX_STEREO);
+ res.put(idx++, caps.getStereo()?GL.GL_TRUE:GL.GL_FALSE);
+ res.put(idx++, GLX.GLX_TRANSPARENT_TYPE);
+ res.put(idx++, GLX.GLX_NONE);
/**
- res[idx++] = caps.isBackgroundOpaque()?GLX.GLX_NONE:GLX.GLX_TRANSPARENT_RGB;
+ res.put(idx++, caps.isBackgroundOpaque()?GLX.GLX_NONE:GLX.GLX_TRANSPARENT_RGB;
if(!caps.isBackgroundOpaque()) {
- res[idx++] = GLX.GLX_TRANSPARENT_RED_VALUE;
- res[idx++] = caps.getTransparentRedValue()>=0?caps.getTransparentRedValue():(int)GLX.GLX_DONT_CARE;
- res[idx++] = GLX.GLX_TRANSPARENT_GREEN_VALUE;
- res[idx++] = caps.getTransparentGreenValue()>=0?caps.getTransparentGreenValue():(int)GLX.GLX_DONT_CARE;
- res[idx++] = GLX.GLX_TRANSPARENT_BLUE_VALUE;
- res[idx++] = caps.getTransparentBlueValue()>=0?caps.getTransparentBlueValue():(int)GLX.GLX_DONT_CARE;
- res[idx++] = GLX.GLX_TRANSPARENT_ALPHA_VALUE;
- res[idx++] = caps.getTransparentAlphaValue()>=0?caps.getTransparentAlphaValue():(int)GLX.GLX_DONT_CARE;
+ res.put(idx++, GLX.GLX_TRANSPARENT_RED_VALUE);
+ res.put(idx++, caps.getTransparentRedValue()>=0?caps.getTransparentRedValue():(int)GLX.GLX_DONT_CARE);
+ res.put(idx++, GLX.GLX_TRANSPARENT_GREEN_VALUE);
+ res.put(idx++, caps.getTransparentGreenValue()>=0?caps.getTransparentGreenValue():(int)GLX.GLX_DONT_CARE);
+ res.put(idx++, GLX.GLX_TRANSPARENT_BLUE_VALUE);
+ res.put(idx++, caps.getTransparentBlueValue()>=0?caps.getTransparentBlueValue():(int)GLX.GLX_DONT_CARE);
+ res.put(idx++, GLX.GLX_TRANSPARENT_ALPHA_VALUE);
+ res.put(idx++, caps.getTransparentAlphaValue()>=0?caps.getTransparentAlphaValue():(int)GLX.GLX_DONT_CARE);
} */
} else {
if (caps.getDoubleBuffered()) {
- res[idx++] = GLX.GLX_DOUBLEBUFFER;
+ res.put(idx++, GLX.GLX_DOUBLEBUFFER);
}
if (caps.getStereo()) {
- res[idx++] = GLX.GLX_STEREO;
+ res.put(idx++, GLX.GLX_STEREO);
}
}
- res[idx++] = GLX.GLX_RED_SIZE;
- res[idx++] = caps.getRedBits();
- res[idx++] = GLX.GLX_GREEN_SIZE;
- res[idx++] = caps.getGreenBits();
- res[idx++] = GLX.GLX_BLUE_SIZE;
- res[idx++] = caps.getBlueBits();
+ res.put(idx++, GLX.GLX_RED_SIZE);
+ res.put(idx++, caps.getRedBits());
+ res.put(idx++, GLX.GLX_GREEN_SIZE);
+ res.put(idx++, caps.getGreenBits());
+ res.put(idx++, GLX.GLX_BLUE_SIZE);
+ res.put(idx++, caps.getBlueBits());
if(caps.getAlphaBits()>0) {
- res[idx++] = GLX.GLX_ALPHA_SIZE;
- res[idx++] = caps.getAlphaBits();
+ res.put(idx++, GLX.GLX_ALPHA_SIZE);
+ res.put(idx++, caps.getAlphaBits());
}
if (caps.getStencilBits() > 0) {
- res[idx++] = GLX.GLX_STENCIL_SIZE;
- res[idx++] = caps.getStencilBits();
+ res.put(idx++, GLX.GLX_STENCIL_SIZE);
+ res.put(idx++, caps.getStencilBits());
}
- res[idx++] = GLX.GLX_DEPTH_SIZE;
- res[idx++] = caps.getDepthBits();
+ res.put(idx++, GLX.GLX_DEPTH_SIZE);
+ res.put(idx++, caps.getDepthBits());
if (caps.getAccumRedBits() > 0 ||
caps.getAccumGreenBits() > 0 ||
caps.getAccumBlueBits() > 0 ||
caps.getAccumAlphaBits() > 0) {
- res[idx++] = GLX.GLX_ACCUM_RED_SIZE;
- res[idx++] = caps.getAccumRedBits();
- res[idx++] = GLX.GLX_ACCUM_GREEN_SIZE;
- res[idx++] = caps.getAccumGreenBits();
- res[idx++] = GLX.GLX_ACCUM_BLUE_SIZE;
- res[idx++] = caps.getAccumBlueBits();
- res[idx++] = GLX.GLX_ACCUM_ALPHA_SIZE;
- res[idx++] = caps.getAccumAlphaBits();
+ res.put(idx++, GLX.GLX_ACCUM_RED_SIZE);
+ res.put(idx++, caps.getAccumRedBits());
+ res.put(idx++, GLX.GLX_ACCUM_GREEN_SIZE);
+ res.put(idx++, caps.getAccumGreenBits());
+ res.put(idx++, GLX.GLX_ACCUM_BLUE_SIZE);
+ res.put(idx++, caps.getAccumBlueBits());
+ res.put(idx++, GLX.GLX_ACCUM_ALPHA_SIZE);
+ res.put(idx++, caps.getAccumAlphaBits());
}
if (isMultisampleAvailable && caps.getSampleBuffers()) {
- res[idx++] = GLX.GLX_SAMPLE_BUFFERS;
- res[idx++] = GL.GL_TRUE;
- res[idx++] = GLX.GLX_SAMPLES;
- res[idx++] = caps.getNumSamples();
+ res.put(idx++, GLX.GLX_SAMPLE_BUFFERS);
+ res.put(idx++, GL.GL_TRUE);
+ res.put(idx++, GLX.GLX_SAMPLES);
+ res.put(idx++, caps.getNumSamples());
}
- if (caps.isPBuffer()) {
- if (caps.getPbufferFloatingPointBuffers()) {
- String glXExtensions = GLX.glXQueryExtensionsString(display, screen);
- if (glXExtensions == null ||
- glXExtensions.indexOf("GLX_NV_float_buffer") < 0) {
- throw new GLException("Floating-point pbuffers on X11 currently require NVidia hardware: "+glXExtensions);
- }
- res[idx++] = GLXExt.GLX_FLOAT_COMPONENTS_NV;
- res[idx++] = GL.GL_TRUE;
- }
- }
- res[idx++] = 0;
+ res.put(idx++, 0);
return res;
}
// FBConfig
-
- static boolean GLXFBConfigIDValid(long display, int screen, int fbcfgid) {
- long fbcfg = X11GLXGraphicsConfiguration.glXFBConfigID2FBConfig(display, screen, fbcfgid);
+
+ static boolean GLXFBConfigIDValid(final long display, final int screen, final int fbcfgid) {
+ final long fbcfg = X11GLXGraphicsConfiguration.glXFBConfigID2FBConfig(display, screen, fbcfgid);
return (0 != fbcfg) ? X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfg ) : false ;
}
- static boolean GLXFBConfigValid(long display, long fbcfg) {
- int[] tmp = new int[1];
- if(GLX.GLX_BAD_ATTRIBUTE == GLX.glXGetFBConfigAttrib(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp, 0)) {
+ static boolean GLXFBConfigValid(final long display, final long fbcfg) {
+ final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
+ if(GLX.GLX_BAD_ATTRIBUTE == GLX.glXGetFBConfigAttrib(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp)) {
return false;
}
return true;
@@ -255,8 +253,14 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
static int FBCfgDrawableTypeBits(final X11GraphicsDevice device, final long fbcfg) {
int val = 0;
- int[] tmp = new int[1];
- int fbtype = glXGetFBConfig(device.getHandle(), fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0);
+ final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
+ if( !glXGetFBConfig(device.getHandle(), fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp) ) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.FBCfgDrawableTypeBits: FBConfig invalid: fbcfg: "+toHexString(fbcfg));
+ }
+ return 0;
+ }
+ final int fbtype = tmp.get(0);
if ( 0 != ( fbtype & GLX.GLX_WINDOW_BIT ) ) {
val |= GLGraphicsConfigurationUtil.WINDOW_BIT |
@@ -271,22 +275,65 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
return val;
}
- static XRenderDirectFormat XVisual2XRenderMask(long dpy, long visual) {
- XRenderPictFormat renderPictFmt = X11Lib.XRenderFindVisualFormat(dpy, visual);
+ static XRenderDirectFormat XVisual2XRenderMask(final long dpy, final long visual) {
+ final XRenderPictFormat renderPictFmt = X11Lib.XRenderFindVisualFormat(dpy, visual);
if(null == renderPictFmt) {
return null;
}
return renderPictFmt.getDirect();
}
+ static XRenderDirectFormat XVisual2XRenderMask(final long dpy, final long visual, final XRenderPictFormat dest) {
+ if( !X11Lib.XRenderFindVisualFormat(dpy, visual, dest) ) {
+ return null;
+ } else {
+ return dest.getDirect();
+ }
+ }
- static X11GLCapabilities GLXFBConfig2GLCapabilities(X11GraphicsDevice device, GLProfile glp, long fbcfg,
- int winattrmask, boolean isMultisampleAvailable) {
+ static X11GLCapabilities GLXFBConfig2GLCapabilities(final X11GraphicsDevice device, final GLProfile glp, final long fbcfg,
+ final int winattrmask, final boolean isMultisampleAvailable) {
+ final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
+ final XRenderPictFormat xRenderPictFormat= XRenderPictFormat.create();
+ return GLXFBConfig2GLCapabilities(device, glp, fbcfg, winattrmask, isMultisampleAvailable, tmp, xRenderPictFormat);
+ }
+
+ static List<GLCapabilitiesImmutable> GLXFBConfig2GLCapabilities(final X11GraphicsDevice device, final GLProfile glp, final PointerBuffer fbcfgsL,
+ final int winattrmask, final boolean isMultisampleAvailable, final boolean onlyFirstValid) {
+ final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
+ final XRenderPictFormat xRenderPictFormat= XRenderPictFormat.create();
+ final List<GLCapabilitiesImmutable> result = new ArrayList<GLCapabilitiesImmutable>();
+ for (int i = 0; i < fbcfgsL.limit(); i++) {
+ final long fbcfg = fbcfgsL.get(i);
+ final GLCapabilitiesImmutable c = GLXFBConfig2GLCapabilities(device, glp, fbcfg, winattrmask, isMultisampleAvailable, tmp, xRenderPictFormat);
+ if( null != c ) {
+ result.add(c);
+ if( onlyFirstValid ) {
+ break;
+ }
+ }
+ }
+ return result;
+ }
+ static X11GLCapabilities GLXFBConfig2GLCapabilities(final X11GraphicsDevice device, final GLProfile glp, final long fbcfg,
+ final int winattrmask, final boolean isMultisampleAvailable,
+ final IntBuffer tmp, final XRenderPictFormat xRenderPictFormat) {
+ final long display = device.getHandle();
final int allDrawableTypeBits = FBCfgDrawableTypeBits(device, fbcfg);
int drawableTypeBits = winattrmask & allDrawableTypeBits;
-
- final long display = device.getHandle();
- int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg);
- XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg);
+ if( 0 == allDrawableTypeBits || 0 == drawableTypeBits ) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: zero drawablebits: allDrawableTypeBits: "+toHexString(allDrawableTypeBits)+", drawableTypeBits "+toHexString(drawableTypeBits));
+ }
+ return null;
+ }
+ final int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg);
+ if( VisualIDHolder.VID_UNDEFINED == fbcfgid ) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: FBConfig invalid (0): fbcfg: "+toHexString(fbcfg));
+ }
+ return null;
+ }
+ final XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg);
if(null == visualInfo) {
if(DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: Null XVisualInfo for FBConfigID 0x" + Integer.toHexString(fbcfgid));
@@ -294,58 +341,90 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
// onscreen must have an XVisualInfo
drawableTypeBits &= ~(GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.FBO_BIT);
}
-
if( 0 == drawableTypeBits ) {
- return null;
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: zero drawablebits: winattrmask: "+toHexString(winattrmask)+", offscreen "+(null == visualInfo));
+ }
+ return null;
}
- int[] tmp = new int[1];
- if(GLX.GLX_BAD_ATTRIBUTE == GLX.glXGetFBConfigAttrib(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp, 0)) {
+ if(GLX.GLX_BAD_ATTRIBUTE == GLX.glXGetFBConfigAttrib(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp)) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: FBConfig invalid (1): fbcfg: "+toHexString(fbcfg));
+ }
return null;
}
- if( 0 == ( GLX.GLX_RGBA_BIT & tmp[0] ) ) {
- return null; // no RGBA -> color index not supported
+ if( 0 == ( GLX.GLX_RGBA_BIT & tmp.get(0) ) ) {
+ // no RGBA -> color index not supported
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: FBConfig not RGBA (2): fbcfg: "+toHexString(fbcfg));
+ }
+ return null;
}
- final X11GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp);
+ final X11GLCapabilities caps = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp);
+
+ final XRenderDirectFormat xrmask = ( null != visualInfo ) ?
+ XVisual2XRenderMask( display, visualInfo.getVisual(), xRenderPictFormat) :
+ null ;
+
+ final int _attributes[] = {
+ GLX.GLX_SAMPLE_BUFFERS,
+ GLX.GLX_SAMPLES,
+ GLX.GLX_DOUBLEBUFFER,
+ GLX.GLX_STEREO,
+ GLX.GLX_CONFIG_CAVEAT,
+ GLX.GLX_RED_SIZE,
+ GLX.GLX_GREEN_SIZE,
+ GLX.GLX_BLUE_SIZE,
+ GLX.GLX_ALPHA_SIZE,
+ GLX.GLX_ACCUM_RED_SIZE,
+ GLX.GLX_ACCUM_GREEN_SIZE,
+ GLX.GLX_ACCUM_BLUE_SIZE,
+ GLX.GLX_ACCUM_ALPHA_SIZE,
+ GLX.GLX_DEPTH_SIZE,
+ GLX.GLX_STENCIL_SIZE
+ };
+ final int offset = isMultisampleAvailable ? 0 : 2;
+ final IntBuffer attributes = Buffers.newDirectIntBuffer(_attributes);
+ attributes.position(offset);
+ final IntBuffer values = Buffers.newDirectIntBuffer(attributes.remaining());
+ final int err = GLX.glXGetFBConfigAttributes(display, fbcfg, attributes, values);
+ if (0 != err) {
+ throw new GLException("glXGetFBConfig("+toHexString(attributes.get(offset+values.get(0)))+") failed: error code " + glXGetFBConfigErrorCode(err));
+ }
+ int j=0;
if (isMultisampleAvailable) {
- res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0);
- res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0));
+ caps.setSampleBuffers(values.get(j++) != 0);
+ caps.setNumSamples (values.get(j++));
}
- final XRenderDirectFormat xrmask = ( null != visualInfo ) ?
- XVisual2XRenderMask( display, visualInfo.getVisual() ) :
- null ;
final int alphaMask = ( null != xrmask ) ? xrmask.getAlphaMask() : 0;
- res.setBackgroundOpaque( 0 >= alphaMask );
- if( !res.isBackgroundOpaque() ) {
- res.setTransparentRedValue(xrmask.getRedMask());
- res.setTransparentGreenValue(xrmask.getGreenMask());
- res.setTransparentBlueValue(xrmask.getBlueMask());
- res.setTransparentAlphaValue(alphaMask);
+ caps.setBackgroundOpaque( 0 >= alphaMask );
+ if( !caps.isBackgroundOpaque() ) {
+ caps.setTransparentRedValue(xrmask.getRedMask());
+ caps.setTransparentGreenValue(xrmask.getGreenMask());
+ caps.setTransparentBlueValue(xrmask.getBlueMask());
+ caps.setTransparentAlphaValue(alphaMask);
}
- // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
- res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0);
- res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0);
- res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp, 0) != GLX.GLX_SLOW_CONFIG);
- res.setRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_RED_SIZE, tmp, 0));
- res.setGreenBits (glXGetFBConfig(display, fbcfg, GLX.GLX_GREEN_SIZE, tmp, 0));
- res.setBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_BLUE_SIZE, tmp, 0));
- res.setAlphaBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ALPHA_SIZE, tmp, 0));
- res.setAccumRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_RED_SIZE, tmp, 0));
- res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0));
- res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0));
- res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0));
- res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp, 0));
- res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp, 0));
-
- try {
- res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE);
- } catch (Exception e) {}
-
- return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
+ // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
+ caps.setDoubleBuffered(values.get(j++) != 0);
+ caps.setStereo (values.get(j++) != 0);
+ caps.setHardwareAccelerated(values.get(j++) != GLX.GLX_SLOW_CONFIG);
+ caps.setRedBits (values.get(j++));
+ caps.setGreenBits (values.get(j++));
+ caps.setBlueBits (values.get(j++));
+ caps.setAlphaBits (values.get(j++));
+ caps.setAccumRedBits (values.get(j++));
+ caps.setAccumGreenBits(values.get(j++));
+ caps.setAccumBlueBits (values.get(j++));
+ caps.setAccumAlphaBits(values.get(j++));
+ caps.setDepthBits (values.get(j++));
+ caps.setStencilBits (values.get(j++));
+
+ return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, caps);
}
- private static String glXGetFBConfigErrorCode(int err) {
+ private static String glXGetFBConfigErrorCode(final int err) {
switch (err) {
case GLX.GLX_NO_EXTENSION: return "GLX_NO_EXTENSION";
case GLX.GLX_BAD_ATTRIBUTE: return "GLX_BAD_ATTRIBUTE";
@@ -353,26 +432,33 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
}
- static int glXGetFBConfig(long display, long cfg, int attrib, int[] tmp, int tmp_offset) {
+ static boolean glXGetFBConfig(final long display, final long cfg, final int attrib, final IntBuffer tmp) {
if (display == 0) {
throw new GLException("No display connection");
}
- int res = GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp, tmp_offset);
- if (res != 0) {
- throw new GLException("glXGetFBConfig("+toHexString(attrib)+") failed: error code " + glXGetFBConfigErrorCode(res));
+ final boolean res = GLX.GLX_BAD_ATTRIBUTE != GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp);
+ if( !res ) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.glXGetFBConfig: FBConfig invalid: fbcfg: "+toHexString(cfg));
+ }
}
- return tmp[tmp_offset];
+ return res;
}
- static int glXFBConfig2FBConfigID(long display, long cfg) {
- int[] tmpID = new int[1];
- return glXGetFBConfig(display, cfg, GLX.GLX_FBCONFIG_ID, tmpID, 0);
+ static int glXFBConfig2FBConfigID(final long display, final long cfg) {
+ final IntBuffer tmpID = Buffers.newDirectIntBuffer(1);
+ if( glXGetFBConfig(display, cfg, GLX.GLX_FBCONFIG_ID, tmpID) ) {
+ return tmpID.get(0);
+ } else {
+ return VisualIDHolder.VID_UNDEFINED; // error
+ }
}
- static long glXFBConfigID2FBConfig(long display, int screen, int id) {
- int[] attribs = new int[] { GLX.GLX_FBCONFIG_ID, id, 0 };
- int[] count = { -1 };
- PointerBuffer fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0);
+ static long glXFBConfigID2FBConfig(final long display, final int screen, final int id) {
+ final IntBuffer attribs = Buffers.newDirectIntBuffer(new int[] { GLX.GLX_FBCONFIG_ID, id, 0 });
+ final IntBuffer count = Buffers.newDirectIntBuffer(1);
+ count.put(0, -1);
+ final PointerBuffer fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, count);
if (fbcfgsL == null || fbcfgsL.limit()<1) {
return 0;
}
@@ -381,15 +467,15 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
// Visual Info
- static XVisualInfo XVisualID2XVisualInfo(long display, long visualID) {
- int[] count = new int[1];
- XVisualInfo template = XVisualInfo.create();
+ static XVisualInfo XVisualID2XVisualInfo(final long display, final long visualID) {
+ final int[] count = new int[1];
+ final XVisualInfo template = XVisualInfo.create();
template.setVisualid(visualID);
- XVisualInfo[] infos = X11Lib.XGetVisualInfo(display, X11Lib.VisualIDMask, template, count, 0);
+ final XVisualInfo[] infos = X11Lib.XGetVisualInfo(display, X11Lib.VisualIDMask, template, count, 0);
if (infos == null || infos.length == 0) {
return null;
- }
- XVisualInfo res = XVisualInfo.create(infos[0]);
+ }
+ final XVisualInfo res = XVisualInfo.create(infos[0]);
if (DEBUG) {
System.err.println("Fetched XVisualInfo for visual ID " + toHexString(visualID));
System.err.println("Resulting XVisualInfo: visualid = " + toHexString(res.getVisualid()));
@@ -397,12 +483,12 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
return res;
}
- static X11GLCapabilities XVisualInfo2GLCapabilities(final X11GraphicsDevice device, GLProfile glp, XVisualInfo info,
- final int winattrmask, boolean isMultisampleEnabled) {
- final int allDrawableTypeBits = GLGraphicsConfigurationUtil.WINDOW_BIT |
+ static X11GLCapabilities XVisualInfo2GLCapabilities(final X11GraphicsDevice device, final GLProfile glp, final XVisualInfo info,
+ final int winattrmask, final boolean isMultisampleEnabled) {
+ final int allDrawableTypeBits = GLGraphicsConfigurationUtil.WINDOW_BIT |
GLGraphicsConfigurationUtil.BITMAP_BIT |
GLGraphicsConfigurationUtil.FBO_BIT ;
-
+
final int drawableTypeBits = winattrmask & allDrawableTypeBits;
if( 0 == drawableTypeBits ) {
@@ -410,15 +496,15 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
final long display = device.getHandle();
- int[] tmp = new int[1];
- int val = glXGetConfig(display, info, GLX.GLX_USE_GL, tmp, 0);
+ final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
+ int val = glXGetConfig(display, info, GLX.GLX_USE_GL, tmp);
if (val == 0) {
if(DEBUG) {
System.err.println("Visual ("+toHexString(info.getVisualid())+") does not support OpenGL");
}
return null;
}
- val = glXGetConfig(display, info, GLX.GLX_RGBA, tmp, 0);
+ val = glXGetConfig(display, info, GLX.GLX_RGBA, tmp);
if (val == 0) {
if(DEBUG) {
System.err.println("Visual ("+toHexString(info.getVisualid())+") does not support RGBA");
@@ -426,20 +512,20 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
return null;
}
- GLCapabilities res = new X11GLCapabilities(info, glp);
+ final GLCapabilities res = new X11GLCapabilities(info, glp);
- res.setDoubleBuffered(glXGetConfig(display, info, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0);
- res.setStereo (glXGetConfig(display, info, GLX.GLX_STEREO, tmp, 0) != 0);
+ res.setDoubleBuffered(glXGetConfig(display, info, GLX.GLX_DOUBLEBUFFER, tmp) != 0);
+ res.setStereo (glXGetConfig(display, info, GLX.GLX_STEREO, tmp) != 0);
// Note: use of hardware acceleration is determined by
// glXCreateContext, not by the XVisualInfo. Optimistically claim
// that all GLCapabilities have the capability to be hardware
- // accelerated.
+ // accelerated.
if (isMultisampleEnabled) {
- res.setSampleBuffers(glXGetConfig(display, info, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0);
- res.setNumSamples (glXGetConfig(display, info, GLX.GLX_SAMPLES, tmp, 0));
+ res.setSampleBuffers(glXGetConfig(display, info, GLX.GLX_SAMPLE_BUFFERS, tmp) != 0);
+ res.setNumSamples (glXGetConfig(display, info, GLX.GLX_SAMPLES, tmp));
}
- final XRenderDirectFormat xrmask = ( null != info ) ?
- XVisual2XRenderMask( display, info.getVisual() ) :
+ final XRenderDirectFormat xrmask = ( null != info ) ?
+ XVisual2XRenderMask( display, info.getVisual() ) :
null ;
final int alphaMask = ( null != xrmask ) ? xrmask.getAlphaMask() : 0;
res.setBackgroundOpaque( 0 >= alphaMask );
@@ -451,21 +537,21 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
// ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
res.setHardwareAccelerated(true);
- res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp, 0));
- res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp, 0));
- res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp, 0));
- res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp, 0));
- res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp, 0));
- res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp, 0));
- res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp, 0));
- res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0));
- res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0));
- res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0));
-
- return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
+ res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp));
+ res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp));
+ res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp));
+ res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp));
+ res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp));
+ res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp));
+ res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp));
+ res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp));
+ res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp));
+ res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp));
+
+ return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
}
- private static String glXGetConfigErrorCode(int err) {
+ private static String glXGetConfigErrorCode(final int err) {
switch (err) {
case GLX.GLX_NO_EXTENSION: return "GLX_NO_EXTENSION";
case GLX.GLX_BAD_SCREEN: return "GLX_BAD_SCREEN";
@@ -475,17 +561,18 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
}
- static int glXGetConfig(long display, XVisualInfo info, int attrib, int[] tmp, int tmp_offset) {
+ static int glXGetConfig(final long display, final XVisualInfo info, final int attrib, final IntBuffer tmp) {
if (display == 0) {
throw new GLException("No display connection");
}
- int res = GLX.glXGetConfig(display, info, attrib, tmp, tmp_offset);
+ final int res = GLX.glXGetConfig(display, info, attrib, tmp);
if (res != 0) {
throw new GLException("glXGetConfig("+toHexString(attrib)+") failed: error code " + glXGetConfigErrorCode(res));
}
- return tmp[tmp_offset];
+ return tmp.get(tmp.position());
}
+ @Override
public String toString() {
return "X11GLXGraphicsConfiguration["+getScreen()+", visualID " + toHexString(getXVisualID()) + ", fbConfigID " + toHexString(getFBConfigID()) +
",\n\trequested " + getRequestedCapabilities()+
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
index 431706e24..44479acc0 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -45,11 +45,11 @@ import javax.media.opengl.DefaultGLCapabilitiesChooser;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
-import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
@@ -59,6 +59,7 @@ import jogamp.nativewindow.x11.XVisualInfo;
import jogamp.opengl.GLGraphicsConfigurationFactory;
import jogamp.opengl.GLGraphicsConfigurationUtil;
+import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -91,8 +92,9 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
private X11GLXGraphicsConfigurationFactory() {
}
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested, final CapabilitiesChooser chooser, final AbstractGraphicsScreen absScreen, final int nativeVisualID) {
if (!(absScreen instanceof X11GraphicsScreen)) {
throw new IllegalArgumentException("Only X11GraphicsScreen are allowed here");
}
@@ -108,7 +110,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects");
}
-
+
if(!GLXUtil.isGLXAvailableOnServer((X11GraphicsDevice)absScreen.getDevice())) {
if(null != fallbackX11GraphicsConfigurationFactory) {
if(DEBUG) {
@@ -117,27 +119,33 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
return fallbackX11GraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen, VisualIDHolder.VID_UNDEFINED);
}
throw new InternalError("No GLX and no fallback GraphicsConfigurationFactory available for: "+absScreen);
- }
+ }
return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested,
(GLCapabilitiesChooser)chooser, (X11GraphicsScreen)absScreen, nativeVisualID);
}
- protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(X11GLXDrawableFactory factory, AbstractGraphicsDevice device) {
- X11GLXDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(final X11GLXDrawableFactory factory, final AbstractGraphicsDevice device) {
+ final X11GLXDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
final X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sharedResource.getScreen();
- final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(sharedScreen.getDevice());
+ final X11GraphicsDevice sharedDevice = (X11GraphicsDevice) sharedScreen.getDevice();
+ final boolean isMultisampleAvailable = sharedResource.isGLXMultisampleAvailable();
final GLProfile glp = GLProfile.getDefault(device);
List<GLCapabilitiesImmutable> availableCaps = null;
- if( sharedResource.isGLXVersionGreaterEqualOneThree() ) {
- availableCaps = getAvailableGLCapabilitiesFBConfig(sharedScreen, glp, isMultisampleAvailable);
- }
- if( null == availableCaps || availableCaps.isEmpty() ) {
- availableCaps = getAvailableGLCapabilitiesXVisual(sharedScreen, glp, isMultisampleAvailable);
+ sharedDevice.lock();
+ try {
+ if( sharedResource.isGLXVersionGreaterEqualOneThree() ) {
+ availableCaps = getAvailableGLCapabilitiesFBConfig(sharedScreen, glp, isMultisampleAvailable);
+ }
+ if( null == availableCaps || availableCaps.isEmpty() ) {
+ availableCaps = getAvailableGLCapabilitiesXVisual(sharedScreen, glp, isMultisampleAvailable);
+ }
+ } finally {
+ sharedDevice.unlock();
}
if( null != availableCaps && availableCaps.size() > 1 ) {
Collections.sort(availableCaps, XVisualIDComparator);
@@ -145,7 +153,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
return availableCaps;
}
- static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesFBConfig(X11GraphicsScreen x11Screen, GLProfile glProfile, boolean isMultisampleAvailable) {
+ static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesFBConfig(final X11GraphicsScreen x11Screen, final GLProfile glProfile, final boolean isMultisampleAvailable) {
PointerBuffer fbcfgsL = null;
// Utilizing FBConfig
@@ -154,13 +162,14 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
final long display = absDevice.getHandle();
final int screen = x11Screen.getIndex();
- final int[] count = { -1 };
+ final IntBuffer count = Buffers.newDirectIntBuffer(1);
+ count.put(0, -1);
final ArrayList<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
- fbcfgsL = GLX.glXChooseFBConfig(display, screen, null, 0, count, 0);
+ fbcfgsL = GLX.glXChooseFBConfig(display, screen, null, count);
if (fbcfgsL == null || fbcfgsL.limit()<=0) {
if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesFBConfig: Failed glXChooseFBConfig ("+x11Screen+"): "+fbcfgsL+", "+count[0]);
+ System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesFBConfig: Failed glXChooseFBConfig ("+x11Screen+"): "+fbcfgsL+", "+count.get(0));
}
return null;
}
@@ -175,20 +184,20 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
return availableCaps;
}
- static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesXVisual(X11GraphicsScreen x11Screen, GLProfile glProfile, boolean isMultisampleAvailable) {
+ static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesXVisual(final X11GraphicsScreen x11Screen, final GLProfile glProfile, final boolean isMultisampleAvailable) {
final X11GraphicsDevice absDevice = (X11GraphicsDevice) x11Screen.getDevice();
final long display = absDevice.getHandle();
- int screen = x11Screen.getIndex();
+ final int screen = x11Screen.getIndex();
- int[] count = new int[1];
- XVisualInfo template = XVisualInfo.create();
+ final int[] count = new int[1];
+ final XVisualInfo template = XVisualInfo.create();
template.setScreen(screen);
- XVisualInfo[] infos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0);
+ final XVisualInfo[] infos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0);
if (infos == null || infos.length<1) {
throw new GLException("Error while enumerating available XVisualInfos");
}
- ArrayList<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
+ final ArrayList<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
for (int i = 0; i < infos.length; i++) {
final GLCapabilitiesImmutable caps = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(absDevice, glProfile, infos[i], GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable);
if(null != caps) {
@@ -202,30 +211,35 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
static X11GLXGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
- GLCapabilitiesImmutable capsReq,
- GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen, int xvisualID) {
+ final GLCapabilitiesImmutable capsReq,
+ final GLCapabilitiesChooser chooser,
+ final X11GraphicsScreen x11Screen, final int xvisualID) {
if (x11Screen == null) {
throw new IllegalArgumentException("AbstractGraphicsScreen is null");
}
if (capsChosen == null) {
capsChosen = new GLCapabilities(null);
}
- X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
- X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
+ final X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
+ final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
+
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory, x11Device);
+ final boolean usePBuffer = !capsChosen.isOnscreen() && capsChosen.isPBuffer();
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(x11Device, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(x11Device) );
- boolean usePBuffer = !capsChosen.isOnscreen() && capsChosen.isPBuffer();
-
X11GLXGraphicsConfiguration res = null;
- if( factory.isGLXVersionGreaterEqualOneThree(x11Device) ) {
- res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen, xvisualID);
- }
- if(null==res) {
- if(usePBuffer) {
- throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for visualID "+toHexString(xvisualID)+", "+capsChosen);
+ x11Device.lock();
+ try {
+ if( factory.isGLXVersionGreaterEqualOneThree(x11Device) ) {
+ res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen, xvisualID);
}
- res = chooseGraphicsConfigurationXVisual(capsChosen, capsReq, chooser, x11Screen, xvisualID);
+ if(null==res) {
+ if(usePBuffer) {
+ throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for visualID "+toHexString(xvisualID)+", "+capsChosen);
+ }
+ res = chooseGraphicsConfigurationXVisual(capsChosen, capsReq, chooser, x11Screen, xvisualID);
+ }
+ } finally {
+ x11Device.unlock();
}
if(null==res) {
throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for visualID "+toHexString(xvisualID)+", "+x11Screen+", "+capsChosen);
@@ -236,7 +250,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
return res;
}
- static X11GLXGraphicsConfiguration fetchGraphicsConfigurationFBConfig(X11GraphicsScreen x11Screen, int fbID, GLProfile glp) {
+ static X11GLXGraphicsConfiguration fetchGraphicsConfigurationFBConfig(final X11GraphicsScreen x11Screen, final int fbID, final GLProfile glp) {
final X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
final long display = x11Device.getHandle();
final int screen = x11Screen.getIndex();
@@ -244,61 +258,71 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
final long fbcfg = X11GLXGraphicsConfiguration.glXFBConfigID2FBConfig(display, screen, fbID);
if( 0 == fbcfg || !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfg ) ) {
if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed - GLX FBConfig invalid: ("+x11Screen+","+toHexString(fbID)+"): fbcfg: "+toHexString(fbcfg));
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed.0 - GLX FBConfig invalid: ("+x11Screen+","+toHexString(fbID)+"): fbcfg: "+toHexString(fbcfg));
}
return null;
}
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
-
+
final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glp, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, factory.isGLXMultisampleAvailable(x11Device));
+ if(null==caps) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed.1 - GLX FBConfig invalid: ("+x11Screen+","+toHexString(fbID)+"): fbcfg: "+toHexString(fbcfg));
+ }
+ return null;
+ }
return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser());
}
- private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationFBConfig(GLCapabilitiesImmutable capsChosen,
- GLCapabilitiesImmutable capsReq,
- GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen, int xvisualID) {
+ private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationFBConfig(final GLCapabilitiesImmutable capsChosen,
+ final GLCapabilitiesImmutable capsReq,
+ final GLCapabilitiesChooser chooser,
+ final X11GraphicsScreen x11Screen, final int xvisualID) {
int recommendedIndex = -1;
PointerBuffer fbcfgsL = null;
- GLProfile glProfile = capsChosen.getGLProfile();
+ final GLProfile glProfile = capsChosen.getGLProfile();
// Utilizing FBConfig
//
- X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
- long display = x11Device.getHandle();
- int screen = x11Screen.getIndex();
-
- final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
+ final X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
+ final long display = x11Device.getHandle();
+ final int screen = x11Screen.getIndex();
+
+ final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(x11Device);
- int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, true, isMultisampleAvailable, display, screen);
- int[] count = { -1 };
- List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
+ final IntBuffer attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, true, isMultisampleAvailable, display, screen);
+ final IntBuffer count = Buffers.newDirectIntBuffer(1);
+ count.put(0, -1);
final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen);
+ List<GLCapabilitiesImmutable> availableCaps;
// 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice,
// skipped if xvisualID is given
+ final boolean hasGLXChosenCaps;
if( VisualIDHolder.VID_UNDEFINED == xvisualID ) {
- fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0);
- }
- if (fbcfgsL != null && fbcfgsL.limit()>0) {
- for (int i = 0; i < fbcfgsL.limit(); i++) {
- final GLCapabilitiesImmutable caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glProfile, fbcfgsL.get(i), winattrmask, isMultisampleAvailable);
- if( null != caps ) {
- availableCaps.add(caps);
- } else if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (1): ("+x11Screen+","+capsChosen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
- }
- }
+ fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, count);
+ hasGLXChosenCaps = fbcfgsL != null && fbcfgsL.limit()>0;
+ } else {
+ hasGLXChosenCaps = false;
+ }
+ final boolean useRecommendedIndex = hasGLXChosenCaps && capsChosen.isBackgroundOpaque(); // only use recommended idx if not translucent
+ final boolean skipCapsChooser = null == chooser && useRecommendedIndex; // fast path: skip choosing if using recommended idx and null chooser is used
+ if (hasGLXChosenCaps) {
+ availableCaps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glProfile, fbcfgsL, winattrmask, isMultisampleAvailable, skipCapsChooser /* onlyFirstValid */);
if(availableCaps.size() > 0) {
- recommendedIndex = capsChosen.isBackgroundOpaque() ? 0 : -1; // only use recommended idx if not translucent
+ recommendedIndex = useRecommendedIndex ? 0 : -1;
if (DEBUG) {
System.err.println("glXChooseFBConfig recommended fbcfg " + toHexString(fbcfgsL.get(0)) + ", idx " + recommendedIndex);
+ System.err.println("useRecommendedIndex "+useRecommendedIndex+", skipCapsChooser "+skipCapsChooser);
System.err.println("user caps " + capsChosen);
- System.err.println("fbcfg caps " + availableCaps.get(0));
+ System.err.println("fbcfg caps " + fbcfgsL.limit()+", availCaps "+availableCaps.get(0));
}
} else if (DEBUG) {
System.err.println("glXChooseFBConfig no caps for recommended fbcfg " + toHexString(fbcfgsL.get(0)));
+ System.err.println("useRecommendedIndex "+useRecommendedIndex+", skipCapsChooser "+skipCapsChooser);
System.err.println("user caps " + capsChosen);
}
+ } else {
+ availableCaps = new ArrayList<GLCapabilitiesImmutable>();
}
// 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available
@@ -306,34 +330,26 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
// reset ..
recommendedIndex = -1;
- fbcfgsL = GLX.glXChooseFBConfig(display, screen, null, 0, count, 0);
+ fbcfgsL = GLX.glXChooseFBConfig(display, screen, null, count);
if (fbcfgsL == null || fbcfgsL.limit()<=0) {
if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXChooseFBConfig ("+x11Screen+","+capsChosen+"): "+fbcfgsL+", "+count[0]);
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXChooseFBConfig ("+x11Screen+","+capsChosen+"): "+fbcfgsL+", "+count.get(0));
}
return null;
}
-
- for (int i = 0; i < fbcfgsL.limit(); i++) {
- final GLCapabilitiesImmutable caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glProfile, fbcfgsL.get(i), winattrmask, isMultisampleAvailable);
- if( null != caps ) {
- availableCaps.add(caps);
- } else if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
- }
- }
+ availableCaps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glProfile, fbcfgsL, winattrmask, isMultisampleAvailable, false /* onlyOneValid */);
}
-
+
if(DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: got configs: "+availableCaps.size());
for(int i=0; i<availableCaps.size(); i++) {
System.err.println(i+": "+availableCaps.get(i));
}
}
-
- if( VisualIDHolder.VID_UNDEFINED != xvisualID ) {
+
+ if( VisualIDHolder.VID_UNDEFINED != xvisualID ) { // implies !hasGLXChosenCaps
for(int i=0; i<availableCaps.size(); ) {
- VisualIDHolder vidh = (VisualIDHolder) availableCaps.get(i);
+ final VisualIDHolder vidh = availableCaps.get(i);
if(vidh.getVisualID(VIDType.X11_XVISUAL) != xvisualID ) {
availableCaps.remove(i);
} else {
@@ -349,8 +365,13 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: post filter visualID "+toHexString(xvisualID)+" got configs: "+availableCaps.size());
}
}
-
- int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
+
+ final int chosenIndex;
+ if( skipCapsChooser && 0 <= recommendedIndex ) {
+ chosenIndex = recommendedIndex;
+ } else {
+ chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
+ }
if ( 0 > chosenIndex ) {
if (DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: failed, return null");
@@ -358,37 +379,37 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
return null;
}
- X11GLCapabilities chosenCaps = (X11GLCapabilities) availableCaps.get(chosenIndex);
+ final X11GLCapabilities chosenCaps = (X11GLCapabilities) availableCaps.get(chosenIndex);
return new X11GLXGraphicsConfiguration(x11Screen, chosenCaps, capsReq, chooser);
}
- private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(GLCapabilitiesImmutable capsChosen,
- GLCapabilitiesImmutable capsReq,
+ private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(final GLCapabilitiesImmutable capsChosen,
+ final GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen, int xvisualID) {
+ final X11GraphicsScreen x11Screen, final int xvisualID) {
if (chooser == null) {
chooser = new DefaultGLCapabilitiesChooser();
}
- GLProfile glProfile = capsChosen.getGLProfile();
+ final GLProfile glProfile = capsChosen.getGLProfile();
final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen.isOnscreen(), capsChosen.isFBO(), false /* pbuffer */, capsChosen.isBitmap());
- List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
+ final List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
int recommendedIndex = -1;
- X11GraphicsDevice absDevice = (X11GraphicsDevice) x11Screen.getDevice();
- long display = absDevice.getHandle();
- int screen = x11Screen.getIndex();
-
- final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(absDevice);
- int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, false, isMultisampleAvailable, display, screen);
+ final X11GraphicsDevice absDevice = (X11GraphicsDevice) x11Screen.getDevice();
+ final long display = absDevice.getHandle();
+ final int screen = x11Screen.getIndex();
+
+ final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
+ final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(absDevice);
+ final IntBuffer attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, false, isMultisampleAvailable, display, screen);
XVisualInfo recommendedVis = null;
// 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice
// skipped if xvisualID is given
- if( VisualIDHolder.VID_UNDEFINED == xvisualID ) {
- recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0);
+ if( VisualIDHolder.VID_UNDEFINED == xvisualID ) {
+ recommendedVis = GLX.glXChooseVisual(display, screen, attribs);
if (DEBUG) {
System.err.print("glXChooseVisual recommended ");
if (recommendedVis == null) {
@@ -400,10 +421,10 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
// 2nd choice: get all GLCapabilities available, preferred recommendedIndex might be available if 1st choice was successful
- int[] count = new int[1];
- XVisualInfo template = XVisualInfo.create();
+ final int[] count = new int[1];
+ final XVisualInfo template = XVisualInfo.create();
template.setScreen(screen);
- XVisualInfo[] infos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0);
+ final XVisualInfo[] infos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0);
if (infos == null || infos.length<1) {
throw new GLException("Error while enumerating available XVisualInfos");
}
@@ -427,10 +448,10 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
System.err.println(i+": "+availableCaps.get(i));
}
}
-
+
if( VisualIDHolder.VID_UNDEFINED != xvisualID ) {
for(int i=0; i<availableCaps.size(); ) {
- VisualIDHolder vidh = (VisualIDHolder) availableCaps.get(i);
+ final VisualIDHolder vidh = availableCaps.get(i);
if(vidh.getVisualID(VIDType.X11_XVISUAL) != xvisualID ) {
availableCaps.remove(i);
} else {
@@ -439,15 +460,15 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
if(0==availableCaps.size()) {
if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: post filter visualID "+toHexString(xvisualID )+" no config found, failed - return null");
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: post filter visualID "+toHexString(xvisualID )+" no config found, failed - return null");
}
return null;
} else if(DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: post filter visualID "+toHexString(xvisualID)+" got configs: "+availableCaps.size());
}
}
-
- int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
+
+ final int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
if ( 0 > chosenIndex ) {
if (DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: failed, return null");
@@ -455,7 +476,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
return null;
}
- X11GLCapabilities chosenCaps = (X11GLCapabilities) availableCaps.get(chosenIndex);
+ final X11GLCapabilities chosenCaps = (X11GLCapabilities) availableCaps.get(chosenIndex);
return new X11GLXGraphicsConfiguration(x11Screen, chosenCaps, capsReq, chooser);
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java
deleted file mode 100644
index 460dc10ca..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-package jogamp.opengl.x11.glx;
-
-import javax.media.opengl.*;
-
-public class X11OnscreenGLXContext extends X11GLXContext {
-
- public X11OnscreenGLXContext(X11OnscreenGLXDrawable drawable, GLContext shareWith) {
- super(drawable, shareWith);
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
index 363299321..866662950 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
@@ -51,12 +51,12 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
long glXWindow; // GLXWindow, a GLXDrawable representation
boolean useGLXWindow;
- protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeSurface component, boolean realized) {
+ protected X11OnscreenGLXDrawable(final GLDrawableFactory factory, final NativeSurface component, final boolean realized) {
super(factory, component, realized);
glXWindow=0;
useGLXWindow=false;
if(realized) {
- updateHandle();
+ createHandle();
}
}
@@ -82,16 +82,16 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
}
@Override
- protected final void updateHandle() {
+ protected final void createHandle() {
if(USE_GLXWINDOW) {
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
+ final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
if(config.getFBConfig()>=0) {
useGLXWindow=true;
- long dpy = getNativeSurface().getDisplayHandle();
+ final long dpy = getNativeSurface().getDisplayHandle();
if(0!=glXWindow) {
GLX.glXDestroyWindow(dpy, glXWindow);
}
- glXWindow = GLX.glXCreateWindow(dpy, config.getFBConfig(), getNativeSurface().getSurfaceHandle(), null, 0);
+ glXWindow = GLX.glXCreateWindow(dpy, config.getFBConfig(), getNativeSurface().getSurfaceHandle(), null);
if (DEBUG) {
System.err.println("X11OnscreenGLXDrawable.setRealized(true): glXWindow: "+toHexString(getNativeSurface().getSurfaceHandle())+" -> "+toHexString(glXWindow));
}
@@ -103,7 +103,7 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new X11OnscreenGLXContext(this, shareWith);
+ public GLContext createContext(final GLContext shareWith) {
+ return new X11GLXContext(this, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java
deleted file mode 100644
index a34e050cd..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.x11.glx;
-
-import javax.media.opengl.*;
-
-public class X11PbufferGLXContext extends X11GLXContext {
-
- public X11PbufferGLXContext(X11PbufferGLXDrawable drawable, GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public void bindPbufferToTexture() {
- // FIXME: figure out how to implement this
- throw new GLException("Not yet implemented");
- }
-
- @Override
- public void releasePbufferFromTexture() {
- // FIXME: figure out how to implement this
- throw new GLException("Not yet implemented");
- }
-
-
- @Override
- public int getFloatingPointMode() {
- return ((X11PbufferGLXDrawable)drawable).getFloatingPointMode();
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
index bba2b3513..21ad06020 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
@@ -40,18 +40,20 @@
package jogamp.opengl.x11.glx;
+import java.nio.IntBuffer;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.MutableSurface;
-import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
-import javax.media.opengl.GLPbuffer;
+
+import com.jogamp.common.nio.Buffers;
public class X11PbufferGLXDrawable extends X11GLXDrawable {
- protected X11PbufferGLXDrawable(GLDrawableFactory factory, NativeSurface target) {
+ protected X11PbufferGLXDrawable(final GLDrawableFactory factory, final NativeSurface target) {
/* GLCapabilities caps,
GLCapabilitiesChooser chooser,
int width, int height */
@@ -68,16 +70,19 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new X11PbufferGLXContext(this, shareWith);
+ public GLContext createContext(final GLContext shareWith) {
+ return new X11GLXContext(this, shareWith);
}
protected void destroyPbuffer() {
- NativeSurface ns = getNativeSurface();
+ final NativeSurface ns = getNativeSurface();
if (ns.getSurfaceHandle() != 0) {
GLX.glXDestroyPbuffer(ns.getDisplayHandle(), ns.getSurfaceHandle());
}
((MutableSurface)ns).setSurfaceHandle(0);
+ if (DEBUG) {
+ System.err.println(getThreadName()+": Destroyed pbuffer " + this);
+ }
}
private void createPbuffer() {
@@ -88,36 +93,26 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
final long display = aDevice.getHandle();
if (DEBUG) {
- System.out.println("Pbuffer config: " + config);
+ System.out.println(getThreadName()+": Pbuffer config: " + config);
}
if (display==0) {
throw new GLException("Null display");
}
- GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
-
- if (chosenCaps.getPbufferRenderToTexture()) {
- throw new GLException("Render-to-texture pbuffers not supported yet on X11");
- }
-
- if (chosenCaps.getPbufferRenderToTextureRectangle()) {
- throw new GLException("Render-to-texture-rectangle pbuffers not supported yet on X11");
- }
-
// Create the p-buffer.
int niattribs = 0;
- int[] iattributes = new int[7];
+ final IntBuffer iattributes = Buffers.newDirectIntBuffer(7);
- iattributes[niattribs++] = GLX.GLX_PBUFFER_WIDTH;
- iattributes[niattribs++] = ms.getWidth();
- iattributes[niattribs++] = GLX.GLX_PBUFFER_HEIGHT;
- iattributes[niattribs++] = ms.getHeight();
- iattributes[niattribs++] = GLX.GLX_LARGEST_PBUFFER; // exact
- iattributes[niattribs++] = 0;
- iattributes[niattribs++] = 0;
+ iattributes.put(niattribs++, GLX.GLX_PBUFFER_WIDTH);
+ iattributes.put(niattribs++, ms.getSurfaceWidth());
+ iattributes.put(niattribs++, GLX.GLX_PBUFFER_HEIGHT);
+ iattributes.put(niattribs++, ms.getSurfaceHeight());
+ iattributes.put(niattribs++, GLX.GLX_LARGEST_PBUFFER); // exact
+ iattributes.put(niattribs++, 0);
+ iattributes.put(niattribs++, 0);
- long pbuffer = GLX.glXCreatePbuffer(display, config.getFBConfig(), iattributes, 0);
+ final long pbuffer = GLX.glXCreatePbuffer(display, config.getFBConfig(), iattributes);
if (pbuffer == 0) {
// FIXME: query X error code for detail error message
throw new GLException("pbuffer creation error: glXCreatePbuffer() failed");
@@ -127,12 +122,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
ms.setSurfaceHandle(pbuffer);
if (DEBUG) {
- System.err.println("Created pbuffer " + this);
+ System.err.println(getThreadName()+": Created pbuffer " + this);
}
}
-
- public int getFloatingPointMode() {
- // Floating-point pbuffers currently require NVidia hardware on X11
- return GLPbuffer.NV_FLOAT;
- }
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
deleted file mode 100644
index 96d0f18dc..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.x11.glx;
-
-import javax.media.opengl.*;
-
-public class X11PixmapGLXContext extends X11GLXContext {
-
- public X11PixmapGLXContext(X11PixmapGLXDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public int getOffscreenContextPixelDataType() {
- GL gl = getGL();
- return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
- }
-
- @Override
- public int getOffscreenContextReadBuffer() {
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities();
- if (caps.getDoubleBuffered()) {
- return GL.GL_BACK;
- }
- return GL.GL_FRONT;
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- // There doesn't seem to be a way to do this in the construction
- // of the Pixmap or GLXPixmap
- return true;
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
index 04627724c..e217e1c2a 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
@@ -54,7 +54,7 @@ import jogamp.nativewindow.x11.XVisualInfo;
public class X11PixmapGLXDrawable extends X11GLXDrawable {
private long pixmap;
- protected X11PixmapGLXDrawable(GLDrawableFactory factory, NativeSurface target) {
+ protected X11PixmapGLXDrawable(final GLDrawableFactory factory, final NativeSurface target) {
super(factory, target, false);
}
@@ -68,26 +68,26 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
}
@Override
- public GLContext createContext(GLContext shareWith) {
- return new X11PixmapGLXContext(this, shareWith);
+ public GLContext createContext(final GLContext shareWith) {
+ return new X11GLXContext(this, shareWith);
}
private void createPixmap() {
- NativeSurface ns = getNativeSurface();
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) ns.getGraphicsConfiguration();
- XVisualInfo vis = config.getXVisualInfo();
- int bitsPerPixel = vis.getDepth();
- AbstractGraphicsScreen aScreen = config.getScreen();
- AbstractGraphicsDevice aDevice = aScreen.getDevice();
- long dpy = aDevice.getHandle();
- int screen = aScreen.getIndex();
+ final NativeSurface ns = getNativeSurface();
+ final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) ns.getGraphicsConfiguration();
+ final XVisualInfo vis = config.getXVisualInfo();
+ final int bitsPerPixel = vis.getDepth();
+ final AbstractGraphicsScreen aScreen = config.getScreen();
+ final AbstractGraphicsDevice aDevice = aScreen.getDevice();
+ final long dpy = aDevice.getHandle();
+ final int screen = aScreen.getIndex();
pixmap = X11Lib.XCreatePixmap(dpy, X11Lib.RootWindow(dpy, screen),
- surface.getWidth(), surface.getHeight(), bitsPerPixel);
+ surface.getSurfaceWidth(), surface.getSurfaceHeight(), bitsPerPixel);
if (pixmap == 0) {
throw new GLException("XCreatePixmap failed");
}
- long drawable = GLX.glXCreateGLXPixmap(dpy, vis, pixmap);
+ final long drawable = GLX.glXCreateGLXPixmap(dpy, vis, pixmap);
if (drawable == 0) {
X11Lib.XFreePixmap(dpy, pixmap);
pixmap = 0;
@@ -95,7 +95,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
}
((MutableSurface)ns).setSurfaceHandle(drawable);
if (DEBUG) {
- System.err.println("Created pixmap " + toHexString(pixmap) +
+ System.err.println(getThreadName()+": Created pixmap " + toHexString(pixmap) +
", GLXPixmap " + toHexString(drawable) +
", display " + toHexString(dpy));
}
@@ -104,12 +104,12 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
protected void destroyPixmap() {
if (pixmap == 0) return;
- NativeSurface ns = getNativeSurface();
+ final NativeSurface ns = getNativeSurface();
long display = ns.getDisplayHandle();
long drawable = ns.getSurfaceHandle();
if (DEBUG) {
- System.err.println("Destroying pixmap " + toHexString(pixmap) +
+ System.err.println(getThreadName()+": Destroying pixmap " + toHexString(pixmap) +
", GLXPixmap " + toHexString(drawable) +
", display " + toHexString(display));
}
@@ -117,7 +117,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
// Must destroy pixmap and GLXPixmap
if (DEBUG) {
- long cur = GLX.glXGetCurrentContext();
+ final long cur = GLX.glXGetCurrentContext();
if (cur != 0) {
System.err.println("WARNING: found context " + toHexString(cur) + " current during pixmap destruction");
}
diff --git a/src/jogl/native/GLContext.c b/src/jogl/native/GLContext.c
new file mode 100644
index 000000000..9be9f82af
--- /dev/null
+++ b/src/jogl/native/GLContext.c
@@ -0,0 +1,46 @@
+
+#include "jogamp_opengl_GLContextImpl.h"
+#include "JoglCommon.h"
+
+#include <assert.h>
+#include <KHR/khrplatform.h>
+
+/*
+ * Class: jogamp_opengl_GLContextImpl
+ * Method: glGetStringInt
+ * Signature: (IJ)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_jogamp_opengl_GLContextImpl_glGetStringInt(JNIEnv *env, jclass _unused, jint name, jlong procAddress) {
+ typedef const khronos_uint8_t * (KHRONOS_APIENTRY*_local_PFNGLGETSTRINGPROC)(unsigned int name);
+ _local_PFNGLGETSTRINGPROC ptr_glGetString;
+ const khronos_uint8_t * _res;
+ ptr_glGetString = (_local_PFNGLGETSTRINGPROC) (intptr_t) procAddress;
+ assert(ptr_glGetString != NULL);
+ _res = (* ptr_glGetString) ((unsigned int) name);
+ if (NULL == _res) return NULL;
+ return (*env)->NewStringUTF(env, (const char *)_res);
+}
+
+/*
+ * Class: jogamp_opengl_GLContextImpl
+ * Method: glGetIntegervInt
+ * Signature: (ILjava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL
+Java_jogamp_opengl_GLContextImpl_glGetIntegervInt(JNIEnv *env, jclass _unused, jint pname, jobject params, jint params_byte_offset, jlong procAddress) {
+ typedef void (KHRONOS_APIENTRY*_local_PFNGLGETINTEGERVPROC)(unsigned int pname, int * params);
+
+ _local_PFNGLGETINTEGERVPROC ptr_glGetIntegerv;
+ int * _params_ptr = NULL;
+ if ( NULL != params ) {
+ _params_ptr = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, params, NULL) ) + params_byte_offset);
+ }
+ ptr_glGetIntegerv = (_local_PFNGLGETINTEGERVPROC) (intptr_t) procAddress;
+ assert(ptr_glGetIntegerv != NULL);
+ (* ptr_glGetIntegerv) ((unsigned int) pname, (int *) _params_ptr);
+ if ( NULL != params ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, params, _params_ptr, 0);
+ }
+}
+
diff --git a/src/jogl/native/GLDebugMessageHandler.c b/src/jogl/native/GLDebugMessageHandler.c
index fea9d90ce..0aa7a01e7 100644
--- a/src/jogl/native/GLDebugMessageHandler.c
+++ b/src/jogl/native/GLDebugMessageHandler.c
@@ -21,11 +21,11 @@
static jmethodID glDebugMessageARB = NULL; // int source, int type, int id, int severity, String msg
static jmethodID glDebugMessageAMD = NULL; // int id, int category, int severity, String msg
-typedef void (GLAPIENTRY* _local_PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const GLvoid *userParam);
-typedef void (GLAPIENTRY* _local_GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+typedef void (APIENTRY* _local_PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const GLvoid *userParam);
+typedef void (APIENTRY* _local_GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
-typedef void (GLAPIENTRY* _local_PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, const GLvoid *userParam);
-typedef void (GLAPIENTRY* _local_GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+typedef void (APIENTRY* _local_PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, const GLvoid *userParam);
+typedef void (APIENTRY* _local_GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
/*
* Class: jogamp_opengl_GLDebugMessageHandler
@@ -49,8 +49,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_opengl_GLDebugMessageHandler_initIDs0
}
typedef struct {
- JavaVM *vm;
- int version;
jobject obj;
int extType;
} DebugHandlerType;
@@ -60,39 +58,21 @@ typedef struct {
static void GLDebugMessageARBCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar *message, GLvoid *userParam) {
DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) userParam;
- JavaVM *vm = handle->vm;
- int version = handle->version;
jobject obj = handle->obj;
- JNIEnv *curEnv = NULL;
- JNIEnv *newEnv = NULL;
- int envRes ;
- DBG_PRINT("GLDebugMessageARBCallback: 00 - %s, vm %p, version 0x%X, jobject %p, extType %d\n",
- message, handle->vm, handle->version, (void*)handle->obj, handle->extType);
-
- // retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*vm)->GetEnv(vm, (void **) &curEnv, version) ;
- DBG_PRINT("GLDebugMessageARBCallback: 01 - JVM Env: curEnv %p, res 0x%X\n", curEnv, envRes);
- if( JNI_EDETACHED == envRes ) {
- // detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*vm)->AttachCurrentThread(vm, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "GLDebugMessageARBCallback: can't attach thread: %d\n", envRes);
- return;
- }
- curEnv = newEnv;
- DBG_PRINT("GLDebugMessageARBCallback: 02 - attached .. \n");
- } else if( JNI_OK != envRes ) {
- // oops ..
- fprintf(stderr, "GLDebugMessageARBCallback: can't GetEnv: %d\n", envRes);
+ JNIEnv *env = NULL;
+ int shallBeDetached ;
+ DBG_PRINT("GLDebugMessageARBCallback: 00 - %s, jobject %p, extType %d\n", message, (void*)handle->obj, handle->extType);
+
+ env = JoglCommon_GetJNIEnv (1 /* asDaemon */, &shallBeDetached);
+ if( NULL == env ) {
+ DBG_PRINT("GLDebugMessageARBCallback: Null JNIEnv\n");
return;
}
- (*curEnv)->CallVoidMethod(curEnv, obj, glDebugMessageARB,
+ (*env)->CallVoidMethod(env, obj, glDebugMessageARB,
(jint) source, (jint) type, (jint) id, (jint) severity,
- (*curEnv)->NewStringUTF(curEnv, message));
- if( NULL != newEnv ) {
- // detached attached thread
- (*vm)->DetachCurrentThread(vm);
- DBG_PRINT("GLDebugMessageARBCallback: 04 - detached .. \n");
- }
+ (*env)->NewStringUTF(env, message));
+ // detaching thread not required - daemon
+ // JoglCommon_ReleaseJNIEnv(shallBeDetached);
DBG_PRINT("GLDebugMessageARBCallback: 0X\n");
/**
* On Java 32bit on 64bit Windows and w/ GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB disables,
@@ -104,39 +84,21 @@ static void GLDebugMessageARBCallback(GLenum source, GLenum type, GLuint id, GLe
static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severity,
GLsizei length, const GLchar *message, GLvoid *userParam) {
DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) userParam;
- JavaVM *vm = handle->vm;
- int version = handle->version;
jobject obj = handle->obj;
- JNIEnv *curEnv = NULL;
- JNIEnv *newEnv = NULL;
- int envRes ;
- DBG_PRINT("GLDebugMessageAMDCallback: 00 - %s, vm %p, version 0x%X, jobject %p, extType %d\n",
- message, handle->vm, handle->version, (void*)handle->obj, handle->extType);
-
- // retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*vm)->GetEnv(vm, (void **) &curEnv, version) ;
- DBG_PRINT("GLDebugMessageAMDCallback: 01 - JVM Env: curEnv %p, res 0x%X\n", curEnv, envRes);
- if( JNI_EDETACHED == envRes ) {
- // detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*vm)->AttachCurrentThread(vm, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "GLDebugMessageAMDCallback: can't attach thread: %d\n", envRes);
- return;
- }
- curEnv = newEnv;
- DBG_PRINT("GLDebugMessageAMDCallback: 02 - attached .. \n");
- } else if( JNI_OK != envRes ) {
- // oops ..
- fprintf(stderr, "GLDebugMessageAMDCallback: can't GetEnv: %d\n", envRes);
+ JNIEnv *env = NULL;
+ int shallBeDetached ;
+ DBG_PRINT("GLDebugMessageAMDCallback: 00 - %s, jobject %p, extType %d\n", message, (void*)handle->obj, handle->extType);
+
+ env = JoglCommon_GetJNIEnv (1 /* asDaemon */, &shallBeDetached);
+ if( NULL == env ) {
+ DBG_PRINT("GLDebugMessageARBCallback: Null JNIEnv\n");
return;
}
- (*curEnv)->CallVoidMethod(curEnv, obj, glDebugMessageAMD,
+ (*env)->CallVoidMethod(env, obj, glDebugMessageAMD,
(jint) id, (jint) category, (jint) severity,
- (*curEnv)->NewStringUTF(curEnv, message));
- if( NULL != newEnv ) {
- // detached attached thread
- (*vm)->DetachCurrentThread(vm);
- DBG_PRINT("GLDebugMessageAMDCallback: 04 - detached .. \n");
- }
+ (*env)->NewStringUTF(env, message));
+ // detached attached thread not required - daemon
+ // JoglCommon_ReleaseJNIEnv(shallBeDetached);
DBG_PRINT("GLDebugMessageAMDCallback: 0X\n");
/**
* On Java 32bit on 64bit Windows,
@@ -153,18 +115,10 @@ static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severit
JNIEXPORT jlong JNICALL Java_jogamp_opengl_GLDebugMessageHandler_register0
(JNIEnv *env, jobject obj, jlong procAddress, jint extType)
{
- JavaVM *vm;
DebugHandlerType * handle = malloc(sizeof(DebugHandlerType));
- if(0 != (*env)->GetJavaVM(env, &vm)) {
- vm = NULL;
- JoglCommon_throwNewRuntimeException(env, "GetJavaVM failed");
- }
- handle->vm = vm;
- handle->version = (*env)->GetVersion(env);
handle->obj = (*env)->NewGlobalRef(env, obj);
handle->extType = extType;
- DBG_PRINT("GLDebugMessageHandler.register0: vm %p, version 0x%X, jobject %p, extType %d\n",
- handle->vm, handle->version, (void*)handle->obj, handle->extType);
+ DBG_PRINT("GLDebugMessageHandler.register0: jobject %p, extType %d\n", (void*)handle->obj, handle->extType);
if(jogamp_opengl_GLDebugMessageHandler_EXT_ARB == extType) {
_local_PFNGLDEBUGMESSAGECALLBACKARBPROC ptr_glDebugMessageCallbackARB;
@@ -191,8 +145,7 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_GLDebugMessageHandler_unregister0
{
DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) jhandle;
- DBG_PRINT("GLDebugMessageHandler.unregister0: vm %p, version 0x%X, jobject %p, extType %d\n",
- handle->vm, handle->version, (void*)handle->obj, handle->extType);
+ DBG_PRINT("GLDebugMessageHandler.unregister0: jobject %p, extType %d\n", (void*)handle->obj, handle->extType);
if(JNI_FALSE == (*env)->IsSameObject(env, obj, handle->obj)) {
JoglCommon_throwNewRuntimeException(env, "wrong handle (obj doesn't match)");
diff --git a/src/jogl/native/JoglCommon.c b/src/jogl/native/JoglCommon.c
index d9f5edd49..e9984ada2 100644
--- a/src/jogl/native/JoglCommon.c
+++ b/src/jogl/native/JoglCommon.c
@@ -1,5 +1,4 @@
-#include "jogamp_opengl_GLContextImpl.h"
#include "JoglCommon.h"
#include <assert.h>
@@ -12,42 +11,38 @@ static JavaVM *_jvmHandle = NULL;
static int _jvmVersion = 0;
void JoglCommon_init(JNIEnv *env) {
- if(NULL==runtimeExceptionClz) {
+ if(NULL==_jvmHandle) {
+ if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+ JoglCommon_FatalError(env, "JOGL: Can't fetch JavaVM handle");
+ } else {
+ _jvmVersion = (*env)->GetVersion(env);
+ }
jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
if(NULL==c) {
- JoglCommon_FatalError(env, "JOGL: can't find %s", ClazzNameRuntimeException);
+ JoglCommon_FatalError(env, "JOGL: Can't find %s", ClazzNameRuntimeException);
}
runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
if(NULL==runtimeExceptionClz) {
- JoglCommon_FatalError(env, "JOGL: can't use %s", ClazzNameRuntimeException);
+ JoglCommon_FatalError(env, "JOGL: Can't use %s", ClazzNameRuntimeException);
}
}
- if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
- JoglCommon_FatalError(env, "JOGL: can't fetch JavaVM handle");
- } else {
- _jvmVersion = (*env)->GetVersion(env);
- }
}
void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
- int shallBeDetached = 0;
- if(NULL == env) {
- env = JoglCommon_GetJNIEnv (&shallBeDetached);
- }
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
-
- fprintf(stderr, "%s\n", buffer);
- if(NULL != env) {
- (*env)->FatalError(env, buffer);
- JoglCommon_ReleaseJNIEnv (shallBeDetached);
+ fprintf(stderr, "%s\n", buffer);
+ if(NULL != env) {
+ (*env)->FatalError(env, buffer);
+ }
}
}
@@ -55,48 +50,42 @@ void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
- int shallBeDetached = 0;
- if(NULL == env) {
- env = JoglCommon_GetJNIEnv (&shallBeDetached);
+ if(NULL==_jvmHandle) {
+ JoglCommon_FatalError(env, "JOGL: NULL JVM handle, call JoglCommon_init 1st\n");
+ return;
}
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
- if(NULL != env) {
- (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
- JoglCommon_ReleaseJNIEnv (shallBeDetached);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
+ }
}
}
-JavaVM *JoglCommon_GetJVMHandle() {
- return _jvmHandle;
-}
-
-int JoglCommon_GetJVMVersion() {
- return _jvmVersion;
-}
-
jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
{
jchar* strChars = NULL;
- strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
- if (strChars != NULL) {
- (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ if( NULL != env && 0 != str ) {
+ strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
+ if (strChars != NULL) {
+ (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ }
}
return strChars;
}
-JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached)
-{
+JNIEnv* JoglCommon_GetJNIEnv (int asDaemon, int * shallBeDetached) {
JNIEnv* curEnv = NULL;
JNIEnv* newEnv = NULL;
int envRes;
- if(NULL == _jvmHandle) {
- fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st");
+ if(NULL==_jvmHandle) {
+ fprintf(stderr, "JOGL GetJNIEnv: NULL JVM handle, call JoglCommon_init 1st\n");
return NULL;
}
@@ -104,18 +93,23 @@ JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached)
envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ;
if( JNI_EDETACHED == envRes ) {
// detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
+ if( asDaemon ) {
+ envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL);
+ } else {
+ envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL);
+ }
+ if( JNI_OK != envRes ) {
+ fprintf(stderr, "JOGL GetJNIEnv: Can't attach thread: %d\n", envRes);
return NULL;
}
curEnv = newEnv;
} else if( JNI_OK != envRes ) {
// oops ..
- fprintf(stderr, "can't GetEnv: %d\n", envRes);
+ fprintf(stderr, "JOGL GetJNIEnv: Can't GetEnv: %d\n", envRes);
return NULL;
}
if (curEnv==NULL) {
- fprintf(stderr, "env is NULL\n");
+ fprintf(stderr, "JOGL GetJNIEnv: env is NULL\n");
return NULL;
}
*shallBeDetached = NULL != newEnv;
@@ -124,28 +118,9 @@ JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached)
void JoglCommon_ReleaseJNIEnv (int shallBeDetached) {
if(NULL == _jvmHandle) {
- fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st");
- }
-
- if(shallBeDetached) {
+ fprintf(stderr, "JOGL ReleaseJNIEnv: No JavaVM handle registered, call JoglCommon_init(..) 1st");
+ } else if(shallBeDetached) {
(*_jvmHandle)->DetachCurrentThread(_jvmHandle);
}
}
-/*
- * Class: jogamp_opengl_GLContextImpl
- * Method: glGetStringInt
- * Signature: (IJ)Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL
-Java_jogamp_opengl_GLContextImpl_glGetStringInt(JNIEnv *env, jclass _unused, jint name, jlong procAddress) {
- typedef const khronos_uint8_t * (KHRONOS_APIENTRY*_local_PFNGLGETSTRINGPROC)(unsigned int name);
- _local_PFNGLGETSTRINGPROC ptr_glGetString;
- const khronos_uint8_t * _res;
- ptr_glGetString = (_local_PFNGLGETSTRINGPROC) (intptr_t) procAddress;
- assert(ptr_glGetString != NULL);
- _res = (* ptr_glGetString) ((unsigned int) name);
- if (NULL == _res) return NULL;
- return (*env)->NewStringUTF(env, _res);
-}
-
diff --git a/src/jogl/native/JoglCommon.h b/src/jogl/native/JoglCommon.h
index 023b4be03..2aeaf7d1d 100644
--- a/src/jogl/native/JoglCommon.h
+++ b/src/jogl/native/JoglCommon.h
@@ -1,3 +1,30 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
#ifndef JOGL_COMMON_H
#define JOGL_COMMON_H 1
@@ -7,29 +34,25 @@
void JoglCommon_init(JNIEnv *env);
-/** Set by JoglCommon_init */
-JavaVM *JoglCommon_GetJVMHandle();
-
-/** Set by JoglCommon_init */
-int JoglCommon_GetJVMVersion();
-
jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str);
-/** env may be NULL, in which case JoglCommon_GetJNIEnv() is being used. */
void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...);
-
-/** env may be NULL, in which case JoglCommon_GetJNIEnv() is being used. */
void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
/**
*
- * 1) Store jvmHandle and jvmVersion is done by 'JoglCommon_init(JNIEnv*)'
- * and internally used by 'JoglCommon_GetJNIEnv(..)' and 'JoglCommon_ReleaseJNIEnv(..)'.
+ * 1) Init static jvmHandle, jvmVersion and clazz references
+ * from an early initialization call w/ valid 'JNIEnv * env'
+
+ JoglCommon_init(env);
+
*
* 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv
*
+
+ int asDaemon = 0;
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(&shallBeDetached);
+ JNIEnv* env = JoglCommon_GetJNIEnv(asDaemon, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("drawRect: null JNIEnv\n");
return;
@@ -41,11 +64,13 @@ void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
.. your JNIEnv code here ..
*
- * 4) Detach thread from JVM, if required
+ * 4) Detach thread from JVM if required, i.e. not attached as daemon!
+ * Not recommended for recurring _daemon_ threads (performance)
*
- JoglCommon_ReleaseJNIEnv (shallBeDetached);
+ JoglCommon_ReleaseJNIEnv(shallBeDetached);
*/
-JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached);
+JNIEnv* JoglCommon_GetJNIEnv (int asDaemon, int * shallBeDetached);
+
void JoglCommon_ReleaseJNIEnv (int shallBeDetached);
#endif
diff --git a/src/jogl/native/libav/ffmpeg_dshow.c b/src/jogl/native/libav/ffmpeg_dshow.c
new file mode 100644
index 000000000..4f1523a81
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_dshow.c
@@ -0,0 +1,215 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "ffmpeg_dshow.h"
+
+#ifdef _WIN32
+
+#include <stdio.h>
+#include <string.h>
+
+// dshow includes strsafe.h, hence tchar.h cannot be used
+// include strsafe.h here for documentation
+// #include <tchar.h>
+#include <strsafe.h>
+#include <dshow.h>
+
+static HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
+{
+ // Create the System Device Enumerator.
+ ICreateDevEnum *pDevEnum;
+ void *pv = NULL;
+
+ HRESULT hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, &IID_ICreateDevEnum, (void**)&pDevEnum);
+
+ if (SUCCEEDED(hr)) {
+ // Create an enumerator for the category.
+ hr = pDevEnum->lpVtbl->CreateClassEnumerator(pDevEnum, category, ppEnum,0);
+ if (hr == S_FALSE)
+ {
+ hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error.
+ }
+ pDevEnum->lpVtbl->Release(pDevEnum);
+ }
+ return hr;
+}
+
+static void getBSTRChars(BSTR bstr, char *pDest, int destLen) {
+
+ #ifdef UNICODE
+ // _sntprintf(pDest, destLen, _T("%s"), bstr);
+ StringCbPrintfW(pDest, destLen, L"%s", bstr);
+ #else
+ // _sntprintf(pDest, destLen, _T("%S"), bstr);
+ StringCchPrintfA(pDest, destLen, "%S", bstr);
+ #endif
+}
+
+
+static int GetDeviceInformation(IEnumMoniker *pEnum, int verbose, int devIdx,
+ char *pDescr, int descrSize,
+ char *pName, int nameSize,
+ char *pPath, int pathSize, int *pWaveID) {
+ IMoniker *pMoniker = NULL;
+ int i=0;
+ int res = devIdx >= 0 ? -1 : 0;
+
+ if( NULL != pDescr ) {
+ *pDescr=0;
+ }
+ if( NULL != pName ) {
+ *pName=0;
+ }
+ if( NULL != pPath ) {
+ *pPath=0;
+ }
+ if( NULL != pWaveID ) {
+ *pWaveID=0;
+ }
+
+ while (pEnum->lpVtbl->Next(pEnum, 1, &pMoniker, NULL) == S_OK) {
+ IPropertyBag *pPropBag;
+ HRESULT hr;
+
+ hr = pMoniker->lpVtbl->BindToStorage(pMoniker, 0, 0, &IID_IPropertyBag, (void**)&pPropBag);
+ if (FAILED(hr)) {
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: bind failed ...\n", i);
+ }
+ pMoniker->lpVtbl->Release(pMoniker);
+ continue;
+ }
+ VARIANT var;
+ VariantInit(&var);
+
+ // Get description or friendly name.
+ hr = pPropBag->lpVtbl->Read(pPropBag, L"Description", &var, 0);
+ if (SUCCEEDED(hr)) {
+ if( i == devIdx && NULL != pDescr ) {
+ res = 0;
+ getBSTRChars(var.bstrVal, pDescr, descrSize);
+ }
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: Descr %S\n", i, var.bstrVal);
+ }
+ VariantClear(&var);
+ } else if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: cannot read Descr..\n", i);
+ }
+
+ hr = pPropBag->lpVtbl->Read(pPropBag, L"FriendlyName", &var, 0);
+ if (SUCCEEDED(hr)) {
+ if( i == devIdx && NULL != pName ) {
+ res = 0;
+ getBSTRChars(var.bstrVal, pName, nameSize);
+ }
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: Name %S\n", i, var.bstrVal);
+ }
+ VariantClear(&var);
+ } else if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: cannot read Name..\n", i);
+ }
+
+ hr = pPropBag->lpVtbl->Write(pPropBag, L"FriendlyName", &var);
+
+ // WaveInID applies only to audio capture devices.
+ hr = pPropBag->lpVtbl->Read(pPropBag, L"WaveInID", &var, 0);
+ if (SUCCEEDED(hr)) {
+ if( i == devIdx && NULL != pWaveID ) {
+ res = 0;
+ *pWaveID=(int)var.lVal;
+ }
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: WaveInID %d\n", i, var.lVal);
+ }
+ VariantClear(&var);
+ }
+
+ hr = pPropBag->lpVtbl->Read(pPropBag, L"DevicePath", &var, 0);
+ if (SUCCEEDED(hr)) {
+ if( i == devIdx && NULL != pPath ) {
+ res = 0;
+ getBSTRChars(var.bstrVal, pPath, pathSize);
+ }
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: Path %S\n", i, var.bstrVal);
+ }
+ VariantClear(&var);
+ }
+
+ pPropBag->lpVtbl->Release(pPropBag);
+ pMoniker->lpVtbl->Release(pMoniker);
+
+ if( devIdx >= 0 && i == devIdx ) {
+ break; // done!
+ }
+ i++;
+ }
+ return res;
+}
+
+int findDShowVideoDevice(char * dest, int destSize, int devIdx, int verbose) {
+ int res = -1;
+
+ HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ if (SUCCEEDED(hr)) {
+ IEnumMoniker *pEnum;
+
+ hr = EnumerateDevices(&CLSID_VideoInputDeviceCategory, &pEnum);
+ if (SUCCEEDED(hr)) {
+ res = GetDeviceInformation(pEnum, verbose, devIdx, NULL /* pDescr */, 0, dest, destSize, NULL /* pPath */, 0, NULL /* pWaveID */);
+ pEnum->lpVtbl->Release(pEnum);
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Get VideoInputDevice: res %d, '%s'\n", res, dest);
+ }
+ } else if( verbose ) {
+ fprintf(stderr, "DShowParser: Get VideoInputDevice failed\n");
+ }
+ /**
+ hr = EnumerateDevices(&CLSID_AudioInputDeviceCategory, &pEnum);
+ if (SUCCEEDED(hr)) {
+ res = GetDeviceInformation(pEnum, verbose, devIdx, NULL, 0, NULL, 0, NULL, 0, NULL);
+ pEnum->lpVtbl->Release(pEnum);
+ } else if( verbose ) {
+ fprintf(stderr, "DShowParser: Get AudioInputDevice failed\n");
+ } */
+ CoUninitialize();
+ } else if( verbose ) {
+ fprintf(stderr, "DShowParser: CoInit failed\n");
+ }
+ return res;
+}
+
+#else
+
+int findDShowVideoDevice(char * dest, int destSize, int devIdx, int verbose) {
+ return -1;
+}
+
+#endif
diff --git a/src/jogl/native/libav/ffmpeg_dshow.h b/src/jogl/native/libav/ffmpeg_dshow.h
new file mode 100644
index 000000000..44524bf4b
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_dshow.h
@@ -0,0 +1,47 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#ifndef _FFMPEG_DSHOW_H
+#define _FFMPEG_DSHOW_H
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+#endif // _WIN32
+
+#include <gluegen_stdint.h>
+#include <gluegen_inttypes.h>
+#include <gluegen_stddef.h>
+#include <gluegen_stdint.h>
+
+extern int findDShowVideoDevice(char * dest, int destSize, int devIdx, int verbose);
+
+
+#endif // _FFMPEG_DSHOW_H
+
diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c
new file mode 100644
index 000000000..3077070db
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_impl_template.c
@@ -0,0 +1,1615 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+// #define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv08 ## METHOD
+
+#include "JoglCommon.h"
+#include "ffmpeg_tool.h"
+#include "ffmpeg_static.h"
+#include "ffmpeg_dshow.h"
+
+#include "libavutil/pixdesc.h"
+#include "libavutil/samplefmt.h"
+#if LIBAVUTIL_VERSION_MAJOR < 53
+ #include "libavutil/audioconvert.h"
+ // 52: #include "libavutil/channel_layout.h"
+#endif
+
+#include <GL/gl.h>
+
+#define HAS_FUNC(f) (NULL!=(f))
+
+typedef unsigned (APIENTRYP AVUTIL_VERSION)(void);
+typedef unsigned (APIENTRYP AVFORMAT_VERSION)(void);
+typedef unsigned (APIENTRYP AVCODEC_VERSION)(void);
+typedef unsigned (APIENTRYP AVRESAMPLE_VERSION)(void);
+typedef unsigned (APIENTRYP SWRESAMPLE_VERSION)(void);
+
+static AVUTIL_VERSION sp_avutil_version;
+static AVFORMAT_VERSION sp_avformat_version;
+static AVCODEC_VERSION sp_avcodec_version;
+static AVRESAMPLE_VERSION sp_avresample_version;
+static SWRESAMPLE_VERSION sp_swresample_version;
+// count: 5
+
+// libavcodec
+typedef int (APIENTRYP AVCODEC_REGISTER_ALL)(void);
+typedef int (APIENTRYP AVCODEC_CLOSE)(AVCodecContext *avctx);
+typedef void (APIENTRYP AVCODEC_STRING)(char *buf, int buf_size, AVCodecContext *enc, int encode);
+typedef AVCodec *(APIENTRYP AVCODEC_FIND_DECODER)(int avCodecID); // lavc 53: 'enum CodecID id', lavc 54: 'enum AVCodecID id'
+typedef int (APIENTRYP AVCODEC_OPEN2)(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options); // 53.6.0
+typedef AVFrame *(APIENTRYP AVCODEC_ALLOC_FRAME)(void);
+typedef void (APIENTRYP AVCODEC_GET_FRAME_DEFAULTS)(AVFrame *frame);
+typedef void (APIENTRYP AVCODEC_FREE_FRAME)(AVFrame **frame);
+typedef int (APIENTRYP AVCODEC_DEFAULT_GET_BUFFER)(AVCodecContext *s, AVFrame *pic); // <= 54 (opt), else AVCODEC_DEFAULT_GET_BUFFER2
+typedef void (APIENTRYP AVCODEC_DEFAULT_RELEASE_BUFFER)(AVCodecContext *s, AVFrame *pic); // <= 54 (opt), else AV_FRAME_UNREF
+typedef int (APIENTRYP AVCODEC_DEFAULT_GET_BUFFER2)(AVCodecContext *s, AVFrame *frame, int flags); // 55. (opt)
+typedef int (APIENTRYP AVCODEC_GET_EDGE_WIDTH)();
+typedef int (APIENTRYP AV_IMAGE_FILL_LINESIZES)(int linesizes[4], int pix_fmt, int width); // lavu 51: 'enum PixelFormat pix_fmt', lavu 53: 'enum AVPixelFormat pix_fmt'
+typedef void (APIENTRYP AVCODEC_ALIGN_DIMENSIONS)(AVCodecContext *s, int *width, int *height);
+typedef void (APIENTRYP AVCODEC_ALIGN_DIMENSIONS2)(AVCodecContext *s, int *width, int *height, int linesize_align[AV_NUM_DATA_POINTERS]);
+typedef void (APIENTRYP AVCODEC_FLUSH_BUFFERS)(AVCodecContext *avctx);
+typedef void (APIENTRYP AV_INIT_PACKET)(AVPacket *pkt);
+typedef int (APIENTRYP AV_NEW_PACKET)(AVPacket *pkt, int size);
+typedef void (APIENTRYP AV_DESTRUCT_PACKET)(AVPacket *pkt);
+typedef void (APIENTRYP AV_FREE_PACKET)(AVPacket *pkt);
+typedef int (APIENTRYP AVCODEC_DECODE_AUDIO4)(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt); // 53.25.0
+typedef int (APIENTRYP AVCODEC_DECODE_VIDEO2)(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt); // 52.23.0
+
+static AVCODEC_REGISTER_ALL sp_avcodec_register_all;
+static AVCODEC_CLOSE sp_avcodec_close;
+static AVCODEC_STRING sp_avcodec_string;
+static AVCODEC_FIND_DECODER sp_avcodec_find_decoder;
+static AVCODEC_OPEN2 sp_avcodec_open2; // 53.6.0
+static AVCODEC_ALLOC_FRAME sp_avcodec_alloc_frame;
+static AVCODEC_GET_FRAME_DEFAULTS sp_avcodec_get_frame_defaults;
+static AVCODEC_FREE_FRAME sp_avcodec_free_frame;
+static AVCODEC_DEFAULT_GET_BUFFER sp_avcodec_default_get_buffer; // <= 54 (opt), else sp_avcodec_default_get_buffer2
+static AVCODEC_DEFAULT_RELEASE_BUFFER sp_avcodec_default_release_buffer; // <= 54 (opt), else sp_av_frame_unref
+static AVCODEC_DEFAULT_GET_BUFFER2 sp_avcodec_default_get_buffer2; // 55. (opt)
+static AVCODEC_GET_EDGE_WIDTH sp_avcodec_get_edge_width;
+static AV_IMAGE_FILL_LINESIZES sp_av_image_fill_linesizes;
+static AVCODEC_ALIGN_DIMENSIONS sp_avcodec_align_dimensions;
+static AVCODEC_ALIGN_DIMENSIONS2 sp_avcodec_align_dimensions2;
+static AVCODEC_FLUSH_BUFFERS sp_avcodec_flush_buffers;
+static AV_INIT_PACKET sp_av_init_packet;
+static AV_NEW_PACKET sp_av_new_packet;
+static AV_DESTRUCT_PACKET sp_av_destruct_packet;
+static AV_FREE_PACKET sp_av_free_packet;
+static AVCODEC_DECODE_AUDIO4 sp_avcodec_decode_audio4; // 53.25.0
+static AVCODEC_DECODE_VIDEO2 sp_avcodec_decode_video2; // 52.23.0
+// count: 27
+
+// libavutil
+typedef void (APIENTRYP AV_FRAME_UNREF)(AVFrame *frame);
+typedef void* (APIENTRYP AV_REALLOC)(void *ptr, size_t size);
+typedef void (APIENTRYP AV_FREE)(void *ptr);
+typedef int (APIENTRYP AV_GET_BITS_PER_PIXEL)(const AVPixFmtDescriptor *pixdesc);
+typedef int (APIENTRYP AV_SAMPLES_GET_BUFFER_SIZE)(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align);
+typedef int (APIENTRYP AV_GET_BYTES_PER_SAMPLE)(enum AVSampleFormat sample_fmt);
+typedef int (APIENTRYP AV_OPT_SET_INT)(void *obj, const char *name, int64_t val, int search_flags);
+typedef AVDictionaryEntry* (APIENTRYP AV_DICT_GET)(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags);
+typedef int (APIENTRYP AV_DICT_COUNT)(AVDictionary *m);
+typedef int (APIENTRYP AV_DICT_SET)(AVDictionary **pm, const char *key, const char *value, int flags);
+typedef void (APIENTRYP AV_DICT_FREE)(AVDictionary **m);
+
+static const AVPixFmtDescriptor* sp_av_pix_fmt_descriptors;
+static AV_FRAME_UNREF sp_av_frame_unref;
+static AV_REALLOC sp_av_realloc;
+static AV_FREE sp_av_free;
+static AV_GET_BITS_PER_PIXEL sp_av_get_bits_per_pixel;
+static AV_SAMPLES_GET_BUFFER_SIZE sp_av_samples_get_buffer_size;
+static AV_GET_BYTES_PER_SAMPLE sp_av_get_bytes_per_sample;
+static AV_OPT_SET_INT sp_av_opt_set_int;
+static AV_DICT_GET sp_av_dict_get;
+static AV_DICT_COUNT sp_av_dict_count;
+static AV_DICT_SET sp_av_dict_set;
+static AV_DICT_FREE sp_av_dict_free;
+// count: 39
+
+// libavformat
+typedef AVFormatContext *(APIENTRYP AVFORMAT_ALLOC_CONTEXT)(void);
+typedef void (APIENTRYP AVFORMAT_FREE_CONTEXT)(AVFormatContext *s); // 52.96.0
+typedef void (APIENTRYP AVFORMAT_CLOSE_INPUT)(AVFormatContext **s); // 53.17.0
+typedef void (APIENTRYP AV_REGISTER_ALL)(void);
+typedef AVInputFormat *(APIENTRYP AV_FIND_INPUT_FORMAT)(const char *short_name);
+typedef int (APIENTRYP AVFORMAT_OPEN_INPUT)(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);
+typedef void (APIENTRYP AV_DUMP_FORMAT)(AVFormatContext *ic, int index, const char *url, int is_output);
+typedef int (APIENTRYP AV_READ_FRAME)(AVFormatContext *s, AVPacket *pkt);
+typedef int (APIENTRYP AV_SEEK_FRAME)(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);
+typedef int (APIENTRYP AVFORMAT_SEEK_FILE)(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
+typedef int (APIENTRYP AV_READ_PLAY)(AVFormatContext *s);
+typedef int (APIENTRYP AV_READ_PAUSE)(AVFormatContext *s);
+typedef int (APIENTRYP AVFORMAT_NETWORK_INIT)(void); // 53.13.0
+typedef int (APIENTRYP AVFORMAT_NETWORK_DEINIT)(void); // 53.13.0
+typedef int (APIENTRYP AVFORMAT_FIND_STREAM_INFO)(AVFormatContext *ic, AVDictionary **options); // 53.3.0
+
+static AVFORMAT_ALLOC_CONTEXT sp_avformat_alloc_context;
+static AVFORMAT_FREE_CONTEXT sp_avformat_free_context; // 52.96.0 (not used, only for outfile cts)
+static AVFORMAT_CLOSE_INPUT sp_avformat_close_input; // 53.17.0
+static AV_REGISTER_ALL sp_av_register_all;
+static AV_FIND_INPUT_FORMAT sp_av_find_input_format;
+static AVFORMAT_OPEN_INPUT sp_avformat_open_input;
+static AV_DUMP_FORMAT sp_av_dump_format;
+static AV_READ_FRAME sp_av_read_frame;
+static AV_SEEK_FRAME sp_av_seek_frame;
+static AVFORMAT_SEEK_FILE sp_avformat_seek_file;
+static AV_READ_PLAY sp_av_read_play;
+static AV_READ_PAUSE sp_av_read_pause;
+static AVFORMAT_NETWORK_INIT sp_avformat_network_init; // 53.13.0
+static AVFORMAT_NETWORK_DEINIT sp_avformat_network_deinit; // 53.13.0
+static AVFORMAT_FIND_STREAM_INFO sp_avformat_find_stream_info; // 53.3.0
+// count: 54
+
+// libavdevice [53.0.0]
+typedef int (APIENTRYP AVDEVICE_REGISTER_ALL)(void);
+static AVDEVICE_REGISTER_ALL sp_avdevice_register_all;
+// count: 55
+
+// libavresample [1.0.1]
+typedef AVAudioResampleContext* (APIENTRYP AVRESAMPLE_ALLOC_CONTEXT)(void); // 1.0.1
+typedef int (APIENTRYP AVRESAMPLE_OPEN)(AVAudioResampleContext *avr); // 1.0.1
+typedef void (APIENTRYP AVRESAMPLE_CLOSE)(AVAudioResampleContext *avr); // 1.0.1
+typedef void (APIENTRYP AVRESAMPLE_FREE)(AVAudioResampleContext **avr); // 1.0.1
+typedef int (APIENTRYP AVRESAMPLE_CONVERT)(AVAudioResampleContext *avr, uint8_t **output,
+ int out_plane_size, int out_samples, uint8_t **input,
+ int in_plane_size, int in_samples); // 1.0.1
+static AVRESAMPLE_ALLOC_CONTEXT sp_avresample_alloc_context;
+static AVRESAMPLE_OPEN sp_avresample_open;
+static AVRESAMPLE_CLOSE sp_avresample_close;
+static AVRESAMPLE_FREE sp_avresample_free;
+static AVRESAMPLE_CONVERT sp_avresample_convert;
+// count: 60
+
+// libswresample [1...]
+typedef int (APIENTRYP AV_OPT_SET_SAMPLE_FMT)(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); // actually lavu .. but exist only w/ swresample!
+typedef struct SwrContext *(APIENTRYP SWR_ALLOC)(void);
+typedef int (APIENTRYP SWR_INIT)(struct SwrContext *s);
+typedef void (APIENTRYP SWR_FREE)(struct SwrContext **s);
+typedef int (APIENTRYP SWR_CONVERT)(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in , int in_count);
+
+static AV_OPT_SET_SAMPLE_FMT sp_av_opt_set_sample_fmt;
+static SWR_ALLOC sp_swr_alloc;
+static SWR_INIT sp_swr_init;
+static SWR_FREE sp_swr_free;
+static SWR_CONVERT sp_swr_convert;
+// count: 65
+
+// We use JNI Monitor Locking, since this removes the need
+// to statically link-in pthreads on window ..
+// #define USE_PTHREAD_LOCKING 1
+//
+#define USE_JNI_LOCKING 1
+
+#if defined (USE_PTHREAD_LOCKING)
+ #include <pthread.h>
+ #warning USE LOCKING PTHREAD
+ static pthread_mutex_t mutex_avcodec_openclose;
+ #define MY_MUTEX_LOCK(e,s) pthread_mutex_lock(&(s))
+ #define MY_MUTEX_UNLOCK(e,s) pthread_mutex_unlock(&(s))
+#elif defined (USE_JNI_LOCKING)
+ static jobject mutex_avcodec_openclose;
+ #define MY_MUTEX_LOCK(e,s) (*e)->MonitorEnter(e, s)
+ #define MY_MUTEX_UNLOCK(e,s) (*e)->MonitorExit(e, s)
+#else
+ #warning USE LOCKING NONE
+ #define MY_MUTEX_LOCK(e,s)
+ #define MY_MUTEX_UNLOCK(e,s)
+#endif
+
+#define SYMBOL_COUNT 65
+
+JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0)
+ (JNIEnv *env, jobject instance, jobject jmutex_avcodec_openclose, jobject jSymbols, jint count)
+{
+ #ifdef USE_PTHREAD_LOCKING
+ pthread_mutexattr_t renderLockAttr;
+ #endif
+ int64_t* symbols; // jlong -> int64_t -> intptr_t -> FUNC_PTR
+ int i;
+
+ if(SYMBOL_COUNT != count) {
+ fprintf(stderr, "FFMPEGNatives.initSymbols0: Wrong symbol count: Expected %d, Is %d\n",
+ SYMBOL_COUNT, count);
+ return JNI_FALSE;
+ }
+ JoglCommon_init(env);
+
+ i = 0;
+ symbols = (int64_t *) (*env)->GetPrimitiveArrayCritical(env, jSymbols, NULL);
+
+ sp_avutil_version = (AVUTIL_VERSION) (intptr_t) symbols[i++];
+ sp_avformat_version = (AVFORMAT_VERSION) (intptr_t) symbols[i++];
+ sp_avcodec_version = (AVCODEC_VERSION) (intptr_t) symbols[i++];
+ sp_avresample_version = (AVRESAMPLE_VERSION) (intptr_t) symbols[i++];
+ sp_swresample_version = (SWRESAMPLE_VERSION) (intptr_t) symbols[i++];
+
+ sp_avcodec_register_all = (AVCODEC_REGISTER_ALL) (intptr_t) symbols[i++];
+ sp_avcodec_close = (AVCODEC_CLOSE) (intptr_t) symbols[i++];
+ sp_avcodec_string = (AVCODEC_STRING) (intptr_t) symbols[i++];
+ sp_avcodec_find_decoder = (AVCODEC_FIND_DECODER) (intptr_t) symbols[i++];
+ sp_avcodec_open2 = (AVCODEC_OPEN2) (intptr_t) symbols[i++];
+ sp_avcodec_alloc_frame = (AVCODEC_ALLOC_FRAME) (intptr_t) symbols[i++];
+ sp_avcodec_get_frame_defaults = (AVCODEC_GET_FRAME_DEFAULTS) (intptr_t) symbols[i++];
+ sp_avcodec_free_frame = (AVCODEC_FREE_FRAME) (intptr_t) symbols[i++];
+ sp_avcodec_default_get_buffer = (AVCODEC_DEFAULT_GET_BUFFER) (intptr_t) symbols[i++];
+ sp_avcodec_default_release_buffer = (AVCODEC_DEFAULT_RELEASE_BUFFER) (intptr_t) symbols[i++];
+ sp_avcodec_default_get_buffer2 = (AVCODEC_DEFAULT_GET_BUFFER2) (intptr_t) symbols[i++];
+ sp_avcodec_get_edge_width = (AVCODEC_GET_EDGE_WIDTH) (intptr_t) symbols[i++];
+ sp_av_image_fill_linesizes = (AV_IMAGE_FILL_LINESIZES) (intptr_t) symbols[i++];
+ sp_avcodec_align_dimensions = (AVCODEC_ALIGN_DIMENSIONS) (intptr_t) symbols[i++];
+ sp_avcodec_align_dimensions2 = (AVCODEC_ALIGN_DIMENSIONS2) (intptr_t) symbols[i++];
+ sp_avcodec_flush_buffers = (AVCODEC_FLUSH_BUFFERS) (intptr_t) symbols[i++];
+ sp_av_init_packet = (AV_INIT_PACKET) (intptr_t) symbols[i++];
+ sp_av_new_packet = (AV_NEW_PACKET) (intptr_t) symbols[i++];
+ sp_av_destruct_packet = (AV_DESTRUCT_PACKET) (intptr_t) symbols[i++];
+ sp_av_free_packet = (AV_FREE_PACKET) (intptr_t) symbols[i++];
+ sp_avcodec_decode_audio4 = (AVCODEC_DECODE_AUDIO4) (intptr_t) symbols[i++];
+ sp_avcodec_decode_video2 = (AVCODEC_DECODE_VIDEO2) (intptr_t) symbols[i++];
+
+ sp_av_pix_fmt_descriptors = (const AVPixFmtDescriptor*) (intptr_t) symbols[i++];
+ sp_av_frame_unref = (AV_FRAME_UNREF) (intptr_t) symbols[i++];
+ sp_av_realloc = (AV_REALLOC) (intptr_t) symbols[i++];
+ sp_av_free = (AV_FREE) (intptr_t) symbols[i++];
+ sp_av_get_bits_per_pixel = (AV_GET_BITS_PER_PIXEL) (intptr_t) symbols[i++];
+ sp_av_samples_get_buffer_size = (AV_SAMPLES_GET_BUFFER_SIZE) (intptr_t) symbols[i++];
+ sp_av_get_bytes_per_sample = (AV_GET_BYTES_PER_SAMPLE) (intptr_t) symbols[i++];
+ sp_av_opt_set_int = (AV_OPT_SET_INT) (intptr_t) symbols[i++];
+ sp_av_dict_get = (AV_DICT_GET) (intptr_t) symbols[i++];
+ sp_av_dict_count = (AV_DICT_COUNT) (intptr_t) symbols[i++];
+ sp_av_dict_set = (AV_DICT_SET) (intptr_t) symbols[i++];
+ sp_av_dict_free = (AV_DICT_FREE) (intptr_t) symbols[i++];
+
+ sp_avformat_alloc_context = (AVFORMAT_ALLOC_CONTEXT) (intptr_t) symbols[i++];;
+ sp_avformat_free_context = (AVFORMAT_FREE_CONTEXT) (intptr_t) symbols[i++];
+ sp_avformat_close_input = (AVFORMAT_CLOSE_INPUT) (intptr_t) symbols[i++];
+ sp_av_register_all = (AV_REGISTER_ALL) (intptr_t) symbols[i++];
+ sp_av_find_input_format = (AV_FIND_INPUT_FORMAT) (intptr_t) symbols[i++];
+ sp_avformat_open_input = (AVFORMAT_OPEN_INPUT) (intptr_t) symbols[i++];
+ sp_av_dump_format = (AV_DUMP_FORMAT) (intptr_t) symbols[i++];
+ sp_av_read_frame = (AV_READ_FRAME) (intptr_t) symbols[i++];
+ sp_av_seek_frame = (AV_SEEK_FRAME) (intptr_t) symbols[i++];
+ sp_avformat_seek_file = (AVFORMAT_SEEK_FILE) (intptr_t) symbols[i++];
+ sp_av_read_play = (AV_READ_PLAY) (intptr_t) symbols[i++];
+ sp_av_read_pause = (AV_READ_PAUSE) (intptr_t) symbols[i++];
+ sp_avformat_network_init = (AVFORMAT_NETWORK_INIT) (intptr_t) symbols[i++];
+ sp_avformat_network_deinit = (AVFORMAT_NETWORK_DEINIT) (intptr_t) symbols[i++];
+ sp_avformat_find_stream_info = (AVFORMAT_FIND_STREAM_INFO) (intptr_t) symbols[i++];
+
+ sp_avdevice_register_all = (AVDEVICE_REGISTER_ALL) (intptr_t) symbols[i++];
+
+ sp_avresample_alloc_context = (AVRESAMPLE_ALLOC_CONTEXT) (intptr_t) symbols[i++];
+ sp_avresample_open = (AVRESAMPLE_OPEN) (intptr_t) symbols[i++];
+ sp_avresample_close = (AVRESAMPLE_CLOSE) (intptr_t) symbols[i++];
+ sp_avresample_free = (AVRESAMPLE_FREE) (intptr_t) symbols[i++];
+ sp_avresample_convert = (AVRESAMPLE_CONVERT) (intptr_t) symbols[i++];
+
+ sp_av_opt_set_sample_fmt = (AV_OPT_SET_SAMPLE_FMT) (intptr_t) symbols[i++];
+ sp_swr_alloc = (SWR_ALLOC) (intptr_t) symbols[i++];
+ sp_swr_init = (SWR_INIT) (intptr_t) symbols[i++];
+ sp_swr_free = (SWR_FREE) (intptr_t) symbols[i++];
+ sp_swr_convert = (SWR_CONVERT) (intptr_t) symbols[i++];
+
+ (*env)->ReleasePrimitiveArrayCritical(env, jSymbols, symbols, 0);
+
+ if(SYMBOL_COUNT != i) {
+ // boom
+ fprintf(stderr, "FFMPEGNatives.initSymbols0: Wrong symbol assignment count: Expected %d, Is %d\n",
+ SYMBOL_COUNT, i);
+ return JNI_FALSE;
+ }
+
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ if(!HAS_FUNC(sp_avcodec_default_get_buffer2) ||
+ !HAS_FUNC(sp_av_frame_unref) ) {
+ fprintf(stderr, "avcodec >= 55: avcodec_default_get_buffer2 %p, av_frame_unref %p\n",
+ sp_avcodec_default_get_buffer2, sp_av_frame_unref);
+ return JNI_FALSE;
+ }
+ #else
+ if(!HAS_FUNC(sp_avcodec_default_get_buffer) ||
+ !HAS_FUNC(sp_avcodec_default_release_buffer)) {
+ fprintf(stderr, "avcodec < 55: avcodec_default_get_buffer %p, sp_avcodec_default_release_buffer %p\n",
+ sp_avcodec_default_get_buffer2, sp_avcodec_default_release_buffer);
+ return JNI_FALSE;
+ }
+ #endif
+
+ #if defined (USE_PTHREAD_LOCKING)
+ pthread_mutexattr_init(&renderLockAttr);
+ pthread_mutexattr_settype(&renderLockAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&mutex_avcodec_openclose, &renderLockAttr); // recursive
+ #elif defined (USE_JNI_LOCKING)
+ mutex_avcodec_openclose = (*env)->NewGlobalRef(env, jmutex_avcodec_openclose);
+ #endif
+
+ /** At static destroy: Never
+ #if defined (USE_PTHREAD_LOCKING)
+ pthread_mutex_unlock(&mutex_avcodec_openclose);
+ pthread_mutex_destroy(&mutex_avcodec_openclose);
+ #elif defined (USE_JNI_LOCKING)
+ (*env)->DeleteGlobalRef(env, mutex_avcodec_openclose);
+ #endif
+ */
+
+ return JNI_TRUE;
+}
+
+static int _isAudioFormatSupported(JNIEnv *env, jobject ffmpegMediaPlayer, enum AVSampleFormat aSampleFmt, int32_t aSampleRate, int32_t aChannels) {
+ return JNI_TRUE == (*env)->CallBooleanMethod(env, ffmpegMediaPlayer, ffmpeg_jni_mid_isAudioFormatSupported, aSampleFmt, aSampleRate, aChannels);
+}
+static void _updateJavaAttributes(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
+ if(NULL!=env) {
+ (*env)->CallVoidMethod(env, pAV->ffmpegMediaPlayer, ffmpeg_jni_mid_setupFFAttributes,
+ pAV->vid, pAV->vPixFmt, pAV->vBufferPlanes,
+ pAV->vBitsPerPixel, pAV->vBytesPerPixelPerPlane,
+ pAV->vTexWidth[0], pAV->vTexWidth[1], pAV->vTexWidth[2],
+ pAV->vWidth, pAV->vHeight,
+ pAV->aid, pAV->aSampleFmtOut, pAV->aSampleRateOut, pAV->aChannelsOut, pAV->aFrameSize);
+ (*env)->CallVoidMethod(env, pAV->ffmpegMediaPlayer, ffmpeg_jni_mid_updateAttributes,
+ pAV->vid, pAV->aid,
+ pAV->vWidth, pAV->vHeight,
+ pAV->bps_stream, pAV->bps_video, pAV->bps_audio,
+ pAV->fps, pAV->frames_video, pAV->frames_audio, pAV->duration,
+ (*env)->NewStringUTF(env, pAV->vcodec),
+ (*env)->NewStringUTF(env, pAV->acodec) );
+ }
+}
+static void _setIsGLOriented(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
+ if(NULL!=env) {
+ (*env)->CallVoidMethod(env, pAV->ffmpegMediaPlayer, ffmpeg_jni_mid_setIsGLOriented, pAV->vFlipped);
+ }
+}
+
+static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
+ int i;
+ if(NULL != pAV) {
+ // Close the A resampler
+ if( NULL != pAV->avResampleCtx ) {
+ sp_avresample_free(&pAV->avResampleCtx);
+ pAV->avResampleCtx = NULL;
+ }
+ if( NULL != pAV->swResampleCtx ) {
+ sp_swr_free(&pAV->swResampleCtx);
+ pAV->swResampleCtx = NULL;
+ }
+ if( NULL != pAV->aResampleBuffer ) {
+ sp_av_free(pAV->aResampleBuffer);
+ pAV->aResampleBuffer = NULL;
+ }
+
+ MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+ {
+ // Close the V codec
+ if(NULL != pAV->pVCodecCtx) {
+ sp_avcodec_close(pAV->pVCodecCtx);
+ pAV->pVCodecCtx = NULL;
+ }
+ pAV->pVCodec=NULL;
+
+ // Close the A codec
+ if(NULL != pAV->pACodecCtx) {
+ sp_avcodec_close(pAV->pACodecCtx);
+ pAV->pACodecCtx = NULL;
+ }
+ pAV->pACodec=NULL;
+ }
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
+
+ // Close the frames
+ if(NULL != pAV->pVFrame) {
+ if(HAS_FUNC(sp_avcodec_free_frame)) {
+ sp_avcodec_free_frame(&pAV->pVFrame);
+ } else {
+ sp_av_free(pAV->pVFrame);
+ }
+ pAV->pVFrame = NULL;
+ }
+ if(NULL != pAV->pANIOBuffers) {
+ for(i=0; i<pAV->aFrameCount; i++) {
+ NIOBuffer_t * pNIOBuffer = &pAV->pANIOBuffers[i];
+ if( NULL != pNIOBuffer->nioRef ) {
+ if(pAV->verbose) {
+ fprintf(stderr, "A NIO: Free.X ptr %p / ref %p, %d bytes\n",
+ pNIOBuffer->origPtr, pNIOBuffer->nioRef, pNIOBuffer->size);
+ }
+ (*env)->DeleteGlobalRef(env, pNIOBuffer->nioRef);
+ }
+ }
+ free(pAV->pANIOBuffers);
+ pAV->pANIOBuffers = NULL;
+ }
+ if(NULL != pAV->pAFrames) {
+ for(i=0; i<pAV->aFrameCount; i++) {
+ if(HAS_FUNC(sp_avcodec_free_frame)) {
+ sp_avcodec_free_frame(&pAV->pAFrames[i]);
+ } else {
+ sp_av_free(pAV->pAFrames[i]);
+ }
+ }
+ free(pAV->pAFrames);
+ pAV->pAFrames = NULL;
+ }
+
+ // Close the video file
+ if(NULL != pAV->pFormatCtx) {
+ sp_avformat_close_input(&pAV->pFormatCtx);
+ // Only for output files!
+ // sp_avformat_free_context(pAV->pFormatCtx);
+ pAV->pFormatCtx = NULL;
+ }
+ if( NULL != pAV->ffmpegMediaPlayer ) {
+ (*env)->DeleteGlobalRef(env, pAV->ffmpegMediaPlayer);
+ pAV->ffmpegMediaPlayer = NULL;
+ }
+
+ free(pAV);
+ }
+}
+
+static int my_getPlaneCount(AVPixFmtDescriptor *pDesc) {
+ int i, p=-1;
+ for(i=pDesc->nb_components-1; i>=0; i--) {
+ int p0 = pDesc->comp[i].plane;
+ if( p < p0 ) {
+ p = p0;
+ }
+ }
+ return p+1;
+}
+
+#if 0
+static int my_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt) {
+ return sp_av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL;
+}
+
+static enum PixelFormat my_get_format(struct AVCodecContext *s, const enum PixelFormat * fmt) {
+ int i=0;
+ enum PixelFormat f0, fR = PIX_FMT_NONE;
+ char buf[256];
+
+ fprintf(stderr, "get_format ****\n");
+ while (fmt[i] != PIX_FMT_NONE /* && ff_is_hwaccel_pix_fmt(fmt[i]) */) {
+ f0 = fmt[i];
+ if(fR==PIX_FMT_NONE && !my_is_hwaccel_pix_fmt(f0)) {
+ fR = f0;
+ }
+ sp_av_get_pix_fmt_string(buf, sizeof(buf), f0);
+ fprintf(stderr, "get_format %d: %d - %s - %s\n", i, f0, sp_av_get_pix_fmt_name(f0), buf);
+ ++i;
+ }
+ fprintf(stderr, "get_format %d - %s *** \n", fR, sp_av_get_pix_fmt_name(fR));
+ fflush(NULL);
+ return fR;
+}
+#endif
+
+JNIEXPORT jint JNICALL FF_FUNC(getAvUtilMajorVersionCC0)
+ (JNIEnv *env, jobject instance) {
+ return (jint) LIBAVUTIL_VERSION_MAJOR;
+}
+
+JNIEXPORT jint JNICALL FF_FUNC(getAvFormatMajorVersionCC0)
+ (JNIEnv *env, jobject instance) {
+ return (jint) LIBAVFORMAT_VERSION_MAJOR;
+}
+
+JNIEXPORT jint JNICALL FF_FUNC(getAvCodecMajorVersionCC0)
+ (JNIEnv *env, jobject instance) {
+ return (jint) LIBAVCODEC_VERSION_MAJOR;
+}
+
+JNIEXPORT jint JNICALL FF_FUNC(getAvResampleMajorVersionCC0)
+ (JNIEnv *env, jobject instance) {
+ return (jint) LIBAVRESAMPLE_VERSION_MAJOR;
+}
+
+JNIEXPORT jint JNICALL FF_FUNC(getSwResampleMajorVersionCC0)
+ (JNIEnv *env, jobject instance) {
+ return (jint) LIBSWRESAMPLE_VERSION_MAJOR;
+}
+
+JNIEXPORT jlong JNICALL FF_FUNC(createInstance0)
+ (JNIEnv *env, jobject instance, jobject ffmpegMediaPlayer, jboolean verbose)
+{
+ FFMPEGToolBasicAV_t * pAV = calloc(1, sizeof(FFMPEGToolBasicAV_t));
+ if(NULL==pAV) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't alloc instance");
+ return 0;
+ }
+ pAV->avcodecVersion = sp_avcodec_version();
+ pAV->avformatVersion = sp_avformat_version();
+ pAV->avutilVersion = sp_avutil_version();
+ if(HAS_FUNC(sp_avresample_version)) {
+ pAV->avresampleVersion = sp_avresample_version();
+ } else {
+ pAV->avresampleVersion = 0;
+ }
+ if(HAS_FUNC(sp_swresample_version)) {
+ pAV->swresampleVersion = sp_swresample_version();
+ } else {
+ pAV->swresampleVersion = 0;
+ }
+
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ // TODO: We keep code on using 1 a/v frame per decoding cycle now.
+ // This is compatible w/ OpenAL's alBufferData(..)
+ // and w/ OpenGL's texture update command, both copy data immediatly.
+ // pAV->useRefCountedFrames = AV_HAS_API_REFCOUNTED_FRAMES(pAV);
+ pAV->useRefCountedFrames = 0;
+ #else
+ pAV->useRefCountedFrames = 0;
+ #endif
+
+ pAV->ffmpegMediaPlayer = (*env)->NewGlobalRef(env, ffmpegMediaPlayer);
+ pAV->verbose = verbose;
+ pAV->vid=AV_STREAM_ID_AUTO;
+ pAV->aid=AV_STREAM_ID_AUTO;
+
+ if(pAV->verbose) {
+ fprintf(stderr, "Info: Has avresample %d, swresample %d, device %d, refCount %d\n",
+ AV_HAS_API_AVRESAMPLE(pAV), AV_HAS_API_SWRESAMPLE(pAV), HAS_FUNC(sp_avdevice_register_all), pAV->useRefCountedFrames);
+ }
+ return (jlong) (intptr_t) pAV;
+}
+
+JNIEXPORT void JNICALL FF_FUNC(destroyInstance0)
+ (JNIEnv *env, jobject instance, jlong ptr)
+{
+ FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
+ if (pAV != NULL) {
+ // stop assumed ..
+ freeInstance(env, pAV);
+ }
+}
+
+static uint64_t getDefaultAudioChannelLayout(int channelCount) {
+ switch(channelCount) {
+ case 1: return AV_CH_LAYOUT_MONO;
+ case 2: return AV_CH_LAYOUT_STEREO;
+ case 3: return AV_CH_LAYOUT_SURROUND;
+ case 4: return AV_CH_LAYOUT_QUAD;
+ case 5: return AV_CH_LAYOUT_5POINT0;
+ case 6: return AV_CH_LAYOUT_5POINT1;
+ case 7: return AV_CH_LAYOUT_6POINT1;
+ case 8: return AV_CH_LAYOUT_7POINT1;
+ default: return AV_CH_LAYOUT_NATIVE;
+ }
+}
+
+static void initPTSStats(PTSStats *ptsStats);
+static int64_t evalPTS(PTSStats *ptsStats, int64_t inPTS, int64_t inDTS);
+
+static AVInputFormat* tryAVInputFormat(const char * name, int verbose) {
+ AVInputFormat* inFmt = sp_av_find_input_format(name);
+ if( verbose) {
+ if ( NULL == inFmt ) {
+ fprintf(stderr, "Warning: Could not find input format '%s'\n", name);
+ } else {
+ fprintf(stderr, "Info: Found input format '%s'\n", name);
+ }
+ }
+ return inFmt;
+}
+static const char * inFmtNames[] = {
+ "video4linux2", // linux
+ "video4linux", // linux (old)
+ "dshow", // windows
+ "vfwcap", // windows (old)
+ "mpg",
+ "yuv2",
+ "mjpeg",
+ "avi",
+ "wmv",
+ "libx264",
+ "h264",
+ "mpegts"
+};
+static AVInputFormat* findAVInputFormat(int verbose) {
+ AVInputFormat* inFmt = NULL;
+ const char *inFmtName;
+ int i=0;
+ do {
+ inFmtName = inFmtNames[i++];
+ if( NULL == inFmtName ) {
+ break;
+ }
+ inFmt = tryAVInputFormat(inFmtName, verbose);
+ } while ( NULL == inFmt );
+ return inFmt;
+}
+
+#if 0
+static void getAlignedLinesizes(AVCodecContext *avctx, int linesize[/*4*/]) {
+ int stride_align[AV_NUM_DATA_POINTERS];
+ int w = avctx->width;
+ int h = avctx->height;
+ int unaligned;
+ int i;
+
+ sp_avcodec_align_dimensions2(avctx, &w, &h, stride_align);
+
+ if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) {
+ int edge_width = sp_avcodec_get_edge_width();
+ w += edge_width * 2;
+ h += edge_width * 2;
+ }
+
+ do {
+ // Get alignment for all planes (-> YUVP .. etc)
+ sp_av_image_fill_linesizes(linesize, avctx->pix_fmt, w);
+ // increase alignment of w for next try (rhs gives the lowest bit set in w)
+ w += w & ~(w - 1);
+
+ unaligned = 0;
+ for (i = 0; i < 4; i++)
+ unaligned |= linesize[i] % stride_align[i];
+ } while (unaligned);
+}
+#endif
+
+JNIEXPORT void JNICALL FF_FUNC(setStream0)
+ (JNIEnv *env, jobject instance, jlong ptr, jstring jURL, jboolean jIsCameraInput,
+ jint vid, jstring jSizeS, jint vWidth, jint vHeight, jint vRate,
+ jint aid, jint aMaxChannelCount, jint aPrefSampleRate)
+{
+ char cameraName[256];
+ int res, i;
+ jboolean iscopy;
+ FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)(intptr_t)ptr;
+
+ if (pAV == NULL) {
+ JoglCommon_throwNewRuntimeException(env, "NULL AV ptr");
+ return;
+ }
+
+ // Register all formats and codecs
+ sp_avcodec_register_all();
+ if( jIsCameraInput && HAS_FUNC(sp_avdevice_register_all) ) {
+ sp_avdevice_register_all();
+ }
+ sp_av_register_all();
+ // Network too ..
+ if(HAS_FUNC(sp_avformat_network_init)) {
+ sp_avformat_network_init();
+ }
+
+ pAV->pFormatCtx = sp_avformat_alloc_context();
+
+ const char *urlPath = (*env)->GetStringUTFChars(env, jURL, &iscopy);
+ const char *filename = urlPath; // allow changing path for camera ..
+
+ // Open video file
+ AVDictionary *inOpts = NULL;
+ AVInputFormat* inFmt = NULL;
+ if( jIsCameraInput ) {
+ char buffer[256];
+ inFmt = findAVInputFormat(pAV->verbose);
+ if( NULL == inFmt ) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't find input format for camera: %s", urlPath);
+ (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
+ return;
+ }
+ if(pAV->verbose) {
+ fprintf(stderr, "Camera: Format: %s (%s)\n", inFmt->long_name, inFmt->name);
+ }
+ if( 0 == strncmp(inFmt->name, "dshow", 255) ) {
+ int devIdx = atoi(urlPath);
+ strncpy(cameraName, "video=", sizeof(cameraName));
+ res = findDShowVideoDevice(cameraName+6, sizeof(cameraName)-6, devIdx, pAV->verbose);
+ if( 0 == res ) {
+ if(pAV->verbose) {
+ fprintf(stderr, "Camera %d found: %s\n", devIdx, cameraName);
+ }
+ filename = cameraName;
+ } else if(pAV->verbose) {
+ fprintf(stderr, "Camera %d not found\n", devIdx);
+ }
+ }
+
+ const char *sizeS = NULL != jSizeS ? (*env)->GetStringUTFChars(env, jSizeS, &iscopy) : NULL;
+ int hasSize = 0;
+ if( NULL != sizeS ) {
+ snprintf(buffer, sizeof(buffer), "%s", sizeS);
+ (*env)->ReleaseStringChars(env, jSizeS, (const jchar *)sizeS);
+ hasSize = 1;
+ } else if( vWidth > 0 && vHeight > 0 ) {
+ snprintf(buffer, sizeof(buffer), "%dx%d", vWidth, vHeight);
+ hasSize = 1;
+ }
+ if( hasSize ) {
+ if(pAV->verbose) {
+ fprintf(stderr, "Camera: Size: %s\n", buffer);
+ }
+ sp_av_dict_set(&inOpts, "video_size", buffer, 0);
+ }
+ if( vRate > 0 ) {
+ snprintf(buffer, sizeof(buffer), "%d", vRate);
+ if(pAV->verbose) {
+ fprintf(stderr, "Camera: FPS: %s\n", buffer);
+ }
+ sp_av_dict_set(&inOpts, "framerate", buffer, 0);
+ }
+ }
+
+ MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+ {
+ res = sp_avformat_open_input(&pAV->pFormatCtx, filename, inFmt, NULL != inOpts ? &inOpts : NULL);
+ if( NULL != inOpts ) {
+ sp_av_dict_free(&inOpts);
+ }
+ if(res != 0) {
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
+ JoglCommon_throwNewRuntimeException(env, "Couldn't open URI: %s [%dx%d @ %d hz], err %d", filename, vWidth, vHeight, vRate, res);
+ (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
+ return;
+ }
+
+ // Retrieve detailed stream information
+ if(sp_avformat_find_stream_info(pAV->pFormatCtx, NULL)<0) {
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
+ (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
+ JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information");
+ return;
+ }
+ }
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
+
+ if(pAV->verbose) {
+ // Dump information about file onto standard error
+ sp_av_dump_format(pAV->pFormatCtx, 0, filename, JNI_FALSE);
+ }
+ (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
+
+ // FIXME: Libav Binary compatibility! JAU01
+ if (pAV->pFormatCtx->duration != AV_NOPTS_VALUE) {
+ pAV->duration = pAV->pFormatCtx->duration / AV_TIME_BASE_MSEC;
+ }
+ if (pAV->pFormatCtx->start_time != AV_NOPTS_VALUE) {
+ pAV->start_time = pAV->pFormatCtx->start_time / AV_TIME_BASE_MSEC;
+ }
+ if (pAV->pFormatCtx->bit_rate) {
+ pAV->bps_stream = pAV->pFormatCtx->bit_rate;
+ }
+
+ if(pAV->verbose) {
+ fprintf(stderr, "Streams: %d, req vid %d aid %d\n", pAV->pFormatCtx->nb_streams, vid, aid);
+ }
+
+ // Find the first audio and video stream, or the one matching vid
+ // FIXME: Libav Binary compatibility! JAU01
+ for(i=0; ( AV_STREAM_ID_AUTO==pAV->aid || AV_STREAM_ID_AUTO==pAV->vid ) && i<pAV->pFormatCtx->nb_streams; i++) {
+ AVStream *st = pAV->pFormatCtx->streams[i];
+ if(pAV->verbose) {
+ fprintf(stderr, "Stream: %d: is-video %d, is-audio %d\n", i, (AVMEDIA_TYPE_VIDEO == st->codec->codec_type), AVMEDIA_TYPE_AUDIO == st->codec->codec_type);
+ }
+ if(AVMEDIA_TYPE_VIDEO == st->codec->codec_type) {
+ if(AV_STREAM_ID_AUTO==pAV->vid && (AV_STREAM_ID_AUTO==vid || vid == i) ) {
+ pAV->pVStream = st;
+ pAV->vid=i;
+ }
+ } else if(AVMEDIA_TYPE_AUDIO == st->codec->codec_type) {
+ if(AV_STREAM_ID_AUTO==pAV->aid && (AV_STREAM_ID_AUTO==aid || aid == i) ) {
+ pAV->pAStream = st;
+ pAV->aid=i;
+ }
+ }
+ }
+ if( AV_STREAM_ID_AUTO == pAV->aid ) {
+ pAV->aid = AV_STREAM_ID_NONE;
+ }
+ if( AV_STREAM_ID_AUTO == pAV->vid ) {
+ pAV->vid = AV_STREAM_ID_NONE;
+ }
+
+ if( pAV->verbose ) {
+ fprintf(stderr, "Found vid %d, aid %d\n", pAV->vid, pAV->aid);
+ }
+
+ if(0<=pAV->aid) {
+ AVFrame * pAFrame0 = sp_avcodec_alloc_frame();
+ if( NULL == pAFrame0 ) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't alloc 1st audio frame\n");
+ return;
+ }
+
+ // Get a pointer to the codec context for the audio stream
+ // FIXME: Libav Binary compatibility! JAU01
+ pAV->pACodecCtx=pAV->pAStream->codec;
+
+ // FIXME: Libav Binary compatibility! JAU01
+ if (pAV->pACodecCtx->bit_rate) {
+ pAV->bps_audio = pAV->pACodecCtx->bit_rate;
+ }
+
+ // Customize ..
+ // pAV->pACodecCtx->thread_count=2;
+ // pAV->pACodecCtx->thread_type=FF_THREAD_FRAME|FF_THREAD_SLICE; // Decode more than one frame at once
+ pAV->pACodecCtx->thread_count=0;
+ pAV->pACodecCtx->thread_type=0;
+ pAV->pACodecCtx->workaround_bugs=FF_BUG_AUTODETECT;
+ pAV->pACodecCtx->skip_frame=AVDISCARD_DEFAULT;
+
+ // Note: OpenAL well supports n-channel by now (SOFT),
+ // however - AFAIK AV_SAMPLE_FMT_S16 would allow no conversion!
+ pAV->pACodecCtx->request_sample_fmt=AV_SAMPLE_FMT_S16;
+ if( 1 <= aMaxChannelCount && aMaxChannelCount <= 2 ) {
+ pAV->pACodecCtx->request_channel_layout=getDefaultAudioChannelLayout(aMaxChannelCount);
+ #if LIBAVCODEC_VERSION_MAJOR < 54
+ /** Until 55.0.0, but stopped working w/ 54 already :( */
+ pAV->pACodecCtx->request_channels=aMaxChannelCount;
+ #endif
+ }
+ pAV->pACodecCtx->skip_frame=AVDISCARD_DEFAULT;
+
+ sp_avcodec_string(pAV->acodec, sizeof(pAV->acodec), pAV->pACodecCtx, 0);
+
+ // Find the decoder for the audio stream
+ pAV->pACodec=sp_avcodec_find_decoder(pAV->pACodecCtx->codec_id);
+ if(pAV->pACodec==NULL) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't find audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec);
+ return;
+ }
+
+ // Open codec
+ MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+ {
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ pAV->pACodecCtx->refcounted_frames = pAV->useRefCountedFrames;
+ #endif
+ res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL);
+ }
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
+ if(res<0) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't open audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec);
+ return;
+ }
+ if (!pAV->pACodecCtx->channel_layout) {
+ pAV->pACodecCtx->channel_layout = getDefaultAudioChannelLayout(pAV->pACodecCtx->channels);
+ }
+ if (!pAV->pACodecCtx->channel_layout) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't determine channel layout of %d channels\n", pAV->pACodecCtx->channels);
+ return;
+ }
+ pAV->aSampleRate = pAV->pACodecCtx->sample_rate;
+ pAV->aChannels = pAV->pACodecCtx->channels;
+ pAV->aFrameSize = pAV->pACodecCtx->frame_size; // in samples per channel!
+ pAV->aSampleFmt = pAV->pACodecCtx->sample_fmt;
+ pAV->frames_audio = pAV->pAStream->nb_frames;
+ pAV->aSinkSupport = _isAudioFormatSupported(env, pAV->ffmpegMediaPlayer, pAV->aSampleFmt, pAV->aSampleRate, pAV->aChannels);
+ if( pAV->verbose ) {
+ fprintf(stderr, "A channels %d [l %"PRId64"], sample_rate %d, frame_size %d, frame_number %d, [afps %f, cfps %f, sfps %f], nb_frames %"PRId64", [maxChan %d, prefRate %d, req_chan_layout %"PRId64", req_chan %d], sink-support %d \n",
+ pAV->aChannels, pAV->pACodecCtx->channel_layout, pAV->aSampleRate, pAV->aFrameSize, pAV->pACodecCtx->frame_number,
+ my_av_q2f(pAV->pAStream->avg_frame_rate),
+ my_av_q2f_r(pAV->pAStream->codec->time_base),
+ my_av_q2f_r(pAV->pAStream->time_base),
+ pAV->pAStream->nb_frames,
+ aMaxChannelCount, aPrefSampleRate, pAV->pACodecCtx->request_channel_layout,
+ #if LIBAVCODEC_VERSION_MAJOR < 54
+ pAV->pACodecCtx->request_channels,
+ #else
+ 0,
+ #endif
+ pAV->aSinkSupport);
+ }
+
+ // default
+ pAV->aSampleFmtOut = pAV->aSampleFmt;
+ pAV->aChannelsOut = pAV->aChannels;
+ pAV->aSampleRateOut = pAV->aSampleRate;
+
+ if( ( AV_HAS_API_AVRESAMPLE(pAV) || AV_HAS_API_SWRESAMPLE(pAV) ) &&
+ ( pAV->aSampleFmt != AV_SAMPLE_FMT_S16 ||
+ ( 0 != aPrefSampleRate && pAV->aSampleRate != aPrefSampleRate ) ||
+ !pAV->aSinkSupport ) ) {
+
+ if( 0 == aPrefSampleRate ) {
+ aPrefSampleRate = pAV->aSampleRate;
+ }
+ int32_t aSinkSupport = 0;
+ enum AVSampleFormat aSampleFmtOut = AV_SAMPLE_FMT_S16;
+ int32_t aChannelsOut;
+ int32_t aSampleRateOut;
+ int32_t minChannelCount = MIN_INT(aMaxChannelCount,pAV->pACodecCtx->channels);
+
+ if( _isAudioFormatSupported(env, pAV->ffmpegMediaPlayer, aSampleFmtOut, aPrefSampleRate, pAV->pACodecCtx->channels) ) {
+ aChannelsOut = pAV->pACodecCtx->channels;
+ aSampleRateOut = aPrefSampleRate;
+ aSinkSupport = 1;
+ } else if( _isAudioFormatSupported(env, pAV->ffmpegMediaPlayer, aSampleFmtOut, aPrefSampleRate, minChannelCount) ) {
+ aChannelsOut = minChannelCount;
+ aSampleRateOut = aPrefSampleRate;
+ aSinkSupport = 1;
+ }
+
+ if( aSinkSupport ) {
+ if( AV_HAS_API_AVRESAMPLE(pAV) ) {
+ pAV->avResampleCtx = sp_avresample_alloc_context();
+ sp_av_opt_set_int(pAV->avResampleCtx, "in_channel_layout", pAV->pACodecCtx->channel_layout, 0);
+ sp_av_opt_set_int(pAV->avResampleCtx, "out_channel_layout", getDefaultAudioChannelLayout(aChannelsOut), 0);
+ sp_av_opt_set_int(pAV->avResampleCtx, "in_sample_rate", pAV->aSampleRate, 0);
+ sp_av_opt_set_int(pAV->avResampleCtx, "out_sample_rate", aSampleRateOut, 0);
+ sp_av_opt_set_int(pAV->avResampleCtx, "in_sample_fmt", pAV->aSampleFmt, 0);
+ sp_av_opt_set_int(pAV->avResampleCtx, "out_sample_fmt", aSampleFmtOut, 0);
+
+ if ( sp_avresample_open(pAV->avResampleCtx) < 0 ) {
+ sp_avresample_free(&pAV->avResampleCtx);
+ pAV->avResampleCtx = NULL;
+ fprintf(stderr, "error initializing avresample ctx\n");
+ } else {
+ // OK
+ pAV->aSampleFmtOut = aSampleFmtOut;
+ pAV->aChannelsOut = aChannelsOut;
+ pAV->aSampleRateOut = aSampleRateOut;
+ pAV->aSinkSupport = 1;
+ }
+ } else if( AV_HAS_API_SWRESAMPLE(pAV) ) {
+ pAV->swResampleCtx = sp_swr_alloc();
+ sp_av_opt_set_int(pAV->swResampleCtx, "in_channel_layout", pAV->pACodecCtx->channel_layout, 0);
+ sp_av_opt_set_int(pAV->swResampleCtx, "out_channel_layout", getDefaultAudioChannelLayout(aChannelsOut), 0);
+ sp_av_opt_set_int(pAV->swResampleCtx, "in_sample_rate", pAV->aSampleRate, 0);
+ sp_av_opt_set_int(pAV->swResampleCtx, "out_sample_rate", aSampleRateOut, 0);
+ sp_av_opt_set_sample_fmt(pAV->swResampleCtx, "in_sample_fmt", pAV->aSampleFmt, 0);
+ sp_av_opt_set_sample_fmt(pAV->swResampleCtx, "out_sample_fmt", aSampleFmtOut, 0);
+
+ if ( sp_swr_init(pAV->swResampleCtx) < 0 ) {
+ sp_swr_free(&pAV->swResampleCtx);
+ pAV->swResampleCtx = NULL;
+ fprintf(stderr, "error initializing swresample ctx\n");
+ } else {
+ // OK
+ pAV->aSampleFmtOut = aSampleFmtOut;
+ pAV->aChannelsOut = aChannelsOut;
+ pAV->aSampleRateOut = aSampleRateOut;
+ pAV->aSinkSupport = 1;
+ }
+ }
+ }
+ }
+ if(pAV->verbose) {
+ fprintf(stderr, "Info: Need resample %d, Use avresample %d, swresample %d\n",
+ pAV->aSinkSupport, NULL!=pAV->avResampleCtx, NULL!=pAV->swResampleCtx);
+ }
+
+ // Allocate audio frames
+ // FIXME: Libav Binary compatibility! JAU01
+ pAV->aFrameCount = 1;
+ pAV->pANIOBuffers = calloc(pAV->aFrameCount, sizeof(NIOBuffer_t));
+ pAV->pAFrames = calloc(pAV->aFrameCount, sizeof(AVFrame*));
+ pAV->pAFrames[0] = pAFrame0;
+ for(i=1; i<pAV->aFrameCount; i++) {
+ pAV->pAFrames[i] = sp_avcodec_alloc_frame();
+ if( NULL == pAV->pAFrames[i] ) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't alloc audio frame %d / %d", i, pAV->aFrameCount);
+ return;
+ }
+ }
+ pAV->aFrameCurrent = 0;
+ }
+
+ if(0<=pAV->vid) {
+ // Get a pointer to the codec context for the video stream
+ // FIXME: Libav Binary compatibility! JAU01
+ pAV->pVCodecCtx=pAV->pVStream->codec;
+ #if 0
+ pAV->pVCodecCtx->get_format = my_get_format;
+ #endif
+
+ if (pAV->pVCodecCtx->bit_rate) {
+ // FIXME: Libav Binary compatibility! JAU01
+ pAV->bps_video = pAV->pVCodecCtx->bit_rate;
+ }
+
+ // Customize ..
+ // pAV->pVCodecCtx->thread_count=2;
+ // pAV->pVCodecCtx->thread_type=FF_THREAD_FRAME|FF_THREAD_SLICE; // Decode more than one frame at once
+ pAV->pVCodecCtx->thread_count=0;
+ pAV->pVCodecCtx->thread_type=0;
+ pAV->pVCodecCtx->workaround_bugs=FF_BUG_AUTODETECT;
+ pAV->pVCodecCtx->skip_frame=AVDISCARD_DEFAULT;
+
+ sp_avcodec_string(pAV->vcodec, sizeof(pAV->vcodec), pAV->pVCodecCtx, 0);
+
+ // Find the decoder for the video stream
+ pAV->pVCodec=sp_avcodec_find_decoder(pAV->pVCodecCtx->codec_id);
+ if(pAV->pVCodec==NULL) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't find video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec);
+ return;
+ }
+
+ // Open codec
+ MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+ {
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ pAV->pVCodecCtx->refcounted_frames = pAV->useRefCountedFrames;
+ #endif
+ res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL);
+ }
+ MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
+ if(res<0) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't open video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec);
+ return;
+ }
+
+ // Hack to correct wrong frame rates that seem to be generated by some codecs
+ // FIXME: Libav Binary compatibility! JAU01
+ if(pAV->pVCodecCtx->time_base.num>1000 && pAV->pVCodecCtx->time_base.den==1) {
+ pAV->pVCodecCtx->time_base.den=1000;
+ }
+ // FIXME: Libav Binary compatibility! JAU01
+ if( pAV->pVStream->avg_frame_rate.den && pAV->pVStream->avg_frame_rate.num ) {
+ pAV->fps = my_av_q2f(pAV->pVStream->avg_frame_rate);
+ #if LIBAVCODEC_VERSION_MAJOR < 55
+ } else if( pAV->pVStream->r_frame_rate.den && pAV->pVStream->r_frame_rate.num ) {
+ pAV->fps = my_av_q2f(pAV->pVStream->r_frame_rate);
+ #endif
+ } else if( pAV->pVStream->codec->time_base.den && pAV->pVStream->codec->time_base.num ) {
+ pAV->fps = my_av_q2f_r(pAV->pVStream->codec->time_base);
+ } else if( pAV->pVStream->time_base.den && pAV->pVStream->time_base.num ) {
+ pAV->fps = my_av_q2f_r(pAV->pVStream->time_base);
+ } else {
+ pAV->fps = 0.0f; // duh!
+ }
+ pAV->frames_video = pAV->pVStream->nb_frames;
+
+ // Allocate video frame
+ // FIXME: Libav Binary compatibility! JAU01
+ pAV->vWidth = pAV->pVCodecCtx->width;
+ pAV->vHeight = pAV->pVCodecCtx->height;
+ pAV->vPixFmt = pAV->pVCodecCtx->pix_fmt;
+ pAV->vFlipped = JNI_FALSE;
+ {
+ AVPixFmtDescriptor pixDesc = sp_av_pix_fmt_descriptors[pAV->vPixFmt];
+ pAV->vBitsPerPixel = sp_av_get_bits_per_pixel(&pixDesc);
+ pAV->vBufferPlanes = my_getPlaneCount(&pixDesc);
+ }
+
+ if( pAV->verbose ) {
+ fprintf(stderr, "V frame_size %d, frame_number %d, [afps %f, rfps %f, cfps %f, sfps %f] -> %f fps, nb_frames %"PRId64", size %dx%d, fmt 0x%X, bpp %d, planes %d, codecCaps 0x%X\n",
+ pAV->pVCodecCtx->frame_size, pAV->pVCodecCtx->frame_number,
+ my_av_q2f(pAV->pVStream->avg_frame_rate),
+ #if LIBAVCODEC_VERSION_MAJOR < 55
+ my_av_q2f(pAV->pVStream->r_frame_rate),
+ #else
+ 0.0f,
+ #endif
+ my_av_q2f_r(pAV->pVStream->codec->time_base),
+ my_av_q2f_r(pAV->pVStream->time_base),
+ pAV->fps,
+ pAV->pVStream->nb_frames,
+ pAV->vWidth, pAV->vHeight, pAV->vPixFmt, pAV->vBitsPerPixel, pAV->vBufferPlanes, pAV->pVCodecCtx->codec->capabilities);
+ }
+
+ pAV->pVFrame=sp_avcodec_alloc_frame();
+ if( pAV->pVFrame == NULL ) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't alloc video frame");
+ return;
+ }
+ // Min. requirement for 'get_buffer2' !
+ pAV->pVFrame->width = pAV->pVCodecCtx->width;
+ pAV->pVFrame->height = pAV->pVCodecCtx->height;
+ pAV->pVFrame->format = pAV->pVCodecCtx->pix_fmt;
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ res = sp_avcodec_default_get_buffer2(pAV->pVCodecCtx, pAV->pVFrame, 0);
+ #else
+ res = sp_avcodec_default_get_buffer(pAV->pVCodecCtx, pAV->pVFrame);
+ #endif
+ if(0!=res) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't peek video buffer dimension");
+ return;
+ }
+ {
+ const int32_t bytesPerPixel = ( pAV->vBitsPerPixel + 7 ) / 8 ;
+ if(1 == pAV->vBufferPlanes) {
+ pAV->vBytesPerPixelPerPlane = bytesPerPixel;
+ } else {
+ pAV->vBytesPerPixelPerPlane = 1;
+ }
+ int32_t vLinesize[4];
+ if( pAV->vBufferPlanes > 1 ) {
+ #if 0
+ getAlignedLinesizes(pAV->pVCodecCtx, vLinesize);
+ for(i=0; i<pAV->vBufferPlanes; i++) {
+ // FIXME: Libav Binary compatibility! JAU01
+ pAV->vTexWidth[i] = vLinesize[i] / pAV->vBytesPerPixelPerPlane ;
+ }
+ #else
+ for(i=0; i<pAV->vBufferPlanes; i++) {
+ // FIXME: Libav Binary compatibility! JAU01
+ vLinesize[i] = pAV->pVFrame->linesize[i];
+ pAV->vTexWidth[i] = vLinesize[i] / pAV->vBytesPerPixelPerPlane ;
+ }
+ #endif
+ } else {
+ vLinesize[0] = pAV->pVFrame->linesize[0];
+ if( pAV->vPixFmt == PIX_FMT_YUYV422 ) {
+ // Stuff 2x 16bpp (YUYV) into one RGBA pixel!
+ pAV->vTexWidth[0] = pAV->pVCodecCtx->width / 2;
+ } else {
+ pAV->vTexWidth[0] = pAV->pVCodecCtx->width;
+ }
+ }
+ if( pAV->verbose ) {
+ for(i=0; i<pAV->vBufferPlanes; i++) {
+ fprintf(stderr, "Video: P[%d]: %d texw * %d bytesPP -> %d line\n", i, pAV->vTexWidth[i], pAV->vBytesPerPixelPerPlane, vLinesize[i]);
+ }
+ }
+ }
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ sp_av_frame_unref(pAV->pVFrame);
+ #else
+ sp_avcodec_default_release_buffer(pAV->pVCodecCtx, pAV->pVFrame);
+ #endif
+ }
+ pAV->vPTS=0;
+ pAV->aPTS=0;
+ initPTSStats(&pAV->vPTSStats);
+ initPTSStats(&pAV->aPTSStats);
+ _updateJavaAttributes(env, pAV);
+}
+
+JNIEXPORT void JNICALL FF_FUNC(setGLFuncs0)
+ (JNIEnv *env, jobject instance, jlong ptr, jlong jProcAddrGLTexSubImage2D, jlong jProcAddrGLGetError, jlong jProcAddrGLFlush, jlong jProcAddrGLFinish)
+{
+ FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
+ pAV->procAddrGLTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) (intptr_t)jProcAddrGLTexSubImage2D;
+ pAV->procAddrGLGetError = (PFNGLGETERRORPROC) (intptr_t)jProcAddrGLGetError;
+ pAV->procAddrGLFlush = (PFNGLFLUSH) (intptr_t)jProcAddrGLFlush;
+ pAV->procAddrGLFinish = (PFNGLFINISH) (intptr_t)jProcAddrGLFinish;
+}
+
+#if 0
+#define DBG_TEXSUBIMG2D_a(c,p,w1,w2,h,i) fprintf(stderr, "TexSubImage2D.%c offset %d / %d, size %d x %d, ", c, (w1*p->pVCodecCtx->width)/w2, p->pVCodecCtx->height/h, p->vTexWidth[i], p->pVCodecCtx->height/h)
+#define DBG_TEXSUBIMG2D_b(p) fprintf(stderr, "err 0x%X\n", pAV->procAddrGLGetError())
+#else
+#define DBG_TEXSUBIMG2D_a(c,p,w1,w2,h,i)
+#define DBG_TEXSUBIMG2D_b(p)
+#endif
+
+JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0)
+ (JNIEnv *env, jobject instance, jlong ptr, jint texTarget, jint texFmt, jint texType)
+{
+ FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
+
+ AVPacket packet;
+ jint resPTS = INVALID_PTS;
+ uint8_t * pkt_odata;
+ int pkt_osize;
+
+ packet.data = NULL; // minimum
+ packet.size = 0; // requirement
+ sp_av_init_packet(&packet);
+
+ const int avRes = sp_av_read_frame(pAV->pFormatCtx, &packet);
+ pkt_odata = packet.data;
+ pkt_osize = packet.size;
+ if( AVERROR_EOF == avRes || ( pAV->pFormatCtx->pb && pAV->pFormatCtx->pb->eof_reached ) ) {
+ if( pAV->verbose ) {
+ fprintf(stderr, "EOS: avRes[res %d, eos %d], pb-EOS %d\n",
+ avRes, AVERROR_EOF == avRes,
+ ( pAV->pFormatCtx->pb && pAV->pFormatCtx->pb->eof_reached ) );
+ }
+ resPTS = END_OF_STREAM_PTS;
+ } else if( 0 <= avRes ) {
+ if( pAV->verbose ) {
+ fprintf(stderr, "P: ptr %p, size %d\n", packet.data, packet.size);
+ }
+ if(packet.stream_index==pAV->aid) {
+ // Decode audio frame
+ if(NULL == pAV->pAFrames) { // no audio registered
+ sp_av_free_packet(&packet);
+ return INVALID_PTS;
+ }
+ int frameCount;
+ int flush_complete = 0;
+ for ( frameCount=0; 0 < packet.size || 0 == frameCount; frameCount++ ) {
+ int frameDecoded;
+ int len1;
+ AVFrame* pAFrameCurrent = pAV->pAFrames[pAV->aFrameCurrent];
+ if( pAV->useRefCountedFrames ) {
+ sp_av_frame_unref(pAFrameCurrent);
+ pAV->aFrameCurrent = ( pAV->aFrameCurrent + 1 ) % pAV->aFrameCount ;
+ }
+ sp_avcodec_get_frame_defaults(pAFrameCurrent);
+
+ if (flush_complete) {
+ break;
+ }
+ len1 = sp_avcodec_decode_audio4(pAV->pACodecCtx, pAFrameCurrent, &frameDecoded, &packet);
+ if (len1 < 0) {
+ // if error, we skip the frame
+ packet.size = 0;
+ break;
+ }
+ packet.data += len1;
+ packet.size -= len1;
+
+ if (!frameDecoded) {
+ // stop sending empty packets if the decoder is finished
+ if (!packet.data && pAV->pACodecCtx->codec->capabilities & CODEC_CAP_DELAY) {
+ flush_complete = 1;
+ }
+ continue;
+ }
+
+ int32_t data_size = 0;
+ if(HAS_FUNC(sp_av_samples_get_buffer_size)) {
+ data_size = sp_av_samples_get_buffer_size(NULL /* linesize, may be NULL */,
+ pAV->aChannels,
+ pAFrameCurrent->nb_samples,
+ pAFrameCurrent->format,
+ 1 /* align */);
+ }
+ #if 0
+ fprintf(stderr, "channels %d sample_rate %d \n", pAV->aChannels , pAV->aSampleRate);
+ fprintf(stderr, "data %d \n", pAV->aFrameSize);
+ #endif
+
+ const AVRational time_base = pAV->pAStream->time_base;
+ const int64_t pkt_pts = pAFrameCurrent->pkt_pts;
+ if( 0 == frameCount && AV_NOPTS_VALUE != pkt_pts ) { // 1st frame only, discard invalid PTS ..
+ pAV->aPTS = my_av_q2i32( pkt_pts * 1000, time_base);
+ } else { // subsequent frames or invalid PTS ..
+ const int32_t bytesPerSample = sp_av_get_bytes_per_sample( pAV->pACodecCtx->sample_fmt );
+ pAV->aPTS += data_size / ( pAV->aChannels * bytesPerSample * ( pAV->aSampleRate / 1000 ) );
+ }
+ if( pAV->verbose ) {
+ int32_t aDTS = my_av_q2i32( pAFrameCurrent->pkt_dts * 1000, time_base);
+
+ fprintf(stderr, "A pts %d [pkt_pts %"PRId64"], dts %d [pkt_dts %"PRId64"], f# %d, aFrame %d/%d %p, dataPtr %p, dataSize %d\n",
+ pAV->aPTS, pkt_pts, aDTS, pAFrameCurrent->pkt_dts, frameCount,
+ pAV->aFrameCurrent, pAV->aFrameCount, pAFrameCurrent, pAFrameCurrent->data[0], data_size);
+ }
+ if( NULL != env ) {
+ void* data_ptr = pAFrameCurrent->data[0]; // default
+
+ if( NULL != pAV->avResampleCtx || NULL != pAV->swResampleCtx ) {
+ uint8_t *tmp_out;
+ int out_samples=-1, out_size, out_linesize;
+ int osize = sp_av_get_bytes_per_sample( pAV->aSampleFmtOut );
+ int nb_samples = pAFrameCurrent->nb_samples;
+
+ out_size = sp_av_samples_get_buffer_size(&out_linesize,
+ pAV->aChannelsOut,
+ nb_samples,
+ pAV->aSampleFmtOut, 0 /* align */);
+
+ tmp_out = sp_av_realloc(pAV->aResampleBuffer, out_size);
+ if (!tmp_out) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't alloc resample buffer of size %d", out_size);
+ return INVALID_PTS;
+ }
+ pAV->aResampleBuffer = tmp_out;
+
+ if( NULL != pAV->avResampleCtx ) {
+ out_samples = sp_avresample_convert(pAV->avResampleCtx,
+ &pAV->aResampleBuffer,
+ out_linesize, nb_samples,
+ pAFrameCurrent->data,
+ pAFrameCurrent->linesize[0],
+ pAFrameCurrent->nb_samples);
+ } else if( NULL != pAV->swResampleCtx ) {
+ out_samples = sp_swr_convert(pAV->swResampleCtx,
+ &pAV->aResampleBuffer, nb_samples,
+ (const uint8_t **)pAFrameCurrent->data, pAFrameCurrent->nb_samples);
+ }
+ if (out_samples < 0) {
+ JoglCommon_throwNewRuntimeException(env, "avresample_convert() failed");
+ return INVALID_PTS;
+ }
+ data_size = out_samples * osize * pAV->aChannelsOut;
+ data_ptr = tmp_out;
+ }
+ NIOBuffer_t * pNIOBufferCurrent = &pAV->pANIOBuffers[pAV->aFrameCurrent];
+ int newNIO = NULL == pNIOBufferCurrent->nioRef;
+ if( !newNIO && ( data_ptr != pNIOBufferCurrent->origPtr || data_size > pNIOBufferCurrent->size ) ) {
+ if(pAV->verbose) {
+ fprintf(stderr, "A NIO: Free.0 ptr %p / ref %p, %d bytes\n",
+ pNIOBufferCurrent->origPtr, pNIOBufferCurrent->nioRef, pNIOBufferCurrent->size);
+ }
+ (*env)->DeleteGlobalRef(env, pNIOBufferCurrent->nioRef);
+ newNIO = 1;
+ }
+ if( newNIO ) {
+ jobject jSampleData = (*env)->NewDirectByteBuffer(env, data_ptr, data_size);
+ pNIOBufferCurrent->nioRef = (*env)->NewGlobalRef(env, jSampleData);
+ pNIOBufferCurrent->origPtr = data_ptr;
+ pNIOBufferCurrent->size = data_size;
+ (*env)->DeleteLocalRef(env, jSampleData);
+ if(pAV->verbose) {
+ fprintf(stderr, "A NIO: Alloc ptr %p / ref %p, %d bytes\n",
+ pNIOBufferCurrent->origPtr, pNIOBufferCurrent->nioRef, pNIOBufferCurrent->size);
+ }
+ }
+ (*env)->CallVoidMethod(env, pAV->ffmpegMediaPlayer, ffmpeg_jni_mid_pushSound, pNIOBufferCurrent->nioRef, data_size, pAV->aPTS);
+ }
+ }
+ } else if(packet.stream_index==pAV->vid) {
+ // Decode video frame
+ if(NULL == pAV->pVFrame) {
+ sp_av_free_packet(&packet);
+ return INVALID_PTS;
+ }
+ int frameCount;
+ int flush_complete = 0;
+ for ( frameCount=0; 0 < packet.size || 0 == frameCount; frameCount++ ) {
+ int frameDecoded;
+ int len1;
+ sp_avcodec_get_frame_defaults(pAV->pVFrame);
+ if (flush_complete) {
+ break;
+ }
+ len1 = sp_avcodec_decode_video2(pAV->pVCodecCtx, pAV->pVFrame, &frameDecoded, &packet);
+ if (len1 < 0) {
+ // if error, we skip the frame
+ packet.size = 0;
+ break;
+ }
+ packet.data += len1;
+ packet.size -= len1;
+
+ if (!frameDecoded) {
+ // stop sending empty packets if the decoder is finished
+ if (!packet.data && pAV->pVCodecCtx->codec->capabilities & CODEC_CAP_DELAY) {
+ flush_complete = 1;
+ }
+ continue;
+ }
+
+ // FIXME: Libav Binary compatibility! JAU01
+ const AVRational time_base = pAV->pVStream->time_base;
+ const int64_t pkt_pts = pAV->pVFrame->pkt_pts;
+ const int64_t pkt_dts = pAV->pVFrame->pkt_dts;
+ const int64_t fix_pts = evalPTS(&pAV->vPTSStats, pkt_pts, pkt_dts);
+ if( AV_NOPTS_VALUE != fix_pts ) { // discard invalid PTS ..
+ pAV->vPTS = my_av_q2i32( fix_pts * 1000, time_base);
+ }
+ if( pAV->verbose ) {
+ const int32_t vPTS = AV_NOPTS_VALUE != pkt_pts ? my_av_q2i32( pkt_pts * 1000, time_base) : 0;
+ const int32_t vDTS = AV_NOPTS_VALUE != pkt_dts ? my_av_q2i32( pkt_dts * 1000, time_base) : 0;
+
+ const double frame_delay_d = av_q2d(pAV->pVCodecCtx->time_base);
+ const double frame_repeat_d = pAV->pVFrame->repeat_pict * (frame_delay_d * 0.5);
+
+ const int32_t frame_delay_i = my_av_q2i32(1000, pAV->pVCodecCtx->time_base);
+ const int32_t frame_repeat_i = pAV->pVFrame->repeat_pict * (frame_delay_i / 2);
+
+ const char * warn = frame_repeat_i > 0 ? "REPEAT" : "NORMAL" ;
+
+ fprintf(stderr, "V fix_pts %d, pts %d [pkt_pts %"PRId64"], dts %d [pkt_dts %"PRId64"], time d(%lf s + r %lf = %lf s), i(%d ms + r %d = %d ms) - %s - f# %d, dec %d, data %p, lsz %d\n",
+ pAV->vPTS, vPTS, pkt_pts, vDTS, pkt_dts,
+ frame_delay_d, frame_repeat_d, (frame_delay_d + frame_repeat_d),
+ frame_delay_i, frame_repeat_i, (frame_delay_i + frame_repeat_i), warn, frameCount,
+ len1, pAV->pVFrame->data[0], pAV->pVFrame->linesize[0]);
+ // fflush(NULL);
+ }
+ if( 0 == pAV->pVFrame->linesize[0] ) {
+ if( pAV->useRefCountedFrames ) {
+ sp_av_frame_unref(pAV->pVFrame);
+ }
+ continue;
+ }
+ resPTS = pAV->vPTS; // Video Frame!
+
+ int p_offset[] = { 0, 0, 0, 0 };
+ if( pAV->pVFrame->linesize[0] < 0 ) {
+ if( JNI_FALSE == pAV->vFlipped ) {
+ pAV->vFlipped = JNI_TRUE;
+ _setIsGLOriented(env, pAV);
+ }
+
+ // image bottom-up
+ int h_1 = pAV->pVCodecCtx->height - 1;
+ p_offset[0] = pAV->pVFrame->linesize[0] * h_1;
+ if( pAV->vBufferPlanes > 1 ) {
+ p_offset[1] = pAV->pVFrame->linesize[1] * h_1;
+ }
+ if( pAV->vBufferPlanes > 2 ) {
+ p_offset[2] = pAV->pVFrame->linesize[2] * h_1;
+ }
+ /**
+ if( pAV->vBufferPlanes > 3 ) {
+ p_offset[3] = pAV->pVFrame->linesize[3] * h_1;
+ } */
+ } else if( JNI_TRUE == pAV->vFlipped ) {
+ pAV->vFlipped = JNI_FALSE;
+ _setIsGLOriented(env, pAV);
+ }
+
+ // 1st plane or complete packed frame
+ // FIXME: Libav Binary compatibility! JAU01
+ DBG_TEXSUBIMG2D_a('Y',pAV,1,1,1,0);
+ pAV->procAddrGLTexSubImage2D(texTarget, 0,
+ 0, 0,
+ pAV->vTexWidth[0], pAV->pVCodecCtx->height,
+ texFmt, texType, pAV->pVFrame->data[0] + p_offset[0]);
+ DBG_TEXSUBIMG2D_b(pAV);
+
+ if( pAV->vPixFmt == PIX_FMT_YUV420P || pAV->vPixFmt == PIX_FMT_YUVJ420P ) {
+ // U plane
+ // FIXME: Libav Binary compatibility! JAU01
+ DBG_TEXSUBIMG2D_a('U',pAV,1,1,2,1);
+ pAV->procAddrGLTexSubImage2D(texTarget, 0,
+ pAV->pVCodecCtx->width, 0,
+ pAV->vTexWidth[1], pAV->pVCodecCtx->height/2,
+ texFmt, texType, pAV->pVFrame->data[1] + p_offset[1]);
+ DBG_TEXSUBIMG2D_b(pAV);
+ // V plane
+ // FIXME: Libav Binary compatibility! JAU01
+ DBG_TEXSUBIMG2D_a('V',pAV,1,1,2,2);
+ pAV->procAddrGLTexSubImage2D(texTarget, 0,
+ pAV->pVCodecCtx->width, pAV->pVCodecCtx->height/2,
+ pAV->vTexWidth[2], pAV->pVCodecCtx->height/2,
+ texFmt, texType, pAV->pVFrame->data[2] + p_offset[2]);
+ DBG_TEXSUBIMG2D_b(pAV);
+ } else if( pAV->vPixFmt == PIX_FMT_YUV422P || pAV->vPixFmt == PIX_FMT_YUVJ422P ) {
+ // U plane
+ // FIXME: Libav Binary compatibility! JAU01
+ DBG_TEXSUBIMG2D_a('U',pAV,1,1,1,1);
+ pAV->procAddrGLTexSubImage2D(texTarget, 0,
+ pAV->pVCodecCtx->width, 0,
+ pAV->vTexWidth[1], pAV->pVCodecCtx->height,
+ texFmt, texType, pAV->pVFrame->data[1] + p_offset[1]);
+ DBG_TEXSUBIMG2D_b(pAV);
+ // V plane
+ // FIXME: Libav Binary compatibility! JAU01
+ DBG_TEXSUBIMG2D_a('V',pAV,3,2,1,1);
+ pAV->procAddrGLTexSubImage2D(texTarget, 0,
+ pAV->pVCodecCtx->width+pAV->pVCodecCtx->width/2, 0,
+ pAV->vTexWidth[2], pAV->pVCodecCtx->height,
+ texFmt, texType, pAV->pVFrame->data[2] + p_offset[2]);
+ DBG_TEXSUBIMG2D_b(pAV);
+ } // FIXME: Add more planar formats !
+
+ pAV->procAddrGLFinish();
+ //pAV->procAddrGLFlush();
+ if( pAV->useRefCountedFrames ) {
+ sp_av_frame_unref(pAV->pVFrame);
+ }
+ }
+ }
+ // restore orig pointer and size values, we may have moved along within packet
+ packet.data = pkt_odata;
+ packet.size = pkt_osize;
+ sp_av_free_packet(&packet);
+ }
+ return resPTS;
+}
+
+static void initPTSStats(PTSStats *ptsStats) {
+ ptsStats->ptsError = 0;
+ ptsStats->dtsError = 0;
+ ptsStats->ptsLast = INT64_MIN;
+ ptsStats->dtsLast = INT64_MIN;
+}
+static int64_t evalPTS(PTSStats *ptsStats, int64_t inPTS, int64_t inDTS) {
+ int64_t resPTS = AV_NOPTS_VALUE;
+
+ if ( inDTS != AV_NOPTS_VALUE ) {
+ ptsStats->dtsError += inDTS <= ptsStats->dtsLast;
+ ptsStats->dtsLast = inDTS;
+ }
+ if ( inPTS != AV_NOPTS_VALUE ) {
+ ptsStats->ptsError += inPTS <= ptsStats->ptsLast;
+ ptsStats->ptsLast = inPTS;
+ }
+ if ( inPTS != AV_NOPTS_VALUE &&
+ ( ptsStats->ptsError<=ptsStats->dtsError || inDTS == AV_NOPTS_VALUE ) ) {
+ resPTS = inPTS;
+ } else {
+ resPTS = inDTS;
+ }
+ return resPTS;
+}
+
+
+JNIEXPORT jint JNICALL FF_FUNC(play0)
+ (JNIEnv *env, jobject instance, jlong ptr)
+{
+ FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
+ return sp_av_read_play(pAV->pFormatCtx);
+}
+JNIEXPORT jint JNICALL FF_FUNC(pause0)
+ (JNIEnv *env, jobject instance, jlong ptr)
+{
+ FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
+ return sp_av_read_pause(pAV->pFormatCtx);
+}
+
+JNIEXPORT jint JNICALL FF_FUNC(seek0)
+ (JNIEnv *env, jobject instance, jlong ptr, jint pos1)
+{
+ const FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
+ int64_t pos0, pts0;
+ int streamID;
+ AVRational time_base;
+ if( pAV->vid >= 0 ) {
+ pos0 = pAV->vPTS;
+ streamID = pAV->vid;
+ time_base = pAV->pVStream->time_base;
+ pts0 = pAV->pVFrame->pkt_pts;
+ } else if( pAV->aid >= 0 ) {
+ pos0 = pAV->aPTS;
+ streamID = pAV->aid;
+ time_base = pAV->pAStream->time_base;
+ pts0 = pAV->pAFrames[pAV->aFrameCurrent]->pkt_pts;
+ } else {
+ return pAV->vPTS;
+ }
+ int64_t pts1 = (int64_t) (pos1 * (int64_t) time_base.den)
+ / (1000 * (int64_t) time_base.num);
+ if(pAV->verbose) {
+ fprintf(stderr, "SEEK: vid %d, aid %d, pos0 %"PRId64", pos1 %d, pts: %"PRId64" -> %"PRId64"\n", pAV->vid, pAV->aid, pos0, pos1, pts0, pts1);
+ }
+ int flags = 0;
+ if(pos1 < pos0) {
+ flags |= AVSEEK_FLAG_BACKWARD;
+ }
+ int res = -2;
+ if(HAS_FUNC(sp_av_seek_frame)) {
+ if(pAV->verbose) {
+ fprintf(stderr, "SEEK.0: pre : s %"PRId64" / %"PRId64" -> t %d / %"PRId64"\n", pos0, pts0, pos1, pts1);
+ }
+ sp_av_seek_frame(pAV->pFormatCtx, streamID, pts1, flags);
+ } else if(HAS_FUNC(sp_avformat_seek_file)) {
+ int64_t ptsD = pts1 - pts0;
+ int64_t seek_min = ptsD > 0 ? pts1 - ptsD : INT64_MIN;
+ int64_t seek_max = ptsD < 0 ? pts1 - ptsD : INT64_MAX;
+ if(pAV->verbose) {
+ fprintf(stderr, "SEEK.1: pre : s %"PRId64" / %"PRId64" -> t %d / %"PRId64" [%"PRId64" .. %"PRId64"]\n",
+ pos0, pts0, pos1, pts1, seek_min, seek_max);
+ }
+ res = sp_avformat_seek_file(pAV->pFormatCtx, -1, seek_min, pts1, seek_max, flags);
+ }
+ if(NULL != pAV->pVCodecCtx) {
+ sp_avcodec_flush_buffers( pAV->pVCodecCtx );
+ }
+ if(NULL != pAV->pACodecCtx) {
+ sp_avcodec_flush_buffers( pAV->pACodecCtx );
+ }
+ const jint rPTS = my_av_q2i32( ( pAV->vid >= 0 ? pAV->pVFrame->pkt_pts : pAV->pAFrames[pAV->aFrameCurrent]->pkt_pts ) * 1000, time_base);
+ if(pAV->verbose) {
+ fprintf(stderr, "SEEK: post : res %d, u %d\n", res, rPTS);
+ }
+ return rPTS;
+}
+
+JNIEXPORT jint JNICALL FF_FUNC(getVideoPTS0)
+ (JNIEnv *env, jobject instance, jlong ptr)
+{
+ FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
+ return pAV->vPTS;
+}
+
+JNIEXPORT jint JNICALL FF_FUNC(getAudioPTS0)
+ (JNIEnv *env, jobject instance, jlong ptr)
+{
+ FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
+ return pAV->aPTS;
+}
+
diff --git a/src/jogl/native/libav/ffmpeg_lavc53_lavf53_lavu51.c b/src/jogl/native/libav/ffmpeg_lavc53_lavf53_lavu51.c
new file mode 100644
index 000000000..edce2ba1d
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_lavc53_lavf53_lavu51.c
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "jogamp_opengl_util_av_impl_FFMPEGv08Natives.h"
+
+#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv08Natives_ ## METHOD
+
+#include "ffmpeg_impl_template.c"
diff --git a/src/jogl/native/libav/ffmpeg_lavc54_lavf54_lavu52_lavr01.c b/src/jogl/native/libav/ffmpeg_lavc54_lavf54_lavu52_lavr01.c
new file mode 100644
index 000000000..651a64976
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_lavc54_lavf54_lavu52_lavr01.c
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "jogamp_opengl_util_av_impl_FFMPEGv09Natives.h"
+
+#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv09Natives_ ## METHOD
+
+#include "ffmpeg_impl_template.c"
diff --git a/src/jogl/native/libav/ffmpeg_lavc55_lavf55_lavu53_lavr01.c b/src/jogl/native/libav/ffmpeg_lavc55_lavf55_lavu53_lavr01.c
new file mode 100644
index 000000000..277100398
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_lavc55_lavf55_lavu53_lavr01.c
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "jogamp_opengl_util_av_impl_FFMPEGv10Natives.h"
+
+#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv10Natives_ ## METHOD
+
+#include "ffmpeg_impl_template.c"
diff --git a/src/jogl/native/libav/ffmpeg_static.c b/src/jogl/native/libav/ffmpeg_static.c
new file mode 100644
index 000000000..c8af59540
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_static.c
@@ -0,0 +1,91 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "ffmpeg_static.h"
+
+#include "JoglCommon.h"
+
+#include <GL/gl-platform.h>
+
+static const char * const ClazzNameFFMPEGMediaPlayer = "jogamp/opengl/util/av/impl/FFMPEGMediaPlayer";
+
+static jclass ffmpegMediaPlayerClazz = NULL;
+jmethodID ffmpeg_jni_mid_pushSound = NULL;
+jmethodID ffmpeg_jni_mid_updateAttributes = NULL;
+jmethodID ffmpeg_jni_mid_setIsGLOriented = NULL;
+jmethodID ffmpeg_jni_mid_setupFFAttributes = NULL;
+jmethodID ffmpeg_jni_mid_isAudioFormatSupported = NULL;
+
+typedef unsigned (APIENTRYP AV_GET_VERSION)(void);
+
+JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGStaticNatives_initIDs0
+ (JNIEnv *env, jclass clazz)
+{
+ jboolean res = JNI_TRUE;
+ JoglCommon_init(env);
+
+ jclass c;
+ if (ffmpegMediaPlayerClazz != NULL) {
+ return JNI_FALSE;
+ }
+
+ c = (*env)->FindClass(env, ClazzNameFFMPEGMediaPlayer);
+ if(NULL==c) {
+ JoglCommon_FatalError(env, "JOGL FFMPEG: can't find %s", ClazzNameFFMPEGMediaPlayer);
+ }
+ ffmpegMediaPlayerClazz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==ffmpegMediaPlayerClazz) {
+ JoglCommon_FatalError(env, "JOGL FFMPEG: can't use %s", ClazzNameFFMPEGMediaPlayer);
+ }
+
+ ffmpeg_jni_mid_pushSound = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSound", "(Ljava/nio/ByteBuffer;II)V");
+ ffmpeg_jni_mid_updateAttributes = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "updateAttributes", "(IIIIIIIFIIILjava/lang/String;Ljava/lang/String;)V");
+ ffmpeg_jni_mid_setIsGLOriented = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "setIsGLOriented", "(Z)V");
+ ffmpeg_jni_mid_setupFFAttributes = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "setupFFAttributes", "(IIIIIIIIIIIIIII)V");
+ ffmpeg_jni_mid_isAudioFormatSupported = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "isAudioFormatSupported", "(III)Z");
+
+ if(ffmpeg_jni_mid_pushSound == NULL ||
+ ffmpeg_jni_mid_updateAttributes == NULL ||
+ ffmpeg_jni_mid_setIsGLOriented == NULL ||
+ ffmpeg_jni_mid_setupFFAttributes == NULL ||
+ ffmpeg_jni_mid_isAudioFormatSupported == NULL) {
+ return JNI_FALSE;
+ }
+ return res;
+}
+
+JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGStaticNatives_getAvVersion0
+ (JNIEnv *env, jclass clazz, jlong func) {
+ if( 0 != func ) {
+ return (jint) ((AV_GET_VERSION) (intptr_t) func)();
+ } else {
+ return 0;
+ }
+}
+
diff --git a/src/jogl/native/libav/ffmpeg_static.h b/src/jogl/native/libav/ffmpeg_static.h
new file mode 100644
index 000000000..ab4db2506
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_static.h
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#ifndef _FFMPEG_STATIC_H
+#define _FFMPEG_STATIC_H
+
+#ifdef _WIN32
+ #include <windows.h>
+#endif
+
+#include <gluegen_stdint.h>
+#include <gluegen_inttypes.h>
+#include <gluegen_stddef.h>
+#include <gluegen_stdint.h>
+
+#include "jogamp_opengl_util_av_impl_FFMPEGStaticNatives.h"
+
+extern jmethodID ffmpeg_jni_mid_pushSound;
+extern jmethodID ffmpeg_jni_mid_updateAttributes;
+extern jmethodID ffmpeg_jni_mid_setIsGLOriented;
+extern jmethodID ffmpeg_jni_mid_setupFFAttributes;
+extern jmethodID ffmpeg_jni_mid_isAudioFormatSupported;
+
+#endif /* _FFMPEG_STATIC_H */
+
diff --git a/src/jogl/native/libav/ffmpeg_tool.h b/src/jogl/native/libav/ffmpeg_tool.h
index 3181a8a8f..136be2ecc 100644
--- a/src/jogl/native/libav/ffmpeg_tool.h
+++ b/src/jogl/native/libav/ffmpeg_tool.h
@@ -41,28 +41,112 @@
#include <gluegen_stddef.h>
#include <gluegen_stdint.h>
-#include <libavcodec/avcodec.h>
-#include <libavformat/avformat.h>
+#include "libavcodec/avcodec.h"
+#include "libavformat/avformat.h"
+#include "libavutil/avutil.h"
+#if LIBAVCODEC_VERSION_MAJOR >= 54
+ #include "libavresample/avresample.h"
+ #include "libswresample/swresample.h"
+#endif
+
+#ifndef LIBAVRESAMPLE_VERSION_MAJOR
+#define LIBAVRESAMPLE_VERSION_MAJOR -1
+// Opaque
+typedef void* AVAudioResampleContext;
+#endif
+#ifndef LIBSWRESAMPLE_VERSION_MAJOR
+#define LIBSWRESAMPLE_VERSION_MAJOR -1
+// Opaque
+typedef struct SwrContext SwrContext;
+#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#include <GL/gl.h>
+
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (APIENTRYP PFNGLFLUSH) (void);
+typedef void (APIENTRYP PFNGLFINISH) (void);
+
/**
* AV_TIME_BASE 1000000
*/
#define AV_TIME_BASE_MSEC (AV_TIME_BASE/1000)
+#define AV_VERSION_MAJOR(i) ( ( i >> 16 ) & 0xFF )
+#define AV_VERSION_MINOR(i) ( ( i >> 8 ) & 0xFF )
+#define AV_VERSION_SUB(i) ( ( i >> 0 ) & 0xFF )
+
+/** Sync w/ GLMediaPlayer.STREAM_ID_NONE */
+#define AV_STREAM_ID_NONE -2
+
+/** Sync w/ GLMediaPlayer.STREAM_ID_AUTO */
+#define AV_STREAM_ID_AUTO -1
+
+/** Default number of audio frames per video frame. Sync w/ FFMPEGMediaPlayer.AV_DEFAULT_AFRAMES. */
+#define AV_DEFAULT_AFRAMES 8
+
+/** Constant PTS marking an invalid PTS, i.e. Integer.MIN_VALUE == 0x80000000 == {@value}. Sync w/ TimeFrameI.INVALID_PTS */
+#define INVALID_PTS 0x80000000
+
+/** Constant PTS marking the end of the stream, i.e. Integer.MIN_VALUE - 1 == 0x7FFFFFFF == {@value}. Sync w/ TimeFrameI.END_OF_STREAM_PTS */
+#define END_OF_STREAM_PTS 0x7FFFFFFF
+
+/** Since 54.0.0.1 */
+#define AV_HAS_API_AVRESAMPLE(pAV) ( ( LIBAVRESAMPLE_VERSION_MAJOR >= 0 ) && ( pAV->avresampleVersion != 0 ) )
+
+/** Since 55.0.0.1 */
+#define AV_HAS_API_SWRESAMPLE(pAV) ( ( LIBSWRESAMPLE_VERSION_MAJOR >= 0 ) && ( pAV->swresampleVersion != 0 ) )
+
+#define MAX_INT(a,b) ( (a >= b) ? a : b )
+#define MIN_INT(a,b) ( (a <= b) ? a : b )
+
static inline float my_av_q2f(AVRational a){
- return a.num / (float) a.den;
+ return (float)a.num / (float)a.den;
+}
+static inline float my_av_q2f_r(AVRational a){
+ return (float)a.den / (float)a.num;
}
-static inline int32_t my_av_q2i32(int32_t snum, AVRational a){
- return (snum * a.num) / a.den;
+static inline int32_t my_av_q2i32(int64_t snum, AVRational a){
+ return (int32_t) ( ( snum * (int64_t) a.num ) / (int64_t)a.den );
}
+static inline int my_align(int v, int a){
+ return ( v + a - 1 ) & ~( a - 1 );
+}
+
+typedef struct {
+ void *origPtr;
+ jobject nioRef;
+ int32_t size;
+} NIOBuffer_t;
+
+typedef struct {
+ int64_t ptsError; // Number of backward PTS values (earlier than last PTS, excluding AV_NOPTS_VALUE)
+ int64_t dtsError; // Number of backward DTS values (earlier than last PTS, excluding AV_NOPTS_VALUE)
+ int64_t ptsLast; // PTS of the last frame
+ int64_t dtsLast; // DTS of the last frame
+} PTSStats;
typedef struct {
+ jobject ffmpegMediaPlayer;
int32_t verbose;
+ uint32_t avcodecVersion;
+ uint32_t avformatVersion;
+ uint32_t avutilVersion;
+ uint32_t avresampleVersion;
+ uint32_t swresampleVersion;
+
+ int32_t useRefCountedFrames;
+
+ PFNGLTEXSUBIMAGE2DPROC procAddrGLTexSubImage2D;
+ PFNGLGETERRORPROC procAddrGLGetError;
+ PFNGLFLUSH procAddrGLFlush;
+ PFNGLFINISH procAddrGLFinish;
+
AVFormatContext* pFormatCtx;
int32_t vid;
AVStream* pVStream;
@@ -74,26 +158,40 @@ typedef struct {
uint32_t vBytesPerPixelPerPlane;
enum PixelFormat vPixFmt; // native decoder fmt
int32_t vPTS; // msec - overall last video PTS
- int32_t vLinesize[3]; // decoded video linesize in bytes for each plane
- int32_t vTexWidth[3]; // decoded video tex width in bytes for each plane
-
+ PTSStats vPTSStats;
+ int32_t vTexWidth[4]; // decoded video tex width in bytes for each plane (max 4)
+ int32_t vWidth;
+ int32_t vHeight;
+ jboolean vFlipped; // false: !GL-Orientation, true: GL-Orientation
int32_t aid;
AVStream* pAStream;
AVCodecContext* pACodecCtx;
AVCodec* pACodec;
- AVFrame* pAFrame;
+ AVFrame** pAFrames;
+ NIOBuffer_t* pANIOBuffers;
+ int32_t aFrameCount;
+ int32_t aFrameCurrent;
+ int32_t aFrameSize; // in samples per channel!
+ enum AVSampleFormat aSampleFmt; // native decoder fmt
int32_t aSampleRate;
int32_t aChannels;
- int32_t aFrameSize;
- enum AVSampleFormat aSampleFmt; // native decoder fmt
+ int32_t aSinkSupport; // supported by AudioSink
+ AVAudioResampleContext* avResampleCtx;
+ struct SwrContext* swResampleCtx;
+ uint8_t* aResampleBuffer;
+ enum AVSampleFormat aSampleFmtOut; // out fmt
+ int32_t aChannelsOut;
+ int32_t aSampleRateOut;
int32_t aPTS; // msec - overall last audio PTS
+ PTSStats aPTSStats;
float fps; // frames per seconds
int32_t bps_stream; // bits per seconds
int32_t bps_video; // bits per seconds
int32_t bps_audio; // bits per seconds
- int32_t totalFrames;
+ int32_t frames_video;
+ int32_t frames_audio;
int32_t duration; // msec
int32_t start_time; // msec
diff --git a/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c b/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c
deleted file mode 100644
index 7fb64dade..000000000
--- a/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/**
- * Copyright 2012 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-#include "jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.h"
-
-#include "JoglCommon.h"
-#include "ffmpeg_tool.h"
-#include <libavutil/pixdesc.h>
-#include <GL/gl.h>
-
-typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
-
-static const char * const ClazzNameFFMPEGMediaPlayer = "jogamp/opengl/util/av/impl/FFMPEGMediaPlayer";
-
-static jclass ffmpegMediaPlayerClazz = NULL;
-static jmethodID jni_mid_updateAttributes1 = NULL;
-static jmethodID jni_mid_updateAttributes2 = NULL;
-
-#define HAS_FUNC(f) (NULL!=(f))
-
-typedef unsigned (APIENTRYP AVCODEC_VERSION)(void);
-typedef unsigned (APIENTRYP AVUTIL_VERSION)(void);
-typedef unsigned (APIENTRYP AVFORMAT_VERSION)(void);
-
-static AVCODEC_VERSION sp_avcodec_version;
-static AVFORMAT_VERSION sp_avformat_version;
-static AVUTIL_VERSION sp_avutil_version;
-// count: 3
-
-
-// libavcodec
-typedef int (APIENTRYP AVCODEC_CLOSE)(AVCodecContext *avctx);
-typedef void (APIENTRYP AVCODEC_STRING)(char *buf, int buf_size, AVCodecContext *enc, int encode);
-typedef AVCodec *(APIENTRYP AVCODEC_FIND_DECODER)(enum CodecID id);
-typedef int (APIENTRYP AVCODEC_OPEN2)(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options); // 53.6.0
-typedef int (APIENTRYP AVCODEC_OPEN)(AVCodecContext *avctx, AVCodec *codec);
-typedef AVFrame *(APIENTRYP AVCODEC_ALLOC_FRAME)(void);
-typedef int (APIENTRYP AVCODEC_DEFAULT_GET_BUFFER)(AVCodecContext *s, AVFrame *pic);
-typedef void (APIENTRYP AVCODEC_DEFAULT_RELEASE_BUFFER)(AVCodecContext *s, AVFrame *pic);
-typedef void (APIENTRYP AV_FREE_PACKET)(AVPacket *pkt);
-typedef int (APIENTRYP AVCODEC_DECODE_AUDIO4)(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt); // 53.25.0
-typedef int (APIENTRYP AVCODEC_DECODE_AUDIO3)(AVCodecContext *avctx, int16_t *samples, int *frame_size_ptr, AVPacket *avpkt); // 52.23.0
-typedef int (APIENTRYP AVCODEC_DECODE_VIDEO2)(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt); // 52.23.0
-
-static AVCODEC_CLOSE sp_avcodec_close;
-static AVCODEC_STRING sp_avcodec_string;
-static AVCODEC_FIND_DECODER sp_avcodec_find_decoder;
-static AVCODEC_OPEN2 sp_avcodec_open2; // 53.6.0
-static AVCODEC_OPEN sp_avcodec_open;
-static AVCODEC_ALLOC_FRAME sp_avcodec_alloc_frame;
-static AVCODEC_DEFAULT_GET_BUFFER sp_avcodec_default_get_buffer;
-static AVCODEC_DEFAULT_RELEASE_BUFFER sp_avcodec_default_release_buffer;
-static AV_FREE_PACKET sp_av_free_packet;
-static AVCODEC_DECODE_AUDIO4 sp_avcodec_decode_audio4; // 53.25.0
-static AVCODEC_DECODE_AUDIO3 sp_avcodec_decode_audio3; // 52.23.0
-static AVCODEC_DECODE_VIDEO2 sp_avcodec_decode_video2; // 52.23.0
-// count: 15
-
-// libavutil
-typedef void (APIENTRYP AV_FREE)(void *ptr);
-typedef int (APIENTRYP AV_GET_BITS_PER_PIXEL)(const AVPixFmtDescriptor *pixdesc);
-static const AVPixFmtDescriptor* sp_av_pix_fmt_descriptors;
-static AV_FREE sp_av_free;
-static AV_GET_BITS_PER_PIXEL sp_av_get_bits_per_pixel;
-// count: 18
-
-// libavformat
-typedef AVFormatContext *(APIENTRYP AVFORMAT_ALLOC_CONTEXT)(void);
-typedef void (APIENTRYP AVFORMAT_FREE_CONTEXT)(AVFormatContext *s); // 52.96.0
-typedef void (APIENTRYP AVFORMAT_CLOSE_INPUT)(AVFormatContext **s); // 53.17.0
-typedef void (APIENTRYP AV_CLOSE_INPUT_FILE)(AVFormatContext *s);
-typedef void (APIENTRYP AV_REGISTER_ALL)(void);
-typedef int (APIENTRYP AVFORMAT_OPEN_INPUT)(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);
-typedef void (APIENTRYP AV_DUMP_FORMAT)(AVFormatContext *ic, int index, const char *url, int is_output);
-typedef int (APIENTRYP AV_READ_FRAME)(AVFormatContext *s, AVPacket *pkt);
-typedef int (APIENTRYP AV_SEEK_FRAME)(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);
-typedef int (APIENTRYP AVFORMAT_NETWORK_INIT)(void); // 53.13.0
-typedef int (APIENTRYP AVFORMAT_NETWORK_DEINIT)(void); // 53.13.0
-typedef int (APIENTRYP AVFORMAT_FIND_STREAM_INFO)(AVFormatContext *ic, AVDictionary **options); // 53.3.0
-typedef int (APIENTRYP AV_FIND_STREAM_INFO)(AVFormatContext *ic);
-
-static AVFORMAT_ALLOC_CONTEXT sp_avformat_alloc_context;
-static AVFORMAT_FREE_CONTEXT sp_avformat_free_context; // 52.96.0
-static AVFORMAT_CLOSE_INPUT sp_avformat_close_input; // 53.17.0
-static AV_CLOSE_INPUT_FILE sp_av_close_input_file;
-static AV_REGISTER_ALL sp_av_register_all;
-static AVFORMAT_OPEN_INPUT sp_avformat_open_input;
-static AV_DUMP_FORMAT sp_av_dump_format;
-static AV_READ_FRAME sp_av_read_frame;
-static AV_SEEK_FRAME sp_av_seek_frame;
-static AVFORMAT_NETWORK_INIT sp_avformat_network_init; // 53.13.0
-static AVFORMAT_NETWORK_DEINIT sp_avformat_network_deinit; // 53.13.0
-static AVFORMAT_FIND_STREAM_INFO sp_avformat_find_stream_info; // 53.3.0
-static AV_FIND_STREAM_INFO sp_av_find_stream_info;
-// count: 31
-
-#define SYMBOL_COUNT 31
-
-JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGDynamicLibraryBundleInfo_initSymbols0
- (JNIEnv *env, jclass clazz, jobject jSymbols, jint count)
-{
- int64_t* symbols; // jlong -> int64_t -> intptr_t -> FUNC_PTR
- int i;
-
- if(SYMBOL_COUNT != count) {
- fprintf(stderr, "FFMPEGDynamicLibraryBundleInfo.initSymbols0: Wrong symbol count: Expected %d, Is %d\n",
- SYMBOL_COUNT, count);
- return JNI_FALSE;
- }
- JoglCommon_init(env);
-
- i = 0;
- symbols = (int64_t *) (*env)->GetPrimitiveArrayCritical(env, jSymbols, NULL);
-
- sp_avcodec_version = (AVCODEC_VERSION) (intptr_t) symbols[i++];
- sp_avformat_version = (AVFORMAT_VERSION) (intptr_t) symbols[i++];
- sp_avutil_version = (AVUTIL_VERSION) (intptr_t) symbols[i++];
- // count: 3
-
- sp_avcodec_close = (AVCODEC_CLOSE) (intptr_t) symbols[i++];
- sp_avcodec_string = (AVCODEC_STRING) (intptr_t) symbols[i++];
- sp_avcodec_find_decoder = (AVCODEC_FIND_DECODER) (intptr_t) symbols[i++];
- sp_avcodec_open2 = (AVCODEC_OPEN2) (intptr_t) symbols[i++];
- sp_avcodec_open = (AVCODEC_OPEN) (intptr_t) symbols[i++];
- sp_avcodec_alloc_frame = (AVCODEC_ALLOC_FRAME) (intptr_t) symbols[i++];
- sp_avcodec_default_get_buffer = (AVCODEC_DEFAULT_GET_BUFFER) (intptr_t) symbols[i++];
- sp_avcodec_default_release_buffer = (AVCODEC_DEFAULT_RELEASE_BUFFER) (intptr_t) symbols[i++];
- sp_av_free_packet = (AV_FREE_PACKET) (intptr_t) symbols[i++];
- sp_avcodec_decode_audio4 = (AVCODEC_DECODE_AUDIO4) (intptr_t) symbols[i++];
- sp_avcodec_decode_audio3 = (AVCODEC_DECODE_AUDIO3) (intptr_t) symbols[i++];
- sp_avcodec_decode_video2 = (AVCODEC_DECODE_VIDEO2) (intptr_t) symbols[i++];
- // count: 15
-
- sp_av_pix_fmt_descriptors = (const AVPixFmtDescriptor*) (intptr_t) symbols[i++];
- sp_av_free = (AV_FREE) (intptr_t) symbols[i++];
- sp_av_get_bits_per_pixel = (AV_GET_BITS_PER_PIXEL) (intptr_t) symbols[i++];
- // count: 18
-
- sp_avformat_alloc_context = (AVFORMAT_ALLOC_CONTEXT) (intptr_t) symbols[i++];;
- sp_avformat_free_context = (AVFORMAT_FREE_CONTEXT) (intptr_t) symbols[i++];
- sp_avformat_close_input = (AVFORMAT_CLOSE_INPUT) (intptr_t) symbols[i++];
- sp_av_close_input_file = (AV_CLOSE_INPUT_FILE) (intptr_t) symbols[i++];
- sp_av_register_all = (AV_REGISTER_ALL) (intptr_t) symbols[i++];
- sp_avformat_open_input = (AVFORMAT_OPEN_INPUT) (intptr_t) symbols[i++];
- sp_av_dump_format = (AV_DUMP_FORMAT) (intptr_t) symbols[i++];
- sp_av_read_frame = (AV_READ_FRAME) (intptr_t) symbols[i++];
- sp_av_seek_frame = (AV_SEEK_FRAME) (intptr_t) symbols[i++];
- sp_avformat_network_init = (AVFORMAT_NETWORK_INIT) (intptr_t) symbols[i++];
- sp_avformat_network_deinit = (AVFORMAT_NETWORK_DEINIT) (intptr_t) symbols[i++];
- sp_avformat_find_stream_info = (AVFORMAT_FIND_STREAM_INFO) (intptr_t) symbols[i++];
- sp_av_find_stream_info = (AV_FIND_STREAM_INFO) (intptr_t) symbols[i++];
- // count: 31
-
- (*env)->ReleasePrimitiveArrayCritical(env, jSymbols, symbols, 0);
-
- if(SYMBOL_COUNT != i) {
- // boom
- fprintf(stderr, "FFMPEGDynamicLibraryBundleInfo.initSymbols0: Wrong symbol assignment count: Expected %d, Is %d\n",
- SYMBOL_COUNT, i);
- return JNI_FALSE;
- }
-
- return JNI_TRUE;
-}
-
-static void _updateJavaAttributes(JNIEnv *env, jobject instance, FFMPEGToolBasicAV_t* pAV)
-{
- // int shallBeDetached = 0;
- // JNIEnv * env = JoglCommon_GetJNIEnv (&shallBeDetached);
- if(NULL!=env) {
- int32_t w, h;
- if( NULL != pAV->pVCodecCtx ) {
- // FIXME: Libav Binary compatibility! JAU01
- w = pAV->pVCodecCtx->width; h = pAV->pVCodecCtx->height;
- } else {
- w = 0; h = 0;
- }
-
- (*env)->CallVoidMethod(env, instance, jni_mid_updateAttributes1,
- w, h,
- pAV->bps_stream, pAV->bps_video, pAV->bps_audio,
- pAV->fps, (int32_t)((pAV->duration/1000)*pAV->fps), pAV->duration,
- (*env)->NewStringUTF(env, pAV->vcodec),
- (*env)->NewStringUTF(env, pAV->acodec) );
- (*env)->CallVoidMethod(env, instance, jni_mid_updateAttributes2,
- pAV->vPixFmt, pAV->vBufferPlanes,
- pAV->vBitsPerPixel, pAV->vBytesPerPixelPerPlane,
- pAV->vLinesize[0], pAV->vLinesize[1], pAV->vLinesize[2],
- pAV->vTexWidth[0], pAV->vTexWidth[1], pAV->vTexWidth[2]);
- // JoglCommon_ReleaseJNIEnv (shallBeDetached);
- }
-}
-
-static void freeInstance(FFMPEGToolBasicAV_t* pAV) {
- int i;
- if(NULL != pAV) {
- // Close the V codec
- if(NULL != pAV->pVCodecCtx) {
- sp_avcodec_close(pAV->pVCodecCtx);
- pAV->pVCodecCtx = NULL;
- }
- pAV->pVCodec=NULL;
-
- // Close the A codec
- if(NULL != pAV->pACodecCtx) {
- sp_avcodec_close(pAV->pACodecCtx);
- pAV->pACodecCtx = NULL;
- }
- pAV->pACodec=NULL;
-
- // Close the frames
- if(NULL != pAV->pVFrame) {
- sp_av_free(pAV->pVFrame);
- pAV->pVFrame = NULL;
- }
- if(NULL != pAV->pAFrame) {
- sp_av_free(pAV->pAFrame);
- pAV->pAFrame = NULL;
- }
-
- // Close the video file
- if(NULL != pAV->pFormatCtx) {
- if(HAS_FUNC(sp_avformat_close_input)) {
- sp_avformat_close_input(&pAV->pFormatCtx);
- } else {
- sp_av_close_input_file(pAV->pFormatCtx);
- if(HAS_FUNC(sp_avformat_free_context)) {
- sp_avformat_free_context(pAV->pFormatCtx);
- }
- }
- pAV->pFormatCtx = NULL;
- }
- free(pAV);
- }
-}
-
-static int my_getPlaneCount(AVPixFmtDescriptor *pDesc) {
- int i, p=-1;
- for(i=pDesc->nb_components-1; i>=0; i--) {
- int p0 = pDesc->comp[i].plane;
- if( p < p0 ) {
- p = p0;
- }
- }
- return p+1;
-}
-
-static int my_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt) {
- return sp_av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL;
-}
-
-#if 0
-static enum PixelFormat my_get_format(struct AVCodecContext *s, const enum PixelFormat * fmt) {
- int i=0;
- enum PixelFormat f0, fR = PIX_FMT_NONE;
- char buf[256];
-
- fprintf(stderr, "get_format ****\n");
- while (fmt[i] != PIX_FMT_NONE /* && ff_is_hwaccel_pix_fmt(fmt[i]) */) {
- f0 = fmt[i];
- if(fR==PIX_FMT_NONE && !my_is_hwaccel_pix_fmt(f0)) {
- fR = f0;
- }
- sp_av_get_pix_fmt_string(buf, sizeof(buf), f0);
- fprintf(stderr, "get_format %d: %d - %s - %s\n", i, f0, sp_av_get_pix_fmt_name(f0), buf);
- ++i;
- }
- fprintf(stderr, "get_format %d - %s *** \n", fR, sp_av_get_pix_fmt_name(fR));
- fflush(NULL);
- return fR;
-}
-#endif
-
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getAvUtilVersion0
- (JNIEnv *env, jclass clazz) {
- return (jint) sp_avutil_version();
-}
-
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getAvFormatVersion0
- (JNIEnv *env, jclass clazz) {
- return (jint) sp_avformat_version();
-}
-
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getAvCodecVersion0
- (JNIEnv *env, jclass clazz) {
- return (jint) sp_avcodec_version();
-}
-
-JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_initIDs0
- (JNIEnv *env, jclass clazz)
-{
- JoglCommon_init(env);
-
- jclass c;
- if (ffmpegMediaPlayerClazz != NULL) {
- return;
- }
-
- c = (*env)->FindClass(env, ClazzNameFFMPEGMediaPlayer);
- if(NULL==c) {
- JoglCommon_FatalError(env, "JOGL FFMPEG: can't find %s", ClazzNameFFMPEGMediaPlayer);
- }
- ffmpegMediaPlayerClazz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==ffmpegMediaPlayerClazz) {
- JoglCommon_FatalError(env, "JOGL FFMPEG: can't use %s", ClazzNameFFMPEGMediaPlayer);
- }
-
- jni_mid_updateAttributes1 = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "updateAttributes", "(IIIIIFIILjava/lang/String;Ljava/lang/String;)V");
- jni_mid_updateAttributes2 = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "updateAttributes2", "(IIIIIIIIII)V");
-
- if(jni_mid_updateAttributes1 == NULL ||
- jni_mid_updateAttributes2 == NULL) {
- return JNI_FALSE;
- }
- return JNI_TRUE;
-}
-
-JNIEXPORT jlong JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_createInstance0
- (JNIEnv *env, jobject instance, jboolean verbose)
-{
- FFMPEGToolBasicAV_t * pAV = calloc(1, sizeof(FFMPEGToolBasicAV_t));
- if(NULL==pAV) {
- JoglCommon_throwNewRuntimeException(env, "Couldn't alloc instance");
- return 0;
- }
- // Register all formats and codecs
- sp_av_register_all();
- // Network too ..
- if(HAS_FUNC(sp_avformat_network_init)) {
- sp_avformat_network_init();
- }
-
- pAV->verbose = verbose;
- pAV->vid=-1;
- pAV->aid=-1;
-
- return (jlong) (intptr_t) pAV;
-}
-
-JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_destroyInstance0
- (JNIEnv *env, jobject instance, jlong ptr)
-{
- FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
- if (pAV != NULL) {
- // stop assumed ..
- freeInstance(pAV);
- }
-}
-
-JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_setStream0
- (JNIEnv *env, jobject instance, jlong ptr, jstring jURL, jint vid, jint aid)
-{
- int res, i;
- jboolean iscopy;
- FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)(intptr_t)ptr;
-
- if (pAV == NULL) {
- JoglCommon_throwNewRuntimeException(env, "NULL AV ptr");
- return;
- }
-
- pAV->pFormatCtx = sp_avformat_alloc_context();
-
- // Open video file
- const char *urlPath = (*env)->GetStringUTFChars(env, jURL, &iscopy);
- res = sp_avformat_open_input(&pAV->pFormatCtx, urlPath, NULL, NULL);
- if(res != 0) {
- (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
- JoglCommon_throwNewRuntimeException(env, "Couldn't open URL");
- return;
- }
-
- // Retrieve detailed stream information
- if(HAS_FUNC(sp_avformat_find_stream_info)) {
- if(sp_avformat_find_stream_info(pAV->pFormatCtx, NULL)<0) {
- (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
- JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information");
- return;
- }
- } else {
- if(sp_av_find_stream_info(pAV->pFormatCtx)<0) {
- (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
- JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information");
- return;
- }
- }
-
- if(pAV->verbose) {
- // Dump information about file onto standard error
- sp_av_dump_format(pAV->pFormatCtx, 0, urlPath, JNI_FALSE);
- }
- (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
- // FIXME: Libav Binary compatibility! JAU01
- if (pAV->pFormatCtx->duration != AV_NOPTS_VALUE) {
- pAV->duration = pAV->pFormatCtx->duration / AV_TIME_BASE_MSEC;
- }
- if (pAV->pFormatCtx->start_time != AV_NOPTS_VALUE) {
- pAV->start_time = pAV->pFormatCtx->start_time / AV_TIME_BASE_MSEC;
- }
- if (pAV->pFormatCtx->bit_rate) {
- pAV->bps_stream = pAV->pFormatCtx->bit_rate;
- }
-
- fprintf(stderr, "Streams: %d\n", pAV->pFormatCtx->nb_streams); // JAU
-
- // Find the first audio and video stream, or the one matching vid
- // FIXME: Libav Binary compatibility! JAU01
- for(i=0; ( -1==pAV->aid || -1==pAV->vid ) && i<pAV->pFormatCtx->nb_streams; i++) {
- AVStream *st = pAV->pFormatCtx->streams[i];
- fprintf(stderr, "Stream: %d: is-video %d, is-audio %d\n", i, (AVMEDIA_TYPE_VIDEO == st->codec->codec_type), AVMEDIA_TYPE_AUDIO == st->codec->codec_type); // JAU
- if(AVMEDIA_TYPE_VIDEO == st->codec->codec_type) {
- if(-1==pAV->vid && (-1==vid || vid == i) ) {
- pAV->pVStream = st;
- pAV->vid=i;
- }
- } else if(AVMEDIA_TYPE_AUDIO == st->codec->codec_type) {
- if(-1==pAV->aid && (-1==aid || aid == i) ) {
- pAV->pAStream = st;
- pAV->aid=i;
- }
- }
- }
-
- fprintf(stderr, "Found vid %d, aid %d\n", pAV->vid, pAV->aid); // JAU
-
- if(0<=pAV->aid) {
- // Get a pointer to the codec context for the audio stream
- // FIXME: Libav Binary compatibility! JAU01
- pAV->pACodecCtx=pAV->pAStream->codec;
-
- // FIXME: Libav Binary compatibility! JAU01
- if (pAV->pACodecCtx->bit_rate) {
- pAV->bps_audio = pAV->pACodecCtx->bit_rate;
- }
- sp_avcodec_string(pAV->acodec, sizeof(pAV->acodec), pAV->pACodecCtx, 0);
-
- // Find the decoder for the audio stream
- pAV->pACodec=sp_avcodec_find_decoder(pAV->pACodecCtx->codec_id);
- if(pAV->pACodec==NULL) {
- JoglCommon_throwNewRuntimeException(env, "Couldn't find audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec);
- return;
- }
-
- // Open codec
- if(HAS_FUNC(sp_avcodec_open2)) {
- res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL);
- } else {
- res = sp_avcodec_open(pAV->pACodecCtx, pAV->pACodec);
- }
- if(res<0) {
- JoglCommon_throwNewRuntimeException(env, "Couldn't open audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec);
- return;
- }
-
- // Allocate audio frames
- // FIXME: Libav Binary compatibility! JAU01
- pAV->aSampleRate = pAV->pACodecCtx->sample_rate;
- pAV->aChannels = pAV->pACodecCtx->channels;
- pAV->aFrameSize = pAV->pACodecCtx->frame_size;
- pAV->aSampleFmt = pAV->pACodecCtx->sample_fmt;
- pAV->pAFrame=sp_avcodec_alloc_frame();
- if(pAV->pAFrame==NULL) {
- JoglCommon_throwNewRuntimeException(env, "Couldn't alloc audio frame");
- return;
- }
- }
-
- if(0<=pAV->vid) {
- // Get a pointer to the codec context for the video stream
- // FIXME: Libav Binary compatibility! JAU01
- pAV->pVCodecCtx=pAV->pVStream->codec;
- #if 0
- pAV->pVCodecCtx->get_format = my_get_format;
- #endif
-
- if (pAV->pVCodecCtx->bit_rate) {
- // FIXME: Libav Binary compatibility! JAU01
- pAV->bps_video = pAV->pVCodecCtx->bit_rate;
- }
- sp_avcodec_string(pAV->vcodec, sizeof(pAV->vcodec), pAV->pVCodecCtx, 0);
-
- // Find the decoder for the video stream
- pAV->pVCodec=sp_avcodec_find_decoder(pAV->pVCodecCtx->codec_id);
- if(pAV->pVCodec==NULL) {
- JoglCommon_throwNewRuntimeException(env, "Couldn't find video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec);
- return;
- }
-
- // Open codec
- if(HAS_FUNC(sp_avcodec_open2)) {
- res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL);
- } else {
- res = sp_avcodec_open(pAV->pVCodecCtx, pAV->pVCodec);
- }
- if(res<0) {
- JoglCommon_throwNewRuntimeException(env, "Couldn't open video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec);
- return;
- }
-
- // Hack to correct wrong frame rates that seem to be generated by some codecs
- // FIXME: Libav Binary compatibility! JAU01
- if(pAV->pVCodecCtx->time_base.num>1000 && pAV->pVCodecCtx->time_base.den==1) {
- pAV->pVCodecCtx->time_base.den=1000;
- }
- // FIXME: Libav Binary compatibility! JAU01
- pAV->fps = my_av_q2f(pAV->pVStream->avg_frame_rate);
-
- // Allocate video frames
- // FIXME: Libav Binary compatibility! JAU01
- pAV->vPixFmt = pAV->pVCodecCtx->pix_fmt;
- {
- AVPixFmtDescriptor pixDesc = sp_av_pix_fmt_descriptors[pAV->vPixFmt];
- pAV->vBitsPerPixel = sp_av_get_bits_per_pixel(&pixDesc);
- pAV->vBufferPlanes = my_getPlaneCount(&pixDesc);
- }
- pAV->pVFrame=sp_avcodec_alloc_frame();
- if( pAV->pVFrame == NULL ) {
- JoglCommon_throwNewRuntimeException(env, "Couldn't alloc video frame");
- return;
- }
- res = sp_avcodec_default_get_buffer(pAV->pVCodecCtx, pAV->pVFrame);
- if(0==res) {
- const int32_t bytesPerPixel = ( pAV->vBitsPerPixel + 7 ) / 8 ;
- if(1 == pAV->vBufferPlanes) {
- pAV->vBytesPerPixelPerPlane = bytesPerPixel;
- } else {
- pAV->vBytesPerPixelPerPlane = 1;
- }
- for(i=0; i<3; i++) {
- // FIXME: Libav Binary compatibility! JAU01
- pAV->vLinesize[i] = pAV->pVFrame->linesize[i];
- pAV->vTexWidth[i] = pAV->vLinesize[i] / pAV->vBytesPerPixelPerPlane ;
- }
- sp_avcodec_default_release_buffer(pAV->pVCodecCtx, pAV->pVFrame);
- } else {
- JoglCommon_throwNewRuntimeException(env, "Couldn't peek video buffer dimension");
- return;
- }
- }
- pAV->vPTS=0;
- pAV->aPTS=0;
- _updateJavaAttributes(env, instance, pAV);
-}
-
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNextPacket0
- (JNIEnv *env, jobject instance, jlong ptr, jlong jProcAddrGLTexSubImage2D, jint texTarget, jint texFmt, jint texType)
-{
- FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
- PFNGLTEXSUBIMAGE2DPROC procAddrGLTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) (intptr_t)jProcAddrGLTexSubImage2D;
-
- jint res = 0; // 1 - audio, 2 - video
- AVPacket packet;
- int frameFinished;
-
- if(sp_av_read_frame(pAV->pFormatCtx, &packet)>=0) {
- /**
- if(packet.stream_index==pAV->aid) {
- // Decode audio frame
- if(NULL == pAV->pAFrame) {
- sp_av_free_packet(&packet);
- return res;
- }
-
- int new_packet = 1;
- int len1;
- int flush_complete = 0;
- int data_size = 0;
- while (packet.size > 0 || (!packet.data && new_packet)) {
- new_packet = 0;
- if (flush_complete) {
- break;
- }
- if(HAS_FUNC(sp_avcodec_decode_audio4)) {
- len1 = sp_avcodec_decode_audio4(pAV->pVCodecCtx, pAV->pAFrame, &frameFinished, &packet);
- } else {
- len1 = sp_avcodec_decode_audio3(pAV->pVCodecCtx, int16_t *samples, int *frame_size_ptr, &frameFinished, &packet);
- }
- if (len1 < 0) {
- // if error, we skip the frame
- packet.size = 0;
- break;
- }
- packet.data += len1;
- packet.size -= len1;
-
- if (!frameFinished) {
- // stop sending empty packets if the decoder is finished
- if (!packet.data && pAV->pVCodecCtx->codec->capabilities & CODEC_CAP_DELAY) {
- flush_complete = 1;
- }
- continue;
- }
-
- int32_t pts = pAV->pAFrame->pkt_pts * my_av_q2i32(1000, pAV->pAStream->time_base);
- pAV->aPTS += ( data_size * 1000 ) / (2 * pAV->pVCodecCtx->channels * pAV->pVCodecCtx->sample_rate);
- printf("A pts %d - %d\n", pts, pAV->aPTS);
- res = 1;
- }
- } else */ if(packet.stream_index==pAV->vid) {
- // Decode video frame
- if(NULL == pAV->pVFrame) {
- sp_av_free_packet(&packet);
- return res;
- }
- sp_avcodec_decode_video2(pAV->pVCodecCtx, pAV->pVFrame, &frameFinished, &packet);
-
- // Did we get a video frame?
- if(frameFinished)
- {
- res = 2;
- // FIXME: Libav Binary compatibility! JAU01
- const AVRational time_base = pAV->pVStream->time_base;
- const int64_t pts = pAV->pVFrame->pkt_pts;
- if(AV_NOPTS_VALUE != pts) { // discard invalid PTS ..
- pAV->vPTS = pts * my_av_q2i32(1000, time_base);
-
- #if 0
- printf("PTS %d = %ld * ( ( 1000 * %ld ) / %ld ) '1000 * time_base', time_base = %lf\n",
- pAV->vPTS, pAV->pVFrame->pkt_pts, time_base.num, time_base.den, (time_base.num/(double)time_base.den));
- #endif
- }
-
- #if 0
- printf("tex2D codec %dx%d - frame %dx%d - width %d tex / %d linesize, pixfmt 0x%X, texType 0x%x, texTarget 0x%x\n",
- pAV->pVCodecCtx->width, pAV->pVCodecCtx->height,
- pAV->pVFrame->width, pAV->pVFrame->height, pAV->vTexWidth[0], pAV->pVFrame->linesize[0],
- texFmt, texType, texTarget);
- #endif
-
- // 1st plane or complete packed frame
- // FIXME: Libav Binary compatibility! JAU01
- procAddrGLTexSubImage2D(texTarget, 0,
- 0, 0,
- pAV->vTexWidth[0], pAV->pVCodecCtx->height,
- texFmt, texType, pAV->pVFrame->data[0]);
-
- if(pAV->vPixFmt == PIX_FMT_YUV420P) {
- // U plane
- // FIXME: Libav Binary compatibility! JAU01
- procAddrGLTexSubImage2D(texTarget, 0,
- pAV->pVCodecCtx->width, 0,
- pAV->vTexWidth[1], pAV->pVCodecCtx->height/2,
- texFmt, texType, pAV->pVFrame->data[1]);
- // V plane
- // FIXME: Libav Binary compatibility! JAU01
- procAddrGLTexSubImage2D(texTarget, 0,
- pAV->pVCodecCtx->width, pAV->pVCodecCtx->height/2,
- pAV->vTexWidth[2], pAV->pVCodecCtx->height/2,
- texFmt, texType, pAV->pVFrame->data[2]);
- } // FIXME: Add more planar formats !
- }
- }
-
- // Free the packet that was allocated by av_read_frame
- sp_av_free_packet(&packet);
- }
- return res;
-}
-
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_seek0
- (JNIEnv *env, jobject instance, jlong ptr, jint pos1)
-{
- FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
- int64_t pos0 = pAV->vPTS;
- int64_t pts0 = pAV->pVFrame->pkt_pts;
- int64_t pts1 = (int64_t) pos1 / my_av_q2i32(1000, pAV->pVStream->time_base);
- int flags = 0;
- if(pos1 < pos0) {
- flags |= AVSEEK_FLAG_BACKWARD;
- }
- fprintf(stderr, "SEEK: pre : u %ld, p %ld -> u %ld, p %ld\n", pos0, pts0, pos1, pts1);
- sp_av_seek_frame(pAV->pFormatCtx, pAV->vid, pts1, flags);
- pAV->vPTS = pAV->pVFrame->pkt_pts * my_av_q2i32(1000, pAV->pVStream->time_base);
- fprintf(stderr, "SEEK: post : u %ld, p %ld\n", pAV->vPTS, pAV->pVFrame->pkt_pts);
- return pAV->vPTS;
-}
-
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getVideoPTS0
- (JNIEnv *env, jobject instance, jlong ptr)
-{
- FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
- return pAV->vPTS;
-}
-
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_getAudioPTS0
- (JNIEnv *env, jobject instance, jlong ptr)
-{
- FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
- return pAV->aPTS;
-}
-
diff --git a/src/jogl/native/macosx/MacOSXCustomCGLCode.c b/src/jogl/native/macosx/MacOSXCustomCGLCode.c
index f8b7a800f..75896c3a2 100644
--- a/src/jogl/native/macosx/MacOSXCustomCGLCode.c
+++ b/src/jogl/native/macosx/MacOSXCustomCGLCode.c
@@ -2,7 +2,7 @@
#include <assert.h>
-#include </usr/include/machine/types.h>
+#include <machine/types.h>
#include "macosx-window-system.h"
void CGLQueryPixelFormat(CGLPixelFormatObj fmt, int* iattrs, int niattrs, int* ivalues) {
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
index f3495efff..d83ddbc22 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
@@ -1,8 +1,25 @@
#import "MacOSXWindowSystemInterface.h"
#import <QuartzCore/QuartzCore.h>
#import <pthread.h>
+#import "NativeWindowProtocols.h"
#include "timespec.h"
+#import <OpenGL/glext.h>
+
+/**
+ * Partial include of gl3.h - which we can only expect and use
+ * in case of a GL3 core context at runtime.
+ * Otherwise we would need to have 2 modules, one including GL2
+ * and one inclusing GL3 headers.
+ */
+#ifndef GL_ARB_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+extern void glBindVertexArray (GLuint array);
+extern void glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+extern void glGenVertexArrays (GLsizei n, GLuint *arrays);
+extern GLboolean glIsVertexArray (GLuint array);
+#endif
+
//
// CADisplayLink only available on iOS >= 3.1, sad, since it's convenient.
// Use CVDisplayLink otherwise.
@@ -25,6 +42,8 @@
//
// #define DBG_PERF 1
+// #define DBG_LIFECYCLE 1
+
/**
* Capture setView(NULL), which produces a 'invalid drawable' message
*
@@ -36,6 +55,10 @@
- (id)initWithFormat:(NSOpenGLPixelFormat *)format shareContext:(NSOpenGLContext *)share;
- (void)setView:(NSView *)view;
- (void)update;
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+#endif
- (void)dealloc;
@end
@@ -44,49 +67,85 @@
- (id)initWithFormat:(NSOpenGLPixelFormat *)format shareContext:(NSOpenGLContext *)share
{
- DBG_PRINT("MyNSOpenGLContext.initWithFormat.0: format %p, share %p\n", format, share);
+ DBG_PRINT("MyNSOpenGLContext::initWithFormat.0: format %p, share %p\n", format, share);
MyNSOpenGLContext * o = [super initWithFormat:format shareContext:share];
- DBG_PRINT("MyNSOpenGLContext.initWithFormat.X: new %p\n", o);
+ DBG_PRINT("MyNSOpenGLContext::initWithFormat.X: new %p\n", o);
return o;
}
- (void)setView:(NSView *)view
{
- DBG_PRINT("MyNSOpenGLContext.setView: this.0 %p, view %p\n", self, view);
+ DBG_PRINT("MyNSOpenGLContext::setView: this.0 %p, view %p\n", self, view);
+ // NSLog(@"MyNSOpenGLContext::setView: %@",[NSThread callStackSymbols]);
if(NULL != view) {
[super setView:view];
+ } else {
+ [self clearDrawable];
}
- DBG_PRINT("MyNSOpenGLContext.setView.X\n");
+ DBG_PRINT("MyNSOpenGLContext::setView.X\n");
}
- (void)update
{
- DBG_PRINT("MyNSOpenGLContext.update: this.0 %p, view %p\n", self, [self view]);
+ DBG_PRINT("MyNSOpenGLContext::update: this.0 %p, view %p\n", self, [self view]);
[super update];
- DBG_PRINT("MyNSOpenGLContext.update.X\n");
+ DBG_PRINT("MyNSOpenGLContext::update.X\n");
}
+#ifdef DBG_LIFECYCLE
+
+- (id)retain
+{
+ DBG_PRINT("MyNSOpenGLContext::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyNSOpenGLContext::retain: %@",[NSThread callStackSymbols]);
+ id o = [super retain];
+ DBG_PRINT("MyNSOpenGLContext::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+ return o;
+}
+
+- (oneway void)release
+{
+ DBG_PRINT("MyNSOpenGLContext::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [super release];
+ // DBG_PRINT("MyNSOpenGLContext::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+#endif
+
- (void)dealloc
{
- DBG_PRINT("MyNSOpenGLContext.dealloc: this.0 %p\n", self);
+ DBG_PRINT("MyNSOpenGLContext::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyNSOpenGLContext::dealloc: %@",[NSThread callStackSymbols]);
+
+ [self clearDrawable];
+
[super dealloc];
- DBG_PRINT("MyNSOpenGLContext.dealloc.X: %p\n", self);
+ DBG_PRINT("MyNSOpenGLContext::dealloc.X\n");
}
@end
-@interface MyNSOpenGLLayer: NSOpenGLLayer
+@interface MyNSOpenGLLayer: NSOpenGLLayer <NWDedicatedFrame>
{
@private
GLfloat gl_texCoords[8];
+ NSOpenGLContext* glContext;
+ Bool isGLEnabled;
@protected
- NSOpenGLContext* parentCtx;
+ GLuint gl3ShaderProgramName;
+ GLuint vboBufVert;
+ GLuint vboBufTexCoord;
+ GLint vertAttrLoc;
+ GLint texCoordAttrLoc;
NSOpenGLPixelFormat* parentPixelFmt;
+ int texWidth;
+ int texHeight;
+ volatile Bool dedicatedFrameSet;
+ volatile CGRect dedicatedFrame;
volatile NSOpenGLPixelBuffer* pbuffer;
volatile GLuint textureID;
- volatile int texWidth;
- volatile int texHeight;
+ volatile NSOpenGLPixelBuffer* newPBuffer;
#ifdef HAS_CADisplayLink
CADisplayLink* displayLink;
#else
@@ -101,35 +160,52 @@
pthread_mutex_t renderLock;
pthread_cond_t renderSignal;
volatile Bool shallDraw;
- volatile int newTexWidth;
- volatile int newTexHeight;
}
- (id) setupWithContext: (NSOpenGLContext*) parentCtx
+ gl3ShaderProgramName: (GLuint) gl3ShaderProgramName
pixelFormat: (NSOpenGLPixelFormat*) pfmt
pbuffer: (NSOpenGLPixelBuffer*) p
texIDArg: (GLuint) texID
opaque: (Bool) opaque
texWidth: (int) texWidth
- texHeight: (int) texHeight;
+ texHeight: (int) texHeight
+ winWidth: (int)winWidth
+ winHeight: (int)winHeight;
-- (Bool) validateTexSizeWithNewSize;
-- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight;
-- (void) setTextureID: (int) _texID;
-
-- (void) validatePBuffer: (NSOpenGLPixelBuffer*) p;
-
-- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat;
+- (void)releaseLayer;
+- (void)deallocPBuffer;
- (void)disableAnimation;
- (void)pauseAnimation:(Bool)pause;
-- (void)deallocPBuffer;
-- (void)releaseLayer;
-- (void)dealloc;
- (void)setSwapInterval:(int)interval;
- (void)tick;
- (void)waitUntilRenderSignal: (long) to_micros;
- (Bool)isGLSourceValid;
+- (void) setGLEnabled: (Bool) enable;
+- (Bool) validateTexSize: (int)newTexWidth height:(int)newTexHeight;
+- (void) setTextureID: (int) _texID;
+
+- (Bool) isSamePBuffer: (NSOpenGLPixelBuffer*) p;
+- (void) setNewPBuffer: (NSOpenGLPixelBuffer*)p;
+- (void) applyNewPBuffer;
+
+- (void)setDedicatedFrame:(CGRect)frame quirks:(int)quirks; // @NWDedicatedFrame
+- (void) setFrame:(CGRect) frame;
+- (id<CAAction>)actionForKey:(NSString *)key ;
+- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask;
+- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat;
+- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp;
+- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp;
+
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+#endif
+- (void)dealloc;
+
@end
#ifndef HAS_CADisplayLink
@@ -168,13 +244,16 @@ static const GLfloat gl_verts[] = {
@implementation MyNSOpenGLLayer
-- (id) setupWithContext: (NSOpenGLContext*) _parentCtx
+- (id) setupWithContext: (NSOpenGLContext*) parentCtx
+ gl3ShaderProgramName: (GLuint) _gl3ShaderProgramName
pixelFormat: (NSOpenGLPixelFormat*) _parentPixelFmt
pbuffer: (NSOpenGLPixelBuffer*) p
texIDArg: (GLuint) texID
opaque: (Bool) opaque
texWidth: (int) _texWidth
- texHeight: (int) _texHeight;
+ texHeight: (int) _texHeight
+ winWidth: (int) _winWidth
+ winHeight: (int) _winHeight
{
pthread_mutexattr_t renderLockAttr;
pthread_mutexattr_init(&renderLockAttr);
@@ -188,17 +267,35 @@ static const GLfloat gl_verts[] = {
gl_texCoords[i] = 0.0f;
}
}
- parentCtx = _parentCtx;
- parentPixelFmt = _parentPixelFmt;
+ /**
+ * Set via
+ * - OSXUtil_SetCALayerPixelScale0
+ * - OSXUtil_AddCASublayer0
+NS_DURING
+ // Available >= 10.7
+ [self setContentsScale: (CGFloat)_texWidth/(CGFloat)_winWidth];
+NS_HANDLER
+NS_ENDHANDLER
+ */
+
+ parentPixelFmt = [_parentPixelFmt retain]; // until destruction
+ glContext = [[MyNSOpenGLContext alloc] initWithFormat:parentPixelFmt shareContext:parentCtx];
+ gl3ShaderProgramName = _gl3ShaderProgramName;
+ vboBufVert = 0;
+ vboBufTexCoord = 0;
+ vertAttrLoc = 0;
+ texCoordAttrLoc = 0;
swapInterval = 1; // defaults to on (as w/ new GL profiles)
swapIntervalCounter = 0;
timespec_now(&lastWaitTime);
shallDraw = NO;
- newTexWidth = _texWidth;
- newTexHeight = _texHeight;
- [self validateTexSizeWithNewSize];
+ isGLEnabled = YES;
+ dedicatedFrameSet = NO;
+ dedicatedFrame = CGRectMake(0, 0, _winWidth, _winHeight);
+ [self validateTexSize: _texWidth height:_texHeight];
[self setTextureID: texID];
+ newPBuffer = NULL;
pbuffer = p;
if(NULL != pbuffer) {
[pbuffer retain];
@@ -232,10 +329,11 @@ static const GLfloat gl_verts[] = {
}
}
if(NULL != displayLink) {
- cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [parentCtx CGLContextObj], [parentPixelFmt CGLPixelFormatObj]);
+ CVReturn cvres;
+ DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.1: setup DisplayLink %p\n", displayLink);
+ cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [glContext CGLContextObj], [parentPixelFmt CGLPixelFormatObj]);
if(kCVReturnSuccess != cvres) {
DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres);
- displayLink = NULL;
}
}
if(NULL != displayLink) {
@@ -257,34 +355,36 @@ static const GLfloat gl_verts[] = {
#ifdef VERBOSE_ON
CGRect lRect = [self bounds];
if(NULL != pbuffer) {
- DBG_PRINT("MyNSOpenGLLayer::init (pbuffer) %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d, bounds: %lf/%lf %lfx%lf (refcnt %d)\n",
- self, parentCtx, parentPixelFmt, pbuffer, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight,
- lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]);
+ DBG_PRINT("MyNSOpenGLLayer::init (pbuffer) %p, pctx %p, pfmt %p, pbuffer %p, ctx %p, opaque %d, pbuffer %dx%d -> tex %dx%d, bounds: %lf/%lf %lfx%lf, displayLink %p (refcnt %d)\n",
+ self, parentCtx, parentPixelFmt, pbuffer, glContext, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight,
+ lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, displayLink, (int)[self retainCount]);
} else {
- DBG_PRINT("MyNSOpenGLLayer::init (texture) %p, ctx %p, pfmt %p, opaque %d, tex[id %d, %dx%d], bounds: %lf/%lf %lfx%lf (refcnt %d)\n",
- self, parentCtx, parentPixelFmt, opaque, (int)textureID, texWidth, texHeight,
- lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]);
+ DBG_PRINT("MyNSOpenGLLayer::init (texture) %p, pctx %p, pfmt %p, ctx %p, opaque %d, tex[id %d, %dx%d], bounds: %lf/%lf %lfx%lf, displayLink %p (refcnt %d)\n",
+ self, parentCtx, parentPixelFmt, glContext, opaque, (int)textureID, texWidth, texHeight,
+ lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, displayLink, (int)[self retainCount]);
}
#endif
return self;
}
-- (Bool) validateTexSizeWithNewSize
+- (void) setGLEnabled: (Bool) enable
{
- return [self validateTexSize: newTexWidth texHeight: newTexHeight];
+ DBG_PRINT("MyNSOpenGLLayer::setGLEnabled: %p, %d -> %d\n", self, (int)isGLEnabled, (int)enable);
+ isGLEnabled = enable;
}
-- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight
+- (Bool) validateTexSize: (int)newTexWidth height:(int)newTexHeight
{
- if(_texHeight != texHeight || _texWidth != texWidth) {
- texWidth = _texWidth;
- texHeight = _texHeight;
- CGRect lRect = [self bounds];
- lRect.origin.x = 0;
- lRect.origin.y = 0;
- lRect.size.width = texWidth;
- lRect.size.height = texHeight;
- [self setFrame: lRect];
+ Bool changed;
+
+ if( newTexHeight != texHeight || newTexWidth != texWidth ) {
+ #ifdef VERBOSE_ON
+ const int oldTexWidth = texWidth;
+ const int oldTexHeight = texHeight;
+ #endif
+ texWidth = newTexWidth;
+ texHeight = newTexHeight;
+ changed = YES;
GLfloat texCoordWidth, texCoordHeight;
if(NULL != pbuffer) {
@@ -306,10 +406,20 @@ static const GLfloat gl_verts[] = {
gl_texCoords[5] = texCoordHeight;
gl_texCoords[4] = texCoordWidth;
gl_texCoords[6] = texCoordWidth;
- return YES;
+ #ifdef VERBOSE_ON
+NS_DURING
+ // Available >= 10.7
+ DBG_PRINT("MyNSOpenGLLayer::validateTexSize %p: tex %dx%d -> %dx%d, dedicatedFrame set:%d %lf/%lf %lfx%lf scale %lf\n",
+ self, oldTexWidth, oldTexHeight, newTexWidth, newTexHeight,
+ dedicatedFrameSet, dedicatedFrame.origin.x, dedicatedFrame.origin.y, dedicatedFrame.size.width, dedicatedFrame.size.height,
+ [self contentsScale]);
+NS_HANDLER
+NS_ENDHANDLER
+ #endif
} else {
- return NO;
+ changed = NO;
}
+ return changed;
}
- (void) setTextureID: (int) _texID
@@ -317,58 +427,32 @@ static const GLfloat gl_verts[] = {
textureID = _texID;
}
-- (void) validatePBuffer: (NSOpenGLPixelBuffer*) p
+- (Bool) isSamePBuffer: (NSOpenGLPixelBuffer*) p
{
- if( pbuffer != p ) {
- DBG_PRINT("MyNSOpenGLLayer::validatePBuffer.0 %p, pbuffer %p, (refcnt %d)\n", self, p, (int)[self retainCount]);
-
- SYNC_PRINT("{PB-nil}");
-
- [self deallocPBuffer];
-
- pbuffer = p;
- if(NULL != pbuffer) {
- [pbuffer retain];
- }
- [self setTextureID: 0];
-
- shallDraw = NO;
- }
+ return pbuffer == p || newPBuffer == p;
}
-/**
-- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask
+- (void)setNewPBuffer: (NSOpenGLPixelBuffer*)p
{
- DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask: %p (refcnt %d) - parent-pfmt %p -> new-pfmt %p\n",
- self, (int)[self retainCount], parentPixelFmt, parentPixelFmt);
- return parentPixelFmt;
-} */
-
-- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat
-{
- DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.0: %p (refcnt %d) - pfmt %p, parent %p\n",
- self, (int)[self retainCount], pixelFormat, parentCtx);
- NSOpenGLContext * nctx = [[MyNSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:parentCtx];
- DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.X: new-ctx %p\n", nctx);
- return nctx;
+ SYNC_PRINT("<NP-S %p -> %p>", pbuffer, p);
+ newPBuffer = p;
+ [newPBuffer retain];
}
-- (void)disableAnimation
+- (void) applyNewPBuffer
{
- DBG_PRINT("MyNSOpenGLLayer::disableAnimation: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink);
- pthread_mutex_lock(&renderLock);
- [self setAsynchronous: NO];
- if(NULL != displayLink) {
-#ifdef HAS_CADisplayLink
- [displayLink setPaused: YES];
- [displayLink release];
-#else
- CVDisplayLinkStop(displayLink);
- CVDisplayLinkRelease(displayLink);
-#endif
- displayLink = NULL;
+ if( NULL != newPBuffer ) { // volatile OK
+ SYNC_PRINT("<NP-A %p -> %p>", pbuffer, newPBuffer);
+
+ if( 0 != textureID ) {
+ glDeleteTextures(1, (GLuint *)&textureID);
+ [self setTextureID: 0];
+ }
+ [pbuffer release];
+
+ pbuffer = newPBuffer;
+ newPBuffer = NULL;
}
- pthread_mutex_unlock(&renderLock);
}
- (void)deallocPBuffer
@@ -381,71 +465,157 @@ static const GLfloat gl_verts[] = {
DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (with ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)textureID);
if( 0 != textureID ) {
- glDeleteTextures(1, &textureID);
+ glDeleteTextures(1, (GLuint *)&textureID);
+ [self setTextureID: 0];
+ }
+ if(NULL != pbuffer) {
+ [pbuffer release];
+ pbuffer = NULL;
+ }
+ if(NULL != newPBuffer) {
+ [newPBuffer release];
+ newPBuffer = NULL;
}
- [pbuffer release];
[context clearDrawable];
} else {
DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (w/o ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)textureID);
}
- pbuffer = NULL;
- [self setTextureID: 0];
}
}
+- (void)disableAnimation
+{
+ DBG_PRINT("MyNSOpenGLLayer::disableAnimation.0: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink);
+ [self setAsynchronous: NO];
+ if(NULL != displayLink) {
+#ifdef HAS_CADisplayLink
+ [displayLink setPaused: YES];
+ [displayLink release];
+#else
+ CVDisplayLinkStop(displayLink);
+ CVDisplayLinkRelease(displayLink);
+#endif
+ displayLink = NULL;
+ }
+ DBG_PRINT("MyNSOpenGLLayer::disableAnimation.X: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink);
+}
+
- (void)releaseLayer
{
DBG_PRINT("MyNSOpenGLLayer::releaseLayer.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
- pthread_mutex_lock(&renderLock);
+ [self setGLEnabled: NO];
[self disableAnimation];
+ pthread_mutex_lock(&renderLock);
[self deallocPBuffer];
- [[self openGLContext] release];
- [self release];
- DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ if( NULL != glContext ) {
+ [glContext release];
+ glContext = NULL;
+ }
+ if( NULL != parentPixelFmt ) {
+ [parentPixelFmt release];
+ parentPixelFmt = NULL;
+ }
pthread_mutex_unlock(&renderLock);
+ [self release];
+ DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p\n", self);
}
+#ifdef DBG_LIFECYCLE
+
+- (id)retain
+{
+ DBG_PRINT("MyNSOpenGLLayer::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyNSOpenGLLayer::retain: %@",[NSThread callStackSymbols]);
+ id o = [super retain];
+ DBG_PRINT("MyNSOpenGLLayer::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+ return o;
+}
+
+- (oneway void)release
+{
+ DBG_PRINT("MyNSOpenGLLayer::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyNSOpenGLLayer::release: %@",[NSThread callStackSymbols]);
+ [super release];
+ // DBG_PRINT("MyNSOpenGLLayer::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+#endif
+
- (void)dealloc
{
DBG_PRINT("MyNSOpenGLLayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
// NSLog(@"MyNSOpenGLLayer::dealloc: %@",[NSThread callStackSymbols]);
-
- pthread_mutex_lock(&renderLock);
[self disableAnimation];
+ pthread_mutex_lock(&renderLock);
[self deallocPBuffer];
pthread_mutex_unlock(&renderLock);
pthread_cond_destroy(&renderSignal);
pthread_mutex_destroy(&renderLock);
[super dealloc];
- DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self);
+ // DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self);
}
- (Bool)isGLSourceValid
{
- return NULL != pbuffer || 0 != textureID ;
+ return NULL != pbuffer || NULL != newPBuffer || 0 != textureID ;
+}
+
+// @NWDedicatedFrame
+- (void)setDedicatedFrame:(CGRect)dFrame quirks:(int)quirks {
+ CGRect lRect = [self frame];
+ Bool dedicatedFramePosSet = 0 != ( NW_DEDICATEDFRAME_QUIRK_POSITION & quirks );
+ Bool dedicatedFrameSizeSet = 0 != ( NW_DEDICATEDFRAME_QUIRK_SIZE & quirks );
+ Bool dedicatedLayoutSet = 0 != ( NW_DEDICATEDFRAME_QUIRK_LAYOUT & quirks );
+ dedicatedFrameSet = dedicatedFramePosSet || dedicatedFrameSizeSet || dedicatedLayoutSet;
+ dedicatedFrame = dFrame;
+
+ DBG_PRINT("MyNSOpenGLLayer::setDedicatedFrame: Quirks [%d, pos %d, size %d, lout %d], %p, texSize %dx%d, %lf/%lf %lfx%lf -> %lf/%lf %lfx%lf\n",
+ quirks, dedicatedFramePosSet, dedicatedFrameSizeSet, dedicatedLayoutSet, self, texWidth, texHeight,
+ lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height,
+ dFrame.origin.x, dFrame.origin.y, dFrame.size.width, dFrame.size.height);
+ (void)lRect; // silence
+
+ if( dedicatedFrameSet ) {
+ [super setFrame: dedicatedFrame];
+ }
}
-- (void)resizeWithOldSuperlayerSize:(CGSize)size
- {
- CGRect lRectS = [[self superlayer] bounds];
+- (void) setFrame:(CGRect) frame {
+ if( dedicatedFrameSet ) {
+ [super setFrame: dedicatedFrame];
+ } else {
+ [super setFrame: frame];
+ }
+}
- DBG_PRINT("MyNSOpenGLLayer::resizeWithOldSuperlayerSize: %p, texSize %dx%d, bounds: %lfx%lf -> %lfx%lf (refcnt %d)\n",
- self, texWidth, texHeight, size.width, size.height, lRectS.size.width, lRectS.size.height, (int)[self retainCount]);
+- (id<CAAction>)actionForKey:(NSString *)key
+{
+ DBG_PRINT("MyNSOpenGLLayer::actionForKey.0 %p key %s -> NIL\n", self, [key UTF8String]);
+ return nil;
+ // return [super actionForKey: key];
+}
- newTexWidth = lRectS.size.width;
- newTexHeight = lRectS.size.height;
- shallDraw = YES;
- SYNC_PRINT("<SZ %dx%d>", newTexWidth, newTexHeight);
+- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask
+{
+ DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask: %p (refcnt %d) - parent-pfmt %p -> new-pfmt %p\n",
+ self, (int)[self retainCount], parentPixelFmt, parentPixelFmt);
+ // We simply take over ownership of parent PixelFormat until releaseLayer..
+ return parentPixelFmt;
+}
- [super resizeWithOldSuperlayerSize: size];
+- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat
+{
+ DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.0: %p (refcnt %d) - pfmt %p, ctx %p, DisplayLink %p\n",
+ self, (int)[self retainCount], pixelFormat, glContext, displayLink);
+ return glContext;
}
- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
{
- SYNC_PRINT("<? %d>", (int)shallDraw);
- return shallDraw;
+ SYNC_PRINT("<? %d, %d>", (int)shallDraw, (int)isGLEnabled);
+ return shallDraw && isGLEnabled;
}
- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
@@ -455,21 +625,40 @@ static const GLfloat gl_verts[] = {
SYNC_PRINT("<* ");
// NSLog(@"MyNSOpenGLLayer::DRAW: %@",[NSThread callStackSymbols]);
- if( shallDraw && ( NULL != pbuffer || 0 != textureID ) ) {
+ if( isGLEnabled && shallDraw && ( NULL != pbuffer || NULL != newPBuffer || 0 != textureID ) ) {
[context makeCurrentContext];
+ if( NULL != newPBuffer ) { // volatile OK
+ [self applyNewPBuffer];
+ }
+
GLenum textureTarget;
- Bool texSizeChanged = [self validateTexSizeWithNewSize];
+ CGRect texDim = dedicatedFrameSet ? dedicatedFrame : [self bounds];
+ CGFloat _contentsScale = 1;
+NS_DURING
+ // Available >= 10.7
+ _contentsScale = [self contentsScale];
+NS_HANDLER
+NS_ENDHANDLER
+ Bool texSizeChanged = [self validateTexSize: (int)(texDim.size.width * _contentsScale + 0.5f)
+ height:(int)(texDim.size.height * _contentsScale + 0.5f)];
+ if( texSizeChanged ) {
+ [context update];
+ }
if( NULL != pbuffer ) {
if( texSizeChanged && 0 != textureID ) {
- glDeleteTextures(1, &textureID);
+ glDeleteTextures(1, (GLuint *)&textureID);
[self setTextureID: 0];
}
textureTarget = [pbuffer textureTarget];
+ if( 0 != gl3ShaderProgramName ) {
+ glUseProgram(gl3ShaderProgramName);
+ glActiveTexture(GL_TEXTURE0);
+ }
if( 0 == textureID ) {
- glGenTextures(1, &textureID);
+ glGenTextures(1, (GLuint *)&textureID);
glBindTexture(textureTarget, textureID);
glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -478,26 +667,80 @@ static const GLfloat gl_verts[] = {
} else {
glBindTexture(textureTarget, textureID);
}
- [context setTextureImageToPixelBuffer: pbuffer colorBuffer: GL_FRONT];
+ [context setTextureImageToPixelBuffer: (NSOpenGLPixelBuffer*) pbuffer colorBuffer: GL_FRONT];
} else {
+ if( 0 != gl3ShaderProgramName ) {
+ glUseProgram(gl3ShaderProgramName);
+ glActiveTexture(GL_TEXTURE0);
+ }
textureTarget = GL_TEXTURE_2D;
glBindTexture(textureTarget, textureID);
}
- SYNC_PRINT(" %d*>", (int)textureID);
-
- glEnable(textureTarget);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, gl_verts);
- glTexCoordPointer(2, GL_FLOAT, 0, gl_texCoords);
-
- glDrawArrays(GL_QUADS, 0, 4);
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glDisable(textureTarget);
+ SYNC_PRINT(" %d gl3Prog %d/%d*>", (int)textureID, (int)gl3ShaderProgramName, (int)glIsProgram (gl3ShaderProgramName));
+
+ if( 0 == vboBufVert ) { // Once: Init Data and Bind to Pointer
+ if( 0 != gl3ShaderProgramName ) {
+ // Install default VAO as required by GL 3.2 core!
+ GLuint vaoBuf = 0;
+ glGenVertexArrays(1, &vaoBuf);
+ glBindVertexArray(vaoBuf);
+
+ // Set texture-unit 0
+ GLint texUnitLoc = glGetUniformLocation (gl3ShaderProgramName, "mgl_Texture0");
+ glUniform1i (texUnitLoc, 0);
+ }
+ glGenBuffers( 1, &vboBufVert );
+ glBindBuffer( GL_ARRAY_BUFFER, vboBufVert );
+ glBufferData( GL_ARRAY_BUFFER, 4 * 2 * sizeof(GLfloat), gl_verts, GL_STATIC_DRAW);
+ if( 0 != gl3ShaderProgramName ) {
+ vertAttrLoc = glGetAttribLocation( gl3ShaderProgramName, "mgl_Vertex" );
+ glVertexAttribPointer( vertAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL );
+ } else {
+ glVertexPointer(2, GL_FLOAT, 0, NULL);
+ }
+
+ glGenBuffers( 1, &vboBufTexCoord );
+ glBindBuffer( GL_ARRAY_BUFFER, vboBufTexCoord );
+ glBufferData( GL_ARRAY_BUFFER, 4 * 2 * sizeof(GLfloat), gl_texCoords, GL_STATIC_DRAW);
+ if( 0 != gl3ShaderProgramName ) {
+ texCoordAttrLoc = glGetAttribLocation( gl3ShaderProgramName, "mgl_MultiTexCoord" );
+ glVertexAttribPointer( texCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL );
+ } else {
+ glTexCoordPointer(2, GL_FLOAT, 0, NULL);
+ }
+ }
+ if( texSizeChanged ) {
+ glBindBuffer( GL_ARRAY_BUFFER, vboBufTexCoord );
+ glBufferSubData( GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), gl_texCoords);
+ if( 0 != gl3ShaderProgramName ) {
+ glVertexAttribPointer( texCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL );
+ } else {
+ glTexCoordPointer(2, GL_FLOAT, 0, NULL);
+ }
+ }
+ if( 0 != gl3ShaderProgramName ) {
+ glEnableVertexAttribArray( vertAttrLoc );
+ glEnableVertexAttribArray( texCoordAttrLoc );
+ } else {
+ glEnable(textureTarget);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ if( 0 != gl3ShaderProgramName ) {
+ glDisableVertexAttribArray( vertAttrLoc );
+ glDisableVertexAttribArray( texCoordAttrLoc );
+ glUseProgram(0);
+ } else {
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDisable(textureTarget);
+ }
+
glBindTexture(textureTarget, 0);
[context clearDrawable];
@@ -595,102 +838,109 @@ static const GLfloat gl_verts[] = {
- (void)waitUntilRenderSignal: (long) to_micros
{
- BOOL ready = NO;
- int wr = 0;
+ struct timespec t0, to_until;
+ BOOL tooLate;
+ int wr;
+ if( 0 >= to_micros ) {
+ to_micros = 16666 + 1000; // defaults to 1/60s + 1ms
+ NSLog(@"MyNSOpenGLContext::waitUntilRenderSignal: to_micros was zero, using defaults");
+ }
pthread_mutex_lock(&renderLock);
- SYNC_PRINT("{W %ld us", to_micros);
- do {
- if(0 >= swapInterval) {
- ready = YES;
- }
- if(NO == ready) {
- #ifdef DBG_SYNC
- struct timespec t0, t1, td, td2;
- timespec_now(&t0);
- #endif
- if(0 < to_micros) {
- struct timespec to_abs = lastWaitTime;
- timespec_addmicros(&to_abs, to_micros);
- #ifdef DBG_SYNC
- timespec_subtract(&td, &to_abs, &t0);
- fprintf(stderr, ", (%ld) / ", timespec_milliseconds(&td));
- #endif
- wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_abs);
- #ifdef DBG_SYNC
- timespec_now(&t1);
- timespec_subtract(&td, &t1, &t0);
- timespec_subtract(&td2, &t1, &lastWaitTime);
- fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
- #endif
- } else {
- pthread_cond_wait (&renderSignal, &renderLock);
- #ifdef DBG_SYNC
- timespec_now(&t1);
- timespec_subtract(&td, &t1, &t0);
- timespec_subtract(&td2, &t1, &lastWaitTime);
- fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
- #endif
- }
- ready = YES;
+ timespec_now(&t0);
+ to_until = lastWaitTime;
+ timespec_addmicros(&to_until, to_micros);
+ tooLate = timespec_compare(&to_until, &t0) < 0;
+ #ifdef DBG_SYNC
+ struct timespec td_until;
+ timespec_subtract(&td_until, &to_until, &t0);
+ SYNC_PRINT("{W %ld ms, to %ld ms, late %d", to_micros/1000, timespec_milliseconds(&td_until), tooLate);
+ #endif
+ if( 0 < swapInterval ) {
+ if( tooLate ) {
+ // adjust!
+ to_until = t0;
+ timespec_addmicros(&to_until, to_micros);
}
- } while (NO == ready && 0 == wr) ;
- SYNC_PRINT("-%d-%d-%d}", shallDraw, wr, ready);
+ wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_until);
+ #ifdef DBG_SYNC
+ struct timespec t1, td, td2;
+ timespec_now(&t1);
+ timespec_subtract(&td, &t1, &t0);
+ timespec_subtract(&td2, &t1, &lastWaitTime);
+ fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
+ #endif
+ }
+ SYNC_PRINT("-%d-%d}\n", shallDraw, wr);
timespec_now(&lastWaitTime);
pthread_mutex_unlock(&renderLock);
}
@end
-NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight) {
- // This simply crashes after dealloc() has been called .. ie. ref-count -> 0 too early ?
- // However using alloc/init, actual dealloc happens at JAWT destruction, hence too later IMHO.
- // return [[MyNSOpenGLLayer layer] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID
- // opaque: opaque texWidth: texWidth texHeight: texHeight];
-
- return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID
- opaque: opaque texWidth: texWidth texHeight: texHeight];
+NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, int gl3ShaderProgramName, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight, int winWidth, int winHeight) {
+ return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx gl3ShaderProgramName: (GLuint)gl3ShaderProgramName pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID
+ opaque: opaque texWidth: texWidth texHeight: texHeight
+ winWidth: winWidth winHeight: winHeight];
+}
+
+void setNSOpenGLLayerEnabled(NSOpenGLLayer* layer, Bool enable) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+ [l setGLEnabled: enable];
+ [pool release];
}
void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval) {
- MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
[l setSwapInterval: interval];
[pool release];
}
void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros) {
- MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
[l waitUntilRenderSignal: to_micros];
[pool release];
}
-void flushNSOpenGLLayerPBuffer(NSOpenGLLayer* layer) {
- MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+void setNSOpenGLLayerNeedsDisplayFBO(NSOpenGLLayer* layer, uint32_t texID) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+ Bool shallDraw;
- pthread_mutex_lock(&l->renderLock);
- [l validatePBuffer:0];
- pthread_mutex_unlock(&l->renderLock);
+ // volatile OK
+ [l setTextureID: texID];
+ shallDraw = [l isGLSourceValid];
+ l->shallDraw = shallDraw;
+ SYNC_PRINT("<! T %d>", (int)shallDraw);
+ if(shallDraw) {
+ if ( [NSThread isMainThread] == YES ) {
+ [l setNeedsDisplay];
+ } else {
+ // don't wait - using doublebuffering
+ [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
+ }
+ }
+ // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l);
[pool release];
}
-void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p, uint32_t texID, int texWidth, int texHeight) {
- MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+void setNSOpenGLLayerNeedsDisplayPBuffer(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
Bool shallDraw;
- pthread_mutex_lock(&l->renderLock);
- [l validatePBuffer:p];
- // l->newTexWidth = texWidth;
- // l->newTexHeight = texHeight;
- [l setTextureID: texID];
+ if( NO == [l isSamePBuffer: p] ) {
+ [l setNewPBuffer: p];
+ }
+
+ // volatile OK
shallDraw = [l isGLSourceValid];
l->shallDraw = shallDraw;
- pthread_mutex_unlock(&l->renderLock);
- SYNC_PRINT("<! T%dx%d O%dx%d %d>", texWidth, texHeight, l->newTexWidth, l->newTexHeight, (int)shallDraw);
+ SYNC_PRINT("<! T %d>", (int)shallDraw);
if(shallDraw) {
if ( [NSThread isMainThread] == YES ) {
[l setNeedsDisplay];
@@ -704,17 +954,18 @@ void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p,
}
void releaseNSOpenGLLayer(NSOpenGLLayer* layer) {
- MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l);
+ MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
- if ( [NSThread isMainThread] == YES ) {
- [l releaseLayer];
- } else {
- [l performSelectorOnMainThread:@selector(releaseLayer) withObject:nil waitUntilDone:NO];
- }
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+ DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l);
+ [l releaseLayer];
DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.X: %p\n", l);
+
+ [CATransaction commit];
+
[pool release];
}
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
index 48807ee29..462b5393d 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
@@ -501,6 +501,28 @@ NSView* getNSView(NSOpenGLContext* ctx) {
return view;
}
+static Bool lockViewIfReady(NSView *view) {
+ Bool viewReady = false;
+
+ if (view != nil) {
+ if ([view lockFocusIfCanDraw] == NO) {
+ DBG_PRINT("lockViewIfReady.1 [view lockFocusIfCanDraw] failed\n");
+ } else {
+ NSRect frame = [view frame];
+ if ((frame.size.width == 0) || (frame.size.height == 0)) {
+ [view unlockFocus];
+ DBG_PRINT("lockViewIfReady.2 view.frame size %dx%d\n", (int)frame.size.width, (int)frame.size.height);
+ } else {
+ DBG_PRINT("lockViewIfReady.X ready and locked\n");
+ viewReady = true;
+ }
+ }
+ } else {
+ DBG_PRINT("lockViewIfReady.3 nil view\n");
+ }
+ return viewReady;
+}
+
NSOpenGLContext* createContext(NSOpenGLContext* share,
NSView* view,
Bool incompleteView,
@@ -515,55 +537,29 @@ NSOpenGLContext* createContext(NSOpenGLContext* share,
DBG_PRINT("createContext.0: share %p, view %p, incompleteView %d, pixfmt %p, opaque %d\n",
share, view, (int)incompleteView, fmt, opaque);
- if (view != nil) {
- Bool viewReady = true;
+ Bool viewReadyAndLocked = incompleteView ? false : lockViewIfReady(view);
- if(!incompleteView) {
- if ([view lockFocusIfCanDraw] == NO) {
- DBG_PRINT("createContext.1 [view lockFocusIfCanDraw] failed\n");
- viewReady = false;
- }
- }
- if(viewReady) {
- NSRect frame = [view frame];
- if ((frame.size.width == 0) || (frame.size.height == 0)) {
- if(!incompleteView) {
- [view unlockFocus];
- }
- DBG_PRINT("createContext.2 view.frame size %dx%d\n", (int)frame.size.width, (int)frame.size.height);
- viewReady = false;
- }
- }
-
- if (!viewReady)
- {
- if (viewNotReady != NULL)
- {
- *viewNotReady = 1;
- }
+ if (nil != viewNotReady) {
+ *viewNotReady = 1;
+ }
- // the view is not ready yet
- DBG_PRINT("createContext.X: view not ready yet\n");
- [pool release];
- return NULL;
- }
+ if (nil != view && !incompleteView && !viewReadyAndLocked) {
+ DBG_PRINT("createContext.X: Assumed complete view not ready yet\n");
+ [pool release];
+ return NULL;
}
-
+
NSOpenGLContext* ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:share];
- if (ctx != nil) {
- if (view != nil) {
+ if ( nil != ctx && nil != view ) {
if(!opaque) {
GLint zeroOpacity = 0;
[ctx setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity];
}
- if(!incompleteView) {
- DBG_PRINT("createContext.3.0: setView\n");
- [ctx setView:view];
- DBG_PRINT("createContext.3.X: setView\n");
+ [ctx setView:view]; // Bug 1087: Set default framebuffer, hence enforce NSView realization
+ if( viewReadyAndLocked ) {
[view unlockFocus];
}
- }
}
DBG_PRINT("createContext.X: ctx: %p\n", ctx);
@@ -571,6 +567,32 @@ NSOpenGLContext* createContext(NSOpenGLContext* share,
return ctx;
}
+void setContextView(NSOpenGLContext* ctx, NSView* view) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ if ( nil != ctx ) {
+ if ( nil != view ) {
+ Bool viewReadyAndLocked = lockViewIfReady(view);
+ DBG_PRINT("setContextView.0: ctx %p, view %p: setView: %d\n", ctx, view, viewReadyAndLocked);
+ if( viewReadyAndLocked ) {
+ [ctx setView:view];
+ [view unlockFocus];
+ }
+ }
+ DBG_PRINT("setContextView.X\n");
+ }
+ [pool release];
+}
+
+void clearDrawable(NSOpenGLContext* ctx) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ if ( nil != ctx ) {
+ DBG_PRINT("clearDrawable.0: %p\n", ctx);
+ [ctx clearDrawable];
+ DBG_PRINT("clearDrawable.X\n");
+ }
+ [pool release];
+}
+
Bool makeCurrentContext(NSOpenGLContext* ctx) {
#if 0
// we issue the CGL Lock from Java upfront!
@@ -719,7 +741,7 @@ void setContextTextureImageToPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer*
Bool isNSOpenGLPixelBuffer(uint64_t object) {
NSObject *nsObj = (NSObject*) (intptr_t) object;
DBG_PRINT("isNSOpenGLPixelBuffer.0: obj %p\n", object);
- Bool res = [nsObj isMemberOfClass:[NSOpenGLPixelBuffer class]];
+ Bool res = [nsObj isKindOfClass:[NSOpenGLPixelBuffer class]];
DBG_PRINT("isNSOpenGLPixelBuffer.X: res %d\n", (int)res);
return res;
}
diff --git a/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c b/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c
index 964ac64a7..3166306ba 100644
--- a/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c
+++ b/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c
@@ -67,7 +67,7 @@ void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pAV)
return;
}
int shallBeDetached = 0;
- JNIEnv * env = JoglCommon_GetJNIEnv (&shallBeDetached);
+ JNIEnv * env = JoglCommon_GetJNIEnv (1 /* daemon */, &shallBeDetached);
if(NULL!=env) {
(*env)->CallVoidMethod(env, (jobject)pAV->jni_instance, jni_mid_updateAttributes,
pAV->width, pAV->height,
@@ -75,7 +75,8 @@ void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pAV)
pAV->framerate, (uint32_t)(pAV->length*pAV->framerate), pAV->length,
(*env)->NewStringUTF(env, pAV->videoCodec),
(*env)->NewStringUTF(env, pAV->audioCodec) );
- JoglCommon_ReleaseJNIEnv (shallBeDetached);
+ // detaching thread not required - daemon
+ // JoglCommon_ReleaseJNIEnv(shallBeDetached);
}
}
@@ -107,11 +108,11 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1setStr
}
JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_OMXGLMediaPlayer__1setStreamEGLImageTexture2D
- (JNIEnv *env, jobject instance, jlong ptr, jint i, jint tex, jlong image, jlong sync)
+ (JNIEnv *env, jobject instance, jlong ptr, jint tex, jlong image, jlong sync)
{
OMXToolBasicAV_t *pOMXAV = (OMXToolBasicAV_t *)((void *)((intptr_t)ptr));
if (pOMXAV != NULL) {
- OMXToolBasicAV_SetStreamEGLImageTexture2D( pOMXAV, i, (GLuint) tex,
+ OMXToolBasicAV_SetStreamEGLImageTexture2D( pOMXAV, (GLuint) tex,
(EGLImageKHR)(intptr_t)image,
(EGLSyncKHR)(intptr_t)sync);
}
diff --git a/src/jogl/native/openmax/omx_tool.c b/src/jogl/native/openmax/omx_tool.c
index 16c43f6a8..35d5cfa58 100644
--- a/src/jogl/native/openmax/omx_tool.c
+++ b/src/jogl/native/openmax/omx_tool.c
@@ -1049,21 +1049,17 @@ void OMXToolBasicAV_SetStream(OMXToolBasicAV_t * pOMXAV, int vBufferNum, const K
DBG_PRINT( "SetStream X\n");
}
-void OMXToolBasicAV_SetStreamEGLImageTexture2D(OMXToolBasicAV_t * pOMXAV, KDint i, GLuint tex, EGLImageKHR image, EGLSyncKHR sync)
+void OMXToolBasicAV_SetStreamEGLImageTexture2D(OMXToolBasicAV_t * pOMXAV, GLuint tex, EGLImageKHR image, EGLSyncKHR sync)
{
if(NULL==pOMXAV) {
JoglCommon_throwNewRuntimeException(0, "OMX instance null\n");
return;
}
- DBG_PRINT( "SetStreamEGLImg %p #%d/%d t:%d i:%p s:%p..\n", pOMXAV, i, pOMXAV->vBufferNum, tex, image, sync);
- if(i<0||i>=pOMXAV->vBufferNum) {
- JoglCommon_throwNewRuntimeException(0, "Buffer index out of range: %d\n", i);
- return;
- }
+ DBG_PRINT( "SetStreamEGLImg %p count %d t:%d i:%p s:%p..\n", pOMXAV, pOMXAV->vBufferNum, tex, image, sync);
kdThreadMutexLock(pOMXAV->mutex);
{
- OMXToolImageBuffer_t *pBuf = &pOMXAV->buffers[i];
+ OMXToolImageBuffer_t *pBuf = &pOMXAV->buffers[0]; // FIXME: Move all sync/buffer handling to Java - Already done -> GLMediaPlayerImpl
pBuf->tex=tex;
pBuf->image=image;
pBuf->sync=sync;
@@ -1644,7 +1640,7 @@ int ModuleTest()
printf("6 eglGetError: 0x%x\n", eglGetError());
- if(OMXToolBasicAV_SetStreamEGLImageTexture2D(pOMXAV, i, tex, image, sync)) {
+ if(OMXToolBasicAV_SetStreamEGLImageTexture2D(pOMXAV, tex, image, sync)) {
return -1;
}
}
diff --git a/src/jogl/native/openmax/omx_tool.h b/src/jogl/native/openmax/omx_tool.h
index 414befca0..022c56cf9 100644
--- a/src/jogl/native/openmax/omx_tool.h
+++ b/src/jogl/native/openmax/omx_tool.h
@@ -28,6 +28,7 @@
#include <stdlib.h>
#include <string.h>
+// FIXME: Move all sync/buffer handling to Java - Already done -> GLMediaPlayerImpl
#define EGLIMAGE_MAX_BUFFERS 4
extern int USE_OPENGL;
@@ -90,6 +91,7 @@ typedef struct {
KDThreadMutex * mutex;
KDThreadSem * flushSem;
+ // FIXME: Move all sync/buffer handling to Java - Already done -> GLMediaPlayerImpl
OMXToolImageBuffer_t buffers[EGLIMAGE_MAX_BUFFERS];
int vBufferNum;
int glPos;
@@ -118,7 +120,7 @@ KDint OMXToolBasicAV_SetState(OMXToolBasicAV_t * pOMXAV, OMX_STATETYPE state, KD
//
OMXToolBasicAV_t * OMXToolBasicAV_CreateInstance(EGLDisplay dpy); // #1
void OMXToolBasicAV_SetStream(OMXToolBasicAV_t * pOMXAV, int vBufferNum, const KDchar * stream); // #2
-void OMXToolBasicAV_SetStreamEGLImageTexture2D(OMXToolBasicAV_t * pOMXAV, KDint i, GLuint tex, EGLImageKHR image, EGLSyncKHR sync); // #3
+void OMXToolBasicAV_SetStreamEGLImageTexture2D(OMXToolBasicAV_t * pOMXAV, GLuint tex, EGLImageKHR image, EGLSyncKHR sync); // #3
void OMXToolBasicAV_ActivateStream(OMXToolBasicAV_t * pOMXAV); // #4
void OMXToolBasicAV_AttachVideoRenderer(OMXToolBasicAV_t * pOMXAV); // Stop, DetachVideoRenderer, SetEGLImageTexture2D .. before ..
diff --git a/src/jogl/native/timespec.c b/src/jogl/native/timespec.c
index 50f0ca8c5..a69f4635e 100644
--- a/src/jogl/native/timespec.c
+++ b/src/jogl/native/timespec.c
@@ -75,3 +75,8 @@ long timespec_milliseconds(struct timespec *a)
{
return a->tv_sec*1000 + a->tv_nsec/1000000;
}
+
+long timespec_microseconds(struct timespec *a)
+{
+ return a->tv_sec*1000000 + a->tv_nsec/1000;
+}
diff --git a/src/jogl/native/timespec.h b/src/jogl/native/timespec.h
index f900bfa16..a621562b9 100644
--- a/src/jogl/native/timespec.h
+++ b/src/jogl/native/timespec.h
@@ -17,4 +17,7 @@ void timespec_subtract(struct timespec *r, struct timespec *a, struct timespec *
/** convert the timespec into milliseconds (may overflow) */
long timespec_milliseconds(struct timespec *a);
+/** convert the timespec into microseconds (may overflow) */
+long timespec_microseconds(struct timespec *a);
+
#endif /* _timespec_h */
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java
index 22c95f3dd..e785af788 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java
@@ -11,29 +11,29 @@ public class DelegatedUpstreamSurfaceHookMutableSize extends UpstreamSurfaceHook
* @param width initial width
* @param height initial height
*/
- public DelegatedUpstreamSurfaceHookMutableSize(UpstreamSurfaceHook upstream, int width, int height) {
+ public DelegatedUpstreamSurfaceHookMutableSize(final UpstreamSurfaceHook upstream, final int width, final int height) {
super(width, height);
this.upstream = upstream;
}
@Override
- public final void create(ProxySurface s) {
+ public final void create(final ProxySurface s) {
if(null != upstream) {
upstream.create(s);
}
}
@Override
- public final void destroy(ProxySurface s) {
+ public final void destroy(final ProxySurface s) {
if(null != upstream) {
upstream.destroy(s);
}
}
-
+
@Override
public String toString() {
- return getClass().getSimpleName()+"[ "+ width + "x" + height + ", " + upstream + "]";
+ return getClass().getSimpleName()+"[ "+ pixWidth + "x" + pixHeight + ", " + upstream + "]";
}
-
+
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java
index 85e24582c..abcc166cb 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java
@@ -10,9 +10,9 @@ public class DelegatedUpstreamSurfaceHookWithSurfaceSize implements UpstreamSurf
/**
* @param upstream optional upstream UpstreamSurfaceHook used for {@link #create(ProxySurface)} and {@link #destroy(ProxySurface)}.
- * @param surface mandatory {@link NativeSurface} used for {@link #getWidth(ProxySurface)} and {@link #getHeight(ProxySurface)}
+ * @param surface mandatory {@link NativeSurface} used for {@link #getSurfaceWidth(ProxySurface)} and {@link #getSurfaceHeight(ProxySurface)}, not used for {@link #getUpstreamSurface()}.
*/
- public DelegatedUpstreamSurfaceHookWithSurfaceSize(UpstreamSurfaceHook upstream, NativeSurface surface) {
+ public DelegatedUpstreamSurfaceHookWithSurfaceSize(final UpstreamSurfaceHook upstream, final NativeSurface surface) {
this.upstream = upstream;
this.surface = surface;
if(null == surface) {
@@ -20,35 +20,46 @@ public class DelegatedUpstreamSurfaceHookWithSurfaceSize implements UpstreamSurf
}
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns <code>null</code>.
+ * </p>
+ */
+ @Override
+ public final NativeSurface getUpstreamSurface() {
+ return null;
+ }
+
@Override
- public final void create(ProxySurface s) {
+ public final void create(final ProxySurface s) {
if(null != upstream) {
upstream.create(s);
}
}
@Override
- public final void destroy(ProxySurface s) {
+ public final void destroy(final ProxySurface s) {
if(null != upstream) {
upstream.destroy(s);
}
}
@Override
- public final int getWidth(ProxySurface s) {
- return surface.getWidth();
+ public final int getSurfaceWidth(final ProxySurface s) {
+ return surface.getSurfaceWidth();
}
@Override
- public final int getHeight(ProxySurface s) {
- return surface.getHeight();
- }
-
+ public final int getSurfaceHeight(final ProxySurface s) {
+ return surface.getSurfaceHeight();
+ }
+
@Override
public String toString() {
- final String us_s = null != surface ? ( surface.getClass().getName() + ": 0x" + Long.toHexString(surface.getSurfaceHandle()) + " " +surface.getWidth() + "x" + surface.getHeight() ) : "nil";
+ final String us_s = null != surface ? ( surface.getClass().getName() + ": 0x" + Long.toHexString(surface.getSurfaceHandle()) + " " +surface.getSurfaceWidth() + "x" + surface.getSurfaceHeight() ) : "nil";
return getClass().getSimpleName()+"["+upstream+", "+us_s+"]";
}
-
+
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/MutableGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/MutableGraphicsConfiguration.java
index 2d5af86b9..a137d46c3 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/MutableGraphicsConfiguration.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/MutableGraphicsConfiguration.java
@@ -32,12 +32,19 @@ import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.DefaultGraphicsConfiguration;
public class MutableGraphicsConfiguration extends DefaultGraphicsConfiguration {
- public MutableGraphicsConfiguration(AbstractGraphicsScreen screen,
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested) {
+ public MutableGraphicsConfiguration(final AbstractGraphicsScreen screen,
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested) {
super(screen, capsChosen, capsRequested);
}
- public void setChosenCapabilities(CapabilitiesImmutable caps) {
+ @Override
+ public void setChosenCapabilities(final CapabilitiesImmutable caps) {
super.setChosenCapabilities(caps);
}
+
+ @Override
+ public void setScreen(final AbstractGraphicsScreen screen) {
+ super.setScreen(screen);
+ }
+
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
index 38bd70a90..7c1a88e6a 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,24 +20,25 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.nativewindow;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.util.JogampVersion;
import com.jogamp.common.util.VersionUtil;
+
import java.util.jar.Manifest;
public class NativeWindowVersion extends JogampVersion {
protected static volatile NativeWindowVersion jogampCommonVersionInfo;
- protected NativeWindowVersion(String packageName, Manifest mf) {
+ protected NativeWindowVersion(final String packageName, final Manifest mf) {
super(packageName, mf);
}
@@ -45,16 +46,17 @@ public class NativeWindowVersion extends JogampVersion {
if(null == jogampCommonVersionInfo) { // volatile: ok
synchronized(NativeWindowVersion.class) {
if( null == jogampCommonVersionInfo ) {
- final String packageName = "javax.media.nativewindow";
- final Manifest mf = VersionUtil.getManifest(NativeWindowVersion.class.getClassLoader(), packageName);
- jogampCommonVersionInfo = new NativeWindowVersion(packageName, mf);
+ final String packageName1 = "javax.media.nativewindow"; // atomic packaging - and identity
+ final String packageName2 = "javax.media.opengl"; // all packaging
+ final Manifest mf = VersionUtil.getManifest(NativeWindowVersion.class.getClassLoader(), new String[]{ packageName1, packageName2 } );
+ jogampCommonVersionInfo = new NativeWindowVersion(packageName1, mf);
}
}
}
return jogampCommonVersionInfo;
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
System.err.println(NativeWindowVersion.getInstance());
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java b/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java
index 29c540ac4..45d12be5e 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java
@@ -1,45 +1,57 @@
package com.jogamp.nativewindow;
+import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
public class UpstreamSurfaceHookMutableSize implements UpstreamSurfaceHook.MutableSize {
- int width, height;
+ int pixWidth, pixHeight;
/**
* @param width initial width
* @param height initial height
*/
- public UpstreamSurfaceHookMutableSize(int width, int height) {
- this.width = width;
- this.height = height;
+ public UpstreamSurfaceHookMutableSize(final int width, final int height) {
+ this.pixWidth = width;
+ this.pixHeight = height;
}
@Override
- public final void setSize(int width, int height) {
- this.width = width;
- this.height = height;
+ public final void setSurfaceSize(final int width, final int height) {
+ this.pixWidth = width;
+ this.pixHeight = height;
}
-
+
@Override
- public final int getWidth(ProxySurface s) {
- return width;
+ public final int getSurfaceWidth(final ProxySurface s) {
+ return pixWidth;
}
@Override
- public final int getHeight(ProxySurface s) {
- return height;
+ public final int getSurfaceHeight(final ProxySurface s) {
+ return pixHeight;
}
@Override
- public void create(ProxySurface s) { /* nop */ }
+ public void create(final ProxySurface s) { /* nop */ }
@Override
- public void destroy(ProxySurface s) { /* nop */ }
-
+ public void destroy(final ProxySurface s) { /* nop */ }
+
@Override
public String toString() {
- return getClass().getSimpleName()+"[ "+ width + "x" + height + "]";
+ return getClass().getSimpleName()+"[pixel "+ pixWidth + "x" + pixHeight + "]";
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns <code>null</code>.
+ * </p>
+ */
+ @Override
+ public final NativeSurface getUpstreamSurface() {
+ return null;
}
-
+
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamWindowHookMutableSizePos.java b/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamWindowHookMutableSizePos.java
new file mode 100644
index 000000000..b509f118a
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamWindowHookMutableSizePos.java
@@ -0,0 +1,56 @@
+package com.jogamp.nativewindow;
+
+public class UpstreamWindowHookMutableSizePos extends UpstreamSurfaceHookMutableSize {
+ int winX, winY, winWidth, winHeight;
+
+ /**
+ * @param winX initial window x-pos
+ * @param winY initial window y-pos
+ * @param winWidth initial window width
+ * @param winHeight initial window height
+ * @param pixWidth initial surface pixel width, FIXME: pixel-dim == window-dim 'for now' ?
+ * @param pixHeight initial surface pixel height, FIXME: pixel-dim == window-dim 'for now' ?
+ */
+ public UpstreamWindowHookMutableSizePos(final int winX, final int winY, final int winWidth, final int winHeight, final int pixWidth, final int pixHeight) {
+ super(pixWidth, pixHeight);
+ this.winX= winX;
+ this.winY= winY;
+ this.winWidth = winWidth;
+ this.winHeight = winHeight;
+ }
+
+ // @Override
+ public final void setWinPos(final int winX, final int winY) {
+ this.winX= winX;
+ this.winY= winY;
+ }
+ // @Override
+ public final void setWinSize(final int winWidth, final int winHeight) {
+ this.winWidth= winWidth;
+ this.winHeight= winHeight;
+ // FIXME HiDPI: Use pixelScale ?!
+ // FIXME HiDPI: Consider setting winWidth/winHeight by setSurfaceSize(..) (back-propagation)
+ this.setSurfaceSize(winWidth, winHeight);
+ }
+
+ public final int getX() {
+ return winX;
+ }
+
+ public final int getY() {
+ return winY;
+ }
+ public final int getWidth() {
+ return winWidth;
+ }
+ public final int getHeight() {
+ return winHeight;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()+"[window "+ winX + "/" + winY + " " + winWidth + "x" + winHeight + ", pixel " + pixWidth + "x" + pixHeight + "]";
+ }
+
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
index 2a152ff35..3a62825a2 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -54,33 +54,34 @@ import jogamp.nativewindow.Debug;
handled in a toolkit-independent manner. */
public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable {
- private GraphicsConfiguration config;
+ private final GraphicsConfiguration config;
AbstractGraphicsConfiguration encapsulated;
- public AWTGraphicsConfiguration(AWTGraphicsScreen screen,
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- GraphicsConfiguration config, AbstractGraphicsConfiguration encapsulated) {
+ public AWTGraphicsConfiguration(final AWTGraphicsScreen screen,
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final GraphicsConfiguration config, final AbstractGraphicsConfiguration encapsulated) {
super(screen, capsChosen, capsRequested);
this.config = config;
this.encapsulated=encapsulated;
}
- private AWTGraphicsConfiguration(AWTGraphicsScreen screen, CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- GraphicsConfiguration config) {
+ private AWTGraphicsConfiguration(final AWTGraphicsScreen screen, final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final GraphicsConfiguration config) {
super(screen, capsChosen, capsRequested);
this.config = config;
this.encapsulated=null;
}
-
+
/**
- * @param capsChosen if null, <code>capsRequested</code> is copied and aligned
- * with the graphics Capabilities of the AWT Component to produce the chosen Capabilities.
+ * @param capsChosen if null, <code>capsRequested</code> is copied and aligned
+ * with the graphics {@link Capabilities} of the AWT Component to produce the chosen {@link Capabilities}.
* Otherwise the <code>capsChosen</code> is used.
+ * @param capsRequested if null, default {@link Capabilities} are used, otherwise the given values.
*/
- public static AWTGraphicsConfiguration create(Component awtComp, CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested) {
+ public static AWTGraphicsConfiguration create(final Component awtComp, CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested) {
final GraphicsConfiguration awtGfxConfig = awtComp.getGraphicsConfiguration();
if(null==awtGfxConfig) {
- throw new NativeWindowException("AWTGraphicsConfiguration.create: Null AWT GraphicsConfiguration @ "+awtComp);
+ throw new NativeWindowException("AWTGraphicsConfiguration.create: Null AWT GraphicsConfiguration @ "+awtComp);
}
final GraphicsDevice awtGraphicsDevice = awtGfxConfig.getDevice();
if(null==awtGraphicsDevice) {
@@ -91,8 +92,11 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple
final AWTGraphicsDevice awtDevice = new AWTGraphicsDevice(awtGraphicsDevice, AbstractGraphicsDevice.DEFAULT_UNIT);
final AWTGraphicsScreen awtScreen = new AWTGraphicsScreen(awtDevice);
+ if(null==capsRequested) {
+ capsRequested = new Capabilities();
+ }
if(null==capsChosen) {
- GraphicsConfiguration gc = awtGraphicsDevice.getDefaultConfiguration();
+ final GraphicsConfiguration gc = awtGraphicsDevice.getDefaultConfiguration();
capsChosen = AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capsRequested, gc);
}
final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(awtDevice, capsChosen);
@@ -105,10 +109,11 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple
}
// open access to superclass method
- public void setChosenCapabilities(CapabilitiesImmutable capsChosen) {
+ @Override
+ public void setChosenCapabilities(final CapabilitiesImmutable capsChosen) {
super.setChosenCapabilities(capsChosen);
}
-
+
@Override
public Object clone() {
return super.clone();
@@ -131,16 +136,16 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple
* @param gc the GraphicsConfiguration from which to derive the RGBA bit depths
* @return the passed Capabilities
*/
- public static CapabilitiesImmutable setupCapabilitiesRGBABits(CapabilitiesImmutable capabilitiesIn, GraphicsConfiguration gc) {
- Capabilities capabilities = (Capabilities) capabilitiesIn.cloneMutable();
+ public static CapabilitiesImmutable setupCapabilitiesRGBABits(final CapabilitiesImmutable capabilitiesIn, final GraphicsConfiguration gc) {
+ final Capabilities capabilities = (Capabilities) capabilitiesIn.cloneMutable();
- ColorModel cm = gc.getColorModel();
+ final ColorModel cm = gc.getColorModel();
if(null==cm) {
throw new NativeWindowException("Could not determine AWT ColorModel");
}
- int cmBitsPerPixel = cm.getPixelSize();
+ final int cmBitsPerPixel = cm.getPixelSize();
int bitsPerPixel = 0;
- int[] bitesPerComponent = cm.getComponentSize();
+ final int[] bitesPerComponent = cm.getComponentSize();
if(bitesPerComponent.length>=3) {
capabilities.setRedBits(bitesPerComponent[0]);
bitsPerPixel += bitesPerComponent[0];
@@ -167,7 +172,7 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple
public String toString() {
return getClass().getSimpleName()+"[" + getScreen() +
",\n\tchosen " + capabilitiesChosen+
- ",\n\trequested " + capabilitiesRequested+
+ ",\n\trequested " + capabilitiesRequested+
",\n\t" + config +
",\n\tencapsulated "+encapsulated+"]";
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsDevice.java
index 635e6d263..219f4bb92 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsDevice.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -48,15 +48,15 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
/** A wrapper for an AWT GraphicsDevice allowing it to be
handled in a toolkit-independent manner. */
public class AWTGraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
- private GraphicsDevice device;
+ private final GraphicsDevice device;
- public AWTGraphicsDevice(GraphicsDevice device, int unitID) {
+ public AWTGraphicsDevice(final GraphicsDevice device, final int unitID) {
super(NativeWindowFactory.TYPE_AWT, device.getIDstring(), unitID);
this.device = device;
}
public static AWTGraphicsDevice createDefault() {
- GraphicsDevice awtDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
+ final GraphicsDevice awtDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
return new AWTGraphicsDevice(awtDevice, AbstractGraphicsDevice.DEFAULT_UNIT);
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsScreen.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsScreen.java
index f4ee06e28..6fc35f719 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsScreen.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsScreen.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -51,35 +51,35 @@ import javax.media.nativewindow.*;
public class AWTGraphicsScreen extends DefaultGraphicsScreen implements Cloneable {
- public AWTGraphicsScreen(AWTGraphicsDevice device) {
+ public AWTGraphicsScreen(final AWTGraphicsDevice device) {
super(device, findScreenIndex(device.getGraphicsDevice()));
}
- public static GraphicsDevice getScreenDevice(int index) {
+ public static GraphicsDevice getScreenDevice(final int index) {
if(index<0) return null;
- GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
- GraphicsDevice[] gs = ge.getScreenDevices();
+ final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ final GraphicsDevice[] gs = ge.getScreenDevices();
if(index<gs.length) {
return gs[index];
}
return null;
}
- public static int findScreenIndex(GraphicsDevice awtDevice) {
+ public static int findScreenIndex(final GraphicsDevice awtDevice) {
if(null==awtDevice) return -1;
- GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
- GraphicsDevice[] gs = ge.getScreenDevices();
+ final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ final GraphicsDevice[] gs = ge.getScreenDevices();
for (int j = 0; j < gs.length; j++) {
if(gs[j] == awtDevice) return j;
}
return -1;
}
- public static AbstractGraphicsScreen createScreenDevice(GraphicsDevice awtDevice, int unitID) {
+ public static AbstractGraphicsScreen createScreenDevice(final GraphicsDevice awtDevice, final int unitID) {
return new AWTGraphicsScreen(new AWTGraphicsDevice(awtDevice, unitID));
}
- public static AbstractGraphicsScreen createScreenDevice(int index, int unitID) {
+ public static AbstractGraphicsScreen createScreenDevice(final int index, final int unitID) {
return createScreenDevice(getScreenDevice(index), unitID);
}
@@ -87,6 +87,7 @@ public class AWTGraphicsScreen extends DefaultGraphicsScreen implements Cloneabl
return new AWTGraphicsScreen(AWTGraphicsDevice.createDefault());
}
+ @Override
public Object clone() {
return super.clone();
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTPrintLifecycle.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTPrintLifecycle.java
new file mode 100644
index 000000000..b0a7fbc76
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTPrintLifecycle.java
@@ -0,0 +1,175 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.nativewindow.awt;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.print.PrinterJob;
+
+import jogamp.nativewindow.awt.AWTMisc;
+
+/**
+ * Interface describing print lifecycle to support AWT printing,
+ * e.g. on AWT {@link javax.media.opengl.GLAutoDrawable GLAutoDrawable}s.
+ * <a name="impl"><h5>Implementations</h5></a>
+ * <p>
+ * Implementing {@link javax.media.opengl.GLAutoDrawable GLAutoDrawable} classes based on AWT
+ * supporting {@link Component#print(Graphics)} shall implement this interface.
+ * </p>
+ * <a name="usage"><h5>Usage</h5></a>
+ * <p>
+ * Users attempting to print an AWT {@link Container} containing {@link AWTPrintLifecycle} elements
+ * shall consider decorating the {@link Container#printAll(Graphics)} call with<br>
+ * {@link #setupPrint(double, double, int, int, int) setupPrint(..)} and {@link #releasePrint()}
+ * on all {@link AWTPrintLifecycle} elements in the {@link Container}.<br>
+ * To minimize this burden, a user can use {@link Context#setupPrint(Container, double, double, int, int, int) Context.setupPrint(..)}:
+ * <pre>
+ * Container cont;
+ * double scaleGLMatXY = 72.0/glDPI;
+ * int numSamples = 0; // leave multisampling as-is
+ * PrinterJob job;
+ * ...
+ final AWTPrintLifecycle.Context ctx = AWTPrintLifecycle.Context.setupPrint(cont, scaleGLMatXY, scaleGLMatXY, numSamples);
+ try {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ try {
+ job.print();
+ } catch (PrinterException ex) {
+ ex.printStackTrace();
+ }
+ } });
+ } finally {
+ ctx.releasePrint();
+ }
+ *
+ * </pre>
+ * </p>
+ */
+public interface AWTPrintLifecycle {
+
+ public static final int DEFAULT_PRINT_TILE_SIZE = 1024;
+
+
+ /**
+ * Shall be called before {@link PrinterJob#print()}.
+ * <p>
+ * See <a href="#usage">Usage</a>.
+ * </p>
+ * @param scaleMatX {@link Graphics2D} {@link Graphics2D#scale(double, double) scaling factor}, i.e. rendering 1/scaleMatX * width pixels
+ * @param scaleMatY {@link Graphics2D} {@link Graphics2D#scale(double, double) scaling factor}, i.e. rendering 1/scaleMatY * height pixels
+ * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples
+ * @param tileWidth custom tile width for {@link com.jogamp.opengl.util.TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param tileHeight custom tile height for {@link com.jogamp.opengl.util.TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ */
+ void setupPrint(double scaleMatX, double scaleMatY, int numSamples, int tileWidth, int tileHeight);
+
+ /**
+ * Shall be called after {@link PrinterJob#print()}.
+ * <p>
+ * See <a href="#usage">Usage</a>.
+ * </p>
+ */
+ void releasePrint();
+
+ /**
+ * Convenient {@link AWTPrintLifecycle} context simplifying calling {@link AWTPrintLifecycle#setupPrint(double, double, int, int, int) setupPrint(..)}
+ * and {@link AWTPrintLifecycle#releasePrint()} on all {@link AWTPrintLifecycle} elements of a {@link Container}.
+ * <p>
+ * See <a href="#usage">Usage</a>.
+ * </p>
+ */
+ public static class Context {
+ /**
+ * <p>
+ * See <a href="#usage">Usage</a>.
+ * </p>
+ *
+ * @param c container to be traversed through to perform {@link AWTPrintLifecycle#setupPrint(double, double, int, int, int) setupPrint(..)} on all {@link AWTPrintLifecycle} elements.
+ * @param scaleMatX {@link Graphics2D} {@link Graphics2D#scale(double, double) scaling factor}, i.e. rendering 1/scaleMatX * width pixels
+ * @param scaleMatY {@link Graphics2D} {@link Graphics2D#scale(double, double) scaling factor}, i.e. rendering 1/scaleMatY * height pixels
+ * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples
+ * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @return the context
+ */
+ public static Context setupPrint(final Container c, final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight) {
+ final Context t = new Context(c, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight);
+ t.setupPrint(c);
+ return t;
+ }
+
+ /**
+ * <p>
+ * See <a href="#usage">Usage</a>.
+ * </p>
+ */
+ public void releasePrint() {
+ count = AWTMisc.performAction(cont, AWTPrintLifecycle.class, releaseAction);
+ }
+
+ /**
+ * @return count of performed actions of last {@link #setupPrint(Container, double, double, int, int, int) setupPrint(..)} or {@link #releasePrint()}.
+ */
+ public int getCount() { return count; }
+
+ private final Container cont;
+ private final double scaleMatX;
+ private final double scaleMatY;
+ private final int numSamples;
+ private final int tileWidth;
+ private final int tileHeight;
+ private int count;
+
+ private final AWTMisc.ComponentAction setupAction = new AWTMisc.ComponentAction() {
+ @Override
+ public void run(final Component c) {
+ ((AWTPrintLifecycle)c).setupPrint(scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight);
+ } };
+ private final AWTMisc.ComponentAction releaseAction = new AWTMisc.ComponentAction() {
+ @Override
+ public void run(final Component c) {
+ ((AWTPrintLifecycle)c).releasePrint();
+ } };
+
+ private Context(final Container c, final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight) {
+ this.cont = c;
+ this.scaleMatX = scaleMatX;
+ this.scaleMatY = scaleMatY;
+ this.numSamples = numSamples;
+ this.tileWidth = tileWidth;
+ this.tileHeight = tileHeight;
+ this.count = 0;
+ }
+ private void setupPrint(final Container c) {
+ count = AWTMisc.performAction(c, AWTPrintLifecycle.class, setupAction);
+ }
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java
index d78b4ac15..496e6e07b 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java
@@ -33,80 +33,81 @@ import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
+
import javax.media.nativewindow.WindowClosingProtocol;
import jogamp.nativewindow.awt.AWTMisc;
public class AWTWindowClosingProtocol implements WindowClosingProtocol {
- private Component comp;
- private Runnable closingOperation;
- private volatile boolean closingListenerSet = false;
- private Object closingListenerLock = new Object();
+ private final Component comp;
+ private Window listenTo;
+ private final Runnable closingOperationClose;
+ private final Runnable closingOperationNOP;
+ private final Object closingListenerLock = new Object();
private WindowClosingMode defaultCloseOperation = WindowClosingMode.DISPOSE_ON_CLOSE;
private boolean defaultCloseOperationSetByUser = false;
- public AWTWindowClosingProtocol(Component comp, Runnable closingOperation) {
+ /**
+ * @param comp mandatory AWT component which AWT Window is being queried by parent traversal
+ * @param closingOperationClose mandatory closing operation, triggered if windowClosing and {@link WindowClosingMode#DISPOSE_ON_CLOSE}
+ * @param closingOperationNOP optional closing operation, triggered if windowClosing and {@link WindowClosingMode#DO_NOTHING_ON_CLOSE}
+ */
+ public AWTWindowClosingProtocol(final Component comp, final Runnable closingOperationClose, final Runnable closingOperationNOP) {
this.comp = comp;
- this.closingOperation = closingOperation;
+ this.listenTo = null;
+ this.closingOperationClose = closingOperationClose;
+ this.closingOperationNOP = closingOperationNOP;
}
class WindowClosingAdapter extends WindowAdapter {
@Override
- public void windowClosing(WindowEvent e) {
+ public void windowClosing(final WindowEvent e) {
final WindowClosingMode op = AWTWindowClosingProtocol.this.getDefaultCloseOperation();
if( WindowClosingMode.DISPOSE_ON_CLOSE == op ) {
// we have to issue this call right away,
// otherwise the window gets destroyed
- closingOperation.run();
+ closingOperationClose.run();
+ } else if( null != closingOperationNOP ){
+ closingOperationNOP.run();
}
}
}
WindowListener windowClosingAdapter = new WindowClosingAdapter();
- final boolean addClosingListenerImpl() {
- Window w = AWTMisc.getWindow(comp);
- if(null!=w) {
- w.addWindowListener(windowClosingAdapter);
- return true;
- }
- return false;
- }
-
/**
- * Adds this closing listener to the components Window if exist and only one time.<br>
- * Hence you may call this method every time to ensure it has been set,
- * ie in case the Window parent is not available yet.
+ * Adds this closing listener to the components Window if exist and only one time.
+ * <p>
+ * If the closing listener is already added, and {@link IllegalStateException} is thrown.
+ * </p>
*
- * @return
+ * @return true if added, otherwise false.
+ * @throws IllegalStateException
*/
- public final boolean addClosingListenerOneShot() {
- if(!closingListenerSet) { // volatile: ok
+ public final boolean addClosingListener() throws IllegalStateException {
synchronized(closingListenerLock) {
- if(!closingListenerSet) {
- closingListenerSet=addClosingListenerImpl();
- return closingListenerSet;
- }
+ if(null != listenTo) {
+ throw new IllegalStateException("WindowClosingListener already set");
+ }
+ listenTo = AWTMisc.getWindow(comp);
+ if(null!=listenTo) {
+ listenTo.addWindowListener(windowClosingAdapter);
+ return true;
+ }
}
- }
- return false;
+ return false;
}
public final boolean removeClosingListener() {
- if(closingListenerSet) { // volatile: ok
synchronized(closingListenerLock) {
- if(closingListenerSet) {
- Window w = AWTMisc.getWindow(comp);
- if(null!=w) {
- w.removeWindowListener(windowClosingAdapter);
- closingListenerSet = false;
- return true;
- }
- }
+ if(null != listenTo) {
+ listenTo.removeWindowListener(windowClosingAdapter);
+ listenTo = null;
+ return true;
+ }
}
- }
- return false;
+ return false;
}
/**
@@ -115,6 +116,7 @@ public class AWTWindowClosingProtocol implements WindowClosingProtocol {
* otherwise return the AWT/Swing close operation value translated to
* a {@link WindowClosingProtocol} value .
*/
+ @Override
public final WindowClosingMode getDefaultCloseOperation() {
synchronized(closingListenerLock) {
if(defaultCloseOperationSetByUser) {
@@ -125,7 +127,8 @@ public class AWTWindowClosingProtocol implements WindowClosingProtocol {
return AWTMisc.getNWClosingOperation(comp);
}
- public final WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
+ @Override
+ public final WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
synchronized(closingListenerLock) {
final WindowClosingMode _op = defaultCloseOperation;
defaultCloseOperation = op;
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AppContextInfo.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AppContextInfo.java
new file mode 100644
index 000000000..2026ada0f
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AppContextInfo.java
@@ -0,0 +1,199 @@
+package com.jogamp.nativewindow.awt;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import com.jogamp.common.util.RunnableTask;
+
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+/**
+ * Instance of this class holds information about a {@link ThreadGroup} associated {@link sun.awt.AppContext}.
+ * <p>
+ * Non intrusive workaround for Bug 983 and Bug 1004, see {@link #getCachedThreadGroup()}.
+ * </p>
+ */
+public class AppContextInfo {
+ private static final boolean DEBUG;
+
+ private static final Method getAppContextMethod;
+ private static final Object mainThreadAppContextLock = new Object();
+ private volatile WeakReference<Object> mainThreadAppContextWR = null;
+ private volatile WeakReference<ThreadGroup> mainThreadGroupWR = null;
+
+ static {
+ DEBUG = JAWTUtil.DEBUG;
+ final Method[] _getAppContextMethod = { null };
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ try {
+ final Class<?> appContextClass = Class.forName("sun.awt.AppContext");
+ _getAppContextMethod[0] = appContextClass.getMethod("getAppContext");
+ } catch(final Throwable ex) {
+ System.err.println("Bug 1004: Caught @ static: "+ex.getMessage());
+ ex.printStackTrace();
+ }
+ return null;
+ } } );
+ getAppContextMethod = _getAppContextMethod[0];
+ }
+
+ public AppContextInfo(final String info) {
+ update(info);
+ }
+
+ /**
+ * Returns <code>true</code> if this instance has valid {@link sun.awt.AppContext} information,
+ * i.e. {@link #getCachedThreadGroup()} returns not <code>null</code>.
+ */
+ public final boolean isValid() {
+ return null != getCachedThreadGroup();
+ }
+
+ /**
+ * Returns the {@link ThreadGroup} belonging to the
+ * last known {@link sun.awt.AppContext} as queried via {@link #update(String)}.
+ * <p>
+ * Returns <code>null</code> if no {@link sun.awt.AppContext} has been queried.
+ * </p>
+ * <p>
+ * The returned {@link ThreadGroup} allows users to create a custom thread
+ * belonging to it and hence mitigating Bug 983 and Bug 1004.
+ * </p>
+ * <p>
+ * {@link #update(String)} should be called from a thread belonging to the
+ * desired {@link sun.awt.AppContext}, i.e. early from within the special threaded application.
+ * </p>
+ * <p>
+ * E.g. {@link JAWTWindow} issues {@link #update(String)} in it's constructor.
+ * </p>
+ */
+ public final ThreadGroup getCachedThreadGroup() {
+ final WeakReference<ThreadGroup> tgRef = mainThreadGroupWR;
+ return null != tgRef ? tgRef.get() : null;
+ }
+
+ /**
+ * Invokes <code>runnable</code> on a {@link Thread} belonging to the {@link sun.awt.AppContext} {@link ThreadGroup},
+ * see {@link #getCachedThreadGroup()}.
+ * <p>
+ * {@link #update(String)} is issued first, which returns <code>true</code>
+ * if the current thread belongs to an AppContext {@link ThreadGroup}.
+ * In this case the <code>runnable</code> is invoked on the current thread,
+ * otherwise a new {@link Thread} will be started.
+ * </p>
+ * <p>
+ * If a new {@link Thread} is required, the AppContext {@link ThreadGroup} is being used
+ * if {@link #isValid() available}, otherwise the default system {@link ThreadGroup}.
+ * </p>
+ *
+ * @param waitUntilDone if <code>true</code>, waits until <code>runnable</code> execution is completed, otherwise returns immediately.
+ * @param runnable the {@link Runnable} to be executed. If <code>waitUntilDone</code> is <code>true</code>,
+ * the runnable <b>must exist</b>, i.e. not loop forever.
+ * @param threadBaseName the base name for the new thread if required.
+ * The resulting thread name will have either '-OnAppContextTG' or '-OnSystemTG' appended
+ * @return the {@link Thread} used to invoke the <code>runnable</code>, which may be the current {@link Thread} or a newly created one, see above.
+ */
+ public Thread invokeOnAppContextThread(final boolean waitUntilDone, final Runnable runnable, final String threadBaseName) {
+ final Thread t;
+ if( update("invoke") ) {
+ t = Thread.currentThread();
+ if( DEBUG ) {
+ System.err.println("Bug 1004: Invoke.0 on current AppContext thread: "+t+" "+toHexString(t.hashCode()));
+ }
+ runnable.run();
+ } else {
+ final ThreadGroup tg = getCachedThreadGroup();
+ final String tName = threadBaseName + ( null != tg ? "-OnAppContextTG" : "-OnSystemTG" );
+ t = RunnableTask.invokeOnNewThread(tg, waitUntilDone, runnable, tName);
+ if( DEBUG ) {
+ final int tgHash = null != tg ? tg.hashCode() : 0;
+ System.err.println("Bug 1004: Invoke.1 on new AppContext thread: "+t+" "+toHexString(t.hashCode())+", tg "+tg+" "+toHexString(tgHash));
+ }
+ }
+ return t;
+ }
+
+ /**
+ * Update {@link sun.awt.AppContext} information for the current ThreadGroup if uninitialized or {@link sun.awt.AppContext} changed.
+ * <p>
+ * See {@link #getCachedThreadGroup()} for usage.
+ * </p>
+ * @param info informal string for logging purposes
+ * @return <code>true</code> if the current ThreadGroup is mapped to an {@link sun.awt.AppContext} and the information is good, otherwise false.
+ */
+ public final boolean update(final String info) {
+ if ( null != getAppContextMethod ) {
+ // Test whether the current thread's ThreadGroup is mapped to an AppContext.
+ final Object thisThreadAppContext = fetchAppContext();
+ final boolean tgMapped = null != thisThreadAppContext;
+
+ final Thread thread = Thread.currentThread();
+ final ThreadGroup threadGroup = thread.getThreadGroup();
+ final Object mainThreadAppContext;
+ {
+ final WeakReference<Object> _mainThreadAppContextWR = mainThreadAppContextWR;
+ mainThreadAppContext = null != _mainThreadAppContextWR ? _mainThreadAppContextWR.get() : null;
+ }
+
+ if( tgMapped ) { // null != thisThreadAppContext
+ // Update info is possible
+ if( null == mainThreadAppContext ||
+ mainThreadAppContext != thisThreadAppContext ) {
+ // GC'ed or 1st fetch !
+ final int mainThreadAppContextHash = null != mainThreadAppContext ? mainThreadAppContext.hashCode() : 0;
+ final int thisThreadAppContextHash;
+ synchronized(mainThreadAppContextLock) {
+ mainThreadGroupWR = new WeakReference<ThreadGroup>(threadGroup);
+ mainThreadAppContextWR = new WeakReference<Object>(thisThreadAppContext);
+ thisThreadAppContextHash = thisThreadAppContext.hashCode();
+ }
+ if( DEBUG ) {
+ System.err.println("Bug 1004[TGMapped "+tgMapped+"]: Init AppContext @ "+info+" on thread "+thread.getName()+" "+toHexString(thread.hashCode())+
+ ": tg "+threadGroup.getName()+" "+toHexString(threadGroup.hashCode())+
+ " -> appCtx [ main "+mainThreadAppContext+" "+toHexString(mainThreadAppContextHash)+
+ " -> this "+thisThreadAppContext+" "+toHexString(thisThreadAppContextHash) + " ] ");
+ }
+ } else {
+ // old info is OK
+ if( DEBUG ) {
+ final int mainThreadAppContextHash = mainThreadAppContext.hashCode();
+ final int thisThreadAppContextHash = thisThreadAppContext.hashCode();
+ System.err.println("Bug 1004[TGMapped "+tgMapped+"]: OK AppContext @ "+info+" on thread "+thread.getName()+" "+toHexString(thread.hashCode())+
+ ": tg "+threadGroup.getName()+" "+toHexString(threadGroup.hashCode())+
+ " : appCtx [ this "+thisThreadAppContext+" "+toHexString(thisThreadAppContextHash)+
+ " , main "+mainThreadAppContext+" "+toHexString(mainThreadAppContextHash) + " ] ");
+ }
+ }
+ return true;
+ } else {
+ if( DEBUG ) {
+ final int mainThreadAppContextHash = null != mainThreadAppContext ? mainThreadAppContext.hashCode() : 0;
+ final int thisThreadAppContextHash = null != thisThreadAppContext ? thisThreadAppContext.hashCode() : 0;
+ System.err.println("Bug 1004[TGMapped "+tgMapped+"]: No AppContext @ "+info+" on thread "+thread.getName()+" "+toHexString(thread.hashCode())+
+ ": tg "+threadGroup.getName()+" "+toHexString(threadGroup.hashCode())+
+ " -> appCtx [ this "+thisThreadAppContext+" "+toHexString(thisThreadAppContextHash)+
+ " -> main "+mainThreadAppContext+" "+toHexString(mainThreadAppContextHash) + " ] ");
+ }
+ }
+ }
+ return false;
+ }
+ private static Object fetchAppContext() {
+ try {
+ return getAppContextMethod.invoke(null);
+ } catch(final Exception ex) {
+ System.err.println("Bug 1004: Caught: "+ex.getMessage());
+ ex.printStackTrace();
+ return null;
+ }
+ }
+
+ private static String toHexString(final int i) {
+ return "0x"+Integer.toHexString(i);
+ }
+
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java
new file mode 100644
index 000000000..c7055099f
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java
@@ -0,0 +1,297 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.nativewindow.awt;
+
+import java.awt.Point;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DirectColorModel;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.awt.image.WritableRaster;
+import java.nio.IntBuffer;
+import java.util.Hashtable;
+
+import com.jogamp.common.nio.Buffers;
+
+/**
+ * {@link DataBuffer} specialization using NIO direct buffer of type {@link DataBuffer#TYPE_INT} as storage.
+ */
+public final class DirectDataBufferInt extends DataBuffer {
+
+ public static class DirectWritableRaster extends WritableRaster {
+ protected DirectWritableRaster(final SampleModel sampleModel, final DirectDataBufferInt dataBuffer, final Point origin) {
+ super(sampleModel, dataBuffer, origin);
+ }
+ }
+
+ public static class BufferedImageInt extends BufferedImage {
+ final int customImageType;
+ public BufferedImageInt (final int customImageType, final ColorModel cm, final WritableRaster raster, final Hashtable<?,?> properties) {
+ super(cm, raster, false /* isRasterPremultiplied */, properties);
+ this.customImageType = customImageType;
+ }
+
+ /**
+ * @return one of the custom image-type values {@link BufferedImage#TYPE_INT_ARGB TYPE_INT_ARGB},
+ * {@link BufferedImage#TYPE_INT_ARGB_PRE TYPE_INT_ARGB_PRE},
+ * {@link BufferedImage#TYPE_INT_RGB TYPE_INT_RGB} or {@link BufferedImage#TYPE_INT_BGR TYPE_INT_BGR}.
+ */
+ public int getCustomType() {
+ return customImageType;
+ }
+
+ @Override
+ public String toString() {
+ return "BufferedImageInt@"+Integer.toHexString(hashCode())
+ +": custom/internal type = "+customImageType+"/"+getType()
+ +" "+getColorModel()+" "+getRaster();
+ }
+ }
+
+ /**
+ * Creates a {@link BufferedImageInt} using a {@link DirectColorModel direct color model} in {@link ColorSpace#CS_sRGB sRGB color space}.<br>
+ * It uses a {@link DirectWritableRaster} utilizing {@link DirectDataBufferInt} storage.
+ * <p>
+ * Note that due to using the custom storage type {@link DirectDataBufferInt}, the resulting
+ * {@link BufferedImage}'s {@link BufferedImage#getType() image-type} is of {@link BufferedImage#TYPE_CUSTOM TYPE_CUSTOM}.
+ * We are not able to change this detail, since the AWT image implementation associates the {@link BufferedImage#getType() image-type}
+ * with a build-in storage-type.
+ * Use {@link BufferedImageInt#getCustomType()} to retrieve the custom image-type, which will return the <code>imageType</code>
+ * value passed here.
+ * </p>
+ *
+ * @param width
+ * @param height
+ * @param imageType one of {@link BufferedImage#TYPE_INT_ARGB TYPE_INT_ARGB}, {@link BufferedImage#TYPE_INT_ARGB_PRE TYPE_INT_ARGB_PRE},
+ * {@link BufferedImage#TYPE_INT_RGB TYPE_INT_RGB} or {@link BufferedImage#TYPE_INT_BGR TYPE_INT_BGR}.
+ * @param location origin, if <code>null</code> 0/0 is assumed.
+ * @param properties <code>Hashtable</code> of
+ * <code>String</code>/<code>Object</code> pairs. Used for {@link BufferedImage#getProperty(String)} etc.
+ * @return
+ */
+ public static BufferedImageInt createBufferedImage(final int width, final int height, final int imageType, Point location, final Hashtable<?,?> properties) {
+ final ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ final int transferType = DataBuffer.TYPE_INT;
+ final int bpp, rmask, gmask, bmask, amask;
+ final boolean alphaPreMul;
+ switch( imageType ) {
+ case BufferedImage.TYPE_INT_ARGB:
+ bpp = 32;
+ rmask = 0x00ff0000;
+ gmask = 0x0000ff00;
+ bmask = 0x000000ff;
+ amask = 0xff000000;
+ alphaPreMul = false;
+ break;
+ case BufferedImage.TYPE_INT_ARGB_PRE:
+ bpp = 32;
+ rmask = 0x00ff0000;
+ gmask = 0x0000ff00;
+ bmask = 0x000000ff;
+ amask = 0xff000000;
+ alphaPreMul = true;
+ break;
+ case BufferedImage.TYPE_INT_RGB:
+ bpp = 24;
+ rmask = 0x00ff0000;
+ gmask = 0x0000ff00;
+ bmask = 0x000000ff;
+ amask = 0x0;
+ alphaPreMul = false;
+ break;
+ case BufferedImage.TYPE_INT_BGR:
+ bpp = 24;
+ rmask = 0x000000ff;
+ gmask = 0x0000ff00;
+ bmask = 0x00ff0000;
+ amask = 0x0;
+ alphaPreMul = false;
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported imageType, must be [INT_ARGB, INT_ARGB_PRE, INT_RGB, INT_BGR], has "+imageType);
+ }
+ final ColorModel colorModel = new DirectColorModel(colorSpace, bpp, rmask, gmask, bmask, amask, alphaPreMul, transferType);
+ final int[] bandMasks;
+ if ( 0 != amask ) {
+ bandMasks = new int[4];
+ bandMasks[3] = amask;
+ }
+ else {
+ bandMasks = new int[3];
+ }
+ bandMasks[0] = rmask;
+ bandMasks[1] = gmask;
+ bandMasks[2] = bmask;
+
+ final DirectDataBufferInt dataBuffer = new DirectDataBufferInt(width*height);
+ if( null == location ) {
+ location = new Point(0,0);
+ }
+ final SinglePixelPackedSampleModel sppsm = new SinglePixelPackedSampleModel(dataBuffer.getDataType(),
+ width, height, width /* scanLineStride */, bandMasks);
+ // IntegerComponentRasters must haveinteger DataBuffers:
+ // final WritableRaster raster = new IntegerInterleavedRaster(sppsm, dataBuffer, location);
+ // Not public:
+ // final WritableRaster raster = new SunWritableRaster(sppsm, dataBuffer, location);
+ final WritableRaster raster = new DirectWritableRaster(sppsm, dataBuffer, location);
+
+ return new BufferedImageInt(imageType, colorModel, raster, properties);
+ }
+
+ /** Default data bank. */
+ private final IntBuffer data;
+
+ /** All data banks */
+ private final IntBuffer bankdata[];
+
+ /**
+ * Constructs an nio integer-based {@link DataBuffer} with a single bank
+ * and the specified size.
+ *
+ * @param size The size of the {@link DataBuffer}.
+ */
+ public DirectDataBufferInt(final int size) {
+ super(TYPE_INT, size);
+ data = Buffers.newDirectIntBuffer(size);
+ bankdata = new IntBuffer[1];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs an nio integer-based {@link DataBuffer} with the specified number of
+ * banks, all of which are the specified size.
+ *
+ * @param size The size of the banks in the {@link DataBuffer}.
+ * @param numBanks The number of banks in the a{@link DataBuffer}.
+ */
+ public DirectDataBufferInt(final int size, final int numBanks) {
+ super(TYPE_INT,size,numBanks);
+ bankdata = new IntBuffer[numBanks];
+ for (int i= 0; i < numBanks; i++) {
+ bankdata[i] = Buffers.newDirectIntBuffer(size);
+ }
+ data = bankdata[0];
+ }
+
+ /**
+ * Constructs an nio integer-based {@link DataBuffer} with a single bank using the
+ * specified array.
+ * <p>
+ * Only the first <code>size</code> elements should be used by accessors of
+ * this {@link DataBuffer}. <code>dataArray</code> must be large enough to
+ * hold <code>size</code> elements.
+ * </p>
+ *
+ * @param dataArray The integer array for the {@link DataBuffer}.
+ * @param size The size of the {@link DataBuffer} bank.
+ */
+ public DirectDataBufferInt(final IntBuffer dataArray, final int size) {
+ super(TYPE_INT,size);
+ data = dataArray;
+ bankdata = new IntBuffer[1];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Returns the default (first) int data array in {@link DataBuffer}.
+ *
+ * @return The first integer data array.
+ */
+ public IntBuffer getData() {
+ return data;
+ }
+
+ /**
+ * Returns the data array for the specified bank.
+ *
+ * @param bank The bank whose data array you want to get.
+ * @return The data array for the specified bank.
+ */
+ public IntBuffer getData(final int bank) {
+ return bankdata[bank];
+ }
+
+ /**
+ * Returns the requested data array element from the first (default) bank.
+ *
+ * @param i The data array element you want to get.
+ * @return The requested data array element as an integer.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ @Override
+ public int getElem(final int i) {
+ return data.get(i+offset);
+ }
+
+ /**
+ * Returns the requested data array element from the specified bank.
+ *
+ * @param bank The bank from which you want to get a data array element.
+ * @param i The data array element you want to get.
+ * @return The requested data array element as an integer.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ @Override
+ public int getElem(final int bank, final int i) {
+ return bankdata[bank].get(i+offsets[bank]);
+ }
+
+ /**
+ * Sets the requested data array element in the first (default) bank
+ * to the specified value.
+ *
+ * @param i The data array element you want to set.
+ * @param val The integer value to which you want to set the data array element.
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ @Override
+ public void setElem(final int i, final int val) {
+ data.put(i+offset, val);
+ }
+
+ /**
+ * Sets the requested data array element in the specified bank
+ * to the integer value <code>i</code>.
+ * @param bank The bank in which you want to set the data array element.
+ * @param i The data array element you want to set.
+ * @param val The integer value to which you want to set the specified data array element.
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ @Override
+ public void setElem(final int bank, final int i, final int val) {
+ bankdata[bank].put(i+offsets[bank], val);
+ }
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index a62d08ccf..6498ebd1e 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -37,13 +37,22 @@
package com.jogamp.nativewindow.awt;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import java.awt.Component;
import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.Window;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
import java.applet.Applet;
+
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.CapabilitiesImmutable;
@@ -52,29 +61,37 @@ import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.OffscreenLayerOption;
import javax.media.nativewindow.OffscreenLayerSurface;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.nativewindow.SurfaceUpdatedListener;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.PixelRectangle;
import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
import javax.media.nativewindow.util.Rectangle;
import javax.media.nativewindow.util.RectangleImmutable;
+import jogamp.common.os.PlatformPropsImpl;
+import jogamp.nativewindow.SurfaceScaleUtils;
import jogamp.nativewindow.SurfaceUpdatedHelper;
+import jogamp.nativewindow.awt.AWTMisc;
import jogamp.nativewindow.jawt.JAWT;
import jogamp.nativewindow.jawt.JAWTUtil;
import jogamp.nativewindow.jawt.JAWT_Rectangle;
-public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, OffscreenLayerOption {
+public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, OffscreenLayerOption, ScalableSurface {
protected static final boolean DEBUG = JAWTUtil.DEBUG;
// user properties
protected boolean shallUseOffscreenLayer = false;
// lifetime: forever
- protected Component component;
- private AWTGraphicsConfiguration config; // control access due to delegation
- private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
- private RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
+ protected final Component component;
+ private final AppContextInfo appContextInfo;
+ private final AWTGraphicsConfiguration config; // control access due to delegation
+ private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
+ private final RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
+ private final JAWTComponentListener jawtComponentListener;
// lifetime: valid after lock but may change with each 1st lock, purges after invalidate
private boolean isApplet;
@@ -83,7 +100,11 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
protected long drawable;
protected Rectangle bounds;
protected Insets insets;
- private long offscreenSurfaceLayer;
+ private volatile long offscreenSurfaceLayer;
+
+ private final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ protected final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
private long drawable_old;
@@ -94,25 +115,150 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
* @param comp
* @param config
*/
- protected JAWTWindow(Object comp, AbstractGraphicsConfiguration config) {
+ protected JAWTWindow(final Object comp, final AbstractGraphicsConfiguration config) {
if (config == null) {
throw new NativeWindowException("Error: AbstractGraphicsConfiguration is null");
}
if(! ( config instanceof AWTGraphicsConfiguration ) ) {
throw new NativeWindowException("Error: AbstractGraphicsConfiguration is not an AWTGraphicsConfiguration: "+config);
}
+ appContextInfo = new AppContextInfo("<init>");
+ this.component = (Component)comp;
this.config = (AWTGraphicsConfiguration) config;
- init((Component)comp);
- }
-
- private void init(Component windowObject) throws NativeWindowException {
+ this.jawtComponentListener = new JAWTComponentListener();
invalidate();
- this.component = windowObject;
this.isApplet = false;
this.offscreenSurfaceLayer = 0;
}
+ private static String id(final Object obj) { return ( null!=obj ? toHexString(obj.hashCode()) : "nil" ); }
+ private String jawtStr() { return "JAWTWindow["+id(JAWTWindow.this)+"]"; }
+
+ private class JAWTComponentListener implements ComponentListener, HierarchyListener {
+ private boolean isShowing;
+
+ private String str(final Object obj) {
+ if( null == obj ) {
+ return "0xnil: null";
+ } else if( obj instanceof Component ) {
+ final Component c = (Component)obj;
+ return id(obj)+": "+c.getClass().getSimpleName()+"[visible "+c.isVisible()+", showing "+c.isShowing()+", valid "+c.isValid()+
+ ", displayable "+c.isDisplayable()+", "+c.getX()+"/"+c.getY()+" "+c.getWidth()+"x"+c.getHeight()+"]";
+ } else {
+ return id(obj)+": "+obj.getClass().getSimpleName()+"[..]";
+ }
+ }
+ private String s(final ComponentEvent e) {
+ return "visible[isShowing "+isShowing+"],"+Platform.getNewline()+
+ " ** COMP "+str(e.getComponent())+Platform.getNewline()+
+ " ** SOURCE "+str(e.getSource())+Platform.getNewline()+
+ " ** THIS "+str(component)+Platform.getNewline()+
+ " ** THREAD "+getThreadName();
+ }
+ private String s(final HierarchyEvent e) {
+ return "visible[isShowing "+isShowing+"], changeBits 0x"+Long.toHexString(e.getChangeFlags())+Platform.getNewline()+
+ " ** COMP "+str(e.getComponent())+Platform.getNewline()+
+ " ** SOURCE "+str(e.getSource())+Platform.getNewline()+
+ " ** CHANGED "+str(e.getChanged())+Platform.getNewline()+
+ " ** CHANGEDPARENT "+str(e.getChangedParent())+Platform.getNewline()+
+ " ** THIS "+str(component)+Platform.getNewline()+
+ " ** THREAD "+getThreadName();
+ }
+ @Override
+ public final String toString() {
+ return "visible[isShowing "+isShowing+"],"+Platform.getNewline()+
+ " ** THIS "+str(component)+Platform.getNewline()+
+ " ** THREAD "+getThreadName();
+ }
+
+ private JAWTComponentListener() {
+ isShowing = component.isShowing();
+ AWTEDTExecutor.singleton.invoke(false, new Runnable() { // Bug 952: Avoid deadlock via AWTTreeLock acquisition ..
+ @Override
+ public void run() {
+ if(DEBUG) {
+ System.err.println(jawtStr()+".attach @ Thread "+getThreadName()+": "+JAWTComponentListener.this.toString());
+ }
+ component.addComponentListener(JAWTComponentListener.this);
+ component.addHierarchyListener(JAWTComponentListener.this);
+ } } );
+ }
+
+ private final void detach() {
+ AWTEDTExecutor.singleton.invoke(false, new Runnable() { // Bug 952: Avoid deadlock via AWTTreeLock acquisition ..
+ @Override
+ public void run() {
+ if(DEBUG) {
+ System.err.println(jawtStr()+".detach @ Thread "+getThreadName()+": "+JAWTComponentListener.this.toString());
+ }
+ component.removeComponentListener(JAWTComponentListener.this);
+ component.removeHierarchyListener(JAWTComponentListener.this);
+ } } );
+ }
+
+ @Override
+ public final void componentResized(final ComponentEvent e) {
+ if(DEBUG) {
+ System.err.println(jawtStr()+".componentResized: "+s(e));
+ }
+ layoutSurfaceLayerIfEnabled(isShowing);
+ }
+
+ @Override
+ public final void componentMoved(final ComponentEvent e) {
+ if(DEBUG) {
+ System.err.println(jawtStr()+".componentMoved: "+s(e));
+ }
+ layoutSurfaceLayerIfEnabled(isShowing);
+ }
+
+ @Override
+ public final void componentShown(final ComponentEvent e) {
+ if(DEBUG) {
+ System.err.println(jawtStr()+".componentShown: "+s(e));
+ }
+ layoutSurfaceLayerIfEnabled(isShowing);
+ }
+
+ @Override
+ public final void componentHidden(final ComponentEvent e) {
+ if(DEBUG) {
+ System.err.println(jawtStr()+".componentHidden: "+s(e));
+ }
+ layoutSurfaceLayerIfEnabled(isShowing);
+ }
+
+ @Override
+ public final void hierarchyChanged(final HierarchyEvent e) {
+ final boolean wasShowing = isShowing;
+ isShowing = component.isShowing();
+ int action = 0;
+ if( 0 != ( java.awt.event.HierarchyEvent.SHOWING_CHANGED & e.getChangeFlags() ) ) {
+ if( e.getChanged() != component && wasShowing != isShowing ) {
+ // A parent component changed and caused a 'showing' state change,
+ // propagate to offscreen-layer!
+ layoutSurfaceLayerIfEnabled(isShowing);
+ action = 1;
+ }
+ }
+ if(DEBUG) {
+ final java.awt.Component changed = e.getChanged();
+ final boolean displayable = changed.isDisplayable();
+ final boolean showing = changed.isShowing();
+ System.err.println(jawtStr()+".hierarchyChanged: action "+action+", displayable "+displayable+", showing [changed "+showing+", comp "+isShowing+"], "+s(e));
+ }
+ }
+ }
+
+ private static String getThreadName() { return Thread.currentThread().getName(); }
protected synchronized void invalidate() {
+ if(DEBUG) {
+ System.err.println(jawtStr()+".invalidate() - "+jawtComponentListener.toString());
+ if( isSurfaceLayerAttached() ) {
+ System.err.println("OffscreenSurfaceLayer still attached: 0x"+Long.toHexString(offscreenSurfaceLayer));
+ }
+ // Thread.dumpStack();
+ }
invalidateNative();
jawt = null;
isOffscreenLayerSurface = false;
@@ -120,37 +266,88 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
drawable_old = 0;
bounds = new Rectangle();
insets = new Insets();
+ hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
}
protected abstract void invalidateNative();
- protected final boolean updateBounds(JAWT_Rectangle jawtBounds) {
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Per default impl. only works for not yet {@link #isRealized() realized} instances,
+ * current exception OSX.
+ * </p>
+ */
+ @Override
+ public void setSurfaceScale(final int[] pixelScale) {
+ SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG ? getClass().getSimpleName() : null);
+ }
+
+ @Override
+ public final int[] getRequestedSurfaceScale(final int[] result) {
+ System.arraycopy(reqPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final int[] getCurrentSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final int[] getNativeSurfaceScale(final int[] result) {
+ System.arraycopy(nativePixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ /**
+ * Updates bounds and pixelScale
+ * @return true if bounds or pixelScale has changed, otherwise false
+ */
+ protected final boolean updateLockedData(final JAWT_Rectangle jawtBounds) {
final Rectangle jb = new Rectangle(jawtBounds.getX(), jawtBounds.getY(), jawtBounds.getWidth(), jawtBounds.getHeight());
- final boolean changed = !bounds.equals(jb);
-
- if(changed) {
- if(DEBUG) {
+ final boolean changedBounds = !bounds.equals(jb);
+
+ if( changedBounds ) {
+ if( DEBUG ) {
System.err.println("JAWTWindow.updateBounds: "+bounds+" -> "+jb);
- Thread.dumpStack();
}
- bounds.setX(jawtBounds.getX());
- bounds.setY(jawtBounds.getY());
- bounds.setWidth(jawtBounds.getWidth());
- bounds.setHeight(jawtBounds.getHeight());
-
+ bounds.set(jawtBounds.getX(), jawtBounds.getY(), jawtBounds.getWidth(), jawtBounds.getHeight());
+
if(component instanceof Container) {
- java.awt.Insets contInsets = ((Container)component).getInsets();
- insets.setLeftWidth(contInsets.left);
- insets.setRightWidth(contInsets.right);
- insets.setTopHeight(contInsets.top);
- insets.setBottomHeight(contInsets.bottom);
+ final java.awt.Insets contInsets = ((Container)component).getInsets();
+ insets.set(contInsets.left, contInsets.right, contInsets.top, contInsets.bottom);
}
}
- return changed;
+ {
+ final int ps = JAWTUtil.getPixelScale(config.getAWTGraphicsConfiguration());
+ nativePixelScale[0] = ps;
+ nativePixelScale[1] = ps;
+ }
+
+ return updatePixelScale() || changedBounds;
+ }
+
+ /**
+ * Update pixelScale
+ * @return true if pixelScale has changed, otherwise false
+ */
+ protected final boolean updatePixelScale() {
+ return SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null);
}
/** @return the JAWT_DrawingSurfaceInfo's (JAWT_Rectangle) bounds, updated with lock */
public final RectangleImmutable getBounds() { return bounds; }
+ /** @return the safe pixelScale value for x-direction, i.e. never negative or zero. Updated with lock. */
+ protected final int getPixelScaleX() { return hasPixelScale[0]; }
+
+ /** @return the safe pixelScale value for y-direction, i.e. never negative or zero. Updated with lock. */
+ protected final int getPixelScaleY() { return hasPixelScale[1]; }
+
@Override
public final InsetsImmutable getInsets() { return insets; }
@@ -174,9 +371,9 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
//
// OffscreenLayerOption
//
-
+
@Override
- public void setShallUseOffscreenLayer(boolean v) {
+ public void setShallUseOffscreenLayer(final boolean v) {
shallUseOffscreenLayer = v;
}
@@ -199,83 +396,126 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
if( !isOffscreenLayerSurfaceEnabled() ) {
throw new NativeWindowException("Not an offscreen layer surface");
}
- int lockRes = lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
- throw new NativeWindowException("Could not lock (offscreen layer): "+this);
- }
- try {
- if(DEBUG) {
- System.err.println("JAWTWindow.attachSurfaceHandle(): 0x"+Long.toHexString(layerHandle) + ", bounds "+bounds);
- }
- attachSurfaceLayerImpl(layerHandle);
- offscreenSurfaceLayer = layerHandle;
- } finally {
- unlockSurface();
+ attachSurfaceLayerImpl(layerHandle);
+ offscreenSurfaceLayer = layerHandle;
+ appContextInfo.invokeOnAppContextThread(false /* waitUntilDone */, repaintTask, "Repaint");
+ }
+ private final Runnable repaintTask = new Runnable() {
+ @Override
+ public void run() {
+ final Component c = component;
+ if( DEBUG ) {
+ System.err.println("Bug 1004: RepaintTask on "+Thread.currentThread()+": Has Comp "+(null != c));
+ }
+ if( null != c ) {
+ c.repaint();
+ }
+ } };
+
+ protected void attachSurfaceLayerImpl(final long layerHandle) {
+ throw new UnsupportedOperationException("offscreen layer not supported");
+ }
+
+ /**
+ * Layout the offscreen layer according to the implementing class's constraints.
+ * <p>
+ * This method allows triggering a re-layout of the offscreen surface
+ * in case the implementation requires it.
+ * </p>
+ * <p>
+ * Call this method if any parent or ancestor's layout has been changed,
+ * which could affects the layout of this surface.
+ * </p>
+ * @see #isOffscreenLayerSurfaceEnabled()
+ * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
+ */
+ protected void layoutSurfaceLayerImpl(final long layerHandle, final boolean visible) {}
+
+ private final void layoutSurfaceLayerIfEnabled(final boolean visible) throws NativeWindowException {
+ if( isOffscreenLayerSurfaceEnabled() && 0 != offscreenSurfaceLayer ) {
+ layoutSurfaceLayerImpl(offscreenSurfaceLayer, visible);
}
}
- protected abstract void attachSurfaceLayerImpl(final long layerHandle);
+
@Override
public final void detachSurfaceLayer() throws NativeWindowException {
- if( !isOffscreenLayerSurfaceEnabled() ) {
- throw new java.lang.UnsupportedOperationException("Not an offscreen layer surface");
- }
if( 0 == offscreenSurfaceLayer) {
throw new NativeWindowException("No offscreen layer attached: "+this);
}
- int lockRes = lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
- throw new NativeWindowException("Could not lock (offscreen layer): "+this);
- }
- try {
- if(DEBUG) {
- System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(offscreenSurfaceLayer));
- }
- detachSurfaceLayerImpl(offscreenSurfaceLayer);
- offscreenSurfaceLayer = 0;
- } finally {
- unlockSurface();
+ if(DEBUG) {
+ System.err.println("JAWTWindow.detachSurfaceHandle(): osh "+toHexString(offscreenSurfaceLayer));
}
+ detachSurfaceLayerImpl(offscreenSurfaceLayer, detachSurfaceLayerNotify);
+ }
+ private final Runnable detachSurfaceLayerNotify = new Runnable() {
+ @Override
+ public void run() {
+ offscreenSurfaceLayer = 0;
+ }
+ };
+
+ /**
+ * @param detachNotify Runnable to be called before native detachment
+ */
+ protected void detachSurfaceLayerImpl(final long layerHandle, final Runnable detachNotify) {
+ throw new UnsupportedOperationException("offscreen layer not supported");
}
- protected abstract void detachSurfaceLayerImpl(final long layerHandle);
- protected final long getAttachedSurfaceLayer() {
+
+ @Override
+ public final long getAttachedSurfaceLayer() {
return offscreenSurfaceLayer;
}
-
+
@Override
public final boolean isSurfaceLayerAttached() {
return 0 != offscreenSurfaceLayer;
}
-
- @Override
- public final void setChosenCapabilities(CapabilitiesImmutable caps) {
- ((MutableGraphicsConfiguration)getGraphicsConfiguration()).setChosenCapabilities(caps);
- getPrivateGraphicsConfiguration().setChosenCapabilities(caps);
- }
-
- //
- // SurfaceUpdateListener
- //
@Override
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
+ public final void setChosenCapabilities(final CapabilitiesImmutable caps) {
+ ((MutableGraphicsConfiguration)getGraphicsConfiguration()).setChosenCapabilities(caps);
+ config.setChosenCapabilities(caps);
}
@Override
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
+ public final RecursiveLock getLock() {
+ return surfaceLock;
}
@Override
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+ public final boolean setCursor(final PixelRectangle pixelrect, final PointImmutable hotSpot) {
+ AWTEDTExecutor.singleton.invoke(false, new Runnable() {
+ public void run() {
+ Cursor c = null;
+ if( null == pixelrect || null == hotSpot ) {
+ c = Cursor.getDefaultCursor();
+ } else {
+ final java.awt.Point awtHotspot = new java.awt.Point(hotSpot.getX(), hotSpot.getY());
+ try {
+ c = AWTMisc.getCursor(pixelrect, awtHotspot);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ if( null != c ) {
+ component.setCursor(c);
+ }
+ } } );
+ return true;
}
@Override
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
+ public final boolean hideCursor() {
+ AWTEDTExecutor.singleton.invoke(false, new Runnable() {
+ public void run() {
+ final Cursor cursor = AWTMisc.getNullCursor();
+ if( null != cursor ) {
+ component.setCursor(cursor);
+ }
+ } } );
+ return true;
}
//
@@ -303,13 +543,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
protected abstract int lockSurfaceImpl() throws NativeWindowException;
protected void dumpJAWTInfo() {
- if(null != jawt) {
- System.err.println("JAWT version: 0x"+Integer.toHexString(jawt.getCachedVersion())+
- ", CA_LAYER: "+ JAWTUtil.isJAWTUsingOffscreenLayer(jawt)+
- ", isLayeredSurface "+isOffscreenLayerSurfaceEnabled()+", bounds "+bounds+", insets "+insets);
- } else {
- System.err.println("JAWT n/a, bounds "+bounds+", insets "+insets);
- }
+ System.err.println(jawt2String(null).toString());
// Thread.dumpStack();
}
@@ -319,32 +553,41 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
if ( LOCK_SURFACE_NOT_READY == res ) {
- determineIfApplet();
- try {
- final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
- adevice.lock();
+ if( !component.isDisplayable() ) {
+ // W/o native peer, we cannot utilize JAWT for locking.
+ surfaceLock.unlock();
+ if(DEBUG) {
+ System.err.println("JAWTWindow: Can't lock surface, component peer n/a. Component displayable "+component.isDisplayable()+", "+component);
+ Thread.dumpStack();
+ }
+ } else {
+ determineIfApplet();
try {
- if(null == jawt) { // no need to re-fetch for each frame
- jawt = fetchJAWTImpl();
- isOffscreenLayerSurface = JAWTUtil.isJAWTUsingOffscreenLayer(jawt);
- }
- res = lockSurfaceImpl();
- if(LOCK_SUCCESS == res && drawable_old != drawable) {
- res = LOCK_SURFACE_CHANGED;
- if(DEBUG) {
- System.err.println("JAWTWindow: surface change 0x"+Long.toHexString(drawable_old)+" -> 0x"+Long.toHexString(drawable));
- // Thread.dumpStack();
+ final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
+ adevice.lock();
+ try {
+ if(null == jawt) { // no need to re-fetch for each frame
+ jawt = fetchJAWTImpl();
+ isOffscreenLayerSurface = JAWTUtil.isJAWTUsingOffscreenLayer(jawt);
+ }
+ res = lockSurfaceImpl();
+ if(LOCK_SUCCESS == res && drawable_old != drawable) {
+ res = LOCK_SURFACE_CHANGED;
+ if(DEBUG) {
+ System.err.println("JAWTWindow: surface change "+toHexString(drawable_old)+" -> "+toHexString(drawable));
+ // Thread.dumpStack();
+ }
+ }
+ } finally {
+ if (LOCK_SURFACE_NOT_READY >= res) {
+ adevice.unlock();
}
}
} finally {
if (LOCK_SURFACE_NOT_READY >= res) {
- adevice.unlock();
+ surfaceLock.unlock();
}
}
- } finally {
- if (LOCK_SURFACE_NOT_READY >= res) {
- surfaceLock.unlock();
- }
}
}
return res;
@@ -386,19 +629,35 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
@Override
- public long getSurfaceHandle() {
- return drawable;
+ public void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
+ }
+
+ @Override
+ public void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
+ surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
}
- public final AWTGraphicsConfiguration getPrivateGraphicsConfiguration() {
- return config;
+ @Override
+ public long getSurfaceHandle() {
+ return drawable;
}
@Override
public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
return config.getNativeGraphicsConfiguration();
}
-
+
@Override
public final long getDisplayHandle() {
return getGraphicsConfiguration().getScreen().getDevice().getHandle();
@@ -410,25 +669,55 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
@Override
- public final int getWidth() {
- return component.getWidth();
+ public final int getSurfaceWidth() {
+ return getWidth() * getPixelScaleX();
}
@Override
- public final int getHeight() {
- return component.getHeight();
+ public final int getSurfaceHeight() {
+ return getHeight() * getPixelScaleY();
}
+ @Override
+ public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
+ pixelUnitsAndResult[0] /= getPixelScaleX();
+ pixelUnitsAndResult[1] /= getPixelScaleY();
+ return pixelUnitsAndResult;
+ }
+
+ @Override
+ public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
+ windowUnitsAndResult[0] *= getPixelScaleX();
+ windowUnitsAndResult[1] *= getPixelScaleY();
+ return windowUnitsAndResult;
+ }
+
+ @Override
+ public final NativeSurface getNativeSurface() { return this; }
+
//
// NativeWindow
//
@Override
+ public final int getWidth() {
+ return component.getWidth();
+ }
+
+ @Override
+ public final int getHeight() {
+ return component.getHeight();
+ }
+
+ @Override
public void destroy() {
surfaceLock.lock();
try {
+ if(DEBUG) {
+ System.err.println(jawtStr()+".destroy @ Thread "+getThreadName());
+ }
+ jawtComponentListener.detach();
invalidate();
- component = null; // don't dispose the AWT component, since we are merely an immutable uplink
} finally {
surfaceLock.unlock();
}
@@ -478,9 +767,13 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
System.err.println("Warning: JAWT Lock hold, but not the AWT tree lock: "+this);
Thread.dumpStack();
}
- return getLocationOnScreenNonBlocking(storage, component);
+ if( null == storage ) {
+ storage = new Point();
+ }
+ getLocationOnScreenNonBlocking(storage, component);
+ return storage;
}
- java.awt.Point awtLOS = component.getLocationOnScreen();
+ final java.awt.Point awtLOS = component.getLocationOnScreen();
if(null!=storage) {
los = storage.translate(awtLOS.x, awtLOS.y);
} else {
@@ -490,8 +783,8 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
return los;
}
- protected Point getLocationOnScreenNative(Point storage) {
- int lockRes = lockSurface();
+ protected Point getLocationOnScreenNative(final Point storage) {
+ final int lockRes = lockSurface();
if(LOCK_SURFACE_NOT_READY == lockRes) {
if(DEBUG) {
System.err.println("Warning: JAWT Lock couldn't be acquired: "+this);
@@ -500,7 +793,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
return null;
}
try {
- Point d = getLocationOnScreenNativeImpl(0, 0);
+ final Point d = getLocationOnScreenNativeImpl(0, 0);
if(null!=d) {
if(null!=storage) {
storage.translate(d.getX(),d.getY());
@@ -514,19 +807,33 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
protected abstract Point getLocationOnScreenNativeImpl(int x, int y);
- protected static Point getLocationOnScreenNonBlocking(Point storage, Component comp) {
- int x = 0;
- int y = 0;
+ protected static Component getLocationOnScreenNonBlocking(final Point storage, Component comp) {
+ final java.awt.Insets insets = new java.awt.Insets(0, 0, 0, 0); // DEBUG
+ Component last = null;
while(null != comp) {
- x += comp.getX();
- y += comp.getY();
+ final int dx = comp.getX();
+ final int dy = comp.getY();
+ if( DEBUG ) {
+ final java.awt.Insets ins = AWTMisc.getInsets(comp, false);
+ if( null != ins ) {
+ insets.bottom += ins.bottom;
+ insets.top += ins.top;
+ insets.left += ins.left;
+ insets.right += ins.right;
+ }
+ System.err.print("LOS: "+storage+" + "+comp.getClass().getName()+"["+dx+"/"+dy+", vis "+comp.isVisible()+", ins "+ins+" -> "+insets+"] -> ");
+ }
+ storage.translate(dx, dy);
+ if( DEBUG ) {
+ System.err.println(storage);
+ }
+ last = comp;
+ if( comp instanceof Window ) { // top-level heavy-weight ?
+ break;
+ }
comp = comp.getParent();
}
- if(null!=storage) {
- storage.translate(x, y);
- return storage;
- }
- return new Point(x, y);
+ return last;
}
@Override
@@ -534,26 +841,53 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
return component.hasFocus();
}
+ protected StringBuilder jawt2String(StringBuilder sb) {
+ if( null == sb ) {
+ sb = new StringBuilder();
+ }
+ sb.append("JVM version: ").append(PlatformPropsImpl.JAVA_VERSION).append(" (").
+ append(PlatformPropsImpl.JAVA_VERSION_NUMBER).
+ append(" update ").append(PlatformPropsImpl.JAVA_VERSION_UPDATE).append(")").append(Platform.getNewline());
+ if(null != jawt) {
+ sb.append("JAWT version: ").append(toHexString(jawt.getCachedVersion())).
+ append(", CA_LAYER: ").append(JAWTUtil.isJAWTUsingOffscreenLayer(jawt)).
+ append(", isLayeredSurface ").append(isOffscreenLayerSurfaceEnabled()).
+ append(", bounds ").append(bounds).append(", insets ").append(insets).
+ append(", pixelScale ").append(getPixelScaleX()).append("x").append(getPixelScaleY());
+ } else {
+ sb.append("JAWT n/a, bounds ").append(bounds).append(", insets ").append(insets);
+ }
+ return sb;
+ }
+
@Override
public String toString() {
- StringBuilder sb = new StringBuilder();
-
- sb.append("JAWT-Window["+
- "windowHandle 0x"+Long.toHexString(getWindowHandle())+
- ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+
- ", bounds "+bounds+", insets "+insets+
- ", shallUseOffscreenLayer "+shallUseOffscreenLayer+", isOffscreenLayerSurface "+isOffscreenLayerSurface);
- if(null!=component) {
- sb.append(", pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
- ", visible "+component.isVisible());
- } else {
- sb.append(", component NULL");
- }
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(jawtStr()+"[");
+ jawt2String(sb);
+ sb.append( ", shallUseOffscreenLayer "+shallUseOffscreenLayer+", isOffscreenLayerSurface "+isOffscreenLayerSurface+
+ ", attachedSurfaceLayer "+toHexString(getAttachedSurfaceLayer())+
+ ", windowHandle "+toHexString(getWindowHandle())+
+ ", surfaceHandle "+toHexString(getSurfaceHandle())+
+ ", bounds "+bounds+", insets "+insets
+ );
+ sb.append(", window ["+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+
+ "], pixels[s "+getPixelScaleX()+"x"+getPixelScaleY()+" -> "+getSurfaceWidth()+"x"+getSurfaceHeight()+"]"+
+ ", visible "+component.isVisible());
sb.append(", lockedExt "+isSurfaceLockedByOtherThread()+
- ",\n\tconfig "+getPrivateGraphicsConfiguration()+
+ ",\n\tconfig "+config+
",\n\tawtComponent "+getAWTComponent()+
",\n\tsurfaceLock "+surfaceLock+"]");
return sb.toString();
}
+
+ protected static final String toHexString(final long l) {
+ return "0x"+Long.toHexString(l);
+ }
+ protected static final String toHexString(final int i) {
+ return "0x"+Integer.toHexString(i);
+ }
+
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
index b824350ff..d21994ea5 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -38,14 +38,14 @@ import javax.media.nativewindow.*;
*/
public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
final long[] nativeDisplayID = new long[1];
- final EGLDisplayLifecycleCallback eglLifecycleCallback;
+ /* final */ EGLDisplayLifecycleCallback eglLifecycleCallback;
/**
* Hack to allow inject a EGL termination call.
* <p>
* FIXME: This shall be removed when relocated EGL to the nativewindow package,
* since then it can be utilized directly.
- * </p>
+ * </p>
*/
public interface EGLDisplayLifecycleCallback {
/**
@@ -55,14 +55,14 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
* @return the initialized EGL display ID, or <code>0</code> if not successful
*/
public long eglGetAndInitDisplay(long[] nativeDisplayID);
-
+
/**
* Implementation should issue an <code>EGL.eglTerminate(eglDisplayHandle)</code> call.
* @param eglDisplayHandle
*/
void eglTerminate(long eglDisplayHandle);
}
-
+
/**
* Note that this is not an open connection, ie no native display handle exist.
* This constructor exist to setup a default device connection/unit.<br>
@@ -73,19 +73,25 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
this.eglLifecycleCallback = null;
}
- public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLDisplayLifecycleCallback eglLifecycleCallback) {
+ public EGLGraphicsDevice(final long nativeDisplayID, final long eglDisplay, final String connection, final int unitID, final EGLDisplayLifecycleCallback eglLifecycleCallback) {
super(NativeWindowFactory.TYPE_EGL, connection, unitID, eglDisplay);
this.nativeDisplayID[0] = nativeDisplayID;
this.eglLifecycleCallback = eglLifecycleCallback;
}
-
+
public long getNativeDisplayID() { return nativeDisplayID[0]; }
-
+
@Override
public Object clone() {
return super.clone();
}
+ /**
+ * Opens the EGL device if handle is null and it's {@link EGLDisplayLifecycleCallback} is valid.
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
@Override
public boolean open() {
if(null != eglLifecycleCallback && 0 == handle) {
@@ -100,7 +106,13 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
}
return false;
}
-
+
+ /**
+ * Closes the EGL device if handle is not null and it's {@link EGLDisplayLifecycleCallback} is valid.
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
@Override
public boolean close() {
if(null != eglLifecycleCallback && 0 != handle) {
@@ -111,10 +123,24 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
}
return super.close();
}
-
+
+ @Override
+ public boolean isHandleOwner() {
+ return null != eglLifecycleCallback;
+ }
+ @Override
+ public void clearHandleOwner() {
+ eglLifecycleCallback = null;
+ }
+ @Override
+ protected Object getHandleOwnership() {
+ return eglLifecycleCallback;
+ }
@Override
- public String toString() {
- return "EGLGraphicsDevice[type EGL, connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", nativeDisplayID 0x"+Long.toHexString(nativeDisplayID[0])+", eglLifecycleCallback "+(null != eglLifecycleCallback)+"]";
+ protected Object setHandleOwnership(final Object newOwnership) {
+ final EGLDisplayLifecycleCallback oldOwnership = eglLifecycleCallback;
+ eglLifecycleCallback = (EGLDisplayLifecycleCallback) newOwnership;
+ return oldOwnership;
}
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/macosx/MacOSXGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/macosx/MacOSXGraphicsDevice.java
index 0dc788c17..ff149447e 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/macosx/MacOSXGraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/macosx/MacOSXGraphicsDevice.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -39,10 +39,11 @@ import javax.media.nativewindow.*;
public class MacOSXGraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
/** Constructs a new MacOSXGraphicsDevice */
- public MacOSXGraphicsDevice(int unitID) {
+ public MacOSXGraphicsDevice(final int unitID) {
super(NativeWindowFactory.TYPE_MACOSX, AbstractGraphicsDevice.DEFAULT_CONNECTION, unitID);
}
+ @Override
public Object clone() {
return super.clone();
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
index 1cc796086..d29e2abbc 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
@@ -30,70 +30,119 @@ package com.jogamp.nativewindow.swt;
import com.jogamp.common.os.Platform;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import javax.media.nativewindow.AbstractGraphicsScreen;
-import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.VisualIDHolder;
import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
-import com.jogamp.nativewindow.x11.X11GraphicsScreen;
import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.nativewindow.x11.X11Lib;
public class SWTAccessor {
- static final Field swt_control_handle;
- static final boolean swt_uses_long_handles;
-
+ private static final boolean DEBUG = true;
+
+ private static final Field swt_control_handle;
+ private static final boolean swt_uses_long_handles;
+
+ private static Object swt_osx_init = new Object();
+ private static Field swt_osx_control_view = null;
+ private static Field swt_osx_view_id = null;
+
+ private static final String nwt;
+ public static final boolean isOSX;
+ public static final boolean isWindows;
+ public static final boolean isX11;
+ public static final boolean isX11GTK;
+
// X11/GTK, Windows/GDI, ..
- static final String str_handle = "handle";
-
+ private static final String str_handle = "handle";
+
// OSX/Cocoa
- static final String str_view = "view"; // OSX
- static final String str_id = "id"; // OSX
+ private static final String str_osx_view = "view"; // OSX
+ private static final String str_osx_id = "id"; // OSX
// static final String str_NSView = "org.eclipse.swt.internal.cocoa.NSView";
-
- static final Method swt_control_internal_new_GC;
- static final Method swt_control_internal_dispose_GC;
- static final String str_internal_new_GC = "internal_new_GC";
- static final String str_internal_dispose_GC = "internal_dispose_GC";
-
- static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS";
- static final Class<?> OS_gtk_class;
- static final Method OS_gtk_widget_realize;
- static final Method OS_gtk_widget_unrealize;
- static final Method OS_GTK_WIDGET_WINDOW;
- static final Method OS_gdk_x11_drawable_get_xdisplay;
- static final Method OS_gdk_x11_drawable_get_xid;
- static final String str_gtk_widget_realize = "gtk_widget_realize";
- static final String str_gtk_widget_unrealize = "gtk_widget_unrealize";
- static final String str_GTK_WIDGET_WINDOW = "GTK_WIDGET_WINDOW";
- static final String str_gdk_x11_drawable_get_xdisplay = "gdk_x11_drawable_get_xdisplay";
- static final String str_gdk_x11_drawable_get_xid = "gdk_x11_drawable_get_xid";
-
+
+ private static final Method swt_control_internal_new_GC;
+ private static final Method swt_control_internal_dispose_GC;
+ private static final String str_internal_new_GC = "internal_new_GC";
+ private static final String str_internal_dispose_GC = "internal_dispose_GC";
+
+ private static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS";
+ public static final Class<?> OS_gtk_class;
+ private static final String str_OS_gtk_version = "GTK_VERSION";
+ public static final VersionNumber OS_gtk_version;
+
+ private static final Method OS_gtk_widget_realize;
+ private static final Method OS_gtk_widget_unrealize; // optional (removed in SWT 4.3)
+ private static final Method OS_GTK_WIDGET_WINDOW;
+ private static final Method OS_gtk_widget_get_window;
+ private static final Method OS_gdk_x11_drawable_get_xdisplay;
+ private static final Method OS_gdk_x11_display_get_xdisplay;
+ private static final Method OS_gdk_window_get_display;
+ private static final Method OS_gdk_x11_drawable_get_xid;
+ private static final Method OS_gdk_x11_window_get_xid;
+ private static final Method OS_gdk_window_set_back_pixmap;
+
+ private static final String str_gtk_widget_realize = "gtk_widget_realize";
+ private static final String str_gtk_widget_unrealize = "gtk_widget_unrealize";
+ private static final String str_GTK_WIDGET_WINDOW = "GTK_WIDGET_WINDOW";
+ private static final String str_gtk_widget_get_window = "gtk_widget_get_window";
+ private static final String str_gdk_x11_drawable_get_xdisplay = "gdk_x11_drawable_get_xdisplay";
+ private static final String str_gdk_x11_display_get_xdisplay = "gdk_x11_display_get_xdisplay";
+ private static final String str_gdk_window_get_display = "gdk_window_get_display";
+ private static final String str_gdk_x11_drawable_get_xid = "gdk_x11_drawable_get_xid";
+ private static final String str_gdk_x11_window_get_xid = "gdk_x11_window_get_xid";
+ private static final String str_gdk_window_set_back_pixmap = "gdk_window_set_back_pixmap";
+
+ private static final VersionNumber GTK_VERSION_2_14_0 = new VersionNumber(2, 14, 0);
+ private static final VersionNumber GTK_VERSION_2_24_0 = new VersionNumber(2, 24, 0);
+ private static final VersionNumber GTK_VERSION_3_0_0 = new VersionNumber(3, 0, 0);
+
+ private static VersionNumber GTK_VERSION(final int version) {
+ // return (major << 16) + (minor << 8) + micro;
+ final int micro = ( version ) & 0x0f;
+ final int minor = ( version >> 8 ) & 0x0f;
+ final int major = ( version >> 16 ) & 0x0f;
+ return new VersionNumber(major, minor, micro);
+ }
+
static {
- Field f = null;
-
- final String nwt = NativeWindowFactory.getNativeWindowType(false);
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ NativeWindowFactory.initSingleton(); // last resort ..
+ return null;
+ } } );
- if(NativeWindowFactory.TYPE_MACOSX != nwt ) {
+ nwt = NativeWindowFactory.getNativeWindowType(false);
+ isOSX = NativeWindowFactory.TYPE_MACOSX == nwt;
+ isWindows = NativeWindowFactory.TYPE_WINDOWS == nwt;
+ isX11 = NativeWindowFactory.TYPE_X11 == nwt;
+
+ Field f = null;
+ if( !isOSX ) {
try {
f = Control.class.getField(str_handle);
- } catch (Exception ex) {
+ } catch (final Exception ex) {
throw new NativeWindowException(ex);
}
- }
+ }
swt_control_handle = f; // maybe null !
-
+
boolean ulh;
if (null != swt_control_handle) {
ulh = swt_control_handle.getGenericType().toString().equals(long.class.toString());
@@ -103,164 +152,291 @@ public class SWTAccessor {
swt_uses_long_handles = ulh;
// System.err.println("SWT long handles: " + swt_uses_long_handles);
// System.err.println("Platform 64bit: "+Platform.is64Bit());
-
+
Method m=null;
try {
m = ReflectionUtil.getMethod(Control.class, str_internal_new_GC, new Class[] { GCData.class });
- } catch (Exception ex) {
+ } catch (final Exception ex) {
throw new NativeWindowException(ex);
}
swt_control_internal_new_GC = m;
-
+
try {
if(swt_uses_long_handles) {
- m = Control.class.getDeclaredMethod(str_internal_dispose_GC, new Class[] { long.class, GCData.class });
+ m = Control.class.getDeclaredMethod(str_internal_dispose_GC, new Class[] { long.class, GCData.class });
} else {
- m = Control.class.getDeclaredMethod(str_internal_dispose_GC, new Class[] { int.class, GCData.class });
+ m = Control.class.getDeclaredMethod(str_internal_dispose_GC, new Class[] { int.class, GCData.class });
}
- } catch (NoSuchMethodException ex) {
+ } catch (final NoSuchMethodException ex) {
throw new NativeWindowException(ex);
}
swt_control_internal_dispose_GC = m;
- Class<?> c=null;
- Method m1=null, m2=null, m3=null, m4=null, m5=null;
- Class<?> handleType = swt_uses_long_handles ? long.class : int.class ;
- if( NativeWindowFactory.TYPE_X11 == nwt ) {
+ Class<?> c=null;
+ VersionNumber _gtk_version = new VersionNumber(0, 0, 0);
+ Method m1=null, m2=null, m3=null, m4=null, m5=null, m6=null, m7=null, m8=null, m9=null, ma=null;
+ final Class<?> handleType = swt_uses_long_handles ? long.class : int.class ;
+ if( isX11 ) {
+ // mandatory
try {
c = ReflectionUtil.getClass(str_OS_gtk_class, false, SWTAccessor.class.getClassLoader());
- m1 = c.getDeclaredMethod(str_gtk_widget_realize, handleType);
+ final Field field_OS_gtk_version = c.getField(str_OS_gtk_version);
+ _gtk_version = GTK_VERSION(field_OS_gtk_version.getInt(null));
+ m1 = c.getDeclaredMethod(str_gtk_widget_realize, handleType);
+ if (_gtk_version.compareTo(GTK_VERSION_2_14_0) >= 0) {
+ m4 = c.getDeclaredMethod(str_gtk_widget_get_window, handleType);
+ } else {
+ m3 = c.getDeclaredMethod(str_GTK_WIDGET_WINDOW, handleType);
+ }
+ if (_gtk_version.compareTo(GTK_VERSION_2_24_0) >= 0) {
+ m6 = c.getDeclaredMethod(str_gdk_x11_display_get_xdisplay, handleType);
+ m7 = c.getDeclaredMethod(str_gdk_window_get_display, handleType);
+ } else {
+ m5 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xdisplay, handleType);
+ }
+ if (_gtk_version.compareTo(GTK_VERSION_3_0_0) >= 0) {
+ m9 = c.getDeclaredMethod(str_gdk_x11_window_get_xid, handleType);
+ } else {
+ m8 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xid, handleType);
+ }
+ ma = c.getDeclaredMethod(str_gdk_window_set_back_pixmap, handleType, handleType, boolean.class);
+ } catch (final Exception ex) { throw new NativeWindowException(ex); }
+ // optional
+ try {
m2 = c.getDeclaredMethod(str_gtk_widget_unrealize, handleType);
- m3 = c.getDeclaredMethod(str_GTK_WIDGET_WINDOW, handleType);
- m4 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xdisplay, handleType);
- m5 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xid, handleType);
- } catch (Exception ex) { throw new NativeWindowException(ex); }
+ } catch (final Exception ex) { }
}
OS_gtk_class = c;
+ OS_gtk_version = _gtk_version;
OS_gtk_widget_realize = m1;
OS_gtk_widget_unrealize = m2;
OS_GTK_WIDGET_WINDOW = m3;
- OS_gdk_x11_drawable_get_xdisplay = m4;
- OS_gdk_x11_drawable_get_xid = m5;
+ OS_gtk_widget_get_window = m4;
+ OS_gdk_x11_drawable_get_xdisplay = m5;
+ OS_gdk_x11_display_get_xdisplay = m6;
+ OS_gdk_window_get_display = m7;
+ OS_gdk_x11_drawable_get_xid = m8;
+ OS_gdk_x11_window_get_xid = m9;
+ OS_gdk_window_set_back_pixmap = ma;
+
+ isX11GTK = isX11 && null != OS_gtk_class;
+
+ if(DEBUG) {
+ System.err.println("SWTAccessor.<init>: GTK Version: "+OS_gtk_version);
+ }
}
- static Object getIntOrLong(long arg) {
+ private static Number getIntOrLong(final long arg) {
if(swt_uses_long_handles) {
- return new Long(arg);
+ return Long.valueOf(arg);
}
- return new Integer((int) arg);
+ return Integer.valueOf((int) arg);
}
-
- static void callStaticMethodL2V(Method m, long arg) {
+
+ private static void callStaticMethodL2V(final Method m, final long arg) {
ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg) });
}
-
- static long callStaticMethodL2L(Method m, long arg) {
- Object o = ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg) });
+
+ private static void callStaticMethodLLZ2V(final Method m, final long arg0, final long arg1, final boolean arg3) {
+ ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg0), getIntOrLong(arg1), Boolean.valueOf(arg3) });
+ }
+
+ private static long callStaticMethodL2L(final Method m, final long arg) {
+ final Object o = ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg) });
if(o instanceof Number) {
return ((Number)o).longValue();
} else {
throw new InternalError("SWT method "+m.getName()+" didn't return int or long but "+o.getClass());
}
}
-
+
+ //
+ // Public properties
+ //
+
public static boolean isUsingLongHandles() {
return swt_uses_long_handles;
}
- public static long getHandle(Control swtControl) {
+ public static boolean useX11GTK() { return isX11GTK; }
+ public static VersionNumber GTK_VERSION() { return OS_gtk_version; }
+
+ //
+ // Common GTK
+ //
+
+ public static long gdk_widget_get_window(final long handle) {
+ final long window;
+ if (OS_gtk_version.compareTo(GTK_VERSION_2_14_0) >= 0) {
+ window = callStaticMethodL2L(OS_gtk_widget_get_window, handle);
+ } else {
+ window = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle);
+ }
+ if(0 == window) {
+ throw new NativeWindowException("Null gtk-window-handle of SWT handle 0x"+Long.toHexString(handle));
+ }
+ return window;
+ }
+
+ public static long gdk_window_get_xdisplay(final long window) {
+ final long xdisplay;
+ if (OS_gtk_version.compareTo(GTK_VERSION_2_24_0) >= 0) {
+ final long display = callStaticMethodL2L(OS_gdk_window_get_display, window);
+ if(0 == display) {
+ throw new NativeWindowException("Null display-handle of gtk-window-handle 0x"+Long.toHexString(window));
+ }
+ xdisplay = callStaticMethodL2L(OS_gdk_x11_display_get_xdisplay, display);
+ } else {
+ xdisplay = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, window);
+ }
+ if(0 == xdisplay) {
+ throw new NativeWindowException("Null x11-display-handle of gtk-window-handle 0x"+Long.toHexString(window));
+ }
+ return xdisplay;
+ }
+
+ public static long gdk_window_get_xwindow(final long window) {
+ final long xWindow;
+ if (OS_gtk_version.compareTo(GTK_VERSION_3_0_0) >= 0) {
+ xWindow = callStaticMethodL2L(OS_gdk_x11_window_get_xid, window);
+ } else {
+ xWindow = callStaticMethodL2L(OS_gdk_x11_drawable_get_xid, window);
+ }
+ if(0 == xWindow) {
+ throw new NativeWindowException("Null x11-window-handle of gtk-window-handle 0x"+Long.toHexString(window));
+ }
+ return xWindow;
+ }
+
+ public static void gdk_window_set_back_pixmap(final long window, final long pixmap, final boolean parent_relative) {
+ callStaticMethodLLZ2V(OS_gdk_window_set_back_pixmap, window, pixmap, parent_relative);
+ }
+
+ //
+ // Common any toolkit
+ //
+
+ /**
+ * @param swtControl the SWT Control to retrieve the native widget-handle from
+ * @return the native widget-handle
+ * @throws NativeWindowException if the widget handle is null
+ */
+ public static long getHandle(final Control swtControl) throws NativeWindowException {
long h = 0;
- if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) {
+ if( isOSX ) {
+ synchronized(swt_osx_init) {
+ try {
+ if(null == swt_osx_view_id) {
+ swt_osx_control_view = Control.class.getField(str_osx_view);
+ final Object view = swt_osx_control_view.get(swtControl);
+ swt_osx_view_id = view.getClass().getField(str_osx_id);
+ h = swt_osx_view_id.getLong(view);
+ } else {
+ h = swt_osx_view_id.getLong( swt_osx_control_view.get(swtControl) );
+ }
+ } catch (final Exception ex) {
+ throw new NativeWindowException(ex);
+ }
+ }
+ } else {
try {
- Field fView = Control.class.getField(str_view);
- Object view = fView.get(swtControl);
- Field fId = view.getClass().getField(str_id);
- return fId.getLong(view);
- } catch (Exception ex) {
+ h = swt_control_handle.getLong(swtControl);
+ } catch (final Exception ex) {
throw new NativeWindowException(ex);
- }
+ }
}
-
- try {
- h = swt_control_handle.getLong(swtControl);
- } catch (Exception ex) {
- throw new NativeWindowException(ex);
+ if(0 == h) {
+ throw new NativeWindowException("Null widget-handle of SWT "+swtControl.getClass().getName()+": "+swtControl.toString());
}
return h;
}
- public static void setRealized(final Control swtControl, final boolean realize) {
+ public static void setRealized(final Control swtControl, final boolean realize)
+ throws NativeWindowException
+ {
+ if(!realize && swtControl.isDisposed()) {
+ return;
+ }
final long handle = getHandle(swtControl);
-
+
if(null != OS_gtk_class) {
invoke(true, new Runnable() {
+ @Override
public void run() {
if(realize) {
callStaticMethodL2V(OS_gtk_widget_realize, handle);
- } else {
+ } else if(null != OS_gtk_widget_unrealize) {
callStaticMethodL2V(OS_gtk_widget_unrealize, handle);
- }
+ }
}
});
}
}
-
- public static AbstractGraphicsDevice getDevice(Control swtControl) {
- long handle = getHandle(swtControl);
- if( null != OS_gtk_class ) {
- long widgedHandle = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle);
- long displayHandle = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, widgedHandle);
- return new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, false);
+
+ /**
+ * @param swtControl the SWT Control to retrieve the native device handle from
+ * @return the AbstractGraphicsDevice w/ the native device handle
+ * @throws NativeWindowException if the widget handle is null
+ * @throws UnsupportedOperationException if the windowing system is not supported
+ */
+ public static AbstractGraphicsDevice getDevice(final Control swtControl) throws NativeWindowException, UnsupportedOperationException {
+ final long handle = getHandle(swtControl);
+ if( isX11GTK ) {
+ final long xdisplay0 = gdk_window_get_xdisplay( gdk_widget_get_window( handle ) );
+ return new X11GraphicsDevice(xdisplay0, AbstractGraphicsDevice.DEFAULT_UNIT, false /* owner */);
}
- final String nwt = NativeWindowFactory.getNativeWindowType(false);
- if( NativeWindowFactory.TYPE_WINDOWS == nwt ) {
+ if( isWindows ) {
return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
}
- if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
+ if( isOSX ) {
return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
}
throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
}
- public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) {
- if( null != OS_gtk_class ) {
- return new X11GraphicsScreen((X11GraphicsDevice)device, screen);
- }
- final String nwt = NativeWindowFactory.getNativeWindowType(false);
- if( NativeWindowFactory.TYPE_WINDOWS == nwt ||
- NativeWindowFactory.TYPE_MACOSX == nwt ) {
- return new DefaultGraphicsScreen(device, screen);
- }
- throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
+
+ /**
+ * @param device
+ * @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen
+ * @return
+ */
+ public static AbstractGraphicsScreen getScreen(final AbstractGraphicsDevice device, final int screen) {
+ return NativeWindowFactory.createScreen(device, screen);
}
- public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) {
- if( null != OS_gtk_class ) {
+
+ public static int getNativeVisualID(final AbstractGraphicsDevice device, final long windowHandle) {
+ if( isX11 ) {
return X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle);
}
- final String nwt = NativeWindowFactory.getNativeWindowType(false);
- if( NativeWindowFactory.TYPE_WINDOWS == nwt ||
- NativeWindowFactory.TYPE_MACOSX == nwt ) {
+ if( isWindows || isOSX ) {
return VisualIDHolder.VID_UNDEFINED;
}
- throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
+ throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
}
-
- public static long getWindowHandle(Control swtControl) {
- long handle = getHandle(swtControl);
- if( null != OS_gtk_class ) {
- long widgedHandle = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle);
- return callStaticMethodL2L(OS_gdk_x11_drawable_get_xid, widgedHandle);
+
+ /**
+ * @param swtControl the SWT Control to retrieve the native window handle from
+ * @return the native window handle
+ * @throws NativeWindowException if the widget handle is null
+ * @throws UnsupportedOperationException if the windowing system is not supported
+ */
+ public static long getWindowHandle(final Control swtControl) throws NativeWindowException, UnsupportedOperationException {
+ final long handle = getHandle(swtControl);
+ if(0 == handle) {
+ throw new NativeWindowException("Null SWT handle of SWT control "+swtControl);
+ }
+ if( isX11GTK ) {
+ return gdk_window_get_xwindow( gdk_widget_get_window( handle ) );
}
- final String nwt = NativeWindowFactory.getNativeWindowType(false);
- if( NativeWindowFactory.TYPE_WINDOWS == nwt ||
- NativeWindowFactory.TYPE_MACOSX == nwt ) {
+ if( isWindows || isOSX ) {
return handle;
}
throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
}
-
+
public static long newGC(final Control swtControl, final GCData gcData) {
final Object[] o = new Object[1];
invoke(true, new Runnable() {
+ @Override
public void run() {
o[0] = ReflectionUtil.callMethod(swtControl, swt_control_internal_new_GC, new Object[] { gcData });
}
@@ -274,39 +450,138 @@ public class SWTAccessor {
public static void disposeGC(final Control swtControl, final long gc, final GCData gcData) {
invoke(true, new Runnable() {
+ @Override
public void run() {
if(swt_uses_long_handles) {
- ReflectionUtil.callMethod(swtControl, swt_control_internal_dispose_GC, new Object[] { new Long(gc), gcData });
+ ReflectionUtil.callMethod(swtControl, swt_control_internal_dispose_GC, new Object[] { Long.valueOf(gc), gcData });
} else {
- ReflectionUtil.callMethod(swtControl, swt_control_internal_dispose_GC, new Object[] { new Integer((int)gc), gcData });
+ ReflectionUtil.callMethod(swtControl, swt_control_internal_dispose_GC, new Object[] { Integer.valueOf((int)gc), gcData });
}
}
});
}
-
+
/**
* Runs the specified action in an SWT compatible thread, which is:
* <ul>
* <li>Mac OSX
* <ul>
* <!--li>AWT EDT: In case AWT is available, the AWT EDT is the OSX UI main thread</li-->
- * <li><i>Main Thread</i>: Run on OSX UI main thread.</li>
+ * <li><i>Main Thread</i>: Run on OSX UI main thread. 'wait' is implemented on Java site via lock/wait on {@link RunnableTask} to not freeze OSX main thread.</li>
* </ul></li>
* <li>Linux, Windows, ..
* <ul>
* <li>Current thread.</li>
- * </ul></li>
+ * </ul></li>
* </ul>
* @see Platform#AWT_AVAILABLE
* @see Platform#getOSType()
*/
- public static void invoke(boolean wait, Runnable runnable) {
- if( Platform.OS_TYPE == Platform.OSType.MACOS ) {
+ public static void invoke(final boolean wait, final Runnable runnable) {
+ if( isOSX ) {
// Use SWT main thread! Only reliable config w/ -XStartOnMainThread !?
- OSXUtil.RunOnMainThread(wait, runnable);
+ OSXUtil.RunOnMainThread(wait, false, runnable);
} else {
runnable.run();
- }
+ }
+ }
+
+ /**
+ * Runs the specified action on the SWT UI thread.
+ * <p>
+ * If <code>display</code> is disposed or the current thread is the SWT UI thread
+ * {@link #invoke(boolean, Runnable)} is being used.
+ * @see #invoke(boolean, Runnable)
+ */
+ public static void invoke(final org.eclipse.swt.widgets.Display display, final boolean wait, final Runnable runnable) {
+ if( display.isDisposed() || Thread.currentThread() == display.getThread() ) {
+ invoke(wait, runnable);
+ } else if( wait ) {
+ display.syncExec(runnable);
+ } else {
+ display.asyncExec(runnable);
+ }
+ }
+
+ //
+ // Specific X11 GTK ChildWindow - Using plain X11 native parenting (works well)
+ //
+
+ public static long createCompatibleX11ChildWindow(final AbstractGraphicsScreen screen, final Control swtControl, final int visualID, final int width, final int height) {
+ final long handle = getHandle(swtControl);
+ final long parentWindow = gdk_widget_get_window( handle );
+ gdk_window_set_back_pixmap (parentWindow, 0, false);
+
+ final long x11ParentHandle = gdk_window_get_xwindow(parentWindow);
+ final long x11WindowHandle = X11Lib.CreateWindow(x11ParentHandle, screen.getDevice().getHandle(), screen.getIndex(), visualID, width, height, true, true);
+
+ return x11WindowHandle;
+ }
+
+ public static void resizeX11Window(final AbstractGraphicsDevice device, final Rectangle clientArea, final long x11Window) {
+ X11Lib.SetWindowPosSize(device.getHandle(), x11Window, clientArea.x, clientArea.y, clientArea.width, clientArea.height);
+ }
+ public static void destroyX11Window(final AbstractGraphicsDevice device, final long x11Window) {
+ X11Lib.DestroyWindow(device.getHandle(), x11Window);
+ }
+
+ //
+ // Specific X11 SWT/GTK ChildWindow - Using SWT/GTK native parenting (buggy - sporadic resize flickering, sporadic drop of rendering)
+ //
+ // FIXME: Need to use reflection for 32bit access as well !
+ //
+
+ // public static final int GDK_WA_TYPE_HINT = 1 << 9;
+ // public static final int GDK_WA_VISUAL = 1 << 6;
+
+ public static long createCompatibleGDKChildWindow(final Control swtControl, final int visualID, final int width, final int height) {
+ return 0;
+ /**
+ final long handle = SWTAccessor.getHandle(swtControl);
+ final long parentWindow = gdk_widget_get_window( handle );
+
+ final long screen = OS.gdk_screen_get_default ();
+ final long gdkvisual = OS.gdk_x11_screen_lookup_visual (screen, visualID);
+
+ final GdkWindowAttr attrs = new GdkWindowAttr();
+ attrs.width = width > 0 ? width : 1;
+ attrs.height = height > 0 ? height : 1;
+ attrs.event_mask = OS.GDK_KEY_PRESS_MASK | OS.GDK_KEY_RELEASE_MASK |
+ OS.GDK_FOCUS_CHANGE_MASK | OS.GDK_POINTER_MOTION_MASK |
+ OS.GDK_BUTTON_PRESS_MASK | OS.GDK_BUTTON_RELEASE_MASK |
+ OS.GDK_ENTER_NOTIFY_MASK | OS.GDK_LEAVE_NOTIFY_MASK |
+ OS.GDK_EXPOSURE_MASK | OS.GDK_VISIBILITY_NOTIFY_MASK |
+ OS.GDK_POINTER_MOTION_HINT_MASK;
+ attrs.window_type = OS.GDK_WINDOW_CHILD;
+ attrs.visual = gdkvisual;
+
+ final long childWindow = OS.gdk_window_new (parentWindow, attrs, OS.GDK_WA_VISUAL|GDK_WA_TYPE_HINT);
+ OS.gdk_window_set_user_data (childWindow, handle);
+ OS.gdk_window_set_back_pixmap (parentWindow, 0, false);
+
+ OS.gdk_window_show (childWindow);
+ OS.gdk_flush();
+ return childWindow; */
+ }
+
+ public static void showGDKWindow(final long gdkWindow) {
+ /* OS.gdk_window_show (gdkWindow);
+ OS.gdk_flush(); */
+ }
+ public static void focusGDKWindow(final long gdkWindow) {
+ /*
+ OS.gdk_window_show (gdkWindow);
+ OS.gdk_window_focus(gdkWindow, 0);
+ OS.gdk_flush(); */
+ }
+ public static void resizeGDKWindow(final Rectangle clientArea, final long gdkWindow) {
+ /**
+ OS.gdk_window_move (gdkWindow, clientArea.x, clientArea.y);
+ OS.gdk_window_resize (gdkWindow, clientArea.width, clientArea.height);
+ OS.gdk_flush(); */
+ }
+
+ public static void destroyGDKWindow(final long gdkWindow) {
+ // OS.gdk_window_destroy (gdkWindow);
}
-
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/windows/WindowsGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/windows/WindowsGraphicsDevice.java
index 5cabdf150..ef0cbddd7 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/windows/WindowsGraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/windows/WindowsGraphicsDevice.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -34,19 +34,20 @@ package com.jogamp.nativewindow.windows;
import javax.media.nativewindow.*;
-/**
+/**
* Encapsulates a graphics device on Windows platforms.<br>
*/
public class WindowsGraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
/** Constructs a new WindowsGraphicsDevice */
- public WindowsGraphicsDevice(int unitID) {
+ public WindowsGraphicsDevice(final int unitID) {
this(AbstractGraphicsDevice.DEFAULT_CONNECTION, unitID);
}
- public WindowsGraphicsDevice(String connection, int unitID) {
+ public WindowsGraphicsDevice(final String connection, final int unitID) {
super(NativeWindowFactory.TYPE_WINDOWS, connection, unitID);
}
+ @Override
public Object clone() {
return super.clone();
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsConfiguration.java
index 0d2914c7d..223cb5194 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsConfiguration.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsConfiguration.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -48,9 +48,9 @@ import jogamp.nativewindow.x11.XVisualInfo;
public class X11GraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {
private XVisualInfo info;
- public X11GraphicsConfiguration(X11GraphicsScreen screen,
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- XVisualInfo info) {
+ public X11GraphicsConfiguration(final X11GraphicsScreen screen,
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final XVisualInfo info) {
super(screen, capsChosen, capsRequested);
this.info = info;
}
@@ -64,19 +64,19 @@ public class X11GraphicsConfiguration extends MutableGraphicsConfiguration imple
return info;
}
- final protected void setXVisualInfo(XVisualInfo info) {
+ final protected void setXVisualInfo(final XVisualInfo info) {
this.info = info;
}
final public int getXVisualID() {
return (null!=info)?(int)info.getVisualid():0;
}
-
+
@Override
public String toString() {
return getClass().getSimpleName()+"["+getScreen()+", visualID 0x" + Long.toHexString(getXVisualID()) +
",\n\tchosen " + capabilitiesChosen+
- ",\n\trequested " + capabilitiesRequested+
+ ",\n\trequested " + capabilitiesRequested+
"]";
}
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
index 152384980..fea4e7019 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -45,7 +45,8 @@ import javax.media.nativewindow.ToolkitLock;
*/
public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
- final boolean handleOwner;
+ /* final */ boolean handleOwner;
+ final boolean isXineramaEnabled;
/** Constructs a new X11GraphicsDevice corresponding to the given connection and default
* {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#getDefaultToolkitLock(String)}.<br>
@@ -53,41 +54,54 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
* This constructor exist to setup a default device connection.
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(String, String, int)
*/
- public X11GraphicsDevice(String connection, int unitID) {
+ public X11GraphicsDevice(final String connection, final int unitID) {
super(NativeWindowFactory.TYPE_X11, connection, unitID);
handleOwner = false;
+ isXineramaEnabled = false;
}
/** Constructs a new X11GraphicsDevice corresponding to the given native display handle and default
- * {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#createDefaultToolkitLock(String, long)}.
+ * {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}.
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(String, String, int, long)
*/
- public X11GraphicsDevice(long display, int unitID, boolean owner) {
- // FIXME: derive unitID from connection could be buggy, one DISPLAY for all screens for example..
- super(NativeWindowFactory.TYPE_X11, X11Lib.XDisplayString(display), unitID, display);
- if(0==display) {
- throw new NativeWindowException("null display");
- }
- handleOwner = owner;
+ public X11GraphicsDevice(final long display, final int unitID, final boolean owner) {
+ this(display, unitID, NativeWindowFactory.getDefaultToolkitLock(NativeWindowFactory.TYPE_X11, display), owner);
}
/**
* @param display the Display connection
- * @param locker custom {@link javax.media.nativewindow.ToolkitLock}, eg to force null locking in NEWT
+ * @param locker custom {@link javax.media.nativewindow.ToolkitLock}, eg to force null locking w/ private connection
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(String, String, int, long, ToolkitLock)
*/
- public X11GraphicsDevice(long display, int unitID, ToolkitLock locker, boolean owner) {
+ public X11GraphicsDevice(final long display, final int unitID, final ToolkitLock locker, final boolean owner) {
super(NativeWindowFactory.TYPE_X11, X11Lib.XDisplayString(display), unitID, display, locker);
if(0==display) {
throw new NativeWindowException("null display");
}
handleOwner = owner;
+ isXineramaEnabled = X11Util.XineramaIsEnabled(this);
+ }
+
+ /**
+ * Constructs a new X11GraphicsDevice corresponding to the given display connection.
+ * <p>
+ * The constructor opens the native connection and takes ownership.
+ * </p>
+ * @param displayConnection the semantic display connection name
+ * @param locker custom {@link javax.media.nativewindow.ToolkitLock}, eg to force null locking w/ private connection
+ * @see DefaultGraphicsDevice#DefaultGraphicsDevice(String, String, int, long, ToolkitLock)
+ */
+ public X11GraphicsDevice(final String displayConnection, final int unitID, final ToolkitLock locker) {
+ super(NativeWindowFactory.TYPE_X11, displayConnection, unitID, 0, locker);
+ handleOwner = true;
+ open();
+ isXineramaEnabled = X11Util.XineramaIsEnabled(this);
}
- private static int getDefaultScreenImpl(long dpy) {
+ private static int getDefaultScreenImpl(final long dpy) {
return X11Lib.DefaultScreen(dpy);
}
-
+
/**
* Returns the default screen number as referenced by the display connection, i.e. 'somewhere:0.1' -> 1
* <p>
@@ -105,7 +119,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
}
return ds;
}
-
+
public int getDefaultVisualID() {
final long display = getHandle();
if(0==display) {
@@ -113,7 +127,11 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
}
return X11Lib.DefaultVisualID(display, getDefaultScreenImpl(display));
}
-
+
+ public final boolean isXineramaEnabled() {
+ return isXineramaEnabled;
+ }
+
@Override
public Object clone() {
return super.clone();
@@ -133,7 +151,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
}
return false;
}
-
+
@Override
public boolean close() {
if(handleOwner && 0 != handle) {
@@ -144,5 +162,23 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
}
return super.close();
}
-}
+ @Override
+ public boolean isHandleOwner() {
+ return handleOwner;
+ }
+ @Override
+ public void clearHandleOwner() {
+ handleOwner = false;
+ }
+ @Override
+ protected Object getHandleOwnership() {
+ return Boolean.valueOf(handleOwner);
+ }
+ @Override
+ protected Object setHandleOwnership(final Object newOwnership) {
+ final Boolean oldOwnership = Boolean.valueOf(handleOwner);
+ handleOwner = ((Boolean) newOwnership).booleanValue();
+ return oldOwnership;
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java
index 5f3c220ca..8ebf3c379 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -33,10 +33,12 @@
package com.jogamp.nativewindow.x11;
-import javax.media.nativewindow.*;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.NativeWindowException;
import jogamp.nativewindow.x11.X11Lib;
-import jogamp.nativewindow.x11.X11Util;
/** Encapsulates a screen index on X11
platforms. Objects of this type are passed to {@link
@@ -47,11 +49,11 @@ import jogamp.nativewindow.x11.X11Util;
public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneable {
/** Constructs a new X11GraphicsScreen corresponding to the given native screen index. */
- public X11GraphicsScreen(X11GraphicsDevice device, int screen) {
- super(device, fetchScreen(device, screen));
+ public X11GraphicsScreen(final X11GraphicsDevice device, final int screen) {
+ super(device, device.isXineramaEnabled() ? 0 : screen);
}
- public static AbstractGraphicsScreen createScreenDevice(long display, int screenIdx, boolean owner) {
+ public static AbstractGraphicsScreen createScreenDevice(final long display, final int screenIdx, final boolean owner) {
if(0==display) throw new NativeWindowException("display is null");
return new X11GraphicsScreen(new X11GraphicsDevice(display, AbstractGraphicsDevice.DEFAULT_UNIT, owner), screenIdx);
}
@@ -60,15 +62,8 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl
// It still could be an AWT hold handle ..
return X11Lib.DefaultVisualID(getDevice().getHandle(), getIndex());
}
-
- private static int fetchScreen(X11GraphicsDevice device, int screen) {
- // It still could be an AWT hold handle ..
- if(X11Util.XineramaIsEnabled(device.getHandle())) {
- screen = 0; // Xinerama -> 1 screen
- }
- return screen;
- }
+ @Override
public Object clone() {
return super.clone();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
index ebdaf2fbb..48f72e574 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -42,8 +42,9 @@ package javax.media.nativewindow;
/** A marker interface describing a graphics configuration, visual, or
pixel format in a toolkit-independent manner. */
-
public interface AbstractGraphicsConfiguration extends VisualIDHolder, Cloneable {
+ public Object clone();
+
/**
* Return the screen this graphics configuration is valid for
*/
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
index 756e4451b..31b64269f 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -45,10 +45,9 @@ import jogamp.nativewindow.Debug;
/** A interface describing a graphics device in a
toolkit-independent manner.
*/
-
public interface AbstractGraphicsDevice extends Cloneable {
public static final boolean DEBUG = Debug.debug("GraphicsDevice");
-
+
/** Dummy connection value for a default connection where no native support for multiple devices is available */
public static String DEFAULT_CONNECTION = "decon";
@@ -58,6 +57,8 @@ public interface AbstractGraphicsDevice extends Cloneable {
/** Default unit id for the 1st device: 0 */
public static int DEFAULT_UNIT = 0;
+ public Object clone();
+
/**
* Returns the type of the underlying subsystem, ie
* NativeWindowFactory.TYPE_KD, NativeWindowFactory.TYPE_X11, ..
@@ -88,10 +89,16 @@ public interface AbstractGraphicsDevice extends Cloneable {
public int getUnitID();
/**
- * Returns a unique ID String of this device using {@link #getType() type},
- * {@link #getConnection() connection} and {@link #getUnitID() unitID}.<br>
- * The unique ID does not reflect the instance of the device, hence the handle is not included.<br>
+ * Returns a unique ID object of this device using {@link #getType() type},
+ * {@link #getConnection() connection} and {@link #getUnitID() unitID} as it's key components.
+ * <p>
+ * The unique ID does not reflect the instance of the device, hence the handle is not included.
* The unique ID may be used as a key for semantic device mapping.
+ * </p>
+ * <p>
+ * The returned string object reference is unique using {@link String#intern()}
+ * and hence can be used as a key itself.
+ * </p>
*/
public String getUniqueID();
@@ -102,27 +109,34 @@ public interface AbstractGraphicsDevice extends Cloneable {
public long getHandle();
/**
- * Optionally locking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock}.
+ * Optionally locking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock#lock()}.
* The lock implementation must be recursive.
*/
public void lock();
- /**
- * Optionally unlocking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock}.
+ /**
+ * Optionally unlocking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock#unlock()}.
* The lock implementation must be recursive.
+ *
+ * @throws RuntimeException in case the lock is not acquired by this thread.
*/
public void unlock();
- /**
+ /**
+ * @throws RuntimeException if current thread does not hold the lock
+ */
+ public void validateLocked() throws RuntimeException;
+
+ /**
* Optionally [re]opening the device if handle is <code>null</code>.
* <p>
* The default implementation is a <code>NOP</code>.
* </p>
* <p>
- * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
- * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
+ * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
+ * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
* issue the native open operation in case handle is <code>null</code>.
- * </p>
+ * </p>
*
* @return true if the handle was <code>null</code> and opening was successful, otherwise false.
*/
@@ -131,15 +145,22 @@ public interface AbstractGraphicsDevice extends Cloneable {
/**
* Optionally closing the device if handle is not <code>null</code>.
* <p>
- * The default implementation is a <code>NOP</code>, just setting the handle to <code>null</code>.
+ * The default implementation {@link ToolkitLock#dispose() dispose} it's {@link ToolkitLock} and sets the handle to <code>null</code>.
* </p>
* <p>
- * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
- * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
- * issue the native close operation or skip it depending on the handles's ownership.
- * </p>
+ * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
+ * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
+ * issue the native close operation or skip it depending on the {@link #isHandleOwner() handles's ownership}.
+ * </p>
*
* @return true if the handle was not <code>null</code> and closing was successful, otherwise false.
*/
public boolean close();
+
+ /**
+ * @return <code>true</code> if instance owns the handle to issue {@link #close()}, otherwise <code>false</code>.
+ */
+ public boolean isHandleOwner();
+
+ public void clearHandleOwner();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
index eb2cc9120..da8f12f3e 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -44,6 +44,8 @@ package javax.media.nativewindow;
*/
public interface AbstractGraphicsScreen extends Cloneable {
+ public Object clone();
+
/**
* Return the device this graphics configuration is valid for
*/
diff --git a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java
index 5795e8cfe..bf8952565 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java
@@ -61,7 +61,7 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
// Switch for on- or offscreen
private boolean onscreen = true;
-
+
// offscreen bitmap mode
private boolean isBitmap = false;
@@ -74,22 +74,22 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
public Object cloneMutable() {
return clone();
}
-
+
@Override
public Object clone() {
try {
return super.clone();
- } catch (CloneNotSupportedException e) {
+ } catch (final CloneNotSupportedException e) {
throw new NativeWindowException(e);
}
}
/**
- * Copies all {@link Capabilities} values
+ * Copies all {@link Capabilities} values
* from <code>source</code> into this instance.
* @return this instance
*/
- public Capabilities copyFrom(CapabilitiesImmutable other) {
+ public Capabilities copyFrom(final CapabilitiesImmutable other) {
redBits = other.getRedBits();
greenBits = other.getGreenBits();
blueBits = other.getBlueBits();
@@ -103,7 +103,7 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
transparentValueAlpha = other.getTransparentAlphaValue();
return this;
}
-
+
@Override
public int hashCode() {
// 31 * x == (x << 5) - x
@@ -122,12 +122,12 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if(this == obj) { return true; }
if(!(obj instanceof CapabilitiesImmutable)) {
return false;
}
- CapabilitiesImmutable other = (CapabilitiesImmutable)obj;
+ final CapabilitiesImmutable other = (CapabilitiesImmutable)obj;
boolean res = other.getRedBits()==redBits &&
other.getGreenBits()==greenBits &&
other.getBlueBits()==blueBits &&
@@ -150,18 +150,16 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
**/
@Override
public int compareTo(final CapabilitiesImmutable caps) {
- /**
+ /**
if ( ! ( o instanceof CapabilitiesImmutable ) ) {
Class<?> c = (null != o) ? o.getClass() : null ;
throw new ClassCastException("Not a CapabilitiesImmutable object, but " + c);
}
final CapabilitiesImmutable caps = (CapabilitiesImmutable) o; */
-
- final int a = ( alphaBits > 0 ) ? alphaBits : 1;
- final int rgba = redBits * greenBits * blueBits * a;
- final int xa = ( caps.getAlphaBits() ) > 0 ? caps.getAlphaBits() : 1;
- final int xrgba = caps.getRedBits() * caps.getGreenBits() * caps.getBlueBits() * xa;
+ final int rgba = redBits * greenBits * blueBits * ( alphaBits + 1 );
+
+ final int xrgba = caps.getRedBits() * caps.getGreenBits() * caps.getBlueBits() * ( caps.getAlphaBits() + 1 );
if(rgba > xrgba) {
return 1;
@@ -173,7 +171,7 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
}
@Override
- public int getVisualID(VIDType type) throws NativeWindowException {
+ public int getVisualID(final VIDType type) throws NativeWindowException {
switch(type) {
case INTRINSIC:
case NATIVE:
@@ -191,7 +189,7 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
/** Sets the number of bits requested for the color buffer's red
component. On some systems only the color depth, which is the
sum of the red, green, and blue bits, is considered. */
- public void setRedBits(int redBits) {
+ public void setRedBits(final int redBits) {
this.redBits = redBits;
}
@@ -203,7 +201,7 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
/** Sets the number of bits requested for the color buffer's green
component. On some systems only the color depth, which is the
sum of the red, green, and blue bits, is considered. */
- public void setGreenBits(int greenBits) {
+ public void setGreenBits(final int greenBits) {
this.greenBits = greenBits;
}
@@ -215,7 +213,7 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
/** Sets the number of bits requested for the color buffer's blue
component. On some systems only the color depth, which is the
sum of the red, green, and blue bits, is considered. */
- public void setBlueBits(int blueBits) {
+ public void setBlueBits(final int blueBits) {
this.blueBits = blueBits;
}
@@ -224,19 +222,19 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
return alphaBits;
}
- /**
+ /**
* Sets the number of bits requested for the color buffer's alpha
* component. On some systems only the color depth, which is the
* sum of the red, green, and blue bits, is considered.
* <p>
- * <b>Note:</b> If alpha bits are <code>zero</code>, they are set to <code>one</code>
+ * <b>Note:</b> If alpha bits are <code>zero</code>, they are set to <code>one</code>
* by {@link #setBackgroundOpaque(boolean)} and it's OpenGL specialization <code>GLCapabilities::setSampleBuffers(boolean)</code>.<br/>
* Ensure to call this method after the above to ensure a <code>zero</code> value.</br>
* The above automated settings takes into account, that the user calls this method to <i>request</i> alpha bits,
* not to <i>reflect</i> a current state. Nevertheless if this is the case - call it at last.
- * </p>
+ * </p>
*/
- public void setAlphaBits(int alphaBits) {
+ public void setAlphaBits(final int alphaBits) {
this.alphaBits = alphaBits;
}
@@ -255,7 +253,7 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
* due to the composite work required by the window manager.
* </p>
*/
- public void setBackgroundOpaque(boolean opaque) {
+ public void setBackgroundOpaque(final boolean opaque) {
backgroundOpaque = opaque;
if(!opaque && getAlphaBits()==0) {
setAlphaBits(1);
@@ -273,13 +271,13 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
* Defaults to true.
* </p>
* <p>
- * If requesting an offscreen surface without further selection of it's mode,
+ * If requesting an offscreen surface without further selection of it's mode,
* e.g. FBO, Pbuffer or {@link #setBitmap(boolean) bitmap},
* the implementation will choose the best available offscreen mode.
* </p>
* @param onscreen
*/
- public void setOnscreen(boolean onscreen) {
+ public void setOnscreen(final boolean onscreen) {
this.onscreen=onscreen;
}
@@ -300,18 +298,18 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
* Requesting offscreen bitmap mode disables the offscreen auto selection.
* </p>
*/
- public void setBitmap(boolean enable) {
+ public void setBitmap(final boolean enable) {
if(enable) {
setOnscreen(false);
}
isBitmap = enable;
}
-
+
@Override
public boolean isBitmap() {
- return isBitmap;
+ return isBitmap;
}
-
+
@Override
public final int getTransparentRedValue() { return transparentValueRed; }
@@ -329,46 +327,46 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
This value is ignored if {@link #isBackgroundOpaque()} equals true.<br>
It defaults to half of the frambuffer value for red. <br>
A value of -1 is interpreted as any value. */
- public void setTransparentRedValue(int transValueRed) { transparentValueRed=transValueRed; }
+ public void setTransparentRedValue(final int transValueRed) { transparentValueRed=transValueRed; }
/** Sets the transparent green value for the frame buffer configuration,
ranging from 0 to the maximum frame buffer value for green.
This value is ignored if {@link #isBackgroundOpaque()} equals true.<br>
It defaults to half of the frambuffer value for green.<br>
A value of -1 is interpreted as any value. */
- public void setTransparentGreenValue(int transValueGreen) { transparentValueGreen=transValueGreen; }
+ public void setTransparentGreenValue(final int transValueGreen) { transparentValueGreen=transValueGreen; }
/** Sets the transparent blue value for the frame buffer configuration,
ranging from 0 to the maximum frame buffer value for blue.
This value is ignored if {@link #isBackgroundOpaque()} equals true.<br>
It defaults to half of the frambuffer value for blue.<br>
A value of -1 is interpreted as any value. */
- public void setTransparentBlueValue(int transValueBlue) { transparentValueBlue=transValueBlue; }
+ public void setTransparentBlueValue(final int transValueBlue) { transparentValueBlue=transValueBlue; }
/** Sets the transparent alpha value for the frame buffer configuration,
ranging from 0 to the maximum frame buffer value for alpha.
This value is ignored if {@link #isBackgroundOpaque()} equals true.<br>
It defaults to half of the frambuffer value for alpha.<br>
A value of -1 is interpreted as any value. */
- public void setTransparentAlphaValue(int transValueAlpha) { transparentValueAlpha=transValueAlpha; }
+ public void setTransparentAlphaValue(final int transValueAlpha) { transparentValueAlpha=transValueAlpha; }
@Override
- public StringBuilder toString(StringBuilder sink) {
+ public StringBuilder toString(final StringBuilder sink) {
return toString(sink, true);
}
-
+
/** Returns a textual representation of this Capabilities
object. */
@Override
public String toString() {
- StringBuilder msg = new StringBuilder();
+ final StringBuilder msg = new StringBuilder();
msg.append("Caps[");
toString(msg);
msg.append("]");
return msg.toString();
}
-
- /** Return a textual representation of this object's on/off screen state. Use the given StringBuffer [optional]. */
+
+ /** Return a textual representation of this object's on/off screen state. Use the given StringBuilder [optional]. */
protected StringBuilder onoffScreenToString(StringBuilder sink) {
if(null == sink) {
sink = new StringBuilder();
@@ -383,29 +381,34 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
} else if(onscreen) {
sink.append("."); // no additional off-screen modes besides on-screen
} else {
- sink.append("auto-cfg"); // auto-config off-screen mode
+ sink.append("auto-cfg"); // auto-config off-screen mode
}
- sink.append("]");
-
+ sink.append("]");
+
return sink;
}
-
- protected StringBuilder toString(StringBuilder sink, boolean withOnOffScreen) {
+
+ /** Element separator */
+ protected static final String ESEP = "/";
+ /** Component separator */
+ protected static final String CSEP = ", ";
+
+ protected StringBuilder toString(StringBuilder sink, final boolean withOnOffScreen) {
if(null == sink) {
sink = new StringBuilder();
}
- sink.append("rgba 0x").append(toHexString(redBits)).append("/").append(toHexString(greenBits)).append("/").append(toHexString(blueBits)).append("/").append(toHexString(alphaBits));
+ sink.append("rgba ").append(redBits).append(ESEP).append(greenBits).append(ESEP).append(blueBits).append(ESEP).append(alphaBits);
if(backgroundOpaque) {
sink.append(", opaque");
} else {
- sink.append(", trans-rgba 0x").append(toHexString(transparentValueRed)).append("/").append(toHexString(transparentValueGreen)).append("/").append(toHexString(transparentValueBlue)).append("/").append(toHexString(transparentValueAlpha));
+ sink.append(", trans-rgba 0x").append(toHexString(transparentValueRed)).append(ESEP).append(toHexString(transparentValueGreen)).append(ESEP).append(toHexString(transparentValueBlue)).append(ESEP).append(toHexString(transparentValueAlpha));
}
if(withOnOffScreen) {
- sink.append(", ");
+ sink.append(CSEP);
onoffScreenToString(sink);
}
return sink;
}
-
- protected final String toHexString(int val) { return Integer.toHexString(val); }
+
+ protected final String toHexString(final int val) { return Integer.toHexString(val); }
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesChooser.java b/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesChooser.java
index e1fdf4938..1f4db7997 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesChooser.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesChooser.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -58,7 +58,7 @@ public interface CapabilitiesChooser {
not necessarily required, that the chooser select that entry.
<P> <em>Note:</em> this method is called automatically by the
- {@link GraphicsConfigurationFactory#chooseGraphicsConfiguration} method
+ {@link GraphicsConfigurationFactory#chooseGraphicsConfiguration} method
when an instance of this class is passed in to it.
It should generally not be
invoked by users directly, unless it is desired to delegate the
diff --git a/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesImmutable.java
index b801ab457..c496a1535 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesImmutable.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesImmutable.java
@@ -70,12 +70,12 @@ public interface CapabilitiesImmutable extends VisualIDHolder, WriteCloneable, C
* Returns whether an opaque or translucent surface is requested, supported or chosen.
* <p>
* Default is true, i.e. opaque.
- * </p>
+ * </p>
*/
boolean isBackgroundOpaque();
/**
- * Returns whether an on- or offscreen surface is requested, available or chosen.
+ * Returns whether an on- or offscreen surface is requested, available or chosen.
* <p>
* Default is true, i.e. onscreen.
* </p>
@@ -83,7 +83,7 @@ public interface CapabilitiesImmutable extends VisualIDHolder, WriteCloneable, C
* Mind that an capabilities intance w/ <i>available</i> semantics
* may show onscreen, but also the offscreen modes FBO, Pbuffer or {@link #setBitmap(boolean) bitmap}.
* This is valid, since one native configuration maybe used for either functionality.
- * </p>
+ * </p>
*/
boolean isOnscreen();
@@ -97,7 +97,7 @@ public interface CapabilitiesImmutable extends VisualIDHolder, WriteCloneable, C
* </p>
*/
boolean isBitmap();
-
+
/**
* Gets the transparent red value for the frame buffer configuration. This
* value is undefined if; equals true.
@@ -130,7 +130,7 @@ public interface CapabilitiesImmutable extends VisualIDHolder, WriteCloneable, C
@Override
int hashCode();
- /** Return a textual representation of this object. Use the given StringBuffer [optional]. */
+ /** Return a textual representation of this object. Use the given StringBuilder [optional]. */
StringBuilder toString(StringBuilder sink);
/** Returns a textual representation of this object. */
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultCapabilitiesChooser.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultCapabilitiesChooser.java
index 744c7e6d5..d0c1a9b85 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultCapabilitiesChooser.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultCapabilitiesChooser.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -42,6 +42,8 @@ package javax.media.nativewindow;
import java.util.List;
+import com.jogamp.common.util.PropertyAccess;
+
import jogamp.nativewindow.Debug;
/** <P> The default implementation of the {@link
@@ -66,11 +68,17 @@ import jogamp.nativewindow.Debug;
*/
public class DefaultCapabilitiesChooser implements CapabilitiesChooser {
- private static final boolean DEBUG = Debug.isPropertyDefined("nativewindow.debug.CapabilitiesChooser", true);
+ private static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = PropertyAccess.isPropertyDefined("nativewindow.debug.CapabilitiesChooser", true);
+ }
private final static int NO_SCORE = -9999999;
private final static int COLOR_MISMATCH_PENALTY_SCALE = 36;
-
+
+ @Override
public int chooseCapabilities(final CapabilitiesImmutable desired,
final List<? extends CapabilitiesImmutable> available,
final int windowSystemRecommendedChoice) {
@@ -94,7 +102,7 @@ public class DefaultCapabilitiesChooser implements CapabilitiesChooser {
}
// Create score array
- int[] scores = new int[availnum];
+ final int[] scores = new int[availnum];
for (int i = 0; i < availnum; i++) {
scores[i] = NO_SCORE;
}
@@ -107,7 +115,7 @@ public class DefaultCapabilitiesChooser implements CapabilitiesChooser {
if (desired.isOnscreen() && !cur.isOnscreen()) {
continue; // requested onscreen, but n/a
}
-
+
int score = 0;
// Compute difference in color depth
score += (COLOR_MISMATCH_PENALTY_SCALE *
@@ -127,11 +135,11 @@ public class DefaultCapabilitiesChooser implements CapabilitiesChooser {
System.err.println(" ]");
}
- // Ready to select. Choose score closest to 0.
+ // Ready to select. Choose score closest to 0.
int scoreClosestToZero = NO_SCORE;
int chosenIndex = -1;
for (int i = 0; i < availnum; i++) {
- int score = scores[i];
+ final int score = scores[i];
if (score == NO_SCORE) {
continue;
}
@@ -155,7 +163,7 @@ public class DefaultCapabilitiesChooser implements CapabilitiesChooser {
return chosenIndex;
}
- private static int sign(int score) {
+ private static int sign(final int score) {
if (score < 0) {
return -1;
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
index a33c3792a..cae37c36c 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -36,13 +36,13 @@ import jogamp.nativewindow.Debug;
public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphicsConfiguration {
protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration");
-
+
private AbstractGraphicsScreen screen;
protected CapabilitiesImmutable capabilitiesChosen;
protected CapabilitiesImmutable capabilitiesRequested;
- public DefaultGraphicsConfiguration(AbstractGraphicsScreen screen,
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested) {
+ public DefaultGraphicsConfiguration(final AbstractGraphicsScreen screen,
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested) {
if(null == screen) {
throw new IllegalArgumentException("Null screen");
}
@@ -52,9 +52,6 @@ public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphics
if(null == capsRequested) {
throw new IllegalArgumentException("Null requested caps");
}
- if( ! ( capsChosen instanceof VisualIDHolder ) ) {
- throw new IllegalArgumentException("Chosen caps is not implementing NativeVisualID");
- }
this.screen = screen;
this.capabilitiesChosen = capsChosen;
this.capabilitiesRequested = capsRequested;
@@ -64,69 +61,74 @@ public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphics
public Object clone() {
try {
return super.clone();
- } catch (CloneNotSupportedException e) {
+ } catch (final CloneNotSupportedException e) {
throw new NativeWindowException(e);
}
}
+ @Override
final public AbstractGraphicsScreen getScreen() {
return screen;
}
+ @Override
final public CapabilitiesImmutable getChosenCapabilities() {
return capabilitiesChosen;
}
+ @Override
final public CapabilitiesImmutable getRequestedCapabilities() {
return capabilitiesRequested;
}
+ @Override
public AbstractGraphicsConfiguration getNativeGraphicsConfiguration() {
return this;
}
@Override
- final public int getVisualID(VIDType type) throws NativeWindowException {
+ final public int getVisualID(final VIDType type) throws NativeWindowException {
return capabilitiesChosen.getVisualID(type);
}
-
+
/**
* Set the capabilities to a new value.
*
+ * <p>
* The use case for setting the Capabilities at a later time is
- * a change of the graphics device in a multi-screen environment.<br>
- *
+ * a change or re-validation of capabilities.
+ * </p>
* @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
*/
- protected void setChosenCapabilities(CapabilitiesImmutable capsChosen) {
- capabilitiesChosen = capsChosen;
+ protected void setChosenCapabilities(final CapabilitiesImmutable capsChosen) {
+ this.capabilitiesChosen = capsChosen;
}
/**
* Set a new screen.
*
+ * <p>
* the use case for setting a new screen at a later time is
- * a change of the graphics device in a multi-screen environment.<br>
- *
- * A copy of the passed object is being used.
+ * a change of the graphics device in a multi-screen environment.
+ * </p>
*/
- final protected void setScreen(DefaultGraphicsScreen screen) {
- this.screen = (AbstractGraphicsScreen) screen.clone();
+ protected void setScreen(final AbstractGraphicsScreen screen) {
+ this.screen = screen;
}
@Override
public String toString() {
return getClass().getSimpleName()+"[" + screen +
",\n\tchosen " + capabilitiesChosen+
- ",\n\trequested " + capabilitiesRequested+
+ ",\n\trequested " + capabilitiesRequested+
"]";
}
- public static String toHexString(int val) {
+ public static String toHexString(final int val) {
return "0x"+Integer.toHexString(val);
}
- public static String toHexString(long val) {
+ public static String toHexString(final long val) {
return "0x"+Long.toHexString(val);
}
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 583fde07f..ab9286b3f 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -37,10 +37,10 @@ import jogamp.nativewindow.NativeWindowFactoryImpl;
public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice {
private static final String separator = "_";
- private String type;
- protected String connection;
- protected int unitID;
- protected String uniqueID;
+ private final String type;
+ protected final String connection;
+ protected final int unitID;
+ protected final String uniqueID;
protected long handle;
protected ToolkitLock toolkitLock;
@@ -49,37 +49,27 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
* gathered via {@link NativeWindowFactory#getDefaultToolkitLock(String)}.
* @param type
*/
- public DefaultGraphicsDevice(String type, String connection, int unitID) {
- this.type = type;
- this.connection = connection;
- this.unitID = unitID;
- this.uniqueID = getUniqueID(type, connection, unitID);
- this.handle = 0;
- this.toolkitLock = NativeWindowFactory.getDefaultToolkitLock(type);
+ public DefaultGraphicsDevice(final String type, final String connection, final int unitID) {
+ this(type, connection, unitID, 0, NativeWindowFactory.getDefaultToolkitLock(type));
}
/**
* Create an instance with the system default {@link ToolkitLock}.
- * gathered via {@link NativeWindowFactory#createDefaultToolkitLock(String, long)}.
+ * gathered via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}.
* @param type
* @param handle
*/
- public DefaultGraphicsDevice(String type, String connection, int unitID, long handle) {
- this.type = type;
- this.connection = connection;
- this.unitID = unitID;
- this.uniqueID = getUniqueID(type, connection, unitID);
- this.handle = handle;
- this.toolkitLock = NativeWindowFactory.createDefaultToolkitLock(type, handle);
+ public DefaultGraphicsDevice(final String type, final String connection, final int unitID, final long handle) {
+ this(type, connection, unitID, handle, NativeWindowFactory.getDefaultToolkitLock(type, handle));
}
/**
- * Create an instance with the given {@link ToolkitLock} instance.
+ * Create an instance with the given {@link ToolkitLock} instance, or <i>null</i> {@link ToolkitLock} if null.
* @param type
* @param handle
- * @param locker
+ * @param locker if null, a non blocking <i>null</i> lock is used.
*/
- public DefaultGraphicsDevice(String type, String connection, int unitID, long handle, ToolkitLock locker) {
+ public DefaultGraphicsDevice(final String type, final String connection, final int unitID, final long handle, final ToolkitLock locker) {
this.type = type;
this.connection = connection;
this.unitID = unitID;
@@ -92,7 +82,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
public Object clone() {
try {
return super.clone();
- } catch (CloneNotSupportedException e) {
+ } catch (final CloneNotSupportedException e) {
throw new NativeWindowException(e);
}
}
@@ -123,8 +113,10 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
}
/**
- * No lock is performed on the graphics device per default,
- * instead the aggregated recursive {@link ToolkitLock#lock()} is invoked.
+ * {@inheritDoc}
+ * <p>
+ * Locking is perfomed via delegation to {@link ToolkitLock#lock()}, {@link ToolkitLock#unlock()}.
+ * </p>
*
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock)
@@ -134,9 +126,16 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
toolkitLock.lock();
}
- /**
- * No lock is performed on the graphics device per default,
- * instead the aggregated recursive {@link ToolkitLock#unlock()} is invoked.
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ toolkitLock.validateLocked();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Locking is perfomed via delegation to {@link ToolkitLock#lock()}, {@link ToolkitLock#unlock()}.
+ * </p>
*
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock)
@@ -145,7 +144,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
public final void unlock() {
toolkitLock.unlock();
}
-
+
@Override
public boolean open() {
return false;
@@ -153,6 +152,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
@Override
public boolean close() {
+ toolkitLock.dispose();
if(0 != handle) {
handle = 0;
return true;
@@ -161,8 +161,53 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
}
@Override
+ public boolean isHandleOwner() {
+ return false;
+ }
+
+ @Override
+ public void clearHandleOwner() {
+ }
+
+ @Override
public String toString() {
- return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+"]";
+ return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", owner "+isHandleOwner()+", "+toolkitLock+"]";
+ }
+
+ /**
+ * Set the native handle of the underlying native device
+ * and return the previous one.
+ */
+ protected final long setHandle(final long newHandle) {
+ final long oldHandle = handle;
+ handle = newHandle;
+ return oldHandle;
+ }
+
+ protected Object getHandleOwnership() {
+ return null;
+ }
+ protected Object setHandleOwnership(final Object newOwnership) {
+ return null;
+ }
+
+ public static final void swapDeviceHandleAndOwnership(final DefaultGraphicsDevice aDevice1, final DefaultGraphicsDevice aDevice2) {
+ aDevice1.lock();
+ try {
+ aDevice2.lock();
+ try {
+ final long aDevice1Handle = aDevice1.getHandle();
+ final long aDevice2Handle = aDevice2.setHandle(aDevice1Handle);
+ aDevice1.setHandle(aDevice2Handle);
+ final Object aOwnership1 = aDevice1.getHandleOwnership();
+ final Object aOwnership2 = aDevice2.setHandleOwnership(aOwnership1);
+ aDevice1.setHandleOwnership(aOwnership2);
+ } finally {
+ aDevice2.unlock();
+ }
+ } finally {
+ aDevice1.unlock();
+ }
}
/**
@@ -173,10 +218,11 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
* The current ToolkitLock is being locked/unlocked while swapping the reference,
* ensuring no concurrent access can occur during the swap.
* </p>
- *
+ *
* @param locker the ToolkitLock, if null, {@link jogamp.nativewindow.NullToolkitLock} is being used
+ * @return the previous ToolkitLock instance
*/
- protected void setToolkitLock(ToolkitLock locker) {
+ protected ToolkitLock setToolkitLock(final ToolkitLock locker) {
final ToolkitLock _toolkitLock = toolkitLock;
_toolkitLock.lock();
try {
@@ -184,6 +230,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
} finally {
_toolkitLock.unlock();
}
+ return _toolkitLock;
}
/**
@@ -196,7 +243,11 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
return toolkitLock;
}
- protected static String getUniqueID(String type, String connection, int unitID) {
+ /**
+ * Returns a unique String object using {@link String#intern()} for the given arguments,
+ * which object reference itself can be used as a key.
+ */
+ private static String getUniqueID(final String type, final String connection, final int unitID) {
return (type + separator + connection + separator + unitID).intern();
}
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
index f50bd0e14..3ee775904 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -33,15 +33,15 @@
package javax.media.nativewindow;
public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen {
- AbstractGraphicsDevice device;
- private int idx;
+ private final AbstractGraphicsDevice device;
+ private final int idx;
- public DefaultGraphicsScreen(AbstractGraphicsDevice device, int idx) {
+ public DefaultGraphicsScreen(final AbstractGraphicsDevice device, final int idx) {
this.device = device;
this.idx = idx;
}
- public static AbstractGraphicsScreen createDefault(String type) {
+ public static AbstractGraphicsScreen createDefault(final String type) {
return new DefaultGraphicsScreen(new DefaultGraphicsDevice(type, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT), 0);
}
@@ -49,15 +49,17 @@ public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen
public Object clone() {
try {
return super.clone();
- } catch (CloneNotSupportedException e) {
+ } catch (final CloneNotSupportedException e) {
throw new NativeWindowException(e);
}
}
+ @Override
public AbstractGraphicsDevice getDevice() {
return device;
}
+ @Override
public int getIndex() {
return idx;
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
index 9694f2491..3f8113baa 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -48,7 +48,7 @@ import java.util.Set;
/**
* Provides the mechanism by which the graphics configuration for a
- * window can be chosen before the window is created. The graphics
+ * window can be chosen before the window is created. The graphics
* configuration decides parameters related to hardware accelerated rendering such
* as the OpenGL pixel format. <br>
* On some window systems (EGL/OpenKODE and X11 in particular) it is necessary to
@@ -69,41 +69,43 @@ public abstract class GraphicsConfigurationFactory {
public final Class<?> deviceType;
public final Class<?> capsType;
private final int hash32;
-
- public DeviceCapsType(Class<?> deviceType, Class<?> capsType) {
+
+ public DeviceCapsType(final Class<?> deviceType, final Class<?> capsType) {
this.deviceType = deviceType;
this.capsType = capsType;
-
+
// 31 * x == (x << 5) - x
int hash32 = 31 + deviceType.hashCode();
hash32 = ((hash32 << 5) - hash32) + capsType.hashCode();
this.hash32 = hash32;
}
-
+
+ @Override
public final int hashCode() {
return hash32;
}
-
- public final boolean equals(Object obj) {
+
+ @Override
+ public final boolean equals(final Object obj) {
if(this == obj) { return true; }
if (obj instanceof DeviceCapsType) {
- DeviceCapsType dct = (DeviceCapsType)obj;
+ final DeviceCapsType dct = (DeviceCapsType)obj;
return deviceType == dct.deviceType && capsType == dct.capsType;
}
return false;
}
-
+
@Override
public final String toString() {
return "DeviceCapsType["+deviceType.getName()+", "+capsType.getName()+"]";
}
-
+
}
-
+
private static final Map<DeviceCapsType, GraphicsConfigurationFactory> registeredFactories;
- private static final DeviceCapsType defaultDeviceCapsType;
+ private static final DeviceCapsType defaultDeviceCapsType;
static boolean initialized = false;
-
+
static {
DEBUG = Debug.debug("GraphicsConfiguration");
if(DEBUG) {
@@ -113,7 +115,7 @@ public abstract class GraphicsConfigurationFactory {
registeredFactories = Collections.synchronizedMap(new HashMap<DeviceCapsType, GraphicsConfigurationFactory>());
defaultDeviceCapsType = new DeviceCapsType(AbstractGraphicsDevice.class, CapabilitiesImmutable.class);
}
-
+
public static synchronized void initSingleton() {
if(!initialized) {
initialized = true;
@@ -121,31 +123,31 @@ public abstract class GraphicsConfigurationFactory {
if(DEBUG) {
System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.initSingleton()");
}
-
+
// Register the default no-op factory for arbitrary
// AbstractGraphicsDevice implementations, including
// AWTGraphicsDevice instances -- the OpenGL binding will take
// care of handling AWTGraphicsDevices on X11 platforms (as
// well as X11GraphicsDevices in non-AWT situations)
registerFactory(defaultDeviceCapsType.deviceType, defaultDeviceCapsType.capsType, new DefaultGraphicsConfigurationFactoryImpl());
-
+
if (NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true)) {
try {
- ReflectionUtil.callStaticMethod("jogamp.nativewindow.x11.X11GraphicsConfigurationFactory",
- "registerFactory", null, null, GraphicsConfigurationFactory.class.getClassLoader());
- } catch (Exception e) {
+ ReflectionUtil.callStaticMethod("jogamp.nativewindow.x11.X11GraphicsConfigurationFactory",
+ "registerFactory", null, null, GraphicsConfigurationFactory.class.getClassLoader());
+ } catch (final Exception e) {
throw new RuntimeException(e);
}
if(NativeWindowFactory.isAWTAvailable()) {
try {
- ReflectionUtil.callStaticMethod("jogamp.nativewindow.x11.awt.X11AWTGraphicsConfigurationFactory",
- "registerFactory", null, null, GraphicsConfigurationFactory.class.getClassLoader());
- } catch (Exception e) { /* n/a */ }
+ ReflectionUtil.callStaticMethod("jogamp.nativewindow.x11.awt.X11AWTGraphicsConfigurationFactory",
+ "registerFactory", null, null, GraphicsConfigurationFactory.class.getClassLoader());
+ } catch (final Exception e) { /* n/a */ }
}
}
}
}
-
+
public static synchronized void shutdown() {
if(initialized) {
initialized = false;
@@ -155,16 +157,16 @@ public abstract class GraphicsConfigurationFactory {
registeredFactories.clear();
}
}
-
+
protected static String getThreadName() {
return Thread.currentThread().getName();
}
- protected static String toHexString(int val) {
+ protected static String toHexString(final int val) {
return "0x" + Integer.toHexString(val);
}
- protected static String toHexString(long val) {
+ protected static String toHexString(final long val) {
return "0x" + Long.toHexString(val);
}
@@ -176,10 +178,10 @@ public abstract class GraphicsConfigurationFactory {
/**
* Returns the graphics configuration factory for use with the
* given device and capability.
- *
+ *
* @see #getFactory(Class, Class)
*/
- public static GraphicsConfigurationFactory getFactory(AbstractGraphicsDevice device, CapabilitiesImmutable caps) {
+ public static GraphicsConfigurationFactory getFactory(final AbstractGraphicsDevice device, final CapabilitiesImmutable caps) {
if (device == null) {
throw new IllegalArgumentException("null device");
}
@@ -195,7 +197,7 @@ public abstract class GraphicsConfigurationFactory {
* <p>
* Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only.
* </p>
- *
+ *
* <p>
* Pseudo code for finding a suitable factory is:
* <pre>
@@ -211,10 +213,10 @@ public abstract class GraphicsConfigurationFactory {
* @param deviceType the minimum capabilities class type accepted, must implement or extend {@link AbstractGraphicsDevice}
* @param capabilitiesType the minimum capabilities class type accepted, must implement or extend {@link CapabilitiesImmutable}
*
- * @throws IllegalArgumentException if the deviceType does not implement {@link AbstractGraphicsDevice} or
+ * @throws IllegalArgumentException if the deviceType does not implement {@link AbstractGraphicsDevice} or
* capabilitiesType does not implement {@link CapabilitiesImmutable}
*/
- public static GraphicsConfigurationFactory getFactory(Class<?> deviceType, Class<?> capabilitiesType)
+ public static GraphicsConfigurationFactory getFactory(final Class<?> deviceType, final Class<?> capabilitiesType)
throws IllegalArgumentException, NativeWindowException
{
if (!(defaultDeviceCapsType.deviceType.isAssignableFrom(deviceType))) {
@@ -228,19 +230,19 @@ public abstract class GraphicsConfigurationFactory {
System.err.println("GraphicsConfigurationFactory.getFactory: "+deviceType.getName()+", "+capabilitiesType.getName());
dumpFactories();
}
-
- final List<Class<?>> deviceTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.deviceType, deviceType, false);
+
+ final List<Class<?>> deviceTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.deviceType, deviceType, false);
if(DEBUG) {
System.err.println("GraphicsConfigurationFactory.getFactory() deviceTypes: " + deviceTypes);
}
- final List<Class<?>> capabilitiesTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.capsType, capabilitiesType, true);
+ final List<Class<?>> capabilitiesTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.capsType, capabilitiesType, true);
if(DEBUG) {
System.err.println("GraphicsConfigurationFactory.getFactory() capabilitiesTypes: " + capabilitiesTypes);
}
for(int j=0; j<deviceTypes.size(); j++) {
final Class<?> interfaceDevice = deviceTypes.get(j);
for(int i=0; i<capabilitiesTypes.size(); i++) {
- Class<?> interfaceCaps = capabilitiesTypes.get(i);
+ final Class<?> interfaceCaps = capabilitiesTypes.get(i);
final DeviceCapsType dct = new DeviceCapsType(interfaceDevice, interfaceCaps);
final GraphicsConfigurationFactory factory = registeredFactories.get(dct);
if (factory != null) {
@@ -258,8 +260,8 @@ public abstract class GraphicsConfigurationFactory {
}
return factory;
}
- private static ArrayList<Class<?>> getAllAssignableClassesFrom(Class<?> superClassOrInterface, Class<?> fromClass, boolean interfacesOnly) {
- // Using a todo list avoiding a recursive loop!
+ private static ArrayList<Class<?>> getAllAssignableClassesFrom(final Class<?> superClassOrInterface, final Class<?> fromClass, final boolean interfacesOnly) {
+ // Using a todo list avoiding a recursive loop!
final ArrayList<Class<?>> inspectClasses = new ArrayList<Class<?>>();
final ArrayList<Class<?>> resolvedInterfaces = new ArrayList<Class<?>>();
inspectClasses.add(fromClass);
@@ -269,7 +271,7 @@ public abstract class GraphicsConfigurationFactory {
}
return resolvedInterfaces;
}
- private static void getAllAssignableClassesFrom(Class<?> superClassOrInterface, Class<?> fromClass, boolean interfacesOnly, List<Class<?>> resolvedInterfaces, List<Class<?>> inspectClasses) {
+ private static void getAllAssignableClassesFrom(final Class<?> superClassOrInterface, final Class<?> fromClass, final boolean interfacesOnly, final List<Class<?>> resolvedInterfaces, final List<Class<?>> inspectClasses) {
final ArrayList<Class<?>> types = new ArrayList<Class<?>>();
if( superClassOrInterface.isAssignableFrom(fromClass) && !resolvedInterfaces.contains(fromClass)) {
if( !interfacesOnly || fromClass.isInterface() ) {
@@ -277,7 +279,7 @@ public abstract class GraphicsConfigurationFactory {
}
}
types.addAll(Arrays.asList(fromClass.getInterfaces()));
-
+
for(int i=0; i<types.size(); i++) {
final Class<?> iface = types.get(i);
if( superClassOrInterface.isAssignableFrom(iface) && !resolvedInterfaces.contains(iface) ) {
@@ -293,35 +295,35 @@ public abstract class GraphicsConfigurationFactory {
}
}
private static void dumpFactories() {
- Set<DeviceCapsType> dcts = registeredFactories.keySet();
+ final Set<DeviceCapsType> dcts = registeredFactories.keySet();
int i=0;
- for(Iterator<DeviceCapsType> iter = dcts.iterator(); iter.hasNext(); ) {
- DeviceCapsType dct = iter.next();
+ for(final Iterator<DeviceCapsType> iter = dcts.iterator(); iter.hasNext(); ) {
+ final DeviceCapsType dct = iter.next();
System.err.println("Factory #"+i+": "+dct+" -> "+registeredFactories.get(dct));
i++;
}
}
- /**
+ /**
* Registers a GraphicsConfigurationFactory handling
* the given graphics device and capability class.
* <p>
* This does not need to be called by end users, only implementors of new
* GraphicsConfigurationFactory subclasses.
* </p>
- *
+ *
* <p>
* Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only.
- * </p>
- *
+ * </p>
+ *
* <p>See {@link #getFactory(Class, Class)} for a description of the find algorithm.</p>
- *
+ *
* @param deviceType the minimum capabilities class type accepted, must implement or extend interface {@link AbstractGraphicsDevice}
* @param capabilitiesType the minimum capabilities class type accepted, must extend interface {@link CapabilitiesImmutable}
* @return the previous registered factory, or null if none
* @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice
*/
- protected static GraphicsConfigurationFactory registerFactory(Class<?> abstractGraphicsDeviceImplementor, Class<?> capabilitiesType, GraphicsConfigurationFactory factory)
+ protected static GraphicsConfigurationFactory registerFactory(final Class<?> abstractGraphicsDeviceImplementor, final Class<?> capabilitiesType, final GraphicsConfigurationFactory factory)
throws IllegalArgumentException
{
if (!(defaultDeviceCapsType.deviceType.isAssignableFrom(abstractGraphicsDeviceImplementor))) {
@@ -329,7 +331,7 @@ public abstract class GraphicsConfigurationFactory {
}
if (!(defaultDeviceCapsType.capsType.isAssignableFrom(capabilitiesType))) {
throw new IllegalArgumentException("Given capabilities class must implement CapabilitiesImmutable");
- }
+ }
final DeviceCapsType dct = new DeviceCapsType(abstractGraphicsDeviceImplementor, capabilitiesType);
final GraphicsConfigurationFactory prevFactory;
if(null == factory) {
@@ -352,7 +354,7 @@ public abstract class GraphicsConfigurationFactory {
* <P> Selects a graphics configuration on the specified graphics
* device compatible with the supplied {@link Capabilities}. Some
* platforms (e.g.: X11, EGL, KD) require the graphics configuration
- * to be specified when the native window is created.
+ * to be specified when the native window is created.
* These architectures have seperated their device, screen, window and drawable
* context and hence are capable of quering the capabilities for each screen.
* A fully established window is not required.</P>
@@ -360,7 +362,7 @@ public abstract class GraphicsConfigurationFactory {
* <P>Other platforms (e.g. Windows, MacOSX) don't offer the mentioned seperation
* and hence need a fully established window and it's drawable.
* Here the validation of the capabilities is performed later.
- * In this case, the AbstractGraphicsConfiguration implementation
+ * In this case, the AbstractGraphicsConfiguration implementation
* must allow an overwrite of the Capabilites, for example
* {@link DefaultGraphicsConfiguration#setChosenCapabilities DefaultGraphicsConfiguration.setChosenCapabilities(..)}.
* </P>
@@ -385,7 +387,7 @@ public abstract class GraphicsConfigurationFactory {
* @param capsRequested the original requested capabilities
* @param chooser the choosing implementation
* @param screen the referring Screen
- * @param nativeVisualID if not {@link VisualIDHolder#VID_UNDEFINED} it reflects a pre-chosen visualID of the native platform's windowing system.
+ * @param nativeVisualID if not {@link VisualIDHolder#VID_UNDEFINED} it reflects a pre-chosen visualID of the native platform's windowing system.
* @return the complete GraphicsConfiguration
*
* @throws IllegalArgumentException if the data type of the passed
@@ -398,9 +400,9 @@ public abstract class GraphicsConfigurationFactory {
* @see javax.media.nativewindow.DefaultGraphicsConfiguration#setChosenCapabilities(Capabilities caps)
*/
public final AbstractGraphicsConfiguration
- chooseGraphicsConfiguration(CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser,
- AbstractGraphicsScreen screen, int nativeVisualID)
+ chooseGraphicsConfiguration(final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser,
+ final AbstractGraphicsScreen screen, final int nativeVisualID)
throws IllegalArgumentException, NativeWindowException {
if(null==capsChosen) {
throw new NativeWindowException("Chosen Capabilities are null");
@@ -411,7 +413,7 @@ public abstract class GraphicsConfigurationFactory {
if(null==screen) {
throw new NativeWindowException("Screen is null");
}
- AbstractGraphicsDevice device = screen.getDevice();
+ final AbstractGraphicsDevice device = screen.getDevice();
if(null==device) {
throw new NativeWindowException("Screen's Device is null");
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java
index ff53c8109..a0db11ad9 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java
@@ -31,12 +31,12 @@ package javax.media.nativewindow;
/**
* Provides a {@link NativeSurface} with a mutable <code>surfaceHandle</code>
* via {@link #setSurfaceHandle(long)}.
- *
+ *
* @see NativeSurface
*/
public interface MutableSurface extends NativeSurface {
- /**
+ /**
* Sets the surface handle which is created outside of this implementation.
*/
public void setSurfaceHandle(long surfaceHandle);
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java
index 27462ae70..4d764dc4f 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,33 +20,39 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package javax.media.nativewindow;
-/** Provides low-level information required for
- hardware-accelerated rendering using a surface in a platform-independent manner.<P>
+package javax.media.nativewindow;
- A NativeSurface created for a particular on- or offscreen component is
- expected to have the same lifetime as that component. As long as
- the component is alive and realized/visible, NativeSurface must be able
- provide information such as the surface handle while it is locked.<P>
-*/
+/**
+ * Provides low-level information required for
+ * hardware-accelerated rendering using a surface in a platform-independent manner.
+ * <p>
+ * All values of this interface are represented in pixel units, if not stated otherwise.
+ * See {@link NativeWindow}.
+ * </p>
+ * <p>
+ * A NativeSurface created for a particular on- or offscreen component is
+ * expected to have the same lifetime as that component. As long as
+ * the component is alive and realized/visible, NativeSurface must be able
+ * provide information such as the surface handle while it is locked.
+ * </p>
+ */
public interface NativeSurface extends SurfaceUpdatedListener {
- /** Unlocked state */
+ /** Unlocked state, {@value}. */
public static final int LOCK_SURFACE_UNLOCKED = 0;
- /** Returned by {@link #lockSurface()} if the surface is not ready to be locked. */
+ /** Returned by {@link #lockSurface()} if the surface is not ready to be locked, {@value}. */
public static final int LOCK_SURFACE_NOT_READY = 1;
- /** Returned by {@link #lockSurface()} if the surface is locked, but has changed. */
+ /** Returned by {@link #lockSurface()} if the surface is locked, but has changed, {@value}. */
public static final int LOCK_SURFACE_CHANGED = 2;
- /** Returned by {@link #lockSurface()} if the surface is locked, and is unchanged. */
+ /** Returned by {@link #lockSurface()} if the surface is locked, and is unchanged, {@value}. */
public static final int LOCK_SUCCESS = 3;
/**
@@ -54,10 +60,10 @@ public interface NativeSurface extends SurfaceUpdatedListener {
* <p>
* The surface handle shall be valid after a successfull call,
* ie return a value other than {@link #LOCK_SURFACE_UNLOCKED} and {@link #LOCK_SURFACE_NOT_READY},
- * which is
- * <pre>
- * boolean ok = lockSurface() > LOCK_SURFACE_NOT_READY;
- * </pre>
+ * which is
+ * <pre>
+ * boolean ok = LOCK_SURFACE_NOT_READY < lockSurface();
+ * </pre>
* </p>
* <p>
* The caller may need to take care of the result {@link #LOCK_SURFACE_CHANGED},
@@ -71,7 +77,7 @@ public interface NativeSurface extends SurfaceUpdatedListener {
* This call allows recursion from the same thread.
* </p>
* <p>
- * The implementation may want to aquire the
+ * The implementation may want to aquire the
* application level {@link com.jogamp.common.util.locks.RecursiveLock}
* first before proceeding with a native surface lock.
* </p>
@@ -115,7 +121,7 @@ public interface NativeSurface extends SurfaceUpdatedListener {
* </pre>
*/
public boolean isSurfaceLockedByOtherThread();
-
+
/**
* Return the locking owner's Thread, or null if not locked.
*/
@@ -123,15 +129,15 @@ public interface NativeSurface extends SurfaceUpdatedListener {
/**
* Provide a mechanism to utilize custom (pre-) swap surface
- * code. This method is called before the render toolkit (e.g. JOGL)
+ * code. This method is called before the render toolkit (e.g. JOGL)
* swaps the buffer/surface if double buffering is enabled.
- * <p>
+ * <p>
* The implementation may itself apply the swapping,
* in which case true shall be returned.
* </p>
*
* @return true if this method completed swapping the surface,
- * otherwise false, in which case eg the GLDrawable
+ * otherwise false, in which case eg the GLDrawable
* implementation has to swap the code.
*/
public boolean surfaceSwap();
@@ -153,13 +159,13 @@ public interface NativeSurface extends SurfaceUpdatedListener {
/** Remove the specified {@link SurfaceUpdatedListener} from the list. */
public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l);
-
+
/**
* Returns the handle to the surface for this NativeSurface. <P>
- *
+ *
* The surface handle should be set/update by {@link #lockSurface()},
* where {@link #unlockSurface()} is not allowed to modify it.
- * After {@link #unlockSurface()} it is no more guaranteed
+ * After {@link #unlockSurface()} it is no more guaranteed
* that the surface handle is still valid.
*
* The surface handle shall reflect the platform one
@@ -172,16 +178,36 @@ public interface NativeSurface extends SurfaceUpdatedListener {
public long getSurfaceHandle();
/**
- * Returns the width of the client area excluding insets (window decorations).
- * @return width of the client area
+ * Returns the width of the client area excluding insets (window decorations) in pixel units.
+ * @return width of the client area in pixel units
+ * @see NativeWindow#getWidth()
+ * @see #convertToWindowUnits(int[])
+ */
+ public int getSurfaceWidth();
+
+ /**
+ * Returns the height of the client area excluding insets (window decorations) in pixel units.
+ * @return height of the client area in pixel units
+ * @see NativeWindow#getHeight()
+ * @see #convertToWindowUnits(int[])
*/
- public int getWidth();
+ public int getSurfaceHeight();
/**
- * Returns the height of the client area excluding insets (window decorations).
- * @return height of the client area
+ * Converts the given pixel units into window units <i>in place</i>.
+ * @param pixelUnitsAndResult int[2] storage holding the pixel units for the x- and y-coord to convert
+ * and the resulting values.
+ * @return result int[2] storage pixelUnitsAndResult for chaining holding the converted values
*/
- public int getHeight();
+ public int[] convertToWindowUnits(final int[] pixelUnitsAndResult);
+
+ /**
+ * Converts the given window units into pixel units <i>in place</i>.
+ * @param windowUnitsAndResult int[2] storage holding the window units for the x- and y-coord to convert
+ * and the resulting values.
+ * @return result int[2] storage windowUnitsAndResult for chaining holding the converted values
+ */
+ public int[] convertToPixelUnits(final int[] windowUnitsAndResult);
/**
* Returns the graphics configuration corresponding to this window.
@@ -195,16 +221,16 @@ public interface NativeSurface extends SurfaceUpdatedListener {
public AbstractGraphicsConfiguration getGraphicsConfiguration();
/**
- * Convenience: Get display handle from
+ * Convenience: Get display handle from
* AbstractGraphicsConfiguration . AbstractGraphicsScreen . AbstractGraphicsDevice
*/
public long getDisplayHandle();
/**
- * Convenience: Get display handle from
+ * Convenience: Get display handle from
* AbstractGraphicsConfiguration . AbstractGraphicsScreen
*/
public int getScreenIndex();
-
+
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeSurfaceHolder.java b/src/nativewindow/classes/javax/media/nativewindow/NativeSurfaceHolder.java
new file mode 100644
index 000000000..b459ab74a
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeSurfaceHolder.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.nativewindow;
+
+/**
+ * Accessor interface for implementing classes with ownership of a {@link NativeSurface}
+ * via an <i>is-a</i> or <i>has-a</i> relation.
+ */
+public interface NativeSurfaceHolder {
+ /**
+ * Returns the associated {@link NativeSurface} of this {@link NativeSurfaceHolder}.
+ */
+ public NativeSurface getNativeSurface();
+}
+
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java
index 12e202975..7f71bc33b 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java
@@ -43,19 +43,44 @@ package javax.media.nativewindow;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
-/** Extend the {@link NativeSurface} interface with windowing
- information such as window handle and position.<P>
+/**
+ * Extend the {@link NativeSurface} interface with windowing
+ * information such as {@link #getWindowHandle() window-handle},
+ * {@link #getWidth() window-size} and {@link #getX() window-position}.
+ * <p>
+ * All values of this interface are represented in window units, if not stated otherwise.
+ * See {@link NativeSurface}.
+ * </p>
+ *
+ * <a name="coordinateSystem"><h5>Coordinate System</h5></a>
+ * <p>
+ * <ul>
+ * <li>Abstract screen space has it's origin in the top-left corner, and may not be at 0/0.</li>
+ * <li>Window origin is in it's top-left corner, see {@link #getX()} and {@link #getY()}. </li>
+ * <li>Window client-area excludes {@link #getInsets() insets}, i.e. window decoration.</li>
+ * <li>Window origin is relative to it's parent window if exist, or the screen position (top-level).</li>
+ * </ul>
+ * </p>
+ * <p>
+ * A window toolkit such as the AWT may either implement this interface
+ * directly with one of its components, or provide and register an
+ * implementation of {@link NativeWindowFactory NativeWindowFactory}
+ * which can create NativeWindow objects for its components.
+ * </p>
+ */
+public interface NativeWindow extends NativeSurface, NativeSurfaceHolder {
- A window toolkit such as the AWT may either implement this interface
- directly with one of its components, or provide and register an
- implementation of {@link NativeWindowFactory NativeWindowFactory}
- which can create NativeWindow objects for its components. <P>
-*/
-public interface NativeWindow extends NativeSurface {
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns this instance, which <i>is-a</i> {@link NativeSurface}.
+ * </p>
+ */
+ @Override
+ public NativeSurface getNativeSurface();
/**
- * destroys the window and releases
- * windowing related resources.
+ * Destroys this window incl. releasing all related resources.
*/
public void destroy();
@@ -77,8 +102,10 @@ public interface NativeWindow extends NativeSurface {
/**
* Returns the insets defined as the width and height of the window decoration
- * on the left, right, top and bottom.<br>
+ * on the left, right, top and bottom in window units.
+ * <p>
* Insets are zero if the window is undecorated, including child windows.
+ * </p>
*
* <p>
* Insets are available only after the native window has been created,
@@ -86,14 +113,14 @@ public interface NativeWindow extends NativeSurface {
*
* The top-level window area's top-left corner is located at
* <pre>
- * getX() - getInsets().{@link InsetsImmutable#getLeftWidth() getLeftWidth()}
- * getY() - getInsets().{@link InsetsImmutable#getTopHeight() getTopHeight()}
+ * {@link #getX()} - getInsets().{@link InsetsImmutable#getLeftWidth() getLeftWidth()}
+ * {@link #getY()} - getInsets().{@link InsetsImmutable#getTopHeight() getTopHeight()}
* </pre>
*
* The top-level window size is
* <pre>
- * getWidth() + getInsets().{@link InsetsImmutable#getTotalWidth() getTotalWidth()}
- * getHeight() + getInsets().{@link InsetsImmutable#getTotalHeight() getTotalHeight()}
+ * {@link #getWidth()} + getInsets().{@link InsetsImmutable#getTotalWidth() getTotalWidth()}
+ * {@link #getHeight()} + getInsets().{@link InsetsImmutable#getTotalHeight() getTotalHeight()}
* </pre>
*
* @return insets
@@ -103,32 +130,71 @@ public interface NativeWindow extends NativeSurface {
/** Returns the current x position of this window, relative to it's parent. */
/**
- * @return the current x position of the top-left corner
- * of the client area relative to it's parent.
- * Since the position reflects the client area, it does not include the insets.
+ * Returns the x position of the top-left corner
+ * of the client area relative to it's parent in window units.
+ * <p>
+ * If no parent exist (top-level window), this coordinate equals the screen coordinate.
+ * </p>
+ * <p>
+ * Since the position reflects the client area, it does not include the insets.
+ * </p>
+ * <p>
+ * See <a href="#coordinateSystem"> Coordinate System</a>.
+ * </p>
* @see #getInsets()
+ * @see #getLocationOnScreen(Point)
*/
public int getX();
/**
- * @return the current y position of the top-left corner
- * of the client area relative to it's parent.
- * Since the position reflects the client area, it does not include the insets.
+ * Returns the current y position of the top-left corner
+ * of the client area relative to it's parent in window units.
+ * <p>
+ * If no parent exist (top-level window), this coordinate equals the screen coordinate.
+ * </p>
+ * <p>
+ * Since the position reflects the client area, it does not include the insets.
+ * </p>
+ * <p>
+ * See <a href="#coordinateSystem"> Coordinate System</a>.
+ * </p>
* @see #getInsets()
+ * @see #getLocationOnScreen(Point)
*/
public int getY();
/**
- * Returns the current position of the top-left corner
- * of the client area in screen coordinates.
+ * Returns the width of the client area excluding insets (window decorations) in window units.
+ * @return width of the client area in window units
+ * @see NativeSurface#getSurfaceWidth()
+ */
+ public int getWidth();
+
+ /**
+ * Returns the height of the client area excluding insets (window decorations) in window units.
+ * @return height of the client area in window units
+ * @see NativeSurface#getSurfaceHeight()
+ */
+ public int getHeight();
+
+ /**
+ * Returns the window's top-left client-area position in the screen.
+ * <p>
+ * If {@link Point} is not <code>null</code>, it is translated about the resulting screen position
+ * and returned.
+ * </p>
+ * <p>
+ * See <a href="#coordinateSystem"> Coordinate System</a>.
+ * </p>
* <p>
* Since the position reflects the client area, it does not include the insets.
* </p>
- * @param point if not null,
- * {@link javax.media.nativewindow.util.Point#translate(javax.media.nativewindow.util.Point)}
- * the passed {@link javax.media.nativewindow.util.Point} by this location on the screen and return it.
- * @return either the passed non null translated point by the screen location of this NativeWindow,
- * or a new instance with the screen location of this NativeWindow.
+ * @param point Optional {@link Point} storage.
+ * If not null, <code>null</code>, it is translated about the resulting screen position
+ * and returned.
+ * @see #getX()
+ * @see #getY()
+ * @see #getInsets()
*/
public Point getLocationOnScreen(Point point);
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowException.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowException.java
index 593c1e7d6..16355032f 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowException.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowException.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -50,19 +50,19 @@ public class NativeWindowException extends RuntimeException {
/** Constructs a NativeWindowException object with the specified detail
message. */
- public NativeWindowException(String message) {
+ public NativeWindowException(final String message) {
super(message);
}
/** Constructs a NativeWindowException object with the specified detail
message and root cause. */
- public NativeWindowException(String message, Throwable cause) {
+ public NativeWindowException(final String message, final Throwable cause) {
super(message, cause);
}
/** Constructs a NativeWindowException object with the specified root
cause. */
- public NativeWindowException(Throwable cause) {
+ public NativeWindowException(final Throwable cause) {
super(cause);
}
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index 89d476a3b..58542f07d 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -33,19 +33,38 @@
package javax.media.nativewindow;
-import java.lang.reflect.Constructor;
+import java.io.File;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import javax.media.nativewindow.util.PointImmutable;
+
+import jogamp.common.os.PlatformPropsImpl;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NativeWindowFactoryImpl;
+import jogamp.nativewindow.ToolkitProperties;
+import jogamp.nativewindow.ResourceToolkitLock;
+import jogamp.nativewindow.WrappedWindow;
+import jogamp.nativewindow.macosx.OSXUtil;
+import jogamp.nativewindow.windows.GDIUtil;
+import jogamp.nativewindow.x11.X11Lib;
import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos;
+import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
+import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
+import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
/** Provides a pluggable mechanism for arbitrary window toolkits to
adapt their components to the {@link NativeWindow} interface,
@@ -57,97 +76,132 @@ public abstract class NativeWindowFactory {
protected static final boolean DEBUG;
/** OpenKODE/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}.*/
- public static final String TYPE_EGL = "jogamp.newt.driver.kd".intern();
+ public static final String TYPE_EGL = ".egl".intern();
/** Microsoft Windows type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
- public static final String TYPE_WINDOWS = "jogamp.newt.driver.windows".intern();
+ public static final String TYPE_WINDOWS = ".windows".intern();
/** X11 type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
- public static final String TYPE_X11 = "jogamp.newt.driver.x11".intern();
+ public static final String TYPE_X11 = ".x11".intern();
+
+ /** Broadcom VC IV/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
+ public static final String TYPE_BCM_VC_IV = ".bcm.vc.iv".intern();
/** Android/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}.*/
- public static final String TYPE_ANDROID = "jogamp.newt.driver.android".intern();
+ public static final String TYPE_ANDROID = ".android".intern();
/** Mac OS X type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
- public static final String TYPE_MACOSX = "jogamp.newt.driver.macosx".intern();
+ public static final String TYPE_MACOSX = ".macosx".intern();
/** Generic AWT type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
- public static final String TYPE_AWT = "jogamp.newt.driver.awt".intern();
+ public static final String TYPE_AWT = ".awt".intern();
/** Generic DEFAULT type, where platform implementation don't care, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
- public static final String TYPE_DEFAULT = "default".intern();
+ public static final String TYPE_DEFAULT = ".default".intern();
private static final String nativeWindowingTypePure; // canonical String via String.intern()
private static final String nativeWindowingTypeCustom; // canonical String via String.intern()
-
+
private static NativeWindowFactory defaultFactory;
private static Map<Class<?>, NativeWindowFactory> registeredFactories;
-
+
private static Class<?> nativeWindowClass;
private static boolean isAWTAvailable;
-
+
private static final String JAWTUtilClassName = "jogamp.nativewindow.jawt.JAWTUtil" ;
+ /** {@link jogamp.nativewindow.x11.X11Util} implements {@link ToolkitProperties}. */
private static final String X11UtilClassName = "jogamp.nativewindow.x11.X11Util";
+ /** {@link jogamp.nativewindow.macosx.OSXUtil} implements {@link ToolkitProperties}. */
private static final String OSXUtilClassName = "jogamp.nativewindow.macosx.OSXUtil";
+ /** {@link jogamp.nativewindow.windows.GDIUtil} implements {@link ToolkitProperties}. */
private static final String GDIClassName = "jogamp.nativewindow.windows.GDIUtil";
-
+
private static ToolkitLock jawtUtilJAWTToolkitLock;
-
- public static final String X11JAWTToolkitLockClassName = "jogamp.nativewindow.jawt.x11.X11JAWTToolkitLock" ;
- public static final String X11ToolkitLockClassName = "jogamp.nativewindow.x11.X11ToolkitLock" ;
-
- private static Class<?> x11JAWTToolkitLockClass;
- private static Constructor<?> x11JAWTToolkitLockConstructor;
- private static Class<?> x11ToolkitLockClass;
- private static Constructor<?> x11ToolkitLockConstructor;
+
private static boolean requiresToolkitLock;
+ private static boolean desktopHasThreadingIssues;
+ // Shutdown hook mechanism for the factory
private static volatile boolean isJVMShuttingDown = false;
-
+ private static final List<Runnable> customShutdownHooks = new ArrayList<Runnable>();
+
/** Creates a new NativeWindowFactory instance. End users do not
need to call this method. */
protected NativeWindowFactory() {
}
+ private static final boolean guessBroadcomVCIV() {
+ return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ private final File vcliblocation = new File(
+ "/opt/vc/lib/libbcm_host.so");
+ @Override
+ public Boolean run() {
+ if ( vcliblocation.isFile() ) {
+ return Boolean.TRUE;
+ }
+ return Boolean.FALSE;
+ }
+ } ).booleanValue();
+ }
+
private static String _getNativeWindowingType() {
- switch(Platform.OS_TYPE) {
+ switch(PlatformPropsImpl.OS_TYPE) {
case ANDROID:
return TYPE_ANDROID;
case MACOS:
return TYPE_MACOSX;
case WINDOWS:
- return TYPE_WINDOWS;
+ return TYPE_WINDOWS;
case OPENKODE:
return TYPE_EGL;
-
+
case LINUX:
case FREEBSD:
case SUNOS:
case HPUX:
default:
+ if( guessBroadcomVCIV() ) {
+ return TYPE_BCM_VC_IV;
+ }
return TYPE_X11;
}
}
static {
- Platform.initSingleton();
- DEBUG = Debug.debug("NativeWindow");
+ final boolean[] _DEBUG = new boolean[] { false };
+ final String[] _tmp = new String[] { null };
+
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ Platform.initSingleton(); // last resort ..
+ _DEBUG[0] = Debug.debug("NativeWindow");
+ _tmp[0] = PropertyAccess.getProperty("nativewindow.ws.name", true);
+ Runtime.getRuntime().addShutdownHook(
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ NativeWindowFactory.shutdown(true);
+ } }, "NativeWindowFactory_ShutdownHook" ) ) ;
+ return null;
+ } } ) ;
+
+ DEBUG = _DEBUG[0];
if(DEBUG) {
System.err.println(Thread.currentThread().getName()+" - Info: NativeWindowFactory.<init>");
// Thread.dumpStack();
}
-
+
// Gather the windowing TK first
nativeWindowingTypePure = _getNativeWindowingType();
- final String tmp = Debug.getProperty("nativewindow.ws.name", true);
- if(null==tmp || tmp.length()==0) {
+ if(null==_tmp[0] || _tmp[0].length()==0) {
nativeWindowingTypeCustom = nativeWindowingTypePure;
} else {
- nativeWindowingTypeCustom = tmp.intern(); // canonical representation
+ nativeWindowingTypeCustom = _tmp[0].intern(); // canonical representation
}
}
- static boolean initialized = false;
+ private static boolean initialized = false;
private static void initSingletonNativeImpl(final ClassLoader cl) {
final String clazzName;
@@ -162,12 +216,81 @@ public abstract class NativeWindowFactory {
}
if( null != clazzName ) {
ReflectionUtil.callStaticMethod(clazzName, "initSingleton", null, null, cl );
-
- final Boolean res = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "requiresToolkitLock", null, null, cl);
- requiresToolkitLock = res.booleanValue();
- } else {
+
+ final Boolean res1 = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "requiresToolkitLock", null, null, cl);
+ requiresToolkitLock = res1.booleanValue();
+ final Boolean res2 = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "hasThreadingIssues", null, null, cl);
+ desktopHasThreadingIssues = res2.booleanValue();
+ } else {
requiresToolkitLock = false;
- }
+ desktopHasThreadingIssues = false;
+ }
+ }
+
+ /** Returns true if the JVM is shutting down, otherwise false. */
+ public static final boolean isJVMShuttingDown() { return isJVMShuttingDown; }
+
+ /**
+ * Add a custom shutdown hook to be performed at JVM shutdown before shutting down NativeWindowFactory instance.
+ *
+ * @param head if true add runnable at the start, otherwise at the end
+ * @param runnable runnable to be added.
+ */
+ public static void addCustomShutdownHook(final boolean head, final Runnable runnable) {
+ synchronized( customShutdownHooks ) {
+ if( !customShutdownHooks.contains( runnable ) ) {
+ if( head ) {
+ customShutdownHooks.add(0, runnable);
+ } else {
+ customShutdownHooks.add( runnable );
+ }
+ }
+ }
+ }
+
+ /**
+ * Cleanup resources at JVM shutdown
+ */
+ public static synchronized void shutdown(final boolean _isJVMShuttingDown) {
+ isJVMShuttingDown = _isJVMShuttingDown;
+ if(DEBUG) {
+ System.err.println("NativeWindowFactory.shutdown() START: JVM Shutdown "+isJVMShuttingDown+", on thread "+Thread.currentThread().getName());
+ }
+ synchronized(customShutdownHooks) {
+ final int cshCount = customShutdownHooks.size();
+ for(int i=0; i < cshCount; i++) {
+ try {
+ if( DEBUG ) {
+ System.err.println("NativeWindowFactory.shutdown - customShutdownHook #"+(i+1)+"/"+cshCount);
+ }
+ customShutdownHooks.get(i).run();
+ } catch(final Throwable t) {
+ System.err.println("NativeWindowFactory.shutdown: Caught "+t.getClass().getName()+" during customShutdownHook #"+(i+1)+"/"+cshCount);
+ if( DEBUG ) {
+ t.printStackTrace();
+ }
+ }
+ }
+ customShutdownHooks.clear();
+ }
+ if(DEBUG) {
+ System.err.println("NativeWindowFactory.shutdown(): Post customShutdownHook");
+ }
+
+ if(initialized) {
+ initialized = false;
+ if(null != registeredFactories) {
+ registeredFactories.clear();
+ registeredFactories = null;
+ }
+ GraphicsConfigurationFactory.shutdown();
+ }
+
+ shutdownNativeImpl(NativeWindowFactory.class.getClassLoader()); // always re-shutdown
+ // SharedResourceToolkitLock.shutdown(DEBUG); // not used yet
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END JVM Shutdown "+isJVMShuttingDown);
+ }
}
private static void shutdownNativeImpl(final ClassLoader cl) {
@@ -183,9 +306,12 @@ public abstract class NativeWindowFactory {
}
if( null != clazzName ) {
ReflectionUtil.callStaticMethod(clazzName, "shutdown", null, null, cl );
- }
+ }
}
-
+
+ /** Returns true if {@link #initSingleton()} has been called w/o subsequent {@link #shutdown(boolean)}. */
+ public static synchronized boolean isInitialized() { return initialized; }
+
/**
* Static one time initialization of this factory.<br>
* This initialization method <b>must be called</b> once by the program or utilizing modules!
@@ -204,19 +330,20 @@ public abstract class NativeWindowFactory {
if( Platform.AWT_AVAILABLE &&
ReflectionUtil.isClassAvailable("com.jogamp.nativewindow.awt.AWTGraphicsDevice", cl) ) {
-
- Method[] jawtUtilMethods = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
+
+ final Method[] jawtUtilMethods = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
+ @Override
public Method[] run() {
try {
- Class<?> _jawtUtilClass = Class.forName(JAWTUtilClassName, true, NativeWindowFactory.class.getClassLoader());
- Method jawtUtilIsHeadlessMethod = _jawtUtilClass.getDeclaredMethod("isHeadlessMode", (Class[])null);
+ final Class<?> _jawtUtilClass = Class.forName(JAWTUtilClassName, true, NativeWindowFactory.class.getClassLoader());
+ final Method jawtUtilIsHeadlessMethod = _jawtUtilClass.getDeclaredMethod("isHeadlessMode", (Class[])null);
jawtUtilIsHeadlessMethod.setAccessible(true);
- Method jawtUtilInitMethod = _jawtUtilClass.getDeclaredMethod("initSingleton", (Class[])null);
+ final Method jawtUtilInitMethod = _jawtUtilClass.getDeclaredMethod("initSingleton", (Class[])null);
jawtUtilInitMethod.setAccessible(true);
- Method jawtUtilGetJAWTToolkitLockMethod = _jawtUtilClass.getDeclaredMethod("getJAWTToolkitLock", new Class[]{});
+ final Method jawtUtilGetJAWTToolkitLockMethod = _jawtUtilClass.getDeclaredMethod("getJAWTToolkitLock", new Class[]{});
jawtUtilGetJAWTToolkitLockMethod.setAccessible(true);
- return new Method[] { jawtUtilInitMethod, jawtUtilIsHeadlessMethod, jawtUtilGetJAWTToolkitLockMethod };
- } catch (Exception e) {
+ return new Method[] { jawtUtilInitMethod, jawtUtilIsHeadlessMethod, jawtUtilGetJAWTToolkitLockMethod };
+ } catch (final Exception e) {
if(DEBUG) {
e.printStackTrace();
}
@@ -228,7 +355,7 @@ public abstract class NativeWindowFactory {
final Method jawtUtilInitMethod = jawtUtilMethods[0];
final Method jawtUtilIsHeadlessMethod = jawtUtilMethods[1];
final Method jawtUtilGetJAWTToolkitLockMethod = jawtUtilMethods[2];
-
+
ReflectionUtil.callMethod(null, jawtUtilInitMethod);
Object resO = ReflectionUtil.callMethod(null, jawtUtilIsHeadlessMethod);
@@ -239,93 +366,61 @@ public abstract class NativeWindowFactory {
} else {
throw new RuntimeException("JAWTUtil.isHeadlessMode() didn't return a Boolean");
}
- resO = ReflectionUtil.callMethod(null, jawtUtilGetJAWTToolkitLockMethod);
+ resO = ReflectionUtil.callMethod(null, jawtUtilGetJAWTToolkitLockMethod);
if(resO instanceof ToolkitLock) {
jawtUtilJAWTToolkitLock = (ToolkitLock) resO;
} else {
throw new RuntimeException("JAWTUtil.getJAWTToolkitLock() didn't return a ToolkitLock");
- }
+ }
}
}
-
+
// X11 initialization after possible AWT initialization
// This is performed post AWT initialization, allowing AWT to complete the same,
- // which may have been triggered before NativeWindow initialization.
- // This way behavior is more uniforms across configurations (Applet/RCP, applications, ..).
+ // which may have been triggered before NativeWindow initialization.
+ // This way behavior is more uniforms across configurations (Applet/RCP, applications, ..).
initSingletonNativeImpl(cl);
-
+
registeredFactories = Collections.synchronizedMap(new HashMap<Class<?>, NativeWindowFactory>());
// register our default factory -> NativeWindow
- NativeWindowFactory factory = new NativeWindowFactoryImpl();
+ final NativeWindowFactory factory = new NativeWindowFactoryImpl();
nativeWindowClass = javax.media.nativewindow.NativeWindow.class;
registerFactory(nativeWindowClass, factory);
defaultFactory = factory;
-
+
if ( isAWTAvailable ) {
// register either our default factory or (if exist) the X11/AWT one -> AWT Component
registerFactory(ReflectionUtil.getClass(ReflectionUtil.AWTNames.ComponentClass, false, cl), factory);
}
- if( TYPE_X11 == nativeWindowingTypePure ) {
- // passing through RuntimeException if not exists intended
- x11ToolkitLockClass = ReflectionUtil.getClass(X11ToolkitLockClassName, false, cl);
- x11ToolkitLockConstructor = ReflectionUtil.getConstructor(x11ToolkitLockClass, new Class[] { long.class } );
- if( isAWTAvailable() ) {
- x11JAWTToolkitLockClass = ReflectionUtil.getClass(X11JAWTToolkitLockClassName, false, cl);
- x11JAWTToolkitLockConstructor = ReflectionUtil.getConstructor(x11JAWTToolkitLockClass, new Class[] { long.class } );
- }
- }
-
if(DEBUG) {
- System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock);
+ System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock+", desktopHasThreadingIssues "+desktopHasThreadingIssues);
System.err.println("NativeWindowFactory isAWTAvailable "+isAWTAvailable+", defaultFactory "+factory);
}
-
+
GraphicsConfigurationFactory.initSingleton();
}
}
- public static synchronized void shutdown(boolean _isJVMShuttingDown) {
- isJVMShuttingDown = _isJVMShuttingDown;
- if(DEBUG) {
- System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() START: JVM Shutdown "+isJVMShuttingDown);
- }
- if(initialized) {
- initialized = false;
- if(null != registeredFactories) {
- registeredFactories.clear();
- registeredFactories = null;
- }
- GraphicsConfigurationFactory.shutdown();
- }
- shutdownNativeImpl(NativeWindowFactory.class.getClassLoader()); // always re-shutdown
- if(DEBUG) {
- System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END JVM Shutdown "+isJVMShuttingDown);
- }
- }
-
- /** Returns true if the JVM is shutting down, otherwise false. */
- public static final boolean isJVMShuttingDown() { return isJVMShuttingDown; }
-
/** @return true if the underlying toolkit requires locking, otherwise false. */
public static boolean requiresToolkitLock() {
return requiresToolkitLock;
- }
-
+ }
+
/** @return true if not headless, AWT Component and NativeWindow's AWT part available */
public static boolean isAWTAvailable() { return isAWTAvailable; }
/**
* @param useCustom if false return the native value, if true return a custom value if set, otherwise fallback to the native value.
- * @return the native window type, e.g. {@link #TYPE_X11}, which is canonical via {@link String#intern()}.
+ * @return the native window type, e.g. {@link #TYPE_X11}, which is canonical via {@link String#intern()}.
* Hence {@link String#equals(Object)} and <code>==</code> produce the same result.
*/
- public static String getNativeWindowType(boolean useCustom) {
+ public static String getNativeWindowType(final boolean useCustom) {
return useCustom?nativeWindowingTypeCustom:nativeWindowingTypePure;
}
- /** Don't know if we shall add this factory here ..
+ /** Don't know if we shall add this factory here ..
public static AbstractGraphicsDevice createGraphicsDevice(String type, String connection, int unitID, long handle, ToolkitLock locker) {
if(TYPE_EGL == type) {
return new
@@ -338,7 +433,7 @@ public abstract class NativeWindowFactory {
} */
/** Sets the default NativeWindowFactory. */
- public static void setDefaultFactory(NativeWindowFactory factory) {
+ public static void setDefaultFactory(final NativeWindowFactory factory) {
defaultFactory = factory;
}
@@ -348,139 +443,102 @@ public abstract class NativeWindowFactory {
}
/**
- * Provides the system default {@link ToolkitLock}, a singleton instance.
- * <br>
+ * Returns the AWT {@link ToolkitLock} (JAWT based) if {@link #isAWTAvailable}, otherwise null.
+ * <p>
+ * The JAWT based {@link ToolkitLock} also locks the global lock,
+ * which matters if the latter is required.
+ * </p>
+ */
+ public static ToolkitLock getAWTToolkitLock() {
+ return jawtUtilJAWTToolkitLock;
+ }
+
+ public static ToolkitLock getNullToolkitLock() {
+ return NativeWindowFactoryImpl.getNullToolkitLock();
+ }
+
+ /**
+ * Provides the system default {@link ToolkitLock} for the default system windowing type.
+ * @see #getNativeWindowType(boolean)
* @see #getDefaultToolkitLock(java.lang.String)
*/
public static ToolkitLock getDefaultToolkitLock() {
- return getDefaultToolkitLock(getNativeWindowType(false));
+ return getDefaultToolkitLock(nativeWindowingTypePure);
}
/**
- * Provides the default {@link ToolkitLock} for <code>type</code>, a singleton instance.
- * <br>
+ * Provides the default {@link ToolkitLock} for <code>type</code>.
* <ul>
- * <li> If {@link #initSingleton(boolean) initSingleton( <b>firstUIActionOnProcess := false</b> )} </li>
- * <ul>
- * <li>If <b>AWT-type</b> and <b>native-X11-type</b> and <b>AWT-available</b></li>
- * <ul>
- * <li> return {@link #getAWTToolkitLock()} </li>
- * </ul>
- * </ul>
- * <li> Otherwise return {@link #getNullToolkitLock()} </li>
+ * <li> JAWT {@link ToolkitLock} if required and <code>type</code> is of {@link #TYPE_AWT} and AWT available,</li>
+ * <li> {@link jogamp.nativewindow.ResourceToolkitLock} if required, otherwise</li>
+ * <li> {@link jogamp.nativewindow.NullToolkitLock} </li>
* </ul>
*/
- public static ToolkitLock getDefaultToolkitLock(String type) {
- if( requiresToolkitLock() ) {
- if( TYPE_AWT == type && TYPE_X11 == getNativeWindowType(false) && isAWTAvailable() ) {
+ public static ToolkitLock getDefaultToolkitLock(final String type) {
+ if( requiresToolkitLock ) {
+ if( TYPE_AWT == type && isAWTAvailable() ) { // uses .intern()!
return getAWTToolkitLock();
}
+ return ResourceToolkitLock.create();
}
return NativeWindowFactoryImpl.getNullToolkitLock();
}
- /** Returns the AWT Toolkit (JAWT based) if {@link #isAWTAvailable}, otherwise null. */
- public static ToolkitLock getAWTToolkitLock() {
- return jawtUtilJAWTToolkitLock;
- }
-
- public static ToolkitLock getNullToolkitLock() {
- return NativeWindowFactoryImpl.getNullToolkitLock();
- }
-
/**
- * Creates the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>.
- * <br>
+ * Provides the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>.
* <ul>
- * <li> If {@link #initSingleton(boolean) initSingleton( <b>firstUIActionOnProcess := false</b> )} </li>
- * <ul>
- * <li>If <b>X11 type</b> </li>
- * <ul>
- * <li> return {@link jogamp.nativewindow.x11.X11ToolkitLock} </li>
- * </ul>
- * </ul>
- * <li> Otherwise return {@link jogamp.nativewindow.NullToolkitLock} </li>
+ * <li> JAWT {@link ToolkitLock} if required and <code>type</code> is of {@link #TYPE_AWT} and AWT available,</li>
+ * <li> {@link jogamp.nativewindow.ResourceToolkitLock} if required, otherwise</li>
+ * <li> {@link jogamp.nativewindow.NullToolkitLock} </li>
* </ul>
*/
- public static ToolkitLock createDefaultToolkitLock(String type, long deviceHandle) {
- if( requiresToolkitLock() ) {
- if( TYPE_X11 == type ) {
- if( 0== deviceHandle ) {
- throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11");
- }
- return createX11ToolkitLock(deviceHandle);
+ public static ToolkitLock getDefaultToolkitLock(final String type, final long deviceHandle) {
+ if( requiresToolkitLock ) {
+ if( TYPE_AWT == type && isAWTAvailable() ) { // uses .intern()!
+ return getAWTToolkitLock();
}
+ return ResourceToolkitLock.create();
}
return NativeWindowFactoryImpl.getNullToolkitLock();
}
-
+
/**
- * Creates the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>.
- * <br>
- * <ul>
- * <li> If {@link #initSingleton(boolean) initSingleton( <b>firstUIActionOnProcess := false</b> )} </li>
- * <ul>
- * <li>If <b>X11 type</b> </li>
- * <ul>
- * <li> If <b>shared-AWT-type</b> and <b>AWT available</b> </li>
- * <ul>
- * <li> return {@link jogamp.nativewindow.jawt.x11.X11JAWTToolkitLock} </li>
- * </ul>
- * <li> else return {@link jogamp.nativewindow.x11.X11ToolkitLock} </li>
- * </ul>
- * </ul>
- * <li> Otherwise return {@link jogamp.nativewindow.NullToolkitLock} </li>
- * </ul>
+ * @param device
+ * @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen
+ * @return newly created AbstractGraphicsScreen matching device's native type
*/
- public static ToolkitLock createDefaultToolkitLock(String type, String sharedType, long deviceHandle) {
- if( requiresToolkitLock() ) {
- if( TYPE_X11 == type ) {
- if( 0== deviceHandle ) {
- throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11");
- }
- if( TYPE_AWT == sharedType && isAWTAvailable() ) {
- return createX11AWTToolkitLock(deviceHandle);
- }
- return createX11ToolkitLock(deviceHandle);
+ public static AbstractGraphicsScreen createScreen(final AbstractGraphicsDevice device, int screen) {
+ final String type = device.getType();
+ if( TYPE_X11 == type ) {
+ final X11GraphicsDevice x11Device = (X11GraphicsDevice)device;
+ if(0 > screen) {
+ screen = x11Device.getDefaultScreen();
}
+ return new X11GraphicsScreen(x11Device, screen);
}
- return NativeWindowFactoryImpl.getNullToolkitLock();
- }
-
- protected static ToolkitLock createX11AWTToolkitLock(long deviceHandle) {
- try {
- if(DEBUG) {
- System.err.println("NativeWindowFactory.createX11AWTToolkitLock(0x"+Long.toHexString(deviceHandle)+")");
- // Thread.dumpStack();
- }
- return (ToolkitLock) x11JAWTToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)});
- } catch (Exception ex) {
- throw new RuntimeException(ex);
+ if(0 > screen) {
+ screen = 0; // FIXME: Needs native API utilization
}
- }
-
- protected static ToolkitLock createX11ToolkitLock(long deviceHandle) {
- try {
- return (ToolkitLock) x11ToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)});
- } catch (Exception ex) {
- throw new RuntimeException(ex);
+ if( TYPE_AWT == type ) {
+ final AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) device;
+ return new AWTGraphicsScreen(awtDevice);
}
+ return new DefaultGraphicsScreen(device, screen);
}
-
/** Returns the appropriate NativeWindowFactory to handle window
objects of the given type. The windowClass might be {@link
NativeWindow NativeWindow}, in which case the client has
already assumed the responsibility of creating a compatible
NativeWindow implementation, or it might be that of a toolkit
class like {@link java.awt.Component Component}. */
- public static NativeWindowFactory getFactory(Class<?> windowClass) throws IllegalArgumentException {
+ public static NativeWindowFactory getFactory(final Class<?> windowClass) throws IllegalArgumentException {
if (nativeWindowClass.isAssignableFrom(windowClass)) {
return registeredFactories.get(nativeWindowClass);
}
Class<?> clazz = windowClass;
while (clazz != null) {
- NativeWindowFactory factory = registeredFactories.get(clazz);
+ final NativeWindowFactory factory = registeredFactories.get(clazz);
if (factory != null) {
return factory;
}
@@ -492,7 +550,7 @@ public abstract class NativeWindowFactory {
/** Registers a NativeWindowFactory handling window objects of the
given class. This does not need to be called by end users,
only implementors of new NativeWindowFactory subclasses. */
- protected static void registerFactory(Class<?> windowClass, NativeWindowFactory factory) {
+ protected static void registerFactory(final Class<?> windowClass, final NativeWindowFactory factory) {
if(DEBUG) {
System.err.println("NativeWindowFactory.registerFactory() "+windowClass+" -> "+factory);
}
@@ -500,7 +558,7 @@ public abstract class NativeWindowFactory {
}
/** Converts the given window object and it's
- {@link AbstractGraphicsConfiguration AbstractGraphicsConfiguration} into a
+ {@link AbstractGraphicsConfiguration AbstractGraphicsConfiguration} into a
{@link NativeWindow NativeWindow} which can be operated upon by a custom
toolkit, e.g. {@link javax.media.opengl.GLDrawableFactory javax.media.opengl.GLDrawableFactory}.<br>
The object may be a component for a particular window toolkit, such as an AWT
@@ -511,14 +569,14 @@ public abstract class NativeWindowFactory {
NativeWindowFactory is responsible for handling objects from a
particular window toolkit. The built-in NativeWindowFactory
handles NativeWindow instances as well as AWT Components.<br>
-
+
@throws IllegalArgumentException if the given window object
could not be handled by any of the registered
NativeWindowFactory instances
@see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
*/
- public static NativeWindow getNativeWindow(Object winObj, AbstractGraphicsConfiguration config) throws IllegalArgumentException, NativeWindowException {
+ public static NativeWindow getNativeWindow(final Object winObj, final AbstractGraphicsConfiguration config) throws IllegalArgumentException, NativeWindowException {
if (winObj == null) {
throw new IllegalArgumentException("Null window object");
}
@@ -530,22 +588,22 @@ public abstract class NativeWindowFactory {
NativeWindow. Implementors of concrete NativeWindowFactory
subclasses should override this method. */
protected abstract NativeWindow getNativeWindowImpl(Object winObj, AbstractGraphicsConfiguration config) throws IllegalArgumentException;
-
+
/**
* Returns the {@link OffscreenLayerSurface} instance of this {@link NativeSurface}.
* <p>
- * In case this surface is a {@link NativeWindow}, we traverse from the given surface
+ * In case this surface is a {@link NativeWindow}, we traverse from the given surface
* up to root until an implementation of {@link OffscreenLayerSurface} is found.
* In case <code>ifEnabled</code> is true, the surface must also implement {@link OffscreenLayerOption}
- * where {@link OffscreenLayerOption#isOffscreenLayerSurfaceEnabled()} is <code>true</code>.
+ * where {@link OffscreenLayerOption#isOffscreenLayerSurfaceEnabled()} is <code>true</code>.
* </p>
- *
+ *
* @param surface The surface to query.
- * @param ifEnabled If true, only return the enabled {@link OffscreenLayerSurface}, see {@link OffscreenLayerOption#isOffscreenLayerSurfaceEnabled()}.
+ * @param ifEnabled If true, only return the enabled {@link OffscreenLayerSurface}, see {@link OffscreenLayerOption#isOffscreenLayerSurfaceEnabled()}.
* @return
*/
- public static OffscreenLayerSurface getOffscreenLayerSurface(NativeSurface surface, boolean ifEnabled) {
- if(surface instanceof OffscreenLayerSurface &&
+ public static OffscreenLayerSurface getOffscreenLayerSurface(final NativeSurface surface, final boolean ifEnabled) {
+ if(surface instanceof OffscreenLayerSurface &&
( !ifEnabled || surface instanceof OffscreenLayerOption ) ) {
final OffscreenLayerSurface ols = (OffscreenLayerSurface) surface;
return ( !ifEnabled || ((OffscreenLayerOption)ols).isOffscreenLayerSurfaceEnabled() ) ? ols : null;
@@ -558,12 +616,12 @@ public abstract class NativeWindowFactory {
final OffscreenLayerSurface ols = (OffscreenLayerSurface) nw;
return ( !ifEnabled || ((OffscreenLayerOption)ols).isOffscreenLayerSurfaceEnabled() ) ? ols : null;
}
- nw = nw.getParent();
+ nw = nw.getParent();
}
}
- return null;
+ return null;
}
-
+
/**
* Returns true if the given visualID is valid for further processing, i.e. OpenGL usage,
* otherwise return false.
@@ -575,9 +633,84 @@ public abstract class NativeWindowFactory {
* at creation time (see above), it is not valid for further processing.
* </p>
*/
- public static boolean isNativeVisualIDValidForProcessing(int visualID) {
- return NativeWindowFactory.TYPE_X11 != NativeWindowFactory.getNativeWindowType(false) ||
+ public static boolean isNativeVisualIDValidForProcessing(final int visualID) {
+ return NativeWindowFactory.TYPE_X11 != NativeWindowFactory.getNativeWindowType(false) ||
VisualIDHolder.VID_UNDEFINED != visualID ;
}
-
+
+ /**
+ * Creates a native device type, following {@link #getNativeWindowType(boolean) getNativeWindowType(true)}.
+ * <p>
+ * The device will be opened if <code>own</code> is true, otherwise no native handle will ever be acquired.
+ * </p>
+ */
+ public static AbstractGraphicsDevice createDevice(final String displayConnection, final boolean own) {
+ final String nwt = NativeWindowFactory.getNativeWindowType(true);
+ if( NativeWindowFactory.TYPE_X11 == nwt ) {
+ if( own ) {
+ return new X11GraphicsDevice(displayConnection, AbstractGraphicsDevice.DEFAULT_UNIT, null /* ToolkitLock */);
+ } else {
+ return new X11GraphicsDevice(displayConnection, AbstractGraphicsDevice.DEFAULT_UNIT);
+ }
+ } else if( NativeWindowFactory.TYPE_WINDOWS == nwt ) {
+ return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ } else if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
+ return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+ /**
+ * FIXME: Needs service provider interface (SPI) for TK dependent implementation
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_ANDROID== nwt ) {
+ } else if( NativeWindowFactory.TYPE_EGL == nwt ) {
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_AWT == nwt ) {
+ */
+ }
+ throw new UnsupportedOperationException("n/a for windowing system: "+nwt);
+ }
+
+ /**
+ * Creates a wrapped {@link NativeWindow} with given native handles and {@link AbstractGraphicsScreen}.
+ * <p>
+ * The given {@link UpstreamWindowHookMutableSizePos} maybe used to reflect resizes and repositioning of the native window.
+ * </p>
+ * <p>
+ * The {@link AbstractGraphicsScreen} may be created via {@link #createScreen(AbstractGraphicsDevice, int)}.
+ * </p>
+ * <p>
+ * The {@link AbstractGraphicsScreen} may have an underlying open {@link AbstractGraphicsDevice}
+ * or a simple <i>dummy</i> instance, see {@link #createDevice(String, boolean)}.
+ * </p>
+ */
+ public static NativeWindow createWrappedWindow(final AbstractGraphicsScreen aScreen, final long surfaceHandle, final long windowHandle,
+ final UpstreamWindowHookMutableSizePos hook) {
+ final CapabilitiesImmutable caps = new Capabilities();
+ final AbstractGraphicsConfiguration config = new DefaultGraphicsConfiguration(aScreen, caps, caps);
+ return new WrappedWindow(config, surfaceHandle, hook, true, windowHandle);
+ }
+
+ /**
+ * @param nw
+ * @return top-left client-area position in window units
+ */
+ public static PointImmutable getLocationOnScreen(final NativeWindow nw) {
+ final String nwt = NativeWindowFactory.getNativeWindowType(true);
+ if( NativeWindowFactory.TYPE_X11 == nwt ) {
+ return X11Lib.GetRelativeLocation(nw.getDisplayHandle(), nw.getScreenIndex(), nw.getWindowHandle(), 0, 0, 0);
+ } else if( NativeWindowFactory.TYPE_WINDOWS == nwt ) {
+ return GDIUtil.GetRelativeLocation(nw.getWindowHandle(), 0, 0, 0);
+ } else if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
+ return OSXUtil.GetLocationOnScreen(nw.getWindowHandle(), 0, 0);
+ /**
+ * FIXME: Needs service provider interface (SPI) for TK dependent implementation
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_ANDROID== nwt ) {
+ } else if( NativeWindowFactory.TYPE_EGL == nwt ) {
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_AWT == nwt ) {
+ */
+ }
+ throw new UnsupportedOperationException("n/a for windowing system: "+nwt);
+ }
+
+
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerOption.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerOption.java
index 12d30b3cd..11496899a 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerOption.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerOption.java
@@ -32,30 +32,30 @@ package javax.media.nativewindow;
* within the implementation.
*/
public interface OffscreenLayerOption {
- /**
+ /**
* Request an offscreen layer, if supported.
* <p>
* Shall be called before the first {@link NativeWindow#lockSurface()},
* and hence before realization.
* </p>
- *
+ *
* @see #getShallUseOffscreenLayer()
- * @see #isOffscreenLayerSurfaceEnabled()
+ * @see #isOffscreenLayerSurfaceEnabled()
*/
public void setShallUseOffscreenLayer(boolean v);
/** Returns the property set by {@link #setShallUseOffscreenLayer(boolean)}. */
public boolean getShallUseOffscreenLayer();
- /**
+ /**
* Returns true if this instance uses an offscreen layer, otherwise false.
* <p>
* This instance is an offscreen layer, if {@link #setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
* has been called before it's realization and first lock and the underlying implementation supports it.
* </p>
* The return value is undefined before issuing the first {@link NativeWindow#lockSurface()}.
- *
- * @see #setShallUseOffscreenLayer(boolean)
+ *
+ * @see #setShallUseOffscreenLayer(boolean)
*/
public boolean isOffscreenLayerSurfaceEnabled();
} \ No newline at end of file
diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
index f9800109c..cf8cf89d2 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
@@ -27,30 +27,60 @@
*/
package javax.media.nativewindow;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PointImmutable;
+
+import com.jogamp.common.util.locks.RecursiveLock;
+
/**
* Interface specifying the offscreen layer surface protocol.
*/
public interface OffscreenLayerSurface {
- /**
+ /**
* Attach the offscreen layer to this offscreen layer surface.
+ * <p>
+ * Implementation may realize all required resources at this point.
+ * </p>
+ *
* @see #isOffscreenLayerSurfaceEnabled()
* @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
*/
public void attachSurfaceLayer(final long layerHandle) throws NativeWindowException;
-
- /**
+
+ /**
* Detaches a previously attached offscreen layer from this offscreen layer surface.
* @see #attachSurfaceLayer(long)
* @see #isOffscreenLayerSurfaceEnabled()
- * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
+ * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
* or no surface layer is attached.
*/
public void detachSurfaceLayer() throws NativeWindowException;
-
+
+ /** Returns the attached surface layer or null if none is attached. */
+ public long getAttachedSurfaceLayer();
+
/** Returns true if a surface layer is attached, otherwise false. */
public boolean isSurfaceLayerAttached();
-
+
/** Sets the capabilities of this instance, allowing upstream API's to refine it, i.e. OpenGL related settings. */
public void setChosenCapabilities(CapabilitiesImmutable caps);
-
+
+ /** Returns the recursive lock object of this surface, which synchronizes multithreaded access. */
+ public RecursiveLock getLock();
+
+ /**
+ * Optional method setting cursor in the corresponding on-screen surface/window, if exists.
+ *
+ * @param pixelrect cursor pixels, maybe null for default cursor
+ * @param hotSpot maybe null for default cursor
+ * @return true if successful, i.e. on-screen surface/window w/ cursor capabilities exists. Otherwise false.
+ */
+ public boolean setCursor(PixelRectangle pixelrect, PointImmutable hotSpot);
+
+ /**
+ * Optional method hiding the cursor in the corresponding on-screen surface/window, if exists.
+ *
+ * @return true if successful, i.e. on-screen surface/window w/ cursor capabilities exists. Otherwise false.
+ */
+ public boolean hideCursor();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
index 395fdc818..7a69b9a40 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
@@ -33,78 +33,95 @@ import jogamp.nativewindow.Debug;
/**
* Provides a mutable {@link NativeSurface}, i.e. {@link MutableSurface}, while allowing an
* {@link UpstreamSurfaceHook} to influence the lifecycle and information.
- *
+ *
* @see UpstreamSurfaceHook
* @see MutableSurface
* @see NativeSurface
*/
-public interface ProxySurface extends MutableSurface {
+public interface ProxySurface extends MutableSurface {
public static final boolean DEBUG = Debug.debug("ProxySurface");
-
- /**
+
+ /**
* Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's surface handle
* @see #addUpstreamOptionBits(int)
+ * @see #clearUpstreamOptionBits(int)
* @see #getUpstreamOptionBits()
- */
+ */
public static final int OPT_PROXY_OWNS_UPSTREAM_SURFACE = 1 << 6;
-
- /**
+
+ /**
* Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's {@link AbstractGraphicsDevice}.
* @see #addUpstreamOptionBits(int)
+ * @see #clearUpstreamOptionBits(int)
* @see #getUpstreamOptionBits()
- */
+ */
public static final int OPT_PROXY_OWNS_UPSTREAM_DEVICE = 1 << 7;
-
- /**
+
+ /**
* Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete.
* @see #addUpstreamOptionBits(int)
+ * @see #clearUpstreamOptionBits(int)
* @see #getUpstreamOptionBits()
- */
+ */
public static final int OPT_UPSTREAM_WINDOW_INVISIBLE = 1 << 8;
/** Allow redefining the AbstractGraphicsConfiguration */
- public void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg);
+ public void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg);
+
+ /**
+ * Returns the optional upstream {@link NativeSurface} if used by implementation, otherwise <code>null</code>.
+ * <p>
+ * The upstream {@link NativeSurface} is retrieved via {@link #getUpstreamSurfaceHook() the UpstreamSurfaceHook},
+ * i.e. {@link UpstreamSurfaceHook#getUpstreamSurface()}.
+ * </p>
+ * <p>
+ * One example is the JOGL EGLWrappedSurface, which might be backed up by a
+ * native platform NativeSurface (X11, WGL, CGL, ..).
+ * </p>
+ */
+ public NativeSurface getUpstreamSurface();
- /** Returns the set {@link UpstreamSurfaceHook}, or null if not set. */
+ /** Returns the {@link UpstreamSurfaceHook} if {@link #setUpstreamSurfaceHook(UpstreamSurfaceHook) set}, otherwise <code>null</code>. */
public UpstreamSurfaceHook getUpstreamSurfaceHook();
-
+
/**
- * Sets the {@link UpstreamSurfaceHook} and returns the previous value.
+ * Overrides the {@link UpstreamSurfaceHook}.
*/
public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook);
-
- /**
- * Enables or disables the {@link UpstreamSurfaceHook} lifecycle functions
+
+ /**
+ * Enables or disables the {@link UpstreamSurfaceHook} lifecycle functions
* {@link UpstreamSurfaceHook#create(ProxySurface)} and {@link UpstreamSurfaceHook#destroy(ProxySurface)}.
* <p>
* Use this for small code blocks where the native resources shall not change,
* i.e. resizing a derived (OpenGL) drawable.
- * </p>
+ * </p>
*/
public void enableUpstreamSurfaceHookLifecycle(boolean enable);
-
- /**
+
+ /**
* {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set.
- */
+ */
public void createNotify();
-
- /**
+
+ /**
* {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all proxy surface/window handles shall be cleared.
- */
+ */
public void destroyNotify();
-
+
public StringBuilder getUpstreamOptionBits(StringBuilder sink);
public int getUpstreamOptionBits();
-
+
/** Returns <code>true</code> if the give bit-mask <code>v</code> is set in this instance upstream-option-bits, otherwise <code>false</code>.*/
public boolean containsUpstreamOptionBits(int v);
-
+
/** Add the given bit-mask to this instance upstream-option-bits using bit-or w/ <code>v</code>.*/
public void addUpstreamOptionBits(int v);
-
+
/** Clear the given bit-mask from this instance upstream-option-bits using bit-and w/ <code>~v</code>*/
public void clearUpstreamOptionBits(int v);
-
+
public StringBuilder toString(StringBuilder sink);
+ @Override
public String toString();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java b/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java
new file mode 100644
index 000000000..ffd5c224c
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java
@@ -0,0 +1,97 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.nativewindow;
+
+/**
+ * Adding mutable surface pixel scale property to implementing class, usually to a {@link NativeSurface} implementation,
+ * see {@link #setSurfaceScale(int[])}.
+ */
+public interface ScalableSurface {
+ /** Setting surface-pixel-scale of {@value}, results in same pixel- and window-units. */
+ public static final int IDENTITY_PIXELSCALE = 1;
+ /** Setting surface-pixel-scale of {@value}, results in maximum platform dependent pixel-scale, i.e. pixel-units >> window-units where available. */
+ public static final int AUTOMAX_PIXELSCALE = 0;
+
+ /**
+ * Request a pixel scale in x- and y-direction for the associated {@link NativeSurface}.
+ * <p>
+ * Default pixel scale request for both directions is {@link #AUTOMAX_PIXELSCALE}.
+ * </p>
+ * <p>
+ * In case platform only supports uniform pixel scale, i.e. one scale for both directions,
+ * either {@link #AUTOMAX_PIXELSCALE} or the maximum requested pixel scale component is used.
+ * </p>
+ * <p>
+ * The <i>requested</i> pixel scale will be validated against platform limits before native scale-setup,
+ * i.e. clipped to {@link #IDENTITY_PIXELSCALE} if not supported or clipped to the platform maximum.
+ * It can be queried via {@link #getRequestedSurfaceScale(int[])}.
+ * </p>
+ * <p>
+ * The actual <i>realized</i> pixel scale values of the {@link NativeSurface}
+ * can be queried via {@link #getCurrentSurfaceScale(int[])} or
+ * computed via <code>surface.{@link NativeSurface#convertToPixelUnits(int[]) convertToPixelUnits}(new int[] { 1, 1 })</code>
+ * </p>
+ * @param pixelScale <i>requested</i> surface pixel scale int[2] values for x- and y-direction.
+ */
+ public void setSurfaceScale(final int[] pixelScale);
+
+ /**
+ * Returns the requested pixel scale of the associated {@link NativeSurface}.
+ *
+ * @param result int[2] storage for the result
+ * @return the passed storage containing the requested pixelScale for chaining
+ */
+ int[] getRequestedSurfaceScale(final int[] result);
+
+ /**
+ * Returns the current pixel scale of the associated {@link NativeSurface}.
+ *
+ * @param result int[2] storage for the result
+ * @return the passed storage containing the current pixelScale for chaining
+ */
+ public int[] getCurrentSurfaceScale(final int[] result);
+
+ /**
+ * Returns the native pixel scale of the associated {@link NativeSurface}
+ * reflecting it's currently bound <i>monitor surface resolution in pixels</i>.
+ * <p>
+ * The native pixel scale maybe used to determine the proper <i>dpi</i>
+ * value of this {@link NativeSurface}:
+ * <pre>
+ * surfacePpMM = monitorPpMM * currentSurfaceScale / nativeSurfaceScale,
+ * with PpMM == pixel per millimeter
+ * </pre>
+ * </p>
+ *
+ * @param result int[2] storage for the result
+ * @return the passed storage containing the native pixelScale for chaining
+ */
+ public int[] getNativeSurfaceScale(final int[] result);
+}
+
diff --git a/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java b/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java
index 0912b5afe..de65a3031 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package javax.media.nativewindow;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
index 30f9660f0..017b996d7 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
@@ -33,12 +33,46 @@ import jogamp.nativewindow.Debug;
/**
* Marker for a singleton global recursive blocking lock implementation,
* optionally locking a native windowing toolkit as well.
- * <br>
- * One use case is the AWT locking on X11, see {@link jogamp.nativewindow.jawt.JAWTToolkitLock}.
+ * <p>
+ * Toolkit locks are created solely via {@link NativeWindowFactory}.
+ * </p>
+ * <p>
+ * One use case is the AWT locking on X11, see {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}.
+ * </p>
*/
public interface ToolkitLock {
+ public static final boolean DEBUG = Debug.debug("ToolkitLock");
public static final boolean TRACE_LOCK = Debug.isPropertyDefined("nativewindow.debug.ToolkitLock.TraceLock", true);
+ /**
+ * Blocking until the lock is acquired by this Thread or a timeout is reached.
+ * <p>
+ * Timeout is implementation specific, if used at all.
+ * </p>
+ *
+ * @throws RuntimeException in case of a timeout
+ */
public void lock();
+
+ /**
+ * Release the lock.
+ *
+ * @throws RuntimeException in case the lock is not acquired by this thread.
+ */
public void unlock();
+
+ /**
+ * @throws RuntimeException if current thread does not hold the lock
+ */
+ public void validateLocked() throws RuntimeException;
+
+ /**
+ * Dispose this instance.
+ * <p>
+ * Shall be called when instance is no more required.
+ * </p>
+ * This allows implementations sharing a lock via resources
+ * to decrease the reference counter.
+ */
+ public void dispose();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java
index 6fe2e5364..572649875 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java
@@ -28,25 +28,39 @@
package javax.media.nativewindow;
-/**
- * Interface allowing upstream caller to pass lifecycle actions and size info
- * to a {@link ProxySurface} instance.
- */
+/**
+ * Interface allowing upstream caller to pass lifecycle actions and size info
+ * to a {@link ProxySurface} instance.
+ */
public interface UpstreamSurfaceHook {
/** called within {@link ProxySurface#createNotify()} within lock, before using surface. */
public void create(ProxySurface s);
/** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */
public void destroy(ProxySurface s);
- /** Returns the width of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */
- public int getWidth(ProxySurface s);
- /** Returns the height of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */
- public int getHeight(ProxySurface s);
-
/**
- * {@link UpstreamSurfaceHook} w/ mutable size, allowing it's {@link ProxySurface} user to resize.
- */
+ * Returns the optional upstream {@link NativeSurface} if used by implementation, otherwise <code>null</code>.
+ * <p>
+ * One example is the JOGL EGLWrappedSurface, which might be backed up by a
+ * native platform NativeSurface (X11, WGL, CGL, ..).
+ * </p>
+ */
+ public NativeSurface getUpstreamSurface();
+
+ /** Returns the width of the upstream surface in pixels, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */
+ public int getSurfaceWidth(ProxySurface s);
+ /** Returns the height of the upstream surface in pixels, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */
+ public int getSurfaceHeight(ProxySurface s);
+
+ /**
+ * {@link UpstreamSurfaceHook} w/ mutable size, allowing it's {@link ProxySurface} user to resize.
+ */
public interface MutableSize extends UpstreamSurfaceHook {
- public void setSize(int width, int height);
+ /**
+ * Resizes the upstream surface.
+ * @param width new width in pixel units
+ * @param height new height in pixel units
+ */
+ public void setSurfaceSize(int width, int height);
}
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/VisualIDHolder.java b/src/nativewindow/classes/javax/media/nativewindow/VisualIDHolder.java
index 4f3d3ff00..e337166d4 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/VisualIDHolder.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/VisualIDHolder.java
@@ -38,7 +38,7 @@ import java.util.Comparator;
* </p>
*/
public interface VisualIDHolder {
-
+
public enum VIDType {
// Generic Values
INTRINSIC(0), NATIVE(1),
@@ -47,19 +47,19 @@ public interface VisualIDHolder {
// X11 Values
X11_XVISUAL(20), X11_FBCONFIG(21),
// Windows Values
- WIN32_PFD(30);
-
+ WIN32_PFD(30);
+
public final int id;
- VIDType(int id){
+ VIDType(final int id){
this.id = id;
}
- }
-
+ }
+
/**
* Returns the native visual ID of the given <code>type</code>
* if supported, or {@link #VID_UNDEFINED} if not supported.
- * <p>
+ * <p>
* Depending on the native windowing system, <code>type</code> is handled as follows:
* <ul>
* <li>X11 throws NativeWindowException on <code>EGL_CONFIG</code>, <code>WIN32_PFD</code>
@@ -76,7 +76,7 @@ public interface VisualIDHolder {
* <li><code>X11_XVISUAL</code>: <i>X11 XVisual ID</i></li>
* <li><code>X11_FBCONFIG</code>: <i>X11 FBConfig ID</i> or <code>VID_UNDEFINED</code></li>
* </ul></li>
- * <li>Windows/GL throws NativeWindowException on <code>EGL_CONFIG</code>, <code>X11_XVISUAL</code>, <code>X11_FBCONFIG</code>
+ * <li>Windows/GL throws NativeWindowException on <code>EGL_CONFIG</code>, <code>X11_XVISUAL</code>, <code>X11_FBCONFIG</code>
* <ul>
* <li><code>INTRINSIC</code>: <i>Win32 PIXELFORMATDESCRIPTOR ID</i></li>
* <li><code>NATIVE</code>: <i>Win32 PIXELFORMATDESCRIPTOR ID</i></li>
@@ -91,36 +91,37 @@ public interface VisualIDHolder {
* </ul>
* </p>
* Note: <code>INTRINSIC</code> and <code>NATIVE</code> are always handled,
- * but may result in {@link #VID_UNDEFINED}. The latter is true if
- * the native value are actually undefined or the corresponding object is not
+ * but may result in {@link #VID_UNDEFINED}. The latter is true if
+ * the native value are actually undefined or the corresponding object is not
* mapped to a native visual object.
- *
+ *
* @throws NativeWindowException if <code>type</code> is neither
* <code>INTRINSIC</code> nor <code>NATIVE</code>
- * and does not match the native implementation.
+ * and does not match the native implementation.
*/
int getVisualID(VIDType type) throws NativeWindowException ;
-
- /**
+
+ /**
* {@link #getVisualID(VIDType)} result indicating an undefined value,
* which could be cause by an unsupported query.
* <p>
* We assume the const value <code>0</code> doesn't reflect a valid native visual ID
* and is interpreted as <i>no value</i> on all platforms.
* This is currently true for Android, X11 and Windows.
- * </p>
+ * </p>
*/
static final int VID_UNDEFINED = 0;
-
+
/** Comparing {@link VIDType#NATIVE} */
public static class VIDComparator implements Comparator<VisualIDHolder> {
- private VIDType type;
-
- public VIDComparator(VIDType type) {
+ private final VIDType type;
+
+ public VIDComparator(final VIDType type) {
this.type = type;
}
-
- public int compare(VisualIDHolder vid1, VisualIDHolder vid2) {
+
+ @Override
+ public int compare(final VisualIDHolder vid1, final VisualIDHolder vid2) {
final int id1 = vid1.getVisualID(type);
final int id2 = vid2.getVisualID(type);
@@ -131,5 +132,5 @@ public interface VisualIDHolder {
}
return 0;
}
- }
+ }
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
index 884c916e4..8570b78da 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
@@ -37,13 +37,17 @@ package javax.media.nativewindow;
* this protocol default behavior {@link WindowClosingMode#DISPOSE_ON_CLOSE DISPOSE_ON_CLOSE} shall be used.</p>
*/
public interface WindowClosingProtocol {
+
+ /**
+ * Window closing mode if triggered by toolkit close operation.
+ */
public enum WindowClosingMode {
/**
* Do nothing on native window close operation.<br>
* This is the default behavior within an AWT environment.
*/
DO_NOTHING_ON_CLOSE,
-
+
/**
* Dispose resources on native window close operation.<br>
* This is the default behavior in case no underlying toolkit defines otherwise.
diff --git a/src/nativewindow/classes/javax/media/nativewindow/package.html b/src/nativewindow/classes/javax/media/nativewindow/package.html
index 14730a548..3fe42bab0 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/package.html
+++ b/src/nativewindow/classes/javax/media/nativewindow/package.html
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
- <title>NativeWindow Protocol Draft Public Review Specification</title>
+ <title>NativeWindow Specification Overview</title>
</head>
<body>
@@ -10,7 +10,7 @@
<h3>Preface</h3>
This specification, an optional set of packages, describing a <i>protocol</i> for a
<i>native windowing interface</i> binding to Java(TM).<br>
- Currently specified <i>native windowing systems</i> are:<br><br>
+ Currently specified <i>native windowing systems</i> are:
<ul>
<li> EGL/OpenKODE Windowing System</li>
<li> X11 Windowing System</li>
@@ -20,95 +20,79 @@
</ul>
<br>
However, any other native windowing system may be added to the implementation,
- using a generic string identifier and an optional specialisation of:<br><br>
+ using a generic string identifier and an optional specialisation of:
<ul>
- <li>{@link javax.media.nativewindow.AbstractGraphicsDevice AbstractGraphicsDevice},<br>
- <br>
- Shall return the new string identifier with {@link javax.media.nativewindow.AbstractGraphicsDevice#getType() getType()}</li>
+ <li>{@link javax.media.nativewindow.AbstractGraphicsDevice AbstractGraphicsDevice},
+ <p>Shall return the new string identifier with {@link javax.media.nativewindow.AbstractGraphicsDevice#getType() getType()}</p></li>
<li>{@link javax.media.nativewindow.AbstractGraphicsScreen AbstractGraphicsScreen}</li>
<li>{@link javax.media.nativewindow.AbstractGraphicsConfiguration AbstractGraphicsConfiguration}</li>
</ul>
- <br>
- The implementor has to provide the following:<br><br>
+ <p>The implementor has to provide the following:</p>
<ul>
- <li> The specialisation of the abstract class {@link javax.media.nativewindow.NativeWindowFactory NativeWindowFactory}<br>
- <br>
- shall be registered with {@link javax.media.nativewindow.NativeWindowFactory#registerFactory NativeWindowFactory.registerFactory(..)}.</li>
+ <li> The specialisation of the abstract class {@link javax.media.nativewindow.NativeWindowFactory NativeWindowFactory}
+ <p>shall be registered with {@link javax.media.nativewindow.NativeWindowFactory#registerFactory NativeWindowFactory.registerFactory(..)}.</p></li>
- <li> The specialisation of the abstract class {@link javax.media.nativewindow.GraphicsConfigurationFactory GraphicsConfigurationFactory}<br>
- <br>
- shall be registered with {@link javax.media.nativewindow.GraphicsConfigurationFactory#registerFactory GraphicsConfigurationFactory.registerFactory(..)}.</li>
- </ul><br>
- This protocol <i>does not</i> describe how to <i>create</i> native windows, but how to <i>bind</i> a native surface to an implementation of
- and window to an implementation of {@link javax.media.nativewindow.NativeSurface NativeSurface}.<br>
- {@link javax.media.nativewindow.NativeWindow NativeWindow} specializes the NativeSurface.<br>
- However, an implementation of this protocol (e.g. {@link com.jogamp.newt}) may support the creation.<br>
+ <li> The specialisation of the abstract class {@link javax.media.nativewindow.GraphicsConfigurationFactory GraphicsConfigurationFactory}
+ <p>shall be registered with {@link javax.media.nativewindow.GraphicsConfigurationFactory#registerFactory GraphicsConfigurationFactory.registerFactory(..)}.</p></li>
+ </ul>
+ <p>This protocol <i>does not</i> describe how to <i>create</i> native windows, but how to <i>bind</i> a native surface to an implementation of
+ and window to an implementation of {@link javax.media.nativewindow.NativeSurface NativeSurface}.</p>
+ <p>{@link javax.media.nativewindow.NativeWindow NativeWindow} specializes the NativeSurface.</p>
+ <p>However, an implementation of this protocol (e.g. {@link com.jogamp.newt}) may support the creation.</p>
<h3>Dependencies</h3>
This binding has dependencies to the following:
<ul>
- <li> Either of the following Java implementations:<br/>
+ <li> Either of the following Java implementations:
<ul>
- <li> <a href="http://java.sun.com/j2se/1.5.0/docs/api/">Java SE 1.5 or later</a> </li>
- <li> A mobile JavaVM with language 1.5 support, ie:
+ <li> <a href="http://docs.oracle.com/javase/6/docs/api/">Java SE 1.6 or later</a> </li>
+ <li> A mobile JavaVM with language 1.6 support, ie:
<ul>
- <li> <a href="http://developer.android.com/reference/packages.html">Dalvik API Level 7</a> </li>
+ <li> <a href="http://developer.android.com/reference/packages.html">Android API Level 9 (Version 2.3)</a> </li>
<li> <a href="http://jamvm.sourceforge.net/">JamVM</a> </li>
</ul>
with
<ul>
- <li> <a href="http://java.sun.com/products/foundation/">Foundation Profile 1.1.2 (JSR 219)</a> </li>
- <li> <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/package-summary.html"> Java 1.4 <i>java.nio</i> implementation</a> </li>
+ <li> <a href="http://docs.oracle.com/javase/1.4.2/docs/api/java/nio/package-summary.html"> Java 1.4 <i>java.nio</i> implementation</a> </li>
</ul></li>
</ul></li>
</ul>
<br>
<h3>Package Structure</h3>
- The packages defined by this specification include:<br/><br/>
+ The packages defined by this specification include:
<ul>
- <li>The <b>javax.media.nativewindow</b> package<br>
- <br>
- This package contains Java bindings for a native windowing system.<br>
- Subsequent packages contain marker type classes, containing native characteristics of the windowing system.
-
- <ul>
- <li>The <b>javax.media.nativewindow.awt</b> package<br>
- <br>
- This sub package contains classes to cover the native characteristics of the AWT windowing system.</li>
+ <li>The <b>javax.media.nativewindow</b> package
+ <p>This package contains Java bindings for a native windowing system.</p>
+ <p>Subsequent packages contain marker type classes, containing native characteristics of the windowing system.</p>
+ <ul>
+ <li>The <b>javax.media.nativewindow.awt</b> package
+ <p>This sub package contains classes to cover the native characteristics of the AWT windowing system.</p></li>
- <li>The <b>javax.media.nativewindow.x11</b> package<br>
- <br>
- This sub package contains classes to cover the native characteristics of the X11 windowing system.</li>
+ <li>The <b>javax.media.nativewindow.x11</b> package
+ <p>This sub package contains classes to cover the native characteristics of the X11 windowing system.</p></li>
- <li>The <b>javax.media.nativewindow.windows</b> package<br>
- <br>
- This sub package contains classes to cover the native characteristics of the Windows windowing system.</li>
+ <li>The <b>javax.media.nativewindow.windows</b> package
+ <p>This sub package contains classes to cover the native characteristics of the Windows windowing system.</p></li>
- <li>The <b>javax.media.nativewindow.macosx</b> package<br>
- <br>
- This sub package contains classes to cover the native characteristics of the MacOSX windowing system.</li>
+ <li>The <b>javax.media.nativewindow.macosx</b> package
+ <p>This sub package contains classes to cover the native characteristics of the MacOSX windowing system.</p></li>
- <li>The <b>javax.media.nativewindow.egl</b> package<br>
- <br>
- This sub package contains classes to cover the native characteristics of the EGL/OpenKODE windowing system.</li>
+ <li>The <b>javax.media.nativewindow.egl</b> package
+ <p>This sub package contains classes to cover the native characteristics of the EGL/OpenKODE windowing system.</p></li>
</ul></li>
</ul>
<h3>Factory Model</h3>
-Running on a platform with a supported windowing system, the factory model shall be used
-to instantiate a native window, see {@link javax.media.nativewindow.NativeWindowFactory NativeWindowFactory}.<br>
-The implementor has to specialize
-All supported
-Regardless of the knowledge of the underly
-<br>
+<p>Running on a platform with a supported windowing system, the factory model shall be used
+to instantiate a native window, see {@link javax.media.nativewindow.NativeWindowFactory NativeWindowFactory}.</p>
-<h3>Revision History<br>
- </h3>
+<h3>Revision History</h3>
<ul>
<li> Early Draft Review, June 2009</li>
<li> 2.0.0 Maintenance Release, February 2011</li>
+<li> 2.0.2 Major Release, July 18th 2013</li>
</ul>
<br>
<br>
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java b/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java
index 0a5a94565..4c9672c26 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java
@@ -4,14 +4,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -21,12 +21,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package javax.media.nativewindow.util;
public class Dimension implements Cloneable, DimensionImmutable {
@@ -37,7 +37,11 @@ public class Dimension implements Cloneable, DimensionImmutable {
this(0, 0);
}
- public Dimension(int width, int height) {
+ public Dimension(final int[] size) {
+ this(size[0], size[1]);
+ }
+
+ public Dimension(final int width, final int height) {
if(width<0 || height<0) {
throw new IllegalArgumentException("width and height must be within: ["+0+".."+Integer.MAX_VALUE+"]");
}
@@ -45,55 +49,79 @@ public class Dimension implements Cloneable, DimensionImmutable {
this.height=height;
}
+ @Override
public Object cloneMutable() {
return clone();
}
-
+
+ @Override
public Object clone() {
try {
return super.clone();
- } catch (CloneNotSupportedException ex) {
+ } catch (final CloneNotSupportedException ex) {
throw new InternalError();
}
}
- public int getWidth() { return width; }
- public int getHeight() { return height; }
+ @Override
+ public final int getWidth() { return width; }
+ @Override
+ public final int getHeight() { return height; }
- public void setWidth(int width) {
+ public final void set(final int width, final int height) {
+ this.width = width;
+ this.height = height;
+ }
+ public final void setWidth(final int width) {
this.width = width;
}
- public void setHeight(int height) {
+ public final void setHeight(final int height) {
this.height = height;
}
- public Dimension scale(int s) {
+ public final Dimension scale(final int s) {
width *= s;
height *= s;
return this;
}
- public Dimension add(Dimension pd) {
+ public final Dimension add(final Dimension pd) {
width += pd.width ;
height += pd.height ;
return this;
}
+ @Override
public String toString() {
- return new String(width+" x "+height);
+ return width + " x " + height;
+ }
+
+ @Override
+ public int compareTo(final DimensionImmutable d) {
+ final int tsq = width*height;
+ final int xsq = d.getWidth()*d.getHeight();
+
+ if(tsq > xsq) {
+ return 1;
+ } else if(tsq < xsq) {
+ return -1;
+ }
+ return 0;
}
- public boolean equals(Object obj) {
+ @Override
+ public boolean equals(final Object obj) {
if(this == obj) { return true; }
if (obj instanceof Dimension) {
- Dimension p = (Dimension)obj;
- return height == p.height &&
+ final Dimension p = (Dimension)obj;
+ return height == p.height &&
width == p.width ;
}
return false;
}
+ @Override
public int hashCode() {
// 31 * x == (x << 5) - x
- int hash = 31 + width;
+ final int hash = 31 + width;
return ((hash << 5) - hash) + height;
}
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/DimensionImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/util/DimensionImmutable.java
index d14e94c10..e6cacf4ff 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/DimensionImmutable.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/DimensionImmutable.java
@@ -37,21 +37,32 @@ import com.jogamp.common.type.WriteCloneable;
* <li><code>height</code></li>
* </ul>
*/
-public interface DimensionImmutable extends WriteCloneable {
+public interface DimensionImmutable extends WriteCloneable, Comparable<DimensionImmutable> {
int getHeight();
int getWidth();
/**
+ * <p>
+ * Compares square of size.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final DimensionImmutable d);
+
+ /**
* Checks whether two dimensions objects are equal. Two instances
* of <code>DimensionReadOnly</code> are equal if two components
* <code>height</code> and <code>width</code> are equal.
* @return <code>true</code> if the two dimensions are equal;
* otherwise <code>false</code>.
*/
+ @Override
boolean equals(Object obj);
+ @Override
int hashCode();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java b/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java
index 199ec27cb..5ec4c758f 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,76 +20,117 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package javax.media.nativewindow.util;
+/**
+ * Mutable insets representing rectangular window decoration insets on all four edges
+ * in window units.
+ */
public class Insets implements Cloneable, InsetsImmutable {
static final InsetsImmutable zeroInsets = new Insets();
public static final InsetsImmutable getZero() { return zeroInsets; }
-
- int l, r, t, b;
+
+ private int l, r, t, b;
public Insets() {
this(0, 0, 0, 0);
}
- public Insets(int left, int right, int top, int bottom) {
+ public Insets(final int left, final int right, final int top, final int bottom) {
this.l=left;
this.r=right;
this.t=top;
this.b=bottom;
}
-
+
+ @Override
public Object cloneMutable() {
return clone();
}
-
+
+ @Override
protected Object clone() {
try {
return super.clone();
- } catch (CloneNotSupportedException ex) {
+ } catch (final CloneNotSupportedException ex) {
throw new InternalError();
}
}
+ @Override
public final int getLeftWidth() { return l; }
+ @Override
public final int getRightWidth() { return r; }
+ @Override
public final int getTotalWidth() { return l + r; }
+ @Override
public final int getTopHeight() { return t; }
+ @Override
public final int getBottomHeight() { return b; }
+ @Override
public final int getTotalHeight() { return t + b; }
- public void setLeftWidth(int left) { l = left; }
- public void setRightWidth(int right) { r = right; }
- public void setTopHeight(int top) { t = top; }
- public void setBottomHeight(int bottom) { b = bottom; }
-
- public boolean equals(Object obj) {
+ /**
+ * Set the inset values of this instance in window units.
+ * @param left left inset width in window units.
+ * @param right right inset width in window units.
+ * @param top top inset width in window units.
+ * @param bottom bottom inset width in window units.
+ */
+ public final void set(final int left, final int right, final int top, final int bottom) {
+ l = left; r = right; t = top; b = bottom;
+ }
+ /**
+ * Set the left inset value of this instance in window units.
+ * @param left left inset width in window units.
+ */
+ public final void setLeftWidth(final int left) { l = left; }
+ /**
+ * Set the right inset value of this instance in window units.
+ * @param right right inset width in window units.
+ */
+ public final void setRightWidth(final int right) { r = right; }
+ /**
+ * Set the top inset value of this instance in window units.
+ * @param top top inset width in window units.
+ */
+ public final void setTopHeight(final int top) { t = top; }
+ /**
+ * Set the bottom inset value of this instance in window units.
+ * @param bottom bottom inset width in window units.
+ */
+ public final void setBottomHeight(final int bottom) { b = bottom; }
+
+ @Override
+ public boolean equals(final Object obj) {
if(this == obj) { return true; }
if (obj instanceof Insets) {
- Insets insets = (Insets)obj;
+ final Insets insets = (Insets)obj;
return (r == insets.r) && (l == insets.l) &&
(b == insets.b) && (t == insets.t);
}
return false;
}
+ @Override
public int hashCode() {
- int sum1 = l + b;
- int sum2 = t + r;
- int val1 = sum1 * (sum1 + 1)/2 + l;
- int val2 = sum2 * (sum2 + 1)/2 + r;
- int sum3 = val1 + val2;
+ final int sum1 = l + b;
+ final int sum2 = t + r;
+ final int val1 = sum1 * (sum1 + 1)/2 + l;
+ final int val2 = sum2 * (sum2 + 1)/2 + r;
+ final int sum3 = val1 + val2;
return sum3 * (sum3 + 1)/2 + val2;
}
+ @Override
public String toString() {
- return new String("[ l "+l+", r "+r+" - t "+t+", b "+b+" - "+getTotalWidth()+"x"+getTotalHeight()+"]");
+ return "[ l "+l+", r "+r+" - t "+t+", b "+b+" - "+getTotalWidth()+"x"+getTotalHeight()+"]";
}
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/InsetsImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/util/InsetsImmutable.java
index 075641ede..0f8ba0158 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/InsetsImmutable.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/InsetsImmutable.java
@@ -30,25 +30,28 @@ package javax.media.nativewindow.util;
import com.jogamp.common.type.WriteCloneable;
-/** Immutable Rectangle interface */
+/**
+ * Immutable insets representing rectangular window decoration insets on all four edges
+ * in window units.
+ */
public interface InsetsImmutable extends WriteCloneable {
- /** @return left inset width */
+ /** @return left inset width in window units. */
int getLeftWidth();
- /** @return right inset width */
+ /** @return right inset width in window units. */
int getRightWidth();
- /** @return total width, ie. <code>left_width + right_width</code> */
+ /** @return total width in window units, ie. <code>left_width + right_width</code> */
int getTotalWidth();
-
- /** @return top inset height */
+
+ /** @return top inset height in window units. */
int getTopHeight();
- /** @return bottom inset height */
+ /** @return bottom inset height in window units. */
int getBottomHeight();
-
- /** @return total height, ie. <code>top_height + bottom_height</code> */
+
+ /** @return total height in window units, ie. <code>top_height + bottom_height</code> */
int getTotalHeight();
/**
@@ -59,8 +62,10 @@ public interface InsetsImmutable extends WriteCloneable {
* @return <code>true</code> if the two Insets are equal;
* otherwise <code>false</code>.
*/
+ @Override
boolean equals(Object obj);
+ @Override
int hashCode();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java
new file mode 100644
index 000000000..e5901f584
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java
@@ -0,0 +1,197 @@
+/**
+ * Copyright (c) 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.nativewindow.util;
+
+/**
+ * Basic pixel formats
+ * <p>
+ * Notation follows OpenGL notation, i.e.
+ * name consist of all it's component names
+ * followed by their bit size.
+ * </p>
+ * <p>
+ * Order of component names is from lowest-bit to highest-bit.
+ * </p>
+ * <p>
+ * In case component-size is 1 byte (e.g. OpenGL data-type GL_UNSIGNED_BYTE),
+ * component names are ordered from lowest-byte to highest-byte.
+ * Note that OpenGL applies special interpretation if
+ * data-type is e.g. GL_UNSIGNED_8_8_8_8_REV or GL_UNSIGNED_8_8_8_8_REV.
+ * </p>
+ * <p>
+ * PixelFormat can be converted to OpenGL GLPixelAttributes
+ * via
+ * <pre>
+ * GLPixelAttributes glpa = GLPixelAttributes.convert(PixelFormat pixFmt, GLProfile glp);
+ * </pre>
+ * </p>
+ * <p>
+ * See OpenGL Specification 4.3 - February 14, 2013, Core Profile,
+ * Section 8.4.4 Transfer of Pixel Rectangles, p. 161-174.
+ * </ul>
+ *
+ * </p>
+ */
+public enum PixelFormat {
+ /**
+ * Pixel size is 1 bytes (8 bits) with one component of size 1 byte (8 bits).
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_ALPHA (< GL3), GL_RED (>= GL3), data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: <i>none</i></li>
+ * </ul>
+ * </p>
+ */
+ LUMINANCE(1, 8),
+
+ /**
+ * Pixel size is 3 bytes (24 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: R, G, B</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_RGB, data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: <i>None</i></li>
+ * </ul>
+ * </p>
+ */
+ RGB888(3, 24),
+
+ /**
+ * Pixel size is 3 bytes (24 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: B, G, R</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_BGR (>= GL2), data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_3BYTE_BGR TYPE_3BYTE_BGR}</li>
+ * </ul>
+ * </p>
+ */
+ BGR888(3, 24),
+
+ /**
+ * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: R, G, B, A</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: <i>None</i></li>
+ * <li>PointerIcon: OSX (NSBitmapImageRep)</li>
+ * <li>Window Icon: OSX (NSBitmapImageRep)</li>
+ * <li>PNGJ: Scanlines</li>
+ * </ul>
+ * </p>
+ */
+ RGBA8888(4, 32),
+
+ /**
+ * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: A, B, G, R</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_8_8_8_8</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_4BYTE_ABGR TYPE_4BYTE_ABGR}</li>
+ * </ul>
+ * </p>
+ */
+ ABGR8888(4, 32),
+
+ /**
+ * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: A, R, G, B</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_BGRA, data-type GL_UNSIGNED_INT_8_8_8_8</li>
+ * <li>AWT: <i>None</i></li>
+ * </ul>
+ * </p>
+ */
+ ARGB8888(4, 32),
+
+ /**
+ * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: B, G, R, A</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_BGRA, data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_INT_ARGB TYPE_INT_ARGB}</li>
+ * <li>PointerIcon: X11 (XCURSOR), Win32, AWT</li>
+ * <li>Window Icon: X11, Win32</li>
+ * </ul>
+ * </p>
+ */
+ BGRA8888(4, 32);
+
+ /** Number of components per pixel, e.g. 4 for RGBA. */
+ public final int componentCount;
+ /** Number of bits per pixel, e.g. 32 for RGBA. */
+ public final int bitsPerPixel;
+ /** Number of bytes per pixel, e.g. 4 for RGBA. */
+ public final int bytesPerPixel() { return (7+bitsPerPixel)/8; }
+
+ private PixelFormat(final int componentCount, final int bpp) {
+ this.componentCount = componentCount;
+ this.bitsPerPixel = bpp;
+ }
+}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
new file mode 100644
index 000000000..21bfa8a54
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
@@ -0,0 +1,373 @@
+/**
+ * Copyright (c) 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package javax.media.nativewindow.util;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import com.jogamp.common.nio.Buffers;
+
+/**
+ * Pixel Rectangle Utilities.
+ * <p>
+ * All conversion methods are endian independent.
+ * </p>
+ */
+public class PixelFormatUtil {
+ public static interface PixelSink {
+ /** Return the sink's destination pixelformat. */
+ PixelFormat getPixelformat();
+
+ /**
+ * Returns stride in byte-size, i.e. byte count from one line to the next.
+ * <p>
+ * Must be >= {@link #getPixelformat()}.{@link PixelFormat#bytesPerPixel() bytesPerPixel()} * {@link #getSize()}.{@link DimensionImmutable#getWidth() getWidth()}.
+ * </p>
+ */
+ int getStride();
+
+ /**
+ * Returns <code>true</code> if the sink's memory is laid out in
+ * OpenGL's coordinate system, <i>origin at bottom left</i>.
+ * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
+ */
+ boolean isGLOriented();
+ }
+ /**
+ * Pixel sink for up-to 32bit.
+ */
+ public static interface PixelSink32 extends PixelSink {
+ /**
+ * Will be invoked over all rows top-to down
+ * and all columns left-to-right.
+ * <p>
+ * Shall consider dest pixelformat and only store as much components
+ * as defined, up to 32bit.
+ * </p>
+ * <p>
+ * Implementation may better write single bytes from low-to-high bits,
+ * e.g. {@link ByteOrder#LITTLE_ENDIAN} order.
+ * Otherwise a possible endian conversion must be taken into consideration.
+ * </p>
+ * @param x
+ * @param y
+ * @param pixel
+ */
+ void store(int x, int y, int pixel);
+ }
+
+ /**
+ * Returns the {@link PixelFormat} with reversed components of <code>fmt</code>.
+ * If no reversed {@link PixelFormat} is available, returns <code>fmt</code>.
+ */
+ public static PixelFormat getReversed(final PixelFormat fmt) {
+ switch(fmt) {
+ case LUMINANCE:
+ return PixelFormat.LUMINANCE;
+ case RGB888:
+ return PixelFormat.BGR888;
+ case BGR888:
+ return PixelFormat.RGB888;
+ case RGBA8888:
+ return PixelFormat.ABGR8888;
+ case ABGR8888:
+ return PixelFormat.RGBA8888;
+ case ARGB8888:
+ return PixelFormat.BGRA8888;
+ case BGRA8888:
+ return PixelFormat.ABGR8888;
+ default:
+ throw new InternalError("Unhandled format "+fmt);
+ }
+ }
+
+ public static int getValue32(final PixelFormat src_fmt, final ByteBuffer src, int srcOff) {
+ switch(src_fmt) {
+ case LUMINANCE: {
+ final byte c1 = src.get(srcOff++);
+ return ( 0xff ) << 24 | ( 0xff & c1 ) << 16 | ( 0xff & c1 ) << 8 | ( 0xff & c1 );
+ }
+ case RGB888:
+ case BGR888: {
+ final byte c1 = src.get(srcOff++);
+ final byte c2 = src.get(srcOff++);
+ final byte c3 = src.get(srcOff++);
+ return ( 0xff ) << 24 | ( 0xff & c3 ) << 16 | ( 0xff & c2 ) << 8 | ( 0xff & c1 );
+ }
+ case RGBA8888:
+ case ABGR8888:
+ case ARGB8888:
+ case BGRA8888: {
+ final byte c1 = src.get(srcOff++);
+ final byte c2 = src.get(srcOff++);
+ final byte c3 = src.get(srcOff++);
+ final byte c4 = src.get(srcOff++);
+ return ( 0xff & c4 ) << 24 | ( 0xff & c3 ) << 16 | ( 0xff & c2 ) << 8 | ( 0xff & c1 );
+ }
+ default:
+ throw new InternalError("Unhandled format "+src_fmt);
+ }
+ }
+
+ public static int convertToInt32(final PixelFormat dest_fmt, final byte r, final byte g, final byte b, final byte a) {
+ switch(dest_fmt) {
+ case LUMINANCE: {
+ final byte l = ( byte) ( ( ( ( 0xff & r ) + ( 0xff & g ) + ( 0xff & b ) ) / 3 ) );
+ return ( 0xff ) << 24 | ( 0xff & l ) << 16 | ( 0xff & l ) << 8 | ( 0xff & l );
+ }
+ case RGB888:
+ return ( 0xff ) << 24 | ( 0xff & b ) << 16 | ( 0xff & g ) << 8 | ( 0xff & r );
+ case BGR888:
+ return ( 0xff ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b );
+ case RGBA8888:
+ return ( 0xff & a ) << 24 | ( 0xff & b ) << 16 | ( 0xff & g ) << 8 | ( 0xff & r );
+ case ABGR8888:
+ return ( 0xff & r ) << 24 | ( 0xff & g ) << 16 | ( 0xff & b ) << 8 | ( 0xff & a );
+ case ARGB8888:
+ return ( 0xff & b ) << 24 | ( 0xff & g ) << 16 | ( 0xff & r ) << 8 | ( 0xff & a );
+ case BGRA8888:
+ return ( 0xff & a ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b );
+ default:
+ throw new InternalError("Unhandled format "+dest_fmt);
+ }
+ }
+
+ public static int convertToInt32(final PixelFormat dest_fmt, final PixelFormat src_fmt, final ByteBuffer src, int srcOff) {
+ final byte r, g, b, a;
+ switch(src_fmt) {
+ case LUMINANCE:
+ r = src.get(srcOff++); // R
+ g = r; // G
+ b = r; // B
+ a = (byte) 0xff; // A
+ break;
+ case RGB888:
+ r = src.get(srcOff++); // R
+ g = src.get(srcOff++); // G
+ b = src.get(srcOff++); // B
+ a = (byte) 0xff; // A
+ break;
+ case BGR888:
+ b = src.get(srcOff++); // B
+ g = src.get(srcOff++); // G
+ r = src.get(srcOff++); // R
+ a = (byte) 0xff; // A
+ break;
+ case RGBA8888:
+ r = src.get(srcOff++); // R
+ g = src.get(srcOff++); // G
+ b = src.get(srcOff++); // B
+ a = src.get(srcOff++); // A
+ break;
+ case ABGR8888:
+ a = src.get(srcOff++); // A
+ b = src.get(srcOff++); // B
+ g = src.get(srcOff++); // G
+ r = src.get(srcOff++); // R
+ break;
+ case ARGB8888:
+ a = src.get(srcOff++); // A
+ r = src.get(srcOff++); // R
+ g = src.get(srcOff++); // G
+ b = src.get(srcOff++); // B
+ break;
+ case BGRA8888:
+ b = src.get(srcOff++); // B
+ g = src.get(srcOff++); // G
+ r = src.get(srcOff++); // R
+ a = src.get(srcOff++); // A
+ break;
+ default:
+ throw new InternalError("Unhandled format "+src_fmt);
+ }
+ return convertToInt32(dest_fmt, r, g, b, a);
+ }
+
+ public static int convertToInt32(final PixelFormat dest_fmt, final PixelFormat src_fmt, final int src_pixel) {
+ final byte r, g, b, a;
+ switch(src_fmt) {
+ case LUMINANCE:
+ r = (byte) ( src_pixel ); // R
+ g = r; // G
+ b = r; // B
+ a = (byte) 0xff; // A
+ break;
+ case RGB888:
+ r = (byte) ( src_pixel ); // R
+ g = (byte) ( src_pixel >>> 8 ); // G
+ b = (byte) ( src_pixel >>> 16 ); // B
+ a = (byte) 0xff; // A
+ break;
+ case BGR888:
+ b = (byte) ( src_pixel ); // B
+ g = (byte) ( src_pixel >>> 8 ); // G
+ r = (byte) ( src_pixel >>> 16 ); // R
+ a = (byte) 0xff; // A
+ break;
+ case RGBA8888:
+ r = (byte) ( src_pixel ); // R
+ g = (byte) ( src_pixel >>> 8 ); // G
+ b = (byte) ( src_pixel >>> 16 ); // B
+ a = (byte) ( src_pixel >>> 24 ); // A
+ break;
+ case ABGR8888:
+ a = (byte) ( src_pixel ); // A
+ b = (byte) ( src_pixel >>> 8 ); // B
+ g = (byte) ( src_pixel >>> 16 ); // G
+ r = (byte) ( src_pixel >>> 24 ); // R
+ break;
+ case ARGB8888:
+ a = (byte) ( src_pixel ); // A
+ r = (byte) ( src_pixel >>> 8 ); // R
+ g = (byte) ( src_pixel >>> 16 ); // G
+ b = (byte) ( src_pixel >>> 24 ); // B
+ break;
+ case BGRA8888:
+ b = (byte) ( src_pixel ); // B
+ g = (byte) ( src_pixel >>> 8 ); // G
+ r = (byte) ( src_pixel >>> 16 ); // R
+ a = (byte) ( src_pixel >>> 24 ); // A
+ break;
+ default:
+ throw new InternalError("Unhandled format "+src_fmt);
+ }
+ return convertToInt32(dest_fmt, r, g, b, a);
+ }
+
+ public static PixelRectangle convert32(final PixelRectangle src,
+ final PixelFormat destFmt, final int ddestStride, final boolean isGLOriented,
+ final boolean destIsDirect) {
+ final int width = src.getSize().getWidth();
+ final int height = src.getSize().getHeight();
+ final int bpp = destFmt.bytesPerPixel();
+ final int destStride;
+ if( 0 != ddestStride ) {
+ destStride = ddestStride;
+ if( destStride < bpp * width ) {
+ throw new IllegalArgumentException("Invalid stride "+destStride+", must be greater than bytesPerPixel "+bpp+" * width "+width);
+ }
+ } else {
+ destStride = bpp * width;
+ }
+ final int capacity = destStride*height;
+ final ByteBuffer bb = destIsDirect ? Buffers.newDirectByteBuffer(capacity) : ByteBuffer.allocate(capacity).order(src.getPixels().order());
+
+ // System.err.println("XXX: SOURCE "+src);
+ // System.err.println("XXX: DEST fmt "+destFmt+", stride "+destStride+" ("+ddestStride+"), isGL "+isGLOriented+", "+width+"x"+height+", capacity "+capacity+", "+bb);
+
+ final PixelFormatUtil.PixelSink32 imgSink = new PixelFormatUtil.PixelSink32() {
+ public void store(final int x, final int y, final int pixel) {
+ int o = destStride*y+x*bpp;
+ bb.put(o++, (byte) ( pixel )); // 1
+ if( 3 <= bpp ) {
+ bb.put(o++, (byte) ( pixel >>> 8 )); // 2
+ bb.put(o++, (byte) ( pixel >>> 16 )); // 3
+ if( 4 <= bpp ) {
+ bb.put(o++, (byte) ( pixel >>> 24 )); // 4
+ }
+ }
+ }
+ @Override
+ public final PixelFormat getPixelformat() {
+ return destFmt;
+ }
+ @Override
+ public final int getStride() {
+ return destStride;
+ }
+ @Override
+ public final boolean isGLOriented() {
+ return isGLOriented;
+ }
+ };
+ convert32(imgSink, src);
+ return new PixelRectangle.GenericPixelRect(destFmt, src.getSize(), destStride, isGLOriented, bb);
+ }
+
+ public static void convert32(final PixelSink32 destInt32, final PixelRectangle src) {
+ convert32(destInt32,
+ src.getPixels(), src.getPixelformat(),
+ src.isGLOriented(),
+ src.getSize().getWidth(), src.getSize().getHeight(),
+ src.getStride());
+ }
+
+ /**
+ *
+ * @param dest32 32bit pixel sink
+ * @param src_bb
+ * @param src_fmt
+ * @param src_glOriented if true, the source memory is laid out in OpenGL's coordinate system, <i>origin at bottom left</i>,
+ * otherwise <i>origin at top left</i>.
+ * @param width
+ * @param height
+ * @param strideInBytes stride in byte-size, i.e. byte count from one line to the next.
+ * If zero, stride is set to <code>width * bytes-per-pixel</code>.
+ * If not zero, value must be >= <code>width * bytes-per-pixel</code>.
+ * @param stride_bytes stride in byte-size, i.e. byte count from one line to the next.
+ * Must be >= {@link PixelFormat#bytesPerPixel() src_fmt.bytesPerPixel()} * width.
+ * @throws IllegalArgumentException if <code>strideInBytes</code> is invalid
+ */
+ public static void convert32(final PixelSink32 dest32,
+ final ByteBuffer src_bb, final PixelFormat src_fmt, final boolean src_glOriented, final int width, final int height, int stride_bytes) {
+ final int src_bpp = src_fmt.bytesPerPixel();
+ if( 0 != stride_bytes ) {
+ if( stride_bytes < src_bpp * width ) {
+ throw new IllegalArgumentException("Invalid stride "+stride_bytes+", must be greater than bytesPerPixel "+src_bpp+" * width "+width);
+ }
+ } else {
+ stride_bytes = src_bpp * width;
+ }
+ final PixelFormat dest_fmt = dest32.getPixelformat();
+ final boolean vert_flip = src_glOriented != dest32.isGLOriented();
+ final boolean fast_copy = src_fmt == dest_fmt && dest_fmt.bytesPerPixel() == 4 ;
+ // System.err.println("XXX: SRC fmt "+src_fmt+", stride "+stride_bytes+", isGL "+src_glOriented+", "+width+"x"+height);
+ // System.err.println("XXX: DST fmt "+dest_fmt+", fast_copy "+fast_copy);
+
+ if( fast_copy ) {
+ // Fast copy
+ for(int y=0; y<height; y++) {
+ int o = vert_flip ? ( height - 1 - y ) * stride_bytes : y * stride_bytes;
+ for(int x=0; x<width; x++) {
+ dest32.store(x, y, getValue32(src_fmt, src_bb, o));
+ o += src_bpp;
+ }
+ }
+ } else {
+ // Conversion
+ for(int y=0; y<height; y++) {
+ int o = vert_flip ? ( height - 1 - y ) * stride_bytes : y * stride_bytes;
+ for(int x=0; x<width; x++) {
+ dest32.store( x, y, convertToInt32( dest_fmt, src_fmt, src_bb, o));
+ o += src_bpp;
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java
new file mode 100644
index 000000000..96c1f7b33
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java
@@ -0,0 +1,194 @@
+/**
+ * Copyright (c) 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package javax.media.nativewindow.util;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Pixel Rectangle identified by it's {@link #hashCode()}.
+ * <p>
+ * The {@link #getPixels()} are assumed to be immutable.
+ * </p>
+ */
+public interface PixelRectangle {
+ /**
+ * <p>
+ * Computes a hash code over:
+ * <ul>
+ * <li>pixelformat</li>
+ * <li>size</li>
+ * <li>stride</li>
+ * <li>isGLOriented</li>
+ * <li>pixels</li>
+ * </ul>
+ * </p>
+ * <p>
+ * The hashCode shall be computed only once with first call
+ * and stored for later retrieval to enhance performance.
+ * </p>
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ @Override
+ int hashCode();
+
+ /** Returns the {@link PixelFormat}. */
+ PixelFormat getPixelformat();
+
+ /** Returns the size, i.e. width and height. */
+ DimensionImmutable getSize();
+
+ /**
+ * Returns stride in byte-size, i.e. byte count from one line to the next.
+ * <p>
+ * Must be >= {@link #getPixelformat()}.{@link PixelFormat#bytesPerPixel() bytesPerPixel()} * {@link #getSize()}.{@link DimensionImmutable#getWidth() getWidth()}.
+ * </p>
+ */
+ int getStride();
+
+ /**
+ * Returns <code>true</code> if the memory is laid out in
+ * OpenGL's coordinate system, <i>origin at bottom left</i>.
+ * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
+ */
+ public boolean isGLOriented();
+
+ /** Returns the pixels. */
+ ByteBuffer getPixels();
+
+ @Override
+ String toString();
+
+ /**
+ * Generic PixelRectangle implementation
+ */
+ public static class GenericPixelRect implements PixelRectangle {
+ protected final PixelFormat pixelformat;
+ protected final DimensionImmutable size;
+ protected final int strideInBytes;
+ protected final boolean isGLOriented;
+ protected final ByteBuffer pixels;
+ private int hashCode = 0;
+ private volatile boolean hashCodeComputed = false;
+
+ /**
+ *
+ * @param pixelformat
+ * @param size
+ * @param strideInBytes stride in byte-size, i.e. byte count from one line to the next.
+ * If not zero, value must be >= <code>width * bytes-per-pixel</code>.
+ * If zero, stride is set to <code>width * bytes-per-pixel</code>.
+ * @param isGLOriented
+ * @param pixels
+ * @throws IllegalArgumentException if <code>strideInBytes</code> is invalid.
+ * @throws IndexOutOfBoundsException if <code>pixels</code> has insufficient bytes left
+ */
+ public GenericPixelRect(final PixelFormat pixelformat, final DimensionImmutable size, int strideInBytes, final boolean isGLOriented, final ByteBuffer pixels)
+ throws IllegalArgumentException, IndexOutOfBoundsException
+ {
+ if( 0 != strideInBytes ) {
+ if( strideInBytes < pixelformat.bytesPerPixel() * size.getWidth()) {
+ throw new IllegalArgumentException("Invalid stride "+strideInBytes+", must be greater than bytesPerPixel "+pixelformat.bytesPerPixel()+" * width "+size.getWidth());
+ }
+ } else {
+ strideInBytes = pixelformat.bytesPerPixel() * size.getWidth();
+ }
+ final int reqBytes = strideInBytes * size.getHeight();
+ if( pixels.limit() < reqBytes ) {
+ throw new IndexOutOfBoundsException("Dest buffer has insufficient bytes left, needs "+reqBytes+": "+pixels);
+ }
+ this.pixelformat = pixelformat;
+ this.size = size;
+ this.strideInBytes = strideInBytes;
+ this.isGLOriented = isGLOriented;
+ this.pixels = pixels;
+ }
+
+ /**
+ * Copy ctor validating src.
+ * @param src
+ * @throws IllegalArgumentException if <code>strideInBytes</code> is invalid.
+ * @throws IndexOutOfBoundsException if <code>pixels</code> has insufficient bytes left
+ */
+ public GenericPixelRect(final PixelRectangle src)
+ throws IllegalArgumentException, IndexOutOfBoundsException
+ {
+ this(src.getPixelformat(), src.getSize(), src.getStride(), src.isGLOriented(), src.getPixels());
+ }
+
+ @Override
+ public int hashCode() {
+ if( !hashCodeComputed ) { // DBL CHECKED OK VOLATILE
+ synchronized (this) {
+ if( !hashCodeComputed ) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + pixelformat.hashCode();
+ hash = ((hash << 5) - hash) + size.hashCode();
+ hash = ((hash << 5) - hash) + strideInBytes;
+ hash = ((hash << 5) - hash) + ( isGLOriented ? 1 : 0);
+ hashCode = ((hash << 5) - hash) + pixels.hashCode();
+ hashCodeComputed = true;
+ }
+ }
+ }
+ return hashCode;
+ }
+
+ @Override
+ public PixelFormat getPixelformat() {
+ return pixelformat;
+ }
+
+ @Override
+ public DimensionImmutable getSize() {
+ return size;
+ }
+
+ @Override
+ public int getStride() {
+ return strideInBytes;
+ }
+
+ @Override
+ public boolean isGLOriented() {
+ return isGLOriented;
+ }
+
+ @Override
+ public ByteBuffer getPixels() {
+ return pixels;
+ }
+
+ @Override
+ public final String toString() {
+ return "PixelRect[obj 0x"+Integer.toHexString(super.hashCode())+", "+pixelformat+", "+size+", stride "+strideInBytes+", isGLOrient "+isGLOriented+", pixels "+pixels+"]";
+ }
+ }
+}
+
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Point.java b/src/nativewindow/classes/javax/media/nativewindow/util/Point.java
index c53b16928..3576a7dd0 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/Point.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/Point.java
@@ -33,7 +33,7 @@ public class Point implements Cloneable, PointImmutable {
int x;
int y;
- public Point(int x, int y) {
+ public Point(final int x, final int y) {
this.x=x;
this.y=y;
}
@@ -42,35 +42,54 @@ public class Point implements Cloneable, PointImmutable {
this(0, 0);
}
+ @Override
public Object cloneMutable() {
return clone();
}
-
+
+ @Override
public Object clone() {
try {
return super.clone();
- } catch (CloneNotSupportedException ex) {
+ } catch (final CloneNotSupportedException ex) {
throw new InternalError();
}
}
- public boolean equals(Object obj) {
+ @Override
+ public int compareTo(final PointImmutable d) {
+ final int sq = x*y;
+ final int xsq = d.getX()*d.getY();
+
+ if(sq > xsq) {
+ return 1;
+ } else if(sq < xsq) {
+ return -1;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
if(this == obj) { return true; }
if (obj instanceof Point) {
- Point p = (Point)obj;
+ final Point p = (Point)obj;
return y == p.y && x == p.x;
}
return false;
}
+ @Override
public final int getX() {
return x;
}
+ @Override
public final int getY() {
return y;
}
+ @Override
public int hashCode() {
// 31 * x == (x << 5) - x
int hash = 31 + x;
@@ -78,29 +97,63 @@ public class Point implements Cloneable, PointImmutable {
return hash;
}
+ @Override
public String toString() {
- return new String( x + " / " + y );
+ return x + " / " + y;
}
- public void setX(int x) { this.x = x; }
- public void setY(int y) { this.y = y; }
+ public final void set(final int x, final int y) { this.x = x; this.y = y; }
+ public final void setX(final int x) { this.x = x; }
+ public final void setY(final int y) { this.y = y; }
- public Point translate(Point pd) {
+ /**
+ * Translate this instance's x- and y-components,
+ * i.e. add the values of the given delta point to them.
+ * @param pd delta point
+ * @return this instance for scaling
+ */
+ public final Point translate(final Point pd) {
x += pd.x ;
y += pd.y ;
return this;
}
- public Point translate(int dx, int dy) {
+ /**
+ * Translate this instance's x- and y-components,
+ * i.e. add the given deltas to them.
+ * @param dx delta for x
+ * @param dy delta for y
+ * @return this instance for scaling
+ */
+ public final Point translate(final int dx, final int dy) {
x += dx ;
y += dy ;
return this;
}
- public Point scale(int sx, int sy) {
+ /**
+ * Scale this instance's x- and y-components,
+ * i.e. multiply them by the given scale factors.
+ * @param sx scale factor for x
+ * @param sy scale factor for y
+ * @return this instance for scaling
+ */
+ public final Point scale(final int sx, final int sy) {
x *= sx ;
y *= sy ;
return this;
}
-
+
+ /**
+ * Inverse scale this instance's x- and y-components,
+ * i.e. divide them by the given scale factors.
+ * @param sx inverse scale factor for x
+ * @param sy inverse scale factor for y
+ * @return this instance for scaling
+ */
+ public final Point scaleInv(final int sx, final int sy) {
+ x /= sx ;
+ y /= sy ;
+ return this;
+ }
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PointImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/util/PointImmutable.java
index d7eb0e7b4..08c628cc1 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/PointImmutable.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PointImmutable.java
@@ -32,21 +32,32 @@ package javax.media.nativewindow.util;
import com.jogamp.common.type.WriteCloneable;
/** Immutable Point interface */
-public interface PointImmutable extends WriteCloneable {
+public interface PointImmutable extends WriteCloneable, Comparable<PointImmutable> {
int getX();
int getY();
/**
+ * <p>
+ * Compares the square of the position.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final PointImmutable d);
+
+ /**
* Checks whether two points objects are equal. Two instances
* of <code>PointReadOnly</code> are equal if the two components
* <code>y</code> and <code>x</code> are equal.
* @return <code>true</code> if the two points are equal;
* otherwise <code>false</code>.
*/
+ @Override
public boolean equals(Object obj);
+ @Override
public int hashCode();
-
+
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java b/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java
index 8d6bfe48f..c30968c4b 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,14 +20,16 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package javax.media.nativewindow.util;
+import java.util.List;
+
public class Rectangle implements Cloneable, RectangleImmutable {
int x;
int y;
@@ -38,55 +40,198 @@ public class Rectangle implements Cloneable, RectangleImmutable {
this(0, 0, 0, 0);
}
- public Rectangle(int x, int y, int width, int height) {
+ public Rectangle(final int x, final int y, final int width, final int height) {
this.x=x;
this.y=y;
this.width=width;
this.height=height;
}
-
+
+ @Override
public Object cloneMutable() {
return clone();
}
-
+
+ @Override
protected Object clone() {
try {
return super.clone();
- } catch (CloneNotSupportedException ex) {
+ } catch (final CloneNotSupportedException ex) {
throw new InternalError();
}
}
+ @Override
public final int getX() { return x; }
+ @Override
public final int getY() { return y; }
+ @Override
public final int getWidth() { return width; }
+ @Override
public final int getHeight() { return height; }
- public void setX(int x) { this.x = x; }
- public void setY(int y) { this.y = y; }
- public void setWidth(int width) { this.width = width; }
- public void setHeight(int height) { this.height = height; }
- public boolean equals(Object obj) {
+ public final void set(final int x, final int y, final int width, final int height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+ public final void set(final Rectangle s) {
+ this.x = s.x;
+ this.y = s.y;
+ this.width = s.width;
+ this.height = s.height;
+ }
+ public final void setX(final int x) { this.x = x; }
+ public final void setY(final int y) { this.y = y; }
+ public final void setWidth(final int width) { this.width = width; }
+ public final void setHeight(final int height) { this.height = height; }
+
+ @Override
+ public final RectangleImmutable union(final RectangleImmutable r) {
+ return union(r.getX(), r.getY(), r.getX() + r.getWidth(), r.getY() + r.getHeight());
+ }
+ @Override
+ public final RectangleImmutable union(final int rx1, final int ry1, final int rx2, final int ry2) {
+ final int x1 = Math.min(x, rx1);
+ final int y1 = Math.min(y, ry1);
+ final int x2 = Math.max(x + width, rx2);
+ final int y2 = Math.max(y + height, ry2);
+ return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+ }
+ /**
+ * Calculates the union of the given rectangles, stores it in this instance and returns this instance.
+ * @param rectangles given list of rectangles
+ * @return this instance holding the union of given rectangles.
+ */
+ public final Rectangle union(final List<RectangleImmutable> rectangles) {
+ int x1=Integer.MAX_VALUE, y1=Integer.MAX_VALUE;
+ int x2=Integer.MIN_VALUE, y2=Integer.MIN_VALUE;
+ for(int i=rectangles.size()-1; i>=0; i--) {
+ final RectangleImmutable vp = rectangles.get(i);
+ x1 = Math.min(x1, vp.getX());
+ x2 = Math.max(x2, vp.getX() + vp.getWidth());
+ y1 = Math.min(y1, vp.getY());
+ y2 = Math.max(y2, vp.getY() + vp.getHeight());
+ }
+ set(x1, y1, x2 - x1, y2 - y1);
+ return this;
+ }
+
+ @Override
+ public final RectangleImmutable intersection(final RectangleImmutable r) {
+ return intersection(r.getX(), r.getY(), r.getX() + r.getWidth(), r.getY() + r.getHeight());
+ }
+ @Override
+ public final RectangleImmutable intersection(final int rx1, final int ry1, final int rx2, final int ry2) {
+ final int x1 = Math.max(x, rx1);
+ final int y1 = Math.max(y, ry1);
+ final int x2 = Math.min(x + width, rx2);
+ final int y2 = Math.min(y + height, ry2);
+ final int ix, iy, iwidth, iheight;
+ if( x2 < x1 ) {
+ ix = 0;
+ iwidth = 0;
+ } else {
+ ix = x1;
+ iwidth = x2 - x1;
+ }
+ if( y2 < y1 ) {
+ iy = 0;
+ iheight = 0;
+ } else {
+ iy = y1;
+ iheight = y2 - y1;
+ }
+ return new Rectangle (ix, iy, iwidth, iheight);
+ }
+ @Override
+ public final float coverage(final RectangleImmutable r) {
+ final RectangleImmutable isect = intersection(r);
+ final float sqI = isect.getWidth()*isect.getHeight();
+ final float sqT = width*height;
+ return sqI / sqT;
+ }
+
+ /**
+ * Scale this instance's components,
+ * i.e. multiply them by the given scale factors.
+ * @param sx scale factor for x
+ * @param sy scale factor for y
+ * @return this instance for scaling
+ */
+ public final Rectangle scale(final int sx, final int sy) {
+ x *= sx ;
+ y *= sy ;
+ width *= sx ;
+ height *= sy ;
+ return this;
+ }
+
+ /**
+ * Inverse scale this instance's components,
+ * i.e. divide them by the given scale factors.
+ * @param sx inverse scale factor for x
+ * @param sy inverse scale factor for y
+ * @return this instance for scaling
+ */
+ public final Rectangle scaleInv(final int sx, final int sy) {
+ x /= sx ;
+ y /= sy ;
+ width /= sx ;
+ height /= sy ;
+ return this;
+ }
+
+ @Override
+ public int compareTo(final RectangleImmutable d) {
+ {
+ final int sq = width*height;
+ final int xsq = d.getWidth()*d.getHeight();
+
+ if(sq > xsq) {
+ return 1;
+ } else if(sq < xsq) {
+ return -1;
+ }
+ }
+ {
+ final int sq = x*y;
+ final int xsq = d.getX()*d.getY();
+
+ if(sq > xsq) {
+ return 1;
+ } else if(sq < xsq) {
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
if(this == obj) { return true; }
if (obj instanceof Rectangle) {
- Rectangle rect = (Rectangle)obj;
+ final Rectangle rect = (Rectangle)obj;
return (y == rect.y) && (x == rect.x) &&
(height == rect.height) && (width == rect.width);
}
return false;
}
+ @Override
public int hashCode() {
- int sum1 = x + height;
- int sum2 = width + y;
- int val1 = sum1 * (sum1 + 1)/2 + x;
- int val2 = sum2 * (sum2 + 1)/2 + y;
- int sum3 = val1 + val2;
+ final int sum1 = x + height;
+ final int sum2 = width + y;
+ final int val1 = sum1 * (sum1 + 1)/2 + x;
+ final int val2 = sum2 * (sum2 + 1)/2 + y;
+ final int sum3 = val1 + val2;
return sum3 * (sum3 + 1)/2 + val2;
}
+ @Override
public String toString() {
- return new String("[ "+x+" / "+y+" "+width+" x "+height+" ]");
+ return "[ "+x+" / "+y+" "+width+" x "+height+" ]";
}
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java
index d3b43c864..7ca92ff53 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java
@@ -31,7 +31,7 @@ package javax.media.nativewindow.util;
import com.jogamp.common.type.WriteCloneable;
/** Immutable Rectangle interface */
-public interface RectangleImmutable extends WriteCloneable {
+public interface RectangleImmutable extends WriteCloneable, Comparable<RectangleImmutable> {
int getHeight();
@@ -41,6 +41,35 @@ public interface RectangleImmutable extends WriteCloneable {
int getY();
+ /** Returns the union of this rectangle and the given rectangle. */
+ RectangleImmutable union(final RectangleImmutable r);
+ /** Returns the union of this rectangleand the given coordinates. */
+ RectangleImmutable union(final int rx1, final int ry1, final int rx2, final int ry2);
+ /** Returns the intersection of this rectangleand the given rectangle. */
+ RectangleImmutable intersection(RectangleImmutable r);
+ /** Returns the intersection of this rectangleand the given coordinates. */
+ RectangleImmutable intersection(final int rx1, final int ry1, final int rx2, final int ry2);
+ /**
+ * Returns the coverage of given rectangle w/ this this one, i.e. between <code>0.0</code> and <code>1.0</code>.
+ * <p>
+ * Coverage is computed by:
+ * <pre>
+ * isect = this.intersection(r);
+ * coverage = area( isect ) / area( this ) ;
+ * </pre>
+ * </p>
+ */
+ float coverage(RectangleImmutable r);
+
+ /**
+ * <p>
+ * Compares square of size 1st, if equal the square of position.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final RectangleImmutable d);
+
/**
* Checks whether two rect objects are equal. Two instances
* of <code>Rectangle</code> are equal if the four integer values
@@ -49,8 +78,10 @@ public interface RectangleImmutable extends WriteCloneable {
* @return <code>true</code> if the two rectangles are equal;
* otherwise <code>false</code>.
*/
+ @Override
boolean equals(Object obj);
+ @Override
int hashCode();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java b/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java
index 8f21bc49b..601e6dd71 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java
@@ -4,14 +4,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -21,25 +21,26 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package javax.media.nativewindow.util;
-/** Immutable SurfaceSize Class, consisting of it's read only components:<br>
+/**
+ * Immutable SurfaceSize Class, consisting of it's read only components:<br>
* <ul>
- * <li>{@link javax.media.nativewindow.util.DimensionImmutable} size in pixels</li>
+ * <li>{@link javax.media.nativewindow.util.DimensionImmutable size in pixels}</li>
* <li><code>bits per pixel</code></li>
* </ul>
*/
-public class SurfaceSize {
- DimensionImmutable resolution;
- int bitsPerPixel;
+public class SurfaceSize implements Comparable<SurfaceSize> {
+ final DimensionImmutable resolution;
+ final int bitsPerPixel;
- public SurfaceSize(DimensionImmutable resolution, int bitsPerPixel) {
+ public SurfaceSize(final DimensionImmutable resolution, final int bitsPerPixel) {
if(null==resolution || bitsPerPixel<=0) {
throw new IllegalArgumentException("resolution must be set and bitsPerPixel greater 0");
}
@@ -47,6 +48,7 @@ public class SurfaceSize {
this.bitsPerPixel=bitsPerPixel;
}
+ /** Returns the resolution in pixel units */
public final DimensionImmutable getResolution() {
return resolution;
}
@@ -55,8 +57,30 @@ public class SurfaceSize {
return bitsPerPixel;
}
+ @Override
public final String toString() {
- return new String("[ "+resolution+" x "+bitsPerPixel+" bpp ]");
+ return "[ "+resolution+" pixels x "+bitsPerPixel+" bpp ]";
+ }
+
+ /**
+ * <p>
+ * Compares {@link DimensionImmutable#compareTo(DimensionImmutable) resolution} 1st, if equal the bitsPerPixel.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final SurfaceSize ssz) {
+ final int rres = resolution.compareTo(ssz.getResolution());
+ if( 0 != rres ) {
+ return rres;
+ }
+ final int xbpp = ssz.getBitsPerPixel();
+ if(bitsPerPixel > xbpp) {
+ return 1;
+ } else if(bitsPerPixel < xbpp) {
+ return -1;
+ }
+ return 0;
}
/**
@@ -67,16 +91,18 @@ public class SurfaceSize {
* @return <code>true</code> if the two dimensions are equal;
* otherwise <code>false</code>.
*/
- public final boolean equals(Object obj) {
+ @Override
+ public final boolean equals(final Object obj) {
if(this == obj) { return true; }
if (obj instanceof SurfaceSize) {
- SurfaceSize p = (SurfaceSize)obj;
+ final SurfaceSize p = (SurfaceSize)obj;
return getResolution().equals(p.getResolution()) &&
getBitsPerPixel() == p.getBitsPerPixel();
}
return false;
}
+ @Override
public final int hashCode() {
// 31 * x == (x << 5) - x
int hash = 31 + getResolution().hashCode();
diff --git a/src/nativewindow/classes/jogamp/nativewindow/Debug.java b/src/nativewindow/classes/jogamp/nativewindow/Debug.java
index e07fd1b57..f2a45377e 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/Debug.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/Debug.java
@@ -1,44 +1,36 @@
-/*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
*/
package jogamp.nativewindow;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
import com.jogamp.common.util.PropertyAccess;
/** Helper routines for logging and debugging. */
@@ -47,41 +39,37 @@ public class Debug extends PropertyAccess {
// Some common properties
private static final boolean verbose;
private static final boolean debugAll;
-
+
static {
- PropertyAccess.addTrustedPrefix("nativewindow.", Debug.class);
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ PropertyAccess.addTrustedPrefix("nativewindow.");
+ return null;
+ } } );
verbose = isPropertyDefined("nativewindow.verbose", true);
debugAll = isPropertyDefined("nativewindow.debug", true);
if (verbose) {
- Package p = Package.getPackage("javax.media.nativewindow");
+ final Package p = Package.getPackage("javax.media.nativewindow");
System.err.println("NativeWindow specification version " + p.getSpecificationVersion());
System.err.println("NativeWindow implementation version " + p.getImplementationVersion());
System.err.println("NativeWindow implementation vendor " + p.getImplementationVendor());
}
}
- public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) {
- return PropertyAccess.isPropertyDefined(property, jnlpAlias, null);
- }
-
- public static String getProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getProperty(property, jnlpAlias, null);
- }
-
- public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getBooleanProperty(property, jnlpAlias, null);
- }
-
- public static boolean verbose() {
+ /** Ensures static init block has been issues, i.e. if calling through to {@link PropertyAccess#isPropertyDefined(String, boolean)}. */
+ public static final void initSingleton() {}
+
+ public static final boolean verbose() {
return verbose;
}
- public static boolean debugAll() {
+ public static final boolean debugAll() {
return debugAll;
}
- public static boolean debug(String subcomponent) {
+ public static final boolean debug(final String subcomponent) {
return debugAll() || isPropertyDefined("nativewindow.debug." + subcomponent, true);
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java b/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java
index 52e9c8308..6061c4e79 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -36,8 +36,9 @@ package jogamp.nativewindow;
import javax.media.nativewindow.*;
public class DefaultGraphicsConfigurationFactoryImpl extends GraphicsConfigurationFactory {
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID) {
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested, final CapabilitiesChooser chooser, final AbstractGraphicsScreen screen, final int nativeVisualID) {
return new DefaultGraphicsConfiguration(screen, capsChosen, capsRequested);
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java
new file mode 100644
index 000000000..4f6c0d155
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.ToolkitLock;
+
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+/**
+ * Implementing a global recursive {@link javax.media.nativewindow.ToolkitLock}.
+ * <p>
+ * This is the last resort for unstable driver where multiple X11 display connections
+ * to the same connection name are not treated thread safe within the GL/X11 driver.
+ * </p>
+ */
+public class GlobalToolkitLock implements ToolkitLock {
+ private static final RecursiveLock globalLock = LockFactory.createRecursiveLock();
+ private static GlobalToolkitLock singleton = new GlobalToolkitLock();
+
+ public static final GlobalToolkitLock getSingleton() {
+ return singleton;
+ }
+
+ private GlobalToolkitLock() { }
+
+ @Override
+ public final void lock() {
+ globalLock.lock();
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" GlobalToolkitLock: lock() "+toStringImpl()); }
+ }
+
+ @Override
+ public final void unlock() {
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" GlobalToolkitLock: unlock() "+toStringImpl()); }
+ globalLock.unlock(); // implicit lock validation
+ }
+
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ globalLock.validateLocked();
+ }
+
+ @Override
+ public final void dispose() {
+ // nop
+ }
+
+ @Override
+ public String toString() {
+ return "GlobalToolkitLock["+toStringImpl()+"]";
+ }
+ private String toStringImpl() {
+ return "obj 0x"+Integer.toHexString(hashCode())+", isOwner "+globalLock.isOwner(Thread.currentThread())+", "+globalLock.toString();
+ }
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java b/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java
index 6c15f9a2b..8d0d04161 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.nativewindow;
@@ -37,20 +37,17 @@ import com.jogamp.common.os.Platform;
import com.jogamp.common.util.cache.TempJarCache;
public class NWJNILibLoader extends JNILibLoaderBase {
-
- public static boolean loadNativeWindow(final String ossuffix) {
- return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
- public Boolean run() {
- Platform.initSingleton();
- final String libName = "nativewindow_"+ossuffix ;
- if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) {
- // either: [jogl-all.jar, jogl-all-noawt.jar, jogl-all-mobile.jar] -> jogl-all-natives-<os.and.arch>.jar
- // or: nativewindow-core.jar -> nativewindow-natives-<os.and.arch>.jar
- addNativeJarLibs(new Class<?>[] { NWJNILibLoader.class }, "-all", new String[] { "-noawt", "-mobile", "-core" } );
- }
- return new Boolean(loadLibrary(libName, false, NWJNILibLoader.class.getClassLoader()));
- }
- }).booleanValue();
- }
-
+ public static boolean loadNativeWindow(final String ossuffix) {
+ return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Platform.initSingleton();
+ final String libName = "nativewindow_"+ossuffix ;
+ if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) {
+ JNILibLoaderBase.addNativeJarLibsJoglCfg(new Class<?>[] { jogamp.nativewindow.Debug.class });
+ }
+ return Boolean.valueOf(loadLibrary(libName, false, NWJNILibLoader.class.getClassLoader()));
+ }
+ }).booleanValue();
+ }
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java b/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java
index 29564da3b..40fca0f7b 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -46,12 +46,13 @@ public class NativeWindowFactoryImpl extends NativeWindowFactory {
private static final ToolkitLock nullToolkitLock = new NullToolkitLock();
public static ToolkitLock getNullToolkitLock() {
- return nullToolkitLock;
+ return nullToolkitLock;
}
-
+
// This subclass of NativeWindowFactory handles the case of
// NativeWindows being passed in
- protected NativeWindow getNativeWindowImpl(Object winObj, AbstractGraphicsConfiguration config) throws IllegalArgumentException {
+ @Override
+ protected NativeWindow getNativeWindowImpl(final Object winObj, final AbstractGraphicsConfiguration config) throws IllegalArgumentException {
if (winObj instanceof NativeWindow) {
// Use the NativeWindow directly
return (NativeWindow) winObj;
@@ -69,10 +70,10 @@ public class NativeWindowFactoryImpl extends NativeWindowFactory {
winObj.getClass().getName() + " is unsupported; expected " +
"javax.media.nativewindow.NativeWindow or "+AWTNames.ComponentClass);
}
-
+
private Constructor<?> nativeWindowConstructor = null;
- private NativeWindow getAWTNativeWindow(Object winObj, AbstractGraphicsConfiguration config) {
+ private NativeWindow getAWTNativeWindow(final Object winObj, final AbstractGraphicsConfiguration config) {
if (nativeWindowConstructor == null) {
try {
final String windowingType = getNativeWindowType(true);
@@ -93,16 +94,16 @@ public class NativeWindowFactoryImpl extends NativeWindowFactory {
}
nativeWindowConstructor = ReflectionUtil.getConstructor(
- windowClassName, new Class[] { Object.class, AbstractGraphicsConfiguration.class },
- getClass().getClassLoader());
- } catch (Exception e) {
+ windowClassName, new Class[] { Object.class, AbstractGraphicsConfiguration.class },
+ true, getClass().getClassLoader());
+ } catch (final Exception e) {
throw new IllegalArgumentException(e);
}
}
try {
return (NativeWindow) nativeWindowConstructor.newInstance(new Object[] { winObj, config });
- } catch (Exception ie) {
+ } catch (final Exception ie) {
throw new IllegalArgumentException(ie);
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java
index 1af6bf279..bbfb585ac 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java
@@ -28,26 +28,48 @@
package jogamp.nativewindow;
+import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ToolkitLock;
/**
- * Implementing a singleton global recursive {@link javax.media.nativewindow.ToolkitLock}
- * without any locking. Since there is no locking it all,
- * it is intrinsically recursive.
+ * Implementing a singleton global NOP {@link javax.media.nativewindow.ToolkitLock}
+ * without any locking. Since there is no locking it all, it is intrinsically recursive.
*/
public class NullToolkitLock implements ToolkitLock {
-
/** Singleton via {@link NativeWindowFactoryImpl#getNullToolkitLock()} */
protected NullToolkitLock() { }
-
+
+ @Override
public final void lock() {
if(TRACE_LOCK) {
- System.err.println("NullToolkitLock.lock()");
- // Thread.dumpStack();
+ System.err.println(Thread.currentThread()+" NullToolkitLock: lock() "+toStringImpl());
+ // ExceptionUtils.dumpStackTrace(System.err, 1, 4);
}
}
+ @Override
public final void unlock() {
- if(TRACE_LOCK) { System.err.println("NullToolkitLock.unlock()"); }
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" NullToolkitLock: unlock() "+toStringImpl()); }
+ }
+
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ if( NativeWindowFactory.requiresToolkitLock() ) {
+ throw new RuntimeException("NullToolkitLock does not lock, but locking is required.");
+ }
}
+
+ @Override
+ public final void dispose() {
+ // nop
+ }
+
+ @Override
+ public String toString() {
+ return "NullToolkitLock["+toStringImpl()+"]";
+ }
+ private String toStringImpl() {
+ return "obj 0x"+Integer.toHexString(hashCode());
+ }
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
index 63f56cbae..deb685b51 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
@@ -36,17 +36,15 @@ import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.SurfaceUpdatedListener;
import javax.media.nativewindow.UpstreamSurfaceHook;
-
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
-public abstract class ProxySurfaceImpl implements ProxySurface {
+public abstract class ProxySurfaceImpl implements ProxySurface {
private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
- protected long displayHandle; // convenient ref of config.screen.device.handle
private AbstractGraphicsConfiguration config; // control access due to delegation
private UpstreamSurfaceHook upstream;
private long surfaceHandle_old;
- private RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
+ private final RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
private int implBitfield;
private boolean upstreamSurfaceHookLifecycleEnabled;
@@ -57,7 +55,7 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
* owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
* otherwise <code>false</code>. Owning the device implies closing it at {@link #destroyNotify()}.
*/
- protected ProxySurfaceImpl(AbstractGraphicsConfiguration cfg, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ protected ProxySurfaceImpl(final AbstractGraphicsConfiguration cfg, final UpstreamSurfaceHook upstream, final boolean ownsDevice) {
if(null == cfg) {
throw new IllegalArgumentException("null AbstractGraphicsConfiguration");
}
@@ -65,38 +63,41 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
throw new IllegalArgumentException("null UpstreamSurfaceHook");
}
this.config = cfg;
- this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
this.upstream = upstream;
this.surfaceHandle_old = 0;
this.implBitfield = 0;
this.upstreamSurfaceHookLifecycleEnabled = true;
if(ownsDevice) {
addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
- }
+ }
+ }
+
+ @Override
+ public final NativeSurface getUpstreamSurface() {
+ return upstream.getUpstreamSurface();
}
@Override
public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; }
-
+
@Override
- public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook) {
+ public void setUpstreamSurfaceHook(final UpstreamSurfaceHook hook) {
if(null == hook) {
throw new IllegalArgumentException("null UpstreamSurfaceHook");
}
upstream = hook;
}
-
+
@Override
- public final void enableUpstreamSurfaceHookLifecycle(boolean enable) {
+ public final void enableUpstreamSurfaceHookLifecycle(final boolean enable) {
upstreamSurfaceHookLifecycleEnabled = enable;
}
-
+
@Override
- public void createNotify() {
+ public void createNotify() {
if(upstreamSurfaceHookLifecycleEnabled) {
upstream.create(this);
}
- this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
this.surfaceHandle_old = 0;
}
@@ -111,25 +112,15 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
}
invalidateImpl();
}
- this.displayHandle = 0;
this.surfaceHandle_old = 0;
}
-
- /**
+
+ /**
* Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed.
- * @see #destroyNotify()
+ * @see #destroyNotify()
*/
protected void invalidateImpl() {
- throw new InternalError("UpstreamSurfaceHook given, but required method not implemented.");
- }
-
- @Override
- public final long getDisplayHandle() {
- return displayHandle;
- }
-
- protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() {
- return config;
+ throw new InternalError("UpstreamSurfaceHook given, but required method not implemented.");
}
@Override
@@ -138,10 +129,15 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
}
@Override
- public final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) {
+ public final long getDisplayHandle() {
+ return config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ }
+
+ @Override
+ public final void setGraphicsConfiguration(final AbstractGraphicsConfiguration cfg) {
config = cfg;
}
-
+
@Override
public final int getScreenIndex() {
return getGraphicsConfiguration().getScreen().getIndex();
@@ -152,15 +148,15 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
@Override
public abstract void setSurfaceHandle(long surfaceHandle);
-
+
@Override
- public final int getWidth() {
- return upstream.getWidth(this);
+ public final int getSurfaceWidth() {
+ return upstream.getSurfaceWidth(this);
}
@Override
- public final int getHeight() {
- return upstream.getHeight(this);
+ public final int getSurfaceHeight() {
+ return upstream.getSurfaceHeight(this);
}
@Override
@@ -169,22 +165,22 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
}
@Override
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ public void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
}
@Override
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ public void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
}
@Override
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ public void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
}
@Override
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
}
@@ -253,7 +249,8 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
public final Thread getSurfaceLockOwner() {
return surfaceLock.getOwner();
}
-
+
+ @Override
public final StringBuilder getUpstreamOptionBits(StringBuilder sink) {
if(null == sink) {
sink = new StringBuilder();
@@ -285,38 +282,41 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
sink.append(" ]");
return sink;
}
-
+
@Override
public final int getUpstreamOptionBits() { return implBitfield; }
-
+
@Override
- public final boolean containsUpstreamOptionBits(int v) {
+ public final boolean containsUpstreamOptionBits(final int v) {
return v == ( implBitfield & v ) ;
}
-
+
@Override
- public final void addUpstreamOptionBits(int v) { implBitfield |= v; }
-
+ public final void addUpstreamOptionBits(final int v) { implBitfield |= v; }
+
@Override
- public final void clearUpstreamOptionBits(int v) { implBitfield &= ~v; }
-
+ public final void clearUpstreamOptionBits(final int v) { implBitfield &= ~v; }
+
@Override
public StringBuilder toString(StringBuilder sink) {
if(null == sink) {
sink = new StringBuilder();
}
- sink.append(getUpstreamSurfaceHook()).
- append(", displayHandle 0x" + Long.toHexString(getDisplayHandle())).
- append(", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle())).
- append(", size " + getWidth() + "x" + getHeight()).append(", ");
+ sink.append("displayHandle 0x" + Long.toHexString(getDisplayHandle())).
+ append("\n, surfaceHandle 0x" + Long.toHexString(getSurfaceHandle())).
+ append("\n, size " + getSurfaceWidth() + "x" + getSurfaceHeight()).append("\n, ");
getUpstreamOptionBits(sink);
- sink.append(", surfaceLock "+surfaceLock);
+ sink.append("\n, "+config).
+ append("\n, surfaceLock "+surfaceLock+"\n, ").
+ append(getUpstreamSurfaceHook()).
+ append("\n, upstreamSurface "+(null != getUpstreamSurface()));
+ // append("\n, upstreamSurface "+getUpstreamSurface());
return sink;
}
-
+
@Override
public String toString() {
- StringBuilder msg = new StringBuilder();
+ final StringBuilder msg = new StringBuilder();
msg.append(getClass().getSimpleName()).append("[ ");
toString(msg);
msg.append(" ]");
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java
index 743d371b7..e4e557d36 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright 2012 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -25,52 +25,62 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package jogamp.nativewindow.jawt.x11;
-import jogamp.nativewindow.jawt.*;
-import jogamp.nativewindow.x11.X11Lib;
-import jogamp.nativewindow.x11.X11Util;
+package jogamp.nativewindow;
+
import javax.media.nativewindow.ToolkitLock;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
/**
- * Implementing a recursive {@link javax.media.nativewindow.ToolkitLock}
- * utilizing JAWT's AWT lock via {@link JAWTUtil#lockToolkit()} and {@link X11Util#XLockDisplay(long)}.
- * <br>
- * This strategy should only be used if AWT is using the underlying native windowing toolkit
- * in a not intrinsic thread safe manner, e.g. under X11 where no XInitThreads() call
- * is issued before any other X11 usage. This is the current situation for e.g. Webstart or Applets.
+ * Implementing a resource based recursive {@link javax.media.nativewindow.ToolkitLock}.
+ * <p>
+ * A resource handle maybe used within a unique object
+ * and can be synchronized across threads via an instance of ResourceToolkitLock.
+ * </p>
*/
-public class X11JAWTToolkitLock implements ToolkitLock {
- long displayHandle;
- RecursiveLock lock;
+public class ResourceToolkitLock implements ToolkitLock {
+ public static final ResourceToolkitLock create() {
+ return new ResourceToolkitLock();
+ }
- public X11JAWTToolkitLock(long displayHandle) {
- this.displayHandle = displayHandle;
- if(!X11Util.isNativeLockAvailable()) {
- lock = LockFactory.createRecursiveLock();
- }
+ private final RecursiveLock lock;
+
+ private ResourceToolkitLock() {
+ this.lock = LockFactory.createRecursiveLock();
}
+ @Override
public final void lock() {
- if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.lock() - native: "+(null==lock)); }
- JAWTUtil.lockToolkit();
- if(null == lock) {
- X11Lib.XLockDisplay(displayHandle);
- } else {
- lock.lock();
+ lock.lock();
+ if(TRACE_LOCK) {
+ System.err.println(Thread.currentThread()+" ResourceToolkitLock: lock() "+toStringImpl());
+ // ExceptionUtils.dumpStackTrace(System.err, 1, 4);
}
}
+ @Override
public final void unlock() {
- if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.unlock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XUnlockDisplay(displayHandle);
- } else {
- lock.unlock();
- }
- JAWTUtil.unlockToolkit();
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" ResourceToolkitLock: unlock() "+toStringImpl()); }
+ lock.unlock(); // implicit lock validation
+ }
+
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ lock.validateLocked();
+ }
+
+ @Override
+ public final void dispose() {
+ // nop
+ }
+
+ @Override
+ public String toString() {
+ return "ResourceToolkitLock["+toStringImpl()+"]";
+ }
+ private String toStringImpl() {
+ return "obj 0x"+Integer.toHexString(hashCode())+", isOwner "+lock.isOwner(Thread.currentThread())+", "+lock.toString();
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java
new file mode 100644
index 000000000..881fd56a6
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java
@@ -0,0 +1,152 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.nativewindow;
+
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.media.nativewindow.ToolkitLock;
+
+import com.jogamp.common.util.LongObjectHashMap;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+/**
+ * Implementing a shared resource based recursive {@link javax.media.nativewindow.ToolkitLock}.
+ * <p>
+ * A resource handle maybe used within many objects
+ * and can be synchronized across threads via an unique instance of SharedResourceToolkitLock.
+ * </p>
+ * <p>
+ * Implementation holds a synchronized map from handle to reference counted {@link SharedResourceToolkitLock}.
+ * New elements are added via {@link #get(long)} if new
+ * and removed via {@link #dispose()} if no more referenced.
+ * </p>
+ */
+public class SharedResourceToolkitLock implements ToolkitLock {
+ private static final LongObjectHashMap handle2Lock;
+ static {
+ handle2Lock = new LongObjectHashMap();
+ handle2Lock.setKeyNotFoundValue(null);
+ }
+
+ /**
+ * @return number of unclosed EGL Displays.<br>
+ */
+ public static int shutdown(final boolean verbose) {
+ if(DEBUG || verbose || handle2Lock.size() > 0 ) {
+ System.err.println("SharedResourceToolkitLock: Shutdown (open: "+handle2Lock.size()+")");
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ if( handle2Lock.size() > 0) {
+ dumpOpenDisplayConnections();
+ }
+ }
+ return handle2Lock.size();
+ }
+
+ public static void dumpOpenDisplayConnections() {
+ System.err.println("SharedResourceToolkitLock: Open ResourceToolkitLock's: "+handle2Lock.size());
+ int i=0;
+ for(final Iterator<LongObjectHashMap.Entry> iter = handle2Lock.iterator(); iter.hasNext(); i++) {
+ final LongObjectHashMap.Entry e = iter.next();
+ System.err.println("SharedResourceToolkitLock: Open["+i+"]: "+e.value);
+ }
+ }
+
+ public static final SharedResourceToolkitLock get(final long handle) {
+ SharedResourceToolkitLock res;
+ synchronized(handle2Lock) {
+ res = (SharedResourceToolkitLock) handle2Lock.get(handle);
+ if( null == res ) {
+ res = new SharedResourceToolkitLock(handle);
+ res.refCount.incrementAndGet();
+ handle2Lock.put(handle, res);
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.get() * NEW *: "+res); }
+ } else {
+ res.refCount.incrementAndGet();
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.get() * EXIST *: "+res); }
+ }
+ }
+ return res;
+ }
+
+ private final RecursiveLock lock;
+ private final long handle;
+ private final AtomicInteger refCount;
+
+ private SharedResourceToolkitLock(final long handle) {
+ this.lock = LockFactory.createRecursiveLock();
+ this.handle = handle;
+ this.refCount = new AtomicInteger(0);
+ }
+
+
+ @Override
+ public final void lock() {
+ lock.lock();
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" SharedResourceToolkitLock: lock() "+toStringImpl()); }
+ }
+
+ @Override
+ public final void unlock() {
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" SharedResourceToolkitLock: unlock() "+toStringImpl()); }
+ lock.unlock();
+ }
+
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ lock.validateLocked();
+ }
+
+ @Override
+ public final void dispose() {
+ if(0 < refCount.get()) { // volatile OK
+ synchronized(handle2Lock) {
+ if( 0 == refCount.decrementAndGet() ) {
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.dispose() * REMOV *: "+this); }
+ handle2Lock.remove(handle);
+ } else {
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.dispose() * DOWN *: "+this); }
+ }
+ }
+ } else {
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.dispose() * NULL *: "+this); }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SharedResourceToolkitLock["+toStringImpl()+"]";
+ }
+ private String toStringImpl() {
+ return "refCount "+refCount+", handle 0x"+Long.toHexString(handle)+", obj 0x"+Integer.toHexString(hashCode())+", isOwner "+lock.isOwner(Thread.currentThread())+", "+lock.toString();
+ }
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java
new file mode 100644
index 000000000..73413cf59
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.ScalableSurface;
+
+/**
+ * Basic {@link ScalableSurface} utility to validate and compute pixel-scale values.
+ */
+public class SurfaceScaleUtils {
+
+ private static final int[] PlatformMaxPixelScale;
+ private static final boolean PlatformUniformPixelScale;
+ private static final boolean PlatformPixelScaleSupported;
+
+ static {
+ if( NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(true) ) {
+ PlatformMaxPixelScale = new int[] { jogamp.nativewindow.macosx.OSXUtil.MAX_PIXELSCALE, jogamp.nativewindow.macosx.OSXUtil.MAX_PIXELSCALE };
+ PlatformUniformPixelScale = true;
+ PlatformPixelScaleSupported = true;
+ } else {
+ PlatformMaxPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ PlatformUniformPixelScale = false;
+ PlatformPixelScaleSupported = false;
+ }
+ }
+
+ /**
+ * Compute a new valid pixelScale to be used by {@link NativeSurface} implementations,
+ * based on the given request and surface's pixelScale
+ *
+ * @param result int[2] storage for result, maybe same as <code>prePixelScale</code> for in-place
+ * @param prePixelScale previous pixelScale
+ * @param reqPixelScale requested pixelScale, validated via {@link #validateReqPixelScale(int[], int, String)}.
+ * @param newPixelScaleRaw new raw surface pixelScale
+ * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix
+ * @return true if pixelScale has changed, otherwise false
+ */
+ public static boolean computePixelScale(final int[] result, final int[] prePixelScale, final int[] reqPixelScale, final int[] newPixelScaleRaw, final String DEBUG_PREFIX) {
+ final int newPixelScaleSafeX = 0 < newPixelScaleRaw[0] ? newPixelScaleRaw[0] : ScalableSurface.IDENTITY_PIXELSCALE;
+ final int newPixelScaleSafeY = 0 < newPixelScaleRaw[1] ? newPixelScaleRaw[1] : ScalableSurface.IDENTITY_PIXELSCALE;
+ final boolean useHiDPI = ScalableSurface.IDENTITY_PIXELSCALE != reqPixelScale[0] || ScalableSurface.IDENTITY_PIXELSCALE != reqPixelScale[1];
+ final int prePixelScaleX = prePixelScale[0];
+ final int prePixelScaleY = prePixelScale[1];
+
+ if( useHiDPI ) {
+ result[0] = newPixelScaleSafeX;
+ result[1] = newPixelScaleSafeY;
+ } else {
+ result[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ result[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ }
+
+ final boolean changed = result[0] != prePixelScaleX || result[1] != prePixelScaleY;
+ if( null != DEBUG_PREFIX ) {
+ System.err.println(DEBUG_PREFIX+".computePixelScale: useHiDPI "+useHiDPI+", ["+prePixelScaleX+"x"+prePixelScaleY+" (pre), "+
+ reqPixelScale[0]+"x"+reqPixelScale[1]+" (req)] -> "+
+ newPixelScaleRaw[0]+"x"+newPixelScaleRaw[1]+" (raw) -> "+
+ newPixelScaleSafeX+"x"+newPixelScaleSafeY+" (safe) -> "+
+ result[0]+"x"+result[1]+" (use), changed "+changed);
+ }
+ return changed;
+ }
+
+ /**
+ * Validate the given requested pixelScale value pair, i.e. clip it to the
+ * limits of {@link ScalableSurface#AUTOMAX_PIXELSCALE} and {@link #getPlatformMaxPixelScale(int[])}
+ * <p>
+ * To be used by {@link ScalableSurface#setSurfaceScale(int[])} implementations.
+ * </p>
+ *
+ * @param result int[2] storage for result
+ * @param reqPixelScale requested pixelScale
+ * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix
+ */
+ public static void validateReqPixelScale(final int[] result, final int[] reqPixelScale, final String DEBUG_PREFIX) {
+ final int minPS = Math.min(reqPixelScale[0], reqPixelScale[1]);
+ if( ScalableSurface.AUTOMAX_PIXELSCALE >= minPS ) {
+ result[0] = ScalableSurface.AUTOMAX_PIXELSCALE;
+ result[1] = ScalableSurface.AUTOMAX_PIXELSCALE;
+ } else if( PlatformUniformPixelScale ) {
+ final int maxPS = Math.max(reqPixelScale[0], reqPixelScale[1]);
+ if( maxPS >= PlatformMaxPixelScale[0] ) {
+ result[0] = PlatformMaxPixelScale[0];
+ result[1] = PlatformMaxPixelScale[1];
+ } else {
+ result[0] = maxPS;
+ result[1] = maxPS;
+ }
+ } else {
+ if( reqPixelScale[0] >= PlatformMaxPixelScale[0] ) {
+ result[0] = PlatformMaxPixelScale[0];
+ } else {
+ result[0] = reqPixelScale[0];
+ }
+ if( reqPixelScale[1] >= PlatformMaxPixelScale[1] ) {
+ result[1] = PlatformMaxPixelScale[1];
+ } else {
+ result[1] = reqPixelScale[1];
+ }
+ }
+ if( null != DEBUG_PREFIX ) {
+ System.err.println(DEBUG_PREFIX+".validateReqPixelScale: ["+reqPixelScale[0]+"x"+reqPixelScale[1]+" (req), "+
+ PlatformMaxPixelScale[0]+"x"+PlatformMaxPixelScale[1]+" (max)] -> "+
+ result[0]+"x"+result[1]+" (valid)");
+ }
+ }
+
+ /**
+ * Replaces {@link ScalableSurface#AUTOMAX_PIXELSCALE} with {@link #getPlatformMaxPixelScale(int[])},
+ * for each component.
+ *
+ * @param pixelScale int[2] value array to be tested and replaced
+ */
+ public static void replaceAutoMaxWithPlatformMax(final int[] pixelScale) {
+ if( ScalableSurface.AUTOMAX_PIXELSCALE == pixelScale[0] ) {
+ pixelScale[0] = PlatformMaxPixelScale[0];
+ }
+ if( ScalableSurface.AUTOMAX_PIXELSCALE == pixelScale[1] ) {
+ pixelScale[1] = PlatformMaxPixelScale[1];
+ }
+ }
+
+ /**
+ * Returns the maximum platform pixelScale
+ */
+ public static int[] getPlatformMaxPixelScale(final int[] result) {
+ System.arraycopy(PlatformMaxPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ /**
+ * Returns true if platform pixelScale is uniform, i.e. same scale factor for x- and y-direction, otherwise false.
+ */
+ public static boolean isPlatformPixelScaleUniform() {
+ return PlatformUniformPixelScale;
+ }
+
+ /**
+ * Returns whether the platform supports pixelScale
+ */
+ public static boolean isPlatformPixelScaleSupported() {
+ return PlatformPixelScaleSupported;
+ }
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
index 4f68c6945..a7e136f76 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -36,48 +36,56 @@ import javax.media.nativewindow.SurfaceUpdatedListener;
public class SurfaceUpdatedHelper implements SurfaceUpdatedListener {
private final Object surfaceUpdatedListenersLock = new Object();
private final ArrayList<SurfaceUpdatedListener> surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>();
+ private volatile boolean isEmpty = true;
//
// Management Utils
- //
- public int size() { return surfaceUpdatedListeners.size(); }
- public SurfaceUpdatedListener get(int i) { return surfaceUpdatedListeners.get(i); }
-
+ //
+ public final int size() { return surfaceUpdatedListeners.size(); }
+ public final SurfaceUpdatedListener get(final int i) { return surfaceUpdatedListeners.get(i); }
+
//
// Implementation of NativeSurface SurfaceUpdatedListener methods
- //
-
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ //
+
+ public final void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
addSurfaceUpdatedListener(-1, l);
}
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l)
+ public final void addSurfaceUpdatedListener(int index, final SurfaceUpdatedListener l)
throws IndexOutOfBoundsException
{
if(l == null) {
return;
}
synchronized(surfaceUpdatedListenersLock) {
- if(0>index) {
- index = surfaceUpdatedListeners.size();
+ if(0>index) {
+ index = surfaceUpdatedListeners.size();
}
surfaceUpdatedListeners.add(index, l);
+ isEmpty = false;
}
}
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ public final boolean removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
if (l == null) {
- return;
+ return false;
}
synchronized(surfaceUpdatedListenersLock) {
- surfaceUpdatedListeners.remove(l);
+ final boolean res = surfaceUpdatedListeners.remove(l);
+ isEmpty = 0 == surfaceUpdatedListeners.size();
+ return res;
}
}
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ @Override
+ public final void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
+ if( isEmpty ) {
+ return;
+ }
synchronized(surfaceUpdatedListenersLock) {
for(int i = 0; i < surfaceUpdatedListeners.size(); i++ ) {
- SurfaceUpdatedListener l = surfaceUpdatedListeners.get(i);
+ final SurfaceUpdatedListener l = surfaceUpdatedListeners.get(i);
l.surfaceUpdated(updater, ns, when);
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java b/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java
new file mode 100644
index 000000000..47b3e63fa
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java
@@ -0,0 +1,47 @@
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.NativeWindowFactory;
+
+/**
+ * Marker interface.
+ * <p>
+ * Implementation requires to provide static methods:
+ * <pre>
+ public static void initSingleton() {}
+
+ public static void shutdown() {}
+
+ public static boolean requiresToolkitLock() {}
+
+ public static boolean hasThreadingIssues() {}
+ * </pre>
+ * Above static methods are invoked by {@link NativeWindowFactory#initSingleton()},
+ * or {@link NativeWindowFactory#shutdown()} via reflection.
+ * </p>
+ */
+public interface ToolkitProperties {
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
+ // void initSingleton();
+
+ /**
+ * Cleanup resources.
+ * <p>
+ * Called by {@link NativeWindowFactory#shutdown()}
+ * </p>
+ */
+ // void shutdown();
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
+ // boolean requiresToolkitLock();
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
+ // boolean hasThreadingIssues();
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
index e544bc61a..d3439b53f 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
@@ -31,17 +31,24 @@ package jogamp.nativewindow;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
-public class WrappedSurface extends ProxySurfaceImpl {
- protected long surfaceHandle;
+/**
+ * Generic Surface implementation which wraps an existing window handle.
+ *
+ * @see ProxySurface
+ */
+public class WrappedSurface extends ProxySurfaceImpl implements ScalableSurface {
+ private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private long surfaceHandle;
/**
* Utilizes a {@link UpstreamSurfaceHook.MutableSize} to hold the size information,
* which is being passed to the {@link ProxySurface} instance.
- *
+ *
* @param cfg the {@link AbstractGraphicsConfiguration} to be used
* @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
* @param initialWidth
@@ -50,11 +57,11 @@ public class WrappedSurface extends ProxySurfaceImpl {
* owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
* otherwise <code>false</code>. Owning the device implies closing it at {@link #destroyNotify()}.
*/
- public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, boolean ownsDevice) {
+ public WrappedSurface(final AbstractGraphicsConfiguration cfg, final long handle, final int initialWidth, final int initialHeight, final boolean ownsDevice) {
super(cfg, new UpstreamSurfaceHookMutableSize(initialWidth, initialHeight), ownsDevice);
surfaceHandle=handle;
}
-
+
/**
* @param cfg the {@link AbstractGraphicsConfiguration} to be used
* @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
@@ -63,14 +70,16 @@ public class WrappedSurface extends ProxySurfaceImpl {
* owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
* otherwise <code>false</code>.
*/
- public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ public WrappedSurface(final AbstractGraphicsConfiguration cfg, final long handle, final UpstreamSurfaceHook upstream, final boolean ownsDevice) {
super(cfg, upstream, ownsDevice);
surfaceHandle=handle;
}
@Override
- protected void invalidateImpl() {
+ protected void invalidateImpl() {
surfaceHandle = 0;
+ hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
}
@Override
@@ -79,10 +88,10 @@ public class WrappedSurface extends ProxySurfaceImpl {
}
@Override
- public final void setSurfaceHandle(long surfaceHandle) {
+ public final void setSurfaceHandle(final long surfaceHandle) {
this.surfaceHandle=surfaceHandle;
}
-
+
@Override
protected final int lockSurfaceImpl() {
return LOCK_SUCCESS;
@@ -92,4 +101,73 @@ public class WrappedSurface extends ProxySurfaceImpl {
protected final void unlockSurfaceImpl() {
}
-}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(int[]) given pixelScale} directly.
+ * </p>
+ */
+ @Override
+ public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
+ pixelUnitsAndResult[0] /= hasPixelScale[0];
+ pixelUnitsAndResult[1] /= hasPixelScale[1];
+ return pixelUnitsAndResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(int[]) given pixelScale} directly.
+ * </p>
+ */
+ @Override
+ public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
+ windowUnitsAndResult[0] *= hasPixelScale[0];
+ windowUnitsAndResult[1] *= hasPixelScale[1];
+ return windowUnitsAndResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * {@link WrappedSurface}'s implementation is to simply pass the given pixelScale
+ * from the caller <i>down</i> to this instance without validation to be applied in the {@link #convertToPixelUnits(int[]) conversion} {@link #convertToWindowUnits(int[]) methods} <b>only</b>.<br/>
+ * This allows the caller to pass down knowledge about window- and pixel-unit conversion and utilize mentioned conversion methods.
+ * </p>
+ * <p>
+ * The given pixelScale will not impact the actual {@link #getSurfaceWidth()} and {@link #getSurfaceHeight()},
+ * which is determinated by this instances {@link #getUpstreamSurface() upstream surface}.
+ * </p>
+ * <p>
+ * Implementation uses the default pixelScale {@link ScalableSurface#IDENTITY_PIXELSCALE}
+ * and resets to default values on {@link #invalidateImpl()}, i.e. {@link #destroyNotify()}.
+ * </p>
+ * <p>
+ * Implementation returns the given pixelScale array.
+ * </p>
+ */
+ @Override
+ public final void setSurfaceScale(final int[] pixelScale) {
+ hasPixelScale[0] = pixelScale[0];
+ hasPixelScale[1] = pixelScale[1];
+ }
+
+ @Override
+ public final int[] getRequestedSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final int[] getCurrentSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final int[] getNativeSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+} \ No newline at end of file
diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedWindow.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedWindow.java
new file mode 100644
index 000000000..fd39a3b4a
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedWindow.java
@@ -0,0 +1,120 @@
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+import javax.media.nativewindow.util.Insets;
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.Point;
+
+import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos;
+
+public class WrappedWindow extends WrappedSurface implements NativeWindow {
+ private final InsetsImmutable insets = new Insets(0, 0, 0, 0);
+ private long windowHandle;
+
+ /**
+ * Utilizes a {@link UpstreamWindowHookMutableSizePos} to hold the size and position information,
+ * which is being passed to the {@link ProxySurface} instance.
+ *
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param surfaceHandle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
+ * @param initialWinX
+ * @param initialWinY
+ * @param initialWinWidth
+ * @param initialWinHeight
+ * @param initialPixelWidth FIXME: pixel-dim == window-dim 'for now' ?
+ * @param initialPixelHeight FIXME: pixel-dim == window-dim 'for now' ?
+ * @param ownsDevice <code>true</code> if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise <code>false</code>. Owning the device implies closing it at {@link #destroyNotify()}.
+ */
+ public WrappedWindow(final AbstractGraphicsConfiguration cfg, final long surfaceHandle,
+ final int initialWinX, final int initialWinY, final int initialWinWidth, final int initialWinHeight,
+ final int initialPixelWidth, final int initialPixelHeight,
+ final boolean ownsDevice, final long windowHandle) {
+ this(cfg, surfaceHandle,
+ new UpstreamWindowHookMutableSizePos(initialWinX, initialWinY, initialWinWidth, initialWinHeight,
+ initialPixelWidth, initialPixelHeight),
+ ownsDevice, windowHandle);
+ }
+
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param surfaceHandle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
+ * @param upstream the {@link UpstreamSurfaceHook} to be used
+ * @param ownsDevice <code>true</code> if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise <code>false</code>.
+ */
+ public WrappedWindow(final AbstractGraphicsConfiguration cfg, final long surfaceHandle, final UpstreamWindowHookMutableSizePos upstream, final boolean ownsDevice, final long windowHandle) {
+ super(cfg, surfaceHandle, upstream, ownsDevice);
+ this.windowHandle = windowHandle;
+ }
+
+ @Override
+ protected void invalidateImpl() {
+ super.invalidateImpl();
+ windowHandle = 0;
+ }
+
+ @Override
+ public void destroy() {
+ destroyNotify();
+ }
+
+ @Override
+ public final NativeSurface getNativeSurface() { return this; }
+
+ @Override
+ public NativeWindow getParent() {
+ return null;
+ }
+
+ @Override
+ public long getWindowHandle() {
+ return windowHandle;
+ }
+
+ @Override
+ public InsetsImmutable getInsets() {
+ return insets;
+ }
+
+ @Override
+ public int getX() {
+ return ((UpstreamWindowHookMutableSizePos)getUpstreamSurfaceHook()).getX();
+ }
+
+ @Override
+ public int getY() {
+ return ((UpstreamWindowHookMutableSizePos)getUpstreamSurfaceHook()).getY();
+ }
+
+ @Override
+ public int getWidth() {
+ return ((UpstreamWindowHookMutableSizePos)getUpstreamSurfaceHook()).getWidth();
+ }
+
+ @Override
+ public int getHeight() {
+ return ((UpstreamWindowHookMutableSizePos)getUpstreamSurfaceHook()).getHeight();
+ }
+
+ @Override
+ public Point getLocationOnScreen(final Point point) {
+ if(null!=point) {
+ return point;
+ } else {
+ return new Point(0, 0);
+ }
+ }
+
+ @Override
+ public boolean hasFocus() {
+ return false;
+ }
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
index d77cd75ef..b0eda63b6 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
@@ -27,17 +27,31 @@
*/
package jogamp.nativewindow.awt;
+import java.awt.Cursor;
+import java.awt.FocusTraversalPolicy;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Toolkit;
import java.awt.Window;
import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
+import java.awt.image.BufferedImage;
+import java.util.HashMap;
+
+import javax.swing.JComponent;
import javax.swing.JFrame;
+import javax.swing.JRootPane;
import javax.swing.WindowConstants;
-
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelFormatUtil;
import javax.swing.MenuSelectionManager;
+import jogamp.nativewindow.jawt.JAWTUtil;
+
public class AWTMisc {
public static JFrame getJFrame(Component c) {
@@ -69,13 +83,157 @@ public class AWTMisc {
}
/**
+ * Return insets of the component w/o traversing up to parent,
+ * i.e. trying Window and JComponent.
+ * <p>
+ * Exception is JRootPane.
+ * Return it's parent's Window component's insets if available,
+ * otherwise return JRootPane's insets.<br>
+ * This is due to <i>experience</i> that <i>some</i> JRootPane's
+ * do not expose valid insets value.
+ * </p>
+ * @param topLevelOnly if true only returns insets of top-level components, i.e. Window and JRootPanel,
+ * otherwise for JComponent as well.
+ */
+ public static Insets getInsets(final Component c, final boolean topLevelOnly) {
+ if( c instanceof Window ) {
+ return ((Window)c).getInsets();
+ }
+ if( c instanceof JRootPane ) {
+ final Window w = getWindow(c);
+ if( null != w ) {
+ return w.getInsets();
+ }
+ return ((JRootPane)c).getInsets();
+ }
+ if( !topLevelOnly && c instanceof JComponent ) {
+ return ((JComponent)c).getInsets();
+ }
+ return null;
+ }
+
+ public static interface ComponentAction {
+ /**
+ * @param c the component to perform the action on
+ */
+ public void run(Component c);
+ }
+
+ public static int performAction(final Container c, final Class<?> cType, final ComponentAction action) {
+ int count = 0;
+ final int cc = c.getComponentCount();
+ for(int i=0; i<cc; i++) {
+ final Component e = c.getComponent(i);
+ if( e instanceof Container ) {
+ count += performAction((Container)e, cType, action);
+ } else if( cType.isInstance(e) ) {
+ action.run(e);
+ count++;
+ }
+ }
+ // we come at last ..
+ if( cType.isInstance(c) ) {
+ action.run(c);
+ count++;
+ }
+ return count;
+ }
+
+ /**
+ * Traverse to the next forward or backward component using the
+ * container's FocusTraversalPolicy.
+ *
+ * @param comp the assumed current focuse component
+ * @param forward if true, returns the next focus component, otherwise the previous one.
+ * @return
+ */
+ public static Component getNextFocus(Component comp, final boolean forward) {
+ Container focusContainer = comp.getFocusCycleRootAncestor();
+ while ( focusContainer != null &&
+ ( !focusContainer.isShowing() || !focusContainer.isFocusable() || !focusContainer.isEnabled() ) )
+ {
+ comp = focusContainer;
+ focusContainer = comp.getFocusCycleRootAncestor();
+ }
+ Component next = null;
+ if (focusContainer != null) {
+ final FocusTraversalPolicy policy = focusContainer.getFocusTraversalPolicy();
+ next = forward ? policy.getComponentAfter(focusContainer, comp) : policy.getComponentBefore(focusContainer, comp);
+ if (next == null) {
+ next = policy.getDefaultComponent(focusContainer);
+ }
+ }
+ return next;
+ }
+
+ /**
* Issue this when your non AWT toolkit gains focus to clear AWT menu path
*/
public static void clearAWTMenus() {
MenuSelectionManager.defaultManager().clearSelectedPath();
}
- public static WindowClosingProtocol.WindowClosingMode AWT2NWClosingOperation(int awtClosingOperation) {
+ static final HashMap<Integer, Cursor> cursorMap = new HashMap<Integer, Cursor>();
+ static final Cursor nulCursor;
+ static {
+ Cursor _nulCursor = null;
+ if( !JAWTUtil.isHeadlessMode() ) {
+ try {
+ final Toolkit toolkit = Toolkit.getDefaultToolkit();
+ final BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
+ _nulCursor = toolkit.createCustomCursor(img, new Point(0,0), "nullCursor");
+ } catch (final Exception he) {
+ if( JAWTUtil.DEBUG ) {
+ System.err.println("Caught exception: "+he.getMessage());
+ he.printStackTrace();
+ }
+ }
+ }
+ nulCursor = _nulCursor;
+ }
+
+ public static synchronized Cursor getNullCursor() { return nulCursor; }
+
+ public static synchronized Cursor getCursor(final PixelRectangle pixelrect, final Point hotSpot) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + pixelrect.hashCode();
+ hash = ((hash << 5) - hash) + hotSpot.hashCode();
+ final Integer key = Integer.valueOf(hash);
+
+ Cursor cursor = cursorMap.get(key);
+ if( null == cursor ) {
+ cursor = createCursor(pixelrect, hotSpot);
+ cursorMap.put(key, cursor);
+ }
+ return cursor;
+ }
+ private static synchronized Cursor createCursor(final PixelRectangle pixelrect, final Point hotSpot) {
+ final int width = pixelrect.getSize().getWidth();
+ final int height = pixelrect.getSize().getHeight();
+ final BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); // PixelFormat.BGRA8888
+ final PixelFormatUtil.PixelSink32 imgSink = new PixelFormatUtil.PixelSink32() {
+ public void store(final int x, final int y, final int pixel) {
+ img.setRGB(x, y, pixel);
+ }
+ @Override
+ public final PixelFormat getPixelformat() {
+ return PixelFormat.BGRA8888;
+ }
+ @Override
+ public int getStride() {
+ return width*4;
+ }
+ @Override
+ public final boolean isGLOriented() {
+ return false;
+ }
+ };
+ PixelFormatUtil.convert32(imgSink, pixelrect);
+ final Toolkit toolkit = Toolkit.getDefaultToolkit();
+ return toolkit.createCustomCursor(img, hotSpot, pixelrect.toString());
+ }
+
+ public static WindowClosingProtocol.WindowClosingMode AWT2NWClosingOperation(final int awtClosingOperation) {
switch (awtClosingOperation) {
case WindowConstants.DISPOSE_ON_CLOSE:
case WindowConstants.EXIT_ON_CLOSE:
@@ -88,7 +246,7 @@ public class AWTMisc {
}
}
- public static WindowClosingProtocol.WindowClosingMode getNWClosingOperation(Component c) {
+ public static WindowClosingProtocol.WindowClosingMode getNWClosingOperation(final Component c) {
final JFrame jf = getJFrame(c);
final int op = (null != jf) ? jf.getDefaultCloseOperation() : WindowConstants.DO_NOTHING_ON_CLOSE ;
return AWT2NWClosingOperation(op);
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTJNILibLoader.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTJNILibLoader.java
index f579da217..8aaffbd84 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTJNILibLoader.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTJNILibLoader.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -47,15 +47,16 @@ import java.awt.Toolkit;
import java.security.AccessController;
import java.security.PrivilegedAction;
-public class JAWTJNILibLoader extends NWJNILibLoader {
+public class JAWTJNILibLoader extends NWJNILibLoader {
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
// Make sure that awt.dll is loaded before loading jawt.dll. Otherwise
// a Dialog with "awt.dll not found" might pop up.
// See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4481947.
Toolkit.getDefaultToolkit();
-
+
// Must pre-load JAWT on all non-Mac platforms to
// ensure references from jogl_awt shared object
// will succeed since JAWT shared object isn't in
@@ -63,7 +64,7 @@ public class JAWTJNILibLoader extends NWJNILibLoader {
if ( NativeWindowFactory.TYPE_MACOSX != NativeWindowFactory.getNativeWindowType(false) ) {
try {
loadLibrary("jawt", null, true, JAWTJNILibLoader.class.getClassLoader());
- } catch (Throwable t) {
+ } catch (final Throwable t) {
// It might be ok .. if it's already loaded
if(DEBUG) {
t.printStackTrace();
@@ -74,9 +75,9 @@ public class JAWTJNILibLoader extends NWJNILibLoader {
}
});
}
-
+
public static void initSingleton() {
- // just exist to ensure static init has been run
+ // just exist to ensure static init has been run
}
-
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
index f1e8a786a..231a89c26 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -38,6 +38,8 @@
package jogamp.nativewindow.jawt;
import java.awt.EventQueue;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.lang.reflect.InvocationTargetException;
@@ -51,23 +53,30 @@ import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ToolkitLock;
+import jogamp.common.os.PlatformPropsImpl;
import jogamp.nativewindow.Debug;
+import jogamp.nativewindow.NWJNILibLoader;
import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
public class JAWTUtil {
public static final boolean DEBUG = Debug.debug("JAWT");
+ private static final boolean SKIP_AWT_HIDPI;
+
/** OSX JAWT version option to use CALayer */
public static final int JAWT_MACOSX_USE_CALAYER = 0x80000000;
-
+
/** OSX JAWT CALayer availability on Mac OS X >= 10.6 Update 4 (recommended) */
public static final VersionNumber JAWT_MacOSXCALayerMinVersion = new VersionNumber(10,6,4);
-
+
/** OSX JAWT CALayer required with Java >= 1.7.0 (implies OS X >= 10.7 */
- public static final VersionNumber JAWT_MacOSXCALayerRequiredForJavaVersion = new VersionNumber(1,7,0);
-
+ public static final VersionNumber JAWT_MacOSXCALayerRequiredForJavaVersion = Platform.Version17;
+
// See whether we're running in headless mode
private static final boolean headlessMode;
private static final JAWT jawtLockObject;
@@ -80,75 +89,196 @@ public class JAWTUtil {
private static final Method sunToolkitAWTUnlockMethod;
private static final boolean hasSunToolkitAWTLock;
+ private static final RecursiveLock jawtLock;
private static final ToolkitLock jawtToolkitLock;
+ private static final Method getScaleFactorMethod;
+
private static class PrivilegedDataBlob1 {
PrivilegedDataBlob1() {
ok = false;
- }
- Method sunToolkitAWTLockMethod;
- Method sunToolkitAWTUnlockMethod;
+ }
+ Method sunToolkitAWTLockMethod;
+ Method sunToolkitAWTUnlockMethod;
+ Method getScaleFactorMethod;
boolean ok;
}
-
+
/**
* Returns true if this platform's JAWT implementation supports offscreen layer.
*/
public static boolean isOffscreenLayerSupported() {
- return Platform.OS_TYPE == Platform.OSType.MACOS &&
- Platform.OS_VERSION_NUMBER.compareTo(JAWTUtil.JAWT_MacOSXCALayerMinVersion) >= 0;
+ return PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS &&
+ PlatformPropsImpl.OS_VERSION_NUMBER.compareTo(JAWTUtil.JAWT_MacOSXCALayerMinVersion) >= 0;
}
-
+
/**
* Returns true if this platform's JAWT implementation requires using offscreen layer.
*/
public static boolean isOffscreenLayerRequired() {
- return Platform.OS_TYPE == Platform.OSType.MACOS &&
- Platform.JAVA_VERSION_NUMBER.compareTo(JAWT_MacOSXCALayerRequiredForJavaVersion)>=0;
+ return PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS &&
+ PlatformPropsImpl.JAVA_VERSION_NUMBER.compareTo(JAWT_MacOSXCALayerRequiredForJavaVersion)>=0;
}
-
+
+ /**
+ * CALayer size needs to be set using the AWT component size.
+ * <p>
+ * AWT's super-calayer, i.e. the AWT's own component CALayer,
+ * does not layout our root-calayer in respect to this component's
+ * position and size, at least when resizing programmatically.
+ * </p>
+ * <p>
+ * As of today, this flag is enabled for all known AWT versions.
+ * </p>
+ * <p>
+ * Sync w/ NativeWindowProtocols.h
+ * </p>
+ */
+ public static final int JAWT_OSX_CALAYER_QUIRK_SIZE = 1 << 0;
+
+ /**
+ * CALayer position needs to be set to zero.
+ * <p>
+ * AWT's super-calayer, i.e. the AWT's own component CALayer,
+ * has a broken layout and needs it's sub-layers to be located at position 0/0.
+ * </p>
+ * <p>
+ * See <code>http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7172187</code>.
+ * </p>
+ * <p>
+ * Further more a re-layout seems to be required in this case,
+ * i.e. a programmatic forced resize +1 and it's inverted resize -1.
+ * </p>
+ * <p>
+ * This flag is enabled w/ AWT < 1.7.0_40.
+ * </p>
+ * <p>
+ * Sync w/ NativeWindowProtocols.h
+ * </p>
+ */
+ public static final int JAWT_OSX_CALAYER_QUIRK_POSITION = 1 << 1;
+
+ /**
+ * CALayer position needs to be derived from AWT position
+ * in relation to super CALayer.
+ * <p>
+ * AWT's super-calayer, i.e. the AWT top-container's CALayer,
+ * does not layout our root-calayer in respect to this component's
+ * position and size, at least when resizing programmatically.
+ * </p>
+ * <p>
+ * CALayer position has origin 0/0 at bottom/left,
+ * where AWT component has origin 0/0 at top/left.
+ * </p>
+ * <p>
+ * The super-calayer bounds exclude the frame's heavyweight border/insets.
+ * </p>
+ * <p>
+ * The super-calayer lies within the AWT top-container client space (content).
+ * </p>
+ * <p>
+ * Component's location in super-calayer:
+ * <pre>
+ p0 = c.locationOnScreen();
+ p0 -= c.getOutterComp.getPos();
+ p0 -= c.getOutterComp.getInsets();
+ * </pre>
+ * Where 'locationOnScreen()' is:
+ * <pre>
+ p0 = 0/0;
+ while( null != c ) {
+ p0 += c.getPos();
+ }
+ * </pre>
+ * </p>
+ * <p>
+ * This flags also sets {@link #JAWT_OSX_CALAYER_QUIRK_SIZE},
+ * i.e. they are related.
+ * </p>
+ * <p>
+ * As of today, this flag is enabled for w/ AWT >= 1.7.0_40.
+ * </p>
+ * <p>
+ * Sync w/ NativeWindowProtocols.h
+ * </p>
+ */
+ public static final int JAWT_OSX_CALAYER_QUIRK_LAYOUT = 1 << 2;
+
+ /**
+ * Returns bitfield of required JAWT OSX CALayer quirks to mediate AWT impl. bugs.
+ * <p>
+ * Returns zero, if platform is not {@link Platform.OSType#MACOS}
+ * or not supporting CALayer, i.e. OSX < 10.6.4.
+ * </p>
+ * <p>
+ * Otherwise includes
+ * <ul>
+ * <li>{@link #JAWT_OSX_CALAYER_QUIRK_SIZE} (always)</li>
+ * <li>{@link #JAWT_OSX_CALAYER_QUIRK_POSITION} if JVM < 1.7.0_40</li>
+ * <li>{@link #JAWT_OSX_CALAYER_QUIRK_LAYOUT} if JVM >= 1.7.0_40</li>
+ * </ul>
+ * </p>
+ */
+ public static int getOSXCALayerQuirks() {
+ int res = 0;
+ if( PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS &&
+ PlatformPropsImpl.OS_VERSION_NUMBER.compareTo(JAWTUtil.JAWT_MacOSXCALayerMinVersion) >= 0 ) {
+
+ /** Knowing impl. all expose the SIZE bug */
+ res |= JAWT_OSX_CALAYER_QUIRK_SIZE;
+
+ final int c = PlatformPropsImpl.JAVA_VERSION_NUMBER.compareTo(PlatformPropsImpl.Version17);
+ if( c < 0 || c == 0 && PlatformPropsImpl.JAVA_VERSION_UPDATE < 40 ) {
+ res |= JAWT_OSX_CALAYER_QUIRK_POSITION;
+ } else {
+ res |= JAWT_OSX_CALAYER_QUIRK_LAYOUT;
+ }
+ }
+ return res;
+ }
+
/**
* @param useOffscreenLayerIfAvailable
* @return
*/
- public static JAWT getJAWT(boolean useOffscreenLayerIfAvailable) {
- final int jawt_version_flags = JAWTFactory.JAWT_VERSION_1_4;
- JAWT jawt = JAWT.create();
-
+ public static JAWT getJAWT(final boolean useOffscreenLayerIfAvailable) {
+ final int jawt_version_flags = JAWTFactory.JAWT_VERSION_1_4;
+ final JAWT jawt = JAWT.create();
+
// default queries
boolean tryOffscreenLayer;
boolean tryOnscreen;
int jawt_version_flags_offscreen = jawt_version_flags;
-
+
if(isOffscreenLayerRequired()) {
- if(Platform.OS_TYPE == Platform.OSType.MACOS) {
- if(Platform.OS_VERSION_NUMBER.compareTo(JAWTUtil.JAWT_MacOSXCALayerMinVersion) >= 0) {
+ if(PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS) {
+ if(PlatformPropsImpl.OS_VERSION_NUMBER.compareTo(JAWTUtil.JAWT_MacOSXCALayerMinVersion) >= 0) {
jawt_version_flags_offscreen |= JAWTUtil.JAWT_MACOSX_USE_CALAYER;
tryOffscreenLayer = true;
tryOnscreen = false;
} else {
- throw new RuntimeException("OSX: Invalid version of Java ("+Platform.JAVA_VERSION_NUMBER+") / OS X ("+Platform.OS_VERSION_NUMBER+")");
+ throw new RuntimeException("OSX: Invalid version of Java ("+PlatformPropsImpl.JAVA_VERSION_NUMBER+") / OS X ("+PlatformPropsImpl.OS_VERSION_NUMBER+")");
}
} else {
- throw new InternalError("offscreen required, but n/a for: "+Platform.OS_TYPE);
+ throw new InternalError("offscreen required, but n/a for: "+PlatformPropsImpl.OS_TYPE);
}
} else if(useOffscreenLayerIfAvailable && isOffscreenLayerSupported()) {
- if(Platform.OS_TYPE == Platform.OSType.MACOS) {
+ if(PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS) {
jawt_version_flags_offscreen |= JAWTUtil.JAWT_MACOSX_USE_CALAYER;
tryOffscreenLayer = true;
tryOnscreen = true;
} else {
- throw new InternalError("offscreen requested and supported, but n/a for: "+Platform.OS_TYPE);
+ throw new InternalError("offscreen requested and supported, but n/a for: "+PlatformPropsImpl.OS_TYPE);
}
} else {
tryOffscreenLayer = false;
tryOnscreen = true;
- }
+ }
if(DEBUG) {
System.err.println("JAWTUtil.getJAWT(tryOffscreenLayer "+tryOffscreenLayer+", tryOnscreen "+tryOnscreen+")");
}
-
- StringBuilder errsb = new StringBuilder();
+
+ final StringBuilder errsb = new StringBuilder();
if(tryOffscreenLayer) {
errsb.append("Offscreen 0x").append(Integer.toHexString(jawt_version_flags_offscreen));
if( JAWT.getJAWT(jawt, jawt_version_flags_offscreen) ) {
@@ -162,82 +292,118 @@ public class JAWTUtil {
errsb.append("Onscreen 0x").append(Integer.toHexString(jawt_version_flags));
if( JAWT.getJAWT(jawt, jawt_version_flags) ) {
return jawt;
- }
+ }
}
throw new RuntimeException("Unable to initialize JAWT, trials: "+errsb.toString());
}
-
- public static boolean isJAWTUsingOffscreenLayer(JAWT jawt) {
+
+ public static boolean isJAWTUsingOffscreenLayer(final JAWT jawt) {
return 0 != ( jawt.getCachedVersion() & JAWTUtil.JAWT_MACOSX_USE_CALAYER );
}
-
+
static {
+ SKIP_AWT_HIDPI = PropertyAccess.isPropertyDefined("nativewindow.awt.nohidpi", true);
+
if(DEBUG) {
- System.err.println("JAWTUtil initialization (JAWT/JNI/...");
+ System.err.println("JAWTUtil initialization (JAWT/JNI/...); SKIP_AWT_HIDPI "+SKIP_AWT_HIDPI);
// Thread.dumpStack();
}
- JAWTJNILibLoader.initSingleton();
- if(!JAWTJNILibLoader.loadNativeWindow("awt")) {
- throw new NativeWindowException("NativeWindow AWT native library load error.");
- }
headlessMode = GraphicsEnvironment.isHeadless();
- boolean ok = false;
- Class<?> jC = null;
- Method m = null;
- if (!headlessMode) {
+
+ if( headlessMode ) {
+ // Headless case
+ jawtLockObject = null;
+ isQueueFlusherThread = null;
+ j2dExist = false;
+ sunToolkitAWTLockMethod = null;
+ sunToolkitAWTUnlockMethod = null;
+ hasSunToolkitAWTLock = false;
+ // hasSunToolkitAWTLock = false;
+ getScaleFactorMethod = null;
+ } else {
+ // Non-headless case
+ JAWTJNILibLoader.initSingleton(); // load libjawt.so
+ if(!NWJNILibLoader.loadNativeWindow("awt")) { // load libnativewindow_awt.so
+ throw new NativeWindowException("NativeWindow AWT native library load error.");
+ }
jawtLockObject = getJAWT(false); // don't care for offscreen layer here
+
+ boolean j2dExistTmp = false;
+ Class<?> java2DClass = null;
+ Method isQueueFlusherThreadTmp = null;
try {
- jC = Class.forName("jogamp.opengl.awt.Java2D");
- m = jC.getMethod("isQueueFlusherThread", (Class[])null);
- ok = true;
- } catch (Exception e) {
+ java2DClass = Class.forName("jogamp.opengl.awt.Java2D");
+ isQueueFlusherThreadTmp = java2DClass.getMethod("isQueueFlusherThread", (Class[])null);
+ j2dExistTmp = true;
+ } catch (final Exception e) {
}
- } else {
- jawtLockObject = null; // headless !
- }
- isQueueFlusherThread = m;
- j2dExist = ok;
-
- PrivilegedDataBlob1 pdb1 = (PrivilegedDataBlob1) AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- PrivilegedDataBlob1 d = new PrivilegedDataBlob1();
- try {
- final Class<?> sunToolkitClass = Class.forName("sun.awt.SunToolkit");
- d.sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[]{});
- d.sunToolkitAWTLockMethod.setAccessible(true);
- d.sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[]{});
- d.sunToolkitAWTUnlockMethod.setAccessible(true);
- d.ok=true;
- } catch (Exception e) {
- // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
+ isQueueFlusherThread = isQueueFlusherThreadTmp;
+ j2dExist = j2dExistTmp;
+
+ final PrivilegedDataBlob1 pdb1 = (PrivilegedDataBlob1) AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ final PrivilegedDataBlob1 d = new PrivilegedDataBlob1();
+ try {
+ final Class<?> sunToolkitClass = Class.forName("sun.awt.SunToolkit");
+ d.sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[]{});
+ d.sunToolkitAWTLockMethod.setAccessible(true);
+ d.sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[]{});
+ d.sunToolkitAWTUnlockMethod.setAccessible(true);
+ d.ok=true;
+ } catch (final Exception e) {
+ // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
+ }
+ try {
+ final GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
+ d.getScaleFactorMethod = gd.getClass().getDeclaredMethod("getScaleFactor");
+ d.getScaleFactorMethod.setAccessible(true);
+ } catch (final Throwable t) {}
+ return d;
+ }
+ });
+ sunToolkitAWTLockMethod = pdb1.sunToolkitAWTLockMethod;
+ sunToolkitAWTUnlockMethod = pdb1.sunToolkitAWTUnlockMethod;
+ getScaleFactorMethod = pdb1.getScaleFactorMethod;
+
+ boolean _hasSunToolkitAWTLock = false;
+ if ( pdb1.ok ) {
+ try {
+ sunToolkitAWTLockMethod.invoke(null, (Object[])null);
+ sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
+ _hasSunToolkitAWTLock = true;
+ } catch (final Exception e) {
}
- return d;
- }
- });
- sunToolkitAWTLockMethod = pdb1.sunToolkitAWTLockMethod;
- sunToolkitAWTUnlockMethod = pdb1.sunToolkitAWTUnlockMethod;
-
- boolean _hasSunToolkitAWTLock = false;
- if ( pdb1.ok ) {
- try {
- sunToolkitAWTLockMethod.invoke(null, (Object[])null);
- sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
- _hasSunToolkitAWTLock = true;
- } catch (Exception e) {
}
+ hasSunToolkitAWTLock = _hasSunToolkitAWTLock;
+ // hasSunToolkitAWTLock = false;
}
- hasSunToolkitAWTLock = _hasSunToolkitAWTLock;
- // hasSunToolkitAWTLock = false;
+
+ jawtLock = LockFactory.createRecursiveLock();
jawtToolkitLock = new ToolkitLock() {
+ @Override
public final void lock() {
JAWTUtil.lockToolkit();
- }
+ }
+ @Override
public final void unlock() {
JAWTUtil.unlockToolkit();
}
- };
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ JAWTUtil.validateLocked();
+ }
+ @Override
+ public final void dispose() {
+ // nop
+ }
+ @Override
+ public String toString() {
+ return "JAWTToolkitLock[obj 0x"+Integer.toHexString(hashCode())+", isOwner "+jawtLock.isOwner(Thread.currentThread())+", "+jawtLock+"]";
+ }
+ };
// trigger native AWT toolkit / properties initialization
Map<?,?> desktophints = null;
@@ -247,8 +413,9 @@ public class JAWTUtil {
} else {
final ArrayList<Map<?,?>> desktophintsBucket = new ArrayList<Map<?,?>>(1);
EventQueue.invokeAndWait(new Runnable() {
+ @Override
public void run() {
- Map<?,?> _desktophints = (Map<?,?>)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints"));
+ final Map<?,?> _desktophints = (Map<?,?>)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints"));
if(null!=_desktophints) {
desktophintsBucket.add(_desktophints);
}
@@ -256,9 +423,9 @@ public class JAWTUtil {
});
desktophints = ( desktophintsBucket.size() > 0 ) ? desktophintsBucket.get(0) : null ;
}
- } catch (InterruptedException ex) {
+ } catch (final InterruptedException ex) {
ex.printStackTrace();
- } catch (InvocationTargetException ex) {
+ } catch (final InvocationTargetException ex) {
ex.printStackTrace();
}
@@ -266,7 +433,7 @@ public class JAWTUtil {
System.err.println("JAWTUtil: Has sun.awt.SunToolkit.awtLock/awtUnlock " + hasSunToolkitAWTLock);
System.err.println("JAWTUtil: Has Java2D " + j2dExist);
System.err.println("JAWTUtil: Is headless " + headlessMode);
- int hints = ( null != desktophints ) ? desktophints.size() : 0 ;
+ final int hints = ( null != desktophints ) ? desktophints.size() : 0 ;
System.err.println("JAWTUtil: AWT Desktop hints " + hints);
System.err.println("JAWTUtil: OffscreenLayer Supported: "+isOffscreenLayerSupported()+" - Required "+isOffscreenLayerRequired());
}
@@ -278,11 +445,11 @@ public class JAWTUtil {
public static void initSingleton() {
// just exist to ensure static init has been run
}
-
+
/**
* Called by {@link NativeWindowFactory#shutdown()}
*/
- public static void shutdown() {
+ public static void shutdown() {
}
public static boolean hasJava2D() {
@@ -294,7 +461,7 @@ public class JAWTUtil {
if(j2dExist) {
try {
b = ((Boolean)isQueueFlusherThread.invoke(null, (Object[])null)).booleanValue();
- } catch (Exception e) {}
+ } catch (final Exception e) {}
}
return b;
}
@@ -304,58 +471,123 @@ public class JAWTUtil {
}
/**
- * Locks the AWT's global ReentrantLock.<br>
- *
+ * Locks the AWT's global ReentrantLock.
+ * <p>
* JAWT's native Lock() function calls SunToolkit.awtLock(),
- * which just uses AWT's global ReentrantLock.<br>
+ * which just uses AWT's global ReentrantLock.
+ * </p>
+ * <p>
+ * AWT locking is wrapped through a recursive lock object.
+ * </p>
*/
- private static void awtLock() {
- if(hasSunToolkitAWTLock) {
- try {
- sunToolkitAWTLockMethod.invoke(null, (Object[])null);
- } catch (Exception e) {
- throw new NativeWindowException("SunToolkit.awtLock failed", e);
+ public static void lockToolkit() throws NativeWindowException {
+ jawtLock.lock();
+ if( 1 == jawtLock.getHoldCount() ) {
+ if(!headlessMode && !isJava2DQueueFlusherThread()) {
+ if(hasSunToolkitAWTLock) {
+ try {
+ sunToolkitAWTLockMethod.invoke(null, (Object[])null);
+ } catch (final Exception e) {
+ throw new NativeWindowException("SunToolkit.awtLock failed", e);
+ }
+ } else {
+ jawtLockObject.Lock();
+ }
}
- } else {
- jawtLockObject.Lock();
}
+ if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.lock(): "+jawtLock); }
}
/**
- * Unlocks the AWT's global ReentrantLock.<br>
- *
+ * Unlocks the AWT's global ReentrantLock.
+ * <p>
* JAWT's native Unlock() function calls SunToolkit.awtUnlock(),
- * which just uses AWT's global ReentrantLock.<br>
+ * which just uses AWT's global ReentrantLock.
+ * </p>
+ * <p>
+ * AWT unlocking is wrapped through a recursive lock object.
+ * </p>
*/
- private static void awtUnlock() {
- if(hasSunToolkitAWTLock) {
- try {
- sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
- } catch (Exception e) {
- throw new NativeWindowException("SunToolkit.awtUnlock failed", e);
+ public static void unlockToolkit() {
+ jawtLock.validateLocked();
+ if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.unlock(): "+jawtLock); }
+ if( 1 == jawtLock.getHoldCount() ) {
+ if(!headlessMode && !isJava2DQueueFlusherThread()) {
+ if(hasSunToolkitAWTLock) {
+ try {
+ sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
+ } catch (final Exception e) {
+ throw new NativeWindowException("SunToolkit.awtUnlock failed", e);
+ }
+ } else {
+ jawtLockObject.Unlock();
+ }
}
- } else {
- jawtLockObject.Unlock();
}
+ jawtLock.unlock();
}
- public static void lockToolkit() throws NativeWindowException {
- if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.lock()"); }
- if(!headlessMode && !isJava2DQueueFlusherThread()) {
- awtLock();
- }
- }
-
- public static void unlockToolkit() {
- if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.unlock()"); }
- if(!headlessMode && !isJava2DQueueFlusherThread()) {
- awtUnlock();
- }
+ public static final void validateLocked() throws RuntimeException {
+ jawtLock.validateLocked();
}
public static ToolkitLock getJAWTToolkitLock() {
return jawtToolkitLock;
}
-
+
+ /**
+ * Returns the pixel scale factor of the given {@link GraphicsDevice}, if supported.
+ * <p>
+ * If the component does not support pixel scaling the default
+ * <code>one</code> is returned.
+ * </p>
+ * <p>
+ * Note: Currently only supported on OSX since 1.7.0_40 for HiDPI retina displays
+ * </p>
+ * @param device the {@link GraphicsDevice} instance used to query the pixel scale
+ * @return the pixel scale factor
+ */
+ public static final int getPixelScale(final GraphicsDevice device) {
+ if( !SKIP_AWT_HIDPI ) {
+ if( null != getScaleFactorMethod ) {
+ try {
+ final Object res = getScaleFactorMethod.invoke(device);
+ if (res instanceof Integer) {
+ return ((Integer)res).intValue();
+ }
+ } catch (final Throwable t) {}
+ }
+ }
+ return 1;
+ }
+
+ /**
+ * Returns the pixel scale factor of the given {@link GraphicsConfiguration}'s {@link GraphicsDevice}, if supported.
+ * <p>
+ * If the {@link GraphicsDevice} is <code>null</code>, <code>zero</code> is returned.
+ * </p>
+ * <p>
+ * If the component does not support pixel scaling the default
+ * <code>one</code> is returned.
+ * </p>
+ * <p>
+ * Note: Currently only supported on OSX since 1.7.0_40 for HiDPI retina displays
+ * </p>
+ * @param gc the {@link GraphicsConfiguration} instance used to query the pixel scale
+ * @return the pixel scale factor
+ */
+ public static final int getPixelScale(final GraphicsConfiguration gc) {
+ final GraphicsDevice device = null != gc ? gc.getDevice() : null;
+ final int ps;
+ if( null == device ) {
+ ps = 0;
+ } else {
+ ps = JAWTUtil.getPixelScale(device);
+ }
+ if( DEBUG ) {
+ System.err.println("JAWTUtil.updatePixelScale: Fetched "+ps);
+ }
+ return ps;
+ }
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWT_PlatformInfo.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWT_PlatformInfo.java
index 40d7b8032..4f12d1925 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWT_PlatformInfo.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWT_PlatformInfo.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
index 5fd242247..fae8db52a 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,30 +29,35 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package jogamp.nativewindow.jawt.macosx;
+import java.awt.Component;
import java.nio.Buffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.MutableSurface;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.nativewindow.awt.JAWTWindow;
+import jogamp.nativewindow.Debug;
+import jogamp.nativewindow.awt.AWTMisc;
import jogamp.nativewindow.jawt.JAWT;
import jogamp.nativewindow.jawt.JAWTFactory;
import jogamp.nativewindow.jawt.JAWTUtil;
@@ -62,72 +67,191 @@ import jogamp.nativewindow.jawt.macosx.JAWT_MacOSXDrawingSurfaceInfo;
import jogamp.nativewindow.macosx.OSXUtil;
public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
- public MacOSXJAWTWindow(Object comp, AbstractGraphicsConfiguration config) {
+ /** May lead to deadlock, due to AWT pos comparison .. don't enable for Applets! */
+ private static final boolean DEBUG_CALAYER_POS_CRITICAL;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_CALAYER_POS_CRITICAL = PropertyAccess.isPropertyDefined("nativewindow.debug.JAWT.OSXCALayerPos", true /* jnlpAlias */);
+ }
+
+ public MacOSXJAWTWindow(final Object comp, final AbstractGraphicsConfiguration config) {
super(comp, config);
if(DEBUG) {
dumpInfo();
}
}
+ @Override
protected void invalidateNative() {
- offscreenSurfaceHandle=0;
- offscreenSurfaceHandleSet=false;
- if(isOffscreenLayerSurfaceEnabled()) {
- if(0 != rootSurfaceLayerHandle) {
- OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
- rootSurfaceLayerHandle = 0;
- }
+ if(DEBUG) {
+ System.err.println("MacOSXJAWTWindow.invalidateNative(): osh-enabled "+isOffscreenLayerSurfaceEnabled()+
+ ", osd-set "+offscreenSurfaceDrawableSet+
+ ", osd "+toHexString(offscreenSurfaceDrawable)+
+ ", osl "+toHexString(getAttachedSurfaceLayer())+
+ ", rsl "+toHexString(rootSurfaceLayer)+
+ ", wh "+toHexString(windowHandle)+" - "+Thread.currentThread().getName());
+ }
+ offscreenSurfaceDrawable=0;
+ offscreenSurfaceDrawableSet=false;
+ if( isOffscreenLayerSurfaceEnabled() ) {
if(0 != windowHandle) {
OSXUtil.DestroyNSWindow(windowHandle);
}
+ OSXUtil.RunOnMainThread(false, true /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ if( 0 != rootSurfaceLayer ) {
+ if( 0 != jawtSurfaceLayersHandle) {
+ UnsetJAWTRootSurfaceLayer0(jawtSurfaceLayersHandle, rootSurfaceLayer);
+ }
+ OSXUtil.DestroyCALayer(rootSurfaceLayer);
+ rootSurfaceLayer = 0;
+ }
+ jawtSurfaceLayersHandle = 0;
+ }
+ });
}
windowHandle=0;
}
+ @Override
+ public void setSurfaceScale(final int[] pixelScale) {
+ super.setSurfaceScale(pixelScale);
+ if( 0 != getWindowHandle() ) { // locked at least once !
+ final int hadPixelScaleX = getPixelScaleX();
+ updatePixelScale();
+
+ if( hadPixelScaleX != getPixelScaleX() && 0 != getAttachedSurfaceLayer() ) {
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ final long osl = getAttachedSurfaceLayer();
+ if( 0 != osl ) {
+ OSXUtil.SetCALayerPixelScale(rootSurfaceLayer, osl, getPixelScaleX());
+ }
+ }
+ });
+ }
+ }
+ }
+
+ @Override
protected void attachSurfaceLayerImpl(final long layerHandle) {
- OSXUtil.AddCASublayer(rootSurfaceLayerHandle, layerHandle);
+ OSXUtil.RunOnMainThread(false, false /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ // AWT position is top-left w/ insets, where CALayer position is bottom/left from root CALayer w/o insets.
+ // Determine p0: components location on screen w/o insets.
+ // CALayer position will be determined in native code.
+ // See detailed description in {@link JAWTUtil#JAWT_OSX_CALAYER_QUIRK_LAYOUT}
+ final Point p0 = new Point();
+ final Component outterComp = getLocationOnScreenNonBlocking(p0, component);
+ final java.awt.Insets outterInsets = AWTMisc.getInsets(outterComp, true);
+ final Point p1 = (Point)p0.cloneMutable();
+ p1.translate(-outterComp.getX(), -outterComp.getY());
+ if( null != outterInsets ) {
+ p1.translate(-outterInsets.left, -outterInsets.top);
+ }
+
+ if( DEBUG_CALAYER_POS_CRITICAL ) {
+ final java.awt.Point pA0 = component.getLocationOnScreen();
+ final Point pA1 = new Point(pA0.x, pA0.y);
+ pA1.translate(-outterComp.getX(), -outterComp.getY());
+ if( null != outterInsets ) {
+ pA1.translate(-outterInsets.left, -outterInsets.top);
+ }
+ System.err.println("JAWTWindow.attachSurfaceLayerImpl: "+toHexString(layerHandle) + ", [ins "+outterInsets+"], pA "+pA0+" -> "+pA1+
+ ", p0 "+p0+" -> "+p1+", bounds "+bounds);
+ } else if( DEBUG ) {
+ System.err.println("JAWTWindow.attachSurfaceLayerImpl: "+toHexString(layerHandle) + ", [ins "+outterInsets+"], p0 "+p0+" -> "+p1+", bounds "+bounds);
+ }
+ // HiDPI: uniform pixel scale
+ OSXUtil.AddCASublayer(rootSurfaceLayer, layerHandle, p1.getX(), p1.getY(), getWidth(), getHeight(), getPixelScaleX(), JAWTUtil.getOSXCALayerQuirks());
+ } } );
+ }
+
+ @Override
+ protected void layoutSurfaceLayerImpl(final long layerHandle, final boolean visible) {
+ final int caLayerQuirks = JAWTUtil.getOSXCALayerQuirks();
+ // AWT position is top-left w/ insets, where CALayer position is bottom/left from root CALayer w/o insets.
+ // Determine p0: components location on screen w/o insets.
+ // CALayer position will be determined in native code.
+ // See detailed description in {@link JAWTUtil#JAWT_OSX_CALAYER_QUIRK_LAYOUT}
+ final Point p0 = new Point();
+ final Component outterComp = getLocationOnScreenNonBlocking(p0, component);
+ final java.awt.Insets outterInsets = AWTMisc.getInsets(outterComp, true);
+ final Point p1 = (Point)p0.cloneMutable();
+ p1.translate(-outterComp.getX(), -outterComp.getY());
+ if( null != outterInsets ) {
+ p1.translate(-outterInsets.left, -outterInsets.top);
+ }
+
+ if( DEBUG_CALAYER_POS_CRITICAL ) {
+ final java.awt.Point pA0 = component.getLocationOnScreen();
+ final Point pA1 = new Point(pA0.x, pA0.y);
+ pA1.translate(-outterComp.getX(), -outterComp.getY());
+ if( null != outterInsets ) {
+ pA1.translate(-outterInsets.left, -outterInsets.top);
+ }
+ System.err.println("JAWTWindow.layoutSurfaceLayerImpl: "+toHexString(layerHandle) + ", quirks "+caLayerQuirks+", visible "+visible+
+ ", [ins "+outterInsets+"], pA "+pA0+" -> "+pA1+
+ ", p0 "+p0+" -> "+p1+", bounds "+bounds);
+ } else if( DEBUG ) {
+ System.err.println("JAWTWindow.layoutSurfaceLayerImpl: "+toHexString(layerHandle) + ", quirks "+caLayerQuirks+", visible "+visible+
+ ", [ins "+outterInsets+"], p0 "+p0+" -> "+p1+", bounds "+bounds);
+ }
+ OSXUtil.FixCALayerLayout(rootSurfaceLayer, layerHandle, visible, p1.getX(), p1.getY(), getWidth(), getHeight(), caLayerQuirks);
}
-
- protected void detachSurfaceLayerImpl(final long layerHandle) {
- OSXUtil.RemoveCASublayer(rootSurfaceLayerHandle, layerHandle);
+
+ @Override
+ protected void detachSurfaceLayerImpl(final long layerHandle, final Runnable detachNotify) {
+ OSXUtil.RunOnMainThread(false, true /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ detachNotify.run();
+ OSXUtil.RemoveCASublayer(rootSurfaceLayer, layerHandle);
+ } });
}
-
+
@Override
public final long getWindowHandle() {
return windowHandle;
}
-
+
@Override
public final long getSurfaceHandle() {
- return offscreenSurfaceHandleSet ? offscreenSurfaceHandle : drawable /* super.getSurfaceHandle() */ ;
+ return offscreenSurfaceDrawableSet ? offscreenSurfaceDrawable : drawable /* super.getSurfaceHandle() */ ;
}
-
- public void setSurfaceHandle(long surfaceHandle) {
+
+ @Override
+ public void setSurfaceHandle(final long surfaceHandle) {
if( !isOffscreenLayerSurfaceEnabled() ) {
throw new java.lang.UnsupportedOperationException("Not using CALAYER");
}
if(DEBUG) {
- System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
+ System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): "+toHexString(surfaceHandle));
}
- this.offscreenSurfaceHandle = surfaceHandle;
- this.offscreenSurfaceHandleSet = true;
+ this.offscreenSurfaceDrawable = surfaceHandle;
+ this.offscreenSurfaceDrawableSet = true;
}
+ @Override
protected JAWT fetchJAWTImpl() throws NativeWindowException {
// use offscreen if supported and [ applet or requested ]
return JAWTUtil.getJAWT(getShallUseOffscreenLayer() || isApplet());
}
+
+ @Override
protected int lockSurfaceImpl() throws NativeWindowException {
- int ret = NativeWindow.LOCK_SURFACE_NOT_READY;
- if(null == ds) {
- ds = getJAWT().GetDrawingSurface(component);
- if (ds == null) {
- // Widget not yet realized
- unlockSurfaceImpl();
- return NativeWindow.LOCK_SURFACE_NOT_READY;
- }
+ int ret = NativeSurface.LOCK_SURFACE_NOT_READY;
+ ds = getJAWT().GetDrawingSurface(component);
+ if (ds == null) {
+ // Widget not yet realized
+ unlockSurfaceImpl();
+ return NativeSurface.LOCK_SURFACE_NOT_READY;
}
- int res = ds.Lock();
+ final int res = ds.Lock();
dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ;
if (!dsLocked) {
unlockSurfaceImpl();
@@ -139,25 +263,24 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
// conditions can cause this code to be triggered -- should test
// more)
if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
- ret = NativeWindow.LOCK_SURFACE_CHANGED;
+ ret = NativeSurface.LOCK_SURFACE_CHANGED;
}
- if(null == dsi) {
- if (firstLock) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- dsi = ds.GetDrawingSurfaceInfo();
- return null;
- }
- });
- } else {
- dsi = ds.GetDrawingSurfaceInfo();
- }
- if (dsi == null) {
- unlockSurfaceImpl();
- return NativeWindow.LOCK_SURFACE_NOT_READY;
- }
+ if (firstLock) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ dsi = ds.GetDrawingSurfaceInfo();
+ return null;
+ }
+ });
+ } else {
+ dsi = ds.GetDrawingSurfaceInfo();
}
- updateBounds(dsi.getBounds());
+ if (dsi == null) {
+ unlockSurfaceImpl();
+ return NativeSurface.LOCK_SURFACE_NOT_READY;
+ }
+ updateLockedData(dsi.getBounds());
if (DEBUG && firstLock ) {
dumpInfo();
}
@@ -166,24 +289,24 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
macosxdsi = (JAWT_MacOSXDrawingSurfaceInfo) dsi.platformInfo(getJAWT());
if (macosxdsi == null) {
unlockSurfaceImpl();
- return NativeWindow.LOCK_SURFACE_NOT_READY;
+ return NativeSurface.LOCK_SURFACE_NOT_READY;
}
drawable = macosxdsi.getCocoaViewRef();
-
+
if (drawable == 0) {
unlockSurfaceImpl();
- return NativeWindow.LOCK_SURFACE_NOT_READY;
+ return NativeSurface.LOCK_SURFACE_NOT_READY;
} else {
windowHandle = OSXUtil.GetNSWindow(drawable);
- ret = NativeWindow.LOCK_SUCCESS;
+ ret = NativeSurface.LOCK_SUCCESS;
}
} else {
/**
* Only create a fake invisible NSWindow for the drawable handle
* to please frameworks requiring such (eg. NEWT).
- *
- * The actual surface/ca-layer shall be created/attached
- * by the upper framework (JOGL) since they require more information.
+ *
+ * The actual surface/ca-layer shall be created/attached
+ * by the upper framework (JOGL) since they require more information.
*/
String errMsg = null;
if(0 == drawable) {
@@ -193,31 +316,44 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
} else {
drawable = OSXUtil.GetNSView(windowHandle);
if(0 == drawable) {
- errMsg = "Null NSView of NSWindow 0x"+Long.toHexString(windowHandle);
+ errMsg = "Null NSView of NSWindow "+toHexString(windowHandle);
}
}
if(null == errMsg) {
- // fix caps reflecting offscreen! (no GL available here ..)
- Capabilities caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable();
+ // Fix caps reflecting offscreen! (no GL available here ..)
+ final Capabilities caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable();
caps.setOnscreen(false);
setChosenCapabilities(caps);
}
}
if(null == errMsg) {
- if(0 == rootSurfaceLayerHandle) {
- rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
- if(0 == rootSurfaceLayerHandle) {
- errMsg = "Could not create root CALayer";
- } else if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) {
- errMsg = "Could not set JAWT rootSurfaceLayerHandle 0x"+Long.toHexString(rootSurfaceLayerHandle);
- }
- }
+ jawtSurfaceLayersHandle = GetJAWTSurfaceLayersHandle0(dsi.getBuffer());
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ String errMsg = null;
+ if(0 == rootSurfaceLayer && 0 != jawtSurfaceLayersHandle) {
+ rootSurfaceLayer = OSXUtil.CreateCALayer(bounds.getWidth(), bounds.getHeight(), getPixelScaleX()); // HiDPI: uniform pixel scale
+ if(0 == rootSurfaceLayer) {
+ errMsg = "Could not create root CALayer";
+ } else {
+ try {
+ SetJAWTRootSurfaceLayer0(jawtSurfaceLayersHandle, rootSurfaceLayer);
+ } catch(final Exception e) {
+ errMsg = "Could not set JAWT rootSurfaceLayerHandle "+toHexString(rootSurfaceLayer)+", cause: "+e.getMessage();
+ }
+ }
+ if(null != errMsg) {
+ if(0 != rootSurfaceLayer) {
+ OSXUtil.DestroyCALayer(rootSurfaceLayer);
+ rootSurfaceLayer = 0;
+ }
+ throw new NativeWindowException(errMsg+": "+MacOSXJAWTWindow.this);
+ }
+ }
+ } } );
}
if(null != errMsg) {
- if(0 != rootSurfaceLayerHandle) {
- OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
- rootSurfaceLayerHandle = 0;
- }
if(0 != windowHandle) {
OSXUtil.DestroyNSWindow(windowHandle);
windowHandle = 0;
@@ -226,12 +362,13 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
unlockSurfaceImpl();
throw new NativeWindowException(errMsg+": "+this);
}
- ret = NativeWindow.LOCK_SUCCESS;
+ ret = NativeSurface.LOCK_SUCCESS;
}
-
+
return ret;
}
-
+
+ @Override
protected void unlockSurfaceImpl() throws NativeWindowException {
if(null!=ds) {
if (null!=dsi) {
@@ -250,7 +387,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
System.err.println("MaxOSXJAWTWindow: 0x"+Integer.toHexString(this.hashCode())+" - thread: "+Thread.currentThread().getName());
dumpJAWTInfo();
}
-
+
/**
* {@inheritDoc}
* <p>
@@ -260,32 +397,48 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
* ..
* ds = getJAWT().GetDrawingSurface(component);
* due to a SIGSEGV.
- *
+ *
* Hence we have some threading / sync issues with the native JAWT implementation.
- * </p>
+ * </p>
*/
@Override
- public Point getLocationOnScreen(Point storage) {
- return getLocationOnScreenNonBlocking(storage, component);
- }
+ public Point getLocationOnScreen(Point storage) {
+ if( null == storage ) {
+ storage = new Point();
+ }
+ getLocationOnScreenNonBlocking(storage, component);
+ return storage;
+ }
+ @Override
protected Point getLocationOnScreenNativeImpl(final int x0, final int y0) { return null; }
- private static native boolean SetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
- // private static native boolean UnsetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
-
+
+ private static native long GetJAWTSurfaceLayersHandle0(Buffer jawtDrawingSurfaceInfoBuffer);
+
+ /**
+ * Set the given root CALayer in the JAWT surface
+ */
+ private static native void SetJAWTRootSurfaceLayer0(long jawtSurfaceLayersHandle, long caLayer);
+
+ /**
+ * Unset the given root CALayer in the JAWT surface, passing the NIO DrawingSurfaceInfo buffer
+ */
+ private static native void UnsetJAWTRootSurfaceLayer0(long jawtSurfaceLayersHandle, long caLayer);
+
// Variables for lockSurface/unlockSurface
private JAWT_DrawingSurface ds;
private boolean dsLocked;
private JAWT_DrawingSurfaceInfo dsi;
-
+ private long jawtSurfaceLayersHandle;
+
private JAWT_MacOSXDrawingSurfaceInfo macosxdsi;
-
- private long rootSurfaceLayerHandle = 0; // attached to the JAWT_SurfaceLayer
-
+
+ private volatile long rootSurfaceLayer = 0; // attached to the JAWT_SurfaceLayer
+
private long windowHandle = 0;
- private long offscreenSurfaceHandle = 0;
- private boolean offscreenSurfaceHandleSet = false;
-
+ private long offscreenSurfaceDrawable = 0;
+ private boolean offscreenSurfaceDrawableSet = false;
+
// Workaround for instance of 4796548
private boolean firstLock = true;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/Win32SunJDKReflection.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/Win32SunJDKReflection.java
index 74dabb67f..5d191f7e5 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/Win32SunJDKReflection.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/Win32SunJDKReflection.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -65,6 +65,7 @@ public class Win32SunJDKReflection {
static {
AccessController.doPrivileged(new PrivilegedAction() {
+ @Override
public Object run() {
try {
win32GraphicsDeviceClass = Class.forName("sun.awt.Win32GraphicsDevice");
@@ -74,7 +75,7 @@ public class Win32SunJDKReflection {
win32GraphicsConfigGetVisualMethod = win32GraphicsConfigClass.getDeclaredMethod("getVisual", new Class[] {});
win32GraphicsConfigGetVisualMethod.setAccessible(true);
initted = true;
- } catch (Exception e) {
+ } catch (final Exception e) {
// Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
}
return null;
@@ -82,37 +83,37 @@ public class Win32SunJDKReflection {
});
}
- public static GraphicsConfiguration graphicsConfigurationGet(GraphicsDevice device, int pfdID) {
+ public static GraphicsConfiguration graphicsConfigurationGet(final GraphicsDevice device, final int pfdID) {
if (!initted) {
return null;
}
try {
- return (GraphicsConfiguration) win32GraphicsConfigGetConfigMethod.invoke(null, new Object[] { device, new Integer(pfdID) });
- } catch (Exception e) {
+ return (GraphicsConfiguration) win32GraphicsConfigGetConfigMethod.invoke(null, new Object[] { device, Integer.valueOf(pfdID) });
+ } catch (final Exception e) {
return null;
}
}
- public static int graphicsConfigurationGetPixelFormatID(AbstractGraphicsConfiguration config) {
+ public static int graphicsConfigurationGetPixelFormatID(final AbstractGraphicsConfiguration config) {
try {
if (config instanceof AWTGraphicsConfiguration) {
return graphicsConfigurationGetPixelFormatID(((AWTGraphicsConfiguration) config).getAWTGraphicsConfiguration());
}
return 0;
- } catch (Exception e) {
+ } catch (final Exception e) {
return 0;
}
}
- public static int graphicsConfigurationGetPixelFormatID(GraphicsConfiguration config) {
+ public static int graphicsConfigurationGetPixelFormatID(final GraphicsConfiguration config) {
if (!initted) {
return 0;
}
try {
return ((Integer) win32GraphicsConfigGetVisualMethod.invoke(config, (Object[])null)).intValue();
- } catch (Exception e) {
+ } catch (final Exception e) {
return 0;
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
index 5d1d43792..7ad914e0a 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,6 +41,7 @@
package jogamp.nativewindow.jawt.windows;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.util.Point;
@@ -56,34 +57,30 @@ import jogamp.nativewindow.windows.GDIUtil;
public class WindowsJAWTWindow extends JAWTWindow {
- public WindowsJAWTWindow(Object comp, AbstractGraphicsConfiguration config) {
+ public WindowsJAWTWindow(final Object comp, final AbstractGraphicsConfiguration config) {
super(comp, config);
}
+ @Override
protected void invalidateNative() {
windowHandle = 0;
}
- protected void attachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
- protected void detachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
-
+ @Override
protected JAWT fetchJAWTImpl() throws NativeWindowException {
return JAWTUtil.getJAWT(false); // no offscreen
}
-
+
+ @Override
protected int lockSurfaceImpl() throws NativeWindowException {
- int ret = NativeWindow.LOCK_SUCCESS;
+ int ret = NativeSurface.LOCK_SUCCESS;
ds = getJAWT().GetDrawingSurface(component);
if (ds == null) {
// Widget not yet realized
unlockSurfaceImpl();
return LOCK_SURFACE_NOT_READY;
}
- int res = ds.Lock();
+ final int res = ds.Lock();
dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ;
if (!dsLocked) {
unlockSurfaceImpl();
@@ -102,7 +99,7 @@ public class WindowsJAWTWindow extends JAWTWindow {
unlockSurfaceImpl();
return LOCK_SURFACE_NOT_READY;
}
- updateBounds(dsi.getBounds());
+ updateLockedData(dsi.getBounds());
win32dsi = (JAWT_Win32DrawingSurfaceInfo) dsi.platformInfo(getJAWT());
if (win32dsi == null) {
unlockSurfaceImpl();
@@ -117,6 +114,7 @@ public class WindowsJAWTWindow extends JAWTWindow {
return ret;
}
+ @Override
protected void unlockSurfaceImpl() throws NativeWindowException {
drawable = 0; // invalid HDC
if(null!=ds) {
@@ -138,7 +136,8 @@ public class WindowsJAWTWindow extends JAWTWindow {
return windowHandle;
}
- protected Point getLocationOnScreenNativeImpl(int x, int y) {
+ @Override
+ protected Point getLocationOnScreenNativeImpl(final int x, final int y) {
return GDIUtil.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
index 736718de8..9abaed731 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -38,6 +38,7 @@
package jogamp.nativewindow.jawt.x11;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.util.Point;
@@ -53,32 +54,28 @@ import jogamp.nativewindow.x11.X11Lib;
public class X11JAWTWindow extends JAWTWindow {
- public X11JAWTWindow(Object comp, AbstractGraphicsConfiguration config) {
+ public X11JAWTWindow(final Object comp, final AbstractGraphicsConfiguration config) {
super(comp, config);
}
+ @Override
protected void invalidateNative() { }
- protected void attachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
- protected void detachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
-
+ @Override
protected JAWT fetchJAWTImpl() throws NativeWindowException {
return JAWTUtil.getJAWT(false); // no offscreen
}
-
+
+ @Override
protected int lockSurfaceImpl() throws NativeWindowException {
- int ret = NativeWindow.LOCK_SUCCESS;
+ int ret = NativeSurface.LOCK_SUCCESS;
ds = getJAWT().GetDrawingSurface(component);
if (ds == null) {
// Widget not yet realized
unlockSurfaceImpl();
return LOCK_SURFACE_NOT_READY;
}
- int res = ds.Lock();
+ final int res = ds.Lock();
dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ;
if (!dsLocked) {
unlockSurfaceImpl();
@@ -97,7 +94,7 @@ public class X11JAWTWindow extends JAWTWindow {
unlockSurfaceImpl();
return LOCK_SURFACE_NOT_READY;
}
- updateBounds(dsi.getBounds());
+ updateLockedData(dsi.getBounds());
x11dsi = (JAWT_X11DrawingSurfaceInfo) dsi.platformInfo(getJAWT());
if (x11dsi == null) {
unlockSurfaceImpl();
@@ -111,6 +108,7 @@ public class X11JAWTWindow extends JAWTWindow {
return ret;
}
+ @Override
protected void unlockSurfaceImpl() throws NativeWindowException {
if(null!=ds) {
if (null!=dsi) {
@@ -126,14 +124,16 @@ public class X11JAWTWindow extends JAWTWindow {
x11dsi = null;
}
- protected Point getLocationOnScreenNativeImpl(int x, int y) {
- return X11Lib.GetRelativeLocation( getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
+ @Override
+ protected Point getLocationOnScreenNativeImpl(final int x, final int y) {
+ // surface is locked and hence the device
+ return X11Lib.GetRelativeLocation(getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
}
-
+
// Variables for lockSurface/unlockSurface
private JAWT_DrawingSurface ds;
private boolean dsLocked;
private JAWT_DrawingSurfaceInfo dsi;
private JAWT_X11DrawingSurfaceInfo x11dsi;
-
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java
index 27e0a5e50..fea1be11a 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -65,6 +65,7 @@ public class X11SunJDKReflection {
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
try {
x11GraphicsDeviceClass = Class.forName("sun.awt.X11GraphicsDevice");
@@ -75,7 +76,7 @@ public class X11SunJDKReflection {
x11GraphicsConfigGetVisualMethod = x11GraphicsConfigClass.getDeclaredMethod("getVisual", new Class[] {});
x11GraphicsConfigGetVisualMethod.setAccessible(true);
initialized = true;
- } catch (Exception e) {
+ } catch (final Exception e) {
// Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
}
return null;
@@ -83,37 +84,37 @@ public class X11SunJDKReflection {
});
}
- public static long graphicsDeviceGetDisplay(GraphicsDevice device) {
+ public static long graphicsDeviceGetDisplay(final GraphicsDevice device) {
if (!initialized) {
return 0;
}
try {
return ((Long) x11GraphicsDeviceGetDisplayMethod.invoke(device, (Object[])null)).longValue();
- } catch (Exception e) {
+ } catch (final Exception e) {
return 0;
}
}
- public static int graphicsConfigurationGetVisualID(AbstractGraphicsConfiguration config) {
+ public static int graphicsConfigurationGetVisualID(final AbstractGraphicsConfiguration config) {
try {
if (config instanceof AWTGraphicsConfiguration) {
return graphicsConfigurationGetVisualID(((AWTGraphicsConfiguration) config).getAWTGraphicsConfiguration());
}
return 0;
- } catch (Exception e) {
+ } catch (final Exception e) {
return 0;
}
}
- public static int graphicsConfigurationGetVisualID(GraphicsConfiguration config) {
+ public static int graphicsConfigurationGetVisualID(final GraphicsConfiguration config) {
if (!initialized) {
return 0;
}
try {
return ((Integer) x11GraphicsConfigGetVisualMethod.invoke(config, (Object[])null)).intValue();
- } catch (Exception e) {
+ } catch (final Exception e) {
return 0;
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java
index de3206c0c..6b54c32ea 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java
@@ -9,39 +9,39 @@ import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
public class OSXDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
long nsWindow;
-
+
/**
- * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
- * not the actual dummy surface width.
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)},
+ * not the actual dummy surface width.
* The latter is platform specific and small
- * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)},
* not the actual dummy surface height,
* The latter is platform specific and small
*/
- public OSXDummyUpstreamSurfaceHook(int width, int height) {
+ public OSXDummyUpstreamSurfaceHook(final int width, final int height) {
super(width, height);
nsWindow = 0;
}
-
+
@Override
- public final void create(ProxySurface s) {
+ public final void create(final ProxySurface s) {
if(0 == nsWindow && 0 == s.getSurfaceHandle()) {
nsWindow = OSXUtil.CreateNSWindow(0, 0, 64, 64);
if(0 == nsWindow) {
throw new NativeWindowException("Error NS window 0");
}
- long nsView = OSXUtil.GetNSView(nsWindow);
+ final long nsView = OSXUtil.GetNSView(nsWindow);
if(0 == nsView) {
throw new NativeWindowException("Error NS view 0");
}
s.setSurfaceHandle(nsView);
- s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
}
s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
}
-
+
@Override
- public final void destroy(ProxySurface s) {
+ public final void destroy(final ProxySurface s) {
if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
if( 0 == nsWindow || 0 == s.getSurfaceHandle() ) {
throw new InternalError("Owns upstream surface, but no OSX view/window: "+s+", nsWindow 0x"+Long.toHexString(nsWindow));
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index b7a83e133..cf163bd82 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -32,15 +32,24 @@ import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.util.Function;
+import com.jogamp.common.util.FunctionTask;
+import com.jogamp.common.util.RunnableTask;
+
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NWJNILibLoader;
+import jogamp.nativewindow.ToolkitProperties;
-public class OSXUtil {
- private static boolean isInit = false;
+public class OSXUtil implements ToolkitProperties {
+ private static boolean isInit = false;
private static final boolean DEBUG = Debug.debug("OSXUtil");
-
+
+ /** FIXME HiDPI: OSX unique and maximum value {@value} */
+ public static final int MAX_PIXELSCALE = 2;
+
/**
* Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
*/
public static synchronized void initSingleton() {
if(!isInit) {
@@ -50,121 +59,318 @@ public class OSXUtil {
if(!NWJNILibLoader.loadNativeWindow("macosx")) {
throw new NativeWindowException("NativeWindow MacOSX native library load error.");
}
-
+
if( !initIDs0() ) {
throw new NativeWindowException("MacOSX: Could not initialized native stub");
- }
+ }
isInit = true;
}
}
/**
* Called by {@link NativeWindowFactory#shutdown()}
+ * @see ToolkitProperties
*/
- public static void shutdown() {
- }
-
- public static boolean requiresToolkitLock() {
- return false;
- }
-
- public static boolean isNSView(long object) {
- return isNSView0(object);
+ public static void shutdown() { }
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static boolean requiresToolkitLock() { return false; }
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static final boolean hasThreadingIssues() { return false; }
+
+ public static boolean isNSView(final long object) {
+ return 0 != object ? isNSView0(object) : false;
}
-
- public static boolean isNSWindow(long object) {
- return isNSWindow0(object);
+
+ public static boolean isNSWindow(final long object) {
+ return 0 != object ? isNSWindow0(object) : false;
}
-
+
/**
- * In case the <code>windowOrView</code> is top-level,
- * you shall set <code>topLevel</code> to true where
- * insets gets into account to compute the client position as follows:
- * <pre>
- if(topLevel) {
- // top-level position -> client window position
- final Insets insets = GetInsets(windowOrView);
- los.setX(los.getX() + insets.getLeftWidth());
- los.setY(los.getY() + insets.getTopHeight());
- }
- * </pre>
* @param windowOrView
- * @param topLevel
* @param src_x
* @param src_y
- * @return the client position
+ * @return top-left client-area position in window units
*/
- public static Point GetLocationOnScreen(long windowOrView, boolean topLevel, int src_x, int src_y) {
- final Point los = (Point) GetLocationOnScreen0(windowOrView, src_x, src_y);
- if(topLevel) {
- // top-level position -> client window position
- final Insets insets = GetInsets(windowOrView);
- los.setX(los.getX() + insets.getLeftWidth());
- los.setY(los.getY() + insets.getTopHeight());
- }
- return los;
+ public static Point GetLocationOnScreen(final long windowOrView, final int src_x, final int src_y) {
+ return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y);
}
-
- public static Insets GetInsets(long windowOrView) {
+
+ public static Insets GetInsets(final long windowOrView) {
return (Insets) GetInsets0(windowOrView);
}
-
- public static long CreateNSWindow(int x, int y, int width, int height) {
+
+ public static double GetPixelScale(final int screenIndex) {
+ return GetPixelScale0(screenIndex);
+ }
+
+ public static double GetPixelScale(final long windowOrView) {
+ return GetPixelScale1(windowOrView);
+ }
+
+ public static long CreateNSWindow(final int x, final int y, final int width, final int height) {
return CreateNSWindow0(x, y, width, height);
}
- public static void DestroyNSWindow(long nsWindow) {
+ public static void DestroyNSWindow(final long nsWindow) {
DestroyNSWindow0(nsWindow);
}
- public static long GetNSView(long nsWindow) {
+ public static long GetNSView(final long nsWindow) {
return GetNSView0(nsWindow);
}
- public static long GetNSWindow(long nsView) {
+ public static long GetNSWindow(final long nsView) {
return GetNSWindow0(nsView);
}
-
- public static long CreateCALayer(int x, int y, int width, int height) {
- return CreateCALayer0(x, y, width, height);
+
+ /**
+ * Create a CALayer suitable to act as a root CALayer.
+ * @param width width of the CALayer in window units (points)
+ * @param height height of the CALayer in window units (points)
+ * @param contentsScale scale for HiDPI support: pixel-dim = window-dim x scale
+ * @return the new CALayer object
+ * @see #DestroyCALayer(long)
+ * @see #AddCASublayer(long, long)
+ */
+ public static long CreateCALayer(final int width, final int height, final float contentsScale) {
+ final long l = CreateCALayer0(width, height, contentsScale);
+ if(DEBUG) {
+ System.err.println("OSXUtil.CreateCALayer: 0x"+Long.toHexString(l)+" - "+Thread.currentThread().getName());
+ }
+ return l;
}
- public static void AddCASublayer(long rootCALayer, long subCALayer) {
+
+ /**
+ * Attach a sub CALayer to the root CALayer
+ * <p>
+ * Method will trigger a <code>display</code>
+ * call to the CALayer hierarchy to enforce resource creation if required, e.g. an NSOpenGLContext.
+ * </p>
+ * <p>
+ * Hence it is important that related resources are not locked <i>if</i>
+ * they will be used for creation.
+ * </p>
+ * @param rootCALayer
+ * @param subCALayer
+ * @param x x-coord of the sub-CALayer in window units (points)
+ * @param y y-coord of the sub-CALayer in window units (points)
+ * @param width width of the sub-CALayer in window units (points)
+ * @param height height of the sub-CALayer in window units (points)
+ * @param contentsScale scale for HiDPI support: pixel-dim = window-dim x scale
+ * @param caLayerQuirks
+ * @see #CreateCALayer(int, int, float)
+ * @see #RemoveCASublayer(long, long, boolean)
+ */
+ public static void AddCASublayer(final long rootCALayer, final long subCALayer,
+ final int x, final int y, final int width, final int height,
+ final float contentsScale, final int caLayerQuirks) {
if(0==rootCALayer || 0==subCALayer) {
throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
}
- AddCASublayer0(rootCALayer, subCALayer);
+ if(DEBUG) {
+ System.err.println("OSXUtil.AttachCALayer: caLayerQuirks "+caLayerQuirks+", 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
+ }
+ AddCASublayer0(rootCALayer, subCALayer, x, y, width, height, contentsScale, caLayerQuirks);
+ }
+
+ /**
+ * Fix root and sub CALayer position to 0/0 and size
+ * <p>
+ * If the sub CALayer implements the Objective-C NativeWindow protocol NWDedicatedSize (e.g. JOGL's MyNSOpenGLLayer),
+ * the dedicated size is passed to the layer, which propagates it appropriately.
+ * </p>
+ * <p>
+ * On OSX/Java7 our root CALayer's frame position and size gets corrupted by its NSView,
+ * hence we have created the NWDedicatedSize protocol.
+ * </p>
+ *
+ * @param rootCALayer the root surface layer, maybe null.
+ * @param subCALayer the client surface layer, maybe null.
+ * @param visible TODO
+ * @param width the expected width in window units (points)
+ * @param height the expected height in window units (points)
+ * @param caLayerQuirks TODO
+ */
+ public static void FixCALayerLayout(final long rootCALayer, final long subCALayer, final boolean visible, final int x, final int y, final int width, final int height, final int caLayerQuirks) {
+ if( 0==rootCALayer && 0==subCALayer ) {
+ return;
+ }
+ FixCALayerLayout0(rootCALayer, subCALayer, visible, x, y, width, height, caLayerQuirks);
+ }
+
+ /**
+ * Set root and sub CALayer pixelScale / contentScale for HiDPI
+ *
+ * @param rootCALayer the root surface layer, maybe null.
+ * @param subCALayer the client surface layer, maybe null.
+ * @param contentsScale scale for HiDPI support: pixel-dim = window-dim x scale
+ */
+ public static void SetCALayerPixelScale(final long rootCALayer, final long subCALayer, final float contentsScale) {
+ if( 0==rootCALayer && 0==subCALayer ) {
+ return;
+ }
+ SetCALayerPixelScale0(rootCALayer, subCALayer, contentsScale);
}
- public static void RemoveCASublayer(long rootCALayer, long subCALayer) {
+
+ /**
+ * Detach a sub CALayer from the root CALayer.
+ */
+ public static void RemoveCASublayer(final long rootCALayer, final long subCALayer) {
if(0==rootCALayer || 0==subCALayer) {
throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
}
+ if(DEBUG) {
+ System.err.println("OSXUtil.DetachCALayer: 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
+ }
RemoveCASublayer0(rootCALayer, subCALayer);
}
- public static void DestroyCALayer(long caLayer) {
+
+ /**
+ * Destroy a CALayer.
+ * @see #CreateCALayer(int, int, float)
+ */
+ public static void DestroyCALayer(final long caLayer) {
if(0==caLayer) {
throw new IllegalArgumentException("caLayer 0x"+Long.toHexString(caLayer));
}
- DestroyCALayer0(caLayer);
+ if(DEBUG) {
+ System.err.println("OSXUtil.DestroyCALayer: 0x"+Long.toHexString(caLayer)+" - "+Thread.currentThread().getName());
+ }
+ DestroyCALayer0(caLayer);
}
-
- public static void RunOnMainThread(boolean waitUntilDone, Runnable runnable) {
- if(IsMainThread0()) {
+
+ /**
+ * Run on OSX UI main thread.
+ * <p>
+ * 'waitUntilDone' is implemented on Java site via lock/wait on {@link RunnableTask} to not freeze OSX main thread.
+ * </p>
+ *
+ * @param waitUntilDone
+ * @param kickNSApp if <code>true</code> issues {@link #KickNSApp()}
+ * @param runnable
+ */
+ public static void RunOnMainThread(final boolean waitUntilDone, final boolean kickNSApp, final Runnable runnable) {
+ if( IsMainThread0() ) {
runnable.run(); // don't leave the JVM
} else {
- RunOnMainThread0(waitUntilDone, runnable);
+ // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
+ // otherwise we may freeze the OSX main thread.
+ Throwable throwable = null;
+ final Object sync = new Object();
+ final RunnableTask rt = new RunnableTask( runnable, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err );
+ synchronized(sync) {
+ RunOnMainThread0(kickNSApp, rt);
+ if( waitUntilDone ) {
+ try {
+ sync.wait();
+ } catch (final InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rt.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Run later on ..
+ * @param onMain if true, run on main-thread, otherwise on the current OSX thread.
+ * @param runnable
+ * @param delay delay to run the runnable in milliseconds
+ */
+ public static void RunLater(final boolean onMain, final Runnable runnable, final int delay) {
+ RunLater0(onMain, false /* kickNSApp */, new RunnableTask( runnable, null, true, System.err ), delay);
+ }
+
+ /**
+ * Wakes up NSApp thread by sending an empty NSEvent ..
+ * <p>
+ * This is deemed important <i>sometimes</i> where resources shall get freed ASAP, e.g. GL context etc.
+ * </p>
+ * <p>
+ * The following scenarios requiring this <i>wake-up</i> are currently known:
+ * <ul>
+ * <li>Destruction of an OpenGL context</li>
+ * <li>Destruction of Windows .. ?</li>
+ * <li>Stopping the NSApp</li>
+ * </ul>
+ * </p>
+ * FIXME: Complete list of scenarios and reason it.
+ */
+ public static void KickNSApp() {
+ KickNSApp0();
+ }
+
+ private static Runnable _nop = new Runnable() { @Override public void run() {}; };
+
+ /** Issues a {@link #RunOnMainThread(boolean, boolean, Runnable)} w/ an <i>NOP</i> runnable, while waiting until done and issuing {@link #KickNSApp()}. */
+ public static void WaitUntilFinish() {
+ RunOnMainThread(true, true /* kickNSApp */, _nop);
+ }
+
+ /**
+ * Run on OSX UI main thread.
+ * <p>
+ * 'waitUntilDone' is implemented on Java site via lock/wait on {@link FunctionTask} to not freeze OSX main thread.
+ * </p>
+ *
+ * @param waitUntilDone
+ * @param kickNSApp if <code>true</code> issues {@link #KickNSApp()}
+ * @param func
+ */
+ public static <R,A> R RunOnMainThread(final boolean waitUntilDone, final boolean kickNSApp, final Function<R,A> func, final A... args) {
+ if( IsMainThread0() ) {
+ return func.eval(args); // don't leave the JVM
+ } else {
+ // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
+ // otherwise we may freeze the OSX main thread.
+ Throwable throwable = null;
+ final Object sync = new Object();
+ final FunctionTask<R,A> rt = new FunctionTask<R,A>( func, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err );
+ synchronized(sync) {
+ rt.setArgs(args);
+ RunOnMainThread0(kickNSApp, rt);
+ if( waitUntilDone ) {
+ try {
+ sync.wait();
+ } catch (final InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rt.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+ return rt.getResult();
}
}
-
+
public static boolean IsMainThread() {
return IsMainThread0();
}
-
+
/** Returns the screen refresh rate in Hz. If unavailable, returns 60Hz. */
- public static int GetScreenRefreshRate(int scrn_idx) {
+ public static int GetScreenRefreshRate(final int scrn_idx) {
return GetScreenRefreshRate0(scrn_idx);
}
-
+
/***
private static boolean isAWTEDTMainThreadInit = false;
private static boolean isAWTEDTMainThread;
-
+
public synchronized static boolean isAWTEDTMainThread() {
if(!isAWTEDTMainThreadInit) {
isAWTEDTMainThreadInit = true;
@@ -178,24 +384,30 @@ public class OSXUtil {
} else {
isAWTEDTMainThread = false;
}
- }
+ }
return isAWTEDTMainThread;
} */
-
+
private static native boolean initIDs0();
private static native boolean isNSView0(long object);
private static native boolean isNSWindow0(long object);
private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y);
private static native Object GetInsets0(long windowOrView);
+ private static native double GetPixelScale0(int screenIndex);
+ private static native double GetPixelScale1(long windowOrView);
private static native long CreateNSWindow0(int x, int y, int width, int height);
private static native void DestroyNSWindow0(long nsWindow);
private static native long GetNSView0(long nsWindow);
private static native long GetNSWindow0(long nsView);
- private static native long CreateCALayer0(int x, int y, int width, int height);
- private static native void AddCASublayer0(long rootCALayer, long subCALayer);
+ private static native long CreateCALayer0(int width, int height, float contentsScale);
+ private static native void AddCASublayer0(long rootCALayer, long subCALayer, int x, int y, int width, int height, float contentsScale, int caLayerQuirks);
+ private static native void FixCALayerLayout0(long rootCALayer, long subCALayer, boolean visible, int x, int y, int width, int height, int caLayerQuirks);
+ private static native void SetCALayerPixelScale0(long rootCALayer, long subCALayer, float contentsScale);
private static native void RemoveCASublayer0(long rootCALayer, long subCALayer);
private static native void DestroyCALayer0(long caLayer);
- private static native void RunOnMainThread0(boolean waitUntilDone, Runnable runnable);
+ private static native void RunOnMainThread0(boolean kickNSApp, Runnable runnable);
+ private static native void RunLater0(boolean onMain, boolean kickNSApp, Runnable runnable, int delay);
+ private static native void KickNSApp0();
private static native boolean IsMainThread0();
private static native int GetScreenRefreshRate0(int scrn_idx);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java
index aa5f3dac5..a08cf9b51 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java
@@ -9,33 +9,33 @@ import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
public class GDIDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
/**
- * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
- * not the actual dummy surface width.
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)},
+ * not the actual dummy surface width.
* The latter is platform specific and small
- * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)},
* not the actual dummy surface height,
* The latter is platform specific and small
*/
- public GDIDummyUpstreamSurfaceHook(int width, int height) {
+ public GDIDummyUpstreamSurfaceHook(final int width, final int height) {
super(width, height);
}
-
+
@Override
- public final void create(ProxySurface s) {
+ public final void create(final ProxySurface s) {
final GDISurface ms = (GDISurface)s;
- if(0 == ms.getWindowHandle()) {
+ if(0 == ms.getWindowHandle()) {
final long windowHandle = GDIUtil.CreateDummyWindow(0, 0, 64, 64);
if(0 == windowHandle) {
throw new NativeWindowException("Error windowHandle 0, werr: "+GDI.GetLastError());
- }
+ }
ms.setWindowHandle(windowHandle);
- ms.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ ms.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
}
s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
}
-
+
@Override
- public final void destroy(ProxySurface s) {
+ public final void destroy(final ProxySurface s) {
final GDISurface ms = (GDISurface)s;
if( ms.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
if( 0 == ms.getWindowHandle() ) {
@@ -46,5 +46,5 @@ public class GDIDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize
ms.setWindowHandle(0);
ms.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
}
- }
+ }
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
index 3db2b5fc9..2f335c428 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
@@ -43,10 +43,12 @@ import jogamp.nativewindow.windows.GDI;
* allowing the use of HDC via lockSurface()/unlockSurface() protocol.
* The latter will get and release the HDC.
* The size via getWidth()/getHeight() is invalid.
+ *
+ * @see ProxySurface
*/
public class GDISurface extends ProxySurfaceImpl {
- protected long windowHandle;
- protected long surfaceHandle;
+ private long windowHandle;
+ private long surfaceHandle;
/**
* @param cfg the {@link AbstractGraphicsConfiguration} to be used
@@ -56,37 +58,37 @@ public class GDISurface extends ProxySurfaceImpl {
* owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
* otherwise <code>false</code>. Owning the device implies closing it at {@link #destroyNotify()}.
*/
- public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ public GDISurface(final AbstractGraphicsConfiguration cfg, final long windowHandle, final UpstreamSurfaceHook upstream, final boolean ownsDevice) {
super(cfg, upstream, ownsDevice);
this.windowHandle=windowHandle;
this.surfaceHandle=0;
}
@Override
- protected void invalidateImpl() {
+ protected void invalidateImpl() {
if(0 != surfaceHandle) {
throw new NativeWindowException("didn't release surface Handle: "+this);
}
windowHandle = 0;
// surfaceHandle = 0;
}
-
+
/**
* {@inheritDoc}
* <p>
- * Actually the window handle (HWND), since the surfaceHandle (HDC) is derived
+ * Actually the window handle (HWND), since the surfaceHandle (HDC) is derived
* from it at {@link #lockSurface()}.
- * </p>
+ * </p>
*/
@Override
- public final void setSurfaceHandle(long surfaceHandle) {
+ public final void setSurfaceHandle(final long surfaceHandle) {
this.windowHandle = surfaceHandle;
}
/**
- * Sets the window handle (HWND).
+ * Sets the window handle (HWND).
*/
- public final void setWindowHandle(long windowHandle) {
+ public final void setWindowHandle(final long windowHandle) {
this.windowHandle = windowHandle;
}
@@ -116,7 +118,7 @@ public class GDISurface extends ProxySurfaceImpl {
final protected void unlockSurfaceImpl() {
if (0 != surfaceHandle) {
if(0 == GDI.ReleaseDC(windowHandle, surfaceHandle)) {
- throw new NativeWindowException("DC not released: "+this+", isWindow "+GDI.IsWindow(windowHandle)+", werr "+GDI.GetLastError()+", thread: "+Thread.currentThread().getName());
+ throw new NativeWindowException("DC not released: "+this+", isWindow "+GDI.IsWindow(windowHandle)+", werr "+GDI.GetLastError()+", thread: "+Thread.currentThread().getName());
}
surfaceHandle=0;
}
@@ -126,4 +128,15 @@ public class GDISurface extends ProxySurfaceImpl {
final public long getSurfaceHandle() {
return surfaceHandle;
}
+
+ @Override
+ public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
+ return pixelUnitsAndResult; // no pixelScale factor
+ }
+
+ @Override
+ public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
+ return windowUnitsAndResult; // no pixelScale factor
+ }
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
index 613c76032..c409b6a39 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
@@ -33,21 +33,22 @@ import javax.media.nativewindow.NativeWindowFactory;
import jogamp.nativewindow.NWJNILibLoader;
import jogamp.nativewindow.Debug;
-import jogamp.nativewindow.x11.X11Util;
+import jogamp.nativewindow.ToolkitProperties;
-public class GDIUtil {
+public class GDIUtil implements ToolkitProperties {
private static final boolean DEBUG = Debug.debug("GDIUtil");
-
+
private static final String dummyWindowClassNameBase = "_dummyWindow_clazz" ;
private static RegisteredClassFactory dummyWindowClassFactory;
- private static boolean isInit = false;
-
+ private static volatile boolean isInit = false;
+
/**
* Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
*/
public static synchronized void initSingleton() {
if(!isInit) {
- synchronized(X11Util.class) {
+ synchronized(GDIUtil.class) {
if(!isInit) {
if(DEBUG) {
System.out.println("GDI.initSingleton()");
@@ -58,53 +59,95 @@ public class GDIUtil {
if( !initIDs0() ) {
throw new NativeWindowException("GDI: Could not initialized native stub");
}
- dummyWindowClassFactory = new RegisteredClassFactory(dummyWindowClassNameBase, getDummyWndProc0());
+ dummyWindowClassFactory = new RegisteredClassFactory(dummyWindowClassNameBase, getDummyWndProc0(),
+ true /* useDummyDispatchThread */,
+ 0 /* iconSmallHandle */, 0 /* iconBigHandle */);
+ if(DEBUG) {
+ System.out.println("GDI.initSingleton() dummyWindowClassFactory "+dummyWindowClassFactory);
+ }
isInit = true;
}
}
}
}
-
+
/**
* Called by {@link NativeWindowFactory#shutdown()}
+ * @see ToolkitProperties
*/
- public static void shutdown() {
+ public static void shutdown() {
}
-
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
public static boolean requiresToolkitLock() { return false; }
-
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static final boolean hasThreadingIssues() { return false; }
+
private static RegisteredClass dummyWindowClass = null;
private static Object dummyWindowSync = new Object();
-
- public static long CreateDummyWindow(int x, int y, int width, int height) {
+
+ public static long CreateDummyWindow(final int x, final int y, final int width, final int height) {
synchronized(dummyWindowSync) {
dummyWindowClass = dummyWindowClassFactory.getSharedClass();
- return CreateDummyWindow0(dummyWindowClass.getHandle(), dummyWindowClass.getName(), dummyWindowClass.getName(), x, y, width, height);
+ if(DEBUG) {
+ System.out.println("GDI.CreateDummyWindow() dummyWindowClassFactory "+dummyWindowClassFactory);
+ System.out.println("GDI.CreateDummyWindow() dummyWindowClass "+dummyWindowClass);
+ }
+ return CreateDummyWindow0(dummyWindowClass.getHInstance(), dummyWindowClass.getName(), dummyWindowClass.getHDispThreadContext(), dummyWindowClass.getName(), x, y, width, height);
}
}
-
- public static boolean DestroyDummyWindow(long hwnd) {
+
+ public static boolean DestroyDummyWindow(final long hwnd) {
boolean res;
synchronized(dummyWindowSync) {
if( null == dummyWindowClass ) {
throw new InternalError("GDI Error ("+dummyWindowClassFactory.getSharedRefCount()+"): SharedClass is null");
}
- res = GDI.DestroyWindow(hwnd);
+ res = DestroyWindow0(dummyWindowClass.getHDispThreadContext(), hwnd);
dummyWindowClassFactory.releaseSharedClass();
}
return res;
}
-
- public static Point GetRelativeLocation(long src_win, long dest_win, int src_x, int src_y) {
+
+ public static Point GetRelativeLocation(final long src_win, final long dest_win, final int src_x, final int src_y) {
return (Point) GetRelativeLocation0(src_win, dest_win, src_x, src_y);
}
-
- public static native boolean CreateWindowClass(long hInstance, String clazzName, long wndProc);
- public static native boolean DestroyWindowClass(long hInstance, String className);
-
+
+ public static boolean IsUndecorated(final long win) {
+ return IsUndecorated0(win);
+ }
+
+ public static boolean IsChild(final long win) {
+ return IsChild0(win);
+ }
+
+ public static void SetProcessThreadsAffinityMask(final long affinityMask, final boolean verbose) {
+ SetProcessThreadsAffinityMask0(affinityMask, verbose);
+ }
+
+ private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
+
+ /** Creates WNDCLASSEX instance */
+ static native boolean CreateWindowClass0(long hInstance, String clazzName, long wndProc, long iconSmallHandle, long iconBigHandle);
+ /** Destroys WNDCLASSEX instance */
+ static native boolean DestroyWindowClass0(long hInstance, String className, long dispThreadCtx);
+ static native long CreateDummyDispatchThread0();
+
private static native boolean initIDs0();
- private static native long getDummyWndProc0();
+ private static native long getDummyWndProc0();
private static native Object GetRelativeLocation0(long src_win, long dest_win, int src_x, int src_y);
-
- static native long CreateDummyWindow0(long hInstance, String className, String windowName, int x, int y, int width, int height);
+ private static native boolean IsChild0(long win);
+ private static native boolean IsUndecorated0(long win);
+
+ private static native void SetProcessThreadsAffinityMask0(long affinityMask, boolean verbose);
+
+ private static native long CreateDummyWindow0(long hInstance, String className, long dispThreadCtx, String windowName, int x, int y, int width, int height);
+ private static native boolean DestroyWindow0(long dispThreadCtx, long win);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
index afb3daf7c..3c7b1adfb 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
@@ -29,17 +29,25 @@
package jogamp.nativewindow.windows;
public class RegisteredClass {
- long hInstance;
- String className;
+ private final long hInstance;
+ private final String className;
+ private final long hDDTCtx;
- RegisteredClass(long hInst, String name) {
- hInstance = hInst;
- className = name;
+ RegisteredClass(final long hInst, final String name, final long hDispatchThreadCtx) {
+ this.hInstance = hInst;
+ this.className = name;
+ this.hDDTCtx = hDispatchThreadCtx;
}
- public final long getHandle() { return hInstance; }
+ /** Application handle, same as {@link RegisteredClassFactory#getHInstance()}. */
+ public final long getHInstance() { return hInstance; }
+
+ /** Unique Window Class Name */
public final String getName() { return className; }
+ /** Unique associated dispatch thread context for this Window Class, or 0 for none. */
+ public final long getHDispThreadContext() { return hDDTCtx; }
+
@Override
- public final String toString() { return "RegisteredClass[handle 0x"+Long.toHexString(hInstance)+", "+className+"]"; }
+ public final String toString() { return "RegisteredClass[handle 0x"+Long.toHexString(hInstance)+", "+className+", dtx 0x"+Long.toHexString(hDDTCtx)+"]"; }
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java
index 00bedfc8e..e3ea49314 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java
@@ -29,46 +29,76 @@
package jogamp.nativewindow.windows;
import jogamp.nativewindow.Debug;
+
import java.util.ArrayList;
+
import javax.media.nativewindow.NativeWindowException;
public class RegisteredClassFactory {
- static final boolean DEBUG = Debug.debug("RegisteredClass");
- private static ArrayList<RegisteredClassFactory> registeredFactories = new ArrayList<RegisteredClassFactory>();
-
- private String classBaseName;
- private long wndProc;
+ private static final boolean DEBUG = Debug.debug("RegisteredClass");
+ private static final ArrayList<RegisteredClassFactory> registeredFactories;
+ private static final long hInstance;
+
+ static {
+ hInstance = GDI.GetApplicationHandle();
+ if( 0 == hInstance ) {
+ throw new NativeWindowException("Error: Null ModuleHandle for Application");
+ }
+ registeredFactories = new ArrayList<RegisteredClassFactory>();
+ }
+
+ private final String classBaseName;
+ private final long wndProc;
+ private final boolean useDummyDispatchThread;
+ private final long iconSmallHandle, iconBigHandle;
private RegisteredClass sharedClass = null;
private int classIter = 0;
private int sharedRefCount = 0;
private final Object sync = new Object();
+ private String toHexString(final long l) { return "0x"+Long.toHexString(l); }
+
+ @Override
+ public final String toString() { return "RegisteredClassFactory[moduleHandle "+toHexString(hInstance)+", "+classBaseName+
+ ", wndProc "+toHexString(wndProc)+", useDDT "+useDummyDispatchThread+", shared[refCount "+sharedRefCount+", class "+sharedClass+"]]"; }
+
/**
- * Release the {@link RegisteredClass} of all {@link RegisteredClassFactory}.
+ * Release the {@link RegisteredClass} of all {@link RegisteredClassFactory}.
*/
public static void shutdownSharedClasses() {
synchronized(registeredFactories) {
+ if( DEBUG ) {
+ System.err.println("RegisteredClassFactory.shutdownSharedClasses: "+registeredFactories.size());
+ }
for(int j=0; j<registeredFactories.size(); j++) {
final RegisteredClassFactory rcf = registeredFactories.get(j);
synchronized(rcf.sync) {
if(null != rcf.sharedClass) {
- GDIUtil.DestroyWindowClass(rcf.sharedClass.getHandle(), rcf.sharedClass.getName());
+ GDIUtil.DestroyWindowClass0(rcf.sharedClass.getHInstance(), rcf.sharedClass.getName(), rcf.sharedClass.getHDispThreadContext());
rcf.sharedClass = null;
rcf.sharedRefCount = 0;
- rcf.classIter = 0;
+ rcf.classIter = 0;
if(DEBUG) {
- System.err.println("RegisteredClassFactory #"+j+"/"+registeredFactories.size()+" shutdownSharedClasses : "+rcf.sharedClass);
+ System.err.println("RegisteredClassFactory #"+j+"/"+registeredFactories.size()+": shutdownSharedClasses : "+rcf.sharedClass);
}
+ } else if(DEBUG) {
+ System.err.println("RegisteredClassFactory #"+j+"/"+registeredFactories.size()+": null");
}
}
}
}
}
- public RegisteredClassFactory(String classBaseName, long wndProc) {
+ /** Application handle. */
+ public static long getHInstance() { return hInstance; }
+
+ public RegisteredClassFactory(final String classBaseName, final long wndProc, final boolean useDummyDispatchThread, final long iconSmallHandle, final long iconBigHandle) {
this.classBaseName = classBaseName;
this.wndProc = wndProc;
+ this.useDummyDispatchThread = useDummyDispatchThread;
+ this.iconSmallHandle = iconSmallHandle;
+ this.iconBigHandle = iconBigHandle;
synchronized(registeredFactories) {
registeredFactories.add(this);
}
@@ -80,23 +110,28 @@ public class RegisteredClassFactory {
if( null != sharedClass ) {
throw new InternalError("Error ("+sharedRefCount+"): SharedClass not null: "+sharedClass);
}
- long hInstance = GDI.GetApplicationHandle();
- if( 0 == hInstance ) {
- throw new NativeWindowException("Error: Null ModuleHandle for Application");
- }
String clazzName = null;
boolean registered = false;
- final int classIterMark = classIter - 1;
+ final int classIterMark = classIter - 1;
while ( !registered && classIterMark != classIter ) {
// Retry with next clazz name, this could happen if more than one JVM is running
clazzName = classBaseName + classIter;
classIter++;
- registered = GDIUtil.CreateWindowClass(hInstance, clazzName, wndProc);
+ registered = GDIUtil.CreateWindowClass0(hInstance, clazzName, wndProc, iconSmallHandle, iconBigHandle);
}
if( !registered ) {
throw new NativeWindowException("Error: Could not create WindowClass: "+clazzName);
}
- sharedClass = new RegisteredClass(hInstance, clazzName);
+ final long hDispatchThread;
+ if( useDummyDispatchThread ) {
+ hDispatchThread = GDIUtil.CreateDummyDispatchThread0();
+ if( 0 == hDispatchThread ) {
+ throw new NativeWindowException("Error: Could not create DDT "+clazzName);
+ }
+ } else {
+ hDispatchThread = 0;
+ }
+ sharedClass = new RegisteredClass(hInstance, clazzName, hDispatchThread);
if(DEBUG) {
System.err.println("RegisteredClassFactory getSharedClass ("+sharedRefCount+") initialized: "+sharedClass);
}
@@ -121,7 +156,7 @@ public class RegisteredClassFactory {
throw new InternalError("Error ("+sharedRefCount+"): SharedClass is null");
}
if( 0 == sharedRefCount ) {
- GDIUtil.DestroyWindowClass(sharedClass.getHandle(), sharedClass.getName());
+ GDIUtil.DestroyWindowClass0(sharedClass.getHInstance(), sharedClass.getName(), sharedClass.getHDispThreadContext());
if(DEBUG) {
System.err.println("RegisteredClassFactory releaseSharedClass ("+sharedRefCount+") released: "+sharedClass);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java
index 4f8cff8c5..0ac3d4a2e 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java
@@ -35,7 +35,7 @@ import javax.media.nativewindow.VisualIDHolder;
public class X11Capabilities extends Capabilities {
final private XVisualInfo xVisualInfo; // maybe null if !onscreen
- public X11Capabilities(XVisualInfo xVisualInfo) {
+ public X11Capabilities(final XVisualInfo xVisualInfo) {
super();
this.xVisualInfo = xVisualInfo;
}
@@ -49,7 +49,7 @@ public class X11Capabilities extends Capabilities {
public Object clone() {
try {
return super.clone();
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
throw new NativeWindowException(e);
}
}
@@ -59,7 +59,7 @@ public class X11Capabilities extends Capabilities {
final public boolean hasXVisualInfo() { return null!=xVisualInfo; }
@Override
- final public int getVisualID(VIDType type) throws NativeWindowException {
+ final public int getVisualID(final VIDType type) throws NativeWindowException {
switch(type) {
case INTRINSIC:
case NATIVE:
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
index 55a29dd5e..7e61ba6d0 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
@@ -14,47 +14,57 @@ import com.jogamp.nativewindow.x11.X11GraphicsScreen;
public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
/**
- * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
- * not the actual dummy surface width.
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)},
+ * not the actual dummy surface width.
* The latter is platform specific and small
- * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)},
* not the actual dummy surface height,
* The latter is platform specific and small
*/
- public X11DummyUpstreamSurfaceHook(int width, int height) {
+ public X11DummyUpstreamSurfaceHook(final int width, final int height) {
super(width, height);
}
-
+
@Override
- public final void create(ProxySurface s) {
+ public final void create(final ProxySurface s) {
final X11GraphicsConfiguration cfg = (X11GraphicsConfiguration) s.getGraphicsConfiguration();
final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen();
final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice();
- if(0 == device.getHandle()) {
- device.open();
- s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
- }
- if( 0 == s.getSurfaceHandle() ) {
- final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64);
- if(0 == windowHandle) {
- throw new NativeWindowException("Creating dummy window failed w/ "+cfg);
+ device.lock();
+ try {
+ if(0 == device.getHandle()) {
+ device.open();
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ if( 0 == s.getSurfaceHandle() ) {
+ final long windowHandle = X11Lib.CreateWindow(0, device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64, false, false);
+ if(0 == windowHandle) {
+ throw new NativeWindowException("Creating dummy window failed w/ "+cfg);
+ }
+ s.setSurfaceHandle(windowHandle);
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
}
- s.setSurfaceHandle(windowHandle);
- s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ } finally {
+ device.unlock();
}
- s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
}
-
+
@Override
- public final void destroy(ProxySurface s) {
+ public final void destroy(final ProxySurface s) {
if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
final X11GraphicsDevice device = (X11GraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice();
if( 0 == s.getSurfaceHandle() ) {
throw new InternalError("Owns upstream surface, but no X11 window: "+s);
}
- X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle());
- s.setSurfaceHandle(0);
- s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ device.lock();
+ try {
+ X11Lib.DestroyWindow(device.getHandle(), s.getSurfaceHandle());
+ s.setSurfaceHandle(0);
+ s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ } finally {
+ device.unlock();
+ }
}
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java
index b11dd1df1..e12c3fd13 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -47,12 +47,13 @@ import com.jogamp.nativewindow.x11.X11GraphicsScreen;
public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactory {
public static void registerFactory() {
GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class, new X11GraphicsConfigurationFactory());
- }
+ }
private X11GraphicsConfigurationFactory() {
}
-
+
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID)
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested, final CapabilitiesChooser chooser, final AbstractGraphicsScreen screen, final int nativeVisualID)
throws IllegalArgumentException, NativeWindowException {
if(!(screen instanceof X11GraphicsScreen)) {
@@ -71,15 +72,15 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor
return res;
}
- public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, int visualID)
+ public static XVisualInfo getXVisualInfo(final AbstractGraphicsScreen screen, final int visualID)
{
- XVisualInfo xvi_temp = XVisualInfo.create();
+ final XVisualInfo xvi_temp = XVisualInfo.create();
xvi_temp.setVisualid(visualID);
xvi_temp.setScreen(screen.getIndex());
- int num[] = { -1 };
- long display = screen.getDevice().getHandle();
+ final int num[] = { -1 };
+ final long display = screen.getDevice().getHandle();
- XVisualInfo[] xvis = X11Lib.XGetVisualInfo(display, X11Lib.VisualIDMask|X11Lib.VisualScreenMask, xvi_temp, num, 0);
+ final XVisualInfo[] xvis = X11Lib.XGetVisualInfo(display, X11Lib.VisualIDMask|X11Lib.VisualScreenMask, xvi_temp, num, 0);
if(xvis==null || num[0]<1) {
return null;
@@ -88,28 +89,28 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor
return XVisualInfo.create(xvis[0]);
}
- public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, CapabilitiesImmutable capabilities)
+ public static XVisualInfo getXVisualInfo(final AbstractGraphicsScreen screen, final CapabilitiesImmutable capabilities)
{
- XVisualInfo xv = getXVisualInfoImpl(screen, capabilities, 4 /* TrueColor */);
+ final XVisualInfo xv = getXVisualInfoImpl(screen, capabilities, 4 /* TrueColor */);
if(null!=xv) return xv;
return getXVisualInfoImpl(screen, capabilities, 5 /* DirectColor */);
}
- private static XVisualInfo getXVisualInfoImpl(AbstractGraphicsScreen screen, CapabilitiesImmutable capabilities, int c_class)
+ private static XVisualInfo getXVisualInfoImpl(final AbstractGraphicsScreen screen, final CapabilitiesImmutable capabilities, final int c_class)
{
XVisualInfo ret = null;
- int[] num = { -1 };
+ final int[] num = { -1 };
- XVisualInfo vinfo_template = XVisualInfo.create();
+ final XVisualInfo vinfo_template = XVisualInfo.create();
vinfo_template.setScreen(screen.getIndex());
vinfo_template.setC_class(c_class);
- long display = screen.getDevice().getHandle();
+ final long display = screen.getDevice().getHandle();
- XVisualInfo[] vinfos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, vinfo_template, num, 0);
+ final XVisualInfo[] vinfos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, vinfo_template, num, 0);
XVisualInfo best=null;
- int rdepth = capabilities.getRedBits() + capabilities.getGreenBits() + capabilities.getBlueBits() + capabilities.getAlphaBits();
+ final int rdepth = capabilities.getRedBits() + capabilities.getGreenBits() + capabilities.getBlueBits() + capabilities.getAlphaBits();
for (int i = 0; vinfos!=null && i < num[0]; i++) {
- if ( best == null ||
+ if ( best == null ||
best.getDepth() < vinfos[i].getDepth() )
{
best = vinfos[i];
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index 93b7f3487..2414248b4 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -34,6 +34,7 @@
package jogamp.nativewindow.x11;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -42,22 +43,27 @@ import javax.media.nativewindow.NativeWindowFactory;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NWJNILibLoader;
+import jogamp.nativewindow.ToolkitProperties;
import com.jogamp.common.util.LongObjectHashMap;
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
/**
* Contains a thread safe X11 utility to retrieve display connections.
*/
-public class X11Util {
- /**
+public class X11Util implements ToolkitProperties {
+ public static final boolean DEBUG = Debug.debug("X11Util");
+
+ /**
* See Bug 515 - https://jogamp.org/bugzilla/show_bug.cgi?id=515
- * <p>
+ * <p>
* It is observed that ATI X11 drivers, eg.
- * <ul>
+ * <ul>
* <li>fglrx 8.78.6,</li>
* <li>fglrx 11.08/8.881 and </li>
* <li>fglrx 11.11/8.911</li>
- * </ul>
+ * </ul>
* are quite sensitive to multiple Display connections.
* </p>
* <p>
@@ -70,33 +76,39 @@ public class X11Util {
* See also native test: jogl/test-native/displayMultiple02.c
* </p>
* <p>
- * Workaround is to not close them at all if driver vendor is ATI.
+ * Workaround is to not close them at all if driver vendor is ATI
+ * during operation.
+ * </p>
+ * <p>
+ * With ATI X11 drivers all connections must be closed at JVM shutdown,
+ * otherwise a SIGSEGV (after JVM safepoint) will be caused.
* </p>
*/
public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true);
- /** Value is <code>true</code>, best 'stable' results if always using XInitThreads(). */
- public static final boolean XINITTHREADS_ALWAYS_ENABLED = true;
-
- /** Value is <code>true</code>, best 'stable' results if not using XLockDisplay/XUnlockDisplay at all. */
- public static final boolean HAS_XLOCKDISPLAY_BUG = true;
-
- public static final boolean DEBUG = Debug.debug("X11Util");
+ /** See {@link #ATI_HAS_XCLOSEDISPLAY_BUG}. */
+ public static final boolean HAS_XCLOSEDISPLAY_BUG = Debug.isPropertyDefined("nativewindow.debug.X11Util.HAS_XCLOSEDISPLAY_BUG", true);
+
+ /**
+ * See Bug 623 - https://jogamp.org/bugzilla/show_bug.cgi?id=623
+ */
+ public static final boolean ATI_HAS_MULTITHREADING_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_MULTITHREADING_BUG", true);
+
public static final boolean XSYNC_ENABLED = Debug.isPropertyDefined("nativewindow.debug.X11Util.XSync", true);
public static final boolean XERROR_STACKDUMP = DEBUG || Debug.isPropertyDefined("nativewindow.debug.X11Util.XErrorStackDump", true);
private static final boolean TRACE_DISPLAY_LIFECYCLE = Debug.isPropertyDefined("nativewindow.debug.X11Util.TraceDisplayLifecycle", true);
private static String nullDisplayName = null;
- private static boolean isX11LockAvailable = false;
- private static boolean requiresX11Lock = true;
private static volatile boolean isInit = false;
- private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues
+ private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues, or GLRendererQuirks.DontCloseX11Display
+ private static boolean hasThreadingIssues = false; // ATI/AMD X11 driver issues
- private static int setX11ErrorHandlerRecCount = 0;
- private static Object setX11ErrorHandlerLock = new Object();
+ private static final Object setX11ErrorHandlerLock = new Object();
+ private static final String X11_EXTENSION_ATIFGLRXDRI = "ATIFGLRXDRI";
+ private static final String X11_EXTENSION_ATIFGLEXTENSION = "ATIFGLEXTENSION";
-
/**
* Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
*/
public static void initSingleton() {
if(!isInit) {
@@ -104,59 +116,84 @@ public class X11Util {
if(!isInit) {
isInit = true;
if(DEBUG) {
- System.out.println("X11UtilUtil.initSingleton()");
+ System.out.println("X11Util.initSingleton()");
}
if(!NWJNILibLoader.loadNativeWindow("x11")) {
throw new NativeWindowException("NativeWindow X11 native library load error.");
}
-
- final boolean callXInitThreads = XINITTHREADS_ALWAYS_ENABLED ;
- final boolean isXInitThreadsOK = initialize0( callXInitThreads, XERROR_STACKDUMP);
- isX11LockAvailable = isXInitThreadsOK && !HAS_XLOCKDISPLAY_BUG ;
-
- final long dpy = X11Lib.XOpenDisplay(null);
+
+ final boolean isInitOK = initialize0( XERROR_STACKDUMP );
+
+ final boolean hasX11_EXTENSION_ATIFGLRXDRI, hasX11_EXTENSION_ATIFGLEXTENSION;
+ final long dpy = X11Lib.XOpenDisplay(PropertyAccess.getProperty("nativewindow.x11.display.default", true));
if(0 != dpy) {
if(XSYNC_ENABLED) {
X11Lib.XSynchronize(dpy, true);
- }
+ }
try {
nullDisplayName = X11Lib.XDisplayString(dpy);
+ hasX11_EXTENSION_ATIFGLRXDRI = X11Lib.QueryExtension(dpy, X11_EXTENSION_ATIFGLRXDRI);
+ hasX11_EXTENSION_ATIFGLEXTENSION = X11Lib.QueryExtension(dpy, X11_EXTENSION_ATIFGLEXTENSION);
} finally {
X11Lib.XCloseDisplay(dpy);
}
} else {
nullDisplayName = "nil";
+ hasX11_EXTENSION_ATIFGLRXDRI = false;
+ hasX11_EXTENSION_ATIFGLEXTENSION = false;
+ }
+ final boolean isATIFGLRX = hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION ;
+ hasThreadingIssues = ATI_HAS_MULTITHREADING_BUG && isATIFGLRX;
+ if ( !markAllDisplaysUnclosable ) {
+ markAllDisplaysUnclosable = ( ATI_HAS_XCLOSEDISPLAY_BUG && isATIFGLRX ) || HAS_XCLOSEDISPLAY_BUG;
}
-
+
if(DEBUG) {
- System.err.println("X11Util requiresX11Lock "+requiresX11Lock+
- ", XInitThreads [called "+callXInitThreads+", OK "+isXInitThreadsOK+"]"+
- ", isX11LockAvailable "+isX11LockAvailable+
- ", X11 Display(NULL) <"+nullDisplayName+">"+
- ", XSynchronize Enabled: "+XSYNC_ENABLED);
+ System.err.println("X11Util.initSingleton(): OK "+isInitOK+"]"+
+ ",\n\t X11 Display(NULL) <"+nullDisplayName+">"+
+ ",\n\t XSynchronize Enabled: " + XSYNC_ENABLED+
+ ",\n\t X11_EXTENSION_ATIFGLRXDRI " + hasX11_EXTENSION_ATIFGLRXDRI+
+ ",\n\t X11_EXTENSION_ATIFGLEXTENSION " + hasX11_EXTENSION_ATIFGLEXTENSION+
+ ",\n\t requiresToolkitLock "+requiresToolkitLock()+
+ ",\n\t hasThreadingIssues "+hasThreadingIssues()+
+ ",\n\t markAllDisplaysUnclosable "+getMarkAllDisplaysUnclosable()
+ );
// Thread.dumpStack();
}
}
}
}
}
-
- /**
+
+ // not exactly thread safe, but good enough for our purpose,
+ // which is to tag a NamedDisplay uncloseable after creation.
+ private static Object globalLock = new Object();
+ private static LongObjectHashMap openDisplayMap = new LongObjectHashMap(); // handle -> name
+ private static List<NamedDisplay> openDisplayList = new ArrayList<NamedDisplay>(); // open, no close attempt
+ private static List<NamedDisplay> reusableDisplayList = new ArrayList<NamedDisplay>(); // close attempt, marked uncloseable, for reuse
+ private static List<NamedDisplay> pendingDisplayList = new ArrayList<NamedDisplay>(); // all open (close attempt or reusable) in creation order
+ private static final HashMap<String /* displayName */, Boolean> displayXineramaEnabledMap = new HashMap<String, Boolean>();
+
+ /**
* Cleanup resources.
* <p>
* Called by {@link NativeWindowFactory#shutdown()}
* </p>
+ * @see ToolkitProperties
*/
public static void shutdown() {
if(isInit) {
synchronized(X11Util.class) {
- if(isInit) {
+ if(isInit) {
final boolean isJVMShuttingDown = NativeWindowFactory.isJVMShuttingDown() ;
- if(DEBUG || openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0) {
+ if( DEBUG ||
+ ( ( openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0 ) &&
+ ( reusableDisplayList.size() != pendingDisplayList.size() || !markAllDisplaysUnclosable )
+ ) ) {
System.err.println("X11Util.Display: Shutdown (JVM shutdown: "+isJVMShuttingDown+
", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+
", reusable (open, marked uncloseable): "+reusableDisplayList.size()+
- ", pending (post closing): "+pendingDisplayList.size()+
+ ", pending (open in creation order): "+pendingDisplayList.size()+
")");
if(DEBUG) {
Thread.dumpStack();
@@ -164,21 +201,24 @@ public class X11Util {
if( openDisplayList.size() > 0) {
X11Util.dumpOpenDisplayConnections();
}
- if( reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0 ) {
- X11Util.dumpPendingDisplayConnections();
+ if(DEBUG) {
+ if( reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0 ) {
+ X11Util.dumpPendingDisplayConnections();
+ }
}
}
-
- synchronized(globalLock) {
- // Only at JVM shutdown time, since AWT impl. seems to
- // dislike closing of X11 Display's (w/ ATI driver).
- if( isJVMShuttingDown ) {
- isInit = false;
- closePendingDisplayConnections();
+
+ // Only at JVM shutdown time, since AWT impl. seems to
+ // dislike closing of X11 Display's (w/ ATI driver).
+ if( isJVMShuttingDown ) {
+ synchronized(globalLock) {
+ isInit = false;
+ closePendingDisplayConnections();
openDisplayList.clear();
reusableDisplayList.clear();
pendingDisplayList.clear();
openDisplayMap.clear();
+ displayXineramaEnabledMap.clear();
shutdown0();
}
}
@@ -187,53 +227,52 @@ public class X11Util {
}
}
- public static synchronized boolean isNativeLockAvailable() {
- return isX11LockAvailable;
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static final boolean requiresToolkitLock() {
+ return true; // JAWT locking: yes, instead of native X11 locking w use a recursive lock per display connection.
}
- public static synchronized boolean requiresToolkitLock() {
- return requiresX11Lock;
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static final boolean hasThreadingIssues() {
+ return hasThreadingIssues; // JOGL impl. may utilize special locking "somewhere"
}
- public static void setX11ErrorHandler(boolean onoff, boolean quiet) {
+ public static void setX11ErrorHandler(final boolean onoff, final boolean quiet) {
synchronized(setX11ErrorHandlerLock) {
- if(onoff) {
- if(0==setX11ErrorHandlerRecCount) {
- setX11ErrorHandler0(true, quiet);
- }
- setX11ErrorHandlerRecCount++;
- } else {
- if(0 >= setX11ErrorHandlerRecCount) {
- throw new InternalError();
- }
- setX11ErrorHandlerRecCount--;
- if(0==setX11ErrorHandlerRecCount) {
- setX11ErrorHandler0(false, false);
- }
- }
+ setX11ErrorHandler0(onoff, quiet);
}
}
public static String getNullDisplayName() {
return nullDisplayName;
}
-
+
+ public static void markAllDisplaysUnclosable() {
+ synchronized(globalLock) {
+ markAllDisplaysUnclosable = true;
+ for(int i=0; i<openDisplayList.size(); i++) {
+ openDisplayList.get(i).setUncloseable(true);
+ }
+ for(int i=0; i<reusableDisplayList.size(); i++) {
+ reusableDisplayList.get(i).setUncloseable(true);
+ }
+ for(int i=0; i<pendingDisplayList.size(); i++) {
+ pendingDisplayList.get(i).setUncloseable(true);
+ }
+ }
+ }
+
public static boolean getMarkAllDisplaysUnclosable() {
return markAllDisplaysUnclosable;
}
- public static void setMarkAllDisplaysUnclosable(boolean v) {
- markAllDisplaysUnclosable = v;
- }
-
- private X11Util() {}
- // not exactly thread safe, but good enough for our purpose,
- // which is to tag a NamedDisplay uncloseable after creation.
- private static Object globalLock = new Object();
- private static LongObjectHashMap openDisplayMap = new LongObjectHashMap(); // handle -> name
- private static List<NamedDisplay> openDisplayList = new ArrayList<NamedDisplay>();
- private static List<NamedDisplay> reusableDisplayList = new ArrayList<NamedDisplay>();
- private static List<NamedDisplay> pendingDisplayList = new ArrayList<NamedDisplay>();
+ private X11Util() {}
public static class NamedDisplay {
final String name;
@@ -243,7 +282,7 @@ public class X11Util {
boolean unCloseable;
Throwable creationStack;
- protected NamedDisplay(String name, long handle) {
+ protected NamedDisplay(final String name, final long handle) {
this.name=name;
this.handle=handle;
this.refCount=0;
@@ -261,58 +300,58 @@ public class X11Util {
}
}
+ @Override
public final int hashCode() {
return hash32;
}
-
- public final boolean equals(Object obj) {
+
+ @Override
+ public final boolean equals(final Object obj) {
if(this == obj) { return true; }
if(obj instanceof NamedDisplay) {
return handle == ((NamedDisplay) obj).handle;
}
return false;
}
-
+
public final void addRef() { refCount++; }
public final void removeRef() { refCount--; }
-
+
public final String getName() { return name; }
public final long getHandle() { return handle; }
public final int getRefCount() { return refCount; }
- public final void setUncloseable(boolean v) { unCloseable = v; }
+ public final void setUncloseable(final boolean v) { unCloseable = v; }
public final boolean isUncloseable() { return unCloseable; }
public final Throwable getCreationStack() { return creationStack; }
@Override
- public Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
-
- @Override
public String toString() {
return "NamedX11Display["+name+", 0x"+Long.toHexString(handle)+", refCount "+refCount+", unCloseable "+unCloseable+"]";
}
}
/**
- * Closing pending Display connections in reverse order.
+ * Closing pending Display connections in original creation order, if {@link #getMarkAllDisplaysUnclosable()} is true.
*
* @return number of closed Display connections
*/
- public static int closePendingDisplayConnections() {
+ private static int closePendingDisplayConnections() {
int num=0;
synchronized(globalLock) {
- if(DEBUG) {
- System.err.println("X11Util: Closing Pending X11 Display Connections in order of their creation: "+pendingDisplayList.size());
- }
- for(int i=0; i<pendingDisplayList.size(); i++) {
- NamedDisplay ndpy = (NamedDisplay) pendingDisplayList.get(i);
+ if( getMarkAllDisplaysUnclosable() ) {
+ for(int i=0; i<pendingDisplayList.size(); i++) {
+ final NamedDisplay ndpy = pendingDisplayList.get(i);
+ if(DEBUG) {
+ final boolean closeAttempted = !openDisplayMap.containsKey(ndpy.getHandle());
+ System.err.println("X11Util.closePendingDisplayConnections(): Closing ["+i+"]: "+ndpy+" - closeAttempted "+closeAttempted);
+ }
+ XCloseDisplay(ndpy.getHandle());
+ num++;
+ }
if(DEBUG) {
- System.err.println("X11Util.closePendingDisplayConnections(): Closing ["+i+"]: "+ndpy);
+ System.err.println("X11Util.closePendingDisplayConnections(): Closed "+num+" pending display connections");
}
- XCloseDisplay(ndpy.getHandle());
- num++;
}
}
return num;
@@ -323,15 +362,15 @@ public class X11Util {
return openDisplayList.size();
}
}
-
+
public static void dumpOpenDisplayConnections() {
synchronized(globalLock) {
System.err.println("X11Util: Open X11 Display Connections: "+openDisplayList.size());
for(int i=0; i<openDisplayList.size(); i++) {
- NamedDisplay ndpy = openDisplayList.get(i);
+ final NamedDisplay ndpy = openDisplayList.get(i);
System.err.println("X11Util: Open["+i+"]: "+ndpy);
if(null!=ndpy) {
- Throwable t = ndpy.getCreationStack();
+ final Throwable t = ndpy.getCreationStack();
if(null!=t) {
t.printStackTrace();
}
@@ -339,7 +378,7 @@ public class X11Util {
}
}
}
-
+
public static int getReusableDisplayConnectionNumber() {
synchronized(globalLock) {
return reusableDisplayList.size();
@@ -356,10 +395,10 @@ public class X11Util {
synchronized(globalLock) {
System.err.println("X11Util: Reusable X11 Display Connections: "+reusableDisplayList.size());
for(int i=0; i<reusableDisplayList.size(); i++) {
- NamedDisplay ndpy = (NamedDisplay) reusableDisplayList.get(i);
+ final NamedDisplay ndpy = reusableDisplayList.get(i);
System.err.println("X11Util: Reusable["+i+"]: "+ndpy);
if(null!=ndpy) {
- Throwable t = ndpy.getCreationStack();
+ final Throwable t = ndpy.getCreationStack();
if(null!=t) {
t.printStackTrace();
}
@@ -367,10 +406,10 @@ public class X11Util {
}
System.err.println("X11Util: Pending X11 Display Connections (creation order): "+pendingDisplayList.size());
for(int i=0; i<pendingDisplayList.size(); i++) {
- NamedDisplay ndpy = (NamedDisplay) pendingDisplayList.get(i);
+ final NamedDisplay ndpy = pendingDisplayList.get(i);
System.err.println("X11Util: Pending["+i+"]: "+ndpy);
if(null!=ndpy) {
- Throwable t = ndpy.getCreationStack();
+ final Throwable t = ndpy.getCreationStack();
if(null!=t) {
t.printStackTrace();
}
@@ -379,7 +418,7 @@ public class X11Util {
}
}
- public static boolean markDisplayUncloseable(long handle) {
+ public static boolean markDisplayUncloseable(final long handle) {
NamedDisplay ndpy;
synchronized(globalLock) {
ndpy = (NamedDisplay) openDisplayMap.get(handle);
@@ -397,8 +436,8 @@ public class X11Util {
NamedDisplay namedDpy = null;
name = validateDisplayName(name);
boolean reused = false;
-
- synchronized(globalLock) {
+
+ synchronized(globalLock) {
for(int i=0; i<reusableDisplayList.size(); i++) {
if(reusableDisplayList.get(i).getName().equals(name)) {
namedDpy = reusableDisplayList.remove(i);
@@ -431,11 +470,9 @@ public class X11Util {
return namedDpy.getHandle();
}
- public static void closeDisplay(long handle) {
- NamedDisplay namedDpy;
-
+ public static void closeDisplay(final long handle) {
synchronized(globalLock) {
- namedDpy = (NamedDisplay) openDisplayMap.remove(handle);
+ final NamedDisplay namedDpy = (NamedDisplay) openDisplayMap.remove(handle);
if(null==namedDpy) {
X11Util.dumpPendingDisplayConnections();
throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped. Thread "+Thread.currentThread().getName());
@@ -444,38 +481,43 @@ public class X11Util {
X11Util.dumpPendingDisplayConnections();
throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") Mapping error: "+namedDpy+". Thread "+Thread.currentThread().getName());
}
-
+
namedDpy.removeRef();
if(!openDisplayList.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); }
-
- if(!namedDpy.isUncloseable()) {
+
+ if( markAllDisplaysUnclosable ) {
+ // if set-mark 'slipped' this one .. just to be safe!
+ namedDpy.setUncloseable(true);
+ }
+ if( !namedDpy.isUncloseable() ) {
XCloseDisplay(namedDpy.getHandle());
pendingDisplayList.remove(namedDpy);
} else {
// for reuse
+ X11Lib.XSync(namedDpy.getHandle(), true); // flush output buffer and discard all events
reusableDisplayList.add(namedDpy);
}
-
+
if(DEBUG) {
System.err.println("X11Util.Display: Closed (real: "+(!namedDpy.isUncloseable())+") "+namedDpy+". Thread "+Thread.currentThread().getName());
- }
+ }
}
}
- public static NamedDisplay getNamedDisplay(long handle) {
+ public static NamedDisplay getNamedDisplay(final long handle) {
synchronized(globalLock) {
return (NamedDisplay) openDisplayMap.get(handle);
}
}
- /**
+ /**
* @return If name is null, it returns the previous queried NULL display name,
* otherwise the name. */
- public static String validateDisplayName(String name) {
+ public static String validateDisplayName(final String name) {
return ( null == name || AbstractGraphicsDevice.DEFAULT_CONNECTION.equals(name) ) ? getNullDisplayName() : name ;
}
- public static String validateDisplayName(String name, long handle) {
+ public static String validateDisplayName(String name, final long handle) {
if( ( null==name || AbstractGraphicsDevice.DEFAULT_CONNECTION.equals(name) ) && 0!=handle) {
name = X11Lib.XDisplayString(handle);
}
@@ -488,54 +530,61 @@ public class X11Util {
**
*******************************/
- public static long XOpenDisplay(String arg0) {
- NativeWindowFactory.getDefaultToolkitLock().lock();
- try {
- long handle = X11Lib.XOpenDisplay(arg0);
- if(XSYNC_ENABLED && 0 != handle) {
- X11Lib.XSynchronize(handle, true);
- }
- if(TRACE_DISPLAY_LIFECYCLE) {
- System.err.println(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle));
- // Thread.dumpStack();
- }
- return handle;
- } finally {
- NativeWindowFactory.getDefaultToolkitLock().unlock();
+ public static long XOpenDisplay(final String arg0) {
+ final long handle = X11Lib.XOpenDisplay(arg0);
+ if(XSYNC_ENABLED && 0 != handle) {
+ X11Lib.XSynchronize(handle, true);
}
+ if(TRACE_DISPLAY_LIFECYCLE) {
+ System.err.println(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle));
+ // Thread.dumpStack();
+ }
+ return handle;
}
- public static int XCloseDisplay(long display) {
- NativeWindowFactory.getDefaultToolkitLock().lock();
+ public static int XCloseDisplay(final long display) {
+ if(TRACE_DISPLAY_LIFECYCLE) {
+ System.err.println(Thread.currentThread()+" - X11Util.XCloseDisplay() 0x"+Long.toHexString(display));
+ // Thread.dumpStack();
+ }
+ int res = -1;
try {
- if(TRACE_DISPLAY_LIFECYCLE) {
- System.err.println(Thread.currentThread()+" - X11Util.XCloseDisplay() 0x"+Long.toHexString(display));
- // Thread.dumpStack();
- }
- int res = -1;
- X11Util.setX11ErrorHandler(true, DEBUG ? false : true);
- try {
- res = X11Lib.XCloseDisplay(display);
- } catch (Exception ex) {
- System.err.println("X11Util: Catched Exception:");
- ex.printStackTrace();
- } finally {
- X11Util.setX11ErrorHandler(false, false);
- }
- return res;
- } finally {
- NativeWindowFactory.getDefaultToolkitLock().unlock();
+ res = X11Lib.XCloseDisplay(display);
+ } catch (final Exception ex) {
+ System.err.println("X11Util: Caught exception:");
+ ex.printStackTrace();
}
+ return res;
}
static volatile boolean XineramaFetched = false;
static long XineramaLibHandle = 0;
static long XineramaQueryFunc = 0;
-
- public static boolean XineramaIsEnabled(long display) {
- if(0==display) {
- throw new IllegalArgumentException("Display NULL");
+
+ public static boolean XineramaIsEnabled(final X11GraphicsDevice device) {
+ if(null == device) {
+ throw new IllegalArgumentException("X11 Display device is NULL");
}
+ device.lock();
+ try {
+ return XineramaIsEnabled(device.getHandle());
+ } finally {
+ device.unlock();
+ }
+ }
+
+ public static boolean XineramaIsEnabled(final long displayHandle) {
+ if( 0 == displayHandle ) {
+ throw new IllegalArgumentException("X11 Display handle is NULL");
+ }
+ final String displayName = X11Lib.XDisplayString(displayHandle);
+ synchronized(displayXineramaEnabledMap) {
+ final Boolean b = displayXineramaEnabledMap.get(displayName);
+ if(null != b) {
+ return b.booleanValue();
+ }
+ }
+ final boolean res;
if(!XineramaFetched) { // volatile: ok
synchronized(X11Util.class) {
if( !XineramaFetched ) {
@@ -548,22 +597,27 @@ public class X11Util {
}
}
if(0!=XineramaQueryFunc) {
- final boolean res = X11Lib.XineramaIsEnabled(XineramaQueryFunc, display);
+ res = X11Lib.XineramaIsEnabled(XineramaQueryFunc, displayHandle);
+ } else {
if(DEBUG) {
- System.err.println("XineramaIsEnabled: "+res);
+ System.err.println("XineramaIsEnabled: Couldn't bind to Xinerama - lib 0x"+Long.toHexString(XineramaLibHandle)+
+ "query 0x"+Long.toHexString(XineramaQueryFunc));
}
- return res;
- } else if(DEBUG) {
- System.err.println("XineramaIsEnabled: Couldn't bind to Xinerama - lib 0x"+Long.toHexString(XineramaLibHandle)+
- "query 0x"+Long.toHexString(XineramaQueryFunc));
+ res = false;
}
- return false;
+ synchronized(displayXineramaEnabledMap) {
+ if(DEBUG) {
+ System.err.println("XineramaIsEnabled Cache: Display "+displayName+" (0x"+Long.toHexString(displayHandle)+") -> "+res);
+ }
+ displayXineramaEnabledMap.put(displayName, Boolean.valueOf(res));
+ }
+ return res;
}
-
+
private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI
private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
-
- private static native boolean initialize0(boolean firstUIActionOnProcess, boolean debug);
+
+ private static native boolean initialize0(boolean debug);
private static native void shutdown0();
private static native void setX11ErrorHandler0(boolean onoff, boolean quiet);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
index 1de03e8be..6b606df97 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -59,16 +59,17 @@ import jogamp.nativewindow.x11.X11Lib;
import jogamp.nativewindow.x11.X11Util;
public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFactory {
-
+
public static void registerFactory() {
GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, CapabilitiesImmutable.class, new X11AWTGraphicsConfigurationFactory());
- }
+ }
private X11AWTGraphicsConfigurationFactory() {
}
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, final int nativeVisualID) {
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects");
@@ -79,19 +80,19 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, (AWTGraphicsScreen)absScreen, nativeVisualID);
}
-
+
public static AWTGraphicsConfiguration chooseGraphicsConfigurationStatic(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AWTGraphicsScreen awtScreen, int nativeVisualID) {
+ CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser, final AWTGraphicsScreen awtScreen, final int nativeVisualID) {
if(DEBUG) {
System.err.println("X11AWTGraphicsConfigurationFactory: got "+awtScreen);
}
-
+
final GraphicsDevice device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice();
-
+
final long displayHandleAWT = X11SunJDKReflection.graphicsDeviceGetDisplay(device);
final long displayHandle;
- boolean owner = false;
+ final boolean owner;
if(0==displayHandleAWT) {
displayHandle = X11Util.openDisplay(null);
owner = true;
@@ -101,8 +102,8 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
} else {
/**
* Using the AWT display handle works fine with NVidia.
- * However we experienced different results w/ AMD drivers,
- * some work, but some behave erratic.
+ * However we experienced different results w/ AMD drivers,
+ * some work, but some behave erratic.
* I.e. hangs in XQueryExtension(..) via X11GraphicsScreen.
*/
final String displayName = X11Lib.XDisplayString(displayHandleAWT);
@@ -112,15 +113,14 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
System.err.println(getThreadName()+" - X11AWTGraphicsConfigurationFactory: AWT dpy "+displayName+" / "+toHexString(displayHandleAWT)+", create X11 display "+toHexString(displayHandle));
}
}
- final ToolkitLock lock = owner ?
- NativeWindowFactory.getDefaultToolkitLock(NativeWindowFactory.TYPE_AWT) : // own non-shared X11 display connection, no X11 lock
- NativeWindowFactory.createDefaultToolkitLock(NativeWindowFactory.TYPE_X11, NativeWindowFactory.TYPE_AWT, displayHandle);
- final X11GraphicsDevice x11Device = new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, lock, owner);
+ // Global JAWT lock required - No X11 resource locking due to private display connection
+ final ToolkitLock lock = NativeWindowFactory.getDefaultToolkitLock(NativeWindowFactory.TYPE_AWT);
+ final X11GraphicsDevice x11Device = new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, lock, owner);
final X11GraphicsScreen x11Screen = new X11GraphicsScreen(x11Device, awtScreen.getIndex());
if(DEBUG) {
System.err.println("X11AWTGraphicsConfigurationFactory: made "+x11Screen);
}
-
+
final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(x11Device, capsChosen);
AbstractGraphicsConfiguration aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen, nativeVisualID);
if (aConfig == null) {
@@ -130,7 +130,7 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
System.err.println("X11AWTGraphicsConfigurationFactory: chosen config: "+aConfig);
// Thread.dumpStack();
}
-
+
//
// Match the X11/GL Visual with AWT:
// - choose a config AWT agnostic and then
@@ -138,12 +138,12 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
//
// The resulting GraphicsConfiguration has to be 'forced' on the AWT native peer,
// ie. returned by GLCanvas's getGraphicsConfiguration() befor call by super.addNotify().
- //
+ //
final GraphicsConfiguration[] configs = device.getConfigurations();
int visualID = aConfig.getVisualID(VIDType.NATIVE);
if(VisualIDHolder.VID_UNDEFINED != visualID) {
for (int i = 0; i < configs.length; i++) {
- GraphicsConfiguration gc = configs[i];
+ final GraphicsConfiguration gc = configs[i];
if (gc != null) {
if (X11SunJDKReflection.graphicsConfigurationGetVisualID(gc) == visualID) {
if(DEBUG) {
diff --git a/src/nativewindow/native/JAWT_DrawingSurfaceInfo.c b/src/nativewindow/native/JAWT_DrawingSurfaceInfo.c
index 2a6651007..5c77b6d46 100644
--- a/src/nativewindow/native/JAWT_DrawingSurfaceInfo.c
+++ b/src/nativewindow/native/JAWT_DrawingSurfaceInfo.c
@@ -43,7 +43,7 @@
#define PLATFORM_DSI_SIZE sizeof(JAWT_Win32DrawingSurfaceInfo)
#elif defined(linux) || defined(__sun) || defined(__FreeBSD__) || defined(_HPUX)
#define PLATFORM_DSI_SIZE sizeof(JAWT_X11DrawingSurfaceInfo)
-#elif defined(macosx)
+#elif defined(__APPLE__)
#define PLATFORM_DSI_SIZE sizeof(JAWT_MacOSXDrawingSurfaceInfo)
#else
ERROR: port JAWT_DrawingSurfaceInfo.c to your platform
diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c
index d2fdd5d69..e65f87272 100644
--- a/src/nativewindow/native/NativewindowCommon.c
+++ b/src/nativewindow/native/NativewindowCommon.c
@@ -1,21 +1,57 @@
#include "NativewindowCommon.h"
#include <string.h>
+#include <sys/time.h>
+
+// #define STDERR_TO_FILE 1
static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
static jclass runtimeExceptionClz=NULL;
+static JavaVM *_jvmHandle = NULL;
+static int _jvmVersion = 0;
+
+int NativewindowCommon_init(JNIEnv *env) {
+ if(NULL==_jvmHandle) {
+ if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+ NativewindowCommon_FatalError(env, "Nativewindow: Can't fetch JavaVM handle");
+ } else {
+ _jvmVersion = (*env)->GetVersion(env);
+ }
+ jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "Nativewindow: Can't find %s", ClazzNameRuntimeException);
+ }
+ runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==runtimeExceptionClz) {
+ NativewindowCommon_FatalError(env, "Nativewindow: Can't use %s", ClazzNameRuntimeException);
+ }
+ #ifdef STDERR_TO_FILE
+ FILE * old_stderr = stderr;
+ FILE * new_stderr = freopen("jogamp_stderr.log", "w", stderr);
+ fprintf(stderr, "STDERR_TO_FILE: %p -> %p\n", old_stderr, new_stderr);
+ #endif
+ return 1;
+ }
+ return 0;
+}
+
void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
- fprintf(stderr, "%s\n", buffer);
- (*env)->FatalError(env, buffer);
+ fprintf(stderr, "%s\n", buffer);
+ if(NULL != env) {
+ (*env)->FatalError(env, buffer);
+ }
+ }
}
void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
@@ -23,27 +59,20 @@ void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, .
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if(NULL==_jvmHandle) {
+ NativewindowCommon_FatalError(env, "Nativewindow: NULL JVM handle, call NativewindowCommon_init 1st\n");
+ return;
+ }
- (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
-}
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
-int NativewindowCommon_init(JNIEnv *env) {
- if(NULL==runtimeExceptionClz) {
- jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "Nativewindow: can't find %s", ClazzNameRuntimeException);
- }
- runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==runtimeExceptionClz) {
- NativewindowCommon_FatalError(env, "Nativewindow: can't use %s", ClazzNameRuntimeException);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
}
- return 1;
}
- return 0;
}
const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText) {
@@ -67,37 +96,63 @@ const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass cla
jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
{
jchar* strChars = NULL;
- strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
- if (strChars != NULL) {
- (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ if( NULL != env && 0 != str ) {
+ strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
+ if (strChars != NULL) {
+ (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ }
}
return strChars;
}
-JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached) {
+JNIEnv* NativewindowCommon_GetJNIEnv (int asDaemon, int * shallBeDetached) {
JNIEnv* curEnv = NULL;
JNIEnv* newEnv = NULL;
int envRes;
+ if(NULL==_jvmHandle) {
+ fprintf(stderr, "Nativewindow GetJNIEnv: NULL JVM handle, call NativewindowCommon_init 1st\n");
+ return NULL;
+ }
+
// retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
+ envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ;
if( JNI_EDETACHED == envRes ) {
// detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
+ if( asDaemon ) {
+ envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL);
+ } else {
+ envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL);
+ }
+ if( JNI_OK != envRes ) {
+ fprintf(stderr, "Nativewindow GetJNIEnv: Can't attach thread: %d\n", envRes);
return NULL;
}
curEnv = newEnv;
} else if( JNI_OK != envRes ) {
// oops ..
- fprintf(stderr, "can't GetEnv: %d\n", envRes);
+ fprintf(stderr, "Nativewindow GetJNIEnv: Can't GetEnv: %d\n", envRes);
return NULL;
}
if (curEnv==NULL) {
- fprintf(stderr, "env is NULL\n");
+ fprintf(stderr, "Nativewindow GetJNIEnv: env is NULL\n");
return NULL;
}
*shallBeDetached = NULL != newEnv;
return curEnv;
}
+void NativewindowCommon_ReleaseJNIEnv (int shallBeDetached) {
+ if(NULL == _jvmHandle) {
+ fprintf(stderr, "Nativewindow ReleaseJNIEnv: No JavaVM handle registered, call NativewindowCommon_init(..) 1st");
+ } else if(shallBeDetached) {
+ (*_jvmHandle)->DetachCurrentThread(_jvmHandle);
+ }
+}
+
+int64_t NativewindowCommon_CurrentTimeMillis() {
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
diff --git a/src/nativewindow/native/NativewindowCommon.h b/src/nativewindow/native/NativewindowCommon.h
index 73b890c4f..f19552e33 100644
--- a/src/nativewindow/native/NativewindowCommon.h
+++ b/src/nativewindow/native/NativewindowCommon.h
@@ -1,9 +1,37 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
#ifndef NATIVEWINDOW_COMMON_H
#define NATIVEWINDOW_COMMON_H 1
#include <jni.h>
#include <stdlib.h>
+#include <gluegen_stdint.h>
int NativewindowCommon_init(JNIEnv *env);
@@ -13,6 +41,40 @@ jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...);
void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
-JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached);
+/**
+ *
+ * 1) Init static jvmHandle, jvmVersion and clazz references
+ * from an early initialization call w/ valid 'JNIEnv * env'
+
+ NativewindowCommon_init(env);
+
+ *
+ * 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv
+ *
+
+ int asDaemon = 0;
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("drawRect: null JNIEnv\n");
+ return;
+ }
+
+ *
+ * 3) Use JNIEnv ..
+ *
+ .. your JNIEnv code here ..
+
+ *
+ * 4) Detach thread from JVM if required, i.e. not attached as daemon!
+ * Not recommended for recurring _daemon_ threads (performance)
+ *
+ NewtCommon_ReleaseJNIEnv(shallBeDetached);
+ */
+JNIEnv* NativewindowCommon_GetJNIEnv (int asDaemon, int * shallBeDetached);
+
+void NativewindowCommon_ReleaseJNIEnv (int shallBeDetached);
+
+int64_t NativewindowCommon_CurrentTimeMillis();
#endif
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionRendererListenerBase01.java b/src/nativewindow/native/macosx/NativeWindowProtocols.h
index 8439d1fff..98e864f8b 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionRendererListenerBase01.java
+++ b/src/nativewindow/native/macosx/NativeWindowProtocols.h
@@ -1,16 +1,16 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright 2013 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,33 +20,39 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package com.jogamp.opengl.test.junit.graph.demos;
-import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.curve.opengl.RegionRenderer;
-import com.jogamp.graph.curve.opengl.RenderState;
+#ifndef NATIVEWINDOWPROTOCOLS_H
+#define NATIVEWINDOWPROTOCOLS_H 1
+
+/**
+ * CALayer size needs to be set using the AWT component size.
+ * See detailed description in JAWTUtil.java and sync w/ changed.
+ */
+#define NW_DEDICATEDFRAME_QUIRK_SIZE ( 1 << 0 )
-/**
- *
- * Action Keys:
- * - 1/2: zoom in/out
- * - 3/4: font +/-
- * - 6/7: 2nd pass texture size
- * - 0/9: rotate
- * - s: toogle draw 'font set'
- * - f: toggle draw fps
- * - v: toggle v-sync
- * - space: toggle font (ubuntu/java)
+/**
+ * CALayer position needs to be set to zero.
+ * See detailed description in JAWTUtil.java and sync w/ changed.
+ */
+#define NW_DEDICATEDFRAME_QUIRK_POSITION ( 1 << 1 )
+
+/**
+ * CALayer position needs to be derived from AWT position.
+ * in relation to super CALayer.
+ * See detailed description in JAWTUtil.java and sync w/ changed.
*/
-public abstract class GPURegionRendererListenerBase01 extends GPURendererListenerBase01 {
- OutlineShape outlineShape = null;
+#define NW_DEDICATEDFRAME_QUIRK_LAYOUT ( 1 << 2 )
+
+#import <Foundation/NSGeometry.h>
+
+@protocol NWDedicatedFrame
+- (void)setDedicatedFrame:(CGRect)dFrame quirks:(int)quirks;
+@end
+
+#endif /* NATIVEWINDOWPROTOCOLS_H_ */
- public GPURegionRendererListenerBase01(RenderState rs, int renderModes, boolean debug, boolean trace) {
- super(RegionRenderer.create(rs, renderModes), renderModes, debug, trace);
- }
-} \ No newline at end of file
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index 1cf41fc9d..127b329d1 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -32,13 +32,14 @@
#include <stdarg.h>
#include <unistd.h>
#include <AppKit/AppKit.h>
+#import <QuartzCore/QuartzCore.h>
+#import "NativeWindowProtocols.h"
#include "NativewindowCommon.h"
#include "jogamp_nativewindow_macosx_OSXUtil.h"
#include "jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow.h"
#include <jawt_md.h>
-#import <JavaNativeFoundation.h>
// #define VERBOSE 1
//
@@ -49,6 +50,16 @@
#define DBG_PRINT(...)
#endif
+// #define VERBOSE2 1
+//
+#ifdef VERBOSE2
+ #define DBG_PRINT2(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#else
+ #define DBG_PRINT2(...)
+#endif
+
+// #define DBG_LIFECYCLE 1
+
static const char * const ClazzNameRunnable = "java/lang/Runnable";
static jmethodID runnableRunID = NULL;
@@ -64,11 +75,9 @@ static const char * const ClazzNameInsetsCstrSignature = "(IIII)V";
static jclass insetsClz = NULL;
static jmethodID insetsCstr = NULL;
-static int _initialized=0;
-
JNIEXPORT jboolean JNICALL
Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
- if(0==_initialized) {
+ if( NativewindowCommon_init(env) ) {
jclass c;
c = (*env)->FindClass(env, ClazzNamePoint);
if(NULL==c) {
@@ -108,7 +117,6 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
if(NULL==runnableRunID) {
NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.run()V", ClazzNameRunnable);
}
- _initialized=1;
}
return JNI_TRUE;
}
@@ -116,13 +124,25 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
JNIEXPORT jboolean JNICALL
Java_jogamp_nativewindow_macosx_OSXUtil_isNSView0(JNIEnv *env, jclass _unused, jlong object) {
NSObject *nsObj = (NSObject*) (intptr_t) object;
- return [nsObj isMemberOfClass:[NSView class]];
+ jboolean u = [nsObj isKindOfClass:[NSView class]];
+ DBG_PRINT( "isNSView(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+ return u;
}
JNIEXPORT jboolean JNICALL
Java_jogamp_nativewindow_macosx_OSXUtil_isNSWindow0(JNIEnv *env, jclass _unused, jlong object) {
NSObject *nsObj = (NSObject*) (intptr_t) object;
- return [nsObj isMemberOfClass:[NSWindow class]];
+ jboolean u = [nsObj isKindOfClass:[NSWindow class]];
+ DBG_PRINT( "isNSWindow(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+ return u;
+}
+
+static CGDirectDisplayID OSXUtil_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
+ // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?!
+ NSDictionary * dict = [screen deviceDescription];
+ NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"];
+ // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size
+ return (CGDirectDisplayID) [val integerValue];
}
/*
@@ -139,10 +159,6 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS
* return location in 0/0 top-left space,
* OSX is 0/0 bottom-left space naturally
*/
- NSRect r;
- int dest_x=-1;
- int dest_y=-1;
-
NSObject *nsObj = (NSObject*) (intptr_t) winOrView;
NSWindow* win = NULL;
NSView* view = NULL;
@@ -154,27 +170,36 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS
view = (NSView*) nsObj;
win = [view window];
} else {
- NativewindowCommon_throwNewRuntimeException(env, "neither win not view %p\n", nsObj);
+ NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj);
}
- NSScreen* screen = [win screen];
- NSRect screenRect = [screen frame];
- NSRect winFrame = [win frame];
+ NSRect viewFrame = [view frame];
+ NSRect r;
r.origin.x = src_x;
- r.origin.y = winFrame.size.height - src_y; // y-flip for 0/0 top-left
+ r.origin.y = viewFrame.size.height - src_y; // y-flip for 0/0 top-left
r.size.width = 0;
r.size.height = 0;
// NSRect rS = [win convertRectToScreen: r]; // 10.7
- NSPoint oS = [win convertBaseToScreen: r.origin];
- /**
- NSLog(@"LOS.1: (bottom-left) %d/%d, screen-y[0: %d, h: %d], (top-left) %d/%d\n",
- (int)oS.x, (int)oS.y, (int)screenRect.origin.y, (int) screenRect.size.height,
- (int)oS.x, (int)(screenRect.origin.y + screenRect.size.height - oS.y)); */
+ NSPoint oS = [win convertBaseToScreen: r.origin]; // BL-screen
- dest_x = (int) oS.x;
- dest_y = (int) screenRect.origin.y + screenRect.size.height - oS.y;
+ NSScreen* screen = [win screen];
+ CGDirectDisplayID display = OSXUtil_getCGDirectDisplayIDByNSScreen(screen);
+ CGRect frameTL = CGDisplayBounds (display); // origin top-left
+ NSRect frameBL = [screen frame]; // origin bottom-left
+ oS.y = frameTL.origin.y + frameTL.size.height - ( oS.y - frameBL.origin.y ); // y-flip from BL-screen -> TL-screen
- jobject res = (*env)->NewObject(env, pointClz, pointCstr, (jint)dest_x, (jint)dest_y);
+#ifdef VERBOSE
+ NSRect winFrame = [win frame];
+ DBG_PRINT( "GetLocationOnScreen0(window: %p):: point-in[%d/%d], winFrame[%d/%d %dx%d], viewFrame[%d/%d %dx%d], screen tl[%d/%d %dx%d] bl[%d/%d %dx%d] -> %d/%d\n",
+ win, (int)src_x, (int)src_y,
+ (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height,
+ (int)viewFrame.origin.x, (int)viewFrame.origin.y, (int)viewFrame.size.width, (int)viewFrame.size.height,
+ (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height,
+ (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height,
+ (int)oS.x, (int)oS.y);
+#endif
+
+ jobject res = (*env)->NewObject(env, pointClz, pointCstr, (jint)oS.x, (jint)oS.y);
[pool release];
@@ -203,7 +228,7 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0
view = (NSView*) nsObj;
win = [view window];
} else {
- NativewindowCommon_throwNewRuntimeException(env, "neither win not view %p\n", nsObj);
+ NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj);
}
NSRect frameRect = [win frame];
@@ -226,6 +251,75 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetPixelScale0
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale0
+ (JNIEnv *env, jclass unused, jint screen_idx)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ CGFloat pixelScale;
+ NSScreen *screen;
+ NSArray *screens = [NSScreen screens];
+ if( screen_idx<0 || screen_idx>=[screens count] ) {
+ screen = NULL;
+ pixelScale = 0.0;
+ } else {
+ screen = (NSScreen *) [screens objectAtIndex: screen_idx];
+ pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen backingScaleFactor]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+ }
+ [pool release];
+
+ return (jdouble)pixelScale;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetPixelScale1
+ * Signature: (J)D
+ */
+JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale1
+ (JNIEnv *env, jclass unused, jlong winOrView)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSObject *nsObj = (NSObject*) (intptr_t) winOrView;
+ NSWindow* win = NULL;
+ NSView* view = NULL;
+ NSScreen *screen = NULL;
+
+ if( [nsObj isKindOfClass:[NSWindow class]] ) {
+ win = (NSWindow*) nsObj;
+ view = [win contentView];
+ screen = [win screen];
+ } else if( nsObj != NULL && [nsObj isKindOfClass:[NSView class]] ) {
+ view = (NSView*) nsObj;
+ win = [view window];
+ screen = [win screen];
+ } else {
+ NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj);
+ }
+
+ CGFloat pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen backingScaleFactor]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+
+ [pool release];
+
+ return (jdouble)pixelScale;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: CreateNSWindow0
* Signature: (IIIIZ)J
*/
@@ -239,7 +333,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0
NSWindow* myWindow = [[NSWindow alloc] initWithContentRect: rect
styleMask: NSBorderlessWindowMask
backing: NSBackingStoreBuffered
- defer: YES];
+ defer: NO]; // Bug 1087: Set default framebuffer, hence enforce NSView realization
[myWindow setReleasedWhenClosed: YES]; // default
[myWindow setPreservesContentDuringLiveResize: YES];
// Remove animations
@@ -255,6 +349,13 @@ NS_ENDHANDLER
[myWindow setOpaque: NO];
[myWindow setBackgroundColor: [NSColor clearColor]];
+ // Bug 1087: Set default framebuffer, hence enforce NSView realization
+ // However, using the NSWindow ctor w/ 'defer: NO' seems sufficient
+ // and we are invisible - no focus!
+ // NSView* myView = [myWindow contentView];
+ // [myView lockFocus];
+ // [myView unlockFocus];
+
[pool release];
return (jlong) ((intptr_t) myWindow);
@@ -313,38 +414,260 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSWindow0
return res;
}
+/**
+ * Track lifecycle via DBG_PRINT messages, if VERBOSE is enabled!
+ */
+@interface MyCALayer: CALayer
+{
+@private
+ BOOL fixedFrameSet;
+ CGRect fixedFrame;
+ float visibleOpacity;
+ BOOL visibleOpacityZeroed;
+}
+- (id)init;
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+- (void)dealloc;
+#endif
+- (id<CAAction>)actionForKey:(NSString *)key ;
+- (void)layoutSublayers;
+- (void)setFrame:(CGRect) frame;
+- (void)fixCALayerLayout: (CALayer*) subLayer visible:(BOOL)visible x:(jint)x y:(jint)y width:(jint)width height:(jint)height caLayerQuirks:(jint)caLayerQuirks force:(jboolean) force;
+
+@end
+
+@implementation MyCALayer
+
+- (id)init
+{
+ DBG_PRINT("MyCALayer::init.0\n");
+ MyCALayer * o = [super init];
+ o->fixedFrameSet = 0;
+ o->fixedFrame = CGRectMake(0, 0, 0, 0);
+ o->visibleOpacity = 1.0;
+ o->visibleOpacityZeroed = 0;
+ DBG_PRINT("MyCALayer::init.X: new %p\n", o);
+ return o;
+}
+
+#ifdef DBG_LIFECYCLE
+
+- (id)retain
+{
+ DBG_PRINT("MyCALayer::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyCALayer::retain: %@",[NSThread callStackSymbols]);
+ id o = [super retain];
+ DBG_PRINT("MyCALayer::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+ return o;
+}
+
+- (oneway void)release
+{
+ DBG_PRINT("MyCALayer::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyCALayer::release: %@",[NSThread callStackSymbols]);
+ [super release];
+ // DBG_PRINT("MyCALayer::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+- (void)dealloc
+{
+ DBG_PRINT("MyCALayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyCALayer::dealloc: %@",[NSThread callStackSymbols]);
+ [super dealloc];
+ // DBG_PRINT("MyCALayer.dealloc.X: %p\n", self);
+}
+
+#endif
+
+- (id<CAAction>)actionForKey:(NSString *)key
+{
+ DBG_PRINT("MyCALayer::actionForKey.0 %p key %s -> NIL\n", self, [key UTF8String]);
+ return nil;
+ // return [super actionForKey: key];
+}
+
+- (void)layoutSublayers
+{
+ if( fixedFrameSet ) {
+ NSArray* subs = [self sublayers];
+ if( NULL != subs ) {
+ CGRect rFrame = [self frame];
+ if( !CGRectEqualToRect(fixedFrame, rFrame) ) {
+ #ifdef VERBOSE
+ DBG_PRINT("CALayer::layoutSublayers.0: Root %p frame %lf/%lf %lfx%lf -> %lf/%lf %lfx%lf\n",
+ self,
+ rFrame.origin.x, rFrame.origin.y, rFrame.size.width, rFrame.size.height,
+ fixedFrame.origin.x, fixedFrame.origin.y, fixedFrame.size.width, fixedFrame.size.height);
+ #endif
+ [super setFrame: fixedFrame];
+ }
+ NSUInteger i = 0;
+ for(i=0; i<[subs count]; i++) {
+ CALayer* sub = [subs objectAtIndex: i];
+ CGRect sFrame = [sub frame];
+ CGRect sFrame2 = CGRectMake(0, 0, fixedFrame.size.width, fixedFrame.size.height);
+ if( !CGRectEqualToRect(sFrame2, sFrame) ) {
+ #ifdef VERBOSE
+ DBG_PRINT("CALayer::layoutSublayers.1: Sub[%d] %p frame %lf/%lf %lfx%lf -> %lf/%lf %lfx%lf\n",
+ (int)i, sub,
+ sFrame.origin.x, sFrame.origin.y, sFrame.size.width, sFrame.size.height,
+ sFrame2.origin.x, sFrame2.origin.y, sFrame2.size.width, sFrame2.size.height);
+ #endif
+ [sub setFrame: sFrame2];
+ }
+ #ifdef VERBOSE
+ DBG_PRINT("CALayer::layoutSublayers.X: Root %p . Sub[%d] %p : frame r: %lf/%lf %lfx%lf . s: %lf/%lf %lfx%lf\n",
+ self, (int)i, sub,
+ rFrame.origin.x, rFrame.origin.y, rFrame.size.width, rFrame.size.height,
+ sFrame.origin.x, sFrame.origin.y, sFrame.size.width, sFrame.size.height);
+ #endif
+ }
+ }
+ } else {
+ [super layoutSublayers];
+ }
+}
+
+- (void) setFrame:(CGRect) frame
+{
+ if( fixedFrameSet ) {
+ [super setFrame: fixedFrame];
+ } else {
+ [super setFrame: frame];
+ }
+}
+
+- (void)fixCALayerLayout: (CALayer*) subLayer visible:(BOOL)visible x:(jint)x y:(jint)y width:(jint)width height:(jint)height caLayerQuirks:(jint)caLayerQuirks force:(jboolean) force
+{
+ int loutQuirk = 0 != ( NW_DEDICATEDFRAME_QUIRK_LAYOUT & caLayerQuirks );
+ {
+ CALayer* superLayer = [self superlayer];
+ CGRect superFrame = [superLayer frame];
+ CGRect lFrame = [self frame];
+ if( visible ) {
+ // Opacity must be 0 to see through the disabled CALayer
+ [subLayer setOpacity: visibleOpacity];
+ [self setOpacity: visibleOpacity];
+ [self setHidden: NO];
+ [subLayer setHidden: NO];
+ visibleOpacityZeroed = 0;
+ } else {
+ [subLayer setHidden: YES];
+ [self setHidden: YES];
+ if( !visibleOpacityZeroed ) {
+ visibleOpacity = [self opacity];
+ }
+ [subLayer setOpacity: 0.0];
+ [self setOpacity: 0.0];
+ visibleOpacityZeroed = 1;
+ }
+ int posQuirk = 0 != ( NW_DEDICATEDFRAME_QUIRK_POSITION & caLayerQuirks ) && ( lFrame.origin.x!=0 || lFrame.origin.y!=0 );
+ int sizeQuirk = 0 != ( NW_DEDICATEDFRAME_QUIRK_SIZE & caLayerQuirks ) && ( lFrame.size.width!=width || lFrame.size.height!=height );
+ if( !posQuirk || loutQuirk ) {
+ // Use root layer position, sub-layer will be on 0/0,
+ // Given AWT position is location on screen w/o insets and top/left origin!
+ fixedFrame.origin.x = x;
+ fixedFrame.origin.y = superFrame.size.height - height - y; // AWT's position top/left -> bottom/left
+ posQuirk |= 8;
+ } else {
+ // Buggy super layer position, always use 0/0
+ fixedFrame.origin.x = 0;
+ fixedFrame.origin.y = 0;
+ }
+ if( !sizeQuirk ) {
+ fixedFrame.size.width = lFrame.size.width;
+ fixedFrame.size.height = lFrame.size.height;
+ } else {
+ fixedFrame.size.width = width;
+ fixedFrame.size.height = height;
+ }
+ DBG_PRINT("CALayer::FixCALayerLayout0.0: Visible %d, Quirks [%d, pos %d, size %d, lout %d, force %d], Super %p frame %lf/%lf %lfx%lf, Root %p frame %lf/%lf %lfx%lf, usr %d/%d %dx%d -> %lf/%lf %lfx%lf\n",
+ (int)visible, caLayerQuirks, posQuirk, sizeQuirk, loutQuirk, (int)force,
+ superLayer, superFrame.origin.x, superFrame.origin.y, superFrame.size.width, superFrame.size.height,
+ self, lFrame.origin.x, lFrame.origin.y, lFrame.size.width, lFrame.size.height,
+ x, y, width, height, fixedFrame.origin.x, fixedFrame.origin.y, fixedFrame.size.width, fixedFrame.size.height);
+ if( posQuirk || sizeQuirk || loutQuirk ) {
+ fixedFrameSet = 1;
+ [super setFrame: fixedFrame];
+ }
+ }
+ if( NULL != subLayer ) {
+ CGRect lFrame = [subLayer frame];
+ int sizeQuirk = 0 != ( NW_DEDICATEDFRAME_QUIRK_SIZE & caLayerQuirks ) && ( lFrame.size.width!=width || lFrame.size.height!=height );
+ CGFloat _x, _y, _w, _h;
+ int posQuirk = 0 != ( NW_DEDICATEDFRAME_QUIRK_POSITION & caLayerQuirks ) && ( lFrame.origin.x!=0 || lFrame.origin.y!=0 );
+ // Sub rel. to used root layer
+ _x = 0;
+ _y = 0;
+ posQuirk |= 8;
+ if( !sizeQuirk ) {
+ _w = lFrame.size.width;
+ _h = lFrame.size.height;
+ } else {
+ _w = width;
+ _h = height;
+ }
+ DBG_PRINT("CALayer::FixCALayerLayout1.0: Visible %d, Quirks [%d, pos %d, size %d, lout %d, force %d], SubL %p frame %lf/%lf %lfx%lf, usr %dx%d -> %lf/%lf %lfx%lf\n",
+ (int)visible, caLayerQuirks, posQuirk, sizeQuirk, loutQuirk, (int)force,
+ subLayer, lFrame.origin.x, lFrame.origin.y, lFrame.size.width, lFrame.size.height,
+ width, height, _x, _y, _w, _h);
+ if( force || posQuirk || sizeQuirk || loutQuirk ) {
+ lFrame.origin.x = _x;
+ lFrame.origin.y = _y;
+ lFrame.size.width = _w;
+ lFrame.size.height = _h;
+ if( [subLayer conformsToProtocol:@protocol(NWDedicatedFrame)] ) {
+ CALayer <NWDedicatedFrame> * subLayerDS = (CALayer <NWDedicatedFrame> *) subLayer;
+ [subLayerDS setDedicatedFrame: lFrame quirks: caLayerQuirks];
+ } else {
+ [subLayer setFrame: lFrame];
+ }
+ }
+ }
+}
+
+@end
+
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: CreateCALayer0
- * Signature: (IIII)J
+ * Signature: (IIF)J
*/
JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
- (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height)
+ (JNIEnv *env, jclass unused, jint width, jint height, jfloat contentsScale)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- CALayer* layer = [[CALayer alloc] init];
- DBG_PRINT("CALayer::CreateCALayer.0: %p %d/%d %dx%d (refcnt %d)\n", layer, (int)x, (int)y, (int)width, (int)height, (int)[layer retainCount]);
+ MyCALayer* layer = [[MyCALayer alloc] init];
+ DBG_PRINT("CALayer::CreateCALayer.0: root %p 0/0 %dx%d @ scale %lf (refcnt %d)\n", layer, (int)width, (int)height, (double)contentsScale, (int)[layer retainCount]);
// avoid zero size
if(0 == width) { width = 32; }
if(0 == height) { height = 32; }
+NS_DURING
+ // Available >= 10.7
+ [layer setContentsScale: (CGFloat)contentsScale];
+NS_HANDLER
+NS_ENDHANDLER
+
// initial dummy size !
- CGRect lRect = [layer frame];
- lRect.origin.x = x;
- lRect.origin.y = y;
- lRect.size.width = width;
- lRect.size.height = height;
- [layer setFrame: lRect];
+ CGRect lFrame = [layer frame];
+ lFrame.origin.x = 0;
+ lFrame.origin.y = 0;
+ lFrame.size.width = width;
+ lFrame.size.height = height;
+ [layer setFrame: lFrame];
// no animations for add/remove/swap sublayers etc
// doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
[layer removeAllAnimations];
+ // [layer addAnimation:nil forKey:kCATransition];
[layer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
[layer setNeedsDisplayOnBoundsChange: YES];
- DBG_PRINT("CALayer::CreateCALayer.1: %p %lf/%lf %lfx%lf\n", layer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height);
- DBG_PRINT("CALayer::CreateCALayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
-
+ DBG_PRINT("CALayer::CreateCALayer.1: root %p %lf/%lf %lfx%lf\n", layer, lFrame.origin.x, lFrame.origin.y, lFrame.size.width, lFrame.size.height);
[pool release];
+ DBG_PRINT("CALayer::CreateCALayer.X: root %p (refcnt %d)\n", layer, (int)[layer retainCount]);
return (jlong) ((intptr_t) layer);
}
@@ -352,46 +675,114 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: AddCASublayer0
- * Signature: (JJ)V
+ * Signature: (JJIIIIIF)V
*/
JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0
- (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer)
+ (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer, jint x, jint y, jint width, jint height, jfloat contentsScale, jint caLayerQuirks)
{
- JNF_COCOA_ENTER(env);
- CALayer* rootLayer = (CALayer*) ((intptr_t) rootCALayer);
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyCALayer* rootLayer = (MyCALayer*) ((intptr_t) rootCALayer);
CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ [rootLayer retain]; // Pairs w/ RemoveCASublayer
+ [subLayer retain]; // Pairs w/ RemoveCASublayer
+
CGRect lRectRoot = [rootLayer frame];
- DBG_PRINT("CALayer::AddCASublayer0.0: Origin %p frame0: %lf/%lf %lfx%lf\n",
- rootLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height);
- if(lRectRoot.origin.x!=0 || lRectRoot.origin.y!=0) {
- lRectRoot.origin.x = 0;
- lRectRoot.origin.y = 0;
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- [rootLayer setFrame: lRectRoot];
- }];
- DBG_PRINT("CALayer::AddCASublayer0.1: Origin %p frame*: %lf/%lf %lfx%lf\n",
- rootLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height);
+
+ // Available >= 10.7
+ DBG_PRINT("CALayer::AddCASublayer0.0: Quirks %d, Root %p (refcnt %d), Sub %p (refcnt %d), frame0: %lf/%lf %lfx%lf scale %lf\n",
+ caLayerQuirks, rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount],
+ lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height, (float)contentsScale);
+
+NS_DURING
+ [subLayer setContentsScale: (CGFloat)contentsScale];
+NS_HANDLER
+NS_ENDHANDLER
+
+ [subLayer setFrame:lRectRoot];
+ [rootLayer addSublayer:subLayer];
+
+ // no animations for add/remove/swap sublayers etc
+ // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
+ [rootLayer removeAllAnimations];
+ // [rootLayer addAnimation:nil forKey:kCATransition]; // JAU
+ [rootLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [rootLayer setNeedsDisplayOnBoundsChange: YES];
+ [subLayer removeAllAnimations];
+ // [subLayer addAnimation:nil forKey:kCATransition]; // JAU
+ [subLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [subLayer setNeedsDisplayOnBoundsChange: YES];
+
+ if( 0 != caLayerQuirks ) {
+ [rootLayer fixCALayerLayout: subLayer visible:1 x:x y:y width:width height:height caLayerQuirks:caLayerQuirks force:JNI_TRUE];
+ }
+
+ [CATransaction commit];
+
+ [pool release];
+ DBG_PRINT("CALayer::AddCASublayer0.X: root %p (refcnt %d) .sub %p (refcnt %d)\n",
+ rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount]);
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: FixCALayerLayout0
+ * Signature: (JJIII)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_FixCALayerLayout0
+ (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer, jboolean visible, jint x, jint y, jint width, jint height, jint caLayerQuirks)
+{
+ if( 0 != caLayerQuirks ) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyCALayer* rootLayer = (MyCALayer*) ((intptr_t) rootCALayer);
+ if( NULL == rootLayer ) {
+ NativewindowCommon_throwNewRuntimeException(env, "Argument \"rootLayer\" is null");
+ }
+ CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ [rootLayer fixCALayerLayout: subLayer visible:(BOOL)visible x:x y:y width:width height:height caLayerQuirks:caLayerQuirks force:JNI_FALSE];
+
+ [CATransaction commit];
+
+ [pool release];
}
- DBG_PRINT("CALayer::AddCASublayer0.2: %p . %p %lf/%lf %lfx%lf (refcnt %d)\n",
- rootLayer, subLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height, (int)[subLayer retainCount]);
-
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- // simple 1:1 layout !
- [subLayer setFrame:lRectRoot];
- [rootLayer addSublayer:subLayer];
-
- // no animations for add/remove/swap sublayers etc
- // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
- [rootLayer removeAllAnimations];
- [rootLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
- [rootLayer setNeedsDisplayOnBoundsChange: YES];
- [subLayer removeAllAnimations];
- [subLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
- [subLayer setNeedsDisplayOnBoundsChange: YES];
- }];
- DBG_PRINT("CALayer::AddCASublayer0.X: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]);
- JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: SetCALayerPixelScale0
+ * Signature: (JJF)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_SetCALayerPixelScale0
+ (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer, jfloat contentsScale)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyCALayer* rootLayer = (MyCALayer*) ((intptr_t) rootCALayer);
+ if( NULL == rootLayer ) {
+ NativewindowCommon_throwNewRuntimeException(env, "Argument \"rootLayer\" is null");
+ }
+ CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+NS_DURING
+ [rootLayer setContentsScale: (CGFloat)contentsScale];
+ if( NULL != subLayer ) {
+ [subLayer setContentsScale: (CGFloat)contentsScale];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ [CATransaction commit];
+
+ [pool release];
}
/*
@@ -402,18 +793,27 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0
JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RemoveCASublayer0
(JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer)
{
- JNF_COCOA_ENTER(env);
- CALayer* rootLayer = (CALayer*) ((intptr_t) rootCALayer);
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyCALayer* rootLayer = (MyCALayer*) ((intptr_t) rootCALayer);
CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
(void)rootLayer; // no warnings
- DBG_PRINT("CALayer::RemoveCASublayer0.0: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]);
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- [subLayer removeFromSuperlayer];
- }];
- DBG_PRINT("CALayer::RemoveCASublayer0.X: %p . %p\n", rootLayer, subLayer);
- JNF_COCOA_EXIT(env);
+ DBG_PRINT("CALayer::RemoveCASublayer0.0: root %p (refcnt %d) .sub %p (refcnt %d)\n",
+ rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount]);
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ [subLayer removeFromSuperlayer];
+ [subLayer release]; // Pairs w/ AddCASublayer
+ [rootLayer release]; // Pairs w/ AddCASublayer
+
+ [CATransaction commit];
+
+ [pool release];
+ DBG_PRINT("CALayer::RemoveCASublayer0.X: root %p (refcnt %d) .sub %p (refcnt %d)\n",
+ rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount]);
}
/*
@@ -424,93 +824,113 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RemoveCASublayer0
JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyCALayer0
(JNIEnv *env, jclass unused, jlong caLayer)
{
- JNF_COCOA_ENTER(env);
- CALayer* layer = (CALayer*) ((intptr_t) caLayer);
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyCALayer* layer = (MyCALayer*) ((intptr_t) caLayer);
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ DBG_PRINT("CALayer::DestroyCALayer0.0: root %p (refcnt %d)\n", layer, (int)[layer retainCount]);
+ [layer release]; // Trigger release and dealloc of root CALayer, it's child etc ..
+
+ [CATransaction commit];
- DBG_PRINT("CALayer::DestroyCALayer0.0: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- [layer release]; // performs release!
- }];
- DBG_PRINT("CALayer::DestroyCALayer0.X: %p\n", layer);
- JNF_COCOA_EXIT(env);
+ [pool release];
+ DBG_PRINT("CALayer::DestroyCALayer0.X: root %p\n", layer);
}
/*
* Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
- * Method: SetJAWTRootSurfaceLayer0
- * Signature: (JJ)Z
+ * Method: GetJAWTSurfaceLayersHandle0
+ * Signature: (J)J
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0
- (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_GetJAWTSurfaceLayersHandle0
+ (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer)
{
- JNF_COCOA_ENTER(env);
JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
if (NULL == dsi) {
NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
- return JNI_FALSE;
+ return 0;
}
- CALayer* layer = (CALayer*) (intptr_t) caLayer;
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
- DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: %p -> %p (refcnt %d)\n", surfaceLayers.layer, layer, (int)[layer retainCount]);
- surfaceLayers.layer = layer; // already incr. retain count
- DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
- }];
- JNF_COCOA_EXIT(env);
- return JNI_TRUE;
+ id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
+ return (jlong) ((intptr_t) surfaceLayers);
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
+ * Method: SetJAWTRootSurfaceLayer0
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0
+ (JNIEnv *env, jclass unused, jlong jawtSurfaceLayersHandle, jlong caLayer)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)(intptr_t)jawtSurfaceLayersHandle;
+ MyCALayer* layer = (MyCALayer*) (intptr_t) caLayer;
+ DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: pre %p -> root %p (refcnt %d)\n", [surfaceLayers layer], layer, (int)[layer retainCount]);
+ [surfaceLayers setLayer: [layer retain]]; // Pairs w/ Unset
+
+ [CATransaction commit];
+
+ [pool release];
+ DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.X: root %p (refcnt %d)\n", layer, (int)[layer retainCount]);
}
/*
* Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
* Method: UnsetJAWTRootSurfaceLayer0
- * Signature: (JJ)Z
-JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0
- (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0
+ (JNIEnv *env, jclass unused, jlong jawtSurfaceLayersHandle, jlong caLayer)
{
- JNF_COCOA_ENTER(env);
- JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
- if (NULL == dsi) {
- NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
- return JNI_FALSE;
- }
- CALayer* layer = (CALayer*) (intptr_t) caLayer;
- {
- id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
- if(layer != surfaceLayers.layer) {
- NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer);
- return JNI_FALSE;
- }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)(intptr_t)jawtSurfaceLayersHandle;
+ MyCALayer* layer = (MyCALayer*) (intptr_t) caLayer;
+ if(layer != [surfaceLayers layer]) {
+ NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer);
+ return;
}
- // [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
- DBG_PRINT("CALayer::detachJAWTSurfaceLayer: (%p) %p -> NULL\n", layer, surfaceLayers.layer);
- surfaceLayers.layer = NULL;
- [layer release];
- // }];
- JNF_COCOA_EXIT(env);
- return JNI_TRUE;
+ DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.0: root %p (refcnt %d) -> nil\n", layer, (int)[layer retainCount]);
+ [layer release]; // Pairs w/ Set
+ [surfaceLayers setLayer: NULL];
+
+ [CATransaction commit];
+
+ [pool release];
+ DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.X: root %p (refcnt %d) -> nil\n", layer, (int)[layer retainCount]);
}
- */
@interface MainRunnable : NSObject
{
- JavaVM *jvmHandle;
- int jvmVersion;
jobject runnableObj;
}
-- (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers;
+- (id) initWithRunnable: (jobject)runnable;
- (void) jRun;
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+- (void)dealloc;
+#endif
+
+
@end
@implementation MainRunnable
-- (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers
+- (id) initWithRunnable: (jobject)runnable
{
- jvmHandle = jvm;
- jvmVersion = jvmVers;
runnableObj = runnable;
return [super init];
}
@@ -518,59 +938,144 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
- (void) jRun
{
int shallBeDetached = 0;
- JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NativewindowCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ DBG_PRINT2("MainRunnable.1 env: %d\n", (int)(NULL!=env));
if(NULL!=env) {
+ DBG_PRINT2("MainRunnable.1.0\n");
(*env)->CallVoidMethod(env, runnableObj, runnableRunID);
+ DBG_PRINT2("MainRunnable.1.1\n");
+ (*env)->DeleteGlobalRef(env, runnableObj);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ DBG_PRINT2("MainRunnable.1.3\n");
+ // detaching thread not required - daemon
+ // NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
}
+ DBG_PRINT2("MainRunnable.X\n");
}
-@end
+#ifdef DBG_LIFECYCLE
+- (id)retain
+{
+ DBG_PRINT2("MainRunnable::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ id o = [super retain];
+ DBG_PRINT2("MainRunnable::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+ return o;
+}
-/*
- * Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: RunOnMainThread0
- * Signature: (ZLjava/lang/Runnable;)V
- */
-JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0
- (JNIEnv *env, jclass unused, jboolean jwait, jobject runnable)
+- (oneway void)release
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ DBG_PRINT2("MainRunnable::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [super release];
+ // DBG_PRINT2("MainRunnable::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
- if ( NO == [NSThread isMainThread] ) {
- jobject runnableGlob = (*env)->NewGlobalRef(env, runnable);
+- (void)dealloc
+{
+ DBG_PRINT2("MainRunnable::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [super dealloc];
+ // DBG_PRINT2("MainRunnable.dealloc.X: %p\n", self);
+}
+
+#endif
+
+@end
+
+static void RunOnThread (JNIEnv *env, jobject runnable, BOOL onMain, jint delayInMS)
+{
+ BOOL isMainThread = [NSThread isMainThread];
+ BOOL forkOnMain = onMain && ( NO == isMainThread || 0 < delayInMS );
- BOOL wait = (JNI_TRUE == jwait) ? YES : NO;
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
+ DBG_PRINT2( "RunOnThread0: forkOnMain %d [onMain %d, delay %dms, isMainThread %d], NSApp %d, NSApp-isRunning %d\n",
+ (int)forkOnMain, (int)onMain, (int)delayInMS, (int)isMainThread, (int)(NULL!=NSApp), (int)([NSApp isRunning]));
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
+ if ( forkOnMain ) {
+ jobject runnableObj = (*env)->NewGlobalRef(env, runnable);
+
+ DBG_PRINT2( "RunOnThread.1.0\n");
+ MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj];
+
+ if( onMain ) {
+ [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO];
} else {
- jvmVersion = (*env)->GetVersion(env);
+ NSTimeInterval delay = (double)delayInMS/1000.0;
+ [mr performSelector:@selector(jRun) withObject:nil afterDelay:delay];
}
+ DBG_PRINT2( "RunOnThread.1.1\n");
- MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableGlob jvmHandle: jvmHandle jvmVersion: jvmVersion];
- [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:wait];
[mr release];
+ DBG_PRINT2( "RunOnThread.1.2\n");
- (*env)->DeleteGlobalRef(env, runnableGlob);
} else {
+ DBG_PRINT2( "RunOnThread.2\n");
(*env)->CallVoidMethod(env, runnable, runnableRunID);
}
+ DBG_PRINT2( "RunOnThread.X\n");
+}
+
+static void OSXUtil_KickNSApp() {
+ NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined
+ location: NSMakePoint(0,0)
+ modifierFlags: 0
+ timestamp: 0.0
+ windowNumber: 0
+ context: nil
+ subtype: 0
+ data1: 0
+ data2: 0];
+ [NSApp postEvent: event atStart: true];
+}
+/**
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: RunOnMainThread0
+ * Signature: (ZLjava/lang/Runnable;)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0
+ (JNIEnv *env, jclass unused, jboolean kickNSApp, jobject runnable)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ RunOnThread (env, runnable, YES, 0);
+ if( kickNSApp ) {
+ OSXUtil_KickNSApp();
+ }
[pool release];
}
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: RunOnMainThread0
+ * Method: RunLater0
+ * Signature: (ZZLjava/lang/Runnable;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunLater0
+ (JNIEnv *env, jclass unused, jboolean onMain, jboolean kickNSApp, jobject runnable, jint delay)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ RunOnThread (env, runnable, onMain ? YES : NO, delay);
+ if( kickNSApp ) {
+ OSXUtil_KickNSApp();
+ }
+ [pool release];
+}
+
+/**
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: KickNSApp0
* Signature: (V)V
*/
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_KickNSApp0
+ (JNIEnv *env, jclass unused)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ OSXUtil_KickNSApp();
+ [pool release];
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: IsMainThread0
+ * Signature: (V)Z
+ */
JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_IsMainThread0
(JNIEnv *env, jclass unused)
{
@@ -614,13 +1119,12 @@ JNIEXPORT jint JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenRefreshR
(JNIEnv *env, jclass unused, jint scrn_idx)
{
int res = 0;
- JNF_COCOA_ENTER(env);
- // NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
DBG_PRINT("GetScreenRefreshRate.0: screen %p\n", (void *)screen);
if(NULL != screen) {
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
- DBG_PRINT("GetScreenRefreshRate.1: display %p\n", (void *)display);
+ DBG_PRINT("GetScreenRefreshRate.1: display %p\n", (void *)(intptr_t)display);
if(0 != display) {
CFDictionaryRef mode = CGDisplayCurrentMode(display);
DBG_PRINT("GetScreenRefreshRate.2: mode %p\n", (void *)mode);
@@ -633,9 +1137,8 @@ JNIEXPORT jint JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenRefreshR
if(0 == res) {
res = 60; // default .. (experienced on OSX 10.6.8)
}
- DBG_PRINT(stderr, "GetScreenRefreshRate.X: %d\n", res);
- // [pool release];
- JNF_COCOA_EXIT(env);
+ DBG_PRINT("GetScreenRefreshRate.X: %d\n", (int)res);
+ [pool release];
return res;
}
diff --git a/src/nativewindow/native/win32/DeviceDriverQuery.txt b/src/nativewindow/native/win32/DeviceDriverQuery.txt
new file mode 100644
index 000000000..7401ed83b
--- /dev/null
+++ b/src/nativewindow/native/win32/DeviceDriverQuery.txt
@@ -0,0 +1,41 @@
+
+ // INCOMPLETE !
+ //
+ // See Bug 706 and Bug 520
+ // https://jogamp.org/bugzilla/show_bug.cgi?id=520
+ // https://jogamp.org/bugzilla/show_bug.cgi?id=706
+ //
+ // Device Driver SDK
+ // http://msdn.microsoft.com/en-us/library/ff553567.aspx#ddk_setupdi_device_information_functions_dg
+ {
+ /**
+ System-Defined Device Setup Classes Available to Vendors (GUID)
+
+ Display Adapters
+ Class = Display
+ ClassGuid = {4d36e968-e325-11ce-bfc1-08002be10318}
+ This class includes video adapters. Drivers for this class include display drivers and video miniport drivers.
+
+ /opt-windows/mingw/include/devguid.h GUID_DEVCLASS_DISPLAY
+ GUID_DEVCLASS_DISPLAY
+ HDEVINFO SetupDiGetClassDevs(
+ _In_opt_ const GUID *ClassGuid,
+ _In_opt_ PCTSTR Enumerator,
+ _In_opt_ HWND hwndParent,
+ _In_ DWORD Flags
+ );
+
+ */
+ const GUID devClassDisplay = GUID_DEVCLASS_DISPLAY;
+ // http://msdn.microsoft.com/en-us/library/ff551069.aspx
+ HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_DISPLAY, NULL /* bus */, NULL /* windows */, DIGCF_PRESENT | DIGCF_PROFILE /* flags */);
+ DWORD MemberIndex = 0;
+ SP_DEVINFO_DATA DeviceInfoData;
+ DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+ while( TRUE == SetupDiEnumDeviceInfo(DeviceInfoSet, MemberIndex, &DeviceInfoData) ) {
+ SetupDiGetSelectedDevice();
+ MemberIndex++;
+ }
+ SetupDiDestroyDeviceInfoList(hDevInfo);
+ }
+
diff --git a/src/nativewindow/native/win32/GDImisc.c b/src/nativewindow/native/win32/GDImisc.c
index 3ab7f9859..76143c426 100644
--- a/src/nativewindow/native/win32/GDImisc.c
+++ b/src/nativewindow/native/win32/GDImisc.c
@@ -20,8 +20,10 @@
#ifdef VERBOSE_ON
#define DBG_PRINT(args...) fprintf(stderr, args);
+ #define DBG_PRINT_FLUSH(args...) fprintf(stderr, args); fflush(stderr);
#else
#define DBG_PRINT(args...)
+ #define DBG_PRINT_FLUSH(args...)
#endif
static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
@@ -30,6 +32,162 @@ static const char * const ClazzNamePointCstrSignature = "(II)V";
static jclass pointClz = NULL;
static jmethodID pointCstr = NULL;
+static jmethodID dumpStackID = NULL;
+
+typedef struct {
+ HANDLE threadHandle;
+ DWORD threadId;
+ volatile BOOL threadReady;
+ volatile BOOL threadDead;
+} DummyThreadContext;
+
+typedef struct {
+ HINSTANCE hInstance;
+ const TCHAR* wndClassName;
+ const TCHAR* wndName;
+ jint x;
+ jint y;
+ jint width;
+ jint height;
+ volatile HWND hWnd;
+ volatile BOOL threadReady;
+} DummyThreadCommand;
+
+#define TM_OPENWIN WM_APP+1
+#define TM_CLOSEWIN WM_APP+2
+#define TM_STOP WM_APP+3
+
+static const char * sTM_OPENWIN = "TM_OPENWIN";
+static const char * sTM_CLOSEWIN = "TM_CLOSEWIN";
+static const char * sTM_STOP = "TM_STOP";
+
+/** 3s timeout */
+static const int64_t TIME_OUT = 3000000;
+
+static jboolean DDT_CheckAlive(JNIEnv *env, const char *msg, DummyThreadContext *ctx) {
+ if( ctx->threadDead ) {
+ NativewindowCommon_throwNewRuntimeException(env, "DDT is dead at %s", msg);
+ return JNI_FALSE;
+ } else {
+ DBG_PRINT_FLUSH("*** DDT-Check ALIVE @ %s\n", msg);
+ return JNI_TRUE;
+ }
+}
+
+static jboolean DDT_WaitUntilCreated(JNIEnv *env, DummyThreadContext *ctx, BOOL created) {
+ const int64_t t0 = NativewindowCommon_CurrentTimeMillis();
+ int64_t t1 = t0;
+ if( created ) {
+ while( !ctx->threadReady && t1-t0 < TIME_OUT ) {
+ t1 = NativewindowCommon_CurrentTimeMillis();
+ }
+ if( !ctx->threadReady ) {
+ NativewindowCommon_throwNewRuntimeException(env, "TIMEOUT (%d ms) while waiting for DDT CREATED", (int)(t1-t0));
+ return JNI_FALSE;
+ }
+ DBG_PRINT_FLUSH("*** DDT-Check CREATED\n");
+ } else {
+ while( !ctx->threadDead && t1-t0 < TIME_OUT ) {
+ t1 = NativewindowCommon_CurrentTimeMillis();
+ }
+ if( !ctx->threadDead ) {
+ NativewindowCommon_throwNewRuntimeException(env, "TIMEOUT (%d ms) while waiting for DDT DESTROYED", (int)(t1-t0));
+ return JNI_FALSE;
+ }
+ DBG_PRINT_FLUSH("*** DDT-Check DEAD\n");
+ }
+ return JNI_TRUE;
+}
+
+static jboolean DDT_WaitUntilReady(JNIEnv *env, const char *msg, DummyThreadCommand *cmd) {
+ const int64_t t0 = NativewindowCommon_CurrentTimeMillis();
+ int64_t t1 = t0;
+ while( !cmd->threadReady && t1-t0 < TIME_OUT ) {
+ t1 = NativewindowCommon_CurrentTimeMillis();
+ }
+ if( !cmd->threadReady ) {
+ NativewindowCommon_throwNewRuntimeException(env, "TIMEOUT (%d ms) while waiting for DDT %s", (int)(t1-t0), msg);
+ return JNI_FALSE;
+ }
+ DBG_PRINT_FLUSH("*** DDT-Check READY @ %s\n", msg);
+ return JNI_TRUE;
+}
+
+static HWND DummyWindowCreate
+ (HINSTANCE hInstance, const TCHAR* wndClassName, const TCHAR* wndName, jint x, jint y, jint width, jint height)
+{
+ DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
+ DWORD dwStyle = WS_OVERLAPPEDWINDOW;
+ HWND hWnd = CreateWindowEx( dwExStyle,
+ wndClassName,
+ wndName,
+ dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ x, y, width, height,
+ NULL, NULL, hInstance, NULL );
+ return hWnd;
+}
+
+static DWORD WINAPI DummyDispatchThreadFunc(LPVOID param)
+{
+ MSG msg;
+ BOOL bRet;
+ BOOL bEOL=FALSE;
+ DummyThreadContext *threadContext = (DummyThreadContext*)param;
+
+ /* there can not be any messages for us now, as the creator waits for
+ threadReady before continuing, but we must use this PeekMessage() to
+ create the thread message queue */
+ PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
+
+ /* now we can safely say: we have a qeue and are ready to receive messages */
+ // threadContext->threadId = GetCurrentThreadId();
+ threadContext->threadDead = FALSE;
+ threadContext->threadReady = TRUE;
+
+ while( !bEOL && (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0 ) {
+ if ( -1 == bRet ) {
+ fprintf(stderr, "DummyDispatchThread (id %d): GetMessage Error %d, werr %d\n",
+ (int)threadContext->threadId, (int)bRet, (int)GetLastError());
+ fflush(stderr);
+ bEOL = TRUE;
+ break; // EOL
+ } else {
+ switch(msg.message) {
+ case TM_OPENWIN: {
+ DummyThreadCommand *tParam = (DummyThreadCommand*)msg.wParam;
+ DBG_PRINT_FLUSH("*** DDT-Dispatch OPENWIN\n");
+ tParam->hWnd = DummyWindowCreate(tParam->hInstance, tParam->wndClassName, tParam->wndName, tParam->x, tParam->y, tParam->width, tParam->height);
+ tParam->threadReady = TRUE;
+ }
+ break;
+ case TM_CLOSEWIN: {
+ DummyThreadCommand *tParam = (DummyThreadCommand*)msg.wParam;
+ DBG_PRINT_FLUSH("*** DDT-Dispatch CLOSEWIN\n");
+ DestroyWindow(tParam->hWnd);
+ tParam->threadReady = TRUE;
+ }
+ break;
+ case TM_STOP: {
+ DummyThreadCommand *tParam = (DummyThreadCommand*)msg.wParam;
+ DBG_PRINT_FLUSH("*** DDT-Dispatch STOP -> DEAD\n");
+ tParam->threadReady = TRUE;
+ bEOL = TRUE;
+ }
+ break; // EOL
+ default:
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ break;
+ }
+ }
+ }
+ /* dead */
+ DBG_PRINT_FLUSH("*** DDT-Dispatch DEAD\n");
+ threadContext->threadDead = TRUE;
+ ExitThread(0);
+ return 0;
+}
+
HINSTANCE GetApplicationHandle() {
return GetModuleHandle(NULL);
@@ -37,16 +195,54 @@ HINSTANCE GetApplicationHandle() {
/* Java->C glue code:
* Java package: jogamp.nativewindow.windows.GDIUtil
- * Java method: boolean CreateWindowClass(long hInstance, java.lang.String clazzName, long wndProc)
- * C function: BOOL CreateWindowClass(HANDLE hInstance, LPCSTR clazzName, HANDLE wndProc);
+ * Java method: long CreateDummyDispatchThread0()
+ */
+JNIEXPORT jlong JNICALL
+Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyDispatchThread0
+ (JNIEnv *env, jclass _unused)
+{
+ DWORD threadId = 0;
+ DummyThreadContext * dispThreadCtx = calloc(1, sizeof(DummyThreadContext));
+
+ dispThreadCtx->threadHandle = CreateThread(NULL, 0, DummyDispatchThreadFunc, (LPVOID)dispThreadCtx, 0, &threadId);
+ if( NULL == dispThreadCtx->threadHandle || 0 == threadId ) {
+ const HANDLE threadHandle = dispThreadCtx->threadHandle;
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT CREATE failed handle %p, id %d, werr %d",
+ (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return (jlong)0;
+ }
+ if( JNI_FALSE == DDT_WaitUntilCreated(env, dispThreadCtx, TRUE) ) {
+ const HANDLE threadHandle = dispThreadCtx->threadHandle;
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT CREATE (ack) failed handle %p, id %d, werr %d",
+ (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return (jlong)0;
+ }
+ DBG_PRINT_FLUSH("*** DDT Created %d\n", (int)threadId);
+ dispThreadCtx->threadId = threadId;
+ return (jlong) (intptr_t) dispThreadCtx;
+}
+
+/* Java->C glue code:
+ * Java package: jogamp.nativewindow.windows.GDIUtil
+ * Java method: boolean CreateWindowClass0(long hInstance, java.lang.String clazzName, long wndProc)
+ * C function: BOOL CreateWindowClass0(HANDLE hInstance, LPCSTR clazzName, HANDLE wndProc);
*/
JNIEXPORT jboolean JNICALL
-Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass
- (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jClazzName, jlong wndProc)
+Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass0
+ (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jClazzName, jlong wndProc,
+ jlong iconSmallHandle, jlong iconBigHandle)
{
HINSTANCE hInstance = (HINSTANCE) (intptr_t) jHInstance;
const TCHAR* clazzName = NULL;
- WNDCLASS wc;
+ WNDCLASSEX wc;
jboolean res;
#ifdef UNICODE
@@ -56,23 +252,25 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass
#endif
ZeroMemory( &wc, sizeof( wc ) );
- if( GetClassInfo( hInstance, clazzName, &wc ) ) {
+ if( GetClassInfoEx( hInstance, clazzName, &wc ) ) {
// registered already
res = JNI_TRUE;
} else {
// register now
ZeroMemory( &wc, sizeof( wc ) );
+ wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.lpfnWndProc = (WNDPROC) (intptr_t) wndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
- wc.hIcon = NULL;
- wc.hCursor = LoadCursor( NULL, IDC_ARROW);
+ wc.hIcon = (HICON) (intptr_t) iconBigHandle;
+ wc.hCursor = NULL;
wc.hbrBackground = NULL; // no background paint - GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = clazzName;
- res = ( 0 != RegisterClass( &wc ) ) ? JNI_TRUE : JNI_FALSE ;
+ wc.hIconSm = (HICON) (intptr_t) iconSmallHandle;
+ res = ( 0 != RegisterClassEx( &wc ) ) ? JNI_TRUE : JNI_FALSE ;
}
#ifdef UNICODE
@@ -86,15 +284,15 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass
/* Java->C glue code:
* Java package: jogamp.nativewindow.windows.GDIUtil
- * Java method: boolean DestroyWindowClass(long hInstance, java.lang.String className)
- * C function: BOOL DestroyWindowClass(HANDLE hInstance, LPCSTR className);
+ * Java method: boolean DestroyWindowClass0(long hInstance, java.lang.String className, long dispThreadCtx)
*/
JNIEXPORT jboolean JNICALL
-Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindowClass
- (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jClazzName)
+Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindowClass0
+ (JNIEnv *env, jclass gdiClazz, jlong jHInstance, jstring jClazzName, jlong jDispThreadCtx)
{
HINSTANCE hInstance = (HINSTANCE) (intptr_t) jHInstance;
const TCHAR* clazzName = NULL;
+ DummyThreadContext * dispThreadCtx = (DummyThreadContext *) (intptr_t) jDispThreadCtx;
jboolean res;
#ifdef UNICODE
@@ -111,55 +309,175 @@ Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindowClass
(*env)->ReleaseStringUTFChars(env, jClazzName, clazzName);
#endif
+ if( NULL != dispThreadCtx) {
+ const HANDLE threadHandle = dispThreadCtx->threadHandle;
+ const DWORD threadId = dispThreadCtx->threadId;
+ DummyThreadCommand tParam = {0};
+ tParam.threadReady = FALSE;
+ DBG_PRINT_FLUSH("*** DDT Destroy %d\n", (int)threadId);
+#ifdef VERBOSE_ON
+ (*env)->CallStaticVoidMethod(env, gdiClazz, dumpStackID);
+#endif
+
+ if( JNI_FALSE == DDT_CheckAlive(env, sTM_STOP, dispThreadCtx) ) {
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT %s (alive) failed handle %p, id %d, werr %d",
+ sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return JNI_FALSE;
+ }
+ if ( 0 != PostThreadMessage(dispThreadCtx->threadId, TM_STOP, (WPARAM)&tParam, 0) ) {
+ if( JNI_FALSE == DDT_WaitUntilReady(env, sTM_STOP, &tParam) ) {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s (ack) failed handle %p, id %d, werr %d",
+ sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return JNI_FALSE;
+ }
+ if( JNI_FALSE == DDT_WaitUntilCreated(env, dispThreadCtx, FALSE) ) {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT KILL %s (ack) failed handle %p, id %d, werr %d",
+ sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return JNI_FALSE;
+ }
+ free(dispThreadCtx); // free after proper DDT shutdown!
+ } else {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s failed handle %p, id %d, werr %d",
+ sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return JNI_FALSE;
+ }
+ }
+
return res;
}
-
/* Java->C glue code:
* Java package: jogamp.nativewindow.windows.GDIUtil
- * Java method: long CreateDummyWindow0(long hInstance, java.lang.String className, java.lang.String windowName, int x, int y, int width, int height)
- * C function: HANDLE CreateDummyWindow0(HANDLE hInstance, LPCSTR className, LPCSTR windowName, int x, int y, int width, int height);
+ * Java method: long CreateDummyWindow0(long hInstance, java.lang.String className, jlong dispThreadCtx, java.lang.String windowName, int x, int y, int width, int height)
*/
JNIEXPORT jlong JNICALL
Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyWindow0
- (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jWndClassName, jstring jWndName, jint x, jint y, jint width, jint height)
+ (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jWndClassName, jlong jDispThreadCtx, jstring jWndName, jint x, jint y, jint width, jint height)
{
- HINSTANCE hInstance = (HINSTANCE) (intptr_t) jHInstance;
- const TCHAR* wndClassName = NULL;
- const TCHAR* wndName = NULL;
- DWORD dwExStyle;
- DWORD dwStyle;
- HWND hWnd;
+ DummyThreadContext * dispThreadCtx = (DummyThreadContext *) (intptr_t) jDispThreadCtx;
+ DummyThreadCommand tParam = {0};
+
+ tParam.hInstance = (HINSTANCE) (intptr_t) jHInstance;
+ tParam.x = x;
+ tParam.y = y;
+ tParam.width = width;
+ tParam.height = height;
+ tParam.hWnd = 0;
+ tParam.threadReady = FALSE;
#ifdef UNICODE
- wndClassName = NewtCommon_GetNullTerminatedStringChars(env, jWndClassName);
- wndName = NewtCommon_GetNullTerminatedStringChars(env, jWndName);
+ tParam.wndClassName = NewtCommon_GetNullTerminatedStringChars(env, jWndClassName);
+ tParam.wndName = NewtCommon_GetNullTerminatedStringChars(env, jWndName);
#else
- wndClassName = (*env)->GetStringUTFChars(env, jWndClassName, NULL);
- wndName = (*env)->GetStringUTFChars(env, jWndName, NULL);
+ tParam.wndClassName = (*env)->GetStringUTFChars(env, jWndClassName, NULL);
+ tParam.wndName = (*env)->GetStringUTFChars(env, jWndName, NULL);
#endif
- dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
- dwStyle = WS_OVERLAPPEDWINDOW;
-
- hWnd = CreateWindowEx( dwExStyle,
- wndClassName,
- wndName,
- dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
- x, y, width, height,
- NULL, NULL, hInstance, NULL );
+ if( NULL == dispThreadCtx ) {
+ tParam.hWnd = DummyWindowCreate(tParam.hInstance, tParam.wndClassName, tParam.wndName, tParam.x, tParam.y, tParam.width, tParam.height);
+ } else {
+ const HANDLE threadHandle = dispThreadCtx->threadHandle;
+ const DWORD threadId = dispThreadCtx->threadId;
+ if( JNI_FALSE == DDT_CheckAlive(env, sTM_OPENWIN, dispThreadCtx) ) {
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT %s (alive) failed handle %p, id %d, werr %d",
+ sTM_OPENWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ } else {
+ if( 0 != PostThreadMessage(dispThreadCtx->threadId, TM_OPENWIN, (WPARAM)&tParam, 0) ) {
+ if( JNI_FALSE == DDT_WaitUntilReady(env, sTM_OPENWIN, &tParam) ) {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ tParam.hWnd = 0;
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s (ack) failed handle %p, id %d, werr %d",
+ sTM_OPENWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ }
+ } else {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ tParam.hWnd = 0;
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s to handle %p, id %d failed, werr %d",
+ sTM_OPENWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ }
+ }
+ }
#ifdef UNICODE
- free((void*) wndClassName);
- free((void*) wndName);
+ free((void*) tParam.wndClassName);
+ free((void*) tParam.wndName);
#else
- (*env)->ReleaseStringUTFChars(env, jWndClassName, wndClassName);
- (*env)->ReleaseStringUTFChars(env, jWndName, wndName);
+ (*env)->ReleaseStringUTFChars(env, jWndClassName, tParam.wndClassName);
+ (*env)->ReleaseStringUTFChars(env, jWndName, tParam.wndName);
#endif
- return (jlong) (intptr_t) hWnd;
+ return (jlong) (intptr_t) tParam.hWnd;
}
+/*
+ * Class: jogamp_nativewindow_windows_GDIUtil
+ * Method: DestroyWindow0
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindow0
+(JNIEnv *env, jclass unused, jlong jDispThreadCtx, jlong jwin)
+{
+ jboolean res = JNI_TRUE;
+ DummyThreadContext * dispThreadCtx = (DummyThreadContext *) (intptr_t) jDispThreadCtx;
+ HWND hWnd = (HWND) (intptr_t) jwin;
+ if( NULL == dispThreadCtx ) {
+ DestroyWindow(hWnd);
+ } else {
+ const HANDLE threadHandle = dispThreadCtx->threadHandle;
+ const DWORD threadId = dispThreadCtx->threadId;
+ DummyThreadCommand tParam = {0};
+
+ tParam.hWnd = hWnd;
+ tParam.threadReady = FALSE;
+
+ if( JNI_FALSE == DDT_CheckAlive(env, sTM_CLOSEWIN, dispThreadCtx) ) {
+ free(dispThreadCtx);
+ res = JNI_FALSE;
+ NativewindowCommon_throwNewRuntimeException(env, "DDT %s (alive) failed handle %p, id %d, werr %d",
+ sTM_CLOSEWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ } else {
+ if ( 0 != PostThreadMessage(dispThreadCtx->threadId, TM_CLOSEWIN, (WPARAM)&tParam, 0) ) {
+ if( JNI_FALSE == DDT_WaitUntilReady(env, sTM_CLOSEWIN, &tParam) ) {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ res = JNI_FALSE;
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s (ack) failed handle %p, id %d, werr %d",
+ sTM_CLOSEWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ }
+ } else {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ res = JNI_FALSE;
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s to handle %p, id %d failed, werr %d",
+ sTM_CLOSEWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ }
+ }
+ }
+ return res;
+}
/*
* Class: jogamp_nativewindow_windows_GDIUtil
@@ -167,9 +485,9 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyWindow0
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_initIDs0
- (JNIEnv *env, jclass clazz)
+ (JNIEnv *env, jclass gdiClazz)
{
- if(NativewindowCommon_init(env)) {
+ if( NativewindowCommon_init(env) ) {
jclass c = (*env)->FindClass(env, ClazzNamePoint);
if(NULL==c) {
NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't find %s", ClazzNamePoint);
@@ -184,12 +502,16 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_initIDs0
NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't fetch %s.%s %s",
ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
}
+ dumpStackID = (*env)->GetStaticMethodID(env, gdiClazz, "dumpStack", "()V");
+ if(NULL==dumpStackID) {
+ NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't get method dumpStack");
+ }
}
return JNI_TRUE;
}
-LRESULT CALLBACK DummyWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- return DefWindowProc(hWnd,uMsg,wParam,lParam);
+static LRESULT CALLBACK DummyWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
/*
@@ -224,3 +546,133 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_windows_GDIUtil_GetRelativeLo
return (*env)->NewObject(env, pointClz, pointCstr, (jint)dest.x, (jint)dest.y);
}
+/*
+ * Class: jogamp_nativewindow_windows_GDIUtil
+ * Method: IsChild0
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_IsChild0
+ (JNIEnv *env, jclass unused, jlong jwin)
+{
+ HWND hWnd = (HWND) (intptr_t) jwin;
+ LONG style = GetWindowLong(hWnd, GWL_STYLE);
+ BOOL bIsChild = 0 != (style & WS_CHILD) ;
+ return bIsChild ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: jogamp_nativewindow_windows_GDIUtil
+ * Method: IsUndecorated0
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_IsUndecorated0
+ (JNIEnv *env, jclass unused, jlong jwin)
+{
+ HWND hWnd = (HWND) (intptr_t) jwin;
+ LONG style = GetWindowLong(hWnd, GWL_STYLE);
+ BOOL bIsUndecorated = 0 != (style & (WS_CHILD|WS_POPUP)) ;
+ return bIsUndecorated ? JNI_TRUE : JNI_FALSE;
+}
+
+#if 0
+
+#include <tlhelp32.h>
+#include <tchar.h>
+
+static void printError( TCHAR* msg )
+{
+ DWORD eNum;
+ TCHAR sysMsg[256];
+ TCHAR* p;
+
+ eNum = GetLastError( );
+ FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, eNum,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ sysMsg, 256, NULL );
+
+ // Trim the end of the line and terminate it with a null
+ p = sysMsg;
+ while( ( *p > 31 ) || ( *p == 9 ) )
+ ++p;
+ do { *p-- = 0; } while( ( p >= sysMsg ) &&
+ ( ( *p == '.' ) || ( *p < 33 ) ) );
+
+ // Display the message
+ _ftprintf(stderr, TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
+}
+
+static BOOL SetProcessThreadsAffinityMask( DWORD dwOwnerPID, DWORD_PTR newTAffinity, BOOL verbose )
+{
+ HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
+ THREADENTRY32 te32;
+ DWORD_PTR preTAffinity;
+ HANDLE threadHandle;
+
+ // Take a snapshot of all running threads
+ hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
+ if( hThreadSnap == INVALID_HANDLE_VALUE )
+ return( FALSE );
+
+ // Fill in the size of the structure before using it.
+ te32.dwSize = sizeof(THREADENTRY32 );
+
+ // Retrieve information about the first thread,
+ // and exit if unsuccessful
+ if( !Thread32First( hThreadSnap, &te32 ) )
+ {
+ if( verbose ) {
+ printError( TEXT("Thread32First") ); // Show cause of failure
+ }
+ CloseHandle( hThreadSnap ); // Must clean up the snapshot object!
+ return( FALSE );
+ }
+
+ // Now walk the thread list of the system,
+ // and display information about each thread
+ // associated with the specified process
+ do
+ {
+ if( te32.th32OwnerProcessID == dwOwnerPID )
+ {
+ if( verbose ) {
+ _ftprintf(stderr, TEXT("\n THREAD ID = 0x%08X, %d"), te32.th32ThreadID, te32.th32ThreadID);
+ _ftprintf(stderr, TEXT("\n base priority = %d"), te32.tpBasePri );
+ _ftprintf(stderr, TEXT("\n delta priority = %d"), te32.tpDeltaPri );
+ }
+ threadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
+ if( NULL != threadHandle ) {
+ preTAffinity = SetThreadAffinityMask(threadHandle, newTAffinity);
+ CloseHandle(threadHandle);
+ if( verbose ) {
+ _ftprintf(stderr, TEXT("\n affinity %p -> %p"), preTAffinity, newTAffinity);
+ }
+ } else {
+ if( verbose ) {
+ _ftprintf(stderr, TEXT("\n OpenThread failed %d"), (int)GetLastError());
+ }
+ }
+ }
+ } while( Thread32Next(hThreadSnap, &te32 ) );
+
+ if( verbose ) {
+ _ftprintf(stderr, TEXT("\n"));
+ }
+
+// Don't forget to clean up the snapshot object.
+ CloseHandle( hThreadSnap );
+ return( TRUE );
+}
+
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_windows_GDIUtil_SetProcessThreadsAffinityMask0
+ (JNIEnv *env, jclass unused, jlong affinityMask, jboolean verbose)
+{
+ SetProcessThreadsAffinityMask( GetCurrentProcessId(), (DWORD_PTR)(intptr_t)affinityMask, (BOOL)verbose );
+}
+
+#else
+
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_windows_GDIUtil_SetProcessThreadsAffinityMask0
+ (JNIEnv *env, jclass unused, jlong affinityMask, jboolean verbose)
+{
+}
+
+#endif
diff --git a/src/nativewindow/native/win32/WindowsDWM.h b/src/nativewindow/native/win32/WindowsDWM.h
index 36f82fc94..6e5160fa4 100644
--- a/src/nativewindow/native/win32/WindowsDWM.h
+++ b/src/nativewindow/native/win32/WindowsDWM.h
@@ -4,6 +4,8 @@
#include <windows.h>
#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified
+ #define DWM_BB_BLURREGION 0x00000002
+ #define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004
#define DWM_EC_DISABLECOMPOSITION 0
#define DWM_EC_ENABLECOMPOSITION 1
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index fcba8580c..247dc1311 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -29,6 +29,14 @@
#include "NativewindowCommon.h"
#include "Xmisc.h"
#include "jogamp_nativewindow_x11_X11Lib.h"
+#include "jogamp_nativewindow_x11_X11Util.h"
+
+#include <X11/Xatom.h>
+
+#include <X11/extensions/Xrender.h>
+
+/** Remove memcpy GLIBC > 2.4 dependencies */
+#include <glibc-compat-symbols.h>
// #define VERBOSE_ON 1
@@ -84,6 +92,8 @@ Bool XF86VidModeSetGammaRamp(
#define RTLD_DEFAULT NULL
#endif
+#define X11_MOUSE_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask)
+
static const char * const ClazzNameBuffers = "com/jogamp/common/nio/Buffers";
static const char * const ClazzNameBuffersStaticCstrName = "copyByteBuffer";
static const char * const ClazzNameBuffersStaticCstrSignature = "(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;";
@@ -103,128 +113,116 @@ static jmethodID pointCstr = NULL;
static void _initClazzAccess(JNIEnv *env) {
jclass c;
- if(!NativewindowCommon_init(env)) return;
-
- getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11UtilClazz, "getCurrentThreadName", "()Ljava/lang/String;");
- if(NULL==getCurrentThreadNameID) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method getCurrentThreadName");
- }
- dumpStackID = (*env)->GetStaticMethodID(env, X11UtilClazz, "dumpStack", "()V");
- if(NULL==dumpStackID) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method dumpStack");
- }
-
- c = (*env)->FindClass(env, ClazzNameBuffers);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers);
- }
- clazzBuffers = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==clazzBuffers) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameBuffers);
- }
- c = (*env)->FindClass(env, ClazzNameByteBuffer);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameByteBuffer);
- }
- clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameByteBuffer);
- }
-
- cstrBuffers = (*env)->GetStaticMethodID(env, clazzBuffers,
- ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
- if(NULL==cstrBuffers) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't create %s.%s %s",
- ClazzNameBuffers, ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
- }
+ if( NativewindowCommon_init(env) ) {
+ getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11UtilClazz, "getCurrentThreadName", "()Ljava/lang/String;");
+ if(NULL==getCurrentThreadNameID) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method getCurrentThreadName");
+ }
+ dumpStackID = (*env)->GetStaticMethodID(env, X11UtilClazz, "dumpStack", "()V");
+ if(NULL==dumpStackID) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method dumpStack");
+ }
- c = (*env)->FindClass(env, ClazzNamePoint);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNamePoint);
- }
- pointClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==pointClz) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNamePoint);
- }
- pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
- if(NULL==pointCstr) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't fetch %s.%s %s",
- ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
- }
-}
+ c = (*env)->FindClass(env, ClazzNameBuffers);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers);
+ }
+ clazzBuffers = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==clazzBuffers) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameBuffers);
+ }
+ c = (*env)->FindClass(env, ClazzNameByteBuffer);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameByteBuffer);
+ }
+ clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameByteBuffer);
+ }
-static JavaVM *jvmHandle = NULL;
-static int jvmVersion = 0;
+ cstrBuffers = (*env)->GetStaticMethodID(env, clazzBuffers,
+ ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
+ if(NULL==cstrBuffers) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't create %s.%s %s",
+ ClazzNameBuffers, ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
+ }
-static void setupJVMVars(JNIEnv * env) {
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
+ c = (*env)->FindClass(env, ClazzNamePoint);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNamePoint);
+ }
+ pointClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==pointClz) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNamePoint);
+ }
+ pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ if(NULL==pointCstr) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't fetch %s.%s %s",
+ ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ }
}
- jvmVersion = (*env)->GetVersion(env);
}
static XErrorHandler origErrorHandler = NULL ;
-static int errorHandlerQuiet = 0 ;
+static int errorHandlerQuiet = 1 ;
static int errorHandlerDebug = 0 ;
static int errorHandlerThrowException = 0;
static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
{
- if(!errorHandlerQuiet) {
+ if( !errorHandlerQuiet || errorHandlerDebug ) {
const char * errnoStr = strerror(errno);
- char threadName[80];
char errCodeStr[80];
char reqCodeStr[80];
-
int shallBeDetached = 0;
- JNIEnv *jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv *jniEnv = NULL;
- (void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
snprintf(errCodeStr, sizeof(errCodeStr), "%d", e->request_code);
XGetErrorDatabaseText(dpy, "XRequest", errCodeStr, "Unknown", reqCodeStr, sizeof(reqCodeStr));
XGetErrorText(dpy, e->error_code, errCodeStr, sizeof(errCodeStr));
- fprintf(stderr, "Info: Nativewindow X11 Error (Thread: %s): %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
- threadName, e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
+ fprintf(stderr, "Info: Nativewindow X11 Error: %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
+ e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
(int)e->request_code, (int)e->minor_code, reqCodeStr);
+ fflush(stderr);
- if( errorHandlerDebug ) {
- (*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
- }
-
- if(errorHandlerThrowException) {
- if(NULL != jniEnv) {
- NativewindowCommon_throwNewRuntimeException(jniEnv, "Nativewindow X11 Error (Thread: %s): %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
- threadName, e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
- (int)e->request_code, (int)e->minor_code, reqCodeStr);
- } else {
+ if( errorHandlerDebug || errorHandlerThrowException ) {
+ jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached);
+ if(NULL == jniEnv) {
fprintf(stderr, "Nativewindow X11 Error: null JNIEnv");
- #if 0
- if(NULL!=origErrorHandler) {
- origErrorHandler(dpy, e);
- }
- #endif
+ fflush(stderr);
}
}
- fflush(stderr);
- if (NULL != jniEnv && shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ if( NULL != jniEnv ) {
+ if( errorHandlerDebug ) {
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
+ }
+
+ if(errorHandlerThrowException) {
+ NativewindowCommon_throwNewRuntimeException(jniEnv, "Nativewindow X11 Error: %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
+ e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
+ (int)e->request_code, (int)e->minor_code, reqCodeStr);
+ }
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
}
}
return 0;
}
-void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync) {
+static void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int force, int onoff, int quiet, int sync) {
errorHandlerQuiet = quiet;
if(onoff) {
- if(NULL==origErrorHandler) {
- setupJVMVars(env);
- origErrorHandler = XSetErrorHandler(x11ErrorHandler);
+ if(force || NULL==origErrorHandler) {
+ XErrorHandler prevErrorHandler;
+ prevErrorHandler = XSetErrorHandler(x11ErrorHandler);
+ if(x11ErrorHandler != prevErrorHandler) { // if forced don't overwrite w/ orig w/ our handler
+ origErrorHandler = prevErrorHandler;
+ }
if(sync && NULL!=dpy) {
XSync(dpy, False);
}
@@ -246,21 +244,16 @@ static int x11IOErrorHandler(Display *dpy)
{
const char * dpyName = XDisplayName(NULL);
const char * errnoStr = strerror(errno);
- char threadName[80];
int shallBeDetached = 0;
- JNIEnv *jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv *jniEnv = NULL;
- (void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
-
- fprintf(stderr, "Nativewindow X11 IOError (Thread %s): Display %p (%s): %s\n", threadName, dpy, dpyName, errnoStr);
- (*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
+ fprintf(stderr, "Nativewindow X11 IOError: Display %p (%s): %s\n", dpy, dpyName, errnoStr);
+ fflush(stderr);
+ jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached);
if (NULL != jniEnv) {
- NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError (Thread %s): Display %p (%s): %s", threadName, dpy, dpyName, errnoStr);
-
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr);
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
}
if(NULL!=origIOErrorHandler) {
origIOErrorHandler(dpy);
@@ -271,7 +264,6 @@ static int x11IOErrorHandler(Display *dpy)
static void x11IOErrorHandlerEnable(int onoff, JNIEnv * env) {
if(onoff) {
if(NULL==origIOErrorHandler) {
- setupJVMVars(env);
origIOErrorHandler = XSetIOErrorHandler(x11IOErrorHandler);
}
} else {
@@ -280,47 +272,49 @@ static void x11IOErrorHandlerEnable(int onoff, JNIEnv * env) {
}
}
-static int _initialized=0;
-static jboolean _xinitThreadsOK=JNI_FALSE;
+static int _initialized = 0;
JNIEXPORT jboolean JNICALL
-Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboolean firstUIActionOnProcess, jboolean debug) {
- if(0==_initialized) {
+Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboolean debug) {
+ if( 0 == _initialized ) {
if(debug) {
errorHandlerDebug = 1;
}
X11UtilClazz = (jclass)(*env)->NewGlobalRef(env, clazz);
- if( JNI_TRUE == firstUIActionOnProcess ) {
- if( 0 == XInitThreads() ) {
- fprintf(stderr, "Warning: XInitThreads() failed\n");
- } else {
- _xinitThreadsOK=JNI_TRUE;
- if(debug) {
- fprintf(stderr, "X11: XInitThreads() called for concurrent Thread support\n");
- }
- }
- } else if(debug) {
- fprintf(stderr, "X11: XInitThreads() _not_ called for concurrent Thread support\n");
- }
_initClazzAccess(env);
x11IOErrorHandlerEnable(1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 1, debug ? 0 : 1, 0 /* no dpy, force, no sync */);
_initialized=1;
if(JNI_TRUE == debug) {
fprintf(stderr, "Info: NativeWindow native init passed\n");
}
}
- return _xinitThreadsOK;
+ return JNI_TRUE;
}
JNIEXPORT void JNICALL
Java_jogamp_nativewindow_x11_X11Util_shutdown0(JNIEnv *env, jclass _unused) {
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, errorHandlerQuiet, 0 /* no dpy, no sync */);
x11IOErrorHandlerEnable(0, env);
}
JNIEXPORT void JNICALL
Java_jogamp_nativewindow_x11_X11Util_setX11ErrorHandler0(JNIEnv *env, jclass _unused, jboolean onoff, jboolean quiet) {
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, onoff ? 1 : 0, quiet ? 1 : 0, 0 /* no dpy, no sync */);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, onoff ? 1 : 0, quiet ? 1 : 0, 0 /* no dpy, force, no sync */);
+}
+
+/* Java->C glue code:
+ * Java package: jogamp.nativewindow.x11.X11Lib
+ * Java method: boolean XRenderFindVisualFormat(long dpy, long visual, XRenderPictFormat dest)
+ */
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_x11_X11Lib_XRenderFindVisualFormat1(JNIEnv *env, jclass _unused, jlong dpy, jlong visual, jobject xRenderPictFormat) {
+ XRenderPictFormat * dest = (XRenderPictFormat *) (*env)->GetDirectBufferAddress(env, xRenderPictFormat);
+ XRenderPictFormat * src = XRenderFindVisualFormat((Display *) (intptr_t) dpy, (Visual *) (intptr_t) visual);
+ if (NULL == src) return JNI_FALSE;
+ memcpy(dest, src, sizeof(XRenderPictFormat));
+ return JNI_TRUE;
}
/* Java->C glue code:
@@ -332,30 +326,30 @@ JNIEXPORT jobject JNICALL
Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Ljava_lang_Object_2I(JNIEnv *env, jclass _unused, jlong arg0, jlong arg1, jobject arg2, jobject arg3, jint arg3_byte_offset) {
XVisualInfo * _ptr2 = NULL;
int * _ptr3 = NULL;
- XVisualInfo * _res;
- int count;
- jobject jbyteSource;
- jobject jbyteCopy;
- if(0==arg0) {
- NativewindowCommon_FatalError(env, "invalid display connection..");
- }
- if (arg2 != NULL) {
- _ptr2 = (XVisualInfo *) (((char*) (*env)->GetDirectBufferAddress(env, arg2)) + 0);
- }
- if (arg3 != NULL) {
- _ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset);
+ XVisualInfo * _res = NULL;
+ int count = 0;
+ jobject jbyteSource = NULL;
+ jobject jbyteCopy = NULL;
+ if( 0 == arg0 || 0 == arg2 || 0 == arg3 ) {
+ NativewindowCommon_FatalError(env, "invalid display connection, vinfo_template or nitems_return");
+ return NULL;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 1, 0, 0);
- _res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, 0);
- count = _ptr3[0];
- if (arg3 != NULL) {
- (*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
+ _ptr2 = (XVisualInfo *) (((char*) (*env)->GetDirectBufferAddress(env, arg2)) + 0);
+ if( NULL != _ptr2 ) {
+ _ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset);
+ if( NULL != _ptr3 ) {
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 1, errorHandlerQuiet, 0);
+ _res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, errorHandlerQuiet, 0);
+ count = _ptr3[0];
+ (*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
+ }
}
if (_res == NULL) return NULL;
jbyteSource = (*env)->NewDirectByteBuffer(env, _res, count * sizeof(XVisualInfo));
jbyteCopy = (*env)->CallStaticObjectMethod(env, clazzBuffers, cstrBuffers, jbyteSource);
+ (*env)->DeleteLocalRef(env, jbyteSource);
XFree(_res);
@@ -371,10 +365,10 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
if(NULL==dpy) {
NativewindowCommon_throwNewRuntimeException(env, "invalid display connection..");
- return;
+ return 0;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 1);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 1);
memset(&xwa, 0, sizeof(XWindowAttributes));
XGetWindowAttributes(dpy, w, &xwa);
if(NULL != xwa.visual) {
@@ -382,7 +376,7 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
} else {
r = 0;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
return r;
}
@@ -394,9 +388,9 @@ Java_jogamp_nativewindow_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused,
if(0==display) {
NativewindowCommon_FatalError(env, "invalid display connection..");
}
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 1, errorHandlerQuiet, 0);
r = (jint) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) );
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, errorHandlerQuiet, 0);
return r;
}
@@ -437,23 +431,68 @@ Java_jogamp_nativewindow_x11_X11Lib_XCloseDisplay__J(JNIEnv *env, jclass _unused
if(0==display) {
NativewindowCommon_FatalError(env, "invalid display connection..");
}
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 1, errorHandlerQuiet, 0);
_res = XCloseDisplay((Display *) (intptr_t) display);
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, errorHandlerQuiet, 0);
return _res;
}
+static void NativewindowX11_setNormalWindowEWMH (Display *dpy, Window w) {
+ Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False );
+ Atom types[1]={0};
+ types[0] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False );
+ XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, 1);
+ XSync(dpy, False);
+}
+
+#define DECOR_USE_MWM 1 // works for known WMs
+// #define DECOR_USE_EWMH 1 // haven't seen this to work (NORMAL->POPUP, never gets undecorated)
+
+/* see <http://tonyobryan.com/index.php?article=9> */
+#define MWM_HINTS_DECORATIONS (1L << 1)
+#define PROP_MWM_HINTS_ELEMENTS 5
+
+static void NativewindowX11_setDecorations (Display *dpy, Window w, Bool decorated) {
+
+#ifdef DECOR_USE_MWM
+ unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status
+ Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False );
+#endif
+
+#ifdef DECOR_USE_EWMH
+ Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False );
+ Atom types[3]={0};
+ int ntypes=0;
+ if(True==decorated) {
+ types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False );
+ } else {
+ types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", False );
+ }
+#endif
+
+#ifdef DECOR_USE_MWM
+ XChangeProperty( dpy, w, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS);
+#endif
+
+#ifdef DECOR_USE_EWMH
+ XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
+#endif
+
+ XSync(dpy, False);
+}
+
/*
* Class: jogamp_nativewindow_x11_X11Lib
- * Method: CreateDummyWindow
- * Signature: (JIIII)J
+ * Method: CreateWindow
+ * Signature: (JJIIIIZZ)J
*/
-JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
- (JNIEnv *env, jclass unused, jlong display, jint screen_index, jint visualID, jint width, jint height)
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateWindow
+ (JNIEnv *env, jclass unused, jlong parent, jlong display, jint screen_index, jint visualID, jint width, jint height, jboolean input, jboolean visible)
{
Display * dpy = (Display *)(intptr_t)display;
int scrn_idx = (int)screen_index;
- Window windowParent = 0;
+ Window root = RootWindow(dpy, scrn_idx);
+ Window windowParent = (Window) parent;
Window window = 0;
XVisualInfo visualTemplate;
@@ -477,9 +516,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
return 0;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
scrn = ScreenOfDisplay(dpy, scrn_idx);
+ if(0==windowParent) {
+ windowParent = root;
+ }
// try given VisualID on screen
memset(&visualTemplate, 0, sizeof(XVisualInfo));
@@ -497,7 +539,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
if (visual==NULL)
{
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
NativewindowCommon_throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!");
return 0;
}
@@ -507,9 +549,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
pVisualQuery=NULL;
}
- if(0==windowParent) {
- windowParent = XRootWindowOfScreen(scrn);
- }
attrMask = ( CWBackingStore | CWBackingPlanes | CWBackingPixel | CWBackPixmap |
CWBorderPixel | CWColormap | CWOverrideRedirect ) ;
@@ -521,15 +560,22 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
xswa.backing_store=NotUseful; /* NotUseful, WhenMapped, Always */
xswa.backing_planes=0; /* planes to be preserved if possible */
xswa.backing_pixel=0; /* value to use in restoring planes */
+ if( input ) {
+ xswa.event_mask = X11_MOUSE_EVENT_MASK;
+ xswa.event_mask |= KeyPressMask | KeyReleaseMask ;
+ }
+ if( visible ) {
+ xswa.event_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask ;
+ }
xswa.colormap = XCreateColormap(dpy,
- XRootWindow(dpy, scrn_idx),
+ windowParent,
visual,
AllocNone);
window = XCreateWindow(dpy,
windowParent,
- 0, 0,
+ 0, 0, // only a hint, WM most likely will override
width, height,
0, // border width
depth,
@@ -537,11 +583,27 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
visual,
attrMask,
&xswa);
+ if(0==window) {
+ NativewindowCommon_throwNewRuntimeException(env, "could not create Window, bail out!");
+ return 0;
+ }
+
+ NativewindowX11_setNormalWindowEWMH(dpy, window);
+ NativewindowX11_setDecorations(dpy, window, False);
+
+ if( visible ) {
+ XEvent event;
+
+ XMapWindow(dpy, window);
+ }
+
XSync(dpy, False);
- XSelectInput(dpy, window, 0); // no events
+ if( !input ) {
+ XSelectInput(dpy, window, 0); // no events
+ }
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", window, dpy);
@@ -551,25 +613,57 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
/*
* Class: jogamp_nativewindow_x11_X11Lib
- * Method: DestroyDummyWindow
+ * Method: DestroyWindow
* Signature: (JJ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyDummyWindow
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyWindow
(JNIEnv *env, jclass unused, jlong display, jlong window)
{
Display * dpy = (Display *)(intptr_t)display;
Window w = (Window) window;
+ XWindowAttributes xwa;
if(NULL==dpy) {
NativewindowCommon_throwNewRuntimeException(env, "invalid display connection..");
return;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
+ XSync(dpy, False);
+ memset(&xwa, 0, sizeof(XWindowAttributes));
+ XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction
+ XSelectInput(dpy, w, 0);
XUnmapWindow(dpy, w);
XSync(dpy, False);
XDestroyWindow(dpy, w);
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ if( None != xwa.colormap ) {
+ XFreeColormap(dpy, xwa.colormap);
+ }
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
+}
+
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_SetWindowPosSize
+ (JNIEnv *env, jclass unused, jlong display, jlong window, jint x, jint y, jint width, jint height) {
+ Display * dpy = (Display *)(intptr_t)display;
+ Window w = (Window) window;
+ XWindowChanges xwc;
+ int flags = 0;
+
+ memset(&xwc, 0, sizeof(XWindowChanges));
+
+ if(0<=x && 0<=y) {
+ flags |= CWX | CWY;
+ xwc.x=x;
+ xwc.y=y;
+ }
+
+ if(0<width && 0<height) {
+ flags |= CWWidth | CWHeight;
+ xwc.width=width;
+ xwc.height=height;
+ }
+ XConfigureWindow(dpy, w, flags, &xwc);
+ XSync(dpy, False);
}
/*
@@ -593,11 +687,11 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_x11_X11Lib_GetRelativeLocatio
if( 0 == jdest_win ) { dest_win = root; }
if( 0 == jsrc_win ) { src_win = root; }
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
res = XTranslateCoordinates(dpy, src_win, dest_win, src_x, src_y, &dest_x, &dest_y, &child);
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 0);
DBG_PRINT( "X11: GetRelativeLocation0: %p %d/%d -> %p %d/%d - ok: %d\n",
(void*)src_win, src_x, src_y, (void*)dest_win, dest_x, dest_y, (int)res);
@@ -605,3 +699,38 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_x11_X11Lib_GetRelativeLocatio
return (*env)->NewObject(env, pointClz, pointCstr, (jint)dest_x, (jint)dest_y);
}
+/*
+ * Class: jogamp_nativewindow_x11_X11Lib
+ * Method: QueryExtension0
+ * Signature: (JLjava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_x11_X11Lib_QueryExtension0
+ (JNIEnv *env, jclass unused, jlong jdisplay, jstring jextensionName)
+{
+ int32_t major_opcode, first_event, first_error;
+ jboolean res = JNI_FALSE;
+ Display * display = (Display *) (intptr_t) jdisplay;
+ const char* extensionName = NULL;
+
+ if(NULL==display) {
+ NativewindowCommon_throwNewRuntimeException(env, "NULL argument \"display\"");
+ return res;
+ }
+ if ( NULL == jextensionName ) {
+ NativewindowCommon_throwNewRuntimeException(env, "NULL argument \"extensionName\"");
+ return res;
+ }
+ extensionName = (*env)->GetStringUTFChars(env, jextensionName, (jboolean*)NULL);
+ if ( NULL == extensionName ) {
+ NativewindowCommon_throwNewRuntimeException(env, "Failed to get UTF-8 chars for argument \"extensionName\"");
+ return res;
+ }
+
+ res = True == XQueryExtension(display, extensionName, &major_opcode, &first_event, &first_error) ? JNI_TRUE : JNI_FALSE;
+
+ if ( NULL != jextensionName ) {
+ (*env)->ReleaseStringUTFChars(env, jextensionName, extensionName);
+ }
+ return res;
+}
+
diff --git a/src/nativewindow/native/x11/Xmisc.h b/src/nativewindow/native/x11/Xmisc.h
index a44da950d..91f2ac5d9 100644
--- a/src/nativewindow/native/x11/Xmisc.h
+++ b/src/nativewindow/native/x11/Xmisc.h
@@ -39,6 +39,4 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync);
-
#endif /* Xmisc_h */
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 1e9a0e9eb..c4b919951 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -28,31 +28,212 @@
package com.jogamp.newt;
-import com.jogamp.newt.util.EDTUtil;
-import jogamp.newt.Debug;
-
-import java.util.*;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PointImmutable;
+
+import jogamp.newt.Debug;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.util.EDTUtil;
public abstract class Display {
public static final boolean DEBUG = Debug.debug("Display");
+ protected static final boolean DEBUG_POINTER_ICON = Debug.debug("Display.PointerIcon");
/** return precomputed hashCode from FQN {@link #getFQName()} */
+ @Override
public abstract int hashCode();
/** return true if obj is of type Display and both FQN {@link #getFQName()} equals */
- public boolean equals(Object obj) {
+ @Override
+ public boolean equals(final Object obj) {
if (this == obj) { return true; }
if (obj instanceof Display) {
- Display d = (Display)obj;
+ final Display d = (Display)obj;
return d.getFQName().equals(getFQName());
}
return false;
}
/**
+ * Native PointerIcon handle.
+ * <p>
+ * Instances can be created via {@link Display}'s
+ * {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) createPointerIcon(pngResource, ..)}
+ * or {@link Display#createPointerIcon(PixelRectangle, int, int) createPointerIcon(pixelrect, ..)}.
+ * </p>
+ * <p>
+ * Instance is {@link #destroy()}'ed automatically if it's {@link #getDisplay() associated Display} is destroyed.
+ * </p>
+ * <p>
+ * Instance can be re-validated after destruction via {@link #validate()}.
+ * </p>
+ * <p>
+ * {@link PointerIcon} must not be {@link #destroy() destroyed} while in use!
+ * </p>
+ * <p>
+ * {@link PointerIcon} may be {@link #destroy() destroyed} manually after use,
+ * i.e. when no {@link Window} {@link Window#setPointerIcon(PointerIcon) uses them} anymore.
+ * However, this is not required.
+ * </p>
+ * <p>
+ * PointerIcons can be used via {@link Window#setPointerIcon(PointerIcon)}.
+ * </p>
+ */
+ public static interface PointerIcon extends PixelRectangle {
+ /**
+ * Always neatly packed, i.e. width * bytes_per_pixel.
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ @Override
+ int getStride();
+
+ /**
+ * Always false, i.e. origin is TOP-LEFT.
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ boolean isGLOriented();
+
+ /**
+ * Computes a hash code over:
+ * <ul>
+ * <li>display</li>
+ * <li>pixelformat</li>
+ * <li>size</li>
+ * <li>stride</li>
+ * <li>isGLOriented</li>
+ * <li>pixels</li>
+ * <li>hotspot</li>
+ * </ul>
+ * Dismissing the native handle!
+ * <p>
+ * The hashCode shall be computed only once with first call
+ * and stored for later retrieval to enhance performance.
+ * </p>
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ @Override
+ int hashCode();
+
+ /**
+ * @return the associated Display
+ */
+ Display getDisplay();
+
+ /** Returns the hotspot. */
+ PointImmutable getHotspot();
+
+ /**
+ * Returns true if valid, otherwise false.
+ * <p>
+ * A PointerIcon instance becomes invalid if it's {@link #getDisplay() associated Display} is destroyed.
+ * </p>
+ */
+ boolean isValid();
+
+ /**
+ * Returns true if instance {@link #isValid()} or validation was successful, otherwise false.
+ * <p>
+ * Validation, i.e. recreation, is required if instance became invalid, see {@link #isValid()}.
+ * </p>
+ */
+ boolean validate();
+
+ /**
+ * Destroys this instance.
+ * <p>
+ * Will be called automatically if it's {@link #getDisplay() associated Display} is destroyed.
+ * </p>
+ */
+ void destroy();
+ }
+
+ /**
+ * Returns the native platform's {@link PixelFormat} for pointer-icon pixel data.
+ * <p>
+ * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}.
+ * </p>
+ * <p>
+ * Known native pixel formats are:
+ * <ul>
+ * <li>X11: {@link PixelFormat#BGRA8888}</li>
+ * <li>Windows: {@link PixelFormat#BGRA8888}</li>
+ * <li>OSX: {@link PixelFormat#RGBA8888}</li>
+ * </ul>
+ * </p>
+ */
+ public abstract PixelFormat getNativePointerIconPixelFormat();
+
+ /**
+ * Returns the native platform's direct NIO buffer requirement pointer-icon pixel data.
+ * <p>
+ * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}.
+ * </p>
+ */
+ public abstract boolean getNativePointerIconForceDirectNIO();
+
+ /**
+ * Returns the newly created {@link PointerIcon} or <code>null</code> if not implemented on platform.
+ * <p>
+ * See {@link PointerIcon} for lifecycle semantics.
+ * </p>
+ *
+ * @param pngResource single PNG resource for the {@link PointerIcon}. Only the first entry of {@link IOUtil.ClassResources#resourcePaths} is used.
+ * @param hotX pointer hotspot x-coord, origin is upper-left corner
+ * @param hotY pointer hotspot y-coord, origin is upper-left corner
+ *
+ * @throws IllegalArgumentException if pngResource is null or invalid
+ * @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}.
+ * @throws IOException if the <code>pngResource</code> could not be {@link IOUtil.ClassResources#resolve(int) resolved}
+ * or via the PNG parser processing the input stream.
+ *
+ * @see PointerIcon
+ * @see Window#setPointerIcon(PointerIcon)
+ */
+ public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException, IOException;
+
+ /**
+ * Returns the newly created {@link PointerIcon} or <code>null</code> if not implemented on platform.
+ * <p>
+ * See {@link PointerIcon} for lifecycle semantics.
+ * </p>
+ * <p>
+ * In case {@link #getNativePointerIconPixelFormat()} or {@link #getNativePointerIconForceDirectNIO()}
+ * is not matched by the given <code>pixelrect</code>, the <code>pixelrect</code> is converted
+ * into the required {@link PixelFormat} and NIO type.
+ * </p>
+ *
+ * @param pixelrect {@link PixelRectangle} source for the {@link PointerIcon}
+ * @param hotX pointer hotspot x-coord, origin is upper-left corner
+ * @param hotY pointer hotspot y-coord, origin is upper-left corner
+ *
+ * @throws IllegalArgumentException if pixelrect is null.
+ * @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}.
+ *
+ * @see PointerIcon
+ * @see Window#setPointerIcon(PointerIcon)
+ * @see #getNativePointerIconPixelFormat()
+ * @see #getNativePointerIconForceDirectNIO()
+ */
+ public abstract PointerIcon createPointerIcon(final PixelRectangle pixelrect, final int hotX, final int hotY) throws IllegalArgumentException, IllegalStateException;
+
+ /**
* Manual trigger the native creation, if it is not done yet.<br>
* This is useful to be able to request the {@link javax.media.nativewindow.AbstractGraphicsDevice}, via
* {@link #getGraphicsDevice()}.<br>
@@ -77,7 +258,7 @@ public abstract class Display {
* Stop the running EDT in case this display is destroyed already.<br>
* @return true if EDT has been stopped (destroyed but running), otherwise false.
*/
- public abstract boolean validateEDT();
+ public abstract boolean validateEDTStopped();
/**
* @return true if the native display handle is valid and ready to operate,
@@ -88,7 +269,7 @@ public abstract class Display {
public abstract boolean isNativeValid();
/**
- * @return number of references by Screen
+ * @return number of references
*/
public abstract int getReferenceCount();
@@ -96,7 +277,7 @@ public abstract class Display {
* The 1st call will initiate native creation,
* since we follow the lazy creation pattern.
*
- * @return number of references after adding one
+ * @return number of references post operation
* @throws NativeWindowException if the native creation failed.
* @see #removeReference()
*/
@@ -106,31 +287,37 @@ public abstract class Display {
* The last call may destroy this instance,
* if {@link #getDestroyWhenUnused()} returns <code>true</code>.
*
- * @return number of references after removing one
+ * @return number of references post operation
* @see #addReference()
* @see #getDestroyWhenUnused()
* @see #setDestroyWhenUnused(boolean)
*/
public abstract int removeReference();
+ /**
+ * Return the {@link AbstractGraphicsDevice} used for depending resources lifecycle,
+ * i.e. {@link Screen} and {@link Window}, as well as the event dispatching (EDT). */
public abstract AbstractGraphicsDevice getGraphicsDevice();
/**
- * @return the fully qualified Display name,
- * which is a key of {@link #getType()} + {@link #getName()} + {@link #getId()}
+ * Return the handle of the {@link AbstractGraphicsDevice} as returned by {@link #getGraphicsDevice()}.
*/
- public abstract String getFQName();
-
public abstract long getHandle();
/**
+ * @return The fully qualified Display name,
+ * which is a key of {@link #getType()} + {@link #getName()} + {@link #getId()}.
+ */
+ public abstract String getFQName();
+
+ /**
* @return this display internal serial id
*/
public abstract int getId();
/**
- * @return This display connection name as defined at creation time.
- * The display connection name is a technical platform specific detail, see {@link AbstractGraphicsDevice#getConnection()}.
+ * @return This display connection name as defined at creation time.
+ * The display connection name is a technical platform specific detail, see {@link AbstractGraphicsDevice#getConnection()}.
*
* @see AbstractGraphicsDevice#getConnection()
*/
@@ -141,53 +328,60 @@ public abstract class Display {
*/
public abstract String getType();
+ /** Return true if this instance is exclusive, i.e. will not be shared. */
+ public abstract boolean isExclusive();
+
/**
* Sets a new {@link EDTUtil} and returns the previous one.
* <p>
- * If <code>newEDTUtil</code> is <code>null</code>,
+ * If <code>usrEDTUtil</code> is <code>null</code>,
* the device's default EDTUtil is created and used.
* </p>
* <p>
- * If a previous one exists and it differs from the new one,
- * it's being stopped, wait-until-idle and reset to allow restart.
+ * If a previous one exists and it differs from <code>usrEDTUtil</code>,
+ * it's being stopped, wait-until-idle.
* </p>
* <p>
- * If <code>newEDTUtil</code> is not null and equals the previous one,
- * <code>null</code> is returned and no change is being made.
+ * If <code>usrEDTUtil</code> is not null and equals the previous one,
+ * no change is being made.
* </p>
*/
- public abstract EDTUtil setEDTUtil(EDTUtil newEDTUtil);
-
+ public abstract EDTUtil setEDTUtil(EDTUtil usrEDTUtil);
+
public abstract EDTUtil getEDTUtil();
+ /**
+ * @return true if EDT is running and not subject to be stopped, otherwise false.
+ */
public abstract boolean isEDTRunning();
public abstract void dispatchMessages();
-
+
// Global Displays
- protected static ArrayList<Display> displayList = new ArrayList<Display>();
+ protected static final ArrayList<WeakReference<Display>> displayList = new ArrayList<WeakReference<Display>>();
protected static int displaysActive = 0;
- public static void dumpDisplayList(String prefix) {
+ public static void dumpDisplayList(final String prefix) {
synchronized(displayList) {
- Iterator<Display> i = displayList.iterator();
System.err.println(prefix+" DisplayList[] entries: "+displayList.size()+" - "+getThreadName());
- for(int j=0; i.hasNext(); j++) {
- Display d = i.next();
- System.err.println(" ["+j+"] : "+d);
+ final Iterator<WeakReference<Display>> ri = displayList.iterator();
+ for(int j=0; ri.hasNext(); j++) {
+ final Display d = ri.next().get();
+ System.err.println(" ["+j+"] : "+d+", GC'ed "+(null==d));
}
}
}
/**
- *
+ *
* @param type
* @param name
- * @param fromIndex start index, then increasing until found or end of list *
- * @return
+ * @param fromIndex start index, then increasing until found or end of list
+ * @paran shared if true, only shared instances are found, otherwise also exclusive
+ * @return
*/
- public static Display getFirstDisplayOf(String type, String name, int fromIndex) {
- return getDisplayOfImpl(type, name, fromIndex, 1);
+ public static Display getFirstDisplayOf(final String type, final String name, final int fromIndex, final boolean shared) {
+ return getDisplayOfImpl(type, name, fromIndex, 1, shared);
}
/**
@@ -195,33 +389,69 @@ public abstract class Display {
* @param type
* @param name
* @param fromIndex start index, then decreasing until found or end of list. -1 is interpreted as size - 1.
+ * @param shared if true, only shared instances are found, otherwise also exclusive
* @return
*/
- public static Display getLastDisplayOf(String type, String name, int fromIndex) {
- return getDisplayOfImpl(type, name, fromIndex, -1);
+ public static Display getLastDisplayOf(final String type, final String name, final int fromIndex, final boolean shared) {
+ return getDisplayOfImpl(type, name, fromIndex, -1, shared);
}
- private static Display getDisplayOfImpl(String type, String name, int fromIndex, int incr) {
+ private static Display getDisplayOfImpl(final String type, final String name, final int fromIndex, final int incr, final boolean shared) {
synchronized(displayList) {
int i = fromIndex >= 0 ? fromIndex : displayList.size() - 1 ;
while( ( incr > 0 ) ? i < displayList.size() : i >= 0 ) {
- Display display = (Display) displayList.get(i);
- if( display.getType().equals(type) &&
- display.getName().equals(name) ) {
- return display;
+ final Display display = displayList.get(i).get();
+ if( null == display ) {
+ // Clear GC'ed dead reference entry!
+ displayList.remove(i);
+ if( incr < 0 ) {
+ // decrease
+ i+=incr;
+ } // else nop - remove shifted subsequent elements to the left
+ } else {
+ if( display.getType().equals(type) &&
+ display.getName().equals(name) &&
+ ( !shared || shared && !display.isExclusive() )
+ ) {
+ return display;
+ }
+ i+=incr;
}
- i+=incr;
}
}
return null;
}
+ protected static void addDisplay2List(final Display display) {
+ synchronized(displayList) {
+ // GC before add
+ int i=0;
+ while( i < displayList.size() ) {
+ if( null == displayList.get(i).get() ) {
+ displayList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ displayList.add(new WeakReference<Display>(display));
+ }
+ }
+
/** Returns the global display collection */
- @SuppressWarnings("unchecked")
public static Collection<Display> getAllDisplays() {
ArrayList<Display> list;
synchronized(displayList) {
- list = (ArrayList<Display>) displayList.clone();
+ list = new ArrayList<Display>();
+ int i = 0;
+ while( i < displayList.size() ) {
+ final Display d = displayList.get(i).get();
+ if( null == d ) {
+ displayList.remove(i);
+ } else {
+ list.add( displayList.get(i).get() );
+ i++;
+ }
+ }
}
return list;
}
@@ -236,15 +466,15 @@ public abstract class Display {
return Thread.currentThread().getName();
}
- public static String toHexString(int hex) {
+ public static String toHexString(final int hex) {
return "0x" + Integer.toHexString(hex);
}
- public static String toHexString(long hex) {
+ public static String toHexString(final long hex) {
return "0x" + Long.toHexString(hex);
}
- public static int hashCodeNullSafe(Object o) {
+ public static int hashCodeNullSafe(final Object o) {
return ( null != o ) ? o.hashCode() : 0;
}
}
diff --git a/src/newt/classes/com/jogamp/newt/MonitorDevice.java b/src/newt/classes/com/jogamp/newt/MonitorDevice.java
new file mode 100644
index 000000000..126162006
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/MonitorDevice.java
@@ -0,0 +1,299 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.newt;
+
+import java.util.List;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.nativewindow.util.SurfaceSize;
+
+import com.jogamp.common.util.ArrayHashSet;
+
+/**
+ * Visual output device, i.e. a CRT, LED ..consisting of it's components:<br>
+ * <ui>
+ * <li>Immutable
+ * <ul>
+ * <li>nativeId</li>
+ * <li>{@link DimensionImmutable} size in [mm]</li>
+ * <li>{@link MonitorMode} original mode</li>
+ * <li><code>List&lt;MonitorMode&gt;</code> supportedModes</li>
+ * </ul></li>
+ * <li>Mutable
+ * <ul>
+ * <li>{@link MonitorMode} current mode</li>
+ * <li>{@link RectangleImmutable} viewport (rotated)</li>
+ * </ul></li>
+ * </ul>
+ * <p>
+ * All values of this interface are represented in pixel units, if not stated otherwise.
+ * </p>
+ */
+public abstract class MonitorDevice {
+ protected final Screen screen; // backref
+ protected final int nativeId; // unique monitor device ID
+ protected final DimensionImmutable sizeMM; // in [mm]
+ protected final MonitorMode originalMode;
+ protected final ArrayHashSet<MonitorMode> supportedModes; // FIXME: May need to support mutable mode, i.e. adding modes on the fly!
+ protected MonitorMode currentMode;
+ protected boolean modeChanged;
+ protected Rectangle viewportPU; // in pixel units
+ protected Rectangle viewportWU; // in window units
+
+ protected MonitorDevice(final Screen screen, final int nativeId, final DimensionImmutable sizeMM, final Rectangle viewportPU, final Rectangle viewportWU, final MonitorMode currentMode, final ArrayHashSet<MonitorMode> supportedModes) {
+ this.screen = screen;
+ this.nativeId = nativeId;
+ this.sizeMM = sizeMM;
+ this.originalMode = currentMode;
+ this.supportedModes = supportedModes;
+ this.currentMode = currentMode;
+ this.viewportPU = viewportPU;
+ this.viewportWU = viewportWU;
+ this.modeChanged = false;
+ }
+
+ /** Returns the {@link Screen} owning this monitor. */
+ public final Screen getScreen() {
+ return screen;
+ }
+
+ /**
+ * Tests equality of two <code>MonitorDevice</code> objects
+ * by evaluating equality of it's components:<br>
+ * <ul>
+ * <li><code>nativeID</code></li>
+ * </ul>
+ * <br>
+ */
+ @Override
+ public final boolean equals(final Object obj) {
+ if (this == obj) { return true; }
+ if (obj instanceof MonitorDevice) {
+ final MonitorDevice md = (MonitorDevice)obj;
+ return md.nativeId == nativeId;
+ }
+ return false;
+ }
+
+ /**
+ * Returns a combined hash code of it's elements:<br>
+ * <ul>
+ * <li><code>nativeID</code></li>
+ * </ul>
+ */
+ @Override
+ public final int hashCode() {
+ return nativeId;
+ }
+
+ /** @return the immutable unique native Id of this monitor device. */
+ public final int getId() { return nativeId; }
+
+ /**
+ * @return the immutable monitor size in millimeters.
+ */
+ public final DimensionImmutable getSizeMM() {
+ return sizeMM;
+ }
+
+ /**
+ * Returns the <i>pixels per millimeter</i> value according to the <i>current</i> {@link MonitorMode mode}'s
+ * {@link SurfaceSize#getResolution() surface resolution}.
+ * <p>
+ * To convert the result to <i>dpi</i>, i.e. dots-per-inch, multiply both components with <code>25.4f</code>.
+ * </p>
+ * @param ppmmStore float[2] storage for the ppmm result
+ * @return the passed storage containing the ppmm for chaining
+ */
+ public final float[] getPixelsPerMM(final float[] ppmmStore) {
+ return getPixelsPerMM(getCurrentMode(), ppmmStore);
+ }
+
+ /**
+ * Returns the <i>pixels per millimeter</i> value according to the given {@link MonitorMode mode}'s
+ * {@link SurfaceSize#getResolution() surface resolution}.
+ * <p>
+ * To convert the result to <i>dpi</i>, i.e. dots-per-inch, multiply both components with <code>25.4f</code>.
+ * </p>
+ * @param mode
+ * @param ppmmStore float[2] storage for the ppmm result
+ * @return the passed storage containing the ppmm for chaining
+ */
+ public final float[] getPixelsPerMM(final MonitorMode mode, final float[] ppmmStore) {
+ final DimensionImmutable sdim = getSizeMM();
+ final DimensionImmutable spix = mode.getSurfaceSize().getResolution();
+ ppmmStore[0] = (float)spix.getWidth() / (float)sdim.getWidth();
+ ppmmStore[1] = (float)spix.getHeight() / (float)sdim.getHeight();
+ return ppmmStore;
+ }
+
+ /**
+ * Returns the immutable original {@link com.jogamp.newt.MonitorMode}, as used at NEWT initialization.
+ * <p>
+ * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+ * </p>
+ */
+ public final MonitorMode getOriginalMode() {
+ return originalMode;
+ }
+
+ /**
+ * Returns a list of immutable {@link MonitorMode}s supported by this monitor.
+ * <p>
+ * The list is ordered in descending order,
+ * see {@link MonitorMode#compareTo(MonitorMode)}.
+ * </p>
+ * <p>
+ * Use w/ care, it's not a copy!
+ * </p>
+ */
+ public final List<MonitorMode> getSupportedModes() {
+ return supportedModes.getData();
+ }
+
+ /**
+ * Returns the {@link RectangleImmutable rectangular} portion
+ * of the <b>rotated</b> virtual {@link Screen} size in pixel units
+ * represented by this monitor, i.e. top-left origin and size.
+ * @see Screen
+ */
+ public final RectangleImmutable getViewport() {
+ return viewportPU;
+ }
+
+ /**
+ * Returns the {@link RectangleImmutable rectangular} portion
+ * of the <b>rotated</b> virtual {@link Screen} size in window units
+ * represented by this monitor, i.e. top-left origin and size.
+ * @see Screen
+ */
+ public final RectangleImmutable getViewportInWindowUnits() {
+ return viewportWU;
+ }
+
+ /**
+ * Returns <code>true</code> if given screen coordinates in pixel units
+ * are contained by this {@link #getViewport() viewport}, otherwise <code>false</code>.
+ * @param x x-coord in pixel units
+ * @param y y-coord in pixel units
+ */
+ public final boolean contains(final int x, final int y) {
+ return x >= viewportPU.getX() &&
+ x < viewportPU.getX() + viewportPU.getWidth() &&
+ y >= viewportPU.getY() &&
+ y < viewportPU.getY() + viewportPU.getHeight() ;
+ }
+
+ /**
+ * Calculates the union of the given monitor's {@link #getViewport() viewport} in pixel- and window units.
+ * @param viewport storage for result in pixel units, maybe null
+ * @param viewportInWindowUnits storage for result in window units, maybe null
+ * @param monitors given list of monitors
+ */
+ public static void unionOfViewports(final Rectangle viewport, final Rectangle viewportInWindowUnits, final List<MonitorDevice> monitors) {
+ int x1PU=Integer.MAX_VALUE, y1PU=Integer.MAX_VALUE;
+ int x2PU=Integer.MIN_VALUE, y2PU=Integer.MIN_VALUE;
+ int x1WU=Integer.MAX_VALUE, y1WU=Integer.MAX_VALUE;
+ int x2WU=Integer.MIN_VALUE, y2WU=Integer.MIN_VALUE;
+ for(int i=monitors.size()-1; i>=0; i--) {
+ if( null != viewport ) {
+ final RectangleImmutable viewPU = monitors.get(i).getViewport();
+ x1PU = Math.min(x1PU, viewPU.getX());
+ x2PU = Math.max(x2PU, viewPU.getX() + viewPU.getWidth());
+ y1PU = Math.min(y1PU, viewPU.getY());
+ y2PU = Math.max(y2PU, viewPU.getY() + viewPU.getHeight());
+ }
+ if( null != viewportInWindowUnits ) {
+ final RectangleImmutable viewWU = monitors.get(i).getViewportInWindowUnits();
+ x1WU = Math.min(x1WU, viewWU.getX());
+ x2WU = Math.max(x2WU, viewWU.getX() + viewWU.getWidth());
+ y1WU = Math.min(y1WU, viewWU.getY());
+ y2WU = Math.max(y2WU, viewWU.getY() + viewWU.getHeight());
+ }
+ }
+ if( null != viewport ) {
+ viewport.set(x1PU, y1PU, x2PU - x1PU, y2PU - y1PU);
+ }
+ if( null != viewportInWindowUnits ) {
+ viewportInWindowUnits.set(x1WU, y1WU, x2WU - x1WU, y2WU - y1WU);
+ }
+ }
+
+ public final boolean isOriginalMode() {
+ return currentMode.hashCode() == originalMode.hashCode();
+ }
+
+ /**
+ * Returns <code>true</true> if the {@link MonitorMode}
+ * has been changed programmatic via this API <i>only</i>, otherwise <code>false</code>.
+ * <p>
+ * Note: We cannot guarantee that we won't interfere w/ another running
+ * application's screen mode change or vice versa.
+ * </p>
+ */
+ public final boolean isModeChangedByUs() {
+ return modeChanged && !isOriginalMode();
+ }
+
+ /**
+ * Returns the cached current {@link MonitorMode} w/o native query.
+ * <p>
+ * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+ * </p>
+ * @see #queryCurrentMode()
+ */
+ public final MonitorMode getCurrentMode() {
+ return currentMode;
+ }
+
+ /**
+ * Returns the current {@link MonitorMode} resulting from a native query.
+ * <p>
+ * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+ * </p>
+ * @see #getCurrentMode()
+ */
+ public abstract MonitorMode queryCurrentMode();
+
+ /**
+ * Set the current {@link com.jogamp.newt.MonitorMode}.
+ * @param mode to be made current, must be element of the list {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+ * @return true if successful, otherwise false
+ */
+ public abstract boolean setCurrentMode(MonitorMode mode);
+
+ @Override
+ public String toString() {
+ return "Monitor[Id "+Display.toHexString(nativeId)+", "+sizeMM+" mm, viewport "+viewportPU+ " [pixels], "+viewportWU+" [window], orig "+originalMode+", curr "+currentMode+
+ ", modeChanged "+modeChanged+", modeCount "+supportedModes.size()+"]";
+ }
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/MonitorMode.java b/src/newt/classes/com/jogamp/newt/MonitorMode.java
new file mode 100644
index 000000000..09bc06ebd
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/MonitorMode.java
@@ -0,0 +1,458 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.newt;
+
+import java.util.Comparator;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.nativewindow.util.SurfaceSize;
+
+import com.jogamp.newt.util.MonitorModeUtil;
+
+
+/**
+ * Immutable MonitorMode Class, consisting of it's read only components:<br>
+ * <ul>
+ * <li>nativeId</li>
+ * <li>{@link SizeAndRRate}, consist out of non rotated {@link #getSurfaceSize() surface size}, {@link #getRefreshRate() refresh rate} and {@link #getFlags() flags}.</li>
+ * <li><code>rotation</code>, measured counter clockwise (CCW)</li>
+ * </ul>
+ *
+ * <i>Aquire and filter MonitorMode</i><br>
+ * <ul>
+ * <li>{@link MonitorDevice} Selection:
+ * <ul>
+ * <li>A List of all {@link MonitorDevice}s is accessible via {@link Screen#getMonitorDevices()}.</li>
+ * <li>The main monitor used by a windows is accessible via {@link Window#getMainMonitor()}.</li>
+ * <li>The main monitor covering an arbitrary rectangle is accessible via {@link Screen#getMainMonitor(RectangleImmutable)}.</li>
+ * </ul></li>
+ * <li>The current MonitorMode can be obtained via {@link MonitorDevice#getCurrentMode()}.</li>
+ * <li>The original MonitorMode can be obtained via {@link MonitorDevice#getOriginalMode()}.</li>
+ * <li>{@link MonitorMode} Filtering:
+ * <ul>
+ * <li>A {@link MonitorDevice}'s MonitorModes is accessible via {@link MonitorDevice#getSupportedModes()}.</li>
+ * <li>You may utilize {@link MonitorModeUtil} to filter and select a desired MonitorMode.</li>
+ * </ul></li>
+ * </ul>
+ * <br>
+ *
+ * <i>Changing MonitorMode</i><br>
+ * <ul>
+ * <li> Use {@link MonitorDevice#setCurrentMode(MonitorMode)}
+ * to change the current MonitorMode for all {@link Screen}s referenced via the {@link Screen#getFQName() full qualified name (FQN)}.</li>
+ * <li> The {@link MonitorDevice#getOriginalMode() original mode} is restored when
+ * <ul>
+ * <li>the last FQN referenced Screen closes.</li>
+ * <li>the JVM shuts down.</li>
+ * </ul></li>
+ * </ul>
+ * <br>
+ * Example for changing the MonitorMode:
+ * <pre>
+ // Pick the monitor:
+ // Either the one used by a window ..
+ MonitorDevice monitor = window.getMainMonitor();
+
+ // Or arbitrary from the list ..
+ List<MonitorDevice> allMonitor = getMonitorDevices();
+ MonitorDevice monitor = allMonitor.get(0);
+
+ // Current and original modes ..
+ MonitorMode mmCurrent = monitor.queryCurrentMode();
+ MonitorMode mmOrig = monitor.getOriginalMode();
+
+ // Target resolution in pixel units
+ DimensionImmutable res = new Dimension(800, 600);
+
+ // Target refresh rate shall be similar to current one ..
+ float freq = mmCurrent.getRefreshRate();
+
+ // Target rotation shall be similar to current one
+ int rot = mmCurrent.getRotation();
+
+ // Filter criterias sequential out of all available MonitorMode of the chosen MonitorDevice
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, rot);
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, res);
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, freq);
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+
+ // pick 1st one and set to current ..
+ MonitorMode mm = monitorModes.get(0);
+ monitor.setCurrentMode(mm);
+ * </pre>
+ */
+public class MonitorMode implements Comparable<MonitorMode> {
+
+ /** Comparator for 2 {@link MonitorMode}s, following comparison order as described in {@link MonitorMode#compareTo(MonitorMode)}, returning the ascending order. */
+ public static final Comparator<MonitorMode> monitorModeComparator = new Comparator<MonitorMode>() {
+ @Override
+ public int compare(final MonitorMode mm1, final MonitorMode mm2) {
+ return mm1.compareTo(mm2);
+ } };
+
+ /** Comparator for 2 {@link MonitorMode}s, following comparison order as described in {@link MonitorMode#compareTo(MonitorMode)}, returning the descending order. */
+ public static final Comparator<MonitorMode> monitorModeComparatorInv = new Comparator<MonitorMode>() {
+ @Override
+ public int compare(final MonitorMode mm1, final MonitorMode mm2) {
+ return mm2.compareTo(mm1);
+ } };
+
+ /**
+ * Immutable <i>surfaceSize, flags and refreshRate</i> Class, consisting of it's read only components:<br>
+ * <ul>
+ * <li>nativeId</li>
+ * <li>{@link SurfaceSize} surface memory size</li>
+ * <li><code>flags</code></li>
+ * <li><code>refresh rate</code></li>
+ * </ul>
+ */
+ public static class SizeAndRRate implements Comparable<SizeAndRRate> {
+ /** Non rotated surface size in pixel units */
+ public final SurfaceSize surfaceSize;
+ /** Mode bitfield flags, i.e. {@link #FLAG_DOUBLESCAN}, {@link #FLAG_INTERLACE}, .. */
+ public final int flags;
+ /** Vertical refresh rate */
+ public final float refreshRate;
+ public final int hashCode;
+
+ public SizeAndRRate(final SurfaceSize surfaceSize, final float refreshRate, final int flags) {
+ if(null==surfaceSize) {
+ throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")");
+ }
+ this.surfaceSize=surfaceSize;
+ this.flags = flags;
+ this.refreshRate=refreshRate;
+ this.hashCode = getHashCode();
+ }
+
+ private final static String STR_INTERLACE = "Interlace";
+ private final static String STR_DOUBLESCAN = "DoubleScan";
+ private final static String STR_SEP = ", ";
+
+ public static final StringBuilder flags2String(final int flags) {
+ final StringBuilder sb = new StringBuilder();
+ boolean sp = false;
+ if( 0 != ( flags & FLAG_INTERLACE ) ) {
+ sb.append(STR_INTERLACE);
+ sp = true;
+ }
+ if( 0 != ( flags & FLAG_DOUBLESCAN ) ) {
+ if( sp ) {
+ sb.append(STR_SEP);
+ }
+ sb.append(STR_DOUBLESCAN);
+ sp = true;
+ }
+ return sb;
+ }
+ @Override
+ public final String toString() {
+ return surfaceSize+" @ "+refreshRate+" Hz, flags ["+flags2String(flags).toString()+"]";
+ }
+
+ /**
+ * <p>
+ * Compares {@link SurfaceSize#compareTo(SurfaceSize) surfaceSize} 1st, then {@link #flags}, then {@link #refreshRate}.
+ * </p>
+ * <p>
+ * Flags are compared as follows:
+ * <pre>
+ * NONE > DOUBLESCAN > INTERLACE
+ * </pre>
+ * </p>
+ * <p>
+ * Refresh rate differences of &lt; 0.01 are considered equal (epsilon).
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final SizeAndRRate sszr) {
+ final int rssz = surfaceSize.compareTo(sszr.surfaceSize);
+ if( 0 != rssz ) {
+ return rssz;
+ }
+ final int tflags = 0 == flags ? Integer.MAX_VALUE : flags; // normalize NONE
+ final int xflags = 0 == sszr.flags ? Integer.MAX_VALUE : sszr.flags; // normalize NONE
+ if( tflags == xflags ) {
+ final float refreshEpsilon = 0.01f; // reasonable sorting granularity of refresh rate
+ final float drate = refreshRate - sszr.refreshRate;
+ if( Math.abs(drate) < refreshEpsilon ) {
+ return 0;
+ } else if( drate > refreshEpsilon ) {
+ return 1;
+ } else {
+ return -1;
+ }
+ } else {
+ if(tflags > xflags) {
+ return 1;
+ } else if(tflags < xflags) {
+ return -1;
+ }
+ return 0;
+ }
+ }
+
+ /**
+ * Tests equality of two {@link SizeAndRRate} objects
+ * by evaluating equality of it's components:<br/>
+ * <ul>
+ * <li><code>surfaceSize</code></li>
+ * <li><code>refreshRate</code></li>
+ * <li><code>flags</code></li>
+ * </ul>
+ */
+ @Override
+ public final boolean equals(final Object obj) {
+ if (this == obj) { return true; }
+ if (obj instanceof SizeAndRRate) {
+ final SizeAndRRate p = (SizeAndRRate)obj;
+ return surfaceSize.equals(p.surfaceSize) &&
+ flags == p.flags &&
+ refreshRate == p.refreshRate ;
+ }
+ return false;
+ }
+
+ /**
+ * Returns a combined hash code of it's elements:<br/>
+ * <ul>
+ * <li><code>surfaceSize</code></li>
+ * <li><code>flags</code></li>
+ * <li><code>refreshRate</code></li>
+ * </ul>
+ */
+ @Override
+ public final int hashCode() {
+ return hashCode;
+ }
+ private final int getHashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + surfaceSize.hashCode();
+ hash = ((hash << 5) - hash) + flags;
+ hash = ((hash << 5) - hash) + (int)(refreshRate*100.0f);
+ return hash;
+ }
+ }
+
+ /** zero rotation, compared to normal settings */
+ public static final int ROTATE_0 = 0;
+
+ /** 90 degrees CCW rotation */
+ public static final int ROTATE_90 = 90;
+
+ /** 180 degrees CCW rotation */
+ public static final int ROTATE_180 = 180;
+
+ /** 270 degrees CCW rotation */
+ public static final int ROTATE_270 = 270;
+
+ /** Frame is split into two fields. See {@link #getFlags()}. */
+ public static final int FLAG_INTERLACE = 1 << 0;
+
+ /** Lines are doubled. See {@link #getFlags()}. */
+ public static final int FLAG_DOUBLESCAN = 1 << 1;
+
+ /** The immutable native Id of this instance, which may not be unique. */
+ private final int nativeId;
+ private final SizeAndRRate sizeAndRRate;
+ private final int rotation;
+ private final int hashCode;
+
+ public static boolean isRotationValid(final int rotation) {
+ return rotation == MonitorMode.ROTATE_0 || rotation == MonitorMode.ROTATE_90 ||
+ rotation == MonitorMode.ROTATE_180 || rotation == MonitorMode.ROTATE_270 ;
+ }
+
+ /**
+ * @param sizeAndRRate the surface size and refresh rate mode
+ * @param rotation the screen rotation, measured counter clockwise (CCW)
+ */
+ public MonitorMode(final int nativeId, final SizeAndRRate sizeAndRRate, final int rotation) {
+ if ( !isRotationValid(rotation) ) {
+ throw new RuntimeException("invalid rotation: "+rotation);
+ }
+ this.nativeId = nativeId;
+ this.sizeAndRRate = sizeAndRRate;
+ this.rotation = rotation;
+ this.hashCode = getHashCode();
+ }
+
+ /**
+ * Creates a user instance w/o {@link #getId() identity} to filter our matching modes w/ identity.
+ * <p>
+ * See {@link com.jogamp.newt.util.MonitorModeUtil} for filter utilities.
+ * </p>
+ * @param surfaceSize
+ * @param refreshRate
+ * @param flags
+ * @param rotation
+ */
+ public MonitorMode(final SurfaceSize surfaceSize, final float refreshRate, final int flags, final int rotation) {
+ this(0, new SizeAndRRate(surfaceSize, refreshRate, flags), rotation);
+ }
+
+ /** @return the immutable native Id of this mode, may not be unique, may be 0. */
+ public final int getId() { return nativeId; }
+
+ /** Returns the <i>surfaceSize and refreshRate</i> instance. */
+ public final SizeAndRRate getSizeAndRRate() {
+ return sizeAndRRate;
+ }
+
+ /** Returns the unrotated {@link SurfaceSize} */
+ public final SurfaceSize getSurfaceSize() {
+ return sizeAndRRate.surfaceSize;
+ }
+
+ /** Returns the vertical refresh rate. */
+ public final float getRefreshRate() {
+ return sizeAndRRate.refreshRate;
+ }
+
+ /** Returns bitfield w/ flags, i.e. {@link #FLAG_DOUBLESCAN}, {@link #FLAG_INTERLACE}, .. */
+ public final int getFlags() {
+ return sizeAndRRate.flags;
+ }
+
+ /** Returns the CCW rotation of this mode */
+ public final int getRotation() {
+ return rotation;
+ }
+
+ /** Returns the rotated screen width in pixel units,
+ * derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
+ * and <code>getRotation()</code>
+ */
+ public final int getRotatedWidth() {
+ return getRotatedWH(true);
+ }
+
+ /** Returns the rotated screen height in pixel units,
+ * derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
+ * and <code>getRotation()</code>
+ */
+ public final int getRotatedHeight() {
+ return getRotatedWH(false);
+ }
+
+ @Override
+ public final String toString() {
+ return "[Id "+Display.toHexString(nativeId)+", " + sizeAndRRate + ", " + rotation + " degr]";
+ }
+
+ /**
+ * <p>
+ * Compares {@link SizeAndRRate#compareTo(SizeAndRRate) sizeAndRRate} 1st, then {@link #rotation}.
+ * </p>
+ * <p>
+ * Rotation is compared inverted, i.e. <code>360 - rotation</code>,
+ * so the lowest rotation reflects a higher value.
+ * </p>
+ * <p>
+ * Order of comparing MonitorMode:
+ * <ul>
+ * <li>resolution</li>
+ * <li>bits per pixel</li>
+ * <li>flags</li>
+ * <li>refresh rate</li>
+ * <li>rotation</li>
+ * </ul>
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final MonitorMode mm) {
+ final int c = sizeAndRRate.compareTo(mm.sizeAndRRate);
+ if( 0 != c ) {
+ return c;
+ }
+ final int trot = 360 - rotation; // normalize rotation
+ final int xrot = 360 - mm.rotation; // normalize rotation
+ if(trot > xrot) {
+ return 1;
+ } else if(trot < xrot) {
+ return -1;
+ }
+ return 0;
+ }
+
+ /**
+ * Tests equality of two {@link MonitorMode} objects
+ * by evaluating equality of it's components:<br/>
+ * <ul>
+ * <li><code>nativeId</code></li>
+ * <li><code>sizeAndRRate</code></li>
+ * <li><code>rotation</code></li>
+ * </ul>
+ */
+ @Override
+ public final boolean equals(final Object obj) {
+ if (this == obj) { return true; }
+ if (obj instanceof MonitorMode) {
+ final MonitorMode sm = (MonitorMode)obj;
+ return sm.nativeId == this.nativeId &&
+ sm.sizeAndRRate.equals(sizeAndRRate) &&
+ sm.rotation == this.rotation ;
+ }
+ return false;
+ }
+
+ /**
+ * Returns a combined hash code of it's elements:<br/>
+ * <ul>
+ * <li><code>nativeId</code></li>
+ * <li><code>sizeAndRRate</code></li>
+ * <li><code>rotation</code></li>
+ * </ul>
+ */
+ @Override
+ public final int hashCode() {
+ return hashCode;
+ }
+ private final int getHashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + getId();
+ hash = ((hash << 5) - hash) + sizeAndRRate.hashCode();
+ hash = ((hash << 5) - hash) + getRotation();
+ return hash;
+ }
+
+ private final int getRotatedWH(final boolean width) {
+ final DimensionImmutable d = sizeAndRRate.surfaceSize.getResolution();
+ final boolean swap = MonitorMode.ROTATE_90 == rotation || MonitorMode.ROTATE_270 == rotation ;
+ if ( ( width && swap ) || ( !width && !swap ) ) {
+ return d.getHeight();
+ }
+ return d.getWidth();
+ }
+}
diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java
index 0644c9164..9606fae08 100644
--- a/src/newt/classes/com/jogamp/newt/NewtFactory.java
+++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,15 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
@@ -41,6 +45,9 @@ import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowFactory;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.PropertyAccess;
+
import jogamp.newt.Debug;
import jogamp.newt.DisplayImpl;
import jogamp.newt.ScreenImpl;
@@ -49,20 +56,60 @@ import jogamp.newt.WindowImpl;
public class NewtFactory {
public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window");
- // Work-around for initialization order problems on Mac OS X
- // between native Newt and (apparently) Fmod
+ public static final String DRIVER_DEFAULT_ROOT_PACKAGE = "jogamp.newt.driver";
+
+ private static IOUtil.ClassResources defaultWindowIcons;
+
static {
- NativeWindowFactory.initSingleton(); // last resort ..
- WindowImpl.init(NativeWindowFactory.getNativeWindowType(true));
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ NativeWindowFactory.initSingleton(); // last resort ..
+ {
+ /** See API Doc in {@link Window} ! */
+ final String[] paths = PropertyAccess.getProperty("newt.window.icons", true, "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png").split("\\s");
+ if( paths.length < 2 ) {
+ throw new IllegalArgumentException("Property 'newt.window.icons' did not specify at least two PNG icons, but "+Arrays.toString(paths));
+ }
+ final Class<?> clazz = NewtFactory.class;
+ defaultWindowIcons = new IOUtil.ClassResources(clazz, paths);
+ }
+ return null;
+ } } );
}
- public static Class<?> getCustomClass(String packageName, String classBaseName) {
+ /**
+ * Returns the application window icon resources to be used.
+ * <p>
+ * Property <code>newt.window.icons</code> may define a list of PNG icons separated by a whitespace character.
+ * Shall reference at least two PNG icons, from lower (16x16) to higher (>= 32x32) resolution.
+ * </p>
+ * <p>
+ * Users may also specify application window icons using {@link #setWindowIcons(com.jogamp.common.util.IOUtil.ClassResources)}.
+ * </p>
+ */
+ public static IOUtil.ClassResources getWindowIcons() { return defaultWindowIcons; }
+
+ /**
+ * Allow user to set custom window icons, only applicable at application start before creating any NEWT instance.
+ * <p>
+ * Shall reference at least two PNG icons, from lower (16x16) to higher (>= 32x32) resolution.
+ * </p>
+ */
+ public static void setWindowIcons(final IOUtil.ClassResources cres) { defaultWindowIcons = cres; }
+
+ public static Class<?> getCustomClass(final String packageName, final String classBaseName) {
Class<?> clazz = null;
if(packageName!=null && classBaseName!=null) {
- final String clazzName = packageName + "." + classBaseName ;
+ final String clazzName;
+ if( packageName.startsWith(".") ) {
+ clazzName = DRIVER_DEFAULT_ROOT_PACKAGE + packageName + "." + classBaseName ;
+ } else {
+ clazzName = packageName + "." + classBaseName ;
+ }
try {
clazz = Class.forName(clazzName);
- } catch (Throwable t) {
+ } catch (final Throwable t) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Warning: Failed to find class <"+clazzName+">: "+t.getMessage());
t.printStackTrace();
@@ -74,12 +121,12 @@ public class NewtFactory {
private static boolean useEDT = true;
- /**
+ /**
* Toggles the usage of an EventDispatchThread while creating a Display.<br>
* The default is enabled.<br>
* The EventDispatchThread is thread local to the Display instance.<br>
*/
- public static synchronized void setUseEDT(boolean onoff) {
+ public static synchronized void setUseEDT(final boolean onoff) {
useEDT = onoff;
}
@@ -92,13 +139,13 @@ public class NewtFactory {
* Native creation is lazily done at usage, ie. {@link Display#addReference()}.
* </p>
* <p>
- * An already existing display connection of the same <code>name</code> will be reused.
+ * An already existing display connection of the same <code>name</code> will be reused.
* </p>
* @param name the display connection name which is a technical platform specific detail,
* see {@link AbstractGraphicsDevice#getConnection()}. Use <code>null</code> for default.
* @return the new or reused Display instance
*/
- public static Display createDisplay(String name) {
+ public static Display createDisplay(final String name) {
return createDisplay(name, true);
}
@@ -116,7 +163,7 @@ public class NewtFactory {
* @param reuse attempt to reuse an existing Display with same <code>name</code> if set true, otherwise create a new instance.
* @return the new or reused Display instance
*/
- public static Display createDisplay(String name, boolean reuse) {
+ public static Display createDisplay(final String name, final boolean reuse) {
return DisplayImpl.create(NativeWindowFactory.getNativeWindowType(true), name, 0, reuse);
}
@@ -133,7 +180,7 @@ public class NewtFactory {
* see {@link AbstractGraphicsDevice#getConnection()}. Use <code>null</code> for default.
* @return the new or reused Display instance
*/
- public static Display createDisplay(String type, String name) {
+ public static Display createDisplay(final String type, final String name) {
return createDisplay(type, name, true);
}
@@ -152,7 +199,7 @@ public class NewtFactory {
* @param reuse attempt to reuse an existing Display with same <code>name</code> if set true, otherwise create a new instance.
* @return the new or reused Display instance
*/
- public static Display createDisplay(String type, String name, boolean reuse) {
+ public static Display createDisplay(final String type, final String name, final boolean reuse) {
return DisplayImpl.create(type, name, 0, reuse);
}
@@ -166,7 +213,7 @@ public class NewtFactory {
* and {@link Display#removeReference()}.
* </p>
*/
- public static Screen createScreen(Display display, int index) {
+ public static Screen createScreen(final Display display, final int index) {
return ScreenImpl.create(display, index);
}
@@ -183,7 +230,7 @@ public class NewtFactory {
* and {@link Screen#removeReference()}.
* </p>
*/
- public static Window createWindow(CapabilitiesImmutable caps) {
+ public static Window createWindow(final CapabilitiesImmutable caps) {
return createWindowImpl(NativeWindowFactory.getNativeWindowType(true), caps);
}
@@ -197,8 +244,8 @@ public class NewtFactory {
* and {@link Screen#removeReference()}.
* </p>
*/
- public static Window createWindow(Screen screen, CapabilitiesImmutable caps) {
- return createWindowImpl(screen, caps);
+ public static Window createWindow(final Screen screen, final CapabilitiesImmutable caps) {
+ return WindowImpl.create(null, 0, screen, caps);
}
/**
@@ -223,8 +270,11 @@ public class NewtFactory {
*
* @param parentWindowObject either a NativeWindow instance
*/
- public static Window createWindow(NativeWindow parentWindow, CapabilitiesImmutable caps) {
+ public static Window createWindow(final NativeWindow parentWindow, final CapabilitiesImmutable caps) {
final String type = NativeWindowFactory.getNativeWindowType(true);
+ if( null == parentWindow ) {
+ return createWindowImpl(type, caps);
+ }
Screen screen = null;
Window newtParentWindow = null;
@@ -234,18 +284,18 @@ public class NewtFactory {
screen = newtParentWindow.getScreen();
} else {
// create a Display/Screen compatible to the NativeWindow
- AbstractGraphicsConfiguration parentConfig = parentWindow.getGraphicsConfiguration();
+ final AbstractGraphicsConfiguration parentConfig = parentWindow.getGraphicsConfiguration();
if(null!=parentConfig) {
- AbstractGraphicsScreen parentScreen = parentConfig.getScreen();
- AbstractGraphicsDevice parentDevice = parentScreen.getDevice();
- Display display = NewtFactory.createDisplay(type, parentDevice.getHandle(), true);
+ final AbstractGraphicsScreen parentScreen = parentConfig.getScreen();
+ final AbstractGraphicsDevice parentDevice = parentScreen.getDevice();
+ final Display display = NewtFactory.createDisplay(type, parentDevice.getHandle(), true);
screen = NewtFactory.createScreen(display, parentScreen.getIndex());
} else {
- Display display = NewtFactory.createDisplay(type, null, true); // local display
+ final Display display = NewtFactory.createDisplay(type, null, true); // local display
screen = NewtFactory.createScreen(display, 0); // screen 0
}
}
- final Window win = createWindowImpl(parentWindow, screen, caps);
+ final Window win = WindowImpl.create(parentWindow, 0, screen, caps);
win.setSize(parentWindow.getWidth(), parentWindow.getHeight());
if ( null != newtParentWindow ) {
@@ -255,32 +305,26 @@ public class NewtFactory {
return win;
}
- protected static Window createWindowImpl(NativeWindow parentNativeWindow, Screen screen, CapabilitiesImmutable caps) {
- return WindowImpl.create(parentNativeWindow, 0, screen, caps);
- }
-
- protected static Window createWindowImpl(long parentWindowHandle, Screen screen, CapabilitiesImmutable caps) {
- return WindowImpl.create(null, parentWindowHandle, screen, caps);
- }
-
- protected static Window createWindowImpl(Screen screen, CapabilitiesImmutable caps) {
- return WindowImpl.create(null, 0, screen, caps);
- }
-
- protected static Window createWindowImpl(String type, CapabilitiesImmutable caps) {
- Display display = NewtFactory.createDisplay(type, null, true); // local display
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ private static Window createWindowImpl(final String type, final CapabilitiesImmutable caps) {
+ final Display display = NewtFactory.createDisplay(type, null, true); // local display
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
return WindowImpl.create(null, 0, screen, caps);
}
/**
* Create a child Window entity attached to the given parent, incl native creation<br>
*
- * @param parentWindowObject the native parent window handle
- * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always
+ * @param displayConnection the parent window's display connection
+ * @param screenIdx the desired screen index
+ * @param parentWindowHandle the native parent window handle
+ * @param caps the desired capabilities
+ * @return
*/
- public static Window createWindow(long parentWindowHandle, Screen screen, CapabilitiesImmutable caps) {
- return createWindowImpl(parentWindowHandle, screen, caps);
+ public static Window createWindow(final String displayConnection, final int screenIdx, final long parentWindowHandle, final CapabilitiesImmutable caps) {
+ final String type = NativeWindowFactory.getNativeWindowType(true);
+ final Display display = NewtFactory.createDisplay(type, displayConnection, true);
+ final Screen screen = NewtFactory.createScreen(display, screenIdx);
+ return WindowImpl.create(null, parentWindowHandle, screen, caps);
}
/**
@@ -290,26 +334,26 @@ public class NewtFactory {
*
* @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always
*/
- public static Window createWindow(Object[] cstrArguments, Screen screen, CapabilitiesImmutable caps) {
+ public static Window createWindow(final Object[] cstrArguments, final Screen screen, final CapabilitiesImmutable caps) {
return WindowImpl.create(cstrArguments, screen, caps);
}
/**
* Instantiate a Display entity using the native handle.
*/
- public static Display createDisplay(String type, long handle, boolean reuse) {
- return DisplayImpl.create(type, null, handle, false);
+ public static Display createDisplay(final String type, final long handle, final boolean reuse) {
+ return DisplayImpl.create(type, null, handle, reuse);
}
- public static boolean isScreenCompatible(NativeWindow parent, Screen childScreen) {
+ public static boolean isScreenCompatible(final NativeWindow parent, final Screen childScreen) {
// Get parent's NativeWindow details
- AbstractGraphicsConfiguration parentConfig = (AbstractGraphicsConfiguration) parent.getGraphicsConfiguration();
- AbstractGraphicsScreen parentScreen = (AbstractGraphicsScreen) parentConfig.getScreen();
- AbstractGraphicsDevice parentDevice = (AbstractGraphicsDevice) parentScreen.getDevice();
+ final AbstractGraphicsConfiguration parentConfig = parent.getGraphicsConfiguration();
+ final AbstractGraphicsScreen parentScreen = parentConfig.getScreen();
+ final AbstractGraphicsDevice parentDevice = parentScreen.getDevice();
- DisplayImpl childDisplay = (DisplayImpl) childScreen.getDisplay();
- String parentDisplayName = childDisplay.validateDisplayName(null, parentDevice.getHandle());
- String childDisplayName = childDisplay.getName();
+ final DisplayImpl childDisplay = (DisplayImpl) childScreen.getDisplay();
+ final String parentDisplayName = childDisplay.validateDisplayName(null, parentDevice.getHandle());
+ final String childDisplayName = childDisplay.getName();
if( ! parentDisplayName.equals( childDisplayName ) ) {
return false;
}
@@ -320,23 +364,23 @@ public class NewtFactory {
return true;
}
- public static Screen createCompatibleScreen(NativeWindow parent) {
+ public static Screen createCompatibleScreen(final NativeWindow parent) {
return createCompatibleScreen(parent, null);
}
- public static Screen createCompatibleScreen(NativeWindow parent, Screen childScreen) {
+ public static Screen createCompatibleScreen(final NativeWindow parent, final Screen childScreen) {
// Get parent's NativeWindow details
- AbstractGraphicsConfiguration parentConfig = (AbstractGraphicsConfiguration) parent.getGraphicsConfiguration();
- AbstractGraphicsScreen parentScreen = (AbstractGraphicsScreen) parentConfig.getScreen();
- AbstractGraphicsDevice parentDevice = (AbstractGraphicsDevice) parentScreen.getDevice();
+ final AbstractGraphicsConfiguration parentConfig = parent.getGraphicsConfiguration();
+ final AbstractGraphicsScreen parentScreen = parentConfig.getScreen();
+ final AbstractGraphicsDevice parentDevice = parentScreen.getDevice();
if(null != childScreen) {
// check if child Display/Screen is compatible already
- DisplayImpl childDisplay = (DisplayImpl) childScreen.getDisplay();
- String parentDisplayName = childDisplay.validateDisplayName(null, parentDevice.getHandle());
- String childDisplayName = childDisplay.getName();
- boolean displayEqual = parentDisplayName.equals( childDisplayName );
- boolean screenEqual = parentScreen.getIndex() == childScreen.getIndex();
+ final DisplayImpl childDisplay = (DisplayImpl) childScreen.getDisplay();
+ final String parentDisplayName = childDisplay.validateDisplayName(null, parentDevice.getHandle());
+ final String childDisplayName = childDisplay.getName();
+ final boolean displayEqual = parentDisplayName.equals( childDisplayName );
+ final boolean screenEqual = parentScreen.getIndex() == childScreen.getIndex();
if(DEBUG_IMPLEMENTATION) {
System.err.println("NewtFactory.createCompatibleScreen: Display: "+
parentDisplayName+" =? "+childDisplayName+" : "+displayEqual+"; Screen: "+
@@ -350,7 +394,7 @@ public class NewtFactory {
// Prep NEWT's Display and Screen according to the parent
final String type = NativeWindowFactory.getNativeWindowType(true);
- Display display = NewtFactory.createDisplay(type, parentDevice.getHandle(), true);
+ final Display display = NewtFactory.createDisplay(type, parentDevice.getHandle(), true);
return NewtFactory.createScreen(display, parentScreen.getIndex());
}
}
diff --git a/src/newt/classes/com/jogamp/newt/NewtVersion.java b/src/newt/classes/com/jogamp/newt/NewtVersion.java
index 961ffdf6a..f4cdee487 100644
--- a/src/newt/classes/com/jogamp/newt/NewtVersion.java
+++ b/src/newt/classes/com/jogamp/newt/NewtVersion.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt;
import com.jogamp.common.GlueGenVersion;
@@ -38,7 +38,7 @@ public class NewtVersion extends JogampVersion {
protected static volatile NewtVersion jogampCommonVersionInfo;
- protected NewtVersion(String packageName, Manifest mf) {
+ protected NewtVersion(final String packageName, final Manifest mf) {
super(packageName, mf);
}
@@ -46,16 +46,17 @@ public class NewtVersion extends JogampVersion {
if(null == jogampCommonVersionInfo) { // volatile: ok
synchronized(NewtVersion.class) {
if( null == jogampCommonVersionInfo ) {
- final String packageName = "com.jogamp.newt";
- final Manifest mf = VersionUtil.getManifest(NewtVersion.class.getClassLoader(), packageName);
- jogampCommonVersionInfo = new NewtVersion(packageName, mf);
+ final String packageName1 = "com.jogamp.newt"; // atomic packaging - and identity
+ final String packageName2 = "javax.media.opengl"; // all packaging
+ final Manifest mf = VersionUtil.getManifest(NativeWindowVersion.class.getClassLoader(), new String[]{ packageName1, packageName2 } );
+ jogampCommonVersionInfo = new NewtVersion(packageName1, mf);
}
}
}
return jogampCommonVersionInfo;
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
System.err.println(NativeWindowVersion.getInstance());
diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java
index 26f19ad6b..0ba557972 100644
--- a/src/newt/classes/com/jogamp/newt/Screen.java
+++ b/src/newt/classes/com/jogamp/newt/Screen.java
@@ -27,14 +27,34 @@
*/
package com.jogamp.newt;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorModeListener;
+
import jogamp.newt.Debug;
+
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+/**
+ * A screen may span multiple {@link MonitorDevice}s representing their combined virtual size.
+ * <p>
+ * All values of this interface are represented in pixel units, if not stated otherwise.
+ * </p>
+ *
+ * <a name="coordinateSystem"><h5>Coordinate System</h5></a>
+ * <p>
+ * <ul>
+ * <li>Screen space has it's origin in the top-left corner, and may not be at 0/0.</li>
+ * <li>{@link #getViewport() Virtual viewport} covers all {@link MonitorDevice}s {@link MonitorDevice#getViewport() viewports} and has it's origin in the top-left corner, and may not be at 0/0.</li>
+ * </ul>
+ * </p>
+*/
public abstract class Screen {
/**
@@ -46,20 +66,22 @@ public abstract class Screen {
public static final boolean DEBUG = Debug.debug("Screen");
/** return precomputed hashCode from FQN {@link #getFQName()} */
+ @Override
public abstract int hashCode();
/** return true if obj is of type Display and both FQN {@link #getFQName()} equals */
- public boolean equals(Object obj) {
+ @Override
+ public boolean equals(final Object obj) {
if (this == obj) { return true; }
if (obj instanceof Screen) {
- Screen s = (Screen)obj;
+ final Screen s = (Screen)obj;
return s.getFQName().equals(getFQName());
}
return false;
}
/**
- * Manual trigger the native creation, if it is not done yet..<br>
+ * Manual trigger the native creation, if not done yet..<br>
* This is useful to be able to request the {@link javax.media.nativewindow.AbstractGraphicsScreen}, via
* {@link #getGraphicsScreen()}.<br>
* Otherwise the abstract device won't be available before the dependent component (Window) is realized.
@@ -89,13 +111,14 @@ public abstract class Screen {
public abstract boolean isNativeValid();
/**
- * @return number of references by Window
+ * @return number of references
*/
public abstract int getReferenceCount();
/**
* See {@link Display#addReference()}
*
+ * @return number of references post operation
* @throws NativeWindowException if the native creation failed.
* @see #removeReference()
* @see #setDestroyWhenUnused(boolean)
@@ -106,6 +129,7 @@ public abstract class Screen {
/**
* See {@link Display#removeReference()}
*
+ * @return number of references post operation
* @see #addReference()
* @see #setDestroyWhenUnused(boolean)
* @see #getDestroyWhenUnused()
@@ -120,81 +144,121 @@ public abstract class Screen {
public abstract int getIndex();
/**
- * @return the x position of the virtual top-left origin.
+ * See <a href="#coordinateSystem"> Coordinate System</a>.
+ *
+ * @return the x position of the virtual viewport's top-left origin in pixel units.
*/
public abstract int getX();
-
+
/**
- * @return the y position of the virtual top-left origin.
+ * See <a href="#coordinateSystem"> Coordinate System</a>.
+ *
+ * @return the y position of the virtual viewport's top-left origin in pixel units.
*/
public abstract int getY();
-
+
/**
- * @return the <b>rotated</b> virtual width.
+ * @return the <b>rotated</b> virtual viewport's width in pixel units.
*/
public abstract int getWidth();
/**
- * @return the <b>rotated</b> virtual height.
+ * @return the <b>rotated</b> virtual viewport's height in pixel units.
*/
public abstract int getHeight();
/**
+ * See <a href="#coordinateSystem"> Coordinate System</a>.
+ *
+ * @return the <b>rotated</b> virtual viewport, i.e. top-left origin and size, in pixel units.
+ * @see #getViewportInWindowUnits()
+ */
+ public abstract RectangleImmutable getViewport();
+
+ /**
+ * See <a href="#coordinateSystem"> Coordinate System</a>.
+ *
+ * @return the <b>rotated</b> virtual viewport, i.e. top-left origin and size, in window units.
+ * @see #getViewport()
+ */
+ public abstract RectangleImmutable getViewportInWindowUnits();
+
+ /**
* @return the associated Display
*/
public abstract Display getDisplay();
- /**
- * @return the screen fully qualified Screen name,
+ /**
+ * @return The screen fully qualified Screen name,
* which is a key of {@link com.jogamp.newt.Display#getFQName()} + {@link #getIndex()}.
*/
public abstract String getFQName();
/**
- * @param sml ScreenModeListener to be added for ScreenMode change events
+ * Return a list of all {@link MonitorMode}s for all {@link MonitorDevice}s.
+ * <p>
+ * The list is ordered in descending order,
+ * see {@link MonitorMode#compareTo(MonitorMode)}.
+ * </p>
*/
- public abstract void addScreenModeListener(ScreenModeListener sml);
+ public abstract List<MonitorMode> getMonitorModes();
/**
- * @param sml ScreenModeListener to be removed from ScreenMode change events
+ * Return a list of available {@link MonitorDevice}s.
*/
- public abstract void removeScreenModeListener(ScreenModeListener sml);
+ public abstract List<MonitorDevice> getMonitorDevices();
- /**
- * Return a list of available {@link com.jogamp.newt.ScreenMode ScreenMode}s.
+ /**
+ * Returns the {@link MonitorDevice} with the highest {@link MonitorDevice#getViewportInWindowUnits() viewport}
+ * {@link RectangleImmutable#coverage(RectangleImmutable) coverage} of the given rectangle in window units.
* <p>
- * If {@link com.jogamp.newt.ScreenMode ScreenMode}s are not supported for this
- * native type {@link com.jogamp.newt.Display#getType()}, it returns a list of size one with the current screen size.</p>
- *
- * @return a shallow copy of the internal immutable {@link com.jogamp.newt.ScreenMode ScreenMode}s.
+ * If no coverage is detected the first {@link MonitorDevice} is returned.
+ * </p>
+ * @param r arbitrary rectangle in window units
*/
- public abstract List<ScreenMode> getScreenModes();
+ public final MonitorDevice getMainMonitor(final RectangleImmutable r) {
+ MonitorDevice res = null;
+ float maxCoverage = Float.MIN_VALUE;
+ final List<MonitorDevice> monitors = getMonitorDevices();
+ for(int i=monitors.size()-1; i>=0; i--) {
+ final MonitorDevice monitor = monitors.get(i);
+ final float coverage = monitor.getViewportInWindowUnits().coverage(r);
+ if( coverage > maxCoverage ) {
+ maxCoverage = coverage;
+ res = monitor;
+ }
+ }
+ if( maxCoverage > 0.0f && null != res ) {
+ return res;
+ }
+ return monitors.get(0);
+ }
/**
- * Return the original {@link com.jogamp.newt.ScreenMode}, as used at NEWT initialization.
- * @return original ScreenMode which is element of the list {@link #getScreenModes()}.
+ * Calculates the union of all monitor's {@link MonitorDevice#getViewport() viewport} in pixel- and window units.
+ * <p>
+ * Should be equal to {@link #getX()}, {@link #getY()}, {@link #getWidth()} and {@link #getHeight()},
+ * however, some native toolkits may choose a different virtual screen area.
+ * </p>
+ * @param viewport storage for result in pixel units, maybe null
+ * @param viewportInWindowUnits storage for result in window units, maybe null
*/
- public abstract ScreenMode getOriginalScreenMode();
+ public final void unionOfMonitorViewports(final Rectangle viewport, final Rectangle viewportInWindowUnits) {
+ MonitorDevice.unionOfViewports(viewport, viewportInWindowUnits, getMonitorDevices());
+ }
/**
- * Return the current {@link com.jogamp.newt.ScreenMode}.
- * <p>
- * If {@link com.jogamp.newt.ScreenMode ScreenMode}s are not supported for this
- * native type {@link com.jogamp.newt.Display#getType()}, it returns one with the current screen size. </p>
- *
- * @return current ScreenMode which is element of the list {@link #getScreenModes()}.
+ * @param sml {@link MonitorModeListener} to be added for {@link MonitorEvent}
*/
- public abstract ScreenMode getCurrentScreenMode();
+ public abstract void addMonitorModeListener(MonitorModeListener sml);
/**
- * Set the current {@link com.jogamp.newt.ScreenMode}.
- * @param screenMode to be made current, must be element of the list {@link #getScreenModes()}.
- * @return true if successful, otherwise false
+ * @param sml {@link MonitorModeListener} to be removed from {@link MonitorEvent}
*/
- public abstract boolean setCurrentScreenMode(ScreenMode screenMode);
+ public abstract void removeMonitorModeListener(MonitorModeListener sml);
// Global Screens
- protected static ArrayList<Screen> screenList = new ArrayList<Screen>();
+ protected static final ArrayList<WeakReference<Screen>> screenList = new ArrayList<WeakReference<Screen>>();
protected static int screensActive = 0;
/**
@@ -204,7 +268,7 @@ public abstract class Screen {
* @param fromIndex start index, then increasing until found or end of list *
* @return
*/
- public static Screen getFirstScreenOf(Display display, int idx, int fromIndex) {
+ public static Screen getFirstScreenOf(final Display display, final int idx, final int fromIndex) {
return getScreenOfImpl(display, idx, fromIndex, 1);
}
@@ -215,29 +279,64 @@ public abstract class Screen {
* @param fromIndex start index, then decreasing until found or end of list. -1 is interpreted as size - 1.
* @return
*/
- public static Screen getLastScreenOf(Display display, int idx, int fromIndex) {
+ public static Screen getLastScreenOf(final Display display, final int idx, final int fromIndex) {
return getScreenOfImpl(display, idx, fromIndex, -1);
}
- private static Screen getScreenOfImpl(Display display, int idx, int fromIndex, int incr) {
+ private static Screen getScreenOfImpl(final Display display, final int idx, final int fromIndex, final int incr) {
synchronized(screenList) {
int i = fromIndex >= 0 ? fromIndex : screenList.size() - 1 ;
while( ( incr > 0 ) ? i < screenList.size() : i >= 0 ) {
- Screen screen = (Screen) screenList.get(i);
- if( screen.getDisplay().equals(display) &&
- screen.getIndex() == idx ) {
- return screen;
+ final Screen screen = screenList.get(i).get();
+ if( null == screen ) {
+ // Clear GC'ed dead reference entry!
+ screenList.remove(i);
+ if( incr < 0 ) {
+ // decrease
+ i+=incr;
+ } // else nop - remove shifted subsequent elements to the left
+ } else {
+ if( screen.getDisplay().equals(display) &&
+ screen.getIndex() == idx ) {
+ return screen;
+ }
+ i+=incr;
}
- i+=incr;
}
}
return null;
}
- /** Returns the global display collection */
+
+ protected static void addScreen2List(final Screen screen) {
+ synchronized(screenList) {
+ // GC before add
+ int i=0;
+ while( i < screenList.size() ) {
+ if( null == screenList.get(i).get() ) {
+ screenList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ screenList.add(new WeakReference<Screen>(screen));
+ }
+ }
+
+ /** Returns the global screen collection */
public static Collection<Screen> getAllScreens() {
ArrayList<Screen> list;
synchronized(screenList) {
- list = (ArrayList<Screen>) screenList.clone();
+ list = new ArrayList<Screen>();
+ int i = 0;
+ while( i < screenList.size() ) {
+ final Screen s = screenList.get(i).get();
+ if( null == s ) {
+ screenList.remove(i);
+ } else {
+ list.add( screenList.get(i).get() );
+ i++;
+ }
+ }
}
return list;
}
diff --git a/src/newt/classes/com/jogamp/newt/ScreenMode.java b/src/newt/classes/com/jogamp/newt/ScreenMode.java
deleted file mode 100644
index 1f12217bb..000000000
--- a/src/newt/classes/com/jogamp/newt/ScreenMode.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.newt;
-
-import javax.media.nativewindow.util.DimensionImmutable;
-
-import com.jogamp.newt.util.MonitorMode;
-
-/** Immutable ScreenMode Class, consisting of it's read only components:<br>
- * <ul>
- * <li>{@link com.jogamp.newt.util.MonitorMode}, non rotated values</li>
- * <li><code>rotation</code>, measured counter clockwise (CCW)</li>
- * </ul>
- *
- * <i>Aquire and filter ScreenModes</i><br>
- * <ul>
- * <li>A List of read only ScreenMode's is being returned by {@link com.jogamp.newt.Screen#getScreenModes()}.</li>
- * <li>You may utilize {@link com.jogamp.newt.util.ScreenModeUtil} to filter and select a desired ScreenMode.</li>
- * <li>The current ScreenMode can be obtained via {@link com.jogamp.newt.Screen#getCurrentScreenMode()}.</li>
- * <li>The initial original ScreenMode (at startup) can be obtained via {@link com.jogamp.newt.Screen#getOriginalScreenMode()}.</li>
- * </ul>
- * <br>
- *
- * <i>Changing ScreenModes</i><br>
- * <ul>
- * <li> Use {@link com.jogamp.newt.Screen#setCurrentScreenMode(com.jogamp.newt.ScreenMode)}</li>
- * to change the current ScreenMode of all Screen's referenced via the full qualified name (FQN)
- * {@link com.jogamp.newt.Screen#getFQName()}.</li>
- * <li> When the last FQN referenced Screen closes, the original ScreenMode ({@link com.jogamp.newt.Screen#getOriginalScreenMode()})
- * is restored.</li>
- * </ul>
- * <br>
- * Example for changing the ScreenMode:
- * <pre>
- // determine target refresh rate
- ScreenMode orig = screen.getOriginalScreenMode();
- int freq = orig.getMonitorMode().getRefreshRate();
-
- // target resolution
- Dimension res = new Dimension(800, 600);
-
- // target rotation
- int rot = 0;
-
- // filter available ScreenModes
- List screenModes = screen.getScreenModes();
- screenModes = ScreenModeUtil.filterByRate(screenModes, freq); // get the nearest ones
- screenModes = ScreenModeUtil.filterByRotation(screenModes, rot);
- screenModes = ScreenModeUtil.filterByResolution(screenModes, res); // get the nearest ones
- screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
-
- // pick 1st one ..
- screen.setCurrentScreenMode((ScreenMode) screenModes.get(0));
- * </pre>
- *
- * X11 / AMD just works<br>
- * <br>
- * X11 / NVidia difficulties
- * <pre>
- NVidia RANDR RefreshRate Bug
- If NVidia's 'DynamicTwinView' is enabled, all refresh rates are
- unique, ie consequent numbers starting with the default refresh, ie 50, 51, ..
- The only way to workaround it is to disable 'DynamicTwinView'.
- Read: http://us.download.nvidia.com/XFree86/Linux-x86/260.19.12/README/configtwinview.html
-
- Check to see if 'DynamicTwinView' is enable:
- nvidia-settings -q :0/DynamicTwinview
-
- To disable it (workaround), add the following option to your xorg.conf device section:
- Option "DynamicTwinView" "False"
-
- NVidia RANDR Rotation:
- To enable it, add the following option to your xorg.conf device section:
- Option "RandRRotation" "on"
- * </pre>
- *
- */
-public class ScreenMode {
- /** zero rotation, compared to normal settings */
- public static final int ROTATE_0 = 0;
-
- /** 90 degrees CCW rotation */
- public static final int ROTATE_90 = 90;
-
- /** 180 degrees CCW rotation */
- public static final int ROTATE_180 = 180;
-
- /** 270 degrees CCW rotation */
- public static final int ROTATE_270 = 270;
-
- MonitorMode monitorMode;
- int rotation;
-
- public static boolean isRotationValid(int rotation) {
- return rotation == ScreenMode.ROTATE_0 || rotation == ScreenMode.ROTATE_90 ||
- rotation == ScreenMode.ROTATE_180 || rotation == ScreenMode.ROTATE_270 ;
- }
-
- /**
- * @param monitorMode the monitor mode
- * @param rotation the screen rotation, measured counter clockwise (CCW)
- */
- public ScreenMode(MonitorMode monitorMode, int rotation) {
- if ( !isRotationValid(rotation) ) {
- throw new RuntimeException("invalid rotation: "+rotation);
- }
- this.monitorMode = monitorMode;
- this.rotation = rotation;
- }
-
- /** Returns the unrotated <code>MonitorMode</code> */
- public final MonitorMode getMonitorMode() {
- return monitorMode;
- }
-
- /** Returns the CCW rotation of this mode */
- public final int getRotation() {
- return rotation;
- }
-
- /** Returns the rotated screen width,
- * derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
- * and <code>getRotation()</code>
- */
- public final int getRotatedWidth() {
- return getRotatedWH(true);
- }
-
- /** Returns the rotated screen height,
- * derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
- * and <code>getRotation()</code>
- */
- public final int getRotatedHeight() {
- return getRotatedWH(false);
- }
-
- public final String toString() {
- return "[ " + getMonitorMode() + ", " + rotation + " degr ]";
- }
-
- /**
- * Tests equality of two <code>ScreenMode</code> objects
- * by evaluating equality of it's components:<br>
- * <ul>
- * <li><code>monitorMode</code></li>
- * <li><code>rotation</code></li>
- * </ul>
- * <br>
- */
- public final boolean equals(Object obj) {
- if (this == obj) { return true; }
- if (obj instanceof ScreenMode) {
- ScreenMode sm = (ScreenMode)obj;
- return sm.getMonitorMode().equals(getMonitorMode()) &&
- sm.getRotation() == this.getRotation() ;
- }
- return false;
- }
-
- /**
- * Returns a combined hash code of it's elements:<br>
- * <ul>
- * <li><code>monitorMode</code></li>
- * <li><code>rotation</code></li>
- * </ul>
- */
- public final int hashCode() {
- // 31 * x == (x << 5) - x
- int hash = 31 + getMonitorMode().hashCode();
- hash = ((hash << 5) - hash) + getRotation();
- return hash;
- }
-
- private final int getRotatedWH(boolean width) {
- final DimensionImmutable d = getMonitorMode().getSurfaceSize().getResolution();
- final boolean swap = ScreenMode.ROTATE_90 == rotation || ScreenMode.ROTATE_270 == rotation ;
- if ( ( width && swap ) || ( !width && !swap ) ) {
- return d.getHeight();
- }
- return d.getWidth();
- }
-}
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java
index 78e2abc6e..ec6d767fa 100644
--- a/src/newt/classes/com/jogamp/newt/Window.java
+++ b/src/newt/classes/com/jogamp/newt/Window.java
@@ -28,16 +28,28 @@
package com.jogamp.newt;
+import java.util.List;
+
+import com.jogamp.newt.Display.PointerIcon;
+import com.jogamp.newt.event.GestureHandler;
+import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.MouseListener;
+
import jogamp.newt.Debug;
+import jogamp.newt.WindowImpl;
+
import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.nativewindow.util.SurfaceSize;
/**
* Specifying NEWT's Window functionality:
@@ -50,12 +62,41 @@ import javax.media.nativewindow.WindowClosingProtocol;
* <li>... and more</li>
* </ul>
* <p>
- * One use case is {@link com.jogamp.newt.opengl.GLWindow}, which delegates
- * window operation to an instance of this interface while providing OpenGL
+ * One use case is {@link com.jogamp.newt.opengl.GLWindow}, which delegates
+ * window operation to an instance of this interface while providing OpenGL
* functionality.
* </p>
+ * <p>
+ * All values of this interface are represented in window units, if not stated otherwise.
+ * </p>
+ *
+ * <a name="coordinateSystem"><h5>Coordinate System</h5></a>
+ * <p>
+ * <ul>
+ * <li>Screen space has it's origin in the top-left corner, and may not be at 0/0.</li>
+ * <li>Window origin is in it's top-left corner, see {@link #getX()} and {@link #getY()}. </li>
+ * <li>Window client-area excludes {@link #getInsets() insets}, i.e. window decoration.</li>
+ * <li>Window origin is relative to it's parent window if exist, or the screen position (top-level).</li>
+ * </ul>
+ * See {@link NativeWindow} and {@link Screen}.
+ * </p>
+ * <a name="customwindowicons"><h5>Custom Window Icons</h5></a>
+ * <p>
+ * Custom window icons can be defined via system property <code>newt.window.icons</code>,
+ * which shall contain a space separated list of PNG icon locations from low- to high-resolution.
+ * The location must be resolvable via classpath, i.e. shall reference a location within the jar file.
+ * Example (our default):
+ * <pre>
+ * -Dnewt.window.icons="newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png"
+ * -Djnlp.newt.window.icons="newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png"
+ * </pre>
+ * The property can also be set programmatically, which must happen before any NEWT classes are <i>touched</i>:
+ * <pre>
+ * System.setProperty("newt.window.icons", "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png");
+ * </pre>
+ * </p>
*/
-public interface Window extends NativeWindow, WindowClosingProtocol {
+public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSurface {
public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent");
public static final boolean DEBUG_KEY_EVENT = Debug.debug("Window.KeyEvent");
public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window");
@@ -77,11 +118,20 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
boolean isNativeValid();
/**
- * @return The associated Screen
+ * @return The associated {@link Screen}
*/
Screen getScreen();
/**
+ * Returns the {@link MonitorDevice} with the highest {@link MonitorDevice#getViewportInWindowUnits() viewport}
+ * {@link RectangleImmutable#coverage(RectangleImmutable) coverage} of this window.
+ * <p>
+ * If no coverage is detected the first {@link MonitorDevice} is returned.
+ * </p>
+ */
+ MonitorDevice getMainMonitor();
+
+ /**
* Set the CapabilitiesChooser to help determine the native visual type.
*
* @param chooser the new CapabilitiesChooser
@@ -104,14 +154,26 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
CapabilitiesImmutable getChosenCapabilities();
/**
- * Destroy the Window and it's children, incl. native destruction.<br>
- * The Window can be recreate via {@link #setVisible(boolean) setVisible(true)}.
- * <p>Visibility is set to false.</p>
+ * {@inheritDoc}
+ * <p>
+ * Also iterates through this window's children and destroys them.
+ * </p>
+ * <p>
+ * Visibility is set to false.
+ * </p>
+ * <p>
+ * Method sends out {@link WindowEvent#EVENT_WINDOW_DESTROY_NOTIFY pre-} and
+ * {@link WindowEvent#EVENT_WINDOW_DESTROYED post-} destruction events
+ * to all of it's {@link WindowListener}.
+ * </p>
* <p>
* This method invokes {@link Screen#removeReference()} after it's own destruction,<br>
* which will issue {@link Screen#destroy()} if the reference count becomes 0.<br>
* This destruction sequence shall end up in {@link Display#destroy()}, if all reference counts become 0.
* </p>
+ * <p>
+ * The Window can be recreate via {@link #setVisible(boolean) setVisible(true)}.
+ * </p>
* @see #destroy()
* @see #setVisible(boolean)
*/
@@ -119,17 +181,38 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
void destroy();
/**
- * <code>setVisible</code> makes the window and children visible if <code>visible</code> is true,
+ * Set a custom action handling destruction issued by a {@link WindowImpl#windowDestroyNotify(boolean) toolkit triggered window destroy}
+ * replacing the default {@link #destroy()} action.
+ * <p>
+ * The custom action shall call {@link #destroy()}
+ * but may perform further tasks before and after.
+ * </p>
+ */
+ void setWindowDestroyNotifyAction(Runnable r);
+
+ /**
+ * Calls {@link #setVisible(boolean, boolean) setVisible(true, visible)},
+ * i.e. blocks until the window becomes visible.
+ * @see #setVisible(boolean, boolean)
+ */
+ void setVisible(boolean visible);
+
+ /**
+ * <code>setVisible(..)</code> makes the window and children visible if <code>visible</code> is true,
* otherwise the window and children becomes invisible.
* <p>
- * The <code>setVisible(true)</code> is responsible to actual create the native window.
+ * <code>setVisible(wait, true)</code> is responsible to actual create the native window.
+ * </p>
+ * <p>
+ * If <code>wait</code> is true, method blocks until window is {@link #isVisible() visible} and {@link #isNativeValid() valid},
+ * otherwise method returns immediately.
* </p>
* <p>
* Zero size semantics are respected, see {@link #setSize(int,int)}:<br>
* <pre>
* if ( 0 == windowHandle && visible ) {
* this.visible = visible;
- * if( 0 &lt; width*height ) {
+ * if( 0 &lt; width && 0 &lt; height ) {
* createNative();
* }
* } else if ( this.visible != visible ) {
@@ -139,12 +222,12 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
* </pre></p>
* <p>
* In case this window is a child window and has a {@link javax.media.nativewindow.NativeWindow} parent,<br>
- * <code>setVisible(true)</code> has no effect as long the parent's is not valid yet,
+ * <code>setVisible(wait, true)</code> has no effect as long the parent's is not valid yet,
* i.e. {@link javax.media.nativewindow.NativeWindow#getWindowHandle()} returns <code>null</code>.<br>
- * <code>setVisible(true)</code> shall be repeated when the parent becomes valid.
+ * <code>setVisible(wait, true)</code> shall be repeated when the parent becomes valid.
* </p>
*/
- void setVisible(boolean visible);
+ void setVisible(boolean wait, boolean visible);
boolean isVisible();
@@ -166,14 +249,40 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
//
/**
- * Sets the size of the window's client area, excluding decorations.
+ * Returns a newly created {@link Rectangle} containing window origin, {@link #getX()} & {@link #getY()},
+ * and size, {@link #getWidth()} & {@link #getHeight()}, in window units.
+ */
+ Rectangle getBounds();
+
+ /**
+ * Returns the <i>pixels per millimeter</i> of this window's {@link NativeSurface}
+ * according to the {@link #getMainMonitor() main monitor}'s <i>current</i> {@link MonitorMode mode}'s
+ * {@link SurfaceSize#getResolution() surface resolution}.
+ * <p>
+ * Method takes the {@link #getCurrentSurfaceScale(int[]) current surface-scale} and {@link #getNativeSurfaceScale(int[]) native surface-scale}
+ * into account, i.e.:
+ * <pre>
+ * surfacePpMM = monitorPpMM * currentSurfaceScale / nativeSurfaceScale,
+ * with PpMM == pixel per millimeter
+ * </pre>
+ * </p>
+ * <p>
+ * To convert the result to <i>dpi</i>, i.e. dots-per-inch, multiply both components with <code>25.4f</code>.
+ * </p>
+ * @param ppmmStore float[2] storage for the ppmm result
+ * @return the passed storage containing the ppmm for chaining
+ */
+ float[] getPixelsPerMM(final float[] ppmmStore);
+
+ /**
+ * Sets the size of the window's client area in window units, excluding decorations.
*
* <p>
* Zero size semantics are respected, see {@link #setVisible(boolean)}:<br>
* <pre>
- * if ( 0 != windowHandle && 0 &ge; width*height && visible ) {
+ * if ( visible && 0 != windowHandle && ( 0 &ge; width || 0 &ge; height ) ) {
* setVisible(false);
- * } else if ( 0 == windowHandle && 0 &lt; width*height && visible ) {
+ * } else if ( visible && 0 == windowHandle && 0 &lt; width && 0 &lt; height ) {
* setVisible(true);
* } else {
* // as expected ..
@@ -182,22 +291,54 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
* <p>
* This call is ignored if in fullscreen mode.<br></p>
*
- * @param width of the window's client area
- * @param height of the window's client area
+ * @param width of the window's client area in window units
+ * @param height of the window's client area in window units
*
+ * @see #setSurfaceSize(int, int)
+ * @see #setTopLevelSize(int, int)
* @see #getInsets()
*/
void setSize(int width, int height);
/**
- * Sets the size of the top-level window including insets (window decorations).
+ * Sets the size of the window's surface in pixel units which claims the window's client area excluding decorations.
+ *
+ * <p>
+ * In multiple monitor mode, setting the window's surface size in pixel units
+ * might not be possible due to unknown <i>scale</i> values of the target display.
+ * Hence re-setting the pixel unit size after window creation is recommended.
+ * </p>
+ * <p>
+ * Zero size semantics are respected, see {@link #setVisible(boolean)}:<br>
+ * <pre>
+ * if ( visible && 0 != windowHandle && ( 0 &ge; width || 0 &ge; height ) ) {
+ * setVisible(false);
+ * } else if ( visible && 0 == windowHandle && 0 &lt; width && 0 &lt; height ) {
+ * setVisible(true);
+ * } else {
+ * // as expected ..
+ * }
+ * </pre></p>
+ * <p>
+ * This call is ignored if in fullscreen mode.<br></p>
+ *
+ * @param pixelWidth of the window's client area in pixel units
+ * @param pixelHeight of the window's client area in pixel units
+ *
+ * @see #setSize(int, int)
+ * @see #getInsets()
+ */
+ void setSurfaceSize(int pixelWidth, int pixelHeight);
+
+ /**
+ * Sets the size of the top-level window including insets (window decorations) in window units.
*
* <p>
* Note: Insets (if supported) are available only after the window is set visible and hence has been created.
* </p>
*
- * @param width of the top-level window area
- * @param height of the top-level window area
+ * @param width of the top-level window area in window units
+ * @param height of the top-level window area in window units
*
* @see #setSize(int, int)
* @see #getInsets()
@@ -205,19 +346,19 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
void setTopLevelSize(int width, int height);
/**
- * Sets the location of the window's client area, excluding insets (window decorations).<br>
+ * Sets the location of the window's client area excluding insets (window decorations) in window units.<br>
*
* This call is ignored if in fullscreen mode.<br>
*
- * @param x coord of the client-area's top left corner
- * @param y coord of the client-area's top left corner
+ * @param x coord of the client-area's top left corner in window units
+ * @param y coord of the client-area's top left corner in window units
*
* @see #getInsets()
*/
void setPosition(int x, int y);
/**
- * Sets the location of the top-level window inclusive insets (window decorations).<br>
+ * Sets the location of the top-level window inclusive insets (window decorations) in window units.<br>
*
* <p>
* Note: Insets (if supported) are available only after the window is set visible and hence has been created.
@@ -225,8 +366,8 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
*
* This call is ignored if in fullscreen mode.<br>
*
- * @param x coord of the top-level left corner
- * @param y coord of the top-level left corner
+ * @param x coord of the top-level left corner in window units
+ * @param y coord of the top-level left corner in window units
*
* @see #setPosition(int, int)
* @see #getInsets()
@@ -257,6 +398,20 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
*/
void setPointerVisible(boolean pointerVisible);
+ /**
+ * Returns the current {@link PointerIcon}, which maybe <code>null</code> for the default.
+ * @see #setPointerIcon(PointerIcon)
+ */
+ PointerIcon getPointerIcon();
+
+ /**
+ * @param pi Valid {@link PointerIcon} reference or <code>null</code> to reset the pointer icon to default.
+ *
+ * @see PointerIcon
+ * @see Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int)
+ */
+ void setPointerIcon(final PointerIcon pi);
+
/** @see #confinePointer(boolean) */
boolean isPointerConfined();
@@ -276,10 +431,10 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
void confinePointer(boolean confine);
/**
- * Moves the pointer to x/y relative to this window's origin.
+ * Moves the pointer to x/y relative to this window's origin in pixel units.
*
- * @param x relative pointer x position within this window
- * @param y relative pointer y position within this window
+ * @param x relative pointer x position within this window in pixel units
+ * @param y relative pointer y position within this window in pixel units
*
* @see #confinePointer(boolean)
*/
@@ -303,6 +458,11 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
ACTION_NATIVE_CREATION_PENDING;
}
+ /** Reparenting hint (bitfield value): Force destroy and hence {@link ReparentOperation#ACTION_NATIVE_CREATION re-creating} the window. */
+ public static final int REPARENT_HINT_FORCE_RECREATION = 1 << 0;
+ /** Reparenting hint (bitfield value): Claim window becomes visible after reparenting, which is important for e.g. preserving the GL-states in case window is invisible while reparenting. */
+ public static final int REPARENT_HINT_BECOMES_VISIBLE = 1 << 1;
+
/**
* Change this window's parent window.<br>
* <P>
@@ -312,15 +472,40 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
* this window is added to it's list of children.<br></P>
*
* @param newParent The new parent NativeWindow. If null, this Window becomes a top level window.
+ * @param x new top-level position in window units, use -1 for default position.
+ * @param y new top-level position in window units, use -1 for default position.
+ * @param hints May contain hints (bitfield values) like {@link #REPARENT_HINT_FORCE_RECREATION} or {@link #REPARENT_HINT_BECOMES_VISIBLE}.
*
* @return The issued reparent action type (strategy) as defined in Window.ReparentAction
*/
- ReparentOperation reparentWindow(NativeWindow newParent);
-
- ReparentOperation reparentWindow(NativeWindow newParent, boolean forceDestroyCreate);
+ ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, int hints);
+ /**
+ * Enable or disable fullscreen mode for this window.
+ * <p>
+ * Fullscreen mode is established on the {@link #getMainMonitor() main monitor}.
+ * </p>
+ * @param fullscreen enable or disable fullscreen mode
+ * @return success
+ * @see #setFullscreen(List)
+ * @see #isFullscreen()
+ */
boolean setFullscreen(boolean fullscreen);
+ /**
+ * Enable fullscreen mode for this window spanning across the given {@link MonitorDevice}s
+ * or across all {@link MonitorDevice}s.
+ * <p>
+ * Disable fullscreen via {@link #setFullscreen(boolean)}.
+ * </p>
+ * @param monitors if <code>null</code> fullscreen will be spanned across all {@link MonitorDevice}s,
+ * otherwise across the given list of {@link MonitorDevice}.
+ * @return success
+ * @see #setFullscreen(boolean)
+ * @see #isFullscreen()
+ */
+ boolean setFullscreen(List<MonitorDevice> monitors);
+
boolean isFullscreen();
static interface FocusRunnable {
@@ -345,7 +530,11 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
* Sets a {@link KeyListener} allowing focus traversal with a covered window toolkit like AWT.
* <p>
* The {@link KeyListener} methods are invoked prior to all other {@link KeyListener}'s
- * allowing to suppress the {@link KeyEvent} via the {@link InputEvent#consumedTag}.
+ * allowing to suppress the {@link KeyEvent} via the {@link InputEvent#consumedTag}
+ * and to perform focus traversal with a 3rd party toolkit.
+ * </p>
+ * <p>
+ * The {@link KeyListener} methods are not invoked for {@link KeyEvent#isAutoRepeat() auto-repeat} events.
* </p>
* @param l
*/
@@ -372,8 +561,20 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
*/
void requestFocus(boolean wait);
+ /**
+ * Trigger window repaint while passing the dirty region in pixel units.
+ * @param x dirty-region y-pos in pixel units
+ * @param y dirty-region x-pos in pixel units
+ * @param width dirty-region width in pixel units
+ * @param height dirty-region height in pixel units
+ */
void windowRepaint(int x, int y, int width, int height);
+ /**
+ * Enqueues a {@link com.jogamp.newt.event.NEWTEvent NEWT event}.
+ * @param wait Passing <code>true</code> will block until the event has been processed, otherwise method returns immediately.
+ * @param event The {@link com.jogamp.newt.event.NEWTEvent event} to enqueue.
+ */
void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event);
void runOnEDTIfAvail(boolean wait, final Runnable task);
@@ -383,10 +584,13 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
// WindowListener
//
+ /**
+ * Send a {@link WindowEvent} to all {@link WindowListener}.
+ * @param eventType a {@link WindowEvent} type, e.g. {@link WindowEvent#EVENT_WINDOW_REPAINT}.
+ */
public void sendWindowEvent(int eventType);
/**
- *
* Appends the given {@link com.jogamp.newt.event.WindowListener} to the end of
* the list.
*/
@@ -468,15 +672,12 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
//
/**
- *
- * Appends the given {@link com.jogamp.newt.event.MouseListener} to the end of
- * the list.
+ * Appends the given {@link MouseListener} to the end of the list.
*/
void addMouseListener(MouseListener l);
/**
- *
- * Inserts the given {@link com.jogamp.newt.event.MouseListener} at the
+ * Inserts the given {@link MouseListener} at the
* specified position in the list.<br>
*
* @param index Position where the listener will be inserted.
@@ -487,10 +688,61 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
*/
void addMouseListener(int index, MouseListener l);
+ /**
+ * Removes the given {@link MouseListener} from the list.
+ */
void removeMouseListener(MouseListener l);
+ /**
+ * Returns the {@link MouseListener} from the list at the given index.
+ */
MouseListener getMouseListener(int index);
+ /**
+ * Returns all {@link MouseListener}
+ */
MouseListener[] getMouseListeners();
+ /** Enable or disable default {@link GestureHandler}. Default is enabled. */
+ void setDefaultGesturesEnabled(boolean enable);
+ /** Return true if default {@link GestureHandler} are enabled. */
+ boolean areDefaultGesturesEnabled();
+ /**
+ * Appends the given {@link GestureHandler} to the end of the list.
+ */
+ void addGestureHandler(GestureHandler gh);
+ /**
+ * Inserts the given {@link GestureHandler} at the
+ * specified position in the list.<br>
+ *
+ * @param index Position where the listener will be inserted.
+ * Should be within (0 <= index && index <= size()).
+ * An index value of -1 is interpreted as the end of the list, size().
+ * @param l The listener object to be inserted
+ * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1
+ */
+ void addGestureHandler(int index, GestureHandler gh);
+ /**
+ * Removes the given {@link GestureHandler} from the list.
+ */
+ void removeGestureHandler(GestureHandler gh);
+ /**
+ * Appends the given {@link GestureHandler.GestureListener} to the end of the list.
+ */
+ void addGestureListener(GestureHandler.GestureListener gl);
+ /**
+ * Inserts the given {@link GestureHandler.GestureListener} at the
+ * specified position in the list.<br>
+ *
+ * @param index Position where the listener will be inserted.
+ * Should be within (0 <= index && index <= size()).
+ * An index value of -1 is interpreted as the end of the list, size().
+ * @param l The listener object to be inserted
+ * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1
+ */
+ void addGestureListener(int index, GestureHandler.GestureListener gl);
+ /**
+ * Removes the given {@link GestureHandler.GestureListener} from the list.
+ */
+ void removeGestureListener(GestureHandler.GestureListener gl);
}
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index 89a749c51..c470f6840 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,20 +20,26 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.awt;
+import java.applet.Applet;
import java.awt.AWTKeyStroke;
import java.awt.Canvas;
+import java.awt.Component;
+import java.awt.EventQueue;
import java.awt.Graphics;
+import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.KeyboardFocusManager;
+import java.awt.geom.NoninvertibleTransformException;
+import java.beans.Beans;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Method;
@@ -42,23 +48,33 @@ import java.security.PrivilegedAction;
import java.util.Set;
import javax.media.nativewindow.NativeWindow;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerOption;
-import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.swing.MenuSelectionManager;
import jogamp.nativewindow.awt.AWTMisc;
+import jogamp.nativewindow.jawt.JAWTUtil;
import jogamp.newt.Debug;
+import jogamp.newt.WindowImpl;
import jogamp.newt.awt.NewtFactoryAWT;
import jogamp.newt.awt.event.AWTParentWindowAdapter;
import jogamp.newt.driver.DriverClearFocus;
+import jogamp.opengl.awt.AWTTilePainter;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.nativewindow.awt.JAWTWindow;
import com.jogamp.newt.Display;
import com.jogamp.newt.Window;
-import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.WindowAdapter;
@@ -67,199 +83,265 @@ import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.event.awt.AWTAdapter;
import com.jogamp.newt.event.awt.AWTKeyAdapter;
import com.jogamp.newt.event.awt.AWTMouseAdapter;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.TileRenderer;
/**
* AWT {@link java.awt.Canvas Canvas} containing a NEWT {@link Window} using native parenting.
- *
+ *
* <h5><A NAME="java2dgl">Offscreen Layer Remarks</A></h5>
- *
+ *
* {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
- * maybe called to use an offscreen drawable (FBO or PBuffer) allowing
+ * maybe called to use an offscreen drawable (FBO or PBuffer) allowing
* the underlying JAWT mechanism to composite the image, if supported.
*/
@SuppressWarnings("serial")
-public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption {
+public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption, AWTPrintLifecycle {
public static final boolean DEBUG = Debug.debug("Window");
+ private final Object sync = new Object();
private JAWTWindow jawtWindow = null;
+ private boolean isApplet = false;
private boolean shallUseOffscreenLayer = false;
private Window newtChild = null;
+ private boolean newtChildAttached = false;
private boolean isOnscreen = true;
private WindowClosingMode newtChildCloseOp;
- private AWTAdapter awtAdapter = null;
- private AWTAdapter awtMouseAdapter = null;
- private AWTAdapter awtKeyAdapter = null;
-
- private AWTWindowClosingProtocol awtWindowClosingProtocol =
+ private final AWTParentWindowAdapter awtWinAdapter;
+ private final AWTAdapter awtMouseAdapter;
+ private final AWTAdapter awtKeyAdapter;
+
+ /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */
+ private boolean destroyJAWTPending = false;
+ /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */
+ private boolean skipJAWTDestroy = false;
+
+ /** Safeguard for AWTWindowClosingProtocol and 'removeNotify()' on other thread than AWT-EDT. */
+ private volatile boolean componentAdded = false;
+
+ private final AWTWindowClosingProtocol awtWindowClosingProtocol =
new AWTWindowClosingProtocol(this, new Runnable() {
+ @Override
+ public void run() {
+ if( componentAdded ) {
+ NewtCanvasAWT.this.destroyImpl(false /* removeNotify */, true /* windowClosing */);
+ }
+ }
+ }, new Runnable() {
+ @Override
public void run() {
- NewtCanvasAWT.this.destroy();
+ if( componentAdded && newtChild != null ) {
+ newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+ }
}
- });
+ } );
/**
* Instantiates a NewtCanvas without a NEWT child.<br>
*/
public NewtCanvasAWT() {
super();
+ awtMouseAdapter = new AWTMouseAdapter().addTo(this);
+ awtKeyAdapter = new AWTKeyAdapter().addTo(this);
+ awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
+ awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
}
/**
* Instantiates a NewtCanvas without a NEWT child.<br>
*/
- public NewtCanvasAWT(GraphicsConfiguration gc) {
+ public NewtCanvasAWT(final GraphicsConfiguration gc) {
super(gc);
+ awtMouseAdapter = new AWTMouseAdapter().addTo(this);
+ awtKeyAdapter = new AWTKeyAdapter().addTo(this);
+ awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
+ awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
}
/**
* Instantiates a NewtCanvas with a NEWT child.
*/
- public NewtCanvasAWT(Window child) {
+ public NewtCanvasAWT(final Window child) {
super();
+ awtMouseAdapter = new AWTMouseAdapter().addTo(this);
+ awtKeyAdapter = new AWTKeyAdapter().addTo(this);
+ awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
+ awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
setNEWTChild(child);
}
/**
* Instantiates a NewtCanvas with a NEWT child.
*/
- public NewtCanvasAWT(GraphicsConfiguration gc, Window child) {
+ public NewtCanvasAWT(final GraphicsConfiguration gc, final Window child) {
super(gc);
+ awtMouseAdapter = new AWTMouseAdapter().addTo(this);
+ awtKeyAdapter = new AWTKeyAdapter().addTo(this);
+ awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
+ awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
setNEWTChild(child);
}
-
- public void setShallUseOffscreenLayer(boolean v) {
+
+ @Override
+ public void setShallUseOffscreenLayer(final boolean v) {
shallUseOffscreenLayer = v;
}
-
+
+ @Override
public final boolean getShallUseOffscreenLayer() {
- return shallUseOffscreenLayer;
+ return shallUseOffscreenLayer;
}
-
- public final boolean isOffscreenLayerSurfaceEnabled() {
- return jawtWindow.isOffscreenLayerSurfaceEnabled();
+
+ @Override
+ public final boolean isOffscreenLayerSurfaceEnabled() {
+ final JAWTWindow w = jawtWindow;
+ return null != w && w.isOffscreenLayerSurfaceEnabled();
}
-
- /**
- * Returns true if the AWT component is parented to an {@link java.applet.Applet},
- * otherwise false. This information is valid only after {@link #addNotify()} is issued,
- * ie. before adding the component to the AWT tree and make it visible.
+
+ /**
+ * Returns true if the AWT component is parented to an {@link java.applet.Applet},
+ * otherwise false. This information is valid only after {@link #addNotify()} is issued.
*/
- public boolean isApplet() {
- return jawtWindow.isApplet();
+ public final boolean isApplet() {
+ return isApplet;
}
- boolean isParent() {
- return null!=newtChild && jawtWindow == newtChild.getParent();
+ private final boolean isParent() {
+ final Window nw = newtChild;
+ return null!=nw && jawtWindow == nw.getParent();
}
-
- boolean isFullscreen() {
- return null != newtChild && newtChild.isFullscreen();
+
+ private final boolean isFullscreen() {
+ final Window nw = newtChild;
+ return null != nw && nw.isFullscreen();
}
-
+
class FocusAction implements Window.FocusRunnable {
+ @Override
public boolean run() {
final boolean isParent = isParent();
final boolean isFullscreen = isFullscreen();
if(DEBUG) {
System.err.println("NewtCanvasAWT.FocusAction: "+Display.getThreadName()+", isOnscreen "+isOnscreen+", hasFocus "+hasFocus()+", isParent "+isParent+", isFS "+isFullscreen);
}
- if(isParent && !isFullscreen) {
- // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
- if(!hasFocus()) {
- // Acquire the AWT focus 1st for proper AWT traversal
- NewtCanvasAWT.super.requestFocus();
- }
- if(isOnscreen) {
+ if( isParent && !isFullscreen ) { // must be parent of newtChild _and_ newtChild not fullscreen
+ if( isOnscreen ) {
// Remove the AWT focus in favor of the native NEWT focus
- KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ AWTEDTExecutor.singleton.invoke(false, awtClearGlobalFocusOwner);
+ } else if( !hasFocus() ) {
+ // In offscreen mode we require the focus!
+ // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
+ NewtCanvasAWT.super.requestFocus();
}
}
return false; // NEWT shall proceed requesting the native focus
}
}
- private FocusAction focusAction = new FocusAction();
-
- WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() {
+ private final FocusAction focusAction = new FocusAction();
+
+ private static class ClearFocusOwner implements Runnable {
+ @Override
+ public void run() {
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ }
+ }
+ private static final Runnable awtClearGlobalFocusOwner = new ClearFocusOwner();
+
+ /** Must run on AWT-EDT non-blocking, since it invokes tasks on AWT-EDT w/ waiting otherwise. */
+ private final Runnable awtClearSelectedMenuPath = new Runnable() {
+ @Override
+ public void run() {
+ MenuSelectionManager.defaultManager().clearSelectedPath();
+ }
+ };
+ private final WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() {
@Override
- public void windowGainedFocus(WindowEvent arg0) {
+ public void windowResized(final WindowEvent e) {
+ updateLayoutSize();
+ }
+ @Override
+ public void windowGainedFocus(final WindowEvent arg0) {
if( isParent() && !isFullscreen() ) {
- MenuSelectionManager.defaultManager().clearSelectedPath();
+ AWTEDTExecutor.singleton.invoke(false, awtClearSelectedMenuPath);
}
}
};
class FocusTraversalKeyListener implements KeyListener {
- boolean suppress = false;
-
- public void keyPressed(KeyEvent e) {
+ @Override
+ public void keyPressed(final KeyEvent e) {
if( isParent() && !isFullscreen() ) {
handleKey(e, false);
}
}
- public void keyReleased(KeyEvent e) {
+ @Override
+ public void keyReleased(final KeyEvent e) {
if( isParent() && !isFullscreen() ) {
handleKey(e, true);
}
}
- public void keyTyped(KeyEvent e) {
- if(suppress) {
- e.setAttachment(InputEvent.consumedTag);
- suppress = false; // reset
- }
- }
-
- void handleKey(KeyEvent evt, boolean onRelease) {
+
+ void handleKey(final KeyEvent evt, final boolean onRelease) {
if(null == keyboardFocusManager) {
throw new InternalError("XXX");
}
final AWTKeyStroke ks = AWTKeyStroke.getAWTKeyStroke(evt.getKeyCode(), evt.getModifiers(), onRelease);
+ boolean suppress = false;
if(null != ks) {
- final Set<AWTKeyStroke> fwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
- final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ final Set<AWTKeyStroke> fwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
if(fwdKeys.contains(ks)) {
+ final Component nextFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, true /* forward */);
if(DEBUG) {
- System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner());
+ System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", nextFocus "+nextFocus);
}
// Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
- NewtCanvasAWT.this.transferFocus();
+ nextFocus.requestFocus();
suppress = true;
} else if(bwdKeys.contains(ks)) {
+ final Component prevFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, false /* forward */);
if(DEBUG) {
- System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner());
+ System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", prevFocus "+prevFocus);
}
// Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
- NewtCanvasAWT.this.transferFocusBackward();
+ prevFocus.requestFocus();
suppress = true;
}
}
if(suppress) {
- evt.setAttachment(InputEvent.consumedTag);
+ evt.setConsumed(true);
}
if(DEBUG) {
System.err.println("NewtCanvasAWT.focusKey: XXX: "+ks);
}
}
}
- private final FocusTraversalKeyListener newtFocusTraversalKeyListener = new FocusTraversalKeyListener();
+ private final FocusTraversalKeyListener newtFocusTraversalKeyListener = new FocusTraversalKeyListener();
class FocusPropertyChangeListener implements PropertyChangeListener {
- public void propertyChange(PropertyChangeEvent evt) {
+ @Override
+ public void propertyChange(final PropertyChangeEvent evt) {
final Object oldF = evt.getOldValue();
final Object newF = evt.getNewValue();
final boolean isParent = isParent();
- final boolean isFullscreen = isFullscreen();
+ final boolean isFullscreen = isFullscreen();
if(DEBUG) {
System.err.println("NewtCanvasAWT.FocusProperty: "+evt.getPropertyName()+", src "+evt.getSource()+", "+oldF+" -> "+newF+", isParent "+isParent+", isFS "+isFullscreen);
}
if(isParent && !isFullscreen) {
- if(oldF == NewtCanvasAWT.this && newF == null) {
+ if(newF == NewtCanvasAWT.this) {
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.FocusProperty: AWT focus -> NEWT focus traversal");
+ }
+ requestFocusNEWTChild();
+ } else if(oldF == NewtCanvasAWT.this && newF == null) {
// focus traversal to NEWT - NOP
- if(DEBUG) {
- System.err.println("NewtCanvasAWT.FocusProperty: NEWT focus traversal");
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.FocusProperty: NEWT focus");
}
} else if(null != newF && newF != NewtCanvasAWT.this) {
// focus traversal to another AWT component
- if(DEBUG) {
+ if(DEBUG) {
System.err.println("NewtCanvasAWT.FocusProperty: lost focus - clear focus");
}
if(newtChild.getDelegatedWindow() instanceof DriverClearFocus) {
@@ -267,40 +349,64 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
}
}
}
- }
+ }
}
private final FocusPropertyChangeListener focusPropertyChangeListener = new FocusPropertyChangeListener();
private volatile KeyboardFocusManager keyboardFocusManager = null;
- /**
+ private final void requestFocusNEWTChild() {
+ if(null!=newtChild) {
+ newtChild.setFocusAction(null);
+ if(isOnscreen) {
+ AWTEDTExecutor.singleton.invoke(false, awtClearGlobalFocusOwner);
+ }
+ newtChild.requestFocus();
+ newtChild.setFocusAction(focusAction);
+ }
+ }
+
+ /**
* Sets a new NEWT child, provoking reparenting.
* <p>
* A previously detached <code>newChild</code> will be released to top-level status
- * and made invisible.
+ * and made invisible.
* </p>
* <p>
- * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
- * produced much cleaner visual results.
+ * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
+ * produced much cleaner visual results.
* </p>
- * @return the previous attached newt child.
+ * @return the previous attached newt child.
*/
- public Window setNEWTChild(Window newChild) {
- final Window prevChild = newtChild;
- if(DEBUG) {
- System.err.println("NewtCanvasAWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
- }
- final java.awt.Container cont = AWTMisc.getContainer(this);
- // remove old one
- if(null != newtChild) {
- reparentWindow( false, cont );
- newtChild = null;
+ public Window setNEWTChild(final Window newChild) {
+ synchronized(sync) {
+ final Window prevChild = newtChild;
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
+ }
+ final java.awt.Container cont = AWTMisc.getContainer(this);
+ // remove old one
+ if(null != newtChild) {
+ detachNewtChild( cont );
+ newtChild = null;
+ }
+ // add new one, reparent only if ready
+ newtChild = newChild;
+
+ updateLayoutSize();
+ // will be done later at paint/display/..: attachNewtChild(cont);
+
+ return prevChild;
}
- // add new one, reparent only if ready
- newtChild = newChild;
- if( isDisplayable() && null != newChild) {
- reparentWindow( true, cont );
+ }
+
+ private final void updateLayoutSize() {
+ final Window w = newtChild;
+ if( null != w ) {
+ // use NEWT child's size for min/pref size!
+ final java.awt.Dimension minSize = new java.awt.Dimension(w.getWidth(), w.getHeight());
+ setMinimumSize(minSize);
+ setPreferredSize(minSize);
}
- return prevChild;
}
/** @return the current NEWT child */
@@ -311,158 +417,92 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
/** @return this AWT Canvas NativeWindow representation, may be null in case {@link #removeNotify()} has been called,
* or {@link #addNotify()} hasn't been called yet.*/
public NativeWindow getNativeWindow() { return jawtWindow; }
-
+
+ @Override
public WindowClosingMode getDefaultCloseOperation() {
return awtWindowClosingProtocol.getDefaultCloseOperation();
}
- public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
+ @Override
+ public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
return awtWindowClosingProtocol.setDefaultCloseOperation(op);
}
- /* package */ void configureNewtChild(boolean attach) {
- if(null!=awtAdapter) {
- awtAdapter.removeFrom(this);
- awtAdapter=null;
- }
- if(null!=awtMouseAdapter) {
- awtMouseAdapter.removeFrom(this);
- awtMouseAdapter = null;
- }
- if(null!=awtKeyAdapter) {
- awtKeyAdapter.removeFrom(this);
- awtKeyAdapter = null;
- }
- if(null != keyboardFocusManager) {
- keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener);
- keyboardFocusManager = null;
- }
-
- if( null != newtChild ) {
- newtChild.setKeyboardFocusHandler(null);
- if(attach) {
- if(null == jawtWindow.getGraphicsConfiguration()) {
- throw new InternalError("XXX");
- }
- isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
- awtAdapter = new AWTParentWindowAdapter(jawtWindow, newtChild).addTo(this);
- newtChild.addWindowListener(clearAWTMenusOnNewtFocus);
- newtChild.setFocusAction(focusAction); // enable AWT focus traversal
- newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
- awtWindowClosingProtocol.addClosingListenerOneShot();
- keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
- keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener);
- if(isOnscreen) {
- // onscreen newt child needs to fwd AWT focus
- newtChild.setKeyboardFocusHandler(newtFocusTraversalKeyListener);
- } else {
- // offscreen newt child requires AWT to fwd AWT key/mouse event
- awtMouseAdapter = new AWTMouseAdapter(newtChild).addTo(this);
- awtKeyAdapter = new AWTKeyAdapter(newtChild).addTo(this);
- }
- } else {
- newtChild.removeWindowListener(clearAWTMenusOnNewtFocus);
- newtChild.setFocusAction(null);
- newtChild.setDefaultCloseOperation(newtChildCloseOp);
- awtWindowClosingProtocol.removeClosingListener();
- }
+ /**
+ * Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy().
+ * <p>
+ * <code>skipJAWTDestroy</code> defaults to <code>false</code>.
+ * Due to above IcedTea-Web issue the <code>Applet</code> code needs to avoid JAWT destruction before
+ * <code>Applet.destroy()</code> is reached by setting <code>skipJAWTDestroy</code> to <code>true</code>.
+ * Afterwards the value should be reset to <code>false</code> and {@link #destroy()} needs to be called,
+ * which finally will perform the pending JAWT destruction.
+ * </p>
+ */
+ public final void setSkipJAWTDestroy(final boolean v) { skipJAWTDestroy = v; }
+ /** See {@link #setSkipJAWTDestroy(boolean)}. */
+ public final boolean getSkipJAWTDestroy() { return skipJAWTDestroy; }
+
+ private final void determineIfApplet() {
+ isApplet = false;
+ Component c = this;
+ while(!isApplet && null != c) {
+ isApplet = c instanceof Applet;
+ c = c.getParent();
}
}
@Override
public void addNotify() {
-
- // before native peer is valid: X11
- disableBackgroundErase();
-
- // creates the native peer
- super.addNotify();
-
- // after native peer is valid: Windows
- disableBackgroundErase();
-
- java.awt.Container cont = AWTMisc.getContainer(this);
- if(DEBUG) {
- // if ( isShowing() == false ) -> Container was not visible yet.
- // if ( isShowing() == true ) -> Container is already visible.
- System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+
- ", displayable "+isDisplayable()+" -> "+cont);
+ if( Beans.isDesignTime() ) {
+ super.addNotify();
+ } else {
+ // before native peer is valid: X11
+ disableBackgroundErase();
+
+ // creates the native peer
+ super.addNotify();
+
+ // after native peer is valid: Windows
+ disableBackgroundErase();
+
+ synchronized(sync) {
+ determineIfApplet();
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.addNotify.0 - isApplet "+isApplet+", addedOnAWTEDT "+EventQueue.isDispatchThread()+" @ "+currentThreadName());
+ Thread.dumpStack();
+ }
+ jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, null != newtChild ? newtChild.getRequestedCapabilities() : null);
+ jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
+ awtWindowClosingProtocol.addClosingListener();
+ componentAdded = true; // Bug 910
+ if(DEBUG) {
+ // if ( isShowing() == false ) -> Container was not visible yet.
+ // if ( isShowing() == true ) -> Container is already visible.
+ System.err.println("NewtCanvasAWT.addNotify.X: twin "+newtWinHandleToHexString(newtChild)+
+ ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+
+ ", displayable "+isDisplayable()+", cont "+AWTMisc.getContainer(this));
+ }
+ }
}
- reparentWindow(true, cont);
}
@Override
public void removeNotify() {
- java.awt.Container cont = AWTMisc.getContainer(this);
- if(DEBUG) {
- System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont);
- }
- final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(newtChild, true);
- if(null != ols && ols.isSurfaceLayerAttached()) {
- ols.detachSurfaceLayer();
- }
- reparentWindow(false, cont);
-
- if(null != jawtWindow) {
- NewtFactoryAWT.destroyNativeWindow(jawtWindow);
- jawtWindow=null;
+ if( Beans.isDesignTime() ) {
+ super.removeNotify();
+ } else {
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.removeNotify.0 - isApplet "+isApplet+" @ "+currentThreadName());
+ Thread.dumpStack();
+ }
+ componentAdded = false; // Bug 910
+ awtWindowClosingProtocol.removeClosingListener();
+ destroyImpl(true /* removeNotify */, false /* windowClosing */);
+ super.removeNotify();
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.removeNotify.X @ "+currentThreadName());
+ }
}
-
- super.removeNotify();
- }
-
- void reparentWindow(boolean add, java.awt.Container cont) {
- if(null==newtChild) {
- return; // nop
- }
- if(DEBUG) {
- System.err.println("NewtCanvasAWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
- }
-
- newtChild.setFocusAction(null); // no AWT focus traversal ..
- if(add) {
- if(DEBUG) {
- System.err.println("NewtCanvasAWT.reparentWindow: newtChild: "+newtChild);
- }
- if(null == jawtWindow) {
- jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities());
- jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
- }
- final int w;
- final int h;
- if(isPreferredSizeSet()) {
- java.awt.Dimension d = getPreferredSize();
- w = d.width;
- h = d.height;
- } else {
- final java.awt.Dimension min;
- if(this.isMinimumSizeSet()) {
- min = getMinimumSize();
- } else {
- min = new java.awt.Dimension(0, 0);
- }
- java.awt.Insets ins = cont.getInsets();
- w = Math.max(min.width, cont.getWidth() - ins.left - ins.right);
- h = Math.max(min.height, cont.getHeight() - ins.top - ins.bottom);
- }
- setSize(w, h);
- newtChild.setSize(w, h);
- newtChild.reparentWindow(jawtWindow);
- newtChild.setVisible(true);
- configureNewtChild(true);
- newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
-
- // force this AWT Canvas to be focus-able,
- // since this it is completely covered by the newtChild (z-order).
- setFocusable(true);
- } else {
- configureNewtChild(false);
- newtChild.setVisible(false);
- newtChild.reparentWindow(null);
- }
- if(DEBUG) {
- System.err.println("NewtCanvasAWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
- }
}
/**
@@ -472,88 +512,438 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
* <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
* <li> Issues <code>destroy()</code> on the NEWT Child</li>
* <li> Remove reference to the NEWT Child</li>
- * <li> Remove this Canvas from it's parent.</li>
* </ul>
* @see Window#destroy()
*/
public final void destroy() {
- if(null!=newtChild) {
- java.awt.Container cont = AWTMisc.getContainer(this);
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.destroy() @ "+currentThreadName());
+ Thread.dumpStack();
+ }
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ @Override
+ public void run() {
+ destroyImpl(false /* removeNotify */, false /* windowClosing */);
+ } } );
+ }
+
+ private final void destroyImpl(final boolean removeNotify, final boolean windowClosing) {
+ synchronized(sync) {
+ final java.awt.Container cont = AWTMisc.getContainer(this);
if(DEBUG) {
- System.err.println("NewtCanvasAWT.destroy(): "+newtChild+", from "+cont);
+ System.err.println("NewtCanvasAWT.destroyImpl @ "+currentThreadName());
+ System.err.println("NewtCanvasAWT.destroyImpl.0 - isApplet "+isApplet+", isOnAWTEDT "+EventQueue.isDispatchThread()+", skipJAWTDestroy "+skipJAWTDestroy+
+ "; removeNotify "+removeNotify+", windowClosing "+windowClosing+", destroyJAWTPending "+destroyJAWTPending+
+ ", hasJAWT "+(null!=jawtWindow)+", hasNEWT "+(null!=newtChild)+
+ "): nw "+newtWinHandleToHexString(newtChild)+", from "+cont);
}
- configureNewtChild(false);
- if(null!=jawtWindow) {
- NewtFactoryAWT.destroyNativeWindow(jawtWindow);
- jawtWindow=null;
+ if( null !=newtChild ) {
+ detachNewtChild(cont);
+
+ if( !removeNotify ) {
+ final Window cWin = newtChild;
+ final Window dWin = cWin.getDelegatedWindow();
+ newtChild=null;
+ if( windowClosing && dWin instanceof WindowImpl ) {
+ ((WindowImpl)dWin).windowDestroyNotify(true);
+ } else {
+ cWin.destroy();
+ }
+ }
}
- newtChild.setVisible(false);
- newtChild.reparentWindow(null);
- newtChild.destroy();
- newtChild=null;
- if(null!=cont) {
- cont.remove(this);
+ if( ( destroyJAWTPending || removeNotify || windowClosing ) && null!=jawtWindow ) {
+ if( skipJAWTDestroy ) {
+ // Bug 910 - See setSkipJAWTDestroy(boolean)
+ destroyJAWTPending = true;
+ } else {
+ NewtFactoryAWT.destroyNativeWindow(jawtWindow);
+ jawtWindow=null;
+ destroyJAWTPending = false;
+ }
}
}
- }
+ }
@Override
- public void paint(Graphics g) {
- awtWindowClosingProtocol.addClosingListenerOneShot();
- if(null!=newtChild) {
- newtChild.windowRepaint(0, 0, getWidth(), getHeight());
+ public void paint(final Graphics g) {
+ synchronized(sync) {
+ if( validateComponent(true) && !printActive ) {
+ newtChild.windowRepaint(0, 0, getWidth(), getHeight());
+ }
}
}
@Override
- public void update(Graphics g) {
- awtWindowClosingProtocol.addClosingListenerOneShot();
- if(null!=newtChild) {
- newtChild.windowRepaint(0, 0, getWidth(), getHeight());
- }
+ public void update(final Graphics g) {
+ paint(g);
}
- private final void requestFocusNEWTChild() {
- if(null!=newtChild) {
- newtChild.setFocusAction(null);
- if(isOnscreen) {
- KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ @SuppressWarnings("deprecation")
+ @Override
+ public void reshape(final int x, final int y, final int width, final int height) {
+ synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape
+ synchronized(sync) {
+ super.reshape(x, y, width, height);
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.reshape: "+x+"/"+y+" "+width+"x"+height);
+ }
+ if( validateComponent(true) ) {
+ // newtChild.setSize(width, height);
+ }
}
- newtChild.requestFocus();
- newtChild.setFocusAction(focusAction);
}
}
+ private volatile boolean printActive = false;
+ private GLAnimatorControl printAnimator = null;
+ private GLAutoDrawable printGLAD = null;
+ private AWTTilePainter printAWTTiles = null;
+
+ private final GLAutoDrawable getGLAD() {
+ if( null != newtChild && newtChild instanceof GLAutoDrawable ) {
+ return (GLAutoDrawable)newtChild;
+ }
+ return null;
+ }
+
@Override
- public void requestFocus() {
- super.requestFocus();
- requestFocusNEWTChild();
+ public void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight) {
+ printActive = true;
+ final int componentCount = isOpaque() ? 3 : 4;
+ final TileRenderer printRenderer = new TileRenderer();
+ printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
}
+ private final Runnable setupPrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ synchronized(sync) {
+ if( !validateComponent(true) ) {
+ if(DEBUG) {
+ System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable not valid yet");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ if( !isVisible() ) {
+ if(DEBUG) {
+ System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, canvas not visible");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ final GLAutoDrawable glad = getGLAD();
+ if( null == glad ) {
+ if( DEBUG ) {
+ System.err.println("AWT print.setup exit, newtChild not a GLAutoDrawable: "+newtChild);
+ }
+ printActive = false;
+ return;
+ }
+ printAnimator = glad.getAnimator();
+ if( null != printAnimator ) {
+ printAnimator.remove(glad);
+ }
+ printGLAD = glad; // _not_ default, shall be replaced by offscreen GLAD
+ final GLCapabilitiesImmutable gladCaps = glad.getChosenGLCapabilities();
+ final int printNumSamples = printAWTTiles.getNumSamples(gladCaps);
+ GLDrawable printDrawable = printGLAD.getDelegatedDrawable();
+ final boolean reqNewGLADSamples = printNumSamples != gladCaps.getNumSamples();
+ final boolean reqNewGLADSize = printAWTTiles.customTileWidth != -1 && printAWTTiles.customTileWidth != printDrawable.getSurfaceWidth() ||
+ printAWTTiles.customTileHeight != -1 && printAWTTiles.customTileHeight != printDrawable.getSurfaceHeight();
+ final boolean reqNewGLADOnscrn = gladCaps.isOnscreen();
+
+ final GLCapabilities newGLADCaps = (GLCapabilities)gladCaps.cloneMutable();
+ newGLADCaps.setDoubleBuffered(false);
+ newGLADCaps.setOnscreen(false);
+ if( printNumSamples != newGLADCaps.getNumSamples() ) {
+ newGLADCaps.setSampleBuffers(0 < printNumSamples);
+ newGLADCaps.setNumSamples(printNumSamples);
+ }
+ final boolean reqNewGLADSafe = GLDrawableUtil.isSwapGLContextSafe(glad.getRequestedGLCapabilities(), gladCaps, newGLADCaps);
+
+ final boolean reqNewGLAD = ( reqNewGLADOnscrn || reqNewGLADSamples || reqNewGLADSize ) && reqNewGLADSafe;
+
+ if( DEBUG ) {
+ System.err.println("AWT print.setup: reqNewGLAD "+reqNewGLAD+"[ onscreen "+reqNewGLADOnscrn+", samples "+reqNewGLADSamples+", size "+reqNewGLADSize+", safe "+reqNewGLADSafe+"], "+
+ ", drawableSize "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+
+ ", customTileSize "+printAWTTiles.customTileWidth+"x"+printAWTTiles.customTileHeight+
+ ", scaleMat "+printAWTTiles.scaleMatX+" x "+printAWTTiles.scaleMatY+
+ ", numSamples "+printAWTTiles.customNumSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
+ }
+ if( reqNewGLAD ) {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(newGLADCaps.getGLProfile());
+ GLOffscreenAutoDrawable offGLAD = null;
+ try {
+ offGLAD = factory.createOffscreenAutoDrawable(null, newGLADCaps, null,
+ printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
+ printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
+ } catch (final GLException gle) {
+ if( DEBUG ) {
+ System.err.println("Caught: "+gle.getMessage());
+ gle.printStackTrace();
+ }
+ }
+ if( null != offGLAD ) {
+ printGLAD = offGLAD;
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glad, printGLAD);
+ printDrawable = printGLAD.getDelegatedDrawable();
+ }
+ }
+ printAWTTiles.setGLOrientation(printGLAD.isGLOriented(), printGLAD.isGLOriented());
+ printAWTTiles.renderer.setTileSize(printDrawable.getSurfaceWidth(), printDrawable.getSurfaceHeight(), 0);
+ printAWTTiles.renderer.attachAutoDrawable(printGLAD);
+ if( DEBUG ) {
+ System.err.println("AWT print.setup "+printAWTTiles);
+ System.err.println("AWT print.setup AA "+printNumSamples+", "+newGLADCaps);
+ System.err.println("AWT print.setup printGLAD: "+printGLAD.getSurfaceWidth()+"x"+printGLAD.getSurfaceHeight()+", "+printGLAD);
+ System.err.println("AWT print.setup printDraw: "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+", "+printDrawable);
+ }
+ }
+ }
+ };
@Override
- public boolean requestFocus(boolean temporary) {
- final boolean res = super.requestFocus(temporary);
- if(res) {
- requestFocusNEWTChild();
+ public void releasePrint() {
+ if( !printActive || null == printGLAD ) {
+ throw new IllegalStateException("setupPrint() not called");
}
- return res;
+ // sendReshape = false; // clear reshape flag
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, releasePrintOnEDT);
+ newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
}
+ private final Runnable releasePrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ synchronized(sync) {
+ if( DEBUG ) {
+ System.err.println("AWT print.release "+printAWTTiles);
+ }
+ final GLAutoDrawable glad = getGLAD();
+ printAWTTiles.dispose();
+ printAWTTiles= null;
+ if( printGLAD != glad ) {
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, glad);
+ printGLAD.destroy();
+ }
+ printGLAD = null;
+ if( null != printAnimator ) {
+ printAnimator.add(glad);
+ printAnimator = null;
+ }
+ printActive = false;
+ }
+ }
+ };
@Override
- public boolean requestFocusInWindow() {
- final boolean res = super.requestFocusInWindow();
- if(res) {
- requestFocusNEWTChild();
+ public void print(final Graphics graphics) {
+ synchronized(sync) {
+ if( !printActive || null == printGLAD ) {
+ throw new IllegalStateException("setupPrint() not called");
+ }
+ if(DEBUG && !EventQueue.isDispatchThread()) {
+ System.err.println(currentThreadName()+": Warning: GLCanvas print - not called from AWT-EDT");
+ // we cannot dispatch print on AWT-EDT due to printing internal locking ..
+ }
+
+ final Graphics2D g2d = (Graphics2D)graphics;
+ try {
+ printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
+ final TileRenderer tileRenderer = printAWTTiles.renderer;
+ if( DEBUG ) {
+ System.err.println("AWT print.0: "+tileRenderer);
+ }
+ if( !tileRenderer.eot() ) {
+ try {
+ do {
+ tileRenderer.display();
+ } while ( !tileRenderer.eot() );
+ if( DEBUG ) {
+ System.err.println("AWT print.1: "+printAWTTiles);
+ }
+ tileRenderer.reset();
+ } finally {
+ printAWTTiles.resetGraphics2D();
+ }
+ }
+ } catch (final NoninvertibleTransformException nte) {
+ System.err.println("Caught: Inversion failed of: "+g2d.getTransform());
+ nte.printStackTrace();
+ }
+ if( DEBUG ) {
+ System.err.println("AWT print.X: "+printAWTTiles);
+ }
}
- return res;
}
- @Override
- public boolean requestFocusInWindow(boolean temporary) {
- final boolean res = super.requestFocusInWindow(temporary);
- if(res) {
- requestFocusNEWTChild();
+ private final boolean validateComponent(final boolean attachNewtChild) {
+ if( Beans.isDesignTime() || !isDisplayable() ) {
+ return false;
+ }
+ if ( null == newtChild || null == jawtWindow ) {
+ return false;
+ }
+ if( 0 >= getWidth() || 0 >= getHeight() ) {
+ return false;
+ }
+
+ if( attachNewtChild && !newtChildAttached && null != newtChild ) {
+ attachNewtChild();
}
- return res;
+
+ return true;
+ }
+
+ private final void configureNewtChild(final boolean attach) {
+ awtWinAdapter.clear();
+ awtKeyAdapter.clear();
+ awtMouseAdapter.clear();
+
+ if(null != keyboardFocusManager) {
+ keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener);
+ keyboardFocusManager = null;
+ }
+
+ if( null != newtChild ) {
+ newtChild.setKeyboardFocusHandler(null);
+ if(attach) {
+ if(null == jawtWindow.getGraphicsConfiguration()) {
+ throw new InternalError("XXX");
+ }
+ isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
+ awtWinAdapter.setDownstream(jawtWindow, newtChild);
+ newtChild.addWindowListener(clearAWTMenusOnNewtFocus);
+ newtChild.setFocusAction(focusAction); // enable AWT focus traversal
+ newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
+ keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener);
+ // force this AWT Canvas to be focus-able,
+ // since this it is completely covered by the newtChild (z-order).
+ setFocusable(true);
+ if(isOnscreen) {
+ // onscreen newt child needs to fwd AWT focus
+ newtChild.setKeyboardFocusHandler(newtFocusTraversalKeyListener);
+ } else {
+ // offscreen newt child requires AWT to fwd AWT key/mouse event
+ awtMouseAdapter.setDownstream(newtChild);
+ // We cannot consume AWT mouse click, since it would disable focus via mouse click!
+ // awtMouseAdapter.setConsumeAWTEvent(true);
+ awtKeyAdapter.setDownstream(newtChild);
+ // We manually transfer the focus via NEWT KeyListener, hence we can mark AWT keys as consumed!
+ awtKeyAdapter.setConsumeAWTEvent(true);
+ }
+ } else {
+ newtChild.removeWindowListener(clearAWTMenusOnNewtFocus);
+ newtChild.setFocusAction(null);
+ newtChild.setDefaultCloseOperation(newtChildCloseOp);
+ setFocusable(false);
+ }
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if Key and Mouse input events will be passed through AWT,
+ * otherwise only the {@link #getNEWTChild() NEWT child} will receive them.
+ * <p>
+ * Normally only the {@link #getNEWTChild() NEWT child} will receive Key and Mouse input events.
+ * In offscreen mode, e.g. OSX/CALayer, the AWT events will be received and translated into NEWT events
+ * and delivered to the NEWT child window.<br/>
+ * Note: AWT key events will {@link java.awt.event.InputEvent#consume() consumed} in pass-through mode.
+ * </p>
+ */
+ public final boolean isAWTEventPassThrough() {
+ return !isOnscreen;
+ }
+
+ private final void attachNewtChild() {
+ if( null == newtChild || null == jawtWindow || newtChildAttached ) {
+ return; // nop
+ }
+ if(DEBUG) {
+ // if ( isShowing() == false ) -> Container was not visible yet.
+ // if ( isShowing() == true ) -> Container is already visible.
+ System.err.println("NewtCanvasAWT.attachNewtChild.0 @ "+currentThreadName());
+ System.err.println("\twin "+newtWinHandleToHexString(newtChild)+
+ ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
+ ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+
+ ", cont "+AWTMisc.getContainer(this));
+ }
+
+ newtChildAttached = true;
+ newtChild.setFocusAction(null); // no AWT focus traversal ..
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.attachNewtChild.1: newtChild: "+newtChild);
+ }
+ final int w = getWidth();
+ final int h = getHeight();
+ final boolean isNValid = newtChild.isNativeValid();
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h+", isNValid "+isNValid);
+ }
+ newtChild.setVisible(false);
+ newtChild.setSize(w, h);
+ final int[] reqSurfaceScale = new int[2];
+ if( isNValid ) {
+ newtChild.getCurrentSurfaceScale(reqSurfaceScale);
+ } else {
+ newtChild.getRequestedSurfaceScale(reqSurfaceScale);
+ }
+ jawtWindow.setSurfaceScale(reqSurfaceScale);
+ newtChild.reparentWindow(jawtWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
+ newtChild.addSurfaceUpdatedListener(jawtWindow);
+ if( jawtWindow.isOffscreenLayerSurfaceEnabled() &&
+ 0 != ( JAWTUtil.JAWT_OSX_CALAYER_QUIRK_POSITION & JAWTUtil.getOSXCALayerQuirks() ) ) {
+ AWTEDTExecutor.singleton.invoke(false, forceRelayout);
+ }
+ newtChild.setVisible(true);
+ configureNewtChild(true);
+ newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
+
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.attachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
+ }
+ }
+ private final Runnable forceRelayout = new Runnable() {
+ @Override
+ public void run() {
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.forceRelayout.0");
+ }
+ // Hack to force proper native AWT layout incl. CALayer components on OSX
+ final java.awt.Component component = NewtCanvasAWT.this;
+ final int cW = component.getWidth();
+ final int cH = component.getHeight();
+ component.setSize(cW+1, cH+1);
+ component.setSize(cW, cH);
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.forceRelayout.X");
+ }
+ } };
+
+ private final void detachNewtChild(final java.awt.Container cont) {
+ if( null == newtChild || null == jawtWindow || !newtChildAttached ) {
+ return; // nop
+ }
+ if(DEBUG) {
+ // if ( isShowing() == false ) -> Container was not visible yet.
+ // if ( isShowing() == true ) -> Container is already visible.
+ System.err.println("NewtCanvasAWT.detachNewtChild.0: win "+newtWinHandleToHexString(newtChild)+
+ ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
+ ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+
+ ", cont "+cont);
+ }
+
+ newtChild.removeSurfaceUpdatedListener(jawtWindow);
+ newtChildAttached = false;
+ newtChild.setFocusAction(null); // no AWT focus traversal ..
+ configureNewtChild(false);
+ newtChild.setVisible(false);
+
+ newtChild.reparentWindow(null, -1, -1, 0 /* hint */); // will destroy context (offscreen -> onscreen) and implicit detachSurfaceLayer
+
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.detachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
+ }
}
// Disables the AWT's erasing of this Canvas's background on Windows
@@ -567,6 +957,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
if (!disableBackgroundEraseInitialized) {
try {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
try {
Class<?> clazz = getToolkit().getClass();
@@ -576,16 +967,16 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
clazz.getDeclaredMethod("disableBackgroundErase",
new Class[] { Canvas.class });
disableBackgroundEraseMethod.setAccessible(true);
- } catch (Exception e) {
+ } catch (final Exception e) {
clazz = clazz.getSuperclass();
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
}
return null;
}
});
- } catch (Exception e) {
+ } catch (final Exception e) {
}
disableBackgroundEraseInitialized = true;
if(DEBUG) {
@@ -597,7 +988,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
Throwable t=null;
try {
disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this });
- } catch (Exception e) {
+ } catch (final Exception e) {
t = e;
}
if(DEBUG) {
@@ -605,11 +996,13 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
}
}
}
-
- static String newtWinHandleToHexString(Window w) {
+
+ protected static String currentThreadName() { return "["+Thread.currentThread().getName()+", isAWT-EDT "+EventQueue.isDispatchThread()+"]"; }
+
+ static String newtWinHandleToHexString(final Window w) {
return null != w ? toHexString(w.getWindowHandle()) : "nil";
}
- static String toHexString(long l) {
+ static String toHexString(final long l) {
return "0x"+Long.toHexString(l);
}
}
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
index d06aca039..72b3e43f3 100755..100644
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
@@ -32,9 +32,11 @@ import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Component;
import java.awt.Container;
+import java.awt.EventQueue;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
+import java.util.Arrays;
import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
import javax.media.opengl.FPSCounter;
@@ -42,15 +44,19 @@ import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import com.jogamp.common.util.awt.AWTEDTExecutor;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.applet.JOGLNewtAppletBase;
-/**
+/**
* Simple GLEventListener deployment as an applet using JOGL. This demo must be
* referenced from a web page via an &lt;applet&gt; tag.
- *
+ *
* <p>
- * Example of an applet tag using GearsES2 within the applet area (normal case):
+ * Example of an applet tag using GearsES2 within the applet area (normal case):
* <pre>
&lt;applet width=100 height=100&gt;
&lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
@@ -63,9 +69,9 @@ import com.jogamp.newt.opengl.GLWindow;
&lt;/applet&gt;Hello Gears !
* </pre>
* </p>
- *
+ *
* <p>
- * Example of an applet tag using GearsES2 in an undecorated, translucent, closeable and always-on-top window:
+ * Example of an applet tag using GearsES2 in an undecorated, translucent, closeable and always-on-top window:
* <pre>
&lt;applet width=1 height=1&gt;
&lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
@@ -93,22 +99,19 @@ import com.jogamp.newt.opengl.GLWindow;
@SuppressWarnings("serial")
public class JOGLNewtApplet1Run extends Applet {
public static final boolean DEBUG = JOGLNewtAppletBase.DEBUG;
-
- GLWindow glWindow;
- NewtCanvasAWT newtCanvasAWT;
- JOGLNewtAppletBase base;
+
+ GLWindow glWindow = null;
+ NewtCanvasAWT newtCanvasAWT = null;
+ JOGLNewtAppletBase base = null;
/** if valid glStandalone:=true (own window) ! */
- int glXd=Integer.MAX_VALUE, glYd=Integer.MAX_VALUE, glWidth=Integer.MAX_VALUE, glHeight=Integer.MAX_VALUE;
- boolean glStandalone = false;
+ int glXd=Integer.MAX_VALUE, glYd=Integer.MAX_VALUE, glWidth=Integer.MAX_VALUE, glHeight=Integer.MAX_VALUE;
+ @Override
public void init() {
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.init() START");
- }
- if(!(this instanceof Container)) {
- throw new RuntimeException("This Applet is not a AWT Container");
+ System.err.println("JOGLNewtApplet1Run.init() START - "+currentThreadName());
}
- Container container = (Container) this;
+ final Container container = this;
String glEventListenerClazzName=null;
String glProfileName=null;
@@ -134,20 +137,20 @@ public class JOGLNewtApplet1Run extends Applet {
glCloseable = JOGLNewtAppletBase.str2Bool(getParameter("gl_closeable"), glCloseable);
glOpaque = JOGLNewtAppletBase.str2Bool(getParameter("gl_opaque"), glOpaque);
glAlphaBits = JOGLNewtAppletBase.str2Int(getParameter("gl_alpha"), glAlphaBits);
- glNumMultisampleBuffer = JOGLNewtAppletBase.str2Int(getParameter("gl_multisamplebuffer"), glNumMultisampleBuffer);
+ glNumMultisampleBuffer = JOGLNewtAppletBase.str2Int(getParameter("gl_multisamplebuffer"), glNumMultisampleBuffer);
glXd = JOGLNewtAppletBase.str2Int(getParameter("gl_dx"), glXd);
glYd = JOGLNewtAppletBase.str2Int(getParameter("gl_dy"), glYd);
glWidth = JOGLNewtAppletBase.str2Int(getParameter("gl_width"), glWidth);
glHeight = JOGLNewtAppletBase.str2Int(getParameter("gl_height"), glHeight);
glNoDefaultKeyListener = JOGLNewtAppletBase.str2Bool(getParameter("gl_nodefaultkeyListener"), glNoDefaultKeyListener);
appletDebugTestBorder = JOGLNewtAppletBase.str2Bool(getParameter("appletDebugTestBorder"), appletDebugTestBorder);
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
if(null==glEventListenerClazzName) {
throw new RuntimeException("No applet parameter 'gl_event_listener_class'");
}
- glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
+ final boolean glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
if(DEBUG) {
System.err.println("JOGLNewtApplet1Run Configuration:");
System.err.println("glStandalone: "+glStandalone);
@@ -167,8 +170,8 @@ public class JOGLNewtApplet1Run extends Applet {
System.err.println("glNumMultisampleBuffer: "+glNumMultisampleBuffer);
System.err.println("glNoDefaultKeyListener: "+glNoDefaultKeyListener);
}
-
- base = new JOGLNewtAppletBase(glEventListenerClazzName,
+
+ base = new JOGLNewtAppletBase(glEventListenerClazzName,
glSwapInterval,
glNoDefaultKeyListener,
glCloseable,
@@ -176,7 +179,7 @@ public class JOGLNewtApplet1Run extends Applet {
glTrace);
try {
- GLCapabilities caps = new GLCapabilities(GLProfile.get(glProfileName));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(glProfileName));
caps.setAlphaBits(glAlphaBits);
if(0<glNumMultisampleBuffer) {
caps.setSampleBuffers(true);
@@ -190,14 +193,17 @@ public class JOGLNewtApplet1Run extends Applet {
glWindow.setDefaultCloseOperation(glCloseable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE);
container.setLayout(new BorderLayout());
if(appletDebugTestBorder) {
- container.add(new Button("North"), BorderLayout.NORTH);
- container.add(new Button("South"), BorderLayout.SOUTH);
- container.add(new Button("East"), BorderLayout.EAST);
- container.add(new Button("West"), BorderLayout.WEST);
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ container.add(new Button("North"), BorderLayout.NORTH);
+ container.add(new Button("South"), BorderLayout.SOUTH);
+ container.add(new Button("East"), BorderLayout.EAST);
+ container.add(new Button("West"), BorderLayout.WEST);
+ } } );
}
base.init(glWindow);
if(base.isValid()) {
- GLEventListener glEventListener = base.getGLEventListener();
+ final GLEventListener glEventListener = base.getGLEventListener();
if(glEventListener instanceof MouseListener) {
addMouseListener((MouseListener)glEventListener);
@@ -209,32 +215,45 @@ public class JOGLNewtApplet1Run extends Applet {
addKeyListener((KeyListener)glEventListener);
}
}
- if(glStandalone) {
- newtCanvasAWT = null;
- } else {
- newtCanvasAWT = new NewtCanvasAWT(glWindow);
- container.add(newtCanvasAWT, BorderLayout.CENTER);
- container.validate();
+ if( !glStandalone ) {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ newtCanvasAWT.setSkipJAWTDestroy(true); // Bug 910
+ container.add(newtCanvasAWT, BorderLayout.CENTER);
+ container.validate();
+ } } );
}
- } catch (Throwable t) {
+ } catch (final Throwable t) {
throw new RuntimeException(t);
}
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.init() END");
+ System.err.println("JOGLNewtApplet1Run.init() END - "+currentThreadName());
}
}
+ private static String currentThreadName() { return "["+Thread.currentThread().getName()+", isAWT-EDT "+EventQueue.isDispatchThread()+"]"; }
+
+ @Override
public void start() {
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.start() START");
+ System.err.println("JOGLNewtApplet1Run.start() START (isVisible "+isVisible()+", isDisplayable "+isDisplayable()+") - "+currentThreadName());
}
- this.validate();
- this.setVisible(true);
-
- final java.awt.Point p0 = this.getLocationOnScreen();
- if(glStandalone) {
+ final java.awt.Point[] p0 = { null };
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ setVisible(true);
+ p0[0] = getLocationOnScreen();
+ if( null != newtCanvasAWT ) {
+ newtCanvasAWT.setFocusable(true);
+ newtCanvasAWT.requestFocus();
+ }
+ }
+ });
+ if( null == newtCanvasAWT ) {
+ glWindow.requestFocus();
glWindow.setSize(glWidth, glHeight);
- glWindow.setPosition(p0.x+glXd, p0.y+glYd);
+ glWindow.setPosition(p0[0].x+glXd, p0[0].y+glYd);
}
if(DEBUG) {
Component topC = this;
@@ -243,7 +262,7 @@ public class JOGLNewtApplet1Run extends Applet {
}
System.err.println("JOGLNewtApplet1Run start:");
System.err.println("TopComponent: "+topC.getLocation()+" rel, "+topC.getLocationOnScreen()+" screen, visible "+topC.isVisible()+", "+topC);
- System.err.println("Applet Pos: "+this.getLocation()+" rel, "+p0+" screen, visible "+this.isVisible()+", "+this);
+ System.err.println("Applet Pos: "+this.getLocation()+" rel, "+Arrays.toString(p0)+" screen, visible "+this.isVisible()+", "+this);
if(null != newtCanvasAWT) {
System.err.println("NewtCanvasAWT Pos: "+newtCanvasAWT.getLocation()+" rel, "+newtCanvasAWT.getLocationOnScreen()+" screen, visible "+newtCanvasAWT.isVisible()+", "+newtCanvasAWT);
}
@@ -251,34 +270,54 @@ public class JOGLNewtApplet1Run extends Applet {
System.err.println("GLWindow: "+glWindow);
}
base.start();
+ if( null != newtCanvasAWT &&
+ newtCanvasAWT.isOffscreenLayerSurfaceEnabled() &&
+ 0 != ( JAWTUtil.JAWT_OSX_CALAYER_QUIRK_POSITION & JAWTUtil.getOSXCALayerQuirks() ) ) {
+ // force relayout
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ final int cW = newtCanvasAWT.getWidth();
+ final int cH = newtCanvasAWT.getHeight();
+ newtCanvasAWT.setSize(cW+1, cH+1);
+ newtCanvasAWT.setSize(cW, cH);
+ } } );
+ }
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.start() END");
+ System.err.println("JOGLNewtApplet1Run.start() END - "+currentThreadName());
}
}
+ @Override
public void stop() {
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.stop() START");
+ System.err.println("JOGLNewtApplet1Run.stop() START - "+currentThreadName());
}
base.stop();
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.stop() END");
+ System.err.println("JOGLNewtApplet1Run.stop() END - "+currentThreadName());
}
}
+ @Override
public void destroy() {
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.destroy() START");
- }
- glWindow.setVisible(false); // hide 1st
- if(!glStandalone) {
- glWindow.reparentWindow(null); // get out of newtCanvasAWT
- this.remove(newtCanvasAWT); // remove newtCanvasAWT
+ System.err.println("JOGLNewtApplet1Run.destroy() START - "+currentThreadName());
}
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ glWindow.setVisible(false); // hide 1st
+ if( null != newtCanvasAWT ) {
+ newtCanvasAWT.setSkipJAWTDestroy(false); // Bug 910
+ remove(newtCanvasAWT); // remove newtCanvasAWT incl. glWindow.reparentWindow(null) if not done yet!
+ newtCanvasAWT.destroy();
+ }
+ } } );
base.destroy(); // destroy glWindow unrecoverable
base=null;
+ glWindow=null;
+ newtCanvasAWT=null;
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.destroy() END");
+ System.err.println("JOGLNewtApplet1Run.destroy() END - "+currentThreadName());
}
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/DoubleTapScrollGesture.java b/src/newt/classes/com/jogamp/newt/event/DoubleTapScrollGesture.java
new file mode 100644
index 000000000..7fec29259
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/DoubleTapScrollGesture.java
@@ -0,0 +1,349 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.newt.event;
+
+import com.jogamp.common.util.PropertyAccess;
+
+import jogamp.newt.Debug;
+
+/**
+ * 2 pointer scroll/rotate gesture handler processing {@link MouseEvent}s
+ * while producing {@link MouseEvent#EVENT_MOUSE_WHEEL_MOVED} events if gesture is completed.
+ * <p>
+ * Criteria related to parameters:
+ * <pre>
+ * - doubleTapSlop (scaled in pixels):
+ * - Max 2 finger distance to start 'scroll' mode
+ * - Max. distance diff of current 2-pointer middle and initiated 2-pointer middle.
+ *
+ * - touchSlop (scaled in pixels):
+ * - Min. movement w/ 2 pointer within ScaledDoubleTapSlop starting 'scroll' mode
+ *
+ * - Avoid computation if not within gesture, especially for MOVE/DRAG
+ *
+ * - Only allow gesture to start with PRESS
+ *
+ * - Leave gesture completely with RELEASE of both/all fingers, or dist-diff exceeds doubleTapSlop
+ *
+ * - Tolerate temporary lift 1 of 2 pointer
+ *
+ * - Always validate pointer-id
+ * </pre>
+ * </p>
+ * Implementation uses a n-state to get detect gesture:
+ * <p>
+ * <table border="1">
+ * <tr><th>from</th> <th>to</th> <th>action</th></tr>
+ * <tr><td>NONE</td> <td>1PRESS</td> <td>1-pointer-pressed</td></tr>
+ * <tr><td>1PRESS</td> <td>2PRESS_T</td> <td>2-pointer-pressed within doubleTapSlope</td></tr>
+ * <tr><td>2PRESS_T</td> <td>SCROLL</td> <td>2-pointer dragged, dist-diff within doubleTapSlop and scrollLen >= scrollSlop</td></tr>
+ * <tr><td>2PRESS_C</td> <td>SCROLL</td> <td>2-pointer dragged, dist-diff within doubleTapSlop</td></tr>
+ * <tr><td>SCROLL</td> <td>SCROLL</td> <td>2-pointer dragged, dist-diff within doubleTapSlop</td></tr>
+ * </table>
+ * State ST_2PRESS_C merely exist to pick up gesture after one pointer has been lost temporarily.
+ * </p>
+ * <p>
+ * {@link #isWithinGesture()} returns gestureState >= 2PRESS_C
+ * </p>
+ */
+public class DoubleTapScrollGesture implements GestureHandler {
+ /** Scroll threshold in pixels (fallback), defaults to 16 pixels. Can be overriden by integer property <code>newt.event.scroll_slop_pixel</code>.*/
+ public static final int SCROLL_SLOP_PIXEL;
+ /** Two pointer 'double tap' slop in pixels (fallback), defaults to 104 pixels. Can be overriden by integer property <code>newt.event.double_tap_slop_pixel</code>.*/
+ public static final int DOUBLE_TAP_SLOP_PIXEL;
+
+ /** Scroll threshold in millimeter, defaults to 3 mm. Can be overriden by integer property <code>newt.event.scroll_slop_mm</code>.*/
+ public static final float SCROLL_SLOP_MM;
+ /** Two pointer 'double tap' slop in millimeter, defaults to 20 mm. Can be overriden by integer property <code>newt.event.double_tap_slop_mm</code>.*/
+ public static final float DOUBLE_TAP_SLOP_MM;
+
+ static {
+ Debug.initSingleton();
+
+ SCROLL_SLOP_PIXEL = PropertyAccess.getIntProperty("newt.event.scroll_slop_pixel", true, 16);
+ DOUBLE_TAP_SLOP_PIXEL = PropertyAccess.getIntProperty("newt.event.double_tap_slop_pixel", true, 104);
+ SCROLL_SLOP_MM = PropertyAccess.getIntProperty("newt.event.scroll_slop_mm", true, 3);
+ DOUBLE_TAP_SLOP_MM = PropertyAccess.getIntProperty("newt.event.double_tap_slop_mm", true, 20);
+ }
+
+ private static final int ST_NONE = 0;
+ private static final int ST_1PRESS = 1;
+ private static final int ST_2PRESS_T = 2;
+ private static final int ST_2PRESS_C = 3;
+ private static final int ST_SCROLL = 4;
+
+ private final int scrollSlop, scrollSlopSquare, doubleTapSlop, doubleTapSlopSquare;
+ private final float[] scrollDistance = new float[] { 0f, 0f };
+ private final int[] pIds = new int[] { -1, -1 };
+ /** See class docu */
+ private int gestureState;
+ private int sqStartDist;
+ private int lastX, lastY;
+ private int pointerDownCount;
+ private MouseEvent hitGestureEvent;
+
+ private static final int getSquareDistance(final float x1, final float y1, final float x2, final float y2) {
+ final int deltaX = (int) x1 - (int) x2;
+ final int deltaY = (int) y1 - (int) y2;
+ return deltaX * deltaX + deltaY * deltaY;
+ }
+
+ private int gesturePointers(final MouseEvent e, final int excludeIndex) {
+ int j = 0;
+ for(int i=e.getPointerCount()-1; i>=0; i--) {
+ if( excludeIndex != i ) {
+ final int id = e.getPointerId(i);
+ if( pIds[0] == id || pIds[1] == id ) {
+ j++;
+ }
+ }
+ }
+ return j;
+ }
+
+ /**
+ * scaledScrollSlop < scaledDoubleTapSlop
+ * @param scaledScrollSlop Distance a pointer can wander before we think the user is scrolling in <i>pixels</i>.
+ * @param scaledDoubleTapSlop Distance in <i>pixels</i> between the first touch and second touch to still be considered a double tap.
+ */
+ public DoubleTapScrollGesture(final int scaledScrollSlop, final int scaledDoubleTapSlop) {
+ scrollSlop = scaledScrollSlop;
+ scrollSlopSquare = scaledScrollSlop * scaledScrollSlop;
+ doubleTapSlop = scaledDoubleTapSlop;
+ doubleTapSlopSquare = scaledDoubleTapSlop * scaledDoubleTapSlop;
+ pointerDownCount = 0;
+ clear(true);
+ if(DEBUG) {
+ System.err.println("DoubleTapScroll scrollSlop (scaled) "+scrollSlop);
+ System.err.println("DoubleTapScroll doubleTapSlop (scaled) "+doubleTapSlop);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "DoubleTapScroll[state "+gestureState+", in "+isWithinGesture()+", has "+(null!=hitGestureEvent)+", pc "+pointerDownCount+"]";
+ }
+
+ @Override
+ public void clear(final boolean clearStarted) {
+ scrollDistance[0] = 0f;
+ scrollDistance[1] = 0f;
+ hitGestureEvent = null;
+ if( clearStarted ) {
+ gestureState = ST_NONE;
+ sqStartDist = 0;
+ pIds[0] = -1;
+ pIds[1] = -1;
+ lastX = 0;
+ lastY = 0;
+ }
+ }
+
+ @Override
+ public boolean isWithinGesture() {
+ return ST_2PRESS_C <= gestureState;
+ }
+
+ @Override
+ public boolean hasGesture() {
+ return null != hitGestureEvent;
+ }
+
+ @Override
+ public InputEvent getGestureEvent() {
+ if( null != hitGestureEvent ) {
+ final MouseEvent ge = hitGestureEvent;
+ int modifiers = ge.getModifiers();
+ final float[] rotationXYZ = ge.getRotation();
+ rotationXYZ[0] = scrollDistance[0] / scrollSlop;
+ rotationXYZ[1] = scrollDistance[1] / scrollSlop;
+ if( rotationXYZ[0]*rotationXYZ[0] > rotationXYZ[1]*rotationXYZ[1] ) {
+ // Horizontal scroll -> SHIFT
+ modifiers |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+ }
+ return new MouseEvent(MouseEvent.EVENT_MOUSE_WHEEL_MOVED, ge.getSource(), ge.getWhen(), modifiers,
+ ge.getAllPointerTypes(), ge.getAllPointerIDs(),
+ ge.getAllX(), ge.getAllY(), ge.getAllPressures(), ge.getMaxPressure(),
+ ge.getButton(), ge.getClickCount(), rotationXYZ, scrollSlop);
+ }
+ return null;
+ }
+
+ public final float[] getScrollDistanceXY() {
+ return scrollDistance;
+ }
+
+ @Override
+ public boolean process(final InputEvent in) {
+ if( null != hitGestureEvent || !(in instanceof MouseEvent) ) {
+ return true;
+ }
+ final MouseEvent pe = (MouseEvent)in;
+ if( pe.getPointerType(0).getPointerClass() != MouseEvent.PointerClass.Onscreen ) {
+ return false;
+ }
+ pointerDownCount = pe.getPointerCount();
+ final int eventType = pe.getEventType();
+ final int x0 = pe.getX(0);
+ final int y0 = pe.getY(0);
+ switch ( eventType ) {
+ case MouseEvent.EVENT_MOUSE_PRESSED: {
+ int gPtr = 0;
+ if( ST_NONE == gestureState && 1 == pointerDownCount ) {
+ pIds[0] = pe.getPointerId(0);
+ pIds[1] = -1;
+ gestureState = ST_1PRESS;
+ } else if( ST_NONE < gestureState && 2 == pointerDownCount && 1 == gesturePointers(pe, 0) /* w/o pressed pointer */ ) {
+ final int x1 = pe.getX(1);
+ final int y1 = pe.getY(1);
+ final int xm = (x0+x1)/2;
+ final int ym = (y0+y1)/2;
+
+ if( ST_1PRESS == gestureState ) {
+ final int sqDist = getSquareDistance(x0, y0, x1, y1);
+ final boolean isDistWithinDoubleTapSlop = sqDist < doubleTapSlopSquare;
+ if( isDistWithinDoubleTapSlop ) {
+ // very first 2-finger touch-down
+ gPtr = 2;
+ pIds[0] = pe.getPointerId(0);
+ pIds[1] = pe.getPointerId(1);
+ lastX = xm;
+ lastY = ym;
+ sqStartDist = sqDist;
+ gestureState = ST_2PRESS_T;
+ }
+ if(DEBUG) {
+ final int dist = (int)Math.round(Math.sqrt(sqDist));
+ System.err.println(this+".pressed.1: dist "+dist+", gPtr "+gPtr+", distWithin2DTSlop "+isDistWithinDoubleTapSlop+", last "+lastX+"/"+lastY+", "+pe);
+ }
+ } else if( ST_2PRESS_C == gestureState ) { // pick up gesture after temp loosing one pointer
+ gPtr = gesturePointers(pe, -1);
+ if( 2 == gPtr ) {
+ // same pointers re-touch-down
+ lastX = xm;
+ lastY = ym;
+ } else {
+ // other 2 pointers .. should rarely happen!
+ clear(true);
+ }
+ }
+ }
+ if(DEBUG) {
+ System.err.println(this+".pressed: gPtr "+gPtr+", this "+lastX+"/"+lastY+", "+pe);
+ }
+ } break;
+
+ case MouseEvent.EVENT_MOUSE_RELEASED: {
+ pointerDownCount--; // lifted
+ final int gPtr = gesturePointers(pe, 0); // w/o lifted pointer
+ if ( 1 == gPtr ) {
+ // tolerate lifting 1 of 2 gesture pointers temporary
+ gestureState = ST_2PRESS_C;
+ } else if( 0 == gPtr ) {
+ // all lifted
+ clear(true);
+ }
+ if(DEBUG) {
+ System.err.println(this+".released: gPtr "+gPtr+", "+pe);
+ }
+ } break;
+
+ case MouseEvent.EVENT_MOUSE_DRAGGED: {
+ if( 2 == pointerDownCount && ST_1PRESS < gestureState ) {
+ final int gPtr = gesturePointers(pe, -1);
+ if( 2 == gPtr ) {
+ // same pointers
+ final int x1 = pe.getX(1);
+ final int y1 = pe.getY(1);
+ final int xm = (x0+x1)/2;
+ final int ym = (y0+y1)/2;
+ final int sqDist = getSquareDistance(x0, y0, x1, y1);
+ final boolean isDistDiffWithinDoubleTapSlop = Math.abs(sqDist - sqStartDist) <= doubleTapSlopSquare;
+ if( isDistDiffWithinDoubleTapSlop ) {
+ switch( gestureState ) {
+ case ST_2PRESS_T: {
+ final int sqScrollLen = getSquareDistance(lastX, lastY, xm, ym);
+ if( sqScrollLen > scrollSlopSquare ) { // min. scrolling threshold reached
+ gestureState = ST_SCROLL;
+ }
+ } break;
+
+ case ST_2PRESS_C:
+ gestureState = ST_SCROLL;
+ break;
+
+ case ST_SCROLL:
+ scrollDistance[0] = lastX - xm;
+ scrollDistance[1] = lastY - ym;
+ hitGestureEvent = pe;
+ break;
+ }
+ if(DEBUG) {
+ final boolean isDistWithinDoubleTapSlop = sqDist < doubleTapSlopSquare;
+ final int dist = (int)Math.round(Math.sqrt(sqDist));
+ final int sqScrollLen = getSquareDistance(lastX, lastY, xm, ym);
+ final int scrollLen = (int)Math.round(Math.sqrt(sqScrollLen));
+ System.err.println(this+".dragged.1: pDist "+dist+", scrollLen "+scrollLen+", gPtr "+gPtr+" ["+pIds[0]+", "+pIds[1]+"]"+
+ ", diffDistWithinTapSlop "+isDistDiffWithinDoubleTapSlop+
+ ", distWithin2DTSlop "+isDistWithinDoubleTapSlop+
+ ", this "+xm+"/"+ym+", last "+lastX+"/"+lastY+", d "+scrollDistance[0]+"/"+scrollDistance[1]);
+ }
+ } else {
+ // distance too big ..
+ if(DEBUG) {
+ final boolean isDistWithinDoubleTapSlop = sqDist < doubleTapSlopSquare;
+ final int dist = (int)Math.round(Math.sqrt(sqDist));
+ final int startDist = (int)Math.round(Math.sqrt(sqStartDist));
+ System.err.println(this+".dragged.X1: pDist "+dist+", distStart "+startDist+", gPtr "+gPtr+" ["+pIds[0]+", "+pIds[1]+"]"+
+ ", diffDistWithinTapSlop "+isDistDiffWithinDoubleTapSlop+
+ ", distWithin2DTSlop "+isDistWithinDoubleTapSlop+
+ ", this "+xm+"/"+ym+", last "+lastX+"/"+lastY+", d "+scrollDistance[0]+"/"+scrollDistance[1]);
+ }
+ clear(true);
+ }
+ if( ST_2PRESS_T < gestureState ) {
+ // state ST_2PRESS_T waits for min scroll threshold !
+ lastX = xm;
+ lastY = ym;
+ }
+ } else {
+ // other 2 pointers .. should rarely happen!
+ if(DEBUG) {
+ System.err.println(this+".dragged.X2: gPtr "+gPtr+" ["+pIds[0]+", "+pIds[1]+"]"+
+ ", last "+lastX+"/"+lastY+", d "+scrollDistance[0]+"/"+scrollDistance[1]);
+ }
+ clear(true);
+ }
+ }
+ } break;
+
+ default:
+ }
+ return null != hitGestureEvent;
+ }
+}
diff --git a/src/newt/classes/com/jogamp/newt/event/GestureHandler.java b/src/newt/classes/com/jogamp/newt/event/GestureHandler.java
new file mode 100644
index 000000000..ea0f76fbb
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/GestureHandler.java
@@ -0,0 +1,155 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.newt.event;
+
+import jogamp.newt.Debug;
+
+/**
+ * Generic gesture handler interface designed to allow pass-through
+ * filtering of {@link InputEvent}s.
+ * <p>
+ * To avoid negative impact on event processing,
+ * implementation shall restrict computation as much as possible
+ * and only within it's appropriate gesture states.
+ * </p>
+ * <p>
+ * To allow custom user events, other than the <i>normal</i> {@link InputEvent}s,
+ * a user may return a {@link GestureEvent} in it's implementation.
+ * </p>
+ */
+public interface GestureHandler {
+ public static final boolean DEBUG = Debug.debug("Window.MouseEvent");
+
+ /** A custom gesture event */
+ @SuppressWarnings("serial")
+ public static class GestureEvent extends InputEvent {
+ /** A gesture has been detected. */
+ public static final short EVENT_GESTURE_DETECTED = 400;
+
+ private final GestureHandler handler;
+ private final InputEvent ie;
+
+ /**
+ * Creates a gesture event with default type {@link #EVENT_GESTURE_DETECTED}.
+ *
+ * @param source
+ * @param when
+ * @param modifiers
+ * @param handler
+ * @param trigger TODO
+ */
+ public GestureEvent(final Object source, final long when, final int modifiers, final GestureHandler handler, final InputEvent trigger) {
+ super(EVENT_GESTURE_DETECTED, source, when, modifiers);
+ this.handler = handler;
+ this.ie = trigger;
+ }
+
+ /**
+ * Creates a gesture event with custom <i>event_type</i> !
+ * @param event_type must lie within [400..599]
+ * @param source
+ * @param when
+ * @param modifiers
+ * @param handler
+ * @param trigger TODO
+ */
+ public GestureEvent(final short event_type, final Object source, final long when, final int modifiers, final GestureHandler handler, final InputEvent trigger) {
+ super(event_type, source, when, modifiers);
+ this.handler = handler;
+ this.ie = trigger;
+ }
+
+ /** Return the {@link GestureHandler}, which produced the event. */
+ public final GestureHandler getHandler() { return handler; }
+
+ /** Triggering {@link InputEvent} */
+ public final InputEvent getTrigger() { return ie; }
+
+ public String toString() {
+ return "GestureEvent[handler "+handler+"]";
+ }
+ }
+
+ /**
+ * Listener for {@link GestureEvent}s.
+ *
+ * @see GestureEvent
+ */
+ public static interface GestureListener extends NEWTEventListener
+ {
+ /** {@link GestureHandler} {@link GestureHandler#hasGesture() has detected} the gesture. */
+ public void gestureDetected(GestureEvent gh);
+ }
+
+ /**
+ * Clears state of handler, i.e. resets all states incl. previous detected gesture.
+ * @param clearStarted if true, also clears {@link #isWithinGesture() started} state,
+ * otherwise stay within gesture - if appropriate.
+ * Staying within a gesture allows fluent continuous gesture sequence,
+ * e.g. for scrolling.
+ */
+ public void clear(boolean clearStarted);
+
+ /**
+ * Returns true if a previous {@link #process(InputEvent)} command produced a gesture,
+ * which has not been {@link #clear(boolean) cleared}.
+ * Otherwise returns false.
+ */
+ public boolean hasGesture();
+
+ /**
+ * Returns the corresponding {@link InputEvent} for the gesture as detected by
+ * a previous {@link #process(InputEvent)}, which has not been {@link #clear(boolean) cleared}.
+ * Otherwise returns null.
+ * <p>
+ * Only implemented for gestures mapping to {@link InputEvent}s.
+ * </p>
+ */
+ public InputEvent getGestureEvent();
+
+ /**
+ * Returns true if within a gesture as detected by a previous {@link #process(InputEvent)} command,
+ * which has not been {@link #clear(boolean) cleared}.
+ * Otherwise returns false.
+ */
+ public boolean isWithinGesture();
+
+ /**
+ * Process the given {@link InputEvent} and returns true if it produced the gesture.
+ * Otherwise returns false.
+ * <p>
+ * If a gesture was already detected previously and has not been cleared,
+ * method does not process the event and returns true.
+ * </p>
+ * <p>
+ * Besides validation of the event's details,
+ * the handler may also validate the {@link InputEvent.InputClass} and/or {@link InputEvent.InputType}.
+ * </p>
+ */
+ public boolean process(InputEvent e);
+}
diff --git a/src/newt/classes/com/jogamp/newt/event/InputEvent.java b/src/newt/classes/com/jogamp/newt/event/InputEvent.java
index 148ac5962..fbda79d46 100644
--- a/src/newt/classes/com/jogamp/newt/event/InputEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/InputEvent.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,100 +29,111 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+import com.jogamp.common.util.IntBitfield;
import com.jogamp.newt.Window;
@SuppressWarnings("serial")
public abstract class InputEvent extends NEWTEvent
{
+ /** Interface marking class of input types */
+ public static interface InputClass {
+ }
+
+ /** Interface marking type of input devices */
+ public static interface InputType {
+ }
+
public static final int SHIFT_MASK = 1 << 0;
public static final int CTRL_MASK = 1 << 1;
public static final int META_MASK = 1 << 2;
public static final int ALT_MASK = 1 << 3;
- public static final int ALT_GRAPH_MASK = 1 << 5;
- public static final int BUTTON1_MASK = 1 << 6;
- public static final int BUTTON2_MASK = 1 << 7;
- public static final int BUTTON3_MASK = 1 << 8;
- public static final int BUTTON4_MASK = 1 << 9;
- public static final int BUTTON5_MASK = 1 << 10;
- public static final int BUTTON6_MASK = 1 << 11;
-
+ public static final int ALT_GRAPH_MASK = 1 << 4;
+
+ public static final int BUTTON1_MASK = 1 << 5;
+ public static final int BUTTON2_MASK = 1 << 6;
+ public static final int BUTTON3_MASK = 1 << 7;
+ public static final int BUTTON4_MASK = 1 << 8;
+ public static final int BUTTON5_MASK = 1 << 9;
+ public static final int BUTTON6_MASK = 1 << 10;
+ public static final int BUTTON7_MASK = 1 << 11;
+ public static final int BUTTON8_MASK = 1 << 12;
+ public static final int BUTTON9_MASK = 1 << 13;
+
+ public static final int BUTTONLAST_MASK = 1 << 20; // 16 buttons
+ public static final int BUTTONALL_MASK = 0xffff << 5 ; // 16 buttons
+
/** Event is caused by auto-repeat. */
- public static final int AUTOREPEAT_MASK = 1 << 15;
-
+ public static final int AUTOREPEAT_MASK = 1 << 29;
+
/** Pointer is confined, see {@link Window#confinePointer(boolean)}. */
- public static final int CONFINED_MASK = 1 << 16;
-
+ public static final int CONFINED_MASK = 1 << 30;
+
/** Pointer is invisible, see {@link Window#setPointerVisible(boolean)}. */
- public static final int INVISIBLE_MASK = 1 << 17;
+ public static final int INVISIBLE_MASK = 1 << 31;
- /**
+ /**
* Returns the corresponding button mask for the given button.
* <p>
- * In case the given button lies outside
- * of the valid range [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON6}],
+ * In case the given button lies outside
+ * of the valid range [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON_COUNT}],
* null is returned.
* </p>
*/
- public static final int getButtonMask(int button) {
- if( 0 < button && button <= MouseEvent.BUTTON_NUMBER ) {
- return 1 << ( 5 + button ) ;
+ public static final int getButtonMask(final int button) {
+ if( 0 < button && button <= MouseEvent.BUTTON_COUNT ) {
+ return 1 << ( 4 + button ) ;
}
return 0;
}
-
- /** Object when attached via {@link #setAttachment(Object)} marks the event consumed,
- * ie. stops propagating the event any further to the event listener.
- */
- public static final Object consumedTag = new Object();
-
- protected InputEvent(int eventType, Object source, long when, int modifiers) {
+
+ protected InputEvent(final short eventType, final Object source, final long when, final int modifiers) {
super(eventType, source, when);
this.modifiers=modifiers;
}
/** Return the modifier bits of this event, e.g. see {@link #SHIFT_MASK} .. etc. */
- public int getModifiers() {
+ public final int getModifiers() {
return modifiers;
}
/** {@link #getModifiers()} contains {@link #ALT_MASK}. */
- public boolean isAltDown() {
+ public final boolean isAltDown() {
return (modifiers&ALT_MASK)!=0;
}
/** {@link #getModifiers()} contains {@link #ALT_GRAPH_MASK}. */
- public boolean isAltGraphDown() {
+ public final boolean isAltGraphDown() {
return (modifiers&ALT_GRAPH_MASK)!=0;
}
/** {@link #getModifiers()} contains {@link #CTRL_MASK}. */
- public boolean isControlDown() {
+ public final boolean isControlDown() {
return (modifiers&CTRL_MASK)!=0;
}
/** {@link #getModifiers()} contains {@link #META_MASK}. */
- public boolean isMetaDown() {
+ public final boolean isMetaDown() {
return (modifiers&META_MASK)!=0;
}
/** {@link #getModifiers()} contains {@link #SHIFT_MASK}. */
- public boolean isShiftDown() {
+ public final boolean isShiftDown() {
return (modifiers&SHIFT_MASK)!=0;
}
/** {@link #getModifiers()} contains {@link #AUTOREPEAT_MASK}. */
- public boolean isAutoRepeat() {
+ public final boolean isAutoRepeat() {
return (modifiers&AUTOREPEAT_MASK)!=0;
}
/** {@link #getModifiers()} contains {@link #CONFINED_MASK}. Pointer is confined, see {@link Window#confinePointer(boolean)}. */
- public boolean isConfined() {
+ public final boolean isConfined() {
return (modifiers&CONFINED_MASK)!=0;
}
- /** {@link #getModifiers()} contains {@link #INVISIBLE_MASK}. Pointer is invisible, see {@link Window#setPointerVisible(boolean)}. */
- public boolean isInvisible() {
+ /** {@link #getModifiers()} contains {@link #INVISIBLE_MASK}. Pointer is invisible, see {@link Window#setPointerVisible(boolean)}. */
+ public final boolean isInvisible() {
return (modifiers&INVISIBLE_MASK)!=0;
}
-
- public StringBuilder getModifiersString(StringBuilder sb) {
+
+ public final StringBuilder getModifiersString(StringBuilder sb) {
if(null == sb) {
sb = new StringBuilder();
}
@@ -130,46 +141,81 @@ public abstract class InputEvent extends NEWTEvent
boolean isFirst = true;
if(isShiftDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("shift"); }
if(isControlDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("ctrl"); }
- if(isMetaDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("meta"); }
+ if(isMetaDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("meta"); }
if(isAltDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("alt"); }
- if(isAltGraphDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("altg"); }
+ if(isAltGraphDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("altgr"); }
if(isAutoRepeat()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("repeat"); }
- for(int i=1; i<=MouseEvent.BUTTON_NUMBER; i++) {
+ for(int i=1; i<=MouseEvent.BUTTON_COUNT; i++) {
if(isButtonDown(i)) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("button").append(i); }
}
if(isConfined()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("confined"); }
if(isInvisible()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("invisible"); }
sb.append("]");
-
+
return sb;
}
/**
- * @return Array of pressed mouse buttons [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON6}].
+ * See also {@link MouseEvent}'s section about <i>Multiple-Pointer Events</i>.
+ * @return Array of pressed mouse buttons [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON6}].
* If none is down, the resulting array is of length 0.
*/
- public final int[] getButtonsDown() {
- int len = 0;
- for(int i=1; i<=MouseEvent.BUTTON_NUMBER; i++) {
- if(isButtonDown(i)) { len++; }
- }
-
- int[] res = new int[len];
+ public final short[] getButtonsDown() {
+ final int len = getButtonDownCount();
+
+ final short[] res = new short[len];
int j = 0;
- for(int i=1; i<=MouseEvent.BUTTON_NUMBER; i++) {
- if(isButtonDown(i)) { res[j++] = ( MouseEvent.BUTTON1 - 1 ) + i; }
+ for(int i=1; i<=MouseEvent.BUTTON_COUNT; i++) {
+ if( isButtonDown(i) ) { res[j++] = (short) ( ( MouseEvent.BUTTON1 - 1 ) + i ); }
}
return res;
}
- public final boolean isButtonDown(int button) {
+ /**
+ * See also {@link MouseEvent}'s section about <i>Multiple-Pointer Events</i>.
+ * @param button the button to test
+ * @return true if the given button is down
+ */
+ public final boolean isButtonDown(final int button) {
return ( modifiers & getButtonMask(button) ) != 0;
}
-
+
+ /**
+ * Returns the number of pressed buttons by counting the set bits:
+ * <pre>
+ * getBitCount(modifiers & BUTTONALL_MASK);
+ * </pre>
+ * <p>
+ * See also {@link MouseEvent}'s section about <i>Multiple-Pointer Events</i>.
+ * </p>
+ * @see IntBitfield#getBitCount(int)
+ * @see #BUTTONALL_MASK
+ */
+ public final int getButtonDownCount() {
+ return IntBitfield.getBitCount(modifiers & BUTTONALL_MASK);
+ }
+
+ /**
+ * Returns true if at least one button is pressed, otherwise false:
+ * <pre>
+ * 0 != ( modifiers & BUTTONALL_MASK )
+ * </pre>
+ * <p>
+ * See also {@link MouseEvent}'s section about <i>Multiple-Pointer Events</i>.
+ * </p>
+ * @see IntBitfield#getBitCount(int)
+ * @see #BUTTONALL_MASK
+ */
+ public final boolean isAnyButtonDown() {
+ return 0 != ( modifiers & BUTTONALL_MASK );
+ }
+
+ @Override
public String toString() {
return toString(null).toString();
}
-
+
+ @Override
public StringBuilder toString(StringBuilder sb) {
if(null == sb) {
sb = new StringBuilder();
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
index 93c8409b1..0f147a722 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
@@ -4,14 +4,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -21,21 +21,21 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event;
public abstract class KeyAdapter implements KeyListener
{
- public void keyPressed(KeyEvent e) {
- }
- public void keyReleased(KeyEvent e) {
+ @Override
+ public void keyPressed(final KeyEvent e) {
}
- public void keyTyped(KeyEvent e) {
+ @Override
+ public void keyReleased(final KeyEvent e) {
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
index 7daaeada6..f29e9eb8c 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,734 +29,937 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+import com.jogamp.common.util.IntBitfield;
+
/**
+ * <a name="eventDelivery"><h5>KeyEvent Delivery</h5></a>
+ *
* Key events are delivered in the following order:
- * <ol>
- * <li>{@link #EVENT_KEY_PRESSED}</li>
- * <li>{@link #EVENT_KEY_RELEASED}</li>
- * <li>{@link #EVENT_KEY_TYPED}</li>
- * </ol>
+ * <p>
+ * <table border="0">
+ * <tr><th>#</th><th>Event Type</th> <th>Constraints</th> <th>Notes</th></tr>
+ * <tr><td>1</td><td>{@link #EVENT_KEY_PRESSED} </td><td> <i> excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys</i></td><td></td></tr>
+ * <tr><td>2</td><td>{@link #EVENT_KEY_RELEASED} </td><td> <i> excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys</i></td><td></td></tr>
+ * </table>
+ * </p>
* In case the native platform does not
- * deliver keyboard events in the above order or skip events,
- * the NEWT driver will reorder and inject synthetic events if required.
+ * deliver keyboard events in the above order or skip events,
+ * the NEWT driver will reorder and inject synthetic events if required.
+ * <p>
+ * Besides regular modifiers like {@link InputEvent#SHIFT_MASK} etc.,
+ * the {@link InputEvent#AUTOREPEAT_MASK} bit is added if repetition is detected, following above constraints.
+ * </p>
+ * <p>
+ * Auto-Repeat shall behave as follow:
+ * <pre>
+ P = pressed, R = released
+ 0 = normal, 1 = auto-repeat
+
+ P(0), [ R(1), P(1), R(1), ..], R(0)
+ * </pre>
+ * The idea is if you mask out auto-repeat in your event listener
+ * you just get one long pressed P/R tuple for {@link #isPrintableKey() printable} and {@link #isActionKey() Action} keys.
+ * </p>
+ * <p>
+ * {@link #isActionKey() Action} keys will produce {@link #EVENT_KEY_PRESSED pressed}
+ * and {@link #EVENT_KEY_RELEASED released} events including {@link #isAutoRepeat() auto-repeat}.
+ * </p>
+ * <p>
+ * {@link #isPrintableKey() Printable} keys will produce {@link #EVENT_KEY_PRESSED pressed} and {@link #EVENT_KEY_RELEASED released} events.
+ * </p>
+ * <p>
+ * {@link #isModifierKey() Modifier} keys will produce {@link #EVENT_KEY_PRESSED pressed} and {@link #EVENT_KEY_RELEASED released} events
+ * excluding {@link #isAutoRepeat() auto-repeat}.
+ * They will also influence subsequent event's {@link #getModifiers() modifier} bits while pressed.
+ * </p>
+ *
+ * <a name="unicodeMapping"><h5>Unicode Mapping</h5></a>
+ * <p>
+ * {@link #getKeyChar() Key-chars}, as well as
+ * {@link #isPrintableKey() printable} {@link #getKeyCode() key-codes} and {@link #getKeySymbol() key-symbols}
+ * use the UTF-16 unicode space w/o collision.
+ *
+ * </p>
* <p>
- * Besides regular modifiers like {@link InputEvent#SHIFT_MASK} etc.,
- * the {@link InputEvent#AUTOREPEAT_MASK} bit is added if repetition is detected.
+ * Non-{@link #isPrintableKey() printable} {@link #getKeyCode() key-codes} and {@link #getKeySymbol() key-symbols},
+ * i.e. {@link #isModifierKey() modifier-} and {@link #isActionKey() action-}keys,
+ * are mapped to unicode's control and private range and do not collide w/ {@link #isPrintableKey() printable} unicode values
+ * with the following exception.
+ * </p>
+ *
+ * <a name="unicodeCollision"><h5>Unicode Collision</h5></a>
+ * <p>
+ * The following {@link #getKeyCode() Key-code}s and {@link #getKeySymbol() key-symbol}s collide w/ unicode space:<br/>
+ * <table border="1">
+ * <tr><th>unicode range</th> <th>virtual key code</th> <th>unicode character</th></tr>
+ * <tr><td>[0x61 .. 0x78]</td> <td>[{@link #VK_F1}..{@link #VK_F24}]</td> <td>['a'..'x']</td></tr>
+ * </table>
+ * </p>
+ * <p>
+ * Collision was chosen for {@link #getKeyCode() Key-code} and {@link #getKeySymbol() key-symbol} mapping
+ * to allow a minimal code range, i.e. <code>[0..255]</code>.
+ * The reduced code range in turn allows the implementation to utilize fast and small lookup tables,
+ * e.g. to implement a key-press state tracker.
+ * </p>
+ * <pre>
+ * http://www.utf8-chartable.de/unicode-utf8-table.pl
+ * http://www.unicode.org/Public/5.1.0/ucd/PropList.txt
+ * https://en.wikipedia.org/wiki/Mapping_of_Unicode_characters
+ * https://en.wikipedia.org/wiki/Unicode_control_characters
+ * https://en.wikipedia.org/wiki/Private_Use_%28Unicode%29#Private_Use_Areas
+ * </pre>
* </p>
*/
@SuppressWarnings("serial")
public class KeyEvent extends InputEvent
{
- public KeyEvent(int eventType, Object source, long when, int modifiers, int keyCode, char keyChar) {
- super(eventType, source, when, modifiers);
- this.keyCode=keyCode;
- this.keyChar=keyChar;
- }
-
- /** Only valid on all platforms at {@link KeyListener#keyTyped(KeyEvent)} */
- public char getKeyChar() {
- return keyChar;
- }
-
- /** Always valid. */
- public int getKeyCode() {
- return keyCode;
- }
-
- public String toString() {
- return toString(null).toString();
- }
-
- public StringBuilder toString(StringBuilder sb) {
- if(null == sb) {
- sb = new StringBuilder();
- }
- sb.append("KeyEvent[").append(getEventTypeString(getEventType())).append(", code ").append(keyCode).append("(").append(toHexString(keyCode)).append("), char '").append(keyChar).append("' (").append(toHexString((int)keyChar)).append("), isActionKey ").append(isActionKey()).append(", ");
- return super.toString(sb).append("]");
- }
-
- public static String getEventTypeString(int type) {
- switch(type) {
- case EVENT_KEY_PRESSED: return "EVENT_KEY_PRESSED";
- case EVENT_KEY_RELEASED: return "EVENT_KEY_RELEASED";
- case EVENT_KEY_TYPED: return "EVENT_KEY_TYPED";
- default: return "unknown (" + type + ")";
- }
- }
-
- public boolean isActionKey() {
- switch (keyCode) {
- case VK_HOME:
- case VK_END:
- case VK_PAGE_UP:
- case VK_PAGE_DOWN:
- case VK_UP:
- case VK_DOWN:
- case VK_LEFT:
- case VK_RIGHT:
-
- case VK_F1:
- case VK_F2:
- case VK_F3:
- case VK_F4:
- case VK_F5:
- case VK_F6:
- case VK_F7:
- case VK_F8:
- case VK_F9:
- case VK_F10:
- case VK_F11:
- case VK_F12:
- case VK_F13:
- case VK_F14:
- case VK_F15:
- case VK_F16:
- case VK_F17:
- case VK_F18:
- case VK_F19:
- case VK_F20:
- case VK_F21:
- case VK_F22:
- case VK_F23:
- case VK_F24:
- case VK_PRINTSCREEN:
- case VK_CAPS_LOCK:
- case VK_PAUSE:
- case VK_INSERT:
-
- case VK_HELP:
- case VK_WINDOWS:
- return true;
+ private KeyEvent(final short eventType, final Object source, final long when, final int modifiers, final short keyCode, final short keySym, final int keySymModMask, final char keyChar) {
+ super(eventType, source, when, modifiers | keySymModMask);
+ this.keyCode=keyCode;
+ this.keySym=keySym;
+ this.keyChar=keyChar;
+ { // cache modifier and action flags
+ byte _flags = 0;
+ if( isPrintableKey(keySym, false) && isPrintableKey((short)keyChar, true) ) {
+ _flags |= F_PRINTABLE_MASK;
+ } else {
+ if( 0 != keySymModMask ) {
+ _flags |= F_MODIFIER_MASK;
+ } else {
+ // A = U - ( P + M )
+ _flags |= F_ACTION_MASK;
+ }
+ }
+ flags = _flags;
+
+ //
+ // Validate flags
+ //
+ final int pma_bits = flags & ( F_PRINTABLE_MASK | F_MODIFIER_MASK | F_ACTION_MASK ) ;
+ final int pma_count = IntBitfield.getBitCount(pma_bits);
+ if ( 1 != pma_count ) {
+ throw new InternalError("Key must be either of type printable, modifier or action - but it is of "+pma_count+" types: "+this);
+ }
+ }
}
- return false;
- }
-
- private final int keyCode;
- private final char keyChar;
-
- public static final int EVENT_KEY_PRESSED = 300;
- public static final int EVENT_KEY_RELEASED= 301;
- public static final int EVENT_KEY_TYPED = 302;
-
- /* Virtual key codes. */
- public static final int VK_ENTER = '\n';
- public static final int VK_BACK_SPACE = '\b';
- public static final int VK_TAB = '\t';
- public static final int VK_CANCEL = 0x03;
- public static final int VK_CLEAR = 0x0C;
- public static final int VK_SHIFT = 0x10;
- public static final int VK_CONTROL = 0x11;
- public static final int VK_ALT = 0x12;
- public static final int VK_PAUSE = 0x13;
- public static final int VK_CAPS_LOCK = 0x14;
- public static final int VK_ESCAPE = 0x1B;
- public static final int VK_SPACE = 0x20;
- public static final int VK_PAGE_UP = 0x21;
- public static final int VK_PAGE_DOWN = 0x22;
- public static final int VK_END = 0x23;
- public static final int VK_HOME = 0x24;
+ public static KeyEvent create(final short eventType, final Object source, final long when, final int modifiers, final short keyCode, final short keySym, final char keyChar) {
+ return new KeyEvent(eventType, source, when, modifiers, keyCode, keySym, getModifierMask(keySym), keyChar);
+ }
/**
- * Constant for the non-numpad <b>left</b> arrow key.
- * @see #VK_KP_LEFT
+ * Returns the <i>UTF-16</i> character reflecting the {@link #getKeySymbol() key symbol}
+ * incl. active {@link #isModifierKey() modifiers}.
+ * @see #getKeySymbol()
+ * @see #getKeyCode()
*/
- public static final int VK_LEFT = 0x25;
+ public final char getKeyChar() {
+ return keyChar;
+ }
/**
- * Constant for the non-numpad <b>up</b> arrow key.
- * @see #VK_KP_UP
+ * Returns the virtual <i>key symbol</i> reflecting the current <i>keyboard layout</i>.
+ * <p>
+ * For {@link #isPrintableKey() printable keys}, the <i>key symbol</i> is the {@link #isModifierKey() unmodified}
+ * representation of the UTF-16 {@link #getKeyChar() key char}.<br/>
+ * E.g. symbol [{@link #VK_A}, 'A'] for char 'a'.
+ * </p>
+ * @see #isPrintableKey()
+ * @see #getKeyChar()
+ * @see #getKeyCode()
*/
- public static final int VK_UP = 0x26;
+ public final short getKeySymbol() {
+ return keySym;
+ }
/**
- * Constant for the non-numpad <b>right</b> arrow key.
- * @see #VK_KP_RIGHT
- */
- public static final int VK_RIGHT = 0x27;
+ * Returns the virtual <i>key code</i> using a fixed mapping to the <i>US keyboard layout</i>.
+ * <p>
+ * In contrast to {@link #getKeySymbol() key symbol}, <i>key code</i>
+ * uses a fixed <i>US keyboard layout</i> and therefore is keyboard layout independent.
+ * </p>
+ * <p>
+ * E.g. <i>virtual key code</i> {@link #VK_Y} denotes the same physical key
+ * regardless whether <i>keyboard layout</i> <code>QWERTY</code> or
+ * <code>QWERTZ</code> is active. The {@link #getKeySymbol() key symbol} of the former is
+ * {@link #VK_Y}, where the latter produces {@link #VK_Y}.
+ * </p>
+ * @see #getKeyChar()
+ * @see #getKeySymbol()
+ */
+ public final short getKeyCode() {
+ return keyCode;
+ }
+
+ @Override
+ public final String toString() {
+ return toString(null).toString();
+ }
+
+ @Override
+ public final StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("KeyEvent[").append(getEventTypeString(getEventType())).append(", code ").append(toHexString(keyCode)).append(", sym ").append(toHexString(keySym)).append(", char '").append(keyChar).append("' (").append(toHexString((short)keyChar))
+ .append("), printable ").append(isPrintableKey()).append(", modifier ").append(isModifierKey()).append(", action ").append(isActionKey()).append(", ");
+ return super.toString(sb).append("]");
+ }
+
+ public static String getEventTypeString(final short type) {
+ switch(type) {
+ case EVENT_KEY_PRESSED: return "EVENT_KEY_PRESSED";
+ case EVENT_KEY_RELEASED: return "EVENT_KEY_RELEASED";
+ default: return "unknown (" + type + ")";
+ }
+ }
/**
- * Constant for the non-numpad <b>down</b> arrow key.
- * @see #VK_KP_DOWN
+ * @param keyChar UTF16 value to map. It is expected that the incoming keyChar value is unshifted and unmodified,
+ * however, lower case a-z is mapped to {@link KeyEvent#VK_A} - {@link KeyEvent#VK_Z}.
+ * @return {@link KeyEvent} virtual key (VK) value.
*/
- public static final int VK_DOWN = 0x28;
+ public static short utf16ToVKey(final char keyChar) {
+ if( 'a' <= keyChar && keyChar <= 'z' ) {
+ return (short) ( ( keyChar - 'a' ) + KeyEvent.VK_A );
+ }
+ return (short) keyChar;
+ }
/**
- * Constant for the comma key, ","
- */
- public static final int VK_COMMA = 0x2C;
+ * Returns <code>true</code> if the given <code>virtualKey</code> represents a modifier key, otherwise <code>false</code>.
+ * <p>
+ * A modifier key is one of {@link #VK_SHIFT}, {@link #VK_CONTROL}, {@link #VK_ALT}, {@link #VK_ALT_GRAPH}, {@link #VK_META}.
+ * </p>
+ */
+ public static boolean isModifierKey(final short vKey) {
+ switch (vKey) {
+ case VK_SHIFT:
+ case VK_CONTROL:
+ case VK_ALT:
+ case VK_ALT_GRAPH:
+ case VK_META:
+ return true;
+ default:
+ return false;
+ }
+ }
/**
- * Constant for the minus key, "-"
- * @since 1.2
- */
- public static final int VK_MINUS = 0x2D;
+ * If <code>vKey</code> is a {@link #isModifierKey() modifier key}, method returns the corresponding modifier mask,
+ * otherwise 0.
+ */
+ public static int getModifierMask(final short vKey) {
+ switch (vKey) {
+ case VK_SHIFT:
+ return InputEvent.SHIFT_MASK;
+ case VK_CONTROL:
+ return InputEvent.CTRL_MASK;
+ case VK_ALT:
+ case VK_ALT_GRAPH:
+ return InputEvent.ALT_MASK;
+ case VK_META:
+ return InputEvent.META_MASK;
+ }
+ return 0;
+ }
/**
- * Constant for the period key, "."
+ * Returns <code>true</code> if {@link #getKeySymbol() key symbol} represents a modifier key,
+ * otherwise <code>false</code>.
+ * <p>
+ * See {@link #isModifierKey(short)} for details.
+ * </p>
+ * <p>
+ * Note: Implementation uses a cached value.
+ * </p>
*/
- public static final int VK_PERIOD = 0x2E;
+ public final boolean isModifierKey() {
+ return 0 != ( F_MODIFIER_MASK & flags ) ;
+ }
/**
- * Constant for the forward slash key, "/"
+ * Returns <code>true</code> if {@link #getKeySymbol() key symbol} represents a non-printable and
+ * non-{@link #isModifierKey(short) modifier} action key, otherwise <code>false</code>.
+ * <p>
+ * Hence it is the set A of all keys U w/o printable P and w/o modifiers M:
+ * <code> A = U - ( P + M ) </code>
+ * </p>
+ * @see #isPrintableKey()
+ * @see #isModifierKey()
*/
- public static final int VK_SLASH = 0x2F;
-
- /** VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */
- public static final int VK_0 = 0x30;
- public static final int VK_1 = 0x31;
- public static final int VK_2 = 0x32;
- public static final int VK_3 = 0x33;
- public static final int VK_4 = 0x34;
- public static final int VK_5 = 0x35;
- public static final int VK_6 = 0x36;
- public static final int VK_7 = 0x37;
- public static final int VK_8 = 0x38;
- public static final int VK_9 = 0x39;
+ public final boolean isActionKey() {
+ return 0 != ( F_ACTION_MASK & flags ) ;
+ }
/**
- * Constant for the semicolon key, ";"
- */
- public static final int VK_SEMICOLON = 0x3B;
+ * Returns <code>true</code> if given <code>uniChar</code> represents a printable character,
+ * i.e. a value other than {@link #VK_UNDEFINED} and not a control or non-printable private code.
+ * <p>
+ * A printable character is neither a {@link #isModifierKey(short) modifier key}, nor an {@link #isActionKey(short) action key}.
+ * </p>
+ * <p>
+ * Otherwise returns <code>false</code>.
+ * </p>
+ * <p>
+ * Distinction of key character and virtual key code is made due to <a href="#unicodeCollision">unicode collision</a>.
+ * </p>
+ *
+ * @param uniChar the UTF-16 unicode value, which maybe a virtual key code or key character.
+ * @param isKeyChar true if <code>uniChar</code> is a key character, otherwise a virtual key code
+ */
+ public static boolean isPrintableKey(final short uniChar, final boolean isKeyChar) {
+ if ( VK_BACK_SPACE == uniChar || VK_TAB == uniChar || VK_ENTER == uniChar ) {
+ return true;
+ }
+ if( !isKeyChar ) {
+ if( ( nonPrintableKeys[0].min <= uniChar && uniChar <= nonPrintableKeys[0].max ) ||
+ ( nonPrintableKeys[1].min <= uniChar && uniChar <= nonPrintableKeys[1].max ) ||
+ ( nonPrintableKeys[2].min <= uniChar && uniChar <= nonPrintableKeys[2].max ) ||
+ ( nonPrintableKeys[3].min <= uniChar && uniChar <= nonPrintableKeys[3].max ) ) {
+ return false;
+ }
+ } else {
+ if( ( nonPrintableKeys[0].inclKeyChar && nonPrintableKeys[0].min <= uniChar && uniChar <= nonPrintableKeys[0].max ) ||
+ ( nonPrintableKeys[1].inclKeyChar && nonPrintableKeys[1].min <= uniChar && uniChar <= nonPrintableKeys[1].max ) ||
+ ( nonPrintableKeys[2].inclKeyChar && nonPrintableKeys[2].min <= uniChar && uniChar <= nonPrintableKeys[2].max ) ||
+ ( nonPrintableKeys[3].inclKeyChar && nonPrintableKeys[3].min <= uniChar && uniChar <= nonPrintableKeys[3].max ) ) {
+ return false;
+ }
+ }
+ return VK_UNDEFINED != uniChar;
+ }
/**
- * Constant for the equals key, "="
+ * Returns <code>true</code> if {@link #getKeySymbol() key symbol} and {@link #getKeyChar() key char}
+ * represents a printable character, i.e. a value other than {@link #VK_UNDEFINED}
+ * and not a control or non-printable private code.
+ * <p>
+ * A printable character is neither a {@link #isModifierKey(short) modifier key}, nor an {@link #isActionKey(short) action key}.
+ * </p>
+ * <p>
+ * Otherwise returns <code>false</code>.
+ * </p>
*/
- public static final int VK_EQUALS = 0x3D;
-
- /** VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
- public static final int VK_A = 0x41;
- public static final int VK_B = 0x42;
- public static final int VK_C = 0x43;
- public static final int VK_D = 0x44;
- public static final int VK_E = 0x45;
- public static final int VK_F = 0x46;
- public static final int VK_G = 0x47;
- public static final int VK_H = 0x48;
- public static final int VK_I = 0x49;
- public static final int VK_J = 0x4A;
- public static final int VK_K = 0x4B;
- public static final int VK_L = 0x4C;
- public static final int VK_M = 0x4D;
- public static final int VK_N = 0x4E;
- public static final int VK_O = 0x4F;
- public static final int VK_P = 0x50;
- public static final int VK_Q = 0x51;
- public static final int VK_R = 0x52;
- public static final int VK_S = 0x53;
- public static final int VK_T = 0x54;
- public static final int VK_U = 0x55;
- public static final int VK_V = 0x56;
- public static final int VK_W = 0x57;
- public static final int VK_X = 0x58;
- public static final int VK_Y = 0x59;
- public static final int VK_Z = 0x5A;
+ public final boolean isPrintableKey() {
+ return 0 != ( F_PRINTABLE_MASK & flags ) ;
+ }
+
+ private final short keyCode;
+ private final short keySym;
+ private final char keyChar;
+ private final byte flags;
+ private static final byte F_MODIFIER_MASK = 1 << 0;
+ private static final byte F_ACTION_MASK = 1 << 1;
+ private static final byte F_PRINTABLE_MASK = 1 << 2;
+
+ /** A key has been pressed, excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys. */
+ public static final short EVENT_KEY_PRESSED = 300;
+ /** A key has been released, excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys. */
+ public static final short EVENT_KEY_RELEASED= 301;
/**
- * Constant for the open bracket key, "["
+ * This value, {@code '\0'}, is used to indicate that the keyChar is unknown or not printable.
*/
- public static final int VK_OPEN_BRACKET = 0x5B;
+ public static final char NULL_CHAR = '\0';
+ /* Virtual key codes. */
+
+ public static class NonPrintableRange {
+ /** min. unicode value, inclusive */
+ public short min;
+ /** max. unicode value, inclusive */
+ public short max;
+ /** true if valid for keyChar values as well, otherwise only valid for keyCode and keySym due to collision. */
+ public final boolean inclKeyChar;
+ private NonPrintableRange(final short min, final short max, final boolean inclKeyChar) {
+ this.min = min;
+ this.max = max;
+ this.inclKeyChar = inclKeyChar;
+ }
+ };
/**
- * Constant for the back slash key, "\"
+ * Non printable key ranges, currently fixed to an array of size 4.
+ * <p>
+ * Not included, queried upfront:
+ * <ul>
+ * <li>{@link #VK_BACK_SPACE}</li>
+ * <li>{@link #VK_TAB}</li>
+ * <li>{@link #VK_ENTER}</li>
+ * </ul>
+ * </p>
*/
- public static final int VK_BACK_SLASH = 0x5C;
+ public final static NonPrintableRange[] nonPrintableKeys = {
+ new NonPrintableRange( (short)0x0000, (short)0x001F, true ), // Unicode: Non printable controls: [0x00 - 0x1F], see exclusion above
+ new NonPrintableRange( (short)0x0061, (short)0x0078, false), // Small 'a' thru 'z' (0x61 - 0x7a) - Not used for keyCode / keySym - Re-used for Fn (collision)
+ new NonPrintableRange( (short)0x008F, (short)0x009F, true ), // Unicode: Non printable controls: [0x7F - 0x9F], Numpad keys [0x7F - 0x8E] are printable!
+ new NonPrintableRange( (short)0xE000, (short)0xF8FF, true ) // Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
+ };
+
+ //
+ // Unicode: Non printable controls: [0x00 - 0x1F]
+ //
/**
- * Constant for the close bracket key, "]"
+ * This value, {@value}, is used to indicate that the keyCode is unknown.
*/
- public static final int VK_CLOSE_BRACKET = 0x5D;
-
- public static final int VK_NUMPAD0 = 0x60;
- public static final int VK_NUMPAD1 = 0x61;
- public static final int VK_NUMPAD2 = 0x62;
- public static final int VK_NUMPAD3 = 0x63;
- public static final int VK_NUMPAD4 = 0x64;
- public static final int VK_NUMPAD5 = 0x65;
- public static final int VK_NUMPAD6 = 0x66;
- public static final int VK_NUMPAD7 = 0x67;
- public static final int VK_NUMPAD8 = 0x68;
- public static final int VK_NUMPAD9 = 0x69;
- public static final int VK_MULTIPLY = 0x6A;
- public static final int VK_ADD = 0x6B;
-
- /**
- * This constant is obsolete, and is included only for backwards
- * compatibility.
- * @see #VK_SEPARATOR
- */
- public static final int VK_SEPARATER = 0x6C;
+ public static final short VK_UNDEFINED = (short) 0x0;
- /**
- * Constant for the Numpad Separator key.
- * @since 1.4
- */
- public static final int VK_SEPARATOR = VK_SEPARATER;
+ static final short VK_FREE01 = (short) 0x01;
- public static final int VK_SUBTRACT = 0x6D;
- public static final int VK_DECIMAL = 0x6E;
- public static final int VK_DIVIDE = 0x6F;
- public static final int VK_DELETE = 0x7F; /* ASCII DEL */
- public static final int VK_NUM_LOCK = 0x90;
- public static final int VK_SCROLL_LOCK = 0x91;
+ /** Constant for the HOME function key. ASCII: Start Of Text. */
+ public static final short VK_HOME = (short) 0x02;
- /** Constant for the F1 function key. */
- public static final int VK_F1 = 0x70;
+ /** Constant for the END function key. ASCII: End Of Text. */
+ public static final short VK_END = (short) 0x03;
- /** Constant for the F2 function key. */
- public static final int VK_F2 = 0x71;
+ /** Constant for the END function key. ASCII: End Of Transmission. */
+ public static final short VK_FINAL = (short) 0x04;
- /** Constant for the F3 function key. */
- public static final int VK_F3 = 0x72;
+ /** Constant for the PRINT function key. ASCII: Enquiry. */
+ public static final short VK_PRINTSCREEN = (short) 0x05;
- /** Constant for the F4 function key. */
- public static final int VK_F4 = 0x73;
+ static final short VK_FREE06 = (short) 0x06;
+ static final short VK_FREE07 = (short) 0x07;
- /** Constant for the F5 function key. */
- public static final int VK_F5 = 0x74;
+ /** Constant for the BACK SPACE key "\b", matching ASCII. Printable! */
+ public static final short VK_BACK_SPACE = (short) 0x08;
- /** Constant for the F6 function key. */
- public static final int VK_F6 = 0x75;
+ /** Constant for the HORIZ TAB key "\t", matching ASCII. Printable! */
+ public static final short VK_TAB = (short) 0x09;
- /** Constant for the F7 function key. */
- public static final int VK_F7 = 0x76;
+ /** LINE_FEED "\n", matching ASCII, n/a on keyboard. */
+ static final short VK_FREE0A = (short) 0x0A;
- /** Constant for the F8 function key. */
- public static final int VK_F8 = 0x77;
+ /** Constant for the PAGE DOWN function key. ASCII: Vertical Tabulation. */
+ public static final short VK_PAGE_DOWN = (short) 0x0B;
- /** Constant for the F9 function key. */
- public static final int VK_F9 = 0x78;
+ /** Constant for the CLEAR key, i.e. FORM FEED, matching ASCII. */
+ public static final short VK_CLEAR = (short) 0x0C;
- /** Constant for the F10 function key. */
- public static final int VK_F10 = 0x79;
+ /** Constant for the ENTER key, i.e. CARRIAGE RETURN, matching ASCII. Printable! */
+ public static final short VK_ENTER = (short) 0x0D;
- /** Constant for the F11 function key. */
- public static final int VK_F11 = 0x7A;
+ static final short VK_FREE0E = (short) 0x0E;
- /** Constant for the F12 function key. */
- public static final int VK_F12 = 0x7B;
+ /** Constant for the CTRL function key. ASCII: shift-in. */
+ public static final short VK_SHIFT = (short) 0x0F;
- /**
- * Constant for the F13 function key.
- * @since 1.2
- */
- /* F13 - F24 are used on IBM 3270 keyboard; use random range for constants. */
- public static final int VK_F13 = 0xF000;
-
- /**
- * Constant for the F14 function key.
- * @since 1.2
- */
- public static final int VK_F14 = 0xF001;
-
- /**
- * Constant for the F15 function key.
- * @since 1.2
- */
- public static final int VK_F15 = 0xF002;
-
- /**
- * Constant for the F16 function key.
- * @since 1.2
- */
- public static final int VK_F16 = 0xF003;
-
- /**
- * Constant for the F17 function key.
- * @since 1.2
- */
- public static final int VK_F17 = 0xF004;
-
- /**
- * Constant for the F18 function key.
- * @since 1.2
- */
- public static final int VK_F18 = 0xF005;
-
- /**
- * Constant for the F19 function key.
- * @since 1.2
- */
- public static final int VK_F19 = 0xF006;
-
- /**
- * Constant for the F20 function key.
- * @since 1.2
- */
- public static final int VK_F20 = 0xF007;
-
- /**
- * Constant for the F21 function key.
- * @since 1.2
- */
- public static final int VK_F21 = 0xF008;
-
- /**
- * Constant for the F22 function key.
- * @since 1.2
- */
- public static final int VK_F22 = 0xF009;
-
- /**
- * Constant for the F23 function key.
- * @since 1.2
- */
- public static final int VK_F23 = 0xF00A;
-
- /**
- * Constant for the F24 function key.
- * @since 1.2
- */
- public static final int VK_F24 = 0xF00B;
-
- public static final int VK_PRINTSCREEN = 0x9A;
- public static final int VK_INSERT = 0x9B;
- public static final int VK_HELP = 0x9C;
- public static final int VK_META = 0x9D;
+ /** Constant for the PAGE UP function key. ASCII: Data Link Escape. */
+ public static final short VK_PAGE_UP = (short) 0x10;
- public static final int VK_BACK_QUOTE = 0xC0;
- public static final int VK_QUOTE = 0xDE;
+ /** Constant for the CTRL function key. ASCII: device-ctrl-one. */
+ public static final short VK_CONTROL = (short) 0x11;
- /**
- * Constant for the numeric keypad <b>up</b> arrow key.
- * @see #VK_UP
- * @since 1.2
- */
- public static final int VK_KP_UP = 0xE0;
+ /** Constant for the left ALT function key. ASCII: device-ctrl-two. */
+ public static final short VK_ALT = (short) 0x12;
- /**
- * Constant for the numeric keypad <b>down</b> arrow key.
- * @see #VK_DOWN
- * @since 1.2
- */
- public static final int VK_KP_DOWN = 0xE1;
+ /** Constant for the ALT_GRAPH function key, i.e. right ALT key. ASCII: device-ctrl-three. */
+ public static final short VK_ALT_GRAPH = (short) 0x13;
- /**
- * Constant for the numeric keypad <b>left</b> arrow key.
- * @see #VK_LEFT
- * @since 1.2
- */
- public static final int VK_KP_LEFT = 0xE2;
+ /** Constant for the CAPS LOCK function key. ASCII: device-ctrl-four. */
+ public static final short VK_CAPS_LOCK = (short) 0x14;
- /**
- * Constant for the numeric keypad <b>right</b> arrow key.
- * @see #VK_RIGHT
- * @since 1.2
- */
- public static final int VK_KP_RIGHT = 0xE3;
-
- /* For European keyboards */
- /** @since 1.2 */
- public static final int VK_DEAD_GRAVE = 0x80;
- /** @since 1.2 */
- public static final int VK_DEAD_ACUTE = 0x81;
- /** @since 1.2 */
- public static final int VK_DEAD_CIRCUMFLEX = 0x82;
- /** @since 1.2 */
- public static final int VK_DEAD_TILDE = 0x83;
- /** @since 1.2 */
- public static final int VK_DEAD_MACRON = 0x84;
- /** @since 1.2 */
- public static final int VK_DEAD_BREVE = 0x85;
- /** @since 1.2 */
- public static final int VK_DEAD_ABOVEDOT = 0x86;
- /** @since 1.2 */
- public static final int VK_DEAD_DIAERESIS = 0x87;
- /** @since 1.2 */
- public static final int VK_DEAD_ABOVERING = 0x88;
- /** @since 1.2 */
- public static final int VK_DEAD_DOUBLEACUTE = 0x89;
- /** @since 1.2 */
- public static final int VK_DEAD_CARON = 0x8a;
- /** @since 1.2 */
- public static final int VK_DEAD_CEDILLA = 0x8b;
- /** @since 1.2 */
- public static final int VK_DEAD_OGONEK = 0x8c;
- /** @since 1.2 */
- public static final int VK_DEAD_IOTA = 0x8d;
- /** @since 1.2 */
- public static final int VK_DEAD_VOICED_SOUND = 0x8e;
- /** @since 1.2 */
- public static final int VK_DEAD_SEMIVOICED_SOUND = 0x8f;
-
- /** @since 1.2 */
- public static final int VK_AMPERSAND = 0x96;
- /** @since 1.2 */
- public static final int VK_ASTERISK = 0x97;
- /** @since 1.2 */
- public static final int VK_QUOTEDBL = 0x98;
- /** @since 1.2 */
- public static final int VK_LESS = 0x99;
-
- /** @since 1.2 */
- public static final int VK_GREATER = 0xa0;
- /** @since 1.2 */
- public static final int VK_BRACELEFT = 0xa1;
- /** @since 1.2 */
- public static final int VK_BRACERIGHT = 0xa2;
+ static final short VK_FREE15 = (short) 0x15;
+
+ /** Constant for the PAUSE function key. ASCII: sync-idle. */
+ public static final short VK_PAUSE = (short) 0x16;
+
+ /** <b>scroll lock</b> key. ASCII: End Of Transmission Block. */
+ public static final short VK_SCROLL_LOCK = (short) 0x17;
+
+ /** Constant for the CANCEL function key. ASCII: Cancel. */
+ public static final short VK_CANCEL = (short) 0x18;
+
+ static final short VK_FREE19 = (short) 0x19;
+
+ /** Constant for the INSERT function key. ASCII: Substitute. */
+ public static final short VK_INSERT = (short) 0x1A;
+
+ /** Constant for the ESCAPE function key. ASCII: Escape. */
+ public static final short VK_ESCAPE = (short) 0x1B;
+
+ /** Constant for the Convert function key, Japanese "henkan". ASCII: File Separator. */
+ public static final short VK_CONVERT = (short) 0x1C;
+
+ /** Constant for the Don't Convert function key, Japanese "muhenkan". ASCII: Group Separator.*/
+ public static final short VK_NONCONVERT = (short) 0x1D;
+
+ /** Constant for the Accept or Commit function key, Japanese "kakutei". ASCII: Record Separator.*/
+ public static final short VK_ACCEPT = (short) 0x1E;
+
+ /** Constant for the Mode Change (?). ASCII: Unit Separator.*/
+ public static final short VK_MODECHANGE = (short) 0x1F;
+
+ //
+ // Unicode: Printable [0x20 - 0x7E]
+ // NOTE: Collision of 'a' - 'x' [0x61 .. 0x78], used for keyCode/keySym Fn function keys
+ //
+
+ /** Constant for the SPACE function key. ASCII: SPACE. */
+ public static final short VK_SPACE = (short) 0x20;
+
+ /** Constant for the "!" key. */
+ public static final short VK_EXCLAMATION_MARK = (short) 0x21;
+
+ /** Constant for the """ key. */
+ public static final short VK_QUOTEDBL = (short) 0x22;
+
+ /** Constant for the "#" key. */
+ public static final short VK_NUMBER_SIGN = (short) 0x23;
+
+ /** Constant for the "$" key. */
+ public static final short VK_DOLLAR = (short) 0x24;
+
+ /** Constant for the "%" key. */
+ public static final short VK_PERCENT = (short) 0x25;
+
+ /** Constant for the "&" key. */
+ public static final short VK_AMPERSAND = (short) 0x26;
+
+ /** Constant for the "'" key. */
+ public static final short VK_QUOTE = (short) 0x27;
+
+ /** Constant for the "(" key. */
+ public static final short VK_LEFT_PARENTHESIS = (short) 0x28;
+
+ /** Constant for the ")" key. */
+ public static final short VK_RIGHT_PARENTHESIS = (short) 0x29;
+
+ /** Constant for the "*" key */
+ public static final short VK_ASTERISK = (short) 0x2A;
+
+ /** Constant for the "+" key. */
+ public static final short VK_PLUS = (short) 0x2B;
+
+ /** Constant for the comma key, "," */
+ public static final short VK_COMMA = (short) 0x2C;
+
+ /** Constant for the minus key, "-" */
+ public static final short VK_MINUS = (short) 0x2D;
+
+ /** Constant for the period key, "." */
+ public static final short VK_PERIOD = (short) 0x2E;
+
+ /** Constant for the forward slash key, "/" */
+ public static final short VK_SLASH = (short) 0x2F;
+
+ /** VK_0 thru VK_9 are the same as UTF16/ASCII '0' thru '9' [0x30 - 0x39] */
+ public static final short VK_0 = (short) 0x30;
+ /** See {@link #VK_0}. */
+ public static final short VK_1 = (short) 0x31;
+ /** See {@link #VK_0}. */
+ public static final short VK_2 = (short) 0x32;
+ /** See {@link #VK_0}. */
+ public static final short VK_3 = (short) 0x33;
+ /** See {@link #VK_0}. */
+ public static final short VK_4 = (short) 0x34;
+ /** See {@link #VK_0}. */
+ public static final short VK_5 = (short) 0x35;
+ /** See {@link #VK_0}. */
+ public static final short VK_6 = (short) 0x36;
+ /** See {@link #VK_0}. */
+ public static final short VK_7 = (short) 0x37;
+ /** See {@link #VK_0}. */
+ public static final short VK_8 = (short) 0x38;
+ /** See {@link #VK_0}. */
+ public static final short VK_9 = (short) 0x39;
+
+ /** Constant for the ":" key. */
+ public static final short VK_COLON = (short) 0x3A;
+
+ /** Constant for the semicolon key, ";" */
+ public static final short VK_SEMICOLON = (short) 0x3B;
+
+ /** Constant for the equals key, "<" */
+ public static final short VK_LESS = (short) 0x3C;
+
+ /** Constant for the equals key, "=" */
+ public static final short VK_EQUALS = (short) 0x3D;
+
+ /** Constant for the equals key, ">" */
+ public static final short VK_GREATER = (short) 0x3E;
+
+ /** Constant for the equals key, "?" */
+ public static final short VK_QUESTIONMARK = (short) 0x3F;
+
+ /** Constant for the equals key, "@" */
+ public static final short VK_AT = (short) 0x40;
+
+ /** VK_A thru VK_Z are the same as Capital UTF16/ASCII 'A' thru 'Z' (0x41 - 0x5A) */
+ public static final short VK_A = (short) 0x41;
+ /** See {@link #VK_A}. */
+ public static final short VK_B = (short) 0x42;
+ /** See {@link #VK_A}. */
+ public static final short VK_C = (short) 0x43;
+ /** See {@link #VK_A}. */
+ public static final short VK_D = (short) 0x44;
+ /** See {@link #VK_A}. */
+ public static final short VK_E = (short) 0x45;
+ /** See {@link #VK_A}. */
+ public static final short VK_F = (short) 0x46;
+ /** See {@link #VK_A}. */
+ public static final short VK_G = (short) 0x47;
+ /** See {@link #VK_A}. */
+ public static final short VK_H = (short) 0x48;
+ /** See {@link #VK_A}. */
+ public static final short VK_I = (short) 0x49;
+ /** See {@link #VK_A}. */
+ public static final short VK_J = (short) 0x4A;
+ /** See {@link #VK_A}. */
+ public static final short VK_K = (short) 0x4B;
+ /** See {@link #VK_A}. */
+ public static final short VK_L = (short) 0x4C;
+ /** See {@link #VK_A}. */
+ public static final short VK_M = (short) 0x4D;
+ /** See {@link #VK_A}. */
+ public static final short VK_N = (short) 0x4E;
+ /** See {@link #VK_A}. */
+ public static final short VK_O = (short) 0x4F;
+ /** See {@link #VK_A}. */
+ public static final short VK_P = (short) 0x50;
+ /** See {@link #VK_A}. */
+ public static final short VK_Q = (short) 0x51;
+ /** See {@link #VK_A}. */
+ public static final short VK_R = (short) 0x52;
+ /** See {@link #VK_A}. */
+ public static final short VK_S = (short) 0x53;
+ /** See {@link #VK_A}. */
+ public static final short VK_T = (short) 0x54;
+ /** See {@link #VK_A}. */
+ public static final short VK_U = (short) 0x55;
+ /** See {@link #VK_A}. */
+ public static final short VK_V = (short) 0x56;
+ /** See {@link #VK_A}. */
+ public static final short VK_W = (short) 0x57;
+ /** See {@link #VK_A}. */
+ public static final short VK_X = (short) 0x58;
+ /** See {@link #VK_A}. */
+ public static final short VK_Y = (short) 0x59;
+ /** See {@link #VK_A}. */
+ public static final short VK_Z = (short) 0x5A;
+
+ /** Constant for the open bracket key, "[" */
+ public static final short VK_OPEN_BRACKET = (short) 0x5B;
+
+ /**Constant for the back slash key, "\" */
+ public static final short VK_BACK_SLASH = (short) 0x5C;
+
+ /** Constant for the close bracket key, "]" */
+ public static final short VK_CLOSE_BRACKET = (short) 0x5D;
+
+ /** Constant for the "^" key. */
+ public static final short VK_CIRCUMFLEX = (short) 0x5E;
+
+ /** Constant for the "_" key */
+ public static final short VK_UNDERSCORE = (short) 0x5F;
+
+ /** Constant for the "`" key */
+ public static final short VK_BACK_QUOTE = (short) 0x60;
+
+ /** Small UTF/ASCII 'a' thru 'z' (0x61 - 0x7a) - Not used for keyCode / keySym. */
+
+ /**
+ * Constant for the F<i>n</i> function keys.
+ * <p>
+ * F1..F24, i.e. F<i>n</i>, are mapped from on <code>0x60+n</code> -> <code>[0x61 .. 0x78]</code>.
+ * </p>
+ * <p>
+ * <b>Warning:</b> The F<i>n</i> function keys <b>do collide</b> with unicode characters small 'a' thru 'x'!<br/>
+ * See <a href="#unicodeCollision">Unicode Collision</a> for details.
+ * </p>
+ */
+ public static final short VK_F1 = (short) ( 0x60+ 1 );
+
+ /** Constant for the F2 function key. See {@link #VK_F1}. */
+ public static final short VK_F2 = (short) ( 0x60+ 2 );
+
+ /** Constant for the F3 function key. See {@link #VK_F1}. */
+ public static final short VK_F3 = (short) ( 0x60+ 3 );
+
+ /** Constant for the F4 function key. See {@link #VK_F1}. */
+ public static final short VK_F4 = (short) ( 0x60+ 4 );
+
+ /** Constant for the F5 function key. See {@link #VK_F1}. */
+ public static final short VK_F5 = (short) ( 0x60+ 5 );
+
+ /** Constant for the F6 function key. See {@link #VK_F1}. */
+ public static final short VK_F6 = (short) ( 0x60+ 6 );
+
+ /** Constant for the F7 function key. See {@link #VK_F1}. */
+ public static final short VK_F7 = (short) ( 0x60+ 7 );
+
+ /** Constant for the F8 function key. See {@link #VK_F1}. */
+ public static final short VK_F8 = (short) ( 0x60+ 8 );
+
+ /** Constant for the F9 function key. See {@link #VK_F1}. */
+ public static final short VK_F9 = (short) ( 0x60+ 9 );
+
+ /** Constant for the F11 function key. See {@link #VK_F1}. */
+ public static final short VK_F10 = (short) ( 0x60+10 );
+
+ /** Constant for the F11 function key. See {@link #VK_F1}. */
+ public static final short VK_F11 = (short) ( 0x60+11 );
+
+ /** Constant for the F12 function key. See {@link #VK_F1}.*/
+ public static final short VK_F12 = (short) ( 0x60+12 );
+
+ /** Constant for the F13 function key. See {@link #VK_F1}. */
+ public static final short VK_F13 = (short) ( 0x60+13 );
+
+ /** Constant for the F14 function key. See {@link #VK_F1}. */
+ public static final short VK_F14 = (short) ( 0x60+14 );
+
+ /** Constant for the F15 function key. See {@link #VK_F1}. */
+ public static final short VK_F15 = (short) ( 0x60+15 );
+
+ /** Constant for the F16 function key. See {@link #VK_F1}. */
+ public static final short VK_F16 = (short) ( 0x60+16 );
+
+ /** Constant for the F17 function key. See {@link #VK_F1}. */
+ public static final short VK_F17 = (short) ( 0x60+17 );
+
+ /** Constant for the F18 function key. See {@link #VK_F1}. */
+ public static final short VK_F18 = (short) ( 0x60+18 );
+
+ /** Constant for the F19 function key. See {@link #VK_F1}. */
+ public static final short VK_F19 = (short) ( 0x60+19 );
+
+ /** Constant for the F20 function key. See {@link #VK_F1}. */
+ public static final short VK_F20 = (short) ( 0x60+20 );
+
+ /** Constant for the F21 function key. See {@link #VK_F1}. */
+ public static final short VK_F21 = (short) ( 0x60+21 );
+
+ /** Constant for the F22 function key. See {@link #VK_F1}. */
+ public static final short VK_F22 = (short) ( 0x60+22 );
+
+ /** Constant for the F23 function key. See {@link #VK_F1}. */
+ public static final short VK_F23 = (short) ( 0x60+23 );
+
+ /** Constant for the F24 function key. See {@link #VK_F1}. */
+ public static final short VK_F24 = (short) ( 0x60+24 );
+
+
+ /** Constant for the "{" key */
+ public static final short VK_LEFT_BRACE = (short) 0x7B;
+ /** Constant for the "|" key */
+ public static final short VK_PIPE = (short) 0x7C;
+ /** Constant for the "}" key */
+ public static final short VK_RIGHT_BRACE = (short) 0x7D;
+
+ /** Constant for the "~" key, matching ASCII */
+ public static final short VK_TILDE = (short) 0x7E;
+
+ //
+ // Unicode: Non printable controls: [0x7F - 0x9F]
+ //
+ // Numpad keys [0x7F - 0x8E] are printable
+ //
+
+ /** Numeric keypad <b>decimal separator</b> key. Non printable UTF control. */
+ public static final short VK_SEPARATOR = (short) 0x7F;
+
+ /** Numeric keypad VK_NUMPAD0 thru VK_NUMPAD9 are mapped to UTF control (0x80 - 0x89). Non printable UTF control. */
+ public static final short VK_NUMPAD0 = (short) 0x80;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD1 = (short) 0x81;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD2 = (short) 0x82;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD3 = (short) 0x83;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD4 = (short) 0x84;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD5 = (short) 0x85;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD6 = (short) 0x86;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD7 = (short) 0x87;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD8 = (short) 0x88;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD9 = (short) 0x89;
+
+ /** Numeric keypad <b>decimal separator</b> key. Non printable UTF control. */
+ public static final short VK_DECIMAL = (short) 0x8A;
+
+ /** Numeric keypad <b>add</b> key. Non printable UTF control. */
+ public static final short VK_ADD = (short) 0x8B;
+
+ /** Numeric keypad <b>subtract</b> key. Non printable UTF control. */
+ public static final short VK_SUBTRACT = (short) 0x8C;
+
+ /** Numeric keypad <b>multiply</b> key. Non printable UTF control. */
+ public static final short VK_MULTIPLY = (short) 0x8D;
+
+ /** Numeric keypad <b>divide</b> key. Non printable UTF control. */
+ public static final short VK_DIVIDE = (short) 0x8E;
+
+ /** Constant for the DEL key, matching ASCII. Non printable UTF control. */
+ public static final short VK_DELETE = (short) 0x93;
+
+ /** Numeric keypad <b>num lock</b> key. Non printable UTF control. */
+ public static final short VK_NUM_LOCK = (short) 0x94;
+
+ /** Constant for the cursor- or numerical-pad <b>left</b> arrow key. Non printable UTF control. */
+ public static final short VK_LEFT = (short) 0x95;
+
+ /** Constant for the cursor- or numerical-pad <b>up</b> arrow key. Non printable UTF control. */
+ public static final short VK_UP = (short) 0x96;
+
+ /** Constant for the cursor- or numerical-pad <b>right</b> arrow key. Non printable UTF control. */
+ public static final short VK_RIGHT = (short) 0x97;
+
+ /** Constant for the cursor- or numerical pad <b>down</b> arrow key. Non printable UTF control. */
+ public static final short VK_DOWN = (short) 0x98;
+
+ /** Constant for the Context Menu key. Non printable UTF control. */
+ public static final short VK_CONTEXT_MENU = (short) 0x99;
/**
- * Constant for the "@" key.
- * @since 1.2
- */
- public static final int VK_AT = 0x0200;
-
- /**
- * Constant for the ":" key.
- * @since 1.2
- */
- public static final int VK_COLON = 0x0201;
-
- /**
- * Constant for the "^" key.
- * @since 1.2
- */
- public static final int VK_CIRCUMFLEX = 0x0202;
-
- /**
- * Constant for the "$" key.
- * @since 1.2
- */
- public static final int VK_DOLLAR = 0x0203;
-
- /**
- * Constant for the Euro currency sign key.
- * @since 1.2
- */
- public static final int VK_EURO_SIGN = 0x0204;
-
- /**
- * Constant for the "!" key.
- * @since 1.2
- */
- public static final int VK_EXCLAMATION_MARK = 0x0205;
-
- /**
- * Constant for the inverted exclamation mark key.
- * @since 1.2
- */
- public static final int VK_INVERTED_EXCLAMATION_MARK = 0x0206;
-
- /**
- * Constant for the "(" key.
- * @since 1.2
- */
- public static final int VK_LEFT_PARENTHESIS = 0x0207;
-
- /**
- * Constant for the "#" key.
- * @since 1.2
+ * Constant for the MS "Windows" function key.
+ * It is used for both the left and right version of the key.
*/
- public static final int VK_NUMBER_SIGN = 0x0208;
-
+ public static final short VK_WINDOWS = (short) 0x9A;
+
+ /** Constant for the Meta function key. */
+ public static final short VK_META = (short) 0x9B;
+
+ /** Constant for the Help function key. */
+ public static final short VK_HELP = (short) 0x9C;
+
+ /** Constant for the Compose function key. */
+ public static final short VK_COMPOSE = (short) 0x9D;
+
+ /** Constant for the Begin function key. */
+ public static final short VK_BEGIN = (short) 0x9E;
+
+ /** Constant for the Stop function key. */
+ public static final short VK_STOP = (short) 0x9F;
+
+ //
+ // Unicode: Printable [0x00A0 - 0xDFFF]
+ //
+
+ /** Constant for the inverted exclamation mark key. */
+ public static final short VK_INVERTED_EXCLAMATION_MARK = (short) 0xA1;
+
+ /** Constant for the Euro currency sign key. */
+ public static final short VK_EURO_SIGN = (short) 0x20AC;
+
+ //
+ // Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
+ //
+
+ /* for Sun keyboards */
+ public static final short VK_CUT = (short) 0xF879;
+ public static final short VK_COPY = (short) 0xF87A;
+ public static final short VK_PASTE = (short) 0xF87B;
+ public static final short VK_UNDO = (short) 0xF87C;
+ public static final short VK_AGAIN = (short) 0xF87D;
+ public static final short VK_FIND = (short) 0xF87E;
+ public static final short VK_PROPS = (short) 0xF87F;
+
+ /* for input method support on Asian Keyboards */
+
/**
- * Constant for the "+" key.
- * @since 1.2
+ * Constant for the input method on/off key.
*/
- public static final int VK_PLUS = 0x0209;
-
+ /* Japanese PC 106 keyboard: kanji. Japanese Solaris keyboard: nihongo */
+ public static final short VK_INPUT_METHOD_ON_OFF = (short) 0xF890;
+
/**
- * Constant for the ")" key.
- * @since 1.2
+ * Constant for the Code Input function key.
*/
- public static final int VK_RIGHT_PARENTHESIS = 0x020A;
-
+ /* Japanese PC 106 keyboard - VK_ALPHANUMERIC + ALT: kanji bangou */
+ public static final short VK_CODE_INPUT = (short) 0xF891;
+
/**
- * Constant for the "_" key.
- * @since 1.2
+ * Constant for the Roman Characters function key.
*/
- public static final int VK_UNDERSCORE = 0x020B;
-
+ /* Japanese PC 106 keyboard: roumaji */
+ public static final short VK_ROMAN_CHARACTERS = (short) 0xF892;
+
/**
- * Constant for the Microsoft Windows "Windows" key.
- * It is used for both the left and right version of the key.
- * @see #getKeyLocation()
- * @since 1.5
+ * Constant for the All Candidates function key.
*/
- public static final int VK_WINDOWS = 0x020C;
-
+ /* Japanese PC 106 keyboard - VK_CONVERT + ALT: zenkouho */
+ public static final short VK_ALL_CANDIDATES = (short) 0xF893;
+
/**
- * Constant for the Microsoft Windows Context Menu key.
- * @since 1.5
+ * Constant for the Previous Candidate function key.
*/
- public static final int VK_CONTEXT_MENU = 0x020D;
-
- /* for input method support on Asian Keyboards */
-
- /* not clear what this means - listed in Microsoft Windows API */
- public static final int VK_FINAL = 0x0018;
-
- /** Constant for the Convert function key. */
- /* Japanese PC 106 keyboard, Japanese Solaris keyboard: henkan */
- public static final int VK_CONVERT = 0x001C;
-
- /** Constant for the Don't Convert function key. */
- /* Japanese PC 106 keyboard: muhenkan */
- public static final int VK_NONCONVERT = 0x001D;
-
- /** Constant for the Accept or Commit function key. */
- /* Japanese Solaris keyboard: kakutei */
- public static final int VK_ACCEPT = 0x001E;
-
- /* not clear what this means - listed in Microsoft Windows API */
- public static final int VK_MODECHANGE = 0x001F;
-
- /* replaced by VK_KANA_LOCK for Microsoft Windows and Solaris;
- might still be used on other platforms */
- public static final int VK_KANA = 0x0015;
-
- /* replaced by VK_INPUT_METHOD_ON_OFF for Microsoft Windows and Solaris;
- might still be used for other platforms */
- public static final int VK_KANJI = 0x0019;
+ /* Japanese PC 106 keyboard - VK_CONVERT + SHIFT: maekouho */
+ public static final short VK_PREVIOUS_CANDIDATE = (short) 0xF894;
/**
* Constant for the Alphanumeric function key.
- * @since 1.2
*/
/* Japanese PC 106 keyboard: eisuu */
- public static final int VK_ALPHANUMERIC = 0x00F0;
-
+ public static final short VK_ALPHANUMERIC = (short) 0xF895;
+
/**
* Constant for the Katakana function key.
- * @since 1.2
*/
/* Japanese PC 106 keyboard: katakana */
- public static final int VK_KATAKANA = 0x00F1;
-
+ public static final short VK_KATAKANA = (short) 0xF896;
+
/**
* Constant for the Hiragana function key.
- * @since 1.2
*/
/* Japanese PC 106 keyboard: hiragana */
- public static final int VK_HIRAGANA = 0x00F2;
-
+ public static final short VK_HIRAGANA = (short) 0xF897;
+
/**
* Constant for the Full-Width Characters function key.
- * @since 1.2
*/
/* Japanese PC 106 keyboard: zenkaku */
- public static final int VK_FULL_WIDTH = 0x00F3;
-
+ public static final short VK_FULL_WIDTH = (short) 0xF898;
+
/**
* Constant for the Half-Width Characters function key.
- * @since 1.2
*/
/* Japanese PC 106 keyboard: hankaku */
- public static final int VK_HALF_WIDTH = 0x00F4;
-
- /**
- * Constant for the Roman Characters function key.
- * @since 1.2
- */
- /* Japanese PC 106 keyboard: roumaji */
- public static final int VK_ROMAN_CHARACTERS = 0x00F5;
-
- /**
- * Constant for the All Candidates function key.
- * @since 1.2
- */
- /* Japanese PC 106 keyboard - VK_CONVERT + ALT: zenkouho */
- public static final int VK_ALL_CANDIDATES = 0x0100;
-
- /**
- * Constant for the Previous Candidate function key.
- * @since 1.2
- */
- /* Japanese PC 106 keyboard - VK_CONVERT + SHIFT: maekouho */
- public static final int VK_PREVIOUS_CANDIDATE = 0x0101;
-
- /**
- * Constant for the Code Input function key.
- * @since 1.2
- */
- /* Japanese PC 106 keyboard - VK_ALPHANUMERIC + ALT: kanji bangou */
- public static final int VK_CODE_INPUT = 0x0102;
-
+ public static final short VK_HALF_WIDTH = (short) 0xF89A;
+
/**
* Constant for the Japanese-Katakana function key.
* This key switches to a Japanese input method and selects its Katakana input mode.
- * @since 1.2
*/
/* Japanese Macintosh keyboard - VK_JAPANESE_HIRAGANA + SHIFT */
- public static final int VK_JAPANESE_KATAKANA = 0x0103;
-
+ public static final short VK_JAPANESE_KATAKANA = (short) 0xF89B;
+
/**
* Constant for the Japanese-Hiragana function key.
* This key switches to a Japanese input method and selects its Hiragana input mode.
- * @since 1.2
*/
/* Japanese Macintosh keyboard */
- public static final int VK_JAPANESE_HIRAGANA = 0x0104;
-
+ public static final short VK_JAPANESE_HIRAGANA = (short) 0xF89C;
+
/**
* Constant for the Japanese-Roman function key.
* This key switches to a Japanese input method and selects its Roman-Direct input mode.
- * @since 1.2
*/
/* Japanese Macintosh keyboard */
- public static final int VK_JAPANESE_ROMAN = 0x0105;
+ public static final short VK_JAPANESE_ROMAN = (short) 0xF89D;
/**
* Constant for the locking Kana function key.
* This key locks the keyboard into a Kana layout.
- * @since 1.3
*/
/* Japanese PC 106 keyboard with special Windows driver - eisuu + Control; Japanese Solaris keyboard: kana */
- public static final int VK_KANA_LOCK = 0x0106;
-
- /**
- * Constant for the input method on/off key.
- * @since 1.3
- */
- /* Japanese PC 106 keyboard: kanji. Japanese Solaris keyboard: nihongo */
- public static final int VK_INPUT_METHOD_ON_OFF = 0x0107;
-
- /* for Sun keyboards */
- /** @since 1.2 */
- public static final int VK_CUT = 0xFFD1;
- /** @since 1.2 */
- public static final int VK_COPY = 0xFFCD;
- /** @since 1.2 */
- public static final int VK_PASTE = 0xFFCF;
- /** @since 1.2 */
- public static final int VK_UNDO = 0xFFCB;
- /** @since 1.2 */
- public static final int VK_AGAIN = 0xFFC9;
- /** @since 1.2 */
- public static final int VK_FIND = 0xFFD0;
- /** @since 1.2 */
- public static final int VK_PROPS = 0xFFCA;
- /** @since 1.2 */
- public static final int VK_STOP = 0xFFC8;
-
- /**
- * Constant for the Compose function key.
- * @since 1.2
- */
- public static final int VK_COMPOSE = 0xFF20;
-
- /**
- * Constant for the AltGraph function key.
- * @since 1.2
- */
- public static final int VK_ALT_GRAPH = 0xFF7E;
+ public static final short VK_KANA_LOCK = (short) 0xF89F;
/**
- * Constant for the Begin key.
- * @since 1.5
+ * Constant for Keyboard became invisible, e.g. Android's soft keyboard Back button hit while keyboard is visible.
*/
- public static final int VK_BEGIN = 0xFF58;
+ public static final short VK_KEYBOARD_INVISIBLE = (short) 0xF8FF;
- /**
- * This value is used to indicate that the keyCode is unknown.
- * KEY_TYPED events do not have a keyCode value; this value
- * is used instead.
- */
- public static final int VK_UNDEFINED = 0x0;
}
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyListener.java b/src/newt/classes/com/jogamp/newt/event/KeyListener.java
index dae343d80..4b16ab61e 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyListener.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,15 +29,33 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+/**
+ * Listener for {@link KeyEvent}s.
+ *
+ * @see KeyEvent
+ */
public interface KeyListener extends NEWTEventListener
{
- public void keyPressed(KeyEvent e);
- public void keyReleased(KeyEvent e);
- public void keyTyped(KeyEvent e) ;
+ /** A key has been {@link KeyEvent#EVENT_KEY_PRESSED pressed}, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. See {@link KeyEvent}. */
+ public void keyPressed(KeyEvent e);
+
+ /**
+ * A key has been {@link KeyEvent#EVENT_KEY_RELEASED released}, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. See {@link KeyEvent}.
+ * <p>
+ * To simulated the removed <code>keyTyped(KeyEvent e)</code> semantics,
+ * simply apply the following constraints upfront and bail out if not matched, i.e.:
+ * <pre>
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ * </pre>
+ * </p>
+ */
+ public void keyReleased(KeyEvent e);
}
diff --git a/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java b/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java
new file mode 100644
index 000000000..2e42f3392
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.newt.event;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+@SuppressWarnings("serial")
+public class MonitorEvent extends OutputEvent {
+ public static final short EVENT_MONITOR_MODE_CHANGE_NOTIFY = 600;
+ public static final short EVENT_MONITOR_MODE_CHANGED = 601;
+
+ private final MonitorMode mode;
+
+ public MonitorEvent (final short eventType, final MonitorDevice source, final long when, final MonitorMode mode) {
+ super(eventType, source, when);
+ this.mode = mode;
+ }
+
+ /** Returns the {@link #getSource() source}, which is a {@link MonitorDevice}. */
+ public final MonitorDevice getMonitor() { return (MonitorDevice)source; }
+
+ public final MonitorMode getMode() { return mode; }
+
+ public static String getEventTypeString(final short type) {
+ switch(type) {
+ case EVENT_MONITOR_MODE_CHANGE_NOTIFY: return "EVENT_MONITOR_MODE_CHANGE_NOTIFY";
+ case EVENT_MONITOR_MODE_CHANGED: return "EVENT_MONITOR_MODE_CHANGED";
+ default: return "unknown (" + type + ")";
+ }
+ }
+
+ @Override
+ public final String toString() {
+ return toString(null).toString();
+ }
+
+ @Override
+ public final StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("MonitorEvent[").append(getEventTypeString(getEventType())).append(", source ").append(source)
+ .append(", mode ").append(mode).append(", ");
+ return super.toString(sb).append("]");
+ }
+}
diff --git a/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java b/src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java
index 7bca23cfe..11e23def1 100644
--- a/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java
@@ -28,12 +28,10 @@
package com.jogamp.newt.event;
-import com.jogamp.newt.ScreenMode;
+public interface MonitorModeListener {
+ /** called before the monitor mode will be changed */
+ void monitorModeChangeNotify(MonitorEvent me);
-public interface ScreenModeListener {
- /** called before the screen mode will be changed */
- void screenModeChangeNotify(ScreenMode sm);
-
- /** called after the screen mode has been changed */
- void screenModeChanged(ScreenMode sm, boolean success);
+ /** called after the monitor mode has been changed */
+ void monitorModeChanged(MonitorEvent me, boolean success);
}
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseAdapter.java b/src/newt/classes/com/jogamp/newt/event/MouseAdapter.java
index 3607ae634..679155d10 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,31 +20,39 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event;
public abstract class MouseAdapter implements MouseListener
{
- public void mouseClicked(MouseEvent e) {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
}
- public void mouseEntered(MouseEvent e) {
+ @Override
+ public void mouseEntered(final MouseEvent e) {
}
- public void mouseExited(MouseEvent e) {
+ @Override
+ public void mouseExited(final MouseEvent e) {
}
- public void mousePressed(MouseEvent e) {
+ @Override
+ public void mousePressed(final MouseEvent e) {
}
- public void mouseReleased(MouseEvent e) {
+ @Override
+ public void mouseReleased(final MouseEvent e) {
}
- public void mouseMoved(MouseEvent e) {
+ @Override
+ public void mouseMoved(final MouseEvent e) {
}
- public void mouseDragged(MouseEvent e) {
+ @Override
+ public void mouseDragged(final MouseEvent e) {
}
- public void mouseWheelMoved(MouseEvent e) {
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
index d293d2db7..2d68c5788 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,192 +29,568 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+import java.util.Arrays;
+
+/**
+ * Pointer event of type {@link PointerType}.
+ * <p>
+ * The historical misleading class name may change in the future to <code>PointerEvent</code>.
+ * </p>
+ * <p>
+ * http://www.w3.org/Submission/pointer-events/#pointerevent-interface
+ * </p>
+ * <a name="coordUnit"><h5>Unit of Coordinates</h5></a>
+ * <p>
+ * All pointer coordinates of this interface are represented in pixel units,
+ * see {@link NativeSurface} and {@link NativeWindow}.
+ * </p>
+ * <a name="multiPtrEvent"><h5>Multiple-Pointer Events</h5></a>
+ * <p>
+ * In case an instance represents a multiple-pointer event, i.e. {@link #getPointerCount()} is &gt; 1,
+ * the first data element of the multiple-pointer fields represents the pointer triggering this event.<br/>
+ * For example {@link #getX(int) e.getX(0)} at {@link #EVENT_MOUSE_PRESSED} returns the data of the pressed pointer, etc.
+ * </p>
+ * <p>
+ * Multiple-pointer event's {@link #getButton() button number} is mapped to the <i>first {@link #getPointerId(int) pointer ID}</i>
+ * triggering the event and the {@link InputEvent#BUTTON1_MASK button mask bits} in the {@link #getModifiers() modifiers}
+ * field represent the pressed pointer IDs.
+ * </p>
+ * <p>
+ * Users can query the pressed button and pointer count via {@link InputEvent#getButtonDownCount()}
+ * or use the simple query {@link InputEvent#isAnyButtonDown()}.
+ * </p>
+ * <p>
+ * If representing a single-pointer {@link PointerType#Mouse} event, {@link #getPointerId(int) pointer-ID} is <code>0</code>
+ * and a {@link #getButton() button value} of <code>0</code> denotes no button activity, i.e. {@link PointerType#Mouse} move.
+ * </p>
+ */
@SuppressWarnings("serial")
public class MouseEvent extends InputEvent
{
+ /** Class of pointer types */
+ public static enum PointerClass implements InputEvent.InputClass {
+ Offscreen, Onscreen, Undefined;
+ }
+
+ /** Type of pointer devices */
+ public static enum PointerType implements InputEvent.InputType {
+ /** {@link PointerClass#Offscreen} mouse. Ordinal 0. */
+ Mouse(PointerClass.Offscreen),
+ /** {@link PointerClass#Offscreen} touch pad, usually using fingers. Ordinal 1. */
+ TouchPad(PointerClass.Offscreen),
+ /** {@link PointerClass#Onscreen} touch screen, usually using fingers. Ordinal 2. */
+ TouchScreen(PointerClass.Onscreen),
+ /** {@link PointerClass#Onscreen} pen usually on screen? Ordinal 3. FIXME*/
+ Pen(PointerClass.Onscreen),
+ /** {@link PointerClass#Undefined} ?. Ordinal 4. */
+ Undefined(PointerClass.Undefined);
+
+ public PointerClass getPointerClass() { return pc; }
+
+ /**
+ * Returns the matching PointerType value corresponding to the given PointerType's integer ordinal.
+ * <pre>
+ * given:
+ * ordinal = enumValue.ordinal()
+ * reverse:
+ * enumValue = EnumClass.values()[ordinal]
+ * </pre>
+ * @throws IllegalArgumentException if the given ordinal is out of range, i.e. not within [ 0 .. PointerType.values().length-1 ]
+ */
+ public static PointerType valueOf(final int ordinal) throws IllegalArgumentException {
+ final PointerType[] all = PointerType.values();
+ if( 0 <= ordinal && ordinal < all.length ) {
+ return all[ordinal];
+ }
+ throw new IllegalArgumentException("Ordinal "+ordinal+" out of range of PointerType.values()[0.."+(all.length-1)+"]");
+ }
+
+ /**
+ * Returns the PointerType array of matching PointerType values corresponding to the given PointerType's integer ordinal values.
+ * <p>
+ * See {@link #valueOf(int)}.
+ * </p>
+ * @throws IllegalArgumentException if one of the given ordinal values is out of range, i.e. not within [ 0 .. PointerType.values().length-1 ]
+ */
+ public static PointerType[] valuesOf(final int[] ordinals) throws IllegalArgumentException {
+ final int count = ordinals.length;
+ final PointerType[] types = new PointerType[count];
+ for(int i=count-1; i>=0; i--) {
+ types[i] = PointerType.valueOf(ordinals[i]);
+ }
+ return types;
+ }
+
+ private PointerType(final PointerClass pc) {
+ this.pc = pc;
+ }
+ PointerClass pc;
+ }
+
/** ID for button 1, value <code>1</code> */
- public static final int BUTTON1 = 1;
+ public static final short BUTTON1 = 1;
/** ID for button 2, value <code>2</code> */
- public static final int BUTTON2 = 2;
+ public static final short BUTTON2 = 2;
/** ID for button 3, value <code>3</code> */
- public static final int BUTTON3 = 3;
+ public static final short BUTTON3 = 3;
/** ID for button 4, value <code>4</code> */
- public static final int BUTTON4 = 4;
+ public static final short BUTTON4 = 4;
/** ID for button 5, value <code>5</code> */
- public static final int BUTTON5 = 5;
+ public static final short BUTTON5 = 5;
/** ID for button 6, value <code>6</code> */
- public static final int BUTTON6 = 6;
- /** Number of buttons, value <code>6</code> */
- public static final int BUTTON_NUMBER = 6;
+ public static final short BUTTON6 = 6;
+ /** ID for button 6, value <code>7</code> */
+ public static final short BUTTON7 = 7;
+ /** ID for button 6, value <code>8</code> */
+ public static final short BUTTON8 = 8;
+ /** ID for button 6, value <code>9</code> */
+ public static final short BUTTON9 = 9;
- public static final int getClickTimeout() {
- return 300;
+ /** Maximum number of buttons, value <code>16</code> */
+ public static final short BUTTON_COUNT = 16;
+
+ /** Returns the 3-axis XYZ rotation array by given rotation on Y axis or X axis (if SHIFT_MASK is given in mods). */
+ public static final float[] getRotationXYZ(final float rotationXorY, final int mods) {
+ final float[] rotationXYZ = new float[] { 0f, 0f, 0f };
+ if( 0 != ( mods & InputEvent.SHIFT_MASK ) ) {
+ rotationXYZ[0] = rotationXorY;
+ } else {
+ rotationXYZ[1] = rotationXorY;
+ }
+ return rotationXYZ;
}
- public MouseEvent(int eventType, Object source, long when,
- int modifiers, int x, int y, int clickCount, int button,
- int rotation)
+ public static final short getClickTimeout() {
+ return 300;
+ }
+
+ /**
+ * Constructor for traditional one-pointer event.
+ *
+ * @param eventType
+ * @param source
+ * @param when
+ * @param modifiers
+ * @param x X-axis
+ * @param y Y-axis
+ * @param clickCount Mouse-button click-count
+ * @param button button number, e.g. [{@link #BUTTON1}..{@link #BUTTON_COUNT}-1].
+ * A button value of <code>0</code> denotes no button activity, i.e. {@link PointerType#Mouse} move.
+ * @param rotationXYZ Rotation of all axis
+ * @param rotationScale Rotation scale
+ */
+ public MouseEvent(final short eventType, final Object source, final long when,
+ final int modifiers, final int x, final int y, final short clickCount, final short button,
+ final float[] rotationXYZ, final float rotationScale)
{
- super(eventType, source, when, modifiers);
+ super(eventType, source, when, modifiers);
this.x = new int[]{x};
this.y = new int[]{y};
- this.pressure = new float[]{0};
- this.pointerids = new int[]{-1};
+ switch(eventType) {
+ case EVENT_MOUSE_CLICKED:
+ case EVENT_MOUSE_PRESSED:
+ case EVENT_MOUSE_DRAGGED:
+ this.pressure = constMousePressure1;
+ break;
+ default:
+ this.pressure = constMousePressure0;
+ }
+ this.maxPressure= 1.0f;
+ this.pointerID = new short[] { (short)0 };
this.clickCount=clickCount;
this.button=button;
- this.wheelRotation = rotation;
+ this.rotationXYZ = rotationXYZ;
+ this.rotationScale = rotationScale;
+ this.pointerType = constMousePointerTypes;
}
- public MouseEvent(int eventType, Object source, long when,
- int modifiers, int[] x, int[] y, float[] pressure, int[] pointerids, int clickCount, int button,
- int rotation)
+ /**
+ * Constructor for a multiple-pointer event.
+ * <p>
+ * First element of multiple-pointer arrays represents the pointer which triggered the event!
+ * </p>
+ * <p>
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * </p>
+ *
+ * @param eventType
+ * @param source
+ * @param when
+ * @param modifiers
+ * @param pointerType PointerType for each pointer (multiple pointer)
+ * @param pointerID Pointer ID for each pointer (multiple pointer). IDs start w/ 0 and are consecutive numbers.
+ * A pointer-ID of -1 may also denote no pointer/button activity, i.e. {@link PointerType#Mouse} move.
+ * @param x X-axis for each pointer (multiple pointer)
+ * @param y Y-axis for each pointer (multiple pointer)
+ * @param pressure Pressure for each pointer (multiple pointer)
+ * @param maxPressure Maximum pointer pressure for all pointer
+ * @param button Corresponding mouse-button
+ * @param clickCount Mouse-button click-count
+ * @param rotationXYZ Rotation of all axis
+ * @param rotationScale Rotation scale
+ */
+ public MouseEvent(final short eventType, final Object source, final long when, final int modifiers,
+ final PointerType pointerType[], final short[] pointerID,
+ final int[] x, final int[] y, final float[] pressure, final float maxPressure,
+ final short button, final short clickCount, final float[] rotationXYZ, final float rotationScale)
{
- super(eventType, source, when, modifiers);
+ super(eventType, source, when, modifiers);
this.x = x;
this.y = y;
- if(pointerids.length != pressure.length ||
- pointerids.length != x.length ||
- pointerids.length != y.length) {
+ final int pointerCount = pointerType.length;
+ if(pointerCount != pointerID.length ||
+ pointerCount != x.length ||
+ pointerCount != y.length ||
+ pointerCount != pressure.length) {
throw new IllegalArgumentException("All multiple pointer arrays must be of same size");
}
+ if( 0.0f >= maxPressure ) {
+ throw new IllegalArgumentException("maxPressure must be > 0.0f");
+ }
this.pressure = pressure;
- this.pointerids = pointerids;
+ this.maxPressure= maxPressure;
+ this.pointerID = pointerID;
this.clickCount=clickCount;
this.button=button;
- this.wheelRotation = rotation;
+ this.rotationXYZ = rotationXYZ;
+ this.rotationScale = rotationScale;
+ this.pointerType = pointerType;
}
-
+
+ public final MouseEvent createVariant(final short newEventType) {
+ return new MouseEvent(newEventType, source, getWhen(), getModifiers(), pointerType, pointerID,
+ x, y, pressure, maxPressure, button, clickCount, rotationXYZ, rotationScale);
+ }
+
/**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
* @return the count of pointers involved in this event
*/
- public int getPointerCount() {
- return x.length;
+ public final int getPointerCount() {
+ return pointerType.length;
+ }
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return the {@link PointerType} for the data at index or null if index not available.
+ */
+ public final PointerType getPointerType(final int index) {
+ if(0 > index || index >= pointerType.length) {
+ return null;
+ }
+ return pointerType[index];
}
-
+
/**
- * @return the pointer id for the data at index.
- * return -1 if index not available.
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return array of all {@link PointerType}s for all pointers
*/
- public int getPointerId(int index) {
- if(index >= pointerids.length)
+ public final PointerType[] getAllPointerTypes() {
+ return pointerType;
+ }
+
+ /**
+ * Return the pointer id for the given index or -1 if index not available.
+ * <p>
+ * IDs start w/ 0 and are consecutive numbers.
+ * </p>
+ * <p>
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * </p>
+ */
+ public final short getPointerId(final int index) {
+ if(0 > index || index >= pointerID.length) {
return -1;
- return pointerids[index];
+ }
+ return pointerID[index];
}
-
- public int getButton() {
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return the pointer index for the given pointer id or -1 if id not available.
+ */
+ public final int getPointerIdx(final short id) {
+ if( id >= 0 ) {
+ for(int i=pointerID.length-1; i>=0; i--) {
+ if( pointerID[i] == id ) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return array of all pointer IDs for all pointers. IDs start w/ 0 and are consecutive numbers.
+ */
+ public final short[] getAllPointerIDs() {
+ return pointerID;
+ }
+
+ /**
+ * Returns the button number, e.g. [{@link #BUTTON1}..{@link #BUTTON_COUNT}-1].
+ * <p>
+ * A button value of <code>0</code> denotes no button activity, i.e. {@link PointerType#Mouse} move.
+ * </p>
+ * <p>
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * </p>
+ */
+ public final short getButton() {
return button;
}
-
- public int getClickCount() {
+
+ public final short getClickCount() {
return clickCount;
}
- public int getX() {
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return X-Coord of the triggering pointer-index zero in pixel units.
+ */
+ public final int getX() {
return x[0];
}
-
- public int getY() {
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return Y-Coord of the triggering pointer-index zero in pixel units.
+ */
+ public final int getY() {
return y[0];
}
- /**
- * @return x-coord at index where index refers to the
- * data coming from a pointer.
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @param index pointer-index within [0 .. {@link #getPointerCount()}-1]
+ * @return X-Coord associated with the pointer-index in pixel units.
* @see getPointerId(index)
*/
- public int getX(int index) {
+ public final int getX(final int index) {
return x[index];
}
- public int getY(int index) {
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @param index pointer-index within [0 .. {@link #getPointerCount()}-1]
+ * @return Y-Coord associated with the pointer-index in pixel units.
+ * @see getPointerId(index)
+ */
+ public final int getY(final int index) {
return y[index];
}
-
- public float getPressure(){
- return pressure[0];
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return array of all X-Coords for all pointers in pixel units.
+ */
+ public final int[] getAllX() {
+ return x;
}
-
+
/**
- * @return the pressure associated with the pointer at index.
- * the value of zero is return if not available.
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return array of all Y-Coords for all pointers in pixel units.
+ */
+ public final int[] getAllY() {
+ return y;
+ }
+
+ /**
+ * @param normalized if true, method returns the normalized pressure, i.e. <code>pressure / maxPressure</code>
+ * @return The pressure associated with the pointer-index 0.
+ * The value of zero is return if not available.
+ * @see #getMaxPressure()
+ */
+ public final float getPressure(final boolean normalized){
+ return normalized ? pressure[0] / maxPressure : pressure[0];
+ }
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @param index pointer-index within [0 .. {@link #getPointerCount()}-1]
+ * @param normalized if true, method returns the normalized pressure, i.e. <code>pressure / maxPressure</code>
+ * @return The pressure associated with the pointer-index.
+ * The value of zero is return if not available.
+ * @see #getMaxPressure()
+ */
+ public final float getPressure(final int index, final boolean normalized){
+ return normalized ? pressure[index] / maxPressure : pressure[index];
+ }
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return array of all raw, un-normalized pressures for all pointers
+ */
+ public final float[] getAllPressures() {
+ return pressure;
+ }
+
+ /**
+ * Returns the maximum pressure known for the input device generating this event.
+ * <p>
+ * This value may be self calibrating on devices/OS, where no known maximum pressure is known.
+ * Hence subsequent events may return a higher value.
+ * </p>
+ * <p>
+ * Self calibrating maximum pressure is performed on:
+ * <ul>
+ * <li>Android</li>
+ * </ul>
+ * </p>
*/
- public float getPressure(int index){
- return pressure[index];
+ public final float getMaxPressure() {
+ return maxPressure;
}
-
+
/**
- * <i>Usually</i> a wheel rotation of <b>&gt; 0 is up</b>,
- * and <b>&lt; 0 is down</b>.<br>
+ * Returns a 3-component float array filled with the values of the rotational axis
+ * in the following order: horizontal-, vertical- and z-axis.
+ * <p>
+ * A vertical rotation of <b>&gt; 0.0f is up</b> and <b>&lt; 0.0f is down</b>.
+ * </p>
+ * <p>
+ * A horizontal rotation of <b>&gt; 0.0f is left</b> and <b>&lt; 0.0f is right</b>.
+ * </p>
+ * <p>
+ * A z-axis rotation of <b>&gt; 0.0f is back</b> and <b>&lt; 0.0f is front</b>.
+ * </p>
+ * <p>
* <i>However</i>, on some OS this might be flipped due to the OS <i>default</i> behavior.
* The latter is true for OS X 10.7 (Lion) for example.
+ * </p>
+ * <p>
+ * On PointerClass {@link PointerClass#Onscreen onscreen} devices, i.e. {@link PointerType#TouchScreen touch screens},
+ * rotation events are usually produced by a 2-finger movement, where horizontal and vertical rotation values are filled.
+ * </p>
+ * <p>
+ * On PointerClass {@link PointerClass#Offscreen offscreen} devices, i.e. {@link PointerType#Mouse mouse},
+ * either the horizontal or the vertical rotation value is filled.
+ * </p>
+ * <p>
+ * The {@link InputEvent#SHIFT_MASK} modifier is set in case <b>|horizontal| &gt; |vertical|</b> value.<br/>
+ * This can be utilized to implement only one 2d rotation direction, you may use {@link #isShiftDown()} to query it.
+ * </p>
* <p>
- * The events will be send usually in steps of one, ie. <i>-1</i> and <i>1</i>.
+ * In case the pointer type is {@link PointerType#Mouse mouse},
+ * events are usually send in steps of one, ie. <i>-1.0f</i> and <i>1.0f</i>.
* Higher values may result due to fast scrolling.
+ * Fractional values may result due to slow scrolling with high resolution devices.<br/>
+ * Here the button number refers to the wheel number.
* </p>
* <p>
- * The button number refers to the wheel number.
- * </p>
- * @return
+ * In case the pointer type is of class {@link PointerClass#Onscreen}, e.g. {@link PointerType#TouchScreen touch screen},
+ * see {@link #getRotationScale()} for semantics.
+ * </p>
*/
- public int getWheelRotation() {
- return wheelRotation;
+ public final float[] getRotation() {
+ return rotationXYZ;
}
- public String toString() {
+ /**
+ * Returns the scale used to determine the {@link #getRotation() rotation value},
+ * which semantics depends on the {@link #getPointerType() pointer type's} {@link PointerClass}.
+ * <p>
+ * For {@link PointerClass#Offscreen}, the scale is usually <code>1.0f</code> and denominates
+ * an abstract value without association to a physical value.
+ * </p>
+ * <p>
+ * For {@link PointerClass#Onscreen}, the scale varies and denominates
+ * the divisor of the distance the finger[s] have moved on the screen.
+ * Hence <code>scale * rotation</code> reproduces the screen distance in pixels the finger[s] have moved.
+ * </p>
+ */
+ public final float getRotationScale() {
+ return rotationScale;
+ }
+
+ @Override
+ public final String toString() {
return toString(null).toString();
}
- public StringBuilder toString(StringBuilder sb) {
+ @Override
+ public final StringBuilder toString(StringBuilder sb) {
if(null == sb) {
sb = new StringBuilder();
}
sb.append("MouseEvent[").append(getEventTypeString(getEventType()))
- .append(", ").append(x).append("/").append(y)
+ .append(", ").append(Arrays.toString(x)).append("/").append(Arrays.toString(y))
.append(", button ").append(button).append(", count ")
- .append(clickCount).append(", wheel rotation ").append(wheelRotation);
- if(pointerids.length>0) {
- sb.append(", pointer<").append(pointerids.length).append(">[");
- for(int i=0; i<pointerids.length; i++) {
+ .append(clickCount).append(", rotation [").append(rotationXYZ[0]).append(", ").append(rotationXYZ[1]).append(", ").append(rotationXYZ[2]).append("] * ").append(rotationScale);
+ if(pointerID.length>0) {
+ sb.append(", pointer<").append(pointerID.length).append(">[");
+ for(int i=0; i<pointerID.length; i++) {
if(i>0) {
sb.append(", ");
}
- sb.append(pointerids[i]).append(": ")
- .append(x[i]).append(" / ").append(y[i]).append(" ")
- .append(pressure[i]).append("p");
+ sb.append(pointerID[i]).append("/").append(pointerType[i]).append(": ")
+ .append(x[i]).append("/").append(y[i]).append(", ")
+ .append("p[").append(pressure[i]).append("/").append(maxPressure).append("=").append(pressure[i]/maxPressure).append("]");
}
sb.append("]");
- }
+ }
sb.append(", ");
return super.toString(sb).append("]");
}
- public static String getEventTypeString(int type) {
+ public static String getEventTypeString(final short type) {
switch(type) {
- case EVENT_MOUSE_CLICKED: return "EVENT_MOUSE_CLICKED";
- case EVENT_MOUSE_ENTERED: return "EVENT_MOUSE_ENTERED";
- case EVENT_MOUSE_EXITED: return "EVENT_MOUSE_EXITED";
- case EVENT_MOUSE_PRESSED: return "EVENT_MOUSE_PRESSED";
- case EVENT_MOUSE_RELEASED: return "EVENT_MOUSE_RELEASED";
- case EVENT_MOUSE_MOVED: return "EVENT_MOUSE_MOVED";
- case EVENT_MOUSE_DRAGGED: return "EVENT_MOUSE_DRAGGED";
- case EVENT_MOUSE_WHEEL_MOVED: return "EVENT_MOUSE_WHEEL_MOVED";
- default: return "unknown (" + type + ")";
+ case EVENT_MOUSE_CLICKED: return "EVENT_MOUSE_CLICKED";
+ case EVENT_MOUSE_ENTERED: return "EVENT_MOUSE_ENTERED";
+ case EVENT_MOUSE_EXITED: return "EVENT_MOUSE_EXITED";
+ case EVENT_MOUSE_PRESSED: return "EVENT_MOUSE_PRESSED";
+ case EVENT_MOUSE_RELEASED: return "EVENT_MOUSE_RELEASED";
+ case EVENT_MOUSE_MOVED: return "EVENT_MOUSE_MOVED";
+ case EVENT_MOUSE_DRAGGED: return "EVENT_MOUSE_DRAGGED";
+ case EVENT_MOUSE_WHEEL_MOVED: return "EVENT_MOUSE_WHEEL_MOVED";
+ default: return "unknown (" + type + ")";
}
}
- private final int x[], y[], clickCount, button, wheelRotation;
+
+ /** PointerType for each pointer (multiple pointer) */
+ private final PointerType pointerType[];
+ /** Pointer-ID for each pointer (multiple pointer). IDs start w/ 0 and are consecutive numbers. */
+ private final short pointerID[];
+ /** X-axis for each pointer (multiple pointer) */
+ private final int x[];
+ /** Y-axis for each pointer (multiple pointer) */
+ private final int y[];
+ /** Pressure for each pointer (multiple pointer) */
private final float pressure[];
- private final int pointerids[];
-
- public static final int EVENT_MOUSE_CLICKED = 200;
- public static final int EVENT_MOUSE_ENTERED = 201;
- public static final int EVENT_MOUSE_EXITED = 202;
- public static final int EVENT_MOUSE_PRESSED = 203;
- public static final int EVENT_MOUSE_RELEASED = 204;
- public static final int EVENT_MOUSE_MOVED = 205;
- public static final int EVENT_MOUSE_DRAGGED = 206;
- public static final int EVENT_MOUSE_WHEEL_MOVED = 207;
+ // private final short tiltX[], tiltY[]; // TODO: A generic way for pointer axis information, see Android MotionEvent!
+ private final short clickCount;
+ /**
+ * Returns the button number, e.g. [{@link #BUTTON1}..{@link #BUTTON_COUNT}-1].
+ * <p>
+ * A button value of <code>0</code> denotes no button activity, i.e. {@link PointerType#Mouse} move.
+ * </p>
+ */
+ private final short button;
+ /** Rotation around the X, Y and X axis */
+ private final float[] rotationXYZ;
+ /** Rotation scale */
+ private final float rotationScale;
+ private final float maxPressure;
+
+ private static final float[] constMousePressure0 = new float[]{0f};
+ private static final float[] constMousePressure1 = new float[]{1f};
+ private static final PointerType[] constMousePointerTypes = new PointerType[] { PointerType.Mouse };
+
+ public static final short EVENT_MOUSE_CLICKED = 200;
+ /** Only generated for {@link PointerType#Mouse} */
+ public static final short EVENT_MOUSE_ENTERED = 201;
+ /** Only generated for {@link PointerType#Mouse} */
+ public static final short EVENT_MOUSE_EXITED = 202;
+ public static final short EVENT_MOUSE_PRESSED = 203;
+ public static final short EVENT_MOUSE_RELEASED = 204;
+ public static final short EVENT_MOUSE_MOVED = 205;
+ public static final short EVENT_MOUSE_DRAGGED = 206;
+ public static final short EVENT_MOUSE_WHEEL_MOVED = 207;
}
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseListener.java b/src/newt/classes/com/jogamp/newt/event/MouseListener.java
index 7668b755c..5e62306f3 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseListener.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,22 +29,37 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+import com.jogamp.newt.event.MouseEvent.PointerType;
+
+/**
+ * Listener for {@link MouseEvent}s.
+ *
+ * @see MouseEvent
+ */
public interface MouseListener extends NEWTEventListener
{
- public void mouseClicked(MouseEvent e);
- public void mouseEntered(MouseEvent e);
- public void mouseExited(MouseEvent e);
- public void mousePressed(MouseEvent e);
- public void mouseReleased(MouseEvent e);
- public void mouseMoved(MouseEvent e);
- public void mouseDragged(MouseEvent e);
-
- /** See {@link MouseEvent#getWheelRotation() } */
- public void mouseWheelMoved(MouseEvent e);
+ public void mouseClicked(MouseEvent e);
+ /** Only generated for {@link PointerType#Mouse} */
+ public void mouseEntered(MouseEvent e);
+ /** Only generated for {@link PointerType#Mouse} */
+ public void mouseExited(MouseEvent e);
+ public void mousePressed(MouseEvent e);
+ public void mouseReleased(MouseEvent e);
+ public void mouseMoved(MouseEvent e);
+ public void mouseDragged(MouseEvent e);
+
+ /**
+ * Traditional event name originally produced by a {@link PointerType#Mouse mouse} pointer type.
+ * <p>
+ * Triggered for any rotational pointer events, see
+ * {@link MouseEvent#getRotation()} and {@link MouseEvent#getRotationScale()}.
+ * </p>
+ */
+ public void mouseWheelMoved(MouseEvent e);
}
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
index fd5b69ccc..a9d9d8bdb 100644
--- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
@@ -41,88 +41,35 @@ package com.jogamp.newt.event;
*
* Event type registry:<br>
* <ul>
- * <li> WindowEvent <code>100..10x</code></li>
- * <li> MouseEvent <code>200..20x</code></li>
- * <li> KeyEvent <code>300..30x</code></li>
+ * <li> WindowEvent <code>100..10x</code></li>
+ * <li> MouseEvent <code>200..20x</code></li>
+ * <li> KeyEvent <code>300..30x</code></li>
+ * <li> GestureEvent <code>400..5xx</code></li>
+ * <li> MonitorEvent <code>600..60x</code></li>
* </ul><br>
*/
@SuppressWarnings("serial")
public class NEWTEvent extends java.util.EventObject {
- private final boolean isSystemEvent;
- private final int eventType;
+ /**
+ * See {@link #setConsumed(boolean)} for description.
+ */
+ public static final Object consumedTag = new Object();
+
+ private final short eventType;
private final long when;
private Object attachment;
static final boolean DEBUG = false;
- // 0: NEWTEvent.java
- // 1: InputEvent.java
- // 2: KeyEvent.java
- // 3: com.jogamp.newt.Window
- // 3: com.jogamp.newt.event.awt.AWTNewtEventFactory
- // 2: MouseEvent.java
- // 3: com.jogamp.newt.Window
- // 3: com.jogamp.newt.event.awt.AWTNewtEventFactory
- // 1: WindowEvent.java
- // 2: com.jogamp.newt.Window
- // 2: com.jogamp.newt.event.awt.AWTNewtEventFactory
- //
- // FIXME: verify the isSystemEvent evaluation
- //
- static final String WindowClazzName = "com.jogamp.newt.Window" ;
- static final String AWTNewtEventFactoryClazzName = "com.jogamp.newt.event.awt.AWTNewtEventFactory" ;
-
- /**
- static final boolean evaluateIsSystemEvent(NEWTEvent event, Throwable t) {
- StackTraceElement[] stack = t.getStackTrace();
- if(stack.length==0 || null==stack[0]) {
- return false;
- }
- if(DEBUG) {
- for (int i = 0; i < stack.length && i<5; i++) {
- System.err.println(i+": " + stack[i].getClassName()+ "." + stack[i].getMethodName());
- }
- }
-
- String clazzName = null;
-
- if( event instanceof com.jogamp.newt.event.WindowEvent ) {
- if ( stack.length > 2 ) {
- clazzName = stack[2].getClassName();
- }
- } else if( (event instanceof com.jogamp.newt.event.MouseEvent) ||
- (event instanceof com.jogamp.newt.event.KeyEvent) ) {
- if ( stack.length > 3 ) {
- clazzName = stack[3].getClassName();
- }
- }
-
- boolean res = null!=clazzName && (
- clazzName.equals(WindowClazzName) ||
- clazzName.equals(AWTNewtEventFactoryClazzName) ) ;
- if(DEBUG) {
- System.err.println("system: "+res);
- }
- return res;
- } */
-
- protected NEWTEvent(int eventType, Object source, long when) {
+ protected NEWTEvent(final short eventType, final Object source, final long when) {
super(source);
- // this.isSystemEvent = evaluateIsSystemEvent(this, new Throwable());
- this.isSystemEvent = false; // FIXME: Need a more efficient way to determine system events
this.eventType = eventType;
this.when = when;
this.attachment=null;
}
- /** Indicates whether this event was produced by the system or
- generated by user code. */
- public final boolean isSystemEvent() {
- return isSystemEvent;
- }
-
/** Returns the event type of this event. */
- public final int getEventType() {
+ public final short getEventType() {
return eventType;
}
@@ -131,25 +78,60 @@ public class NEWTEvent extends java.util.EventObject {
return when;
}
- /**
+ /**
* Attach the passed object to this event.<br>
* If an object was previously attached, it will be replaced.<br>
* Attachments to NEWT events allow users to pass on information
- * from one custom listener to another, ie custom listener to listener
+ * from one custom listener to another, ie custom listener to listener
* communication.
* @param attachment User application specific object
*/
- public final void setAttachment(Object attachment) {
- this.attachment=attachment;
+ public final void setAttachment(final Object attachment) {
+ this.attachment = attachment;
}
- /**
+ /**
* @return The user application specific attachment, or null
*/
public final Object getAttachment() {
return attachment;
}
+ /**
+ * Returns <code>true</code> if this events has been {@link #setConsumed(boolean) consumed},
+ * otherwise <code>false</code>.
+ * @see #setConsumed(boolean)
+ */
+ public final boolean isConsumed() {
+ return consumedTag == attachment;
+ }
+
+ /**
+ * If <code>consumed</code> is <code>true</code>, this event is marked as consumed,
+ * ie. the event will not be propagated any further to potential <i>other</i> event listener.
+ * Otherwise the event will be propagated to other event listener, the default.
+ * <p>
+ * The event is marked as being consumed while {@link #setAttachment(Object) attaching}
+ * the {@link #consumedTag}.
+ * </p>
+ * <p>
+ * Events with platform specific actions will be supressed if marked as consumed.
+ * Examples are:
+ * <ul>
+ * <li>{@link KeyEvent#VK_ESCAPE} on Android's BACK button w/ Activity::finish()</li>
+ * <li>{@link KeyEvent#VK_HOME} on Android's HOME button w/ Intend.ACTION_MAIN[Intend.CATEGORY_HOME]</li>
+ * </ul>
+ * </p>
+ */
+ public final void setConsumed(final boolean consumed) {
+ if( consumed ) {
+ setAttachment( consumedTag );
+ } else if( consumedTag == attachment ) {
+ setAttachment( null );
+ }
+ }
+
+ @Override
public String toString() {
return toString(null).toString();
}
@@ -158,14 +140,10 @@ public class NEWTEvent extends java.util.EventObject {
if(null == sb) {
sb = new StringBuilder();
}
- return sb.append("NEWTEvent[sys:").append(isSystemEvent()).append(", source:").append(getSource().getClass().getName()).append(", when:").append(getWhen()).append(" d ").append((System.currentTimeMillis()-getWhen())).append("ms]");
- }
-
- public static String toHexString(int hex) {
- return "0x" + Integer.toHexString(hex);
+ return sb.append("NEWTEvent[source:").append(getSource().getClass().getName()).append(", consumed ").append(isConsumed()).append(", when:").append(getWhen()).append(" d ").append((System.currentTimeMillis()-getWhen())).append("ms]");
}
- public static String toHexString(long hex) {
- return "0x" + Long.toHexString(hex);
+ public static String toHexString(final short hex) {
+ return "0x" + Integer.toHexString( hex & 0x0000FFFF );
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java b/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java
index 6aa19e5f8..14fba6742 100644
--- a/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java
+++ b/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,18 +20,18 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event;
public interface NEWTEventConsumer {
- /**
- * Consume the event
+ /**
+ * Consume the event
*
* @return true if the event has been consumed,
* otherwise it returns false for later propagation.
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEventFiFo.java b/src/newt/classes/com/jogamp/newt/event/NEWTEventFiFo.java
index fe224bba6..dd6395354 100644
--- a/src/newt/classes/com/jogamp/newt/event/NEWTEventFiFo.java
+++ b/src/newt/classes/com/jogamp/newt/event/NEWTEventFiFo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,22 +20,22 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event;
import java.util.LinkedList;
public class NEWTEventFiFo
{
- private LinkedList/*<NEWTEvent>*/ events = new LinkedList/*<NEWTEvent>*/();
+ private final LinkedList/*<NEWTEvent>*/ events = new LinkedList/*<NEWTEvent>*/();
/** Add NEWTEvent to tail */
- public synchronized void put(NEWTEvent event) {
+ public synchronized void put(final NEWTEvent event) {
events.addLast(event);
notifyAll();
}
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEventListener.java b/src/newt/classes/com/jogamp/newt/event/NEWTEventListener.java
index 677136573..f7ee3d739 100644
--- a/src/newt/classes/com/jogamp/newt/event/NEWTEventListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/NEWTEventListener.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
diff --git a/src/newt/classes/com/jogamp/newt/event/OutputEvent.java b/src/newt/classes/com/jogamp/newt/event/OutputEvent.java
new file mode 100644
index 000000000..bd3a11a13
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/OutputEvent.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.newt.event;
+
+@SuppressWarnings("serial")
+public abstract class OutputEvent extends NEWTEvent
+{
+ protected OutputEvent(final short eventType, final Object source, final long when) {
+ super(eventType, source, when);
+ }
+
+ /**
+ public String toString() {
+ return toString(null).toString();
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("OutputEvent[");
+ super.toString(sb).append("]");
+ return sb;
+ } */
+}
diff --git a/src/newt/classes/com/jogamp/newt/event/PinchToZoomGesture.java b/src/newt/classes/com/jogamp/newt/event/PinchToZoomGesture.java
new file mode 100644
index 000000000..9c7a4bcb8
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/PinchToZoomGesture.java
@@ -0,0 +1,252 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.newt.event;
+
+import javax.media.nativewindow.NativeSurface;
+
+import com.jogamp.newt.event.MouseEvent.PointerClass;
+
+import jogamp.newt.Debug;
+
+/**
+ * 2 pointer zoom, a.k.a. <i>pinch to zoom</i>, gesture handler processing {@link MouseEvent}s
+ * while producing {@link ZoomEvent}s if gesture is completed.
+ * <p>
+ * Zoom value lies within [0..2], with 1 as <i>1:1</i>.
+ * </p>
+ * <pre>
+ * - choosing the smallest surface edge (width/height -> x/y)
+ * - tolerating other fingers to be pressed and hence user to add functionality (scale, ..)
+ * </pre>
+ */
+public class PinchToZoomGesture implements GestureHandler {
+ public static final boolean DEBUG = Debug.debug("Window.MouseEvent");
+
+ /** A {@link GestureHandler.GestureEvent} denominating zoom. */
+ @SuppressWarnings("serial")
+ public static class ZoomEvent extends GestureEvent {
+ private final float zoom;
+ private final float delta;
+ private final float scale;
+ public ZoomEvent(final Object source, final long when, final int modifiers, final GestureHandler handler, final MouseEvent pe,
+ final float zoom, final float delta, final float scale) {
+ super(source, when, modifiers, handler, pe);
+ this.zoom = zoom;
+ this.delta = delta;
+ this.scale = scale;
+ }
+ /** Zoom value lies within [0..2], with 1 as <i>1:1</i>. */
+ public final float getZoom() { return zoom; }
+ /** Delta to last zoom value lies within [-1..1]. */
+ public final float getDelta() { return delta; }
+ /**
+ * Returns the scale used to determine the {@link #getZoom() zoom}
+ * and hence it's {@link #getDelta() delta} value,
+ * which semantics depends on the {@link #getPointerType() pointer type's} {@link PointerClass}.
+ * <p>
+ * For {@link PointerClass#Offscreen}, the scale is usually <code>1.0f</code> and denominates
+ * an abstract value without association to a physical value.
+ * </p>
+ * <p>
+ * For {@link PointerClass#Onscreen}, the scale varies and denominates
+ * the divisor of the distance the finger[s] have moved on the screen.
+ * Hence <code>scale * delta</code> reproduces the screen distance in pixels the finger[s] have moved.
+ * </p>
+ */
+ public final float getScale() { return scale; }
+
+ public final String toString() {
+ return "ZoomEvent[zoom "+zoom+", delta "+delta+", scale "+scale+", trigger "+getTrigger()+", handler "+getHandler()+"]";
+ }
+ }
+
+ private final NativeSurface surface;
+ private final boolean allowMorePointer;
+ private float zoom;
+ private int zoomLastEdgeDist;
+ private boolean zoomFirstTouch;
+ private boolean zoomMode;
+ private ZoomEvent zoomEvent;
+ private final short[] pIds = new short[] { -1, -1 };
+
+ /**
+ * @param surface the {@link NativeSurface}, which size is used to compute the relative zoom factor
+ * @param allowMorePointer if false, allow only 2 pressed pointers (safe and recommended), otherwise accept other pointer to be pressed.
+ */
+ public PinchToZoomGesture(final NativeSurface surface, final boolean allowMorePointer) {
+ clear(true);
+ this.surface = surface;
+ this.allowMorePointer = allowMorePointer;
+ this.zoom = 1f;
+ }
+
+ @Override
+ public String toString() {
+ return "PinchZoom[1stTouch "+zoomFirstTouch+", in "+isWithinGesture()+", has "+(null!=zoomEvent)+", zoom "+zoom+"]";
+ }
+
+ private int gesturePointers(final MouseEvent e, final int excludeIndex) {
+ int j = 0;
+ for(int i=e.getPointerCount()-1; i>=0; i--) {
+ if( excludeIndex != i ) {
+ final int id = e.getPointerId(i);
+ if( pIds[0] == id || pIds[1] == id ) {
+ j++;
+ }
+ }
+ }
+ return j;
+ }
+
+ @Override
+ public void clear(final boolean clearStarted) {
+ zoomEvent = null;
+ if( clearStarted ) {
+ zoomLastEdgeDist = 0;
+ zoomFirstTouch = true;
+ zoomMode = false;
+ pIds[0] = -1;
+ pIds[1] = -1;
+ }
+ }
+
+ @Override
+ public boolean isWithinGesture() {
+ return zoomMode;
+ }
+
+ @Override
+ public boolean hasGesture() {
+ return null != zoomEvent;
+ }
+
+ @Override
+ public InputEvent getGestureEvent() {
+ return zoomEvent;
+ }
+
+ /** Zoom value lies within [0..2], with 1 as <i>1:1</i>. */
+ public final float getZoom() {
+ return zoom;
+ }
+ /** Set zoom value within [0..2], with 1 as <i>1:1</i>. */
+ public final void setZoom(final float zoom) {
+ this.zoom=zoom;
+ }
+
+ @Override
+ public boolean process(final InputEvent in) {
+ if( null != zoomEvent || !(in instanceof MouseEvent) ) {
+ return true;
+ }
+ final MouseEvent pe = (MouseEvent)in;
+ final int pointerDownCount = pe.getPointerCount();
+
+ if( pe.getPointerType(0).getPointerClass() != MouseEvent.PointerClass.Onscreen ||
+ ( !allowMorePointer && pointerDownCount > 2 ) ) {
+ return false;
+ }
+
+ final int eventType = pe.getEventType();
+ final boolean useY = surface.getSurfaceWidth() >= surface.getSurfaceHeight(); // use smallest dimension
+ switch ( eventType ) {
+ case MouseEvent.EVENT_MOUSE_PRESSED: {
+ if( 1 == pointerDownCount ) {
+ pIds[0] = pe.getPointerId(0);
+ pIds[1] = -1;
+ } else if ( 2 <= pointerDownCount ) { // && 1 == gesturePointers(pe, 0) /* w/o pressed pointer */) {
+ pIds[0] = pe.getPointerId(0);
+ pIds[1] = pe.getPointerId(1);
+ }
+ if(DEBUG) {
+ System.err.println("XXX1: id0 "+pIds[0]+" -> idx0 "+0+", id1 "+pIds[1]+" -> idx1 "+1);
+ System.err.println(this+".pressed: down "+pointerDownCount+", gPtr "+gesturePointers(pe, -1)+", event "+pe);
+ }
+ } break;
+
+ case MouseEvent.EVENT_MOUSE_RELEASED: {
+ final int gPtr = gesturePointers(pe, 0); // w/o lifted pointer
+ if ( 1 == gPtr ) {
+ zoomFirstTouch = true;
+ zoomMode = false;
+ } else if( 0 == gPtr ) {
+ // all lifted
+ clear(true);
+ }
+ if(DEBUG) {
+ System.err.println(this+".released: down "+pointerDownCount+", gPtr "+gPtr+", event "+pe);
+ }
+ } break;
+
+ case MouseEvent.EVENT_MOUSE_DRAGGED: {
+ if( 2 <= pointerDownCount ) {
+ final int gPtr = gesturePointers(pe, -1);
+ if( 2 == gPtr ) {
+ // same pointers
+ final int p0Idx = pe.getPointerIdx(pIds[0]);
+ final int p1Idx = pe.getPointerIdx(pIds[1]);
+ if( 0 <= p0Idx && 0 <= p1Idx ) {
+ final int edge0 = useY ? pe.getY(p0Idx) : pe.getX(p0Idx);
+ final int edge1 = useY ? pe.getY(p1Idx) : pe.getX(p1Idx);
+ // Diff. 1:1 Zoom: finger-distance to screen-coord
+ if(zoomFirstTouch) {
+ zoomLastEdgeDist = Math.abs(edge0-edge1);
+ zoomFirstTouch=false;
+ zoomMode = true;
+ } else if( zoomMode ) {
+ final int d = Math.abs(edge0-edge1);
+ final int dd = d - zoomLastEdgeDist;
+ final float screenEdge = useY ? surface.getSurfaceHeight() : surface.getSurfaceWidth();
+ final float delta = dd / screenEdge; // [-1..1]
+ if(DEBUG) {
+ System.err.println("XXX2: id0 "+pIds[0]+" -> idx0 "+p0Idx+", id1 "+pIds[1]+" -> idx1 "+p1Idx);
+ System.err.println("XXX3: d "+d+", ld "+zoomLastEdgeDist+", dd "+dd+", screen "+screenEdge+" -> incr "+delta+", zoom "+zoom+" -> "+(zoom+delta));
+ }
+ zoom += delta;
+ // clip value
+ if( 2f < zoom ) {
+ zoom = 2f;
+ } else if( 0 > zoom ) {
+ zoom = 0;
+ }
+ zoomLastEdgeDist = d;
+ zoomEvent = new ZoomEvent(pe.getSource(), pe.getWhen(), pe.getModifiers(), this, pe, zoom, delta, screenEdge);
+ }
+ }
+ }
+ if(DEBUG) {
+ System.err.println(this+".dragged: down "+pointerDownCount+", gPtr "+gPtr+", event "+pe);
+ }
+ }
+ } break;
+
+ default:
+ }
+ return null != zoomEvent;
+ }
+}
diff --git a/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
index 98ba5a24d..50eae9626 100644
--- a/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event;
public class TraceKeyAdapter implements KeyListener {
@@ -36,21 +36,19 @@ public class TraceKeyAdapter implements KeyListener {
this.downstream = null;
}
- public TraceKeyAdapter(KeyListener downstream) {
+ public TraceKeyAdapter(final KeyListener downstream) {
this.downstream = downstream;
}
- public void keyPressed(KeyEvent e) {
+ @Override
+ public void keyPressed(final KeyEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.keyPressed(e); }
}
- public void keyReleased(KeyEvent e) {
+ @Override
+ public void keyReleased(final KeyEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.keyReleased(e); }
}
- public void keyTyped(KeyEvent e) {
- System.err.println(e);
- if(null!=downstream) { downstream.keyTyped(e); }
- }
}
diff --git a/src/newt/classes/com/jogamp/newt/event/TraceMouseAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceMouseAdapter.java
index 14ee633a0..e54c3730f 100644
--- a/src/newt/classes/com/jogamp/newt/event/TraceMouseAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/TraceMouseAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event;
public class TraceMouseAdapter implements MouseListener {
@@ -36,39 +36,47 @@ public class TraceMouseAdapter implements MouseListener {
this.downstream = null;
}
- public TraceMouseAdapter(MouseListener downstream) {
+ public TraceMouseAdapter(final MouseListener downstream) {
this.downstream = downstream;
}
- public void mouseClicked(MouseEvent e) {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseClicked(e); }
}
- public void mouseEntered(MouseEvent e) {
+ @Override
+ public void mouseEntered(final MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseEntered(e); }
}
- public void mouseExited(MouseEvent e) {
+ @Override
+ public void mouseExited(final MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseExited(e); }
}
- public void mousePressed(MouseEvent e) {
+ @Override
+ public void mousePressed(final MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mousePressed(e); }
}
- public void mouseReleased(MouseEvent e) {
+ @Override
+ public void mouseReleased(final MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseReleased(e); }
}
- public void mouseMoved(MouseEvent e) {
+ @Override
+ public void mouseMoved(final MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseMoved(e); }
}
- public void mouseDragged(MouseEvent e) {
+ @Override
+ public void mouseDragged(final MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseDragged(e); }
}
- public void mouseWheelMoved(MouseEvent e) {
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseWheelMoved(e); }
}
diff --git a/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java
index 8542820c4..299a6ff90 100644
--- a/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event;
public class TraceWindowAdapter implements WindowListener {
@@ -36,35 +36,42 @@ public class TraceWindowAdapter implements WindowListener {
this.downstream = null;
}
- public TraceWindowAdapter(WindowListener downstream) {
+ public TraceWindowAdapter(final WindowListener downstream) {
this.downstream = downstream;
}
- public void windowResized(WindowEvent e) {
+ @Override
+ public void windowResized(final WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowResized(e); }
}
- public void windowMoved(WindowEvent e) {
+ @Override
+ public void windowMoved(final WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowMoved(e); }
}
- public void windowDestroyNotify(WindowEvent e) {
+ @Override
+ public void windowDestroyNotify(final WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowDestroyNotify(e); }
}
- public void windowDestroyed(WindowEvent e) {
+ @Override
+ public void windowDestroyed(final WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowDestroyed(e); }
}
- public void windowGainedFocus(WindowEvent e) {
+ @Override
+ public void windowGainedFocus(final WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowGainedFocus(e); }
}
- public void windowLostFocus(WindowEvent e) {
+ @Override
+ public void windowLostFocus(final WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowLostFocus(e); }
}
- public void windowRepaint(WindowUpdateEvent e) {
+ @Override
+ public void windowRepaint(final WindowUpdateEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowRepaint(e); }
}
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java
index b9e487e9b..c1bae40ea 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,28 +20,35 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event;
public abstract class WindowAdapter implements WindowListener
{
- public void windowResized(WindowEvent e) {
+ @Override
+ public void windowResized(final WindowEvent e) {
}
- public void windowMoved(WindowEvent e) {
+ @Override
+ public void windowMoved(final WindowEvent e) {
}
- public void windowDestroyNotify(WindowEvent e) {
+ @Override
+ public void windowDestroyNotify(final WindowEvent e) {
}
- public void windowDestroyed(WindowEvent e) {
+ @Override
+ public void windowDestroyed(final WindowEvent e) {
}
- public void windowGainedFocus(WindowEvent e) {
+ @Override
+ public void windowGainedFocus(final WindowEvent e) {
}
- public void windowLostFocus(WindowEvent e) {
+ @Override
+ public void windowLostFocus(final WindowEvent e) {
}
- public void windowRepaint(WindowUpdateEvent e) {
+ @Override
+ public void windowRepaint(final WindowUpdateEvent e) {
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowEvent.java b/src/newt/classes/com/jogamp/newt/event/WindowEvent.java
index 163b51439..021bd6cae 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowEvent.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
@@ -41,19 +41,19 @@ package com.jogamp.newt.event;
*/
@SuppressWarnings("serial")
public class WindowEvent extends NEWTEvent {
- public static final int EVENT_WINDOW_RESIZED = 100;
- public static final int EVENT_WINDOW_MOVED = 101;
- public static final int EVENT_WINDOW_DESTROY_NOTIFY = 102;
- public static final int EVENT_WINDOW_GAINED_FOCUS = 103;
- public static final int EVENT_WINDOW_LOST_FOCUS = 104;
- public static final int EVENT_WINDOW_REPAINT = 105;
- public static final int EVENT_WINDOW_DESTROYED = 106;
+ public static final short EVENT_WINDOW_RESIZED = 100;
+ public static final short EVENT_WINDOW_MOVED = 101;
+ public static final short EVENT_WINDOW_DESTROY_NOTIFY = 102;
+ public static final short EVENT_WINDOW_GAINED_FOCUS = 103;
+ public static final short EVENT_WINDOW_LOST_FOCUS = 104;
+ public static final short EVENT_WINDOW_REPAINT = 105;
+ public static final short EVENT_WINDOW_DESTROYED = 106;
- public WindowEvent(int eventType, Object source, long when) {
+ public WindowEvent(final short eventType, final Object source, final long when) {
super(eventType, source, when);
}
- public static String getEventTypeString(int type) {
+ public static String getEventTypeString(final short type) {
switch(type) {
case EVENT_WINDOW_RESIZED: return "WINDOW_RESIZED";
case EVENT_WINDOW_MOVED: return "WINDOW_MOVED";
@@ -65,11 +65,13 @@ public class WindowEvent extends NEWTEvent {
default: return "unknown (" + type + ")";
}
}
-
+
+ @Override
public String toString() {
return toString(null).toString();
}
+ @Override
public StringBuilder toString(StringBuilder sb) {
if(null == sb) {
sb = new StringBuilder();
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowListener.java b/src/newt/classes/com/jogamp/newt/event/WindowListener.java
index e841a06cf..e097edf23 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowListener.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,14 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+import javax.media.nativewindow.WindowClosingProtocol;
+
+/** NEWT {@link WindowEvent} listener. */
public interface WindowListener extends NEWTEventListener {
/** Window is resized, your application shall respect the new window dimension. A repaint is recommended. */
public void windowResized(WindowEvent e);
@@ -41,10 +44,19 @@ public interface WindowListener extends NEWTEventListener {
/** Window has been moved. */
public void windowMoved(WindowEvent e);
- /** Window will be destroyed. Release of resources is recommended. */
+ /**
+ * Window destruction has been requested.
+ * <p>
+ * Depending on the {@link WindowClosingProtocol#getDefaultCloseOperation() default close operation},
+ * the window maybe destroyed or not.
+ * </p>
+ * In case the window will be destroyed (see above), release of resources is recommended.
+ **/
public void windowDestroyNotify(WindowEvent e);
- /** Window has been destroyed.*/
+ /**
+ * Window has been destroyed.
+ */
public void windowDestroyed(WindowEvent e);
/** Window gained focus. */
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java b/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
index e3f0373ec..4a5fecd83 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event;
import javax.media.nativewindow.util.Rectangle;
@@ -34,7 +34,7 @@ import javax.media.nativewindow.util.Rectangle;
public class WindowUpdateEvent extends WindowEvent {
final Rectangle bounds;
- public WindowUpdateEvent(int eventType, Object source, long when, Rectangle bounds)
+ public WindowUpdateEvent(final short eventType, final Object source, final long when, final Rectangle bounds)
{
super(eventType, source, when);
this.bounds = bounds;
@@ -44,10 +44,12 @@ public class WindowUpdateEvent extends WindowEvent {
return bounds;
}
+ @Override
public String toString() {
return toString(null).toString();
}
+ @Override
public StringBuilder toString(StringBuilder sb) {
if(null == sb) {
sb = new StringBuilder();
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java
index 8991203d5..a49c10a1e 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,14 +20,16 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event.awt;
+import javax.media.nativewindow.NativeSurfaceHolder;
+
import jogamp.newt.Debug;
/**
@@ -48,10 +50,10 @@ import jogamp.newt.Debug;
* Common:<br>
* <pre>
// your demo/render code
- javax.media.opengl.GLEvenListener demo1 = new javax.media.opengl.GLEvenListener() { ... } ;
+ javax.media.opengl.GLEvenListener demo1 = new javax.media.opengl.GLEvenListener() { ... } ;
// your AWT agnostic NEWT mouse listener code
- com.jogamp.newt.event.MouseListener mouseListener = new com.jogamp.newt.event.MouseAdapter() { ... } ;
+ com.jogamp.newt.event.MouseListener mouseListener = new com.jogamp.newt.event.MouseAdapter() { ... } ;
* </pre> </p>
* <p>
* Default NEWT use case, without using the AWTAdapter:<br>
@@ -96,7 +98,7 @@ import jogamp.newt.Debug;
<br>
new AWTMouseAdapter(mouseListener, glWindow).addTo(comp);<br>
* </pre> </p>
- *
+ *
* Last but not least, the AWTAdapter maybe used as a general AWT event forwarder to NEWT.<br>
*
* <p>
@@ -108,7 +110,7 @@ import jogamp.newt.Debug;
<br>
new AWTMouseAdapter(glWindow).addTo(comp); // forward all AWT events to glWindow, as NEWT events<br>
* </pre> </p>
- *
+ *
* @see #attachTo
*/
public abstract class AWTAdapter implements java.util.EventListener
@@ -117,60 +119,138 @@ public abstract class AWTAdapter implements java.util.EventListener
com.jogamp.newt.event.NEWTEventListener newtListener;
com.jogamp.newt.Window newtWindow;
+ NativeSurfaceHolder nsHolder;
+ boolean consumeAWTEvent;
+ protected boolean isSetup;
- /**
- * Simply wrap aroung a NEWT EventListener, exposed as an AWT EventListener.<br>
+ /**
+ * Create a proxy adapter, wrapping around an NEWT EventListener, exposed as an AWT EventListener,<br>
+ * where the given {@link NativeSurfaceHolder} impersonates the event's source.
* The NEWT EventListener will be called when an event happens.<br>
*/
- public AWTAdapter(com.jogamp.newt.event.NEWTEventListener newtListener) {
+ protected AWTAdapter(final com.jogamp.newt.event.NEWTEventListener newtListener, final NativeSurfaceHolder nsProxy) {
if(null==newtListener) {
- throw new RuntimeException("Argument newtListener is null");
+ throw new IllegalArgumentException("Argument newtListener is null");
+ }
+ if(null==nsProxy) {
+ throw new IllegalArgumentException("Argument nwProxy is null");
}
this.newtListener = newtListener;
this.newtWindow = null;
+ this.nsHolder = nsProxy;
+ this.consumeAWTEvent = false;
+ this.isSetup = true;
}
- /**
- * Wrap aroung a NEWT EventListener, exposed as an AWT EventListener,<br>
- * where the given NEWT Window impersonates as the event's source.
+ /**
+ * Create a proxy adapter, wrapping around an NEWT EventListener, exposed as an AWT EventListener,<br>
+ * where the given {@link com.jogamp.newt.Window NEWT Window}, a {@link NativeSurfaceHolder}, impersonates the event's source.
* The NEWT EventListener will be called when an event happens.<br>
*/
- public AWTAdapter(com.jogamp.newt.event.NEWTEventListener newtListener, com.jogamp.newt.Window newtProxy) {
+ protected AWTAdapter(final com.jogamp.newt.event.NEWTEventListener newtListener, final com.jogamp.newt.Window newtProxy) {
if(null==newtListener) {
- throw new RuntimeException("Argument newtListener is null");
+ throw new IllegalArgumentException("Argument newtListener is null");
}
if(null==newtProxy) {
- throw new RuntimeException("Argument newtProxy is null");
+ throw new IllegalArgumentException("Argument newtProxy is null");
}
this.newtListener = newtListener;
this.newtWindow = newtProxy;
+ this.nsHolder = newtProxy;
+ this.consumeAWTEvent = false;
+ this.isSetup = true;
}
- /**
+ /**
* Create a pipeline adapter, AWT EventListener.<br>
* Once attached to an AWT component, it sends the converted AWT events to the NEWT downstream window.<br>
* This is only supported with EDT enabled!
+ * @throws IllegalStateException if EDT is not enabled
*/
- public AWTAdapter(com.jogamp.newt.Window downstream) {
+ protected AWTAdapter(final com.jogamp.newt.Window downstream) throws IllegalStateException {
+ this();
+ setDownstream(downstream);
+ }
+
+ public AWTAdapter() {
+ clear();
+ this.consumeAWTEvent = false;
+ }
+
+ /**
+ * Setup a pipeline adapter, AWT EventListener.<br>
+ * Once attached to an AWT component, it sends the converted AWT events to the NEWT downstream window.<br>
+ * This is only supported with EDT enabled!
+ * @throws IllegalStateException if EDT is not enabled
+ */
+ public synchronized AWTAdapter setDownstream(final com.jogamp.newt.Window downstream) throws IllegalStateException {
if(null==downstream) {
throw new RuntimeException("Argument downstream is null");
}
this.newtListener = null;
this.newtWindow = downstream;
+ this.nsHolder = downstream;
if( null == newtWindow.getScreen().getDisplay().getEDTUtil() ) {
- throw new RuntimeException("EDT not enabled");
+ throw new IllegalStateException("EDT not enabled");
}
+ this.isSetup = true;
+ return this;
+ }
+
+ /**
+ * Removes all references, downstream and NEWT-EventListener.
+ * <p>
+ * Also sets the internal <code>setup</code> flag and {@link #setConsumeAWTEvent(boolean)} to <code>false</code>.
+ * </p>
+ */
+ public synchronized AWTAdapter clear() {
+ this.newtListener = null;
+ this.newtWindow = null;
+ this.nsHolder = null;
+ this.isSetup = false;
+ this.consumeAWTEvent = false;
+ return this;
+ }
+
+ public final synchronized void setConsumeAWTEvent(final boolean v) {
+ this.consumeAWTEvent = v;
}
- public final com.jogamp.newt.Window getNewtWindow() {
- return newtWindow;
+ /**
+ * Returns the {@link NativeSurfaceHolder} acting {@link #AWTAdapter(com.jogamp.newt.Window) as downstream},
+ * {@link #AWTAdapter(com.jogamp.newt.event.NEWTEventListener, com.jogamp.newt.Window) NEWT window proxy}
+ * or as an {@link #AWTAdapter(com.jogamp.newt.event.NEWTEventListener, NativeSurfaceHolder) NativeSurfaceHolder proxy}.
+ * <p>
+ * Returned value is never null.
+ * </p>
+ */
+ public final synchronized NativeSurfaceHolder getNativeSurfaceHolder() {
+ return nsHolder;
+ }
+
+ /**
+ * Returns the {@link com.jogamp.newt.Window NEWT Window} acting {@link #AWTAdapter(com.jogamp.newt.Window) as downstream}
+ * or as a {@link #AWTAdapter(com.jogamp.newt.event.NEWTEventListener, com.jogamp.newt.Window) NEWT window proxy}.
+ * <p>
+ * Returned value maybe null if instance is used to be a
+ * {@link #AWTAdapter(com.jogamp.newt.event.NEWTEventListener, NativeSurfaceHolder) NativeSurfaceHolder proxy}.
+ * </p>
+ */
+ public final synchronized com.jogamp.newt.Window getNewtWindow() {
+ return newtWindow;
}
-
- public final com.jogamp.newt.event.NEWTEventListener getNewtEventListener() {
- return newtListener;
+
+ /**
+ * Returns the {@link com.jogamp.newt.event.NEWTEventListener NEWT event-listener} if instance
+ * is used as an {@link #AWTAdapter(com.jogamp.newt.event.NEWTEventListener, NativeSurfaceHolder) NativeSurfaceHolder proxy}
+ * or {@link #AWTAdapter(com.jogamp.newt.event.NEWTEventListener, com.jogamp.newt.Window) NEWT window proxy},
+ * otherwise method returns <code>null</code>.
+ */
+ public final synchronized com.jogamp.newt.event.NEWTEventListener getNewtEventListener() {
+ return newtListener;
}
-
- /**
+
+ /**
* Due to the fact that some NEWT {@link com.jogamp.newt.event.NEWTEventListener}
* are mapped to more than one {@link java.util.EventListener},
* this method is for your convenience to use this Adapter as a listener for all types.<br>
@@ -181,8 +261,46 @@ public abstract class AWTAdapter implements java.util.EventListener
/** @see #addTo(java.awt.Component) */
public abstract AWTAdapter removeFrom(java.awt.Component awtComponent);
- void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
- newtWindow.enqueueEvent(wait, event);
+ /**
+ * Return value for {@link AWTAdapter#processEvent(boolean, com.jogamp.newt.event.NEWTEvent) event processing}.
+ */
+ static enum EventProcRes {
+ /** Event shall be dispatched appropriately */
+ DISPATCH,
+ /** Event has been enqueued */
+ ENQUEUED,
+ /** No known processing method applies */
+ NOP
+ }
+
+ /**
+ * Process the event.
+ * <p>
+ * If {@link #getNewtEventListener()} is not <code>null</code>,
+ * {@link EventProcRes#DISPATCH DISPATCH} is returned and caller shall dispatch the event appropriately.
+ * </p>
+ * <p>
+ * If {@link #getNewtWindow()} is not <code>null</code>,
+ * {@link EventProcRes#ENQUEUED ENQUEUED} is returned and the event has been {@link com.jogamp.newt.Window#enqueueEvent(boolean, com.jogamp.newt.event.NEWTEvent) enqueued already}.
+ * </p>
+ * <p>
+ * If none of the above matches, {@link EventProcRes#NOP NOP} is returned and none of the above processing method applies.
+ * </p>
+ *
+ * @param wait In case the event will be {@link EventProcRes#ENQUEUED ENQUEUED},
+ * passing <code>true</code> will block until the event has been processed, otherwise method returns immediately.
+ * @param event The {@link com.jogamp.newt.event.NEWTEvent event} to enqueue.
+ * @return One of the {@link EventProcRes} values, see above.
+ */
+ EventProcRes processEvent(final boolean wait, final com.jogamp.newt.event.NEWTEvent event) {
+ if(null != newtListener) {
+ return EventProcRes.DISPATCH;
+ }
+ if( null != newtWindow ) {
+ newtWindow.enqueueEvent(wait, event);
+ return EventProcRes.ENQUEUED;
+ }
+ return EventProcRes.NOP;
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
index 7b0f6ba97..4f11e8772 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,64 +20,82 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event.awt;
+import javax.media.nativewindow.NativeSurfaceHolder;
+
import jogamp.newt.awt.event.AWTNewtEventFactory;
+/**
+ * AWT:
+ * printable: PRESSED (t0), TYPED (t0), RELEASED (t1)
+ * non-printable: PRESSED (t0), RELEASED (t1)
+ */
public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListener
{
- public AWTKeyAdapter(com.jogamp.newt.event.KeyListener newtListener) {
- super(newtListener);
+ public AWTKeyAdapter(final com.jogamp.newt.event.KeyListener newtListener, final NativeSurfaceHolder nsProxy) {
+ super(newtListener, nsProxy);
}
- public AWTKeyAdapter(com.jogamp.newt.event.KeyListener newtListener, com.jogamp.newt.Window newtProxy) {
+ public AWTKeyAdapter(final com.jogamp.newt.event.KeyListener newtListener, final com.jogamp.newt.Window newtProxy) {
super(newtListener, newtProxy);
}
- public AWTKeyAdapter(com.jogamp.newt.Window downstream) {
+ public AWTKeyAdapter(final com.jogamp.newt.Window downstream) {
super(downstream);
}
- public AWTAdapter addTo(java.awt.Component awtComponent) {
+ public AWTKeyAdapter() {
+ super();
+ }
+
+ @Override
+ public synchronized AWTAdapter addTo(final java.awt.Component awtComponent) {
awtComponent.addKeyListener(this);
return this;
}
- public AWTAdapter removeFrom(java.awt.Component awtComponent) {
+ @Override
+ public synchronized AWTAdapter removeFrom(final java.awt.Component awtComponent) {
awtComponent.removeKeyListener(this);
return this;
}
- public void keyPressed(java.awt.event.KeyEvent e) {
- com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void keyPressed(final java.awt.event.KeyEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED, e, nsHolder);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.KeyListener)newtListener).keyPressed(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void keyReleased(java.awt.event.KeyEvent e) {
- com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void keyReleased(final java.awt.event.KeyEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED, e, nsHolder);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.KeyListener)newtListener).keyReleased(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void keyTyped(java.awt.event.KeyEvent e) {
- com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow);
- if(null!=newtListener) {
- ((com.jogamp.newt.event.KeyListener)newtListener).keyTyped(event);
- } else {
- enqueueEvent(false, event);
+ @Override
+ public synchronized void keyTyped(final java.awt.event.KeyEvent e) {
+ if( !isSetup ) { return; }
+ if( consumeAWTEvent ) {
+ e.consume();
}
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java
index 115743a0d..d9531cd5f 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,115 +20,147 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event.awt;
+import javax.media.nativewindow.NativeSurfaceHolder;
+
import jogamp.newt.awt.event.AWTNewtEventFactory;
-public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseListener,
+public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseListener,
java.awt.event.MouseMotionListener,
java.awt.event.MouseWheelListener
{
- public AWTMouseAdapter(com.jogamp.newt.event.MouseListener newtListener) {
- super(newtListener);
+ public AWTMouseAdapter(final com.jogamp.newt.event.MouseListener newtListener, final NativeSurfaceHolder nsProxy) {
+ super(newtListener, nsProxy);
}
- public AWTMouseAdapter(com.jogamp.newt.event.MouseListener newtListener, com.jogamp.newt.Window newtProxy) {
+ public AWTMouseAdapter(final com.jogamp.newt.event.MouseListener newtListener, final com.jogamp.newt.Window newtProxy) {
super(newtListener, newtProxy);
}
- public AWTMouseAdapter(com.jogamp.newt.Window downstream) {
+ public AWTMouseAdapter(final com.jogamp.newt.Window downstream) {
super(downstream);
}
- public AWTAdapter addTo(java.awt.Component awtComponent) {
+ public AWTMouseAdapter() {
+ super();
+ }
+
+ @Override
+ public synchronized AWTAdapter addTo(final java.awt.Component awtComponent) {
awtComponent.addMouseListener(this);
awtComponent.addMouseMotionListener(this);
awtComponent.addMouseWheelListener(this);
return this;
}
- public AWTAdapter removeFrom(java.awt.Component awtComponent) {
+ @Override
+ public synchronized AWTAdapter removeFrom(final java.awt.Component awtComponent) {
awtComponent.removeMouseListener(this);
awtComponent.removeMouseMotionListener(this);
awtComponent.removeMouseWheelListener(this);
return this;
}
- public void mouseClicked(java.awt.event.MouseEvent e) {
- com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void mouseClicked(final java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, nsHolder);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseClicked(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void mouseEntered(java.awt.event.MouseEvent e) {
- com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void mouseEntered(final java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, nsHolder);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseEntered(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void mouseExited(java.awt.event.MouseEvent e) {
- com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void mouseExited(final java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, nsHolder);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseExited(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void mousePressed(java.awt.event.MouseEvent e) {
- com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void mousePressed(final java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, nsHolder);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.MouseListener)newtListener).mousePressed(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void mouseReleased(java.awt.event.MouseEvent e) {
- com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void mouseReleased(final java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, nsHolder);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseReleased(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void mouseDragged(java.awt.event.MouseEvent e) {
- com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void mouseDragged(final java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, nsHolder);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseDragged(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void mouseMoved(java.awt.event.MouseEvent e) {
- com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void mouseMoved(final java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, nsHolder);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseMoved(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void mouseWheelMoved(java.awt.event.MouseWheelEvent e) {
- com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void mouseWheelMoved(final java.awt.event.MouseWheelEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, nsHolder);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseWheelMoved(event);
- } else {
- enqueueEvent(false, event);
}
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java
index 2d63ca455..a8105403d 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,59 +20,70 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.newt.event.awt;
import java.awt.Dimension;
+import javax.media.nativewindow.NativeSurfaceHolder;
+
import jogamp.newt.awt.event.AWTNewtEventFactory;
-public class AWTWindowAdapter
- extends AWTAdapter
+public class AWTWindowAdapter
+ extends AWTAdapter
implements java.awt.event.ComponentListener, java.awt.event.WindowListener, java.awt.event.FocusListener
{
WindowClosingListener windowClosingListener;
- public AWTWindowAdapter(com.jogamp.newt.event.WindowListener newtListener) {
- super(newtListener);
+ public AWTWindowAdapter(final com.jogamp.newt.event.WindowListener newtListener, final NativeSurfaceHolder nsProxy) {
+ super(newtListener, nsProxy);
}
- public AWTWindowAdapter(com.jogamp.newt.event.WindowListener newtListener, com.jogamp.newt.Window newtProxy) {
+ public AWTWindowAdapter(final com.jogamp.newt.event.WindowListener newtListener, final com.jogamp.newt.Window newtProxy) {
super(newtListener, newtProxy);
}
- public AWTWindowAdapter(com.jogamp.newt.Window downstream) {
+ public AWTWindowAdapter(final com.jogamp.newt.Window downstream) {
super(downstream);
}
- public AWTAdapter addTo(java.awt.Component awtComponent) {
- java.awt.Window win = getWindow(awtComponent);
+ public AWTWindowAdapter() {
+ super();
+ }
+
+ @Override
+ public synchronized AWTAdapter addTo(final java.awt.Component awtComponent) {
+ final java.awt.Window win = getWindow(awtComponent);
awtComponent.addComponentListener(this);
awtComponent.addFocusListener(this);
- if( null == windowClosingListener ) {
+ if( null != win && null == windowClosingListener ) {
windowClosingListener = new WindowClosingListener();
- }
- if( null != win ) {
win.addWindowListener(windowClosingListener);
}
if(awtComponent instanceof java.awt.Window) {
((java.awt.Window)awtComponent).addWindowListener(this);
}
- return this;
+ return this;
}
-
- public AWTAdapter removeFrom(java.awt.Component awtComponent) {
- awtComponent.removeFocusListener(this);
- awtComponent.removeComponentListener(this);
- java.awt.Window win = getWindow(awtComponent);
+
+ public synchronized AWTAdapter removeWindowClosingFrom(final java.awt.Component awtComponent) {
+ final java.awt.Window win = getWindow(awtComponent);
if( null != win && null != windowClosingListener ) {
win.removeWindowListener(windowClosingListener);
}
+ return this;
+ }
+
+ @Override
+ public synchronized AWTAdapter removeFrom(final java.awt.Component awtComponent) {
+ awtComponent.removeFocusListener(this);
+ awtComponent.removeComponentListener(this);
+ removeWindowClosingFrom(awtComponent);
if(awtComponent instanceof java.awt.Window) {
((java.awt.Window)awtComponent).removeWindowListener(this);
}
@@ -83,38 +94,37 @@ public class AWTWindowAdapter
while( null != comp && !(comp instanceof java.awt.Window) ) {
comp = comp.getParent();
}
- if(comp instanceof java.awt.Window) {
- return (java.awt.Window) comp;
- }
- return null;
+ return (java.awt.Window) comp; // either null or a 'java.awt.Window'
}
- public void focusGained(java.awt.event.FocusEvent e) {
- com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+ @Override
+ public synchronized void focusGained(final java.awt.event.FocusEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, nsHolder);
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: focusGained: "+e+" -> "+event);
}
- if(null!=newtListener) {
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.WindowListener)newtListener).windowGainedFocus(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void focusLost(java.awt.event.FocusEvent e) {
- com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+ @Override
+ public synchronized void focusLost(final java.awt.event.FocusEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, nsHolder);
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: focusLost: "+e+" -> "+event);
}
- if(null!=newtListener) {
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.WindowListener)newtListener).windowLostFocus(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void componentResized(java.awt.event.ComponentEvent e) {
- com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+ @Override
+ public synchronized void componentResized(final java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, nsHolder);
if(DEBUG_IMPLEMENTATION) {
final java.awt.Component c = e.getComponent();
final java.awt.Dimension sz = c.getSize();
@@ -130,26 +140,26 @@ public class AWTWindowAdapter
}
System.err.println("AWT: componentResized: "+sz+" ( "+insets+", "+sz2+" ), "+e+" -> "+event);
}
- if(null!=newtListener) {
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.WindowListener)newtListener).windowResized(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void componentMoved(java.awt.event.ComponentEvent e) {
- com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+ @Override
+ public synchronized void componentMoved(final java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, nsHolder);
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentMoved: "+e+" -> "+event);
}
- if(null!=newtListener) {
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.WindowListener)newtListener).windowMoved(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void componentShown(java.awt.event.ComponentEvent e) {
+ @Override
+ public synchronized void componentShown(final java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
final java.awt.Component comp = e.getComponent();
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentShown: "+comp);
@@ -166,7 +176,9 @@ public class AWTWindowAdapter
}*/
}
- public void componentHidden(java.awt.event.ComponentEvent e) {
+ @Override
+ public synchronized void componentHidden(final java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
final java.awt.Component comp = e.getComponent();
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentHidden: "+comp);
@@ -183,50 +195,71 @@ public class AWTWindowAdapter
}*/
}
- public void windowActivated(java.awt.event.WindowEvent e) {
- com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void windowActivated(final java.awt.event.WindowEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, nsHolder);
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.WindowListener)newtListener).windowGainedFocus(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void windowClosed(java.awt.event.WindowEvent e) { }
+ @Override
+ public synchronized void windowClosed(final java.awt.event.WindowEvent e) { }
- public void windowClosing(java.awt.event.WindowEvent e) { }
+ @Override
+ public synchronized void windowClosing(final java.awt.event.WindowEvent e) { }
- public void windowDeactivated(java.awt.event.WindowEvent e) {
- com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
- if(null!=newtListener) {
+ @Override
+ public synchronized void windowDeactivated(final java.awt.event.WindowEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, nsHolder);
+ if( EventProcRes.DISPATCH == processEvent(false, event) ) {
((com.jogamp.newt.event.WindowListener)newtListener).windowLostFocus(event);
- } else {
- enqueueEvent(false, event);
}
}
- public void windowDeiconified(java.awt.event.WindowEvent e) { }
+ @Override
+ public synchronized void windowDeiconified(final java.awt.event.WindowEvent e) { }
- public void windowIconified(java.awt.event.WindowEvent e) { }
+ @Override
+ public synchronized void windowIconified(final java.awt.event.WindowEvent e) { }
- public void windowOpened(java.awt.event.WindowEvent e) { }
+ @Override
+ public synchronized void windowOpened(final java.awt.event.WindowEvent e) { }
class WindowClosingListener implements java.awt.event.WindowListener {
- public void windowClosing(java.awt.event.WindowEvent e) {
- com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
- if(null!=newtListener) {
- ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyNotify(event);
- } else {
- enqueueEvent(true, event);
+ @Override
+ public void windowClosing(final java.awt.event.WindowEvent e) {
+ synchronized( AWTWindowAdapter.this ) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, nsHolder);
+ if( EventProcRes.DISPATCH == processEvent(true, event) ) {
+ ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyNotify(event);
+ }
+ }
+ }
+ @Override
+ public void windowClosed(final java.awt.event.WindowEvent e) {
+ synchronized( AWTWindowAdapter.this ) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, nsHolder);
+ if( EventProcRes.DISPATCH == processEvent(true, event) ) {
+ ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyed(event);
+ }
}
}
- public void windowActivated(java.awt.event.WindowEvent e) { }
- public void windowClosed(java.awt.event.WindowEvent e) { }
- public void windowDeactivated(java.awt.event.WindowEvent e) { }
- public void windowDeiconified(java.awt.event.WindowEvent e) { }
- public void windowIconified(java.awt.event.WindowEvent e) { }
- public void windowOpened(java.awt.event.WindowEvent e) { }
+ @Override
+ public void windowActivated(final java.awt.event.WindowEvent e) { }
+ @Override
+ public void windowDeactivated(final java.awt.event.WindowEvent e) { }
+ @Override
+ public void windowDeiconified(final java.awt.event.WindowEvent e) { }
+ @Override
+ public void windowIconified(final java.awt.event.WindowEvent e) { }
+ @Override
+ public void windowOpened(final java.awt.event.WindowEvent e) { }
}
}
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index a89ccaedb..2ba030f76 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -34,18 +34,24 @@
package com.jogamp.newt.opengl;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.List;
+
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.SurfaceUpdatedListener;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
import javax.media.opengl.FPSCounter;
import javax.media.opengl.GL;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GL4ES3;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -53,9 +59,13 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLES2;
+import javax.media.opengl.GLES3;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
+import javax.media.opengl.GLSharedContextSetter;
import jogamp.newt.WindowImpl;
import jogamp.opengl.GLAutoDrawableBase;
@@ -65,30 +75,45 @@ import jogamp.opengl.GLDrawableImpl;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.util.VersionUtil;
import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
import com.jogamp.newt.Window;
+import com.jogamp.newt.Display.PointerIcon;
+import com.jogamp.newt.event.GestureHandler;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseListener;
import com.jogamp.newt.event.NEWTEvent;
import com.jogamp.newt.event.NEWTEventConsumer;
+import com.jogamp.newt.event.NEWTEventListener;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.event.WindowUpdateEvent;
import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.GLStateKeeper;
/**
* An implementation of {@link GLAutoDrawable} and {@link Window} interface,
* using a delegated {@link Window} instance, which may be an aggregation (lifecycle: created and destroyed).
* <P>
+ * This implementation supports {@link GLStateKeeper GL state preservation},
+ * hence {@link #isGLStatePreservationSupported()} returns <code>true</code>.
+ * </P>
+ * <P>
* This implementation does not make the OpenGL context current<br>
- * before calling the various input EventListener callbacks, ie {@link com.jogamp.newt.event.MouseListener} etc.<br>
+ * before calling the various input EventListener callbacks, ie {@link MouseListener} etc.<br>
* This design decision is made in favor of a more performant and simplified
* implementation. Also the event dispatcher shall be implemented OpenGL agnostic.<br>
- * To be able to use OpenGL commands from within such input {@link com.jogamp.newt.event.NEWTEventListener},<br>
- * you can inject {@link javax.media.opengl.GLRunnable} objects
- * via {@link #invoke(boolean, javax.media.opengl.GLRunnable)} to the OpenGL command stream.<br>
+ * To be able to use OpenGL commands from within such input {@link NEWTEventListener},<br>
+ * you can inject {@link GLRunnable} objects
+ * via {@link #invoke(boolean, GLRunnable)} to the OpenGL command stream.<br>
+ * </p>
+ * <p>
+ * <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a>
+ * To share a {@link GLContext} see the following note in the documentation overview:
+ * <a href="../../../../overview-summary.html#SHARING">context sharing</a>
+ * as well as {@link GLSharedContextSetter}.
* </p>
*/
public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Window, NEWTEventConsumer, FPSCounter {
@@ -97,25 +122,25 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
/**
* Constructor. Do not call this directly -- use {@link #create()} instead.
*/
- protected GLWindow(Window window) {
+ protected GLWindow(final Window window) {
super(null, null, false /* always handle device lifecycle ourselves */);
this.window = (WindowImpl) window;
- this.window.setHandleDestroyNotify(false);
+ this.window.setWindowDestroyNotifyAction( new Runnable() {
+ @Override
+ public void run() {
+ defaultWindowDestroyNotifyOp();
+ } } );
window.addWindowListener(new WindowAdapter() {
@Override
- public void windowRepaint(WindowUpdateEvent e) {
+ public void windowRepaint(final WindowUpdateEvent e) {
defaultWindowRepaintOp();
}
@Override
- public void windowResized(WindowEvent e) {
- defaultWindowResizedOp(getWidth(), getHeight());
+ public void windowResized(final WindowEvent e) {
+ defaultWindowResizedOp(getSurfaceWidth(), getSurfaceHeight());
}
- @Override
- public void windowDestroyNotify(WindowEvent e) {
- defaultWindowDestroyNotifyOp();
- }
});
this.window.setLifecycleHook(new GLLifecycleHook());
}
@@ -124,7 +149,12 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
public final Object getUpstreamWidget() {
return window;
}
-
+
+ @Override
+ public final RecursiveLock getUpstreamLock() {
+ return window.getLock();
+ }
+
/**
* Creates a new GLWindow attaching a new Window referencing a
* new default Screen and default Display with the given GLCapabilities.
@@ -134,7 +164,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
* </p>
* The default Display will be reused if already instantiated.
*/
- public static GLWindow create(GLCapabilitiesImmutable caps) {
+ public static GLWindow create(final GLCapabilitiesImmutable caps) {
return new GLWindow(NewtFactory.createWindow(caps));
}
@@ -146,7 +176,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
* and {@link Screen#removeReference()}.
* </p>
*/
- public static GLWindow create(Screen screen, GLCapabilitiesImmutable caps) {
+ public static GLWindow create(final Screen screen, final GLCapabilitiesImmutable caps) {
return new GLWindow(NewtFactory.createWindow(screen, caps));
}
@@ -157,7 +187,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
* and {@link Screen#removeReference()}.
* </p>
*/
- public static GLWindow create(Window window) {
+ public static GLWindow create(final Window window) {
return new GLWindow(window);
}
@@ -174,7 +204,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
* and {@link Screen#removeReference()}.
* </p>
*/
- public static GLWindow create(NativeWindow parentNativeWindow, GLCapabilitiesImmutable caps) {
+ public static GLWindow create(final NativeWindow parentNativeWindow, final GLCapabilitiesImmutable caps) {
return new GLWindow(NewtFactory.createWindow(parentNativeWindow, caps));
}
@@ -187,7 +217,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
+ public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
return window.setDefaultCloseOperation(op);
}
@@ -196,14 +226,14 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
//
@Override
- public CapabilitiesChooser setCapabilitiesChooser(CapabilitiesChooser chooser) {
+ public CapabilitiesChooser setCapabilitiesChooser(final CapabilitiesChooser chooser) {
return window.setCapabilitiesChooser(chooser);
}
@Override
public final CapabilitiesImmutable getChosenCapabilities() {
final GLDrawable _drawable = drawable;
- return null != _drawable ? _drawable.getChosenGLCapabilities() : window.getChosenCapabilities();
+ return null != _drawable ? _drawable.getChosenGLCapabilities() : window.getChosenCapabilities();
}
@Override
@@ -227,7 +257,12 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void setTitle(String title) {
+ public final MonitorDevice getMainMonitor() {
+ return window.getMainMonitor();
+ }
+
+ @Override
+ public final void setTitle(final String title) {
window.setTitle(title);
}
@@ -242,27 +277,37 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void setPointerVisible(boolean mouseVisible) {
+ public final void setPointerVisible(final boolean mouseVisible) {
window.setPointerVisible(mouseVisible);
}
@Override
+ public final PointerIcon getPointerIcon() {
+ return window.getPointerIcon();
+ }
+
+ @Override
+ public final void setPointerIcon(final PointerIcon pi) {
+ window.setPointerIcon(pi);
+ }
+
+ @Override
public final boolean isPointerConfined() {
return window.isPointerConfined();
}
@Override
- public final void confinePointer(boolean grab) {
+ public final void confinePointer(final boolean grab) {
window.confinePointer(grab);
}
@Override
- public final void setUndecorated(boolean value) {
+ public final void setUndecorated(final boolean value) {
window.setUndecorated(value);
}
@Override
- public final void warpPointer(int x, int y) {
+ public final void warpPointer(final int x, final int y) {
window.warpPointer(x, y);
}
@Override
@@ -271,7 +316,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void setAlwaysOnTop(boolean value) {
+ public final void setAlwaysOnTop(final boolean value) {
window.setAlwaysOnTop(value);
}
@@ -281,12 +326,12 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void setFocusAction(FocusRunnable focusAction) {
+ public final void setFocusAction(final FocusRunnable focusAction) {
window.setFocusAction(focusAction);
}
@Override
- public void setKeyboardFocusHandler(KeyListener l) {
+ public void setKeyboardFocusHandler(final KeyListener l) {
window.setKeyboardFocusHandler(l);
}
@@ -296,7 +341,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void requestFocus(boolean wait) {
+ public final void requestFocus(final boolean wait) {
window.requestFocus(wait);
}
@@ -319,7 +364,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
public final int getY() {
return window.getY();
}
-
+
@Override
public final int getWidth() {
return window.getWidth();
@@ -329,22 +374,77 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
public final int getHeight() {
return window.getHeight();
}
-
+
+ @Override
+ public final Rectangle getBounds() {
+ return window.getBounds();
+ }
+
+ @Override
+ public final int getSurfaceWidth() {
+ return window.getSurfaceWidth();
+ }
+
+ @Override
+ public final int getSurfaceHeight() {
+ return window.getSurfaceHeight();
+ }
+
+ @Override
+ public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
+ return window.convertToWindowUnits(pixelUnitsAndResult);
+ }
+
+ @Override
+ public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
+ return window.convertToPixelUnits(windowUnitsAndResult);
+ }
+
+ @Override
+ public final void setSurfaceScale(final int[] pixelScale) {
+ window.setSurfaceScale(pixelScale);
+ }
+
+ @Override
+ public final int[] getRequestedSurfaceScale(final int[] result) {
+ return window.getRequestedSurfaceScale(result);
+ }
+
+ @Override
+ public final int[] getCurrentSurfaceScale(final int[] result) {
+ return window.getCurrentSurfaceScale(result);
+ }
+
+ @Override
+ public final int[] getNativeSurfaceScale(final int[] result) {
+ return window.getNativeSurfaceScale(result);
+ }
+
@Override
- public final void setPosition(int x, int y) {
+ public final float[] getPixelsPerMM(final float[] ppmmStore) {
+ return window.getPixelsPerMM(ppmmStore);
+ }
+
+ @Override
+ public final void setPosition(final int x, final int y) {
window.setPosition(x, y);
}
@Override
- public void setTopLevelPosition(int x, int y) {
+ public void setTopLevelPosition(final int x, final int y) {
window.setTopLevelPosition(x, y);
}
@Override
- public final boolean setFullscreen(boolean fullscreen) {
+ public final boolean setFullscreen(final boolean fullscreen) {
return window.setFullscreen(fullscreen);
}
@Override
+ public boolean setFullscreen(final List<MonitorDevice> monitors) {
+ return window.setFullscreen(monitors);
+ }
+
+ @Override
public final boolean isFullscreen() {
return window.isFullscreen();
}
@@ -361,22 +461,17 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final ReparentOperation reparentWindow(NativeWindow newParent) {
- return window.reparentWindow(newParent);
+ public final ReparentOperation reparentWindow(final NativeWindow newParent, final int x, final int y, final int hints) {
+ return window.reparentWindow(newParent, x, y, hints);
}
@Override
- public final ReparentOperation reparentWindow(NativeWindow newParent, boolean forceDestroyCreate) {
- return window.reparentWindow(newParent, forceDestroyCreate);
- }
-
- @Override
- public final boolean removeChild(NativeWindow win) {
+ public final boolean removeChild(final NativeWindow win) {
return window.removeChild(win);
}
@Override
- public final boolean addChild(NativeWindow win) {
+ public final boolean addChild(final NativeWindow win) {
return window.addChild(win);
}
@@ -390,16 +485,30 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void setVisible(boolean visible) {
+ public void setWindowDestroyNotifyAction(final Runnable r) {
+ window.setWindowDestroyNotifyAction(r);
+ }
+
+ @Override
+ public final void setVisible(final boolean visible) {
window.setVisible(visible);
}
@Override
- public final void setSize(int width, int height) {
+ public void setVisible(final boolean wait, final boolean visible) {
+ window.setVisible(wait, visible);
+ }
+
+ @Override
+ public final void setSize(final int width, final int height) {
window.setSize(width, height);
}
@Override
- public void setTopLevelSize(int width, int height) {
+ public final void setSurfaceSize(final int pixelWidth, final int pixelHeight) {
+ window.setSurfaceSize(pixelWidth, pixelHeight);
+ }
+ @Override
+ public void setTopLevelSize(final int width, final int height) {
window.setTopLevelSize(width, height);
}
@@ -409,7 +518,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public Point getLocationOnScreen(Point storage) {
+ public Point getLocationOnScreen(final Point storage) {
return window.getLocationOnScreen(storage);
}
@@ -417,6 +526,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
protected class GLLifecycleHook implements WindowImpl.LifecycleHook {
@Override
+ public void preserveGLStateAtDestroy(final boolean value) {
+ GLWindow.this.preserveGLStateAtDestroy(value);
+ }
+
+ @Override
public synchronized void destroyActionPreLock() {
// nop
}
@@ -424,7 +538,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
@Override
public synchronized void destroyActionInLock() {
if(Window.DEBUG_IMPLEMENTATION) {
- String msg = "GLWindow.destroy() "+WindowImpl.getThreadName()+", start";
+ final String msg = "GLWindow.destroy() "+WindowImpl.getThreadName()+", start";
System.err.println(msg);
//Exception e1 = new Exception(msg);
//e1.printStackTrace();
@@ -443,10 +557,14 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
System.err.println("GLWindow.resetCounter() "+WindowImpl.getThreadName());
}
GLWindow.this.resetFPSCounter();
+ final GLAnimatorControl animator = GLWindow.this.getAnimator();
+ if( null != animator ) {
+ animator.resetFPSCounter();
+ }
}
@Override
- public synchronized void setVisibleActionPost(boolean visible, boolean nativeWindowCreated) {
+ public synchronized void setVisibleActionPost(final boolean visible, final boolean nativeWindowCreated) {
long t0;
if(Window.DEBUG_IMPLEMENTATION) {
t0 = System.nanoTime();
@@ -455,26 +573,29 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
t0 = 0;
}
- /* if (nativeWindowCreated && null != context) {
- throw new GLException("InternalError: Native Windows has been just created, but context wasn't destroyed (is not null)");
- } */
- if (null == context && visible && 0 != window.getWindowHandle() && 0<getWidth()*getHeight()) {
- NativeWindow nw;
- if (window.getWrappedWindow() != null) {
- nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getPrivateGraphicsConfiguration());
- } else {
- nw = window;
- }
- GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) nw.getGraphicsConfiguration().getChosenCapabilities();
- if(null==factory) {
- factory = GLDrawableFactory.getFactory(glCaps.getGLProfile());
+ if (null == drawable && visible && 0 != window.getWindowHandle() && 0<getSurfaceWidth()*getSurfaceHeight()) {
+ if( ( null != context ) ) {
+ throw new InternalError("GLWindow.LifecycleHook.setVisiblePost: "+WindowImpl.getThreadName()+" - Null drawable, but valid context - "+GLWindow.this);
}
- if(null==drawable) {
- drawable = (GLDrawableImpl) factory.createGLDrawable(nw);
+ final GLContext[] shareWith = { null };
+ if( !helper.isSharedGLContextPending(shareWith) ) {
+ final NativeSurface ns;
+ {
+ final NativeSurface wrapped_ns = window.getWrappedSurface();
+ ns = null != wrapped_ns ? wrapped_ns : window;
+ }
+ final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) ns.getGraphicsConfiguration().getChosenCapabilities();
+ if(null==factory) {
+ factory = GLDrawableFactory.getFactory(glCaps.getGLProfile());
+ }
+ drawable = (GLDrawableImpl) factory.createGLDrawable(ns);
+ drawable.setRealized(true);
+
+ if( !GLWindow.this.restoreGLEventListenerState() ) {
+ context = (GLContextImpl) drawable.createContext(shareWith[0]);
+ context.setContextCreationFlags(additionalCtxCreationFlags);
+ }
}
- drawable.setRealized(true);
- context = (GLContextImpl) drawable.createContext(sharedContext);
- context.setContextCreationFlags(additionalCtxCreationFlags);
}
if(Window.DEBUG_IMPLEMENTATION) {
System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", fin: dt "+ (System.nanoTime()-t0)/1e6 +"ms");
@@ -485,10 +606,12 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
@Override
public synchronized boolean pauseRenderingAction() {
- boolean animatorPaused = false;
+ final boolean animatorPaused;
savedAnimator = GLWindow.this.getAnimator();
if ( null != savedAnimator ) {
animatorPaused = savedAnimator.pause();
+ } else {
+ animatorPaused = false;
}
return animatorPaused;
}
@@ -499,31 +622,40 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
savedAnimator.resume();
}
}
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void shutdownRenderingAction() {
+ final GLAnimatorControl anim = GLWindow.this.getAnimator();
+ if ( null != anim && anim.isAnimating() ) {
+ final Thread animThread = anim.getThread();
+ if( animThread == Thread.currentThread() ) {
+ anim.stop(); // on anim thread, non-blocking
+ } else {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ if( anim.isAnimating() && null != animThread ) {
+ try {
+ animThread.stop();
+ } catch(final Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ }
+ return null;
+ } } );
+ }
+ }
+ }
}
//----------------------------------------------------------------------
// OpenGL-related methods and state
//
- private GLContext sharedContext = null;
-
- @Override
- protected final RecursiveLock getLock() {
- return window.getLock();
- }
-
- /**
- * Specifies an {@link javax.media.opengl.GLContext OpenGL context} to share with.<br>
- * At native creation, {@link #setVisible(boolean) setVisible(true)},
- * a {@link javax.media.opengl.GLDrawable drawable} and {@link javax.media.opengl.GLContext context} is created besides the native Window itself,<br>
- * hence you shall set the shared context before.
- *
- * @param sharedContext The OpenGL context shared by this GLWindow's one
- */
- public void setSharedContext(GLContext sharedContext) {
- this.sharedContext = sharedContext;
- }
-
@Override
public void display() {
if( !isNativeValid() || !isVisible() ) { return; }
@@ -548,12 +680,21 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
} finally {
lock.unlock();
}
- if( !done && 0<getWidth()*getHeight() ) {
+ if( !done && ( 0 < getSurfaceWidth() && 0 < getSurfaceHeight() ) ) {
// retry drawable and context creation, will itself issue resize -> display
setVisible(true);
}
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * GLWindow supports GL state preservation, hence returns <code>true</code>.
+ * </p>
+ */
+ @Override
+ public final boolean isGLStatePreservationSupported() { return true; }
+
//----------------------------------------------------------------------
// GLDrawable methods
//
@@ -565,19 +706,15 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void setRealized(boolean realized) {
- }
-
- @Override
public final void swapBuffers() throws GLException {
defaultSwapBuffers();
}
-
+
//----------------------------------------------------------------------
// NEWTEventConsumer
//
@Override
- public boolean consumeEvent(NEWTEvent event) {
+ public boolean consumeEvent(final NEWTEvent event) {
return window.consumeEvent(event);
}
@@ -585,42 +722,27 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
// Window completion
//
@Override
- public final void windowRepaint(int x, int y, int width, int height) {
+ public final void windowRepaint(final int x, final int y, final int width, final int height) {
window.windowRepaint(x, y, width, height);
}
@Override
- public final void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
+ public final void enqueueEvent(final boolean wait, final com.jogamp.newt.event.NEWTEvent event) {
window.enqueueEvent(wait, event);
}
@Override
- public final void runOnEDTIfAvail(boolean wait, final Runnable task) {
+ public final void runOnEDTIfAvail(final boolean wait, final Runnable task) {
window.runOnEDTIfAvail(wait, task);
}
@Override
- public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- window.removeSurfaceUpdatedListener(l);
- }
-
- @Override
- public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- window.addSurfaceUpdatedListener(l);
- }
-
- @Override
- public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
- window.addSurfaceUpdatedListener(index, l);
- }
-
- @Override
- public void sendWindowEvent(int eventType) {
+ public void sendWindowEvent(final int eventType) {
window.sendWindowEvent(eventType);
}
@Override
- public final WindowListener getWindowListener(int index) {
+ public final WindowListener getWindowListener(final int index) {
return window.getWindowListener(index);
}
@@ -630,22 +752,22 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void removeWindowListener(WindowListener l) {
+ public final void removeWindowListener(final WindowListener l) {
window.removeWindowListener(l);
}
@Override
- public final void addWindowListener(WindowListener l) {
+ public final void addWindowListener(final WindowListener l) {
window.addWindowListener(l);
}
@Override
- public final void addWindowListener(int index, WindowListener l) throws IndexOutOfBoundsException {
+ public final void addWindowListener(final int index, final WindowListener l) throws IndexOutOfBoundsException {
window.addWindowListener(index, l);
}
@Override
- public final void setKeyboardVisible(boolean visible) {
+ public final void setKeyboardVisible(final boolean visible) {
window.setKeyboardVisible(visible);
}
@@ -655,22 +777,22 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void addKeyListener(KeyListener l) {
+ public final void addKeyListener(final KeyListener l) {
window.addKeyListener(l);
}
@Override
- public final void addKeyListener(int index, KeyListener l) {
+ public final void addKeyListener(final int index, final KeyListener l) {
window.addKeyListener(index, l);
}
@Override
- public final void removeKeyListener(KeyListener l) {
+ public final void removeKeyListener(final KeyListener l) {
window.removeKeyListener(l);
}
@Override
- public final KeyListener getKeyListener(int index) {
+ public final KeyListener getKeyListener(final int index) {
return window.getKeyListener(index);
}
@@ -680,22 +802,22 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
- public final void addMouseListener(MouseListener l) {
+ public final void addMouseListener(final MouseListener l) {
window.addMouseListener(l);
}
@Override
- public final void addMouseListener(int index, MouseListener l) {
+ public final void addMouseListener(final int index, final MouseListener l) {
window.addMouseListener(index, l);
}
@Override
- public final void removeMouseListener(MouseListener l) {
+ public final void removeMouseListener(final MouseListener l) {
window.removeMouseListener(l);
}
@Override
- public final MouseListener getMouseListener(int index) {
+ public final MouseListener getMouseListener(final int index) {
return window.getMouseListener(index);
}
@@ -704,6 +826,39 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
return window.getMouseListeners();
}
+ @Override
+ public void setDefaultGesturesEnabled(final boolean enable) {
+ window.setDefaultGesturesEnabled(enable);
+ }
+ @Override
+ public boolean areDefaultGesturesEnabled() {
+ return window.areDefaultGesturesEnabled();
+ }
+ @Override
+ public final void addGestureHandler(final GestureHandler gh) {
+ window.addGestureHandler(gh);
+ }
+ @Override
+ public final void addGestureHandler(final int index, final GestureHandler gh) {
+ window.addGestureHandler(index, gh);
+ }
+ @Override
+ public final void removeGestureHandler(final GestureHandler gh) {
+ window.removeGestureHandler(gh);
+ }
+ @Override
+ public final void addGestureListener(final GestureHandler.GestureListener gl) {
+ window.addGestureListener(-1, gl);
+ }
+ @Override
+ public final void addGestureListener(final int index, final GestureHandler.GestureListener gl) {
+ window.addGestureListener(index, gl);
+ }
+ @Override
+ public final void removeGestureListener(final GestureHandler.GestureListener gl) {
+ window.removeGestureListener(gl);
+ }
+
//----------------------------------------------------------------------
// NativeWindow completion
//
@@ -735,6 +890,26 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
+ public final void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
+ window.removeSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
+ window.addSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ window.addSurfaceUpdatedListener(index, l);
+ }
+
+ @Override
+ public final void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
+ window.surfaceUpdated(updater, ns, when);
+ }
+
+ @Override
public final long getWindowHandle() {
return window.getWindowHandle();
@@ -761,46 +936,102 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
return window.getScreenIndex();
}
- @Override
- public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- window.surfaceUpdated(updater, ns, when);
- }
-
/**
* A most simple JOGL AWT test entry
*/
- public static void main(String args[]) {
+ public static void main(final String args[]) {
+ final boolean forceES2;
+ final boolean forceES3;
+ final boolean forceGL3;
+ final boolean forceGL4ES3;
+ {
+ boolean _forceES2 = false;
+ boolean _forceES3 = false;
+ boolean _forceGL3 = false;
+ boolean _forceGL4ES3 = false;
+ if( null != args ) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-es2")) {
+ _forceES2 = true;
+ } else if(args[i].equals("-es3")) {
+ _forceES3 = true;
+ } else if(args[i].equals("-gl3")) {
+ _forceGL3 = true;
+ } else if(args[i].equals("-gl4es3")) {
+ _forceGL4ES3 = true;
+ }
+ }
+ }
+ forceES2 = _forceES2;
+ forceES3 = _forceES3;
+ forceGL3 = _forceGL3;
+ forceGL4ES3 = _forceGL4ES3;
+ }
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceES3 "+forceES3);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("forceGL4ES3 "+forceGL4ES3);
+
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
System.err.println(JoglVersion.getInstance());
System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
- final GLProfile glp = GLProfile.getDefault();
+ final GLProfile glp;
+ if(forceGL4ES3) {
+ glp = GLProfile.get(GLProfile.GL4ES3);
+ } else if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES3) {
+ glp = GLProfile.get(GLProfile.GLES3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getDefault();
+ }
final GLCapabilitiesImmutable caps = new GLCapabilities( glp );
+ System.err.println("Requesting: "+caps);
- GLWindow glWindow = GLWindow.create(caps);
+ final GLWindow glWindow = GLWindow.create(caps);
glWindow.setSize(128, 128);
glWindow.addGLEventListener(new GLEventListener() {
@Override
- public void init(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
System.err.println(JoglVersion.getGLInfo(gl, null));
System.err.println("Requested: "+drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities());
System.err.println("Chosen : "+drawable.getChosenGLCapabilities());
+ System.err.println("GL impl. class "+gl.getClass().getName());
+ if( gl.isGL4ES3() ) {
+ final GL4ES3 _gl = gl.getGL4ES3();
+ System.err.println("GL4ES3 retrieved, impl. class "+_gl.getClass().getName());
+ }
+ if( gl.isGL3() ) {
+ final GL3 _gl = gl.getGL3();
+ System.err.println("GL3 retrieved, impl. class "+_gl.getClass().getName());
+ }
+ if( gl.isGLES3() ) {
+ final GLES3 _gl = gl.getGLES3();
+ System.err.println("GLES3 retrieved, impl. class "+_gl.getClass().getName());
+ }
+ if( gl.isGLES2() ) {
+ final GLES2 _gl = gl.getGLES2();
+ System.err.println("GLES2 retrieved, impl. class "+_gl.getClass().getName());
+ }
}
@Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
}
@Override
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
}
@Override
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
}
});
diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
index 36bc3f28f..76af2d0ec 100644
--- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
+++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,13 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
package com.jogamp.newt.swt;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
@@ -44,18 +43,20 @@ import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
+import javax.media.opengl.GLCapabilities;
import jogamp.nativewindow.macosx.OSXUtil;
+import jogamp.nativewindow.windows.GDIUtil;
+import jogamp.nativewindow.x11.X11Lib;
import jogamp.newt.Debug;
+import jogamp.newt.swt.SWTEDTUtil;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ControlAdapter;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.newt.Display;
@@ -65,111 +66,159 @@ import com.jogamp.newt.util.EDTUtil;
/**
* SWT {@link Canvas} containing a NEWT {@link Window} using native parenting.
+ * <p>
+ * Implementation allows use of custom {@link GLCapabilities}.
+ * </p>
*/
public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
private static final boolean DEBUG = Debug.debug("Window");
- private static final boolean isOSX = NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false);
-
- private final AbstractGraphicsScreen screen;
-
+
+ private final AbstractGraphicsScreen screen;
+
private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE;
private volatile Rectangle clientArea;
private volatile SWTNativeWindow nativeWindow;
private volatile Window newtChild = null;
+ private volatile boolean newtChildReady = false; // ready if SWTEDTUtil is set and newtChild parented
+ private volatile boolean postSetSize = false; // pending resize
+ private volatile boolean postSetPos = false; // pending pos
- /**
- * Creates an instance using {@link #NewtCanvasSWT(Composite, int, Window)}
+ /**
+ * Creates an instance using {@link #NewtCanvasSWT(Composite, int, Window)}
* on the SWT thread.
- *
+ *
* <p>
* Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
- * via {@link Display#setEDTUtil(EDTUtil)}.
+ * via {@link Display#setEDTUtil(EDTUtil)}.
* </p>
- *
+ *
* @param parent the SWT composite
- * @param style additional styles to SWT#NO_BACKGROUND
- * @param child optional preassigned {@link #Window}, maybe null
+ * @param style additional styles to SWT#NO_BACKGROUND
+ * @param child optional preassigned {@link #Window}, maybe null
* @return a new instance
*/
public static NewtCanvasSWT create(final Composite parent, final int style, final Window child) {
- final NewtCanvasSWT[] res = new NewtCanvasSWT[] { null };
+ final NewtCanvasSWT[] res = new NewtCanvasSWT[] { null };
parent.getDisplay().syncExec( new Runnable() {
+ @Override
public void run() {
res[0] = new NewtCanvasSWT( parent, style, child);
}
});
return res[0];
}
-
+
/**
* Instantiates a NewtCanvas with a NEWT child.
- *
+ *
* <p>
* Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
- * via {@link Display#setEDTUtil(EDTUtil)}.
+ * via {@link Display#setEDTUtil(EDTUtil)}.
* </p>
- *
+ *
* @param parent the SWT composite
- * @param style additional styles to SWT#NO_BACKGROUND
- * @param child optional preassigned {@link #Window}, maybe null
+ * @param style additional styles to SWT#NO_BACKGROUND
+ * @param child optional preassigned {@link #Window}, maybe null
*/
- public NewtCanvasSWT(final Composite parent, final int style, Window child) {
+ public NewtCanvasSWT(final Composite parent, final int style, final Window child) {
super(parent, style | SWT.NO_BACKGROUND);
-
+
SWTAccessor.setRealized(this, true);
clientArea = getClientArea();
final AbstractGraphicsDevice device = SWTAccessor.getDevice(this);
- screen = SWTAccessor.getScreen(device, 0);
+ screen = SWTAccessor.getScreen(device, -1 /* default */);
nativeWindow = null;
-
+
if(null != child) {
setNEWTChild(child);
}
-
- /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
- /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
- addPaintListener(new PaintListener() {
+
+ final Listener listener = new Listener () {
@Override
- public void paintControl(final PaintEvent arg0) {
- if( null != nativeWindow || validateNative() ) {
- if( null !=newtChild ) {
- newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
+ public void handleEvent (final Event event) {
+ switch (event.type) {
+ case SWT.Paint:
+ if( DEBUG ) {
+ System.err.println("NewtCanvasSWT.Event.PAINT, "+event);
+ }
+ if( null != nativeWindow || validateNative() ) {
+ if( newtChildReady ) {
+ if( postSetSize ) {
+ newtChild.setSize(clientArea.width, clientArea.height);
+ postSetSize = false;
+ }
+ if( postSetPos ) {
+ newtChild.setPosition(clientArea.x, clientArea.y);
+ postSetPos = false;
+ }
+ newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
+ }
+ }
+ break;
+ case SWT.Move:
+ if( DEBUG ) {
+ System.err.println("NewtCanvasSWT.Event.MOVE, "+event);
+ }
+ // updatePosSizeCheck();
+ break;
+ case SWT.Resize:
+ if( DEBUG ) {
+ System.err.println("NewtCanvasSWT.Event.RESIZE, "+event);
+ }
+ updateSizeCheck();
+ break;
+ case SWT.Dispose:
+ if( DEBUG ) {
+ System.err.println("NewtCanvasSWT.Event.DISPOSE, "+event);
+ }
+ NewtCanvasSWT.this.dispose();
+ break;
+ default:
+ if( DEBUG ) {
+ System.err.println("NewtCanvasSWT.Event.misc: "+event.type+", "+event);
}
}
}
- });
+ };
+ // addListener (SWT.Move, listener);
+ addListener (SWT.Resize, listener);
+ addListener (SWT.Paint, listener);
+ addListener (SWT.Dispose, listener);
+ }
- addControlListener(new ControlAdapter() {
- @Override
- public void controlResized(final ControlEvent arg0) {
- updateSizeCheck();
- }
- });
+ @Override
+ public void setBounds(final int x, final int y, final int width, final int height) {
+ super.setBounds(x, y, width, height);
+ if( DEBUG ) {
+ System.err.println("NewtCanvasSWT.setBounds: "+x+"/"+y+" "+width+"x"+height);
+ }
+ if( SWTAccessor.isOSX ) {
+ // Force newtChild to update its size and position (OSX only)
+ updatePosSizeCheck(x, y, width, height, true /* updatePos */);
+ }
}
-
+
/** assumes nativeWindow == null ! */
protected final boolean validateNative() {
- if( isDisposed() ) {
- return false;
- }
updateSizeCheck();
final Rectangle nClientArea = clientArea;
- if(0 == nClientArea.width * nClientArea.height) {
+ if(0 >= nClientArea.width || 0 >= nClientArea.height) {
return false;
}
-
+ screen.getDevice().open();
+
/* Native handle for the control, used to associate with GLContext */
final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
final int visualID = SWTAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle);
final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID);
if(DEBUG) {
System.err.println("NewtCanvasSWT.validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid);
- }
+ }
if( visualIDValid ) {
- /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
+ /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
* Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */
final CapabilitiesImmutable caps = new Capabilities();
final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDevice(), caps);
@@ -177,27 +226,64 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
if(DEBUG) {
System.err.println("NewtCanvasSWT.validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config);
// Thread.dumpStack();
- }
+ }
if (null == config) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
nativeWindow = new SWTNativeWindow(config, nativeWindowHandle);
reparentWindow( true );
+ if( SWTAccessor.isOSX && newtChildReady ) {
+ // initial positioning for OSX, called when the window is created
+ newtChild.setPosition(getLocation().x, getLocation().y);
+ }
}
return null != nativeWindow;
}
-
+
protected final void updateSizeCheck() {
- final Rectangle oClientArea = clientArea;
final Rectangle nClientArea = getClientArea();
- if ( nClientArea != null &&
- ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
- ) {
- clientArea = nClientArea; // write back new value
- if( null != newtChild ) {
- newtChild.setSize(clientArea.width, clientArea.height);
+ if( null != nClientArea ) {
+ updatePosSizeCheck(nClientArea.x, nClientArea.y, nClientArea.width, nClientArea.height, false /* updatePos */);
+ }
+ }
+ protected final void updatePosSizeCheck() {
+ final Rectangle nClientArea = getClientArea();
+ if( null != nClientArea ) {
+ updatePosSizeCheck(nClientArea.x, nClientArea.y, nClientArea.width, nClientArea.height, true /* updatePos */);
+ }
+ }
+ protected final void updatePosSizeCheck(final int newX, final int newY, final int newWidth, final int newHeight, final boolean updatePos) {
+ final boolean sizeChanged, posChanged;
+ final Rectangle nClientArea;
+ {
+ final Rectangle oClientArea = clientArea;
+ sizeChanged = newWidth != oClientArea.width || newHeight != oClientArea.height;
+ posChanged = newX != oClientArea.x || newY != oClientArea.y;
+ if( sizeChanged || posChanged ) {
+ nClientArea = new Rectangle(updatePos ? newX : oClientArea.x, updatePos ? newY : oClientArea.y, newWidth, newHeight);
+ clientArea = nClientArea;
+ } else {
+ nClientArea = clientArea;
+ }
+ }
+ if(DEBUG) {
+ final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0;
+ System.err.println("NewtCanvasSWT.updatePosSizeCheck: sizeChanged "+sizeChanged+", posChanged "+posChanged+", updatePos "+updatePos+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(nsh));
+ }
+ if( sizeChanged ) {
+ if( newtChildReady ) {
+ newtChild.setSize(nClientArea.width, nClientArea.height);
+ } else {
+ postSetSize = true;
+ }
+ }
+ if( updatePos && posChanged ) {
+ if( newtChildReady ) {
+ newtChild.setPosition(nClientArea.x, nClientArea.y);
+ } else {
+ postSetPos = true;
}
}
}
@@ -206,7 +292,7 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
public void update() {
// don't paint background etc .. nop avoids flickering
}
-
+
/**
* Destroys this resource:
* <ul>
@@ -226,49 +312,61 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
}
configureNewtChild(false);
newtChild.setVisible(false);
- newtChild.reparentWindow(null);
+ newtChild.reparentWindow(null, -1, -1, 0 /* hint */);
newtChild.destroy();
newtChild = null;
}
+ screen.getDevice().close();
nativeWindow = null;
- super.dispose();
+ super.dispose();
}
-
+
+ private Point getParentLocationOnScreen() {
+ final org.eclipse.swt.graphics.Point[] parentLoc = new org.eclipse.swt.graphics.Point[] { null };
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ parentLoc[0] = getParent().toDisplay(0,0);
+ } } );
+ return new Point(parentLoc[0].x, parentLoc[0].y);
+ }
+
/** @return this SWT Canvas NativeWindow representation, may be null in case it has not been realized. */
public NativeWindow getNativeWindow() { return nativeWindow; }
-
+
+ @Override
public WindowClosingMode getDefaultCloseOperation() {
- return newtChildCloseOp; // FIXME
+ return newtChildCloseOp; // TODO: implement ?!
}
- public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
- return newtChildCloseOp = op; // FIXME
+ @Override
+ public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
+ return newtChildCloseOp = op; // TODO: implement ?!
}
boolean isParent() {
- return null!=newtChild ;
+ return null!=newtChild ;
}
boolean isFullscreen() {
return null != newtChild && newtChild.isFullscreen();
}
- /**
+ /**
* Sets a new NEWT child, provoking reparenting.
* <p>
* A previously detached <code>newChild</code> will be released to top-level status
- * and made invisible.
+ * and made invisible.
* </p>
* <p>
- * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
- * produced much cleaner visual results.
+ * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
+ * produced much cleaner visual results.
* </p>
* <p>
* Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
- * via {@link Display#setEDTUtil(EDTUtil)}.
+ * via {@link Display#setEDTUtil(EDTUtil)}.
* </p>
- * @return the previous attached newt child.
+ * @return the previous attached newt child.
*/
public Window setNEWTChild(final Window newChild) {
final Window prevChild = newtChild;
@@ -285,62 +383,67 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
if(null != nativeWindow && null != newChild) {
reparentWindow( true );
}
- return prevChild;
+ return prevChild;
}
-
+
/** @return the current NEWT child */
public Window getNEWTChild() {
return newtChild;
}
-
+
@Override
- public boolean setParent(Composite parent) {
+ public boolean setParent(final Composite parent) {
return super.setParent(parent);
}
- /* package */ void configureNewtChild(boolean attach) {
-
+ /* package */ void configureNewtChild(final boolean attach) {
+ newtChildReady = attach;
if( null != newtChild ) {
newtChild.setKeyboardFocusHandler(null);
- if(attach) {
- newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
+ if(attach) {
+ newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
} else {
newtChild.setFocusAction(null);
- newtChild.setDefaultCloseOperation(newtChildCloseOp);
+ newtChild.setDefaultCloseOperation(newtChildCloseOp);
}
}
}
- void reparentWindow(boolean add) {
+ void reparentWindow(final boolean add) {
if( null == newtChild ) {
return; // nop
}
if(DEBUG) {
System.err.println("NewtCanvasSWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
}
-
+
newtChild.setFocusAction(null); // no AWT focus traversal ..
if(add) {
updateSizeCheck();
final int w = clientArea.width;
final int h = clientArea.height;
- final Display newtDisplay = newtChild.getScreen().getDisplay();
- newtDisplay.setEDTUtil(new SWTEDTUtil(newtDisplay, getDisplay()));
-
+ // set SWT EDT and start it
+ {
+ final Display newtDisplay = newtChild.getScreen().getDisplay();
+ final EDTUtil edtUtil = new SWTEDTUtil(newtDisplay, getDisplay());
+ edtUtil.start();
+ newtDisplay.setEDTUtil( edtUtil );
+ }
+
newtChild.setSize(w, h);
- newtChild.reparentWindow(nativeWindow);
+ newtChild.reparentWindow(nativeWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
newtChild.setVisible(true);
configureNewtChild(true);
newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
- // force this SWT Canvas to be focus-able,
- // since this it is completely covered by the newtChild (z-order).
+ // force this SWT Canvas to be focus-able,
+ // since it is completely covered by the newtChild (z-order).
setEnabled(true);
} else {
configureNewtChild(false);
newtChild.setVisible(false);
- newtChild.reparentWindow(null);
+ newtChild.reparentWindow(null, -1, -1, 0 /* hints */);
}
if(DEBUG) {
System.err.println("NewtCanvasSWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
@@ -348,34 +451,34 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
}
private final void requestFocusNEWTChild() {
- if( null != newtChild ) {
+ if( newtChildReady ) {
newtChild.setFocusAction(null);
newtChild.requestFocus();
}
}
-
+
@Override
public boolean forceFocus() {
final boolean res = NewtCanvasSWT.super.forceFocus();
requestFocusNEWTChild();
- return res;
+ return res;
}
-
+
private class SWTNativeWindow implements NativeWindow {
private final AbstractGraphicsConfiguration config;
private final long nativeWindowHandle;
private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX
-
- public SWTNativeWindow(AbstractGraphicsConfiguration config, long nativeWindowHandle) {
+
+ public SWTNativeWindow(final AbstractGraphicsConfiguration config, final long nativeWindowHandle) {
this.config = config;
this.nativeWindowHandle = nativeWindowHandle;
- if(isOSX) {
+ if( SWTAccessor.isOSX ) {
this.insets = OSXUtil.GetInsets(nativeWindowHandle);
} else {
this.insets = new Insets(0, 0, 0, 0);
}
}
-
+
@Override
public int lockSurface() throws NativeWindowException, RuntimeException {
return NativeSurface.LOCK_SUCCESS;
@@ -400,31 +503,54 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
}
@Override
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { }
+ public void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) { }
@Override
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ public void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
}
@Override
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { }
+ public void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) { }
@Override
- public long getSurfaceHandle() {
+ public long getSurfaceHandle() {
return 0;
}
@Override
public int getWidth() {
- return clientArea.width;
+ return getSurfaceWidth(); // FIXME: Use 'scale' or an actual window-width
}
@Override
public int getHeight() {
+ return getSurfaceHeight(); // FIXME: Use 'scale' or an actual window-width
+ }
+
+ @Override
+ public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
+ return pixelUnitsAndResult; // FIXME HiDPI: use 'pixelScale'
+ }
+
+ @Override
+ public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
+ return windowUnitsAndResult; // FIXME HiDPI: use 'pixelScale'
+ }
+
+ @Override
+ public int getSurfaceWidth() {
+ return clientArea.width;
+ }
+
+ @Override
+ public int getSurfaceHeight() {
return clientArea.height;
}
@Override
+ public final NativeSurface getNativeSurface() { return this; }
+
+ @Override
public AbstractGraphicsConfiguration getGraphicsConfiguration() {
return config;
}
@@ -440,7 +566,7 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
}
@Override
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) { }
+ public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) { }
@Override
public void destroy() { }
@@ -471,36 +597,38 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
}
@Override
- public Point getLocationOnScreen(Point point) {
- if( isOSX ) {
- final Point los = OSXUtil.GetLocationOnScreen(nativeWindowHandle, false, 0, 0);
- // top-level position -> client window position
- los.setX(los.getX() + insets.getLeftWidth());
- los.setY(los.getY() + insets.getTopHeight());
- if(null!=point) {
- return point.translate(los);
- } else {
- return los;
- }
+ public Point getLocationOnScreen(final Point point) {
+ final Point los; // client window location on screen
+ if( SWTAccessor.isOSX ) {
+ // let getLOS provide the point where the child window may be placed
+ // from, as taken from SWT Control.toDisplay();
+ los = getParentLocationOnScreen();
+ } else if (SWTAccessor.isX11) {
+ final AbstractGraphicsScreen s = config.getScreen();
+ los = X11Lib.GetRelativeLocation(s.getDevice().getHandle(), s.getIndex(), nativeWindowHandle, 0 /*root win*/, 0, 0);
+ } else if (SWTAccessor.isWindows) {
+ los = GDIUtil.GetRelativeLocation( nativeWindowHandle, 0 /*root win*/, 0, 0);
} else {
- // client position on 'normal' windowing systems is 0/0
- if(null == point) {
- point = new Point(0, 0);
- }
- return point;
+ // fall-back to 0/0
+ los = new Point(0, 0);
+ }
+ if(null!=point) {
+ return point.translate(los);
+ } else {
+ return los;
}
}
@Override
public boolean hasFocus() {
return isFocusControl();
- }
+ }
};
- static String newtWinHandleToHexString(Window w) {
+ static String newtWinHandleToHexString(final Window w) {
return null != w ? toHexString(w.getWindowHandle()) : "nil";
}
- static String toHexString(long l) {
+ static String toHexString(final long l) {
return "0x"+Long.toHexString(l);
}
}
diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
deleted file mode 100644
index d4b83d891..000000000
--- a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/**
- * Copyright 2012 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.newt.swt;
-
-import java.awt.EventQueue;
-
-import jogamp.newt.Debug;
-
-import com.jogamp.newt.util.EDTUtil;
-
-/**
- * Simple {@link EDTUtil} implementation utilizing the SWT UI thread
- * of the given {@link Display}.
- */
-public class SWTEDTUtil implements EDTUtil {
- public static final boolean DEBUG = Debug.debug("EDT");
-
- private final Object edtLock = new Object(); // locking the EDT start/stop state
- private final ThreadGroup threadGroup;
- private final String name;
- private final Runnable dispatchMessages;
- private final org.eclipse.swt.widgets.Display swtDisplay;
- private NewtEventDispatchThread nedt = null;
- private int start_iter=0;
- private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
-
- public SWTEDTUtil(final com.jogamp.newt.Display newtDisplay, org.eclipse.swt.widgets.Display swtDisplay) {
- this.threadGroup = Thread.currentThread().getThreadGroup();
- this.name=Thread.currentThread().getName()+"-SWTDisplay-"+newtDisplay.getFQName()+"-EDT-";
- this.dispatchMessages = new Runnable() {
- public void run() {
- ((jogamp.newt.DisplayImpl) newtDisplay).dispatchMessages();
- } };
- this.swtDisplay = swtDisplay;
- this.nedt = new NewtEventDispatchThread(threadGroup, name);
- this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
- }
-
- public final org.eclipse.swt.widgets.Display getDisplay() {
- return swtDisplay;
- }
-
- @Override
- public long getPollPeriod() {
- return pollPeriod;
- }
-
- @Override
- public void setPollPeriod(long ms) {
- pollPeriod = ms;
- }
-
- @Override
- public void reset() {
- synchronized(edtLock) {
- waitUntilStopped();
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT reset - edt: "+nedt);
- }
- this.nedt = new NewtEventDispatchThread(threadGroup, name);
- this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
- }
- }
-
- private final void startImpl() {
- if(nedt.isAlive()) {
- throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt);
- }
- start_iter++;
- nedt.setName(name+start_iter);
- nedt.shouldStop = false;
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT START - edt: "+nedt);
- // Thread.dumpStack();
- }
- nedt.start();
- }
-
- @Override
- public boolean isCurrentThreadEDT() {
- return swtDisplay.getThread() == Thread.currentThread();
- }
-
- @Override
- public final boolean isCurrentThreadNEDT() {
- return nedt == Thread.currentThread();
- }
-
- @Override
- public final boolean isCurrentThreadEDTorNEDT() {
- final Thread ct = Thread.currentThread();
- return ct == swtDisplay.getThread() || ct == nedt ;
- }
-
- @Override
- public boolean isRunning() {
- return nedt.isRunning() ; // SWT is always running
- }
-
- @Override
- public final void invokeStop(Runnable task) {
- invokeImpl(true, task, true);
- }
-
- @Override
- public final void invoke(boolean wait, Runnable task) {
- invokeImpl(wait, task, false);
- }
-
- private void invokeImpl(boolean wait, Runnable task, boolean stop) {
- if(task == null) {
- throw new RuntimeException("Null Runnable");
- }
- synchronized(edtLock) { // lock the EDT status
- if( nedt.shouldStop ) {
- // drop task ..
- if(DEBUG) {
- System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+nedt);
- Thread.dumpStack();
- }
- return;
- }
- // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
- // Thread.dumpStack();
- if(stop) {
- nedt.shouldStop = true;
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt);
- // Thread.dumpStack();
- }
- }
-
- // start if should not stop && not started yet
- if( !stop && !nedt.isRunning() ) {
- startImpl();
- }
- }
- if(wait) {
- swtDisplay.syncExec(task);
- } else {
- swtDisplay.asyncExec(task);
- }
- }
-
- @Override
- final public void waitUntilIdle() {
- final NewtEventDispatchThread _edt;
- synchronized(edtLock) {
- _edt = nedt;
- }
- if(!_edt.isRunning() || EventQueue.isDispatchThread() || _edt == Thread.currentThread()) {
- return;
- }
- try {
- swtDisplay.syncExec(new Runnable() {
- public void run() { }
- });
- } catch (Exception e) { }
- }
-
- @Override
- final public void waitUntilStopped() {
- synchronized(edtLock) {
- if(nedt.isRunning() && nedt != Thread.currentThread() ) {
- while(nedt.isRunning()) {
- try {
- edtLock.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
-
- class NewtEventDispatchThread extends Thread {
- volatile boolean shouldStop = false;
- volatile boolean isRunning = false;
- Object sync = new Object();
-
- public NewtEventDispatchThread(ThreadGroup tg, String name) {
- super(tg, name);
- }
-
- final public boolean isRunning() {
- return isRunning;
- }
-
- @Override
- final public void start() throws IllegalThreadStateException {
- isRunning = true;
- super.start();
- }
-
- /**
- * Utilizing locking only on tasks and its execution,
- * not for event dispatching.
- */
- @Override
- final public void run() {
- if(DEBUG) {
- System.err.println(getName()+": EDT run() START "+ getName());
- }
- RuntimeException error = null;
- try {
- do {
- // event dispatch
- if(!shouldStop) {
- // FIXME: Determine whether we require to run the
- // delivery of events (dispatch) on AWT-EDT.
- // Since the WindowDriver itself delivers all Window related events,
- // this shall not be required.
- // AWTEDTExecutor.singleton.invoke(true, dispatchMessages);
- dispatchMessages.run();
- }
- // wait
- synchronized(sync) {
- if(!shouldStop) {
- try {
- sync.wait(pollPeriod);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- } while(!shouldStop) ;
- } catch (Throwable t) {
- // handle errors ..
- shouldStop = true;
- if(t instanceof RuntimeException) {
- error = (RuntimeException) t;
- } else {
- error = new RuntimeException("Within EDT", t);
- }
- } finally {
- if(DEBUG) {
- System.err.println(getName()+": EDT run() END "+ getName()+", "+error);
- }
- synchronized(edtLock) {
- isRunning = !shouldStop;
- if(!isRunning) {
- edtLock.notifyAll();
- }
- }
- if(DEBUG) {
- System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error);
- }
- if(null!=error) {
- throw error;
- }
- } // finally
- } // run()
- } // EventDispatchThread
-
-}
diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
index 7e19d9de5..58aa67105 100644
--- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
+++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
@@ -63,25 +63,30 @@ public interface EDTUtil {
* @param ms poll period in milliseconds
*/
public void setPollPeriod(long ms);
-
+
/**
- * Create a new EDT. One should invoke <code>reset()</code><br>
- * after <code>invokeStop(..)</code> in case another start via <code>invoke(..)</code>
- * is expected.
+ * Starts the EDT after it's creation or after {@link #invokeStop(boolean, Runnable) stopping}.
+ * <p>
+ * If the EDT is running, it must be {@link #invokeStop(boolean, Runnable) stopped} first
+ * and the caller should wait {@link #waitUntilStopped() until it's stopped}.
+ * </p>
*
- * @see #invoke(boolean, java.lang.Runnable)
- * @see #invokeStop(java.lang.Runnable)
+ * @throws IllegalStateException if EDT is running and not subject to be stopped, i.e. {@link #isRunning()} returns true
+ * @throws RuntimeException if EDT could not be started
+ *
+ * @see #invokeStop(boolean, java.lang.Runnable)
+ * @see #waitUntilStopped()
*/
- public void reset();
+ public void start() throws IllegalStateException;
/**
* Returns true if the current thread is the event dispatch thread (EDT).
* <p>
- * The EDT is the platform specific thread dispatching toolkit-events
+ * The EDT is the platform specific thread dispatching toolkit-events
* and executing toolkit-tasks enqueued via {@link #invoke(boolean, Runnable)}.
* </p>
* <p>
- * Usually it is the same thread as used to dequeue informal {@link NEWTEvent}s (NEDT), see {@link #isCurrentThreadNEDT()},
+ * Usually it is the same thread as used to dequeue informal {@link NEWTEvent}s (NEDT), see {@link #isCurrentThreadNEDT()},
* however, this may differ, e.g. SWT and AWT implementation.
* </p>
*/
@@ -90,60 +95,74 @@ public interface EDTUtil {
/**
* Returns true if the current thread is the internal NEWT event dequeue thread (NEDT).
* <p>
- * The NEDT is the NEWT thread used to dequeue informal {@link NEWTEvent}s enqueued internally
+ * The NEDT is the NEWT thread used to dequeue informal {@link NEWTEvent}s enqueued internally
* via {@link DisplayImpl#enqueueEvent(boolean, NEWTEvent)}.
* </p>
* <p>
- * Usually it is the same thread as the EDT, see {@link #isCurrentThreadEDT()},
+ * Usually it is the same thread as the EDT, see {@link #isCurrentThreadEDT()},
* however, this may differ, e.g. SWT and AWT implementation.
* </p>
*/
public boolean isCurrentThreadNEDT();
-
+
/**
* Returns <code>true</code> if either {@link #isCurrentThreadEDT()} or {@link #isCurrentThreadNEDT()} is <code>true</code>,
* otherwise <code>false</code>.
*/
public boolean isCurrentThreadEDTorNEDT();
-
+
/**
- * @return True if EDT is running
+ * @return True if EDT is running and not subject to be stopped.
*/
public boolean isRunning();
- /**
+ /**
* Append the final task to the EDT task queue,
- * signals EDT to stop and wait until stopped.<br>
+ * signals EDT to stop.
+ * <p>
+ * If <code>wait</code> is <code>true</code> methods
+ * blocks until EDT is stopped.
+ * </p>
+ * <p>
+ * <code>task</code> maybe <code>null</code><br/>
* Due to the nature of this method:
* <ul>
* <li>All previous queued tasks will be finished.</li>
* <li>No new tasks are allowed, an Exception is thrown.</li>
* <li>Can be issued from within EDT, ie from within an enqueued task.</li>
- * <li>{@link #reset()} may follow immediately, ie creating a new EDT</li>
+ * <li>{@link #start()} may follow immediately, ie creating a new EDT</li>
* </ul>
+ * </p>
+ * @return true if <code>task</code> has been executed or queued for later execution, otherwise false
*/
- public void invokeStop(Runnable finalTask);
+ public boolean invokeStop(boolean wait, Runnable finalTask);
- /**
- * Shall start the thread if not running.<br>
- * Append task to the EDT task queue.<br>
- * Wait until execution is finished if <code>wait == true</code>.<br>
+ /**
+ * Appends task to the EDT task queue if current thread is not EDT,
+ * otherwise execute task immediately.
+ * <p>
+ * Wait until execution is finished if <code>wait == true</code>.
+ * </p>
* Can be issued from within EDT, ie from within an enqueued task.<br>
- *
- * @throws RuntimeException in case EDT is stopped and not {@link #reset()}
+ * @return true if <code>task</code> has been executed or queued for later execution, otherwise false
*/
- public void invoke(boolean wait, Runnable task);
+ public boolean invoke(boolean wait, Runnable task);
- /**
+ /**
* Wait until the EDT task queue is empty.<br>
* The last task may still be in execution when this method returns.
+ * @return true if waited for idle, otherwise false, i.e. in case of current thread is EDT or NEDT
*/
- public void waitUntilIdle();
+ public boolean waitUntilIdle();
/**
* Wait until EDT task is stopped.<br>
- * No <code>stop</code> action is performed, {@link #invokeStop(java.lang.Runnable)} should be used before.
+ * No <code>stop</code> action is performed, {@link #invokeStop(boolean, java.lang.Runnable)} should be used before.
+ * <p>
+ * If caller thread is EDT or NEDT, this call will not block.
+ * </p>
+ * @return true if stopped, otherwise false, i.e. in case of current thread is EDT or NEDT
*/
- public void waitUntilStopped();
+ public boolean waitUntilStopped();
}
diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java
index 5e79e9b49..80da1ce3b 100644
--- a/src/newt/classes/com/jogamp/newt/util/MainThread.java
+++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -45,6 +45,7 @@ import java.util.List;
import javax.media.nativewindow.NativeWindowFactory;
import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
import jogamp.newt.Debug;
@@ -54,13 +55,13 @@ import jogamp.newt.NEWTJNILibLoader;
* NEWT Utility class MainThread<P>
*
* <p>
- * FIXME: Update this documentation!
+ * FIXME: Update this documentation!
* This class just provides a main-thread utility, forking of a main java class
* on another thread while being able to continue doing platform specific things
* on the main-thread. The latter is essential for eg. MacOSX, where we continue
* to run NSApp.run().
* </p>
- *
+ *
* This class provides a startup singleton <i>main thread</i>,
* from which a new thread with the users main class is launched.<br>
*
@@ -72,17 +73,17 @@ import jogamp.newt.NEWTJNILibLoader;
* use a NEWT multithreaded application with window handling within the different threads,
* even on these restricted platforms.<br>
*
- * To support your NEWT Window platform,
+ * To support your NEWT Window platform,
* you have to pass your <i>main thread</i> actions to {@link #invoke invoke(..)},
* have a look at the {@link jogamp.newt.driver.macosx.WindowDriver NEWT Mac OSX Window} driver implementation.<br>
- * <i>TODO</i>: Some hardcoded dependencies exist in this implementation,
+ * <i>TODO</i>: Some hardcoded dependencies exist in this implementation,
* where you have to patch this code or factor it out. <P>
- *
+ *
* If your platform is not Mac OS X, but you want to test your code without modifying
* this class, you have to set the system property <code>newt.MainThread.force</code> to <code>true</code>.<P>
*
* The code is compatible with all other platform, which support multithreaded windowing handling.
- * Since those platforms won't trigger the <i>main thread</i> serialization, the main method
+ * Since those platforms won't trigger the <i>main thread</i> serialization, the main method
* will be simply executed, in case you haven't set <code>newt.MainThread.force</code> to <code>true</code>.<P>
*
* Test case on Mac OS X (or any other platform):
@@ -96,36 +97,36 @@ public class MainThread {
private static final Platform.OSType osType;
private static final boolean isMacOSX;
private static final ThreadGroup rootThreadGroup;
-
+
/** if true, use the main thread EDT, otherwise AWT's EDT */
public static final boolean HINT_USE_MAIN_THREAD;
-
+
static {
NativeWindowFactory.initSingleton();
NEWTJNILibLoader.loadNEWT();
- HINT_USE_MAIN_THREAD = !NativeWindowFactory.isAWTAvailable() ||
- Debug.getBooleanProperty("newt.MainThread.force", true);
+ HINT_USE_MAIN_THREAD = !NativeWindowFactory.isAWTAvailable() ||
+ PropertyAccess.getBooleanProperty("newt.MainThread.force", true);
osType = Platform.getOSType();
isMacOSX = osType == Platform.OSType.MACOS;
rootThreadGroup = getRootThreadGroup();
}
-
+
public static boolean useMainThread = false;
-
+
protected static final boolean DEBUG = Debug.debug("MainThread");
private static final MainThread singletonMainThread = new MainThread(); // one singleton MainThread
-
+
private static final ThreadGroup getRootThreadGroup() {
ThreadGroup rootGroup = Thread.currentThread( ).getThreadGroup( );
ThreadGroup parentGroup;
while ( ( parentGroup = rootGroup.getParent() ) != null ) {
rootGroup = parentGroup;
}
- return rootGroup;
+ return rootGroup;
}
-
- private static final Thread[] getAllThreads(int[] count) {
+
+ private static final Thread[] getAllThreads(final int[] count) {
int tn;
Thread[] threads = new Thread[ rootThreadGroup.activeCount() ];
while ( ( tn = rootThreadGroup.enumerate( threads, true ) ) == threads.length ) {
@@ -135,9 +136,9 @@ public class MainThread {
return threads;
}
private static final List<Thread> getNonDaemonThreads() {
- List<Thread> res = new ArrayList<Thread>();
- int[] tn = { 0 };
- Thread[] threads = getAllThreads(tn);
+ final List<Thread> res = new ArrayList<Thread>();
+ final int[] tn = { 0 };
+ final Thread[] threads = getAllThreads(tn);
for(int i = tn[0] - 1; i >= 0; i--) {
final Thread thread = threads[i];
try {
@@ -145,31 +146,31 @@ public class MainThread {
res.add(thread);
if(DEBUG) System.err.println("XXX0: "+thread.getName()+", "+thread);
}
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
}
}
- return res;
+ return res;
}
- private static final int getNonDaemonThreadCount(List<Thread> ignoreThreads) {
+ private static final int getNonDaemonThreadCount(final List<Thread> ignoreThreads) {
int res = 0;
- int[] tn = { 0 };
- Thread[] threads = getAllThreads(tn);
-
+ final int[] tn = { 0 };
+ final Thread[] threads = getAllThreads(tn);
+
for(int i = tn[0] - 1; i >= 0; i--) {
final Thread thread = threads[i];
try {
- if(thread.isAlive() && !thread.isDaemon() && !ignoreThreads.contains(thread)) {
+ if(thread.isAlive() && !thread.isDaemon() && !ignoreThreads.contains(thread)) {
res++;
if(DEBUG) System.err.println("MainAction.run(): non daemon thread: "+thread);
}
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
}
}
- return res;
+ return res;
}
-
+
static class UserApp extends Thread {
private final String mainClassNameShort;
private final String mainClassName;
@@ -177,11 +178,11 @@ public class MainThread {
private final Method mainClassMain;
private List<Thread> nonDaemonThreadsAtStart;
- public UserApp(String mainClassName, String[] mainClassArgs) throws SecurityException, NoSuchMethodException, ClassNotFoundException {
+ public UserApp(final String mainClassName, final String[] mainClassArgs) throws SecurityException, NoSuchMethodException, ClassNotFoundException {
super();
this.mainClassName=mainClassName;
this.mainClassArgs=mainClassArgs;
-
+
final Class<?> mainClass = ReflectionUtil.getClass(mainClassName, true, getClass().getClassLoader());
if(null==mainClass) {
throw new ClassNotFoundException("MainAction couldn't find main class "+mainClassName);
@@ -192,7 +193,7 @@ public class MainThread {
setName(getName()+"-UserApp-"+mainClassNameShort);
setDaemon(false);
-
+
if(DEBUG) System.err.println("MainAction(): instantiated: "+getName()+", is daemon "+isDaemon()+", main-class: "+mainClass.getName());
}
@@ -204,10 +205,10 @@ public class MainThread {
try {
if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" invoke "+mainClassName);
mainClassMain.invoke(null, new Object[] { mainClassArgs } );
- } catch (InvocationTargetException ite) {
+ } catch (final InvocationTargetException ite) {
ite.getTargetException().printStackTrace();
return;
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
return;
}
@@ -219,7 +220,7 @@ public class MainThread {
if(DEBUG) System.err.println("MainAction.run(): post user app, non daemon threads alive: "+ndtr);
try {
Thread.sleep(1000);
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
e.printStackTrace();
}
}
@@ -230,32 +231,32 @@ public class MainThread {
if(isMacOSX) {
try {
if(DEBUG) {
- System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.0");
+ System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.0");
}
- ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "stopNSApplication",
+ ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "stopNSApplication",
null, null, MainThread.class.getClassLoader());
if(DEBUG) {
- System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.X");
+ System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.X");
}
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
} else {
if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainAction fin - System.exit(0)");
- System.exit(0);
- }
+ System.exit(0);
+ }
}
}
}
private static UserApp mainAction;
- /** Your new java application main entry, which pipelines your application
- * @throws ClassNotFoundException
- * @throws NoSuchMethodException
+ /** Your new java application main entry, which pipelines your application
+ * @throws ClassNotFoundException
+ * @throws NoSuchMethodException
* @throws SecurityException */
- public static void main(String[] args) throws SecurityException, NoSuchMethodException, ClassNotFoundException {
+ public static void main(final String[] args) throws SecurityException, NoSuchMethodException, ClassNotFoundException {
final Thread cur = Thread.currentThread();
-
+
useMainThread = HINT_USE_MAIN_THREAD;
if(DEBUG) {
@@ -268,13 +269,13 @@ public class MainThread {
if(!useMainThread && !NativeWindowFactory.isAWTAvailable()) {
throw new RuntimeException("!USE_MAIN_THREAD and no AWT available");
}
-
+
if(args.length==0) {
return;
}
- String mainClassName=args[0];
- String[] mainClassArgs=new String[args.length-1];
+ final String mainClassName=args[0];
+ final String[] mainClassArgs=new String[args.length-1];
if(args.length>1) {
System.arraycopy(args, 1, mainClassArgs, 0, args.length-1);
}
@@ -282,32 +283,32 @@ public class MainThread {
mainAction = new UserApp(mainClassName, mainClassArgs);
if(isMacOSX) {
- ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "initSingleton",
+ ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "initSingleton",
null, null, MainThread.class.getClassLoader());
}
if ( useMainThread ) {
try {
cur.setName(cur.getName()+"-MainThread");
- } catch (Exception e) {}
-
+ } catch (final Exception e) {}
+
// dispatch user's main thread ..
mainAction.start();
-
+
if(isMacOSX) {
try {
if(DEBUG) {
- System.err.println("MainThread.main(): "+cur.getName()+"- runNSApp");
+ System.err.println("MainThread.main(): "+cur.getName()+"- runNSApp");
}
- ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "runNSApplication",
+ ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "runNSApplication",
null, null, MainThread.class.getClassLoader());
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
- }
- if(DEBUG) { System.err.println("MainThread - wait until last non daemon thread ends ..."); }
+ }
+ if(DEBUG) { System.err.println("MainThread - wait until last non daemon thread ends ..."); }
} else {
- // run user's main in this thread
+ // run user's main in this thread
mainAction.run();
}
}
diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java b/src/newt/classes/com/jogamp/newt/util/MonitorMode.java
deleted file mode 100644
index 8104f207a..000000000
--- a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.newt.util;
-
-import javax.media.nativewindow.util.*;
-
-/** Immutable MonitorMode Class, consisting of it's read only components:<br>
- * <ul>
- * <li>{@link javax.media.nativewindow.util.SurfaceSize} surface memory size</li>
- * <li>{@link javax.media.nativewindow.util.DimensionImmutable} size in [mm]</li>
- * <li><code>refresh rate</code></li>
- * </ul>
- */
-public class MonitorMode {
- SurfaceSize surfaceSize;
- DimensionImmutable screenSizeMM; // in [mm]
- int refreshRate;
-
- public MonitorMode(SurfaceSize surfaceSize, DimensionImmutable screenSizeMM, int refreshRate) {
- // Don't validate screenSizeMM and refreshRate, since they may not be supported by the OS
- if(null==surfaceSize) {
- throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")");
- }
- this.surfaceSize=surfaceSize;
- this.screenSizeMM=screenSizeMM;
- this.refreshRate=refreshRate;
- }
-
- public final SurfaceSize getSurfaceSize() {
- return surfaceSize;
- }
-
- public final DimensionImmutable getScreenSizeMM() {
- return screenSizeMM;
- }
-
- public final int getRefreshRate() {
- return refreshRate;
- }
-
- public final String toString() {
- return new String("[ "+surfaceSize+" x "+refreshRate+" Hz, "+screenSizeMM+" mm ]");
- }
-
- /**
- * Checks whether two size objects are equal. Two instances
- * of <code>MonitorMode</code> are equal if the three components
- * <code>surfaceSize</code> and <code>refreshRate</code>
- * are equal. <code>screenSizeMM</code> is kept out intentional to reduce the requirements for finding the current mode.
- * @return <code>true</code> if the two dimensions are equal;
- * otherwise <code>false</code>.
- */
- public final boolean equals(Object obj) {
- if (this == obj) { return true; }
- if (obj instanceof MonitorMode) {
- MonitorMode p = (MonitorMode)obj;
- return getSurfaceSize().equals(p.getSurfaceSize()) &&
- /* getScreenSizeMM().equals(p.getScreenSizeMM()) && */
- getRefreshRate() == p.getRefreshRate() ;
- }
- return false;
- }
-
- /**
- * returns a hash code over <code>surfaceSize</code> and <code>refreshRate</code>.
- * <code>screenSizeMM</code> is kept out intentional to reduce the requirements for finding the current mode.
- */
- public final int hashCode() {
- // 31 * x == (x << 5) - x
- int hash = 31 + getSurfaceSize().hashCode();
- /* hash = ((hash << 5) - hash) + getScreenSizeMM().hashCode(); */
- hash = ((hash << 5) - hash) + getRefreshRate();
- return hash;
- }
-}
-
diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java b/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java
new file mode 100644
index 000000000..e5f8ff17c
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java
@@ -0,0 +1,258 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.newt.util;
+
+import com.jogamp.newt.MonitorMode;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.SurfaceSize;
+
+/**
+ * Convenient {@link com.jogamp.newt.MonitorMode} utility methods,
+ * filters etc.
+ */
+public class MonitorModeUtil {
+
+ public static int getIndex(final List<MonitorMode> monitorModes, final MonitorMode search) {
+ return monitorModes.indexOf(search);
+ }
+
+ public static int getIndexByHashCode(final List<MonitorMode> monitorModes, final MonitorMode search) {
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; i<monitorModes.size(); i++) {
+ if ( search.hashCode() == monitorModes.get(i).hashCode() ) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ public static MonitorMode getByNativeSizeRateIdAndRotation(final List<MonitorMode> monitorModes, final MonitorMode.SizeAndRRate sizeAndRate, final int modeId, final int rotation) {
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if( mode.getSizeAndRRate().equals(sizeAndRate) && mode.getId() == modeId && mode.getRotation() == rotation ) {
+ return mode;
+ }
+ }
+ }
+ return null;
+ }
+
+ /** Sort the given {@link MonitorMode} collection w/ {@link MonitorMode#compareTo(MonitorMode)} function. */
+ public static void sort(final List<MonitorMode> monitorModes, final boolean ascendingOrder) {
+ if( ascendingOrder ) {
+ Collections.sort(monitorModes);
+ } else {
+ Collections.sort(monitorModes, MonitorMode.monitorModeComparatorInv);
+ }
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @param surfaceSize
+ * @return modes with exact {@link SurfaceSize}. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterBySurfaceSize(final List<MonitorMode> monitorModes, final SurfaceSize surfaceSize) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if(mode.getSurfaceSize().equals(surfaceSize)) {
+ out.add(mode);
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @param rotation
+ * @return modes with exact rotation. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterByRotation(final List<MonitorMode> monitorModes, final int rotation) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if(mode.getRotation() == rotation) {
+ out.add(mode);
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @param bitsPerPixel
+ * @return modes with exact bpp. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterByBpp(final List<MonitorMode> monitorModes, final int bitsPerPixel) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if(mode.getSurfaceSize().getBitsPerPixel() == bitsPerPixel) {
+ out.add(mode);
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @param flags
+ * @return modes with exact flags. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterByFlags(final List<MonitorMode> monitorModes, final int flags) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if(mode.getFlags() == flags) {
+ out.add(mode);
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ * @param monitorModes
+ * @param resolution in pixel units
+ * @return modes with nearest resolution, or matching ones. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterByResolution(final List<MonitorMode> monitorModes, final DimensionImmutable resolution) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ final int resolution_sq = resolution.getHeight()*resolution.getWidth();
+ int mode_dsq=Integer.MAX_VALUE, mode_dsq_idx=0;
+
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ final DimensionImmutable res = mode.getSurfaceSize().getResolution();
+ final int dsq = Math.abs(resolution_sq - res.getHeight()*res.getWidth());
+ if(dsq<mode_dsq) {
+ mode_dsq = dsq;
+ mode_dsq_idx = i;
+ }
+ if(res.equals(resolution)) {
+ out.add(mode);
+ }
+ }
+ if(out.size() == 0 && 0 <= mode_dsq_idx ) {
+ // nearest ..
+ out.add(monitorModes.get(mode_dsq_idx));
+ }
+ }
+ return out;
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @param refreshRate
+ * @return modes with nearest refreshRate, or matching ones. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterByRate(final List<MonitorMode> monitorModes, final float refreshRate) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ float mode_dr = Float.MAX_VALUE;
+ int mode_dr_idx = -1;
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ final float dr = Math.abs(refreshRate - mode.getRefreshRate());
+ if(dr<mode_dr) {
+ mode_dr = dr;
+ mode_dr_idx = i;
+ }
+ if(0 == dr) {
+ out.add(mode);
+ }
+ }
+ if(out.size() == 0 && 0 <= mode_dr_idx ) {
+ // nearest ..
+ out.add(monitorModes.get(mode_dr_idx));
+ }
+ }
+ return out;
+ }
+
+ /**
+ * @param monitorModes
+ * @return modes with highest available bpp (color depth). May return zero sized list for non.
+ */
+ public static List<MonitorMode> getHighestAvailableBpp(final List<MonitorMode> monitorModes) {
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ int highest = -1;
+ for (int i=0; null!=monitorModes && i < monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ final int bpp = mode.getSurfaceSize().getBitsPerPixel();
+ if (bpp > highest) {
+ highest = bpp;
+ }
+ }
+ return filterByBpp(monitorModes, highest);
+ }
+ return new ArrayList<MonitorMode>();
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @return modes with highest available refresh rate. May return zero sized list for non.
+ */
+ public static List<MonitorMode> getHighestAvailableRate(final List<MonitorMode> monitorModes) {
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ float highest = -1;
+ for (int i=0; null!=monitorModes && i < monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ final float rate = mode.getRefreshRate();
+ if (rate > highest) {
+ highest = rate;
+ }
+ }
+ return filterByRate(monitorModes, highest);
+ }
+ return new ArrayList<MonitorMode>();
+ }
+
+}
diff --git a/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java b/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java
deleted file mode 100644
index 93797c5fb..000000000
--- a/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.newt.util;
-
-import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.newt.ScreenMode;
-import java.util.ArrayList;
-import java.util.List;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.SurfaceSize;
-
-/**
- * Convenient {@link com.jogamp.newt.ScreenMode} utility methods,
- * filters etc.
- */
-public class ScreenModeUtil {
- /** WARNING: must be synchronized with ScreenMode.h, native implementation
- * 2: width and height
- */
- public static final int NUM_RESOLUTION_PROPERTIES = 2;
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation
- * 1: bpp
- */
- public static final int NUM_SURFACE_SIZE_PROPERTIES = 1;
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation
- * 3: ScreenSizeMM[width, height], refresh-rate
- */
- public static final int NUM_MONITOR_MODE_PROPERTIES = 3;
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation
- * 1: rotation, native_mode_id
- */
- public static final int NUM_SCREEN_MODE_PROPERTIES = 1;
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation
- * count + all the above
- */
- public static final int NUM_SCREEN_MODE_PROPERTIES_ALL = 8;
-
- public static int getIndex(List<ScreenMode> screenModes, ScreenMode search) {
- return screenModes.indexOf(search);
- }
-
- public static int getIndexByHashCode(List<ScreenMode> screenModes, ScreenMode search) {
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- if ( search.hashCode() == screenModes.get(i).hashCode() ) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * @param screenModes
- * @param resolution
- * @return modes with nearest resolution, or matching ones
- */
- public static List<ScreenMode> filterByResolution(List<ScreenMode> screenModes, DimensionImmutable resolution) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- List<ScreenMode> out = new ArrayList<ScreenMode>();
- int resolution_sq = resolution.getHeight()*resolution.getWidth();
- int sm_dsq=resolution_sq, sm_dsq_idx=0;
-
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- DimensionImmutable res = sm.getMonitorMode().getSurfaceSize().getResolution();
- int dsq = Math.abs(resolution_sq - res.getHeight()*res.getWidth());
- if(dsq<sm_dsq) {
- sm_dsq = dsq;
- sm_dsq_idx = i;
- }
- if(res.equals(resolution)) {
- out.add(sm);
- }
- }
- if(out.size()>0) {
- return out;
- }
- // nearest ..
- resolution = screenModes.get(sm_dsq_idx).getMonitorMode().getSurfaceSize().getResolution();
- return filterByResolution(screenModes, resolution);
- }
-
- public static List<ScreenMode> filterBySurfaceSize(List<ScreenMode> screenModes, SurfaceSize surfaceSize) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- List<ScreenMode> out = new ArrayList<ScreenMode>();
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- if(sm.getMonitorMode().getSurfaceSize().equals(surfaceSize)) {
- out.add(sm);
- }
- }
- return out.size()>0 ? out : null;
- }
-
- public static List<ScreenMode> filterByRotation(List<ScreenMode> screenModes, int rotation) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- List<ScreenMode> out = new ArrayList<ScreenMode>();
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- if(sm.getRotation() == rotation) {
- out.add(sm);
- }
- }
- return out.size()>0 ? out : null;
- }
-
- public static List<ScreenMode> filterByBpp(List<ScreenMode> screenModes, int bitsPerPixel) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- List<ScreenMode> out = new ArrayList<ScreenMode>();
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- if(sm.getMonitorMode().getSurfaceSize().getBitsPerPixel() == bitsPerPixel) {
- out.add(sm);
- }
- }
- return out.size()>0 ? out : null;
- }
-
- /**
- *
- * @param screenModes
- * @param refreshRate
- * @return modes with nearest refreshRate, or matching ones
- */
- public static List<ScreenMode> filterByRate(List<ScreenMode> screenModes, int refreshRate) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- int sm_dr = refreshRate;
- int sm_dr_idx = -1;
- List<ScreenMode> out = new ArrayList<ScreenMode>();
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- int dr = Math.abs(refreshRate - sm.getMonitorMode().getRefreshRate());
- if(dr<sm_dr) {
- sm_dr = dr;
- sm_dr_idx = i;
- }
- if(0 == dr) {
- out.add(sm);
- }
- }
- if(out.size()>0) {
- return out;
- }
- refreshRate = screenModes.get(sm_dr_idx).getMonitorMode().getRefreshRate();
- return filterByRate(screenModes, refreshRate);
- }
-
- public static List<ScreenMode> getHighestAvailableBpp(List<ScreenMode> screenModes) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- int highest = -1;
- for (int i=0; null!=screenModes && i < screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- int bpp = sm.getMonitorMode().getSurfaceSize().getBitsPerPixel();
- if (bpp > highest) {
- highest = bpp;
- }
- }
- return filterByBpp(screenModes, highest);
- }
-
- public static List<ScreenMode> getHighestAvailableRate(List<ScreenMode> screenModes) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- int highest = -1;
- for (int i=0; null!=screenModes && i < screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- int rate = sm.getMonitorMode().getRefreshRate();
- if (rate > highest) {
- highest = rate;
- }
- }
- return filterByRate(screenModes, highest);
- }
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation */
- public static DimensionImmutable streamInResolution(int[] resolutionProperties, int offset) {
- Dimension resolution = new Dimension(resolutionProperties[offset++], resolutionProperties[offset++]);
- return resolution;
- }
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation */
- public static SurfaceSize streamInSurfaceSize(DimensionImmutable resolution, int[] sizeProperties, int offset) {
- SurfaceSize surfaceSize = new SurfaceSize(resolution, sizeProperties[offset++]);
- return surfaceSize;
- }
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation */
- public static MonitorMode streamInMonitorMode(SurfaceSize surfaceSize, DimensionImmutable screenSizeMM, int[] monitorProperties, int offset) {
- int refreshRate = monitorProperties[offset++];
- return new MonitorMode(surfaceSize, screenSizeMM, refreshRate);
- }
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation */
- public static ScreenMode streamInScreenMode(MonitorMode monitorMode, int[] modeProperties, int offset) {
- int rotation = modeProperties[offset++];
- return new ScreenMode(monitorMode, rotation);
- }
-
- /**
- * WARNING: must be synchronized with ScreenMode.h, native implementation
- *
- * @param modeProperties the input data
- * @param offset the offset to the input data
- * @return ScreenMode element matching the input <code>modeProperties</code>,
- * or null if input could not be processed.
- */
- public static ScreenMode streamIn(int[] modeProperties, int offset) {
- return streamInImpl(null, null, null, null, null, modeProperties, offset);
- }
-
- /**
- * WARNING: must be synchronized with ScreenMode.h, native implementation
- *
- * @param resolutionPool hash array of unique resolutions, no duplicates
- * @param surfaceSizePool hash array of unique SurfaceSize, no duplicates
- * @param monitorModePool hash array of unique MonitorMode, no duplicates
- * @param screenModePool hash array of unique ScreenMode, no duplicates
- * @param modeProperties the input data
- * @param offset the offset to the input data
- * @return index of the identical (old or new) ScreenMode element in <code>screenModePool</code>,
- * matching the input <code>modeProperties</code>, or -1 if input could not be processed.
- */
- public static int streamIn(ArrayHashSet<DimensionImmutable> resolutionPool,
- ArrayHashSet<SurfaceSize> surfaceSizePool,
- ArrayHashSet<DimensionImmutable> screenSizeMMPool,
- ArrayHashSet<MonitorMode> monitorModePool,
- ArrayHashSet<ScreenMode> screenModePool,
- int[] modeProperties, int offset) {
- ScreenMode screenMode = streamInImpl(resolutionPool, surfaceSizePool, screenSizeMMPool, monitorModePool, screenModePool,
- modeProperties, offset);
- return screenModePool.indexOf(screenMode);
- }
-
-
- private static ScreenMode streamInImpl(ArrayHashSet<DimensionImmutable> resolutionPool,
- ArrayHashSet<SurfaceSize> surfaceSizePool,
- ArrayHashSet<DimensionImmutable> screenSizeMMPool,
- ArrayHashSet<MonitorMode> monitorModePool,
- ArrayHashSet<ScreenMode> screenModePool,
- int[] modeProperties, int offset) {
- int count = modeProperties[offset];
- if(NUM_SCREEN_MODE_PROPERTIES_ALL != count) {
- throw new RuntimeException("NUM_SCREEN_MODE_PROPERTIES should be "+NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+count+", len "+(modeProperties.length-offset));
- }
- if(NUM_SCREEN_MODE_PROPERTIES_ALL > modeProperties.length-offset) {
- throw new RuntimeException("properties array too short, should be >= "+NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+(modeProperties.length-offset));
- }
- offset++;
- DimensionImmutable resolution = ScreenModeUtil.streamInResolution(modeProperties, offset);
- offset += ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
- if(null!=resolutionPool) {
- resolution = resolutionPool.getOrAdd(resolution);
- }
-
- SurfaceSize surfaceSize = ScreenModeUtil.streamInSurfaceSize(resolution, modeProperties, offset);
- offset += ScreenModeUtil.NUM_SURFACE_SIZE_PROPERTIES;
- if(null!=surfaceSizePool) {
- surfaceSize = surfaceSizePool.getOrAdd(surfaceSize);
- }
-
- DimensionImmutable screenSizeMM = ScreenModeUtil.streamInResolution(modeProperties, offset);
- offset += ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
- if(null!=screenSizeMMPool) {
- screenSizeMM = screenSizeMMPool.getOrAdd(screenSizeMM);
- }
-
- MonitorMode monitorMode = ScreenModeUtil.streamInMonitorMode(surfaceSize, screenSizeMM, modeProperties, offset);
- offset += ScreenModeUtil.NUM_MONITOR_MODE_PROPERTIES - ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
- if(null!=monitorModePool) {
- monitorMode = monitorModePool.getOrAdd(monitorMode);
- }
-
- ScreenMode screenMode = ScreenModeUtil.streamInScreenMode(monitorMode, modeProperties, offset);
- if(null!=screenModePool) {
- screenMode = screenModePool.getOrAdd(screenMode);
- }
- return screenMode;
- }
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation */
- public static int[] streamOut (ScreenMode screenMode) {
- int[] data = new int[NUM_SCREEN_MODE_PROPERTIES_ALL];
- int idx=0;
- data[idx++] = NUM_SCREEN_MODE_PROPERTIES_ALL;
- data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getResolution().getWidth();
- data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getResolution().getHeight();
- data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getBitsPerPixel();
- data[idx++] = screenMode.getMonitorMode().getScreenSizeMM().getWidth();
- data[idx++] = screenMode.getMonitorMode().getScreenSizeMM().getHeight();
- data[idx++] = screenMode.getMonitorMode().getRefreshRate();
- data[idx++] = screenMode.getRotation();
- if(NUM_SCREEN_MODE_PROPERTIES_ALL != idx) {
- throw new InternalError("wrong number of attributes: got "+idx+" != should "+NUM_SCREEN_MODE_PROPERTIES_ALL);
- }
- return data;
- }
-
-}
diff --git a/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtApplet3Run.java b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtApplet3Run.java
new file mode 100644
index 000000000..9a3e79a8f
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtApplet3Run.java
@@ -0,0 +1,360 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.newt.util.applet;
+
+import java.util.Locale;
+
+import com.jogamp.plugin.applet.Applet3;
+import com.jogamp.plugin.applet.Applet3Context;
+import com.jogamp.plugin.ui.NativeWindowDownstream;
+import com.jogamp.plugin.ui.NativeWindowUpstream;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.opengl.FPSCounter;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.GLWindow;
+
+/**
+ * Simple GLEventListener deployment as an applet using JOGL. This demo must be
+ * referenced from a web page via an &lt;applet&gt; tag.
+ *
+ * <p>
+ * Example of an applet tag using GearsES2 within the applet area (normal case):
+ * <pre>
+ &lt;applet width=100 height=100&gt;
+ &lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
+ &lt;param name="gl_event_listener_class" value="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2"&gt;
+ &lt;param name="gl_profile" value="GL2"&gt;
+ &lt;param name="gl_swap_interval" value="1"&gt;
+ &lt;param name="gl_debug" value="false"&gt;
+ &lt;param name="gl_trace" value="false"&gt;
+ &lt;param name="jnlp_href" value="jogl-newt-applet-runner.jnlp"&gt;
+ &lt;/applet&gt;Hello Gears !
+ * </pre>
+ * </p>
+ *
+ * <p>
+ * Example of an applet tag using GearsES2 in an undecorated, translucent, closeable and always-on-top window:
+ * <pre>
+ &lt;applet width=1 height=1&gt;
+ &lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
+ &lt;param name="gl_event_listener_class" value="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2"&gt;
+ &lt;param name="gl_profile" value="GL2"&gt;
+ &lt;param name="gl_swap_interval" value="1"&gt;
+ &lt;param name="gl_undecorated" value="true"&gt;
+ &lt;param name="gl_alwaysontop" value="true"&gt;
+ &lt;param name="gl_closeable" value="true"&gt;
+ &lt;param name="gl_alpha" value="1"&gt;
+ &lt;param name="gl_multisamplebuffer" value="0"&gt;
+ &lt;param name="gl_opaque" value="false"&gt;
+ &lt;param name="gl_dx" value="10"&gt;
+ &lt;param name="gl_dy" value="0"&gt;
+ &lt;param name="gl_width" value="100"&gt;
+ &lt;param name="gl_height" value="100"&gt;
+ &lt;param name="gl_nodefaultkeyListener" value="true"&gt;
+ &lt;param name="gl_debug" value="false"&gt;
+ &lt;param name="gl_trace" value="false"&gt;
+ &lt;param name="jnlp_href" value="jogl-newt-applet-runner.jnlp"&gt;
+ &lt;/applet&gt;Hello Gears !
+ * </pre>
+ * </p>
+ */
+public class JOGLNewtApplet3Run implements Applet3 {
+ public static final boolean DEBUG = JOGLNewtAppletBase.DEBUG;
+
+ GLWindow glWindow = null;
+ JOGLNewtAppletBase base = null;
+ /** if valid glStandalone:=true (own window) ! */
+ int glXd=Integer.MAX_VALUE, glYd=Integer.MAX_VALUE, glWidth=Integer.MAX_VALUE, glHeight=Integer.MAX_VALUE;
+ Applet3Context ctx;
+ boolean glStandalone = false;
+ UpstreamWindowHookMutableSizePos upstreamSizePosHook;
+ PointImmutable upstreamLocOnScreen;
+ NativeWindow browserWin;
+
+ final String getParameter(final String name) {
+ return ctx.getParameter(name);
+ }
+
+ @Override
+ public NativeWindowDownstream createNativeWindow(final Applet3Context ctx, final NativeWindowUpstream upstreamWin) {
+ this.ctx = ctx;
+
+ String glProfileName=null;
+ boolean glOpaque=true;
+ int glAlphaBits=0;
+ int glNumMultisampleBuffer=0;
+ boolean glUndecorated=false;
+ boolean glAlwaysOnTop=false;
+ try {
+ glProfileName = getParameter("gl_profile");
+ glOpaque = JOGLNewtAppletBase.str2Bool(getParameter("gl_opaque"), glOpaque);
+ glAlphaBits = JOGLNewtAppletBase.str2Int(getParameter("gl_alpha"), glAlphaBits);
+ glNumMultisampleBuffer = JOGLNewtAppletBase.str2Int(getParameter("gl_multisamplebuffer"), glNumMultisampleBuffer);
+ glXd = JOGLNewtAppletBase.str2Int(getParameter("gl_dx"), glXd);
+ glYd = JOGLNewtAppletBase.str2Int(getParameter("gl_dy"), glYd);
+ glWidth = JOGLNewtAppletBase.str2Int(getParameter("gl_width"), glWidth);
+ glHeight = JOGLNewtAppletBase.str2Int(getParameter("gl_height"), glHeight);
+ glUndecorated = JOGLNewtAppletBase.str2Bool(getParameter("gl_undecorated"), glUndecorated);
+ glAlwaysOnTop = JOGLNewtAppletBase.str2Bool(getParameter("gl_alwaysontop"), glAlwaysOnTop);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(glProfileName));
+ caps.setAlphaBits(glAlphaBits);
+ if(0<glNumMultisampleBuffer) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(glNumMultisampleBuffer);
+ }
+ caps.setBackgroundOpaque(glOpaque);
+
+ final AbstractGraphicsDevice aDevice = NativeWindowFactory.createDevice(upstreamWin.getDisplayConnection(),
+ true /* own */); // open and own! (for upstreamLocOnScreen)
+ final AbstractGraphicsScreen aScreen = NativeWindowFactory.createScreen(aDevice, upstreamWin.getScreenIndex());
+ upstreamSizePosHook = new UpstreamWindowHookMutableSizePos(upstreamWin.getX(), upstreamWin.getY(),
+ upstreamWin.getWidth(), upstreamWin.getHeight(),
+ upstreamWin.getWidth(), upstreamWin.getHeight()); // FIXME: pixel-dim == window-dim 'for now' ?
+ browserWin = NativeWindowFactory.createWrappedWindow(aScreen, 0 /* surfaceHandle */, upstreamWin.getWindowHandle(),
+ upstreamSizePosHook);
+ upstreamLocOnScreen = NativeWindowFactory.getLocationOnScreen(browserWin);
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet3Run Configuration:");
+ System.err.println("glStandalone: "+glStandalone);
+ System.err.println("glProfileName: "+glProfileName);
+ System.err.println("glOpaque: "+glOpaque);
+ System.err.println("glAlphaBits: "+glAlphaBits);
+ System.err.println("glNumMultisampleBuffer: "+glNumMultisampleBuffer);
+ System.err.println("glUndecorated: "+glUndecorated);
+ System.err.println("glAlwaysOnTop: "+glAlwaysOnTop);
+ System.err.println("UpstreamWin: "+upstreamWin+", LOS "+upstreamLocOnScreen);
+ if(glStandalone) {
+ System.err.println("pos-size: "+glXd+"/"+glYd+" "+glWidth+"x"+glHeight);
+ }
+ }
+
+ final Window w = NewtFactory.createWindow(glStandalone ? null : browserWin, caps);
+ glWindow = GLWindow.create(w);
+ glWindow.setUndecorated(glUndecorated);
+ glWindow.setAlwaysOnTop(glAlwaysOnTop);
+ glWindow.setSize(browserWin.getWidth(), browserWin.getHeight());
+
+ return new NativeWindowDownstream() {
+ @Override
+ public void setVisible(final boolean v) {
+ if( null != glWindow ) {
+ glWindow.setVisible(v);
+ }
+ }
+
+ @Override
+ public void setSize(final int width, final int height) {
+ upstreamSizePosHook.setWinSize(width, height);
+ if( null != glWindow ) {
+ glWindow.setSize(width, height);
+ }
+ }
+
+ @Override
+ public void requestFocus() {
+ if( null != glWindow ) {
+ glWindow.requestFocus();
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if( null != glWindow ) {
+ glWindow.destroy();
+ }
+ }
+
+ @Override
+ public NativeWindowUpstream getParent() {
+ return upstreamWin;
+ }
+
+ @Override
+ public long getWindowHandle() {
+ if( null != glWindow ) {
+ return glWindow.getWindowHandle();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public void display() {
+ if( null != glWindow ) {
+ glWindow.display();
+ }
+ }
+
+ @Override
+ public void notifyPositionChanged(final NativeWindowUpstream nw) {
+ upstreamSizePosHook.setWinPos(nw.getX(), nw.getY());
+ if( null != glWindow ) {
+ glWindow.setPosition(nw.getX(), nw.getY());
+ }
+ }
+ };
+ }
+
+ @Override
+ public void init(final Applet3Context ctx) {
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.init() START - "+currentThreadName());
+ }
+ this.ctx = ctx;
+ String glEventListenerClazzName=null;
+ int glSwapInterval=0;
+ boolean glDebug=false;
+ boolean glTrace=false;
+ boolean glNoDefaultKeyListener = false;
+ boolean glCloseable=false;
+
+ try {
+ glEventListenerClazzName = getParameter("gl_event_listener_class");
+ glSwapInterval = JOGLNewtAppletBase.str2Int(getParameter("gl_swap_interval"), glSwapInterval);
+ glDebug = JOGLNewtAppletBase.str2Bool(getParameter("gl_debug"), glDebug);
+ glTrace = JOGLNewtAppletBase.str2Bool(getParameter("gl_trace"), glTrace);
+ glNoDefaultKeyListener = JOGLNewtAppletBase.str2Bool(getParameter("gl_nodefaultkeyListener"), glNoDefaultKeyListener);
+ glCloseable = JOGLNewtAppletBase.str2Bool(getParameter("gl_closeable"), glCloseable);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ if(null==glEventListenerClazzName) {
+ throw new RuntimeException("No applet parameter 'gl_event_listener_class'");
+ }
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run Configuration:");
+ System.err.println("glEventListenerClazzName: "+glEventListenerClazzName);
+ System.err.println("glSwapInterval: "+glSwapInterval);
+ System.err.println("glDebug: "+glDebug);
+ System.err.println("glTrace: "+glTrace);
+ System.err.println("glNoDefaultKeyListener: "+glNoDefaultKeyListener);
+ System.err.println("glCloseable: "+glCloseable);
+ }
+
+ base = new JOGLNewtAppletBase(glEventListenerClazzName,
+ glSwapInterval,
+ glNoDefaultKeyListener,
+ glCloseable,
+ glDebug,
+ glTrace);
+
+ try {
+ glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
+ glWindow.setDefaultCloseOperation(glCloseable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE);
+ base.init(glWindow);
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.init() END - "+currentThreadName());
+ }
+ }
+
+ private static String currentThreadName() { return "["+Thread.currentThread().getName()+"]"; }
+
+ @Override
+ public void start() {
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.start() START (isVisible "+glWindow.isVisible()+") - "+currentThreadName());
+ }
+ if( glStandalone ) {
+ glWindow.setSize(glWidth, glHeight);
+ glWindow.setPosition(upstreamLocOnScreen.getX()+glXd, upstreamLocOnScreen.getY()+glYd);
+ glWindow.setVisible(true);
+ glWindow.requestFocus();
+ }
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run start:");
+ System.err.println("GLWindow Pos: "+glWindow.getX()+"/"+glWindow.getY()+" rel, "+glWindow.getLocationOnScreen(null)+" screen");
+ System.err.println("GLWindow: "+glWindow);
+ }
+ base.start();
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.start() END - "+currentThreadName());
+ }
+ }
+
+ @Override
+ public void stop() {
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.stop() START - "+currentThreadName());
+ }
+ base.stop();
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.stop() END - "+currentThreadName());
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.destroy() START - "+currentThreadName());
+ }
+ glWindow.setVisible(false); // hide 1st
+ base.destroy(); // destroy glWindow unrecoverable
+ base=null;
+ glWindow=null;
+ browserWin.destroy(); // make sure the open display connection gets closed!
+ browserWin = null;
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.destroy() END - "+currentThreadName());
+ }
+ }
+
+ @Override
+ public String getAppletInfo() {
+ return null;
+ }
+
+ @Override
+ public Locale getLocale() {
+ return null;
+ }
+
+ @Override
+ public String[][] getParameterInfo() {
+ return null;
+ }
+
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java
index 082c01c23..d40e09d96 100755..100644
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
+++ b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java
@@ -25,7 +25,7 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package com.jogamp.newt.awt.applet;
+package com.jogamp.newt.util.applet;
import java.lang.reflect.Field;
import java.security.AccessController;
@@ -33,6 +33,7 @@ import java.security.PrivilegedAction;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
+import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.opengl.FPSCounter;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
@@ -41,6 +42,10 @@ import javax.media.opengl.GLPipelineFactory;
import jogamp.newt.Debug;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.Display.PointerIcon;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseListener;
@@ -49,6 +54,7 @@ import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
/** Shows how to deploy an applet using JOGL. This demo must be
@@ -56,27 +62,28 @@ import com.jogamp.opengl.util.Animator;
public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
public static final boolean DEBUG = Debug.debug("Applet");
-
+
String glEventListenerClazzName;
int glSwapInterval;
boolean noDefaultKeyListener;
boolean glClosable;
boolean glDebug;
boolean glTrace;
+ PointerIcon pointerIconTest = null;
GLEventListener glEventListener = null;
GLWindow glWindow = null;
Animator glAnimator=null;
boolean isValid = false;
- NativeWindow awtParent;
-
- public JOGLNewtAppletBase(String glEventListenerClazzName,
- int glSwapInterval,
- boolean noDefaultKeyListener,
- boolean glClosable,
- boolean glDebug,
- boolean glTrace) {
-
+ NativeWindow parentWin;
+
+ public JOGLNewtAppletBase(final String glEventListenerClazzName,
+ final int glSwapInterval,
+ final boolean noDefaultKeyListener,
+ final boolean glClosable,
+ final boolean glDebug,
+ final boolean glTrace) {
+
this.glEventListenerClazzName=glEventListenerClazzName;
this.glSwapInterval=glSwapInterval;
this.noDefaultKeyListener = noDefaultKeyListener;
@@ -90,19 +97,19 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
public Animator getGLAnimator() { return glAnimator; }
public boolean isValid() { return isValid; }
- public static boolean str2Bool(String str, boolean def) {
+ public static boolean str2Bool(final String str, final boolean def) {
if(null==str) return def;
try {
return Boolean.valueOf(str).booleanValue();
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return def;
}
- public static int str2Int(String str, int def) {
+ public static int str2Int(final String str, final int def) {
if(null==str) return def;
try {
return Integer.parseInt(str);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return def;
}
@@ -111,19 +118,20 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
try {
final Class<?> clazz = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ @Override
public Class<?> run() {
final ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class<?> clazz = null;
try {
clazz = Class.forName(clazzName, false, cl);
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
}
return clazz;
}
});
instance = clazz.newInstance();
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
throw new RuntimeException("Error while instantiating demo: "+clazzName);
}
@@ -136,46 +144,30 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
return (GLEventListener) instance;
}
- public static boolean setField(Object instance, String fieldName, Object value) {
+ public static boolean setField(final Object instance, final String fieldName, final Object value) {
try {
- Field f = instance.getClass().getField(fieldName);
+ final Field f = instance.getClass().getField(fieldName);
if(f.getType().isInstance(value)) {
f.set(instance, value);
return true;
} else {
System.out.println(instance.getClass()+" '"+fieldName+"' field not assignable with "+value.getClass()+", it's a: "+f.getType());
}
- } catch (NoSuchFieldException nsfe) {
+ } catch (final NoSuchFieldException nsfe) {
System.out.println(instance.getClass()+" has no '"+fieldName+"' field");
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
}
return false;
}
- public void init(GLWindow glWindow) {
+ public void init(final GLWindow glWindow) {
init(Thread.currentThread().getThreadGroup(), glWindow);
}
- public void init(ThreadGroup tg, final GLWindow glWindow) {
+ public void init(final ThreadGroup tg, final GLWindow glWindow) {
isValid = false;
this.glWindow = glWindow;
- this.glWindow.addWindowListener(new WindowAdapter() {
- // Closing action: back to parent!
- @Override
- public void windowDestroyNotify(WindowEvent e) {
- if( WindowClosingMode.DO_NOTHING_ON_CLOSE == glWindow.getDefaultCloseOperation() ) {
- if(null == glWindow.getParent()) {
- // we may be called directly by the native EDT
- new Thread(new Runnable() {
- public void run() {
- glWindow.reparentWindow(awtParent);
- }
- }).start();
- }
- }
- } } );
-
glEventListener = createInstance(glEventListenerClazzName);
if(null == glEventListener) {
return;
@@ -200,7 +192,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
if(glEventListener instanceof KeyListener) {
glWindow.addKeyListener((KeyListener)glEventListener);
}
-
+
if(!noDefaultKeyListener) {
glWindow.addKeyListener(this);
}
@@ -208,26 +200,59 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
// glAnimator = new FPSAnimator(canvas, 60);
- glAnimator = new Animator(tg, glWindow);
+ glAnimator = new Animator();
+ glAnimator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD); // No AWT thread involved!
+ glAnimator.setThreadGroup(tg);
+ glAnimator.add(glWindow);
glAnimator.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, null);
-
- } catch (Throwable t) {
+
+ } catch (final Throwable t) {
throw new RuntimeException(t);
}
isValid = true;
}
+ private final WindowListener reparentHomeListener = new WindowAdapter() {
+ // Closing action: back to parent!
+ @Override
+ public void windowDestroyNotify(final WindowEvent e) {
+ if( isValid() && WindowClosingMode.DO_NOTHING_ON_CLOSE == glWindow.getDefaultCloseOperation() &&
+ null == glWindow.getParent() && null != parentWin && 0 != parentWin.getWindowHandle() )
+ {
+ // we may be called directly by the native EDT
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if( glWindow.isNativeValid() && null != parentWin && 0 != parentWin.getWindowHandle() ) {
+ glWindow.reparentWindow(parentWin, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
+ }
+ }
+ }).start();
+ }
+ } };
+
public void start() {
if(isValid) {
glWindow.setVisible(true);
glWindow.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
+ if( null == pointerIconTest ) {
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } );
+ final Display disp = glWindow.getScreen().getDisplay();
+ try {
+ pointerIconTest = disp.createPointerIcon(res, 8, 8);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
glAnimator.start();
- awtParent = glWindow.getParent();
+ parentWin = glWindow.getParent();
+ glWindow.addWindowListener(reparentHomeListener);
}
}
public void stop() {
if(null!=glAnimator) {
+ glWindow.removeWindowListener(reparentHomeListener);
glAnimator.stop();
glWindow.setVisible(false);
}
@@ -250,58 +275,117 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
// ***********************************************************************************
// ***********************************************************************************
- public void init(GLAutoDrawable drawable) {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
GL _gl = drawable.getGL();
if(glDebug) {
try {
_gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, _gl, null) );
- } catch (Exception e) {e.printStackTrace();}
+ } catch (final Exception e) {e.printStackTrace();}
}
if(glTrace) {
try {
// Trace ..
_gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, _gl, new Object[] { System.err } ) );
- } catch (Exception e) {e.printStackTrace();}
+ } catch (final Exception e) {e.printStackTrace();}
}
if(glSwapInterval>=0) {
_gl.setSwapInterval(glSwapInterval);
}
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
}
- public void display(GLAutoDrawable drawable) {
+ @Override
+ public void display(final GLAutoDrawable drawable) {
}
- public void dispose(GLAutoDrawable drawable) {
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
}
// ***********************************************************************************
// ***********************************************************************************
// ***********************************************************************************
- public void keyPressed(KeyEvent e) {
- }
- public void keyReleased(KeyEvent e) {
- }
- public void keyTyped(KeyEvent e) {
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
if(e.getKeyChar()=='d') {
- glWindow.setUndecorated(!glWindow.isUndecorated());
+ new Thread() {
+ public void run() {
+ glWindow.setUndecorated(!glWindow.isUndecorated());
+ } }.start();
} if(e.getKeyChar()=='f') {
- glWindow.setFullscreen(!glWindow.isFullscreen());
+ new Thread() {
+ public void run() {
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ } }.start();
} else if(e.getKeyChar()=='a') {
- glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
- } else if(e.getKeyChar()=='r' && null!=awtParent) {
- if(null == glWindow.getParent()) {
- glWindow.reparentWindow(awtParent);
- } else {
- glWindow.reparentWindow(null);
- if(glClosable) {
- glWindow.setDefaultCloseOperation(WindowClosingMode.DISPOSE_ON_CLOSE);
- }
- }
+ new Thread() {
+ public void run() {
+ glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
+ } }.start();
+ } else if(e.getKeyChar()=='r' && null!=parentWin) {
+ new Thread() {
+ public void run() {
+ if(null == glWindow.getParent()) {
+ glWindow.reparentWindow(parentWin, -1, -1, 0 /* hints */);
+ } else {
+ final InsetsImmutable insets = glWindow.getInsets();
+ final int x, y;
+ if ( 0 >= insets.getTopHeight() ) {
+ // fail safe ..
+ x = 32;
+ y = 32;
+ } else {
+ x = insets.getLeftWidth();
+ y = insets.getTopHeight();
+ }
+ glWindow.reparentWindow(null, x, y, 0 /* hints */);
+ glWindow.setDefaultCloseOperation( glClosable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE );
+ }
+ } }.start();
+ } else if(e.getKeyChar()=='c') {
+ new Thread() {
+ public void run() {
+ System.err.println("[set pointer-icon pre]");
+ final PointerIcon currentPI = glWindow.getPointerIcon();
+ glWindow.setPointerIcon( currentPI == pointerIconTest ? null : pointerIconTest);
+ System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon());
+ } }.start();
+ } else if(e.getKeyChar()=='i') {
+ new Thread() {
+ public void run() {
+ System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible());
+ glWindow.setPointerVisible(!glWindow.isPointerVisible());
+ System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible());
+ } }.start();
+ } else if(e.getKeyChar()=='j') {
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
+ glWindow.confinePointer(!glWindow.isPointerConfined());
+ System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
+ glWindow.setExclusiveContextThread(t);
+ } }.start();
+ } else if(e.getKeyChar()=='w') {
+ new Thread() {
+ public void run() {
+ System.err.println("[set mouse pos pre]");
+ glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2);
+ System.err.println("[set mouse pos post]");
+ } }.start();
}
}
+
+ @Override
+ public void keyReleased(final KeyEvent e) {
+ }
}
diff --git a/src/newt/classes/com/jogamp/newt/util/applet/VersionApplet3.java b/src/newt/classes/com/jogamp/newt/util/applet/VersionApplet3.java
new file mode 100644
index 000000000..7ec790ee2
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/util/applet/VersionApplet3.java
@@ -0,0 +1,226 @@
+package com.jogamp.newt.util.applet;
+
+import com.jogamp.plugin.applet.Applet3;
+import com.jogamp.plugin.applet.Applet3Context;
+import com.jogamp.plugin.ui.NativeWindowDownstream;
+import com.jogamp.plugin.ui.NativeWindowUpstream;
+
+import java.util.List;
+import java.util.Locale;
+
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+
+import com.jogamp.common.GlueGenVersion;
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.JoglVersion;
+
+public class VersionApplet3 implements Applet3 {
+
+ public static void main(final String[] args) {
+ final VersionApplet3 va = new VersionApplet3();
+
+ final NativeWindowDownstream nwc = va.createNativeWindow(null, new NativeWindowUpstream() {
+ @Override
+ public long getWindowHandle() {
+ return 0;
+ }
+ @Override
+ public int getWidth() {
+ return 64;
+ }
+ @Override
+ public int getHeight() {
+ return 64;
+ }
+ @Override
+ public String getDisplayConnection() {
+ return null; // default
+ }
+ @Override
+ public int getScreenIndex() {
+ return 0; // default
+ }
+ @Override
+ public void notifySurfaceUpdated(final NativeWindowDownstream swappedWin) {
+ // NOP
+ }
+ @Override
+ public int getX() {
+ return 0;
+ }
+ @Override
+ public int getY() {
+ return 0;
+ }
+ });
+ va.init(null);
+ va.start();
+ va.stop();
+ va.destroy();
+ nwc.destroy();
+ }
+
+ GLWindow canvas;
+
+ @Override
+ public NativeWindowDownstream createNativeWindow(final Applet3Context ctx, final NativeWindowUpstream parentWin) {
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ final Window w = NewtFactory.createWindow(parentWin.getDisplayConnection(), parentWin.getScreenIndex(), parentWin.getWindowHandle(), caps);
+ canvas = GLWindow.create(w);
+ canvas.setSize(parentWin.getWidth(), parentWin.getHeight());
+
+ return new NativeWindowDownstream() {
+ @Override
+ public void setVisible(final boolean v) {
+ if( null != canvas ) {
+ canvas.setVisible(v);
+ }
+ }
+
+ @Override
+ public void setSize(final int width, final int height) {
+ if( null != canvas ) {
+ canvas.setSize(width, height);
+ }
+ }
+
+ @Override
+ public void requestFocus() {
+ if( null != canvas ) {
+ canvas.requestFocus();
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if( null != canvas ) {
+ canvas.destroy();
+ }
+ }
+
+ @Override
+ public NativeWindowUpstream getParent() {
+ return parentWin;
+ }
+
+ @Override
+ public long getWindowHandle() {
+ if( null != canvas ) {
+ return canvas.getWindowHandle();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public void display() {
+ if( null != canvas ) {
+ canvas.display();
+ }
+ }
+
+ @Override
+ public void notifyPositionChanged(final NativeWindowUpstream nw) {
+ if( null != canvas ) {
+ canvas.setPosition(nw.getX(), nw.getY());
+ }
+ }
+ };
+ }
+
+ @Override
+ public void init(final Applet3Context ctx) {
+ System.err.println("VersionApplet: init() - begin");
+ canvas.addGLEventListener(new GLInfo());
+ System.err.println("VersionApplet: init() - end");
+ }
+
+ @Override
+ public void start() {
+ System.err.println("VersionApplet: start() - begin");
+
+ String s;
+
+ s = VersionUtil.getPlatformInfo().toString();
+ System.err.println(s);
+
+ s = GlueGenVersion.getInstance().toString();
+ System.err.println(s);
+
+ /*
+ s = NativeWindowVersion.getInstance().toString();
+ System.err.println(s);
+ */
+
+ s = JoglVersion.getInstance().toString();
+ System.err.println(s);
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(canvas.getGLProfile());
+ final List<GLCapabilitiesImmutable> availCaps = factory.getAvailableCapabilities(null);
+ for(int i=0; i<availCaps.size(); i++) {
+ s = availCaps.get(i).toString();
+ System.err.println(s);
+ }
+ canvas.display();
+ System.err.println("VersionApplet: start() - end");
+ }
+
+ @Override
+ public void stop() {
+ System.err.println("VersionApplet: stop() - begin");
+ canvas.setVisible(false);
+ System.err.println("VersionApplet: stop() - end");
+ }
+
+ @Override
+ public void destroy() {
+ System.err.println("VersionApplet: destroy() - start");
+ if(null!=canvas) {
+ canvas.destroy();
+ canvas = null;
+ }
+ System.err.println("VersionApplet: destroy() - end");
+ }
+
+ @Override
+ public String getAppletInfo() {
+ return null;
+ }
+
+ @Override
+ public Locale getLocale() {
+ return null;
+ }
+
+ @Override
+ public String[][] getParameterInfo() {
+ return null;
+ }
+
+ static class GLInfo implements GLEventListener {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ final String s = JoglVersion.getGLInfo(gl, null).toString();
+ System.err.println(s);
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ }
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ }
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/Debug.java b/src/newt/classes/jogamp/newt/Debug.java
index 3c83da4d9..a255cb755 100644
--- a/src/newt/classes/jogamp/newt/Debug.java
+++ b/src/newt/classes/jogamp/newt/Debug.java
@@ -1,44 +1,36 @@
-/*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
*/
package jogamp.newt;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
import com.jogamp.common.util.PropertyAccess;
/** Helper routines for logging and debugging. */
@@ -47,40 +39,37 @@ public class Debug extends PropertyAccess {
// Some common properties
private static final boolean verbose;
private static final boolean debugAll;
-
+
static {
- PropertyAccess.addTrustedPrefix("newt.", Debug.class);
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ PropertyAccess.addTrustedPrefix("newt.");
+ return null;
+ } } );
+
verbose = isPropertyDefined("newt.verbose", true);
debugAll = isPropertyDefined("newt.debug", true);
if (verbose) {
- Package p = Package.getPackage("com.jogamp.newt");
+ final Package p = Package.getPackage("com.jogamp.newt");
System.err.println("NEWT specification version " + p.getSpecificationVersion());
System.err.println("NEWT implementation version " + p.getImplementationVersion());
System.err.println("NEWT implementation vendor " + p.getImplementationVendor());
}
}
- public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) {
- return PropertyAccess.isPropertyDefined(property, jnlpAlias, null);
- }
-
- public static final int getIntProperty(final String property, final boolean jnlpAlias, int defaultValue) {
- return PropertyAccess.getIntProperty(property, jnlpAlias, null, defaultValue);
- }
-
- public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getBooleanProperty(property, jnlpAlias, null);
- }
-
- public static boolean verbose() {
+ /** Ensures static init block has been issues, i.e. if calling through to {@link PropertyAccess#isPropertyDefined(String, boolean)}. */
+ public static final void initSingleton() {}
+
+ public static final boolean verbose() {
return verbose;
}
- public static boolean debugAll() {
+ public static final boolean debugAll() {
return debugAll;
}
- public static boolean debug(String subcomponent) {
+ public static final boolean debug(final String subcomponent) {
return debugAll() || isPropertyDefined("newt.debug." + subcomponent, true);
}
}
diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
index 18418a8dc..ef8ea66b6 100644
--- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -38,6 +38,7 @@
package jogamp.newt;
import java.util.ArrayList;
+
import javax.media.nativewindow.NativeWindowException;
import jogamp.common.util.locks.LockDebugUtil;
@@ -49,19 +50,24 @@ import com.jogamp.newt.util.EDTUtil;
public class DefaultEDTUtil implements EDTUtil {
public static final boolean DEBUG = Debug.debug("EDT");
+ /** Used to implement {@link #invokeStop(boolean, Runnable)}. */
+ private static final Object TASK_ATTACHMENT_STOP = new Object();
+ /** Used to provoke an exception on the EDT while waiting / blocking. Merely exists to test code.*/
+ private static final Object TASK_ATTACHMENT_TEST_ERROR = new Object();
+
private final Object edtLock = new Object(); // locking the EDT start/stop state
- private final ThreadGroup threadGroup;
+ private /* final */ ThreadGroup threadGroup;
private final String name;
private final Runnable dispatchMessages;
- private EventDispatchThread edt = null;
+ private NEDT edt = null;
private int start_iter=0;
private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
- public DefaultEDTUtil(ThreadGroup tg, String name, Runnable dispatchMessages) {
+ public DefaultEDTUtil(final ThreadGroup tg, final String name, final Runnable dispatchMessages) {
this.threadGroup = tg;
this.name=Thread.currentThread().getName()+"-"+name+"-EDT-";
this.dispatchMessages=dispatchMessages;
- this.edt = new EventDispatchThread(threadGroup, name);
+ this.edt = new NEDT(threadGroup, name);
this.edt.setDaemon(true); // don't stop JVM from shutdown ..
}
@@ -71,36 +77,45 @@ public class DefaultEDTUtil implements EDTUtil {
}
@Override
- final public void setPollPeriod(long ms) {
- pollPeriod = ms;
+ final public void setPollPeriod(final long ms) {
+ pollPeriod = ms; // writing to static field is intended
}
-
+
@Override
- public final void reset() {
- synchronized(edtLock) {
- waitUntilStopped();
+ public final void start() throws IllegalStateException {
+ synchronized(edtLock) {
+ if( edt.isRunning() ) {
+ throw new IllegalStateException("EDT still running and not subject to stop. Curr "+Thread.currentThread().getName()+", EDT "+edt.getName()+", isRunning "+edt.isRunning+", shouldStop "+edt.shouldStop);
+ }
if(DEBUG) {
if(edt.tasks.size()>0) {
- System.err.println(Thread.currentThread()+": EDT reset, remaining tasks: "+edt.tasks.size()+" - "+edt);
- // Thread.dumpStack();
+ System.err.println(Thread.currentThread()+": Default-EDT reset, remaining tasks: "+edt.tasks.size()+" - "+edt);
+ }
+ System.err.println(Thread.currentThread()+": Default-EDT reset - edt: "+edt);
+ }
+ if( edt.getState() != Thread.State.NEW ) {
+ if( null != threadGroup && threadGroup.isDestroyed() ) {
+ // best thing we can do is to use this thread's TG
+ threadGroup = Thread.currentThread().getThreadGroup();
}
- System.err.println(Thread.currentThread()+": EDT reset - edt: "+edt);
+ edt = new NEDT(threadGroup, name);
+ edt.setDaemon(true); // don't stop JVM from shutdown ..
}
- this.edt = new EventDispatchThread(threadGroup, name);
- this.edt.setDaemon(true); // don't stop JVM from shutdown ..
+ startImpl();
+ }
+ if( !edt.isRunning() ) {
+ throw new RuntimeException("EDT could not be started: "+edt);
}
}
private final void startImpl() {
if(edt.isAlive()) {
- throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size());
+ throw new RuntimeException("Default-EDT Thread.isAlive(): true, isRunning: "+edt.isRunning+", shouldStop "+edt.shouldStop+", edt: "+edt+", tasks: "+edt.tasks.size());
}
start_iter++;
edt.setName(name+start_iter);
- edt.shouldStop = false;
if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT START - edt: "+edt);
- // Thread.dumpStack();
+ System.err.println(Thread.currentThread()+": Default-EDT START - edt: "+edt);
}
edt.start();
}
@@ -109,7 +124,7 @@ public class DefaultEDTUtil implements EDTUtil {
public final boolean isCurrentThreadEDT() {
return edt == Thread.currentThread(); // EDT == NEDT
}
-
+
@Override
public final boolean isCurrentThreadNEDT() {
return edt == Thread.currentThread(); // EDT == NEDT
@@ -118,81 +133,109 @@ public class DefaultEDTUtil implements EDTUtil {
@Override
public final boolean isCurrentThreadEDTorNEDT() {
return edt == Thread.currentThread(); // EDT == NEDT
- }
-
+ }
+
@Override
public final boolean isRunning() {
return edt.isRunning() ;
}
@Override
- public final void invokeStop(Runnable task) {
- invokeImpl(true, task, true);
+ public final boolean invokeStop(final boolean wait, final Runnable task) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": Default-EDT.invokeStop wait "+wait);
+ Thread.dumpStack();
+ }
+ return invokeImpl(wait, task, true /* stop */, false /* provokeError */);
+ }
+
+ public final boolean invokeAndWaitError(final Runnable task) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": Default-EDT.invokeAndWaitError");
+ Thread.dumpStack();
+ }
+ return invokeImpl(true /* wait */, task, false /* stop */, true /* provokeError */);
}
@Override
- public final void invoke(boolean wait, Runnable task) {
- invokeImpl(wait, task, false);
+ public final boolean invoke(final boolean wait, final Runnable task) {
+ return invokeImpl(wait, task, false /* stop */, false /* provokeError */);
}
- private void invokeImpl(boolean wait, Runnable task, boolean stop) {
- if(task == null) {
- throw new RuntimeException("Null Runnable");
- }
+ private static Runnable nullTask = new Runnable() {
+ @Override
+ public void run() { }
+ };
+
+ private final boolean invokeImpl(boolean wait, Runnable task, final boolean stop, final boolean provokeError) {
Throwable throwable = null;
RunnableTask rTask = null;
- Object rTaskLock = new Object();
+ final Object rTaskLock = new Object();
synchronized(rTaskLock) { // lock the optional task execution
synchronized(edtLock) { // lock the EDT status
if( edt.shouldStop ) {
// drop task ..
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT about (1) to stop, won't enqueue new task: "+edt);
if(DEBUG) {
- System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+edt);
Thread.dumpStack();
}
- return;
- }
- // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
- // Thread.dumpStack();
- if(stop) {
- edt.shouldStop = true;
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - tasks: "+edt.tasks.size()+" - "+edt);
- // Thread.dumpStack();
- }
+ return false;
}
if( isCurrentThreadEDT() ) {
- task.run();
+ if(null != task) {
+ task.run();
+ }
wait = false; // running in same thread (EDT) -> no wait
- if(stop && edt.tasks.size()>0) {
- System.err.println("Warning: EDT about (2) to stop, having remaining tasks: "+edt.tasks.size()+" - "+edt);
- if(DEBUG) {
- Thread.dumpStack();
+ if( stop ) {
+ edt.shouldStop = true;
+ if( edt.tasks.size()>0 ) {
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT about (2) to stop, task executed. Remaining tasks: "+edt.tasks.size()+" - "+edt);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
}
}
} else {
- // start if should not stop && not started yet
- if( !stop && !edt.isRunning() ) {
- startImpl();
+ if( !edt.isRunning ) {
+ if( null != task ) {
+ if( stop ) {
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT is about (3) to stop and stopped already, dropping task. Remaining tasks: "+edt.tasks.size()+" - "+edt);
+ } else {
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT is not running, dropping task. NEDT "+edt);
+ }
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ }
+ return false;
+ } else if( stop && null == task ) {
+ task = nullTask; // ensures execution triggering stop
}
- synchronized(edt.tasks) {
- wait = wait && edt.isRunning();
- rTask = new RunnableTask(task,
- wait ? rTaskLock : null,
- true /* always catch and report Exceptions, don't disturb EDT */);
- if(stop) {
- rTask.setAttachment(new Boolean(true)); // mark final task
+
+ if(null != task) {
+ synchronized(edt.tasks) {
+ rTask = new RunnableTask(task,
+ wait ? rTaskLock : null,
+ true /* always catch and report Exceptions, don't disturb EDT */,
+ wait ? null : System.err);
+ if(stop) {
+ rTask.setAttachment(TASK_ATTACHMENT_STOP); // mark final task, will imply shouldStop:=true
+ } else if(provokeError) {
+ rTask.setAttachment(TASK_ATTACHMENT_TEST_ERROR);
+ }
+ // append task ..
+ edt.tasks.add(rTask);
+ edt.tasks.notifyAll();
}
- // append task ..
- edt.tasks.add(rTask);
- edt.tasks.notifyAll();
+ } else {
+ wait = false;
}
}
}
if( wait ) {
try {
rTaskLock.wait(); // free lock, allow execution of rTask
- } catch (InterruptedException ie) {
+ } catch (final InterruptedException ie) {
throwable = ie;
}
if(null==throwable) {
@@ -205,59 +248,66 @@ public class DefaultEDTUtil implements EDTUtil {
throw new RuntimeException(throwable);
}
}
- }
- if(DEBUG && stop) {
- System.err.println(Thread.currentThread()+": EDT signal STOP X edt: "+edt);
+ if(DEBUG) {
+ if( stop) {
+ System.err.println(Thread.currentThread()+": Default-EDT signal STOP X edt: "+edt);
+ }
+ }
+ return true;
}
}
@Override
- final public void waitUntilIdle() {
- final EventDispatchThread _edt;
+ final public boolean waitUntilIdle() {
+ final NEDT _edt;
synchronized(edtLock) {
_edt = edt;
}
- if(!_edt.isRunning() || _edt == Thread.currentThread()) {
- return;
+ if(!_edt.isRunning || _edt == Thread.currentThread()) {
+ return false;
}
synchronized(_edt.tasks) {
- while(_edt.isRunning() && _edt.tasks.size()>0) {
+ while(_edt.isRunning && _edt.tasks.size()>0) {
try {
_edt.tasks.notifyAll();
_edt.tasks.wait();
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
e.printStackTrace();
}
}
+ return true;
}
}
@Override
- final public void waitUntilStopped() {
+ final public boolean waitUntilStopped() {
synchronized(edtLock) {
- if(edt.isRunning() && edt != Thread.currentThread() ) {
- while(edt.isRunning()) {
+ if(edt.isRunning && edt != Thread.currentThread() ) {
+ while( edt.isRunning ) {
try {
edtLock.wait();
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
e.printStackTrace();
}
}
+ return true;
+ } else {
+ return false;
}
}
}
- class EventDispatchThread extends Thread {
+ class NEDT extends Thread {
volatile boolean shouldStop = false;
volatile boolean isRunning = false;
- ArrayList<RunnableTask> tasks = new ArrayList<RunnableTask>(); // one shot tasks
+ final ArrayList<RunnableTask> tasks = new ArrayList<RunnableTask>(); // one shot tasks
- public EventDispatchThread(ThreadGroup tg, String name) {
+ public NEDT(final ThreadGroup tg, final String name) {
super(tg, name);
}
final public boolean isRunning() {
- return isRunning;
+ return isRunning && !shouldStop;
}
@Override
@@ -267,24 +317,24 @@ public class DefaultEDTUtil implements EDTUtil {
}
private final void validateNoRecursiveLocksHold() {
- if(Lock.DEBUG) {
- if(LockDebugUtil.getRecursiveLockTrace().size()>0) {
- LockDebugUtil.dumpRecursiveLockTrace(System.err);
- throw new InternalError("XXX");
- }
+ if(LockDebugUtil.getRecursiveLockTrace().size()>0) {
+ LockDebugUtil.dumpRecursiveLockTrace(System.err);
+ throw new InternalError("XXX");
}
}
-
- /**
+
+ /**
* Utilizing locking only on tasks and its execution,
* not for event dispatching.
*/
@Override
final public void run() {
if(DEBUG) {
- System.err.println(getName()+": EDT run() START "+ getName());
+ System.err.println(getName()+": Default-EDT run() START "+ getName());
+ }
+ if(Lock.DEBUG) {
+ validateNoRecursiveLocksHold();
}
- validateNoRecursiveLocksHold();
RuntimeException error = null;
try {
do {
@@ -299,7 +349,7 @@ public class DefaultEDTUtil implements EDTUtil {
if(!shouldStop && tasks.size()==0) {
try {
tasks.wait(pollPeriod);
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
e.printStackTrace();
}
}
@@ -307,58 +357,58 @@ public class DefaultEDTUtil implements EDTUtil {
if(tasks.size()>0) {
task = tasks.remove(0);
tasks.notifyAll();
+ final Object attachment = task.getAttachment();
+ if( TASK_ATTACHMENT_STOP == attachment ) {
+ shouldStop = true;
+ } else if( TASK_ATTACHMENT_TEST_ERROR == attachment ) {
+ tasks.add(0, task);
+ task = null;
+ throw new RuntimeException("TASK_ATTACHMENT_TEST_ERROR");
+ }
}
}
if(null!=task) {
task.run();
- validateNoRecursiveLocksHold();
+ if(Lock.DEBUG) {
+ validateNoRecursiveLocksHold();
+ }
if(!task.hasWaiter() && null != task.getThrowable()) {
// at least dump stack-trace in case nobody waits for result
+ System.err.println("DefaultEDT.run(): Caught exception occured on thread "+Thread.currentThread().getName()+": "+task.toString());
task.getThrowable().printStackTrace();
}
}
} while(!shouldStop) ;
- } catch (Throwable t) {
+ } catch (final Throwable t) {
// handle errors ..
shouldStop = true;
if(t instanceof RuntimeException) {
error = (RuntimeException) t;
} else {
- error = new RuntimeException("Within EDT", t);
+ error = new RuntimeException("Within Default-EDT", t);
}
} finally {
+ final String msg = getName()+": Default-EDT finished w/ "+tasks.size()+" left";
if(DEBUG) {
- RunnableTask rt = ( tasks.size() > 0 ) ? tasks.get(0) : null ;
- System.err.println(getName()+": EDT run() END "+ getName()+", tasks: "+tasks.size()+", "+rt+", "+error);
+ System.err.println(msg+", "+error);
}
synchronized(edtLock) {
- if(null==error) {
- synchronized(tasks) {
- // drain remaining tasks (stop not on EDT),
- // while having tasks and no previous-task, or previous-task is non final
- RunnableTask task = null;
- while ( ( null == task || task.getAttachment() == null ) && tasks.size() > 0 ) {
- task = tasks.remove(0);
- task.run();
- tasks.notifyAll();
- }
- if(DEBUG) {
- if(null!=task && task.getAttachment()==null) {
- System.err.println(getName()+" Warning: EDT exit: Last task Not Final: "+tasks.size()+", "+task+" - "+edt);
- } else if(tasks.size()>0) {
- System.err.println(getName()+" Warning: EDT exit: Remaining tasks Post Final: "+tasks.size());
- }
- Thread.dumpStack();
- }
+ int i = 0;
+ while( tasks.size() > 0 ) {
+ // notify all waiter
+ final String msg2 = msg+", task #"+i;
+ final Throwable t = null != error ? new Throwable(msg2, error) : new Throwable(msg2);
+ final RunnableTask rt = tasks.remove(0);
+ if( null != rt ) {
+ rt.flush(t);
+ i++;
}
}
- isRunning = !shouldStop;
- if(!isRunning) {
- edtLock.notifyAll();
- }
+ isRunning = false;
+ edtLock.notifyAll();
}
if(DEBUG) {
- System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error);
+ System.err.println(msg+" EXIT, exception: "+error);
}
if(null!=error) {
throw error;
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index bca7f6e5b..84ce45238 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,44 +29,249 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.newt.Display;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.event.NEWTEvent;
import com.jogamp.newt.event.NEWTEventConsumer;
import jogamp.newt.event.NEWTEventTask;
+
import com.jogamp.newt.util.EDTUtil;
+import com.jogamp.opengl.util.PNGPixelRect;
+
+import java.io.IOException;
+import java.net.URLConnection;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.util.PixelFormatUtil;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
public abstract class DisplayImpl extends Display {
private static int serialno = 1;
+ private static final boolean pngUtilAvail;
+
+ static {
+ NativeWindowFactory.addCustomShutdownHook(true /* head */, new Runnable() {
+ @Override
+ public void run() {
+ WindowImpl.shutdownAll();
+ ScreenImpl.shutdownAll();
+ DisplayImpl.shutdownAll();
+ }
+ });
+
+ final ClassLoader cl = DisplayImpl.class.getClassLoader();
+ pngUtilAvail = ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.PNGPixelRect", cl);
+ }
+
+ public static final boolean isPNGUtilAvailable() { return pngUtilAvail; }
+
+ final ArrayList<PointerIconImpl> pointerIconList = new ArrayList<PointerIconImpl>();
+
+ /** Executed from EDT! */
+ private void destroyAllPointerIconFromList(final long dpy) {
+ synchronized(pointerIconList) {
+ final int count = pointerIconList.size();
+ for( int i=0; i < count; i++ ) {
+ final PointerIconImpl item = pointerIconList.get(i);
+ if(DEBUG) {
+ System.err.println("destroyAllPointerIconFromList: dpy "+toHexString(dpy)+", # "+i+"/"+count+": "+item+" @ "+getThreadName());
+ }
+ if( null != item && item.isValid() ) {
+ item.destroyOnEDT(dpy);
+ }
+ }
+ pointerIconList.clear();
+ }
+ }
+
+ @Override
+ public PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.BGRA8888; }
+ @Override
+ public boolean getNativePointerIconForceDirectNIO() { return false; }
+
+ @Override
+ public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException, IOException
+ {
+ if( null == pngResource || 0 >= pngResource.resourceCount() ) {
+ throw new IllegalArgumentException("Null or invalid pngResource "+pngResource);
+ }
+ if( !pngUtilAvail ) {
+ return null;
+ }
+ final PointerIconImpl[] res = { null };
+ runOnEDTIfAvail(true, new Runnable() {
+ public void run() {
+ try {
+ if( !DisplayImpl.this.isNativeValidAsync() ) {
+ throw new IllegalStateException("Display.createPointerIcon: Display invalid "+DisplayImpl.this);
+ }
+ final URLConnection urlConn = pngResource.resolve(0);
+ if( null == urlConn ) {
+ throw new IOException("Could not resolve "+pngResource.resourcePaths[0]);
+ }
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(),
+ getNativePointerIconPixelFormat(),
+ getNativePointerIconForceDirectNIO(),
+ 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ final long handle = createPointerIconImplChecked(image.getPixelformat(), image.getSize().getWidth(), image.getSize().getHeight(),
+ image.getPixels(), hotX, hotY);
+ final PointImmutable hotspot = new Point(hotX, hotY);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconPNG.0: "+image+", handle: "+toHexString(handle)+", hot "+hotspot);
+ }
+ if( 0 != handle ) {
+ res[0] = new PointerIconImpl(DisplayImpl.this, image, hotspot, handle);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconPNG.0: "+res[0]);
+ }
+ }
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ } } );
+ if( null != res[0] ) {
+ synchronized(pointerIconList) {
+ pointerIconList.add(res[0]);
+ }
+ }
+ return res[0];
+ }
+
+ @Override
+ public final PointerIcon createPointerIcon(final PixelRectangle pixelrect, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException
+ {
+ if( null == pixelrect ) {
+ throw new IllegalArgumentException("Null or pixelrect");
+ }
+ final PixelRectangle fpixelrect;
+ if( getNativePointerIconPixelFormat() != pixelrect.getPixelformat() || pixelrect.isGLOriented() ) {
+ // conversion !
+ fpixelrect = PixelFormatUtil.convert32(pixelrect, getNativePointerIconPixelFormat(),
+ 0 /* ddestStride */, false /* isGLOriented */, getNativePointerIconForceDirectNIO() );
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: Conversion-FMT "+pixelrect+" -> "+fpixelrect);
+ }
+ } else if( getNativePointerIconForceDirectNIO() && !Buffers.isDirect(pixelrect.getPixels()) ) {
+ // transfer to direct NIO
+ final ByteBuffer sBB = pixelrect.getPixels();
+ final ByteBuffer dBB = Buffers.newDirectByteBuffer(sBB.array(), sBB.arrayOffset());
+ fpixelrect = new PixelRectangle.GenericPixelRect(pixelrect.getPixelformat(), pixelrect.getSize(), pixelrect.getStride(), pixelrect.isGLOriented(), dBB);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: Conversion-NIO "+pixelrect+" -> "+fpixelrect);
+ }
+ } else {
+ fpixelrect = pixelrect;
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: No conversion "+fpixelrect);
+ }
+ }
+ final PointerIconImpl[] res = { null };
+ runOnEDTIfAvail(true, new Runnable() {
+ public void run() {
+ try {
+ if( !DisplayImpl.this.isNativeValidAsync() ) {
+ throw new IllegalStateException("Display.createPointerIcon: Display invalid "+DisplayImpl.this);
+ }
+ if( null != fpixelrect ) {
+ final long handle = createPointerIconImplChecked(fpixelrect.getPixelformat(),
+ fpixelrect.getSize().getWidth(),
+ fpixelrect.getSize().getHeight(),
+ fpixelrect.getPixels(), hotX, hotY);
+ if( 0 != handle ) {
+ res[0] = new PointerIconImpl(DisplayImpl.this, fpixelrect, new Point(hotX, hotY), handle);
+ }
+ }
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ } } );
+ if( null != res[0] ) {
+ synchronized(pointerIconList) {
+ pointerIconList.add(res[0]);
+ }
+ }
+ return res[0];
+ }
+
+ /**
+ * Executed from EDT!
+ *
+ * @param pixelformat the <code>pixels</code>'s format
+ * @param width the <code>pixels</code>'s width
+ * @param height the <code>pixels</code>'s height
+ * @param pixels the <code>pixels</code>
+ * @param hotX the PointerIcon's hot-spot x-coord
+ * @param hotY the PointerIcon's hot-spot x-coord
+ * @return if successful a valid handle (not null), otherwise null.
+ */
+ protected final long createPointerIconImplChecked(final PixelFormat pixelformat, final int width, final int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ if( getNativePointerIconPixelFormat() != pixelformat ) {
+ throw new IllegalArgumentException("Pixelformat no "+getNativePointerIconPixelFormat()+", but "+pixelformat);
+ }
+ if( getNativePointerIconForceDirectNIO() && !Buffers.isDirect(pixels) ) {
+ throw new IllegalArgumentException("pixel buffer is not direct "+pixels);
+ }
+ return createPointerIconImpl(pixelformat, width, height, pixels, hotX, hotY);
+ }
+
+ /**
+ * Executed from EDT!
+ *
+ * @param pixelformat the <code>pixels</code>'s format
+ * @param width the <code>pixels</code>'s width
+ * @param height the <code>pixels</code>'s height
+ * @param pixels the <code>pixels</code>
+ * @param hotX the PointerIcon's hot-spot x-coord
+ * @param hotY the PointerIcon's hot-spot x-coord
+ * @return if successful a valid handle (not null), otherwise null.
+ */
+ protected long createPointerIconImpl(final PixelFormat pixelformat, final int width, final int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return 0;
+ }
- private static Class<?> getDisplayClass(String type)
- throws ClassNotFoundException
+ /** Executed from EDT! */
+ protected void destroyPointerIconImpl(final long displayHandle, final long piHandle) { }
+
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
+
+ private static Class<?> getDisplayClass(final String type)
+ throws ClassNotFoundException
{
final Class<?> displayClass = NewtFactory.getCustomClass(type, "DisplayDriver");
if(null==displayClass) {
- throw new ClassNotFoundException("Failed to find NEWT Display Class <"+type+".DisplayDriver>");
+ throw new ClassNotFoundException("Failed to find NEWT Display Class <"+type+".DisplayDriver>");
}
return displayClass;
}
/** Make sure to reuse a Display with the same name */
- public static Display create(String type, String name, final long handle, boolean reuse) {
+ public static Display create(final String type, String name, final long handle, final boolean reuse) {
try {
- Class<?> displayClass = getDisplayClass(type);
- DisplayImpl display = (DisplayImpl) displayClass.newInstance();
+ final Class<?> displayClass = getDisplayClass(type);
+ final DisplayImpl display = (DisplayImpl) displayClass.newInstance();
name = display.validateDisplayName(name, handle);
synchronized(displayList) {
if(reuse) {
- Display display0 = Display.getLastDisplayOf(type, name, -1);
+ final Display display0 = Display.getLastDisplayOf(type, name, -1, true /* shared only */);
if(null != display0) {
if(DEBUG) {
System.err.println("Display.create() REUSE: "+display0+" "+getThreadName());
@@ -74,29 +279,28 @@ public abstract class DisplayImpl extends Display {
return display0;
}
}
+ display.exclusive = !reuse;
display.name = name;
display.type=type;
- display.destroyWhenUnused=false;
display.refCount=0;
display.id = serialno++;
display.fqname = getFQName(display.type, display.name, display.id);
display.hashCode = display.fqname.hashCode();
- displayList.add(display);
- }
- if(null == display.edtUtil) {
- display.setEDTUtil(null); // device's default if EDT is used, or null
+ display.setEDTUtil( display.edtUtil ); // device's default if EDT is used, or null
+ Display.addDisplay2List(display);
}
+
if(DEBUG) {
System.err.println("Display.create() NEW: "+display+" "+getThreadName());
}
return display;
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new RuntimeException(e);
}
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
@@ -116,48 +320,47 @@ public abstract class DisplayImpl extends Display {
return true;
}
+ @Override
public int hashCode() {
return hashCode;
}
- public synchronized final void createNative()
+ @Override
+ public synchronized final void createNative()
throws NativeWindowException
{
- if(null==aDevice) {
+ if( null == aDevice ) {
if(DEBUG) {
System.err.println("Display.createNative() START ("+getThreadName()+", "+this+")");
}
final DisplayImpl f_dpy = this;
try {
runOnEDTIfAvail(true, new Runnable() {
+ @Override
public void run() {
f_dpy.createNativeImpl();
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
throw new NativeWindowException(t);
}
- if(null==aDevice) {
+ if( null == aDevice ) {
throw new NativeWindowException("Display.createNative() failed to instanciate an AbstractGraphicsDevice");
}
- if(DEBUG) {
- System.err.println("Display.createNative() END ("+getThreadName()+", "+this+")");
- }
synchronized(displayList) {
displaysActive++;
+ if(DEBUG) {
+ System.err.println("Display.createNative() END ("+getThreadName()+", "+this+", active "+displaysActive+")");
+ }
}
}
}
- protected boolean shallRunOnEDT() {
- return true;
- }
-
protected EDTUtil createEDTUtil() {
final EDTUtil def;
if(NewtFactory.useEDT()) {
- def = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable);
+ def = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable);
if(DEBUG) {
- System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName());
+ System.err.println("Display.createEDTUtil("+getFQName()+"): "+def.getClass().getName());
}
} else {
def = null;
@@ -166,26 +369,20 @@ public abstract class DisplayImpl extends Display {
}
@Override
- public EDTUtil setEDTUtil(EDTUtil newEDTUtil) {
- if(null == newEDTUtil) {
- newEDTUtil = createEDTUtil();
- } else if( newEDTUtil == edtUtil ) {
- if(DEBUG) {
- System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!");
+ public synchronized EDTUtil setEDTUtil(final EDTUtil usrEDTUtil) {
+ final EDTUtil oldEDTUtil = edtUtil;
+ if( null != usrEDTUtil && usrEDTUtil == oldEDTUtil ) {
+ if( DEBUG ) {
+ System.err.println("Display.setEDTUtil: "+usrEDTUtil+" - keep!");
}
- return null; // no change
+ return oldEDTUtil;
}
- final EDTUtil oldEDTUtil = edtUtil;
if(DEBUG) {
- System.err.println("Display.setEDTUtil: "+oldEDTUtil+" -> "+newEDTUtil);
- }
- if(null != oldEDTUtil) {
- stopEDT( new Runnable() { public void run() {} } );
- // ready for restart ..
- oldEDTUtil.waitUntilStopped();
- oldEDTUtil.reset();
+ final String msg = ( null == usrEDTUtil ) ? "default" : "custom";
+ System.err.println("Display.setEDTUtil("+msg+"): "+oldEDTUtil+" -> "+usrEDTUtil);
}
- edtUtil = newEDTUtil;
+ stopEDT( oldEDTUtil, null );
+ edtUtil = ( null == usrEDTUtil ) ? createEDTUtil() : usrEDTUtil;
return oldEDTUtil;
}
@@ -194,72 +391,143 @@ public abstract class DisplayImpl extends Display {
return edtUtil;
}
- private void stopEDT(final Runnable task) {
- if( shallRunOnEDT() && null!=edtUtil ) {
- edtUtil.invokeStop(task);
- } else {
+ private static void stopEDT(final EDTUtil edtUtil, final Runnable task) {
+ if( null != edtUtil ) {
+ if( edtUtil.isRunning() ) {
+ final boolean res = edtUtil.invokeStop(true, task);
+ if( DEBUG ) {
+ if ( !res ) {
+ System.err.println("Warning: invokeStop() failed");
+ Thread.dumpStack();
+ }
+ }
+ }
+ edtUtil.waitUntilStopped();
+ // ready for restart ..
+ } else if( null != task ) {
task.run();
}
}
- public void runOnEDTIfAvail(boolean wait, final Runnable task) {
- if( shallRunOnEDT() && null!=edtUtil && !edtUtil.isCurrentThreadEDT()) {
- edtUtil.invoke(wait, task);
- } else {
- task.run();
+ public void runOnEDTIfAvail(final boolean wait, final Runnable task) {
+ final EDTUtil _edtUtil = edtUtil;
+ if( !_edtUtil.isRunning() ) { // start EDT if not running yet
+ synchronized( this ) {
+ if( !_edtUtil.isRunning() ) { // // volatile dbl-checked-locking OK
+ if( DEBUG ) {
+ System.err.println("Info: EDT start "+Thread.currentThread().getName()+", "+this);
+ Thread.dumpStack();
+ }
+ _edtUtil.start();
+ }
+ }
+ }
+ if( !_edtUtil.isCurrentThreadEDT() ) {
+ if( _edtUtil.invoke(wait, task) ) {
+ return; // done
+ }
+ if( DEBUG ) {
+ System.err.println("Warning: invoke(wait "+wait+", ..) on EDT failed .. invoke on current thread "+Thread.currentThread().getName());
+ Thread.dumpStack();
+ }
}
+ task.run();
}
- public boolean validateEDT() {
- if(0==refCount && null==aDevice && null != edtUtil && edtUtil.isRunning()) {
- stopEDT( new Runnable() {
- public void run() {
- // nop
+ @Override
+ public boolean validateEDTStopped() {
+ if( 0==refCount && null == aDevice ) {
+ final EDTUtil _edtUtil = edtUtil;
+ if( null != _edtUtil && _edtUtil.isRunning() ) {
+ synchronized( this ) {
+ if( null != edtUtil && edtUtil.isRunning() ) { // // volatile dbl-checked-locking OK
+ stopEDT( edtUtil, null );
+ return true;
+ }
}
- } );
- edtUtil.waitUntilStopped();
- edtUtil.reset();
- return true;
+ }
}
return false;
}
+ @Override
public synchronized final void destroy() {
if(DEBUG) {
dumpDisplayList("Display.destroy("+getFQName()+") BEGIN");
}
synchronized(displayList) {
- displayList.remove(this);
if(0 < displaysActive) {
displaysActive--;
}
+ if(DEBUG) {
+ System.err.println("Display.destroy(): "+this+", active "+displaysActive+" "+getThreadName());
+ }
}
- if(DEBUG) {
- System.err.println("Display.destroy(): "+this+" "+getThreadName());
- }
- final AbstractGraphicsDevice f_aDevice = aDevice;
final DisplayImpl f_dpy = this;
- stopEDT( new Runnable() {
+ final AbstractGraphicsDevice f_aDevice = aDevice;
+ aDevice = null;
+ refCount=0;
+ stopEDT( edtUtil, new Runnable() { // blocks!
+ @Override
public void run() {
if ( null != f_aDevice ) {
- f_dpy.closeNativeImpl();
+ f_dpy.destroyAllPointerIconFromList(f_aDevice.getHandle());
+ f_dpy.closeNativeImpl(f_aDevice);
}
}
} );
- if(null!=edtUtil) {
- edtUtil.waitUntilStopped();
- edtUtil.reset();
- }
- aDevice = null;
- refCount=0;
if(DEBUG) {
dumpDisplayList("Display.destroy("+getFQName()+") END");
}
}
+ /** May be utilized at a shutdown hook, impl. does not block. */
+ /* pp */ static final void shutdownAll() {
+ final int dCount = displayList.size();
+ if(DEBUG) {
+ dumpDisplayList("Display.shutdownAll "+dCount+" instances, on thread "+getThreadName());
+ }
+ for(int i=0; i<dCount && displayList.size()>0; i++) { // be safe ..
+ final DisplayImpl d = (DisplayImpl) displayList.remove(0).get();
+ if(DEBUG) {
+ System.err.println("Display.shutdownAll["+(i+1)+"/"+dCount+"]: "+d+", GCed "+(null==d));
+ }
+ if( null != d ) { // GC'ed ?
+ if(0 < displaysActive) {
+ displaysActive--;
+ }
+ final EDTUtil edtUtil = d.getEDTUtil();
+ final AbstractGraphicsDevice f_aDevice = d.aDevice;
+ d.aDevice = null;
+ d.refCount=0;
+ final Runnable closeNativeTask = new Runnable() {
+ @Override
+ public void run() {
+ if ( null != d.getGraphicsDevice() ) {
+ d.destroyAllPointerIconFromList(f_aDevice.getHandle());
+ d.closeNativeImpl(f_aDevice);
+ }
+ }
+ };
+ if(null != edtUtil) {
+ final long coopSleep = edtUtil.getPollPeriod() * 2;
+ if( edtUtil.isRunning() ) {
+ edtUtil.invokeStop(false, closeNativeTask); // don't block
+ }
+ try {
+ Thread.sleep( coopSleep < 50 ? coopSleep : 50 );
+ } catch (final InterruptedException e) { }
+ } else {
+ closeNativeTask.run();
+ }
+ }
+ }
+ }
+
+ @Override
public synchronized final int addReference() {
if(DEBUG) {
- System.err.println("Display.addReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount+1));
+ System.err.println("Display.addReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount+1));
}
if ( 0 == refCount ) {
createNative();
@@ -271,9 +539,10 @@ public abstract class DisplayImpl extends Display {
}
+ @Override
public synchronized final int removeReference() {
if(DEBUG) {
- System.err.println("Display.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1));
+ System.err.println("Display.removeReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount-1));
}
refCount--; // could become < 0, in case of manual destruction without actual creation/addReference
if(0>=refCount) {
@@ -283,50 +552,61 @@ public abstract class DisplayImpl extends Display {
return refCount;
}
+ @Override
public synchronized final int getReferenceCount() {
return refCount;
}
protected abstract void createNativeImpl();
- protected abstract void closeNativeImpl();
+ protected abstract void closeNativeImpl(AbstractGraphicsDevice aDevice);
+ @Override
public final int getId() {
return id;
}
+ @Override
public final String getType() {
return type;
}
+ @Override
public final String getName() {
return name;
}
+ @Override
public final String getFQName() {
return fqname;
}
+ @Override
+ public final boolean isExclusive() {
+ return exclusive;
+ }
+
public static final String nilString = "nil" ;
- public String validateDisplayName(String name, long handle) {
+ public String validateDisplayName(String name, final long handle) {
if(null==name && 0!=handle) {
name="wrapping-"+toHexString(handle);
}
return ( null == name ) ? nilString : name ;
}
- private static String getFQName(String type, String name, int id) {
+ private static String getFQName(String type, String name, final int id) {
if(null==type) type=nilString;
if(null==name) name=nilString;
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append(type);
sb.append("_");
sb.append(name);
sb.append("-");
sb.append(id);
- return sb.toString().intern();
+ return sb.toString();
}
+ @Override
public final long getHandle() {
if(null!=aDevice) {
return aDevice.getHandle();
@@ -334,49 +614,51 @@ public abstract class DisplayImpl extends Display {
return 0;
}
+ @Override
public final AbstractGraphicsDevice getGraphicsDevice() {
return aDevice;
}
+ @Override
public synchronized final boolean isNativeValid() {
return null != aDevice;
}
+ protected final boolean isNativeValidAsync() {
+ return null != aDevice;
+ }
+ @Override
public boolean isEDTRunning() {
- if(null!=edtUtil) {
- return edtUtil.isRunning();
+ final EDTUtil _edtUtil = edtUtil;
+ if( null != _edtUtil ) {
+ return _edtUtil.isRunning();
}
return false;
}
@Override
public String toString() {
- return "NEWT-Display["+getFQName()+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", edtRunning "+isEDTRunning()+", "+aDevice+"]";
+ final EDTUtil _edtUtil = edtUtil;
+ final boolean _edtUtilRunning = ( null != _edtUtil ) ? _edtUtil.isRunning() : false;
+ return "NEWT-Display["+getFQName()+", excl "+exclusive+", refCount "+refCount+", hasEDT "+(null!=_edtUtil)+", edtRunning "+_edtUtilRunning+", "+aDevice+"]";
}
+ /** Dispatch native Toolkit messageges */
protected abstract void dispatchMessagesNative();
- private Object eventsLock = new Object();
+ private final Object eventsLock = new Object();
private ArrayList<NEWTEventTask> events = new ArrayList<NEWTEventTask>();
private volatile boolean haveEvents = false;
- class DispatchMessagesRunnable implements Runnable {
+ final protected Runnable dispatchMessagesRunnable = new Runnable() {
+ @Override
public void run() {
DisplayImpl.this.dispatchMessages();
- }
- }
- protected DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable();
+ } };
- final void dispatchMessage(final NEWTEventTask eventTask) {
- final NEWTEvent event = eventTask.get();
- try {
- if(null == event) {
- // Ooops ?
- System.err.println("Warning: event of eventTask is NULL");
- Thread.dumpStack();
- return;
- }
- final Object source = event.getSource();
+ final void dispatchMessage(final NEWTEvent event) {
+ try {
+ final Object source = event.getSource();
if(source instanceof NEWTEventConsumer) {
final NEWTEventConsumer consumer = (NEWTEventConsumer) source ;
if(!consumer.consumeEvent(event)) {
@@ -386,13 +668,28 @@ public abstract class DisplayImpl extends Display {
} else {
throw new RuntimeException("Event source not NEWT: "+source.getClass().getName()+", "+source);
}
- } catch (Throwable t) {
+ } catch (final Throwable t) {
final RuntimeException re;
if(t instanceof RuntimeException) {
re = (RuntimeException) t;
} else {
re = new RuntimeException(t);
}
+ throw re;
+ }
+ }
+
+ final void dispatchMessage(final NEWTEventTask eventTask) {
+ final NEWTEvent event = eventTask.get();
+ try {
+ if(null == event) {
+ // Ooops ?
+ System.err.println("Warning: event of eventTask is NULL");
+ Thread.dumpStack();
+ return;
+ }
+ dispatchMessage(event);
+ } catch (final RuntimeException re) {
if( eventTask.isCallerWaiting() ) {
// propagate exception to caller
eventTask.setException(re);
@@ -400,14 +697,15 @@ public abstract class DisplayImpl extends Display {
throw re;
}
}
- eventTask.notifyCaller();
+ eventTask.notifyCaller();
}
-
+
+ @Override
public void dispatchMessages() {
// System.err.println("Display.dispatchMessages() 0 "+this+" "+getThreadName());
- if(0==refCount || // no screens
+ if(0==refCount || // no screens
null==getGraphicsDevice() // no native device
- )
+ )
{
return;
}
@@ -435,22 +733,23 @@ public abstract class DisplayImpl extends Display {
dispatchMessagesNative();
}
- public void enqueueEvent(boolean wait, NEWTEvent e) {
- if(!isEDTRunning()) {
+ public void enqueueEvent(final boolean wait, final NEWTEvent e) {
+ final EDTUtil _edtUtil = edtUtil;
+ if( !_edtUtil.isRunning() ) {
// oops .. we are already dead
if(DEBUG) {
- Throwable t = new Throwable("Warning: EDT already stopped: wait:="+wait+", "+e);
- t.printStackTrace();
+ System.err.println("Warning: EDT already stopped: wait:="+wait+", "+e);
+ Thread.dumpStack();
}
return;
}
-
+
// can't wait if we are on EDT or NEDT -> consume right away
- if(wait && edtUtil.isCurrentThreadEDTorNEDT() ) {
- dispatchMessage(new NEWTEventTask(e, null));
+ if(wait && _edtUtil.isCurrentThreadEDTorNEDT() ) {
+ dispatchMessage(e);
return;
}
-
+
final Object lock = new Object();
final NEWTEventTask eTask = new NEWTEventTask(e, wait?lock:null);
synchronized(lock) {
@@ -462,42 +761,45 @@ public abstract class DisplayImpl extends Display {
if( wait ) {
try {
lock.wait();
- } catch (InterruptedException ie) {
+ } catch (final InterruptedException ie) {
throw new RuntimeException(ie);
}
if( null != eTask.getException() ) {
throw eTask.getException();
}
- }
+ }
}
}
public interface DisplayRunnable<T> {
T run(long dpy);
- }
- public final <T> T runWithLockedDisplayHandle(DisplayRunnable<T> action) {
- final AbstractGraphicsDevice aDevice = getGraphicsDevice();
- if(null == aDevice) {
- throw new RuntimeException("null device - not initialized: "+this);
- }
+ }
+ public static final <T> T runWithLockedDevice(final AbstractGraphicsDevice device, final DisplayRunnable<T> action) {
T res;
- aDevice.lock();
+ device.lock();
try {
- res = action.run(aDevice.getHandle());
+ res = action.run(device.getHandle());
} finally {
- aDevice.unlock();
+ device.unlock();
}
return res;
}
-
- protected EDTUtil edtUtil = null;
+ public final <T> T runWithLockedDisplayDevice(final DisplayRunnable<T> action) {
+ final AbstractGraphicsDevice device = getGraphicsDevice();
+ if(null == device) {
+ throw new RuntimeException("null device - not initialized: "+this);
+ }
+ return runWithLockedDevice(device, action);
+ }
+
+ protected volatile EDTUtil edtUtil = null;
protected int id;
protected String name;
protected String type;
protected String fqname;
protected int hashCode;
protected int refCount; // number of Display references by Screen
- protected boolean destroyWhenUnused;
+ protected boolean exclusive; // do not share this display, uses NullLock!
protected AbstractGraphicsDevice aDevice;
}
diff --git a/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java
new file mode 100644
index 000000000..72300740f
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java
@@ -0,0 +1,146 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.newt;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.Screen;
+
+public class MonitorDeviceImpl extends MonitorDevice {
+
+ public MonitorDeviceImpl(final ScreenImpl screen, final int nativeId, final DimensionImmutable sizeMM, final Rectangle viewportPU, final Rectangle viewportWU, final MonitorMode currentMode, final ArrayHashSet<MonitorMode> supportedModes) {
+ super(screen, nativeId, sizeMM, viewportPU, viewportWU, currentMode, supportedModes);
+ }
+
+ @Override
+ public final MonitorMode queryCurrentMode() {
+ final ScreenImpl screenImpl = (ScreenImpl)screen;
+ final ScreenMonitorState sms = screenImpl.getScreenMonitorStatus(true);
+ sms.lock();
+ try {
+ final MonitorMode mm0 = screenImpl.queryCurrentMonitorModeIntern(this);
+ if(null == mm0) {
+ throw new InternalError("getCurrentMonitorModeIntern() == null");
+ }
+ MonitorMode mmU = supportedModes.get(mm0); // unified instance
+ if( null == mmU ) {
+ // add new mode avoiding exception!
+ mmU = sms.getMonitorModes().getOrAdd(mm0);
+ mmU = supportedModes.getOrAdd(mmU);
+ if( Screen.DEBUG ) {
+ System.err.println("Adding new mode: "+mm0+" -> "+mmU);
+ }
+ }
+ // if mode has changed somehow, update it ..
+ if( getCurrentMode().hashCode() != mmU.hashCode() ) {
+ setCurrentModeValue(mmU);
+ sms.fireMonitorModeChanged(this, mmU, true);
+ }
+ return mmU;
+ } finally {
+ sms.unlock();
+ }
+ }
+
+ @Override
+ public final boolean setCurrentMode(final MonitorMode mode) {
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode.0: "+this+" -> "+mode);
+ }
+ final ScreenImpl screenImpl = (ScreenImpl)screen;
+ final ScreenMonitorState sms = screenImpl.getScreenMonitorStatus(true);
+ sms.lock();
+ try {
+ final MonitorMode mmC = queryCurrentMode();
+ final MonitorMode mmU = supportedModes.get(mode); // unify via value hash
+ if( null == mmU ) {
+ throw new IllegalArgumentException("Given mode not in set of modes. Current mode "+mode+", "+this);
+ }
+ if( mmU.equals( mmC ) ) {
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode: 0.0 is-current (skip) "+mmU+" == "+mmC);
+ }
+ return true;
+ }
+ final long tStart;
+ if(Screen.DEBUG) {
+ tStart = System.currentTimeMillis();
+ } else {
+ tStart = 0;
+ }
+
+ sms.fireMonitorModeChangeNotify(this, mmU);
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): fireModeChangeNotify() "+mmU);
+ }
+
+ boolean success = screenImpl.setCurrentMonitorModeImpl(this, mmU);
+ if(success) {
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): setCurrentModeImpl() "+mmU+", success(1): "+success);
+ }
+ } else {
+ // 2nd attempt validate!
+ final MonitorMode queriedCurrent = queryCurrentMode(); // may fireModeChanged(..) if successful and differs!
+ success = queriedCurrent.hashCode() == mmU.hashCode() ;
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode.2: queried "+queriedCurrent);
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): setCurrentModeImpl() "+mmU+", success(2): "+success);
+ }
+ }
+ if( success ) {
+ setCurrentModeValue(mmU);
+ modeChanged = !isOriginalMode();
+ }
+ sms.fireMonitorModeChanged(this, mmU, success);
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): X.X: success "+success+": "+this);
+ }
+ return success;
+ } finally {
+ sms.unlock();
+ }
+ }
+
+ private final void setCurrentModeValue(final MonitorMode currentMode) {
+ this.currentMode = currentMode;
+ }
+
+ /* pp */ final Rectangle getMutuableViewportPU() { return viewportPU; }
+ /* pp */ final Rectangle getMutuableViewportWU() { return viewportWU; }
+
+ /* pp */ final ArrayHashSet<MonitorMode> getSupportedModesImpl() {
+ return supportedModes;
+ }
+
+}
diff --git a/src/newt/classes/jogamp/newt/MonitorModeProps.java b/src/newt/classes/jogamp/newt/MonitorModeProps.java
new file mode 100644
index 000000000..6e376ce48
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/MonitorModeProps.java
@@ -0,0 +1,418 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.newt;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+import java.util.List;
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.SurfaceSize;
+
+import jogamp.newt.MonitorDeviceImpl;
+import jogamp.newt.ScreenImpl;
+
+/**
+ * Encodes and decodes {@link MonitorMode} and {@link MonitorDevice} properties.
+ */
+public class MonitorModeProps {
+ /**
+ * {@value} Elements: width, height
+ * <p>
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * </p>
+ */
+ public static final int NUM_RESOLUTION_PROPERTIES = 2;
+
+ /**
+ * {@value} Element: bpp
+ * <p>
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * </p>
+ */
+ public static final int NUM_SURFACE_SIZE_PROPERTIES = 1;
+
+ /**
+ * {@value} Elements: refresh-rate (Hz*100), flags
+ * <p>
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * </p>
+ */
+ public static final int NUM_SIZEANDRATE_PROPERTIES = 2;
+
+ /**
+ * {@value} Elements: id, rotation
+ * <p>
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * </p>
+ */
+ public static final int NUM_MONITOR_MODE_PROPERTIES = 2;
+
+ /**
+ * {@value} Elements:
+ * <ul>
+ * <li>count</li>
+ * <li>{@link #NUM_RESOLUTION_PROPERTIES}</li>
+ * <li>{@link #NUM_SURFACE_SIZE_PROPERTIES}</li>
+ * <li>{@link #NUM_SIZEANDRATE_PROPERTIES}</li>
+ * <li>{@link #NUM_MONITOR_MODE_PROPERTIES}</li>
+ * <li>mode-id</li>
+ * </ul>
+ * <p>
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * </p>
+ */
+ public static final int NUM_MONITOR_MODE_PROPERTIES_ALL = 8;
+
+ /**
+ * {@value} Elements: count + {@link #NUM_RESOLUTION_PROPERTIES}
+ * <p>
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * </p>
+ */
+ public static final int IDX_MONITOR_MODE_BPP = 1 // count
+ + MonitorModeProps.NUM_RESOLUTION_PROPERTIES
+ ;
+ /**
+ * {@value} Elements:
+ * <ul>
+ * <li>count</li>
+ * <li>{@link #NUM_RESOLUTION_PROPERTIES}</li>
+ * <li>{@link #NUM_SURFACE_SIZE_PROPERTIES}</li>
+ * <li>{@link #NUM_SIZEANDRATE_PROPERTIES}</li>
+ * <li>mode-id</li>
+ * </ul>
+ * <p>
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * </p>
+ */
+ public static final int IDX_MONITOR_MODE_ROT = 1 // count
+ + MonitorModeProps.NUM_RESOLUTION_PROPERTIES
+ + MonitorModeProps.NUM_SURFACE_SIZE_PROPERTIES
+ + MonitorModeProps.NUM_SIZEANDRATE_PROPERTIES
+ + 1 // id of MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES
+ ;
+
+ /**
+ * {@value} Elements:
+ * <ul>
+ * <li>count</li>
+ * <li>id</li>
+ * <li>ScreenSizeMM[width, height] (2 elements)</li>
+ * <li>Rotated Viewport pixel-units (4 elements)</li>
+ * <li>Rotated Viewport window-units (4 elements)</li>
+ * <li>CurrentMonitorModeId</li>
+ * <li>Rotation</li>
+ * <li>SupportedModeId+</li>
+ * </ul>
+ * <p>
+ * Viewport := [x, y, width, height] (4 elements)
+ * </p>
+ * <p>
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * </p>
+ */
+ public static final int MIN_MONITOR_DEVICE_PROPERTIES = 15;
+
+ public static final int IDX_MONITOR_DEVICE_VIEWPORT = 1 // count
+ + 1 // native mode
+ + MonitorModeProps.NUM_RESOLUTION_PROPERTIES // sizeMM
+ ;
+
+ public static class Cache {
+ public final ArrayHashSet<DimensionImmutable> resolutions = new ArrayHashSet<DimensionImmutable>();
+ public final ArrayHashSet<SurfaceSize> surfaceSizes = new ArrayHashSet<SurfaceSize>();
+ public final ArrayHashSet<MonitorMode.SizeAndRRate> sizeAndRates = new ArrayHashSet<MonitorMode.SizeAndRRate>();
+ public final ArrayHashSet<MonitorMode> monitorModes = new ArrayHashSet<MonitorMode>();
+ public final ArrayHashSet<MonitorDevice> monitorDevices = new ArrayHashSet<MonitorDevice>();
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ private static DimensionImmutable streamInResolution(final int[] resolutionProperties, int offset) {
+ final Dimension resolution = new Dimension(resolutionProperties[offset++], resolutionProperties[offset++]);
+ return resolution;
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ private static SurfaceSize streamInSurfaceSize(final DimensionImmutable resolution, final int[] sizeProperties, final int offset) {
+ return new SurfaceSize(resolution, sizeProperties[offset]);
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ private static MonitorMode.SizeAndRRate streamInSizeAndRRate(final SurfaceSize surfaceSize, final int[] sizeAndRRateProperties, int offset) {
+ final float refreshRate = sizeAndRRateProperties[offset++]/100.0f;
+ final int flags = sizeAndRRateProperties[offset++];
+ return new MonitorMode.SizeAndRRate(surfaceSize, refreshRate, flags);
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ private static MonitorMode streamInMonitorMode0(final MonitorMode.SizeAndRRate sizeAndRate, final int[] modeProperties, int offset) {
+ final int id = modeProperties[offset++];
+ final int rotation = modeProperties[offset++];
+ return new MonitorMode(id, sizeAndRate, rotation);
+ }
+
+ /**
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ *
+ * @param mode_idx if not null and cache is given, returns the index of resulting {@link MonitorMode} within {@link Cache#monitorModes}.
+ * @param cache optional hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
+ * @param modeProperties the input data
+ * @param offset the offset to the input data
+ * @return {@link MonitorMode} of the identical (old or new) element in {@link Cache#monitorModes},
+ * matching the input <code>modeProperties</code>, or null if input could not be processed.
+ */
+ public static MonitorMode streamInMonitorMode(final int[] mode_idx, final Cache cache,
+ final int[] modeProperties, int offset) {
+ final int count = modeProperties[offset];
+ if(NUM_MONITOR_MODE_PROPERTIES_ALL != count) {
+ throw new RuntimeException("property count should be "+NUM_MONITOR_MODE_PROPERTIES_ALL+", but is "+count+", len "+(modeProperties.length-offset));
+ }
+ if(NUM_MONITOR_MODE_PROPERTIES_ALL > modeProperties.length-offset) {
+ throw new RuntimeException("properties array too short, should be >= "+NUM_MONITOR_MODE_PROPERTIES_ALL+", is "+(modeProperties.length-offset));
+ }
+ offset++;
+ DimensionImmutable resolution = MonitorModeProps.streamInResolution(modeProperties, offset);
+ offset += MonitorModeProps.NUM_RESOLUTION_PROPERTIES;
+ if(null!=cache) {
+ resolution = cache.resolutions.getOrAdd(resolution);
+ }
+
+ SurfaceSize surfaceSize = MonitorModeProps.streamInSurfaceSize(resolution, modeProperties, offset);
+ offset += MonitorModeProps.NUM_SURFACE_SIZE_PROPERTIES;
+ if(null!=cache) {
+ surfaceSize = cache.surfaceSizes.getOrAdd(surfaceSize);
+ }
+
+ MonitorMode.SizeAndRRate sizeAndRate = MonitorModeProps.streamInSizeAndRRate(surfaceSize, modeProperties, offset);
+ offset += MonitorModeProps.NUM_SIZEANDRATE_PROPERTIES;
+ if(null!=cache) {
+ sizeAndRate = cache.sizeAndRates.getOrAdd(sizeAndRate);
+ }
+
+ MonitorMode monitorMode = MonitorModeProps.streamInMonitorMode0(sizeAndRate, modeProperties, offset);
+ if(null!=cache) {
+ monitorMode = cache.monitorModes.getOrAdd(monitorMode);
+ }
+ if( null != mode_idx && null!=cache) {
+ final int _modeIdx = cache.monitorModes.indexOf(monitorMode);
+ if( 0 > _modeIdx ) {
+ throw new InternalError("Invalid index of current unified mode "+monitorMode);
+ }
+ mode_idx[0] = _modeIdx;
+ }
+ return monitorMode;
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ public static int[] streamOutMonitorMode (final MonitorMode monitorMode) {
+ final int[] data = new int[NUM_MONITOR_MODE_PROPERTIES_ALL];
+ int idx=0;
+ data[idx++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+ data[idx++] = monitorMode.getSurfaceSize().getResolution().getWidth();
+ data[idx++] = monitorMode.getSurfaceSize().getResolution().getHeight();
+ data[idx++] = monitorMode.getSurfaceSize().getBitsPerPixel();
+ data[idx++] = (int)(monitorMode.getRefreshRate()*100.0f); // Hz*100
+ data[idx++] = monitorMode.getFlags();
+ data[idx++] = monitorMode.getId();
+ data[idx++] = monitorMode.getRotation();
+ if(NUM_MONITOR_MODE_PROPERTIES_ALL != idx) {
+ throw new InternalError("wrong number of attributes: got "+idx+" != should "+NUM_MONITOR_MODE_PROPERTIES_ALL);
+ }
+ return data;
+ }
+
+ /**
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * <p>
+ * Note: This variant only works for impl. w/ a unique mode key pair <i>modeId, rotation</i>.
+ * </p>
+ * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
+ * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
+ * @param modeProperties the input data
+ * @param offset the offset to the input data
+ * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices},
+ * matching the input <code>modeProperties</code>, or null if input could not be processed.
+ */
+ public static MonitorDevice streamInMonitorDevice(final int[] monitor_idx, final Cache cache, final ScreenImpl screen, final int[] monitorProperties, int offset) {
+ // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+ final int count = monitorProperties[offset];
+ if(MIN_MONITOR_DEVICE_PROPERTIES > count) {
+ throw new RuntimeException("property count should be >= "+MIN_MONITOR_DEVICE_PROPERTIES+", but is "+count+", len "+(monitorProperties.length-offset));
+ }
+ if(MIN_MONITOR_DEVICE_PROPERTIES > monitorProperties.length-offset) {
+ throw new RuntimeException("properties array too short (min), should be >= "+MIN_MONITOR_DEVICE_PROPERTIES+", is "+(monitorProperties.length-offset));
+ }
+ if(count > monitorProperties.length-offset) {
+ throw new RuntimeException("properties array too short (count), should be >= "+count+", is "+(monitorProperties.length-offset));
+ }
+ final int limit = offset + count;
+ offset++;
+ final List<MonitorMode> allMonitorModes = cache.monitorModes.getData();
+ final int id = monitorProperties[offset++];
+ final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES;
+ final Rectangle viewportPU = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
+ final Rectangle viewportWU = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
+ final MonitorMode currentMode;
+ {
+ final int modeId = monitorProperties[offset++];
+ final int rotation = monitorProperties[offset++];
+ currentMode = getByNativeIdAndRotation(allMonitorModes, modeId, rotation);
+ }
+ final ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
+ while( offset < limit ) {
+ final int modeId = monitorProperties[offset++];
+ for (int i=0; i<allMonitorModes.size(); i++) {
+ final MonitorMode mode = allMonitorModes.get(i);
+ if( mode.getId() == modeId ) {
+ supportedModes.add(mode);
+ }
+ }
+ }
+ MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewportPU, viewportWU, currentMode, supportedModes);
+ if(null!=cache) {
+ monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice);
+ }
+ if( null != monitor_idx ) {
+ final int _monitorIdx = cache.monitorDevices.indexOf(monitorDevice);
+ if( 0 > _monitorIdx ) {
+ throw new InternalError("Invalid index of current unified mode "+monitorDevice);
+ }
+ monitor_idx[0] = _monitorIdx;
+ }
+ return monitorDevice;
+ }
+ private static MonitorMode getByNativeIdAndRotation(final List<MonitorMode> monitorModes, final int modeId, final int rotation) {
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if( mode.getId() == modeId && mode.getRotation() == rotation ) {
+ return mode;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * <p>
+ * This variant expects <code>count</code> to be <code>{@link MIN_MONITOR_DEVICE_PROPERTIES} - 1 - {@link NUM_MONITOR_MODE_PROPERTIES}</code>,
+ * due to lack of supported mode and current mode.
+ * </p>
+ *
+ * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
+ * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
+ * @param supportedModes pre-assembled list of supported {@link MonitorMode}s from cache.
+ * @param currentMode pre-fetched current {@link MonitorMode}s from cache.
+ * @param modeProperties the input data minus supported modes!
+ * @param offset the offset to the input data
+ * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices},
+ * matching the input <code>modeProperties</code>, or null if input could not be processed.
+ */
+ public static MonitorDevice streamInMonitorDevice(final int[] monitor_idx, final Cache cache, final ScreenImpl screen, final ArrayHashSet<MonitorMode> supportedModes, final MonitorMode currentMode, final int[] monitorProperties, int offset) {
+ // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+ final int count = monitorProperties[offset];
+ if(MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES != count) {
+ throw new RuntimeException("property count should be == "+(MIN_MONITOR_DEVICE_PROPERTIES-1-NUM_MONITOR_MODE_PROPERTIES)+", but is "+count+", len "+(monitorProperties.length-offset));
+ }
+ if(MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES > monitorProperties.length-offset) {
+ throw new RuntimeException("properties array too short (min), should be >= "+(MIN_MONITOR_DEVICE_PROPERTIES-1-NUM_MONITOR_MODE_PROPERTIES)+", is "+(monitorProperties.length-offset));
+ }
+ if(count > monitorProperties.length-offset) {
+ throw new RuntimeException("properties array too short (count), should be >= "+count+", is "+(monitorProperties.length-offset));
+ }
+ offset++;
+ final int id = monitorProperties[offset++];
+ final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES;
+ final Rectangle viewportPU = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
+ final Rectangle viewportWU = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
+ MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewportPU, viewportWU, currentMode, supportedModes);
+ if(null!=cache) {
+ monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice);
+ }
+ if( null != monitor_idx ) {
+ final int _monitorIdx = cache.monitorDevices.indexOf(monitorDevice);
+ if( 0 > _monitorIdx ) {
+ throw new InternalError("Invalid index of current unified mode "+monitorDevice);
+ }
+ monitor_idx[0] = _monitorIdx;
+ }
+ return monitorDevice;
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ public static int[] streamOutMonitorDevice (final MonitorDevice monitorDevice) {
+ // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+ final int supportedModeCount = monitorDevice.getSupportedModes().size();
+ if( 0 == supportedModeCount ) {
+ throw new RuntimeException("no supported modes: "+monitorDevice);
+ }
+ final int[] data = new int[MIN_MONITOR_DEVICE_PROPERTIES + supportedModeCount - 1];
+ int idx=0;
+ data[idx++] = data.length;
+ data[idx++] = monitorDevice.getId();
+ data[idx++] = monitorDevice.getSizeMM().getWidth();
+ data[idx++] = monitorDevice.getSizeMM().getHeight();
+ data[idx++] = monitorDevice.getViewport().getX();
+ data[idx++] = monitorDevice.getViewport().getY();
+ data[idx++] = monitorDevice.getViewport().getWidth();
+ data[idx++] = monitorDevice.getViewport().getHeight();
+ data[idx++] = monitorDevice.getViewportInWindowUnits().getX();
+ data[idx++] = monitorDevice.getViewportInWindowUnits().getY();
+ data[idx++] = monitorDevice.getViewportInWindowUnits().getWidth();
+ data[idx++] = monitorDevice.getViewportInWindowUnits().getHeight();
+ data[idx++] = monitorDevice.getCurrentMode().getId();
+ data[idx++] = monitorDevice.getCurrentMode().getRotation();
+ final List<MonitorMode> supportedModes = monitorDevice.getSupportedModes();
+ for(int i=0; i<supportedModes.size(); i++) {
+ data[idx++] = supportedModes.get(i).getId();
+ }
+ if(data.length != idx) {
+ throw new InternalError("wrong number of attributes: got "+idx+" != should "+data.length);
+ }
+ return data;
+ }
+
+ public final void swapRotatePair(final int rotation, final int[] pairs, int offset, final int numPairs) {
+ if( MonitorMode.ROTATE_0 == rotation || MonitorMode.ROTATE_180 == rotation ) {
+ // nop
+ return;
+ }
+ for(int i=0; i<numPairs; i++, offset+=2) {
+ final int tmp = pairs[offset];
+ pairs[offset] = pairs[offset+1];
+ pairs[offset+1] = tmp;
+ }
+ }
+
+}
diff --git a/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java b/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java
index bc0eb7531..793fbf9b0 100644
--- a/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java
+++ b/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -42,29 +42,22 @@ package jogamp.newt;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import jogamp.nativewindow.NWJNILibLoader;
-
import com.jogamp.common.jvm.JNILibLoaderBase;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.cache.TempJarCache;
public class NEWTJNILibLoader extends JNILibLoaderBase {
-
- public static void loadNEWT() {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- Platform.initSingleton();
- final String libName = "newt";
- if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) {
- // either: [jogl-all.jar, jogl-all-noawt.jar, jogl-all-mobile.jar] -> jogl-all-natives-<os.and.arch>.jar
- // or: nativewindow-core.jar -> nativewindow-natives-<os.and.arch>.jar,
- // newt-core.jar -> newt-natives-<os.and.arch>.jar
- JNILibLoaderBase.addNativeJarLibs(new Class<?>[] { NWJNILibLoader.class, NEWTJNILibLoader.class }, "-all", new String[] { "-noawt", "-mobile", "-core" } );
- }
- loadLibrary(libName, false, NEWTJNILibLoader.class.getClassLoader());
- return null;
- }
- });
- }
-
+ public static boolean loadNEWT() {
+ return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Platform.initSingleton();
+ final String libName = "newt";
+ if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) {
+ JNILibLoaderBase.addNativeJarLibsJoglCfg(new Class<?>[] { jogamp.nativewindow.Debug.class, jogamp.newt.Debug.class });
+ }
+ return Boolean.valueOf(loadLibrary(libName, false, NEWTJNILibLoader.class.getClassLoader()));
+ }
+ }).booleanValue();
+ }
}
diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java
index c6c1814f6..749391f1f 100644
--- a/src/newt/classes/jogamp/newt/OffscreenWindow.java
+++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,13 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt;
+import java.util.List;
+
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.GraphicsConfigurationFactory;
@@ -43,16 +45,19 @@ import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
+import com.jogamp.newt.MonitorDevice;
+
public class OffscreenWindow extends WindowImpl implements MutableSurface {
long surfaceHandle;
-
+
public OffscreenWindow() {
surfaceHandle = 0;
}
static long nextWindowHandle = 0x100; // start here - a marker
+ @Override
protected void createNativeImpl() {
if(capsRequested.isOnscreen()) {
throw new NativeWindowException("Capabilities is onscreen");
@@ -68,9 +73,10 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface {
synchronized(OffscreenWindow.class) {
setWindowHandle(nextWindowHandle++);
}
- visibleChanged(false, true);
+ visibleChanged(false, true);
}
+ @Override
protected void closeNativeImpl() {
// nop
}
@@ -81,30 +87,38 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface {
surfaceHandle = 0;
}
- public void setSurfaceHandle(long handle) {
+ @Override
+ public void setSurfaceHandle(final long handle) {
surfaceHandle = handle ;
}
@Override
public long getSurfaceHandle() {
return surfaceHandle;
- }
+ }
- protected void requestFocusImpl(boolean reparented) {
+ @Override
+ protected void requestFocusImpl(final boolean reparented) {
}
@Override
- public void setPosition(int x, int y) {
+ public void setPosition(final int x, final int y) {
// nop
}
-
+
@Override
- public boolean setFullscreen(boolean fullscreen) {
- // nop
- return false;
+ public boolean setFullscreen(final boolean fullscreen) {
+ return false; // nop
}
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+ @Override
+ public boolean setFullscreen(final List<MonitorDevice> monitors) {
+ return false; // nop
+ }
+
+
+ @Override
+ protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
sizeChanged(false, width, height, false);
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
@@ -121,21 +135,22 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface {
}
@Override
- public Point getLocationOnScreen(Point storage) {
+ public Point getLocationOnScreen(final Point storage) {
if(null!=storage) {
- storage.setX(0);
- storage.setY(0);
+ storage.set(0, 0);
return storage;
}
return new Point(0,0);
}
-
- protected Point getLocationOnScreenImpl(int x, int y) {
+
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
return new Point(x,y);
}
-
- protected void updateInsetsImpl(Insets insets) {
- // nop ..
+
+ @Override
+ protected void updateInsetsImpl(final Insets insets) {
+ // nop ..
}
}
diff --git a/src/newt/classes/jogamp/newt/PointerIconImpl.java b/src/newt/classes/jogamp/newt/PointerIconImpl.java
new file mode 100644
index 000000000..546a463de
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/PointerIconImpl.java
@@ -0,0 +1,171 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.newt;
+
+import java.nio.ByteBuffer;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PointImmutable;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Display.PointerIcon;
+
+public class PointerIconImpl implements PointerIcon {
+ private final DisplayImpl display;
+ private final PixelFormat pixelformat;
+ private final DimensionImmutable size;
+ private final ByteBuffer pixels;
+ private final PointImmutable hotspot;
+ private long handle;
+ private int hashCode = 0;
+ private volatile boolean hashCodeComputed = false;
+
+ public PointerIconImpl(final DisplayImpl display, final PixelFormat pixelformat, final DimensionImmutable size, final ByteBuffer pixels, final PointImmutable hotspot, final long handle) {
+ this.display = display;
+ this.pixelformat = pixelformat;
+ this.size = size;
+ this.pixels = pixels;
+ this.hotspot = hotspot;
+
+ this.handle=handle;
+ }
+ public PointerIconImpl(final DisplayImpl display, final PixelRectangle pixelrect, final PointImmutable hotspot, final long handle) {
+ this.display = display;
+ this.pixelformat = pixelrect.getPixelformat();
+ this.size = pixelrect.getSize();
+ this.pixels = pixelrect.getPixels();
+ this.hotspot = hotspot;
+ this.handle=handle;
+ }
+
+ @Override
+ public int hashCode() {
+ if( !hashCodeComputed ) { // DBL CHECKED OK VOLATILE
+ synchronized (this) {
+ if( !hashCodeComputed ) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + display.getFQName().hashCode();
+ hash = ((hash << 5) - hash) + pixelformat.hashCode();
+ hash = ((hash << 5) - hash) + size.hashCode();
+ hash = ((hash << 5) - hash) + getStride();
+ hash = ((hash << 5) - hash) + ( isGLOriented() ? 1 : 0);
+ hash = ((hash << 5) - hash) + pixels.hashCode();
+ hashCode = ((hash << 5) - hash) + hotspot.hashCode();
+ }
+ }
+ }
+ return hashCode;
+ }
+
+ public synchronized final long getHandle() { return handle; }
+ public synchronized final long validatedHandle() {
+ synchronized(display.pointerIconList) {
+ if( !display.pointerIconList.contains(this) ) {
+ display.pointerIconList.add(this);
+ }
+ }
+ if( 0 == handle ) {
+ try {
+ handle = display.createPointerIconImpl(pixelformat, size.getWidth(), size.getHeight(), pixels, hotspot.getX(), hotspot.getY());
+ return handle;
+ } catch (final Exception e) {
+ e.printStackTrace();
+ return 0;
+ }
+ } else {
+ return handle;
+ }
+ }
+ @Override
+ public final Display getDisplay() { return display; }
+ @Override
+ public final PixelFormat getPixelformat() { return pixelformat; }
+ @Override
+ public final ByteBuffer getPixels() { return pixels; }
+ @Override
+ public synchronized final boolean isValid() { return 0 != handle; }
+ @Override
+ public synchronized final boolean validate() {
+ if( 0 == handle ) {
+ return 0 != validatedHandle();
+ }
+ return true;
+ }
+
+ @Override
+ public synchronized void destroy() {
+ if(Display.DEBUG) {
+ System.err.println("PointerIcon.destroy: "+this+", "+display+", "+Display.getThreadName());
+ }
+ if( 0 != handle ) {
+ synchronized(display.pointerIconList) {
+ display.pointerIconList.remove(this);
+ }
+ display.runOnEDTIfAvail(false, new Runnable() {
+ public void run() {
+ if( !display.isNativeValidAsync() ) {
+ destroyOnEDT(display.getHandle());
+ }
+ } } );
+ }
+ }
+
+ /** No checks, assume execution on EDT */
+ synchronized void destroyOnEDT(final long dpy) {
+ final long h = handle;
+ handle = 0;
+ try {
+ display.destroyPointerIconImpl(dpy, h);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public final DimensionImmutable getSize() {
+ return size;
+ }
+ @Override
+ public final int getStride() {
+ return size.getWidth() * pixelformat.bytesPerPixel();
+ }
+ @Override
+ public final boolean isGLOriented() {
+ return false;
+ }
+ @Override
+ public final PointImmutable getHotspot() {
+ return hotspot;
+ }
+ @Override
+ public final String toString() {
+ return "PointerIcon[obj 0x"+Integer.toHexString(super.hashCode())+", "+display.getFQName()+", 0x"+Long.toHexString(handle)+", "+pixelformat+", "+size+", "+hotspot+", pixels "+pixels+"]";
+ }
+} \ No newline at end of file
diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java
index e2c0f746f..e73e153ad 100644
--- a/src/newt/classes/jogamp/newt/ScreenImpl.java
+++ b/src/newt/classes/jogamp/newt/ScreenImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,84 +29,84 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.Point;
-import javax.media.nativewindow.util.SurfaceSize;
-
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.common.util.IntIntHashMap;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
-import com.jogamp.newt.util.MonitorMode;
-import com.jogamp.newt.util.ScreenModeUtil;
-
-public abstract class ScreenImpl extends Screen implements ScreenModeListener {
- protected static final boolean DEBUG_TEST_SCREENMODE_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableScreenMode", true);
-
- protected static final int default_sm_bpp = 32;
- protected static final int default_sm_widthmm = 519;
- protected static final int default_sm_heightmm = 324;
- protected static final int default_sm_rate = 60;
- protected static final int default_sm_rotation = 0;
-
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
+import com.jogamp.newt.util.MonitorModeUtil;
+
+public abstract class ScreenImpl extends Screen implements MonitorModeListener {
+ protected static final boolean DEBUG_TEST_SCREENMODE_DISABLED;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_TEST_SCREENMODE_DISABLED = PropertyAccess.isPropertyDefined("newt.test.Screen.disableScreenMode", true);
+ }
+
+ public static final int default_sm_bpp = 32;
+ public static final int default_sm_widthmm = 519;
+ public static final int default_sm_heightmm = 324;
+ public static final int default_sm_rate = 60;
+ public static final int default_sm_rotation = 0;
+
+ static {
+ DisplayImpl.initSingleton();
+ }
+
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
+
protected DisplayImpl display;
protected int screen_idx;
protected String fqname;
protected int hashCode;
protected AbstractGraphicsScreen aScreen;
protected int refCount; // number of Screen references by Window
- protected Point vOrigin = new Point(0, 0); // virtual top-left origin
- protected Dimension vSize = new Dimension(0, 0); // virtual rotated screen size
+ protected Rectangle virtViewportPU = new Rectangle(0, 0, 0, 0); // virtual rotated viewport in pixel units
+ protected Rectangle virtViewportWU = new Rectangle(0, 0, 0, 0); // virtual rotated viewport in window units
protected static Dimension usrSize = null; // property values: newt.ws.swidth and newt.ws.sheight
protected static volatile boolean usrSizeQueried = false;
- private ArrayList<ScreenModeListener> referencedScreenModeListener = new ArrayList<ScreenModeListener>();
+ private final ArrayList<MonitorModeListener> refMonitorModeListener = new ArrayList<MonitorModeListener>();
+
private long tCreated; // creationTime
- static {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- registerShutdownHook();
- return null;
- }
- });
- }
-
- private static Class<?> getScreenClass(String type) throws ClassNotFoundException
+ private static Class<?> getScreenClass(final String type) throws ClassNotFoundException
{
final Class<?> screenClass = NewtFactory.getCustomClass(type, "ScreenDriver");
if(null==screenClass) {
- throw new ClassNotFoundException("Failed to find NEWT Screen Class <"+type+".ScreenDriver>");
+ throw new ClassNotFoundException("Failed to find NEWT Screen Class <"+type+".ScreenDriver>");
}
return screenClass;
}
- public static Screen create(Display display, int idx) {
+ public static Screen create(final Display display, int idx) {
try {
if(!usrSizeQueried) {
synchronized (Screen.class) {
if(!usrSizeQueried) {
usrSizeQueried = true;
- final int w = Debug.getIntProperty("newt.ws.swidth", true, 0);
- final int h = Debug.getIntProperty("newt.ws.sheight", true, 0);
+ final int w = PropertyAccess.getIntProperty("newt.ws.swidth", true, 0);
+ final int h = PropertyAccess.getIntProperty("newt.ws.sheight", true, 0);
if(w>0 && h>0) {
usrSize = new Dimension(w, h);
System.err.println("User screen size "+usrSize);
@@ -115,12 +115,12 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
}
}
synchronized(screenList) {
- Class<?> screenClass = getScreenClass(display.getType());
+ final Class<?> screenClass = getScreenClass(display.getType());
ScreenImpl screen = (ScreenImpl) screenClass.newInstance();
screen.display = (DisplayImpl) display;
idx = screen.validateScreenIndex(idx);
{
- Screen screen0 = ScreenImpl.getLastScreenOf(display, idx, -1);
+ final Screen screen0 = Screen.getLastScreenOf(display, idx, -1);
if(null != screen0) {
if(DEBUG) {
System.err.println("Screen.create() REUSE: "+screen0+" "+Display.getThreadName());
@@ -130,21 +130,30 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
}
}
screen.screen_idx = idx;
- screen.fqname = (display.getFQName()+idx).intern();
+ screen.fqname = display.getFQName()+"-s"+idx;
screen.hashCode = screen.fqname.hashCode();
- screenList.add(screen);
+ screen.instantiationFinished();
+ Screen.addScreen2List(screen);
if(DEBUG) {
System.err.println("Screen.create() NEW: "+screen+" "+Display.getThreadName());
}
return screen;
- }
- } catch (Exception e) {
+ }
+ } catch (final Exception e) {
throw new RuntimeException(e);
}
}
+ /**
+ * Notifies the driver impl. that the instantiation is finished,
+ * ie. instance created and all fields set.
+ */
+ protected void instantiationFinished() {
+ // nop
+ }
+
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
@@ -161,52 +170,54 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
return true;
}
+ @Override
public int hashCode() {
return hashCode;
}
+ @Override
public synchronized final void createNative()
throws NativeWindowException
- {
+ {
if(null == aScreen) {
if(DEBUG) {
tCreated = System.nanoTime();
- System.err.println("Screen.createNative() START ("+DisplayImpl.getThreadName()+", "+this+")");
+ System.err.println("Screen.createNative() START ("+Display.getThreadName()+", "+this+")");
} else {
tCreated = 0;
}
-
display.addReference();
-
+
createNativeImpl();
if(null == aScreen) {
throw new NativeWindowException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen");
}
-
- initScreenModeStatus();
- updateVirtualScreenOriginAndSize();
- if(DEBUG) {
- System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+"), total "+ (System.nanoTime()-tCreated)/1e6 +"ms");
- }
+
+ initMonitorState();
synchronized(screenList) {
screensActive++;
+ if(DEBUG) {
+ System.err.println("Screen.createNative() END ("+Display.getThreadName()+", "+this+"), active "+screensActive+", total "+ (System.nanoTime()-tCreated)/1e6 +"ms");
+ }
}
+ ScreenMonitorState.getScreenMonitorState(this.getFQName()).addListener(this);
}
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- sms.addListener(this);
}
+ @Override
public synchronized final void destroy() {
- releaseScreenModeStatus();
-
synchronized(screenList) {
- screenList.remove(this);
if(0 < screensActive) {
screensActive--;
}
+ if(DEBUG) {
+ System.err.println("Screen.destroy() ("+Display.getThreadName()+"): active "+screensActive);
+ // Thread.dumpStack();
+ }
}
if ( null != aScreen ) {
+ releaseMonitorState();
closeNativeImpl();
aScreen = null;
}
@@ -214,23 +225,24 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
display.removeReference();
}
+ @Override
public synchronized final int addReference() throws NativeWindowException {
if(DEBUG) {
- System.err.println("Screen.addReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount+1));
+ System.err.println("Screen.addReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount+1));
// Thread.dumpStack();
}
if ( 0 == refCount ) {
createNative();
- }
- if(null == aScreen) {
+ } else if(null == aScreen) {
throw new NativeWindowException("Screen.addReference() (refCount "+refCount+") null AbstractGraphicsScreen");
}
return ++refCount;
}
+ @Override
public synchronized final int removeReference() {
if(DEBUG) {
- System.err.println("Screen.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1));
+ System.err.println("Screen.removeReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount-1));
// Thread.dumpStack();
}
refCount--; // could become < 0, in case of manual destruction without actual creation/addReference
@@ -241,13 +253,14 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
return refCount;
}
+ @Override
public synchronized final int getReferenceCount() {
return refCount;
}
protected abstract void createNativeImpl();
protected abstract void closeNativeImpl();
-
+
/**
* Returns the validated screen index, which is either the passed <code>idx</code>
* value or <code>0</code>.
@@ -256,421 +269,433 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
* </p>
*/
protected abstract int validateScreenIndex(int idx);
-
+
/**
- * Stores the virtual origin and virtual <b>rotated</b> screen size.
+ * Calculates the virtual rotated viewport in pixel- and window units.
* <p>
- * This method is called after the ScreenMode has been set,
+ * This method is called after the MonitorMode has been set or changed,
* hence you may utilize it.
- * </p>
- * @param virtualOrigin the store for the virtual origin
- * @param virtualSize the store for the virtual rotated size
+ * </p>
+ * <p>
+ * Default implementation uses the union of all monitor's viewport,
+ * calculated via {@link #unionOfMonitorViewportSize()}, however driver impl. may chose a different methodology.
+ * </p>
+ * @param viewport storage for result in pixel units
+ * @param viewportInWindowUnits storage for result in window units
*/
- protected abstract void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize);
-
+ protected void calcVirtualScreenOriginAndSize(final Rectangle viewport, final Rectangle viewportInWindowUnits) {
+ unionOfMonitorViewports(viewport, viewportInWindowUnits);
+ }
+
+ @Override
public final String getFQName() {
return fqname;
}
/**
- * Updates the <b>rotated</b> virtual ScreenSize using the native impl.
+ * Updates the <b>rotated</b> virtual viewport, may use native impl.
*/
protected void updateVirtualScreenOriginAndSize() {
- getVirtualScreenOriginAndSize(vOrigin, vSize);
- if(DEBUG) {
- System.err.println("Detected screen origin "+vOrigin+", size "+vSize);
+ if(null != usrSize ) {
+ virtViewportPU.set(0, 0, usrSize.getWidth(), usrSize.getHeight());
+ virtViewportWU.set(0, 0, usrSize.getWidth(), usrSize.getHeight());
+ if(DEBUG) {
+ System.err.println("Update user virtual screen viewport @ "+Thread.currentThread().getName()+": "+virtViewportPU);
+ }
+ } else {
+ calcVirtualScreenOriginAndSize(virtViewportPU, virtViewportWU);
+ if(DEBUG) {
+ System.err.println("Updated virtual screen viewport @ "+Thread.currentThread().getName()+": "+virtViewportPU+" [pixel], "+virtViewportWU+" [window]");
+ }
}
}
+ @Override
public final Display getDisplay() {
return display;
}
+ @Override
public final int getIndex() {
return screen_idx;
}
+ @Override
public final AbstractGraphicsScreen getGraphicsScreen() {
return aScreen;
}
+ @Override
public synchronized final boolean isNativeValid() {
return null != aScreen;
}
- public int getX() { return vOrigin.getX(); }
- public int getY() { return vOrigin.getY(); }
-
- public final int getWidth() {
- return (null != usrSize) ? usrSize.getWidth() : vSize.getWidth();
- }
-
- public final int getHeight() {
- return (null != usrSize) ? usrSize.getHeight() : vSize.getHeight();
- }
+ @Override
+ public final int getX() { return virtViewportPU.getX(); }
+ @Override
+ public final int getY() { return virtViewportPU.getY(); }
+ @Override
+ public final int getWidth() { return virtViewportPU.getWidth(); }
+ @Override
+ public final int getHeight() { return virtViewportPU.getHeight(); }
+ @Override
+ public final RectangleImmutable getViewport() { return virtViewportPU; }
+ @Override
+ public final RectangleImmutable getViewportInWindowUnits() { return virtViewportWU; }
@Override
public String toString() {
- return "NEWT-Screen["+getFQName()+", idx "+screen_idx+", refCount "+refCount+", "+getWidth()+"x"+getHeight()+", "+aScreen+", "+display+"]";
+ return "NEWT-Screen["+getFQName()+", idx "+screen_idx+", refCount "+refCount+", vsize "+virtViewportPU+" [pixels], "+virtViewportWU+" [window], "+aScreen+", "+display+
+ ", monitors: "+getMonitorDevices()+"]";
}
- public final List<ScreenMode> getScreenModes() {
- ArrayHashSet<ScreenMode> screenModes = getScreenModesOrig();
- if(null != screenModes && 0 < screenModes.size()) {
- return screenModes.toArrayList();
- }
- return null;
+ //
+ // MonitorDevice and MonitorMode
+ //
+
+ /**
+ * To be implemented by the native specification.<br>
+ * Is called within a thread safe environment.<br>
+ * Is called only to collect the {@link MonitorMode}s and {@link MonitorDevice}s, usually at startup setting up modes.<br>
+ * <br>
+ * <b>WARNING</b>: must be synchronized with
+ * <ul>
+ * <li>{@link MonitorModeProps#NUM_SCREEN_MODE_PROPERTIES} and </li>
+ * <li>{@link MonitorModeProps#MIN_MONITOR_DEVICE_PROPERTIES}</li>
+ * </ul>, i.e.
+ * <ul>
+ * <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, int[], int)}</li>
+ * <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, ArrayHashSet, int[], int)}</li>
+ * <li>{@link MonitorModeProps#streamInMonitorMode(int[], jogamp.newt.MonitorModeProps.Cache, int[], int)}</li>
+ * </ul>
+ * @param cache memory pool caching the result
+ */
+ protected abstract void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache);
+
+ protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor,
+ final Rectangle viewportPU, final Rectangle viewportWU) {
+ return false;
}
- public ScreenMode getOriginalScreenMode() {
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- return ( null != sms ) ? sms.getOriginalScreenMode() : null ;
+ /**
+ * To be implemented by the native specification.<br>
+ * Is called within a thread safe environment.<br>
+ * <p>
+ * Implementation shall not unify the result w/ monitor's supported modes or a locally
+ * saved {@link MonitorModeProps.Cache}, since caller will perform such tasks.
+ * </p>
+ */
+ protected abstract MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor);
+
+ /**
+ * To be implemented by the native specification.<br>
+ * Is called within a thread safe environment.<br>
+ */
+ protected abstract boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode);
+
+ @Override
+ public final List<MonitorMode> getMonitorModes() {
+ final ScreenMonitorState sms = getScreenMonitorStatus(false);
+ return null != sms ? sms.getMonitorModes().getData() : null;
}
- public ScreenMode getCurrentScreenMode() {
- ScreenMode smU = null;
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- if(null == sms) {
- throw new InternalError("ScreenModeStatus.getScreenModeStatus("+this.getFQName()+") == null");
- }
- ScreenMode sm0 = getCurrentScreenModeIntern();
- if(null == sm0) {
- throw new InternalError("getCurrentScreenModeImpl() == null");
- }
- sms.lock();
- try {
- smU = sms.getScreenModes().getOrAdd(sm0); // unified instance, maybe new
+ @Override
+ public final List<MonitorDevice> getMonitorDevices() {
+ final ScreenMonitorState sms = getScreenMonitorStatus(false);
+ return null != sms ? sms.getMonitorDevices().getData() : null;
+ }
- // if mode has changed somehow, update it ..
- if( sms.getCurrentScreenMode().hashCode() != smU.hashCode() ) {
- sms.fireScreenModeChanged(smU, true);
- }
- } finally {
- sms.unlock();
+ final ScreenMonitorState getScreenMonitorStatus(final boolean throwException) {
+ final String key = this.getFQName();
+ final ScreenMonitorState res = ScreenMonitorState.getScreenMonitorState(key);
+ if(null == res & throwException) {
+ throw new InternalError("ScreenMonitorStatus.getMonitorModeStatus("+key+") == null");
}
- return smU;
+ return res;
}
- public boolean setCurrentScreenMode(ScreenMode screenMode) {
- final ScreenMode smC = getCurrentScreenMode();
- ScreenMode smU = getScreenModesOrig().get(screenMode); // unify via value hash
- if(smU.equals(smC)) {
- if(DEBUG) {
- System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tCreated)+"): 0.0 is-current (skip) "+smU+" == "+smC);
- }
- return true;
- }
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- if(null == sms) {
- throw new InternalError("ScreenModeStatus.getScreenModeStatus("+this.getFQName()+") == null");
+ @Override
+ public void monitorModeChangeNotify(final MonitorEvent me) {
+ if(DEBUG) {
+ System.err.println("monitorModeChangeNotify @ "+Thread.currentThread().getName()+": "+me);
}
- boolean success;
- sms.lock();
- try {
- final long tStart;
- if(DEBUG) {
- tStart = System.nanoTime();
- } else {
- tStart = 0;
- }
-
- sms.fireScreenModeChangeNotify(smU);
- if(DEBUG) {
- System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): fireScreenModeChangeNotify() "+smU);
- }
-
- success = setCurrentScreenModeImpl(smU);
- if(DEBUG) {
- System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentScreenModeImpl() "+smU+", success: "+success);
- }
-
- sms.fireScreenModeChanged(smU, success);
- if(DEBUG) {
- System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): X.X "+smU+", success: "+success);
- }
- } finally {
- sms.unlock();
+ for(int i=0; i<refMonitorModeListener.size(); i++) {
+ refMonitorModeListener.get(i).monitorModeChangeNotify(me);
}
- return success;
}
- public void screenModeChangeNotify(ScreenMode sm) {
- for(int i=0; i<referencedScreenModeListener.size(); i++) {
- ((ScreenModeListener)referencedScreenModeListener.get(i)).screenModeChangeNotify(sm);
+ private void updateNativeMonitorDevicesViewport() {
+ final List<MonitorDevice> monitors = getMonitorDevices();
+ for(int i=monitors.size()-1; i>=0; i--) {
+ final MonitorDeviceImpl monitor = (MonitorDeviceImpl) monitors.get(i);
+ final boolean viewportUpdated = updateNativeMonitorDeviceViewportImpl(monitor, monitor.getMutuableViewportPU(), monitor.getMutuableViewportWU());
+ if( DEBUG ) {
+ System.err.println("Screen.updateMonitorViewport["+i+"] @ "+Thread.currentThread().getName()+": updated: "+viewportUpdated+", PU "+monitor.getViewport()+", WU "+monitor.getViewportInWindowUnits());
+ }
}
}
- public void screenModeChanged(ScreenMode sm, boolean success) {
+ @Override
+ public void monitorModeChanged(final MonitorEvent me, final boolean success) {
if(success) {
+ updateNativeMonitorDevicesViewport();
updateVirtualScreenOriginAndSize();
}
- for(int i=0; i<referencedScreenModeListener.size(); i++) {
- ((ScreenModeListener)referencedScreenModeListener.get(i)).screenModeChanged(sm, success);
+ if(DEBUG) {
+ System.err.println("monitorModeChangeNotify @ "+Thread.currentThread().getName()+": success "+success+", "+me);
}
- }
-
- public synchronized final void addScreenModeListener(ScreenModeListener sml) {
- referencedScreenModeListener.add(sml);
- }
-
- public synchronized final void removeScreenModeListener(ScreenModeListener sml) {
- referencedScreenModeListener.remove(sml);
- }
-
- /** ScreenModeStatus bridge to native implementation */
- protected final ArrayHashSet<ScreenMode> getScreenModesOrig() {
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- if(null!=sms) {
- return sms.getScreenModes();
+ for(int i=0; i<refMonitorModeListener.size(); i++) {
+ refMonitorModeListener.get(i).monitorModeChanged(me, success);
}
- return null;
}
- /** ScreenModeStatus bridge to native implementation */
- protected final IntIntHashMap getScreenModesIdx2NativeIdx() {
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- if(null!=sms) {
- return sms.getScreenModesIdx2NativeIdx();
- }
- return null;
+ @Override
+ public synchronized final void addMonitorModeListener(final MonitorModeListener sml) {
+ refMonitorModeListener.add(sml);
}
- /**
- * To be implemented by the native specification.<br>
- * Is called within a thread safe environment.<br>
- * Is called only to collect the ScreenModes, usually at startup setting up modes.<br>
- * <br>
- * <b>WARNING</b>: must be synchronized with {@link com.jogamp.newt.util.ScreenModeUtil#NUM_SCREEN_MODE_PROPERTIES},
- * ie {@link com.jogamp.newt.util.ScreenModeUtil#streamIn(com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, int[], int)}<br>
- * <br>
- * <b>Note</b>: Additional 1st element is native mode id.
- */
- protected int[] getScreenModeFirstImpl() {
- return null;
+ @Override
+ public synchronized final void removeMonitorModeListener(final MonitorModeListener sml) {
+ refMonitorModeListener.remove(sml);
}
/**
- * To be implemented by the native specification.<br>
- * Is called within a thread safe environment.<br>
- * Is called only to collect the ScreenModes, usually at startup setting up modes.<br>
- * <br>
- * <b>WARNING</b>: must be synchronized with {@link com.jogamp.newt.util.ScreenModeUtil#NUM_SCREEN_MODE_PROPERTIES},
- * ie {@link com.jogamp.newt.util.ScreenModeUtil#streamIn(com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, int[], int)}<br>
- * <br>
- * <b>Note</b>: Additional 1st element is native mode id.
+ *
+ * @param cache optional ..
+ * @param modeId
+ * @return
*/
- protected int[] getScreenModeNextImpl() {
- return null;
+ private final MonitorMode getVirtualMonitorMode(final MonitorModeProps.Cache cache, final int modeId) {
+ final int[] props = new int[MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = getWidth(); // width
+ props[i++] = getHeight(); // height
+ props[i++] = default_sm_bpp;
+ props[i++] = default_sm_rate * 100;
+ props[i++] = 0; // flags
+ props[i++] = modeId;
+ props[i++] = default_sm_rotation;
+ if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) {
+ throw new InternalError("XX");
+ }
+ return MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
}
/**
- * To be implemented by the native specification.<br>
- * Is called within a thread safe environment.<br>
+ *
+ * @param cache mandatory !
+ * @param monitorId
+ * @param currentMode
+ * @return
*/
- protected ScreenMode getCurrentScreenModeImpl() {
- return null;
+ private final MonitorDevice getVirtualMonitorDevice(final MonitorModeProps.Cache cache, final int monitorId, final MonitorMode currentMode) {
+ final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES];
+ int i = 0;
+ props[i++] = MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES;
+ props[i++] = monitorId;
+ props[i++] = default_sm_widthmm;
+ props[i++] = default_sm_heightmm;
+ props[i++] = 0; // rotated viewport x pixel-units
+ props[i++] = 0; // rotated viewport y pixel-units
+ props[i++] = currentMode.getRotatedWidth(); // rotated viewport width pixel-units
+ props[i++] = currentMode.getRotatedHeight(); // rotated viewport height pixel-units
+ props[i++] = 0; // rotated viewport x window-units
+ props[i++] = 0; // rotated viewport y window-units
+ props[i++] = currentMode.getRotatedWidth(); // rotated viewport width window-units
+ props[i++] = currentMode.getRotatedHeight(); // rotated viewport height window-units
+ props[i++] = currentMode.getId(); // current mode id
+ props[i++] = currentMode.getRotation();
+ props[i++] = currentMode.getId(); // supported mode id #1
+ if( MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES != i ) {
+ throw new InternalError("XX");
+ }
+ return MonitorModeProps.streamInMonitorDevice(null, cache, this, props, 0);
}
-
+
/**
- * Utilizes {@link #getCurrentScreenModeImpl()}, if the latter returns null it uses
+ * Utilizes {@link #getCurrentMonitorModeImpl()}, if the latter returns null it uses
* the current screen size and dummy values.
*/
- protected ScreenMode getCurrentScreenModeIntern() {
- ScreenMode res;
+ protected final MonitorMode queryCurrentMonitorModeIntern(final MonitorDevice monitor) {
+ MonitorMode res;
if(DEBUG_TEST_SCREENMODE_DISABLED) {
res = null;
} else {
- res = getCurrentScreenModeImpl();
+ res = queryCurrentMonitorModeImpl(monitor);
}
if(null == res) {
- if( 0==getWidth()*getHeight() ) {
+ if( 0>=getWidth() || 0>=getHeight() ) {
updateVirtualScreenOriginAndSize();
}
- int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
- int i = 0;
- props[i++] = 0; // set later for verification of iterator
- props[i++] = getWidth(); // width
- props[i++] = getHeight(); // height
- props[i++] = default_sm_bpp;
- props[i++] = default_sm_widthmm;
- props[i++] = default_sm_heightmm;
- props[i++] = default_sm_rate;
- props[i++] = default_sm_rotation;
- props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count
- res = ScreenModeUtil.streamIn(props, 0);
+ res = getVirtualMonitorMode(null, monitor.getCurrentMode().getId());
}
return res;
}
- /**
- * To be implemented by the native specification.<br>
- * Is called within a thread safe environment.<br>
- */
- protected boolean setCurrentScreenModeImpl(ScreenMode screenMode) {
- return false;
- }
-
- private ScreenModeStatus initScreenModeStatus() {
+ private final ScreenMonitorState initMonitorState() {
long t0;
if(DEBUG) {
t0 = System.nanoTime();
- System.err.println("Screen.initScreenModeStatus() START ("+DisplayImpl.getThreadName()+", "+this+")");
+ System.err.println("Screen.initMonitorState() START ("+Display.getThreadName()+", "+this+")");
} else {
t0 = 0;
}
- ScreenModeStatus sms;
- ScreenModeStatus.lockScreenModeStatus();
+ boolean vScrnSizeUpdated = false;
+ ScreenMonitorState sms;
+ ScreenMonitorState.lockScreenMonitorState();
try {
- sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- if(null==sms) {
- IntIntHashMap screenModesIdx2NativeIdx = new IntIntHashMap();
- final ScreenMode currentSM = getCurrentScreenModeIntern();
- if(null == currentSM) {
- throw new InternalError("getCurrentScreenModeImpl() == null");
+ sms = ScreenMonitorState.getScreenMonitorState(this.getFQName());
+ if(null==sms) {
+ final MonitorModeProps.Cache cache = new MonitorModeProps.Cache();
+ if( 0 >= collectNativeMonitorModes(cache) ) {
+ updateVirtualScreenOriginAndSize();
+ vScrnSizeUpdated = true;
+ final MonitorMode mode = getVirtualMonitorMode(cache, 0);
+ cache.monitorModes.getOrAdd(mode);
+ final MonitorDevice monitor = getVirtualMonitorDevice(cache, 0, mode);
+ cache.monitorDevices.getOrAdd(monitor);
+ }
+ // Sort MonitorModes (all and per device) in descending order - default!
+ MonitorModeUtil.sort(cache.monitorModes.getData(), false ); // descending order
+ for(final Iterator<MonitorDevice> iMonitor=cache.monitorDevices.iterator(); iMonitor.hasNext(); ) {
+ MonitorModeUtil.sort(iMonitor.next().getSupportedModes(), false ); // descending order
}
-
- ArrayHashSet<ScreenMode> screenModes = collectNativeScreenModes(screenModesIdx2NativeIdx);
- screenModes.getOrAdd(currentSM);
if(DEBUG) {
int i=0;
- for(Iterator<ScreenMode> iter=screenModes.iterator(); iter.hasNext(); i++) {
- System.err.println(i+": "+iter.next());
+ for(final Iterator<MonitorMode> iMode=cache.monitorModes.iterator(); iMode.hasNext(); i++) {
+ System.err.println("All["+i+"]: "+iMode.next());
+ }
+ i=0;
+ for(final Iterator<MonitorDevice> iMonitor=cache.monitorDevices.iterator(); iMonitor.hasNext(); i++) {
+ final MonitorDevice crt = iMonitor.next();
+ System.err.println("["+i+"]: "+crt);
+ int j=0;
+ for(final Iterator<MonitorMode> iMode=crt.getSupportedModes().iterator(); iMode.hasNext(); j++) {
+ System.err.println("["+i+"]["+j+"]: "+iMode.next());
+ }
}
}
-
- sms = new ScreenModeStatus(screenModes, screenModesIdx2NativeIdx);
- ScreenMode originalScreenMode0 = screenModes.get(currentSM); // unify via value hash
- if(null == originalScreenMode0) {
- throw new RuntimeException(currentSM+" could not be hashed from ScreenMode list");
- }
- sms.setOriginalScreenMode(originalScreenMode0);
- ScreenModeStatus.mapScreenModeStatus(this.getFQName(), sms);
+ sms = new ScreenMonitorState(cache.monitorDevices, cache.monitorModes);
+ ScreenMonitorState.mapScreenMonitorState(this.getFQName(), sms);
}
} finally {
- ScreenModeStatus.unlockScreenModeStatus();
+ ScreenMonitorState.unlockScreenMonitorState();
}
if(DEBUG) {
- System.err.println("Screen.initScreenModeStatus() END dt "+ (System.nanoTime()-t0)/1e6 +"ms");
+ System.err.println("Screen.initMonitorState() END dt "+ (System.nanoTime()-t0)/1e6 +"ms");
}
+ if( !vScrnSizeUpdated ) {
+ updateVirtualScreenOriginAndSize();
+ }
+
return sms;
}
- /** ignores bpp < 15 */
- private ArrayHashSet<ScreenMode> collectNativeScreenModes(IntIntHashMap screenModesIdx2NativeId) {
- ArrayHashSet<DimensionImmutable> resolutionPool = new ArrayHashSet<DimensionImmutable>();
- ArrayHashSet<SurfaceSize> surfaceSizePool = new ArrayHashSet<SurfaceSize>();
- ArrayHashSet<DimensionImmutable> screenSizeMMPool = new ArrayHashSet<DimensionImmutable>();
- ArrayHashSet<MonitorMode> monitorModePool = new ArrayHashSet<MonitorMode>();
- ArrayHashSet<ScreenMode> screenModePool = new ArrayHashSet<ScreenMode>();
-
- int[] smProps = null;
- int num = 0;
- final int idxBpp = 1 // native mode
- + 1 // count
- + ScreenModeUtil.NUM_RESOLUTION_PROPERTIES
- + ScreenModeUtil.NUM_SURFACE_SIZE_PROPERTIES
- - 1 ; // index 0 based
- do {
- if(DEBUG_TEST_SCREENMODE_DISABLED) {
- smProps = null;
- } else if(0 == num) {
- smProps = getScreenModeFirstImpl();
- } else {
- smProps = getScreenModeNextImpl();
- }
- if(null != smProps && 0 < smProps.length && smProps[idxBpp] >= 15) {
- int nativeId = smProps[0];
- int screenModeIdx = ScreenModeUtil.streamIn(resolutionPool, surfaceSizePool, screenSizeMMPool,
- monitorModePool, screenModePool, smProps, 1);
- if(DEBUG) {
- System.err.println("ScreenImpl.collectNativeScreenModes: #"+num+": idx: "+nativeId+" native -> "+screenModeIdx+" newt");
+ /**
+ * Returns the number of successful collected {@link MonitorDevice}s.
+ * <p>
+ * Collects {@link MonitorDevice}s and {@link MonitorMode}s within the given cache.
+ * </p>
+ */
+ private final int collectNativeMonitorModes(final MonitorModeProps.Cache cache) {
+ if(!DEBUG_TEST_SCREENMODE_DISABLED) {
+ collectNativeMonitorModesAndDevicesImpl(cache);
+ }
+ // filter out insufficient modes
+ for(int i=cache.monitorModes.size()-1; i>=0; i--) {
+ final MonitorMode mode = cache.monitorModes.get(i);
+ if( 16 > mode.getSurfaceSize().getBitsPerPixel() ) {
+ boolean keep = false;
+ for(int j=cache.monitorDevices.size()-1; !keep && j>=0; j--) {
+ final MonitorDevice monitor = cache.monitorDevices.get(j);
+ keep = monitor.getCurrentMode().equals(mode);
}
-
- if(screenModeIdx >= 0) {
- screenModesIdx2NativeId.put(screenModeIdx, nativeId);
+ if(!keep) {
+ cache.monitorModes.remove(i);
+ for(int j=cache.monitorDevices.size()-1; j>=0; j--) {
+ final MonitorDeviceImpl monitor = (MonitorDeviceImpl) cache.monitorDevices.get(j);
+ monitor.getSupportedModesImpl().remove(mode);
+ }
}
- } else if(DEBUG) {
- System.err.println("ScreenImpl.collectNativeScreenModes: #"+num+": smProps: "+(null!=smProps)+
- ", len: "+(null != smProps ? smProps.length : 0)+
- ", bpp: "+(null != smProps && 0 < smProps.length ? smProps[idxBpp] : 0)+
- " - DROPPING");
}
- num++;
- } while ( null != smProps && 0 < smProps.length );
-
- if(DEBUG) {
- System.err.println("ScreenImpl.collectNativeScreenModes: ScreenMode number : "+screenModePool.size());
- System.err.println("ScreenImpl.collectNativeScreenModes: MonitorMode number : "+monitorModePool.size());
- System.err.println("ScreenImpl.collectNativeScreenModes: ScreenSizeMM number: "+screenSizeMMPool.size());
- System.err.println("ScreenImpl.collectNativeScreenModes: SurfaceSize number : "+surfaceSizePool.size());
- System.err.println("ScreenImpl.collectNativeScreenModes: Resolution number : "+resolutionPool.size());
}
-
- return screenModePool;
+ if( DEBUG ) {
+ System.err.println("ScreenImpl.collectNativeMonitorModes: MonitorDevice number : "+cache.monitorDevices.size());
+ System.err.println("ScreenImpl.collectNativeMonitorModes: MonitorMode number : "+cache.monitorModes.size());
+ System.err.println("ScreenImpl.collectNativeMonitorModes: SizeAndRate number : "+cache.sizeAndRates.size());
+ System.err.println("ScreenImpl.collectNativeMonitorModes: SurfaceSize number : "+cache.surfaceSizes.size());
+ System.err.println("ScreenImpl.collectNativeMonitorModes: Resolution number : "+cache.resolutions.size());
+ }
+ return cache.monitorDevices.size();
}
- private void releaseScreenModeStatus() {
- ScreenModeStatus sms;
- ScreenModeStatus.lockScreenModeStatus();
+ private final void releaseMonitorState() {
+ ScreenMonitorState sms;
+ ScreenMonitorState.lockScreenMonitorState();
try {
- sms = ScreenModeStatus.getScreenModeStatus(getFQName());
+ sms = ScreenMonitorState.getScreenMonitorState(getFQName());
if(null != sms) {
sms.lock();
try {
if(0 == sms.removeListener(this)) {
- if(sms.isOriginalModeChangedByOwner()) {
- System.err.println("Screen.destroy(): "+sms.getCurrentScreenMode()+" -> "+sms.getOriginalScreenMode());
- try {
- setCurrentScreenMode(sms.getOriginalScreenMode());
- } catch (Throwable t) {
- // be verbose but continue
- t.printStackTrace();
+ final ArrayList<MonitorDevice> monitorDevices = sms.getMonitorDevices().getData();
+ for(int i=0; i<monitorDevices.size(); i++) {
+ final MonitorDevice monitor = monitorDevices.get(i);
+ if( monitor.isModeChangedByUs() ) {
+ System.err.println("Screen.destroy(): Reset "+monitor);
+ try {
+ monitor.setCurrentMode(monitor.getOriginalMode());
+ } catch (final Throwable t) {
+ // be verbose but continue
+ t.printStackTrace();
+ }
}
}
- ScreenModeStatus.unmapScreenModeStatus(getFQName());
+ ScreenMonitorState.unmapScreenMonitorState(getFQName());
}
} finally {
sms.unlock();
}
- }
+ }
} finally {
- ScreenModeStatus.unlockScreenModeStatus();
+ ScreenMonitorState.unlockScreenMonitorState();
}
}
-
+
private final void shutdown() {
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatusUnlocked(getFQName());
+ final ScreenMonitorState sms = ScreenMonitorState.getScreenMonitorStateUnlocked(getFQName());
if(null != sms) {
- if(sms.isOriginalModeChangedByOwner()) {
- try {
- System.err.println("Screen.shutdown(): "+sms.getCurrentScreenMode()+" -> "+sms.getOriginalScreenMode());
- setCurrentScreenModeImpl(sms.getOriginalScreenMode());
- } catch (Throwable t) {
- // be quiet .. shutdown
+ final ArrayList<MonitorDevice> monitorDevices = sms.getMonitorDevices().getData();
+ for(int i=0; i<monitorDevices.size(); i++) {
+ final MonitorDevice monitor = monitorDevices.get(i);
+ if( monitor.isModeChangedByUs() ) {
+ System.err.println("Screen.shutdown(): Reset "+monitor);
+ try {
+ monitor.setCurrentMode(monitor.getOriginalMode());
+ } catch (final Throwable t) {
+ // be quiet .. shutdown
+ }
}
}
- ScreenModeStatus.unmapScreenModeStatusUnlocked(getFQName());
- }
- }
- private static final void shutdownAll() {
- for(int i=0; i < screenList.size(); i++) {
- ((ScreenImpl)screenList.get(i)).shutdown();
+ ScreenMonitorState.unmapScreenMonitorStateUnlocked(getFQName());
}
}
-
- private static synchronized void registerShutdownHook() {
- final Thread shutdownHook = new Thread(new Runnable() {
- public void run() {
- ScreenImpl.shutdownAll();
+
+ /** pp */ static final void shutdownAll() {
+ final int sCount = screenList.size();
+ if(DEBUG) {
+ System.err.println("Screen.shutdownAll "+sCount+" instances, on thread "+Display.getThreadName());
+ }
+ for(int i=0; i<sCount && screenList.size()>0; i++) { // be safe ..
+ final ScreenImpl s = (ScreenImpl) screenList.remove(0).get();
+ if(DEBUG) {
+ System.err.println("Screen.shutdownAll["+(i+1)+"/"+sCount+"]: "+s+", GCed "+(null==s));
}
- });
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- Runtime.getRuntime().addShutdownHook(shutdownHook);
- return null;
+ if( null != s ) {
+ s.shutdown();
}
- });
+ }
}
}
-
diff --git a/src/newt/classes/jogamp/newt/ScreenModeStatus.java b/src/newt/classes/jogamp/newt/ScreenModeStatus.java
deleted file mode 100644
index 4075fb131..000000000
--- a/src/newt/classes/jogamp/newt/ScreenModeStatus.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package jogamp.newt;
-
-import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.common.util.IntIntHashMap;
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
-import com.jogamp.newt.Screen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-public class ScreenModeStatus {
- private static boolean DEBUG = Screen.DEBUG;
-
- private RecursiveLock lock = LockFactory.createRecursiveLock();
- private ArrayHashSet<ScreenMode> screenModes;
- private IntIntHashMap screenModesIdx2NativeIdx;
- private ScreenMode currentScreenMode;
- private ScreenMode originalScreenMode;
- private boolean screenModeChangedByOwner;
- private ArrayList<ScreenModeListener> listener = new ArrayList<ScreenModeListener>();
-
- private static HashMap<String, ScreenModeStatus> screenFQN2ScreenModeStatus = new HashMap<String, ScreenModeStatus>();
- private static RecursiveLock screen2ScreenModeStatusLock = LockFactory.createRecursiveLock();
-
- protected static void mapScreenModeStatus(String screenFQN, ScreenModeStatus sms) {
- screen2ScreenModeStatusLock.lock();
- try {
- ScreenModeStatus _sms = screenFQN2ScreenModeStatus.get(screenFQN);
- if( null != _sms ) {
- throw new RuntimeException("ScreenModeStatus "+_sms+" already mapped to "+screenFQN);
- }
- screenFQN2ScreenModeStatus.put(screenFQN, sms);
- if(DEBUG) {
- System.err.println("ScreenModeStatus.map "+screenFQN+" -> "+sms);
- }
- } finally {
- screen2ScreenModeStatusLock.unlock();
- }
- }
-
- /**
- * @param screen the prev user
- * @return true if mapping is empty, ie no more usage of the mapped ScreenModeStatus
- */
- protected static void unmapScreenModeStatus(String screenFQN) {
- screen2ScreenModeStatusLock.lock();
- try {
- unmapScreenModeStatusUnlocked(screenFQN);
- } finally {
- screen2ScreenModeStatusLock.unlock();
- }
- }
- protected static void unmapScreenModeStatusUnlocked(String screenFQN) {
- ScreenModeStatus sms = screenFQN2ScreenModeStatus.remove(screenFQN);
- if(DEBUG) {
- System.err.println("ScreenModeStatus.unmap "+screenFQN+" -> "+sms);
- }
- }
-
- protected static ScreenModeStatus getScreenModeStatus(String screenFQN) {
- screen2ScreenModeStatusLock.lock();
- try {
- return getScreenModeStatusUnlocked(screenFQN);
- } finally {
- screen2ScreenModeStatusLock.unlock();
- }
- }
- protected static ScreenModeStatus getScreenModeStatusUnlocked(String screenFQN) {
- return screenFQN2ScreenModeStatus.get(screenFQN);
- }
-
- protected static void lockScreenModeStatus() {
- screen2ScreenModeStatusLock.lock();
- }
-
- protected static void unlockScreenModeStatus() {
- screen2ScreenModeStatusLock.unlock();
- }
-
- public ScreenModeStatus(ArrayHashSet<ScreenMode> screenModes,
- IntIntHashMap screenModesIdx2NativeIdx) {
- this.screenModes = screenModes;
- this.screenModesIdx2NativeIdx = screenModesIdx2NativeIdx;
- this.screenModeChangedByOwner = false;
- }
-
- protected final void setOriginalScreenMode(ScreenMode originalScreenMode) {
- this.originalScreenMode = originalScreenMode;
- this.currentScreenMode = originalScreenMode;
- }
-
- public final ScreenMode getOriginalScreenMode() {
- return originalScreenMode;
- }
-
- public final ScreenMode getCurrentScreenMode() {
- lock();
- try {
- return currentScreenMode;
- } finally {
- unlock();
- }
- }
-
- /**
- * We cannot guarantee that we won't interfere w/ another running
- * application's screen mode change.
- * <p>
- * At least we only return <code>true</true> if the owner, ie. the Screen,
- * has changed the screen mode and if the original screen mode
- * is not current the current one.
- * </p>
- * @return
- */
- public final boolean isOriginalModeChangedByOwner() {
- lock();
- try {
- return screenModeChangedByOwner && !isCurrentModeOriginalMode();
- } finally {
- unlock();
- }
- }
-
- protected final boolean isCurrentModeOriginalMode() {
- if(null != currentScreenMode && null != originalScreenMode) {
- return currentScreenMode.hashCode() == originalScreenMode.hashCode();
- }
- return true;
- }
-
- protected final ArrayHashSet<ScreenMode> getScreenModes() {
- return screenModes;
- }
-
- protected final IntIntHashMap getScreenModesIdx2NativeIdx() {
- return screenModesIdx2NativeIdx;
- }
-
- protected final int addListener(ScreenModeListener l) {
- lock();
- try {
- listener.add(l);
- if(DEBUG) {
- System.err.println("ScreenModeStatus.addListener (size: "+listener.size()+"): "+l);
- }
- return listener.size();
- } finally {
- unlock();
- }
- }
-
- protected final int removeListener(ScreenModeListener l) {
- lock();
- try {
- if(!listener.remove(l)) {
- throw new RuntimeException("ScreenModeListener "+l+" not contained");
- }
- if(DEBUG) {
- System.err.println("ScreenModeStatus.removeListener (size: "+listener.size()+"): "+l);
- }
- return listener.size();
- } finally {
- unlock();
- }
- }
-
- protected final void fireScreenModeChangeNotify(ScreenMode desiredScreenMode) {
- lock();
- try {
- for(int i=0; i<listener.size(); i++) {
- listener.get(i).screenModeChangeNotify(desiredScreenMode);
- }
- } finally {
- unlock();
- }
- }
-
- protected void fireScreenModeChanged(ScreenMode currentScreenMode, boolean success) {
- lock();
- try {
- if(success) {
- this.currentScreenMode = currentScreenMode;
- this.screenModeChangedByOwner = !isCurrentModeOriginalMode();
- }
- for(int i=0; i<listener.size(); i++) {
- listener.get(i).screenModeChanged(currentScreenMode, success);
- }
- } finally {
- unlock();
- }
- }
-
- protected final void lock() throws RuntimeException {
- lock.lock();
- }
-
- protected final void unlock() throws RuntimeException {
- lock.unlock();
- }
-}
diff --git a/src/newt/classes/jogamp/newt/ScreenMonitorState.java b/src/newt/classes/jogamp/newt/ScreenMonitorState.java
new file mode 100644
index 000000000..ae982414b
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/ScreenMonitorState.java
@@ -0,0 +1,195 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.newt;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class ScreenMonitorState {
+ private static boolean DEBUG = Screen.DEBUG;
+
+ private final RecursiveLock lock = LockFactory.createRecursiveLock();
+ private final ArrayHashSet<MonitorDevice> allMonitors;
+ private final ArrayHashSet<MonitorMode> allMonitorModes;
+ private final ArrayList<MonitorModeListener> listener = new ArrayList<MonitorModeListener>();
+
+ private static HashMap<String, ScreenMonitorState> screenFQN2ScreenMonitorState = new HashMap<String, ScreenMonitorState>();
+ private static RecursiveLock screen2ScreenMonitorState = LockFactory.createRecursiveLock();
+
+ protected static void mapScreenMonitorState(final String screenFQN, final ScreenMonitorState sms) {
+ screen2ScreenMonitorState.lock();
+ try {
+ final ScreenMonitorState _sms = screenFQN2ScreenMonitorState.get(screenFQN);
+ if( null != _sms ) {
+ throw new RuntimeException("ScreenMonitorState "+_sms+" already mapped to "+screenFQN);
+ }
+ screenFQN2ScreenMonitorState.put(screenFQN, sms);
+ if(DEBUG) {
+ System.err.println("ScreenMonitorState.map "+screenFQN+" -> "+sms);
+ }
+ } finally {
+ screen2ScreenMonitorState.unlock();
+ }
+ }
+
+ /**
+ * @param screen the prev user
+ * @return true if mapping is empty, ie no more usage of the mapped ScreenMonitorState
+ */
+ protected static void unmapScreenMonitorState(final String screenFQN) {
+ screen2ScreenMonitorState.lock();
+ try {
+ unmapScreenMonitorStateUnlocked(screenFQN);
+ } finally {
+ screen2ScreenMonitorState.unlock();
+ }
+ }
+ protected static void unmapScreenMonitorStateUnlocked(final String screenFQN) {
+ final ScreenMonitorState sms = screenFQN2ScreenMonitorState.remove(screenFQN);
+ if(DEBUG) {
+ System.err.println("ScreenMonitorState.unmap "+screenFQN+" -> "+sms);
+ }
+ }
+
+ protected static ScreenMonitorState getScreenMonitorState(final String screenFQN) {
+ screen2ScreenMonitorState.lock();
+ try {
+ return getScreenMonitorStateUnlocked(screenFQN);
+ } finally {
+ screen2ScreenMonitorState.unlock();
+ }
+ }
+ protected static ScreenMonitorState getScreenMonitorStateUnlocked(final String screenFQN) {
+ return screenFQN2ScreenMonitorState.get(screenFQN);
+ }
+
+ protected static void lockScreenMonitorState() {
+ screen2ScreenMonitorState.lock();
+ }
+
+ protected static void unlockScreenMonitorState() {
+ screen2ScreenMonitorState.unlock();
+ }
+
+ public ScreenMonitorState(final ArrayHashSet<MonitorDevice> allMonitors,
+ final ArrayHashSet<MonitorMode> allMonitorModes) {
+ this.allMonitors = allMonitors;
+ this.allMonitorModes = allMonitorModes;
+ }
+
+ protected ArrayHashSet<MonitorDevice> getMonitorDevices() {
+ return allMonitors;
+ }
+
+ protected ArrayHashSet<MonitorMode> getMonitorModes() {
+ return allMonitorModes;
+ }
+
+ protected final int addListener(final MonitorModeListener l) {
+ lock();
+ try {
+ listener.add(l);
+ if(DEBUG) {
+ System.err.println("ScreenMonitorState.addListener (size: "+listener.size()+"): "+l);
+ }
+ return listener.size();
+ } finally {
+ unlock();
+ }
+ }
+
+ protected final int removeListener(final MonitorModeListener l) {
+ lock();
+ try {
+ if(!listener.remove(l)) {
+ throw new RuntimeException("MonitorModeListener "+l+" not contained");
+ }
+ if(DEBUG) {
+ System.err.println("ScreenMonitorState.removeListener (size: "+listener.size()+"): "+l);
+ }
+ return listener.size();
+ } finally {
+ unlock();
+ }
+ }
+
+ protected final MonitorDevice getMonitor(final MonitorDevice monitor) {
+ return allMonitors.get(monitor);
+ }
+
+ protected final void validateMonitor(final MonitorDevice monitor) {
+ final MonitorDevice md = allMonitors.get(monitor);
+ if( null == md ) {
+ throw new InternalError("Monitor unknown: "+monitor);
+ }
+ }
+
+ protected final void fireMonitorModeChangeNotify(final MonitorDevice monitor, final MonitorMode desiredMode) {
+ lock();
+ try {
+ validateMonitor(monitor);
+ final MonitorEvent me = new MonitorEvent(MonitorEvent.EVENT_MONITOR_MODE_CHANGE_NOTIFY, monitor, System.currentTimeMillis(), desiredMode);
+ for(int i=0; i<listener.size(); i++) {
+ listener.get(i).monitorModeChangeNotify(me);
+ }
+ } finally {
+ unlock();
+ }
+ }
+
+ protected void fireMonitorModeChanged(final MonitorDevice monitor, final MonitorMode currentMode, final boolean success) {
+ lock();
+ try {
+ validateMonitor(monitor);
+ final MonitorEvent me = new MonitorEvent(MonitorEvent.EVENT_MONITOR_MODE_CHANGED, monitor, System.currentTimeMillis(), currentMode);
+ for(int i=0; i<listener.size(); i++) {
+ listener.get(i).monitorModeChanged(me, success);
+ }
+ } finally {
+ unlock();
+ }
+ }
+
+ protected final void lock() throws RuntimeException {
+ lock.lock();
+ }
+
+ protected final void unlock() throws RuntimeException {
+ lock.unlock();
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index c1ac87d38..b62628962 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,33 +29,15 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt;
-import java.util.ArrayList;
+import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
-
-import com.jogamp.common.util.ReflectionUtil;
-import com.jogamp.newt.NewtFactory;
-import com.jogamp.newt.Display;
-import com.jogamp.newt.Screen;
-import com.jogamp.newt.Window;
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.InputEvent;
-import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.KeyListener;
-import com.jogamp.newt.event.MouseEvent;
-import com.jogamp.newt.event.MouseListener;
-import com.jogamp.newt.event.NEWTEvent;
-import com.jogamp.newt.event.NEWTEventConsumer;
-import com.jogamp.newt.event.ScreenModeListener;
-import com.jogamp.newt.event.WindowEvent;
-import com.jogamp.newt.event.WindowListener;
-import com.jogamp.newt.event.WindowUpdateEvent;
+import java.util.ArrayList;
+import java.util.List;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -65,28 +47,123 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.OffscreenLayerSurface;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.nativewindow.SurfaceUpdatedListener;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.util.DimensionImmutable;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.PixelRectangle;
import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+import jogamp.nativewindow.SurfaceScaleUtils;
import jogamp.nativewindow.SurfaceUpdatedHelper;
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.IntBitfield;
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Display.PointerIcon;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.DoubleTapScrollGesture;
+import com.jogamp.newt.event.GestureHandler;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.KeyListener;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.MouseEvent.PointerType;
+import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.event.NEWTEvent;
+import com.jogamp.newt.event.NEWTEventConsumer;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.event.WindowUpdateEvent;
+
public abstract class WindowImpl implements Window, NEWTEventConsumer
{
- public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE = Debug.isPropertyDefined("newt.test.Window.reparent.incompatible", true);
-
+ public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_TEST_REPARENT_INCOMPATIBLE = PropertyAccess.isPropertyDefined("newt.test.Window.reparent.incompatible", true);
+
+ ScreenImpl.initSingleton();
+ }
+
+ protected static final ArrayList<WeakReference<WindowImpl>> windowList = new ArrayList<WeakReference<WindowImpl>>();
+
+ /** Maybe utilized at a shutdown hook, impl. does not block. */
+ public static final void shutdownAll() {
+ final int wCount = windowList.size();
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.shutdownAll "+wCount+" instances, on thread "+getThreadName());
+ }
+ for(int i=0; i<wCount && windowList.size()>0; i++) { // be safe ..
+ final WindowImpl w = windowList.remove(0).get();
+ if(DEBUG_IMPLEMENTATION) {
+ final long wh = null != w ? w.getWindowHandle() : 0;
+ System.err.println("Window.shutdownAll["+(i+1)+"/"+wCount+"]: "+toHexString(wh)+", GCed "+(null==w));
+ }
+ if( null != w ) {
+ w.shutdown();
+ }
+ }
+ }
+ private static void addWindow2List(final WindowImpl window) {
+ synchronized(windowList) {
+ // GC before add
+ int i=0, gced=0;
+ while( i < windowList.size() ) {
+ if( null == windowList.get(i).get() ) {
+ gced++;
+ windowList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ windowList.add(new WeakReference<WindowImpl>(window));
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.addWindow2List: GCed "+gced+", size "+windowList.size());
+ }
+ }
+ }
+
/** Timeout of queued events (repaint and resize) */
- static final long QUEUED_EVENT_TO = 1200; // ms
-
+ static final long QUEUED_EVENT_TO = 1200; // ms
+
+ private static final PointerType[] constMousePointerTypes = new PointerType[] { PointerType.Mouse };
+
+ //
+ // Volatile: Multithread Mutable Access
+ //
private volatile long windowHandle = 0; // lifecycle critical
private volatile boolean visible = false; // lifecycle critical
- private RecursiveLock windowLock = LockFactory.createRecursiveLock(); // Window instance wide lock
- private RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); // Surface only lock
-
+ private volatile boolean hasFocus = false;
+ private volatile int pixWidth = 128, pixHeight = 128; // client-area size w/o insets in pixel units, default: may be overwritten by user
+ private volatile int winWidth = 128, winHeight = 128; // client-area size w/o insets in window units, default: may be overwritten by user
+ protected final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ protected final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ protected final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+
+ private volatile int x = 64, y = 64; // client-area pos w/o insets in window units
+ private volatile Insets insets = new Insets(); // insets of decoration (if top-level && decorated)
+ private boolean blockInsetsChange = false; // block insets change (from same thread)
+
+ private final RecursiveLock windowLock = LockFactory.createRecursiveLock(); // Window instance wide lock
+ private int surfaceLockCount = 0; // surface lock recursion count
+
private ScreenImpl screen; // never null after create - may change reference though (reparent)
private boolean screenReferenceAdded = false;
private NativeWindow parentWindow = null;
@@ -94,72 +171,118 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private AbstractGraphicsConfiguration config = null; // control access due to delegation
protected CapabilitiesImmutable capsRequested = null;
protected CapabilitiesChooser capabilitiesChooser = null; // default null -> default
- private boolean fullscreen = false, hasFocus = false, brokenFocusChange = false;
- private int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user
- private int x = 64, y = 64; // client-area pos w/o insets
+ private boolean fullscreen = false, brokenFocusChange = false;
+ private List<MonitorDevice> fullscreenMonitors = null;
+ private boolean fullscreenUseMainMonitor = true;
private boolean autoPosition = true; // default: true (allow WM to choose top-level position, if not set by user)
- private Insets insets = new Insets(); // insets of decoration (if top-level && decorated)
-
+
private int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets
+ private boolean nfs_alwaysOnTop; // non fullscreen alwaysOnTop setting
private NativeWindow nfs_parent = null; // non fullscreen parent, in case explicit reparenting is performed (offscreen)
private String title = "Newt Window";
private boolean undecorated = false;
private boolean alwaysOnTop = false;
+ private PointerIconImpl pointerIcon = null;
private boolean pointerVisible = true;
private boolean pointerConfined = false;
private LifecycleHook lifecycleHook = null;
- private boolean handleDestroyNotify = true;
+ private Runnable windowDestroyNotifyAction = null;
private FocusRunnable focusAction = null;
private KeyListener keyboardFocusHandler = null;
- private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
-
- private Object childWindowsLock = new Object();
- private ArrayList<NativeWindow> childWindows = new ArrayList<NativeWindow>();
+ private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
+
+ private final Object childWindowsLock = new Object();
+ private final ArrayList<NativeWindow> childWindows = new ArrayList<NativeWindow>();
private ArrayList<MouseListener> mouseListeners = new ArrayList<MouseListener>();
- private int mouseButtonPressed = 0; // current pressed mouse button number
- private long lastMousePressed = 0; // last time when a mouse button was pressed
- private int lastMouseClickCount = 0; // last mouse button click count
- private boolean mouseInWindow = false;// mouse entered window - is inside the window (may be synthetic)
- private Point lastMousePosition = new Point();
- private ArrayList<KeyListener> keyListeners = new ArrayList<KeyListener>();
+ /** from event passing: {@link WindowImpl#consumePointerEvent(MouseEvent)}. */
+ private static class PointerState0 {
+ /** Pointer entered window - is inside the window (may be synthetic) */
+ boolean insideSurface = false;
+ /** Mouse EXIT has been sent (only for MOUSE type enter/exit)*/
+ boolean exitSent = false;
- private ArrayList<WindowListener> windowListeners = new ArrayList<WindowListener>();
- private boolean repaintQueued = false;
+ /** last time when a pointer button was pressed */
+ long lastButtonPressTime = 0;
- // Workaround for initialization order problems on Mac OS X
- // between native Newt and (apparently) Fmod -- if Fmod is
- // initialized first then the connection to the window server
- // breaks, leading to errors from deep within the AppKit
- public static void init(String type) {
- if (NativeWindowFactory.TYPE_MACOSX.equals(type)) {
- try {
- getWindowClass(type);
- } catch (Exception e) {
- e.printStackTrace();
+ /** Pointer in dragging mode */
+ boolean dragging = false;
+
+ void clearButton() {
+ lastButtonPressTime = 0;
+ }
+ public String toString() { return "PState0[inside "+insideSurface+", exitSent "+exitSent+", lastPress "+lastButtonPressTime+", dragging "+dragging+"]"; }
+ }
+ private final PointerState0 pState0 = new PointerState0();
+
+ /** from direct input: {@link WindowImpl#doPointerEvent(boolean, boolean, int[], short, int, int, boolean, short[], int[], int[], float[], float, float[], float)}. */
+ private static class PointerState1 extends PointerState0 {
+ /** Current pressed mouse button number */
+ short buttonPressed = (short)0;
+ /** Current pressed mouse button modifier mask */
+ int buttonPressedMask = 0;
+ /** Last mouse button click count */
+ short lastButtonClickCount = (short)0;
+
+ @Override
+ final void clearButton() {
+ super.clearButton();
+ lastButtonClickCount = (short)0;
+ if( !dragging || 0 == buttonPressedMask ) {
+ buttonPressed = 0;
+ buttonPressedMask = 0;
+ dragging = false;
+ }
+ }
+
+ /** Last pointer-move position for 8 touch-down pointers */
+ final Point[] movePositions = new Point[] {
+ new Point(), new Point(), new Point(), new Point(),
+ new Point(), new Point(), new Point(), new Point() };
+ final Point getMovePosition(final int id) {
+ if( 0 <= id && id < movePositions.length ) {
+ return movePositions[id];
}
+ return null;
}
+ public final String toString() { return "PState1[inside "+insideSurface+", exitSent "+exitSent+", lastPress "+lastButtonPressTime+
+ ", pressed [button "+buttonPressed+", mask "+buttonPressedMask+", dragging "+dragging+", clickCount "+lastButtonClickCount+"]"; }
}
+ private final PointerState1 pState1 = new PointerState1();
+
+ /** Pointer names -> pointer ID (consecutive index, starting w/ 0) */
+ private final ArrayHashSet<Integer> pName2pID = new ArrayHashSet<Integer>();
+
+ private boolean defaultGestureHandlerEnabled = true;
+ private DoubleTapScrollGesture gesture2PtrTouchScroll = null;
+ private ArrayList<GestureHandler> pointerGestureHandler = new ArrayList<GestureHandler>();
+
+ private ArrayList<GestureHandler.GestureListener> gestureListeners = new ArrayList<GestureHandler.GestureListener>();
+
+ private ArrayList<KeyListener> keyListeners = new ArrayList<KeyListener>();
+
+ private ArrayList<WindowListener> windowListeners = new ArrayList<WindowListener>();
+ private boolean repaintQueued = false;
//
// Construction Methods
//
- private static Class<?> getWindowClass(String type)
+ private static Class<?> getWindowClass(final String type)
throws ClassNotFoundException
{
final Class<?> windowClass = NewtFactory.getCustomClass(type, "WindowDriver");
if(null==windowClass) {
- throw new ClassNotFoundException("Failed to find NEWT Window Class <"+type+".WindowDriver>");
+ throw new ClassNotFoundException("Failed to find NEWT Window Class <"+type+".WindowDriver>");
}
return windowClass;
}
- public static WindowImpl create(NativeWindow parentWindow, long parentWindowHandle, Screen screen, CapabilitiesImmutable caps) {
+ public static WindowImpl create(final NativeWindow parentWindow, final long parentWindowHandle, final Screen screen, final CapabilitiesImmutable caps) {
try {
Class<?> windowClass;
if(caps.isOnscreen()) {
@@ -167,44 +290,60 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
} else {
windowClass = OffscreenWindow.class;
}
- WindowImpl window = (WindowImpl) windowClass.newInstance();
+ final WindowImpl window = (WindowImpl) windowClass.newInstance();
window.parentWindow = parentWindow;
window.parentWindowHandle = parentWindowHandle;
window.screen = (ScreenImpl) screen;
window.capsRequested = (CapabilitiesImmutable) caps.cloneMutable();
- window.setUndecorated(0!=parentWindowHandle);
window.instantiationFinished();
+ addWindow2List(window);
return window;
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
throw new NativeWindowException(t);
}
}
-
- public static WindowImpl create(Object[] cstrArguments, Screen screen, CapabilitiesImmutable caps) {
+
+ public static WindowImpl create(final Object[] cstrArguments, final Screen screen, final CapabilitiesImmutable caps) {
try {
- Class<?> windowClass = getWindowClass(screen.getDisplay().getType());
- Class<?>[] cstrArgumentTypes = getCustomConstructorArgumentTypes(windowClass);
+ final Class<?> windowClass = getWindowClass(screen.getDisplay().getType());
+ final Class<?>[] cstrArgumentTypes = getCustomConstructorArgumentTypes(windowClass);
if(null==cstrArgumentTypes) {
throw new NativeWindowException("WindowClass "+windowClass+" doesn't support custom arguments in constructor");
}
- int argsChecked = verifyConstructorArgumentTypes(cstrArgumentTypes, cstrArguments);
+ final int argsChecked = verifyConstructorArgumentTypes(cstrArgumentTypes, cstrArguments);
if ( argsChecked < cstrArguments.length ) {
throw new NativeWindowException("WindowClass "+windowClass+" constructor mismatch at argument #"+argsChecked+"; Constructor: "+getTypeStrList(cstrArgumentTypes)+", arguments: "+getArgsStrList(cstrArguments));
}
- WindowImpl window = (WindowImpl) ReflectionUtil.createInstance( windowClass, cstrArgumentTypes, cstrArguments ) ;
+ final WindowImpl window = (WindowImpl) ReflectionUtil.createInstance( windowClass, cstrArgumentTypes, cstrArguments ) ;
window.screen = (ScreenImpl) screen;
window.capsRequested = (CapabilitiesImmutable) caps.cloneMutable();
+ window.instantiationFinished();
+ addWindow2List(window);
return window;
- } catch (Throwable t) {
+ } catch (final Throwable t) {
throw new NativeWindowException(t);
}
}
- protected final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) {
+ /** Fast invalidation of instance w/o any blocking function call. */
+ private final void shutdown() {
+ if(null!=lifecycleHook) {
+ lifecycleHook.shutdownRenderingAction();
+ }
+ setWindowHandle(0);
+ visible = false;
+ fullscreen = false;
+ fullscreenMonitors = null;
+ fullscreenUseMainMonitor = true;
+ hasFocus = false;
+ parentWindowHandle = 0;
+ }
+
+ protected final void setGraphicsConfiguration(final AbstractGraphicsConfiguration cfg) {
config = cfg;
}
-
+
public static interface LifecycleHook {
/**
* Reset of internal state counter, ie totalFrames, etc.
@@ -212,15 +351,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
*/
public abstract void resetCounter();
- /**
- * Invoked after Window setVisible,
+ /**
+ * Invoked after Window setVisible,
* allows allocating resources depending on the native Window.
* Called from EDT while window is locked.
*/
void setVisibleActionPost(boolean visible, boolean nativeWindowCreated);
- /**
- * Invoked before Window destroy action,
+ /**
+ * Notifies the receiver to preserve resources (GL, ..)
+ * for the next destroy*() calls (only), if supported and if <code>value</code> is <code>true</code>, otherwise clears preservation flag.
+ * @param value <code>true</code> to set the one-shot preservation if supported, otherwise clears it.
+ */
+ void preserveGLStateAtDestroy(boolean value);
+
+ /**
+ * Invoked before Window destroy action,
* allows releasing of resources depending on the native Window.<br>
* Surface not locked yet.<br>
* Called not necessarily from EDT.
@@ -236,7 +382,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
void destroyActionInLock();
/**
- * Invoked for expensive modifications, ie while reparenting and ScreenMode change.<br>
+ * Invoked for expensive modifications, ie while reparenting and MonitorMode change.<br>
* No lock is hold when invoked.<br>
*
* @return true is paused, otherwise false. If true {@link #resumeRenderingAction()} shall be issued.
@@ -246,12 +392,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
boolean pauseRenderingAction();
/**
- * Invoked for expensive modifications, ie while reparenting and ScreenMode change.
+ * Invoked for expensive modifications, ie while reparenting and MonitorMode change.
* No lock is hold when invoked.<br>
*
* @see #pauseRenderingAction()
*/
void resumeRenderingAction();
+
+ /**
+ * Shutdown rendering action (thread) abnormally.
+ * <p>
+ * Should be called only at shutdown, if necessary.
+ * </p>
+ */
+ void shutdownRenderingAction();
}
private boolean createNative() {
@@ -262,38 +416,59 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
} else {
tStart = 0;
}
-
- if( null != parentWindow &&
+
+ if( null != parentWindow &&
NativeSurface.LOCK_SURFACE_NOT_READY >= parentWindow.lockSurface() ) {
throw new NativeWindowException("Parent surface lock: not ready: "+parentWindow);
}
-
+
+ final boolean hasParent = null != parentWindow || 0 != this.parentWindowHandle;
+
// child window: position defaults to 0/0, no auto position, no negative position
- if( null != parentWindow && ( autoPosition || 0>getX() || 0>getY() ) ) {
+ if( hasParent && ( autoPosition || 0>getX() || 0>getY() ) ) {
definePosition(0, 0);
}
boolean postParentlockFocus = false;
try {
if(validateParentWindowHandle()) {
- if(screenReferenceAdded) {
- throw new InternalError("XXX");
- }
- if(canCreateNativeImpl()) {
+ if( !screenReferenceAdded ) {
screen.addReference();
screenReferenceAdded = true;
+ }
+ if(canCreateNativeImpl()) {
+ final int wX, wY;
+ final boolean usePosition;
+ if( autoPosition ) {
+ wX = 0;
+ wY = 0;
+ usePosition = false;
+ } else {
+ wX = getX();
+ wY = getY();
+ usePosition = true;
+ }
+ final long t0 = System.currentTimeMillis();
createNativeImpl();
- screen.addScreenModeListener(screenModeListenerImpl);
+ screen.addMonitorModeListener(monitorModeListenerImpl);
setTitleImpl(title);
- setPointerVisibleImpl(pointerVisible);
+ setPointerIconIntern(pointerIcon);
+ setPointerVisibleIntern(pointerVisible);
confinePointerImpl(pointerConfined);
setKeyboardVisible(keyboardVisible);
- if(waitForVisible(true, false)) {
+ final long remainingV = waitForVisible(true, false);
+ if( 0 <= remainingV ) {
if(isFullscreen()) {
synchronized(fullScreenAction) {
fullscreen = false; // trigger a state change
fullScreenAction.init(true);
fullScreenAction.run();
}
+ } else if ( !hasParent ) {
+ // Wait until position is reached within tolerances, either auto-position or custom position.
+ waitForPosition(usePosition, wX, wY, Window.TIMEOUT_NATIVEWINDOW);
+ }
+ if (DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.createNative(): elapsed "+(System.currentTimeMillis()-t0)+" ms");
}
postParentlockFocus = true;
}
@@ -306,7 +481,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
if(postParentlockFocus) {
// harmonize focus behavior for all platforms: focus on creation
- requestFocusInt(isFullscreen() /* skipFocusAction */);
+ requestFocusInt(isFullscreen() /* skipFocusAction if fullscreen */);
((DisplayImpl) screen.getDisplay()).dispatchMessagesNative(); // status up2date
}
if(DEBUG_IMPLEMENTATION) {
@@ -333,7 +508,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return true;
}
- private static long getNativeWindowHandle(NativeWindow nativeWindow) {
+ private static long getNativeWindowHandle(final NativeWindow nativeWindow) {
long handle = 0;
if(null!=nativeWindow) {
boolean wasLocked = false;
@@ -344,7 +519,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(0==handle) {
throw new NativeWindowException("Parent native window handle is NULL, after succesful locking: "+nativeWindow);
}
- } catch (NativeWindowException nwe) {
+ } catch (final NativeWindowException nwe) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.getNativeWindowHandle: not successful yet: "+nwe);
}
@@ -371,18 +546,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
//----------------------------------------------------------------------
// WindowClosingProtocol implementation
//
- private Object closingListenerLock = new Object();
+ private final Object closingListenerLock = new Object();
private WindowClosingMode defaultCloseOperation = WindowClosingMode.DISPOSE_ON_CLOSE;
- public WindowClosingMode getDefaultCloseOperation() {
+ @Override
+ public final WindowClosingMode getDefaultCloseOperation() {
synchronized (closingListenerLock) {
return defaultCloseOperation;
}
}
- public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
+ @Override
+ public final WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
synchronized (closingListenerLock) {
- WindowClosingMode _op = defaultCloseOperation;
+ final WindowClosingMode _op = defaultCloseOperation;
defaultCloseOperation = op;
return _op;
}
@@ -394,28 +571,28 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
/**
* Notifies the driver impl. that the instantiation is finished,
- * ie. instance created and all fields set.
+ * ie. instance created and all fields set.
*/
protected void instantiationFinished() {
// nop
}
-
+
protected boolean canCreateNativeImpl() {
return true; // default: always able to be created
}
-
- /**
+
+ /**
* The native implementation must set the native windowHandle.<br>
*
* <p>
* The implementation shall respect the states {@link #isAlwaysOnTop()}/{@link #FLAG_IS_ALWAYSONTOP} and
* {@link #isUndecorated()}/{@link #FLAG_IS_UNDECORATED}, ie. the created window shall reflect those settings.
* </p>
- *
+ *
* <p>
* The implementation should invoke the referenced java state callbacks
* to notify this Java object of state changes.</p>
- *
+ *
* @see #windowDestroyNotify(boolean)
* @see #focusChanged(boolean, boolean)
* @see #visibleChanged(boolean, boolean)
@@ -427,16 +604,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
protected abstract void closeNativeImpl();
- /**
+ /**
* Async request which shall be performed within {@link #TIMEOUT_NATIVEWINDOW}.
* <p>
- * If if <code>force == false</code> the native implementation
+ * If if <code>force == false</code> the native implementation
* may only request focus if not yet owner.</p>
* <p>
* {@link #focusChanged(boolean, boolean)} should be called
- * to notify about the focus traversal.
- * </p>
- *
+ * to notify about the focus traversal.
+ * </p>
+ *
* @param force if true, bypass {@link #focusChanged(boolean, boolean)} and force focus request
*/
protected abstract void requestFocusImpl(boolean force);
@@ -446,26 +623,27 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
public static final int FLAG_CHANGE_FULLSCREEN = 1 << 2;
public static final int FLAG_CHANGE_ALWAYSONTOP = 1 << 3;
public static final int FLAG_CHANGE_VISIBILITY = 1 << 4;
-
+
public static final int FLAG_HAS_PARENT = 1 << 8;
public static final int FLAG_IS_UNDECORATED = 1 << 9;
public static final int FLAG_IS_FULLSCREEN = 1 << 10;
- public static final int FLAG_IS_ALWAYSONTOP = 1 << 11;
- public static final int FLAG_IS_VISIBLE = 1 << 12;
+ public static final int FLAG_IS_FULLSCREEN_SPAN = 1 << 11;
+ public static final int FLAG_IS_ALWAYSONTOP = 1 << 12;
+ public static final int FLAG_IS_VISIBLE = 1 << 13;
/**
* The native implementation should invoke the referenced java state callbacks
* to notify this Java object of state changes.
- *
+ *
* <p>
* Implementations shall set x/y to 0, in case it's negative. This could happen due
* to insets and positioning a decorated window to 0/0, which would place the frame
* outside of the screen.</p>
- *
- * @param x client-area position, or <0 if unchanged
- * @param y client-area position, or <0 if unchanged
- * @param width client-area size, or <=0 if unchanged
- * @param height client-area size, or <=0 if unchanged
+ *
+ * @param x client-area position in window units, or <0 if unchanged
+ * @param y client-area position in window units, or <0 if unchanged
+ * @param width client-area size in window units, or <=0 if unchanged
+ * @param height client-area size in window units, or <=0 if unchanged
* @param flags bitfield of change and status flags
*
* @see #sizeChanged(int,int)
@@ -473,79 +651,99 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
*/
protected abstract boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags);
- protected int getReconfigureFlags(int changeFlags, boolean visible) {
- return changeFlags |= ( ( 0 != getParentWindowHandle() ) ? FLAG_HAS_PARENT : 0 ) |
- ( isUndecorated() ? FLAG_IS_UNDECORATED : 0 ) |
- ( isFullscreen() ? FLAG_IS_FULLSCREEN : 0 ) |
- ( isAlwaysOnTop() ? FLAG_IS_ALWAYSONTOP : 0 ) |
- ( visible ? FLAG_IS_VISIBLE : 0 ) ;
+ /**
+ * Tests whether a single reconfigure flag is supported by implementation.
+ * <p>
+ * Default is all but {@link #FLAG_IS_FULLSCREEN_SPAN}
+ * </p>
+ */
+ protected boolean isReconfigureFlagSupported(final int changeFlags) {
+ return 0 == ( changeFlags & FLAG_IS_FULLSCREEN_SPAN );
}
- protected static String getReconfigureFlagsAsString(StringBuilder sb, int flags) {
+
+ protected int getReconfigureFlags(final int changeFlags, final boolean visible) {
+ return changeFlags | ( ( 0 != getParentWindowHandle() ) ? FLAG_HAS_PARENT : 0 ) |
+ ( isUndecorated() ? FLAG_IS_UNDECORATED : 0 ) |
+ ( isFullscreen() ? FLAG_IS_FULLSCREEN : 0 ) |
+ ( isAlwaysOnTop() ? FLAG_IS_ALWAYSONTOP : 0 ) |
+ ( visible ? FLAG_IS_VISIBLE : 0 ) ;
+ }
+ protected static String getReconfigureFlagsAsString(StringBuilder sb, final int flags) {
if(null == sb) { sb = new StringBuilder(); }
sb.append("[");
-
+
if( 0 != ( FLAG_CHANGE_PARENTING & flags) ) {
sb.append("*");
}
- sb.append("PARENT_");
+ sb.append("PARENT ");
sb.append(0 != ( FLAG_HAS_PARENT & flags));
sb.append(", ");
-
+
if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
sb.append("*");
}
- sb.append("FS_");
+ sb.append("FS ");
sb.append(0 != ( FLAG_IS_FULLSCREEN & flags));
- sb.append(", ");
+ sb.append("[span ");
+ sb.append(0 != ( FLAG_IS_FULLSCREEN_SPAN & flags));
+ sb.append("], ");
if( 0 != ( FLAG_CHANGE_DECORATION & flags) ) {
sb.append("*");
}
- sb.append("UNDECOR_");
+ sb.append("UNDECOR ");
sb.append(0 != ( FLAG_IS_UNDECORATED & flags));
sb.append(", ");
-
+
if( 0 != ( FLAG_CHANGE_ALWAYSONTOP & flags) ) {
sb.append("*");
}
- sb.append("ALWAYSONTOP_");
+ sb.append("ALWAYSONTOP ");
sb.append(0 != ( FLAG_IS_ALWAYSONTOP & flags));
sb.append(", ");
-
+
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
sb.append("*");
}
- sb.append("VISIBLE_");
+ sb.append("VISIBLE ");
sb.append(0 != ( FLAG_IS_VISIBLE & flags));
-
+
sb.append("]");
return sb.toString();
}
-
- protected void setTitleImpl(String title) {}
+
+ protected void setTitleImpl(final String title) {}
/**
- * Return screen coordinates of the given coordinates
- * or null, in which case a NativeWindow traversal shall being used
+ * Translates the given window client-area coordinates with top-left origin
+ * to screen coordinates in window units.
+ * <p>
+ * Since the position reflects the client area, it does not include the insets.
+ * </p>
+ * <p>
+ * May return <code>null</code>, in which case the caller shall traverse through the NativeWindow tree
* as demonstrated in {@link #getLocationOnScreen(javax.media.nativewindow.util.Point)}.
+ * </p>
*
* @return if not null, the screen location of the given coordinates
*/
protected abstract Point getLocationOnScreenImpl(int x, int y);
-
- /** Triggered by user via {@link #getInsets()}.<br>
- * Implementations may implement this hook to update the insets.<br>
+
+ /**
+ * Triggered by user via {@link #getInsets()}.<br>
+ * Implementations may implement this hook to update the insets.<br>
* However, they may prefer the event driven path via {@link #insetsChanged(boolean, int, int, int, int)}.
- *
+ *
* @see #getInsets()
* @see #insetsChanged(boolean, int, int, int, int)
*/
protected abstract void updateInsetsImpl(Insets insets);
- protected boolean setPointerVisibleImpl(boolean pointerVisible) { return false; }
- protected boolean confinePointerImpl(boolean confine) { return false; }
- protected void warpPointerImpl(int x, int y) { }
-
+ protected boolean setPointerVisibleImpl(final boolean pointerVisible) { return false; }
+ protected boolean confinePointerImpl(final boolean confine) { return false; }
+ protected void warpPointerImpl(final int x, final int y) { }
+ protected void setPointerIconImpl(final PointerIconImpl pi) { }
+
//----------------------------------------------------------------------
// NativeSurface
//
@@ -553,10 +751,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
@Override
public final int lockSurface() throws NativeWindowException, RuntimeException {
final RecursiveLock _wlock = windowLock;
- final RecursiveLock _slock = surfaceLock;
_wlock.lock();
- _slock.lock();
- int res = _slock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
+ surfaceLockCount++;
+ int res = ( 1 == surfaceLockCount ) ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
if ( LOCK_SURFACE_NOT_READY == res ) {
try {
@@ -573,7 +770,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
} finally {
if (LOCK_SURFACE_NOT_READY >= res) {
- _slock.unlock();
+ surfaceLockCount--;
_wlock.unlock();
}
}
@@ -583,12 +780,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
@Override
public final void unlockSurface() {
- final RecursiveLock _slock = surfaceLock;
final RecursiveLock _wlock = windowLock;
- _slock.validateLocked();
_wlock.validateLocked();
- if (_slock.getHoldCount() == 1) {
+ if ( 1 == surfaceLockCount ) {
final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
try {
unlockSurfaceImpl();
@@ -596,42 +791,67 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
adevice.unlock();
}
}
- _slock.unlock();
+ surfaceLockCount--;
_wlock.unlock();
}
@Override
public final boolean isSurfaceLockedByOtherThread() {
- return surfaceLock.isLockedByOtherThread();
+ return windowLock.isLockedByOtherThread();
}
@Override
public final Thread getSurfaceLockOwner() {
- return surfaceLock.getOwner();
+ return windowLock.getOwner();
}
public final RecursiveLock getLock() {
return windowLock;
}
-
+
+ @Override
public long getSurfaceHandle() {
return windowHandle; // default: return window handle
}
+ @Override
public boolean surfaceSwap() {
return false;
}
+ @Override
+ public final void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
+ }
+
+ @Override
+ public final void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
+ surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
+ }
+
+ @Override
public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
return config.getNativeGraphicsConfiguration();
}
+ @Override
public final long getDisplayHandle() {
- return getScreen().getDisplay().getHandle();
+ return config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
}
+ @Override
public final int getScreenIndex() {
- return getScreen().getIndex();
+ return screen.getIndex();
}
//----------------------------------------------------------------------
@@ -640,14 +860,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// public final void destroy() - see below
+ @Override
+ public final NativeSurface getNativeSurface() { return this; }
+
+ @Override
public final NativeWindow getParent() {
return parentWindow;
}
+ @Override
public final long getWindowHandle() {
return windowHandle;
}
+ @Override
public Point getLocationOnScreen(Point storage) {
if(isNativeValid()) {
Point d;
@@ -684,32 +910,47 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Window
//
+ @Override
public final boolean isNativeValid() {
return 0 != windowHandle ;
}
+ @Override
public final Screen getScreen() {
return screen;
}
- protected final void setVisibleImpl(boolean visible, int x, int y, int width, int height) {
- reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, visible));
- }
- final void setVisibleActionImpl(boolean visible) {
+ protected void setScreen(final ScreenImpl newScreen) { // never null !
+ removeScreenReference();
+ screen = newScreen;
+ }
+
+ @Override
+ public final MonitorDevice getMainMonitor() {
+ return screen.getMainMonitor( getBounds() );
+ }
+
+ /**
+ * @param visible
+ * @param x client-area position in window units, or <0 if unchanged
+ * @param y client-area position in window units, or <0 if unchanged
+ * @param width client-area size in window units, or <=0 if unchanged
+ * @param height client-area size in window units, or <=0 if unchanged
+ */
+ protected final void setVisibleImpl(final boolean visible, final int x, final int y, final int width, final int height) {
+ reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, visible));
+ }
+ final void setVisibleActionImpl(final boolean visible) {
boolean nativeWindowCreated = false;
boolean madeVisible = false;
-
+
final RecursiveLock _lock = windowLock;
_lock.lock();
try {
- if(null!=lifecycleHook) {
- lifecycleHook.resetCounter();
- }
-
if(!visible && null!=childWindows && childWindows.size()>0) {
synchronized(childWindowsLock) {
for(int i = 0; i < childWindows.size(); i++ ) {
- NativeWindow nw = childWindows.get(i);
+ final NativeWindow nw = childWindows.get(i);
if(nw instanceof WindowImpl) {
((WindowImpl)nw).setVisible(false);
}
@@ -722,12 +963,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
madeVisible = nativeWindowCreated;
}
// always flag visible, allowing a retry ..
- WindowImpl.this.visible = true;
+ WindowImpl.this.visible = true;
} else if(WindowImpl.this.visible != visible) {
if(isNativeValid()) {
setVisibleImpl(visible, getX(), getY(), getWidth(), getHeight());
- WindowImpl.this.waitForVisible(visible, true);
+ WindowImpl.this.waitForVisible(visible, false);
madeVisible = visible;
+ } else {
+ WindowImpl.this.visible = true;
}
}
@@ -738,7 +981,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(isNativeValid() && visible && null!=childWindows && childWindows.size()>0) {
synchronized(childWindowsLock) {
for(int i = 0; i < childWindows.size(); i++ ) {
- NativeWindow nw = childWindows.get(i);
+ final NativeWindow nw = childWindows.get(i);
if(nw instanceof WindowImpl) {
((WindowImpl)nw).setVisible(true);
}
@@ -749,6 +992,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
System.err.println("Window setVisible: END ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+WindowImpl.this.visible+", nativeWindowCreated: "+nativeWindowCreated+", madeVisible: "+madeVisible);
}
} finally {
+ if(null!=lifecycleHook) {
+ lifecycleHook.resetCounter();
+ }
_lock.unlock();
}
if( nativeWindowCreated || madeVisible ) {
@@ -758,54 +1004,62 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private class VisibleAction implements Runnable {
boolean visible;
- private VisibleAction(boolean visible) {
+ private VisibleAction(final boolean visible) {
this.visible = visible;
}
+ @Override
public final void run() {
setVisibleActionImpl(visible);
}
}
- protected void setVisible(boolean wait, boolean visible) {
+ @Override
+ public final void setVisible(final boolean wait, final boolean visible) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window setVisible: START ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow));
}
- runOnEDTIfAvail(wait, new VisibleAction(visible));
+ runOnEDTIfAvail(wait, new VisibleAction(visible));
}
-
- public void setVisible(boolean visible) {
+
+ @Override
+ public final void setVisible(final boolean visible) {
setVisible(true, visible);
}
-
+
private class SetSizeAction implements Runnable {
int width, height;
+ boolean force;
- private SetSizeAction(int w, int h) {
+ private SetSizeAction(final int w, final int h, final boolean disregardFS) {
this.width = w;
this.height = h;
+ this.force = disregardFS;
}
+ @Override
public final void run() {
final RecursiveLock _lock = windowLock;
_lock.lock();
try {
- if ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) {
+ if ( force || ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) ) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible);
+ System.err.println("Window setSize: START force "+force+", "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible);
}
int visibleAction; // 0 nop, 1 invisible, 2 visible (create)
- if ( isNativeValid() && 0>=width*height && visible ) {
+ if ( visible && isNativeValid() && ( 0 >= width || 0 >= height ) ) {
visibleAction=1; // invisible
defineSize(0, 0);
- } else if ( !isNativeValid() && 0<width*height && visible ) {
+ } else if ( visible && !isNativeValid() && 0 < width && 0 < height ) {
visibleAction = 2; // visible (create)
defineSize(width, height);
- } else if ( isNativeValid() ) {
+ } else if ( visible && isNativeValid() ) {
visibleAction = 0;
// this width/height will be set by windowChanged, called by the native implementation
reconfigureWindowImpl(getX(), getY(), width, height, getReconfigureFlags(0, isVisible()));
+ WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW);
} else {
+ // invisible or invalid w/ 0 size
visibleAction = 0;
defineSize(width, height);
}
@@ -823,14 +1077,25 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- public void setSize(int width, int height) {
- runOnEDTIfAvail(true, new SetSizeAction(width, height));
- }
- public void setTopLevelSize(int width, int height) {
+ private void setSize(final int width, final int height, final boolean force) {
+ runOnEDTIfAvail(true, new SetSizeAction(width, height, force));
+ }
+ @Override
+ public final void setSize(final int width, final int height) {
+ runOnEDTIfAvail(true, new SetSizeAction(width, height, false));
+ }
+ @Override
+ public final void setSurfaceSize(final int pixelWidth, final int pixelHeight) {
+ // FIXME HiDPI: Shortcut, may need to adjust if we change scaling methodology
+ setSize(pixelWidth / getPixelScaleX(), pixelHeight / getPixelScaleY());
+ }
+ @Override
+ public final void setTopLevelSize(final int width, final int height) {
setSize(width - getInsets().getTotalWidth(), height - getInsets().getTotalHeight());
}
- private class DestroyAction implements Runnable {
+ private final Runnable destroyAction = new Runnable() {
+ @Override
public final void run() {
boolean animatorPaused = false;
if(null!=lifecycleHook) {
@@ -839,23 +1104,27 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(null!=lifecycleHook) {
lifecycleHook.destroyActionPreLock();
}
+ RuntimeException lifecycleCaughtInLock = null;
final RecursiveLock _lock = windowLock;
_lock.lock();
try {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window DestroyAction() "+getThreadName());
+ System.err.println("Window DestroyAction() hasScreen "+(null != screen)+", isNativeValid "+isNativeValid()+" - "+getThreadName());
}
+
+ // send synced destroy-notify notification
+ sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+
// Childs first ..
synchronized(childWindowsLock) {
if(childWindows.size()>0) {
// avoid ConcurrentModificationException: parent -> child -> parent.removeChild(this)
@SuppressWarnings("unchecked")
- ArrayList<NativeWindow> clonedChildWindows = (ArrayList<NativeWindow>) childWindows.clone();
+ final ArrayList<NativeWindow> clonedChildWindows = (ArrayList<NativeWindow>) childWindows.clone();
while( clonedChildWindows.size() > 0 ) {
- NativeWindow nw = clonedChildWindows.remove(0);
+ final NativeWindow nw = clonedChildWindows.remove(0);
if(nw instanceof WindowImpl) {
- ((WindowImpl)nw).sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
- ((WindowImpl)nw).destroy();
+ ((WindowImpl)nw).windowDestroyNotify(true);
} else {
nw.destroy();
}
@@ -865,19 +1134,26 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(null!=lifecycleHook) {
// send synced destroy notification for proper cleanup, eg GLWindow/OpenGL
- lifecycleHook.destroyActionInLock();
+ try {
+ lifecycleHook.destroyActionInLock();
+ } catch (final RuntimeException re) {
+ lifecycleCaughtInLock = re;
+ }
}
- if( null != screen ) {
- if( isNativeValid() ) {
- screen.removeScreenModeListener(screenModeListenerImpl);
- closeNativeImpl();
- removeScreenReference();
- }
- Display dpy = screen.getDisplay();
- if(null != dpy) {
- dpy.validateEDT();
+ if( isNativeValid() ) {
+ screen.removeMonitorModeListener(monitorModeListenerImpl);
+ closeNativeImpl();
+ final AbstractGraphicsDevice cfgADevice = config.getScreen().getDevice();
+ if( cfgADevice != screen.getDisplay().getGraphicsDevice() ) { // don't pull display's device
+ cfgADevice.close(); // ensure a cfg's device is closed
}
+ setGraphicsConfiguration(null);
+ }
+ removeScreenReference();
+ final Display dpy = screen.getDisplay();
+ if(null != dpy) {
+ dpy.validateEDTStopped();
}
// send synced destroyed notification
@@ -885,54 +1161,73 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.destroy() END "+getThreadName()/*+", "+WindowImpl.this*/);
+ if( null != lifecycleCaughtInLock ) {
+ System.err.println("Window.destroy() caught: "+lifecycleCaughtInLock.getMessage());
+ lifecycleCaughtInLock.printStackTrace();
+ }
+ }
+ if( null != lifecycleCaughtInLock ) {
+ throw lifecycleCaughtInLock;
}
} finally {
// update states before release window lock
setWindowHandle(0);
visible = false;
fullscreen = false;
+ fullscreenMonitors = null;
+ fullscreenUseMainMonitor = true;
hasFocus = false;
parentWindowHandle = 0;
+ hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
_lock.unlock();
}
if(animatorPaused) {
lifecycleHook.resumeRenderingAction();
}
-
+
// these refs shall be kept alive - resurrection via setVisible(true)
/**
if(null!=parentWindow && parentWindow instanceof Window) {
((Window)parentWindow).removeChild(WindowImpl.this);
- }
+ }
childWindows = null;
surfaceUpdatedListeners = null;
mouseListeners = null;
keyListeners = null;
capsRequested = null;
lifecycleHook = null;
-
- screen = null;
+
+ screen = null;
windowListeners = null;
parentWindow = null;
- */
- }
- }
- private final DestroyAction destroyAction = new DestroyAction();
+ */
+ } };
+ @Override
public void destroy() {
- visible = false; // Immediately mark synchronized visibility flag, avoiding possible recreation
+ visible = false; // Immediately mark synchronized visibility flag, avoiding possible recreation
runOnEDTIfAvail(true, destroyAction);
}
+ protected void destroy(final boolean preserveResources) {
+ if( null != lifecycleHook ) {
+ lifecycleHook.preserveGLStateAtDestroy( preserveResources );
+ }
+ destroy();
+ }
+
/**
* @param cWin child window, must not be null
* @param pWin parent window, may be null
- * @return true if at least one of both window's configurations is offscreen
+ * @return true if at least one of both window's configurations is offscreen
*/
- protected static boolean isOffscreenInstance(NativeWindow cWin, NativeWindow pWin) {
+ protected static boolean isOffscreenInstance(final NativeWindow cWin, final NativeWindow pWin) {
boolean ofs = false;
- final AbstractGraphicsConfiguration cWinCfg = cWin.getGraphicsConfiguration();
+ final AbstractGraphicsConfiguration cWinCfg = cWin.getGraphicsConfiguration();
if( null != cWinCfg ) {
ofs = !cWinCfg.getChosenCapabilities().isOnscreen();
}
@@ -944,15 +1239,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
return ofs;
}
-
+
private class ReparentAction implements Runnable {
- NativeWindow newParentWindow;
- boolean forceDestroyCreate;
+ final NativeWindow newParentWindow;
+ final int topLevelX, topLevelY;
+ final int hints;
ReparentOperation operation;
- private ReparentAction(NativeWindow newParentWindow, boolean forceDestroyCreate) {
+ private ReparentAction(final NativeWindow newParentWindow, final int topLevelX, final int topLevelY, int hints) {
this.newParentWindow = newParentWindow;
- this.forceDestroyCreate = forceDestroyCreate | DEBUG_TEST_REPARENT_INCOMPATIBLE;
+ this.topLevelX = topLevelX;
+ this.topLevelY = topLevelY;
+ if( DEBUG_TEST_REPARENT_INCOMPATIBLE ) {
+ hints |= REPARENT_HINT_FORCE_RECREATION;
+ }
+ this.hints = hints;
this.operation = ReparentOperation.ACTION_INVALID; // ensure it's set
}
@@ -960,12 +1261,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return operation;
}
- private void setScreen(ScreenImpl newScreen) { // never null !
- removeScreenReference();
- screen = newScreen;
- }
-
+ @Override
public final void run() {
+ if( WindowImpl.this.isFullscreen() ) {
+ // Bug 924: Ignore reparent when in fullscreen - otherwise may confuse WM
+ if( DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.reparent: NOP (in fullscreen, "+getThreadName()+") valid "+isNativeValid()+
+ ", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+ }
+ return;
+ }
boolean animatorPaused = false;
if(null!=lifecycleHook) {
animatorPaused = lifecycleHook.pauseRenderingAction();
@@ -975,24 +1280,35 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
lifecycleHook.resumeRenderingAction();
}
}
-
+
private void reparent() {
// mirror pos/size so native change notification can get overwritten
- int x = getX();
- int y = getY();
- int width = getWidth();
- int height = getHeight();
- boolean wasVisible;
-
+ final int oldX = getX();
+ final int oldY = getY();
+ final int oldWidth = getWidth();
+ final int oldHeight = getHeight();
+ final int x, y;
+ int width = oldWidth;
+ int height = oldHeight;
+
+ final boolean wasVisible;
+ final boolean becomesVisible;
+ final boolean forceDestroyCreate;
+
final RecursiveLock _lock = windowLock;
_lock.lock();
try {
- if(isNativeValid()) {
- // force recreation if offscreen, since it may become onscreen
- forceDestroyCreate |= isOffscreenInstance(WindowImpl.this, newParentWindow);
+ {
+ boolean v = 0 != ( REPARENT_HINT_FORCE_RECREATION & hints );
+ if(isNativeValid()) {
+ // force recreation if offscreen, since it may become onscreen
+ v |= isOffscreenInstance(WindowImpl.this, newParentWindow);
+ }
+ forceDestroyCreate = v;
}
-
+
wasVisible = isVisible();
+ becomesVisible = wasVisible || 0 != ( REPARENT_HINT_BECOMES_VISIBLE & hints );
Window newParentWindowNEWT = null;
if(newParentWindow instanceof Window) {
@@ -1001,15 +1317,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
long newParentWindowHandle = 0 ;
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparent: START ("+getThreadName()+") valid "+isNativeValid()+", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+", visible "+wasVisible+", old parentWindow: "+Display.hashCodeNullSafe(parentWindow)+", new parentWindow: "+Display.hashCodeNullSafe(newParentWindow)+", forceDestroyCreate "+forceDestroyCreate+", "+x+"/"+y+" "+width+"x"+height);
- }
-
- if(null!=lifecycleHook) {
- lifecycleHook.resetCounter();
+ if( DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.reparent: START ("+getThreadName()+") valid "+isNativeValid()+
+ ", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+
+ ", visible "+wasVisible+", becomesVisible "+becomesVisible+
+ ", forceDestroyCreate "+forceDestroyCreate+
+ ", DEBUG_TEST_REPARENT_INCOMPATIBLE "+DEBUG_TEST_REPARENT_INCOMPATIBLE+
+ ", HINT_FORCE_RECREATION "+( 0 != ( REPARENT_HINT_FORCE_RECREATION & hints ) )+
+ ", HINT_BECOMES_VISIBLE "+( 0 != ( REPARENT_HINT_BECOMES_VISIBLE & hints ) ) +
+ ", old parentWindow: "+Display.hashCodeNullSafe(parentWindow)+
+ ", new parentWindow: "+Display.hashCodeNullSafe(newParentWindow) );
}
if(null!=newParentWindow) {
+ // REPARENT TO CHILD WINDOW
+
// reset position to 0/0 within parent space
x = 0;
y = 0;
@@ -1031,7 +1353,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
// Destroy this window and use parent's Screen.
// It may be created properly when the parent is made visible.
- destroy();
+ destroy( becomesVisible );
setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING;
} else if(newParentWindow != getParent()) {
@@ -1042,25 +1364,24 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(null!=newParentWindowNEWT) {
setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
} else {
- Screen newScreen = NewtFactory.createCompatibleScreen(newParentWindow, getScreen());
- if( getScreen() != newScreen ) {
+ final Screen newScreen = NewtFactory.createCompatibleScreen(newParentWindow, screen);
+ if( screen != newScreen ) {
// auto destroy on-the-fly created Screen/Display
setScreen( (ScreenImpl) newScreen );
}
}
- if( 0<width*height ) {
+ if( 0 < width && 0 < height ) {
operation = ReparentOperation.ACTION_NATIVE_CREATION;
} else {
operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING;
}
- } else if ( forceDestroyCreate || !NewtFactory.isScreenCompatible(newParentWindow, getScreen()) ) {
- // Destroy this window, may create a new compatible Screen/Display,
- // and mark it for creation.
- destroy();
+ } else if ( forceDestroyCreate || !NewtFactory.isScreenCompatible(newParentWindow, screen) ) {
+ // Destroy this window, may create a new compatible Screen/Display, while trying to preserve resources if becoming visible again.
+ destroy( becomesVisible );
if(null!=newParentWindowNEWT) {
setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
} else {
- setScreen( (ScreenImpl) NewtFactory.createCompatibleScreen(newParentWindow, getScreen()) );
+ setScreen( (ScreenImpl) NewtFactory.createCompatibleScreen(newParentWindow, screen) );
}
operation = ReparentOperation.ACTION_NATIVE_CREATION;
} else {
@@ -1072,12 +1393,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
operation = ReparentOperation.ACTION_NOP;
}
} else {
- if( null != parentWindow ) {
+ // REPARENT TO TOP-LEVEL WINDOW
+ if( 0 <= topLevelX && 0 <= topLevelY ) {
+ x = topLevelX;
+ y = topLevelY;
+ } else if( null != parentWindow ) {
// child -> top
// put client to current parent+child position
- Point p = getLocationOnScreen(null);
+ final Point p = getLocationOnScreen(null);
x = p.getX();
y = p.getY();
+ } else {
+ x = oldX;
+ y = oldY;
}
// Case: Top Window
@@ -1086,8 +1414,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
operation = ReparentOperation.ACTION_NOP;
} else if( !isNativeValid() || forceDestroyCreate ) {
// Destroy this window and mark it for [pending] creation.
- destroy();
- if( 0<width*height ) {
+ // If isNativeValid() and becoming visible again - try to preserve resources, i.e. b/c on-/offscreen switch.
+ destroy( becomesVisible );
+ if( 0 < width && 0 < height ) {
operation = ReparentOperation.ACTION_NATIVE_CREATION;
} else {
operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING;
@@ -1103,15 +1432,18 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
throw new NativeWindowException("Internal Error: reparentAction not set");
}
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.reparent: ACTION ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" new parentWindowHandle "+toHexString(newParentWindowHandle)+", reparentAction "+operation+", pos/size "+x+"/"+y+" "+width+"x"+height+", visible "+wasVisible);
+ }
+
if( ReparentOperation.ACTION_NOP == operation ) {
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparent: NO CHANGE ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" new parentWindowHandle "+toHexString(newParentWindowHandle)+", visible "+wasVisible);
- }
return;
}
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparent: ACTION ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" new parentWindowHandle "+toHexString(newParentWindowHandle)+", reparentAction "+operation+", visible "+wasVisible);
+ if( null == newParentWindow ) {
+ // CLIENT -> TOP: Reset Parent's Pointer State
+ setOffscreenPointerIcon(null);
+ setOffscreenPointerVisible(true, null);
}
// rearrange window tree
@@ -1123,23 +1455,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
((Window)parentWindow).addChild(WindowImpl.this);
}
- if( ReparentOperation.ACTION_NATIVE_CREATION_PENDING == operation ) {
- // make size and position persistent for proper recreation
- definePosition(x, y);
- defineSize(width, height);
- return;
- }
-
if( ReparentOperation.ACTION_NATIVE_REPARENTING == operation ) {
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
display.dispatchMessagesNative(); // status up2date
- if(wasVisible) {
- setVisibleImpl(false, x, y, width, height);
- WindowImpl.this.waitForVisible(false, true);
- // some composite WM behave slacky .. give 'em chance to change state -> invisible,
+ // TOP -> CLIENT: !visible first (fixes X11 unsuccessful return to parent window)
+ if( null != parentWindow && wasVisible && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
+ setVisibleImpl(false, oldX, oldY, oldWidth, oldHeight);
+ WindowImpl.this.waitForVisible(false, false);
+ // FIXME: Some composite WM behave slacky .. give 'em chance to change state -> invisible,
// even though we do exactly that (KDE+Composite)
- try { Thread.sleep(100); } catch (InterruptedException e) { }
+ try { Thread.sleep(100); } catch (final InterruptedException e) { }
display.dispatchMessagesNative(); // status up2date
}
@@ -1163,45 +1489,74 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
parentWindowLocked.unlockSurface();
}
}
+ definePosition(x, y); // position might not get updated by WM events (SWT parent apparently)
// set visible again
if(ok) {
display.dispatchMessagesNative(); // status up2date
if(wasVisible) {
setVisibleImpl(true, x, y, width, height);
- ok = WindowImpl.this.waitForVisible(true, false);
- display.dispatchMessagesNative(); // status up2date
+ ok = 0 <= WindowImpl.this.waitForVisible(true, false);
if(ok) {
+ if( isAlwaysOnTop() && 0 == parentWindowHandle && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
+ // Reinforce ALWAYSONTOP when CHILD -> TOP reparenting, since reparenting itself cause X11 WM to loose it's state.
+ reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
+ }
ok = WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW);
}
if(ok) {
- requestFocusInt(false /* skipFocusAction */);
- display.dispatchMessagesNative(); // status up2date
+ if( 0 == parentWindowHandle ) {
+ // Position mismatch shall not lead to reparent failure
+ WindowImpl.this.waitForPosition(true, x, y, TIMEOUT_NATIVEWINDOW);
+ }
+
+ requestFocusInt( 0 == parentWindowHandle /* skipFocusAction if top-level */);
+ display.dispatchMessagesNative(); // status up2date
}
}
}
if(!ok || !wasVisible) {
- // make size and position persistent manual,
+ // make size and position persistent manual,
// since we don't have a WM feedback (invisible or recreation)
definePosition(x, y);
defineSize(width, height);
}
-
+
if(!ok) {
- // native reparent failed -> try creation
+ // native reparent failed -> try creation, while trying to preserve resources if becoming visible again.
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.reparent: native reparenting failed ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentWindowHandle)+" - Trying recreation");
}
- destroy();
+ destroy( becomesVisible );
operation = ReparentOperation.ACTION_NATIVE_CREATION ;
+ } else {
+ if( null != parentWindow ) {
+ // TOP -> CLIENT: Setup Parent's Pointer State
+ setOffscreenPointerIcon(pointerIcon);
+ setOffscreenPointerVisible(pointerVisible, pointerIcon);
+ }
}
+ } else {
+ // Case
+ // ACTION_NATIVE_CREATION
+ // ACTION_NATIVE_CREATION_PENDING;
+
+ // make size and position persistent for proper [re]creation
+ definePosition(x, y);
+ defineSize(width, height);
}
-
+
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparentWindow: END-1 ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height);
+ System.err.println("Window.reparent: END-1 ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+
+ ", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+
+ ", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+
+ getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
}
} finally {
+ if(null!=lifecycleHook) {
+ lifecycleHook.resetCounter();
+ }
_lock.unlock();
}
if(wasVisible) {
@@ -1215,53 +1570,55 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// This may run on the new Display/Screen connection, hence a new EDT task
runOnEDTIfAvail(true, reparentActionRecreate);
break;
-
+
default:
}
}
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparentWindow: END-X ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height);
+ System.err.println("Window.reparent: END-X ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+
+ ", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+
+ ", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+
+ getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
}
}
}
- private class ReparentActionRecreate implements Runnable {
+ private final Runnable reparentActionRecreate = new Runnable() {
+ @Override
public final void run() {
final RecursiveLock _lock = windowLock;
_lock.lock();
try {
- visible = true;
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparentWindow: ReparentActionRecreate ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+Display.hashCodeNullSafe(parentWindow));
+ System.err.println("Window.reparent: ReparentActionRecreate ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+Display.hashCodeNullSafe(parentWindow));
}
- setVisible(true); // native creation
+ setVisibleActionImpl(true); // native creation
+ requestFocusInt( 0 == parentWindowHandle /* skipFocusAction if top-level */);
} finally {
_lock.unlock();
}
- }
- }
- private final ReparentActionRecreate reparentActionRecreate = new ReparentActionRecreate();
+ } };
- public final ReparentOperation reparentWindow(NativeWindow newParent) {
- return reparentWindow(newParent, false);
- }
-
- public ReparentOperation reparentWindow(NativeWindow newParent, boolean forceDestroyCreate) {
- final ReparentAction reparentAction = new ReparentAction(newParent, forceDestroyCreate);
+ @Override
+ public final ReparentOperation reparentWindow(final NativeWindow newParent, final int x, final int y, final int hints) {
+ final ReparentAction reparentAction = new ReparentAction(newParent, x, y, hints);
runOnEDTIfAvail(true, reparentAction);
return reparentAction.getOp();
}
- public CapabilitiesChooser setCapabilitiesChooser(CapabilitiesChooser chooser) {
- CapabilitiesChooser old = this.capabilitiesChooser;
+ @Override
+ public final CapabilitiesChooser setCapabilitiesChooser(final CapabilitiesChooser chooser) {
+ final CapabilitiesChooser old = this.capabilitiesChooser;
this.capabilitiesChooser = chooser;
return old;
}
+ @Override
public final CapabilitiesImmutable getChosenCapabilities() {
return getGraphicsConfiguration().getChosenCapabilities();
}
+ @Override
public final CapabilitiesImmutable getRequestedCapabilities() {
return capsRequested;
}
@@ -1269,10 +1626,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private class DecorationAction implements Runnable {
boolean undecorated;
- private DecorationAction(boolean undecorated) {
+ private DecorationAction(final boolean undecorated) {
this.undecorated = undecorated;
}
+ @Override
public final void run() {
final RecursiveLock _lock = windowLock;
_lock.lock();
@@ -1288,7 +1646,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
final int width = getWidth();
final int height = getHeight();
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
display.dispatchMessagesNative(); // status up2date
reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_DECORATION, isVisible()));
display.dispatchMessagesNative(); // status up2date
@@ -1301,10 +1659,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- public void setUndecorated(boolean value) {
+ @Override
+ public final void setUndecorated(final boolean value) {
runOnEDTIfAvail(true, new DecorationAction(value));
}
+ @Override
public final boolean isUndecorated() {
return 0 != parentWindowHandle || undecorated || fullscreen ;
}
@@ -1312,10 +1672,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private class AlwaysOnTopAction implements Runnable {
boolean alwaysOnTop;
- private AlwaysOnTopAction(boolean alwaysOnTop) {
+ private AlwaysOnTopAction(final boolean alwaysOnTop) {
this.alwaysOnTop = alwaysOnTop;
}
+ @Override
public final void run() {
final RecursiveLock _lock = windowLock;
_lock.lock();
@@ -1323,7 +1684,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(WindowImpl.this.alwaysOnTop != alwaysOnTop) {
// set current state
WindowImpl.this.alwaysOnTop = alwaysOnTop;
-
+
if( isNativeValid() ) {
// Mirror pos/size so native change notification can get overwritten
final int x = getX();
@@ -1331,7 +1692,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
final int width = getWidth();
final int height = getHeight();
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
display.dispatchMessagesNative(); // status up2date
reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
display.dispatchMessagesNative(); // status up2date
@@ -1344,18 +1705,26 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- public final void setAlwaysOnTop(boolean value) {
- runOnEDTIfAvail(true, new AlwaysOnTopAction(value));
+ @Override
+ public final void setAlwaysOnTop(final boolean value) {
+ if( isFullscreen() ) {
+ nfs_alwaysOnTop = value;
+ } else {
+ runOnEDTIfAvail(true, new AlwaysOnTopAction(value));
+ }
}
-
+
+ @Override
public final boolean isAlwaysOnTop() {
return alwaysOnTop;
}
-
- public String getTitle() {
+
+ @Override
+ public final String getTitle() {
return title;
}
- public void setTitle(String title) {
+ @Override
+ public final void setTitle(String title) {
if (title == null) {
title = "";
}
@@ -1365,31 +1734,128 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- public boolean isPointerVisible() {
+ @Override
+ public final boolean isPointerVisible() {
return pointerVisible;
}
- public void setPointerVisible(boolean pointerVisible) {
+ @Override
+ public final void setPointerVisible(final boolean pointerVisible) {
if(this.pointerVisible != pointerVisible) {
boolean setVal = 0 == getWindowHandle();
if(!setVal) {
- setVal = setPointerVisibleImpl(pointerVisible);
+ setVal = setPointerVisibleIntern(pointerVisible);
}
if(setVal) {
- this.pointerVisible = pointerVisible;
+ this.pointerVisible = pointerVisible;
}
}
}
- public boolean isPointerConfined() {
+ private boolean setPointerVisibleIntern(final boolean pointerVisible) {
+ final boolean res = setOffscreenPointerVisible(pointerVisible, pointerIcon);
+ return setPointerVisibleImpl(pointerVisible) || res; // accept onscreen or offscreen positive result!
+ }
+ /**
+ * Helper method to delegate {@link #setPointerVisibleImpl(boolean)} to
+ * {@link OffscreenLayerSurface#hideCursor()} or {@link OffscreenLayerSurface#setCursor(PixelRectangle, PointImmutable)}.
+ * <p>
+ * Note: JAWTWindow is an OffscreenLayerSurface.
+ * </p>
+ * <p>
+ * Performing OffscreenLayerSurface's setCursor(..)/hideCursor(), if available,
+ * gives same behavior on all platforms.
+ * </p>
+ * <p>
+ * If visible, implementation invokes {@link #setOffscreenPointerIcon(OffscreenLayerSurface, PointerIconImpl)} using the
+ * given <code>defaultPointerIcon</code>, otherwise {@link OffscreenLayerSurface#hideCursor()} is invoked.
+ * </p>
+ * @param pointerVisible true for visible, otherwise invisible.
+ * @param defaultPointerIcon default PointerIcon for visibility
+ * @param ols the {@link OffscreenLayerSurface} instance, if null method does nothing.
+ */
+ private boolean setOffscreenPointerVisible(final boolean pointerVisible, final PointerIconImpl defaultPointerIcon) {
+ if( pointerVisible ) {
+ return setOffscreenPointerIcon(defaultPointerIcon);
+ } else {
+ final NativeWindow parent = getParent();
+ if( parent instanceof OffscreenLayerSurface ) {
+ final OffscreenLayerSurface ols = (OffscreenLayerSurface) parent;
+ try {
+ return ols.hideCursor();
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public final PointerIcon getPointerIcon() { return pointerIcon; }
+
+ @Override
+ public final void setPointerIcon(final PointerIcon pi) {
+ final PointerIconImpl piImpl = (PointerIconImpl)pi;
+ if( this.pointerIcon != piImpl ) {
+ if( isNativeValid() ) {
+ runOnEDTIfAvail(true, new Runnable() {
+ public void run() {
+ setPointerIconIntern(piImpl);
+ } } );
+ }
+ this.pointerIcon = piImpl;
+ }
+ }
+ private void setPointerIconIntern(final PointerIconImpl pi) {
+ setOffscreenPointerIcon(pi);
+ setPointerIconImpl(pi);
+ }
+ /**
+ * Helper method to delegate {@link #setPointerIconIntern(PointerIconImpl)} to
+ * {@link OffscreenLayerSurface#setCursor(PixelRectangle, PointImmutable)}
+ * <p>
+ * Note: JAWTWindow is an OffscreenLayerSurface.
+ * </p>
+ * <p>
+ * Performing OffscreenLayerSurface's setCursor(..), if available,
+ * gives same behavior on all platforms.
+ * </p>
+ * <p>
+ * Workaround for AWT/Windows bug within browser,
+ * where the PointerIcon gets periodically overridden
+ * by the AWT Component's icon.
+ * </p>
+ * @param ols the {@link OffscreenLayerSurface} instance, if null method does nothing.
+ * @param pi the {@link PointerIconImpl} instance, if null PointerIcon gets reset.
+ */
+ private boolean setOffscreenPointerIcon(final PointerIconImpl pi) {
+ final NativeWindow parent = getParent();
+ if( parent instanceof OffscreenLayerSurface ) {
+ final OffscreenLayerSurface ols = (OffscreenLayerSurface) parent;
+ try {
+ if( null != pi ) {
+ return ols.setCursor(pi, pi.getHotspot());
+ } else {
+ return ols.setCursor(null, null); // default
+ }
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public final boolean isPointerConfined() {
return pointerConfined;
}
-
- public void confinePointer(boolean confine) {
+ @Override
+ public final void confinePointer(final boolean confine) {
if(this.pointerConfined != confine) {
boolean setVal = 0 == getWindowHandle();
if(!setVal) {
if(confine) {
requestFocus();
- warpPointer(getWidth()/2, getHeight()/2);
+ warpPointer(getSurfaceWidth()/2, getSurfaceHeight()/2);
}
setVal = confinePointerImpl(confine);
if(confine) {
@@ -1397,21 +1863,23 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// this allows user listener to sync previous position value to the new centered position
try {
Thread.sleep(3 * screen.getDisplay().getEDTUtil().getPollPeriod());
- } catch (InterruptedException e) { }
+ } catch (final InterruptedException e) { }
}
}
if(setVal) {
- this.pointerConfined = confine;
+ this.pointerConfined = confine;
}
- }
+ }
}
-
- public void warpPointer(int x, int y) {
+
+ @Override
+ public final void warpPointer(final int x, final int y) {
if(0 != getWindowHandle()) {
warpPointerImpl(x, y);
}
}
-
+
+ @Override
public final InsetsImmutable getInsets() {
if(isUndecorated()) {
return Insets.getZero();
@@ -1419,27 +1887,109 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
updateInsetsImpl(insets);
return insets;
}
-
+
+ @Override
+ public final int getX() {
+ return x;
+ }
+
+ @Override
+ public final int getY() {
+ return y;
+ }
+
+ @Override
public final int getWidth() {
- return width;
+ return winWidth;
}
+ @Override
public final int getHeight() {
- return height;
+ return winHeight;
}
- public final int getX() {
- return x;
+ @Override
+ public final Rectangle getBounds() {
+ return new Rectangle(x, y, winWidth, winHeight);
}
- public final int getY() {
- return y;
+ @Override
+ public final int getSurfaceWidth() {
+ return pixWidth;
+ }
+
+ @Override
+ public final int getSurfaceHeight() {
+ return pixHeight;
+ }
+
+ @Override
+ public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
+ pixelUnitsAndResult[0] /= getPixelScaleX();
+ pixelUnitsAndResult[1] /= getPixelScaleY();
+ return pixelUnitsAndResult;
+ }
+
+ @Override
+ public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
+ windowUnitsAndResult[0] *= getPixelScaleX();
+ windowUnitsAndResult[1] *= getPixelScaleY();
+ return windowUnitsAndResult;
+ }
+
+ protected final Point convertToWindowUnits(final Point pixelUnitsAndResult) {
+ return pixelUnitsAndResult.scaleInv(getPixelScaleX(), getPixelScaleY());
+ }
+
+ protected final Point convertToPixelUnits(final Point windowUnitsAndResult) {
+ return windowUnitsAndResult.scale(getPixelScaleX(), getPixelScaleY());
+ }
+
+ /** HiDPI: We currently base scaling of window units to pixel units on an integer scale factor per component. */
+ protected final int getPixelScaleX() {
+ return hasPixelScale[0];
+ }
+
+ /** HiDPI: We currently base scaling of window units to pixel units on an integer scale factor per component. */
+ protected final int getPixelScaleY() {
+ return hasPixelScale[1];
+ }
+
+ @Override
+ public void setSurfaceScale(final int[] pixelScale) {
+ SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG_IMPLEMENTATION ? getClass().getSimpleName() : null);
+ }
+
+ @Override
+ public final int[] getRequestedSurfaceScale(final int[] result) {
+ System.arraycopy(reqPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final int[] getCurrentSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final int[] getNativeSurfaceScale(final int[] result) {
+ System.arraycopy(nativePixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final float[] getPixelsPerMM(final float[] ppmmStore) {
+ getMainMonitor().getPixelsPerMM(ppmmStore);
+ ppmmStore[0] *= (float)hasPixelScale[0] / (float)nativePixelScale[0];
+ ppmmStore[1] *= (float)hasPixelScale[1] / (float)nativePixelScale[1];
+ return ppmmStore;
}
protected final boolean autoPosition() { return autoPosition; }
-
- /** Sets the position fields {@link #x} and {@link #y} to the given values and {@link #autoPosition} to false. */
- protected final void definePosition(int x, int y) {
+
+ /** Sets the position fields {@link #x} and {@link #y} in window units to the given values and {@link #autoPosition} to false. */
+ protected final void definePosition(final int x, final int y) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("definePosition: "+this.x+"/"+this.y+" -> "+x+"/"+y);
// Thread.dumpStack();
@@ -1448,19 +1998,28 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
this.x = x; this.y = y;
}
- /** Sets the size fields {@link #width} and {@link #height} to the given values. */
- protected final void defineSize(int width, int height) {
+ /**
+ * Sets the size fields {@link #winWidth} and {@link #winHeight} in window units to the given values
+ * and {@link #pixWidth} and {@link #pixHeight} in pixel units according to {@link #convertToPixelUnits(int[])}.
+ */
+ protected final void defineSize(final int winWidth, final int winHeight) {
+ final int pixWidth = winWidth * getPixelScaleX(); // FIXME HiDPI: Shortcut, may need to adjust if we change scaling methodology
+ final int pixHeight = winHeight * getPixelScaleY();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("defineSize: "+this.width+"x"+this.height+" -> "+width+"x"+height);
+ System.err.println("defineSize: win["+this.winWidth+"x"+this.winHeight+" -> "+winWidth+"x"+winHeight+
+ "], pixel["+this.pixWidth+"x"+this.pixHeight+" -> "+pixWidth+"x"+pixHeight+"]");
// Thread.dumpStack();
}
- this.width = width; this.height = height;
+ this.winWidth = winWidth; this.winHeight = winHeight;
+ this.pixWidth = pixWidth; this.pixHeight = pixHeight;
}
-
+
+ @Override
public final boolean isVisible() {
return visible;
}
+ @Override
public final boolean isFullscreen() {
return fullscreen;
}
@@ -1469,6 +2028,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Window
//
+ @Override
+ public final Window getDelegatedWindow() {
+ return this;
+ }
+
+ //----------------------------------------------------------------------
+ // WindowImpl
+ //
+
/**
* If the implementation is capable of detecting a device change
* return true and clear the status/reason of the change.
@@ -1477,66 +2045,49 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return false;
}
- public LifecycleHook getLifecycleHook() {
+ public final LifecycleHook getLifecycleHook() {
return lifecycleHook;
}
- public LifecycleHook setLifecycleHook(LifecycleHook hook) {
- LifecycleHook old = lifecycleHook;
+ public final LifecycleHook setLifecycleHook(final LifecycleHook hook) {
+ final LifecycleHook old = lifecycleHook;
lifecycleHook = hook;
return old;
}
- /** If this Window actually wraps one from another toolkit such as
- the AWT, this will return a non-null value. */
- public Object getWrappedWindow() {
- return null;
- }
-
- public final Window getDelegatedWindow() {
- return this;
- }
-
/**
- * If set to true, the default value, this NEWT Window implementation will
- * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify(boolean)} implementation.<br>
- * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify(boolean)}.
+ * If this Window actually wraps a {@link NativeSurface} from another instance or toolkit,
+ * it will return such reference. Otherwise returns null.
*/
- public void setHandleDestroyNotify(boolean b) {
- handleDestroyNotify = b;
+ public NativeSurface getWrappedSurface() {
+ return null;
}
- //----------------------------------------------------------------------
- // WindowImpl
- //
-
- /**
- * Returns the non delegated {@link AbstractGraphicsConfiguration},
- * see {@link #getGraphicsConfiguration()}. */
- public final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() {
- return config;
+ @Override
+ public final void setWindowDestroyNotifyAction(final Runnable r) {
+ windowDestroyNotifyAction = r;
}
-
+
protected final long getParentWindowHandle() {
return isFullscreen() ? 0 : parentWindowHandle;
}
@Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
+ public final String toString() {
+ final StringBuilder sb = new StringBuilder();
sb.append(getClass().getName()+"[Config "+config+
- "\n, "+screen+
- "\n, ParentWindow "+parentWindow+
- "\n, ParentWindowHandle "+toHexString(parentWindowHandle)+" ("+(0!=getParentWindowHandle())+")"+
- "\n, WindowHandle "+toHexString(getWindowHandle())+
- "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+windowLock.isLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+
- "\n, Pos "+getX()+"/"+getY()+" (auto "+autoPosition()+"), size "+getWidth()+"x"+getHeight()+
- "\n, Visible "+isVisible()+", focus "+hasFocus()+
- "\n, Undecorated "+undecorated+" ("+isUndecorated()+")"+
- "\n, AlwaysOnTop "+alwaysOnTop+", Fullscreen "+fullscreen+
- "\n, WrappedWindow "+getWrappedWindow()+
- "\n, ChildWindows "+childWindows.size());
+ ",\n "+screen+
+ ",\n ParentWindow "+parentWindow+
+ ",\n ParentWindowHandle "+toHexString(parentWindowHandle)+" ("+(0!=getParentWindowHandle())+")"+
+ ",\n WindowHandle "+toHexString(getWindowHandle())+
+ ",\n SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+windowLock.isLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+
+ ",\n window["+getX()+"/"+getY()+" (auto "+autoPosition()+") "+getWidth()+"x"+getHeight()+"], pixel["+getSurfaceWidth()+"x"+getSurfaceHeight()+
+ "],\n Visible "+isVisible()+", focus "+hasFocus()+
+ ",\n Undecorated "+undecorated+" ("+isUndecorated()+")"+
+ ",\n AlwaysOnTop "+alwaysOnTop+", Fullscreen "+fullscreen+
+ ",\n WrappedSurface "+getWrappedSurface()+
+ ",\n ChildWindows "+childWindows.size());
sb.append(", SurfaceUpdatedListeners num "+surfaceUpdatedHelper.size()+" [");
for (int i = 0; i < surfaceUpdatedHelper.size(); i++ ) {
@@ -1550,33 +2101,33 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
for (int i = 0; i < mouseListeners.size(); i++ ) {
sb.append(mouseListeners.get(i)+", ");
}
+ sb.append("], PointerGestures default "+defaultGestureHandlerEnabled+", custom "+pointerGestureHandler.size()+" [");
+ for (int i = 0; i < pointerGestureHandler.size(); i++ ) {
+ sb.append(pointerGestureHandler.get(i)+", ");
+ }
sb.append("], KeyListeners num "+keyListeners.size()+" [");
for (int i = 0; i < keyListeners.size(); i++ ) {
sb.append(keyListeners.get(i)+", ");
}
- sb.append("], surfaceLock "+surfaceLock);
- sb.append(", windowLock "+windowLock+"]");
+ sb.append("], windowLock "+windowLock+", surfaceLockCount "+surfaceLockCount+"]");
return sb.toString();
}
- protected final void setWindowHandle(long handle) {
+ protected final void setWindowHandle(final long handle) {
windowHandle = handle;
}
- public void runOnEDTIfAvail(boolean wait, final Runnable task) {
- if(windowLock.isOwner(Thread.currentThread())) {
+ @Override
+ public final void runOnEDTIfAvail(final boolean wait, final Runnable task) {
+ if( windowLock.isOwner( Thread.currentThread() ) ) {
task.run();
} else {
- Screen scrn = getScreen();
- if(null==scrn) {
- throw new RuntimeException("Null screen of inner class: "+this);
- }
- DisplayImpl d = (DisplayImpl) scrn.getDisplay();
- d.runOnEDTIfAvail(wait, task);
+ ( (DisplayImpl) screen.getDisplay() ).runOnEDTIfAvail(wait, task);
}
}
private final Runnable requestFocusAction = new Runnable() {
+ @Override
public final void run() {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.RequestFocusAction: force 0 - ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
@@ -1585,6 +2136,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
};
private final Runnable requestFocusActionForced = new Runnable() {
+ @Override
public final void run() {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.RequestFocusAction: force 1 - ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
@@ -1593,40 +2145,44 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
};
+ @Override
public final boolean hasFocus() {
return hasFocus;
}
- public void requestFocus() {
+ @Override
+ public final void requestFocus() {
requestFocus(true);
}
- public void requestFocus(boolean wait) {
+ @Override
+ public final void requestFocus(final boolean wait) {
requestFocus(wait /* wait */, false /* skipFocusAction */, brokenFocusChange /* force */);
}
-
- private void requestFocus(boolean wait, boolean skipFocusAction, boolean force) {
+
+ private void requestFocus(final boolean wait, final boolean skipFocusAction, final boolean force) {
if( isNativeValid() &&
( force || !hasFocus() ) &&
( skipFocusAction || !focusAction() ) ) {
runOnEDTIfAvail(wait, force ? requestFocusActionForced : requestFocusAction);
}
}
-
+
/** Internally forcing request focus on current thread */
- private void requestFocusInt(boolean skipFocusAction) {
+ private void requestFocusInt(final boolean skipFocusAction) {
if( skipFocusAction || !focusAction() ) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.RequestFocusInt: forcing - ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+ System.err.println("Window.RequestFocusInt: forcing - ("+getThreadName()+"): skipFocusAction "+skipFocusAction+", focus "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
}
requestFocusImpl(true);
- }
+ }
}
-
- public void setFocusAction(FocusRunnable focusAction) {
+
+ @Override
+ public final void setFocusAction(final FocusRunnable focusAction) {
this.focusAction = focusAction;
}
-
+
private boolean focusAction() {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.focusAction() START - "+getThreadName()+", focusAction: "+focusAction+" - windowHandle "+toHexString(getWindowHandle()));
@@ -1642,23 +2198,25 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
return res;
}
-
- protected void setBrokenFocusChange(boolean v) {
+
+ protected final void setBrokenFocusChange(final boolean v) {
brokenFocusChange = v;
}
-
- public void setKeyboardFocusHandler(KeyListener l) {
+
+ @Override
+ public final void setKeyboardFocusHandler(final KeyListener l) {
keyboardFocusHandler = l;
}
-
+
private class SetPositionAction implements Runnable {
int x, y;
- private SetPositionAction(int x, int y) {
+ private SetPositionAction(final int x, final int y) {
this.x = x;
this.y = y;
}
+ @Override
public final void run() {
final RecursiveLock _lock = windowLock;
_lock.lock();
@@ -1666,10 +2224,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window setPosition: "+getX()+"/"+getY()+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle));
}
- if ( !isFullscreen() && ( getX() != x || getY() != y ) ) {
+ // Let the window be positioned if !fullscreen and position changed or being a child window.
+ if ( !isFullscreen() && ( getX() != x || getY() != y || null != getParent()) ) {
if(isNativeValid()) {
// this.x/this.y will be set by sizeChanged, triggered by windowing event system
reconfigureWindowImpl(x, y, getWidth(), getHeight(), getReconfigureFlags(0, isVisible()));
+ if( null == parentWindow ) {
+ // Wait until custom position is reached within tolerances
+ waitForPosition(true, x, y, Window.TIMEOUT_NATIVEWINDOW);
+ }
} else {
definePosition(x, y); // set pos for createNative(..)
}
@@ -1680,58 +2243,96 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- public void setPosition(int x, int y) {
+ @Override
+ public void setPosition(final int x, final int y) {
autoPosition = false;
runOnEDTIfAvail(true, new SetPositionAction(x, y));
}
-
- public void setTopLevelPosition(int x, int y) {
+
+ @Override
+ public final void setTopLevelPosition(final int x, final int y) {
setPosition(x + getInsets().getLeftWidth(), y + getInsets().getTopHeight());
}
-
+
private class FullScreenAction implements Runnable {
- boolean fullscreen;
+ boolean _fullscreen;
- private boolean init(boolean fullscreen) {
+ private boolean init(final boolean fullscreen) {
if(isNativeValid()) {
- this.fullscreen = fullscreen;
+ this._fullscreen = fullscreen;
return isFullscreen() != fullscreen;
} else {
WindowImpl.this.fullscreen = fullscreen; // set current state for createNative(..)
return false;
}
- }
- public boolean fsOn() { return fullscreen; }
+ }
+ public boolean fsOn() { return _fullscreen; }
+ @Override
public final void run() {
final RecursiveLock _lock = windowLock;
_lock.lock();
+ blockInsetsChange = true;
try {
- // set current state
- WindowImpl.this.fullscreen = fullscreen;
+ final int oldX = getX();
+ final int oldY = getY();
+ final int oldWidth = getWidth();
+ final int oldHeight = getHeight();
int x,y,w,h;
-
- if(fullscreen) {
- nfs_x = getX();
- nfs_y = getY();
- nfs_width = getWidth();
- nfs_height = getHeight();
- x = screen.getX();
- y = screen.getY();
- w = screen.getWidth();
- h = screen.getHeight();
+
+ final RectangleImmutable sviewport = screen.getViewportInWindowUnits(); // window units
+ final RectangleImmutable viewport; // window units
+ final int fs_span_flag;
+ final boolean alwaysOnTopChange;
+ if(_fullscreen) {
+ if( null == fullscreenMonitors ) {
+ if( fullscreenUseMainMonitor ) {
+ fullscreenMonitors = new ArrayList<MonitorDevice>();
+ fullscreenMonitors.add( getMainMonitor() );
+ } else {
+ fullscreenMonitors = getScreen().getMonitorDevices();
+ }
+ }
+ {
+ final Rectangle viewportInWindowUnits = new Rectangle();
+ MonitorDevice.unionOfViewports(null, viewportInWindowUnits, fullscreenMonitors);
+ viewport = viewportInWindowUnits;
+ }
+ if( isReconfigureFlagSupported(FLAG_IS_FULLSCREEN_SPAN) &&
+ ( fullscreenMonitors.size() > 1 || sviewport.compareTo(viewport) > 0 ) ) {
+ fs_span_flag = FLAG_IS_FULLSCREEN_SPAN;
+ } else {
+ fs_span_flag = 0;
+ }
+ nfs_x = oldX;
+ nfs_y = oldY;
+ nfs_width = oldWidth;
+ nfs_height = oldHeight;
+ nfs_alwaysOnTop = alwaysOnTop;
+ x = viewport.getX();
+ y = viewport.getY();
+ w = viewport.getWidth();
+ h = viewport.getHeight();
+ alwaysOnTop = false;
+ alwaysOnTopChange = nfs_alwaysOnTop != alwaysOnTop;
} else {
+ fullscreenUseMainMonitor = true;
+ fullscreenMonitors = null;
+ fs_span_flag = 0;
+ viewport = null;
x = nfs_x;
y = nfs_y;
w = nfs_width;
h = nfs_height;
-
+ alwaysOnTopChange = nfs_alwaysOnTop != alwaysOnTop;
+ alwaysOnTop = nfs_alwaysOnTop;
+
if(null!=parentWindow) {
// reset position to 0/0 within parent space
x = 0;
y = 0;
-
+
// refit if size is bigger than parent
if( w > parentWindow.getWidth() ) {
w = parentWindow.getWidth();
@@ -1741,14 +2342,30 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
}
+
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ display.dispatchMessagesNative(); // status up2date
+ final boolean wasVisible = isVisible();
+ final boolean tempInvisible = !_fullscreen && wasVisible && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true);
+
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+", "+screen);
+ System.err.println("Window fs: "+_fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+
+ ", virtl-screenSize: "+sviewport+" [wu], monitorsViewport "+viewport+" [wu]"+
+ ", spanning "+(0!=fs_span_flag)+
+ ", alwaysOnTop "+alwaysOnTop+(alwaysOnTopChange?"*":"")+
+ ", wasVisible "+wasVisible+", tempInvisible "+tempInvisible+
+ ", hasParent "+(null!=parentWindow)+
+ " @ "+Thread.currentThread().getName());
+ }
+
+ // fullscreen off: !visible first (fixes X11 unsuccessful return to parent window _and_ wrong window size propagation)
+ if( tempInvisible ) {
+ setVisibleImpl(false, oldX, oldY, oldWidth, oldHeight);
+ WindowImpl.this.waitForVisible(false, false);
+ try { Thread.sleep(100); } catch (final InterruptedException e) { }
+ display.dispatchMessagesNative(); // status up2date
}
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
- display.dispatchMessagesNative(); // status up2date
- boolean wasVisible = isVisible();
-
// Lock parentWindow only during reparenting (attempt)
final NativeWindow parentWindowLocked;
if( null != parentWindow ) {
@@ -1760,28 +2377,51 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
parentWindowLocked = null;
}
try {
- reconfigureWindowImpl(x, y, w, h,
- getReconfigureFlags( ( ( null != parentWindowLocked ) ? FLAG_CHANGE_PARENTING : 0 ) |
- FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) );
+ if(alwaysOnTopChange && _fullscreen) {
+ // Enter fullscreen - Disable alwaysOnTop
+ reconfigureWindowImpl(oldX, oldY, oldWidth, oldHeight, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
+ }
+
+ WindowImpl.this.fullscreen = _fullscreen;
+ reconfigureWindowImpl(x, y, w, h,
+ getReconfigureFlags( ( ( null != parentWindowLocked ) ? FLAG_CHANGE_PARENTING : 0 ) |
+ fs_span_flag | FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, isVisible()) );
+ if(alwaysOnTopChange && !_fullscreen) {
+ // Leave fullscreen - Restore alwaysOnTop
+ reconfigureWindowImpl(x, y, w, h, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
+ }
} finally {
if(null!=parentWindowLocked) {
parentWindowLocked.unlockSurface();
}
}
display.dispatchMessagesNative(); // status up2date
-
+
if(wasVisible) {
+ if( NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
+ // Give sluggy WM's (e.g. Unity) a chance to properly restore window ..
+ try { Thread.sleep(100); } catch (final InterruptedException e) { }
+ display.dispatchMessagesNative(); // status up2date
+ }
setVisibleImpl(true, x, y, w, h);
- WindowImpl.this.waitForVisible(true, false);
- display.dispatchMessagesNative(); // status up2date
- WindowImpl.this.waitForSize(w, h, false, TIMEOUT_NATIVEWINDOW);
- display.dispatchMessagesNative(); // status up2date
-
+ boolean ok = 0 <= WindowImpl.this.waitForVisible(true, false);
+ if(ok) {
+ ok = WindowImpl.this.waitForSize(w, h, false, TIMEOUT_NATIVEWINDOW);
+ }
+ if(ok && !_fullscreen && null == parentWindow) {
+ // Position mismatch shall not lead to fullscreen failure
+ WindowImpl.this.waitForPosition(true, x, y, TIMEOUT_NATIVEWINDOW);
+ }
+ if(ok) {
+ requestFocusInt(_fullscreen /* skipFocusAction if fullscreen */);
+ display.dispatchMessagesNative(); // status up2date
+ }
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window fs done: " + WindowImpl.this);
+ System.err.println("Window fs done: ok " + ok + ", " + WindowImpl.this);
}
}
} finally {
+ blockInsetsChange = false;
_lock.unlock();
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
@@ -1789,86 +2429,170 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
private final FullScreenAction fullScreenAction = new FullScreenAction();
- public boolean setFullscreen(boolean fullscreen) {
+ @Override
+ public boolean setFullscreen(final boolean fullscreen) {
+ return setFullscreenImpl(fullscreen, true, null);
+ }
+
+ @Override
+ public boolean setFullscreen(final List<MonitorDevice> monitors) {
+ return setFullscreenImpl(true, false, monitors);
+ }
+
+ private boolean setFullscreenImpl(final boolean fullscreen, final boolean useMainMonitor, final List<MonitorDevice> monitors) {
synchronized(fullScreenAction) {
- if( fullScreenAction.init(fullscreen) ) {
- if(fullScreenAction.fsOn() && isOffscreenInstance(WindowImpl.this, parentWindow)) {
+ fullscreenMonitors = monitors;
+ fullscreenUseMainMonitor = useMainMonitor;
+ if( fullScreenAction.init(fullscreen) ) {
+ if( fullScreenAction.fsOn() && isOffscreenInstance(WindowImpl.this, parentWindow) ) {
// enable fullscreen on offscreen instance
if(null != parentWindow) {
nfs_parent = parentWindow;
- reparentWindow(null, true);
+ reparentWindow(null, -1, -1, REPARENT_HINT_FORCE_RECREATION | REPARENT_HINT_BECOMES_VISIBLE);
} else {
throw new InternalError("Offscreen instance w/o parent unhandled");
}
}
-
+
runOnEDTIfAvail(true, fullScreenAction);
-
+
if(!fullScreenAction.fsOn() && null != nfs_parent) {
// disable fullscreen on offscreen instance
- reparentWindow(nfs_parent, true);
+ reparentWindow(nfs_parent, -1, -1, REPARENT_HINT_FORCE_RECREATION | REPARENT_HINT_BECOMES_VISIBLE);
nfs_parent = null;
}
-
- if(isVisible()) {
- requestFocus(true /* wait */, this.fullscreen /* skipFocusAction */, true /* force */);
- }
}
- return this.fullscreen;
+ return this.fullscreen;
}
}
- private class ScreenModeListenerImpl implements ScreenModeListener {
- boolean animatorPaused = false;
+ /** Notify WindowDriver about the finished monitor mode change. */
+ protected void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ }
- public void screenModeChangeNotify(ScreenMode sm) {
+ private class MonitorModeListenerImpl implements MonitorModeListener {
+ boolean animatorPaused = false;
+ boolean hidden = false;
+ boolean hadFocus = false;
+ boolean fullscreenPaused = false;
+ List<MonitorDevice> _fullscreenMonitors = null;
+ boolean _fullscreenUseMainMonitor = true;
+
+ @Override
+ public void monitorModeChangeNotify(final MonitorEvent me) {
+ hadFocus = hasFocus();
+ final boolean isOSX = NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(true);
+ final boolean quirkFSPause = fullscreen && isReconfigureFlagSupported(FLAG_IS_FULLSCREEN_SPAN);
+ final boolean quirkHide = !quirkFSPause && !fullscreen && isVisible() && isOSX;
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.screenModeChangeNotify: "+sm);
+ System.err.println("Window.monitorModeChangeNotify: hadFocus "+hadFocus+", qFSPause "+quirkFSPause+", qHide "+quirkHide+", "+me+" @ "+Thread.currentThread().getName());
}
if(null!=lifecycleHook) {
animatorPaused = lifecycleHook.pauseRenderingAction();
}
+ if( quirkFSPause ) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.monitorModeChangeNotify: FS Pause");
+ }
+ fullscreenPaused = true;
+ _fullscreenMonitors = fullscreenMonitors;
+ _fullscreenUseMainMonitor = fullscreenUseMainMonitor;
+ setFullscreenImpl(false, true, null);
+ }
+ if( quirkHide ) {
+ // hiding & showing the window around mode-change solves issues w/ OSX,
+ // where the content would be black until a resize.
+ hidden = true;
+ WindowImpl.this.setVisible(false);
+ }
}
- public void screenModeChanged(ScreenMode sm, boolean success) {
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.screenModeChanged: "+sm+", success: "+success);
+ @Override
+ public void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ if(!animatorPaused && success && null!=lifecycleHook) {
+ // Didn't pass above notify method. probably detected screen change after it happened.
+ animatorPaused = lifecycleHook.pauseRenderingAction();
}
-
- if(success) {
- if(!animatorPaused && null!=lifecycleHook) {
- // Didn't pass above notify method. probably detected screen change after it happened.
- animatorPaused = lifecycleHook.pauseRenderingAction();
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.monitorModeChanged.0: success: "+success+", hadFocus "+hadFocus+", animPaused "+animatorPaused+
+ ", hidden "+hidden+", FS "+fullscreen+", FS-paused "+fullscreenPaused+
+ " @ "+Thread.currentThread().getName());
+ System.err.println("Window.monitorModeChanged.0: "+getScreen());
+ System.err.println("Window.monitorModeChanged.0: "+me);
+ }
+ WindowImpl.this.monitorModeChanged(me, success);
+
+ if( success && !fullscreen && !fullscreenPaused ) {
+ // Simply move/resize window to fit in virtual screen if required
+ final RectangleImmutable viewport = screen.getViewportInWindowUnits();
+ if( viewport.getWidth() > 0 && viewport.getHeight() > 0 ) { // failsafe
+ final RectangleImmutable rect = new Rectangle(getX(), getY(), getWidth(), getHeight());
+ final RectangleImmutable isect = viewport.intersection(rect);
+ if ( getHeight() > isect.getHeight() ||
+ getWidth() > isect.getWidth() ) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.monitorModeChanged.1: Non-FS - Fit window "+rect+" into screen viewport "+viewport+
+ ", due to minimal intersection "+isect);
+ }
+ definePosition(viewport.getX(), viewport.getY()); // set pos for setVisible(..) or createNative(..) - reduce EDT roundtrip
+ setSize(viewport.getWidth(), viewport.getHeight(), true /* force */);
+ }
}
- DimensionImmutable screenSize = sm.getMonitorMode().getSurfaceSize().getResolution();
- if ( getHeight() > screenSize.getHeight() ||
- getWidth() > screenSize.getWidth() ) {
- setSize(screenSize.getWidth(), screenSize.getHeight());
+ } else if( fullscreenPaused ) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.monitorModeChanged.2: FS Restore");
+ }
+ setFullscreenImpl(true, _fullscreenUseMainMonitor, _fullscreenMonitors);
+ fullscreenPaused = false;
+ _fullscreenMonitors = null;
+ _fullscreenUseMainMonitor = true;
+ } else if( success && fullscreen && null != fullscreenMonitors ) {
+ // If changed monitor is part of this fullscreen mode, reset size! (Bug 771)
+ final MonitorDevice md = me.getMonitor();
+ if( fullscreenMonitors.contains(md) ) {
+ final Rectangle viewportInWindowUnits = new Rectangle();
+ MonitorDevice.unionOfViewports(null, viewportInWindowUnits, fullscreenMonitors);
+ if(DEBUG_IMPLEMENTATION) {
+ final RectangleImmutable winBounds = WindowImpl.this.getBounds();
+ System.err.println("Window.monitorModeChanged.3: FS Monitor Match: Fit window "+winBounds+" into new viewport union "+viewportInWindowUnits+" [window], provoked by "+md);
+ }
+ definePosition(viewportInWindowUnits.getX(), viewportInWindowUnits.getY()); // set pos for setVisible(..) or createNative(..) - reduce EDT roundtrip
+ setSize(viewportInWindowUnits.getWidth(), viewportInWindowUnits.getHeight(), true /* force */);
}
}
-
+ if( hidden ) {
+ WindowImpl.this.setVisible(true);
+ hidden = false;
+ }
+ sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
if(animatorPaused) {
lifecycleHook.resumeRenderingAction();
}
- sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
+ if( hadFocus ) {
+ requestFocus(true);
+ }
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.monitorModeChanged.X: @ "+Thread.currentThread().getName()+", this: "+WindowImpl.this);
+ }
}
}
- private final ScreenModeListenerImpl screenModeListenerImpl = new ScreenModeListenerImpl();
-
+ private final MonitorModeListenerImpl monitorModeListenerImpl = new MonitorModeListenerImpl();
//----------------------------------------------------------------------
// Child Window Management
- //
+ //
- public final boolean removeChild(NativeWindow win) {
+ @Override
+ public final boolean removeChild(final NativeWindow win) {
synchronized(childWindowsLock) {
return childWindows.remove(win);
}
}
- public final boolean addChild(NativeWindow win) {
+ @Override
+ public final boolean addChild(final NativeWindow win) {
if (win == null) {
return false;
}
@@ -1880,7 +2604,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
//----------------------------------------------------------------------
// Generic Event Support
//
- private void doEvent(boolean enqueue, boolean wait, com.jogamp.newt.event.NEWTEvent event) {
+ private void doEvent(final boolean enqueue, boolean wait, final com.jogamp.newt.event.NEWTEvent event) {
boolean done = false;
if(!enqueue) {
@@ -1893,13 +2617,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- public void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
+ @Override
+ public final void enqueueEvent(final boolean wait, final com.jogamp.newt.event.NEWTEvent event) {
if(isNativeValid()) {
- ((DisplayImpl)getScreen().getDisplay()).enqueueEvent(wait, event);
+ ((DisplayImpl)screen.getDisplay()).enqueueEvent(wait, event);
}
}
- public boolean consumeEvent(NEWTEvent e) {
+ @Override
+ public final boolean consumeEvent(final NEWTEvent e) {
switch(e.getEventType()) {
// special repaint treatment
case WindowEvent.EVENT_WINDOW_REPAINT:
@@ -1910,9 +2636,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
repaintQueued=true;
final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.consumeEvent: "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
+ System.err.println("Window.consumeEvent: REPAINT "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
// Thread.dumpStack();
- }
+ }
return discardTO; // discardTO:=true -> consumed
}
return true;
@@ -1926,7 +2652,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if( null != windowLock.getOwner() ) {
final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.consumeEvent: "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
+ System.err.println("Window.consumeEvent: RESIZED "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
// Thread.dumpStack();
}
return discardTO; // discardTO:=true -> consumed
@@ -1940,7 +2666,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
} else if(e instanceof KeyEvent) {
consumeKeyEvent((KeyEvent)e);
} else if(e instanceof MouseEvent) {
- consumeMouseEvent((MouseEvent)e);
+ consumePointerEvent((MouseEvent)e);
} else {
throw new NativeWindowException("Unexpected NEWTEvent type " + e);
}
@@ -1948,189 +2674,736 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
//
- // SurfaceUpdatedListener Support
+ // MouseListener/Event Support
//
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
- }
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
+ //
+ // Native MouseEvents pre-processed to be enqueued or consumed directly
+ //
+
+ public final void sendMouseEvent(final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
+ doMouseEvent(false, false, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
+ }
+ public final void enqueueMouseEvent(final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
+ doMouseEvent(true, wait, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
+ }
+ protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
+ doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
}
+ /**
+ public final void sendMouseEvent(final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
+ doMouseEvent(false, false, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
+ }
+ public final void enqueueMouseEvent(final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
+ doMouseEvent(true, wait, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
+ } */
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+ /**
+ * Send mouse event (one-pointer) either to be directly consumed or to be enqueued
+ *
+ * @param enqueue if true, event will be {@link #enqueueEvent(boolean, NEWTEvent) enqueued},
+ * otherwise {@link #consumeEvent(NEWTEvent) consumed} directly.
+ * @param wait if true wait until {@link #consumeEvent(NEWTEvent) consumed}.
+ */
+ protected void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
+ if( 0 > button || button > MouseEvent.BUTTON_COUNT ) {
+ throw new NativeWindowException("Invalid mouse button number" + button);
+ }
+ doPointerEvent(enqueue, wait, constMousePointerTypes, eventType, modifiers,
+ 0 /*actionIdx*/, new short[] { (short)0 }, button,
+ new int[]{x}, new int[]{y}, new float[]{0f} /*pressure*/,
+ 1f /*maxPressure*/, rotationXYZ, rotationScale);
}
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
+ /**
+ * Send multiple-pointer event either to be directly consumed or to be enqueued
+ * <p>
+ * The index for the element of multiple-pointer arrays represents the pointer which triggered the event
+ * is passed via <i>actionIdx</i>.
+ * </p>
+ * <p>
+ * The given pointer names, <code>pNames</code>, are mapped to consecutive pointer IDs starting w/ 0
+ * using a hash-map if <code>normalPNames</code> is <code>false</code>.
+ * Otherwise a simple <code>int</code> to <code>short</code> type cast is performed.
+ * </p>
+ * <p>
+ * See {@link #doPointerEvent(boolean, boolean, PointerType[], short, int, int, short[], short, int[], int[], float[], float, float[], float)}
+ * for details!
+ * </p>
+ *
+ * @param enqueue if true, event will be {@link #enqueueEvent(boolean, NEWTEvent) enqueued},
+ * otherwise {@link #consumeEvent(NEWTEvent) consumed} directly.
+ * @param wait if true wait until {@link #consumeEvent(NEWTEvent) consumed}.
+ * @param pTypes {@link MouseEvent.PointerType} for each pointer (multiple pointer)
+ * @param eventType
+ * @param modifiers
+ * @param actionIdx index of multiple-pointer arrays representing the pointer which triggered the event
+ * @param normalPNames see pName below.
+ * @param pNames Pointer name for each pointer (multiple pointer).
+ * We assume consecutive pointer names starting w/ 0 if <code>normalPIDs</code> is <code>true</code>.
+ * Otherwise we hash-map the values during state pressed to retrieve the normal ID.
+ * @param pX X-axis for each pointer (multiple pointer)
+ * @param pY Y-axis for each pointer (multiple pointer)
+ * @param pPressure Pressure for each pointer (multiple pointer)
+ * @param maxPressure Maximum pointer pressure for all pointer
+ */
+ public final void doPointerEvent(final boolean enqueue, final boolean wait,
+ final PointerType[] pTypes, final short eventType, final int modifiers,
+ final int actionIdx, final boolean normalPNames, final int[] pNames,
+ final int[] pX, final int[] pY, final float[] pPressure,
+ final float maxPressure, final float[] rotationXYZ, final float rotationScale) {
+ final int pCount = pNames.length;
+ final short[] pIDs = new short[pCount];
+ for(int i=0; i<pCount; i++) {
+ if( !normalPNames ) {
+ // hash map int name -> short idx
+ final int sz0 = pName2pID.size();
+ final Integer pNameI1 = pName2pID.getOrAdd(Integer.valueOf(pNames[i]));
+ final short pID = (short)pName2pID.indexOf(pNameI1);
+ pIDs[i] = pID;
+ if(DEBUG_MOUSE_EVENT) {
+ final int sz1 = pName2pID.size();
+ if( sz0 != sz1 ) {
+ System.err.println("PointerName2ID[sz "+sz1+"]: Map "+pNameI1+" == "+pID);
+ }
+ }
+ if( MouseEvent.EVENT_MOUSE_RELEASED == eventType ) {
+ pName2pID.remove(pNameI1);
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("PointerName2ID[sz "+pName2pID.size()+"]: Unmap "+pNameI1+" == "+pID);
+ }
+ }
+ } else {
+ // simple type cast
+ pIDs[i] = (short)pNames[i];
+ }
+ }
+ final short button = 0 < pCount ? (short) ( pIDs[0] + 1 ) : (short)0;
+ doPointerEvent(enqueue, wait, pTypes, eventType, modifiers, actionIdx, pIDs, button,
+ pX, pY, pPressure, maxPressure, rotationXYZ, rotationScale);
}
- //
- // MouseListener/Event Support
- //
- public void sendMouseEvent(int eventType, int modifiers,
- int x, int y, int button, int rotation) {
- doMouseEvent(false, false, eventType, modifiers, x, y, button, rotation);
- }
- public void enqueueMouseEvent(boolean wait, int eventType, int modifiers,
- int x, int y, int button, int rotation) {
- doMouseEvent(true, wait, eventType, modifiers, x, y, button, rotation);
- }
-
- protected void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers,
- int x, int y, int button, int rotation) {
- if(eventType == MouseEvent.EVENT_MOUSE_ENTERED ||
- eventType == MouseEvent.EVENT_MOUSE_EXITED) {
- if(eventType == MouseEvent.EVENT_MOUSE_EXITED && x==-1 && y==-1) {
- x = lastMousePosition.getX();
- y = lastMousePosition.getY();
- }
- // clip coordinates to window dimension
- x = Math.min(Math.max(x, 0), getWidth()-1);
- y = Math.min(Math.max(y, 0), getHeight()-1);
- mouseInWindow = eventType == MouseEvent.EVENT_MOUSE_ENTERED;
- lastMousePressed=0; // clear state
- mouseButtonPressed=0; // clear state
- }
- if(x<0||y<0||x>=getWidth()||y>=getHeight()) {
+ /**
+ * Send multiple-pointer event either to be directly consumed or to be enqueued.
+ * <p>
+ * Pointer/Mouse Processing Pass 1 (Pass 2 is performed in {@link #consumePointerEvent(MouseEvent)}.
+ * </p>
+ * <p>
+ * Usually directly called by event source to enqueue and process event.
+ * </p>
+ * <p>
+ * The index for the element of multiple-pointer arrays represents the pointer which triggered the event
+ * is passed via <i>actionIdx</i>.
+ * </p>
+ * <p>
+ * <ul>
+ * <li>Determine ENTERED/EXITED state</li>
+ * <li>Remove redundant move/drag events</li>
+ * <li>Reset states if applicable</li>
+ * <li>Drop exterior events</li>
+ * <li>Determine CLICK COUNT</li>
+ * <li>Ignore sent CLICKED</li>
+ * <li>Track buttonPressed incl. buttonPressedMask</li>
+ * <li>Synthesize DRAGGED event (from MOVED if pointer is pressed)</li>
+ * </ul>
+ * </p>
+ *
+ * @param enqueue if true, event will be {@link #enqueueEvent(boolean, NEWTEvent) enqueued},
+ * otherwise {@link #consumeEvent(NEWTEvent) consumed} directly.
+ * @param wait if true wait until {@link #consumeEvent(NEWTEvent) consumed}.
+ * @param pTypes {@link MouseEvent.PointerType} for each pointer (multiple pointer)
+ * @param eventType
+ * @param modifiers
+ * @param pActionIdx index of multiple-pointer arrays representing the pointer which triggered the event
+ * @param pID Pointer ID for each pointer (multiple pointer). We assume consecutive pointerIDs starting w/ 0.
+ * @param button Corresponding mouse-button, a button of 0 denotes no activity, i.e. {@link PointerType#Mouse} move.
+ * @param pX X-axis for each pointer (multiple pointer)
+ * @param pY Y-axis for each pointer (multiple pointer)
+ * @param pPressure Pressure for each pointer (multiple pointer)
+ * @param maxPressure Maximum pointer pressure for all pointer
+ */
+ public final void doPointerEvent(final boolean enqueue, final boolean wait,
+ final PointerType[] pTypes, final short eventType, int modifiers,
+ final int pActionIdx, final short[] pID, final short buttonIn, final int[] pX, final int[] pY,
+ final float[] pPressure, final float maxPressure, final float[] rotationXYZ, final float rotationScale) {
+ final long when = System.currentTimeMillis();
+ final int pCount = pTypes.length;
+
+ if( 0 > pActionIdx || pActionIdx >= pCount) {
+ throw new IllegalArgumentException("actionIdx out of bounds [0.."+(pCount-1)+"]");
+ }
+ if( 0 < pActionIdx ) {
+ // swap values to make idx 0 the triggering pointer
+ {
+ final PointerType aType = pTypes[pActionIdx];
+ pTypes[pActionIdx] = pTypes[0];
+ pTypes[0] = aType;
+ }
+ {
+ final short s = pID[pActionIdx];
+ pID[pActionIdx] = pID[0];
+ pID[0] = s;
+ }
+ {
+ int s = pX[pActionIdx];
+ pX[pActionIdx] = pX[0];
+ pX[0] = s;
+ s = pY[pActionIdx];
+ pY[pActionIdx] = pY[0];
+ pY[0] = s;
+ }
+ {
+ final float aPress = pPressure[pActionIdx];
+ pPressure[pActionIdx] = pPressure[0];
+ pPressure[0] = aPress;
+ }
+ }
+ final short button;
+ {
+ // validate button
+ if( 0 <= buttonIn && buttonIn <= com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ) { // we allow button==0 for no button, i.e. mouse-ptr move
+ button = buttonIn;
+ } else {
+ button = com.jogamp.newt.event.MouseEvent.BUTTON1;
+ }
+ }
+
+ //
+ // - Determine ENTERED/EXITED state
+ // - Remove redundant move/drag events
+ // - Reset states if applicable
+ //
+ int x = pX[0];
+ int y = pY[0];
+ final boolean insideSurface = x >= 0 && y >= 0 && x < getSurfaceWidth() && y < getSurfaceHeight();
+ final Point movePositionP0 = pState1.getMovePosition(pID[0]);
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_EXITED:
+ if( pState1.dragging ) {
+ // Drop mouse EXIT if dragging, i.e. due to exterior dragging outside of window.
+ // NOTE-1: X11 produces the 'premature' EXIT, however it also produces 'EXIT' after exterior dragging!
+ // NOTE-2: consumePointerEvent(MouseEvent) will synthesize a missing EXIT event!
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("doPointerEvent: drop "+MouseEvent.getEventTypeString(eventType)+" due to dragging: "+pState1);
+ }
+ return;
+ }
+ if( null != movePositionP0 ) {
+ if( x==-1 && y==-1 ) {
+ x = movePositionP0.getX();
+ y = movePositionP0.getY();
+ }
+ movePositionP0.set(0, 0);
+ }
+ // Fall through intended!
+
+ case MouseEvent.EVENT_MOUSE_ENTERED:
+ if( eventType == MouseEvent.EVENT_MOUSE_ENTERED ) {
+ pState1.insideSurface = true;
+ pState1.exitSent = false;
+ } else {
+ pState1.insideSurface = false;
+ pState1.exitSent = true;
+ }
+ pState1.clearButton();
+ if( pTypes[0] != PointerType.Mouse ) {
+ // Drop !MOUSE ENTER/EXIT Events - Safeguard for non compliant implementations only.
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("doPointerEvent: drop "+MouseEvent.getEventTypeString(eventType)+" due to !Mouse but "+pTypes[0]+": "+pState1);
+ }
+ return;
+ }
+ // clip coordinates to window dimension
+ x = Math.min(Math.max(x, 0), getSurfaceWidth()-1);
+ y = Math.min(Math.max(y, 0), getSurfaceHeight()-1);
+ break;
+
+ case MouseEvent.EVENT_MOUSE_MOVED:
+ case MouseEvent.EVENT_MOUSE_DRAGGED:
+ if( null != movePositionP0 ) {
+ if( movePositionP0.getX() == x && movePositionP0.getY() == y ) {
+ // Drop same position
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("doPointerEvent: drop "+MouseEvent.getEventTypeString(eventType)+" w/ same position: "+movePositionP0+", "+pState1);
+ }
+ return;
+ }
+ movePositionP0.set(x, y);
+ }
+
+ // Fall through intended !
+
+ default:
+ if( pState1.insideSurface != insideSurface ) {
+ // ENTER/EXIT!
+ pState1.insideSurface = insideSurface;
+ if( insideSurface ) {
+ pState1.exitSent = false;
+ }
+ pState1.clearButton();
+ }
+ }
+
+ //
+ // Drop exterior events if not dragging pointer and not EXIT event
+ // Safeguard for non compliant implementations!
+ //
+ if( !pState1.dragging && !insideSurface && MouseEvent.EVENT_MOUSE_EXITED != eventType ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("doPointerEvent: drop: "+MouseEvent.getEventTypeString(eventType)+
+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+movePositionP0+", insideWindow "+insideSurface+", "+pState1);
+ }
return; // .. invalid ..
}
if(DEBUG_MOUSE_EVENT) {
- System.err.println("doMouseEvent: enqueue "+enqueue+", wait "+wait+", "+MouseEvent.getEventTypeString(eventType)+
- ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+lastMousePosition);
- }
- long when = System.currentTimeMillis();
- MouseEvent eEntered = null;
- if(eventType == MouseEvent.EVENT_MOUSE_MOVED) {
- if(!mouseInWindow) {
- mouseInWindow = true;
- eEntered = new MouseEvent(MouseEvent.EVENT_MOUSE_ENTERED, this, when,
- modifiers, x, y, lastMouseClickCount, button, 0);
- lastMousePressed=0; // clear state
- mouseButtonPressed=0; // clear state
- } else if(lastMousePosition.getX() == x && lastMousePosition.getY()==y) {
+ System.err.println("doPointerEvent: enqueue "+enqueue+", wait "+wait+", "+MouseEvent.getEventTypeString(eventType)+
+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+movePositionP0+", "+pState1);
+ }
+
+ final int buttonMask = InputEvent.getButtonMask(button);
+ modifiers |= buttonMask; // Always add current button to modifier mask (Bug 571)
+ modifiers |= pState1.buttonPressedMask; // Always add currently pressed mouse buttons to modifier mask
+
+ if( isPointerConfined() ) {
+ modifiers |= InputEvent.CONFINED_MASK;
+ }
+ if( !isPointerVisible() ) {
+ modifiers |= InputEvent.INVISIBLE_MASK;
+ }
+
+ pX[0] = x;
+ pY[0] = y;
+
+ //
+ // - Determine CLICK COUNT
+ // - Ignore sent CLICKED
+ // - Track buttonPressed incl. buttonPressedMask
+ // - Synthesize DRAGGED event (from MOVED if pointer is pressed)
+ //
+ final MouseEvent e;
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_CLICKED:
+ e = null;
+ break;
+
+ case MouseEvent.EVENT_MOUSE_PRESSED:
+ if( 0 >= pPressure[0] ) {
+ pPressure[0] = maxPressure;
+ }
+ pState1.buttonPressedMask |= buttonMask;
+ if( 1 == pCount ) {
+ if( when - pState1.lastButtonPressTime < MouseEvent.getClickTimeout() ) {
+ pState1.lastButtonClickCount++;
+ } else {
+ pState1.lastButtonClickCount=(short)1;
+ }
+ pState1.lastButtonPressTime = when;
+ pState1.buttonPressed = button;
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, pState1.lastButtonClickCount, rotationXYZ, rotationScale);
+ } else {
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, (short)1, rotationXYZ, rotationScale);
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ pState1.buttonPressedMask &= ~buttonMask;
+ if( 1 == pCount ) {
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, pState1.lastButtonClickCount, rotationXYZ, rotationScale);
+ if( when - pState1.lastButtonPressTime >= MouseEvent.getClickTimeout() ) {
+ pState1.lastButtonClickCount = (short)0;
+ pState1.lastButtonPressTime = 0;
+ }
+ pState1.buttonPressed = 0;
+ pState1.dragging = false;
+ } else {
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, (short)1, rotationXYZ, rotationScale);
+ if( 0 == pState1.buttonPressedMask ) {
+ pState1.clearButton();
+ }
+ }
+ if( null != movePositionP0 ) {
+ movePositionP0.set(0, 0);
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_MOVED:
+ if ( 0 != pState1.buttonPressedMask ) { // any button or pointer move -> drag
+ e = new MouseEvent(MouseEvent.EVENT_MOUSE_DRAGGED, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, pState1.buttonPressed, (short)1, rotationXYZ, rotationScale);
+ pState1.dragging = true;
+ } else {
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, (short)0, rotationXYZ, rotationScale);
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_DRAGGED:
+ if( 0 >= pPressure[0] ) {
+ pPressure[0] = maxPressure;
+ }
+ pState1.dragging = true;
+ // Fall through intended!
+ default:
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, (short)0, rotationXYZ, rotationScale);
+ }
+ doEvent(enqueue, wait, e); // actual mouse event
+ }
+
+ private static int step(final int lower, final int edge, final int value) {
+ return value < edge ? lower : value;
+ }
+
+ /**
+ * Consume the {@link MouseEvent}.
+ * <p>
+ * Pointer/Mouse Processing Pass 2 (Pass 1 is performed in {@link #doPointerEvent(boolean, boolean, PointerType[], short, int, int, short[], short, int[], int[], float[], float, float[], float)}).
+ * </p>
+ * <p>
+ * Invoked before dispatching the dequeued event.
+ * </p>
+ * <p>
+ * <ul>
+ * <li>Validate</li>
+ * <li>Handle gestures</li>
+ * <li>Synthesize events [ENTERED, EXIT, CLICK] and gestures.</li>
+ * <li>Drop exterior events</li>
+ * <li>Dispatch event to listener</li>
+ * </ul>
+ * </p>
+ */
+ protected void consumePointerEvent(MouseEvent pe) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent.in: "+pe+", "+pState0+", pos "+pe.getX()+"/"+pe.getY()+", win["+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+
+ "], pixel["+getSurfaceWidth()+"x"+getSurfaceHeight()+"]");
+ }
+
+ //
+ // - Determine ENTERED/EXITED state
+ // - Synthesize ENTERED and EXIT event
+ // - Reset states if applicable
+ //
+ final long when = pe.getWhen();
+ final int eventType = pe.getEventType();
+ final boolean insideSurface;
+ boolean eExitAllowed = false;
+ MouseEvent eEntered = null, eExited = null;
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_EXITED:
+ if( pState0.exitSent || pState0.dragging ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent: drop "+(pState0.exitSent?"already sent":"due to dragging")+": "+pe+", "+pState0);
+ }
+ return;
+ }
+ // Fall through intended !
+ case MouseEvent.EVENT_MOUSE_ENTERED:
+ // clip coordinates to window dimension
+ // final int pe_x = Math.min(Math.max(pe.getX(), 0), getSurfaceWidth()-1);
+ // final int pe_y = Math.min(Math.max(pe.getY(), 0), getSurfaceHeight()-1);
+ pState0.clearButton();
+ if( eventType == MouseEvent.EVENT_MOUSE_ENTERED ) {
+ insideSurface = true;
+ pState0.insideSurface = true;
+ pState0.exitSent = false;
+ pState0.dragging = false;
+ } else {
+ insideSurface = false;
+ pState0.insideSurface = false;
+ pState0.exitSent = true;
+ }
+ break;
+
+ case MouseEvent.EVENT_MOUSE_MOVED:
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ if( 1 >= pe.getButtonDownCount() ) { // MOVE or RELEASE last button
+ eExitAllowed = !pState0.exitSent;
+ pState0.dragging = false;
+ }
+ // Fall through intended !
+
+ default:
+ final int pe_x = pe.getX();
+ final int pe_y = pe.getY();
+ insideSurface = pe_x >= 0 && pe_y >= 0 && pe_x < getSurfaceWidth() && pe_y < getSurfaceHeight();
+ if( pe.getPointerType(0) == PointerType.Mouse ) {
+ if( !pState0.insideSurface && insideSurface ) {
+ // ENTER .. use clipped coordinates
+ eEntered = new MouseEvent(MouseEvent.EVENT_MOUSE_ENTERED, pe.getSource(), pe.getWhen(), pe.getModifiers(),
+ Math.min(Math.max(pe_x, 0), getSurfaceWidth()-1),
+ Math.min(Math.max(pe_y, 0), getSurfaceHeight()-1),
+ (short)0, (short)0, pe.getRotation(), pe.getRotationScale());
+ pState0.exitSent = false;
+ } else if( !insideSurface && eExitAllowed ) {
+ // EXIT .. use clipped coordinates
+ eExited = new MouseEvent(MouseEvent.EVENT_MOUSE_EXITED, pe.getSource(), pe.getWhen(), pe.getModifiers(),
+ Math.min(Math.max(pe_x, 0), getSurfaceWidth()-1),
+ Math.min(Math.max(pe_y, 0), getSurfaceHeight()-1),
+ (short)0, (short)0, pe.getRotation(), pe.getRotationScale());
+ pState0.exitSent = true;
+ }
+ }
+ if( pState0.insideSurface != insideSurface || null != eEntered || null != eExited) {
+ pState0.clearButton();
+ }
+ pState0.insideSurface = insideSurface;
+ }
+ if( null != eEntered ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent.send.0: "+eEntered+", "+pState0);
+ }
+ dispatchMouseEvent(eEntered);
+ } else if( DEBUG_MOUSE_EVENT && !insideSurface ) {
+ System.err.println("INFO consumePointerEvent.exterior: "+pState0+", "+pe);
+ }
+
+ //
+ // Handle Default Gestures
+ //
+ if( defaultGestureHandlerEnabled &&
+ pe.getPointerType(0).getPointerClass() == MouseEvent.PointerClass.Onscreen )
+ {
+ if( null == gesture2PtrTouchScroll ) {
+ final int scaledScrollSlop;
+ final int scaledDoubleTapSlop;
+ final MonitorDevice monitor = getMainMonitor();
+ if ( null != monitor ) {
+ final DimensionImmutable mm = monitor.getSizeMM();
+ final float pixWPerMM = (float)monitor.getCurrentMode().getRotatedWidth() / (float)mm.getWidth();
+ final float pixHPerMM = (float)monitor.getCurrentMode().getRotatedHeight() / (float)mm.getHeight();
+ final float pixPerMM = Math.min(pixHPerMM, pixWPerMM);
+ scaledScrollSlop = Math.round(DoubleTapScrollGesture.SCROLL_SLOP_MM * pixPerMM);
+ scaledDoubleTapSlop = Math.round(DoubleTapScrollGesture.DOUBLE_TAP_SLOP_MM * pixPerMM);
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent.gscroll: scrollSlop "+scaledScrollSlop+", doubleTapSlop "+scaledDoubleTapSlop+", pixPerMM "+pixPerMM+", "+monitor+", "+pState0);
+ }
+ } else {
+ scaledScrollSlop = DoubleTapScrollGesture.SCROLL_SLOP_PIXEL;
+ scaledDoubleTapSlop = DoubleTapScrollGesture.DOUBLE_TAP_SLOP_PIXEL;
+ }
+ gesture2PtrTouchScroll = new DoubleTapScrollGesture(step(DoubleTapScrollGesture.SCROLL_SLOP_PIXEL, DoubleTapScrollGesture.SCROLL_SLOP_PIXEL/2, scaledScrollSlop),
+ step(DoubleTapScrollGesture.DOUBLE_TAP_SLOP_PIXEL, DoubleTapScrollGesture.DOUBLE_TAP_SLOP_PIXEL/2, scaledDoubleTapSlop));
+ }
+ if( gesture2PtrTouchScroll.process(pe) ) {
+ pe = (MouseEvent) gesture2PtrTouchScroll.getGestureEvent();
+ gesture2PtrTouchScroll.clear(false);
if(DEBUG_MOUSE_EVENT) {
- System.err.println("doMouseEvent: skip EVENT_MOUSE_MOVED w/ same position: "+lastMousePosition);
+ System.err.println("consumePointerEvent.gscroll: "+pe+", "+pState0);
+ }
+ dispatchMouseEvent(pe);
+ return;
+ }
+ if( gesture2PtrTouchScroll.isWithinGesture() ) {
+ return; // within gesture .. need more input ..
+ }
+ }
+ //
+ // Handle Custom Gestures
+ //
+ {
+ final int pointerGestureHandlerCount = pointerGestureHandler.size();
+ if( pointerGestureHandlerCount > 0 ) {
+ boolean withinGesture = false;
+ for(int i = 0; !pe.isConsumed() && i < pointerGestureHandlerCount; i++ ) {
+ final GestureHandler gh = pointerGestureHandler.get(i);
+ if( gh.process(pe) ) {
+ final InputEvent ieG = gh.getGestureEvent();
+ gh.clear(false);
+ if( ieG instanceof MouseEvent ) {
+ dispatchMouseEvent((MouseEvent)ieG);
+ } else if( ieG instanceof GestureHandler.GestureEvent) {
+ final GestureHandler.GestureEvent ge = (GestureHandler.GestureEvent) ieG;
+ for(int j = 0; !ge.isConsumed() && j < gestureListeners.size(); j++ ) {
+ gestureListeners.get(j).gestureDetected(ge);
+ }
+ }
+ return;
+ }
+ withinGesture |= gh.isWithinGesture();
+ }
+ if( withinGesture ) {
+ return;
}
- return; // skip same position
}
- lastMousePosition.setX(x);
- lastMousePosition.setY(y);
- }
- if( 0 > button || button > MouseEvent.BUTTON_NUMBER ) {
- throw new NativeWindowException("Invalid mouse button number" + button);
}
- // Fixes Bug 571: X11 behavior, where the PRESSED button is not included in the native mask.
- modifiers |= InputEvent.getButtonMask(button);
+ //
+ // - Synthesize mouse CLICKED
+ // - Ignore sent CLICKED
+ //
MouseEvent eClicked = null;
- MouseEvent e = null;
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_PRESSED:
+ if( 1 == pe.getPointerCount() ) {
+ pState0.lastButtonPressTime = when;
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ if( 1 == pe.getPointerCount() && when - pState0.lastButtonPressTime < MouseEvent.getClickTimeout() ) {
+ eClicked = pe.createVariant(MouseEvent.EVENT_MOUSE_CLICKED);
+ } else {
+ pState0.lastButtonPressTime = 0;
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_CLICKED:
+ // ignore - synthesized here ..
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent: drop recv'ed (synth here) "+pe+", "+pState0);
+ }
+ pe = null;
+ break;
- if(isPointerConfined()) {
- modifiers |= InputEvent.CONFINED_MASK;
- }
- if(!isPointerVisible()) {
- modifiers |= InputEvent.INVISIBLE_MASK;
+ case MouseEvent.EVENT_MOUSE_DRAGGED:
+ pState0.dragging = true;
+ break;
}
-
- if(MouseEvent.EVENT_MOUSE_PRESSED==eventType) {
- if(when-lastMousePressed<MouseEvent.getClickTimeout()) {
- lastMouseClickCount++;
- } else {
- lastMouseClickCount=1;
- }
- lastMousePressed=when;
- mouseButtonPressed=button;
- e = new MouseEvent(eventType, this, when,
- modifiers, x, y, lastMouseClickCount, button, 0);
- } else if(MouseEvent.EVENT_MOUSE_RELEASED==eventType) {
- e = new MouseEvent(eventType, this, when,
- modifiers, x, y, lastMouseClickCount, button, 0);
- if(when-lastMousePressed<MouseEvent.getClickTimeout()) {
- eClicked = new MouseEvent(MouseEvent.EVENT_MOUSE_CLICKED, this, when,
- modifiers, x, y, lastMouseClickCount, button, 0);
- } else {
- lastMouseClickCount=0;
- lastMousePressed=0;
- }
- mouseButtonPressed=0;
- } else if(MouseEvent.EVENT_MOUSE_MOVED==eventType) {
- if (mouseButtonPressed>0) {
- e = new MouseEvent(MouseEvent.EVENT_MOUSE_DRAGGED, this, when,
- modifiers, x, y, 1, mouseButtonPressed, 0);
- } else {
- e = new MouseEvent(eventType, this, when,
- modifiers, x, y, 0, button, 0);
+
+ if( null != pe ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent.send.1: "+pe+", "+pState0);
}
- } else if(MouseEvent.EVENT_MOUSE_WHEEL_MOVED==eventType) {
- e = new MouseEvent(eventType, this, when, modifiers, x, y, 0, button, rotation);
- } else {
- e = new MouseEvent(eventType, this, when, modifiers, x, y, 0, button, 0);
+ dispatchMouseEvent(pe); // actual mouse event
}
- if(null!=eEntered) {
+ if( null != eClicked ) {
if(DEBUG_MOUSE_EVENT) {
- System.err.println("doMouseEvent: synthesized MOUSE_ENTERED event: "+eEntered);
+ System.err.println("consumePointerEvent.send.2: "+eClicked+", "+pState0);
}
- doEvent(enqueue, wait, eEntered);
+ dispatchMouseEvent(eClicked);
}
- doEvent(enqueue, wait, e); // actual mouse event
- if(null!=eClicked) {
+ if( null != eExited ) {
if(DEBUG_MOUSE_EVENT) {
- System.err.println("doMouseEvent: synthesized MOUSE_CLICKED event: "+eClicked);
+ System.err.println("consumePointerEvent.send.3: "+eExited+", "+pState0);
}
- doEvent(enqueue, wait, eClicked);
+ dispatchMouseEvent(eExited);
}
}
-
- public void addMouseListener(MouseListener l) {
+ @Override
+ public final void addMouseListener(final MouseListener l) {
addMouseListener(-1, l);
}
- public void addMouseListener(int index, MouseListener l) {
+ @Override
+ public final void addMouseListener(int index, final MouseListener l) {
if(l == null) {
return;
}
@SuppressWarnings("unchecked")
+ final
ArrayList<MouseListener> clonedListeners = (ArrayList<MouseListener>) mouseListeners.clone();
- if(0>index) {
- index = clonedListeners.size();
+ if(0>index) {
+ index = clonedListeners.size();
}
clonedListeners.add(index, l);
mouseListeners = clonedListeners;
}
- public void removeMouseListener(MouseListener l) {
+ @Override
+ public final void removeMouseListener(final MouseListener l) {
if (l == null) {
return;
}
@SuppressWarnings("unchecked")
+ final
ArrayList<MouseListener> clonedListeners = (ArrayList<MouseListener>) mouseListeners.clone();
clonedListeners.remove(l);
mouseListeners = clonedListeners;
}
- public MouseListener getMouseListener(int index) {
+ @Override
+ public final MouseListener getMouseListener(int index) {
@SuppressWarnings("unchecked")
+ final
ArrayList<MouseListener> clonedListeners = (ArrayList<MouseListener>) mouseListeners.clone();
- if(0>index) {
- index = clonedListeners.size()-1;
+ if(0>index) {
+ index = clonedListeners.size()-1;
}
return clonedListeners.get(index);
}
- public MouseListener[] getMouseListeners() {
+ @Override
+ public final MouseListener[] getMouseListeners() {
return mouseListeners.toArray(new MouseListener[mouseListeners.size()]);
}
- protected void consumeMouseEvent(MouseEvent e) {
- if(DEBUG_MOUSE_EVENT) {
- System.err.println("consumeMouseEvent: event: "+e);
+ @Override
+ public final void setDefaultGesturesEnabled(final boolean enable) {
+ defaultGestureHandlerEnabled = enable;
+ }
+ @Override
+ public final boolean areDefaultGesturesEnabled() {
+ return defaultGestureHandlerEnabled;
+ }
+
+ @Override
+ public final void addGestureHandler(final GestureHandler gh) {
+ addGestureHandler(-1, gh);
+ }
+ @Override
+ public final void addGestureHandler(int index, final GestureHandler gh) {
+ if(gh == null) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ final
+ ArrayList<GestureHandler> cloned = (ArrayList<GestureHandler>) pointerGestureHandler.clone();
+ if(0>index) {
+ index = cloned.size();
+ }
+ cloned.add(index, gh);
+ pointerGestureHandler = cloned;
+ }
+ @Override
+ public final void removeGestureHandler(final GestureHandler gh) {
+ if (gh == null) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ final
+ ArrayList<GestureHandler> cloned = (ArrayList<GestureHandler>) pointerGestureHandler.clone();
+ cloned.remove(gh);
+ pointerGestureHandler = cloned;
+ }
+ @Override
+ public final void addGestureListener(final GestureHandler.GestureListener gl) {
+ addGestureListener(-1, gl);
+ }
+ @Override
+ public final void addGestureListener(int index, final GestureHandler.GestureListener gl) {
+ if(gl == null) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ final
+ ArrayList<GestureHandler.GestureListener> cloned = (ArrayList<GestureHandler.GestureListener>) gestureListeners.clone();
+ if(0>index) {
+ index = cloned.size();
}
- boolean consumed = false;
- for(int i = 0; !consumed && i < mouseListeners.size(); i++ ) {
- MouseListener l = mouseListeners.get(i);
+ cloned.add(index, gl);
+ gestureListeners = cloned;
+ }
+ @Override
+ public final void removeGestureListener(final GestureHandler.GestureListener gl) {
+ if (gl == null) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ final
+ ArrayList<GestureHandler.GestureListener> cloned = (ArrayList<GestureHandler.GestureListener>) gestureListeners.clone();
+ cloned.remove(gl);
+ gestureListeners= cloned;
+ }
+
+ private final void dispatchMouseEvent(final MouseEvent e) {
+ for(int i = 0; !e.isConsumed() && i < mouseListeners.size(); i++ ) {
+ final MouseListener l = mouseListeners.get(i);
switch(e.getEventType()) {
case MouseEvent.EVENT_MOUSE_CLICKED:
l.mouseClicked(e);
@@ -2159,46 +3432,83 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
default:
throw new NativeWindowException("Unexpected mouse event type " + e.getEventType());
}
- consumed = InputEvent.consumedTag == e.getAttachment();
}
}
//
// KeyListener/Event Support
//
- public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
- consumeKeyEvent(new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) );
+ private static final int keyTrackingRange = 255;
+ private final IntBitfield keyPressedState = new IntBitfield( keyTrackingRange + 1 );
+
+ protected final boolean isKeyCodeTracked(final short keyCode) {
+ return ( 0xFFFF & keyCode ) <= keyTrackingRange;
}
- public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
- enqueueEvent(wait, new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) );
+ /**
+ * @param keyCode the keyCode to set pressed state
+ * @param pressed true if pressed, otherwise false
+ * @return the previus pressed value
+ */
+ protected final boolean setKeyPressed(final short keyCode, final boolean pressed) {
+ final int v = 0xFFFF & keyCode;
+ if( v <= keyTrackingRange ) {
+ return keyPressedState.put(v, pressed);
+ }
+ return false;
+ }
+ /**
+ * @param keyCode the keyCode to test pressed state
+ * @return true if pressed, otherwise false
+ */
+ protected final boolean isKeyPressed(final short keyCode) {
+ final int v = 0xFFFF & keyCode;
+ if( v <= keyTrackingRange ) {
+ return keyPressedState.get(v);
+ }
+ return false;
}
- public void addKeyListener(KeyListener l) {
- addKeyListener(-1, l);
+ public void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) {
+ // Always add currently pressed mouse buttons to modifier mask
+ consumeKeyEvent( KeyEvent.create(eventType, this, System.currentTimeMillis(), modifiers | pState1.buttonPressedMask, keyCode, keySym, keyChar) );
+ }
+
+ public void enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) {
+ // Always add currently pressed mouse buttons to modifier mask
+ enqueueEvent(wait, KeyEvent.create(eventType, this, System.currentTimeMillis(), modifiers | pState1.buttonPressedMask, keyCode, keySym, keyChar) );
}
- public final void setKeyboardVisible(boolean visible) {
+ @Override
+ public final void setKeyboardVisible(final boolean visible) {
if(isNativeValid()) {
// We don't skip the impl. if it seems that there is no state change,
- // since we cannot assume the impl. reliably gives us it's current state.
- final boolean n = setKeyboardVisibleImpl(visible);
+ // since we cannot assume the impl. reliably gives us it's current state.
+ final boolean ok = setKeyboardVisibleImpl(visible);
if(DEBUG_IMPLEMENTATION || DEBUG_KEY_EVENT) {
- System.err.println("setKeyboardVisible(native): visible "+keyboardVisible+" -> "+visible +" -> "+n);
+ System.err.println("setKeyboardVisible(native): visible "+keyboardVisible+" -- op[visible:"+visible +", ok "+ok+"] -> "+(visible && ok));
}
- keyboardVisible = n;
+ keyboardVisibilityChanged( visible && ok );
} else {
- keyboardVisible = visible; // earmark for creation
+ keyboardVisibilityChanged( visible ); // earmark for creation
}
}
+ @Override
public final boolean isKeyboardVisible() {
return keyboardVisible;
- }
- protected boolean setKeyboardVisibleImpl(boolean visible) {
+ }
+ /**
+ * Returns <code>true</code> if operation was successful, otherwise <code>false</code>.
+ * <p>
+ * We assume that a failed invisible operation is due to an already invisible keyboard,
+ * hence even if an invisible operation failed, the keyboard is considered invisible!
+ * </p>
+ */
+ protected boolean setKeyboardVisibleImpl(final boolean visible) {
return false; // nop
}
/** Triggered by implementation's WM events to update the virtual on-screen keyboard's visibility state. */
- protected void keyboardVisibilityChanged(boolean visible) {
+ protected void keyboardVisibilityChanged(final boolean visible) {
if(keyboardVisible != visible) {
if(DEBUG_IMPLEMENTATION || DEBUG_KEY_EVENT) {
System.err.println("keyboardVisibilityChanged: "+keyboardVisible+" -> "+visible);
@@ -2207,44 +3517,56 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
protected boolean keyboardVisible = false;
-
- public void addKeyListener(int index, KeyListener l) {
+
+ @Override
+ public final void addKeyListener(final KeyListener l) {
+ addKeyListener(-1, l);
+ }
+
+ @Override
+ public final void addKeyListener(int index, final KeyListener l) {
if(l == null) {
return;
}
@SuppressWarnings("unchecked")
+ final
ArrayList<KeyListener> clonedListeners = (ArrayList<KeyListener>) keyListeners.clone();
- if(0>index) {
+ if(0>index) {
index = clonedListeners.size();
}
clonedListeners.add(index, l);
keyListeners = clonedListeners;
}
- public void removeKeyListener(KeyListener l) {
+ @Override
+ public final void removeKeyListener(final KeyListener l) {
if (l == null) {
return;
}
@SuppressWarnings("unchecked")
+ final
ArrayList<KeyListener> clonedListeners = (ArrayList<KeyListener>) keyListeners.clone();
clonedListeners.remove(l);
keyListeners = clonedListeners;
}
- public KeyListener getKeyListener(int index) {
+ @Override
+ public final KeyListener getKeyListener(int index) {
@SuppressWarnings("unchecked")
+ final
ArrayList<KeyListener> clonedListeners = (ArrayList<KeyListener>) keyListeners.clone();
- if(0>index) {
+ if(0>index) {
index = clonedListeners.size()-1;
}
return clonedListeners.get(index);
}
- public KeyListener[] getKeyListeners() {
+ @Override
+ public final KeyListener[] getKeyListeners() {
return keyListeners.toArray(new KeyListener[keyListeners.size()]);
}
- private final boolean propagateKeyEvent(KeyEvent e, KeyListener l) {
+ private final boolean propagateKeyEvent(final KeyEvent e, final KeyListener l) {
switch(e.getEventType()) {
case KeyEvent.EVENT_KEY_PRESSED:
l.keyPressed(e);
@@ -2252,92 +3574,101 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
case KeyEvent.EVENT_KEY_RELEASED:
l.keyReleased(e);
break;
- case KeyEvent.EVENT_KEY_TYPED:
- l.keyTyped(e);
- break;
default:
throw new NativeWindowException("Unexpected key event type " + e.getEventType());
}
- return InputEvent.consumedTag == e.getAttachment();
+ return e.isConsumed();
}
-
- protected void consumeKeyEvent(KeyEvent e) {
- boolean consumed;
- if(null != keyboardFocusHandler) {
- consumed = propagateKeyEvent(e, keyboardFocusHandler);
+
+ protected void consumeKeyEvent(final KeyEvent e) {
+ boolean consumedE = false;
+ if( null != keyboardFocusHandler && !e.isAutoRepeat() ) {
+ consumedE = propagateKeyEvent(e, keyboardFocusHandler);
if(DEBUG_KEY_EVENT) {
- System.err.println("consumeKeyEvent: "+e+", keyboardFocusHandler consumed: "+consumed);
+ if( consumedE ) {
+ System.err.println("consumeKeyEvent(kfh): "+e+", consumed: "+consumedE);
+ }
+ }
+ }
+ if( !consumedE ) {
+ for(int i = 0; !consumedE && i < keyListeners.size(); i++ ) {
+ consumedE = propagateKeyEvent(e, keyListeners.get(i));
}
- } else {
- consumed = false;
if(DEBUG_KEY_EVENT) {
- System.err.println("consumeKeyEvent: "+e);
+ System.err.println("consumeKeyEvent(usr): "+e+", consumed: "+consumedE);
}
}
- for(int i = 0; !consumed && i < keyListeners.size(); i++ ) {
- consumed = propagateKeyEvent(e, keyListeners.get(i));
- }
}
//
// WindowListener/Event Support
//
- public void sendWindowEvent(int eventType) {
- consumeWindowEvent( new WindowEvent(eventType, this, System.currentTimeMillis()) );
+ @Override
+ public final void sendWindowEvent(final int eventType) {
+ consumeWindowEvent( new WindowEvent((short)eventType, this, System.currentTimeMillis()) );
}
- public void enqueueWindowEvent(boolean wait, int eventType) {
- enqueueEvent( wait, new WindowEvent(eventType, this, System.currentTimeMillis()) );
+ public final void enqueueWindowEvent(final boolean wait, final int eventType) {
+ enqueueEvent( wait, new WindowEvent((short)eventType, this, System.currentTimeMillis()) );
}
- public void addWindowListener(WindowListener l) {
+ @Override
+ public final void addWindowListener(final WindowListener l) {
addWindowListener(-1, l);
}
- public void addWindowListener(int index, WindowListener l)
+ @Override
+ public final void addWindowListener(int index, final WindowListener l)
throws IndexOutOfBoundsException
{
if(l == null) {
return;
}
@SuppressWarnings("unchecked")
+ final
ArrayList<WindowListener> clonedListeners = (ArrayList<WindowListener>) windowListeners.clone();
- if(0>index) {
- index = clonedListeners.size();
+ if(0>index) {
+ index = clonedListeners.size();
}
clonedListeners.add(index, l);
windowListeners = clonedListeners;
}
- public final void removeWindowListener(WindowListener l) {
+ @Override
+ public final void removeWindowListener(final WindowListener l) {
if (l == null) {
return;
}
@SuppressWarnings("unchecked")
+ final
ArrayList<WindowListener> clonedListeners = (ArrayList<WindowListener>) windowListeners.clone();
clonedListeners.remove(l);
windowListeners = clonedListeners;
}
- public WindowListener getWindowListener(int index) {
+ @Override
+ public final WindowListener getWindowListener(int index) {
@SuppressWarnings("unchecked")
+ final
ArrayList<WindowListener> clonedListeners = (ArrayList<WindowListener>) windowListeners.clone();
- if(0>index) {
- index = clonedListeners.size()-1;
+ if(0>index) {
+ index = clonedListeners.size()-1;
}
return clonedListeners.get(index);
}
- public WindowListener[] getWindowListeners() {
+ @Override
+ public final WindowListener[] getWindowListeners() {
return windowListeners.toArray(new WindowListener[windowListeners.size()]);
}
- protected void consumeWindowEvent(WindowEvent e) {
+ protected void consumeWindowEvent(final WindowEvent e) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("consumeWindowEvent: "+e+", visible "+isVisible()+" "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
+ System.err.println("consumeWindowEvent: "+e+", visible "+isVisible()+" "+getX()+"/"+getY()+", win["+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+
+ "], pixel["+getSurfaceWidth()+"x"+getSurfaceHeight()+"]");
}
- for(int i = 0; i < windowListeners.size(); i++ ) {
- WindowListener l = windowListeners.get(i);
+ for(int i = 0; !e.isConsumed() && i < windowListeners.size(); i++ ) {
+ final WindowListener l = windowListeners.get(i);
switch(e.getEventType()) {
case WindowEvent.EVENT_WINDOW_RESIZED:
l.windowResized(e);
@@ -2361,7 +3692,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
l.windowRepaint((WindowUpdateEvent)e);
break;
default:
- throw
+ throw
new NativeWindowException("Unexpected window event type "
+ e.getEventType());
}
@@ -2369,13 +3700,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
/** Triggered by implementation's WM events to update the focus state. */
- protected void focusChanged(boolean defer, boolean focusGained) {
+ protected void focusChanged(final boolean defer, final boolean focusGained) {
if(brokenFocusChange || hasFocus != focusGained) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.focusChanged: ("+getThreadName()+"): (defer: "+defer+") "+this.hasFocus+" -> "+focusGained+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
}
hasFocus = focusGained;
- final int evt = focusGained ? WindowEvent.EVENT_WINDOW_GAINED_FOCUS : WindowEvent.EVENT_WINDOW_LOST_FOCUS ;
+ final int evt = focusGained ? WindowEvent.EVENT_WINDOW_GAINED_FOCUS : WindowEvent.EVENT_WINDOW_LOST_FOCUS ;
if(!defer) {
sendWindowEvent(evt);
} else {
@@ -2383,9 +3714,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
}
-
+
/** Triggered by implementation's WM events to update the visibility state. */
- protected void visibleChanged(boolean defer, boolean visible) {
+ protected final void visibleChanged(final boolean defer, final boolean visible) {
if(this.visible != visible) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.visibleChanged ("+getThreadName()+"): (defer: "+defer+") "+this.visible+" -> "+visible+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
@@ -2394,32 +3725,43 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- private boolean waitForVisible(boolean visible, boolean failFast) {
+ /** Returns -1 if failed, otherwise remaining time until {@link #TIMEOUT_NATIVEWINDOW}, maybe zero. */
+ private long waitForVisible(final boolean visible, final boolean failFast) {
return waitForVisible(visible, failFast, TIMEOUT_NATIVEWINDOW);
}
- private boolean waitForVisible(boolean visible, boolean failFast, long timeOut) {
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
- for(long sleep = timeOut; 0<sleep && this.visible != visible; sleep-=10 ) {
+ /** Returns -1 if failed, otherwise remaining time until <code>timeOut</code>, maybe zero. */
+ private long waitForVisible(final boolean visible, final boolean failFast, final long timeOut) {
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ display.dispatchMessagesNative(); // status up2date
+ long remaining;
+ for(remaining = timeOut; 0<remaining && this.visible != visible; remaining-=10 ) {
+ try { Thread.sleep(10); } catch (final InterruptedException ie) {}
display.dispatchMessagesNative(); // status up2date
- try { Thread.sleep(10); } catch (InterruptedException ie) {}
}
if(this.visible != visible) {
- final String msg = "Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+this.visible;
+ final String msg = "Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+this.visible;
if(failFast) {
throw new NativeWindowException(msg);
} else if (DEBUG_IMPLEMENTATION) {
System.err.println(msg);
+ Thread.dumpStack();
}
+ return -1;
+ } else if( 0 < remaining ){
+ return remaining;
+ } else {
+ return 0;
}
- return this.visible == visible;
}
- /** Triggered by implementation's WM events to update the client-area size w/o insets/decorations. */
- protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
+ /** Triggered by implementation's WM events to update the client-area size in window units w/o insets/decorations. */
+ protected void sizeChanged(final boolean defer, final int newWidth, final int newHeight, final boolean force) {
if(force || getWidth() != newWidth || getHeight() != newHeight) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.sizeChanged: ("+getThreadName()+"): (defer: "+defer+") force "+force+", "+getWidth()+"x"+getHeight()+" -> "+newWidth+"x"+newHeight+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+ System.err.println("Window.sizeChanged: ("+getThreadName()+"): (defer: "+defer+") force "+force+", "+
+ getWidth()+"x"+getHeight()+" -> "+newWidth+"x"+newHeight+
+ " - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
}
if(0>newWidth || 0>newHeight) {
throw new NativeWindowException("Illegal width or height "+newWidth+"x"+newHeight+" (must be >= 0)");
@@ -2434,20 +3776,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
}
-
- private boolean waitForSize(int w, int h, boolean failFast, long timeOut) {
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
- boolean reached = false;
- for(long sleep = timeOut; !reached && 0<sleep; sleep-=10 ) {
- if( w==getWidth() && h==getHeight() ) {
- // reached pos/size
- reached = true;
- } else {
- display.dispatchMessagesNative(); // status up2date
- try { Thread.sleep(10); } catch (InterruptedException ie) {}
- }
+
+ private boolean waitForSize(final int w, final int h, final boolean failFast, final long timeOut) {
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ display.dispatchMessagesNative(); // status up2date
+ long sleep;
+ for(sleep = timeOut; 0<sleep && w!=getWidth() && h!=getHeight(); sleep-=10 ) {
+ try { Thread.sleep(10); } catch (final InterruptedException ie) {}
+ display.dispatchMessagesNative(); // status up2date
}
- if(!reached) {
+ if(0 >= sleep) {
final String msg = "Size/Pos not reached as requested within "+timeOut+"ms : requested "+w+"x"+h+", is "+getWidth()+"x"+getHeight();
if(failFast) {
throw new NativeWindowException(msg);
@@ -2455,12 +3793,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
System.err.println(msg);
Thread.dumpStack();
}
+ return false;
+ } else {
+ return true;
}
- return reached;
}
-
- /** Triggered by implementation's WM events to update the position. */
- protected void positionChanged(boolean defer, int newX, int newY) {
+
+ /** Triggered by implementation's WM events to update the position. */
+ protected final void positionChanged(final boolean defer, final int newX, final int newY) {
if ( getX() != newX || getY() != newY ) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.positionChanged: ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
@@ -2472,82 +3812,146 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_MOVED);
}
} else {
- autoPosition = false; // ensure it's off even w/ same position
+ autoPosition = false; // ensure it's off even w/ same position
+ }
+ }
+
+ /**
+ * Wait until position is reached within tolerances, either auto-position or custom position.
+ * <p>
+ * Since WM may not obey our positional request exactly, we allow a tolerance of 2 times insets[left/top], or 64 pixels, whatever is greater.
+ * </p>
+ */
+ private boolean waitForPosition(final boolean useCustomPosition, final int x, final int y, final long timeOut) {
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ final int maxDX, maxDY;
+ {
+ final InsetsImmutable insets = getInsets();
+ maxDX = Math.max(64, insets.getLeftWidth() * 2);
+ maxDY = Math.max(64, insets.getTopHeight() * 2);
+ }
+ long remaining = timeOut;
+ boolean ok;
+ do {
+ if( useCustomPosition ) {
+ ok = Math.abs(x - getX()) <= maxDX && Math.abs(y - getY()) <= maxDY ;
+ } else {
+ ok = !autoPosition;
+ }
+ if( !ok ) {
+ try { Thread.sleep(10); } catch (final InterruptedException ie) {}
+ display.dispatchMessagesNative(); // status up2date
+ remaining-=10;
+ }
+ } while ( 0<remaining && !ok );
+ if (DEBUG_IMPLEMENTATION) {
+ if( !ok ) {
+ if( useCustomPosition ) {
+ System.err.println("Custom position "+x+"/"+y+" not reached within timeout, has "+getX()+"/"+getY()+", remaining "+remaining);
+ } else {
+ System.err.println("Auto position not reached within timeout, has "+getX()+"/"+getY()+", autoPosition "+autoPosition+", remaining "+remaining);
+ }
+ Thread.dumpStack();
+ }
}
+ return ok;
}
/**
- * Triggered by implementation's WM events to update the insets.
- *
+ * Triggered by implementation's WM events to update the insets.
+ *
* @see #getInsets()
* @see #updateInsetsImpl(Insets)
*/
- protected void insetsChanged(boolean defer, int left, int right, int top, int bottom) {
+ protected void insetsChanged(final boolean defer, final int left, final int right, final int top, final int bottom) {
if ( left >= 0 && right >= 0 && top >= 0 && bottom >= 0 ) {
- if(isUndecorated()) {
+ if( blockInsetsChange || isUndecorated() ) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.insetsChanged: skip insets change for undecoration mode");
+ System.err.println("Window.insetsChanged (defer: "+defer+"): Skip insets change "+insets+" -> "+new Insets(left, right, top, bottom)+" (blocked "+blockInsetsChange+", undecoration "+isUndecorated()+")");
}
- } else if ( (left != insets.getLeftWidth() || right != insets.getRightWidth() ||
+ } else if ( (left != insets.getLeftWidth() || right != insets.getRightWidth() ||
top != insets.getTopHeight() || bottom != insets.getBottomHeight() )
) {
- insets.setLeftWidth(left);
- insets.setRightWidth(right);
- insets.setTopHeight(top);
- insets.setBottomHeight(bottom);
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.insetsChanged: (defer: "+defer+") "+insets);
+ System.err.println("Window.insetsChanged (defer: "+defer+"): Changed "+insets+" -> "+new Insets(left, right, top, bottom));
}
+ insets.set(left, right, top, bottom);
}
}
}
-
+
/**
- * Triggered by implementation's WM events or programmatically
- *
+ * Triggered by implementation's WM events or programmatic while respecting {@link #getDefaultCloseOperation()}.
+ *
* @param force if true, overrides {@link #setDefaultCloseOperation(WindowClosingMode)} with {@link WindowClosingProtocol#DISPOSE_ON_CLOSE}
* and hence force destruction. Otherwise is follows the user settings.
* @return true if this window is no more valid and hence has been destroyed, otherwise false.
*/
- protected boolean windowDestroyNotify(boolean force) {
+ public final boolean windowDestroyNotify(final boolean force) {
+ final WindowClosingMode defMode = getDefaultCloseOperation();
+ final WindowClosingMode mode = force ? WindowClosingMode.DISPOSE_ON_CLOSE : defMode;
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.windowDestroyNotify(force: "+force+") START "+getThreadName()+": "+this);
- }
- if(force) {
- setDefaultCloseOperation(WindowClosingMode.DISPOSE_ON_CLOSE);
+ System.err.println("Window.windowDestroyNotify(isNativeValid: "+isNativeValid()+", force: "+force+", mode "+defMode+" -> "+mode+") "+getThreadName()+": "+this);
+ // Thread.dumpStack();
}
- // send synced destroy notifications
- enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+ final boolean destroyed;
- if(handleDestroyNotify && WindowClosingMode.DISPOSE_ON_CLOSE == getDefaultCloseOperation()) {
- destroy();
+ if( isNativeValid() ) {
+ if( WindowClosingMode.DISPOSE_ON_CLOSE == mode ) {
+ if(force) {
+ setDefaultCloseOperation(mode);
+ }
+ try {
+ if( null == windowDestroyNotifyAction ) {
+ destroy();
+ } else {
+ windowDestroyNotifyAction.run();
+ }
+ } finally {
+ if(force) {
+ setDefaultCloseOperation(defMode);
+ }
+ }
+ } else {
+ // send synced destroy notifications
+ sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+ }
+
+ destroyed = !isNativeValid();
+ } else {
+ destroyed = true;
}
-
- final boolean destroyed = !isNativeValid();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.windowDestroyNotify(force: "+force+") END "+getThreadName()+": destroyed "+destroyed+", "+this);
+ System.err.println("Window.windowDestroyNotify(isNativeValid: "+isNativeValid()+", force: "+force+", mode "+mode+") END "+getThreadName()+": destroyed "+destroyed+", "+this);
}
+
return destroyed;
}
- public void windowRepaint(int x, int y, int width, int height) {
- windowRepaint(false, x, y, width, height);
+ @Override
+ public final void windowRepaint(final int x, final int y, final int width, final int height) {
+ windowRepaint(false, x, y, width, height);
}
-
+
/**
* Triggered by implementation's WM events to update the content
- */
- protected void windowRepaint(boolean defer, int x, int y, int width, int height) {
- width = ( 0 >= width ) ? getWidth() : width;
- height = ( 0 >= height ) ? getHeight() : height;
+ * @param defer if true sent event later, otherwise wait until processed.
+ * @param x dirty-region y-pos in pixel units
+ * @param y dirty-region x-pos in pixel units
+ * @param width dirty-region width in pixel units
+ * @param height dirty-region height in pixel units
+ */
+ protected final void windowRepaint(final boolean defer, final int x, final int y, int width, int height) {
+ width = ( 0 >= width ) ? getSurfaceWidth() : width;
+ height = ( 0 >= height ) ? getSurfaceHeight() : height;
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.windowRepaint "+getThreadName()+" (defer: "+defer+") "+x+"/"+y+" "+width+"x"+height);
}
if(isNativeValid()) {
- NEWTEvent e = new WindowUpdateEvent(WindowEvent.EVENT_WINDOW_REPAINT, this, System.currentTimeMillis(),
+ final NEWTEvent e = new WindowUpdateEvent(WindowEvent.EVENT_WINDOW_REPAINT, this, System.currentTimeMillis(),
new Rectangle(x, y, width, height));
doEvent(defer, false, e);
}
@@ -2557,16 +3961,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Reflection helper ..
//
- private static Class<?>[] getCustomConstructorArgumentTypes(Class<?> windowClass) {
+ private static Class<?>[] getCustomConstructorArgumentTypes(final Class<?> windowClass) {
Class<?>[] argTypes = null;
try {
- Method m = windowClass.getDeclaredMethod("getCustomConstructorArgumentTypes");
+ final Method m = windowClass.getDeclaredMethod("getCustomConstructorArgumentTypes");
argTypes = (Class[]) m.invoke(null, (Object[])null);
- } catch (Throwable t) {}
+ } catch (final Throwable t) {}
return argTypes;
}
- private static int verifyConstructorArgumentTypes(Class<?>[] types, Object[] args) {
+ private static int verifyConstructorArgumentTypes(final Class<?>[] types, final Object[] args) {
if(types.length != args.length) {
return -1;
}
@@ -2578,8 +3982,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return args.length;
}
- private static String getArgsStrList(Object[] args) {
- StringBuilder sb = new StringBuilder();
+ private static String getArgsStrList(final Object[] args) {
+ final StringBuilder sb = new StringBuilder();
for(int i=0; i<args.length; i++) {
sb.append(args[i].getClass());
if(i<args.length) {
@@ -2589,8 +3993,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return sb.toString();
}
- private static String getTypeStrList(Class<?>[] types) {
- StringBuilder sb = new StringBuilder();
+ private static String getTypeStrList(final Class<?>[] types) {
+ final StringBuilder sb = new StringBuilder();
for(int i=0; i<types.length; i++) {
sb.append(types[i]);
if(i<types.length) {
@@ -2600,19 +4004,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return sb.toString();
}
- protected final void shouldNotCallThis() {
- throw new NativeWindowException("Should not call this");
- }
-
public static String getThreadName() {
return Display.getThreadName();
}
- public static String toHexString(int hex) {
+ public static String toHexString(final int hex) {
return Display.toHexString(hex);
}
- public static String toHexString(long hex) {
+ public static String toHexString(final long hex) {
return Display.toHexString(hex);
}
}
diff --git a/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java
index 861a6d6be..682313ef4 100644
--- a/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java
+++ b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.newt.awt;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
@@ -55,7 +55,7 @@ public class NewtFactoryAWT extends NewtFactory {
*
* @param awtCompObject must be of type java.awt.Component
*/
- public static JAWTWindow getNativeWindow(Object awtCompObject, CapabilitiesImmutable capsRequested) {
+ public static JAWTWindow getNativeWindow(final Object awtCompObject, final CapabilitiesImmutable capsRequested) {
if(null==awtCompObject) {
throw new NativeWindowException("Null AWT Component");
}
@@ -65,9 +65,9 @@ public class NewtFactoryAWT extends NewtFactory {
return getNativeWindow( (java.awt.Component) awtCompObject, capsRequested );
}
- public static JAWTWindow getNativeWindow(java.awt.Component awtComp, CapabilitiesImmutable capsRequested) {
- AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(awtComp, null, capsRequested);
- NativeWindow nw = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow
+ public static JAWTWindow getNativeWindow(final java.awt.Component awtComp, final CapabilitiesImmutable capsRequested) {
+ final AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(awtComp, null, capsRequested);
+ final NativeWindow nw = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow
if(! ( nw instanceof JAWTWindow ) ) {
throw new NativeWindowException("Not an AWT NativeWindow: "+nw);
}
@@ -76,12 +76,12 @@ public class NewtFactoryAWT extends NewtFactory {
}
return (JAWTWindow)nw;
}
-
- public static void destroyNativeWindow(JAWTWindow jawtWindow) {
+
+ public static void destroyNativeWindow(final JAWTWindow jawtWindow) {
final AbstractGraphicsConfiguration config = jawtWindow.getGraphicsConfiguration();
jawtWindow.destroy();
- config.getScreen().getDevice().close();
+ config.getScreen().getDevice().close();
}
-
+
}
diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java b/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java
index cb70da13f..31ee92ca4 100644
--- a/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java
+++ b/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,138 +20,653 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.newt.awt.event;
-import com.jogamp.common.util.IntIntHashMap;
-import com.jogamp.newt.event.InputEvent;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeSurfaceHolder;
+
+import com.jogamp.newt.event.MouseEvent;
+/**
+ *
+ * <a name="AWTEventModifierMapping"><h5>AWT Event Modifier Mapping</h5></a>
+ * <pre>
+ Modifier AWT Constant AWT Bit AWT Ex NEWT Constant NEWT Bit
+ ------------- ------------------------------- ------- ------ ------------------------- --------
+ Shift Event.SHIFT_MASK 0
+ Ctrl Event.CTRL_MASK 1
+ Meta Event.META_MASK 2
+ Alt Event.ALT_MASK 3
+ Button1 InputEvent.BUTTON1_MASK 4
+ Button2 InputEvent.BUTTON2_MASK 3
+ Button3 InputEvent.BUTTON3_MASK 2
+ Shift Down InputEvent.SHIFT_DOWN_MASK 6 * InputEvent.SHIFT_MASK 0
+ Ctrl Down InputEvent.CTRL_DOWN_MASK 7 * InputEvent.CTRL_MASK 1
+ Meta Down InputEvent.META_DOWN_MASK 8 * InputEvent.META_MASK 2
+ Alt Down InputEvent.ALT_DOWN_MASK 9 * InputEvent.ALT_MASK 3
+ Button1 Down InputEvent.BUTTON1_DOWN_MASK 10 * InputEvent.BUTTON1_MASK 5
+ Button2 Down InputEvent.BUTTON2_DOWN_MASK 11 * InputEvent.BUTTON2_MASK 6
+ Button3 Down InputEvent.BUTTON3_DOWN_MASK 12 * InputEvent.BUTTON3_MASK 7
+ AltGraph Down InputEvent.ALT_GRAPH_DOWN_MASK 13 * InputEvent.ALT_GRAPH_MASK 4
+ Button4 Down -- 14 * InputEvent.BUTTON4_MASK 8
+ Button5 Down -- 15 * InputEvent.BUTTON5_MASK 9
+ Button6 Down -- 16 * InputEvent.BUTTON6_MASK 10
+ Button7 Down -- 17 * InputEvent.BUTTON7_MASK 11
+ Button8 Down -- 18 * InputEvent.BUTTON8_MASK 12
+ Button9 Down -- 19 * InputEvent.BUTTON9_MASK 13
+ Button10 Down -- 20 * 14
+ Button11 Down -- 21 * 15
+ Button12 Down -- 22 * 16
+ Button13 Down -- 23 * 17
+ Button14 Down -- 24 * 18
+ Button15 Down -- 25 * 19
+ Button16 Down -- 26 * InputEvent.BUTTONLAST_MASK 20
+ Button17 Down -- 27 *
+ Button18 Down -- 28 *
+ Button19 Down -- 29 *
+ Button20 Down -- 30 *
+ Autorepeat -- - InputEvent.AUTOREPEAT_MASK 29
+ Confined -- - InputEvent.CONFINED_MASK 30
+ Invisible -- - InputEvent.INVISIBLE_MASK 31
+ * </pre>
+ *
+ */
public class AWTNewtEventFactory {
- protected static final IntIntHashMap eventTypeAWT2NEWT;
+ /** zero-based AWT button mask array filled by {@link #getAWTButtonDownMask(int)}, allowing fast lookup. */
+ private static int awtButtonDownMasks[] ;
static {
- IntIntHashMap map = new IntIntHashMap();
- map.setKeyNotFoundValue(0xFFFFFFFF);
- // n/a map.put(java.awt.event.WindowEvent.WINDOW_OPENED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_OPENED);
- map.put(java.awt.event.WindowEvent.WINDOW_CLOSING, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
- map.put(java.awt.event.WindowEvent.WINDOW_CLOSED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROYED);
- // n/a map.put(java.awt.event.WindowEvent.WINDOW_ICONIFIED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_ICONIFIED);
- // n/a map.put(java.awt.event.WindowEvent.WINDOW_DEICONIFIED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DEICONIFIED);
- map.put(java.awt.event.WindowEvent.WINDOW_ACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
- map.put(java.awt.event.WindowEvent.WINDOW_GAINED_FOCUS, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
- map.put(java.awt.event.FocusEvent.FOCUS_GAINED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
- map.put(java.awt.event.WindowEvent.WINDOW_DEACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
- map.put(java.awt.event.WindowEvent.WINDOW_LOST_FOCUS, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
- map.put(java.awt.event.FocusEvent.FOCUS_LOST, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
- // n/a map.put(java.awt.event.WindowEvent.WINDOW_STATE_CHANGED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_STATE_CHANGED);
-
- map.put(java.awt.event.ComponentEvent.COMPONENT_MOVED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_MOVED);
- map.put(java.awt.event.ComponentEvent.COMPONENT_RESIZED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_RESIZED);
- // n/a map.put(java.awt.event.ComponentEvent.COMPONENT_SHOWN, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_SHOWN);
- // n/a map.put(java.awt.event.ComponentEvent.COMPONENT_HIDDEN, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_HIDDEN);
-
- map.put(java.awt.event.MouseEvent.MOUSE_CLICKED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED);
- map.put(java.awt.event.MouseEvent.MOUSE_PRESSED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED);
- map.put(java.awt.event.MouseEvent.MOUSE_RELEASED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
- map.put(java.awt.event.MouseEvent.MOUSE_MOVED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED);
- map.put(java.awt.event.MouseEvent.MOUSE_ENTERED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED);
- map.put(java.awt.event.MouseEvent.MOUSE_EXITED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED);
- map.put(java.awt.event.MouseEvent.MOUSE_DRAGGED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED);
- map.put(java.awt.event.MouseEvent.MOUSE_WHEEL, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED);
-
- map.put(java.awt.event.KeyEvent.KEY_PRESSED, com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED);
- map.put(java.awt.event.KeyEvent.KEY_RELEASED, com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED);
- map.put(java.awt.event.KeyEvent.KEY_TYPED, com.jogamp.newt.event.KeyEvent.EVENT_KEY_TYPED);
-
- eventTypeAWT2NEWT = map;
+ // There is an assumption in awtModifiers2Newt(int,int,boolean)
+ // that the awtButtonMasks and newtButtonMasks are peers, i.e.
+ // a given index refers to the same button in each array.
+
+ /* {
+ Method _getMaskForButtonMethod = null;
+ try {
+ _getMaskForButtonMethod = ReflectionUtil.getMethod(java.awt.event.InputEvent.class, "getMaskForButton", int.class);
+ } catch(Throwable t) {}
+ getMaskForButtonMethod = _getMaskForButtonMethod;
+ } */
+
+ awtButtonDownMasks = new int[com.jogamp.newt.event.MouseEvent.BUTTON_COUNT] ; // java.awt.MouseInfo.getNumberOfButtons() ;
+ for (int n = 0 ; n < awtButtonDownMasks.length ; ++n) {
+ awtButtonDownMasks[n] = getAWTButtonDownMaskImpl(n+1);
+ }
+ }
+
+ public static final short eventTypeAWT2NEWT(final int awtType) {
+ switch( awtType ) {
+ // n/a case java.awt.event.WindowEvent.WINDOW_OPENED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_OPENED;
+ case java.awt.event.WindowEvent.WINDOW_CLOSING: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY;
+ case java.awt.event.WindowEvent.WINDOW_CLOSED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROYED;
+ // n/a case java.awt.event.WindowEvent.WINDOW_ICONIFIED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_ICONIFIED;
+ // n/a case java.awt.event.WindowEvent.WINDOW_DEICONIFIED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DEICONIFIED;
+ case java.awt.event.WindowEvent.WINDOW_ACTIVATED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+ case java.awt.event.WindowEvent.WINDOW_GAINED_FOCUS: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+ case java.awt.event.FocusEvent.FOCUS_GAINED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+ case java.awt.event.WindowEvent.WINDOW_DEACTIVATED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS;
+ case java.awt.event.WindowEvent.WINDOW_LOST_FOCUS: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS;
+ case java.awt.event.FocusEvent.FOCUS_LOST: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS;
+ // n/a case java.awt.event.WindowEvent.WINDOW_STATE_CHANGED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_STATE_CHANGED;
+
+ case java.awt.event.ComponentEvent.COMPONENT_MOVED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_MOVED;
+ case java.awt.event.ComponentEvent.COMPONENT_RESIZED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_RESIZED;
+ // n/a case java.awt.event.ComponentEvent.COMPONENT_SHOWN: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_SHOWN;
+ // n/a case java.awt.event.ComponentEvent.COMPONENT_HIDDEN: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_HIDDEN;
+
+ case java.awt.event.MouseEvent.MOUSE_CLICKED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED;
+ case java.awt.event.MouseEvent.MOUSE_PRESSED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED;
+ case java.awt.event.MouseEvent.MOUSE_RELEASED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED;
+ case java.awt.event.MouseEvent.MOUSE_MOVED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED;
+ case java.awt.event.MouseEvent.MOUSE_ENTERED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED;
+ case java.awt.event.MouseEvent.MOUSE_EXITED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED;
+ case java.awt.event.MouseEvent.MOUSE_DRAGGED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED;
+ case java.awt.event.MouseEvent.MOUSE_WHEEL: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+
+ case java.awt.event.KeyEvent.KEY_PRESSED: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
+ case java.awt.event.KeyEvent.KEY_RELEASED: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
+ }
+ return (short)0;
+ }
+
+ private static int getAWTButtonDownMaskImpl(final int button) {
+ /**
+ * java.awt.event.InputEvent.getMaskForButton(button);
+ *
+ if(null != getMaskForButtonMethod) {
+ Object r=null;
+ try {
+ r = getMaskForButtonMethod.invoke(null, new Integer(button));
+ } catch (Throwable t) { }
+ if(null != r) {
+ return ((Integer)r).intValue();
+ }
+ } */
+ final int m;
+ switch(button) {
+ case 0 : m = 0; break;
+ case 1 : m = java.awt.event.InputEvent.BUTTON1_DOWN_MASK; break; // 1<<10
+ case 2 : m = java.awt.event.InputEvent.BUTTON2_DOWN_MASK; break; // 1<<11
+ case 3 : m = java.awt.event.InputEvent.BUTTON3_DOWN_MASK; break; // 1<<12
+ default:
+ if( button <= com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ) {
+ m = 1 << ( 10 + button ) ; // b4 = 1<<14, b5 = 1<<15, etc
+ } else {
+ m = 0;
+ }
+ }
+ return m;
+ }
+
+ /**
+ * <p>
+ * See <a href="#AWTEventModifierMapping"> AWT event modifier mapping details</a>.
+ * </p>
+ *
+ * @param button
+ * @return
+ */
+ public static int getAWTButtonDownMask(final int button) {
+ if( 0 < button && button <= awtButtonDownMasks.length ) {
+ return awtButtonDownMasks[button-1];
+ } else {
+ return 0;
+ }
+ }
+
+ public static final short awtButton2Newt(final int awtButton) {
+ if( 0 < awtButton && awtButton <= com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ) {
+ return (short)awtButton;
+ } else {
+ return (short)0;
+ }
}
- public static final int awtModifiers2Newt(int awtMods, boolean mouseHint) {
+ /**
+ * Converts the specified set of AWT event modifiers and extended event
+ * modifiers to the equivalent NEWT event modifiers.
+ *
+ * <p>
+ * See <a href="#AWTEventModifierMapping"> AWT event modifier mapping details</a>.
+ * </p>
+ *
+ * @param awtMods
+ * The AWT event modifiers.
+ *
+ * @param awtModsEx
+ * The AWT extended event modifiers.
+ * AWT passes mouse button specific bits here and are the preferred way check the mouse button state.
+ */
+ public static final int awtModifiers2Newt(final int awtMods, final int awtModsEx) {
int newtMods = 0;
+
+ /** Redundant old modifiers ..
if ((awtMods & java.awt.event.InputEvent.SHIFT_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
if ((awtMods & java.awt.event.InputEvent.CTRL_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK;
if ((awtMods & java.awt.event.InputEvent.META_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.META_MASK;
if ((awtMods & java.awt.event.InputEvent.ALT_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
- if ((awtMods & java.awt.event.InputEvent.ALT_GRAPH_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK;
+ if ((awtMods & java.awt.event.InputEvent.ALT_GRAPH_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK; */
+
+ if ((awtModsEx & java.awt.event.InputEvent.SHIFT_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+ if ((awtModsEx & java.awt.event.InputEvent.CTRL_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK;
+ if ((awtModsEx & java.awt.event.InputEvent.META_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.META_MASK;
+ if ((awtModsEx & java.awt.event.InputEvent.ALT_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
+ if ((awtModsEx & java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK;
+
+ // The BUTTON1_MASK, BUTTON2_MASK, and BUTTON3_MASK bits are
+ // being ignored intentionally. The AWT docs say that the
+ // BUTTON1_DOWN_MASK etc bits in the extended modifiers are
+ // the preferred place to check current button state.
+
+ if( 0 != awtModsEx ) {
+ for (int n = 0 ; n < awtButtonDownMasks.length ; ++n) {
+ if ( (awtModsEx & awtButtonDownMasks[n]) != 0 ) {
+ newtMods |= com.jogamp.newt.event.InputEvent.getButtonMask(n+1);
+ }
+ }
+ }
+
return newtMods;
}
- public static final int awtButton2Newt(int awtButton) {
- switch (awtButton) {
- case java.awt.event.MouseEvent.BUTTON1: return com.jogamp.newt.event.MouseEvent.BUTTON1;
- case java.awt.event.MouseEvent.BUTTON2: return com.jogamp.newt.event.MouseEvent.BUTTON2;
- case java.awt.event.MouseEvent.BUTTON3: return com.jogamp.newt.event.MouseEvent.BUTTON3;
+ public static short awtKeyCode2NewtKeyCode(final int awtKeyCode) {
+ final short defNEWTKeyCode = (short)awtKeyCode;
+ switch (awtKeyCode) {
+ case java.awt.event.KeyEvent.VK_HOME : return com.jogamp.newt.event.KeyEvent.VK_HOME;
+ case java.awt.event.KeyEvent.VK_END : return com.jogamp.newt.event.KeyEvent.VK_END;
+ case java.awt.event.KeyEvent.VK_FINAL : return com.jogamp.newt.event.KeyEvent.VK_FINAL;
+ case java.awt.event.KeyEvent.VK_PRINTSCREEN : return com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN;
+ case java.awt.event.KeyEvent.VK_BACK_SPACE : return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
+ case java.awt.event.KeyEvent.VK_TAB : return com.jogamp.newt.event.KeyEvent.VK_TAB;
+ case java.awt.event.KeyEvent.VK_ENTER : return com.jogamp.newt.event.KeyEvent.VK_ENTER;
+ case java.awt.event.KeyEvent.VK_PAGE_DOWN : return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN;
+ case java.awt.event.KeyEvent.VK_CLEAR : return com.jogamp.newt.event.KeyEvent.VK_CLEAR;
+ case java.awt.event.KeyEvent.VK_SHIFT : return com.jogamp.newt.event.KeyEvent.VK_SHIFT;
+ case java.awt.event.KeyEvent.VK_PAGE_UP : return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP;
+ case java.awt.event.KeyEvent.VK_CONTROL : return com.jogamp.newt.event.KeyEvent.VK_CONTROL;
+ case java.awt.event.KeyEvent.VK_ALT : return com.jogamp.newt.event.KeyEvent.VK_ALT;
+ case java.awt.event.KeyEvent.VK_ALT_GRAPH : return com.jogamp.newt.event.KeyEvent.VK_ALT_GRAPH;
+ case java.awt.event.KeyEvent.VK_CAPS_LOCK : return com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK;
+ case java.awt.event.KeyEvent.VK_PAUSE : return com.jogamp.newt.event.KeyEvent.VK_PAUSE;
+ case java.awt.event.KeyEvent.VK_SCROLL_LOCK : return com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK;
+ case java.awt.event.KeyEvent.VK_CANCEL : return com.jogamp.newt.event.KeyEvent.VK_CANCEL;
+ case java.awt.event.KeyEvent.VK_INSERT : return com.jogamp.newt.event.KeyEvent.VK_INSERT;
+ case java.awt.event.KeyEvent.VK_ESCAPE : return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
+ case java.awt.event.KeyEvent.VK_CONVERT : return com.jogamp.newt.event.KeyEvent.VK_CONVERT;
+ case java.awt.event.KeyEvent.VK_NONCONVERT : return com.jogamp.newt.event.KeyEvent.VK_NONCONVERT;
+ case java.awt.event.KeyEvent.VK_ACCEPT : return com.jogamp.newt.event.KeyEvent.VK_ACCEPT;
+ case java.awt.event.KeyEvent.VK_MODECHANGE : return com.jogamp.newt.event.KeyEvent.VK_MODECHANGE;
+ case java.awt.event.KeyEvent.VK_SPACE : return com.jogamp.newt.event.KeyEvent.VK_SPACE;
+ case java.awt.event.KeyEvent.VK_EXCLAMATION_MARK: return com.jogamp.newt.event.KeyEvent.VK_EXCLAMATION_MARK;
+ case java.awt.event.KeyEvent.VK_QUOTEDBL : return com.jogamp.newt.event.KeyEvent.VK_QUOTEDBL;
+ case java.awt.event.KeyEvent.VK_NUMBER_SIGN : return com.jogamp.newt.event.KeyEvent.VK_NUMBER_SIGN;
+ case java.awt.event.KeyEvent.VK_DOLLAR : return com.jogamp.newt.event.KeyEvent.VK_DOLLAR;
+ // case 0x25 : return com.jogamp.newt.event.KeyEvent.VK_PERCENT;
+ case java.awt.event.KeyEvent.VK_AMPERSAND : return com.jogamp.newt.event.KeyEvent.VK_AMPERSAND;
+ case java.awt.event.KeyEvent.VK_QUOTE : return com.jogamp.newt.event.KeyEvent.VK_QUOTE;
+ case java.awt.event.KeyEvent.VK_LEFT_PARENTHESIS : return com.jogamp.newt.event.KeyEvent.VK_LEFT_PARENTHESIS;
+ case java.awt.event.KeyEvent.VK_RIGHT_PARENTHESIS: return com.jogamp.newt.event.KeyEvent.VK_RIGHT_PARENTHESIS;
+ case java.awt.event.KeyEvent.VK_ASTERISK : return com.jogamp.newt.event.KeyEvent.VK_ASTERISK;
+ case java.awt.event.KeyEvent.VK_PLUS : return com.jogamp.newt.event.KeyEvent.VK_PLUS;
+ case java.awt.event.KeyEvent.VK_COMMA : return com.jogamp.newt.event.KeyEvent.VK_COMMA;
+ case java.awt.event.KeyEvent.VK_MINUS : return com.jogamp.newt.event.KeyEvent.VK_MINUS;
+ case java.awt.event.KeyEvent.VK_PERIOD : return com.jogamp.newt.event.KeyEvent.VK_PERIOD;
+ case java.awt.event.KeyEvent.VK_SLASH : return com.jogamp.newt.event.KeyEvent.VK_SLASH;
+ case java.awt.event.KeyEvent.VK_0 : return com.jogamp.newt.event.KeyEvent.VK_0;
+ case java.awt.event.KeyEvent.VK_1 : return com.jogamp.newt.event.KeyEvent.VK_1;
+ case java.awt.event.KeyEvent.VK_2 : return com.jogamp.newt.event.KeyEvent.VK_2;
+ case java.awt.event.KeyEvent.VK_3 : return com.jogamp.newt.event.KeyEvent.VK_3;
+ case java.awt.event.KeyEvent.VK_4 : return com.jogamp.newt.event.KeyEvent.VK_4;
+ case java.awt.event.KeyEvent.VK_5 : return com.jogamp.newt.event.KeyEvent.VK_5;
+ case java.awt.event.KeyEvent.VK_6 : return com.jogamp.newt.event.KeyEvent.VK_6;
+ case java.awt.event.KeyEvent.VK_7 : return com.jogamp.newt.event.KeyEvent.VK_7;
+ case java.awt.event.KeyEvent.VK_8 : return com.jogamp.newt.event.KeyEvent.VK_8;
+ case java.awt.event.KeyEvent.VK_9 : return com.jogamp.newt.event.KeyEvent.VK_9;
+ case java.awt.event.KeyEvent.VK_COLON : return com.jogamp.newt.event.KeyEvent.VK_COLON;
+ case java.awt.event.KeyEvent.VK_SEMICOLON : return com.jogamp.newt.event.KeyEvent.VK_SEMICOLON;
+ case java.awt.event.KeyEvent.VK_LESS : return com.jogamp.newt.event.KeyEvent.VK_LESS;
+ case java.awt.event.KeyEvent.VK_EQUALS : return com.jogamp.newt.event.KeyEvent.VK_EQUALS;
+ case java.awt.event.KeyEvent.VK_GREATER : return com.jogamp.newt.event.KeyEvent.VK_GREATER;
+ case 0x3f : return com.jogamp.newt.event.KeyEvent.VK_QUESTIONMARK;
+ case java.awt.event.KeyEvent.VK_AT : return com.jogamp.newt.event.KeyEvent.VK_AT;
+ case java.awt.event.KeyEvent.VK_A : return com.jogamp.newt.event.KeyEvent.VK_A;
+ case java.awt.event.KeyEvent.VK_B : return com.jogamp.newt.event.KeyEvent.VK_B;
+ case java.awt.event.KeyEvent.VK_C : return com.jogamp.newt.event.KeyEvent.VK_C;
+ case java.awt.event.KeyEvent.VK_D : return com.jogamp.newt.event.KeyEvent.VK_D;
+ case java.awt.event.KeyEvent.VK_E : return com.jogamp.newt.event.KeyEvent.VK_E;
+ case java.awt.event.KeyEvent.VK_F : return com.jogamp.newt.event.KeyEvent.VK_F;
+ case java.awt.event.KeyEvent.VK_G : return com.jogamp.newt.event.KeyEvent.VK_G;
+ case java.awt.event.KeyEvent.VK_H : return com.jogamp.newt.event.KeyEvent.VK_H;
+ case java.awt.event.KeyEvent.VK_I : return com.jogamp.newt.event.KeyEvent.VK_I;
+ case java.awt.event.KeyEvent.VK_J : return com.jogamp.newt.event.KeyEvent.VK_J;
+ case java.awt.event.KeyEvent.VK_K : return com.jogamp.newt.event.KeyEvent.VK_K;
+ case java.awt.event.KeyEvent.VK_L : return com.jogamp.newt.event.KeyEvent.VK_L;
+ case java.awt.event.KeyEvent.VK_M : return com.jogamp.newt.event.KeyEvent.VK_M;
+ case java.awt.event.KeyEvent.VK_N : return com.jogamp.newt.event.KeyEvent.VK_N;
+ case java.awt.event.KeyEvent.VK_O : return com.jogamp.newt.event.KeyEvent.VK_O;
+ case java.awt.event.KeyEvent.VK_P : return com.jogamp.newt.event.KeyEvent.VK_P;
+ case java.awt.event.KeyEvent.VK_Q : return com.jogamp.newt.event.KeyEvent.VK_Q;
+ case java.awt.event.KeyEvent.VK_R : return com.jogamp.newt.event.KeyEvent.VK_R;
+ case java.awt.event.KeyEvent.VK_S : return com.jogamp.newt.event.KeyEvent.VK_S;
+ case java.awt.event.KeyEvent.VK_T : return com.jogamp.newt.event.KeyEvent.VK_T;
+ case java.awt.event.KeyEvent.VK_U : return com.jogamp.newt.event.KeyEvent.VK_U;
+ case java.awt.event.KeyEvent.VK_V : return com.jogamp.newt.event.KeyEvent.VK_V;
+ case java.awt.event.KeyEvent.VK_W : return com.jogamp.newt.event.KeyEvent.VK_W;
+ case java.awt.event.KeyEvent.VK_X : return com.jogamp.newt.event.KeyEvent.VK_X;
+ case java.awt.event.KeyEvent.VK_Y : return com.jogamp.newt.event.KeyEvent.VK_Y;
+ case java.awt.event.KeyEvent.VK_Z : return com.jogamp.newt.event.KeyEvent.VK_Z;
+ case java.awt.event.KeyEvent.VK_OPEN_BRACKET : return com.jogamp.newt.event.KeyEvent.VK_OPEN_BRACKET;
+ case java.awt.event.KeyEvent.VK_BACK_SLASH : return com.jogamp.newt.event.KeyEvent.VK_BACK_SLASH;
+ case java.awt.event.KeyEvent.VK_CLOSE_BRACKET : return com.jogamp.newt.event.KeyEvent.VK_CLOSE_BRACKET;
+ case java.awt.event.KeyEvent.VK_CIRCUMFLEX : return com.jogamp.newt.event.KeyEvent.VK_CIRCUMFLEX;
+ case java.awt.event.KeyEvent.VK_UNDERSCORE : return com.jogamp.newt.event.KeyEvent.VK_UNDERSCORE;
+ case java.awt.event.KeyEvent.VK_BACK_QUOTE : return com.jogamp.newt.event.KeyEvent.VK_BACK_QUOTE;
+ case java.awt.event.KeyEvent.VK_F1 : return com.jogamp.newt.event.KeyEvent.VK_F1;
+ case java.awt.event.KeyEvent.VK_F2 : return com.jogamp.newt.event.KeyEvent.VK_F2;
+ case java.awt.event.KeyEvent.VK_F3 : return com.jogamp.newt.event.KeyEvent.VK_F3;
+ case java.awt.event.KeyEvent.VK_F4 : return com.jogamp.newt.event.KeyEvent.VK_F4;
+ case java.awt.event.KeyEvent.VK_F5 : return com.jogamp.newt.event.KeyEvent.VK_F5;
+ case java.awt.event.KeyEvent.VK_F6 : return com.jogamp.newt.event.KeyEvent.VK_F6;
+ case java.awt.event.KeyEvent.VK_F7 : return com.jogamp.newt.event.KeyEvent.VK_F7;
+ case java.awt.event.KeyEvent.VK_F8 : return com.jogamp.newt.event.KeyEvent.VK_F8;
+ case java.awt.event.KeyEvent.VK_F9 : return com.jogamp.newt.event.KeyEvent.VK_F9;
+ case java.awt.event.KeyEvent.VK_F10 : return com.jogamp.newt.event.KeyEvent.VK_F10;
+ case java.awt.event.KeyEvent.VK_F11 : return com.jogamp.newt.event.KeyEvent.VK_F11;
+ case java.awt.event.KeyEvent.VK_F12 : return com.jogamp.newt.event.KeyEvent.VK_F12;
+ case java.awt.event.KeyEvent.VK_F13 : return com.jogamp.newt.event.KeyEvent.VK_F13;
+ case java.awt.event.KeyEvent.VK_F14 : return com.jogamp.newt.event.KeyEvent.VK_F14;
+ case java.awt.event.KeyEvent.VK_F15 : return com.jogamp.newt.event.KeyEvent.VK_F15;
+ case java.awt.event.KeyEvent.VK_F16 : return com.jogamp.newt.event.KeyEvent.VK_F16;
+ case java.awt.event.KeyEvent.VK_F17 : return com.jogamp.newt.event.KeyEvent.VK_F17;
+ case java.awt.event.KeyEvent.VK_F18 : return com.jogamp.newt.event.KeyEvent.VK_F18;
+ case java.awt.event.KeyEvent.VK_F19 : return com.jogamp.newt.event.KeyEvent.VK_F19;
+ case java.awt.event.KeyEvent.VK_F20 : return com.jogamp.newt.event.KeyEvent.VK_F20;
+ case java.awt.event.KeyEvent.VK_F21 : return com.jogamp.newt.event.KeyEvent.VK_F21;
+ case java.awt.event.KeyEvent.VK_F22 : return com.jogamp.newt.event.KeyEvent.VK_F22;
+ case java.awt.event.KeyEvent.VK_F23 : return com.jogamp.newt.event.KeyEvent.VK_F23;
+ case java.awt.event.KeyEvent.VK_F24 : return com.jogamp.newt.event.KeyEvent.VK_F24;
+ case java.awt.event.KeyEvent.VK_BRACELEFT : return com.jogamp.newt.event.KeyEvent.VK_LEFT_BRACE;
+ case 0x7c : return com.jogamp.newt.event.KeyEvent.VK_PIPE;
+ case java.awt.event.KeyEvent.VK_BRACERIGHT : return com.jogamp.newt.event.KeyEvent.VK_RIGHT_BRACE;
+ case java.awt.event.KeyEvent.VK_DEAD_TILDE : return com.jogamp.newt.event.KeyEvent.VK_TILDE;
+ case java.awt.event.KeyEvent.VK_DELETE : return com.jogamp.newt.event.KeyEvent.VK_DELETE;
+ case java.awt.event.KeyEvent.VK_NUMPAD0 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD0;
+ case java.awt.event.KeyEvent.VK_NUMPAD1 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD1;
+ case java.awt.event.KeyEvent.VK_NUMPAD2 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD2;
+ case java.awt.event.KeyEvent.VK_NUMPAD3 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD3;
+ case java.awt.event.KeyEvent.VK_NUMPAD4 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD4;
+ case java.awt.event.KeyEvent.VK_NUMPAD5 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD5;
+ case java.awt.event.KeyEvent.VK_NUMPAD6 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD6;
+ case java.awt.event.KeyEvent.VK_NUMPAD7 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD7;
+ case java.awt.event.KeyEvent.VK_NUMPAD8 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD8;
+ case java.awt.event.KeyEvent.VK_NUMPAD9 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD9;
+ case java.awt.event.KeyEvent.VK_DECIMAL : return com.jogamp.newt.event.KeyEvent.VK_DECIMAL;
+ case java.awt.event.KeyEvent.VK_SEPARATOR : return com.jogamp.newt.event.KeyEvent.VK_SEPARATOR;
+ case java.awt.event.KeyEvent.VK_ADD : return com.jogamp.newt.event.KeyEvent.VK_ADD;
+ case java.awt.event.KeyEvent.VK_SUBTRACT : return com.jogamp.newt.event.KeyEvent.VK_SUBTRACT;
+ case java.awt.event.KeyEvent.VK_MULTIPLY : return com.jogamp.newt.event.KeyEvent.VK_MULTIPLY;
+ case java.awt.event.KeyEvent.VK_DIVIDE : return com.jogamp.newt.event.KeyEvent.VK_DIVIDE;
+ case java.awt.event.KeyEvent.VK_NUM_LOCK : return com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK;
+ case java.awt.event.KeyEvent.VK_KP_LEFT : /** Fall through intended .. */
+ case java.awt.event.KeyEvent.VK_LEFT : return com.jogamp.newt.event.KeyEvent.VK_LEFT;
+ case java.awt.event.KeyEvent.VK_KP_UP : /** Fall through intended .. */
+ case java.awt.event.KeyEvent.VK_UP : return com.jogamp.newt.event.KeyEvent.VK_UP;
+ case java.awt.event.KeyEvent.VK_KP_RIGHT : /** Fall through intended .. */
+ case java.awt.event.KeyEvent.VK_RIGHT : return com.jogamp.newt.event.KeyEvent.VK_RIGHT;
+ case java.awt.event.KeyEvent.VK_KP_DOWN : /** Fall through intended .. */
+ case java.awt.event.KeyEvent.VK_DOWN : return com.jogamp.newt.event.KeyEvent.VK_DOWN;
+ case java.awt.event.KeyEvent.VK_CONTEXT_MENU : return com.jogamp.newt.event.KeyEvent.VK_CONTEXT_MENU;
+ case java.awt.event.KeyEvent.VK_WINDOWS : return com.jogamp.newt.event.KeyEvent.VK_WINDOWS;
+ case java.awt.event.KeyEvent.VK_META : return com.jogamp.newt.event.KeyEvent.VK_META;
+ case java.awt.event.KeyEvent.VK_HELP : return com.jogamp.newt.event.KeyEvent.VK_HELP;
+ case java.awt.event.KeyEvent.VK_COMPOSE : return com.jogamp.newt.event.KeyEvent.VK_COMPOSE;
+ case java.awt.event.KeyEvent.VK_BEGIN : return com.jogamp.newt.event.KeyEvent.VK_BEGIN;
+ case java.awt.event.KeyEvent.VK_STOP : return com.jogamp.newt.event.KeyEvent.VK_STOP;
+ case java.awt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK: return com.jogamp.newt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK;
+ case java.awt.event.KeyEvent.VK_EURO_SIGN : return com.jogamp.newt.event.KeyEvent.VK_EURO_SIGN;
+ case java.awt.event.KeyEvent.VK_CUT : return com.jogamp.newt.event.KeyEvent.VK_CUT;
+ case java.awt.event.KeyEvent.VK_COPY : return com.jogamp.newt.event.KeyEvent.VK_COPY;
+ case java.awt.event.KeyEvent.VK_PASTE : return com.jogamp.newt.event.KeyEvent.VK_PASTE;
+ case java.awt.event.KeyEvent.VK_UNDO : return com.jogamp.newt.event.KeyEvent.VK_UNDO;
+ case java.awt.event.KeyEvent.VK_AGAIN : return com.jogamp.newt.event.KeyEvent.VK_AGAIN;
+ case java.awt.event.KeyEvent.VK_FIND : return com.jogamp.newt.event.KeyEvent.VK_FIND;
+ case java.awt.event.KeyEvent.VK_PROPS : return com.jogamp.newt.event.KeyEvent.VK_PROPS;
+ case java.awt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF: return com.jogamp.newt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF;
+ case java.awt.event.KeyEvent.VK_CODE_INPUT : return com.jogamp.newt.event.KeyEvent.VK_CODE_INPUT;
+ case java.awt.event.KeyEvent.VK_ROMAN_CHARACTERS: return com.jogamp.newt.event.KeyEvent.VK_ROMAN_CHARACTERS;
+ case java.awt.event.KeyEvent.VK_ALL_CANDIDATES: return com.jogamp.newt.event.KeyEvent.VK_ALL_CANDIDATES;
+ case java.awt.event.KeyEvent.VK_PREVIOUS_CANDIDATE: return com.jogamp.newt.event.KeyEvent.VK_PREVIOUS_CANDIDATE;
+ case java.awt.event.KeyEvent.VK_ALPHANUMERIC : return com.jogamp.newt.event.KeyEvent.VK_ALPHANUMERIC;
+ case java.awt.event.KeyEvent.VK_KATAKANA : return com.jogamp.newt.event.KeyEvent.VK_KATAKANA;
+ case java.awt.event.KeyEvent.VK_HIRAGANA : return com.jogamp.newt.event.KeyEvent.VK_HIRAGANA;
+ case java.awt.event.KeyEvent.VK_FULL_WIDTH : return com.jogamp.newt.event.KeyEvent.VK_FULL_WIDTH;
+ case java.awt.event.KeyEvent.VK_HALF_WIDTH : return com.jogamp.newt.event.KeyEvent.VK_HALF_WIDTH;
+ case java.awt.event.KeyEvent.VK_JAPANESE_KATAKANA: return com.jogamp.newt.event.KeyEvent.VK_JAPANESE_KATAKANA;
+ case java.awt.event.KeyEvent.VK_JAPANESE_HIRAGANA: return com.jogamp.newt.event.KeyEvent.VK_JAPANESE_HIRAGANA;
+ case java.awt.event.KeyEvent.VK_JAPANESE_ROMAN: return com.jogamp.newt.event.KeyEvent.VK_JAPANESE_ROMAN;
+ case java.awt.event.KeyEvent.VK_KANA_LOCK : return com.jogamp.newt.event.KeyEvent.VK_KANA_LOCK;
+ }
+ return defNEWTKeyCode;
+ }
+
+ public static int newtKeyCode2AWTKeyCode(final short newtKeyCode) {
+ final int defAwtKeyCode = 0xFFFF & newtKeyCode;
+ switch (newtKeyCode) {
+ case com.jogamp.newt.event.KeyEvent.VK_HOME : return java.awt.event.KeyEvent.VK_HOME;
+ case com.jogamp.newt.event.KeyEvent.VK_END : return java.awt.event.KeyEvent.VK_END;
+ case com.jogamp.newt.event.KeyEvent.VK_FINAL : return java.awt.event.KeyEvent.VK_FINAL;
+ case com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN : return java.awt.event.KeyEvent.VK_PRINTSCREEN;
+ case com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE : return java.awt.event.KeyEvent.VK_BACK_SPACE;
+ case com.jogamp.newt.event.KeyEvent.VK_TAB : return java.awt.event.KeyEvent.VK_TAB;
+ case com.jogamp.newt.event.KeyEvent.VK_ENTER : return java.awt.event.KeyEvent.VK_ENTER;
+ case com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN : return java.awt.event.KeyEvent.VK_PAGE_DOWN;
+ case com.jogamp.newt.event.KeyEvent.VK_CLEAR : return java.awt.event.KeyEvent.VK_CLEAR;
+ case com.jogamp.newt.event.KeyEvent.VK_SHIFT : return java.awt.event.KeyEvent.VK_SHIFT;
+ case com.jogamp.newt.event.KeyEvent.VK_PAGE_UP : return java.awt.event.KeyEvent.VK_PAGE_UP;
+ case com.jogamp.newt.event.KeyEvent.VK_CONTROL : return java.awt.event.KeyEvent.VK_CONTROL;
+ case com.jogamp.newt.event.KeyEvent.VK_ALT : return java.awt.event.KeyEvent.VK_ALT;
+ // FIXME: On X11 it results to 0xff7e w/ AWTRobot, which is wrong. 0xffea Alt_R is expected AFAIK.
+ case com.jogamp.newt.event.KeyEvent.VK_ALT_GRAPH : return java.awt.event.KeyEvent.VK_ALT_GRAPH;
+ case com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK : return java.awt.event.KeyEvent.VK_CAPS_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_PAUSE : return java.awt.event.KeyEvent.VK_PAUSE;
+ case com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK : return java.awt.event.KeyEvent.VK_SCROLL_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_CANCEL : return java.awt.event.KeyEvent.VK_CANCEL;
+ case com.jogamp.newt.event.KeyEvent.VK_INSERT : return java.awt.event.KeyEvent.VK_INSERT;
+ case com.jogamp.newt.event.KeyEvent.VK_ESCAPE : return java.awt.event.KeyEvent.VK_ESCAPE;
+ case com.jogamp.newt.event.KeyEvent.VK_CONVERT : return java.awt.event.KeyEvent.VK_CONVERT;
+ case com.jogamp.newt.event.KeyEvent.VK_NONCONVERT : return java.awt.event.KeyEvent.VK_NONCONVERT;
+ case com.jogamp.newt.event.KeyEvent.VK_ACCEPT : return java.awt.event.KeyEvent.VK_ACCEPT;
+ case com.jogamp.newt.event.KeyEvent.VK_MODECHANGE : return java.awt.event.KeyEvent.VK_MODECHANGE;
+ case com.jogamp.newt.event.KeyEvent.VK_SPACE : return java.awt.event.KeyEvent.VK_SPACE;
+ case com.jogamp.newt.event.KeyEvent.VK_EXCLAMATION_MARK: return java.awt.event.KeyEvent.VK_EXCLAMATION_MARK;
+ case com.jogamp.newt.event.KeyEvent.VK_QUOTEDBL : return java.awt.event.KeyEvent.VK_QUOTEDBL;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMBER_SIGN : return java.awt.event.KeyEvent.VK_NUMBER_SIGN;
+ case com.jogamp.newt.event.KeyEvent.VK_DOLLAR : return java.awt.event.KeyEvent.VK_DOLLAR;
+ case com.jogamp.newt.event.KeyEvent.VK_PERCENT : return defAwtKeyCode;
+ case com.jogamp.newt.event.KeyEvent.VK_AMPERSAND : return java.awt.event.KeyEvent.VK_AMPERSAND;
+ case com.jogamp.newt.event.KeyEvent.VK_QUOTE : return java.awt.event.KeyEvent.VK_QUOTE;
+ case com.jogamp.newt.event.KeyEvent.VK_LEFT_PARENTHESIS : return java.awt.event.KeyEvent.VK_LEFT_PARENTHESIS;
+ case com.jogamp.newt.event.KeyEvent.VK_RIGHT_PARENTHESIS: return java.awt.event.KeyEvent.VK_RIGHT_PARENTHESIS;
+ case com.jogamp.newt.event.KeyEvent.VK_ASTERISK : return java.awt.event.KeyEvent.VK_ASTERISK;
+ case com.jogamp.newt.event.KeyEvent.VK_PLUS : return java.awt.event.KeyEvent.VK_PLUS;
+ case com.jogamp.newt.event.KeyEvent.VK_COMMA : return java.awt.event.KeyEvent.VK_COMMA;
+ case com.jogamp.newt.event.KeyEvent.VK_MINUS : return java.awt.event.KeyEvent.VK_MINUS;
+ case com.jogamp.newt.event.KeyEvent.VK_PERIOD : return java.awt.event.KeyEvent.VK_PERIOD;
+ case com.jogamp.newt.event.KeyEvent.VK_SLASH : return java.awt.event.KeyEvent.VK_SLASH;
+ case com.jogamp.newt.event.KeyEvent.VK_0 : return java.awt.event.KeyEvent.VK_0;
+ case com.jogamp.newt.event.KeyEvent.VK_1 : return java.awt.event.KeyEvent.VK_1;
+ case com.jogamp.newt.event.KeyEvent.VK_2 : return java.awt.event.KeyEvent.VK_2;
+ case com.jogamp.newt.event.KeyEvent.VK_3 : return java.awt.event.KeyEvent.VK_3;
+ case com.jogamp.newt.event.KeyEvent.VK_4 : return java.awt.event.KeyEvent.VK_4;
+ case com.jogamp.newt.event.KeyEvent.VK_5 : return java.awt.event.KeyEvent.VK_5;
+ case com.jogamp.newt.event.KeyEvent.VK_6 : return java.awt.event.KeyEvent.VK_6;
+ case com.jogamp.newt.event.KeyEvent.VK_7 : return java.awt.event.KeyEvent.VK_7;
+ case com.jogamp.newt.event.KeyEvent.VK_8 : return java.awt.event.KeyEvent.VK_8;
+ case com.jogamp.newt.event.KeyEvent.VK_9 : return java.awt.event.KeyEvent.VK_9;
+ case com.jogamp.newt.event.KeyEvent.VK_COLON : return java.awt.event.KeyEvent.VK_COLON;
+ case com.jogamp.newt.event.KeyEvent.VK_SEMICOLON : return java.awt.event.KeyEvent.VK_SEMICOLON;
+ case com.jogamp.newt.event.KeyEvent.VK_LESS : return java.awt.event.KeyEvent.VK_LESS;
+ case com.jogamp.newt.event.KeyEvent.VK_EQUALS : return java.awt.event.KeyEvent.VK_EQUALS;
+ case com.jogamp.newt.event.KeyEvent.VK_GREATER : return java.awt.event.KeyEvent.VK_GREATER;
+ case com.jogamp.newt.event.KeyEvent.VK_QUESTIONMARK : return defAwtKeyCode;
+ case com.jogamp.newt.event.KeyEvent.VK_AT : return java.awt.event.KeyEvent.VK_AT;
+ case com.jogamp.newt.event.KeyEvent.VK_A : return java.awt.event.KeyEvent.VK_A;
+ case com.jogamp.newt.event.KeyEvent.VK_B : return java.awt.event.KeyEvent.VK_B;
+ case com.jogamp.newt.event.KeyEvent.VK_C : return java.awt.event.KeyEvent.VK_C;
+ case com.jogamp.newt.event.KeyEvent.VK_D : return java.awt.event.KeyEvent.VK_D;
+ case com.jogamp.newt.event.KeyEvent.VK_E : return java.awt.event.KeyEvent.VK_E;
+ case com.jogamp.newt.event.KeyEvent.VK_F : return java.awt.event.KeyEvent.VK_F;
+ case com.jogamp.newt.event.KeyEvent.VK_G : return java.awt.event.KeyEvent.VK_G;
+ case com.jogamp.newt.event.KeyEvent.VK_H : return java.awt.event.KeyEvent.VK_H;
+ case com.jogamp.newt.event.KeyEvent.VK_I : return java.awt.event.KeyEvent.VK_I;
+ case com.jogamp.newt.event.KeyEvent.VK_J : return java.awt.event.KeyEvent.VK_J;
+ case com.jogamp.newt.event.KeyEvent.VK_K : return java.awt.event.KeyEvent.VK_K;
+ case com.jogamp.newt.event.KeyEvent.VK_L : return java.awt.event.KeyEvent.VK_L;
+ case com.jogamp.newt.event.KeyEvent.VK_M : return java.awt.event.KeyEvent.VK_M;
+ case com.jogamp.newt.event.KeyEvent.VK_N : return java.awt.event.KeyEvent.VK_N;
+ case com.jogamp.newt.event.KeyEvent.VK_O : return java.awt.event.KeyEvent.VK_O;
+ case com.jogamp.newt.event.KeyEvent.VK_P : return java.awt.event.KeyEvent.VK_P;
+ case com.jogamp.newt.event.KeyEvent.VK_Q : return java.awt.event.KeyEvent.VK_Q;
+ case com.jogamp.newt.event.KeyEvent.VK_R : return java.awt.event.KeyEvent.VK_R;
+ case com.jogamp.newt.event.KeyEvent.VK_S : return java.awt.event.KeyEvent.VK_S;
+ case com.jogamp.newt.event.KeyEvent.VK_T : return java.awt.event.KeyEvent.VK_T;
+ case com.jogamp.newt.event.KeyEvent.VK_U : return java.awt.event.KeyEvent.VK_U;
+ case com.jogamp.newt.event.KeyEvent.VK_V : return java.awt.event.KeyEvent.VK_V;
+ case com.jogamp.newt.event.KeyEvent.VK_W : return java.awt.event.KeyEvent.VK_W;
+ case com.jogamp.newt.event.KeyEvent.VK_X : return java.awt.event.KeyEvent.VK_X;
+ case com.jogamp.newt.event.KeyEvent.VK_Y : return java.awt.event.KeyEvent.VK_Y;
+ case com.jogamp.newt.event.KeyEvent.VK_Z : return java.awt.event.KeyEvent.VK_Z;
+ case com.jogamp.newt.event.KeyEvent.VK_OPEN_BRACKET : return java.awt.event.KeyEvent.VK_OPEN_BRACKET;
+ case com.jogamp.newt.event.KeyEvent.VK_BACK_SLASH : return java.awt.event.KeyEvent.VK_BACK_SLASH;
+ case com.jogamp.newt.event.KeyEvent.VK_CLOSE_BRACKET : return java.awt.event.KeyEvent.VK_CLOSE_BRACKET;
+ case com.jogamp.newt.event.KeyEvent.VK_CIRCUMFLEX : return java.awt.event.KeyEvent.VK_CIRCUMFLEX;
+ case com.jogamp.newt.event.KeyEvent.VK_UNDERSCORE : return java.awt.event.KeyEvent.VK_UNDERSCORE;
+ case com.jogamp.newt.event.KeyEvent.VK_BACK_QUOTE : return java.awt.event.KeyEvent.VK_BACK_QUOTE;
+ case com.jogamp.newt.event.KeyEvent.VK_F1 : return java.awt.event.KeyEvent.VK_F1;
+ case com.jogamp.newt.event.KeyEvent.VK_F2 : return java.awt.event.KeyEvent.VK_F2;
+ case com.jogamp.newt.event.KeyEvent.VK_F3 : return java.awt.event.KeyEvent.VK_F3;
+ case com.jogamp.newt.event.KeyEvent.VK_F4 : return java.awt.event.KeyEvent.VK_F4;
+ case com.jogamp.newt.event.KeyEvent.VK_F5 : return java.awt.event.KeyEvent.VK_F5;
+ case com.jogamp.newt.event.KeyEvent.VK_F6 : return java.awt.event.KeyEvent.VK_F6;
+ case com.jogamp.newt.event.KeyEvent.VK_F7 : return java.awt.event.KeyEvent.VK_F7;
+ case com.jogamp.newt.event.KeyEvent.VK_F8 : return java.awt.event.KeyEvent.VK_F8;
+ case com.jogamp.newt.event.KeyEvent.VK_F9 : return java.awt.event.KeyEvent.VK_F9;
+ case com.jogamp.newt.event.KeyEvent.VK_F10 : return java.awt.event.KeyEvent.VK_F10;
+ case com.jogamp.newt.event.KeyEvent.VK_F11 : return java.awt.event.KeyEvent.VK_F11;
+ case com.jogamp.newt.event.KeyEvent.VK_F12 : return java.awt.event.KeyEvent.VK_F12;
+ case com.jogamp.newt.event.KeyEvent.VK_F13 : return java.awt.event.KeyEvent.VK_F13;
+ case com.jogamp.newt.event.KeyEvent.VK_F14 : return java.awt.event.KeyEvent.VK_F14;
+ case com.jogamp.newt.event.KeyEvent.VK_F15 : return java.awt.event.KeyEvent.VK_F15;
+ case com.jogamp.newt.event.KeyEvent.VK_F16 : return java.awt.event.KeyEvent.VK_F16;
+ case com.jogamp.newt.event.KeyEvent.VK_F17 : return java.awt.event.KeyEvent.VK_F17;
+ case com.jogamp.newt.event.KeyEvent.VK_F18 : return java.awt.event.KeyEvent.VK_F18;
+ case com.jogamp.newt.event.KeyEvent.VK_F19 : return java.awt.event.KeyEvent.VK_F19;
+ case com.jogamp.newt.event.KeyEvent.VK_F20 : return java.awt.event.KeyEvent.VK_F20;
+ case com.jogamp.newt.event.KeyEvent.VK_F21 : return java.awt.event.KeyEvent.VK_F21;
+ case com.jogamp.newt.event.KeyEvent.VK_F22 : return java.awt.event.KeyEvent.VK_F22;
+ case com.jogamp.newt.event.KeyEvent.VK_F23 : return java.awt.event.KeyEvent.VK_F23;
+ case com.jogamp.newt.event.KeyEvent.VK_F24 : return java.awt.event.KeyEvent.VK_F24;
+ case com.jogamp.newt.event.KeyEvent.VK_LEFT_BRACE : return java.awt.event.KeyEvent.VK_BRACELEFT;
+ case com.jogamp.newt.event.KeyEvent.VK_PIPE : return defAwtKeyCode;
+ case com.jogamp.newt.event.KeyEvent.VK_RIGHT_BRACE : return java.awt.event.KeyEvent.VK_BRACERIGHT;
+ case com.jogamp.newt.event.KeyEvent.VK_TILDE : return java.awt.event.KeyEvent.VK_DEAD_TILDE;
+ case com.jogamp.newt.event.KeyEvent.VK_DELETE : return java.awt.event.KeyEvent.VK_DELETE;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD0 : return java.awt.event.KeyEvent.VK_NUMPAD0;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD1 : return java.awt.event.KeyEvent.VK_NUMPAD1;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD2 : return java.awt.event.KeyEvent.VK_NUMPAD2;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD3 : return java.awt.event.KeyEvent.VK_NUMPAD3;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD4 : return java.awt.event.KeyEvent.VK_NUMPAD4;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD5 : return java.awt.event.KeyEvent.VK_NUMPAD5;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD6 : return java.awt.event.KeyEvent.VK_NUMPAD6;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD7 : return java.awt.event.KeyEvent.VK_NUMPAD7;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD8 : return java.awt.event.KeyEvent.VK_NUMPAD8;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD9 : return java.awt.event.KeyEvent.VK_NUMPAD9;
+ case com.jogamp.newt.event.KeyEvent.VK_DECIMAL : return java.awt.event.KeyEvent.VK_DECIMAL;
+ case com.jogamp.newt.event.KeyEvent.VK_SEPARATOR : return java.awt.event.KeyEvent.VK_SEPARATOR;
+ case com.jogamp.newt.event.KeyEvent.VK_ADD : return java.awt.event.KeyEvent.VK_ADD;
+ case com.jogamp.newt.event.KeyEvent.VK_SUBTRACT : return java.awt.event.KeyEvent.VK_SUBTRACT;
+ case com.jogamp.newt.event.KeyEvent.VK_MULTIPLY : return java.awt.event.KeyEvent.VK_MULTIPLY;
+ case com.jogamp.newt.event.KeyEvent.VK_DIVIDE : return java.awt.event.KeyEvent.VK_DIVIDE;
+ case com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK : return java.awt.event.KeyEvent.VK_NUM_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_LEFT : return java.awt.event.KeyEvent.VK_LEFT;
+ case com.jogamp.newt.event.KeyEvent.VK_UP : return java.awt.event.KeyEvent.VK_UP;
+ case com.jogamp.newt.event.KeyEvent.VK_RIGHT : return java.awt.event.KeyEvent.VK_RIGHT;
+ case com.jogamp.newt.event.KeyEvent.VK_DOWN : return java.awt.event.KeyEvent.VK_DOWN;
+ case com.jogamp.newt.event.KeyEvent.VK_CONTEXT_MENU : return java.awt.event.KeyEvent.VK_CONTEXT_MENU;
+ case com.jogamp.newt.event.KeyEvent.VK_WINDOWS : return java.awt.event.KeyEvent.VK_WINDOWS;
+ case com.jogamp.newt.event.KeyEvent.VK_META : return java.awt.event.KeyEvent.VK_META;
+ case com.jogamp.newt.event.KeyEvent.VK_HELP : return java.awt.event.KeyEvent.VK_HELP;
+ case com.jogamp.newt.event.KeyEvent.VK_COMPOSE : return java.awt.event.KeyEvent.VK_COMPOSE;
+ case com.jogamp.newt.event.KeyEvent.VK_BEGIN : return java.awt.event.KeyEvent.VK_BEGIN;
+ case com.jogamp.newt.event.KeyEvent.VK_STOP : return java.awt.event.KeyEvent.VK_STOP;
+ case com.jogamp.newt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK: return java.awt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK;
+ case com.jogamp.newt.event.KeyEvent.VK_EURO_SIGN : return java.awt.event.KeyEvent.VK_EURO_SIGN;
+ case com.jogamp.newt.event.KeyEvent.VK_CUT : return java.awt.event.KeyEvent.VK_CUT;
+ case com.jogamp.newt.event.KeyEvent.VK_COPY : return java.awt.event.KeyEvent.VK_COPY;
+ case com.jogamp.newt.event.KeyEvent.VK_PASTE : return java.awt.event.KeyEvent.VK_PASTE;
+ case com.jogamp.newt.event.KeyEvent.VK_UNDO : return java.awt.event.KeyEvent.VK_UNDO;
+ case com.jogamp.newt.event.KeyEvent.VK_AGAIN : return java.awt.event.KeyEvent.VK_AGAIN;
+ case com.jogamp.newt.event.KeyEvent.VK_FIND : return java.awt.event.KeyEvent.VK_FIND;
+ case com.jogamp.newt.event.KeyEvent.VK_PROPS : return java.awt.event.KeyEvent.VK_PROPS;
+ case com.jogamp.newt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF: return java.awt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF;
+ case com.jogamp.newt.event.KeyEvent.VK_CODE_INPUT : return java.awt.event.KeyEvent.VK_CODE_INPUT;
+ case com.jogamp.newt.event.KeyEvent.VK_ROMAN_CHARACTERS: return java.awt.event.KeyEvent.VK_ROMAN_CHARACTERS;
+ case com.jogamp.newt.event.KeyEvent.VK_ALL_CANDIDATES: return java.awt.event.KeyEvent.VK_ALL_CANDIDATES;
+ case com.jogamp.newt.event.KeyEvent.VK_PREVIOUS_CANDIDATE: return java.awt.event.KeyEvent.VK_PREVIOUS_CANDIDATE;
+ case com.jogamp.newt.event.KeyEvent.VK_ALPHANUMERIC : return java.awt.event.KeyEvent.VK_ALPHANUMERIC;
+ case com.jogamp.newt.event.KeyEvent.VK_KATAKANA : return java.awt.event.KeyEvent.VK_KATAKANA;
+ case com.jogamp.newt.event.KeyEvent.VK_HIRAGANA : return java.awt.event.KeyEvent.VK_HIRAGANA;
+ case com.jogamp.newt.event.KeyEvent.VK_FULL_WIDTH : return java.awt.event.KeyEvent.VK_FULL_WIDTH;
+ case com.jogamp.newt.event.KeyEvent.VK_HALF_WIDTH : return java.awt.event.KeyEvent.VK_HALF_WIDTH;
+ case com.jogamp.newt.event.KeyEvent.VK_JAPANESE_KATAKANA: return java.awt.event.KeyEvent.VK_JAPANESE_KATAKANA;
+ case com.jogamp.newt.event.KeyEvent.VK_JAPANESE_HIRAGANA: return java.awt.event.KeyEvent.VK_JAPANESE_HIRAGANA;
+ case com.jogamp.newt.event.KeyEvent.VK_JAPANESE_ROMAN: return java.awt.event.KeyEvent.VK_JAPANESE_ROMAN;
+ case com.jogamp.newt.event.KeyEvent.VK_KANA_LOCK : return java.awt.event.KeyEvent.VK_KANA_LOCK;
}
- return 0;
+ return defAwtKeyCode;
}
- public static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.WindowEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeAWT2NEWT.get(event.getID());
- if(0xFFFFFFFF != type) {
- return new com.jogamp.newt.event.WindowEvent(type, ((null==newtSource)?(Object)event.getComponent():(Object)newtSource), System.currentTimeMillis());
+ public static final com.jogamp.newt.event.WindowEvent createWindowEvent(final java.awt.event.WindowEvent event, final NativeSurfaceHolder sourceHolder) {
+ final short newtType = eventTypeAWT2NEWT(event.getID());
+ if( (short)0 != newtType ) {
+ return new com.jogamp.newt.event.WindowEvent(newtType, sourceHolder, System.currentTimeMillis());
}
return null; // no mapping ..
}
- public static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.ComponentEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeAWT2NEWT.get(event.getID());
- if(0xFFFFFFFF != type) {
- return new com.jogamp.newt.event.WindowEvent(type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
+ public static final com.jogamp.newt.event.WindowEvent createWindowEvent(final java.awt.event.ComponentEvent event, final NativeSurfaceHolder sourceHolder) {
+ final short newtType = eventTypeAWT2NEWT(event.getID());
+ if( (short)0 != newtType ) {
+ return new com.jogamp.newt.event.WindowEvent(newtType, sourceHolder, System.currentTimeMillis());
}
return null; // no mapping ..
}
- public static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.FocusEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeAWT2NEWT.get(event.getID());
- if(0xFFFFFFFF != type) {
- return new com.jogamp.newt.event.WindowEvent(type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
+ public static final com.jogamp.newt.event.WindowEvent createWindowEvent(final java.awt.event.FocusEvent event, final NativeSurfaceHolder sourceHolder) {
+ final short newtType = eventTypeAWT2NEWT(event.getID());
+ if( (short)0 != newtType ) {
+ return new com.jogamp.newt.event.WindowEvent(newtType, sourceHolder, System.currentTimeMillis());
}
return null; // no mapping ..
}
- public static final com.jogamp.newt.event.MouseEvent createMouseEvent(java.awt.event.MouseEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeAWT2NEWT.get(event.getID());
- if(0xFFFFFFFF != type) {
- int rotation = 0;
+ public static final com.jogamp.newt.event.MouseEvent createMouseEvent(final java.awt.event.MouseEvent event, final NativeSurfaceHolder sourceHolder) {
+ final short newtType = eventTypeAWT2NEWT(event.getID());
+ if( (short)0 != newtType ) {
+ float rotation = 0;
if (event instanceof java.awt.event.MouseWheelEvent) {
// AWT/NEWT rotation is reversed - AWT +1 is down, NEWT +1 is up.
- rotation = -1 * ((java.awt.event.MouseWheelEvent)event).getWheelRotation();
+ rotation = -1f * ((java.awt.event.MouseWheelEvent)event).getWheelRotation();
}
- int mods = awtModifiers2Newt(event.getModifiers(), true);
- if(null!=newtSource) {
- if(newtSource.isPointerConfined()) {
- mods |= InputEvent.CONFINED_MASK;
- }
- if(!newtSource.isPointerVisible()) {
- mods |= InputEvent.INVISIBLE_MASK;
+ final short newtButton = awtButton2Newt(event.getButton());
+ int mods = awtModifiers2Newt(event.getModifiers(), event.getModifiersEx());
+ mods |= com.jogamp.newt.event.InputEvent.getButtonMask(newtButton); // always include NEWT BUTTON_MASK
+ final NativeSurface source = sourceHolder.getNativeSurface();
+ final int[] pixelPos;
+ if( null != source ) {
+ if( source instanceof com.jogamp.newt.Window ) {
+ final com.jogamp.newt.Window newtSource = (com.jogamp.newt.Window) source;
+ if(newtSource.isPointerConfined()) {
+ mods |= com.jogamp.newt.event.InputEvent.CONFINED_MASK;
+ }
+ if(!newtSource.isPointerVisible()) {
+ mods |= com.jogamp.newt.event.InputEvent.INVISIBLE_MASK;
+ }
}
+ pixelPos = source.convertToPixelUnits(new int[] { event.getX(), event.getY() });
+ } else {
+ pixelPos = new int[] { event.getX(), event.getY() };
}
-
+
return new com.jogamp.newt.event.MouseEvent(
- type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, event.getWhen(),
- mods, event.getX(), event.getY(), event.getClickCount(),
- awtButton2Newt(event.getButton()), rotation);
+ newtType, sourceHolder, event.getWhen(),
+ mods, pixelPos[0], pixelPos[1], (short)event.getClickCount(),
+ newtButton, MouseEvent.getRotationXYZ(rotation, mods), 1f);
}
return null; // no mapping ..
}
- public static final com.jogamp.newt.event.KeyEvent createKeyEvent(java.awt.event.KeyEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeAWT2NEWT.get(event.getID());
- if(0xFFFFFFFF != type) {
- return new com.jogamp.newt.event.KeyEvent(
- type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, event.getWhen(),
- awtModifiers2Newt(event.getModifiers(), false),
- event.getKeyCode(), event.getKeyChar());
+ public static final com.jogamp.newt.event.KeyEvent createKeyEvent(final java.awt.event.KeyEvent event, final NativeSurfaceHolder sourceHolder) {
+ return createKeyEvent(eventTypeAWT2NEWT(event.getID()), event, sourceHolder);
+ }
+
+ public static final com.jogamp.newt.event.KeyEvent createKeyEvent(final short newtType, final java.awt.event.KeyEvent event, final NativeSurfaceHolder sourceHolder) {
+ if( (short)0 != newtType ) {
+ final short newtKeyCode = awtKeyCode2NewtKeyCode( event.getKeyCode() );
+ return com.jogamp.newt.event.KeyEvent.create(
+ newtType, sourceHolder, event.getWhen(),
+ awtModifiers2Newt(event.getModifiers(), event.getModifiersEx()),
+ newtKeyCode, newtKeyCode, event.getKeyChar());
}
return null; // no mapping ..
}
}
-
diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
index 747e2368e..93cdd7e56 100644
--- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
+++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.newt.awt.event;
import java.awt.KeyboardFocusManager;
@@ -42,113 +42,147 @@ import com.jogamp.newt.event.awt.AWTWindowAdapter;
* Specialized parent/client adapter,
* where the NEWT child window really gets resized,
* and the parent move window event gets discarded. */
-public class AWTParentWindowAdapter
- extends AWTWindowAdapter
- implements java.awt.event.HierarchyListener
+public class AWTParentWindowAdapter extends AWTWindowAdapter implements java.awt.event.HierarchyListener
{
NativeWindow downstreamParent;
-
- public AWTParentWindowAdapter(NativeWindow downstreamParent, com.jogamp.newt.Window downstream) {
+
+ public AWTParentWindowAdapter(final NativeWindow downstreamParent, final com.jogamp.newt.Window downstream) {
super(downstream);
this.downstreamParent = downstreamParent;
}
+ public AWTParentWindowAdapter() {
+ super();
+ }
+ public AWTParentWindowAdapter setDownstream(final NativeWindow downstreamParent, final com.jogamp.newt.Window downstream) {
+ setDownstream(downstream);
+ this.downstreamParent = downstreamParent;
+ return this;
+ }
+
+ @Override
+ public synchronized AWTAdapter clear() {
+ super.clear();
+ this.downstreamParent = null;
+ return this;
+ }
- public AWTAdapter addTo(java.awt.Component awtComponent) {
+ @Override
+ public synchronized AWTAdapter addTo(final java.awt.Component awtComponent) {
awtComponent.addHierarchyListener(this);
return super.addTo(awtComponent);
}
- public AWTAdapter removeFrom(java.awt.Component awtComponent) {
+ @Override
+ public synchronized AWTAdapter removeFrom(final java.awt.Component awtComponent) {
awtComponent.removeHierarchyListener(this);
return super.removeFrom(awtComponent);
}
- public void focusGained(java.awt.event.FocusEvent e) {
+ @Override
+ public synchronized void focusGained(final java.awt.event.FocusEvent e) {
+ if( !isSetup ) { return; }
// forward focus to NEWT child
final com.jogamp.newt.Window newtChild = getNewtWindow();
- final boolean isOnscreen = newtChild.isNativeValid() && newtChild.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
- final boolean isParent = downstreamParent == newtChild.getParent();
- final boolean isFullscreen = newtChild.isFullscreen();
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("AWT: focusGained: onscreen "+ isOnscreen+", "+e+", isParent: "+isParent+", isFS "+isFullscreen);
- }
- if(isParent) {
- if(isOnscreen && !isFullscreen) {
- KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ if( null != newtChild ) {
+ final boolean isOnscreen = newtChild.isNativeValid() && newtChild.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
+ final boolean isParent = downstreamParent == newtChild.getParent();
+ final boolean isFullscreen = newtChild.isFullscreen();
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("AWT: focusGained: onscreen "+ isOnscreen+", "+e+", isParent: "+isParent+", isFS "+isFullscreen);
+ }
+ if(isParent) {
+ if(isOnscreen && !isFullscreen) {
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ }
+ newtChild.requestFocus(false);
}
- newtChild.requestFocus(false);
}
}
- public void focusLost(java.awt.event.FocusEvent e) {
+ @Override
+ public synchronized void focusLost(final java.awt.event.FocusEvent e) {
+ if( !isSetup ) { return; }
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: focusLost: "+ e);
}
}
- public void componentResized(java.awt.event.ComponentEvent e) {
+ @Override
+ public synchronized void componentResized(final java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
// Need to resize the NEWT child window
// the resized event will be send via the native window feedback.
final java.awt.Component comp = e.getComponent();
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentResized: "+comp);
}
- final Window newtWindow = getNewtWindow();
- newtWindow.runOnEDTIfAvail(false, new Runnable() {
- public void run() {
- int cw = comp.getWidth();
- int ch = comp.getHeight();
- if( 0 < cw * ch ) {
- if( newtWindow.getWidth() != cw || newtWindow.getHeight() != ch ) {
- newtWindow.setSize(cw, ch);
- if(comp.isVisible() != newtWindow.isVisible()) {
- newtWindow.setVisible(comp.isVisible());
+ final Window newtChild = getNewtWindow();
+ if( null != newtChild ) {
+ newtChild.runOnEDTIfAvail(false, new Runnable() {
+ @Override
+ public void run() {
+ final int cw = comp.getWidth();
+ final int ch = comp.getHeight();
+ if( 0 < cw && 0 < ch ) {
+ if( newtChild.getWidth() != cw || newtChild.getHeight() != ch ) {
+ newtChild.setSize(cw, ch);
+ final boolean v = comp.isShowing(); // compute showing-state throughout hierarchy
+ if(v != newtChild.isVisible()) {
+ newtChild.setVisible(v);
+ }
}
+ } else if(newtChild.isVisible()) {
+ newtChild.setVisible(false);
}
- } else if(newtWindow.isVisible()) {
- newtWindow.setVisible(false);
- }
- }});
+ }});
+ }
}
- public void componentMoved(java.awt.event.ComponentEvent e) {
+ @Override
+ public synchronized void componentMoved(final java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
if(DEBUG_IMPLEMENTATION) {
- System.err.println("AWT: componentMoved: "+e);
+ System.err.println("AWT: componentMoved: "+e);
+ }
+ final Window newtChild = getNewtWindow();
+ if( null != newtChild && ( newtChild.getDelegatedWindow() instanceof DriverUpdatePosition ) ) {
+ ((DriverUpdatePosition)newtChild.getDelegatedWindow()).updatePosition(0, 0);
}
- final Window newtWindow = getNewtWindow();
- if(newtWindow.getDelegatedWindow() instanceof DriverUpdatePosition) {
- ((DriverUpdatePosition)newtWindow.getDelegatedWindow()).updatePosition();
- }
}
- public void windowActivated(java.awt.event.WindowEvent e) {
+ @Override
+ public synchronized void windowActivated(final java.awt.event.WindowEvent e) {
// no propagation to NEWT child window
}
- public void windowDeactivated(java.awt.event.WindowEvent e) {
+ @Override
+ public synchronized void windowDeactivated(final java.awt.event.WindowEvent e) {
// no propagation to NEWT child window
}
- public void hierarchyChanged(java.awt.event.HierarchyEvent e) {
- if( null == getNewtEventListener() ) {
- long bits = e.getChangeFlags();
- final java.awt.Component changed = e.getChanged();
+ @Override
+ public synchronized void hierarchyChanged(final java.awt.event.HierarchyEvent e) {
+ if( !isSetup ) { return; }
+ final Window newtChild = getNewtWindow();
+ if( null != newtChild && null == getNewtEventListener() ) {
+ final long bits = e.getChangeFlags();
+ final java.awt.Component comp = e.getComponent();
if( 0 != ( java.awt.event.HierarchyEvent.SHOWING_CHANGED & bits ) ) {
- final boolean showing = changed.isShowing();
+ final boolean showing = comp.isShowing(); // compute showing-state throughout hierarchy
if(DEBUG_IMPLEMENTATION) {
- System.err.println("AWT: hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed+", source "+e.getComponent());
+ System.err.println("AWT: hierarchyChanged SHOWING_CHANGED: showing "+showing+", comp "+comp+", changed "+e.getChanged());
}
- getNewtWindow().runOnEDTIfAvail(false, new Runnable() {
+ newtChild.runOnEDTIfAvail(false, new Runnable() {
+ @Override
public void run() {
- if(getNewtWindow().isVisible() != showing) {
- getNewtWindow().setVisible(showing);
+ if(newtChild.isVisible() != showing) {
+ newtChild.setVisible(showing);
}
}});
- }
+ }
if(DEBUG_IMPLEMENTATION) {
if( 0 != ( java.awt.event.HierarchyEvent.DISPLAYABILITY_CHANGED & bits ) ) {
- final boolean displayability = changed.isDisplayable();
- System.err.println("AWT: hierarchyChanged DISPLAYABILITY_CHANGED: displayability "+displayability+", "+changed);
+ System.err.println("AWT: hierarchyChanged DISPLAYABILITY_CHANGED: "+e.getChanged());
}
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java b/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java
index 0a824e83b..0ff86fe93 100644
--- a/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java
+++ b/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java
@@ -1,10 +1,10 @@
package jogamp.newt.driver;
-/**
+/**
* Interface tagging driver requirement of clearing the focus.
* <p>
- * Some drivers require a programmatic {@link #clearFocus()} when traversing the focus.
- * </p>
+ * Some drivers require a programmatic {@link #clearFocus()} when traversing the focus.
+ * </p>
*/
public interface DriverClearFocus {
/** Programmatic clear the focus */
diff --git a/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java b/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java
index bb846c081..e5f9b6a68 100644
--- a/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java
+++ b/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java
@@ -1,9 +1,15 @@
package jogamp.newt.driver;
-/**
+/**
* Interface tagging driver requirement of absolute positioning, ie. depend on parent position.
*/
public interface DriverUpdatePosition {
- /** Programmatic update the position */
- void updatePosition();
+ /**
+ * Programmatic update the top-left corner
+ * of the client area relative to it's parent.
+ *
+ * @param x x-component
+ * @param y y-component
+ **/
+ void updatePosition(int x, int y);
}
diff --git a/src/newt/classes/jogamp/newt/driver/PNGIcon.java b/src/newt/classes/jogamp/newt/driver/PNGIcon.java
new file mode 100644
index 000000000..43cfa9b25
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/PNGIcon.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.newt.driver;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.ByteBuffer;
+
+import jogamp.newt.Debug;
+import jogamp.newt.DisplayImpl;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.ReflectionUtil;
+
+public class PNGIcon {
+ private static final String err0 = "PNG decoder not implemented.";
+
+ private static final boolean avail;
+
+ static {
+ Debug.initSingleton();
+
+ final ClassLoader cl = PNGIcon.class.getClassLoader();
+ avail = DisplayImpl.isPNGUtilAvailable() && ReflectionUtil.isClassAvailable("jogamp.newt.driver.opengl.JoglUtilPNGIcon", cl);
+ }
+
+ /** Returns true if PNG decoder is available. */
+ public static boolean isAvailable() {
+ return avail;
+ }
+
+ /**
+ * Special implementation for X11 Window Icons
+ * <p>
+ * The returned byte buffer is a direct buffer!
+ * </p>
+ *
+ * @param resources
+ * @param data_size
+ * @param elem_bytesize
+ *
+ * @return BGRA8888 bytes with origin at upper-left corner where component B is located on the lowest 8-bit and component A is located on the highest 8-bit.
+ *
+ * @throws UnsupportedOperationException if not implemented
+ * @throws InterruptedException
+ * @throws IOException
+ * @throws MalformedURLException
+ */
+ public static ByteBuffer arrayToX11BGRAImages(final IOUtil.ClassResources resources, final int[] data_size, final int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
+ if( avail ) {
+ return jogamp.newt.driver.opengl.JoglUtilPNGIcon.arrayToX11BGRAImages(resources, data_size, elem_bytesize);
+ }
+ throw new UnsupportedOperationException(err0);
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java
index a367462c4..a5f4fc769 100644
--- a/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -53,14 +53,15 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl {
protected void createNativeImpl() {
// EGL Device
aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice.open();
}
- protected void closeNativeImpl() {
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
aDevice.close();
}
protected void dispatchMessagesNative() {
// n/a .. DispatchMessages();
- }
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/MD.java b/src/newt/classes/jogamp/newt/driver/android/MD.java
index f2f30937b..e6316004b 100644
--- a/src/newt/classes/jogamp/newt/driver/android/MD.java
+++ b/src/newt/classes/jogamp/newt/driver/android/MD.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,13 +20,15 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package jogamp.newt.driver.android;
+import jogamp.common.os.PlatformPropsImpl;
+
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionUtil;
@@ -34,22 +36,22 @@ import com.jogamp.opengl.JoglVersion;
public class MD {
public static final String TAG = "JogAmp.NEWT";
-
- public static String getInfo() {
- StringBuilder sb = new StringBuilder();
-
- sb.append(VersionUtil.getPlatformInfo()).append(Platform.NEWLINE)
- .append(GlueGenVersion.getInstance()).append(Platform.NEWLINE)
- .append(JoglVersion.getInstance()).append(Platform.NEWLINE)
- .append(Platform.NEWLINE);
-
+
+ public static String getInfo() {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(VersionUtil.getPlatformInfo()).append(PlatformPropsImpl.NEWLINE)
+ .append(GlueGenVersion.getInstance()).append(PlatformPropsImpl.NEWLINE)
+ .append(JoglVersion.getInstance()).append(PlatformPropsImpl.NEWLINE)
+ .append(PlatformPropsImpl.NEWLINE);
+
JoglVersion.getDefaultOpenGLInfo(null, sb, true);
- return sb.toString();
+ return sb.toString();
}
-
- public static void main(String args[]) {
-
+
+ public static void main(final String args[]) {
+
System.err.println(getInfo());
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java
index 28c4da72f..68d43ac75 100644
--- a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java
+++ b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -32,9 +32,12 @@ import java.util.List;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.opengl.FPSCounter;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
import com.jogamp.newt.Window;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.GLStateKeeper;
import jogamp.newt.driver.android.WindowDriver;
@@ -46,102 +49,174 @@ import android.view.WindowManager;
public class NewtBaseActivity extends Activity {
List<Window> newtWindows = new ArrayList<Window>();
- Animator animator = null;
-
+ List<GLAutoDrawable> glAutoDrawables = new ArrayList<GLAutoDrawable>();
+
+ GLAnimatorControl animator = null;
+
boolean isDelegatedActivity;
Activity rootActivity;
boolean setThemeCalled = false;
-
+
+ protected void startAnimation(final boolean start) {
+ if(null != animator) {
+ final boolean res;
+ if( start ) {
+ if( animator.isPaused() ) {
+ res = animator.resume();
+ } else {
+ res = animator.start();
+ }
+ } else {
+ res = animator.stop();
+ }
+ Log.d(MD.TAG, "Animator global: start "+start+", result "+res);
+ }
+ for(int i=0; i<glAutoDrawables.size(); i++) {
+ final GLAnimatorControl anim = glAutoDrawables.get(i).getAnimator();
+ if(null != anim) {
+ final boolean res;
+ if( start ) {
+ if( anim.isPaused() ) {
+ res = anim.resume();
+ } else {
+ res = anim.start();
+ }
+ } else {
+ res = anim.stop();
+ }
+ Log.d(MD.TAG, "Animator glad["+i+"]: start "+start+", result "+res);
+ }
+ }
+ }
+
public NewtBaseActivity() {
super();
isDelegatedActivity = false;
rootActivity = this;
}
-
- public void setRootActivity(Activity rootActivity) {
- this.isDelegatedActivity = true;
+
+ public void setRootActivity(final Activity rootActivity) {
this.rootActivity = rootActivity;
+ this.isDelegatedActivity = this != rootActivity;
}
-
+
public final boolean isDelegatedActivity() {
return isDelegatedActivity;
}
-
+
public final Activity getActivity() {
return rootActivity;
- }
-
+ }
+
/**
* This is one of the three registration methods (see below).
* <p>
* This methods issues {@link android.view.Window#setContentView(android.view.View, android.view.ViewGroup.LayoutParams) androidWindow.setContenView(newtWindow.getAndroidView())}
* and finally calls {@link #registerNEWTWindow(Window)}.
- * </p>
+ * </p>
* @param androidWindow
* @param newtWindow
+ * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
+ * @see #registerNEWTWindow(Window)
* @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
*/
- public void setContentView(android.view.Window androidWindow, Window newtWindow) {
- newtWindow = newtWindow.getDelegatedWindow();
- if(newtWindow instanceof WindowDriver) {
- adaptTheme4Transparency(newtWindow.getRequestedCapabilities());
- layoutForNEWTWindow(androidWindow, newtWindow);
- WindowDriver newtAWindow = (WindowDriver)newtWindow;
+ public void setContentView(final android.view.Window androidWindow, final Window newtWindow) throws IllegalArgumentException {
+ final Window delegateWindow = newtWindow.getDelegatedWindow();
+ if(delegateWindow instanceof WindowDriver) {
+ adaptTheme4Transparency(delegateWindow.getRequestedCapabilities());
+ layoutForNEWTWindow(androidWindow, delegateWindow);
+ final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
androidWindow.setContentView(newtAWindow.getAndroidView());
- registerNEWTWindow(newtAWindow);
} else {
- throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass());
+ throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass().getName());
}
+ registerNEWTWindow(newtWindow);
}
/**
* This is one of the three registration methods (see below).
* <p>
* This methods issues {@link android.view.Window#addContentView(android.view.View, android.view.ViewGroup.LayoutParams) androidWindow.addContenView(newtWindow.getAndroidView(), params)}
* and finally calls {@link #registerNEWTWindow(Window)}.
- * </p>
+ * </p>
* @param androidWindow
* @param newtWindow
* @param params
- * @see #setContentView(android.view.Window, Window)
+ * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
* @see #registerNEWTWindow(Window)
+ * @see #setContentView(android.view.Window, Window)
*/
- public void addContentView(android.view.Window androidWindow, Window newtWindow, android.view.ViewGroup.LayoutParams params) {
- newtWindow = newtWindow.getDelegatedWindow();
- if(newtWindow instanceof WindowDriver) {
- WindowDriver newtAWindow = (WindowDriver)newtWindow;
+ public void addContentView(final android.view.Window androidWindow, final Window newtWindow, final android.view.ViewGroup.LayoutParams params) throws IllegalArgumentException {
+ final Window delegateWindow = newtWindow.getDelegatedWindow();
+ if(delegateWindow instanceof WindowDriver) {
+ final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
androidWindow.addContentView(newtAWindow.getAndroidView(), params);
- registerNEWTWindow(newtAWindow);
} else {
- throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass());
- }
+ throw new IllegalArgumentException("Given NEWT Window's Delegate is not an Android Window: "+delegateWindow.getClass().getName());
+ }
+ registerNEWTWindow(newtWindow);
}
/**
* This is one of the three registration methods (see below).
* <p>
- * This methods simply registers the given NEWT window to ensure it's destruction at {@link #onDestroy()}.
- * </p>
- *
+ * This methods registers the given NEWT window to ensure it's destruction at {@link #onDestroy()}.
+ * </p>
+ * <p>
+ * If adding a {@link GLAutoDrawable} implementation, the {@link GLAnimatorControl} retrieved by {@link GLAutoDrawable#getAnimator()}
+ * will be used for {@link #onPause()} and {@link #onResume()}.
+ * </p>
+ * <p>
+ * If adding a {@link GLAutoDrawable} implementation, the {@link GLEventListenerState} will preserve it's state
+ * when {@link #onPause()} is being called while not {@link #isFinishing()}. A later {@link #onResume()} will
+ * reinstate the {@link GLEventListenerState}.
+ * </p>
+ *
* @param newtWindow
+ * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
* @see #setContentView(android.view.Window, Window)
* @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
*/
- public void registerNEWTWindow(Window newtWindow) {
+ public void registerNEWTWindow(final Window newtWindow) throws IllegalArgumentException {
+ final Window delegateWindow = newtWindow.getDelegatedWindow();
+ Log.d(MD.TAG, "registerNEWTWindow: Type "+newtWindow.getClass().getName()+", delegate "+delegateWindow.getClass().getName());
+ if(delegateWindow instanceof WindowDriver) {
+ final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
+ newtAWindow.registerActivity(getActivity());
+ } else {
+ throw new IllegalArgumentException("Given NEWT Window's Delegate is not an Android Window: "+delegateWindow.getClass().getName());
+ }
newtWindows.add(newtWindow);
+ if(newtWindow instanceof GLAutoDrawable) {
+ glAutoDrawables.add((GLAutoDrawable)newtWindow);
+ }
+ if(newtWindow instanceof GLStateKeeper) {
+ ((GLStateKeeper)newtWindow).setGLStateKeeperListener(glStateKeeperListener);
+ }
}
-
+ private final GLStateKeeper.Listener glStateKeeperListener = new GLStateKeeper.Listener() {
+ @Override
+ public void glStatePreserveNotify(final GLStateKeeper glsk) {
+ Log.d(MD.TAG, "GLStateKeeper Preserving: 0x"+Integer.toHexString(glsk.hashCode()));
+ }
+ @Override
+ public void glStateRestored(final GLStateKeeper glsk) {
+ Log.d(MD.TAG, "GLStateKeeper Restored: 0x"+Integer.toHexString(glsk.hashCode()));
+ startAnimation(true);
+ }
+ };
+
/**
- * Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window.
+ * Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window.
* <p>
* Must be called before creating the view and adding any content, i.e. setContentView() !
* </p>
* @param androidWindow
* @param newtWindow
*/
- public void layoutForNEWTWindow(android.view.Window androidWindow, Window newtWindow) {
+ public void layoutForNEWTWindow(final android.view.Window androidWindow, final Window newtWindow) {
if(null == androidWindow || null == newtWindow) {
throw new IllegalArgumentException("Android or NEWT Window null");
}
-
+
if( newtWindow.isFullscreen() || newtWindow.isUndecorated() ) {
androidWindow.requestFeature(android.view.Window.FEATURE_NO_TITLE);
}
@@ -150,27 +225,27 @@ public class NewtBaseActivity extends Activity {
androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
} else {
androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
- androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
-
- if(newtWindow.getWidth()>0 && newtWindow.getHeight()>0 && !newtWindow.isFullscreen()) {
+
+ if(newtWindow.getWidth()>0 && newtWindow.getHeight()>0 && !newtWindow.isFullscreen()) {
androidWindow.setLayout(newtWindow.getWidth(), newtWindow.getHeight());
- }
+ }
}
/**
- * Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window.
+ * Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window.
* <p>
* Must be called before creating the view and adding any content, i.e. setContentView() !
* </p>
* @param androidWindow
* @param newtWindow
*/
- public void setFullscreenFeature(android.view.Window androidWindow, boolean fullscreen) {
+ public void setFullscreenFeature(final android.view.Window androidWindow, final boolean fullscreen) {
if(null == androidWindow) {
throw new IllegalArgumentException("Android or Window null");
}
-
+
if( fullscreen ) {
androidWindow.requestFeature(android.view.Window.FEATURE_NO_TITLE);
androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
@@ -180,19 +255,19 @@ public class NewtBaseActivity extends Activity {
androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
-
+
/**
- * Convenient method to set this context's theme to transparency depending on {@link CapabilitiesImmutable#isBackgroundOpaque()}.
+ * Convenient method to set this context's theme to transparency depending on {@link CapabilitiesImmutable#isBackgroundOpaque()}.
* <p>
* Must be called before creating the view and adding any content, i.e. setContentView() !
* </p>
*/
- protected void adaptTheme4Transparency(CapabilitiesImmutable caps) {
+ protected void adaptTheme4Transparency(final CapabilitiesImmutable caps) {
if(!caps.isBackgroundOpaque()) {
setTransparencyTheme();
}
}
-
+
/**
* Convenient method to set this context's theme to transparency.
* <p>
@@ -204,12 +279,12 @@ public class NewtBaseActivity extends Activity {
* </p>
* <p>
* Can be called only once.
- * </p>
+ * </p>
*/
public void setTransparencyTheme() {
if(!setThemeCalled) {
setThemeCalled = true;
- final Context ctx = getActivity().getApplicationContext();
+ final Context ctx = getActivity().getApplicationContext();
final String frn = ctx.getPackageName()+":style/Theme.Transparent";
final int resID = ctx.getResources().getIdentifier("Theme.Transparent", "style", ctx.getPackageName());
if(0 == resID) {
@@ -220,48 +295,72 @@ public class NewtBaseActivity extends Activity {
}
}
}
-
- public void setAnimator(Animator animator) {
+
+ /**
+ * Setting up a global {@Link GLAnimatorControl} for {@link #onPause()} and {@link #onResume()}.
+ * <p>
+ * Note that if adding a {@link GLAutoDrawable} implementation via {@link #registerNEWTWindow(Window)},
+ * {@link #setContentView(android.view.Window, Window)} or {@link #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)}
+ * their {@link GLAnimatorControl} retrieved by {@link GLAutoDrawable#getAnimator()} will be used as well.
+ * In this case, using this global {@Link GLAnimatorControl} is redundant.
+ * </p>
+ * @see #registerNEWTWindow(Window)
+ * @see #setContentView(android.view.Window, Window)
+ * @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
+ */
+ public void setAnimator(final GLAnimatorControl animator) {
this.animator = animator;
if(!animator.isStarted()) {
animator.start();
}
animator.pause();
}
-
+
@Override
public android.view.Window getWindow() {
- return getActivity().getWindow();
+ if( isDelegatedActivity() ) {
+ return getActivity().getWindow();
+ } else {
+ return super.getWindow();
+ }
}
-
+
@Override
- public void onCreate(Bundle savedInstanceState) {
- Log.d(MD.TAG, "onCreate");
+ public void onCreate(final Bundle savedInstanceState) {
+ Log.d(MD.TAG, "onCreate.0");
if(!isDelegatedActivity()) {
super.onCreate(savedInstanceState);
}
+ // Extraordinary cleanup, for cases of 'onCreate()' calls w/ valid states,
+ // i.e. w/o having onDestroy() being called.
+ // Could happened due to spec when App process is killed for memory exhaustion or other reasons.
+ cleanup();
+
jogamp.common.os.android.StaticContext.init(rootActivity.getApplicationContext());
+ Log.d(MD.TAG, "onCreate.X");
}
-
+
@Override
public void onStart() {
- Log.d(MD.TAG, "onStart");
+ Log.d(MD.TAG, "onStart.0");
if(!isDelegatedActivity()) {
super.onStart();
}
+ Log.d(MD.TAG, "onStart.X");
}
-
+
@Override
public void onRestart() {
- Log.d(MD.TAG, "onRestart");
+ Log.d(MD.TAG, "onRestart.0");
if(!isDelegatedActivity()) {
super.onRestart();
}
+ Log.d(MD.TAG, "onRestart.X");
}
@Override
public void onResume() {
- Log.d(MD.TAG, "onResume");
+ Log.d(MD.TAG, "onResume.0");
if(!isDelegatedActivity()) {
super.onResume();
}
@@ -272,49 +371,93 @@ public class NewtBaseActivity extends Activity {
((FPSCounter)win).resetFPSCounter();
}
}
- if(null != animator) {
- animator.resume();
- animator.resetFPSCounter();
- }
+ startAnimation(true);
+ Log.d(MD.TAG, "onResume.X");
}
@Override
public void onPause() {
- Log.d(MD.TAG, "onPause");
- if(null != animator) {
- animator.pause();
- }
- for(int i=0; i<newtWindows.size(); i++) {
- final Window win = newtWindows.get(i);
- win.setVisible(false);
+ Log.d(MD.TAG, "onPause.0");
+ if( !getActivity().isFinishing() ) {
+ int ok=0, fail=0;
+ for(int i=0; i<glAutoDrawables.size(); i++) {
+ final GLAutoDrawable glad = glAutoDrawables.get(i);
+ if(glad instanceof GLStateKeeper) {
+ if( ((GLStateKeeper)glad).preserveGLStateAtDestroy(true) ) {
+ ok++;
+ } else {
+ fail++;
+ }
+ }
+ }
+ Log.d(MD.TAG, "GLStateKeeper.Mark2Preserve: Total "+glAutoDrawables.size()+", OK "+ok+", Fail "+fail);
}
- if(!isDelegatedActivity()) {
+ startAnimation(false);
+ if( !isDelegatedActivity() ) {
super.onPause();
}
+ Log.d(MD.TAG, "onPause.X");
}
@Override
public void onStop() {
- Log.d(MD.TAG, "onStop");
- if(!isDelegatedActivity()) {
- super.onStop();
+ Log.d(MD.TAG, "onStop.0");
+ for(int i=0; i<newtWindows.size(); i++) {
+ final Window win = newtWindows.get(i);
+ win.setVisible(false);
+ }
+ if( !isDelegatedActivity() ) {
+ super.onStop();
}
+ Log.d(MD.TAG, "onStop.X");
}
- @Override
- public void onDestroy() {
- Log.d(MD.TAG, "onDestroy");
- if(null != animator) {
- animator.stop();
- animator = null;
+ /**
+ * Performs cleaning up all references,
+ * <p>
+ * Cleaning and destroying up all preserved GLEventListenerState
+ * and clearing the preserve-flag of all GLStateKeeper.
+ * </p>
+ * <p>
+ * Destroying all GLWindow.
+ * </p>
+ */
+ private void cleanup() {
+ Log.d(MD.TAG, "cleanup.0");
+ int glelsKilled = 0, glelsClean = 0;
+ for(int i=0; i<glAutoDrawables.size(); i++) {
+ final GLAutoDrawable glad = glAutoDrawables.get(i);
+ if(glad instanceof GLStateKeeper) {
+ final GLStateKeeper glsk = (GLStateKeeper)glad;
+ glsk.preserveGLStateAtDestroy(false);
+ final GLEventListenerState glels = glsk.clearPreservedGLState();
+ if( null != glels) {
+ glels.destroy();
+ glelsKilled++;
+ } else {
+ glelsClean++;
+ }
+ }
}
- while(newtWindows.size()>0) {
- final Window win = newtWindows.remove(newtWindows.size()-1);
+ Log.d(MD.TAG, "cleanup.1: GLStateKeeper.ForceDestroy: Total "+glAutoDrawables.size()+", destroyed "+glelsKilled+", clean "+glelsClean);
+ for(int i=0; i<newtWindows.size(); i++) {
+ final Window win = newtWindows.get(i);
win.destroy();
}
+ newtWindows.clear();
+ glAutoDrawables.clear();
+ Log.d(MD.TAG, "cleanup.1: StaticContext.getContext: "+jogamp.common.os.android.StaticContext.getContext());
jogamp.common.os.android.StaticContext.clear();
+ Log.d(MD.TAG, "cleanup.X");
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(MD.TAG, "onDestroy.0");
+ cleanup(); // normal cleanup
if(!isDelegatedActivity()) {
- super.onDestroy();
+ super.onDestroy();
}
- }
+ Log.d(MD.TAG, "onDestroy.X");
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
index a49f1648c..4dd96c9a0 100644
--- a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
+++ b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -33,6 +33,8 @@ import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
+import jogamp.common.os.PlatformPropsImpl;
+
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionUtil;
@@ -47,58 +49,75 @@ import android.widget.ScrollView;
import android.widget.TextView;
public class NewtVersionActivity extends NewtBaseActivity {
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
setFullscreenFeature(getWindow(), true);
final android.view.ViewGroup viewGroup = new android.widget.FrameLayout(getActivity().getApplicationContext());
getWindow().setContentView(viewGroup);
-
+
final TextView tv = new TextView(getActivity());
final ScrollView scroller = new ScrollView(getActivity());
scroller.addView(tv);
viewGroup.addView(scroller, new android.widget.FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, Gravity.TOP|Gravity.LEFT));
-
- tv.setText(VersionUtil.getPlatformInfo()+Platform.NEWLINE+GlueGenVersion.getInstance()+Platform.NEWLINE+JoglVersion.getInstance()+Platform.NEWLINE);
-
- // create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
- GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
- GLWindow glWindow = GLWindow.create(caps);
- glWindow.setUndecorated(true);
- glWindow.setSize(32, 32);
- glWindow.setPosition(0, 0);
- final android.view.View androidGLView = ((WindowDriver)glWindow.getDelegatedWindow()).getAndroidView();
- viewGroup.addView(androidGLView, new android.widget.FrameLayout.LayoutParams(glWindow.getWidth(), glWindow.getHeight(), Gravity.BOTTOM|Gravity.RIGHT));
- registerNEWTWindow(glWindow);
-
- glWindow.addGLEventListener(new GLEventListener() {
- public void init(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
- final StringBuffer sb = new StringBuffer();
- sb.append(JoglVersion.getGLInfo(gl, null)).append(Platform.NEWLINE);
- sb.append("Requested: ").append(Platform.NEWLINE);
- sb.append(drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()).append(Platform.NEWLINE).append(Platform.NEWLINE);
- sb.append("Chosen: ").append(Platform.NEWLINE);
- sb.append(drawable.getChosenGLCapabilities()).append(Platform.NEWLINE).append(Platform.NEWLINE);
- viewGroup.post(new Runnable() {
- public void run() {
- tv.append(sb.toString());
- viewGroup.removeView(androidGLView);
- } } );
- }
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- }
+ final String info1 = "JOGL Version Info"+PlatformPropsImpl.NEWLINE+VersionUtil.getPlatformInfo()+PlatformPropsImpl.NEWLINE+GlueGenVersion.getInstance()+PlatformPropsImpl.NEWLINE+JoglVersion.getInstance()+PlatformPropsImpl.NEWLINE;
+ Log.d(MD.TAG, info1);
+ tv.setText(info1);
+
+ final GLProfile glp;
+ if( GLProfile.isAvailable(GLProfile.GL2ES2) ) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ } else if( GLProfile.isAvailable(GLProfile.GL2ES1) ) {
+ glp = GLProfile.get(GLProfile.GL2ES1);
+ } else {
+ glp = null;
+ tv.append("No GLProfile GL2ES2 nor GL2ES1 available!");
+ }
+ if( null != glp ) {
+ // create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLWindow glWindow = GLWindow.create(caps);
+ glWindow.setUndecorated(true);
+ glWindow.setSize(32, 32);
+ glWindow.setPosition(0, 0);
+ final android.view.View androidGLView = ((WindowDriver)glWindow.getDelegatedWindow()).getAndroidView();
+ viewGroup.addView(androidGLView, new android.widget.FrameLayout.LayoutParams(glWindow.getSurfaceWidth(), glWindow.getSurfaceHeight(), Gravity.BOTTOM|Gravity.RIGHT));
+ registerNEWTWindow(glWindow);
+
+ glWindow.addGLEventListener(new GLEventListener() {
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ final StringBuilder sb = new StringBuilder();
+ sb.append(JoglVersion.getGLInfo(gl, null, true)).append(PlatformPropsImpl.NEWLINE);
+ sb.append("Requested: ").append(PlatformPropsImpl.NEWLINE);
+ sb.append(drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()).append(PlatformPropsImpl.NEWLINE).append(PlatformPropsImpl.NEWLINE);
+ sb.append("Chosen: ").append(PlatformPropsImpl.NEWLINE);
+ sb.append(drawable.getChosenGLCapabilities()).append(PlatformPropsImpl.NEWLINE).append(PlatformPropsImpl.NEWLINE);
+ final String info2 = sb.toString();
+ // Log.d(MD.TAG, info2); // too big!
+ System.err.println(info2);
+ viewGroup.post(new Runnable() {
+ public void run() {
+ tv.append(info2);
+ viewGroup.removeView(androidGLView);
+ } } );
+ }
+
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ }
- public void display(GLAutoDrawable drawable) {
- }
+ public void display(final GLAutoDrawable drawable) {
+ }
- public void dispose(GLAutoDrawable drawable) {
- }
- });
- glWindow.setVisible(true);
+ public void dispose(final GLAutoDrawable drawable) {
+ }
+ });
+ glWindow.setVisible(true);
+ }
Log.d(MD.TAG, "onCreate - X");
- }
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java
index cb8799b19..190f55e71 100644
--- a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java
+++ b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java
@@ -8,14 +8,14 @@ import android.util.Log;
public class NewtVersionActivityLauncher extends Activity {
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- final Uri uri = Uri.parse("launch://jogamp.org/jogamp.newt.driver.android.NewtVersionActivity");
- final Intent intent = new Intent("org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL", uri);
+
+ final Uri uri = Uri.parse("launch://jogamp.org/jogamp.newt.driver.android.NewtVersionActivity?sys=com.jogamp.common&sys=javax.media.opengl&pkg=com.jogamp.opengl.test&jogamp.debug=all&nativewindow.debug=all&jogl.debug=all&newt.debug=all");
+ final Intent intent = new Intent("org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL", uri);
Log.d(getClass().getSimpleName(), "Launching Activity: "+intent);
startActivity (intent);
-
+
finish(); // done
- }
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
index 795aac5fb..b28cdcbed 100644
--- a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -28,12 +28,10 @@
package jogamp.newt.driver.android;
-import javax.media.nativewindow.*;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.DefaultGraphicsScreen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.MonitorModeProps.Cache;
import android.content.Context;
import android.graphics.PixelFormat;
@@ -41,6 +39,9 @@ import android.util.DisplayMetrics;
import android.view.Surface;
import android.view.WindowManager;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
public class ScreenDriver extends jogamp.newt.ScreenImpl {
static {
@@ -50,59 +51,103 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
public ScreenDriver() {
}
+ @Override
protected void createNativeImpl() {
aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
}
+ @Override
protected void closeNativeImpl() { }
- protected ScreenMode getCurrentScreenModeImpl() {
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ return 0; // FIXME: only one screen available ?
+ }
+
+ private final MonitorMode getModeImpl(final Cache cache, final android.view.Display aDisplay, final DisplayMetrics outMetrics, final int modeIdx, final int screenSizeNRot, final int nrot) {
+ final int[] props = new int[MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ i = getScreenSize(outMetrics, screenSizeNRot, props, i); // width, height
+ i = getBpp(aDisplay, props, i); // bpp
+ props[i++] = (int) ( aDisplay.getRefreshRate() * 100.0f ); // Hz * 100
+ props[i++] = 0; // flags
+ props[i++] = modeIdx; // modeId;
+ props[i++] = nrot;
+ return MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+ }
+
+ @Override
+ protected void collectNativeMonitorModesAndDevicesImpl(final Cache cache) {
+ // FIXME: Multi Monitor Implementation missing [for newer Android version ?]
+
final Context ctx = jogamp.common.os.android.StaticContext.getContext();
final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
final DisplayMetrics outMetrics = new DisplayMetrics();
final android.view.Display aDisplay = wmgr.getDefaultDisplay();
aDisplay.getMetrics(outMetrics);
-
+
final int arot = aDisplay.getRotation();
final int nrot = androidRotation2NewtRotation(arot);
- int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
- int offset = 1; // set later for verification of iterator
- offset = getScreenSize(outMetrics, nrot, props, offset);
- offset = getBpp(aDisplay, props, offset);
- offset = getScreenSizeMM(outMetrics, props, offset);
- props[offset++] = (int) aDisplay.getRefreshRate();
- props[offset++] = nrot;
- props[offset - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = offset; // count
- return ScreenModeUtil.streamIn(props, 0);
+
+ final int modeIdx=0; // no native modeId in use - use 0
+ MonitorMode currentMode = null;
+ for(int r=0; r<4; r++) { // for all rotations
+ final int nrot_i = r*MonitorMode.ROTATE_90;
+ final MonitorMode mode = getModeImpl(cache, aDisplay, outMetrics, modeIdx, 0, nrot_i);
+ if( nrot == nrot_i ) {
+ currentMode = mode;
+ }
+ }
+
+ final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ int i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ i = getScreenSizeMM(outMetrics, props, i); // sizeMM
+ props[i++] = 0; // rotated viewport x pixel-units
+ props[i++] = 0; // rotated viewport y pixel-units
+ props[i++] = outMetrics.widthPixels; // rotated viewport width pixel-units
+ props[i++] = outMetrics.heightPixels; // rotated viewport height pixel-units
+ props[i++] = 0; // rotated viewport x window-units
+ props[i++] = 0; // rotated viewport y window-units
+ props[i++] = outMetrics.widthPixels; // rotated viewport width window-units
+ props[i++] = outMetrics.heightPixels; // rotated viewport height window-units
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
}
-
- protected int validateScreenIndex(int idx) {
- return 0; // FIXME: only one screen available ?
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ final Context ctx = jogamp.common.os.android.StaticContext.getContext();
+ final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
+ final DisplayMetrics outMetrics = new DisplayMetrics();
+ final android.view.Display aDisplay = wmgr.getDefaultDisplay();
+ aDisplay.getMetrics(outMetrics);
+
+ final int currNRot = androidRotation2NewtRotation(aDisplay.getRotation());
+ return getModeImpl(null, aDisplay, outMetrics, 0, currNRot, currNRot);
}
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- final ScreenMode sm = getCurrentScreenMode();
- virtualSize.setWidth(sm.getRotatedWidth());
- virtualSize.setHeight(sm.getRotatedHeight());
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return false;
}
-
+
//----------------------------------------------------------------------
// Internals only
//
- static int androidRotation2NewtRotation(int arot) {
+ static int androidRotation2NewtRotation(final int arot) {
switch(arot) {
- case Surface.ROTATION_270: return ScreenMode.ROTATE_270;
- case Surface.ROTATION_180: return ScreenMode.ROTATE_180;
- case Surface.ROTATION_90: return ScreenMode.ROTATE_90;
+ case Surface.ROTATION_270: return MonitorMode.ROTATE_270;
+ case Surface.ROTATION_180: return MonitorMode.ROTATE_180;
+ case Surface.ROTATION_90: return MonitorMode.ROTATE_90;
case Surface.ROTATION_0:
}
- return ScreenMode.ROTATE_0;
+ return MonitorMode.ROTATE_0;
}
- static int getScreenSize(DisplayMetrics outMetrics, int nrot, int[] props, int offset) {
+ static int getScreenSize(final DisplayMetrics outMetrics, final int nrot, final int[] props, int offset) {
// swap width and height, since Android reflects rotated dimension, we don't
- if (ScreenMode.ROTATE_90 == nrot || ScreenMode.ROTATE_270 == nrot) {
+ if (MonitorMode.ROTATE_90 == nrot || MonitorMode.ROTATE_270 == nrot) {
props[offset++] = outMetrics.heightPixels;
props[offset++] = outMetrics.widthPixels;
} else {
@@ -110,8 +155,8 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
props[offset++] = outMetrics.heightPixels;
}
return offset;
- }
- static int getBpp(android.view.Display aDisplay, int[] props, int offset) {
+ }
+ static int getBpp(final android.view.Display aDisplay, final int[] props, int offset) {
int bpp;
switch(aDisplay.getPixelFormat()) {
case PixelFormat.RGBA_8888: bpp=32; break;
@@ -121,18 +166,28 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
case PixelFormat.RGBA_5551: bpp=16; break;
case PixelFormat.RGBA_4444: bpp=16; break;
case PixelFormat.RGB_332: bpp= 8; break;
- default: bpp=32;
- }
- props[offset++] = bpp;
+ default: bpp=32;
+ }
+ props[offset++] = bpp;
return offset;
}
- static int getScreenSizeMM(DisplayMetrics outMetrics, int[] props, int offset) {
- final float iw = (float) outMetrics.widthPixels / outMetrics.xdpi;
- final float ih = (float) outMetrics.heightPixels / outMetrics.xdpi;
+ static int getScreenSizeMM(final DisplayMetrics outMetrics, final int[] props, int offset) {
+ final float inW = outMetrics.widthPixels / outMetrics.xdpi;
+ final float inH = outMetrics.heightPixels / outMetrics.ydpi;
final float mmpi = 25.4f;
- props[offset++] = (int) ((iw * mmpi)+0.5);
- props[offset++] = (int) ((ih * mmpi)+0.5);
+ final float mmW = inW * mmpi;
+ final float mmH = inH * mmpi;
+ if( DEBUG ) {
+ System.err.println("Screen A screen "+outMetrics.widthPixels+" x "+outMetrics.heightPixels);
+ System.err.println("Screen A xy dpi "+outMetrics.xdpi+" x "+outMetrics.ydpi);
+ System.err.println("Screen A densityDPI "+outMetrics.densityDpi);
+ System.err.println("Screen A density "+outMetrics.density);
+ System.err.println("Screen N xy inch "+inW+" x "+inH);
+ System.err.println("Screen N xy mm "+mmW+" x "+mmH);
+ }
+ props[offset++] = Math.round(mmW);
+ props[offset++] = Math.round(mmH);
return offset;
- }
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
index f18520630..786ebb31c 100644
--- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -29,53 +29,144 @@
package jogamp.newt.driver.android;
import jogamp.common.os.android.StaticContext;
+import jogamp.newt.WindowImpl;
import jogamp.newt.driver.android.event.AndroidNewtEventFactory;
+import jogamp.newt.driver.android.event.AndroidNewtEventTranslator;
+import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.Capabilities;
import javax.media.nativewindow.CapabilitiesImmutable;
+import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLException;
+import com.jogamp.common.os.AndroidVersion;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.Window;
import jogamp.opengl.egl.EGL;
+import jogamp.opengl.egl.EGLDisplayUtil;
import jogamp.opengl.egl.EGLGraphicsConfiguration;
import jogamp.opengl.egl.EGLGraphicsConfigurationFactory;
-
+import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.Looper;
import android.os.ResultReceiver;
import android.util.Log;
+import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback2;
+import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.view.SurfaceView;
-import android.view.View;
+import android.view.KeyEvent;
-public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
+
+public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
static {
DisplayDriver.initSingleton();
}
- public static CapabilitiesImmutable fixCaps(boolean matchFormatPrecise, int format, CapabilitiesImmutable rCaps) {
- PixelFormat pf = new PixelFormat();
+ /**
+ * First stage of selecting an Android PixelFormat,
+ * at construction via {@link SurfaceHolder#setFormat(int)}
+ * before native realization!
+ *
+ * @param rCaps requested Capabilities
+ * @return An Android PixelFormat number suitable for {@link SurfaceHolder#setFormat(int)}.
+ */
+ public static final int getSurfaceHolderFormat(final CapabilitiesImmutable rCaps) {
+ int fmt = PixelFormat.UNKNOWN;
+
+ if( !rCaps.isBackgroundOpaque() ) {
+ fmt = PixelFormat.TRANSLUCENT;
+ } else if( rCaps.getRedBits()<=5 &&
+ rCaps.getGreenBits()<=6 &&
+ rCaps.getBlueBits()<=5 &&
+ rCaps.getAlphaBits()==0 ) {
+ fmt = PixelFormat.RGB_565;
+ } else if( rCaps.getAlphaBits()==0 ) {
+ fmt = PixelFormat.RGB_888;
+ } else {
+ fmt = PixelFormat.RGBA_8888;
+ }
+ Log.d(MD.TAG, "getSurfaceHolderFormat: requested: "+rCaps);
+ Log.d(MD.TAG, "getSurfaceHolderFormat: returned: "+fmt);
+
+ return fmt;
+ }
+
+
+ public static final int NATIVE_WINDOW_FORMAT_RGBA_8888 = 1;
+ public static final int NATIVE_WINDOW_FORMAT_RGBX_8888 = 2;
+ public static final int NATIVE_WINDOW_FORMAT_RGB_565 = 4;
+
+ /**
+ * Second stage of selecting an Android PixelFormat,
+ * at right after native (surface) realization at {@link Callback2#surfaceChanged(SurfaceHolder, int, int, int)}.
+ * Selection happens via {@link #setSurfaceVisualID0(long, int)} before native EGL creation.
+ *
+ * @param androidPixelFormat An Android PixelFormat delivered via {@link Callback2#surfaceChanged(SurfaceHolder, int, int, int)} params.
+ * @return A native Android PixelFormat number suitable for {@link #setSurfaceVisualID0(long, int)}.
+ */
+ public static final int getANativeWindowFormat(final int androidPixelFormat) {
+ final int nativePixelFormat;
+ switch(androidPixelFormat) {
+ case PixelFormat.RGBA_8888:
+ case PixelFormat.RGBA_5551:
+ case PixelFormat.RGBA_4444:
+ nativePixelFormat = NATIVE_WINDOW_FORMAT_RGBA_8888;
+ break;
+
+ case PixelFormat.RGBX_8888:
+ case PixelFormat.RGB_888:
+ nativePixelFormat = NATIVE_WINDOW_FORMAT_RGBX_8888;
+ break;
+
+ case PixelFormat.RGB_565:
+ case PixelFormat.RGB_332:
+ nativePixelFormat = NATIVE_WINDOW_FORMAT_RGB_565;
+ break;
+ default: nativePixelFormat = NATIVE_WINDOW_FORMAT_RGBA_8888;
+ }
+ Log.d(MD.TAG, "getANativeWindowFormat: android: "+androidPixelFormat+" -> native "+nativePixelFormat);
+ return nativePixelFormat;
+ }
+
+ /**
+ * Final stage of Android PixelFormat operation,
+ * match the requested Capabilities w/ Android PixelFormat number.
+ * This is done at native realization @ {@link Callback2#surfaceChanged(SurfaceHolder, int, int, int)}.
+ *
+ * @param matchFormatPrecise
+ * @param format
+ * @param rCaps requested Capabilities
+ * @return The fixed Capabilities
+ */
+ public static final CapabilitiesImmutable fixCaps(final boolean matchFormatPrecise, final int format, final CapabilitiesImmutable rCaps) {
+ final PixelFormat pf = new PixelFormat();
PixelFormat.getPixelFormatInfo(format, pf);
- final CapabilitiesImmutable res;
+ final CapabilitiesImmutable res;
int r, g, b, a;
-
+
switch(format) {
- case PixelFormat.RGBA_8888: r=8; g=8; b=8; a=8; break;
- case PixelFormat.RGBX_8888: r=8; g=8; b=8; a=0; break;
+ case PixelFormat.RGBA_8888: r=8; g=8; b=8; a=8; break; // NATIVE_WINDOW_FORMAT_RGBA_8888
+ case PixelFormat.RGBX_8888: r=8; g=8; b=8; a=0; break; // NATIVE_WINDOW_FORMAT_RGBX_8888
case PixelFormat.RGB_888: r=8; g=8; b=8; a=0; break;
- case PixelFormat.RGB_565: r=5; g=6; b=5; a=0; break;
+ case PixelFormat.RGB_565: r=5; g=6; b=5; a=0; break; // NATIVE_WINDOW_FORMAT_RGB_565
case PixelFormat.RGBA_5551: r=5; g=5; b=5; a=1; break;
case PixelFormat.RGBA_4444: r=4; g=4; b=4; a=4; break;
case PixelFormat.RGB_332: r=3; g=3; b=2; a=0; break;
@@ -86,51 +177,25 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
rCaps.getGreenBits() > g &&
rCaps.getBlueBits() > b &&
rCaps.getAlphaBits() > a ;
-
+
if(change) {
- Capabilities nCaps = (Capabilities) rCaps.cloneMutable();
+ final Capabilities nCaps = (Capabilities) rCaps.cloneMutable();
nCaps.setRedBits(r);
nCaps.setGreenBits(g);
nCaps.setBlueBits(b);
nCaps.setAlphaBits(a);
- res = nCaps;
+ res = nCaps;
} else {
res = rCaps;
}
Log.d(MD.TAG, "fixCaps: format: "+format);
Log.d(MD.TAG, "fixCaps: requested: "+rCaps);
Log.d(MD.TAG, "fixCaps: chosen: "+res);
-
+
return res;
}
-
- public static int getFormat(CapabilitiesImmutable rCaps) {
- int fmt = PixelFormat.UNKNOWN;
-
- if(!rCaps.isBackgroundOpaque()) {
- fmt = PixelFormat.TRANSLUCENT;
- } else if(rCaps.getRedBits()<=5 &&
- rCaps.getGreenBits()<=6 &&
- rCaps.getBlueBits()<=5 &&
- rCaps.getAlphaBits()==0) {
- fmt = PixelFormat.RGB_565;
- }
- /* else if(rCaps.getRedBits()<=5 &&
- rCaps.getGreenBits()<=5 &&
- rCaps.getBlueBits()<=5 &&
- rCaps.getAlphaBits()==1) {
- fmt = PixelFormat.RGBA_5551; // FIXME: Supported ?
- } */
- else {
- fmt = PixelFormat.RGBA_8888;
- }
- Log.d(MD.TAG, "getFormat: requested: "+rCaps);
- Log.d(MD.TAG, "getFormat: returned: "+fmt);
-
- return fmt;
- }
-
- public static boolean isAndroidFormatTransparent(int aFormat) {
+
+ public static final boolean isAndroidFormatTransparent(final int aFormat) {
switch (aFormat) {
case PixelFormat.TRANSLUCENT:
case PixelFormat.TRANSPARENT:
@@ -138,53 +203,22 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
}
return false;
}
-
- class AndroidEvents implements View.OnKeyListener, View.OnTouchListener, View.OnFocusChangeListener {
-
- @Override
- public boolean onTouch(View v, android.view.MotionEvent event) {
- final com.jogamp.newt.event.MouseEvent[] newtEvents = AndroidNewtEventFactory.createMouseEvents(event, WindowDriver.this);
- if(null != newtEvents) {
- focusChanged(false, true);
- for(int i=0; i<newtEvents.length; i++) {
- WindowDriver.this.enqueueEvent(false, newtEvents[i]);
- }
- try { Thread.sleep((long) (1000.0F/30.0F)); }
- catch(InterruptedException e) { }
- return true; // consumed/handled, further interest in events
- }
- return false; // no mapping, no further interest in the event!
- }
-
- @Override
- public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
- final com.jogamp.newt.event.KeyEvent[] newtEvents = AndroidNewtEventFactory.createKeyEvents(keyCode, event, WindowDriver.this);
- if(null != newtEvents) {
- for(int i=0; i<newtEvents.length; i++) {
- WindowDriver.this.enqueueEvent(false, newtEvents[i]);
- }
- return true;
- }
- return false;
- }
-
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- WindowDriver.this.focusChanged(false, hasFocus);
- }
-
- }
public static Class<?>[] getCustomConstructorArgumentTypes() {
return new Class<?>[] { Context.class } ;
}
-
+
public WindowDriver() {
reset();
}
- private void reset() {
- ownAndroidWindow = false;
+ public void registerActivity(final Activity activity) {
+ this.activity = activity;
+ }
+ protected Activity activity = null;
+
+ private final void reset() {
+ added2StaticViewGroup = false;
androidView = null;
nativeFormat = VisualIDHolder.VID_UNDEFINED;
androidFormat = VisualIDHolder.VID_UNDEFINED;
@@ -193,93 +227,200 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
surfaceHandle = 0;
eglSurface = 0;
definePosition(0, 0); // default to 0/0
+ defineSize(0, 0); // default size -> TBD !
+
setBrokenFocusChange(true);
}
-
+
+ private final void setupInputListener(final boolean enable) {
+ Log.d(MD.TAG, "setupInputListener(enable "+enable+") - "+Thread.currentThread().getName());
+
+ final AndroidNewtEventTranslator eventTranslator =
+ enable ? new AndroidNewtEventTranslator(this, androidView.getContext(), androidView.getHandler()) : null;
+ androidView.setOnTouchListener(eventTranslator);
+ androidView.setOnKeyListener(eventTranslator);
+ androidView.setOnFocusChangeListener(eventTranslator);
+ if(AndroidVersion.SDK_INT >= 12) { // API Level 12
+ Log.d(MD.TAG, "setupInputListener - enable GenericMotionListener - "+Thread.currentThread().getName());
+ androidView.setOnGenericMotionListener(eventTranslator);
+ }
+ if( enable ) {
+ androidView.post(new Runnable() {
+ public void run() {
+ androidView.setClickable(false);
+ androidView.setFocusable(true);
+ androidView.setFocusableInTouchMode(true);
+ } } );
+ }
+ }
+
+ private final void setupAndroidView(final Context ctx) {
+ androidView = new MSurfaceView(ctx);
+
+ final SurfaceHolder sh = androidView.getHolder();
+ sh.addCallback(WindowDriver.this);
+ sh.setFormat(getSurfaceHolderFormat(getRequestedCapabilities()));
+ }
+
+ public final SurfaceView getAndroidView() { return androidView; }
+
@Override
- protected void instantiationFinished() {
- final Context ctx = StaticContext.getContext();
+ protected final void instantiationFinished() {
+ Log.d(MD.TAG, "instantiationFinished() - "+Thread.currentThread().getName());
+
+ final Context ctx = StaticContext.getContext();
if(null == ctx) {
throw new NativeWindowException("No static [Application] Context has been set. Call StaticContext.setContext(Context) first.");
}
- androidView = new MSurfaceView(ctx);
-
- final AndroidEvents ae = new AndroidEvents();
- androidView.setOnTouchListener(ae);
- androidView.setClickable(false);
- androidView.setOnKeyListener(ae);
- androidView.setOnFocusChangeListener(ae);
- androidView.setFocusable(true);
- androidView.setFocusableInTouchMode(true);
-
- final SurfaceHolder sh = androidView.getHolder();
- sh.addCallback(WindowDriver.this);
- sh.setFormat(getFormat(getRequestedCapabilities()));
-
- // default size -> TBD !
- defineSize(0, 0);
- }
-
- public SurfaceView getAndroidView() { return androidView; }
-
+
+ if( null != Looper.myLooper() ) {
+ setupAndroidView(ctx);
+ }
+ }
+
@Override
- protected boolean canCreateNativeImpl() {
- final boolean b = 0 != surfaceHandle;
- Log.d(MD.TAG, "canCreateNativeImpl: "+b);
+ protected final boolean canCreateNativeImpl() {
+ Log.d(MD.TAG, "canCreateNativeImpl.0: surfaceHandle ready "+(0!=surfaceHandle)+" - on thread "+Thread.currentThread().getName());
+ if(Window.DEBUG_IMPLEMENTATION) {
+ Thread.dumpStack();
+ }
+
+ if( isFullscreen() ) {
+ final MonitorDevice mainMonitor = getMainMonitor();
+ final RectangleImmutable winRect = mainMonitor.getViewportInWindowUnits();
+ definePosition(winRect.getX(), winRect.getY());
+ defineSize(winRect.getWidth(), winRect.getHeight());
+ }
+
+ final boolean b;
+
+ if( 0 == surfaceHandle ) {
+ // Static ViewGroup, i.e. self contained main code
+ final ViewGroup viewGroup = StaticContext.getContentViewGroup();
+ Log.d(MD.TAG, "canCreateNativeImpl: viewGroup "+viewGroup);
+ if( null != viewGroup && !added2StaticViewGroup ) {
+ added2StaticViewGroup = true;
+ viewGroup.post(new Runnable() {
+ public void run() {
+ if(null == androidView) {
+ setupAndroidView( StaticContext.getContext() );
+ }
+ viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(getWidth(), getHeight(), Gravity.BOTTOM|Gravity.RIGHT));
+ Log.d(MD.TAG, "canCreateNativeImpl: added to static ViewGroup - on thread "+Thread.currentThread().getName());
+ } });
+ for(long sleep = TIMEOUT_NATIVEWINDOW; 0<sleep && 0 == surfaceHandle; sleep-=10 ) {
+ try { Thread.sleep(10); } catch (final InterruptedException ie) {}
+ }
+ b = 0 != surfaceHandle;
+ Log.d(MD.TAG, "canCreateNativeImpl: surfaceHandle ready(2) "+b+" - on thread "+Thread.currentThread().getName());
+ } else {
+ // No surfaceHandle defined, No static ViewGroup to add ourselves
+ b = false;
+ }
+ } else {
+ // surfaceHandle already defined
+ b = true;
+ }
return b;
}
@Override
- protected void createNativeImpl() {
- Log.d(MD.TAG, "createNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
- ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName());
+ protected final void createNativeImpl() {
+ // Create own screen/device resource instance allowing independent ownership,
+ // while still utilizing shared EGL resources.
+ final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen();
+ final EGLGraphicsDevice aDevice = (EGLGraphicsDevice) aScreen.getDevice();
+ final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(aDevice.getNativeDisplayID(), aDevice.getConnection(), aDevice.getUnitID());
+ eglDevice.open();
+ final DefaultGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aScreen.getIndex());
+
+ Log.d(MD.TAG, "createNativeImpl 0 - eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
+ ", format [a "+androidFormat+", n "+nativeFormat+"], win["+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+
+ "], pixel["+getSurfaceWidth()+"x"+getSurfaceHeight()+
+ "] - on thread "+Thread.currentThread().getName());
if(0!=getParentWindowHandle()) {
throw new NativeWindowException("Window parenting not supported (yet)");
}
if(0==surfaceHandle) {
- throw new InternalError("XXX");
+ throw new InternalError("surfaceHandle null");
}
-
- final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice();
+
final EGLGraphicsConfiguration eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- capsByFormat, (GLCapabilitiesImmutable) getRequestedCapabilities(),
- (GLCapabilitiesChooser)capabilitiesChooser, getScreen().getGraphicsScreen(), nativeFormat,
- isAndroidFormatTransparent(androidFormat));
+ capsByFormat, (GLCapabilitiesImmutable) getRequestedCapabilities(),
+ (GLCapabilitiesChooser)capabilitiesChooser, eglScreen, nativeFormat, isAndroidFormatTransparent(androidFormat));
if (eglConfig == null) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
final int nativeVisualID = eglConfig.getVisualID(VisualIDHolder.VIDType.NATIVE);
Log.d(MD.TAG, "nativeVisualID 0x"+Integer.toHexString(nativeVisualID));
+ Log.d(MD.TAG, "requestedCaps: "+eglConfig.getRequestedCapabilities());
+ Log.d(MD.TAG, "chosenCaps : "+eglConfig.getChosenCapabilities());
if(VisualIDHolder.VID_UNDEFINED != nativeVisualID) {
setSurfaceVisualID0(surfaceHandle, nativeVisualID);
}
-
+
eglSurface = EGL.eglCreateWindowSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surfaceHandle, null);
if (EGL.EGL_NO_SURFACE==eglSurface) {
throw new NativeWindowException("Creation of window surface failed: "+eglConfig+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+", error "+toHexString(EGL.eglGetError()));
}
-
+
// propagate data ..
setGraphicsConfiguration(eglConfig);
setWindowHandle(surfaceHandle);
+ visibleChanged(false, true);
focusChanged(false, true);
- Log.d(MD.TAG, "createNativeImpl X: eglSurfaceHandle 0x"+Long.toHexString(eglSurface));
+
+ setupInputListener(true);
+
+ Log.d(MD.TAG, "createNativeImpl X: eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", eglSurfaceHandle 0x"+Long.toHexString(eglSurface));
}
@Override
- protected void closeNativeImpl() {
- Log.d(MD.TAG, "closeNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
+ protected final void closeNativeImpl() {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getGraphicsConfiguration().getScreen().getDevice();
+
+ Log.d(MD.TAG, "closeNativeImpl 0 - eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
", eglSurfaceHandle 0x"+Long.toHexString(eglSurface)+
- ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName());
+ ", format [a "+androidFormat+", n "+nativeFormat+"], win["+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+
+ "], pixel["+getSurfaceWidth()+"x"+getSurfaceHeight()+"],"+
+ " - on thread "+Thread.currentThread().getName());
+ if(Window.DEBUG_IMPLEMENTATION) {
+ Thread.dumpStack();
+ }
+
+ setupInputListener(false);
+
if(0 != eglSurface) {
- final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice();
- if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) {
- throw new GLException("Error destroying window surface (eglDestroySurface)");
+ try {
+ if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) {
+ throw new GLException("Error destroying window surface (eglDestroySurface)");
+ }
+ } catch (final Throwable t) {
+ Log.d(MD.TAG, "closeNativeImpl: Catch exception "+t.getMessage());
+ t.printStackTrace();
+ } finally {
+ eglSurface = 0;
}
- eglSurface = 0;
- }
+ }
release0(surfaceHandle);
+
+ eglDevice.close();
+
+ if( null != androidView ) {
+ if( added2StaticViewGroup ) {
+ added2StaticViewGroup = false;
+ final ViewGroup viewGroup = StaticContext.getContentViewGroup();
+ if( null != viewGroup) {
+ viewGroup.post(new Runnable() {
+ public void run() {
+ viewGroup.removeView(androidView);
+ Log.d(MD.TAG, "closeNativeImpl: removed from static ViewGroup - on thread "+Thread.currentThread().getName());
+ } });
+ }
+ }
+ }
+
surface = null;
surfaceHandle = 0;
}
@@ -288,8 +429,21 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
public final long getSurfaceHandle() {
return eglSurface;
}
-
- protected void requestFocusImpl(boolean reparented) {
+
+ /**
+ * <p>
+ * Accessible protected method!
+ * </p>
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public final void focusChanged(final boolean defer, final boolean focusGained) {
+ super.focusChanged(defer, focusGained);
+ }
+
+ @Override
+ protected final void requestFocusImpl(final boolean reparented) {
if(null != androidView) {
Log.d(MD.TAG, "requestFocusImpl: reparented "+reparented);
androidView.post(new Runnable() {
@@ -301,9 +455,10 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
}
}
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+ @Override
+ protected final boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
boolean res = true;
-
+
if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
Log.d(MD.TAG, "reconfigureWindowImpl.setFullscreen post creation (setContentView()) n/a");
return false;
@@ -325,32 +480,34 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
}
}
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
- visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+ visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
return res;
}
- protected Point getLocationOnScreenImpl(int x, int y) {
+ @Override
+ protected final Point getLocationOnScreenImpl(final int x, final int y) {
return new Point(x,y);
}
- protected void updateInsetsImpl(Insets insets) {
- // nop ..
+ @Override
+ protected final void updateInsetsImpl(final Insets insets) {
+ // nop ..
}
-
+
//----------------------------------------------------------------------
- // Virtual On-Screen Keyboard / SoftInput
+ // Virtual On-Screen Keyboard / SoftInput
//
-
+
private class KeyboardVisibleReceiver extends ResultReceiver {
public KeyboardVisibleReceiver() {
super(null);
}
-
- @Override
- public void onReceiveResult(int r, Bundle data) {
+
+ @Override
+ public void onReceiveResult(final int r, final Bundle data) {
boolean v = false;
-
+
switch(r) {
case InputMethodManager.RESULT_UNCHANGED_SHOWN:
case InputMethodManager.RESULT_SHOWN:
@@ -359,41 +516,49 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
case InputMethodManager.RESULT_HIDDEN:
case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
v = false;
- break;
+ break;
}
Log.d(MD.TAG, "keyboardVisible: "+v);
keyboardVisibilityChanged(v);
}
}
- private KeyboardVisibleReceiver keyboardVisibleReceiver = new KeyboardVisibleReceiver();
-
- protected final boolean setKeyboardVisibleImpl(boolean visible) {
+ private final KeyboardVisibleReceiver keyboardVisibleReceiver = new KeyboardVisibleReceiver();
+
+ @Override
+ protected final boolean setKeyboardVisibleImpl(final boolean visible) {
if(null != androidView) {
final InputMethodManager imm = (InputMethodManager) getAndroidView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
final IBinder winid = getAndroidView().getWindowToken();
+ final boolean result;
if(visible) {
// Show soft-keyboard:
- imm.showSoftInput(androidView, 0, keyboardVisibleReceiver);
+ result = imm.showSoftInput(androidView, 0, keyboardVisibleReceiver);
} else {
// hide keyboard :
- imm.hideSoftInputFromWindow(winid, 0, keyboardVisibleReceiver);
+ result = imm.hideSoftInputFromWindow(winid, 0, keyboardVisibleReceiver);
}
- return visible;
+ return result;
} else {
return false; // nop
}
}
-
+
//----------------------------------------------------------------------
- // Surface Callbacks
+ // Surface Callbacks
//
-
- public void surfaceCreated(SurfaceHolder holder) {
- Log.d(MD.TAG, "surfaceCreated: "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
+
+ @Override
+ public final void surfaceCreated(final SurfaceHolder holder) {
+ Log.d(MD.TAG, "surfaceCreated: win["+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+
+ "], pixels["+" "+getSurfaceWidth()+"x"+getSurfaceHeight()+"] - on thread "+Thread.currentThread().getName());
}
- public void surfaceChanged(SurfaceHolder aHolder, int aFormat, int aWidth, int aHeight) {
- Log.d(MD.TAG, "surfaceChanged: f "+nativeFormat+" -> "+aFormat+", "+aWidth+"x"+aHeight+", current surfaceHandle: 0x"+Long.toHexString(surfaceHandle));
+ @Override
+ public final void surfaceChanged(final SurfaceHolder aHolder, final int aFormat, final int aWidth, final int aHeight) {
+ Log.d(MD.TAG, "surfaceChanged: f "+nativeFormat+" -> "+aFormat+", "+aWidth+"x"+aHeight+", current surfaceHandle: 0x"+Long.toHexString(surfaceHandle)+" - on thread "+Thread.currentThread().getName());
+ if(Window.DEBUG_IMPLEMENTATION) {
+ Thread.dumpStack();
+ }
if(0!=surfaceHandle && androidFormat != aFormat ) {
// re-create
Log.d(MD.TAG, "surfaceChanged (destroy old)");
@@ -404,29 +569,35 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
surface=null;
}
if(getScreen().isNativeValid()) {
- getScreen().getCurrentScreenMode(); // if ScreenMode changed .. trigger ScreenMode event
+ // if MonitorMode changed .. trigger MonitorMode event
+ final MonitorDevice mainMonitor = getMainMonitor();
+ mainMonitor.queryCurrentMode();
}
if(0>getX() || 0>getY()) {
positionChanged(false, 0, 0);
}
-
+
if(0 == surfaceHandle) {
androidFormat = aFormat;
surface = aHolder.getSurface();
surfaceHandle = getSurfaceHandle0(surface);
acquire0(surfaceHandle);
+ final int aNativeWindowFormat = getANativeWindowFormat(androidFormat);
+ setSurfaceVisualID0(surfaceHandle, aNativeWindowFormat);
nativeFormat = getSurfaceVisualID0(surfaceHandle);
- final int nWidth = getWidth0(surfaceHandle);
- final int nHeight = getHeight0(surfaceHandle);
+ Log.d(MD.TAG, "surfaceChanged: androidFormat "+androidFormat+" -- (set-native "+aNativeWindowFormat+") --> nativeFormat "+nativeFormat);
+
+ final int[] newSurfSize = { getWidth0(surfaceHandle), getHeight0(surfaceHandle) };
+ final int[] newWinSize = convertToWindowUnits(new int[]{ newSurfSize[0], newSurfSize[1] }); // HiDPI: Not necessary yet ..
capsByFormat = (GLCapabilitiesImmutable) fixCaps(true /* matchFormatPrecise */, nativeFormat, getRequestedCapabilities());
- sizeChanged(false, nWidth, nHeight, false);
-
+ sizeChanged(false, newWinSize[0], newWinSize[1], false);
+
Log.d(MD.TAG, "surfaceRealized: isValid: "+surface.isValid()+
", new surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
- ", format [a "+androidFormat+"/n "+nativeFormat+"], "+
- getX()+"/"+getY()+" "+nWidth+"x"+nHeight+", visible: "+isVisible());
-
+ ", format [a "+androidFormat+"/n "+nativeFormat+"], win["+
+ getX()+"/"+getY()+" "+newWinSize[0]+"x"+newWinSize[1]+"], pixel["+newSurfSize[0]+"x"+newSurfSize[1]+"], visible: "+isVisible());
+
if(isVisible()) {
setVisible(false, true);
}
@@ -435,18 +606,78 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
windowRepaint(0, 0, aWidth, aHeight);
Log.d(MD.TAG, "surfaceChanged: X");
}
-
- public void surfaceDestroyed(SurfaceHolder holder) {
- Log.d(MD.TAG, "surfaceDestroyed");
+
+ @Override
+ public final void surfaceDestroyed(final SurfaceHolder holder) {
+ Log.d(MD.TAG, "surfaceDestroyed - on thread "+Thread.currentThread().getName());
windowDestroyNotify(true); // actually too late .. however ..
+ Thread.dumpStack();
}
- public void surfaceRedrawNeeded(SurfaceHolder holder) {
- Log.d(MD.TAG, "surfaceRedrawNeeded");
- windowRepaint(0, 0, getWidth(), getHeight());
+ @Override
+ public final void surfaceRedrawNeeded(final SurfaceHolder holder) {
+ Log.d(MD.TAG, "surfaceRedrawNeeded - on thread "+Thread.currentThread().getName());
+ windowRepaint(0, 0, getSurfaceWidth(), getSurfaceHeight());
}
-
- private boolean ownAndroidWindow;
+
+ protected boolean handleKeyCodeBack(final KeyEvent.DispatcherState state, final android.view.KeyEvent event) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
+ Log.d(MD.TAG, "handleKeyCodeBack.0 : "+event);
+ state.startTracking(event, this);
+ } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled() && state.isTracking(event)) {
+ // Since we cannot trust the visibility state 'completly',
+ // assume an already invisible state if the invisible operation fails.
+ final boolean wasVisible = setKeyboardVisibleImpl(false);
+ Log.d(MD.TAG, "handleKeyCodeBack.1 : wasVisible "+wasVisible+": "+event);
+ keyboardVisibilityChanged(false);
+ if( wasVisible ) {
+ // event processed, just send invisible event, no activity.finished()
+ enqueueAKey2NKeyUpDown(event, com.jogamp.newt.event.KeyEvent.VK_KEYBOARD_INVISIBLE);
+ return true;
+ } else if( null != activity ) {
+ // process event on our own, since we have an activity to call finish()
+ // and decide in overriden consumeKeyEvent(..) whether we suppress or proceed w/ activity.finish().
+ enqueueAKey2NKeyUpDown(event, com.jogamp.newt.event.KeyEvent.VK_ESCAPE);
+ return true;
+ } else {
+ Log.d(MD.TAG, "handleKeyCodeBack.X1 : "+event);
+ windowDestroyNotify(true);
+ // -> default BACK action, usually activity.finish()
+ }
+ }
+ return false; // continue w/ further processing
+ }
+ private void enqueueAKey2NKeyUpDown(final android.view.KeyEvent aEvent, final short newtKeyCode) {
+ final com.jogamp.newt.event.KeyEvent eDown = AndroidNewtEventFactory.createKeyEvent(aEvent, newtKeyCode, com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED, this);
+ final com.jogamp.newt.event.KeyEvent eUp = AndroidNewtEventFactory.createKeyEvent(aEvent, newtKeyCode, com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED, this);
+ enqueueEvent(false, eDown);
+ enqueueEvent(false, eUp);
+ }
+
+ @Override
+ protected void consumeKeyEvent(final com.jogamp.newt.event.KeyEvent e) {
+ super.consumeKeyEvent(e); // consume event, i.e. call all KeyListener
+ if( com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED == e.getEventType() && !e.isConsumed() ) {
+ if( com.jogamp.newt.event.KeyEvent.VK_ESCAPE == e.getKeyCode() ) {
+ Log.d(MD.TAG, "handleKeyCodeBack.X2 : "+e);
+ activity.finish();
+ } else if( com.jogamp.newt.event.KeyEvent.VK_HOME == e.getKeyCode() ) {
+ Log.d(MD.TAG, "handleKeyCodeHome.X2 : "+e);
+ triggerHome();
+ }
+ }
+ }
+ private void triggerHome() {
+ final Context ctx = StaticContext.getContext();
+ if(null == ctx) {
+ throw new NativeWindowException("No static [Application] Context has been set. Call StaticContext.setContext(Context) first.");
+ }
+ final Intent showOptions = new Intent(Intent.ACTION_MAIN);
+ showOptions.addCategory(Intent.CATEGORY_HOME);
+ ctx.startActivity(showOptions);
+ }
+
+ private boolean added2StaticViewGroup;
private MSurfaceView androidView;
private int nativeFormat; // chosen current native PixelFormat (suitable for EGL)
private int androidFormat; // chosen current android PixelFormat (-1, -2 ..)
@@ -454,20 +685,34 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
private Surface surface;
private volatile long surfaceHandle;
private long eglSurface;
-
+
class MSurfaceView extends SurfaceView {
- public MSurfaceView (Context ctx) {
+ public MSurfaceView (final Context ctx) {
super(ctx);
setBackgroundDrawable(null);
// setBackgroundColor(Color.TRANSPARENT);
}
+
+ @Override
+ public boolean onKeyPreIme(final int keyCode, final KeyEvent event) {
+ Log.d(MD.TAG, "onKeyPreIme : "+event);
+ if ( event.getKeyCode() == KeyEvent.KEYCODE_BACK ) {
+ final KeyEvent.DispatcherState state = getKeyDispatcherState();
+ if (state != null) {
+ return handleKeyCodeBack(state, event);
+ }
+ }
+ return false; // cont. processing
+ }
}
//----------------------------------------------------------------------
// Internals only
//
protected static native boolean initIDs0();
protected static native long getSurfaceHandle0(Surface surface);
+ /** Return the native window format via <code>ANativeWindow_getFormat(..)</code>. */
protected static native int getSurfaceVisualID0(long surfaceHandle);
+ /** Set the native window format via <code>ANativeWindow_setBuffersGeometry(..)</code>. */
protected static native void setSurfaceVisualID0(long surfaceHandle, int nativeVisualID);
protected static native int getWidth0(long surfaceHandle);
protected static native int getHeight0(long surfaceHandle);
diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
index d23b5f576..579edc590 100644
--- a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
+++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,60 +20,99 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.newt.driver.android.event;
-import java.awt.event.MouseEvent;
+import jogamp.newt.Debug;
+import android.view.MotionEvent;
-import com.jogamp.common.util.IntIntHashMap;
-import com.jogamp.newt.Window;
+import com.jogamp.common.os.AndroidVersion;
import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.NEWTEvent;
public class AndroidNewtEventFactory {
+ private static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Android.MouseEvent");
+ private static final boolean DEBUG_KEY_EVENT = Debug.debug("Android.KeyEvent");
- protected static final IntIntHashMap eventTypeANDROID2NEWT;
-
- private static final String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
- "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
-
- static {
- IntIntHashMap map = new IntIntHashMap();
- map.setKeyNotFoundValue(0xFFFFFFFF);
-
- map.put(android.view.MotionEvent.ACTION_DOWN, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED);
- map.put(android.view.MotionEvent.ACTION_UP, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
- map.put(android.view.MotionEvent.ACTION_CANCEL, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
- map.put(android.view.MotionEvent.ACTION_MOVE, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED);
- map.put(android.view.MotionEvent.ACTION_OUTSIDE, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED);
-
- map.put(android.view.MotionEvent.ACTION_POINTER_DOWN, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED);
- map.put(android.view.MotionEvent.ACTION_POINTER_UP, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
-
- map.put(android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
-
- eventTypeANDROID2NEWT = map;
+ /** API Level 12: {@link android.view.MotionEvent#ACTION_SCROLL} = {@value} */
+ private static final int ACTION_SCROLL = 8;
+
+ private static final com.jogamp.newt.event.MouseEvent.PointerType aToolType2PointerType(final int aToolType) {
+ switch( aToolType ) {
+ case MotionEvent.TOOL_TYPE_FINGER:
+ return com.jogamp.newt.event.MouseEvent.PointerType.TouchScreen;
+ case MotionEvent.TOOL_TYPE_MOUSE:
+ return com.jogamp.newt.event.MouseEvent.PointerType.Mouse;
+ case MotionEvent.TOOL_TYPE_STYLUS:
+ case MotionEvent.TOOL_TYPE_ERASER:
+ return com.jogamp.newt.event.MouseEvent.PointerType.Pen;
+ default:
+ return com.jogamp.newt.event.MouseEvent.PointerType.Undefined;
+ }
+ }
+
+ private static final short aMotionEventType2Newt(final int aType) {
+ switch( aType ) {
+ case android.view.MotionEvent.ACTION_DOWN:
+ case android.view.MotionEvent.ACTION_POINTER_DOWN:
+ return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED;
+ case android.view.MotionEvent.ACTION_UP:
+ case android.view.MotionEvent.ACTION_POINTER_UP:
+ case android.view.MotionEvent.ACTION_CANCEL:
+ return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED;
+ case android.view.MotionEvent.ACTION_MOVE:
+ return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED;
+ case android.view.MotionEvent.ACTION_OUTSIDE:
+ return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED;
+ // case ACTION_HOVER_MOVE
+ case ACTION_SCROLL: // API Level 12 !
+ return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+ // case ACTION_HOVER_ENTER
+ // case ACTION_HOVER_EXIT
+ }
+ return (short)0;
+ }
+
+ private static final short aAccessibilityEventType2Newt(final int aType) {
+ switch( aType ) {
+ case android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED:
+ return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+ }
+ return (short)0;
+ }
+
+ private static final short aKeyEventType2NewtEventType(final int androidKeyAction) {
+ switch(androidKeyAction) {
+ case android.view.KeyEvent.ACTION_DOWN:
+ case android.view.KeyEvent.ACTION_MULTIPLE:
+ return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
+ case android.view.KeyEvent.ACTION_UP:
+ return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
+ }
+ return (short)0;
}
- static final int androidKeyCode2Newt(int androidKeyCode) {
+ private static final short aKeyCode2NewtKeyCode(final int androidKeyCode, final boolean inclSysKeys) {
if(android.view.KeyEvent.KEYCODE_0 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_9) {
- return com.jogamp.newt.event.KeyEvent.VK_0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_0 ) ;
+ return (short) ( com.jogamp.newt.event.KeyEvent.VK_0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_0 ) );
}
if(android.view.KeyEvent.KEYCODE_A <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_Z) {
- return com.jogamp.newt.event.KeyEvent.VK_A + ( androidKeyCode - android.view.KeyEvent.KEYCODE_A ) ;
+ return (short) ( com.jogamp.newt.event.KeyEvent.VK_A + ( androidKeyCode - android.view.KeyEvent.KEYCODE_A ) );
}
if(android.view.KeyEvent.KEYCODE_F1 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_F12) {
- return com.jogamp.newt.event.KeyEvent.VK_F1 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_F1 ) ;
+ return (short) ( com.jogamp.newt.event.KeyEvent.VK_F1 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_F1 ) );
}
if(android.view.KeyEvent.KEYCODE_NUMPAD_0 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_NUMPAD_9) {
- return com.jogamp.newt.event.KeyEvent.VK_NUMPAD0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_NUMPAD_0 ) ;
- }
+ return (short) ( com.jogamp.newt.event.KeyEvent.VK_NUMPAD0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_NUMPAD_0 ) );
+ }
switch(androidKeyCode) {
- case android.view.KeyEvent.KEYCODE_COMMA: return com.jogamp.newt.event.KeyEvent.VK_COMMA;
+ case android.view.KeyEvent.KEYCODE_COMMA: return com.jogamp.newt.event.KeyEvent.VK_COMMA;
case android.view.KeyEvent.KEYCODE_PERIOD: return com.jogamp.newt.event.KeyEvent.VK_PERIOD;
case android.view.KeyEvent.KEYCODE_ALT_LEFT: return com.jogamp.newt.event.KeyEvent.VK_ALT;
case android.view.KeyEvent.KEYCODE_ALT_RIGHT: return com.jogamp.newt.event.KeyEvent.VK_ALT_GRAPH;
@@ -82,7 +121,7 @@ public class AndroidNewtEventFactory {
case android.view.KeyEvent.KEYCODE_TAB: return com.jogamp.newt.event.KeyEvent.VK_TAB;
case android.view.KeyEvent.KEYCODE_SPACE: return com.jogamp.newt.event.KeyEvent.VK_SPACE;
case android.view.KeyEvent.KEYCODE_ENTER: return com.jogamp.newt.event.KeyEvent.VK_ENTER;
- case android.view.KeyEvent.KEYCODE_DEL: return com.jogamp.newt.event.KeyEvent.VK_DELETE;
+ case android.view.KeyEvent.KEYCODE_DEL: return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
case android.view.KeyEvent.KEYCODE_MINUS: return com.jogamp.newt.event.KeyEvent.VK_MINUS;
case android.view.KeyEvent.KEYCODE_EQUALS: return com.jogamp.newt.event.KeyEvent.VK_EQUALS;
case android.view.KeyEvent.KEYCODE_LEFT_BRACKET: return com.jogamp.newt.event.KeyEvent.VK_LEFT_PARENTHESIS;
@@ -95,149 +134,231 @@ public class AndroidNewtEventFactory {
// case android.view.KeyEvent.KEYCODE_MUTE: ??
case android.view.KeyEvent.KEYCODE_PAGE_UP: return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP;
case android.view.KeyEvent.KEYCODE_PAGE_DOWN: return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN;
- // case android.view.KeyEvent.KEYCODE_HOME: return com.jogamp.newt.event.KeyEvent.VK_HOME;
- // case android.view.KeyEvent.KEYCODE_BACK: return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
case android.view.KeyEvent.KEYCODE_ESCAPE: return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
case android.view.KeyEvent.KEYCODE_CTRL_LEFT: return com.jogamp.newt.event.KeyEvent.VK_CONTROL;
case android.view.KeyEvent.KEYCODE_CTRL_RIGHT: return com.jogamp.newt.event.KeyEvent.VK_CONTROL; // ??
- }
- return 0;
- }
-
- public static final com.jogamp.newt.event.WindowEvent createWindowEvent(android.view.accessibility.AccessibilityEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeANDROID2NEWT.get(event.getEventType());
- if(0xFFFFFFFF != type) {
- return new com.jogamp.newt.event.WindowEvent(type, ((null==newtSource)?null:(Object)newtSource), event.getEventTime());
+ case android.view.KeyEvent.KEYCODE_BACK:
+ if( inclSysKeys ) {
+ // Note that manual mapping is performed, based on the keyboard state.
+ // I.e. we map to VK_KEYBOARD_INVISIBLE if keyboard was visible and now becomes invisible!
+ // Otherwise we map to VK_ESCAPE, and if not consumed by user, the application will be terminated.
+ return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
+ }
+ break;
+ case android.view.KeyEvent.KEYCODE_HOME:
+ if( inclSysKeys ) {
+ // If not consumed by user, the application will be 'paused',
+ // i.e. resources (GLEventListener) pulled before surface gets destroyed!
+ return com.jogamp.newt.event.KeyEvent.VK_HOME;
+ }
+ break;
}
- return null; // no mapping ..
+ return com.jogamp.newt.event.KeyEvent.VK_UNDEFINED;
}
- static final int androidKeyModifiers2Newt(int androidMods) {
+ private static final int aKeyModifiers2Newt(final int androidMods) {
int newtMods = 0;
if ((androidMods & android.view.KeyEvent.META_SYM_ON) != 0) newtMods |= com.jogamp.newt.event.InputEvent.META_MASK;
if ((androidMods & android.view.KeyEvent.META_SHIFT_ON) != 0) newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
if ((androidMods & android.view.KeyEvent.META_ALT_ON) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
-
+
return newtMods;
}
-
- private static final int androidKeyAction2NewtEventType(int androidKeyAction) {
- switch(androidKeyAction) {
- case android.view.KeyEvent.ACTION_DOWN:
- case android.view.KeyEvent.ACTION_MULTIPLE:
- return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
- case android.view.KeyEvent.ACTION_UP:
- return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
- default:
- return 0;
+
+ public static com.jogamp.newt.event.WindowEvent createWindowEvent(final android.view.accessibility.AccessibilityEvent event, final com.jogamp.newt.Window newtSource) {
+ final int aType = event.getEventType();
+ final short nType = aAccessibilityEventType2Newt(aType);
+
+ if( (short)0 != nType) {
+ return new com.jogamp.newt.event.WindowEvent(nType, ((null==newtSource)?null:(Object)newtSource), event.getEventTime());
}
+ return null; // no mapping ..
}
-
- public static final com.jogamp.newt.event.KeyEvent[] createKeyEvents(int keyCode, android.view.KeyEvent event, com.jogamp.newt.Window newtSource) {
- final int type = androidKeyAction2NewtEventType(event.getAction());
- if(Window.DEBUG_MOUSE_EVENT) {
- System.err.println("createKeyEvent: type 0x"+Integer.toHexString(type)+", keyCode 0x"+Integer.toHexString(keyCode)+", "+event);
- }
- if(0xFFFFFFFF != type) {
- final int newtKeyCode = androidKeyCode2Newt(keyCode);
- if(0 != newtKeyCode) {
- final Object src = (null==newtSource)?null:(Object)newtSource;
- final long unixTime = System.currentTimeMillis() + ( event.getEventTime() - android.os.SystemClock.uptimeMillis() );
- final int newtMods = androidKeyModifiers2Newt(event.getMetaState());
-
- final com.jogamp.newt.event.KeyEvent ke1 = new com.jogamp.newt.event.KeyEvent(
- type, src, unixTime, newtMods, newtKeyCode, event.getDisplayLabel());
-
- if( com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED == type ) {
- return new com.jogamp.newt.event.KeyEvent[] { ke1,
- new com.jogamp.newt.event.KeyEvent(
- com.jogamp.newt.event.KeyEvent.EVENT_KEY_TYPED,
- src, unixTime, newtMods, newtKeyCode, event.getDisplayLabel()) };
- } else {
- return new com.jogamp.newt.event.KeyEvent[] { ke1 };
- }
- }
+
+
+ public static com.jogamp.newt.event.KeyEvent createKeyEvent(final android.view.KeyEvent aEvent, final com.jogamp.newt.Window newtSource, final boolean inclSysKeys) {
+ final com.jogamp.newt.event.KeyEvent res;
+ final short newtType = aKeyEventType2NewtEventType(aEvent.getAction());
+ if( (short)0 != newtType) {
+ final short newtKeyCode = aKeyCode2NewtKeyCode(aEvent.getKeyCode(), inclSysKeys);
+ res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+ } else {
+ res = null;
+ }
+ if(DEBUG_KEY_EVENT) {
+ System.err.println("createKeyEvent0: "+aEvent+" -> "+res);
+ }
+ return res;
+ }
+
+ public static com.jogamp.newt.event.KeyEvent createKeyEvent(final android.view.KeyEvent aEvent, final short newtType, final com.jogamp.newt.Window newtSource, final boolean inclSysKeys) {
+ final short newtKeyCode = aKeyCode2NewtKeyCode(aEvent.getKeyCode(), inclSysKeys);
+ final com.jogamp.newt.event.KeyEvent res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+ if(DEBUG_KEY_EVENT) {
+ System.err.println("createKeyEvent1: newtType "+NEWTEvent.toHexString(newtType)+", "+aEvent+" -> "+res);
+ }
+ return res;
+ }
+
+ public static com.jogamp.newt.event.KeyEvent createKeyEvent(final android.view.KeyEvent aEvent, final short newtKeyCode, final short newtType, final com.jogamp.newt.Window newtSource) {
+ final com.jogamp.newt.event.KeyEvent res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+ if(DEBUG_KEY_EVENT) {
+ System.err.println("createKeyEvent2: newtType "+NEWTEvent.toHexString(newtType)+", "+aEvent+" -> "+res);
+ }
+ return res;
+ }
+
+ private static com.jogamp.newt.event.KeyEvent createKeyEventImpl(final android.view.KeyEvent aEvent, final short newtType, final short newtKeyCode, final com.jogamp.newt.Window newtSource) {
+ if( (short)0 != newtType && com.jogamp.newt.event.KeyEvent.VK_UNDEFINED != newtKeyCode ) {
+ final Object src = null==newtSource ? null : newtSource;
+ final long unixTime = System.currentTimeMillis() + ( aEvent.getEventTime() - android.os.SystemClock.uptimeMillis() );
+ final int newtMods = aKeyModifiers2Newt(aEvent.getMetaState());
+
+ return com.jogamp.newt.event.KeyEvent.create(
+ newtType, src, unixTime, newtMods, newtKeyCode, newtKeyCode, (char) aEvent.getUnicodeChar());
}
return null;
}
- public static final com.jogamp.newt.event.MouseEvent[] createMouseEvents(android.view.MotionEvent event, com.jogamp.newt.Window newtSource) {
- if(Window.DEBUG_MOUSE_EVENT) {
- System.err.println("createMouseEvent: "+toString(event));
+ private static float maxPressure = 0.7f; // experienced maximum value (Amazon HD = 0.8f)
+
+ /**
+ * Dynamic calibration of maximum MotionEvent pressure, starting from 0.7f
+ * <p>
+ * Specification says no pressure is 0.0f and
+ * normal pressure is 1.0f, where &gt; 1.0f denominates very high pressure.
+ * </p>
+ * <p>
+ * Some devices exceed this spec, or better, most devices do.
+ * <ul>
+ * <li>Asus TF2*: Pressure always &gt; 1.0f</li>
+ * <li>Amazon HD: Pressure always &le; 0.8f</li>
+ * </ul>
+ * </p>
+ *
+ * @return
+ */
+ public static float getMaxPressure() {
+ return maxPressure;
+ }
+
+ private final int touchSlop;
+ public AndroidNewtEventFactory(final android.content.Context context, final android.os.Handler handler) {
+ final android.view.ViewConfiguration configuration = android.view.ViewConfiguration.get(context);
+ touchSlop = configuration.getScaledTouchSlop();
+ final int doubleTapSlop = configuration.getScaledDoubleTapSlop();
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("AndroidNewtEventFactory scrollSlop (scaled) "+touchSlop);
+ System.err.println("AndroidNewtEventFactory doubleTapSlop (scaled) "+doubleTapSlop);
}
- int type = eventTypeANDROID2NEWT.get(event.getAction());
- if(0xFFFFFFFF != type) {
- int rotation = 0;
- int clickCount = 1;
+ }
+
+ private static void collectPointerData(final MotionEvent e, final int count, final int[] x, final int[] y, final float[] pressure,
+ final short[] pointerIds, final MouseEvent.PointerType[] pointerTypes) {
+ for(int i=0; i < count; i++) {
+ x[i] = (int)e.getX(i);
+ y[i] = (int)e.getY(i);
+ pressure[i] = e.getPressure(i);
+ pointerIds[i] = (short)e.getPointerId(i);
+ if( pressure[i] > maxPressure ) {
+ maxPressure = pressure[i];
+ }
+ pointerTypes[i] = aToolType2PointerType( e.getToolType(i) );
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("createMouseEvent: ptr-data["+i+"] "+x[i]+"/"+y[i]+", pressure "+pressure[i]+", id "+pointerIds[i]+", type "+pointerTypes[i]);
+ }
+ }
+ }
+
+ public boolean sendPointerEvent(final boolean enqueue, final boolean wait, final boolean setFocusOnDown, final boolean isOnTouchEvent,
+ final android.view.MotionEvent event, final jogamp.newt.driver.android.WindowDriver newtSource) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("createMouseEvent: isOnTouchEvent "+isOnTouchEvent+", "+event);
+ }
+
+ if( event.getPressure() > maxPressure ) {
+ maxPressure = event.getPressure(); // write to static field intended
+ }
+
+ //
+ // Prefilter Android Event (Gesture, ..) and determine final type
+ //
+ final int aType = event.getActionMasked();
+ final short nType = aMotionEventType2Newt(aType);
+ final float rotationScale = touchSlop;
+ final float[] rotationXYZ = new float[] { 0f, 0f, 0f };
+
+ if( (short)0 != nType ) {
int modifiers = 0;
-
- int[] x = new int[event.getPointerCount()];
- int[] y = new int[event.getPointerCount()];
- float[] pressure = new float[event.getPointerCount()];
- int[] pointers = new int[event.getPointerCount()];
- int index = 0;
- while(index < event.getPointerCount()) {
- x[index] = (int)event.getX(index);
- y[index] = (int)event.getY(index);
- pressure[index] = event.getPressure(index);
- pointers[index] = event.getPointerId(index);
- index++;
+
+ //
+ // Determine SDK 12 SCROLL, newt-button and whether dedicated pointer is pressed
+ //
+ final int pIndex;
+ final short button;
+ switch( aType ) {
+ case android.view.MotionEvent.ACTION_POINTER_DOWN:
+ case android.view.MotionEvent.ACTION_POINTER_UP: {
+ pIndex = event.getActionIndex();
+ final int b = event.getPointerId(pIndex) + 1; // FIXME: Assumption that Pointer-ID starts w/ 0 !
+ if( com.jogamp.newt.event.MouseEvent.BUTTON1 <= b && b <= com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ) {
+ button = (short)b;
+ } else {
+ button = com.jogamp.newt.event.MouseEvent.BUTTON1;
+ }
+ }
+ break;
+
+ case ACTION_SCROLL:
+ if( AndroidVersion.SDK_INT >= 12 ) { // API Level 12
+ rotationXYZ[0] = event.getAxisValue(android.view.MotionEvent.AXIS_X) / rotationScale;
+ rotationXYZ[1] = event.getAxisValue(android.view.MotionEvent.AXIS_Y) / rotationScale;
+
+ if( rotationXYZ[0]*rotationXYZ[0] > rotationXYZ[1]*rotationXYZ[1] ) {
+ // Horizontal
+ modifiers |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+ }
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("createMouseEvent: SDK-12 Scroll "+rotationXYZ[0]+"/"+rotationXYZ[1]+", "+rotationScale+", mods "+modifiers);
+ }
+ }
+ // Fall through intended!
+
+ default: {
+ pIndex = 0;
+ button = com.jogamp.newt.event.MouseEvent.BUTTON1;
+ }
}
+ final int pCount = event.getPointerCount(); // all
- if(null!=newtSource) {
- if(newtSource.isPointerConfined()) {
- modifiers |= InputEvent.CONFINED_MASK;
- }
- if(!newtSource.isPointerVisible()) {
- modifiers |= InputEvent.INVISIBLE_MASK;
- }
+ switch( aType ) {
+ case android.view.MotionEvent.ACTION_DOWN:
+ case android.view.MotionEvent.ACTION_POINTER_DOWN:
+ // modifier button-mask will be set on doPointerEvent(..)
+ if( setFocusOnDown ) {
+ newtSource.focusChanged(false, true);
+ }
}
-
- final Object src = (null==newtSource)?null:(Object)newtSource;
- final long unixTime = System.currentTimeMillis() + ( event.getEventTime() - android.os.SystemClock.uptimeMillis() );
- final int button = pointers.length==1 ? MouseEvent.BUTTON1 : 0;
-
- final com.jogamp.newt.event.MouseEvent me1 = new com.jogamp.newt.event.MouseEvent(
- type, src, unixTime,
- modifiers, x, y, pressure, pointers, clickCount,
- button, rotation);
-
- if(type == com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED) {
- return new com.jogamp.newt.event.MouseEvent[] { me1,
- new com.jogamp.newt.event.MouseEvent(
- com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED,
- src, unixTime, modifiers, x, y, pressure, pointers, clickCount,
- button, rotation) };
- } else {
- return new com.jogamp.newt.event.MouseEvent[] { me1 };
+
+ //
+ // Collect common data
+ //
+ final int[] x = new int[pCount];
+ final int[] y = new int[pCount];
+ final float[] pressure = new float[pCount];
+ final short[] pointerIds = new short[pCount];
+ final MouseEvent.PointerType[] pointerTypes = new MouseEvent.PointerType[pCount];
+ if( 0 < pCount ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("createMouseEvent: collect ptr-data [0.."+(pCount-1)+", count "+pCount+", action "+pIndex+"], aType "+aType+", button "+button);
+ }
+ collectPointerData(event, pCount, x, y, pressure, pointerIds, pointerTypes);
}
- }
- return null; // no mapping ..
+ newtSource.doPointerEvent(enqueue, wait, pointerTypes, nType, modifiers,
+ pIndex, pointerIds, button, x, y, pressure, maxPressure, rotationXYZ, rotationScale);
+ return true;
+ }
+ return false; // no mapping ..
}
-
-
- public static String toString(android.view.MotionEvent event) {
- StringBuilder sb = new StringBuilder();
- int action = event.getAction();
- int actionCode = action & android.view.MotionEvent.ACTION_MASK;
- sb.append("ACTION_" ).append(names[actionCode]);
- if (actionCode == android.view.MotionEvent.ACTION_POINTER_DOWN
- || actionCode == android.view.MotionEvent.ACTION_POINTER_UP) {
- sb.append("(pid " ).append(
- action >> android.view.MotionEvent.ACTION_POINTER_ID_SHIFT);
- sb.append(")" );
- }
- sb.append("[" );
- for (int i = 0; i < event.getPointerCount(); i++) {
- sb.append("#" ).append(i);
- sb.append("(pid " ).append(event.getPointerId(i));
- sb.append(")=" ).append((int) event.getX(i));
- sb.append("," ).append((int) event.getY(i));
- if (i + 1 < event.getPointerCount())
- sb.append(";" );
- }
- sb.append("]" );
- return sb.toString();
- }
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java
new file mode 100644
index 000000000..8d20ef448
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java
@@ -0,0 +1,50 @@
+package jogamp.newt.driver.android.event;
+
+import jogamp.newt.driver.android.WindowDriver;
+import android.view.View;
+
+public class AndroidNewtEventTranslator implements View.OnKeyListener, View.OnTouchListener, View.OnFocusChangeListener, View.OnGenericMotionListener {
+ private final WindowDriver newtWindow;
+ private final AndroidNewtEventFactory factory;
+
+ public AndroidNewtEventTranslator(final WindowDriver newtWindow, final android.content.Context context, final android.os.Handler handler) {
+ this.newtWindow = newtWindow;
+ this.factory = new AndroidNewtEventFactory(context, handler);
+ }
+
+ private final boolean processTouchMotionEvents(final View v, final android.view.MotionEvent event, final boolean isOnTouchEvent) {
+ final boolean eventSent = factory.sendPointerEvent(true /*enqueue*/, false /*wait*/, true /*setFocusOnDown*/,
+ isOnTouchEvent, event, newtWindow);
+ if( eventSent ) {
+ try { Thread.sleep((long) (100.0F/3.0F)); } // 33 ms - FIXME ??
+ catch(final InterruptedException e) { }
+ return true; // consumed/handled, further interest in events
+ }
+ return false; // no mapping, no further interest in the event!
+ }
+
+ @Override
+ public boolean onTouch(final View v, final android.view.MotionEvent event) {
+ return processTouchMotionEvents(v, event, true);
+ }
+
+ @Override
+ public boolean onGenericMotion(final View v, final android.view.MotionEvent event) {
+ return processTouchMotionEvents(v, event, false);
+ }
+
+ @Override
+ public boolean onKey(final View v, final int keyCode, final android.view.KeyEvent event) {
+ final com.jogamp.newt.event.KeyEvent newtEvent = AndroidNewtEventFactory.createKeyEvent(event, newtWindow, false /* no system keys */);
+ if(null != newtEvent) {
+ newtWindow.enqueueEvent(false, newtEvent);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onFocusChange(final View v, final boolean hasFocus) {
+ newtWindow.focusChanged(false, hasFocus);
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
index 17eb6a2fb..eccdd63cf 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.awt;
@@ -47,13 +47,15 @@ import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.VisualIDHolder;
-
import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.awt.JAWTWindow;
import com.jogamp.newt.Window;
@SuppressWarnings("serial")
@@ -61,22 +63,27 @@ public class AWTCanvas extends Canvas {
private GraphicsDevice device;
private GraphicsConfiguration chosen;
private AWTGraphicsConfiguration awtConfig;
-
- private WindowDriver newtWindowImpl;
+ private volatile JAWTWindow jawtWindow=null; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
private CapabilitiesChooser chooser=null;
- private CapabilitiesImmutable capabilities;
+ private final CapabilitiesImmutable capabilities;
+ private final UpstreamScalable upstreamScale;
+
+ public static interface UpstreamScalable {
+ int[] getReqPixelScale();
+ void setHasPixelScale(final int[] pixelScale);
+ }
private boolean displayConfigChanged=false;
- public AWTCanvas(WindowDriver newtWindowImpl, CapabilitiesImmutable capabilities, CapabilitiesChooser chooser) {
+ public AWTCanvas(final CapabilitiesImmutable capabilities, final CapabilitiesChooser chooser, final UpstreamScalable upstreamScale) {
super();
- this.newtWindowImpl = newtWindowImpl;
if(null==capabilities) {
throw new NativeWindowException("Capabilities null");
}
this.capabilities=capabilities;
this.chooser=chooser;
+ this.upstreamScale = upstreamScale;
}
public AWTGraphicsConfiguration getAWTGraphicsConfiguration() {
@@ -88,8 +95,8 @@ public class AWTCanvas extends Canvas {
* canvas from interfering with the OpenGL rendering.
*/
@Override
- public void update(Graphics g) {
- paint(g);
+ public void update(final Graphics g) {
+ // paint(g);
}
/** Overridden to cause OpenGL rendering to be performed during
@@ -98,16 +105,16 @@ public class AWTCanvas extends Canvas {
properly.
*/
@Override
- public void paint(Graphics g) {
- newtWindowImpl.windowRepaint(0, 0, getWidth(), getHeight());
+ public void paint(final Graphics g) {
}
-
+
public boolean hasDeviceChanged() {
- boolean res = displayConfigChanged;
+ final boolean res = displayConfigChanged;
displayConfigChanged=false;
return res;
}
+ @Override
public void addNotify() {
/**
@@ -120,8 +127,7 @@ public class AWTCanvas extends Canvas {
*/
awtConfig = chooseGraphicsConfiguration(capabilities, capabilities, chooser, device);
if(Window.DEBUG_IMPLEMENTATION) {
- Exception e = new Exception("Info: Created Config: "+awtConfig);
- e.printStackTrace();
+ System.err.println(getThreadName()+": AWTCanvas.addNotify.0: Created Config: "+awtConfig);
}
if(null==awtConfig) {
throw new NativeWindowException("Error: NULL AWTGraphicsConfiguration");
@@ -137,12 +143,34 @@ public class AWTCanvas extends Canvas {
// after native peer is valid: Windows
disableBackgroundErase();
- GraphicsConfiguration gc = super.getGraphicsConfiguration();
+ {
+ jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
+ // trigger initialization cycle
+ jawtWindow.setSurfaceScale(upstreamScale.getReqPixelScale() );
+ jawtWindow.lockSurface();
+ upstreamScale.setHasPixelScale(jawtWindow.getCurrentSurfaceScale(new int[2]));
+ jawtWindow.unlockSurface();
+ }
+
+ final GraphicsConfiguration gc = super.getGraphicsConfiguration();
if(null!=gc) {
device = gc.getDevice();
}
+ if(Window.DEBUG_IMPLEMENTATION) {
+ System.err.println(getThreadName()+": AWTCanvas.addNotify.X");
+ }
}
+ public NativeWindow getNativeWindow() {
+ final JAWTWindow _jawtWindow = jawtWindow;
+ return (null != _jawtWindow) ? _jawtWindow : null;
+ }
+
+ public boolean isOffscreenLayerSurfaceEnabled() {
+ return null != jawtWindow ? jawtWindow.isOffscreenLayerSurfaceEnabled() : false;
+ }
+
+ @Override
public void removeNotify() {
try {
dispose();
@@ -152,29 +180,39 @@ public class AWTCanvas extends Canvas {
}
private void dispose() {
+ if( null != jawtWindow ) {
+ jawtWindow.destroy();
+ if(Window.DEBUG_IMPLEMENTATION) {
+ System.err.println(getThreadName()+": AWTCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post JAWTWindow: "+jawtWindow);
+ }
+ jawtWindow=null;
+ }
if(null != awtConfig) {
- AbstractGraphicsDevice adevice = awtConfig.getNativeGraphicsConfiguration().getScreen().getDevice();
+ final AbstractGraphicsDevice adevice = awtConfig.getNativeGraphicsConfiguration().getScreen().getDevice();
String adeviceMsg=null;
if(Window.DEBUG_IMPLEMENTATION) {
adeviceMsg = adevice.toString();
}
- boolean closed = adevice.close();
+ final boolean closed = adevice.close();
if(Window.DEBUG_IMPLEMENTATION) {
- System.err.println("AWTCanvas.dispose(): closed GraphicsDevice: "+adeviceMsg+", result: "+closed);
+ System.err.println(getThreadName()+": AWTCanvas.dispose(): closed GraphicsDevice: "+adeviceMsg+", result: "+closed);
}
}
}
+ private String getThreadName() { return Thread.currentThread().getName(); }
+
/**
* Overridden to choose a GraphicsConfiguration on a parent container's
* GraphicsDevice because both devices
*/
+ @Override
public GraphicsConfiguration getGraphicsConfiguration() {
/*
* Workaround for problems with Xinerama and java.awt.Component.checkGD
* when adding to a container on a different graphics device than the
* one that this Canvas is associated with.
- *
+ *
* GC will be null unless:
* - A native peer has assigned it. This means we have a native
* peer, and are already comitted to a graphics configuration.
@@ -188,7 +226,7 @@ public class AWTCanvas extends Canvas {
* chosen is only non-null on platforms where the GLDrawableFactory
* returns a non-null GraphicsConfiguration (in the GLCanvas
* constructor).
- *
+ *
* if gc is from this Canvas' native peer then it should equal chosen,
* otherwise it is from an ancestor component that this Canvas is being
* added to, and we go into this block.
@@ -198,30 +236,30 @@ public class AWTCanvas extends Canvas {
* Check for compatibility with gc. If they differ by only the
* device then return a new GCconfig with the super-class' GDevice
* (and presumably the same visual ID in Xinerama).
- *
+ *
*/
if (!chosen.getDevice().getIDstring().equals(gc.getDevice().getIDstring())) {
/*
* Here we select a GraphicsConfiguration on the alternate
* device that is presumably identical to the chosen
* configuration, but on the other device.
- *
+ *
* Should really check to ensure that we select a configuration
* with the same X visual ID for Xinerama screens, otherwise the
* GLDrawable may have the wrong visual ID (I don't think this
* ever gets updated). May need to add a method to
* X11GLDrawableFactory to do this in a platform specific
* manner.
- *
+ *
* However, on platforms where we can actually get into this
* block, both devices should have the same visual list, and the
* same configuration should be selected here.
*/
- AWTGraphicsConfiguration config = chooseGraphicsConfiguration(
+ final AWTGraphicsConfiguration config = chooseGraphicsConfiguration(
awtConfig.getChosenCapabilities(), awtConfig.getRequestedCapabilities(), chooser, gc.getDevice());
final GraphicsConfiguration compatible = (null!=config)?config.getAWTGraphicsConfiguration():null;
if(Window.DEBUG_IMPLEMENTATION) {
- Exception e = new Exception("Info: Call Stack: "+Thread.currentThread().getName());
+ final Exception e = new Exception("Info: Call Stack: "+Thread.currentThread().getName());
e.printStackTrace();
System.err.println("Created Config (n): HAVE GC "+chosen);
System.err.println("Created Config (n): THIS GC "+gc);
@@ -239,7 +277,7 @@ public class AWTCanvas extends Canvas {
chosen = compatible;
if( !config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities())) {
displayConfigChanged=true;
- }
+ }
awtConfig = config;
}
}
@@ -249,7 +287,7 @@ public class AWTCanvas extends Canvas {
* return the GC that was selected in the constructor (and might
* cause an exception in Component.checkGD when adding to a
* container, but in this case that would be the desired behavior).
- *
+ *
*/
return chosen;
} else if (gc == null) {
@@ -269,14 +307,14 @@ public class AWTCanvas extends Canvas {
return gc;
}
- private static AWTGraphicsConfiguration chooseGraphicsConfiguration(CapabilitiesImmutable capsChosen,
- CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser,
- GraphicsDevice device) {
- final AbstractGraphicsScreen aScreen = null != device ?
+ private static AWTGraphicsConfiguration chooseGraphicsConfiguration(final CapabilitiesImmutable capsChosen,
+ final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser,
+ final GraphicsDevice device) {
+ final AbstractGraphicsScreen aScreen = null != device ?
AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT):
AWTGraphicsScreen.createDefault();
- AWTGraphicsConfiguration config = (AWTGraphicsConfiguration)
+ final AWTGraphicsConfiguration config = (AWTGraphicsConfiguration)
GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, capsChosen.getClass()).chooseGraphicsConfiguration(capsChosen,
capsRequested,
chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
@@ -298,6 +336,7 @@ public class AWTCanvas extends Canvas {
if (!disableBackgroundEraseInitialized) {
try {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
try {
Class<?> clazz = getToolkit().getClass();
@@ -307,16 +346,16 @@ public class AWTCanvas extends Canvas {
clazz.getDeclaredMethod("disableBackgroundErase",
new Class[] { Canvas.class });
disableBackgroundEraseMethod.setAccessible(true);
- } catch (Exception e) {
+ } catch (final Exception e) {
clazz = clazz.getSuperclass();
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
}
return null;
}
});
- } catch (Exception e) {
+ } catch (final Exception e) {
}
disableBackgroundEraseInitialized = true;
if(Window.DEBUG_IMPLEMENTATION) {
@@ -328,7 +367,7 @@ public class AWTCanvas extends Canvas {
Throwable t=null;
try {
disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this });
- } catch (Exception e) {
+ } catch (final Exception e) {
// FIXME: workaround for 6504460 (incorrect backport of 6333613 in 5.0u10)
// throw new GLException(e);
t = e;
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
index 8771f5c74..39e68e48c 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
@@ -30,27 +30,30 @@ package jogamp.newt.driver.awt;
import java.awt.EventQueue;
+import javax.media.nativewindow.NativeWindowException;
+
+import com.jogamp.common.util.RunnableTask;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
import com.jogamp.newt.util.EDTUtil;
-import jogamp.common.awt.AWTEDTExecutor;
import jogamp.newt.Debug;
public class AWTEDTUtil implements EDTUtil {
public static final boolean DEBUG = Debug.debug("EDT");
-
+
private final Object edtLock = new Object(); // locking the EDT start/stop state
- private final ThreadGroup threadGroup;
+ private final ThreadGroup threadGroup;
private final String name;
private final Runnable dispatchMessages;
- private NewtEventDispatchThread nedt = null;
+ private NEDT nedt = null;
private int start_iter=0;
private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
- public AWTEDTUtil(ThreadGroup tg, String name, Runnable dispatchMessages) {
+ public AWTEDTUtil(final ThreadGroup tg, final String name, final Runnable dispatchMessages) {
this.threadGroup = tg;
this.name=Thread.currentThread().getName()+"-"+name+"-EDT-";
this.dispatchMessages=dispatchMessages;
- this.nedt = new NewtEventDispatchThread(threadGroup, name);
+ this.nedt = new NEDT(threadGroup, name);
this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
}
@@ -60,31 +63,38 @@ public class AWTEDTUtil implements EDTUtil {
}
@Override
- final public void setPollPeriod(long ms) {
- pollPeriod = ms;
+ final public void setPollPeriod(final long ms) {
+ pollPeriod = ms; // writing to static field is intended
}
-
+
@Override
- final public void reset() {
- synchronized(edtLock) {
- waitUntilStopped();
+ public final void start() throws IllegalStateException {
+ synchronized(edtLock) {
+ if( nedt.isRunning() ) {
+ throw new IllegalStateException("EDT still running and not subject to stop. Curr "+Thread.currentThread().getName()+", NEDT "+nedt.getName()+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", on AWT-EDT "+EventQueue.isDispatchThread());
+ }
if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT reset - edt: "+nedt);
+ System.err.println(Thread.currentThread()+": AWT-EDT reset - edt: "+nedt);
}
- this.nedt = new NewtEventDispatchThread(threadGroup, name);
- this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ if( nedt.getState() != Thread.State.NEW ) {
+ nedt = new NEDT(threadGroup, name);
+ nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+ startImpl();
+ }
+ if( !nedt.isRunning() ) {
+ throw new RuntimeException("EDT could not be started: "+nedt);
}
}
private final void startImpl() {
if(nedt.isAlive()) {
- throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt);
+ throw new RuntimeException("AWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", edt: "+nedt);
}
start_iter++;
nedt.setName(name+start_iter);
- nedt.shouldStop = false;
if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT START - edt: "+nedt);
+ System.err.println(Thread.currentThread()+": AWT-EDT START - edt: "+nedt);
// Thread.dumpStack();
}
nedt.start();
@@ -99,100 +109,148 @@ public class AWTEDTUtil implements EDTUtil {
public final boolean isCurrentThreadNEDT() {
return nedt == Thread.currentThread();
}
-
+
@Override
public final boolean isCurrentThreadEDTorNEDT() {
- return EventQueue.isDispatchThread() || nedt == Thread.currentThread();
+ return EventQueue.isDispatchThread() || nedt == Thread.currentThread();
}
-
+
@Override
final public boolean isRunning() {
- return nedt.isRunning() ; // AWT is always running
+ return nedt.isRunning() ;
}
@Override
- public final void invokeStop(Runnable task) {
- invokeImpl(true, task, true);
+ public final boolean invokeStop(final boolean wait, final Runnable task) {
+ return invokeImpl(wait, task, true);
}
@Override
- public final void invoke(boolean wait, Runnable task) {
- invokeImpl(wait, task, false);
+ public final boolean invoke(final boolean wait, final Runnable task) {
+ return invokeImpl(wait, task, false);
}
-
- private void invokeImpl(boolean wait, Runnable task, boolean stop) {
- if(task == null) {
- throw new RuntimeException("Null Runnable");
- }
- synchronized(edtLock) { // lock the EDT status
- if( nedt.shouldStop ) {
- // drop task ..
- if(DEBUG) {
- System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+nedt);
- Thread.dumpStack();
+
+ private final boolean invokeImpl(boolean wait, final Runnable task, final boolean stop) {
+ Throwable throwable = null;
+ RunnableTask rTask = null;
+ final Object rTaskLock = new Object();
+ synchronized(rTaskLock) { // lock the optional task execution
+ synchronized(edtLock) { // lock the EDT status
+ if( nedt.shouldStop ) {
+ // drop task ..
+ System.err.println(Thread.currentThread()+": Warning: AWT-EDT about (1) to stop, won't enqueue new task: "+nedt);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ return false;
}
- return;
- }
- // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
- // Thread.dumpStack();
- if(stop) {
- nedt.shouldStop = true;
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt);
- // Thread.dumpStack();
+ if( isCurrentThreadEDT() ) {
+ if(null != task) {
+ task.run();
+ }
+ wait = false; // running in same thread (EDT) -> no wait
+ if(stop) {
+ nedt.shouldStop = true;
+ }
+ } else {
+ if( !nedt.isRunning ) {
+ if( null != task ) {
+ if( stop ) {
+ System.err.println(Thread.currentThread()+": Warning: AWT-EDT is about (3) to stop and stopped already, dropping task. NEDT "+nedt);
+ } else {
+ System.err.println(Thread.currentThread()+": Warning: AWT-EDT is not running, dropping task. NEDT "+nedt);
+ }
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ }
+ return false;
+ } else if( stop ) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": AWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop);
+ }
+ synchronized(nedt.sync) {
+ nedt.shouldStop = true;
+ nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
+ }
+ }
+
+ if(null != task) {
+ rTask = new RunnableTask(task,
+ wait ? rTaskLock : null,
+ true /* always catch and report Exceptions, don't disturb EDT */,
+ wait ? null : System.err);
+ AWTEDTExecutor.singleton.invoke(false, rTask);
+ }
}
}
-
- // start if should not stop && not started yet
- if( !stop && !nedt.isRunning() ) {
- startImpl();
+ if( wait ) {
+ try {
+ rTaskLock.wait(); // free lock, allow execution of rTask
+ } catch (final InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rTask.getThrowable();
+ }
+ if(null!=throwable) {
+ if(throwable instanceof NativeWindowException) {
+ throw (NativeWindowException)throwable;
+ }
+ throw new RuntimeException(throwable);
+ }
}
+ return true;
}
- AWTEDTExecutor.singleton.invoke(wait, task);
- }
+ }
@Override
- final public void waitUntilIdle() {
- final NewtEventDispatchThread _edt;
+ final public boolean waitUntilIdle() {
+ final NEDT _edt;
synchronized(edtLock) {
_edt = nedt;
}
- if(!_edt.isRunning() || EventQueue.isDispatchThread() || _edt == Thread.currentThread()) {
- return;
+ if(!_edt.isRunning || _edt == Thread.currentThread() || EventQueue.isDispatchThread()) {
+ return false;
}
try {
AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ @Override
public void run() { }
});
- } catch (Exception e) { }
+ } catch (final Exception e) { }
+ return true;
}
@Override
- final public void waitUntilStopped() {
+ final public boolean waitUntilStopped() {
synchronized(edtLock) {
- if(nedt.isRunning() && nedt != Thread.currentThread() ) {
- while(nedt.isRunning()) {
+ if( nedt.isRunning && nedt != Thread.currentThread() && !EventQueue.isDispatchThread() ) {
+ while( nedt.isRunning ) {
try {
edtLock.wait();
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
e.printStackTrace();
}
}
+ return true;
+ } else {
+ return false;
}
}
}
-
- class NewtEventDispatchThread extends Thread {
+
+ class NEDT extends Thread {
volatile boolean shouldStop = false;
volatile boolean isRunning = false;
Object sync = new Object();
- public NewtEventDispatchThread(ThreadGroup tg, String name) {
+ public NEDT(final ThreadGroup tg, final String name) {
super(tg, name);
}
final public boolean isRunning() {
- return isRunning;
+ return isRunning && !shouldStop;
}
@Override
@@ -201,58 +259,55 @@ public class AWTEDTUtil implements EDTUtil {
super.start();
}
- /**
+ /**
* Utilizing locking only on tasks and its execution,
* not for event dispatching.
*/
@Override
final public void run() {
if(DEBUG) {
- System.err.println(getName()+": EDT run() START "+ getName());
+ System.err.println(getName()+": AWT-EDT run() START "+ getName());
}
RuntimeException error = null;
try {
do {
// event dispatch
if(!shouldStop) {
- // FIXME: Determine whether we require to run the
- // delivery of events (dispatch) on AWT-EDT.
- // Since the WindowDriver itself delivers all Window related events,
- // this shall not be required.
- // AWTEDTExecutor.singleton.invoke(true, dispatchMessages);
- dispatchMessages.run();
+ // EDT invoke thread is AWT-EDT,
+ // hence dispatching is required to run on AWT-EDT as well.
+ // Otherwise a deadlock may happen due to dispatched event's
+ // triggering a locking action.
+ AWTEDTExecutor.singleton.invoke(true, dispatchMessages);
}
// wait
synchronized(sync) {
if(!shouldStop) {
try {
sync.wait(pollPeriod);
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
} while(!shouldStop) ;
- } catch (Throwable t) {
+ } catch (final Throwable t) {
// handle errors ..
shouldStop = true;
if(t instanceof RuntimeException) {
error = (RuntimeException) t;
} else {
- error = new RuntimeException("Within EDT", t);
+ error = new RuntimeException("Within AWT-EDT", t);
}
} finally {
if(DEBUG) {
- System.err.println(getName()+": EDT run() END "+ getName()+", "+error);
+ System.err.println(getName()+": AWT-EDT run() END "+ getName()+", "+error);
}
synchronized(edtLock) {
- isRunning = !shouldStop;
- if(!isRunning) {
- edtLock.notifyAll();
- }
+ isRunning = false;
+ edtLock.notifyAll();
}
if(DEBUG) {
- System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error);
+ System.err.println(getName()+": AWT-EDT run() EXIT "+ getName()+", exception: "+error);
}
if(null!=error) {
throw error;
@@ -260,7 +315,7 @@ public class AWTEDTUtil implements EDTUtil {
} // finally
} // run()
} // EventDispatchThread
-
+
}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
index 70e9ba570..23da69dba 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,34 +29,37 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.awt;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.util.EDTUtil;
-import jogamp.newt.DefaultEDTUtil;
import jogamp.newt.DisplayImpl;
public class DisplayDriver extends DisplayImpl {
public DisplayDriver() {
}
+ @Override
protected void createNativeImpl() {
aDevice = AWTGraphicsDevice.createDefault();
}
- protected void setAWTGraphicsDevice(AWTGraphicsDevice d) {
+ protected void setAWTGraphicsDevice(final AWTGraphicsDevice d) {
aDevice = d;
}
+ @Override
protected EDTUtil createEDTUtil() {
final EDTUtil def;
if(NewtFactory.useEDT()) {
- def = new AWTEDTUtil(Thread.currentThread().getThreadGroup(), "AWTDisplay-"+getFQName(), dispatchMessagesRunnable);
+ def = new AWTEDTUtil(Thread.currentThread().getThreadGroup(), "AWTDisplay-"+getFQName(), dispatchMessagesRunnable);
if(DEBUG) {
System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName());
}
@@ -66,8 +69,12 @@ public class DisplayDriver extends DisplayImpl {
return def;
}
- protected void closeNativeImpl() { }
+ @Override
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
+ aDevice.close();
+ }
+ @Override
protected void dispatchMessagesNative() { /* nop */ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
index 6b1283a00..57948cfc3 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,29 +28,33 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.awt;
import java.awt.DisplayMode;
+import java.awt.GraphicsDevice;
+import jogamp.newt.MonitorModeProps.Cache;
+import jogamp.newt.MonitorModeProps;
import jogamp.newt.ScreenImpl;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
public class ScreenDriver extends ScreenImpl {
public ScreenDriver() {
}
+ @Override
protected void createNativeImpl() {
aScreen = new AWTGraphicsScreen((AWTGraphicsDevice)display.getGraphicsDevice());
}
- protected void setAWTGraphicsScreen(AWTGraphicsScreen s) {
+ protected void setAWTGraphicsScreen(final AWTGraphicsScreen s) {
aScreen = s;
}
@@ -62,20 +66,70 @@ public class ScreenDriver extends ScreenImpl {
super.updateVirtualScreenOriginAndSize();
}
+ @Override
protected void closeNativeImpl() { }
-
- protected int validateScreenIndex(int idx) {
- return idx; // pass through ...
- }
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- final DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode();
- if(null != mode) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(mode.getWidth());
- virtualSize.setHeight(mode.getHeight());
+
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ return idx; // pass through ...
+ }
+
+ private static MonitorMode getModeProps(final Cache cache, final DisplayMode mode) {
+ int rate = mode.getRefreshRate();
+ if( DisplayMode.REFRESH_RATE_UNKNOWN == rate ) {
+ rate = ScreenImpl.default_sm_rate;
+ }
+ int bpp = mode.getBitDepth();
+ if( DisplayMode.BIT_DEPTH_MULTI == bpp ) {
+ bpp= ScreenImpl.default_sm_bpp;
}
+ final int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = mode.getWidth();
+ props[i++] = mode.getHeight();
+ props[i++] = bpp;
+ props[i++] = rate * 100;
+ props[i++] = 0; // flags
+ props[i++] = 0; // mode_idx
+ props[i++] = 0; // rotation
+ return MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
}
-
+
+ @Override
+ protected void collectNativeMonitorModesAndDevicesImpl(final Cache cache) {
+ final GraphicsDevice awtGD = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice();
+ final DisplayMode[] awtModes = awtGD.getDisplayModes();
+ for(int i=0; i<awtModes.length; i++) {
+ getModeProps(cache, awtModes[i]);
+ }
+ final MonitorMode currentMode = getModeProps(cache, awtGD.getDisplayMode());
+
+ final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ int i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+ props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+ props[i++] = 0; // rotated viewport x pixel-units
+ props[i++] = 0; // rotated viewport y pixel-units
+ props[i++] = currentMode.getRotatedWidth(); // rotated viewport width pixel-units
+ props[i++] = currentMode.getRotatedHeight(); // rotated viewport height pixel-units
+ props[i++] = 0; // rotated viewport x window-units
+ props[i++] = 0; // rotated viewport y window-units
+ props[i++] = currentMode.getRotatedWidth(); // rotated viewport width window-units
+ props[i++] = currentMode.getRotatedHeight(); // rotated viewport height window-units
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return null;
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return false;
+ }
+
}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java
index bee43a95e..06dcb8ff5 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.awt;
@@ -40,11 +40,15 @@ import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Insets;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.util.Point;
+import jogamp.nativewindow.awt.AWTMisc;
import jogamp.newt.WindowImpl;
+import com.jogamp.common.os.Platform;
import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
@@ -68,146 +72,205 @@ public class WindowDriver extends WindowImpl {
return new Class<?>[] { Container.class } ;
}
- public WindowDriver(Container container) {
+ public WindowDriver(final Container container) {
super();
- this.container = container;
+ this.awtContainer = container;
if(container instanceof Frame) {
- frame = (Frame) container;
+ awtFrame = (Frame) container;
}
}
private boolean owningFrame;
- private Container container = null;
- private Frame frame = null; // same instance as container, just for impl. convenience
- private AWTCanvas canvas;
+ private Container awtContainer = null;
+ /** same instance as container, just for impl. convenience */
+ private Frame awtFrame = null;
+ private AWTCanvas awtCanvas;
- protected void requestFocusImpl(boolean reparented) {
- container.requestFocus();
+ @Override
+ protected void requestFocusImpl(final boolean reparented) {
+ awtContainer.requestFocus();
}
@Override
protected void setTitleImpl(final String title) {
- if (frame != null) {
- frame.setTitle(title);
+ if (awtFrame != null) {
+ awtFrame.setTitle(title);
}
}
+ private final AWTCanvas.UpstreamScalable upstreamScalable = new AWTCanvas.UpstreamScalable() {
+ @Override
+ public int[] getReqPixelScale() {
+ return WindowDriver.this.reqPixelScale;
+ }
+
+ @Override
+ public void setHasPixelScale(final int[] pixelScale) {
+ System.arraycopy(pixelScale, 0, WindowDriver.this.hasPixelScale, 0, 2);
+ }
+ };
+
+ @Override
protected void createNativeImpl() {
if(0!=getParentWindowHandle()) {
throw new RuntimeException("Window parenting not supported in AWT, use AWTWindow(Frame) cstr for wrapping instead");
}
- if(null==container) {
- frame = new Frame();
- container = frame;
+ if(null==awtContainer) {
+ awtFrame = new Frame();
+ awtContainer = awtFrame;
owningFrame=true;
} else {
owningFrame=false;
- defineSize(container.getWidth(), container.getHeight());
- definePosition(container.getX(), container.getY());
+ defineSize(awtContainer.getWidth(), awtContainer.getHeight());
+ definePosition(awtContainer.getX(), awtContainer.getY());
}
- if(null!=frame) {
- frame.setTitle(getTitle());
+ if(null!=awtFrame) {
+ awtFrame.setTitle(getTitle());
+ }
+ awtContainer.setLayout(new BorderLayout());
+
+ if( null == awtCanvas ) {
+ awtCanvas = new AWTCanvas(capsRequested, WindowDriver.this.capabilitiesChooser, upstreamScalable);
+
+ // canvas.addComponentListener(listener);
+ awtContainer.add(awtCanvas, BorderLayout.CENTER);
+
+ // via EDT ..
+ new AWTMouseAdapter(this).addTo(awtCanvas); // fwd all AWT Mouse events to here
+ new AWTKeyAdapter(this).addTo(awtCanvas); // fwd all AWT Key events to here
+
+ // direct w/o EDT
+ new AWTWindowAdapter(new LocalWindowListener(), this).addTo(awtCanvas); // fwd all AWT Window events to here
}
- container.setLayout(new BorderLayout());
-
- canvas = new AWTCanvas(this, capsRequested, WindowDriver.this.capabilitiesChooser);
-
- // canvas.addComponentListener(listener);
- container.add(canvas, BorderLayout.CENTER);
-
- // via EDT ..
- new AWTMouseAdapter(this).addTo(canvas); // fwd all AWT Mouse events to here
- new AWTKeyAdapter(this).addTo(canvas); // fwd all AWT Key events to here
-
- // direct w/o EDT
- new AWTWindowAdapter(new LocalWindowListener(), this).addTo(canvas); // fwd all AWT Window events to here
reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true));
// throws exception if failed ..
-
- setWindowHandle(1); // just a marker ..
+
+ final NativeWindow nw = awtCanvas.getNativeWindow();
+ if( null != nw ) {
+ setGraphicsConfiguration( awtCanvas.getAWTGraphicsConfiguration() );
+ setWindowHandle( nw.getWindowHandle() );
+ }
}
+ @Override
protected void closeNativeImpl() {
- setWindowHandle(0); // just a marker ..
- if(null!=container) {
- container.setVisible(false);
- container.remove(canvas);
- container.setEnabled(false);
- canvas.setEnabled(false);
+ setWindowHandle(0);
+ if(null!=awtContainer) {
+ awtContainer.setVisible(false);
+ awtContainer.remove(awtCanvas);
+ awtContainer.setEnabled(false);
+ awtCanvas.setEnabled(false);
}
- if(owningFrame && null!=frame) {
- frame.dispose();
+ if(owningFrame && null!=awtFrame) {
+ awtFrame.dispose();
owningFrame=false;
- frame = null;
}
+ awtCanvas = null;
+ awtFrame = null;
+ awtContainer = null;
}
@Override
public boolean hasDeviceChanged() {
- boolean res = canvas.hasDeviceChanged();
+ final boolean res = awtCanvas.hasDeviceChanged();
if(res) {
- final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration();
+ final AWTGraphicsConfiguration cfg = awtCanvas.getAWTGraphicsConfiguration();
if (null == cfg) {
throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this);
}
setGraphicsConfiguration(cfg);
-
+
// propagate new info ..
((ScreenDriver)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)cfg.getScreen());
((DisplayDriver)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)cfg.getScreen().getDevice());
-
+
((ScreenDriver)getScreen()).updateVirtualScreenOriginAndSize();
}
return res;
}
- protected void updateInsetsImpl(javax.media.nativewindow.util.Insets insets) {
- Insets contInsets = container.getInsets();
- insets.setLeftWidth(contInsets.left);
- insets.setRightWidth(contInsets.right);
- insets.setTopHeight(contInsets.top);
- insets.setBottomHeight(contInsets.bottom);
+ @Override
+ protected void updateInsetsImpl(final javax.media.nativewindow.util.Insets insets) {
+ final Insets contInsets = awtContainer.getInsets();
+ insets.set(contInsets.left, contInsets.right, contInsets.top, contInsets.bottom);
}
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
- if(0 != ( FLAG_CHANGE_DECORATION & flags) && null!=frame) {
- if(!container.isDisplayable()) {
- frame.setUndecorated(isUndecorated());
+ private void setCanvasSizeImpl(final int width, final int height) {
+ final Dimension szClient = new Dimension(width, height);
+ final java.awt.Window awtWindow = AWTMisc.getWindow(awtCanvas);
+ final Container c= null != awtWindow ? awtWindow : awtContainer;
+ awtCanvas.setMinimumSize(szClient);
+ awtCanvas.setPreferredSize(szClient);
+ if(DEBUG_IMPLEMENTATION) {
+ final Insets insets = c.getInsets();
+ final Dimension szContainer = new Dimension(width + insets.left + insets.right,
+ height + insets.top + insets.bottom);
+ System.err.println(getThreadName()+": AWTWindow setCanvasSize: szClient "+szClient+", szCont "+szContainer+", insets "+insets);
+ }
+ awtCanvas.setSize(szClient);
+ awtCanvas.invalidate();
+ if(null != awtWindow) {
+ awtWindow.pack();
+ } else {
+ awtContainer.validate();
+ }
+ }
+ private void setFrameSizeImpl(final int width, final int height) {
+ final Insets insets = awtContainer.getInsets();
+ final Dimension szContainer = new Dimension(width + insets.left + insets.right,
+ height + insets.top + insets.bottom);
+ if(DEBUG_IMPLEMENTATION) {
+ final Dimension szClient = new Dimension(width, height);
+ System.err.println(getThreadName()+": AWTWindow setFrameSize: szClient "+szClient+", szCont "+szContainer+", insets "+insets);
+ }
+ awtContainer.setSize(szContainer);
+ awtCanvas.invalidate();
+ awtContainer.validate();
+ }
+
+ @Override
+ protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("AWTWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
+ getReconfigureFlagsAsString(null, flags));
+ }
+ if(0 != ( FLAG_CHANGE_DECORATION & flags) && null!=awtFrame) {
+ if(!awtContainer.isDisplayable()) {
+ awtFrame.setUndecorated(isUndecorated());
} else {
if(DEBUG_IMPLEMENTATION) {
System.err.println(getThreadName()+": AWTWindow can't undecorate already created frame");
}
}
}
-
- final Dimension szClient = new Dimension(width, height);
- canvas.setMinimumSize(szClient);
- canvas.setPreferredSize(szClient);
- canvas.setSize(szClient);
- if(DEBUG_IMPLEMENTATION) {
- final Insets insets = container.getInsets();
- final Dimension szContainer = new Dimension(width + insets.left + insets.right,
- height + insets.top + insets.bottom);
- System.err.println(getThreadName()+": AWTWindow new size: szClient "+szClient+", szCont "+szContainer+", insets "+insets);
- }
-
+
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
- if(null != frame) {
- frame.pack();
+ if( 0 != ( FLAG_IS_VISIBLE & flags) ) {
+ setCanvasSizeImpl(width, height);
+ awtContainer.setVisible( true );
+ } else {
+ awtContainer.setVisible( false );
+ }
+ } else if( awtCanvas.getWidth() != width || awtCanvas.getHeight() != height ) {
+ if( Platform.OSType.MACOS == Platform.getOSType() && awtCanvas.isOffscreenLayerSurfaceEnabled() ) {
+ setFrameSizeImpl(width, height);
+ } else {
+ setCanvasSizeImpl(width, height);
}
- container.validate();
- container.setVisible(0 != ( FLAG_IS_VISIBLE & flags));
}
-
- container.setLocation(x, y);
-
+ defineSize(width, height); // we are on AWT-EDT .. change values immediately
+
+ if( awtContainer.getX() != x || awtContainer.getY() != y ) {
+ awtContainer.setLocation(x, y);
+ }
+
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
if( 0 != ( FLAG_IS_VISIBLE & flags ) ) {
if( !hasDeviceChanged() ) {
- // oops ??
- final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration();
+ // oops ??
+ final AWTGraphicsConfiguration cfg = awtCanvas.getAWTGraphicsConfiguration();
if(null == cfg) {
throw new NativeWindowException("Error: !hasDeviceChanged && null == GraphicsConfiguration: "+this);
}
@@ -215,63 +278,64 @@ public class WindowDriver extends WindowImpl {
}
}
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
- } else {
- container.invalidate();
- if(null != frame) {
- frame.pack();
- }
- container.validate();
}
-
+
return true;
}
- protected Point getLocationOnScreenImpl(int x, int y) {
- java.awt.Point ap = canvas.getLocationOnScreen();
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
+ final java.awt.Point ap = awtCanvas.getLocationOnScreen();
ap.translate(x, y);
return new Point((int)(ap.getX()+0.5),(int)(ap.getY()+0.5));
}
-
+
@Override
- public Object getWrappedWindow() {
- return canvas;
+ public NativeSurface getWrappedSurface() {
+ return ( null != awtCanvas ) ? awtCanvas.getNativeWindow() : null;
}
- class LocalWindowListener implements com.jogamp.newt.event.WindowListener {
+ class LocalWindowListener implements com.jogamp.newt.event.WindowListener {
@Override
- public void windowMoved(com.jogamp.newt.event.WindowEvent e) {
- if(null!=container) {
- WindowDriver.this.positionChanged(false, container.getX(), container.getY());
+ public void windowMoved(final com.jogamp.newt.event.WindowEvent e) {
+ if(null!=awtContainer) {
+ WindowDriver.this.positionChanged(false, awtContainer.getX(), awtContainer.getY());
}
}
@Override
- public void windowResized(com.jogamp.newt.event.WindowEvent e) {
- if(null!=canvas) {
- WindowDriver.this.sizeChanged(false, canvas.getWidth(), canvas.getHeight(), false);
+ public void windowResized(final com.jogamp.newt.event.WindowEvent e) {
+ if(null!=awtCanvas) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window Resized: "+awtCanvas);
+ }
+ WindowDriver.this.sizeChanged(false, awtCanvas.getWidth(), awtCanvas.getHeight(), true);
+ WindowDriver.this.windowRepaint(false, 0, 0, getSurfaceWidth(), getSurfaceHeight());
}
}
@Override
- public void windowDestroyNotify(WindowEvent e) {
+ public void windowDestroyNotify(final WindowEvent e) {
WindowDriver.this.windowDestroyNotify(false);
}
@Override
- public void windowDestroyed(WindowEvent e) {
- if(isNativeValid()) {
- WindowDriver.this.windowDestroyNotify(true);
- }
-
+ public void windowDestroyed(final WindowEvent e) {
+ // Not fwd by AWTWindowAdapter, synthesized by NEWT
}
@Override
- public void windowGainedFocus(WindowEvent e) {
- WindowDriver.this.focusChanged(false, true);
+ public void windowGainedFocus(final WindowEvent e) {
+ WindowDriver.this.focusChanged(false, true);
}
@Override
- public void windowLostFocus(WindowEvent e) {
- WindowDriver.this.focusChanged(false, false);
+ public void windowLostFocus(final WindowEvent e) {
+ WindowDriver.this.focusChanged(false, false);
}
@Override
- public void windowRepaint(WindowUpdateEvent e) {
- WindowDriver.this.windowRepaint(false, 0, 0, getWidth(), getHeight());
+ public void windowRepaint(final WindowUpdateEvent e) {
+ if(null!=awtCanvas) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window Repaint: "+awtCanvas);
+ }
+ WindowDriver.this.windowRepaint(false, 0, 0, getSurfaceWidth(), getSurfaceHeight());
+ }
}
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java
index 65ca63eec..ceb337150 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.bcm.egl;
@@ -60,6 +60,7 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl {
public DisplayDriver() {
}
+ @Override
protected void createNativeImpl() {
final long handle = CreateDisplay(ScreenDriver.fixedWidth, ScreenDriver.fixedHeight);
if (handle == EGL.EGL_NO_DISPLAY) {
@@ -68,12 +69,15 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl {
aDevice = new EGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, null);
}
- protected void closeNativeImpl() {
+ @Override
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) {
DestroyDisplay(aDevice.getHandle());
}
+ aDevice.close();
}
+ @Override
protected void dispatchMessagesNative() {
// n/a .. DispatchMessages();
}
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
index deb2a534b..2cd47313a 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,14 +29,19 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.bcm.egl;
import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
public class ScreenDriver extends jogamp.newt.ScreenImpl {
@@ -48,23 +53,66 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
public ScreenDriver() {
}
+ @Override
protected void createNativeImpl() {
aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
}
+ @Override
protected void closeNativeImpl() { }
- protected int validateScreenIndex(int idx) {
- return 0; // only one screen available
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ return 0; // only one screen available
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(final MonitorModeProps.Cache cache) {
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = fixedWidth; // FIXME
+ props[i++] = fixedHeight; // FIXME
+ props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+ props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+ props[i++] = 0; // flags
+ props[i++] = 0; // mode_idx
+ props[i++] = 0; // rotation
+ final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+ props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+ props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+ props[i++] = 0; // rotated viewport x pixel-units
+ props[i++] = 0; // rotated viewport y pixel-units
+ props[i++] = fixedWidth; // FIXME rotated viewport width pixel-units
+ props[i++] = fixedHeight; // FIXME rotated viewport height pixel-units
+ props[i++] = 0; // rotated viewport x window-units
+ props[i++] = 0; // rotated viewport y window-units
+ props[i++] = fixedWidth; // FIXME rotated viewport width window-units
+ props[i++] = fixedHeight; // FIXME rotated viewport height window-units
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
}
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(fixedWidth); // FIXME
- virtualSize.setHeight(fixedHeight); // FIXME
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return monitor.getSupportedModes().get(0);
}
-
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return false;
+ }
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(final Rectangle viewport, final Rectangle viewportInWindowUnits) {
+ viewport.set(0, 0, fixedWidth, fixedHeight); // FIXME
+ viewportInWindowUnits.set(viewport);
+ }
+
//----------------------------------------------------------------------
// Internals only
//
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java
index 49d3d98ba..aec85f875 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.bcm.egl;
@@ -52,11 +52,12 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
public WindowDriver() {
}
+ @Override
protected void createNativeImpl() {
if(0!=getParentWindowHandle()) {
throw new RuntimeException("Window parenting not supported (yet)");
}
- // query a good configuration, however chose the final one by the native queried egl-cfg-id
+ // query a good configuration, however chose the final one by the native queried egl-cfg-id
// after creation at {@link #windowCreated(int, int, int)}.
final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
@@ -64,7 +65,8 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
setGraphicsConfiguration(cfg);
- setSizeImpl(getScreen().getWidth(), getScreen().getHeight());
+ final int[] winSize = convertToWindowUnits(new int[] {getScreen().getWidth(), getScreen().getHeight()});
+ setSizeImpl(winSize[0], winSize[1]);
setWindowHandle(realizeWindow(true, getWidth(), getHeight()));
if (0 == getWindowHandle()) {
@@ -72,15 +74,17 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
}
}
+ @Override
protected void closeNativeImpl() {
if(0!=windowHandleClose) {
CloseWindow(getDisplayHandle(), windowHandleClose);
}
}
- protected void requestFocusImpl(boolean reparented) { }
+ @Override
+ protected void requestFocusImpl(final boolean reparented) { }
- protected void setSizeImpl(int width, int height) {
+ protected void setSizeImpl(final int width, final int height) {
if(0!=getWindowHandle()) {
// n/a in BroadcomEGL
System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window");
@@ -89,8 +93,9 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
}
}
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
- if(0!=getWindowHandle()) {
+ @Override
+ protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
+ if(0!=getWindowHandle()) {
if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) {
if( 0 != ( FLAG_IS_FULLSCREEN & flags) ) {
// n/a in BroadcomEGL
@@ -110,19 +115,21 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
if(x>=0 || y>=0) {
System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL");
}
-
+
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
return true;
}
- protected Point getLocationOnScreenImpl(int x, int y) {
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
return new Point(x,y);
}
- protected void updateInsetsImpl(Insets insets) {
- // nop ..
+ @Override
+ protected void updateInsetsImpl(final Insets insets) {
+ // nop ..
}
@Override
@@ -141,11 +148,11 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
private native void SwapWindow(long eglDisplayHandle, long eglWindowHandle);
- private long realizeWindow(boolean chromaKey, int width, int height) {
+ private long realizeWindow(final boolean chromaKey, final int width, final int height) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("BCEGL Window.realizeWindow() with: chroma "+chromaKey+", "+width+"x"+height+", "+getGraphicsConfiguration());
}
- long handle = CreateWindow(getDisplayHandle(), chromaKey, width, height);
+ final long handle = CreateWindow(getDisplayHandle(), chromaKey, width, height);
if (0 == handle) {
throw new NativeWindowException("Error native Window Handle is null");
}
@@ -153,9 +160,9 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
return handle;
}
- private void windowCreated(int cfgID, int width, int height) {
+ private void windowCreated(final int cfgID, final int width, final int height) {
defineSize(width, height);
- GLCapabilitiesImmutable capsReq = (GLCapabilitiesImmutable) getGraphicsConfiguration().getRequestedCapabilities();
+ final GLCapabilitiesImmutable capsReq = (GLCapabilitiesImmutable) getGraphicsConfiguration().getRequestedCapabilities();
final AbstractGraphicsConfiguration cfg = EGLGraphicsConfiguration.create(capsReq, getScreen().getGraphicsScreen(), cfgID);
if (null == cfg) {
throw new NativeWindowException("Error creating EGLGraphicsConfiguration from id: "+cfgID+", "+this);
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java
index 08c5c573c..1b67fa755 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -28,15 +28,28 @@
package jogamp.newt.driver.bcm.vc.iv;
+import java.net.URLConnection;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.PixelFormat;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.util.PNGPixelRect;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
+import jogamp.newt.PointerIconImpl;
+import jogamp.newt.driver.linux.LinuxMouseTracker;
import jogamp.opengl.egl.EGL;
import jogamp.opengl.egl.EGLDisplayUtil;
public class DisplayDriver extends DisplayImpl {
+ static final PNGPixelRect defaultPointerIconImage;
+
static {
NEWTJNILibLoader.loadNEWT();
@@ -49,6 +62,18 @@ public class DisplayDriver extends DisplayImpl {
if (!WindowDriver.initIDs()) {
throw new NativeWindowException("Failed to initialize bcm.vc.iv Window jmethodIDs");
}
+
+ PNGPixelRect image = null;
+ if( DisplayImpl.isPNGUtilAvailable() ) {
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(DisplayDriver.class, new String[] { "newt/data/pointer-grey-alpha-16x24.png" } );
+ try {
+ final URLConnection urlConn = res.resolve(0);
+ image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ defaultPointerIconImage = image;
}
public static void initSingleton() {
@@ -57,22 +82,128 @@ public class DisplayDriver extends DisplayImpl {
public DisplayDriver() {
+ bcmHandle = 0;
+ activePointerIcon = 0;
+ activePointerIconVisible = false;
}
+ @Override
protected void createNativeImpl() {
// FIXME: map name to EGL_*_DISPLAY
+ bcmHandle = OpenBCMDisplay0();
aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice.open();
+
+ defaultPointerIcon = (PointerIconImpl) createPointerIcon(defaultPointerIconImage, 0, 0);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("Display.PointerIcon.createDefault: "+defaultPointerIcon);
+ }
+ if( null != defaultPointerIcon ) {
+ final LinuxMouseTracker lmt = LinuxMouseTracker.getSingleton();
+ setPointerIconActive(defaultPointerIcon.getHandle(), lmt.getLastX(), lmt.getLastY());
+ }
}
+ private PointerIconImpl defaultPointerIcon = null;
- protected void closeNativeImpl() {
+ @Override
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
aDevice.close();
+ CloseBCMDisplay0(bcmHandle);
+ bcmHandle = 0;
}
+ /* pp */ final long getBCMHandle() { return bcmHandle; }
+
+ @Override
protected void dispatchMessagesNative() {
- DispatchMessages();
+ DispatchMessages0();
+ }
+
+ // @Override
+ // public final PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.BGRA8888; }
+
+ @Override
+ protected final long createPointerIconImpl(final PixelFormat pixelformat, final int width, final int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return CreatePointerIcon(bcmHandle, pixels, width, height, hotX, hotY);
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, final long piHandle) {
+ DestroyPointerIcon0(piHandle);
+ }
+
+ /* pp */ void setPointerIconActive(long piHandle, final int x, final int y) {
+ synchronized(pointerIconSync) {
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("Display.PointerIcon.set.0: active ["+toHexString(activePointerIcon)+", visible "+activePointerIconVisible+"] -> "+toHexString(piHandle));
+ }
+ if( 0 != activePointerIcon && activePointerIconVisible ) {
+ SetPointerIcon0(bcmHandle, activePointerIcon, false, x, y);
+ }
+ if( 0 == piHandle && null != defaultPointerIcon ) {
+ piHandle = defaultPointerIcon.getHandle();
+ }
+ if( 0 != piHandle ) {
+ SetPointerIcon0(bcmHandle, piHandle, true, x, y);
+ activePointerIconVisible = true;
+ } else {
+ activePointerIconVisible = false;
+ }
+ activePointerIcon = piHandle;
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("Display.PointerIcon.set.X: active ["+toHexString(activePointerIcon)+", visible "+activePointerIconVisible+"]");
+ }
+ }
+ }
+ /* pp */ void setActivePointerIconVisible(final boolean visible, final int x, final int y) {
+ synchronized(pointerIconSync) {
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("Display.PointerIcon.visible: active ["+toHexString(activePointerIcon)+", visible "+activePointerIconVisible+"] -> visible "+visible);
+ }
+ if( activePointerIconVisible != visible ) {
+ if( 0 != activePointerIcon ) {
+ SetPointerIcon0(bcmHandle, activePointerIcon, visible, x, y);
+ }
+ activePointerIconVisible = visible;
+ }
+ }
}
+ /* pp */ void moveActivePointerIcon(final int x, final int y) {
+ synchronized(pointerIconSync) {
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("Display.PointerIcon.move: active ["+toHexString(activePointerIcon)+", visible "+activePointerIconVisible+"], "+x+"/"+y);
+ }
+ if( 0 != activePointerIcon && activePointerIconVisible ) {
+ MovePointerIcon0(activePointerIcon, x, y);
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+
+ protected static native boolean initIDs();
+ private static native long OpenBCMDisplay0();
+ private static native void CloseBCMDisplay0(long handle);
+
+ private static long CreatePointerIcon(final long bcmHandle, final Buffer pixels, final int width, final int height, final int hotX, final int hotY) {
+ final boolean pixels_is_direct = Buffers.isDirect(pixels);
+ return CreatePointerIcon0(pixels_is_direct ? pixels : Buffers.getArray(pixels),
+ pixels_is_direct ? Buffers.getDirectBufferByteOffset(pixels) : Buffers.getIndirectBufferByteOffset(pixels),
+ pixels_is_direct,
+ width, height, hotX, hotY);
+ }
+ private static native long CreatePointerIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY);
+ private static native void DestroyPointerIcon0(long handle);
+ private static native void SetPointerIcon0(long bcmHandle, long handle, boolean enable, int x, int y);
+ private static native void MovePointerIcon0(long handle, int x, int y);
+
+ private static native void DispatchMessages0();
- protected static native boolean initIDs();
- private native void DispatchMessages();
+ private long bcmHandle;
+ private long activePointerIcon;
+ private boolean activePointerIconVisible;
+ private final Object pointerIconSync = new Object();
}
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
index 787d1a1b4..64cae75f6 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -29,9 +29,12 @@
package jogamp.newt.driver.bcm.vc.iv;
import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+import jogamp.newt.MonitorModeProps;
import jogamp.newt.ScreenImpl;
public class ScreenDriver extends ScreenImpl {
@@ -42,31 +45,75 @@ public class ScreenDriver extends ScreenImpl {
public ScreenDriver() {
}
+ @Override
protected void createNativeImpl() {
aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
initNative();
}
+ @Override
protected void closeNativeImpl() { }
- protected int validateScreenIndex(int idx) {
- return 0; // only one screen available
- }
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(cachedWidth);
- virtualSize.setHeight(cachedHeight);
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ return 0; // only one screen available
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(final MonitorModeProps.Cache cache) {
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = cachedWidth; // width
+ props[i++] = cachedHeight; // height
+ props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+ props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+ props[i++] = 0; // flags
+ props[i++] = 0; // mode_idx
+ props[i++] = 0; // rotation
+ final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+ props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+ props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+ props[i++] = 0; // rotated viewport x pixel-units
+ props[i++] = 0; // rotated viewport y pixel-units
+ props[i++] = cachedWidth; // rotated viewport width pixel-units
+ props[i++] = cachedWidth; // rotated viewport height pixel-units
+ props[i++] = 0; // rotated viewport x window-units
+ props[i++] = 0; // rotated viewport y window-units
+ props[i++] = cachedWidth; // rotated viewport width window-units
+ props[i++] = cachedWidth; // rotated viewport height window-units
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
}
-
- protected void setScreenSize(int width, int height) {
- cachedWidth = width;
- cachedHeight = height;
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return monitor.getSupportedModes().get(0);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return false;
+ }
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(final Rectangle viewport, final Rectangle viewportInWindowUnits) {
+ viewport.set(0, 0, cachedWidth, cachedHeight);
+ viewportInWindowUnits.set(viewport);
+ }
+
+ /** Called from {@link #initNative()}. */
+ protected void setScreenSize(final int width, final int height) {
+ cachedWidth = width; // write to static field intended
+ cachedHeight = height; // write to static field intended
}
-
+
private static int cachedWidth = 0;
- private static int cachedHeight = 0;
+ private static int cachedHeight = 0;
protected static native boolean initIDs();
protected native void initNative();
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java
index 7b8d2e958..ad6d0b688 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -29,15 +29,24 @@
package jogamp.newt.driver.bcm.vc.iv;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.util.IntBitfield;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+import com.jogamp.newt.event.MouseEvent;
+
+import jogamp.newt.PointerIconImpl;
import jogamp.newt.WindowImpl;
+import jogamp.newt.driver.linux.LinuxEventDeviceTracker;
import jogamp.newt.driver.linux.LinuxMouseTracker;
+import jogamp.opengl.egl.EGLDisplayUtil;
public class WindowDriver extends WindowImpl {
private static final String WINDOW_CLASS_NAME = "NewtWindow";
@@ -47,110 +56,160 @@ public class WindowDriver extends WindowImpl {
}
public WindowDriver() {
+ linuxMouseTracker = LinuxMouseTracker.getSingleton();
+ linuxEventDeviceTracker = LinuxEventDeviceTracker.getSingleton();
+ layer = -1;
+ nativeWindowHandle = 0;
+ windowHandleClose = 0;
}
+ @Override
protected void createNativeImpl() {
if(0!=getParentWindowHandle()) {
throw new RuntimeException("Window parenting not supported (yet)");
}
- // FIXME: Hack - Native BCM_VC_IV code CreateWindow() uses the default alpha value setting,
- // which is alpha:8 ! Hence we require to chose alpha from the egl configurations.
- // TODO: Properly select the alpha mode in CreateWindow()! This will allow this hack.
- final Capabilities capsChosen = (Capabilities) capsRequested.cloneMutable();
- capsChosen.setAlphaBits(1);
-
+ synchronized( layerSync ) {
+ if( layerCount >= MAX_LAYERS ) {
+ throw new RuntimeException("Max windows reached: "+layerCount+" ( "+MAX_LAYERS+" )");
+ }
+ for(int i=0; 0 > layer && i<MAX_LAYERS; i++) {
+ if( !usedLayers.get(nextLayer) ) {
+ layer = nextLayer;
+ usedLayers.put(layer, true);
+ layerCount++;
+ }
+ nextLayer++;
+ if( MAX_LAYERS == nextLayer ) {
+ nextLayer=0;
+ }
+ }
+ // System.err.println("XXX.Open capacity "+usedLayers.capacity()+", count "+usedLayers.getBitCount());
+ }
+ if( 0 > layer ) {
+ throw new InternalError("Could not find a free layer: count "+layerCount+", max "+MAX_LAYERS);
+ }
+ final ScreenDriver screen = (ScreenDriver) getScreen();
+ final DisplayDriver display = (DisplayDriver) screen.getDisplay();
+
+ // Create own screen/device resource instance allowing independent ownership,
+ // while still utilizing shared EGL resources.
+ final AbstractGraphicsScreen aScreen = screen.getGraphicsScreen();
+ final EGLGraphicsDevice aDevice = (EGLGraphicsDevice) aScreen.getDevice();
+ final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(aDevice.getNativeDisplayID(), aDevice.getConnection(), aDevice.getUnitID());
+ eglDevice.open();
+ final DefaultGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aScreen.getIndex());
+
final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
- capsChosen, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
+ capsRequested, capsRequested, capabilitiesChooser, eglScreen, VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
+ final Capabilities chosenCaps = (Capabilities) cfg.getChosenCapabilities();
+ // FIXME: Pass along opaque flag, since EGL doesn't determine it
+ if(capsRequested.isBackgroundOpaque() != chosenCaps.isBackgroundOpaque()) {
+ chosenCaps.setBackgroundOpaque(capsRequested.isBackgroundOpaque());
+ }
setGraphicsConfiguration(cfg);
-
- nativeWindowHandle = CreateWindow(getWidth(), getHeight());
+ nativeWindowHandle = CreateWindow0(display.getBCMHandle(), layer, getX(), getY(), getWidth(), getHeight(),
+ chosenCaps.isBackgroundOpaque(), chosenCaps.getAlphaBits());
if (nativeWindowHandle == 0) {
throw new NativeWindowException("Error creating egl window: "+cfg);
}
- setVisible0(nativeWindowHandle, false);
setWindowHandle(nativeWindowHandle);
if (0 == getWindowHandle()) {
throw new NativeWindowException("Error native Window Handle is null");
}
windowHandleClose = nativeWindowHandle;
- addWindowListener(LinuxMouseTracker.getSingleton());
- focusChanged(false, true);
+
+ addWindowListener(linuxEventDeviceTracker);
+ addWindowListener(linuxMouseTracker);
+ focusChanged(false, true);
}
+ @Override
protected void closeNativeImpl() {
- removeWindowListener(LinuxMouseTracker.getSingleton());
-
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getGraphicsConfiguration().getScreen().getDevice();
+
+ removeWindowListener(linuxMouseTracker);
+ removeWindowListener(linuxEventDeviceTracker);
+
if(0!=windowHandleClose) {
- CloseWindow(windowHandleClose, windowUserData);
- windowUserData=0;
+ CloseWindow0(display.getBCMHandle(), windowHandleClose);
+ }
+
+ eglDevice.close();
+
+ synchronized( layerSync ) {
+ usedLayers.put(layer, false);
+ layerCount--;
+ layer = -1;
+ // System.err.println("XXX.Close capacity "+usedLayers.capacity()+", count "+usedLayers.getBitCount());
}
}
- protected void requestFocusImpl(boolean reparented) {
+ @Override
+ protected void requestFocusImpl(final boolean reparented) {
focusChanged(false, true);
}
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
- if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
- setVisible0(nativeWindowHandle, 0 != ( FLAG_IS_VISIBLE & flags));
- visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
- }
-
- if(0!=nativeWindowHandle) {
- if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) {
- final boolean fs = 0 != ( FLAG_IS_FULLSCREEN & flags) ;
- setFullScreen0(nativeWindowHandle, fs);
- if(fs) {
- return true;
- }
- }
- // int _x=(x>=0)?x:this.x;
- // int _y=(x>=0)?y:this.y;
- width=(width>0)?width:getWidth();
- height=(height>0)?height:getHeight();
- if(width>0 || height>0) {
- setSize0(nativeWindowHandle, width, height);
- }
- if(x>=0 || y>=0) {
- System.err.println("setPosition n/a in KD");
- }
- }
-
- if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
- visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
- }
-
+ @Override
+ protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
+ reconfigure0(nativeWindowHandle, x, y, width, height, flags);
return true;
}
- protected Point getLocationOnScreenImpl(int x, int y) {
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
return new Point(x,y);
}
- protected void updateInsetsImpl(Insets insets) {
- // nop ..
+ @Override
+ protected void updateInsetsImpl(final Insets insets) {
+ // nop ..
+ }
+
+ @Override
+ protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
+ if( MouseEvent.EVENT_MOUSE_MOVED == eventType ) {
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ display.moveActivePointerIcon(x, y);
+ }
+ super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
+ }
+
+ @Override
+ protected void setPointerIconImpl(final PointerIconImpl pi) {
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ display.setPointerIconActive(null != pi ? pi.validatedHandle() : 0, linuxMouseTracker.getLastX(), linuxMouseTracker.getLastY());
+ }
+
+ @Override
+ protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ display.setActivePointerIconVisible(pointerVisible, linuxMouseTracker.getLastX(), linuxMouseTracker.getLastY());
+ return true;
}
-
+
//----------------------------------------------------------------------
// Internals only
//
+ private final LinuxMouseTracker linuxMouseTracker;
+ private final LinuxEventDeviceTracker linuxEventDeviceTracker;
protected static native boolean initIDs();
- private native long CreateWindow(int width, int height);
- private native long RealizeWindow(long eglWindowHandle);
- private native int CloseWindow(long eglWindowHandle, long userData);
- private native void setVisible0(long eglWindowHandle, boolean visible);
- private native void setSize0(long eglWindowHandle, int width, int height);
- private native void setFullScreen0(long eglWindowHandle, boolean fullscreen);
-
- private void windowCreated(long userData) {
- windowUserData=userData;
- }
+ private native long CreateWindow0(long bcmDisplay, int layer, int x, int y, int width, int height, boolean opaque, int alphaBits);
+ private native void CloseWindow0(long bcmDisplay, long eglWindowHandle);
+ private native void reconfigure0(long eglWindowHandle, int x, int y, int width, int height, int flags);
+ private int layer;
private long nativeWindowHandle;
private long windowHandleClose;
- private long windowUserData;
+
+ private static int nextLayer = 0;
+ private static int layerCount = 0;
+ private static final int MAX_LAYERS = 32;
+ private static final IntBitfield usedLayers = new IntBitfield(MAX_LAYERS);
+ private static final Object layerSync = new Object();
}
diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java
index 97c384d33..1d43017c3 100644
--- a/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.intel.gdl;
@@ -59,6 +59,7 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl {
public DisplayDriver() {
}
+ @Override
protected void createNativeImpl() {
synchronized(DisplayDriver.class) {
if(0==initCounter) {
@@ -72,7 +73,8 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl {
aDevice = new DefaultGraphicsDevice(NativeWindowFactory.TYPE_DEFAULT, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, displayHandle);
}
- protected void closeNativeImpl() {
+ @Override
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
if(0==displayHandle) {
throw new NativeWindowException("displayHandle null; initCnt "+initCounter);
}
@@ -84,15 +86,17 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl {
}
}
}
+ aDevice.close();
}
+ @Override
protected void dispatchMessagesNative() {
if(0!=displayHandle) {
DispatchMessages(displayHandle, focusedWindow);
}
}
- protected void setFocus(WindowDriver focus) {
+ protected void setFocus(final WindowDriver focus) {
focusedWindow = focus;
}
diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
index 8eed14dde..2ce835c52 100644
--- a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,15 +29,20 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.intel.gdl;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
public class ScreenDriver extends jogamp.newt.ScreenImpl {
@@ -48,25 +53,68 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
public ScreenDriver() {
}
+ @Override
protected void createNativeImpl() {
- AbstractGraphicsDevice adevice = getDisplay().getGraphicsDevice();
+ final AbstractGraphicsDevice adevice = getDisplay().getGraphicsDevice();
GetScreenInfo(adevice.getHandle(), screen_idx);
aScreen = new DefaultGraphicsScreen(adevice, screen_idx);
}
+ @Override
protected void closeNativeImpl() { }
- protected int validateScreenIndex(int idx) {
- return 0; // only one screen available
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ return 0; // only one screen available
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(final MonitorModeProps.Cache cache) {
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = cachedWidth; // width
+ props[i++] = cachedHeight; // height
+ props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+ props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+ props[i++] = 0; // flags
+ props[i++] = 0; // mode_idx
+ props[i++] = 0; // rotation
+ final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+ props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+ props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+ props[i++] = 0; // rotated viewport x pixel-units
+ props[i++] = 0; // rotated viewport y pixel-units
+ props[i++] = cachedWidth; // rotated viewport width pixel-units
+ props[i++] = cachedWidth; // rotated viewport height pixel-units
+ props[i++] = 0; // rotated viewport x window-units
+ props[i++] = 0; // rotated viewport y window-units
+ props[i++] = cachedWidth; // rotated viewport width window-units
+ props[i++] = cachedWidth; // rotated viewport height window-units
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return monitor.getSupportedModes().get(0);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return false;
}
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(cachedWidth);
- virtualSize.setHeight(cachedHeight);
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(final Rectangle viewport, final Rectangle viewportInWindowUnits) {
+ viewport.set(0, 0, cachedWidth, cachedHeight);
+ viewportInWindowUnits.set(viewport);
}
-
+
//----------------------------------------------------------------------
// Internals only
//
@@ -75,11 +123,11 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
private native void GetScreenInfo(long displayHandle, int screen_idx);
// called by GetScreenInfo() ..
- private void screenCreated(int width, int height) {
+ private void screenCreated(final int width, final int height) {
cachedWidth = width;
cachedHeight = height;
}
-
+
private static int cachedWidth = 0;
private static int cachedHeight = 0;
}
diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java
index 98335f192..d7bd17e42 100644
--- a/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.intel.gdl;
@@ -48,6 +48,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
static long nextWindowHandle = 1;
+ @Override
protected void createNativeImpl() {
if(0!=getParentWindowHandle()) {
throw new NativeWindowException("GDL Window does not support window parenting");
@@ -65,13 +66,15 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
synchronized(WindowDriver.class) {
setWindowHandle(nextWindowHandle++); // just a marker
- surfaceHandle = CreateSurface(aDevice.getHandle(), getScreen().getWidth(), getScreen().getHeight(), getX(), getY(), getWidth(), getHeight());
+ surfaceHandle = CreateSurface(aDevice.getHandle(), getScreen().getWidth(), getScreen().getHeight(),
+ getX(), getY(), getSurfaceWidth(), getSurfaceHeight());
if (surfaceHandle == 0) {
throw new NativeWindowException("Error creating window");
}
}
}
+ @Override
protected void closeNativeImpl() {
if(0!=surfaceHandle) {
synchronized(WindowDriver.class) {
@@ -82,9 +85,11 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
}
}
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
- ScreenDriver screen = (ScreenDriver) getScreen();
+ @Override
+ protected boolean reconfigureWindowImpl(int x, int y, int width, int height, final int flags) {
+ final ScreenDriver screen = (ScreenDriver) getScreen();
+ // Note for GDL: window units == pixel units
if(width>screen.getWidth()) {
width=screen.getWidth();
}
@@ -108,11 +113,12 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
}
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
-
+
return true;
}
- protected void requestFocusImpl(boolean reparented) {
+ @Override
+ protected void requestFocusImpl(final boolean reparented) {
((DisplayDriver)getScreen().getDisplay()).setFocus(this);
}
@@ -121,14 +127,16 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
return surfaceHandle;
}
- protected Point getLocationOnScreenImpl(int x, int y) {
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
return new Point(x,y);
}
- protected void updateInsetsImpl(Insets insets) {
- // nop ..
+ @Override
+ protected void updateInsetsImpl(final Insets insets) {
+ // nop ..
}
-
+
//----------------------------------------------------------------------
// Internals only
//
@@ -138,7 +146,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
private native void CloseSurface(long displayHandle, long surfaceHandle);
private native void SetBounds0(long surfaceHandle, int scrn_width, int scrn_height, int x, int y, int width, int height);
- private void updateBounds(int x, int y, int width, int height) {
+ private void updateBounds(final int x, final int y, final int width, final int height) {
definePosition(x, y);
defineSize(width, height);
}
diff --git a/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java
index 745be5dae..e72ddbc11 100644
--- a/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.kd;
@@ -59,15 +59,19 @@ public class DisplayDriver extends DisplayImpl {
public DisplayDriver() {
}
+ @Override
protected void createNativeImpl() {
// FIXME: map name to EGL_*_DISPLAY
aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice.open();
}
- protected void closeNativeImpl() {
+ @Override
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
aDevice.close();
}
+ @Override
protected void dispatchMessagesNative() {
DispatchMessages();
}
diff --git a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
index 656bcf5c9..d4113561a 100644
--- a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,15 +29,18 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.kd;
import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+import jogamp.newt.MonitorModeProps;
import jogamp.newt.ScreenImpl;
public class ScreenDriver extends ScreenImpl {
@@ -48,28 +51,71 @@ public class ScreenDriver extends ScreenImpl {
public ScreenDriver() {
}
+ @Override
protected void createNativeImpl() {
aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
}
+ @Override
protected void closeNativeImpl() { }
- protected int validateScreenIndex(int idx) {
- return 0; // only one screen available
- }
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(cachedWidth);
- virtualSize.setHeight(cachedHeight);
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ return 0; // only one screen available
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(final MonitorModeProps.Cache cache) {
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = cachedWidth; // width
+ props[i++] = cachedHeight; // height
+ props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+ props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+ props[i++] = 0; // flags
+ props[i++] = 0; // mode_idx
+ props[i++] = 0; // rotation
+ final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+ props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+ props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+ props[i++] = 0; // rotated viewport x pixel-units
+ props[i++] = 0; // rotated viewport y pixel-units
+ props[i++] = cachedWidth; // rotated viewport width pixel-units
+ props[i++] = cachedWidth; // rotated viewport height pixel-units
+ props[i++] = 0; // rotated viewport x window-units
+ props[i++] = 0; // rotated viewport y window-units
+ props[i++] = cachedWidth; // rotated viewport width window-units
+ props[i++] = cachedWidth; // rotated viewport height window-units
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return monitor.getSupportedModes().get(0);
}
-
- protected void sizeChanged(int w, int h) {
- cachedWidth = w;
- cachedHeight = h;
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return false;
+ }
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(final Rectangle viewport, final Rectangle viewportInWindowUnits) {
+ viewport.set(0, 0, cachedWidth, cachedHeight);
+ viewportInWindowUnits.set(viewport);
}
-
+
+ protected void sizeChanged(final int w, final int h) {
+ cachedWidth = w; // write to static field intended
+ cachedHeight = h; // write to static field intended
+ }
+
private static int cachedWidth = 0;
- private static int cachedHeight = 0;
+ private static int cachedHeight = 0;
}
diff --git a/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java
index c733a3e94..d53ef00cd 100644
--- a/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.kd;
@@ -56,6 +56,7 @@ public class WindowDriver extends WindowImpl {
public WindowDriver() {
}
+ @Override
protected void createNativeImpl() {
if(0!=getParentWindowHandle()) {
throw new RuntimeException("Window parenting not supported (yet)");
@@ -67,9 +68,9 @@ public class WindowDriver extends WindowImpl {
}
setGraphicsConfiguration(cfg);
- GLCapabilitiesImmutable eglCaps = (GLCapabilitiesImmutable) cfg.getChosenCapabilities();
- int eglConfigID = eglCaps.getVisualID(VIDType.EGL_CONFIG);
- long eglConfig = EGLGraphicsConfiguration.EGLConfigId2EGLConfig(getDisplayHandle(), eglConfigID);
+ final GLCapabilitiesImmutable eglCaps = (GLCapabilitiesImmutable) cfg.getChosenCapabilities();
+ final int eglConfigID = eglCaps.getVisualID(VIDType.EGL_CONFIG);
+ final long eglConfig = EGLGraphicsConfiguration.EGLConfigId2EGLConfig(getDisplayHandle(), eglConfigID);
eglWindowHandle = CreateWindow(getDisplayHandle(), eglConfig);
if (eglWindowHandle == 0) {
@@ -83,6 +84,7 @@ public class WindowDriver extends WindowImpl {
windowHandleClose = eglWindowHandle;
}
+ @Override
protected void closeNativeImpl() {
if(0!=windowHandleClose) {
CloseWindow(windowHandleClose, windowUserData);
@@ -90,14 +92,16 @@ public class WindowDriver extends WindowImpl {
}
}
- protected void requestFocusImpl(boolean reparented) { }
+ @Override
+ protected void requestFocusImpl(final boolean reparented) { }
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+ @Override
+ protected boolean reconfigureWindowImpl(final int x, final int y, int width, int height, final int flags) {
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
setVisible0(eglWindowHandle, 0 != ( FLAG_IS_VISIBLE & flags));
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
-
+
if(0!=eglWindowHandle) {
if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) {
final boolean fs = 0 != ( FLAG_IS_FULLSCREEN & flags) ;
@@ -117,22 +121,24 @@ public class WindowDriver extends WindowImpl {
System.err.println("setPosition n/a in KD");
}
}
-
+
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
-
+
return true;
}
- protected Point getLocationOnScreenImpl(int x, int y) {
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
return new Point(x,y);
}
- protected void updateInsetsImpl(Insets insets) {
- // nop ..
+ @Override
+ protected void updateInsetsImpl(final Insets insets) {
+ // nop ..
}
-
+
//----------------------------------------------------------------------
// Internals only
//
@@ -145,12 +151,12 @@ public class WindowDriver extends WindowImpl {
private native void setSize0(long eglWindowHandle, int width, int height);
private native void setFullScreen0(long eglWindowHandle, boolean fullscreen);
- private void windowCreated(long userData) {
+ private void windowCreated(final long userData) {
windowUserData=userData;
}
@Override
- protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
+ protected void sizeChanged(final boolean defer, final int newWidth, final int newHeight, final boolean force) {
if(isFullscreen()) {
((ScreenDriver)getScreen()).sizeChanged(getWidth(), getHeight());
}
diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java
new file mode 100644
index 000000000..49a815cb6
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java
@@ -0,0 +1,959 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.newt.driver.linux;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.Integer;
+import java.lang.Runnable;
+import java.lang.String;
+import java.lang.Thread;
+import java.nio.ByteBuffer;
+
+import jogamp.newt.WindowImpl;
+
+import com.jogamp.common.nio.StructAccessor;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.event.WindowUpdateEvent;
+import com.jogamp.newt.event.KeyEvent;
+
+/**
+ * Experimental native event device tracker thread for GNU/Linux
+ * just reading <code>/dev/input/event*</code>
+ * within it's own polling thread.
+ */
+
+public class LinuxEventDeviceTracker implements WindowListener {
+
+ private static final LinuxEventDeviceTracker ledt;
+
+
+ static {
+ ledt = new LinuxEventDeviceTracker();
+ final Thread t = new Thread(ledt.eventDeviceManager, "NEWT-LinuxEventDeviceManager");
+ t.setDaemon(true);
+ t.start();
+ }
+
+ public static LinuxEventDeviceTracker getSingleton() {
+ return ledt;
+ }
+
+ private WindowImpl focusedWindow = null;
+ private final EventDeviceManager eventDeviceManager = new EventDeviceManager();
+
+ /*
+ The devices are in /dev/input:
+
+ crw-r--r-- 1 root root 13, 64 Apr 1 10:49 event0
+ crw-r--r-- 1 root root 13, 65 Apr 1 10:50 event1
+ crw-r--r-- 1 root root 13, 66 Apr 1 10:50 event2
+ crw-r--r-- 1 root root 13, 67 Apr 1 10:50 event3
+ ...
+
+ And so on up to event31.
+ */
+ private final EventDevicePoller[] eventDevicePollers = new EventDevicePoller[32];
+
+ @Override
+ public void windowResized(final WindowEvent e) { }
+
+ @Override
+ public void windowMoved(final WindowEvent e) { }
+
+ @Override
+ public void windowDestroyNotify(final WindowEvent e) {
+ final Object s = e.getSource();
+ if(focusedWindow == s) {
+ focusedWindow = null;
+ }
+ }
+
+ @Override
+ public void windowDestroyed(final WindowEvent e) { }
+
+ @Override
+ public void windowGainedFocus(final WindowEvent e) {
+ final Object s = e.getSource();
+ if(s instanceof WindowImpl) {
+ focusedWindow = (WindowImpl) s;
+ }
+ }
+
+ @Override
+ public void windowLostFocus(final WindowEvent e) {
+ final Object s = e.getSource();
+ if(focusedWindow == s) {
+ focusedWindow = null;
+ }
+ }
+
+ public static void main(final String[] args ){
+ System.setProperty("newt.debug.Window.KeyEvent", "true");
+ LinuxEventDeviceTracker.getSingleton();
+ try {
+ while(true) {
+ Thread.sleep(1000);
+ }
+ } catch (final InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void windowRepaint(final WindowUpdateEvent e) { }
+
+ class EventDeviceManager implements Runnable {
+
+ private volatile boolean stop = false;
+
+ @Override
+ public void run() {
+ final File f = new File("/dev/input/");
+ int number;
+ while(!stop){
+ for(final String path:f.list()){
+ if(path.startsWith("event")) {
+ final String stringNumber = path.substring(5);
+ number = Integer.parseInt(stringNumber);
+ if(number<32&&number>=0) {
+ if(eventDevicePollers[number]==null){
+ eventDevicePollers[number] = new EventDevicePoller(number);
+ final Thread t = new Thread(eventDevicePollers[number], "NEWT-LinuxEventDeviceTracker-event"+number);
+ t.setDaemon(true);
+ t.start();
+ } else if(eventDevicePollers[number].stop) {
+ eventDevicePollers[number]=null;
+ }
+ }
+ }
+ }
+ try {
+ Thread.sleep(2000);
+ } catch (final InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ class EventDevicePoller implements Runnable {
+
+ private volatile boolean stop = false;
+ private final String eventDeviceName;
+
+ public EventDevicePoller(final int eventDeviceNumber){
+ this.eventDeviceName="/dev/input/event"+eventDeviceNumber;
+ }
+
+ @Override
+ public void run() {
+ final byte[] b = new byte[16];
+ /**
+ * The Linux input event interface.
+ * http://www.kernel.org/doc/Documentation/input/input.txt
+ *
+ * struct input_event {
+ * struct timeval time;
+ * unsigned short type;
+ * unsigned short code;
+ * unsigned int value;
+ * };
+ */
+ final ByteBuffer bb = ByteBuffer.wrap(b);
+ final StructAccessor s = new StructAccessor(bb);
+ final File f = new File(eventDeviceName);
+ f.setReadOnly();
+ InputStream fis;
+ try {
+ fis = new FileInputStream(f);
+ } catch (final FileNotFoundException e) {
+ stop=true;
+ return;
+ }
+
+ int timeSeconds;
+ int timeSecondFraction;
+ short type;
+ short code;
+ int value;
+
+ short keyCode=KeyEvent.VK_UNDEFINED;
+ char keyChar=' ';
+ short eventType=0;
+ int modifiers=0;
+
+ loop:
+ while(!stop) {
+ int remaining=16;
+ while(remaining>0) {
+ int read = 0;
+ try {
+ read = fis.read(b, 0, remaining);
+ } catch (final IOException e) {
+ stop = true;
+ break loop;
+ }
+ if(read<0) {
+ stop = true; // EOF of event device file !?
+ break loop;
+ } else {
+ remaining -= read;
+ }
+ }
+
+ timeSeconds = s.getIntAt(0);
+ timeSecondFraction = s.getShortAt(4);
+ type = s.getShortAt(8);
+ code = s.getShortAt(10);
+ value = s.getIntAt(12);
+
+
+ /*
+ * Linux sends Keyboard events in the following order:
+ * EV_MSC (optional, contains scancode)
+ * EV_KEY
+ * SYN_REPORT (sent before next key)
+ */
+
+ switch(type) {
+ case 0: // SYN_REPORT
+ // Clear
+ eventType = 0;
+ keyCode = KeyEvent.VK_UNDEFINED;
+ keyChar = 0; // Print null for unprintable char.
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("[SYN_REPORT----]");
+ }
+ break;
+ case 1: // EV_KEY
+ keyCode = LinuxEVKey2NewtVKey(code); // The device independent code.
+ keyChar = NewtVKey2Unicode(keyCode, modifiers); // The printable character w/ key modifiers.
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("[EV_KEY: [time "+timeSeconds+":"+timeSecondFraction+"] type "+type+" / code "+code+" = value "+value);
+ }
+
+ switch(value) {
+ case 0:
+ eventType=KeyEvent.EVENT_KEY_RELEASED;
+
+ switch(keyCode) {
+ case KeyEvent.VK_SHIFT:
+ modifiers &= ~InputEvent.SHIFT_MASK;
+ break;
+ case KeyEvent.VK_ALT:
+ modifiers &= ~InputEvent.ALT_MASK;
+ break;
+ case KeyEvent.VK_ALT_GRAPH:
+ modifiers &= ~InputEvent.ALT_GRAPH_MASK;
+ break;
+ case KeyEvent.VK_CONTROL:
+ modifiers &= ~InputEvent.CTRL_MASK;
+ break;
+ }
+
+ if(null != focusedWindow) {
+ focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyCode, keyChar);
+ }
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("[event released] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+ }
+ break;
+ case 1:
+ eventType=KeyEvent.EVENT_KEY_PRESSED;
+
+ switch(keyCode) {
+ case KeyEvent.VK_SHIFT:
+ modifiers |= InputEvent.SHIFT_MASK;
+ break;
+ case KeyEvent.VK_ALT:
+ modifiers |= InputEvent.ALT_MASK;
+ break;
+ case KeyEvent.VK_ALT_GRAPH:
+ modifiers |= InputEvent.ALT_GRAPH_MASK;
+ break;
+ case KeyEvent.VK_CONTROL:
+ modifiers |= InputEvent.CTRL_MASK;
+ break;
+ }
+
+ if(null != focusedWindow) {
+ focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyCode, keyChar);
+ }
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("[event pressed] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+ }
+ break;
+ case 2:
+ eventType=KeyEvent.EVENT_KEY_PRESSED;
+ modifiers |= InputEvent.AUTOREPEAT_MASK;
+
+ switch(keyCode) {
+ case KeyEvent.VK_SHIFT:
+ modifiers |= InputEvent.SHIFT_MASK;
+ break;
+ case KeyEvent.VK_ALT:
+ modifiers |= InputEvent.ALT_MASK;
+ break;
+ case KeyEvent.VK_ALT_GRAPH:
+ modifiers |= InputEvent.ALT_GRAPH_MASK;
+ break;
+ case KeyEvent.VK_CONTROL:
+ modifiers |= InputEvent.CTRL_MASK;
+ break;
+ }
+
+ if(null != focusedWindow) {
+ //Send syntetic autorepeat release
+ focusedWindow.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keyCode, keyChar);
+
+ focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyCode, keyChar);
+ }
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("[event released auto] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+ System.out.println("[event pressed auto] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+ }
+ modifiers &= ~InputEvent.AUTOREPEAT_MASK;
+ break;
+ }
+ break;
+ case 4: // EV_MSC
+ if(code==4) { // MSC_SCAN
+ // scancode ignore, linux kernel specific
+ }
+ break;
+ // TODO: handle joystick events
+ // TODO: handle mouse events
+ // TODO: handle headphone/hdmi connector events
+ default: // Print number.
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("TODO EventDevicePoller: [time "+timeSeconds+":"+timeSecondFraction+"] type "+type+" / code "+code+" = value "+value);
+ }
+ }
+ }
+
+ if(null != fis) {
+ try {
+ fis.close();
+ } catch (final IOException e) {
+ }
+ }
+ stop=true;
+ }
+
+ private char NewtVKey2Unicode(final short VK, final int modifiers) {
+ if( KeyEvent.isPrintableKey(VK, true) ) {
+ if((modifiers & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) {
+ return (char)VK;
+ } else {
+ return String.valueOf((char)VK).toLowerCase().charAt(0);
+ }
+ }
+ return 0;
+ }
+
+ @SuppressWarnings("unused")
+ private char LinuxEVKey2Unicode(final short EVKey) {
+ // This is the stuff normally mapped by a system keymap
+
+ switch(EVKey) {
+ case 17: // w
+ return 'w';
+ case 31: // s
+ return 's';
+ case 30: // a
+ return 'a';
+ case 32: // d
+ return 'd';
+ case 1: // ESC
+ return 27;
+ case 28: // Enter
+ case 96: // Keypad Enter
+ return '\n';
+ case 57: // Space
+ return ' ';
+ case 11: // 0
+ case 82: // Numpad 0
+ return '0';
+ case 2: // 1
+ case 79: // Numpad 1
+ return '1';
+ case 3: // 2
+ case 80: // Numpad 1
+ return '2';
+ case 4: // 3
+ case 81: // Numpad 3
+ return '3';
+ case 5: // 4
+ case 75: // Numpad 4
+ return '4';
+ case 6: // 5
+ case 76: // Numpad 5
+ return '5';
+ case 7: // 6
+ case 77: // Numpad 6
+ return '6';
+ case 8: // 7
+ case 71: // Numpad 7
+ return '7';
+ case 9: // 8
+ case 72: // Numpad 8
+ return '8';
+ case 10: // 9
+ case 73: // Numpad 9
+ return '9';
+
+ default:
+ }
+
+ return 0;
+ }
+
+ private short LinuxEVKey2NewtVKey(final short EVKey) {
+
+ switch(EVKey) {
+ case 1: // ESC
+ return KeyEvent.VK_ESCAPE;
+ case 2: // 1
+ return KeyEvent.VK_1;
+ case 79: // Numpad 1
+ return KeyEvent.VK_NUMPAD1;
+ case 3: // 2
+ return KeyEvent.VK_2;
+ case 80: // Numpad 2
+ return KeyEvent.VK_NUMPAD2;
+ case 4: // 3
+ return KeyEvent.VK_3;
+ case 81: // Numpad 3
+ return KeyEvent.VK_NUMPAD3;
+ case 5: // 4
+ return KeyEvent.VK_4;
+ case 75: // Numpad 4
+ return KeyEvent.VK_NUMPAD4;
+ case 6: // 5
+ return KeyEvent.VK_5;
+ case 76: // Numpad 5
+ return KeyEvent.VK_NUMPAD5;
+ case 7: // 6
+ return KeyEvent.VK_6;
+ case 77: // Numpad 6
+ return KeyEvent.VK_NUMPAD6;
+ case 8: // 7
+ return KeyEvent.VK_7;
+ case 71: // Numpad 7
+ return KeyEvent.VK_NUMPAD7;
+ case 9: // 8
+ return KeyEvent.VK_8;
+ case 72: // Numpad 8
+ return KeyEvent.VK_NUMPAD8;
+ case 10: // 9
+ return KeyEvent.VK_9;
+ case 73: // Numpad 9
+ return KeyEvent.VK_NUMPAD9;
+ case 11: // 0
+ return KeyEvent.VK_0;
+ case 82: // Numpad 0
+ return KeyEvent.VK_NUMPAD0;
+ case 12:
+ return KeyEvent.VK_MINUS;
+ case 13:
+ return KeyEvent.VK_EQUALS;
+ case 14: // Backspace
+ return KeyEvent.VK_BACK_SPACE;
+
+ case 15:
+ return KeyEvent.VK_TAB;
+ case 16:
+ return KeyEvent.VK_Q;
+ case 17: // w
+ return KeyEvent.VK_W;
+ case 18:
+ return KeyEvent.VK_E;
+ case 19:
+ return KeyEvent.VK_R;
+ case 20:
+ return KeyEvent.VK_T;
+ case 21:
+ return KeyEvent.VK_Y;
+ case 22:
+ return KeyEvent.VK_U;
+ case 23:
+ return KeyEvent.VK_I;
+ case 24:
+ return KeyEvent.VK_O;
+ case 25:
+ return KeyEvent.VK_P;
+ case 26: // left brace
+ return KeyEvent.VK_LEFT_PARENTHESIS;
+ case 27: // right brace
+ return KeyEvent.VK_RIGHT_PARENTHESIS;
+ case 28: // Enter
+ case 96: // Keypad Enter
+ return KeyEvent.VK_ENTER;
+
+ case 29: // left ctrl
+ return KeyEvent.VK_CONTROL;
+ case 30: // a
+ return KeyEvent.VK_A;
+ case 31: // s
+ return KeyEvent.VK_S;
+ case 32: // d
+ return KeyEvent.VK_D;
+ case 33:
+ return KeyEvent.VK_F;
+ case 34:
+ return KeyEvent.VK_G;
+ case 35:
+ return KeyEvent.VK_H;
+ case 36:
+ return KeyEvent.VK_J;
+ case 37:
+ return KeyEvent.VK_K;
+ case 38:
+ return KeyEvent.VK_L;
+ case 39:
+ return KeyEvent.VK_SEMICOLON;
+ case 40: // apostrophe
+ return KeyEvent.VK_QUOTE;
+ case 41: // grave
+ return KeyEvent.VK_BACK_QUOTE;
+
+ case 42: // left shift
+ return KeyEvent.VK_SHIFT;
+ case 43:
+ return KeyEvent.VK_BACK_SLASH;
+ case 44:
+ return KeyEvent.VK_Z;
+ case 45:
+ return KeyEvent.VK_X;
+ case 46:
+ return KeyEvent.VK_C;
+ case 47:
+ return KeyEvent.VK_V;
+ case 48:
+ return KeyEvent.VK_B;
+ case 49:
+ return KeyEvent.VK_N;
+ case 50:
+ return KeyEvent.VK_M;
+ case 51:
+ return KeyEvent.VK_COMMA;
+ case 52: // dot
+ return KeyEvent.VK_PERIOD;
+ case 53:
+ return KeyEvent.VK_SLASH;
+ case 54:
+ return KeyEvent.VK_SHIFT;
+ case 55: // kp asterisk
+ return KeyEvent.VK_ASTERISK;
+ case 56: // left alt
+ return KeyEvent.VK_ALT;
+ case 57: // Space
+ return KeyEvent.VK_SPACE;
+ case 58:
+ return KeyEvent.VK_CAPS_LOCK;
+
+ case 59:
+ return KeyEvent.VK_F1;
+ case 60:
+ return KeyEvent.VK_F2;
+ case 61:
+ return KeyEvent.VK_F3;
+ case 62:
+ return KeyEvent.VK_F4;
+ case 63:
+ return KeyEvent.VK_F5;
+ case 64:
+ return KeyEvent.VK_F6;
+ case 65:
+ return KeyEvent.VK_F7;
+ case 66:
+ return KeyEvent.VK_F8;
+ case 67:
+ return KeyEvent.VK_F9;
+ case 68:
+ return KeyEvent.VK_F10;
+
+ case 69:
+ return KeyEvent.VK_NUM_LOCK;
+ case 70:
+ return KeyEvent.VK_SCROLL_LOCK;
+
+ case 74: // kp minus
+ return KeyEvent.VK_MINUS;
+ case 78: // kp plus
+ return KeyEvent.VK_PLUS;
+ case 83: // kp dot
+ return KeyEvent.VK_PERIOD;
+
+ // TODO: add mappings for japanese special buttons
+ case 85: // zenkakuhankaku
+ case 86: // 102nd
+ break; // FIXME
+
+ case 87:
+ return KeyEvent.VK_F11;
+ case 88:
+ return KeyEvent.VK_F12;
+
+ case 89: // ro
+ return KeyEvent.VK_ROMAN_CHARACTERS;
+ case 90: // Katakana
+ return KeyEvent.VK_KATAKANA;
+ case 91:
+ return KeyEvent.VK_HIRAGANA;
+
+ case 92: // kenkan
+ break; // FIXME
+ case 93: // katakana hiragana
+ break; // FIXME
+ case 94: // mu henkan
+ break; // FIXME
+ case 95: // kp jp comma
+ break; // FIXME
+
+ case 97: // right ctrl
+ return KeyEvent.VK_CONTROL;
+ case 98: // kp slash
+ return KeyEvent.VK_SLASH;
+
+ case 99: // sysrq
+ break; // FIXME
+
+ case 100: // right alt
+ return KeyEvent.VK_ALT;
+ case 101: // linefeed
+ break; // FIXME
+ case 102: // home
+ return KeyEvent.VK_HOME;
+ case 103: // KEY_UP
+ return KeyEvent.VK_UP;
+ case 104:
+ return KeyEvent.VK_PAGE_UP;
+ case 105: // KEY_LEFT
+ return KeyEvent.VK_LEFT;
+ case 106: // KEY_RIGHT
+ return KeyEvent.VK_RIGHT;
+ case 107:
+ return KeyEvent.VK_END;
+ case 108: // KEY_DOWN
+ return KeyEvent.VK_DOWN;
+ case 109:
+ return KeyEvent.VK_PAGE_DOWN;
+ case 110:
+ return KeyEvent.VK_INSERT;
+ case 111: // del
+ return KeyEvent.VK_DELETE;
+
+ case 112: // macro
+ break; // FIXME DEAD_MACRON?
+ case 113: // mute
+ break; // FIXME
+ case 114: // vol up
+ break; // FIXME
+ case 115: // vol down
+ break; // FIXME
+ case 116: // power
+ break; // FIXME
+
+ case 117: // kp equals
+ return KeyEvent.VK_EQUALS;
+ case 118: // kp plus minux
+ break; // FIXME
+ case 119: // pause
+ return KeyEvent.VK_PAUSE;
+ case 120: // scale AL compiz scale expose
+ break; // FIXME
+ case 121: // kp comma
+ return KeyEvent.VK_COMMA;
+ case 122: // hangeul
+ break; // FIXME
+ case 123: // hanja
+ break; // FIXME
+ case 124: // yen
+ break; // FIXME
+
+ case 125: // left meta
+ case 126: // right meta
+ return KeyEvent.VK_META;
+ case 127: // compose
+ return KeyEvent.VK_COMPOSE;
+
+ case 128: // stop
+ return KeyEvent.VK_STOP;
+ case 129: // again
+ return KeyEvent.VK_AGAIN;
+ case 130: // properties
+ return KeyEvent.VK_PROPS;
+ case 131: // undo
+ return KeyEvent.VK_UNDO;
+ case 132: // front
+ break; // FIXME
+ case 133: // copy
+ return KeyEvent.VK_COPY;
+ case 134: // open
+ break; // FIXME
+ case 135: // paste
+ return KeyEvent.VK_PASTE;
+ case 136: // find
+ return KeyEvent.VK_FIND;
+ case 137: // cut
+ return KeyEvent.VK_CUT;
+ case 138: // help
+ return KeyEvent.VK_HELP;
+ case 139: // menu
+ break; // FIXME
+ case 140: // calc
+ break; // FIXME
+ case 141: // setup
+ break; // FIXME
+ case 142: // sleep
+ break; // FIXME
+ case 143: // wakeup
+ break; // FIXME
+ case 144: // file
+ break; // FIXME
+ case 145: // send file
+ break; // FIXME
+ case 146: // delete file
+ break; // FIXME
+ case 147: // xfer
+ break; // FIXME
+ case 148: // prog1
+ break; // FIXME
+ case 149: // prog2
+ break; // FIXME
+ case 150: // www
+ break; // FIXME
+ case 151: // msdos
+ break; // FIXME
+ case 152: // coffee
+ break; // FIXME
+ case 153: // direction
+ break; // FIXME
+ case 154: // cycle windows
+ break; // FIXME
+ case 155: // mail
+ break; // FIXME
+ case 156: // bookmarks
+ break; // FIXME
+ case 157: // computer
+ break; // FIXME
+ case 158: // back
+ break; // FIXME
+ case 159: // forward
+ break; // FIXME
+ case 160: // close cd
+ break; // FIXME
+ case 161: // eject cd
+ break; // FIXME
+ case 162: // eject close cd
+ break; // FIXME
+ case 163: // next song
+ break; // FIXME
+ case 164: // play pause
+ break; // FIXME
+ case 165: // previous song
+ break; // FIXME
+ case 166: // stop cd
+ break; // FIXME
+ case 167: // record
+ break; // FIXME
+ case 168: // rewind
+ break; // FIXME
+ case 169: // phone
+ break; // FIXME
+ case 170: // ISO
+ break; // FIXME
+ case 171: // config
+ break; // FIXME
+ case 172: // home page
+ break; // FIXME
+ case 173: // refresh
+ break; // FIXME
+ case 174: // exit
+ break; // FIXME
+ case 175: // move
+ break; // FIXME
+ case 176: // edit
+ break; // FIXME
+ case 177: // scroll up
+ break; // FIXME PAGE_UP?
+ case 178: // scroll down
+ break; // FIXME PAGE_DOWN?
+ case 179: // kp left paren
+ return KeyEvent.VK_LEFT_PARENTHESIS;
+ case 180: // kp right paren
+ return KeyEvent.VK_RIGHT_PARENTHESIS;
+ case 181: // new
+ break; // FIXME
+ case 182: // redo
+ break; // FIXME
+
+ case 183: // F13
+ return KeyEvent.VK_F13;
+ case 184: // F14
+ return KeyEvent.VK_F14;
+ case 185: // F15
+ return KeyEvent.VK_F15;
+ case 186: // F16
+ return KeyEvent.VK_F16;
+ case 187: // F17
+ return KeyEvent.VK_F17;
+ case 188: // F18
+ return KeyEvent.VK_F18;
+ case 189: // F19
+ return KeyEvent.VK_F19;
+ case 190: // F20
+ return KeyEvent.VK_F20;
+ case 191: // F21
+ return KeyEvent.VK_F21;
+ case 192: // F22
+ return KeyEvent.VK_F22;
+ case 193: // F23
+ return KeyEvent.VK_F23;
+ case 194: // F24
+ return KeyEvent.VK_F24;
+
+ case 200: // play cd
+ break; // FIXME
+ case 201: // pause cd
+ break; // FIXME
+ case 202: // prog 3
+ break; // FIXME
+ case 203: // prog 4
+ break; // FIXME
+ case 204: // dashboard
+ break; // FIXME
+ case 205: // suspend
+ break; // FIXME
+ case 206: // close
+ break; // FIXME
+ case 207: // play
+ break; // FIXME
+ case 208: // fast forward
+ break; // FIXME
+ case 210: // print
+ return KeyEvent.VK_PRINTSCREEN; // FIXME ?
+ case 211: // HP
+ break; // FIXME
+ case 212: // camera
+ break; // FIXME
+ case 213: // sound
+ break; // FIXME
+ case 214: // question
+ break; // FIXME
+ case 215: // email
+ break; // FIXME
+ case 216: // chat
+ break; // FIXME
+ case 217: // search
+ break; // FIXME
+ case 218: // connect
+ break; // FIXME
+ case 219: // finance
+ break; // FIXME
+ case 220: // sport
+ break; // FIXME
+ case 221: // shop
+ break; // FIXME
+ case 222: // alt erase
+ break; // FIXME
+ case 223: // cancel
+ break; // FIXME
+ case 224: // brightness down
+ break; // FIXME
+ case 225: // brightness up
+ break; // FIXME
+ case 226: // media
+ break; // FIXME
+ case 227: // switch video mode
+ break; // FIXME
+ case 228: // kb dillum toggle
+ break; // FIXME
+ case 229: // kb dillum down
+ break; // FIXME
+ case 230: // kb dillum up
+ break; // FIXME
+ case 231: // send
+ break; // FIXME
+ case 232: // reply
+ break; // FIXME
+ case 233: // forward mail
+ break; // FIXME
+ case 234: // save
+ break; // FIXME
+ case 235: // documents
+ break; // FIXME
+ case 236: // battery
+ break; // FIXME
+ case 237: // bluetooth
+ break; // FIXME
+ case 238: // wlan
+ break; // FIXME
+ case 239: // UWB
+ break; // FIXME
+ case 240: // unknown
+ return KeyEvent.VK_UNDEFINED;
+ case 241: // video next
+ break; // FIXME
+ case 242: // video prev
+ break; // FIXME
+ case 243: // brightness cycle
+ break; // FIXME
+ case 244: // brightness zero
+ break; // FIXME
+ case 245: // display off
+ break; // FIXME
+ case 246: // wimax
+ break; // FIXME
+ case 247: // rf kill radio off
+ break; // FIXME
+ case 248: // mic mute
+ break; // FIXME
+
+ default:
+ }
+
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("TODO LinuxEVKey2NewtVKey: Unmapped EVKey "+EVKey);
+ }
+
+ return KeyEvent.VK_UNDEFINED;
+ }
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java
index 885649d17..1d9377563 100644
--- a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java
+++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -36,6 +36,7 @@ import java.io.InputStream;
import jogamp.newt.WindowImpl;
+import com.jogamp.newt.Screen;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.WindowEvent;
@@ -48,16 +49,16 @@ import com.jogamp.newt.event.WindowUpdateEvent;
* within it's own polling thread.
*/
public class LinuxMouseTracker implements WindowListener {
-
+
private static final LinuxMouseTracker lmt;
-
+
static {
lmt = new LinuxMouseTracker();
final Thread t = new Thread(lmt.mouseDevicePoller, "NEWT-LinuxMouseTracker");
t.setDaemon(true);
t.start();
}
-
+
public static LinuxMouseTracker getSingleton() {
return lmt;
}
@@ -65,49 +66,54 @@ public class LinuxMouseTracker implements WindowListener {
private volatile boolean stop = false;
private int x = 0;
private int y = 0;
- private int buttonDown = 0;
+ private short buttonDown = 0;
private int old_x = 0;
private int old_y = 0;
- private int old_buttonDown = 0;
+ private volatile int lastFocusedX = 0;
+ private volatile int lastFocusedY = 0;
+ private short old_buttonDown = 0;
private WindowImpl focusedWindow = null;
- private MouseDevicePoller mouseDevicePoller = new MouseDevicePoller();
-
+ private final MouseDevicePoller mouseDevicePoller = new MouseDevicePoller();
+
+ public final int getLastX() { return lastFocusedX; }
+ public final int getLastY() { return lastFocusedY; }
+
@Override
- public void windowResized(WindowEvent e) { }
+ public void windowResized(final WindowEvent e) { }
@Override
- public void windowMoved(WindowEvent e) { }
+ public void windowMoved(final WindowEvent e) { }
@Override
- public void windowDestroyNotify(WindowEvent e) {
- Object s = e.getSource();
+ public void windowDestroyNotify(final WindowEvent e) {
+ final Object s = e.getSource();
if(focusedWindow == s) {
focusedWindow = null;
}
}
@Override
- public void windowDestroyed(WindowEvent e) { }
+ public void windowDestroyed(final WindowEvent e) { }
@Override
- public void windowGainedFocus(WindowEvent e) {
- Object s = e.getSource();
+ public void windowGainedFocus(final WindowEvent e) {
+ final Object s = e.getSource();
if(s instanceof WindowImpl) {
focusedWindow = (WindowImpl) s;
}
}
@Override
- public void windowLostFocus(WindowEvent e) {
- Object s = e.getSource();
+ public void windowLostFocus(final WindowEvent e) {
+ final Object s = e.getSource();
if(focusedWindow == s) {
focusedWindow = null;
}
}
@Override
- public void windowRepaint(WindowUpdateEvent e) { }
-
+ public void windowRepaint(final WindowUpdateEvent e) { }
+
class MouseDevicePoller implements Runnable {
@Override
public void run() {
@@ -117,7 +123,7 @@ public class LinuxMouseTracker implements WindowListener {
InputStream fis;
try {
fis = new FileInputStream(f);
- } catch (FileNotFoundException e) {
+ } catch (final FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
@@ -131,7 +137,7 @@ public class LinuxMouseTracker implements WindowListener {
int read = 0;
try {
read = fis.read(b, 0, remaining);
- } catch (IOException e) {
+ } catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
@@ -150,17 +156,18 @@ public class LinuxMouseTracker implements WindowListener {
yo=(b[0]&128)>0;
xd=b[1];
yd=b[2];
-
+
x+=xd;
- y+=yd;
-
+ y-=yd;
+
if(x<0) {
x=0;
}
if(y<0) {
y=0;
}
-
+
+ buttonDown = 0;
if(lb) {
buttonDown = MouseEvent.BUTTON1;
}
@@ -170,52 +177,56 @@ public class LinuxMouseTracker implements WindowListener {
if(rb) {
buttonDown = MouseEvent.BUTTON3;
}
-
+
if(null != focusedWindow) {
- if( x >= focusedWindow.getScreen().getWidth() ) {
- x = focusedWindow.getScreen().getWidth() - 1;
- }
- if( y >= focusedWindow.getScreen().getHeight() ) {
- y = focusedWindow.getScreen().getHeight() - 1;
+ // Clip to Screen Size
+ {
+ final Screen focusedScreen = focusedWindow.getScreen();
+ final int sw = focusedScreen.getWidth();
+ final int sh = focusedScreen.getHeight();
+ if( x >= sw ) {
+ x = sw - 1;
+ }
+ if( y >= sh ) {
+ y = sh - 1;
+ }
}
- int wx = x - focusedWindow.getX(), wy = y - focusedWindow.getY();
-
+ final int[] winScreenPos = focusedWindow.convertToPixelUnits(new int[] { focusedWindow.getX(), focusedWindow.getY() });
+ final int wx = x - winScreenPos[0], wy = y - winScreenPos[1];
if(old_x != x || old_y != y) {
// mouse moved
- focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_MOVED, 0, wx, wy, 0, 0 );
+ lastFocusedX = wx;
+ lastFocusedY = wy;
+ focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_MOVED, 0, wx, wy, (short)0, 0 );
}
-
+
if(old_buttonDown != buttonDown) {
// press/release
if( 0 != buttonDown ) {
- focusedWindow.sendMouseEvent(
- MouseEvent.EVENT_MOUSE_PRESSED,
- 0, wx, wy, buttonDown, 0 );
+ focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_PRESSED, 0, wx, wy, buttonDown, 0 );
} else {
- focusedWindow.sendMouseEvent(
- MouseEvent.EVENT_MOUSE_RELEASED,
- 0, wx, wy, old_buttonDown, 0 );
+ focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_RELEASED, 0, wx, wy, old_buttonDown, 0 );
}
- }
+ }
} else {
if(Window.DEBUG_MOUSE_EVENT) {
System.out.println(x+"/"+y+", hs="+hs+",vs="+vs+",lb="+lb+",rb="+rb+",mb="+mb+",xo="+xo+",yo="+yo+"xd="+xd+",yd="+yd);
}
}
-
+
old_x = x;
old_y = y;
old_buttonDown = buttonDown;
-
+
}
if(null != fis) {
try {
fis.close();
- } catch (IOException e) {
+ } catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- }
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
index 1a3f14859..051294dce 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,20 +29,31 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.macosx;
+import java.net.URLConnection;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.PixelFormat;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.opengl.util.PNGPixelRect;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
public class DisplayDriver extends DisplayImpl {
+ private static final PNGPixelRect defaultIconData;
+
static {
NEWTJNILibLoader.loadNEWT();
@@ -52,6 +63,27 @@ public class DisplayDriver extends DisplayImpl {
if(!WindowDriver.initIDs0()) {
throw new NativeWindowException("Failed to initialize jmethodIDs");
}
+ {
+ PNGPixelRect image=null;
+ if( DisplayImpl.isPNGUtilAvailable() ) {
+ try {
+ // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons();
+ final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1);
+ image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.RGBA8888, true /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ defaultIconData = image;
+ if( null != defaultIconData ) {
+ final Buffer pixels = defaultIconData.getPixels();
+ DisplayDriver.setAppIcon0(
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */,
+ defaultIconData.getSize().getWidth(), defaultIconData.getSize().getHeight());
+ }
+ }
+
if(DEBUG) {
System.err.println("MacDisplay.init App and IDs OK "+Thread.currentThread().getName());
}
@@ -60,19 +92,48 @@ public class DisplayDriver extends DisplayImpl {
public static void initSingleton() {
// just exist to ensure static init has been run
}
-
+
public DisplayDriver() {
}
+ @Override
+ public PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.RGBA8888; }
+
+ @Override
protected void dispatchMessagesNative() {
// nop
}
-
+
+ @Override
protected void createNativeImpl() {
aDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
}
- protected void closeNativeImpl() { }
+ @Override
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
+ aDevice.close();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ * </p>
+ */
+ @Override
+ public final boolean getNativePointerIconForceDirectNIO() { return true; }
+
+ @Override
+ protected final long createPointerIconImpl(final PixelFormat pixelformat, final int width, final int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createPointerIcon0(
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */,
+ width, height, hotX, hotY);
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, final long piHandle) {
+ destroyPointerIcon0(piHandle);
+ }
public static void runNSApplication() {
runNSApplication0();
@@ -84,5 +145,9 @@ public class DisplayDriver extends DisplayImpl {
private static native boolean initNSApplication0();
private static native void runNSApplication0();
private static native void stopNSApplication0();
+ /* pp */ static native void setAppIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height);
+ private static native long createPointerIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY);
+ private static native long destroyPointerIcon0(long handle);
+
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java b/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java
index d39e0027b..d80d43e8f 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -30,57 +30,130 @@ package jogamp.newt.driver.macosx;
import com.jogamp.newt.event.KeyEvent;
public class MacKeyUtil {
-
- // KeyCodes (independent)
- private static final int kVK_Return = 0x24;
- private static final int kVK_Tab = 0x30;
- private static final int kVK_Space = 0x31;
- private static final int kVK_Delete = 0x33;
- private static final int kVK_Escape = 0x35;
- private static final int kVK_Command = 0x37;
- private static final int kVK_Shift = 0x38;
- private static final int kVK_CapsLock = 0x39;
- private static final int kVK_Option = 0x3A;
- private static final int kVK_Control = 0x3B;
- private static final int kVK_RightShift = 0x3C;
- private static final int kVK_RightOption = 0x3D;
- private static final int kVK_RightControl = 0x3E;
- private static final int kVK_Function = 0x3F;
- private static final int kVK_F17 = 0x40;
- private static final int kVK_VolumeUp = 0x48;
- private static final int kVK_VolumeDown = 0x49;
- private static final int kVK_Mute = 0x4A;
- private static final int kVK_F18 = 0x4F;
- private static final int kVK_F19 = 0x50;
- private static final int kVK_F20 = 0x5A;
- private static final int kVK_F5 = 0x60;
- private static final int kVK_F6 = 0x61;
- private static final int kVK_F7 = 0x62;
- private static final int kVK_F3 = 0x63;
- private static final int kVK_F8 = 0x64;
- private static final int kVK_F9 = 0x65;
- private static final int kVK_F11 = 0x67;
- private static final int kVK_F13 = 0x69;
- private static final int kVK_F16 = 0x6A;
- private static final int kVK_F14 = 0x6B;
- private static final int kVK_F10 = 0x6D;
- private static final int kVK_F12 = 0x6F;
- private static final int kVK_F15 = 0x71;
- private static final int kVK_Help = 0x72;
- private static final int kVK_Home = 0x73;
- private static final int kVK_PageUp = 0x74;
- private static final int kVK_ForwardDelete = 0x75;
- private static final int kVK_F4 = 0x76;
- private static final int kVK_End = 0x77;
- private static final int kVK_F2 = 0x78;
- private static final int kVK_PageDown = 0x79;
- private static final int kVK_F1 = 0x7A;
- private static final int kVK_LeftArrow = 0x7B;
- private static final int kVK_RightArrow = 0x7C;
- private static final int kVK_DownArrow = 0x7D;
- private static final int kVK_UpArrow = 0x7E;
-
+
+ //
+ // KeyCodes (Layout Dependent)
+ //
+ private static final short kVK_ANSI_A = 0x00;
+ private static final short kVK_ANSI_S = 0x01;
+ private static final short kVK_ANSI_D = 0x02;
+ private static final short kVK_ANSI_F = 0x03;
+ private static final short kVK_ANSI_H = 0x04;
+ private static final short kVK_ANSI_G = 0x05;
+ private static final short kVK_ANSI_Z = 0x06;
+ private static final short kVK_ANSI_X = 0x07;
+ private static final short kVK_ANSI_C = 0x08;
+ private static final short kVK_ANSI_V = 0x09;
+ private static final short kVK_ANSI_B = 0x0B;
+ private static final short kVK_ANSI_Q = 0x0C;
+ private static final short kVK_ANSI_W = 0x0D;
+ private static final short kVK_ANSI_E = 0x0E;
+ private static final short kVK_ANSI_R = 0x0F;
+ private static final short kVK_ANSI_Y = 0x10;
+ private static final short kVK_ANSI_T = 0x11;
+ private static final short kVK_ANSI_1 = 0x12;
+ private static final short kVK_ANSI_2 = 0x13;
+ private static final short kVK_ANSI_3 = 0x14;
+ private static final short kVK_ANSI_4 = 0x15;
+ private static final short kVK_ANSI_6 = 0x16;
+ private static final short kVK_ANSI_5 = 0x17;
+ private static final short kVK_ANSI_Equal = 0x18;
+ private static final short kVK_ANSI_9 = 0x19;
+ private static final short kVK_ANSI_7 = 0x1A;
+ private static final short kVK_ANSI_Minus = 0x1B;
+ private static final short kVK_ANSI_8 = 0x1C;
+ private static final short kVK_ANSI_0 = 0x1D;
+ private static final short kVK_ANSI_RightBracket = 0x1E;
+ private static final short kVK_ANSI_O = 0x1F;
+ private static final short kVK_ANSI_U = 0x20;
+ private static final short kVK_ANSI_LeftBracket = 0x21;
+ private static final short kVK_ANSI_I = 0x22;
+ private static final short kVK_ANSI_P = 0x23;
+ private static final short kVK_ANSI_L = 0x25;
+ private static final short kVK_ANSI_J = 0x26;
+ private static final short kVK_ANSI_Quote = 0x27;
+ private static final short kVK_ANSI_K = 0x28;
+ private static final short kVK_ANSI_Semicolon = 0x29;
+ private static final short kVK_ANSI_Backslash = 0x2A;
+ private static final short kVK_ANSI_Comma = 0x2B;
+ private static final short kVK_ANSI_Slash = 0x2C;
+ private static final short kVK_ANSI_N = 0x2D;
+ private static final short kVK_ANSI_M = 0x2E;
+ private static final short kVK_ANSI_Period = 0x2F;
+ private static final short kVK_ANSI_Grave = 0x32;
+ private static final short kVK_ANSI_KeypadDecimal = 0x41;
+ private static final short kVK_ANSI_KeypadMultiply = 0x43;
+ private static final short kVK_ANSI_KeypadPlus = 0x45;
+ private static final short kVK_ANSI_KeypadClear = 0x47;
+ private static final short kVK_ANSI_KeypadDivide = 0x4B;
+ private static final short kVK_ANSI_KeypadEnter = 0x4C;
+ private static final short kVK_ANSI_KeypadMinus = 0x4E;
+ private static final short kVK_ANSI_KeypadEquals = 0x51;
+ private static final short kVK_ANSI_Keypad0 = 0x52;
+ private static final short kVK_ANSI_Keypad1 = 0x53;
+ private static final short kVK_ANSI_Keypad2 = 0x54;
+ private static final short kVK_ANSI_Keypad3 = 0x55;
+ private static final short kVK_ANSI_Keypad4 = 0x56;
+ private static final short kVK_ANSI_Keypad5 = 0x57;
+ private static final short kVK_ANSI_Keypad6 = 0x58;
+ private static final short kVK_ANSI_Keypad7 = 0x59;
+ private static final short kVK_ANSI_Keypad8 = 0x5B;
+ private static final short kVK_ANSI_Keypad9 = 0x5C;
+
+ //
+ // KeyCodes (Layout Independent)
+ //
+ private static final short kVK_Return = 0x24;
+ private static final short kVK_Tab = 0x30;
+ private static final short kVK_Space = 0x31;
+ private static final short kVK_Delete = 0x33;
+ private static final short kVK_Escape = 0x35;
+ private static final short kVK_Command = 0x37;
+ private static final short kVK_Shift = 0x38;
+ private static final short kVK_CapsLock = 0x39;
+ private static final short kVK_Option = 0x3A;
+ private static final short kVK_Control = 0x3B;
+ private static final short kVK_RightShift = 0x3C;
+ private static final short kVK_RightOption = 0x3D;
+ private static final short kVK_RightControl = 0x3E;
+ // private static final short kVK_Function = 0x3F;
+ private static final short kVK_F17 = 0x40;
+ // private static final short kVK_VolumeUp = 0x48;
+ // private static final short kVK_VolumeDown = 0x49;
+ // private static final short kVK_Mute = 0x4A;
+ private static final short kVK_F18 = 0x4F;
+ private static final short kVK_F19 = 0x50;
+ private static final short kVK_F20 = 0x5A;
+ private static final short kVK_F5 = 0x60;
+ private static final short kVK_F6 = 0x61;
+ private static final short kVK_F7 = 0x62;
+ private static final short kVK_F3 = 0x63;
+ private static final short kVK_F8 = 0x64;
+ private static final short kVK_F9 = 0x65;
+ private static final short kVK_F11 = 0x67;
+ private static final short kVK_F13 = 0x69;
+ private static final short kVK_F16 = 0x6A;
+ private static final short kVK_F14 = 0x6B;
+ private static final short kVK_F10 = 0x6D;
+ private static final short kVK_F12 = 0x6F;
+ private static final short kVK_F15 = 0x71;
+ private static final short kVK_Help = 0x72;
+ private static final short kVK_Home = 0x73;
+ private static final short kVK_PageUp = 0x74;
+ private static final short kVK_ForwardDelete = 0x75;
+ private static final short kVK_F4 = 0x76;
+ private static final short kVK_End = 0x77;
+ private static final short kVK_F2 = 0x78;
+ private static final short kVK_PageDown = 0x79;
+ private static final short kVK_F1 = 0x7A;
+ private static final short kVK_LeftArrow = 0x7B;
+ private static final short kVK_RightArrow = 0x7C;
+ private static final short kVK_DownArrow = 0x7D;
+ private static final short kVK_UpArrow = 0x7E;
+
+ //
// Key constants handled differently on Mac OS X than other platforms
+ //
private static final char NSUpArrowFunctionKey = 0xF700;
private static final char NSDownArrowFunctionKey = 0xF701;
private static final char NSLeftArrowFunctionKey = 0xF702;
@@ -109,6 +182,7 @@ public class MacKeyUtil {
private static final char NSF22FunctionKey = 0xF719;
private static final char NSF23FunctionKey = 0xF71A;
private static final char NSF24FunctionKey = 0xF71B;
+ /**
private static final char NSF25FunctionKey = 0xF71C;
private static final char NSF26FunctionKey = 0xF71D;
private static final char NSF27FunctionKey = 0xF71E;
@@ -120,6 +194,7 @@ public class MacKeyUtil {
private static final char NSF33FunctionKey = 0xF724;
private static final char NSF34FunctionKey = 0xF725;
private static final char NSF35FunctionKey = 0xF726;
+ */
private static final char NSInsertFunctionKey = 0xF727;
private static final char NSDeleteFunctionKey = 0xF728;
private static final char NSHomeFunctionKey = 0xF729;
@@ -130,10 +205,11 @@ public class MacKeyUtil {
private static final char NSPrintScreenFunctionKey = 0xF72E;
private static final char NSScrollLockFunctionKey = 0xF72F;
private static final char NSPauseFunctionKey = 0xF730;
- private static final char NSSysReqFunctionKey = 0xF731;
- private static final char NSBreakFunctionKey = 0xF732;
- private static final char NSResetFunctionKey = 0xF733;
+ // private static final char NSSysReqFunctionKey = 0xF731;
+ // private static final char NSBreakFunctionKey = 0xF732;
+ // private static final char NSResetFunctionKey = 0xF733;
private static final char NSStopFunctionKey = 0xF734;
+ /**
private static final char NSMenuFunctionKey = 0xF735;
private static final char NSUserFunctionKey = 0xF736;
private static final char NSSystemFunctionKey = 0xF737;
@@ -153,26 +229,99 @@ public class MacKeyUtil {
private static final char NSFindFunctionKey = 0xF745;
private static final char NSHelpFunctionKey = 0xF746;
private static final char NSModeSwitchFunctionKey = 0xF747;
-
- static int validateKeyCode(int keyCode, char keyChar) {
+ */
+
+ static short validateKeyCode(final short keyCode, final char keyChar) {
// OS X Virtual Keycodes
switch(keyCode) {
+ //
+ // KeyCodes (Layout Dependent)
+ //
+ case kVK_ANSI_A: return KeyEvent.VK_A;
+ case kVK_ANSI_S: return KeyEvent.VK_S;
+ case kVK_ANSI_D: return KeyEvent.VK_D;
+ case kVK_ANSI_F: return KeyEvent.VK_F;
+ case kVK_ANSI_H: return KeyEvent.VK_H;
+ case kVK_ANSI_G: return KeyEvent.VK_G;
+ case kVK_ANSI_Z: return KeyEvent.VK_Z;
+ case kVK_ANSI_X: return KeyEvent.VK_X;
+ case kVK_ANSI_C: return KeyEvent.VK_C;
+ case kVK_ANSI_V: return KeyEvent.VK_V;
+ case kVK_ANSI_B: return KeyEvent.VK_B;
+ case kVK_ANSI_Q: return KeyEvent.VK_Q;
+ case kVK_ANSI_W: return KeyEvent.VK_W;
+ case kVK_ANSI_E: return KeyEvent.VK_E;
+ case kVK_ANSI_R: return KeyEvent.VK_R;
+ case kVK_ANSI_Y: return KeyEvent.VK_Y;
+ case kVK_ANSI_T: return KeyEvent.VK_T;
+ case kVK_ANSI_1: return KeyEvent.VK_1;
+ case kVK_ANSI_2: return KeyEvent.VK_2;
+ case kVK_ANSI_3: return KeyEvent.VK_3;
+ case kVK_ANSI_4: return KeyEvent.VK_4;
+ case kVK_ANSI_6: return KeyEvent.VK_6;
+ case kVK_ANSI_5: return KeyEvent.VK_5;
+ case kVK_ANSI_Equal: return KeyEvent.VK_EQUALS;
+ case kVK_ANSI_9: return KeyEvent.VK_9;
+ case kVK_ANSI_7: return KeyEvent.VK_7;
+ case kVK_ANSI_Minus: return KeyEvent.VK_MINUS;
+ case kVK_ANSI_8: return KeyEvent.VK_8;
+ case kVK_ANSI_0: return KeyEvent.VK_0;
+ case kVK_ANSI_RightBracket: return KeyEvent.VK_CLOSE_BRACKET;
+ case kVK_ANSI_O: return KeyEvent.VK_O;
+ case kVK_ANSI_U: return KeyEvent.VK_U;
+ case kVK_ANSI_LeftBracket: return KeyEvent.VK_OPEN_BRACKET;
+ case kVK_ANSI_I: return KeyEvent.VK_I;
+ case kVK_ANSI_P: return KeyEvent.VK_P;
+ case kVK_ANSI_L: return KeyEvent.VK_L;
+ case kVK_ANSI_J: return KeyEvent.VK_J;
+ case kVK_ANSI_Quote: return KeyEvent.VK_QUOTE;
+ case kVK_ANSI_K: return KeyEvent.VK_K;
+ case kVK_ANSI_Semicolon: return KeyEvent.VK_SEMICOLON;
+ case kVK_ANSI_Backslash: return KeyEvent.VK_BACK_SLASH;
+ case kVK_ANSI_Comma: return KeyEvent.VK_COMMA;
+ case kVK_ANSI_Slash: return KeyEvent.VK_SLASH;
+ case kVK_ANSI_N: return KeyEvent.VK_N;
+ case kVK_ANSI_M: return KeyEvent.VK_M;
+ case kVK_ANSI_Period: return KeyEvent.VK_PERIOD;
+ case kVK_ANSI_Grave: return KeyEvent.VK_BACK_QUOTE; // KeyEvent.VK_DEAD_GRAVE
+ case kVK_ANSI_KeypadDecimal: return KeyEvent.VK_DECIMAL;
+ case kVK_ANSI_KeypadMultiply: return KeyEvent.VK_MULTIPLY;
+ case kVK_ANSI_KeypadPlus: return KeyEvent.VK_PLUS;
+ case kVK_ANSI_KeypadClear: return KeyEvent.VK_CLEAR;
+ case kVK_ANSI_KeypadDivide: return KeyEvent.VK_DIVIDE;
+ case kVK_ANSI_KeypadEnter: return KeyEvent.VK_ENTER;
+ case kVK_ANSI_KeypadMinus: return KeyEvent.VK_MINUS;
+ case kVK_ANSI_KeypadEquals: return KeyEvent.VK_EQUALS;
+ case kVK_ANSI_Keypad0: return KeyEvent.VK_0;
+ case kVK_ANSI_Keypad1: return KeyEvent.VK_1;
+ case kVK_ANSI_Keypad2: return KeyEvent.VK_2;
+ case kVK_ANSI_Keypad3: return KeyEvent.VK_3;
+ case kVK_ANSI_Keypad4: return KeyEvent.VK_4;
+ case kVK_ANSI_Keypad5: return KeyEvent.VK_5;
+ case kVK_ANSI_Keypad6: return KeyEvent.VK_6;
+ case kVK_ANSI_Keypad7: return KeyEvent.VK_7;
+ case kVK_ANSI_Keypad8: return KeyEvent.VK_8;
+ case kVK_ANSI_Keypad9: return KeyEvent.VK_9;
+
+ //
+ // KeyCodes (Layout Independent)
+ //
case kVK_Return: return KeyEvent.VK_ENTER;
case kVK_Tab: return KeyEvent.VK_TAB;
case kVK_Space: return KeyEvent.VK_SPACE;
case kVK_Delete: return KeyEvent.VK_BACK_SPACE;
case kVK_Escape: return KeyEvent.VK_ESCAPE;
- case kVK_Command: return KeyEvent.VK_ALT;
+ case kVK_Command: return KeyEvent.VK_WINDOWS;
case kVK_Shift: return KeyEvent.VK_SHIFT;
case kVK_CapsLock: return KeyEvent.VK_CAPS_LOCK;
- case kVK_Option: return KeyEvent.VK_WINDOWS;
+ case kVK_Option: return KeyEvent.VK_ALT;
case kVK_Control: return KeyEvent.VK_CONTROL;
case kVK_RightShift: return KeyEvent.VK_SHIFT;
- case kVK_RightOption: return KeyEvent.VK_WINDOWS;
+ case kVK_RightOption: return KeyEvent.VK_ALT_GRAPH;
case kVK_RightControl: return KeyEvent.VK_CONTROL;
// case kVK_Function: return KeyEvent.VK_F;
case kVK_F17: return KeyEvent.VK_F17;
- // case kVK_VolumeUp:
+ // case kVK_VolumeUp:
// case kVK_VolumeDown:
// case kVK_Mute:
case kVK_F18: return KeyEvent.VK_F18;
@@ -205,85 +354,73 @@ public class MacKeyUtil {
case kVK_DownArrow: return KeyEvent.VK_DOWN;
case kVK_UpArrow: return KeyEvent.VK_UP;
}
-
- if (keyChar == '\r') {
- // Turn these into \n
- return KeyEvent.VK_ENTER;
- }
-
- if (keyChar >= NSUpArrowFunctionKey && keyChar <= NSModeSwitchFunctionKey) {
- switch (keyChar) {
- case NSUpArrowFunctionKey: return KeyEvent.VK_UP;
- case NSDownArrowFunctionKey: return KeyEvent.VK_DOWN;
- case NSLeftArrowFunctionKey: return KeyEvent.VK_LEFT;
- case NSRightArrowFunctionKey: return KeyEvent.VK_RIGHT;
- case NSF1FunctionKey: return KeyEvent.VK_F1;
- case NSF2FunctionKey: return KeyEvent.VK_F2;
- case NSF3FunctionKey: return KeyEvent.VK_F3;
- case NSF4FunctionKey: return KeyEvent.VK_F4;
- case NSF5FunctionKey: return KeyEvent.VK_F5;
- case NSF6FunctionKey: return KeyEvent.VK_F6;
- case NSF7FunctionKey: return KeyEvent.VK_F7;
- case NSF8FunctionKey: return KeyEvent.VK_F8;
- case NSF9FunctionKey: return KeyEvent.VK_F9;
- case NSF10FunctionKey: return KeyEvent.VK_F10;
- case NSF11FunctionKey: return KeyEvent.VK_F11;
- case NSF12FunctionKey: return KeyEvent.VK_F12;
- case NSF13FunctionKey: return KeyEvent.VK_F13;
- case NSF14FunctionKey: return KeyEvent.VK_F14;
- case NSF15FunctionKey: return KeyEvent.VK_F15;
- case NSF16FunctionKey: return KeyEvent.VK_F16;
- case NSF17FunctionKey: return KeyEvent.VK_F17;
- case NSF18FunctionKey: return KeyEvent.VK_F18;
- case NSF19FunctionKey: return KeyEvent.VK_F19;
- case NSF20FunctionKey: return KeyEvent.VK_F20;
- case NSF21FunctionKey: return KeyEvent.VK_F21;
- case NSF22FunctionKey: return KeyEvent.VK_F22;
- case NSF23FunctionKey: return KeyEvent.VK_F23;
- case NSF24FunctionKey: return KeyEvent.VK_F24;
- case NSInsertFunctionKey: return KeyEvent.VK_INSERT;
- case NSDeleteFunctionKey: return KeyEvent.VK_DELETE;
- case NSHomeFunctionKey: return KeyEvent.VK_HOME;
- case NSBeginFunctionKey: return KeyEvent.VK_BEGIN;
- case NSEndFunctionKey: return KeyEvent.VK_END;
- case NSPageUpFunctionKey: return KeyEvent.VK_PAGE_UP;
- case NSPageDownFunctionKey: return KeyEvent.VK_PAGE_DOWN;
- case NSPrintScreenFunctionKey: return KeyEvent.VK_PRINTSCREEN;
- case NSScrollLockFunctionKey: return KeyEvent.VK_SCROLL_LOCK;
- case NSPauseFunctionKey: return KeyEvent.VK_PAUSE;
- // Not handled:
- // NSSysReqFunctionKey
- // NSBreakFunctionKey
- // NSResetFunctionKey
- case NSStopFunctionKey: return KeyEvent.VK_STOP;
- // Not handled:
- // NSMenuFunctionKey
- // NSUserFunctionKey
- // NSSystemFunctionKey
- // NSPrintFunctionKey
- // NSClearLineFunctionKey
- // NSClearDisplayFunctionKey
- // NSInsertLineFunctionKey
- // NSDeleteLineFunctionKey
- // NSInsertCharFunctionKey
- // NSDeleteCharFunctionKey
- // NSPrevFunctionKey
- // NSNextFunctionKey
- // NSSelectFunctionKey
- // NSExecuteFunctionKey
- // NSUndoFunctionKey
- // NSRedoFunctionKey
- // NSFindFunctionKey
- // NSHelpFunctionKey
- // NSModeSwitchFunctionKey
- default: break;
- }
- }
- if ('a' <= keyChar && keyChar <= 'z') {
- return KeyEvent.VK_A + ( keyChar - 'a' ) ;
+ switch (keyChar) {
+ case NSUpArrowFunctionKey: return KeyEvent.VK_UP;
+ case NSDownArrowFunctionKey: return KeyEvent.VK_DOWN;
+ case NSLeftArrowFunctionKey: return KeyEvent.VK_LEFT;
+ case NSRightArrowFunctionKey: return KeyEvent.VK_RIGHT;
+ case NSF1FunctionKey: return KeyEvent.VK_F1;
+ case NSF2FunctionKey: return KeyEvent.VK_F2;
+ case NSF3FunctionKey: return KeyEvent.VK_F3;
+ case NSF4FunctionKey: return KeyEvent.VK_F4;
+ case NSF5FunctionKey: return KeyEvent.VK_F5;
+ case NSF6FunctionKey: return KeyEvent.VK_F6;
+ case NSF7FunctionKey: return KeyEvent.VK_F7;
+ case NSF8FunctionKey: return KeyEvent.VK_F8;
+ case NSF9FunctionKey: return KeyEvent.VK_F9;
+ case NSF10FunctionKey: return KeyEvent.VK_F10;
+ case NSF11FunctionKey: return KeyEvent.VK_F11;
+ case NSF12FunctionKey: return KeyEvent.VK_F12;
+ case NSF13FunctionKey: return KeyEvent.VK_F13;
+ case NSF14FunctionKey: return KeyEvent.VK_F14;
+ case NSF15FunctionKey: return KeyEvent.VK_F15;
+ case NSF16FunctionKey: return KeyEvent.VK_F16;
+ case NSF17FunctionKey: return KeyEvent.VK_F17;
+ case NSF18FunctionKey: return KeyEvent.VK_F18;
+ case NSF19FunctionKey: return KeyEvent.VK_F19;
+ case NSF20FunctionKey: return KeyEvent.VK_F20;
+ case NSF21FunctionKey: return KeyEvent.VK_F21;
+ case NSF22FunctionKey: return KeyEvent.VK_F22;
+ case NSF23FunctionKey: return KeyEvent.VK_F23;
+ case NSF24FunctionKey: return KeyEvent.VK_F24;
+ case NSInsertFunctionKey: return KeyEvent.VK_INSERT;
+ case NSDeleteFunctionKey: return KeyEvent.VK_DELETE;
+ case NSHomeFunctionKey: return KeyEvent.VK_HOME;
+ case NSBeginFunctionKey: return KeyEvent.VK_BEGIN;
+ case NSEndFunctionKey: return KeyEvent.VK_END;
+ case NSPageUpFunctionKey: return KeyEvent.VK_PAGE_UP;
+ case NSPageDownFunctionKey: return KeyEvent.VK_PAGE_DOWN;
+ case NSPrintScreenFunctionKey: return KeyEvent.VK_PRINTSCREEN;
+ case NSScrollLockFunctionKey: return KeyEvent.VK_SCROLL_LOCK;
+ case NSPauseFunctionKey: return KeyEvent.VK_PAUSE;
+ // Not handled:
+ // NSSysReqFunctionKey
+ // NSBreakFunctionKey
+ // NSResetFunctionKey
+ case NSStopFunctionKey: return KeyEvent.VK_STOP;
+ // Not handled:
+ // NSMenuFunctionKey
+ // NSUserFunctionKey
+ // NSSystemFunctionKey
+ // NSPrintFunctionKey
+ // NSClearLineFunctionKey
+ // NSClearDisplayFunctionKey
+ // NSInsertLineFunctionKey
+ // NSDeleteLineFunctionKey
+ // NSInsertCharFunctionKey
+ // NSDeleteCharFunctionKey
+ // NSPrevFunctionKey
+ // NSNextFunctionKey
+ // NSSelectFunctionKey
+ // NSExecuteFunctionKey
+ // NSUndoFunctionKey
+ // NSRedoFunctionKey
+ // NSFindFunctionKey
+ // NSHelpFunctionKey
+ // NSModeSwitchFunctionKey
}
- return (int) keyChar; // let's hope for the best (compatibility of keyChar/keyCode's)
- }
+ return (short) keyChar; // let's hope for the best (compatibility of keyChar/keyCode's)
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
index 24e60ba0a..5f458e2c9 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2011 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,115 +29,179 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.macosx;
-import java.util.List;
-
import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+import jogamp.nativewindow.macosx.OSXUtil;
+import jogamp.newt.MonitorModeProps;
import jogamp.newt.ScreenImpl;
-import com.jogamp.common.util.IntObjectHashMap;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.opengl.math.FloatUtil;
public class ScreenDriver extends ScreenImpl {
-
- // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call)
- private static IntObjectHashMap/*<int, DimensionImmutable>*/ scrnIdx2Dimension;
-
+
static {
DisplayDriver.initSingleton();
- scrnIdx2Dimension = new IntObjectHashMap();
- scrnIdx2Dimension.setKeyNotFoundValue(null);
}
public ScreenDriver() {
}
+ @Override
protected void createNativeImpl() {
aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
}
+ @Override
protected void closeNativeImpl() { }
- private static native int getWidthImpl0(int scrn_idx);
- private static native int getHeightImpl0(int scrn_idx);
-
- private int[] getScreenModeIdx(int idx) {
- // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call)
- DimensionImmutable dim = (DimensionImmutable) scrnIdx2Dimension.get(screen_idx);
- if(null == dim) {
- int[] res = getScreenSizeMM0(screen_idx);
- if(null == res || 0 == res.length) {
- return null;
- }
- dim = new Dimension(res[0], res[1]);
- scrnIdx2Dimension.put(screen_idx, dim);
+ private MonitorMode getMonitorModeImpl(final MonitorModeProps.Cache cache, final int crt_idx, final int mode_idx) {
+ final int[] modeProps = getMonitorMode0(crt_idx, mode_idx);
+ final MonitorMode res;
+ if (null == modeProps || 0 >= modeProps.length) {
+ res = null;
+ } else {
+ res = MonitorModeProps.streamInMonitorMode(null, cache, modeProps, 0);
}
+ return res;
+ }
- int[] modeProps = getScreenMode0(screen_idx, idx, dim.getWidth(), dim.getHeight());
- if (null == modeProps || 0 == modeProps.length) {
- return null;
- }
- if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) {
- throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length);
+ private class CrtProps {
+ CrtProps() {
+ count = getMonitorCount0();
+ pixelScaleArray = new int[count];
+ propsOrigArray = new int[count][];
+ propsFixedArray = new int[count][];
+
+ //
+ // Gather whole topology of monitors (NSScreens)
+ //
+ for(int crtIdx=0; crtIdx<count; crtIdx++) {
+ final float pixelScaleRaw = (float) OSXUtil.GetPixelScale(crtIdx);
+ pixelScaleArray[crtIdx] = FloatUtil.isZero(pixelScaleRaw, FloatUtil.EPSILON) ? 1 : (int)pixelScaleRaw;
+ propsOrigArray[crtIdx] = getMonitorProps0(crtIdx);
+ if ( null == propsOrigArray[crtIdx] ) {
+ throw new InternalError("Could not gather device props "+crtIdx+"/"+count);
+ }
+ // copy orig -> fixed
+ final int propsLen = propsOrigArray[crtIdx].length;
+ propsFixedArray[crtIdx] = new int[propsLen];
+ System.arraycopy(propsOrigArray[crtIdx], 0, propsFixedArray[crtIdx], 0, propsLen);
+ }
+
+ //
+ // Fix scaled viewport w/ pixelScale of each monitorProps,
+ // i.e. size by its own pixelScale and x/y offset by querying it's neighbors.
+ //
+ for(int crtIdx=0; crtIdx<count; crtIdx++) {
+ final int[] thisMonitorProps = propsFixedArray[crtIdx];
+ final int x = thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+0];
+ final int y = thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+1];
+ final int thisPixelScale = pixelScaleArray[crtIdx];
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+2] *= thisPixelScale; // fix width
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+3] *= thisPixelScale; // fix height
+ if( 0 != x ) {
+ // find matching viewport width for x-offset to apply it's pixelSize
+ for(int i=0; i<count; i++) {
+ if( i != crtIdx && x == propsOrigArray[i][MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+2] ) {
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+0] *= pixelScaleArray[i];
+ break;
+ }
+ }
+ }
+ if( 0 != y ) {
+ // find matching viewport height for y-offset to apply it's pixelSize
+ for(int i=0; i<count; i++) {
+ if( i != crtIdx && y == propsOrigArray[i][MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+3] ) {
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+1] *= pixelScaleArray[i];
+ break;
+ }
+ }
+ }
+ }
}
- return modeProps;
+ final int count;
+ final int[] pixelScaleArray;
+ final int[][] propsOrigArray;
+ final int[][] propsFixedArray;
}
- private int nativeModeIdx;
-
- protected int[] getScreenModeFirstImpl() {
- nativeModeIdx = 0;
- return getScreenModeNextImpl();
- }
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(final MonitorModeProps.Cache cache) {
+ final CrtProps crtProps = new CrtProps();
- protected int[] getScreenModeNextImpl() {
- int[] modeProps = getScreenModeIdx(nativeModeIdx);
- if (null != modeProps && 0 < modeProps.length) {
- nativeModeIdx++;
- return modeProps;
+ //
+ // Collect all monitorModes for all monitorDevices
+ //
+ for(int crtIdx=0; crtIdx<crtProps.count; crtIdx++) {
+ final ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
+ int modeIdx = 0;
+ {
+ // Get all supported modes for this monitorDevice
+ MonitorMode mode;
+ while( true ) {
+ mode = getMonitorModeImpl(cache, crtIdx, modeIdx);
+ if( null != mode ) {
+ if( mode.getSurfaceSize().getBitsPerPixel() >= 24 ) { // drop otherwise
+ supportedModes.getOrAdd(mode);
+ }
+ modeIdx++; // next mode on same monitor
+ } else {
+ break; // done with modes on this monitor
+ }
+ }
+ }
+ if( 0 >= modeIdx ) {
+ throw new InternalError("Could not gather single mode of device "+crtIdx+"/"+crtProps.count);
+ }
+ final MonitorMode currentMode = getMonitorModeImpl(cache, crtIdx, -1);
+ if ( null == currentMode ) {
+ throw new InternalError("Could not gather current mode of device "+crtIdx+"/"+crtProps.count+", but gathered "+modeIdx+" modes");
+ }
+ // merge monitor-props + supported modes
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, crtProps.propsFixedArray[crtIdx], 0);
}
- return null;
}
- protected ScreenMode getCurrentScreenModeImpl() {
- int[] modeProps = getScreenModeIdx(-1);
- if (null != modeProps && 0 < modeProps.length) {
- return ScreenModeUtil.streamIn(modeProps, 0);
+ @Override
+ protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final Rectangle viewportPU, final Rectangle viewportWU) {
+ final CrtProps crtProps = new CrtProps();
+ final int crtIdx = monitor.getId();
+ if( 0 > crtIdx || crtIdx >= crtProps.count ) {
+ throw new IndexOutOfBoundsException("monitor id "+crtIdx+" not withon [0.."+(crtProps.count-1)+"]");
}
- return null;
+ final int[] fixedMonitorProps = crtProps.propsFixedArray[crtIdx];
+ int offset = MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT;
+ viewportPU.set(fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++]);
+ viewportWU.set(fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++]);
+ return true;
}
-
- protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) {
- final List<ScreenMode> screenModes = this.getScreenModesOrig();
- final int screenModeIdx = screenModes.indexOf(screenMode);
- if(0>screenModeIdx) {
- throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode);
- }
- final int nativeModeIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx);
- return setScreenMode0(screen_idx, nativeModeIdx);
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return getMonitorModeImpl(null, monitor.getId(), -1);
}
-
- protected int validateScreenIndex(int idx) {
- return idx;
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return setMonitorMode0(monitor.getId(), mode.getId(), mode.getRotation());
}
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(getWidthImpl0(screen_idx));
- virtualSize.setHeight(getHeightImpl0(screen_idx));
+
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ return 0; // big-desktop w/ multiple monitor attached, only one screen available
}
- private native int[] getScreenSizeMM0(int screen_idx);
- private native int[] getScreenMode0(int screen_index, int mode_index, int widthMM, int heightMM);
- private native boolean setScreenMode0(int screen_index, int mode_idx);
+ private native int getMonitorCount0();
+ private native int[] getMonitorProps0(int crt_idx);
+ private native int[] getMonitorMode0(int crt_index, int mode_idx);
+ private native boolean setMonitorMode0(int crt_index, int nativeId, int rot);
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
index 4eeafb244..c0f7d3859 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.macosx;
@@ -39,28 +39,146 @@ import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.MutableSurface;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
-import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
import javax.media.nativewindow.util.PointImmutable;
+import jogamp.nativewindow.SurfaceScaleUtils;
+import jogamp.nativewindow.macosx.OSXUtil;
+import jogamp.newt.PointerIconImpl;
+import jogamp.newt.ScreenImpl;
import jogamp.newt.WindowImpl;
import jogamp.newt.driver.DriverClearFocus;
import jogamp.newt.driver.DriverUpdatePosition;
import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.opengl.math.FloatUtil;
public class WindowDriver extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition {
-
+
static {
DisplayDriver.initSingleton();
}
public WindowDriver() {
}
-
+
+ private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final float newPixelScaleRaw, final float nativePixelScaleRaw) {
+ final int[] newPixelScale = new int[2];
+ {
+ final int _newPixelScale = FloatUtil.isZero(newPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : (int) newPixelScaleRaw;
+ newPixelScale[0]= _newPixelScale;
+ newPixelScale[1]= _newPixelScale;
+ final int _nativePixelScale = FloatUtil.isZero(nativePixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : (int) nativePixelScaleRaw;
+ nativePixelScale[0]= _nativePixelScale;
+ nativePixelScale[1]= _nativePixelScale;
+ }
+
+ if( SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, newPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) {
+ if( sendEvent ) {
+ super.sizeChanged(defer, getWidth(), getHeight(), true);
+ } else {
+ defineSize(getWidth(), getHeight());
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean updatePixelScaleByScreenIdx(final boolean sendEvent) {
+ final float nativePixelScaleRaw = (float) OSXUtil.GetPixelScale(getScreen().getIndex());
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+", "+nativePixelScaleRaw+" (native)");
+ }
+ return updatePixelScale(sendEvent, true /* defer */, nativePixelScaleRaw, nativePixelScaleRaw);
+ }
+
+ private boolean updatePixelScaleByWindowHandle(final boolean sendEvent) {
+ final long handle = getWindowHandle();
+ if( 0 != handle ) {
+ final float nativePixelScaleRaw = (float)OSXUtil.GetPixelScale(handle);
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+", "+nativePixelScaleRaw+" (native)");
+ }
+ return updatePixelScale(sendEvent, true /* defer */, nativePixelScaleRaw, nativePixelScaleRaw);
+ } else {
+ return false;
+ }
+ }
+
+ /** Called from native code */
+ protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw, final float nativePixelScaleRaw) {
+ final long handle = getWindowHandle();
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (raw), "+nativePixelScaleRaw+" (native), drop "+(0==handle));
+ }
+ if( 0 != handle ) {
+ updatePixelScale(true /* sendEvent*/, defer, newPixelScaleRaw, nativePixelScaleRaw);
+ }
+ }
+
+ @Override
+ protected final void instantiationFinished() {
+ updatePixelScaleByScreenIdx(false /* sendEvent*/);
+ }
+
+ @Override
+ protected void setScreen(final ScreenImpl newScreen) { // never null !
+ super.setScreen(newScreen);
+ updatePixelScaleByScreenIdx(false /* sendEvent*/); // caller (reparent, ..) will send reshape event
+ }
+
+ @Override
+ protected void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ updatePixelScaleByWindowHandle(false /* sendEvent*/); // send reshape event itself
+ }
+
+ @Override
+ public final void setSurfaceScale(final int[] pixelScale) {
+ SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null);
+
+ final int[] resPixelScale;
+ if( isNativeValid() ) {
+ if( isOffscreenInstance ) {
+ final NativeWindow pWin = getParent();
+ if( pWin instanceof ScalableSurface ) {
+ final ScalableSurface sSurf = (ScalableSurface)pWin;
+ sSurf.setSurfaceScale(reqPixelScale);
+ final int[] pPixelScale = sSurf.getCurrentSurfaceScale(new int[2]);
+ sSurf.getNativeSurfaceScale(nativePixelScale);
+ updatePixelScale(true /* sendEvent */, true /* defer */, pPixelScale[0], nativePixelScale[0]); // HiDPI: uniformPixelScale
+ } else {
+ // just notify updated pixelScale if offscreen
+ SurfaceScaleUtils.replaceAutoMaxWithPlatformMax(reqPixelScale);
+ updatePixelScale(true /* sendEvent */, true /* defer */, reqPixelScale[0], nativePixelScale[0]); // HiDPI: uniformPixelScale
+ }
+ } else {
+ // set pixelScale in native code, will issue an update PixelScale
+ OSXUtil.RunOnMainThread(true, false, new Runnable() {
+ @Override
+ public void run() {
+ setPixelScale0(getWindowHandle(), surfaceHandle, reqPixelScale[0]); // HiDPI: uniformPixelScale
+ }
+ } );
+ }
+ resPixelScale = hasPixelScale;
+ } else {
+ hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ resPixelScale = reqPixelScale;
+ }
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.setPixelScale: "+pixelScale[0]+"x"+pixelScale[1]+" (req) -> "+
+ reqPixelScale[0]+"x"+reqPixelScale[1]+" (validated) -> "+
+ resPixelScale[0]+"x"+resPixelScale[1]+" (result) - realized "+isNativeValid());
+ }
+ }
+
@Override
protected void createNativeImpl() {
final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
@@ -69,7 +187,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
setGraphicsConfiguration(cfg);
- reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true));
+ reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true));
if (0 == getWindowHandle()) {
throw new NativeWindowException("Error creating window");
}
@@ -79,373 +197,532 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
protected void closeNativeImpl() {
try {
if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); }
- final long handle = getWindowHandle();
+ final long handle = getWindowHandle();
+ visibleChanged(true, false);
setWindowHandle(0);
surfaceHandle = 0;
sscSurfaceHandle = 0;
- isOffscreenInstance = false;
+ isOffscreenInstance = false;
if (0 != handle) {
- close0(handle);
+ OSXUtil.RunOnMainThread(false, true /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ close0( handle );
+ } });
}
- } catch (Throwable t) {
- if(DEBUG_IMPLEMENTATION) {
- Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t);
+ } catch (final Throwable t) {
+ if(DEBUG_IMPLEMENTATION) {
+ final Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t);
e.printStackTrace();
}
}
}
-
+
@Override
protected int lockSurfaceImpl() {
- if(!isOffscreenInstance) {
- return lockSurface0(getWindowHandle()) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
+ /**
+ * if( isOffscreenInstance ) {
+ * return LOCK_SUCCESS;
+ * }
+ */
+ final long w = getWindowHandle();
+ final long v = surfaceHandle;
+ if( 0 != v && 0 != w ) {
+ return lockSurface0(w, v) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
}
- return LOCK_SUCCESS;
+ return LOCK_SURFACE_NOT_READY;
}
@Override
protected void unlockSurfaceImpl() {
- if(!isOffscreenInstance) {
- final long h = getWindowHandle();
- if(0 != h) {
- unlockSurface0(h);
+ /**
+ * if( isOffscreenInstance ) {
+ * return;
+ * }
+ */
+ final long w = getWindowHandle();
+ final long v = surfaceHandle;
+ if(0 != w && 0 != v) {
+ if( !unlockSurface0(w, v) ) {
+ throw new NativeWindowException("Failed to unlock surface, probably not locked!");
}
}
}
-
+
@Override
public final long getSurfaceHandle() {
return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle;
}
@Override
- public void setSurfaceHandle(long surfaceHandle) {
+ public void setSurfaceHandle(final long surfaceHandle) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
}
sscSurfaceHandle = surfaceHandle;
if (isNativeValid()) {
if (0 != sscSurfaceHandle) {
- orderOut0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
- } /** this is done by recreation!
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+ } } );
+ } /** this is done by recreation!
else if (isVisible()){
- orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ public void run() {
+ orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+ } } );
} */
- }
+ }
}
@Override
protected void setTitleImpl(final String title) {
- setTitle0(getWindowHandle(), title);
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setTitle0(getWindowHandle(), title);
+ } } );
}
- protected void requestFocusImpl(boolean force) {
- if(!isOffscreenInstance) {
- requestFocus0(getWindowHandle(), force);
+ @Override
+ protected void requestFocusImpl(final boolean force) {
+ final boolean _isFullscreen = isFullscreen();
+ final boolean _isOffscreenInstance = isOffscreenInstance;
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: requestFocusImpl(), isOffscreenInstance "+_isOffscreenInstance+", isFullscreen "+_isFullscreen);
+ }
+ if(!_isOffscreenInstance) {
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ requestFocus0(getWindowHandle(), force);
+ if(_isFullscreen) {
+ // 'NewtMacWindow::windowDidBecomeKey()' is not always called in fullscreen-mode!
+ focusChanged(false, true);
+ }
+ } } );
} else {
focusChanged(false, true);
}
}
-
+
+ @Override
public final void clearFocus() {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("MacWindow: clearFocus() - requestFocusParent, isOffscreenInstance "+isOffscreenInstance);
+ System.err.println("MacWindow: clearFocus(), isOffscreenInstance "+isOffscreenInstance);
}
if(!isOffscreenInstance) {
- resignFocus0(getWindowHandle());
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ resignFocus0(getWindowHandle());
+ } } );
} else {
focusChanged(false, false);
}
}
-
- public void updatePosition() {
- final Point pS = getTopLevelLocationOnScreen(getX(), getY());
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("MacWindow: updatePosition() - isOffscreenInstance "+isOffscreenInstance+", new abs pos: pS "+pS);
+
+ private boolean useParent(final NativeWindow parent) { return null != parent && 0 != parent.getWindowHandle(); }
+
+ @Override
+ public void updatePosition(final int x, final int y) {
+ final long handle = getWindowHandle();
+ if( 0 != handle && !isOffscreenInstance ) {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ final int pX=parent.getX(), pY=parent.getY();
+ final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: updatePosition() parent["+useParent+" "+pX+"/"+pY+"] "+x+"/"+y+" -> "+x+"/"+y+" rel-client-pos, "+p0S+" screen-client-pos");
+ }
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPoint0(handle, p0S.getX(), p0S.getY(), isVisible());
+ } } );
+ // no native event (fullscreen, some reparenting)
+ positionChanged(true, x, y);
+ }
+ }
+
+ @Override
+ protected void sizeChanged(final boolean defer, final int newWidth, final int newHeight, final boolean force) {
+ final long handle = getWindowHandle();
+ if( 0 != handle && !isOffscreenInstance ) {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ if( useParent && ( getWidth() != newWidth || getHeight() != newHeight ) ) {
+ final int x=getX(), y=getY();
+ final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" -> "+p0S+" screen-client-pos");
+ }
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
+ } } );
+ }
}
- if( !isOffscreenInstance ) {
- setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY());
- } // else no offscreen position
- // no native event (fullscreen, some reparenting)
- super.positionChanged(true, getX(), getY());
+ super.sizeChanged(defer, newWidth, newHeight, force);
}
-
-
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+
+ @Override
+ protected boolean reconfigureWindowImpl(int x, int y, final int width, final int height, final int flags) {
final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent());
isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance;
- final PointImmutable pS = isOffscreenInstance ? new Point(0, 0) : getTopLevelLocationOnScreen(x, y);
-
+ final PointImmutable pClientLevelOnSreen;
+ if( isOffscreenInstance ) {
+ x = 0; y = 0;
+ pClientLevelOnSreen = new Point(0, 0);
+ } else {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ if( useParent ) {
+ pClientLevelOnSreen = getLocationOnScreenImpl(x, y, parent, useParent);
+ } else {
+ pClientLevelOnSreen = new Point(x, y);
+ }
+ }
+
+ final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags);
+ final boolean hasFocus = hasFocus();
+
if(DEBUG_IMPLEMENTATION) {
final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration();
final NativeWindow pWin = getParent();
final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null;
- System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+
+ System.err.println("MacWindow reconfig.0: "+x+"/"+y+" -> clientPos "+pClientLevelOnSreen+" - "+width+"x"+height+
",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+
",\n\t this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+
",\n\t parent-chosenCaps "+(null != pWinCfg ? pWinCfg.getChosenCapabilities() : null)+
", isOffscreenInstance(sscSurfaceHandle "+toHexString(sscSurfaceHandle)+
", ioi: "+_isOffscreenInstance+
") -> "+isOffscreenInstance+
- "\n\t, "+getReconfigureFlagsAsString(null, flags));
+ "\n\t, "+getReconfigureFlagsAsString(null, flags)+", setVisible "+setVisible+", hasFocus "+hasFocus);
+ // Thread.dumpStack();
}
-
- if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) {
+
+ if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && !setVisible ) {
if ( !isOffscreenInstance ) {
- orderOut0(getWindowHandle());
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ orderOut0(getWindowHandle());
+ visibleChanged(true, false);
+ } } );
+ } else {
+ visibleChanged(true, false);
}
- // no native event ..
- visibleChanged(true, false);
}
- if( 0 == getWindowHandle() && 0 != ( FLAG_IS_VISIBLE & flags) ||
+ if( 0 == getWindowHandle() && setVisible ||
0 != ( FLAG_CHANGE_DECORATION & flags) ||
0 != ( FLAG_CHANGE_PARENTING & flags) ||
0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
if(isOffscreenInstance) {
- createWindow(true, 0 != getWindowHandle(), pS, 64, 64, false);
+ createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false, setVisible, false);
} else {
- createWindow(false, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags));
+ createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height,
+ 0 != ( FLAG_IS_FULLSCREEN & flags), setVisible, 0 != ( FLAG_IS_ALWAYSONTOP & flags));
}
- if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; }
- }
- if(x>=0 && y>=0) {
- if( !isOffscreenInstance ) {
- setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY());
- } // else no offscreen position
- // no native event (fullscreen, some reparenting)
- super.positionChanged(true, x, y);
- }
- if(width>0 && height>0) {
- if( !isOffscreenInstance ) {
- setContentSize0(getWindowHandle(), width, height);
- } // else offscreen size is realized via recreation
// no native event (fullscreen, some reparenting)
- sizeChanged(true, width, height, false); // incl. validation (incl. repositioning)
- }
- if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) {
- if( !isOffscreenInstance ) {
- orderFront0(getWindowHandle());
+ positionChanged(false, x, y);
+ updatePixelScaleByWindowHandle(false /* sendEvent */);
+ super.sizeChanged(false, width, height, true);
+ visibleChanged(false, setVisible);
+ if( hasFocus ) {
+ requestFocusImpl(true);
+ }
+ } else {
+ if( width>0 && height>0 ) {
+ if( !isOffscreenInstance ) {
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height, setVisible);
+ } } );
+ } // else offscreen size is realized via recreation
+ // no native event (fullscreen, some reparenting)
+ positionChanged(true, x, y);
+ super.sizeChanged(true, width, height, false);
+ }
+ if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && setVisible ) {
+ if( !isOffscreenInstance ) {
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ orderFront0(getWindowHandle());
+ visibleChanged(true, true);
+ } } );
+ } else {
+ visibleChanged(true, true);
+ }
+ }
+ if( !isOffscreenInstance ) {
+ setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
}
- // no native event ..
- visibleChanged(true, true);
- }
- if( !isOffscreenInstance ) {
- setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
+ }
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow reconfig.X: clientPos "+pClientLevelOnSreen+", "+width+"x"+height+" -> clientPos "+getLocationOnScreenImpl(0, 0)+", insets: "+getInsets());
}
return true;
}
- protected Point getLocationOnScreenImpl(int x, int y) {
- Point p = new Point(x, y);
- // min val is 0
- p.setX(Math.max(p.getX(), 0));
- p.setY(Math.max(p.getY(), 0));
-
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
final NativeWindow parent = getParent();
- if( null != parent && 0 != parent.getWindowHandle() ) {
- p.translate(parent.getLocationOnScreen(null));
- }
- return p;
+ final boolean useParent = useParent(parent);
+ return getLocationOnScreenImpl(x, y, parent, useParent);
}
-
- private Point getTopLevelLocationOnScreen(int x, int y) {
- final InsetsImmutable _insets = getInsets(); // zero if undecorated
- // client position -> top-level window position
- x -= _insets.getLeftWidth() ;
- y -= _insets.getTopHeight() ;
- return getLocationOnScreenImpl(x, y);
- }
-
- protected void updateInsetsImpl(Insets insets) {
- // nop - using event driven insetsChange(..)
- }
-
- @Override
- protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
- if(getWidth() != newWidth || getHeight() != newHeight) {
- final Point p0S = getTopLevelLocationOnScreen(getX(), getY());
- setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), p0S.getX(), p0S.getY());
+
+ private Point getLocationOnScreenImpl(final int x, final int y, final NativeWindow parent, final boolean useParent) {
+ if( !useParent && !isOffscreenInstance && 0 != surfaceHandle) {
+ return OSXUtil.GetLocationOnScreen(surfaceHandle, x, y);
}
- super.sizeChanged(defer, newWidth, newHeight, force);
+
+ final Point p = new Point(x, y);
+ if( useParent ) {
+ p.translate( parent.getLocationOnScreen(null) );
+ }
+ return p;
}
-
+
@Override
- protected void positionChanged(boolean defer, int newX, int newY) {
+ protected void updateInsetsImpl(final Insets insets) {
+ // nop - using event driven insetsChange(..)
+ }
+
+ /** Callback for native screen position change event of the client area. */
+ protected void screenPositionChanged(final boolean defer, final int newX, final int newY) {
// passed coordinates are in screen position of the client area
if(getWindowHandle()!=0) {
- // screen position -> window position
- Point absPos = new Point(newX, newY);
final NativeWindow parent = getParent();
- if(null != parent) {
- absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) );
+ if( null == parent || isOffscreenInstance ) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
+ }
+ positionChanged(defer, newX, newY);
+ } else {
+ // screen position -> rel child window position
+ final Point absPos = new Point(newX, newY);
+ final Point parentOnScreen = parent.getLocationOnScreen(null);
+ absPos.translate( parentOnScreen.scale(-1, -1) );
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos);
+ }
+ positionChanged(defer, absPos.getX(), absPos.getY());
}
- super.positionChanged(defer, absPos.getX(), absPos.getY());
+ } else if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
}
}
-
+
+ @Override
+ protected void setPointerIconImpl(final PointerIconImpl pi) {
+ if( !isOffscreenInstance ) {
+ final long piHandle = null != pi ? pi.validatedHandle() : 0;
+ OSXUtil.RunOnMainThread(true, false, new Runnable() { // waitUntildone due to PointerIconImpl's Lifecycle !
+ @Override
+ public void run() {
+ setPointerIcon0(getWindowHandle(), piHandle);
+ } } );
+ }
+ }
+
@Override
protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
- if( !isOffscreenInstance ) {
- return setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible);
- } // else may need offscreen solution ? FIXME
+ if( !isOffscreenInstance ) {
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible);
+ } } );
+ return true;
+ }
return false;
}
@Override
protected boolean confinePointerImpl(final boolean confine) {
- if( !isOffscreenInstance ) {
- return confinePointer0(getWindowHandle(), confine);
+ if( !isOffscreenInstance ) {
+ confinePointer0(getWindowHandle(), confine);
+ return true;
} // else may need offscreen solution ? FIXME
return false;
}
-
+
@Override
protected void warpPointerImpl(final int x, final int y) {
- if( !isOffscreenInstance ) {
- warpPointer0(getWindowHandle(), x, y);
+ if( !isOffscreenInstance ) {
+ warpPointer0(getWindowHandle(), x / getPixelScaleX(), y / getPixelScaleY());
} // else may need offscreen solution ? FIXME
}
-
+
@Override
- public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
- // Note that we send the key char for the key code on this
- // platform -- we do not get any useful key codes out of the system
- final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar);
- final boolean valid = validateKeyEvent(eventType, modifiers, keyCode);
- if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid);
- if(valid) {
- if(pressedKeyBalance > 1) {
- // Auto-Repeat: OSX delivers only PRESSED
- // inject auto-repeat RELEASE and TYPED keys _before_
- pressedKeyBalance--;
- modifiers |= InputEvent.AUTOREPEAT_MASK;
- super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, (char)-1); // RELEASED
- super.sendKeyEvent(KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, keyChar); // TYPED
- }
- // only deliver keyChar on key Typed events, harmonizing platform behavior
- keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1;
- super.sendKeyEvent(eventType, modifiers, keyCode2, keyChar);
- }
- }
-
+ protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
+ super.doMouseEvent(enqueue, wait, eventType, modifiers, x * getPixelScaleX(), y * getPixelScaleY(), button, rotationXYZ, rotationScale);
+ }
+
@Override
- public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
+ public final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+ }
+
+ @Override
+ public final void enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short _keyCode, final short _keySym, final char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+ }
+
+ protected final void enqueueKeyEvent(final boolean wait, final short eventType, int modifiers, final short _keyCode, final char keyChar, final char keySymChar) {
// Note that we send the key char for the key code on this
// platform -- we do not get any useful key codes out of the system
- final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar);
- final boolean valid = validateKeyEvent(eventType, modifiers, keyCode);
- if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid);
- if(valid) {
- if(pressedKeyBalance > 1) {
- // Auto-Repeat: OSX delivers only PRESSED
- // inject auto-repeat RELEASE and TYPED keys _before_
- pressedKeyBalance--;
- modifiers |= InputEvent.AUTOREPEAT_MASK;
- super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, (char)-1); // RELEASED
- super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, keyChar); // TYPED
- }
- // only deliver keyChar on key Typed events, harmonizing platform behavior
- keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1;
- super.enqueueKeyEvent(wait, eventType, modifiers, keyCode2, keyChar);
- }
- }
-
- private int keyDownModifiers = 0;
- private int keyDownCode = 0;
- private int pressedKeyBalance = 0;
-
- private boolean validateKeyEvent(int eventType, int modifiers, int keyCode) {
+ final short keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar);
+ final short keySym;
+ {
+ final short _keySym = KeyEvent.NULL_CHAR != keySymChar ? KeyEvent.utf16ToVKey(keySymChar) : KeyEvent.VK_UNDEFINED;
+ keySym = KeyEvent.VK_UNDEFINED != _keySym ? _keySym : keyCode;
+ }
+ /**
+ {
+ final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
+ System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+
+ ", keyCode 0x"+Integer.toHexString(_keyCode)+" -> 0x"+Integer.toHexString(keyCode)+
+ ", keySymChar '"+keySymChar+"', 0x"+Integer.toHexString(keySymChar)+" -> 0x"+Integer.toHexString(keySym)+
+ ", mods "+toHexString(modifiers)+
+ ", was: pressed "+isKeyPressed(keyCode)+", isModifierKeyCode "+isModifierKeyCode+
+ ", nativeValid "+isNativeValid()+", isOffscreen "+isOffscreenInstance);
+ } */
+
+ // OSX delivery order is PRESSED (t0), RELEASED (t1) and TYPED (t2) -> NEWT order: PRESSED (t0) and RELEASED (t1)
+ // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE key _before_ PRESSED
switch(eventType) {
- case KeyEvent.EVENT_KEY_PRESSED:
- pressedKeyBalance++;
- keyDownModifiers = modifiers;
- keyDownCode = keyCode;
- return true;
case KeyEvent.EVENT_KEY_RELEASED:
- pressedKeyBalance--;
- return keyDownModifiers == modifiers && keyDownCode == keyCode;
- case KeyEvent.EVENT_KEY_TYPED:
- final boolean matchKeyDown = keyDownModifiers == modifiers && keyDownCode == keyCode;
- keyDownModifiers = 0;
- keyDownCode = 0;
- return matchKeyDown;
- default:
- throw new NativeWindowException("Unexpected key event type " + eventType);
+ if( isKeyCodeTracked(keyCode) ) {
+ setKeyPressed(keyCode, false);
+ }
+ break;
+ case KeyEvent.EVENT_KEY_PRESSED:
+ if( isKeyCodeTracked(keyCode) ) {
+ if( setKeyPressed(keyCode, true) ) {
+ // key was already pressed
+ modifiers |= InputEvent.AUTOREPEAT_MASK;
+ super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED
+ }
+ }
+ break;
}
+ super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar);
}
-
//----------------------------------------------------------------------
// Internals only
- //
-
- private void createWindow(final boolean offscreenInstance, final boolean recreate,
- final PointImmutable pS, final int width, final int height,
- final boolean fullscreen) {
+ //
+
+ private void createWindow(final boolean offscreenInstance, final boolean recreate,
+ final PointImmutable pS, final int width, final int height,
+ final boolean fullscreen, final boolean visible, final boolean alwaysOnTop) {
+
+ final long parentWinHandle = getParentWindowHandle();
+ final long preWinHandle = getWindowHandle();
- if(0!=getWindowHandle() && !recreate) {
- return;
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+
+ ": offscreen "+offscreenInstance+", recreate "+recreate+
+ ", pS "+pS+", "+width+"x"+height+", fullscreen "+fullscreen+", visible "+visible+
+ ", alwaysOnTop "+alwaysOnTop+", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+
+ ", surfaceHandle "+toHexString(surfaceHandle));
+ // Thread.dumpStack();
}
try {
- if(0!=getWindowHandle()) {
- // save the view .. close the window
- surfaceHandle = changeContentView0(getParentWindowHandle(), getWindowHandle(), 0);
- if(recreate && 0==surfaceHandle) {
- throw new NativeWindowException("Internal Error - recreate, window but no view");
- }
- close0(getWindowHandle());
+ if( 0 != preWinHandle ) {
setWindowHandle(0);
+ if( 0 == surfaceHandle ) {
+ throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView");
+ }
+ OSXUtil.RunOnMainThread(false, false /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ changeContentView0(parentWinHandle, preWinHandle, 0);
+ close0( preWinHandle );
+ } });
} else {
- surfaceHandle = 0;
- }
- setWindowHandle(createWindow0(getParentWindowHandle(),
- pS.getX(), pS.getY(), width, height,
- (getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance),
- fullscreen,
- ((isUndecorated() || offscreenInstance) ?
- NSBorderlessWindowMask :
- NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask),
- NSBackingStoreBuffered,
- getScreen().getIndex(), surfaceHandle));
- if (getWindowHandle() == 0) {
- throw new NativeWindowException("Could create native window "+Thread.currentThread().getName()+" "+this);
+ if( 0 != surfaceHandle ) {
+ throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView");
+ }
+ surfaceHandle = createView0(pS.getX(), pS.getY(), width, height);
+ if( 0 == surfaceHandle ) {
+ throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this);
+ }
}
- surfaceHandle = contentView0(getWindowHandle());
- if( offscreenInstance ) {
- orderOut0(0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle());
- } else {
- setTitle0(getWindowHandle(), getTitle());
+
+ final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, fullscreen,
+ ( isUndecorated() || offscreenInstance ) ? NSBorderlessWindowMask :
+ NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask,
+ NSBackingStoreBuffered, surfaceHandle);
+ if ( newWin == 0 ) {
+ throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this);
}
- } catch (Exception ie) {
+ setWindowHandle( newWin );
+
+ final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance;
+ // Blocking initialization on main-thread!
+ OSXUtil.RunOnMainThread(true, false /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height, reqPixelScale[0] /* HiDPI uniformPixelScale */,
+ isOpaque, visible && !offscreenInstance, surfaceHandle);
+ if( offscreenInstance ) {
+ orderOut0(0!=parentWinHandle ? parentWinHandle : newWin);
+ } else {
+ setTitle0(newWin, getTitle());
+ setAlwaysOnTop0(getWindowHandle(), alwaysOnTop);
+ }
+ } });
+ } catch (final Exception ie) {
ie.printStackTrace();
}
}
-
+
protected static native boolean initIDs0();
- private native long createWindow0(long parentWindowHandle, int x, int y, int w, int h,
- boolean opaque, boolean fullscreen, int windowStyle,
- int backingStoreType,
- int screen_idx, long view);
- private native boolean lockSurface0(long window);
- private native void unlockSurface0(long window);
+ private native long createView0(int x, int y, int w, int h);
+ private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view);
+ /** Must be called on Main-Thread */
+ private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, float reqPixelScale,
+ boolean opaque, boolean visible, long view);
+ private native void setPixelScale0(long window, long view, float reqPixelScale);
+ private native boolean lockSurface0(long window, long view);
+ private native boolean unlockSurface0(long window, long view);
+ /** Must be called on Main-Thread */
private native void requestFocus0(long window, boolean force);
+ /** Must be called on Main-Thread */
private native void resignFocus0(long window);
- /** in case of a child window, it actually only issues orderBack(..) */
+ /** Must be called on Main-Thread. In case this is a child window and parent is still visible, orderBack(..) is issued instead of orderOut(). */
private native void orderOut0(long window);
+ /** Must be called on Main-Thread */
private native void orderFront0(long window);
+ /** Must be called on Main-Thread */
private native void close0(long window);
+ /** Must be called on Main-Thread */
private native void setTitle0(long window, String title);
private native long contentView0(long window);
- private native long changeContentView0(long parentWindowOrViewHandle, long window, long view);
- private native void setContentSize0(long window, int w, int h);
- private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y);
+ /** Must be called on Main-Thread */
+ private native void changeContentView0(long parentWindowOrView, long window, long view);
+ /** Must be called on Main-Thread */
+ private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h, boolean display);
+ /** Must be called on Main-Thread */
+ private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display);
+ /** Must be called on Main-Thread */
private native void setAlwaysOnTop0(long window, boolean atop);
private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y);
- private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible);
- private static native boolean confinePointer0(long windowHandle, boolean confine);
+ private static native void setPointerIcon0(long windowHandle, long handle);
+ private static native void setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible);
+ private static native void confinePointer0(long windowHandle, boolean confine);
private static native void warpPointer0(long windowHandle, int x, int y);
-
+
// Window styles
private static final int NSBorderlessWindowMask = 0;
private static final int NSTitledWindowMask = 1 << 0;
@@ -461,5 +738,5 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
private volatile long surfaceHandle = 0;
private long sscSurfaceHandle = 0;
private boolean isOffscreenInstance = false;
-
+
}
diff --git a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
new file mode 100644
index 000000000..5e703f690
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.newt.driver.opengl;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+import java.nio.ByteBuffer;
+
+import javax.media.nativewindow.util.PixelFormat;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.util.PNGPixelRect;
+
+public class JoglUtilPNGIcon {
+
+ public static ByteBuffer arrayToX11BGRAImages(final IOUtil.ClassResources resources, final int[] data_size, final int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
+ final PNGPixelRect[] images = new PNGPixelRect[resources.resourceCount()];
+ data_size[0] = 0;
+ for(int i=0; i<resources.resourceCount(); i++) {
+ final URLConnection urlConn = resources.resolve(i);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ data_size[0] += 2 + image.getSize().getWidth() * image.getSize().getHeight();
+ images[i] = image;
+ }
+ final boolean is64Bit = Platform.is64Bit();
+ elem_bytesize[0] = is64Bit ? Buffers.SIZEOF_LONG : Buffers.SIZEOF_INT;
+ final ByteBuffer buffer = Buffers.newDirectByteBuffer( data_size[0] * elem_bytesize[0] );
+
+ for(int i=0; i<images.length; i++) {
+ final PNGPixelRect image1 = images[i];
+ final int width = image1.getSize().getWidth();
+ final int height = image1.getSize().getHeight();
+ if( is64Bit ) {
+ buffer.putLong(width);
+ buffer.putLong(height);
+ } else {
+ buffer.putInt(width);
+ buffer.putInt(height);
+ }
+ final ByteBuffer bb = image1.getPixels();
+ final int stride = image1.getStride();
+ for(int y=0; y<height; y++) {
+ int bbOff = y * stride;
+ for(int x=0; x<width; x++) {
+ long pixel;
+ pixel = ( 0xffL & bb.get(bbOff++) ); // B
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 8; // G
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 16; // R
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 24; // A
+ if( is64Bit ) {
+ buffer.putLong(pixel);
+ } else {
+ buffer.putInt((int)pixel);
+ }
+ }
+ }
+ }
+ buffer.rewind();
+ return buffer;
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
index 579ec5be8..8973ae7ed 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,67 +29,128 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.windows;
+import java.net.URLConnection;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
import jogamp.nativewindow.windows.RegisteredClass;
import jogamp.nativewindow.windows.RegisteredClassFactory;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.PixelFormat;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.opengl.util.PNGPixelRect;
public class DisplayDriver extends DisplayImpl {
private static final String newtClassBaseName = "_newt_clazz" ;
+ private static final long[] defaultIconHandles;
private static RegisteredClassFactory sharedClassFactory;
static {
NEWTJNILibLoader.loadNEWT();
-
- if (!WindowDriver.initIDs0()) {
+ {
+ final long[] _defaultIconHandle = { 0, 0 };
+ if( DisplayImpl.isPNGUtilAvailable() ) {
+ try {
+ final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons();
+ {
+ final URLConnection urlConn = iconRes.resolve(0);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ _defaultIconHandle[0] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0);
+ }
+ {
+ final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ _defaultIconHandle[1] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0);
+ }
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ defaultIconHandles = _defaultIconHandle;
+ }
+ sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowDriver.getNewtWndProc0(),
+ false /* useDummyDispatchThread */, defaultIconHandles[0], defaultIconHandles[1]);
+
+ if (!WindowDriver.initIDs0(RegisteredClassFactory.getHInstance())) {
throw new NativeWindowException("Failed to initialize WindowsWindow jmethodIDs");
- }
- sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowDriver.getNewtWndProc0());
+ }
}
public static void initSingleton() {
// just exist to ensure static init has been run
}
+ protected static long getHInstance() {
+ return RegisteredClassFactory.getHInstance();
+ }
+
private RegisteredClass sharedClass;
public DisplayDriver() {
}
+ @Override
protected void createNativeImpl() {
sharedClass = sharedClassFactory.getSharedClass();
aDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
}
- protected void closeNativeImpl() {
+ @Override
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
sharedClassFactory.releaseSharedClass();
+ aDevice.close();
}
+ @Override
protected void dispatchMessagesNative() {
DispatchMessages0();
}
- protected long getHInstance() {
- return sharedClass.getHandle();
- }
-
protected String getWindowClassName() {
return sharedClass.getName();
}
+ @Override
+ protected final long createPointerIconImpl(final PixelFormat pixelformat, final int width, final int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createBGRA8888Icon0(pixels, width, height, true, hotX, hotY);
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, final long piHandle) {
+ destroyIcon0(piHandle);
+ }
+
//----------------------------------------------------------------------
// Internals only
//
private static native void DispatchMessages0();
+
+ static long createBGRA8888Icon0(final Buffer pixels, final int width, final int height, final boolean isCursor, final int hotX, final int hotY) {
+ if( null == pixels ) {
+ throw new IllegalArgumentException("data buffer/size");
+ }
+ final boolean pixels_is_direct = Buffers.isDirect(pixels);
+ return createBGRA8888Icon0(
+ pixels_is_direct ? pixels : Buffers.getArray(pixels),
+ pixels_is_direct ? Buffers.getDirectBufferByteOffset(pixels) : Buffers.getIndirectBufferByteOffset(pixels),
+ pixels_is_direct,
+ width, height, isCursor, hotX, hotY);
+ }
+ private static native long createBGRA8888Icon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, boolean isCursor, int hotX, int hotY);
+ private static native void destroyIcon0(long handle);
}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
index 948b29460..38acd03ae 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,96 +29,148 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.windows;
import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+import jogamp.newt.MonitorModeProps;
import jogamp.newt.ScreenImpl;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.Screen;
public class ScreenDriver extends ScreenImpl {
static {
DisplayDriver.initSingleton();
+ if( Screen.DEBUG ) {
+ dumpMonitorInfo0();
+ }
}
public ScreenDriver() {
}
+ @Override
protected void createNativeImpl() {
aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
}
-
+
+ @Override
protected void closeNativeImpl() {
}
- private int[] getScreenModeIdx(int idx) {
- int[] modeProps = getScreenMode0(screen_idx, idx);
- if (null == modeProps || 0 == modeProps.length) {
+ private final String getAdapterName(final int crt_idx) {
+ return getAdapterName0(crt_idx);
+ }
+ private final String getActiveMonitorName(final String adapterName, final int monitor_idx) {
+ return getActiveMonitorName0(adapterName, monitor_idx);
+ }
+
+ private final MonitorMode getMonitorModeImpl(final MonitorModeProps.Cache cache, final String adapterName, final int crtModeIdx) {
+ if( null == adapterName ) {
return null;
}
- if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) {
- throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length);
+ final String activeMonitorName = getActiveMonitorName(adapterName, 0);
+ final int[] modeProps = null != activeMonitorName ? getMonitorMode0(adapterName, crtModeIdx) : null;
+ if ( null == modeProps || 0 >= modeProps.length) {
+ return null;
}
- return modeProps;
+ return MonitorModeProps.streamInMonitorMode(null, cache, modeProps, 0);
}
- private int nativeModeIdx;
+ @Override
+ protected void collectNativeMonitorModesAndDevicesImpl(final MonitorModeProps.Cache cache) {
+ int crtIdx = 0;
+ ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
+ String adapterName = getAdapterName(crtIdx);
+ while( null != adapterName ) {
+ int crtModeIdx = 0;
+ MonitorMode mode;
+ do {
+ mode = getMonitorModeImpl(cache, adapterName, crtModeIdx);
+ if( null != mode ) {
+ supportedModes.getOrAdd(mode);
+ // next mode on same monitor
+ crtModeIdx++;
+ }
+ } while( null != mode);
+ if( 0 < crtModeIdx ) {
+ // has at least one mode -> add device
+ final MonitorMode currentMode = getMonitorModeImpl(cache, adapterName, -1);
+ if ( null != currentMode ) { // enabled
+ final int[] monitorProps = getMonitorDevice0(adapterName, crtIdx);
+ // merge monitor-props + supported modes
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, monitorProps, 0);
- protected int[] getScreenModeFirstImpl() {
- nativeModeIdx = 0;
- return getScreenModeNextImpl();
+ // next monitor, 1st mode
+ supportedModes= new ArrayHashSet<MonitorMode>();
+ }
+ }
+ crtIdx++;
+ adapterName = getAdapterName(crtIdx);
+ }
}
- protected int[] getScreenModeNextImpl() {
- int[] modeProps = getScreenModeIdx(nativeModeIdx);
- if (null != modeProps && 0 < modeProps.length) {
- nativeModeIdx++;
- return modeProps;
+ @Override
+ protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final Rectangle viewportPU, final Rectangle viewportWU) {
+ final String adapterName = getAdapterName(monitor.getId());
+ if( null != adapterName ) {
+ final String activeMonitorName = getActiveMonitorName(adapterName, 0);
+ if( null != activeMonitorName ) {
+ final int[] monitorProps = getMonitorDevice0(adapterName, monitor.getId());
+ int offset = MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT;
+ viewportPU.set(monitorProps[offset++], monitorProps[offset++], monitorProps[offset++], monitorProps[offset++]);
+ viewportWU.set(monitorProps[offset++], monitorProps[offset++], monitorProps[offset++], monitorProps[offset++]);
+ return true;
+ }
}
- return null;
+ return false;
}
- protected ScreenMode getCurrentScreenModeImpl() {
- int[] modeProps = getScreenModeIdx(-1);
- if (null != modeProps && 0 < modeProps.length) {
- return ScreenModeUtil.streamIn(modeProps, 0);
- }
- return null;
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return getMonitorModeImpl(null, getAdapterName(monitor.getId()), -1);
}
- protected boolean setCurrentScreenModeImpl(ScreenMode sm) {
- return setScreenMode0(screen_idx,
- sm.getMonitorMode().getSurfaceSize().getResolution().getWidth(),
- sm.getMonitorMode().getSurfaceSize().getResolution().getHeight(),
- sm.getMonitorMode().getSurfaceSize().getBitsPerPixel(),
- sm.getMonitorMode().getRefreshRate(),
- sm.getRotation());
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return setMonitorMode0(monitor.getId(),
+ -1, -1, // no fixed position!
+ mode.getSurfaceSize().getResolution().getWidth(),
+ mode.getSurfaceSize().getResolution().getHeight(),
+ mode.getSurfaceSize().getBitsPerPixel(),
+ (int)mode.getRefreshRate(), // simply cut-off, orig is int
+ mode.getFlags(),
+ mode.getRotation());
}
- protected int validateScreenIndex(int idx) {
- return 0; // big-desktop, only one screen available
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ return 0; // big-desktop w/ multiple monitor attached, only one screen available
}
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(getOriginX0(screen_idx));
- virtualOrigin.setY(getOriginY0(screen_idx));
- virtualSize.setWidth(getWidthImpl0(screen_idx));
- virtualSize.setHeight(getHeightImpl0(screen_idx));
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(final Rectangle viewport, final Rectangle viewportInWindowUnits) {
+ viewport.set(getVirtualOriginX0(), getVirtualOriginY0(), getVirtualWidthImpl0(), getVirtualHeightImpl0());
+ viewportInWindowUnits.set(viewport);
}
-
+
// Native calls
- private native int getOriginX0(int screen_idx);
- private native int getOriginY0(int screen_idx);
- private native int getWidthImpl0(int scrn_idx);
- private native int getHeightImpl0(int scrn_idx);
+ private native int getVirtualOriginX0();
+ private native int getVirtualOriginY0();
+ private native int getVirtualWidthImpl0();
+ private native int getVirtualHeightImpl0();
- private native int[] getScreenMode0(int screen_index, int mode_index);
- private native boolean setScreenMode0(int screen_index, int width, int height, int bits, int freq, int rot);
+ private static native void dumpMonitorInfo0();
+ private native String getAdapterName0(int crt_index);
+ private native String getActiveMonitorName0(String adapterName, int crtModeIdx);
+ private native int[] getMonitorMode0(String adapterName, int crtModeIdx);
+ private native int[] getMonitorDevice0(String adapterName, int monitor_index);
+ private native boolean setMonitorMode0(int monitor_index, int x, int y, int width, int height, int bits, int freq, int flags, int rot);
}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
index 71437c461..1c5c34457 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,13 +29,16 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.windows;
+import java.nio.ByteBuffer;
+
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.GDIUtil;
+import jogamp.newt.PointerIconImpl;
import jogamp.newt.WindowImpl;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
@@ -46,22 +49,24 @@ import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.MouseEvent.PointerType;
public class WindowDriver extends WindowImpl {
+ static {
+ DisplayDriver.initSingleton();
+ }
+
private long hmon;
private long hdc;
private long hdc_old;
private long windowHandleClose;
- static {
- DisplayDriver.initSingleton();
- }
-
public WindowDriver() {
}
@@ -70,21 +75,28 @@ public class WindowDriver extends WindowImpl {
if (0 != hdc) {
throw new InternalError("surface not released");
}
- hdc = GDI.GetDC(getWindowHandle());
- hmon = MonitorFromWindow0(getWindowHandle());
-
+ final long hWnd = getWindowHandle();
+ hdc = GDI.GetDC(hWnd);
+
// return ( 0 == hdc ) ? LOCK_SURFACE_NOT_READY : ( hdc_old != hdc ) ? LOCK_SURFACE_CHANGED : LOCK_SUCCESS ;
- if( 0 == hdc ) {
+ if( 0 == hdc ) {
return LOCK_SURFACE_NOT_READY;
}
+ hmon = MonitorFromWindow0(hWnd);
+
+ // Let's not trigger on HDC change, GLDrawableImpl.'s destroy/create is a nop here anyways.
+ // FIXME: Validate against EGL surface creation: ANGLE uses HWND -> fine!
+ return LOCK_SUCCESS;
+
+ /**
if( hdc_old == hdc ) {
return LOCK_SUCCESS;
}
- if(DEBUG_IMPLEMENTATION) {
+ if(DEBUG_IMPLEMENTATION) {
System.err.println("WindowsWindow: surface change "+toHexString(hdc_old)+" -> "+toHexString(hdc));
// Thread.dumpStack();
}
- return LOCK_SURFACE_CHANGED;
+ return LOCK_SURFACE_CHANGED; */
}
@Override
@@ -104,7 +116,7 @@ public class WindowDriver extends WindowImpl {
@Override
public boolean hasDeviceChanged() {
if(0!=getWindowHandle()) {
- long _hmon = MonitorFromWindow0(getWindowHandle());
+ final long _hmon = MonitorFromWindow0(getWindowHandle());
if (hmon != _hmon) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Info: Window Device Changed "+Thread.currentThread().getName()+
@@ -118,6 +130,7 @@ public class WindowDriver extends WindowImpl {
return false;
}
+ @Override
protected void createNativeImpl() {
final ScreenDriver screen = (ScreenDriver) getScreen();
final DisplayDriver display = (DisplayDriver) screen.getDisplay();
@@ -127,70 +140,68 @@ public class WindowDriver extends WindowImpl {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
setGraphicsConfiguration(cfg);
- final int flags = getReconfigureFlags(0, true) &
+ final VersionNumber winVer = Platform.getOSVersionNumber();
+ final int flags = getReconfigureFlags(0, true) &
( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
- setWindowHandle(CreateWindow0(display.getHInstance(), display.getWindowClassName(), display.getWindowClassName(),
- getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags));
- if (getWindowHandle() == 0) {
+ final long _windowHandle = CreateWindow0(DisplayDriver.getHInstance(), display.getWindowClassName(), display.getWindowClassName(),
+ winVer.getMajor(), winVer.getMinor(),
+ getParentWindowHandle(),
+ getX(), getY(), getWidth(), getHeight(), autoPosition(), flags);
+ if ( 0 == _windowHandle ) {
throw new NativeWindowException("Error creating window");
}
- windowHandleClose = getWindowHandle();
- addMouseListener(new MouseTracker());
-
+ setWindowHandle(_windowHandle);
+ windowHandleClose = _windowHandle;
+
if(DEBUG_IMPLEMENTATION) {
- Exception e = new Exception("Info: Window new window handle "+Thread.currentThread().getName()+
+ final Exception e = new Exception("Info: Window new window handle "+Thread.currentThread().getName()+
" (Parent HWND "+toHexString(getParentWindowHandle())+
- ") : HWND "+toHexString(getWindowHandle())+", "+Thread.currentThread());
+ ") : HWND "+toHexString(_windowHandle)+", "+Thread.currentThread());
e.printStackTrace();
}
}
-
- class MouseTracker extends MouseAdapter {
- public void mouseEntered(MouseEvent e) {
- WindowDriver.trackPointerLeave0(WindowDriver.this.getWindowHandle());
- }
- }
+ @Override
protected void closeNativeImpl() {
- if(windowHandleClose != 0) {
- if (hdc != 0) {
+ if( 0 != windowHandleClose ) {
+ if ( 0 != hdc ) {
try {
GDI.ReleaseDC(windowHandleClose, hdc);
- } catch (Throwable t) {
- if(DEBUG_IMPLEMENTATION) {
- Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
+ } catch (final Throwable t) {
+ if(DEBUG_IMPLEMENTATION) {
+ final Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
e.printStackTrace();
}
}
}
try {
GDI.DestroyWindow(windowHandleClose);
- } catch (Throwable t) {
+ } catch (final Throwable t) {
if(DEBUG_IMPLEMENTATION) {
- Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
+ final Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
e.printStackTrace();
}
- } finally {
- windowHandleClose = 0;
}
}
+ windowHandleClose = 0;
hdc = 0;
hdc_old = 0;
}
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+ @Override
+ protected boolean reconfigureWindowImpl(int x, int y, int width, int height, final int flags) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("WindowsWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
getReconfigureFlagsAsString(null, flags));
}
-
+
if(0 == ( FLAG_IS_UNDECORATED & flags)) {
final InsetsImmutable i = getInsets();
-
+
// client position -> top-level window position
x -= i.getLeftWidth() ;
y -= i.getTopHeight() ;
-
+
if(0<width && 0<height) {
// client size -> top-level window size
width += i.getTotalWidth();
@@ -198,14 +209,15 @@ public class WindowDriver extends WindowImpl {
}
}
reconfigureWindow0( getParentWindowHandle(), getWindowHandle(), x, y, width, height, flags);
-
+
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
- visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+ visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
return true;
}
- protected void requestFocusImpl(boolean force) {
+ @Override
+ protected void requestFocusImpl(final boolean force) {
requestFocus0(getWindowHandle(), force);
}
@@ -215,136 +227,150 @@ public class WindowDriver extends WindowImpl {
}
@Override
+ protected void setPointerIconImpl(final PointerIconImpl pi) {
+ setPointerIcon0(getWindowHandle(), null != pi ? pi.validatedHandle() : 0);
+ }
+
+ @Override
protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
- final Boolean[] res = new Boolean[] { Boolean.FALSE };
-
+ final boolean[] res = new boolean[] { false };
+
this.runOnEDTIfAvail(true, new Runnable() {
+ @Override
public void run() {
- res[0] = Boolean.valueOf(setPointerVisible0(getWindowHandle(), pointerVisible));
+ res[0] = setPointerVisible0(getWindowHandle(), pointerVisible);
}
});
- return res[0].booleanValue();
+ return res[0];
}
@Override
protected boolean confinePointerImpl(final boolean confine) {
final Boolean[] res = new Boolean[] { Boolean.FALSE };
-
+
this.runOnEDTIfAvail(true, new Runnable() {
+ @Override
public void run() {
- final Point p0 = getLocationOnScreenImpl(0, 0);
- res[0] = Boolean.valueOf(confinePointer0(getWindowHandle(), confine,
- p0.getX(), p0.getY(), p0.getX()+getWidth(), p0.getY()+getHeight()));
+ final Point p0 = convertToPixelUnits( getLocationOnScreenImpl(0, 0) );
+ res[0] = Boolean.valueOf(confinePointer0(getWindowHandle(), confine,
+ p0.getX(), p0.getY(),
+ p0.getX()+getSurfaceWidth(), p0.getY()+getSurfaceHeight()));
}
});
return res[0].booleanValue();
}
-
+
@Override
- protected void warpPointerImpl(final int x, final int y) {
+ protected void warpPointerImpl(final int x, final int y) {
this.runOnEDTIfAvail(true, new Runnable() {
+ @Override
public void run() {
- final Point sPos = getLocationOnScreenImpl(x, y);
+ final Point sPos = convertToPixelUnits( getLocationOnScreenImpl(x, y) );
warpPointer0(getWindowHandle(), sPos.getX(), sPos.getY());
}
});
return;
}
-
- protected Point getLocationOnScreenImpl(int x, int y) {
+
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
return GDIUtil.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y);
}
- protected void updateInsetsImpl(Insets insets) {
- // nop - using event driven insetsChange(..)
+ @Override
+ protected void updateInsetsImpl(final Insets insets) {
+ // nop - using event driven insetsChange(..)
}
-
- private final int validateKeyCode(int eventType, int modifiers, int keyCode, char keyChar) {
- switch(eventType) {
- case KeyEvent.EVENT_KEY_RELEASED:
- pressedKeyBalance--;
- lastPressedKeyCode = keyCode;
- break;
- case KeyEvent.EVENT_KEY_PRESSED:
- pressedKeyBalance++;
- lastPressedKeyCode = keyCode;
- break;
- case KeyEvent.EVENT_KEY_TYPED:
- if(-1==keyCode) {
- keyCode = lastPressedKeyCode;
- }
- lastPressedKeyCode = -1;
- break;
+
+ //
+ // PointerEvent Handling
+ //
+ /**
+ * Send multiple-pointer {@link MouseEvent.PointerType#TouchScreen} event to be directly consumed
+ * <p>
+ * Assumes non normal pointer names and rotation/scroll will be determined by a gesture handler.
+ * </p>
+ * <p>
+ * See {@link #doPointerEvent(boolean, boolean, PointerType[], short, int, int, boolean, int[], int[], int[], float[], float, float[], float)}
+ * for details.
+ * </p>
+ */
+ public final void sendTouchScreenEvent(final short eventType, final int modifiers,
+ final int pActionIdx, final int[] pNames,
+ final int[] pX, final int[] pY, final float[] pPressure, final float maxPressure) {
+ final int pCount = pNames.length;
+ final MouseEvent.PointerType[] pTypes = new MouseEvent.PointerType[pCount];
+ for(int i=pCount-1; i>=0; i--) { pTypes[i] = PointerType.TouchScreen; }
+ doPointerEvent(false /*enqueue*/, false /*wait*/,
+ pTypes, eventType, modifiers, pActionIdx, false /*normalPNames*/, pNames,
+ pX, pY, pPressure, maxPressure, new float[] { 0f, 0f, 0f} /*rotationXYZ*/, 1f/*rotationScale*/);
+ }
+
+ //
+ // KeyEvent Handling
+ //
+ private short repeatedKey = KeyEvent.VK_UNDEFINED;
+
+ private final boolean handlePressTypedAutoRepeat(final boolean isModifierKey, int modifiers, final short keyCode, final short keySym, final char keyChar) {
+ if( setKeyPressed(keyCode, true) ) {
+ // AR: Key was already pressed: Either [enter | within] AR mode
+ final boolean withinAR = repeatedKey == keyCode;
+ repeatedKey = keyCode;
+ if( !isModifierKey ) {
+ // AR: Key was already pressed: Either [enter | within] AR mode
+ modifiers |= InputEvent.AUTOREPEAT_MASK;
+ if( withinAR ) {
+ // AR: Within AR mode
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar);
+ } // else { AR: Enter AR mode - skip already send PRESSED ; or ALT }
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar);
+ }
+ return true;
}
- return keyCode;
+ return false;
}
- private int lastPressedKeyCode = 0;
- private int pressedKeyBalance = 0;
- private int autoRepeat = 0;
-
+
@Override
- public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
- // Note that we have to regenerate the keyCode for EVENT_KEY_TYPED on this platform
- keyCode = validateKeyCode(eventType, modifiers, keyCode, keyChar);
+ public final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) {
+ final boolean isModifierKey = KeyEvent.isModifierKey(keySym);
+ // System.err.println("*** sendKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar+">, mods "+toHexString(modifiers)+
+ // ", isKeyCodeTracked "+isKeyCodeTracked(keyCode)+", was: pressed "+isKeyPressed(keyCode)+", printableKey "+KeyEvent.isPrintableKey(keyCode, false)+" [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis());
+
+ // Reorder: WINDOWS delivery order is PRESSED (t0), TYPED (t0) and RELEASED (t1) -> NEWT order: PRESSED (t0) and RELEASED (t1)
+ // Auto-Repeat: WINDOWS delivers only PRESSED (t0) and TYPED (t0).
switch(eventType) {
case KeyEvent.EVENT_KEY_RELEASED:
- // reorder: WINDOWS delivery order is PRESSED, TYPED and RELEASED -> NEWT order: PRESSED, RELEASED and TYPED
+ if( isKeyCodeTracked(keyCode) ) {
+ if( repeatedKey == keyCode && !isModifierKey ) {
+ // AR out - send out missing PRESSED
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, keySym, keyChar);
+ }
+ setKeyPressed(keyCode, false);
+ repeatedKey = KeyEvent.VK_UNDEFINED;
+ }
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar);
break;
case KeyEvent.EVENT_KEY_PRESSED:
- if(pressedKeyBalance > 1) {
- // Auto-Repeat: WINDOWS delivers only PRESSED and TYPED.
- // Since reordering already injects RELEASE, we only need to set the AUTOREPEAT_MASK.
- pressedKeyBalance--;
- autoRepeat |= InputEvent.AUTOREPEAT_MASK;
- } else {
- autoRepeat &= ~InputEvent.AUTOREPEAT_MASK;
+ if( !handlePressTypedAutoRepeat(isModifierKey, modifiers, keyCode, keySym, keyChar) ) {
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar);
}
- super.sendKeyEvent(eventType, modifiers | autoRepeat, keyCode, (char)-1);
- break;
- case KeyEvent.EVENT_KEY_TYPED:
- modifiers |= autoRepeat;
- super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, (char)-1);
- super.sendKeyEvent(eventType, modifiers, keyCode, keyChar);
break;
}
}
-
+
@Override
- public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
- // Note that we have to regenerate the keyCode for EVENT_KEY_TYPED on this platform
- keyCode = validateKeyCode(eventType, modifiers, keyCode, keyChar);
- switch(eventType) {
- case KeyEvent.EVENT_KEY_RELEASED:
- // reorder: WINDOWS delivery order is PRESSED, TYPED and RELEASED -> NEWT order: PRESSED, RELEASED and TYPED
- break;
- case KeyEvent.EVENT_KEY_PRESSED:
- if(pressedKeyBalance > 1) {
- // Auto-Repeat: WINDOWS delivers only PRESSED and TYPED.
- // Since reordering already injects RELEASE, we only need to set the AUTOREPEAT_MASK.
- pressedKeyBalance--;
- autoRepeat |= InputEvent.AUTOREPEAT_MASK;
- } else {
- autoRepeat &= ~InputEvent.AUTOREPEAT_MASK;
- }
- super.enqueueKeyEvent(wait, eventType, modifiers | autoRepeat, keyCode, (char)-1);
- break;
- case KeyEvent.EVENT_KEY_TYPED:
- modifiers |= autoRepeat;
- super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, (char)-1);
- super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keyChar);
- break;
- }
+ public final void enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
}
-
+
//----------------------------------------------------------------------
// Internals only
//
- protected static native boolean initIDs0();
protected static native long getNewtWndProc0();
+ protected static native boolean initIDs0(long hInstance);
- private native long CreateWindow0(long hInstance, String wndClassName, String wndName,
- long parentWindowHandle,
- int x, int y, int width, int height, boolean autoPosition, int flags);
+ private native long CreateWindow0(long hInstance, String wndClassName, String wndName, int winMajor, int winMinor,
+ long parentWindowHandle, int x, int y, int width, int height, boolean autoPosition, int flags);
private native long MonitorFromWindow0(long windowHandle);
private native void reconfigureWindow0(long parentWindowHandle, long windowHandle,
int x, int y, int width, int height, int flags);
@@ -353,6 +379,8 @@ public class WindowDriver extends WindowImpl {
private static native boolean setPointerVisible0(long windowHandle, boolean visible);
private static native boolean confinePointer0(long windowHandle, boolean grab, int l, int t, int r, int b);
- private static native void warpPointer0(long windowHandle, int x, int y);
- private static native void trackPointerLeave0(long windowHandle);
+ private static native void warpPointer0(long windowHandle, int x, int y);
+ private static native ByteBuffer newDirectByteBuffer(long addr, long capacity);
+
+ private static native void setPointerIcon0(long windowHandle, long iconHandle);
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
index 714324d63..e2b9a65d1 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,15 +29,19 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.x11;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.util.PixelFormat;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import jogamp.nativewindow.x11.X11Util;
@@ -58,15 +62,14 @@ public class DisplayDriver extends DisplayImpl {
}
}
- public static void initSingleton() {
- // just exist to ensure static init has been run
- }
-
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
public DisplayDriver() {
}
- public String validateDisplayName(String name, long handle) {
+ @Override
+ public String validateDisplayName(final String name, final long handle) {
return X11Util.validateDisplayName(name, handle);
}
@@ -74,98 +77,99 @@ public class DisplayDriver extends DisplayImpl {
* {@inheritDoc}
*
* We use a private non-shared X11 Display instance for EDT window operations and one for exposed animation, eg. OpenGL.
- * <p>
- * In case {@link X11Util#HAS_XLOCKDISPLAY_BUG} and {@link X11Util#XINITTHREADS_ALWAYS_ENABLED},
- * we use null locking. Even though this seems not to be rational, it gives most stable results on all platforms.
- * </p>
- * <p>
- * Otherwise we use basic locking via the constructor {@link X11GraphicsDevice#X11GraphicsDevice(long, int, boolean)},
- * since it is possible to share this device via {@link com.jogamp.newt.NewtFactory#createDisplay(String, boolean)}.
- * </p>
*/
- @SuppressWarnings("unused")
+ @Override
protected void createNativeImpl() {
- long handle = X11Util.openDisplay(name);
+ X11Util.setX11ErrorHandler(true, DEBUG ? false : true); // make sure X11 error handler is set
+ final long handle = X11Util.openDisplay(name);
if( 0 == handle ) {
throw new RuntimeException("Error creating display(Win): "+name);
}
- if(USE_SEPARATE_DISPLAY_FOR_EDT) {
- edtDisplayHandle = X11Util.openDisplay(name);
- if( 0 == edtDisplayHandle ) {
- X11Util.closeDisplay(handle);
- throw new RuntimeException("Error creating display(EDT): "+name);
- }
- } else {
- edtDisplayHandle = handle;
- }
+ aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
try {
- CompleteDisplay0(edtDisplayHandle);
- } catch(RuntimeException e) {
- closeNativeImpl();
+ CompleteDisplay0(aDevice.getHandle());
+ } catch(final RuntimeException e) {
+ closeNativeImpl(aDevice);
throw e;
}
-
- // see API doc above!
- if(X11Util.XINITTHREADS_ALWAYS_ENABLED && X11Util.HAS_XLOCKDISPLAY_BUG) {
- aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock(), false);
- } else {
- aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, false);
- }
}
- protected void closeNativeImpl() {
- DisplayRelease0(edtDisplayHandle, javaObjectAtom, windowDeleteAtom);
+ @Override
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
+ DisplayRelease0(aDevice.getHandle(), javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
javaObjectAtom = 0;
windowDeleteAtom = 0;
- // closing using ATI driver bug 'same order'
- final long handle = getHandle();
- X11Util.closeDisplay(handle);
- if(handle != edtDisplayHandle) {
- X11Util.closeDisplay(edtDisplayHandle);
- }
- edtDisplayHandle = 0;
+ // kbdHandle = 0;
+ aDevice.close(); // closes X11 display
}
+ @Override
protected void dispatchMessagesNative() {
- if(0 != edtDisplayHandle) {
- DispatchMessages0(edtDisplayHandle, javaObjectAtom, windowDeleteAtom);
+ final AbstractGraphicsDevice _aDevice = aDevice; // aDevice could be pulled by destroy event
+ _aDevice.lock();
+ try {
+ final long handle = _aDevice.getHandle();
+ if(0 != handle) {
+ DispatchMessages0(handle, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
+ }
+ } finally {
+ _aDevice.unlock();
}
}
- protected long getEDTHandle() { return edtDisplayHandle; }
protected long getJavaObjectAtom() { return javaObjectAtom; }
protected long getWindowDeleteAtom() { return windowDeleteAtom; }
-
+ // protected long getKbdHandle() { return kbdHandle; } // XKB disabled for now
+
+ /** Returns <code>null</code> if !{@link #isNativeValid()}, otherwise the Boolean value of {@link X11GraphicsDevice#isXineramaEnabled()}. */
+ protected Boolean isXineramaEnabled() { return isNativeValid() ? Boolean.valueOf(((X11GraphicsDevice)aDevice).isXineramaEnabled()) : null; }
+
+ @Override
+ protected final long createPointerIconImpl(final PixelFormat pixelformat, final int width, final int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createPointerIcon(getHandle(), pixels, width, height, hotX, hotY);
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, final long piHandle) {
+ destroyPointerIcon0(displayHandle, piHandle);
+ }
+
//----------------------------------------------------------------------
// Internals only
//
+
private static native boolean initIDs0(boolean debug);
private native void CompleteDisplay0(long handle);
- private void displayCompleted(long javaObjectAtom, long windowDeleteAtom) {
+ private void displayCompleted(final long javaObjectAtom, final long windowDeleteAtom /*, long kbdHandle */) {
this.javaObjectAtom=javaObjectAtom;
this.windowDeleteAtom=windowDeleteAtom;
+ // this.kbdHandle = kbdHandle; // XKB disabled for now
}
- private native void DisplayRelease0(long handle, long javaObjectAtom, long windowDeleteAtom);
+ private native void DisplayRelease0(long handle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle */); // XKB disabled for now
- private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom);
+ private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom /* , long kbdHandle */); // XKB disabled for now
+
+ private static long createPointerIcon(final long display, final Buffer pixels, final int width, final int height, final int hotX, final int hotY) {
+ final boolean pixels_is_direct = Buffers.isDirect(pixels);
+ return createPointerIcon0(display,
+ pixels_is_direct ? pixels : Buffers.getArray(pixels),
+ pixels_is_direct ? Buffers.getDirectBufferByteOffset(pixels) : Buffers.getIndirectBufferByteOffset(pixels),
+ pixels_is_direct,
+ width, height, hotX, hotY);
+ }
+ private static native long createPointerIcon0(long display, Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY);
+
+ private static native void destroyPointerIcon0(long display, long handle);
- /**
- * 2011/06/14 libX11 1.4.2 and libxcb 1.7 bug 20708 - Multithreading Issues w/ OpenGL, ..
- * https://bugs.freedesktop.org/show_bug.cgi?id=20708
- * https://jogamp.org/bugzilla/show_bug.cgi?id=502
- * Affects: Ubuntu 11.04, OpenSuSE 11, ..
- * Workaround: Using a separate X11 Display connection for event dispatching (EDT)
- */
- private final boolean USE_SEPARATE_DISPLAY_FOR_EDT = true;
-
- private long edtDisplayHandle;
-
/** X11 Window delete atom marker used on EDT */
private long windowDeleteAtom;
-
+
/** X11 Window java object property used on EDT */
private long javaObjectAtom;
+
+ /** X11 Keyboard handle used on EDT */
+ // private long kbdHandle; // XKB disabled for now
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR.java b/src/newt/classes/jogamp/newt/driver/x11/RandR.java
new file mode 100644
index 000000000..8b065d1f0
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.newt.driver.x11;
+
+import java.util.List;
+
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import jogamp.newt.MonitorModeProps;
+
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+public interface RandR {
+ public static final VersionNumber version110 = new VersionNumber(1, 1, 0);
+ public static final VersionNumber version130 = new VersionNumber(1, 3, 0);
+ public static final VersionNumber version140 = new VersionNumber(1, 4, 0);
+
+ VersionNumber getVersion();
+
+ void dumpInfo(final long dpy, final int screen_idx);
+
+ /**
+ * Encapsulate initial device query allowing caching of internal data structures.
+ * Methods covered:
+ * <ul>
+ * <li>{@link #getMonitorDeviceCount(long, ScreenDriver)}</li>
+ * <li>{@link #getAvailableRotations(long, ScreenDriver, int)}</li>
+ * <li>{@link #getMonitorModeProps(long, ScreenDriver, int)}</li>
+ * <li>{@link #getCurrentMonitorModeProps(long, ScreenDriver, int)</li>
+ * <li>{@link #getMonitorDeviceProps(long, ScreenDriver, List, int, MonitorMode)}</li>
+ * </ul>
+ * <p>
+ * Above methods may be called w/o begin/end, in which case no
+ * internal data structures can be cached:
+ * </p>
+ * @param dpy TODO
+ * @param screen TODO
+ * @return TODO
+ */
+ boolean beginInitialQuery(long dpy, ScreenDriver screen);
+ void endInitialQuery(long dpy, ScreenDriver screen);
+
+ int getMonitorDeviceCount(final long dpy, final ScreenDriver screen);
+ int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx);
+ /**
+ *
+ * @param dpy
+ * @param screen
+ * @param mode_idx w/o indexing rotation
+ * @return props w/o actual rotation
+ */
+ int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx);
+ int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_idx);
+ int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx);
+ int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx);
+ boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode);
+
+ public void updateScreenViewport(final long dpy, final ScreenDriver screen, RectangleImmutable viewport);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
new file mode 100644
index 000000000..4803852f9
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
@@ -0,0 +1,370 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.newt.driver.x11;
+
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.Screen;
+
+class RandR11 implements RandR {
+ private static final boolean DEBUG = ScreenDriver.DEBUG;
+
+ RandR11() {
+ }
+
+ @Override
+ public final VersionNumber getVersion() {
+ return version110;
+ }
+
+ @Override
+ public void dumpInfo(final long dpy, final int screen_idx) {
+ // NOP
+ }
+
+ private int widthMM=0, heightMM=0;
+ private int modeCount = 0;
+ private int resolutionCount = 0;
+ private int[][] nrates = null; // [nres_number][nrate_number]
+ private int[] idx_rate = null, idx_res = null;
+
+ @Override
+ public boolean beginInitialQuery(final long dpy, final ScreenDriver screen) {
+ // initialize iterators and static data
+ final int screen_idx = screen.getIndex();
+ resolutionCount = getNumScreenResolutions0(dpy, screen_idx);
+ if(0==resolutionCount) {
+ endInitialQuery(dpy, screen);
+ return false;
+ }
+
+ nrates = new int[resolutionCount][];
+ for(int i=0; i<resolutionCount; i++) {
+ nrates[i] = getScreenRates0(dpy, screen_idx, i);
+ if(null==nrates[i] || 0==nrates[i].length) {
+ endInitialQuery(dpy, screen);
+ return false;
+ }
+ }
+
+ for(int nresIdx=0; nresIdx < resolutionCount; nresIdx++) {
+ modeCount += nrates[nresIdx].length;
+ }
+
+ idx_rate = new int[modeCount];
+ idx_res = new int[modeCount];
+
+ int modeIdx=0;
+ for(int nresIdx=0; nresIdx < resolutionCount; nresIdx++) {
+ for(int nrateIdx=0; nrateIdx < nrates[nresIdx].length; nrateIdx++) {
+ idx_rate[modeIdx] = nrateIdx;
+ idx_res[modeIdx] = nresIdx;
+ modeIdx++;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void endInitialQuery(final long dpy, final ScreenDriver screen) {
+ idx_rate=null;
+ idx_res=null;
+ nrates=null;
+ }
+
+ @Override
+ public int getMonitorDeviceCount(final long dpy, final ScreenDriver screen) {
+ return 1;
+ }
+
+ @Override
+ public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ if( 0 < crt_idx ) {
+ // RandR11 only supports 1 CRT
+ return null;
+ }
+ final int screen_idx = screen.getIndex();
+ final int[] availRotations = getAvailableScreenRotations0(dpy, screen_idx);
+ if(null==availRotations || 0==availRotations.length) {
+ return null;
+ }
+ return availRotations;
+ }
+
+ @Override
+ public int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx) {
+ if( mode_idx >= modeCount ) {
+ return null;
+ }
+ final int screen_idx = screen.getIndex();
+
+ final int nres_index = idx_res[mode_idx];
+ final int nrate_index = idx_rate[mode_idx];
+
+ final int[] res = getScreenResolution0(dpy, screen_idx, nres_index);
+ if(null==res || 0==res.length) {
+ return null;
+ }
+ if(0>=res[0] || 0>=res[1]) {
+ throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+resolutionCount);
+ }
+ if( res[2] > widthMM ) {
+ widthMM = res[2];
+ }
+ if( res[3] > heightMM ) {
+ heightMM = res[3];
+ }
+
+ int rate = nrates[nres_index][nrate_index];
+ if(0>=rate) {
+ rate = ScreenImpl.default_sm_rate;
+ if(DEBUG) {
+ System.err.println("Invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length+", using default: "+ScreenImpl.default_sm_rate);
+ }
+ }
+
+ final int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = res[0]; // width
+ props[i++] = res[1]; // height
+ props[i++] = ScreenImpl.default_sm_bpp; // bpp n/a in RandR11
+ props[i++] = rate*100; // rate (Hz*100)
+ props[i++] = 0; // flags;
+ props[i++] = nres_index;
+ props[i++] = -1; // rotation placeholder;
+ if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) {
+ throw new InternalError("XX");
+ }
+ return props;
+ }
+
+ @Override
+ public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, final MonitorModeProps.Cache cache, final int crt_idx) {
+ if( 0 < crt_idx ) {
+ // RandR11 only supports 1 CRT
+ return null;
+ }
+ final int[] currentModeProps = getCurrentMonitorModeProps(dpy, screen, crt_idx);
+ if( null == currentModeProps) { // disabled
+ return null;
+ }
+ final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, currentModeProps, 0);
+ final int allModesCount = cache.monitorModes.size();
+ final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 + allModesCount];
+ int i = 0;
+ props[i++] = props.length;
+ props[i++] = crt_idx;
+ props[i++] = widthMM;
+ props[i++] = heightMM;
+ props[i++] = 0; // rotated viewport x pixel-units
+ props[i++] = 0; // rotated viewport y pixel-units
+ props[i++] = currentMode.getRotatedWidth(); // rotated viewport width pixel-units
+ props[i++] = currentMode.getRotatedHeight(); // rotated viewport height pixel-units
+ props[i++] = 0; // rotated viewport x window-units
+ props[i++] = 0; // rotated viewport y window-units
+ props[i++] = currentMode.getRotatedWidth(); // rotated viewport width window-units
+ props[i++] = currentMode.getRotatedHeight(); // rotated viewport height window-units
+ props[i++] = currentMode.getId(); // current mode id
+ props[i++] = currentMode.getRotation();
+ for(int j=0; j<allModesCount; j++) {
+ props[i++] = cache.monitorModes.get(j).getId();
+ }
+ return props;
+ }
+
+ @Override
+ public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ if( 0 < crt_idx ) {
+ // RandR11 only supports 1 CRT
+ return null;
+ }
+ final int screen_idx = screen.getIndex();
+ final long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
+ if(0 == screenConfigHandle) {
+ return null;
+ }
+ int[] res;
+ final int nres_idx;
+ try {
+ final int resNumber = getNumScreenResolutions0(dpy, screen_idx);
+ if(0==resNumber) {
+ return null;
+ }
+
+ nres_idx = getCurrentScreenResolutionIndex0(screenConfigHandle);
+ if(0>nres_idx) {
+ return null;
+ }
+ if(nres_idx>=resNumber) {
+ throw new RuntimeException("Invalid resolution index: ! "+nres_idx+" < "+resNumber);
+ }
+ res = getScreenResolution0(dpy, screen_idx, nres_idx);
+ if(null==res || 0==res.length) {
+ return null;
+ }
+ if(0>=res[0] || 0>=res[1]) {
+ throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_idx+"/"+resNumber);
+ }
+ } finally {
+ freeScreenConfiguration0(screenConfigHandle);
+ }
+ final int[] props = new int[4];
+ int i = 0;
+ props[i++] = 0;
+ props[i++] = 0;
+ props[i++] = res[0]; // width
+ props[i++] = res[1]; // height
+ return props;
+ }
+
+ @Override
+ public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ if( 0 < crt_idx ) {
+ // RandR11 only supports 1 CRT
+ return null;
+ }
+ final int screen_idx = screen.getIndex();
+ final long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
+ if(0 == screenConfigHandle) {
+ return null;
+ }
+ int[] res;
+ int rate, rot;
+ final int nres_idx;
+ try {
+ final int resNumber = getNumScreenResolutions0(dpy, screen_idx);
+ if(0==resNumber) {
+ return null;
+ }
+
+ nres_idx = getCurrentScreenResolutionIndex0(screenConfigHandle);
+ if(0>nres_idx) {
+ return null;
+ }
+ if(nres_idx>=resNumber) {
+ throw new RuntimeException("Invalid resolution index: ! "+nres_idx+" < "+resNumber);
+ }
+ res = getScreenResolution0(dpy, screen_idx, nres_idx);
+ if(null==res || 0==res.length) {
+ return null;
+ }
+ if(0>=res[0] || 0>=res[1]) {
+ throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_idx+"/"+resNumber);
+ }
+ rate = getCurrentScreenRate0(screenConfigHandle);
+ if(0>rate) {
+ return null;
+ }
+ rot = getCurrentScreenRotation0(screenConfigHandle);
+ if(0>rot) {
+ return null;
+ }
+ } finally {
+ freeScreenConfiguration0(screenConfigHandle);
+ }
+ final int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = res[0]; // width
+ props[i++] = res[1]; // height
+ props[i++] = ScreenImpl.default_sm_bpp;
+ props[i++] = rate*100; // rate (Hz*100)
+ props[i++] = 0; // flags;
+ props[i++] = nres_idx; // mode_idx;
+ props[i++] = rot;
+ if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) {
+ throw new InternalError("XX");
+ }
+ return props;
+ }
+
+ @Override
+ public boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, final MonitorDevice monitor, final MonitorMode mode) {
+ final long t0 = System.currentTimeMillis();
+ boolean done = false;
+ final int screen_idx = screen.getIndex();
+ final long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
+ if(0 == screenConfigHandle) {
+ return Boolean.valueOf(done);
+ }
+ try {
+ final int resId = mode.getId();
+ if(0>resId || resId>=resolutionCount) {
+ throw new RuntimeException("Invalid resolution index: ! 0 < "+resId+" < "+resolutionCount+", "+monitor+", "+mode);
+ }
+ final int f = (int)mode.getRefreshRate(); // simply cut-off, orig is int
+ final int r = mode.getRotation();
+
+ if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resId, f, r) ) {
+ while(!done && System.currentTimeMillis()-t0 < Screen.SCREEN_MODE_CHANGE_TIMEOUT) {
+ done = setCurrentScreenModePollEnd0(dpy, screen_idx, resId, f, r);
+ if(!done) {
+ try { Thread.sleep(10); } catch (final InterruptedException e) { }
+ }
+ }
+ }
+ } finally {
+ freeScreenConfiguration0(screenConfigHandle);
+ }
+ return done;
+ }
+
+ @Override
+ public final void updateScreenViewport(final long dpy, final ScreenDriver screen, final RectangleImmutable viewport) {
+ // nop
+ }
+
+ /** @return int[] { rot1, .. } */
+ private static native int[] getAvailableScreenRotations0(long display, int screen_index);
+
+ private static native int getNumScreenResolutions0(long display, int screen_index);
+
+ /** @return int[] { width, height, widthmm, heightmm } */
+ private static native int[] getScreenResolution0(long display, int screen_index, int mode_index);
+
+ private static native int[] getScreenRates0(long display, int screen_index, int mode_index);
+
+ private static native long getScreenConfiguration0(long display, int screen_index);
+ private static native void freeScreenConfiguration0(long screenConfiguration);
+
+ private static native int getCurrentScreenResolutionIndex0(long screenConfiguration);
+ private static native int getCurrentScreenRate0(long screenConfiguration);
+ private static native int getCurrentScreenRotation0(long screenConfiguration);
+
+ /** needs own Display connection for XRANDR event handling */
+ private static native boolean setCurrentScreenModeStart0(long display, int screen_index, long screenConfiguration, int mode_index, int freq, int rot);
+ private static native boolean setCurrentScreenModePollEnd0(long display, int screen_index, int mode_index, int freq, int rot);
+
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
new file mode 100644
index 000000000..7a409bba1
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
@@ -0,0 +1,274 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.newt.driver.x11;
+
+import java.util.Iterator;
+
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import jogamp.newt.MonitorModeProps;
+
+import com.jogamp.common.util.IntLongHashMap;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+/**
+ * Mapping details:
+ * <pre>
+ * MonitorMode.id == XRR mode-id (not index)
+ * MonitorDevice.id == XRR monitor-idx (not id)
+ * </pre>
+ */
+class RandR13 implements RandR {
+ private static final boolean DEBUG = ScreenDriver.DEBUG;
+
+ RandR13() {
+ }
+
+ @Override
+ public final VersionNumber getVersion() {
+ return version130;
+ }
+
+ @Override
+ public void dumpInfo(final long dpy, final int screen_idx) {
+ final long screenResources = getScreenResources0(dpy, screen_idx);
+ if(0 == screenResources) {
+ return;
+ }
+ try {
+ dumpInfo0(dpy, screen_idx, screenResources);
+ } finally {
+ freeScreenResources0(screenResources);
+ }
+ }
+
+ long sessionScreenResources = 0;
+ IntLongHashMap crtInfoHandleMap = null;
+
+ @Override
+ public boolean beginInitialQuery(final long dpy, final ScreenDriver screen) {
+ final int screen_idx = screen.getIndex();
+ sessionScreenResources = getScreenResources0(dpy, screen_idx);
+ if( 0 != sessionScreenResources ) {
+ crtInfoHandleMap = new IntLongHashMap();
+ crtInfoHandleMap.setKeyNotFoundValue(0);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void endInitialQuery(final long dpy, final ScreenDriver screen) {
+ if( null != crtInfoHandleMap ) {
+ for(final Iterator<IntLongHashMap.Entry> iter = crtInfoHandleMap.iterator(); iter.hasNext(); ) {
+ final IntLongHashMap.Entry entry = iter.next();
+ freeMonitorInfoHandle0(entry.value);
+ }
+ crtInfoHandleMap.clear();
+ crtInfoHandleMap = null;
+ }
+ if( 0 != sessionScreenResources ) {
+ freeScreenResources0( sessionScreenResources );
+ sessionScreenResources = 0;
+ }
+ }
+
+ private final long getScreenResourceHandle(final long dpy, final int screen_idx) {
+ if( 0 != sessionScreenResources ) {
+ return sessionScreenResources;
+ }
+ return getScreenResources0(dpy, screen_idx);
+ }
+ private final void releaseScreenResourceHandle(final long screenResourceHandle) {
+ if( 0 == sessionScreenResources ) {
+ freeScreenResources0( screenResourceHandle );
+ }
+ }
+
+ private final long getMonitorInfoHandle(final long dpy, final int screen_idx, final long screenResources, final int monitor_idx) {
+ if( null != crtInfoHandleMap ) {
+ long h = crtInfoHandleMap.get(monitor_idx);
+ if( 0 == h ) {
+ h = getMonitorInfoHandle0(dpy, screen_idx, screenResources, monitor_idx);
+ crtInfoHandleMap.put(monitor_idx, h);
+ }
+ return h;
+ } else {
+ return getMonitorInfoHandle0(dpy, screen_idx, screenResources, monitor_idx);
+ }
+ }
+ private final void releaseMonitorInfoHandle(final long monitorInfoHandle) {
+ if( null == crtInfoHandleMap ) {
+ freeMonitorInfoHandle0(monitorInfoHandle);
+ }
+ }
+
+ @Override
+ public int getMonitorDeviceCount(final long dpy, final ScreenDriver screen) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ return getMonitorDeviceCount0(screenResources);
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ try {
+ final int[] availRotations = getAvailableRotations0(monitorInfo);
+ if(null==availRotations || 0==availRotations.length) {
+ return null;
+ }
+ return availRotations;
+ } finally {
+ releaseMonitorInfoHandle(monitorInfo);
+ }
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ return getMonitorMode0(screenResources, mode_idx);
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, final MonitorModeProps.Cache cache, final int crt_idx) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ try {
+ return getMonitorDevice0(dpy, screenResources, monitorInfo, crt_idx);
+ } finally {
+ releaseMonitorInfoHandle(monitorInfo);
+ }
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ try {
+ return getMonitorViewport0(monitorInfo);
+ } finally {
+ releaseMonitorInfoHandle(monitorInfo);
+ }
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ try {
+ return getMonitorCurrentMode0(screenResources, monitorInfo);
+ } finally {
+ releaseMonitorInfoHandle(monitorInfo);
+ }
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, final MonitorDevice monitor, final MonitorMode mode) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ final boolean res;
+ try {
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, monitor.getId());
+ try {
+ res = setMonitorMode0(dpy, screenResources, monitorInfo, monitor.getId(), mode.getId(), mode.getRotation(),
+ -1, -1); // no fixed position!
+ } finally {
+ releaseMonitorInfoHandle(monitorInfo);
+ }
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ return res;
+ }
+
+ @Override
+ public final void updateScreenViewport(final long dpy, final ScreenDriver screen, final RectangleImmutable viewport) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ setScreenViewport0(dpy, screen_idx, screenResources, viewport.getX(), viewport.getY(), viewport.getWidth(), viewport.getHeight());
+ } finally {
+ dumpInfo0(dpy, screen_idx, screenResources);
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ private static native long getScreenResources0(long display, int screen_index);
+ private static native void freeScreenResources0(long screenResources);
+ private static native void dumpInfo0(long display, int screen_index, long screenResources);
+
+ private static native int getMonitorDeviceCount0(long screenResources);
+
+ private static native long getMonitorInfoHandle0(long display, int screen_index, long screenResources, int monitor_index);
+ private static native void freeMonitorInfoHandle0(long monitorInfoHandle);
+
+ private static native int[] getAvailableRotations0(long monitorInfo);
+ private static native int[] getMonitorViewport0(long monitorInfo);
+ private static native int[] getMonitorCurrentMode0(long monitorInfo);
+
+ private static native int[] getMonitorMode0(long screenResources, int mode_index);
+ private static native int[] getMonitorCurrentMode0(long screenResources, long monitorInfo);
+ private static native int[] getMonitorDevice0(long display, long screenResources, long monitorInfo, int monitor_idx);
+
+ private static native boolean setMonitorMode0(long display, long screenResources, long monitorInfo, int monitor_idx, int mode_id, int rotation, int x, int y);
+ private static native boolean setScreenViewport0(long display, int screen_index, long screenResources, int x, int y, int width, int height);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
index 10f6b84da..f7361740e 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,290 +29,241 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.x11;
+import java.util.ArrayList;
import java.util.List;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
import jogamp.nativewindow.x11.X11Util;
+import jogamp.newt.Debug;
import jogamp.newt.DisplayImpl;
+import jogamp.newt.MonitorModeProps;
import jogamp.newt.DisplayImpl.DisplayRunnable;
import jogamp.newt.ScreenImpl;
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
public class ScreenDriver extends ScreenImpl {
+ protected static final boolean DEBUG_TEST_RANDR13_DISABLED;
static {
+ Debug.initSingleton();
+ DEBUG_TEST_RANDR13_DISABLED = PropertyAccess.isPropertyDefined("newt.test.Screen.disableRandR13", true);
+
DisplayDriver.initSingleton();
}
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
+
public ScreenDriver() {
}
+ @Override
protected void createNativeImpl() {
// validate screen index
- Long handle = display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Long>() {
- public Long run(long dpy) {
- return new Long(GetScreen0(dpy, screen_idx));
- } } );
+ final Long handle = runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Long>() {
+ @Override
+ public Long run(final long dpy) {
+ return Long.valueOf(GetScreen0(dpy, screen_idx));
+ } } );
if (handle.longValue() == 0) {
throw new RuntimeException("Error creating screen: " + screen_idx);
- }
- aScreen = new X11GraphicsScreen((X11GraphicsDevice) getDisplay().getGraphicsDevice(), screen_idx);
+ }
+ final X11GraphicsDevice x11dev = (X11GraphicsDevice) getDisplay().getGraphicsDevice();
+ final long dpy = x11dev.getHandle();
+ aScreen = new X11GraphicsScreen(x11dev, screen_idx);
+ {
+ final int v[] = getRandRVersion0(dpy);
+ randrVersion = new VersionNumber(v[0], v[1], 0);
+ }
+ {
+ if( !DEBUG_TEST_RANDR13_DISABLED && randrVersion.compareTo(RandR.version130) >= 0 ) {
+ rAndR = new RandR13();
+ } else if( randrVersion.compareTo(RandR.version110) >= 0 ) {
+ rAndR = new RandR11();
+ } else {
+ rAndR = null;
+ }
+ }
+ if( DEBUG ) {
+ System.err.println("RandR "+randrVersion+", "+rAndR);
+ rAndR.dumpInfo(dpy, screen_idx);
+ }
}
+ @Override
protected void closeNativeImpl() {
}
- private int[] nrotations;
- private int nrotation_index;
- private int nres_number;
- private int nres_index;
- private int[] nrates;
- private int nrate_index;
- private int nmode_number;
+ private VersionNumber randrVersion;
+ private RandR rAndR;
- protected int[] getScreenModeFirstImpl() {
- return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<int[]>() {
- public int[] run(long dpy) {
- // initialize iterators and static data
- nrotations = getAvailableScreenModeRotations0(dpy, screen_idx);
- if(null==nrotations || 0==nrotations.length) {
- return null;
- }
- nrotation_index = 0;
-
- nres_number = getNumScreenModeResolutions0(dpy, screen_idx);
- if(0==nres_number) {
- return null;
- }
- nres_index = 0;
-
- nrates = getScreenModeRates0(dpy, screen_idx, nres_index);
- if(null==nrates || 0==nrates.length) {
- return null;
- }
- nrate_index = 0;
-
- nmode_number = 0;
-
- return getScreenModeNextImpl();
- } } );
- }
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(final MonitorModeProps.Cache cache) {
+ if( null == rAndR ) { return; }
+ final AbstractGraphicsDevice device = getDisplay().getGraphicsDevice();
+ device.lock();
+ try {
+ if( rAndR.beginInitialQuery(device.getHandle(), this) ) {
+ try {
+ final int crtCount = rAndR.getMonitorDeviceCount(device.getHandle(), this);
- protected int[] getScreenModeNextImpl() {
- // assemble: w x h x bpp x f x r
- return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<int[]>() {
- public int[] run(long dpy) {
- /**
- System.err.println("******** mode: "+nmode_number);
- System.err.println("rot "+nrotation_index);
- System.err.println("rate "+nrate_index);
- System.err.println("res "+nres_index); */
-
- int[] res = getScreenModeResolution0(dpy, screen_idx, nres_index);
- if(null==res || 0==res.length) {
- return null;
- }
- if(0>=res[0] || 0>=res[1]) {
- throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+nres_number);
- }
- int rate = nrates[nrate_index];
- if(0>=rate) {
- rate = default_sm_rate;
- if(DEBUG) {
- System.err.println("Invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length+", using default: "+default_sm_rate);
- }
- }
- int rotation = nrotations[nrotation_index];
-
- int[] props = new int[ 1 + ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL ];
- int i = 0;
- props[i++] = nres_index; // use resolution index, not unique for native -> ScreenMode
- props[i++] = 0; // set later for verification of iterator
- props[i++] = res[0]; // width
- props[i++] = res[1]; // height
- props[i++] = default_sm_bpp; // FIXME
- props[i++] = res[2]; // widthmm
- props[i++] = res[3]; // heightmm
- props[i++] = rate; // rate
- props[i++] = rotation;
- props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i - 1; // count without extra element
-
- nmode_number++;
-
- // iteration: r -> f -> bpp -> [w x h]
- nrotation_index++;
- if(nrotation_index == nrotations.length) {
- nrotation_index=0;
- nrate_index++;
- if(null == nrates || nrate_index == nrates.length){
- nres_index++;
- if(nres_index == nres_number) {
- // done
- nrates=null;
- nrotations=null;
- return null;
+ // Gather all available rotations
+ final ArrayHashSet<Integer> availableRotations = new ArrayHashSet<Integer>();
+ for(int i = 0; i < crtCount; i++) {
+ final int[] rotations = rAndR.getAvailableRotations(device.getHandle(), this, i);
+ if( null != rotations ) {
+ final List<Integer> rotationList = new ArrayList<Integer>(rotations.length);
+ for(int j=0; j<rotations.length; j++ ) { rotationList.add(rotations[j]); }
+ availableRotations.addAll(rotationList);
}
-
- nrates = getScreenModeRates0(dpy, screen_idx, nres_index);
- if(null==nrates || 0==nrates.length) {
- return null;
- }
- nrate_index = 0;
}
- }
-
- return props;
- } } );
- }
- protected ScreenMode getCurrentScreenModeImpl() {
- return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<ScreenMode>() {
- public ScreenMode run(long dpy) {
- long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
- if(0 == screenConfigHandle) {
- return null;
- }
- int[] res;
- int rate, rot;
- try {
- int resNumber = getNumScreenModeResolutions0(dpy, screen_idx);
- if(0==resNumber) {
- return null;
- }
-
- int resIdx = getCurrentScreenResolutionIndex0(screenConfigHandle);
- if(0>resIdx) {
- return null;
- }
- if(resIdx>=resNumber) {
- throw new RuntimeException("Invalid resolution index: ! "+resIdx+" < "+resNumber);
- }
- res = getScreenModeResolution0(dpy, screen_idx, resIdx);
- if(null==res || 0==res.length) {
- return null;
- }
- if(0>=res[0] || 0>=res[1]) {
- throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+resIdx+"/"+resNumber);
- }
- rate = getCurrentScreenRate0(screenConfigHandle);
- if(0>rate) {
- return null;
+ // collect all modes, while injecting all available rotations
+ {
+ int modeIdx = 0;
+ int[] props;
+ do {
+ props = rAndR.getMonitorModeProps(device.getHandle(), this, modeIdx++);
+ if( null != props ) {
+ for(int i = 0; i < availableRotations.size(); i++) {
+ props[MonitorModeProps.IDX_MONITOR_MODE_ROT] = availableRotations.get(i);
+ MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+ }
+ }
+ } while( null != props);
}
- rot = getCurrentScreenRotation0(screenConfigHandle);
- if(0>rot) {
- return null;
+ if( cache.monitorModes.size() > 0 ) {
+ for(int i = 0; i < crtCount; i++) {
+ final int[] monitorProps = rAndR.getMonitorDeviceProps(device.getHandle(), this, cache, i);
+ if( null != monitorProps &&
+ MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps[0] && // Enabled ? I.e. contains active modes ?
+ MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps.length ) {
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, monitorProps, 0);
+ }
+ }
}
} finally {
- freeScreenConfiguration0(screenConfigHandle);
+ rAndR.endInitialQuery(device.getHandle(), this);
}
- int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
- int i = 0;
- props[i++] = 0; // set later for verification of iterator
- props[i++] = res[0]; // width
- props[i++] = res[1]; // height
- props[i++] = default_sm_bpp; // FIXME
- props[i++] = res[2]; // widthmm
- props[i++] = res[3]; // heightmm
- props[i++] = rate; // rate
- props[i++] = rot;
- props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count
- return ScreenModeUtil.streamIn(props, 0);
- } } );
+ }
+ } finally {
+ device.unlock();
+ }
}
- protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) {
- final List<ScreenMode> screenModes = this.getScreenModesOrig();
- final int screenModeIdx = screenModes.indexOf(screenMode);
- if(0>screenModeIdx) {
- throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode);
+ @Override
+ protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final Rectangle viewportPU, final Rectangle viewportWU) {
+ final AbstractGraphicsDevice device = getDisplay().getGraphicsDevice();
+ device.lock();
+ try {
+ final int[] viewportProps = rAndR.getMonitorDeviceViewport(device.getHandle(), this, monitor.getId());
+ viewportPU.set(viewportProps[0], viewportProps[1], viewportProps[2], viewportProps[3]);
+ viewportWU.set(viewportProps[0], viewportProps[1], viewportProps[2], viewportProps[3]); // equal window-units and pixel-units
+ return true;
+ } finally {
+ device.unlock();
}
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ if( null == rAndR ) { return null; }
+
+ return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<MonitorMode>() {
+ @Override
+ public MonitorMode run(final long dpy) {
+ final int[] currentModeProps = rAndR.getCurrentMonitorModeProps(dpy, ScreenDriver.this, monitor.getId());
+ return MonitorModeProps.streamInMonitorMode(null, null, currentModeProps, 0);
+ } } );
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ if( null == rAndR ) { return false; }
+
final long t0 = System.currentTimeMillis();
- boolean done = runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
- public Boolean run(long dpy) {
- boolean done = false;
- long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
- if(0 == screenConfigHandle) {
- return Boolean.valueOf(done);
- }
- try {
- int resNumber = getNumScreenModeResolutions0(dpy, screen_idx);
- int resIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx);
- if(0>resIdx || resIdx>=resNumber) {
- throw new RuntimeException("Invalid resolution index: ! 0 < "+resIdx+" < "+resNumber+", screenMode["+screenModeIdx+"] "+screenMode);
- }
-
- final int f = screenMode.getMonitorMode().getRefreshRate();
- final int r = screenMode.getRotation();
-
- if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resIdx, f, r) ) {
- while(!done && System.currentTimeMillis()-t0 < SCREEN_MODE_CHANGE_TIMEOUT) {
- done = setCurrentScreenModePollEnd0(dpy, screen_idx, resIdx, f, r);
- if(!done) {
- try { Thread.sleep(10); } catch (InterruptedException e) { }
- }
- }
- }
- } finally {
- freeScreenConfiguration0(screenConfigHandle);
- }
- return Boolean.valueOf(done);
- }
+ final boolean done = runWithOptTempDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
+ @Override
+ public Boolean run(final long dpy) {
+ return Boolean.valueOf( rAndR.setCurrentMonitorMode(dpy, ScreenDriver.this, monitor, mode) );
+ }
}).booleanValue();
-
+
if(DEBUG || !done) {
- System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+
- (System.currentTimeMillis()-t0)+"ms; Current: "+getCurrentScreenMode()+"; Desired: "+screenMode);
+ System.err.println("X11Screen.setCurrentMonitorModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+
+ (System.currentTimeMillis()-t0)+"ms; "+monitor.getCurrentMode()+" -> "+mode);
}
return done;
}
- private class XineramaEnabledQuery implements DisplayImpl.DisplayRunnable<Boolean> {
- public Boolean run(long dpy) {
- return new Boolean(X11Util.XineramaIsEnabled(dpy));
- }
- }
- private XineramaEnabledQuery xineramaEnabledQuery = new XineramaEnabledQuery();
-
+ private final DisplayImpl.DisplayRunnable<Boolean> xineramaEnabledQueryWithTemp = new DisplayImpl.DisplayRunnable<Boolean>() {
+ @Override
+ public Boolean run(final long dpy) {
+ return Boolean.valueOf(X11Util.XineramaIsEnabled(dpy));
+ } };
+
+ @Override
protected int validateScreenIndex(final int idx) {
- if(getDisplay().isNativeValid()) {
- return runWithLockedDisplayHandle( xineramaEnabledQuery ).booleanValue() ? 0 : idx;
+ final DisplayDriver x11Display = (DisplayDriver) getDisplay();
+ final Boolean r = x11Display.isXineramaEnabled();
+ if( null != r ) {
+ return r.booleanValue() ? 0 : idx;
} else {
- return runWithTempDisplayHandle( xineramaEnabledQuery ).booleanValue() ? 0 : idx;
+ return runWithTempDisplayHandle( xineramaEnabledQueryWithTemp ).booleanValue() ? 0 : idx;
}
}
-
- protected void getVirtualScreenOriginAndSize(final Point virtualOrigin, final Dimension virtualSize) {
- display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Object>() {
- public Object run(long dpy) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(getWidth0(dpy, screen_idx));
- virtualSize.setHeight(getHeight0(dpy, screen_idx));
- return null;
- } } );
- }
-
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(final Rectangle viewport, final Rectangle viewportInWindowUnits) {
+ final RectangleImmutable ov = DEBUG ? (RectangleImmutable) getViewport().cloneMutable() : null;
+ /**
+ if( null != rAndR && rAndR.getVersion().compareTo(RandR.version130) >= 0 && getMonitorDevices().size()>0 ) {
+ super.calcVirtualScreenOriginAndSize(vOriginSize);
+ if( DEBUG ) {
+ System.err.println("X11Screen.calcVirtualScreenOriginAndSize: UpdatingViewport "+ov+" -> "+vOriginSize);
+ }
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ public Object run(long dpy) {
+ rAndR.updateScreenViewport(dpy, ScreenDriver.this, vOriginSize);
+ return null;
+ } } );
+ } else */ {
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(final long dpy) {
+ viewport.set(0, 0, getWidth0(dpy, screen_idx), getHeight0(dpy, screen_idx));
+ viewportInWindowUnits.set(viewport);
+ return null;
+ } } );
+ if( DEBUG ) {
+ System.err.println("X11Screen.calcVirtualScreenOriginAndSize: Querying X11: "+ov+" -> "+viewport);
+ }
+ }
+ }
+
//----------------------------------------------------------------------
// Internals only
- //
- private final <T> T runWithLockedDisplayHandle(DisplayRunnable<T> action) {
- return display.runWithLockedDisplayHandle(action);
- // return runWithTempDisplayHandle(action);
- // return runWithoutLock(action);
+ //
+ private final <T> T runWithLockedDisplayDevice(final DisplayRunnable<T> action) {
+ return display.runWithLockedDisplayDevice(action);
}
-
- private final <T> T runWithTempDisplayHandle(DisplayRunnable<T> action) {
- final long displayHandle = X11Util.openDisplay(display.getName());
+
+ private final <T> T runWithTempDisplayHandle(final DisplayRunnable<T> action) {
+ final long displayHandle = X11Util.openDisplay(display.getName());
if(0 == displayHandle) {
throw new RuntimeException("null device");
}
@@ -324,34 +275,20 @@ public class ScreenDriver extends ScreenImpl {
}
return res;
}
- private final <T> T runWithoutLock(DisplayRunnable<T> action) {
- return action.run(display.getHandle());
+
+ private final <T> T runWithOptTempDisplayHandle(final DisplayRunnable<T> action) {
+ if( null != rAndR && rAndR.getVersion().compareTo(RandR.version130) >= 0 ) {
+ return display.runWithLockedDisplayDevice(action);
+ } else {
+ return runWithTempDisplayHandle(action);
+ }
}
-
+
private static native long GetScreen0(long dpy, int scrn_idx);
private static native int getWidth0(long display, int scrn_idx);
private static native int getHeight0(long display, int scrn_idx);
- /** @return int[] { rot1, .. } */
- private static native int[] getAvailableScreenModeRotations0(long display, int screen_index);
-
- private static native int getNumScreenModeResolutions0(long display, int screen_index);
-
- /** @return int[] { width, height, widthmm, heightmm } */
- private static native int[] getScreenModeResolution0(long display, int screen_index, int mode_index);
-
- private static native int[] getScreenModeRates0(long display, int screen_index, int mode_index);
-
- private static native long getScreenConfiguration0(long display, int screen_index);
- private static native void freeScreenConfiguration0(long screenConfiguration);
-
- private static native int getCurrentScreenResolutionIndex0(long screenConfiguration);
- private static native int getCurrentScreenRate0(long screenConfiguration);
- private static native int getCurrentScreenRotation0(long screenConfiguration);
-
- /** needs own Display connection for XRANDR event handling */
- private static native boolean setCurrentScreenModeStart0(long display, int screen_index, long screenConfiguration, int mode_index, int freq, int rot);
- private static native boolean setCurrentScreenModePollEnd0(long display, int screen_index, int mode_index, int freq, int rot);
+ private static native int[] getRandRVersion0(long display);
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
index 97d1ae3db..afa9786e2 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,46 +29,91 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.x11;
+import java.nio.Buffer;
+
import jogamp.nativewindow.x11.X11Lib;
+import jogamp.nativewindow.x11.X11Util;
import jogamp.newt.DisplayImpl;
import jogamp.newt.DisplayImpl.DisplayRunnable;
+import jogamp.newt.PointerIconImpl;
import jogamp.newt.WindowImpl;
+import jogamp.newt.driver.PNGIcon;
+
import javax.media.nativewindow.*;
import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.MouseEvent;
public class WindowDriver extends WindowImpl {
private static final String WINDOW_CLASS_NAME = "NewtWindow";
- private static final int X11_WHEEL_ONE_UP_BUTTON = 4;
+ private static final int X11_WHEEL_ONE_UP_BUTTON = 4;
private static final int X11_WHEEL_ONE_DOWN_BUTTON = 5;
- private static final int X11_WHEEL_TWO_UP_BUTTON = 6;
+ private static final int X11_WHEEL_TWO_UP_BUTTON = 6;
private static final int X11_WHEEL_TWO_DOWN_BUTTON = 7;
-
+
+ private static final int defaultIconDataSize;
+ private static final Buffer defaultIconData;
+
static {
- DisplayDriver.initSingleton();
+ ScreenDriver.initSingleton();
+
+ int _icon_data_size=0, _icon_elem_bytesize=0;
+ Buffer _icon_data=null;
+ if( PNGIcon.isAvailable() ) {
+ try {
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
+ final int[] data_size = { 0 }, elem_bytesize = { 0 };
+ _icon_data = PNGIcon.arrayToX11BGRAImages(NewtFactory.getWindowIcons(), data_size, elem_bytesize);
+ _icon_data_size = data_size[0];
+ _icon_elem_bytesize = elem_bytesize[0];
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ defaultIconDataSize = _icon_data_size;
+ defaultIconData = _icon_data;
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Def. Icon: data_size "+defaultIconDataSize+" * elem_size "+_icon_elem_bytesize+" = data "+defaultIconData);
+ }
}
public WindowDriver() {
}
+ @Override
protected void createNativeImpl() {
final ScreenDriver screen = (ScreenDriver) getScreen();
final DisplayDriver display = (DisplayDriver) screen.getDisplay();
+ final AbstractGraphicsDevice edtDevice = display.getGraphicsDevice();
+
+ // Decoupled X11 Device/Screen allowing X11 display lock-free off-thread rendering
+ final long renderDeviceHandle = X11Util.openDisplay(edtDevice.getConnection());
+ if( 0 == renderDeviceHandle ) {
+ throw new RuntimeException("Error creating display(GfxCfg/Render): "+edtDevice.getConnection());
+ }
+ renderDevice = new X11GraphicsDevice(renderDeviceHandle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
+ final AbstractGraphicsScreen renderScreen = new X11GraphicsScreen(renderDevice, screen.getIndex());
+
final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested);
final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
+ capsRequested, capsRequested, capabilitiesChooser, renderScreen, VisualIDHolder.VID_UNDEFINED);
if(DEBUG_IMPLEMENTATION) {
System.err.println("X11Window.createNativeImpl() factory: "+factory+", chosen config: "+cfg);
- }
+ }
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
@@ -77,115 +122,231 @@ public class WindowDriver extends WindowImpl {
throw new NativeWindowException("Chosen Configuration w/o native visual ID: "+cfg);
}
setGraphicsConfiguration(cfg);
- final int flags = getReconfigureFlags(0, true) &
- ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
- setWindowHandle(CreateWindow0(getParentWindowHandle(),
- display.getEDTHandle(), screen.getIndex(), visualID,
- display.getJavaObjectAtom(), display.getWindowDeleteAtom(),
- getX(), getY(), getWidth(), getHeight(), autoPosition(), flags));
+ final int flags = getReconfigureFlags(0, true) &
+ ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
+ edtDevice.lock();
+ try {
+ setWindowHandle(CreateWindow(getParentWindowHandle(),
+ edtDevice.getHandle(), screen.getIndex(), visualID,
+ display.getJavaObjectAtom(), display.getWindowDeleteAtom(),
+ getX(), getY(), getWidth(), getHeight(), autoPosition(), flags,
+ defaultIconDataSize, defaultIconData));
+ } finally {
+ edtDevice.unlock();
+ }
windowHandleClose = getWindowHandle();
if (0 == windowHandleClose) {
throw new NativeWindowException("Error creating window");
}
}
+ @Override
protected void closeNativeImpl() {
if(0!=windowHandleClose && null!=getScreen() ) {
- DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ final AbstractGraphicsDevice edtDevice = display.getGraphicsDevice();
+ edtDevice.lock();
try {
- CloseWindow0(display.getEDTHandle(), windowHandleClose,
- display.getJavaObjectAtom(), display.getWindowDeleteAtom());
- } catch (Throwable t) {
- if(DEBUG_IMPLEMENTATION) {
- Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
+ CloseWindow0(edtDevice.getHandle(), windowHandleClose,
+ display.getJavaObjectAtom(), display.getWindowDeleteAtom() /* , display.getKbdHandle() */); // XKB disabled for now
+ } catch (final Throwable t) {
+ if(DEBUG_IMPLEMENTATION) {
+ final Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
e.printStackTrace();
}
} finally {
+ edtDevice.unlock();
windowHandleClose = 0;
}
}
+ if(null != renderDevice) {
+ renderDevice.close(); // closes X11 display
+ renderDevice = null;
+ }
}
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+ /**
+ * <p>
+ * X11 Window supports {@link #FLAG_IS_FULLSCREEN_SPAN}
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean isReconfigureFlagSupported(final int changeFlags) {
+ return true; // all flags!
+ }
+
+ @Override
+ protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, int flags) {
+ final int _x, _y;
+ final InsetsImmutable _insets;
+ if( 0 == ( FLAG_IS_UNDECORATED & flags) ) {
+ // client position -> top-level window position
+ _insets = getInsets();
+ _x = x - _insets.getLeftWidth() ;
+ _y = y - _insets.getTopHeight() ;
+ } else {
+ _insets = null;
+ _x = x;
+ _y = y;
+ }
if(DEBUG_IMPLEMENTATION) {
- System.err.println("X11Window reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
- getReconfigureFlagsAsString(null, flags));
+ System.err.println("X11Window reconfig: "+x+"/"+y+" -> "+_x+"/"+_y+" "+width+"x"+height+", insets "+_insets+", "+ getReconfigureFlagsAsString(null, flags));
}
- if(0 == ( FLAG_IS_UNDECORATED & flags)) {
- final InsetsImmutable i = getInsets();
-
- // client position -> top-level window position
- x -= i.getLeftWidth() ;
- y -= i.getTopHeight() ;
+ if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags ) ) {
+ if( 0 != ( FLAG_IS_FULLSCREEN & flags) && 0 == ( FLAG_IS_ALWAYSONTOP & flags) ) {
+ tempFSAlwaysOnTop = true;
+ flags |= FLAG_IS_ALWAYSONTOP;
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("X11Window reconfig.2: temporary "+getReconfigureFlagsAsString(null, flags));
+ }
+ } else {
+ tempFSAlwaysOnTop = false;
+ }
}
+ final int fflags = flags;
final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
- reconfigureWindow0( getDisplayEDTHandle(), getScreenIndex(),
- getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
- x, y, width, height, flags);
-
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(final long dpy) {
+ reconfigureWindow0( dpy, getScreenIndex(),
+ getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
+ _x, _y, width, height, fflags);
+ return null;
+ }
+ });
return true;
}
+ volatile boolean tempFSAlwaysOnTop = false;
+
+ /**
+ * <p>
+ * Deal w/ tempAlwaysOnTop.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ protected void focusChanged(final boolean defer, final boolean focusGained) {
+ if( isNativeValid() && isFullscreen() && tempFSAlwaysOnTop && hasFocus() != focusGained ) {
+ final int flags = getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()) | ( focusGained ? FLAG_IS_ALWAYSONTOP : 0 );
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("X11Window reconfig.3 (focus): temporary "+getReconfigureFlagsAsString(null, flags));
+ }
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(final long dpy) {
+ reconfigureWindow0( dpy, getScreenIndex(),
+ getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
+ getX(), getY(), getWidth(), getHeight(), flags);
+ return null;
+ }
+ });
+ }
+ super.focusChanged(defer, focusGained);
+ }
- protected void reparentNotify(long newParentWindowHandle) {
+ protected void reparentNotify(final long newParentWindowHandle) {
if(DEBUG_IMPLEMENTATION) {
final long p0 = getParentWindowHandle();
System.err.println("Window.reparentNotify ("+getThreadName()+"): "+toHexString(p0)+" -> "+toHexString(newParentWindowHandle));
}
}
-
- protected void requestFocusImpl(boolean force) {
- requestFocus0(getDisplayEDTHandle(), getWindowHandle(), force);
+
+ @Override
+ protected void requestFocusImpl(final boolean force) {
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(final long dpy) {
+ requestFocus0(dpy, getWindowHandle(), force);
+ return null;
+ }
+ });
}
@Override
protected void setTitleImpl(final String title) {
- runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Object>() {
- public Object run(long dpy) {
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(final long dpy) {
setTitle0(dpy, getWindowHandle(), title);
return null;
}
});
}
-
+
+ @Override
+ protected void setPointerIconImpl(final PointerIconImpl pi) {
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(final long dpy) {
+ try {
+ setPointerIcon0(dpy, getWindowHandle(), null != pi ? pi.validatedHandle() : 0);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ });
+ }
+
@Override
protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
- return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
- public Boolean run(long dpy) {
- return Boolean.valueOf(setPointerVisible0(getDisplayEDTHandle(), getWindowHandle(), pointerVisible));
+ return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Boolean>() {
+ @Override
+ public Boolean run(final long dpy) {
+ final PointerIconImpl pi = (PointerIconImpl)getPointerIcon();
+ final boolean res;
+ if( pointerVisible && null != pi ) {
+ setPointerIcon0(dpy, getWindowHandle(), pi.validatedHandle());
+ res = true;
+ } else {
+ res = setPointerVisible0(dpy, getWindowHandle(), pointerVisible);
+ }
+ return Boolean.valueOf(res);
}
}).booleanValue();
}
@Override
protected boolean confinePointerImpl(final boolean confine) {
- return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
- public Boolean run(long dpy) {
- return Boolean.valueOf(confinePointer0(getDisplayEDTHandle(), getWindowHandle(), confine));
+ return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Boolean>() {
+ @Override
+ public Boolean run(final long dpy) {
+ return Boolean.valueOf(confinePointer0(dpy, getWindowHandle(), confine));
}
}).booleanValue();
}
-
+
@Override
protected void warpPointerImpl(final int x, final int y) {
- runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Object>() {
- public Object run(long dpy) {
- warpPointer0(getDisplayEDTHandle(), getWindowHandle(), x, y);
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(final long dpy) {
+ warpPointer0(dpy, getWindowHandle(), x, y);
return null;
}
});
}
-
+
+ @Override
protected Point getLocationOnScreenImpl(final int x, final int y) {
- // X11Util.GetRelativeLocation: locks display already !
- return X11Lib.GetRelativeLocation( getScreen().getDisplay().getHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
+ return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Point>() {
+ @Override
+ public Point run(final long dpy) {
+ return X11Lib.GetRelativeLocation(dpy, getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
+ }
+ } );
}
- protected void updateInsetsImpl(Insets insets) {
- // nop - using event driven insetsChange(..)
+ @Override
+ protected void updateInsetsImpl(final Insets insets) {
+ // nop - using event driven insetsChange(..)
}
-
- protected void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers,
- int x, int y, int button, int rotation) {
+
+ @Override
+ protected final void doMouseEvent(final boolean enqueue, final boolean wait, short eventType, int modifiers,
+ final int x, final int y, short button, final float[] rotationXYZ, final float rotationScale) {
switch(eventType) {
case MouseEvent.EVENT_MOUSE_PRESSED:
switch(button) {
@@ -198,64 +359,111 @@ public class WindowDriver extends WindowImpl {
}
break;
case MouseEvent.EVENT_MOUSE_RELEASED:
+ final boolean shiftPressed = 0 != ( modifiers & InputEvent.SHIFT_MASK );
switch(button) {
- case X11_WHEEL_ONE_UP_BUTTON:
+ case X11_WHEEL_ONE_UP_BUTTON: // vertical scroll up
eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
button = 1;
- rotation = 1;
+ rotationXYZ[shiftPressed ? 0 : 1] = 1;
break;
- case X11_WHEEL_ONE_DOWN_BUTTON:
+ case X11_WHEEL_ONE_DOWN_BUTTON: // vertical scroll down
eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
button = 1;
- rotation = -1;
+ rotationXYZ[shiftPressed ? 0 : 1] = -1;
break;
- case X11_WHEEL_TWO_UP_BUTTON:
+ case X11_WHEEL_TWO_UP_BUTTON: // horizontal scroll left
eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
- button = 2;
- rotation = 1;
+ button = 1;
+ rotationXYZ[0] = 1;
+ modifiers |= InputEvent.SHIFT_MASK;
break;
- case X11_WHEEL_TWO_DOWN_BUTTON:
+ case X11_WHEEL_TWO_DOWN_BUTTON: // horizontal scroll right
eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
- button = 2;
- rotation = -1;
+ button = 1;
+ rotationXYZ[0] = -1;
+ modifiers |= InputEvent.SHIFT_MASK;
break;
- }
+ }
break;
}
- super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotation);
+ super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
}
-
-
+
+ /** Called by native TK */
+ protected final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar0, final String keyString) {
+ // handleKeyEvent(true, false, eventType, modifiers, keyCode, keyChar);
+ final boolean isModifierKey = KeyEvent.isModifierKey(keyCode);
+ final boolean isAutoRepeat = 0 != ( InputEvent.AUTOREPEAT_MASK & modifiers );
+ final char keyChar = ( null != keyString ) ? keyString.charAt(0) : keyChar0;
+ // System.err.println("*** sendKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar0+">/<"+keyChar+">, keyString "+keyString+", mods "+toHexString(modifiers)+
+ // ", isKeyCodeTracked "+isKeyCodeTracked(keyCode)+", was: pressed "+isKeyPressed(keyCode)+", repeat "+isAutoRepeat+", [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis());
+
+ if( !isAutoRepeat || !isModifierKey ) { // ! ( isModifierKey && isAutoRepeat )
+ switch(eventType) {
+ case KeyEvent.EVENT_KEY_PRESSED:
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar);
+ break;
+
+ case KeyEvent.EVENT_KEY_RELEASED:
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+ }
+ @Override
+ public final void enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+ }
+
//----------------------------------------------------------------------
// Internals only
//
-
private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI
private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
-
- private final long getDisplayEDTHandle() {
- return ((DisplayDriver) getScreen().getDisplay()).getEDTHandle();
- }
- private final <T> T runWithLockedDisplayHandle(DisplayRunnable<T> action) {
- return ((DisplayImpl) getScreen().getDisplay()).runWithLockedDisplayHandle(action);
- // return runWithTempDisplayHandle(action);
+
+ private final <T> T runWithLockedDisplayDevice(final DisplayRunnable<T> action) {
+ return ((DisplayDriver) getScreen().getDisplay()).runWithLockedDisplayDevice(action);
}
protected static native boolean initIDs0();
-
- private native long CreateWindow0(long parentWindowHandle, long display, int screen_index,
- int visualID, long javaObjectAtom, long windowDeleteAtom,
- int x, int y, int width, int height, boolean autoPosition, int flags);
- private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom);
+
+ private long CreateWindow(final long parentWindowHandle, final long display, final int screen_index,
+ final int visualID, final long javaObjectAtom, final long windowDeleteAtom,
+ final int x, final int y, final int width, final int height, final boolean autoPosition, final int flags,
+ final int pixelDataSize, final Buffer pixels) {
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
+ if( !Buffers.isDirect(pixels) ) {
+ throw new IllegalArgumentException("data buffer is not direct "+pixels);
+ }
+ return CreateWindow0(parentWindowHandle, display, screen_index,
+ visualID, javaObjectAtom, windowDeleteAtom,
+ x, y, width, height, autoPosition, flags,
+ pixelDataSize,
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */);
+ }
+ private native long CreateWindow0(long parentWindowHandle, long display, int screen_index,
+ int visualID, long javaObjectAtom, long windowDeleteAtom,
+ int x, int y, int width, int height, boolean autoPosition, int flags,
+ int pixelDataSize, Object pixels, int pixels_byte_offset, boolean pixels_is_direct);
+ private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle*/ ); // XKB disabled for now
private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle,
- long windowDeleteAtom, int x, int y, int width, int height, int flags);
+ long windowDeleteAtom, int x, int y, int width, int height, int flags);
private native void requestFocus0(long display, long windowHandle, boolean force);
-
+
private static native void setTitle0(long display, long windowHandle, String title);
+
+ private static native void setPointerIcon0(long display, long windowHandle, long handle);
+
private static native long getParentWindow0(long display, long windowHandle);
private static native boolean setPointerVisible0(long display, long windowHandle, boolean visible);
private static native boolean confinePointer0(long display, long windowHandle, boolean grab);
private static native void warpPointer0(long display, long windowHandle, int x, int y);
-
+
private long windowHandleClose;
+ private X11GraphicsDevice renderDevice;
}
diff --git a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java
index 93d5e2fb9..2bdab2796 100644
--- a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java
+++ b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.newt.event;
import com.jogamp.newt.event.NEWTEvent;
@@ -35,18 +35,18 @@ import com.jogamp.newt.event.NEWTEvent;
* which notifies after sending the event for the <code>invokeAndWait()</code> semantics.
*/
public class NEWTEventTask {
- private NEWTEvent event;
- private Object notifyObject;
+ private final NEWTEvent event;
+ private final Object notifyObject;
private RuntimeException exception;
- public NEWTEventTask(NEWTEvent event, Object notifyObject) {
+ public NEWTEventTask(final NEWTEvent event, final Object notifyObject) {
this.event = event ;
this.notifyObject = notifyObject ;
this.exception = null;
}
public final NEWTEvent get() { return event; }
- public final void setException(RuntimeException e) { exception = e; }
+ public final void setException(final RuntimeException e) { exception = e; }
public final RuntimeException getException() { return exception; }
public final boolean isCallerWaiting() { return null != notifyObject; }
diff --git a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
new file mode 100644
index 000000000..794e989a6
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
@@ -0,0 +1,370 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.newt.swt;
+
+import javax.media.nativewindow.NativeWindowException;
+
+import jogamp.newt.Debug;
+
+import com.jogamp.common.util.RunnableTask;
+import com.jogamp.newt.util.EDTUtil;
+
+/**
+ * Simple {@link EDTUtil} implementation utilizing the SWT UI thread
+ * of the given {@link Display}.
+ */
+public class SWTEDTUtil implements EDTUtil {
+ public static final boolean DEBUG = Debug.debug("EDT");
+
+ private final Object edtLock = new Object(); // locking the EDT start/stop state
+ private final ThreadGroup threadGroup;
+ private final String name;
+ private final Runnable dispatchMessages;
+ private final org.eclipse.swt.widgets.Display swtDisplay;
+ private NEDT nedt = null;
+ private int start_iter=0;
+ private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
+
+ public SWTEDTUtil(final com.jogamp.newt.Display newtDisplay, final org.eclipse.swt.widgets.Display swtDisplay) {
+ this.threadGroup = Thread.currentThread().getThreadGroup();
+ this.name=Thread.currentThread().getName()+"-SWTDisplay-"+newtDisplay.getFQName()+"-EDT-";
+ this.dispatchMessages = new Runnable() {
+ @Override
+ public void run() {
+ ((jogamp.newt.DisplayImpl) newtDisplay).dispatchMessages();
+ } };
+ this.swtDisplay = swtDisplay;
+ this.nedt = new NEDT(threadGroup, name);
+ this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+
+ public final org.eclipse.swt.widgets.Display getDisplay() {
+ return swtDisplay;
+ }
+
+ @Override
+ public long getPollPeriod() {
+ return pollPeriod;
+ }
+
+ @Override
+ public void setPollPeriod(final long ms) {
+ pollPeriod = ms; // writing to static field is intended
+ }
+
+ @Override
+ public final void start() throws IllegalStateException {
+ final boolean swtDisposed = swtDisplay.isDisposed();
+ synchronized(edtLock) {
+ if( nedt.isRunning() ) {
+ final Thread curT = Thread.currentThread();
+ final String swtTName;
+ final Thread swtT;
+ if( !swtDisposed ) {
+ swtT = swtDisplay.getThread();
+ swtTName = swtT.getName();
+ } else {
+ swtT = null;
+ swtTName = null;
+ }
+ final boolean onSWTEDT = swtT == curT;
+ throw new IllegalStateException("EDT still running and not subject to stop. Curr "+curT.getName()+
+ ", NEDT "+nedt.getName()+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", SWT-EDT "+swtTName+", on SWT-EDT "+onSWTEDT);
+ }
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": SWT-EDT reset - edt: "+nedt+", swtDisposed (skipping) "+swtDisposed);
+ }
+ if( !swtDisposed ) {
+ if( nedt.getState() != Thread.State.NEW ) {
+ nedt = new NEDT(threadGroup, name);
+ nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+ startImpl();
+ }
+ }
+ if( !swtDisposed ) {
+ if( !nedt.isRunning() ) {
+ throw new RuntimeException("EDT could not be started: "+nedt);
+ }
+ } else {
+ // FIXME: Throw exception ?
+ }
+ }
+
+ private final void startImpl() {
+ if(nedt.isAlive()) {
+ throw new RuntimeException("SWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", edt: "+nedt);
+ }
+ start_iter++;
+ nedt.setName(name+start_iter);
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": SWT-EDT START - edt: "+nedt);
+ // Thread.dumpStack();
+ }
+ nedt.start();
+ }
+
+ @Override
+ public boolean isCurrentThreadEDT() {
+ return !swtDisplay.isDisposed() && swtDisplay.getThread() == Thread.currentThread();
+ }
+
+ @Override
+ public final boolean isCurrentThreadNEDT() {
+ return nedt == Thread.currentThread();
+ }
+
+ @Override
+ public final boolean isCurrentThreadEDTorNEDT() {
+ final Thread ct = Thread.currentThread();
+ return ( !swtDisplay.isDisposed() && ct == swtDisplay.getThread() ) || ct == nedt ;
+ }
+
+ @Override
+ public boolean isRunning() {
+ return nedt.isRunning();
+ }
+
+ @Override
+ public final boolean invokeStop(final boolean wait, final Runnable task) {
+ return invokeImpl(wait, task, true);
+ }
+
+ @Override
+ public final boolean invoke(final boolean wait, final Runnable task) {
+ return invokeImpl(wait, task, false);
+ }
+
+ private final boolean invokeImpl(boolean wait, final Runnable task, boolean stop) {
+ Throwable throwable = null;
+ RunnableTask rTask = null;
+ final Object rTaskLock = new Object();
+ synchronized(rTaskLock) { // lock the optional task execution
+ synchronized(edtLock) { // lock the EDT status
+ if( nedt.shouldStop ) {
+ // drop task ..
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT about (1) to stop, won't enqueue new task: "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop);
+ Thread.dumpStack();
+ }
+ return false;
+ }
+ if( swtDisplay.isDisposed() ) {
+ stop = true;
+ }
+
+ if( isCurrentThreadEDT() ) {
+ if(null != task) {
+ task.run();
+ }
+ wait = false; // running in same thread (EDT) -> no wait
+ if( stop ) {
+ nedt.shouldStop = true;
+ }
+ } else {
+ if( !nedt.isRunning && !swtDisplay.isDisposed() ) {
+ if( null != task ) {
+ if( stop ) {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT is about (3) to stop and stopped already, dropping task. NEDT "+nedt);
+ } else {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT is not running, dropping task. NEDT "+nedt);
+ }
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ }
+ return false;
+ } else if( stop ) {
+ if( nedt.isRunning ) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": SWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop);
+ }
+ synchronized(nedt.sync) {
+ nedt.shouldStop = true;
+ nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
+ }
+ }
+ if( swtDisplay.isDisposed() ) {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT is about (3) to stop and stopped already, dropping task. "+nedt);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ return false;
+ }
+ }
+
+ if( null != task ) {
+ rTask = new RunnableTask(task,
+ wait ? rTaskLock : null,
+ true /* always catch and report Exceptions, don't disturb EDT */,
+ wait ? null : System.err);
+ swtDisplay.asyncExec(rTask);
+ }
+ }
+ }
+ if( wait ) {
+ try {
+ rTaskLock.wait(); // free lock, allow execution of rTask
+ } catch (final InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rTask.getThrowable();
+ }
+ if(null!=throwable) {
+ if(throwable instanceof NativeWindowException) {
+ throw (NativeWindowException)throwable;
+ }
+ throw new RuntimeException(throwable);
+ }
+ }
+ return true;
+ }
+ }
+
+ @Override
+ final public boolean waitUntilIdle() {
+ final NEDT _nedt;
+ synchronized(edtLock) {
+ _nedt = nedt;
+ }
+ final Thread ct = Thread.currentThread();
+ if( !_nedt.isRunning || _nedt == ct || swtDisplay.isDisposed() || swtDisplay.getThread() == ct ) {
+ return false;
+ }
+ try {
+ swtDisplay.syncExec(new Runnable() {
+ @Override
+ public void run() { }
+ });
+ } catch (final Exception e) { }
+ return true;
+ }
+
+ @Override
+ final public boolean waitUntilStopped() {
+ synchronized(edtLock) {
+ final Thread curT = Thread.currentThread();
+ final Thread swtT = !swtDisplay.isDisposed() ? swtDisplay.getThread() : null;
+ final boolean onSWTEDT = swtT == curT;
+ if( nedt.isRunning && nedt != curT && !onSWTEDT ) {
+ while( nedt.isRunning ) {
+ try {
+ edtLock.wait();
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ class NEDT extends Thread {
+ volatile boolean shouldStop = false;
+ volatile boolean isRunning = false;
+ Object sync = new Object();
+
+ public NEDT(final ThreadGroup tg, final String name) {
+ super(tg, name);
+ }
+
+ final public boolean isRunning() {
+ return isRunning && !shouldStop;
+ }
+
+ @Override
+ final public void start() throws IllegalThreadStateException {
+ isRunning = true;
+ super.start();
+ }
+
+ /**
+ * Utilizing locking only on tasks and its execution,
+ * not for event dispatching.
+ */
+ @Override
+ final public void run() {
+ if(DEBUG) {
+ System.err.println(getName()+": SWT-EDT run() START "+ getName());
+ }
+ RuntimeException error = null;
+ try {
+ do {
+ // event dispatch
+ if(!shouldStop) {
+ // EDT invoke thread is SWT-EDT,
+ // hence dispatching is required to run on SWT-EDT as well.
+ // Otherwise a deadlock may happen due to dispatched event's
+ // triggering a locking action.
+ if ( !swtDisplay.isDisposed() ) {
+ swtDisplay.syncExec(dispatchMessages);
+ } else {
+ dispatchMessages.run();
+ }
+ }
+ // wait
+ synchronized(sync) {
+ if(!shouldStop) {
+ try {
+ sync.wait(pollPeriod);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } while(!shouldStop) ;
+ } catch (final Throwable t) {
+ // handle errors ..
+ shouldStop = true;
+ if(t instanceof RuntimeException) {
+ error = (RuntimeException) t;
+ } else {
+ error = new RuntimeException("Within SWT-EDT", t);
+ }
+ } finally {
+ if(DEBUG) {
+ System.err.println(getName()+": SWT-EDT run() END "+ getName()+", "+error);
+ }
+ synchronized(edtLock) {
+ isRunning = false;
+ edtLock.notifyAll();
+ }
+ if(DEBUG) {
+ System.err.println(getName()+": SWT-EDT run() EXIT "+ getName()+", exception: "+error);
+ }
+ if(null!=error) {
+ throw error;
+ }
+ } // finally
+ } // run()
+ } // EventDispatchThread
+
+}
diff --git a/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java b/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
new file mode 100644
index 000000000..a989345dd
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
@@ -0,0 +1,396 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.newt.swt.event;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeSurfaceHolder;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.MouseEvent;
+
+/**
+ * SWT event translator to NEWT, inclusive dispatch listener.
+ * <p>
+ * <b>Disclaimer:</b> This code is merely tested and subject to change.
+ * </p>
+ */
+public class SWTNewtEventFactory {
+
+ public static final short eventTypeSWT2NEWT(final int swtType) {
+ switch( swtType ) {
+ // case SWT.MouseXXX: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED;
+ case SWT.MouseDown: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED;
+ case SWT.MouseUp: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED;
+ case SWT.MouseMove: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED;
+ case SWT.MouseEnter: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED;
+ case SWT.MouseExit: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED;
+ // case SWT.MouseXXX: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED;
+ case SWT.MouseVerticalWheel: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+
+ case SWT.KeyDown: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
+ case SWT.KeyUp: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
+ }
+ return (short)0;
+ }
+
+ public static final int swtModifiers2Newt(final int awtMods, final boolean mouseHint) {
+ int newtMods = 0;
+ if ((awtMods & SWT.SHIFT) != 0) newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+ if ((awtMods & SWT.CTRL) != 0) newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK;
+ if ((awtMods & SWT.ALT) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
+ return newtMods;
+ }
+
+ public static short swtKeyCode2NewtKeyCode(final int swtKeyCode) {
+ final short defNEWTKeyCode = (short)swtKeyCode;
+ switch (swtKeyCode) {
+ case SWT.HOME : return com.jogamp.newt.event.KeyEvent.VK_HOME;
+ case SWT.END : return com.jogamp.newt.event.KeyEvent.VK_END;
+ case SWT.PRINT_SCREEN : return com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN;
+ case SWT.BS : return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
+ case SWT.TAB : return com.jogamp.newt.event.KeyEvent.VK_TAB;
+ case SWT.LF : return com.jogamp.newt.event.KeyEvent.VK_ENTER;
+ case SWT.PAGE_DOWN : return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN;
+ case SWT.PAGE_UP : return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP;
+ case SWT.CONTROL : return com.jogamp.newt.event.KeyEvent.VK_CONTROL;
+ case SWT.CAPS_LOCK : return com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK;
+ case SWT.PAUSE : return com.jogamp.newt.event.KeyEvent.VK_PAUSE;
+ case SWT.SCROLL_LOCK : return com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK;
+ case SWT.CANCEL : return com.jogamp.newt.event.KeyEvent.VK_CANCEL;
+ case SWT.INSERT : return com.jogamp.newt.event.KeyEvent.VK_INSERT;
+ case SWT.ESC : return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
+ case SWT.SPACE : return com.jogamp.newt.event.KeyEvent.VK_SPACE;
+ case SWT.F1 : return com.jogamp.newt.event.KeyEvent.VK_F1;
+ case SWT.F2 : return com.jogamp.newt.event.KeyEvent.VK_F2;
+ case SWT.F3 : return com.jogamp.newt.event.KeyEvent.VK_F3;
+ case SWT.F4 : return com.jogamp.newt.event.KeyEvent.VK_F4;
+ case SWT.F5 : return com.jogamp.newt.event.KeyEvent.VK_F5;
+ case SWT.F6 : return com.jogamp.newt.event.KeyEvent.VK_F6;
+ case SWT.F7 : return com.jogamp.newt.event.KeyEvent.VK_F7;
+ case SWT.F8 : return com.jogamp.newt.event.KeyEvent.VK_F8;
+ case SWT.F9 : return com.jogamp.newt.event.KeyEvent.VK_F9;
+ case SWT.F10 : return com.jogamp.newt.event.KeyEvent.VK_F10;
+ case SWT.F11 : return com.jogamp.newt.event.KeyEvent.VK_F11;
+ case SWT.F12 : return com.jogamp.newt.event.KeyEvent.VK_F12;
+ case SWT.F13 : return com.jogamp.newt.event.KeyEvent.VK_F13;
+ case SWT.F14 : return com.jogamp.newt.event.KeyEvent.VK_F14;
+ case SWT.F15 : return com.jogamp.newt.event.KeyEvent.VK_F15;
+ case SWT.F16 : return com.jogamp.newt.event.KeyEvent.VK_F16;
+ case SWT.F17 : return com.jogamp.newt.event.KeyEvent.VK_F17;
+ case SWT.F18 : return com.jogamp.newt.event.KeyEvent.VK_F18;
+ case SWT.F19 : return com.jogamp.newt.event.KeyEvent.VK_F19;
+ case SWT.F20 : return com.jogamp.newt.event.KeyEvent.VK_F20;
+ case SWT.DEL : return com.jogamp.newt.event.KeyEvent.VK_DELETE;
+ case SWT.KEYPAD_0 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD0;
+ case SWT.KEYPAD_1 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD1;
+ case SWT.KEYPAD_2 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD2;
+ case SWT.KEYPAD_3 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD3;
+ case SWT.KEYPAD_4 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD4;
+ case SWT.KEYPAD_5 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD5;
+ case SWT.KEYPAD_6 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD6;
+ case SWT.KEYPAD_7 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD7;
+ case SWT.KEYPAD_8 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD8;
+ case SWT.KEYPAD_9 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD9;
+ case SWT.KEYPAD_DECIMAL: return com.jogamp.newt.event.KeyEvent.VK_DECIMAL;
+ case SWT.KEYPAD_ADD : return com.jogamp.newt.event.KeyEvent.VK_ADD;
+ case SWT.KEYPAD_SUBTRACT: return com.jogamp.newt.event.KeyEvent.VK_SUBTRACT;
+ case SWT.KEYPAD_MULTIPLY: return com.jogamp.newt.event.KeyEvent.VK_MULTIPLY;
+ case SWT.KEYPAD_DIVIDE : return com.jogamp.newt.event.KeyEvent.VK_DIVIDE;
+ case SWT.NUM_LOCK : return com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK;
+ case SWT.ARROW_LEFT : return com.jogamp.newt.event.KeyEvent.VK_LEFT;
+ case SWT.ARROW_UP : return com.jogamp.newt.event.KeyEvent.VK_UP;
+ case SWT.ARROW_RIGHT : return com.jogamp.newt.event.KeyEvent.VK_RIGHT;
+ case SWT.ARROW_DOWN : return com.jogamp.newt.event.KeyEvent.VK_DOWN;
+ case SWT.HELP : return com.jogamp.newt.event.KeyEvent.VK_HELP;
+ }
+ return defNEWTKeyCode;
+ }
+
+ public static int newtKeyCode2SWTKeyCode(final short newtKeyCode) {
+ final int defSWTKeyCode = 0xFFFF & newtKeyCode;
+ switch (newtKeyCode) {
+ case com.jogamp.newt.event.KeyEvent.VK_HOME : return SWT.HOME;
+ case com.jogamp.newt.event.KeyEvent.VK_END : return SWT.END;
+ case com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN : return SWT.PRINT_SCREEN;
+ case com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE : return SWT.BS;
+ case com.jogamp.newt.event.KeyEvent.VK_TAB : return SWT.TAB;
+ case com.jogamp.newt.event.KeyEvent.VK_ENTER : return SWT.LF;
+ case com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN : return SWT.PAGE_DOWN;
+ case com.jogamp.newt.event.KeyEvent.VK_PAGE_UP : return SWT.PAGE_UP;
+ case com.jogamp.newt.event.KeyEvent.VK_CONTROL : return SWT.CONTROL;
+ case com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK : return SWT.CAPS_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_PAUSE : return SWT.PAUSE;
+ case com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK : return SWT.SCROLL_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_CANCEL : return SWT.CANCEL;
+ case com.jogamp.newt.event.KeyEvent.VK_INSERT : return SWT.INSERT;
+ case com.jogamp.newt.event.KeyEvent.VK_ESCAPE : return SWT.ESC;
+ case com.jogamp.newt.event.KeyEvent.VK_SPACE : return SWT.SPACE;
+ case com.jogamp.newt.event.KeyEvent.VK_F1 : return SWT.F1;
+ case com.jogamp.newt.event.KeyEvent.VK_F2 : return SWT.F2;
+ case com.jogamp.newt.event.KeyEvent.VK_F3 : return SWT.F3;
+ case com.jogamp.newt.event.KeyEvent.VK_F4 : return SWT.F4;
+ case com.jogamp.newt.event.KeyEvent.VK_F5 : return SWT.F5;
+ case com.jogamp.newt.event.KeyEvent.VK_F6 : return SWT.F6;
+ case com.jogamp.newt.event.KeyEvent.VK_F7 : return SWT.F7;
+ case com.jogamp.newt.event.KeyEvent.VK_F8 : return SWT.F8;
+ case com.jogamp.newt.event.KeyEvent.VK_F9 : return SWT.F9;
+ case com.jogamp.newt.event.KeyEvent.VK_F10 : return SWT.F10;
+ case com.jogamp.newt.event.KeyEvent.VK_F11 : return SWT.F11;
+ case com.jogamp.newt.event.KeyEvent.VK_F12 : return SWT.F12;
+ case com.jogamp.newt.event.KeyEvent.VK_F13 : return SWT.F13;
+ case com.jogamp.newt.event.KeyEvent.VK_F14 : return SWT.F14;
+ case com.jogamp.newt.event.KeyEvent.VK_F15 : return SWT.F15;
+ case com.jogamp.newt.event.KeyEvent.VK_F16 : return SWT.F16;
+ case com.jogamp.newt.event.KeyEvent.VK_F17 : return SWT.F17;
+ case com.jogamp.newt.event.KeyEvent.VK_F18 : return SWT.F18;
+ case com.jogamp.newt.event.KeyEvent.VK_F19 : return SWT.F19;
+ case com.jogamp.newt.event.KeyEvent.VK_F20 : return SWT.F20;
+ case com.jogamp.newt.event.KeyEvent.VK_DELETE : return SWT.DEL;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD0 : return SWT.KEYPAD_0;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD1 : return SWT.KEYPAD_1;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD2 : return SWT.KEYPAD_2;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD3 : return SWT.KEYPAD_3;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD4 : return SWT.KEYPAD_4;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD5 : return SWT.KEYPAD_5;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD6 : return SWT.KEYPAD_6;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD7 : return SWT.KEYPAD_7;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD8 : return SWT.KEYPAD_8;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD9 : return SWT.KEYPAD_9;
+ case com.jogamp.newt.event.KeyEvent.VK_DECIMAL : return SWT.KEYPAD_DECIMAL;
+ case com.jogamp.newt.event.KeyEvent.VK_ADD : return SWT.KEYPAD_ADD;
+ case com.jogamp.newt.event.KeyEvent.VK_SUBTRACT : return SWT.KEYPAD_SUBTRACT;
+ case com.jogamp.newt.event.KeyEvent.VK_MULTIPLY : return SWT.KEYPAD_MULTIPLY;
+ case com.jogamp.newt.event.KeyEvent.VK_DIVIDE : return SWT.KEYPAD_DIVIDE;
+ case com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK : return SWT.NUM_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_LEFT : return SWT.ARROW_LEFT;
+ case com.jogamp.newt.event.KeyEvent.VK_UP : return SWT.ARROW_UP;
+ case com.jogamp.newt.event.KeyEvent.VK_RIGHT : return SWT.ARROW_RIGHT;
+ case com.jogamp.newt.event.KeyEvent.VK_DOWN : return SWT.ARROW_DOWN;
+ case com.jogamp.newt.event.KeyEvent.VK_HELP : return SWT.HELP;
+ }
+ return defSWTKeyCode;
+ }
+
+
+ public static final com.jogamp.newt.event.InputEvent createInputEvent(final org.eclipse.swt.widgets.Event event, final NativeSurfaceHolder sourceHolder) {
+ com.jogamp.newt.event.InputEvent res = createMouseEvent(event, sourceHolder);
+ if(null == res) {
+ res = createKeyEvent(event, sourceHolder);
+ }
+ return res;
+ }
+
+ public static final com.jogamp.newt.event.MouseEvent createMouseEvent(final org.eclipse.swt.widgets.Event event, final NativeSurfaceHolder sourceHolder) {
+ switch(event.type) {
+ case SWT.MouseDown:
+ case SWT.MouseUp:
+ case SWT.MouseMove:
+ case SWT.MouseEnter:
+ case SWT.MouseExit:
+ case SWT.MouseVerticalWheel:
+ break;
+ default:
+ return null;
+ }
+ final short type = eventTypeSWT2NEWT(event.type);
+ if( (short)0 != type ) {
+ float rotation = 0;
+ if (SWT.MouseVerticalWheel == event.type) {
+ // SWT/NEWT rotation is reversed - AWT +1 is down, NEWT +1 is up.
+ // rotation = -1 * (int) event.rotation;
+ rotation = (float) event.rotation;
+ }
+
+ int mods = swtModifiers2Newt(event.stateMask, true);
+
+ final NativeSurface source = sourceHolder.getNativeSurface();
+ final int[] pixelPos;
+ if( null != source ) {
+ if( source instanceof com.jogamp.newt.Window) {
+ final com.jogamp.newt.Window newtSource = (com.jogamp.newt.Window)source;
+ if(newtSource.isPointerConfined()) {
+ mods |= InputEvent.CONFINED_MASK;
+ }
+ if(!newtSource.isPointerVisible()) {
+ mods |= InputEvent.INVISIBLE_MASK;
+ }
+ }
+ pixelPos = source.convertToPixelUnits(new int[] { event.x, event.y });
+ } else {
+ pixelPos = new int[] { event.x, event.y };
+ }
+
+ return new com.jogamp.newt.event.MouseEvent(
+ type, sourceHolder, (0xFFFFFFFFL & event.time),
+ mods, pixelPos[0], pixelPos[1], (short)event.count, (short)event.button, MouseEvent.getRotationXYZ(rotation, mods), 1f);
+ }
+ return null; // no mapping ..
+ }
+
+ public static final com.jogamp.newt.event.KeyEvent createKeyEvent(final org.eclipse.swt.widgets.Event event, final NativeSurfaceHolder sourceHolder) {
+ switch(event.type) {
+ case SWT.KeyDown:
+ case SWT.KeyUp:
+ break;
+ default:
+ return null;
+ }
+ final short type = eventTypeSWT2NEWT(event.type);
+ if( (short)0 != type ) {
+ final short newtKeyCode = swtKeyCode2NewtKeyCode( event.keyCode );
+ return com.jogamp.newt.event.KeyEvent.create(
+ type, sourceHolder, (0xFFFFFFFFL & event.time),
+ swtModifiers2Newt(event.stateMask, false),
+ newtKeyCode, newtKeyCode, event.character);
+ }
+ return null; // no mapping ..
+ }
+
+ //
+ //
+ //
+
+ short dragButtonDown = 0;
+
+ public SWTNewtEventFactory() {
+ resetButtonsDown();
+ }
+
+ final void resetButtonsDown() {
+ dragButtonDown = 0;
+ }
+
+ public final boolean dispatchMouseEvent(final org.eclipse.swt.widgets.Event event, final NativeSurfaceHolder sourceHolder, final com.jogamp.newt.event.MouseListener l) {
+ final com.jogamp.newt.event.MouseEvent res = createMouseEvent(event, sourceHolder);
+ if(null != res) {
+ if(null != l) {
+ switch(event.type) {
+ case SWT.MouseDown:
+ dragButtonDown = (short) event.button;
+ l.mousePressed(res); break;
+ case SWT.MouseUp:
+ dragButtonDown = 0;
+ l.mouseReleased(res);
+ {
+ final com.jogamp.newt.event.MouseEvent res2 = new com.jogamp.newt.event.MouseEvent(
+ com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED,
+ res.getSource(),
+ res.getWhen(), res.getModifiers(),
+ res.getX(), res.getY(), res.getClickCount(),
+ res.getButton(), res.getRotation(), res.getRotationScale());
+ l.mouseClicked(res2);
+ }
+ break;
+ case SWT.MouseMove:
+ if( 0 < dragButtonDown ) {
+ final com.jogamp.newt.event.MouseEvent res2 = new com.jogamp.newt.event.MouseEvent(
+ com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED,
+ res.getSource(),
+ res.getWhen(), res.getModifiers(),
+ res.getX(), res.getY(), res.getClickCount(),
+ dragButtonDown, res.getRotation(), res.getRotationScale());
+ l.mouseDragged( res2 );
+ } else {
+ l.mouseMoved(res);
+ }
+ break;
+ case SWT.MouseEnter:
+ l.mouseEntered(res);
+ break;
+ case SWT.MouseExit:
+ resetButtonsDown();
+ l.mouseExited(res);
+ break;
+ case SWT.MouseVerticalWheel:
+ l.mouseWheelMoved(res);
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public final boolean dispatchKeyEvent(final org.eclipse.swt.widgets.Event event, final NativeSurfaceHolder sourceHolder, final com.jogamp.newt.event.KeyListener l) {
+ final com.jogamp.newt.event.KeyEvent res = createKeyEvent(event, sourceHolder);
+ if(null != res) {
+ if(null != l) {
+ switch(event.type) {
+ case SWT.KeyDown:
+ l.keyPressed(res);
+ break;
+ case SWT.KeyUp:
+ l.keyReleased(res);
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public final void attachDispatchListener(final org.eclipse.swt.widgets.Control ctrl, final NativeSurfaceHolder sourceHolder,
+ final com.jogamp.newt.event.MouseListener ml,
+ final com.jogamp.newt.event.KeyListener kl) {
+ if(null==ctrl) {
+ throw new IllegalArgumentException("Argument ctrl is null");
+ }
+ if(null==sourceHolder) {
+ throw new IllegalArgumentException("Argument source is null");
+ }
+
+ if( null != ml ) {
+ final Listener listener = new Listener () {
+ @Override
+ public void handleEvent (final Event event) {
+ dispatchMouseEvent( event, sourceHolder, ml );
+ } };
+ ctrl.addListener(SWT.MouseDown, listener);
+ ctrl.addListener(SWT.MouseUp, listener);
+ ctrl.addListener(SWT.MouseMove, listener);
+ ctrl.addListener(SWT.MouseEnter, listener);
+ ctrl.addListener(SWT.MouseExit, listener);
+ ctrl.addListener(SWT.MouseVerticalWheel, listener);
+ }
+ if( null != kl ) {
+ final Listener listener = new Listener () {
+ @Override
+ public void handleEvent (final Event event) {
+ dispatchKeyEvent( event, sourceHolder, kl );
+ } };
+ ctrl.addListener(SWT.KeyDown, listener);
+ ctrl.addListener(SWT.KeyUp, listener);
+ }
+ }
+}
+
diff --git a/src/newt/native/InputEvent.h b/src/newt/native/InputEvent.h
index 51c56c474..2de46f82e 100644
--- a/src/newt/native/InputEvent.h
+++ b/src/newt/native/InputEvent.h
@@ -38,15 +38,26 @@
#define EVENT_CTRL_MASK (1 << 1)
#define EVENT_META_MASK (1 << 2)
#define EVENT_ALT_MASK (1 << 3)
-#define EVENT_ALT_GRAPH_MASK (1 << 5)
-#define EVENT_BUTTON1_MASK (1 << 6)
-#define EVENT_BUTTON2_MASK (1 << 7)
-#define EVENT_BUTTON3_MASK (1 << 8)
-#define EVENT_BUTTON4_MASK (1 << 9)
-#define EVENT_BUTTON5_MASK (1 << 10)
-#define EVENT_BUTTON6_MASK (1 << 11)
-#define EVENT_AUTOREPEAT_MASK (1 << 15)
-#define EVENT_CONFINED_MASK (1 << 16)
-#define EVENT_INVISIBLE_MASK (1 << 17)
+#define EVENT_ALT_GRAPH_MASK (1 << 4)
+
+#define EVENT_BUTTON1_MASK (1 << 5)
+#define EVENT_BUTTON2_MASK (1 << 6)
+#define EVENT_BUTTON3_MASK (1 << 7)
+#define EVENT_BUTTON4_MASK (1 << 8)
+#define EVENT_BUTTON5_MASK (1 << 9)
+#define EVENT_BUTTON6_MASK (1 << 10)
+#define EVENT_BUTTON7_MASK (1 << 11)
+#define EVENT_BUTTON8_MASK (1 << 12)
+#define EVENT_BUTTON9_MASK (1 << 13)
+
+/** 16 buttons */
+#define EVENT_BUTTONLAST_MASK (1 << 20)
+
+/** 16 buttons */
+#define EVENT_BUTTONALL_MASK ( 0xffff << 5 )
+
+#define EVENT_AUTOREPEAT_MASK (1 << 29)
+#define EVENT_CONFINED_MASK (1 << 30)
+#define EVENT_INVISIBLE_MASK (1 << 31)
#endif
diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c
index f1d6aecdf..cfec60dc1 100644
--- a/src/newt/native/KDWindow.c
+++ b/src/newt/native/KDWindow.c
@@ -161,14 +161,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages
if(KD_INPUT_POINTER_SELECT==ptr->index) {
DBG_PRINT( "event mouse click: src: %p, s:%d, (%d,%d)\n", userData, ptr->select, ptr->x, ptr->y);
(*env)->CallVoidMethod(env, javaWindow, sendMouseEventID,
- (ptr->select==0) ? (jint) EVENT_MOUSE_RELEASED : (jint) EVENT_MOUSE_PRESSED,
+ (ptr->select==0) ? (jshort) EVENT_MOUSE_RELEASED : (jshort) EVENT_MOUSE_PRESSED,
(jint) 0,
- (jint) ptr->x, (jint) ptr->y, 1, 0);
+ (jint) ptr->x, (jint) ptr->y, (short)1, 0.0f);
} else {
DBG_PRINT( "event mouse: src: %d, s:%p, i:0x%X (%d,%d)\n", userData, ptr->select, ptr->index, ptr->x, ptr->y);
- (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED,
0,
- (jint) ptr->x, (jint) ptr->y, 0, 0);
+ (jint) ptr->x, (jint) ptr->y, (jshort)0, 0.0f);
}
}
break;
@@ -193,8 +193,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_WindowDriver_initIDs
sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+ sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V");
+ sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V");
if (windowCreatedID == NULL ||
sizeChangedID == NULL ||
visibleChangedID == NULL ||
diff --git a/src/newt/native/KeyEvent.h b/src/newt/native/KeyEvent.h
index 0f7b1606b..c0a366a17 100644
--- a/src/newt/native/KeyEvent.h
+++ b/src/newt/native/KeyEvent.h
@@ -31,197 +31,203 @@
#define EVENT_KEY_PRESSED 300
#define EVENT_KEY_RELEASED 301
-#define EVENT_KEY_TYPED 302
-
-#define J_CHAR_UNDEFINED 0xFFFF;
-#define J_VK_ENTER '\n'
-#define J_VK_BACK_SPACE '\b'
-#define J_VK_TAB '\t'
-#define J_VK_CANCEL 0x03
-#define J_VK_CLEAR 0x0C
-#define J_VK_SHIFT 0x10
-#define J_VK_CONTROL 0x11
-#define J_VK_ALT 0x12
-#define J_VK_PAUSE 0x13
-#define J_VK_CAPS_LOCK 0x14
-#define J_VK_ESCAPE 0x1B
-#define J_VK_SPACE 0x20
-#define J_VK_PAGE_UP 0x21
-#define J_VK_PAGE_DOWN 0x22
-#define J_VK_END 0x23
-#define J_VK_HOME 0x24
-#define J_VK_LEFT 0x25
-#define J_VK_UP 0x26
-#define J_VK_RIGHT 0x27
-#define J_VK_DOWN 0x28
-#define J_VK_COMMA 0x2C
-#define J_VK_MINUS 0x2D
-#define J_VK_PERIOD 0x2E
-#define J_VK_SLASH 0x2F
-#define J_VK_0 0x30
-#define J_VK_1 0x31
-#define J_VK_2 0x32
-#define J_VK_3 0x33
-#define J_VK_4 0x34
-#define J_VK_5 0x35
-#define J_VK_6 0x36
-#define J_VK_7 0x37
-#define J_VK_8 0x38
-#define J_VK_9 0x39
-#define J_VK_SEMICOLON 0x3B
-#define J_VK_EQUALS 0x3D
-#define J_VK_A 0x41
-#define J_VK_B 0x42
-#define J_VK_C 0x43
-#define J_VK_D 0x44
-#define J_VK_E 0x45
-#define J_VK_F 0x46
-#define J_VK_G 0x47
-#define J_VK_H 0x48
-#define J_VK_I 0x49
-#define J_VK_J 0x4A
-#define J_VK_K 0x4B
-#define J_VK_L 0x4C
-#define J_VK_M 0x4D
-#define J_VK_N 0x4E
-#define J_VK_O 0x4F
-#define J_VK_P 0x50
-#define J_VK_Q 0x51
-#define J_VK_R 0x52
-#define J_VK_S 0x53
-#define J_VK_T 0x54
-#define J_VK_U 0x55
-#define J_VK_V 0x56
-#define J_VK_W 0x57
-#define J_VK_X 0x58
-#define J_VK_Y 0x59
-#define J_VK_Z 0x5A
-#define J_VK_OPEN_BRACKET 0x5B
-#define J_VK_BACK_SLASH 0x5C
-#define J_VK_CLOSE_BRACKET 0x5D
-#define J_VK_NUMPAD0 0x60
-#define J_VK_NUMPAD1 0x61
-#define J_VK_NUMPAD2 0x62
-#define J_VK_NUMPAD3 0x63
-#define J_VK_NUMPAD4 0x64
-#define J_VK_NUMPAD5 0x65
-#define J_VK_NUMPAD6 0x66
-#define J_VK_NUMPAD7 0x67
-#define J_VK_NUMPAD8 0x68
-#define J_VK_NUMPAD9 0x69
-#define J_VK_MULTIPLY 0x6A
-#define J_VK_ADD 0x6B
-#define J_VK_SEPARATOR 0x6C
-#define J_VK_SUBTRACT 0x6D
-#define J_VK_DECIMAL 0x6E
-#define J_VK_DIVIDE 0x6F
-#define J_VK_DELETE 0x7F /* ASCII DEL */
-#define J_VK_NUM_LOCK 0x90
-#define J_VK_SCROLL_LOCK 0x91
-#define J_VK_F1 0x70
-#define J_VK_F2 0x71
-#define J_VK_F3 0x72
-#define J_VK_F4 0x73
-#define J_VK_F5 0x74
-#define J_VK_F6 0x75
-#define J_VK_F7 0x76
-#define J_VK_F8 0x77
-#define J_VK_F9 0x78
-#define J_VK_F10 0x79
-#define J_VK_F11 0x7A
-#define J_VK_F12 0x7B
-#define J_VK_F13 0xF000
-#define J_VK_F14 0xF001
-#define J_VK_F15 0xF002
-#define J_VK_F16 0xF003
-#define J_VK_F17 0xF004
-#define J_VK_F18 0xF005
-#define J_VK_F19 0xF006
-#define J_VK_F20 0xF007
-#define J_VK_F21 0xF008
-#define J_VK_F22 0xF009
-#define J_VK_F23 0xF00A
-#define J_VK_F24 0xF00B
-#define J_VK_PRINTSCREEN 0x9A
-#define J_VK_INSERT 0x9B
-#define J_VK_HELP 0x9C
-#define J_VK_META 0x9D
-#define J_VK_BACK_QUOTE 0xC0
-#define J_VK_QUOTE 0xDE
-#define J_VK_KP_UP 0xE0
-#define J_VK_KP_DOWN 0xE1
-#define J_VK_KP_LEFT 0xE2
-#define J_VK_KP_RIGHT 0xE3
-#define J_VK_DEAD_GRAVE 0x80
-#define J_VK_DEAD_ACUTE 0x81
-#define J_VK_DEAD_CIRCUMFLEX 0x82
-#define J_VK_DEAD_TILDE 0x83
-#define J_VK_DEAD_MACRON 0x84
-#define J_VK_DEAD_BREVE 0x85
-#define J_VK_DEAD_ABOVEDOT 0x86
-#define J_VK_DEAD_DIAERESIS 0x87
-#define J_VK_DEAD_ABOVERING 0x88
-#define J_VK_DEAD_DOUBLEACUTE 0x89
-#define J_VK_DEAD_CARON 0x8a
-#define J_VK_DEAD_CEDILLA 0x8b
-#define J_VK_DEAD_OGONEK 0x8c
-#define J_VK_DEAD_IOTA 0x8d
-#define J_VK_DEAD_VOICED_SOUND 0x8e
-#define J_VK_DEAD_SEMIVOICED_SOUND 0x8f
-#define J_VK_AMPERSAND 0x96
-#define J_VK_ASTERISK 0x97
-#define J_VK_QUOTEDBL 0x98
-#define J_VK_LESS 0x99
-#define J_VK_GREATER 0xa0
-#define J_VK_BRACELEFT 0xa1
-#define J_VK_BRACERIGHT 0xa2
-#define J_VK_AT 0x0200
-#define J_VK_COLON 0x0201
-#define J_VK_CIRCUMFLEX 0x0202
-#define J_VK_DOLLAR 0x0203
-#define J_VK_EURO_SIGN 0x0204
-#define J_VK_EXCLAMATION_MARK 0x0205
-#define J_VK_INVERTED_EXCLAMATION_MARK 0x0206
-#define J_VK_LEFT_PARENTHESIS 0x0207
-#define J_VK_NUMBER_SIGN 0x0208
-#define J_VK_PLUS 0x0209
-#define J_VK_RIGHT_PARENTHESIS 0x020A
-#define J_VK_UNDERSCORE 0x020B
-#define J_VK_WINDOWS 0x020C
-#define J_VK_CONTEXT_MENU 0x020D
-#define J_VK_FINAL 0x0018
-#define J_VK_CONVERT 0x001C
-#define J_VK_NONCONVERT 0x001D
-#define J_VK_ACCEPT 0x001E
-#define J_VK_MODECHANGE 0x001F
-#define J_VK_KANA 0x0015
-#define J_VK_KANJI 0x0019
-#define J_VK_ALPHANUMERIC 0x00F0
-#define J_VK_KATAKANA 0x00F1
-#define J_VK_HIRAGANA 0x00F2
-#define J_VK_FULL_WIDTH 0x00F3
-#define J_VK_HALF_WIDTH 0x00F4
-#define J_VK_ROMAN_CHARACTERS 0x00F5
-#define J_VK_ALL_CANDIDATES 0x0100
-#define J_VK_PREVIOUS_CANDIDATE 0x0101
-#define J_VK_CODE_INPUT 0x0102
-#define J_VK_JAPANESE_KATAKANA 0x0103
-#define J_VK_JAPANESE_HIRAGANA 0x0104
-#define J_VK_JAPANESE_ROMAN 0x0105
-#define J_VK_KANA_LOCK 0x0106
-#define J_VK_INPUT_METHOD_ON_OFF 0x0107
-#define J_VK_CUT 0xFFD1
-#define J_VK_COPY 0xFFCD
-#define J_VK_PASTE 0xFFCF
-#define J_VK_UNDO 0xFFCB
-#define J_VK_AGAIN 0xFFC9
-#define J_VK_FIND 0xFFD0
-#define J_VK_PROPS 0xFFCA
-#define J_VK_STOP 0xFFC8
-#define J_VK_COMPOSE 0xFF20
-#define J_VK_ALT_GRAPH 0xFF7E
-#define J_VK_BEGIN 0xFF58
-#define J_VK_UNDEFINED 0x0
+
+#define J_VK_UNDEFINED ( 0x0U )
+#define J_VK_HOME ( 0x02U )
+#define J_VK_END ( 0x03U )
+#define J_VK_FINAL ( 0x04U )
+#define J_VK_PRINTSCREEN ( 0x05U )
+#define J_VK_BACK_SPACE ( 0x08U )
+#define J_VK_TAB ( 0x09U )
+#define J_VK_PAGE_DOWN ( 0x0BU )
+#define J_VK_CLEAR ( 0x0CU )
+#define J_VK_ENTER ( 0x0DU )
+#define J_VK_SHIFT ( 0x0FU )
+#define J_VK_PAGE_UP ( 0x10U )
+#define J_VK_CONTROL ( 0x11U )
+#define J_VK_ALT ( 0x12U )
+#define J_VK_ALT_GRAPH ( 0x13U )
+#define J_VK_CAPS_LOCK ( 0x14U )
+#define J_VK_PAUSE ( 0x16U )
+#define J_VK_SCROLL_LOCK ( 0x17U )
+#define J_VK_CANCEL ( 0x18U )
+#define J_VK_INSERT ( 0x1AU )
+#define J_VK_ESCAPE ( 0x1BU )
+#define J_VK_CONVERT ( 0x1CU )
+#define J_VK_NONCONVERT ( 0x1DU )
+#define J_VK_ACCEPT ( 0x1EU )
+#define J_VK_MODECHANGE ( 0x1FU )
+
+//
+// Unicode: Printable [0x20 - 0x7E]
+//
+
+#define J_VK_SPACE ( 0x20U )
+#define J_VK_EXCLAMATION_MARK ( 0x21U )
+#define J_VK_QUOTEDBL ( 0x22U )
+#define J_VK_NUMBER_SIGN ( 0x23U )
+#define J_VK_DOLLAR ( 0x24U )
+#define J_VK_PERCENT ( 0x25U )
+#define J_VK_AMPERSAND ( 0x26U )
+#define J_VK_QUOTE ( 0x27U )
+#define J_VK_LEFT_PARENTHESIS ( 0x28U )
+#define J_VK_RIGHT_PARENTHESIS ( 0x29U )
+#define J_VK_ASTERISK ( 0x2AU )
+#define J_VK_PLUS ( 0x2BU )
+#define J_VK_COMMA ( 0x2CU )
+#define J_VK_MINUS ( 0x2DU )
+#define J_VK_PERIOD ( 0x2EU )
+#define J_VK_SLASH ( 0x2FU )
+#define J_VK_0 ( 0x30U )
+#define J_VK_1 ( 0x31U )
+#define J_VK_2 ( 0x32U )
+#define J_VK_3 ( 0x33U )
+#define J_VK_4 ( 0x34U )
+#define J_VK_5 ( 0x35U )
+#define J_VK_6 ( 0x36U )
+#define J_VK_7 ( 0x37U )
+#define J_VK_8 ( 0x38U )
+#define J_VK_9 ( 0x39U )
+#define J_VK_COLON ( 0x3AU )
+#define J_VK_SEMICOLON ( 0x3BU )
+#define J_VK_LESS ( 0x3CU )
+#define J_VK_EQUALS ( 0x3DU )
+#define J_VK_GREATER ( 0x3EU )
+#define J_VK_QUESTIONMARK ( 0x3FU )
+#define J_VK_AT ( 0x40U )
+#define J_VK_A ( 0x41U )
+#define J_VK_B ( 0x42U )
+#define J_VK_C ( 0x43U )
+#define J_VK_D ( 0x44U )
+#define J_VK_E ( 0x45U )
+#define J_VK_F ( 0x46U )
+#define J_VK_G ( 0x47U )
+#define J_VK_H ( 0x48U )
+#define J_VK_I ( 0x49U )
+#define J_VK_J ( 0x4AU )
+#define J_VK_K ( 0x4BU )
+#define J_VK_L ( 0x4CU )
+#define J_VK_M ( 0x4DU )
+#define J_VK_N ( 0x4EU )
+#define J_VK_O ( 0x4FU )
+#define J_VK_P ( 0x50U )
+#define J_VK_Q ( 0x51U )
+#define J_VK_R ( 0x52U )
+#define J_VK_S ( 0x53U )
+#define J_VK_T ( 0x54U )
+#define J_VK_U ( 0x55U )
+#define J_VK_V ( 0x56U )
+#define J_VK_W ( 0x57U )
+#define J_VK_X ( 0x58U )
+#define J_VK_Y ( 0x59U )
+#define J_VK_Z ( 0x5AU )
+#define J_VK_OPEN_BRACKET ( 0x5BU )
+#define J_VK_BACK_SLASH ( 0x5CU )
+#define J_VK_CLOSE_BRACKET ( 0x5DU )
+#define J_VK_CIRCUMFLEX ( 0x5EU )
+#define J_VK_UNDERSCORE ( 0x5FU )
+#define J_VK_BACK_QUOTE ( 0x60U )
+#define J_VK_F1 ( 0x60U+ 1U )
+#define J_VK_F2 ( 0x60U+ 2U )
+#define J_VK_F3 ( 0x60U+ 3U )
+#define J_VK_F4 ( 0x60U+ 4U )
+#define J_VK_F5 ( 0x60U+ 5U )
+#define J_VK_F6 ( 0x60U+ 6U )
+#define J_VK_F7 ( 0x60U+ 7U )
+#define J_VK_F8 ( 0x60U+ 8U )
+#define J_VK_F9 ( 0x60U+ 9U )
+#define J_VK_F10 ( 0x60U+10U )
+#define J_VK_F11 ( 0x60U+11U )
+#define J_VK_F12 ( 0x60U+12U )
+#define J_VK_F13 ( 0x60U+13U )
+#define J_VK_F14 ( 0x60U+14U )
+#define J_VK_F15 ( 0x60U+15U )
+#define J_VK_F16 ( 0x60U+16U )
+#define J_VK_F17 ( 0x60U+17U )
+#define J_VK_F18 ( 0x60U+18U )
+#define J_VK_F19 ( 0x60U+19U )
+#define J_VK_F20 ( 0x60U+20U )
+#define J_VK_F21 ( 0x60U+21U )
+#define J_VK_F22 ( 0x60U+22U )
+#define J_VK_F23 ( 0x60U+23U )
+#define J_VK_F24 ( 0x60U+24U )
+#define J_VK_LEFT_BRACE ( 0x7BU )
+#define J_VK_PIPE ( 0x7CU )
+#define J_VK_RIGHT_BRACE ( 0x7DU )
+#define J_VK_TILDE ( 0x7EU )
+
+//
+// Unicode: Non printable controls: [0x7F - 0x9F]
+//
+
+#define J_VK_SEPARATOR ( 0x7FU )
+#define J_VK_NUMPAD0 ( 0x80U )
+#define J_VK_NUMPAD1 ( 0x81U )
+#define J_VK_NUMPAD2 ( 0x82U )
+#define J_VK_NUMPAD3 ( 0x83U )
+#define J_VK_NUMPAD4 ( 0x84U )
+#define J_VK_NUMPAD5 ( 0x85U )
+#define J_VK_NUMPAD6 ( 0x86U )
+#define J_VK_NUMPAD7 ( 0x87U )
+#define J_VK_NUMPAD8 ( 0x88U )
+#define J_VK_NUMPAD9 ( 0x89U )
+#define J_VK_DECIMAL ( 0x8AU )
+#define J_VK_ADD ( 0x8BU )
+#define J_VK_SUBTRACT ( 0x8CU )
+#define J_VK_MULTIPLY ( 0x8DU )
+#define J_VK_DIVIDE ( 0x8EU )
+
+#define J_VK_DELETE ( 0x93U )
+#define J_VK_NUM_LOCK ( 0x94U )
+#define J_VK_LEFT ( 0x95U )
+#define J_VK_UP ( 0x96U )
+#define J_VK_RIGHT ( 0x97U )
+#define J_VK_DOWN ( 0x98U )
+#define J_VK_CONTEXT_MENU ( 0x99U )
+#define J_VK_WINDOWS ( 0x9AU )
+#define J_VK_META ( 0x9BU )
+#define J_VK_HELP ( 0x9CU )
+#define J_VK_COMPOSE ( 0x9DU )
+#define J_VK_BEGIN ( 0x9EU )
+#define J_VK_STOP ( 0x9FU )
+
+//
+// Unicode: Printable [0x00A0 - 0xDFFF]
+//
+
+#define J_VK_INVERTED_EXCLAMATION_MARK ( 0xA1U )
+#define J_VK_EURO_SIGN ( 0x20ACU )
+
+//
+// Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
+//
+
+/* for Sun keyboards */
+#define J_VK_CUT ( 0xF879U )
+#define J_VK_COPY ( 0xF87AU )
+#define J_VK_PASTE ( 0xF87BU )
+#define J_VK_UNDO ( 0xF87CU )
+#define J_VK_AGAIN ( 0xF87DU )
+#define J_VK_FIND ( 0xF87EU )
+#define J_VK_PROPS ( 0xF87FU )
+
+/* for input method support on Asian Keyboards */
+#define J_VK_INPUT_METHOD_ON_OFF ( 0xF890U )
+#define J_VK_CODE_INPUT ( 0xF891U )
+#define J_VK_ROMAN_CHARACTERS ( 0xF892U )
+#define J_VK_ALL_CANDIDATES ( 0xF893U )
+#define J_VK_PREVIOUS_CANDIDATE ( 0xF894U )
+#define J_VK_ALPHANUMERIC ( 0xF895U )
+#define J_VK_KATAKANA ( 0xF896U )
+#define J_VK_HIRAGANA ( 0xF897U )
+#define J_VK_FULL_WIDTH ( 0xF898U )
+#define J_VK_HALF_WIDTH ( 0xF89AU )
+#define J_VK_JAPANESE_KATAKANA ( 0xF89BU )
+#define J_VK_JAPANESE_HIRAGANA ( 0xF89CU )
+#define J_VK_JAPANESE_ROMAN ( 0xF89DU )
+#define J_VK_KANA_LOCK ( 0xF89FU )
+
+#define J_VK_KEYBOARD_INVISIBLE ( 0xF8FFU )
#endif
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index b9c339285..2bd11da3c 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -62,12 +62,36 @@ static NSString* jstringToNSString(JNIEnv* env, jstring jstr)
return str;
}
-static void setFrameTopLeftPoint(NSWindow* pWin, NewtMacWindow* mWin, jint x, jint y) {
- NSPoint pS = [mWin newtScreenWinPos2OSXScreenPos: NSMakePoint(x, y)];
+static void setWindowClientTopLeftPoint(NewtMacWindow* mWin, jint x, jint y, BOOL doDisplay) {
+ DBG_PRINT( "setWindowClientTopLeftPoint.0 - window: %p %d/%d, display %d\n", mWin, (int)x, (int)y, (int)doDisplay);
+ NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)];
+ DBG_PRINT( "setWindowClientTopLeftPoint.1: %d/%d\n", (int)pS.x, (int)pS.y);
+
[mWin setFrameOrigin: pS];
+ DBG_PRINT( "setWindowClientTopLeftPoint.X: %d/%d\n", (int)pS.x, (int)pS.y);
+
+ if( doDisplay ) {
+ NSView* mView = [mWin contentView];
+ [mWin invalidateCursorRectsForView: mView];
+ }
+}
- NSView* mView = [mWin contentView];
- [mWin invalidateCursorRectsForView: mView];
+static void setWindowClientTopLeftPointAndSize(NewtMacWindow* mWin, jint x, jint y, jint width, jint height, BOOL doDisplay) {
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.0 - window: %p %d/%d %dx%d, display %d\n", mWin, (int)x, (int)y, (int)width, (int)height, (int)doDisplay);
+ NSSize clientSZ = NSMakeSize(width, height);
+ NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y) size: clientSZ];
+ NSSize topSZ = [mWin newtClientSize2TLSize: clientSZ];
+ NSRect rect = { pS, topSZ };
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.1: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height);
+
+ [mWin setFrame: rect display:doDisplay];
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.X: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height);
+
+ // -> display:YES
+ // if( doDisplay ) {
+ // NSView* mView = [mWin contentView];
+ // [mWin invalidateCursorRectsForView: mView];
+ // }
}
#ifdef VERBOSE_ON
@@ -76,22 +100,38 @@ static int getRetainCount(NSObject * obj) {
}
#endif
-static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView) {
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtView *view, BOOL enable) {
+ DBG_PRINT( "setJavaWindowObject.0: View %p\n", view);
+ if( !enable) {
+ jobject globJavaWindowObject = [view getJavaWindowObject];
+ if( NULL != globJavaWindowObject ) {
+ DBG_PRINT( "setJavaWindowObject.1: View %p - Clear old javaWindowObject %p\n", view, globJavaWindowObject);
+ (*env)->DeleteGlobalRef(env, globJavaWindowObject);
+ [view setJavaWindowObject: NULL];
+ }
+ } else if( NULL != newJavaWindowObject ) {
+ DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject);
+ jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject);
+ [view setJavaWindowObject: globJavaWindowObject];
+ }
+ DBG_PRINT( "setJavaWindowObject.X: View %p\n", view);
+}
+
+static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView, BOOL setJavaWindow) {
NSView* oldNSView = [win contentView];
- NewtView* oldView = NULL;
+ NewtView* oldNewtView = NULL;
#ifdef VERBOSE_ON
int dbgIdx = 1;
#endif
- if( [oldNSView isMemberOfClass:[NewtView class]] ) {
- oldView = (NewtView *) oldNSView;
+ if( [oldNSView isKindOfClass:[NewtView class]] ) {
+ oldNewtView = (NewtView *) oldNSView;
}
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d), parent view %p\n",
- dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView), pview);
+ dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView), pview);
- if(NULL!=oldNSView) {
+ if( NULL!=oldNSView ) {
NS_DURING
// Available >= 10.5 - Makes the menubar disapear
BOOL iifs;
@@ -106,34 +146,21 @@ NS_DURING
NS_HANDLER
NS_ENDHANDLER
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d)\n",
- dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+ dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView));
- if( NULL != oldView ) {
- jobject globJavaWindowObject = [oldView getJavaWindowObject];
- (*env)->DeleteGlobalRef(env, globJavaWindowObject);
- [oldView setJavaWindowObject: NULL];
- [oldView setDestroyNotifySent: false];
+ if( NULL != oldNewtView ) {
+ [oldNewtView setDestroyNotifySent: false];
+ setJavaWindowObject(env, NULL, oldNewtView, NO);
}
[oldNSView removeFromSuperviewWithoutNeedingDisplay];
}
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n",
dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
- if(NULL!=newView) {
- jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject);
- [newView setJavaWindowObject: globJavaWindowObject];
+ if( NULL!=newView ) {
[newView setDestroyNotifySent: false];
- {
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
-
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- } else {
- jvmVersion = (*env)->GetVersion(env);
- }
- [newView setJVMHandle: jvmHandle];
- [newView setJVMVersion: jvmVersion];
+ if( setJavaWindow ) {
+ setJavaWindowObject(env, javaWindowObject, newView, YES);
}
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d)\n",
@@ -152,12 +179,10 @@ NS_ENDHANDLER
dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
// make sure the insets are updated in the java object
- [win updateInsets: env];
+ [win updateInsets: env jwin:javaWindowObject];
DBG_PRINT( "changeContentView.X win %p, view (%p,%d -> %p,%d)\n",
win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView));
-
- [pool release];
}
/*
@@ -173,6 +198,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_initNSAp
if(initialized) return JNI_TRUE;
initialized = 1;
+ NewtCommon_init(env);
+
// This little bit of magic is needed in order to receive mouse
// motion events and allow key focus to be properly transferred.
// FIXME: are these Carbon APIs? They come from the
@@ -248,50 +275,151 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_stopNSApplic
[pool release];
}
-static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) {
- NSArray *screens = [NSScreen screens];
- if(screen_idx<0) screen_idx=0;
- if(screen_idx>=[screens count]) screen_idx=0;
- return (NSScreen *) [screens objectAtIndex: screen_idx];
+static NSImage * createNSImageFromData(JNIEnv *env, unsigned char * iconData, jint jiconWidth, jint jiconHeight) {
+ if( NULL != iconData ) {
+ NSInteger iconWidth = (NSInteger) jiconWidth;
+ NSInteger iconHeight = (NSInteger) jiconHeight;
+ const NSInteger bpc = 8 /* bits per component */, spp=4 /* RGBA */, bpp = bpc * spp;
+ const NSBitmapFormat bfmt = NSAlphaNonpremultipliedBitmapFormat;
+ const BOOL hasAlpha = YES;
+
+ NSBitmapImageRep* bir = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: &iconData
+ pixelsWide: iconWidth
+ pixelsHigh: iconHeight
+ bitsPerSample: bpc
+ samplesPerPixel: spp
+ hasAlpha: hasAlpha
+ isPlanar: NO
+ colorSpaceName: NSCalibratedRGBColorSpace
+ bitmapFormat: bfmt
+ bytesPerRow: iconWidth*4
+ bitsPerPixel: bpp];
+ [bir autorelease];
+ NSImage* nsImage = [[NSImage alloc] initWithCGImage: [bir CGImage] size:NSZeroSize];
+ return nsImage;
+ }
+ return NULL;
}
/*
- * Class: jogamp_newt_driver_macosx_ScreenDriver
- * Method: getWidthImpl
- * Signature: (I)I
+ * Class: jogamp_newt_driver_macosx_DisplayDriver
+ * Method: setAppIcon0
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getWidthImpl0
- (JNIEnv *env, jclass clazz, jint screen_idx)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_setAppIcon0
+ (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height)
{
+ if( 0 == pixels ) {
+ return;
+ }
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx);
- NSRect rect = [screen frame];
-
+ // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height);
+ if( NULL != nsImage ) {
+ [nsImage autorelease];
+ [NSApp setApplicationIconImage: nsImage];
+ }
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
[pool release];
+}
- return (jint) (rect.size.width);
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPointerIcon0
+ (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
+{
+ if( 0 == pixels ) {
+ return 0;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height);
+ NSCursor * res = NULL;
+ if( NULL != nsImage ) {
+ [nsImage autorelease];
+ NSPoint hotP = { hotX, hotY };
+ res = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP];
+ }
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+ [pool release];
+ DBG_PRINT( "createPointerIcon0 %p\n", res);
+ return (jlong) (intptr_t) res;
}
-/*
- * Class: jogamp_newt_driver_macosx_ScreenDriver
- * Method: getHeightImpl
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getHeightImpl0
- (JNIEnv *env, jclass clazz, jint screen_idx)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_destroyPointerIcon0
+ (JNIEnv *env, jobject unused, jlong handle)
{
+ NSCursor * c = (NSCursor*) (intptr_t) handle ;
+ if( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c);
+ return;
+ }
+ DBG_PRINT( "destroyPointerIcon0 %p\n", c);
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [c release];
+ [pool release];
+}
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx);
- NSRect rect = [screen frame];
+NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx, BOOL cap) {
+ NSArray *screens = [NSScreen screens];
+ if( screen_idx<0 || screen_idx>=[screens count] ) {
+ if( cap ) {
+ screen_idx=0;
+ } else {
+ return NULL;
+ }
+ }
+ return (NSScreen *) [screens objectAtIndex: screen_idx];
+}
- [pool release];
+NSScreen * NewtScreen_getNSScreenByCoord(int x, int y) {
+ NSArray *screens = [NSScreen screens];
+ int i;
+ for(i=[screens count]-1; i>=0; i--) {
+ NSScreen * screen = (NSScreen *) [screens objectAtIndex: i];
+ NSRect frame = [screen frame];
+ if( x >= frame.origin.x &&
+ y >= frame.origin.y &&
+ x < frame.origin.x + frame.size.width &&
+ y < frame.origin.y + frame.size.height ) {
+ return screen;
+ }
+ }
+ return (NSScreen *) [screens objectAtIndex: 0];
+}
- return (jint) (rect.size.height);
+static void NewtScreen_dump() {
+#ifdef VERBOSE_ON
+ NSArray *screens = [NSScreen screens];
+ int i;
+ for(i=0; i<[screens count]; i++) {
+ NSScreen * screen = (NSScreen *) [screens objectAtIndex: i];
+ NSRect screenFrame = [screen frame];
+ NSRect screenVisibleFrame = [screen visibleFrame];
+ CGFloat pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen backingScaleFactor]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+ NSWindowDepth depth = [screen depth]; // an (int) value!
+ DBG_PRINT( "NSScreen #%d (%p): Frame %lf/%lf %lfx%lf (vis %lf/%lf %lfx%lf), scale %lf, depth %d\n",
+ i, screen,
+ screenFrame.origin.x, screenFrame.origin.y, screenFrame.size.width, screenFrame.size.height,
+ screenVisibleFrame.origin.x, screenVisibleFrame.origin.y, screenVisibleFrame.size.width, screenVisibleFrame.size.height,
+ pixelScale, depth);
+ }
+#endif
}
-static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
+
+CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
// Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?!
NSDictionary * dict = [screen deviceDescription];
NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"];
@@ -325,11 +453,25 @@ static long GetDictionaryLong(CFDictionaryRef theDict, const void* key)
/*
* Class: jogamp_newt_driver_macosx_ScreenDriver
- * Method: getScreenSizeMM0
+ * Method: getMonitorCount0
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorCount0
+ (JNIEnv *env, jobject obj)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSArray *screens = [NSScreen screens];
+ [pool release];
+ return (jint) [screens count];
+}
+
+/*
+ * Class: jogamp_newt_driver_macosx_ScreenDriver
+ * Method: getMonitorProps0
* Signature: (I)[I
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScreenSizeMM0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorProps0
+ (JNIEnv *env, jobject obj, jint crt_idx)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@@ -339,33 +481,58 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
timespec_now(&t0);
#endif
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
#ifdef DBG_PERF
timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "MacScreen_getScreenSizeMM0.1: %ld ms\n", td_ms); fflush(NULL);
+ fprintf(stderr, "MacScreen_getMonitorProps0.1: %ld ms\n", td_ms); fflush(NULL);
#endif
-
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+ if( NULL == screen ) {
+ [pool release];
+ return NULL;
+ }
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
#ifdef DBG_PERF
timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "MacScreen_getScreenSizeMM0.2: %ld ms\n", td_ms); fflush(NULL);
+ fprintf(stderr, "MacScreen_getMonitorProps0.2: %ld ms\n", td_ms); fflush(NULL);
#endif
- CGSize screenDim = CGDisplayScreenSize(display);
+ CGSize sizeMM = CGDisplayScreenSize(display);
#ifdef DBG_PERF
timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "MacScreen_getScreenSizeMM0.3: %ld ms\n", td_ms); fflush(NULL);
+ fprintf(stderr, "MacScreen_getMonitorProps0.3: %ld ms\n", td_ms); fflush(NULL);
#endif
- jint prop[ 2 ];
- prop[0] = (jint) screenDim.width;
- prop[1] = (jint) screenDim.height;
+ CGRect dBounds = CGDisplayBounds (display); // origin top-left
+#ifdef VERBOSE_ON
+ BOOL usesGL = CGDisplayUsesOpenGLAcceleration(display);
+ NSRect sFrame = [screen frame]; // origin bottom-left
+ DBG_PRINT( "getMonitorProps0: scrn %d, top-left displayBounds[%d/%d %dx%d], bottom-left screenFrame[%d/%d %dx%d], usesGL %d\n", (int)crt_idx,
+ (int)dBounds.origin.x, (int)dBounds.origin.y, (int)dBounds.size.width, (int)dBounds.size.height,
+ (int)sFrame.origin.x, (int)sFrame.origin.y, (int)sFrame.size.width, (int)sFrame.size.height,
+ (int)usesGL);
+#endif
- jintArray properties = (*env)->NewIntArray(env, 2);
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES;
+ jint prop[ propCount ];
+ int offset = 0;
+ prop[offset++] = propCount;
+ prop[offset++] = crt_idx;
+ prop[offset++] = (jint) sizeMM.width;
+ prop[offset++] = (jint) sizeMM.height;
+ prop[offset++] = (jint) dBounds.origin.x; // rotated viewport x (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.origin.y; // rotated viewport y (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.width; // rotated viewport width (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.height; // rotated viewport height (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.origin.x; // rotated viewport x (window units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.origin.y; // rotated viewport y (window units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.width; // rotated viewport width (window units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.height; // rotated viewport height (window units, will be fixed in java code)
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2");
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
}
- (*env)->SetIntArrayRegion(env, properties, 0, 2, prop);
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
[pool release];
@@ -374,16 +541,26 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
/*
* Class: jogamp_newt_driver_macosx_ScreenDriver
- * Method: getScreenMode0
- * Signature: (IIII)[I
+ * Method: getMonitorMode0
+ * Signature: (II)[I
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScreenMode0
- (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx, jint widthMM, jint heightMM)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorMode0
+ (JNIEnv *env, jobject obj, jint crt_idx, jint mode_idx)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL;
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+ if( NULL == screen ) {
+ [pool release];
+ return NULL;
+ }
+ CGFloat pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen backingScaleFactor]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
CFArrayRef availableModes = CGDisplayAvailableModes(display);
@@ -392,12 +569,13 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
CFDictionaryRef mode = NULL;
int currentCCWRot = (int)CGDisplayRotation(display);
jint ccwRot = 0;
+ int nativeId = 0;
#ifdef VERBOSE_ON
if(0 >= mode_idx) {
// only for current mode (-1) and first mode (scanning)
- DBG_PRINT( "getScreenMode0: scrn %d (%p, %p), mode %d, avail: %d/%d, current rot %d ccw\n",
- (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot);
+ DBG_PRINT( "getScreenMode0: scrn %d (s %p, d %p, pscale %lf), mode %d, avail: %d/%d, current rot %d ccw\n",
+ (int)crt_idx, screen, (void*)(intptr_t)display, pixelScale, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot);
}
#endif
@@ -406,21 +584,27 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
DBG_PRINT( "getScreenMode0: end of modes: mode %d, avail: %d/%d\n",
(int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
[pool release];
- return (*env)->NewIntArray(env, 0);
+ return NULL;
} else if(-1 < mode_idx) {
// only at initialization time, where index >= 0
- prop_num++; // add 1st extra prop, mode_idx
- mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE);
+ nativeId = mode_idx / ROTMODES_PER_REALMODE;
ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90;
+ mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId);
} else {
// current mode
mode = CGDisplayCurrentMode(display);
ccwRot = currentCCWRot;
+ CFRange range = CFRangeMake (0, numberOfAvailableModes);
+ nativeId = CFArrayGetFirstIndexOfValue(availableModes, range, (CFDictionaryRef)mode);
}
// mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
int mWidth = CGDDGetModeWidth(mode);
int mHeight = CGDDGetModeHeight(mode);
+ if( -1 == mode_idx ) {
+ mWidth *= (int)pixelScale; // accomodate HiDPI
+ mHeight *= (int)pixelScale; // accomodate HiDPI
+ }
// swap width and height, since OSX reflects rotated dimension, we don't
if ( 90 == currentCCWRot || 270 == currentCCWRot ) {
@@ -429,36 +613,30 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
mHeight = tempWidth;
}
- jint prop[ prop_num ];
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
int propIndex = 0;
- int propIndexRes = 0;
- if( -1 < mode_idx ) {
- prop[propIndex++] = mode_idx;
- }
int refreshRate = CGDDGetModeRefreshRate(mode);
int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8)
- prop[propIndex++] = 0; // set later for verification of iterator
- propIndexRes = propIndex;
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
prop[propIndex++] = mWidth;
prop[propIndex++] = mHeight;
prop[propIndex++] = CGDDGetModeBitsPerPixel(mode);
- prop[propIndex++] = widthMM;
- prop[propIndex++] = heightMM;
- prop[propIndex++] = fRefreshRate;
+ prop[propIndex++] = fRefreshRate * 100; // Hz*100
+ prop[propIndex++] = 0; // flags
+ prop[propIndex++] = nativeId;
prop[propIndex++] = ccwRot;
- prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL
-
- DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d / %d Hz, rot %d ccw\n",
+
+ DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %d / %d Hz, nativeId %d, rot %d ccw\n",
(int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes,
- (int)prop[propIndexRes+0], (int)prop[propIndexRes+1], (int)prop[propIndexRes+2],
- (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], refreshRate, (int)prop[propIndexRes+6]);
+ (int)prop[1], (int)prop[2], (int)prop[3],
+ (int)prop[4], refreshRate, (int)prop[6], (int)prop[7]);
- jintArray properties = (*env)->NewIntArray(env, prop_num);
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num);
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
}
- (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop);
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
// CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef
[pool release];
@@ -468,36 +646,47 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
/*
* Class: jogamp_newt_driver_macosx_ScreenDriver
- * Method: setScreenMode0
- * Signature: (II)Z
+ * Method: setMonitorMode0
+ * Signature: (III)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setScreenMode0
- (JNIEnv *env, jobject object, jint scrn_idx, jint mode_idx)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setMonitorMode0
+ (JNIEnv *env, jobject object, jint crt_idx, jint nativeId, jint ccwRot)
{
jboolean res = JNI_TRUE;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+ if( NULL == screen ) {
+ [pool release];
+ return JNI_FALSE;
+ }
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
CFArrayRef availableModes = CGDisplayAvailableModes(display);
-#ifdef VERBOSE_ON
CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes);
+#ifdef VERBOSE_ON
CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes;
#endif
- CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE);
- // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
- int ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90;
- DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), mode %d, rot %d ccw, avail: %d/%d\n",
- (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
+ DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), nativeID %d, rot %d ccw, avail: %d/%d\n",
+ (int)crt_idx, screen, (void*)(intptr_t)display, (int)nativeId, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
+
+ CFDictionaryRef mode = NULL;
- if(ccwRot!=0) {
+ if( 0 != ccwRot ) {
// FIXME: How to rotate the display/screen on OSX programmatically ?
DBG_PRINT( "setScreenMode0: Don't know how to rotate screen on OS X: rot %d ccw\n", ccwRot);
res = JNI_FALSE;
+ } else {
+ if( numberOfAvailableModes <= nativeId ) {
+ res = JNI_FALSE;
+ } else {
+ mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId);
+ // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
+ }
}
- if(JNI_TRUE == res) {
+
+ if( NULL != mode ) {
CGError err = CGDisplaySwitchToMode(display, mode);
if(kCGErrorSuccess != err) {
DBG_PRINT( "setScreenMode0: SetMode failed: %d\n", (int)err);
@@ -526,6 +715,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtScreen_dump();
+
jclass c;
c = (*env)->FindClass(env, ClazzNamePoint);
if(NULL==c) {
@@ -553,48 +744,106 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0
return (jboolean) res;
}
-/*
+/**
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: createView0
+ * Signature: (IIII)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createView0
+ (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT( "createView0 - %p (this), %d/%d %dx%d (START)\n",
+ (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h);
+
+ NSRect rectView = NSMakeRect(0, 0, w, h);
+ NewtView *myView = [[NewtView alloc] initWithFrame: rectView] ;
+ DBG_PRINT( "createView0.X - new view: %p\n", myView);
+
+ [pool release];
+
+ return (jlong) (intptr_t) myView;
+}
+
+/**
+ * Method creates a deferred un-initialized Window, hence no special invocation required inside method.
+ *
* Class: jogamp_newt_driver_macosx_WindowDriver
* Method: createWindow0
- * Signature: (JIIIIZIIIJ)J
+ * Signature: (IIIIZIIJ)J
*/
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow0
- (JNIEnv *env, jobject jthis, jlong parent, jint x, jint y, jint w, jint h, jboolean opaque, jboolean fullscreen, jint styleMask,
- jint bufferingType, jint screen_idx, jlong jview)
+ (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h,
+ jboolean fullscreen, jint styleMask, jint bufferingType, jlong jview)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* myView = (NewtView*) (intptr_t) jview ;
- DBG_PRINT( "createWindow0 - %p (this), %p (parent), %d/%d %dx%d, opaque %d, fs %d, style %X, buffType %X, screenidx %d, view %p (START)\n",
- (void*)(intptr_t)jthis, (void*)(intptr_t)parent, (int)x, (int)y, (int)w, (int)h, (int) opaque, (int)fullscreen,
- (int)styleMask, (int)bufferingType, (int)screen_idx, myView);
-
- NSArray *screens = [NSScreen screens];
- if(screen_idx<0) screen_idx=0;
- if(screen_idx>=[screens count]) screen_idx=0;
- NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx];
- NSRect rect;
+ DBG_PRINT( "createWindow0 - %p (this), %d/%d %dx%d, fs %d, style %X, buffType %X, view %p (START)\n",
+ (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen,
+ (int)styleMask, (int)bufferingType, myView);
+ (void)myView;
if (fullscreen) {
styleMask = NSBorderlessWindowMask;
- rect = [myScreen frame];
- x = 0;
- y = 0;
- w = (jint) (rect.size.width);
- h = (jint) (rect.size.height);
- } else {
- rect = NSMakeRect(x, y, w, h);
}
+ NSRect rectWin = NSMakeRect(x, y, w, h);
// Allocate the window
- NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rect
+ NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rectWin
styleMask: (NSUInteger) styleMask
backing: (NSBackingStoreType) bufferingType
- defer: NO
- screen: myScreen
+ defer: YES
isFullscreenWindow: fullscreen];
- [myWindow setReleasedWhenClosed: YES]; // default
+ // DBG_PRINT( "createWindow0.1 - %p, isVisible %d\n", myWindow, [myWindow isVisible]);
+
+ DBG_PRINT( "createWindow0.X - %p, isVisible %d\n", myWindow, [myWindow isVisible]);
+
+ [pool release];
+
+ return (jlong) ((intptr_t) myWindow);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: initWindow0
+ * Signature: (JJIIIIFZZZJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0
+ (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, jfloat reqPixelScale,
+ jboolean opaque, jboolean visible, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window);
+ NewtView* myView = (NewtView*) (intptr_t) jview ;
+ BOOL fullscreen = myWindow->isFullscreenWindow;
+
+ DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, reqPixScale %f, opaque %d, fs %d, visible %d, view %p (START)\n",
+ (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, (float)reqPixelScale,
+ (int) opaque, (int)fullscreen, (int)visible, myView);
+
+NS_DURING
+ // HiDPI scaling: Setup - Available >= 10.7
+ if( 1.0 == reqPixelScale ) {
+ [myView setWantsBestResolutionOpenGLSurface: NO];
+ } else {
+ [myView setWantsBestResolutionOpenGLSurface: YES];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ [myWindow setReleasedWhenClosed: NO]; // We control NSWindow destruction!
[myWindow setPreservesContentDuringLiveResize: NO];
+NS_DURING
+ if ( [myWindow respondsToSelector:@selector(setRestorable:)] ) {
+ // Available >= 10.7 - Removes restauration 'feature', really close
+ [myWindow setRestorable: NO];
+ }
+NS_HANDLER
+NS_ENDHANDLER
NSObject* nsParentObj = (NSObject*) ((intptr_t) parent);
NSWindow* parentWindow = NULL;
@@ -602,15 +851,15 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow
if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) {
parentWindow = (NSWindow*) nsParentObj;
parentView = [parentWindow contentView];
- DBG_PRINT( "createWindow0 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView);
+ DBG_PRINT( "initWindow0 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView);
} else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) {
parentView = (NSView*) nsParentObj;
parentWindow = [parentView window];
- DBG_PRINT( "createWindow0 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow);
+ DBG_PRINT( "initWindow0 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow);
} else {
- DBG_PRINT( "createWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj);
+ DBG_PRINT( "initWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj);
}
- DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]);
+ DBG_PRINT( "initWindow0 - is visible.1: %d\n", [myWindow isVisible]);
// Remove animations for child windows
if(NULL != parentWindow) {
@@ -628,11 +877,11 @@ NS_ENDHANDLER
#endif
if(opaque) {
[myWindow setOpaque: YES];
- DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
+ DBG_PRINT( "initWindow0.%d\n", dbgIdx++);
if (!fullscreen) {
[myWindow setShowsResizeIndicator: YES];
}
- DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
+ DBG_PRINT( "initWindow0.%d\n", dbgIdx++);
} else {
[myWindow setOpaque: NO];
[myWindow setBackgroundColor: [NSColor clearColor]];
@@ -640,35 +889,29 @@ NS_ENDHANDLER
// specify we want mouse-moved events
[myWindow setAcceptsMouseMovedEvents:YES];
- DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
- // Use given NewtView or allocate an NewtView if NULL
- if(NULL == myView) {
- myView = [[NewtView alloc] initWithFrame: rect] ;
- DBG_PRINT( "createWindow0.%d - use new view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView));
- } else {
- DBG_PRINT( "createWindow0.%d - use given view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView));
- }
-
- DBG_PRINT( "createWindow0.%d - %p,%d view %p,%d, isVisible %d\n",
- dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
// Set the content view
- changeContentView(env, jthis, parentView, myWindow, myView);
+ changeContentView(env, jthis, parentView, myWindow, myView, NO);
+ [myWindow setInitialFirstResponder: myView];
- DBG_PRINT( "createWindow0.%d - %p,%d view %p,%d, isVisible %d\n",
- dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
if(NULL!=parentWindow) {
[myWindow attachToParent: parentWindow];
}
- // Immediately re-position the window based on an upper-left coordinate system
- setFrameTopLeftPoint(parentWindow, myWindow, x, y);
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d, visible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible], visible);
- // force surface creation
- [myView lockFocus];
- [myView unlockFocus];
+ // Immediately re-position this window based on an upper-left coordinate system
+ setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO);
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
NS_DURING
// concurrent view rendering
@@ -676,49 +919,115 @@ NS_DURING
if ( [myWindow respondsToSelector:@selector(setAllowsConcurrentViewDrawing:)] ) {
[myWindow setAllowsConcurrentViewDrawing: YES];
}
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
if ( [myView respondsToSelector:@selector(setCanDrawConcurrently:)] ) {
[myView setCanDrawConcurrently: YES];
}
NS_HANDLER
NS_ENDHANDLER
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
// visible on front
- [myWindow orderFront: myWindow];
+ if( visible ) {
+ [myWindow orderFront: myWindow];
+ }
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
+ // force surface creation
+ // [myView lockFocus];
+ // [myView unlockFocus];
+
+ // Set the next responder to be the window so that we can forward
+ // right mouse button down events
+ [myView setNextResponder: myWindow];
+
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
+
+ [myView setDestroyNotifySent: false];
+ setJavaWindowObject(env, jthis, myView, YES);
+
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
NS_DURING
- // Available >= 10.5 - Makes the menubar disapear
- if(fullscreen) {
+ if( fullscreen ) {
+ /**
+ * See Bug 914: We don't use exclusive fullscreen anymore (capturing display)
+ * allowing ALT-TAB to allow process/app switching!
+ * Shall have no penalty on modern GPU and is also recommended, see bottom box @
+ * <https://developer.apple.com/library/mac/documentation/graphicsimaging/Conceptual/QuartzDisplayServicesConceptual/Articles/DisplayCapture.html>
+ *
+ NSScreen *myScreen = NewtScreen_getNSScreenByCoord(x, y);
if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) {
+ // Available >= 10.5 - Makes the menubar disapear
[myView enterFullScreenMode: myScreen withOptions:NULL];
+ } */
+ if( myWindow->hasPresentationSwitch ) {
+ DBG_PRINT( "initWindow0.%d - %p view %p, setPresentationOptions 0x%X\n",
+ dbgIdx++, myWindow, myView, (int)myWindow->fullscreenPresentationOptions);
+ [NSApp setPresentationOptions: myWindow->fullscreenPresentationOptions];
}
}
NS_HANDLER
NS_ENDHANDLER
- // Set the next responder to be the window so that we can forward
- // right mouse button down events
- [myView setNextResponder: myWindow];
-
- DBG_PRINT( "createWindow0 - %p (this), %p (parent): new window: %p, view %p,%d (END)\n",
- (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView, getRetainCount(myView));
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
[pool release];
-
- return (jlong) ((intptr_t) myWindow);
+ DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p\n",
+ (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
}
-// Footnote: Our view handling produces random 'Assertion failure' even w/o parenting:
-//
-// [NSThemeFrame lockFocus], /SourceCache/AppKit/AppKit-1138.23/AppKit.subproj/NSView.m:6053
-// [NSThemeFrame(0x7fe94bc72c80) lockFocus] failed with window=0x7fe94bc445a0, windowNumber=9425, [self isHiddenOrHasHiddenAncestor]=0
-// ..
-// AppKit 0x00007fff89621001 -[NSView lockFocus] + 250
-// AppKit 0x00007fff8961eafa -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 3780
-// AppKit 0x00007fff8961793e -[NSView displayIfNeeded] + 1676
-// AppKit 0x00007fff8961707d _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints + 648
-//
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: setPixelScale0
+ * Signature: (JJF)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPixelScale0
+ (JNIEnv *env, jobject jthis, jlong window, jlong view, jfloat reqPixelScale)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window);
+ NewtView* myView = (NewtView*) (intptr_t) view ;
+#ifdef VERBOSE_ON
+ int dbgIdx = 1;
+#endif
+
+ DBG_PRINT( "setPixelScale0 - %p (this), %p (window), view %p, reqPixScale %f (START)\n",
+ (void*)(intptr_t)jthis, myWindow, myView, (float)reqPixelScale);
-/*
+NS_DURING
+ // HiDPI scaling: Setup - Available >= 10.7
+ if( 1.0 == reqPixelScale ) {
+ [myView setWantsBestResolutionOpenGLSurface: NO];
+ } else {
+ [myView setWantsBestResolutionOpenGLSurface: YES];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ DBG_PRINT( "setPixelScale0.%d - %p (this), window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, myWindow, myView);
+
+ [pool release];
+ DBG_PRINT( "setPixelScale0.X - %p (this), window: %p, view %p\n",
+ (void*)(intptr_t)jthis, myWindow, myView);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
* Class: jogamp_newt_driver_macosx_WindowDriver
* Method: close0
* Signature: (J)V
@@ -726,31 +1035,50 @@ NS_ENDHANDLER
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0
(JNIEnv *env, jobject unused, jlong window)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "windowClose.0 - NULL NEWT win - abort\n");
+ return;
+ }
+ BOOL isNSWin = [mWin isKindOfClass:[NSWindow class]];
+ BOOL isNewtWin = [mWin isKindOfClass:[NewtMacWindow class]];
+ NSWindow *pWin = [mWin parentWindow];
+ DBG_PRINT( "windowClose.0 - %p [isNSWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin);
+ (void)isNSWin; // silence
+ if( !isNewtWin ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* mView = (NewtView *)[mWin contentView];
- NSWindow* pWin = [mWin parentWindow];
- BOOL destroyNotifySent = (NULL != mView) ? [mView getDestroyNotifySent] : false;
+ BOOL fullscreen = mWin->isFullscreenWindow;
+ BOOL destroyNotifySent, isNSView, isNewtView;
+ if( NULL != mView ) {
+ isNSView = [mView isKindOfClass:[NSView class]];
+ isNewtView = [mView isKindOfClass:[NewtView class]];
+ destroyNotifySent = isNewtView ? [mView getDestroyNotifySent] : false;
+ } else {
+ isNSView = false;
+ isNewtView = false;
+ destroyNotifySent = false;
+ }
- DBG_PRINT( "windowClose.0 - %p,%d, destroyNotifySent %d, view %p,%d, parent %p\n",
- mWin, getRetainCount(mWin), destroyNotifySent, mView, getRetainCount(mView), pWin);
+ DBG_PRINT( "windowClose.0 - %p, destroyNotifySent %d, view %p [isNSView %d, isNewtView %d], fullscreen %d, parent %p\n",
+ mWin, destroyNotifySent, mView, isNSView, isNewtView, (int)fullscreen, pWin);
- [mWin setUnrealized];
+ [mWin setRealized: NO];
- if(NULL!=mView) {
+ if( isNewtView ) {
// cleanup view
- jobject javaWindowObject = [mView getJavaWindowObject];
[mView setDestroyNotifySent: true];
- if(NULL!=javaWindowObject) {
- DBG_PRINT( "windowClose.0: Clear global javaWindowObject reference (%p)\n", javaWindowObject);
- (*env)->DeleteGlobalRef(env, javaWindowObject);
- [mView setJavaWindowObject: NULL];
- }
+ setJavaWindowObject(env, NULL, mView, NO);
}
NS_DURING
+ /**
+ * See Bug 914: We don't use exclusive fullscreen anymore (capturing display)
+ * See initWindow0(..) above ..
if(NULL!=mView) {
- // Available >= 10.5 - Makes the menubar disapear
BOOL iifs;
if ( [mView respondsToSelector:@selector(isInFullScreenMode)] ) {
iifs = [mView isInFullScreenMode];
@@ -760,9 +1088,15 @@ NS_DURING
if(iifs && [mView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) {
[mView exitFullScreenModeWithOptions: NULL];
}
- // Note: mWin's release will also release it's mView!
- // [mWin setContentView: nil];
- // [mView release];
+ } */
+ // Note: mWin's release will also release it's mView!
+ DBG_PRINT( "windowClose.1a - %p view %p, fullscreen %d, hasPresSwitch %d, defaultPresentationOptions 0x%X\n",
+ mWin, mView, (int)fullscreen, (int)mWin->hasPresentationSwitch, (int)mWin->defaultPresentationOptions);
+
+ if( fullscreen && mWin->hasPresentationSwitch ) {
+ DBG_PRINT( "windowClose.1b - %p view %p, setPresentationOptions 0x%X\n",
+ mWin, mView, (int)mWin->defaultPresentationOptions);
+ [NSApp setPresentationOptions: mWin->defaultPresentationOptions];
}
NS_HANDLER
NS_ENDHANDLER
@@ -770,19 +1104,13 @@ NS_ENDHANDLER
if(NULL!=pWin) {
[mWin detachFromParent: pWin];
}
- [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
+ [mWin orderOut: mWin];
- DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n",
- mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin);
+ DBG_PRINT( "windowClose.2 - %p view %p, parent %p\n", mWin, mView, pWin);
- // Only release window, if release is not yet in process.
- // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked.
- if(!destroyNotifySent) {
- [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
- }
+ [mWin release];
- DBG_PRINT( "windowClose.X - %p,%d, released %d, view %p,%d, parent %p\n",
- mWin, getRetainCount(mWin), !destroyNotifySent, mView, getRetainCount(mView), pWin);
+ DBG_PRINT( "windowClose.Xp\n");
[pool release];
}
@@ -790,16 +1118,16 @@ NS_ENDHANDLER
/*
* Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: lockSurface0
- * Signature: (J)Z
+ * Signature: (JJ)Z
*/
JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurface0
- (JNIEnv *env, jclass clazz, jlong window)
+ (JNIEnv *env, jclass clazz, jlong window, jlong view)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
if(NO == [mWin isRealized]) {
return JNI_FALSE;
}
- NewtView * mView = (NewtView *) [mWin contentView];
+ NewtView * mView = (NewtView *) ((intptr_t) view);
return [mView softLock] == YES ? JNI_TRUE : JNI_FALSE;
/** deadlocks, since we render independent of focus
return [mView lockFocusIfCanDraw] == YES ? JNI_TRUE : JNI_FALSE; */
@@ -808,14 +1136,15 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurfa
/*
* Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: unlockSurface0
- * Signature: (J)V
+ * Signature: (JJ)Z
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0
- (JNIEnv *env, jclass clazz, jlong window)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0
+ (JNIEnv *env, jclass clazz, jlong window, jlong view)
{
- NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- NewtView * mView = (NewtView *) [mWin contentView];
- [mView softUnlock];
+ // NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
+ (void) window;
+ NewtView * mView = (NewtView *) ((intptr_t) view);
+ return [mView softUnlock] == YES ? JNI_TRUE : JNI_FALSE;
/** deadlocks, since we render independent of focus
[mView unlockFocus]; */
}
@@ -833,12 +1162,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0
#ifdef VERBOSE_ON
BOOL hasFocus = [mWin isKeyWindow];
#endif
-
DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus);
+ [mWin setAcceptsMouseMovedEvents: YES];
[mWin makeFirstResponder: nil];
- [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO];
- [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO];
+ [mWin orderFrontRegardless];
+ [mWin makeKeyWindow];
DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force);
@@ -861,10 +1190,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0
DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
if( hasFocus ) {
if(NULL != pWin) {
- // [mWin performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:pWin waitUntilDone:NO];
- [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO];
+ // [mWin makeFirstResponder: pWin];
+ [pWin makeKeyWindow];
} else {
- [mWin performSelectorOnMainThread:@selector(resignKeyWindow) withObject:nil waitUntilDone:NO];
+ [pWin resignKeyWindow];
}
}
DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin);
@@ -881,13 +1210,18 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0
(JNIEnv *env, jobject unused, jlong window)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NSWindow* mWin = (NSWindow*) ((intptr_t) window);
+ NSWindow* pWin = [mWin parentWindow];
- DBG_PRINT( "orderFront0 - window: %p (START)\n", win);
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
- [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO];
+ if( NULL == pWin ) {
+ [mWin orderFrontRegardless];
+ } else {
+ [mWin orderWindow: NSWindowAbove relativeTo: [pWin windowNumber]];
+ }
- DBG_PRINT( "orderFront0 - window: %p (END)\n", win);
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p (END)\n", pWin, mWin);
[pool release];
}
@@ -904,12 +1238,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0
NSWindow* mWin = (NSWindow*) ((intptr_t) window);
NSWindow* pWin = [mWin parentWindow];
- DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin);
+ DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
- if(NULL == pWin) {
- [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
+ if( NULL == pWin ) {
+ [mWin orderOut: mWin];
} else {
- [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:NO];
+ [mWin orderWindow: NSWindowOut relativeTo: [pWin windowNumber]];
}
DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin);
@@ -941,7 +1275,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setTitle0
/*
* Class: jogamp_newt_driver_macosx_WindowDriver
- * Method: contentView
+ * Method: contentView0
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0
@@ -949,38 +1283,38 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NSView* nsView = [win contentView];
+ NewtView* newtView = NULL;
- DBG_PRINT( "contentView0 - window: %p (START)\n", win);
+ if( [nsView isKindOfClass:[NewtView class]] ) {
+ newtView = (NewtView *) nsView;
+ }
- jlong res = (jlong) ((intptr_t) [win contentView]);
+ DBG_PRINT( "contentView0 - window: %p, view: %p, newtView %p\n", win, nsView, newtView);
- DBG_PRINT( "contentView0 - window: %p (END)\n", win);
+ jlong res = (jlong) ((intptr_t) nsView);
[pool release];
return res;
}
-/*
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
* Class: jogamp_newt_driver_macosx_WindowDriver
* Method: changeContentView
- * Signature: (J)J
+ * Signature: (J)V
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0
(JNIEnv *env, jobject jthis, jlong parentWindowOrView, jlong window, jlong jview)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* newView = (NewtView *) ((intptr_t) jview);
NewtMacWindow* win = (NewtMacWindow*) ((intptr_t) window);
- NSView* oldNSView = [win contentView];
- NewtView* oldView = NULL;
- if( [oldNSView isMemberOfClass:[NewtView class]] ) {
- oldView = (NewtView *) oldNSView;
- }
-
- DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d (%d) -> %p,%d)\n",
- win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+ DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d)\n",
+ win, newView, getRetainCount(newView));
NSObject *nsParentObj = (NSObject*) ((intptr_t) parentWindowOrView);
NSView* pView = NULL;
@@ -993,62 +1327,49 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeConten
}
}
- changeContentView(env, jthis, pView, win, newView);
+ changeContentView(env, jthis, pView, win, newView, YES);
- DBG_PRINT( "changeContentView0.X - win %p, view (%p,%d (%d) -> %p,%d)\n",
- win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+ DBG_PRINT( "changeContentView0.X\n");
[pool release];
-
- return (jlong) ((intptr_t) oldView);
}
/*
* Class: jogamp_newt_driver_macosx_WindowDriver
- * Method: setContentSize
- * Signature: (JII)V
+ * Method: setWindowClientTopLeftPointAndSize0
+ * Signature: (JIIIIZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setContentSize0
- (JNIEnv *env, jobject unused, jlong window, jint w, jint h)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
- DBG_PRINT( "setContentSize0 - window: %p (START)\n", win);
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin);
- NSSize sz = NSMakeSize(w, h);
- [win setContentSize: sz];
+ setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display);
- DBG_PRINT( "setContentSize0 - window: %p (END)\n", win);
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin);
[pool release];
}
/*
* Class: jogamp_newt_driver_macosx_WindowDriver
- * Method: setFrameTopLeftPoint
- * Signature: (JJII)V
+ * Method: setWindowClientTopLeftPoint0
+ * Signature: (JIIZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setFrameTopLeftPoint0
- (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
- NSObject *nsParentObj = (NSObject*) ((intptr_t) parent);
- NSWindow* pWin = NULL;
- if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) {
- pWin = (NSWindow*) nsParentObj;
- } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) {
- NSView* pView = (NSView*) nsParentObj;
- pWin = [pView window];
- }
-
- DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (START)\n", mWin, pWin);
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin);
- setFrameTopLeftPoint(pWin, mWin, x, y);
+ setWindowClientTopLeftPoint(mWin, x, y, display);
- DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (END)\n", mWin, pWin);
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin);
[pool release];
}
@@ -1064,7 +1385,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* win = (NSWindow*) ((intptr_t) window);
- DBG_PRINT( "setAlwaysOnTop0 - window: %p (START)\n", win);
+ DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (START)\n", win, (int)atop);
if(atop) {
[win setLevel:NSFloatingWindowLevel];
@@ -1072,7 +1393,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo
[win setLevel:NSNormalWindowLevel];
}
- DBG_PRINT( "setAlwaysOnTop0 - window: %p (END)\n", win);
+ DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (END)\n", win, (int)atop);
[pool release];
}
@@ -1085,31 +1406,60 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo
JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocationOnScreen0
(JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y)
{
- NSObject *nsObj = (NSObject*) ((intptr_t) win);
- NewtMacWindow * mWin = NULL;
-
- if( [nsObj isKindOfClass:[NewtMacWindow class]] ) {
- mWin = (NewtMacWindow*) nsObj;
- } else {
- NewtCommon_throwNewRuntimeException(env, "not NewtMacWindow %p\n", nsObj);
+ NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) win;
+ if( ![mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return NULL;
}
-
NSPoint p0 = [mWin getLocationOnScreen: NSMakePoint(src_x, src_y)];
return (*env)->NewObject(env, pointClz, pointCstr, (jint)p0.x, (jint)p0.y);
}
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0
+ (JNIEnv *env, jobject unused, jlong window, jlong handle)
+{
+ NSCursor *c = (NSCursor*) (intptr_t) handle ;
+ if ( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c);
+ return;
+ }
+ NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window;
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setPointerIcon: c];
+ [pool release];
+}
+
/*
* Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: setPointerVisible0
* Signature: (JZ)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0
(JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- [mWin setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO
- hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO];
- return JNI_TRUE;
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO
+ hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO];
+ [pool release];
}
/*
@@ -1117,12 +1467,22 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointe
* Method: confinePointer0
* Signature: (JZ)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0
(JNIEnv *env, jclass clazz, jlong window, jboolean confine)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- [mWin setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO];
- return JNI_TRUE;
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO];
+ [pool release];
}
/*
@@ -1134,6 +1494,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0
(JNIEnv *env, jclass clazz, jlong window, jint x, jint y)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- [mWin setMousePosition: [mWin newtClientWinPos2OSXScreenPos: NSMakePoint(x, y)]];
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setMousePosition: [mWin newtRelClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]];
+ [pool release];
}
diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c
index 7f070e7d3..231d6182f 100644
--- a/src/newt/native/NewtCommon.c
+++ b/src/newt/native/NewtCommon.c
@@ -5,17 +5,43 @@
static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
static jclass runtimeExceptionClz=NULL;
+static JavaVM *_jvmHandle = NULL;
+static int _jvmVersion = 0;
+
+void NewtCommon_init(JNIEnv *env) {
+ if(NULL==_jvmHandle) {
+ if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+ NewtCommon_FatalError(env, "NEWT: Can't fetch JavaVM handle");
+ } else {
+ _jvmVersion = (*env)->GetVersion(env);
+ }
+ jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
+ if(NULL==c) {
+ NewtCommon_FatalError(env, "NEWT: Can't find %s", ClazzNameRuntimeException);
+ }
+ runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==runtimeExceptionClz) {
+ NewtCommon_FatalError(env, "NEWT: Can't use %s", ClazzNameRuntimeException);
+ }
+ }
+}
+
void NewtCommon_FatalError(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
- fprintf(stderr, "%s\n", buffer);
- (*env)->FatalError(env, buffer);
+ fprintf(stderr, "%s\n", buffer);
+ if(NULL != env) {
+ (*env)->FatalError(env, buffer);
+ }
+ }
}
void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
@@ -23,23 +49,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if(NULL==_jvmHandle) {
+ NewtCommon_FatalError(env, "NEWT: NULL JVM handle, call NewtCommon_init 1st\n");
+ return;
+ }
- (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
-}
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
-void NewtCommon_init(JNIEnv *env) {
- if(NULL==runtimeExceptionClz) {
- jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
- if(NULL==c) {
- NewtCommon_FatalError(env, "NEWT: can't find %s", ClazzNameRuntimeException);
- }
- runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==runtimeExceptionClz) {
- NewtCommon_FatalError(env, "NEWT: can't use %s", ClazzNameRuntimeException);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
}
}
}
@@ -65,37 +86,57 @@ const char * NewtCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmet
jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
{
jchar* strChars = NULL;
- strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
- if (strChars != NULL) {
- (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ if( NULL != env && 0 != str ) {
+ strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
+ if (strChars != NULL) {
+ (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ }
}
return strChars;
}
-JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached) {
+JNIEnv* NewtCommon_GetJNIEnv(int asDaemon, int * shallBeDetached) {
JNIEnv* curEnv = NULL;
JNIEnv* newEnv = NULL;
int envRes;
+ if(NULL==_jvmHandle) {
+ fprintf(stderr, "NEWT GetJNIEnv: NULL JVM handle, call NewtCommon_init 1st\n");
+ return NULL;
+ }
+
// retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
+ envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ;
if( JNI_EDETACHED == envRes ) {
// detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
+ if( asDaemon ) {
+ envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL);
+ } else {
+ envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL);
+ }
+ if( JNI_OK != envRes ) {
+ fprintf(stderr, "NEWT GetJNIEnv: Can't attach thread: %d\n", envRes);
return NULL;
}
curEnv = newEnv;
} else if( JNI_OK != envRes ) {
// oops ..
- fprintf(stderr, "can't GetEnv: %d\n", envRes);
+ fprintf(stderr, "NEWT GetJNIEnv: Can't GetEnv: %d\n", envRes);
return NULL;
}
if (curEnv==NULL) {
- fprintf(stderr, "env is NULL\n");
+ fprintf(stderr, "NEWT GetJNIEnv: env is NULL\n");
return NULL;
}
*shallBeDetached = NULL != newEnv;
return curEnv;
}
+void NewtCommon_ReleaseJNIEnv (int shallBeDetached) {
+ if(NULL == _jvmHandle) {
+ fprintf(stderr, "NEWT ReleaseJNIEnv: No JavaVM handle registered, call NewtCommon_init(..) 1st");
+ } else if(shallBeDetached) {
+ (*_jvmHandle)->DetachCurrentThread(_jvmHandle);
+ }
+}
+
diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h
index 9a4e5ac70..43db72b5b 100644
--- a/src/newt/native/NewtCommon.h
+++ b/src/newt/native/NewtCommon.h
@@ -42,23 +42,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
/**
*
- * 1) Store jvmHandle and jvmVersion
+ * 1) Init static jvmHandle, jvmVersion and clazz references
+ * from an early initialization call w/ valid 'JNIEnv * env'
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
-
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- } else {
- jvmVersion = (*env)->GetVersion(env);
- }
+ NewtCommon_init(env);
*
* 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv
*
+ int asDaemon = 0;
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("drawRect: null JNIEnv\n");
return;
@@ -70,12 +65,13 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
.. your JNIEnv code here ..
*
- * 4) Detach thread from JVM, if required
+ * 4) Detach thread from JVM if required, i.e. not attached as daemon!
+ * Not recommended for recurring _daemon_ threads (performance)
*
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
*/
-JNIEnv* NewtCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached);
+JNIEnv* NewtCommon_GetJNIEnv (int asDaemon, int * shallBeDetached);
+
+void NewtCommon_ReleaseJNIEnv (int shallBeDetached);
#endif
diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h
index c0912ad3c..0f80df2d7 100644
--- a/src/newt/native/NewtMacWindow.h
+++ b/src/newt/native/NewtMacWindow.h
@@ -41,53 +41,55 @@
// #define VERBOSE_ON 1
#ifdef VERBOSE_ON
- #define DBG_PRINT(...) NSLog(@ __VA_ARGS__)
+ #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) ; fflush(stderr)
// #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
#else
#define DBG_PRINT(...)
#endif
+// #define DBG_LIFECYCLE 1
+
+NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx, BOOL cap);
+NSScreen * NewtScreen_getNSScreenByCoord(int x, int y);
+CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen);
+
@interface NewtView : NSView
{
jobject javaWindowObject;
- // This is set while messages are being dispatched and cleared afterward
- JavaVM *jvmHandle;
- int jvmVersion;
-
volatile BOOL destroyNotifySent;
- volatile BOOL softLocked;
+ volatile int softLockCount;
pthread_mutex_t softLockSync;
- NSTrackingRectTag ptrTrackingTag;
+ volatile NSTrackingRectTag ptrTrackingTag;
NSRect ptrRect;
NSCursor * myCursor;
+ BOOL modsDown[4]; // shift, ctrl, alt/option, win/command
+
+ BOOL mouseConfined;
+ BOOL mouseInside;
+ BOOL mouseVisible;
+ BOOL cursorIsHidden;
+ NSPoint lastInsideMousePosition;
}
- (id)initWithFrame:(NSRect)frameRect;
+
+#ifdef DBG_LIFECYCLE
- (void) release;
+#endif
- (void) dealloc;
-/* Set during event dispatching cycle */
-- (void) setJVMHandle: (JavaVM*) vm;
-- (JavaVM*) getJVMHandle;
-- (void) setJVMVersion: (int) ver;
-- (int) getJVMVersion;
-
/* Register or deregister (NULL) the java Window object,
ie, if NULL, no events are send */
- (void) setJavaWindowObject: (jobject) javaWindowObj;
- (jobject) getJavaWindowObject;
-- (void) rightMouseDown: (NSEvent*) theEvent;
-- (void) resetCursorRects;
-- (NSCursor *) cursor;
-
- (void) setDestroyNotifySent: (BOOL) v;
- (BOOL) getDestroyNotifySent;
- (BOOL) softLock;
-- (void) softUnlock;
+- (BOOL) softUnlock;
- (BOOL) needsDisplay;
- (void) displayIfNeeded;
@@ -96,6 +98,42 @@
- (void) viewDidHide;
- (void) viewDidUnhide;
- (BOOL) acceptsFirstResponder;
+- (BOOL) becomeFirstResponder;
+- (BOOL) resignFirstResponder;
+
+- (void) removeCursorRects;
+- (void) addCursorRects;
+- (void) removeMyCursor;
+- (void) resetCursorRects;
+- (void) setPointerIcon: (NSCursor*)c;
+- (void) mouseEntered: (NSEvent*) theEvent;
+- (void) mouseExited: (NSEvent*) theEvent;
+- (BOOL) updateMouseInside;
+- (void) cursorHide:(BOOL)v enter:(int)enterState;
+- (void) setPointerIcon:(NSCursor*)c;
+- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus;
+- (BOOL) isMouseVisible;
+- (void) setMouseConfined:(BOOL)v;
+- (void) setMousePosition:(NSPoint)p;
+- (void) mouseMoved: (NSEvent*) theEvent;
+- (void) scrollWheel: (NSEvent*) theEvent;
+- (void) mouseDown: (NSEvent*) theEvent;
+- (void) mouseDragged: (NSEvent*) theEvent;
+- (void) mouseUp: (NSEvent*) theEvent;
+- (void) rightMouseDown: (NSEvent*) theEvent;
+- (void) rightMouseDragged: (NSEvent*) theEvent;
+- (void) rightMouseUp: (NSEvent*) theEvent;
+- (void) otherMouseDown: (NSEvent*) theEvent;
+- (void) otherMouseDragged: (NSEvent*) theEvent;
+- (void) otherMouseUp: (NSEvent*) theEvent;
+- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType;
+- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p;
+
+- (void) handleFlagsChanged:(NSUInteger) mods;
+- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods;
+- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType;
+- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType;
+- (void) viewDidChangeBackingProperties;
@end
@@ -105,14 +143,12 @@
@interface NewtMacWindow : NSWindow
#endif
{
- BOOL isFullscreenWindow;
- BOOL mouseConfined;
- BOOL mouseVisible;
- BOOL mouseInside;
- BOOL cursorIsHidden;
BOOL realized;
- NSPoint lastInsideMousePosition;
@public
+ BOOL hasPresentationSwitch;
+ NSUInteger defaultPresentationOptions;
+ NSUInteger fullscreenPresentationOptions;
+ BOOL isFullscreenWindow;
int cachedInsets[4]; // l, r, t, b
}
@@ -122,32 +158,31 @@
styleMask: (NSUInteger) windowStyle
backing: (NSBackingStoreType) bufferingType
defer: (BOOL) deferCreation
- screen:(NSScreen *)screen
isFullscreenWindow:(BOOL)isfs;
+#ifdef DBG_LIFECYCLE
- (void) release;
+#endif
- (void) dealloc;
-- (void) setUnrealized;
+- (void) setRealized: (BOOL)v;
- (BOOL) isRealized;
-- (void) updateInsets: (JNIEnv*) env;
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin;
- (void) attachToParent: (NSWindow*) parent;
- (void) detachFromParent: (NSWindow*) parent;
-- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p;
-- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p;
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p;
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz;
+- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p;
+- (NSSize) newtClientSize2TLSize: (NSSize) nsz;
- (NSPoint) getLocationOnScreen: (NSPoint) p;
-- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p;
-
-- (BOOL) isMouseInside;
-- (void) cursorHide:(BOOL)v;
-- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus;
-- (void) setMouseConfined:(BOOL)v;
-- (void) setMousePosition:(NSPoint)p;
-- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType;
-- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType;
- (void) focusChanged: (BOOL) gained;
+- (void) keyDown: (NSEvent*) theEvent;
+- (void) keyUp: (NSEvent*) theEvent;
+- (void) flagsChanged: (NSEvent *) theEvent;
+- (BOOL) acceptsMouseMovedEvents;
+- (BOOL) acceptsFirstResponder;
- (BOOL) becomeFirstResponder;
- (BOOL) resignFirstResponder;
- (BOOL) canBecomeKeyWindow;
@@ -155,20 +190,7 @@
- (void) resignKeyWindow;
- (void) windowDidBecomeKey: (NSNotification *) notification;
- (void) windowDidResignKey: (NSNotification *) notification;
-- (void) keyDown: (NSEvent*) theEvent;
-- (void) keyUp: (NSEvent*) theEvent;
-- (void) mouseEntered: (NSEvent*) theEvent;
-- (void) mouseExited: (NSEvent*) theEvent;
-- (void) mouseMoved: (NSEvent*) theEvent;
-- (void) scrollWheel: (NSEvent*) theEvent;
-- (void) mouseDown: (NSEvent*) theEvent;
-- (void) mouseDragged: (NSEvent*) theEvent;
-- (void) mouseUp: (NSEvent*) theEvent;
-- (void) rightMouseDown: (NSEvent*) theEvent;
-- (void) rightMouseDragged: (NSEvent*) theEvent;
-- (void) rightMouseUp: (NSEvent*) theEvent;
-- (void) otherMouseDown: (NSEvent*) theEvent;
-- (void) otherMouseUp: (NSEvent*) theEvent;
+
- (void) windowDidResize: (NSNotification*) notification;
- (void) windowDidMove: (NSNotification*) notification;
- (BOOL) windowClosingImpl: (BOOL) force;
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
index b58b99e38..caf9e54e0 100644
--- a/src/newt/native/NewtMacWindow.m
+++ b/src/newt/native/NewtMacWindow.m
@@ -36,70 +36,171 @@
#import "KeyEvent.h"
#import "MouseEvent.h"
-jint GetDeltaY(NSEvent *event, jint javaMods) {
- CGFloat deltaY = 0.0;
+#include <CoreFoundation/CoreFoundation.h>
+#include <Carbon/Carbon.h> /* For kVK_ constants, and TIS functions. */
+
+#include <math.h>
+
+#define PRINTF(...) NSLog(@ __VA_ARGS__)
+
+static jfloat GetDelta(NSEvent *event, jint javaMods[]) {
CGEventRef cgEvent = [event CGEvent];
+ CGFloat deltaY = 0.0;
+ CGFloat deltaX = 0.0;
+ CGFloat delta = 0.0;
if (CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous)) {
// mouse pad case
- deltaY =
- CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
- // fprintf(stderr, "WHEEL/PAD: %lf\n", (double)deltaY);
+ deltaX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
+ deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
+ // fprintf(stderr, "WHEEL/PAD: %lf/%lf - 0x%X\n", (double)deltaX, (double)deltaY, javaMods[0]);
+ if( fabsf(deltaX) > fabsf(deltaY) ) {
+ javaMods[0] |= EVENT_SHIFT_MASK;
+ delta = deltaX;
+ } else {
+ delta = deltaY;
+ }
} else {
// traditional mouse wheel case
+ deltaX = [event deltaX];
deltaY = [event deltaY];
- // fprintf(stderr, "WHEEL/TRAD: %lf\n", (double)deltaY);
- if (deltaY == 0.0 && (javaMods & EVENT_SHIFT_MASK) != 0) {
+ // fprintf(stderr, "WHEEL/TRACK: %lf/%lf - 0x%X\n", (double)deltaX, (double)deltaY, javaMods[0]);
+ if (deltaY == 0.0 && (javaMods[0] & EVENT_SHIFT_MASK) != 0) {
// shift+vertical wheel scroll produces horizontal scroll
// we convert it to vertical
- deltaY = [event deltaX];
+ delta = deltaX;
+ } else {
+ delta = deltaY;
}
- if (-1.0 < deltaY && deltaY < 1.0) {
- deltaY *= 10.0;
+ if (-1.0 < delta && delta < 1.0) {
+ delta *= 10.0;
} else {
- if (deltaY < 0.0) {
- deltaY = deltaY - 0.5f;
+ if (delta < 0.0) {
+ delta = delta - 0.5f;
} else {
- deltaY = deltaY + 0.5f;
+ delta = delta + 0.5f;
+ }
+ }
+ }
+ // fprintf(stderr, "WHEEL/RES: %lf - 0x%X\n", (double)delta, javaMods[0]);
+ return (jfloat) delta;
+}
+
+#define kVK_Shift 0x38
+#define kVK_Option 0x3A
+#define kVK_Control 0x3B
+#define kVK_Command 0x37
+
+static jint mods2JavaMods(NSUInteger mods)
+{
+ int javaMods = 0;
+ if (mods & NSShiftKeyMask) {
+ javaMods |= EVENT_SHIFT_MASK;
+ }
+ if (mods & NSControlKeyMask) {
+ javaMods |= EVENT_CTRL_MASK;
+ }
+ if (mods & NSCommandKeyMask) {
+ javaMods |= EVENT_META_MASK;
+ }
+ if (mods & NSAlternateKeyMask) {
+ javaMods |= EVENT_ALT_MASK;
+ }
+ return javaMods;
+}
+
+static CFStringRef CKCH_CreateStringForKey(CGKeyCode keyCode, const UCKeyboardLayout *keyboardLayout) {
+ UInt32 keysDown = 0;
+ UniChar chars[4];
+ UniCharCount realLength;
+
+ UCKeyTranslate(keyboardLayout, keyCode,
+ kUCKeyActionDisplay, 0,
+ LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit,
+ &keysDown, sizeof(chars) / sizeof(chars[0]), &realLength, chars);
+
+ return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1);
+}
+
+static CFMutableDictionaryRef CKCH_CreateCodeToCharDict(TISInputSourceRef keyboard) {
+ CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
+ if( NULL == layoutData ) {
+ return NULL;
+ }
+ const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
+
+ CFMutableDictionaryRef codeToCharDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 128, NULL, NULL);
+ if ( NULL != codeToCharDict ) {
+ intptr_t i;
+ for (i = 0; i < 128; ++i) {
+ CFStringRef string = CKCH_CreateStringForKey((CGKeyCode)i, keyboardLayout);
+ if( NULL != string ) {
+ CFIndex stringLen = CFStringGetLength (string);
+ if ( 0 < stringLen ) {
+ UniChar character = CFStringGetCharacterAtIndex(string, 0);
+ DBG_PRINT("CKCH: MAP 0x%X -> %c\n", (int)i, character);
+ CFDictionaryAddValue(codeToCharDict, (const void *)i, (const void *)(intptr_t)character);
+ }
+ CFRelease(string);
}
}
}
- // fprintf(stderr, "WHEEL/res: %d\n", (int)deltaY);
- return (jint) deltaY;
+ return codeToCharDict;
+}
+
+static CFMutableDictionaryRef CKCH_USCodeToNNChar = NULL;
+
+static void CKCH_CreateDictionaries() {
+ TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
+ if( NULL != currentKeyboard ) {
+ CKCH_USCodeToNNChar = CKCH_CreateCodeToCharDict(currentKeyboard);
+ CFRelease(currentKeyboard);
+ }
+}
+
+static UniChar CKCH_CharForKeyCode(jshort keyCode) {
+ UniChar rChar = 0;
+
+ if ( NULL != CKCH_USCodeToNNChar ) {
+ intptr_t code = (intptr_t) keyCode;
+ intptr_t character = 0;
+
+ if ( CFDictionaryGetValueIfPresent(CKCH_USCodeToNNChar, (void *)code, (const void **)&character) ) {
+ rChar = (UniChar) character;
+ DBG_PRINT("CKCH: OK 0x%X -> 0x%X\n", (int)keyCode, (int)rChar);
+ }
+ }
+ return rChar;
}
static jmethodID enqueueMouseEventID = NULL;
-static jmethodID sendMouseEventID = NULL;
static jmethodID enqueueKeyEventID = NULL;
-static jmethodID sendKeyEventID = NULL;
static jmethodID requestFocusID = NULL;
static jmethodID insetsChangedID = NULL;
static jmethodID sizeChangedID = NULL;
+static jmethodID updatePixelScaleID = NULL;
static jmethodID visibleChangedID = NULL;
static jmethodID positionChangedID = NULL;
static jmethodID focusChangedID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
-// Can't use USE_SENDIO_DIRECT, ie w/o enqueueing to EDT,
+// Need to enqueue all events to EDT,
// since we may operate on AWT-AppKit (Main Thread)
// and direct issuing 'requestFocus()' would deadlock:
// AWT-AppKit
// AWT-EventQueue-0
-//
-// #define USE_SENDIO_DIRECT 1
@implementation NewtView
- (id)initWithFrame:(NSRect)frameRect
{
+ id res = [super initWithFrame:frameRect];
javaWindowObject = NULL;
- jvmHandle = NULL;
- jvmVersion = 0;
destroyNotifySent = NO;
- softLocked = NO;
+ softLockCount = 0;
pthread_mutexattr_t softLockSyncAttr;
pthread_mutexattr_init(&softLockSyncAttr);
@@ -107,59 +208,46 @@ static jmethodID windowRepaintID = NULL;
pthread_mutex_init(&softLockSync, &softLockSyncAttr); // recursive
ptrTrackingTag = 0;
-
- /**
- NSCursor crs = [NSCursor arrowCursor];
- NSImage crsImg = [crs image];
- NSPoint crsHot = [crs hotSpot];
- myCursor = [[NSCursor alloc] initWithImage: crsImg hotSpot:crsHot];
- */
myCursor = NULL;
- return [super initWithFrame:frameRect];
+ modsDown[0] = NO; // shift
+ modsDown[1] = NO; // ctrl
+ modsDown[2] = NO; // alt
+ modsDown[3] = NO; // win
+ mouseConfined = NO;
+ mouseVisible = YES;
+ mouseInside = NO;
+ cursorIsHidden = NO;
+
+ DBG_PRINT("NewtView::create: %p (refcnt %d)\n", res, (int)[res retainCount]);
+ return res;
}
+#ifdef DBG_LIFECYCLE
- (void) release
{
-#ifdef VERBOSE_ON
- NSLog(@"NewtView::release\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
+ DBG_PRINT("NewtView::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
[super release];
}
+#endif
- (void) dealloc
{
- if(softLocked) {
+ DBG_PRINT("NewtView::dealloc.0: %p (refcnt %d), ptrTrackingTag %d\n", self, (int)[self retainCount], (int)ptrTrackingTag);
+#ifdef DBG_LIFECYCLE
+ NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+ if( 0 < softLockCount ) {
NSLog(@"NewtView::dealloc: softLock still hold @ dealloc!\n");
}
+ [self removeCursorRects];
+ [self removeMyCursor];
+
pthread_mutex_destroy(&softLockSync);
-#ifdef VERBOSE_ON
- NSLog(@"NewtView::dealloc\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
+ DBG_PRINT("NewtView::dealloc.X: %p\n", self);
[super dealloc];
}
-- (void) setJVMHandle: (JavaVM*) vm
-{
- jvmHandle = vm;
-}
-- (JavaVM*) getJVMHandle
-{
- return jvmHandle;
-}
-
-- (void) setJVMVersion: (int) ver
-{
- jvmVersion = ver;
-}
-
-- (int) getJVMVersion
-{
- return jvmVersion;
-}
-
- (void) setJavaWindowObject: (jobject) javaWindowObj
{
javaWindowObject = javaWindowObj;
@@ -170,32 +258,6 @@ static jmethodID windowRepaintID = NULL;
return javaWindowObject;
}
-- (void) rightMouseDown: (NSEvent*) theEvent
-{
- NSResponder* next = [self nextResponder];
- if (next != nil) {
- [next rightMouseDown: theEvent];
- }
-}
-
-- (void) resetCursorRects
-{
- [super resetCursorRects];
-
- if(0 != ptrTrackingTag) {
- // [self removeCursorRect: ptrRect cursor: myCursor];
- [self removeTrackingRect: ptrTrackingTag];
- }
- ptrRect = [self bounds];
- // [self addCursorRect: ptrRect cursor: myCursor];
- ptrTrackingTag = [self addTrackingRect: ptrRect owner: self userData: nil assumeInside: NO];
-}
-
-- (NSCursor *) cursor
-{
- return myCursor;
-}
-
- (void) setDestroyNotifySent: (BOOL) v
{
destroyNotifySent = v;
@@ -209,18 +271,27 @@ static jmethodID windowRepaintID = NULL;
- (BOOL) softLock
{
// DBG_PRINT("*************** softLock.0: %p\n", (void*)pthread_self());
- // NSLog(@"NewtView::softLock: %@",[NSThread callStackSymbols]);
- pthread_mutex_lock(&softLockSync);
- softLocked = YES;
+ int err;
+ if( 0 != ( err = pthread_mutex_lock(&softLockSync) ) ) {
+ NSLog(@"NewtView::softLock failed: errCode %d - %@", err, [NSThread callStackSymbols]);
+ return NO;
+ }
+ softLockCount++;
// DBG_PRINT("*************** softLock.X: %p\n", (void*)pthread_self());
- return softLocked;
+ return 0 < softLockCount;
}
-- (void) softUnlock
+- (BOOL) softUnlock
{
// DBG_PRINT("*************** softUnlock: %p\n", (void*)pthread_self());
- softLocked = NO;
- pthread_mutex_unlock(&softLockSync);
+ softLockCount--;
+ int err;
+ if( 0 != ( err = pthread_mutex_unlock(&softLockSync) ) ) {
+ softLockCount++;
+ NSLog(@"NewtView::softUnlock failed: Not locked by current thread - errCode %d - %@", err, [NSThread callStackSymbols]);
+ return NO;
+ }
+ return YES;
}
- (BOOL) needsDisplay
@@ -256,7 +327,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("drawRect: null JNIEnv\n");
return;
@@ -265,12 +336,11 @@ static jmethodID windowRepaintID = NULL;
NSRect viewFrame = [self frame];
(*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE, // defer ..
- dirtyRect.origin.x, viewFrame.size.height - dirtyRect.origin.y,
- dirtyRect.size.width, dirtyRect.size.height);
+ (int)dirtyRect.origin.x, (int)viewFrame.size.height - (int)dirtyRect.origin.y,
+ (int)dirtyRect.size.width, (int)dirtyRect.size.height);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (void) viewDidHide
@@ -280,7 +350,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("viewDidHide: null JNIEnv\n");
return;
@@ -288,9 +358,8 @@ static jmethodID windowRepaintID = NULL;
(*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_FALSE);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
[super viewDidHide];
}
@@ -302,7 +371,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("viewDidUnhide: null JNIEnv\n");
return;
@@ -310,9 +379,8 @@ static jmethodID windowRepaintID = NULL;
(*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_TRUE);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
[super viewDidUnhide];
}
@@ -322,232 +390,152 @@ static jmethodID windowRepaintID = NULL;
return YES;
}
-@end
-
-@implementation NewtMacWindow
-
-+ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz
+- (BOOL) becomeFirstResponder
{
- enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
- sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
- visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
- insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V");
- positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V");
- focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
- windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
- windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
- requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
- if (enqueueMouseEventID && sendMouseEventID && enqueueKeyEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID &&
- positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
- {
- return YES;
- }
- return NO;
+ DBG_PRINT( "*************** View.becomeFirstResponder\n");
+ return [super becomeFirstResponder];
}
-- (id) initWithContentRect: (NSRect) contentRect
- styleMask: (NSUInteger) windowStyle
- backing: (NSBackingStoreType) bufferingType
- defer: (BOOL) deferCreation
- screen:(NSScreen *)screen
- isFullscreenWindow:(BOOL)isfs
+- (BOOL) resignFirstResponder
{
- id res = [super initWithContentRect: contentRect
- styleMask: windowStyle
- backing: bufferingType
- defer: deferCreation
- screen: screen];
- isFullscreenWindow = isfs;
- // Why is this necessary? Without it we don't get any of the
- // delegate methods like resizing and window movement.
- [self setDelegate: self];
- cachedInsets[0] = 0; // l
- cachedInsets[1] = 0; // r
- cachedInsets[2] = 0; // t
- cachedInsets[3] = 0; // b
- mouseConfined = NO;
- mouseVisible = YES;
- mouseInside = NO;
- cursorIsHidden = NO;
- realized = YES;
- return res;
+ DBG_PRINT( "*************** View.resignFirstResponder\n");
+ return [super resignFirstResponder];
}
-- (void) release
+- (void) removeCursorRects
{
-#ifdef VERBOSE_ON
- NSLog(@"NewtWindow::release\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
- [super release];
+ if(0 != ptrTrackingTag) {
+ if(NULL != myCursor) {
+ [self removeCursorRect: ptrRect cursor: myCursor];
+ }
+ [self removeTrackingRect: ptrTrackingTag];
+ ptrTrackingTag = 0;
+ }
}
-- (void) dealloc
+- (void) addCursorRects
{
-#ifdef VERBOSE_ON
- NSLog(@"NewtWindow::dealloc\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
- [super dealloc];
+ ptrRect = [self bounds];
+ if(NULL != myCursor) {
+ [self addCursorRect: ptrRect cursor: myCursor];
+ }
+ ptrTrackingTag = [self addTrackingRect: ptrRect owner: self userData: nil assumeInside: NO];
}
-- (void) setUnrealized
+- (void) removeMyCursor
{
- realized = NO;
+ if(NULL != myCursor) {
+ [myCursor release];
+ myCursor = NULL;
+ }
}
-- (BOOL) isRealized
+- (void) resetCursorRects
{
- return realized;
+ [super resetCursorRects];
+
+ [self removeCursorRects];
+ [self addCursorRects];
}
-- (void) updateInsets: (JNIEnv*) env
+- (void) setPointerIcon: (NSCursor*)c
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
+ DBG_PRINT( "setPointerIcon: %p -> %p, top %p, mouseInside %d\n", myCursor, c, [NSCursor currentCursor], (int)mouseInside);
+ if( c != myCursor ) {
+ [self removeCursorRects];
+ [self removeMyCursor];
+ myCursor = c;
+ if( NULL != myCursor ) {
+ [myCursor retain];
+ }
}
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
- if (env==NULL || javaWindowObject == NULL) {
- return;
+ NSWindow* nsWin = [self window];
+ if( NULL != nsWin ) {
+ [nsWin invalidateCursorRectsForView: self];
}
-
- NSRect frameRect = [self frame];
- NSRect contentRect = [self contentRectForFrameRect: frameRect];
-
- // note: this is a simplistic implementation which doesn't take
- // into account DPI and scaling factor
- CGFloat l = contentRect.origin.x - frameRect.origin.x;
- cachedInsets[0] = (int)l; // l
- cachedInsets[1] = (int)(frameRect.size.width - (contentRect.size.width + l)); // r
- cachedInsets[2] = (jint)(frameRect.size.height - contentRect.size.height); // t
- cachedInsets[3] = (jint)(contentRect.origin.y - frameRect.origin.y); // b
-
- DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
-
- (*env)->CallVoidMethod(env, javaWindowObject, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
-}
-
-- (void) attachToParent: (NSWindow*) parent
-{
- DBG_PRINT( "attachToParent.1\n");
- [parent addChildWindow: self ordered: NSWindowAbove];
- DBG_PRINT( "attachToParent.2\n");
- [self setParentWindow: parent];
- DBG_PRINT( "attachToParent.X\n");
}
-- (void) detachFromParent: (NSWindow*) parent
+- (void) mouseEntered: (NSEvent*) theEvent
{
- DBG_PRINT( "detachFromParent.1\n");
- [self setParentWindow: nil];
- if(NULL != parent) {
- DBG_PRINT( "detachFromParent.2\n");
- [parent removeChildWindow: self];
+ DBG_PRINT( "mouseEntered: confined %d, visible %d, PointerIcon %p, top %p\n", mouseConfined, mouseVisible, myCursor, [NSCursor currentCursor]);
+ mouseInside = YES;
+ [self cursorHide: !mouseVisible enter: 1];
+ if(NO == mouseConfined) {
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED];
+ }
+ NSWindow* nsWin = [self window];
+ if( NULL != nsWin ) {
+ [nsWin makeFirstResponder: self];
}
- DBG_PRINT( "detachFromParent.X\n");
-}
-
-/**
- * p abs screen position w/ top-left origin
- * returns: abs screen position w/ bottom-left origin
- */
-- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p
-{
- NSView* mView = [self contentView];
- NSRect mViewFrame = [mView frame];
- int totalHeight = mViewFrame.size.height + cachedInsets[2] + cachedInsets[3]; // height + insets[top+bottom]
-
- NSScreen* screen = [self screen];
- NSRect screenFrame = [screen frame];
-
- return NSMakePoint(screenFrame.origin.x + p.x + cachedInsets[0],
- screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight);
}
-/**
- * p rel client window position w/ top-left origin
- * returns: abs screen position w/ bottom-left origin
- */
-- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p
+- (void) mouseExited: (NSEvent*) theEvent
{
- NSRect winFrame = [self frame];
-
- NSView* mView = [self contentView];
- NSRect mViewFrame = [mView frame];
-
- return NSMakePoint(winFrame.origin.x + p.x,
- winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view
+ DBG_PRINT( "mouseExited: confined %d, visible %d, PointerIcon %p, top %p\n", mouseConfined, mouseVisible, myCursor, [NSCursor currentCursor]);
+ if(NO == mouseConfined) {
+ mouseInside = NO;
+ [self cursorHide: NO enter: -1];
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED];
+ [self resignFirstResponder];
+ } else {
+ [self setMousePosition: lastInsideMousePosition];
+ }
}
/**
- * y-flips input / output
- * p rel client window position w/ top-left origin
- * returns: location in 0/0 top-left space.
+ * p abs screen position w/ bottom-left origin
*/
-- (NSPoint) getLocationOnScreen: (NSPoint) p
+- (void) setMousePosition:(NSPoint)p
{
- NSScreen* screen = [self screen];
- NSRect screenRect = [screen frame];
+ NSWindow* nsWin = [self window];
+ if( NULL != nsWin ) {
+ NSScreen* screen = [nsWin screen];
- NSView* view = [self contentView];
- NSRect viewFrame = [view frame];
+ CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
+ CGRect frameTL = CGDisplayBounds (display); // origin top-left
+ NSRect frameBL = [screen frame]; // origin bottom-left
+ CGPoint pt = { p.x, frameTL.origin.y + frameTL.size.height - ( p.y - frameBL.origin.y ) }; // y-flip from BL-screen -> TL-screen
- NSRect r;
- r.origin.x = p.x;
- r.origin.y = viewFrame.size.height - p.y; // y-flip
- r.size.width = 0;
- r.size.height = 0;
- // NSRect rS = [win convertRectToScreen: r]; // 10.7
- NSPoint oS = [self convertBaseToScreen: r.origin];
- oS.y = screenRect.origin.y + screenRect.size.height - oS.y;
- return oS;
-}
+ DBG_PRINT( "setMousePosition: point-in[%d/%d], screen tl[%d/%d %dx%d] bl[%d/%d %dx%d] -> %d/%d\n",
+ (int)p.x, (int)p.y,
+ (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height,
+ (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height,
+ (int)pt.x, (int)pt.y);
-- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p
-{
- NSView* view = [self contentView];
- NSRect viewFrame = [view frame];
-
- NSRect r;
- r.origin.x = p.x;
- r.origin.y = p.y;
- r.size.width = 0;
- r.size.height = 0;
- // NSRect rS = [win convertRectFromScreen: r]; // 10.7
- NSPoint oS = [self convertScreenToBase: r.origin];
- oS.y = viewFrame.size.height - oS.y; // y-flip
- return oS;
+ CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft);
+ CGEventPost (kCGHIDEventTap, ev);
+ }
}
-- (BOOL) isMouseInside
+- (BOOL) updateMouseInside
{
- NSView* view = [self contentView];
- NSRect viewFrame = [view frame];
+ NSRect viewFrame = [self frame];
NSPoint l1 = [NSEvent mouseLocation];
NSPoint l0 = [self screenPos2NewtClientWinPos: l1];
- return viewFrame.origin.x <= l0.x && l0.x < (viewFrame.origin.x+viewFrame.size.width) &&
- viewFrame.origin.y <= l0.y && l0.y < (viewFrame.origin.y+viewFrame.size.height) ;
+ mouseInside = viewFrame.origin.x <= l0.x && l0.x < (viewFrame.origin.x+viewFrame.size.width) &&
+ viewFrame.origin.y <= l0.y && l0.y < (viewFrame.origin.y+viewFrame.size.height) ;
+ return mouseInside;
}
- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus
{
mouseVisible = v;
- mouseInside = [self isMouseInside];
+ [self updateMouseInside];
DBG_PRINT( "setMouseVisible: confined %d, visible %d (current: %d), mouseInside %d, hasFocus %d\n",
mouseConfined, mouseVisible, !cursorIsHidden, mouseInside, focus);
if(YES == focus && YES == mouseInside) {
- [self cursorHide: !mouseVisible];
+ [self cursorHide: !mouseVisible enter: 0];
}
}
+- (BOOL) isMouseVisible
+{
+ return mouseVisible;
+}
-- (void) cursorHide:(BOOL)v
+- (void) cursorHide:(BOOL)v enter:(int)enterState
{
- DBG_PRINT( "cursorHide: %d -> %d\n", cursorIsHidden, v);
+ DBG_PRINT( "cursorHide: %d -> %d, enter %d; PointerIcon: %p, top %p\n",
+ cursorIsHidden, v, enterState, myCursor, [NSCursor currentCursor]);
if(v) {
if(!cursorIsHidden) {
[NSCursor hide];
@@ -567,108 +555,105 @@ static jmethodID windowRepaintID = NULL;
DBG_PRINT( "setMouseConfined: confined %d, visible %d\n", mouseConfined, mouseVisible);
}
-- (void) setMousePosition:(NSPoint)p
+- (void) mouseMoved: (NSEvent*) theEvent
{
- NSScreen* screen = [self screen];
- NSRect screenRect = [screen frame];
+ if( mouseInside ) {
+ NSCursor * currentCursor = [NSCursor currentCursor];
+ BOOL setCursor = NULL != myCursor && NO == cursorIsHidden && currentCursor != myCursor;
+ DBG_PRINT( "mouseMoved.set: %d; mouseInside %d, CursorHidden %d, PointerIcon: %p, top %p\n",
+ setCursor, mouseInside, cursorIsHidden, myCursor, currentCursor);
+ if( setCursor ) {
+ // FIXME: Workaround missing NSCursor update for 'fast moving' pointer
+ [myCursor set];
+ }
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ }
+}
- CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin)
- CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft);
- CGEventPost (kCGHIDEventTap, ev);
+- (void) scrollWheel: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_WHEEL_MOVED];
}
-static jint mods2JavaMods(NSUInteger mods)
+- (void) mouseDown: (NSEvent*) theEvent
{
- int javaMods = 0;
- if (mods & NSShiftKeyMask) {
- javaMods |= EVENT_SHIFT_MASK;
- }
- if (mods & NSControlKeyMask) {
- javaMods |= EVENT_CTRL_MASK;
- }
- if (mods & NSCommandKeyMask) {
- javaMods |= EVENT_META_MASK;
- }
- if (mods & NSAlternateKeyMask) {
- javaMods |= EVENT_ALT_MASK;
- }
- return javaMods;
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
}
-- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType
+- (void) mouseDragged: (NSEvent*) theEvent
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
- }
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
- if (javaWindowObject == NULL) {
- DBG_PRINT("sendKeyEvent: null javaWindowObject\n");
- return;
- }
- int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
- if(NULL==env) {
- DBG_PRINT("sendKeyEvent: null JNIEnv\n");
- return;
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
+
+- (void) mouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+}
+
+- (void) rightMouseDown: (NSEvent*) theEvent
+{
+ NSResponder* next = [self nextResponder];
+ if (next != nil) {
+ [next rightMouseDown: theEvent];
}
+ // FIXME: ^^ OR [super rightMouseDown: theEvent] ?
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+}
- int i;
- jint keyCode = (jint) [event keyCode];
- NSString* chars = [event charactersIgnoringModifiers];
- int len = [chars length];
- jint javaMods = mods2JavaMods([event modifierFlags]);
+- (void) rightMouseDragged: (NSEvent*) theEvent
+{
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
- for (i = 0; i < len; i++) {
- // Note: the key code in the NSEvent does not map to anything we can use
- jchar keyChar = (jchar) [chars characterAtIndex: i];
+- (void) rightMouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+}
- DBG_PRINT("sendKeyEvent: %d/%d char 0x%X, code 0x%X\n", i, len, (int)keyChar, (int)keyCode);
+- (void) otherMouseDown: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+}
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID,
- evType, javaMods, keyCode, keyChar);
- #else
- (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
- evType, javaMods, keyCode, keyChar);
- #endif
- }
+- (void) otherMouseDragged: (NSEvent*) theEvent
+{
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+- (void) otherMouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
}
-- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType
+- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
- }
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
if (javaWindowObject == NULL) {
DBG_PRINT("sendMouseEvent: null javaWindowObject\n");
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("sendMouseEvent: null JNIEnv\n");
return;
}
- jint javaMods = mods2JavaMods([event modifierFlags]);
+ jint javaMods[] = { 0 } ;
+ javaMods[0] = mods2JavaMods([event modifierFlags]);
// convert to 1-based button number (or use zero if no button is involved)
// TODO: detect mouse button when mouse wheel scrolled
- jint javaButtonNum = 0;
- jint scrollDeltaY = 0;
+ jshort javaButtonNum = 0;
+ jfloat scrollDeltaY = 0.0f;
switch ([event type]) {
case NSScrollWheel: {
- scrollDeltaY = GetDeltaY(event, javaMods);
+ scrollDeltaY = GetDelta(event, javaMods);
javaButtonNum = 1;
break;
}
@@ -699,246 +684,537 @@ static jint mods2JavaMods(NSUInteger mods)
NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]];
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, javaWindowObject, sendMouseEventID,
- evType, javaMods,
- (jint) location.x, (jint) location.y,
- javaButtonNum, scrollDeltaY);
- #else
(*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE,
- evType, javaMods,
+ evType, javaMods[0],
(jint) location.x, (jint) location.y,
javaButtonNum, scrollDeltaY);
- #endif
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p
+{
+ NSRect viewFrame = [self frame];
+
+ NSRect r;
+ r.origin.x = p.x;
+ r.origin.y = p.y;
+ r.size.width = 0;
+ r.size.height = 0;
+ // NSRect rS = [[self window] convertRectFromScreen: r]; // 10.7
+ NSPoint oS = [[self window] convertScreenToBase: r.origin];
+ oS.y = viewFrame.size.height - oS.y; // y-flip
+ return oS;
+}
+
+- (void) handleFlagsChanged:(NSUInteger) mods
+{
+ [self handleFlagsChanged: NSShiftKeyMask keyIndex: 0 keyCode: kVK_Shift modifiers: mods];
+ [self handleFlagsChanged: NSControlKeyMask keyIndex: 1 keyCode: kVK_Control modifiers: mods];
+ [self handleFlagsChanged: NSAlternateKeyMask keyIndex: 2 keyCode: kVK_Option modifiers: mods];
+ [self handleFlagsChanged: NSCommandKeyMask keyIndex: 3 keyCode: kVK_Command modifiers: mods];
+}
+
+- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods
+{
+ if ( NO == modsDown[keyIdx] && 0 != ( mods & keyMask ) ) {
+ modsDown[keyIdx] = YES;
+ [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_PRESSED];
+ } else if ( YES == modsDown[keyIdx] && 0 == ( mods & keyMask ) ) {
+ modsDown[keyIdx] = NO;
+ [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_RELEASED];
}
}
-- (void) focusChanged: (BOOL) gained
+- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType
{
- DBG_PRINT( "focusChanged: gained %d\n", gained);
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ jshort keyCode = (jshort) [event keyCode];
+ NSString* chars = [event charactersIgnoringModifiers];
+ NSUInteger mods = [event modifierFlags];
+ [self sendKeyEvent: keyCode characters: chars modifiers: mods eventType: evType];
+}
+
+- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType
+{
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("sendKeyEvent: null javaWindowObject\n");
return;
}
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("sendKeyEvent: null JNIEnv\n");
+ return;
+ }
+
+ int i;
+ int len = NULL != chars ? [chars length] : 0;
+ jint javaMods = mods2JavaMods(mods);
+
+ if(len > 0) {
+ // printable chars
+ for (i = 0; i < len; i++) {
+ // Note: the key code in the NSEvent does not map to anything we can use
+ UniChar keyChar = (UniChar) [chars characterAtIndex: i];
+ UniChar keySymChar = CKCH_CharForKeyCode(keyCode);
+
+ DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X, mods 0x%X/0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar,
+ (int)mods, (int)javaMods, (int)keySymChar);
+
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
+ evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar);
+ }
+ } else {
+ // non-printable chars
+ jchar keyChar = (jchar) 0;
+
+ DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode);
+
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
+ evType, javaMods, keyCode, keyChar, keyChar);
+ }
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (void)viewDidChangeBackingProperties
+{
+ [super viewDidChangeBackingProperties];
+
+ // HiDPI scaling
+ BOOL useHiDPI = [self wantsBestResolutionOpenGLSurface];
+ CGFloat pixelScaleNative = [[self window] backingScaleFactor];
+ CGFloat pixelScaleUse = useHiDPI ? pixelScaleNative : 1.0;
+ DBG_PRINT("viewDidChangeBackingProperties: PixelScale: HiDPI %d, native %f -> use %f\n", useHiDPI, (float)pixelScaleNative, (float)pixelScaleUse);
+ [[self layer] setContentsScale: pixelScaleUse];
+
if (javaWindowObject == NULL) {
- DBG_PRINT("focusChanged: null javaWindowObject\n");
+ DBG_PRINT("viewDidChangeBackingProperties: null javaWindowObject\n");
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
- DBG_PRINT("focusChanged: null JNIEnv\n");
+ DBG_PRINT("viewDidChangeBackingProperties: null JNIEnv\n");
return;
}
- (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
+ (*env)->CallVoidMethod(env, javaWindowObject, updatePixelScaleID, JNI_TRUE, (jfloat)pixelScaleUse, (jfloat)pixelScaleNative); // defer
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+
+@end
+
+@implementation NewtMacWindow
+
++ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz
+{
+ enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V");
+ enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V");
+ sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
+ updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFF)V");
+ visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
+ insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V");
+ positionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V");
+ focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
+ windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
+ windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
+ requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
+ if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && insetsChangedID &&
+ positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
+ {
+ CKCH_CreateDictionaries();
+ return YES;
+ }
+ return NO;
+}
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+- (id) initWithContentRect: (NSRect) contentRect
+ styleMask: (NSUInteger) windowStyle
+ backing: (NSBackingStoreType) bufferingType
+ defer: (BOOL) deferCreation
+ isFullscreenWindow:(BOOL)isfs
+{
+ id res = [super initWithContentRect: contentRect
+ styleMask: windowStyle
+ backing: bufferingType
+ defer: deferCreation];
+ // OSX 10.6
+ if ( [NSApp respondsToSelector:@selector(currentSystemPresentationOptions)] &&
+ [NSApp respondsToSelector:@selector(setPresentationOptions:)] ) {
+ hasPresentationSwitch = YES;
+ defaultPresentationOptions = [NSApp currentSystemPresentationOptions];
+ fullscreenPresentationOptions =
+ // NSApplicationPresentationDefault|
+ // NSApplicationPresentationAutoHideDock|
+ NSApplicationPresentationHideDock|
+ // NSApplicationPresentationAutoHideMenuBar|
+ NSApplicationPresentationHideMenuBar|
+ NSApplicationPresentationDisableAppleMenu|
+ // NSApplicationPresentationDisableProcessSwitching|
+ // NSApplicationPresentationDisableSessionTermination|
+ NSApplicationPresentationDisableHideApplication|
+ // NSApplicationPresentationDisableMenuBarTransparency|
+ // NSApplicationPresentationFullScreen| // OSX 10.7
+ 0 ;
+ } else {
+ hasPresentationSwitch = NO;
+ defaultPresentationOptions = 0;
+ fullscreenPresentationOptions = 0;
}
+
+ isFullscreenWindow = isfs;
+ // Why is this necessary? Without it we don't get any of the
+ // delegate methods like resizing and window movement.
+ [self setDelegate: self];
+
+ cachedInsets[0] = 0; // l
+ cachedInsets[1] = 0; // r
+ cachedInsets[2] = 0; // t
+ cachedInsets[3] = 0; // b
+
+ realized = YES;
+ DBG_PRINT("NewtWindow::create: %p, realized %d, hasPresentationSwitch %d[defaultOptions 0x%X, fullscreenOptions 0x%X], (refcnt %d)\n",
+ res, realized, (int)hasPresentationSwitch, (int)defaultPresentationOptions, (int)fullscreenPresentationOptions, (int)[res retainCount]);
+ return res;
}
-- (BOOL) becomeFirstResponder
+#ifdef DBG_LIFECYCLE
+- (void) release
{
- DBG_PRINT( "*************** becomeFirstResponder\n");
- return [super becomeFirstResponder];
+ DBG_PRINT("NewtWindow::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"%@",[NSThread callStackSymbols]);
+ [super release];
}
+#endif
-- (BOOL) resignFirstResponder
+- (void) dealloc
{
- DBG_PRINT( "*************** resignFirstResponder\n");
- return [super resignFirstResponder];
+ DBG_PRINT("NewtWindow::dealloc.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+#ifdef DBG_LIFECYCLE
+ NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+
+ NewtView* mView = (NewtView *)[self contentView];
+ if( NULL != mView ) {
+ [mView release];
+ }
+ [super dealloc];
+ DBG_PRINT("NewtWindow::dealloc.X: %p\n", self);
}
-- (BOOL) canBecomeKeyWindow
+- (void) setRealized: (BOOL)v
{
- // Even if the window is borderless, we still want it to be able
- // to become the key window to receive keyboard events
- return YES;
+ realized = v;
}
-- (void) becomeKeyWindow
+- (BOOL) isRealized
{
- DBG_PRINT( "*************** becomeKeyWindow\n");
- [super becomeKeyWindow];
+ return realized;
}
-- (void) resignKeyWindow
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin
{
- DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow);
- if(!isFullscreenWindow) {
- [super resignKeyWindow];
+ NSRect frameRect = [self frame];
+ NSRect contentRect = [self contentRectForFrameRect: frameRect];
+
+ // note: this is a simplistic implementation which doesn't take
+ // into account DPI and scaling factor
+ CGFloat l = contentRect.origin.x - frameRect.origin.x;
+ cachedInsets[0] = (int)l; // l
+ cachedInsets[1] = (int)(frameRect.size.width - (contentRect.size.width + l)); // r
+ cachedInsets[2] = (jint)(frameRect.size.height - contentRect.size.height); // t
+ cachedInsets[3] = (jint)(contentRect.origin.y - frameRect.origin.y); // b
+
+ DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
+
+ if( NULL != env && NULL != javaWin ) {
+ (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
}
}
-- (void) windowDidBecomeKey: (NSNotification *) notification
+- (void) attachToParent: (NSWindow*) parent
{
- DBG_PRINT( "*************** windowDidBecomeKey\n");
- mouseInside = [self isMouseInside];
- if(YES == mouseInside) {
- [self cursorHide: !mouseVisible];
+ DBG_PRINT( "attachToParent.1\n");
+ [parent addChildWindow: self ordered: NSWindowAbove];
+ DBG_PRINT( "attachToParent.2\n");
+ [self setParentWindow: parent];
+ DBG_PRINT( "attachToParent.X\n");
+}
+
+- (void) detachFromParent: (NSWindow*) parent
+{
+ DBG_PRINT( "detachFromParent.1\n");
+ [self setParentWindow: nil];
+ if(NULL != parent) {
+ DBG_PRINT( "detachFromParent.2\n");
+ [parent removeChildWindow: self];
}
- [self focusChanged: YES];
+ DBG_PRINT( "detachFromParent.X\n");
}
-- (void) windowDidResignKey: (NSNotification *) notification
+/**
+ * p abs screen position of client-area pos w/ top-left origin, using contentView's client NSSize
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p
{
- DBG_PRINT( "*************** windowDidResignKey\n");
- // Implicit mouse exit by OS X
- [self focusChanged: NO];
+ NSView* mView = [self contentView];
+ NSRect mViewFrame = [mView frame];
+ return [self newtAbsClientTLWinPos2AbsBLScreenPos: p size: mViewFrame.size];
}
-- (void) keyDown: (NSEvent*) theEvent
+/**
+ * p abs screen position of client-area pos w/ top-left origin, using given client NSSize
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz
{
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED];
+ int totalHeight = nsz.height + cachedInsets[3]; // height + insets.bottom
+
+ DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: point-in[%d/%d], size-in[%dx%d], insets bottom %d -> totalHeight %d\n",
+ (int)p.x, (int)p.y, (int)nsz.width, (int)nsz.height, cachedInsets[3], totalHeight);
+
+ NSScreen* screen = [self screen];
+
+ CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
+ CGRect frameTL = CGDisplayBounds (display); // origin top-left
+ NSRect frameBL = [screen frame]; // origin bottom-left
+ NSPoint r = NSMakePoint(p.x, frameBL.origin.y + frameBL.size.height - ( p.y - frameTL.origin.y ) - totalHeight); // y-flip from TL-screen -> BL-screen
+
+ DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: screen tl[%d/%d %dx%d] bl[%d/%d %dx%d -> %d/%d\n",
+ (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height,
+ (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height,
+ (int)r.x, (int)r.y);
+
+ return r;
}
-- (void) keyUp: (NSEvent*) theEvent
+/**
+ * p rel client window position w/ top-left origin
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p
{
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED];
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_TYPED];
+ NSRect winFrame = [self frame];
+
+ NSView* mView = [self contentView];
+ NSRect mViewFrame = [mView frame];
+ NSPoint r = NSMakePoint(winFrame.origin.x + p.x,
+ winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view
+
+ DBG_PRINT( "newtRelClientTLWinPos2AbsBLScreenPos: point-in[%d/%d], winFrame[%d/%d %dx%d], viewFrame[%d/%d %dx%d] -> %d/%d\n",
+ (int)p.x, (int)p.y,
+ (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height,
+ (int)mViewFrame.origin.x, (int)mViewFrame.origin.y, (int)mViewFrame.size.width, (int)mViewFrame.size.height,
+ (int)r.x, (int)r.y);
+
+ return r;
}
-- (void) mouseEntered: (NSEvent*) theEvent
+- (NSSize) newtClientSize2TLSize: (NSSize) nsz
{
- DBG_PRINT( "mouseEntered: confined %d, visible %d\n", mouseConfined, mouseVisible);
- mouseInside = YES;
- [self cursorHide: !mouseVisible];
- if(NO == mouseConfined) {
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED];
+ NSSize topSZ = { nsz.width, nsz.height + cachedInsets[2] + cachedInsets[3] }; // height + insets.top + insets.bottom
+ return topSZ;
+}
+
+/**
+ * y-flips input / output
+ * p rel client window position w/ top-left origin
+ * returns: location in 0/0 top-left space.
+ */
+- (NSPoint) getLocationOnScreen: (NSPoint) p
+{
+ NSView* view = [self contentView];
+ NSRect viewFrame = [view frame];
+ NSRect r;
+ r.origin.x = p.x;
+ r.origin.y = viewFrame.size.height - p.y; // y-flip
+ r.size.width = 0;
+ r.size.height = 0;
+ // NSRect rS = [self convertRectToScreen: r]; // 10.7
+ NSPoint oS = [self convertBaseToScreen: r.origin]; // BL-screen
+
+ NSScreen* screen = [self screen];
+ CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
+ CGRect frameTL = CGDisplayBounds (display); // origin top-left
+ NSRect frameBL = [screen frame]; // origin bottom-left
+ oS.y = frameTL.origin.y + frameTL.size.height - ( oS.y - frameBL.origin.y ); // y-flip from BL-screen -> TL-screen
+
+#ifdef VERBOSE_ON
+ NSRect winFrame = [self frame];
+ DBG_PRINT( "getLocationOnScreen: point-in[%d/%d], winFrame[%d/%d %dx%d], viewFrame[%d/%d %dx%d], screen tl[%d/%d %dx%d] bl[%d/%d %dx%d] -> %d/%d\n",
+ (int)p.x, (int)p.y,
+ (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height,
+ (int)viewFrame.origin.x, (int)viewFrame.origin.y, (int)viewFrame.size.width, (int)viewFrame.size.height,
+ (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height,
+ (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height,
+ (int)oS.x, (int)oS.y);
+#endif
+
+ return oS;
+}
+
+- (void) focusChanged: (BOOL) gained
+{
+ DBG_PRINT( "focusChanged: gained %d\n", gained);
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtView class]] ) {
+ return;
}
+ jobject javaWindowObject = [newtView getJavaWindowObject];
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("focusChanged: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("focusChanged: null JNIEnv\n");
+ return;
+ }
+
+ (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
-- (void) mouseExited: (NSEvent*) theEvent
+- (void) keyDown: (NSEvent*) theEvent
{
- DBG_PRINT( "mouseExited: confined %d, visible %d\n", mouseConfined, mouseVisible);
- if(NO == mouseConfined) {
- mouseInside = NO;
- [self cursorHide: NO];
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED];
- } else {
- [self setMousePosition: lastInsideMousePosition];
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ [newtView sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_PRESSED];
}
}
-- (void) mouseMoved: (NSEvent*) theEvent
+- (void) keyUp: (NSEvent*) theEvent
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ [newtView sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_RELEASED];
+ }
}
-- (void) scrollWheel: (NSEvent*) theEvent
+- (void) flagsChanged:(NSEvent *) theEvent
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_WHEEL_MOVED];
+ NSUInteger mods = [theEvent modifierFlags];
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ [newtView handleFlagsChanged: mods];
+ }
}
-- (void) mouseDown: (NSEvent*) theEvent
+- (BOOL) acceptsMouseMovedEvents
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+ return YES;
}
-- (void) mouseDragged: (NSEvent*) theEvent
+- (BOOL) acceptsFirstResponder
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ return YES;
}
-- (void) mouseUp: (NSEvent*) theEvent
+- (BOOL) becomeFirstResponder
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+ DBG_PRINT( "*************** Win.becomeFirstResponder\n");
+ return [super becomeFirstResponder];
}
-- (void) rightMouseDown: (NSEvent*) theEvent
+- (BOOL) resignFirstResponder
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+ DBG_PRINT( "*************** Win.resignFirstResponder\n");
+ return [super resignFirstResponder];
}
-- (void) rightMouseDragged: (NSEvent*) theEvent
+- (BOOL) canBecomeKeyWindow
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ // Even if the window is borderless, we still want it to be able
+ // to become the key window to receive keyboard events
+ return YES;
}
-- (void) rightMouseUp: (NSEvent*) theEvent
+- (void) becomeKeyWindow
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+ DBG_PRINT( "*************** becomeKeyWindow\n");
+ [super becomeKeyWindow];
}
-- (void) otherMouseDown: (NSEvent*) theEvent
+- (void) resignKeyWindow
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+ DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow);
+ if(!isFullscreenWindow) {
+ [super resignKeyWindow];
+ }
}
-- (void) otherMouseDragged: (NSEvent*) theEvent
+- (void) windowDidBecomeKey: (NSNotification *) notification
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ DBG_PRINT( "*************** windowDidBecomeKey\n");
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ BOOL mouseInside = [newtView updateMouseInside];
+ if(YES == mouseInside) {
+ [newtView cursorHide: ![newtView isMouseVisible] enter: 1];
+ }
+ }
+ [self focusChanged: YES];
}
-- (void) otherMouseUp: (NSEvent*) theEvent
+- (void) windowDidResignKey: (NSNotification *) notification
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+ DBG_PRINT( "*************** windowDidResignKey\n");
+ // Implicit mouse exit by OS X
+ [self focusChanged: NO];
}
- (void)windowDidResize: (NSNotification*) notification
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
- }
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
- if (javaWindowObject == NULL) {
- DBG_PRINT("windowDidResize: null javaWindowObject\n");
- return;
- }
+ jobject javaWindowObject = NULL;
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
- if(NULL==env) {
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+
+ if( NULL == env ) {
DBG_PRINT("windowDidResize: null JNIEnv\n");
return;
}
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ javaWindowObject = [newtView getJavaWindowObject];
+ }
+ if( NULL != javaWindowObject ) {
+ // update insets on every window resize for lack of better hook place
+ [self updateInsets: env jwin:javaWindowObject];
- // update insets on every window resize for lack of better hook place
- [self updateInsets: env];
-
- NSRect frameRect = [self frame];
- NSRect contentRect = [self contentRectForFrameRect: frameRect];
-
- (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE,
- (jint) contentRect.size.width,
- (jint) contentRect.size.height, JNI_FALSE);
+ NSRect frameRect = [self frame];
+ NSRect contentRect = [self contentRectForFrameRect: frameRect];
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_TRUE, // defer
+ (jint) contentRect.size.width,
+ (jint) contentRect.size.height, JNI_FALSE);
}
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (void)windowDidMove: (NSNotification*) notification
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtView class]] ) {
return;
}
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
+ jobject javaWindowObject = [newtView getJavaWindowObject];
if (javaWindowObject == NULL) {
DBG_PRINT("windowDidMove: null javaWindowObject\n");
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("windowDidMove: null JNIEnv\n");
return;
@@ -948,9 +1224,8 @@ static jint mods2JavaMods(NSUInteger mods)
p0 = [self getLocationOnScreen: p0];
(*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_FALSE, (jint) p0.x, (jint) p0.y);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (BOOL)windowShouldClose: (id) sender
@@ -966,41 +1241,38 @@ static jint mods2JavaMods(NSUInteger mods)
- (BOOL) windowClosingImpl: (BOOL) force
{
jboolean closed = JNI_FALSE;
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- [self cursorHide: NO];
-
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtView class]] ) {
return NO;
}
- NewtView* view = (NewtView *) nsview;
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [newtView cursorHide: NO enter: -1];
- if( false == [view getDestroyNotifySent] ) {
- jobject javaWindowObject = [view getJavaWindowObject];
+ if( false == [newtView getDestroyNotifySent] ) {
+ jobject javaWindowObject = [newtView getJavaWindowObject];
DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject);
if (javaWindowObject == NULL) {
DBG_PRINT("windowWillClose: null javaWindowObject\n");
+ [pool release];
return NO;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("windowWillClose: null JNIEnv\n");
+ [pool release];
return NO;
}
-
- [view setDestroyNotifySent: true]; // earmark assumption of being closed
+ [newtView setDestroyNotifySent: true]; // earmark assumption of being closed
closed = (*env)->CallBooleanMethod(env, javaWindowObject, windowDestroyNotifyID, force ? JNI_TRUE : JNI_FALSE);
if(!force && !closed) {
// not closed on java side, not force -> clear flag
- [view setDestroyNotifySent: false];
+ [newtView setDestroyNotifySent: false];
}
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed);
} else {
DBG_PRINT( "*************** windowWillClose (skip)\n");
@@ -1010,3 +1282,4 @@ static jint mods2JavaMods(NSUInteger mods)
}
@end
+
diff --git a/src/newt/native/ScreenMode.h b/src/newt/native/ScreenMode.h
index bb782910e..56c424b11 100644
--- a/src/newt/native/ScreenMode.h
+++ b/src/newt/native/ScreenMode.h
@@ -33,12 +33,18 @@
#ifndef _SCREEN_MODE_H
#define _SCREEN_MODE_H
-#define NUM_RESOLUTION_PROPERTIES 2 /* width, height */
-#define NUM_SURFACE_SIZE_PROPERTIES 1 /* bpp */
-#define NUM_MONITOR_MODE_PROPERTIES 3 /* ScreenSizeMM[width, height], refresh-rate */
-#define NUM_SCREEN_MODE_PROPERTIES 1 /* rotation */
+#define NUM_RESOLUTION_PROPERTIES 2 /* width, height */
+#define NUM_SURFACE_SIZE_PROPERTIES 1 /* bpp */
+#define NUM_SIZEANDRATE_PROPERTIES 2 /* refresh-rate, flags */
+#define NUM_MONITOR_MODE_PROPERTIES 2 /* id, rotation */
-#define NUM_SCREEN_MODE_PROPERTIES_ALL 8 /* count + the above */
+#define NUM_MONITOR_MODE_PROPERTIES_ALL 8 /* count + the above */
+
+#define MIN_MONITOR_DEVICE_PROPERTIES 15 /* count + id, ScreenSizeMM[width, height], rotated Viewport pixel-units, rotated Viewport pixel-units, currentMonitorModeId, rotation, supportedModeId+ */
+ /* Viewport := [x, y, width, height] (4 elements) */
+
+#define FLAG_INTERLACE ( 1 << 0 )
+#define FLAG_DOUBLESCAN ( 1 << 1 )
#endif
diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h
index 4755c4fc5..d9ee5fd1f 100644
--- a/src/newt/native/Window.h
+++ b/src/newt/native/Window.h
@@ -38,8 +38,9 @@
#define FLAG_HAS_PARENT ( 1 << 8 )
#define FLAG_IS_UNDECORATED ( 1 << 9 )
#define FLAG_IS_FULLSCREEN ( 1 << 10 )
-#define FLAG_IS_ALWAYSONTOP ( 1 << 11 )
-#define FLAG_IS_VISIBLE ( 1 << 12 )
+#define FLAG_IS_FULLSCREEN_SPAN ( 1 << 11 )
+#define FLAG_IS_ALWAYSONTOP ( 1 << 12 )
+#define FLAG_IS_VISIBLE ( 1 << 13 )
#define TST_FLAG_CHANGE_PARENTING(f) ( 0 != ( (f) & FLAG_CHANGE_PARENTING ) )
#define TST_FLAG_CHANGE_DECORATION(f) ( 0 != ( (f) & FLAG_CHANGE_DECORATION ) )
@@ -47,11 +48,11 @@
#define TST_FLAG_CHANGE_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_CHANGE_ALWAYSONTOP ) )
#define TST_FLAG_CHANGE_VISIBILITY(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) )
-#define TST_FLAG_HAS_PARENT(f) ( 0 != ( (f) & FLAG_HAS_PARENT ) )
-#define TST_FLAG_IS_UNDECORATED(f) ( 0 != ( (f) & FLAG_IS_UNDECORATED ) )
-#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) )
-#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) )
-#define TST_FLAG_IS_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) )
-#define TST_FLAG_IS_VISIBLE(f) ( 0 != ( (f) & FLAG_IS_VISIBLE ) )
+#define TST_FLAG_HAS_PARENT(f) ( 0 != ( (f) & FLAG_HAS_PARENT ) )
+#define TST_FLAG_IS_UNDECORATED(f) ( 0 != ( (f) & FLAG_IS_UNDECORATED ) )
+#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) )
+#define TST_FLAG_IS_FULLSCREEN_SPAN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN_SPAN ) )
+#define TST_FLAG_IS_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) )
+#define TST_FLAG_IS_VISIBLE(f) ( 0 != ( (f) & FLAG_IS_VISIBLE ) )
#endif
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index 40252f59b..70d0c6f83 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -32,6 +32,16 @@
*
*/
+//
+// Min. required version Windows 7 (For WM_TOUCH)
+//
+#if WINVER < 0x0601
+#error WINVER must be >= 0x0601
+#endif
+#if _WIN32_WINNT < 0x0601
+#error _WIN32_WINNT must be >= 0x0601
+#endif
+
#include <Windows.h>
#include <Windowsx.h>
#include <tchar.h>
@@ -49,13 +59,22 @@
#define strdup(s) _strdup(s)
#endif
+/* GetProcAddress doesn't exist in A/W variants under desktop Windows */
+#ifndef UNDER_CE
+#define GetProcAddressA GetProcAddress
+#endif
+
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif //WM_MOUSEWHEEL
-#ifndef WHEEL_DELTA
-#define WHEEL_DELTA 120
-#endif //WHEEL_DELTA
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL 0x020E
+#endif //WM_MOUSEHWHEEL
+
+#ifndef WHEEL_DELTAf
+#define WHEEL_DELTAf (120.0f)
+#endif //WHEEL_DELTAf
#ifndef WHEEL_PAGESCROLL
#define WHEEL_PAGESCROLL (UINT_MAX)
@@ -64,6 +83,30 @@
#ifndef GET_WHEEL_DELTA_WPARAM // defined for (_WIN32_WINNT >= 0x0500)
#define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
#endif
+#ifndef GET_KEYSTATE_WPARAM
+#define GET_KEYSTATE_WPARAM(wParam) ((short)LOWORD(wParam))
+#endif
+
+#ifndef WM_HSCROLL
+#define WM_HSCROLL 0x0114
+#endif
+#ifndef WM_VSCROLL
+#define WM_VSCROLL 0x0115
+#endif
+
+#ifndef WH_MOUSE
+#define WH_MOUSE 7
+#endif
+#ifndef WH_MOUSE_LL
+#define WH_MOUSE_LL 14
+#endif
+
+#ifndef WM_TOUCH
+#define WM_TOUCH 0x0240
+#endif
+#ifndef TOUCH_COORD_TO_PIXEL
+#define TOUCH_COORD_TO_PIXEL(l) (l/100)
+#endif
#ifndef MONITOR_DEFAULTTONULL
#define MONITOR_DEFAULTTONULL 0
@@ -80,6 +123,9 @@
#ifndef DISPLAY_DEVICE_ACTIVE
#define DISPLAY_DEVICE_ACTIVE 0x00000001
#endif
+#ifndef DM_INTERLACED
+#define DM_INTERLACED 2
+#endif
#include "jogamp_newt_driver_windows_DisplayDriver.h"
#include "jogamp_newt_driver_windows_ScreenDriver.h"
@@ -111,504 +157,442 @@ static jmethodID focusChangedID = NULL;
static jmethodID visibleChangedID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
-static jmethodID enqueueMouseEventID = NULL;
static jmethodID sendMouseEventID = NULL;
-static jmethodID enqueueKeyEventID = NULL;
+static jmethodID sendTouchScreenEventID = NULL;
static jmethodID sendKeyEventID = NULL;
static jmethodID requestFocusID = NULL;
+typedef WINBOOL (WINAPI *CloseTouchInputHandlePROCADDR)(HANDLE hTouchInput);
+typedef WINBOOL (WINAPI *GetTouchInputInfoPROCADDR)(HANDLE hTouchInput, UINT cInputs, PTOUCHINPUT pInputs, int cbSize);
+typedef WINBOOL (WINAPI *IsTouchWindowPROCADDR)(HWND hWnd,PULONG pulFlags);
+typedef WINBOOL (WINAPI *RegisterTouchWindowPROCADDR)(HWND hWnd,ULONG ulFlags);
+typedef WINBOOL (WINAPI *UnregisterTouchWindowPROCADDR)(HWND hWnd);
+
+static int WinTouch_func_avail = 0;
+static CloseTouchInputHandlePROCADDR WinTouch_CloseTouchInputHandle = NULL;
+static GetTouchInputInfoPROCADDR WinTouch_GetTouchInputInfo = NULL;
+static IsTouchWindowPROCADDR WinTouch_IsTouchWindow = NULL;
+static RegisterTouchWindowPROCADDR WinTouch_RegisterTouchWindow = NULL;
+static UnregisterTouchWindowPROCADDR WinTouch_UnregisterTouchWindow = NULL;
+
static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd);
typedef struct {
JNIEnv* jenv;
jobject jinstance;
+ /* client size width */
+ int width;
+ /* client size height */
+ int height;
+ /** Tristate: -1 HIDE, 0 NOP, 1 SHOW */
+ int setPointerVisible;
+ /** Tristate: -1 RESET, 0 NOP, 1 SET-NEW */
+ int setPointerAction;
+ HCURSOR setPointerHandle;
+ HCURSOR defPointerHandle;
+ /** Bool: 0 NOP, 1 FULLSCREEN */
+ int isFullscreen;
+ /** Bool: 0 TOP, 1 CHILD */
+ int isChildWindow;
+ int pointerCaptured;
+ int pointerInside;
+ int touchDownCount;
+ int touchDownLastUp; // mitigate LBUTTONUP after last TOUCH lift
+ int supportsMTouch;
} WindowUserData;
typedef struct {
- UINT javaKey;
- UINT windowsKey;
+ USHORT javaKey;
+ USHORT windowsKey;
+ USHORT windowsScanCodeUS;
} KeyMapEntry;
// Static table, arranged more or less spatially.
static KeyMapEntry keyMapTable[] = {
// Modifier keys
- {J_VK_CAPS_LOCK, VK_CAPITAL},
- {J_VK_SHIFT, VK_SHIFT},
- {J_VK_CONTROL, VK_CONTROL},
- {J_VK_ALT, VK_MENU},
- {J_VK_NUM_LOCK, VK_NUMLOCK},
+ {J_VK_CAPS_LOCK, VK_CAPITAL, 0},
+ {J_VK_SHIFT, VK_SHIFT, 0},
+ {J_VK_SHIFT, VK_LSHIFT, 0},
+ {J_VK_SHIFT, VK_RSHIFT, 0},
+ {J_VK_CONTROL, VK_CONTROL, 0},
+ {J_VK_CONTROL, VK_LCONTROL, 0},
+ {J_VK_CONTROL, VK_RCONTROL, 0},
+ {J_VK_ALT, VK_MENU, 0},
+ {J_VK_ALT, VK_LMENU, 0},
+ {J_VK_ALT_GRAPH, VK_RMENU, 0},
+ {J_VK_NUM_LOCK, VK_NUMLOCK, 0},
// Miscellaneous Windows keys
- {J_VK_WINDOWS, VK_LWIN},
- {J_VK_WINDOWS, VK_RWIN},
- {J_VK_CONTEXT_MENU, VK_APPS},
+ {J_VK_WINDOWS, VK_LWIN, 0},
+ {J_VK_WINDOWS, VK_RWIN, 0},
+ {J_VK_CONTEXT_MENU, VK_APPS, 0},
// Alphabet
- {J_VK_A, 'A'},
- {J_VK_B, 'B'},
- {J_VK_C, 'C'},
- {J_VK_D, 'D'},
- {J_VK_E, 'E'},
- {J_VK_F, 'F'},
- {J_VK_G, 'G'},
- {J_VK_H, 'H'},
- {J_VK_I, 'I'},
- {J_VK_J, 'J'},
- {J_VK_K, 'K'},
- {J_VK_L, 'L'},
- {J_VK_M, 'M'},
- {J_VK_N, 'N'},
- {J_VK_O, 'O'},
- {J_VK_P, 'P'},
- {J_VK_Q, 'Q'},
- {J_VK_R, 'R'},
- {J_VK_S, 'S'},
- {J_VK_T, 'T'},
- {J_VK_U, 'U'},
- {J_VK_V, 'V'},
- {J_VK_W, 'W'},
- {J_VK_X, 'X'},
- {J_VK_Y, 'Y'},
- {J_VK_Z, 'Z'},
- {J_VK_0, '0'},
- {J_VK_1, '1'},
- {J_VK_2, '2'},
- {J_VK_3, '3'},
- {J_VK_4, '4'},
- {J_VK_5, '5'},
- {J_VK_6, '6'},
- {J_VK_7, '7'},
- {J_VK_8, '8'},
- {J_VK_9, '9'},
- {J_VK_ENTER, VK_RETURN},
- {J_VK_SPACE, VK_SPACE},
- {J_VK_BACK_SPACE, VK_BACK},
- {J_VK_TAB, VK_TAB},
- {J_VK_ESCAPE, VK_ESCAPE},
- {J_VK_INSERT, VK_INSERT},
- {J_VK_DELETE, VK_DELETE},
- {J_VK_HOME, VK_HOME},
- {J_VK_END, VK_END},
- {J_VK_PAGE_UP, VK_PRIOR},
- {J_VK_PAGE_DOWN, VK_NEXT},
- {J_VK_CLEAR, VK_CLEAR}, // NumPad 5
+ {J_VK_A, 'A', 0},
+ {J_VK_B, 'B', 0},
+ {J_VK_C, 'C', 0},
+ {J_VK_D, 'D', 0},
+ {J_VK_E, 'E', 0},
+ {J_VK_F, 'F', 0},
+ {J_VK_G, 'G', 0},
+ {J_VK_H, 'H', 0},
+ {J_VK_I, 'I', 0},
+ {J_VK_J, 'J', 0},
+ {J_VK_K, 'K', 0},
+ {J_VK_L, 'L', 0},
+ {J_VK_M, 'M', 0},
+ {J_VK_N, 'N', 0},
+ {J_VK_O, 'O', 0},
+ {J_VK_P, 'P', 0},
+ {J_VK_Q, 'Q', 0},
+ {J_VK_R, 'R', 0},
+ {J_VK_S, 'S', 0},
+ {J_VK_T, 'T', 0},
+ {J_VK_U, 'U', 0},
+ {J_VK_V, 'V', 0},
+ {J_VK_W, 'W', 0},
+ {J_VK_X, 'X', 0},
+ {J_VK_Y, 'Y', 0},
+ {J_VK_Z, 'Z', 0},
+ {J_VK_0, '0', 0},
+ {J_VK_1, '1', 0},
+ {J_VK_2, '2', 0},
+ {J_VK_3, '3', 0},
+ {J_VK_4, '4', 0},
+ {J_VK_5, '5', 0},
+ {J_VK_6, '6', 0},
+ {J_VK_7, '7', 0},
+ {J_VK_8, '8', 0},
+ {J_VK_9, '9', 0},
+ {J_VK_ENTER, VK_RETURN, 0},
+ {J_VK_SPACE, VK_SPACE, 0},
+ {J_VK_BACK_SPACE, VK_BACK, 0},
+ {J_VK_TAB, VK_TAB, 0},
+ {J_VK_ESCAPE, VK_ESCAPE, 0},
+ {J_VK_INSERT, VK_INSERT, 0},
+ {J_VK_DELETE, VK_DELETE, 0},
+ {J_VK_HOME, VK_HOME, 0},
+ // {J_VK_BEGIN, VK_BEGIN, 0}, // not mapped
+ {J_VK_END, VK_END, 0},
+ {J_VK_PAGE_UP, VK_PRIOR, 0},
+ {J_VK_PAGE_DOWN, VK_NEXT, 0},
+ {J_VK_CLEAR, VK_CLEAR, 0}, // NumPad 5
// NumPad with NumLock off & extended arrows block (triangular)
- {J_VK_LEFT, VK_LEFT},
- {J_VK_RIGHT, VK_RIGHT},
- {J_VK_UP, VK_UP},
- {J_VK_DOWN, VK_DOWN},
+ {J_VK_LEFT, VK_LEFT, 0},
+ {J_VK_RIGHT, VK_RIGHT, 0},
+ {J_VK_UP, VK_UP, 0},
+ {J_VK_DOWN, VK_DOWN, 0},
// NumPad with NumLock on: numbers
- {J_VK_NUMPAD0, VK_NUMPAD0},
- {J_VK_NUMPAD1, VK_NUMPAD1},
- {J_VK_NUMPAD2, VK_NUMPAD2},
- {J_VK_NUMPAD3, VK_NUMPAD3},
- {J_VK_NUMPAD4, VK_NUMPAD4},
- {J_VK_NUMPAD5, VK_NUMPAD5},
- {J_VK_NUMPAD6, VK_NUMPAD6},
- {J_VK_NUMPAD7, VK_NUMPAD7},
- {J_VK_NUMPAD8, VK_NUMPAD8},
- {J_VK_NUMPAD9, VK_NUMPAD9},
+ {J_VK_NUMPAD0, VK_NUMPAD0, 0},
+ {J_VK_NUMPAD1, VK_NUMPAD1, 0},
+ {J_VK_NUMPAD2, VK_NUMPAD2, 0},
+ {J_VK_NUMPAD3, VK_NUMPAD3, 0},
+ {J_VK_NUMPAD4, VK_NUMPAD4, 0},
+ {J_VK_NUMPAD5, VK_NUMPAD5, 0},
+ {J_VK_NUMPAD6, VK_NUMPAD6, 0},
+ {J_VK_NUMPAD7, VK_NUMPAD7, 0},
+ {J_VK_NUMPAD8, VK_NUMPAD8, 0},
+ {J_VK_NUMPAD9, VK_NUMPAD9, 0},
// NumPad with NumLock on
- {J_VK_MULTIPLY, VK_MULTIPLY},
- {J_VK_ADD, VK_ADD},
- {J_VK_SEPARATOR, VK_SEPARATOR},
- {J_VK_SUBTRACT, VK_SUBTRACT},
- {J_VK_DECIMAL, VK_DECIMAL},
- {J_VK_DIVIDE, VK_DIVIDE},
+ {J_VK_MULTIPLY, VK_MULTIPLY, 0},
+ {J_VK_ADD, VK_ADD, 0},
+ {J_VK_SEPARATOR, VK_SEPARATOR, 0},
+ {J_VK_SUBTRACT, VK_SUBTRACT, 0},
+ {J_VK_DECIMAL, VK_DECIMAL, 0},
+ {J_VK_DIVIDE, VK_DIVIDE, 0},
// Functional keys
- {J_VK_F1, VK_F1},
- {J_VK_F2, VK_F2},
- {J_VK_F3, VK_F3},
- {J_VK_F4, VK_F4},
- {J_VK_F5, VK_F5},
- {J_VK_F6, VK_F6},
- {J_VK_F7, VK_F7},
- {J_VK_F8, VK_F8},
- {J_VK_F9, VK_F9},
- {J_VK_F10, VK_F10},
- {J_VK_F11, VK_F11},
- {J_VK_F12, VK_F12},
- {J_VK_F13, VK_F13},
- {J_VK_F14, VK_F14},
- {J_VK_F15, VK_F15},
- {J_VK_F16, VK_F16},
- {J_VK_F17, VK_F17},
- {J_VK_F18, VK_F18},
- {J_VK_F19, VK_F19},
- {J_VK_F20, VK_F20},
- {J_VK_F21, VK_F21},
- {J_VK_F22, VK_F22},
- {J_VK_F23, VK_F23},
- {J_VK_F24, VK_F24},
-
- {J_VK_PRINTSCREEN, VK_SNAPSHOT},
- {J_VK_SCROLL_LOCK, VK_SCROLL},
- {J_VK_PAUSE, VK_PAUSE},
- {J_VK_CANCEL, VK_CANCEL},
- {J_VK_HELP, VK_HELP},
+ {J_VK_F1, VK_F1, 0},
+ {J_VK_F2, VK_F2, 0},
+ {J_VK_F3, VK_F3, 0},
+ {J_VK_F4, VK_F4, 0},
+ {J_VK_F5, VK_F5, 0},
+ {J_VK_F6, VK_F6, 0},
+ {J_VK_F7, VK_F7, 0},
+ {J_VK_F8, VK_F8, 0},
+ {J_VK_F9, VK_F9, 0},
+ {J_VK_F10, VK_F10, 0},
+ {J_VK_F11, VK_F11, 0},
+ {J_VK_F12, VK_F12, 0},
+ {J_VK_F13, VK_F13, 0},
+ {J_VK_F14, VK_F14, 0},
+ {J_VK_F15, VK_F15, 0},
+ {J_VK_F16, VK_F16, 0},
+ {J_VK_F17, VK_F17, 0},
+ {J_VK_F18, VK_F18, 0},
+ {J_VK_F19, VK_F19, 0},
+ {J_VK_F20, VK_F20, 0},
+ {J_VK_F21, VK_F21, 0},
+ {J_VK_F22, VK_F22, 0},
+ {J_VK_F23, VK_F23, 0},
+ {J_VK_F24, VK_F24, 0},
+
+ {J_VK_PRINTSCREEN, VK_SNAPSHOT, 0},
+ {J_VK_SCROLL_LOCK, VK_SCROLL, 0},
+ {J_VK_PAUSE, VK_PAUSE, 0},
+ {J_VK_CANCEL, VK_CANCEL, 0},
+ {J_VK_HELP, VK_HELP, 0},
+
+ // Since we unify mappings via US kbd layout .. this is valid:
+ {J_VK_SEMICOLON, VK_OEM_1, 0}, // US only ';:'
+ {J_VK_EQUALS, VK_OEM_PLUS, 0}, // '=+'
+ {J_VK_COMMA, VK_OEM_COMMA, 0}, // ',<'
+ {J_VK_MINUS, VK_OEM_MINUS, 0}, // '-_'
+ {J_VK_PERIOD, VK_OEM_PERIOD, 0}, // '.>'
+ {J_VK_SLASH, VK_OEM_2, 0}, // US only '/?'
+ {J_VK_BACK_QUOTE, VK_OEM_3, 0}, // US only '`~'
+ {J_VK_OPEN_BRACKET, VK_OEM_4, 0}, // US only '[}'
+ {J_VK_BACK_SLASH, VK_OEM_5, 0}, // US only '\|'
+ {J_VK_CLOSE_BRACKET, VK_OEM_6, 0}, // US only ']}'
+ {J_VK_QUOTE, VK_OEM_7, 0}, // US only ''"'
+ // {J_VK_????, VK_OEM_8, 0}, // varies ..
+ // {J_VK_????, VK_OEM_102, 0}, // angle-bracket or backslash key on RT 102-key kbd
// Japanese
/*
- {J_VK_CONVERT, VK_CONVERT},
- {J_VK_NONCONVERT, VK_NONCONVERT},
- {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI},
- {J_VK_ALPHANUMERIC, VK_DBE_ALPHANUMERIC},
- {J_VK_KATAKANA, VK_DBE_KATAKANA},
- {J_VK_HIRAGANA, VK_DBE_HIRAGANA},
- {J_VK_FULL_WIDTH, VK_DBE_DBCSCHAR},
- {J_VK_HALF_WIDTH, VK_DBE_SBCSCHAR},
- {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN},
+ {J_VK_CONVERT, VK_CONVERT, 0},
+ {J_VK_NONCONVERT, VK_NONCONVERT, 0},
+ {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI, 0},
+ {J_VK_ALPHANUMERIC, VK_DBE_ALPHANUMERIC, 0},
+ {J_VK_KATAKANA, VK_DBE_KATAKANA, 0},
+ {J_VK_HIRAGANA, VK_DBE_HIRAGANA, 0},
+ {J_VK_FULL_WIDTH, VK_DBE_DBCSCHAR, 0},
+ {J_VK_HALF_WIDTH, VK_DBE_SBCSCHAR, 0},
+ {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN, 0},
*/
- {J_VK_UNDEFINED, 0}
-};
-
-/*
-Dynamic mapping table for OEM VK codes. This table is refilled
-by BuildDynamicKeyMapTable when keyboard layout is switched.
-(see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values).
-*/
-typedef struct {
- // OEM VK codes known in advance
- UINT windowsKey;
- // depends on input langauge (kbd layout)
- UINT javaKey;
-} DynamicKeyMapEntry;
-
-static DynamicKeyMapEntry dynamicKeyMapTable[] = {
- {0x00BA, J_VK_UNDEFINED}, // VK_OEM_1
- {0x00BB, J_VK_UNDEFINED}, // VK_OEM_PLUS
- {0x00BC, J_VK_UNDEFINED}, // VK_OEM_COMMA
- {0x00BD, J_VK_UNDEFINED}, // VK_OEM_MINUS
- {0x00BE, J_VK_UNDEFINED}, // VK_OEM_PERIOD
- {0x00BF, J_VK_UNDEFINED}, // VK_OEM_2
- {0x00C0, J_VK_UNDEFINED}, // VK_OEM_3
- {0x00DB, J_VK_UNDEFINED}, // VK_OEM_4
- {0x00DC, J_VK_UNDEFINED}, // VK_OEM_5
- {0x00DD, J_VK_UNDEFINED}, // VK_OEM_6
- {0x00DE, J_VK_UNDEFINED}, // VK_OEM_7
- {0x00DF, J_VK_UNDEFINED}, // VK_OEM_8
- {0x00E2, J_VK_UNDEFINED}, // VK_OEM_102
- {0, 0}
+ {J_VK_UNDEFINED, 0, 0}
};
-// Auxiliary tables used to fill the above dynamic table. We first
-// find the character for the OEM VK code using ::MapVirtualKey and
-// then go through these auxiliary tables to map it to Java VK code.
+#ifndef KLF_ACTIVATE
+ #define KLF_ACTIVATE 0x00000001
+#endif
+#ifndef MAPVK_VK_TO_VSC
+ #define MAPVK_VK_TO_VSC 0
+#endif
+#ifndef MAPVK_VSC_TO_VK
+ #define MAPVK_VSC_TO_VK 1
+#endif
+#ifndef MAPVK_VK_TO_CHAR
+ #define MAPVK_VK_TO_CHAR 2
+#endif
+#ifndef MAPVK_VSC_TO_VK_EX
+ #define MAPVK_VSC_TO_VK_EX 3
+#endif
+#ifndef MAPVK_VK_TO_VSC_EX
+ #define MAPVK_VK_TO_VSC_EX 4
+#endif
-typedef struct {
- WCHAR c;
- UINT javaKey;
-} CharToVKEntry;
-
-static const CharToVKEntry charToVKTable[] = {
- {L'!', J_VK_EXCLAMATION_MARK},
- {L'"', J_VK_QUOTEDBL},
- {L'#', J_VK_NUMBER_SIGN},
- {L'$', J_VK_DOLLAR},
- {L'&', J_VK_AMPERSAND},
- {L'\'', J_VK_QUOTE},
- {L'(', J_VK_LEFT_PARENTHESIS},
- {L')', J_VK_RIGHT_PARENTHESIS},
- {L'*', J_VK_ASTERISK},
- {L'+', J_VK_PLUS},
- {L',', J_VK_COMMA},
- {L'-', J_VK_MINUS},
- {L'.', J_VK_PERIOD},
- {L'/', J_VK_SLASH},
- {L':', J_VK_COLON},
- {L';', J_VK_SEMICOLON},
- {L'<', J_VK_LESS},
- {L'=', J_VK_EQUALS},
- {L'>', J_VK_GREATER},
- {L'@', J_VK_AT},
- {L'[', J_VK_OPEN_BRACKET},
- {L'\\', J_VK_BACK_SLASH},
- {L']', J_VK_CLOSE_BRACKET},
- {L'^', J_VK_CIRCUMFLEX},
- {L'_', J_VK_UNDERSCORE},
- {L'`', J_VK_BACK_QUOTE},
- {L'{', J_VK_BRACELEFT},
- {L'}', J_VK_BRACERIGHT},
- {0x00A1, J_VK_INVERTED_EXCLAMATION_MARK},
- {0x20A0, J_VK_EURO_SIGN}, // ????
- {0,0}
-};
+#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b))
-// For dead accents some layouts return ASCII punctuation, while some
-// return spacing accent chars, so both should be listed. NB: MS docs
-// say that conversion routings return spacing accent character, not
-// combining.
-static const CharToVKEntry charToDeadVKTable[] = {
- {L'`', J_VK_DEAD_GRAVE},
- {L'\'', J_VK_DEAD_ACUTE},
- {0x00B4, J_VK_DEAD_ACUTE},
- {L'^', J_VK_DEAD_CIRCUMFLEX},
- {L'~', J_VK_DEAD_TILDE},
- {0x02DC, J_VK_DEAD_TILDE},
- {0x00AF, J_VK_DEAD_MACRON},
- {0x02D8, J_VK_DEAD_BREVE},
- {0x02D9, J_VK_DEAD_ABOVEDOT},
- {L'"', J_VK_DEAD_DIAERESIS},
- {0x00A8, J_VK_DEAD_DIAERESIS},
- {0x02DA, J_VK_DEAD_ABOVERING},
- {0x02DD, J_VK_DEAD_DOUBLEACUTE},
- {0x02C7, J_VK_DEAD_CARON}, // aka hacek
- {L',', J_VK_DEAD_CEDILLA},
- {0x00B8, J_VK_DEAD_CEDILLA},
- {0x02DB, J_VK_DEAD_OGONEK},
- {0x037A, J_VK_DEAD_IOTA}, // ASCII ???
- {0x309B, J_VK_DEAD_VOICED_SOUND},
- {0x309C, J_VK_DEAD_SEMIVOICED_SOUND},
- {0,0}
-};
+static HKL kbdLayoutUS = 0;
+static const LPCSTR US_LAYOUT_NAME = "00000409";
-// ANSI CP identifiers are no longer than this
-#define MAX_ACP_STR_LEN 7
+static BYTE kbdState[256];
+static USHORT spaceScanCode;
-static void BuildDynamicKeyMapTable()
-{
+static void InitKeyMapTableScanCode(JNIEnv *env) {
HKL hkl = GetKeyboardLayout(0);
- // Will need this to reset layout after dead keys.
- UINT spaceScanCode = MapVirtualKeyEx(VK_SPACE, 0, hkl);
- DynamicKeyMapEntry *dynamic;
-
- LANGID idLang = LOWORD(GetKeyboardLayout(0));
- UINT codePage;
- TCHAR strCodePage[MAX_ACP_STR_LEN];
- // use the LANGID to create a LCID
- LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
- // get the ANSI code page associated with this locale
- if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE,
- strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
- {
- codePage = _ttoi(strCodePage);
- } else {
- codePage = GetACP();
+ int i;
+
+ kbdLayoutUS = LoadKeyboardLayout( US_LAYOUT_NAME, 0 /* ? KLF_ACTIVATE ? */ );
+ if( 0 == kbdLayoutUS ) {
+ int lastError = (int) GetLastError();
+ kbdLayoutUS = hkl; // use prev. layout .. well
+ STD_PRINT("Warning: NEWT Windows: LoadKeyboardLayout(US, ..) failed: winErr 0x%X %d\n", lastError, lastError);
}
+ ActivateKeyboardLayout(hkl, 0);
- // Entries in dynamic table that maps between Java VK and Windows
- // VK are built in three steps:
- // 1. Map windows VK to ANSI character (cannot map to unicode
- // directly, since ::ToUnicode is not implemented on win9x)
- // 2. Convert ANSI char to Unicode char
- // 3. Map Unicode char to Java VK via two auxilary tables.
+ spaceScanCode = MapVirtualKeyEx(VK_SPACE, MAPVK_VK_TO_VSC, hkl);
- for (dynamic = dynamicKeyMapTable; dynamic->windowsKey != 0; ++dynamic)
- {
- char cbuf[2] = { '\0', '\0'};
- WCHAR ucbuf[2] = { L'\0', L'\0' };
- int nchars;
- UINT scancode;
- const CharToVKEntry *charMap;
- int nconverted;
- WCHAR uc;
- BYTE kbdState[256];
-
- // Defaults to J_VK_UNDEFINED
- dynamic->javaKey = J_VK_UNDEFINED;
-
- GetKeyboardState(kbdState);
-
- kbdState[dynamic->windowsKey] |= 0x80; // Press the key.
-
- // Unpress modifiers, since they are most likely pressed as
- // part of the keyboard switching shortcut.
- kbdState[VK_CONTROL] &= ~0x80;
- kbdState[VK_SHIFT] &= ~0x80;
- kbdState[VK_MENU] &= ~0x80;
-
- scancode = MapVirtualKeyEx(dynamic->windowsKey, 0, hkl);
- nchars = ToAsciiEx(dynamic->windowsKey, scancode, kbdState,
- (WORD*)cbuf, 0, hkl);
-
- // Auxiliary table used to map Unicode character to Java VK.
- // Will assign a different table for dead keys (below).
- charMap = charToVKTable;
-
- if (nchars < 0) { // Dead key
- char junkbuf[2] = { '\0', '\0'};
- // Use a different table for dead chars since different layouts
- // return different characters for the same dead key.
- charMap = charToDeadVKTable;
-
- // We also need to reset layout so that next translation
- // is unaffected by the dead status. We do this by
- // translating <SPACE> key.
- kbdState[dynamic->windowsKey] &= ~0x80;
- kbdState[VK_SPACE] |= 0x80;
-
- ToAsciiEx(VK_SPACE, spaceScanCode, kbdState,
- (WORD*)junkbuf, 0, hkl);
+ // Setup keyMapTable's windowsScanCodeUS
+ for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+ USHORT scancode = (USHORT) MapVirtualKeyEx(keyMapTable[i].windowsKey, MAPVK_VK_TO_VSC_EX, kbdLayoutUS);
+ #ifdef DEBUG_KEYS
+ if( 0 == scancode ) {
+ int lastError = (int) GetLastError();
+ STD_PRINT("*** WindowsWindow: InitKeyMapTableScanCode: No ScanCode for windows vkey 0x%X (item %d), winErr 0x%X %d\n",
+ keyMapTable[i].windowsKey, i, lastError, lastError);
}
+ STD_PRINT("*** WindowsWindow: InitKeyMapTableScanCode: %3.3d windows vkey 0x%X -> scancode 0x%X\n",
+ i, keyMapTable[i].windowsKey, scancode);
+ #endif
+ keyMapTable[i].windowsScanCodeUS = scancode;
+ }
+}
- nconverted = MultiByteToWideChar(codePage, 0,
- cbuf, 1, ucbuf, 2);
+static void ParseWmVKeyAndScanCode(USHORT winVKey, BYTE winScanCode, BYTE flags, USHORT *outJavaVKeyUS, USHORT *outJavaVKeyXX, USHORT *outUTF16Char) {
+ wchar_t uniChars[2] = { L'\0', L'\0' }; // uint16_t
+ USHORT winVKeyUS = 0;
+ int nUniChars, i, j;
+ USHORT javaVKeyUS = J_VK_UNDEFINED;
+ USHORT javaVKeyXX = J_VK_UNDEFINED;
- uc = ucbuf[0];
- {
- const CharToVKEntry *map;
- for (map = charMap; map->c != 0; ++map) {
- if (uc == map->c) {
- dynamic->javaKey = map->javaKey;
- break;
- }
+ HKL hkl = GetKeyboardLayout(0);
+
+ //
+ // winVKey, winScanCode -> UTF16 w/ current KeyboardLayout
+ //
+ GetKeyboardState(kbdState);
+ kbdState[winVKey] |= 0x80;
+ nUniChars = ToUnicodeEx(winVKey, winScanCode, kbdState, uniChars, 2, 0, hkl);
+ kbdState[winVKey] &= ~0x80;
+
+ *outUTF16Char = (USHORT)(uniChars[0]); // Note: Even dead key are written in uniChar's ..
+
+ if ( 0 > nUniChars ) { // Dead key
+ char junkbuf[2] = { '\0', '\0'};
+
+ // We need to reset layout so that next translation
+ // is unaffected by the dead status. We do this by
+ // translating <SPACE> key.
+ kbdState[VK_SPACE] |= 0x80;
+ ToAsciiEx(VK_SPACE, spaceScanCode, kbdState, (WORD*)junkbuf, 0, hkl);
+ kbdState[VK_SPACE] &= ~0x80;
+ }
+
+ //
+ // winVKey -> javaVKeyXX
+ //
+ for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+ if ( keyMapTable[i].windowsKey == winVKey ) {
+ javaVKeyXX = keyMapTable[i].javaKey;
+ break;
+ }
+ }
+ if( IS_WITHIN( winVKey, VK_NUMPAD0, VK_DIVIDE ) ) {
+ // Use modded keySym for keypad for US and NN
+ winVKeyUS = winVKey;
+ javaVKeyUS = javaVKeyXX;
+ } else {
+ // Assume extended scan code 0xE0 if extended flags is set (no 0xE1 from WM_KEYUP/WM_KEYDOWN)
+ USHORT winScanCodeExt = winScanCode;
+ if( 0 != ( 0x01 & flags ) ) {
+ winScanCodeExt |= 0xE000;
+ }
+
+ //
+ // winVKey, winScanCodeExt -> javaVKeyUS w/ US KeyboardLayout
+ //
+ for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+ if ( keyMapTable[i].windowsScanCodeUS == winScanCodeExt ) {
+ winVKeyUS = keyMapTable[i].windowsKey;
+ javaVKeyUS = keyMapTable[i].javaKey;
+ break;
}
}
+ if( J_VK_UNDEFINED == javaVKeyUS ) {
+ javaVKeyUS = javaVKeyXX;
+ }
+ }
+
+ *outJavaVKeyUS = javaVKeyUS;
+ *outJavaVKeyXX = javaVKeyXX;
- } // for each VK_OEM_*
+#ifdef DEBUG_KEYS
+ STD_PRINT("*** WindowsWindow: ParseWmVKeyAndScanCode winVKey 0x%X, winScanCode 0x%X, flags 0x%X -> UTF(0x%X, %c, res %d, sizeof %d), vKeys( US(win 0x%X, java 0x%X), XX(win 0x%X, java 0x%X))\n",
+ (int)winVKey, (int)winScanCode, (int)flags,
+ *outUTF16Char, *outUTF16Char, nUniChars, sizeof(uniChars[0]),
+ winVKeyUS, javaVKeyUS, winVKey, javaVKeyXX);
+#endif
}
-static jint GetModifiers() {
+static jint GetModifiers(USHORT jkey) {
jint modifiers = 0;
// have to do &0xFFFF to avoid runtime assert caused by compiling with
// /RTCcsu
- if (HIBYTE((GetKeyState(VK_CONTROL) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_CONTROL) & 0xFFFF)) != 0 || J_VK_CONTROL == jkey ) {
modifiers |= EVENT_CTRL_MASK;
}
- if (HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0 || J_VK_SHIFT == jkey ) {
modifiers |= EVENT_SHIFT_MASK;
}
- if (HIBYTE((GetKeyState(VK_MENU) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_LMENU) & 0xFFFF)) != 0 || J_VK_ALT == jkey ) {
modifiers |= EVENT_ALT_MASK;
}
- if (HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_RMENU) & 0xFFFF)) != 0 || (USHORT)J_VK_ALT_GRAPH == jkey ) {
+ modifiers |= EVENT_ALT_GRAPH_MASK;
+ }
+ if ( HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON1_MASK;
}
- if (HIBYTE((GetKeyState(VK_MBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_MBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON2_MASK;
}
- if (HIBYTE((GetKeyState(VK_RBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_RBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON3_MASK;
}
return modifiers;
}
-static int WmChar(JNIEnv *env, jobject window, UINT character, UINT repCnt,
- UINT flags, BOOL system)
-{
+/**
+static BOOL IsAltKeyDown(BYTE flags, BOOL system) {
// The Alt modifier is reported in the 29th bit of the lParam,
- // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
- BOOL alt_is_down = (flags & (1<<13)) != 0;
- if (system && alt_is_down) {
- if (character == VK_SPACE) {
- return 1;
- }
- }
+ // i.e., it is the 5th bit of `flags' (which is HIBYTE(HIWORD(lParam))).
+ return system && ( flags & (1<<5) ) != 0;
+} */
- if (character == VK_RETURN) {
- character = J_VK_ENTER;
- }
- (*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_TYPED,
- GetModifiers(),
- (jint) -1,
- (jchar) character);
- return 1;
-}
-
-UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers)
-{
- int i, j;
- // for the general case, use a bi-directional table
- for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
- if (keyMapTable[i].windowsKey == windowsKey) {
- return keyMapTable[i].javaKey;
- }
- }
- for (j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
- if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
- if (dynamicKeyMapTable[j].javaKey != J_VK_UNDEFINED) {
- return dynamicKeyMapTable[j].javaKey;
- } else {
- break;
- }
- }
- }
-
- return J_VK_UNDEFINED;
-}
-
-static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
- UINT flags, BOOL system)
-{
- UINT modifiers = 0, jkey = 0, character = -1;
+static int WmKeyDown(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
+ UINT modifiers = 0;
+ USHORT javaVKeyUS=0, javaVKeyXX=0, utf16Char=0;
if (wkey == VK_PROCESSKEY) {
return 1;
}
- modifiers = GetModifiers();
- jkey = WindowsKeyToJavaKey(wkey, modifiers);
+ ParseWmVKeyAndScanCode(wkey, scanCode, flags, &javaVKeyUS, &javaVKeyXX, &utf16Char);
-/*
- character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
-*/
+ modifiers = GetModifiers( javaVKeyUS );
(*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_PRESSED,
- modifiers,
- (jint) jkey,
- (jchar) character);
-
- /* windows does not create a WM_CHAR for the Del key
- for some reason, so we need to create the KEY_TYPED event on the
- WM_KEYDOWN.
- */
- if (jkey == J_VK_DELETE) {
- (*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_TYPED,
- GetModifiers(),
- (jint) -1,
- (jchar) '\177');
- }
+ (jshort) EVENT_KEY_PRESSED,
+ (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char);
return 0;
}
-static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
- UINT flags, BOOL system)
-{
- UINT modifiers = 0, jkey = 0, character = -1;
+static int WmKeyUp(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
+ UINT modifiers = 0;
+ USHORT javaVKeyUS=0, javaVKeyXX=0, utf16Char=0;
if (wkey == VK_PROCESSKEY) {
return 1;
}
- modifiers = GetModifiers();
- jkey = WindowsKeyToJavaKey(wkey, modifiers);
-/*
- character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
-*/
+ ParseWmVKeyAndScanCode(wkey, scanCode, flags, &javaVKeyUS, &javaVKeyXX, &utf16Char);
+
+ modifiers = GetModifiers( javaVKeyUS );
(*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_RELEASED,
- modifiers,
- (jint) jkey,
- (jchar) character);
+ (jshort) EVENT_KEY_RELEASED,
+ (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char);
return 0;
}
static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jboolean force) {
HWND pHwnd, current;
+ BOOL isEnabled = IsWindowEnabled(hwnd);
pHwnd = GetParent(hwnd);
current = GetFocus();
- DBG_PRINT("*** WindowsWindow: requestFocus.S parent %p, window %p, isCurrent %d\n",
- (void*) pHwnd, (void*)hwnd, current==hwnd);
+ DBG_PRINT("*** WindowsWindow: requestFocus.S force %d, parent %p, window %p, isEnabled %d, isCurrent %d\n",
+ (int)force, (void*)pHwnd, (void*)hwnd, isEnabled, current==hwnd);
- if( JNI_TRUE==force || current!=hwnd) {
+ if( JNI_TRUE==force || current!=hwnd || !isEnabled ) {
UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if(!isEnabled) {
+ EnableWindow(hwnd, TRUE);
+ }
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags);
SetForegroundWindow(hwnd); // Slightly Higher Priority
- SetFocus(hwnd);// Sets Keyboard Focus To Window
+ SetFocus(hwnd);// Sets Keyboard Focus To Window (activates parent window if exist, or this window)
if(NULL!=pHwnd) {
SetActiveWindow(hwnd);
}
- DBG_PRINT("*** WindowsWindow: requestFocus.X1\n");
+ current = GetFocus();
+ DBG_PRINT("*** WindowsWindow: requestFocus.X1 isCurrent %d\n", current==hwnd);
}
DBG_PRINT("*** WindowsWindow: requestFocus.XX\n");
}
@@ -620,7 +604,33 @@ static void NewtWindows_trackPointerLeave(HWND hwnd) {
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hwnd;
tme.dwHoverTime = 0; // we don't use TME_HOVER
- TrackMouseEvent(&tme);
+ BOOL ok = TrackMouseEvent(&tme);
+ DBG_PRINT( "*** WindowsWindow: trackPointerLeave: %d\n", ok);
+ #ifdef VERBOSE_ON
+ if(!ok) {
+ int lastError = (int) GetLastError();
+ DBG_PRINT( "*** WindowsWindow: trackPointerLeave: lastError 0x%X %d\n", lastError, lastError);
+ }
+ #endif
+ (void)ok;
+}
+
+static jboolean NewtWindows_setFullScreen(jboolean fullscreen)
+{
+ int flags = 0;
+ DEVMODE dm;
+
+ // initialize the DEVMODE structure
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
+ {
+ return JNI_FALSE;
+ }
+ flags = ( JNI_TRUE == fullscreen ) ? CDS_FULLSCREEN : CDS_RESET ;
+
+ return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE;
}
#if 0
@@ -711,7 +721,7 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd)
{
LONG style = GetWindowLong(hwnd, GWL_STYLE);
- BOOL bIsUndecorated = (style & (WS_CHILD|WS_POPUP|WS_SYSMENU)) != 0;
+ BOOL bIsUndecorated = (style & (WS_CHILD|WS_POPUP)) != 0;
if (!bIsUndecorated) {
/* Get outer frame sizes. */
if (style & WS_THICKFRAME) {
@@ -745,11 +755,11 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd)
#endif
-static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type)
+static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type)
{
RECT rc;
- int w, h;
BOOL isVisible = IsWindowVisible(wnd);
+ jobject window = wud->jinstance;
if (type == SIZE_MINIMIZED) {
// TODO: deal with minimized window sizing
@@ -762,29 +772,147 @@ static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type)
GetClientRect(wnd, &rc);
// we report back the dimensions of the client area
- w = (int) ( rc.right - rc.left );
- h = (int) ( rc.bottom - rc.top );
+ wud->width = (int) ( rc.right - rc.left );
+ wud->height = (int) ( rc.bottom - rc.top );
- DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d, visible %d\n", (void*)wnd, w, h, isVisible);
+ DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d, visible %d\n", (void*)wnd, wud->width, wud->height, isVisible);
- (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, w, h, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, wud->width, wud->height, JNI_FALSE);
}
-static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
- WPARAM wParam, LPARAM lParam)
+#ifdef TEST_MOUSE_HOOKS
+
+static HHOOK hookLLMP;
+static HHOOK hookMP;
+
+static LRESULT CALLBACK HookLowLevelMouseProc (int code, WPARAM wParam, LPARAM lParam)
{
+ // if (code == HC_ACTION)
+ {
+ const char *msg;
+ char msg_buff[128];
+ switch (wParam)
+ {
+ case WM_LBUTTONDOWN: msg = "WM_LBUTTONDOWN"; break;
+ case WM_LBUTTONUP: msg = "WM_LBUTTONUP"; break;
+ case WM_MOUSEMOVE: msg = "WM_MOUSEMOVE"; break;
+ case WM_MOUSEWHEEL: msg = "WM_MOUSEWHEEL"; break;
+ case WM_MOUSEHWHEEL: msg = "WM_MOUSEHWHEEL"; break;
+ case WM_RBUTTONDOWN: msg = "WM_RBUTTONDOWN"; break;
+ case WM_RBUTTONUP: msg = "WM_RBUTTONUP"; break;
+ default:
+ sprintf(msg_buff, "Unknown msg: %u", wParam);
+ msg = msg_buff;
+ break;
+ }//switch
+
+ const MSLLHOOKSTRUCT *p = (MSLLHOOKSTRUCT*)lParam;
+ DBG_PRINT("**** LLMP: Code: 0x%X: %s - %d/%d\n", code, msg, (int)p->pt.x, (int)p->pt.y);
+ //} else {
+ // DBG_PRINT("**** LLMP: CODE: 0x%X\n", code);
+ }
+ return CallNextHookEx(hookLLMP, code, wParam, lParam);
+}
+
+static LRESULT CALLBACK HookMouseProc (int code, WPARAM wParam, LPARAM lParam)
+{
+ // if (code == HC_ACTION)
+ {
+ const char *msg;
+ char msg_buff[128];
+ switch (wParam)
+ {
+ case WM_LBUTTONDOWN: msg = "WM_LBUTTONDOWN"; break;
+ case WM_LBUTTONUP: msg = "WM_LBUTTONUP"; break;
+ case WM_MOUSEMOVE: msg = "WM_MOUSEMOVE"; break;
+ case WM_MOUSEWHEEL: msg = "WM_MOUSEWHEEL"; break;
+ case WM_MOUSEHWHEEL: msg = "WM_MOUSEHWHEEL"; break;
+ case WM_RBUTTONDOWN: msg = "WM_RBUTTONDOWN"; break;
+ case WM_RBUTTONUP: msg = "WM_RBUTTONUP"; break;
+ default:
+ sprintf(msg_buff, "Unknown msg: %u", wParam);
+ msg = msg_buff;
+ break;
+ }//switch
+
+ const MOUSEHOOKSTRUCT *p = (MOUSEHOOKSTRUCT*)lParam;
+ DBG_PRINT("**** MP: Code: 0x%X: %s - hwnd %p, %d/%d\n", code, msg, p->hwnd, (int)p->pt.x, (int)p->pt.y);
+ //} else {
+ // DBG_PRINT("**** MP: CODE: 0x%X\n", code);
+ }
+ return CallNextHookEx(hookMP, code, wParam, lParam);
+}
+
+#endif
+
+static BOOL SafeShowCursor(BOOL show) {
+ int count, countPre;
+ BOOL b;
+
+ if( show ) {
+ count = ShowCursor(TRUE);
+ if(count < 0) {
+ do {
+ countPre = count;
+ count = ShowCursor(TRUE);
+ } while( count > countPre && count < 0 );
+ }
+ b = count>=0 ? TRUE : FALSE;
+ } else {
+ count = ShowCursor(FALSE);
+ if(count >= 0) {
+ do {
+ countPre = count;
+ count = ShowCursor(FALSE);
+ } while( count < countPre && count >= 0 );
+ }
+ b = count<0 ? TRUE : FALSE;
+ }
+ return b;
+}
+
+static void sendTouchScreenEvent(JNIEnv *env, jobject window,
+ short eventType, int modifiers, int actionIdx,
+ int count, jint* pointerNames, jint* x, jint* y, jfloat* pressure, float maxPressure) {
+ jintArray jNames = (*env)->NewIntArray(env, count);
+ if (jNames == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (names) of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, jNames, 0, count, pointerNames);
+
+ jintArray jX = (*env)->NewIntArray(env, count);
+ if (jX == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (x) of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, jX, 0, count, x);
+
+ jintArray jY = (*env)->NewIntArray(env, count);
+ if (jY == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (y) of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, jY, 0, count, y);
+
+ jfloatArray jPressure = (*env)->NewFloatArray(env, count);
+ if (jPressure == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate float array (pressure) of size %d", count);
+ }
+ (*env)->SetFloatArrayRegion(env, jPressure, 0, count, pressure);
+
+ (*env)->CallVoidMethod(env, window, sendTouchScreenEventID,
+ (jshort)eventType, (jint)modifiers, (jint)actionIdx,
+ jNames, jX, jY, jPressure, (jfloat)maxPressure);
+}
+
+
+static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) {
LRESULT res = 0;
int useDefWindowProc = 0;
JNIEnv *env = NULL;
jobject window = NULL;
BOOL isKeyDown = FALSE;
WindowUserData * wud;
-
-#ifdef DEBUG_KEYS
- if ( WM_KEYDOWN == message ) {
- STD_PRINT("*** WindowsWindow: wndProc window %p, 0x%X %d/%d\n", wnd, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
- }
-#endif
+ WORD repCnt;
+ BYTE scanCode, flags;
#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
wud = (WindowUserData *) GetWindowLong(wnd, GWL_USERDATA);
@@ -797,216 +925,580 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
env = wud->jenv;
window = wud->jinstance;
- // DBG_PRINT("*** WindowsWindow: thread 0x%X - window %p -> %p, 0x%X %d/%d\n", (int)GetCurrentThreadId(), wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
+ // DBG_PRINT("*** WindowsWindow: thread 0x%X - window %p -> %p, msg 0x%X, %d/%d\n", (int)GetCurrentThreadId(), wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
if (NULL==window || NULL==env) {
return DefWindowProc(wnd, message, wParam, lParam);
}
switch (message) {
+ //
+ // The signal pipeline for destruction is:
+ // Java::DestroyWindow(wnd) _or_ window-close-button ->
+ // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY
+ case WM_CLOSE:
+ (*env)->CallBooleanMethod(env, window, windowDestroyNotifyID, JNI_FALSE);
+ break;
- //
- // The signal pipeline for destruction is:
- // Java::DestroyWindow(wnd) _or_ window-close-button ->
- // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY
- case WM_CLOSE:
- (*env)->CallBooleanMethod(env, window, windowDestroyNotifyID, JNI_FALSE);
- break;
-
- case WM_DESTROY:
- {
-#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
- SetWindowLong(wnd, GWL_USERDATA, (intptr_t) NULL);
-#else
- SetWindowLongPtr(wnd, GWLP_USERDATA, (intptr_t) NULL);
-#endif
- free(wud); wud=NULL;
- (*env)->DeleteGlobalRef(env, window);
- }
- break;
+ case WM_DESTROY:
+ {
+ #if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ SetWindowLong(wnd, GWL_USERDATA, (intptr_t) NULL);
+ #else
+ SetWindowLongPtr(wnd, GWLP_USERDATA, (intptr_t) NULL);
+ #endif
+ free(wud); wud=NULL;
+ (*env)->DeleteGlobalRef(env, window);
+ }
+ break;
- case WM_SYSCHAR:
- useDefWindowProc = WmChar(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
- break;
+ case WM_ACTIVATE: {
+ HWND wndPrev = (HWND) lParam;
+ BOOL fMinimized = (BOOL) HIWORD(wParam);
+ int fActive = LOWORD(wParam);
+ BOOL inactive = WA_INACTIVE==fActive;
+ #ifdef VERBOSE_ON
+ BOOL anyActive = WA_ACTIVE==fActive, clickActive = WA_CLICKACTIVE==fActive;
+ DBG_PRINT("*** WindowsWindow: WM_ACTIVATE window %p, prev %p, minimized %d, active %d (any %d, click %d, inactive %d), FS %d\n",
+ wnd, wndPrev, fMinimized, fActive, anyActive, clickActive, inactive, wud->isFullscreen);
+ #endif
+ if( wud->isFullscreen ) {
+ // Bug 916 - NEWT Fullscreen Mode on Windows ALT-TAB doesn't allow Application Switching
+ // Remedy for 'some' display drivers, i.e. Intel HD:
+ // Explicitly push fullscreen window to BOTTOM when inactive (ALT-TAB)
+ UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if( inactive ) {
+ SetWindowPos(wnd, HWND_BOTTOM, 0, 0, 0, 0, flags);
+ } else {
+ SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, flags);
+ SetForegroundWindow(wnd); // Slightly Higher Priority
+ }
+ }
+ useDefWindowProc = 1;
+ }
+ break;
- case WM_CHAR:
- useDefWindowProc = WmChar(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), TRUE);
- break;
-
- case WM_KEYDOWN:
-#ifdef DEBUG_KEYS
- STD_PRINT("*** WindowsWindow: windProc sending window %p -> %p, 0x%X %d/%d\n", wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
-#endif
- useDefWindowProc = WmKeyDown(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
- break;
+ case WM_SETTINGCHANGE:
+ if (wParam == SPI_SETNONCLIENTMETRICS) {
+ // make sure insets are updated, we don't need to resize the window
+ // because the size of the client area doesn't change
+ (void)UpdateInsets(env, window, wnd);
+ } else {
+ useDefWindowProc = 1;
+ }
+ break;
- case WM_KEYUP:
- useDefWindowProc = WmKeyUp(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
- break;
+ case WM_SIZE:
+ WmSize(env, wud, wnd, (UINT)wParam);
+ break;
- case WM_SIZE:
- WmSize(env, window, wnd, (UINT)wParam);
- break;
+ case WM_SHOWWINDOW:
+ (*env)->CallVoidMethod(env, window, visibleChangedID, JNI_FALSE, wParam==TRUE?JNI_TRUE:JNI_FALSE);
+ break;
- case WM_SETTINGCHANGE:
- if (wParam == SPI_SETNONCLIENTMETRICS) {
- // make sure insets are updated, we don't need to resize the window
- // because the size of the client area doesn't change
- (void)UpdateInsets(env, window, wnd);
- } else {
+ case WM_MOVE:
+ DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)GET_X_LPARAM(lParam), (jint)GET_Y_LPARAM(lParam));
useDefWindowProc = 1;
+ break;
+
+ case WM_PAINT: {
+ RECT r;
+ if (GetUpdateRect(wnd, &r, FALSE /* do not erase background */)) {
+ // clear the whole client area and issue repaint for it, w/o looping through erase background
+ ValidateRect(wnd, NULL); // clear all!
+ (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
+ } else {
+ // shall not happen ?
+ ValidateRect(wnd, NULL); // clear all!
+ }
+ // return 0 == done
+ break;
}
- break;
+ case WM_ERASEBKGND:
+ // ignore erase background
+ (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
+ res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this
+ break;
+ case WM_SETCURSOR :
+ if (0 != wud->setPointerVisible) { // Tristate, -1, 0, 1
+ BOOL visibilityChangeSuccessful;
+ if (1 == wud->setPointerVisible) {
+ visibilityChangeSuccessful = SafeShowCursor(TRUE);
+ } else /* -1 == wud->setPointerVisible */ {
+ visibilityChangeSuccessful = SafeShowCursor(FALSE);
+ }
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR requested visibility: %d success: %d\n", wud->setPointerVisible, visibilityChangeSuccessful);
+ wud->setPointerVisible = 0;
+ // own signal, consumed, no further processing
+ res = 1;
+ } else if( 0 != wud->setPointerAction ) {
+ if( -1 == wud->setPointerAction ) {
+ wud->setPointerHandle = wud->defPointerHandle;
+ }
+ HCURSOR preHandle = SetCursor(wud->setPointerHandle);
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR PointerIcon change %d: pre %p -> set %p, def %p\n",
+ wud->setPointerAction, (void*)preHandle, (void*)wud->setPointerHandle, (void*)wud->defPointerHandle);
+ wud->setPointerAction = 0;
+ // own signal, consumed, no further processing
+ res = 1;
+ } else if( HTCLIENT == LOWORD(lParam) ) {
+ BOOL setCur = wud->isChildWindow && wud->defPointerHandle != wud->setPointerHandle;
+ #ifdef VERBOSE_ON
+ HCURSOR cur = GetCursor();
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR PointerIcon NOP [1 custom-override] set %p, def %p, cur %p, isChild %d, setCur %d\n",
+ (void*)wud->setPointerHandle, (void*)wud->defPointerHandle, (void*)cur, wud->isChildWindow, setCur);
+ #endif
+ if( setCur ) {
+ SetCursor(wud->setPointerHandle);
+ // own signal, consumed, no further processing
+ res = 1;
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR PointerIcon NOP [2 parent-override] set %p, def %p\n", (void*)wud->setPointerHandle, (void*)wud->defPointerHandle);
+ // NOP for us, allow parent to act
+ res = 0;
+ }
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR !HTCLIENT\n");
+ // NOP for us, allow parent to act
+ res = 0;
+ }
+ break;
- case WM_LBUTTONDOWN:
- DBG_PRINT("*** WindowsWindow: LBUTTONDOWN\n");
- (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 1, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SETFOCUS:
+ DBG_PRINT("*** WindowsWindow: WM_SETFOCUS window %p, lost %p\n", wnd, (HWND)wParam);
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE);
+ useDefWindowProc = 1;
+ break;
- case WM_LBUTTONUP:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 1, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_KILLFOCUS:
+ DBG_PRINT("*** WindowsWindow: WM_KILLFOCUS window %p, received %p, inside %d, captured %d, tDown %d\n",
+ wnd, (HWND)wParam, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount);
+ if( wud->touchDownCount == 0 ) {
+ wud->pointerInside = 0;
+ if( wud->pointerCaptured ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE);
+ useDefWindowProc = 1;
+ } else {
+ // quick focus .. we had it already, are enabled ..
+ SetFocus(wnd);// Sets Keyboard Focus To Window (activates parent window if exist, or this window)
+ }
+ break;
- case WM_MBUTTONDOWN:
- DBG_PRINT("*** WindowsWindow: MBUTTONDOWN\n");
- (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 2, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SYSCHAR:
+ useDefWindowProc = 1;
+ break;
- case WM_MBUTTONUP:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 2, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SYSKEYDOWN:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_SYSKEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyDown(env, window, (USHORT)wParam, repCnt, scanCode, flags, TRUE);
+ break;
- case WM_RBUTTONDOWN:
- DBG_PRINT("*** WindowsWindow: RBUTTONDOWN\n");
- (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 3, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SYSKEYUP:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_SYSKEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyUp(env, window, (USHORT)wParam, repCnt, scanCode, flags, TRUE);
+ break;
- case WM_RBUTTONUP:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 3, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_CHAR:
+ useDefWindowProc = 1;
+ break;
+
+ case WM_KEYDOWN:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_KEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyDown(env, window, wParam, repCnt, scanCode, flags, FALSE);
+ break;
- case WM_MOUSEMOVE:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_MOVED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 0, (jint) 0);
- useDefWindowProc = 1;
- break;
- case WM_MOUSELEAVE:
- (*env)->CallVoidMethod(env, window, enqueueMouseEventID, JNI_FALSE,
- (jint) EVENT_MOUSE_EXITED,
- 0,
- (jint) -1, (jint) -1, // fake
- (jint) 0, (jint) 0);
- useDefWindowProc = 1;
- break;
- // Java synthesizes EVENT_MOUSE_ENTERED
-
- case WM_MOUSEWHEEL: {
- // need to convert the coordinates to component-relative
- int x = GET_X_LPARAM(lParam);
- int y = GET_Y_LPARAM(lParam);
- POINT eventPt;
- eventPt.x = x;
- eventPt.y = y;
- ScreenToClient(wnd, &eventPt);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_WHEEL_MOVED,
- GetModifiers(),
- (jint) eventPt.x, (jint) eventPt.y,
- (jint) 1, (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f));
- useDefWindowProc = 1;
- break;
- }
+ case WM_KEYUP:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_KEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyUp(env, window, wParam, repCnt, scanCode, flags, FALSE);
+ break;
- case WM_SETFOCUS:
- (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE);
- useDefWindowProc = 1;
- break;
+ case WM_LBUTTONDOWN: {
+ DBG_PRINT("*** WindowsWindow: WM_LBUTTONDOWN %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownLastUp && 0 == wud->touchDownCount ) {
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_PRESSED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 1, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_KILLFOCUS:
- (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE);
- useDefWindowProc = 1;
- break;
+ case WM_LBUTTONUP: {
+ DBG_PRINT("*** WindowsWindow: WM_LBUTTONUP %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 < wud->touchDownLastUp ) {
+ // mitigate LBUTTONUP after last TOUCH lift
+ wud->touchDownLastUp = 0;
+ } else if( 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_RELEASED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 1, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_SHOWWINDOW:
- (*env)->CallVoidMethod(env, window, visibleChangedID, JNI_FALSE, wParam==TRUE?JNI_TRUE:JNI_FALSE);
- break;
+ case WM_MBUTTONDOWN: {
+ DBG_PRINT("*** WindowsWindow: WM_MBUTTONDOWN %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_PRESSED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 2, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_MOVE:
- DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)GET_X_LPARAM(lParam), (jint)GET_Y_LPARAM(lParam));
- useDefWindowProc = 1;
- break;
+ case WM_MBUTTONUP: {
+ DBG_PRINT("*** WindowsWindow: WM_MBUTTONUP %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_RELEASED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 2, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_PAINT: {
- RECT r;
- useDefWindowProc = 0;
- if (GetUpdateRect(wnd, &r, TRUE /* erase background */)) {
- /*
- jint width = r.right-r.left;
- jint height = r.bottom-r.top;
- if (width > 0 && height > 0) {
- (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, r.left, r.top, width, height);
+ case WM_RBUTTONDOWN: {
+ DBG_PRINT("*** WindowsWindow: WM_RBUTTONDOWN %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_PRESSED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 3, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
+
+ case WM_RBUTTONUP: {
+ DBG_PRINT("*** WindowsWindow: WM_RBUTTONUP %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_RELEASED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 3, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
+
+ case WM_MOUSEMOVE: {
+ DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownLastUp && 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( 0 == wud->pointerCaptured && 0 != ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 1;
+ SetCapture(wnd);
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ SetCursor(wud->setPointerHandle);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 0, (jfloat) 0.0f);
+ }
+ useDefWindowProc = 1;
+ }
+ break;
+ case WM_MOUSELEAVE: {
+ DBG_PRINT("*** WindowsWindow: WM_MOUSELEAVE %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ wud->pointerInside = 0;
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_EXITED,
+ 0,
+ (jint) -1, (jint) -1, // fake
+ (jshort) 0, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
+ // Java synthesizes EVENT_MOUSE_ENTERED
+
+ case WM_HSCROLL: { // Only delivered if windows has WS_HSCROLL, hence dead code!
+ int sb = LOWORD(wParam);
+ int modifiers = GetModifiers( 0 ) | EVENT_SHIFT_MASK;
+ float rotation;
+ switch(sb) {
+ case SB_LINELEFT:
+ rotation = 1.0f;
+ break;
+ case SB_PAGELEFT:
+ rotation = 2.0f;
+ break;
+ case SB_LINERIGHT:
+ rotation = -1.0f;
+ break;
+ case SB_PAGERIGHT:
+ rotation = -1.0f;
+ break;
+ }
+ DBG_PRINT("*** WindowsWindow: WM_HSCROLL 0x%X, rotation %f, mods 0x%X\n", sb, rotation, modifiers);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_WHEEL_MOVED,
+ modifiers,
+ (jint) 0, (jint) 0,
+ (jshort) 1, (jfloat) rotation);
+ useDefWindowProc = 1;
+ break;
}
- ValidateRect(wnd, &r);
- */
+ case WM_MOUSEHWHEEL: /* tilt */
+ case WM_MOUSEWHEEL: /* rotation */ {
+ // need to convert the coordinates to component-relative
+ int x = GET_X_LPARAM(lParam);
+ int y = GET_Y_LPARAM(lParam);
+ int modifiers = GetModifiers( 0 );
+ float rotationOrTilt = (float)(GET_WHEEL_DELTA_WPARAM(wParam))/WHEEL_DELTAf;
+ int vKeys = GET_KEYSTATE_WPARAM(wParam);
+ POINT eventPt;
+ eventPt.x = x;
+ eventPt.y = y;
+ ScreenToClient(wnd, &eventPt);
+
+ if( WM_MOUSEHWHEEL == message ) {
+ modifiers |= EVENT_SHIFT_MASK;
+ DBG_PRINT("*** WindowsWindow: WM_MOUSEHWHEEL %d/%d, tilt %f, vKeys 0x%X, mods 0x%X\n",
+ (int)eventPt.x, (int)eventPt.y, rotationOrTilt, vKeys, modifiers);
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_MOUSEWHEEL %d/%d, rotation %f, vKeys 0x%X, mods 0x%X\n",
+ (int)eventPt.x, (int)eventPt.y, rotationOrTilt, vKeys, modifiers);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_WHEEL_MOVED,
+ modifiers,
+ (jint) eventPt.x, (jint) eventPt.y,
+ (jshort) 1, (jfloat) rotationOrTilt);
+ useDefWindowProc = 1;
+ break;
}
- break;
- }
- case WM_ERASEBKGND:
- // ignore erase background
- (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
- useDefWindowProc = 0;
- res = 1; // OpenGL, etc .. erases the background, hence we claim to have just done this
- break;
+ case WM_TOUCH: if( wud->supportsMTouch ) {
+ UINT cInputs = LOWORD(wParam);
+ // DBG_PRINT("*** WindowsWindow: WM_TOUCH window %p, cInputs %d\n", wnd, cInputs);
+ HTOUCHINPUT hTouch = (HTOUCHINPUT)lParam;
+ PTOUCHINPUT pInputs = (PTOUCHINPUT) calloc(cInputs, sizeof(TOUCHINPUT));
+ if (NULL != pInputs) {
+ if ( WinTouch_GetTouchInputInfo(hTouch, cInputs, pInputs, sizeof(TOUCHINPUT)) ) {
+ UINT i;
+ short eventType[cInputs];
+ jint modifiers = GetModifiers( 0 );
+ jint actionIdx = -1;
+ jint pointerNames[cInputs];
+ jint x[cInputs], y[cInputs];
+ jfloat pressure[cInputs];
+ jfloat maxPressure = 1.0F; // FIXME: n/a on windows ?
+ int allPInside = 0 < cInputs;
+ int sendFocus = 0;
+
+ for (i=0; i < cInputs; i++) {
+ PTOUCHINPUT pTi = & pInputs[i];
+ POINT eventPt;
+ int isDown = pTi->dwFlags & TOUCHEVENTF_DOWN;
+ int isUp = pTi->dwFlags & TOUCHEVENTF_UP;
+ int isMove = pTi->dwFlags & TOUCHEVENTF_MOVE;
+
+ int isPrim = pTi->dwFlags & TOUCHEVENTF_PRIMARY;
+ int isNoCoalesc = pTi->dwFlags & TOUCHEVENTF_NOCOALESCE;
+
+ #ifdef VERBOSE_ON
+ const char * touchAction;
+ if( isDown ) {
+ touchAction = "down";
+ } else if( isUp ) {
+ touchAction = "_up_";
+ } else if( isMove ) {
+ touchAction = "move";
+ } else {
+ touchAction = "undf";
+ }
+ #endif
+
+ pointerNames[i] = (jint)pTi->dwID;
+ eventPt.x = TOUCH_COORD_TO_PIXEL(pTi->x);
+ eventPt.y = TOUCH_COORD_TO_PIXEL(pTi->y);
+ ScreenToClient(wnd, &eventPt);
+
+ int pInside = 0 <= eventPt.x && 0 <= eventPt.y && eventPt.x < wud->width && eventPt.y < wud->height;
+ allPInside &= pInside;
+
+ x[i] = (jint)eventPt.x;
+ y[i] = (jint)eventPt.y;
+ pressure[i] = 1.0F; // FIXME: n/a on windows ?
+ if(isDown) {
+ sendFocus = 0 == wud->touchDownCount;
+ eventType[i] = (jshort) EVENT_MOUSE_PRESSED;
+ wud->touchDownCount++;
+ wud->touchDownLastUp = 0;
+ } else if(isUp) {
+ eventType[i] = (jshort) EVENT_MOUSE_RELEASED;
+ wud->touchDownCount--;
+ // mitigate LBUTTONUP after last TOUCH lift
+ wud->touchDownLastUp = 0 == wud->touchDownCount;
+ } else if(isMove) {
+ eventType[i] = (jshort) EVENT_MOUSE_MOVED;
+ wud->touchDownLastUp = 0;
+ } else {
+ eventType[i] = (jshort) 0;
+ }
+ if(isPrim) {
+ actionIdx = (jint)i;
+ }
+
+ #ifdef VERBOSE_ON
+ DBG_PRINT("*** WindowsWindow: WM_TOUCH[%d/%d].%s name 0x%x, prim %d, nocoalsc %d, %d/%d [%dx%d] inside [%d/%d], tDown [c %d, lastUp %d]\n",
+ (i+1), cInputs, touchAction, (int)(pTi->dwID), isPrim, isNoCoalesc, x[i], y[i], wud->width, wud->height,
+ pInside, allPInside, wud->touchDownCount, wud->touchDownLastUp);
+ #endif
+ }
+ wud->pointerInside = allPInside;
+ if( sendFocus ) {
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ }
+ int sentCount = 0, updownCount=0, moveCount=0;
+ // Primary first, if available!
+ if( 0 <= actionIdx ) {
+ sendTouchScreenEvent(env, window, eventType[actionIdx], modifiers, actionIdx,
+ cInputs, pointerNames, x, y, pressure, maxPressure);
+ sentCount++;
+ }
+ // 1 Move second ..
+ for (i=0; i < cInputs; i++) {
+ short et = eventType[i];
+ if( (jshort) EVENT_MOUSE_MOVED == et ) {
+ if( i != actionIdx && 0 == moveCount ) {
+ sendTouchScreenEvent(env, window, et, modifiers, i,
+ cInputs, pointerNames, x, y, pressure, maxPressure);
+ sentCount++;
+ }
+ moveCount++;
+ }
+ }
+ // Up and downs last
+ for (i=0; i < cInputs; i++) {
+ short et = eventType[i];
+ if( (jshort) EVENT_MOUSE_MOVED != et ) {
+ if( i != actionIdx ) {
+ sendTouchScreenEvent(env, window, et, modifiers, i,
+ cInputs, pointerNames, x, y, pressure, maxPressure);
+ sentCount++;
+ }
+ updownCount++;
+ }
+ }
+ DBG_PRINT("*** WindowsWindow: WM_TOUCH.summary pCount %d, prim %d, updown %d, move %d, sent %d, inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ cInputs, actionIdx, updownCount, moveCount, sentCount, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+
+ // Message processed - close it
+ WinTouch_CloseTouchInputHandle(hTouch);
+ } else {
+ useDefWindowProc = 1;
+ }
+ free(pInputs);
+ }
+ break;
+ }
- default:
- useDefWindowProc = 1;
+ default:
+ useDefWindowProc = 1;
}
- if (useDefWindowProc)
+
+ if (useDefWindowProc) {
return DefWindowProc(wnd, message, wParam, lParam);
+ }
return res;
}
@@ -1028,12 +1520,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_DispatchMes
// DBG_PRINT("*** WindowsWindow.DispatchMessages0: thread 0x%X - gotOne %d\n", (int)GetCurrentThreadId(), (int)gotOne);
if (gotOne) {
++i;
-#ifdef DEBUG_KEYS
- if(WM_KEYDOWN == msg.message) {
- STD_PRINT("*** WindowsWindow: DispatchMessages window %p, 0x%X %d/%d\n", msg.hwnd, msg.message, (int)LOWORD(msg.lParam), (int)HIWORD(msg.lParam));
- }
-#endif
- TranslateMessage(&msg);
+ // TranslateMessage(&msg); // No more needed: We translate V_KEY -> UTF Char manually in key up/down
DispatchMessage(&msg);
}
} while (gotOne && i < 100);
@@ -1041,11 +1528,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_DispatchMes
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: getOriginX0
- * Signature: (I)I
+ * Method: getVirtualOriginX0
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginX0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualOriginX0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS) > 1) {
return (jint)GetSystemMetrics(SM_XVIRTUALSCREEN);
@@ -1056,11 +1543,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginX0
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: getOriginY0
- * Signature: (I)I
+ * Method: getVirtualOriginY0
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginY0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualOriginY0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS ) > 1) {
return (jint)GetSystemMetrics(SM_YVIRTUALSCREEN);
@@ -1071,11 +1558,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginY0
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: getWidthImpl
- * Signature: (I)I
+ * Method: getVirtualWidthImpl
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getWidthImpl0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualWidthImpl0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS) > 1) {
return (jint)GetSystemMetrics(SM_CXVIRTUALSCREEN);
@@ -1086,11 +1573,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getWidthImpl
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: getHeightImpl
- * Signature: (I)I
+ * Method: getVirtualHeightImpl
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getHeightImpl0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualHeightImpl0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS ) > 1) {
return (jint)GetSystemMetrics(SM_CYVIRTUALSCREEN);
@@ -1142,65 +1629,137 @@ static int NewtScreen_RotationNewtCCW2NativeCCW(JNIEnv *env, jint newt) {
return native;
}
-/*
-static void NewtScreen_scanDisplayDevices() {
- DISPLAY_DEVICE device;
- int i = 0;
- LPCTSTR name;
- while(NULL != (name = NewtScreen_getDisplayDeviceName(&device, i))) {
- fprintf(stderr, "*** [%d]: <%s> active %d\n", i, name, ( 0 != ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
- i++;
+static LPCTSTR NewtScreen_getAdapterName(DISPLAY_DEVICE * device, int crt_idx) {
+ memset(device, 0, sizeof(DISPLAY_DEVICE));
+ device->cb = sizeof(DISPLAY_DEVICE);
+ if( FALSE == EnumDisplayDevices(NULL, crt_idx, device, 0) ) {
+ DBG_PRINT("*** WindowsWindow: getAdapterName.EnumDisplayDevices(crt_idx %d) -> FALSE\n", crt_idx);
+ return NULL;
}
-}*/
-static LPCTSTR NewtScreen_getDisplayDeviceName(DISPLAY_DEVICE * device, int scrn_idx) {
- device->cb = sizeof(DISPLAY_DEVICE);
- if( FALSE == EnumDisplayDevices(NULL, scrn_idx, device, 0) ) {
- DBG_PRINT("*** WindowsWindow: getDisplayDeviceName.EnumDisplayDevices(scrn_idx %d) -> FALSE\n", scrn_idx);
+ if( NULL == device->DeviceName || 0 == _tcslen(device->DeviceName) ) {
return NULL;
}
- if( 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) {
- DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(scrn_idx %d)\n", scrn_idx);
+ return device->DeviceName;
+}
+
+static LPCTSTR NewtScreen_getMonitorName(LPCTSTR adapterName, DISPLAY_DEVICE * device, int monitor_idx, BOOL onlyActive) {
+ memset(device, 0, sizeof(DISPLAY_DEVICE));
+ device->cb = sizeof(DISPLAY_DEVICE);
+ if( 0 == monitor_idx ) {
+ if( FALSE == EnumDisplayDevices(adapterName, monitor_idx, device, 0) ) {
+ DBG_PRINT("*** WindowsWindow: getDisplayName.EnumDisplayDevices(monitor_idx %d).adapter -> FALSE\n", monitor_idx);
+ return NULL;
+ }
+ }
+
+ if( onlyActive && 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) {
+ DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(monitor_idx %d).display\n", monitor_idx);
+ return NULL;
+ }
+ if( NULL == device->DeviceName || 0 == _tcslen(device->DeviceName) ) {
return NULL;
}
return device->DeviceName;
}
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_dumpMonitorInfo0
+ (JNIEnv *env, jclass clazz)
+{
+ DISPLAY_DEVICE aDevice, dDevice;
+ int i = 0, j;
+ LPCTSTR aName, dName;
+ while(NULL != (aName = NewtScreen_getAdapterName(&aDevice, i))) {
+ fprintf(stderr, "*** [%d]: <%s> flags 0x%X active %d\n", i, aName, aDevice.StateFlags, ( 0 != ( aDevice.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
+ j=0;
+ while(NULL != (dName = NewtScreen_getMonitorName(aName, &dDevice, j, FALSE))) {
+ fprintf(stderr, "*** [%d][%d]: <%s> flags 0x%X active %d\n", i, j, dName, dDevice.StateFlags, ( 0 != ( dDevice.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
+ j++;
+ }
+ i++;
+ }
+}
+
static HDC NewtScreen_createDisplayDC(LPCTSTR displayDeviceName) {
return CreateDC("DISPLAY", displayDeviceName, NULL, NULL);
}
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: getScreenMode0
- * Signature: (II)[I
+ * Method: getAdapterName0
+ * Signature: (I)Ljava/lang/String;
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScreenMode0
- (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx)
+JNIEXPORT jstring JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getAdapterName0
+ (JNIEnv *env, jobject obj, jint crt_idx)
{
DISPLAY_DEVICE device;
- int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL;
- LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx);
- if(NULL == deviceName) {
- DBG_PRINT("*** WindowsWindow: getScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx);
- return (*env)->NewIntArray(env, 0);
+ LPCTSTR adapterName = NewtScreen_getAdapterName(&device, crt_idx);
+ DBG_PRINT("*** WindowsWindow: getAdapterName(crt_idx %d) -> %s, active %d\n", crt_idx,
+ (NULL==adapterName?"nil":adapterName), 0 == ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ));
+ if(NULL == adapterName) {
+ return NULL;
}
+#ifdef UNICODE
+ return (*env)->NewString(env, adapterName, wcslen(adapterName));
+#else
+ return (*env)->NewStringUTF(env, adapterName);
+#endif
+}
+/*
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getActiveMonitorName0
+ * Signature: (Ljava/lang/String;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getActiveMonitorName0
+ (JNIEnv *env, jobject obj, jstring jAdapterName, jint monitor_idx)
+{
+ DISPLAY_DEVICE device;
+ LPCTSTR monitorName;
+#ifdef UNICODE
+ LPCTSTR adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+ monitorName = NewtScreen_getMonitorName(adapterName, &device, monitor_idx, TRUE);
+ DBG_PRINT("*** WindowsWindow: getMonitorName(%s, monitor_idx %d) -> %s\n", adapterName, monitor_idx, (NULL==monitorName?"nil":monitorName));
+ free((void*) adapterName);
+#else
+ LPCTSTR adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+ monitorName = NewtScreen_getMonitorName(adapterName, &device, monitor_idx, TRUE);
+ DBG_PRINT("*** WindowsWindow: getMonitorName(%s, monitor_idx %d) -> %s\n", adapterName, monitor_idx, (NULL==monitorName?"nil":monitorName));
+ (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+ if(NULL == monitorName) {
+ return NULL;
+ }
+#ifdef UNICODE
+ return (*env)->NewString(env, monitorName, wcslen(monitorName));
+#else
+ return (*env)->NewStringUTF(env, monitorName);
+#endif
+}
+
+/*
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getMonitorMode0
+ * Signature: (Ljava/lang/String;I)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getMonitorMode0
+ (JNIEnv *env, jobject obj, jstring jAdapterName, jint mode_idx)
+{
+ DISPLAY_DEVICE device;
+ LPCTSTR adapterName;
+ {
+#ifdef UNICODE
+ adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+#else
+ adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+#endif
+ }
int devModeID;
- int widthmm, heightmm;
if(-1 < mode_idx) {
- // only at initialization time, where index >= 0
- HDC hdc = NewtScreen_createDisplayDC(deviceName);
- widthmm = GetDeviceCaps(hdc, HORZSIZE);
- heightmm = GetDeviceCaps(hdc, VERTSIZE);
- DeleteDC(hdc);
devModeID = (int) mode_idx;
- prop_num++; // add 1st extra prop, mode_idx
} else {
- widthmm = 0;
- heightmm = 0;
devModeID = ENUM_CURRENT_SETTINGS;
}
@@ -1208,11 +1767,18 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScre
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
- if (0 == EnumDisplaySettingsEx(deviceName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE)) {
- DBG_PRINT("*** WindowsWindow: getScreenMode.EnumDisplaySettingsEx(mode_idx %d/%d) -> NULL\n", mode_idx, devModeID);
+ int res = EnumDisplaySettingsEx(adapterName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE);
+ DBG_PRINT("*** WindowsWindow: getMonitorMode.EnumDisplaySettingsEx(%s, mode_idx %d/%d) -> %d\n", adapterName, mode_idx, devModeID, res);
+#ifdef UNICODE
+ free((void*) adapterName);
+#else
+ (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+
+ if (0 == res) {
return (*env)->NewIntArray(env, 0);
}
-
+
// swap width and height, since Windows reflects rotated dimension, we don't
if (DMDO_90 == dm.dmDisplayOrientation || DMDO_270 == dm.dmDisplayOrientation) {
int tempWidth = dm.dmPelsWidth;
@@ -1220,43 +1786,114 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScre
dm.dmPelsHeight = tempWidth;
}
- jint prop[ prop_num ];
+ int flags = 0;
+ if( 0 != ( dm.dmDisplayFlags & DM_INTERLACED ) ) {
+ flags |= FLAG_INTERLACE;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
int propIndex = 0;
- if( -1 < mode_idx ) {
- prop[propIndex++] = mode_idx;
- }
- prop[propIndex++] = 0; // set later for verification of iterator
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
prop[propIndex++] = dm.dmPelsWidth;
prop[propIndex++] = dm.dmPelsHeight;
prop[propIndex++] = dm.dmBitsPerPel;
- prop[propIndex++] = widthmm;
- prop[propIndex++] = heightmm;
- prop[propIndex++] = dm.dmDisplayFrequency;
+ prop[propIndex++] = dm.dmDisplayFrequency * 100; // Hz*100
+ prop[propIndex++] = flags;
+ prop[propIndex++] = 0; // not bound to id
prop[propIndex++] = NewtScreen_RotationNativeCCW2NewtCCW(env, dm.dmDisplayOrientation);
- prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL
- jintArray properties = (*env)->NewIntArray(env, prop_num);
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num);
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
}
- (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop);
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
return properties;
}
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: setScreenMode0
- * Signature: (IIIIII)Z
+ * Method: getMonitorDevice0
+ * Signature: (Ljava/lang/String;I)[I
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScreenMode0
- (JNIEnv *env, jobject object, jint scrn_idx, jint width, jint height, jint bits, jint rate, jint rot)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getMonitorDevice0
+ (JNIEnv *env, jobject obj, jstring jAdapterName, jint monitor_idx)
{
DISPLAY_DEVICE device;
- LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx);
- if(NULL == deviceName) {
- DBG_PRINT("*** WindowsWindow: setScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx);
+ LPCTSTR adapterName;
+ {
+#ifdef UNICODE
+ adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+#else
+ adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+#endif
+ }
+
+ HDC hdc = NewtScreen_createDisplayDC(adapterName);
+ int widthmm = GetDeviceCaps(hdc, HORZSIZE);
+ int heightmm = GetDeviceCaps(hdc, VERTSIZE);
+ DeleteDC(hdc);
+ int devModeID = ENUM_CURRENT_SETTINGS;
+
+ DEVMODE dm;
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ int res = EnumDisplaySettingsEx(adapterName, devModeID, &dm, 0);
+ DBG_PRINT("*** WindowsWindow: getMonitorDevice.EnumDisplaySettingsEx(%s, devModeID %d) -> %d\n", adapterName, devModeID, res);
+#ifdef UNICODE
+ free((void*) adapterName);
+#else
+ (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+ if (0 == res) {
+ return (*env)->NewIntArray(env, 0);
+ }
+
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES;
+ jint prop[ propCount ];
+ int propIndex = 0;
+
+ prop[propIndex++] = propCount;
+ prop[propIndex++] = monitor_idx;
+ prop[propIndex++] = widthmm;
+ prop[propIndex++] = heightmm;
+ prop[propIndex++] = dm.dmPosition.x; // rotated viewport pixel units
+ prop[propIndex++] = dm.dmPosition.y; // rotated viewport pixel units
+ prop[propIndex++] = dm.dmPelsWidth; // rotated viewport pixel units
+ prop[propIndex++] = dm.dmPelsHeight; // rotated viewport pixel units
+ prop[propIndex++] = dm.dmPosition.x; // rotated viewport window units (same)
+ prop[propIndex++] = dm.dmPosition.y; // rotated viewport window units (same)
+ prop[propIndex++] = dm.dmPelsWidth; // rotated viewport window units (same)
+ prop[propIndex++] = dm.dmPelsHeight; // rotated viewport window units (same)
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: setMonitorMode0
+ * Signature: (IIIIIIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setMonitorMode0
+ (JNIEnv *env, jobject object, jint monitor_idx, jint x, jint y, jint width, jint height, jint bits, jint rate, jint flags, jint rot)
+{
+ DISPLAY_DEVICE adapterDevice, monitorDevice;
+ LPCTSTR adapterName = NewtScreen_getAdapterName(&adapterDevice, monitor_idx);
+ if(NULL == adapterName) {
+ DBG_PRINT("*** WindowsWindow: setMonitorMode.getAdapterName(monitor_idx %d) -> NULL\n", monitor_idx);
+ return JNI_FALSE;
+ }
+ LPCTSTR monitorName = NewtScreen_getMonitorName(adapterName, &monitorDevice, 0, TRUE);
+ if(NULL == monitorName) {
+ DBG_PRINT("*** WindowsWindow: setMonitorMode.getMonitorName(monitor_idx 0) -> NULL\n");
return JNI_FALSE;
}
@@ -1264,10 +1901,17 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree
// initialize the DEVMODE structure
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
+ if( 0 <= x && 0 <= y ) {
+ dm.dmPosition.x = (int)x;
+ dm.dmPosition.y = (int)y;
+ }
dm.dmPelsWidth = (int)width;
dm.dmPelsHeight = (int)height;
dm.dmBitsPerPel = (int)bits;
dm.dmDisplayFrequency = (int)rate;
+ if( 0 != ( flags & FLAG_INTERLACE ) ) {
+ dm.dmDisplayFlags |= DM_INTERLACED;
+ }
dm.dmDisplayOrientation = NewtScreen_RotationNewtCCW2NativeCCW(env, rot);
// swap width and height, since Windows reflects rotated dimension, we don't
@@ -1277,9 +1921,12 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree
dm.dmPelsHeight = tempWidth;
}
- dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+ dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
+ if( 0 <= x && 0 <= y ) {
+ dm.dmFields |= DM_POSITION;
+ }
- return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, 0) ) ? JNI_TRUE : JNI_FALSE ;
+ return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(adapterName, &dm, NULL, 0, NULL) ) ? JNI_TRUE : JNI_FALSE ;
}
/*
@@ -1288,7 +1935,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
- (JNIEnv *env, jclass clazz)
+ (JNIEnv *env, jclass clazz, jlong hInstance)
{
NewtCommon_init(env);
@@ -1299,10 +1946,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
- enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+ sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V");
+ sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SII[I[I[I[FF)V");
+ sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V");
requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
if (insetsChangedID == NULL ||
@@ -1312,14 +1958,30 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
visibleChangedID == NULL ||
windowDestroyNotifyID == NULL ||
windowRepaintID == NULL ||
- enqueueMouseEventID == NULL ||
sendMouseEventID == NULL ||
- enqueueKeyEventID == NULL ||
+ sendTouchScreenEventID == NULL ||
sendKeyEventID == NULL ||
requestFocusID == NULL) {
return JNI_FALSE;
}
- BuildDynamicKeyMapTable();
+ InitKeyMapTableScanCode(env);
+
+ {
+ HANDLE shell = LoadLibrary(TEXT("user32.dll"));
+ if (shell) {
+ WinTouch_CloseTouchInputHandle = (CloseTouchInputHandlePROCADDR) GetProcAddressA(shell, "CloseTouchInputHandle");
+ WinTouch_GetTouchInputInfo = (GetTouchInputInfoPROCADDR) GetProcAddressA(shell, "GetTouchInputInfo");
+ WinTouch_IsTouchWindow = (IsTouchWindowPROCADDR) GetProcAddressA(shell, "IsTouchWindow");
+ WinTouch_RegisterTouchWindow = (RegisterTouchWindowPROCADDR) GetProcAddressA(shell, "RegisterTouchWindow");
+ WinTouch_UnregisterTouchWindow = (UnregisterTouchWindowPROCADDR) GetProcAddressA(shell, "UnregisterTouchWindow");
+ if(NULL != WinTouch_CloseTouchInputHandle && NULL != WinTouch_GetTouchInputInfo &&
+ NULL != WinTouch_IsTouchWindow && NULL != WinTouch_RegisterTouchWindow && NULL != WinTouch_UnregisterTouchWindow) {
+ WinTouch_func_avail = 1;
+ } else {
+ WinTouch_func_avail = 0;
+ }
+ }
+ }
return JNI_TRUE;
}
@@ -1365,20 +2027,21 @@ static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible,
UpdateWindow(hwnd);
}
+#define WS_DEFAULT_STYLES (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP)
+
/*
* Class: jogamp_newt_driver_windows_WindowDriver
* Method: CreateWindow
*/
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindow0
(JNIEnv *env, jobject obj,
- jlong hInstance, jstring jWndClassName, jstring jWndName,
- jlong parent,
- jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags)
+ jlong hInstance, jstring jWndClassName, jstring jWndName, jint winMajor, jint winMinor,
+ jlong parent, jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags)
{
HWND parentWindow = (HWND) (intptr_t) parent;
const TCHAR* wndClassName = NULL;
const TCHAR* wndName = NULL;
- DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_TABSTOP;
+ DWORD windowStyle = WS_DEFAULT_STYLES | WS_VISIBLE;
int x=(int)jx, y=(int)jy;
int width=(int)defaultWidth, height=(int)defaultHeight;
HWND window = NULL;
@@ -1415,8 +2078,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
(HINSTANCE) (intptr_t) hInstance,
NULL);
- DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n",
- (int)GetCurrentThreadId(), parentWindow, window, x, y, width, height,
+ DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, win %d.%d parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n",
+ (int)GetCurrentThreadId(), winMajor, winMinor, parentWindow, window, x, y, width, height,
TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition);
if (NULL == window) {
@@ -1427,6 +2090,31 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
WindowUserData * wud = (WindowUserData *) malloc(sizeof(WindowUserData));
wud->jinstance = (*env)->NewGlobalRef(env, obj);
wud->jenv = env;
+ wud->width = width;
+ wud->height = height;
+ wud->setPointerVisible = 0;
+ wud->setPointerAction = 0;
+ wud->defPointerHandle = LoadCursor( NULL, IDC_ARROW);
+ wud->setPointerHandle = wud->defPointerHandle;
+ wud->isFullscreen = 0;
+ wud->isChildWindow = NULL!=parentWindow;
+ wud->pointerCaptured = 0;
+ wud->pointerInside = 0;
+ wud->touchDownCount = 0;
+ wud->touchDownLastUp = 0;
+ wud->supportsMTouch = 0;
+ if ( WinTouch_func_avail && winMajor > 6 || ( winMajor == 6 && winMinor >= 1 ) ) {
+ int value = GetSystemMetrics(SM_DIGITIZER);
+ if (value & NID_READY) { /* ready */
+ if (value & NID_MULTI_INPUT) { /* multitouch */
+ wud->supportsMTouch = 1;
+ }
+ if (value & NID_INTEGRATED_TOUCH) { /* Integrated touch */
+ }
+ }
+ }
+ DBG_PRINT("*** WindowsWindow: CreateWindow winTouchFuncAvail %d, supportsMTouch %d\n", WinTouch_func_avail, wud->supportsMTouch);
+
#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
SetWindowLong(window, GWL_USERDATA, (intptr_t) wud);
#else
@@ -1459,6 +2147,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
NewtWindow_setVisiblePosSize(window, TST_FLAG_IS_ALWAYSONTOP(flags), TRUE, x, y, width, height);
}
+ if( wud->supportsMTouch ) {
+ WinTouch_RegisterTouchWindow(window, 0);
+ }
}
#ifdef UNICODE
@@ -1469,6 +2160,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
(*env)->ReleaseStringUTFChars(env, jWndName, wndName);
#endif
+#ifdef TEST_MOUSE_HOOKS
+ hookLLMP = SetWindowsHookEx(WH_MOUSE_LL, &HookLowLevelMouseProc, (HINSTANCE) (intptr_t) hInstance, 0);
+ hookMP = SetWindowsHookEx(WH_MOUSE_LL, &HookMouseProc, (HINSTANCE) (intptr_t) hInstance, 0);
+ DBG_PRINT("**** LLMP Hook %p, MP Hook %p\n", hookLLMP, hookMP);
+#endif
+
return (jlong) (intptr_t) window;
}
@@ -1487,24 +2184,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_MonitorFrom
#endif
}
-static jboolean NewtWindows_setFullScreen(jboolean fullscreen)
-{
- int flags = 0;
- DEVMODE dm;
- // initialize the DEVMODE structure
- ZeroMemory(&dm, sizeof(dm));
- dm.dmSize = sizeof(dm);
-
- if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
- {
- return JNI_FALSE;
- }
-
- flags = ( JNI_TRUE == fullscreen ) ? CDS_FULLSCREEN : CDS_RESET ;
-
- return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE;
-}
-
/*
* Class: jogamp_newt_driver_windows_WindowDriver
* Method: reconfigureWindow0
@@ -1516,16 +2195,23 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
{
HWND hwndP = (HWND) (intptr_t) parent;
HWND hwnd = (HWND) (intptr_t) window;
- DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
+ DWORD windowStyle = WS_DEFAULT_STYLES;
BOOL styleChange = TST_FLAG_CHANGE_DECORATION(flags) || TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ;
+ WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
- DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d\n",
+
+ DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d, isChild %d, isFullscreen %d\n",
parent, window, x, y, width, height,
TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags),
TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags),
TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags),
TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags),
- TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), styleChange);
+ TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), styleChange, wud->isChildWindow, wud->isFullscreen);
if (!IsWindow(hwnd)) {
DBG_PRINT("*** WindowsWindow: reconfigureWindow0 failure: Passed window %p is invalid\n", (void*)hwnd);
@@ -1537,6 +2223,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
return;
}
+ wud->isChildWindow = NULL != hwndP;
+
if(TST_FLAG_IS_VISIBLE(flags)) {
windowStyle |= WS_VISIBLE ;
}
@@ -1547,11 +2235,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
//
if( TST_FLAG_CHANGE_PARENTING(flags) && NULL == hwndP ) {
// TOP: in -> out
+
+ // HIDE to allow setting ICONs (Windows bug?) .. WS_VISIBLE (style) will reset visibility
+ ShowWindow(hwnd, SW_HIDE);
+
SetParent(hwnd, NULL);
}
if( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) { // FS on
// TOP: in -> out
+ wud->isFullscreen = 1;
NewtWindows_setFullScreen(JNI_TRUE);
}
@@ -1569,6 +2262,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
if( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off
// CHILD: out -> in
+ wud->isFullscreen = 0;
NewtWindows_setFullScreen(JNI_FALSE);
}
@@ -1587,7 +2281,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
}
}
- DBG_PRINT("*** WindowsWindow: reconfigureWindow0.X\n");
+ DBG_PRINT("*** WindowsWindow: reconfigureWindow0.X isChild %d, isFullscreen %d\n", wud->isChildWindow, wud->isFullscreen);
}
/*
@@ -1629,34 +2323,16 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_setPoint
(JNIEnv *env, jclass clazz, jlong window, jboolean mouseVisible)
{
HWND hwnd = (HWND) (intptr_t) window;
- int res, resOld, i;
- jboolean b;
-
- if(JNI_TRUE == mouseVisible) {
- res = ShowCursor(TRUE);
- if(res < 0) {
- i=0;
- do {
- resOld = res;
- res = ShowCursor(TRUE);
- } while(res!=resOld && res<0 && ++i<10);
- }
- b = res>=0 ? JNI_TRUE : JNI_FALSE;
- } else {
- res = ShowCursor(FALSE);
- if(res >= 0) {
- i=0;
- do {
- resOld = res;
- res = ShowCursor(FALSE);
- } while(res!=resOld && res>=0 && ++i<10);
- }
- b = res<0 ? JNI_TRUE : JNI_FALSE;
- }
-
- DBG_PRINT( "*** WindowsWindow: setPointerVisible0: %d, res %d/%d\n", mouseVisible, res, b);
+ WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
+ wud->setPointerVisible = mouseVisible ? 1 : -1;
+ SendMessage(hwnd, WM_SETCURSOR, 0, 0);
- return b;
+ return JNI_TRUE;
}
/*
@@ -1671,12 +2347,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_confineP
jboolean res;
if(JNI_TRUE == confine) {
- // SetCapture(hwnd);
- // res = ( GetCapture() == hwnd ) ? JNI_TRUE : JNI_FALSE;
RECT rect = { l, t, r, b };
res = ClipCursor(&rect) ? JNI_TRUE : JNI_FALSE;
} else {
- // res = ReleaseCapture() ? JNI_TRUE : JNI_FALSE;
res = ClipCursor(NULL) ? JNI_TRUE : JNI_FALSE;
}
DBG_PRINT( "*** WindowsWindow: confinePointer0: %d, [ l %d t %d r %d b %d ], res %d\n",
@@ -1697,16 +2370,93 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_warpPointer0
SetCursorPos(x, y);
}
-/*
- * Class: Java_jogamp_newt_driver_windows_WindowDriver
- * Method: trackPointerLeave0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_trackPointerLeave0
- (JNIEnv *env, jclass clazz, jlong window)
-{
+JNIEXPORT jlong JNICALL
+Java_jogamp_newt_driver_windows_DisplayDriver_createBGRA8888Icon0(JNIEnv *env, jobject _unused,
+ jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jboolean isCursor, jint hotX, jint hotY) {
+
+ if( 0 == pixels ) {
+ return 0;
+ }
+
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ const int bytes = 4 * width * height; // BGRA8888
+
+ DWORD dwWidth, dwHeight;
+ BITMAPV5HEADER bi;
+ HBITMAP hBitmap;
+ void *lpBits;
+ HICON handle = NULL;
+
+ dwWidth = width; // width of cursor
+ dwHeight = height; // height of cursor
+
+ ZeroMemory(&bi,sizeof(BITMAPV5HEADER));
+ bi.bV5Size = sizeof(BITMAPV5HEADER);
+ bi.bV5Width = dwWidth;
+ bi.bV5Height = -1 * dwHeight;
+ bi.bV5Planes = 1;
+ bi.bV5BitCount = 32;
+ bi.bV5Compression = BI_BITFIELDS;
+ // The following mask specification specifies a supported 32 BPP
+ // alpha format for Windows XP.
+ bi.bV5RedMask = 0x00FF0000;
+ bi.bV5GreenMask = 0x0000FF00;
+ bi.bV5BlueMask = 0x000000FF;
+ bi.bV5AlphaMask = 0xFF000000;
+
+ HDC hdc;
+ hdc = GetDC(NULL);
+
+ // Create the DIB section with an alpha channel.
+ hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
+ (void **)&lpBits, NULL, (DWORD)0);
+
+ memcpy(lpBits, pixelPtr + pixels_byte_offset, bytes);
+
+ ReleaseDC(NULL,hdc);
+
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
+ // Create an empty mask bitmap.
+ HBITMAP hMonoBitmap = CreateBitmap(dwWidth,dwHeight,1,1,NULL);
+
+ ICONINFO ii;
+ ii.fIcon = isCursor ? FALSE : TRUE;
+ ii.xHotspot = hotX;
+ ii.yHotspot = hotY;
+ ii.hbmMask = hMonoBitmap;
+ ii.hbmColor = hBitmap;
+
+ // Create the alpha cursor with the alpha DIB section.
+ handle = CreateIconIndirect(&ii);
+
+ DeleteObject(hBitmap);
+ DeleteObject(hMonoBitmap);
+
+ return (jlong) (intptr_t) handle;
+}
+
+JNIEXPORT void JNICALL
+Java_jogamp_newt_driver_windows_DisplayDriver_destroyIcon0(JNIEnv *env, jobject _unused, jlong jhandle) {
+ HICON handle = (HICON) (intptr_t) jhandle;
+ DestroyIcon(handle);
+}
+
+JNIEXPORT void JNICALL
+Java_jogamp_newt_driver_windows_WindowDriver_setPointerIcon0(JNIEnv *env, jobject _unused, jlong window, jlong iconHandle) {
HWND hwnd = (HWND) (intptr_t) window;
- DBG_PRINT( "*** WindowsWindow: trackMouseLeave0\n");
- NewtWindows_trackPointerLeave(hwnd);
+ WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
+ wud->setPointerAction = 0 != iconHandle ? 1 : -1;
+ wud->setPointerHandle = (HCURSOR) (intptr_t) iconHandle;
+ SendMessage(hwnd, WM_SETCURSOR, 0, 0);
}
diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h
index 128b6b6f1..e58cdb755 100644
--- a/src/newt/native/X11Common.h
+++ b/src/newt/native/X11Common.h
@@ -45,8 +45,10 @@
#include <X11/extensions/Xrandr.h>
-#include "jogamp_newt_driver_x11_ScreenDriver.h"
#include "jogamp_newt_driver_x11_DisplayDriver.h"
+#include "jogamp_newt_driver_x11_ScreenDriver.h"
+#include "jogamp_newt_driver_x11_RandR11.h"
+#include "jogamp_newt_driver_x11_RandR13.h"
#include "jogamp_newt_driver_x11_WindowDriver.h"
#include "Window.h"
@@ -70,7 +72,6 @@ extern jclass X11NewtWindowClazz;
extern jmethodID insetsChangedID;
extern jmethodID visibleChangedID;
-void NewtDisplay_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync);
jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning);
Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return);
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 84b3a7630..b62a9b234 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -28,7 +28,9 @@
#include "X11Common.h"
-#define USE_SENDIO_DIRECT 1
+#include <X11/Xcursor/Xcursor.h>
+
+// #include <X11/XKBlib.h> // XKB disabled for now
jclass X11NewtWindowClazz = NULL;
jmethodID insetsChangedID = NULL;
@@ -46,107 +48,35 @@ static jmethodID focusChangedID = NULL;
static jmethodID reparentNotifyID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
-static jmethodID enqueueMouseEventID = NULL;
static jmethodID sendMouseEventID = NULL;
-static jmethodID enqueueKeyEventID = NULL;
static jmethodID sendKeyEventID = NULL;
static jmethodID requestFocusID = NULL;
-static JavaVM *jvmHandle = NULL;
-static int jvmVersion = 0;
-
-static void setupJVMVars(JNIEnv * env) {
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- }
- jvmVersion = (*env)->GetVersion(env);
-}
-
-static XErrorHandler origErrorHandler = NULL ;
-static int errorHandlerQuiet = 0 ;
-static int errorHandlerDebug = 0 ;
-static int errorHandlerThrowException = 0;
-
-static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
-{
- if(!errorHandlerQuiet) {
- const char * errnoStr = strerror(errno);
- char threadName[80];
- char errCodeStr[80];
- char reqCodeStr[80];
-
- int shallBeDetached = 0;
- JNIEnv *jniEnv = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
-
- (void) NewtCommon_GetStaticStringMethod(jniEnv, X11NewtWindowClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
- snprintf(errCodeStr, sizeof(errCodeStr), "%d", e->request_code);
- XGetErrorDatabaseText(dpy, "XRequest", errCodeStr, "Unknown", reqCodeStr, sizeof(reqCodeStr));
- XGetErrorText(dpy, e->error_code, errCodeStr, sizeof(errCodeStr));
-
- fprintf(stderr, "Info: Newt X11 Error (Thread: %s): %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
- threadName, e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
- (int)e->request_code, (int)e->minor_code, reqCodeStr);
-
- if( errorHandlerDebug ) {
- (*jniEnv)->CallStaticVoidMethod(jniEnv, X11NewtWindowClazz, dumpStackID);
- }
-
- if(errorHandlerThrowException) {
- if(NULL != jniEnv) {
- NewtCommon_throwNewRuntimeException(jniEnv, "Newt X11 Error (Thread: %s): %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
- threadName, e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
- (int)e->request_code, (int)e->minor_code, reqCodeStr);
- } else {
- fprintf(stderr, "Nativewindow X11 Error: null JNIEnv");
- #if 0
- if(NULL!=origErrorHandler) {
- origErrorHandler(dpy, e);
- }
- #endif
- }
- }
- fflush(stderr);
-
- if (NULL != jniEnv && shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
- }
-
- return 0;
-}
-
-void NewtDisplay_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync) {
- errorHandlerQuiet = quiet;
- if(onoff) {
- if(NULL==origErrorHandler) {
- setupJVMVars(env);
- origErrorHandler = XSetErrorHandler(x11ErrorHandler);
- if(sync && NULL!=dpy) {
- XSync(dpy, False);
- }
- }
- } else {
- if(NULL!=origErrorHandler) {
- if(sync && NULL!=dpy) {
- XSync(dpy, False);
- }
- XSetErrorHandler(origErrorHandler);
- origErrorHandler = NULL;
- }
- }
-}
-
/**
* Keycode
*/
+// #define DEBUG_KEYS 1
+
#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b))
-static jint X11KeySym2NewtVKey(KeySym keySym) {
- if(IS_WITHIN(keySym,XK_F1,XK_F12))
- return (keySym-XK_F1)+J_VK_F1;
- if(IS_WITHIN(keySym,XK_KP_0,XK_KP_9))
- return (keySym-XK_KP_0)+J_VK_NUMPAD0;
+/**
+ * QT Reference:
+ * <http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/kernel/qkeymapper_x11.cpp#line879>
+ */
+static short X11KeySym2NewtVKey(KeySym keySym) {
+ if( IS_WITHIN( keySym, XK_a, XK_z ) ) {
+ return ( keySym - XK_a ) + J_VK_A ;
+ }
+ if( IS_WITHIN( keySym, XK_0, XK_9 ) ) {
+ return ( keySym - XK_0 ) + J_VK_0 ;
+ }
+ if( IS_WITHIN( keySym, XK_KP_0, XK_KP_9 ) ) {
+ return ( keySym - XK_KP_0 ) + J_VK_NUMPAD0 ;
+ }
+ if( IS_WITHIN( keySym, XK_F1, XK_F12 ) ) {
+ return ( keySym - XK_F1 ) + J_VK_F1 ;
+ }
switch(keySym) {
case XK_Return:
@@ -160,8 +90,6 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
return J_VK_TAB;
case XK_Cancel:
return J_VK_CANCEL;
- case XK_Clear:
- return J_VK_CLEAR;
case XK_Shift_L:
case XK_Shift_R:
return J_VK_SHIFT;
@@ -169,8 +97,15 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
case XK_Control_R:
return J_VK_CONTROL;
case XK_Alt_L:
- case XK_Alt_R:
return J_VK_ALT;
+ case XK_Alt_R:
+ case XK_ISO_Level3_Shift:
+ return J_VK_ALT_GRAPH;
+ case XK_Super_L:
+ case XK_Super_R:
+ return J_VK_WINDOWS;
+ case XK_Menu:
+ return J_VK_CONTEXT_MENU;
case XK_Pause:
return J_VK_PAUSE;
case XK_Caps_Lock:
@@ -189,6 +124,10 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
case XK_End:
case XK_KP_End:
return J_VK_END;
+ case XK_Begin:
+ return J_VK_BEGIN;
+ case XK_KP_Begin: // NumPad 5 - equal behavior w/ QT/Windows
+ return J_VK_CLEAR;
case XK_Home:
case XK_KP_Home:
return J_VK_HOME;
@@ -216,6 +155,7 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
return J_VK_DECIMAL;
case XK_KP_Divide:
return J_VK_DIVIDE;
+ case XK_Clear: // equal behavior w/ QT
case XK_Delete:
case XK_KP_Delete:
return J_VK_DELETE;
@@ -230,28 +170,43 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
return J_VK_INSERT;
case XK_Help:
return J_VK_HELP;
+ case XK_grave:
+ return J_VK_BACK_QUOTE;
+ case XK_apostrophe:
+ return J_VK_QUOTE;
}
return keySym;
}
-static jint X11InputState2NewtModifiers(unsigned int xstate) {
+#define ShiftCtrlModMask ( ShiftMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask )
+
+static jboolean altGraphDown = JNI_FALSE;
+
+static jint X11InputState2NewtModifiers(unsigned int xstate, jshort javaVKey, jboolean keyDown) {
jint modifiers = 0;
- if ((ControlMask & xstate) != 0) {
+ if ( (ControlMask & xstate) != 0 || J_VK_CONTROL == javaVKey ) {
modifiers |= EVENT_CTRL_MASK;
}
- if ((ShiftMask & xstate) != 0) {
+ if ( (ShiftMask & xstate) != 0 || J_VK_SHIFT == javaVKey ) {
modifiers |= EVENT_SHIFT_MASK;
}
- if ((Mod1Mask & xstate) != 0) {
+ if ( J_VK_ALT == javaVKey ) {
+ altGraphDown = JNI_FALSE;
modifiers |= EVENT_ALT_MASK;
+ } else if ( (short)J_VK_ALT_GRAPH == javaVKey ) {
+ altGraphDown = keyDown;
+ modifiers |= EVENT_ALT_GRAPH_MASK;
+ } else if ( (Mod1Mask & xstate) != 0 ) {
+ // XK_Alt_L or XK_Alt_R
+ modifiers |= altGraphDown ? EVENT_ALT_GRAPH_MASK : EVENT_ALT_MASK;
}
- if ((Button1Mask & xstate) != 0) {
+ if ( (Button1Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON1_MASK;
}
- if ((Button2Mask & xstate) != 0) {
+ if ( (Button2Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON2_MASK;
}
- if ((Button3Mask & xstate) != 0) {
+ if ( (Button3Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON3_MASK;
}
@@ -273,9 +228,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
{
jclass c;
- if(debug) {
- errorHandlerDebug = 1 ;
- }
NewtCommon_init(env);
if(NULL==X11NewtWindowClazz) {
@@ -290,6 +242,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
}
}
+ // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJ)V"); // Variant using XKB
displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;");
dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V");
@@ -301,10 +254,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z");
windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V");
- enqueueMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueMouseEvent", "(ZIIIIII)V");
- sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(IIIIII)V");
- enqueueKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueKeyEvent", "(ZIIIC)V");
- sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(IIIC)V");
+ sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V");
+ sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V");
requestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "requestFocus", "(Z)V");
if (displayCompletedID == NULL ||
@@ -318,9 +269,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
reparentNotifyID == NULL ||
windowDestroyNotifyID == NULL ||
windowRepaintID == NULL ||
- enqueueMouseEventID == NULL ||
sendMouseEventID == NULL ||
- enqueueKeyEventID == NULL ||
sendKeyEventID == NULL ||
requestFocusID == NULL) {
return JNI_FALSE;
@@ -341,6 +290,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
Display * dpy = (Display *)(intptr_t)display;
jlong javaObjectAtom;
jlong windowDeleteAtom;
+ // jlong kbdHandle; // XKB disabled for now
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
@@ -359,10 +309,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
}
// XSetCloseDownMode(dpy, RetainTemporary); // Just a try ..
+ // kbdHandle = (jlong) (intptr_t) XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd); // XKB disabled for now
DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy);
- (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom);
+ (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom /*, kbdHandle*/); // XKB disabled for now
}
/*
@@ -371,11 +322,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
* Signature: (JJJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
- (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom)
+ (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/)
{
Display * dpy = (Display *)(intptr_t)display;
Atom wm_javaobject_atom = (Atom)javaObjectAtom;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ // XkbDescPtr kbdDesc = (XkbDescPtr)(intptr_t)kbdHandle; // XKB disabled for now
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
@@ -385,6 +337,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
(void) wm_javaobject_atom;
(void) wm_delete_atom;
+ // XkbFreeKeyboard(kbdDesc, XkbAllNamesMask, True); // XKB disabled for now
+
XSync(dpy, True); // discard all pending events
DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy);
}
@@ -392,13 +346,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
/*
* Class: jogamp_newt_driver_x11_DisplayDriver
* Method: DispatchMessages
- * Signature: (JIJJ)V
+ * Signature: (JJJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0
- (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom)
+ (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/)
{
Display * dpy = (Display *) (intptr_t) display;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ // XkbDescPtr kbdDesc = (XkbDescPtr)(intptr_t)kbdHandle; // XKB disabled for now
int num_events = 100;
int autoRepeatModifiers = 0;
@@ -406,20 +361,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
return;
}
+ /** XKB disabled for now
+ if( NULL == kbdDesc) {
+ NewtCommon_throwNewRuntimeException(env, "NULL kbd handle, bail out!");
+ return;
+ } */
+
// Periodically take a break
while( num_events > 0 ) {
jobject jwindow = NULL;
XEvent evt;
KeySym keySym = 0;
+ KeyCode keyCode = 0;
+ jshort javaVKeyUS = 0;
+ jshort javaVKeyNN = 0;
jint modifiers = 0;
- char keyChar = 0;
+ uint16_t keyChar = 0;
+ jstring keyString = NULL;
char text[255];
// XEventsQueued(dpy, X):
- // QueuedAlready : No I/O Flush or system call doesn't work on some cards (eg ATI) ?)
+ // QueuedAlready == XQLength(): No I/O Flush or system call doesn't work on some cards (eg ATI) ?)
// QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available
// QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more ..
- if ( 0 >= XPending(dpy) ) {
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
// DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
return;
}
@@ -427,19 +392,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
XNextEvent(dpy, &evt);
num_events--;
- if( 0==evt.xany.window ) {
- NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!");
- return ;
- }
-
if(dpy!=evt.xany.display) {
NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
return ;
}
- // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
+ if( 0==evt.xany.window ) {
+ DBG_PRINT( "X11: DispatchMessages dpy %p, Event %d - Window NULL, ignoring\n", (void*)dpy, (int)evt.type);
+ continue;
+ }
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
#ifdef VERBOSE_ON
@@ -449,11 +412,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
#endif
);
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
-
if(NULL==jwindow) {
- fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
- (void*)dpy, evt.type, (void*)evt.xany.window);
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window);
continue;
}
@@ -470,26 +430,73 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
} else {
autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
}
+ } else {
+ autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
}
// fall through intended
- case KeyPress:
- if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
- KeySym lower_return = 0, upper_return = 0;
- keyChar=text[0];
- XConvertCase(keySym, &lower_return, &upper_return);
- // always return upper case, set modifier masks (SHIFT, ..)
- keySym = X11KeySym2NewtVKey(upper_return);
- } else {
- keyChar=0;
- keySym = X11KeySym2NewtVKey(keySym);
+ case KeyPress: {
+ KeySym shiftedKeySym; // layout depending keySym w/ SHIFT
+ KeySym unShiftedKeySym; // layout depending keySym w/o SHIFT
+ unsigned int xkey_state = evt.xkey.state;
+
+ keyCode = evt.xkey.keycode;
+
+ // Layout depending keySym w/o SHIFT,
+ // using fixed group 0 (US default layout)
+ //
+ // unsigned int mods_rtrn = 0;
+ // Bool res = XkbTranslateKeyCode (kbdDesc, keyCode, 0, &mods_rtrn, &keySym); // XKB disabled for now
+ // if( !res ) {
+ keySym = XkbKeycodeToKeysym(dpy, keyCode, 0 /* group */, 0 /* shift level */);
+ // }
+
+ text[0] = 0; text[1] = 0; text[2] = 0;
+ int charCount = XLookupString(&evt.xkey, text, 2, &shiftedKeySym, NULL);
+ if( 1 == charCount ) {
+ keyChar = 0x00FF & (uint16_t) (text[0]);
+ } else if( 2 == charCount ) {
+ // Example: UTF-16: 00DF, UTF-8: c3 9f, LATIN SMALL LETTER SHARP S
+ keyChar = ( 0x00FF & (uint16_t)(text[0]) ) << 8 | ( 0x00FF & (uint16_t)(text[1]) ); // UTF-16BE
+ keyString = (*env)->NewStringUTF(env, text);
+ }
+
+ #ifdef DEBUG_KEYS
+ fprintf(stderr, "NEWT X11 Key.0: keyCode 0x%X keySym 0x%X, (shifted: 0x%X)\n",
+ (int)keyCode, (int)keySym, (int) shiftedKeySym);
+ #endif
+ if( IS_WITHIN( shiftedKeySym, XK_KP_Space, XK_KP_9 ) ) {
+ // Use modded keySym for keypad for US and NN
+ keySym = shiftedKeySym;
+ unShiftedKeySym = shiftedKeySym;
+ } else if( 0 == keyChar ) {
+ // Use keyCode's keySym for dead-key (aka modifiers, etc)
+ unShiftedKeySym = keySym;
+ } else if( 0 == ( evt.xkey.state & ShiftCtrlModMask ) ) {
+ // Use non modded keySym
+ unShiftedKeySym = shiftedKeySym;
+ } else {
+ evt.xkey.state = evt.xkey.state & ~ShiftCtrlModMask; // clear shift, ctrl and Mod*
+ XLookupString(&evt.xkey, text, 0, &unShiftedKeySym, NULL);
+ // unShiftedKeySym = XLookupKeysym(&evt.xkey, 0 /* index ? */);
+ }
+
+ javaVKeyNN = X11KeySym2NewtVKey(unShiftedKeySym);
+ javaVKeyUS = X11KeySym2NewtVKey(keySym);
+ modifiers |= X11InputState2NewtModifiers(xkey_state, javaVKeyNN, evt.type == KeyPress) | autoRepeatModifiers;
+
+ #ifdef DEBUG_KEYS
+ fprintf(stderr, "NEWT X11 Key.X: keyCode 0x%X keySym 0x%X, (0x%X, shifted: 0x%X), keyChar '%c' 0x%X %d, javaVKey[US 0x%X, NN 0x%X], xstate 0x%X %u, jmods 0x%X\n",
+ (int)keyCode, (int)keySym, (int) unShiftedKeySym, (int)shiftedKeySym, keyChar, keyChar, charCount,
+ (int)javaVKeyUS, (int)javaVKeyNN,
+ (int)xkey_state, (int)xkey_state, (int)modifiers);
+ #endif
}
- modifiers |= X11InputState2NewtModifiers(evt.xkey.state) | autoRepeatModifiers;
break;
case ButtonPress:
case ButtonRelease:
case MotionNotify:
- modifiers |= X11InputState2NewtModifiers(evt.xbutton.state);
+ modifiers |= X11InputState2NewtModifiers(evt.xbutton.state, 0, JNI_FALSE);
break;
default:
@@ -499,87 +506,43 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
switch(evt.type) {
case ButtonPress:
(*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED,
modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
- modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #endif
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/);
break;
case ButtonRelease:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
- modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED,
modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #endif
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/);
break;
case MotionNotify:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
- modifiers,
- (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED,
modifiers,
- (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
- #endif
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jshort) 0, 0.0f /*rotation*/);
break;
case EnterNotify:
DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED,
modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED,
- modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #endif
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
break;
case LeaveNotify:
DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED,
- modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED,
modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #endif
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ break;
+ case MappingNotify:
+ DBG_PRINT( "X11: event . MappingNotify call %p type %d\n", (void*)evt.xmapping.window, evt.xmapping.type);
+ XRefreshKeyboardMapping(&evt.xmapping);
break;
case KeyPress:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
- modifiers, keySym, (jchar) -1);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
- modifiers, keySym, (jchar) -1);
- #endif
-
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED,
+ modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString);
break;
case KeyRelease:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
- modifiers, keySym, (jchar) -1);
-
- (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED,
- modifiers, keySym, (jchar) keyChar);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
- modifiers, keySym, (jchar) -1);
-
- (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED,
- modifiers, keySym, (jchar) keyChar);
- #endif
-
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED,
+ modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString);
break;
case DestroyNotify:
DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
@@ -709,4 +672,59 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
}
}
+/*
+ * Class: Java_jogamp_newt_driver_x11_DisplayDriver
+ * Method: createPointerIcon0
+ * Signature: (JJILjava/lang/Object;I)V
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
+{
+ Cursor c;
+
+ if( 0 != pixels ) {
+ Display * dpy = (Display *) (intptr_t) display;
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ XcursorImage ci;
+ ci.version = 1; // XCURSOR_IMAGE_VERSION;
+ ci.size = width; // nominal size (assume square ..)
+ ci.width = width;
+ ci.height = height;
+ ci.xhot = hotX;
+ ci.yhot = hotY;
+ ci.delay = 0;
+ ci.pixels = (XcursorPixel *)(intptr_t)(pixelPtr + pixels_byte_offset);
+
+ c = XcursorImageLoadCursor (dpy, &ci);
+
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+ DBG_PRINT( "X11: createPointerIcon0: %p %dx%d %d/%d -> %p\n", (pixelPtr+pixels_byte_offset), width, height, hotX, hotY, (void *)c);
+
+ } else {
+ c = 0;
+ }
+ return (jlong) (intptr_t) c;
+}
+
+/*
+ * Class: Java_jogamp_newt_driver_x11_DisplayDriver
+ * Method: destroyPointerIcon0
+ * Signature: (JJILjava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_destroyPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jlong handle)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+
+ if( 0 != handle ) {
+ Cursor c = (Cursor) (intptr_t) handle;
+ DBG_PRINT( "X11: destroyPointerIcon0: %p\n", (void *)c);
+ XFreeCursor(dpy, c);
+ }
+}
+
diff --git a/src/newt/native/X11Event.c b/src/newt/native/X11Event.c
new file mode 100644
index 000000000..32a55c67c
--- /dev/null
+++ b/src/newt/native/X11Event.c
@@ -0,0 +1,305 @@
+
+#include "X11Event.h"
+
+void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong windowDeleteAtom) {
+ Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ int num_events = 100;
+ int autoRepeatModifiers = 0;
+
+ if ( NULL == dpy ) {
+ return;
+ }
+
+ // Periodically take a break
+ while( num_events > 0 ) {
+ jobject jwindow = NULL;
+ XEvent evt;
+ KeySym keySym = 0;
+ jint modifiers = 0;
+ char keyChar = 0;
+ char text[255];
+
+ // XEventsQueued(dpy, X):
+ // QueuedAlready == XQLength(): No I/O Flush or system call doesn't work on some cards (eg ATI) ?)
+ // QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available
+ // QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more ..
+ // if ( 0 >= XPending(dpy) )
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) )
+ {
+ // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
+ return;
+ }
+
+ XNextEvent(dpy, &evt);
+ num_events--;
+
+ if(dpy!=evt.xany.display) {
+ NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
+ return ;
+ }
+
+ if( 0==evt.xany.window ) {
+ DBG_PRINT( "X11: DispatchMessages dpy %p, Event %d - Window NULL, ignoring\n", (void*)dpy, (int)evt.type);
+ continue;
+ }
+
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
+
+ jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
+ #ifdef VERBOSE_ON
+ True
+ #else
+ False
+ #endif
+ );
+
+ if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window);
+ continue;
+ }
+
+ switch(evt.type) {
+ case KeyRelease:
+ if (XEventsQueued(dpy, QueuedAfterReading)) {
+ XEvent nevt;
+ XPeekEvent(dpy, &nevt);
+
+ if (nevt.type == KeyPress && nevt.xkey.time == evt.xkey.time &&
+ nevt.xkey.keycode == evt.xkey.keycode)
+ {
+ autoRepeatModifiers |= EVENT_AUTOREPEAT_MASK;
+ } else {
+ autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
+ }
+ }
+ // fall through intended
+ case KeyPress:
+ if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
+ KeySym lower_return = 0, upper_return = 0;
+ keyChar=text[0];
+ XConvertCase(keySym, &lower_return, &upper_return);
+ // always return upper case, set modifier masks (SHIFT, ..)
+ keySym = X11KeySym2NewtVKey(upper_return);
+ } else {
+ keyChar=0;
+ keySym = X11KeySym2NewtVKey(keySym);
+ }
+ modifiers |= X11InputState2NewtModifiers(evt.xkey.state) | autoRepeatModifiers;
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ modifiers |= X11InputState2NewtModifiers(evt.xbutton.state);
+ break;
+
+ default:
+ break;
+ }
+
+ switch(evt.type) {
+ case ButtonPress:
+ (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #endif
+ break;
+ case ButtonRelease:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #endif
+ break;
+ case MotionNotify:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/);
+ #endif
+ break;
+ case EnterNotify:
+ DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #endif
+ break;
+ case LeaveNotify:
+ DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #endif
+ break;
+ case KeyPress:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
+ modifiers, keySym, (jchar) -1);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
+ modifiers, keySym, (jchar) -1);
+ #endif
+
+ break;
+ case KeyRelease:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
+ modifiers, keySym, (jchar) -1);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
+ modifiers, keySym, (jchar) -1);
+ #endif
+
+ break;
+ case DestroyNotify:
+ DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
+ (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event);
+ if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) {
+ // ignore child destroy notification
+ }
+ break;
+ case CreateNotify:
+ DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n",
+ (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent);
+ break;
+ case ConfigureNotify:
+ DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n",
+ (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above,
+ evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height,
+ evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event);
+ if ( evt.xconfigure.window == evt.xconfigure.event ) {
+ // ignore child window change notification
+ {
+ // update insets
+ int left, right, top, bottom;
+ NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+ }
+ (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE,
+ (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
+ (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE,
+ (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
+ }
+ break;
+ case ClientMessage:
+ if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom
+ jboolean closed;
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
+ closed = (*env)->CallBooleanMethod(env, jwindow, windowDestroyNotifyID, JNI_FALSE);
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, closed: %d\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, (int)closed);
+ // Called by Window.java: CloseWindow();
+ num_events = 0; // end loop in case of destroyed display
+ }
+ break;
+
+ case FocusIn:
+ DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE);
+ break;
+
+ case FocusOut:
+ DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE);
+ break;
+
+ case Expose:
+ DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count);
+
+ if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) {
+ (*env)->CallVoidMethod(env, jwindow, windowRepaintID, JNI_FALSE,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+ }
+ break;
+
+ case MapNotify:
+ DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n",
+ (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect,
+ evt.xmap.event!=evt.xmap.window);
+ if( evt.xmap.event == evt.xmap.window ) {
+ // ignore child window notification
+ {
+ // update insets
+ int left, right, top, bottom;
+ NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+ }
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
+ }
+ break;
+
+ case UnmapNotify:
+ DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n",
+ (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure,
+ evt.xunmap.event!=evt.xunmap.window);
+ if( evt.xunmap.event == evt.xunmap.window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE);
+ }
+ break;
+
+ case ReparentNotify:
+ {
+ jlong parentResult; // 0 if root, otherwise proper value
+ Window winRoot, winTopParent;
+ #ifdef VERBOSE_ON
+ Window oldParentRoot, oldParentTopParent;
+ Window parentRoot, parentTopParent;
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) {
+ oldParentRoot=0; oldParentTopParent = 0;
+ }
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) {
+ parentRoot=0; parentTopParent = 0;
+ }
+ #endif
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) {
+ winRoot=0; winTopParent = 0;
+ }
+ if(evt.xreparent.parent == winRoot) {
+ parentResult = 0; // our java indicator for root window
+ } else {
+ parentResult = (jlong) (intptr_t) evt.xreparent.parent;
+ }
+ #ifdef VERBOSE_ON
+ DBG_PRINT( "X11: event . ReparentNotify: call %d/%d OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n",
+ evt.xreparent.x, evt.xreparent.y,
+ (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent,
+ (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent,
+ (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
+ #endif
+ (*env)->CallVoidMethod(env, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent);
+ }
+ break;
+
+ // unhandled events .. yet ..
+
+ default:
+ DBG_PRINT("X11: event . unhandled %d 0x%X call %p\n", (int)evt.type, (unsigned int)evt.type, (void*)evt.xunmap.window);
+ }
+ }
+}
diff --git a/src/newt/native/X11Event.h b/src/newt/native/X11Event.h
new file mode 100644
index 000000000..969bcdeed
--- /dev/null
+++ b/src/newt/native/X11Event.h
@@ -0,0 +1,9 @@
+
+#ifndef _X11Event_h
+#define _X11Event_h
+
+#include "X11Common.h"
+
+extern void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom);
+
+#endif /* _X11Event_h */
diff --git a/src/newt/native/X11RandR11.c b/src/newt/native/X11RandR11.c
new file mode 100644
index 000000000..38d61289b
--- /dev/null
+++ b/src/newt/native/X11RandR11.c
@@ -0,0 +1,371 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "X11Screen.h"
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getAvailableScreenRotations0
+ * Signature: (JI)I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getAvailableScreenRotations0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+ int num_rotations = 0;
+ Rotation cur_rotation, rotations_supported;
+ int rotations[4];
+ int major, minor;
+
+ rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
+
+ if(0 != (rotations_supported & RR_Rotate_0)) {
+ rotations[num_rotations++] = 0;
+ }
+ if(0 != (rotations_supported & RR_Rotate_90)) {
+ rotations[num_rotations++] = 90;
+ }
+ if(0 != (rotations_supported & RR_Rotate_180)) {
+ rotations[num_rotations++] = 180;
+ }
+ if(0 != (rotations_supported & RR_Rotate_270)) {
+ rotations[num_rotations++] = 270;
+ }
+
+ jintArray properties = NULL;
+
+ if(num_rotations>0) {
+ properties = (*env)->NewIntArray(env, num_rotations);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
+ }
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getNumScreenResolution0
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getNumScreenResolutions0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+#ifdef DBG_PERF
+ struct timespec t0, t1, td;
+ long td_ms;
+ timespec_now(&t0);
+#endif
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getNumScreenResolution0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getNumScreenResolution0.2 (XRRSizes): %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ DBG_PRINT("getNumScreenResolutions0: %p:%d -> %d\n", dpy, (int)scrn_idx, num_sizes);
+
+ return num_sizes;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getScreenResolutions0
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenResolution0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ // Fill the properties in temp jint array
+ int propIndex = 0;
+ jint prop[4];
+
+ prop[propIndex++] = xrrs[(int)resMode_idx].width;
+ prop[propIndex++] = xrrs[(int)resMode_idx].height;
+ prop[propIndex++] = xrrs[(int)resMode_idx].mwidth;
+ prop[propIndex++] = xrrs[(int)resMode_idx].mheight;
+
+ jintArray properties = (*env)->NewIntArray(env, 4);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, 4, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getScreenRates0
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenRates0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ int num_rates;
+ short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates);
+
+ jint prop[num_rates];
+ int i;
+ for(i=0; i<num_rates; i++) {
+ prop[i] = (int) rates[i];
+ /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */
+ }
+
+ jintArray properties = (*env)->NewIntArray(env, num_rates);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getScreenConfiguration0
+ * Signature: (JI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenConfiguration0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+#ifdef DBG_PERF
+ struct timespec t0, t1, td;
+ long td_ms;
+ timespec_now(&t0);
+#endif
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getScreenConfiguration0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ // get current resolutions and frequencies
+ XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root);
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getScreenConfiguration0.2 (XRRGetScreenInfo): %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ return (jlong) (intptr_t) conf;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: freeScreenConfiguration0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR11_freeScreenConfiguration0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRFreeScreenConfigInfo( (XRRScreenConfiguration *) (intptr_t) screenConfiguration );
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getCurrentScreenRate0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenRate0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+
+ short original_rate = XRRConfigCurrentRate(conf);
+ DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate);
+
+ return (jint) original_rate;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getCurrentScreenRotation0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenRotation0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+ Rotation rotation;
+
+ XRRConfigCurrentConfiguration(conf, &rotation);
+
+ return NewtScreen_XRotation2Degree(env, rotation);
+}
+
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getCurrentScreenResolutionIndex0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenResolutionIndex0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+
+ short original_rate = XRRConfigCurrentRate(conf);
+
+ Rotation original_rotation;
+ SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
+
+ DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id);
+ return (jint)original_size_id;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: setCurrentScreenModeStart0
+ * Signature: (JIJIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenModeStart0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenConfiguration, jint resMode_idx, jint freq, jint rotation)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+ Window root = RootWindow(dpy, (int)screen_idx);
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n",
+ resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
+
+ int xrot = NewtScreen_Degree2XRotation(env, rotation);
+
+ XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
+
+ XSync(dpy, False);
+ XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, xrot, (short)freq, CurrentTime);
+ XSync(dpy, False);
+
+ return JNI_TRUE;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: setCurrentScreenModePollEnd0
+ * Signature: (JIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenModePollEnd0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ int randr_event_base, randr_error_base;
+ XEvent evt;
+ XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
+ XRRScreenConfiguration *conf;
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
+
+ int done = 0;
+ int rot;
+ do {
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
+ return JNI_FALSE; // not done
+ }
+ XNextEvent(dpy, &evt);
+
+ switch (evt.type - randr_event_base) {
+ case RRScreenChangeNotify:
+ if(0 < scn_event->rotation ) {
+ rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
+ DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(1) %p (root %p) resIdx %d rot %d %dx%d\n",
+ (void*)scn_event->window, (void*)scn_event->root,
+ (int)scn_event->size_index, rot,
+ scn_event->width, scn_event->height);
+ // done = scn_event->size_index == resMode_idx; // not reliable ..
+ done = rot == rotation &&
+ scn_event->width == xrrs[resMode_idx].width &&
+ scn_event->height == xrrs[resMode_idx].height;
+ } else {
+ DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(0) %p (root %p) resIdx %d %dx%d\n",
+ (void*)scn_event->window, (void*)scn_event->root,
+ (int)scn_event->size_index,
+ scn_event->width, scn_event->height);
+ }
+ break;
+ default:
+ DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
+ }
+ XRRUpdateConfiguration(&evt);
+ } while(!done);
+
+ XSync(dpy, False);
+
+ return done ? JNI_TRUE : JNI_FALSE;
+}
+
diff --git a/src/newt/native/X11RandR13.c b/src/newt/native/X11RandR13.c
new file mode 100644
index 000000000..4e92a32b4
--- /dev/null
+++ b/src/newt/native/X11RandR13.c
@@ -0,0 +1,519 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "X11Common.h"
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getScreenResources0
+ * Signature: (JI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenResources0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+
+ XRRScreenResources *res = XRRGetScreenResourcesCurrent( dpy, root); // 1.3
+ // XRRScreenResources *res = XRRGetScreenResources( dpy, root); // 1.2
+
+ return (jlong) (intptr_t) res;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: freeScreenResources0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeScreenResources0
+ (JNIEnv *env, jclass clazz, jlong screenResources)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ if( NULL != resources ) {
+ XRRFreeScreenResources( resources );
+ }
+}
+
+#define SAFE_STRING(s) (NULL==s?"":s)
+
+static void dumpOutputs(const char *prefix, Display *dpy, XRRScreenResources *resources, int noutput, RROutput * outputs) {
+ int i, j;
+ fprintf(stderr, "%s %p: Output count %d\n", prefix, resources, noutput);
+ for(i=0; i<noutput; i++) {
+ RROutput output = outputs[i];
+ XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
+ fprintf(stderr, " Output[%d]: id %#lx, crtx 0x%X, name %s (%d), %lux%lu, ncrtc %d, .., nmode %d (preferred %d)\n",
+ i, output, xrrOutputInfo->crtc, SAFE_STRING(xrrOutputInfo->name), xrrOutputInfo->nameLen, xrrOutputInfo->mm_width, xrrOutputInfo->mm_height,
+ xrrOutputInfo->ncrtc, xrrOutputInfo->nmode, xrrOutputInfo->npreferred);
+ for(j=0; j<xrrOutputInfo->nmode; j++) {
+ fprintf(stderr, " Output[%d].Mode[%d].id %#lx\n", i, j, xrrOutputInfo->modes[j]);
+ }
+ XRRFreeOutputInfo (xrrOutputInfo);
+ }
+}
+
+/** Returns vertical refresh rate in hertz */
+static float getVRefresh(XRRModeInfo *mode) {
+ float rate;
+ unsigned int vTotal = mode->vTotal;
+
+ if (mode->modeFlags & RR_DoubleScan) {
+ /* doublescan doubles the number of lines */
+ vTotal *= 2;
+ }
+
+ if (mode->modeFlags & RR_Interlace) {
+ /* interlace splits the frame into two fields */
+ /* the field rate is what is typically reported by monitors */
+ vTotal /= 2;
+ }
+
+ if (mode->hTotal && vTotal) {
+ rate = ( (float) mode->dotClock /
+ ( (float) mode->hTotal * (float) vTotal )
+ );
+ } else {
+ rate = 0;
+ }
+ return rate;
+}
+
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_dumpInfo0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ int pos[] = { 0, 0 } ;
+ int i, j, minWidth, minHeight, maxWidth, maxHeight;
+
+ int vs_width = DisplayWidth(dpy, screen_idx);
+ int vs_height = DisplayHeight(dpy, screen_idx);
+ int vs_width_mm = DisplayWidthMM(dpy, screen_idx);
+ int vs_height_mm = DisplayHeightMM(dpy, screen_idx);
+ fprintf(stderr, "ScreenVirtualSize: %dx%d %dx%d mm\n", vs_width, vs_height, vs_width_mm, vs_height_mm);
+
+ XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight, &maxWidth, &maxHeight);
+ fprintf(stderr, "XRRGetScreenSizeRange: %dx%d .. %dx%d\n", minWidth, minHeight, maxWidth, maxHeight);
+
+ if( NULL == resources ) {
+ fprintf(stderr, "XRRScreenResources NULL\n");
+ return;
+ }
+ fprintf(stderr, "XRRScreenResources %p: Crtc count %d\n", resources, resources->ncrtc);
+ for(i=0; i<resources->ncrtc; i++) {
+ RRCrtc crtc = resources->crtcs[i];
+ XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc);
+ fprintf(stderr, "Crtc[%d]: %d/%d %dx%d, rot 0x%X, mode.id %#lx\n",
+ i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height, xrrCrtcInfo->rotations, xrrCrtcInfo->mode);
+ for(j=0; j<xrrCrtcInfo->noutput; j++) {
+ fprintf(stderr, " Crtc[%d].Output[%d].id %#lx\n", i, j, xrrCrtcInfo->outputs[j]);
+ }
+ XRRFreeCrtcInfo(xrrCrtcInfo);
+ }
+
+ dumpOutputs("XRRScreenResources.outputs", dpy, resources, resources->noutput, resources->outputs);
+
+ fprintf(stderr, "XRRScreenResources %p: Mode count %d\n", resources, resources->nmode);
+ for(i=0; i<resources->nmode; i++) {
+ XRRModeInfo *mode = &resources->modes[i];
+
+ unsigned int dots = mode->hTotal * mode->vTotal;
+ float refresh = getVRefresh(mode);
+ fprintf(stderr, "Mode[%d, id %#lx]: %ux%u@%f, name %s\n", i, mode->id, mode->width, mode->height, refresh, SAFE_STRING(mode->name));
+ }
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorDeviceCount0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDeviceCount0
+ (JNIEnv *env, jclass clazz, jlong screenResources)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ return ( NULL != resources ) ? resources->ncrtc : 0;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorInfoHandle0
+ * Signature: (JIJI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorInfoHandle0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint crt_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+
+ if( NULL == resources || crt_idx >= resources->ncrtc ) {
+ return 0;
+ }
+ RRCrtc crtc = resources->crtcs[crt_idx];
+ XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc);
+
+ return (jlong) (intptr_t) xrrCrtcInfo;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: freeMonitorInfoHandle0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeMonitorInfoHandle0
+ (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+ if( NULL != xrrCrtcInfo ) {
+ XRRFreeCrtcInfo( xrrCrtcInfo );
+ }
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getAvailableRotations0
+ * Signature: (J)I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getAvailableRotations0
+ (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+ if( NULL == xrrCrtcInfo ) {
+ return NULL;
+ }
+ Rotation rotations_supported = xrrCrtcInfo->rotations;
+
+ int num_rotations = 0;
+ int rotations[4];
+ if(0 != (rotations_supported & RR_Rotate_0)) {
+ rotations[num_rotations++] = 0;
+ }
+ if(0 != (rotations_supported & RR_Rotate_90)) {
+ rotations[num_rotations++] = 90;
+ }
+ if(0 != (rotations_supported & RR_Rotate_180)) {
+ rotations[num_rotations++] = 180;
+ }
+ if(0 != (rotations_supported & RR_Rotate_270)) {
+ rotations[num_rotations++] = 270;
+ }
+
+ jintArray properties = NULL;
+
+ if(num_rotations>0) {
+ properties = (*env)->NewIntArray(env, num_rotations);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
+ }
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorViewport0
+ * Signature: (J)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorViewport0
+ (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+ if( NULL == xrrCrtcInfo ) {
+ // n/a
+ return NULL;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return NULL;
+ }
+
+ jsize propCount = 4;
+ jint prop[ propCount ];
+ int propIndex = 0;
+
+ prop[propIndex++] = xrrCrtcInfo->x;
+ prop[propIndex++] = xrrCrtcInfo->y;
+ prop[propIndex++] = xrrCrtcInfo->width;
+ prop[propIndex++] = xrrCrtcInfo->height;
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorMode0
+ * Signature: (JI)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorMode0
+ (JNIEnv *env, jclass clazz, jlong screenResources, jint mode_idx)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+
+ if( NULL == resources || mode_idx >= resources->nmode ) {
+ return NULL;
+ }
+
+ XRRModeInfo *mode = &resources->modes[mode_idx];
+ unsigned int dots = mode->hTotal * mode->vTotal;
+ int refresh = (int) ( getVRefresh(mode) * 100.0f ); // Hz * 100
+ int flags = 0;
+ if (mode->modeFlags & RR_Interlace) {
+ flags |= FLAG_INTERLACE;
+ }
+ if (mode->modeFlags & RR_DoubleScan) {
+ flags |= FLAG_DOUBLESCAN;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int propIndex = 0;
+
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+ prop[propIndex++] = mode->width;
+ prop[propIndex++] = mode->height;
+ prop[propIndex++] = 32; // TODO: XRandR > 1.4 may support bpp
+ prop[propIndex++] = refresh;
+ prop[propIndex++] = flags;
+ prop[propIndex++] = mode->id;
+ prop[propIndex++] = -1; // rotation placeholder
+
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorCurrentMode0
+ * Signature: (JJ)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorCurrentMode0
+ (JNIEnv *env, jclass clazz, jlong screenResources, jlong monitorInfo)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+ if( NULL == resources || NULL == xrrCrtcInfo ) {
+ // n/a
+ return NULL;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return NULL;
+ }
+
+ int modeId = xrrCrtcInfo->mode;
+ XRRModeInfo *mode = NULL;
+ int i;
+ for(i=0; i<resources->nmode; i++) {
+ XRRModeInfo *imode = &resources->modes[i];
+ if( imode->id == modeId ) {
+ mode = imode;
+ break;
+ }
+ }
+ if( NULL == mode ) {
+ // oops ..
+ return NULL;
+ }
+
+ unsigned int dots = mode->hTotal * mode->vTotal;
+ int refresh = (int) ( getVRefresh(mode) * 100.0f ); // Hz * 100
+ int flags = 0;
+ if (mode->modeFlags & RR_Interlace) {
+ flags |= FLAG_INTERLACE;
+ }
+ if (mode->modeFlags & RR_DoubleScan) {
+ flags |= FLAG_DOUBLESCAN;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int propIndex = 0;
+
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+ prop[propIndex++] = mode->width;
+ prop[propIndex++] = mode->height;
+ prop[propIndex++] = 32; // TODO: XRandR > 1.4 may support bpp
+ prop[propIndex++] = refresh;
+ prop[propIndex++] = flags;
+ prop[propIndex++] = mode->id;
+ prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation);
+
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorDevice0
+ * Signature: (JJJJ)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDevice0
+ (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+ if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) {
+ // n/a
+ return NULL;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return NULL;
+ }
+
+ RROutput output = xrrCrtcInfo->outputs[0];
+ XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
+ int numModes = xrrOutputInfo->nmode;
+
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 + numModes;
+ jint prop[ propCount ];
+ int propIndex = 0;
+
+ prop[propIndex++] = propCount;
+ prop[propIndex++] = crt_idx;
+ prop[propIndex++] = xrrOutputInfo->mm_width;
+ prop[propIndex++] = xrrOutputInfo->mm_height;
+ prop[propIndex++] = xrrCrtcInfo->x; // rotated viewport pixel units
+ prop[propIndex++] = xrrCrtcInfo->y; // rotated viewport pixel units
+ prop[propIndex++] = xrrCrtcInfo->width; // rotated viewport pixel units
+ prop[propIndex++] = xrrCrtcInfo->height; // rotated viewport pixel units
+ prop[propIndex++] = xrrCrtcInfo->x; // rotated viewport window units (same)
+ prop[propIndex++] = xrrCrtcInfo->y; // rotated viewport window units (same)
+ prop[propIndex++] = xrrCrtcInfo->width; // rotated viewport window units (same)
+ prop[propIndex++] = xrrCrtcInfo->height; // rotated viewport window units (same)
+ prop[propIndex++] = xrrCrtcInfo->mode; // current mode id
+ prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation);
+ int i;
+ for(i=0; i<numModes; i++) {
+ // avail modes ..
+ prop[propIndex++] = xrrOutputInfo->modes[i];
+ }
+
+ XRRFreeOutputInfo (xrrOutputInfo);
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: setMonitorMode0
+ * Signature: (JJJIIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setMonitorMode0
+ (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx, jint modeId, jint rotation, jint x, jint y)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+ jboolean res = JNI_FALSE;
+
+ if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) {
+ // n/a
+ return res;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return res;
+ }
+
+ if( 0 >= modeId ) {
+ // oops ..
+ return res;
+ }
+
+ if( 0 > x || 0 > y ) {
+ x = xrrCrtcInfo->x;
+ y = xrrCrtcInfo->y;
+ }
+
+ Status status = XRRSetCrtcConfig( dpy, resources, resources->crtcs[crt_idx], CurrentTime,
+ x, y, modeId, NewtScreen_Degree2XRotation(env, rotation),
+ xrrCrtcInfo->outputs, xrrCrtcInfo->noutput );
+ res = status == RRSetConfigSuccess;
+
+ return res;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: setScreenViewport0
+ * Signature: (JIJIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setScreenViewport0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint x, jint y, jint width, jint height)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ jboolean res = JNI_FALSE;
+
+ if( NULL == resources ) {
+ // n/a
+ return JNI_FALSE;
+ }
+
+ XRRSetScreenSize (dpy, root, width, height, DisplayWidthMM(dpy, screen_idx), DisplayHeightMM(dpy, screen_idx));
+ return JNI_TRUE;
+}
+
+
diff --git a/src/newt/native/X11Screen.c b/src/newt/native/X11Screen.c
index 334c39727..152a092c9 100644
--- a/src/newt/native/X11Screen.c
+++ b/src/newt/native/X11Screen.c
@@ -29,7 +29,7 @@
// #define VERBOSE_ON 1
// #define DBG_PERF 1
-#include "X11Common.h"
+#include "X11Screen.h"
#ifdef DBG_PERF
#include "timespec.h"
@@ -74,418 +74,66 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getHeight0
return (jint) DisplayHeight( dpy, scrn_idx);
}
-static int showedRandRVersion = 0;
-
-static Bool NewtScreen_getRANDRVersion(Display *dpy, int *major, int *minor) {
- if( 0 == XRRQueryVersion(dpy, major, minor) ) {
- return False;
- }
- if(0 == showedRandRVersion) {
- DBG_PRINT("X11 RandR Version %d.%d\n", *major, *minor);
- showedRandRVersion = 1;
- }
- return True;
-}
-
-static Bool NewtScreen_hasRANDR(Display *dpy) {
- int major, minor;
- return NewtScreen_getRANDRVersion(dpy, &major, &minor);
-}
-
-static int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
- int rot;
+int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
+ int degree;
if(xrotation == RR_Rotate_0) {
- rot = 0;
+ degree = 0;
}
else if(xrotation == RR_Rotate_90) {
- rot = 90;
+ degree = 90;
}
else if(xrotation == RR_Rotate_180) {
- rot = 180;
+ degree = 180;
}
else if(xrotation == RR_Rotate_270) {
- rot = 270;
+ degree = 270;
} else {
NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", xrotation);
}
- return rot;
+ return degree;
}
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getAvailableScreenModeRotations0
- * Signature: (JI)I
- */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getAvailableScreenModeRotations0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
- Window root = RootWindow(dpy, (int)scrn_idx);
- int num_rotations = 0;
- Rotation cur_rotation, rotations_supported;
- int rotations[4];
- int major, minor;
-
- if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) {
- fprintf(stderr, "RANDR not available\n");
- return (*env)->NewIntArray(env, 0);
- }
-
- rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
-
- if(0 != (rotations_supported & RR_Rotate_0)) {
- rotations[num_rotations++] = 0;
- }
- if(0 != (rotations_supported & RR_Rotate_90)) {
- rotations[num_rotations++] = 90;
- }
- if(0 != (rotations_supported & RR_Rotate_180)) {
- rotations[num_rotations++] = 180;
+int NewtScreen_Degree2XRotation(JNIEnv *env, int degree) {
+ int xrot;
+ if(degree == 0) {
+ xrot = RR_Rotate_0;
}
- if(0 != (rotations_supported & RR_Rotate_270)) {
- rotations[num_rotations++] = 270;
+ else if(degree == 90) {
+ xrot = RR_Rotate_90;
}
-
- jintArray properties = NULL;
-
- if(num_rotations>0) {
- properties = (*env)->NewIntArray(env, num_rotations);
- if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
- }
-
- // move from the temp structure to the java structure
- (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
- }
-
- return properties;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getNumScreenModeResolution0
- * Signature: (JI)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
-#ifdef DBG_PERF
- struct timespec t0, t1, td;
- long td_ms;
- timespec_now(&t0);
-#endif
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0: RANDR not available\n");
- return 0;
+ else if(degree == 180) {
+ xrot = RR_Rotate_180;
}
-
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getNumScreenModeResolution0.1: %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getNumScreenModeResolution0.2 (XRRSizes): %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- DBG_PRINT("getNumScreenModeResolutions0: %p:%d -> %d\n", dpy, (int)scrn_idx, num_sizes);
-
- return num_sizes;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getScreenModeResolutions0
- * Signature: (JII)[I
- */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0: RANDR not available\n");
- return (*env)->NewIntArray(env, 0);
- }
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
- }
-
- // Fill the properties in temp jint array
- int propIndex = 0;
- jint prop[4];
-
- prop[propIndex++] = xrrs[(int)resMode_idx].width;
- prop[propIndex++] = xrrs[(int)resMode_idx].height;
- prop[propIndex++] = xrrs[(int)resMode_idx].mwidth;
- prop[propIndex++] = xrrs[(int)resMode_idx].mheight;
-
- jintArray properties = (*env)->NewIntArray(env, 4);
- if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4);
+ else if(degree == 270) {
+ xrot = RR_Rotate_270;
+ } else {
+ NewtCommon_throwNewRuntimeException(env, "invalid degree: %d", degree);
}
-
- // move from the temp structure to the java structure
- (*env)->SetIntArrayRegion(env, properties, 0, 4, prop);
-
- return properties;
+ return xrot;
}
/*
* Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getScreenModeRates0
- * Signature: (JII)[I
+ * Method: GetRandRVersion0
+ * Signature: (J)[I
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getRandRVersion0
+ (JNIEnv *env, jclass clazz, jlong display)
{
- Display *dpy = (Display *) (intptr_t) display;
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0: RANDR not available\n");
- return (*env)->NewIntArray(env, 0);
- }
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ Display * dpy = (Display *)(intptr_t)display;
+ jint version[2];
+ if( 0 == XRRQueryVersion(dpy, &version[0], &version[1] ) ) {
+ version[0] = 0;
+ version[1] = 0;
}
-
- int num_rates;
- short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates);
-
- jint prop[num_rates];
- int i;
- for(i=0; i<num_rates; i++) {
- prop[i] = (int) rates[i];
- /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */
- }
-
- jintArray properties = (*env)->NewIntArray(env, num_rates);
- if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates);
+ jintArray jversion = (*env)->NewIntArray(env, 2);
+ if (jversion == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2");
}
// move from the temp structure to the java structure
- (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop);
+ (*env)->SetIntArrayRegion(env, jversion, 0, 2, version);
- return properties;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getScreenConfiguration0
- * Signature: (JI)J
- */
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenConfiguration0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
- Window root = RootWindow(dpy, (int)screen_idx);
-#ifdef DBG_PERF
- struct timespec t0, t1, td;
- long td_ms;
- timespec_now(&t0);
-#endif
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenConfiguration0: RANDR not available\n");
- return 0;
- }
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getScreenConfiguration0.1: %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- // get current resolutions and frequencies
- XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root);
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getScreenConfiguration0.2 (XRRGetScreenInfo): %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- return (jlong) (intptr_t) conf;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: freeScreenConfiguration0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_freeScreenConfiguration0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRFreeScreenConfigInfo( (XRRScreenConfiguration *) (intptr_t) screenConfiguration );
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getCurrentScreenRate0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRate0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
-
- short original_rate = XRRConfigCurrentRate(conf);
- DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate);
-
- return (jint) original_rate;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getCurrentScreenRotation0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRotation0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
- Rotation rotation;
-
- XRRConfigCurrentConfiguration(conf, &rotation);
-
- return NewtScreen_XRotation2Degree(env, rotation);
-}
-
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getCurrentScreenResolutionIndex0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenResolutionIndex0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
-
- short original_rate = XRRConfigCurrentRate(conf);
-
- Rotation original_rotation;
- SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
-
- DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id);
- return (jint)original_size_id;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: setCurrentScreenModeStart0
- * Signature: (JIJIII)Z
- */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModeStart0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenConfiguration, jint resMode_idx, jint freq, jint rotation)
-{
- Display *dpy = (Display *) (intptr_t) display;
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
- Window root = RootWindow(dpy, (int)screen_idx);
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
- int rot;
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
- }
-
- switch(rotation) {
- case 0:
- rot = RR_Rotate_0;
- break;
- case 90:
- rot = RR_Rotate_90;
- break;
- case 180:
- rot = RR_Rotate_180;
- break;
- case 270:
- rot = RR_Rotate_270;
- break;
- default:
- NewtCommon_throwNewRuntimeException(env, "Invalid rotation: %d", rotation);
- }
-
- DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n",
- resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
-
- XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
-
- XSync(dpy, False);
- XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime);
- XSync(dpy, False);
-
- return JNI_TRUE;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: setCurrentScreenModePollEnd0
- * Signature: (J)Z
- */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
-{
- Display *dpy = (Display *) (intptr_t) display;
- int randr_event_base, randr_error_base;
- XEvent evt;
- XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0: RANDR not available\n");
- return JNI_FALSE;
- }
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
- XRRScreenConfiguration *conf;
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
- }
-
- XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
-
- int done = 0;
- int rot;
- do {
- if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
- return;
- }
- XNextEvent(dpy, &evt);
-
- switch (evt.type - randr_event_base) {
- case RRScreenChangeNotify:
- rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
- DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n",
- (void*)scn_event->window, (void*)scn_event->root,
- (int)scn_event->size_index, rot,
- scn_event->width, scn_event->height);
- // done = scn_event->size_index == resMode_idx; // not reliable ..
- done = rot == rotation &&
- scn_event->width == xrrs[resMode_idx].width &&
- scn_event->height == xrrs[resMode_idx].height;
- break;
- default:
- DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
- }
- XRRUpdateConfiguration(&evt);
- } while(!done);
-
- XSync(dpy, False);
-
+ return jversion;
}
diff --git a/src/newt/native/X11Screen.h b/src/newt/native/X11Screen.h
new file mode 100644
index 000000000..c81ee05d5
--- /dev/null
+++ b/src/newt/native/X11Screen.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#ifndef _X11SCREEN_H
+#define _X11SCREEN_H
+
+
+#include "X11Common.h"
+
+int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation);
+int NewtScreen_Degree2XRotation(JNIEnv *env, int degree);
+
+#endif /* _X11SCREEN_H */
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 59862f463..2cc66c78d 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -98,11 +98,11 @@ static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlon
}
jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) {
- Atom actual_type;
- int actual_format;
+ Atom actual_type = 0;
+ int actual_format = 0;
int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ;
unsigned char * jogl_java_object_data_pp = NULL;
- jobject jwindow;
+ jobject jwindow = 0;
{
unsigned long nitems= 0;
@@ -122,7 +122,9 @@ jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong ja
}
if(actual_type!=(Atom)javaObjectAtom || nitems<nitems_32 || NULL==jogl_java_object_data_pp) {
- XFree(jogl_java_object_data_pp);
+ if( NULL != jogl_java_object_data_pp ) {
+ XFree(jogl_java_object_data_pp);
+ }
if(True==showWarning) {
fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom NEWT_JAVA_OBJECT window property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, NEWT_JAVA_OBJECT %ld, result 0!\n",
res, nitems, bytes_after, (long)actual_type, (long)javaObjectAtom);
@@ -189,8 +191,8 @@ static Status NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window
return 0; // Error
}
static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left, int *right, int *top, int *bottom) {
- Atom actual_type;
- int actual_format;
+ Atom actual_type = 0;
+ int actual_format = 0;
int nitems_32 = 4; // l, r, t, b
unsigned char * frame_extends_data_pp = NULL;
@@ -210,7 +212,9 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left
}
if(nitems<nitems_32 || NULL==frame_extends_data_pp) {
- XFree(frame_extends_data_pp);
+ if( NULL != frame_extends_data_pp ) {
+ XFree(frame_extends_data_pp);
+ }
// DBG_PRINT( "Warning: NEWT X11Window: Fetched invalid Atom _NET_FRAME_EXTENTS window property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, actual_format %d, _NET_FRAME_EXTENTS %ld, result 0!\n",
// res, nitems, bytes_after, (long)actual_type, actual_format, _NET_FRAME_EXTENTS);
return 0; // Error, but ok - ie window not mapped
@@ -271,18 +275,21 @@ static Bool NewtWindows_hasDecorations (Display *dpy, Window w) {
#ifdef DECOR_USE_MWM
Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False );
- unsigned char *wm_data;
- Atom wm_type;
- int wm_format;
- unsigned long wm_nitems, wm_bytes_after;
+ unsigned char *wm_data = NULL;
+ Atom wm_type = 0;
+ int wm_format = 0;
+ unsigned long wm_nitems = 0, wm_bytes_after = 0;
if( Success == XGetWindowProperty(dpy, w, _MOTIF_WM_HINTS, 0, PROP_MWM_HINTS_ELEMENTS, False, AnyPropertyType,
&wm_type, &wm_format, &wm_nitems, &wm_bytes_after, &wm_data) ) {
- if(wm_type != None) {
+ if(wm_type != None && NULL != wm_data && wm_nitems >= PROP_MWM_HINTS_ELEMENTS) {
// unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status
unsigned long *hints = (unsigned long *) wm_data;
decor = ( 0 != (hints[0] & MWM_HINTS_DECORATIONS) ) && ( 0 != hints[2] );
}
+ if( NULL != wm_data ) {
+ XFree(wm_data);
+ }
}
#endif
@@ -299,9 +306,8 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) {
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
-
-#define _NET_WM_FULLSCREEN ( 1 << 0 )
-#define _NET_WM_ABOVE ( 1 << 1 )
+#define _NET_WM_STATE_FLAG_FULLSCREEN ( 1 << 0 )
+#define _NET_WM_STATE_FLAG_ABOVE ( 1 << 1 )
/**
* Set fullscreen using Extended Window Manager Hints (EWMH)
@@ -314,101 +320,98 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) {
* and resets it when leaving FS.
* The same is assumed for the decoration state.
*/
-static int NewtWindows_isFullscreenEWMHSupported (Display *dpy, Window w) {
+static int NewtWindows_getSupportedStackingEWMHFlags(Display *dpy, Window w) {
+#ifdef VERBOSE_ON
+ // Code doesn't work reliable on KDE4 ...
Atom _NET_WM_ALLOWED_ACTIONS = XInternAtom( dpy, "_NET_WM_ALLOWED_ACTIONS", False );
Atom _NET_WM_ACTION_FULLSCREEN = XInternAtom( dpy, "_NET_WM_ACTION_FULLSCREEN", False );
Atom _NET_WM_ACTION_ABOVE = XInternAtom( dpy, "_NET_WM_ACTION_ABOVE", False );
- Atom * actions;
- Atom type;
- unsigned long action_len, remain;
- int res = 0, form, i;
+ Atom * actions = NULL;
+ Atom type = 0;
+ unsigned long action_len = 0, remain = 0;
+ int res = 0, form = 0, i = 0;
Status s;
if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, AnyPropertyType,
&type, &form, &action_len, &remain, (unsigned char**)&actions)) ) {
- for(i=0; i<action_len; i++) {
- if(_NET_WM_ACTION_FULLSCREEN == actions[i]) {
- DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_FULLSCREEN (*)\n", i);
- res |= _NET_WM_FULLSCREEN ;
- } else if(_NET_WM_ACTION_ABOVE == actions[i]) {
- DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_ABOVE (*)\n", i);
- res |= _NET_WM_ABOVE ;
- }
-#ifdef VERBOSE_ON
- else {
- char * astr = XGetAtomName(dpy, actions[i]);
- DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: %s (unused)\n", i, astr);
- XFree(astr);
+ if( NULL != actions ) {
+ for(i=0; i<action_len; i++) {
+ if(_NET_WM_ACTION_FULLSCREEN == actions[i]) {
+ DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_FULLSCREEN (*)\n", i);
+ res |= _NET_WM_STATE_FLAG_FULLSCREEN ;
+ } else if(_NET_WM_ACTION_ABOVE == actions[i]) {
+ DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_ABOVE (*)\n", i);
+ res |= _NET_WM_STATE_FLAG_ABOVE ;
+ }
+ else {
+ char * astr = XGetAtomName(dpy, actions[i]);
+ DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: %s (unused)\n", i, astr);
+ XFree(astr);
+ }
}
-#endif
+ XFree(actions);
}
DBG_PRINT( "**************** X11: FS EWMH CHECK: 0x%X\n", res);
} else {
DBG_PRINT( "**************** X11: FS EWMH CHECK: XGetWindowProperty failed: %d\n", s);
}
- // above code doesn't work reliable on KDE4 ...
- res = _NET_WM_FULLSCREEN | _NET_WM_ABOVE ;
- return res;
+#endif
+ return _NET_WM_STATE_FLAG_FULLSCREEN | _NET_WM_STATE_FLAG_ABOVE ;
}
-static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) {
+static Bool NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) {
Atom _NET_WM_STATE = XInternAtom( dpy, "_NET_WM_STATE", False );
Atom _NET_WM_STATE_ABOVE = XInternAtom( dpy, "_NET_WM_STATE_ABOVE", False );
Atom _NET_WM_STATE_FULLSCREEN = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", False );
- int ewmhMask = NewtWindows_isFullscreenEWMHSupported(dpy, w);
+ int ewmhMask = NewtWindows_getSupportedStackingEWMHFlags(dpy, w);
+ Bool changeFullscreen = 0 != ( ( _NET_WM_STATE_FLAG_FULLSCREEN & ewmhMask ) & ewmhFlags ) ;
+ Bool changeAbove = 0 != ( ( _NET_WM_STATE_FLAG_ABOVE & ewmhMask ) & ewmhFlags ) ;
Bool res = False;
if(0 == ewmhMask) {
return res;
}
- if(!isVisible && True==enable) {
- Atom types[2]={0};
- int ntypes=0;
-
- if( 0 != ( ( _NET_WM_FULLSCREEN & ewmhMask ) & ewmhFlags ) ) {
- types[ntypes++] = _NET_WM_STATE_FULLSCREEN;
- }
- if( 0 != ( ( _NET_WM_ABOVE & ewmhMask ) & ewmhFlags ) ) {
- types[ntypes++] = _NET_WM_STATE_ABOVE;
- }
- if(ntypes>0) {
- XChangeProperty( dpy, w, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
- XSync(dpy, False);
- res = True;
- }
- } else {
- if(enable) {
- NewtWindows_setCWAbove(dpy, w);
- }
- XEvent xev;
- long mask = SubstructureNotifyMask | SubstructureRedirectMask ;
- int i=0;
-
- memset ( &xev, 0, sizeof(xev) );
-
- xev.type = ClientMessage;
- xev.xclient.window = w;
- xev.xclient.message_type = _NET_WM_STATE;
- xev.xclient.format = 32;
+ // _NET_WM_STATE: fullscreen and/or above
+ if( changeFullscreen || changeAbove ) {
+ {
+ // _NET_WM_STATE as event to root window
+ XEvent xev;
+ long mask = SubstructureNotifyMask | SubstructureRedirectMask ;
+ int i=0;
- xev.xclient.data.l[i++] = ( True == enable ) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
- if( 0 != ( ( _NET_WM_FULLSCREEN & ewmhMask ) & ewmhFlags ) ) {
- xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN;
- }
- if( 0 != ( ( _NET_WM_ABOVE & ewmhMask ) & ewmhFlags ) ) {
- xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE;
- }
- xev.xclient.data.l[3] = 1; //source indication for normal applications
+ memset ( &xev, 0, sizeof(xev) );
+
+ xev.type = ClientMessage;
+ xev.xclient.window = w;
+ xev.xclient.message_type = _NET_WM_STATE;
+ xev.xclient.format = 32;
+
+ xev.xclient.data.l[i++] = enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
+ if( changeFullscreen ) {
+ xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN;
+ }
+ if( changeAbove ) {
+ xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE;
+ }
+ xev.xclient.data.l[3] = 1; //source indication for normal applications
- if(i>0) {
XSendEvent ( dpy, root, False, mask, &xev );
- res = True;
}
+ // Also change _NET_WM_BYPASS_COMPOSITOR!
+ // A value of 0 indicates no preference.
+ // A value of 1 hints the compositor to disabling compositing of this window.
+ // A value of 2 hints the compositor to not disabling compositing of this window
+ {
+ Atom _NET_WM_BYPASS_COMPOSITOR = XInternAtom( dpy, "_NET_WM_BYPASS_COMPOSITOR", False );
+ unsigned long value = enable ? 1 : 0;
+ XChangeProperty( dpy, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1);
+ }
+ XSync(dpy, False);
+ res = True;
}
- XSync(dpy, False);
- DBG_PRINT( "X11: reconfigureWindow0 FULLSCREEN EWMH ON %d, ewmhMask 0x%X, ewmhFlags 0x%X, visible %d: %d\n",
- enable, ewmhMask, ewmhFlags, isVisible, res);
+ DBG_PRINT( "X11: setStackingEWMHFlags ON %d, changeFullscreen %d, changeAbove %d, visible %d: %d\n",
+ enable, changeFullscreen, changeAbove, isVisible, res);
return res;
}
@@ -438,7 +441,7 @@ Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Wind
return 0; // Error
}
-static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) {
+static void NewtWindows_requestFocus (Display *dpy, Window w, Bool force) {
XWindowAttributes xwa;
Window focus_return;
int revert_to_return;
@@ -447,7 +450,7 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy,
XGetInputFocus(dpy, &focus_return, &revert_to_return);
DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)w, force, focus_return==w);
- if( JNI_TRUE==force || focus_return!=w) {
+ if( True==force || focus_return!=w) {
DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w);
XRaiseWindow(dpy, w);
NewtWindows_setCWAbove(dpy, w);
@@ -504,6 +507,12 @@ static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint
}
}
+static void NewtWindows_setIcon(Display *dpy, Window w, int data_size, const unsigned char * data_ptr) {
+ Atom _NET_WM_ICON = XInternAtom(dpy, "_NET_WM_ICON", False);
+ Atom CARDINAL = XInternAtom(dpy, "CARDINAL", False);
+ XChangeProperty(dpy, w, _NET_WM_ICON, CARDINAL, 32, PropModeReplace, data_ptr, data_size);
+}
+
/*
* Class: jogamp_newt_driver_x11_WindowDriver
* Method: CreateWindow
@@ -512,7 +521,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
(JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index,
jint visualID,
jlong javaObjectAtom, jlong windowDeleteAtom,
- jint x, jint y, jint width, jint height, jboolean autoPosition, int flags)
+ jint x, jint y, jint width, jint height, jboolean autoPosition, int flags,
+ jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct)
{
Display * dpy = (Display *)(intptr_t)display;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
@@ -632,12 +642,27 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
{
XEvent event;
int left=0, right=0, top=0, bottom=0;
+ const unsigned char * pixelPtr = NULL;
+
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
+ DBG_PRINT("X11: CreateWindow icon: size %d, pixels %p, offset %d, direct %d\n", pixelDataSize, (void*)pixels, pixels_byte_offset, pixels_is_direct);
+ if( 0 < pixelDataSize && NULL != pixels ) {
+ pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ DBG_PRINT("X11: CreateWindow icon: NIO %p\n", pixelPtr);
+ NewtWindows_setIcon(dpy, window, (int)pixelDataSize, pixelPtr+pixels_byte_offset);
+ }
XMapWindow(dpy, window);
XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values
XSync(dpy, False);
+ if( JNI_FALSE == pixels_is_direct && NULL != pixelPtr ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
// send insets before visibility, allowing java code a proper sync point!
NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom);
(*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
@@ -657,7 +682,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
NewtWindows_setPosSize(dpy, window, x, y, width, height);
if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- NewtWindows_setFullscreenEWMH(dpy, root, window, _NET_WM_ABOVE, True, True);
+ NewtWindows_setStackingEWMHFlags(dpy, root, window, _NET_WM_STATE_FLAG_ABOVE, True, True);
}
}
@@ -671,11 +696,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
- (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom)
+ (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/) // XKB disabled for now
{
Display * dpy = (Display *) (intptr_t) display;
Window w = (Window)window;
jobject jwindow;
+ XWindowAttributes xwa;
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
@@ -683,51 +709,52 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
DBG_PRINT( "X11: CloseWindow START dpy %p, win %p\n", (void*)dpy, (void*)w);
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
-
jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom, True);
if(NULL==jwindow) {
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
NewtCommon_throwNewRuntimeException(env, "could not fetch Java Window object, bail out!");
return;
}
if ( JNI_FALSE == (*env)->IsSameObject(env, jwindow, obj) ) {
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
NewtCommon_throwNewRuntimeException(env, "Internal Error .. Window global ref not the same!");
return;
}
XSync(dpy, False);
+ memset(&xwa, 0, sizeof(XWindowAttributes));
+ XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction
XSelectInput(dpy, w, 0);
XUnmapWindow(dpy, w);
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
// Drain all events related to this window ..
- Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom);
+ Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
XDestroyWindow(dpy, w);
- XSync(dpy, False);
+ if( None != xwa.colormap ) {
+ XFreeColormap(dpy, xwa.colormap);
+ }
+ XSync(dpy, True); // discard all events now, no more handler
(*env)->DeleteGlobalRef(env, jwindow);
DBG_PRINT( "X11: CloseWindow END\n");
}
-#if 0
+// #define REPARENT_WAIT_FOR_REPARENT_NOTIFY 1
+
+#ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) {
- return (event->type == ReparentNotify) && (event->xreparent.window == (Window) arg);
+ Bool res = (event->type == ReparentNotify) && (event->xreparent.window == (Window) arg);
+ #ifdef VERBOSE_ON
+ if( event->type == ReparentNotify ) {
+ DBG_PRINT( "X11.WaitForReparentNotify: Event ReparentNotify: Result %d, exp %p, has %p\n", (int)res, arg, event->xreparent.window);
+ } else {
+ DBG_PRINT( "X11.WaitForReparentNotify: Event 0x%X: Result %d, exp %p, has %p\n", (int)event->type, (int)res, arg, event->xreparent.window);
+ }
+ #endif
+ return res;
}
#endif
-/**
- * KDE cause lost input focus in fullscreen mode.
- * Using 'XGrabKeyboard(..)' would prevent the loss,
- * but also would disable WM task switcher etc.
- *
- * #define FS_GRAB_KEYBOARD 1
- *
- */
-
/*
* Class: jogamp_newt_driver_x11_WindowDriver
* Method: reconfigureWindow0
@@ -746,51 +773,60 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
XEvent event;
Bool isVisible = !TST_FLAG_CHANGE_VISIBILITY(flags) && TST_FLAG_IS_VISIBLE(flags) ;
Bool tempInvisible = ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ) && isVisible ;
+ // Bool tempInvisible = TST_FLAG_CHANGE_PARENTING(flags) && isVisible ;
int fsEWMHFlags = 0;
if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) {
- fsEWMHFlags |= _NET_WM_FULLSCREEN;
+ if( !TST_FLAG_IS_FULLSCREEN_SPAN(flags) ) { // doesn't work w/ spanning across monitors. See also Bug 770 & Bug 771
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN;
+ }
if( TST_FLAG_IS_FULLSCREEN(flags) ) {
if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // fs on, above on
- } // else { } // fs on, above off
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs on, above on
+ } // else { } // fs on, above off
} else if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // fs off, above off
- } // else { } // fs off, above on
- }
- if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // toggle above
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs off, above off
+ } // else { } // fs off, above on
+ } else if( TST_FLAG_CHANGE_PARENTING(flags) ) {
+ // Fix for Unity WM, i.e. _remove_ persistent previous states
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN; // fs off
+ if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) {
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // above off
+ }
+ } else if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) {
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // toggle above
}
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
-
- DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
+ DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d (span %d), alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
(void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w,
x, y, width, height,
TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags),
TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags),
- TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags),
+ TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN_SPAN(flags),
TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags),
- TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), tempInvisible, fsEWMHFlags);
+ TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags),
+ tempInvisible, fsEWMHFlags);
- // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state shall be enough.
+ // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state should be enough.
// However, we have to consider other cases like reparenting and WM which don't support it.
-
+ #if 0 // Also doesn't work work properly w/ Unity WM
if( fsEWMHFlags && !TST_FLAG_CHANGE_PARENTING(flags) && isVisible &&
+ !TST_FLAG_IS_FULLSCREEN_SPAN(flags) &&
( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) {
Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ;
- if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
- #ifdef FS_GRAB_KEYBOARD
- if(TST_FLAG_CHANGE_FULLSCREEN(flags)) {
- if(TST_FLAG_IS_FULLSCREEN(flags)) {
- XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- } else {
- XUngrabKeyboard(dpy, CurrentTime);
- }
- } else if(TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags)) {
- XUngrabKeyboard(dpy, CurrentTime);
+ if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
+ if ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - restore decoration
+ NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True);
}
- #endif
+ DBG_PRINT( "X11: reconfigureWindow0 X (fs.atop.fast)\n");
+ return;
+ }
+ }
+ #endif
+ // Toggle ALWAYSONTOP (only) w/o visibility or window stacking sideffects
+ if( isVisible && fsEWMHFlags && TST_FLAG_CHANGE_ALWAYSONTOP(flags) &&
+ !TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_CHANGE_FULLSCREEN(flags) ) {
+ if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, TST_FLAG_IS_ALWAYSONTOP(flags)) ) {
+ DBG_PRINT( "X11: reconfigureWindow0 X (atop.fast)\n");
return;
}
}
@@ -802,21 +838,22 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
// no need to notify the java side .. just temp change
}
- if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) ||
- ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS off
- NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, False);
- #ifdef FS_GRAB_KEYBOARD
- XUngrabKeyboard(dpy, CurrentTime);
- #endif
+ if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) || // FS off
+ ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // AlwaysOnTop off
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False);
}
if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) {
// TOP: in -> out
DBG_PRINT( "X11: reconfigureWindow0 PARENTING in->out\n");
XReparentWindow( dpy, w, parent, x, y ); // actual reparent call
- // XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
+ XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #endif
XSync(dpy, False);
XSetWMProtocols(dpy, w, &wm_delete_atom, 1); // windowDeleteAtom
+ // Fix for Unity WM, i.e. _remove_ persistent previous states
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False);
}
if( TST_FLAG_CHANGE_DECORATION(flags) ) {
@@ -831,7 +868,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
// CHILD: out -> in
DBG_PRINT( "X11: reconfigureWindow0 PARENTING out->in\n");
XReparentWindow( dpy, w, parent, x, y ); // actual reparent call
- // XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
+ XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #endif
XSync(dpy, False);
}
@@ -840,32 +879,28 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
XMapRaised(dpy, w);
XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) w );
// no need to notify the java side .. just temp change
- }
-
- if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
+ } else if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
if( TST_FLAG_IS_VISIBLE(flags) ) {
DBG_PRINT( "X11: reconfigureWindow0 VISIBLE ON\n");
XMapRaised(dpy, w);
+ XSync(dpy, False);
+ // WM may disregard pos/size XConfigureWindow requests for invisible windows!
+ DBG_PRINT( "X11: reconfigureWindow0 setPosSize.2 %d/%d %dx%d\n", x, y, width, height);
+ NewtWindows_setPosSize(dpy, w, x, y, width, height);
} else {
DBG_PRINT( "X11: reconfigureWindow0 VISIBLE OFF\n");
XUnmapWindow(dpy, w);
+ XSync(dpy, False);
}
- XSync(dpy, False);
}
- if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) ||
- ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS on
- NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, True);
- #ifdef FS_GRAB_KEYBOARD
- if(TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags)) {
- XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- }
- #endif
+ if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) || // FS on
+ ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // AlwaysOnTop on
+ NewtWindows_requestFocus (dpy, w, True);
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, True);
}
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
-
- DBG_PRINT( "X11: reconfigureWindow0 X\n");
+ DBG_PRINT( "X11: reconfigureWindow0 X (full)\n");
}
/*
@@ -876,7 +911,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0
(JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force)
{
- NewtWindows_requestFocus ( env, obj, (Display *) (intptr_t) display, (Window)window, force ) ;
+ NewtWindows_requestFocus ( (Display *) (intptr_t) display, (Window)window, JNI_TRUE==force?True:False ) ;
}
/*
@@ -943,6 +978,27 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0
/*
* Class: Java_jogamp_newt_driver_x11_WindowDriver
+ * Method: setPointerIcon0
+ * Signature: (JJILjava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong handle)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window w = (Window)window;
+
+ if( 0 == handle ) {
+ DBG_PRINT( "X11: setPointerIcon0: reset\n");
+ XUndefineCursor(dpy, w);
+ } else {
+ Cursor c = (Cursor) (intptr_t) handle;
+ DBG_PRINT( "X11: setPointerIcon0: %p\n", (void*)c);
+ XDefineCursor(dpy, w, c);
+ }
+}
+
+/*
+ * Class: Java_jogamp_newt_driver_x11_WindowDriver
* Method: setPointerVisible0
* Signature: (JJZ)Z
*/
diff --git a/src/newt/native/XCBEvent.c b/src/newt/native/XCBEvent.c
new file mode 100644
index 000000000..d02d5a4ba
--- /dev/null
+++ b/src/newt/native/XCBEvent.c
@@ -0,0 +1,308 @@
+
+#define VERBOSE_ON 1
+
+#include "XCBEvent.h"
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_event.h>
+#include <xcb/xproto.h>
+#include <xcb/xcb_keysyms.h>
+#include <X11/Xlib-xcb.h>
+
+void XCBSetEventQueueOwner(Display *dpy) {
+ XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
+}
+
+void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom) {
+ int num_events = 100;
+ xcb_connection_t *conn = NULL;
+
+ if ( NULL == dpy ) {
+ return;
+ }
+ conn = XGetXCBConnection(dpy);
+
+ // Periodically take a break
+ while( num_events > 0 ) {
+ jobject jwindow = NULL;
+ xcb_generic_event_t *evt;
+ // KeySym keySym = 0;
+ jint modifiers = 0;
+ char keyChar = 0;
+ // char text[255];
+
+ evt = xcb_poll_for_event(conn);
+ if(NULL == evt) {
+ // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
+ return;
+ }
+ num_events--;
+
+ /*if( 0==evt.xany.window ) {
+ free(evt);
+ NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!");
+ return ;
+ }
+
+ if(dpy!=evt.xany.display) {
+ free(evt);
+ NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
+ return ;
+ }*/
+
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, evt.type);
+
+ // X11WindowDisplayErrorHandlerEnable(1, env);
+
+ // jwindow = X11WindowGetJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, VERBOSE_BOOL);
+
+ //X11WindowDisplayErrorHandlerEnable(0, env);
+
+ /*if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
+ (void*)dpy, evt.type, (void*)evt.xany.window);
+ continue;
+ }*/
+
+ uint8_t xcb_event_type = evt->response_type & ~0x80;
+ xcb_window_t event_window = 0;
+
+ switch( xcb_event_type ) {
+ case XCB_BUTTON_PRESS:
+ case XCB_BUTTON_RELEASE:
+ event_window = ((xcb_button_press_event_t *)evt)->event;
+ modifiers = X11InputState2NewtModifiers(((xcb_button_press_event_t *)evt)->state);
+ break;
+ case XCB_MOTION_NOTIFY:
+ event_window = ((xcb_motion_notify_event_t *)evt)->event;
+ break;
+ case XCB_KEY_PRESS:
+ case XCB_KEY_RELEASE: {
+ xcb_key_press_event_t *_evt = (xcb_key_press_event_t *)evt;
+ event_window = _evt->event;
+ /*
+ xcb_keycode_t detail = _evt->detail;
+ if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
+ KeySym lower_return = 0, upper_return = 0;
+ keyChar=text[0];
+ XConvertCase(keySym, &lower_return, &upper_return);
+ // always return upper case, set modifier masks (SHIFT, ..)
+ keySym = upper_return;
+ modifiers = X11InputState2NewtModifiers(evt.xkey.state);
+ } else {
+ keyChar=0;
+ }*/
+ }
+ break;
+ case XCB_EXPOSE:
+ event_window = ((xcb_expose_event_t *)evt)->window;
+ break;
+ case XCB_MAP_NOTIFY:
+ event_window = ((xcb_map_notify_event_t *)evt)->window;
+ break;
+ case XCB_UNMAP_NOTIFY:
+ event_window = ((xcb_unmap_notify_event_t *)evt)->window;
+ break;
+ }
+ if(0==event_window) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d, no X11 window associated\n",
+ (void*)dpy, xcb_event_type);
+ continue;
+ }
+ jwindow = getJavaWindowProperty(env, dpy, event_window, javaObjectAtom,
+ #ifdef VERBOSE_ON
+ True
+ #else
+ False
+ #endif
+ );
+ if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
+ (void*)(intptr_t)dpy, xcb_event_type, (void*)(intptr_t)event_window);
+ continue;
+ }
+
+ switch( xcb_event_type ) {
+ case XCB_BUTTON_PRESS: {
+ xcb_button_press_event_t *_evt = (xcb_button_press_event_t *)evt;
+ (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #endif
+ } break;
+ case XCB_BUTTON_RELEASE: {
+ xcb_button_release_event_t *_evt = (xcb_button_release_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #endif
+ } break;
+ case XCB_MOTION_NOTIFY: {
+ xcb_motion_notify_event_t *_evt = (xcb_motion_notify_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/);
+ #endif
+ } break;
+ case XCB_KEY_PRESS: {
+ xcb_key_press_event_t *_evt = (xcb_key_press_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #endif
+ } break;
+ case XCB_KEY_RELEASE: {
+ xcb_key_release_event_t *_evt = (xcb_key_release_event_t *)evt;
+ event_window = ((xcb_key_release_event_t *)evt)->event;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #endif
+
+ } break;
+ /*
+ case DestroyNotify:
+ DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
+ (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event);
+ if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) {
+ // ignore child destroy notification
+ }
+ break;
+ case CreateNotify:
+ DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n",
+ (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent);
+ break;
+ case ConfigureNotify:
+ DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n",
+ (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above,
+ evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height,
+ evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event);
+ if ( evt.xconfigure.window == evt.xconfigure.event ) {
+ // ignore child window change notification
+ (*env)->CallVoidMethod(env, jwindow, sizeChangedID,
+ (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
+ (*env)->CallVoidMethod(env, jwindow, positionChangedID,
+ (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
+ }
+ break;
+ case ClientMessage:
+ if (evt.xclient.send_event==True && evt.xclient.data.l[0]==(Atom)wmDeleteAtom) {
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X !!!\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
+ (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID);
+ // Called by Window.java: CloseWindow();
+ num_events = 0; // end loop in case of destroyed display
+ }
+ break;
+
+ case FocusIn:
+ DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_TRUE);
+ break;
+
+ case FocusOut:
+ DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE);
+ break;
+ */
+
+ case XCB_EXPOSE: {
+ xcb_expose_event_t *_evt = (xcb_expose_event_t *)evt;
+ DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)(intptr_t)_evt->window,
+ _evt->x, _evt->y, _evt->width, _evt->height, _evt->count);
+
+ if (_evt->count == 0 && _evt->width > 0 && _evt->height > 0) {
+ (*env)->CallVoidMethod(env, jwindow, windowRepaintID,
+ _evt->x, _evt->y, _evt->width, _evt->height);
+ }
+ } break;
+
+ case XCB_MAP_NOTIFY: {
+ xcb_map_notify_event_t *_evt = (xcb_map_notify_event_t *)evt;
+ DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n",
+ (void*)(intptr_t)_evt->event, (void*)(intptr_t)_evt->window, (int)_evt->override_redirect,
+ _evt->event!=_evt->window);
+ if( _evt->event == _evt->window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE);
+ }
+ } break;
+
+ case XCB_UNMAP_NOTIFY: {
+ xcb_unmap_notify_event_t *_evt = (xcb_unmap_notify_event_t *)evt;
+ DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, child-event: %d\n",
+ (void*)(intptr_t)_evt->event, (void*)(intptr_t)_evt->window,
+ _evt->event!=_evt->window);
+ if( _evt->event == _evt->window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE);
+ }
+ } break;
+ /*
+
+ case ReparentNotify:
+ {
+ jlong parentResult; // 0 if root, otherwise proper value
+ Window winRoot, winTopParent;
+ #ifdef VERBOSE_ON
+ Window oldParentRoot, oldParentTopParent;
+ Window parentRoot, parentTopParent;
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) {
+ oldParentRoot=0; oldParentTopParent = 0;
+ }
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) {
+ parentRoot=0; parentTopParent = 0;
+ }
+ #endif
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) {
+ winRoot=0; winTopParent = 0;
+ }
+ if(evt.xreparent.parent == winRoot) {
+ parentResult = 0; // our java indicator for root window
+ } else {
+ parentResult = (jlong) (intptr_t) evt.xreparent.parent;
+ }
+ #ifdef VERBOSE_ON
+ DBG_PRINT( "X11: event . ReparentNotify: call OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n",
+ (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent,
+ (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent,
+ (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
+ #endif
+
+ (*env)->CallVoidMethod(env, jwindow, windowReparentedID, parentResult);
+ }
+ break;
+ */
+
+ // unhandled events .. yet ..
+
+ default:
+ DBG_PRINT("XCB: event . unhandled %d 0x%X call %p\n", (int)xcb_event_type, (unsigned int)xcb_event_type, (void*)(intptr_t)event_window);
+ }
+ free(evt);
+ }
+}
+
+
diff --git a/src/newt/native/XCBEvent.h b/src/newt/native/XCBEvent.h
new file mode 100644
index 000000000..d70797566
--- /dev/null
+++ b/src/newt/native/XCBEvent.h
@@ -0,0 +1,10 @@
+
+#ifndef _XCBEvent_h
+#define _XCBEvent_h
+
+#include "X11Common.h"
+
+extern void XCBSetEventQueueOwner(Display *dpy);
+extern void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom);
+
+#endif /* _XCBDisplayXCBEvent_h */
diff --git a/src/newt/native/bcm_vc_iv.c b/src/newt/native/bcm_vc_iv.c
index e41745e14..ee59f0aa6 100644
--- a/src/newt/native/bcm_vc_iv.c
+++ b/src/newt/native/bcm_vc_iv.c
@@ -30,28 +30,50 @@
#include <stdio.h>
#include <string.h>
+/**
+ * See references in header file.
+ */
#include "bcm_vc_iv.h"
#include "jogamp_newt_driver_bcm_vc_iv_DisplayDriver.h"
#include "jogamp_newt_driver_bcm_vc_iv_ScreenDriver.h"
#include "jogamp_newt_driver_bcm_vc_iv_WindowDriver.h"
-#define VERBOSE_ON 1
+// #define VERBOSE_ON 1
#ifdef VERBOSE_ON
- #define DBG_PRINT(...) fprintf(stdout, __VA_ARGS__)
+ #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
#else
#define DBG_PRINT(...)
#endif
+typedef struct {
+ DISPMANX_ELEMENT_HANDLE_T handle; // magic BCM EGL position (EGL_DISPMANX_WINDOW_T)
+ int width; // magic BCM EGL position (EGL_DISPMANX_WINDOW_T)
+ int height; // magic BCM EGL position (EGL_DISPMANX_WINDOW_T)
+ int x;
+ int y;
+ int32_t layer;
+} BCM_ELEMENT_T;
+
+typedef struct {
+ DISPMANX_RESOURCE_HANDLE_T handle;
+ VC_IMAGE_TYPE_T type;
+ uint32_t native_image_handle;
+} BCM_RESOURCE_T;
+
+typedef struct {
+ BCM_ELEMENT_T element;
+ BCM_RESOURCE_T resource;
+ int hotX, hotY;
+} POINTER_ICON_T;
+
static jmethodID setScreenSizeID = NULL;
-static jmethodID windowCreatedID = NULL;
static jmethodID sizeChangedID = NULL;
+static jmethodID positionChangedID = NULL;
static jmethodID visibleChangedID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
-static jmethodID sendMouseEventID = NULL;
-static jmethodID sendKeyEventID = NULL;
/**
* Display
@@ -66,11 +88,210 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_initI
return JNI_TRUE;
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_DispatchMessages
- (JNIEnv *env, jobject obj)
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_OpenBCMDisplay0
+ (JNIEnv *env, jclass clazz)
+{
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
+ DBG_PRINT( "BCM.Display Open %p\n", (void*)(intptr_t)dispman_display);
+ return (jlong) (intptr_t) dispman_display;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_CloseBCMDisplay0
+ (JNIEnv *env, jclass clazz, jlong display)
+{
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+ DBG_PRINT( "BCM.Display Close %p\n", (void*)(intptr_t)dispman_display);
+ vc_dispmanx_display_close( dispman_display );
+}
+
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_DispatchMessages0
+ (JNIEnv *env, jclass clazz)
{
}
+static void bcm_moveTo(DISPMANX_ELEMENT_HANDLE_T element, uint32_t layer, int x, int y, int width, int height) {
+ VC_RECT_T src_rect;
+ VC_RECT_T dst_rect;
+ uint32_t change_flags = DISPMANX_ELEMENT_CHANGE_DEST_RECT | DISPMANX_ELEMENT_CHANGE_SRC_RECT;
+ DISPMANX_RESOURCE_HANDLE_T mask = 0;
+ DISPMANX_TRANSFORM_T transform = 0;
+
+ uint8_t opacity = 0; // NOP
+
+ dst_rect.x = x;
+ dst_rect.y = y;
+ dst_rect.width = width;
+ dst_rect.height = height;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = width << 16;
+ src_rect.height = height << 16;
+
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_change_attributes( dispman_update,
+ element,
+ change_flags,
+ layer,
+ opacity,
+ &dst_rect,
+ &src_rect,
+ mask,
+ transform );
+ vc_dispmanx_update_submit_sync( dispman_update );
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_CreatePointerIcon0
+ (JNIEnv *env, jclass clazz, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
+{
+ if( 0 == pixels ) {
+ return 0;
+ }
+ int32_t success = 0;
+ VC_RECT_T dst_rect;
+ VC_RECT_T src_rect;
+ int x = 0;
+ int y = 0;
+ int pitch = width * 4; // RGBA
+
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+
+ POINTER_ICON_T * p = calloc(1, sizeof(POINTER_ICON_T));
+ p->hotX = hotX;
+ p->hotY = hotY;
+ p->element.layer = 2000;
+ p->element.x = x;
+ p->element.y = y;
+ p->element.width = width;
+ p->element.height = height;
+ p->resource.type = VC_IMAGE_ARGB8888; /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
+ p->resource.handle = vc_dispmanx_resource_create( p->resource.type,
+ width,
+ height,
+ &(p->resource.native_image_handle) );
+
+ dst_rect.x = x;
+ dst_rect.y = y;
+ dst_rect.width = width;
+ dst_rect.height = height;
+
+ vc_dispmanx_resource_write_data( p->resource.handle,
+ p->resource.type,
+ pitch,
+ (void*)(intptr_t)(pixelPtr + pixels_byte_offset),
+ &dst_rect );
+
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
+ DBG_PRINT( "BCM.Display PointerIcon.Create PI %p, resource %p\n", p, (void*)(intptr_t)p->resource.handle);
+ return (jlong) (intptr_t) p;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_DestroyPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong handle)
+{
+ POINTER_ICON_T * p = (POINTER_ICON_T *) (intptr_t) handle ;
+ if( 0 == p ) {
+ return;
+ }
+
+ DBG_PRINT( "BCM.Display PointerIcon.Destroy.0 PI %p, resource %p, element %p\n",
+ p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle);
+
+ if( 0 != p->element.handle ) {
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_remove( dispman_update, p->element.handle );
+ p->element.handle = 0;
+ vc_dispmanx_update_submit_sync( dispman_update );
+ }
+ if( 0 != p->resource.handle ) {
+ vc_dispmanx_resource_delete( p->resource.handle );
+ p->resource.handle = 0;
+ }
+ free( p );
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_SetPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jlong handle, jboolean enable, jint x, jint y)
+{
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+ POINTER_ICON_T * p = (POINTER_ICON_T *) (intptr_t) handle ;
+ VC_RECT_T dst_rect;
+ VC_RECT_T src_rect;
+
+ if( 0 == dispman_display || NULL == p || 0 == p->resource.handle ) {
+ return;
+ }
+
+ DBG_PRINT( "BCM.Display PointerIcon.Set.0 %p, PI %p, resource %p, element %p - enable %d - %d/%d\n",
+ (void*)(intptr_t)display, p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle, enable, x, y);
+
+ if( enable ) {
+ if( 0 != p->element.handle ) {
+ return;
+ }
+
+ p->element.x = x;
+ p->element.y = y;
+ dst_rect.x = p->element.x - p->hotX;
+ dst_rect.y = p->element.y - p->hotY;
+ dst_rect.width = p->element.width;
+ dst_rect.height = p->element.height;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = p->element.width << 16;
+ src_rect.height = p->element.height << 16;
+
+ VC_DISPMANX_ALPHA_T dispman_alpha;
+ memset(&dispman_alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
+ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE ;
+ dispman_alpha.opacity = 0xFF;
+ dispman_alpha.mask = 0xFF;
+
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ p->element.handle = vc_dispmanx_element_add ( dispman_update, dispman_display,
+ p->element.layer, &dst_rect,
+ p->resource.handle /*src*/,
+ &src_rect, DISPMANX_PROTECTION_NONE,
+ &dispman_alpha /*alpha */, 0/*clamp*/, 0/*transform*/);
+ vc_dispmanx_update_submit_sync( dispman_update );
+ } else {
+ // DISABLE
+ if( 0 == p->element.handle ) {
+ return;
+ }
+ p->element.x = x;
+ p->element.y = y;
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_remove( dispman_update, p->element.handle );
+ p->element.handle = 0;
+ vc_dispmanx_update_submit_sync( dispman_update );
+ }
+ DBG_PRINT( "BCM.Display PointerIcon.Set.X %p, PI %p, resource %p, element %p - enable %d - %d/%d\n",
+ (void*)(intptr_t)display, p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle, enable, x, y);
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_MovePointerIcon0
+ (JNIEnv *env, jclass clazz, jlong handle, jint x, jint y)
+{
+ POINTER_ICON_T * p = (POINTER_ICON_T *) (intptr_t) handle ;
+
+ if( NULL == p || 0 == p->element.handle ) {
+ return;
+ }
+ DBG_PRINT( "BCM.Display PointerIcon.Move.0 PI %p, resource %p, element %p - %d/%d\n",
+ p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle, x, y);
+ p->element.x = x;
+ p->element.y = y;
+ bcm_moveTo( p->element.handle, p->element.layer, p->element.x - p->hotX, p->element.y - p->hotY, p->element.width, p->element.height);
+}
+
/**
* Screen
*/
@@ -101,8 +322,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_ScreenDriver_initNative
if( graphics_get_display_size(0 /* LCD */, &screen_width, &screen_height) >= 0 ) {
DBG_PRINT( "BCM.Screen initNative ok %dx%d\n", screen_width, screen_height );
(*env)->CallVoidMethod(env, obj, setScreenSizeID, (jint) screen_width, (jint) screen_height);
+ } else {
+ DBG_PRINT( "BCM.Screen initNative failed\n" );
}
- DBG_PRINT( "BCM.Screen initNative failed\n" );
}
/**
@@ -112,18 +334,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_ScreenDriver_initNative
JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_initIDs
(JNIEnv *env, jclass clazz)
{
- windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V");
sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
+ positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V");
visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
- if (windowCreatedID == NULL ||
- sizeChangedID == NULL ||
+ if (sizeChangedID == NULL ||
+ positionChangedID == NULL ||
visibleChangedID == NULL ||
- windowDestroyNotifyID == NULL ||
- sendMouseEventID == NULL ||
- sendKeyEventID == NULL) {
+ windowDestroyNotifyID == NULL) {
DBG_PRINT( "initIDs failed\n" );
return JNI_FALSE;
}
@@ -131,15 +349,18 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_initID
return JNI_TRUE;
}
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CreateWindow
- (JNIEnv *env, jobject obj, jint width, jint height)
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CreateWindow0
+ (JNIEnv *env, jobject obj, jlong display, jint layer, jint x, jint y, jint width, jint height, jboolean opaque, jint alphaBits)
{
int32_t success = 0;
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
- dst_rect.x = 0;
- dst_rect.y = 0;
+ if( 0 == display ) {
+ return;
+ }
+ dst_rect.x = x;
+ dst_rect.y = y;
dst_rect.width = width;
dst_rect.height = height;
@@ -148,57 +369,95 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CreateWin
src_rect.width = width << 16;
src_rect.height = height << 16;
- DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
+ VC_DISPMANX_ALPHA_T dispman_alpha;
+ memset(&dispman_alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
+
+ if( JNI_TRUE == opaque ) {
+ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS ;
+ dispman_alpha.opacity = 0xFF;
+ dispman_alpha.mask = 0;
+ } else {
+ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE ;
+ dispman_alpha.opacity = 0xFF;
+ dispman_alpha.mask = 0xFF;
+ }
+
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+
+ DBG_PRINT( "BCM.Display Window.Create.0 %p, %d/%d %dx%d, opaque %d, alphaBits %d, layer %d\n",
+ (void*)(intptr_t)dispman_display, x, y, width, height, opaque, alphaBits, layer);
+
+ BCM_ELEMENT_T * p = calloc(1, sizeof(BCM_ELEMENT_T));
DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
- DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
- 0/*layer*/, &dst_rect, 0/*src*/,
- &src_rect, DISPMANX_PROTECTION_NONE,
- 0 /*alpha TODO*/, 0/*clamp*/, 0/*transform*/);
- EGL_DISPMANX_WINDOW_T * nativeWindowPtr = calloc(1, sizeof(EGL_DISPMANX_WINDOW_T));
- nativeWindowPtr->element = dispman_element;
- nativeWindowPtr->width = width;
- nativeWindowPtr->height = height;
+ p->layer = layer;
+ p->x = x;
+ p->y = y;
+ p->width = width;
+ p->height = height;
+ p->handle = vc_dispmanx_element_add ( dispman_update, dispman_display,
+ p->layer, &dst_rect, 0/*src*/,
+ &src_rect, DISPMANX_PROTECTION_NONE,
+ &dispman_alpha /*alpha */, 0/*clamp*/, 0/*transform*/);
vc_dispmanx_update_submit_sync( dispman_update );
(*env)->CallVoidMethod(env, obj, visibleChangedID, JNI_FALSE, JNI_TRUE); // FIXME: or defer=true ?
- return (jlong) (intptr_t) nativeWindowPtr;
-}
+ DBG_PRINT( "BCM.Display Window.Create.X %p, element %p\n",
+ (void*)(intptr_t)dispman_display, (void*)(intptr_t)p->handle);
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_RealizeWindow
- (JNIEnv *env, jobject obj, jlong window)
-{
- return (jlong) (intptr_t) 0;
+ return (jlong) (intptr_t) p;
}
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CloseWindow
- (JNIEnv *env, jobject obj, jlong window, jlong juserData)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CloseWindow0
+ (JNIEnv *env, jobject obj, jlong display, jlong window)
{
- EGL_DISPMANX_WINDOW_T * nativeWindowPtr = (EGL_DISPMANX_WINDOW_T *) (intptr_t) window ;
- free( nativeWindowPtr );
- return 0;
-}
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+ BCM_ELEMENT_T * p = (BCM_ELEMENT_T *) (intptr_t) window ;
-/*
- * Class: jogamp_newt_driver_bcm_vc_iv_WindowDriver
- * Method: setVisible0
- * Signature: (JJZ)V
- */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_setVisible0
- (JNIEnv *env, jobject obj, jlong window, jboolean visible)
-{
-}
+ DBG_PRINT( "BCM.Display Window.Close %p, element %p\n",
+ (void*)(intptr_t)dispman_display, (void*)(intptr_t)p->handle);
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_setFullScreen0
- (JNIEnv *env, jobject obj, jlong window, jboolean fullscreen)
-{
+ if( 0 == dispman_display || NULL == p || 0 == p->handle ) {
+ return;
+ }
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_remove( dispman_update, p->handle );
+ p->handle = 0;
+ vc_dispmanx_update_submit_sync( dispman_update );
+ free( p );
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_setSize0
- (JNIEnv *env, jobject obj, jlong window, jint width, jint height)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_reconfigure0
+ (JNIEnv *env, jobject obj, jlong window, jint x, jint y, jint width, jint height, jint flags)
{
- // FIXME RESIZE (*env)->CallVoidMethod(env, obj, sizeChangedID, JNI_FALSE, (jint) width, (jint) height, JNI_FALSE);
-}
+ BCM_ELEMENT_T * p = (BCM_ELEMENT_T *) (intptr_t) window ;
+
+ if( NULL == p || 0 == p->handle ) {
+ return;
+ }
+ /***
+ int isVisible = !TST_FLAG_CHANGE_VISIBILITY(flags) && TST_FLAG_IS_VISIBLE(flags) ;
+ ...
+ see X11Window.c
+ */
+ int posChanged = p->x != x || p->y != y;
+ int sizeChanged = p->width != width || p->height != height;
+ p->x = x;
+ p->y = y;
+ p->width = width;
+ p->height = height;
+
+ DBG_PRINT( "BCM.Display Window.Reconfig %p, element %p - %d/%d %dx%d\n",
+ p, (void*)(intptr_t)p->handle, p->x, p->y, p->width, p->height);
+
+ bcm_moveTo( p->handle, p->layer, p->x, p->y, p->width, p->height);
+ if( posChanged ) {
+ (*env)->CallVoidMethod(env, obj, positionChangedID, JNI_FALSE, x, y);
+ }
+ if( sizeChanged ) {
+ (*env)->CallVoidMethod(env, obj, sizeChangedID, JNI_FALSE, (jint) width, (jint) height, JNI_FALSE);
+ }
+}
diff --git a/src/newt/native/bcm_vc_iv.h b/src/newt/native/bcm_vc_iv.h
index b43483c10..42189f3d6 100644
--- a/src/newt/native/bcm_vc_iv.h
+++ b/src/newt/native/bcm_vc_iv.h
@@ -29,6 +29,11 @@
#ifndef BCM_VC_IV_H
#define BCM_VC_IV_H
+/**
+ * http://en.wikipedia.org/wiki/VideoCore
+ * https://github.com/raspberrypi/userland
+ */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -150,12 +155,6 @@ typedef struct {
} DISPMANX_CLAMP_T;
-typedef struct {
- DISPMANX_ELEMENT_HANDLE_T element;
- int width; /* This is necessary because dispmanx elements are not queriable. */
- int height;
-} EGL_DISPMANX_WINDOW_T;
-
typedef struct tag_VC_RECT_T {
int32_t x;
int32_t y;
@@ -163,6 +162,102 @@ typedef struct tag_VC_RECT_T {
int32_t height;
} VC_RECT_T;
+/* Types of image supported. */
+/* Please add any new types to the *end* of this list. Also update
+ * case_VC_IMAGE_ANY_xxx macros (below), and the vc_image_type_info table in
+ * vc_image/vc_image_helper.c.
+ */
+typedef enum
+{
+ VC_IMAGE_MIN = 0, //bounds for error checking
+
+ VC_IMAGE_RGB565 = 1,
+ VC_IMAGE_1BPP,
+ VC_IMAGE_YUV420,
+ VC_IMAGE_48BPP,
+ VC_IMAGE_RGB888,
+ VC_IMAGE_8BPP,
+ VC_IMAGE_4BPP, // 4bpp palettised image
+ VC_IMAGE_3D32, /* A separated format of 16 colour/light shorts followed by 16 z values */
+ VC_IMAGE_3D32B, /* 16 colours followed by 16 z values */
+ VC_IMAGE_3D32MAT, /* A separated format of 16 material/colour/light shorts followed by 16 z values */
+ VC_IMAGE_RGB2X9, /* 32 bit format containing 18 bits of 6.6.6 RGB, 9 bits per short */
+ VC_IMAGE_RGB666, /* 32-bit format holding 18 bits of 6.6.6 RGB */
+ VC_IMAGE_PAL4_OBSOLETE, // 4bpp palettised image with embedded palette
+ VC_IMAGE_PAL8_OBSOLETE, // 8bpp palettised image with embedded palette
+ VC_IMAGE_RGBA32, /* RGB888 with an alpha byte after each pixel */ /* xxx: isn't it BEFORE each pixel? */
+ VC_IMAGE_YUV422, /* a line of Y (32-byte padded), a line of U (16-byte padded), and a line of V (16-byte padded) */
+ VC_IMAGE_RGBA565, /* RGB565 with a transparent patch */
+ VC_IMAGE_RGBA16, /* Compressed (4444) version of RGBA32 */
+ VC_IMAGE_YUV_UV, /* VCIII codec format */
+ VC_IMAGE_TF_RGBA32, /* VCIII T-format RGBA8888 */
+ VC_IMAGE_TF_RGBX32, /* VCIII T-format RGBx8888 */
+ VC_IMAGE_TF_FLOAT, /* VCIII T-format float */
+ VC_IMAGE_TF_RGBA16, /* VCIII T-format RGBA4444 */
+ VC_IMAGE_TF_RGBA5551, /* VCIII T-format RGB5551 */
+ VC_IMAGE_TF_RGB565, /* VCIII T-format RGB565 */
+ VC_IMAGE_TF_YA88, /* VCIII T-format 8-bit luma and 8-bit alpha */
+ VC_IMAGE_TF_BYTE, /* VCIII T-format 8 bit generic sample */
+ VC_IMAGE_TF_PAL8, /* VCIII T-format 8-bit palette */
+ VC_IMAGE_TF_PAL4, /* VCIII T-format 4-bit palette */
+ VC_IMAGE_TF_ETC1, /* VCIII T-format Ericsson Texture Compressed */
+ VC_IMAGE_BGR888, /* RGB888 with R & B swapped */
+ VC_IMAGE_BGR888_NP, /* RGB888 with R & B swapped, but with no pitch, i.e. no padding after each row of pixels */
+ VC_IMAGE_BAYER, /* Bayer image, extra defines which variant is being used */
+ VC_IMAGE_CODEC, /* General wrapper for codec images e.g. JPEG from camera */
+ VC_IMAGE_YUV_UV32, /* VCIII codec format */
+ VC_IMAGE_TF_Y8, /* VCIII T-format 8-bit luma */
+ VC_IMAGE_TF_A8, /* VCIII T-format 8-bit alpha */
+ VC_IMAGE_TF_SHORT,/* VCIII T-format 16-bit generic sample */
+ VC_IMAGE_TF_1BPP, /* VCIII T-format 1bpp black/white */
+ VC_IMAGE_OPENGL,
+ VC_IMAGE_YUV444I, /* VCIII-B0 HVS YUV 4:4:4 interleaved samples */
+ VC_IMAGE_YUV422PLANAR, /* Y, U, & V planes separately (VC_IMAGE_YUV422 has them interleaved on a per line basis) */
+ VC_IMAGE_ARGB8888, /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
+ VC_IMAGE_XRGB8888, /* 32bpp with 8bit unused at MS byte, with R, G, B (LS byte) */
+
+ VC_IMAGE_YUV422YUYV, /* interleaved 8 bit samples of Y, U, Y, V */
+ VC_IMAGE_YUV422YVYU, /* interleaved 8 bit samples of Y, V, Y, U */
+ VC_IMAGE_YUV422UYVY, /* interleaved 8 bit samples of U, Y, V, Y */
+ VC_IMAGE_YUV422VYUY, /* interleaved 8 bit samples of V, Y, U, Y */
+
+ VC_IMAGE_RGBX32, /* 32bpp like RGBA32 but with unused alpha */
+ VC_IMAGE_RGBX8888, /* 32bpp, corresponding to RGBA with unused alpha */
+ VC_IMAGE_BGRX8888, /* 32bpp, corresponding to BGRA with unused alpha */
+
+ VC_IMAGE_YUV420SP, /* Y as a plane, then UV byte interleaved in plane with with same pitch, half height */
+
+ VC_IMAGE_YUV444PLANAR, /* Y, U, & V planes separately 4:4:4 */
+
+ VC_IMAGE_MAX, //bounds for error checking
+ VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
+} VC_IMAGE_TYPE_T;
+
+/**
+ * From https://github.com/raspberrypi/userland/blob/master/interface/vmcs_host/vc_vchi_dispmanx.h
+ */
+typedef enum {
+ DISPMANX_ELEMENT_CHANGE_LAYER = (1<<0),
+ DISPMANX_ELEMENT_CHANGE_OPACITY = (1<<1),
+ DISPMANX_ELEMENT_CHANGE_DEST_RECT = (1<<2),
+ DISPMANX_ELEMENT_CHANGE_SRC_RECT = (1<<3),
+ DISPMANX_ELEMENT_CHANGE_MASK_RESOURCE = (1<<4),
+ DISPMANX_ELEMENT_CHANGE_TRANSFORM = (1<<5)
+/**
+ * Not working /validated !
+ DISPMANX_ELEMENT_CHANGE_MIN = 0x00,
+ DISPMANX_ELEMENT_CHANGE_SOURCE = 0x01,
+ DISPMANX_ELEMENT_INSERT_ABOVE = 0x80,
+ DISPMANX_ELEMENT_CHANGE_FLAGS = 0x100,
+ DISPMANX_ELEMENT_CHANGE_NOTHING = 0x200,
+ DISPMANX_ELEMENT_CHANGE_ALPHA_FLAGS = 0x400,
+ DISPMANX_ELEMENT_CHANGE_PROTECTION = 0x800,
+ DISPMANX_ELEMENT_CHANGE_MAX = 0x1000
+ */
+} DISPMANX_ELEMENT_CHANGE_T;
+
+
+
extern void bcm_host_init(void);
extern void bcm_host_deinit(void);
@@ -171,15 +266,38 @@ extern int32_t graphics_get_display_size( const uint16_t display_number,
uint32_t *height);
extern DISPMANX_DISPLAY_HANDLE_T vc_dispmanx_display_open( uint32_t device );
+extern int vc_dispmanx_display_close( DISPMANX_DISPLAY_HANDLE_T display );
+
+extern DISPMANX_RESOURCE_HANDLE_T vc_dispmanx_resource_create(VC_IMAGE_TYPE_T type, uint32_t width, uint32_t height, uint32_t *native_image_handle);
+extern int vc_dispmanx_resource_write_data( DISPMANX_RESOURCE_HANDLE_T res, VC_IMAGE_TYPE_T src_type, int src_pitch, void * src_address, const VC_RECT_T * rect );
+//extern int vc_dispmanx_resource_write_data_handle( DISPMANX_RESOURCE_HANDLE_T res, VC_IMAGE_TYPE_T src_type, int src_pitch,
+// VCHI_MEM_HANDLE_T handle, uint32_t offset, const VC_RECT_T * rect );
+extern int vc_dispmanx_resource_delete( DISPMANX_RESOURCE_HANDLE_T res );
+
+
+
extern DISPMANX_UPDATE_HANDLE_T vc_dispmanx_update_start( int32_t priority );
extern DISPMANX_ELEMENT_HANDLE_T vc_dispmanx_element_add ( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display,
int32_t layer, const VC_RECT_T *dest_rect, DISPMANX_RESOURCE_HANDLE_T src,
const VC_RECT_T *src_rect, DISPMANX_PROTECTION_T protection,
VC_DISPMANX_ALPHA_T *alpha,
DISPMANX_CLAMP_T *clamp, DISPMANX_TRANSFORM_T transform );
+extern int vc_dispmanx_element_remove( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element );
+
extern int vc_dispmanx_update_submit_sync( DISPMANX_UPDATE_HANDLE_T update );
+//New function added to VCHI to change attributes, set_opacity does not work there.
+extern int vc_dispmanx_element_change_attributes( DISPMANX_UPDATE_HANDLE_T update,
+ DISPMANX_ELEMENT_HANDLE_T element,
+ uint32_t change_flags,
+ int32_t layer,
+ uint8_t opacity,
+ const VC_RECT_T *dest_rect,
+ const VC_RECT_T *src_rect,
+ DISPMANX_RESOURCE_HANDLE_T mask,
+ DISPMANX_TRANSFORM_T transform );
+
#ifdef __cplusplus
}
#endif
diff --git a/src/oculusvr/classes/com/jogamp/oculusvr/OVRDynamicLibraryBundleInfo.java b/src/oculusvr/classes/com/jogamp/oculusvr/OVRDynamicLibraryBundleInfo.java
new file mode 100644
index 000000000..86041b35d
--- /dev/null
+++ b/src/oculusvr/classes/com/jogamp/oculusvr/OVRDynamicLibraryBundleInfo.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.oculusvr;
+
+import com.jogamp.common.jvm.JNILibLoaderBase;
+import com.jogamp.common.os.DynamicLibraryBundle;
+import com.jogamp.common.os.DynamicLibraryBundleInfo;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.RunnableExecutor;
+import com.jogamp.common.util.cache.TempJarCache;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+
+/* pp */ final class OVRDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
+ private static final List<String> glueLibNames;
+ static {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ Platform.initSingleton();
+
+ if(TempJarCache.isInitialized()) {
+ // only: oculusvr.jar -> oculusvr-natives-<os.and.arch>.jar
+ JNILibLoaderBase.addNativeJarLibs(new Class<?>[] { com.jogamp.oculusvr.OVRDynamicLibraryBundleInfo.class }, null);
+ }
+ return null;
+ }
+ });
+
+ glueLibNames = new ArrayList<String>();
+ glueLibNames.add("oculusvr");
+ }
+
+ /* pp */ OVRDynamicLibraryBundleInfo() {
+ }
+
+ /**
+ * <p>
+ * Returns <code>true</code>,
+ * since we might load the library and allow symbol access to subsequent libs.
+ * </p>
+ */
+ @Override
+ public final boolean shallLinkGlobal() { return true; }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns <code>false</code>.
+ * </p>
+ */
+ @Override
+ public final boolean shallLookupGlobal() { return true; }
+
+ @Override
+ public final List<String> getGlueLibNames() {
+ return glueLibNames;
+ }
+
+ @Override
+ public final List<List<String>> getToolLibNames() {
+ return new ArrayList<List<String>>(); // None
+ }
+
+ @Override
+ public final List<String> getToolGetProcAddressFuncNameList() {
+ return null;
+ }
+
+ @Override
+ public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) {
+ return 0;
+ }
+
+ @Override
+ public final boolean useToolGetProcAdressFirst(final String funcName) {
+ return false;
+ }
+
+ @Override
+ public final RunnableExecutor getLibLoaderExecutor() {
+ return DynamicLibraryBundle.getDefaultRunnableExecutor();
+ }
+}
+
+
diff --git a/src/oculusvr/classes/com/jogamp/oculusvr/OVRException.java b/src/oculusvr/classes/com/jogamp/oculusvr/OVRException.java
new file mode 100644
index 000000000..f2a254e14
--- /dev/null
+++ b/src/oculusvr/classes/com/jogamp/oculusvr/OVRException.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.oculusvr;
+
+/** A generic exception for OculusVR errors used throughout the binding
+ as a substitute for {@link RuntimeException}. */
+@SuppressWarnings("serial")
+public class OVRException extends RuntimeException {
+ /** Constructs an ALException object. */
+ public OVRException() {
+ super();
+ }
+
+ /** Constructs an ALException object with the specified detail
+ message. */
+ public OVRException(final String message) {
+ super(message);
+ }
+
+ /** Constructs an ALException object with the specified detail
+ message and root cause. */
+ public OVRException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ /** Constructs an ALException object with the specified root
+ cause. */
+ public OVRException(final Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/src/oculusvr/classes/com/jogamp/oculusvr/OVRVersion.java b/src/oculusvr/classes/com/jogamp/oculusvr/OVRVersion.java
new file mode 100644
index 000000000..cf6eb5dda
--- /dev/null
+++ b/src/oculusvr/classes/com/jogamp/oculusvr/OVRVersion.java
@@ -0,0 +1,155 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.oculusvr;
+
+import com.jogamp.common.GlueGenVersion;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.common.util.JogampVersion;
+import com.jogamp.oculusvr.OVR;
+import com.jogamp.oculusvr.OvrHmdContext;
+import com.jogamp.oculusvr.ovrHmdDesc;
+import com.jogamp.oculusvr.ovrSensorDesc;
+import com.jogamp.oculusvr.ovrSizei;
+import com.jogamp.oculusvr.ovrVector2i;
+
+import java.util.jar.Manifest;
+
+public class OVRVersion extends JogampVersion {
+
+ protected static volatile OVRVersion jogampCommonVersionInfo;
+
+ protected OVRVersion(final String packageName, final Manifest mf) {
+ super(packageName, mf);
+ }
+
+ public static OVRVersion getInstance() {
+ if(null == jogampCommonVersionInfo) { // volatile: ok
+ synchronized(OVRVersion.class) {
+ if( null == jogampCommonVersionInfo ) {
+ final String packageName = "com.jogamp.oculusvr";
+ final Manifest mf = VersionUtil.getManifest(OVRVersion.class.getClassLoader(), packageName);
+ jogampCommonVersionInfo = new OVRVersion(packageName, mf);
+ }
+ }
+ }
+ return jogampCommonVersionInfo;
+ }
+
+ public static StringBuilder getAvailableCapabilitiesInfo(final int ovrHmdIndex, StringBuilder sb) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ if( !OVR.ovr_Initialize() ) { // recursive ..
+ sb.append("\tOVR not available").append(Platform.getNewline());
+ } else {
+ final OvrHmdContext ovrHmdCtx = OVR.ovrHmd_Create(ovrHmdIndex);
+ if( null != ovrHmdCtx ) {
+ getAvailableCapabilitiesInfo(ovrHmdCtx, ovrHmdIndex, sb);
+ OVR.ovrHmd_Destroy(ovrHmdCtx);
+ } else {
+ sb.append("\thmd."+ovrHmdIndex+" not available").append(Platform.getNewline());
+ }
+ }
+ // Nope .. ovr.ovr_Shutdown();
+ sb.append(Platform.getNewline());
+ return sb;
+ }
+ /**
+ *
+ * @param ovrHmdCtx
+ * @param ovrHmdIndex only for informal purposes, OVR HMD index of created <code>ovrHmdHandle</code>
+ * @param sb
+ * @return
+ */
+ public static StringBuilder getAvailableCapabilitiesInfo(final OvrHmdContext ovrHmdCtx, final int ovrHmdIndex, StringBuilder sb) {
+ if(null == ovrHmdCtx) {
+ throw new IllegalArgumentException("null ovrHmdHandle");
+ }
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ final ovrHmdDesc hmdDesc = ovrHmdDesc.create();
+ OVR.ovrHmd_GetDesc(ovrHmdCtx, hmdDesc);
+ getAvailableCapabilitiesInfo(hmdDesc, ovrHmdIndex, sb);
+
+ final ovrSensorDesc sensorDesc = ovrSensorDesc.create();
+ if( OVR.ovrHmd_GetSensorDesc(ovrHmdCtx, sensorDesc) ) {
+ sb.append("\thmd."+ovrHmdIndex+".sensor.productId:\t0x"+Integer.toHexString(sensorDesc.getProductId())).append(Platform.getNewline());
+ sb.append("\thmd."+ovrHmdIndex+".sensor.vendorId:\t0x"+Integer.toHexString(sensorDesc.getVendorId())).append(Platform.getNewline());
+ sb.append("\thmd."+ovrHmdIndex+".sensor.serial:\t"+sensorDesc.getSerialNumberAsString()).append(Platform.getNewline());
+ } else {
+ sb.append("\thmd."+ovrHmdIndex+".sensor:\tn/a").append(Platform.getNewline());
+ }
+ return sb;
+ }
+ /**
+ *
+ * @param hmdDesc
+ * @param ovrHmdIndex only for informal purposes, OVR HMD index of <code>hmdDesc</code>
+ * @param sb
+ * @return
+ */
+ public static StringBuilder getAvailableCapabilitiesInfo(final ovrHmdDesc hmdDesc, final int ovrHmdIndex, StringBuilder sb) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("\thmd."+ovrHmdIndex+".productName:\t"+hmdDesc.getProductNameAsString()).append(Platform.getNewline());
+ sb.append("\thmd."+ovrHmdIndex+".vendorName:\t"+hmdDesc.getManufacturerAsString()).append(Platform.getNewline());
+ sb.append("\thmd."+ovrHmdIndex+".deviceName:\t"+hmdDesc.getDisplayDeviceNameAsString()).append(Platform.getNewline());
+ sb.append("\thmd."+ovrHmdIndex+".type:\t"+hmdDesc.getType()).append(Platform.getNewline());
+ sb.append("\thmd."+ovrHmdIndex+".hmdCaps:\t"+hmdDesc.getHmdCaps()).append(Platform.getNewline());
+ sb.append("\thmd."+ovrHmdIndex+".distorCaps:\t"+hmdDesc.getDistortionCaps()).append(Platform.getNewline());
+ sb.append("\thmd."+ovrHmdIndex+".sensorCaps:\t"+hmdDesc.getSensorCaps()).append(Platform.getNewline());
+ final ovrSizei resolution = hmdDesc.getResolution();
+ sb.append("\thmd."+ovrHmdIndex+".resolution:\t"+resolution.getW()+"x"+resolution.getH()).append(Platform.getNewline());
+ final ovrVector2i winPos = hmdDesc.getWindowsPos();
+ sb.append("\thmd."+ovrHmdIndex+".winPos:\t"+winPos.getX()+" / "+winPos.getY()).append(Platform.getNewline());
+ return sb;
+ }
+
+ public static StringBuilder getAllAvailableCapabilitiesInfo(StringBuilder sb) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ sb.append(Platform.getNewline()).append(Platform.getNewline());
+ sb.append("HMD.0 Capabilities: ").append(Platform.getNewline());
+ getAvailableCapabilitiesInfo(0, sb);
+ return sb;
+ }
+
+ public static void main(final String args[]) {
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println(GlueGenVersion.getInstance());
+ // System.err.println(NativeWindowVersion.getInstance());
+ System.err.println(OVRVersion.getInstance());
+ System.err.println(OVRVersion.getAllAvailableCapabilitiesInfo(null).toString());
+ }
+}
+
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java
new file mode 100644
index 000000000..f6dc8bf9f
--- /dev/null
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java
@@ -0,0 +1,219 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.oculusvr;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import com.jogamp.oculusvr.OVR;
+import com.jogamp.oculusvr.OvrHmdContext;
+import com.jogamp.oculusvr.ovrEyeRenderDesc;
+import com.jogamp.oculusvr.ovrFovPort;
+import com.jogamp.oculusvr.ovrHmdDesc;
+import com.jogamp.oculusvr.ovrSizei;
+import com.jogamp.opengl.math.FovHVHalves;
+import com.jogamp.opengl.util.stereo.StereoDevice;
+import com.jogamp.opengl.util.stereo.StereoDeviceFactory;
+import com.jogamp.opengl.util.stereo.StereoDeviceRenderer;
+import com.jogamp.opengl.util.stereo.StereoUtil;
+
+public class OVRStereoDevice implements StereoDevice {
+ /** 1.6 up, 5 forward */
+ private static final float[] DEFAULT_EYE_POSITION_OFFSET = { 0.0f, 1.6f, -5.0f };
+
+ private final StereoDeviceFactory factory;
+ public final OvrHmdContext handle;
+ public final int deviceIndex;
+ public final ovrHmdDesc hmdDesc;
+ private final FovHVHalves[] defaultEyeFov;
+
+ private boolean sensorsStarted = false;
+ private final int[] eyeRenderOrder;
+ private final int supportedDistortionBits, recommendedDistortionBits, minimumDistortionBits;
+
+ public OVRStereoDevice(final StereoDeviceFactory factory, final OvrHmdContext nativeContext, final int deviceIndex) {
+ if( null == nativeContext ) {
+ throw new IllegalArgumentException("Passed null nativeContext");
+ }
+ this.factory = factory;
+ this.handle = nativeContext;
+ this.deviceIndex = deviceIndex;
+ this.hmdDesc = ovrHmdDesc.create();
+ OVR.ovrHmd_GetDesc(handle, hmdDesc);
+ final ovrFovPort[] defaultOVREyeFov = hmdDesc.getDefaultEyeFov(0, new ovrFovPort[hmdDesc.getEyeRenderOrderArrayLength()]);
+ defaultEyeFov = new FovHVHalves[defaultOVREyeFov.length];
+ for(int i=0; i<defaultEyeFov.length; i++) {
+ defaultEyeFov[i] = OVRUtil.getFovHV(defaultOVREyeFov[i]);
+ }
+ eyeRenderOrder = new int[hmdDesc.getEyeRenderOrderArrayLength()];
+ hmdDesc.getEyeRenderOrder(0, eyeRenderOrder);
+ supportedDistortionBits = OVRUtil.ovrDistCaps2DistBits(hmdDesc.getDistortionCaps());
+ recommendedDistortionBits = supportedDistortionBits & ~StereoDeviceRenderer.DISTORTION_TIMEWARP;
+ minimumDistortionBits = StereoDeviceRenderer.DISTORTION_BARREL;
+ }
+
+ @Override
+ public final StereoDeviceFactory getFactory() { return factory; }
+
+ @Override
+ public final String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("OVRStereoDevice[product "+hmdDesc.getProductNameAsString());
+ sb.append(", vendor "+hmdDesc.getManufacturerAsString());
+ sb.append(", device "+hmdDesc.getDisplayDeviceNameAsString());
+ sb.append(", surfaceSize "+getSurfaceSize());
+ sb.append(", surfacePos "+getPosition());
+ sb.append(", distortionBits[supported ["+StereoUtil.distortionBitsToString(getSupportedDistortionBits())+
+ "], recommended ["+StereoUtil.distortionBitsToString(getRecommendedDistortionBits())+
+ "], minimum ["+StereoUtil.distortionBitsToString(getMinimumDistortionBits())+"]]]");
+ return sb.toString();
+ }
+
+ @Override
+ public final void dispose() {
+ // NOP
+ }
+
+ @Override
+ public final PointImmutable getPosition() {
+ return OVRUtil.getVec2iAsPoint(hmdDesc.getWindowsPos());
+ }
+
+ @Override
+ public final DimensionImmutable getSurfaceSize() {
+ return OVRUtil.getOVRSizei(hmdDesc.getResolution());
+ }
+
+ @Override
+ public float[] getDefaultEyePositionOffset() {
+ return DEFAULT_EYE_POSITION_OFFSET;
+ }
+
+ @Override
+ public final FovHVHalves[] getDefaultFOV() {
+ return defaultEyeFov;
+ }
+
+ @Override
+ public final boolean startSensors(final boolean start) {
+ if( start && !sensorsStarted ) {
+ // Start the sensor which provides the Rift’s pose and motion.
+ final int requiredSensorCaps = 0;
+ final int supportedSensorCaps = requiredSensorCaps | OVR.ovrSensorCap_Orientation | OVR.ovrSensorCap_YawCorrection | OVR.ovrSensorCap_Position;
+ if( OVR.ovrHmd_StartSensor(handle, supportedSensorCaps, requiredSensorCaps) ) {
+ sensorsStarted = true;
+ return true;
+ } else {
+ sensorsStarted = false;
+ return false;
+ }
+ } else if( sensorsStarted ) {
+ OVR.ovrHmd_StopSensor(handle);
+ sensorsStarted = false;
+ return true;
+ } else {
+ // No state change -> Success
+ return true;
+ }
+ }
+ @Override
+ public final boolean getSensorsStarted() { return sensorsStarted; }
+
+ @Override
+ public final int[] getEyeRenderOrder() {
+ return eyeRenderOrder;
+ }
+
+ @Override
+ public final int getSupportedDistortionBits() {
+ return supportedDistortionBits;
+ };
+
+ @Override
+ public final int getRecommendedDistortionBits() {
+ return recommendedDistortionBits;
+ }
+
+ @Override
+ public final int getMinimumDistortionBits() {
+ return minimumDistortionBits;
+ }
+
+ @Override
+ public final StereoDeviceRenderer createRenderer(final int distortionBits,
+ final int textureCount, final float[] eyePositionOffset,
+ final FovHVHalves[] eyeFov, final float pixelsPerDisplayPixel, final int textureUnit) {
+ final ovrFovPort ovrEyeFov0 = OVRUtil.getOVRFovPort(eyeFov[0]);
+ final ovrFovPort ovrEyeFov1 = OVRUtil.getOVRFovPort(eyeFov[1]);
+
+ final ovrEyeRenderDesc[] eyeRenderDesc = new ovrEyeRenderDesc[2];
+ eyeRenderDesc[0] = OVR.ovrHmd_GetRenderDesc(handle, OVR.ovrEye_Left, ovrEyeFov0);
+ eyeRenderDesc[1] = OVR.ovrHmd_GetRenderDesc(handle, OVR.ovrEye_Right, ovrEyeFov1);
+ if( StereoDevice.DEBUG ) {
+ System.err.println("XXX: eyeRenderDesc[0] "+OVRUtil.toString(eyeRenderDesc[0]));
+ System.err.println("XXX: eyeRenderDesc[1] "+OVRUtil.toString(eyeRenderDesc[1]));
+ }
+
+ final ovrSizei recommenedTex0Size = OVR.ovrHmd_GetFovTextureSize(handle, OVR.ovrEye_Left, eyeRenderDesc[0].getFov(), pixelsPerDisplayPixel);
+ final ovrSizei recommenedTex1Size = OVR.ovrHmd_GetFovTextureSize(handle, OVR.ovrEye_Right, eyeRenderDesc[1].getFov(), pixelsPerDisplayPixel);
+ if( StereoDevice.DEBUG ) {
+ System.err.println("XXX: recommenedTex0Size "+OVRUtil.toString(recommenedTex0Size));
+ System.err.println("XXX: recommenedTex1Size "+OVRUtil.toString(recommenedTex1Size));
+ }
+ final int unifiedW = Math.max(recommenedTex0Size.getW(), recommenedTex1Size.getW());
+ final int unifiedH = Math.max(recommenedTex0Size.getH(), recommenedTex1Size.getH());
+
+ final DimensionImmutable singleTextureSize = new Dimension(unifiedW, unifiedH);
+ final DimensionImmutable totalTextureSize = new Dimension(recommenedTex0Size.getW() + recommenedTex1Size.getW(), unifiedH);
+ if( StereoDevice.DEBUG ) {
+ System.err.println("XXX: textureSize Single "+singleTextureSize);
+ System.err.println("XXX: textureSize Total "+totalTextureSize);
+ }
+
+ final RectangleImmutable[] eyeRenderViewports = new RectangleImmutable[2];
+ if( 1 == textureCount ) { // validated in ctor below!
+ eyeRenderViewports[0] = new Rectangle(0, 0,
+ totalTextureSize.getWidth() / 2,
+ totalTextureSize.getHeight());
+
+ eyeRenderViewports[1] = new Rectangle((totalTextureSize.getWidth() + 1) / 2, 0,
+ totalTextureSize.getWidth() / 2,
+ totalTextureSize.getHeight());
+ } else {
+ eyeRenderViewports[0] = new Rectangle(0, 0,
+ singleTextureSize.getWidth(),
+ singleTextureSize.getHeight());
+ eyeRenderViewports[1] = eyeRenderViewports[0];
+ }
+ return new OVRStereoDeviceRenderer(this, distortionBits, textureCount, eyePositionOffset,
+ eyeRenderDesc, singleTextureSize, totalTextureSize, eyeRenderViewports, textureUnit);
+ }
+} \ No newline at end of file
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java
index 5166ef577..06f716ddc 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright 2014 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -25,46 +25,38 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package jogamp.nativewindow.x11;
+package jogamp.opengl.oculusvr;
-import javax.media.nativewindow.ToolkitLock;
+import com.jogamp.oculusvr.OVR;
+import com.jogamp.oculusvr.OVRVersion;
+import com.jogamp.oculusvr.OvrHmdContext;
+import com.jogamp.opengl.util.stereo.StereoDevice;
+import com.jogamp.opengl.util.stereo.StereoDevice.Config;
+import com.jogamp.opengl.util.stereo.StereoDeviceFactory;
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
+public class OVRStereoDeviceFactory extends StereoDeviceFactory {
-/**
- * Implementing a recursive {@link javax.media.nativewindow.ToolkitLock}
- * utilizing {@link X11Util#XLockDisplay(long)}.
- * <br>
- * This strategy should not be used in case XInitThreads() is being used,
- * or a higher level toolkit lock is required, ie AWT lock.
- */
-public class X11ToolkitLock implements ToolkitLock {
- long displayHandle;
- RecursiveLock lock;
-
- public X11ToolkitLock(long displayHandle) {
- this.displayHandle = displayHandle;
- if(!X11Util.isNativeLockAvailable()) {
- lock = LockFactory.createRecursiveLock();
+ public static boolean isAvailable() {
+ if( OVR.ovr_Initialize() ) { // recursive ..
+ return 0 < OVR.ovrHmd_Detect();
}
+ return false;
}
- public final void lock() {
- if(TRACE_LOCK) { System.err.println("X11ToolkitLock.lock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XLockDisplay(displayHandle);
- } else {
- lock.lock();
+ @Override
+ public final StereoDevice createDevice(final int deviceIndex, final Config config, final boolean verbose) {
+ final OvrHmdContext hmdCtx = OVR.ovrHmd_Create(deviceIndex);
+ if( null == hmdCtx ) {
+ if( verbose ) {
+ System.err.println("Failed to create hmdCtx for device index "+deviceIndex+" on thread "+Thread.currentThread().getName());
+ Thread.dumpStack();
+ }
+ return null;
}
- }
-
- public final void unlock() {
- if(TRACE_LOCK) { System.err.println("X11ToolkitLock.unlock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XUnlockDisplay(displayHandle);
- } else {
- lock.unlock();
+ final OVRStereoDevice ctx = new OVRStereoDevice(this, hmdCtx, deviceIndex);
+ if( verbose ) {
+ System.err.println(OVRVersion.getAvailableCapabilitiesInfo(ctx.hmdDesc, deviceIndex, null).toString());
}
+ return ctx;
}
}
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java
new file mode 100644
index 000000000..39736217c
--- /dev/null
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java
@@ -0,0 +1,604 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.oculusvr;
+
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLArrayData;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+
+import jogamp.common.os.PlatformPropsImpl;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.oculusvr.OVR;
+import com.jogamp.oculusvr.OVRException;
+import com.jogamp.oculusvr.OvrHmdContext;
+import com.jogamp.oculusvr.ovrDistortionMesh;
+import com.jogamp.oculusvr.ovrDistortionVertex;
+import com.jogamp.oculusvr.ovrEyeRenderDesc;
+import com.jogamp.oculusvr.ovrFovPort;
+import com.jogamp.oculusvr.ovrFrameTiming;
+import com.jogamp.oculusvr.ovrMatrix4f;
+import com.jogamp.oculusvr.ovrPosef;
+import com.jogamp.oculusvr.ovrRecti;
+import com.jogamp.oculusvr.ovrSizei;
+import com.jogamp.oculusvr.ovrVector2f;
+import com.jogamp.oculusvr.ovrVector3f;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.stereo.EyeParameter;
+import com.jogamp.opengl.util.stereo.EyePose;
+import com.jogamp.opengl.util.stereo.StereoDevice;
+import com.jogamp.opengl.util.stereo.StereoDeviceRenderer;
+import com.jogamp.opengl.util.stereo.StereoUtil;
+
+/**
+ * OculusVR Stereo Device Distortion and OpenGL Renderer Utility
+ */
+public class OVRStereoDeviceRenderer implements StereoDeviceRenderer {
+ private static final String shaderPrefix01 = "dist01";
+ private static final String shaderTimewarpSuffix = "_timewarp";
+ private static final String shaderChromaSuffix = "_chroma";
+ private static final String shaderPlainSuffix = "_plain";
+
+ public static class OVREye implements StereoDeviceRenderer.Eye {
+ private final int eyeName;
+ private final int distortionBits;
+ private final int vertexCount;
+ private final int indexCount;
+ private final RectangleImmutable viewport;
+
+ private final GLUniformData eyeToSourceUVScale;
+ private final GLUniformData eyeToSourceUVOffset;
+ private final GLUniformData eyeRotationStart;
+ private final GLUniformData eyeRotationEnd;
+
+ /** 2+2+2+2+2: { vec2 position, vec2 color, vec2 texCoordR, vec2 texCoordG, vec2 texCoordB } */
+ private final GLArrayDataServer iVBO;
+ private final GLArrayData vboPos, vboParams, vboTexCoordsR, vboTexCoordsG, vboTexCoordsB;
+ private final GLArrayDataServer indices;
+
+ private final ovrEyeRenderDesc ovrEyeDesc;
+ private final ovrFovPort ovrEyeFov;
+ private final EyeParameter eyeParameter;
+
+ private ovrPosef ovrEyePose;
+ private final EyePose eyePose;
+
+ @Override
+ public final RectangleImmutable getViewport() { return viewport; }
+
+ @Override
+ public final EyeParameter getEyeParameter() { return eyeParameter; }
+
+ @Override
+ public final EyePose getLastEyePose() { return eyePose; }
+
+ private OVREye(final OvrHmdContext hmdCtx, final int distortionBits,
+ final float[] eyePositionOffset, final ovrEyeRenderDesc eyeDesc,
+ final ovrSizei ovrTextureSize, final RectangleImmutable eyeViewport) {
+ this.eyeName = eyeDesc.getEye();
+ this.distortionBits = distortionBits;
+ this.viewport = eyeViewport;
+
+ final boolean usesTimewarp = StereoUtil.usesTimewarpDistortion(distortionBits);
+ final FloatBuffer fstash = Buffers.newDirectFloatBuffer( 2 + 2 + ( usesTimewarp ? 16 + 16 : 0 ) ) ;
+
+ eyeToSourceUVScale = new GLUniformData("ovr_EyeToSourceUVScale", 2, Buffers.slice2Float(fstash, 0, 2));
+ eyeToSourceUVOffset = new GLUniformData("ovr_EyeToSourceUVOffset", 2, Buffers.slice2Float(fstash, 2, 2));
+
+ if( usesTimewarp ) {
+ eyeRotationStart = new GLUniformData("ovr_EyeRotationStart", 4, 4, Buffers.slice2Float(fstash, 4, 16));
+ eyeRotationEnd = new GLUniformData("ovr_EyeRotationEnd", 4, 4, Buffers.slice2Float(fstash, 20, 16));
+ } else {
+ eyeRotationStart = null;
+ eyeRotationEnd = null;
+ }
+
+ this.ovrEyeDesc = eyeDesc;
+ this.ovrEyeFov = eyeDesc.getFov();
+
+ final ovrVector3f eyeViewAdjust = eyeDesc.getViewAdjust();
+ this.eyeParameter = new EyeParameter(eyeName, eyePositionOffset, OVRUtil.getFovHV(ovrEyeFov),
+ eyeViewAdjust.getX(), eyeViewAdjust.getY(), eyeViewAdjust.getZ());
+
+ this.eyePose = new EyePose(eyeName);
+
+ updateEyePose(hmdCtx); // 1st init
+
+ // Setup: eyeToSourceUVScale, eyeToSourceUVOffset
+ {
+ final ovrVector2f[] uvScaleOffsetOut = new ovrVector2f[2];
+ uvScaleOffsetOut[0] = ovrVector2f.create(); // FIXME: remove ctor / double check
+ uvScaleOffsetOut[1] = ovrVector2f.create();
+
+ final ovrRecti ovrEyeRenderViewport = OVRUtil.createOVRRecti(eyeViewport);
+ OVR.ovrHmd_GetRenderScaleAndOffset(ovrEyeFov, ovrTextureSize, ovrEyeRenderViewport, uvScaleOffsetOut);
+ if( StereoDevice.DEBUG ) {
+ System.err.println("XXX."+eyeName+": eyeParam "+eyeParameter);
+ System.err.println("XXX."+eyeName+": uvScale "+OVRUtil.toString(uvScaleOffsetOut[0]));
+ System.err.println("XXX."+eyeName+": uvOffset "+OVRUtil.toString(uvScaleOffsetOut[1]));
+ System.err.println("XXX."+eyeName+": textureSize "+OVRUtil.toString(ovrTextureSize));
+ System.err.println("XXX."+eyeName+": viewport "+OVRUtil.toString(ovrEyeRenderViewport));
+ }
+ final FloatBuffer eyeToSourceUVScaleFB = eyeToSourceUVScale.floatBufferValue();
+ eyeToSourceUVScaleFB.put(0, uvScaleOffsetOut[0].getX());
+ eyeToSourceUVScaleFB.put(1, uvScaleOffsetOut[0].getY());
+ final FloatBuffer eyeToSourceUVOffsetFB = eyeToSourceUVOffset.floatBufferValue();
+ eyeToSourceUVOffsetFB.put(0, uvScaleOffsetOut[1].getX());
+ eyeToSourceUVOffsetFB.put(1, uvScaleOffsetOut[1].getY());
+ }
+
+ final ovrDistortionMesh meshData = ovrDistortionMesh.create();
+
+ final int ovrDistortionCaps = distBits2OVRDistCaps(distortionBits);
+ if( !OVR.ovrHmd_CreateDistortionMesh(hmdCtx, eyeName, ovrEyeFov, ovrDistortionCaps, meshData) ) {
+ throw new OVRException("Failed to create meshData for eye "+eyeName+", "+OVRUtil.toString(ovrEyeFov)+" and "+StereoUtil.distortionBitsToString(distortionBits));
+ }
+ vertexCount = meshData.getVertexCount();
+ indexCount = meshData.getIndexCount();
+
+ /** 2+2+2+2+2: { vec2 position, vec2 color, vec2 texCoordR, vec2 texCoordG, vec2 texCoordB } */
+ final boolean useChromatic = StereoUtil.usesChromaticDistortion(distortionBits);
+ final boolean useVignette = StereoUtil.usesVignetteDistortion(distortionBits);
+
+ final int compsPerElement = 2+2+2+( useChromatic ? 2+2 /* texCoordG + texCoordB */: 0 );
+ iVBO = GLArrayDataServer.createGLSLInterleaved(compsPerElement, GL.GL_FLOAT, false, vertexCount, GL.GL_STATIC_DRAW);
+ vboPos = iVBO.addGLSLSubArray("ovr_Position", 2, GL.GL_ARRAY_BUFFER);
+ vboParams = iVBO.addGLSLSubArray("ovr_Params", 2, GL.GL_ARRAY_BUFFER);
+ vboTexCoordsR = iVBO.addGLSLSubArray("ovr_TexCoordR", 2, GL.GL_ARRAY_BUFFER);
+ if( useChromatic ) {
+ vboTexCoordsG = iVBO.addGLSLSubArray("ovr_TexCoordG", 2, GL.GL_ARRAY_BUFFER);
+ vboTexCoordsB = iVBO.addGLSLSubArray("ovr_TexCoordB", 2, GL.GL_ARRAY_BUFFER);
+ } else {
+ vboTexCoordsG = null;
+ vboTexCoordsB = null;
+ }
+ indices = GLArrayDataServer.createData(1, GL.GL_SHORT, indexCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
+
+ /** 2+2+2+2+2: { vec2 position, vec2 color, vec2 texCoordR, vec2 texCoordG, vec2 texCoordB } */
+ final FloatBuffer iVBOFB = (FloatBuffer)iVBO.getBuffer();
+ final ovrDistortionVertex[] ovRes = new ovrDistortionVertex[1];
+ ovRes[0] = ovrDistortionVertex.create(); // FIXME: remove ctor / double check
+
+ for ( int vertNum = 0; vertNum < vertexCount; vertNum++ ) {
+ final ovrDistortionVertex ov = meshData.getPVertexData(vertNum, ovRes)[0];
+ ovrVector2f v;
+
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": START VERTEX "+vertNum+" / "+vertexCount);
+ }
+ // pos
+ v = ov.getPos();
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": pos "+OVRUtil.toString(v));
+ }
+ iVBOFB.put(v.getX());
+ iVBOFB.put(v.getY());
+
+ // params
+ if( useVignette ) {
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": vignette "+ov.getVignetteFactor());
+ }
+ iVBOFB.put(ov.getVignetteFactor());
+ } else {
+ iVBOFB.put(1.0f);
+ }
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": timewarp "+ov.getTimeWarpFactor());
+ }
+ iVBOFB.put(ov.getTimeWarpFactor());
+
+ // texCoordR
+ v = ov.getTexR();
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": texR "+OVRUtil.toString(v));
+ }
+ iVBOFB.put(v.getX());
+ iVBOFB.put(v.getY());
+
+ if( useChromatic ) {
+ // texCoordG
+ v = ov.getTexG();
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": texG "+OVRUtil.toString(v));
+ }
+ iVBOFB.put(v.getX());
+ iVBOFB.put(v.getY());
+
+ // texCoordB
+ v = ov.getTexB();
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": texB "+OVRUtil.toString(v));
+ }
+ iVBOFB.put(v.getX());
+ iVBOFB.put(v.getY());
+ }
+ }
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": iVBO "+iVBO);
+ }
+ {
+ final ShortBuffer in = meshData.getPIndexData();
+ if( StereoDevice.DUMP_DATA ) {
+ System.err.println("XXX."+eyeName+": idx "+indices+", count "+indexCount);
+ for(int i=0; i< indexCount; i++) {
+ if( 0 == i % 16 ) {
+ System.err.printf("%n%5d: ", i);
+ }
+ System.err.printf("%5d, ", (int)in.get(i));
+ }
+ System.err.println();
+ }
+ final ShortBuffer out = (ShortBuffer) indices.getBuffer();
+ out.put(in);
+ }
+ if( StereoDevice.DEBUG ) {
+ System.err.println("XXX."+eyeName+": "+this);
+ }
+ OVR.ovrHmd_DestroyDistortionMesh(meshData);
+ }
+
+ private void linkData(final GL2ES2 gl, final ShaderProgram sp) {
+ if( 0 > vboPos.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+vboPos);
+ }
+ if( 0 > vboParams.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+vboParams);
+ }
+ if( 0 > vboTexCoordsR.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+vboTexCoordsR);
+ }
+ if( StereoUtil.usesChromaticDistortion(distortionBits) ) {
+ if( 0 > vboTexCoordsG.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+vboTexCoordsG);
+ }
+ if( 0 > vboTexCoordsB.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+vboTexCoordsB);
+ }
+ }
+ if( 0 > eyeToSourceUVScale.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+eyeToSourceUVScale);
+ }
+ if( 0 > eyeToSourceUVOffset.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+eyeToSourceUVOffset);
+ }
+ if( StereoUtil.usesTimewarpDistortion(distortionBits) ) {
+ if( 0 > eyeRotationStart.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+eyeRotationStart);
+ }
+ if( 0 > eyeRotationEnd.setLocation(gl, sp.program()) ) {
+ throw new GLException("Couldn't locate "+eyeRotationEnd);
+ }
+ }
+ iVBO.seal(gl, true);
+ iVBO.enableBuffer(gl, false);
+ indices.seal(gl, true);
+ indices.enableBuffer(gl, false);
+ }
+
+ private void dispose(final GL2ES2 gl) {
+ iVBO.destroy(gl);
+ indices.destroy(gl);
+ }
+ private void enableVBO(final GL2ES2 gl, final boolean enable) {
+ iVBO.enableBuffer(gl, enable);
+ indices.bindBuffer(gl, enable); // keeps VBO binding if enable:=true
+ }
+
+ private void updateUniform(final GL2ES2 gl, final ShaderProgram sp) {
+ gl.glUniform(eyeToSourceUVScale);
+ gl.glUniform(eyeToSourceUVOffset);
+ if( StereoUtil.usesTimewarpDistortion(distortionBits) ) {
+ gl.glUniform(eyeRotationStart);
+ gl.glUniform(eyeRotationEnd);
+ }
+ }
+
+ private void updateTimewarp(final OvrHmdContext hmdCtx, final ovrPosef eyeRenderPose, final float[] mat4Tmp1, final float[] mat4Tmp2) {
+ final ovrMatrix4f[] timeWarpMatrices = new ovrMatrix4f[2];
+ timeWarpMatrices[0] = ovrMatrix4f.create(); // FIXME: remove ctor / double check
+ timeWarpMatrices[1] = ovrMatrix4f.create();
+ OVR.ovrHmd_GetEyeTimewarpMatrices(hmdCtx, eyeName, eyeRenderPose, timeWarpMatrices);
+
+ final float[] eyeRotationStartM = FloatUtil.transposeMatrix(timeWarpMatrices[0].getM(0, mat4Tmp1), mat4Tmp2);
+ final FloatBuffer eyeRotationStartU = eyeRotationStart.floatBufferValue();
+ eyeRotationStartU.put(eyeRotationStartM);
+ eyeRotationStartU.rewind();
+
+ final float[] eyeRotationEndM = FloatUtil.transposeMatrix(timeWarpMatrices[1].getM(0, mat4Tmp1), mat4Tmp2);
+ final FloatBuffer eyeRotationEndU = eyeRotationEnd.floatBufferValue();
+ eyeRotationEndU.put(eyeRotationEndM);
+ eyeRotationEndU.rewind();
+ }
+
+ /**
+ * Updates {@link #ovrEyePose} and it's extracted
+ * {@link #eyeRenderPoseOrientation} and {@link #eyeRenderPosePosition}.
+ * @param hmdCtx used get the {@link #ovrEyePose} via {@link OVR#ovrHmd_GetEyePose(OvrHmdContext, int)}
+ */
+ private EyePose updateEyePose(final OvrHmdContext hmdCtx) {
+ ovrEyePose = OVR.ovrHmd_GetEyePose(hmdCtx, eyeName);
+ final ovrVector3f pos = ovrEyePose.getPosition();
+ eyePose.setPosition(pos.getX(), pos.getY(), pos.getZ());
+ OVRUtil.copyToQuaternion(ovrEyePose.getOrientation(), eyePose.orientation);
+ return eyePose;
+ }
+
+ @Override
+ public String toString() {
+ return "Eye["+eyeName+", viewport "+viewport+
+ ", "+eyeParameter+
+ ", vertices "+vertexCount+", indices "+indexCount+
+ ", uvScale["+eyeToSourceUVScale.floatBufferValue().get(0)+", "+eyeToSourceUVScale.floatBufferValue().get(1)+
+ "], uvOffset["+eyeToSourceUVOffset.floatBufferValue().get(0)+", "+eyeToSourceUVOffset.floatBufferValue().get(1)+
+ "], desc"+OVRUtil.toString(ovrEyeDesc)+", "+eyePose+"]";
+ }
+ }
+
+ private final OVRStereoDevice context;
+ private final OVREye[] eyes;
+ private final int distortionBits;
+ private final int textureCount;
+ private final DimensionImmutable singleTextureSize;
+ private final DimensionImmutable totalTextureSize;
+ private final GLUniformData texUnit0;
+
+
+ private final float[] mat4Tmp1 = new float[16];
+ private final float[] mat4Tmp2 = new float[16];
+
+ private ShaderProgram sp;
+ private ovrFrameTiming frameTiming;
+
+ @Override
+ public String toString() {
+ return "OVRDist[distortion["+StereoUtil.distortionBitsToString(distortionBits)+
+ "], singleSize "+singleTextureSize+
+ ", sbsSize "+totalTextureSize+
+ ", texCount "+textureCount+", texUnit "+getTextureUnit()+
+ ", "+PlatformPropsImpl.NEWLINE+" "+eyes[0]+", "+PlatformPropsImpl.NEWLINE+" "+eyes[1]+"]";
+ }
+
+
+ private static int distBits2OVRDistCaps(final int distortionBits) {
+ int caps = 0;
+ if( StereoUtil.usesTimewarpDistortion(distortionBits) ) {
+ caps |= OVR.ovrDistortionCap_TimeWarp;
+ }
+ if( StereoUtil.usesChromaticDistortion(distortionBits) ) {
+ caps |= OVR.ovrDistortionCap_Chromatic;
+ }
+ if( StereoUtil.usesVignetteDistortion(distortionBits) ) {
+ caps |= OVR.ovrDistortionCap_Vignette;
+ }
+ return caps;
+ }
+
+ /* pp */ OVRStereoDeviceRenderer(final OVRStereoDevice context, final int distortionBits,
+ final int textureCount, final float[] eyePositionOffset,
+ final ovrEyeRenderDesc[] eyeRenderDescs, final DimensionImmutable singleTextureSize, final DimensionImmutable totalTextureSize,
+ final RectangleImmutable[] eyeViewports, final int textureUnit) {
+ if( 1 > textureCount || 2 < textureCount ) {
+ throw new IllegalArgumentException("textureCount can only be 1 or 2, has "+textureCount);
+ }
+ this.context = context;
+ this.eyes = new OVREye[2];
+ this.distortionBits = ( distortionBits | context.getMinimumDistortionBits() ) & context.getSupportedDistortionBits();
+ this.textureCount = textureCount;
+ this.singleTextureSize = singleTextureSize;
+ this.totalTextureSize = totalTextureSize;
+
+ texUnit0 = new GLUniformData("ovr_Texture0", textureUnit);
+
+ final ovrSizei ovrTextureSize = OVRUtil.createOVRSizei( 1 == textureCount ? totalTextureSize : singleTextureSize );
+ eyes[0] = new OVREye(context.handle, this.distortionBits, eyePositionOffset, eyeRenderDescs[0], ovrTextureSize, eyeViewports[0]);
+ eyes[1] = new OVREye(context.handle, this.distortionBits, eyePositionOffset, eyeRenderDescs[1], ovrTextureSize, eyeViewports[1]);
+ sp = null;
+ frameTiming = null;
+ }
+
+ @Override
+ public StereoDevice getDevice() {
+ return context;
+ }
+
+ @Override
+ public final int getDistortionBits() { return distortionBits; }
+
+ @Override
+ public final boolean usesSideBySideStereo() { return true; }
+
+ @Override
+ public final DimensionImmutable getSingleSurfaceSize() { return singleTextureSize; }
+
+ @Override
+ public final DimensionImmutable getTotalSurfaceSize() { return totalTextureSize; }
+
+ @Override
+ public final int getTextureCount() { return textureCount; }
+
+ @Override
+ public final int getTextureUnit() { return texUnit0.intValue(); }
+
+ @Override
+ public final boolean ppAvailable() { return 0 != distortionBits; }
+
+ @Override
+ public final void init(final GL gl) {
+ if( StereoDevice.DEBUG ) {
+ System.err.println(JoglVersion.getGLInfo(gl, null).toString());
+ }
+ if( null != sp ) {
+ throw new IllegalStateException("Already initialized");
+ }
+ final GL2ES2 gl2es2 = gl.getGL2ES2();
+
+ final String vertexShaderBasename;
+ final String fragmentShaderBasename;
+ {
+ final boolean usesTimewarp = StereoUtil.usesTimewarpDistortion(distortionBits);
+ final boolean usesChromatic = StereoUtil.usesChromaticDistortion(distortionBits);
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append(shaderPrefix01);
+ if( !usesChromatic && !usesTimewarp ) {
+ sb.append(shaderPlainSuffix);
+ } else if( usesChromatic && !usesTimewarp ) {
+ sb.append(shaderChromaSuffix);
+ } else if( usesTimewarp ) {
+ sb.append(shaderTimewarpSuffix);
+ if( usesChromatic ) {
+ sb.append(shaderChromaSuffix);
+ }
+ }
+ vertexShaderBasename = sb.toString();
+ sb.setLength(0);
+ sb.append(shaderPrefix01);
+ if( usesChromatic ) {
+ sb.append(shaderChromaSuffix);
+ } else {
+ sb.append(shaderPlainSuffix);
+ }
+ fragmentShaderBasename = sb.toString();
+ }
+ final ShaderCode vp0 = ShaderCode.create(gl2es2, GL2ES2.GL_VERTEX_SHADER, OVRStereoDeviceRenderer.class, "shader",
+ "shader/bin", vertexShaderBasename, true);
+ final ShaderCode fp0 = ShaderCode.create(gl2es2, GL2ES2.GL_FRAGMENT_SHADER, OVRStereoDeviceRenderer.class, "shader",
+ "shader/bin", fragmentShaderBasename, true);
+ vp0.defaultShaderCustomization(gl2es2, true, true);
+ fp0.defaultShaderCustomization(gl2es2, true, true);
+
+ sp = new ShaderProgram();
+ sp.add(gl2es2, vp0, System.err);
+ sp.add(gl2es2, fp0, System.err);
+ if(!sp.link(gl2es2, System.err)) {
+ throw new GLException("could not link program: "+sp);
+ }
+ sp.useProgram(gl2es2, true);
+ if( 0 > texUnit0.setLocation(gl2es2, sp.program()) ) {
+ throw new OVRException("Couldn't locate "+texUnit0);
+ }
+ eyes[0].linkData(gl2es2, sp);
+ eyes[1].linkData(gl2es2, sp);
+ sp.useProgram(gl2es2, false);
+ }
+
+ @Override
+ public final void dispose(final GL gl) {
+ final GL2ES2 gl2es2 = gl.getGL2ES2();
+ sp.useProgram(gl2es2, false);
+ eyes[0].dispose(gl2es2);
+ eyes[1].dispose(gl2es2);
+ sp.destroy(gl2es2);
+ frameTiming = null;
+ }
+
+ @Override
+ public final Eye getEye(final int eyeNum) {
+ return eyes[eyeNum];
+ }
+
+ @Override
+ public final EyePose updateEyePose(final int eyeNum) {
+ return eyes[eyeNum].updateEyePose(context.handle);
+ }
+
+ @Override
+ public final void beginFrame(final GL gl) {
+ frameTiming = OVR.ovrHmd_BeginFrameTiming(context.handle, 0);
+ }
+
+ @Override
+ public final void endFrame(final GL gl) {
+ if( null == frameTiming ) {
+ throw new IllegalStateException("beginFrame not called");
+ }
+ OVR.ovrHmd_EndFrameTiming(context.handle);
+ frameTiming = null;
+ }
+
+ @Override
+ public final void ppBegin(final GL gl) {
+ if( null == sp ) {
+ throw new IllegalStateException("Not initialized");
+ }
+ if( null == frameTiming ) {
+ throw new IllegalStateException("beginFrame not called");
+ }
+ if( StereoUtil.usesTimewarpDistortion(distortionBits) ) {
+ OVR.ovr_WaitTillTime(frameTiming.getTimewarpPointSeconds());
+ }
+ final GL2ES2 gl2es2 = gl.getGL2ES2();
+
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + getTextureUnit());
+
+ gl2es2.glDisable(GL.GL_CULL_FACE);
+ gl2es2.glDisable(GL.GL_DEPTH_TEST);
+ gl2es2.glDisable(GL.GL_BLEND);
+
+ if( !gl2es2.isGLcore() ) {
+ gl2es2.glEnable(GL.GL_TEXTURE_2D);
+ }
+
+ sp.useProgram(gl2es2, true);
+
+ gl2es2.glUniform(texUnit0);
+ }
+
+ @Override
+ public final void ppOneEye(final GL gl, final int eyeNum) {
+ final OVREye eye = eyes[eyeNum];
+ if( StereoUtil.usesTimewarpDistortion(distortionBits) ) {
+ eye.updateTimewarp(context.handle, eye.ovrEyePose, mat4Tmp1, mat4Tmp2);
+ }
+ final GL2ES2 gl2es2 = gl.getGL2ES2();
+
+ eye.updateUniform(gl2es2, sp);
+ eye.enableVBO(gl2es2, true);
+ gl2es2.glDrawElements(GL.GL_TRIANGLES, eye.indexCount, GL.GL_UNSIGNED_SHORT, 0);
+ eyes[eyeNum].enableVBO(gl2es2, false);
+ }
+
+ @Override
+ public final void ppEnd(final GL gl) {
+ sp.useProgram(gl.getGL2ES2(), false);
+ }
+}
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java
new file mode 100644
index 000000000..44ec728fc
--- /dev/null
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java
@@ -0,0 +1,173 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.oculusvr;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import com.jogamp.oculusvr.OVR;
+import com.jogamp.oculusvr.ovrEyeRenderDesc;
+import com.jogamp.oculusvr.ovrFovPort;
+import com.jogamp.oculusvr.ovrQuatf;
+import com.jogamp.oculusvr.ovrRecti;
+import com.jogamp.oculusvr.ovrSizei;
+import com.jogamp.oculusvr.ovrVector2f;
+import com.jogamp.oculusvr.ovrVector2i;
+import com.jogamp.oculusvr.ovrVector3f;
+import com.jogamp.opengl.math.FovHVHalves;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.util.stereo.StereoDeviceRenderer;
+
+/**
+ * OculusVR Data Conversion Helper Functions
+ */
+public class OVRUtil {
+ public static ovrRecti createOVRRecti(final int[] rect) {
+ final ovrRecti res = ovrRecti.create();
+ final ovrVector2i pos = res.getPos();
+ final ovrSizei size = res.getSize();
+ pos.setX(rect[0]);
+ pos.setY(rect[1]);
+ size.setW(rect[2]);
+ size.setH(rect[3]);
+ return res;
+ }
+ public static ovrRecti createOVRRecti(final RectangleImmutable rect) {
+ final ovrRecti res = ovrRecti.create();
+ final ovrVector2i pos = res.getPos();
+ final ovrSizei size = res.getSize();
+ pos.setX(rect.getX());
+ pos.setY(rect.getY());
+ size.setW(rect.getWidth());
+ size.setH(rect.getHeight());
+ return res;
+ }
+ public static ovrRecti[] createOVRRectis(final int[][] rects) {
+ final ovrRecti[] res = new ovrRecti[rects.length];
+ for(int i=0; i<res.length; i++) {
+ res[0] = createOVRRecti(rects[i]);
+ }
+ return res;
+ }
+ public static ovrSizei createOVRSizei(final int[] size) {
+ final ovrSizei res = ovrSizei.create();
+ res.setW(size[0]);
+ res.setH(size[1]);
+ return res;
+ }
+ public static ovrSizei createOVRSizei(final DimensionImmutable size) {
+ final ovrSizei res = ovrSizei.create();
+ res.setW(size.getWidth());
+ res.setH(size.getHeight());
+ return res;
+ }
+ public static DimensionImmutable getOVRSizei(final ovrSizei v) {
+ return new Dimension(v.getW(), v.getH());
+ }
+ public static PointImmutable getVec2iAsPoint(final ovrVector2i v) {
+ return new Point(v.getX(), v.getY());
+ }
+ public static int[] getVec2i(final ovrVector2i v) {
+ return new int[] { v.getX(), v.getY() };
+ }
+ public static void copyVec2iToInt(final ovrVector2i v, final int[] res) {
+ res[0] = v.getX();
+ res[1] = v.getY();
+ }
+ public static float[] getVec3f(final ovrVector3f v) {
+ return new float[] { v.getX(), v.getY(), v.getZ() };
+ }
+ public static void copyVec3fToFloat(final ovrVector3f v, final float[] res) {
+ res[0] = v.getX();
+ res[1] = v.getY();
+ res[2] = v.getZ();
+ }
+ public static Quaternion getQuaternion(final ovrQuatf q) {
+ return new Quaternion(q.getX(), q.getY(), q.getZ(), q.getW());
+ }
+ public static void copyToQuaternion(final ovrQuatf in, final Quaternion out) {
+ out.set(in.getX(), in.getY(), in.getZ(), in.getW());
+ }
+
+ public static FovHVHalves getFovHV(final ovrFovPort tanHalfFov) {
+ return new FovHVHalves(tanHalfFov.getLeftTan(), tanHalfFov.getRightTan(),
+ tanHalfFov.getUpTan(), tanHalfFov.getDownTan(),
+ true);
+ }
+ public static ovrFovPort getOVRFovPort(final FovHVHalves fovHVHalves) {
+ final ovrFovPort tanHalfFov = ovrFovPort.create();
+ final FovHVHalves fovHVHalvesTan = fovHVHalves.toTangents();
+ tanHalfFov.setLeftTan(fovHVHalvesTan.left);
+ tanHalfFov.setRightTan(fovHVHalvesTan.right);
+ tanHalfFov.setUpTan(fovHVHalvesTan.top);
+ tanHalfFov.setDownTan(fovHVHalvesTan.bottom);
+ return tanHalfFov;
+ }
+
+ public static int ovrDistCaps2DistBits(final int ovrDistortionCaps) {
+ int bits = StereoDeviceRenderer.DISTORTION_BARREL;
+ if( 0 != ( OVR.ovrDistortionCap_TimeWarp & ovrDistortionCaps ) ) {
+ bits |= StereoDeviceRenderer.DISTORTION_TIMEWARP;
+ }
+ if( 0 != ( OVR.ovrDistortionCap_Chromatic & ovrDistortionCaps ) ) {
+ bits |= StereoDeviceRenderer.DISTORTION_CHROMATIC;
+ }
+ if( 0 != ( OVR.ovrDistortionCap_Vignette & ovrDistortionCaps ) ) {
+ bits |= StereoDeviceRenderer.DISTORTION_VIGNETTE;
+ }
+ return bits;
+ }
+
+
+ public static String toString(final ovrFovPort fov) {
+ return "["+fov.getLeftTan()+" l, "+fov.getRightTan()+" r, "+
+ fov.getUpTan()+" u, "+fov.getDownTan()+" d]";
+ }
+ public static String toString(final ovrSizei rect) {
+ return "["+rect.getW()+" x "+rect.getH()+"]";
+ }
+ public static String toString(final ovrRecti rect) {
+ return "["+rect.getPos().getX()+" / "+rect.getPos().getY()+" "+
+ rect.getSize().getW()+" x "+rect.getSize().getH()+"]";
+ }
+ public static String toString(final ovrVector2f v2) {
+ return "["+v2.getX()+", "+v2.getY()+"]";
+ }
+ public static String toString(final ovrVector3f v3) {
+ return "["+v3.getX()+", "+v3.getY()+", "+v3.getZ()+"]";
+ }
+ public static String toString(final ovrEyeRenderDesc desc) {
+ return "["+desc.getEye()+", fov"+toString(desc.getFov())+
+ ", viewport"+toString(desc.getDistortedViewport())+
+ ", pptCtr"+toString(desc.getPixelsPerTanAngleAtCenter())+
+ ", view-adjust"+toString(desc.getViewAdjust())+"]";
+ }
+}
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_chroma.fp b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_chroma.fp
new file mode 100644
index 000000000..6d450fe40
--- /dev/null
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_chroma.fp
@@ -0,0 +1,26 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 ovr_FragColor;
+ #define texture2D texture
+#else
+ #define ovr_FragColor gl_FragColor
+#endif
+
+uniform sampler2D ovr_Texture0;
+
+varying vec3 ovv_Fade;
+varying vec2 ovv_TexCoordR;
+varying vec2 ovv_TexCoordG;
+varying vec2 ovv_TexCoordB;
+
+void main (void)
+{
+ // 3 samples for fixing chromatic aberrations
+ vec3 color = vec3(texture2D(ovr_Texture0, ovv_TexCoordR).r,
+ texture2D(ovr_Texture0, ovv_TexCoordG).g,
+ texture2D(ovr_Texture0, ovv_TexCoordB).b);
+ ovr_FragColor = vec4(ovv_Fade * color, 1.0); // include vignetteFade
+}
+
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_chroma.vp b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_chroma.vp
new file mode 100644
index 000000000..254d4b081
--- /dev/null
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_chroma.vp
@@ -0,0 +1,33 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 ovr_EyeToSourceUVScale;
+uniform vec2 ovr_EyeToSourceUVOffset;
+
+attribute vec2 ovr_Position;
+attribute vec2 ovr_Params;
+attribute vec2 ovr_TexCoordR;
+attribute vec2 ovr_TexCoordG;
+attribute vec2 ovr_TexCoordB;
+
+varying vec3 ovv_Fade;
+varying vec2 ovv_TexCoordR;
+varying vec2 ovv_TexCoordG;
+varying vec2 ovv_TexCoordB;
+
+void main(void)
+{
+ gl_Position = vec4(ovr_Position.xy, 0.5, 1.0);
+ ovv_Fade = vec3(ovr_Params.r); // vignetteFade
+
+ ovv_TexCoordR = ovr_TexCoordR * ovr_EyeToSourceUVScale + ovr_EyeToSourceUVOffset;
+ ovv_TexCoordR.y = 1.0-ovv_TexCoordR.y;
+ ovv_TexCoordG = ovr_TexCoordG * ovr_EyeToSourceUVScale + ovr_EyeToSourceUVOffset;
+ ovv_TexCoordG.y = 1.0-ovv_TexCoordG.y;
+ ovv_TexCoordB = ovr_TexCoordB * ovr_EyeToSourceUVScale + ovr_EyeToSourceUVOffset;
+ ovv_TexCoordB.y = 1.0-ovv_TexCoordB.y;
+}
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_plain.fp b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_plain.fp
new file mode 100644
index 000000000..d3ee5d04d
--- /dev/null
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_plain.fp
@@ -0,0 +1,22 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 ovr_FragColor;
+ #define texture2D texture
+#else
+ #define ovr_FragColor gl_FragColor
+#endif
+
+uniform sampler2D ovr_Texture0;
+
+varying vec3 ovv_Fade;
+varying vec2 ovv_TexCoordR;
+
+void main (void)
+{
+ // 3 samples for fixing chromatic aberrations
+ vec3 color = texture2D(ovr_Texture0, ovv_TexCoordR).rgb;
+ ovr_FragColor = vec4(ovv_Fade * color, 1.0); // include vignetteFade
+}
+
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_plain.vp b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_plain.vp
new file mode 100644
index 000000000..6456c7a83
--- /dev/null
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_plain.vp
@@ -0,0 +1,27 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 ovr_EyeToSourceUVScale;
+uniform vec2 ovr_EyeToSourceUVOffset;
+
+attribute vec2 ovr_Position;
+attribute vec2 ovr_Params;
+attribute vec2 ovr_TexCoordR;
+
+varying vec3 ovv_Fade;
+varying vec2 ovv_TexCoordR;
+
+void main(void)
+{
+ gl_Position = vec4(ovr_Position.xy, 0.5, 1.0);
+ ovv_Fade = vec3(ovr_Params.r); // vignetteFade
+
+ // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+ // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+ ovv_TexCoordR = ovr_TexCoordR * ovr_EyeToSourceUVScale + ovr_EyeToSourceUVOffset;
+ ovv_TexCoordR.y = 1.0-ovv_TexCoordR.y;
+}
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_timewarp.vp b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_timewarp.vp
new file mode 100644
index 000000000..3485625d2
--- /dev/null
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_timewarp.vp
@@ -0,0 +1,44 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 ovr_EyeToSourceUVScale;
+uniform vec2 ovr_EyeToSourceUVOffset;
+uniform mat4 ovr_EyeRotationStart;
+uniform mat4 ovr_EyeRotationEnd;
+
+attribute vec2 ovr_Position;
+attribute vec2 ovr_Params;
+attribute vec2 ovr_TexCoordR;
+
+varying vec3 ovv_Fade;
+varying vec2 ovv_TexCoordR;
+
+void main(void)
+{
+ gl_Position = vec4(ovr_Position.xy, 0.0, 1.0);
+ ovv_Fade = vec3(ovr_Params.r); // vignetteFade
+
+ // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+ // These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
+ vec3 TanEyeAngle = vec3 ( ovr_TexCoordR, 1.0 );
+
+ // Accurate time warp lerp vs. faster
+ // Apply the two 3x3 timewarp rotations to these vectors.
+ vec3 TransformedStart = (ovr_EyeRotationStart * vec4(TanEyeAngle, 0)).xyz;
+ vec3 TransformedEnd = (ovr_EyeRotationEnd * vec4(TanEyeAngle, 0)).xyz;
+ // And blend between them.
+ vec3 Transformed = mix ( TransformedStart, TransformedEnd, ovr_Params.g /* timewarpLerpFactor */ );
+
+ // Project them back onto the Z=1 plane of the rendered images.
+ float RecipZ = 1.0 / Transformed.z;
+ vec2 Flattened = vec2 ( Transformed.x * RecipZ, Transformed.y * RecipZ );
+
+ // These are now still in TanEyeAngle space.
+ // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+ ovv_TexCoordR = Flattened * ovr_EyeToSourceUVScale + ovr_EyeToSourceUVOffset;
+ ovv_TexCoordR.y = 1.0-ovv_TexCoordR.y;
+}
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_timewarp_chroma.vp b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_timewarp_chroma.vp
new file mode 100644
index 000000000..e2a45e430
--- /dev/null
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/shader/dist01_timewarp_chroma.vp
@@ -0,0 +1,65 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 ovr_EyeToSourceUVScale;
+uniform vec2 ovr_EyeToSourceUVOffset;
+uniform mat4 ovr_EyeRotationStart;
+uniform mat4 ovr_EyeRotationEnd;
+
+attribute vec2 ovr_Position;
+attribute vec2 ovr_Params;
+attribute vec2 ovr_TexCoordR;
+attribute vec2 ovr_TexCoordG;
+attribute vec2 ovr_TexCoordB;
+
+varying vec3 ovv_Fade;
+varying vec2 ovv_TexCoordR;
+varying vec2 ovv_TexCoordG;
+varying vec2 ovv_TexCoordB;
+
+void main(void)
+{
+ gl_Position = vec4(ovr_Position.xy, 0.0, 1.0);
+ ovv_Fade = vec3(ovr_Params.r); // vignetteFade
+
+ // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+ // These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
+ vec3 TanEyeAngleR = vec3 ( ovr_TexCoordR, 1.0 );
+ vec3 TanEyeAngleG = vec3 ( ovr_TexCoordG, 1.0 );
+ vec3 TanEyeAngleB = vec3 ( ovr_TexCoordB, 1.0 );
+
+ // Accurate time warp lerp vs. faster
+ // Apply the two 3x3 timewarp rotations to these vectors.
+ vec3 TransformedRStart = (ovr_EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;
+ vec3 TransformedGStart = (ovr_EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;
+ vec3 TransformedBStart = (ovr_EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;
+ vec3 TransformedREnd = (ovr_EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;
+ vec3 TransformedGEnd = (ovr_EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;
+ vec3 TransformedBEnd = (ovr_EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;
+
+ // And blend between them.
+ vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, ovr_Params.g /* timewarpLerpFactor */ );
+ vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, ovr_Params.g /* timewarpLerpFactor */ );
+ vec3 TransformedB = mix ( TransformedBStart, TransformedBEnd, ovr_Params.g /* timewarpLerpFactor */ );
+
+ // Project them back onto the Z=1 plane of the rendered images.
+ float RecipZR = 1.0 / TransformedR.z;
+ float RecipZG = 1.0 / TransformedG.z;
+ float RecipZB = 1.0 / TransformedB.z;
+ vec2 FlattenedR = vec2 ( TransformedR.x * RecipZR, TransformedR.y * RecipZR );
+ vec2 FlattenedG = vec2 ( TransformedG.x * RecipZG, TransformedG.y * RecipZG );
+ vec2 FlattenedB = vec2 ( TransformedB.x * RecipZB, TransformedB.y * RecipZB );
+
+ // These are now still in TanEyeAngle space.
+ // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+ ovv_TexCoordR = FlattenedR * ovr_EyeToSourceUVScale + ovr_EyeToSourceUVOffset;
+ ovv_TexCoordR.y = 1.0-ovv_TexCoordR.y;
+ ovv_TexCoordG = FlattenedG * ovr_EyeToSourceUVScale + ovr_EyeToSourceUVOffset;
+ ovv_TexCoordG.y = 1.0-ovv_TexCoordG.y;
+ ovv_TexCoordB = FlattenedB * ovr_EyeToSourceUVScale + ovr_EyeToSourceUVOffset;
+ ovv_TexCoordB.y = 1.0-ovv_TexCoordB.y;
+}
diff --git a/src/oculusvr/native/OVRImplMisc.cpp b/src/oculusvr/native/OVRImplMisc.cpp
new file mode 100644
index 000000000..08ebddf62
--- /dev/null
+++ b/src/oculusvr/native/OVRImplMisc.cpp
@@ -0,0 +1,30 @@
+#include "OVR_CAPI.h"
+
+#include "CAPI_DistortionRenderer.h"
+
+namespace OVR { namespace CAPI {
+
+ /**
+ * Index is: apiConfig->Header.API, with
+ * ovrRenderAPIConfig * apiConfig
+ * ovrRenderAPIConfigHeader Header
+ * ovrRenderAPIType Header.API
+ */
+ DistortionRenderer::CreateFunc DistortionRenderer::APICreateRegistry[ovrRenderAPI_Count] =
+ {
+ 0, // None
+ 0, // None for GL - &GL::DistortionRenderer::Create,
+ 0, // Android_GLES
+ 0, // D3D9
+ 0, // D3D10
+ 0 // D3D11
+ };
+
+}} // namespace OVR::CAPI
+
+//
+// TBD: Replace stdc++ for compatibility !
+//
+// This is not enough:
+// extern "C" void __cxa_pure_virtual() { while (1); }
+
diff --git a/src/test-native/Bug907GetAllWindowNamesViaMessageDispatch.c b/src/test-native/Bug907GetAllWindowNamesViaMessageDispatch.c
new file mode 100644
index 000000000..9144e965b
--- /dev/null
+++ b/src/test-native/Bug907GetAllWindowNamesViaMessageDispatch.c
@@ -0,0 +1,34 @@
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include <wingdi.h>
+#include <stddef.h>
+#include <stdio.h>
+
+BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
+{
+ static int i = 0;
+ char buffer[255];
+ BOOL bRet = SendMessageTimeout(hwnd, WM_GETTEXT, 255, (LPARAM)buffer,
+ SMTO_ABORTIFHUNG, 1000/*ms*/, NULL);
+ if(bRet == 0) {
+ fprintf(stderr,"#%4d: FAILURE!\n", i++); fflush(stderr);
+ return FALSE;
+ } else {
+ fprintf(stderr,"#%4d: GOT: %s\n", i++, buffer); fflush(stderr);
+ return TRUE;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ BOOL bRet = EnumWindows(EnumWindowsProc, 0);
+ if(bRet == 0)
+ {
+ fprintf(stderr,"ERROR!");
+ exit(EXIT_FAILURE);
+ }
+ fprintf(stderr,"SUCCESS!");
+ exit(EXIT_SUCCESS);
+}
diff --git a/src/test-native/contextRetargetDrawable01.c b/src/test-native/contextRetargetDrawable01.c
new file mode 100644
index 000000000..bad6c661f
--- /dev/null
+++ b/src/test-native/contextRetargetDrawable01.c
@@ -0,0 +1,154 @@
+/**
+ * compile with: gcc -o contextRetargetDrawable01 contextRetargetDrawable01.c -lX11 -lGL
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+static PFNGLXSWAPINTERVALSGIPROC _glXSwapIntervalSGI = NULL;
+
+static void testRetarget();
+
+static const char * msg = "contextRetargetDrawable01";
+
+static const useconds_t demodelay = 2 * 1000 * 1000;
+
+int main(int nargs, char **vargs) {
+ _glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB("glXSwapIntervalSGI");
+ if(NULL == _glXSwapIntervalSGI) {
+ fprintf(stderr, "No glXSwapIntervalSGI avail, bail out\n");
+ return 1;
+ }
+ testRetarget();
+ return 0;
+}
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height, float c, int swapInterval);
+
+static void testRetarget() {
+ int major, minor;
+ Display *disp1;
+ Window win1;
+ GLXContext ctx1;
+
+ Display *disp2;
+ Window win2;
+ GLXContext ctx2;
+
+ fprintf(stderr, "%s: Create #1\n", msg);
+ disp1 = XOpenDisplay(NULL);
+ createGLWin(disp1, 200, 200, &win1, &ctx1);
+
+ fprintf(stderr, "%s: Create #2\n", msg);
+ disp2 = disp1;
+ // disp2 = XOpenDisplay(NULL);
+ createGLWin(disp2, 300, 300, &win2, &ctx2);
+
+ fprintf(stderr, "%s: Use #1.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.0f, 1); // OK
+
+ fprintf(stderr, "%s: Use #1.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 1.0f, 1); // OK
+
+ usleep( demodelay );
+
+ fprintf(stderr, "%s: Retarget Drawable\n", msg);
+ {
+ Window _win = win2;
+ win2 = win1;
+ win1 = _win;
+ }
+
+ fprintf(stderr, "%s: Use #2.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.0f, 0); // no setSwapInterval - OK
+
+ fprintf(stderr, "%s: Use #2.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 1.0f, 0); // no setSwapInterval - OK
+
+ usleep( demodelay );
+
+ fprintf(stderr, "%s: Use #3.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.1f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+
+ fprintf(stderr, "%s: Use #3.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 0.9f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+
+ fprintf(stderr, "%s: Success - no bug\n", msg);
+
+ usleep( demodelay );
+
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ glXMakeContextCurrent(disp1, 0, 0, 0);
+ glXDestroyContext(disp1, ctx1);
+ if( disp1 != disp2 ) {
+ XCloseDisplay(disp1);
+ }
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+
+ fprintf(stderr, "%s: Destroy #2.0\n", msg);
+ glXMakeContextCurrent(disp2, 0, 0, 0);
+ glXDestroyContext(disp2, ctx2);
+ XCloseDisplay(disp2);
+ fprintf(stderr, "%s: Destroy #2.X\n", msg);
+
+ fprintf(stderr, "%s: Exit - OK\n", msg);
+}
+
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height, float c, int swapInterval)
+{
+ glXMakeContextCurrent(dpy, win, win, ctx);
+ glViewport(0, 0, width, height);
+ if(0 < swapInterval) {
+ fprintf(stderr, "%s: glXSwapIntervalSGI(1)\n", msg);
+ _glXSwapIntervalSGI(1); // offending op after retargeting drawable
+ }
+ fprintf(stderr, "GL_VENDOR: %s\n", glGetString(GL_VENDOR));
+ fprintf(stderr, "GL_VERSION: %s\n", glGetString(GL_VERSION));
+ fprintf(stderr, "GL_RENDERER: %s\n", glGetString(GL_RENDERER));
+ glClearColor(c, c, c, 0.0f);
+ glClearDepth(1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glXSwapBuffers(dpy, win);
+ glXMakeContextCurrent(dpy, 0, 0, 0);
+}
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 4 bits per color and a 16 bit depth buffer */
+static int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 4,
+ GLX_GREEN_SIZE, 4,
+ GLX_BLUE_SIZE, 4,
+ GLX_DEPTH_SIZE, 16,
+ None };
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+ int screen = DefaultScreen(dpy);
+ XVisualInfo *vi = glXChooseVisual(dpy, screen, attrListDbl);
+ Colormap cmap;
+ XSetWindowAttributes attr;
+
+ /* create a GLX context */
+ *rCtx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+
+ /* create a color map */
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+ attr.colormap = cmap;
+ attr.border_pixel = 0;
+
+ /* create a window in window mode*/
+ attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+ StructureNotifyMask;
+ *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+ 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+ CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+ XMapRaised(dpy, *rWin);
+}
+
diff --git a/src/test-native/contextRetargetDrawable02.c b/src/test-native/contextRetargetDrawable02.c
new file mode 100644
index 000000000..3d0807b78
--- /dev/null
+++ b/src/test-native/contextRetargetDrawable02.c
@@ -0,0 +1,382 @@
+/**
+ * compile with: gcc -o contextRetargetDrawable02 contextRetargetDrawable02.c -lX11 -lGL
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+typedef int bool;
+#define true 1
+#define false 0
+
+static PFNGLXSWAPINTERVALSGIPROC _glXSwapIntervalSGI = NULL;
+
+static void testRetarget(bool reverse);
+
+static const char * msg = "contextRetargetDrawable01";
+
+static const useconds_t demodelay = 2 * 1000 * 1000;
+
+int main(int nargs, char **vargs) {
+ _glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB("glXSwapIntervalSGI");
+ if(NULL == _glXSwapIntervalSGI) {
+ fprintf(stderr, "No glXSwapIntervalSGI avail, bail out\n");
+ return 1;
+ }
+ testRetarget(false);
+ return 0;
+}
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height, float c, int swapInterval);
+
+static void testRetarget(bool reverse) {
+ int major, minor;
+ Display *disp1;
+ Window win1;
+ GLXContext ctx1;
+
+ Display *disp2;
+ Window win2;
+ GLXContext ctx2;
+
+ fprintf(stderr, "%s: Create #1\n", msg);
+ disp1 = XOpenDisplay(NULL);
+ createGLWin(disp1, 200, 200, &win1, &ctx1);
+
+ fprintf(stderr, "%s: Create #2\n", msg);
+ disp2 = disp1;
+ // disp2 = XOpenDisplay(NULL);
+ createGLWin(disp2, 300, 300, &win2, &ctx2);
+
+ fprintf(stderr, "%s: Use #1.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.0f, 1); // OK
+
+ fprintf(stderr, "%s: Use #1.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 1.0f, 1); // OK
+
+ usleep( demodelay );
+
+ fprintf(stderr, "%s: Retarget Drawable\n", msg);
+ {
+ GLXContext _ctx = ctx2;
+ ctx2 = ctx1;
+ ctx1 = _ctx;
+ }
+
+ /**
+ if(reverse) {
+ fprintf(stderr, "%s: Use #2.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 1.0f, 0); // no setSwapInterval - OK
+
+ fprintf(stderr, "%s: Use #2.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.0f, 0); // no setSwapInterval - OK
+ } else {
+ fprintf(stderr, "%s: Use #2.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.0f, 0); // no setSwapInterval - OK
+
+ fprintf(stderr, "%s: Use #2.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 1.0f, 0); // no setSwapInterval - OK
+ }
+ usleep( demodelay ); */
+
+ if(reverse) {
+ fprintf(stderr, "%s: Use #3.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 0.9f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+
+ fprintf(stderr, "%s: Use #3.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.1f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+ } else {
+ fprintf(stderr, "%s: Use #3.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.1f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+
+ fprintf(stderr, "%s: Use #3.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 0.9f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+ }
+ fprintf(stderr, "%s: Success - no bug\n", msg);
+ usleep( demodelay );
+
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ glXMakeContextCurrent(disp1, 0, 0, 0);
+ glXDestroyContext(disp1, ctx1);
+ if( disp1 != disp2 ) {
+ XCloseDisplay(disp1);
+ }
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+
+ fprintf(stderr, "%s: Destroy #2.0\n", msg);
+ glXMakeContextCurrent(disp2, 0, 0, 0);
+ glXDestroyContext(disp2, ctx2);
+ XCloseDisplay(disp2);
+ fprintf(stderr, "%s: Destroy #2.X\n", msg);
+
+ fprintf(stderr, "%s: Exit - OK\n", msg);
+}
+
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height, float c, int swapInterval)
+{
+ glXMakeContextCurrent(dpy, win, win, ctx);
+ glViewport(0, 0, width, height);
+ if(0 < swapInterval) {
+ fprintf(stderr, "%s: glXSwapIntervalSGI(1)\n", msg);
+ _glXSwapIntervalSGI(1); // offending op after retargeting drawable
+ }
+ fprintf(stderr, "GL_VENDOR: %s\n", glGetString(GL_VENDOR));
+ fprintf(stderr, "GL_VERSION: %s\n", glGetString(GL_VERSION));
+ fprintf(stderr, "GL_RENDERER: %s\n", glGetString(GL_RENDERER));
+ glClearColor(c, c, c, 0.0f);
+ glClearDepth(1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glXSwapBuffers(dpy, win);
+ glXMakeContextCurrent(dpy, 0, 0, 0);
+}
+
+static volatile bool ctxErrorOccurred = false;
+static int ctxErrorHandler( Display *dpy, XErrorEvent *e )
+{
+ const char * errnoStr = strerror(errno);
+ char errCodeStr[80];
+ char reqCodeStr[80];
+
+ snprintf(errCodeStr, sizeof(errCodeStr), "%d", e->request_code);
+ XGetErrorDatabaseText(dpy, "XRequest", errCodeStr, "Unknown", reqCodeStr, sizeof(reqCodeStr));
+ XGetErrorText(dpy, e->error_code, errCodeStr, sizeof(errCodeStr));
+
+ fprintf(stderr, "X11 Error: %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
+ e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
+ (int)e->request_code, (int)e->minor_code, reqCodeStr);
+ fflush(stderr);
+
+ ctxErrorOccurred = true;
+ return 0;
+}
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 8 bits per color and a 16 bit depth buffer */
+static int visual_attribs[] = {
+ GLX_X_RENDERABLE , True,
+ GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
+ GLX_RENDER_TYPE , GLX_RGBA_BIT,
+ GLX_RED_SIZE , 8,
+ GLX_GREEN_SIZE , 8,
+ GLX_BLUE_SIZE , 8,
+ GLX_DEPTH_SIZE , 16,
+ GLX_DOUBLEBUFFER , True,
+ GLX_STEREO , False,
+ GLX_TRANSPARENT_TYPE, GLX_NONE,
+ //GLX_SAMPLE_BUFFERS , 1,
+ //GLX_SAMPLES , 4,
+ None };
+
+static int context_attribs[] = {
+ GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
+ GLX_CONTEXT_MINOR_VERSION_ARB, 0,
+ GLX_RENDER_TYPE , GLX_RGBA_TYPE,
+ GLX_CONTEXT_FLAGS_ARB , 0,
+ // GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
+ // GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
+ None };
+
+static bool isExtensionSupported(const char *extList, const char *extension);
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+ int glx_major, glx_minor;
+
+ // FBConfigs were added in GLX version 1.3.
+ if ( !glXQueryVersion( dpy, &glx_major, &glx_minor ) ||
+ ( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) )
+ {
+ printf( "Invalid GLX version" );
+ exit(1);
+ }
+
+ int fbcount;
+ GLXFBConfig *fbc = glXChooseFBConfig( dpy, DefaultScreen( dpy ),
+ visual_attribs, &fbcount );
+ if ( !fbc || 0 == fbcount )
+ {
+ printf( "Failed to retrieve a framebuffer config\n" );
+ exit(1);
+ }
+ printf( "Found %d matching FB configs.\n", fbcount );
+
+ GLXFBConfig bestFbc = fbc[ 0 ];
+ int bestFbcID = 0;
+ if( 0 != glXGetFBConfigAttrib( dpy, bestFbc, GLX_FBCONFIG_ID, &bestFbcID ) ) {
+ printf( "Invalid FBConfigID\n" );
+ exit(1);
+ }
+ printf( "Chosen FBConfigID = 0x%x\n", bestFbcID);
+
+ XVisualInfo *vi = glXGetVisualFromFBConfig( dpy, bestFbc );
+ printf( "Chosen visual ID = 0x%x\n", (int) vi->visualid );
+
+ XSetWindowAttributes swa;
+ Colormap cmap;
+ swa.colormap = cmap = XCreateColormap( dpy,
+ RootWindow( dpy, vi->screen ),
+ vi->visual, AllocNone );
+ swa.background_pixmap = None ;
+ swa.border_pixel = 0;
+ swa.event_mask = StructureNotifyMask;
+
+ printf( "Creating window\n" );
+ Window win = XCreateWindow( dpy, RootWindow( dpy, vi->screen ),
+ 0, 0, width, height, 0, vi->depth, InputOutput,
+ vi->visual,
+ CWBorderPixel|CWColormap|CWEventMask, &swa );
+ if ( !win )
+ {
+ printf( "Failed to create window.\n" );
+ exit(1);
+ }
+
+ // Done with the visual info data
+ XFree( vi );
+
+ XStoreName( dpy, win, "GL Window" );
+
+ XMapWindow( dpy, win );
+
+ *rWin = win;
+
+ GLXContext ctx0 = glXCreateNewContext( dpy, bestFbc, GLX_RGBA_TYPE, 0, True );
+ if( !ctx0 ) {
+ printf( "Failed to create intermediate old OpenGL context\n" );
+ exit(1);
+ }
+ glXMakeContextCurrent(dpy, win, win, ctx0);
+
+
+ // Get the default screen's GLX extension list
+ const char *glxExts01 = glXQueryExtensionsString( dpy,
+ DefaultScreen( dpy ) );
+ const char *glxExts02 = glXGetClientString( dpy, GLX_EXTENSIONS);
+ const char *glxExts03 = glXQueryServerString( dpy, DefaultScreen( dpy ), GLX_EXTENSIONS);
+
+ // NOTE: It is not necessary to create or make current to a context before
+ // calling glXGetProcAddressARB
+ PFNGLXCREATECONTEXTATTRIBSARBPROC _glXCreateContextAttribsARB = 0;
+ _glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
+ glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
+
+ // Check for the GLX_ARB_create_context extension string and the function.
+ // If either is not present, use GLX 1.3 context creation method.
+ bool isGLX_ARB_create_contextAvail = isExtensionSupported( glxExts01, "GLX_ARB_create_context" ) ||
+ isExtensionSupported( glxExts02, "GLX_ARB_create_context" ) ||
+ isExtensionSupported( glxExts03, "GLX_ARB_create_context" );
+
+ glXMakeContextCurrent(dpy, 0, 0, 0);
+
+ GLXContext ctx = 0;
+
+ // Install an X error handler so the application won't exit if GL 3.0
+ // context allocation fails.
+ //
+ // Note this error handler is global. All display connections in all threads
+ // of a process use the same error handler, so be sure to guard against other
+ // threads issuing X commands while this code is running.
+ int (*oldHandler)(Display*, XErrorEvent*) =
+ XSetErrorHandler(&ctxErrorHandler);
+
+ if ( !isGLX_ARB_create_contextAvail || !_glXCreateContextAttribsARB )
+ {
+ printf( "glXCreateContextAttribsARB() not found (ext %d, func %p)"
+ " ... using old-style GLX context\n", isGLX_ARB_create_contextAvail, _glXCreateContextAttribsARB );
+ printf( "extensions 01: %s\n", glxExts01);
+ printf( "extensions 02: %s\n", glxExts02);
+ printf( "extensions 03: %s\n", glxExts03);
+ ctx = ctx0;
+ }
+
+ // If it does, try to get a GL 3.0 context!
+ else
+ {
+ printf( "Creating context\n" );
+ XSync( dpy, False );
+ ctxErrorOccurred = false;
+ ctx = _glXCreateContextAttribsARB( dpy, bestFbc, 0, True, context_attribs );
+ XSync( dpy, False );
+
+ if ( !ctxErrorOccurred && ctx ) {
+ printf( "Created GL 3.0 context\n" );
+ glXDestroyContext(dpy, ctx0); // get rid of old ctx
+ } else
+ {
+ // Couldn't create GL 3.0 context. Fall back to old-style 2.x context.
+ // When a context version below 3.0 is requested, implementations will
+ // return the newest context version compatible with OpenGL versions less
+ // than version 3.0.
+ // GLX_CONTEXT_MAJOR_VERSION_ARB = 1
+ context_attribs[1] = 1;
+ // GLX_CONTEXT_MINOR_VERSION_ARB = 0
+ context_attribs[3] = 0;
+
+ printf( "Failed to create GL 3.0 context (err %d, ctx %p)"
+ " ... using old-style GLX context\n", ctxErrorOccurred, (void*)ctx );
+ ctx = ctx0;
+
+ ctxErrorOccurred = false;
+ }
+ }
+
+ // Sync to ensure any errors generated are processed.
+ XSync( dpy, False );
+
+ // Restore the original error handler
+ XSetErrorHandler( oldHandler );
+
+ if ( ctxErrorOccurred || !ctx )
+ {
+ printf( "Failed to create an OpenGL context\n" );
+ exit(1);
+ }
+
+ XFree( fbc );
+
+ *rCtx = ctx;
+}
+
+// Helper to check for extension string presence. Adapted from:
+// http://www.opengl.org/resources/features/OGLextensions/
+static bool isExtensionSupported(const char *extList, const char *extension)
+{
+
+ const char *start;
+ const char *where, *terminator;
+
+ /* Extension names should not have spaces. */
+ where = strchr(extension, ' ');
+ if ( where || *extension == '\0' )
+ return false;
+
+ /* It takes a bit of care to be fool-proof about parsing the
+ OpenGL extensions string. Don't be fooled by sub-strings,
+ etc. */
+ for ( start = extList; ; ) {
+ where = strstr( start, extension );
+
+ if ( !where )
+ break;
+
+ terminator = where + strlen( extension );
+
+ if ( where == start || *(where - 1) == ' ' )
+ if ( *terminator == ' ' || *terminator == '\0' )
+ return true;
+
+ start = terminator;
+ }
+
+ return false;
+}
+
diff --git a/src/test-native/displayMultiple02_mch.c b/src/test-native/displayMultiple02_mch.c
new file mode 100644
index 000000000..c2ab25fbb
--- /dev/null
+++ b/src/test-native/displayMultiple02_mch.c
@@ -0,0 +1,130 @@
+/**
+ * compile with: gcc -o displayMultiple02 displayMultiple02.c -lX11 -lGL
+ */
+
+#include <stdio.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+static void testOrder(int reverseDestroyOrder, const char * msg);
+
+static int useXLockDisplay = 0;
+
+int main(int nargs, char **vargs) {
+ int arg=1;
+ while(arg<nargs) {
+ if(0 == strcmp(vargs[arg], "-xlock")) {
+ useXLockDisplay = 1;
+ }
+ arg++;
+ }
+ fprintf(stderr, "-xlock (XLockDisplay): %d\n", useXLockDisplay);
+
+ if( useXLockDisplay ) {
+ XInitThreads();
+ }
+ testOrder(0, "Normal order");
+ testOrder(1, "Reverse order");
+ return 0;
+}
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height);
+
+static void XLOCKDISPLAY(Display *dpy) {
+ if( useXLockDisplay ) {
+ XLockDisplay(dpy);
+ }
+}
+static void XUNLOCKDISPLAY(Display *dpy) {
+ if( useXLockDisplay ) {
+ XUnlockDisplay(dpy);
+ }
+}
+
+void testOrder(int reverseDestroyOrder, const char * msg) {
+ int major, minor;
+ Display *disp1;
+ Window win1;
+ GLXContext ctx1;
+
+ fprintf(stderr, "%s: Create #1\n", msg);
+ disp1 = XOpenDisplay(NULL);
+ XLOCKDISPLAY(disp1);
+ createGLWin(disp1, 200, 200, &win1, &ctx1);
+ useGL(disp1, win1, ctx1, 200, 200);
+ XUNLOCKDISPLAY(disp1);
+
+ if(reverseDestroyOrder) {
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ XLOCKDISPLAY(disp1);
+ fprintf(stderr, "%s: Destroy #1.1\n", msg);
+ glXMakeCurrent(disp1, 0, 0);
+ fprintf(stderr, "%s: Destroy #1.2\n", msg);
+ glXDestroyContext(disp1, ctx1);
+ fprintf(stderr, "%s: Destroy #1.3\n", msg);
+ XUNLOCKDISPLAY(disp1);
+ fprintf(stderr, "%s: Destroy #1.4\n", msg);
+ XCloseDisplay(disp1);
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+ } else {
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ XLOCKDISPLAY(disp1);
+ glXMakeCurrent(disp1, 0, 0);
+ glXDestroyContext(disp1, ctx1);
+ XUNLOCKDISPLAY(disp1);
+ XCloseDisplay(disp1);
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+ }
+
+ fprintf(stderr, "%s: Success - no bug\n", msg);
+}
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 4 bits per color and a 16 bit depth buffer */
+static int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 4,
+ GLX_GREEN_SIZE, 4,
+ GLX_BLUE_SIZE, 4,
+ GLX_DEPTH_SIZE, 16,
+ None };
+
+void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+ int screen = DefaultScreen(dpy);
+ XVisualInfo *vi = glXChooseVisual(dpy, screen, attrListDbl);
+ Colormap cmap;
+ XSetWindowAttributes attr;
+
+ /* create a GLX context */
+ *rCtx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+ /* create a color map */
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+ attr.colormap = cmap;
+ attr.border_pixel = 0;
+
+ /* create a window in window mode*/
+ attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+ StructureNotifyMask;
+ *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+ 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+ CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+ XMapRaised(dpy, *rWin);
+}
+
+void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height)
+{
+ glXMakeCurrent(dpy, win, ctx);
+ glShadeModel(GL_SMOOTH);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClearDepth(1.0f);
+ glViewport(0, 0, width, height);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glXSwapBuffers(dpy, win);
+ glXMakeCurrent(dpy, 0, 0);
+}
+
diff --git a/src/test-native/displayMultiple02_new_mch.c b/src/test-native/displayMultiple02_new_mch.c
new file mode 100644
index 000000000..f64d41472
--- /dev/null
+++ b/src/test-native/displayMultiple02_new_mch.c
@@ -0,0 +1,199 @@
+/**
+ * compile with: gcc -o displayMultiple02 displayMultiple02.c -lX11 -lGL
+ */
+
+#include <stdio.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+static void testOrder(int reverseDestroyOrder, const char * msg);
+
+static int useXLockDisplay = 0;
+
+int main(int nargs, char **vargs) {
+ int arg=1;
+ while(arg<nargs) {
+ if(0 == strcmp(vargs[arg], "-xlock")) {
+ useXLockDisplay = 1;
+ }
+ arg++;
+ }
+ fprintf(stderr, "-xlock (XLockDisplay): %d\n", useXLockDisplay);
+
+ if( useXLockDisplay ) {
+ XInitThreads();
+ }
+ testOrder(0, "Normal order");
+ testOrder(1, "Reverse order");
+ return 0;
+}
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void createGLWinNew(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height);
+
+static void XLOCKDISPLAY(Display *dpy) {
+ if( useXLockDisplay ) {
+ XLockDisplay(dpy);
+ }
+}
+static void XUNLOCKDISPLAY(Display *dpy) {
+ if( useXLockDisplay ) {
+ XUnlockDisplay(dpy);
+ }
+}
+
+void testOrder(int reverseDestroyOrder, const char * msg) {
+ int major, minor;
+ Display *disp1;
+ Window win1;
+ GLXContext ctx1;
+
+ Display *disp2;
+ Window win2;
+ GLXContext ctx2;
+
+ fprintf(stderr, "%s: Create #1\n", msg);
+ disp1 = XOpenDisplay(NULL);
+ XLOCKDISPLAY(disp1);
+ createGLWinNew(disp1, 200, 200, &win1, &ctx1);
+ useGL(disp1, win1, ctx1, 200, 200);
+ XUNLOCKDISPLAY(disp1);
+
+ fprintf(stderr, "%s: Create #2\n", msg);
+ disp2 = XOpenDisplay(NULL);
+ XLOCKDISPLAY(disp2);
+ createGLWinNew(disp2, 300, 300, &win2, &ctx2);
+ useGL(disp2, win2, ctx2, 300, 300);
+ XUNLOCKDISPLAY(disp2);
+
+ if(reverseDestroyOrder) {
+ fprintf(stderr, "%s: Destroy #2.0\n", msg);
+ XLOCKDISPLAY(disp2);
+ glXMakeCurrent(disp2, 0, 0);
+ glXDestroyContext(disp2, ctx2);
+ XUNLOCKDISPLAY(disp2);
+ XCloseDisplay(disp2);
+ fprintf(stderr, "%s: Destroy #2.X\n", msg);
+
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ XLOCKDISPLAY(disp1);
+ fprintf(stderr, "%s: Destroy #1.1\n", msg);
+ glXMakeCurrent(disp1, 0, 0);
+ fprintf(stderr, "%s: Destroy #1.2\n", msg);
+ glXDestroyContext(disp1, ctx1);
+ fprintf(stderr, "%s: Destroy #1.3\n", msg);
+ XUNLOCKDISPLAY(disp1);
+ fprintf(stderr, "%s: Destroy #1.4\n", msg);
+ XCloseDisplay(disp1);
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+ } else {
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ XLOCKDISPLAY(disp1);
+ glXMakeCurrent(disp1, 0, 0);
+ glXDestroyContext(disp1, ctx1);
+ XUNLOCKDISPLAY(disp1);
+ XCloseDisplay(disp1);
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+
+ fprintf(stderr, "%s: Destroy #2.0\n", msg);
+ XLOCKDISPLAY(disp2);
+ fprintf(stderr, "%s: Destroy #2.1\n", msg);
+ glXMakeCurrent(disp2, 0, 0);
+ fprintf(stderr, "%s: Destroy #2.2\n", msg);
+ glXDestroyContext(disp2, ctx2);
+ fprintf(stderr, "%s: Destroy #2.3\n", msg);
+ XUNLOCKDISPLAY(disp2);
+ fprintf(stderr, "%s: Destroy #2.4\n", msg);
+ XCloseDisplay(disp2);
+ fprintf(stderr, "%s: Destroy #2.X\n", msg);
+ }
+
+ fprintf(stderr, "%s: Success - no bug\n", msg);
+}
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 4 bits per color and a 16 bit depth buffer */
+static int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 4,
+ GLX_GREEN_SIZE, 4,
+ GLX_BLUE_SIZE, 4,
+ GLX_DEPTH_SIZE, 16,
+ None };
+static int attrListDblNew[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DOUBLEBUFFER, True,
+ GLX_BUFFER_SIZE, 24,
+ GLX_DEPTH_SIZE, 24,
+ None };
+
+void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+ int screen = DefaultScreen(dpy);
+ XVisualInfo *vi = glXChooseVisual(dpy, screen, attrListDbl);
+ Colormap cmap;
+ XSetWindowAttributes attr;
+
+ /* create a GLX context */
+ *rCtx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+ /* create a color map */
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+ attr.colormap = cmap;
+ attr.border_pixel = 0;
+
+ /* create a window in window mode*/
+ attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+ StructureNotifyMask;
+ *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+ 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+ CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+ XMapRaised(dpy, *rWin);
+}
+
+void createGLWinNew(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+ int screen = DefaultScreen(dpy);
+ Colormap cmap;
+ XSetWindowAttributes attr;
+
+ // create configs
+ int nelements;
+ GLXFBConfig *fbconfigs = glXChooseFBConfig(dpy,screen,attrListDblNew,&nelements );
+
+ // get visual
+ XVisualInfo *vi = glXGetVisualFromFBConfig(dpy,*fbconfigs);
+
+ /* create a GLX context */
+ *rCtx = glXCreateNewContext(dpy, *fbconfigs, GLX_RGBA_TYPE, 0, GL_TRUE);
+
+ /* create a color map */
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+ attr.colormap = cmap;
+ attr.border_pixel = 0;
+
+ /* create a window in window mode*/
+ attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+ StructureNotifyMask;
+ *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+ 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+ CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+ XMapRaised(dpy, *rWin);
+}
+
+void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height)
+{
+ glXMakeCurrent(dpy, win, ctx);
+ glShadeModel(GL_SMOOTH);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClearDepth(1.0f);
+ glViewport(0, 0, width, height);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glXSwapBuffers(dpy, win);
+ glXMakeCurrent(dpy, 0, 0);
+}
+
diff --git a/src/test-native/glExtensionsListGL2.c b/src/test-native/glExtensionsListGL2.c
index 89815e9c0..ea47b8c69 100644
--- a/src/test-native/glExtensionsListGL2.c
+++ b/src/test-native/glExtensionsListGL2.c
@@ -77,6 +77,8 @@ void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height)
glXMakeCurrent(dpy, win, ctx);
fprintf(stderr, "GL_VENDOR: %s\n", glGetString(GL_VENDOR));
+ fprintf(stderr, "GL_VERSION: %s\n", glGetString(GL_VERSION));
+ fprintf(stderr, "GL_RENDERER: %s\n", glGetString(GL_RENDERER));
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
fprintf(stderr, "GL_NUM_EXTENSIONS: %d\n", n);
diff --git a/src/test-native/glExtensionsListGL3.c b/src/test-native/glExtensionsListGL3.c
index c531577e8..5875c10bc 100644
--- a/src/test-native/glExtensionsListGL3.c
+++ b/src/test-native/glExtensionsListGL3.c
@@ -59,6 +59,8 @@ void dumpGLExtension() {
int i, n;
fprintf(stderr, "GL_VENDOR: %s\n", glGetString(GL_VENDOR));
+ fprintf(stderr, "GL_VERSION: %s\n", glGetString(GL_VERSION));
+ fprintf(stderr, "GL_RENDERER: %s\n", glGetString(GL_RENDERER));
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
fprintf(stderr, "GL_NUM_EXTENSIONS: %d\n", n);
@@ -153,9 +155,6 @@ int main (int argc, char ** argv)
GLXFBConfig bestFbc = fbc[ best_fbc ];
- // Be sure to free the FBConfig list allocated by glXChooseFBConfig()
- XFree( fbc );
-
// Get a visual
XVisualInfo *vi = glXGetVisualFromFBConfig( display, bestFbc );
printf( "Chosen visual ID = 0x%x\n", (int) vi->visualid );
@@ -190,8 +189,9 @@ int main (int argc, char ** argv)
XMapWindow( display, win );
// Get the default screen's GLX extension list
- const char *glxExts = glXQueryExtensionsString( display,
- DefaultScreen( display ) );
+ const char *glxExts01 = glXQueryExtensionsString( display, DefaultScreen( display ) );
+ const char *glxExts02 = glXGetClientString( display, GLX_EXTENSIONS);
+ const char *glxExts03 = glXQueryServerString( display, DefaultScreen( display ), GLX_EXTENSIONS);
// NOTE: It is not necessary to create or make current to a context before
// calling glXGetProcAddressARB
@@ -213,11 +213,16 @@ int main (int argc, char ** argv)
// Check for the GLX_ARB_create_context extension string and the function.
// If either is not present, use GLX 1.3 context creation method.
- if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
- !glXCreateContextAttribsARB )
+ bool isGLX_ARB_create_contextAvail = isExtensionSupported( glxExts01, "GLX_ARB_create_context" ) ||
+ isExtensionSupported( glxExts02, "GLX_ARB_create_context" ) ||
+ isExtensionSupported( glxExts03, "GLX_ARB_create_context" );
+ if ( !isGLX_ARB_create_contextAvail || !glXCreateContextAttribsARB )
{
printf( "glXCreateContextAttribsARB() not found"
" ... using old-style GLX context\n" );
+ printf( "extensions 01: %s\n", glxExts01);
+ printf( "extensions 02: %s\n", glxExts02);
+ printf( "extensions 03: %s\n", glxExts03);
ctx = glXCreateNewContext( display, bestFbc, GLX_RGBA_TYPE, 0, True );
}
@@ -229,7 +234,8 @@ int main (int argc, char ** argv)
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
GLX_RENDER_TYPE , GLX_RGBA_TYPE,
- GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
+ // GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
+ // GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
None
};
@@ -261,6 +267,9 @@ int main (int argc, char ** argv)
}
}
+ // Be sure to free the FBConfig list allocated by glXChooseFBConfig()
+ XFree( fbc );
+
// Sync to ensure any errors generated are processed.
XSync( display, False );
diff --git a/src/test-native/make.sh b/src/test-native/make.sh
index 20bd49e4a..c6d47ff03 100755
--- a/src/test-native/make.sh
+++ b/src/test-native/make.sh
@@ -2,5 +2,9 @@
gcc -o displayMultiple01 displayMultiple01.c -lX11 -lGL
gcc -o displayMultiple02 displayMultiple02.c -lX11 -lGL
+gcc -o displayMultiple02_mch displayMultiple02_mch.c -lX11 -lGL
+gcc -o displayMultiple02_new_mch displayMultiple02_new_mch.c -lX11 -lGL
gcc -o glExtensionsListGL2 glExtensionsListGL2.c -lX11 -lGL
gcc -o glExtensionsListGL3 glExtensionsListGL3.c -lX11 -lGL
+gcc -o contextRetargetDrawable01 contextRetargetDrawable01.c -lX11 -lGL
+gcc -o contextRetargetDrawable02 contextRetargetDrawable02.c -lX11 -lGL
diff --git a/src/test/com/jogamp/opengl/test/android/LauncherUtil.java b/src/test/com/jogamp/opengl/test/android/LauncherUtil.java
index 11416cd67..11dbe12cf 100644
--- a/src/test/com/jogamp/opengl/test/android/LauncherUtil.java
+++ b/src/test/com/jogamp/opengl/test/android/LauncherUtil.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -43,41 +43,45 @@ import android.util.Log;
* Helper class to parse Uri's and programmatically add package names and properties to create an Uri or Intend.
* <p>
* The order of the Uri segments (any arguments) is preserved.
- * </p>
+ * </p>
*/
public class LauncherUtil {
-
+
/** Default launch mode. */
public static final String LAUNCH_ACTIVITY_NORMAL = "org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL";
-
+
/** Transparent launch mode. Note: This seems to be required to achieve translucency, since setTheme(..) doesn't work. */
public static final String LAUNCH_ACTIVITY_TRANSPARENT = "org.jogamp.launcher.action.LAUNCH_ACTIVITY_TRANSPARENT";
-
+
/** FIXME: TODO */
public static final String LAUNCH_MAIN = "org.jogamp.launcher.action.LAUNCH_MAIN";
-
+
/** FIXME: TODO */
public static final String LAUNCH_JUNIT = "org.jogamp.launcher.action.LAUNCH_JUNIT";
-
+
/** The protocol <code>launch</code> */
public static final String SCHEME = "launch";
-
+
/** The host <code>jogamp.org</code> */
public static final String HOST = "jogamp.org";
-
- static final String PKG = "pkg";
-
+
+ static final String SYS_PKG = "sys";
+
+ static final String USR_PKG = "pkg";
+
+ static final String ARG = "arg";
+
public static abstract class BaseActivityLauncher extends Activity {
final OrderedProperties props = new OrderedProperties();
-
- /**
+ final ArrayList<String> args = new ArrayList<String>();
+ /**
* Returns the default {@link LauncherUtil#LAUNCH_ACTIVITY_NORMAL} action.
* <p>
* Should be overridden for other action, eg. {@link LauncherUtil#LAUNCH_ACTIVITY_TRANSPARENT}.
* </p>
*/
public String getAction() { return LAUNCH_ACTIVITY_NORMAL; }
-
+
/**
* Returns the properties, which are being propagated to the target activity.
* <p>
@@ -85,47 +89,66 @@ public class LauncherUtil {
* </p>
*/
public final OrderedProperties getProperties() { return props; }
-
+
+ /**
+ * Returns the commandline arguments, which are being propagated to the target activity.
+ * <p>
+ * Maybe be used to set custom commandline arguments.
+ * </p>
+ */
+ public final ArrayList<String> getArguments() { return args; }
+
/** Custom initialization hook which can be overriden to setup data, e.g. fill the properties retrieved by {@link #getProperties()}. */
public void init() { }
-
+
/** Returns true if this launcher activity shall end after starting the downstream activity. Defaults to <code>true</code>, override to change behavior. */
public boolean finishAfterDelegate() { return true; }
-
+
/** Must return the downstream Activity class name */
public abstract String getActivityName();
-
- /** Must return a list of required packages, at least one. */
- public abstract List<String> getPackages();
+
+ /** Must return a list of required user packages, at least one containing the activity. */
+ public abstract List<String> getUsrPackages();
+
+ /** Return a list of required system packages w/ native libraries, may return null or a zero sized list. */
+ public abstract List<String> getSysPackages();
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
init();
-
+
final DataSet data = new DataSet();
data.setActivityName(getActivityName());
- data.addAllPackages(getPackages());
+ data.addAllSysPackages(getSysPackages());
+ data.addAllUsrPackages(getUsrPackages());
data.addAllProperties(props);
-
+ data.addAllArguments(args);
+
final Intent intent = LauncherUtil.getIntent(getAction(), data);
Log.d(getClass().getSimpleName(), "Launching Activity: "+intent);
startActivity (intent);
-
+
if(finishAfterDelegate()) {
finish(); // done
}
- }
+ }
}
-
+
public static class OrderedProperties {
HashMap<String, String> map = new HashMap<String, String>();
- ArrayList<String> keyList = new ArrayList<String>();
-
- public final void setProperty(String key, String value) {
- if(key.equals(PKG)) {
- throw new IllegalArgumentException("Illegal property key, '"+PKG+"' is reserved");
+ ArrayList<String> keyList = new ArrayList<String>();
+
+ public final void setProperty(final String key, final String value) {
+ if(key.equals(SYS_PKG)) {
+ throw new IllegalArgumentException("Illegal property key, '"+SYS_PKG+"' is reserved");
+ }
+ if(key.equals(USR_PKG)) {
+ throw new IllegalArgumentException("Illegal property key, '"+USR_PKG+"' is reserved");
+ }
+ if(key.equals(ARG)) {
+ throw new IllegalArgumentException("Illegal property key, '"+ARG+"' is reserved");
}
final String oval = map.put(key, value);
if(null != oval) {
@@ -134,36 +157,47 @@ public class LauncherUtil {
}
keyList.add(key); // new key
}
-
- public final void addAll(OrderedProperties props) {
- Iterator<String> argKeys = props.keyList.iterator();
+
+ public final void addAll(final OrderedProperties props) {
+ final Iterator<String> argKeys = props.keyList.iterator();
while(argKeys.hasNext()) {
final String key = argKeys.next();
setProperty(key, props.map.get(key));
- }
+ }
}
-
+
public final void setSystemProperties() {
- Iterator<String> argKeys = keyList.iterator();
+ final Iterator<String> argKeys = keyList.iterator();
while(argKeys.hasNext()) {
final String key = argKeys.next();
System.setProperty(key, map.get(key));
}
}
public final void clearSystemProperties() {
- Iterator<String> argKeys = keyList.iterator();
+ final Iterator<String> argKeys = keyList.iterator();
while(argKeys.hasNext()) {
System.clearProperty(argKeys.next());
}
}
-
- public final String getProperty(String key) { return map.get(key); }
+
+ public final String getProperty(final String key) { return map.get(key); }
public final Map<String, String> getProperties() { return map; }
-
+
/** Returns the list of property keys in the order, as they were added. */
- public final List<String> getPropertyKeys() { return keyList; }
+ public final List<String> getPropertyKeys() { return keyList; }
}
-
+
+ /**
+ * Data set to transfer from and to launch URI consisting out of:
+ * <ul>
+ * <li>system packages w/ native libraries used on Android, which may use a cached ClassLoader, see {@link DataSet#getSysPackages()}.</li>
+ * <li>user packages w/o native libraries used on Android, which do not use a cached ClassLoader, see {@link DataSet#getUsrPackages()}.</li>
+ * <li>activity name, used to launch an Android activity, see {@link DataSet#getActivityName()}.</li>
+ * <li>properties, which will be added to the system properties, see {@link DataSet#getProperties()}.</li>
+ * <li>arguments, used to launch a class main-entry, see {@link DataSet#getArguments()}.</li>
+ * </ul>
+ * {@link DataSet#getUri()} returns a URI representation of all components.
+ */
public static class DataSet {
static final char SLASH = '/';
static final char QMARK = '?';
@@ -171,72 +205,121 @@ public class LauncherUtil {
static final char ASSIG = '=';
static final String COLSLASH2 = "://";
static final String EMPTY = "";
-
+
String activityName = null;
- ArrayList<String> packages = new ArrayList<String>();
+ ArrayList<String> sysPackages = new ArrayList<String>();
+ ArrayList<String> usrPackages = new ArrayList<String>();
OrderedProperties properties = new OrderedProperties();
-
- public final void setActivityName(String name) { activityName = name; }
+ ArrayList<String> arguments = new ArrayList<String>();
+
+ public final void setActivityName(final String name) { activityName = name; }
public final String getActivityName() { return activityName; }
-
- public final void addPackage(String p) {
- packages.add(p);
- }
- public final void addAllPackages(List<String> plist) {
- packages.addAll(plist);
- }
- public final List<String> getPackages() { return packages; }
-
- public final void setProperty(String key, String value) {
+
+ public final void addSysPackage(final String p) {
+ sysPackages.add(p);
+ }
+ public final void addAllSysPackages(final List<String> plist) {
+ sysPackages.addAll(plist);
+ }
+ public final List<String> getSysPackages() { return sysPackages; }
+
+ public final void addUsrPackage(final String p) {
+ usrPackages.add(p);
+ }
+ public final void addAllUsrPackages(final List<String> plist) {
+ usrPackages.addAll(plist);
+ }
+ public final List<String> getUsrPackages() { return usrPackages; }
+
+ public final void setProperty(final String key, final String value) {
properties.setProperty(key, value);
}
- public final void addAllProperties(OrderedProperties props) {
+ public final void addAllProperties(final OrderedProperties props) {
properties.addAll(props);
}
public final void setSystemProperties() {
properties.setSystemProperties();
- }
+ }
public final void clearSystemProperties() {
properties.clearSystemProperties();
- }
- public final String getProperty(String key) { return properties.getProperty(key); }
+ }
+ public final String getProperty(final String key) { return properties.getProperty(key); }
public final OrderedProperties getProperties() { return properties; }
- public final List<String> getPropertyKeys() { return properties.getPropertyKeys(); }
-
+ public final List<String> getPropertyKeys() { return properties.getPropertyKeys(); }
+
+ public final void addArgument(final String arg) { arguments.add(arg); }
+ public final void addAllArguments(final List<String> args) {
+ arguments.addAll(args);
+ }
+ public final ArrayList<String> getArguments() { return arguments; }
+
public final Uri getUri() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append(SCHEME).append(COLSLASH2).append(HOST).append(SLASH).append(getActivityName());
+ boolean needsQMark = true;
boolean needsSep = false;
- if(packages.size()>0) {
- sb.append(QMARK);
- for(int i=0; i<packages.size(); i++) {
+ if(sysPackages.size()>0) {
+ if( needsQMark ) {
+ sb.append(QMARK);
+ needsQMark = false;
+ }
+ for(int i=0; i<sysPackages.size(); i++) {
if(needsSep) {
sb.append(AMPER);
}
- sb.append(PKG).append(ASSIG).append(packages.get(i));
+ sb.append(SYS_PKG).append(ASSIG).append(sysPackages.get(i));
needsSep = true;
}
}
- Iterator<String> argKeys = properties.keyList.iterator();
- while(argKeys.hasNext()) {
+ if(usrPackages.size()>0) {
+ if( needsQMark ) {
+ sb.append(QMARK);
+ needsQMark = false;
+ }
+ for(int i=0; i<usrPackages.size(); i++) {
if(needsSep) {
sb.append(AMPER);
}
- final String key = argKeys.next();
- sb.append(key).append(ASSIG).append(properties.map.get(key));
+ sb.append(USR_PKG).append(ASSIG).append(usrPackages.get(i));
needsSep = true;
+ }
+ }
+ final Iterator<String> propKeys = properties.keyList.iterator();
+ while(propKeys.hasNext()) {
+ if( needsQMark ) {
+ sb.append(QMARK);
+ needsQMark = false;
+ }
+ if(needsSep) {
+ sb.append(AMPER);
+ }
+ final String key = propKeys.next();
+ sb.append(key).append(ASSIG).append(properties.map.get(key));
+ needsSep = true;
+ }
+ final Iterator<String> args = arguments.iterator();
+ while(args.hasNext()) {
+ if( needsQMark ) {
+ sb.append(QMARK);
+ needsQMark = false;
+ }
+ if(needsSep) {
+ sb.append(AMPER);
+ }
+ sb.append(ARG).append(ASSIG).append(args.next());
+ needsSep = true;
}
return Uri.parse(sb.toString());
}
-
- public static final DataSet create(Uri uri) {
+
+ public static final DataSet create(final Uri uri) {
if(!uri.getScheme().equals(SCHEME)) {
return null;
}
if(!uri.getHost().equals(HOST)) {
return null;
}
- DataSet data = new DataSet();
+ final DataSet data = new DataSet();
{
String an = uri.getPath();
if(SLASH == an.charAt(0)) {
@@ -247,16 +330,16 @@ public class LauncherUtil {
}
data.setActivityName(an);
}
-
+
final String q = uri.getQuery();
final int q_l = null != q ? q.length() : -1;
int q_e = -1;
while(q_e < q_l) {
- int q_b = q_e + 1; // next term
+ final int q_b = q_e + 1; // next term
q_e = q.indexOf(AMPER, q_b);
if(0 == q_e) {
- // single seperator
- continue;
+ // single separator
+ continue;
}
if(0 > q_e) {
// end
@@ -269,18 +352,28 @@ public class LauncherUtil {
// assignment
final String k = part.substring(0, assignment);
final String v = part.substring(assignment+1);
- if(k.equals(PKG)) {
+ if(k.equals(SYS_PKG)) {
+ if(v.length()==0) {
+ throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri);
+ }
+ data.addSysPackage(v);
+ } else if(k.equals(USR_PKG)) {
if(v.length()==0) {
throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri);
}
- data.addPackage(v);
+ data.addUsrPackage(v);
+ } else if(k.equals(ARG)) {
+ if(v.length()==0) {
+ throw new IllegalArgumentException("Empty argument name: part <"+part+">, query <"+q+"> of "+uri);
+ }
+ data.addArgument(v);
} else {
data.setProperty(k, v);
}
} else {
// property key only
- if(part.equals(PKG)) {
- throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri);
+ if( part.equals(USR_PKG) || part.equals(ARG) ) {
+ throw new IllegalArgumentException("Reserved key <"+part+"> in query <"+q+"> of "+uri);
}
data.setProperty(part, EMPTY);
}
@@ -288,39 +381,50 @@ public class LauncherUtil {
data.validate();
return data;
}
-
+
public final void validate() {
if(null == activityName) {
throw new RuntimeException("Activity is not NULL");
}
}
}
-
- public final static Intent getIntent(String action, DataSet data) {
+
+ public final static Intent getIntent(final String action, final DataSet data) {
data.validate();
return new Intent(action, data.getUri());
}
-
+
public static void main(String[] args) {
if(args.length==0) {
args = new String[] {
- SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1&"+PKG+"=javax.pack2&"+PKG+"=com.jogamp.pack3&jogamp.common.debug=true&com.jogamp.test=false",
- SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false",
- SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1"
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+SYS_PKG+"=jogamp.pack1&"+SYS_PKG+"=javax.pack2&"+USR_PKG+"=com.jogamp.pack3&"+USR_PKG+"=com.jogamp.pack4&jogamp.common.debug=true&com.jogamp.test=false",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+SYS_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+USR_PKG+"=com.jogamp.pack2",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+USR_PKG+"=javax.pack2&"+USR_PKG+"=com.jogamp.pack3&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3"
};
}
+ int errors = 0;
for(int i=0; i<args.length; i++) {
- String uri_s = args[i];
- Uri uri0 = Uri.parse(uri_s);
- DataSet data = DataSet.create(uri0);
+ final String uri_s = args[i];
+ final Uri uri0 = Uri.parse(uri_s);
+ final DataSet data = DataSet.create(uri0);
if(null == data) {
+ errors++;
System.err.println("Error: NULL JogAmpLauncherUtil: <"+uri_s+"> -> "+uri0+" -> NULL");
- }
- Uri uri1 = data.getUri();
- if(!uri0.equals(uri1)) {
- System.err.println("Error: Not equal: <"+uri_s+"> -> "+uri0+" -> "+uri1);
+ } else {
+ final Uri uri1 = data.getUri();
+ if(!uri0.equals(uri1)) {
+ errors++;
+ System.err.println("Error: Not equal: <"+uri_s+"> -> "+uri0+" -> "+uri1);
+ } else {
+ System.err.println("OK: "+uri1);
+ }
}
}
+ System.err.println("LauncherUtil Self Test: Errors: "+errors);
}
-
+
}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
deleted file mode 100644
index a30262ee3..000000000
--- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * Copyright 2011 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.opengl.test.android;
-
-import java.io.IOException;
-import java.net.URLConnection;
-import java.util.Arrays;
-
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLProfile;
-
-import jogamp.newt.driver.android.NewtBaseActivity;
-
-import com.jogamp.common.util.IOUtil;
-import com.jogamp.newt.NewtFactory;
-import com.jogamp.newt.event.MouseAdapter;
-import com.jogamp.newt.event.MouseEvent;
-import com.jogamp.newt.opengl.GLWindow;
-
-import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube;
-import com.jogamp.opengl.util.Animator;
-
-import android.os.Bundle;
-import android.util.Log;
-
-public class MovieCubeActivity0 extends NewtBaseActivity {
- static String TAG = "MovieCubeActivity0";
-
- MouseAdapter showKeyboardMouseListener = new MouseAdapter() {
- @Override
- public void mousePressed(MouseEvent e) {
- if(e.getPressure()>2f) {
- ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true);
- }
- }
- };
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- String[] urls0 = new String[] {
- System.getProperty("jnlp.media0_url2"),
- System.getProperty("jnlp.media0_url1"),
- System.getProperty("jnlp.media0_url0") };
- final URLConnection urlConnection0 = getResource(urls0, 0);
- if(null == urlConnection0) { throw new RuntimeException("no media reachable: "+Arrays.asList(urls0)); }
-
- // also initializes JOGL
- final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2());
- capsMain.setBackgroundOpaque(false);
-
- // screen for layout params ..
- final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null);
- final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0);
- scrn.addReference();
-
- try {
- final Animator animator = new Animator();
- setAnimator(animator);
-
- // Main
- final MovieCube demoMain = new MovieCube(urlConnection0, -2.3f, 0f, 0f);
- final GLWindow glWindowMain = GLWindow.create(scrn, capsMain);
- glWindowMain.setFullscreen(true);
- setContentView(getWindow(), glWindowMain);
- glWindowMain.addMouseListener(showKeyboardMouseListener);
- glWindowMain.addGLEventListener(demoMain);
- animator.add(glWindowMain);
- glWindowMain.setVisible(true);
-
- // animator.setUpdateFPSFrames(60, System.err);
- animator.setUpdateFPSFrames(-1, null);
- animator.resetFPSCounter();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- scrn.removeReference();
-
- Log.d(TAG, "onCreate - X");
- }
-
- static URLConnection getResource(String path[], int off) {
- URLConnection uc = null;
- for(int i=off; null==uc && i<path.length; i++) {
- if(null != path[i] && path[i].length()>0) {
- uc = IOUtil.getResource(path[i], null);
- Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uc));
- }
- }
- return uc;
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0a.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0a.java
new file mode 100644
index 000000000..66959e90f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0a.java
@@ -0,0 +1,166 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.android;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URISyntaxException;
+import java.net.URLConnection;
+import java.util.Arrays;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import jogamp.newt.driver.android.NewtBaseActivity;
+
+import com.jogamp.common.net.Uri;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.event.MouseAdapter;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+import android.os.Bundle;
+import android.util.Log;
+
+public class MovieCubeActivity0a extends NewtBaseActivity {
+ static String TAG = "MovieCubeActivity0a";
+
+ MouseAdapter showKeyboardMouseListener = new MouseAdapter() {
+ @Override
+ public void mousePressed(final MouseEvent e) {
+ if( e.getPointerCount() == 4 && e.getPressure(0, true) > 0.7f ) {
+ ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true);
+ }
+ }
+ };
+
+ @Override
+ public void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final String[] streamLocs = new String[] {
+ System.getProperty("jnlp.media0_url0"),
+ System.getProperty("jnlp.media0_url1"),
+ System.getProperty("jnlp.media0_url2") };
+ final Uri streamLoc = getUri(streamLocs, 0, false);
+ if(null == streamLoc) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); }
+
+ // also initializes JOGL
+ final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2());
+ capsMain.setBackgroundOpaque(false);
+
+ // screen for layout params ..
+ final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null);
+ final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0);
+ scrn.addReference();
+
+ try {
+ final Animator anim = new Animator();
+
+ // Main
+ final GLWindow glWindowMain = GLWindow.create(scrn, capsMain);
+ glWindowMain.setFullscreen(true);
+ setContentView(getWindow(), glWindowMain);
+ anim.add(glWindowMain);
+ glWindowMain.setVisible(true);
+ glWindowMain.addMouseListener(showKeyboardMouseListener);
+
+ final MovieCube demoMain = new MovieCube(MovieCube.zoom_def, 0f, 0f, false);
+ final GLMediaPlayer mPlayer = demoMain.getGLMediaPlayer();
+ mPlayer.addEventListener(new GLMediaEventListener() {
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) {
+ }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ System.err.println("MovieCubeActivity0 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieCubeActivity0 State: "+mp);
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ glWindowMain.addGLEventListener(demoMain);
+ anim.setUpdateFPSFrames(60*5, null);
+ anim.resetFPSCounter();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
+ anim.resetFPSCounter();
+ }
+ if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
+ final StreamException se = mPlayer.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ getActivity().finish();
+ }
+ }
+ });
+ demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+
+ scrn.removeReference();
+
+ Log.d(TAG, "onCreate - X");
+ }
+
+ static Uri getUri(final String path[], final int off, final boolean checkAvail) {
+ Uri uri = null;
+ for(int i=off; null==uri && i<path.length; i++) {
+ if(null != path[i] && path[i].length()>0) {
+ if( checkAvail ) {
+ final URLConnection uc = IOUtil.getResource(path[i], null);
+ if( null != uc ) {
+ try {
+ uri = Uri.valueOf(uc.getURL());
+ } catch (final URISyntaxException e) {
+ uri = null;
+ }
+ if( uc instanceof HttpURLConnection ) {
+ ((HttpURLConnection)uc).disconnect();
+ }
+ }
+ } else {
+ try {
+ uri = Uri.cast(path[i]);
+ } catch (final URISyntaxException e) {
+ uri = null;
+ }
+ }
+ Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri));
+ }
+ }
+ return uri;
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0b.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0b.java
new file mode 100644
index 000000000..33dbe8fc5
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0b.java
@@ -0,0 +1,168 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.android;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URISyntaxException;
+import java.net.URLConnection;
+import java.util.Arrays;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import jogamp.newt.driver.android.NewtBaseActivity;
+
+import com.jogamp.common.net.Uri;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.event.MouseAdapter;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+import android.os.Bundle;
+import android.util.Log;
+
+public class MovieCubeActivity0b extends NewtBaseActivity {
+ static String TAG = "MovieCubeActivity0a";
+
+ MouseAdapter showKeyboardMouseListener = new MouseAdapter() {
+ @Override
+ public void mousePressed(final MouseEvent e) {
+ if( e.getPointerCount() == 4 && e.getPressure(0, true) > 0.7f ) {
+ ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true);
+ }
+ }
+ };
+
+ @Override
+ public void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final String[] streamLocs = new String[] {
+ System.getProperty("jnlp.media0_url0"),
+ System.getProperty("jnlp.media0_url1"),
+ System.getProperty("jnlp.media0_url2") };
+ final Uri streamLoc = getUri(streamLocs, 0, false);
+ if(null == streamLoc) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); }
+
+ // also initializes JOGL
+ final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2());
+ capsMain.setNumSamples(4);
+ capsMain.setSampleBuffers(true);
+ capsMain.setBackgroundOpaque(false);
+
+ // screen for layout params ..
+ final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null);
+ final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0);
+ scrn.addReference();
+
+ try {
+ final Animator anim = new Animator();
+
+ // Main
+ final GLWindow glWindowMain = GLWindow.create(scrn, capsMain);
+ glWindowMain.setFullscreen(true);
+ setContentView(getWindow(), glWindowMain);
+ anim.add(glWindowMain);
+ glWindowMain.setVisible(true);
+ glWindowMain.addMouseListener(showKeyboardMouseListener);
+
+ final MovieCube demoMain = new MovieCube(MovieCube.zoom_def, 0f, 0f, true);
+ final GLMediaPlayer mPlayer = demoMain.getGLMediaPlayer();
+ mPlayer.addEventListener(new GLMediaEventListener() {
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) {
+ }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ System.err.println("MovieCubeActivity0 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieCubeActivity0 State: "+mp);
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ glWindowMain.addGLEventListener(demoMain);
+ anim.setUpdateFPSFrames(60*5, null);
+ anim.resetFPSCounter();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
+ anim.resetFPSCounter();
+ }
+ if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
+ final StreamException se = mPlayer.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ getActivity().finish();
+ }
+ }
+ });
+ demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+
+ scrn.removeReference();
+
+ Log.d(TAG, "onCreate - X");
+ }
+
+ static Uri getUri(final String path[], final int off, final boolean checkAvail) {
+ Uri uri = null;
+ for(int i=off; null==uri && i<path.length; i++) {
+ if(null != path[i] && path[i].length()>0) {
+ if( checkAvail ) {
+ final URLConnection uc = IOUtil.getResource(path[i], null);
+ if( null != uc ) {
+ try {
+ uri = Uri.valueOf(uc.getURL());
+ } catch (final URISyntaxException e) {
+ uri = null;
+ }
+ if( uc instanceof HttpURLConnection ) {
+ ((HttpURLConnection)uc).disconnect();
+ }
+ }
+ } else {
+ try {
+ uri = Uri.cast(path[i]);
+ } catch (final URISyntaxException e) {
+ uri = null;
+ }
+ }
+ Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri));
+ }
+ }
+ return uri;
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0a.java
index c4b74c56f..f9703fd98 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0a.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -32,50 +32,55 @@ import java.util.List;
import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
-public class MovieCubeActivityLauncher0 extends LauncherUtil.BaseActivityLauncher {
+public class MovieCubeActivityLauncher0a extends LauncherUtil.BaseActivityLauncher {
+
+ static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0a";
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
- static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0";
- // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" };
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
@Override
public void init() {
- final OrderedProperties props = getProperties();
- // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v");
- props.setProperty("jnlp.media0_url2", "");
- props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
+ final OrderedProperties props = getProperties();
+ props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ props.setProperty("jnlp.media1_url1", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
+ props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
// props.setProperty("jogamp.debug.Lock", "true");
// props.setProperty("jogamp.debug.Lock.TraceLock", "true");
// props.setProperty("nativewindow.debug", "all");
- props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// props.setProperty("jogl.debug", "all");
// props.setProperty("jogl.debug.GLProfile", "true");
- props.setProperty("jogl.debug.GLDrawable", "true");
- props.setProperty("jogl.debug.GLContext", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
+ // props.setProperty("jogl.debug.GLContext", "true");
+ props.setProperty("jogl.debug.GLMediaPlayer", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// props.setProperty("jogl.debug.GLSLState", "true");
// props.setProperty("jogl.debug.DebugGL", "true");
// props.setProperty("jogl.debug.TraceGL", "true");
// props.setProperty("newt.debug", "all");
// props.setProperty("newt.debug.Window", "true");
// props.setProperty("newt.debug.Window.MouseEvent", "true");
- // props.setProperty("newt.debug.Window.KeyEvent", "true");
+ // props.setProperty("newt.debug.Window.KeyEvent", "true");
props.setProperty("jogamp.debug.IOUtil", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
+
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0b.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0b.java
new file mode 100644
index 000000000..81d8a3b04
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0b.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.android;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
+
+public class MovieCubeActivityLauncher0b extends LauncherUtil.BaseActivityLauncher {
+
+ static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0b";
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
+ @Override
+ public void init() {
+ final OrderedProperties props = getProperties();
+ props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ props.setProperty("jnlp.media1_url1", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
+ props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
+ // props.setProperty("jogamp.debug.JNILibLoader", "true");
+ // props.setProperty("jogamp.debug.NativeLibrary", "true");
+ // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.Lock", "true");
+ // props.setProperty("jogamp.debug.Lock.TraceLock", "true");
+ // props.setProperty("nativewindow.debug", "all");
+ // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("jogl.debug", "all");
+ // props.setProperty("jogl.debug.GLProfile", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
+ // props.setProperty("jogl.debug.GLContext", "true");
+ // props.setProperty("jogl.debug.GLMediaPlayer", "true");
+ props.setProperty("jogl.debug.GLSLCode", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.GLSLState", "true");
+ // props.setProperty("jogl.debug.DebugGL", "true");
+ // props.setProperty("jogl.debug.TraceGL", "true");
+ // props.setProperty("newt.debug", "all");
+ // props.setProperty("newt.debug.Window", "true");
+ // props.setProperty("newt.debug.Window.MouseEvent", "true");
+ // props.setProperty("newt.debug.Window.KeyEvent", "true");
+ props.setProperty("jogamp.debug.IOUtil", "true");
+ }
+
+ @Override
+ public String getActivityName() {
+ return demo;
+ }
+
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1a.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1a.java
new file mode 100644
index 000000000..205fa8074
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1a.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.android;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
+
+public class MovieCubeActivityLauncher1a extends LauncherUtil.BaseActivityLauncher {
+
+ static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0a";
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
+ @Override
+ public void init() {
+ final OrderedProperties props = getProperties();
+ props.setProperty("jnlp.media0_url0", "camera:/0");
+ props.setProperty("jnlp.media0_url1", "");
+ props.setProperty("jnlp.media1_url2", "");
+ // props.setProperty("jogamp.debug.JNILibLoader", "true");
+ // props.setProperty("jogamp.debug.NativeLibrary", "true");
+ // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.Lock", "true");
+ // props.setProperty("jogamp.debug.Lock.TraceLock", "true");
+ // props.setProperty("nativewindow.debug", "all");
+ // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("jogl.debug", "all");
+ // props.setProperty("jogl.debug.GLProfile", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
+ // props.setProperty("jogl.debug.GLContext", "true");
+ props.setProperty("jogl.debug.GLMediaPlayer", "true");
+ props.setProperty("jogl.debug.GLSLCode", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.GLSLState", "true");
+ // props.setProperty("jogl.debug.DebugGL", "true");
+ // props.setProperty("jogl.debug.TraceGL", "true");
+ // props.setProperty("newt.debug", "all");
+ // props.setProperty("newt.debug.Window", "true");
+ // props.setProperty("newt.debug.Window.MouseEvent", "true");
+ // props.setProperty("newt.debug.Window.KeyEvent", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
+ }
+
+ @Override
+ public String getActivityName() {
+ return demo;
+ }
+
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1b.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1b.java
new file mode 100644
index 000000000..2e85775cf
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1b.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.android;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
+
+public class MovieCubeActivityLauncher1b extends LauncherUtil.BaseActivityLauncher {
+
+ static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0b";
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
+ @Override
+ public void init() {
+ final OrderedProperties props = getProperties();
+ props.setProperty("jnlp.media0_url0", "camera:/1");
+ props.setProperty("jnlp.media0_url1", "");
+ props.setProperty("jnlp.media1_url2", "");
+ // props.setProperty("jogamp.debug.JNILibLoader", "true");
+ // props.setProperty("jogamp.debug.NativeLibrary", "true");
+ // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.Lock", "true");
+ // props.setProperty("jogamp.debug.Lock.TraceLock", "true");
+ // props.setProperty("nativewindow.debug", "all");
+ // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("jogl.debug", "all");
+ // props.setProperty("jogl.debug.GLProfile", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
+ // props.setProperty("jogl.debug.GLContext", "true");
+ // props.setProperty("jogl.debug.GLMediaPlayer", "true");
+ props.setProperty("jogl.debug.GLSLCode", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.GLSLState", "true");
+ // props.setProperty("jogl.debug.DebugGL", "true");
+ // props.setProperty("jogl.debug.TraceGL", "true");
+ // props.setProperty("newt.debug", "all");
+ // props.setProperty("newt.debug.Window", "true");
+ // props.setProperty("newt.debug.Window.MouseEvent", "true");
+ // props.setProperty("newt.debug.Window.KeyEvent", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
+ }
+
+ @Override
+ public String getActivityName() {
+ return demo;
+ }
+
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java
index 89395e309..5991e28ee 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,14 +20,15 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.jogamp.opengl.test.android;
-import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URISyntaxException;
import java.net.URLConnection;
import java.util.Arrays;
@@ -36,84 +37,123 @@ import javax.media.opengl.GLProfile;
import jogamp.newt.driver.android.NewtBaseActivity;
+import com.jogamp.common.net.Uri;
import com.jogamp.common.util.IOUtil;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.opengl.GLWindow;
-
import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple;
import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
import android.os.Bundle;
import android.util.Log;
public class MovieSimpleActivity0 extends NewtBaseActivity {
static String TAG = "MovieSimpleActivity0";
-
+
MouseAdapter toFrontMouseListener = new MouseAdapter() {
- public void mouseClicked(MouseEvent e) {
- Object src = e.getSource();
+ public void mouseClicked(final MouseEvent e) {
+ final Object src = e.getSource();
if(src instanceof Window) {
((Window)src).requestFocus(false);
}
} };
-
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- String[] urls0 = new String[] {
- System.getProperty("jnlp.media0_url2"),
+
+ final String[] streamLocs = new String[] {
+ System.getProperty("jnlp.media0_url0"),
System.getProperty("jnlp.media0_url1"),
- System.getProperty("jnlp.media0_url0") };
- final URLConnection urlConnection0 = getResource(urls0, 0);
- if(null == urlConnection0) { throw new RuntimeException("no media reachable: "+Arrays.asList(urls0)); }
-
+ System.getProperty("jnlp.media0_url2") };
+ final Uri streamLoc = getUri(streamLocs, 0, false);
+ if(null == streamLoc) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); }
+
// also initializes JOGL
final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2());
+ capsMain.setNumSamples(4);
+ capsMain.setSampleBuffers(true);
capsMain.setBackgroundOpaque(false);
// screen for layout params ..
final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null);
final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0);
scrn.addReference();
-
- try {
- final Animator animator = new Animator();
- setAnimator(animator);
-
- // Main
- final MovieSimple demoMain = new MovieSimple(urlConnection0);
- demoMain.setScaleOrig(true);
- final GLWindow glWindowMain = GLWindow.create(scrn, capsMain);
- glWindowMain.setFullscreen(true);
- setContentView(getWindow(), glWindowMain);
- glWindowMain.addGLEventListener(demoMain);
- animator.add(glWindowMain);
- glWindowMain.setVisible(true);
-
- animator.setUpdateFPSFrames(60, System.err);
- // animator.setUpdateFPSFrames(-1, null);
- animator.resetFPSCounter();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
+
+ final Animator anim = new Animator();
+
+ // Main
+ final GLWindow glWindowMain = GLWindow.create(scrn, capsMain);
+ glWindowMain.setFullscreen(true);
+ setContentView(getWindow(), glWindowMain);
+ anim.add(glWindowMain);
+ glWindowMain.setVisible(true);
+
+ final MovieSimple demoMain = new MovieSimple(null);
+ demoMain.setScaleOrig(true);
+ final GLMediaPlayer mPlayer = demoMain.getGLMediaPlayer();
+ mPlayer.addEventListener( new GLMediaPlayer.GLMediaEventListener() {
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) { }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ System.err.println("MovieSimpleActivity0 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieSimpleActivity0 State: "+mp);
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ glWindowMain.addGLEventListener(demoMain);
+ anim.setUpdateFPSFrames(60*5, System.err);
+ anim.resetFPSCounter();
+ }
+ if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
+ final StreamException se = mPlayer.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ getActivity().finish();
+ }
+ }
+ });
+ demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0);
+
scrn.removeReference();
Log.d(TAG, "onCreate - X");
}
-
- static URLConnection getResource(String path[], int off) {
- URLConnection uc = null;
- for(int i=off; null==uc && i<path.length; i++) {
+
+ static Uri getUri(final String path[], final int off, final boolean checkAvail) {
+ Uri uri = null;
+ for(int i=off; null==uri && i<path.length; i++) {
if(null != path[i] && path[i].length()>0) {
- uc = IOUtil.getResource(path[i], null);
- Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uc));
+ if( checkAvail ) {
+ final URLConnection uc = IOUtil.getResource(path[i], null);
+ if( null != uc ) {
+ try {
+ uri = Uri.valueOf(uc.getURL());
+ } catch (final URISyntaxException e) {
+ uri = null;
+ }
+ if( uc instanceof HttpURLConnection ) {
+ ((HttpURLConnection)uc).disconnect();
+ }
+ }
+ } else {
+ try {
+ uri = Uri.cast(path[i]);
+ } catch (final URISyntaxException e) {
+ uri = null;
+ }
+ }
+ Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri));
}
}
- return uc;
+ return uri;
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java
index a7fefd838..0267db514 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.jogamp.opengl.test.android;
-import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URISyntaxException;
import java.net.URLConnection;
import java.util.Arrays;
+import javax.media.nativewindow.util.Rectangle;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
@@ -38,16 +40,19 @@ import javax.media.opengl.GLRunnable;
import jogamp.newt.driver.android.NewtBaseActivity;
+import com.jogamp.common.net.Uri;
import com.jogamp.common.util.IOUtil;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.opengl.GLWindow;
-
import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
import android.os.Bundle;
import android.util.Log;
@@ -55,150 +60,203 @@ import android.view.Gravity;
public class MovieSimpleActivity1 extends NewtBaseActivity {
static String TAG = "MovieSimpleActivity1";
-
+
MouseAdapter toFrontMouseListener = new MouseAdapter() {
- public void mouseClicked(MouseEvent e) {
- Object src = e.getSource();
+ public void mouseClicked(final MouseEvent e) {
+ final Object src = e.getSource();
if(src instanceof Window) {
((Window)src).requestFocus(false);
}
} };
-
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- final boolean mPlayerLocal = Boolean.valueOf(System.getProperty("jnlp.mplayer.local"));
+
final boolean mPlayerNoZoom = Boolean.valueOf(System.getProperty("jnlp.mplayer.nozoom"));
final boolean mPlayerHUD = Boolean.valueOf(System.getProperty("jnlp.mplayer.hud"));
final boolean mPlayerSharedHUD = mPlayerHUD && Boolean.valueOf(System.getProperty("jnlp.mplayer.hud.shared"));
- Log.d(TAG, "onCreate - 0 - mPlayerLocal "+mPlayerLocal+", mPlayerNoScale "+mPlayerNoZoom+", mPlayerHUD "+mPlayerHUD+", mPlayerSharedHUD "+mPlayerSharedHUD);
-
- String[] urls0 = new String[] {
- System.getProperty("jnlp.media0_url2"),
+ Log.d(TAG, "onCreate - 0 - mPlayerNoScale "+mPlayerNoZoom+", mPlayerHUD "+mPlayerHUD+", mPlayerSharedHUD "+mPlayerSharedHUD);
+
+ final String[] streamLocs = new String[] {
+ System.getProperty("jnlp.media0_url0"),
System.getProperty("jnlp.media0_url1"),
- System.getProperty("jnlp.media0_url0") };
- final URLConnection urlConnection0 = getResource(urls0, mPlayerLocal ? 2 : 0);
- if(null == urlConnection0) { throw new RuntimeException("no media reachable: "+Arrays.asList(urls0)); }
-
- final URLConnection urlConnection1;
+ System.getProperty("jnlp.media0_url2") };
+ final Uri streamLoc0 = getUri(streamLocs, 2, false);
+ if(null == streamLoc0) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); }
+
+ final Uri streamLoc1;
{
- URLConnection _urlConnection1 = null;
+ Uri _streamLoc1 = null;
if(mPlayerHUD && !mPlayerSharedHUD) {
- String[] urls1 = new String[] { System.getProperty("jnlp.media1_url0") };
- _urlConnection1 = getResource(urls1, 0);
+ final String[] urls1 = new String[] { System.getProperty("jnlp.media1_url0") };
+ _streamLoc1 = getUri(urls1, 1, false);
}
- if(null == _urlConnection1) { _urlConnection1 = urlConnection0; }
- urlConnection1 = _urlConnection1;
+ if(null == _streamLoc1) { _streamLoc1 = streamLoc0; }
+ streamLoc1 = _streamLoc1;
}
-
+
setTransparencyTheme();
setFullscreenFeature(getWindow(), true);
-
+
final android.view.ViewGroup viewGroup = new android.widget.FrameLayout(getActivity().getApplicationContext());
getWindow().setContentView(viewGroup);
-
+
// also initializes JOGL
final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2());
+ capsMain.setNumSamples(4);
+ capsMain.setSampleBuffers(true);
capsMain.setBackgroundOpaque(!mPlayerHUD);
// screen for layout params ..
final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null);
final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0);
scrn.addReference();
-
- try {
- final Animator animator = new Animator();
- setAnimator(animator);
-
- // Main
- final MovieSimple demoMain = new MovieSimple(urlConnection0);
- if(mPlayerHUD) {
- demoMain.setEffects(MovieSimple.EFFECT_GRADIENT_BOTTOM2TOP);
- demoMain.setTransparency(0.9f);
- }
- demoMain.setScaleOrig(mPlayerNoZoom);
- final GLWindow glWindowMain = GLWindow.create(scrn, capsMain);
- {
- final int padding = mPlayerHUD ? 32 : 0;
- final android.view.View androidView = ((jogamp.newt.driver.android.WindowDriver)glWindowMain.getDelegatedWindow()).getAndroidView();
- glWindowMain.setSize(scrn.getWidth()-padding, scrn.getHeight()-padding);
- glWindowMain.setUndecorated(true);
- // setContentView(getWindow(), glWindowMain);
- viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowMain.getWidth(), glWindowMain.getHeight(), Gravity.BOTTOM|Gravity.RIGHT));
- registerNEWTWindow(glWindowMain);
+
+ final Animator anim = new Animator();
+
+ // Main
+ final GLWindow glWindowMain = GLWindow.create(scrn, capsMain);
+ {
+ final int padding = mPlayerHUD ? 32 : 0;
+ final android.view.View androidView = ((jogamp.newt.driver.android.WindowDriver)glWindowMain.getDelegatedWindow()).getAndroidView();
+ glWindowMain.setSurfaceSize(scrn.getWidth()-padding, scrn.getHeight()-padding);
+ glWindowMain.setUndecorated(true);
+ // setContentView(getWindow(), glWindowMain);
+ viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowMain.getSurfaceWidth(), glWindowMain.getSurfaceHeight(), Gravity.BOTTOM|Gravity.RIGHT));
+ registerNEWTWindow(glWindowMain);
+ }
+ anim.add(glWindowMain);
+ glWindowMain.setVisible(true);
+
+ final MovieSimple demoMain = new MovieSimple(null);
+ final GLMediaPlayer mPlayerMain = demoMain.getGLMediaPlayer();
+ if(mPlayerHUD) {
+ demoMain.setEffects(MovieSimple.EFFECT_GRADIENT_BOTTOM2TOP);
+ demoMain.setTransparency(0.9f);
+ }
+ demoMain.setScaleOrig(mPlayerNoZoom);
+ mPlayerMain.addEventListener( new GLMediaPlayer.GLMediaEventListener() {
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) { }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ System.err.println("MovieSimpleActivity1 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieSimpleActivity1 State: "+mp);
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ glWindowMain.addGLEventListener(demoMain);
+ anim.setUpdateFPSFrames(60*5, System.err);
+ anim.resetFPSCounter();
+ }
+ if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
+ final StreamException se = mPlayerMain.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ getActivity().finish();
+ }
}
-
- glWindowMain.addGLEventListener(demoMain);
- animator.add(glWindowMain);
- glWindowMain.setVisible(true);
-
- if(mPlayerHUD) {
- final GLMediaPlayer sharedPlayer = mPlayerSharedHUD ? demoMain.getGLMediaPlayer() : null;
- final GLCapabilities capsHUD = new GLCapabilities(GLProfile.getGL2ES2());
- capsHUD.setBackgroundOpaque(false);
- final GLWindow glWindowHUD = GLWindow.create(scrn, capsHUD);
- glWindowMain.invoke(false, new GLRunnable() {
- @Override
- public boolean run(GLAutoDrawable drawable) {
- int x2 = scrn.getX();
- int y2 = scrn.getY();
- int w2 = scrn.getWidth()/3;
- int h2 = scrn.getHeight()/3;
- if(null != sharedPlayer) {
- if(0 < sharedPlayer.getWidth() && sharedPlayer.getWidth()<scrn.getWidth()/2 &&
- 0 < sharedPlayer.getHeight() && sharedPlayer.getHeight()<scrn.getHeight()/2) {
- w2 = sharedPlayer.getWidth();
- h2 = sharedPlayer.getHeight();
- }
- glWindowHUD.setSharedContext(glWindowMain.getContext());
- glWindowHUD.addGLEventListener(new MovieSimple(sharedPlayer));
- } else {
- try {
- glWindowHUD.addGLEventListener(new MovieSimple(urlConnection1));
- } catch (IOException e) {
- e.printStackTrace();
+ });
+ demoMain.initStream(streamLoc0, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0);
+
+ if(mPlayerHUD) {
+ final GLMediaPlayer mPlayerShared = mPlayerSharedHUD ? mPlayerMain : null;
+ final GLCapabilities capsHUD = new GLCapabilities(GLProfile.getGL2ES2());
+ capsHUD.setNumSamples(4);
+ capsHUD.setSampleBuffers(true);
+ capsHUD.setBackgroundOpaque(false);
+ final GLWindow glWindowHUD = GLWindow.create(scrn, capsHUD);
+ glWindowMain.invoke(false, new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ final GLMediaPlayer mPlayerSub;
+ final MovieSimple demoHUD;
+ final Rectangle windowBounds = (Rectangle) scrn.getViewportInWindowUnits().cloneMutable();
+ if(null != mPlayerShared) {
+ if(0 < mPlayerShared.getWidth() && mPlayerShared.getWidth()<scrn.getWidth()/2 &&
+ 0 < mPlayerShared.getHeight() && mPlayerShared.getHeight()<scrn.getHeight()/2) {
+ final int[] wh = glWindowHUD.convertToWindowUnits(new int[]{mPlayerShared.getWidth(), mPlayerShared.getHeight()});
+ windowBounds.setWidth( wh[0] );
+ windowBounds.setHeight( wh[1] );
+ }
+ glWindowHUD.setSharedAutoDrawable(glWindowMain);
+ demoHUD = new MovieSimple(mPlayerShared);
+ mPlayerSub = mPlayerShared;
+ } else {
+ demoHUD = new MovieSimple(null);
+ mPlayerSub = demoHUD.getGLMediaPlayer();
+ }
+ mPlayerSub.addEventListener( new GLMediaPlayer.GLMediaEventListener() {
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) { }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ glWindowHUD.addGLEventListener(demoHUD);
+ }
+ if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
+ final StreamException se = mPlayerMain.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ getActivity().finish();
}
- }
- glWindowHUD.setPosition(x2, y2);
- glWindowHUD.setSize(w2, h2);
- System.err.println("HUD: "+mPlayerHUD);
- System.err.println("HUD: "+w2+"x"+h2);
- glWindowHUD.addMouseListener(toFrontMouseListener);
-
- viewGroup.post(new Runnable() {
- public void run() {
- final android.view.View androidView = ((jogamp.newt.driver.android.WindowDriver)glWindowHUD.getDelegatedWindow()).getAndroidView();
- // addContentView(getWindow(), glWindowHUD, new android.view.ViewGroup.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight()));
- viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight(), Gravity.TOP|Gravity.LEFT));
- registerNEWTWindow(glWindowHUD);
- animator.add(glWindowHUD);
- glWindowHUD.setVisible(true);
- } } );
- return true;
- } } );
- }
-
- animator.setUpdateFPSFrames(60, System.err);
- // animator.setUpdateFPSFrames(-1, null);
- animator.resetFPSCounter();
- } catch (IOException e) {
- e.printStackTrace();
+ }
+ });
+ demoHUD.initStream(streamLoc1, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0);
+
+ glWindowHUD.setPosition(windowBounds.getX(), windowBounds.getY());
+ glWindowHUD.setSize(windowBounds.getWidth(), windowBounds.getHeight());
+ System.err.println("HUD: "+mPlayerHUD);
+ System.err.println("HUD: "+windowBounds);
+ glWindowHUD.addMouseListener(toFrontMouseListener);
+
+ viewGroup.post(new Runnable() {
+ public void run() {
+ final android.view.View androidView = ((jogamp.newt.driver.android.WindowDriver)glWindowHUD.getDelegatedWindow()).getAndroidView();
+ // addContentView(getWindow(), glWindowHUD, new android.view.ViewGroup.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight()));
+ viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowHUD.getSurfaceWidth(), glWindowHUD.getSurfaceHeight(), Gravity.TOP|Gravity.LEFT));
+ registerNEWTWindow(glWindowHUD);
+ anim.add(glWindowHUD);
+ glWindowHUD.setVisible(true);
+ } } );
+ return true;
+ } } );
}
-
+
scrn.removeReference();
Log.d(TAG, "onCreate - X");
}
-
- static URLConnection getResource(String path[], int off) {
- URLConnection uc = null;
- for(int i=off; null==uc && i<path.length; i++) {
+
+ static Uri getUri(final String path[], final int off, final boolean checkAvail) {
+ Uri uri = null;
+ for(int i=off; null==uri && i<path.length; i++) {
if(null != path[i] && path[i].length()>0) {
- uc = IOUtil.getResource(path[i], null);
- Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uc));
+ if( checkAvail ) {
+ final URLConnection uc = IOUtil.getResource(path[i], null);
+ if( null != uc ) {
+ try {
+ uri = Uri.valueOf(uc.getURL());
+ } catch (final URISyntaxException e) {
+ uri = null;
+ }
+ if( uc instanceof HttpURLConnection ) {
+ ((HttpURLConnection)uc).disconnect();
+ }
+ }
+ } else {
+ try {
+ uri = Uri.cast(path[i]);
+ } catch (final URISyntaxException e) {
+ uri = null;
+ }
+ }
+ Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri));
}
}
- return uc;
+ return uri;
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java
index 8c08e987f..bcc20f770 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -34,33 +34,29 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class MovieSimpleActivityLauncher00b extends LauncherUtil.BaseActivityLauncher {
- static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1";
- // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" };
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity0";
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
- props.setProperty("jnlp.mplayer.nozoom", "false");
- props.setProperty("jnlp.mplayer.hud", "false");
- props.setProperty("jnlp.mplayer.hud.shared", "false");
- // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v");
- props.setProperty("jnlp.media0_url2", "");
- props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
+ final OrderedProperties props = getProperties();
+ props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ props.setProperty("jnlp.media0_url1", "http://video.webmfiles.org/big-buck-bunny_trailer.webm");
+ props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
// props.setProperty("nativewindow.debug", "all");
- props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// props.setProperty("jogl.debug", "all");
// props.setProperty("jogl.debug.GLProfile", "true");
- props.setProperty("jogl.debug.GLDrawable", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
props.setProperty("jogl.debug.GLContext", "true");
+ props.setProperty("jogl.debug.GLMediaPlayer", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// props.setProperty("jogl.debug.GLSLState", "true");
// props.setProperty("jogl.debug.DebugGL", "true");
// props.setProperty("jogl.debug.TraceGL", "true");
@@ -70,13 +66,18 @@ public class MovieSimpleActivityLauncher00b extends LauncherUtil.BaseActivityLau
// props.setProperty("newt.debug.Window.KeyEvent", "true");
props.setProperty("jogamp.debug.IOUtil", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00c.java
index fbb0223f8..e9636fb39 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00c.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -32,35 +32,31 @@ import java.util.List;
import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
-public class MovieSimpleActivityLauncher00a extends LauncherUtil.BaseActivityLauncher {
+public class MovieSimpleActivityLauncher00c extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity0";
- // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" };
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
- props.setProperty("jnlp.mplayer.nozoom", "true");
- props.setProperty("jnlp.mplayer.hud", "false");
- props.setProperty("jnlp.mplayer.hud.shared", "false");
- // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v");
+ final OrderedProperties props = getProperties();
+ props.setProperty("jnlp.media0_url0", "camera:/0");
+ props.setProperty("jnlp.media0_url1", "");
props.setProperty("jnlp.media0_url2", "");
- props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
// props.setProperty("nativewindow.debug", "all");
- props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// props.setProperty("jogl.debug", "all");
// props.setProperty("jogl.debug.GLProfile", "true");
- props.setProperty("jogl.debug.GLDrawable", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
props.setProperty("jogl.debug.GLContext", "true");
+ props.setProperty("jogl.debug.GLMediaPlayer", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// props.setProperty("jogl.debug.GLSLState", "true");
// props.setProperty("jogl.debug.DebugGL", "true");
// props.setProperty("jogl.debug.TraceGL", "true");
@@ -68,15 +64,20 @@ public class MovieSimpleActivityLauncher00a extends LauncherUtil.BaseActivityLau
// props.setProperty("newt.debug.Window", "true");
// props.setProperty("newt.debug.Window.MouseEvent", "true");
// props.setProperty("newt.debug.Window.KeyEvent", "true");
- props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java
index b2a3facbd..5fbd90751 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -35,32 +35,31 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class MovieSimpleActivityLauncher01a extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1";
- // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" };
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
+ final OrderedProperties props = getProperties();
props.setProperty("jnlp.mplayer.nozoom", "true");
props.setProperty("jnlp.mplayer.hud", "true");
props.setProperty("jnlp.mplayer.hud.shared", "true");
- // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v");
- props.setProperty("jnlp.media0_url2", "");
- props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
+ props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ props.setProperty("jnlp.media1_url1", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
+ props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
// props.setProperty("nativewindow.debug", "all");
- props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// props.setProperty("jogl.debug", "all");
// props.setProperty("jogl.debug.GLProfile", "true");
- props.setProperty("jogl.debug.GLDrawable", "true");
- props.setProperty("jogl.debug.GLContext", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
+ // props.setProperty("jogl.debug.GLContext", "true");
+ // props.setProperty("jogl.debug.GLMediaPlayer", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// props.setProperty("jogl.debug.GLSLState", "true");
// props.setProperty("jogl.debug.DebugGL", "true");
// props.setProperty("jogl.debug.TraceGL", "true");
@@ -70,13 +69,18 @@ public class MovieSimpleActivityLauncher01a extends LauncherUtil.BaseActivityLau
// props.setProperty("newt.debug.Window.KeyEvent", "true");
props.setProperty("jogamp.debug.IOUtil", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java
index 905e2628d..d9f6244a6 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -35,32 +35,31 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class MovieSimpleActivityLauncher01b extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1";
- // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" };
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
+ final OrderedProperties props = getProperties();
props.setProperty("jnlp.mplayer.nozoom", "false");
props.setProperty("jnlp.mplayer.hud", "true");
props.setProperty("jnlp.mplayer.hud.shared", "true");
- // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v");
- props.setProperty("jnlp.media0_url2", "");
- props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
+ props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ props.setProperty("jnlp.media1_url1", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
+ props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
// props.setProperty("nativewindow.debug", "all");
- props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// props.setProperty("jogl.debug", "all");
// props.setProperty("jogl.debug.GLProfile", "true");
- props.setProperty("jogl.debug.GLDrawable", "true");
- props.setProperty("jogl.debug.GLContext", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
+ // props.setProperty("jogl.debug.GLContext", "true");
+ // props.setProperty("jogl.debug.GLMediaPlayer", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// props.setProperty("jogl.debug.GLSLState", "true");
// props.setProperty("jogl.debug.DebugGL", "true");
// props.setProperty("jogl.debug.TraceGL", "true");
@@ -70,13 +69,18 @@ public class MovieSimpleActivityLauncher01b extends LauncherUtil.BaseActivityLau
// props.setProperty("newt.debug.Window.KeyEvent", "true");
props.setProperty("jogamp.debug.IOUtil", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java
index 369457946..09f4f9224 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -35,32 +35,31 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class MovieSimpleActivityLauncher02 extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1";
- // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" };
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
+ final OrderedProperties props = getProperties();
props.setProperty("jnlp.mplayer.nozoom", "false");
props.setProperty("jnlp.mplayer.hud", "true");
props.setProperty("jnlp.mplayer.hud.shared", "false");
- // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v");
- props.setProperty("jnlp.media0_url2", "");
- props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
- props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
+ props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ props.setProperty("jnlp.media1_url1", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4");
+ props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4");
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
// props.setProperty("nativewindow.debug", "all");
- props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// props.setProperty("jogl.debug", "all");
// props.setProperty("jogl.debug.GLProfile", "true");
- props.setProperty("jogl.debug.GLDrawable", "true");
- props.setProperty("jogl.debug.GLContext", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
+ // props.setProperty("jogl.debug.GLContext", "true");
+ // props.setProperty("jogl.debug.GLMediaPlayer", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// props.setProperty("jogl.debug.GLSLState", "true");
// props.setProperty("jogl.debug.DebugGL", "true");
// props.setProperty("jogl.debug.TraceGL", "true");
@@ -70,13 +69,18 @@ public class MovieSimpleActivityLauncher02 extends LauncherUtil.BaseActivityLaun
// props.setProperty("newt.debug.Window.KeyEvent", "true");
props.setProperty("jogamp.debug.IOUtil", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java
index d1c8f2743..9183e572c 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile;
import jogamp.newt.driver.android.NewtBaseActivity;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es2.ElektronenMultiplizierer;
@@ -44,34 +44,35 @@ import android.util.Log;
public class NEWTElektronActivity extends NewtBaseActivity {
static String TAG = "NEWTElektronActivity";
-
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "onCreate - 0");
super.onCreate(savedInstanceState);
-
+
// create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
- GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2));
Log.d(TAG, "req caps: "+caps);
- GLWindow glWindow = GLWindow.create(caps);
+ final GLWindow glWindow = GLWindow.create(caps);
glWindow.setFullscreen(true);
setContentView(getWindow(), glWindow);
-
+
glWindow.addGLEventListener(new ElektronenMultiplizierer());
- glWindow.getScreen().addScreenModeListener(new ScreenModeListener() {
- public void screenModeChangeNotify(ScreenMode sm) { }
- public void screenModeChanged(ScreenMode sm, boolean success) {
- System.err.println("ScreenMode Changed: "+sm);
- }
+ glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() {
+ @Override
+ public void monitorModeChangeNotify(final MonitorEvent me) { }
+ @Override
+ public void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ System.err.println("MonitorMode Changed (success "+success+"): "+me);
+ }
});
glWindow.setVisible(true);
- Animator animator = new Animator(glWindow);
- setAnimator(animator);
-
+ final Animator animator = new Animator(glWindow);
+
animator.setUpdateFPSFrames(60, System.err);
animator.resetFPSCounter();
glWindow.resetFPSCounter();
-
+
Log.d(TAG, "onCreate - X");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTElektronActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTElektronActivityLauncher.java
index 33e05de8d..95504b7a7 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTElektronActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTElektronActivityLauncher.java
@@ -8,15 +8,16 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class NEWTElektronActivityLauncher extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.NEWTElektronActivity";
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
+ final OrderedProperties props = getProperties();
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // properties.setProperty("jogamp.debug.IOUtil", "true");
+ // properties.setProperty("jogamp.debug.IOUtil", "true");
// properties.setProperty("nativewindow.debug", "all");
props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// properties.setProperty("jogl.debug", "all");
@@ -24,7 +25,7 @@ public class NEWTElektronActivityLauncher extends LauncherUtil.BaseActivityLaunc
props.setProperty("jogl.debug.GLDrawable", "true");
props.setProperty("jogl.debug.GLContext", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// properties.setProperty("jogl.debug.GLSLState", "true");
// properties.setProperty("jogl.debug.DebugGL", "true");
// properties.setProperty("jogl.debug.TraceGL", "true");
@@ -33,13 +34,18 @@ public class NEWTElektronActivityLauncher extends LauncherUtil.BaseActivityLaunc
// properties.setProperty("newt.debug.Window.MouseEvent", "true");
// properties.setProperty("newt.debug.Window.KeyEvent", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java
index c24c3af28..3ec85c108 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile;
import jogamp.newt.driver.android.NewtBaseActivity;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1;
@@ -44,39 +44,40 @@ import android.util.Log;
public class NEWTGearsES1Activity extends NewtBaseActivity {
static String TAG = "NEWTGearsES1Activity";
-
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "onCreate - 0");
super.onCreate(savedInstanceState);
-
+
// create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
- GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES1));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES1));
/*
caps.setRedBits(5);
caps.setGreenBits(6);
caps.setBlueBits(5);
caps.setAlphaBits(0); */
Log.d(TAG, "req caps: "+caps);
- GLWindow glWindow = GLWindow.create(caps);
+ final GLWindow glWindow = GLWindow.create(caps);
glWindow.setFullscreen(true);
setContentView(getWindow(), glWindow);
-
+
glWindow.addGLEventListener(new GearsES1(-1));
- glWindow.getScreen().addScreenModeListener(new ScreenModeListener() {
- public void screenModeChangeNotify(ScreenMode sm) { }
- public void screenModeChanged(ScreenMode sm, boolean success) {
- System.err.println("ScreenMode Changed: "+sm);
- }
+ glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() {
+ @Override
+ public void monitorModeChangeNotify(final MonitorEvent me) { }
+ @Override
+ public void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ System.err.println("MonitorMode Changed (success "+success+"): "+me);
+ }
});
glWindow.setVisible(true);
- Animator animator = new Animator(glWindow);
- setAnimator(animator);
-
+ final Animator animator = new Animator(glWindow);
+
animator.setUpdateFPSFrames(60, System.err);
animator.resetFPSCounter();
glWindow.resetFPSCounter();
-
+
Log.d(TAG, "onCreate - X");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES1ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES1ActivityLauncher.java
index d0f6263f3..db4d57825 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES1ActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES1ActivityLauncher.java
@@ -7,15 +7,16 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class NEWTGearsES1ActivityLauncher extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.NEWTGearsES1Activity";
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
+ final OrderedProperties props = getProperties();
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // properties.setProperty("jogamp.debug.IOUtil", "true");
+ // properties.setProperty("jogamp.debug.IOUtil", "true");
// properties.setProperty("nativewindow.debug", "all");
props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// properties.setProperty("jogl.debug", "all");
@@ -23,7 +24,7 @@ public class NEWTGearsES1ActivityLauncher extends LauncherUtil.BaseActivityLaunc
props.setProperty("jogl.debug.GLDrawable", "true");
props.setProperty("jogl.debug.GLContext", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// properties.setProperty("jogl.debug.GLSLState", "true");
// properties.setProperty("jogl.debug.DebugGL", "true");
// properties.setProperty("jogl.debug.TraceGL", "true");
@@ -32,13 +33,18 @@ public class NEWTGearsES1ActivityLauncher extends LauncherUtil.BaseActivityLaunc
// properties.setProperty("newt.debug.Window.MouseEvent", "true");
// properties.setProperty("newt.debug.Window.KeyEvent", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java
index 4468868f6..25eb25892 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,22 +20,26 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.jogamp.opengl.test.android;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import jogamp.newt.driver.android.NewtBaseActivity;
-import com.jogamp.newt.ScreenMode;
+import com.jogamp.newt.event.MonitorEvent;
import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorModeListener;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
@@ -46,47 +50,83 @@ import android.util.Log;
public class NEWTGearsES2Activity extends NewtBaseActivity {
static String TAG = "NEWTGearsES2Activity";
-
+
+ static final String forceRGBA5650 = "demo.force.rgba5650";
+ static final String forceECT = "demo.force.ect";
+ static final String forceKillProcessTest = "demo.force.killProcessTest";
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "onCreate - 0");
super.onCreate(savedInstanceState);
-
+
// create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
- GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2));
+ if( null != System.getProperty(forceRGBA5650) ) {
+ Log.d(TAG, "forceRGBA5650");
+ caps.setRedBits(5); caps.setGreenBits(6); caps.setBlueBits(5);
+ }
+
Log.d(TAG, "req caps: "+caps);
- GLWindow glWindow = GLWindow.create(caps);
+ final GLWindow glWindow = GLWindow.create(caps);
glWindow.setFullscreen(true);
setContentView(getWindow(), glWindow);
- glWindow.addMouseListener(new MouseAdapter() {
- @Override
- public void mousePressed(MouseEvent e) {
- if(e.getPressure()>2f) { // show Keyboard
- ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true);
- }
- }
- });
-
- GearsES2 demo = new GearsES2(-1);
+
+ final GearsES2 demo = new GearsES2(-1);
// demo.enableAndroidTrace(true);
glWindow.addGLEventListener(demo);
- glWindow.getScreen().addScreenModeListener(new ScreenModeListener() {
- public void screenModeChangeNotify(ScreenMode sm) { }
- public void screenModeChanged(ScreenMode sm, boolean success) {
- System.err.println("ScreenMode Changed: "+sm);
- }
+ glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() {
+ @Override
+ public void monitorModeChangeNotify(final MonitorEvent me) { }
+ @Override
+ public void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ System.err.println("MonitorMode Changed (success "+success+"): "+me);
+ }
});
- Animator animator = new Animator(glWindow);
+ if( null != System.getProperty(forceKillProcessTest) ) {
+ Log.d(TAG, "forceKillProcessTest");
+ glWindow.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(final MouseEvent e) {
+ if( e.getPointerCount() == 3 ) {
+ Log.d(TAG, "MemoryHog");
+ new Thread(new Runnable() {
+ public void run() {
+ final ArrayList<Buffer> buffers = new ArrayList<Buffer>();
+ while(true) {
+ final int halfMB = 512 * 1024;
+ final float osizeMB = buffers.size() * 0.5f;
+ final float nsizeMB = osizeMB + 0.5f;
+ System.err.println("MemoryHog: ****** +4k: "+osizeMB+" MB +"+nsizeMB+" MB - Try");
+ buffers.add(ByteBuffer.allocateDirect(halfMB)); // 0.5 MB each
+ System.err.println("MemoryHog: ****** +4k: "+osizeMB+" MB +"+nsizeMB+" MB - Done");
+ try {
+ Thread.sleep(500);
+ } catch (final Exception e) { e.printStackTrace(); };
+ }
+ } }, "MemoryHog").start();
+ } else if( e.getPointerCount() == 4 ) {
+ Log.d(TAG, "ForceKill");
+ android.os.Process.killProcess( android.os.Process.myPid() );
+ }
+ }
+ });
+ }
+ final Animator animator = new Animator(glWindow);
// animator.setRunAsFastAsPossible(true);
- setAnimator(animator);
// glWindow.setSkipContextReleaseThread(animator.getThread());
-
+
+ if( null != System.getProperty(forceECT) ) {
+ Log.d(TAG, "forceECT");
+ animator.setExclusiveContext(true);
+ }
+
glWindow.setVisible(true);
-
+
animator.setUpdateFPSFrames(60, System.err);
animator.resetFPSCounter();
glWindow.resetFPSCounter();
Log.d(TAG, "onCreate - X");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java
index 415efc7f2..06316c4b0 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -35,39 +35,49 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2Activity";
- // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" };
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
+ final OrderedProperties props = getProperties();
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
- // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
// properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
// props.setProperty("nativewindow.debug", "all");
props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// props.setProperty("jogl.debug", "all");
// properties.setProperty("jogl.debug.GLProfile", "true");
- props.setProperty("jogl.debug.GLDrawable", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
props.setProperty("jogl.debug.GLContext", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// props.setProperty("jogl.debug.GLSLState", "true");
// props.setProperty("jogl.debug.DebugGL", "true");
// props.setProperty("jogl.debug.TraceGL", "true");
// props.setProperty("newt.debug", "all");
- // props.setProperty("newt.debug.Window", "true");
- // props.setProperty("newt.debug.Window.MouseEvent", "true");
+ props.setProperty("newt.debug.Screen", "true");
+ props.setProperty("newt.debug.Window", "true");
+ props.setProperty("newt.debug.Window.MouseEvent", "true");
props.setProperty("newt.debug.Window.KeyEvent", "true");
+ // props.setProperty("newt.debug.Android.MouseEvent", "true");
+
+ // props.setProperty("demo.force.killProcessTest", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
+
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ECTActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ECTActivityLauncher.java
new file mode 100644
index 000000000..2e005cb7f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ECTActivityLauncher.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.android;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
+
+public class NEWTGearsES2ECTActivityLauncher extends LauncherUtil.BaseActivityLauncher {
+
+ static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2Activity";
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
+ @Override
+ public void init() {
+ final OrderedProperties props = getProperties();
+ // props.setProperty("jogamp.debug.JNILibLoader", "true");
+ // props.setProperty("jogamp.debug.NativeLibrary", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
+ // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
+ // props.setProperty("nativewindow.debug", "all");
+ props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("jogl.debug", "all");
+ // properties.setProperty("jogl.debug.GLProfile", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
+ props.setProperty("jogl.debug.GLContext", "true");
+ props.setProperty("jogl.debug.GLSLCode", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.GLSLState", "true");
+ // props.setProperty("jogl.debug.DebugGL", "true");
+ // props.setProperty("jogl.debug.TraceGL", "true");
+ // props.setProperty("newt.debug", "all");
+ props.setProperty("newt.debug.Window", "true");
+ props.setProperty("newt.debug.Window.MouseEvent", "true");
+ props.setProperty("newt.debug.Window.KeyEvent", "true");
+
+ props.setProperty("demo.force.ect", "true");
+ }
+
+ @Override
+ public String getActivityName() {
+ return demo;
+ }
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2RGB565ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2RGB565ActivityLauncher.java
new file mode 100644
index 000000000..94e32f1d0
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2RGB565ActivityLauncher.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.android;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
+
+public class NEWTGearsES2RGB565ActivityLauncher extends LauncherUtil.BaseActivityLauncher {
+
+ static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2Activity";
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
+ @Override
+ public void init() {
+ final OrderedProperties props = getProperties();
+ // props.setProperty("jogamp.debug.JNILibLoader", "true");
+ // props.setProperty("jogamp.debug.NativeLibrary", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
+ // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
+ // props.setProperty("nativewindow.debug", "all");
+ props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
+ // props.setProperty("jogl.debug", "all");
+ // properties.setProperty("jogl.debug.GLProfile", "true");
+ // props.setProperty("jogl.debug.GLDrawable", "true");
+ props.setProperty("jogl.debug.GLContext", "true");
+ props.setProperty("jogl.debug.GLSLCode", "true");
+ // props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ // props.setProperty("jogl.debug.GLSLState", "true");
+ // props.setProperty("jogl.debug.DebugGL", "true");
+ // props.setProperty("jogl.debug.TraceGL", "true");
+ // props.setProperty("newt.debug", "all");
+ props.setProperty("newt.debug.Window", "true");
+ props.setProperty("newt.debug.Window.MouseEvent", "true");
+ props.setProperty("newt.debug.Window.KeyEvent", "true");
+
+ props.setProperty("demo.force.rgba5650", "true");
+ }
+
+ @Override
+ public String getActivityName() {
+ return demo;
+ }
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
+ @Override
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java
index 9e50a1be1..1080b2d89 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -34,8 +34,8 @@ import jogamp.newt.driver.android.NewtBaseActivity;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
@@ -46,42 +46,43 @@ import android.util.Log;
public class NEWTGearsES2TransActivity extends NewtBaseActivity {
static String TAG = "NEWTGearsES2TransActivity";
-
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "onCreate - 0");
super.onCreate(savedInstanceState);
-
+
// create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
- GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2));
caps.setBackgroundOpaque(false);
-
+
Log.d(TAG, "req caps: "+caps);
- Screen screen = NewtFactory.createScreen(NewtFactory.createDisplay(null), 0);
+ final Screen screen = NewtFactory.createScreen(NewtFactory.createDisplay(null), 0);
screen.addReference();
- GLWindow glWindow = GLWindow.create(screen, caps);
- glWindow.setSize(2*screen.getWidth()/3, 2*screen.getHeight()/3);
+ final GLWindow glWindow = GLWindow.create(screen, caps);
+ glWindow.setSurfaceSize(2*screen.getWidth()/3, 2*screen.getHeight()/3);
glWindow.setUndecorated(true);
setContentView(getWindow(), glWindow);
-
+
glWindow.addGLEventListener(new GearsES2(-1));
- glWindow.getScreen().addScreenModeListener(new ScreenModeListener() {
- public void screenModeChangeNotify(ScreenMode sm) { }
- public void screenModeChanged(ScreenMode sm, boolean success) {
- System.err.println("ScreenMode Changed: "+sm);
- }
+ glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() {
+ @Override
+ public void monitorModeChangeNotify(final MonitorEvent me) { }
+ @Override
+ public void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ System.err.println("MonitorMode Changed (success "+success+"): "+me);
+ }
});
- Animator animator = new Animator(glWindow);
- setAnimator(animator);
+ final Animator animator = new Animator(glWindow);
// glWindow.setSkipContextReleaseThread(animator.getThread());
-
+
glWindow.setVisible(true);
-
+
animator.setUpdateFPSFrames(60, System.err);
animator.resetFPSCounter();
glWindow.resetFPSCounter();
-
+
screen.removeReference();
Log.d(TAG, "onCreate - X");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivityLauncher.java
index c29c0c5db..332b26e76 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivityLauncher.java
@@ -7,16 +7,17 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class NEWTGearsES2TransActivityLauncher extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2TransActivity";
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
+ final OrderedProperties props = getProperties();
// props.setProperty("jnlp.android.translucent", "true");
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // properties.setProperty("jogamp.debug.IOUtil", "true");
+ // properties.setProperty("jogamp.debug.IOUtil", "true");
// properties.setProperty("nativewindow.debug", "all");
props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// properties.setProperty("jogl.debug", "all");
@@ -24,7 +25,7 @@ public class NEWTGearsES2TransActivityLauncher extends LauncherUtil.BaseActivity
props.setProperty("jogl.debug.GLDrawable", "true");
props.setProperty("jogl.debug.GLContext", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// properties.setProperty("jogl.debug.GLSLState", "true");
// properties.setProperty("jogl.debug.DebugGL", "true");
// properties.setProperty("jogl.debug.TraceGL", "true");
@@ -34,17 +35,24 @@ public class NEWTGearsES2TransActivityLauncher extends LauncherUtil.BaseActivity
// properties.setProperty("newt.debug.Window.KeyEvent", "true");
props.setProperty("jogamp.debug.IOUtil", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
+
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
+
@Override
public String getAction() {
return LauncherUtil.LAUNCH_ACTIVITY_TRANSPARENT;
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java
index b8bf285c6..cd7eb4c66 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile;
import jogamp.newt.driver.android.NewtBaseActivity;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.graph.demos.GPUUISceneGLListener0A;
@@ -44,37 +44,38 @@ import android.util.Log;
public class NEWTGraphUI1pActivity extends NewtBaseActivity {
static String TAG = "NEWTGraphUIActivity";
-
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "onCreate - 0");
super.onCreate(savedInstanceState);
-
+
// create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
- GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2));
caps.setAlphaBits(4);
caps.setNumSamples(4);
caps.setSampleBuffers(true);
Log.d(TAG, "req caps: "+caps);
- GLWindow glWindow = GLWindow.create(caps);
+ final GLWindow glWindow = GLWindow.create(caps);
glWindow.setFullscreen(true);
setContentView(getWindow(), glWindow);
-
+
glWindow.addGLEventListener(new GPUUISceneGLListener0A(0));
- glWindow.getScreen().addScreenModeListener(new ScreenModeListener() {
- public void screenModeChangeNotify(ScreenMode sm) { }
- public void screenModeChanged(ScreenMode sm, boolean success) {
- System.err.println("ScreenMode Changed: "+sm);
- }
+ glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() {
+ @Override
+ public void monitorModeChangeNotify(final MonitorEvent me) { }
+ @Override
+ public void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ System.err.println("MonitorMode Changed (success "+success+"): "+me);
+ }
});
glWindow.setVisible(true);
- Animator animator = new Animator(glWindow);
- setAnimator(animator);
-
+ final Animator animator = new Animator(glWindow);
+
animator.setUpdateFPSFrames(60, System.err);
animator.resetFPSCounter();
glWindow.resetFPSCounter();
-
+
Log.d(TAG, "onCreate - X");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java
index 576305835..5dd8686b4 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java
@@ -7,15 +7,16 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class NEWTGraphUI1pActivityLauncher extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.NEWTGraphUI1pActivity";
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
+ final OrderedProperties props = getProperties();
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // props.setProperty("jogamp.debug.IOUtil", "true");
+ // props.setProperty("jogamp.debug.IOUtil", "true");
// props.setProperty("nativewindow.debug", "all");
props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// props.setProperty("jogl.debug", "all");
@@ -23,7 +24,7 @@ public class NEWTGraphUI1pActivityLauncher extends LauncherUtil.BaseActivityLaun
props.setProperty("jogl.debug.GLDrawable", "true");
props.setProperty("jogl.debug.GLContext", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// props.setProperty("jogl.debug.GLSLState", "true");
// props.setProperty("jogl.debug.DebugGL", "true");
// props.setProperty("jogl.debug.TraceGL", "true");
@@ -32,13 +33,19 @@ public class NEWTGraphUI1pActivityLauncher extends LauncherUtil.BaseActivityLaun
// props.setProperty("newt.debug.Window.MouseEvent", "true");
// props.setProperty("newt.debug.Window.KeyEvent", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
+
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java
index 103af1aab..55bdbcff6 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -33,8 +33,8 @@ import javax.media.opengl.GLProfile;
import jogamp.newt.driver.android.NewtBaseActivity;
import com.jogamp.graph.curve.Region;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.graph.demos.GPUUISceneGLListener0A;
@@ -45,37 +45,36 @@ import android.util.Log;
public class NEWTGraphUI2pActivity extends NewtBaseActivity {
static String TAG = "NEWTGraphUIActivity";
-
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "onCreate - 0");
super.onCreate(savedInstanceState);
-
+
// create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
- GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2));
caps.setAlphaBits(4);
- caps.setNumSamples(4);
- caps.setSampleBuffers(true);
Log.d(TAG, "req caps: "+caps);
- GLWindow glWindow = GLWindow.create(caps);
+ final GLWindow glWindow = GLWindow.create(caps);
glWindow.setFullscreen(true);
setContentView(getWindow(), glWindow);
-
+
glWindow.addGLEventListener(new GPUUISceneGLListener0A(Region.VBAA_RENDERING_BIT));
- glWindow.getScreen().addScreenModeListener(new ScreenModeListener() {
- public void screenModeChangeNotify(ScreenMode sm) { }
- public void screenModeChanged(ScreenMode sm, boolean success) {
- System.err.println("ScreenMode Changed: "+sm);
- }
+ glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() {
+ @Override
+ public void monitorModeChangeNotify(final MonitorEvent me) { }
+ @Override
+ public void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ System.err.println("MonitorMode Changed (success "+success+"): "+me);
+ }
});
glWindow.setVisible(true);
- Animator animator = new Animator(glWindow);
- setAnimator(animator);
-
+ final Animator animator = new Animator(glWindow);
+
animator.setUpdateFPSFrames(60, System.err);
animator.resetFPSCounter();
glWindow.resetFPSCounter();
-
+
Log.d(TAG, "onCreate - X");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivityLauncher.java
index 8f6b51484..09e500b36 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivityLauncher.java
@@ -7,15 +7,16 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class NEWTGraphUI2pActivityLauncher extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.NEWTGraphUI2pActivity";
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
+ final OrderedProperties props = getProperties();
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // properties.setProperty("jogamp.debug.IOUtil", "true");
+ // properties.setProperty("jogamp.debug.IOUtil", "true");
// properties.setProperty("nativewindow.debug", "all");
props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// properties.setProperty("jogl.debug", "all");
@@ -23,7 +24,7 @@ public class NEWTGraphUI2pActivityLauncher extends LauncherUtil.BaseActivityLaun
props.setProperty("jogl.debug.GLDrawable", "true");
props.setProperty("jogl.debug.GLContext", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// properties.setProperty("jogl.debug.GLSLState", "true");
// properties.setProperty("jogl.debug.DebugGL", "true");
// properties.setProperty("jogl.debug.TraceGL", "true");
@@ -32,13 +33,19 @@ public class NEWTGraphUI2pActivityLauncher extends LauncherUtil.BaseActivityLaun
// properties.setProperty("newt.debug.Window.MouseEvent", "true");
// properties.setProperty("newt.debug.Window.KeyEvent", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
+
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java
index a394482fc..f256f98a9 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile;
import jogamp.newt.driver.android.NewtBaseActivity;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1;
@@ -44,33 +44,34 @@ import android.util.Log;
public class NEWTRedSquareES1Activity extends NewtBaseActivity {
static String TAG = "NEWTGearsES1Activity";
-
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "onCreate - 0");
super.onCreate(savedInstanceState);
-
+
// create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
- GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES1));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES1));
Log.d(TAG, "req caps: "+caps);
- GLWindow glWindow = GLWindow.create(caps);
+ final GLWindow glWindow = GLWindow.create(caps);
setContentView(getWindow(), glWindow);
-
+
glWindow.addGLEventListener(new RedSquareES1(-1));
- glWindow.getScreen().addScreenModeListener(new ScreenModeListener() {
- public void screenModeChangeNotify(ScreenMode sm) { }
- public void screenModeChanged(ScreenMode sm, boolean success) {
- System.err.println("ScreenMode Changed: "+sm);
- }
+ glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() {
+ @Override
+ public void monitorModeChangeNotify(final MonitorEvent me) { }
+ @Override
+ public void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ System.err.println("MonitorMode Changed (success "+success+"): "+me);
+ }
});
glWindow.setVisible(true);
- Animator animator = new Animator(glWindow);
- setAnimator(animator);
-
+ final Animator animator = new Animator(glWindow);
+
animator.setUpdateFPSFrames(60, System.err);
animator.resetFPSCounter();
glWindow.resetFPSCounter();
-
+
Log.d(TAG, "onCreate - X");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1ActivityLauncher.java
index 478fe65b7..4b5a05f37 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1ActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1ActivityLauncher.java
@@ -7,15 +7,16 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
public class NEWTRedSquareES1ActivityLauncher extends LauncherUtil.BaseActivityLauncher {
static String demo = "com.jogamp.opengl.test.android.NEWTRedSquareES1Activity";
- static String[] pkgs = new String[] { "com.jogamp.opengl.test" };
-
+ static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" };
+ static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" };
+
@Override
public void init() {
- final OrderedProperties props = getProperties();
+ final OrderedProperties props = getProperties();
// props.setProperty("jogamp.debug.JNILibLoader", "true");
// props.setProperty("jogamp.debug.NativeLibrary", "true");
// properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true");
- // properties.setProperty("jogamp.debug.IOUtil", "true");
+ // properties.setProperty("jogamp.debug.IOUtil", "true");
// properties.setProperty("nativewindow.debug", "all");
props.setProperty("nativewindow.debug.GraphicsConfiguration", "true");
// properties.setProperty("jogl.debug", "all");
@@ -23,7 +24,7 @@ public class NEWTRedSquareES1ActivityLauncher extends LauncherUtil.BaseActivityL
props.setProperty("jogl.debug.GLDrawable", "true");
props.setProperty("jogl.debug.GLContext", "true");
props.setProperty("jogl.debug.GLSLCode", "true");
- props.setProperty("jogl.debug.CapabilitiesChooser", "true");
+ props.setProperty("jogl.debug.CapabilitiesChooser", "true");
// properties.setProperty("jogl.debug.GLSLState", "true");
// properties.setProperty("jogl.debug.DebugGL", "true");
// properties.setProperty("jogl.debug.TraceGL", "true");
@@ -32,13 +33,19 @@ public class NEWTRedSquareES1ActivityLauncher extends LauncherUtil.BaseActivityL
// properties.setProperty("newt.debug.Window.MouseEvent", "true");
// properties.setProperty("newt.debug.Window.KeyEvent", "true");
}
-
+
@Override
public String getActivityName() {
return demo;
}
+
+ @Override
+ public List<String> getSysPackages() {
+ return Arrays.asList(sys_pkgs);
+ }
+
@Override
- public List<String> getPackages() {
- return Arrays.asList(pkgs);
+ public List<String> getUsrPackages() {
+ return Arrays.asList(usr_pkgs);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java
index e850b9310..99c65d6ad 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile;
import jogamp.newt.driver.android.NewtBaseActivity;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
@@ -44,55 +44,56 @@ import android.util.Log;
public class NEWTRedSquareES2Activity extends NewtBaseActivity {
static String TAG = "NEWTGearsES2Activity";
-
+
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "onCreate - 0");
super.onCreate(savedInstanceState);
-
+
// create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
- GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2));
Log.d(TAG, "req caps: "+caps);
- GLWindow glWindow = GLWindow.create(caps);
+ final GLWindow glWindow = GLWindow.create(caps);
// glWindow.setSize(200, 200);
// glWindow.setUndecorated(true);
- glWindow.setFullscreen(true);
+ glWindow.setFullscreen(true);
setContentView(getWindow(), glWindow);
-
+
final RedSquareES2 demo = new RedSquareES2(-1);
// demo.enableAndroidTrace(true);
glWindow.addGLEventListener(demo);
- glWindow.getScreen().addScreenModeListener(new ScreenModeListener() {
- public void screenModeChangeNotify(ScreenMode sm) { }
- public void screenModeChanged(ScreenMode sm, boolean success) {
- System.err.println("ScreenMode Changed: "+sm);
- }
+ glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() {
+ @Override
+ public void monitorModeChangeNotify(final MonitorEvent me) { }
+ @Override
+ public void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ System.err.println("MonitorMode Changed (success "+success+"): "+me);
+ }
});
- Animator animator = new Animator(glWindow);
+ final Animator animator = new Animator(glWindow);
// animator.setRunAsFastAsPossible(true);
- setAnimator(animator);
// glWindow.setSkipContextReleaseThread(animator.getThread());
glWindow.setVisible(true);
-
+
animator.setUpdateFPSFrames(60, System.err);
animator.resetFPSCounter();
glWindow.resetFPSCounter();
-
+
Log.d(TAG, "onCreate - X");
}
-
+
@Override
public void onResume() {
// android.os.Debug.startMethodTracing("GearsES2.trace");
- // android.os.Debug.startAllocCounting();
+ // android.os.Debug.startAllocCounting();
super.onResume();
}
-
+
@Override
public void onPause() {
// android.os.Debug.stopAllocCounting();
// android.os.Debug.stopMethodTracing();
- super.onPause();
+ super.onPause();
}
-
+
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java
index 96299e873..40cb4bfb5 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java
@@ -8,14 +8,14 @@ import android.util.Log;
public class NEWTRedSquareES2ActivityLauncher extends Activity {
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- final Uri uri = Uri.parse("launch://jogamp.org/com.jogamp.opengl.test.android.NEWTRedSquareES2Activity?pkg=com.jogamp.opengl.test");
- final Intent intent = new Intent("org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL", uri);
+
+ final Uri uri = Uri.parse("launch://jogamp.org/com.jogamp.opengl.test.android.NEWTRedSquareES2Activity?sys=com.jogamp.common&sys=javax.media.opengl&pkg=com.jogamp.opengl.test");
+ final Intent intent = new Intent("org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL", uri);
Log.d(getClass().getSimpleName(), "Launching Activity: "+intent);
startActivity (intent);
-
+
finish(); // done
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java b/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java
index 9bf492e0f..9136b4e61 100644
--- a/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java
@@ -1,9 +1,12 @@
package com.jogamp.opengl.test.bugs;
import javax.swing.*;
+
import java.awt.*;
+
import javax.media.opengl.*;
import javax.media.opengl.awt.*;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
public class Bug427GLJPanelTest1 extends JFrame implements GLEventListener {
@@ -13,28 +16,42 @@ public class Bug427GLJPanelTest1 extends JFrame implements GLEventListener {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
- setSize(600, 600);
- setLocation(40, 40);
- setVisible(true);
-
- GLProfile glp = GLProfile.get(GLProfile.GL2);
- GLCapabilities caps = new GLCapabilities(glp);
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ setSize(600, 600);
+ setLocation(40, 40);
+ setVisible(true);
+ } } );
+ } catch(final Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilities caps = new GLCapabilities(glp);
caps.setDoubleBuffered(true);
caps.setHardwareAccelerated(true);
- GLJPanel panel = new GLJPanel(caps);
+ final GLJPanel panel = new GLJPanel(caps);
panel.addGLEventListener(this);
add(panel, BorderLayout.CENTER);
}
- public static void main(String[] args) {
- Bug427GLJPanelTest1 demo = new Bug427GLJPanelTest1();
- demo.setVisible(true);
+ public static void main(final String[] args) {
+ final Bug427GLJPanelTest1 demo = new Bug427GLJPanelTest1();
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ demo.setVisible(true);
+ } } );
+ } catch(final Exception ex) {
+ throw new RuntimeException(ex);
+ }
}
- public void display(GLAutoDrawable drawable) {
- GL2 gl = drawable.getGL().getGL2();
+ public void display(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glBegin(GL.GL_TRIANGLES);
@@ -52,21 +69,21 @@ public class Bug427GLJPanelTest1 extends JFrame implements GLEventListener {
gl.glFlush();
}
- public void init(GLAutoDrawable drawable) {
- GL2 gl = drawable.getGL().getGL2();
+ public void init(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
gl.glClearColor(0, 0, 0, 0);
- gl.glMatrixMode(GL2.GL_PROJECTION);
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(0, 1, 0, 1, -1, 1);
}
- public void reshape(GLAutoDrawable glDrawable, int x, int y, int w, int h) {
+ public void reshape(final GLAutoDrawable glDrawable, final int x, final int y, final int w, final int h) {
}
- public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
+ public void displayChanged(final GLAutoDrawable drawable, final boolean modeChanged, final boolean deviceChanged) {
}
-
- public void dispose(GLAutoDrawable drawable) {
+
+ public void dispose(final GLAutoDrawable drawable) {
}
}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync0-flush-wait-finish.log b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync0-flush-wait-finish.log
new file mode 100644
index 000000000..2261a3caa
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync0-flush-wait-finish.log
@@ -0,0 +1,751 @@
+NSZombieEnabled
+NSTraceEvents YES
+OBJC_PRINT_EXCEPTIONS
+/usr/bin/java
+java version "1.6.0_37"
+Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909)
+Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)
+LD_LIBRARY_PATH :../../gluegen/make/../build-macosx/obj:../build-macosx/lib
+LIBXCB_ALLOW_SLOPPY_LOCK:
+LIBGL_DRIVERS_PATH:
+LIBGL_DEBUG:
+LIBGL_ALWAYS_INDIRECT:
+LIBGL_ALWAYS_SOFTWARE:
+SWT_CLASSPATH: ../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar
+/usr/bin/java -d64 -time 100000 -vsync 0
+CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar
+CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar
+
+Test Start: com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0
+
+/usr/bin/java -d64 -Djava.awt.headless=false -Djogl.debug.calayer.SwapM1 com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0
+swapInterval 0
+exclusiveContext false
+SWAP_M1 true
+SWAP_M2 false
+NewtCanvasAWT.attachNewtChild.2: size 500x268
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init ...
+LandscapeES2 init on Thread[main-Display-.macosx_nil-1-EDT-1,5,main]
+Chosen GLCapabilities: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/0, dbl, mono , hw, GLProfile[GL2/GL2.hw], offscr[fbo]]
+INIT GL IS: jogamp.opengl.gl4.GL4bcImpl
+GL_VENDOR: NVIDIA Corporation
+GL_RENDERER: NVIDIA GeForce 320M OpenGL Engine
+GL_VERSION: 2.1 NVIDIA-7.32.12
+GL GLSL: true, has-compiler-func: true, version 1.20, 1.20.0
+GL FBO: basic true, full true
+GL Profile: GLProfile[GL2/GL2.hw]
+GL Renderer Quirks:[NoOffscreenBitmap]
+GL:jogamp.opengl.gl4.GL4bcImpl@6a6779e6, 2.1 (hardware) - 2.1 NVIDIA-7.32.12
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init FIN
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7ff0e40a7db0
+Thread[AWT-EventQueue-0,6,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7ff0e40a7db0
+XXX[1] TO 17 ms, lFrame0 119 ms, lFrameX 858 / 858 ~858.987 ms, flushGL 1 / 1 ~1.135 ms, waitGL 1 / 1 ~1.056 ms, finishGL 737 / 737 ~737.152 ms
+XXX[2] TO 17 ms, lFrame0 104 ms, lFrameX 194 / 1053 ~526.583 ms, flushGL 0 / 1 ~0.57 ms, waitGL 0 / 1 ~0.531 ms, finishGL 89 / 826 ~413.413 ms
+XXX[3] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 1136 ~378.802 ms, flushGL 0 / 1 ~0.383 ms, waitGL 0 / 1 ~0.355 ms, finishGL 81 / 908 ~302.677 ms
+XXX[4] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 1219 ~304.958 ms, flushGL 0 / 1 ~0.289 ms, waitGL 0 / 1 ~0.268 ms, finishGL 81 / 989 ~247.438 ms
+XXX[5] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 1302 ~260.583 ms, flushGL 0 / 1 ~0.232 ms, waitGL 0 / 1 ~0.215 ms, finishGL 82 / 1071 ~214.354 ms
+XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1385 ~230.882 ms, flushGL 0 / 1 ~0.194 ms, waitGL 0 / 1 ~0.18 ms, finishGL 81 / 1153 ~192.227 ms
+XXX[7] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 1467 ~209.645 ms, flushGL 0 / 1 ~0.169 ms, waitGL 0 / 1 ~0.155 ms, finishGL 80 / 1233 ~176.248 ms
+XXX[8] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 1550 ~193.788 ms, flushGL 0 / 1 ~0.149 ms, waitGL 0 / 1 ~0.136 ms, finishGL 81 / 1314 ~164.348 ms
+XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1632 ~181.44 ms, flushGL 0 / 1 ~0.133 ms, waitGL 0 / 1 ~0.121 ms, finishGL 81 / 1396 ~155.19 ms
+XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1715 ~171.594 ms, flushGL 0 / 1 ~0.12 ms, waitGL 0 / 1 ~0.109 ms, finishGL 82 / 1478 ~147.892 ms
+XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 1814 ~164.944 ms, flushGL 0 / 1 ~0.109 ms, waitGL 0 / 1 ~0.099 ms, finishGL 97 / 1576 ~143.33 ms
+XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1897 ~158.103 ms, flushGL 0 / 1 ~0.1 ms, waitGL 0 / 1 ~0.092 ms, finishGL 82 / 1658 ~138.232 ms
+XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 1974 ~151.875 ms, flushGL 0 / 1 ~0.093 ms, waitGL 0 / 1 ~0.085 ms, finishGL 76 / 1735 ~133.461 ms
+XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 2078 ~148.498 ms, flushGL 0 / 1 ~0.086 ms, waitGL 0 / 1 ~0.079 ms, finishGL 104 / 1839 ~131.357 ms
+XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2161 ~144.112 ms, flushGL 0 / 1 ~0.081 ms, waitGL 0 / 1 ~0.074 ms, finishGL 82 / 1921 ~128.079 ms
+XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2237 ~139.828 ms, flushGL 0 / 1 ~0.076 ms, waitGL 0 / 1 ~0.069 ms, finishGL 74 / 1995 ~124.741 ms
+XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 2327 ~136.929 ms, flushGL 0 / 1 ~0.071 ms, waitGL 0 / 1 ~0.065 ms, finishGL 90 / 2086 ~122.706 ms
+XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 2427 ~134.845 ms, flushGL 0 / 1 ~0.068 ms, waitGL 0 / 1 ~0.062 ms, finishGL 98 / 2184 ~121.372 ms
+XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2510 ~132.139 ms, flushGL 0 / 1 ~0.064 ms, waitGL 0 / 1 ~0.059 ms, finishGL 82 / 2267 ~119.34 ms
+XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2586 ~129.322 ms, flushGL 0 / 1 ~0.061 ms, waitGL 0 / 1 ~0.056 ms, finishGL 75 / 2342 ~117.125 ms
+XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2693 ~128.273 ms, flushGL 0 / 1 ~0.058 ms, waitGL 0 / 1 ~0.053 ms, finishGL 106 / 2449 ~116.638 ms
+XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2776 ~126.226 ms, flushGL 0 / 1 ~0.056 ms, waitGL 0 / 1 ~0.051 ms, finishGL 82 / 2532 ~115.096 ms
+XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 2851 ~123.993 ms, flushGL 0 / 1 ~0.054 ms, waitGL 0 / 1 ~0.049 ms, finishGL 74 / 2606 ~113.316 ms
+XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 2957 ~123.214 ms, flushGL 0 / 1 ~0.051 ms, waitGL 0 / 1 ~0.047 ms, finishGL 104 / 2711 ~112.961 ms
+XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 3037 ~121.514 ms, flushGL 0 / 1 ~0.049 ms, waitGL 0 / 1 ~0.045 ms, finishGL 80 / 2791 ~111.652 ms
+XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 3108 ~119.541 ms, flushGL 0 / 1 ~0.048 ms, waitGL 0 / 1 ~0.044 ms, finishGL 69 / 2860 ~110.026 ms
+XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 3202 ~118.618 ms, flushGL 0 / 1 ~0.046 ms, waitGL 0 / 1 ~0.042 ms, finishGL 93 / 2954 ~109.423 ms
+XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3285 ~117.322 ms, flushGL 0 / 1 ~0.044 ms, waitGL 0 / 1 ~0.041 ms, finishGL 81 / 3036 ~108.439 ms
+XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3352 ~115.598 ms, flushGL 0 / 1 ~0.043 ms, waitGL 0 / 1 ~0.039 ms, finishGL 66 / 3102 ~106.999 ms
+XXX[30] TO 17 ms, lFrame0 1 ms, lFrameX 97 / 3449 ~114.992 ms, flushGL 0 / 1 ~0.042 ms, waitGL 0 / 1 ~0.038 ms, finishGL 96 / 3199 ~106.644 ms
+XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 3531 ~113.92 ms, flushGL 0 / 1 ~0.04 ms, waitGL 0 / 1 ~0.037 ms, finishGL 81 / 3280 ~105.828 ms
+XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3596 ~112.392 ms, flushGL 0 / 1 ~0.039 ms, waitGL 0 / 1 ~0.036 ms, finishGL 64 / 3345 ~104.535 ms
+XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3680 ~111.53 ms, flushGL 0 / 1 ~0.038 ms, waitGL 0 / 1 ~0.035 ms, finishGL 83 / 3428 ~103.889 ms
+XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3746 ~110.179 ms, flushGL 0 / 1 ~0.037 ms, waitGL 0 / 1 ~0.034 ms, finishGL 65 / 3493 ~102.75 ms
+XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3810 ~108.86 ms, flushGL 0 / 1 ~0.036 ms, waitGL 0 / 1 ~0.034 ms, finishGL 63 / 3556 ~101.622 ms
+XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 3894 ~108.192 ms, flushGL 0 / 1 ~0.035 ms, waitGL 0 / 1 ~0.033 ms, finishGL 84 / 3641 ~101.141 ms
+XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3962 ~107.095 ms, flushGL 0 / 1 ~0.034 ms, waitGL 0 / 1 ~0.032 ms, finishGL 67 / 3708 ~100.222 ms
+XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 4025 ~105.924 ms, flushGL 0 / 1 ~0.033 ms, waitGL 0 / 1 ~0.031 ms, finishGL 61 / 3770 ~99.213 ms
+XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 4111 ~105.414 ms, flushGL 0 / 1 ~0.033 ms, waitGL 0 / 1 ~0.03 ms, finishGL 85 / 3855 ~98.863 ms
+XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4176 ~104.413 ms, flushGL 0 / 1 ~0.032 ms, waitGL 0 / 1 ~0.03 ms, finishGL 64 / 3920 ~98.012 ms
+XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 4237 ~103.353 ms, flushGL 0 / 1 ~0.031 ms, waitGL 0 / 1 ~0.029 ms, finishGL 60 / 3980 ~97.094 ms
+XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 4325 ~102.99 ms, flushGL 0 / 1 ~0.03 ms, waitGL 0 / 1 ~0.028 ms, finishGL 87 / 4068 ~96.868 ms
+XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4391 ~102.13 ms, flushGL 0 / 1 ~0.03 ms, waitGL 0 / 1 ~0.028 ms, finishGL 65 / 4134 ~96.14 ms
+XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 4451 ~101.179 ms, flushGL 0 / 1 ~0.029 ms, waitGL 0 / 1 ~0.027 ms, finishGL 59 / 4193 ~95.31 ms
+XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 4541 ~100.92 ms, flushGL 0 / 1 ~0.029 ms, waitGL 0 / 1 ~0.027 ms, finishGL 88 / 4282 ~95.166 ms
+XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4607 ~100.161 ms, flushGL 0 / 1 ~0.028 ms, waitGL 0 / 1 ~0.026 ms, finishGL 65 / 4348 ~94.521 ms
+XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 4667 ~99.304 ms, flushGL 0 / 1 ~0.027 ms, waitGL 0 / 1 ~0.026 ms, finishGL 59 / 4407 ~93.768 ms
+XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 4756 ~99.098 ms, flushGL 0 / 1 ~0.027 ms, waitGL 0 / 1 ~0.025 ms, finishGL 88 / 4496 ~93.666 ms
+XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4823 ~98.431 ms, flushGL 0 / 1 ~0.026 ms, waitGL 0 / 1 ~0.025 ms, finishGL 65 / 4561 ~93.099 ms
+XXX[50] TO 17 ms, lFrame0 1 ms, lFrameX 59 / 4883 ~97.662 ms, flushGL 0 / 1 ~0.026 ms, waitGL 0 / 1 ~0.024 ms, finishGL 58 / 4620 ~92.415 ms
+XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 4972 ~97.49 ms, flushGL 0 / 1 ~0.025 ms, waitGL 0 / 1 ~0.024 ms, finishGL 88 / 4709 ~92.336 ms
+XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5038 ~96.903 ms, flushGL 0 / 1 ~0.025 ms, waitGL 0 / 1 ~0.023 ms, finishGL 66 / 4775 ~91.84 ms
+XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 58 / 5097 ~96.188 ms, flushGL 0 / 1 ~0.025 ms, waitGL 0 / 1 ~0.023 ms, finishGL 58 / 4834 ~91.211 ms
+XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 5188 ~96.089 ms, flushGL 0 / 1 ~0.024 ms, waitGL 0 / 1 ~0.022 ms, finishGL 90 / 4924 ~91.197 ms
+XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 5254 ~95.534 ms, flushGL 0 / 1 ~0.024 ms, waitGL 0 / 1 ~0.022 ms, finishGL 65 / 4989 ~90.723 ms
+XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 5313 ~94.892 ms, flushGL 0 / 1 ~0.023 ms, waitGL 0 / 1 ~0.022 ms, finishGL 58 / 5048 ~90.152 ms
+XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 5404 ~94.815 ms, flushGL 0 / 1 ~0.023 ms, waitGL 0 / 1 ~0.021 ms, finishGL 89 / 5138 ~90.148 ms
+XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5471 ~94.336 ms, flushGL 0 / 1 ~0.023 ms, waitGL 0 / 1 ~0.021 ms, finishGL 66 / 5204 ~89.74 ms
+XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 5531 ~93.755 ms, flushGL 0 / 1 ~0.022 ms, waitGL 0 / 1 ~0.021 ms, finishGL 59 / 5264 ~89.227 ms
+XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 5620 ~93.682 ms, flushGL 0 / 1 ~0.022 ms, waitGL 0 / 1 ~0.02 ms, finishGL 88 / 5353 ~89.222 ms
+XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5687 ~93.244 ms, flushGL 0 / 1 ~0.022 ms, waitGL 0 / 1 ~0.02 ms, finishGL 66 / 5419 ~88.848 ms
+XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 5747 ~92.707 ms, flushGL 0 / 1 ~0.021 ms, waitGL 0 / 1 ~0.02 ms, finishGL 59 / 5479 ~88.371 ms
+XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 5837 ~92.662 ms, flushGL 0 / 1 ~0.021 ms, waitGL 0 / 1 ~0.02 ms, finishGL 88 / 5568 ~88.381 ms
+XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5905 ~92.267 ms, flushGL 0 / 1 ~0.021 ms, waitGL 0 / 1 ~0.019 ms, finishGL 66 / 5634 ~88.042 ms
+XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 5967 ~91.8 ms, flushGL 0 / 1 ~0.021 ms, waitGL 0 / 1 ~0.019 ms, finishGL 61 / 5695 ~87.629 ms
+XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 6055 ~91.744 ms, flushGL 0 / 1 ~0.02 ms, waitGL 0 / 1 ~0.019 ms, finishGL 87 / 5783 ~87.626 ms
+XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6122 ~91.376 ms, flushGL 0 / 1 ~0.02 ms, waitGL 0 / 1 ~0.019 ms, finishGL 66 / 5849 ~87.312 ms
+XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 6185 ~90.96 ms, flushGL 0 / 1 ~0.02 ms, waitGL 0 / 1 ~0.018 ms, finishGL 62 / 5912 ~86.945 ms
+XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 6272 ~90.899 ms, flushGL 0 / 1 ~0.019 ms, waitGL 0 / 1 ~0.018 ms, finishGL 86 / 5998 ~86.932 ms
+XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6338 ~90.547 ms, flushGL 0 / 1 ~0.019 ms, waitGL 0 / 1 ~0.018 ms, finishGL 65 / 6064 ~86.631 ms
+XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 6400 ~90.149 ms, flushGL 0 / 1 ~0.019 ms, waitGL 0 / 1 ~0.018 ms, finishGL 61 / 6125 ~86.276 ms
+XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 6486 ~90.094 ms, flushGL 0 / 1 ~0.019 ms, waitGL 0 / 1 ~0.017 ms, finishGL 85 / 6211 ~86.268 ms
+XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6552 ~89.761 ms, flushGL 0 / 1 ~0.019 ms, waitGL 0 / 1 ~0.017 ms, finishGL 65 / 6276 ~85.98 ms
+XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 6613 ~89.376 ms, flushGL 0 / 1 ~0.018 ms, waitGL 0 / 1 ~0.017 ms, finishGL 60 / 6337 ~85.639 ms
+XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 6702 ~89.368 ms, flushGL 0 / 1 ~0.018 ms, waitGL 0 / 1 ~0.017 ms, finishGL 88 / 6425 ~85.675 ms
+XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6769 ~89.071 ms, flushGL 0 / 1 ~0.018 ms, waitGL 0 / 1 ~0.017 ms, finishGL 66 / 6491 ~85.42 ms
+XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 6830 ~88.709 ms, flushGL 0 / 1 ~0.018 ms, waitGL 0 / 1 ~0.016 ms, finishGL 60 / 6552 ~85.097 ms
+XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 6919 ~88.707 ms, flushGL 0 / 1 ~0.018 ms, waitGL 0 / 1 ~0.016 ms, finishGL 88 / 6640 ~85.135 ms
+XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6986 ~88.437 ms, flushGL 0 / 1 ~0.017 ms, waitGL 0 / 1 ~0.016 ms, finishGL 66 / 6707 ~84.904 ms
+XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 7049 ~88.124 ms, flushGL 0 / 1 ~0.017 ms, waitGL 0 / 1 ~0.016 ms, finishGL 62 / 6769 ~84.624 ms
+XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 7136 ~88.109 ms, flushGL 0 / 1 ~0.017 ms, waitGL 0 / 1 ~0.016 ms, finishGL 86 / 6856 ~84.647 ms
+XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7203 ~87.846 ms, flushGL 0 / 1 ~0.017 ms, waitGL 0 / 1 ~0.016 ms, finishGL 65 / 6922 ~84.42 ms
+XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 7267 ~87.556 ms, flushGL 0 / 1 ~0.017 ms, waitGL 0 / 1 ~0.015 ms, finishGL 63 / 6985 ~84.164 ms
+XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 7353 ~87.538 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 85 / 7071 ~84.181 ms
+XXX[85] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 7419 ~87.287 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 65 / 7136 ~83.956 ms
+XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 7482 ~87.011 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 62 / 7199 ~83.711 ms
+XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 7569 ~87.002 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 85 / 7284 ~83.732 ms
+XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7635 ~86.767 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 65 / 7350 ~83.529 ms
+XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 7698 ~86.495 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 61 / 7412 ~83.287 ms
+XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 7784 ~86.498 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.014 ms, finishGL 86 / 7498 ~83.321 ms
+XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7851 ~86.278 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 65 / 7564 ~83.131 ms
+XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 7914 ~86.024 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 62 / 7627 ~82.903 ms
+XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 8000 ~86.024 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 85 / 7712 ~82.931 ms
+XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8066 ~85.812 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 65 / 7778 ~82.748 ms
+XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 8127 ~85.556 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 60 / 7839 ~82.516 ms
+XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 8215 ~85.577 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 87 / 7926 ~82.563 ms
+XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8281 ~85.376 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 65 / 7991 ~82.388 ms
+XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 8342 ~85.123 ms, flushGL 0 / 1 ~0.014 ms, waitGL 0 / 1 ~0.013 ms, finishGL 59 / 8051 ~82.158 ms
+XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 8431 ~85.161 ms, flushGL 0 / 1 ~0.014 ms, waitGL 0 / 1 ~0.013 ms, finishGL 88 / 8139 ~82.22 ms
+XXX[1] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 66 ~66.288 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 65 / 65 ~65.79 ms
+XXX[2] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 126 ~63.1 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 59 / 125 ~62.55 ms
+XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 216 ~72.024 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 89 / 214 ~71.495 ms
+XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 282 ~70.719 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 66 / 280 ~70.203 ms
+XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 344 ~68.97 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 61 / 342 ~68.43 ms
+XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 434 ~72.357 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 88 / 430 ~71.813 ms
+XXX[7] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 499 ~71.382 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 65 / 495 ~70.842 ms
+XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 560 ~70.03 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 59 / 555 ~69.454 ms
+XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 648 ~72.085 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 88 / 643 ~71.521 ms
+XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 714 ~71.489 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 65 / 709 ~70.934 ms
+XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 774 ~70.434 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 59 / 768 ~69.865 ms
+XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 864 ~72.036 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 88 / 857 ~71.454 ms
+XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 931 ~71.665 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 66 / 924 ~71.094 ms
+XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 992 ~70.887 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 60 / 984 ~70.309 ms
+XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 1081 ~72.122 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 88 / 1073 ~71.554 ms
+XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1149 ~71.826 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 66 / 1140 ~71.265 ms
+XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 1211 ~71.277 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 62 / 1202 ~70.724 ms
+XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 1300 ~72.24 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 88 / 1290 ~71.689 ms
+XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1366 ~71.934 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 65 / 1356 ~71.388 ms
+FrameCount: 120 - FrameRate: 15.0
+XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 1430 ~71.539 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 1419 ~70.979 ms
+XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 1516 ~72.228 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 85 / 1505 ~71.674 ms
+XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1582 ~71.935 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 65 / 1570 ~71.383 ms
+XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 1647 ~71.614 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 1634 ~71.055 ms
+XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 1732 ~72.202 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 85 / 1719 ~71.646 ms
+XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1798 ~71.927 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 1784 ~71.376 ms
+XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 1862 ~71.624 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 1847 ~71.063 ms
+XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 1948 ~72.167 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 85 / 1933 ~71.601 ms
+XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2015 ~71.976 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 66 / 1999 ~71.412 ms
+XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 2079 ~71.695 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 2062 ~71.129 ms
+XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 2148 ~71.624 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 69 / 2131 ~71.061 ms
+XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2213 ~71.415 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 2196 ~70.855 ms
+XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2281 ~71.295 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 67 / 2263 ~70.736 ms
+XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2346 ~71.114 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 2328 ~70.558 ms
+XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2414 ~71.014 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 67 / 2395 ~70.461 ms
+XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 2479 ~70.84 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 2460 ~70.289 ms
+XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2547 ~70.758 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 67 / 2527 ~70.209 ms
+XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 2612 ~70.595 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 2591 ~70.048 ms
+XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2678 ~70.489 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 66 / 2657 ~69.944 ms
+XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2743 ~70.352 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 2722 ~69.808 ms
+XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 2807 ~70.197 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 2786 ~69.656 ms
+XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 2871 ~70.035 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 2849 ~69.496 ms
+XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 2934 ~69.863 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 62 / 2911 ~69.326 ms
+XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 2995 ~69.661 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 60 / 2972 ~69.126 ms
+XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 46 / 3042 ~69.141 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 46 / 3018 ~68.607 ms
+XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3091 ~68.708 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 49 / 3067 ~68.175 ms
+XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3140 ~68.274 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 48 / 3116 ~67.743 ms
+XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3189 ~67.865 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 48 / 3164 ~67.334 ms
+XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3238 ~67.473 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 48 / 3213 ~66.944 ms
+XXX[49] TO 17 ms, lFrame0 1 ms, lFrameX 41 / 3279 ~66.937 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 40 / 3253 ~66.396 ms
+XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 3354 ~67.082 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 73 / 3327 ~66.541 ms
+XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3403 ~66.729 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 48 / 3375 ~66.189 ms
+XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 39 / 3442 ~66.203 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 38 / 3414 ~65.658 ms
+XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 3501 ~66.074 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 58 / 3473 ~65.529 ms
+XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3550 ~65.758 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 48 / 3521 ~65.213 ms
+XXX[55] TO 17 ms, lFrame0 1 ms, lFrameX 37 / 3588 ~65.249 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 36 / 3558 ~64.693 ms
+XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 3632 ~64.869 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 43 / 3601 ~64.315 ms
+XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3697 ~64.87 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 3666 ~64.319 ms
+XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3745 ~64.586 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 47 / 3714 ~64.036 ms
+XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 3779 ~64.054 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 32 / 3746 ~63.502 ms
+XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3843 ~64.065 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 3810 ~63.515 ms
+XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3892 ~63.804 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 47 / 3858 ~63.254 ms
+XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 29 / 3921 ~63.257 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 29 / 3887 ~62.703 ms
+XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 3973 ~63.067 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 50 / 3938 ~62.512 ms
+XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4005 ~62.586 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 31 / 3970 ~62.032 ms
+XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 27 / 4033 ~62.049 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 27 / 3997 ~61.494 ms
+XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 54 / 4087 ~61.93 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 53 / 4050 ~61.376 ms
+XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 31 / 4119 ~61.482 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 31 / 4082 ~60.93 ms
+XXX[68] TO 17 ms, lFrame0 1 ms, lFrameX 25 / 4144 ~60.955 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 24 / 4106 ~60.396 ms
+XXX[69] TO 17 ms, lFrame0 1 ms, lFrameX 39 / 4184 ~60.646 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 38 / 4145 ~60.074 ms
+XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4233 ~60.475 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 48 / 4193 ~59.904 ms
+XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4265 ~60.081 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 32 / 4225 ~59.512 ms
+XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4289 ~59.578 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 23 / 4248 ~59.008 ms
+XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 26 / 4316 ~59.127 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 25 / 4274 ~58.555 ms
+XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4365 ~58.995 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 48 / 4323 ~58.422 ms
+XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4398 ~58.646 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 32 / 4355 ~58.072 ms
+XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4422 ~58.189 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 23 / 4378 ~57.612 ms
+XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 26 / 4448 ~57.777 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 25 / 4404 ~57.201 ms
+XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 4501 ~57.717 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 52 / 4457 ~57.142 ms
+XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 38 / 4540 ~57.476 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 38 / 4495 ~56.903 ms
+XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 37 / 4578 ~57.226 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 36 / 4532 ~56.651 ms
+XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 4647 ~57.373 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 68 / 4600 ~56.8 ms
+XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 4698 ~57.303 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 51 / 4651 ~56.73 ms
+XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 4742 ~57.134 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 42 / 4694 ~56.559 ms
+XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 4816 ~57.335 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 73 / 4767 ~56.761 ms
+XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4865 ~57.246 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 49 / 4817 ~56.674 ms
+XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 4909 ~57.083 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 42 / 4859 ~56.51 ms
+XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 4982 ~57.269 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 4932 ~56.696 ms
+XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5032 ~57.19 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 49 / 4982 ~56.618 ms
+XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 5076 ~57.041 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 43 / 5025 ~56.469 ms
+XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5149 ~57.214 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 71 / 5097 ~56.64 ms
+XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5199 ~57.141 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 50 / 5147 ~56.569 ms
+XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 44 / 5244 ~57.002 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 43 / 5191 ~56.429 ms
+XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 5317 ~57.174 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 5264 ~56.602 ms
+XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 5368 ~57.111 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 50 / 5314 ~56.54 ms
+XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 5416 ~57.02 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 47 / 5362 ~56.449 ms
+XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 5487 ~57.157 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 69 / 5432 ~56.586 ms
+XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5554 ~57.266 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 5499 ~56.696 ms
+XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 5607 ~57.216 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 51 / 5551 ~56.645 ms
+XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 5690 ~57.484 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 5634 ~56.913 ms
+XXX[100] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 5762 ~57.624 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 70 / 5705 ~57.053 ms
+XXX[101] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 5823 ~57.661 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 5765 ~57.088 ms
+XXX[102] TO 17 ms, lFrame0 0 ms, lFrameX 91 / 5914 ~57.989 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 90 / 5856 ~57.415 ms
+XXX[103] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5982 ~58.082 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 5923 ~57.509 ms
+XXX[104] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 6045 ~58.13 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 62 / 5985 ~57.555 ms
+XXX[105] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 6131 ~58.396 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 6071 ~57.82 ms
+XXX[106] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6199 ~58.482 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 6138 ~57.907 ms
+XXX[107] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6264 ~58.543 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 6202 ~57.966 ms
+XXX[108] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 6351 ~58.805 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 86 / 6288 ~58.228 ms
+XXX[109] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6434 ~59.034 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 6372 ~58.459 ms
+XXX[110] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6501 ~59.1 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 6437 ~58.523 ms
+XXX[111] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 6600 ~59.465 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 99 / 6536 ~58.888 ms
+XXX[112] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6684 ~59.681 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 6619 ~59.105 ms
+XXX[113] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6751 ~59.748 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 6686 ~59.172 ms
+XXX[114] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 6851 ~60.104 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 99 / 6786 ~59.528 ms
+XXX[115] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 6937 ~60.326 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 6871 ~59.75 ms
+XXX[116] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 7010 ~60.433 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 71 / 6943 ~59.854 ms
+XXX[117] TO 17 ms, lFrame0 0 ms, lFrameX 96 / 7107 ~60.744 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 96 / 7039 ~60.167 ms
+XXX[118] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7192 ~60.949 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 7123 ~60.372 ms
+XXX[119] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 7269 ~61.085 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 76 / 7200 ~60.506 ms
+XXX[120] TO 17 ms, lFrame0 0 ms, lFrameX 106 / 7376 ~61.467 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 106 / 7306 ~60.888 ms
+XXX[121] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 7455 ~61.614 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 7385 ~61.036 ms
+2013-06-17 03:02:44.695 java[63324:5f03] Persistent UI failed to open file file://localhost/Users/jogamp/Library/Saved%20Application%20State/com.apple.javajdk16.cmd.savedState/window_1.data: Operation not permitted (1)
+XXX[122] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 7525 ~61.68 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 69 / 7454 ~61.102 ms
+XXX[123] TO 17 ms, lFrame0 0 ms, lFrameX 93 / 7618 ~61.941 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 93 / 7547 ~61.363 ms
+XXX[124] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7699 ~62.095 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 7628 ~61.517 ms
+XXX[125] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7765 ~62.124 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 7693 ~61.544 ms
+XXX[126] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 7864 ~62.413 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 98 / 7791 ~61.834 ms
+XXX[127] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7946 ~62.573 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 7873 ~61.995 ms
+XXX[128] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 8010 ~62.584 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 7936 ~62.005 ms
+XXX[129] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 8096 ~62.76 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 8021 ~62.181 ms
+XXX[130] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8178 ~62.913 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 8103 ~62.333 ms
+XXX[131] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 8243 ~62.924 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 8167 ~62.343 ms
+XXX[132] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 8328 ~63.093 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 8251 ~62.511 ms
+XXX[133] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8394 ~63.115 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 8317 ~62.534 ms
+XXX[134] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 8457 ~63.117 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 62 / 8379 ~62.534 ms
+XXX[135] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 8543 ~63.287 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 8465 ~62.703 ms
+XXX[136] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8609 ~63.306 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 8530 ~62.723 ms
+XXX[137] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 8671 ~63.293 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 8591 ~62.709 ms
+XXX[138] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 8758 ~63.466 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 86 / 8677 ~62.882 ms
+XXX[139] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8825 ~63.489 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 8743 ~62.906 ms
+FrameCount: 240 - FrameRate: 13.0
+XXX[140] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 8886 ~63.474 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 8804 ~62.889 ms
+XXX[141] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 8974 ~63.649 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 8892 ~63.065 ms
+XXX[142] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9040 ~63.667 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 8957 ~63.082 ms
+XXX[143] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 9102 ~63.652 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 9018 ~63.066 ms
+XXX[144] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 9190 ~63.824 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 9106 ~63.238 ms
+XXX[145] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9257 ~63.841 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 9172 ~63.257 ms
+XXX[146] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 9318 ~63.823 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 9232 ~63.238 ms
+XXX[147] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 9407 ~63.995 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 88 / 9321 ~63.411 ms
+XXX[148] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9473 ~64.008 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 9386 ~63.424 ms
+XXX[149] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 9534 ~63.992 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 61 / 9447 ~63.408 ms
+XXX[150] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 9622 ~64.151 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 9535 ~63.568 ms
+XXX[151] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9688 ~64.161 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 9600 ~63.578 ms
+XXX[152] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 9748 ~64.132 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 59 / 9659 ~63.548 ms
+XXX[153] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 9837 ~64.297 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 88 / 9747 ~63.712 ms
+XXX[154] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9903 ~64.306 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 9813 ~63.721 ms
+XXX[155] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 9962 ~64.272 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 58 / 9871 ~63.687 ms
+XXX[156] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 10052 ~64.439 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 89 / 9961 ~63.854 ms
+XXX[157] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10118 ~64.451 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 10027 ~63.867 ms
+XXX[158] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 10177 ~64.417 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 58 / 10085 ~63.832 ms
+XXX[159] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 10268 ~64.583 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 90 / 10175 ~63.999 ms
+XXX[160] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10335 ~64.597 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 10242 ~64.014 ms
+XXX[161] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 10394 ~64.565 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 58 / 10300 ~63.981 ms
+XXX[162] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 10485 ~64.727 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 90 / 10391 ~64.144 ms
+XXX[163] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10552 ~64.741 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 10457 ~64.158 ms
+XXX[164] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 10613 ~64.714 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 59 / 10517 ~64.131 ms
+XXX[165] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 10702 ~64.862 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 88 / 10605 ~64.277 ms
+XXX[166] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10768 ~64.873 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 10671 ~64.288 ms
+XXX[167] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 10830 ~64.852 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 10732 ~64.266 ms
+XXX[168] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 10920 ~65.003 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 89 / 10822 ~64.418 ms
+XXX[169] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 10988 ~65.021 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 10889 ~64.436 ms
+XXX[170] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 11052 ~65.014 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 10952 ~64.428 ms
+XXX[171] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11138 ~65.136 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 11038 ~64.55 ms
+XXX[172] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11205 ~65.148 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 11104 ~64.562 ms
+XXX[173] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11273 ~65.165 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 11172 ~64.578 ms
+XXX[174] TO 17 ms, lFrame0 0 ms, lFrameX 101 / 11375 ~65.376 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 101 / 11273 ~64.789 ms
+XXX[175] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11460 ~65.49 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 11358 ~64.904 ms
+XXX[176] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 11535 ~65.542 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 73 / 11432 ~64.955 ms
+XXX[177] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 11632 ~65.722 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 96 / 11528 ~65.134 ms
+XXX[178] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11717 ~65.827 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 11612 ~65.239 ms
+XXX[179] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 11796 ~65.904 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 11691 ~65.315 ms
+XXX[180] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 11901 ~66.121 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 104 / 11795 ~65.532 ms
+XXX[181] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 11985 ~66.216 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 11878 ~65.627 ms
+XXX[182] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 12066 ~66.298 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 11958 ~65.708 ms
+XXX[183] TO 17 ms, lFrame0 0 ms, lFrameX 103 / 12170 ~66.502 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 12062 ~65.912 ms
+XXX[184] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12253 ~66.594 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 12144 ~66.004 ms
+XXX[185] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 12332 ~66.662 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 12223 ~66.071 ms
+XXX[186] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 12433 ~66.846 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 100 / 12323 ~66.254 ms
+XXX[187] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12515 ~66.929 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 12405 ~66.338 ms
+XXX[188] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 12592 ~66.983 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 76 / 12481 ~66.391 ms
+XXX[189] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 12696 ~67.179 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 12585 ~66.588 ms
+XXX[190] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12780 ~67.264 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 12667 ~66.673 ms
+XXX[191] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 12857 ~67.316 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 76 / 12744 ~66.724 ms
+XXX[192] TO 17 ms, lFrame0 1 ms, lFrameX 105 / 12963 ~67.517 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 104 / 12849 ~66.922 ms
+XXX[193] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13047 ~67.602 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 12932 ~67.008 ms
+XXX[194] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 13122 ~67.64 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 74 / 13006 ~67.045 ms
+XXX[195] TO 17 ms, lFrame0 0 ms, lFrameX 106 / 13228 ~67.837 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 105 / 13112 ~67.242 ms
+XXX[196] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13309 ~67.908 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 13193 ~67.313 ms
+XXX[197] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 13381 ~67.928 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 71 / 13264 ~67.332 ms
+XXX[198] TO 17 ms, lFrame0 0 ms, lFrameX 91 / 13473 ~68.046 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 90 / 13355 ~67.451 ms
+XXX[199] TO 17 ms, lFrame0 1 ms, lFrameX 81 / 13554 ~68.114 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 79 / 13435 ~67.514 ms
+XXX[200] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 13621 ~68.109 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 13501 ~67.508 ms
+XXX[201] TO 17 ms, lFrame0 0 ms, lFrameX 96 / 13718 ~68.251 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 95 / 13597 ~67.649 ms
+XXX[202] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13800 ~68.317 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 13678 ~67.716 ms
+XXX[203] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 13864 ~68.296 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 13742 ~67.695 ms
+XXX[204] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 13949 ~68.381 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 13827 ~67.781 ms
+XXX[205] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 14015 ~68.369 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 13892 ~67.769 ms
+XXX[206] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 14081 ~68.358 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 13958 ~67.757 ms
+XXX[207] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 14170 ~68.455 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 88 / 14046 ~67.855 ms
+XXX[208] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14255 ~68.537 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 14131 ~67.938 ms
+XXX[209] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 14329 ~68.56 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 14203 ~67.961 ms
+XXX[210] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 14426 ~68.699 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 96 / 14300 ~68.099 ms
+XXX[211] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 14511 ~68.774 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 14384 ~68.174 ms
+XXX[212] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 14588 ~68.814 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 76 / 14461 ~68.214 ms
+XXX[213] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 14694 ~68.986 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 105 / 14566 ~68.387 ms
+XXX[214] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 14777 ~69.051 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 14648 ~68.452 ms
+XXX[215] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 14852 ~69.081 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 74 / 14723 ~68.482 ms
+XXX[216] TO 17 ms, lFrame0 1 ms, lFrameX 106 / 14959 ~69.256 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 105 / 14829 ~68.653 ms
+XXX[217] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15041 ~69.314 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 14910 ~68.712 ms
+XXX[218] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 15114 ~69.333 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 14983 ~68.73 ms
+XXX[219] TO 17 ms, lFrame0 0 ms, lFrameX 91 / 15206 ~69.435 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 91 / 15074 ~68.833 ms
+XXX[220] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15287 ~69.489 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 15155 ~68.888 ms
+XXX[221] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 15356 ~69.486 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 68 / 15223 ~68.885 ms
+XXX[222] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 15451 ~69.599 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 94 / 15317 ~68.998 ms
+XXX[223] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15532 ~69.652 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 15398 ~69.051 ms
+XXX[224] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 15597 ~69.63 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 15462 ~69.028 ms
+XXX[225] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 15677 ~69.678 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 79 / 15542 ~69.077 ms
+XXX[226] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 15744 ~69.664 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 15608 ~69.062 ms
+XXX[227] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 15807 ~69.637 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 62 / 15671 ~69.035 ms
+XXX[228] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 15893 ~69.709 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 15756 ~69.107 ms
+XXX[229] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 15960 ~69.696 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 15822 ~69.095 ms
+XXX[230] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 16023 ~69.667 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 62 / 15884 ~69.064 ms
+XXX[231] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 16109 ~69.738 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 15970 ~69.134 ms
+XXX[232] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16175 ~69.721 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 16035 ~69.119 ms
+XXX[233] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 16237 ~69.687 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 61 / 16096 ~69.085 ms
+XXX[234] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 16324 ~69.764 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 16184 ~69.162 ms
+XXX[235] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16392 ~69.754 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 16250 ~69.152 ms
+XXX[236] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 16456 ~69.729 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 16314 ~69.127 ms
+XXX[237] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 16543 ~69.804 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 16401 ~69.203 ms
+XXX[238] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16611 ~69.796 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 16468 ~69.196 ms
+XXX[239] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16679 ~69.788 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 16535 ~69.187 ms
+XXX[240] TO 17 ms, lFrame0 0 ms, lFrameX 103 / 16782 ~69.926 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 102 / 16638 ~69.326 ms
+XXX[241] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 16868 ~69.993 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 16723 ~69.393 ms
+XXX[242] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 16942 ~70.009 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 73 / 16796 ~69.408 ms
+XXX[243] TO 17 ms, lFrame0 0 ms, lFrameX 95 / 17037 ~70.113 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 94 / 16891 ~69.512 ms
+XXX[244] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17122 ~70.173 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 16975 ~69.573 ms
+XXX[245] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 17200 ~70.204 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 77 / 17053 ~69.604 ms
+XXX[246] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 17307 ~70.356 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 107 / 17160 ~69.756 ms
+XXX[247] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17391 ~70.411 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 17243 ~69.811 ms
+XXX[248] TO 17 ms, lFrame0 0 ms, lFrameX 78 / 17470 ~70.445 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 17321 ~69.845 ms
+XXX[249] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 17574 ~70.58 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 17424 ~69.979 ms
+XXX[250] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17657 ~70.629 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 17507 ~70.029 ms
+XXX[251] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 17735 ~70.658 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 77 / 17584 ~70.058 ms
+XXX[252] TO 17 ms, lFrame0 0 ms, lFrameX 103 / 17839 ~70.789 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 17687 ~70.189 ms
+XXX[253] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17921 ~70.836 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 17769 ~70.236 ms
+XXX[254] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 17997 ~70.856 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 75 / 17845 ~70.256 ms
+XXX[255] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 18102 ~70.988 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 17949 ~70.388 ms
+XXX[256] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18184 ~71.032 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 18030 ~70.432 ms
+XXX[257] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 18257 ~71.04 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 18103 ~70.44 ms
+XXX[258] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 18347 ~71.114 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 89 / 18192 ~70.514 ms
+XXX[259] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18429 ~71.157 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 18274 ~70.557 ms
+FrameCount: 360 - FrameRate: 12.0
+XXX[260] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 18499 ~71.152 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 69 / 18343 ~70.551 ms
+XXX[261] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 18594 ~71.241 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 94 / 18437 ~70.641 ms
+XXX[262] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18676 ~71.285 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 18519 ~70.684 ms
+XXX[263] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 18744 ~71.27 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 18586 ~70.67 ms
+XXX[264] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 18841 ~71.37 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 97 / 18683 ~70.77 ms
+XXX[265] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18923 ~71.409 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 18764 ~70.809 ms
+XXX[266] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 18988 ~71.386 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 18829 ~70.786 ms
+XXX[267] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 19071 ~71.43 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 18911 ~70.83 ms
+XXX[268] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19137 ~71.409 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 18977 ~70.809 ms
+XXX[269] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 19201 ~71.38 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 62 / 19039 ~70.78 ms
+XXX[270] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 19286 ~71.431 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 19124 ~70.831 ms
+XXX[271] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 19351 ~71.407 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 19188 ~70.807 ms
+XXX[272] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 19411 ~71.366 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 59 / 19248 ~70.765 ms
+XXX[273] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 19499 ~71.426 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 19335 ~70.827 ms
+XXX[274] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19564 ~71.404 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 19400 ~70.805 ms
+XXX[275] TO 17 ms, lFrame0 0 ms, lFrameX 57 / 19622 ~71.353 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 56 / 19457 ~70.753 ms
+XXX[276] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 19694 ~71.358 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 19529 ~70.759 ms
+XXX[277] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19760 ~71.335 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 19594 ~70.737 ms
+XXX[278] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 19813 ~71.271 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 52 / 19647 ~70.672 ms
+XXX[279] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 19891 ~71.294 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 77 / 19724 ~70.695 ms
+XXX[280] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19957 ~71.276 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 19789 ~70.677 ms
+XXX[281] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 20008 ~71.205 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 50 / 19840 ~70.605 ms
+XXX[282] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 20089 ~71.237 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 79 / 19920 ~70.638 ms
+XXX[283] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20154 ~71.218 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 19985 ~70.62 ms
+XXX[284] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 20204 ~71.141 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 48 / 20034 ~70.542 ms
+XXX[285] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 20287 ~71.184 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 20117 ~70.585 ms
+XXX[286] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20354 ~71.167 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 20182 ~70.569 ms
+XXX[287] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 20404 ~71.095 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 49 / 20232 ~70.496 ms
+XXX[288] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 20488 ~71.139 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 20315 ~70.541 ms
+XXX[289] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 20556 ~71.129 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 20383 ~70.532 ms
+XXX[290] TO 17 ms, lFrame0 0 ms, lFrameX 55 / 20611 ~71.074 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 54 / 20438 ~70.476 ms
+XXX[291] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 20693 ~71.111 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 20519 ~70.513 ms
+XXX[292] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 20762 ~71.105 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 68 / 20588 ~70.507 ms
+XXX[293] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 20826 ~71.08 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 20651 ~70.483 ms
+XXX[294] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 20921 ~71.16 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 93 / 20745 ~70.562 ms
+XXX[295] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 21010 ~71.221 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 88 / 20834 ~70.624 ms
+XXX[296] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 21086 ~71.239 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 75 / 20909 ~70.64 ms
+XXX[297] TO 17 ms, lFrame0 0 ms, lFrameX 110 / 21197 ~71.372 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 110 / 21019 ~70.773 ms
+XXX[298] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21281 ~71.415 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 21103 ~70.816 ms
+XXX[299] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 21360 ~71.441 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 21181 ~70.842 ms
+XXX[300] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 21465 ~71.55 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 21285 ~70.951 ms
+XXX[301] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21549 ~71.592 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 21369 ~70.993 ms
+XXX[302] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 21630 ~71.622 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 21449 ~71.023 ms
+XXX[303] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 21734 ~71.731 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 104 / 21553 ~71.132 ms
+XXX[304] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 21835 ~71.825 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 99 / 21653 ~71.227 ms
+XXX[305] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 21915 ~71.855 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 21733 ~71.256 ms
+XXX[306] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 22016 ~71.948 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 99 / 21832 ~71.349 ms
+XXX[307] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22098 ~71.982 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 21914 ~71.383 ms
+XXX[308] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 22178 ~72.006 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 79 / 21993 ~71.408 ms
+XXX[309] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 22264 ~72.053 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 86 / 22079 ~71.455 ms
+XXX[310] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22347 ~72.088 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22162 ~71.49 ms
+XXX[311] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22430 ~72.124 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22245 ~71.527 ms
+XXX[312] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22513 ~72.159 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22327 ~71.562 ms
+XXX[313] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22597 ~72.195 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22410 ~71.597 ms
+XXX[314] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22680 ~72.23 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22492 ~71.633 ms
+XXX[315] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22763 ~72.265 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22575 ~71.668 ms
+XXX[316] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 22863 ~72.351 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 98 / 22674 ~71.754 ms
+XXX[317] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 22947 ~72.39 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 22758 ~71.793 ms
+XXX[318] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23031 ~72.425 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 22841 ~71.829 ms
+XXX[319] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23112 ~72.453 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 22922 ~71.857 ms
+XXX[320] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 23196 ~72.49 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 23006 ~71.894 ms
+XXX[321] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23279 ~72.522 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 23088 ~71.926 ms
+XXX[322] TO 17 ms, lFrame0 5 ms, lFrameX 84 / 23363 ~72.557 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 23167 ~71.947 ms
+XXX[323] TO 17 ms, lFrame0 0 ms, lFrameX 96 / 23460 ~72.632 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 96 / 23263 ~72.022 ms
+XXX[324] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23542 ~72.662 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 23345 ~72.052 ms
+XXX[325] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23625 ~72.694 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 23427 ~72.085 ms
+XXX[326] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23708 ~72.726 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 23510 ~72.117 ms
+XXX[327] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23791 ~72.758 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 23592 ~72.149 ms
+XXX[328] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23874 ~72.789 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 23675 ~72.18 ms
+XXX[329] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23957 ~72.819 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 23757 ~72.21 ms
+XXX[330] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24040 ~72.85 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 23840 ~72.243 ms
+XXX[331] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24123 ~72.88 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 23922 ~72.273 ms
+XXX[332] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24206 ~72.911 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24005 ~72.304 ms
+XXX[333] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24289 ~72.942 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24087 ~72.335 ms
+XXX[334] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24372 ~72.972 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24170 ~72.365 ms
+XXX[335] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24456 ~73.004 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 24253 ~72.398 ms
+XXX[336] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24539 ~73.034 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24335 ~72.428 ms
+XXX[337] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24622 ~73.063 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24418 ~72.457 ms
+XXX[338] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24705 ~73.094 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 24501 ~72.488 ms
+XXX[339] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24788 ~73.123 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24583 ~72.518 ms
+XXX[340] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24872 ~73.153 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24666 ~72.548 ms
+XXX[341] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24955 ~73.184 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 24749 ~72.579 ms
+XXX[342] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25038 ~73.211 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 24831 ~72.606 ms
+XXX[343] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 25121 ~73.24 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24913 ~72.634 ms
+XXX[344] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25204 ~73.268 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24996 ~72.663 ms
+XXX[345] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25288 ~73.299 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 25079 ~72.694 ms
+XXX[346] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25371 ~73.328 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25162 ~72.723 ms
+XXX[347] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25454 ~73.355 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25244 ~72.75 ms
+XXX[348] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25537 ~73.384 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25327 ~72.78 ms
+XXX[349] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25621 ~73.414 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 25410 ~72.81 ms
+XXX[350] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25704 ~73.442 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25493 ~72.838 ms
+XXX[351] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25788 ~73.472 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 25577 ~72.869 ms
+XXX[352] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25871 ~73.499 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25659 ~72.895 ms
+XXX[353] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25955 ~73.527 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 25742 ~72.924 ms
+XXX[354] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26037 ~73.553 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25824 ~72.95 ms
+XXX[355] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26121 ~73.582 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 25908 ~72.98 ms
+XXX[356] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26204 ~73.608 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25990 ~73.006 ms
+XXX[357] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26287 ~73.634 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26072 ~73.033 ms
+XXX[358] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 26369 ~73.657 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 26154 ~73.056 ms
+XXX[359] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26452 ~73.683 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26236 ~73.083 ms
+XXX[360] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26534 ~73.708 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26318 ~73.107 ms
+XXX[361] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26618 ~73.734 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26401 ~73.134 ms
+XXX[362] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26700 ~73.758 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 26483 ~73.159 ms
+XXX[363] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26783 ~73.785 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26566 ~73.185 ms
+XXX[364] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26866 ~73.809 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26648 ~73.21 ms
+XXX[365] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26949 ~73.833 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26730 ~73.235 ms
+XXX[366] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27031 ~73.857 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26812 ~73.259 ms
+XXX[367] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27114 ~73.882 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26895 ~73.284 ms
+XXX[368] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27197 ~73.906 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26977 ~73.308 ms
+XXX[369] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27279 ~73.928 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 27059 ~73.331 ms
+XXX[370] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27362 ~73.954 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27142 ~73.357 ms
+XXX[371] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 27447 ~73.983 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 84 / 27226 ~73.387 ms
+XXX[372] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 27532 ~74.01 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 27310 ~73.414 ms
+XXX[373] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27615 ~74.035 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27393 ~73.439 ms
+XXX[374] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27698 ~74.06 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27475 ~73.464 ms
+XXX[375] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 27782 ~74.087 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 27559 ~73.492 ms
+XXX[376] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 27868 ~74.117 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 84 / 27644 ~73.522 ms
+XXX[377] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 27952 ~74.144 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 27728 ~73.549 ms
+XXX[378] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28035 ~74.168 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27811 ~73.574 ms
+XXX[379] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28118 ~74.191 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27893 ~73.597 ms
+FrameCount: 480 - FrameRate: 12.0
+XXX[380] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28201 ~74.215 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27976 ~73.621 ms
+XXX[381] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28284 ~74.238 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28058 ~73.645 ms
+XXX[382] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28367 ~74.261 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28141 ~73.667 ms
+XXX[383] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28450 ~74.284 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28223 ~73.691 ms
+XXX[384] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28533 ~74.306 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28306 ~73.714 ms
+XXX[385] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28616 ~74.327 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 28388 ~73.735 ms
+XXX[386] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28699 ~74.35 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28470 ~73.758 ms
+XXX[387] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28781 ~74.371 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28552 ~73.779 ms
+XXX[388] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 28863 ~74.39 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 28634 ~73.799 ms
+XXX[389] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 28945 ~74.41 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 28715 ~73.818 ms
+XXX[390] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29028 ~74.432 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28797 ~73.84 ms
+XXX[391] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29111 ~74.453 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 28880 ~73.862 ms
+XXX[392] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29194 ~74.475 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 28962 ~73.884 ms
+XXX[393] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29277 ~74.497 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29045 ~73.906 ms
+XXX[394] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29359 ~74.516 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 81 / 29127 ~73.926 ms
+XXX[395] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29442 ~74.537 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29209 ~73.947 ms
+XXX[396] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29525 ~74.559 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29291 ~73.969 ms
+XXX[397] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29608 ~74.579 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29373 ~73.989 ms
+XXX[398] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29691 ~74.601 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29456 ~74.011 ms
+XXX[399] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29775 ~74.624 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 83 / 29539 ~74.034 ms
+XXX[400] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29857 ~74.643 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 81 / 29621 ~74.054 ms
+XXX[401] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29940 ~74.663 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29704 ~74.074 ms
+XXX[402] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30022 ~74.683 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29786 ~74.095 ms
+XXX[403] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30105 ~74.703 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29868 ~74.115 ms
+XXX[404] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30188 ~74.724 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29951 ~74.136 ms
+XXX[405] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30272 ~74.745 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 30034 ~74.158 ms
+XXX[406] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30355 ~74.768 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 83 / 30117 ~74.18 ms
+XXX[407] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30439 ~74.79 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 83 / 30200 ~74.203 ms
+XXX[408] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30524 ~74.814 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 83 / 30284 ~74.227 ms
+XXX[409] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30606 ~74.833 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 81 / 30366 ~74.246 ms
+XXX[410] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 30686 ~74.846 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 79 / 30446 ~74.259 ms
+XXX[411] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 30767 ~74.859 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 79 / 30526 ~74.273 ms
+XXX[412] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 30847 ~74.872 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 79 / 30606 ~74.286 ms
+XXX[413] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 30911 ~74.846 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 63 / 30669 ~74.26 ms
+XXX[414] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 30977 ~74.825 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 30735 ~74.239 ms
+XXX[415] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31043 ~74.802 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 30800 ~74.217 ms
+XXX[416] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31108 ~74.78 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 30865 ~74.195 ms
+XXX[417] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31174 ~74.759 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 30930 ~74.174 ms
+XXX[418] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31240 ~74.738 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 30996 ~74.154 ms
+XXX[419] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31306 ~74.718 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 31062 ~74.134 ms
+XXX[420] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31373 ~74.697 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 31127 ~74.113 ms
+XXX[421] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31438 ~74.675 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 64 / 31192 ~74.092 ms
+XXX[422] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31504 ~74.656 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 31258 ~74.072 ms
+XXX[423] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31570 ~74.635 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 31324 ~74.052 ms
+XXX[424] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31637 ~74.617 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 66 / 31390 ~74.034 ms
+XXX[425] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 31704 ~74.599 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31457 ~74.016 ms
+XXX[426] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31771 ~74.58 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31523 ~73.997 ms
+XXX[427] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31837 ~74.561 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 31588 ~73.978 ms
+XXX[428] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 31905 ~74.544 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 67 / 31656 ~73.962 ms
+XXX[429] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31971 ~74.526 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31722 ~73.944 ms
+XXX[430] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32038 ~74.508 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31788 ~73.927 ms
+XXX[431] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32105 ~74.49 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31854 ~73.909 ms
+XXX[432] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32172 ~74.473 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31921 ~73.892 ms
+XXX[433] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32238 ~74.453 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 31987 ~73.873 ms
+XXX[434] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32305 ~74.435 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 32053 ~73.855 ms
+XXX[435] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32371 ~74.416 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32118 ~73.836 ms
+XXX[436] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32438 ~74.399 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 32185 ~73.819 ms
+XXX[437] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32504 ~74.381 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 32251 ~73.801 ms
+XXX[438] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32570 ~74.362 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32316 ~73.782 ms
+XXX[439] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32636 ~74.342 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32381 ~73.763 ms
+XXX[440] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32702 ~74.323 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32447 ~73.744 ms
+XXX[441] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32768 ~74.303 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32512 ~73.724 ms
+XXX[442] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32833 ~74.284 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32577 ~73.705 ms
+XXX[443] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32898 ~74.263 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 32642 ~73.685 ms
+XXX[444] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32964 ~74.244 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32707 ~73.665 ms
+XXX[445] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33030 ~74.224 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32772 ~73.646 ms
+XXX[446] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33096 ~74.206 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32838 ~73.628 ms
+XXX[447] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33161 ~74.186 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 32903 ~73.609 ms
+XXX[448] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33226 ~74.167 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 32968 ~73.589 ms
+XXX[449] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33292 ~74.148 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 33033 ~73.571 ms
+XXX[450] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33358 ~74.129 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 33098 ~73.552 ms
+XXX[451] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33423 ~74.11 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 33163 ~73.533 ms
+XXX[452] TO 17 ms, lFrame0 0 ms, lFrameX 47 / 33471 ~74.052 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 47 / 33210 ~73.474 ms
+XXX[453] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 33521 ~73.999 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 33260 ~73.422 ms
+XXX[454] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33570 ~73.944 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33308 ~73.367 ms
+XXX[455] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33619 ~73.888 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 47 / 33356 ~73.311 ms
+XXX[456] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 33669 ~73.836 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 33406 ~73.259 ms
+XXX[457] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33718 ~73.781 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33454 ~73.205 ms
+XXX[458] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33767 ~73.728 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33503 ~73.152 ms
+XXX[459] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33816 ~73.674 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33552 ~73.099 ms
+XXX[460] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33866 ~73.622 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 33601 ~73.046 ms
+XXX[461] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33915 ~73.569 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33650 ~72.993 ms
+XXX[462] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33964 ~73.515 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33698 ~72.94 ms
+XXX[463] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34013 ~73.462 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33747 ~72.887 ms
+XXX[464] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34062 ~73.41 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33795 ~72.835 ms
+XXX[465] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34111 ~73.357 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33844 ~72.783 ms
+XXX[466] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34160 ~73.305 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33892 ~72.731 ms
+XXX[467] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34209 ~73.253 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33941 ~72.679 ms
+XXX[468] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34258 ~73.202 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33989 ~72.628 ms
+XXX[469] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34307 ~73.15 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 34038 ~72.576 ms
+XXX[470] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34356 ~73.099 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 34087 ~72.525 ms
+XXX[471] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34405 ~73.048 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 34135 ~72.474 ms
+XXX[472] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34455 ~72.998 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 34184 ~72.424 ms
+XXX[473] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34503 ~72.945 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 47 / 34232 ~72.372 ms
+XXX[474] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34553 ~72.897 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 34281 ~72.324 ms
+XXX[475] TO 17 ms, lFrame0 2 ms, lFrameX 34 / 34588 ~72.816 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 31 / 34313 ~72.239 ms
+XXX[476] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 34653 ~72.8 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 34378 ~72.223 ms
+XXX[477] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34703 ~72.754 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 50 / 34428 ~72.177 ms
+XXX[478] TO 17 ms, lFrame0 1 ms, lFrameX 33 / 34737 ~72.672 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 32 / 34461 ~72.094 ms
+XXX[479] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 34803 ~72.658 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 34526 ~72.08 ms
+XXX[480] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34852 ~72.61 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 34575 ~72.031 ms
+XXX[481] TO 17 ms, lFrame0 0 ms, lFrameX 34 / 34887 ~72.53 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 33 / 34608 ~71.951 ms
+XXX[482] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 34954 ~72.519 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 34675 ~71.94 ms
+XXX[483] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35004 ~72.473 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 34725 ~71.894 ms
+XXX[484] TO 17 ms, lFrame0 0 ms, lFrameX 35 / 35040 ~72.396 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 34 / 34760 ~71.818 ms
+XXX[485] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 35105 ~72.381 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 34824 ~71.803 ms
+XXX[486] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35155 ~72.336 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 34874 ~71.757 ms
+XXX[487] TO 17 ms, lFrame0 0 ms, lFrameX 37 / 35192 ~72.264 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 36 / 34911 ~71.685 ms
+XXX[488] TO 17 ms, lFrame0 1 ms, lFrameX 46 / 35238 ~72.21 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 44 / 34955 ~71.629 ms
+XXX[489] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35289 ~72.167 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 50 / 35005 ~71.585 ms
+XXX[490] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 35356 ~72.156 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 35071 ~71.574 ms
+XXX[491] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35406 ~72.111 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 35121 ~71.529 ms
+XXX[492] TO 17 ms, lFrame0 0 ms, lFrameX 38 / 35445 ~72.043 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 37 / 35159 ~71.461 ms
+XXX[493] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 35506 ~72.021 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 60 / 35220 ~71.44 ms
+XXX[494] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35557 ~71.978 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 35269 ~71.396 ms
+XXX[495] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35607 ~71.933 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 35318 ~71.35 ms
+XXX[496] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35657 ~71.89 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 35368 ~71.307 ms
+XXX[497] TO 17 ms, lFrame0 0 ms, lFrameX 41 / 35698 ~71.828 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 40 / 35408 ~71.244 ms
+XXX[498] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 35775 ~71.837 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 75 / 35484 ~71.254 ms
+XXX[499] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 35828 ~71.799 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 52 / 35537 ~71.216 ms
+FrameCount: 600 - FrameRate: 20.0
+XXX[500] TO 17 ms, lFrame0 0 ms, lFrameX 47 / 35875 ~71.75 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 46 / 35583 ~71.167 ms
+XXX[501] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 35950 ~71.756 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 73 / 35657 ~71.172 ms
+XXX[502] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 36020 ~71.753 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 69 / 35727 ~71.169 ms
+XXX[503] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 36080 ~71.73 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 59 / 35787 ~71.147 ms
+XXX[504] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 36151 ~71.728 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 70 / 35857 ~71.145 ms
+XXX[505] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 36241 ~71.766 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 90 / 35947 ~71.183 ms
+XXX[506] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36325 ~71.789 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 36030 ~71.207 ms
+XXX[507] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36408 ~71.811 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36113 ~71.229 ms
+XXX[508] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36491 ~71.833 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36195 ~71.251 ms
+XXX[509] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36575 ~71.856 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 36278 ~71.274 ms
+XXX[510] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36658 ~71.878 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36361 ~71.296 ms
+XXX[511] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36740 ~71.899 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36443 ~71.317 ms
+XXX[512] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36823 ~71.921 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36525 ~71.339 ms
+XXX[513] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36906 ~71.942 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36608 ~71.361 ms
+XXX[514] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36990 ~71.965 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 36691 ~71.384 ms
+XXX[515] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37073 ~71.987 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36774 ~71.406 ms
+XXX[516] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37156 ~72.009 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36857 ~71.428 ms
+XXX[517] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37240 ~72.031 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 36940 ~71.451 ms
+XXX[518] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37323 ~72.053 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37023 ~71.473 ms
+XXX[519] TO 17 ms, lFrame0 6 ms, lFrameX 82 / 37406 ~72.073 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 76 / 37099 ~71.482 ms
+XXX[520] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37488 ~72.092 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 37181 ~71.501 ms
+XXX[521] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37571 ~72.113 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37263 ~71.523 ms
+XXX[522] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37654 ~72.134 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37345 ~71.543 ms
+XXX[523] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37736 ~72.154 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37427 ~71.563 ms
+XXX[524] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37819 ~72.174 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37510 ~71.584 ms
+XXX[525] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37902 ~72.195 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37592 ~71.605 ms
+XXX[526] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37985 ~72.215 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37675 ~71.625 ms
+XXX[527] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38068 ~72.237 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 37758 ~71.647 ms
+XXX[528] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38152 ~72.258 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37841 ~71.668 ms
+XXX[529] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38235 ~72.278 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37923 ~71.689 ms
+XXX[530] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38319 ~72.3 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 38007 ~71.711 ms
+XXX[531] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38403 ~72.323 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 84 / 38091 ~71.734 ms
+XXX[532] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38486 ~72.343 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 38173 ~71.755 ms
+XXX[533] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38571 ~72.366 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 38257 ~71.777 ms
+XXX[534] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38654 ~72.387 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 38340 ~71.799 ms
+XXX[535] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38738 ~72.408 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 38423 ~71.82 ms
+XXX[536] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38822 ~72.429 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 38507 ~71.841 ms
+XXX[537] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38906 ~72.45 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 38590 ~71.862 ms
+XXX[538] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38988 ~72.469 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 38672 ~71.881 ms
+XXX[539] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39070 ~72.487 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 38754 ~71.9 ms
+XXX[540] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39153 ~72.506 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 38836 ~71.919 ms
+XXX[541] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39236 ~72.525 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 38918 ~71.938 ms
+XXX[542] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39318 ~72.543 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 39000 ~71.956 ms
+XXX[543] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 39398 ~72.557 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 80 / 39080 ~71.971 ms
+XXX[544] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39481 ~72.575 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 39162 ~71.989 ms
+XXX[545] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39564 ~72.594 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 39244 ~72.008 ms
+XXX[546] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39645 ~72.611 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 39325 ~72.025 ms
+XXX[547] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39727 ~72.627 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 39406 ~72.041 ms
+XXX[548] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39808 ~72.643 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 80 / 39487 ~72.057 ms
+XXX[549] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39889 ~72.659 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 80 / 39568 ~72.073 ms
+XXX[550] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39971 ~72.676 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 39649 ~72.09 ms
+XXX[551] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 40036 ~72.661 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 39714 ~72.076 ms
+XXX[552] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40101 ~72.648 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 39778 ~72.063 ms
+XXX[553] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40166 ~72.634 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 39843 ~72.049 ms
+XXX[554] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40232 ~72.622 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 39908 ~72.037 ms
+XXX[555] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40298 ~72.609 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 39973 ~72.024 ms
+XXX[556] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40364 ~72.597 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 40039 ~72.012 ms
+XXX[557] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 40431 ~72.588 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 40106 ~72.003 ms
+XXX[558] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40497 ~72.576 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 40171 ~71.991 ms
+XXX[559] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40563 ~72.565 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 40237 ~71.981 ms
+XXX[560] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40630 ~72.554 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 40303 ~71.971 ms
+XXX[561] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40697 ~72.544 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 40369 ~71.96 ms
+XXX[562] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40763 ~72.532 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 40435 ~71.948 ms
+XXX[563] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 40831 ~72.525 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 68 / 40503 ~71.942 ms
+XXX[564] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 40901 ~72.52 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 69 / 40572 ~71.936 ms
+XXX[565] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 40973 ~72.518 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 71 / 40643 ~71.935 ms
+XXX[566] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 41061 ~72.546 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 87 / 40731 ~71.963 ms
+XXX[567] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 41148 ~72.571 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 86 / 40817 ~71.989 ms
+XXX[568] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 41233 ~72.594 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 85 / 40903 ~72.012 ms
+XXX[569] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 41317 ~72.614 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 40986 ~72.032 ms
+XXX[570] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 41398 ~72.629 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 80 / 41066 ~72.047 ms
+XXX[571] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 41480 ~72.644 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 80 / 41147 ~72.062 ms
+XXX[572] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41562 ~72.661 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41229 ~72.08 ms
+XXX[573] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41645 ~72.679 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41312 ~72.098 ms
+XXX[574] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41728 ~72.697 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41394 ~72.115 ms
+XXX[575] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41810 ~72.713 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 41476 ~72.132 ms
+XXX[576] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41893 ~72.731 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41558 ~72.15 ms
+XXX[577] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 41976 ~72.749 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41641 ~72.169 ms
+XXX[578] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42059 ~72.767 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41724 ~72.187 ms
+XXX[579] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42143 ~72.787 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 41807 ~72.206 ms
+XXX[580] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42227 ~72.805 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 41890 ~72.225 ms
+XXX[581] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42310 ~72.823 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41973 ~72.243 ms
+XXX[582] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42395 ~72.844 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 84 / 42057 ~72.264 ms
+XXX[583] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42478 ~72.862 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 42140 ~72.282 ms
+XXX[584] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42562 ~72.88 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 42223 ~72.301 ms
+XXX[585] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42644 ~72.896 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 42305 ~72.317 ms
+XXX[586] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 42726 ~72.911 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 42386 ~72.332 ms
+XXX[587] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 42808 ~72.926 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 42468 ~72.347 ms
+XXX[588] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42890 ~72.942 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 42549 ~72.363 ms
+XXX[589] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42973 ~72.959 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 42632 ~72.38 ms
+XXX[590] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 43056 ~72.977 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 42715 ~72.398 ms
+XXX[591] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43138 ~72.992 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 42796 ~72.413 ms
+XXX[592] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 43221 ~73.01 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 42879 ~72.431 ms
+XXX[593] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43304 ~73.026 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 42961 ~72.448 ms
+XXX[594] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43387 ~73.042 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43043 ~72.464 ms
+XXX[595] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43470 ~73.059 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43126 ~72.48 ms
+XXX[596] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 43553 ~73.075 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43208 ~72.497 ms
+XXX[597] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43636 ~73.092 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43290 ~72.514 ms
+XXX[598] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43718 ~73.108 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43373 ~72.53 ms
+XXX[599] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 43802 ~73.126 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 43456 ~72.549 ms
+XXX[600] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43885 ~73.142 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 43538 ~72.564 ms
+XXX[601] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43968 ~73.158 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43621 ~72.581 ms
+XXX[602] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 44051 ~73.175 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43704 ~72.598 ms
+XXX[603] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 44135 ~73.193 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 43787 ~72.616 ms
+XXX[604] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 44219 ~73.21 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 43870 ~72.633 ms
+XXX[605] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 44302 ~73.227 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43953 ~72.65 ms
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync1-flush-wait-finish.log b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync1-flush-wait-finish.log
new file mode 100644
index 000000000..fe90a4ede
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync1-flush-wait-finish.log
@@ -0,0 +1,745 @@
+NSZombieEnabled
+NSTraceEvents YES
+OBJC_PRINT_EXCEPTIONS
+/usr/bin/java
+java version "1.6.0_37"
+Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909)
+Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)
+LD_LIBRARY_PATH :../../gluegen/make/../build-macosx/obj:../build-macosx/lib
+LIBXCB_ALLOW_SLOPPY_LOCK:
+LIBGL_DRIVERS_PATH:
+LIBGL_DEBUG:
+LIBGL_ALWAYS_INDIRECT:
+LIBGL_ALWAYS_SOFTWARE:
+SWT_CLASSPATH: ../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar
+/usr/bin/java -d64 -time 100000 -vsyncN 0
+CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar
+CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar
+
+Test Start: com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsyncN 0
+
+/usr/bin/java -d64 -Djava.awt.headless=false -Djogl.debug.calayer.SwapM1 com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsyncN 0
+swapInterval 1
+exclusiveContext false
+SWAP_M1 true
+SWAP_M2 false
+NewtCanvasAWT.attachNewtChild.2: size 500x268
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init ...
+LandscapeES2 init on Thread[main-Display-.macosx_nil-1-EDT-1,5,main]
+Chosen GLCapabilities: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/0, dbl, mono , hw, GLProfile[GL2/GL2.hw], offscr[fbo]]
+INIT GL IS: jogamp.opengl.gl4.GL4bcImpl
+GL_VENDOR: NVIDIA Corporation
+GL_RENDERER: NVIDIA GeForce 320M OpenGL Engine
+GL_VERSION: 2.1 NVIDIA-7.32.12
+GL GLSL: true, has-compiler-func: true, version 1.20, 1.20.0
+GL FBO: basic true, full true
+GL Profile: GLProfile[GL2/GL2.hw]
+GL Renderer Quirks:[NoOffscreenBitmap]
+GL:jogamp.opengl.gl4.GL4bcImpl@57ac3379, 2.1 (hardware) - 2.1 NVIDIA-7.32.12
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init FIN
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.reshape 0/0 500x268, swapInterval 1, drawable 0x7ffd218cbca0
+Thread[AWT-EventQueue-0,6,main] LandscapeES2.reshape 0/0 500x268, swapInterval 1, drawable 0x7ffd218cbca0
+XXX[1] TO 17 ms, lFrame0 112 ms, lFrameX 850 / 850 ~850.044 ms, flushGL 1 / 1 ~1.124 ms, waitGL 5 / 5 ~5.544 ms, finishGL 731 / 731 ~731.319 ms
+XXX[2] TO 17 ms, lFrame0 91 ms, lFrameX 179 / 1029 ~514.913 ms, flushGL 0 / 1 ~0.564 ms, waitGL 30 / 36 ~18.01 ms, finishGL 57 / 788 ~394.472 ms
+XXX[3] TO 17 ms, lFrame0 2 ms, lFrameX 82 / 1112 ~370.819 ms, flushGL 0 / 1 ~0.379 ms, waitGL 0 / 36 ~12.319 ms, finishGL 79 / 868 ~289.378 ms
+XXX[4] TO 17 ms, lFrame0 1 ms, lFrameX 85 / 1197 ~299.411 ms, flushGL 0 / 1 ~0.285 ms, waitGL 2 / 39 ~9.817 ms, finishGL 81 / 949 ~237.342 ms
+XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1279 ~255.977 ms, flushGL 0 / 1 ~0.229 ms, waitGL 1 / 40 ~8.166 ms, finishGL 79 / 1029 ~205.818 ms
+XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 1362 ~227.166 ms, flushGL 0 / 1 ~0.191 ms, waitGL 1 / 42 ~7.095 ms, finishGL 80 / 1109 ~184.917 ms
+XXX[7] TO 17 ms, lFrame0 1 ms, lFrameX 81 / 1444 ~206.414 ms, flushGL 0 / 1 ~0.165 ms, waitGL 1 / 44 ~6.362 ms, finishGL 78 / 1187 ~169.699 ms
+XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 1527 ~190.994 ms, flushGL 0 / 1 ~0.145 ms, waitGL 3 / 48 ~6.0 ms, finishGL 79 / 1266 ~158.37 ms
+XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 1626 ~180.729 ms, flushGL 0 / 1 ~0.131 ms, waitGL 3 / 51 ~5.692 ms, finishGL 94 / 1361 ~151.302 ms
+XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 1709 ~170.991 ms, flushGL 0 / 1 ~0.118 ms, waitGL 4 / 56 ~5.623 ms, finishGL 77 / 1439 ~143.949 ms
+XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 78 / 1788 ~162.557 ms, flushGL 0 / 1 ~0.108 ms, waitGL 4 / 60 ~5.514 ms, finishGL 72 / 1512 ~137.495 ms
+XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 1892 ~157.681 ms, flushGL 0 / 1 ~0.099 ms, waitGL 8 / 69 ~5.801 ms, finishGL 94 / 1606 ~133.9 ms
+XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1974 ~151.887 ms, flushGL 0 / 1 ~0.092 ms, waitGL 5 / 74 ~5.764 ms, finishGL 76 / 1683 ~129.467 ms
+XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 2051 ~146.508 ms, flushGL 0 / 1 ~0.086 ms, waitGL 6 / 80 ~5.784 ms, finishGL 69 / 1752 ~125.199 ms
+XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 2155 ~143.713 ms, flushGL 0 / 1 ~0.08 ms, waitGL 11 / 92 ~6.191 ms, finishGL 91 / 1844 ~122.975 ms
+XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2238 ~139.928 ms, flushGL 0 / 1 ~0.076 ms, waitGL 8 / 101 ~6.326 ms, finishGL 74 / 1918 ~119.93 ms
+XXX[17] TO 17 ms, lFrame0 1 ms, lFrameX 75 / 2314 ~136.122 ms, flushGL 0 / 1 ~0.071 ms, waitGL 7 / 108 ~6.397 ms, finishGL 66 / 1985 ~116.79 ms
+XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2421 ~134.528 ms, flushGL 0 / 1 ~0.068 ms, waitGL 14 / 123 ~6.866 ms, finishGL 91 / 2077 ~115.4 ms
+XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2504 ~131.823 ms, flushGL 0 / 1 ~0.064 ms, waitGL 8 / 132 ~6.949 ms, finishGL 74 / 2151 ~113.231 ms
+XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2580 ~129.009 ms, flushGL 0 / 1 ~0.061 ms, waitGL 7 / 139 ~6.994 ms, finishGL 66 / 2218 ~110.919 ms
+XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2687 ~127.962 ms, flushGL 0 / 1 ~0.058 ms, waitGL 14 / 154 ~7.365 ms, finishGL 91 / 2310 ~110.007 ms
+XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2770 ~125.93 ms, flushGL 0 / 1 ~0.056 ms, waitGL 8 / 163 ~7.414 ms, finishGL 74 / 2384 ~108.382 ms
+XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 2845 ~123.71 ms, flushGL 0 / 1 ~0.054 ms, waitGL 8 / 171 ~7.442 ms, finishGL 66 / 2450 ~106.547 ms
+XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 2951 ~122.963 ms, flushGL 0 / 1 ~0.051 ms, waitGL 15 / 186 ~7.773 ms, finishGL 89 / 2540 ~105.845 ms
+XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 3031 ~121.259 ms, flushGL 0 / 1 ~0.05 ms, waitGL 10 / 197 ~7.885 ms, finishGL 69 / 2609 ~104.382 ms
+XXX[26] TO 17 ms, lFrame0 1 ms, lFrameX 70 / 3101 ~119.303 ms, flushGL 0 / 1 ~0.048 ms, waitGL 12 / 209 ~8.07 ms, finishGL 56 / 2666 ~102.545 ms
+XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 3196 ~118.373 ms, flushGL 0 / 1 ~0.046 ms, waitGL 8 / 218 ~8.075 ms, finishGL 85 / 2751 ~101.909 ms
+XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3278 ~117.099 ms, flushGL 0 / 1 ~0.045 ms, waitGL 13 / 231 ~8.283 ms, finishGL 67 / 2819 ~100.691 ms
+XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3346 ~115.386 ms, flushGL 0 / 1 ~0.043 ms, waitGL 14 / 246 ~8.511 ms, finishGL 51 / 2871 ~99.0 ms
+XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 3443 ~114.777 ms, flushGL 0 / 1 ~0.042 ms, waitGL 13 / 260 ~8.668 ms, finishGL 83 / 2954 ~98.477 ms
+XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 3525 ~113.715 ms, flushGL 0 / 1 ~0.041 ms, waitGL 16 / 276 ~8.926 ms, finishGL 64 / 3019 ~97.389 ms
+XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3589 ~112.176 ms, flushGL 0 / 1 ~0.041 ms, waitGL 1 / 278 ~8.689 ms, finishGL 62 / 3081 ~96.295 ms
+XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3673 ~111.319 ms, flushGL 0 / 1 ~0.04 ms, waitGL 2 / 280 ~8.499 ms, finishGL 80 / 3162 ~95.828 ms
+XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3739 ~109.987 ms, flushGL 0 / 1 ~0.039 ms, waitGL 1 / 282 ~8.304 ms, finishGL 63 / 3225 ~94.878 ms
+XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 3802 ~108.655 ms, flushGL 0 / 1 ~0.038 ms, waitGL 2 / 284 ~8.131 ms, finishGL 60 / 3286 ~93.897 ms
+XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 3888 ~108.004 ms, flushGL 0 / 1 ~0.037 ms, waitGL 5 / 289 ~8.052 ms, finishGL 79 / 3365 ~93.496 ms
+XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3955 ~106.916 ms, flushGL 0 / 1 ~0.036 ms, waitGL 3 / 293 ~7.931 ms, finishGL 63 / 3429 ~92.691 ms
+XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 4018 ~105.762 ms, flushGL 0 / 1 ~0.035 ms, waitGL 2 / 296 ~7.795 ms, finishGL 59 / 3489 ~91.822 ms
+XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 4104 ~105.241 ms, flushGL 0 / 1 ~0.034 ms, waitGL 5 / 301 ~7.731 ms, finishGL 79 / 3568 ~91.509 ms
+XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4170 ~104.255 ms, flushGL 0 / 1 ~0.033 ms, waitGL 3 / 304 ~7.622 ms, finishGL 61 / 3630 ~90.771 ms
+XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 4230 ~103.185 ms, flushGL 0 / 1 ~0.033 ms, waitGL 4 / 308 ~7.535 ms, finishGL 55 / 3686 ~89.918 ms
+XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 4318 ~102.829 ms, flushGL 0 / 1 ~0.032 ms, waitGL 9 / 318 ~7.588 ms, finishGL 78 / 3764 ~89.635 ms
+XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4385 ~101.979 ms, flushGL 0 / 1 ~0.031 ms, waitGL 5 / 323 ~7.534 ms, finishGL 60 / 3825 ~88.959 ms
+XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 4444 ~101.014 ms, flushGL 0 / 1 ~0.031 ms, waitGL 5 / 329 ~7.486 ms, finishGL 53 / 3879 ~88.159 ms
+XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 4534 ~100.772 ms, flushGL 0 / 1 ~0.03 ms, waitGL 11 / 340 ~7.577 ms, finishGL 78 / 3957 ~87.933 ms
+XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4600 ~100.017 ms, flushGL 0 / 1 ~0.029 ms, waitGL 5 / 346 ~7.526 ms, finishGL 60 / 4017 ~87.333 ms
+XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 4661 ~99.171 ms, flushGL 0 / 1 ~0.029 ms, waitGL 5 / 351 ~7.484 ms, finishGL 53 / 4071 ~86.623 ms
+XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 4750 ~98.961 ms, flushGL 0 / 1 ~0.028 ms, waitGL 11 / 363 ~7.565 ms, finishGL 77 / 4148 ~86.428 ms
+XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4816 ~98.297 ms, flushGL 0 / 1 ~0.028 ms, waitGL 6 / 369 ~7.534 ms, finishGL 59 / 4208 ~85.887 ms
+XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 4876 ~97.524 ms, flushGL 0 / 1 ~0.027 ms, waitGL 5 / 375 ~7.502 ms, finishGL 53 / 4261 ~85.231 ms
+XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 4965 ~97.36 ms, flushGL 0 / 1 ~0.027 ms, waitGL 12 / 387 ~7.595 ms, finishGL 76 / 4338 ~85.059 ms
+XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5032 ~96.78 ms, flushGL 0 / 1 ~0.026 ms, waitGL 7 / 394 ~7.586 ms, finishGL 59 / 4397 ~84.57 ms
+XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 5091 ~96.069 ms, flushGL 0 / 1 ~0.026 ms, waitGL 5 / 400 ~7.554 ms, finishGL 52 / 4450 ~83.966 ms
+XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 5182 ~95.967 ms, flushGL 0 / 1 ~0.025 ms, waitGL 12 / 413 ~7.649 ms, finishGL 77 / 4527 ~83.843 ms
+XXX[55] TO 17 ms, lFrame0 1 ms, lFrameX 65 / 5247 ~95.414 ms, flushGL 0 / 1 ~0.025 ms, waitGL 6 / 419 ~7.626 ms, finishGL 58 / 4585 ~83.374 ms
+XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 58 / 5306 ~94.761 ms, flushGL 0 / 1 ~0.025 ms, waitGL 6 / 426 ~7.609 ms, finishGL 51 / 4637 ~82.806 ms
+XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 5396 ~94.675 ms, flushGL 0 / 1 ~0.024 ms, waitGL 13 / 439 ~7.717 ms, finishGL 75 / 4712 ~82.679 ms
+XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5463 ~94.203 ms, flushGL 0 / 1 ~0.024 ms, waitGL 8 / 447 ~7.722 ms, finishGL 58 / 4771 ~82.269 ms
+XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 5523 ~93.626 ms, flushGL 0 / 1 ~0.023 ms, waitGL 6 / 454 ~7.709 ms, finishGL 52 / 4824 ~81.765 ms
+XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 5613 ~93.551 ms, flushGL 0 / 1 ~0.023 ms, waitGL 12 / 467 ~7.785 ms, finishGL 76 / 4900 ~81.672 ms
+XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5679 ~93.106 ms, flushGL 0 / 1 ~0.023 ms, waitGL 7 / 474 ~7.773 ms, finishGL 58 / 4959 ~81.297 ms
+XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 5739 ~92.578 ms, flushGL 0 / 1 ~0.022 ms, waitGL 6 / 480 ~7.757 ms, finishGL 52 / 5011 ~80.836 ms
+XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 5813 ~92.276 ms, flushGL 0 / 1 ~0.022 ms, waitGL 12 / 493 ~7.833 ms, finishGL 60 / 5072 ~80.515 ms
+XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5880 ~91.883 ms, flushGL 0 / 1 ~0.022 ms, waitGL 5 / 499 ~7.8 ms, finishGL 60 / 5133 ~80.208 ms
+XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5947 ~91.498 ms, flushGL 0 / 1 ~0.022 ms, waitGL 5 / 504 ~7.759 ms, finishGL 61 / 5194 ~79.917 ms
+XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6013 ~91.121 ms, flushGL 0 / 1 ~0.021 ms, waitGL 4 / 508 ~7.711 ms, finishGL 61 / 5256 ~79.638 ms
+XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6080 ~90.758 ms, flushGL 0 / 1 ~0.021 ms, waitGL 4 / 513 ~7.666 ms, finishGL 61 / 5317 ~79.37 ms
+XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6148 ~90.413 ms, flushGL 0 / 1 ~0.021 ms, waitGL 4 / 517 ~7.617 ms, finishGL 62 / 5380 ~79.122 ms
+XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6214 ~90.065 ms, flushGL 0 / 1 ~0.021 ms, waitGL 3 / 521 ~7.552 ms, finishGL 62 / 5443 ~78.886 ms
+XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6280 ~89.725 ms, flushGL 0 / 1 ~0.02 ms, waitGL 3 / 524 ~7.492 ms, finishGL 62 / 5505 ~78.649 ms
+XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6347 ~89.396 ms, flushGL 0 / 1 ~0.02 ms, waitGL 3 / 528 ~7.439 ms, finishGL 62 / 5567 ~78.417 ms
+XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6413 ~89.073 ms, flushGL 0 / 1 ~0.02 ms, waitGL 3 / 531 ~7.385 ms, finishGL 62 / 5629 ~78.19 ms
+XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6479 ~88.753 ms, flushGL 0 / 1 ~0.02 ms, waitGL 4 / 536 ~7.343 ms, finishGL 60 / 5690 ~77.954 ms
+XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6544 ~88.442 ms, flushGL 0 / 1 ~0.019 ms, waitGL 4 / 540 ~7.307 ms, finishGL 60 / 5751 ~77.719 ms
+XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6611 ~88.153 ms, flushGL 0 / 1 ~0.019 ms, waitGL 6 / 547 ~7.294 ms, finishGL 59 / 5811 ~77.483 ms
+XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6677 ~87.867 ms, flushGL 0 / 1 ~0.019 ms, waitGL 5 / 552 ~7.265 ms, finishGL 60 / 5872 ~77.264 ms
+XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6744 ~87.595 ms, flushGL 0 / 1 ~0.019 ms, waitGL 5 / 557 ~7.24 ms, finishGL 61 / 5933 ~77.055 ms
+XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6812 ~87.341 ms, flushGL 0 / 1 ~0.018 ms, waitGL 5 / 562 ~7.217 ms, finishGL 61 / 5994 ~76.857 ms
+XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6879 ~87.081 ms, flushGL 0 / 1 ~0.018 ms, waitGL 3 / 566 ~7.169 ms, finishGL 62 / 6057 ~76.68 ms
+XXX[80] TO 17 ms, lFrame0 4 ms, lFrameX 66 / 6945 ~86.819 ms, flushGL 0 / 1 ~0.018 ms, waitGL 16 / 582 ~7.283 ms, finishGL 44 / 6102 ~76.282 ms
+XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7012 ~86.575 ms, flushGL 0 / 1 ~0.018 ms, waitGL 3 / 586 ~7.239 ms, finishGL 62 / 6165 ~76.118 ms
+XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7078 ~86.325 ms, flushGL 0 / 1 ~0.018 ms, waitGL 3 / 589 ~7.188 ms, finishGL 62 / 6228 ~75.952 ms
+XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7145 ~86.089 ms, flushGL 0 / 1 ~0.018 ms, waitGL 3 / 593 ~7.145 ms, finishGL 62 / 6290 ~75.792 ms
+XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7212 ~85.859 ms, flushGL 0 / 1 ~0.017 ms, waitGL 3 / 596 ~7.1 ms, finishGL 62 / 6353 ~75.638 ms
+XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7279 ~85.637 ms, flushGL 0 / 1 ~0.017 ms, waitGL 2 / 599 ~7.052 ms, finishGL 63 / 6417 ~75.496 ms
+XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7345 ~85.409 ms, flushGL 0 / 1 ~0.017 ms, waitGL 2 / 602 ~7.002 ms, finishGL 62 / 6480 ~75.349 ms
+XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7411 ~85.188 ms, flushGL 0 / 1 ~0.017 ms, waitGL 3 / 605 ~6.958 ms, finishGL 62 / 6542 ~75.202 ms
+XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7477 ~84.976 ms, flushGL 0 / 1 ~0.017 ms, waitGL 3 / 608 ~6.917 ms, finishGL 62 / 6605 ~75.059 ms
+XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7544 ~84.766 ms, flushGL 0 / 1 ~0.017 ms, waitGL 3 / 611 ~6.873 ms, finishGL 62 / 6668 ~74.922 ms
+XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7610 ~84.566 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 615 ~6.835 ms, finishGL 62 / 6730 ~74.788 ms
+XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7676 ~84.361 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 618 ~6.796 ms, finishGL 62 / 6793 ~74.649 ms
+XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7743 ~84.166 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 621 ~6.759 ms, finishGL 62 / 6855 ~74.518 ms
+XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7810 ~83.979 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 625 ~6.728 ms, finishGL 62 / 6918 ~74.388 ms
+XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7876 ~83.792 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 629 ~6.693 ms, finishGL 62 / 6980 ~74.261 ms
+XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7942 ~83.603 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 632 ~6.657 ms, finishGL 62 / 7042 ~74.133 ms
+XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8008 ~83.42 ms, flushGL 0 / 1 ~0.016 ms, waitGL 4 / 636 ~6.631 ms, finishGL 61 / 7104 ~74.0 ms
+XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8074 ~83.245 ms, flushGL 0 / 1 ~0.015 ms, waitGL 4 / 641 ~6.609 ms, finishGL 61 / 7165 ~73.871 ms
+XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8140 ~83.07 ms, flushGL 0 / 1 ~0.015 ms, waitGL 4 / 645 ~6.588 ms, finishGL 61 / 7226 ~73.741 ms
+XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8207 ~82.9 ms, flushGL 0 / 1 ~0.015 ms, waitGL 4 / 650 ~6.57 ms, finishGL 60 / 7287 ~73.612 ms
+XXX[1] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 66 ~66.068 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 5 ~5.429 ms, finishGL 60 / 60 ~60.167 ms
+XXX[2] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 132 ~66.192 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 10 ~5.453 ms, finishGL 60 / 120 ~60.277 ms
+XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 198 ~66.248 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 16 ~5.506 ms, finishGL 60 / 180 ~60.269 ms
+XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 264 ~66.104 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 22 ~5.581 ms, finishGL 59 / 240 ~60.061 ms
+XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 330 ~66.144 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 6 / 28 ~5.786 ms, finishGL 59 / 299 ~59.896 ms
+XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 397 ~66.292 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 6 / 35 ~5.943 ms, finishGL 59 / 359 ~59.883 ms
+XXX[7] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 464 ~66.376 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 6 / 41 ~5.974 ms, finishGL 60 / 419 ~59.933 ms
+XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 531 ~66.462 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 47 ~5.941 ms, finishGL 60 / 480 ~60.052 ms
+XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 599 ~66.638 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 53 ~5.912 ms, finishGL 61 / 542 ~60.257 ms
+XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 665 ~66.544 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 3 / 56 ~5.684 ms, finishGL 61 / 603 ~60.392 ms
+XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 731 ~66.491 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 4 / 61 ~5.563 ms, finishGL 61 / 665 ~60.459 ms
+XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 797 ~66.436 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 4 / 66 ~5.511 ms, finishGL 60 / 725 ~60.457 ms
+XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 863 ~66.445 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 71 ~5.515 ms, finishGL 60 / 786 ~60.463 ms
+XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 929 ~66.392 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 77 ~5.523 ms, finishGL 59 / 845 ~60.402 ms
+XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 996 ~66.401 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 6 / 83 ~5.572 ms, finishGL 59 / 905 ~60.36 ms
+XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1062 ~66.427 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 6 / 90 ~5.64 ms, finishGL 59 / 965 ~60.319 ms
+XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1130 ~66.474 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 96 ~5.66 ms, finishGL 60 / 1025 ~60.347 ms
+XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1196 ~66.479 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 101 ~5.642 ms, finishGL 60 / 1086 ~60.369 ms
+XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1263 ~66.504 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 106 ~5.618 ms, finishGL 61 / 1147 ~60.418 ms
+FrameCount: 120 - FrameRate: 15.0
+XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1330 ~66.516 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 4 / 111 ~5.581 ms, finishGL 61 / 1209 ~60.461 ms
+XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1397 ~66.566 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 115 ~5.523 ms, finishGL 62 / 1271 ~60.569 ms
+XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1464 ~66.586 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 119 ~5.418 ms, finishGL 63 / 1335 ~60.694 ms
+XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1531 ~66.586 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 122 ~5.318 ms, finishGL 63 / 1398 ~60.795 ms
+XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1598 ~66.601 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 125 ~5.226 ms, finishGL 63 / 1461 ~60.903 ms
+XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1665 ~66.609 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 128 ~5.14 ms, finishGL 63 / 1524 ~60.998 ms
+XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1731 ~66.586 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 130 ~5.009 ms, finishGL 63 / 1588 ~61.105 ms
+XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1798 ~66.602 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 132 ~4.92 ms, finishGL 63 / 1652 ~61.21 ms
+XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1864 ~66.603 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 135 ~4.839 ms, finishGL 63 / 1716 ~61.292 ms
+XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1930 ~66.575 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 137 ~4.738 ms, finishGL 63 / 1779 ~61.365 ms
+XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1997 ~66.575 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 139 ~4.666 ms, finishGL 63 / 1843 ~61.438 ms
+XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2063 ~66.569 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 142 ~4.596 ms, finishGL 63 / 1906 ~61.502 ms
+XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2129 ~66.557 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 144 ~4.531 ms, finishGL 63 / 1969 ~61.556 ms
+XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2197 ~66.575 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 147 ~4.479 ms, finishGL 63 / 2033 ~61.626 ms
+XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2263 ~66.574 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 150 ~4.414 ms, finishGL 63 / 2097 ~61.689 ms
+XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2329 ~66.556 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 152 ~4.352 ms, finishGL 63 / 2160 ~61.734 ms
+XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2396 ~66.559 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 155 ~4.306 ms, finishGL 63 / 2224 ~61.783 ms
+XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2462 ~66.558 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 157 ~4.257 ms, finishGL 63 / 2287 ~61.831 ms
+XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2528 ~66.548 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 160 ~4.223 ms, finishGL 62 / 2350 ~61.856 ms
+XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2595 ~66.55 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 162 ~4.178 ms, finishGL 63 / 2414 ~61.903 ms
+XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2662 ~66.55 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 165 ~4.142 ms, finishGL 63 / 2477 ~61.939 ms
+XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2728 ~66.548 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 168 ~4.116 ms, finishGL 62 / 2540 ~61.962 ms
+XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2794 ~66.536 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 171 ~4.077 ms, finishGL 63 / 2603 ~61.987 ms
+XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2860 ~66.521 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 173 ~4.044 ms, finishGL 62 / 2666 ~62.005 ms
+XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2925 ~66.49 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 177 ~4.027 ms, finishGL 61 / 2727 ~61.987 ms
+XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 2990 ~66.456 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 181 ~4.043 ms, finishGL 59 / 2787 ~61.933 ms
+XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3054 ~66.404 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 188 ~4.094 ms, finishGL 57 / 2844 ~61.83 ms
+XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 3117 ~66.333 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 196 ~4.189 ms, finishGL 54 / 2898 ~61.665 ms
+XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 3180 ~66.252 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 208 ~4.349 ms, finishGL 50 / 2948 ~61.424 ms
+XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 3242 ~66.165 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 224 ~4.587 ms, finishGL 45 / 2993 ~61.099 ms
+XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3290 ~65.805 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 228 ~4.571 ms, finishGL 43 / 3037 ~60.756 ms
+XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3339 ~65.474 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 234 ~4.595 ms, finishGL 42 / 3080 ~60.401 ms
+XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3388 ~65.155 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 240 ~4.634 ms, finishGL 41 / 3122 ~60.044 ms
+XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3437 ~64.853 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 248 ~4.682 ms, finishGL 41 / 3163 ~59.693 ms
+XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3486 ~64.56 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 256 ~4.745 ms, finishGL 40 / 3204 ~59.336 ms
+XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3535 ~64.285 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 264 ~4.816 ms, finishGL 40 / 3244 ~58.991 ms
+XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3585 ~64.022 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 273 ~4.891 ms, finishGL 40 / 3284 ~58.653 ms
+XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3634 ~63.762 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 283 ~4.966 ms, finishGL 39 / 3324 ~58.317 ms
+XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3683 ~63.514 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 292 ~5.051 ms, finishGL 39 / 3363 ~57.986 ms
+XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3733 ~63.271 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 303 ~5.139 ms, finishGL 38 / 3401 ~57.654 ms
+XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3782 ~63.034 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 314 ~5.236 ms, finishGL 37 / 3439 ~57.32 ms
+XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3831 ~62.805 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 325 ~5.341 ms, finishGL 36 / 3476 ~56.986 ms
+XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3879 ~62.576 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 338 ~5.456 ms, finishGL 35 / 3511 ~56.642 ms
+XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3928 ~62.356 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 351 ~5.585 ms, finishGL 34 / 3546 ~56.294 ms
+XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3977 ~62.142 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 366 ~5.727 ms, finishGL 33 / 3580 ~55.938 ms
+XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4025 ~61.937 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 382 ~5.881 ms, finishGL 32 / 3612 ~55.579 ms
+XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4074 ~61.731 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 382 ~5.794 ms, finishGL 47 / 3660 ~55.461 ms
+XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 30 / 4104 ~61.265 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 384 ~5.736 ms, finishGL 27 / 3688 ~55.045 ms
+XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4155 ~61.106 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 388 ~5.711 ms, finishGL 45 / 3733 ~54.911 ms
+XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4187 ~60.689 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 392 ~5.684 ms, finishGL 28 / 3761 ~54.521 ms
+XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 28 / 4216 ~60.231 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 397 ~5.677 ms, finishGL 22 / 3784 ~54.069 ms
+XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 4269 ~60.13 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 406 ~5.721 ms, finishGL 43 / 3828 ~53.925 ms
+XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4301 ~59.745 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 412 ~5.727 ms, finishGL 25 / 3854 ~53.535 ms
+XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 25 / 4327 ~59.278 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 418 ~5.739 ms, finishGL 18 / 3872 ~53.052 ms
+XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 39 / 4366 ~59.011 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 432 ~5.845 ms, finishGL 25 / 3898 ~52.678 ms
+XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4415 ~58.868 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 439 ~5.862 ms, finishGL 40 / 3938 ~52.519 ms
+XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4447 ~58.52 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 449 ~5.913 ms, finishGL 22 / 3961 ~52.12 ms
+XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4471 ~58.069 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 459 ~5.968 ms, finishGL 12 / 3974 ~51.61 ms
+XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 42 / 4513 ~57.866 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 462 ~5.932 ms, finishGL 38 / 4012 ~51.443 ms
+XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4547 ~57.557 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 473 ~5.991 ms, finishGL 22 / 4034 ~51.074 ms
+XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4570 ~57.135 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 483 ~6.039 ms, finishGL 13 / 4047 ~50.599 ms
+XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 42 / 4613 ~56.951 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 485 ~5.999 ms, finishGL 38 / 4086 ~50.453 ms
+XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4646 ~56.659 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 496 ~6.053 ms, finishGL 22 / 4108 ~50.107 ms
+XXX[83] TO 17 ms, lFrame0 1 ms, lFrameX 25 / 4671 ~56.288 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 505 ~6.094 ms, finishGL 15 / 4123 ~49.685 ms
+XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 46 / 4718 ~56.169 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 505 ~6.023 ms, finishGL 45 / 4169 ~49.637 ms
+XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 38 / 4756 ~55.957 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 510 ~6.002 ms, finishGL 33 / 4203 ~49.447 ms
+XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 36 / 4793 ~55.733 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 525 ~6.11 ms, finishGL 20 / 4223 ~49.114 ms
+XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 4862 ~55.889 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 537 ~6.174 ms, finishGL 57 / 4280 ~49.206 ms
+XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 4914 ~55.849 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 547 ~6.218 ms, finishGL 41 / 4322 ~49.122 ms
+XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 42 / 4957 ~55.703 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 554 ~6.226 ms, finishGL 35 / 4358 ~48.967 ms
+XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 5031 ~55.911 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 567 ~6.304 ms, finishGL 60 / 4418 ~49.096 ms
+XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5082 ~55.846 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 573 ~6.297 ms, finishGL 43 / 4462 ~49.039 ms
+XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 5125 ~55.711 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 578 ~6.289 ms, finishGL 37 / 4499 ~48.91 ms
+XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5198 ~55.892 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 590 ~6.344 ms, finishGL 60 / 4560 ~49.036 ms
+XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5248 ~55.834 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 596 ~6.343 ms, finishGL 43 / 4604 ~48.979 ms
+XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 44 / 5292 ~55.709 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 601 ~6.327 ms, finishGL 38 / 4642 ~48.87 ms
+XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5365 ~55.885 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 611 ~6.371 ms, finishGL 61 / 4704 ~49.002 ms
+XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5415 ~55.831 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 617 ~6.36 ms, finishGL 44 / 4749 ~48.959 ms
+XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 44 / 5460 ~55.717 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 620 ~6.335 ms, finishGL 40 / 4789 ~48.869 ms
+XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5532 ~55.886 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 629 ~6.358 ms, finishGL 63 / 4852 ~49.014 ms
+XXX[100] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 5584 ~55.843 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 632 ~6.327 ms, finishGL 47 / 4900 ~49.001 ms
+XXX[101] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 5632 ~55.771 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 634 ~6.282 ms, finishGL 46 / 4946 ~48.973 ms
+XXX[102] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 5702 ~55.909 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 636 ~6.244 ms, finishGL 66 / 5013 ~49.147 ms
+XXX[103] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5770 ~56.024 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 653 ~6.344 ms, finishGL 50 / 5063 ~49.161 ms
+XXX[104] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 5823 ~55.992 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 668 ~6.428 ms, finishGL 36 / 5100 ~49.043 ms
+XXX[105] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 5906 ~56.252 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 679 ~6.472 ms, finishGL 71 / 5171 ~49.256 ms
+XXX[106] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 5977 ~56.391 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 691 ~6.527 ms, finishGL 58 / 5230 ~49.341 ms
+XXX[107] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 6038 ~56.436 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 699 ~6.533 ms, finishGL 53 / 5283 ~49.381 ms
+XXX[108] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 6114 ~56.613 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 710 ~6.582 ms, finishGL 63 / 5346 ~49.508 ms
+XXX[109] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6181 ~56.713 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 713 ~6.549 ms, finishGL 64 / 5410 ~49.641 ms
+XXX[110] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6248 ~56.803 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 715 ~6.507 ms, finishGL 64 / 5475 ~49.774 ms
+XXX[111] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6314 ~56.885 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 717 ~6.464 ms, finishGL 63 / 5538 ~49.9 ms
+XXX[112] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6381 ~56.976 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 719 ~6.427 ms, finishGL 64 / 5603 ~50.028 ms
+XXX[113] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6448 ~57.067 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 721 ~6.386 ms, finishGL 65 / 5668 ~50.161 ms
+XXX[114] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6514 ~57.146 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 722 ~6.341 ms, finishGL 64 / 5732 ~50.285 ms
+XXX[115] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6582 ~57.239 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 724 ~6.298 ms, finishGL 66 / 5798 ~50.422 ms
+XXX[116] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 6667 ~57.476 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 740 ~6.387 ms, finishGL 67 / 5866 ~50.57 ms
+XXX[117] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 6749 ~57.69 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 756 ~6.462 ms, finishGL 66 / 5933 ~50.71 ms
+XXX[118] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6833 ~57.911 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 771 ~6.54 ms, finishGL 67 / 6000 ~50.852 ms
+XXX[119] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 6917 ~58.13 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 786 ~6.613 ms, finishGL 68 / 6069 ~51.0 ms
+XXX[120] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7001 ~58.341 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 801 ~6.677 ms, finishGL 68 / 6137 ~51.147 ms
+XXX[121] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7084 ~58.552 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 815 ~6.738 ms, finishGL 69 / 6206 ~51.297 ms
+XXX[122] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 7170 ~58.774 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 828 ~6.792 ms, finishGL 71 / 6278 ~51.465 ms
+XXX[123] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 7255 ~58.988 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 839 ~6.825 ms, finishGL 73 / 6352 ~51.647 ms
+XXX[124] TO 17 ms, lFrame0 1 ms, lFrameX 75 / 7331 ~59.122 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 847 ~6.832 ms, finishGL 66 / 6418 ~51.763 ms
+XXX[125] TO 17 ms, lFrame0 0 ms, lFrameX 93 / 7424 ~59.396 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 864 ~6.912 ms, finishGL 76 / 6494 ~51.958 ms
+XXX[126] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7508 ~59.588 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 870 ~6.907 ms, finishGL 76 / 6571 ~52.154 ms
+XXX[127] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7591 ~59.773 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 876 ~6.9 ms, finishGL 76 / 6648 ~52.347 ms
+2013-06-17 02:51:40.860 java[62528:5f07] Persistent UI failed to open file file://localhost/Users/jogamp/Library/Saved%20Application%20State/com.apple.javajdk16.cmd.savedState/window_1.data: Operation not permitted (1)
+XXX[128] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 7671 ~59.93 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 882 ~6.892 ms, finishGL 73 / 6721 ~52.512 ms
+XXX[129] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 7751 ~60.091 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 891 ~6.911 ms, finishGL 70 / 6792 ~52.655 ms
+XXX[130] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7834 ~60.261 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 903 ~6.948 ms, finishGL 70 / 6862 ~52.788 ms
+XXX[131] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7915 ~60.424 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 916 ~6.993 ms, finishGL 68 / 6930 ~52.907 ms
+XXX[132] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7997 ~60.583 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 930 ~7.048 ms, finishGL 66 / 6997 ~53.011 ms
+XXX[133] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8079 ~60.751 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 946 ~7.116 ms, finishGL 66 / 7063 ~53.112 ms
+XXX[134] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8162 ~60.912 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 963 ~7.187 ms, finishGL 65 / 7129 ~53.202 ms
+XXX[135] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8245 ~61.075 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 963 ~7.137 ms, finishGL 82 / 7211 ~53.415 ms
+XXX[136] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8328 ~61.236 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 965 ~7.096 ms, finishGL 80 / 7292 ~53.618 ms
+XXX[137] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8393 ~61.266 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 966 ~7.051 ms, finishGL 63 / 7355 ~53.693 ms
+XXX[138] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 8460 ~61.31 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 968 ~7.015 ms, finishGL 64 / 7420 ~53.774 ms
+XXX[139] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8526 ~61.345 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 969 ~6.972 ms, finishGL 64 / 7485 ~53.851 ms
+FrameCount: 240 - FrameRate: 13.0
+XXX[140] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8593 ~61.38 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 970 ~6.932 ms, finishGL 64 / 7549 ~53.926 ms
+XXX[141] TO 17 ms, lFrame0 4 ms, lFrameX 69 / 8662 ~61.435 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 985 ~6.989 ms, finishGL 49 / 7599 ~53.894 ms
+XXX[142] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 8742 ~61.566 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1001 ~7.05 ms, finishGL 63 / 7663 ~53.965 ms
+XXX[143] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8808 ~61.599 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1003 ~7.015 ms, finishGL 63 / 7726 ~54.032 ms
+XXX[144] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8874 ~61.628 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1005 ~6.983 ms, finishGL 62 / 7789 ~54.094 ms
+XXX[145] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8940 ~61.659 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1008 ~6.955 ms, finishGL 62 / 7852 ~54.153 ms
+XXX[146] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9006 ~61.69 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1011 ~6.931 ms, finishGL 62 / 7914 ~54.209 ms
+XXX[147] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9073 ~61.726 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1015 ~6.909 ms, finishGL 62 / 7977 ~54.267 ms
+XXX[148] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9139 ~61.755 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1019 ~6.89 ms, finishGL 61 / 8038 ~54.316 ms
+XXX[149] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9206 ~61.787 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1024 ~6.874 ms, finishGL 61 / 8100 ~54.364 ms
+XXX[150] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9272 ~61.818 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1027 ~6.852 ms, finishGL 62 / 8162 ~54.416 ms
+XXX[151] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9339 ~61.85 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1031 ~6.831 ms, finishGL 62 / 8225 ~54.47 ms
+XXX[152] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9405 ~61.878 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1035 ~6.81 ms, finishGL 62 / 8287 ~54.52 ms
+XXX[153] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9472 ~61.912 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1039 ~6.791 ms, finishGL 62 / 8349 ~54.573 ms
+XXX[154] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9538 ~61.939 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1042 ~6.769 ms, finishGL 62 / 8412 ~54.623 ms
+XXX[155] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9606 ~61.974 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1046 ~6.748 ms, finishGL 63 / 8475 ~54.679 ms
+XXX[156] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9672 ~62.0 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1048 ~6.723 ms, finishGL 62 / 8538 ~54.731 ms
+XXX[157] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9738 ~62.028 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1052 ~6.701 ms, finishGL 62 / 8600 ~54.782 ms
+XXX[158] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9804 ~62.054 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1055 ~6.679 ms, finishGL 62 / 8663 ~54.83 ms
+XXX[159] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9870 ~62.08 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1058 ~6.66 ms, finishGL 62 / 8725 ~54.875 ms
+XXX[160] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9936 ~62.103 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1062 ~6.643 ms, finishGL 61 / 8786 ~54.915 ms
+XXX[161] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10002 ~62.127 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1067 ~6.63 ms, finishGL 60 / 8847 ~54.952 ms
+XXX[162] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10068 ~62.152 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1072 ~6.622 ms, finishGL 60 / 8907 ~54.985 ms
+XXX[163] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10135 ~62.178 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1078 ~6.616 ms, finishGL 60 / 8968 ~55.018 ms
+XXX[164] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10200 ~62.2 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1084 ~6.61 ms, finishGL 59 / 9027 ~55.047 ms
+XXX[165] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10267 ~62.228 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1090 ~6.61 ms, finishGL 59 / 9087 ~55.076 ms
+XXX[166] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10334 ~62.253 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1096 ~6.606 ms, finishGL 59 / 9147 ~55.105 ms
+XXX[167] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 10402 ~62.287 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1102 ~6.603 ms, finishGL 61 / 9208 ~55.143 ms
+XXX[168] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 10467 ~62.303 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1106 ~6.588 ms, finishGL 60 / 9268 ~55.172 ms
+XXX[169] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10534 ~62.331 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1112 ~6.584 ms, finishGL 60 / 9329 ~55.204 ms
+XXX[170] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10600 ~62.354 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1118 ~6.577 ms, finishGL 60 / 9389 ~55.234 ms
+XXX[171] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10667 ~62.382 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1123 ~6.572 ms, finishGL 60 / 9450 ~55.267 ms
+XXX[172] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10734 ~62.408 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1129 ~6.564 ms, finishGL 61 / 9511 ~55.301 ms
+XXX[173] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10801 ~62.435 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1133 ~6.554 ms, finishGL 61 / 9573 ~55.339 ms
+XXX[174] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10867 ~62.455 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1138 ~6.541 ms, finishGL 61 / 9634 ~55.373 ms
+XXX[175] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10934 ~62.48 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1143 ~6.531 ms, finishGL 61 / 9696 ~55.407 ms
+XXX[176] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11000 ~62.501 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1147 ~6.519 ms, finishGL 61 / 9757 ~55.44 ms
+XXX[177] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11067 ~62.529 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1152 ~6.509 ms, finishGL 62 / 9819 ~55.479 ms
+XXX[178] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11135 ~62.559 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1155 ~6.494 ms, finishGL 63 / 9883 ~55.525 ms
+XXX[179] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11203 ~62.588 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1158 ~6.471 ms, finishGL 64 / 9948 ~55.577 ms
+XXX[180] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11270 ~62.613 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1159 ~6.44 ms, finishGL 65 / 10014 ~55.633 ms
+XXX[181] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11354 ~62.732 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1159 ~6.408 ms, finishGL 82 / 10097 ~55.784 ms
+XXX[182] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11438 ~62.849 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1176 ~6.462 ms, finishGL 67 / 10164 ~55.848 ms
+XXX[183] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11523 ~62.97 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1191 ~6.511 ms, finishGL 69 / 10233 ~55.92 ms
+XXX[184] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 11607 ~63.082 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1204 ~6.548 ms, finishGL 69 / 10302 ~55.994 ms
+XXX[185] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 11694 ~63.211 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1218 ~6.583 ms, finishGL 73 / 10376 ~56.088 ms
+XXX[186] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 11780 ~63.334 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 1227 ~6.598 ms, finishGL 76 / 10452 ~56.197 ms
+XXX[187] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11865 ~63.452 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1233 ~6.598 ms, finishGL 78 / 10530 ~56.315 ms
+XXX[188] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11950 ~63.565 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1238 ~6.585 ms, finishGL 80 / 10611 ~56.441 ms
+XXX[189] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12034 ~63.673 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1240 ~6.564 ms, finishGL 80 / 10691 ~56.57 ms
+XXX[190] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12118 ~63.782 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1242 ~6.539 ms, finishGL 82 / 10774 ~56.705 ms
+XXX[191] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12217 ~63.968 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1242 ~6.507 ms, finishGL 98 / 10872 ~56.922 ms
+XXX[192] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12301 ~64.07 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1244 ~6.48 ms, finishGL 81 / 10953 ~57.051 ms
+XXX[193] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12383 ~64.163 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1245 ~6.451 ms, finishGL 80 / 11034 ~57.174 ms
+XXX[194] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12468 ~64.271 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1247 ~6.428 ms, finishGL 82 / 11117 ~57.305 ms
+XXX[195] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 12566 ~64.441 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 17 / 1264 ~6.482 ms, finishGL 80 / 11197 ~57.422 ms
+XXX[196] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 12647 ~64.529 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1266 ~6.461 ms, finishGL 78 / 11276 ~57.531 ms
+XXX[197] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12730 ~64.619 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1270 ~6.446 ms, finishGL 77 / 11354 ~57.634 ms
+XXX[198] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12813 ~64.715 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1274 ~6.438 ms, finishGL 78 / 11432 ~57.738 ms
+XXX[199] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12896 ~64.806 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1279 ~6.428 ms, finishGL 77 / 11510 ~57.84 ms
+XXX[200] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12979 ~64.899 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1284 ~6.42 ms, finishGL 78 / 11588 ~57.942 ms
+XXX[201] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13063 ~64.99 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1288 ~6.411 ms, finishGL 78 / 11666 ~58.043 ms
+XXX[202] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13145 ~65.079 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1293 ~6.401 ms, finishGL 78 / 11744 ~58.141 ms
+XXX[203] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13229 ~65.167 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1297 ~6.392 ms, finishGL 77 / 11822 ~58.239 ms
+XXX[204] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13311 ~65.251 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1302 ~6.384 ms, finishGL 77 / 11899 ~58.331 ms
+XXX[205] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13393 ~65.332 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1308 ~6.381 ms, finishGL 75 / 11975 ~58.416 ms
+XXX[206] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13475 ~65.414 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1315 ~6.384 ms, finishGL 74 / 12050 ~58.495 ms
+XXX[207] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13557 ~65.494 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1323 ~6.392 ms, finishGL 73 / 12123 ~58.567 ms
+XXX[208] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13639 ~65.572 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 1332 ~6.405 ms, finishGL 72 / 12195 ~58.633 ms
+XXX[209] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13720 ~65.647 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 1343 ~6.426 ms, finishGL 69 / 12265 ~58.687 ms
+XXX[210] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13802 ~65.725 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 1355 ~6.455 ms, finishGL 69 / 12334 ~58.736 ms
+XXX[211] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13884 ~65.801 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1369 ~6.489 ms, finishGL 67 / 12402 ~58.779 ms
+XXX[212] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13965 ~65.875 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 1384 ~6.529 ms, finishGL 65 / 12468 ~58.812 ms
+XXX[213] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 14047 ~65.952 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1400 ~6.577 ms, finishGL 65 / 12533 ~58.842 ms
+XXX[214] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 14113 ~65.949 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1401 ~6.55 ms, finishGL 63 / 12597 ~58.866 ms
+XXX[215] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14180 ~65.957 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1403 ~6.529 ms, finishGL 65 / 12662 ~58.896 ms
+XXX[216] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14248 ~65.965 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1404 ~6.503 ms, finishGL 66 / 12729 ~58.93 ms
+XXX[217] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 14333 ~66.05 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1421 ~6.548 ms, finishGL 67 / 12796 ~58.97 ms
+XXX[218] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14418 ~66.142 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1436 ~6.587 ms, finishGL 70 / 12867 ~59.023 ms
+XXX[219] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14504 ~66.23 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 1448 ~6.613 ms, finishGL 72 / 12939 ~59.086 ms
+XXX[220] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14590 ~66.319 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 1458 ~6.628 ms, finishGL 75 / 13015 ~59.159 ms
+XXX[221] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14675 ~66.405 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1465 ~6.631 ms, finishGL 77 / 13092 ~59.243 ms
+XXX[222] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14759 ~66.484 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1471 ~6.626 ms, finishGL 77 / 13170 ~59.328 ms
+XXX[223] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14842 ~66.559 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1475 ~6.616 ms, finishGL 78 / 13249 ~59.413 ms
+XXX[224] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 14925 ~66.63 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1479 ~6.605 ms, finishGL 77 / 13326 ~59.494 ms
+XXX[225] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15008 ~66.702 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1484 ~6.598 ms, finishGL 77 / 13404 ~59.574 ms
+XXX[226] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15090 ~66.773 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1489 ~6.592 ms, finishGL 76 / 13481 ~59.651 ms
+XXX[227] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15173 ~66.843 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1495 ~6.589 ms, finishGL 76 / 13557 ~59.724 ms
+XXX[228] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15255 ~66.911 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1502 ~6.587 ms, finishGL 75 / 13633 ~59.794 ms
+XXX[229] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15338 ~66.978 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1509 ~6.59 ms, finishGL 74 / 13707 ~59.859 ms
+XXX[230] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15420 ~67.045 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 1517 ~6.596 ms, finishGL 73 / 13781 ~59.92 ms
+XXX[231] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15501 ~67.107 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 1526 ~6.606 ms, finishGL 72 / 13853 ~59.972 ms
+XXX[232] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15583 ~67.17 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 1536 ~6.624 ms, finishGL 70 / 13924 ~60.018 ms
+XXX[233] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15665 ~67.233 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 1548 ~6.647 ms, finishGL 69 / 13993 ~60.058 ms
+XXX[234] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15746 ~67.294 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1562 ~6.676 ms, finishGL 67 / 14061 ~60.09 ms
+XXX[235] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15828 ~67.357 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1577 ~6.713 ms, finishGL 66 / 14127 ~60.116 ms
+XXX[236] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15910 ~67.415 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1593 ~6.753 ms, finishGL 64 / 14191 ~60.134 ms
+XXX[237] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 15976 ~67.411 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1595 ~6.731 ms, finishGL 64 / 14256 ~60.152 ms
+XXX[238] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16043 ~67.409 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1597 ~6.71 ms, finishGL 64 / 14321 ~60.172 ms
+XXX[239] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16109 ~67.402 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1598 ~6.686 ms, finishGL 64 / 14385 ~60.189 ms
+XXX[240] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16176 ~67.4 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1599 ~6.666 ms, finishGL 64 / 14450 ~60.208 ms
+XXX[241] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16241 ~67.394 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1601 ~6.643 ms, finishGL 64 / 14514 ~60.224 ms
+XXX[242] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16308 ~67.389 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1603 ~6.624 ms, finishGL 63 / 14577 ~60.239 ms
+XXX[243] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16374 ~67.384 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1605 ~6.606 ms, finishGL 63 / 14641 ~60.252 ms
+XXX[244] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16440 ~67.377 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1607 ~6.589 ms, finishGL 62 / 14704 ~60.262 ms
+XXX[245] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16507 ~67.376 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1611 ~6.575 ms, finishGL 63 / 14767 ~60.275 ms
+XXX[246] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16573 ~67.372 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1613 ~6.559 ms, finishGL 63 / 14830 ~60.287 ms
+XXX[247] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16640 ~67.371 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1616 ~6.543 ms, finishGL 63 / 14894 ~60.302 ms
+XXX[248] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16708 ~67.372 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1618 ~6.525 ms, finishGL 65 / 14959 ~60.321 ms
+XXX[249] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16776 ~67.373 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1619 ~6.502 ms, finishGL 66 / 15026 ~60.345 ms
+XXX[250] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 16860 ~67.442 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1635 ~6.542 ms, finishGL 67 / 15093 ~60.374 ms
+XXX[251] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 16945 ~67.513 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1650 ~6.576 ms, finishGL 69 / 15163 ~60.411 ms
+XXX[252] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17030 ~67.582 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1663 ~6.602 ms, finishGL 71 / 15234 ~60.455 ms
+XXX[253] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 17116 ~67.652 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 1675 ~6.621 ms, finishGL 73 / 15308 ~60.507 ms
+XXX[254] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17200 ~67.719 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 1684 ~6.63 ms, finishGL 74 / 15383 ~60.563 ms
+XXX[255] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17285 ~67.785 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1691 ~6.635 ms, finishGL 76 / 15459 ~60.625 ms
+XXX[256] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17369 ~67.85 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1698 ~6.634 ms, finishGL 77 / 15537 ~60.692 ms
+XXX[257] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17454 ~67.916 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1703 ~6.629 ms, finishGL 79 / 15616 ~60.763 ms
+XXX[258] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17538 ~67.977 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1706 ~6.615 ms, finishGL 79 / 15696 ~60.837 ms
+XXX[259] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17621 ~68.038 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1709 ~6.6 ms, finishGL 80 / 15776 ~60.913 ms
+FrameCount: 360 - FrameRate: 15.0
+XXX[260] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17704 ~68.095 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1712 ~6.587 ms, finishGL 79 / 15855 ~60.984 ms
+XXX[261] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17787 ~68.153 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1715 ~6.571 ms, finishGL 80 / 15936 ~61.057 ms
+XXX[262] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17871 ~68.21 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1717 ~6.556 ms, finishGL 79 / 16016 ~61.129 ms
+XXX[263] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17953 ~68.264 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1720 ~6.541 ms, finishGL 79 / 16095 ~61.199 ms
+XXX[264] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18035 ~68.318 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1723 ~6.528 ms, finishGL 78 / 16174 ~61.265 ms
+XXX[265] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18118 ~68.371 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1727 ~6.519 ms, finishGL 78 / 16252 ~61.329 ms
+XXX[266] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18201 ~68.425 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1732 ~6.512 ms, finishGL 77 / 16329 ~61.39 ms
+XXX[267] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18283 ~68.478 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1737 ~6.507 ms, finishGL 77 / 16406 ~61.448 ms
+XXX[268] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18366 ~68.53 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1743 ~6.504 ms, finishGL 75 / 16482 ~61.502 ms
+XXX[269] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18448 ~68.582 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1750 ~6.505 ms, finishGL 75 / 16558 ~61.554 ms
+XXX[270] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 18529 ~68.627 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1757 ~6.508 ms, finishGL 73 / 16631 ~61.597 ms
+XXX[271] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18611 ~68.677 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 1766 ~6.519 ms, finishGL 71 / 16703 ~61.635 ms
+XXX[272] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18694 ~68.728 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 1777 ~6.534 ms, finishGL 71 / 16774 ~61.672 ms
+XXX[273] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18775 ~68.775 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 1788 ~6.551 ms, finishGL 69 / 16844 ~61.701 ms
+XXX[274] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18858 ~68.826 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1801 ~6.575 ms, finishGL 69 / 16913 ~61.729 ms
+XXX[275] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18940 ~68.875 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1814 ~6.599 ms, finishGL 68 / 16982 ~61.755 ms
+XXX[276] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19023 ~68.924 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1828 ~6.626 ms, finishGL 68 / 17050 ~61.777 ms
+XXX[277] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19105 ~68.973 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 1843 ~6.655 ms, finishGL 67 / 17117 ~61.797 ms
+XXX[278] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19187 ~69.021 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1858 ~6.686 ms, finishGL 66 / 17184 ~61.814 ms
+XXX[279] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19270 ~69.069 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1875 ~6.721 ms, finishGL 65 / 17249 ~61.827 ms
+XXX[280] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19352 ~69.116 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1875 ~6.699 ms, finishGL 81 / 17331 ~61.896 ms
+XXX[281] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19418 ~69.106 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1876 ~6.679 ms, finishGL 64 / 17395 ~61.906 ms
+XXX[282] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19484 ~69.094 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1878 ~6.66 ms, finishGL 63 / 17459 ~61.913 ms
+XXX[283] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19549 ~69.08 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1880 ~6.645 ms, finishGL 62 / 17522 ~61.915 ms
+XXX[284] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19615 ~69.067 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1883 ~6.633 ms, finishGL 61 / 17583 ~61.914 ms
+XXX[285] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19680 ~69.055 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1889 ~6.629 ms, finishGL 59 / 17643 ~61.906 ms
+XXX[286] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19746 ~69.042 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1894 ~6.625 ms, finishGL 59 / 17702 ~61.897 ms
+XXX[287] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19811 ~69.03 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1901 ~6.625 ms, finishGL 58 / 17761 ~61.886 ms
+XXX[288] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19877 ~69.018 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1908 ~6.627 ms, finishGL 57 / 17819 ~61.872 ms
+XXX[289] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 19942 ~69.003 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 1917 ~6.634 ms, finishGL 55 / 17874 ~61.85 ms
+XXX[290] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20007 ~68.992 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 1927 ~6.646 ms, finishGL 55 / 17929 ~61.827 ms
+XXX[291] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20073 ~68.979 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 1938 ~6.661 ms, finishGL 53 / 17983 ~61.8 ms
+XXX[292] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20138 ~68.968 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 1950 ~6.679 ms, finishGL 53 / 18037 ~61.771 ms
+XXX[293] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20204 ~68.958 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 1962 ~6.699 ms, finishGL 52 / 18090 ~61.741 ms
+XXX[294] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20270 ~68.946 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1975 ~6.72 ms, finishGL 51 / 18142 ~61.707 ms
+XXX[295] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20336 ~68.936 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 1990 ~6.746 ms, finishGL 51 / 18193 ~61.672 ms
+XXX[296] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20402 ~68.926 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 2004 ~6.773 ms, finishGL 50 / 18244 ~61.636 ms
+XXX[297] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20468 ~68.916 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 2019 ~6.8 ms, finishGL 50 / 18294 ~61.599 ms
+XXX[298] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20534 ~68.909 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 2035 ~6.829 ms, finishGL 50 / 18345 ~61.562 ms
+XXX[299] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20602 ~68.903 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 2050 ~6.859 ms, finishGL 51 / 18396 ~61.527 ms
+XXX[300] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20669 ~68.896 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 2065 ~6.885 ms, finishGL 51 / 18448 ~61.495 ms
+XXX[301] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20736 ~68.892 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 2079 ~6.909 ms, finishGL 53 / 18501 ~61.466 ms
+XXX[302] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 20804 ~68.889 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 2092 ~6.929 ms, finishGL 54 / 18556 ~61.444 ms
+XXX[303] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 20873 ~68.889 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2104 ~6.944 ms, finishGL 56 / 18612 ~61.428 ms
+XXX[304] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 20942 ~68.888 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2114 ~6.957 ms, finishGL 57 / 18670 ~61.415 ms
+XXX[305] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 21012 ~68.892 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2121 ~6.957 ms, finishGL 62 / 18733 ~61.419 ms
+XXX[306] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 21083 ~68.9 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2125 ~6.944 ms, finishGL 67 / 18800 ~61.439 ms
+XXX[307] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 21171 ~68.963 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 2140 ~6.971 ms, finishGL 72 / 18873 ~61.475 ms
+XXX[308] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 21258 ~69.02 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2150 ~6.981 ms, finishGL 76 / 18949 ~61.523 ms
+XXX[309] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 21343 ~69.073 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2157 ~6.98 ms, finishGL 78 / 19027 ~61.577 ms
+XXX[310] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 21428 ~69.125 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2161 ~6.972 ms, finishGL 80 / 19107 ~61.637 ms
+XXX[311] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 21512 ~69.17 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2163 ~6.957 ms, finishGL 80 / 19187 ~61.697 ms
+XXX[312] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 21594 ~69.214 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2166 ~6.943 ms, finishGL 79 / 19267 ~61.755 ms
+XXX[313] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 21678 ~69.259 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2169 ~6.93 ms, finishGL 80 / 19347 ~61.814 ms
+XXX[314] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21762 ~69.305 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2171 ~6.914 ms, finishGL 80 / 19428 ~61.874 ms
+XXX[315] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21846 ~69.353 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2173 ~6.899 ms, finishGL 81 / 19510 ~61.937 ms
+XXX[316] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21930 ~69.4 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 2174 ~6.879 ms, finishGL 82 / 19593 ~62.003 ms
+XXX[317] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 22030 ~69.497 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 16 / 2190 ~6.91 ms, finishGL 83 / 19676 ~62.07 ms
+XXX[318] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 22129 ~69.589 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 16 / 2206 ~6.939 ms, finishGL 81 / 19758 ~62.133 ms
+XXX[319] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 22228 ~69.682 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 2207 ~6.92 ms, finishGL 98 / 19856 ~62.245 ms
+XXX[320] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22311 ~69.722 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 2208 ~6.902 ms, finishGL 81 / 19937 ~62.304 ms
+XXX[321] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22394 ~69.764 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 2210 ~6.885 ms, finishGL 80 / 20018 ~62.362 ms
+XXX[322] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22476 ~69.803 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 2212 ~6.87 ms, finishGL 80 / 20098 ~62.417 ms
+XXX[323] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22559 ~69.844 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2214 ~6.857 ms, finishGL 80 / 20178 ~62.472 ms
+XXX[324] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22642 ~69.885 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2217 ~6.844 ms, finishGL 79 / 20258 ~62.525 ms
+XXX[325] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22726 ~69.926 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2220 ~6.831 ms, finishGL 79 / 20338 ~62.579 ms
+XXX[326] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22809 ~69.968 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2223 ~6.819 ms, finishGL 80 / 20418 ~62.633 ms
+XXX[327] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22892 ~70.008 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2225 ~6.805 ms, finishGL 80 / 20498 ~62.687 ms
+XXX[328] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22976 ~70.049 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2227 ~6.791 ms, finishGL 80 / 20579 ~62.742 ms
+XXX[329] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23057 ~70.084 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2229 ~6.778 ms, finishGL 78 / 20658 ~62.791 ms
+XXX[330] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 23142 ~70.129 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2233 ~6.768 ms, finishGL 80 / 20739 ~62.846 ms
+XXX[331] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 23226 ~70.171 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 2235 ~6.753 ms, finishGL 81 / 20821 ~62.903 ms
+XXX[332] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23308 ~70.207 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 2236 ~6.735 ms, finishGL 80 / 20901 ~62.957 ms
+XXX[333] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23392 ~70.248 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2238 ~6.721 ms, finishGL 81 / 20983 ~63.012 ms
+XXX[334] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23475 ~70.285 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 2239 ~6.705 ms, finishGL 80 / 21063 ~63.065 ms
+XXX[335] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23558 ~70.323 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 2241 ~6.69 ms, finishGL 80 / 21144 ~63.117 ms
+XXX[336] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23640 ~70.359 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2243 ~6.676 ms, finishGL 79 / 21224 ~63.167 ms
+XXX[337] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23721 ~70.391 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2246 ~6.665 ms, finishGL 77 / 21301 ~63.21 ms
+XXX[338] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23804 ~70.427 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2251 ~6.66 ms, finishGL 77 / 21379 ~63.251 ms
+XXX[339] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23887 ~70.465 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2257 ~6.658 ms, finishGL 76 / 21456 ~63.292 ms
+XXX[340] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23971 ~70.503 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2262 ~6.654 ms, finishGL 77 / 21533 ~63.333 ms
+XXX[341] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24053 ~70.538 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2267 ~6.648 ms, finishGL 77 / 21610 ~63.374 ms
+XXX[342] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24136 ~70.574 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2272 ~6.646 ms, finishGL 76 / 21687 ~63.412 ms
+XXX[343] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24219 ~70.611 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2279 ~6.644 ms, finishGL 76 / 21763 ~63.451 ms
+XXX[344] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24302 ~70.646 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2284 ~6.642 ms, finishGL 76 / 21840 ~63.488 ms
+XXX[345] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24385 ~70.683 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2291 ~6.641 ms, finishGL 76 / 21916 ~63.526 ms
+XXX[346] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24468 ~70.718 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2297 ~6.64 ms, finishGL 76 / 21992 ~63.562 ms
+XXX[347] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24551 ~70.754 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2304 ~6.641 ms, finishGL 75 / 22068 ~63.598 ms
+XXX[348] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24635 ~70.791 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2311 ~6.641 ms, finishGL 76 / 22145 ~63.635 ms
+XXX[349] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24718 ~70.826 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2317 ~6.64 ms, finishGL 76 / 22221 ~63.67 ms
+XXX[350] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24801 ~70.861 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2323 ~6.639 ms, finishGL 76 / 22297 ~63.706 ms
+XXX[351] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24884 ~70.896 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2330 ~6.639 ms, finishGL 76 / 22373 ~63.743 ms
+XXX[352] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24967 ~70.931 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2336 ~6.637 ms, finishGL 76 / 22450 ~63.779 ms
+XXX[353] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25051 ~70.967 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2342 ~6.636 ms, finishGL 76 / 22527 ~63.815 ms
+XXX[354] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25134 ~71.001 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2348 ~6.634 ms, finishGL 76 / 22603 ~63.852 ms
+XXX[355] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25217 ~71.035 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2354 ~6.633 ms, finishGL 76 / 22680 ~63.887 ms
+XXX[356] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25300 ~71.068 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2360 ~6.631 ms, finishGL 76 / 22756 ~63.922 ms
+XXX[357] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25383 ~71.102 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2367 ~6.631 ms, finishGL 76 / 22832 ~63.957 ms
+XXX[358] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25466 ~71.136 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2373 ~6.63 ms, finishGL 76 / 22909 ~63.992 ms
+XXX[359] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 25550 ~71.171 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2380 ~6.629 ms, finishGL 77 / 22986 ~64.028 ms
+XXX[360] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25633 ~71.205 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2385 ~6.627 ms, finishGL 76 / 23063 ~64.064 ms
+XXX[361] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25716 ~71.236 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2391 ~6.624 ms, finishGL 76 / 23139 ~64.099 ms
+XXX[362] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 25800 ~71.271 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2397 ~6.622 ms, finishGL 77 / 23217 ~64.136 ms
+XXX[363] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25884 ~71.306 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2402 ~6.618 ms, finishGL 78 / 23295 ~64.175 ms
+XXX[364] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25967 ~71.339 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2406 ~6.612 ms, finishGL 78 / 23374 ~64.214 ms
+XXX[365] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26051 ~71.372 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2411 ~6.606 ms, finishGL 78 / 23452 ~64.253 ms
+XXX[366] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26133 ~71.404 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2415 ~6.599 ms, finishGL 77 / 23530 ~64.291 ms
+XXX[367] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26217 ~71.436 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2420 ~6.595 ms, finishGL 78 / 23608 ~64.329 ms
+XXX[368] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26300 ~71.468 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2424 ~6.588 ms, finishGL 78 / 23687 ~64.367 ms
+XXX[369] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26383 ~71.499 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2429 ~6.582 ms, finishGL 77 / 23765 ~64.404 ms
+XXX[370] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26467 ~71.532 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2433 ~6.577 ms, finishGL 78 / 23843 ~64.442 ms
+XXX[371] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26549 ~71.561 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2438 ~6.571 ms, finishGL 77 / 23921 ~64.478 ms
+XXX[372] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26631 ~71.59 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2442 ~6.566 ms, finishGL 76 / 23998 ~64.511 ms
+XXX[373] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26714 ~71.62 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2448 ~6.563 ms, finishGL 76 / 24074 ~64.544 ms
+XXX[374] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26797 ~71.651 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2454 ~6.562 ms, finishGL 76 / 24151 ~64.576 ms
+XXX[375] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 26896 ~71.724 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2460 ~6.561 ms, finishGL 92 / 24244 ~64.651 ms
+XXX[376] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26979 ~71.755 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2467 ~6.562 ms, finishGL 75 / 24320 ~64.681 ms
+XXX[377] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27062 ~71.783 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2474 ~6.562 ms, finishGL 75 / 24395 ~64.709 ms
+XXX[378] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27145 ~71.813 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2481 ~6.564 ms, finishGL 75 / 24470 ~64.737 ms
+XXX[379] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27227 ~71.841 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2488 ~6.566 ms, finishGL 74 / 24545 ~64.763 ms
+FrameCount: 480 - FrameRate: 12.0
+XXX[380] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27310 ~71.869 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2496 ~6.57 ms, finishGL 74 / 24619 ~64.787 ms
+XXX[381] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27393 ~71.898 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2505 ~6.575 ms, finishGL 73 / 24692 ~64.81 ms
+XXX[382] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27475 ~71.926 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2514 ~6.582 ms, finishGL 73 / 24765 ~64.832 ms
+XXX[383] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27558 ~71.955 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2524 ~6.59 ms, finishGL 72 / 24838 ~64.853 ms
+XXX[384] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27642 ~71.985 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2533 ~6.598 ms, finishGL 73 / 24911 ~64.874 ms
+XXX[385] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 27727 ~72.019 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2543 ~6.606 ms, finishGL 75 / 24986 ~64.901 ms
+XXX[386] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27811 ~72.049 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2551 ~6.609 ms, finishGL 75 / 25062 ~64.929 ms
+XXX[387] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27894 ~72.078 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2558 ~6.61 ms, finishGL 75 / 25138 ~64.957 ms
+XXX[388] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27978 ~72.108 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2564 ~6.609 ms, finishGL 76 / 25215 ~64.987 ms
+XXX[389] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 28063 ~72.142 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2570 ~6.608 ms, finishGL 78 / 25293 ~65.022 ms
+XXX[390] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 28147 ~72.172 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2574 ~6.602 ms, finishGL 78 / 25372 ~65.056 ms
+XXX[391] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28231 ~72.202 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2578 ~6.594 ms, finishGL 79 / 25451 ~65.094 ms
+XXX[392] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28314 ~72.23 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2581 ~6.584 ms, finishGL 80 / 25531 ~65.132 ms
+XXX[393] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28397 ~72.258 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2583 ~6.574 ms, finishGL 79 / 25611 ~65.17 ms
+XXX[394] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28480 ~72.285 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2586 ~6.565 ms, finishGL 79 / 25691 ~65.206 ms
+XXX[395] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28563 ~72.313 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2589 ~6.556 ms, finishGL 79 / 25771 ~65.243 ms
+XXX[396] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28646 ~72.339 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2592 ~6.547 ms, finishGL 79 / 25850 ~65.279 ms
+XXX[397] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28729 ~72.366 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2596 ~6.539 ms, finishGL 79 / 25929 ~65.314 ms
+XXX[398] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28812 ~72.393 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2599 ~6.531 ms, finishGL 79 / 26008 ~65.348 ms
+XXX[399] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28895 ~72.418 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2603 ~6.524 ms, finishGL 78 / 26087 ~65.381 ms
+XXX[400] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28977 ~72.444 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2607 ~6.518 ms, finishGL 78 / 26165 ~65.413 ms
+XXX[401] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29059 ~72.468 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2612 ~6.514 ms, finishGL 76 / 26242 ~65.442 ms
+XXX[402] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 29141 ~72.491 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2617 ~6.512 ms, finishGL 75 / 26317 ~65.467 ms
+XXX[403] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29224 ~72.517 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2625 ~6.513 ms, finishGL 75 / 26393 ~65.491 ms
+XXX[404] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29307 ~72.542 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2632 ~6.516 ms, finishGL 74 / 26467 ~65.514 ms
+XXX[405] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29390 ~72.568 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2640 ~6.519 ms, finishGL 74 / 26542 ~65.537 ms
+XXX[406] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29473 ~72.594 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2648 ~6.522 ms, finishGL 74 / 26617 ~65.559 ms
+XXX[407] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29555 ~72.618 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2656 ~6.527 ms, finishGL 73 / 26690 ~65.578 ms
+XXX[408] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29638 ~72.644 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2665 ~6.533 ms, finishGL 73 / 26764 ~65.598 ms
+XXX[409] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29721 ~72.669 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2674 ~6.539 ms, finishGL 73 / 26837 ~65.618 ms
+XXX[410] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29804 ~72.693 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2683 ~6.546 ms, finishGL 72 / 26910 ~65.635 ms
+XXX[411] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29887 ~72.719 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2694 ~6.554 ms, finishGL 72 / 26983 ~65.653 ms
+XXX[412] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29970 ~72.744 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2703 ~6.561 ms, finishGL 73 / 27056 ~65.671 ms
+XXX[413] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30052 ~72.767 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2713 ~6.569 ms, finishGL 72 / 27128 ~65.686 ms
+XXX[414] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30136 ~72.792 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2723 ~6.578 ms, finishGL 72 / 27200 ~65.702 ms
+XXX[415] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30219 ~72.817 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2734 ~6.588 ms, finishGL 71 / 27272 ~65.717 ms
+XXX[416] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30301 ~72.84 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2745 ~6.599 ms, finishGL 71 / 27343 ~65.73 ms
+XXX[417] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30384 ~72.865 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2756 ~6.61 ms, finishGL 71 / 27415 ~65.743 ms
+XXX[418] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30468 ~72.89 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2767 ~6.621 ms, finishGL 71 / 27486 ~65.757 ms
+XXX[419] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30551 ~72.914 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2779 ~6.633 ms, finishGL 71 / 27557 ~65.77 ms
+XXX[420] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30635 ~72.941 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2790 ~6.644 ms, finishGL 72 / 27630 ~65.786 ms
+XXX[421] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30720 ~72.969 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2801 ~6.653 ms, finishGL 73 / 27703 ~65.805 ms
+XXX[422] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30803 ~72.993 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2809 ~6.658 ms, finishGL 73 / 27777 ~65.824 ms
+XXX[423] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 30883 ~73.011 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2818 ~6.663 ms, finishGL 71 / 27848 ~65.836 ms
+XXX[424] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 30964 ~73.028 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2830 ~6.675 ms, finishGL 68 / 27917 ~65.842 ms
+XXX[425] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31044 ~73.046 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 2844 ~6.693 ms, finishGL 65 / 27982 ~65.842 ms
+XXX[426] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31124 ~73.063 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 2844 ~6.678 ms, finishGL 79 / 28062 ~65.874 ms
+XXX[427] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31189 ~73.044 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2848 ~6.67 ms, finishGL 61 / 28123 ~65.863 ms
+XXX[428] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31256 ~73.028 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2852 ~6.665 ms, finishGL 61 / 28185 ~65.852 ms
+XXX[429] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31321 ~73.01 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2857 ~6.66 ms, finishGL 59 / 28244 ~65.839 ms
+XXX[430] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31387 ~72.994 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2863 ~6.659 ms, finishGL 59 / 28304 ~65.824 ms
+XXX[431] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31454 ~72.979 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2869 ~6.658 ms, finishGL 59 / 28364 ~65.809 ms
+XXX[432] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31519 ~72.962 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2876 ~6.658 ms, finishGL 58 / 28422 ~65.793 ms
+XXX[433] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31586 ~72.947 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2883 ~6.659 ms, finishGL 58 / 28481 ~65.777 ms
+XXX[434] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31651 ~72.93 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2890 ~6.661 ms, finishGL 57 / 28539 ~65.759 ms
+XXX[435] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31718 ~72.915 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2899 ~6.664 ms, finishGL 57 / 28597 ~65.74 ms
+XXX[436] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31784 ~72.899 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2907 ~6.668 ms, finishGL 57 / 28654 ~65.72 ms
+XXX[437] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31850 ~72.884 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2916 ~6.673 ms, finishGL 57 / 28711 ~65.701 ms
+XXX[438] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31917 ~72.871 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2925 ~6.678 ms, finishGL 57 / 28769 ~65.682 ms
+XXX[439] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31984 ~72.857 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2934 ~6.683 ms, finishGL 57 / 28826 ~65.664 ms
+XXX[440] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32050 ~72.843 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2942 ~6.686 ms, finishGL 57 / 28884 ~65.646 ms
+XXX[441] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32117 ~72.829 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2950 ~6.689 ms, finishGL 58 / 28942 ~65.63 ms
+XXX[442] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32185 ~72.817 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2957 ~6.692 ms, finishGL 59 / 29002 ~65.615 ms
+XXX[443] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32251 ~72.803 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2964 ~6.692 ms, finishGL 59 / 29061 ~65.601 ms
+XXX[444] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32318 ~72.788 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2971 ~6.692 ms, finishGL 59 / 29120 ~65.586 ms
+XXX[445] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32385 ~72.776 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2978 ~6.692 ms, finishGL 60 / 29180 ~65.574 ms
+XXX[446] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32451 ~72.761 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2984 ~6.691 ms, finishGL 59 / 29240 ~65.561 ms
+XXX[447] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32518 ~72.747 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2990 ~6.69 ms, finishGL 59 / 29299 ~65.547 ms
+XXX[448] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32585 ~72.734 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2997 ~6.689 ms, finishGL 60 / 29359 ~65.535 ms
+XXX[449] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32651 ~72.72 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3002 ~6.688 ms, finishGL 59 / 29419 ~65.523 ms
+XXX[450] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32718 ~72.707 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3009 ~6.686 ms, finishGL 60 / 29480 ~65.511 ms
+XXX[451] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32784 ~72.692 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3014 ~6.684 ms, finishGL 59 / 29540 ~65.499 ms
+XXX[452] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32850 ~72.677 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3021 ~6.683 ms, finishGL 59 / 29599 ~65.484 ms
+XXX[453] TO 17 ms, lFrame0 1 ms, lFrameX 65 / 32915 ~72.662 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3027 ~6.682 ms, finishGL 58 / 29657 ~65.469 ms
+XXX[454] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32981 ~72.645 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 3034 ~6.684 ms, finishGL 57 / 29714 ~65.451 ms
+XXX[455] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33047 ~72.63 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3043 ~6.689 ms, finishGL 56 / 29771 ~65.431 ms
+XXX[456] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33112 ~72.614 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3053 ~6.695 ms, finishGL 55 / 29826 ~65.409 ms
+XXX[457] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33178 ~72.6 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3063 ~6.704 ms, finishGL 54 / 29881 ~65.386 ms
+XXX[458] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33243 ~72.584 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 3074 ~6.713 ms, finishGL 53 / 29935 ~65.361 ms
+XXX[459] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33309 ~72.569 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 3087 ~6.725 ms, finishGL 53 / 29988 ~65.334 ms
+XXX[460] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33375 ~72.554 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3100 ~6.739 ms, finishGL 52 / 30040 ~65.306 ms
+XXX[461] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33440 ~72.539 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3113 ~6.754 ms, finishGL 51 / 30092 ~65.275 ms
+XXX[462] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33506 ~72.524 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 3128 ~6.771 ms, finishGL 50 / 30142 ~65.244 ms
+XXX[463] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33571 ~72.509 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3143 ~6.79 ms, finishGL 49 / 30192 ~65.21 ms
+XXX[464] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33637 ~72.494 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 16 / 3160 ~6.81 ms, finishGL 48 / 30241 ~65.174 ms
+XXX[465] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33702 ~72.479 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 3161 ~6.798 ms, finishGL 64 / 30305 ~65.172 ms
+XXX[466] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33751 ~72.428 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 3162 ~6.786 ms, finishGL 46 / 30352 ~65.133 ms
+XXX[467] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33801 ~72.379 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 3165 ~6.778 ms, finishGL 46 / 30398 ~65.092 ms
+XXX[468] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33850 ~72.329 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 3168 ~6.77 ms, finishGL 45 / 30443 ~65.05 ms
+XXX[469] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33899 ~72.28 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3172 ~6.763 ms, finishGL 45 / 30488 ~65.008 ms
+XXX[470] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33948 ~72.231 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3176 ~6.758 ms, finishGL 44 / 30533 ~64.963 ms
+XXX[471] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33998 ~72.182 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3181 ~6.755 ms, finishGL 43 / 30576 ~64.919 ms
+XXX[472] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34047 ~72.134 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3187 ~6.752 ms, finishGL 43 / 30620 ~64.874 ms
+XXX[473] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34096 ~72.086 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3192 ~6.75 ms, finishGL 43 / 30663 ~64.827 ms
+XXX[474] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34145 ~72.036 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3199 ~6.749 ms, finishGL 41 / 30705 ~64.779 ms
+XXX[475] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34194 ~71.988 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 3206 ~6.75 ms, finishGL 41 / 30746 ~64.729 ms
+XXX[476] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34243 ~71.94 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3214 ~6.753 ms, finishGL 40 / 30787 ~64.678 ms
+XXX[477] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34292 ~71.892 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3223 ~6.758 ms, finishGL 39 / 30826 ~64.626 ms
+XXX[478] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34341 ~71.845 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3233 ~6.763 ms, finishGL 39 / 30866 ~64.573 ms
+XXX[479] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34390 ~71.797 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3243 ~6.77 ms, finishGL 38 / 30904 ~64.518 ms
+XXX[480] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34439 ~71.749 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 3254 ~6.779 ms, finishGL 37 / 30941 ~64.461 ms
+XXX[481] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34488 ~71.702 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 3266 ~6.79 ms, finishGL 36 / 30978 ~64.404 ms
+XXX[482] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34537 ~71.655 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 3278 ~6.802 ms, finishGL 36 / 31014 ~64.345 ms
+XXX[483] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34586 ~71.608 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3292 ~6.815 ms, finishGL 35 / 31049 ~64.285 ms
+XXX[484] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34635 ~71.561 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 3306 ~6.831 ms, finishGL 34 / 31084 ~64.223 ms
+XXX[485] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34685 ~71.516 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3321 ~6.848 ms, finishGL 33 / 31117 ~64.16 ms
+XXX[486] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34735 ~71.471 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 16 / 3337 ~6.867 ms, finishGL 33 / 31150 ~64.096 ms
+XXX[487] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34784 ~71.426 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3352 ~6.884 ms, finishGL 33 / 31184 ~64.033 ms
+XXX[488] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34834 ~71.381 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3368 ~6.902 ms, finishGL 33 / 31218 ~63.971 ms
+XXX[489] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34884 ~71.338 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 17 / 3385 ~6.924 ms, finishGL 32 / 31250 ~63.906 ms
+XXX[490] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34934 ~71.295 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3401 ~6.941 ms, finishGL 34 / 31284 ~63.846 ms
+XXX[491] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34984 ~71.251 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3416 ~6.958 ms, finishGL 34 / 31318 ~63.785 ms
+XXX[492] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35034 ~71.207 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3431 ~6.974 ms, finishGL 34 / 31352 ~63.725 ms
+XXX[493] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35083 ~71.163 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3446 ~6.991 ms, finishGL 33 / 31386 ~63.664 ms
+XXX[494] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 35134 ~71.123 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3462 ~7.008 ms, finishGL 35 / 31422 ~63.607 ms
+XXX[495] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35185 ~71.081 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 3476 ~7.023 ms, finishGL 35 / 31457 ~63.55 ms
+XXX[496] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35235 ~71.039 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3489 ~7.036 ms, finishGL 36 / 31494 ~63.496 ms
+XXX[497] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35285 ~70.997 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3503 ~7.048 ms, finishGL 36 / 31530 ~63.442 ms
+XXX[498] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35336 ~70.956 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 3515 ~7.059 ms, finishGL 37 / 31568 ~63.389 ms
+XXX[499] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35386 ~70.914 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 3527 ~7.069 ms, finishGL 37 / 31605 ~63.338 ms
+FrameCount: 600 - FrameRate: 19.0
+XXX[500] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35436 ~70.873 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 3538 ~7.077 ms, finishGL 38 / 31644 ~63.288 ms
+XXX[501] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35486 ~70.831 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3549 ~7.085 ms, finishGL 38 / 31683 ~63.239 ms
+XXX[502] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35537 ~70.791 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3560 ~7.092 ms, finishGL 39 / 31722 ~63.191 ms
+XXX[503] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35587 ~70.749 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3570 ~7.098 ms, finishGL 39 / 31761 ~63.144 ms
+XXX[504] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35637 ~70.709 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3580 ~7.104 ms, finishGL 39 / 31801 ~63.098 ms
+XXX[505] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35687 ~70.667 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3589 ~7.108 ms, finishGL 39 / 31841 ~63.052 ms
+XXX[506] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35737 ~70.627 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3599 ~7.113 ms, finishGL 40 / 31881 ~63.007 ms
+XXX[507] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35788 ~70.588 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3608 ~7.117 ms, finishGL 41 / 31923 ~62.964 ms
+XXX[508] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35837 ~70.547 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3616 ~7.119 ms, finishGL 40 / 31964 ~62.921 ms
+XXX[509] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35888 ~70.507 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3625 ~7.122 ms, finishGL 41 / 32005 ~62.878 ms
+XXX[510] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35938 ~70.467 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3633 ~7.123 ms, finishGL 41 / 32047 ~62.837 ms
+XXX[511] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35989 ~70.429 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 3640 ~7.124 ms, finishGL 43 / 32090 ~62.799 ms
+XXX[512] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 36042 ~70.394 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3646 ~7.121 ms, finishGL 45 / 32136 ~62.766 ms
+XXX[513] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 36093 ~70.358 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3649 ~7.114 ms, finishGL 47 / 32184 ~62.737 ms
+XXX[514] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 36147 ~70.325 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 3651 ~7.103 ms, finishGL 51 / 32236 ~62.716 ms
+XXX[515] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 36217 ~70.324 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 3665 ~7.117 ms, finishGL 54 / 32290 ~62.7 ms
+XXX[516] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 36287 ~70.325 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 3676 ~7.125 ms, finishGL 59 / 32349 ~62.693 ms
+XXX[517] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 36363 ~70.336 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3683 ~7.124 ms, finishGL 68 / 32418 ~62.705 ms
+XXX[518] TO 17 ms, lFrame0 0 ms, lFrameX 91 / 36455 ~70.376 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3697 ~7.138 ms, finishGL 77 / 32495 ~62.732 ms
+XXX[519] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36539 ~70.402 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3703 ~7.135 ms, finishGL 77 / 32573 ~62.761 ms
+XXX[520] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36622 ~70.427 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3708 ~7.131 ms, finishGL 77 / 32650 ~62.79 ms
+XXX[521] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36705 ~70.451 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3713 ~7.127 ms, finishGL 77 / 32728 ~62.818 ms
+XXX[522] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36788 ~70.476 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3718 ~7.123 ms, finishGL 77 / 32806 ~62.847 ms
+XXX[523] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36871 ~70.5 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3723 ~7.118 ms, finishGL 77 / 32883 ~62.875 ms
+XXX[524] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36954 ~70.523 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3728 ~7.115 ms, finishGL 76 / 32960 ~62.902 ms
+XXX[525] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37037 ~70.547 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3733 ~7.112 ms, finishGL 77 / 33037 ~62.929 ms
+XXX[526] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37120 ~70.57 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3739 ~7.109 ms, finishGL 76 / 33114 ~62.955 ms
+XXX[527] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37204 ~70.595 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3745 ~7.107 ms, finishGL 77 / 33191 ~62.982 ms
+XXX[528] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37287 ~70.619 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3750 ~7.103 ms, finishGL 77 / 33269 ~63.01 ms
+XXX[529] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37370 ~70.643 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3755 ~7.1 ms, finishGL 77 / 33346 ~63.037 ms
+XXX[530] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37454 ~70.668 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3761 ~7.096 ms, finishGL 77 / 33424 ~63.065 ms
+XXX[531] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37537 ~70.692 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3765 ~7.091 ms, finishGL 78 / 33502 ~63.094 ms
+XXX[532] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37620 ~70.714 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3771 ~7.088 ms, finishGL 76 / 33579 ~63.119 ms
+XXX[533] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37703 ~70.738 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3776 ~7.084 ms, finishGL 77 / 33657 ~63.146 ms
+XXX[534] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37786 ~70.761 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3779 ~7.078 ms, finishGL 77 / 33735 ~63.174 ms
+XXX[535] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37868 ~70.782 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3784 ~7.074 ms, finishGL 76 / 33811 ~63.199 ms
+XXX[536] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37951 ~70.805 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3790 ~7.072 ms, finishGL 76 / 33888 ~63.224 ms
+XXX[537] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38035 ~70.828 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3796 ~7.07 ms, finishGL 76 / 33964 ~63.249 ms
+XXX[538] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38117 ~70.85 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3802 ~7.068 ms, finishGL 76 / 34041 ~63.273 ms
+XXX[539] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38200 ~70.872 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3809 ~7.068 ms, finishGL 75 / 34116 ~63.295 ms
+XXX[540] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38284 ~70.896 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 3817 ~7.068 ms, finishGL 76 / 34192 ~63.319 ms
+XXX[541] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38367 ~70.919 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3823 ~7.067 ms, finishGL 76 / 34268 ~63.343 ms
+XXX[542] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38450 ~70.942 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3830 ~7.066 ms, finishGL 76 / 34345 ~63.367 ms
+XXX[543] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38534 ~70.965 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3836 ~7.064 ms, finishGL 76 / 34422 ~63.392 ms
+XXX[544] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38617 ~70.988 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3842 ~7.062 ms, finishGL 76 / 34499 ~63.417 ms
+XXX[545] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38700 ~71.01 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3847 ~7.06 ms, finishGL 77 / 34576 ~63.442 ms
+XXX[546] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38785 ~71.035 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3853 ~7.057 ms, finishGL 77 / 34654 ~63.469 ms
+XXX[547] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38868 ~71.058 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3858 ~7.054 ms, finishGL 77 / 34731 ~63.495 ms
+XXX[548] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38952 ~71.081 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3863 ~7.049 ms, finishGL 79 / 34811 ~63.523 ms
+XXX[549] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39036 ~71.104 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3866 ~7.042 ms, finishGL 79 / 34890 ~63.553 ms
+XXX[550] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 39120 ~71.128 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3869 ~7.035 ms, finishGL 80 / 34971 ~63.584 ms
+XXX[551] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39203 ~71.149 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 3871 ~7.026 ms, finishGL 79 / 35051 ~63.614 ms
+XXX[552] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39285 ~71.168 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 3874 ~7.018 ms, finishGL 79 / 35130 ~63.641 ms
+XXX[553] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39367 ~71.189 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3877 ~7.012 ms, finishGL 78 / 35208 ~63.668 ms
+XXX[554] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39450 ~71.21 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3881 ~7.007 ms, finishGL 77 / 35286 ~63.694 ms
+XXX[555] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39532 ~71.23 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3886 ~7.002 ms, finishGL 77 / 35363 ~63.718 ms
+XXX[556] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39615 ~71.25 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3892 ~7.0 ms, finishGL 76 / 35440 ~63.741 ms
+XXX[557] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 39695 ~71.266 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3898 ~6.999 ms, finishGL 73 / 35513 ~63.758 ms
+XXX[558] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39778 ~71.287 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3907 ~7.003 ms, finishGL 73 / 35586 ~63.775 ms
+XXX[559] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39860 ~71.306 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3917 ~7.008 ms, finishGL 71 / 35658 ~63.789 ms
+XXX[560] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39941 ~71.324 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3928 ~7.015 ms, finishGL 70 / 35728 ~63.801 ms
+XXX[561] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40023 ~71.342 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 3941 ~7.025 ms, finishGL 68 / 35796 ~63.808 ms
+XXX[562] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40104 ~71.36 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 3955 ~7.038 ms, finishGL 66 / 35863 ~63.813 ms
+XXX[563] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40186 ~71.379 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 16 / 3972 ~7.055 ms, finishGL 65 / 35928 ~63.815 ms
+XXX[564] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40251 ~71.368 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 3973 ~7.045 ms, finishGL 63 / 35991 ~63.815 ms
+XXX[565] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40316 ~71.356 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 3976 ~7.037 ms, finishGL 61 / 36053 ~63.811 ms
+XXX[566] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40382 ~71.346 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3980 ~7.032 ms, finishGL 60 / 36113 ~63.805 ms
+XXX[567] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40447 ~71.335 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3985 ~7.028 ms, finishGL 60 / 36174 ~63.798 ms
+XXX[568] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40513 ~71.326 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3991 ~7.026 ms, finishGL 59 / 36233 ~63.791 ms
+XXX[569] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40579 ~71.316 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3997 ~7.025 ms, finishGL 58 / 36292 ~63.782 ms
+XXX[570] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 40646 ~71.309 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4005 ~7.026 ms, finishGL 59 / 36351 ~63.774 ms
+XXX[571] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40712 ~71.299 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 4011 ~7.025 ms, finishGL 58 / 36410 ~63.765 ms
+XXX[572] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40778 ~71.291 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4018 ~7.025 ms, finishGL 58 / 36469 ~63.757 ms
+XXX[573] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40845 ~71.283 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4025 ~7.025 ms, finishGL 59 / 36528 ~63.749 ms
+XXX[574] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40912 ~71.275 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4032 ~7.026 ms, finishGL 59 / 36587 ~63.741 ms
+XXX[575] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40977 ~71.265 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4039 ~7.026 ms, finishGL 58 / 36645 ~63.731 ms
+XXX[576] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 41046 ~71.261 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4047 ~7.027 ms, finishGL 60 / 36706 ~63.725 ms
+XXX[577] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 41116 ~71.259 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4053 ~7.024 ms, finishGL 63 / 36770 ~63.726 ms
+XXX[578] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 41187 ~71.258 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 4055 ~7.016 ms, finishGL 68 / 36838 ~63.734 ms
+XXX[579] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 41276 ~71.288 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 4069 ~7.028 ms, finishGL 73 / 36912 ~63.751 ms
+XXX[580] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 41363 ~71.316 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 4078 ~7.032 ms, finishGL 77 / 36989 ~63.775 ms
+XXX[581] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 41449 ~71.34 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 4083 ~7.028 ms, finishGL 80 / 37070 ~63.804 ms
+XXX[582] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 41533 ~71.362 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 4086 ~7.02 ms, finishGL 81 / 37151 ~63.834 ms
+XXX[583] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 41613 ~71.378 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 4087 ~7.011 ms, finishGL 78 / 37230 ~63.859 ms
+XXX[584] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 41695 ~71.396 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 4091 ~7.005 ms, finishGL 77 / 37307 ~63.883 ms
+XXX[585] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41778 ~71.415 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4096 ~7.002 ms, finishGL 76 / 37384 ~63.905 ms
+XXX[586] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41860 ~71.434 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4102 ~7.0 ms, finishGL 76 / 37460 ~63.925 ms
+XXX[587] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41943 ~71.453 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 4109 ~7.0 ms, finishGL 75 / 37536 ~63.946 ms
+XXX[588] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42026 ~71.473 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 4116 ~7.0 ms, finishGL 75 / 37611 ~63.965 ms
+XXX[589] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42109 ~71.492 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4123 ~7.0 ms, finishGL 75 / 37686 ~63.984 ms
+XXX[590] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42192 ~71.512 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4131 ~7.002 ms, finishGL 74 / 37761 ~64.002 ms
+XXX[591] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42275 ~71.532 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 4140 ~7.005 ms, finishGL 74 / 37835 ~64.019 ms
+XXX[592] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42358 ~71.551 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4147 ~7.006 ms, finishGL 74 / 37910 ~64.037 ms
+XXX[593] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42442 ~71.572 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4155 ~7.007 ms, finishGL 75 / 37986 ~64.057 ms
+XXX[594] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42526 ~71.592 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 4162 ~7.007 ms, finishGL 76 / 38062 ~64.078 ms
+XXX[595] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42610 ~71.614 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 4168 ~7.006 ms, finishGL 77 / 38139 ~64.1 ms
+XXX[596] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42694 ~71.634 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 4173 ~7.003 ms, finishGL 77 / 38217 ~64.123 ms
+XXX[597] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42778 ~71.655 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4178 ~6.999 ms, finishGL 78 / 38296 ~64.147 ms
+XXX[598] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42860 ~71.672 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4184 ~6.996 ms, finishGL 76 / 38372 ~64.168 ms
+XXX[599] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 42942 ~71.689 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4189 ~6.993 ms, finishGL 76 / 38448 ~64.188 ms
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait-exclctx.log b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait-exclctx.log
new file mode 100644
index 000000000..cf5bd39f5
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait-exclctx.log
@@ -0,0 +1,751 @@
+NSZombieEnabled
+NSTraceEvents YES
+OBJC_PRINT_EXCEPTIONS
+/usr/bin/java
+java version "1.6.0_37"
+Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909)
+Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)
+LD_LIBRARY_PATH :../../gluegen/make/../build-macosx/obj:../build-macosx/lib
+LIBXCB_ALLOW_SLOPPY_LOCK:
+LIBGL_DRIVERS_PATH:
+LIBGL_DEBUG:
+LIBGL_ALWAYS_INDIRECT:
+LIBGL_ALWAYS_SOFTWARE:
+SWT_CLASSPATH: ../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar
+/usr/bin/java -d64 -time 100000 -vsync 0 -exclctx
+CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar
+CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar
+
+Test Start: com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0 -exclctx
+
+/usr/bin/java -d64 -Djava.awt.headless=false -Djogl.debug.calayer.SwapM2 com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0 -exclctx
+swapInterval 0
+exclusiveContext true
+SWAP_M1 false
+SWAP_M2 true
+NewtCanvasAWT.attachNewtChild.2: size 500x268
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init ...
+LandscapeES2 init on Thread[main-Display-.macosx_nil-1-EDT-1,5,main]
+Chosen GLCapabilities: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/0, dbl, mono , hw, GLProfile[GL2/GL2.hw], offscr[fbo]]
+INIT GL IS: jogamp.opengl.gl4.GL4bcImpl
+GL_VENDOR: NVIDIA Corporation
+GL_RENDERER: NVIDIA GeForce 320M OpenGL Engine
+GL_VERSION: 2.1 NVIDIA-7.32.12
+GL GLSL: true, has-compiler-func: true, version 1.20, 1.20.0
+GL FBO: basic true, full true
+GL Profile: GLProfile[GL2/GL2.hw]
+GL Renderer Quirks:[NoOffscreenBitmap]
+GL:jogamp.opengl.gl4.GL4bcImpl@57ac3379, 2.1 (hardware) - 2.1 NVIDIA-7.32.12
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init FIN
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7f98910ac7d0
+Thread[AWT-EventQueue-0,6,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7f98910ac7d0
+XXX[1] TO 17 ms, lFrame0 110 ms, lFrameX 848 / 848 ~848.189 ms, finishGL 736 / 736 ~736.724 ms, waitGL 1 / 1 ~1.131 ms
+XXX[2] TO 17 ms, lFrame0 122 ms, lFrameX 211 / 1059 ~529.747 ms, finishGL 88 / 825 ~412.707 ms, waitGL 0 / 1 ~0.572 ms
+XXX[3] TO 17 ms, lFrame0 2 ms, lFrameX 100 / 1159 ~386.566 ms, finishGL 97 / 923 ~307.754 ms, waitGL 0 / 1 ~0.395 ms
+XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 1259 ~314.909 ms, finishGL 99 / 1022 ~255.589 ms, waitGL 0 / 1 ~0.299 ms
+XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 1359 ~271.82 ms, finishGL 98 / 1121 ~224.2 ms, waitGL 0 / 1 ~0.242 ms
+XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 1440 ~240.077 ms, finishGL 80 / 1201 ~200.259 ms, waitGL 0 / 1 ~0.203 ms
+XXX[7] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 1524 ~217.736 ms, finishGL 81 / 1283 ~183.315 ms, waitGL 0 / 1 ~0.176 ms
+XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1606 ~200.869 ms, finishGL 82 / 1365 ~170.676 ms, waitGL 0 / 1 ~0.156 ms
+XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 1705 ~189.545 ms, finishGL 98 / 1463 ~162.626 ms, waitGL 0 / 1 ~0.14 ms
+XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1788 ~178.844 ms, finishGL 81 / 1545 ~154.52 ms, waitGL 0 / 1 ~0.128 ms
+XXX[11] TO 17 ms, lFrame0 1 ms, lFrameX 78 / 1866 ~169.691 ms, finishGL 77 / 1622 ~147.48 ms, waitGL 0 / 1 ~0.118 ms
+XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 1970 ~164.238 ms, finishGL 103 / 1725 ~143.819 ms, waitGL 0 / 1 ~0.109 ms
+XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2052 ~157.921 ms, finishGL 81 / 1807 ~139.019 ms, waitGL 0 / 1 ~0.102 ms
+XXX[14] TO 17 ms, lFrame0 1 ms, lFrameX 77 / 2130 ~152.18 ms, finishGL 76 / 1883 ~134.53 ms, waitGL 0 / 1 ~0.096 ms
+XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 2235 ~149.003 ms, finishGL 104 / 1987 ~132.499 ms, waitGL 0 / 1 ~0.09 ms
+XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2317 ~144.869 ms, finishGL 82 / 2069 ~129.364 ms, waitGL 0 / 1 ~0.086 ms
+XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2393 ~140.812 ms, finishGL 74 / 2144 ~126.164 ms, waitGL 0 / 1 ~0.081 ms
+XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2501 ~138.947 ms, finishGL 106 / 2251 ~125.084 ms, waitGL 0 / 1 ~0.078 ms
+XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2584 ~136.019 ms, finishGL 82 / 2334 ~122.861 ms, waitGL 0 / 1 ~0.074 ms
+XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2659 ~132.991 ms, finishGL 74 / 2409 ~120.458 ms, waitGL 0 / 1 ~0.071 ms
+XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2767 ~131.792 ms, finishGL 107 / 2516 ~119.829 ms, waitGL 0 / 1 ~0.068 ms
+XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2850 ~129.57 ms, finishGL 82 / 2598 ~118.129 ms, waitGL 0 / 1 ~0.066 ms
+XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 2923 ~127.112 ms, finishGL 72 / 2671 ~116.144 ms, waitGL 0 / 1 ~0.064 ms
+XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 3028 ~126.189 ms, finishGL 104 / 2775 ~115.653 ms, waitGL 0 / 1 ~0.062 ms
+XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3111 ~124.449 ms, finishGL 82 / 2857 ~114.316 ms, waitGL 0 / 1 ~0.06 ms
+XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 3179 ~122.303 ms, finishGL 68 / 2925 ~112.537 ms, waitGL 0 / 1 ~0.058 ms
+XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 96 / 3276 ~121.334 ms, finishGL 95 / 3021 ~111.912 ms, waitGL 0 / 1 ~0.056 ms
+XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3358 ~119.931 ms, finishGL 81 / 3103 ~110.824 ms, waitGL 0 / 1 ~0.055 ms
+XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3425 ~118.108 ms, finishGL 66 / 3169 ~109.29 ms, waitGL 0 / 1 ~0.053 ms
+XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 3522 ~117.427 ms, finishGL 97 / 3266 ~108.885 ms, waitGL 0 / 1 ~0.052 ms
+XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3605 ~116.298 ms, finishGL 81 / 3348 ~108.018 ms, waitGL 0 / 1 ~0.051 ms
+XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3670 ~114.699 ms, finishGL 64 / 3413 ~106.659 ms, waitGL 0 / 1 ~0.05 ms
+XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3753 ~113.755 ms, finishGL 83 / 3496 ~105.943 ms, waitGL 0 / 1 ~0.049 ms
+XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3819 ~112.326 ms, finishGL 64 / 3560 ~104.731 ms, waitGL 0 / 1 ~0.047 ms
+XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 3882 ~110.923 ms, finishGL 62 / 3623 ~103.536 ms, waitGL 0 / 1 ~0.046 ms
+XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 3952 ~109.795 ms, finishGL 69 / 3693 ~102.601 ms, waitGL 0 / 1 ~0.046 ms
+XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4018 ~108.616 ms, finishGL 65 / 3759 ~101.602 ms, waitGL 0 / 1 ~0.045 ms
+XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4084 ~107.492 ms, finishGL 65 / 3824 ~100.649 ms, waitGL 0 / 1 ~0.044 ms
+XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4150 ~106.426 ms, finishGL 65 / 3890 ~99.745 ms, waitGL 0 / 1 ~0.043 ms
+XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4216 ~105.406 ms, finishGL 65 / 3955 ~98.88 ms, waitGL 0 / 1 ~0.042 ms
+XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4282 ~104.446 ms, finishGL 65 / 4020 ~98.069 ms, waitGL 0 / 1 ~0.042 ms
+XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4348 ~103.54 ms, finishGL 65 / 4086 ~97.305 ms, waitGL 0 / 1 ~0.041 ms
+XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4415 ~102.674 ms, finishGL 65 / 4152 ~96.568 ms, waitGL 0 / 1 ~0.04 ms
+XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4481 ~101.854 ms, finishGL 66 / 4218 ~95.875 ms, waitGL 0 / 1 ~0.04 ms
+XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4547 ~101.064 ms, finishGL 65 / 4284 ~95.207 ms, waitGL 0 / 1 ~0.039 ms
+XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4614 ~100.307 ms, finishGL 65 / 4349 ~94.563 ms, waitGL 0 / 1 ~0.039 ms
+XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4680 ~99.591 ms, finishGL 66 / 4416 ~93.958 ms, waitGL 0 / 1 ~0.038 ms
+XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4746 ~98.887 ms, finishGL 65 / 4481 ~93.363 ms, waitGL 0 / 1 ~0.038 ms
+XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4813 ~98.226 ms, finishGL 66 / 4547 ~92.806 ms, waitGL 0 / 1 ~0.037 ms
+XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4879 ~97.587 ms, finishGL 65 / 4613 ~92.262 ms, waitGL 0 / 1 ~0.037 ms
+XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4945 ~96.967 ms, finishGL 65 / 4678 ~91.737 ms, waitGL 0 / 1 ~0.037 ms
+XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5011 ~96.381 ms, finishGL 66 / 4744 ~91.244 ms, waitGL 0 / 1 ~0.036 ms
+XXX[53] TO 17 ms, lFrame0 9 ms, lFrameX 68 / 5080 ~95.852 ms, finishGL 58 / 4803 ~90.633 ms, waitGL 0 / 1 ~0.036 ms
+XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 5145 ~95.284 ms, finishGL 64 / 4868 ~90.153 ms, waitGL 0 / 1 ~0.035 ms
+XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5211 ~94.762 ms, finishGL 65 / 4934 ~89.712 ms, waitGL 0 / 1 ~0.035 ms
+XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 5276 ~94.225 ms, finishGL 64 / 4998 ~89.255 ms, waitGL 0 / 1 ~0.035 ms
+XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5342 ~93.732 ms, finishGL 65 / 5063 ~88.841 ms, waitGL 0 / 1 ~0.034 ms
+XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5410 ~93.277 ms, finishGL 66 / 5130 ~88.463 ms, waitGL 0 / 1 ~0.034 ms
+XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5477 ~92.831 ms, finishGL 66 / 5197 ~88.09 ms, waitGL 0 / 2 ~0.034 ms
+XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5543 ~92.388 ms, finishGL 65 / 5263 ~87.717 ms, waitGL 0 / 2 ~0.033 ms
+XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5609 ~91.963 ms, finishGL 65 / 5329 ~87.36 ms, waitGL 0 / 2 ~0.033 ms
+XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5676 ~91.562 ms, finishGL 66 / 5395 ~87.026 ms, waitGL 0 / 2 ~0.033 ms
+XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5743 ~91.161 ms, finishGL 65 / 5461 ~86.688 ms, waitGL 0 / 2 ~0.032 ms
+XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5809 ~90.78 ms, finishGL 66 / 5527 ~86.37 ms, waitGL 0 / 2 ~0.032 ms
+XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5877 ~90.417 ms, finishGL 66 / 5594 ~86.067 ms, waitGL 0 / 2 ~0.032 ms
+XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5944 ~90.064 ms, finishGL 66 / 5660 ~85.771 ms, waitGL 0 / 2 ~0.032 ms
+XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6010 ~89.705 ms, finishGL 65 / 5726 ~85.47 ms, waitGL 0 / 2 ~0.031 ms
+XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6077 ~89.37 ms, finishGL 66 / 5792 ~85.189 ms, waitGL 0 / 2 ~0.031 ms
+XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6144 ~89.049 ms, finishGL 66 / 5859 ~84.922 ms, waitGL 0 / 2 ~0.031 ms
+XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6210 ~88.723 ms, finishGL 65 / 5925 ~84.65 ms, waitGL 0 / 2 ~0.031 ms
+XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6277 ~88.41 ms, finishGL 65 / 5991 ~84.387 ms, waitGL 0 / 2 ~0.031 ms
+XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6343 ~88.105 ms, finishGL 65 / 6057 ~84.13 ms, waitGL 0 / 2 ~0.03 ms
+XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6409 ~87.8 ms, finishGL 65 / 6122 ~83.873 ms, waitGL 0 / 2 ~0.03 ms
+XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6475 ~87.502 ms, finishGL 65 / 6188 ~83.622 ms, waitGL 0 / 2 ~0.03 ms
+XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6540 ~87.209 ms, finishGL 64 / 6252 ~83.371 ms, waitGL 0 / 2 ~0.03 ms
+XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6606 ~86.932 ms, finishGL 65 / 6318 ~83.14 ms, waitGL 0 / 2 ~0.03 ms
+XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6674 ~86.678 ms, finishGL 66 / 6385 ~82.928 ms, waitGL 0 / 2 ~0.029 ms
+XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6740 ~86.422 ms, finishGL 66 / 6451 ~82.714 ms, waitGL 0 / 2 ~0.029 ms
+XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6807 ~86.17 ms, finishGL 65 / 6517 ~82.502 ms, waitGL 0 / 2 ~0.029 ms
+XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6874 ~85.928 ms, finishGL 66 / 6584 ~82.3 ms, waitGL 0 / 2 ~0.029 ms
+XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6941 ~85.692 ms, finishGL 66 / 6650 ~82.104 ms, waitGL 0 / 2 ~0.029 ms
+XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7008 ~85.471 ms, finishGL 67 / 6717 ~81.92 ms, waitGL 0 / 2 ~0.029 ms
+XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7075 ~85.242 ms, finishGL 65 / 6783 ~81.728 ms, waitGL 0 / 2 ~0.028 ms
+XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7141 ~85.019 ms, finishGL 66 / 6849 ~81.54 ms, waitGL 0 / 2 ~0.028 ms
+XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7208 ~84.805 ms, finishGL 66 / 6915 ~81.361 ms, waitGL 0 / 2 ~0.028 ms
+XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7275 ~84.596 ms, finishGL 66 / 6982 ~81.187 ms, waitGL 0 / 2 ~0.028 ms
+XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7341 ~84.384 ms, finishGL 65 / 7047 ~81.009 ms, waitGL 0 / 2 ~0.028 ms
+XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7407 ~84.179 ms, finishGL 65 / 7113 ~80.836 ms, waitGL 0 / 2 ~0.028 ms
+XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7474 ~83.98 ms, finishGL 65 / 7179 ~80.669 ms, waitGL 0 / 2 ~0.028 ms
+XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7540 ~83.784 ms, finishGL 65 / 7245 ~80.504 ms, waitGL 0 / 2 ~0.028 ms
+XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7607 ~83.599 ms, finishGL 66 / 7311 ~80.348 ms, waitGL 0 / 2 ~0.027 ms
+XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7673 ~83.407 ms, finishGL 65 / 7377 ~80.186 ms, waitGL 0 / 2 ~0.027 ms
+XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7740 ~83.226 ms, finishGL 66 / 7443 ~80.035 ms, waitGL 0 / 2 ~0.027 ms
+XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7806 ~83.051 ms, finishGL 66 / 7509 ~79.888 ms, waitGL 0 / 2 ~0.027 ms
+XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7872 ~82.873 ms, finishGL 65 / 7575 ~79.738 ms, waitGL 0 / 2 ~0.027 ms
+XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7938 ~82.695 ms, finishGL 65 / 7640 ~79.588 ms, waitGL 0 / 2 ~0.027 ms
+XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8005 ~82.526 ms, finishGL 65 / 7706 ~79.446 ms, waitGL 0 / 2 ~0.027 ms
+XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8071 ~82.359 ms, finishGL 65 / 7771 ~79.305 ms, waitGL 0 / 2 ~0.027 ms
+XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8137 ~82.197 ms, finishGL 65 / 7837 ~79.169 ms, waitGL 0 / 2 ~0.026 ms
+XXX[1] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 66 ~66.612 ms, finishGL 66 / 66 ~66.069 ms, waitGL 0 / 0 ~0.017 ms
+XXX[2] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 131 ~65.969 ms, finishGL 64 / 130 ~65.483 ms, waitGL 0 / 0 ~0.018 ms
+XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 198 ~66.176 ms, finishGL 66 / 197 ~65.684 ms, waitGL 0 / 0 ~0.017 ms
+XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 265 ~66.274 ms, finishGL 66 / 263 ~65.784 ms, waitGL 0 / 0 ~0.016 ms
+XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 331 ~66.257 ms, finishGL 65 / 328 ~65.765 ms, waitGL 0 / 0 ~0.016 ms
+XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 397 ~66.228 ms, finishGL 65 / 394 ~65.727 ms, waitGL 0 / 0 ~0.016 ms
+XXX[7] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 464 ~66.289 ms, finishGL 66 / 460 ~65.791 ms, waitGL 0 / 0 ~0.015 ms
+XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 531 ~66.42 ms, finishGL 66 / 527 ~65.919 ms, waitGL 0 / 0 ~0.015 ms
+XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 598 ~66.459 ms, finishGL 66 / 593 ~65.961 ms, waitGL 0 / 0 ~0.016 ms
+XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 666 ~66.638 ms, finishGL 67 / 661 ~66.141 ms, waitGL 0 / 0 ~0.016 ms
+XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 732 ~66.562 ms, finishGL 65 / 726 ~66.062 ms, waitGL 0 / 0 ~0.016 ms
+XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 798 ~66.515 ms, finishGL 65 / 792 ~66.004 ms, waitGL 0 / 0 ~0.016 ms
+XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 863 ~66.433 ms, finishGL 64 / 856 ~65.919 ms, waitGL 0 / 0 ~0.016 ms
+XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 930 ~66.441 ms, finishGL 66 / 923 ~65.929 ms, waitGL 0 / 0 ~0.016 ms
+XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 996 ~66.432 ms, finishGL 65 / 988 ~65.92 ms, waitGL 0 / 0 ~0.016 ms
+XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1062 ~66.436 ms, finishGL 66 / 1054 ~65.926 ms, waitGL 0 / 0 ~0.015 ms
+XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1129 ~66.447 ms, finishGL 66 / 1120 ~65.94 ms, waitGL 0 / 0 ~0.015 ms
+XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1196 ~66.495 ms, finishGL 66 / 1187 ~65.989 ms, waitGL 0 / 0 ~0.015 ms
+XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1263 ~66.485 ms, finishGL 65 / 1253 ~65.979 ms, waitGL 0 / 0 ~0.015 ms
+FrameCount: 120 - FrameRate: 15.0
+XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1330 ~66.512 ms, finishGL 66 / 1320 ~66.002 ms, waitGL 0 / 0 ~0.015 ms
+XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1397 ~66.528 ms, finishGL 66 / 1386 ~66.019 ms, waitGL 0 / 0 ~0.015 ms
+XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1464 ~66.577 ms, finishGL 67 / 1453 ~66.069 ms, waitGL 0 / 0 ~0.015 ms
+XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1531 ~66.581 ms, finishGL 66 / 1519 ~66.074 ms, waitGL 0 / 0 ~0.015 ms
+XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1598 ~66.589 ms, finishGL 66 / 1585 ~66.082 ms, waitGL 0 / 0 ~0.015 ms
+XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1665 ~66.601 ms, finishGL 66 / 1652 ~66.095 ms, waitGL 0 / 0 ~0.015 ms
+XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1732 ~66.617 ms, finishGL 66 / 1718 ~66.112 ms, waitGL 0 / 0 ~0.015 ms
+XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1798 ~66.607 ms, finishGL 65 / 1784 ~66.103 ms, waitGL 0 / 0 ~0.016 ms
+XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1864 ~66.599 ms, finishGL 65 / 1850 ~66.095 ms, waitGL 0 / 0 ~0.016 ms
+XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1931 ~66.611 ms, finishGL 66 / 1917 ~66.107 ms, waitGL 0 / 0 ~0.016 ms
+XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1997 ~66.589 ms, finishGL 65 / 1982 ~66.088 ms, waitGL 0 / 0 ~0.016 ms
+XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2063 ~66.572 ms, finishGL 65 / 2048 ~66.074 ms, waitGL 0 / 0 ~0.015 ms
+XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2130 ~66.576 ms, finishGL 66 / 2114 ~66.077 ms, waitGL 0 / 0 ~0.015 ms
+XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2196 ~66.568 ms, finishGL 65 / 2180 ~66.069 ms, waitGL 0 / 0 ~0.016 ms
+XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2263 ~66.587 ms, finishGL 66 / 2247 ~66.089 ms, waitGL 0 / 0 ~0.015 ms
+XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2330 ~66.58 ms, finishGL 65 / 2312 ~66.082 ms, waitGL 0 / 0 ~0.015 ms
+XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2396 ~66.574 ms, finishGL 65 / 2378 ~66.077 ms, waitGL 0 / 0 ~0.015 ms
+XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2463 ~66.57 ms, finishGL 65 / 2444 ~66.07 ms, waitGL 0 / 0 ~0.015 ms
+XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2530 ~66.579 ms, finishGL 66 / 2510 ~66.078 ms, waitGL 0 / 0 ~0.015 ms
+XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2596 ~66.572 ms, finishGL 65 / 2576 ~66.072 ms, waitGL 0 / 0 ~0.015 ms
+XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2662 ~66.566 ms, finishGL 65 / 2642 ~66.062 ms, waitGL 0 / 0 ~0.016 ms
+XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2728 ~66.555 ms, finishGL 65 / 2708 ~66.052 ms, waitGL 0 / 0 ~0.016 ms
+XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2795 ~66.566 ms, finishGL 66 / 2774 ~66.063 ms, waitGL 0 / 0 ~0.016 ms
+XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2861 ~66.554 ms, finishGL 65 / 2840 ~66.052 ms, waitGL 0 / 0 ~0.016 ms
+XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2927 ~66.536 ms, finishGL 65 / 2905 ~66.035 ms, waitGL 0 / 0 ~0.015 ms
+XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2992 ~66.506 ms, finishGL 64 / 2970 ~66.001 ms, waitGL 0 / 0 ~0.016 ms
+XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3057 ~66.473 ms, finishGL 64 / 3034 ~65.966 ms, waitGL 0 / 0 ~0.016 ms
+XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3122 ~66.425 ms, finishGL 63 / 3098 ~65.918 ms, waitGL 0 / 0 ~0.016 ms
+XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 3185 ~66.364 ms, finishGL 63 / 3161 ~65.858 ms, waitGL 0 / 0 ~0.016 ms
+XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 3247 ~66.267 ms, finishGL 61 / 3222 ~65.763 ms, waitGL 0 / 0 ~0.016 ms
+XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 3309 ~66.196 ms, finishGL 62 / 3284 ~65.693 ms, waitGL 0 / 0 ~0.016 ms
+XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 47 / 3357 ~65.831 ms, finishGL 47 / 3331 ~65.329 ms, waitGL 0 / 0 ~0.016 ms
+XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3406 ~65.512 ms, finishGL 48 / 3380 ~65.011 ms, waitGL 0 / 0 ~0.016 ms
+XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3455 ~65.197 ms, finishGL 48 / 3428 ~64.697 ms, waitGL 0 / 0 ~0.016 ms
+XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3504 ~64.902 ms, finishGL 48 / 3477 ~64.403 ms, waitGL 0 / 0 ~0.016 ms
+XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3553 ~64.612 ms, finishGL 48 / 3526 ~64.112 ms, waitGL 0 / 0 ~0.016 ms
+XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3602 ~64.335 ms, finishGL 48 / 3574 ~63.837 ms, waitGL 0 / 0 ~0.016 ms
+XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3652 ~64.083 ms, finishGL 49 / 3624 ~63.583 ms, waitGL 0 / 0 ~0.016 ms
+XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3701 ~63.821 ms, finishGL 48 / 3672 ~63.322 ms, waitGL 0 / 0 ~0.016 ms
+XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3751 ~63.583 ms, finishGL 49 / 3722 ~63.084 ms, waitGL 0 / 0 ~0.016 ms
+XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3800 ~63.342 ms, finishGL 48 / 3770 ~62.842 ms, waitGL 0 / 0 ~0.016 ms
+XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3849 ~63.111 ms, finishGL 48 / 3819 ~62.611 ms, waitGL 0 / 1 ~0.016 ms
+XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3898 ~62.875 ms, finishGL 48 / 3867 ~62.375 ms, waitGL 0 / 1 ~0.016 ms
+XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3947 ~62.657 ms, finishGL 48 / 3915 ~62.158 ms, waitGL 0 / 1 ~0.016 ms
+XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3996 ~62.439 ms, finishGL 48 / 3964 ~61.94 ms, waitGL 0 / 1 ~0.016 ms
+XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4044 ~62.229 ms, finishGL 48 / 4012 ~61.729 ms, waitGL 0 / 1 ~0.016 ms
+XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4093 ~62.018 ms, finishGL 47 / 4060 ~61.519 ms, waitGL 0 / 1 ~0.016 ms
+XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4141 ~61.82 ms, finishGL 48 / 4108 ~61.319 ms, waitGL 0 / 1 ~0.016 ms
+XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 29 / 4171 ~61.351 ms, finishGL 29 / 4137 ~60.851 ms, waitGL 0 / 1 ~0.016 ms
+XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 4223 ~61.207 ms, finishGL 50 / 4188 ~60.706 ms, waitGL 0 / 1 ~0.016 ms
+XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4255 ~60.791 ms, finishGL 31 / 4220 ~60.289 ms, waitGL 0 / 1 ~0.016 ms
+XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 28 / 4283 ~60.33 ms, finishGL 27 / 4247 ~59.828 ms, waitGL 0 / 1 ~0.016 ms
+XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 4337 ~60.239 ms, finishGL 53 / 4301 ~59.736 ms, waitGL 0 / 1 ~0.016 ms
+XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4369 ~59.853 ms, finishGL 31 / 4332 ~59.35 ms, waitGL 0 / 1 ~0.016 ms
+XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 26 / 4395 ~59.4 ms, finishGL 25 / 4358 ~58.895 ms, waitGL 0 / 1 ~0.016 ms
+XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 39 / 4434 ~59.13 ms, finishGL 38 / 4396 ~58.625 ms, waitGL 0 / 1 ~0.016 ms
+XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4483 ~58.99 ms, finishGL 47 / 4444 ~58.481 ms, waitGL 0 / 1 ~0.016 ms
+XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 31 / 4515 ~58.637 ms, finishGL 31 / 4476 ~58.129 ms, waitGL 0 / 1 ~0.016 ms
+XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 22 / 4538 ~58.18 ms, finishGL 22 / 4498 ~57.673 ms, waitGL 0 / 1 ~0.016 ms
+XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 26 / 4564 ~57.78 ms, finishGL 26 / 4524 ~57.273 ms, waitGL 0 / 1 ~0.016 ms
+XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 22 / 4587 ~57.343 ms, finishGL 22 / 4547 ~56.84 ms, waitGL 0 / 1 ~0.016 ms
+XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 4631 ~57.178 ms, finishGL 43 / 4590 ~56.675 ms, waitGL 0 / 1 ~0.016 ms
+XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4664 ~56.885 ms, finishGL 32 / 4623 ~56.382 ms, waitGL 0 / 1 ~0.016 ms
+XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4688 ~56.487 ms, finishGL 23 / 4646 ~55.982 ms, waitGL 0 / 1 ~0.016 ms
+XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 42 / 4730 ~56.317 ms, finishGL 41 / 4688 ~55.812 ms, waitGL 0 / 1 ~0.016 ms
+XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 36 / 4766 ~56.079 ms, finishGL 35 / 4723 ~55.575 ms, waitGL 0 / 1 ~0.016 ms
+XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 30 / 4797 ~55.783 ms, finishGL 29 / 4753 ~55.275 ms, waitGL 0 / 1 ~0.016 ms
+XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 4856 ~55.824 ms, finishGL 58 / 4812 ~55.316 ms, waitGL 0 / 1 ~0.016 ms
+XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 55 / 4912 ~55.82 ms, finishGL 55 / 4867 ~55.313 ms, waitGL 0 / 1 ~0.016 ms
+XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 41 / 4953 ~55.662 ms, finishGL 41 / 4908 ~55.153 ms, waitGL 0 / 1 ~0.016 ms
+XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 5015 ~55.723 ms, finishGL 60 / 4969 ~55.211 ms, waitGL 0 / 1 ~0.016 ms
+XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 5066 ~55.677 ms, finishGL 51 / 5020 ~55.166 ms, waitGL 0 / 1 ~0.016 ms
+XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 42 / 5109 ~55.532 ms, finishGL 41 / 5061 ~55.021 ms, waitGL 0 / 1 ~0.016 ms
+XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 5183 ~55.732 ms, finishGL 73 / 5135 ~55.222 ms, waitGL 0 / 1 ~0.016 ms
+XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5233 ~55.671 ms, finishGL 49 / 5185 ~55.161 ms, waitGL 0 / 1 ~0.016 ms
+XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5283 ~55.613 ms, finishGL 49 / 5234 ~55.103 ms, waitGL 0 / 1 ~0.016 ms
+XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 5326 ~55.486 ms, finishGL 42 / 5277 ~54.974 ms, waitGL 0 / 1 ~0.016 ms
+XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5399 ~55.667 ms, finishGL 72 / 5350 ~55.155 ms, waitGL 0 / 1 ~0.016 ms
+XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5449 ~55.61 ms, finishGL 49 / 5399 ~55.1 ms, waitGL 0 / 1 ~0.016 ms
+XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5500 ~55.56 ms, finishGL 50 / 5450 ~55.051 ms, waitGL 0 / 1 ~0.016 ms
+XXX[100] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5550 ~55.5 ms, finishGL 49 / 5499 ~54.991 ms, waitGL 0 / 1 ~0.016 ms
+XXX[101] TO 17 ms, lFrame0 0 ms, lFrameX 45 / 5595 ~55.402 ms, finishGL 45 / 5544 ~54.895 ms, waitGL 0 / 1 ~0.016 ms
+XXX[102] TO 17 ms, lFrame0 0 ms, lFrameX 56 / 5652 ~55.411 ms, finishGL 55 / 5600 ~54.905 ms, waitGL 0 / 1 ~0.016 ms
+XXX[103] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 5704 ~55.379 ms, finishGL 51 / 5651 ~54.873 ms, waitGL 0 / 1 ~0.016 ms
+XXX[104] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5771 ~55.496 ms, finishGL 67 / 5719 ~54.99 ms, waitGL 0 / 1 ~0.016 ms
+XXX[105] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5838 ~55.609 ms, finishGL 66 / 5785 ~55.103 ms, waitGL 0 / 1 ~0.016 ms
+XXX[106] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 5907 ~55.727 ms, finishGL 67 / 5853 ~55.221 ms, waitGL 0 / 1 ~0.016 ms
+XXX[107] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 5975 ~55.846 ms, finishGL 67 / 5921 ~55.34 ms, waitGL 0 / 1 ~0.016 ms
+XXX[108] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 6046 ~55.983 ms, finishGL 70 / 5991 ~55.478 ms, waitGL 0 / 1 ~0.016 ms
+XXX[109] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 6115 ~56.107 ms, finishGL 69 / 6060 ~55.602 ms, waitGL 0 / 1 ~0.016 ms
+XXX[110] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6182 ~56.207 ms, finishGL 66 / 6127 ~55.703 ms, waitGL 0 / 1 ~0.016 ms
+XXX[111] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6249 ~56.303 ms, finishGL 66 / 6193 ~55.8 ms, waitGL 0 / 1 ~0.016 ms
+XXX[112] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6317 ~56.405 ms, finishGL 67 / 6260 ~55.901 ms, waitGL 0 / 1 ~0.016 ms
+XXX[113] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6383 ~56.49 ms, finishGL 65 / 6326 ~55.986 ms, waitGL 0 / 1 ~0.016 ms
+XXX[114] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6450 ~56.579 ms, finishGL 66 / 6392 ~56.075 ms, waitGL 0 / 1 ~0.016 ms
+XXX[115] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6517 ~56.673 ms, finishGL 66 / 6459 ~56.169 ms, waitGL 0 / 1 ~0.016 ms
+XXX[116] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6584 ~56.761 ms, finishGL 66 / 6525 ~56.257 ms, waitGL 0 / 1 ~0.016 ms
+XXX[117] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6651 ~56.848 ms, finishGL 66 / 6592 ~56.344 ms, waitGL 0 / 1 ~0.016 ms
+XXX[118] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 6736 ~57.085 ms, finishGL 84 / 6676 ~56.581 ms, waitGL 0 / 1 ~0.016 ms
+XXX[119] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 6818 ~57.298 ms, finishGL 81 / 6758 ~56.794 ms, waitGL 0 / 1 ~0.016 ms
+XXX[120] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 6884 ~57.372 ms, finishGL 65 / 6823 ~56.863 ms, waitGL 0 / 1 ~0.015 ms
+XXX[121] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 6985 ~57.731 ms, finishGL 100 / 6923 ~57.222 ms, waitGL 0 / 1 ~0.015 ms
+XXX[122] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7068 ~57.939 ms, finishGL 82 / 7006 ~57.431 ms, waitGL 0 / 1 ~0.015 ms
+XXX[123] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7136 ~58.021 ms, finishGL 67 / 7074 ~57.513 ms, waitGL 0 / 1 ~0.015 ms
+XXX[124] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 7221 ~58.24 ms, finishGL 84 / 7158 ~57.732 ms, waitGL 0 / 1 ~0.015 ms
+XXX[125] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 7307 ~58.46 ms, finishGL 85 / 7244 ~57.952 ms, waitGL 0 / 1 ~0.015 ms
+XXX[126] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7391 ~58.666 ms, finishGL 83 / 7327 ~58.155 ms, waitGL 0 / 2 ~0.015 ms
+XXX[127] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7476 ~58.872 ms, finishGL 84 / 7411 ~58.361 ms, waitGL 0 / 2 ~0.015 ms
+XXX[128] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7561 ~59.076 ms, finishGL 84 / 7496 ~58.565 ms, waitGL 0 / 2 ~0.015 ms
+XXX[129] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7644 ~59.26 ms, finishGL 82 / 7578 ~58.749 ms, waitGL 0 / 2 ~0.016 ms
+XXX[130] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 7724 ~59.419 ms, finishGL 79 / 7658 ~58.909 ms, waitGL 0 / 2 ~0.016 ms
+2013-06-17 03:36:23.407 java[65080:5f07] Persistent UI failed to open file file://localhost/Users/jogamp/Library/Saved%20Application%20State/com.apple.javajdk16.cmd.savedState/window_1.data: Operation not permitted (1)
+XXX[131] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 7805 ~59.58 ms, finishGL 80 / 7738 ~59.071 ms, waitGL 0 / 2 ~0.016 ms
+XXX[132] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7886 ~59.749 ms, finishGL 81 / 7819 ~59.239 ms, waitGL 0 / 2 ~0.016 ms
+XXX[133] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7968 ~59.913 ms, finishGL 81 / 7900 ~59.404 ms, waitGL 0 / 2 ~0.016 ms
+XXX[134] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 8049 ~60.074 ms, finishGL 80 / 7981 ~59.565 ms, waitGL 0 / 2 ~0.016 ms
+XXX[135] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8132 ~60.24 ms, finishGL 82 / 8063 ~59.731 ms, waitGL 0 / 2 ~0.016 ms
+XXX[136] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8214 ~60.404 ms, finishGL 82 / 8145 ~59.895 ms, waitGL 0 / 2 ~0.016 ms
+XXX[137] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8298 ~60.57 ms, finishGL 82 / 8228 ~60.061 ms, waitGL 0 / 2 ~0.016 ms
+XXX[138] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 8364 ~60.612 ms, finishGL 64 / 8293 ~60.097 ms, waitGL 0 / 2 ~0.016 ms
+XXX[139] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 8463 ~60.888 ms, finishGL 98 / 8391 ~60.373 ms, waitGL 0 / 2 ~0.016 ms
+FrameCount: 240 - FrameRate: 13.0
+XXX[140] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8529 ~60.926 ms, finishGL 65 / 8457 ~60.41 ms, waitGL 0 / 2 ~0.015 ms
+XXX[141] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 8593 ~60.949 ms, finishGL 63 / 8520 ~60.43 ms, waitGL 0 / 2 ~0.015 ms
+XXX[142] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 8679 ~61.12 ms, finishGL 84 / 8605 ~60.601 ms, waitGL 0 / 2 ~0.015 ms
+XXX[143] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8745 ~61.156 ms, finishGL 65 / 8671 ~60.638 ms, waitGL 0 / 2 ~0.015 ms
+XXX[144] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 8807 ~61.166 ms, finishGL 62 / 8733 ~60.648 ms, waitGL 0 / 2 ~0.015 ms
+XXX[145] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 8878 ~61.23 ms, finishGL 69 / 8803 ~60.712 ms, waitGL 0 / 2 ~0.015 ms
+XXX[146] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8944 ~61.263 ms, finishGL 65 / 8868 ~60.745 ms, waitGL 0 / 2 ~0.015 ms
+XXX[147] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9010 ~61.293 ms, finishGL 65 / 8934 ~60.776 ms, waitGL 0 / 2 ~0.015 ms
+XXX[148] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9076 ~61.329 ms, finishGL 65 / 9000 ~60.811 ms, waitGL 0 / 2 ~0.015 ms
+XXX[149] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9143 ~61.365 ms, finishGL 66 / 9066 ~60.847 ms, waitGL 0 / 2 ~0.015 ms
+XXX[150] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9208 ~61.393 ms, finishGL 65 / 9131 ~60.875 ms, waitGL 0 / 2 ~0.015 ms
+XXX[151] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9276 ~61.43 ms, finishGL 66 / 9197 ~60.913 ms, waitGL 0 / 2 ~0.015 ms
+XXX[152] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9341 ~61.46 ms, finishGL 65 / 9263 ~60.943 ms, waitGL 0 / 2 ~0.015 ms
+XXX[153] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9409 ~61.497 ms, finishGL 66 / 9330 ~60.981 ms, waitGL 0 / 2 ~0.015 ms
+XXX[154] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9475 ~61.529 ms, finishGL 65 / 9396 ~61.013 ms, waitGL 0 / 2 ~0.015 ms
+XXX[155] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9541 ~61.555 ms, finishGL 65 / 9461 ~61.039 ms, waitGL 0 / 2 ~0.015 ms
+XXX[156] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9608 ~61.595 ms, finishGL 67 / 9528 ~61.08 ms, waitGL 0 / 2 ~0.015 ms
+XXX[157] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9674 ~61.623 ms, finishGL 65 / 9594 ~61.109 ms, waitGL 0 / 2 ~0.015 ms
+XXX[158] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9742 ~61.659 ms, finishGL 66 / 9660 ~61.144 ms, waitGL 0 / 2 ~0.015 ms
+XXX[159] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9808 ~61.691 ms, finishGL 66 / 9727 ~61.176 ms, waitGL 0 / 2 ~0.015 ms
+XXX[160] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9874 ~61.718 ms, finishGL 65 / 9792 ~61.204 ms, waitGL 0 / 2 ~0.015 ms
+XXX[161] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9940 ~61.743 ms, finishGL 65 / 9858 ~61.229 ms, waitGL 0 / 2 ~0.015 ms
+XXX[162] TO 17 ms, lFrame0 7 ms, lFrameX 68 / 10009 ~61.788 ms, finishGL 61 / 9919 ~61.228 ms, waitGL 0 / 2 ~0.015 ms
+XXX[163] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 10071 ~61.788 ms, finishGL 61 / 9980 ~61.229 ms, waitGL 0 / 2 ~0.015 ms
+XXX[164] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10137 ~61.813 ms, finishGL 65 / 10045 ~61.255 ms, waitGL 0 / 2 ~0.015 ms
+XXX[165] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10203 ~61.841 ms, finishGL 65 / 10111 ~61.283 ms, waitGL 0 / 2 ~0.015 ms
+XXX[166] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10269 ~61.866 ms, finishGL 65 / 10177 ~61.308 ms, waitGL 0 / 2 ~0.015 ms
+XXX[167] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10336 ~61.893 ms, finishGL 65 / 10243 ~61.336 ms, waitGL 0 / 2 ~0.015 ms
+XXX[168] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10402 ~61.918 ms, finishGL 65 / 10308 ~61.362 ms, waitGL 0 / 2 ~0.015 ms
+XXX[169] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10469 ~61.949 ms, finishGL 66 / 10375 ~61.394 ms, waitGL 0 / 2 ~0.015 ms
+XXX[170] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10535 ~61.974 ms, finishGL 65 / 10441 ~61.419 ms, waitGL 0 / 2 ~0.015 ms
+XXX[171] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10602 ~62.005 ms, finishGL 66 / 10508 ~61.45 ms, waitGL 0 / 2 ~0.015 ms
+XXX[172] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10668 ~62.027 ms, finishGL 65 / 10573 ~61.473 ms, waitGL 0 / 2 ~0.015 ms
+XXX[173] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10736 ~62.058 ms, finishGL 66 / 10640 ~61.505 ms, waitGL 0 / 2 ~0.015 ms
+XXX[174] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10803 ~62.087 ms, finishGL 66 / 10706 ~61.534 ms, waitGL 0 / 2 ~0.015 ms
+XXX[175] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10869 ~62.114 ms, finishGL 66 / 10773 ~61.561 ms, waitGL 0 / 2 ~0.015 ms
+XXX[176] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10935 ~62.135 ms, finishGL 65 / 10838 ~61.583 ms, waitGL 0 / 2 ~0.015 ms
+XXX[177] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11002 ~62.163 ms, finishGL 66 / 10905 ~61.611 ms, waitGL 0 / 2 ~0.016 ms
+XXX[178] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11070 ~62.193 ms, finishGL 66 / 10972 ~61.641 ms, waitGL 0 / 2 ~0.016 ms
+XXX[179] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11137 ~62.222 ms, finishGL 66 / 11038 ~61.67 ms, waitGL 0 / 2 ~0.016 ms
+XXX[180] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11205 ~62.254 ms, finishGL 67 / 11106 ~61.701 ms, waitGL 0 / 2 ~0.016 ms
+XXX[181] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11273 ~62.284 ms, finishGL 67 / 11173 ~61.732 ms, waitGL 0 / 2 ~0.016 ms
+XXX[182] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11340 ~62.31 ms, finishGL 66 / 11240 ~61.758 ms, waitGL 0 / 2 ~0.016 ms
+XXX[183] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11407 ~62.334 ms, finishGL 66 / 11306 ~61.783 ms, waitGL 0 / 2 ~0.016 ms
+XXX[184] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 11490 ~62.446 ms, finishGL 82 / 11388 ~61.895 ms, waitGL 0 / 2 ~0.016 ms
+XXX[185] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 11558 ~62.479 ms, finishGL 67 / 11456 ~61.928 ms, waitGL 0 / 2 ~0.016 ms
+XXX[186] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 11644 ~62.607 ms, finishGL 85 / 11542 ~62.056 ms, waitGL 0 / 2 ~0.016 ms
+XXX[187] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11730 ~62.727 ms, finishGL 84 / 11627 ~62.177 ms, waitGL 0 / 2 ~0.016 ms
+XXX[188] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11815 ~62.849 ms, finishGL 85 / 11712 ~62.299 ms, waitGL 0 / 3 ~0.016 ms
+XXX[189] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11901 ~62.97 ms, finishGL 85 / 11797 ~62.421 ms, waitGL 0 / 3 ~0.016 ms
+XXX[190] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11986 ~63.085 ms, finishGL 84 / 11881 ~62.535 ms, waitGL 0 / 3 ~0.016 ms
+XXX[191] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12070 ~63.197 ms, finishGL 84 / 11965 ~62.648 ms, waitGL 0 / 3 ~0.016 ms
+XXX[192] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12154 ~63.303 ms, finishGL 83 / 12048 ~62.755 ms, waitGL 0 / 3 ~0.016 ms
+XXX[193] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12238 ~63.411 ms, finishGL 83 / 12132 ~62.863 ms, waitGL 0 / 3 ~0.016 ms
+XXX[194] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12320 ~63.509 ms, finishGL 81 / 12214 ~62.961 ms, waitGL 0 / 3 ~0.016 ms
+XXX[195] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12405 ~63.617 ms, finishGL 84 / 12298 ~63.07 ms, waitGL 0 / 3 ~0.016 ms
+XXX[196] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12505 ~63.801 ms, finishGL 99 / 12397 ~63.254 ms, waitGL 0 / 3 ~0.016 ms
+XXX[197] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12604 ~63.981 ms, finishGL 98 / 12496 ~63.434 ms, waitGL 0 / 3 ~0.016 ms
+XXX[198] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 12685 ~64.067 ms, finishGL 80 / 12576 ~63.52 ms, waitGL 0 / 3 ~0.016 ms
+XXX[199] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12767 ~64.16 ms, finishGL 82 / 12659 ~63.613 ms, waitGL 0 / 3 ~0.016 ms
+XXX[200] TO 17 ms, lFrame0 3 ms, lFrameX 80 / 12848 ~64.243 ms, finishGL 77 / 12736 ~63.682 ms, waitGL 0 / 3 ~0.016 ms
+XXX[201] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 12927 ~64.317 ms, finishGL 78 / 12814 ~63.754 ms, waitGL 0 / 3 ~0.016 ms
+XXX[202] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 13033 ~64.52 ms, finishGL 104 / 12919 ~63.958 ms, waitGL 0 / 3 ~0.016 ms
+XXX[203] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13115 ~64.608 ms, finishGL 81 / 13001 ~64.046 ms, waitGL 0 / 3 ~0.016 ms
+XXX[204] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 13192 ~64.67 ms, finishGL 76 / 13077 ~64.107 ms, waitGL 0 / 3 ~0.016 ms
+XXX[205] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 13298 ~64.869 ms, finishGL 104 / 13182 ~64.306 ms, waitGL 0 / 3 ~0.016 ms
+XXX[206] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13380 ~64.952 ms, finishGL 81 / 13264 ~64.39 ms, waitGL 0 / 3 ~0.016 ms
+XXX[207] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 13455 ~65.0 ms, finishGL 74 / 13338 ~64.437 ms, waitGL 0 / 3 ~0.016 ms
+XXX[208] TO 17 ms, lFrame0 0 ms, lFrameX 106 / 13561 ~65.198 ms, finishGL 105 / 13444 ~64.634 ms, waitGL 0 / 3 ~0.016 ms
+XXX[209] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13642 ~65.276 ms, finishGL 81 / 13525 ~64.713 ms, waitGL 0 / 3 ~0.016 ms
+XXX[210] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 13713 ~65.303 ms, finishGL 70 / 13595 ~64.74 ms, waitGL 0 / 3 ~0.016 ms
+XXX[211] TO 17 ms, lFrame0 0 ms, lFrameX 92 / 13806 ~65.434 ms, finishGL 92 / 13687 ~64.87 ms, waitGL 0 / 3 ~0.015 ms
+XXX[212] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13888 ~65.509 ms, finishGL 81 / 13768 ~64.947 ms, waitGL 0 / 3 ~0.015 ms
+XXX[213] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 13954 ~65.514 ms, finishGL 65 / 13834 ~64.95 ms, waitGL 0 / 3 ~0.016 ms
+XXX[214] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 14053 ~65.668 ms, finishGL 97 / 13932 ~65.104 ms, waitGL 0 / 3 ~0.016 ms
+XXX[215] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 14134 ~65.744 ms, finishGL 81 / 14013 ~65.18 ms, waitGL 0 / 3 ~0.015 ms
+XXX[216] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 14198 ~65.731 ms, finishGL 62 / 14076 ~65.167 ms, waitGL 0 / 3 ~0.015 ms
+XXX[217] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 14285 ~65.83 ms, finishGL 86 / 14162 ~65.266 ms, waitGL 0 / 3 ~0.015 ms
+XXX[218] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 14351 ~65.833 ms, finishGL 65 / 14228 ~65.269 ms, waitGL 0 / 3 ~0.016 ms
+XXX[219] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14418 ~65.839 ms, finishGL 66 / 14295 ~65.274 ms, waitGL 0 / 3 ~0.016 ms
+XXX[220] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 14506 ~65.938 ms, finishGL 86 / 14382 ~65.373 ms, waitGL 0 / 3 ~0.015 ms
+XXX[221] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14592 ~66.028 ms, finishGL 85 / 14467 ~65.463 ms, waitGL 0 / 3 ~0.015 ms
+XXX[222] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 14667 ~66.069 ms, finishGL 74 / 14541 ~65.503 ms, waitGL 0 / 3 ~0.015 ms
+XXX[223] TO 17 ms, lFrame0 0 ms, lFrameX 95 / 14763 ~66.203 ms, finishGL 95 / 14636 ~65.636 ms, waitGL 0 / 3 ~0.015 ms
+XXX[224] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14847 ~66.282 ms, finishGL 83 / 14719 ~65.714 ms, waitGL 0 / 3 ~0.015 ms
+XXX[225] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 14924 ~66.331 ms, finishGL 76 / 14796 ~65.762 ms, waitGL 0 / 3 ~0.015 ms
+XXX[226] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 15029 ~66.503 ms, finishGL 104 / 14901 ~65.934 ms, waitGL 0 / 3 ~0.015 ms
+XXX[227] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15112 ~66.574 ms, finishGL 82 / 14983 ~66.006 ms, waitGL 0 / 3 ~0.015 ms
+XXX[228] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 15187 ~66.613 ms, finishGL 74 / 15058 ~66.044 ms, waitGL 0 / 3 ~0.015 ms
+XXX[229] TO 17 ms, lFrame0 0 ms, lFrameX 106 / 15294 ~66.787 ms, finishGL 106 / 15164 ~66.218 ms, waitGL 0 / 3 ~0.015 ms
+XXX[230] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15376 ~66.853 ms, finishGL 81 / 15245 ~66.285 ms, waitGL 0 / 3 ~0.015 ms
+XXX[231] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 15449 ~66.88 ms, finishGL 72 / 15317 ~66.311 ms, waitGL 0 / 3 ~0.015 ms
+XXX[232] TO 17 ms, lFrame0 0 ms, lFrameX 91 / 15540 ~66.985 ms, finishGL 90 / 15408 ~66.416 ms, waitGL 0 / 3 ~0.015 ms
+XXX[233] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15622 ~67.047 ms, finishGL 80 / 15489 ~66.478 ms, waitGL 0 / 3 ~0.015 ms
+XXX[234] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 15690 ~67.053 ms, finishGL 67 / 15556 ~66.482 ms, waitGL 0 / 3 ~0.015 ms
+XXX[235] TO 17 ms, lFrame0 0 ms, lFrameX 95 / 15786 ~67.174 ms, finishGL 95 / 15652 ~66.605 ms, waitGL 0 / 3 ~0.015 ms
+XXX[236] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15867 ~67.236 ms, finishGL 81 / 15733 ~66.666 ms, waitGL 0 / 3 ~0.015 ms
+XXX[237] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 15932 ~67.225 ms, finishGL 63 / 15797 ~66.654 ms, waitGL 0 / 3 ~0.015 ms
+XXX[238] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 16014 ~67.289 ms, finishGL 82 / 15879 ~66.719 ms, waitGL 0 / 3 ~0.015 ms
+XXX[239] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16081 ~67.286 ms, finishGL 66 / 15945 ~66.716 ms, waitGL 0 / 3 ~0.015 ms
+XXX[240] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 16144 ~67.268 ms, finishGL 62 / 16007 ~66.699 ms, waitGL 0 / 3 ~0.015 ms
+XXX[241] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 16230 ~67.346 ms, finishGL 85 / 16093 ~66.778 ms, waitGL 0 / 3 ~0.015 ms
+XXX[242] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16297 ~67.344 ms, finishGL 66 / 16159 ~66.776 ms, waitGL 0 / 3 ~0.015 ms
+XXX[243] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 16360 ~67.327 ms, finishGL 62 / 16222 ~66.759 ms, waitGL 0 / 3 ~0.015 ms
+XXX[244] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 16446 ~67.403 ms, finishGL 85 / 16307 ~66.834 ms, waitGL 0 / 3 ~0.015 ms
+XXX[245] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16512 ~67.397 ms, finishGL 65 / 16373 ~66.829 ms, waitGL 0 / 3 ~0.015 ms
+XXX[246] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 16574 ~67.376 ms, finishGL 61 / 16434 ~66.807 ms, waitGL 0 / 3 ~0.015 ms
+XXX[247] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 16662 ~67.458 ms, finishGL 86 / 16521 ~66.888 ms, waitGL 0 / 3 ~0.015 ms
+XXX[248] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16730 ~67.46 ms, finishGL 67 / 16588 ~66.89 ms, waitGL 0 / 3 ~0.015 ms
+XXX[249] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 16794 ~67.446 ms, finishGL 63 / 16652 ~66.877 ms, waitGL 0 / 3 ~0.015 ms
+XXX[250] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 16881 ~67.525 ms, finishGL 86 / 16739 ~66.956 ms, waitGL 0 / 3 ~0.015 ms
+XXX[251] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 16966 ~67.594 ms, finishGL 84 / 16823 ~67.025 ms, waitGL 0 / 3 ~0.015 ms
+XXX[252] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 17035 ~67.599 ms, finishGL 68 / 16891 ~67.031 ms, waitGL 0 / 3 ~0.015 ms
+XXX[253] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 17120 ~67.668 ms, finishGL 84 / 16976 ~67.1 ms, waitGL 0 / 3 ~0.015 ms
+XXX[254] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17205 ~67.736 ms, finishGL 84 / 17060 ~67.168 ms, waitGL 0 / 3 ~0.015 ms
+XXX[255] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17290 ~67.804 ms, finishGL 84 / 17145 ~67.236 ms, waitGL 0 / 4 ~0.015 ms
+XXX[256] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17374 ~67.868 ms, finishGL 83 / 17229 ~67.301 ms, waitGL 0 / 4 ~0.015 ms
+XXX[257] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17459 ~67.935 ms, finishGL 84 / 17313 ~67.367 ms, waitGL 0 / 4 ~0.015 ms
+XXX[258] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17543 ~67.999 ms, finishGL 83 / 17397 ~67.432 ms, waitGL 0 / 4 ~0.015 ms
+XXX[259] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17627 ~68.058 ms, finishGL 82 / 17480 ~67.492 ms, waitGL 0 / 4 ~0.015 ms
+FrameCount: 360 - FrameRate: 14.0
+XXX[260] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17710 ~68.119 ms, finishGL 83 / 17563 ~67.553 ms, waitGL 0 / 4 ~0.015 ms
+XXX[261] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17793 ~68.176 ms, finishGL 82 / 17646 ~67.61 ms, waitGL 0 / 4 ~0.015 ms
+XXX[262] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17877 ~68.234 ms, finishGL 82 / 17729 ~67.668 ms, waitGL 0 / 4 ~0.015 ms
+XXX[263] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17960 ~68.29 ms, finishGL 82 / 17811 ~67.725 ms, waitGL 0 / 4 ~0.015 ms
+XXX[264] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18042 ~68.342 ms, finishGL 81 / 17893 ~67.777 ms, waitGL 0 / 4 ~0.015 ms
+XXX[265] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18125 ~68.396 ms, finishGL 82 / 17975 ~67.832 ms, waitGL 0 / 4 ~0.015 ms
+XXX[266] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18207 ~68.451 ms, finishGL 82 / 18058 ~67.887 ms, waitGL 0 / 4 ~0.015 ms
+XXX[267] TO 17 ms, lFrame0 8 ms, lFrameX 85 / 18293 ~68.514 ms, finishGL 76 / 18135 ~67.921 ms, waitGL 0 / 4 ~0.015 ms
+XXX[268] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 18373 ~68.556 ms, finishGL 79 / 18214 ~67.964 ms, waitGL 0 / 4 ~0.015 ms
+XXX[269] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18455 ~68.608 ms, finishGL 82 / 18296 ~68.016 ms, waitGL 0 / 4 ~0.015 ms
+XXX[270] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18537 ~68.656 ms, finishGL 80 / 18377 ~68.064 ms, waitGL 0 / 4 ~0.015 ms
+XXX[271] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18618 ~68.704 ms, finishGL 81 / 18458 ~68.112 ms, waitGL 0 / 4 ~0.015 ms
+XXX[272] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18701 ~68.754 ms, finishGL 82 / 18540 ~68.163 ms, waitGL 0 / 4 ~0.015 ms
+XXX[273] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18783 ~68.804 ms, finishGL 81 / 18622 ~68.212 ms, waitGL 0 / 4 ~0.015 ms
+XXX[274] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18865 ~68.851 ms, finishGL 81 / 18703 ~68.261 ms, waitGL 0 / 4 ~0.015 ms
+XXX[275] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18947 ~68.901 ms, finishGL 82 / 18785 ~68.311 ms, waitGL 0 / 4 ~0.015 ms
+XXX[276] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 19029 ~68.948 ms, finishGL 81 / 18867 ~68.359 ms, waitGL 0 / 4 ~0.015 ms
+XXX[277] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19112 ~68.998 ms, finishGL 82 / 18949 ~68.408 ms, waitGL 0 / 4 ~0.015 ms
+XXX[278] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19195 ~69.047 ms, finishGL 82 / 19031 ~68.459 ms, waitGL 0 / 4 ~0.015 ms
+XXX[279] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19277 ~69.095 ms, finishGL 81 / 19113 ~68.507 ms, waitGL 0 / 4 ~0.015 ms
+XXX[280] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19360 ~69.143 ms, finishGL 81 / 19195 ~68.555 ms, waitGL 0 / 4 ~0.015 ms
+XXX[281] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19442 ~69.19 ms, finishGL 81 / 19277 ~68.602 ms, waitGL 0 / 4 ~0.015 ms
+XXX[282] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19508 ~69.179 ms, finishGL 65 / 19343 ~68.592 ms, waitGL 0 / 4 ~0.015 ms
+XXX[283] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19574 ~69.166 ms, finishGL 65 / 19408 ~68.579 ms, waitGL 0 / 4 ~0.015 ms
+XXX[284] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19639 ~69.152 ms, finishGL 64 / 19472 ~68.565 ms, waitGL 0 / 4 ~0.015 ms
+XXX[285] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19704 ~69.139 ms, finishGL 65 / 19537 ~68.553 ms, waitGL 0 / 4 ~0.015 ms
+XXX[286] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19770 ~69.128 ms, finishGL 65 / 19602 ~68.541 ms, waitGL 0 / 4 ~0.015 ms
+XXX[287] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19836 ~69.116 ms, finishGL 65 / 19668 ~68.53 ms, waitGL 0 / 4 ~0.015 ms
+XXX[288] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19901 ~69.103 ms, finishGL 64 / 19732 ~68.516 ms, waitGL 0 / 4 ~0.015 ms
+XXX[289] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19966 ~69.089 ms, finishGL 64 / 19797 ~68.503 ms, waitGL 0 / 4 ~0.015 ms
+XXX[290] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 20031 ~69.073 ms, finishGL 64 / 19861 ~68.488 ms, waitGL 0 / 4 ~0.015 ms
+XXX[291] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20097 ~69.063 ms, finishGL 65 / 19927 ~68.478 ms, waitGL 0 / 4 ~0.015 ms
+XXX[292] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20163 ~69.051 ms, finishGL 65 / 19992 ~68.466 ms, waitGL 0 / 4 ~0.015 ms
+XXX[293] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20228 ~69.038 ms, finishGL 64 / 20057 ~68.454 ms, waitGL 0 / 4 ~0.015 ms
+XXX[294] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20294 ~69.029 ms, finishGL 65 / 20123 ~68.446 ms, waitGL 0 / 4 ~0.015 ms
+XXX[295] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20360 ~69.017 ms, finishGL 64 / 20188 ~68.434 ms, waitGL 0 / 4 ~0.015 ms
+XXX[296] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20426 ~69.007 ms, finishGL 65 / 20253 ~68.424 ms, waitGL 0 / 4 ~0.015 ms
+XXX[297] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20492 ~68.998 ms, finishGL 65 / 20319 ~68.415 ms, waitGL 0 / 4 ~0.015 ms
+XXX[298] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20558 ~68.988 ms, finishGL 65 / 20384 ~68.405 ms, waitGL 0 / 4 ~0.015 ms
+XXX[299] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20625 ~68.98 ms, finishGL 66 / 20451 ~68.399 ms, waitGL 0 / 4 ~0.015 ms
+XXX[300] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20692 ~68.975 ms, finishGL 66 / 20518 ~68.393 ms, waitGL 0 / 4 ~0.015 ms
+XXX[301] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20759 ~68.969 ms, finishGL 66 / 20585 ~68.388 ms, waitGL 0 / 4 ~0.015 ms
+XXX[302] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20827 ~68.965 ms, finishGL 67 / 20652 ~68.385 ms, waitGL 0 / 4 ~0.015 ms
+XXX[303] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20894 ~68.96 ms, finishGL 66 / 20719 ~68.38 ms, waitGL 0 / 4 ~0.015 ms
+XXX[304] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 20964 ~68.962 ms, finishGL 69 / 20788 ~68.383 ms, waitGL 0 / 4 ~0.015 ms
+XXX[305] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 21033 ~68.96 ms, finishGL 67 / 20856 ~68.381 ms, waitGL 0 / 4 ~0.015 ms
+XXX[306] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 21103 ~68.966 ms, finishGL 70 / 20926 ~68.388 ms, waitGL 0 / 4 ~0.015 ms
+XXX[307] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 21175 ~68.974 ms, finishGL 70 / 20997 ~68.395 ms, waitGL 0 / 4 ~0.015 ms
+XXX[308] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 21263 ~69.036 ms, finishGL 87 / 21085 ~68.457 ms, waitGL 0 / 4 ~0.015 ms
+XXX[309] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 21349 ~69.092 ms, finishGL 85 / 21170 ~68.513 ms, waitGL 0 / 4 ~0.015 ms
+XXX[310] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21434 ~69.143 ms, finishGL 84 / 21255 ~68.565 ms, waitGL 0 / 4 ~0.015 ms
+XXX[311] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 21520 ~69.197 ms, finishGL 85 / 21340 ~68.618 ms, waitGL 0 / 4 ~0.015 ms
+XXX[312] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 21603 ~69.24 ms, finishGL 82 / 21422 ~68.662 ms, waitGL 0 / 4 ~0.015 ms
+XXX[313] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 21685 ~69.283 ms, finishGL 82 / 21504 ~68.705 ms, waitGL 0 / 4 ~0.015 ms
+XXX[314] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 21768 ~69.326 ms, finishGL 82 / 21587 ~68.748 ms, waitGL 0 / 4 ~0.015 ms
+XXX[315] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21853 ~69.374 ms, finishGL 84 / 21671 ~68.797 ms, waitGL 0 / 5 ~0.015 ms
+XXX[316] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21937 ~69.421 ms, finishGL 83 / 21755 ~68.845 ms, waitGL 0 / 5 ~0.015 ms
+XXX[317] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 22021 ~69.469 ms, finishGL 83 / 21838 ~68.892 ms, waitGL 0 / 5 ~0.015 ms
+XXX[318] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 22121 ~69.564 ms, finishGL 99 / 21938 ~68.987 ms, waitGL 0 / 5 ~0.015 ms
+XXX[319] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 22220 ~69.655 ms, finishGL 98 / 22036 ~69.079 ms, waitGL 0 / 5 ~0.015 ms
+XXX[320] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22303 ~69.697 ms, finishGL 82 / 22118 ~69.121 ms, waitGL 0 / 5 ~0.015 ms
+XXX[321] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 22384 ~69.733 ms, finishGL 80 / 22199 ~69.158 ms, waitGL 0 / 5 ~0.015 ms
+XXX[322] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 22468 ~69.778 ms, finishGL 83 / 22282 ~69.201 ms, waitGL 0 / 5 ~0.015 ms
+XXX[323] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22551 ~69.818 ms, finishGL 82 / 22365 ~69.241 ms, waitGL 0 / 5 ~0.015 ms
+XXX[324] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22634 ~69.859 ms, finishGL 82 / 22447 ~69.282 ms, waitGL 0 / 5 ~0.015 ms
+XXX[325] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22717 ~69.899 ms, finishGL 82 / 22530 ~69.323 ms, waitGL 0 / 5 ~0.015 ms
+XXX[326] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22800 ~69.941 ms, finishGL 82 / 22613 ~69.365 ms, waitGL 0 / 5 ~0.015 ms
+XXX[327] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22883 ~69.98 ms, finishGL 82 / 22695 ~69.404 ms, waitGL 0 / 5 ~0.015 ms
+XXX[328] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22967 ~70.022 ms, finishGL 83 / 22778 ~69.447 ms, waitGL 0 / 5 ~0.015 ms
+XXX[329] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23049 ~70.058 ms, finishGL 81 / 22860 ~69.483 ms, waitGL 0 / 5 ~0.015 ms
+XXX[330] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 23134 ~70.103 ms, finishGL 84 / 22944 ~69.528 ms, waitGL 0 / 5 ~0.015 ms
+XXX[331] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23217 ~70.143 ms, finishGL 83 / 23027 ~69.569 ms, waitGL 0 / 5 ~0.015 ms
+XXX[332] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 23301 ~70.186 ms, finishGL 83 / 23111 ~69.612 ms, waitGL 0 / 5 ~0.015 ms
+XXX[333] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23384 ~70.222 ms, finishGL 81 / 23192 ~69.648 ms, waitGL 0 / 5 ~0.015 ms
+XXX[334] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23467 ~70.262 ms, finishGL 83 / 23275 ~69.688 ms, waitGL 0 / 5 ~0.015 ms
+XXX[335] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23550 ~70.299 ms, finishGL 82 / 23357 ~69.725 ms, waitGL 0 / 5 ~0.015 ms
+XXX[336] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23633 ~70.336 ms, finishGL 82 / 23440 ~69.762 ms, waitGL 0 / 5 ~0.015 ms
+XXX[337] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23715 ~70.373 ms, finishGL 82 / 23522 ~69.799 ms, waitGL 0 / 5 ~0.015 ms
+XXX[338] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23798 ~70.409 ms, finishGL 81 / 23604 ~69.835 ms, waitGL 0 / 5 ~0.015 ms
+XXX[339] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23881 ~70.445 ms, finishGL 82 / 23686 ~69.872 ms, waitGL 0 / 5 ~0.015 ms
+XXX[340] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23964 ~70.483 ms, finishGL 82 / 23769 ~69.909 ms, waitGL 0 / 5 ~0.015 ms
+XXX[341] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 24046 ~70.516 ms, finishGL 81 / 23850 ~69.943 ms, waitGL 0 / 5 ~0.015 ms
+XXX[342] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24129 ~70.552 ms, finishGL 82 / 23933 ~69.979 ms, waitGL 0 / 5 ~0.015 ms
+XXX[343] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24211 ~70.587 ms, finishGL 82 / 24015 ~70.014 ms, waitGL 0 / 5 ~0.015 ms
+XXX[344] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24294 ~70.624 ms, finishGL 82 / 24097 ~70.052 ms, waitGL 0 / 5 ~0.015 ms
+XXX[345] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24377 ~70.658 ms, finishGL 81 / 24179 ~70.085 ms, waitGL 0 / 5 ~0.015 ms
+XXX[346] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24460 ~70.696 ms, finishGL 83 / 24262 ~70.122 ms, waitGL 0 / 5 ~0.015 ms
+XXX[347] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24543 ~70.731 ms, finishGL 82 / 24345 ~70.158 ms, waitGL 0 / 5 ~0.015 ms
+XXX[348] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24627 ~70.768 ms, finishGL 82 / 24427 ~70.195 ms, waitGL 0 / 5 ~0.015 ms
+XXX[349] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24710 ~70.805 ms, finishGL 83 / 24511 ~70.232 ms, waitGL 0 / 5 ~0.015 ms
+XXX[350] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24793 ~70.839 ms, finishGL 82 / 24593 ~70.266 ms, waitGL 0 / 5 ~0.015 ms
+XXX[351] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24876 ~70.874 ms, finishGL 82 / 24675 ~70.301 ms, waitGL 0 / 5 ~0.015 ms
+XXX[352] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24960 ~70.909 ms, finishGL 82 / 24758 ~70.337 ms, waitGL 0 / 5 ~0.015 ms
+XXX[353] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25043 ~70.944 ms, finishGL 82 / 24841 ~70.372 ms, waitGL 0 / 5 ~0.015 ms
+XXX[354] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25126 ~70.979 ms, finishGL 82 / 24924 ~70.407 ms, waitGL 0 / 5 ~0.015 ms
+XXX[355] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25210 ~71.014 ms, finishGL 82 / 25007 ~70.442 ms, waitGL 0 / 5 ~0.015 ms
+XXX[356] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25292 ~71.047 ms, finishGL 82 / 25089 ~70.475 ms, waitGL 0 / 5 ~0.015 ms
+XXX[357] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25375 ~71.079 ms, finishGL 82 / 25171 ~70.508 ms, waitGL 0 / 5 ~0.015 ms
+XXX[358] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25459 ~71.115 ms, finishGL 83 / 25254 ~70.544 ms, waitGL 0 / 5 ~0.015 ms
+XXX[359] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25542 ~71.148 ms, finishGL 82 / 25337 ~70.578 ms, waitGL 0 / 5 ~0.015 ms
+XXX[360] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25626 ~71.184 ms, finishGL 83 / 25421 ~70.614 ms, waitGL 0 / 5 ~0.015 ms
+XXX[361] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25709 ~71.217 ms, finishGL 82 / 25503 ~70.647 ms, waitGL 0 / 5 ~0.015 ms
+XXX[362] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25792 ~71.249 ms, finishGL 82 / 25586 ~70.679 ms, waitGL 0 / 5 ~0.015 ms
+XXX[363] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25876 ~71.284 ms, finishGL 83 / 25669 ~70.714 ms, waitGL 0 / 5 ~0.015 ms
+XXX[364] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 25960 ~71.319 ms, finishGL 83 / 25753 ~70.75 ms, waitGL 0 / 5 ~0.015 ms
+XXX[365] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26043 ~71.352 ms, finishGL 82 / 25835 ~70.783 ms, waitGL 0 / 5 ~0.015 ms
+XXX[366] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26126 ~71.384 ms, finishGL 82 / 25918 ~70.815 ms, waitGL 0 / 5 ~0.015 ms
+XXX[367] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26209 ~71.415 ms, finishGL 82 / 26000 ~70.847 ms, waitGL 0 / 5 ~0.015 ms
+XXX[368] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26293 ~71.448 ms, finishGL 83 / 26083 ~70.88 ms, waitGL 0 / 5 ~0.015 ms
+XXX[369] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26376 ~71.481 ms, finishGL 82 / 26166 ~70.912 ms, waitGL 0 / 5 ~0.015 ms
+XXX[370] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26459 ~71.511 ms, finishGL 82 / 26248 ~70.943 ms, waitGL 0 / 5 ~0.015 ms
+XXX[371] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26542 ~71.542 ms, finishGL 82 / 26331 ~70.973 ms, waitGL 0 / 5 ~0.015 ms
+XXX[372] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26625 ~71.574 ms, finishGL 82 / 26414 ~71.006 ms, waitGL 0 / 5 ~0.015 ms
+XXX[373] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26707 ~71.603 ms, finishGL 81 / 26495 ~71.034 ms, waitGL 0 / 5 ~0.015 ms
+XXX[374] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26790 ~71.633 ms, finishGL 82 / 26578 ~71.065 ms, waitGL 0 / 5 ~0.015 ms
+XXX[375] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26873 ~71.663 ms, finishGL 82 / 26660 ~71.095 ms, waitGL 0 / 5 ~0.015 ms
+XXX[376] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26956 ~71.694 ms, finishGL 82 / 26743 ~71.126 ms, waitGL 0 / 5 ~0.015 ms
+XXX[377] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27039 ~71.723 ms, finishGL 82 / 26825 ~71.155 ms, waitGL 0 / 5 ~0.015 ms
+XXX[378] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27122 ~71.751 ms, finishGL 81 / 26907 ~71.184 ms, waitGL 0 / 6 ~0.015 ms
+XXX[379] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27205 ~71.781 ms, finishGL 82 / 26990 ~71.214 ms, waitGL 0 / 6 ~0.015 ms
+FrameCount: 480 - FrameRate: 12.0
+XXX[380] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27287 ~71.81 ms, finishGL 82 / 27072 ~71.243 ms, waitGL 0 / 6 ~0.015 ms
+XXX[381] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27370 ~71.838 ms, finishGL 82 / 27154 ~71.271 ms, waitGL 0 / 6 ~0.015 ms
+XXX[382] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27453 ~71.867 ms, finishGL 82 / 27236 ~71.3 ms, waitGL 0 / 6 ~0.015 ms
+XXX[383] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27535 ~71.894 ms, finishGL 81 / 27318 ~71.328 ms, waitGL 0 / 6 ~0.015 ms
+XXX[384] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27618 ~71.922 ms, finishGL 82 / 27400 ~71.356 ms, waitGL 0 / 6 ~0.015 ms
+XXX[385] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 27702 ~71.953 ms, finishGL 83 / 27484 ~71.387 ms, waitGL 0 / 6 ~0.015 ms
+XXX[386] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27785 ~71.983 ms, finishGL 82 / 27567 ~71.417 ms, waitGL 0 / 6 ~0.015 ms
+XXX[387] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27869 ~72.013 ms, finishGL 83 / 27650 ~71.447 ms, waitGL 0 / 6 ~0.015 ms
+XXX[388] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27952 ~72.043 ms, finishGL 83 / 27733 ~71.478 ms, waitGL 0 / 6 ~0.015 ms
+XXX[389] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 28038 ~72.077 ms, finishGL 84 / 27818 ~71.512 ms, waitGL 0 / 6 ~0.015 ms
+XXX[390] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 28123 ~72.11 ms, finishGL 84 / 27902 ~71.545 ms, waitGL 0 / 6 ~0.015 ms
+XXX[391] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 28207 ~72.141 ms, finishGL 83 / 27986 ~71.576 ms, waitGL 0 / 6 ~0.015 ms
+XXX[392] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28290 ~72.17 ms, finishGL 83 / 28069 ~71.606 ms, waitGL 0 / 6 ~0.015 ms
+XXX[393] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28374 ~72.198 ms, finishGL 82 / 28152 ~71.634 ms, waitGL 0 / 6 ~0.015 ms
+XXX[394] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28457 ~72.227 ms, finishGL 82 / 28235 ~71.663 ms, waitGL 0 / 6 ~0.015 ms
+XXX[395] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28540 ~72.254 ms, finishGL 82 / 28317 ~71.69 ms, waitGL 0 / 6 ~0.015 ms
+XXX[396] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28623 ~72.281 ms, finishGL 82 / 28400 ~71.718 ms, waitGL 0 / 6 ~0.015 ms
+XXX[397] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28706 ~72.309 ms, finishGL 83 / 28483 ~71.746 ms, waitGL 0 / 6 ~0.015 ms
+XXX[398] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28789 ~72.336 ms, finishGL 82 / 28565 ~71.773 ms, waitGL 0 / 6 ~0.015 ms
+XXX[399] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28872 ~72.362 ms, finishGL 82 / 28648 ~71.8 ms, waitGL 0 / 6 ~0.015 ms
+XXX[400] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28955 ~72.388 ms, finishGL 82 / 28730 ~71.826 ms, waitGL 0 / 6 ~0.015 ms
+XXX[401] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 29036 ~72.409 ms, finishGL 80 / 28810 ~71.847 ms, waitGL 0 / 6 ~0.015 ms
+XXX[402] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29118 ~72.434 ms, finishGL 82 / 28893 ~71.873 ms, waitGL 0 / 6 ~0.015 ms
+XXX[403] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29200 ~72.458 ms, finishGL 81 / 28974 ~71.897 ms, waitGL 0 / 6 ~0.015 ms
+XXX[404] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29283 ~72.483 ms, finishGL 82 / 29056 ~71.922 ms, waitGL 0 / 6 ~0.015 ms
+XXX[405] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29366 ~72.509 ms, finishGL 82 / 29139 ~71.948 ms, waitGL 0 / 6 ~0.015 ms
+XXX[406] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29449 ~72.534 ms, finishGL 82 / 29221 ~71.973 ms, waitGL 0 / 6 ~0.015 ms
+XXX[407] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29531 ~72.559 ms, finishGL 82 / 29303 ~71.998 ms, waitGL 0 / 6 ~0.015 ms
+XXX[408] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29614 ~72.585 ms, finishGL 82 / 29385 ~72.024 ms, waitGL 0 / 6 ~0.015 ms
+XXX[409] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29697 ~72.61 ms, finishGL 82 / 29468 ~72.049 ms, waitGL 0 / 6 ~0.015 ms
+XXX[410] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29780 ~72.634 ms, finishGL 81 / 29550 ~72.073 ms, waitGL 0 / 6 ~0.015 ms
+XXX[411] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29863 ~72.659 ms, finishGL 82 / 29632 ~72.099 ms, waitGL 0 / 6 ~0.015 ms
+XXX[412] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29946 ~72.685 ms, finishGL 82 / 29715 ~72.125 ms, waitGL 0 / 6 ~0.015 ms
+XXX[413] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30030 ~72.713 ms, finishGL 83 / 29799 ~72.153 ms, waitGL 0 / 6 ~0.015 ms
+XXX[414] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30113 ~72.738 ms, finishGL 82 / 29881 ~72.178 ms, waitGL 0 / 6 ~0.015 ms
+XXX[415] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30196 ~72.762 ms, finishGL 82 / 29964 ~72.202 ms, waitGL 0 / 6 ~0.015 ms
+XXX[416] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30279 ~72.787 ms, finishGL 82 / 30046 ~72.228 ms, waitGL 0 / 6 ~0.015 ms
+XXX[417] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 30361 ~72.809 ms, finishGL 81 / 30128 ~72.25 ms, waitGL 0 / 6 ~0.015 ms
+XXX[418] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30445 ~72.835 ms, finishGL 82 / 30211 ~72.275 ms, waitGL 0 / 6 ~0.015 ms
+XXX[419] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30527 ~72.857 ms, finishGL 81 / 30292 ~72.297 ms, waitGL 0 / 6 ~0.015 ms
+XXX[420] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30611 ~72.884 ms, finishGL 83 / 30376 ~72.325 ms, waitGL 0 / 6 ~0.015 ms
+XXX[421] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30695 ~72.911 ms, finishGL 83 / 30460 ~72.351 ms, waitGL 0 / 6 ~0.015 ms
+XXX[422] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30779 ~72.937 ms, finishGL 83 / 30543 ~72.378 ms, waitGL 0 / 6 ~0.015 ms
+XXX[423] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30863 ~72.963 ms, finishGL 83 / 30627 ~72.404 ms, waitGL 0 / 6 ~0.015 ms
+XXX[424] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 30945 ~72.984 ms, finishGL 81 / 30708 ~72.425 ms, waitGL 0 / 6 ~0.015 ms
+XXX[425] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 31025 ~73.0 ms, finishGL 79 / 30787 ~72.441 ms, waitGL 0 / 6 ~0.015 ms
+XXX[426] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31105 ~73.017 ms, finishGL 79 / 30867 ~72.458 ms, waitGL 0 / 6 ~0.015 ms
+XXX[427] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31185 ~73.034 ms, finishGL 80 / 30947 ~72.476 ms, waitGL 0 / 6 ~0.015 ms
+XXX[428] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 31250 ~73.015 ms, finishGL 64 / 31011 ~72.456 ms, waitGL 0 / 6 ~0.015 ms
+XXX[429] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31316 ~72.999 ms, finishGL 65 / 31077 ~72.441 ms, waitGL 0 / 6 ~0.015 ms
+XXX[430] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31382 ~72.982 ms, finishGL 65 / 31142 ~72.424 ms, waitGL 0 / 6 ~0.015 ms
+XXX[431] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31448 ~72.966 ms, finishGL 65 / 31208 ~72.408 ms, waitGL 0 / 6 ~0.015 ms
+XXX[432] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31514 ~72.95 ms, finishGL 65 / 31273 ~72.392 ms, waitGL 0 / 6 ~0.015 ms
+XXX[433] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31580 ~72.933 ms, finishGL 65 / 31338 ~72.376 ms, waitGL 0 / 6 ~0.015 ms
+XXX[434] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31646 ~72.918 ms, finishGL 65 / 31404 ~72.361 ms, waitGL 0 / 6 ~0.015 ms
+XXX[435] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31712 ~72.901 ms, finishGL 64 / 31469 ~72.344 ms, waitGL 0 / 6 ~0.015 ms
+XXX[436] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31778 ~72.886 ms, finishGL 66 / 31535 ~72.329 ms, waitGL 0 / 6 ~0.015 ms
+XXX[437] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31844 ~72.871 ms, finishGL 65 / 31601 ~72.314 ms, waitGL 0 / 6 ~0.015 ms
+XXX[438] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31911 ~72.856 ms, finishGL 65 / 31667 ~72.299 ms, waitGL 0 / 6 ~0.015 ms
+XXX[439] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31977 ~72.842 ms, finishGL 66 / 31733 ~72.285 ms, waitGL 0 / 7 ~0.015 ms
+XXX[440] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32044 ~72.827 ms, finishGL 65 / 31799 ~72.271 ms, waitGL 0 / 7 ~0.015 ms
+XXX[441] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32111 ~72.815 ms, finishGL 66 / 31866 ~72.258 ms, waitGL 0 / 7 ~0.015 ms
+XXX[442] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32178 ~72.801 ms, finishGL 66 / 31932 ~72.245 ms, waitGL 0 / 7 ~0.015 ms
+XXX[443] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32245 ~72.788 ms, finishGL 66 / 31999 ~72.233 ms, waitGL 0 / 7 ~0.015 ms
+XXX[444] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32312 ~72.775 ms, finishGL 66 / 32065 ~72.22 ms, waitGL 0 / 7 ~0.015 ms
+XXX[445] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32378 ~72.761 ms, finishGL 65 / 32131 ~72.205 ms, waitGL 0 / 7 ~0.015 ms
+XXX[446] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32446 ~72.749 ms, finishGL 66 / 32198 ~72.193 ms, waitGL 0 / 7 ~0.015 ms
+XXX[447] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32512 ~72.734 ms, finishGL 66 / 32264 ~72.179 ms, waitGL 0 / 7 ~0.015 ms
+XXX[448] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32578 ~72.72 ms, finishGL 65 / 32330 ~72.165 ms, waitGL 0 / 7 ~0.015 ms
+XXX[449] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32645 ~72.707 ms, finishGL 66 / 32396 ~72.152 ms, waitGL 0 / 7 ~0.015 ms
+XXX[450] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32711 ~72.692 ms, finishGL 65 / 32462 ~72.138 ms, waitGL 0 / 7 ~0.015 ms
+XXX[451] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32777 ~72.678 ms, finishGL 65 / 32528 ~72.124 ms, waitGL 0 / 7 ~0.015 ms
+XXX[452] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32844 ~72.665 ms, finishGL 66 / 32594 ~72.111 ms, waitGL 0 / 7 ~0.015 ms
+XXX[453] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32910 ~72.65 ms, finishGL 65 / 32659 ~72.096 ms, waitGL 0 / 7 ~0.015 ms
+XXX[454] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32976 ~72.635 ms, finishGL 65 / 32725 ~72.081 ms, waitGL 0 / 7 ~0.015 ms
+XXX[455] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33042 ~72.621 ms, finishGL 65 / 32790 ~72.067 ms, waitGL 0 / 7 ~0.015 ms
+XXX[456] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 33107 ~72.604 ms, finishGL 64 / 32855 ~72.05 ms, waitGL 0 / 7 ~0.015 ms
+XXX[457] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33173 ~72.589 ms, finishGL 65 / 32920 ~72.036 ms, waitGL 0 / 7 ~0.015 ms
+XXX[458] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33239 ~72.574 ms, finishGL 65 / 32985 ~72.021 ms, waitGL 0 / 7 ~0.015 ms
+XXX[459] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33304 ~72.558 ms, finishGL 64 / 33050 ~72.005 ms, waitGL 0 / 7 ~0.015 ms
+XXX[460] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33370 ~72.544 ms, finishGL 65 / 33115 ~71.991 ms, waitGL 0 / 7 ~0.015 ms
+XXX[461] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33435 ~72.529 ms, finishGL 65 / 33181 ~71.976 ms, waitGL 0 / 7 ~0.015 ms
+XXX[462] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33500 ~72.512 ms, finishGL 64 / 33245 ~71.96 ms, waitGL 0 / 7 ~0.015 ms
+XXX[463] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33567 ~72.499 ms, finishGL 65 / 33311 ~71.947 ms, waitGL 0 / 7 ~0.015 ms
+XXX[464] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33632 ~72.484 ms, finishGL 64 / 33376 ~71.932 ms, waitGL 0 / 7 ~0.016 ms
+XXX[465] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33698 ~72.469 ms, finishGL 65 / 33441 ~71.917 ms, waitGL 0 / 7 ~0.016 ms
+XXX[466] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33764 ~72.455 ms, finishGL 65 / 33507 ~71.903 ms, waitGL 0 / 7 ~0.016 ms
+XXX[467] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33813 ~72.404 ms, finishGL 48 / 33555 ~71.853 ms, waitGL 0 / 7 ~0.016 ms
+XXX[468] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33862 ~72.355 ms, finishGL 48 / 33604 ~71.803 ms, waitGL 0 / 7 ~0.016 ms
+XXX[469] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33911 ~72.305 ms, finishGL 48 / 33652 ~71.754 ms, waitGL 0 / 7 ~0.016 ms
+XXX[470] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33960 ~72.256 ms, finishGL 48 / 33701 ~71.704 ms, waitGL 0 / 7 ~0.016 ms
+XXX[471] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34009 ~72.207 ms, finishGL 48 / 33749 ~71.655 ms, waitGL 0 / 7 ~0.016 ms
+XXX[472] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34058 ~72.158 ms, finishGL 48 / 33798 ~71.606 ms, waitGL 0 / 7 ~0.016 ms
+XXX[473] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34108 ~72.11 ms, finishGL 49 / 33847 ~71.559 ms, waitGL 0 / 7 ~0.016 ms
+XXX[474] TO 17 ms, lFrame0 0 ms, lFrameX 47 / 34155 ~72.058 ms, finishGL 47 / 33894 ~71.507 ms, waitGL 0 / 7 ~0.016 ms
+XXX[475] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34206 ~72.014 ms, finishGL 50 / 33945 ~71.463 ms, waitGL 0 / 7 ~0.016 ms
+XXX[476] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34255 ~71.965 ms, finishGL 48 / 33993 ~71.415 ms, waitGL 0 / 7 ~0.016 ms
+XXX[477] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34305 ~71.918 ms, finishGL 48 / 34042 ~71.367 ms, waitGL 0 / 7 ~0.016 ms
+XXX[478] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34353 ~71.869 ms, finishGL 48 / 34090 ~71.319 ms, waitGL 0 / 7 ~0.016 ms
+XXX[479] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34403 ~71.822 ms, finishGL 48 / 34139 ~71.271 ms, waitGL 0 / 7 ~0.016 ms
+XXX[480] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34452 ~71.775 ms, finishGL 48 / 34187 ~71.224 ms, waitGL 0 / 7 ~0.016 ms
+XXX[481] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34500 ~71.727 ms, finishGL 48 / 34236 ~71.176 ms, waitGL 0 / 7 ~0.016 ms
+XXX[482] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34550 ~71.681 ms, finishGL 48 / 34285 ~71.13 ms, waitGL 0 / 7 ~0.016 ms
+XXX[483] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34599 ~71.634 ms, finishGL 48 / 34333 ~71.083 ms, waitGL 0 / 7 ~0.016 ms
+XXX[484] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34648 ~71.587 ms, finishGL 48 / 34382 ~71.037 ms, waitGL 0 / 7 ~0.016 ms
+XXX[485] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34697 ~71.54 ms, finishGL 48 / 34430 ~70.99 ms, waitGL 0 / 7 ~0.016 ms
+XXX[486] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34746 ~71.495 ms, finishGL 48 / 34479 ~70.944 ms, waitGL 0 / 7 ~0.016 ms
+XXX[487] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34796 ~71.45 ms, finishGL 49 / 34528 ~70.9 ms, waitGL 0 / 7 ~0.016 ms
+XXX[488] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34845 ~71.405 ms, finishGL 49 / 34577 ~70.855 ms, waitGL 0 / 7 ~0.016 ms
+XXX[489] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34895 ~71.36 ms, finishGL 48 / 34626 ~70.81 ms, waitGL 0 / 7 ~0.016 ms
+XXX[490] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34945 ~71.317 ms, finishGL 49 / 34675 ~70.767 ms, waitGL 0 / 7 ~0.016 ms
+XXX[491] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34995 ~71.274 ms, finishGL 49 / 34725 ~70.723 ms, waitGL 0 / 7 ~0.016 ms
+XXX[492] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35045 ~71.231 ms, finishGL 49 / 34775 ~70.68 ms, waitGL 0 / 7 ~0.016 ms
+XXX[493] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35095 ~71.187 ms, finishGL 49 / 34824 ~70.637 ms, waitGL 0 / 7 ~0.016 ms
+XXX[494] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35144 ~71.143 ms, finishGL 49 / 34873 ~70.593 ms, waitGL 0 / 7 ~0.016 ms
+XXX[495] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35195 ~71.101 ms, finishGL 49 / 34922 ~70.551 ms, waitGL 0 / 7 ~0.016 ms
+XXX[496] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 35246 ~71.06 ms, finishGL 50 / 34973 ~70.511 ms, waitGL 0 / 7 ~0.016 ms
+XXX[497] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35296 ~71.019 ms, finishGL 49 / 35023 ~70.469 ms, waitGL 0 / 8 ~0.016 ms
+XXX[498] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35346 ~70.976 ms, finishGL 49 / 35072 ~70.427 ms, waitGL 0 / 8 ~0.016 ms
+XXX[499] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35396 ~70.935 ms, finishGL 49 / 35122 ~70.386 ms, waitGL 0 / 8 ~0.016 ms
+FrameCount: 600 - FrameRate: 19.0
+XXX[500] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35447 ~70.894 ms, finishGL 49 / 35172 ~70.345 ms, waitGL 0 / 8 ~0.016 ms
+XXX[501] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35497 ~70.853 ms, finishGL 49 / 35222 ~70.304 ms, waitGL 0 / 8 ~0.016 ms
+XXX[502] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35547 ~70.812 ms, finishGL 50 / 35272 ~70.263 ms, waitGL 0 / 8 ~0.016 ms
+XXX[503] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35598 ~70.771 ms, finishGL 49 / 35322 ~70.223 ms, waitGL 0 / 8 ~0.016 ms
+XXX[504] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35648 ~70.73 ms, finishGL 49 / 35371 ~70.181 ms, waitGL 0 / 8 ~0.016 ms
+XXX[505] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35698 ~70.69 ms, finishGL 49 / 35421 ~70.141 ms, waitGL 0 / 8 ~0.016 ms
+XXX[506] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35748 ~70.649 ms, finishGL 49 / 35470 ~70.1 ms, waitGL 0 / 8 ~0.016 ms
+XXX[507] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35798 ~70.609 ms, finishGL 49 / 35520 ~70.06 ms, waitGL 0 / 8 ~0.016 ms
+XXX[508] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35849 ~70.568 ms, finishGL 49 / 35570 ~70.02 ms, waitGL 0 / 8 ~0.016 ms
+XXX[509] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35899 ~70.528 ms, finishGL 49 / 35620 ~69.98 ms, waitGL 0 / 8 ~0.016 ms
+XXX[510] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35949 ~70.488 ms, finishGL 49 / 35669 ~69.94 ms, waitGL 0 / 8 ~0.016 ms
+XXX[511] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35999 ~70.449 ms, finishGL 49 / 35719 ~69.9 ms, waitGL 0 / 8 ~0.016 ms
+XXX[512] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 36050 ~70.41 ms, finishGL 50 / 35769 ~69.862 ms, waitGL 0 / 8 ~0.016 ms
+XXX[513] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 36102 ~70.375 ms, finishGL 51 / 35821 ~69.827 ms, waitGL 0 / 8 ~0.016 ms
+XXX[514] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 36153 ~70.338 ms, finishGL 50 / 35872 ~69.79 ms, waitGL 0 / 8 ~0.016 ms
+XXX[515] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 36207 ~70.306 ms, finishGL 53 / 35925 ~69.758 ms, waitGL 0 / 8 ~0.016 ms
+XXX[516] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 36276 ~70.302 ms, finishGL 67 / 35993 ~69.755 ms, waitGL 0 / 8 ~0.016 ms
+XXX[517] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 36346 ~70.302 ms, finishGL 69 / 36063 ~69.755 ms, waitGL 0 / 8 ~0.016 ms
+XXX[518] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 36421 ~70.311 ms, finishGL 74 / 36137 ~69.764 ms, waitGL 0 / 8 ~0.016 ms
+XXX[519] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 36497 ~70.322 ms, finishGL 75 / 36213 ~69.775 ms, waitGL 0 / 8 ~0.016 ms
+XXX[520] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 36583 ~70.353 ms, finishGL 85 / 36299 ~69.806 ms, waitGL 0 / 8 ~0.016 ms
+XXX[521] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36666 ~70.377 ms, finishGL 82 / 36381 ~69.83 ms, waitGL 0 / 8 ~0.016 ms
+XXX[522] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36749 ~70.401 ms, finishGL 82 / 36464 ~69.855 ms, waitGL 0 / 8 ~0.016 ms
+XXX[523] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36833 ~70.426 ms, finishGL 82 / 36547 ~69.879 ms, waitGL 0 / 8 ~0.016 ms
+XXX[524] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36915 ~70.449 ms, finishGL 82 / 36629 ~69.903 ms, waitGL 0 / 8 ~0.016 ms
+XXX[525] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36998 ~70.473 ms, finishGL 82 / 36711 ~69.927 ms, waitGL 0 / 8 ~0.016 ms
+XXX[526] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37081 ~70.497 ms, finishGL 82 / 36794 ~69.951 ms, waitGL 0 / 8 ~0.016 ms
+XXX[527] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37165 ~70.522 ms, finishGL 82 / 36877 ~69.976 ms, waitGL 0 / 8 ~0.016 ms
+XXX[528] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37248 ~70.547 ms, finishGL 83 / 36960 ~70.001 ms, waitGL 0 / 8 ~0.016 ms
+XXX[529] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37332 ~70.572 ms, finishGL 83 / 37043 ~70.026 ms, waitGL 0 / 8 ~0.016 ms
+XXX[530] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37415 ~70.595 ms, finishGL 82 / 37126 ~70.049 ms, waitGL 0 / 8 ~0.016 ms
+XXX[531] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37498 ~70.619 ms, finishGL 82 / 37209 ~70.073 ms, waitGL 0 / 8 ~0.016 ms
+XXX[532] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37582 ~70.643 ms, finishGL 82 / 37291 ~70.097 ms, waitGL 0 / 8 ~0.016 ms
+XXX[533] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37665 ~70.667 ms, finishGL 82 / 37374 ~70.121 ms, waitGL 0 / 8 ~0.016 ms
+XXX[534] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37749 ~70.691 ms, finishGL 82 / 37457 ~70.145 ms, waitGL 0 / 8 ~0.016 ms
+XXX[535] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37832 ~70.714 ms, finishGL 82 / 37540 ~70.168 ms, waitGL 0 / 8 ~0.016 ms
+XXX[536] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37914 ~70.735 ms, finishGL 81 / 37621 ~70.19 ms, waitGL 0 / 8 ~0.016 ms
+XXX[537] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37997 ~70.757 ms, finishGL 82 / 37704 ~70.212 ms, waitGL 0 / 8 ~0.016 ms
+XXX[538] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38080 ~70.78 ms, finishGL 82 / 37786 ~70.235 ms, waitGL 0 / 8 ~0.016 ms
+XXX[539] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38162 ~70.802 ms, finishGL 82 / 37868 ~70.257 ms, waitGL 0 / 8 ~0.016 ms
+XXX[540] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38245 ~70.825 ms, finishGL 82 / 37951 ~70.279 ms, waitGL 0 / 8 ~0.016 ms
+XXX[541] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38329 ~70.848 ms, finishGL 82 / 38034 ~70.303 ms, waitGL 0 / 8 ~0.016 ms
+XXX[542] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38412 ~70.871 ms, finishGL 82 / 38116 ~70.325 ms, waitGL 0 / 8 ~0.016 ms
+XXX[543] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38495 ~70.894 ms, finishGL 83 / 38199 ~70.349 ms, waitGL 0 / 8 ~0.016 ms
+XXX[544] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38579 ~70.917 ms, finishGL 82 / 38282 ~70.372 ms, waitGL 0 / 8 ~0.016 ms
+XXX[545] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38662 ~70.94 ms, finishGL 82 / 38365 ~70.395 ms, waitGL 0 / 8 ~0.016 ms
+XXX[546] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38745 ~70.962 ms, finishGL 82 / 38447 ~70.417 ms, waitGL 0 / 8 ~0.016 ms
+XXX[547] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38829 ~70.986 ms, finishGL 83 / 38531 ~70.441 ms, waitGL 0 / 8 ~0.016 ms
+XXX[548] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38913 ~71.01 ms, finishGL 83 / 38614 ~70.465 ms, waitGL 0 / 8 ~0.016 ms
+XXX[549] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38997 ~71.034 ms, finishGL 83 / 38698 ~70.488 ms, waitGL 0 / 8 ~0.016 ms
+XXX[550] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 39081 ~71.057 ms, finishGL 83 / 38781 ~70.512 ms, waitGL 0 / 8 ~0.016 ms
+XXX[551] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39165 ~71.08 ms, finishGL 83 / 38864 ~70.535 ms, waitGL 0 / 8 ~0.016 ms
+XXX[552] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39248 ~71.101 ms, finishGL 82 / 38947 ~70.556 ms, waitGL 0 / 8 ~0.016 ms
+XXX[553] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39331 ~71.123 ms, finishGL 82 / 39029 ~70.578 ms, waitGL 0 / 8 ~0.016 ms
+XXX[554] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39413 ~71.143 ms, finishGL 81 / 39111 ~70.598 ms, waitGL 0 / 8 ~0.016 ms
+XXX[555] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39495 ~71.163 ms, finishGL 82 / 39193 ~70.619 ms, waitGL 0 / 8 ~0.016 ms
+XXX[556] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39578 ~71.183 ms, finishGL 81 / 39275 ~70.639 ms, waitGL 0 / 8 ~0.016 ms
+XXX[557] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39660 ~71.203 ms, finishGL 81 / 39357 ~70.659 ms, waitGL 0 / 8 ~0.016 ms
+XXX[558] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39742 ~71.223 ms, finishGL 81 / 39438 ~70.678 ms, waitGL 0 / 9 ~0.016 ms
+XXX[559] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39824 ~71.243 ms, finishGL 81 / 39520 ~70.698 ms, waitGL 0 / 9 ~0.016 ms
+XXX[560] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39907 ~71.263 ms, finishGL 82 / 39603 ~70.719 ms, waitGL 0 / 9 ~0.016 ms
+XXX[561] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 39987 ~71.279 ms, finishGL 79 / 39682 ~70.735 ms, waitGL 0 / 9 ~0.016 ms
+XXX[562] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40069 ~71.297 ms, finishGL 80 / 39763 ~70.753 ms, waitGL 0 / 9 ~0.016 ms
+XXX[563] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40150 ~71.315 ms, finishGL 80 / 39844 ~70.771 ms, waitGL 0 / 9 ~0.016 ms
+XXX[564] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40231 ~71.332 ms, finishGL 80 / 39925 ~70.789 ms, waitGL 0 / 9 ~0.016 ms
+XXX[565] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 40314 ~71.352 ms, finishGL 82 / 40007 ~70.809 ms, waitGL 0 / 9 ~0.016 ms
+XXX[566] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 40378 ~71.339 ms, finishGL 63 / 40070 ~70.796 ms, waitGL 0 / 9 ~0.016 ms
+XXX[567] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40444 ~71.329 ms, finishGL 65 / 40135 ~70.786 ms, waitGL 0 / 9 ~0.016 ms
+XXX[568] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40509 ~71.319 ms, finishGL 64 / 40200 ~70.776 ms, waitGL 0 / 9 ~0.016 ms
+XXX[569] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40575 ~71.309 ms, finishGL 65 / 40266 ~70.766 ms, waitGL 0 / 9 ~0.016 ms
+XXX[570] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40640 ~71.299 ms, finishGL 65 / 40331 ~70.756 ms, waitGL 0 / 9 ~0.016 ms
+XXX[571] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40707 ~71.291 ms, finishGL 65 / 40397 ~70.748 ms, waitGL 0 / 9 ~0.016 ms
+XXX[572] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40773 ~71.281 ms, finishGL 65 / 40462 ~70.738 ms, waitGL 0 / 9 ~0.016 ms
+XXX[573] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40838 ~71.271 ms, finishGL 65 / 40527 ~70.728 ms, waitGL 0 / 9 ~0.016 ms
+XXX[574] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 40905 ~71.264 ms, finishGL 66 / 40594 ~70.721 ms, waitGL 0 / 9 ~0.016 ms
+XXX[575] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 40973 ~71.257 ms, finishGL 66 / 40660 ~70.714 ms, waitGL 0 / 9 ~0.016 ms
+XXX[576] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 41039 ~71.249 ms, finishGL 66 / 40727 ~70.706 ms, waitGL 0 / 9 ~0.016 ms
+XXX[577] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 41107 ~71.243 ms, finishGL 66 / 40794 ~70.7 ms, waitGL 0 / 9 ~0.016 ms
+XXX[578] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 41176 ~71.24 ms, finishGL 69 / 40863 ~70.697 ms, waitGL 0 / 9 ~0.016 ms
+XXX[579] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 41246 ~71.238 ms, finishGL 69 / 40932 ~70.695 ms, waitGL 0 / 9 ~0.016 ms
+XXX[580] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 41336 ~71.269 ms, finishGL 88 / 41021 ~70.726 ms, waitGL 0 / 9 ~0.016 ms
+XXX[581] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 41424 ~71.298 ms, finishGL 87 / 41109 ~70.755 ms, waitGL 0 / 9 ~0.016 ms
+XXX[582] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 41510 ~71.323 ms, finishGL 85 / 41194 ~70.78 ms, waitGL 0 / 9 ~0.016 ms
+XXX[583] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 41594 ~71.345 ms, finishGL 83 / 41278 ~70.803 ms, waitGL 0 / 9 ~0.016 ms
+XXX[584] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41676 ~71.364 ms, finishGL 81 / 41360 ~70.822 ms, waitGL 0 / 9 ~0.016 ms
+XXX[585] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 41757 ~71.38 ms, finishGL 80 / 41440 ~70.838 ms, waitGL 0 / 9 ~0.016 ms
+XXX[586] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 41839 ~71.398 ms, finishGL 81 / 41521 ~70.856 ms, waitGL 0 / 9 ~0.016 ms
+XXX[587] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41922 ~71.417 ms, finishGL 82 / 41604 ~70.875 ms, waitGL 0 / 9 ~0.016 ms
+XXX[588] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42004 ~71.436 ms, finishGL 81 / 41686 ~70.894 ms, waitGL 0 / 9 ~0.016 ms
+XXX[589] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42088 ~71.456 ms, finishGL 82 / 41769 ~70.915 ms, waitGL 0 / 9 ~0.016 ms
+XXX[590] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42170 ~71.475 ms, finishGL 81 / 41851 ~70.934 ms, waitGL 0 / 9 ~0.016 ms
+XXX[591] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42253 ~71.495 ms, finishGL 82 / 41933 ~70.953 ms, waitGL 0 / 9 ~0.016 ms
+XXX[592] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42336 ~71.514 ms, finishGL 82 / 42016 ~70.973 ms, waitGL 0 / 9 ~0.016 ms
+XXX[593] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42420 ~71.535 ms, finishGL 83 / 42099 ~70.994 ms, waitGL 0 / 9 ~0.016 ms
+XXX[594] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42503 ~71.555 ms, finishGL 82 / 42182 ~71.013 ms, waitGL 0 / 9 ~0.016 ms
+XXX[595] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42588 ~71.577 ms, finishGL 84 / 42266 ~71.035 ms, waitGL 0 / 9 ~0.016 ms
+XXX[596] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42672 ~71.597 ms, finishGL 83 / 42349 ~71.056 ms, waitGL 0 / 9 ~0.016 ms
+XXX[597] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42755 ~71.617 ms, finishGL 82 / 42432 ~71.076 ms, waitGL 0 / 9 ~0.016 ms
+XXX[598] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42839 ~71.638 ms, finishGL 83 / 42516 ~71.097 ms, waitGL 0 / 9 ~0.016 ms
+XXX[599] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42922 ~71.657 ms, finishGL 82 / 42598 ~71.116 ms, waitGL 0 / 9 ~0.016 ms
+XXX[600] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 43004 ~71.673 ms, finishGL 80 / 42679 ~71.132 ms, waitGL 0 / 9 ~0.016 ms
+XXX[601] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 43085 ~71.689 ms, finishGL 81 / 42760 ~71.149 ms, waitGL 0 / 9 ~0.016 ms
+XXX[602] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43167 ~71.707 ms, finishGL 81 / 42842 ~71.166 ms, waitGL 0 / 9 ~0.016 ms
+XXX[603] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43250 ~71.725 ms, finishGL 82 / 42924 ~71.185 ms, waitGL 0 / 9 ~0.016 ms
+XXX[604] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43333 ~71.743 ms, finishGL 82 / 43006 ~71.203 ms, waitGL 0 / 9 ~0.016 ms
+XXX[605] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 43416 ~71.762 ms, finishGL 82 / 43089 ~71.222 ms, waitGL 0 / 9 ~0.016 ms
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait.log b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait.log
new file mode 100644
index 000000000..3f9bb251d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait.log
@@ -0,0 +1,751 @@
+NSZombieEnabled
+NSTraceEvents YES
+OBJC_PRINT_EXCEPTIONS
+/usr/bin/java
+java version "1.6.0_37"
+Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909)
+Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)
+LD_LIBRARY_PATH :../../gluegen/make/../build-macosx/obj:../build-macosx/lib
+LIBXCB_ALLOW_SLOPPY_LOCK:
+LIBGL_DRIVERS_PATH:
+LIBGL_DEBUG:
+LIBGL_ALWAYS_INDIRECT:
+LIBGL_ALWAYS_SOFTWARE:
+SWT_CLASSPATH: ../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar
+/usr/bin/java -d64 -time 100000 -vsync 0
+CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar
+CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar
+
+Test Start: com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0
+
+/usr/bin/java -d64 -Djava.awt.headless=false -Djogl.debug.calayer.SwapM2 com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0
+swapInterval 0
+exclusiveContext false
+SWAP_M1 false
+SWAP_M2 true
+NewtCanvasAWT.attachNewtChild.2: size 500x268
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init ...
+LandscapeES2 init on Thread[main-Display-.macosx_nil-1-EDT-1,5,main]
+Chosen GLCapabilities: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/0, dbl, mono , hw, GLProfile[GL2/GL2.hw], offscr[fbo]]
+INIT GL IS: jogamp.opengl.gl4.GL4bcImpl
+GL_VENDOR: NVIDIA Corporation
+GL_RENDERER: NVIDIA GeForce 320M OpenGL Engine
+GL_VERSION: 2.1 NVIDIA-7.32.12
+GL GLSL: true, has-compiler-func: true, version 1.20, 1.20.0
+GL FBO: basic true, full true
+GL Profile: GLProfile[GL2/GL2.hw]
+GL Renderer Quirks:[NoOffscreenBitmap]
+GL:jogamp.opengl.gl4.GL4bcImpl@3e018c74, 2.1 (hardware) - 2.1 NVIDIA-7.32.12
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init FIN
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7fc3498bf2c0
+Thread[AWT-EventQueue-0,6,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7fc3498bf2c0
+XXX[1] TO 17 ms, lFrame0 110 ms, lFrameX 848 / 848 ~848.637 ms, finishGL 736 / 736 ~736.829 ms, waitGL 1 / 1 ~1.296 ms
+XXX[2] TO 17 ms, lFrame0 81 ms, lFrameX 169 / 1017 ~508.969 ms, finishGL 87 / 824 ~412.402 ms, waitGL 0 / 1 ~0.654 ms
+XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 1099 ~366.547 ms, finishGL 80 / 905 ~301.882 ms, waitGL 0 / 1 ~0.441 ms
+XXX[4] TO 17 ms, lFrame0 1 ms, lFrameX 86 / 1185 ~296.444 ms, finishGL 84 / 990 ~247.652 ms, waitGL 0 / 1 ~0.334 ms
+XXX[5] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 1269 ~253.857 ms, finishGL 81 / 1071 ~214.388 ms, waitGL 0 / 1 ~0.27 ms
+XXX[6] TO 17 ms, lFrame0 2 ms, lFrameX 82 / 1351 ~225.33 ms, finishGL 80 / 1152 ~192.095 ms, waitGL 0 / 1 ~0.227 ms
+XXX[7] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 1435 ~205.021 ms, finishGL 80 / 1233 ~176.15 ms, waitGL 0 / 1 ~0.196 ms
+XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 1532 ~191.621 ms, finishGL 97 / 1330 ~166.297 ms, waitGL 0 / 1 ~0.174 ms
+XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1615 ~179.507 ms, finishGL 81 / 1412 ~156.923 ms, waitGL 0 / 1 ~0.156 ms
+XXX[10] TO 17 ms, lFrame0 1 ms, lFrameX 79 / 1694 ~169.458 ms, finishGL 77 / 1490 ~149.019 ms, waitGL 0 / 1 ~0.141 ms
+XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 103 / 1798 ~163.463 ms, finishGL 102 / 1592 ~144.812 ms, waitGL 0 / 1 ~0.129 ms
+XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 1881 ~156.761 ms, finishGL 82 / 1675 ~139.611 ms, waitGL 0 / 1 ~0.12 ms
+XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 1958 ~150.688 ms, finishGL 76 / 1752 ~134.783 ms, waitGL 0 / 1 ~0.111 ms
+XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 2046 ~146.155 ms, finishGL 86 / 1838 ~131.346 ms, waitGL 0 / 1 ~0.104 ms
+XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 2144 ~142.991 ms, finishGL 98 / 1936 ~129.13 ms, waitGL 0 / 1 ~0.098 ms
+XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2227 ~139.237 ms, finishGL 81 / 2018 ~126.184 ms, waitGL 0 / 1 ~0.093 ms
+XXX[17] TO 17 ms, lFrame0 1 ms, lFrameX 75 / 2302 ~135.468 ms, finishGL 74 / 2093 ~123.12 ms, waitGL 0 / 1 ~0.089 ms
+XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2410 ~133.895 ms, finishGL 106 / 2199 ~122.184 ms, waitGL 0 / 1 ~0.085 ms
+XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2493 ~131.251 ms, finishGL 82 / 2282 ~120.108 ms, waitGL 0 / 1 ~0.081 ms
+XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2569 ~128.458 ms, finishGL 74 / 2356 ~117.844 ms, waitGL 0 / 1 ~0.077 ms
+XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2676 ~127.46 ms, finishGL 107 / 2463 ~117.328 ms, waitGL 0 / 1 ~0.074 ms
+XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2760 ~125.462 ms, finishGL 83 / 2546 ~115.768 ms, waitGL 0 / 1 ~0.072 ms
+XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2836 ~123.307 ms, finishGL 75 / 2622 ~114.004 ms, waitGL 0 / 1 ~0.069 ms
+XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 2941 ~122.558 ms, finishGL 104 / 2726 ~113.619 ms, waitGL 0 / 1 ~0.067 ms
+XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 3020 ~120.817 ms, finishGL 78 / 2805 ~112.217 ms, waitGL 0 / 1 ~0.065 ms
+XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 3090 ~118.863 ms, finishGL 69 / 2875 ~110.579 ms, waitGL 0 / 1 ~0.063 ms
+XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 3169 ~117.398 ms, finishGL 78 / 2953 ~109.402 ms, waitGL 0 / 1 ~0.061 ms
+XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3251 ~116.14 ms, finishGL 81 / 3035 ~108.413 ms, waitGL 0 / 1 ~0.06 ms
+XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3334 ~114.972 ms, finishGL 81 / 3117 ~107.495 ms, waitGL 0 / 1 ~0.058 ms
+XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3416 ~113.876 ms, finishGL 81 / 3199 ~106.633 ms, waitGL 0 / 1 ~0.057 ms
+XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3498 ~112.869 ms, finishGL 82 / 3281 ~105.845 ms, waitGL 0 / 1 ~0.055 ms
+XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3581 ~111.907 ms, finishGL 81 / 3362 ~105.085 ms, waitGL 0 / 1 ~0.054 ms
+XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3646 ~110.507 ms, finishGL 64 / 3427 ~103.87 ms, waitGL 0 / 1 ~0.053 ms
+XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3713 ~109.219 ms, finishGL 66 / 3493 ~102.763 ms, waitGL 0 / 1 ~0.052 ms
+XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3779 ~107.986 ms, finishGL 65 / 3559 ~101.701 ms, waitGL 0 / 1 ~0.051 ms
+XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3845 ~106.813 ms, finishGL 65 / 3624 ~100.684 ms, waitGL 0 / 1 ~0.05 ms
+XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3911 ~105.716 ms, finishGL 65 / 3690 ~99.739 ms, waitGL 0 / 1 ~0.049 ms
+XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3977 ~104.665 ms, finishGL 65 / 3755 ~98.825 ms, waitGL 0 / 1 ~0.048 ms
+XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 4044 ~103.71 ms, finishGL 66 / 3822 ~98.008 ms, waitGL 0 / 1 ~0.047 ms
+XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4111 ~102.777 ms, finishGL 65 / 3888 ~97.206 ms, waitGL 0 / 1 ~0.047 ms
+XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4176 ~101.867 ms, finishGL 65 / 3953 ~96.42 ms, waitGL 0 / 1 ~0.046 ms
+XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4242 ~101.018 ms, finishGL 65 / 4018 ~95.689 ms, waitGL 0 / 1 ~0.045 ms
+XXX[43] TO 17 ms, lFrame0 7 ms, lFrameX 68 / 4311 ~100.267 ms, finishGL 61 / 4080 ~94.884 ms, waitGL 0 / 1 ~0.044 ms
+XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 4375 ~99.44 ms, finishGL 63 / 4143 ~94.168 ms, waitGL 0 / 1 ~0.044 ms
+XXX[45] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4441 ~98.703 ms, finishGL 64 / 4208 ~93.516 ms, waitGL 0 / 1 ~0.043 ms
+XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4508 ~98.0 ms, finishGL 65 / 4274 ~92.914 ms, waitGL 0 / 1 ~0.042 ms
+XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4574 ~97.329 ms, finishGL 65 / 4340 ~92.341 ms, waitGL 0 / 1 ~0.042 ms
+XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4640 ~96.682 ms, finishGL 65 / 4405 ~91.788 ms, waitGL 0 / 2 ~0.041 ms
+XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4707 ~96.066 ms, finishGL 66 / 4471 ~91.262 ms, waitGL 0 / 2 ~0.041 ms
+XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4773 ~95.471 ms, finishGL 65 / 4537 ~90.753 ms, waitGL 0 / 2 ~0.04 ms
+XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4839 ~94.895 ms, finishGL 65 / 4603 ~90.259 ms, waitGL 0 / 2 ~0.04 ms
+XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4905 ~94.343 ms, finishGL 65 / 4668 ~89.787 ms, waitGL 0 / 2 ~0.039 ms
+XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 4970 ~93.788 ms, finishGL 64 / 4733 ~89.308 ms, waitGL 0 / 2 ~0.039 ms
+XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5037 ~93.294 ms, finishGL 66 / 4799 ~88.885 ms, waitGL 0 / 2 ~0.038 ms
+XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5104 ~92.8 ms, finishGL 65 / 4865 ~88.462 ms, waitGL 0 / 2 ~0.038 ms
+XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5170 ~92.332 ms, finishGL 66 / 4931 ~88.063 ms, waitGL 0 / 2 ~0.037 ms
+XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5236 ~91.871 ms, finishGL 65 / 4997 ~87.668 ms, waitGL 0 / 2 ~0.037 ms
+XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5303 ~91.442 ms, finishGL 66 / 5063 ~87.303 ms, waitGL 0 / 2 ~0.037 ms
+XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5369 ~91.015 ms, finishGL 65 / 5129 ~86.938 ms, waitGL 0 / 2 ~0.036 ms
+XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5436 ~90.614 ms, finishGL 66 / 5195 ~86.598 ms, waitGL 0 / 2 ~0.036 ms
+XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5503 ~90.224 ms, finishGL 66 / 5262 ~86.266 ms, waitGL 0 / 2 ~0.036 ms
+XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5570 ~89.839 ms, finishGL 65 / 5327 ~85.933 ms, waitGL 0 / 2 ~0.035 ms
+XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5637 ~89.477 ms, finishGL 66 / 5394 ~85.625 ms, waitGL 0 / 2 ~0.035 ms
+XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5703 ~89.118 ms, finishGL 66 / 5460 ~85.319 ms, waitGL 0 / 2 ~0.035 ms
+XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5770 ~88.771 ms, finishGL 65 / 5526 ~85.02 ms, waitGL 0 / 2 ~0.035 ms
+XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5836 ~88.435 ms, finishGL 66 / 5592 ~84.734 ms, waitGL 0 / 2 ~0.034 ms
+XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5904 ~88.122 ms, finishGL 66 / 5659 ~84.469 ms, waitGL 0 / 2 ~0.034 ms
+XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5970 ~87.805 ms, finishGL 66 / 5725 ~84.199 ms, waitGL 0 / 2 ~0.034 ms
+XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6037 ~87.498 ms, finishGL 66 / 5791 ~83.937 ms, waitGL 0 / 2 ~0.033 ms
+XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6104 ~87.206 ms, finishGL 66 / 5858 ~83.689 ms, waitGL 0 / 2 ~0.033 ms
+XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6171 ~86.919 ms, finishGL 66 / 5924 ~83.445 ms, waitGL 0 / 2 ~0.033 ms
+XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6237 ~86.636 ms, finishGL 65 / 5990 ~83.201 ms, waitGL 0 / 2 ~0.033 ms
+XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6303 ~86.354 ms, finishGL 65 / 6056 ~82.96 ms, waitGL 0 / 2 ~0.032 ms
+XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6370 ~86.081 ms, finishGL 65 / 6121 ~82.725 ms, waitGL 0 / 2 ~0.032 ms
+XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6435 ~85.806 ms, finishGL 64 / 6186 ~82.485 ms, waitGL 0 / 2 ~0.032 ms
+XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6501 ~85.551 ms, finishGL 65 / 6251 ~82.261 ms, waitGL 0 / 2 ~0.032 ms
+XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6567 ~85.298 ms, finishGL 65 / 6317 ~82.044 ms, waitGL 0 / 2 ~0.032 ms
+XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6634 ~85.057 ms, finishGL 66 / 6383 ~81.839 ms, waitGL 0 / 2 ~0.031 ms
+XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6701 ~84.826 ms, finishGL 66 / 6449 ~81.642 ms, waitGL 0 / 2 ~0.031 ms
+XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6768 ~84.601 ms, finishGL 66 / 6516 ~81.452 ms, waitGL 0 / 2 ~0.031 ms
+XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6834 ~84.376 ms, finishGL 65 / 6582 ~81.259 ms, waitGL 0 / 2 ~0.031 ms
+XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6901 ~84.162 ms, finishGL 66 / 6648 ~81.077 ms, waitGL 0 / 2 ~0.031 ms
+XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6968 ~83.956 ms, finishGL 66 / 6714 ~80.903 ms, waitGL 0 / 2 ~0.031 ms
+XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7035 ~83.759 ms, finishGL 66 / 6781 ~80.737 ms, waitGL 0 / 2 ~0.03 ms
+XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7102 ~83.556 ms, finishGL 65 / 6847 ~80.563 ms, waitGL 0 / 2 ~0.03 ms
+XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7168 ~83.355 ms, finishGL 65 / 6913 ~80.391 ms, waitGL 0 / 2 ~0.03 ms
+XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7235 ~83.167 ms, finishGL 66 / 6980 ~80.23 ms, waitGL 0 / 2 ~0.03 ms
+XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7302 ~82.979 ms, finishGL 66 / 7046 ~80.07 ms, waitGL 0 / 2 ~0.03 ms
+XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7368 ~82.791 ms, finishGL 65 / 7111 ~79.909 ms, waitGL 0 / 2 ~0.029 ms
+XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7435 ~82.616 ms, finishGL 66 / 7178 ~79.761 ms, waitGL 0 / 2 ~0.029 ms
+XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7501 ~82.432 ms, finishGL 65 / 7243 ~79.603 ms, waitGL 0 / 2 ~0.029 ms
+XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7567 ~82.258 ms, finishGL 65 / 7309 ~79.454 ms, waitGL 0 / 2 ~0.029 ms
+XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7634 ~82.088 ms, finishGL 65 / 7375 ~79.309 ms, waitGL 0 / 2 ~0.029 ms
+XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7700 ~81.921 ms, finishGL 65 / 7441 ~79.167 ms, waitGL 0 / 2 ~0.029 ms
+XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7767 ~81.758 ms, finishGL 65 / 7507 ~79.028 ms, waitGL 0 / 2 ~0.029 ms
+XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7833 ~81.601 ms, finishGL 66 / 7573 ~78.893 ms, waitGL 0 / 2 ~0.028 ms
+XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7899 ~81.443 ms, finishGL 65 / 7639 ~78.758 ms, waitGL 0 / 2 ~0.028 ms
+XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7965 ~81.282 ms, finishGL 65 / 7704 ~78.62 ms, waitGL 0 / 2 ~0.028 ms
+XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8031 ~81.129 ms, finishGL 65 / 7770 ~78.486 ms, waitGL 0 / 2 ~0.028 ms
+XXX[1] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 66 ~66.634 ms, finishGL 66 / 66 ~66.169 ms, waitGL 0 / 0 ~0.015 ms
+XXX[2] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 132 ~66.347 ms, finishGL 65 / 131 ~65.882 ms, waitGL 0 / 0 ~0.018 ms
+XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 198 ~66.312 ms, finishGL 65 / 197 ~65.839 ms, waitGL 0 / 0 ~0.017 ms
+XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 265 ~66.27 ms, finishGL 65 / 263 ~65.792 ms, waitGL 0 / 0 ~0.016 ms
+XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 331 ~66.372 ms, finishGL 66 / 329 ~65.865 ms, waitGL 0 / 0 ~0.016 ms
+XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 397 ~66.297 ms, finishGL 65 / 394 ~65.793 ms, waitGL 0 / 0 ~0.015 ms
+XXX[7] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 464 ~66.324 ms, finishGL 65 / 460 ~65.82 ms, waitGL 0 / 0 ~0.015 ms
+XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 530 ~66.269 ms, finishGL 65 / 526 ~65.77 ms, waitGL 0 / 0 ~0.016 ms
+XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 597 ~66.378 ms, finishGL 66 / 592 ~65.88 ms, waitGL 0 / 0 ~0.016 ms
+XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 663 ~66.399 ms, finishGL 66 / 659 ~65.904 ms, waitGL 0 / 0 ~0.015 ms
+XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 732 ~66.55 ms, finishGL 67 / 726 ~66.051 ms, waitGL 0 / 0 ~0.015 ms
+XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 798 ~66.573 ms, finishGL 66 / 792 ~66.075 ms, waitGL 0 / 0 ~0.015 ms
+XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 864 ~66.529 ms, finishGL 65 / 858 ~66.03 ms, waitGL 0 / 0 ~0.015 ms
+XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 930 ~66.465 ms, finishGL 65 / 923 ~65.966 ms, waitGL 0 / 0 ~0.015 ms
+XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 996 ~66.452 ms, finishGL 65 / 989 ~65.954 ms, waitGL 0 / 0 ~0.015 ms
+XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1063 ~66.44 ms, finishGL 65 / 1055 ~65.943 ms, waitGL 0 / 0 ~0.015 ms
+XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1129 ~66.447 ms, finishGL 66 / 1121 ~65.95 ms, waitGL 0 / 0 ~0.016 ms
+XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1195 ~66.422 ms, finishGL 65 / 1186 ~65.925 ms, waitGL 0 / 0 ~0.015 ms
+XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1262 ~66.442 ms, finishGL 66 / 1252 ~65.946 ms, waitGL 0 / 0 ~0.015 ms
+FrameCount: 120 - FrameRate: 16.0
+XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1329 ~66.479 ms, finishGL 66 / 1319 ~65.976 ms, waitGL 0 / 0 ~0.015 ms
+XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1396 ~66.484 ms, finishGL 66 / 1385 ~65.981 ms, waitGL 0 / 0 ~0.015 ms
+XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1463 ~66.515 ms, finishGL 66 / 1452 ~66.013 ms, waitGL 0 / 0 ~0.015 ms
+XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1530 ~66.53 ms, finishGL 66 / 1518 ~66.028 ms, waitGL 0 / 0 ~0.015 ms
+XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1597 ~66.567 ms, finishGL 66 / 1585 ~66.065 ms, waitGL 0 / 0 ~0.015 ms
+XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1664 ~66.589 ms, finishGL 66 / 1652 ~66.087 ms, waitGL 0 / 0 ~0.015 ms
+XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1731 ~66.587 ms, finishGL 66 / 1718 ~66.086 ms, waitGL 0 / 0 ~0.015 ms
+XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1798 ~66.595 ms, finishGL 66 / 1784 ~66.095 ms, waitGL 0 / 0 ~0.015 ms
+XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1865 ~66.624 ms, finishGL 66 / 1851 ~66.124 ms, waitGL 0 / 0 ~0.015 ms
+XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1930 ~66.58 ms, finishGL 64 / 1916 ~66.081 ms, waitGL 0 / 0 ~0.015 ms
+XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1998 ~66.6 ms, finishGL 66 / 1983 ~66.101 ms, waitGL 0 / 0 ~0.015 ms
+XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2064 ~66.593 ms, finishGL 65 / 2048 ~66.095 ms, waitGL 0 / 0 ~0.015 ms
+XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2130 ~66.585 ms, finishGL 65 / 2114 ~66.085 ms, waitGL 0 / 0 ~0.015 ms
+XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2197 ~66.581 ms, finishGL 65 / 2180 ~66.082 ms, waitGL 0 / 0 ~0.015 ms
+XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2263 ~66.576 ms, finishGL 65 / 2246 ~66.078 ms, waitGL 0 / 0 ~0.015 ms
+XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2330 ~66.571 ms, finishGL 65 / 2312 ~66.073 ms, waitGL 0 / 0 ~0.015 ms
+XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2396 ~66.576 ms, finishGL 66 / 2378 ~66.077 ms, waitGL 0 / 0 ~0.015 ms
+XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2462 ~66.558 ms, finishGL 65 / 2444 ~66.058 ms, waitGL 0 / 0 ~0.015 ms
+XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2529 ~66.564 ms, finishGL 66 / 2510 ~66.066 ms, waitGL 0 / 0 ~0.015 ms
+XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2596 ~66.572 ms, finishGL 66 / 2576 ~66.074 ms, waitGL 0 / 0 ~0.015 ms
+XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2662 ~66.564 ms, finishGL 65 / 2642 ~66.067 ms, waitGL 0 / 0 ~0.015 ms
+XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2728 ~66.551 ms, finishGL 65 / 2708 ~66.054 ms, waitGL 0 / 0 ~0.015 ms
+XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2795 ~66.567 ms, finishGL 66 / 2774 ~66.07 ms, waitGL 0 / 0 ~0.015 ms
+XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2861 ~66.558 ms, finishGL 65 / 2840 ~66.061 ms, waitGL 0 / 0 ~0.015 ms
+XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2928 ~66.556 ms, finishGL 65 / 2906 ~66.059 ms, waitGL 0 / 0 ~0.015 ms
+XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2994 ~66.547 ms, finishGL 65 / 2972 ~66.05 ms, waitGL 0 / 0 ~0.015 ms
+XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3060 ~66.525 ms, finishGL 65 / 3037 ~66.028 ms, waitGL 0 / 0 ~0.015 ms
+XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3125 ~66.498 ms, finishGL 64 / 3101 ~65.999 ms, waitGL 0 / 0 ~0.015 ms
+XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3190 ~66.461 ms, finishGL 64 / 3166 ~65.962 ms, waitGL 0 / 0 ~0.015 ms
+XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 3254 ~66.41 ms, finishGL 63 / 3229 ~65.912 ms, waitGL 0 / 0 ~0.015 ms
+XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 3316 ~66.338 ms, finishGL 62 / 3291 ~65.839 ms, waitGL 0 / 0 ~0.015 ms
+XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 3378 ~66.251 ms, finishGL 61 / 3353 ~65.755 ms, waitGL 0 / 0 ~0.015 ms
+XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 46 / 3425 ~65.874 ms, finishGL 46 / 3399 ~65.378 ms, waitGL 0 / 0 ~0.015 ms
+XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3474 ~65.548 ms, finishGL 48 / 3447 ~65.053 ms, waitGL 0 / 0 ~0.015 ms
+XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3522 ~65.238 ms, finishGL 48 / 3496 ~64.743 ms, waitGL 0 / 0 ~0.015 ms
+XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3571 ~64.941 ms, finishGL 48 / 3544 ~64.444 ms, waitGL 0 / 0 ~0.015 ms
+XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3621 ~64.662 ms, finishGL 48 / 3593 ~64.166 ms, waitGL 0 / 0 ~0.015 ms
+XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3670 ~64.387 ms, finishGL 48 / 3641 ~63.891 ms, waitGL 0 / 0 ~0.015 ms
+XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3719 ~64.131 ms, finishGL 48 / 3690 ~63.634 ms, waitGL 0 / 0 ~0.015 ms
+XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3768 ~63.879 ms, finishGL 48 / 3739 ~63.382 ms, waitGL 0 / 0 ~0.016 ms
+XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3818 ~63.639 ms, finishGL 48 / 3788 ~63.142 ms, waitGL 0 / 0 ~0.016 ms
+XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3867 ~63.404 ms, finishGL 48 / 3837 ~62.907 ms, waitGL 0 / 0 ~0.016 ms
+XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3916 ~63.174 ms, finishGL 48 / 3886 ~62.677 ms, waitGL 0 / 0 ~0.016 ms
+XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3966 ~62.952 ms, finishGL 48 / 3934 ~62.455 ms, waitGL 0 / 1 ~0.016 ms
+XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4014 ~62.732 ms, finishGL 48 / 3983 ~62.236 ms, waitGL 0 / 1 ~0.016 ms
+XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4063 ~62.517 ms, finishGL 48 / 4031 ~62.021 ms, waitGL 0 / 1 ~0.016 ms
+XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4112 ~62.307 ms, finishGL 48 / 4079 ~61.811 ms, waitGL 0 / 1 ~0.016 ms
+XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4161 ~62.107 ms, finishGL 48 / 4127 ~61.611 ms, waitGL 0 / 1 ~0.016 ms
+XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4209 ~61.911 ms, finishGL 48 / 4175 ~61.411 ms, waitGL 0 / 1 ~0.016 ms
+XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4258 ~61.713 ms, finishGL 47 / 4223 ~61.211 ms, waitGL 0 / 1 ~0.016 ms
+XXX[70] TO 17 ms, lFrame0 1 ms, lFrameX 30 / 4289 ~61.272 ms, finishGL 29 / 4253 ~60.762 ms, waitGL 0 / 1 ~0.016 ms
+XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4339 ~61.117 ms, finishGL 49 / 4303 ~60.607 ms, waitGL 0 / 1 ~0.016 ms
+XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4371 ~60.714 ms, finishGL 31 / 4334 ~60.203 ms, waitGL 0 / 1 ~0.016 ms
+XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4404 ~60.329 ms, finishGL 32 / 4366 ~59.819 ms, waitGL 0 / 1 ~0.016 ms
+XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 27 / 4431 ~59.881 ms, finishGL 26 / 4393 ~59.369 ms, waitGL 0 / 1 ~0.016 ms
+XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 54 / 4485 ~59.812 ms, finishGL 53 / 4447 ~59.297 ms, waitGL 0 / 1 ~0.016 ms
+XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4518 ~59.447 ms, finishGL 31 / 4478 ~58.932 ms, waitGL 0 / 1 ~0.016 ms
+XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 25 / 4543 ~59.002 ms, finishGL 24 / 4503 ~58.485 ms, waitGL 0 / 1 ~0.016 ms
+XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 40 / 4583 ~58.762 ms, finishGL 39 / 4543 ~58.245 ms, waitGL 0 / 1 ~0.016 ms
+XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4632 ~58.633 ms, finishGL 47 / 4590 ~58.113 ms, waitGL 0 / 1 ~0.016 ms
+XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4664 ~58.309 ms, finishGL 32 / 4623 ~57.79 ms, waitGL 0 / 1 ~0.016 ms
+XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4688 ~57.883 ms, finishGL 22 / 4646 ~57.36 ms, waitGL 0 / 1 ~0.016 ms
+XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 26 / 4715 ~57.503 ms, finishGL 26 / 4672 ~56.981 ms, waitGL 0 / 1 ~0.016 ms
+XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4764 ~57.404 ms, finishGL 48 / 4721 ~56.882 ms, waitGL 0 / 1 ~0.016 ms
+XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4797 ~57.113 ms, finishGL 32 / 4753 ~56.59 ms, waitGL 0 / 1 ~0.016 ms
+XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4821 ~56.72 ms, finishGL 22 / 4776 ~56.195 ms, waitGL 0 / 1 ~0.016 ms
+XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 45 / 4866 ~56.59 ms, finishGL 45 / 4821 ~56.066 ms, waitGL 0 / 1 ~0.016 ms
+XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 37 / 4904 ~56.373 ms, finishGL 37 / 4858 ~55.849 ms, waitGL 0 / 1 ~0.016 ms
+XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4937 ~56.111 ms, finishGL 32 / 4891 ~55.585 ms, waitGL 0 / 1 ~0.016 ms
+XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 57 / 4994 ~56.123 ms, finishGL 56 / 4948 ~55.597 ms, waitGL 0 / 1 ~0.016 ms
+XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 5048 ~56.092 ms, finishGL 52 / 5001 ~55.567 ms, waitGL 0 / 1 ~0.016 ms
+XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 41 / 5089 ~55.932 ms, finishGL 40 / 5041 ~55.405 ms, waitGL 0 / 1 ~0.016 ms
+XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 5166 ~56.159 ms, finishGL 76 / 5118 ~55.633 ms, waitGL 0 / 1 ~0.016 ms
+XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5216 ~56.093 ms, finishGL 49 / 5167 ~55.567 ms, waitGL 0 / 1 ~0.016 ms
+XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 5259 ~55.956 ms, finishGL 42 / 5210 ~55.427 ms, waitGL 0 / 1 ~0.016 ms
+XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 5333 ~56.137 ms, finishGL 72 / 5282 ~55.606 ms, waitGL 0 / 1 ~0.016 ms
+XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5383 ~56.075 ms, finishGL 49 / 5332 ~55.545 ms, waitGL 0 / 1 ~0.016 ms
+XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 5427 ~55.949 ms, finishGL 43 / 5375 ~55.416 ms, waitGL 0 / 1 ~0.016 ms
+XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5499 ~56.116 ms, finishGL 71 / 5447 ~55.582 ms, waitGL 0 / 1 ~0.016 ms
+XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5549 ~56.06 ms, finishGL 50 / 5497 ~55.526 ms, waitGL 0 / 1 ~0.016 ms
+XXX[100] TO 17 ms, lFrame0 0 ms, lFrameX 44 / 5594 ~55.946 ms, finishGL 43 / 5541 ~55.41 ms, waitGL 0 / 1 ~0.016 ms
+XXX[101] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5667 ~56.112 ms, finishGL 72 / 5613 ~55.576 ms, waitGL 0 / 1 ~0.016 ms
+XXX[102] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5718 ~56.06 ms, finishGL 50 / 5663 ~55.525 ms, waitGL 0 / 1 ~0.016 ms
+XXX[103] TO 17 ms, lFrame0 0 ms, lFrameX 46 / 5764 ~55.97 ms, finishGL 46 / 5709 ~55.433 ms, waitGL 0 / 1 ~0.016 ms
+XXX[104] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5836 ~56.124 ms, finishGL 71 / 5781 ~55.588 ms, waitGL 0 / 1 ~0.016 ms
+XXX[105] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 5905 ~56.239 ms, finishGL 67 / 5848 ~55.704 ms, waitGL 0 / 1 ~0.016 ms
+XXX[106] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 5956 ~56.191 ms, finishGL 50 / 5899 ~55.653 ms, waitGL 0 / 1 ~0.016 ms
+XXX[107] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 6040 ~56.453 ms, finishGL 83 / 5983 ~55.916 ms, waitGL 0 / 1 ~0.016 ms
+XXX[108] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 6110 ~56.579 ms, finishGL 69 / 6052 ~56.041 ms, waitGL 0 / 1 ~0.016 ms
+XXX[109] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 6170 ~56.614 ms, finishGL 59 / 6112 ~56.075 ms, waitGL 0 / 1 ~0.016 ms
+XXX[110] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 6265 ~56.956 ms, finishGL 93 / 6206 ~56.418 ms, waitGL 0 / 1 ~0.016 ms
+XXX[111] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 6333 ~57.058 ms, finishGL 67 / 6273 ~56.518 ms, waitGL 0 / 1 ~0.016 ms
+XXX[112] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 6396 ~57.114 ms, finishGL 62 / 6336 ~56.571 ms, waitGL 0 / 1 ~0.016 ms
+XXX[113] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 6483 ~57.373 ms, finishGL 85 / 6421 ~56.829 ms, waitGL 0 / 1 ~0.016 ms
+XXX[114] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6549 ~57.455 ms, finishGL 66 / 6487 ~56.91 ms, waitGL 0 / 1 ~0.016 ms
+XXX[115] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 6613 ~57.507 ms, finishGL 62 / 6550 ~56.961 ms, waitGL 0 / 1 ~0.016 ms
+XXX[116] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 6702 ~57.775 ms, finishGL 88 / 6638 ~57.229 ms, waitGL 0 / 1 ~0.015 ms
+XXX[117] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 6786 ~58.001 ms, finishGL 83 / 6722 ~57.453 ms, waitGL 0 / 1 ~0.015 ms
+XXX[118] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6852 ~58.072 ms, finishGL 65 / 6787 ~57.522 ms, waitGL 0 / 1 ~0.015 ms
+XXX[119] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 6952 ~58.425 ms, finishGL 99 / 6887 ~57.876 ms, waitGL 0 / 1 ~0.016 ms
+XXX[120] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7035 ~58.629 ms, finishGL 82 / 6969 ~58.081 ms, waitGL 0 / 1 ~0.015 ms
+XXX[121] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7102 ~58.699 ms, finishGL 66 / 7036 ~58.148 ms, waitGL 0 / 1 ~0.016 ms
+XXX[122] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 7203 ~59.044 ms, finishGL 100 / 7136 ~58.494 ms, waitGL 0 / 1 ~0.016 ms
+XXX[123] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7287 ~59.249 ms, finishGL 83 / 7220 ~58.701 ms, waitGL 0 / 1 ~0.015 ms
+XXX[124] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 7359 ~59.349 ms, finishGL 70 / 7291 ~58.8 ms, waitGL 0 / 1 ~0.015 ms
+XXX[125] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 7458 ~59.665 ms, finishGL 98 / 7389 ~59.114 ms, waitGL 0 / 1 ~0.015 ms
+XXX[126] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7542 ~59.86 ms, finishGL 83 / 7472 ~59.308 ms, waitGL 0 / 2 ~0.016 ms
+XXX[127] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 7618 ~59.989 ms, finishGL 75 / 7548 ~59.437 ms, waitGL 0 / 2 ~0.015 ms
+XXX[128] TO 17 ms, lFrame0 0 ms, lFrameX 93 / 7712 ~60.252 ms, finishGL 93 / 7641 ~59.701 ms, waitGL 0 / 2 ~0.015 ms
+XXX[129] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7793 ~60.415 ms, finishGL 80 / 7722 ~59.865 ms, waitGL 0 / 2 ~0.015 ms
+2013-06-17 03:01:17.725 java[63231:5f07] Persistent UI failed to open file file://localhost/Users/jogamp/Library/Saved%20Application%20State/com.apple.javajdk16.cmd.savedState/window_1.data: Operation not permitted (1)
+XXX[130] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 7873 ~60.562 ms, finishGL 79 / 7801 ~60.012 ms, waitGL 0 / 2 ~0.015 ms
+XXX[131] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7954 ~60.719 ms, finishGL 80 / 7882 ~60.168 ms, waitGL 0 / 2 ~0.015 ms
+XXX[132] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8036 ~60.885 ms, finishGL 82 / 7964 ~60.335 ms, waitGL 0 / 2 ~0.015 ms
+XXX[133] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 8118 ~61.038 ms, finishGL 80 / 8045 ~60.489 ms, waitGL 0 / 2 ~0.015 ms
+XXX[134] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8200 ~61.195 ms, finishGL 81 / 8126 ~60.646 ms, waitGL 0 / 2 ~0.015 ms
+XXX[135] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8282 ~61.353 ms, finishGL 81 / 8208 ~60.804 ms, waitGL 0 / 2 ~0.016 ms
+XXX[136] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8365 ~61.51 ms, finishGL 82 / 8290 ~60.962 ms, waitGL 0 / 2 ~0.016 ms
+XXX[137] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8448 ~61.666 ms, finishGL 82 / 8373 ~61.118 ms, waitGL 0 / 2 ~0.016 ms
+XXX[138] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8531 ~61.822 ms, finishGL 82 / 8456 ~61.275 ms, waitGL 0 / 2 ~0.016 ms
+XXX[139] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8614 ~61.973 ms, finishGL 82 / 8538 ~61.425 ms, waitGL 0 / 2 ~0.016 ms
+FrameCount: 240 - FrameRate: 13.0
+XXX[140] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8679 ~61.996 ms, finishGL 64 / 8602 ~61.448 ms, waitGL 0 / 2 ~0.016 ms
+XXX[141] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 8746 ~62.032 ms, finishGL 66 / 8669 ~61.485 ms, waitGL 0 / 2 ~0.016 ms
+XXX[142] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8812 ~62.063 ms, finishGL 65 / 8735 ~61.516 ms, waitGL 0 / 2 ~0.016 ms
+XXX[143] TO 17 ms, lFrame0 5 ms, lFrameX 69 / 8882 ~62.114 ms, finishGL 64 / 8799 ~61.534 ms, waitGL 0 / 2 ~0.016 ms
+XXX[144] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 8962 ~62.24 ms, finishGL 79 / 8879 ~61.661 ms, waitGL 0 / 2 ~0.016 ms
+XXX[145] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9028 ~62.262 ms, finishGL 65 / 8944 ~61.684 ms, waitGL 0 / 2 ~0.016 ms
+XXX[146] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9093 ~62.287 ms, finishGL 65 / 9009 ~61.709 ms, waitGL 0 / 2 ~0.016 ms
+XXX[147] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9160 ~62.315 ms, finishGL 65 / 9075 ~61.737 ms, waitGL 0 / 2 ~0.016 ms
+XXX[148] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9226 ~62.342 ms, finishGL 65 / 9141 ~61.766 ms, waitGL 0 / 2 ~0.016 ms
+XXX[149] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9293 ~62.372 ms, finishGL 66 / 9207 ~61.794 ms, waitGL 0 / 2 ~0.016 ms
+XXX[150] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9361 ~62.406 ms, finishGL 67 / 9274 ~61.829 ms, waitGL 0 / 2 ~0.016 ms
+XXX[151] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9426 ~62.427 ms, finishGL 64 / 9339 ~61.849 ms, waitGL 0 / 2 ~0.016 ms
+XXX[152] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9493 ~62.453 ms, finishGL 66 / 9405 ~61.876 ms, waitGL 0 / 2 ~0.016 ms
+XXX[153] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9559 ~62.479 ms, finishGL 65 / 9471 ~61.902 ms, waitGL 0 / 2 ~0.016 ms
+XXX[154] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9625 ~62.501 ms, finishGL 65 / 9536 ~61.925 ms, waitGL 0 / 2 ~0.016 ms
+XXX[155] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9692 ~62.532 ms, finishGL 66 / 9603 ~61.956 ms, waitGL 0 / 2 ~0.016 ms
+XXX[156] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9759 ~62.559 ms, finishGL 66 / 9669 ~61.983 ms, waitGL 0 / 2 ~0.016 ms
+XXX[157] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9825 ~62.583 ms, finishGL 65 / 9735 ~62.008 ms, waitGL 0 / 2 ~0.016 ms
+XXX[158] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9890 ~62.599 ms, finishGL 64 / 9799 ~62.024 ms, waitGL 0 / 2 ~0.015 ms
+XXX[159] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9957 ~62.624 ms, finishGL 66 / 9866 ~62.051 ms, waitGL 0 / 2 ~0.015 ms
+XXX[160] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10023 ~62.646 ms, finishGL 65 / 9931 ~62.072 ms, waitGL 0 / 2 ~0.015 ms
+XXX[161] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10089 ~62.665 ms, finishGL 65 / 9996 ~62.092 ms, waitGL 0 / 2 ~0.015 ms
+XXX[162] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10155 ~62.687 ms, finishGL 65 / 10062 ~62.115 ms, waitGL 0 / 2 ~0.015 ms
+XXX[163] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10221 ~62.709 ms, finishGL 65 / 10128 ~62.138 ms, waitGL 0 / 2 ~0.015 ms
+XXX[164] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 10287 ~62.729 ms, finishGL 64 / 10193 ~62.155 ms, waitGL 0 / 2 ~0.015 ms
+XXX[165] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10354 ~62.754 ms, finishGL 66 / 10259 ~62.179 ms, waitGL 0 / 2 ~0.015 ms
+XXX[166] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10420 ~62.772 ms, finishGL 65 / 10324 ~62.197 ms, waitGL 0 / 2 ~0.015 ms
+XXX[167] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10486 ~62.793 ms, finishGL 65 / 10390 ~62.22 ms, waitGL 0 / 2 ~0.015 ms
+XXX[168] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10553 ~62.816 ms, finishGL 66 / 10456 ~62.243 ms, waitGL 0 / 2 ~0.015 ms
+XXX[169] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10619 ~62.839 ms, finishGL 66 / 10523 ~62.266 ms, waitGL 0 / 2 ~0.015 ms
+XXX[170] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10686 ~62.861 ms, finishGL 66 / 10589 ~62.289 ms, waitGL 0 / 2 ~0.015 ms
+XXX[171] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10753 ~62.884 ms, finishGL 66 / 10655 ~62.312 ms, waitGL 0 / 2 ~0.015 ms
+XXX[172] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10819 ~62.906 ms, finishGL 66 / 10721 ~62.335 ms, waitGL 0 / 2 ~0.015 ms
+XXX[173] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10887 ~62.931 ms, finishGL 66 / 10788 ~62.36 ms, waitGL 0 / 2 ~0.015 ms
+XXX[174] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10953 ~62.951 ms, finishGL 65 / 10854 ~62.38 ms, waitGL 0 / 2 ~0.016 ms
+XXX[175] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11020 ~62.972 ms, finishGL 66 / 10920 ~62.402 ms, waitGL 0 / 2 ~0.015 ms
+XXX[176] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11086 ~62.99 ms, finishGL 65 / 10986 ~62.421 ms, waitGL 0 / 2 ~0.015 ms
+XXX[177] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11153 ~63.012 ms, finishGL 66 / 11052 ~62.443 ms, waitGL 0 / 2 ~0.016 ms
+XXX[178] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11220 ~63.035 ms, finishGL 66 / 11118 ~62.466 ms, waitGL 0 / 2 ~0.015 ms
+XXX[179] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11288 ~63.061 ms, finishGL 67 / 11186 ~62.493 ms, waitGL 0 / 2 ~0.016 ms
+XXX[180] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11355 ~63.088 ms, finishGL 67 / 11253 ~62.52 ms, waitGL 0 / 2 ~0.015 ms
+XXX[181] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11422 ~63.107 ms, finishGL 65 / 11319 ~62.539 ms, waitGL 0 / 2 ~0.015 ms
+XXX[182] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11490 ~63.132 ms, finishGL 67 / 11386 ~62.565 ms, waitGL 0 / 2 ~0.015 ms
+XXX[183] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11557 ~63.154 ms, finishGL 66 / 11453 ~62.587 ms, waitGL 0 / 2 ~0.016 ms
+XXX[184] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11624 ~63.177 ms, finishGL 66 / 11520 ~62.611 ms, waitGL 0 / 2 ~0.016 ms
+XXX[185] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11709 ~63.294 ms, finishGL 84 / 11604 ~62.728 ms, waitGL 0 / 2 ~0.016 ms
+XXX[186] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11794 ~63.412 ms, finishGL 84 / 11689 ~62.847 ms, waitGL 0 / 2 ~0.016 ms
+XXX[187] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 11881 ~63.536 ms, finishGL 86 / 11775 ~62.971 ms, waitGL 0 / 2 ~0.016 ms
+XXX[188] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 11967 ~63.657 ms, finishGL 85 / 11861 ~63.092 ms, waitGL 0 / 3 ~0.016 ms
+XXX[189] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 12052 ~63.771 ms, finishGL 84 / 11946 ~63.206 ms, waitGL 0 / 3 ~0.016 ms
+XXX[190] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12137 ~63.882 ms, finishGL 84 / 12030 ~63.318 ms, waitGL 0 / 3 ~0.016 ms
+XXX[191] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12221 ~63.986 ms, finishGL 83 / 12113 ~63.422 ms, waitGL 0 / 3 ~0.016 ms
+XXX[192] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12306 ~64.094 ms, finishGL 84 / 12197 ~63.53 ms, waitGL 0 / 3 ~0.016 ms
+XXX[193] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12405 ~64.276 ms, finishGL 98 / 12296 ~63.712 ms, waitGL 0 / 3 ~0.016 ms
+XXX[194] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12489 ~64.376 ms, finishGL 83 / 12379 ~63.812 ms, waitGL 0 / 3 ~0.016 ms
+XXX[195] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12588 ~64.557 ms, finishGL 99 / 12478 ~63.994 ms, waitGL 0 / 3 ~0.016 ms
+XXX[196] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12671 ~64.648 ms, finishGL 81 / 12560 ~64.085 ms, waitGL 0 / 3 ~0.016 ms
+XXX[197] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 12752 ~64.735 ms, finishGL 81 / 12642 ~64.173 ms, waitGL 0 / 3 ~0.016 ms
+XXX[198] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 12835 ~64.823 ms, finishGL 81 / 12723 ~64.259 ms, waitGL 0 / 3 ~0.016 ms
+XXX[199] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12918 ~64.914 ms, finishGL 82 / 12805 ~64.35 ms, waitGL 0 / 3 ~0.016 ms
+XXX[200] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13001 ~65.005 ms, finishGL 82 / 12888 ~64.441 ms, waitGL 0 / 3 ~0.016 ms
+XXX[201] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13084 ~65.094 ms, finishGL 82 / 12970 ~64.531 ms, waitGL 0 / 3 ~0.016 ms
+XXX[202] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13167 ~65.185 ms, finishGL 82 / 13053 ~64.622 ms, waitGL 0 / 3 ~0.016 ms
+XXX[203] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13250 ~65.274 ms, finishGL 82 / 13136 ~64.711 ms, waitGL 0 / 3 ~0.016 ms
+XXX[204] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13333 ~65.36 ms, finishGL 82 / 13218 ~64.798 ms, waitGL 0 / 3 ~0.016 ms
+XXX[205] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13416 ~65.447 ms, finishGL 82 / 13301 ~64.885 ms, waitGL 0 / 3 ~0.016 ms
+XXX[206] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13498 ~65.527 ms, finishGL 81 / 13383 ~64.966 ms, waitGL 0 / 3 ~0.016 ms
+XXX[207] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13580 ~65.608 ms, finishGL 81 / 13464 ~65.047 ms, waitGL 0 / 3 ~0.016 ms
+XXX[208] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13663 ~65.687 ms, finishGL 81 / 13546 ~65.126 ms, waitGL 0 / 3 ~0.016 ms
+XXX[209] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13744 ~65.764 ms, finishGL 81 / 13627 ~65.204 ms, waitGL 0 / 3 ~0.016 ms
+XXX[210] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13826 ~65.84 ms, finishGL 81 / 13708 ~65.279 ms, waitGL 0 / 3 ~0.016 ms
+XXX[211] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13908 ~65.915 ms, finishGL 81 / 13789 ~65.354 ms, waitGL 0 / 3 ~0.016 ms
+XXX[212] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13989 ~65.99 ms, finishGL 81 / 13871 ~65.43 ms, waitGL 0 / 3 ~0.016 ms
+XXX[213] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 14071 ~66.064 ms, finishGL 81 / 13952 ~65.504 ms, waitGL 0 / 3 ~0.016 ms
+XXX[214] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 14153 ~66.137 ms, finishGL 81 / 14033 ~65.577 ms, waitGL 0 / 3 ~0.016 ms
+XXX[215] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 14235 ~66.211 ms, finishGL 81 / 14115 ~65.652 ms, waitGL 0 / 3 ~0.016 ms
+XXX[216] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 14301 ~66.212 ms, finishGL 65 / 14181 ~65.653 ms, waitGL 0 / 3 ~0.016 ms
+XXX[217] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14369 ~66.216 ms, finishGL 66 / 14247 ~65.658 ms, waitGL 0 / 3 ~0.016 ms
+XXX[218] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14452 ~66.296 ms, finishGL 83 / 14330 ~65.738 ms, waitGL 0 / 3 ~0.016 ms
+XXX[219] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14538 ~66.385 ms, finishGL 85 / 14416 ~65.827 ms, waitGL 0 / 3 ~0.016 ms
+XXX[220] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14624 ~66.473 ms, finishGL 85 / 14501 ~65.915 ms, waitGL 0 / 3 ~0.016 ms
+XXX[221] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14709 ~66.56 ms, finishGL 85 / 14586 ~66.003 ms, waitGL 0 / 3 ~0.016 ms
+XXX[222] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 14795 ~66.648 ms, finishGL 85 / 14672 ~66.091 ms, waitGL 0 / 3 ~0.016 ms
+XXX[223] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 14880 ~66.73 ms, finishGL 84 / 14756 ~66.173 ms, waitGL 0 / 3 ~0.016 ms
+XXX[224] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14964 ~66.804 ms, finishGL 82 / 14839 ~66.247 ms, waitGL 0 / 3 ~0.016 ms
+XXX[225] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 15047 ~66.876 ms, finishGL 82 / 14921 ~66.319 ms, waitGL 0 / 3 ~0.016 ms
+XXX[226] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15129 ~66.946 ms, finishGL 82 / 15004 ~66.389 ms, waitGL 0 / 3 ~0.016 ms
+XXX[227] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15212 ~67.017 ms, finishGL 82 / 15086 ~66.46 ms, waitGL 0 / 3 ~0.016 ms
+XXX[228] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15295 ~67.085 ms, finishGL 82 / 15168 ~66.529 ms, waitGL 0 / 3 ~0.016 ms
+XXX[229] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15377 ~67.152 ms, finishGL 81 / 15250 ~66.596 ms, waitGL 0 / 3 ~0.016 ms
+XXX[230] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15460 ~67.219 ms, finishGL 82 / 15332 ~66.663 ms, waitGL 0 / 3 ~0.016 ms
+XXX[231] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15542 ~67.283 ms, finishGL 81 / 15414 ~66.727 ms, waitGL 0 / 3 ~0.016 ms
+XXX[232] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15624 ~67.346 ms, finishGL 81 / 15495 ~66.791 ms, waitGL 0 / 3 ~0.016 ms
+XXX[233] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15706 ~67.411 ms, finishGL 81 / 15577 ~66.856 ms, waitGL 0 / 3 ~0.016 ms
+XXX[234] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15787 ~67.469 ms, finishGL 80 / 15658 ~66.915 ms, waitGL 0 / 3 ~0.016 ms
+XXX[235] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15869 ~67.529 ms, finishGL 81 / 15739 ~66.975 ms, waitGL 0 / 3 ~0.016 ms
+XXX[236] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15951 ~67.591 ms, finishGL 81 / 15820 ~67.037 ms, waitGL 0 / 3 ~0.016 ms
+XXX[237] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 16033 ~67.651 ms, finishGL 81 / 15902 ~67.097 ms, waitGL 0 / 3 ~0.016 ms
+XXX[238] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 16115 ~67.711 ms, finishGL 81 / 15983 ~67.157 ms, waitGL 0 / 3 ~0.016 ms
+XXX[239] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16181 ~67.705 ms, finishGL 65 / 16049 ~67.152 ms, waitGL 0 / 3 ~0.016 ms
+XXX[240] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16248 ~67.7 ms, finishGL 66 / 16115 ~67.148 ms, waitGL 0 / 3 ~0.016 ms
+XXX[241] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16314 ~67.694 ms, finishGL 65 / 16181 ~67.141 ms, waitGL 0 / 3 ~0.016 ms
+XXX[242] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16381 ~67.69 ms, finishGL 66 / 16247 ~67.138 ms, waitGL 0 / 3 ~0.016 ms
+XXX[243] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16446 ~67.681 ms, finishGL 64 / 16312 ~67.129 ms, waitGL 0 / 3 ~0.016 ms
+XXX[244] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16513 ~67.677 ms, finishGL 66 / 16378 ~67.125 ms, waitGL 0 / 3 ~0.016 ms
+XXX[245] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16579 ~67.671 ms, finishGL 65 / 16444 ~67.119 ms, waitGL 0 / 3 ~0.016 ms
+XXX[246] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16645 ~67.664 ms, finishGL 65 / 16509 ~67.112 ms, waitGL 0 / 3 ~0.016 ms
+XXX[247] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16712 ~67.661 ms, finishGL 66 / 16576 ~67.11 ms, waitGL 0 / 3 ~0.016 ms
+XXX[248] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16779 ~67.657 ms, finishGL 66 / 16642 ~67.106 ms, waitGL 0 / 3 ~0.016 ms
+XXX[249] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16846 ~67.656 ms, finishGL 66 / 16709 ~67.104 ms, waitGL 0 / 4 ~0.016 ms
+XXX[250] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16913 ~67.655 ms, finishGL 67 / 16776 ~67.105 ms, waitGL 0 / 4 ~0.016 ms
+XXX[251] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 16998 ~67.723 ms, finishGL 84 / 16860 ~67.172 ms, waitGL 0 / 4 ~0.016 ms
+XXX[252] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17083 ~67.79 ms, finishGL 84 / 16944 ~67.239 ms, waitGL 0 / 4 ~0.016 ms
+XXX[253] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 17168 ~67.859 ms, finishGL 84 / 17029 ~67.309 ms, waitGL 0 / 4 ~0.016 ms
+XXX[254] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 17253 ~67.928 ms, finishGL 84 / 17114 ~67.378 ms, waitGL 0 / 4 ~0.016 ms
+XXX[255] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17338 ~67.994 ms, finishGL 84 / 17198 ~67.444 ms, waitGL 0 / 4 ~0.016 ms
+XXX[256] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17423 ~68.06 ms, finishGL 84 / 17282 ~67.51 ms, waitGL 0 / 4 ~0.016 ms
+XXX[257] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17507 ~68.123 ms, finishGL 83 / 17366 ~67.574 ms, waitGL 0 / 4 ~0.016 ms
+XXX[258] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17592 ~68.188 ms, finishGL 84 / 17451 ~67.64 ms, waitGL 0 / 4 ~0.016 ms
+XXX[259] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17676 ~68.25 ms, finishGL 83 / 17534 ~67.702 ms, waitGL 0 / 4 ~0.016 ms
+FrameCount: 360 - FrameRate: 15.0
+XXX[260] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17760 ~68.309 ms, finishGL 82 / 17617 ~67.76 ms, waitGL 0 / 4 ~0.016 ms
+XXX[261] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17843 ~68.367 ms, finishGL 82 / 17700 ~67.818 ms, waitGL 0 / 4 ~0.016 ms
+XXX[262] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17926 ~68.423 ms, finishGL 82 / 17783 ~67.875 ms, waitGL 0 / 4 ~0.016 ms
+XXX[263] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18009 ~68.478 ms, finishGL 82 / 17865 ~67.93 ms, waitGL 0 / 4 ~0.016 ms
+XXX[264] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18092 ~68.532 ms, finishGL 82 / 17947 ~67.984 ms, waitGL 0 / 4 ~0.016 ms
+XXX[265] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18175 ~68.586 ms, finishGL 82 / 18030 ~68.038 ms, waitGL 0 / 4 ~0.016 ms
+XXX[266] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18257 ~68.638 ms, finishGL 81 / 18111 ~68.089 ms, waitGL 0 / 4 ~0.016 ms
+XXX[267] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18340 ~68.691 ms, finishGL 82 / 18194 ~68.143 ms, waitGL 0 / 4 ~0.016 ms
+XXX[268] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18423 ~68.743 ms, finishGL 81 / 18276 ~68.194 ms, waitGL 0 / 4 ~0.016 ms
+XXX[269] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18505 ~68.794 ms, finishGL 82 / 18358 ~68.246 ms, waitGL 0 / 4 ~0.016 ms
+XXX[270] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18588 ~68.844 ms, finishGL 81 / 18440 ~68.296 ms, waitGL 0 / 4 ~0.016 ms
+XXX[271] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18669 ~68.892 ms, finishGL 81 / 18521 ~68.344 ms, waitGL 0 / 4 ~0.016 ms
+XXX[272] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18751 ~68.939 ms, finishGL 81 / 18602 ~68.391 ms, waitGL 0 / 4 ~0.016 ms
+XXX[273] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18833 ~68.987 ms, finishGL 81 / 18684 ~68.44 ms, waitGL 0 / 4 ~0.016 ms
+XXX[274] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18915 ~69.036 ms, finishGL 81 / 18766 ~68.489 ms, waitGL 0 / 4 ~0.016 ms
+XXX[275] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18998 ~69.084 ms, finishGL 81 / 18847 ~68.537 ms, waitGL 0 / 4 ~0.016 ms
+XXX[276] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19080 ~69.132 ms, finishGL 81 / 18929 ~68.585 ms, waitGL 0 / 4 ~0.016 ms
+XXX[277] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19162 ~69.179 ms, finishGL 81 / 19011 ~68.633 ms, waitGL 0 / 4 ~0.016 ms
+XXX[278] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19245 ~69.228 ms, finishGL 82 / 19093 ~68.682 ms, waitGL 0 / 4 ~0.016 ms
+XXX[279] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19327 ~69.274 ms, finishGL 81 / 19175 ~68.728 ms, waitGL 0 / 4 ~0.016 ms
+XXX[280] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19410 ~69.322 ms, finishGL 82 / 19257 ~68.777 ms, waitGL 0 / 4 ~0.016 ms
+XXX[281] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19492 ~69.368 ms, finishGL 81 / 19339 ~68.823 ms, waitGL 0 / 4 ~0.016 ms
+XXX[282] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19575 ~69.415 ms, finishGL 82 / 19421 ~68.87 ms, waitGL 0 / 4 ~0.016 ms
+XXX[283] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19640 ~69.402 ms, finishGL 65 / 19486 ~68.857 ms, waitGL 0 / 4 ~0.016 ms
+XXX[284] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19706 ~69.389 ms, finishGL 65 / 19552 ~68.845 ms, waitGL 0 / 4 ~0.016 ms
+XXX[285] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19772 ~69.375 ms, finishGL 64 / 19616 ~68.83 ms, waitGL 0 / 4 ~0.016 ms
+XXX[286] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19837 ~69.362 ms, finishGL 65 / 19681 ~68.817 ms, waitGL 0 / 4 ~0.016 ms
+XXX[287] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19902 ~69.348 ms, finishGL 64 / 19746 ~68.804 ms, waitGL 0 / 4 ~0.016 ms
+XXX[288] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19968 ~69.336 ms, finishGL 65 / 19812 ~68.792 ms, waitGL 0 / 4 ~0.016 ms
+XXX[289] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20034 ~69.322 ms, finishGL 64 / 19877 ~68.778 ms, waitGL 0 / 4 ~0.016 ms
+XXX[290] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 20098 ~69.306 ms, finishGL 64 / 19941 ~68.762 ms, waitGL 0 / 4 ~0.016 ms
+XXX[291] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20163 ~69.292 ms, finishGL 64 / 20005 ~68.748 ms, waitGL 0 / 4 ~0.016 ms
+XXX[292] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20230 ~69.281 ms, finishGL 65 / 20071 ~68.738 ms, waitGL 0 / 4 ~0.016 ms
+XXX[293] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20295 ~69.267 ms, finishGL 64 / 20136 ~68.724 ms, waitGL 0 / 4 ~0.016 ms
+XXX[294] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20361 ~69.257 ms, finishGL 65 / 20202 ~68.714 ms, waitGL 0 / 4 ~0.016 ms
+XXX[295] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20427 ~69.244 ms, finishGL 65 / 20267 ~68.702 ms, waitGL 0 / 4 ~0.016 ms
+XXX[296] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20493 ~69.233 ms, finishGL 65 / 20332 ~68.691 ms, waitGL 0 / 4 ~0.016 ms
+XXX[297] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20559 ~69.222 ms, finishGL 65 / 20398 ~68.68 ms, waitGL 0 / 4 ~0.016 ms
+XXX[298] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20625 ~69.212 ms, finishGL 65 / 20463 ~68.67 ms, waitGL 0 / 4 ~0.016 ms
+XXX[299] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20691 ~69.202 ms, finishGL 65 / 20529 ~68.66 ms, waitGL 0 / 4 ~0.016 ms
+XXX[300] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20758 ~69.193 ms, finishGL 66 / 20595 ~68.652 ms, waitGL 0 / 4 ~0.016 ms
+XXX[301] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20825 ~69.187 ms, finishGL 66 / 20662 ~68.645 ms, waitGL 0 / 4 ~0.016 ms
+XXX[302] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20892 ~69.181 ms, finishGL 66 / 20729 ~68.64 ms, waitGL 0 / 4 ~0.016 ms
+XXX[303] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20960 ~69.177 ms, finishGL 67 / 20796 ~68.635 ms, waitGL 0 / 4 ~0.016 ms
+XXX[304] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 21029 ~69.175 ms, finishGL 68 / 20864 ~68.634 ms, waitGL 0 / 4 ~0.016 ms
+XXX[305] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 21097 ~69.172 ms, finishGL 67 / 20932 ~68.631 ms, waitGL 0 / 4 ~0.016 ms
+XXX[306] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 21166 ~69.173 ms, finishGL 68 / 21001 ~68.632 ms, waitGL 0 / 4 ~0.016 ms
+XXX[307] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 21237 ~69.178 ms, finishGL 70 / 21072 ~68.638 ms, waitGL 0 / 4 ~0.016 ms
+XXX[308] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 21309 ~69.185 ms, finishGL 70 / 21142 ~68.645 ms, waitGL 0 / 4 ~0.016 ms
+XXX[309] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 21397 ~69.246 ms, finishGL 87 / 21230 ~68.706 ms, waitGL 0 / 4 ~0.016 ms
+XXX[310] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 21482 ~69.298 ms, finishGL 85 / 21315 ~68.759 ms, waitGL 0 / 4 ~0.016 ms
+XXX[311] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 21568 ~69.351 ms, finishGL 85 / 21400 ~68.811 ms, waitGL 0 / 5 ~0.016 ms
+XXX[312] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21652 ~69.398 ms, finishGL 83 / 21484 ~68.859 ms, waitGL 0 / 5 ~0.016 ms
+XXX[313] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 21735 ~69.442 ms, finishGL 82 / 21566 ~68.903 ms, waitGL 0 / 5 ~0.016 ms
+XXX[314] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 21818 ~69.485 ms, finishGL 82 / 21649 ~68.946 ms, waitGL 0 / 5 ~0.016 ms
+XXX[315] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 21901 ~69.529 ms, finishGL 82 / 21731 ~68.99 ms, waitGL 0 / 5 ~0.016 ms
+XXX[316] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21985 ~69.575 ms, finishGL 83 / 21815 ~69.036 ms, waitGL 0 / 5 ~0.016 ms
+XXX[317] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 22070 ~69.622 ms, finishGL 83 / 21899 ~69.083 ms, waitGL 0 / 5 ~0.016 ms
+XXX[318] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 22171 ~69.72 ms, finishGL 100 / 21999 ~69.182 ms, waitGL 0 / 5 ~0.016 ms
+XXX[319] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 22270 ~69.814 ms, finishGL 98 / 22098 ~69.274 ms, waitGL 0 / 5 ~0.016 ms
+XXX[320] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 22369 ~69.904 ms, finishGL 98 / 22197 ~69.365 ms, waitGL 0 / 5 ~0.016 ms
+XXX[321] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22451 ~69.942 ms, finishGL 81 / 22278 ~69.403 ms, waitGL 0 / 5 ~0.016 ms
+XXX[322] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22534 ~69.982 ms, finishGL 82 / 22360 ~69.443 ms, waitGL 0 / 5 ~0.016 ms
+XXX[323] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22617 ~70.022 ms, finishGL 82 / 22443 ~69.483 ms, waitGL 0 / 5 ~0.016 ms
+XXX[324] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22700 ~70.063 ms, finishGL 82 / 22526 ~69.525 ms, waitGL 0 / 5 ~0.016 ms
+XXX[325] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22783 ~70.102 ms, finishGL 82 / 22608 ~69.564 ms, waitGL 0 / 5 ~0.016 ms
+XXX[326] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22866 ~70.143 ms, finishGL 83 / 22691 ~69.605 ms, waitGL 0 / 5 ~0.016 ms
+XXX[327] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22950 ~70.183 ms, finishGL 82 / 22774 ~69.645 ms, waitGL 0 / 5 ~0.016 ms
+XXX[328] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23033 ~70.223 ms, finishGL 82 / 22856 ~69.685 ms, waitGL 0 / 5 ~0.016 ms
+XXX[329] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23116 ~70.263 ms, finishGL 83 / 22939 ~69.725 ms, waitGL 0 / 5 ~0.016 ms
+XXX[330] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23198 ~70.298 ms, finishGL 81 / 23021 ~69.761 ms, waitGL 0 / 5 ~0.016 ms
+XXX[331] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 23283 ~70.343 ms, finishGL 84 / 23105 ~69.806 ms, waitGL 0 / 5 ~0.016 ms
+XXX[332] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23367 ~70.383 ms, finishGL 83 / 23189 ~69.846 ms, waitGL 0 / 5 ~0.016 ms
+XXX[333] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23450 ~70.422 ms, finishGL 82 / 23271 ~69.885 ms, waitGL 0 / 5 ~0.016 ms
+XXX[334] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23533 ~70.459 ms, finishGL 82 / 23354 ~69.922 ms, waitGL 0 / 5 ~0.016 ms
+XXX[335] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23616 ~70.495 ms, finishGL 82 / 23436 ~69.958 ms, waitGL 0 / 5 ~0.016 ms
+XXX[336] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23699 ~70.534 ms, finishGL 82 / 23518 ~69.996 ms, waitGL 0 / 5 ~0.016 ms
+XXX[337] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23782 ~70.569 ms, finishGL 82 / 23600 ~70.032 ms, waitGL 0 / 5 ~0.016 ms
+XXX[338] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23863 ~70.602 ms, finishGL 80 / 23681 ~70.064 ms, waitGL 0 / 5 ~0.016 ms
+XXX[339] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23945 ~70.636 ms, finishGL 81 / 23763 ~70.098 ms, waitGL 0 / 5 ~0.016 ms
+XXX[340] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24028 ~70.673 ms, finishGL 82 / 23846 ~70.135 ms, waitGL 0 / 5 ~0.016 ms
+XXX[341] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24112 ~70.71 ms, finishGL 82 / 23928 ~70.172 ms, waitGL 0 / 5 ~0.016 ms
+XXX[342] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24195 ~70.746 ms, finishGL 82 / 24011 ~70.208 ms, waitGL 0 / 5 ~0.016 ms
+XXX[343] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24278 ~70.782 ms, finishGL 82 / 24093 ~70.243 ms, waitGL 0 / 5 ~0.016 ms
+XXX[344] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24360 ~70.816 ms, finishGL 82 / 24175 ~70.278 ms, waitGL 0 / 5 ~0.016 ms
+XXX[345] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24444 ~70.852 ms, finishGL 82 / 24258 ~70.314 ms, waitGL 0 / 5 ~0.016 ms
+XXX[346] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24527 ~70.887 ms, finishGL 82 / 24340 ~70.349 ms, waitGL 0 / 5 ~0.016 ms
+XXX[347] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24610 ~70.922 ms, finishGL 82 / 24423 ~70.384 ms, waitGL 0 / 5 ~0.016 ms
+XXX[348] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24693 ~70.958 ms, finishGL 82 / 24506 ~70.42 ms, waitGL 0 / 5 ~0.016 ms
+XXX[349] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24776 ~70.992 ms, finishGL 82 / 24588 ~70.454 ms, waitGL 0 / 5 ~0.016 ms
+XXX[350] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24860 ~71.028 ms, finishGL 83 / 24671 ~70.491 ms, waitGL 0 / 5 ~0.016 ms
+XXX[351] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24943 ~71.063 ms, finishGL 82 / 24754 ~70.525 ms, waitGL 0 / 5 ~0.016 ms
+XXX[352] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25025 ~71.096 ms, finishGL 82 / 24836 ~70.559 ms, waitGL 0 / 5 ~0.016 ms
+XXX[353] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25109 ~71.131 ms, finishGL 83 / 24919 ~70.594 ms, waitGL 0 / 5 ~0.016 ms
+XXX[354] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25192 ~71.165 ms, finishGL 82 / 25002 ~70.629 ms, waitGL 0 / 5 ~0.016 ms
+XXX[355] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25275 ~71.199 ms, finishGL 82 / 25085 ~70.662 ms, waitGL 0 / 5 ~0.016 ms
+XXX[356] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25359 ~71.234 ms, finishGL 83 / 25168 ~70.698 ms, waitGL 0 / 5 ~0.016 ms
+XXX[357] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25442 ~71.266 ms, finishGL 82 / 25250 ~70.73 ms, waitGL 0 / 5 ~0.016 ms
+XXX[358] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25525 ~71.3 ms, finishGL 82 / 25333 ~70.764 ms, waitGL 0 / 5 ~0.016 ms
+XXX[359] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25608 ~71.332 ms, finishGL 82 / 25416 ~70.796 ms, waitGL 0 / 5 ~0.016 ms
+XXX[360] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25692 ~71.367 ms, finishGL 83 / 25499 ~70.831 ms, waitGL 0 / 5 ~0.016 ms
+XXX[361] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25775 ~71.4 ms, finishGL 83 / 25582 ~70.865 ms, waitGL 0 / 5 ~0.016 ms
+XXX[362] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25858 ~71.432 ms, finishGL 82 / 25664 ~70.896 ms, waitGL 0 / 5 ~0.016 ms
+XXX[363] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25941 ~71.465 ms, finishGL 82 / 25747 ~70.929 ms, waitGL 0 / 5 ~0.016 ms
+XXX[364] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26025 ~71.499 ms, finishGL 83 / 25830 ~70.963 ms, waitGL 0 / 5 ~0.016 ms
+XXX[365] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26108 ~71.531 ms, finishGL 82 / 25913 ~70.996 ms, waitGL 0 / 5 ~0.016 ms
+XXX[366] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 26192 ~71.565 ms, finishGL 83 / 25997 ~71.03 ms, waitGL 0 / 5 ~0.016 ms
+XXX[367] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26275 ~71.596 ms, finishGL 82 / 26079 ~71.061 ms, waitGL 0 / 5 ~0.016 ms
+XXX[368] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26359 ~71.628 ms, finishGL 82 / 26162 ~71.093 ms, waitGL 0 / 5 ~0.016 ms
+XXX[369] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26442 ~71.658 ms, finishGL 82 / 26244 ~71.123 ms, waitGL 0 / 5 ~0.016 ms
+XXX[370] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26526 ~71.691 ms, finishGL 83 / 26328 ~71.157 ms, waitGL 0 / 5 ~0.016 ms
+XXX[371] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26608 ~71.722 ms, finishGL 82 / 26410 ~71.187 ms, waitGL 0 / 5 ~0.016 ms
+XXX[372] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26691 ~71.752 ms, finishGL 82 / 26492 ~71.217 ms, waitGL 0 / 5 ~0.016 ms
+XXX[373] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 26773 ~71.779 ms, finishGL 81 / 26574 ~71.245 ms, waitGL 0 / 5 ~0.016 ms
+XXX[374] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26856 ~71.809 ms, finishGL 82 / 26656 ~71.274 ms, waitGL 0 / 6 ~0.016 ms
+XXX[375] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26939 ~71.838 ms, finishGL 82 / 26738 ~71.303 ms, waitGL 0 / 6 ~0.016 ms
+XXX[376] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27022 ~71.869 ms, finishGL 82 / 26821 ~71.334 ms, waitGL 0 / 6 ~0.016 ms
+XXX[377] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27105 ~71.897 ms, finishGL 81 / 26903 ~71.362 ms, waitGL 0 / 6 ~0.016 ms
+XXX[378] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27188 ~71.927 ms, finishGL 82 / 26986 ~71.393 ms, waitGL 0 / 6 ~0.016 ms
+XXX[379] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27271 ~71.955 ms, finishGL 82 / 27068 ~71.421 ms, waitGL 0 / 6 ~0.016 ms
+FrameCount: 480 - FrameRate: 12.0
+XXX[380] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27353 ~71.983 ms, finishGL 82 / 27150 ~71.449 ms, waitGL 0 / 6 ~0.016 ms
+XXX[381] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27436 ~72.011 ms, finishGL 82 / 27232 ~71.477 ms, waitGL 0 / 6 ~0.016 ms
+XXX[382] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27519 ~72.04 ms, finishGL 82 / 27315 ~71.506 ms, waitGL 0 / 6 ~0.016 ms
+XXX[383] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27602 ~72.068 ms, finishGL 82 / 27397 ~71.534 ms, waitGL 0 / 6 ~0.016 ms
+XXX[384] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27684 ~72.094 ms, finishGL 81 / 27479 ~71.56 ms, waitGL 0 / 6 ~0.016 ms
+XXX[385] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27767 ~72.123 ms, finishGL 82 / 27562 ~71.59 ms, waitGL 0 / 6 ~0.016 ms
+XXX[386] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 27852 ~72.157 ms, finishGL 84 / 27646 ~71.623 ms, waitGL 0 / 6 ~0.016 ms
+XXX[387] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27936 ~72.187 ms, finishGL 83 / 27730 ~71.653 ms, waitGL 0 / 6 ~0.016 ms
+XXX[388] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28020 ~72.216 ms, finishGL 83 / 27813 ~71.683 ms, waitGL 0 / 6 ~0.016 ms
+XXX[389] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28103 ~72.244 ms, finishGL 82 / 27895 ~71.711 ms, waitGL 0 / 6 ~0.016 ms
+XXX[390] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 28187 ~72.276 ms, finishGL 84 / 27979 ~71.743 ms, waitGL 0 / 6 ~0.016 ms
+XXX[391] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 28272 ~72.309 ms, finishGL 84 / 28064 ~71.776 ms, waitGL 0 / 6 ~0.016 ms
+XXX[392] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 28357 ~72.34 ms, finishGL 83 / 28148 ~71.807 ms, waitGL 0 / 6 ~0.016 ms
+XXX[393] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 28440 ~72.368 ms, finishGL 82 / 28230 ~71.833 ms, waitGL 0 / 6 ~0.016 ms
+XXX[394] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28523 ~72.395 ms, finishGL 82 / 28312 ~71.86 ms, waitGL 0 / 6 ~0.016 ms
+XXX[395] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 28606 ~72.421 ms, finishGL 81 / 28394 ~71.885 ms, waitGL 0 / 6 ~0.016 ms
+XXX[396] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28689 ~72.448 ms, finishGL 82 / 28477 ~71.912 ms, waitGL 0 / 6 ~0.016 ms
+XXX[397] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28772 ~72.475 ms, finishGL 82 / 28559 ~71.939 ms, waitGL 0 / 6 ~0.016 ms
+XXX[398] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28855 ~72.502 ms, finishGL 82 / 28642 ~71.966 ms, waitGL 0 / 6 ~0.016 ms
+XXX[399] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28938 ~72.528 ms, finishGL 82 / 28725 ~71.992 ms, waitGL 0 / 6 ~0.016 ms
+XXX[400] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29021 ~72.553 ms, finishGL 82 / 28807 ~72.017 ms, waitGL 0 / 6 ~0.016 ms
+XXX[401] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29104 ~72.58 ms, finishGL 82 / 28889 ~72.044 ms, waitGL 0 / 6 ~0.016 ms
+XXX[402] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29187 ~72.605 ms, finishGL 82 / 28971 ~72.069 ms, waitGL 0 / 6 ~0.016 ms
+XXX[403] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 29269 ~72.627 ms, finishGL 81 / 29053 ~72.092 ms, waitGL 0 / 6 ~0.016 ms
+XXX[404] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 29350 ~72.65 ms, finishGL 81 / 29134 ~72.115 ms, waitGL 0 / 6 ~0.016 ms
+XXX[405] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29433 ~72.675 ms, finishGL 82 / 29216 ~72.14 ms, waitGL 0 / 6 ~0.016 ms
+XXX[406] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29516 ~72.7 ms, finishGL 82 / 29299 ~72.165 ms, waitGL 0 / 6 ~0.016 ms
+XXX[407] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29599 ~72.726 ms, finishGL 82 / 29381 ~72.191 ms, waitGL 0 / 6 ~0.016 ms
+XXX[408] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29682 ~72.751 ms, finishGL 82 / 29464 ~72.216 ms, waitGL 0 / 6 ~0.016 ms
+XXX[409] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29765 ~72.775 ms, finishGL 81 / 29546 ~72.239 ms, waitGL 0 / 6 ~0.016 ms
+XXX[410] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29847 ~72.799 ms, finishGL 82 / 29628 ~72.264 ms, waitGL 0 / 6 ~0.016 ms
+XXX[411] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29930 ~72.824 ms, finishGL 82 / 29710 ~72.289 ms, waitGL 0 / 6 ~0.016 ms
+XXX[412] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30013 ~72.848 ms, finishGL 82 / 29793 ~72.313 ms, waitGL 0 / 6 ~0.016 ms
+XXX[413] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30096 ~72.873 ms, finishGL 82 / 29875 ~72.338 ms, waitGL 0 / 6 ~0.016 ms
+XXX[414] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30180 ~72.899 ms, finishGL 83 / 29959 ~72.365 ms, waitGL 0 / 6 ~0.016 ms
+XXX[415] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30262 ~72.922 ms, finishGL 81 / 30040 ~72.387 ms, waitGL 0 / 6 ~0.016 ms
+XXX[416] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30345 ~72.946 ms, finishGL 82 / 30123 ~72.411 ms, waitGL 0 / 6 ~0.016 ms
+XXX[417] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30428 ~72.969 ms, finishGL 82 / 30205 ~72.434 ms, waitGL 0 / 6 ~0.016 ms
+XXX[418] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30511 ~72.992 ms, finishGL 82 / 30287 ~72.458 ms, waitGL 0 / 6 ~0.016 ms
+XXX[419] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30594 ~73.017 ms, finishGL 82 / 30370 ~72.482 ms, waitGL 0 / 6 ~0.016 ms
+XXX[420] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30677 ~73.041 ms, finishGL 82 / 30452 ~72.506 ms, waitGL 0 / 6 ~0.016 ms
+XXX[421] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30761 ~73.067 ms, finishGL 83 / 30536 ~72.532 ms, waitGL 0 / 6 ~0.016 ms
+XXX[422] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30845 ~73.093 ms, finishGL 83 / 30619 ~72.558 ms, waitGL 0 / 6 ~0.016 ms
+XXX[423] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30929 ~73.12 ms, finishGL 83 / 30703 ~72.585 ms, waitGL 0 / 6 ~0.016 ms
+XXX[424] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 31012 ~73.142 ms, finishGL 81 / 30785 ~72.607 ms, waitGL 0 / 6 ~0.016 ms
+XXX[425] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31092 ~73.159 ms, finishGL 79 / 30865 ~72.624 ms, waitGL 0 / 6 ~0.016 ms
+XXX[426] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31173 ~73.176 ms, finishGL 79 / 30945 ~72.641 ms, waitGL 0 / 6 ~0.016 ms
+XXX[427] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31253 ~73.192 ms, finishGL 79 / 31024 ~72.657 ms, waitGL 0 / 6 ~0.016 ms
+XXX[428] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 31317 ~73.171 ms, finishGL 63 / 31088 ~72.636 ms, waitGL 0 / 6 ~0.016 ms
+XXX[429] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31382 ~73.153 ms, finishGL 64 / 31153 ~72.618 ms, waitGL 0 / 6 ~0.016 ms
+XXX[430] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31449 ~73.137 ms, finishGL 65 / 31218 ~72.602 ms, waitGL 0 / 6 ~0.016 ms
+XXX[431] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31514 ~73.12 ms, finishGL 65 / 31284 ~72.585 ms, waitGL 0 / 6 ~0.016 ms
+XXX[432] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31580 ~73.103 ms, finishGL 65 / 31349 ~72.568 ms, waitGL 0 / 6 ~0.016 ms
+XXX[433] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31646 ~73.087 ms, finishGL 65 / 31415 ~72.552 ms, waitGL 0 / 6 ~0.016 ms
+XXX[434] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31713 ~73.071 ms, finishGL 65 / 31480 ~72.536 ms, waitGL 0 / 7 ~0.016 ms
+XXX[435] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31779 ~73.055 ms, finishGL 65 / 31546 ~72.521 ms, waitGL 0 / 7 ~0.016 ms
+XXX[436] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31844 ~73.038 ms, finishGL 64 / 31611 ~72.503 ms, waitGL 0 / 7 ~0.016 ms
+XXX[437] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31911 ~73.023 ms, finishGL 65 / 31677 ~72.488 ms, waitGL 0 / 7 ~0.016 ms
+XXX[438] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31977 ~73.007 ms, finishGL 65 / 31743 ~72.472 ms, waitGL 0 / 7 ~0.016 ms
+XXX[439] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32043 ~72.992 ms, finishGL 66 / 31809 ~72.458 ms, waitGL 0 / 7 ~0.016 ms
+XXX[440] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32110 ~72.979 ms, finishGL 66 / 31875 ~72.444 ms, waitGL 0 / 7 ~0.016 ms
+XXX[441] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32177 ~72.964 ms, finishGL 66 / 31941 ~72.43 ms, waitGL 0 / 7 ~0.016 ms
+XXX[442] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32243 ~72.95 ms, finishGL 66 / 32007 ~72.415 ms, waitGL 0 / 7 ~0.016 ms
+XXX[443] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32311 ~72.937 ms, finishGL 66 / 32074 ~72.402 ms, waitGL 0 / 7 ~0.016 ms
+XXX[444] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32378 ~72.923 ms, finishGL 66 / 32140 ~72.389 ms, waitGL 0 / 7 ~0.016 ms
+XXX[445] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32444 ~72.909 ms, finishGL 66 / 32207 ~72.375 ms, waitGL 0 / 7 ~0.016 ms
+XXX[446] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32511 ~72.895 ms, finishGL 66 / 32273 ~72.361 ms, waitGL 0 / 7 ~0.016 ms
+XXX[447] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32578 ~72.882 ms, finishGL 66 / 32339 ~72.348 ms, waitGL 0 / 7 ~0.016 ms
+XXX[448] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32644 ~72.867 ms, finishGL 65 / 32405 ~72.333 ms, waitGL 0 / 7 ~0.016 ms
+XXX[449] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32711 ~72.853 ms, finishGL 66 / 32471 ~72.32 ms, waitGL 0 / 7 ~0.016 ms
+XXX[450] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32778 ~72.84 ms, finishGL 66 / 32537 ~72.306 ms, waitGL 0 / 7 ~0.016 ms
+XXX[451] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32844 ~72.826 ms, finishGL 66 / 32604 ~72.292 ms, waitGL 0 / 7 ~0.016 ms
+XXX[452] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32911 ~72.812 ms, finishGL 66 / 32670 ~72.279 ms, waitGL 0 / 7 ~0.016 ms
+XXX[453] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32977 ~72.797 ms, finishGL 65 / 32735 ~72.264 ms, waitGL 0 / 7 ~0.016 ms
+XXX[454] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33042 ~72.781 ms, finishGL 65 / 32800 ~72.248 ms, waitGL 0 / 7 ~0.016 ms
+XXX[455] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33108 ~72.765 ms, finishGL 65 / 32865 ~72.232 ms, waitGL 0 / 7 ~0.016 ms
+XXX[456] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33174 ~72.751 ms, finishGL 65 / 32931 ~72.219 ms, waitGL 0 / 7 ~0.016 ms
+XXX[457] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33240 ~72.735 ms, finishGL 64 / 32996 ~72.202 ms, waitGL 0 / 7 ~0.016 ms
+XXX[458] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33305 ~72.719 ms, finishGL 64 / 33061 ~72.186 ms, waitGL 0 / 7 ~0.016 ms
+XXX[459] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33371 ~72.704 ms, finishGL 65 / 33126 ~72.171 ms, waitGL 0 / 7 ~0.016 ms
+XXX[460] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33436 ~72.688 ms, finishGL 65 / 33191 ~72.156 ms, waitGL 0 / 7 ~0.016 ms
+XXX[461] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33502 ~72.674 ms, finishGL 65 / 33257 ~72.142 ms, waitGL 0 / 7 ~0.016 ms
+XXX[462] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33568 ~72.658 ms, finishGL 64 / 33322 ~72.126 ms, waitGL 0 / 7 ~0.016 ms
+XXX[463] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33633 ~72.643 ms, finishGL 64 / 33387 ~72.11 ms, waitGL 0 / 7 ~0.016 ms
+XXX[464] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33699 ~72.628 ms, finishGL 65 / 33452 ~72.096 ms, waitGL 0 / 7 ~0.016 ms
+XXX[465] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33765 ~72.613 ms, finishGL 65 / 33517 ~72.081 ms, waitGL 0 / 7 ~0.016 ms
+XXX[466] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33830 ~72.597 ms, finishGL 64 / 33582 ~72.065 ms, waitGL 0 / 7 ~0.016 ms
+XXX[467] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33878 ~72.545 ms, finishGL 47 / 33630 ~72.013 ms, waitGL 0 / 7 ~0.016 ms
+XXX[468] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 33928 ~72.497 ms, finishGL 49 / 33680 ~71.965 ms, waitGL 0 / 7 ~0.016 ms
+XXX[469] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33977 ~72.447 ms, finishGL 48 / 33728 ~71.915 ms, waitGL 0 / 7 ~0.016 ms
+XXX[470] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34026 ~72.397 ms, finishGL 48 / 33776 ~71.865 ms, waitGL 0 / 7 ~0.016 ms
+XXX[471] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34076 ~72.349 ms, finishGL 49 / 33825 ~71.817 ms, waitGL 0 / 7 ~0.016 ms
+XXX[472] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34125 ~72.299 ms, finishGL 48 / 33874 ~71.767 ms, waitGL 0 / 7 ~0.016 ms
+XXX[473] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34174 ~72.251 ms, finishGL 48 / 33923 ~71.719 ms, waitGL 0 / 7 ~0.016 ms
+XXX[474] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34223 ~72.202 ms, finishGL 48 / 33971 ~71.67 ms, waitGL 0 / 7 ~0.016 ms
+XXX[475] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34272 ~72.151 ms, finishGL 47 / 34019 ~71.62 ms, waitGL 0 / 7 ~0.016 ms
+XXX[476] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34322 ~72.106 ms, finishGL 50 / 34069 ~71.574 ms, waitGL 0 / 7 ~0.016 ms
+XXX[477] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34371 ~72.057 ms, finishGL 48 / 34117 ~71.525 ms, waitGL 0 / 7 ~0.016 ms
+XXX[478] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34420 ~72.009 ms, finishGL 48 / 34166 ~71.478 ms, waitGL 0 / 7 ~0.016 ms
+XXX[479] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34469 ~71.961 ms, finishGL 48 / 34215 ~71.43 ms, waitGL 0 / 7 ~0.016 ms
+XXX[480] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34518 ~71.914 ms, finishGL 48 / 34263 ~71.383 ms, waitGL 0 / 7 ~0.016 ms
+XXX[481] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34567 ~71.865 ms, finishGL 47 / 34311 ~71.334 ms, waitGL 0 / 7 ~0.016 ms
+XXX[482] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34616 ~71.818 ms, finishGL 48 / 34360 ~71.288 ms, waitGL 0 / 7 ~0.016 ms
+XXX[483] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34665 ~71.772 ms, finishGL 48 / 34409 ~71.241 ms, waitGL 0 / 7 ~0.016 ms
+XXX[484] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34714 ~71.725 ms, finishGL 48 / 34458 ~71.194 ms, waitGL 0 / 7 ~0.016 ms
+XXX[485] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34764 ~71.678 ms, finishGL 48 / 34506 ~71.148 ms, waitGL 0 / 7 ~0.016 ms
+XXX[486] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34813 ~71.631 ms, finishGL 48 / 34554 ~71.1 ms, waitGL 0 / 7 ~0.016 ms
+XXX[487] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34862 ~71.586 ms, finishGL 48 / 34603 ~71.054 ms, waitGL 0 / 7 ~0.016 ms
+XXX[488] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34912 ~71.541 ms, finishGL 49 / 34653 ~71.01 ms, waitGL 0 / 7 ~0.016 ms
+XXX[489] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34961 ~71.495 ms, finishGL 48 / 34701 ~70.964 ms, waitGL 0 / 7 ~0.016 ms
+XXX[490] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35011 ~71.451 ms, finishGL 49 / 34750 ~70.92 ms, waitGL 0 / 7 ~0.016 ms
+XXX[491] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35061 ~71.408 ms, finishGL 49 / 34800 ~70.877 ms, waitGL 0 / 7 ~0.016 ms
+XXX[492] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35111 ~71.365 ms, finishGL 49 / 34850 ~70.834 ms, waitGL 0 / 8 ~0.016 ms
+XXX[493] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35161 ~71.321 ms, finishGL 49 / 34899 ~70.79 ms, waitGL 0 / 8 ~0.016 ms
+XXX[494] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35211 ~71.277 ms, finishGL 48 / 34948 ~70.746 ms, waitGL 0 / 8 ~0.016 ms
+XXX[495] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35260 ~71.234 ms, finishGL 49 / 34997 ~70.703 ms, waitGL 0 / 8 ~0.016 ms
+XXX[496] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35311 ~71.193 ms, finishGL 50 / 35048 ~70.662 ms, waitGL 0 / 8 ~0.016 ms
+XXX[497] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35362 ~71.151 ms, finishGL 50 / 35098 ~70.62 ms, waitGL 0 / 8 ~0.016 ms
+XXX[498] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35412 ~71.109 ms, finishGL 49 / 35148 ~70.578 ms, waitGL 0 / 8 ~0.016 ms
+XXX[499] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35462 ~71.067 ms, finishGL 49 / 35197 ~70.536 ms, waitGL 0 / 8 ~0.016 ms
+FrameCount: 600 - FrameRate: 20.0
+XXX[500] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35513 ~71.026 ms, finishGL 49 / 35247 ~70.495 ms, waitGL 0 / 8 ~0.016 ms
+XXX[501] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35563 ~70.984 ms, finishGL 49 / 35297 ~70.454 ms, waitGL 0 / 8 ~0.016 ms
+XXX[502] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35613 ~70.944 ms, finishGL 50 / 35347 ~70.413 ms, waitGL 0 / 8 ~0.016 ms
+XXX[503] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35664 ~70.903 ms, finishGL 49 / 35397 ~70.372 ms, waitGL 0 / 8 ~0.016 ms
+XXX[504] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35714 ~70.861 ms, finishGL 49 / 35446 ~70.331 ms, waitGL 0 / 8 ~0.016 ms
+XXX[505] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35764 ~70.82 ms, finishGL 49 / 35496 ~70.29 ms, waitGL 0 / 8 ~0.016 ms
+XXX[506] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35814 ~70.78 ms, finishGL 49 / 35546 ~70.249 ms, waitGL 0 / 8 ~0.016 ms
+XXX[507] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35864 ~70.738 ms, finishGL 48 / 35595 ~70.207 ms, waitGL 0 / 8 ~0.016 ms
+XXX[508] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35914 ~70.698 ms, finishGL 50 / 35645 ~70.168 ms, waitGL 0 / 8 ~0.016 ms
+XXX[509] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35965 ~70.658 ms, finishGL 49 / 35695 ~70.128 ms, waitGL 0 / 8 ~0.016 ms
+XXX[510] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 36015 ~70.618 ms, finishGL 49 / 35744 ~70.088 ms, waitGL 0 / 8 ~0.016 ms
+XXX[511] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 36065 ~70.578 ms, finishGL 49 / 35794 ~70.048 ms, waitGL 0 / 8 ~0.016 ms
+XXX[512] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 36115 ~70.538 ms, finishGL 49 / 35844 ~70.008 ms, waitGL 0 / 8 ~0.016 ms
+XXX[513] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 36166 ~70.5 ms, finishGL 50 / 35895 ~69.971 ms, waitGL 0 / 8 ~0.016 ms
+XXX[514] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 36218 ~70.464 ms, finishGL 51 / 35946 ~69.934 ms, waitGL 0 / 8 ~0.016 ms
+XXX[515] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 36270 ~70.429 ms, finishGL 51 / 35998 ~69.899 ms, waitGL 0 / 8 ~0.016 ms
+XXX[516] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 36324 ~70.396 ms, finishGL 53 / 36051 ~69.866 ms, waitGL 0 / 8 ~0.016 ms
+XXX[517] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 36393 ~70.392 ms, finishGL 68 / 36119 ~69.863 ms, waitGL 0 / 8 ~0.016 ms
+XXX[518] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 36463 ~70.392 ms, finishGL 69 / 36189 ~69.863 ms, waitGL 0 / 8 ~0.016 ms
+XXX[519] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 36539 ~70.402 ms, finishGL 75 / 36264 ~69.873 ms, waitGL 0 / 8 ~0.016 ms
+XXX[520] TO 17 ms, lFrame0 0 ms, lFrameX 92 / 36631 ~70.444 ms, finishGL 91 / 36355 ~69.915 ms, waitGL 0 / 8 ~0.016 ms
+XXX[521] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 36716 ~70.473 ms, finishGL 85 / 36441 ~69.944 ms, waitGL 0 / 8 ~0.016 ms
+XXX[522] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36799 ~70.496 ms, finishGL 81 / 36522 ~69.967 ms, waitGL 0 / 8 ~0.016 ms
+XXX[523] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36882 ~70.521 ms, finishGL 83 / 36606 ~69.992 ms, waitGL 0 / 8 ~0.016 ms
+XXX[524] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36965 ~70.545 ms, finishGL 82 / 36688 ~70.016 ms, waitGL 0 / 8 ~0.016 ms
+XXX[525] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37048 ~70.569 ms, finishGL 82 / 36771 ~70.04 ms, waitGL 0 / 8 ~0.016 ms
+XXX[526] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37131 ~70.592 ms, finishGL 82 / 36853 ~70.063 ms, waitGL 0 / 8 ~0.016 ms
+XXX[527] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37215 ~70.616 ms, finishGL 82 / 36936 ~70.087 ms, waitGL 0 / 8 ~0.016 ms
+XXX[528] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37298 ~70.64 ms, finishGL 82 / 37019 ~70.111 ms, waitGL 0 / 8 ~0.016 ms
+XXX[529] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37381 ~70.665 ms, finishGL 82 / 37101 ~70.136 ms, waitGL 0 / 8 ~0.016 ms
+XXX[530] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37465 ~70.688 ms, finishGL 82 / 37184 ~70.159 ms, waitGL 0 / 8 ~0.016 ms
+XXX[531] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37548 ~70.712 ms, finishGL 82 / 37267 ~70.183 ms, waitGL 0 / 8 ~0.016 ms
+XXX[532] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37632 ~70.737 ms, finishGL 83 / 37350 ~70.208 ms, waitGL 0 / 8 ~0.016 ms
+XXX[533] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37714 ~70.759 ms, finishGL 82 / 37432 ~70.23 ms, waitGL 0 / 8 ~0.016 ms
+XXX[534] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37798 ~70.782 ms, finishGL 82 / 37515 ~70.253 ms, waitGL 0 / 8 ~0.016 ms
+XXX[535] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 37879 ~70.803 ms, finishGL 81 / 37596 ~70.274 ms, waitGL 0 / 8 ~0.016 ms
+XXX[536] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37962 ~70.826 ms, finishGL 82 / 37679 ~70.296 ms, waitGL 0 / 8 ~0.016 ms
+XXX[537] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38045 ~70.848 ms, finishGL 82 / 37761 ~70.319 ms, waitGL 0 / 8 ~0.016 ms
+XXX[538] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38128 ~70.87 ms, finishGL 82 / 37843 ~70.341 ms, waitGL 0 / 8 ~0.016 ms
+XXX[539] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38211 ~70.892 ms, finishGL 81 / 37925 ~70.362 ms, waitGL 0 / 8 ~0.016 ms
+XXX[540] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38294 ~70.915 ms, finishGL 82 / 38007 ~70.385 ms, waitGL 0 / 8 ~0.016 ms
+XXX[541] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38376 ~70.937 ms, finishGL 82 / 38090 ~70.406 ms, waitGL 0 / 8 ~0.016 ms
+XXX[542] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38460 ~70.961 ms, finishGL 83 / 38173 ~70.43 ms, waitGL 0 / 8 ~0.016 ms
+XXX[543] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38543 ~70.983 ms, finishGL 82 / 38255 ~70.452 ms, waitGL 0 / 8 ~0.016 ms
+XXX[544] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38627 ~71.006 ms, finishGL 82 / 38338 ~70.475 ms, waitGL 0 / 8 ~0.016 ms
+XXX[545] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38710 ~71.029 ms, finishGL 82 / 38421 ~70.498 ms, waitGL 0 / 8 ~0.016 ms
+XXX[546] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38794 ~71.051 ms, finishGL 82 / 38504 ~70.521 ms, waitGL 0 / 8 ~0.016 ms
+XXX[547] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38878 ~71.076 ms, finishGL 83 / 38588 ~70.545 ms, waitGL 0 / 8 ~0.016 ms
+XXX[548] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38963 ~71.1 ms, finishGL 84 / 38672 ~70.57 ms, waitGL 0 / 8 ~0.016 ms
+XXX[549] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39046 ~71.122 ms, finishGL 82 / 38755 ~70.592 ms, waitGL 0 / 8 ~0.016 ms
+XXX[550] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 39130 ~71.147 ms, finishGL 83 / 38839 ~70.616 ms, waitGL 0 / 8 ~0.016 ms
+XXX[551] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39214 ~71.169 ms, finishGL 83 / 38922 ~70.639 ms, waitGL 0 / 8 ~0.016 ms
+XXX[552] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 39299 ~71.194 ms, finishGL 84 / 39006 ~70.664 ms, waitGL 0 / 8 ~0.016 ms
+XXX[553] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39381 ~71.214 ms, finishGL 82 / 39088 ~70.684 ms, waitGL 0 / 9 ~0.016 ms
+XXX[554] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39463 ~71.233 ms, finishGL 80 / 39169 ~70.703 ms, waitGL 0 / 9 ~0.016 ms
+XXX[555] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39545 ~71.253 ms, finishGL 82 / 39251 ~70.724 ms, waitGL 0 / 9 ~0.016 ms
+XXX[556] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39628 ~71.274 ms, finishGL 82 / 39334 ~70.744 ms, waitGL 0 / 9 ~0.016 ms
+XXX[557] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39710 ~71.293 ms, finishGL 81 / 39415 ~70.763 ms, waitGL 0 / 9 ~0.016 ms
+XXX[558] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39793 ~71.313 ms, finishGL 81 / 39497 ~70.783 ms, waitGL 0 / 9 ~0.016 ms
+XXX[559] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 39873 ~71.33 ms, finishGL 80 / 39577 ~70.8 ms, waitGL 0 / 9 ~0.016 ms
+XXX[560] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39956 ~71.35 ms, finishGL 82 / 39659 ~70.82 ms, waitGL 0 / 9 ~0.016 ms
+XXX[561] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 40038 ~71.369 ms, finishGL 81 / 39741 ~70.839 ms, waitGL 0 / 9 ~0.016 ms
+XXX[562] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40120 ~71.388 ms, finishGL 81 / 39822 ~70.858 ms, waitGL 0 / 9 ~0.016 ms
+XXX[563] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40201 ~71.406 ms, finishGL 80 / 39903 ~70.876 ms, waitGL 0 / 9 ~0.016 ms
+XXX[564] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 40282 ~71.423 ms, finishGL 80 / 39983 ~70.893 ms, waitGL 0 / 9 ~0.016 ms
+XXX[565] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40364 ~71.441 ms, finishGL 81 / 40065 ~70.911 ms, waitGL 0 / 9 ~0.016 ms
+XXX[566] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40429 ~71.43 ms, finishGL 64 / 40130 ~70.901 ms, waitGL 0 / 9 ~0.016 ms
+XXX[567] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 40494 ~71.419 ms, finishGL 64 / 40194 ~70.889 ms, waitGL 0 / 9 ~0.016 ms
+XXX[568] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40560 ~71.408 ms, finishGL 64 / 40258 ~70.878 ms, waitGL 0 / 9 ~0.016 ms
+XXX[569] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40625 ~71.398 ms, finishGL 65 / 40324 ~70.868 ms, waitGL 0 / 9 ~0.016 ms
+XXX[570] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40691 ~71.388 ms, finishGL 65 / 40389 ~70.858 ms, waitGL 0 / 9 ~0.016 ms
+XXX[571] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40756 ~71.378 ms, finishGL 64 / 40454 ~70.847 ms, waitGL 0 / 9 ~0.016 ms
+XXX[572] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 40825 ~71.372 ms, finishGL 67 / 40521 ~70.842 ms, waitGL 0 / 9 ~0.016 ms
+XXX[573] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40890 ~71.362 ms, finishGL 64 / 40586 ~70.831 ms, waitGL 0 / 9 ~0.016 ms
+XXX[574] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40956 ~71.353 ms, finishGL 65 / 40651 ~70.822 ms, waitGL 0 / 9 ~0.016 ms
+XXX[575] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 41023 ~71.345 ms, finishGL 66 / 40718 ~70.814 ms, waitGL 0 / 9 ~0.016 ms
+XXX[576] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 41089 ~71.336 ms, finishGL 65 / 40783 ~70.804 ms, waitGL 0 / 9 ~0.016 ms
+XXX[577] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 41155 ~71.327 ms, finishGL 65 / 40848 ~70.795 ms, waitGL 0 / 9 ~0.016 ms
+XXX[578] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 41223 ~71.321 ms, finishGL 67 / 40916 ~70.789 ms, waitGL 0 / 9 ~0.016 ms
+XXX[579] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 41293 ~71.319 ms, finishGL 69 / 40985 ~70.787 ms, waitGL 0 / 9 ~0.016 ms
+XXX[580] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 41364 ~71.318 ms, finishGL 70 / 41056 ~70.786 ms, waitGL 0 / 9 ~0.016 ms
+XXX[581] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 41454 ~71.349 ms, finishGL 89 / 41145 ~70.818 ms, waitGL 0 / 9 ~0.016 ms
+XXX[582] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 41540 ~71.376 ms, finishGL 86 / 41231 ~70.844 ms, waitGL 0 / 9 ~0.016 ms
+XXX[583] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 41626 ~71.401 ms, finishGL 85 / 41317 ~70.869 ms, waitGL 0 / 9 ~0.016 ms
+XXX[584] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 41710 ~71.422 ms, finishGL 83 / 41400 ~70.891 ms, waitGL 0 / 9 ~0.016 ms
+XXX[585] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 41792 ~71.44 ms, finishGL 81 / 41481 ~70.909 ms, waitGL 0 / 9 ~0.016 ms
+XXX[586] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 41873 ~71.456 ms, finishGL 80 / 41562 ~70.925 ms, waitGL 0 / 9 ~0.016 ms
+XXX[587] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41955 ~71.474 ms, finishGL 81 / 41644 ~70.943 ms, waitGL 0 / 9 ~0.016 ms
+XXX[588] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42038 ~71.494 ms, finishGL 82 / 41726 ~70.963 ms, waitGL 0 / 9 ~0.016 ms
+XXX[589] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42121 ~71.513 ms, finishGL 82 / 41808 ~70.982 ms, waitGL 0 / 9 ~0.016 ms
+XXX[590] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 42203 ~71.532 ms, finishGL 81 / 41890 ~71.0 ms, waitGL 0 / 9 ~0.016 ms
+XXX[591] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42286 ~71.551 ms, finishGL 82 / 41972 ~71.019 ms, waitGL 0 / 9 ~0.016 ms
+XXX[592] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42369 ~71.57 ms, finishGL 82 / 42054 ~71.038 ms, waitGL 0 / 9 ~0.016 ms
+XXX[593] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42453 ~71.591 ms, finishGL 83 / 42138 ~71.059 ms, waitGL 0 / 9 ~0.016 ms
+XXX[594] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42536 ~71.609 ms, finishGL 81 / 42220 ~71.078 ms, waitGL 0 / 9 ~0.016 ms
+XXX[595] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42620 ~71.63 ms, finishGL 83 / 42303 ~71.099 ms, waitGL 0 / 9 ~0.016 ms
+XXX[596] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42703 ~71.65 ms, finishGL 83 / 42387 ~71.119 ms, waitGL 0 / 9 ~0.016 ms
+XXX[597] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42788 ~71.672 ms, finishGL 84 / 42471 ~71.141 ms, waitGL 0 / 9 ~0.016 ms
+XXX[598] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42871 ~71.692 ms, finishGL 82 / 42554 ~71.16 ms, waitGL 0 / 9 ~0.016 ms
+XXX[599] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42956 ~71.713 ms, finishGL 83 / 42637 ~71.181 ms, waitGL 0 / 9 ~0.016 ms
+XXX[600] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43038 ~71.73 ms, finishGL 81 / 42719 ~71.199 ms, waitGL 0 / 9 ~0.016 ms
+XXX[601] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 43120 ~71.747 ms, finishGL 81 / 42800 ~71.216 ms, waitGL 0 / 9 ~0.016 ms
+XXX[602] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 43202 ~71.764 ms, finishGL 81 / 42881 ~71.232 ms, waitGL 0 / 9 ~0.016 ms
+XXX[603] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43284 ~71.781 ms, finishGL 81 / 42963 ~71.248 ms, waitGL 0 / 9 ~0.016 ms
+XXX[604] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43366 ~71.799 ms, finishGL 82 / 43045 ~71.267 ms, waitGL 0 / 9 ~0.016 ms
+XXX[605] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43449 ~71.818 ms, finishGL 82 / 43128 ~71.285 ms, waitGL 0 / 9 ~0.016 ms
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync1-finish-wait.log b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync1-finish-wait.log
new file mode 100644
index 000000000..940cad603
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync1-finish-wait.log
@@ -0,0 +1,745 @@
+NSZombieEnabled
+NSTraceEvents YES
+OBJC_PRINT_EXCEPTIONS
+/usr/bin/java
+java version "1.6.0_37"
+Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909)
+Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)
+LD_LIBRARY_PATH :../../gluegen/make/../build-macosx/obj:../build-macosx/lib
+LIBXCB_ALLOW_SLOPPY_LOCK:
+LIBGL_DRIVERS_PATH:
+LIBGL_DEBUG:
+LIBGL_ALWAYS_INDIRECT:
+LIBGL_ALWAYS_SOFTWARE:
+SWT_CLASSPATH: ../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar
+/usr/bin/java -d64 -time 100000 -vsyncN 0
+CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar
+CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar
+
+Test Start: com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsyncN 0
+
+/usr/bin/java -d64 -Djava.awt.headless=false -Djogl.debug.calayer.SwapM2 com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsyncN 0
+swapInterval 1
+exclusiveContext false
+SWAP_M1 false
+SWAP_M2 true
+NewtCanvasAWT.attachNewtChild.2: size 500x268
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init ...
+LandscapeES2 init on Thread[main-Display-.macosx_nil-1-EDT-1,5,main]
+Chosen GLCapabilities: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/0, dbl, mono , hw, GLProfile[GL2/GL2.hw], offscr[fbo]]
+INIT GL IS: jogamp.opengl.gl4.GL4bcImpl
+GL_VENDOR: NVIDIA Corporation
+GL_RENDERER: NVIDIA GeForce 320M OpenGL Engine
+GL_VERSION: 2.1 NVIDIA-7.32.12
+GL GLSL: true, has-compiler-func: true, version 1.20, 1.20.0
+GL FBO: basic true, full true
+GL Profile: GLProfile[GL2/GL2.hw]
+GL Renderer Quirks:[NoOffscreenBitmap]
+GL:jogamp.opengl.gl4.GL4bcImpl@7b7a4989, 2.1 (hardware) - 2.1 NVIDIA-7.32.12
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init FIN
+Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.reshape 0/0 500x268, swapInterval 1, drawable 0x7fd1cbcd7ed0
+Thread[AWT-EventQueue-0,6,main] LandscapeES2.reshape 0/0 500x268, swapInterval 1, drawable 0x7fd1cbcd7ed0
+XXX[1] TO 17 ms, lFrame0 110 ms, lFrameX 849 / 849 ~849.6 ms, finishGL 736 / 736 ~736.509 ms, waitGL 2 / 2 ~2.611 ms
+XXX[2] TO 17 ms, lFrame0 89 ms, lFrameX 182 / 1031 ~515.996 ms, finishGL 88 / 825 ~412.638 ms, waitGL 3 / 6 ~3.222 ms
+XXX[3] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 1115 ~371.971 ms, finishGL 80 / 905 ~301.799 ms, waitGL 2 / 8 ~2.84 ms
+XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 1214 ~303.748 ms, finishGL 95 / 1001 ~250.348 ms, waitGL 2 / 11 ~2.756 ms
+XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 1298 ~259.668 ms, finishGL 80 / 1081 ~216.348 ms, waitGL 2 / 13 ~2.67 ms
+XXX[6] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 1381 ~230.176 ms, finishGL 79 / 1161 ~193.531 ms, waitGL 1 / 15 ~2.523 ms
+XXX[7] TO 17 ms, lFrame0 1 ms, lFrameX 100 / 1481 ~211.599 ms, finishGL 93 / 1255 ~179.308 ms, waitGL 4 / 19 ~2.805 ms
+XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1564 ~195.509 ms, finishGL 78 / 1333 ~166.666 ms, waitGL 4 / 23 ~2.965 ms
+XXX[9] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 1647 ~183.082 ms, finishGL 78 / 1411 ~156.839 ms, waitGL 4 / 28 ~3.128 ms
+XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1730 ~173.057 ms, finishGL 77 / 1489 ~148.941 ms, waitGL 4 / 32 ~3.258 ms
+XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1813 ~164.847 ms, finishGL 77 / 1566 ~142.424 ms, waitGL 4 / 37 ~3.391 ms
+XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 1913 ~159.477 ms, finishGL 93 / 1659 ~138.306 ms, waitGL 6 / 44 ~3.681 ms
+XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1996 ~153.553 ms, finishGL 75 / 1735 ~133.48 ms, waitGL 5 / 50 ~3.853 ms
+XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2079 ~148.52 ms, finishGL 75 / 1810 ~129.351 ms, waitGL 6 / 56 ~4.045 ms
+XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 2180 ~145.336 ms, finishGL 90 / 1901 ~126.785 ms, waitGL 9 / 65 ~4.378 ms
+XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2262 ~141.415 ms, finishGL 74 / 1976 ~123.506 ms, waitGL 7 / 73 ~4.576 ms
+XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2345 ~137.958 ms, finishGL 74 / 2050 ~120.613 ms, waitGL 7 / 80 ~4.751 ms
+XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 2446 ~135.894 ms, finishGL 90 / 2141 ~118.948 ms, waitGL 9 / 90 ~5.025 ms
+XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2528 ~133.085 ms, finishGL 74 / 2215 ~116.618 ms, waitGL 7 / 97 ~5.149 ms
+XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2611 ~130.572 ms, finishGL 74 / 2290 ~114.523 ms, waitGL 7 / 105 ~5.273 ms
+XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 2712 ~129.145 ms, finishGL 91 / 2381 ~113.407 ms, waitGL 9 / 114 ~5.456 ms
+XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2794 ~127.016 ms, finishGL 75 / 2456 ~111.662 ms, waitGL 6 / 121 ~5.517 ms
+XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2877 ~125.106 ms, finishGL 74 / 2531 ~110.048 ms, waitGL 7 / 129 ~5.619 ms
+XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 2978 ~124.095 ms, finishGL 86 / 2617 ~109.073 ms, waitGL 13 / 142 ~5.948 ms
+XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3061 ~122.451 ms, finishGL 69 / 2687 ~107.499 ms, waitGL 12 / 155 ~6.224 ms
+XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3143 ~120.916 ms, finishGL 69 / 2756 ~106.024 ms, waitGL 12 / 168 ~6.469 ms
+XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3227 ~119.539 ms, finishGL 68 / 2824 ~104.617 ms, waitGL 15 / 183 ~6.797 ms
+XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3310 ~118.236 ms, finishGL 67 / 2891 ~103.284 ms, waitGL 15 / 198 ~7.097 ms
+XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3393 ~117.023 ms, finishGL 66 / 2958 ~102.005 ms, waitGL 16 / 214 ~7.411 ms
+XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3476 ~115.89 ms, finishGL 65 / 3023 ~100.789 ms, waitGL 16 / 231 ~7.715 ms
+XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3543 ~114.294 ms, finishGL 64 / 3088 ~99.614 ms, waitGL 1 / 233 ~7.516 ms
+XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3608 ~112.769 ms, finishGL 63 / 3151 ~98.498 ms, waitGL 0 / 233 ~7.311 ms
+XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 3692 ~111.899 ms, finishGL 79 / 3231 ~97.929 ms, waitGL 3 / 237 ~7.203 ms
+XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3758 ~110.539 ms, finishGL 63 / 3295 ~96.913 ms, waitGL 1 / 239 ~7.047 ms
+XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3824 ~109.274 ms, finishGL 63 / 3358 ~95.955 ms, waitGL 2 / 241 ~6.908 ms
+XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3908 ~108.567 ms, finishGL 78 / 3437 ~95.474 ms, waitGL 4 / 246 ~6.847 ms
+XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3974 ~107.41 ms, finishGL 63 / 3500 ~94.603 ms, waitGL 2 / 248 ~6.72 ms
+XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4040 ~106.341 ms, finishGL 62 / 3562 ~93.755 ms, waitGL 3 / 252 ~6.638 ms
+XXX[39] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4107 ~105.31 ms, finishGL 61 / 3624 ~92.927 ms, waitGL 3 / 255 ~6.558 ms
+XXX[40] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4173 ~104.339 ms, finishGL 61 / 3685 ~92.135 ms, waitGL 4 / 259 ~6.498 ms
+XXX[41] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4240 ~103.417 ms, finishGL 60 / 3746 ~91.37 ms, waitGL 4 / 264 ~6.454 ms
+XXX[42] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4306 ~102.536 ms, finishGL 60 / 3806 ~90.628 ms, waitGL 5 / 269 ~6.424 ms
+XXX[43] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4372 ~101.696 ms, finishGL 60 / 3866 ~89.923 ms, waitGL 5 / 274 ~6.391 ms
+XXX[44] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4439 ~100.895 ms, finishGL 60 / 3926 ~89.245 ms, waitGL 5 / 280 ~6.365 ms
+XXX[45] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4506 ~100.135 ms, finishGL 60 / 3986 ~88.596 ms, waitGL 5 / 285 ~6.349 ms
+XXX[46] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4572 ~99.399 ms, finishGL 59 / 4046 ~87.965 ms, waitGL 5 / 291 ~6.331 ms
+XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 4639 ~98.711 ms, finishGL 59 / 4106 ~87.361 ms, waitGL 6 / 298 ~6.341 ms
+XXX[48] TO 17 ms, lFrame0 1 ms, lFrameX 65 / 4705 ~98.027 ms, finishGL 59 / 4165 ~86.771 ms, waitGL 5 / 303 ~6.329 ms
+XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4771 ~97.382 ms, finishGL 59 / 4224 ~86.213 ms, waitGL 6 / 310 ~6.329 ms
+XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4838 ~96.763 ms, finishGL 59 / 4283 ~85.67 ms, waitGL 6 / 316 ~6.336 ms
+XXX[51] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4904 ~96.166 ms, finishGL 58 / 4342 ~85.145 ms, waitGL 6 / 323 ~6.336 ms
+XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 4971 ~95.613 ms, finishGL 58 / 4400 ~84.625 ms, waitGL 8 / 331 ~6.383 ms
+XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5037 ~95.056 ms, finishGL 58 / 4459 ~84.139 ms, waitGL 6 / 338 ~6.389 ms
+XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5104 ~94.527 ms, finishGL 58 / 4518 ~83.667 ms, waitGL 7 / 345 ~6.407 ms
+XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 5170 ~94.001 ms, finishGL 58 / 4576 ~83.211 ms, waitGL 6 / 352 ~6.407 ms
+XXX[56] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 5236 ~93.515 ms, finishGL 58 / 4635 ~82.77 ms, waitGL 7 / 359 ~6.42 ms
+XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5303 ~93.048 ms, finishGL 58 / 4693 ~82.348 ms, waitGL 7 / 367 ~6.443 ms
+XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5370 ~92.591 ms, finishGL 58 / 4752 ~81.938 ms, waitGL 7 / 374 ~6.463 ms
+XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5436 ~92.142 ms, finishGL 58 / 4811 ~81.548 ms, waitGL 6 / 381 ~6.464 ms
+XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5502 ~91.713 ms, finishGL 59 / 4870 ~81.18 ms, waitGL 6 / 387 ~6.463 ms
+XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5569 ~91.299 ms, finishGL 59 / 4930 ~80.821 ms, waitGL 6 / 394 ~6.467 ms
+XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 5635 ~90.89 ms, finishGL 59 / 4989 ~80.482 ms, waitGL 5 / 400 ~6.453 ms
+XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5701 ~90.504 ms, finishGL 59 / 5049 ~80.152 ms, waitGL 6 / 406 ~6.449 ms
+XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5768 ~90.129 ms, finishGL 59 / 5109 ~79.837 ms, waitGL 6 / 412 ~6.444 ms
+XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5834 ~89.765 ms, finishGL 60 / 5169 ~79.537 ms, waitGL 5 / 417 ~6.429 ms
+XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5901 ~89.412 ms, finishGL 60 / 5230 ~79.256 ms, waitGL 5 / 422 ~6.408 ms
+XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5967 ~89.07 ms, finishGL 61 / 5292 ~78.986 ms, waitGL 4 / 427 ~6.386 ms
+XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6033 ~88.733 ms, finishGL 61 / 5353 ~78.728 ms, waitGL 4 / 432 ~6.353 ms
+XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6100 ~88.413 ms, finishGL 61 / 5415 ~78.484 ms, waitGL 4 / 436 ~6.323 ms
+XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6166 ~88.092 ms, finishGL 62 / 5477 ~78.254 ms, waitGL 3 / 439 ~6.279 ms
+XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6233 ~87.802 ms, finishGL 62 / 5540 ~78.028 ms, waitGL 4 / 444 ~6.257 ms
+XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6299 ~87.495 ms, finishGL 61 / 5602 ~77.805 ms, waitGL 3 / 447 ~6.216 ms
+XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6366 ~87.213 ms, finishGL 61 / 5663 ~77.582 ms, waitGL 4 / 452 ~6.199 ms
+XXX[74] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 6432 ~86.931 ms, finishGL 60 / 5724 ~77.354 ms, waitGL 4 / 457 ~6.177 ms
+XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6499 ~86.656 ms, finishGL 60 / 5784 ~77.128 ms, waitGL 5 / 462 ~6.166 ms
+XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6565 ~86.393 ms, finishGL 59 / 5844 ~76.902 ms, waitGL 6 / 468 ~6.164 ms
+XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6632 ~86.135 ms, finishGL 60 / 5904 ~76.685 ms, waitGL 5 / 474 ~6.16 ms
+XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6698 ~85.878 ms, finishGL 60 / 5965 ~76.476 ms, waitGL 5 / 479 ~6.148 ms
+XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6765 ~85.634 ms, finishGL 60 / 6025 ~76.277 ms, waitGL 5 / 484 ~6.138 ms
+XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6831 ~85.388 ms, finishGL 60 / 6086 ~76.083 ms, waitGL 4 / 489 ~6.12 ms
+XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6898 ~85.162 ms, finishGL 60 / 6147 ~75.896 ms, waitGL 5 / 495 ~6.115 ms
+XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6964 ~84.932 ms, finishGL 61 / 6209 ~75.721 ms, waitGL 4 / 499 ~6.093 ms
+XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7030 ~84.709 ms, finishGL 62 / 6271 ~75.56 ms, waitGL 3 / 503 ~6.062 ms
+XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7097 ~84.491 ms, finishGL 62 / 6333 ~75.399 ms, waitGL 3 / 506 ~6.032 ms
+XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7163 ~84.28 ms, finishGL 61 / 6395 ~75.241 ms, waitGL 3 / 510 ~6.007 ms
+XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7230 ~84.076 ms, finishGL 62 / 6458 ~75.095 ms, waitGL 3 / 514 ~5.977 ms
+XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7296 ~83.87 ms, finishGL 63 / 6521 ~74.958 ms, waitGL 2 / 516 ~5.938 ms
+XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7363 ~83.676 ms, finishGL 62 / 6584 ~74.819 ms, waitGL 3 / 520 ~5.913 ms
+XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7430 ~83.483 ms, finishGL 62 / 6646 ~74.684 ms, waitGL 3 / 523 ~5.881 ms
+XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7496 ~83.293 ms, finishGL 62 / 6709 ~74.544 ms, waitGL 3 / 527 ~5.859 ms
+XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7562 ~83.108 ms, finishGL 62 / 6771 ~74.411 ms, waitGL 3 / 531 ~5.835 ms
+XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7629 ~82.927 ms, finishGL 62 / 6833 ~74.281 ms, waitGL 3 / 534 ~5.811 ms
+XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7695 ~82.751 ms, finishGL 61 / 6895 ~74.146 ms, waitGL 4 / 538 ~5.792 ms
+XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7762 ~82.579 ms, finishGL 61 / 6957 ~74.016 ms, waitGL 4 / 542 ~5.775 ms
+XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7828 ~82.408 ms, finishGL 62 / 7019 ~73.893 ms, waitGL 3 / 546 ~5.753 ms
+XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7895 ~82.243 ms, finishGL 62 / 7081 ~73.769 ms, waitGL 4 / 550 ~5.736 ms
+XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7962 ~82.082 ms, finishGL 61 / 7143 ~73.641 ms, waitGL 4 / 555 ~5.727 ms
+XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8028 ~81.924 ms, finishGL 60 / 7204 ~73.511 ms, waitGL 5 / 560 ~5.721 ms
+XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8095 ~81.77 ms, finishGL 60 / 7265 ~73.385 ms, waitGL 5 / 566 ~5.717 ms
+XXX[1] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 66 ~66.52 ms, finishGL 60 / 60 ~60.267 ms, waitGL 5 / 5 ~5.535 ms
+XXX[2] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 132 ~66.402 ms, finishGL 59 / 120 ~60.116 ms, waitGL 5 / 11 ~5.576 ms
+XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 198 ~66.297 ms, finishGL 59 / 180 ~60.016 ms, waitGL 5 / 16 ~5.646 ms
+XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 265 ~66.437 ms, finishGL 60 / 240 ~60.014 ms, waitGL 6 / 23 ~5.809 ms
+XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 332 ~66.458 ms, finishGL 59 / 299 ~59.909 ms, waitGL 6 / 29 ~5.929 ms
+XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 398 ~66.452 ms, finishGL 59 / 358 ~59.831 ms, waitGL 6 / 36 ~6.026 ms
+XXX[7] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 465 ~66.461 ms, finishGL 58 / 417 ~59.693 ms, waitGL 7 / 43 ~6.184 ms
+XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 531 ~66.442 ms, finishGL 59 / 477 ~59.686 ms, waitGL 6 / 49 ~6.182 ms
+XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 597 ~66.442 ms, finishGL 59 / 537 ~59.686 ms, waitGL 6 / 55 ~6.196 ms
+XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 664 ~66.417 ms, finishGL 61 / 598 ~59.828 ms, waitGL 4 / 60 ~6.038 ms
+XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 730 ~66.425 ms, finishGL 61 / 659 ~59.986 ms, waitGL 4 / 64 ~5.896 ms
+XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 797 ~66.433 ms, finishGL 60 / 720 ~60.066 ms, waitGL 5 / 69 ~5.826 ms
+XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 863 ~66.411 ms, finishGL 60 / 780 ~60.063 ms, waitGL 5 / 75 ~5.792 ms
+XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 930 ~66.443 ms, finishGL 59 / 840 ~60.054 ms, waitGL 6 / 81 ~5.835 ms
+XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 996 ~66.419 ms, finishGL 59 / 900 ~60.025 ms, waitGL 5 / 87 ~5.845 ms
+XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1063 ~66.45 ms, finishGL 59 / 959 ~59.969 ms, waitGL 7 / 94 ~5.918 ms
+XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1129 ~66.444 ms, finishGL 59 / 1018 ~59.933 ms, waitGL 6 / 101 ~5.952 ms
+XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1195 ~66.444 ms, finishGL 59 / 1078 ~59.91 ms, waitGL 6 / 107 ~5.973 ms
+XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1262 ~66.438 ms, finishGL 60 / 1138 ~59.931 ms, waitGL 5 / 113 ~5.949 ms
+FrameCount: 120 - FrameRate: 15.0
+XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1328 ~66.439 ms, finishGL 60 / 1199 ~59.954 ms, waitGL 5 / 118 ~5.924 ms
+XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1395 ~66.459 ms, finishGL 61 / 1260 ~60.005 ms, waitGL 5 / 123 ~5.898 ms
+XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1461 ~66.436 ms, finishGL 61 / 1321 ~60.064 ms, waitGL 3 / 127 ~5.802 ms
+XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1528 ~66.437 ms, finishGL 62 / 1383 ~60.164 ms, waitGL 3 / 131 ~5.71 ms
+XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1594 ~66.428 ms, finishGL 62 / 1446 ~60.279 ms, waitGL 2 / 134 ~5.592 ms
+XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1661 ~66.449 ms, finishGL 62 / 1509 ~60.379 ms, waitGL 3 / 137 ~5.519 ms
+XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1727 ~66.438 ms, finishGL 63 / 1572 ~60.495 ms, waitGL 2 / 140 ~5.397 ms
+XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1794 ~66.47 ms, finishGL 63 / 1636 ~60.62 ms, waitGL 3 / 143 ~5.309 ms
+XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1860 ~66.46 ms, finishGL 63 / 1699 ~60.705 ms, waitGL 2 / 146 ~5.219 ms
+XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1926 ~66.444 ms, finishGL 63 / 1763 ~60.801 ms, waitGL 1 / 148 ~5.106 ms
+XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1993 ~66.448 ms, finishGL 63 / 1827 ~60.905 ms, waitGL 2 / 150 ~5.01 ms
+XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2060 ~66.46 ms, finishGL 63 / 1890 ~60.984 ms, waitGL 3 / 153 ~4.947 ms
+XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2126 ~66.45 ms, finishGL 63 / 1953 ~61.047 ms, waitGL 2 / 155 ~4.866 ms
+XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2193 ~66.463 ms, finishGL 62 / 2016 ~61.095 ms, waitGL 3 / 159 ~4.835 ms
+XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2259 ~66.454 ms, finishGL 62 / 2078 ~61.142 ms, waitGL 2 / 162 ~4.778 ms
+XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2326 ~66.477 ms, finishGL 63 / 2142 ~61.22 ms, waitGL 3 / 165 ~4.727 ms
+XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2392 ~66.457 ms, finishGL 63 / 2205 ~61.272 ms, waitGL 2 / 167 ~4.658 ms
+XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2458 ~66.459 ms, finishGL 63 / 2268 ~61.323 ms, waitGL 2 / 170 ~4.611 ms
+XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2525 ~66.457 ms, finishGL 63 / 2332 ~61.38 ms, waitGL 2 / 173 ~4.556 ms
+XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2591 ~66.459 ms, finishGL 63 / 2395 ~61.43 ms, waitGL 2 / 175 ~4.508 ms
+XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2658 ~66.458 ms, finishGL 63 / 2458 ~61.472 ms, waitGL 2 / 178 ~4.467 ms
+XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2725 ~66.47 ms, finishGL 63 / 2522 ~61.516 ms, waitGL 3 / 181 ~4.438 ms
+XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2791 ~66.471 ms, finishGL 63 / 2585 ~61.552 ms, waitGL 3 / 185 ~4.405 ms
+XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2857 ~66.464 ms, finishGL 63 / 2648 ~61.589 ms, waitGL 2 / 187 ~4.364 ms
+XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2924 ~66.466 ms, finishGL 62 / 2710 ~61.611 ms, waitGL 3 / 191 ~4.346 ms
+XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2991 ~66.47 ms, finishGL 61 / 2772 ~61.615 ms, waitGL 4 / 195 ~4.347 ms
+XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3058 ~66.48 ms, finishGL 60 / 2833 ~61.592 ms, waitGL 5 / 201 ~4.383 ms
+XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3124 ~66.479 ms, finishGL 58 / 2891 ~61.531 ms, waitGL 7 / 208 ~4.444 ms
+XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3191 ~66.483 ms, finishGL 56 / 2948 ~61.417 ms, waitGL 10 / 219 ~4.563 ms
+XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3257 ~66.482 ms, finishGL 52 / 3000 ~61.228 ms, waitGL 13 / 232 ~4.751 ms
+XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3307 ~66.146 ms, finishGL 47 / 3047 ~60.945 ms, waitGL 2 / 234 ~4.698 ms
+XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3373 ~66.144 ms, finishGL 59 / 3106 ~60.92 ms, waitGL 5 / 240 ~4.721 ms
+XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3422 ~65.821 ms, finishGL 42 / 3149 ~60.571 ms, waitGL 5 / 246 ~4.737 ms
+XXX[53] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 3472 ~65.521 ms, finishGL 41 / 3191 ~60.216 ms, waitGL 7 / 253 ~4.782 ms
+XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3539 ~65.552 ms, finishGL 57 / 3248 ~60.158 ms, waitGL 9 / 263 ~4.872 ms
+XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3588 ~65.246 ms, finishGL 40 / 3288 ~59.799 ms, waitGL 7 / 270 ~4.925 ms
+XXX[56] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 3638 ~64.97 ms, finishGL 40 / 3328 ~59.446 ms, waitGL 8 / 279 ~4.993 ms
+XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3705 ~65.014 ms, finishGL 55 / 3384 ~59.376 ms, waitGL 11 / 290 ~5.104 ms
+XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3755 ~64.75 ms, finishGL 38 / 3423 ~59.018 ms, waitGL 10 / 301 ~5.193 ms
+XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3805 ~64.497 ms, finishGL 38 / 3461 ~58.667 ms, waitGL 10 / 311 ~5.285 ms
+XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3855 ~64.251 ms, finishGL 37 / 3499 ~58.319 ms, waitGL 11 / 323 ~5.386 ms
+XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3904 ~64.014 ms, finishGL 37 / 3536 ~57.97 ms, waitGL 11 / 334 ~5.491 ms
+XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3954 ~63.784 ms, finishGL 36 / 3572 ~57.617 ms, waitGL 13 / 348 ~5.613 ms
+XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4003 ~63.545 ms, finishGL 34 / 3607 ~57.256 ms, waitGL 13 / 361 ~5.732 ms
+XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4053 ~63.336 ms, finishGL 33 / 3640 ~56.886 ms, waitGL 15 / 376 ~5.889 ms
+XXX[65] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 4103 ~63.138 ms, finishGL 32 / 3673 ~56.51 ms, waitGL 16 / 393 ~6.059 ms
+XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4153 ~62.935 ms, finishGL 31 / 3704 ~56.132 ms, waitGL 17 / 411 ~6.229 ms
+XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4186 ~62.489 ms, finishGL 30 / 3735 ~55.75 ms, waitGL 1 / 413 ~6.164 ms
+XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4219 ~62.058 ms, finishGL 29 / 3764 ~55.366 ms, waitGL 2 / 415 ~6.117 ms
+XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4269 ~61.872 ms, finishGL 44 / 3808 ~55.202 ms, waitGL 4 / 420 ~6.093 ms
+XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4302 ~61.462 ms, finishGL 27 / 3836 ~54.811 ms, waitGL 4 / 425 ~6.075 ms
+XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4335 ~61.06 ms, finishGL 27 / 3864 ~54.424 ms, waitGL 4 / 430 ~6.06 ms
+XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4385 ~60.91 ms, finishGL 42 / 3907 ~54.264 ms, waitGL 6 / 437 ~6.071 ms
+XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4418 ~60.527 ms, finishGL 25 / 3932 ~53.871 ms, waitGL 6 / 443 ~6.078 ms
+XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4451 ~60.15 ms, finishGL 25 / 3957 ~53.482 ms, waitGL 6 / 450 ~6.088 ms
+XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4501 ~60.016 ms, finishGL 40 / 3998 ~53.31 ms, waitGL 9 / 459 ~6.128 ms
+XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4534 ~59.662 ms, finishGL 23 / 4021 ~52.916 ms, waitGL 9 / 468 ~6.169 ms
+XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4567 ~59.314 ms, finishGL 22 / 4044 ~52.527 ms, waitGL 9 / 478 ~6.209 ms
+XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4617 ~59.204 ms, finishGL 38 / 4083 ~52.35 ms, waitGL 11 / 489 ~6.278 ms
+XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4651 ~58.873 ms, finishGL 23 / 4106 ~51.979 ms, waitGL 9 / 499 ~6.317 ms
+XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4683 ~58.54 ms, finishGL 23 / 4129 ~51.619 ms, waitGL 8 / 507 ~6.344 ms
+XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4716 ~58.226 ms, finishGL 23 / 4152 ~51.269 ms, waitGL 9 / 516 ~6.379 ms
+XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4767 ~58.135 ms, finishGL 38 / 4191 ~51.116 ms, waitGL 11 / 528 ~6.439 ms
+XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4799 ~57.826 ms, finishGL 26 / 4218 ~50.823 ms, waitGL 4 / 532 ~6.421 ms
+XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4832 ~57.528 ms, finishGL 30 / 4248 ~50.576 ms, waitGL 2 / 534 ~6.368 ms
+XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4882 ~57.437 ms, finishGL 33 / 4281 ~50.375 ms, waitGL 15 / 550 ~6.477 ms
+XXX[86] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 4932 ~57.351 ms, finishGL 38 / 4320 ~50.233 ms, waitGL 10 / 561 ~6.527 ms
+XXX[87] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 4981 ~57.262 ms, finishGL 40 / 4360 ~50.122 ms, waitGL 7 / 569 ~6.542 ms
+XXX[88] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5031 ~57.177 ms, finishGL 41 / 4402 ~50.023 ms, waitGL 7 / 576 ~6.55 ms
+XXX[89] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5081 ~57.094 ms, finishGL 43 / 4445 ~49.945 ms, waitGL 5 / 582 ~6.539 ms
+XXX[90] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5131 ~57.013 ms, finishGL 42 / 4487 ~49.862 ms, waitGL 6 / 588 ~6.535 ms
+XXX[91] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5181 ~56.934 ms, finishGL 42 / 4530 ~49.786 ms, waitGL 5 / 593 ~6.526 ms
+XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5230 ~56.857 ms, finishGL 43 / 4573 ~49.715 ms, waitGL 6 / 600 ~6.522 ms
+XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5280 ~56.781 ms, finishGL 42 / 4616 ~49.641 ms, waitGL 6 / 606 ~6.522 ms
+XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5330 ~56.708 ms, finishGL 43 / 4660 ~49.575 ms, waitGL 5 / 612 ~6.516 ms
+XXX[95] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5380 ~56.635 ms, finishGL 43 / 4703 ~49.508 ms, waitGL 5 / 617 ~6.505 ms
+XXX[96] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5430 ~56.563 ms, finishGL 43 / 4746 ~49.442 ms, waitGL 5 / 623 ~6.495 ms
+XXX[97] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5480 ~56.494 ms, finishGL 43 / 4790 ~49.383 ms, waitGL 5 / 628 ~6.481 ms
+XXX[98] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5529 ~56.426 ms, finishGL 44 / 4834 ~49.332 ms, waitGL 4 / 633 ~6.459 ms
+XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5579 ~56.358 ms, finishGL 44 / 4879 ~49.288 ms, waitGL 4 / 637 ~6.438 ms
+XXX[100] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5629 ~56.293 ms, finishGL 45 / 4925 ~49.253 ms, waitGL 3 / 641 ~6.41 ms
+XXX[101] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5679 ~56.228 ms, finishGL 46 / 4971 ~49.225 ms, waitGL 2 / 643 ~6.369 ms
+XXX[102] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 5729 ~56.174 ms, finishGL 47 / 5019 ~49.211 ms, waitGL 1 / 645 ~6.324 ms
+XXX[103] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 5812 ~56.428 ms, finishGL 64 / 5084 ~49.365 ms, waitGL 16 / 661 ~6.423 ms
+XXX[104] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5879 ~56.533 ms, finishGL 49 / 5134 ~49.369 ms, waitGL 17 / 678 ~6.526 ms
+XXX[105] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5945 ~56.628 ms, finishGL 51 / 5185 ~49.388 ms, waitGL 14 / 693 ~6.6 ms
+XXX[106] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6011 ~56.711 ms, finishGL 53 / 5239 ~49.428 ms, waitGL 11 / 704 ~6.645 ms
+XXX[107] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 6078 ~56.805 ms, finishGL 57 / 5296 ~49.503 ms, waitGL 8 / 712 ~6.659 ms
+XXX[108] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6145 ~56.898 ms, finishGL 60 / 5356 ~49.601 ms, waitGL 6 / 718 ~6.656 ms
+XXX[109] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6211 ~56.983 ms, finishGL 61 / 5417 ~49.705 ms, waitGL 4 / 723 ~6.638 ms
+XXX[110] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6277 ~57.069 ms, finishGL 61 / 5479 ~49.817 ms, waitGL 3 / 727 ~6.613 ms
+XXX[111] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6344 ~57.153 ms, finishGL 61 / 5541 ~49.926 ms, waitGL 3 / 731 ~6.589 ms
+XXX[112] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6410 ~57.237 ms, finishGL 61 / 5603 ~50.032 ms, waitGL 3 / 735 ~6.565 ms
+XXX[113] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6477 ~57.319 ms, finishGL 61 / 5665 ~50.136 ms, waitGL 4 / 739 ~6.543 ms
+XXX[114] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6543 ~57.398 ms, finishGL 63 / 5728 ~50.251 ms, waitGL 2 / 742 ~6.51 ms
+XXX[115] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6610 ~57.483 ms, finishGL 64 / 5793 ~50.374 ms, waitGL 2 / 744 ~6.474 ms
+XXX[116] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6693 ~57.705 ms, finishGL 65 / 5858 ~50.503 ms, waitGL 17 / 762 ~6.569 ms
+XXX[117] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6776 ~57.922 ms, finishGL 65 / 5923 ~50.632 ms, waitGL 16 / 778 ~6.658 ms
+XXX[118] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 6859 ~58.133 ms, finishGL 65 / 5989 ~50.755 ms, waitGL 17 / 796 ~6.747 ms
+XXX[119] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6943 ~58.345 ms, finishGL 65 / 6054 ~50.877 ms, waitGL 17 / 813 ~6.838 ms
+XXX[120] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7026 ~58.552 ms, finishGL 66 / 6120 ~51.006 ms, waitGL 16 / 830 ~6.916 ms
+XXX[121] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7109 ~58.754 ms, finishGL 66 / 6187 ~51.135 ms, waitGL 15 / 845 ~6.988 ms
+XXX[122] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7191 ~58.948 ms, finishGL 67 / 6254 ~51.267 ms, waitGL 14 / 860 ~7.051 ms
+XXX[123] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7275 ~59.149 ms, finishGL 69 / 6324 ~51.416 ms, waitGL 13 / 873 ~7.103 ms
+XXX[124] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7357 ~59.338 ms, finishGL 71 / 6395 ~51.578 ms, waitGL 10 / 884 ~7.131 ms
+XXX[125] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7441 ~59.532 ms, finishGL 72 / 6468 ~51.748 ms, waitGL 10 / 894 ~7.157 ms
+XXX[126] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7524 ~59.718 ms, finishGL 74 / 6542 ~51.925 ms, waitGL 8 / 902 ~7.164 ms
+XXX[127] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7607 ~59.901 ms, finishGL 76 / 6618 ~52.116 ms, waitGL 6 / 909 ~7.158 ms
+XXX[128] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7690 ~60.084 ms, finishGL 74 / 6693 ~52.293 ms, waitGL 8 / 917 ~7.164 ms
+XXX[129] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7774 ~60.264 ms, finishGL 72 / 6765 ~52.449 ms, waitGL 10 / 927 ~7.189 ms
+2013-06-17 02:52:55.855 java[62619:cc07] Persistent UI failed to open file file://localhost/Users/jogamp/Library/Saved%20Application%20State/com.apple.javajdk16.cmd.savedState/window_1.data: Operation not permitted (1)
+XXX[130] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7855 ~60.427 ms, finishGL 68 / 6834 ~52.574 ms, waitGL 12 / 939 ~7.228 ms
+XXX[131] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 7937 ~60.593 ms, finishGL 68 / 6903 ~52.696 ms, waitGL 12 / 952 ~7.267 ms
+XXX[132] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 8020 ~60.763 ms, finishGL 67 / 6970 ~52.805 ms, waitGL 14 / 966 ~7.325 ms
+XXX[133] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 8104 ~60.932 ms, finishGL 65 / 7035 ~52.899 ms, waitGL 16 / 983 ~7.396 ms
+XXX[134] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8170 ~60.973 ms, finishGL 64 / 7100 ~52.987 ms, waitGL 1 / 984 ~7.348 ms
+XXX[135] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 8254 ~61.144 ms, finishGL 81 / 7181 ~53.199 ms, waitGL 2 / 986 ~7.309 ms
+XXX[136] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8337 ~61.305 ms, finishGL 80 / 7262 ~53.397 ms, waitGL 2 / 989 ~7.274 ms
+XXX[137] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8404 ~61.343 ms, finishGL 63 / 7325 ~53.474 ms, waitGL 1 / 990 ~7.232 ms
+XXX[138] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8487 ~61.501 ms, finishGL 79 / 7405 ~53.662 ms, waitGL 3 / 994 ~7.203 ms
+XXX[139] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8553 ~61.532 ms, finishGL 63 / 7469 ~53.737 ms, waitGL 1 / 995 ~7.16 ms
+FrameCount: 240 - FrameRate: 13.0
+XXX[140] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8619 ~61.565 ms, finishGL 62 / 7532 ~53.8 ms, waitGL 2 / 997 ~7.127 ms
+XXX[141] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8702 ~61.722 ms, finishGL 79 / 7611 ~53.984 ms, waitGL 3 / 1001 ~7.1 ms
+XXX[142] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8769 ~61.753 ms, finishGL 63 / 7674 ~54.047 ms, waitGL 2 / 1003 ~7.066 ms
+XXX[143] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 8835 ~61.786 ms, finishGL 62 / 7737 ~54.106 ms, waitGL 2 / 1006 ~7.036 ms
+XXX[144] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 8902 ~61.819 ms, finishGL 62 / 7799 ~54.164 ms, waitGL 2 / 1009 ~7.008 ms
+XXX[145] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 8968 ~61.851 ms, finishGL 61 / 7861 ~54.215 ms, waitGL 3 / 1012 ~6.986 ms
+XXX[146] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9034 ~61.883 ms, finishGL 61 / 7922 ~54.264 ms, waitGL 4 / 1017 ~6.97 ms
+XXX[147] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9101 ~61.914 ms, finishGL 61 / 7983 ~54.312 ms, waitGL 4 / 1022 ~6.952 ms
+XXX[148] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 9168 ~61.946 ms, finishGL 61 / 8045 ~54.359 ms, waitGL 4 / 1026 ~6.933 ms
+XXX[149] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9234 ~61.976 ms, finishGL 61 / 8106 ~54.406 ms, waitGL 4 / 1030 ~6.918 ms
+XXX[150] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9301 ~62.007 ms, finishGL 61 / 8167 ~54.451 ms, waitGL 5 / 1035 ~6.905 ms
+XXX[151] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9367 ~62.036 ms, finishGL 60 / 8228 ~54.492 ms, waitGL 5 / 1040 ~6.893 ms
+XXX[152] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 9433 ~62.065 ms, finishGL 61 / 8289 ~54.535 ms, waitGL 4 / 1045 ~6.876 ms
+XXX[153] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 9500 ~62.093 ms, finishGL 61 / 8350 ~54.579 ms, waitGL 4 / 1049 ~6.857 ms
+XXX[154] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 9566 ~62.122 ms, finishGL 60 / 8411 ~54.618 ms, waitGL 4 / 1054 ~6.844 ms
+XXX[155] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9633 ~62.15 ms, finishGL 61 / 8472 ~54.66 ms, waitGL 4 / 1058 ~6.829 ms
+XXX[156] TO 17 ms, lFrame0 1 ms, lFrameX 67 / 9700 ~62.184 ms, finishGL 61 / 8533 ~54.702 ms, waitGL 5 / 1063 ~6.818 ms
+XXX[157] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9766 ~62.208 ms, finishGL 60 / 8594 ~54.741 ms, waitGL 4 / 1068 ~6.805 ms
+XXX[158] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9833 ~62.235 ms, finishGL 60 / 8654 ~54.777 ms, waitGL 5 / 1073 ~6.797 ms
+XXX[159] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9899 ~62.259 ms, finishGL 60 / 8715 ~54.814 ms, waitGL 4 / 1078 ~6.783 ms
+XXX[160] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9965 ~62.286 ms, finishGL 60 / 8775 ~54.848 ms, waitGL 5 / 1084 ~6.777 ms
+XXX[161] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10032 ~62.316 ms, finishGL 59 / 8835 ~54.88 ms, waitGL 6 / 1091 ~6.777 ms
+XXX[162] TO 17 ms, lFrame0 1 ms, lFrameX 65 / 10098 ~62.338 ms, finishGL 58 / 8894 ~54.904 ms, waitGL 6 / 1097 ~6.772 ms
+XXX[163] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10165 ~62.367 ms, finishGL 58 / 8952 ~54.926 ms, waitGL 8 / 1105 ~6.78 ms
+XXX[164] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10232 ~62.392 ms, finishGL 58 / 9011 ~54.946 ms, waitGL 7 / 1112 ~6.785 ms
+XXX[165] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10298 ~62.416 ms, finishGL 58 / 9069 ~54.966 ms, waitGL 7 / 1120 ~6.791 ms
+XXX[166] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10365 ~62.441 ms, finishGL 58 / 9127 ~54.985 ms, waitGL 7 / 1128 ~6.797 ms
+XXX[167] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10431 ~62.465 ms, finishGL 57 / 9185 ~55.003 ms, waitGL 8 / 1136 ~6.805 ms
+XXX[168] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10498 ~62.488 ms, finishGL 57 / 9243 ~55.02 ms, waitGL 7 / 1144 ~6.811 ms
+XXX[169] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10564 ~62.511 ms, finishGL 58 / 9301 ~55.039 ms, waitGL 7 / 1151 ~6.815 ms
+XXX[170] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10630 ~62.534 ms, finishGL 58 / 9360 ~55.059 ms, waitGL 7 / 1159 ~6.819 ms
+XXX[171] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10697 ~62.557 ms, finishGL 58 / 9418 ~55.079 ms, waitGL 7 / 1166 ~6.822 ms
+XXX[172] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10763 ~62.579 ms, finishGL 58 / 9477 ~55.1 ms, waitGL 7 / 1173 ~6.824 ms
+XXX[173] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10829 ~62.6 ms, finishGL 59 / 9536 ~55.125 ms, waitGL 6 / 1180 ~6.82 ms
+XXX[174] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10896 ~62.622 ms, finishGL 59 / 9596 ~55.151 ms, waitGL 6 / 1186 ~6.818 ms
+XXX[175] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10963 ~62.646 ms, finishGL 59 / 9655 ~55.174 ms, waitGL 6 / 1193 ~6.817 ms
+XXX[176] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 11028 ~62.664 ms, finishGL 59 / 9715 ~55.199 ms, waitGL 5 / 1198 ~6.811 ms
+XXX[177] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11095 ~62.689 ms, finishGL 59 / 9774 ~55.222 ms, waitGL 7 / 1206 ~6.813 ms
+XXX[178] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11162 ~62.708 ms, finishGL 60 / 9834 ~55.252 ms, waitGL 4 / 1211 ~6.803 ms
+XXX[179] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11228 ~62.73 ms, finishGL 61 / 9896 ~55.287 ms, waitGL 4 / 1215 ~6.791 ms
+XXX[180] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11294 ~62.749 ms, finishGL 62 / 9958 ~55.327 ms, waitGL 3 / 1218 ~6.77 ms
+XXX[181] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11361 ~62.77 ms, finishGL 63 / 10022 ~55.37 ms, waitGL 3 / 1221 ~6.75 ms
+XXX[182] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11428 ~62.793 ms, finishGL 64 / 10086 ~55.418 ms, waitGL 2 / 1224 ~6.725 ms
+XXX[183] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 11510 ~62.899 ms, finishGL 64 / 10150 ~55.469 ms, waitGL 16 / 1240 ~6.779 ms
+XXX[184] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 11593 ~63.01 ms, finishGL 82 / 10233 ~55.615 ms, waitGL 0 / 1240 ~6.744 ms
+XXX[185] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 11677 ~63.119 ms, finishGL 68 / 10301 ~55.685 ms, waitGL 14 / 1255 ~6.784 ms
+XXX[186] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 11777 ~63.322 ms, finishGL 86 / 10388 ~55.85 ms, waitGL 13 / 1268 ~6.821 ms
+XXX[187] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 11860 ~63.427 ms, finishGL 74 / 10462 ~55.951 ms, waitGL 7 / 1276 ~6.827 ms
+XXX[188] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 11943 ~63.527 ms, finishGL 77 / 10540 ~56.066 ms, waitGL 3 / 1280 ~6.811 ms
+XXX[189] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12043 ~63.72 ms, finishGL 94 / 10635 ~56.269 ms, waitGL 4 / 1285 ~6.799 ms
+XXX[190] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 12126 ~63.823 ms, finishGL 79 / 10714 ~56.39 ms, waitGL 2 / 1287 ~6.778 ms
+XXX[191] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12209 ~63.924 ms, finishGL 80 / 10794 ~56.515 ms, waitGL 2 / 1290 ~6.756 ms
+XXX[192] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12293 ~64.027 ms, finishGL 79 / 10873 ~56.633 ms, waitGL 3 / 1293 ~6.739 ms
+XXX[193] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12376 ~64.128 ms, finishGL 80 / 10954 ~56.759 ms, waitGL 2 / 1295 ~6.714 ms
+XXX[194] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 12475 ~64.308 ms, finishGL 97 / 11051 ~56.968 ms, waitGL 1 / 1296 ~6.685 ms
+XXX[195] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 12576 ~64.495 ms, finishGL 97 / 11149 ~57.177 ms, waitGL 2 / 1299 ~6.664 ms
+XXX[196] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 12675 ~64.67 ms, finishGL 95 / 11244 ~57.372 ms, waitGL 3 / 1302 ~6.645 ms
+XXX[197] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 12758 ~64.764 ms, finishGL 77 / 11322 ~57.474 ms, waitGL 4 / 1307 ~6.635 ms
+XXX[198] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 12842 ~64.862 ms, finishGL 77 / 11399 ~57.573 ms, waitGL 5 / 1313 ~6.632 ms
+XXX[199] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12925 ~64.952 ms, finishGL 76 / 11475 ~57.667 ms, waitGL 5 / 1319 ~6.628 ms
+XXX[200] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 13008 ~65.04 ms, finishGL 76 / 11552 ~57.762 ms, waitGL 4 / 1324 ~6.62 ms
+XXX[201] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13091 ~65.131 ms, finishGL 77 / 11629 ~57.859 ms, waitGL 5 / 1329 ~6.613 ms
+XXX[202] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13174 ~65.22 ms, finishGL 77 / 11706 ~57.954 ms, waitGL 5 / 1334 ~6.608 ms
+XXX[203] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 13257 ~65.309 ms, finishGL 76 / 11783 ~58.046 ms, waitGL 5 / 1340 ~6.602 ms
+XXX[204] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 13341 ~65.397 ms, finishGL 76 / 11859 ~58.135 ms, waitGL 4 / 1345 ~6.593 ms
+XXX[205] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13424 ~65.483 ms, finishGL 75 / 11934 ~58.219 ms, waitGL 6 / 1351 ~6.594 ms
+XXX[206] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13507 ~65.569 ms, finishGL 74 / 12009 ~58.299 ms, waitGL 8 / 1359 ~6.601 ms
+XXX[207] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13590 ~65.654 ms, finishGL 73 / 12083 ~58.373 ms, waitGL 9 / 1368 ~6.613 ms
+XXX[208] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13673 ~65.738 ms, finishGL 71 / 12155 ~58.439 ms, waitGL 10 / 1379 ~6.632 ms
+XXX[209] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 13756 ~65.822 ms, finishGL 70 / 12225 ~58.497 ms, waitGL 11 / 1391 ~6.655 ms
+XXX[210] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13839 ~65.904 ms, finishGL 68 / 12294 ~58.546 ms, waitGL 13 / 1404 ~6.688 ms
+XXX[211] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 13923 ~65.986 ms, finishGL 67 / 12362 ~58.588 ms, waitGL 14 / 1419 ~6.726 ms
+XXX[212] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14006 ~66.067 ms, finishGL 65 / 12428 ~58.623 ms, waitGL 16 / 1435 ~6.772 ms
+XXX[213] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14073 ~66.073 ms, finishGL 64 / 12492 ~58.65 ms, waitGL 2 / 1437 ~6.75 ms
+XXX[214] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 14155 ~66.148 ms, finishGL 80 / 12572 ~58.75 ms, waitGL 1 / 1439 ~6.726 ms
+XXX[215] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 14222 ~66.15 ms, finishGL 63 / 12636 ~58.772 ms, waitGL 2 / 1441 ~6.705 ms
+XXX[216] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 14289 ~66.152 ms, finishGL 63 / 12699 ~58.795 ms, waitGL 2 / 1443 ~6.684 ms
+XXX[217] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14356 ~66.158 ms, finishGL 63 / 12763 ~58.819 ms, waitGL 2 / 1446 ~6.667 ms
+XXX[218] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14439 ~66.236 ms, finishGL 65 / 12829 ~58.85 ms, waitGL 16 / 1463 ~6.715 ms
+XXX[219] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 14521 ~66.308 ms, finishGL 68 / 12898 ~58.896 ms, waitGL 12 / 1475 ~6.739 ms
+XXX[220] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 14604 ~66.384 ms, finishGL 71 / 12969 ~58.951 ms, waitGL 11 / 1486 ~6.758 ms
+XXX[221] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 14687 ~66.46 ms, finishGL 73 / 13042 ~59.017 ms, waitGL 8 / 1495 ~6.766 ms
+XXX[222] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 14770 ~66.535 ms, finishGL 76 / 13118 ~59.094 ms, waitGL 5 / 1501 ~6.763 ms
+XXX[223] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 14854 ~66.61 ms, finishGL 76 / 13195 ~59.173 ms, waitGL 5 / 1506 ~6.755 ms
+XXX[224] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14937 ~66.683 ms, finishGL 76 / 13272 ~59.252 ms, waitGL 5 / 1512 ~6.751 ms
+XXX[225] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 15021 ~66.761 ms, finishGL 76 / 13349 ~59.33 ms, waitGL 6 / 1518 ~6.75 ms
+XXX[226] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 15104 ~66.834 ms, finishGL 75 / 13424 ~59.401 ms, waitGL 7 / 1526 ~6.753 ms
+XXX[227] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15186 ~66.902 ms, finishGL 75 / 13499 ~59.47 ms, waitGL 6 / 1532 ~6.751 ms
+XXX[228] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15270 ~66.973 ms, finishGL 74 / 13574 ~59.537 ms, waitGL 7 / 1539 ~6.753 ms
+XXX[229] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15353 ~67.044 ms, finishGL 73 / 13648 ~59.6 ms, waitGL 8 / 1547 ~6.759 ms
+XXX[230] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15436 ~67.114 ms, finishGL 73 / 13721 ~59.658 ms, waitGL 9 / 1556 ~6.769 ms
+XXX[231] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15519 ~67.183 ms, finishGL 72 / 13793 ~59.714 ms, waitGL 9 / 1566 ~6.781 ms
+XXX[232] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15602 ~67.253 ms, finishGL 70 / 13864 ~59.761 ms, waitGL 11 / 1578 ~6.802 ms
+XXX[233] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 15685 ~67.32 ms, finishGL 69 / 13933 ~59.801 ms, waitGL 12 / 1590 ~6.827 ms
+XXX[234] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 15768 ~67.388 ms, finishGL 67 / 14001 ~59.836 ms, waitGL 14 / 1605 ~6.86 ms
+XXX[235] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15852 ~67.456 ms, finishGL 66 / 14067 ~59.863 ms, waitGL 15 / 1621 ~6.899 ms
+XXX[236] TO 17 ms, lFrame0 1 ms, lFrameX 67 / 15919 ~67.455 ms, finishGL 65 / 14133 ~59.885 ms, waitGL 1 / 1622 ~6.874 ms
+XXX[237] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 16001 ~67.518 ms, finishGL 79 / 14212 ~59.967 ms, waitGL 2 / 1624 ~6.854 ms
+XXX[238] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16068 ~67.513 ms, finishGL 63 / 14275 ~59.98 ms, waitGL 2 / 1627 ~6.836 ms
+XXX[239] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16134 ~67.509 ms, finishGL 63 / 14338 ~59.994 ms, waitGL 2 / 1629 ~6.817 ms
+XXX[240] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16201 ~67.505 ms, finishGL 62 / 14401 ~60.006 ms, waitGL 2 / 1631 ~6.799 ms
+XXX[241] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16267 ~67.5 ms, finishGL 63 / 14464 ~60.019 ms, waitGL 2 / 1633 ~6.779 ms
+XXX[242] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16334 ~67.497 ms, finishGL 62 / 14527 ~60.03 ms, waitGL 2 / 1636 ~6.762 ms
+XXX[243] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16400 ~67.492 ms, finishGL 62 / 14590 ~60.042 ms, waitGL 2 / 1639 ~6.745 ms
+XXX[244] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16467 ~67.488 ms, finishGL 62 / 14652 ~60.05 ms, waitGL 3 / 1642 ~6.73 ms
+XXX[245] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16533 ~67.484 ms, finishGL 61 / 14713 ~60.056 ms, waitGL 4 / 1646 ~6.721 ms
+XXX[246] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16600 ~67.48 ms, finishGL 61 / 14775 ~60.063 ms, waitGL 3 / 1650 ~6.708 ms
+XXX[247] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16666 ~67.476 ms, finishGL 61 / 14837 ~60.07 ms, waitGL 3 / 1653 ~6.695 ms
+XXX[248] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16733 ~67.472 ms, finishGL 62 / 14899 ~60.08 ms, waitGL 2 / 1656 ~6.68 ms
+XXX[249] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16799 ~67.468 ms, finishGL 63 / 14963 ~60.093 ms, waitGL 1 / 1658 ~6.661 ms
+XXX[250] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16866 ~67.464 ms, finishGL 64 / 15027 ~60.11 ms, waitGL 1 / 1660 ~6.64 ms
+XXX[251] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 16966 ~67.593 ms, finishGL 82 / 15110 ~60.201 ms, waitGL 16 / 1676 ~6.679 ms
+XXX[252] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17049 ~67.655 ms, finishGL 68 / 15178 ~60.233 ms, waitGL 14 / 1690 ~6.709 ms
+XXX[253] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 17132 ~67.717 ms, finishGL 69 / 15248 ~60.271 ms, waitGL 12 / 1703 ~6.731 ms
+XXX[254] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 17215 ~67.779 ms, finishGL 72 / 15320 ~60.317 ms, waitGL 10 / 1713 ~6.746 ms
+XXX[255] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 17298 ~67.838 ms, finishGL 73 / 15393 ~60.367 ms, waitGL 8 / 1722 ~6.753 ms
+XXX[256] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17381 ~67.898 ms, finishGL 75 / 15468 ~60.425 ms, waitGL 7 / 1729 ~6.756 ms
+XXX[257] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 17466 ~67.961 ms, finishGL 76 / 15545 ~60.487 ms, waitGL 6 / 1736 ~6.755 ms
+XXX[258] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17548 ~68.018 ms, finishGL 76 / 15622 ~60.55 ms, waitGL 5 / 1741 ~6.75 ms
+XXX[259] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 17632 ~68.078 ms, finishGL 78 / 15700 ~60.619 ms, waitGL 4 / 1745 ~6.74 ms
+FrameCount: 360 - FrameRate: 13.0
+XXX[260] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17714 ~68.134 ms, finishGL 78 / 15778 ~60.687 ms, waitGL 3 / 1749 ~6.729 ms
+XXX[261] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 17797 ~68.19 ms, finishGL 78 / 15857 ~60.756 ms, waitGL 3 / 1752 ~6.715 ms
+XXX[262] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17881 ~68.248 ms, finishGL 78 / 15936 ~60.825 ms, waitGL 3 / 1756 ~6.704 ms
+XXX[263] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17964 ~68.304 ms, finishGL 78 / 16015 ~60.894 ms, waitGL 3 / 1760 ~6.693 ms
+XXX[264] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18047 ~68.36 ms, finishGL 77 / 16093 ~60.958 ms, waitGL 4 / 1764 ~6.685 ms
+XXX[265] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18130 ~68.417 ms, finishGL 77 / 16170 ~61.02 ms, waitGL 5 / 1770 ~6.679 ms
+XXX[266] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 18214 ~68.475 ms, finishGL 76 / 16247 ~61.08 ms, waitGL 6 / 1776 ~6.679 ms
+XXX[267] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18296 ~68.527 ms, finishGL 75 / 16323 ~61.136 ms, waitGL 5 / 1782 ~6.675 ms
+XXX[268] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18380 ~68.582 ms, finishGL 75 / 16399 ~61.19 ms, waitGL 6 / 1788 ~6.674 ms
+XXX[269] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18463 ~68.636 ms, finishGL 74 / 16473 ~61.241 ms, waitGL 7 / 1796 ~6.678 ms
+XXX[270] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18546 ~68.692 ms, finishGL 74 / 16548 ~61.289 ms, waitGL 8 / 1805 ~6.685 ms
+XXX[271] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 18629 ~68.744 ms, finishGL 71 / 16619 ~61.327 ms, waitGL 10 / 1815 ~6.697 ms
+XXX[272] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18712 ~68.797 ms, finishGL 70 / 16690 ~61.362 ms, waitGL 11 / 1826 ~6.715 ms
+XXX[273] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 18796 ~68.849 ms, finishGL 70 / 16760 ~61.394 ms, waitGL 12 / 1838 ~6.735 ms
+XXX[274] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 18879 ~68.902 ms, finishGL 68 / 16829 ~61.42 ms, waitGL 13 / 1852 ~6.76 ms
+XXX[275] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 18962 ~68.954 ms, finishGL 68 / 16897 ~61.444 ms, waitGL 14 / 1866 ~6.787 ms
+XXX[276] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 19045 ~69.006 ms, finishGL 67 / 16964 ~61.465 ms, waitGL 14 / 1881 ~6.816 ms
+XXX[277] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 19128 ~69.056 ms, finishGL 66 / 17030 ~61.483 ms, waitGL 15 / 1897 ~6.849 ms
+XXX[278] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 19211 ~69.107 ms, finishGL 66 / 17096 ~61.499 ms, waitGL 16 / 1913 ~6.884 ms
+XXX[279] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 19278 ~69.098 ms, finishGL 64 / 17161 ~61.512 ms, waitGL 0 / 1914 ~6.86 ms
+XXX[280] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 19361 ~69.148 ms, finishGL 81 / 17243 ~61.584 ms, waitGL 1 / 1915 ~6.839 ms
+XXX[281] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 19444 ~69.197 ms, finishGL 80 / 17324 ~61.652 ms, waitGL 1 / 1916 ~6.821 ms
+XXX[282] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19511 ~69.188 ms, finishGL 63 / 17387 ~61.659 ms, waitGL 2 / 1919 ~6.805 ms
+XXX[283] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19577 ~69.178 ms, finishGL 62 / 17450 ~61.662 ms, waitGL 3 / 1922 ~6.792 ms
+XXX[284] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19644 ~69.169 ms, finishGL 61 / 17512 ~61.662 ms, waitGL 4 / 1926 ~6.784 ms
+XXX[285] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19710 ~69.16 ms, finishGL 60 / 17573 ~61.659 ms, waitGL 5 / 1932 ~6.779 ms
+XXX[286] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 19777 ~69.15 ms, finishGL 59 / 17632 ~61.651 ms, waitGL 5 / 1938 ~6.776 ms
+XXX[287] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 19843 ~69.142 ms, finishGL 58 / 17690 ~61.639 ms, waitGL 7 / 1945 ~6.777 ms
+XXX[288] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 19910 ~69.132 ms, finishGL 57 / 17748 ~61.625 ms, waitGL 7 / 1952 ~6.78 ms
+XXX[289] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 19976 ~69.122 ms, finishGL 56 / 17804 ~61.607 ms, waitGL 8 / 1961 ~6.787 ms
+XXX[290] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20043 ~69.115 ms, finishGL 54 / 17859 ~61.583 ms, waitGL 11 / 1973 ~6.804 ms
+XXX[291] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20109 ~69.105 ms, finishGL 53 / 17912 ~61.555 ms, waitGL 11 / 1984 ~6.821 ms
+XXX[292] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20176 ~69.096 ms, finishGL 52 / 17965 ~61.525 ms, waitGL 13 / 1997 ~6.842 ms
+XXX[293] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20242 ~69.087 ms, finishGL 51 / 18017 ~61.492 ms, waitGL 13 / 2011 ~6.864 ms
+XXX[294] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20308 ~69.078 ms, finishGL 51 / 18068 ~61.457 ms, waitGL 13 / 2025 ~6.888 ms
+XXX[295] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20375 ~69.069 ms, finishGL 50 / 18119 ~61.42 ms, waitGL 14 / 2040 ~6.915 ms
+XXX[296] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20442 ~69.061 ms, finishGL 49 / 18169 ~61.381 ms, waitGL 15 / 2055 ~6.945 ms
+XXX[297] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20508 ~69.052 ms, finishGL 49 / 18218 ~61.341 ms, waitGL 15 / 2071 ~6.975 ms
+XXX[298] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20575 ~69.043 ms, finishGL 49 / 18267 ~61.3 ms, waitGL 16 / 2087 ~7.006 ms
+XXX[299] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20641 ~69.035 ms, finishGL 49 / 18316 ~61.26 ms, waitGL 15 / 2103 ~7.036 ms
+XXX[300] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20707 ~69.026 ms, finishGL 49 / 18366 ~61.222 ms, waitGL 15 / 2119 ~7.064 ms
+XXX[301] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20774 ~69.018 ms, finishGL 51 / 18417 ~61.188 ms, waitGL 14 / 2133 ~7.088 ms
+XXX[302] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20840 ~69.009 ms, finishGL 51 / 18469 ~61.156 ms, waitGL 13 / 2147 ~7.111 ms
+XXX[303] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20907 ~69.001 ms, finishGL 52 / 18522 ~61.129 ms, waitGL 12 / 2160 ~7.128 ms
+XXX[304] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20973 ~68.993 ms, finishGL 55 / 18577 ~61.109 ms, waitGL 10 / 2170 ~7.139 ms
+XXX[305] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 21040 ~68.985 ms, finishGL 57 / 18634 ~61.097 ms, waitGL 8 / 2178 ~7.143 ms
+XXX[306] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 21106 ~68.977 ms, finishGL 60 / 18694 ~61.094 ms, waitGL 5 / 2183 ~7.136 ms
+XXX[307] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 21173 ~68.968 ms, finishGL 65 / 18760 ~61.107 ms, waitGL 0 / 2184 ~7.114 ms
+XXX[308] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 21273 ~69.069 ms, finishGL 87 / 18847 ~61.192 ms, waitGL 12 / 2196 ~7.13 ms
+XXX[309] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21356 ~69.114 ms, finishGL 74 / 18922 ~61.236 ms, waitGL 7 / 2203 ~7.131 ms
+XXX[310] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21439 ~69.16 ms, finishGL 76 / 18998 ~61.286 ms, waitGL 5 / 2208 ~7.125 ms
+XXX[311] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21522 ~69.205 ms, finishGL 78 / 19077 ~61.341 ms, waitGL 3 / 2212 ~7.113 ms
+XXX[312] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 21606 ~69.25 ms, finishGL 79 / 19156 ~61.398 ms, waitGL 3 / 2215 ~7.101 ms
+XXX[313] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21689 ~69.294 ms, finishGL 78 / 19235 ~61.454 ms, waitGL 3 / 2218 ~7.088 ms
+XXX[314] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21772 ~69.338 ms, finishGL 78 / 19313 ~61.509 ms, waitGL 3 / 2222 ~7.076 ms
+XXX[315] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21855 ~69.382 ms, finishGL 79 / 19393 ~61.565 ms, waitGL 3 / 2225 ~7.064 ms
+XXX[316] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21938 ~69.426 ms, finishGL 80 / 19473 ~61.624 ms, waitGL 1 / 2226 ~7.046 ms
+XXX[317] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22022 ~69.471 ms, finishGL 81 / 19554 ~61.687 ms, waitGL 1 / 2228 ~7.029 ms
+XXX[318] TO 17 ms, lFrame0 0 ms, lFrameX 115 / 22138 ~69.617 ms, finishGL 98 / 19653 ~61.802 ms, waitGL 16 / 2245 ~7.059 ms
+XXX[319] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22221 ~69.659 ms, finishGL 80 / 19734 ~61.862 ms, waitGL 1 / 2246 ~7.042 ms
+XXX[320] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22304 ~69.702 ms, finishGL 79 / 19814 ~61.919 ms, waitGL 2 / 2248 ~7.027 ms
+XXX[321] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22387 ~69.744 ms, finishGL 79 / 19893 ~61.973 ms, waitGL 3 / 2251 ~7.015 ms
+XXX[322] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22471 ~69.786 ms, finishGL 79 / 19972 ~62.026 ms, waitGL 3 / 2255 ~7.005 ms
+XXX[323] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22554 ~69.827 ms, finishGL 78 / 20050 ~62.077 ms, waitGL 3 / 2259 ~6.994 ms
+XXX[324] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22637 ~69.868 ms, finishGL 78 / 20129 ~62.128 ms, waitGL 3 / 2262 ~6.982 ms
+XXX[325] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22720 ~69.909 ms, finishGL 78 / 20207 ~62.178 ms, waitGL 3 / 2266 ~6.972 ms
+XXX[326] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22803 ~69.95 ms, finishGL 78 / 20286 ~62.227 ms, waitGL 3 / 2269 ~6.962 ms
+XXX[327] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22887 ~69.991 ms, finishGL 78 / 20365 ~62.278 ms, waitGL 4 / 2274 ~6.954 ms
+XXX[328] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22970 ~70.031 ms, finishGL 79 / 20444 ~62.33 ms, waitGL 3 / 2277 ~6.942 ms
+XXX[329] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 23053 ~70.07 ms, finishGL 78 / 20522 ~62.379 ms, waitGL 3 / 2280 ~6.931 ms
+XXX[330] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 23136 ~70.11 ms, finishGL 79 / 20602 ~62.432 ms, waitGL 2 / 2282 ~6.917 ms
+XXX[331] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 23220 ~70.152 ms, finishGL 79 / 20681 ~62.483 ms, waitGL 3 / 2286 ~6.907 ms
+XXX[332] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23302 ~70.189 ms, finishGL 79 / 20761 ~62.535 ms, waitGL 2 / 2288 ~6.893 ms
+XXX[333] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23386 ~70.229 ms, finishGL 80 / 20842 ~62.589 ms, waitGL 2 / 2290 ~6.879 ms
+XXX[334] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23469 ~70.267 ms, finishGL 80 / 20922 ~62.641 ms, waitGL 2 / 2293 ~6.866 ms
+XXX[335] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 23552 ~70.305 ms, finishGL 79 / 21002 ~62.693 ms, waitGL 2 / 2295 ~6.852 ms
+XXX[336] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 23635 ~70.344 ms, finishGL 79 / 21081 ~62.742 ms, waitGL 2 / 2298 ~6.841 ms
+XXX[337] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 23718 ~70.382 ms, finishGL 78 / 21160 ~62.79 ms, waitGL 3 / 2301 ~6.83 ms
+XXX[338] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23802 ~70.421 ms, finishGL 77 / 21238 ~62.834 ms, waitGL 5 / 2307 ~6.826 ms
+XXX[339] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23885 ~70.459 ms, finishGL 76 / 21314 ~62.875 ms, waitGL 5 / 2313 ~6.823 ms
+XXX[340] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23969 ~70.497 ms, finishGL 77 / 21391 ~62.917 ms, waitGL 5 / 2319 ~6.82 ms
+XXX[341] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24052 ~70.533 ms, finishGL 77 / 21468 ~62.958 ms, waitGL 5 / 2324 ~6.816 ms
+XXX[342] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24135 ~70.57 ms, finishGL 76 / 21545 ~62.998 ms, waitGL 6 / 2330 ~6.814 ms
+XXX[343] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24218 ~70.607 ms, finishGL 76 / 21621 ~63.037 ms, waitGL 6 / 2336 ~6.813 ms
+XXX[344] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24301 ~70.644 ms, finishGL 76 / 21697 ~63.075 ms, waitGL 6 / 2343 ~6.812 ms
+XXX[345] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24384 ~70.68 ms, finishGL 75 / 21773 ~63.112 ms, waitGL 6 / 2350 ~6.812 ms
+XXX[346] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24467 ~70.715 ms, finishGL 76 / 21849 ~63.15 ms, waitGL 6 / 2356 ~6.811 ms
+XXX[347] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24551 ~70.752 ms, finishGL 75 / 21925 ~63.186 ms, waitGL 7 / 2363 ~6.812 ms
+XXX[348] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24633 ~70.787 ms, finishGL 75 / 22001 ~63.222 ms, waitGL 6 / 2370 ~6.811 ms
+XXX[349] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24717 ~70.822 ms, finishGL 75 / 22077 ~63.258 ms, waitGL 6 / 2377 ~6.811 ms
+XXX[350] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24800 ~70.857 ms, finishGL 75 / 22153 ~63.295 ms, waitGL 6 / 2383 ~6.811 ms
+XXX[351] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24883 ~70.892 ms, finishGL 75 / 22228 ~63.329 ms, waitGL 7 / 2391 ~6.812 ms
+XXX[352] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24966 ~70.927 ms, finishGL 75 / 22304 ~63.365 ms, waitGL 6 / 2397 ~6.812 ms
+XXX[353] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25049 ~70.961 ms, finishGL 75 / 22380 ~63.399 ms, waitGL 6 / 2404 ~6.812 ms
+XXX[354] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25131 ~70.993 ms, finishGL 75 / 22456 ~63.435 ms, waitGL 5 / 2410 ~6.809 ms
+XXX[355] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25215 ~71.03 ms, finishGL 76 / 22532 ~63.471 ms, waitGL 7 / 2417 ~6.81 ms
+XXX[356] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25298 ~71.062 ms, finishGL 76 / 22608 ~63.507 ms, waitGL 5 / 2423 ~6.807 ms
+XXX[357] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25382 ~71.098 ms, finishGL 75 / 22684 ~63.541 ms, waitGL 7 / 2430 ~6.808 ms
+XXX[358] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25465 ~71.131 ms, finishGL 76 / 22760 ~63.576 ms, waitGL 6 / 2437 ~6.807 ms
+XXX[359] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25548 ~71.164 ms, finishGL 75 / 22836 ~63.61 ms, waitGL 6 / 2443 ~6.807 ms
+XXX[360] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25631 ~71.198 ms, finishGL 76 / 22912 ~63.645 ms, waitGL 6 / 2450 ~6.806 ms
+XXX[361] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25714 ~71.23 ms, finishGL 76 / 22988 ~63.681 ms, waitGL 5 / 2456 ~6.803 ms
+XXX[362] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25797 ~71.263 ms, finishGL 76 / 23065 ~63.715 ms, waitGL 6 / 2462 ~6.803 ms
+XXX[363] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25880 ~71.297 ms, finishGL 76 / 23141 ~63.751 ms, waitGL 6 / 2468 ~6.801 ms
+XXX[364] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25963 ~71.327 ms, finishGL 77 / 23219 ~63.788 ms, waitGL 4 / 2473 ~6.794 ms
+XXX[365] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26046 ~71.361 ms, finishGL 78 / 23297 ~63.827 ms, waitGL 5 / 2478 ~6.789 ms
+XXX[366] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26129 ~71.393 ms, finishGL 77 / 23374 ~63.865 ms, waitGL 4 / 2483 ~6.784 ms
+XXX[367] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26213 ~71.425 ms, finishGL 77 / 23451 ~63.901 ms, waitGL 5 / 2488 ~6.781 ms
+XXX[368] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26296 ~71.457 ms, finishGL 77 / 23529 ~63.939 ms, waitGL 4 / 2493 ~6.775 ms
+XXX[369] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26379 ~71.489 ms, finishGL 77 / 23607 ~63.977 ms, waitGL 4 / 2498 ~6.77 ms
+XXX[370] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26462 ~71.52 ms, finishGL 78 / 23685 ~64.015 ms, waitGL 4 / 2502 ~6.763 ms
+XXX[371] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26545 ~71.551 ms, finishGL 77 / 23763 ~64.052 ms, waitGL 4 / 2507 ~6.757 ms
+XXX[372] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26628 ~71.583 ms, finishGL 77 / 23841 ~64.089 ms, waitGL 4 / 2512 ~6.753 ms
+XXX[373] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26711 ~71.613 ms, finishGL 76 / 23918 ~64.123 ms, waitGL 5 / 2517 ~6.75 ms
+XXX[374] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26795 ~71.645 ms, finishGL 76 / 23994 ~64.156 ms, waitGL 6 / 2524 ~6.75 ms
+XXX[375] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26878 ~71.675 ms, finishGL 75 / 24070 ~64.187 ms, waitGL 6 / 2531 ~6.75 ms
+XXX[376] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26961 ~71.706 ms, finishGL 75 / 24145 ~64.217 ms, waitGL 6 / 2538 ~6.75 ms
+XXX[377] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27044 ~71.737 ms, finishGL 75 / 24220 ~64.246 ms, waitGL 7 / 2545 ~6.753 ms
+XXX[378] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27128 ~71.767 ms, finishGL 75 / 24296 ~64.275 ms, waitGL 7 / 2553 ~6.754 ms
+XXX[379] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27211 ~71.797 ms, finishGL 75 / 24371 ~64.303 ms, waitGL 7 / 2560 ~6.757 ms
+FrameCount: 480 - FrameRate: 12.0
+XXX[380] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27294 ~71.827 ms, finishGL 74 / 24445 ~64.329 ms, waitGL 8 / 2569 ~6.761 ms
+XXX[381] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27377 ~71.856 ms, finishGL 73 / 24518 ~64.353 ms, waitGL 9 / 2578 ~6.767 ms
+XXX[382] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27460 ~71.885 ms, finishGL 73 / 24591 ~64.376 ms, waitGL 8 / 2587 ~6.773 ms
+XXX[383] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27543 ~71.916 ms, finishGL 73 / 24664 ~64.399 ms, waitGL 9 / 2597 ~6.781 ms
+XXX[384] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27626 ~71.945 ms, finishGL 72 / 24737 ~64.419 ms, waitGL 10 / 2607 ~6.79 ms
+XXX[385] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27710 ~71.974 ms, finishGL 72 / 24809 ~64.441 ms, waitGL 9 / 2617 ~6.798 ms
+XXX[386] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27793 ~72.002 ms, finishGL 73 / 24882 ~64.463 ms, waitGL 9 / 2626 ~6.805 ms
+XXX[387] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27876 ~72.031 ms, finishGL 73 / 24956 ~64.486 ms, waitGL 9 / 2636 ~6.812 ms
+XXX[388] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27959 ~72.059 ms, finishGL 73 / 25029 ~64.51 ms, waitGL 8 / 2644 ~6.816 ms
+XXX[389] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28042 ~72.088 ms, finishGL 74 / 25104 ~64.535 ms, waitGL 8 / 2653 ~6.82 ms
+XXX[390] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28125 ~72.115 ms, finishGL 75 / 25179 ~64.563 ms, waitGL 6 / 2660 ~6.82 ms
+XXX[391] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28208 ~72.143 ms, finishGL 76 / 25256 ~64.594 ms, waitGL 5 / 2665 ~6.817 ms
+XXX[392] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 28291 ~72.171 ms, finishGL 77 / 25334 ~64.628 ms, waitGL 4 / 2670 ~6.811 ms
+XXX[393] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28374 ~72.199 ms, finishGL 78 / 25412 ~64.662 ms, waitGL 4 / 2674 ~6.805 ms
+XXX[394] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28457 ~72.226 ms, finishGL 78 / 25490 ~64.697 ms, waitGL 4 / 2678 ~6.798 ms
+XXX[395] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28540 ~72.254 ms, finishGL 77 / 25568 ~64.73 ms, waitGL 5 / 2683 ~6.794 ms
+XXX[396] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28623 ~72.282 ms, finishGL 77 / 25646 ~64.763 ms, waitGL 4 / 2688 ~6.789 ms
+XXX[397] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28707 ~72.309 ms, finishGL 77 / 25724 ~64.795 ms, waitGL 4 / 2693 ~6.785 ms
+XXX[398] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28790 ~72.337 ms, finishGL 77 / 25801 ~64.828 ms, waitGL 5 / 2698 ~6.781 ms
+XXX[399] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28873 ~72.364 ms, finishGL 77 / 25879 ~64.86 ms, waitGL 4 / 2703 ~6.776 ms
+XXX[400] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28957 ~72.392 ms, finishGL 76 / 25956 ~64.89 ms, waitGL 6 / 2709 ~6.774 ms
+XXX[401] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29039 ~72.418 ms, finishGL 76 / 26032 ~64.919 ms, waitGL 5 / 2715 ~6.771 ms
+XXX[402] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29123 ~72.445 ms, finishGL 75 / 26108 ~64.945 ms, waitGL 7 / 2722 ~6.772 ms
+XXX[403] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29206 ~72.472 ms, finishGL 74 / 26182 ~64.969 ms, waitGL 8 / 2730 ~6.776 ms
+XXX[404] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29289 ~72.498 ms, finishGL 73 / 26256 ~64.99 ms, waitGL 9 / 2740 ~6.782 ms
+XXX[405] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29372 ~72.524 ms, finishGL 73 / 26329 ~65.012 ms, waitGL 8 / 2748 ~6.786 ms
+XXX[406] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29455 ~72.551 ms, finishGL 72 / 26402 ~65.03 ms, waitGL 10 / 2758 ~6.794 ms
+XXX[407] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29538 ~72.575 ms, finishGL 72 / 26475 ~65.049 ms, waitGL 9 / 2768 ~6.801 ms
+XXX[408] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29621 ~72.602 ms, finishGL 72 / 26547 ~65.067 ms, waitGL 11 / 2779 ~6.811 ms
+XXX[409] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29705 ~72.628 ms, finishGL 71 / 26619 ~65.083 ms, waitGL 10 / 2789 ~6.821 ms
+XXX[410] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 29787 ~72.651 ms, finishGL 71 / 26691 ~65.1 ms, waitGL 8 / 2798 ~6.826 ms
+XXX[411] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 29870 ~72.677 ms, finishGL 72 / 26763 ~65.117 ms, waitGL 10 / 2808 ~6.834 ms
+XXX[412] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 29953 ~72.702 ms, finishGL 71 / 26834 ~65.133 ms, waitGL 10 / 2819 ~6.842 ms
+XXX[413] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30036 ~72.728 ms, finishGL 72 / 26907 ~65.15 ms, waitGL 10 / 2829 ~6.851 ms
+XXX[414] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30119 ~72.753 ms, finishGL 71 / 26978 ~65.165 ms, waitGL 10 / 2840 ~6.86 ms
+XXX[415] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30203 ~72.778 ms, finishGL 70 / 27049 ~65.179 ms, waitGL 11 / 2851 ~6.87 ms
+XXX[416] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30286 ~72.803 ms, finishGL 71 / 27120 ~65.193 ms, waitGL 10 / 2862 ~6.88 ms
+XXX[417] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30369 ~72.828 ms, finishGL 70 / 27190 ~65.205 ms, waitGL 11 / 2874 ~6.892 ms
+XXX[418] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30452 ~72.853 ms, finishGL 69 / 27260 ~65.216 ms, waitGL 12 / 2886 ~6.905 ms
+XXX[419] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30535 ~72.877 ms, finishGL 69 / 27329 ~65.226 ms, waitGL 12 / 2898 ~6.918 ms
+XXX[420] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30619 ~72.902 ms, finishGL 70 / 27400 ~65.239 ms, waitGL 11 / 2910 ~6.93 ms
+XXX[421] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 30702 ~72.926 ms, finishGL 70 / 27470 ~65.251 ms, waitGL 11 / 2922 ~6.941 ms
+XXX[422] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30785 ~72.95 ms, finishGL 71 / 27542 ~65.266 ms, waitGL 10 / 2932 ~6.949 ms
+XXX[423] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30868 ~72.974 ms, finishGL 72 / 27614 ~65.283 ms, waitGL 9 / 2942 ~6.955 ms
+XXX[424] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30951 ~72.998 ms, finishGL 71 / 27686 ~65.298 ms, waitGL 10 / 2952 ~6.963 ms
+XXX[425] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 31034 ~73.023 ms, finishGL 68 / 27755 ~65.307 ms, waitGL 13 / 2965 ~6.978 ms
+XXX[426] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 31117 ~73.046 ms, finishGL 65 / 27820 ~65.307 ms, waitGL 16 / 2982 ~7.0 ms
+XXX[427] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31184 ~73.031 ms, finishGL 62 / 27883 ~65.3 ms, waitGL 3 / 2985 ~6.991 ms
+XXX[428] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31250 ~73.016 ms, finishGL 60 / 27944 ~65.289 ms, waitGL 4 / 2990 ~6.986 ms
+XXX[429] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31317 ~73.0 ms, finishGL 59 / 28003 ~65.277 ms, waitGL 5 / 2995 ~6.982 ms
+XXX[430] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31383 ~72.985 ms, finishGL 59 / 28063 ~65.263 ms, waitGL 6 / 3001 ~6.98 ms
+XXX[431] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31450 ~72.97 ms, finishGL 58 / 28121 ~65.248 ms, waitGL 6 / 3008 ~6.979 ms
+XXX[432] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31516 ~72.955 ms, finishGL 58 / 28179 ~65.231 ms, waitGL 7 / 3015 ~6.98 ms
+XXX[433] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31583 ~72.94 ms, finishGL 57 / 28237 ~65.214 ms, waitGL 7 / 3023 ~6.981 ms
+XXX[434] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31649 ~72.926 ms, finishGL 57 / 28295 ~65.197 ms, waitGL 7 / 3030 ~6.983 ms
+XXX[435] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31716 ~72.911 ms, finishGL 56 / 28352 ~65.178 ms, waitGL 8 / 3039 ~6.986 ms
+XXX[436] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31782 ~72.896 ms, finishGL 56 / 28409 ~65.158 ms, waitGL 8 / 3048 ~6.99 ms
+XXX[437] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31849 ~72.882 ms, finishGL 56 / 28465 ~65.137 ms, waitGL 9 / 3057 ~6.996 ms
+XXX[438] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31915 ~72.867 ms, finishGL 55 / 28520 ~65.116 ms, waitGL 9 / 3066 ~7.002 ms
+XXX[439] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31982 ~72.853 ms, finishGL 55 / 28576 ~65.093 ms, waitGL 10 / 3077 ~7.01 ms
+XXX[440] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32047 ~72.836 ms, finishGL 56 / 28632 ~65.073 ms, waitGL 8 / 3086 ~7.014 ms
+XXX[441] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32114 ~72.822 ms, finishGL 56 / 28689 ~65.055 ms, waitGL 8 / 3095 ~7.018 ms
+XXX[442] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32180 ~72.807 ms, finishGL 56 / 28746 ~65.036 ms, waitGL 8 / 3103 ~7.021 ms
+XXX[443] TO 17 ms, lFrame0 1 ms, lFrameX 67 / 32248 ~72.795 ms, finishGL 57 / 28803 ~65.02 ms, waitGL 8 / 3112 ~7.025 ms
+XXX[444] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32313 ~72.779 ms, finishGL 57 / 28861 ~65.002 ms, waitGL 8 / 3120 ~7.027 ms
+XXX[445] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32380 ~72.765 ms, finishGL 58 / 28919 ~64.987 ms, waitGL 7 / 3127 ~7.029 ms
+XXX[446] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32446 ~72.751 ms, finishGL 58 / 28977 ~64.972 ms, waitGL 7 / 3135 ~7.029 ms
+XXX[447] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32513 ~72.737 ms, finishGL 59 / 29036 ~64.959 ms, waitGL 6 / 3141 ~7.027 ms
+XXX[448] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32579 ~72.722 ms, finishGL 58 / 29095 ~64.944 ms, waitGL 6 / 3148 ~7.027 ms
+XXX[449] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32646 ~72.709 ms, finishGL 58 / 29154 ~64.931 ms, waitGL 7 / 3155 ~7.027 ms
+XXX[450] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32712 ~72.695 ms, finishGL 58 / 29212 ~64.917 ms, waitGL 6 / 3161 ~7.026 ms
+XXX[451] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32779 ~72.681 ms, finishGL 58 / 29271 ~64.903 ms, waitGL 6 / 3168 ~7.026 ms
+XXX[452] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32845 ~72.667 ms, finishGL 58 / 29330 ~64.889 ms, waitGL 6 / 3175 ~7.025 ms
+XXX[453] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32912 ~72.654 ms, finishGL 58 / 29388 ~64.876 ms, waitGL 7 / 3182 ~7.026 ms
+XXX[454] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32978 ~72.64 ms, finishGL 57 / 29446 ~64.859 ms, waitGL 8 / 3190 ~7.028 ms
+XXX[455] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33045 ~72.627 ms, finishGL 56 / 29503 ~64.841 ms, waitGL 8 / 3199 ~7.032 ms
+XXX[456] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33111 ~72.613 ms, finishGL 55 / 29558 ~64.821 ms, waitGL 9 / 3209 ~7.037 ms
+XXX[457] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33178 ~72.6 ms, finishGL 55 / 29613 ~64.8 ms, waitGL 10 / 3219 ~7.045 ms
+XXX[458] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33244 ~72.586 ms, finishGL 53 / 29667 ~64.776 ms, waitGL 11 / 3230 ~7.054 ms
+XXX[459] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33311 ~72.573 ms, finishGL 53 / 29721 ~64.751 ms, waitGL 12 / 3243 ~7.066 ms
+XXX[460] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33377 ~72.56 ms, finishGL 52 / 29773 ~64.724 ms, waitGL 12 / 3256 ~7.079 ms
+XXX[461] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33444 ~72.547 ms, finishGL 51 / 29824 ~64.695 ms, waitGL 14 / 3270 ~7.094 ms
+XXX[462] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33510 ~72.533 ms, finishGL 50 / 29874 ~64.664 ms, waitGL 14 / 3285 ~7.111 ms
+XXX[463] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33577 ~72.52 ms, finishGL 49 / 29924 ~64.631 ms, waitGL 15 / 3301 ~7.13 ms
+XXX[464] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 33627 ~72.473 ms, finishGL 48 / 29973 ~64.597 ms, waitGL 1 / 3302 ~7.117 ms
+XXX[465] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33693 ~72.46 ms, finishGL 63 / 30036 ~64.595 ms, waitGL 1 / 3304 ~7.105 ms
+XXX[466] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33760 ~72.448 ms, finishGL 63 / 30100 ~64.593 ms, waitGL 2 / 3306 ~7.096 ms
+XXX[467] TO 17 ms, lFrame0 1 ms, lFrameX 48 / 33809 ~72.397 ms, finishGL 46 / 30146 ~64.554 ms, waitGL 1 / 3308 ~7.084 ms
+XXX[468] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 33859 ~72.349 ms, finishGL 45 / 30192 ~64.513 ms, waitGL 3 / 3311 ~7.076 ms
+XXX[469] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 33909 ~72.301 ms, finishGL 44 / 30237 ~64.472 ms, waitGL 3 / 3315 ~7.068 ms
+XXX[470] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 33959 ~72.253 ms, finishGL 44 / 30281 ~64.428 ms, waitGL 4 / 3319 ~7.063 ms
+XXX[471] TO 17 ms, lFrame0 1 ms, lFrameX 48 / 34007 ~72.202 ms, finishGL 43 / 30325 ~64.385 ms, waitGL 2 / 3322 ~7.054 ms
+XXX[472] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 34057 ~72.155 ms, finishGL 42 / 30368 ~64.339 ms, waitGL 6 / 3328 ~7.052 ms
+XXX[473] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34107 ~72.109 ms, finishGL 41 / 30409 ~64.291 ms, waitGL 8 / 3336 ~7.054 ms
+XXX[474] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34157 ~72.061 ms, finishGL 41 / 30451 ~64.243 ms, waitGL 6 / 3343 ~7.054 ms
+XXX[475] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 34206 ~72.014 ms, finishGL 41 / 30492 ~64.194 ms, waitGL 7 / 3351 ~7.055 ms
+XXX[476] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 34256 ~71.967 ms, finishGL 40 / 30532 ~64.144 ms, waitGL 8 / 3359 ~7.057 ms
+XXX[477] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 34307 ~71.922 ms, finishGL 39 / 30572 ~64.093 ms, waitGL 9 / 3369 ~7.063 ms
+XXX[478] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34356 ~71.874 ms, finishGL 38 / 30611 ~64.039 ms, waitGL 10 / 3379 ~7.069 ms
+XXX[479] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34406 ~71.828 ms, finishGL 38 / 30649 ~63.987 ms, waitGL 10 / 3389 ~7.076 ms
+XXX[480] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34455 ~71.782 ms, finishGL 38 / 30688 ~63.933 ms, waitGL 10 / 3400 ~7.084 ms
+XXX[481] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34505 ~71.737 ms, finishGL 37 / 30725 ~63.878 ms, waitGL 11 / 3412 ~7.094 ms
+XXX[482] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34555 ~71.691 ms, finishGL 35 / 30761 ~63.82 ms, waitGL 13 / 3425 ~7.107 ms
+XXX[483] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 34605 ~71.646 ms, finishGL 35 / 30796 ~63.761 ms, waitGL 13 / 3439 ~7.12 ms
+XXX[484] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34655 ~71.601 ms, finishGL 34 / 30831 ~63.701 ms, waitGL 14 / 3453 ~7.135 ms
+XXX[485] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 34704 ~71.556 ms, finishGL 33 / 30864 ~63.638 ms, waitGL 15 / 3468 ~7.151 ms
+XXX[486] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34754 ~71.511 ms, finishGL 33 / 30898 ~63.576 ms, waitGL 16 / 3484 ~7.17 ms
+XXX[487] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34804 ~71.466 ms, finishGL 33 / 30931 ~63.513 ms, waitGL 15 / 3500 ~7.187 ms
+XXX[488] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 34854 ~71.422 ms, finishGL 32 / 30963 ~63.45 ms, waitGL 16 / 3516 ~7.206 ms
+XXX[489] TO 17 ms, lFrame0 1 ms, lFrameX 34 / 34888 ~71.346 ms, finishGL 32 / 30996 ~63.387 ms, waitGL 0 / 3517 ~7.192 ms
+XXX[490] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 34953 ~71.334 ms, finishGL 48 / 31044 ~63.356 ms, waitGL 16 / 3533 ~7.211 ms
+XXX[491] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 34987 ~71.258 ms, finishGL 33 / 31077 ~63.294 ms, waitGL 0 / 3533 ~7.197 ms
+XXX[492] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 35053 ~71.246 ms, finishGL 49 / 31127 ~63.266 ms, waitGL 15 / 3549 ~7.214 ms
+XXX[493] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35104 ~71.204 ms, finishGL 33 / 31160 ~63.205 ms, waitGL 16 / 3566 ~7.234 ms
+XXX[494] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35153 ~71.16 ms, finishGL 32 / 31192 ~63.142 ms, waitGL 15 / 3582 ~7.252 ms
+XXX[495] TO 17 ms, lFrame0 1 ms, lFrameX 33 / 35187 ~71.085 ms, finishGL 32 / 31224 ~63.08 ms, waitGL 0 / 3582 ~7.238 ms
+XXX[496] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 35252 ~71.074 ms, finishGL 50 / 31275 ~63.054 ms, waitGL 14 / 3597 ~7.253 ms
+XXX[497] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35302 ~71.031 ms, finishGL 35 / 31310 ~62.998 ms, waitGL 13 / 3611 ~7.266 ms
+XXX[498] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35352 ~70.988 ms, finishGL 34 / 31344 ~62.941 ms, waitGL 13 / 3625 ~7.279 ms
+XXX[499] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35402 ~70.946 ms, finishGL 35 / 31380 ~62.887 ms, waitGL 13 / 3638 ~7.291 ms
+FrameCount: 600 - FrameRate: 21.0
+XXX[500] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35452 ~70.904 ms, finishGL 37 / 31417 ~62.835 ms, waitGL 11 / 3649 ~7.299 ms
+XXX[501] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35501 ~70.861 ms, finishGL 36 / 31454 ~62.783 ms, waitGL 12 / 3662 ~7.309 ms
+XXX[502] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35551 ~70.82 ms, finishGL 37 / 31492 ~62.733 ms, waitGL 11 / 3673 ~7.317 ms
+XXX[503] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35601 ~70.778 ms, finishGL 37 / 31529 ~62.683 ms, waitGL 11 / 3684 ~7.325 ms
+XXX[504] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35651 ~70.736 ms, finishGL 38 / 31567 ~62.634 ms, waitGL 10 / 3695 ~7.331 ms
+XXX[505] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35701 ~70.695 ms, finishGL 38 / 31606 ~62.586 ms, waitGL 10 / 3705 ~7.338 ms
+XXX[506] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35750 ~70.653 ms, finishGL 38 / 31644 ~62.538 ms, waitGL 10 / 3716 ~7.345 ms
+XXX[507] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35800 ~70.612 ms, finishGL 38 / 31683 ~62.491 ms, waitGL 9 / 3726 ~7.35 ms
+XXX[508] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35850 ~70.571 ms, finishGL 39 / 31722 ~62.445 ms, waitGL 9 / 3736 ~7.354 ms
+XXX[509] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35900 ~70.53 ms, finishGL 40 / 31762 ~62.401 ms, waitGL 8 / 3744 ~7.356 ms
+XXX[510] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35950 ~70.49 ms, finishGL 39 / 31802 ~62.357 ms, waitGL 8 / 3753 ~7.359 ms
+XXX[511] TO 17 ms, lFrame0 2 ms, lFrameX 48 / 35998 ~70.447 ms, finishGL 39 / 31841 ~62.313 ms, waitGL 6 / 3759 ~7.357 ms
+XXX[512] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 36048 ~70.406 ms, finishGL 41 / 31883 ~62.272 ms, waitGL 6 / 3766 ~7.356 ms
+XXX[513] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 36098 ~70.366 ms, finishGL 42 / 31926 ~62.234 ms, waitGL 6 / 3772 ~7.353 ms
+XXX[514] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 36147 ~70.326 ms, finishGL 44 / 31971 ~62.2 ms, waitGL 4 / 3776 ~7.347 ms
+XXX[515] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 36197 ~70.286 ms, finishGL 47 / 32018 ~62.172 ms, waitGL 1 / 3778 ~7.336 ms
+XXX[516] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 36265 ~70.281 ms, finishGL 49 / 32068 ~62.147 ms, waitGL 17 / 3795 ~7.355 ms
+XXX[517] TO 17 ms, lFrame0 1 ms, lFrameX 65 / 36330 ~70.272 ms, finishGL 52 / 32120 ~62.129 ms, waitGL 11 / 3807 ~7.363 ms
+XXX[518] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 36396 ~70.264 ms, finishGL 58 / 32179 ~62.122 ms, waitGL 6 / 3813 ~7.362 ms
+XXX[519] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36480 ~70.289 ms, finishGL 68 / 32248 ~62.135 ms, waitGL 14 / 3827 ~7.375 ms
+XXX[520] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36563 ~70.313 ms, finishGL 76 / 32324 ~62.161 ms, waitGL 6 / 3834 ~7.373 ms
+XXX[521] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36646 ~70.338 ms, finishGL 76 / 32401 ~62.19 ms, waitGL 5 / 3839 ~7.37 ms
+XXX[522] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36729 ~70.363 ms, finishGL 76 / 32477 ~62.217 ms, waitGL 6 / 3846 ~7.368 ms
+XXX[523] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36812 ~70.387 ms, finishGL 76 / 32553 ~62.244 ms, waitGL 6 / 3852 ~7.366 ms
+XXX[524] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 36895 ~70.412 ms, finishGL 76 / 32630 ~62.271 ms, waitGL 5 / 3858 ~7.362 ms
+XXX[525] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 36979 ~70.436 ms, finishGL 76 / 32706 ~62.297 ms, waitGL 5 / 3864 ~7.36 ms
+XXX[526] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37062 ~70.46 ms, finishGL 75 / 32782 ~62.323 ms, waitGL 6 / 3870 ~7.358 ms
+XXX[527] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 37146 ~70.486 ms, finishGL 75 / 32857 ~62.348 ms, waitGL 7 / 3877 ~7.358 ms
+XXX[528] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37228 ~70.508 ms, finishGL 74 / 32932 ~62.372 ms, waitGL 7 / 3884 ~7.357 ms
+XXX[529] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37311 ~70.532 ms, finishGL 75 / 33008 ~62.397 ms, waitGL 6 / 3890 ~7.355 ms
+XXX[530] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37395 ~70.556 ms, finishGL 76 / 33084 ~62.423 ms, waitGL 6 / 3897 ~7.353 ms
+XXX[531] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37478 ~70.58 ms, finishGL 76 / 33160 ~62.449 ms, waitGL 6 / 3903 ~7.351 ms
+XXX[532] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37561 ~70.603 ms, finishGL 76 / 33237 ~62.476 ms, waitGL 5 / 3909 ~7.348 ms
+XXX[533] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37644 ~70.627 ms, finishGL 76 / 33313 ~62.502 ms, waitGL 5 / 3914 ~7.344 ms
+XXX[534] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37727 ~70.651 ms, finishGL 76 / 33390 ~62.528 ms, waitGL 5 / 3920 ~7.341 ms
+XXX[535] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37810 ~70.674 ms, finishGL 76 / 33466 ~62.554 ms, waitGL 5 / 3926 ~7.338 ms
+XXX[536] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37893 ~70.697 ms, finishGL 76 / 33542 ~62.579 ms, waitGL 5 / 3931 ~7.335 ms
+XXX[537] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37977 ~70.721 ms, finishGL 75 / 33618 ~62.604 ms, waitGL 6 / 3938 ~7.333 ms
+XXX[538] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38060 ~70.744 ms, finishGL 75 / 33694 ~62.628 ms, waitGL 6 / 3944 ~7.332 ms
+XXX[539] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38143 ~70.767 ms, finishGL 75 / 33769 ~62.651 ms, waitGL 6 / 3951 ~7.331 ms
+XXX[540] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38226 ~70.79 ms, finishGL 74 / 33843 ~62.673 ms, waitGL 7 / 3958 ~7.331 ms
+XXX[541] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38309 ~70.813 ms, finishGL 74 / 33918 ~62.695 ms, waitGL 7 / 3966 ~7.332 ms
+XXX[542] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38393 ~70.835 ms, finishGL 74 / 33992 ~62.717 ms, waitGL 7 / 3974 ~7.332 ms
+XXX[543] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38476 ~70.858 ms, finishGL 75 / 34067 ~62.74 ms, waitGL 6 / 3981 ~7.331 ms
+XXX[544] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38559 ~70.881 ms, finishGL 74 / 34142 ~62.762 ms, waitGL 7 / 3988 ~7.331 ms
+XXX[545] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38642 ~70.903 ms, finishGL 75 / 34218 ~62.786 ms, waitGL 6 / 3994 ~7.329 ms
+XXX[546] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38725 ~70.926 ms, finishGL 75 / 34294 ~62.809 ms, waitGL 7 / 4001 ~7.329 ms
+XXX[547] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38809 ~70.95 ms, finishGL 75 / 34369 ~62.833 ms, waitGL 7 / 4009 ~7.329 ms
+XXX[548] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38892 ~70.97 ms, finishGL 76 / 34446 ~62.857 ms, waitGL 5 / 4014 ~7.326 ms
+XXX[549] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38975 ~70.993 ms, finishGL 77 / 34523 ~62.884 ms, waitGL 4 / 4019 ~7.321 ms
+XXX[550] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 39058 ~71.015 ms, finishGL 77 / 34601 ~62.912 ms, waitGL 3 / 4023 ~7.315 ms
+XXX[551] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39141 ~71.037 ms, finishGL 78 / 34680 ~62.94 ms, waitGL 4 / 4027 ~7.31 ms
+XXX[552] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 39225 ~71.06 ms, finishGL 79 / 34759 ~62.97 ms, waitGL 4 / 4031 ~7.304 ms
+XXX[553] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39307 ~71.081 ms, finishGL 78 / 34837 ~62.997 ms, waitGL 3 / 4035 ~7.296 ms
+XXX[554] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39391 ~71.103 ms, finishGL 77 / 34915 ~63.024 ms, waitGL 4 / 4040 ~7.292 ms
+XXX[555] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39474 ~71.124 ms, finishGL 77 / 34992 ~63.05 ms, waitGL 5 / 4045 ~7.289 ms
+XXX[556] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 39557 ~71.146 ms, finishGL 76 / 35069 ~63.074 ms, waitGL 5 / 4051 ~7.286 ms
+XXX[557] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39640 ~71.168 ms, finishGL 75 / 35145 ~63.097 ms, waitGL 6 / 4057 ~7.284 ms
+XXX[558] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39724 ~71.19 ms, finishGL 73 / 35219 ~63.116 ms, waitGL 9 / 4066 ~7.287 ms
+XXX[559] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39807 ~71.212 ms, finishGL 73 / 35292 ~63.134 ms, waitGL 9 / 4076 ~7.292 ms
+XXX[560] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39890 ~71.233 ms, finishGL 72 / 35364 ~63.15 ms, waitGL 10 / 4086 ~7.297 ms
+XXX[561] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39974 ~71.255 ms, finishGL 71 / 35435 ~63.164 ms, waitGL 11 / 4098 ~7.305 ms
+XXX[562] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 40057 ~71.276 ms, finishGL 69 / 35504 ~63.175 ms, waitGL 13 / 4112 ~7.316 ms
+XXX[563] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 40140 ~71.297 ms, finishGL 67 / 35572 ~63.183 ms, waitGL 15 / 4127 ~7.33 ms
+XXX[564] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 40223 ~71.318 ms, finishGL 65 / 35637 ~63.187 ms, waitGL 16 / 4144 ~7.347 ms
+XXX[565] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40289 ~71.308 ms, finishGL 64 / 35702 ~63.189 ms, waitGL 0 / 4145 ~7.336 ms
+XXX[566] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 40372 ~71.329 ms, finishGL 78 / 35780 ~63.217 ms, waitGL 3 / 4148 ~7.329 ms
+XXX[567] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40438 ~71.32 ms, finishGL 61 / 35842 ~63.213 ms, waitGL 4 / 4153 ~7.324 ms
+XXX[568] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 40504 ~71.311 ms, finishGL 60 / 35902 ~63.208 ms, waitGL 4 / 4157 ~7.32 ms
+XXX[569] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 40588 ~71.333 ms, finishGL 74 / 35977 ~63.229 ms, waitGL 8 / 4166 ~7.322 ms
+XXX[570] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40654 ~71.323 ms, finishGL 58 / 36035 ~63.22 ms, waitGL 6 / 4173 ~7.321 ms
+XXX[571] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 40720 ~71.315 ms, finishGL 58 / 36094 ~63.212 ms, waitGL 6 / 4179 ~7.319 ms
+XXX[572] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40787 ~71.306 ms, finishGL 58 / 36152 ~63.204 ms, waitGL 7 / 4186 ~7.319 ms
+XXX[573] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 40853 ~71.298 ms, finishGL 57 / 36210 ~63.193 ms, waitGL 8 / 4194 ~7.32 ms
+XXX[574] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 40920 ~71.289 ms, finishGL 57 / 36267 ~63.184 ms, waitGL 7 / 4202 ~7.321 ms
+XXX[575] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 40986 ~71.281 ms, finishGL 57 / 36325 ~63.174 ms, waitGL 8 / 4210 ~7.322 ms
+XXX[576] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 41053 ~71.273 ms, finishGL 57 / 36382 ~63.164 ms, waitGL 8 / 4218 ~7.324 ms
+XXX[577] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 41120 ~71.265 ms, finishGL 57 / 36440 ~63.154 ms, waitGL 8 / 4227 ~7.325 ms
+XXX[578] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 41186 ~71.256 ms, finishGL 61 / 36501 ~63.151 ms, waitGL 3 / 4231 ~7.32 ms
+XXX[579] TO 17 ms, lFrame0 1 ms, lFrameX 67 / 41253 ~71.25 ms, finishGL 64 / 36565 ~63.153 ms, waitGL 1 / 4232 ~7.31 ms
+XXX[580] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 41352 ~71.298 ms, finishGL 86 / 36652 ~63.194 ms, waitGL 11 / 4244 ~7.318 ms
+XXX[581] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 41436 ~71.318 ms, finishGL 75 / 36728 ~63.215 ms, waitGL 6 / 4251 ~7.317 ms
+XXX[582] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 41519 ~71.338 ms, finishGL 78 / 36807 ~63.242 ms, waitGL 4 / 4255 ~7.311 ms
+XXX[583] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 41602 ~71.359 ms, finishGL 79 / 36886 ~63.269 ms, waitGL 2 / 4258 ~7.303 ms
+XXX[584] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 41685 ~71.379 ms, finishGL 79 / 36965 ~63.297 ms, waitGL 2 / 4260 ~7.296 ms
+XXX[585] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 41768 ~71.399 ms, finishGL 76 / 37042 ~63.319 ms, waitGL 5 / 4266 ~7.293 ms
+XXX[586] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 41851 ~71.419 ms, finishGL 75 / 37117 ~63.339 ms, waitGL 6 / 4273 ~7.293 ms
+XXX[587] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 41935 ~71.441 ms, finishGL 74 / 37191 ~63.359 ms, waitGL 8 / 4282 ~7.294 ms
+XXX[588] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 42019 ~71.461 ms, finishGL 74 / 37266 ~63.379 ms, waitGL 5 / 4287 ~7.292 ms
+XXX[589] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42101 ~71.479 ms, finishGL 73 / 37340 ~63.396 ms, waitGL 8 / 4296 ~7.294 ms
+XXX[590] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42184 ~71.499 ms, finishGL 73 / 37414 ~63.414 ms, waitGL 8 / 4304 ~7.296 ms
+XXX[591] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42267 ~71.519 ms, finishGL 73 / 37487 ~63.431 ms, waitGL 9 / 4313 ~7.299 ms
+XXX[592] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42351 ~71.538 ms, finishGL 73 / 37561 ~63.448 ms, waitGL 8 / 4322 ~7.301 ms
+XXX[593] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42434 ~71.558 ms, finishGL 73 / 37635 ~63.465 ms, waitGL 8 / 4330 ~7.302 ms
+XXX[594] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42517 ~71.578 ms, finishGL 73 / 37709 ~63.483 ms, waitGL 8 / 4338 ~7.303 ms
+XXX[595] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42600 ~71.597 ms, finishGL 74 / 37784 ~63.502 ms, waitGL 7 / 4345 ~7.303 ms
+XXX[596] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42683 ~71.616 ms, finishGL 75 / 37859 ~63.522 ms, waitGL 6 / 4352 ~7.302 ms
+XXX[597] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42766 ~71.636 ms, finishGL 76 / 37935 ~63.544 ms, waitGL 5 / 4358 ~7.3 ms
+XXX[598] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42850 ~71.655 ms, finishGL 76 / 38012 ~63.566 ms, waitGL 5 / 4363 ~7.297 ms
+XXX[599] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42933 ~71.674 ms, finishGL 77 / 38090 ~63.589 ms, waitGL 5 / 4369 ~7.294 ms
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java
new file mode 100644
index 000000000..c463ede2a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java
@@ -0,0 +1,430 @@
+package com.jogamp.opengl.test.bugs;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.nio.FloatBuffer;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.glu.GLU;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+/**
+ * Original test case.
+ * <br/>
+ * OSX Results:
+ * <pre>
+ * - Visible content
+ * - Fluent animation
+ * </pre>
+ */
+@SuppressWarnings("serial")
+public class Bug735Inv0AppletAWT extends Applet implements Runnable {
+ static public final int AWT = 0;
+ static public final int NEWT = 1;
+
+ static public final int APPLET_WIDTH = 500;
+ static public final int APPLET_HEIGHT = 290;
+ static public final int TARGET_FPS = 120;
+ static public final int TOOLKIT = NEWT;
+ static public final boolean MANUAL_FRAME_HANDLING = true;
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ static private Frame frame;
+ static private Bug735Inv0AppletAWT applet;
+ private GLCanvas awtCanvas;
+ private GLWindow newtWindow;
+ private NewtCanvasAWT newtCanvas;
+ private DrawRunnable drawRunnable;
+ private GLContext context;
+ private GLU glu;
+
+ private int width;
+ private int height;
+ private Thread thread;
+
+ private boolean doneInit = false;
+ private boolean doneSetup = false;
+
+ private final long frameRatePeriod = 1000000000L / TARGET_FPS;
+ private long millisOffset;
+ private int frameCount;
+ private float frameRate;
+
+ private ShaderCode vertShader;
+ private ShaderCode fragShader;
+ private ShaderProgram shaderProg;
+ private ShaderState shaderState;
+ private GLUniformData resolution;
+ private GLUniformData time;
+ private GLArrayDataServer vertices;
+
+ private int fcount = 0, lastm = 0;
+ private final int fint = 1;
+
+ public void init() {
+ setSize(APPLET_WIDTH, APPLET_HEIGHT);
+ setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT));
+ width = APPLET_WIDTH;
+ height = APPLET_HEIGHT;
+ }
+
+ public void start() {
+ thread = new Thread(this, "Animation Thread");
+ thread.start();
+ }
+
+ public void run() {
+ int noDelays = 0;
+ // Number of frames with a delay of 0 ms before the
+ // animation thread yields to other running threads.
+ final int NO_DELAYS_PER_YIELD = 15;
+ final int TIMEOUT_SECONDS = 2;
+
+ long beforeTime = System.nanoTime();
+ long overSleepTime = 0L;
+
+ millisOffset = System.currentTimeMillis();
+ frameCount = 1;
+ while (Thread.currentThread() == thread) {
+ final CountDownLatch latch = new CountDownLatch(1);
+ requestDraw(latch);
+ try {
+ latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ if (frameCount == 1) {
+ EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ requestFocusInWindow();
+ }
+ });
+ }
+
+ final long afterTime = System.nanoTime();
+ final long timeDiff = afterTime - beforeTime;
+ final long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime;
+ if (sleepTime > 0) { // some time left in this cycle
+ try {
+ Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L));
+ noDelays = 0; // Got some sleep, not delaying anymore
+ } catch (final InterruptedException ex) { }
+ overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
+ } else { // sleepTime <= 0; the frame took longer than the period
+ overSleepTime = 0L;
+ noDelays++;
+ if (noDelays > NO_DELAYS_PER_YIELD) {
+ Thread.yield(); // give another thread a chance to run
+ noDelays = 0;
+ }
+ }
+ beforeTime = System.nanoTime();
+ }
+ }
+
+ public void requestDraw(final CountDownLatch latch) {
+ if (!doneInit) {
+ initDraw();
+ }
+
+ if (TOOLKIT == AWT) {
+ awtCanvas.invoke(true, drawRunnable);
+ } else if (TOOLKIT == NEWT) {
+ newtWindow.invoke(true, drawRunnable);
+ }
+
+ if (latch != null) {
+ latch.countDown();
+ }
+ }
+
+ private class DrawRunnable implements GLRunnable {
+ private boolean notCurrent;
+
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ if (MANUAL_FRAME_HANDLING) {
+ makeContextCurrent();
+ }
+
+ if (doneSetup) {
+ draw(drawable.getGL().getGL2ES2());
+ } else {
+ setup(drawable.getGL().getGL2ES2());
+ }
+ checkGLErrors(drawable.getGL());
+
+ if (MANUAL_FRAME_HANDLING) {
+ swapBuffers();
+ releaseCurrentContext();
+ }
+
+ return true;
+ }
+
+ private void makeContextCurrent() {
+ final int MAX_CONTEXT_GRAB_ATTEMPTS = 10;
+
+ if (context.isCurrent()) {
+ notCurrent = false;
+ } else {
+ notCurrent = true;
+ int value = GLContext.CONTEXT_NOT_CURRENT;
+ int attempt = 0;
+ do {
+ try {
+ value = context.makeCurrent();
+ System.out.println("Made context current");
+ } catch (final GLException gle) {
+ gle.printStackTrace();
+ } finally {
+ attempt++;
+ if (attempt == MAX_CONTEXT_GRAB_ATTEMPTS) {
+ throw new RuntimeException("Failed to claim OpenGL context.");
+ }
+ }
+ try {
+ Thread.sleep(5);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ } while (value == GLContext.CONTEXT_NOT_CURRENT);
+ }
+ }
+
+ private void swapBuffers() {
+ final GL gl = GLContext.getCurrentGL();
+ gl.glFlush();
+ GLContext.getCurrent().getGLDrawable().swapBuffers();
+ }
+
+ private void releaseCurrentContext() {
+ if (notCurrent) {
+ try {
+ context.release();
+ System.out.println("Released context");
+ } catch (final GLException gle) {
+ gle.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private void initGL() {
+ final GLProfile profile = GLProfile.getDefault();
+ final GLCapabilities caps = new GLCapabilities(profile);
+ caps.setBackgroundOpaque(true);
+ caps.setOnscreen(true);
+ caps.setSampleBuffers(false);
+
+ if (TOOLKIT == AWT) {
+ awtCanvas = new GLCanvas(caps);
+ awtCanvas.setBounds(0, 0, applet.width, applet.height);
+ awtCanvas.setBackground(new Color(0xFFCCCCCC, true));
+ awtCanvas.setFocusable(true);
+
+ applet.setLayout(new BorderLayout());
+ applet.add(awtCanvas, BorderLayout.CENTER);
+
+ if (MANUAL_FRAME_HANDLING) {
+ awtCanvas.setIgnoreRepaint(true);
+ awtCanvas.setAutoSwapBufferMode(false);
+ }
+ } else if (TOOLKIT == NEWT) {
+ newtWindow = GLWindow.create(caps);
+ newtCanvas = new NewtCanvasAWT(newtWindow);
+ newtCanvas.setBounds(0, 0, applet.width, applet.height);
+ newtCanvas.setBackground(new Color(0xFFCCCCCC, true));
+ newtCanvas.setFocusable(true);
+
+ applet.setLayout(new BorderLayout());
+ applet.add(newtCanvas, BorderLayout.CENTER);
+
+ if (MANUAL_FRAME_HANDLING) {
+ newtCanvas.setIgnoreRepaint(true);
+ newtWindow.setAutoSwapBufferMode(false);
+ }
+ }
+ }
+
+ private void initDraw() {
+ if (TOOLKIT == AWT) {
+ awtCanvas.setVisible(true);
+ // Force the realization
+ awtCanvas.display();
+ if (awtCanvas.getDelegatedDrawable().isRealized()) {
+ // Request the focus here as it cannot work when the window is not visible
+ awtCanvas.requestFocus();
+ context = awtCanvas.getContext();
+ }
+ } else if (TOOLKIT == NEWT) {
+ newtCanvas.setVisible(true);
+ // Force the realization
+ newtWindow.display();
+ if (newtWindow.isRealized()) {
+ // Request the focus here as it cannot work when the window is not visible
+ newtCanvas.requestFocus();
+ context = newtWindow.getContext();
+ }
+ }
+
+ drawRunnable = new DrawRunnable();
+
+ doneInit = true;
+ }
+
+ private void setup(final GL2ES2 gl) {
+ if (60 < TARGET_FPS) {
+ // Disables vsync
+ gl.setSwapInterval(0);
+ }
+ glu = new GLU();
+
+ vertShader = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true);
+ fragShader = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true);
+ vertShader.defaultShaderCustomization(gl, true, true);
+ fragShader.defaultShaderCustomization(gl, true, true);
+ shaderProg = new ShaderProgram();
+ shaderProg.add(gl, vertShader, System.err);
+ shaderProg.add(gl, fragShader, System.err);
+
+ shaderState = new ShaderState();
+ shaderState.attachShaderProgram(gl, shaderProg, true);
+
+ resolution = new GLUniformData("iResolution", 3, FloatBuffer.wrap(new float[] {width, height, 0}));
+ shaderState.ownUniform(resolution);
+ shaderState.uniform(gl, resolution);
+
+ time = new GLUniformData("iGlobalTime", 0.0f);
+ shaderState.ownUniform(time);
+
+ vertices = GLArrayDataServer.createGLSL("inVertex", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ vertices.putf(-1.0f); vertices.putf(-1.0f);
+ vertices.putf(+1.0f); vertices.putf(-1.0f);
+ vertices.putf(-1.0f); vertices.putf(+1.0f);
+ vertices.putf(+1.0f); vertices.putf(+1.0f);
+ vertices.seal(gl, true);
+ shaderState.ownAttribute(vertices, true);
+ shaderState.useProgram(gl, false);
+
+ doneSetup = true;
+ }
+
+ private void draw(final GL2ES2 gl) {
+ // gl.glClearColor(0.5f, 0.1f, 0.1f, 1);
+ // gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT);
+
+ shaderState.useProgram(gl, true);
+
+ time.setData((System.currentTimeMillis() - millisOffset) / 1000.0f);
+ shaderState.uniform(gl, time);
+ vertices.enableBuffer(gl, true);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ vertices.enableBuffer(gl, false);
+
+ shaderState.useProgram(gl, false);
+
+ // Compute current framerate and printout.
+ frameCount++;
+ fcount += 1;
+ final int m = (int) (System.currentTimeMillis() - millisOffset);
+ if (m - lastm > 1000 * fint) {
+ frameRate = (float)(fcount) / fint;
+ fcount = 0;
+ lastm = m;
+ }
+ if (frameCount % TARGET_FPS == 0) {
+ System.out.println("FrameCount: " + frameCount + " - " +
+ "FrameRate: " + frameRate);
+ }
+ }
+
+ private void checkGLErrors(final GL gl) {
+ final int err = gl.glGetError();
+ if (err != 0) {
+ final String errString = glu.gluErrorString(err);
+ System.out.println(errString);
+ }
+ }
+
+ static public void main(final String[] args) {
+ final GraphicsEnvironment environment =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ final GraphicsDevice displayDevice = environment.getDefaultScreenDevice();
+
+ frame = new Frame(displayDevice.getDefaultConfiguration());
+ frame.setBackground(new Color(0xCC, 0xCC, 0xCC));
+ frame.setTitle("TestBug735Inv0AppletAWT");
+
+ try {
+ final Class<?> c = Thread.currentThread().getContextClassLoader().
+ loadClass(Bug735Inv0AppletAWT.class.getName());
+ applet = (Bug735Inv0AppletAWT) c.newInstance();
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ frame.setLayout(null);
+ frame.add(applet);
+ frame.pack();
+ frame.setResizable(false);
+
+ applet.init();
+
+ final Insets insets = frame.getInsets();
+ final int windowW = applet.width + insets.left + insets.right;
+ final int windowH = applet.height + insets.top + insets.bottom;
+ frame.setSize(windowW, windowH);
+
+ final Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds();
+ frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2,
+ screenRect.y + (screenRect.height - applet.height) / 2);
+
+ final int usableWindowH = windowH - insets.top - insets.bottom;
+ applet.setBounds((windowW - applet.width)/2,
+ insets.top + (usableWindowH - applet.height)/2,
+ applet.width, applet.height);
+
+ // This allows to close the frame.
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ applet.initGL();
+ frame.setVisible(true);
+ applet.start();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java
new file mode 100644
index 000000000..580f3caea
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java
@@ -0,0 +1,429 @@
+package com.jogamp.opengl.test.bugs;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.nio.FloatBuffer;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.glu.GLU;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+/**
+ * Difference to orig. Bug735Inv0AppletAWT:
+ * <pre>
+ * - MANUAL_FRAME_HANDLING: impl using pass through GLContext instead of static
+ * </pre>
+ * OSX Results:
+ * <pre>
+ * - Visible content
+ * - Fluent animation
+ * </pre>
+ */
+@SuppressWarnings("serial")
+public class Bug735Inv1AppletAWT extends Applet implements Runnable {
+ static public final int AWT = 0;
+ static public final int NEWT = 1;
+
+ static public final int APPLET_WIDTH = 500;
+ static public final int APPLET_HEIGHT = 290;
+ static public final int TARGET_FPS = 120;
+ static public final int TOOLKIT = NEWT;
+ static public final boolean MANUAL_FRAME_HANDLING = true;
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ static private Frame frame;
+ static private Bug735Inv1AppletAWT applet;
+ private GLCanvas awtCanvas;
+ private GLWindow newtWindow;
+ private NewtCanvasAWT newtCanvas;
+ private DrawRunnable drawRunnable;
+ // JAU private GLContext context;
+ private GLU glu;
+
+ private int width;
+ private int height;
+ private Thread thread;
+
+ private boolean doneInit = false;
+ private boolean doneSetup = false;
+
+ private final long frameRatePeriod = 1000000000L / TARGET_FPS;
+ private long millisOffset;
+ private int frameCount;
+ private float frameRate;
+
+ private ShaderCode vertShader;
+ private ShaderCode fragShader;
+ private ShaderProgram shaderProg;
+ private ShaderState shaderState;
+ private GLUniformData resolution;
+ private GLUniformData time;
+ private GLArrayDataServer vertices;
+
+ private int fcount = 0, lastm = 0;
+ private final int fint = 1;
+
+ public void init() {
+ setSize(APPLET_WIDTH, APPLET_HEIGHT);
+ setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT));
+ width = APPLET_WIDTH;
+ height = APPLET_HEIGHT;
+ }
+
+ public void start() {
+ thread = new Thread(this, "Animation Thread");
+ thread.start();
+ }
+
+ public void run() {
+ int noDelays = 0;
+ // Number of frames with a delay of 0 ms before the
+ // animation thread yields to other running threads.
+ final int NO_DELAYS_PER_YIELD = 15;
+ final int TIMEOUT_SECONDS = 2;
+
+ long beforeTime = System.nanoTime();
+ long overSleepTime = 0L;
+
+ millisOffset = System.currentTimeMillis();
+ frameCount = 1;
+ while (Thread.currentThread() == thread) {
+ final CountDownLatch latch = new CountDownLatch(1);
+ requestDraw(latch);
+ try {
+ latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ if (frameCount == 1) {
+ EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ requestFocusInWindow();
+ }
+ });
+ }
+
+ final long afterTime = System.nanoTime();
+ final long timeDiff = afterTime - beforeTime;
+ final long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime;
+ if (sleepTime > 0) { // some time left in this cycle
+ try {
+ Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L));
+ noDelays = 0; // Got some sleep, not delaying anymore
+ } catch (final InterruptedException ex) { }
+ overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
+ } else { // sleepTime <= 0; the frame took longer than the period
+ overSleepTime = 0L;
+ noDelays++;
+ if (noDelays > NO_DELAYS_PER_YIELD) {
+ Thread.yield(); // give another thread a chance to run
+ noDelays = 0;
+ }
+ }
+ beforeTime = System.nanoTime();
+ }
+ }
+
+ public void requestDraw(final CountDownLatch latch) {
+ if (!doneInit) {
+ initDraw();
+ }
+
+ if (TOOLKIT == AWT) {
+ awtCanvas.invoke(true, drawRunnable);
+ } else if (TOOLKIT == NEWT) {
+ newtWindow.invoke(true, drawRunnable);
+ }
+
+ if (latch != null) {
+ latch.countDown();
+ }
+ }
+
+ private class DrawRunnable implements GLRunnable {
+ private boolean notCurrent;
+
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ if (MANUAL_FRAME_HANDLING) {
+ makeContextCurrent(drawable.getContext());
+ }
+
+ if (!doneSetup) {
+ setup(drawable.getGL().getGL2ES2());
+ }
+ draw(drawable.getGL().getGL2ES2());
+ checkGLErrors(drawable.getGL());
+
+ if (MANUAL_FRAME_HANDLING) {
+ swapBuffers(drawable.getContext());
+ releaseCurrentContext(drawable.getContext());
+ }
+
+ return true;
+ }
+
+ private void makeContextCurrent(final GLContext context) {
+ final int MAX_CONTEXT_GRAB_ATTEMPTS = 10;
+
+ if (context.isCurrent()) {
+ notCurrent = false;
+ } else {
+ notCurrent = true;
+ int value = GLContext.CONTEXT_NOT_CURRENT;
+ int attempt = 0;
+ do {
+ try {
+ value = context.makeCurrent();
+ System.out.println("Made context current");
+ } catch (final GLException gle) {
+ gle.printStackTrace();
+ } finally {
+ attempt++;
+ if (attempt == MAX_CONTEXT_GRAB_ATTEMPTS) {
+ throw new RuntimeException("Failed to claim OpenGL context.");
+ }
+ }
+ try {
+ Thread.sleep(5);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ } while (value == GLContext.CONTEXT_NOT_CURRENT);
+ }
+ }
+
+ private void swapBuffers(final GLContext context) {
+ final GL gl = context.getGL();
+ gl.glFlush();
+ context.getGLDrawable().swapBuffers();
+ }
+
+ private void releaseCurrentContext(final GLContext context) {
+ if (notCurrent) {
+ try {
+ context.release();
+ System.out.println("Released context");
+ } catch (final GLException gle) {
+ gle.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private void initGL() {
+ final GLProfile profile = GLProfile.getDefault();
+ final GLCapabilities caps = new GLCapabilities(profile);
+ caps.setBackgroundOpaque(true);
+ caps.setOnscreen(true);
+ caps.setSampleBuffers(false);
+
+ if (TOOLKIT == AWT) {
+ awtCanvas = new GLCanvas(caps);
+ awtCanvas.setBounds(0, 0, applet.width, applet.height);
+ awtCanvas.setBackground(new Color(0xFFCCCCCC, true));
+ awtCanvas.setFocusable(true);
+
+ applet.setLayout(new BorderLayout());
+ applet.add(awtCanvas, BorderLayout.CENTER);
+
+ if (MANUAL_FRAME_HANDLING) {
+ awtCanvas.setIgnoreRepaint(true);
+ awtCanvas.setAutoSwapBufferMode(false);
+ }
+ } else if (TOOLKIT == NEWT) {
+ newtWindow = GLWindow.create(caps);
+ newtCanvas = new NewtCanvasAWT(newtWindow);
+ newtCanvas.setBounds(0, 0, applet.width, applet.height);
+ newtCanvas.setBackground(new Color(0xFFCCCCCC, true));
+ newtCanvas.setFocusable(true);
+
+ applet.setLayout(new BorderLayout());
+ applet.add(newtCanvas, BorderLayout.CENTER);
+
+ if (MANUAL_FRAME_HANDLING) {
+ newtCanvas.setIgnoreRepaint(true);
+ newtWindow.setAutoSwapBufferMode(false);
+ }
+ }
+ }
+
+ private void initDraw() {
+ if (TOOLKIT == AWT) {
+ awtCanvas.setVisible(true);
+ // Force the realization
+ awtCanvas.display();
+ if (awtCanvas.getDelegatedDrawable().isRealized()) {
+ // Request the focus here as it cannot work when the window is not visible
+ awtCanvas.requestFocus();
+ }
+ } else if (TOOLKIT == NEWT) {
+ newtCanvas.setVisible(true);
+ // Force the realization
+ newtWindow.display();
+ if (newtWindow.isRealized()) {
+ // Request the focus here as it cannot work when the window is not visible
+ newtCanvas.requestFocus();
+ }
+ }
+
+ drawRunnable = new DrawRunnable();
+
+ doneInit = true;
+ }
+
+ private void setup(final GL2ES2 gl) {
+ if (60 < TARGET_FPS) {
+ // Disables vsync
+ gl.setSwapInterval(0);
+ }
+ glu = new GLU();
+
+ vertShader = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true);
+ fragShader = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true);
+ vertShader.defaultShaderCustomization(gl, true, true);
+ fragShader.defaultShaderCustomization(gl, true, true);
+ shaderProg = new ShaderProgram();
+ shaderProg.add(gl, vertShader, System.err);
+ shaderProg.add(gl, fragShader, System.err);
+
+ shaderState = new ShaderState();
+ shaderState.attachShaderProgram(gl, shaderProg, true);
+
+ resolution = new GLUniformData("iResolution", 3, FloatBuffer.wrap(new float[] {width, height, 0}));
+ shaderState.ownUniform(resolution);
+ shaderState.uniform(gl, resolution);
+
+ time = new GLUniformData("iGlobalTime", 0.0f);
+ shaderState.ownUniform(time);
+
+ vertices = GLArrayDataServer.createGLSL("inVertex", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ vertices.putf(-1.0f); vertices.putf(-1.0f);
+ vertices.putf(+1.0f); vertices.putf(-1.0f);
+ vertices.putf(-1.0f); vertices.putf(+1.0f);
+ vertices.putf(+1.0f); vertices.putf(+1.0f);
+ vertices.seal(gl, true);
+ shaderState.ownAttribute(vertices, true);
+ shaderState.useProgram(gl, false);
+
+ doneSetup = true;
+ }
+
+ private void draw(final GL2ES2 gl) {
+ // gl.glClearColor(0.5f, 0.1f, 0.1f, 1);
+ // gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT);
+
+ shaderState.useProgram(gl, true);
+
+ time.setData((System.currentTimeMillis() - millisOffset) / 1000.0f);
+ shaderState.uniform(gl, time);
+ vertices.enableBuffer(gl, true);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ vertices.enableBuffer(gl, false);
+
+ shaderState.useProgram(gl, false);
+
+ // Compute current framerate and printout.
+ frameCount++;
+ fcount += 1;
+ final int m = (int) (System.currentTimeMillis() - millisOffset);
+ if (m - lastm > 1000 * fint) {
+ frameRate = (float)(fcount) / fint;
+ fcount = 0;
+ lastm = m;
+ }
+ if (frameCount % TARGET_FPS == 0) {
+ System.out.println("FrameCount: " + frameCount + " - " +
+ "FrameRate: " + frameRate);
+ }
+ }
+
+ private void checkGLErrors(final GL gl) {
+ final int err = gl.glGetError();
+ if (err != 0) {
+ final String errString = glu.gluErrorString(err);
+ System.out.println(errString);
+ }
+ }
+
+ static public void main(final String[] args) {
+ final GraphicsEnvironment environment =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ final GraphicsDevice displayDevice = environment.getDefaultScreenDevice();
+
+ frame = new Frame(displayDevice.getDefaultConfiguration());
+ frame.setBackground(new Color(0xCC, 0xCC, 0xCC));
+ frame.setTitle("TestBug735Inv1AppletAWT");
+
+ try {
+ final Class<?> c = Thread.currentThread().getContextClassLoader().
+ loadClass(Bug735Inv1AppletAWT.class.getName());
+ applet = (Bug735Inv1AppletAWT) c.newInstance();
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ frame.setLayout(null);
+ frame.add(applet);
+ frame.pack();
+ frame.setResizable(false);
+
+ applet.init();
+
+ final Insets insets = frame.getInsets();
+ final int windowW = applet.width + insets.left + insets.right;
+ final int windowH = applet.height + insets.top + insets.bottom;
+ frame.setSize(windowW, windowH);
+
+ final Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds();
+ frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2,
+ screenRect.y + (screenRect.height - applet.height) / 2);
+
+ final int usableWindowH = windowH - insets.top - insets.bottom;
+ applet.setBounds((windowW - applet.width)/2,
+ insets.top + (usableWindowH - applet.height)/2,
+ applet.width, applet.height);
+
+ // This allows to close the frame.
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ applet.initGL();
+ frame.setVisible(true);
+ applet.start();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java
new file mode 100644
index 000000000..1128c7680
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java
@@ -0,0 +1,272 @@
+package com.jogamp.opengl.test.bugs;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Difference to orig. Bug735Inv0AppletAWT:
+ * <pre>
+ * - Use GLEventListener
+ * - Add GLEventListener to GLAutoDrawable
+ * - Use GLAutoDrawable.display() instead of GLAutoDrawable.invoke(true, GLRunnable { init / render })
+ * - Removed MANUAL_FRAME_HANDLING, obsolete due to GLAutoDrawable/GLEventListener
+ * </pre>
+ * OSX Results:
+ * <pre>
+ * - Visible content
+ * - Fluent animation
+ * </pre>
+ */
+@SuppressWarnings("serial")
+public class Bug735Inv2AppletAWT extends Applet implements Runnable {
+ static public final int AWT = 0;
+ static public final int NEWT = 1;
+
+ static public final int APPLET_WIDTH = 500;
+ static public final int APPLET_HEIGHT = 290;
+ static public final int TARGET_FPS = 120;
+ static public final int TOOLKIT = NEWT;
+ static public final boolean IGNORE_AWT_REPAINT = false;
+ static public boolean USE_ECT = false;
+ static public int SWAP_INTERVAL = 1;
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ static boolean waitForKey = false;
+ static private Frame frame;
+ static private Bug735Inv2AppletAWT applet;
+ private GLCanvas awtCanvas;
+ private GLWindow newtWindow;
+ private GLAutoDrawable glad;
+ private NewtCanvasAWT newtCanvas;
+ private GLEventListener demo;
+
+ private int width;
+ private int height;
+ private Thread thread;
+
+ private final long frameRatePeriod = 1000000000L / TARGET_FPS;
+ private int frameCount;
+
+ public void init() {
+ setSize(APPLET_WIDTH, APPLET_HEIGHT);
+ setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT));
+ width = APPLET_WIDTH;
+ height = APPLET_HEIGHT;
+ initGL();
+ }
+
+ public void start() {
+ initDraw();
+ thread = new Thread(this, "Animation Thread");
+ thread.start();
+ }
+
+ public void run() {
+ int noDelays = 0;
+ // Number of frames with a delay of 0 ms before the
+ // animation thread yields to other running threads.
+ final int NO_DELAYS_PER_YIELD = 15;
+ final int TIMEOUT_SECONDS = 2;
+
+ long beforeTime = System.nanoTime();
+ long overSleepTime = 0L;
+
+ frameCount = 1;
+ while (Thread.currentThread() == thread) {
+ if (frameCount == 1) {
+ EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ requestFocusInWindow();
+ }
+ });
+ if( USE_ECT ) {
+ glad.setExclusiveContextThread(thread);
+ }
+ }
+ final CountDownLatch latch = new CountDownLatch(1);
+ requestDraw(latch);
+ try {
+ latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ final long afterTime = System.nanoTime();
+ final long timeDiff = afterTime - beforeTime;
+ final long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime;
+ if (sleepTime > 0) { // some time left in this cycle
+ try {
+ Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L));
+ noDelays = 0; // Got some sleep, not delaying anymore
+ } catch (final InterruptedException ex) { }
+ overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
+ } else { // sleepTime <= 0; the frame took longer than the period
+ overSleepTime = 0L;
+ noDelays++;
+ if (noDelays > NO_DELAYS_PER_YIELD) {
+ Thread.yield(); // give another thread a chance to run
+ noDelays = 0;
+ }
+ }
+ beforeTime = System.nanoTime();
+ }
+ }
+
+ public void requestDraw(final CountDownLatch latch) {
+ glad.display();
+
+ if (latch != null) {
+ latch.countDown();
+ }
+ }
+
+ private void initGL() {
+ final GLProfile profile = GLProfile.getDefault();
+ final GLCapabilities caps = new GLCapabilities(profile);
+ caps.setBackgroundOpaque(true);
+ caps.setOnscreen(true);
+ caps.setSampleBuffers(false);
+
+ if (TOOLKIT == AWT) {
+ awtCanvas = new GLCanvas(caps);
+ awtCanvas.setBounds(0, 0, applet.width, applet.height);
+ awtCanvas.setBackground(new Color(0xFFCCCCCC, true));
+ awtCanvas.setFocusable(true);
+
+ applet.setLayout(new BorderLayout());
+ applet.add(awtCanvas, BorderLayout.CENTER);
+
+ if (IGNORE_AWT_REPAINT) {
+ awtCanvas.setIgnoreRepaint(true);
+ }
+ glad = awtCanvas;
+ } else if (TOOLKIT == NEWT) {
+ newtWindow = GLWindow.create(caps);
+ newtCanvas = new NewtCanvasAWT(newtWindow);
+ newtCanvas.setBounds(0, 0, applet.width, applet.height);
+ newtCanvas.setBackground(new Color(0xFFCCCCCC, true));
+ newtCanvas.setFocusable(true);
+
+ applet.setLayout(new BorderLayout());
+ applet.add(newtCanvas, BorderLayout.CENTER);
+
+ if (IGNORE_AWT_REPAINT) {
+ newtCanvas.setIgnoreRepaint(true);
+ }
+ glad = newtWindow;
+ }
+
+ demo = new LandscapeES2(SWAP_INTERVAL);
+ glad.addGLEventListener(demo);
+ }
+
+ private void initDraw() {
+ if (TOOLKIT == AWT) {
+ awtCanvas.setVisible(true);
+ // Force the realization
+ awtCanvas.display();
+ if (awtCanvas.getDelegatedDrawable().isRealized()) {
+ // Request the focus here as it cannot work when the window is not visible
+ awtCanvas.requestFocus();
+ }
+ } else if (TOOLKIT == NEWT) {
+ newtCanvas.setVisible(true);
+ // Force the realization
+ newtWindow.display();
+ if (newtWindow.isRealized()) {
+ // Request the focus here as it cannot work when the window is not visible
+ newtCanvas.requestFocus();
+ }
+ }
+ }
+
+ static public void main(final String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-vsync")) {
+ i++;
+ SWAP_INTERVAL = MiscUtils.atoi(args[i], SWAP_INTERVAL);
+ } else if(args[i].equals("-exclctx")) {
+ USE_ECT = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ System.err.println("swapInterval "+SWAP_INTERVAL);
+ System.err.println("exclusiveContext "+USE_ECT);
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
+
+ final GraphicsEnvironment environment =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ final GraphicsDevice displayDevice = environment.getDefaultScreenDevice();
+
+ frame = new Frame(displayDevice.getDefaultConfiguration());
+ frame.setBackground(new Color(0xCC, 0xCC, 0xCC));
+ frame.setTitle("TestBug735Inv2AppletAWT");
+
+ try {
+ final Class<?> c = Thread.currentThread().getContextClassLoader().
+ loadClass(Bug735Inv2AppletAWT.class.getName());
+ applet = (Bug735Inv2AppletAWT) c.newInstance();
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ frame.setLayout(null);
+ frame.add(applet);
+ frame.pack();
+ frame.setResizable(false);
+
+ applet.init();
+
+ final Insets insets = frame.getInsets();
+ final int windowW = applet.width + insets.left + insets.right;
+ final int windowH = applet.height + insets.top + insets.bottom;
+ frame.setSize(windowW, windowH);
+
+ final Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds();
+ frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2,
+ screenRect.y + (screenRect.height - applet.height) / 2);
+
+ final int usableWindowH = windowH - insets.top - insets.bottom;
+ applet.setBounds((windowW - applet.width)/2,
+ insets.top + (usableWindowH - applet.height)/2,
+ applet.width, applet.height);
+
+ // This allows to close the frame.
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ frame.setVisible(true);
+ applet.start();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv3AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv3AppletAWT.java
new file mode 100644
index 000000000..83db15cf3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv3AppletAWT.java
@@ -0,0 +1,218 @@
+package com.jogamp.opengl.test.bugs;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.SwingUtilities;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+
+/**
+ * Difference to orig. Bug735Inv0AppletAWT:
+ * <pre>
+ * - Use GLEventListener
+ * - Add GLEventListener to GLAutoDrawable
+ * - Use GLAutoDrawable.display() instead of GLAutoDrawable.invoke(true, GLRunnable { init / render })
+ * - Removed MANUAL_FRAME_HANDLING, obsolete due to GLAutoDrawable/GLEventListener
+ * - Use Animator
+ * - Remove applet, component sizes, use frame based size via validate
+ * - Run frame validation/visibility on AWT-EDT
+ * - Add Wait-For-Key after init (perf-test)
+ * </pre>
+ * OSX Results:
+ * <pre>
+ * - Visible content
+ * - Fluent animation
+ * </pre>
+ */
+@SuppressWarnings("serial")
+public class Bug735Inv3AppletAWT extends Applet {
+ static public final int AWT = 0;
+ static public final int NEWT = 1;
+
+ static public final int APPLET_WIDTH = 500;
+ static public final int APPLET_HEIGHT = 290;
+ static public final int TOOLKIT = NEWT;
+ static public final boolean IGNORE_AWT_REPAINT = false;
+ static public boolean USE_ECT = false;
+ static public int SWAP_INTERVAL = 1;
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ static boolean waitForKey = false;
+ static private Frame frame;
+ static private Bug735Inv3AppletAWT applet;
+ private GLCanvas awtCanvas;
+ private GLWindow newtWindow;
+ private GLAutoDrawable glad;
+ private NewtCanvasAWT newtCanvas;
+ private GLEventListener demo;
+ private AnimatorBase animator;
+
+ private int width;
+ private int height;
+
+ public void init() {
+ setSize(APPLET_WIDTH, APPLET_HEIGHT);
+ // JAU setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT));
+ width = APPLET_WIDTH;
+ height = APPLET_HEIGHT;
+ initGL();
+ }
+
+ public void start() {
+ initDraw();
+ animator.start();
+ animator.setUpdateFPSFrames(60, System.err);
+ }
+
+ private void initGL() {
+ final GLProfile profile = GLProfile.getDefault();
+ final GLCapabilities caps = new GLCapabilities(profile);
+ caps.setBackgroundOpaque(true);
+ caps.setOnscreen(true);
+ caps.setSampleBuffers(false);
+
+ if (TOOLKIT == AWT) {
+ awtCanvas = new GLCanvas(caps);
+ // JAU awtCanvas.setBounds(0, 0, applet.width, applet.height);
+ awtCanvas.setBackground(new Color(0xFFCCCCCC, true));
+ awtCanvas.setFocusable(true);
+
+ applet.setLayout(new BorderLayout());
+ applet.add(awtCanvas, BorderLayout.CENTER);
+
+ if (IGNORE_AWT_REPAINT) {
+ awtCanvas.setIgnoreRepaint(true);
+ }
+ glad = awtCanvas;
+ } else if (TOOLKIT == NEWT) {
+ newtWindow = GLWindow.create(caps);
+ newtCanvas = new NewtCanvasAWT(newtWindow);
+ // JAU newtCanvas.setBounds(0, 0, applet.width, applet.height);
+ newtCanvas.setBackground(new Color(0xFFCCCCCC, true));
+ newtCanvas.setFocusable(true);
+
+ applet.setLayout(new BorderLayout());
+ applet.add(newtCanvas, BorderLayout.CENTER);
+
+ if (IGNORE_AWT_REPAINT) {
+ newtCanvas.setIgnoreRepaint(true);
+ }
+ glad = newtWindow;
+ }
+
+ demo = new LandscapeES2(SWAP_INTERVAL);
+ // demo = new GearsES2(SWAP_INTERVAL);
+ glad.addGLEventListener(demo);
+ animator = new Animator(glad);
+ animator.setExclusiveContext(USE_ECT);
+ }
+
+ private void initDraw() {
+ if (TOOLKIT == AWT) {
+ // JAU awtCanvas.setVisible(true);
+ if (awtCanvas.getDelegatedDrawable().isRealized()) {
+ // Request the focus here as it cannot work when the window is not visible
+ awtCanvas.requestFocus();
+ }
+ } else if (TOOLKIT == NEWT) {
+ // JAU newtCanvas.setVisible(true);
+ // Force the realization
+ // JAU newtWindow.display();
+ if (newtWindow.isRealized()) {
+ // Request the focus here as it cannot work when the window is not visible
+ newtCanvas.requestFocus();
+ }
+ }
+ }
+
+ static public void main(final String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-vsync")) {
+ i++;
+ SWAP_INTERVAL = MiscUtils.atoi(args[i], SWAP_INTERVAL);
+ } else if(args[i].equals("-exclctx")) {
+ USE_ECT = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ System.err.println("swapInterval "+SWAP_INTERVAL);
+ System.err.println("exclusiveContext "+USE_ECT);
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
+
+ final GraphicsEnvironment environment =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ final GraphicsDevice displayDevice = environment.getDefaultScreenDevice();
+
+ frame = new Frame(displayDevice.getDefaultConfiguration());
+ frame.setBackground(new Color(0xCC, 0xCC, 0xCC));
+ frame.setTitle("TestBug735Inv3AppletAWT");
+
+ // This allows to close the frame.
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ try {
+ final Class<?> c = Thread.currentThread().getContextClassLoader().
+ loadClass(Bug735Inv3AppletAWT.class.getName());
+ applet = (Bug735Inv3AppletAWT) c.newInstance();
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ // JAU frame.setLayout(null);
+ frame.add(applet);
+
+ applet.init();
+
+ final Insets insets = frame.getInsets();
+ final int windowW = applet.width + insets.left + insets.right;
+ final int windowH = applet.height + insets.top + insets.bottom;
+
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(windowW, windowH);
+ frame.validate();
+ // JAU frame.pack();
+ final Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds();
+ frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2,
+ screenRect.y + (screenRect.height - applet.height) / 2);
+
+ frame.setResizable(false);
+ frame.setVisible(true);
+ }
+ });
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+
+ applet.start();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv4AWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv4AWT.java
new file mode 100644
index 000000000..a3fd3fa21
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv4AWT.java
@@ -0,0 +1,202 @@
+package com.jogamp.opengl.test.bugs;
+
+import java.awt.Color;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.SwingUtilities;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+
+/**
+ * Difference to orig. Bug735Inv0AppletAWT:
+ * <pre>
+ * - Use GLEventListener
+ * - Add GLEventListener to GLAutoDrawable
+ * - Use GLAutoDrawable.display() instead of GLAutoDrawable.invoke(true, GLRunnable { init / render })
+ * - Removed MANUAL_FRAME_HANDLING, obsolete due to GLAutoDrawable/GLEventListener
+ * - Use Animator
+ * - Remove component sizes, use frame based size via validate
+ * - Run frame validation/visibility on AWT-EDT
+ * - Add Wait-For-Key after init (perf-test)
+ * - Remove intermediate applet!
+ * </pre>
+ * OSX Results:
+ * <pre>
+ * - Visible content
+ * - Fluent animation
+ * </pre>
+ */
+public class Bug735Inv4AWT {
+ static public final int AWT = 0;
+ static public final int NEWT = 1;
+
+ static public final int APPLET_WIDTH = 500;
+ static public final int APPLET_HEIGHT = 290;
+ static public final int TOOLKIT = NEWT;
+ static public final boolean IGNORE_AWT_REPAINT = false;
+ static public boolean USE_ECT = false;
+ static public int SWAP_INTERVAL = 1;
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ static boolean waitForKey = false;
+ static private Frame frame;
+ static private Bug735Inv4AWT applet;
+ private GLCanvas awtCanvas;
+ private GLWindow newtWindow;
+ private GLAutoDrawable glad;
+ private NewtCanvasAWT newtCanvas;
+ private GLEventListener demo;
+ private AnimatorBase animator;
+
+ private int width;
+ private int height;
+
+ public void init() {
+ width = APPLET_WIDTH;
+ height = APPLET_HEIGHT;
+ initGL();
+ }
+
+ public void start() {
+ initDraw();
+ animator.start();
+ animator.setUpdateFPSFrames(60, System.err);
+ }
+
+ private void initGL() {
+ final GLProfile profile = GLProfile.getDefault();
+ final GLCapabilities caps = new GLCapabilities(profile);
+ caps.setBackgroundOpaque(true);
+ caps.setOnscreen(true);
+ caps.setSampleBuffers(false);
+
+ if (TOOLKIT == AWT) {
+ awtCanvas = new GLCanvas(caps);
+ awtCanvas.setBackground(new Color(0xFFCCCCCC, true));
+ awtCanvas.setFocusable(true);
+
+ if (IGNORE_AWT_REPAINT) {
+ awtCanvas.setIgnoreRepaint(true);
+ }
+ glad = awtCanvas;
+ } else if (TOOLKIT == NEWT) {
+ newtWindow = GLWindow.create(caps);
+ newtCanvas = new NewtCanvasAWT(newtWindow);
+ newtCanvas.setBackground(new Color(0xFFCCCCCC, true));
+ newtCanvas.setFocusable(true);
+
+ if (IGNORE_AWT_REPAINT) {
+ newtCanvas.setIgnoreRepaint(true);
+ }
+ glad = newtWindow;
+ }
+
+ demo = new LandscapeES2(SWAP_INTERVAL);
+ // demo = new GearsES2(SWAP_INTERVAL);
+ glad.addGLEventListener(demo);
+ animator = new Animator(glad);
+ animator.setExclusiveContext(USE_ECT);
+ }
+
+ private void initDraw() {
+ if (TOOLKIT == AWT) {
+ if (awtCanvas.getDelegatedDrawable().isRealized()) {
+ // Request the focus here as it cannot work when the window is not visible
+ awtCanvas.requestFocus();
+ }
+ } else if (TOOLKIT == NEWT) {
+ // newtCanvas.repaint();
+ // Force the realization
+ // newtWindow.display();
+ if (newtWindow.isRealized()) {
+ // Request the focus here as it cannot work when the window is not visible
+ newtCanvas.requestFocus();
+ }
+ }
+ }
+
+ static public void main(final String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-vsync")) {
+ i++;
+ SWAP_INTERVAL = MiscUtils.atoi(args[i], SWAP_INTERVAL);
+ } else if(args[i].equals("-exclctx")) {
+ USE_ECT = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ System.err.println("swapInterval "+SWAP_INTERVAL);
+ System.err.println("exclusiveContext "+USE_ECT);
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
+
+ final GraphicsEnvironment environment =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ final GraphicsDevice displayDevice = environment.getDefaultScreenDevice();
+
+ frame = new Frame(displayDevice.getDefaultConfiguration());
+ // JAU frame.setBackground(new Color(0xCC, 0xCC, 0xCC));
+ frame.setTitle("TestBug735Inv4AWT");
+
+ // This allows to close the frame.
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ applet = new Bug735Inv4AWT();
+ applet.init();
+
+ if (TOOLKIT == AWT) {
+ frame.add(applet.awtCanvas);
+ } else if (TOOLKIT == NEWT) {
+ frame.add(applet.newtCanvas);
+ }
+ // frame.pack();
+ // frame.setResizable(false);
+
+ final Insets insets = frame.getInsets();
+ final int windowW = applet.width + insets.left + insets.right;
+ final int windowH = applet.height + insets.top + insets.bottom;
+
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(windowW, windowH);
+ frame.validate();
+ // frame.pack();
+ final Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds();
+ frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2,
+ screenRect.y + (screenRect.height - applet.height) / 2);
+
+ frame.setVisible(true);
+ }
+ });
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+
+ applet.start();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/bugs/DemoBug910ExtendedAWTAppletLifecycleCheck.java b/src/test/com/jogamp/opengl/test/bugs/DemoBug910ExtendedAWTAppletLifecycleCheck.java
new file mode 100644
index 000000000..3d43c2f8f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/bugs/DemoBug910ExtendedAWTAppletLifecycleCheck.java
@@ -0,0 +1,235 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.bugs;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.Graphics;
+import java.lang.reflect.InvocationTargetException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@SuppressWarnings("serial")
+public class DemoBug910ExtendedAWTAppletLifecycleCheck extends Applet {
+
+ private static String currentThreadName() { return "["+Thread.currentThread().getName()+", isAWT-EDT "+EventQueue.isDispatchThread()+"]"; }
+
+ private static void invoke(final boolean wait, final Runnable r) {
+ if(EventQueue.isDispatchThread()) {
+ r.run();
+ } else {
+ try {
+ if(wait) {
+ EventQueue.invokeAndWait(r);
+ } else {
+ EventQueue.invokeLater(r);
+ }
+ } catch (final InvocationTargetException e) {
+ throw new RuntimeException(e.getTargetException());
+ } catch (final InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private static final String comp2Str(final Component c) {
+ return c.getClass().getSimpleName()+"[visible "+c.isVisible()+", showing "+c.isShowing()+", valid "+c.isValid()+
+ ", displayable "+c.isDisplayable()+", "+c.getX()+"/"+c.getY()+" "+c.getWidth()+"x"+c.getHeight()+"]";
+ }
+
+ private void println(final String msg) {
+ System.err.println(msg);
+ }
+
+ private final void checkComponentState(final String msg, final boolean expIsContained, final int expAddNotifyCount, final int expRemoveNotifyCount) {
+ final int compCount = getComponentCount();
+ final Component c = 1 <= compCount ? getComponent(0) : null;
+ final String clazzName = null != c ? c.getName() : "n/a";
+ final boolean isContained = c == myCanvas;
+ final String okS = ( expIsContained == isContained &&
+ expAddNotifyCount == myCanvas.addNotifyCount &&
+ expRemoveNotifyCount == myCanvas.removeNotifyCount ) ? "OK" : "ERROR";
+ println("Component-State @ "+msg+": "+okS+
+ ", contained[exp "+expIsContained+", has "+isContained+"]"+(expIsContained!=isContained?"*":"")+
+ ", addNotify[exp "+expAddNotifyCount+", has "+myCanvas.addNotifyCount+"]"+(expAddNotifyCount!=myCanvas.addNotifyCount?"*":"")+
+ ", removeNotify[exp "+expRemoveNotifyCount+", has "+myCanvas.removeNotifyCount+"]"+(expRemoveNotifyCount!=myCanvas.removeNotifyCount?"*":"")+
+ ", compCount "+compCount+", compClazz "+clazzName);
+ }
+
+ AtomicInteger initCount = new AtomicInteger(0);
+ AtomicInteger startCount = new AtomicInteger(0);
+ AtomicInteger stopCount = new AtomicInteger(0);
+ AtomicInteger destroyCount = new AtomicInteger(0);
+
+ private final void checkAppletState(final String msg, final boolean expIsActive,
+ final int expInitCount, final int expStartCount, final int expStopCount, final boolean startStopCountEquals, final int expDestroyCount) {
+ final boolean isActive = this.isActive();
+ final String okS = ( expInitCount == initCount.get() &&
+ expIsActive == isActive &&
+ expStartCount == startCount.get() &&
+ expStopCount == stopCount.get() &&
+ expDestroyCount == destroyCount.get() &&
+ ( !startStopCountEquals || startCount == stopCount ) ) ? "OK" : "ERROR";
+ println("Applet-State @ "+msg+": "+okS+
+ ", active[exp "+expIsActive+", has "+isActive+"]"+(expIsActive!=isActive?"*":"")+
+ ", init[exp "+expInitCount+", has "+initCount+"]"+(expInitCount!=initCount.get()?"*":"")+
+ ", start[exp "+expStartCount+", has "+startCount+"]"+(expStartCount!=startCount.get()?"*":"")+
+ ", stop[exp "+expStopCount+", has "+stopCount+"]"+(expStopCount!=stopCount.get()?"*":"")+
+ ", start==stop[exp "+startStopCountEquals+", start "+startCount+", stop "+stopCount+"]"+(( startStopCountEquals && startCount != stopCount )?"*":"")+
+ ", destroy[exp "+expDestroyCount+", has "+destroyCount+"]"+(expDestroyCount!=destroyCount.get()?"*":""));
+ }
+
+ private class MyCanvas extends Canvas {
+ int addNotifyCount = 0;
+ int removeNotifyCount = 0;
+ int paintCount = 0;
+
+ MyCanvas() {
+ setBackground( new Color( 200, 200, 255 ) );
+ }
+
+ public String toString() {
+ return comp2Str(this)+", add/remove[addNotify "+addNotifyCount+", removeCount "+removeNotifyCount+"]";
+ }
+
+ @Override
+ public void addNotify() {
+ addNotifyCount++;
+ println("Applet.Canvas.addNotify() - "+currentThreadName());
+ if( !EventQueue.isDispatchThread() ) {
+ println("Applet.Canvas.addNotify() ERROR: Not on AWT-EDT");
+ }
+ // Thread.dumpStack();
+ super.addNotify();
+ println("Applet.Canvas.addNotify(): "+this);
+ }
+
+ @Override
+ public void removeNotify() {
+ removeNotifyCount++;
+ println("Applet.Canvas.removeNotify() - "+currentThreadName());
+ println("Applet.Canvas.removeNotify(): "+this);
+ if( !EventQueue.isDispatchThread() ) {
+ println("Applet.Canvas.removeNotify() ERROR: Not on AWT-EDT");
+ }
+ // Thread.dumpStack();
+ super.removeNotify();
+ }
+
+ @Override
+ public void paint(final Graphics g) {
+ super.paint(g);
+ paintCount++;
+ final int width = getWidth();
+ final int height = getHeight();
+ final String msg = "The payload Canvas. Paint "+width+"x"+height+" #"+paintCount;
+ g.setColor(Color.black);
+ g.drawString(msg, 64, 64);
+ }
+ }
+ MyCanvas myCanvas = null;
+
+ @Override
+ public void init() {
+ final java.awt.Dimension aSize = getSize();
+ println("Applet.init() START - applet.size "+aSize+" - "+currentThreadName());
+ initCount.incrementAndGet();
+ checkAppletState("init", false /* expIsActive */, 1 /* expInitCount */,
+ 0 /* expStartCount */, 0 /* expStopCount */, true /* startStopCountEquals */,
+ 0 /* expDestroyCount */);
+ invoke(true, new Runnable() {
+ public void run() {
+ setLayout(new BorderLayout());
+ myCanvas = new MyCanvas();
+ println("Applet.init(): self "+comp2Str(DemoBug910ExtendedAWTAppletLifecycleCheck.this));
+ println("Applet.init(): canvas "+comp2Str(myCanvas));
+ checkComponentState("init-add.pre", false, 0, 0);
+ add(myCanvas, BorderLayout.CENTER);
+ validate();
+ checkComponentState("init-add.post", true, 1, 0);
+ println("Applet.init(): canvas "+comp2Str(myCanvas));
+ } } );
+ println("Applet.init() END - "+currentThreadName());
+ }
+
+ @Override
+ public void start() {
+ println("Applet.start() START (isVisible "+isVisible()+", isDisplayable "+isDisplayable()+") - "+currentThreadName());
+ startCount.incrementAndGet();
+ checkAppletState("start", true /* expIsActive */, 1 /* expInitCount */,
+ startCount.get() /* expStartCount */, startCount.get()-1 /* expStopCount */, false /* startStopCountEquals */,
+ 0 /* expDestroyCount */);
+ invoke(true, new Runnable() {
+ public void run() {
+ checkComponentState("start-visible.pre", true, 1, 0);
+ if( null != myCanvas ) {
+ myCanvas.setFocusable(true);
+ myCanvas.requestFocus();
+ }
+ checkComponentState("start-visible.post", true, 1, 0);
+ println("Applet.start(): self "+comp2Str(DemoBug910ExtendedAWTAppletLifecycleCheck.this));
+ println("Applet.start(): canvas "+comp2Str(myCanvas));
+ }
+ });
+ println("Applet.start() END - "+currentThreadName());
+ }
+
+ @Override
+ public void stop() {
+ println("Applet.stop() START - "+currentThreadName());
+ stopCount.incrementAndGet();
+ checkAppletState("stop", false /* expIsActive */, 1 /* expInitCount */,
+ stopCount.get() /* expStartCount */, stopCount.get() /* expStopCount */, true /* startStopCountEquals */,
+ 0 /* expDestroyCount */);
+ invoke(true, new Runnable() {
+ public void run() {
+ checkComponentState("stop", true, 1, 0);
+ } } );
+ println("Applet.stop() END - "+currentThreadName());
+ }
+
+ @Override
+ public void destroy() {
+ println("Applet.destroy() START - "+currentThreadName());
+ destroyCount.incrementAndGet();
+ checkAppletState("destroy", false /* expIsActive */, 1 /* expInitCount */,
+ startCount.get() /* expStartCount */, stopCount.get() /* expStopCount */, true /* startStopCountEquals */,
+ 1 /* expDestroyCount */);
+ invoke(true, new Runnable() {
+ public void run() {
+ checkComponentState("destroy-remove.pre", true, 1, 0);
+ remove(myCanvas);
+ checkComponentState("destroy-remove.post", false, 1, 1);
+ } } );
+ println("Applet.destroy() END - "+currentThreadName());
+ }
+}
+
diff --git a/src/test/com/jogamp/opengl/test/bugs/Issue326Test1.java b/src/test/com/jogamp/opengl/test/bugs/Issue326Test1.java
index 833f34153..802bd65d5 100644
--- a/src/test/com/jogamp/opengl/test/bugs/Issue326Test1.java
+++ b/src/test/com/jogamp/opengl/test/bugs/Issue326Test1.java
@@ -9,16 +9,18 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Random;
+import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.awt.TextRenderer;
-/**
+/**
* Demonstrates corruption with older versions of TextRenderer. Two
* problems: errors when punting from glyph-based renderer to
* string-by-string renderer, and failure of glyph-based renderer when
@@ -31,64 +33,64 @@ public class Issue326Test1 extends Frame implements GLEventListener {
int width, height;
- public static void main(String[] args) {
- new Issue326Test1();
+ public static void main(final String[] args) {
+ new Issue326Test1();
}
-
+
GLCanvas canvas;
TextRenderer tr ;
-
+
public Issue326Test1() {
super("TextTest");
this.setSize(800, 800);
canvas = new GLCanvas();
canvas.addGLEventListener(this);
add(canvas);
-
+
setVisible(true);
addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
+ public void windowClosing(final WindowEvent e) {
System.exit(0);
}
});
}
- public void display(GLAutoDrawable drawable) {
- GL2 gl = drawable.getGL().getGL2();
+ public void display(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
gl.glClearColor(0, 0, 0, 0);
- gl.glClear(GL2.GL_COLOR_BUFFER_BIT|GL2.GL_DEPTH_BUFFER_BIT);
-
-
- gl.glMatrixMode(GL2.GL_PROJECTION);
- gl.glLoadIdentity();
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT);
+
+
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
//new GLU().gluPerspective(45f, (float)width/(float)height, 0.1f, 1000f);
gl.glOrtho(0.0, 800, 0.0, 800, -100.0, 100.0);
- gl.glMatrixMode(GL2.GL_MODELVIEW);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
-
+
tr.beginRendering(800,800);
tr.draw( "die Marktwirtschaft. Da regelt sich � angeblich", 16, 32);
tr.draw( "Hello World! This text is scrambled", 16, 16);
tr.endRendering();
-
+
}
- public void init(GLAutoDrawable arg0) {
+ public void init(final GLAutoDrawable arg0) {
tr = new TextRenderer(new java.awt.Font("Verdana", java.awt.Font.PLAIN, 12), true, false, null, false);
tr.setColor(1, 1, 1 ,1);
}
- public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3, int arg4) {
+ public void reshape(final GLAutoDrawable arg0, final int arg1, final int arg2, final int arg3, final int arg4) {
width = arg3;
height = arg4;
- GL2 gl = arg0.getGL().getGL2();
+ final GL2 gl = arg0.getGL().getGL2();
gl.glViewport(0, 0, width, height);
- gl.glMatrixMode(GL2.GL_PROJECTION);
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(0.0, 800, 0.0, 200, -100.0, 100.0);
- gl.glMatrixMode(GL2.GL_MODELVIEW);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
}
- public void dispose(GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Issue326Test2.java b/src/test/com/jogamp/opengl/test/bugs/Issue326Test2.java
index ac5d819b3..032eaa23c 100644
--- a/src/test/com/jogamp/opengl/test/bugs/Issue326Test2.java
+++ b/src/test/com/jogamp/opengl/test/bugs/Issue326Test2.java
@@ -3,10 +3,13 @@ package com.jogamp.opengl.test.bugs;
import java.awt.Font;
import java.awt.Frame;
import java.awt.event.*;
+
+import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.opengl.util.awt.*;
@@ -20,54 +23,54 @@ public class Issue326Test2 extends Frame implements GLEventListener {
int width, height;
- public static void main(String[] args) {
- new Issue326Test2();
+ public static void main(final String[] args) {
+ new Issue326Test2();
}
-
+
GLCanvas canvas;
TextRenderer tr;
-
+
public Issue326Test2() {
super("");
this.setSize(800, 800);
canvas = new GLCanvas();
canvas.addGLEventListener(this);
add(canvas);
-
+
setVisible(true);
addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
+ public void windowClosing(final WindowEvent e) {
System.exit(0);
}
});
}
- public void display(GLAutoDrawable drawable) {
- GL2 gl = drawable.getGL().getGL2();
+ public void display(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
gl.glClearColor(0, 0, 0, 0);
- gl.glClear(GL2.GL_COLOR_BUFFER_BIT|GL2.GL_DEPTH_BUFFER_BIT);
-
- tr.beginRendering(drawable.getWidth(), drawable.getHeight());
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT);
+
+ tr.beginRendering(drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
tr.draw("LA CLAPI\u00c8RE \nAlt: 1100-1700m \nGlissement de terrain majeur", 16, 80);
tr.draw("dans la haute Tin\u00e9e, sur un flanc du Parc du Mercantour.", 16, 16);
tr.endRendering();
-
+
}
- public void init(GLAutoDrawable arg0) {
+ public void init(final GLAutoDrawable arg0) {
tr = new TextRenderer(Font.decode("Arial-BOLD-64"));
tr.setColor(1, 1, 1 ,1);
}
- public void reshape(GLAutoDrawable arg0, int x, int y, int w, int h) {
- GL2 gl = arg0.getGL().getGL2();
- gl.glMatrixMode(GL2.GL_PROJECTION);
+ public void reshape(final GLAutoDrawable arg0, final int x, final int y, final int w, final int h) {
+ final GL2 gl = arg0.getGL().getGL2();
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(0.0, w, 0.0, h, -1, 1);
- gl.glMatrixMode(GL2.GL_MODELVIEW);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
}
- public void dispose(GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java b/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java
index 9b0a4c6a0..54786bbc3 100644
--- a/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java
+++ b/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java
@@ -6,11 +6,14 @@ import java.awt.Frame;
import java.awt.event.*;
import java.awt.geom.*;
+import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.*;
+
import com.jogamp.opengl.util.awt.TextRenderer;
/** Test Code adapted from TextCube.java (in JOGL demos)
@@ -35,17 +38,17 @@ public abstract class Issue344Base implements GLEventListener
protected abstract String getText();
- protected void run(String[] args) {
- Frame frame = new Frame(getClass().getName());
+ protected void run(final String[] args) {
+ final Frame frame = new Frame(getClass().getName());
frame.setLayout(new BorderLayout());
- GLCanvas canvas = new GLCanvas();
+ final GLCanvas canvas = new GLCanvas();
canvas.addGLEventListener(this);
frame.add(canvas, BorderLayout.CENTER);
frame.setSize(512, 512);
frame.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
+ public void windowClosing(final WindowEvent e) {
new Thread(new Runnable() {
public void run() {
System.exit(0);
@@ -53,55 +56,62 @@ public abstract class Issue344Base implements GLEventListener
}).start();
}
});
- frame.setVisible(true);
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(true);
+ } } );
+ } catch(final Exception ex) {
+ throw new RuntimeException(ex);
+ }
}
- public void init(GLAutoDrawable drawable)
+ public void init(final GLAutoDrawable drawable)
{
- GL2 gl = drawable.getGL().getGL2();
+ final GL2 gl = drawable.getGL().getGL2();
- gl.glEnable(GL2.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_DEPTH_TEST);
renderer = new TextRenderer(font, useMipMaps);
- Rectangle2D bounds = renderer.getBounds(getText());
- float w = (float) bounds.getWidth();
- float h = (float) bounds.getHeight();
+ final Rectangle2D bounds = renderer.getBounds(getText());
+ final float w = (float) bounds.getWidth();
+ // final float h = (float) bounds.getHeight();
textScaleFactor = 2.0f / (w * 1.1f);
gl.setSwapInterval(0);
}
- public void display(GLAutoDrawable drawable)
+ public void display(final GLAutoDrawable drawable)
{
- GL2 gl = drawable.getGL().getGL2();
- gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
+ final GL2 gl = drawable.getGL().getGL2();
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- gl.glMatrixMode(GL2.GL_MODELVIEW);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
glu.gluLookAt(0, 0, 10,
0, 0, 0,
0, 1, 0);
renderer.begin3DRendering();
- Rectangle2D bounds = renderer.getBounds(getText());
- float w = (float) bounds.getWidth();
- float h = (float) bounds.getHeight();
+ final Rectangle2D bounds = renderer.getBounds(getText());
+ final float w = (float) bounds.getWidth();
+ final float h = (float) bounds.getHeight();
renderer.draw3D(getText(),
w / -2.0f * textScaleFactor,
h / -2.0f * textScaleFactor,
3f,
textScaleFactor);
-
+
renderer.end3DRendering();
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height)
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height)
{
- GL2 gl = drawable.getGL().getGL2();
- gl.glMatrixMode(GL2.GL_PROJECTION);
+ final GL2 gl = drawable.getGL().getGL2();
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(15, (float) width / (float) height, 5, 15);
}
- public void dispose(GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Issue344Test1.java b/src/test/com/jogamp/opengl/test/bugs/Issue344Test1.java
index f0da7cbf8..384b6e993 100644
--- a/src/test/com/jogamp/opengl/test/bugs/Issue344Test1.java
+++ b/src/test/com/jogamp/opengl/test/bugs/Issue344Test1.java
@@ -2,11 +2,11 @@ package com.jogamp.opengl.test.bugs;
public class Issue344Test1 extends Issue344Base {
protected String getText() {
- // test 1 - weird artifacts appear with a large font & long string
+ // test 1 - weird artifacts appear with a large font & long string
return "abcdefghijklmnopqrstuvwxyz1234567890";
}
- public static void main(String[] args) {
+ public static void main(final String[] args) {
new Issue344Test1().run(args);
}
}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Issue344Test2.java b/src/test/com/jogamp/opengl/test/bugs/Issue344Test2.java
index bb1acf2de..9941b3f5b 100644
--- a/src/test/com/jogamp/opengl/test/bugs/Issue344Test2.java
+++ b/src/test/com/jogamp/opengl/test/bugs/Issue344Test2.java
@@ -6,7 +6,7 @@ public class Issue344Test2 extends Issue344Base {
return "\u201Cabcdefghijklmnopqrstuvwxyz\u201D";
}
- public static void main(String[] args) {
+ public static void main(final String[] args) {
new Issue344Test2().run(args);
}
}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Issue344Test3.java b/src/test/com/jogamp/opengl/test/bugs/Issue344Test3.java
index bb73d84ec..7ae4245c6 100644
--- a/src/test/com/jogamp/opengl/test/bugs/Issue344Test3.java
+++ b/src/test/com/jogamp/opengl/test/bugs/Issue344Test3.java
@@ -6,7 +6,7 @@ public class Issue344Test3 extends Issue344Base {
return "abcde";
}
- public static void main(String[] args) {
+ public static void main(final String[] args) {
new Issue344Test3().run(args);
}
}
diff --git a/src/test/com/jogamp/opengl/test/bugs/Issue344Test4.java b/src/test/com/jogamp/opengl/test/bugs/Issue344Test4.java
index de4c37a40..87a5b644e 100644
--- a/src/test/com/jogamp/opengl/test/bugs/Issue344Test4.java
+++ b/src/test/com/jogamp/opengl/test/bugs/Issue344Test4.java
@@ -6,7 +6,7 @@ public class Issue344Test4 extends Issue344Base {
return "\u201CGreetings\u201D!";
}
- public static void main(String[] args) {
+ public static void main(final String[] args) {
new Issue344Test4().run(args);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/FontSet01.java b/src/test/com/jogamp/opengl/test/junit/graph/FontSet01.java
new file mode 100644
index 000000000..0666ec4db
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/FontSet01.java
@@ -0,0 +1,35 @@
+package com.jogamp.opengl.test.junit.graph;
+
+import java.io.IOException;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.font.FontSet;
+
+public class FontSet01 {
+ public static Font[] getSet01() throws IOException {
+ final Font[] fonts = new Font[11];
+ int i = 0;
+ fonts[i++] = FontFactory.get(FontFactory.UBUNTU).getDefault(); // FontSet.FAMILY_REGULAR, FontSet.STYLE_NONE
+ fonts[i++] = FontFactory.get(FontFactory.UBUNTU).get(FontSet.FAMILY_REGULAR, FontSet.STYLE_ITALIC);
+ fonts[i++] = FontFactory.get(FontFactory.UBUNTU).get(FontSet.FAMILY_REGULAR, FontSet.STYLE_BOLD);
+ fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class,
+ "fonts/freefont/FreeMono.ttf").getInputStream(), true);
+ fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class,
+ "fonts/freefont/FreeMonoBold.ttf").getInputStream(), true);
+ fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class,
+ "fonts/freefont/FreeSans.ttf").getInputStream(), true);
+ fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class,
+ "fonts/freefont/FreeSansBold.ttf").getInputStream(), true);
+ fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class,
+ "fonts/freefont/FreeSerif.ttf").getInputStream(), true);
+ fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class,
+ "fonts/freefont/FreeSerifBold.ttf").getInputStream(), true);
+ fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class,
+ "fonts/freefont/FreeSerifBoldItalic.ttf").getInputStream(), true);
+ fonts[i++] = FontFactory.get(IOUtil.getResource(TestTextRendererNEWTBugXXXX.class,
+ "fonts/freefont/FreeSerifItalic.ttf").getInputStream(), true);
+ return fonts;
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java
new file mode 100644
index 000000000..e0c6d2ac0
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph;
+
+import java.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.Font.Glyph;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestFontsNEWT00 extends UITestCase {
+ static boolean mainRun = false;
+
+ static int atoi(final String a) {
+ try {
+ return Integer.parseInt(a);
+ } catch (final Exception ex) { throw new RuntimeException(ex); }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ mainRun = true;
+ final String tstname = TestFontsNEWT00.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+ @Test
+ public void test00() throws InterruptedException, IOException {
+ testFontImpl(FontSet01.getSet01());
+ }
+ void testFontImpl(final Font[] fonts) throws InterruptedException, IOException {
+ final float fontSize = 10;
+ final float dpi = 96;
+ for(int i=0; i<fonts.length; i++) {
+ final Font font = fonts[i];
+ final float pixelSize = font.getPixelSize(fontSize, dpi);
+ System.err.println(font.getFullFamilyName(null).toString()+": "+fontSize+"p, "+dpi+"dpi -> "+pixelSize+"px:");
+ testFontGlyphAdvancedSize(font, ' ', Glyph.ID_SPACE, fontSize, dpi, pixelSize);
+ testFontGlyphAdvancedSize(font, 'X', 'X', fontSize, dpi, pixelSize);
+ }
+ }
+ void testFontGlyphAdvancedSize(final Font font, final char c, final int glyphID,
+ final float fontSize, final float dpi, final float pixelSize) {
+ final float glyphScale = font.getGlyph(c).getScale(pixelSize);
+ final float fontScale = font.getMetrics().getScale(pixelSize);
+
+ // return this.metrics.getAdvance(pixelSize, useFrationalMetrics);
+ // this.metrics.getAdvance(pixelSize, useFrationalMetrics)
+ // this.advance * this.font.getMetrics().getScale(pixelSize)
+ // font.getHmtxTable().getAdvanceWidth(glyphID) * this.font.getMetrics().getScale(pixelSize)
+ final float spaceAdvanceSizeOfGlyph = font.getGlyph(c).getAdvance(pixelSize, true);
+
+ // font.getHmtxTable().getAdvanceWidth(glyphID) * metrics.getScale(pixelSize);
+ // font.getHmtxTable().getAdvanceWidth(glyphID) * pixelSize * unitsPerEM_Inv;
+ final float spaceAdvanceWidth = font.getAdvanceWidth(glyphID, pixelSize);
+ System.err.println(" Char '"+c+"', "+glyphID+":");
+ System.err.println(" glyphScale "+glyphScale);
+ System.err.println(" glyphSize "+spaceAdvanceSizeOfGlyph);
+ System.err.println(" fontScale "+fontScale);
+ System.err.println(" fontWidth "+spaceAdvanceWidth);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java
index a6616945d..8e647c3ab 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java
@@ -36,38 +36,42 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import jogamp.common.os.PlatformPropsImpl;
+
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.os.Platform;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.graph.geom.SVertex;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.graph.demos.GPURegionGLListener01;
import com.jogamp.opengl.test.junit.graph.demos.GPURegionGLListener02;
-import com.jogamp.opengl.test.junit.graph.demos.GPURegionRendererListenerBase01;
+import com.jogamp.opengl.test.junit.graph.demos.GPURendererListenerBase01;
import com.jogamp.opengl.test.junit.util.UITestCase;
-import com.jogamp.opengl.util.glsl.ShaderState;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestRegionRendererNEWT01 extends UITestCase {
- public static void main(String args[]) throws IOException {
- String tstname = TestRegionRendererNEWT01.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestRegionRendererNEWT01.class.getName();
org.junit.runner.JUnitCore.main(tstname);
- }
-
- static void destroyWindow(GLWindow window) {
+ }
+
+ static void destroyWindow(final GLWindow window) {
if(null!=window) {
window.destroy();
}
}
- static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) {
+ static GLWindow createWindow(final String title, final GLCapabilitiesImmutable caps, final int width, final int height) {
Assert.assertNotNull(caps);
- GLWindow window = GLWindow.create(caps);
+ final GLWindow window = GLWindow.create(caps);
window.setSize(width, height);
window.setPosition(10, 10);
window.setTitle(title);
@@ -77,146 +81,209 @@ public class TestRegionRendererNEWT01 extends UITestCase {
return window;
}
- @Test
- public void testRegionRendererR2T01() throws InterruptedException {
- if(Platform.CPUFamily.X86 != Platform.CPU_ARCH.family) { // FIXME
- // FIXME: Disabled for now - since it doesn't seem fit for mobile (performance wise).
+ // @Test
+ public void test00RegionRendererNONE01() throws InterruptedException {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ // caps.setOnscreen(false);
+ caps.setAlphaBits(4);
+
+ final GLWindow window = createWindow("shape-vbaa0-msaa0", caps, 800, 400);
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+
+ final GPURegionGLListener01 demo01Listener = new GPURegionGLListener01 (rs, 0, 0, false, false);
+ demo01Listener.attachInputListenerTo(window);
+ window.addGLEventListener(demo01Listener);
+
+ final RegionGLListener listener = new RegionGLListener(demo01Listener, window.getTitle(), "GPURegion01");
+ window.addGLEventListener(listener);
+
+ listener.setTech(-20, 0, -300, 0f, 2);
+ window.display();
+
+ listener.setTech(-20, 0, -150, 0f, 3);
+ window.display();
+
+ listener.setTech(-20, 0, -50, 0f, 4);
+ window.display();
+
+ destroyWindow(window);
+ }
+
+ // @Test
+ public void test01RegionRendererNONE02() throws InterruptedException {
+ if(Platform.CPUFamily.X86 != PlatformPropsImpl.CPU_ARCH.family) { // FIXME
+ // FIXME: Disabled for now - since it doesn't seem fit for mobile (performance wise).
+ // FIXME: Also the GLSL code for VARIABLE_CURVE is not fit for mobile yet!
System.err.println("disabled on non desktop (x86) arch for now ..");
return;
}
- GLProfile glp = GLProfile.getGL2ES2();
-
- GLCapabilities caps = new GLCapabilities(glp);
- //caps.setOnscreen(false);
- caps.setAlphaBits(4);
-
- GLWindow window = createWindow("shape-vbaa1-msaa0", caps, 800,400);
- RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- GPURegionGLListener02 demo02Listener = new GPURegionGLListener02 (rs, Region.VBAA_RENDERING_BIT, 1140, false, false);
- demo02Listener.attachInputListenerTo(window);
- window.addGLEventListener(demo02Listener);
-
- RegionGLListener listener = new RegionGLListener(demo02Listener, window.getTitle(), "GPURegionNewtDemo02");
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
+
+ final GLWindow window = createWindow("shape-vbaa0-msaa0", caps, 800, 400);
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+
+ final GPURegionGLListener01 demo01Listener = new GPURegionGLListener01 (rs, Region.VARWEIGHT_RENDERING_BIT, 0, false, false);
+ demo01Listener.attachInputListenerTo(window);
+ window.addGLEventListener(demo01Listener);
+
+ final RegionGLListener listener = new RegionGLListener(demo01Listener, window.getTitle(), "GPURegion02");
window.addGLEventListener(listener);
-
- listener.setTech(-20, 00, 0f, -300, 400);
+
+ listener.setTech(-20, 0, -300, 0f, 2);
window.display();
-
- listener.setTech(-20, 00, 0f, -150, 800);
+
+ listener.setTech(-20, 0, -150, 0f, 3);
window.display();
-
- listener.setTech(-20, 00, 0f, -50, 1000);
+
+ listener.setTech(-20, 0, -50, 0f, 4);
window.display();
- destroyWindow(window);
+ destroyWindow(window);
}
-
+
@Test
- public void testRegionRendererMSAA01() throws InterruptedException {
- GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
- GLCapabilities caps = new GLCapabilities(glp);
+ public void test10RegionRendererMSAA01() throws InterruptedException {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
+ final GLCapabilities caps = new GLCapabilities(glp);
// caps.setOnscreen(false);
- caps.setAlphaBits(4);
+ caps.setAlphaBits(4);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
- GLWindow window = createWindow("shape-vbaa0-msaa1", caps, 800, 400);
- RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
+ final GLWindow window = createWindow("shape-vbaa0-msaa1", caps, 800, 400);
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
- GPURegionGLListener01 demo01Listener = new GPURegionGLListener01 (rs, 0, 0, false, false);
- demo01Listener.attachInputListenerTo(window);
+ final GPURegionGLListener01 demo01Listener = new GPURegionGLListener01 (rs, 0, 0, false, false);
+ demo01Listener.attachInputListenerTo(window);
window.addGLEventListener(demo01Listener);
-
- RegionGLListener listener = new RegionGLListener(demo01Listener, window.getTitle(), "GPURegion01");
+
+ final RegionGLListener listener = new RegionGLListener(demo01Listener, window.getTitle(), "GPURegion01");
window.addGLEventListener(listener);
-
- listener.setTech(-20, 00, 0f, -300, 400);
+
+ listener.setTech(-20, 00, -300, 0f, 2);
window.display();
-
- listener.setTech(-20, 00, 0f, -150, 800);
+
+ listener.setTech(-20, 00, -150, 0f, 3);
window.display();
-
- listener.setTech(-20, 00, 0f, -50, 1000);
+
+ listener.setTech(-20, 00, -50, 0f, 4);
window.display();
-
- destroyWindow(window);
+
+ destroyWindow(window);
}
-
- @Test
- public void testRegionRendererMSAA02() throws InterruptedException {
- if(Platform.CPUFamily.X86 != Platform.CPU_ARCH.family) { // FIXME
+
+ // @Test
+ public void test11RegionRendererMSAA02() throws InterruptedException {
+ if(Platform.CPUFamily.X86 != PlatformPropsImpl.CPU_ARCH.family) { // FIXME
// FIXME: Disabled for now - since it doesn't seem fit for mobile (performance wise).
// FIXME: Also the GLSL code for VARIABLE_CURVE is not fit for mobile yet!
System.err.println("disabled on non desktop (x86) arch for now ..");
return;
}
- GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
- GLWindow window = createWindow("shape-vbaa0-msaa1", caps, 800, 400);
- RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
+ final GLWindow window = createWindow("shape-vbaa0-msaa1", caps, 800, 400);
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
- GPURegionGLListener01 demo01Listener = new GPURegionGLListener01 (rs, Region.VARIABLE_CURVE_WEIGHT_BIT, 0, false, false);
- demo01Listener.attachInputListenerTo(window);
+ final GPURegionGLListener01 demo01Listener = new GPURegionGLListener01 (rs, Region.VARWEIGHT_RENDERING_BIT, 0, false, false);
+ demo01Listener.attachInputListenerTo(window);
window.addGLEventListener(demo01Listener);
-
- RegionGLListener listener = new RegionGLListener(demo01Listener, window.getTitle(), "GPURegion02");
+
+ final RegionGLListener listener = new RegionGLListener(demo01Listener, window.getTitle(), "GPURegion02");
window.addGLEventListener(listener);
-
- listener.setTech(-20, 00, 0f, -300, 400);
+
+ listener.setTech(-20, 00, -300, 0f, 2);
window.display();
-
- listener.setTech(-20, 00, 0f, -150, 800);
+
+ listener.setTech(-20, 00, -150, 0f, 3);
window.display();
-
- listener.setTech(-20, 00, 0f, -50, 1000);
+
+ listener.setTech(-20, 00, -50, 0f, 4);
window.display();
-
- destroyWindow(window);
+
+ destroyWindow(window);
}
-
- private class RegionGLListener implements GLEventListener {
+
+ @Test
+ public void test20RegionRendererR2T01() throws InterruptedException {
+ if(Platform.CPUFamily.X86 != PlatformPropsImpl.CPU_ARCH.family) { // FIXME
+ // FIXME: Disabled for now - since it doesn't seem fit for mobile (performance wise).
+ System.err.println("disabled on non desktop (x86) arch for now ..");
+ return;
+ }
+ final GLProfile glp = GLProfile.getGL2ES2();
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ //caps.setOnscreen(false);
+ caps.setAlphaBits(4);
+
+ final GLWindow window = createWindow("shape-vbaa1-msaa0", caps, 800,400);
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+ final GPURegionGLListener02 demo02Listener = new GPURegionGLListener02 (rs, Region.VBAA_RENDERING_BIT, 4, false, false);
+ demo02Listener.attachInputListenerTo(window);
+ window.addGLEventListener(demo02Listener);
+
+ final RegionGLListener listener = new RegionGLListener(demo02Listener, window.getTitle(), "GPURegionNewtDemo02");
+ window.addGLEventListener(listener);
+
+ listener.setTech(-20, 00, -300, 0f, 2);
+ window.display();
+
+ listener.setTech(-20, 00, -150, 0f, 3);
+ window.display();
+
+ listener.setTech(-20, 00, -50, 0f, 4);
+ window.display();
+
+ destroyWindow(window);
+ }
+
+ private static class RegionGLListener implements GLEventListener {
String winTitle;
String name;
- GPURegionRendererListenerBase01 impl;
-
- public RegionGLListener(GPURegionRendererListenerBase01 impl, String title, String name) {
+ GPURendererListenerBase01 impl;
+
+ public RegionGLListener(final GPURendererListenerBase01 impl, final String title, final String name) {
this.impl = impl;
this.winTitle = title;
this.name = name;
}
-
- public void setTech(float xt, float yt, float angle, int zoom, int fboSize){
- impl.setMatrix(xt, yt, angle, zoom, fboSize);
+
+ public void setTech(final float xt, final float yt, final int zt, final float angle, final int sampleCount){
+ impl.setMatrix(xt, yt, zt, angle, sampleCount);
}
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
impl.init(drawable);
}
-
- public void display(GLAutoDrawable drawable) {
+
+ public void display(final GLAutoDrawable drawable) {
impl.display(drawable);
try {
impl.printScreen(drawable, "./", winTitle, name, false);
- } catch (GLException e) {
+ } catch (final GLException e) {
e.printStackTrace();
- } catch (IOException e) {
+ } catch (final IOException e) {
e.printStackTrace();
}
}
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
impl.dispose(drawable);
-
+
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
impl.reshape(drawable, x, y, width, height);
-
+
}
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
index b22be0a93..2f67466a9 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
@@ -29,84 +29,136 @@ package com.jogamp.opengl.test.junit.graph;
import java.io.File;
import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import java.net.URL;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
-import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
import org.junit.Assert;
-import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import com.jogamp.common.os.Platform;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.curve.opengl.TextRenderer;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
-import com.jogamp.graph.geom.AABBox;
-import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.graph.geom.SVertex;
+import com.jogamp.newt.Window;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
-import com.jogamp.opengl.util.glsl.ShaderState;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTextRendererNEWT00 extends UITestCase {
static final boolean DEBUG = false;
static final boolean TRACE = false;
- static long duration = 100; // ms
-
- static final float[] textPosition = new float[] {0,0,0};
- static final int[] texSize = new int[] { 0 };
- static final int fontSize = 24;
- static Font font;
-
- @BeforeClass
- public static void setup() throws IOException {
- font = FontFactory.get(FontFactory.UBUNTU).getDefault();
- }
-
- static int atoi(String a) {
+ static long Duration = 2000; // ms
+ static boolean WaitStartEnd = false;
+ static boolean TextAnim = false;
+ static int SceneMSAASamples = 0;
+ static int GraphVBAASamples = 0;
+ static int GraphMSAASamples = 0;
+ static boolean ManualTest = false;
+ static int SwapInterval = 0;
+
+ static String fontFileName = null;
+ static URL fontURL = null;
+ static int fontSet = 0;
+ static int fontFamily = 0;
+ static int fontStylebits = 0;
+ static float fontSizeFixed = 14f;
+
+ static int atoi(final String a) {
try {
return Integer.parseInt(a);
- } catch (Exception ex) { throw new RuntimeException(ex); }
+ } catch (final Exception ex) { throw new RuntimeException(ex); }
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
+ ManualTest = args.length > 0;
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
- duration = atoi(args[i]);
+ Duration = atoi(args[i]);
+ } else if(args[i].equals("-fontURL")) {
+ i++;
+ fontURL = new URL(args[i]);
+ } else if(args[i].equals("-fontFile")) {
+ i++;
+ fontFileName = args[i];
+ } else if(args[i].equals("-fontSet")) {
+ i++;
+ fontSet = atoi(args[i]);
+ } else if(args[i].equals("-fontFamily")) {
+ i++;
+ fontFamily = atoi(args[i]);
+ } else if(args[i].equals("-fontStyle")) {
+ i++;
+ fontStylebits = atoi(args[i]);
+ } else if(args[i].equals("-fontSize")) {
+ i++;
+ fontSizeFixed = atoi(args[i]);
+ } else if(args[i].equals("-smsaa")) {
+ i++;
+ SceneMSAASamples = atoi(args[i]);
+ } else if(args[i].equals("-gmsaa")) {
+ i++;
+ GraphMSAASamples = atoi(args[i]);
+ } else if(args[i].equals("-gvbaa")) {
+ i++;
+ GraphVBAASamples = atoi(args[i]);
+ } else if(args[i].equals("-textAnim")) {
+ TextAnim = true;
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ SwapInterval = MiscUtils.atoi(args[i], SwapInterval);
+ } else if(args[i].equals("-wait")) {
+ WaitStartEnd = true;
}
}
- String tstname = TestTextRendererNEWT00.class.getName();
+ System.err.println("Font [set "+fontSet+", family "+fontFamily+", style "+fontStylebits+", size "+fontSizeFixed+"], fontFileName "+fontFileName);
+ System.err.println("Scene MSAA Samples "+SceneMSAASamples);
+ System.err.println("Graph MSAA Samples "+GraphMSAASamples);
+ System.err.println("Graph VBAA Samples "+GraphVBAASamples);
+ System.err.println("swapInterval "+SwapInterval);
+ final String tstname = TestTextRendererNEWT00.class.getName();
org.junit.runner.JUnitCore.main(tstname);
- }
-
+ }
+
static void sleep() {
+ sleep(Duration);
+ }
+ static void sleep(final long d) {
try {
- System.err.println("** new frame ** (sleep: "+duration+"ms)");
- Thread.sleep(duration);
- } catch (InterruptedException ie) {}
+ System.err.println("** new frame ** (sleep: "+d+"ms)");
+ Thread.sleep(d);
+ } catch (final InterruptedException ie) {}
}
-
- static void destroyWindow(GLWindow window) {
+
+ static void destroyWindow(final GLWindow window) {
if(null!=window) {
window.destroy();
}
}
- static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) {
+ static GLWindow createWindow(final String title, final GLCapabilitiesImmutable caps, final int width, final int height) {
Assert.assertNotNull(caps);
- GLWindow window = GLWindow.create(caps);
+ final GLWindow window = GLWindow.create(caps);
window.setSize(width, height);
window.setPosition(10, 10);
window.setTitle(title);
@@ -115,122 +167,255 @@ public class TestTextRendererNEWT00 extends UITestCase {
return window;
}
-
+
+ @Test
+ public void test00Manual() throws InterruptedException {
+ if( ManualTest ) {
+ testImpl(SceneMSAASamples, GraphMSAASamples, GraphVBAASamples);
+ }
+ }
@Test
- public void testTextRendererMSAA01() throws InterruptedException {
- GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
- caps.setSampleBuffers(true);
- caps.setNumSamples(4);
- System.err.println("Requested: "+caps);
-
- GLWindow window = createWindow("text-vbaa0-msaa1", caps, 800, 400);
+ public void test00SceneNoAA() throws InterruptedException {
+ if( !ManualTest ) {
+ testImpl(0, 0, 0);
+ }
+ }
+ @Test
+ public void test01SceneMSAA04() throws InterruptedException {
+ if( !ManualTest ) {
+ testImpl(4, 0, 0);
+ }
+ }
+ @Test
+ public void test02GraphMSAA04() throws InterruptedException {
+ if( !ManualTest ) {
+ testImpl(0, 4, 0);
+ }
+ }
+ @Test
+ public void test03GraphVBAA04() throws InterruptedException {
+ if( !ManualTest ) {
+ testImpl(0, 0, 4);
+ }
+ }
+
+ public void testImpl(final int sceneMSAASamples, final int graphMSAASamples, final int graphVBAASamples) throws InterruptedException {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
+ if( 0 < sceneMSAASamples ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(sceneMSAASamples);
+ }
+ System.err.println("Requested: "+caps+", graph[msaaSamples "+graphMSAASamples+", vbaaSamples "+graphVBAASamples+"]");
+
+ final GLWindow window = createWindow("text-gvbaa"+graphVBAASamples+"-gmsaa"+graphMSAASamples+"-smsaa"+sceneMSAASamples, caps, 1024, 640);
window.display();
System.err.println("Chosen: "+window.getChosenGLCapabilities());
-
- final RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- final TextRendererListener textGLListener = new TextRendererListener(rs);
- final TextRenderer renderer = textGLListener.getRenderer();
+ if( WaitStartEnd ) {
+ UITestCase.waitForKey("Start");
+ }
+
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+ final int renderModes, sampleCount;
+ if( graphVBAASamples > 0 ) {
+ renderModes = Region.VBAA_RENDERING_BIT;
+ sampleCount = graphVBAASamples;
+ } else if ( graphMSAASamples > 0 ) {
+ renderModes = Region.MSAA_RENDERING_BIT;
+ sampleCount = graphMSAASamples;
+ } else {
+ renderModes = 0;
+ sampleCount = 0;
+ }
+ final TextRendererGLEL textGLListener = new TextRendererGLEL(rs, renderModes, sampleCount);
+ System.err.println(textGLListener.getFontInfo());
+
window.addGLEventListener(textGLListener);
+ final Animator anim = new Animator();
+ anim.add(window);
+ anim.start();
+ anim.setUpdateFPSFrames(60, null);
+ sleep();
window.invoke(true, new GLRunnable() {
@Override
- public boolean run(GLAutoDrawable drawable) {
- int c=0;
- renderString(drawable, renderer, "GlueGen", c++, -1, -1000);
- renderString(drawable, renderer, "JOAL", c++, -1, -1000);
- renderString(drawable, renderer, "JOGL", c++, -1, -1000);
- renderString(drawable, renderer, "JOCL", c++, -1, -1000);
+ public boolean run(final GLAutoDrawable drawable) {
try {
- textGLListener.printScreen(drawable, "./", "TestTextRendererNEWT00-snap"+screenshot_num, false);
- } catch (Exception e) {
+ textGLListener.printScreen(renderModes, drawable, "./", "TestTextRendererNEWT00-snap"+screenshot_num, false);
+ screenshot_num++;
+ } catch (final Exception e) {
e.printStackTrace();
}
return true;
- }
+ }
});
- sleep();
-
- destroyWindow(window);
- }
- int screenshot_num = 0;
-
- int lastRow = -1;
-
- void renderString(GLAutoDrawable drawable, TextRenderer renderer, String text, int column, int row, int z0) {
- final GL2ES2 gl = drawable.getGL().getGL2ES2();
- final int height = drawable.getHeight();
-
- int dx = 0;
- int dy = height;
- if(0>row) {
- row = lastRow + 1;
- }
- AABBox textBox = font.getStringBounds(text, fontSize);
- dx += font.getAdvanceWidth('X', fontSize) * column;
- dy -= (int)textBox.getHeight() * ( row + 1 );
- renderer.resetModelview(null);
- renderer.translate(gl, dx, dy, z0);
- renderer.drawString3D(gl, font, text, textPosition, fontSize, texSize);
-
- lastRow = row;
+ anim.stop();
+ if( WaitStartEnd ) {
+ UITestCase.waitForKey("Stop");
+ }
+ destroyWindow(window);
}
-
- public class TextRendererListener implements GLEventListener {
- private GLReadBufferUtil screenshot;
- private TextRenderer renderer;
-
- public TextRendererListener(RenderState rs) {
+ int screenshot_num = 0;
+
+ static final String textX2 =
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec sapien tellus. \n"+
+ "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+
+ "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices ultricies nec a elit. \n"+
+ "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia pharetra at venenatis est.\n"+
+ "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat nec, volutpat nec nisi.\n"+
+ "Donec ut dolor et nulla tristique varius. In nulla magna, fermentum id tempus quis, semper \n"+
+ "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin. Quisque sit amet neque lorem,\n" +
+ "-------Press H to change text---------\n";
+
+ private static final class TextRendererGLEL extends TextRendererGLELBase {
+ private final GLReadBufferUtil screenshot;
+ private final GLRegion regionFPS, regionFPSAnim;
+ final Font font;
+ final float fontSizeMin, fontSizeMax;
+ private long t0;
+ float fontSizeAnim, fontSizeDelta;
+ float dpiH;
+
+ TextRendererGLEL(final RenderState rs, final int renderModes, final int sampleCount) {
+ super(renderModes, new int[] { sampleCount });
+ setRendererCallbacks(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
+ setRenderState(rs);
+
+ regionFPS = GLRegion.create(renderModes, null);
+ regionFPSAnim = GLRegion.create(renderModes, null);
+ if( null != fontURL ) {
+ Font _font = null;
+ try {
+ _font = FontFactory.get(fontURL.openStream(), true);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ font = _font;
+ } else if( null != fontFileName ) {
+ Font _font = null;
+ try {
+ _font = FontFactory.get(getClass(), fontFileName, false);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ font = _font;
+ } else {
+ font = getFont(fontSet, fontFamily, fontStylebits);
+ }
+
+ staticRGBAColor[0] = 0.1f;
+ staticRGBAColor[1] = 0.1f;
+ staticRGBAColor[2] = 0.1f;
+ staticRGBAColor[3] = 1.0f;
+
this.screenshot = new GLReadBufferUtil(false, false);
- this.renderer = TextRenderer.create(rs, 0);
- }
-
- public final TextRenderer getRenderer() { return renderer; }
-
- public void printScreen(GLAutoDrawable drawable, String dir, String objName, boolean exportAlpha) throws GLException, IOException {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- pw.printf("%s-%03dx%03d-T%04d", objName, drawable.getWidth(), drawable.getHeight(), texSize[0]);
-
- final String filename = dir + sw +".png";
+ // fontSizeMin = Math.max(8, fontSizeFixed-5);
+ fontSizeMin = fontSizeFixed;
+ fontSizeMax = fontSizeFixed+8;
+ fontSizeAnim = fontSizeFixed;
+ fontSizeDelta = 0.01f;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ super.init(drawable);
+ drawable.getGL().setSwapInterval(SwapInterval);
+ t0 = Platform.currentTimeMillis();
+
+ final Window win = (Window)drawable.getUpstreamWidget();
+ final float[] pixelsPerMM = win.getPixelsPerMM(new float[2]);
+ final float[] dotsPerInch = new float[] { pixelsPerMM[0]*25.4f, pixelsPerMM[1]*25.4f };
+ dpiH = dotsPerInch[1];
+ System.err.println(getFontInfo());
+ System.err.println("fontSize "+fontSizeFixed+", dotsPerMM "+pixelsPerMM[0]+"x"+pixelsPerMM[1]+", dpi "+dotsPerInch[0]+"x"+dotsPerInch[1]+", pixelSize "+font.getPixelSize(fontSizeFixed, dotsPerInch[1] /* dpi display */));
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ screenshot.dispose(gl);
+ regionFPS.destroy(gl);
+ regionFPSAnim.destroy(gl);
+ super.dispose(drawable);
+ }
+
+ public void printScreen(final int renderModes, final GLAutoDrawable drawable, final String dir, final String objName, final boolean exportAlpha) throws GLException, IOException {
+ final String modeS = Region.getRenderModeString(renderModes);
+ final String bname = String.format("%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName,
+ drawable.getChosenGLCapabilities().getNumSamples(),
+ TestTextRendererNEWT00.fontSizeFixed, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), modeS, vbaaSampleCount[0]);
+ final String filename = dir + bname +".png";
if(screenshot.readPixels(drawable.getGL(), false)) {
screenshot.write(new File(filename));
}
}
-
- public void init(GLAutoDrawable drawable) {
- final GL2ES2 gl = drawable.getGL().getGL2ES2();
- gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- renderer.init(gl);
- renderer.setAlpha(gl, 1.0f);
- renderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f);
+
+ String getFontInfo() {
+ final float unitsPerEM_Inv = font.getMetrics().getScale(1f);
+ final float unitsPerEM = 1f / unitsPerEM_Inv;
+ return String.format("Font %s%n %s%nunitsPerEM %f (upem)",
+ font.getFullFamilyName(null).toString(),
+ font.getName(Font.NAME_UNIQUNAME),
+ unitsPerEM);
}
-
- public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height) {
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- gl.glViewport(xstart, ystart, width, height);
- // renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 1000.0f);
- renderer.reshapeOrtho(gl, width, height, 0.1f, 1000.0f);
- }
-
- public void display(GLAutoDrawable drawable) {
- final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
-
- renderString(drawable, renderer, "012345678901234567890123456789", 0, 0, -1000);
- renderString(drawable, renderer, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0, -1, -1000);
- renderString(drawable, renderer, "Hello World", 0, -1, -1000);
- renderString(drawable, renderer, "4567890123456", 4, -1, -1000);
- renderString(drawable, renderer, "I like JogAmp", 4, -1, -1000);
- }
-
- public void dispose(GLAutoDrawable drawable) {
- final GL2ES2 gl = drawable.getGL().getGL2ES2();
- screenshot.dispose(gl);
- renderer.destroy(gl);
- }
- }
+
+ final GLAnimatorControl anim = drawable.getAnimator();
+ final float lfps = null != anim ? anim.getLastFPS() : 0f;
+ final float tfps = null != anim ? anim.getTotalFPS() : 0f;
+
+ // Note: MODELVIEW is from [ 0 .. height ]
+
+ final long t1 = Platform.currentTimeMillis();
+
+ // final float fontSize = TestTextRendererNEWT00.fontSize;
+
+ fontSizeAnim += fontSizeDelta;
+ if( fontSizeMin >= fontSizeAnim || fontSizeAnim >= fontSizeMax ) {
+ fontSizeDelta *= -1f;
+ }
+
+ final float pixelSize = font.getPixelSize(fontSizeFixed, dpiH);
+ final float pixelSizeAnim = font.getPixelSize(fontSizeAnim, dpiH);
+
+ final String modeS = Region.getRenderModeString(renderModes);
+
+ if( false ) {
+ // renderString(drawable, font, pixelSize, "I - / H P 7 0", 0, 0, 0, 0, -1000f, true);
+ // renderString(drawable, font, pixelSize, "A M > } ] ", 0, 0, 0, 0, -1000f, true);
+ // renderString(drawable, font, pixelSize, "M", 0, 0, 0, 0, -1000f, true);
+ // renderString(drawable, font, pixelSize, "0 6 9 a b O Q A M > } ] ", 0, 0, 0, 0, -1000f, true);
+ // renderString(drawable, font, pixelSize, "012345678901234567890123456789", 0, 0, 0, -1000, true);
+ // renderString(drawable, font, pixelSize, textX2, 0, 0, 0, 0, -1000f, true);
+ // renderString(drawable, font, pixelSize, text1, 0, 0, 0, -1000f, regionFPS); // no-cache
+ final String text1 = lfps+" / "+tfps+" fps, vsync "+gl.getSwapInterval()+", elapsed "+(t1-t0)/1000.0+
+ " s, fontSize "+fontSizeFixed+", msaa "+drawable.getChosenGLCapabilities().getNumSamples()+
+ ", "+modeS+"-samples "+vbaaSampleCount[0];
+ renderString(drawable, font, pixelSize, text1, 0, 0, 0, 0, -1000, regionFPS); // no-cache
+ } else {
+ final String text1 = String.format("%03.1f/%03.1f fps, vsync %d, elapsed %4.1f s, fontSize %2.2f, msaa %d, %s-samples %d",
+ lfps, tfps, gl.getSwapInterval(), (t1-t0)/1000.0, fontSizeFixed,
+ drawable.getChosenGLCapabilities().getNumSamples(), modeS, vbaaSampleCount[0]);
+ renderString(drawable, font, pixelSize, getFontInfo(), 0, 0, 0, 0, -1000, true);
+ renderString(drawable, font, pixelSize, "012345678901234567890123456789", 0, 0, 0, -1000, true);
+ renderString(drawable, font, pixelSize, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0, 0, 0, -1000, true);
+ renderString(drawable, font, pixelSize, "Hello World", 0, 0, 0, -1000, true);
+ renderString(drawable, font, pixelSize, "4567890123456", 4, 0, 0, -1000, true);
+ renderString(drawable, font, pixelSize, "I like JogAmp", 4, 0, 0, -1000, true);
+ renderString(drawable, font, pixelSize, "Hello World", 0, 0, 0, -1000, true);
+ renderString(drawable, font, pixelSize, textX2, 0, 0, 0, -1000, true);
+ renderString(drawable, font, pixelSize, text1, 0, 0, 0, -1000, regionFPS); // no-cache
+ if( TextAnim ) {
+ renderString(drawable, font, pixelSizeAnim, text1, 0, 0, 0, -1000, regionFPSAnim); // no-cache
+ }
+ }
+ } };
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java
index ea02e930c..26fc2e07c 100755..100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java
@@ -37,60 +37,63 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import jogamp.common.os.PlatformPropsImpl;
+
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.os.Platform;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.curve.opengl.TextRenderer;
import com.jogamp.graph.font.FontFactory;
-import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.graph.geom.SVertex;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.graph.demos.GPUTextRendererListenerBase01;
import com.jogamp.opengl.test.junit.util.UITestCase;
-import com.jogamp.opengl.util.glsl.ShaderState;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTextRendererNEWT01 extends UITestCase {
static final boolean DEBUG = false;
static final boolean TRACE = false;
static long duration = 100; // ms
- static int atoi(String a) {
+ static int atoi(final String a) {
try {
return Integer.parseInt(a);
- } catch (Exception ex) { throw new RuntimeException(ex); }
+ } catch (final Exception ex) { throw new RuntimeException(ex); }
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
duration = atoi(args[i]);
}
}
- String tstname = TestTextRendererNEWT01.class.getName();
+ final String tstname = TestTextRendererNEWT01.class.getName();
org.junit.runner.JUnitCore.main(tstname);
- }
-
+ }
+
static void sleep() {
try {
System.err.println("** new frame ** (sleep: "+duration+"ms)");
Thread.sleep(duration);
- } catch (InterruptedException ie) {}
+ } catch (final InterruptedException ie) {}
}
-
- static void destroyWindow(GLWindow window) {
+
+ static void destroyWindow(final GLWindow window) {
if(null!=window) {
window.destroy();
}
}
- static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) {
+ static GLWindow createWindow(final String title, final GLCapabilitiesImmutable caps, final int width, final int height) {
Assert.assertNotNull(caps);
- GLWindow window = GLWindow.create(caps);
+ final GLWindow window = GLWindow.create(caps);
window.setSize(width, height);
window.setPosition(10, 10);
window.setTitle(title);
@@ -102,85 +105,85 @@ public class TestTextRendererNEWT01 extends UITestCase {
@Test
public void testTextRendererR2T01() throws InterruptedException {
- if(Platform.CPUFamily.X86 != Platform.CPU_ARCH.family) { // FIXME
+ if(Platform.CPUFamily.X86 != PlatformPropsImpl.CPU_ARCH.family) { // FIXME
// FIXME: Disabled for now - since it doesn't seem fit for mobile (performance wise).
System.err.println("disabled on non desktop (x86) arch for now ..");
return;
}
- GLProfile glp = GLProfile.getGL2ES2();
-
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
+ final GLProfile glp = GLProfile.getGL2ES2();
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
System.err.println("Requested: "+caps);
- GLWindow window = createWindow("text-vbaa1-msaa0", caps, 800,400);
+ final GLWindow window = createWindow("text-vbaa1-msaa0", caps, 800,400);
window.display();
System.err.println("Chosen: "+window.getChosenGLCapabilities());
-
- RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- TextGLListener textGLListener = new TextGLListener(rs, Region.VBAA_RENDERING_BIT, DEBUG, TRACE);
+
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+ final TextGLListener textGLListener = new TextGLListener(rs, Region.VBAA_RENDERING_BIT, DEBUG, TRACE);
textGLListener.attachInputListenerTo(window);
window.addGLEventListener(textGLListener);
-
+
if(textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0)) {
- textGLListener.setTech(-400, -30, 0f, -1000, window.getWidth()*2);
+ textGLListener.setTech(-400, -30, 0f, -1000, 2);
window.display();
sleep();
-
- textGLListener.setTech(-400, -30, 0, -380, window.getWidth()*3);
+
+ textGLListener.setTech(-400, -30, 0f, -380, 3);
window.display();
sleep();
-
- textGLListener.setTech(-400, -20, 0, -80, window.getWidth()*4);
+
+ textGLListener.setTech(-400, -20, 0f, -80, 4);
window.display();
sleep();
}
if(textGLListener.setFontSet(FontFactory.JAVA, 0, 0)) {
- textGLListener.setTech(-400, -30, 0f, -1000, window.getWidth()*2);
+ textGLListener.setTech(-400, -30, 0f, -1000, 2);
window.display();
sleep();
-
- textGLListener.setTech(-400, -30, 0, -380, window.getWidth()*3);
+
+ textGLListener.setTech(-400, -30, 0f, -380, 3);
window.display();
sleep();
-
- textGLListener.setTech(-400, -20, 0, -80, window.getWidth()*4);
+
+ textGLListener.setTech(-400, -20, 0f, -80, 4);
window.display();
sleep();
}
-
- destroyWindow(window);
+
+ destroyWindow(window);
}
-
+
@Test
public void testTextRendererMSAA01() throws InterruptedException {
- GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
System.err.println("Requested: "+caps);
- GLWindow window = createWindow("text-vbaa0-msaa1", caps, 800, 400);
+ final GLWindow window = createWindow("text-vbaa0-msaa1", caps, 800, 400);
window.display();
System.err.println("Chosen: "+window.getChosenGLCapabilities());
-
- RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- TextGLListener textGLListener = new TextGLListener(rs, 0, DEBUG, TRACE);
+
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+ final TextGLListener textGLListener = new TextGLListener(rs, 0, DEBUG, TRACE);
textGLListener.attachInputListenerTo(window);
window.addGLEventListener(textGLListener);
-
+
if(textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0)) {
textGLListener.setTech(-400, -30, 0f, -1000, 0);
window.display();
sleep();
-
- textGLListener.setTech(-400, -30, 0, -380, 0);
+
+ textGLListener.setTech(-400, -30, 0, -380, 0);
window.display();
sleep();
-
- textGLListener.setTech(-400, -20, 0, -80, 0);
+
+ textGLListener.setTech(-400, -20, 0, -80, 0);
window.display();
sleep();
}
@@ -189,55 +192,53 @@ public class TestTextRendererNEWT01 extends UITestCase {
textGLListener.setTech(-400, -30, 0f, -1000, 0);
window.display();
sleep();
-
- textGLListener.setTech(-400, -30, 0, -380, 0);
+
+ textGLListener.setTech(-400, -30, 0, -380, 0);
window.display();
sleep();
-
- textGLListener.setTech(-400, -20, 0, -80, 0);
+
+ textGLListener.setTech(-400, -20, 0, -80, 0);
window.display();
sleep();
}
-
- destroyWindow(window);
+
+ destroyWindow(window);
}
-
- private class TextGLListener extends GPUTextRendererListenerBase01 {
+
+ private static class TextGLListener extends GPUTextRendererListenerBase01 {
String winTitle;
-
- public TextGLListener(RenderState rs, int type, boolean debug, boolean trace) {
- super(rs, type, debug, trace);
+
+ public TextGLListener(final RenderState rs, final int type, final boolean debug, final boolean trace) {
+ super(rs, type, 4, true, debug, trace);
}
-
- public void attachInputListenerTo(GLWindow window) {
+
+ public void attachInputListenerTo(final GLWindow window) {
super.attachInputListenerTo(window);
winTitle = window.getTitle();
}
- public void setTech(float xt, float yt, float angle, int zoom, int fboSize){
- setMatrix(xt, yt, angle, zoom, fboSize);
+ public void setTech(final float xt, final float yt, final float angle, final int zoom, final int sampleCount){
+ setMatrix(xt, yt, zoom, angle, sampleCount);
}
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
super.init(drawable);
-
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
gl.setSwapInterval(1);
gl.glEnable(GL.GL_DEPTH_TEST);
-
- final TextRenderer textRenderer = (TextRenderer) getRenderer();
-
- textRenderer.setAlpha(gl, 1.0f);
- textRenderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f);
+
+ final RenderState rs = getRenderer().getRenderState();
+ rs.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f);
}
-
- public void display(GLAutoDrawable drawable) {
+
+ public void display(final GLAutoDrawable drawable) {
super.display(drawable);
try {
printScreen(drawable, "./", winTitle, false);
- } catch (GLException e) {
+ } catch (final GLException e) {
e.printStackTrace();
- } catch (IOException e) {
+ } catch (final IOException e) {
e.printStackTrace();
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java
index ff7eb4ed1..78dc87489 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java
@@ -27,142 +27,228 @@
*/
package com.jogamp.opengl.test.junit.graph;
+import java.io.File;
import java.io.IOException;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.curve.opengl.TextRenderer;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.curve.opengl.TextRegionUtil;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
-import com.jogamp.graph.geom.AABBox;
-import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.graph.geom.SVertex;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.NEWTGLContext;
import com.jogamp.opengl.test.junit.util.UITestCase;
-import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.PMVMatrix;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTextRendererNEWT10 extends UITestCase {
static final boolean DEBUG = false;
static final boolean TRACE = false;
static long duration = 100; // ms
-
- static final float[] textPosition = new float[] {0,0,0};
- static final int[] texSize = new int[] { 0 };
- static final int fontSize = 24;
+ static boolean forceES2 = false;
+ static boolean forceGL3 = false;
+ static boolean mainRun = false;
+ static boolean useMSAA = true;
+
static Font font;
+ static float fontSize = 24;
+ static String customStr = null;
@BeforeClass
public static void setup() throws IOException {
- font = FontFactory.get(FontFactory.UBUNTU).getDefault();
+ if( null == font ) {
+ font = FontFactory.get(FontFactory.UBUNTU).getDefault();
+ // font = FontFactory.get(FontFactory.JAVA).getDefault();
+ }
}
-
- static int atoi(String a) {
+
+ static int atoi(final String a) {
try {
return Integer.parseInt(a);
- } catch (Exception ex) { throw new RuntimeException(ex); }
+ } catch (final Exception ex) { throw new RuntimeException(ex); }
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
+ mainRun = true;
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
duration = atoi(args[i]);
+ } else if(args[i].equals("-noMSAA")) {
+ useMSAA = false;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-font")) {
+ i++;
+ font = FontFactory.get(IOUtil.getResource(TestTextRendererNEWT10.class, args[i]).getInputStream(), true);
+ } else if(args[i].equals("-fontSize")) {
+ i++;
+ fontSize = MiscUtils.atof(args[i], fontSize);
+ } else if(args[i].equals("-text")) {
+ i++;
+ customStr = args[i];
}
}
- String tstname = TestTextRendererNEWT10.class.getName();
+ final String tstname = TestTextRendererNEWT10.class.getName();
org.junit.runner.JUnitCore.main(tstname);
- }
-
+ }
+
static void sleep() {
try {
System.err.println("** new frame ** (sleep: "+duration+"ms)");
Thread.sleep(duration);
- } catch (InterruptedException ie) {}
+ } catch (final InterruptedException ie) {}
}
-
+
@Test
- public void testTextRendererMSAA01() throws InterruptedException {
- GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
- caps.setSampleBuffers(true);
- caps.setNumSamples(4);
+ public void test00TextRendererNONE00() throws InterruptedException, GLException, IOException {
+ testTextRendererImpl(0, 0);
+ }
+
+ @Test
+ public void test01TextRendererMSAA04() throws InterruptedException, GLException, IOException {
+ testTextRendererImpl(0, 4);
+ }
+
+ @Test
+ public void test02TextRendererVBAA04() throws InterruptedException, GLException, IOException {
+ testTextRendererImpl(Region.VBAA_RENDERING_BIT, 4);
+ }
+
+ void testTextRendererImpl(final int renderModes, final int sampleCount) throws InterruptedException, GLException, IOException {
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+
+ final GLCapabilities caps = new GLCapabilities( glp );
+ caps.setAlphaBits(4);
+ if( 0 < sampleCount && !Region.isVBAA(renderModes) ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(sampleCount);
+ }
System.err.println("Requested: "+caps);
+ System.err.println("Requested: "+Region.getRenderModeString(renderModes));
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow(caps, 800, 400, true);
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(caps, 800, 400, true);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL2ES2 gl = winctx.context.getGL().getGL2ES2();
- System.err.println(winctx.context);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
System.err.println("Chosen: "+winctx.window.getChosenCapabilities());
-
- final RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- final TextRenderer renderer = TextRenderer.create(rs, 0);
+
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+ final RegionRenderer renderer = RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
+ rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
+ final TextRegionUtil textRenderUtil = new TextRegionUtil(renderModes);
// init
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- renderer.init(gl);
- renderer.setAlpha(gl, 1.0f);
- renderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f);
+ renderer.init(gl, 0);
+ rs.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f);
+ screenshot = new GLReadBufferUtil(false, false);
// reshape
- gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
+ gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
// renderer.reshapePerspective(gl, 45.0f, drawable.getWidth(), drawable.getHeight(), 0.1f, 1000.0f);
- renderer.reshapeOrtho(gl, drawable.getWidth(), drawable.getHeight(), 0.1f, 1000.0f);
+ renderer.reshapeOrtho(drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), 0.1f, 1000.0f);
+ final int[] sampleCountIO = { sampleCount };
// display
- gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- renderString(drawable, gl, renderer, "012345678901234567890123456789", 0, 0, -1000);
- renderString(drawable, gl, renderer, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0, -1, -1000);
- renderString(drawable, gl, renderer, "Hello World", 0, -1, -1000);
- renderString(drawable, gl, renderer, "4567890123456", 4, -1, -1000);
- renderString(drawable, gl, renderer, "I like JogAmp", 4, -1, -1000);
-
- int c = 0;
- renderString(drawable, gl, renderer, "GlueGen", c++, -1, -1000);
- renderString(drawable, gl, renderer, "JOAL", c++, -1, -1000);
- renderString(drawable, gl, renderer, "JOGL", c++, -1, -1000);
- renderString(drawable, gl, renderer, "JOCL", c++, -1, -1000);
-
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ if( null == customStr ) {
+ renderString(drawable, gl, renderer, textRenderUtil, "012345678901234567890123456789", 0, 0, -1000, sampleCountIO);
+ renderString(drawable, gl, renderer, textRenderUtil, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0, -1, -1000, sampleCountIO);
+ renderString(drawable, gl, renderer, textRenderUtil, "Hello World", 0, -1, -1000, sampleCountIO);
+ renderString(drawable, gl, renderer, textRenderUtil, "4567890123456", 4, -1, -1000,sampleCountIO);
+ renderString(drawable, gl, renderer, textRenderUtil, "I like JogAmp", 4, -1, -1000, sampleCountIO);
+
+ int c = 0;
+ renderString(drawable, gl, renderer, textRenderUtil, "GlueGen", c++, -1, -1000, sampleCountIO);
+ renderString(drawable, gl, renderer, textRenderUtil, "JOAL", c++, -1, -1000, sampleCountIO);
+ renderString(drawable, gl, renderer, textRenderUtil, "JOGL", c++, -1, -1000, sampleCountIO);
+ renderString(drawable, gl, renderer, textRenderUtil, "JOCL", c++, -1, -1000, sampleCountIO);
+ } else {
+ renderString(drawable, gl, renderer, textRenderUtil, customStr, 0, 0, -1000, sampleCountIO);
+ }
drawable.swapBuffers();
- sleep();
+ printScreen(renderModes, drawable, gl, false, sampleCount);
+
+ sleep();
// dispose
+ screenshot.dispose(gl);
renderer.destroy(gl);
-
+
NEWTGLContext.destroyWindow(winctx);
- }
- int screenshot_num = 0;
-
+ }
+
+ private GLReadBufferUtil screenshot;
int lastRow = -1;
-
- void renderString(GLDrawable drawable, GL2ES2 gl, TextRenderer renderer, String text, int column, int row, int z0) {
- final int height = drawable.getHeight();
-
+
+ void renderString(final GLDrawable drawable, final GL2ES2 gl, final RegionRenderer renderer, final TextRegionUtil textRenderUtil, final String text, final int column, int row, final int z0, final int[] sampleCount) {
+ final int height = drawable.getSurfaceHeight();
+
int dx = 0;
- int dy = height;
+ int dy = height;
if(0>row) {
row = lastRow + 1;
}
- AABBox textBox = font.getStringBounds(text, fontSize);
+ final AABBox textBox = font.getMetricBounds(text, fontSize);
dx += font.getAdvanceWidth('X', fontSize) * column;
dy -= (int)textBox.getHeight() * ( row + 1 );
- renderer.resetModelview(null);
- renderer.translate(gl, dx, dy, z0);
- renderer.drawString3D(gl, font, text, textPosition, fontSize, texSize);
-
+
+ final PMVMatrix pmv = renderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ pmv.glTranslatef(dx, dy, z0);
+ textRenderUtil.drawString3D(gl, renderer, font, fontSize, text, null, sampleCount);
+
lastRow = row;
- }
+ }
+
+ private int screenshot_num = 0;
+
+ public void printScreen(final int renderModes, final GLDrawable drawable, final GL gl, final boolean exportAlpha, final int sampleCount) throws GLException, IOException {
+ final String dir = "./";
+ final String objName = getSimpleTestName(".")+"-snap"+screenshot_num;
+ screenshot_num++;
+ final String modeS = Region.getRenderModeString(renderModes);
+ final String bname = String.format("%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName,
+ drawable.getChosenGLCapabilities().getNumSamples(),
+ TestTextRendererNEWT10.fontSize, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), modeS, sampleCount);
+ final String filename = dir + bname +".png";
+ if(screenshot.readPixels(gl, false)) {
+ screenshot.write(new File(filename));
+ }
+ }
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java
new file mode 100644
index 000000000..d6affd7e2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java
@@ -0,0 +1,224 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.curve.opengl.TextRegionUtil;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.geom.SVertex;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.test.junit.util.NEWTGLContext;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.PMVMatrix;
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTextRendererNEWTBugXXXX extends UITestCase {
+ static long duration = 100; // ms
+ static boolean forceES2 = false;
+ static boolean forceGL3 = false;
+ static boolean mainRun = false;
+ static boolean useMSAA = true;
+ static boolean onlyIssues = false;
+
+ static final float fontSize = 24;
+
+ static int atoi(final String a) {
+ try {
+ return Integer.parseInt(a);
+ } catch (final Exception ex) { throw new RuntimeException(ex); }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ mainRun = true;
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = atoi(args[i]);
+ } else if(args[i].equals("-noMSAA")) {
+ useMSAA = false;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ }
+ }
+ final String tstname = TestTextRendererNEWTBugXXXX.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+ static void sleep() {
+ try {
+ System.err.println("** new frame ** (sleep: "+duration+"ms)");
+ Thread.sleep(duration);
+ } catch (final InterruptedException ie) {}
+ }
+
+ @Test
+ public void test00All() throws InterruptedException, GLException, IOException {
+ testTextRendererImpl(FontSet01.getSet01(), Region.VBAA_RENDERING_BIT, 4, false);
+ }
+ @Test
+ public void test01OnlyIssues() throws InterruptedException, GLException, IOException {
+ testTextRendererImpl(FontSet01.getSet01(), Region.VBAA_RENDERING_BIT, 4, true);
+ }
+ void testTextRendererImpl(final Font[] fonts, final int renderModes, final int sampleCount, final boolean onlyIssues) throws InterruptedException, GLException, IOException {
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+
+ final GLCapabilities caps = new GLCapabilities( glp );
+ caps.setAlphaBits(4);
+ if( 0 < sampleCount && !Region.isVBAA(renderModes) ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(sampleCount);
+ }
+ caps.setOnscreen(false);
+ System.err.println("Requested: "+caps);
+ System.err.println("Requested: "+Region.getRenderModeString(renderModes));
+
+ final int totalHeight = ( (int)fontSize + 1 ) * ( onlyIssues ? 3 : 6 ) * fonts.length;
+ final NEWTGLContext.WindowContext winctx =
+ NEWTGLContext.createWindow(caps, 800, totalHeight, true);
+ final GLDrawable drawable = winctx.context.getGLDrawable();
+ final GL2ES2 gl = winctx.context.getGL().getGL2ES2();
+
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ System.err.println("Chosen: "+winctx.window.getChosenCapabilities());
+
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+ final RegionRenderer renderer = RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
+ rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
+ final TextRegionUtil textRenderUtil = new TextRegionUtil(renderModes);
+
+ // init
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ renderer.init(gl, 0);
+ rs.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f);
+ screenshot = new GLReadBufferUtil(false, false);
+
+ // reshape
+ gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+
+ // renderer.reshapePerspective(gl, 45.0f, drawable.getWidth(), drawable.getHeight(), 0.1f, 1000.0f);
+ renderer.reshapeOrtho(drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), 0.1f, 1000.0f);
+
+ final int[] sampleCountIO = { sampleCount };
+ // display
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ for(int i=0; i<fonts.length; i++) {
+ final Font font = fonts[i];
+ renderString(drawable, gl, renderer, font, textRenderUtil, font.getFullFamilyName(null).toString()+": "+issues, 0, 0==i?0:-1, -1000, sampleCountIO);
+ if(!onlyIssues) {
+ renderString(drawable, gl, renderer, font, textRenderUtil, "012345678901234567890123456789", 0, -1, -1000, sampleCountIO);
+ renderString(drawable, gl, renderer, font, textRenderUtil, "abcdefghijklmnopqrstuvwxyz", 0, -1, -1000, sampleCountIO);
+ renderString(drawable, gl, renderer, font, textRenderUtil, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, -1, -1000, sampleCountIO);
+ }
+ renderString(drawable, gl, renderer, font, textRenderUtil, "", 0, -1, -1000, sampleCountIO);
+ renderString(drawable, gl, renderer, font, textRenderUtil, "", 0, -1, -1000, sampleCountIO);
+ }
+
+ drawable.swapBuffers();
+ printScreen(renderModes, drawable, gl, false, sampleCount);
+
+ sleep();
+
+ // dispose
+ screenshot.dispose(gl);
+ renderer.destroy(gl);
+
+ NEWTGLContext.destroyWindow(winctx);
+ }
+
+ private static final String issues = "m M n u 8 g q Q";
+ private GLReadBufferUtil screenshot;
+ int lastRow = -1;
+
+ void renderString(final GLDrawable drawable, final GL2ES2 gl, final RegionRenderer renderer, final Font font, final TextRegionUtil textRenderUtil, final String text, final int column, int row, final int z0, final int[] sampleCount) {
+ final int height = drawable.getSurfaceHeight();
+
+ int dx = 0;
+ int dy = height;
+ if(0>row) {
+ row = lastRow + 1;
+ }
+ final AABBox textBox = font.getMetricBounds(text, fontSize);
+ dx += font.getAdvanceWidth('X', fontSize) * column;
+ dy -= (int)textBox.getHeight() * ( row + 1 );
+
+ final PMVMatrix pmv = renderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ pmv.glTranslatef(dx, dy, z0);
+ textRenderUtil.drawString3D(gl, renderer, font, fontSize, text, null, sampleCount);
+
+ lastRow = row;
+ }
+
+ private int screenshot_num = 0;
+
+ public void printScreen(final int renderModes, final GLDrawable drawable, final GL gl, final boolean exportAlpha, final int sampleCount) throws GLException, IOException {
+ final String dir = "./";
+ final String objName = getSimpleTestName(".")+"-snap"+screenshot_num;
+ screenshot_num++;
+ final String modeS = Region.getRenderModeString(renderModes);
+ final String bname = String.format("%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName,
+ drawable.getChosenGLCapabilities().getNumSamples(),
+ TestTextRendererNEWTBugXXXX.fontSize, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), modeS, sampleCount);
+ final String filename = dir + bname +".png";
+ if(screenshot.readPixels(gl, false)) {
+ screenshot.write(new File(filename));
+ }
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java
new file mode 100644
index 000000000..f1a6b761b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java
@@ -0,0 +1,287 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph;
+
+import java.io.IOException;
+
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.curve.opengl.TextRegionUtil;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.font.FontSet;
+import com.jogamp.graph.geom.SVertex;
+import com.jogamp.newt.Window;
+import com.jogamp.opengl.util.PMVMatrix;
+
+public abstract class TextRendererGLELBase implements GLEventListener {
+ public final int renderModes;
+
+ protected final int[] vbaaSampleCount;
+ protected final float[] staticRGBAColor = new float[] { 1f, 1f, 1f, 1f };
+
+ private boolean exclusivePMVMatrix = true;
+ private PMVMatrix sharedPMVMatrix = null;
+ private RenderState rs = null;
+ private RegionRenderer.GLCallback enableCallback=null, disableCallback=null;
+ protected RegionRenderer renderer = null;
+ protected TextRegionUtil textRenderUtil = null;
+
+ /** scale pixel, default is 1f */
+ protected float pixelScale = 1.0f;
+
+ /** dpi display resolution, queried at {@link #init(GLAutoDrawable)} if NEWT, otherwise 96. */
+ protected float dpiH = 96;
+
+ boolean flipVerticalInGLOrientation = false;
+
+ /**
+ * @param fontSet e.g. default is {@link FontFactory#UBUNTU}
+ * @param fontFamily e.g. default is {@link FontSet#FAMILY_REGULAR}
+ * @param fontStylebits e.g. default is {@link FontSet#STYLE_NONE}
+ * @return the resulting font.
+ */
+ public static Font getFont(final int fontSet, final int fontFamily, final int fontStylebits) {
+ try {
+ return FontFactory.get(fontSet).get(fontFamily, fontStylebits);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * @param renderModes
+ * @param sampleCount desired multisampling sample count for msaa-rendering.
+ * @see #setRendererCallbacks(com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback)
+ */
+ public TextRendererGLELBase(final int renderModes, final int[] sampleCount) {
+ this.renderModes = renderModes;
+ this.vbaaSampleCount = sampleCount;
+ }
+
+ /**
+ * <p>
+ * Must be called before {@link #init(GLAutoDrawable)}.
+ * </p>
+ * @param rs
+ */
+ public void setRenderState(final RenderState rs) { this.rs = rs; }
+
+ /**
+ * In exclusive mode, impl. uses a pixelScale of 1f and orthogonal PMV on window dimensions
+ * and renderString uses 'height' for '1'.
+ * <p>
+ * In non-exclusive mode, i.e. shared w/ custom PMV (within another 3d scene),
+ * it uses the custom pixelScale and renderString uses normalized 'height', i.e. '1'.
+ * </p>
+ * <p>
+ * Must be called before {@link #init(GLAutoDrawable)}.
+ * </p>
+ */
+ public void setSharedPMVMatrix(final PMVMatrix pmv) {
+ this.sharedPMVMatrix = pmv;
+ }
+
+ /**
+ * See {@link RegionRenderer#create(RenderState, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback)}.
+ * <p>
+ * Must be called before {@link #init(GLAutoDrawable)}.
+ * </p>
+ */
+ public void setRendererCallbacks(final RegionRenderer.GLCallback enable, final RegionRenderer.GLCallback disable) {
+ this.enableCallback = enable;
+ this.disableCallback = disable;
+ }
+
+ public void setFlipVerticalInGLOrientation(final boolean v) { flipVerticalInGLOrientation=v; }
+ public final RegionRenderer getRenderer() { return renderer; }
+ public final TextRegionUtil getTextRenderUtil() { return textRenderUtil; }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ if( null == this.rs ) {
+ exclusivePMVMatrix = null == sharedPMVMatrix;
+ this.rs = RenderState.createRenderState(SVertex.factory(), sharedPMVMatrix);
+ }
+ this.renderer = RegionRenderer.create(rs, enableCallback, disableCallback);
+ rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
+ this.textRenderUtil = new TextRegionUtil(renderModes);
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ renderer.init(gl, renderModes);
+ rs.setColorStatic(staticRGBAColor[0], staticRGBAColor[1], staticRGBAColor[2], staticRGBAColor[3]);
+ renderer.enable(gl, false);
+
+ final Object upObj = drawable.getUpstreamWidget();
+ if( upObj instanceof Window ) {
+ final float[] pixelsPerMM = ((Window)upObj).getPixelsPerMM(new float[2]);
+ dpiH = pixelsPerMM[1]*25.4f;
+ }
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ if( null != renderer ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ renderer.enable(gl, true);
+ if( exclusivePMVMatrix ) {
+ // renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 1000.0f);
+ renderer.reshapeOrtho(width, height, 0.1f, 1000.0f);
+ pixelScale = 1.0f;
+ } else {
+ renderer.reshapeNotify(width, height);
+ }
+ renderer.enable(gl, false);
+ }
+ }
+
+ @Override
+ public abstract void display(GLAutoDrawable drawable);
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( null != renderer ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ renderer.destroy(gl);
+ }
+ }
+
+ int lastRow = -1;
+
+ /**
+ *
+ * @param drawable
+ * @param font
+ * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
+ * @param text
+ * @param column
+ * @param tx
+ * @param ty
+ * @param tz
+ * @param cacheRegion
+ */
+ public void renderString(final GLAutoDrawable drawable,
+ final Font font, final float pixelSize, final String text,
+ final int column, final float tx, final float ty, final float tz, final boolean cacheRegion) {
+ final int row = lastRow + 1;
+ renderStringImpl(drawable, font, pixelSize, text, column, row, tx, ty, tz, cacheRegion, null);
+ }
+
+ public void renderString(final GLAutoDrawable drawable,
+ final Font font, final float pixelSize, final String text,
+ final int column, final float tx, final float ty, final float tz, final GLRegion region) {
+ final int row = lastRow + 1;
+ renderStringImpl(drawable, font, pixelSize, text, column, row, tx, ty, tz, false, region);
+ }
+
+ /**
+ *
+ * @param drawable
+ * @param font
+ * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
+ * @param text
+ * @param column
+ * @param row
+ * @param tx
+ * @param ty
+ * @param tz
+ * @param cacheRegion
+ */
+ public void renderString(final GLAutoDrawable drawable,
+ final Font font, final float pixelSize, final String text,
+ final int column, final int row,
+ final float tx, final float ty, final float tz, final boolean cacheRegion) {
+ renderStringImpl(drawable, font, pixelSize, text, column, row, tx, ty, tz, cacheRegion, null);
+ }
+
+ public void renderString(final GLAutoDrawable drawable,
+ final Font font, final float pixelSize, final String text,
+ final int column, final int row,
+ final float tx, final float ty, final float tz, final GLRegion region) {
+ renderStringImpl(drawable, font, pixelSize, text, column, row, tx, ty, tz, false, region);
+ }
+
+ private void renderStringImpl(final GLAutoDrawable drawable,
+ final Font font, final float pixelSize, final String text,
+ final int column, final int row,
+ final float tx, final float ty, final float tz, final boolean cacheRegion, final GLRegion region) {
+ if( null != renderer ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ float dx = tx;
+ float dy;
+
+ if( !exclusivePMVMatrix ) {
+ dy = 1f-ty;
+ } else {
+ final int height = drawable.getSurfaceHeight();
+ dy = height-ty;
+ }
+ final int newLineCount = TextRegionUtil.getCharCount(text, '\n');
+ final float lineHeight = font.getLineHeight(pixelSize);
+ dx += pixelScale * font.getAdvanceWidth('X', pixelSize) * column;
+ dy -= pixelScale * lineHeight * ( row + 1 );
+
+ final PMVMatrix pmvMatrix = rs.getMatrix();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ if( !exclusivePMVMatrix ) {
+ pmvMatrix.glPushMatrix();
+ } else {
+ pmvMatrix.glLoadIdentity();
+ }
+ pmvMatrix.glTranslatef(dx, dy, tz);
+ if( flipVerticalInGLOrientation && drawable.isGLOriented() ) {
+ pmvMatrix.glScalef(pixelScale, -1f*pixelScale, 1f);
+ } else if( 1f != pixelScale ) {
+ pmvMatrix.glScalef(pixelScale, pixelScale, 1f);
+ }
+ renderer.enable(gl, true);
+ if( cacheRegion ) {
+ textRenderUtil.drawString3D(gl, renderer, font, pixelSize, text, null, vbaaSampleCount);
+ } else if( null != region ) {
+ TextRegionUtil.drawString3D(gl, region, renderer, font, pixelSize, text, null, vbaaSampleCount,
+ textRenderUtil.tempT1, textRenderUtil.tempT2);
+ } else {
+ TextRegionUtil.drawString3D(gl, renderModes, renderer, font, pixelSize, text, null, vbaaSampleCount,
+ textRenderUtil.tempT1, textRenderUtil.tempT2);
+ }
+ renderer.enable(gl, false);
+
+ if( !exclusivePMVMatrix ) {
+ pmvMatrix.glPopMatrix();
+ }
+ lastRow = row + newLineCount;
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java
index 46557e8c8..82d129f4e 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java
@@ -31,26 +31,30 @@ package com.jogamp.opengl.test.junit.graph.demos;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.opengl.GLRegion;
-import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.opengl.util.PMVMatrix;
/** Demonstrate the rendering of multiple outlines into one region/OutlineShape
* These Outlines are not necessary connected or contained.
* The output of this demo shows two identical shapes but the left one
- * has some vertices with off-curve flag set to true, and the right allt he vertices
- * are on the curve. Demos the Res. Independent Nurbs based Curve rendering
+ * has some vertices with off-curve flag set to true, and the right allt he vertices
+ * are on the curve. Demos the Res. Independent Nurbs based Curve rendering
*
*/
-public class GPURegionGLListener01 extends GPURegionRendererListenerBase01 {
+public class GPURegionGLListener01 extends GPURendererListenerBase01 {
OutlineShape outlineShape = null;
-
- public GPURegionGLListener01 (RenderState rs, int renderModes, int fbosize, boolean debug, boolean trace) {
- super(rs, renderModes, debug, trace);
- setMatrix(-20, 00, 0f, -50, fbosize);
+
+ public GPURegionGLListener01 (final RenderState rs, final int renderModes, final int sampleCount, final boolean debug, final boolean trace) {
+ super(RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable), renderModes, debug, trace);
+ rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
+ setMatrix(-20, 00, -50, 0f, sampleCount);
}
-
+
private void createTestOutline(){
float offset = 0;
outlineShape = new OutlineShape(getRenderer().getRenderState().getVertexFactory());
@@ -61,14 +65,14 @@ public class GPURegionGLListener01 extends GPURegionRendererListenerBase01 {
outlineShape.addVertex(6.0f,15.0f, false);
outlineShape.addVertex(5.0f,8.0f, false);
outlineShape.addVertex(0.0f,10.0f,true);
- outlineShape.closeLastOutline();
+ outlineShape.closeLastOutline(true);
outlineShape.addEmptyOutline();
outlineShape.addVertex(5.0f,-5.0f,true);
outlineShape.addVertex(10.0f,-5.0f, false);
outlineShape.addVertex(10.0f,0.0f, true);
outlineShape.addVertex(5.0f,0.0f, false);
- outlineShape.closeLastOutline();
-
+ outlineShape.closeLastOutline(true);
+
/** Same shape as above but without any off-curve vertices */
offset = 30;
outlineShape.addEmptyOutline();
@@ -79,47 +83,48 @@ public class GPURegionGLListener01 extends GPURegionRendererListenerBase01 {
outlineShape.addVertex(offset+7.0f,15.0f, true);
outlineShape.addVertex(offset+6.0f,8.0f, true);
outlineShape.addVertex(offset+0.0f,10.0f, true);
- outlineShape.closeLastOutline();
+ outlineShape.closeLastOutline(true);
outlineShape.addEmptyOutline();
outlineShape.addVertex(offset+5.0f,0.0f, true);
outlineShape.addVertex(offset+5.0f,-5.0f, true);
outlineShape.addVertex(offset+10.0f,-5.0f, true);
outlineShape.addVertex(offset+10.0f,0.0f, true);
- outlineShape.closeLastOutline();
-
- region = GLRegion.create(outlineShape, getRenderModes());
+ outlineShape.closeLastOutline(true);
+
+ region = GLRegion.create(getRenderModes(), null);
+ region.addOutlineShape(outlineShape, null, region.hasColorChannel() ? getRenderer().getRenderState().getColorStatic(new float[4]) : null);
}
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
super.init(drawable);
-
- GL2ES2 gl = drawable.getGL().getGL2ES2();
- final RegionRenderer regionRenderer = (RegionRenderer) getRenderer();
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ final RenderState rs = getRenderer().getRenderState();
gl.setSwapInterval(1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
- gl.glEnable(GL2ES2.GL_BLEND);
- regionRenderer.setAlpha(gl, 1.0f);
- regionRenderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f);
-
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_BLEND);
+ rs.setColorStatic(0.0f, 0.0f, 0.0f, 1.0f);
+
createTestOutline();
}
- public void display(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- final RegionRenderer regionRenderer = (RegionRenderer) getRenderer();
-
- regionRenderer.resetModelview(null);
- regionRenderer.translate(null, getXTran(), getYTran(), getZoom());
- regionRenderer.rotate(gl, getAngle(), 0, 1, 0);
- if( weight != regionRenderer.getWeight()) {
- regionRenderer.setWeight(gl, weight);
+ final RegionRenderer regionRenderer = getRenderer();
+ final PMVMatrix pmv = regionRenderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ pmv.glTranslatef(getXTran(), getYTran(), getZTran());
+ pmv.glRotatef(getAngle(), 0, 1, 0);
+ if( weight != regionRenderer.getRenderState().getWeight() ) {
+ regionRenderer.getRenderState().setWeight(weight);
}
- regionRenderer.draw(gl, region, getPosition(), getTexSize());
- }
+ region.draw(gl, regionRenderer, getSampleCount());
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java
index 525c5e648..2486b5853 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java
@@ -28,97 +28,107 @@
package com.jogamp.opengl.test.junit.graph.demos;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.opengl.GLRegion;
-import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.opengl.util.PMVMatrix;
/** Demonstrate the rendering of multiple OutlineShapes
* into one region
*
*/
-public class GPURegionGLListener02 extends GPURegionRendererListenerBase01 {
- OutlineShape[] outlineShapes = new OutlineShape[2];
+public class GPURegionGLListener02 extends GPURendererListenerBase01 {
+ List<OutlineShape> outlineShapes = new ArrayList<OutlineShape>();
- public GPURegionGLListener02 (RenderState rs, int renderModes, int fbosize, boolean debug, boolean trace) {
- super(rs, renderModes, debug, trace);
- setMatrix(-20, 00, 0f, -50, fbosize);
+ public GPURegionGLListener02 (final RenderState rs, final int renderModes, final int sampleCount, final boolean debug, final boolean trace) {
+ super(RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable), renderModes, debug, trace);
+ rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
+ setMatrix(-20, 00, -50, 0f, sampleCount);
}
-
+
private void createTestOutline(){
float offset = 0;
- outlineShapes[0] = new OutlineShape(getRenderer().getRenderState().getVertexFactory());
- outlineShapes[0].addVertex(0.0f,-10.0f,true);
- outlineShapes[0].addVertex(15.0f,-10.0f, true);
- outlineShapes[0].addVertex(10.0f,5.0f, false);
- outlineShapes[0].addVertex(15.0f,10.0f, true);
- outlineShapes[0].addVertex(6.0f,15.0f, false);
- outlineShapes[0].addVertex(5.0f,8.0f, false);
- outlineShapes[0].addVertex(0.0f,10.0f,true);
- outlineShapes[0].closeLastOutline();
- outlineShapes[0].addEmptyOutline();
- outlineShapes[0].addVertex(5.0f,-5.0f,true);
- outlineShapes[0].addVertex(10.0f,-5.0f, false);
- outlineShapes[0].addVertex(10.0f,0.0f, true);
- outlineShapes[0].addVertex(5.0f,0.0f, false);
- outlineShapes[0].closeLastOutline();
-
+ OutlineShape shape = new OutlineShape(getRenderer().getRenderState().getVertexFactory());
+ outlineShapes.add(shape);
+ shape.addVertex(0.0f,-10.0f,true);
+ shape.addVertex(15.0f,-10.0f, true);
+ shape.addVertex(10.0f,5.0f, false);
+ shape.addVertex(15.0f,10.0f, true);
+ shape.addVertex(6.0f,15.0f, false);
+ shape.addVertex(5.0f,8.0f, false);
+ shape.addVertex(0.0f,10.0f,true);
+ shape.closeLastOutline(true);
+ shape.addEmptyOutline();
+ shape.addVertex(5.0f,-5.0f,true);
+ shape.addVertex(10.0f,-5.0f, false);
+ shape.addVertex(10.0f,0.0f, true);
+ shape.addVertex(5.0f,0.0f, false);
+ shape.closeLastOutline(true);
+
/** Same shape as above but without any off-curve vertices */
- outlineShapes[1] = new OutlineShape(getRenderer().getRenderState().getVertexFactory());
+ shape = new OutlineShape(getRenderer().getRenderState().getVertexFactory());
+ outlineShapes.add(shape);
offset = 30;
- outlineShapes[1].addVertex(offset+0.0f,-10.0f, true);
- outlineShapes[1].addVertex(offset+17.0f,-10.0f, true);
- outlineShapes[1].addVertex(offset+11.0f,5.0f, true);
- outlineShapes[1].addVertex(offset+16.0f,10.0f, true);
- outlineShapes[1].addVertex(offset+7.0f,15.0f, true);
- outlineShapes[1].addVertex(offset+6.0f,8.0f, true);
- outlineShapes[1].addVertex(offset+0.0f,10.0f, true);
- outlineShapes[1].closeLastOutline();
- outlineShapes[1].addEmptyOutline();
- outlineShapes[1].addVertex(offset+5.0f,0.0f, true);
- outlineShapes[1].addVertex(offset+5.0f,-5.0f, true);
- outlineShapes[1].addVertex(offset+10.0f,-5.0f, true);
- outlineShapes[1].addVertex(offset+10.0f,0.0f, true);
- outlineShapes[1].closeLastOutline();
-
- region = GLRegion.create(outlineShapes, getRenderModes());
+ shape.addVertex(offset+0.0f,-10.0f, true);
+ shape.addVertex(offset+17.0f,-10.0f, true);
+ shape.addVertex(offset+11.0f,5.0f, true);
+ shape.addVertex(offset+16.0f,10.0f, true);
+ shape.addVertex(offset+7.0f,15.0f, true);
+ shape.addVertex(offset+6.0f,8.0f, true);
+ shape.addVertex(offset+0.0f,10.0f, true);
+ shape.closeLastOutline(true);
+ shape.addEmptyOutline();
+ shape.addVertex(offset+5.0f,0.0f, true);
+ shape.addVertex(offset+5.0f,-5.0f, true);
+ shape.addVertex(offset+10.0f,-5.0f, true);
+ shape.addVertex(offset+10.0f,0.0f, true);
+ shape.closeLastOutline(true);
+
+ region = GLRegion.create(getRenderModes(), null);
+ region.addOutlineShapes(outlineShapes, null, null);
}
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
super.init(drawable);
-
- GL2ES2 gl = drawable.getGL().getGL2ES2();
- final RegionRenderer regionRenderer = (RegionRenderer) getRenderer();
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ final RenderState rs = getRenderer().getRenderState();
gl.setSwapInterval(1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
- gl.glEnable(GL2ES2.GL_BLEND);
- regionRenderer.setAlpha(gl, 1.0f);
- regionRenderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f);
-
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_BLEND);
+ rs.setColorStatic(0.0f, 0.0f, 0.0f, 1.0f);
+
createTestOutline();
}
- public void display(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- final RegionRenderer regionRenderer = (RegionRenderer) getRenderer();
-
- regionRenderer.resetModelview(null);
- regionRenderer.translate(null, getXTran(), getYTran(), getZoom());
- regionRenderer.rotate(gl, getAngle(), 0, 1, 0);
- if( weight != regionRenderer.getWeight()) {
- regionRenderer.setWeight(gl, weight);
+ final RegionRenderer regionRenderer = getRenderer();
+
+ final PMVMatrix pmv = regionRenderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ pmv.glTranslatef(getXTran(), getYTran(), getZTran());
+ pmv.glRotatef(getAngle(), 0, 1, 0);
+ if( weight != regionRenderer.getRenderState().getWeight() ) {
+ regionRenderer.getRenderState().setWeight(weight);
}
- regionRenderer.draw(gl, region, getPosition(), getTexSize());
-
- }
+ region.draw(gl, regionRenderer, getSampleCount());
+
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo.java
new file mode 100644
index 000000000..77456d5e3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo.java
@@ -0,0 +1,156 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.graph.demos;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.geom.SVertex;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+
+/** Demonstrate the rendering of multiple outlines into one region/OutlineShape
+ * These Outlines are not necessary connected or contained.
+ * The output of this demo shows two identical shapes but the left one
+ * has some vertices with off-curve flag set to true, and the right allt he vertices
+ * are on the curve. Demos the Res. Independent Nurbs based Curve rendering
+ *
+ */
+public class GPURegionNewtDemo {
+ static final boolean DEBUG = false;
+ static final boolean TRACE = false;
+
+ static int SceneMSAASamples = 0;
+ static int GraphVBAASamples = 4;
+ static int GraphMSAASamples = 0;
+ static boolean GraphUseWeight = true;
+
+ public static void main(final String[] args) {
+ int width = 800, height = 400;
+ int x = 10, y = 10;
+ if( 0 != args.length ) {
+ SceneMSAASamples = 0;
+ GraphMSAASamples = 0;
+ GraphVBAASamples = 0;
+ GraphUseWeight = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-smsaa")) {
+ i++;
+ SceneMSAASamples = MiscUtils.atoi(args[i], SceneMSAASamples);
+ } else if(args[i].equals("-gmsaa")) {
+ i++;
+ GraphMSAASamples = MiscUtils.atoi(args[i], GraphMSAASamples);
+ GraphVBAASamples = 0;
+ } else if(args[i].equals("-gvbaa")) {
+ i++;
+ GraphMSAASamples = 0;
+ GraphVBAASamples = MiscUtils.atoi(args[i], GraphVBAASamples);
+ } else if(args[i].equals("-gweight")) {
+ GraphUseWeight = true;
+ } else if(args[i].equals("-width")) {
+ i++;
+ width = MiscUtils.atoi(args[i], width);
+ } else if(args[i].equals("-height")) {
+ i++;
+ height = MiscUtils.atoi(args[i], height);
+ } else if(args[i].equals("-x")) {
+ i++;
+ x = MiscUtils.atoi(args[i], x);
+ } else if(args[i].equals("-y")) {
+ i++;
+ y = MiscUtils.atoi(args[i], y);
+ }
+ }
+ }
+ System.err.println("Desired win size "+width+"x"+height);
+ System.err.println("Desired win pos "+x+"/"+y);
+ System.err.println("Scene MSAA Samples "+SceneMSAASamples);
+ System.err.println("Graph MSAA Samples"+GraphMSAASamples);
+ System.err.println("Graph VBAA Samples "+GraphVBAASamples);
+ System.err.println("Graph Weight Mode "+GraphUseWeight);
+
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
+ if( SceneMSAASamples > 0 ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(SceneMSAASamples);
+ }
+ System.out.println("Requested: " + caps);
+
+ int rmode = GraphUseWeight ? Region.VARWEIGHT_RENDERING_BIT : 0;
+ int sampleCount = 0;
+ if( GraphVBAASamples > 0 ) {
+ rmode |= Region.VBAA_RENDERING_BIT;
+ sampleCount += GraphVBAASamples;
+ } else if( GraphMSAASamples > 0 ) {
+ rmode |= Region.MSAA_RENDERING_BIT;
+ sampleCount += GraphMSAASamples;
+ }
+
+ final GLWindow window = GLWindow.create(caps);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setTitle("GPU Curve Region Newt Demo - graph[vbaa"+GraphVBAASamples+" msaa"+GraphMSAASamples+"], msaa "+SceneMSAASamples);
+
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+ final GPURegionGLListener01 regionGLListener = new GPURegionGLListener01 (rs, rmode, sampleCount, DEBUG, TRACE);
+ regionGLListener.attachInputListenerTo(window);
+ window.addGLEventListener(regionGLListener);
+ window.setVisible(true);
+
+ //FPSAnimator animator = new FPSAnimator(60);
+ final Animator animator = new Animator();
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.add(window);
+
+ window.addKeyListener(new KeyAdapter() {
+ public void keyPressed(final KeyEvent arg0) {
+ if(arg0.getKeyCode() == KeyEvent.VK_F4) {
+ window.destroy();
+ }
+ }
+ });
+ window.addWindowListener(new WindowAdapter() {
+ public void windowDestroyed(final WindowEvent e) {
+ animator.stop();
+ }
+ });
+
+ animator.start();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java
deleted file mode 100755
index 160dc0ffe..000000000
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.opengl.test.junit.graph.demos;
-
-import javax.media.opengl.FPSCounter;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLProfile;
-
-import com.jogamp.graph.curve.Region;
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.opengl.SVertex;
-import com.jogamp.newt.event.KeyAdapter;
-import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.WindowAdapter;
-import com.jogamp.newt.event.WindowEvent;
-import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.glsl.ShaderState;
-
-/** Demonstrate the rendering of multiple outlines into one region/OutlineShape
- * These Outlines are not necessary connected or contained.
- * The output of this demo shows two identical shapes but the left one
- * has some vertices with off-curve flag set to true, and the right allt he vertices
- * are on the curve. Demos the Res. Independent Nurbs based Curve rendering
- *
- */
-public class GPURegionNewtDemo01 {
- static final boolean DEBUG = false;
- static final boolean TRACE = false;
-
- public static void main(String[] args) {
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
- caps.setSampleBuffers(true);
- caps.setNumSamples(4); // 2 samples is not enough ..
- System.out.println("Requested: " + caps);
-
- final GLWindow window = GLWindow.create(caps);
- window.setPosition(10, 10);
- window.setSize(800, 400);
- window.setTitle("GPU Curve Region Newt Demo 01 - vbaa0 msaa1");
-
- RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- GPURegionGLListener01 regionGLListener = new GPURegionGLListener01 (rs, Region.VARIABLE_CURVE_WEIGHT_BIT, 0, DEBUG, TRACE);
- regionGLListener.attachInputListenerTo(window);
- window.addGLEventListener(regionGLListener);
-
- window.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
- window.setVisible(true);
-
- //FPSAnimator animator = new FPSAnimator(60);
- final Animator animator = new Animator();
- animator.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
- animator.add(window);
-
- window.addKeyListener(new KeyAdapter() {
- public void keyPressed(KeyEvent arg0) {
- if(arg0.getKeyCode() == KeyEvent.VK_F4) {
- window.destroy();
- }
- }
- });
- window.addWindowListener(new WindowAdapter() {
- public void windowDestroyed(WindowEvent e) {
- animator.stop();
- }
- });
-
- animator.start();
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java
deleted file mode 100644
index e7b5c73c5..000000000
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.opengl.test.junit.graph.demos;
-
-import javax.media.opengl.FPSCounter;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLProfile;
-
-import com.jogamp.graph.curve.Region;
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.opengl.SVertex;
-import com.jogamp.newt.event.KeyAdapter;
-import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.WindowAdapter;
-import com.jogamp.newt.event.WindowEvent;
-import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.glsl.ShaderState;
-
-/** Demonstrate the rendering of multiple OutlineShapes
- * into one region
- *
- */
-public class GPURegionNewtDemo02 {
- static final boolean DEBUG = false;
- static final boolean TRACE = false;
-
- public static void main(String[] args) {
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
- System.out.println("Requested: " + caps);
-
- final GLWindow window = GLWindow.create(caps);
- window.setPosition(10, 10);
- window.setSize(800, 400);
- window.setTitle("GPU Curve Region Newt Demo 02 - vbaa1 msaa0");
-
- RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- GPURegionGLListener02 regionGLListener = new GPURegionGLListener02 (rs, Region.VBAA_RENDERING_BIT|Region.VARIABLE_CURVE_WEIGHT_BIT, 1140, DEBUG, TRACE);
- regionGLListener.attachInputListenerTo(window);
- window.addGLEventListener(regionGLListener);
-
- window.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
- window.setVisible(true);
-
- //FPSAnimator animator = new FPSAnimator(60);
- final Animator animator = new Animator();
- animator.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
- animator.add(window);
-
- window.addKeyListener(new KeyAdapter() {
- public void keyPressed(KeyEvent arg0) {
- if(arg0.getKeyCode() == KeyEvent.VK_F4) {
- window.destroy();
- }
- }
- });
- window.addWindowListener(new WindowAdapter() {
- public void windowDestroyed(WindowEvent e) {
- animator.stop();
- }
- });
-
- animator.start();
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java
index 6378c1ee3..159d4b84c 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java
@@ -41,76 +41,86 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLPipelineFactory;
import javax.media.opengl.GLRunnable;
-
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
-import com.jogamp.graph.curve.opengl.Renderer;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.curve.opengl.RenderState;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.PMVMatrix;
/**
*
* Action Keys:
* - 1/2: zoom in/out
* - 6/7: 2nd pass texture size
- * - 0/9: rotate
+ * - 0/9: rotate
* - Q/W: change weight
* - v: toggle v-sync
* - s: screenshot
*/
public abstract class GPURendererListenerBase01 implements GLEventListener {
- private GLReadBufferUtil screenshot;
- private Renderer renderer;
- private int renderModes;
- private boolean debug;
- private boolean trace;
-
+ private final RegionRenderer renderer;
+ private final int renderModes;
+ private final boolean debug;
+ private final boolean trace;
+
protected GLRegion region;
+ private final GLReadBufferUtil screenshot;
+
private KeyAction keyAction;
-
+
private volatile GLAutoDrawable autoDrawable = null;
-
+
private final float[] position = new float[] {0,0,0};
-
+
+ protected final float zNear = 0.1f, zFar = 7000f;
+ /** Describing the bounding box in model-coordinates of the near-plane parallel at distance one. */
+ protected final AABBox nearPlane1Box;
+
private float xTran = -10;
- private float yTran = 10;
+ private float yTran = 10;
private float ang = 0f;
- private float zoom = -70f;
- private int[] texSize = new int[] { 400 };
+ private float zTran = -70f;
+ private final int[] sampleCount = new int[] { 4 };
protected volatile float weight = 1.0f;
boolean ignoreInput = false;
- public GPURendererListenerBase01(Renderer renderer, int renderModes, boolean debug, boolean trace) {
+ public GPURendererListenerBase01(final RegionRenderer renderer, final int renderModes, final boolean debug, final boolean trace) {
this.renderer = renderer;
this.renderModes = renderModes;
this.debug = debug;
this.trace = trace;
this.screenshot = new GLReadBufferUtil(false, false);
+ nearPlane1Box = new AABBox();
}
-
- public final Renderer getRenderer() { return renderer; }
+
+ public final RegionRenderer getRenderer() { return renderer; }
public final int getRenderModes() { return renderModes; }
- public final float getZoom() { return zoom; }
+ public final float getZTran() { return zTran; }
public final float getXTran() { return xTran; }
public final float getYTran() { return yTran; }
public final float getAngle() { return ang; }
- public final int[] getTexSize() { return texSize; }
+ public final int[] getSampleCount() { return sampleCount; }
public final float[] getPosition() { return position; }
- public void setMatrix(float xtrans, float ytrans, float angle, int zoom, int fbosize) {
+ public void setMatrix(final float xtrans, final float ytrans, final float zTran, final float angle, final int sampleCount) {
this.xTran = xtrans;
- this.yTran = ytrans;
- this.ang = angle;
- this.zoom = zoom;
- this.texSize[0] = fbosize;
+ this.yTran = ytrans;
+ this.zTran = zTran;
+ this.ang = angle;
+ this.sampleCount[0] = sampleCount;
}
-
- public void init(GLAutoDrawable drawable) {
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
autoDrawable = drawable;
GL2ES2 gl = drawable.getGL().getGL2ES2();
if(debug) {
@@ -123,97 +133,131 @@ public abstract class GPURendererListenerBase01 implements GLEventListener {
System.err.println("*** GLDebugMessage "+gl.getContext().isGLDebugMessageEnabled());
MSAATool.dump(drawable);
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- getRenderer().init(gl);
+ getRenderer().init(gl, renderModes);
}
-
- public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- gl.glViewport(xstart, ystart, width, height);
- renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 7000.0f);
-
+
+ public static void mapWin2ObjectCoords(final PMVMatrix pmv, final int[] view,
+ final float zNear, final float zFar,
+ final float orthoX, final float orthoY, final float orthoDist,
+ final float[] winZ, final float[] objPos) {
+ winZ[0] = (1f/zNear-1f/orthoDist)/(1f/zNear-1f/zFar);
+ pmv.gluUnProject(orthoX, orthoY, winZ[0], view, 0, objPos, 0);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int xstart, final int ystart, final int width, final int height) {
+ final PMVMatrix pmv = renderer.getMatrix();
+ renderer.reshapePerspective(45.0f, width, height, zNear, zFar);
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ System.err.printf("Reshape: zNear %f, zFar %f%n", zNear, zFar);
+ System.err.printf("Reshape: Frustum: %s%n", pmv.glGetFrustum());
+ {
+ final float orthoDist = 1f;
+ final float[] obj00Coord = new float[3];
+ final float[] obj11Coord = new float[3];
+ final float[] winZ = new float[1];
+ final int[] view = new int[] { 0, 0, width, height };
+
+ mapWin2ObjectCoords(pmv, view, zNear, zFar, 0f, 0f, orthoDist, winZ, obj00Coord);
+ System.err.printf("Reshape: mapped.00: [%f, %f, %f], winZ %f -> [%f, %f, %f]%n", 0f, 0f, orthoDist, winZ[0], obj00Coord[0], obj00Coord[1], obj00Coord[2]);
+
+ mapWin2ObjectCoords(pmv, view, zNear, zFar, width, height, orthoDist, winZ, obj11Coord);
+ System.err.printf("Reshape: mapped.11: [%f, %f, %f], winZ %f -> [%f, %f, %f]%n", (float)width, (float)height, orthoDist, winZ[0], obj11Coord[0], obj11Coord[1], obj11Coord[2]);
+
+ nearPlane1Box.setSize( obj00Coord[0], // lx
+ obj00Coord[1], // ly
+ obj00Coord[2], // lz
+ obj11Coord[0], // hx
+ obj11Coord[1], // hy
+ obj11Coord[2] );// hz
+ System.err.printf("Reshape: dist1Box: %s%n", nearPlane1Box);
+ }
+
dumpMatrix();
- System.err.println("Reshape: "+renderer.getRenderState());
+ // System.err.println("Reshape: "+renderer.getRenderState());
}
-
- public void dispose(GLAutoDrawable drawable) {
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
autoDrawable = null;
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
if(null != region) {
- region.destroy(gl, renderer.getRenderState());
+ region.destroy(gl);
}
screenshot.dispose(gl);
renderer.destroy(gl);
- }
-
- public void zoom(int v){
- zoom += v;
+ }
+
+ public void zoom(final int v){
+ zTran += v;
dumpMatrix();
}
-
- public void move(float x, float y){
+
+ public void move(final float x, final float y){
xTran += x;
yTran += y;
dumpMatrix();
}
- public void rotate(float delta){
+ public void rotate(final float delta){
ang += delta;
ang %= 360.0f;
dumpMatrix();
}
- public void editGlobalWeight(float delta) {
- if( !Renderer.isWeightValid(weight+delta) ) {
+ public void editGlobalWeight(final float delta) {
+ if( !RenderState.isWeightValid(weight+delta) ) {
return;
}
weight += delta;
System.err.println("Global Weight: "+ weight);
}
-
+
void dumpMatrix() {
- System.err.println("Matrix: " + xTran + "/" + yTran + " x"+zoom + " @"+ang);
+ System.err.println("Matrix: " + xTran + " / " + yTran + " / "+zTran + " @ "+ang);
}
-
- /** Attach the input listener to the window */
- public void attachInputListenerTo(GLWindow window) {
+
+ /** Attach the input listener to the window */
+ public void attachInputListenerTo(final GLWindow window) {
if ( null == keyAction ) {
keyAction = new KeyAction();
- window.addKeyListener(keyAction);
+ window.addKeyListener(keyAction);
}
}
-
- public void detachInputListenerFrom(GLWindow window) {
+
+ public void detachInputListenerFrom(final GLWindow window) {
if ( null == keyAction ) {
return;
}
window.removeKeyListener(keyAction);
}
-
- public void printScreen(GLAutoDrawable drawable, String dir, String tech, String objName, boolean exportAlpha) throws GLException, IOException {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), texSize[0], objName);
-
+
+ public void printScreen(final GLAutoDrawable drawable, final String dir, final String tech, final String objName, final boolean exportAlpha) throws GLException, IOException {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw);
+ pw.printf("-%03dx%03d-Z%04d-S%02d-%s", drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), (int)Math.abs(zTran), sampleCount[0], objName);
+
final String filename = dir + tech + sw +".png";
if(screenshot.readPixels(drawable.getGL(), false)) {
screenshot.write(new File(filename));
}
}
-
+
int screenshot_num = 0;
- public void setIgnoreInput(boolean v) {
+ public void setIgnoreInput(final boolean v) {
ignoreInput = v;
}
public boolean getIgnoreInput() {
return ignoreInput;
}
-
+
public class KeyAction implements KeyListener {
- public void keyPressed(KeyEvent arg0) {
+ @Override
+ public void keyPressed(final KeyEvent arg0) {
if(ignoreInput) {
return;
}
-
+
if(arg0.getKeyCode() == KeyEvent.VK_1){
zoom(10);
}
@@ -227,25 +271,25 @@ public abstract class GPURendererListenerBase01 implements GLEventListener {
move(0, 1);
}
else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){
- move(1, 0);
+ move(-1, 0);
}
else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){
- move(-1, 0);
+ move(1, 0);
}
else if(arg0.getKeyCode() == KeyEvent.VK_6){
- texSize[0] -= 10;
- System.err.println("Tex Size: " + texSize[0]);
+ sampleCount[0] -= 1;
+ System.err.println("Sample Count: " + sampleCount[0]);
}
else if(arg0.getKeyCode() == KeyEvent.VK_7){
- texSize[0] += 10;
- System.err.println("Tex Size: " + texSize[0]);
- }
+ sampleCount[0] += 1;
+ System.err.println("Sample Count: " + sampleCount[0]);
+ }
else if(arg0.getKeyCode() == KeyEvent.VK_0){
rotate(1);
}
else if(arg0.getKeyCode() == KeyEvent.VK_9){
rotate(-1);
- }
+ }
else if(arg0.getKeyCode() == KeyEvent.VK_Q){
editGlobalWeight(-0.1f);
}
@@ -255,9 +299,10 @@ public abstract class GPURendererListenerBase01 implements GLEventListener {
else if(arg0.getKeyCode() == KeyEvent.VK_V) {
if(null != autoDrawable) {
autoDrawable.invoke(false, new GLRunnable() {
- public boolean run(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
- int i = gl.getSwapInterval();
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ int i = gl.getSwapInterval();
i = i==0 ? 1 : 0;
gl.setSwapInterval(i);
final GLAnimatorControl a = drawable.getAnimator();
@@ -271,29 +316,31 @@ public abstract class GPURendererListenerBase01 implements GLEventListener {
return true;
}
});
- }
+ }
}
else if(arg0.getKeyCode() == KeyEvent.VK_S){
rotate(-1);
if(null != autoDrawable) {
autoDrawable.invoke(false, new GLRunnable() {
- public boolean run(GLAutoDrawable drawable) {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
try {
- final String type = Region.isVBAA(renderModes) ? "vbaa0-msaa1" : "vbaa1-msaa0" + ( Region.isNonUniformWeight(renderModes) ? "-vc" : "-uc" ) ;
+ final String modeS = Region.getRenderModeString(renderModes);
+ final String type = modeS + ( Region.hasVariableWeight(renderModes) ? "-vc" : "-uc" ) ;
printScreen(drawable, "./", "demo-"+type, "snap"+screenshot_num, false);
screenshot_num++;
- } catch (GLException e) {
+ } catch (final GLException e) {
e.printStackTrace();
- } catch (IOException e) {
+ } catch (final IOException e) {
e.printStackTrace();
- }
+ }
return true;
}
});
- }
- }
+ }
+ }
}
- public void keyTyped(KeyEvent arg0) {}
- public void keyReleased(KeyEvent arg0) {}
+ @Override
+ public void keyReleased(final KeyEvent arg0) {}
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java
index 5c7d15ad1..602879319 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java
@@ -28,45 +28,44 @@
package com.jogamp.opengl.test.junit.graph.demos;
+import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
+import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.curve.opengl.TextRenderer;
-import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.geom.SVertex;
import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.opengl.util.glsl.ShaderState;
public class GPUTextGLListener0A extends GPUTextRendererListenerBase01 {
-
+
public GPUTextGLListener0A() {
- this( RenderState.createRenderState(new ShaderState(), SVertex.factory()), 0, 0, false, false ) ;
+ super(RenderState.createRenderState(SVertex.factory()), Region.VBAA_RENDERING_BIT, 4, true, false, false);
}
-
- public GPUTextGLListener0A(RenderState rs, int numpass, int fbosize, boolean debug, boolean trace) {
- super(rs, numpass, debug, trace);
- setMatrix(-400, -30, 0f, -500, fbosize);
+
+ public GPUTextGLListener0A(final RenderState rs, final int renderModes, final int sampleCount, final boolean blending, final boolean debug, final boolean trace) {
+ super(rs, renderModes, sampleCount, blending, debug, trace);
}
-
- public void init(GLAutoDrawable drawable) {
+
+ public void init(final GLAutoDrawable drawable) {
if(drawable instanceof GLWindow) {
final GLWindow glw = (GLWindow) drawable;
attachInputListenerTo(glw);
- }
+ }
super.init(drawable);
-
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- final TextRenderer textRenderer = (TextRenderer) getRenderer();
-
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ final RenderState rs = getRenderer().getRenderState();
+
gl.setSwapInterval(1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
- gl.glEnable(GL2ES2.GL_BLEND);
- textRenderer.setAlpha(gl, 1.0f);
- textRenderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_BLEND);
+ rs.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f);
}
-
- public void dispose(GLAutoDrawable drawable) {
+
+ public void dispose(final GLAutoDrawable drawable) {
if(drawable instanceof GLWindow) {
final GLWindow glw = (GLWindow) drawable;
detachInputListenerFrom(glw);
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo.java
index 1b71cd781..cba70c09f 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo.java
@@ -27,73 +27,127 @@
*/
package com.jogamp.opengl.test.junit.graph.demos;
-import javax.media.opengl.FPSCounter;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.graph.geom.SVertex;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.glsl.ShaderState;
-public class GPUTextNewtDemo02 {
+public class GPUTextNewtDemo {
/**
* FIXME:
- *
+ *
* If DEBUG is enabled:
- *
- * Caused by: javax.media.opengl.GLException: Thread[main-Display-X11_:0.0-1-EDT-1,5,main] glGetError() returned the following error codes after a call to glFramebufferRenderbuffer(<int> 0x8D40, <int> 0x1902, <int> 0x8D41, <int> 0x1): GL_INVALID_ENUM ( 1280 0x500),
+ *
+ * Caused by: javax.media.opengl.GLException: Thread[main-Display-X11_:0.0-1-EDT-1,5,main] glGetError() returned the following error codes after a call to glFramebufferRenderbuffer(<int> 0x8D40, <int> 0x1902, <int> 0x8D41, <int> 0x1): GL_INVALID_ENUM ( 1280 0x500),
* at javax.media.opengl.DebugGL4bc.checkGLGetError(DebugGL4bc.java:33961)
* at javax.media.opengl.DebugGL4bc.glFramebufferRenderbuffer(DebugGL4bc.java:33077)
* at jogamp.graph.curve.opengl.VBORegion2PGL3.initFBOTexture(VBORegion2PGL3.java:295)
*/
static final boolean DEBUG = false;
static final boolean TRACE = false;
-
- public static void main(String[] args) {
- GLProfile glp = GLProfile.getGL2ES2();
-
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
- System.out.println("Requested: "+caps);
-
+
+ static int SceneMSAASamples = 0;
+ static int GraphVBAASamples = 4;
+ static int GraphMSAASamples = 0;
+
+ public static void main(final String[] args) {
+ int width = 800, height = 400;
+ int x = 10, y = 10;
+ if( 0 != args.length ) {
+ SceneMSAASamples = 0;
+ GraphMSAASamples = 0;
+ GraphVBAASamples = 0;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-smsaa")) {
+ i++;
+ SceneMSAASamples = MiscUtils.atoi(args[i], SceneMSAASamples);
+ } else if(args[i].equals("-gmsaa")) {
+ i++;
+ GraphMSAASamples = MiscUtils.atoi(args[i], GraphMSAASamples);
+ GraphVBAASamples = 0;
+ } else if(args[i].equals("-gvbaa")) {
+ i++;
+ GraphMSAASamples = 0;
+ GraphVBAASamples = MiscUtils.atoi(args[i], GraphVBAASamples);
+ } else if(args[i].equals("-width")) {
+ i++;
+ width = MiscUtils.atoi(args[i], width);
+ } else if(args[i].equals("-height")) {
+ i++;
+ height = MiscUtils.atoi(args[i], height);
+ } else if(args[i].equals("-x")) {
+ i++;
+ x = MiscUtils.atoi(args[i], x);
+ } else if(args[i].equals("-y")) {
+ i++;
+ y = MiscUtils.atoi(args[i], y);
+ }
+ }
+ }
+ System.err.println("Desired win size "+width+"x"+height);
+ System.err.println("Desired win pos "+x+"/"+y);
+ System.err.println("Scene MSAA Samples "+SceneMSAASamples);
+ System.err.println("Graph MSAA Samples "+GraphMSAASamples);
+ System.err.println("Graph VBAA Samples "+GraphVBAASamples);
+
+ final GLProfile glp = GLProfile.getGL2ES2();
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
+ if( SceneMSAASamples > 0 ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(SceneMSAASamples);
+ }
+ System.out.println("Requested: " + caps);
+
+ int rmode = 0; // Region.VARIABLE_CURVE_WEIGHT_BIT;
+ int sampleCount = 0;
+ if( GraphVBAASamples > 0 ) {
+ rmode |= Region.VBAA_RENDERING_BIT;
+ sampleCount += GraphVBAASamples;
+ } else if( GraphMSAASamples > 0 ) {
+ rmode |= Region.MSAA_RENDERING_BIT;
+ sampleCount += GraphMSAASamples;
+ }
+
final GLWindow window = GLWindow.create(caps);
-
- window.setPosition(10, 10);
- window.setSize(800, 400);
- window.setTitle("GPU Text Newt Demo 02 - vbaa1 msaa0");
-
- RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- GPUTextGLListener0A textGLListener = new GPUTextGLListener0A(rs, Region.VBAA_RENDERING_BIT, window.getWidth()*3, DEBUG, TRACE);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setTitle("GPU Text Newt Demo - graph[vbaa"+GraphVBAASamples+" msaa"+GraphMSAASamples+"], msaa "+SceneMSAASamples);
+
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+ final GPUTextGLListener0A textGLListener = new GPUTextGLListener0A(rs, rmode, sampleCount, true, DEBUG, TRACE);
// ((TextRenderer)textGLListener.getRenderer()).setCacheLimit(32);
window.addGLEventListener(textGLListener);
-
- window.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
window.setVisible(true);
// FPSAnimator animator = new FPSAnimator(60);
final Animator animator = new Animator();
- animator.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
+ animator.setUpdateFPSFrames(60, System.err);
animator.add(window);
-
+
window.addKeyListener(new KeyAdapter() {
- public void keyPressed(KeyEvent arg0) {
+ public void keyPressed(final KeyEvent arg0) {
if(arg0.getKeyCode() == KeyEvent.VK_F4) {
window.destroy();
}
}
});
window.addWindowListener(new WindowAdapter() {
- public void windowDestroyed(WindowEvent e) {
+ public void windowDestroyed(final WindowEvent e) {
animator.stop();
}
});
-
+
animator.start();
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo01.java
deleted file mode 100644
index d257f78fc..000000000
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo01.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.opengl.test.junit.graph.demos;
-
-
-import javax.media.opengl.FPSCounter;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLProfile;
-
-
-import com.jogamp.graph.curve.opengl.GLRegion;
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.opengl.SVertex;
-import com.jogamp.newt.event.KeyAdapter;
-import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.WindowAdapter;
-import com.jogamp.newt.event.WindowEvent;
-import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.glsl.ShaderState;
-
-public class GPUTextNewtDemo01 {
- static final boolean DEBUG = false;
- static final boolean TRACE = false;
-
- public static void main(String[] args) {
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
- caps.setSampleBuffers(true);
- caps.setNumSamples(4); // 2 samples is not enough ..
- System.out.println("Requested: "+caps);
-
- final GLWindow window = GLWindow.create(caps);
- window.setPosition(10, 10);
- window.setSize(800, 400);
- window.setTitle("GPU Text Newt Demo 01 - vbaa0 msaa1");
-
- final RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- GPUTextGLListener0A textGLListener = new GPUTextGLListener0A(rs, 0, 0, DEBUG, TRACE);
- window.addGLEventListener(textGLListener);
- window.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
-
- final Animator animator = new Animator();
- animator.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
- animator.add(window);
-
- window.addKeyListener(new KeyAdapter() {
- public void keyPressed(KeyEvent arg0) {
- if(arg0.getKeyCode() == KeyEvent.VK_F4) {
- window.destroy();
- }
- }
- });
- window.addWindowListener(new WindowAdapter() {
- public void windowDestroyed(WindowEvent e) {
- animator.stop();
- }
- });
-
- window.setVisible(true);
- // FPSAnimator animator = new FPSAnimator(10);
- animator.start();
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
index 7fb199a5d..bb688f9b3 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
@@ -34,15 +34,21 @@ import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLException;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.curve.opengl.TextRenderer;
+import com.jogamp.graph.curve.opengl.TextRegionUtil;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
-import com.jogamp.graph.geom.AABBox;
+import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.util.PMVMatrix;
/**
*
@@ -52,7 +58,7 @@ import com.jogamp.newt.opengl.GLWindow;
* - 0/9: rotate
* - v: toggle v-sync
* - s: screenshot
- *
+ *
* Additional Keys:
* - 3/4: font +/-
* - h: toogle draw 'font set'
@@ -61,254 +67,378 @@ import com.jogamp.newt.opengl.GLWindow;
* - i: live input text input (CR ends it, backspace supported)
*/
public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerBase01 {
+ public final TextRegionUtil textRegionUtil;
+ private final GLRegion regionFPS, regionBottom;
int fontSet = FontFactory.UBUNTU;
Font font;
-
+
int headType = 0;
- boolean drawFPS = false;
- final int fontSizeFixed = 6;
- int fontSize = 40;
+ boolean drawFPS = true;
+ final float fontSizeFName = 8f;
+ final float fontSizeFPS = 10f;
+ final int[] sampleCountFPS = new int[] { 8 };
+ float fontSizeHead = 12f;
+ float fontSizeBottom = 16f;
+ float dpiH = 96;
final int fontSizeModulo = 100;
String fontName;
AABBox fontNameBox;
String headtext;
AABBox headbox;
-
+
static final String text1 = "abcdefghijklmnopqrstuvwxyz\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]";
static final String text2 = "The quick brown fox jumps over the lazy dog";
- static final String textX =
+ static final String textX =
"JOGAMP graph demo using Resolution Independent NURBS\n"+
"JOGAMP JOGL - OpenGL ES2 profile\n"+
"Press 1/2 to zoom in/out the below text\n"+
+ "Press 3/4 to incr/decs font size (alt: head, w/o bottom)\n"+
"Press 6/7 to edit texture size if using VBAA\n"+
"Press 0/9 to rotate the below string\n"+
"Press v to toggle vsync\n"+
"Press i for live input text input (CR ends it, backspace supported)\n"+
- "Press f to toggle fps. H for different text, space for font type\n";
-
- static final String textX2 =
+ "Press f to toggle fps. H for different text, space for font type\n";
+
+ static final String textX2 =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec sapien tellus. \n"+
"Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+
"quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices ultricies nec a elit. \n"+
- "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia pharetra at venenatis est.\n"+
+ "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia pharetra at venenatis est.\n"+
"Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat nec, volutpat nec nisi.\n"+
"Donec ut dolor et nulla tristique varius. In nulla magna, fermentum id tempus quis, semper \n"+
"in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin. Quisque sit amet neque lorem,\n" +
- "-------Press H to change text---------\n";
-
+ "-------Press H to change text---------";
+
StringBuilder userString = new StringBuilder();
boolean userInput = false;
-
- public GPUTextRendererListenerBase01(RenderState rs, int modes, boolean debug, boolean trace) {
- super(TextRenderer.create(rs, modes), modes, debug, trace);
+ public GPUTextRendererListenerBase01(final RenderState rs, final int renderModes, final int sampleCount, final boolean blending, final boolean debug, final boolean trace) {
+ // NOTE_ALPHA_BLENDING: We use alpha-blending
+ super(RegionRenderer.create(rs, blending ? RegionRenderer.defaultBlendEnable : null,
+ blending ? RegionRenderer.defaultBlendDisable : null),
+ renderModes, debug, trace);
+ rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
+ this.textRegionUtil = new TextRegionUtil(renderModes);
+ this.regionFPS = GLRegion.create(renderModes, null);
+ this.regionBottom = GLRegion.create(renderModes, null);
try {
this.font = FontFactory.get(fontSet).getDefault();
dumpFontNames();
-
+
this.fontName = font.toString();
- this.fontNameBox = font.getStringBounds(fontName, fontSizeFixed*2);
- switchHeadBox();
- } catch (IOException ioe) {
- System.err.println("Catched: "+ioe.getMessage());
+ } catch (final IOException ioe) {
+ System.err.println("Caught: "+ioe.getMessage());
ioe.printStackTrace();
}
+ setMatrix(0, 0, 0, 0f, sampleCount);
}
void dumpFontNames() {
System.err.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
System.err.println(font.getAllNames(null, "\n"));
- System.err.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+ System.err.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
-
+
void switchHeadBox() {
- headType = ( headType + 1 ) % 4 ;
+ headType = ( headType + 1 ) % 4 ;
switch(headType) {
case 0:
headtext = null;
break;
-
+
case 1:
headtext= textX2;
break;
case 2:
headtext= textX;
break;
-
+
default:
- headtext = text1;
+ headtext = text1;
}
if(null != headtext) {
- headbox = font.getStringBounds(headtext, fontSizeFixed*3);
+ headbox = font.getMetricBounds(headtext, font.getPixelSize(fontSizeHead, dpiH));
+ }
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ super.init(drawable);
+ final Object upObj = drawable.getUpstreamWidget();
+ if( upObj instanceof Window ) {
+ final float[] pixelsPerMM = new float[2];
+ ((Window)upObj).getPixelsPerMM(pixelsPerMM);
+ dpiH = pixelsPerMM[1]*25.4f;
}
+ fontNameBox = font.getMetricBounds(fontName, font.getPixelSize(fontSizeFName, dpiH));
+ switchHeadBox();
+
}
- public void display(GLAutoDrawable drawable) {
- final int width = drawable.getWidth();
- final int height = drawable.getHeight();
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Demo02 needs to have this set here as well .. hmm ?
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int xstart, final int ystart, final int width, final int height) {
+ super.reshape(drawable, xstart, ystart, width, height);
+ final float dist = 100f;
+ nearPlaneX0 = nearPlane1Box.getMinX() * dist;
+ nearPlaneY0 = nearPlane1Box.getMinY() * dist;
+ nearPlaneZ0 = nearPlane1Box.getMinZ() * dist;
+ final float xd = nearPlane1Box.getWidth() * dist;
+ final float yd = nearPlane1Box.getHeight() * dist;
+ nearPlaneSx = xd / width;
+ nearPlaneSy = yd / height;
+ nearPlaneS = nearPlaneSy;
+ System.err.printf("Scale: [%f x %f] / [%d x %d] = [%f, %f] -> %f%n", xd, yd, width, height, nearPlaneSx, nearPlaneSy, nearPlaneS);
+ }
+ float nearPlaneX0, nearPlaneY0, nearPlaneZ0, nearPlaneSx, nearPlaneSy, nearPlaneS;
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ regionFPS.destroy(drawable.getGL().getGL2ES2());
+ regionBottom.destroy(drawable.getGL().getGL2ES2());
+ super.dispose(drawable);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final int width = drawable.getSurfaceWidth();
+ final int height = drawable.getSurfaceHeight();
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- final TextRenderer textRenderer = (TextRenderer) getRenderer();
- textRenderer.reshapeOrtho(null, width, height, 0.1f, 7000.0f);
- textRenderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f);
- final GLAnimatorControl animator = drawable.getAnimator();
- final boolean _drawFPS = drawFPS && null != animator && animator.getTotalFPSFrames()>10;
-
- if(_drawFPS) {
- final float fps = animator.getTotalFPS();
- final String fpsS = String.valueOf(fps);
- final int fpsSp = fpsS.indexOf('.');
- textRenderer.resetModelview(null);
- textRenderer.translate(gl, fontSizeFixed, fontSizeFixed, -6000);
- textRenderer.drawString3D(gl, font, fpsS.substring(0, fpsSp+2)+" fps", getPosition(), fontSizeFixed*3, getTexSize());
+ // final float zDistance0 = 500f;
+ // final float zDistance1 = 400f;
+ // final float[] objPos = new float[3];
+ // final float[] winZ = new float[1];
+ // final int[] view = new int[] { 0, 0, drawable.getWidth(), drawable.getHeight() };
+
+ final RegionRenderer renderer = getRenderer();
+ final RenderState rs = renderer.getRenderState();
+ final PMVMatrix pmv = renderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ rs.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f);
+ final float pixelSizeFName = font.getPixelSize(fontSizeFName, dpiH);
+ final float pixelSizeHead = font.getPixelSize(fontSizeHead, dpiH);
+ final float pixelSizeBottom = font.getPixelSize(fontSizeBottom, dpiH);
+
+ if( drawFPS ) {
+ final float pixelSizeFPS = font.getPixelSize(fontSizeFPS, dpiH);
+ final float lfps, tfps, td;
+ final GLAnimatorControl animator = drawable.getAnimator();
+ if( null != animator ) {
+ lfps = animator.getLastFPS();
+ tfps = animator.getTotalFPS();
+ td = animator.getTotalFPSDuration()/1000f;
+ } else {
+ lfps = 0f;
+ tfps = 0f;
+ td = 0f;
+ }
+ final String modeS = Region.getRenderModeString(regionFPS.getRenderModes());
+ final String text = String.format("%03.1f/%03.1f fps, v-sync %d, fontSize [head %.1f, bottom %.1f], %s-samples [%d, this %d], td %4.1f, blend %b, alpha-bits %d",
+ lfps, tfps, gl.getSwapInterval(), fontSizeHead, fontSizeBottom, modeS, getSampleCount()[0], sampleCountFPS[0], td,
+ renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED),
+ drawable.getChosenGLCapabilities().getAlphaBits());
+
+ // bottom, half line up
+ pmv.glTranslatef(nearPlaneX0, nearPlaneY0+(nearPlaneS * pixelSizeFPS / 2f), nearPlaneZ0);
+
+ // No cache, keep region alive!
+ TextRegionUtil.drawString3D(gl, regionFPS, renderer, font, nearPlaneS * pixelSizeFPS, text, null, sampleCountFPS,
+ textRegionUtil.tempT1, textRegionUtil.tempT2);
}
-
- int dx = width-(int)fontNameBox.getWidth()-2 ;
- int dy = height - 10;
-
- textRenderer.resetModelview(null);
- textRenderer.translate(gl, dx, dy, -6000);
- textRenderer.drawString3D(gl, font, fontName, getPosition(), fontSizeFixed*2, getTexSize());
-
- dx = 10;
- dy += -(int)fontNameBox.getHeight() - 10;
-
- if(null != headtext) {
- textRenderer.resetModelview(null);
- textRenderer.translate(gl, dx, dy, -6000);
- textRenderer.drawString3D(gl, font, headtext, getPosition(), fontSizeFixed*3, getTexSize());
+
+ float dx = width-fontNameBox.getWidth()-2f;
+ float dy = height - 10f;
+
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0);
+ // System.err.printf("FontN: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy));
+ textRegionUtil.drawString3D(gl, renderer, font, nearPlaneS * pixelSizeFName, fontName, null, getSampleCount());
+
+ dx = 10f;
+ dy += -fontNameBox.getHeight() - 10f;
+
+ if(null != headtext) {
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ // System.err.printf("Head: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy));
+ pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0);
+ // pmv.glTranslatef(x0, y1, z0);
+ textRegionUtil.drawString3D(gl, renderer, font, nearPlaneS * pixelSizeHead, headtext, null, getSampleCount());
}
-
- textRenderer.reshapePerspective(null, 45.0f, width, height, 0.1f, 7000.0f);
- textRenderer.resetModelview(null);
- textRenderer.translate(null, getXTran(), getYTran(), getZoom());
- textRenderer.rotate(gl, getAngle(), 0, 1, 0);
- textRenderer.setColorStatic(gl, 1.0f, 0.0f, 0.0f);
+ dy += -headbox.getHeight() - font.getLineHeight(pixelSizeBottom);
+
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0);
+ // System.err.printf("Bottom: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy));
+ pmv.glTranslatef(getXTran(), getYTran(), getZTran());
+ pmv.glRotatef(getAngle(), 0, 1, 0);
+ rs.setColorStatic(0.9f, 0.0f, 0.0f, 1.0f);
+
+ if( bottomTextUseFrustum ) {
+ regionBottom.setFrustum(pmv.glGetFrustum());
+ }
if(!userInput) {
- textRenderer.drawString3D(gl, font, text2, getPosition(), fontSize, getTexSize());
+ if( bottomTextUseFrustum ) {
+ TextRegionUtil.drawString3D(gl, regionBottom, renderer, font, nearPlaneS * pixelSizeBottom, text2, null, getSampleCount(),
+ textRegionUtil.tempT1, textRegionUtil.tempT2);
+ } else {
+ textRegionUtil.drawString3D(gl, renderer, font, nearPlaneS * pixelSizeBottom, text2, null, getSampleCount());
+ }
} else {
- textRenderer.drawString3D(gl, font, userString.toString(), getPosition(), fontSize, getTexSize());
+ if( bottomTextUseFrustum ) {
+ TextRegionUtil.drawString3D(gl, regionBottom, renderer, font, nearPlaneS * pixelSizeBottom, userString.toString(), null, getSampleCount(),
+ textRegionUtil.tempT1, textRegionUtil.tempT2);
+ } else {
+ textRegionUtil.drawString3D(gl, renderer, font, nearPlaneS * pixelSizeBottom, userString.toString(), null, getSampleCount());
+ }
}
- }
-
- public void fontIncr(int v) {
- fontSize = Math.abs((fontSize + v) % fontSizeModulo) ;
+ }
+ final boolean bottomTextUseFrustum = true;
+
+ public void fontBottomIncr(final int v) {
+ fontSizeBottom = Math.abs((fontSizeBottom + v) % fontSizeModulo) ;
dumpMatrix(true);
}
- public boolean nextFontSet() {
+ public void fontHeadIncr(final int v) {
+ fontSizeHead = Math.abs((fontSizeHead + v) % fontSizeModulo) ;
+ if(null != headtext) {
+ headbox = font.getMetricBounds(headtext, font.getPixelSize(fontSizeHead, dpiH));
+ }
+ }
+
+ public boolean nextFontSet() {
try {
- int set = ( fontSet == FontFactory.UBUNTU ) ? FontFactory.JAVA : FontFactory.UBUNTU ;
- Font _font = FontFactory.get(set).getDefault();
+ final int set = ( fontSet == FontFactory.UBUNTU ) ? FontFactory.JAVA : FontFactory.UBUNTU ;
+ final Font _font = FontFactory.get(set).getDefault();
if(null != _font) {
fontSet = set;
font = _font;
fontName = font.getFullFamilyName(null).toString();
- fontNameBox = font.getStringBounds(fontName, fontSizeFixed*3);
+ fontNameBox = font.getMetricBounds(fontName, font.getPixelSize(fontSizeFName, dpiH));
dumpFontNames();
return true;
}
- } catch (IOException ex) {
- System.err.println("Catched: "+ex.getMessage());
+ } catch (final IOException ex) {
+ System.err.println("Caught: "+ex.getMessage());
}
return false;
}
-
- public boolean setFontSet(int set, int family, int stylebits) {
+
+ public boolean setFontSet(final int set, final int family, final int stylebits) {
try {
- Font _font = FontFactory.get(set).get(family, stylebits);
+ final Font _font = FontFactory.get(set).get(family, stylebits);
if(null != _font) {
fontSet = set;
font = _font;
fontName = font.getFullFamilyName(null).toString();
- fontNameBox = font.getStringBounds(fontName, fontSizeFixed*3);
+ fontNameBox = font.getMetricBounds(fontName, font.getPixelSize(fontSizeFName, dpiH));
dumpFontNames();
return true;
}
- } catch (IOException ex) {
- System.err.println("Catched: "+ex.getMessage());
+ } catch (final IOException ex) {
+ System.err.println("Caught: "+ex.getMessage());
}
return false;
}
-
+
public boolean isUserInputMode() { return userInput; }
-
- void dumpMatrix(boolean bbox) {
- System.err.println("Matrix: " + getXTran() + "/" + getYTran() + " x"+getZoom() + " @"+getAngle() +" fontSize "+fontSize);
+
+ void dumpMatrix(final boolean bbox) {
+ System.err.println("Matrix: " + getXTran() + "/" + getYTran() + " x"+getZTran() + " @"+getAngle() +" fontSize "+fontSizeBottom);
if(bbox) {
- System.err.println("bbox: "+font.getStringBounds(text2, fontSize));
+ System.err.println("bbox: "+font.getMetricBounds(text2, nearPlaneS * font.getPixelSize(fontSizeBottom, dpiH)));
}
}
-
+
KeyAction keyAction = null;
-
+
@Override
- public void attachInputListenerTo(GLWindow window) {
+ public void attachInputListenerTo(final GLWindow window) {
if ( null == keyAction ) {
keyAction = new KeyAction();
window.addKeyListener(keyAction);
- super.attachInputListenerTo(window);
- }
+ super.attachInputListenerTo(window);
+ }
}
@Override
- public void detachInputListenerFrom(GLWindow window) {
+ public void detachInputListenerFrom(final GLWindow window) {
super.detachInputListenerFrom(window);
if ( null == keyAction ) {
return;
}
window.removeKeyListener(keyAction);
}
-
- public void printScreen(GLAutoDrawable drawable, String dir, String tech, boolean exportAlpha) throws GLException, IOException {
- final String fn = font.getFullFamilyName(null).toString();
+
+ public void printScreen(final GLAutoDrawable drawable, final String dir, final String tech, final boolean exportAlpha) throws GLException, IOException {
+ final String fn = font.getFullFamilyName(null).toString();
printScreen(drawable, dir, tech, fn.replace(' ', '_'), exportAlpha);
}
-
+
+ float fontHeadScale = 1f;
+
public class KeyAction implements KeyListener {
- public void keyPressed(KeyEvent arg0) {
+ @Override
+ public void keyPressed(final KeyEvent e) {
if(userInput) {
return;
}
-
- if(arg0.getKeyCode() == KeyEvent.VK_3) {
- fontIncr(10);
+ final short s = e.getKeySymbol();
+ if(s == KeyEvent.VK_3) {
+ if( e.isAltDown() ) {
+ fontHeadIncr(1);
+ } else {
+ fontBottomIncr(1);
+ }
}
- else if(arg0.getKeyCode() == KeyEvent.VK_4) {
- fontIncr(-10);
+ else if(s == KeyEvent.VK_4) {
+ if( e.isAltDown() ) {
+ fontHeadIncr(-1);
+ } else {
+ fontBottomIncr(-1);
+ }
}
- else if(arg0.getKeyCode() == KeyEvent.VK_H) {
+ else if(s == KeyEvent.VK_H) {
switchHeadBox();
- }
- else if(arg0.getKeyCode() == KeyEvent.VK_F) {
- drawFPS = !drawFPS;
- }
- else if(arg0.getKeyCode() == KeyEvent.VK_SPACE) {
+ }
+ else if(s == KeyEvent.VK_F) {
+ drawFPS = !drawFPS;
+ }
+ else if(s == KeyEvent.VK_SPACE) {
nextFontSet();
}
- else if(arg0.getKeyCode() == KeyEvent.VK_I) {
+ else if(s == KeyEvent.VK_I) {
userInput = true;
setIgnoreInput(true);
}
}
-
- public void keyTyped(KeyEvent arg0) {
- if(userInput) {
- char c = arg0.getKeyChar();
-
- if(c == 0x0d) {
+
+ @Override
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ if(userInput) {
+ final short k = e.getKeySymbol();
+ if( KeyEvent.VK_ENTER == k ) {
userInput = false;
setIgnoreInput(false);
- } else if(c == 0x08 && userString.length()>0) {
+ } else if( KeyEvent.VK_BACK_SPACE == k && userString.length()>0) {
userString.deleteCharAt(userString.length()-1);
- } else if( font.isPrintableChar( c ) ) {
- userString.append(c);
+ } else {
+ final char c = e.getKeyChar();
+ if( font.isPrintableChar( c ) ) {
+ userString.append(c);
+ }
}
}
}
- public void keyReleased(KeyEvent arg0) {}
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener02.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener02.java
new file mode 100644
index 000000000..80225c92d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener02.java
@@ -0,0 +1,9 @@
+package com.jogamp.opengl.test.junit.graph.demos;
+
+import com.jogamp.graph.curve.Region;
+
+public class GPUUISceneGLListener02 extends GPUUISceneGLListener0A {
+ public GPUUISceneGLListener02() {
+ super(Region.VBAA_RENDERING_BIT);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener04.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener04.java
new file mode 100644
index 000000000..461e2c114
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener04.java
@@ -0,0 +1,7 @@
+package com.jogamp.opengl.test.junit.graph.demos;
+
+public class GPUUISceneGLListener04 extends GPUUISceneGLListener0A {
+ public GPUUISceneGLListener04() {
+ super(GPUUISceneGLListener0A.DefaultNoAADPIThreshold /* noAADPIThreshold */);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java
index eaac2b1bf..685e3bd86 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java
@@ -1,7 +1,13 @@
package com.jogamp.opengl.test.junit.graph.demos;
+import java.io.File;
import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.media.nativewindow.util.Dimension;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAnimatorControl;
@@ -10,127 +16,253 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLPipelineFactory;
import javax.media.opengl.GLRunnable;
+import com.jogamp.common.net.Uri;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
-import com.jogamp.graph.geom.opengl.SVertex;
-import com.jogamp.newt.event.MouseAdapter;
+import com.jogamp.graph.geom.SVertex;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.PinchToZoomGesture;
+import com.jogamp.newt.event.GestureHandler.GestureEvent;
+import com.jogamp.newt.event.MouseEvent.PointerClass;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.test.junit.graph.demos.ui.CrossHair;
+import com.jogamp.opengl.test.junit.graph.demos.ui.GLEventListenerButton;
import com.jogamp.opengl.test.junit.graph.demos.ui.Label;
-import com.jogamp.opengl.test.junit.graph.demos.ui.RIButton;
+import com.jogamp.opengl.test.junit.graph.demos.ui.LabelButton;
+import com.jogamp.opengl.test.junit.graph.demos.ui.MediaPlayerButton;
+import com.jogamp.opengl.test.junit.graph.demos.ui.RoundButton;
import com.jogamp.opengl.test.junit.graph.demos.ui.SceneUIController;
-import com.jogamp.opengl.test.junit.graph.demos.ui.opengl.UIRegion;
-import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.test.junit.graph.demos.ui.ImageSeqButton;
+import com.jogamp.opengl.test.junit.graph.demos.ui.UIShape;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
+import com.jogamp.opengl.util.texture.ImageSequence;
+import com.jogamp.opengl.util.texture.TextureIO;
public class GPUUISceneGLListener0A implements GLEventListener {
private boolean debug = false;
- private boolean trace = false;
-
- private final int renderModes;
- private final int[] texSize = new int[1];
- private final int renderModes2;
- private final int[] texSize2 = new int[1];
- private RegionRenderer regionRenderer;
- private RenderState rs;
-
- int fontSet = FontFactory.UBUNTU;
- Font font;
- final int fontSizeFixed = 6;
-
- private float xTran = 0;
- private float yTran = 0;
- private float ang = 0f;
- private float zoom = -200f;
- private float zoomText = 1f;
+ private boolean trace = false;
+
+ private final float noAADPIThreshold;
+ private final RenderState rs;
+ private final SceneUIController sceneUIController;
+
+ /** -1 == AUTO, TBD @ init(..) */
+ private int renderModes;
+ private RegionRenderer renderer;
+
+ private final int fontSet = FontFactory.UBUNTU;
+ private Font font;
+
+ private final float sceneDist = 3000f;
+ private final float zNear = 0.1f, zFar = 7000f;
+
+ private final float relTop = 5f/6f;
+ private final float relMiddle = 2f/6f;
+ private final float relLeft = 1f/6f;
+
+ /** Proportional Button Size to Window Height, per-vertical-pixels [PVP] */
+ private final float buttonYSizePVP = 0.084f;
+ private final float buttonXSizePVP = 0.105f;
+ private final float fontSizePt = 10f;
+ /** Proportional Font Size to Window Height for Main Text, per-vertical-pixels [PVP] */
+ private final float fontSizeFixedPVP = 0.046f;
+ /** Proportional Font Size to Window Height for FPS Status Line, per-vertical-pixels [PVP] */
+ private final float fontSizeFpsPVP = 0.038f;
+ private float dpiH = 96;
+
+ /**
+ * Default DPI threshold value to disable {@link Region#VBAA_RENDERING_BIT VBAA}: {@value} dpi
+ * @see #GPUUISceneGLListener0A(float)
+ * @see #GPUUISceneGLListener0A(float, boolean, boolean)
+ */
+ public static final float DefaultNoAADPIThreshold = 200f;
+
private int currentText = 0;
-
+
+ private String actionText = null;
private Label[] labels = null;
private String[] strings = null;
- private UIRegion[] labelRegions;
- private UIRegion fpsRegion = null;
- private UIRegion jogampRegion = null;
- private RIButton[] buttons = null;
-
- private int numSelectable = 6;
-
- private SceneUIController sceneUIController = null;
- private MultiTouchListener multiTouchListener = null;
- private boolean showFPS = false;
+ private final List<RoundButton> buttons = new ArrayList<RoundButton>();
+ private int buttonsLeftCount = 0;
+ private Label truePtSizeLabel = null;
+ private Label jogampLabel = null;
+ private Label fpsLabel = null;
+ private CrossHair crossHairCtr = null;
+
+ private boolean ioAttached = false;
private GLAutoDrawable cDrawable;
- private float fps = 0;
-
- private String jogamp = "JogAmp - Jogl Graph Module Demo";
- private float angText = 0;
-
+
+ private final GLReadBufferUtil screenshot;
+
+ private final String jogamp = "JogAmp - Jogl Graph Module Demo";
+ private final String truePtSize = fontSizePt+" pt font size label - true scale!";
+
public GPUUISceneGLListener0A() {
this(0);
}
-
- public GPUUISceneGLListener0A(int renderModes) {
- this(RenderState.createRenderState(new ShaderState(), SVertex.factory()), renderModes, false, false);
+
+ /**
+ * @param noAADPIThreshold see {@link #DefaultNoAADPIThreshold}
+ */
+ public GPUUISceneGLListener0A(final float noAADPIThreshold) {
+ this(noAADPIThreshold, false, false);
}
-
- public GPUUISceneGLListener0A(RenderState rs, int renderModes, boolean debug, boolean trace) {
- this.rs = rs;
- this.renderModes = renderModes;
- this.texSize[0] = Region.isVBAA(renderModes) ? 400 : 0;
- this.renderModes2 = 0;
- this.texSize2[0] = 0;
-
+
+ /**
+ * @param renderModes
+ */
+ public GPUUISceneGLListener0A(final int renderModes) {
+ this(renderModes, false, false);
+ }
+
+ /**
+ * @param renderModes
+ * @param debug
+ * @param trace
+ */
+ public GPUUISceneGLListener0A(final int renderModes, final boolean debug, final boolean trace) {
+ this(0f, renderModes, debug, trace);
+ }
+
+ /**
+ * @param noAADPIThreshold see {@link #DefaultNoAADPIThreshold}
+ * @param debug
+ * @param trace
+ */
+ public GPUUISceneGLListener0A(final float noAADPIThreshold, final boolean debug, final boolean trace) {
+ this(noAADPIThreshold, 0, debug, trace);
+ }
+
+ private GPUUISceneGLListener0A(final float noAADPIThreshold, final int renderModes, final boolean debug, final boolean trace) {
+ this.noAADPIThreshold = noAADPIThreshold;
+ this.rs = RenderState.createRenderState(SVertex.factory());
this.debug = debug;
this.trace = trace;
+
+ this.renderModes = renderModes;
+
try {
font = FontFactory.get(FontFactory.UBUNTU).getDefault();
- } catch (IOException ioe) {
- System.err.println("Catched: "+ioe.getMessage());
- ioe.printStackTrace();
+ } catch (final IOException ioe) {
+ throw new RuntimeException(ioe);
}
- labelRegions = new UIRegion[3];
- sceneUIController = new SceneUIController();
+ sceneUIController = new SceneUIController(sceneDist, zNear, zFar);
+ screenshot = new GLReadBufferUtil(false, false);
}
-
- private void initButtons(int width, int height) {
- buttons = new RIButton[numSelectable];
- int xaxis = -110;
- float xSize = 40f;
- float ySize = 16f;
-
- int start = 50;
- int diff = (int)ySize + 5;
-
- buttons[0] = new RIButton(SVertex.factory(), font, "Next Text", xSize, ySize){
- public void onClick() {
- currentText = (currentText+1)%3;
+
+ private void rotateButtons(float[] angdeg) {
+ angdeg = VectorUtil.scaleVec3(angdeg, angdeg, FloatUtil.PI / 180.0f);
+ for(int i=0; i<buttons.size(); i++) {
+ buttons.get(i).getRotation().rotateByEuler( angdeg );
+ }
+ }
+ private void translateButtons(final float tx, final float ty, final float tz) {
+ for(int i=0; i<buttons.size(); i++) {
+ buttons.get(i).translate(tx, ty, tz);
+ }
+ }
+
+ private void setButtonsSpacing(final float dx, final float dy) {
+ for(int i=0; i<buttons.size(); i++) {
+ final RoundButton b = buttons.get(i);
+ if( b instanceof LabelButton ) {
+ final LabelButton lb = (LabelButton) b;
+ final float sx = lb.getSpacingX()+dx, sy = lb.getSpacingY()+dy;
+ System.err.println("Spacing: X "+sx+", Y "+sy);
+ lb.setSpacing(sx, sy);
}
- public void onPressed() { }
- public void onRelease() { }
- };
-
- buttons[0].setPosition(xaxis,start,0);
-
- buttons[1] = new RIButton(SVertex.factory(), font, "Show FPS", xSize, ySize){
- public void onClick() {
+ }
+ }
+
+ private void setButtonsCorner(final float dc) {
+ for(int i=0; i<buttons.size(); i++) {
+ final float c = buttons.get(i).getCorner()+dc;
+ System.err.println("Corner: "+c);
+ buttons.get(i).setCorner(c);
+ }
+ }
+
+ private void resetButtons() {
+ for(int i=0; i<buttons.size(); i++) {
+ final RoundButton b = buttons.get(i);
+ b.getRotation().setIdentity();
+ b.setCorner(RoundButton.DEFAULT_CORNER);
+ if( b instanceof LabelButton ) {
+ ((LabelButton)b).setSpacing(LabelButton.DEFAULT_SPACING_X, LabelButton.DEFAULT_SPACING_Y);
+ }
+ }
+ }
+
+ private void initButtons(final GL2ES2 gl, final int width, final int height, final RegionRenderer renderer) {
+ final boolean pass2Mode = Region.isTwoPass( renderModes ) ;
+ buttons.clear();
+
+ final float buttonXSize = buttonXSizePVP * width;
+ // final float buttonYSize = buttonYSizePVP * height;
+ final float buttonYSize = buttonXSize / 2.5f;
+ System.err.println("Button Size: "+buttonXSizePVP+" x "+buttonYSizePVP+" * "+width+" x "+height+" -> "+buttonXSize+" x "+buttonYSize);
+ final float xStartLeft = 0f; // aligned to left edge w/ space via reshape
+ final float yStartTop = 0f; // aligned to top edge w/ space via reshape
+ final float diffX = 1.2f * buttonXSize;
+ final float diffY = 1.5f * buttonYSize;
+
+ LabelButton button = new LabelButton(SVertex.factory(), renderModes, font, "Next Text", buttonXSize, buttonYSize);
+ button.translate(xStartLeft,yStartTop-diffY*buttons.size(), 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ if( null != labels[currentText] ) {
+ labels[currentText].setEnabled(false);
+ }
+ currentText = (currentText+1)%labels.length;
+ if( null != labels[currentText] ) {
+ labels[currentText].setEnabled(true);
+ }
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+
+ button = new LabelButton(SVertex.factory(), renderModes, font, "Show FPS", buttonXSize, buttonYSize);
+ button.setName(100); // FIXME: DEBUG tag
+ button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
+ button.setToggleable(true);
+ button.setToggle(fpsLabel.isEnabled());
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
final GLAnimatorControl a = cDrawable.getAnimator();
if( null != a ) {
a.resetFPSCounter();
}
- showFPS = !showFPS;
- }
- public void onPressed() { }
- public void onRelease() { }
- };
- buttons[1].setPosition(xaxis,start - diff,0);
- buttons[1].setToggleable(true);
-
- buttons[2] = new RIButton(SVertex.factory(), font, "v-sync", xSize, ySize){
- public void onClick() {
+ fpsLabel.setEnabled(!fpsLabel.isEnabled());
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+
+ button = new LabelButton(SVertex.factory(), renderModes, font, "v-sync", buttonXSize, buttonYSize);
+ button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
+ button.setToggleable(true);
+ button.setToggle(gl.getSwapInterval()>0);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
cDrawable.invoke(false, new GLRunnable() {
- public boolean run(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
gl.setSwapInterval(gl.getSwapInterval()<=0?1:0);
final GLAnimatorControl a = drawable.getAnimator();
if( null != a ) {
@@ -139,76 +271,426 @@ public class GPUUISceneGLListener0A implements GLEventListener {
return true;
}
});
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+
+ button = new LabelButton(SVertex.factory(), renderModes, font, "< tilt >", buttonXSize, buttonYSize);
+ button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
+ rotateButtons(new float[] { 0f, -5f, 0f}); // left-half pressed
+ } else {
+ rotateButtons(new float[] { 0f, 5f, 0f}); // right-half pressed
+ }
+ }
}
- public void onPressed() { }
- public void onRelease() { }
- };
- buttons[2].setPosition(xaxis,start-diff*2,0);
- buttons[2].setToggleable(true);
-
- buttons[3] = new RIButton(SVertex.factory(), font, "Tilt +Y", xSize, ySize) {
- public void onClick() {
- ang+=10;
- }
- public void onPressed() {
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
+ rotateButtons(new float[] { 0f, e.getRotation()[1], 0f});
+ } } );
+ buttons.add(button);
+
+ if( pass2Mode ) { // second column to the left
+ button = new LabelButton(SVertex.factory(), renderModes, font, "< samples >", buttonXSize, buttonYSize);
+ button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ int sampleCount = sceneUIController.getSampleCount();
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
+ // left-half pressed
+ sampleCount--;
+ } else {
+ // right-half pressed
+ sampleCount++;
+ }
+ sampleCount = sceneUIController.setSampleCount(sampleCount); // validated / clipped
+ }
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+
+ button = new LabelButton(SVertex.factory(), renderModes, font, "< quality >", buttonXSize, buttonYSize);
+ button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ int quality = shapeEvent.shape.getQuality();
+
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
+ // left-half pressed
+ if( quality > 0 ) {
+ quality--;
+ }
+ } else {
+ // right-half pressed
+ if( quality < Region.MAX_QUALITY ) {
+ quality++;
+ }
+ }
+ sceneUIController.setAllShapesQuality(quality);
+ }
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+ }
+
+ button = new LabelButton(SVertex.factory(), renderModes, font, "Quit", buttonXSize, buttonYSize);
+ button.translate(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
+ button.setColor(0.7f, 0.0f, 0.0f, 1.0f);
+ button.setLabelColor(1.2f, 1.2f, 1.2f);
+ button.setPressedColorMod(1.1f, 0.0f, 0.0f, 1.0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ new Thread() {
+ public void run() {
+ if( null != cDrawable ) {
+ final GLAnimatorControl actrl = cDrawable.getAnimator();
+ if( null != actrl ) {
+ actrl.stop();
+ }
+ cDrawable.destroy();
+ }
+ } }.start();
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+
+ // second column to the left
+ {
+ final int j = 1; // column
+ int k = 0; // row
+ button = new LabelButton(SVertex.factory(), renderModes, font, "y flip", buttonXSize, buttonYSize);
+ button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ rotateButtons(new float[] { 0f, 180f, 0f});
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+
+ k++;
+ button = new LabelButton(SVertex.factory(), renderModes, font, "x flip", buttonXSize, buttonYSize);
+ button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ rotateButtons(new float[] { 180f, 0f, 0f});
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+ k++;
+
+ button = new LabelButton(SVertex.factory(), renderModes, font, "+", buttonXSize, buttonYSize);
+ button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ // rel position to center
+ final float dx = shapeEvent.objPos[0] - shapeEvent.shape.getBounds().getCenter()[0] ;
+ final float dy = shapeEvent.objPos[1] - shapeEvent.shape.getBounds().getCenter()[1] ;
+ // per-cent position to center (remove dependency on dimension)
+ final float awdx = Math.abs(dx)/shapeEvent.shape.getBounds().getWidth();
+ final float awdy = Math.abs(dy)/shapeEvent.shape.getBounds().getHeight();
+ float tx = 0, ty = 0;
+ if ( awdx > awdy ) {
+ tx = dx < 0 ? -5 : 5;
+ } else {
+ ty = dy < 0 ? -5 : 5;
+ }
+ translateButtons(tx, ty, 0f);
+ }
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+ k++;
+
+ button = new LabelButton(SVertex.factory(), renderModes, font, "< space >", buttonXSize, buttonYSize);
+ button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ final float dx, dy;
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
+ dx=-0.01f; dy=-0.005f;
+ } else {
+ dx=0.01f; dy=0.005f;
+ }
+ setButtonsSpacing(dx, dy);
+ }
+ }
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
+ setButtonsSpacing(e.getRotation()[0]/100f, e.getRotation()[1]/200f);
+ } } );
+ buttons.add(button);
+ k++;
+
+ button = new LabelButton(SVertex.factory(), renderModes, font, "< corner >", buttonXSize, buttonYSize);
+ button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ final float dc;
+ if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) {
+ dc=-0.1f;
+ } else {
+ dc=0.1f;
+ }
+ setButtonsCorner(dc);
+ }
+
+ }
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
+ setButtonsCorner(e.getRotation()[1]/20f);
+ } } );
+ buttons.add(button);
+ k++;
+
+ button = new LabelButton(SVertex.factory(), renderModes, font, "reset", buttonXSize, buttonYSize);
+ button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ resetButtons();
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+ k++;
+
+ button = new LabelButton(SVertex.factory(), renderModes, font, "screenshot", buttonXSize, buttonYSize);
+ button.translate(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ cDrawable.invoke(false, new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ printScreen(drawable.getGL());
+ return true;
+ }
+ });
+ } } );
+ button.addMouseListener(dragZoomRotateListener);
+ buttons.add(button);
+ k++;
+ }
+
+ buttonsLeftCount = buttons.size();
+
+ final float button2XSize = 2f*buttonXSize;
+ final float button2YSize = 2f*buttonYSize;
+ final float xStartRight = -button2XSize - 8f; // aligned to right edge via reshape
+ final int texUnitMediaPlayer, texUnitImageButton, texUnitGLELButton;
+ if( false ) {
+ texUnitMediaPlayer=0;
+ texUnitImageButton=0;
+ texUnitGLELButton=0;
+ } else {
+ // works - but not required ..
+ texUnitMediaPlayer=1;
+ texUnitImageButton=2;
+ texUnitGLELButton=3;
+ }
+ if( true ) {
+ final GLMediaPlayer mPlayer = GLMediaPlayerFactory.createDefault();
+ mPlayer.setTextureUnit(texUnitMediaPlayer);
+ final MediaPlayerButton mPlayerButton = new MediaPlayerButton(renderer.getRenderState().getVertexFactory(), renderModes,
+ button2XSize, button2YSize, mPlayer);
+ mPlayerButton.addDefaultEventListener();
+ mPlayerButton.translate(xStartRight, yStartTop - diffY*1, 0f);
+ mPlayerButton.setToggleable(true);
+ mPlayerButton.setToggle(false); // toggle == false -> mute audio
+ mPlayerButton.setToggleOffColorMod(0f, 1f, 0f, 1.0f);
+ mPlayerButton.addMouseListener(dragZoomRotateListener);
+ mPlayerButton.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ mPlayer.setAudioVolume( mPlayerButton.isToggleOn() ? 1f : 0f );
+ } } );
+ buttons.add(mPlayerButton);
+ try {
+ final Uri streamLoc = Uri.cast("http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ mPlayer.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
+ } catch (final URISyntaxException e1) {
+ e1.printStackTrace();
}
- public void onRelease() { }
- };
- buttons[3].setPosition(xaxis,start-diff*3,0);
-
- buttons[4] = new RIButton(SVertex.factory(), font, "Tilt -Y", xSize, ySize){
- public void onClick() {
- ang-=10;
+ }
+ if( true ) {
+ final ImageSequence imgSeq = new ImageSequence(texUnitImageButton, true);
+ final ImageSeqButton imgButton = new ImageSeqButton(renderer.getRenderState().getVertexFactory(), renderModes,
+ button2XSize, button2YSize, imgSeq);
+ try {
+ imgSeq.addFrame(gl, GPUUISceneGLListener0A.class, "button-released-145x53.png", TextureIO.PNG);
+ imgSeq.addFrame(gl, GPUUISceneGLListener0A.class, "button-pressed-145x53.png", TextureIO.PNG);
+ } catch (final IOException e2) {
+ e2.printStackTrace();
}
- public void onPressed() { }
- public void onRelease() { }
- };
- buttons[4].setPosition(xaxis,start-diff*4,0);
-
- buttons[5] = new RIButton(SVertex.factory(), font, "Quit", xSize, ySize){
- public void onClick() {
- cDrawable.destroy();
+ imgSeq.setManualStepping(true);
+ imgButton.translate(xStartRight, yStartTop - diffY*2.5f, 0f);
+ imgButton.addMouseListener(dragZoomRotateListener);
+ imgButton.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mousePressed(final MouseEvent e) {
+ imgButton.setCurrentIdx(1);
+ System.err.println("XXX: "+imgButton);
+ }
+ @Override
+ public void mouseReleased(final MouseEvent e) {
+ imgButton.setCurrentIdx(0);
+ } } );
+ buttons.add(imgButton);
+ }
+ if( true ) {
+ // Issues w/ OSX and NewtCanvasAWT when rendering / animating
+ // Probably related to CALayer - FBO - FBO* (of this button)
+ final GLEventListener glel;
+ if( true ) {
+ final GearsES2 gears = new GearsES2(0);
+ gears.setVerbose(false);
+ gears.setClearColor(new float[] { 0.9f, 0.9f, 0.9f, 1f } );
+ glel = gears;
+ } else if( false ) {
+ glel = new RedSquareES2(0);
+ } else {
+ glel = new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
+ // gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ }
+
+ };
}
- public void onPressed() { }
- public void onRelease() { }
- };
- buttons[5].setPosition(xaxis,start-diff*5,0);
- buttons[5].setButtonColor(0.8f, 0.0f, 0.0f);
- buttons[5].setLabelColor(1.0f, 1.0f, 1.0f);
-
- buttons[5].setButtonSelectedColor(0.8f, 0.8f, 0.8f);
- buttons[5].setLabelSelectedColor(0.8f, 0.0f, 0.0f);
+ final GLEventListenerButton glelButton = new GLEventListenerButton(renderer.getRenderState().getVertexFactory(), renderModes,
+ button2XSize, button2YSize,
+ texUnitGLELButton, glel, false /* useAlpha */,
+ (int)(button2XSize), (int)(button2YSize));
+ glelButton.setToggleable(true);
+ glelButton.setToggle(false); // toggle == true -> animation
+ glelButton.setAnimate(false);
+ glelButton.translate(xStartRight, yStartTop - diffY*4f, 0f);
+ glelButton.addMouseListener(dragZoomRotateListener);
+ glelButton.addMouseListener(new UIShape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ glelButton.setAnimate( glelButton.isToggleOn() );
+ } } );
+ buttons.add(glelButton);
+ }
}
-
+
private void initTexts() {
- strings = new String[3];
-
- strings[0] = "abcdefghijklmn\nopqrstuvwxyz\nABCDEFGHIJKL\nMNOPQRSTUVWXYZ\n0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]";
- strings[1] = "The quick brown fox\njumps over the lazy\ndog";
-
- strings[2] =
- "Lorem ipsum dolor sit amet, consectetur\n"+
- "Ut purus odio, rhoncus sit amet com\n"+
- "quam iaculis urna cursus ornare. Nullam\n"+
- "In hac habitasse platea dictumst. Vivam\n"+
- "Morbi quis bibendum nibh. Donec lectus\n"+
- "Donec ut dolor et nulla tristique variu\n"+
- "in lorem. Maecenas in ipsum ac justo sc\n";
-
- labels = new Label[3];
+ strings = new String[4];
+ int i = 0;
+
+ strings[i++] =
+ "- Mouse Scroll Over Object\n"+
+ " - General\n"+
+ " - Z Translation\n"+
+ " - Ctrl: Y-Rotation (Shift: X-Rotation)\n"+
+ " - Tilt, Space and Corner\n"+
+ " - Their respective action via wheel\n"+
+ " (shift = other value)\n"+
+ "\n"+
+ "- Mouse Drag On Object\n"+
+ " - Click on Object and drag mouse\n"+
+ " - Current postion in status line at bottom\n"+
+ "\n"+
+ "- Tilt Button Rotate Whole Button Group";
+
+ strings[i++] = "abcdefghijklmn\nopqrstuvwxyz\n"+
+ "ABCDEFGHIJKL\n"+
+ "MNOPQRSTUVWXYZ\n"+
+ "0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]";
+
+ strings[i++] = "The quick brown fox\njumps over the lazy\ndog";
+
+ strings[i++] =
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec \n"+
+ "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel\n"+
+ "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices\n"+
+ "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia\n"+
+ "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat\n"+
+ "Donec ut dolor et nulla tristique varius. In nulla magna, fermentum\n"+
+ "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin.\n";
+
+ labels = new Label[i];
}
- public void init(GLAutoDrawable drawable) {
+
+ final boolean enableOthers = true;
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final Object upObj = drawable.getUpstreamWidget();
+ if( upObj instanceof Window ) {
+ final Window upWin = (Window)upObj;
+ final MonitorDevice mm = upWin.getMainMonitor();
+ final float[] monitorPixelsPerMM = mm.getPixelsPerMM(new float[2]);
+ final float monitorDpiH = monitorPixelsPerMM[1]*25.4f;
+ final float[] surfacePixelsPerMM = upWin.getPixelsPerMM(new float[2]);
+ dpiH = surfacePixelsPerMM[1]*25.4f;
+ System.err.println("Monitor detected: "+mm);
+ System.err.println("Monitor dpi: "+monitorDpiH);
+ System.err.println("Surface scale: native "+new Dimension(upWin.getNativeSurfaceScale(new int[2]))+", current "+new Dimension(upWin.getCurrentSurfaceScale(new int[2])));
+ System.err.println("Surface dpi: "+dpiH);
+ } else {
+ System.err.println("Using default DPI of "+dpiH);
+ }
+ if( 0 == renderModes && !FloatUtil.isZero(noAADPIThreshold, FloatUtil.EPSILON)) {
+ final boolean noAA = dpiH >= noAADPIThreshold;
+ final String noAAs = noAA ? " >= " : " < ";
+ System.err.println("AUTO RenderMode: dpi "+dpiH+noAAs+noAADPIThreshold+" -> noAA "+noAA);
+ renderModes = noAA ? 0 : Region.VBAA_RENDERING_BIT;
+ }
if(drawable instanceof GLWindow) {
System.err.println("GPUUISceneGLListener0A: init (1)");
final GLWindow glw = (GLWindow) drawable;
attachInputListenerTo(glw);
} else {
- System.err.println("GPUUISceneGLListener0A: init (0)");
+ System.err.println("GPUUISceneGLListener0A: init (0)");
}
- final int width = drawable.getWidth();
- final int height = drawable.getHeight();
+ System.err.println("Chosen: "+drawable.getChosenGLCapabilities());
cDrawable = drawable;
GL2ES2 gl = drawable.getGL().getGL2ES2();
if(debug) {
@@ -217,219 +699,290 @@ public class GPUUISceneGLListener0A implements GLEventListener {
if(trace) {
gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2();
}
-
+
try {
font = FontFactory.get(fontSet).getDefault();
- } catch (IOException ioe) {
- System.err.println("Catched: "+ioe.getMessage());
- ioe.printStackTrace();
- }
-
- regionRenderer = RegionRenderer.create(rs, renderModes);
-
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
- gl.glEnable(GL2ES2.GL_BLEND);
-
- regionRenderer.init(gl);
- regionRenderer.setAlpha(gl, 1.0f);
- regionRenderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f);
-
+ } catch (final IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+
+ renderer = RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
+ rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
+ // renderer = RegionRenderer.create(rs, null, null);
+
+ gl.setSwapInterval(1);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_BLEND);
+
+ renderer.init(gl, renderModes);
+
initTexts();
- initButtons(width, height);
-
- sceneUIController.setRenderer(regionRenderer, rs, renderModes, texSize);
- sceneUIController.addShape(buttons[0]);
- sceneUIController.addShape(buttons[1]);
- sceneUIController.addShape(buttons[2]);
- sceneUIController.addShape(buttons[3]);
- sceneUIController.addShape(buttons[4]);
- sceneUIController.addShape(buttons[5]);
- drawable.addGLEventListener(sceneUIController);
-
- Label jlabel = new Label(SVertex.factory(), font, fontSizeFixed, jogamp){
- public void onClick() { }
- public void onPressed() { }
- public void onRelease() { }
- };
-
- jogampRegion = new UIRegion(jlabel);
+
+ sceneUIController.setRenderer(renderer);
+
+ final float pixelSizeFixed = fontSizeFixedPVP * drawable.getSurfaceHeight();
+ jogampLabel = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSizeFixed, jogamp);
+ jogampLabel.addMouseListener(dragZoomRotateListener);
+ sceneUIController.addShape(jogampLabel);
+ jogampLabel.setEnabled(enableOthers);
+
+ final float pixelSize10Pt = font.getPixelSize(fontSizePt, dpiH);
+ System.err.println("10Pt PixelSize: Display "+dpiH+" dpi, fontSize "+fontSizePt+" ppi -> "+pixelSize10Pt+" pixel-size");
+ truePtSizeLabel = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSize10Pt, truePtSize);
+ sceneUIController.addShape(truePtSizeLabel);
+ truePtSizeLabel.setEnabled(enableOthers);
+ truePtSizeLabel.translate(0, - 1.5f * jogampLabel.getLineHeight(), 0f);
+ truePtSizeLabel.setColor(0.1f, 0.1f, 0.1f, 1.0f);
+
+ /**
+ *
+ * [Label] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 18.814816
+ * [FPS] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 15.679012
+ */
+ final float pixelSizeFPS = fontSizeFpsPVP * drawable.getSurfaceHeight();
+ fpsLabel = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSizeFPS, "Nothing there yet");
+ fpsLabel.addMouseListener(dragZoomRotateListener);
+ sceneUIController.addShape(fpsLabel);
+ fpsLabel.setEnabled(enableOthers);
+ fpsLabel.setColor(0.3f, 0.3f, 0.3f, 1.0f);
+
+ crossHairCtr = new CrossHair(renderer.getRenderState().getVertexFactory(), 0, 100f, 100f, 2f);
+ crossHairCtr.addMouseListener(dragZoomRotateListener);
+ sceneUIController.addShape(crossHairCtr);
+ crossHairCtr.setEnabled(true);
+ crossHairCtr.translate(0f, 0f, -1f);
+
+ initButtons(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), renderer);
+ for(int i=0; i<buttons.size(); i++) {
+ sceneUIController.addShape(buttons.get(i));
+ }
+
+ sceneUIController.init(drawable);
+
final GLAnimatorControl a = drawable.getAnimator();
if( null != a ) {
a.resetFPSCounter();
- }
+ }
}
- public void dispose(GLAutoDrawable drawable) {
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
if(drawable instanceof GLWindow) {
System.err.println("GPUUISceneGLListener0A: dispose (1)");
final GLWindow glw = (GLWindow) drawable;
detachInputListenerFrom(glw);
} else {
- System.err.println("GPUUISceneGLListener0A: dispose (0)");
+ System.err.println("GPUUISceneGLListener0A: dispose (0)");
+ }
+
+ sceneUIController.dispose(drawable); // disposes all registered UIShapes
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ renderer.destroy(gl);
+ screenshot.dispose(gl);
+ }
+
+ private int shotCount = 0;
+
+ public void printScreen(final GL gl) {
+ final String modeS = Region.getRenderModeString(jogampLabel.getRenderModes());
+ final String filename = String.format("GraphUIDemo-shot%03d-%03dx%03d-S_%s_%02d.png",
+ shotCount++, renderer.getWidth(), renderer.getHeight(),
+ modeS, sceneUIController.getSampleCount());
+ gl.glFinish(); // just make sure rendering finished ..
+ if(screenshot.readPixels(gl, false)) {
+ screenshot.write(new File(filename));
+ System.err.println("Wrote: "+filename);
}
-
- drawable.removeGLEventListener(sceneUIController);
- sceneUIController.dispose(drawable);
-
- GL2ES2 gl = drawable.getGL().getGL2ES2();
- regionRenderer.destroy(gl);
}
- public void display(GLAutoDrawable drawable) {
+ @Override
+ public void display(final GLAutoDrawable drawable) {
// System.err.println("GPUUISceneGLListener0A: display");
- final int width = drawable.getWidth();
- final int height = drawable.getHeight();
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
-
- regionRenderer.reshapePerspective(null, 45.0f, width, height, 0.1f, 7000.0f);
- sceneUIController.setTranslate(xTran, yTran, zoom);
- sceneUIController.setRotation(0, ang, 0);
-
- renderScene(drawable);
- }
-
- private void renderScene(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- regionRenderer.resetModelview(null);
- regionRenderer.translate(null, xTran-50, yTran+43, zoom);
- regionRenderer.translate(gl, 0, 30, 0);
- regionRenderer.scale(null, zoomText, zoomText, 1);
- regionRenderer.scale(gl, 1.5f, 1.5f, 1.0f);
- regionRenderer.rotate(gl, angText , 0, 1, 0);
- regionRenderer.setColorStatic(gl, 0.0f, 1.0f, 0.0f);
- regionRenderer.draw(gl, jogampRegion.getRegion(gl, rs, 0), new float[]{0,0,0}, null);
-
- if(null == labelRegions[currentText]) {
- if( null == labels[currentText]) {
- labels[currentText] = new Label(SVertex.factory(), font, fontSizeFixed, strings[currentText]){
- public void onClick() { }
- public void onPressed() { }
- public void onRelease() { }
- };
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ if(null == labels[currentText]) {
+ final float pixelSizeFixed = fontSizeFixedPVP * drawable.getSurfaceHeight();
+ final float dyTop = drawable.getSurfaceHeight() - 2f*jogampLabel.getLineHeight();
+ final float dxMiddle = drawable.getSurfaceWidth() * relMiddle;
+ labels[currentText] = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSizeFixed, strings[currentText]);
+ labels[currentText].setColor(0.1f, 0.1f, 0.1f, 1.0f);
+ labels[currentText].setEnabled(enableOthers);
+ labels[currentText].translate(dxMiddle,
+ dyTop - 1.5f * jogampLabel.getLineHeight()
+ - 1.5f * truePtSizeLabel.getLineHeight(), 0f);
+ labels[currentText].addMouseListener(dragZoomRotateListener);
+ sceneUIController.addShape(labels[currentText]);
+ System.err.println("Label["+currentText+"] CTOR: "+labels[currentText]);
+ System.err.println("Label["+currentText+"] CTOR: "+Arrays.toString(labels[currentText].getTranslate()));
+ }
+ if( fpsLabel.isEnabled() ) {
+ final float lfps, tfps, td;
+ final GLAnimatorControl animator = drawable.getAnimator();
+ if( null != animator ) {
+ lfps = animator.getLastFPS();
+ tfps = animator.getTotalFPS();
+ td = animator.getTotalFPSDuration()/1000f;
+ } else {
+ lfps = 0f;
+ tfps = 0f;
+ td = 0f;
}
- labelRegions[currentText] = new UIRegion(labels[currentText]);
- }
-
- regionRenderer.resetModelview(null);
- regionRenderer.translate(null, xTran-50, yTran, zoom);
- regionRenderer.translate(gl, 0, 30, 0);
- regionRenderer.scale(null, zoomText, zoomText, 1);
- regionRenderer.scale(gl, 1.5f, 1.5f, 1.0f);
- regionRenderer.rotate(gl, zoomText, 0, 1, 0);
-
- regionRenderer.setColorStatic(gl, 0.0f, 0.0f, 0.0f);
- regionRenderer.draw(gl, labelRegions[currentText].getRegion(gl, rs, renderModes2), new float[]{0,0,0}, texSize2);
-
- final GLAnimatorControl animator = drawable.getAnimator();
- final boolean _drawFPS = showFPS && null != animator;
-
- if(_drawFPS && fps != animator.getTotalFPS()) {
- if(null != fpsRegion) {
- fpsRegion.destroy(gl, rs);
+ final String modeS = Region.getRenderModeString(renderModes);
+ final String text;
+ if( null == actionText ) {
+ final String timePrec = gl.isGLES() ? "4.0" : "4.1";
+ text = String.format("%03.1f/%03.1f fps, v-sync %d, dpi %.1f, fontSize %.1f, %s-samples %d, q %d, td %"+timePrec+"f, blend %b, alpha %d, msaa %d",
+ lfps, tfps, gl.getSwapInterval(), dpiH, fontSizeFixedPVP, modeS, sceneUIController.getSampleCount(), fpsLabel.getQuality(), td,
+ renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED),
+ drawable.getChosenGLCapabilities().getAlphaBits(),
+ drawable.getChosenGLCapabilities().getNumSamples());
+ } else {
+ text = String.format("%03.1f/%03.1f fps, v-sync %d, fontSize %.1f, %s",
+ lfps, tfps, gl.getSwapInterval(), fontSizeFixedPVP, actionText);
}
- fps = animator.getTotalFPS();
- final String fpsS = String.valueOf(fps);
- final int fpsSp = fpsS.indexOf('.');
-
- Label fpsLabel = new Label(SVertex.factory(), font, fontSizeFixed, fpsS.substring(0, fpsSp+2)+" fps"){
- public void onClick() { }
- public void onPressed() { }
- public void onRelease() { }
- };
- fpsRegion = new UIRegion(fpsLabel);
- }
- if(showFPS && null != fpsRegion) {
- regionRenderer.translate(gl, 0, -60, 0);
- regionRenderer.scale(null, zoomText, zoomText, 1);
- regionRenderer.draw(gl, fpsRegion.getRegion(gl, rs, 0), new float[]{0,0,0}, null);
+ fpsLabel.setText(text);
}
+ sceneUIController.display(drawable);
}
-
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+
+
+ float lastWidth = 0f, lastHeight = 0f;
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
System.err.println("GPUUISceneGLListener0A: reshape");
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- gl.glViewport(x, y, width, height);
- regionRenderer.reshapePerspective(gl, 45.0f, width, height, 5f, 70.0f);
- }
- public void attachInputListenerTo(GLWindow window) {
- if ( null == multiTouchListener ) {
- multiTouchListener = new MultiTouchListener();
- window.addMouseListener(multiTouchListener);
+ //
+ // Layout all shapes: Relational move regarding window coordinates
+ //
+ final float dw = width - lastWidth;
+ final float dh = height - lastHeight;
+
+ final float dz = 0f;
+ final float dyTop = dh * relTop;
+ final float dxLeft = dw * relLeft;
+ final float dxRight = dw;
+
+ for(int i=0; i<buttons.size() && i<buttonsLeftCount; i++) {
+ buttons.get(i).translate(dxLeft, dyTop, dz);
+ }
+ for(int i=buttonsLeftCount; i<buttons.size(); i++) {
+ buttons.get(i).translate(dxRight, dyTop, dz);
+ }
+ final float dxMiddleAbs = width * relMiddle;
+ final float dyTopLabelAbs = drawable.getSurfaceHeight() - 2f*jogampLabel.getLineHeight();
+ jogampLabel.setTranslate(dxMiddleAbs, dyTopLabelAbs, dz);
+ truePtSizeLabel.setTranslate(dxMiddleAbs, dyTopLabelAbs, dz);
+ truePtSizeLabel.setTranslate(dxMiddleAbs, dyTopLabelAbs - 1.5f * jogampLabel.getLineHeight(), 0f);
+ fpsLabel.translate(0f, 0f, 0f);
+ if( null != labels[currentText] ) {
+ labels[currentText].setTranslate(dxMiddleAbs,
+ dyTopLabelAbs - 1.5f * jogampLabel.getLineHeight()
+ - 1.5f * truePtSizeLabel.getLineHeight(), 0f);
+ System.err.println("Label["+currentText+"] MOVE: "+labels[currentText]);
+ System.err.println("Label["+currentText+"] MOVE: "+Arrays.toString(labels[currentText].getTranslate()));
+ }
+ crossHairCtr.translate(dw/2f, dh/2f, 0f);
+
+ sceneUIController.reshape(drawable, x, y, width, height);
+
+ lastWidth = width;
+ lastHeight = height;
+ }
+
+ public void attachInputListenerTo(final GLWindow window) {
+ if ( !ioAttached ) {
+ ioAttached = true;
sceneUIController.attachInputListenerTo(window);
}
}
-
- public void detachInputListenerFrom(GLWindow window) {
- if ( null != multiTouchListener ) {
- window.removeMouseListener(multiTouchListener);
+
+ public void detachInputListenerFrom(final GLWindow window) {
+ if ( ioAttached ) {
+ ioAttached = false;
sceneUIController.detachInputListenerFrom(window);
}
}
-
- private class MultiTouchListener extends MouseAdapter {
- int lx = 0;
- int ly = 0;
-
- boolean first = false;
-
+
+ /**
+ * We can share this instance w/ all UI elements,
+ * since only mouse action / gesture is complete for a single one (press, drag, released and click).
+ */
+ private final UIShape.MouseGestureAdapter dragZoomRotateListener = new UIShape.MouseGestureAdapter() {
+ float dragFirstX=-1f, dragFirstY=-1f;
+ boolean dragFirst = false;
+
@Override
- public void mousePressed(MouseEvent e) {
- first = true;
+ public void mousePressed(final MouseEvent e) {
+ dragFirst = true;
}
@Override
- public void mouseReleased(MouseEvent e) {
- first = false;
+ public void mouseReleased(final MouseEvent e) {
+ dragFirst = false;
+ actionText = null;
}
@Override
- public void mouseDragged(MouseEvent e) {
- System.err.println("demo:mousedragged "+e);
- if(e.getPointerCount()==2) {
- // 2 pointers zoom ..
- if(first) {
- lx = Math.abs(e.getY(0)-e.getY(1));
- first=false;
- return;
- }
- int nv = Math.abs(e.getY(0)-e.getY(1));
- int dy = nv - lx;
-
- zoom += 2 * Math.signum(dy);
-
- lx = nv;
- } else {
- // 1 pointer drag
- if(first) {
- lx = e.getX();
- ly = e.getY();
- first=false;
- return;
- }
- int nx = e.getX();
- int ny = e.getY();
- int dx = nx - lx;
- int dy = ny - ly;
- if(Math.abs(dx) > Math.abs(dy)){
- xTran += Math.signum(dx);
- }
- else {
- yTran -= Math.signum(dy);
+ public void mouseDragged(final MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ if( e.getPointerCount() == 1 ) {
+ // 1 pointer drag
+ if(dragFirst) {
+ dragFirstX = shapeEvent.objPos[0]; // e.getX();
+ dragFirstY = shapeEvent.objPos[1]; // e.getY();
+ dragFirst=false;
+ return;
+ }
+ final float nx = shapeEvent.objPos[0]; // e.getX();
+ final float ny = shapeEvent.objPos[1]; // e.getY();
+ final float dx = nx - dragFirstX;
+ final float dy = ny - dragFirstY;
+ // final float dy = -(ny - dragLastY);
+ shapeEvent.shape.translate(dx, dy, 0f);
+ final float[] tx = shapeEvent.shape.getTranslate();
+ actionText = String.format("Pos %6.2f / %6.2f / %6.2f", tx[0], tx[1], tx[2]);
}
- lx = nx;
- ly = ny;
}
}
-
+
@Override
- public void mouseWheelMoved(MouseEvent e) {
- zoom += 2f*e.getWheelRotation();
+ public void mouseWheelMoved(final MouseEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ final boolean isOnscreen = PointerClass.Onscreen == e.getPointerType(0).getPointerClass();
+ if( 0 == ( ~InputEvent.BUTTONALL_MASK & e.getModifiers() ) && !isOnscreen ) {
+ // offscreen vertical mouse wheel zoom
+ final float tz = 8f*e.getRotation()[1]; // vertical: wheel
+ System.err.println("Rotate.Zoom.W: "+tz);
+ shapeEvent.shape.translate(0f, 0f, tz);
+ } else if( isOnscreen || e.isControlDown() ) {
+ final float[] rot = VectorUtil.scaleVec3(e.getRotation(), e.getRotation(), FloatUtil.PI / 180.0f);
+ if( isOnscreen ) {
+ System.err.println("XXX: "+e);
+ // swap axis for onscreen rotation matching natural feel
+ final float tmp = rot[0]; rot[0] = rot[1]; rot[1] = tmp;
+ VectorUtil.scaleVec3(rot, rot, 2f);
+ }
+ shapeEvent.shape.getRotation().rotateByEuler( rot );
+ }
+ }
}
- }
-} \ No newline at end of file
+ @Override
+ public void gestureDetected(final GestureEvent e) {
+ final Object attachment = e.getAttachment();
+ if( attachment instanceof UIShape.PointerEventInfo ) {
+ final UIShape.PointerEventInfo shapeEvent = (UIShape.PointerEventInfo)attachment;
+ if( e instanceof PinchToZoomGesture.ZoomEvent ) {
+ final PinchToZoomGesture.ZoomEvent ze = (PinchToZoomGesture.ZoomEvent) e;
+ final float tz = ze.getDelta() * ze.getScale();
+ System.err.println("Rotate.Zoom.G: "+tz);
+ shapeEvent.shape.translate(0f, 0f, tz);
+ }
+ }
+ } };
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java
new file mode 100644
index 000000000..274fbea2a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java
@@ -0,0 +1,189 @@
+package com.jogamp.opengl.test.junit.graph.demos;
+
+import java.awt.Component;
+import java.awt.Frame;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.nativewindow.ScalableSurface;
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assume;
+
+import com.jogamp.graph.curve.Region;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+
+public class GPUUISceneNewtCanvasAWTDemo {
+ static final boolean DEBUG = false;
+ static final boolean TRACE = false;
+
+ static int SceneMSAASamples = 0;
+ static boolean GraphVBAAMode = false;
+ static boolean GraphMSAAMode = false;
+ static float GraphAutoMode = GPUUISceneGLListener0A.DefaultNoAADPIThreshold;
+
+ static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+
+ static void setComponentSize(final Component comp, final DimensionImmutable new_sz) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final java.awt.Dimension d = new java.awt.Dimension(new_sz.getWidth(), new_sz.getHeight());
+ comp.setMinimumSize(d);
+ comp.setPreferredSize(d);
+ comp.setSize(d);
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ public static void main(final String[] args) throws InterruptedException, InvocationTargetException {
+ int width = 800, height = 400;
+ int x = 10, y = 10;
+
+ boolean forceES2 = false;
+ boolean forceES3 = false;
+ boolean forceGL3 = false;
+ boolean forceGLDef = false;
+
+ if( 0 != args.length ) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-smsaa")) {
+ i++;
+ SceneMSAASamples = MiscUtils.atoi(args[i], SceneMSAASamples);
+ GraphMSAAMode = false;
+ GraphVBAAMode = false;
+ GraphAutoMode = 0f;
+ } else if(args[i].equals("-gmsaa")) {
+ GraphMSAAMode = true;
+ GraphVBAAMode = false;
+ GraphAutoMode = 0f;
+ } else if(args[i].equals("-gvbaa")) {
+ GraphMSAAMode = false;
+ GraphVBAAMode = true;
+ GraphAutoMode = 0f;
+ } else if(args[i].equals("-gauto")) {
+ GraphMSAAMode = false;
+ GraphVBAAMode = true;
+ i++;
+ GraphAutoMode = MiscUtils.atof(args[i], GraphAutoMode);
+ } else if(args[i].equals("-width")) {
+ i++;
+ width = MiscUtils.atoi(args[i], width);
+ } else if(args[i].equals("-height")) {
+ i++;
+ height = MiscUtils.atoi(args[i], height);
+ } else if(args[i].equals("-x")) {
+ i++;
+ x = MiscUtils.atoi(args[i], x);
+ } else if(args[i].equals("-y")) {
+ i++;
+ y = MiscUtils.atoi(args[i], y);
+ } else if(args[i].equals("-pixelScale")) {
+ i++;
+ final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+ reqSurfacePixelScale[0] = pS;
+ reqSurfacePixelScale[1] = pS;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-es3")) {
+ forceES3 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-gldef")) {
+ forceGLDef = true;
+ }
+ }
+ }
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceES3 "+forceES3);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("forceGLDef "+forceGLDef);
+ System.err.println("Desired win size "+width+"x"+height);
+ System.err.println("Desired win pos "+x+"/"+y);
+ System.err.println("Scene MSAA Samples "+SceneMSAASamples);
+ System.err.println("Graph MSAA Mode "+GraphMSAAMode);
+ System.err.println("Graph VBAA Mode "+GraphVBAAMode);
+ System.err.println("Graph Auto Mode "+GraphAutoMode+" no-AA dpi threshold");
+
+ final GLProfile glp;
+ if(forceGLDef) {
+ glp = GLProfile.getDefault();
+ } else if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES3) {
+ glp = GLProfile.get(GLProfile.GLES3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ System.err.println("GLProfile: "+glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
+ if( SceneMSAASamples > 0 ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(SceneMSAASamples);
+ }
+ System.out.println("Requested: " + caps);
+
+ final int rmode;
+ if( GraphVBAAMode ) {
+ rmode = Region.VBAA_RENDERING_BIT;
+ } else if( GraphMSAAMode ) {
+ rmode = Region.MSAA_RENDERING_BIT;
+ } else {
+ rmode = 0;
+ }
+
+ final GLWindow window = GLWindow.create(caps);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setTitle("GraphUI Newt/AWT Demo: graph["+Region.getRenderModeString(rmode)+"], msaa "+SceneMSAASamples);
+ window.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new int[2]);
+
+ final GPUUISceneGLListener0A sceneGLListener = 0 < GraphAutoMode ? new GPUUISceneGLListener0A(GraphAutoMode, DEBUG, TRACE) :
+ new GPUUISceneGLListener0A(rmode, DEBUG, TRACE);
+
+ window.addGLEventListener(sceneGLListener);
+ sceneGLListener.attachInputListenerTo(window);
+
+ final Animator animator = new Animator();
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.add(window);
+
+ window.addWindowListener(new WindowAdapter() {
+ public void windowDestroyed(final WindowEvent e) {
+ animator.stop();
+ }
+ });
+
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(window);
+ final Frame frame = new Frame("GraphUI Newt/AWT Demo: graph["+Region.getRenderModeString(rmode)+"], msaa "+SceneMSAASamples);
+
+ setComponentSize(newtCanvasAWT, new Dimension(width, height));
+ frame.add(newtCanvasAWT);
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ frame.setVisible(true);
+ }
+ });
+ final int[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new int[2]);
+ System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ animator.start();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java
new file mode 100644
index 000000000..16d56a041
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java
@@ -0,0 +1,154 @@
+package com.jogamp.opengl.test.junit.graph.demos;
+
+import javax.media.nativewindow.ScalableSurface;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.graph.curve.Region;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+
+public class GPUUISceneNewtDemo {
+ static final boolean DEBUG = false;
+ static final boolean TRACE = false;
+
+ static int SceneMSAASamples = 0;
+ static boolean GraphVBAAMode = false;
+ static boolean GraphMSAAMode = false;
+ static float GraphAutoMode = GPUUISceneGLListener0A.DefaultNoAADPIThreshold;
+
+ static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+
+ public static void main(final String[] args) {
+ int width = 800, height = 400;
+ int x = 10, y = 10;
+
+ boolean forceES2 = false;
+ boolean forceES3 = false;
+ boolean forceGL3 = false;
+ boolean forceGLDef = false;
+
+ if( 0 != args.length ) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-smsaa")) {
+ i++;
+ SceneMSAASamples = MiscUtils.atoi(args[i], SceneMSAASamples);
+ GraphMSAAMode = false;
+ GraphVBAAMode = false;
+ GraphAutoMode = 0f;
+ } else if(args[i].equals("-gmsaa")) {
+ GraphMSAAMode = true;
+ GraphVBAAMode = false;
+ GraphAutoMode = 0f;
+ } else if(args[i].equals("-gvbaa")) {
+ GraphMSAAMode = false;
+ GraphVBAAMode = true;
+ GraphAutoMode = 0f;
+ } else if(args[i].equals("-gauto")) {
+ GraphMSAAMode = false;
+ GraphVBAAMode = true;
+ i++;
+ GraphAutoMode = MiscUtils.atof(args[i], GraphAutoMode);
+ } else if(args[i].equals("-width")) {
+ i++;
+ width = MiscUtils.atoi(args[i], width);
+ } else if(args[i].equals("-height")) {
+ i++;
+ height = MiscUtils.atoi(args[i], height);
+ } else if(args[i].equals("-x")) {
+ i++;
+ x = MiscUtils.atoi(args[i], x);
+ } else if(args[i].equals("-y")) {
+ i++;
+ y = MiscUtils.atoi(args[i], y);
+ } else if(args[i].equals("-pixelScale")) {
+ i++;
+ final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+ reqSurfacePixelScale[0] = pS;
+ reqSurfacePixelScale[1] = pS;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-es3")) {
+ forceES3 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-gldef")) {
+ forceGLDef = true;
+ }
+ }
+ }
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceES3 "+forceES3);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("forceGLDef "+forceGLDef);
+ System.err.println("Desired win size "+width+"x"+height);
+ System.err.println("Desired win pos "+x+"/"+y);
+ System.err.println("Scene MSAA Samples "+SceneMSAASamples);
+ System.err.println("Graph MSAA Mode "+GraphMSAAMode);
+ System.err.println("Graph VBAA Mode "+GraphVBAAMode);
+ System.err.println("Graph Auto Mode "+GraphAutoMode+" no-AA dpi threshold");
+
+ final GLProfile glp;
+ if(forceGLDef) {
+ glp = GLProfile.getDefault();
+ } else if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES3) {
+ glp = GLProfile.get(GLProfile.GLES3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ System.err.println("GLProfile: "+glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
+ if( SceneMSAASamples > 0 ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(SceneMSAASamples);
+ }
+ System.out.println("Requested: " + caps);
+
+ final int rmode;
+ if( GraphVBAAMode ) {
+ rmode = Region.VBAA_RENDERING_BIT;
+ } else if( GraphMSAAMode ) {
+ rmode = Region.MSAA_RENDERING_BIT;
+ } else {
+ rmode = 0;
+ }
+
+ final GLWindow window = GLWindow.create(caps);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setTitle("GraphUI Newt Demo: graph["+Region.getRenderModeString(rmode)+"], msaa "+SceneMSAASamples);
+ window.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new int[2]);
+
+ final GPUUISceneGLListener0A sceneGLListener = 0 < GraphAutoMode ? new GPUUISceneGLListener0A(GraphAutoMode, DEBUG, TRACE) :
+ new GPUUISceneGLListener0A(rmode, DEBUG, TRACE);
+
+ window.addGLEventListener(sceneGLListener);
+ sceneGLListener.attachInputListenerTo(window);
+
+ final Animator animator = new Animator();
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.add(window);
+
+ window.addWindowListener(new WindowAdapter() {
+ public void windowDestroyed(final WindowEvent e) {
+ animator.stop();
+ }
+ });
+
+ window.setVisible(true);
+ final int[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new int[2]);
+ System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ animator.start();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo01.java
deleted file mode 100644
index 0563ab2cf..000000000
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo01.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.jogamp.opengl.test.junit.graph.demos;
-
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLProfile;
-
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.opengl.SVertex;
-import com.jogamp.newt.event.WindowAdapter;
-import com.jogamp.newt.event.WindowEvent;
-import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.glsl.ShaderState;
-
-public class GPUUISceneNewtDemo01 {
- static final boolean DEBUG = false;
- static final boolean TRACE = false;
-
- public static void main(String[] args) {
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
- caps.setSampleBuffers(true);
- caps.setNumSamples(4);
-
- final GLWindow window = GLWindow.create(caps);
- window.setPosition(10, 10);
- window.setSize(680, 480);
- window.setTitle("GraphUI Newt Demo");
-
- final RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- GPUUISceneGLListener0A textGLListener = new GPUUISceneGLListener0A(rs, 0, DEBUG, TRACE);
- window.addGLEventListener(textGLListener);
- textGLListener.attachInputListenerTo(window);
-
- final Animator animator = new Animator();
- animator.setUpdateFPSFrames(60, System.err);
- animator.add(window);
-
- window.addWindowListener(new WindowAdapter() {
- public void windowDestroyed(WindowEvent e) {
- animator.stop();
- }
- });
-
- window.setVisible(true);
- animator.start();
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo02.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo02.java
deleted file mode 100644
index 4c8da139e..000000000
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo02.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.jogamp.opengl.test.junit.graph.demos;
-
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLProfile;
-
-import com.jogamp.graph.curve.Region;
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.opengl.SVertex;
-import com.jogamp.newt.event.WindowAdapter;
-import com.jogamp.newt.event.WindowEvent;
-import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.glsl.ShaderState;
-
-public class GPUUISceneNewtDemo02 {
- static final boolean DEBUG = false;
- static final boolean TRACE = false;
-
- public static void main(String[] args) {
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
- caps.setAlphaBits(4);
- caps.setSampleBuffers(true);
- caps.setNumSamples(4);
-
- final GLWindow window = GLWindow.create(caps);
- window.setPosition(10, 10);
- window.setSize(680, 480);
- window.setTitle("GraphUI Newt Demo");
-
- final RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- GPUUISceneGLListener0A textGLListener = new GPUUISceneGLListener0A(rs, Region.VBAA_RENDERING_BIT, DEBUG, TRACE);
- window.addGLEventListener(textGLListener);
- textGLListener.attachInputListenerTo(window);
-
- final Animator animator = new Animator();
- animator.setUpdateFPSFrames(60, System.err);
- animator.add(window);
-
- window.addWindowListener(new WindowAdapter() {
- public void windowDestroyed(WindowEvent e) {
- animator.stop();
- }
- });
-
- window.setVisible(true);
- animator.start();
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/MSAATool.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/MSAATool.java
index 4cddb1340..d838e42e8 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/MSAATool.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/MSAATool.java
@@ -34,50 +34,63 @@ import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilitiesImmutable;
public class MSAATool {
- public static boolean glIsEnabled(GL gl, int name) {
+ public static boolean glIsEnabled(final GL gl, final int name) {
boolean isEnabled = false;
try {
isEnabled = gl.glIsEnabled(name);
- int glerr = gl.glGetError();
+ final int glerr = gl.glGetError();
if(GL.GL_NO_ERROR != glerr) {
System.err.println("glIsEnabled(0x"+Integer.toHexString(name)+") -> error 0x"+Integer.toHexString(glerr));
}
- } catch (Exception e) {
- System.err.println("Catched Exception: "+e.getMessage());
+ } catch (final Exception e) {
+ System.err.println("Caught exception: "+e.getMessage());
// e.printStackTrace();
- }
+ }
return isEnabled;
}
- public static void dump(GLAutoDrawable drawable) {
- float[] vf = new float[] { 0f };
- byte[] vb = new byte[] { 0 };
- int[] vi = new int[] { 0, 0 };
-
+ public static void dump(final GLAutoDrawable drawable) {
+ final float[] vf = new float[] { 0f };
+ final byte[] vb = new byte[] { 0 };
+ final int[] vi = new int[] { 0, 0 };
+
System.out.println("GL MSAA SETUP:");
- GL2ES2 gl = drawable.getGL().getGL2ES2();
- GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
- System.out.println(" Caps realised "+caps);
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
+ System.out.println(" Caps realised "+caps);
System.out.println(" Caps sample buffers "+caps.getSampleBuffers()+", samples "+caps.getNumSamples());
-
- System.out.println(" GL MULTISAMPLE "+glIsEnabled(gl, GL2ES2.GL_MULTISAMPLE));
- // sample buffers min 0, same as GLX_SAMPLE_BUFFERS_ARB or WGL_SAMPLE_BUFFERS_ARB
- gl.glGetIntegerv(GL2GL3.GL_SAMPLE_BUFFERS, vi, 0);
+
+ System.out.println(" GL MULTISAMPLE "+glIsEnabled(gl, GL.GL_MULTISAMPLE));
+ // sample buffers min 0, same as GLX_SAMPLE_BUFFERS_ARB or WGL_SAMPLE_BUFFERS_ARB
+ gl.glGetIntegerv(GL.GL_SAMPLE_BUFFERS, vi, 0);
// samples min 0
- gl.glGetIntegerv(GL2GL3.GL_SAMPLES, vi, 1);
+ gl.glGetIntegerv(GL.GL_SAMPLES, vi, 1);
System.out.println(" GL SAMPLE_BUFFERS "+vi[0]+", SAMPLES "+vi[1]);
-
+
System.out.println("GL CSAA SETUP:");
// default FALSE
- System.out.println(" GL SAMPLE COVERAGE "+glIsEnabled(gl, GL2GL3.GL_SAMPLE_COVERAGE));
+ System.out.println(" GL SAMPLE COVERAGE "+glIsEnabled(gl, GL.GL_SAMPLE_COVERAGE));
// default FALSE
- System.out.println(" GL SAMPLE_ALPHA_TO_COVERAGE "+glIsEnabled(gl, GL2GL3.GL_SAMPLE_ALPHA_TO_COVERAGE));
+ System.out.println(" GL SAMPLE_ALPHA_TO_COVERAGE "+glIsEnabled(gl, GL.GL_SAMPLE_ALPHA_TO_COVERAGE));
// default FALSE
- System.out.println(" GL SAMPLE_ALPHA_TO_ONE "+glIsEnabled(gl, GL2GL3.GL_SAMPLE_ALPHA_TO_ONE));
+ System.out.println(" GL SAMPLE_ALPHA_TO_ONE "+glIsEnabled(gl, GL.GL_SAMPLE_ALPHA_TO_ONE));
// default FALSE, value 1, invert false
- gl.glGetFloatv(GL2GL3.GL_SAMPLE_COVERAGE_VALUE, vf, 0);
- gl.glGetBooleanv(GL2GL3.GL_SAMPLE_COVERAGE_INVERT, vb, 0);
- System.out.println(" GL SAMPLE_COVERAGE "+glIsEnabled(gl, GL2GL3.GL_SAMPLE_COVERAGE) +
+ gl.glGetFloatv(GL.GL_SAMPLE_COVERAGE_VALUE, vf, 0);
+ gl.glGetBooleanv(GL.GL_SAMPLE_COVERAGE_INVERT, vb, 0);
+ System.out.println(" GL SAMPLE_COVERAGE "+glIsEnabled(gl, GL.GL_SAMPLE_COVERAGE) +
": SAMPLE_COVERAGE_VALUE "+vf[0]+
- ", SAMPLE_COVERAGE_INVERT "+vb[0]);
+ ", SAMPLE_COVERAGE_INVERT "+vb[0]);
+ dumpBlend(gl);
+ }
+ public static void dumpBlend(final GL gl) {
+ final int[] vi = new int[] { 0, 0, 0, 0 };
+ gl.glGetIntegerv(GL.GL_BLEND, vi, 0);
+ gl.glGetIntegerv(GL.GL_BLEND_SRC_ALPHA, vi, 1);
+ gl.glGetIntegerv(GL.GL_BLEND_SRC_RGB, vi, 2);
+ gl.glGetIntegerv(GL.GL_BLEND_DST_RGB, vi, 3);
+ final boolean blendEnabled = vi[0] == GL.GL_TRUE;
+ System.out.println("GL_BLEND "+blendEnabled+"/"+glIsEnabled(gl, GL.GL_BLEND) +
+ " GL_SRC_ALPHA 0x"+Integer.toHexString(vi[1])+
+ " GL_SRC_RGB 0x"+Integer.toHexString(vi[2])+
+ " GL_DST_RGB 0x"+Integer.toHexString(vi[3]));
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/button-pressed-145x53.png b/src/test/com/jogamp/opengl/test/junit/graph/demos/button-pressed-145x53.png
new file mode 100644
index 000000000..1eba3a09e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/button-pressed-145x53.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/button-released-145x53.png b/src/test/com/jogamp/opengl/test/junit/graph/demos/button-released-145x53.png
new file mode 100644
index 000000000..fe223c6d3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/button-released-145x53.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/CrossHair.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/CrossHair.java
new file mode 100644
index 000000000..0086222dc
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/CrossHair.java
@@ -0,0 +1,110 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph.demos.ui;
+
+import javax.media.opengl.GL2ES2;
+
+import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
+
+/**
+ * GPU based resolution independent Button impl
+ */
+public class CrossHair extends UIShape {
+ private float width, height, lineWidth;
+
+ public CrossHair(final Factory<? extends Vertex> factory, final int renderModes, final float width, final float height, final float linewidth) {
+ super(factory, renderModes);
+ this.width = width;
+ this.height = height;
+ this.lineWidth = linewidth;
+ }
+
+ public final float getWidth() { return width; }
+ public final float getHeight() { return height; }
+ public final float getLineWidth() { return lineWidth; }
+
+ public void setDimension(final float width, final float height, final float lineWidth) {
+ this.width = width;
+ this.height = height;
+ this.lineWidth = lineWidth;
+ markShapeDirty();
+ }
+
+ @Override
+ protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) {
+ }
+
+ @Override
+ protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) {
+ }
+
+ @Override
+ protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) {
+ final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory());
+
+ final float tw = getWidth();
+ final float th = getHeight();
+ final float twh = tw/2f;
+ final float thh = th/2f;
+ final float lwh = lineWidth/2f;
+
+ final float ctrX = 0f, ctrY = 0f;
+ float ctrZ = 0f;
+
+ // vertical (CCW!)
+ shape.addVertex(ctrX-lwh, ctrY-thh, ctrZ, true);
+ shape.addVertex(ctrX+lwh, ctrY-thh, ctrZ, true);
+ shape.addVertex(ctrX+lwh, ctrY+thh, ctrZ, true);
+ shape.addVertex(ctrX-lwh, ctrY+thh, ctrZ, true);
+ shape.closeLastOutline(true);
+
+ ctrZ -= 0.05f;
+
+ // horizontal (CCW!)
+ shape.addEmptyOutline();
+ shape.addVertex(ctrX-twh, ctrY-lwh, ctrZ, true);
+ shape.addVertex(ctrX+twh, ctrY-lwh, ctrZ, true);
+ shape.addVertex(ctrX+twh, ctrY+lwh, ctrZ, true);
+ shape.addVertex(ctrX-twh, ctrY+lwh, ctrZ, true);
+ shape.closeLastOutline(true);
+
+ shape.setIsQuadraticNurbs();
+ shape.setSharpness(shapesSharpness);
+ region.addOutlineShape(shape, null, rgbaColor);
+
+ box.resize(shape.getBounds());
+ }
+
+ @Override
+ public String getSubString() {
+ return super.getSubString()+", dim "+getWidth() + "x" + getHeight();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/GLEventListenerButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/GLEventListenerButton.java
new file mode 100644
index 000000000..a8cd32035
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/GLEventListenerButton.java
@@ -0,0 +1,132 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph.demos.ui;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLOffscreenAutoDrawable;
+
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.util.texture.ImageSequence;
+import com.jogamp.opengl.util.texture.Texture;
+
+/**
+ * GPU based resolution independent Button impl,
+ * rendering {@link GLEventListener} content via FBO as an {@link ImageSequence}.
+ */
+public class GLEventListenerButton extends TextureSeqButton {
+ private final GLEventListener glel;
+ private final boolean useAlpha;
+ private volatile int fboWidth = 200;
+ private volatile int fboHeight = 200;
+ private volatile GLOffscreenAutoDrawable.FBO fboGLAD = null;
+ private boolean animateGLEL = false;
+
+ public GLEventListenerButton(final Factory<? extends Vertex> factory, final int renderModes,
+ final float width, final float height, final int textureUnit,
+ final GLEventListener glel, final boolean useAlpha, final int fboWidth, final int fboHeight) {
+ super(factory, renderModes, width, height, new ImageSequence(textureUnit, true));
+ this.glel = glel;
+ this.useAlpha = useAlpha;
+
+ setColor(0.95f, 0.95f, 0.95f, 1.0f);
+ setPressedColorMod(1f, 1f, 1f, 0.9f);
+ setToggleOffColorMod(0.8f, 0.8f, 0.8f, 1.0f);
+ setToggleOnColorMod(1.0f, 1.0f, 1.0f, 1.0f);
+
+ this.fboWidth = fboWidth;
+ this.fboHeight = fboHeight;
+ }
+
+ public final void setAnimate(final boolean v) { animateGLEL = v; }
+ public final boolean getAnimate() { return animateGLEL; }
+
+ public final void setFBOSize(final int fboWidth, final int fboHeight) {
+ this.fboWidth = fboWidth;
+ this.fboHeight = fboHeight;
+ }
+
+ public final GLOffscreenAutoDrawable.FBO getFBOAutoDrawable() { return fboGLAD; }
+
+ @Override
+ public void drawShape(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
+ if( null == fboGLAD ) {
+ final ImageSequence imgSeq = (ImageSequence)texSeq;
+
+ final GLContext ctx = gl.getContext();
+ final GLDrawable drawable = ctx.getGLDrawable();
+ final GLCapabilitiesImmutable reqCaps = drawable.getRequestedGLCapabilities();
+ final GLCapabilities caps = (GLCapabilities) reqCaps.cloneMutable();
+ caps.setFBO(true);
+ caps.setDoubleBuffered(false);
+ if( !useAlpha ) {
+ caps.setAlphaBits(0);
+ }
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+
+ fboGLAD = (GLOffscreenAutoDrawable.FBO) factory.createOffscreenAutoDrawable(
+ drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(),
+ caps, null, fboWidth, fboHeight);
+ fboWidth = 0;
+ fboHeight = 0;
+ fboGLAD.setSharedContext(ctx);
+ fboGLAD.setTextureUnit(imgSeq.getTextureUnit());
+ fboGLAD.addGLEventListener(glel);
+ fboGLAD.display(); // 1st init!
+
+ final FBObject.TextureAttachment texA01 = fboGLAD.getColorbuffer(GL.GL_FRONT).getTextureAttachment();
+ final Texture tex = new Texture(texA01.getName(), imgSeq.getTextureTarget(),
+ fboGLAD.getSurfaceWidth(), fboGLAD.getSurfaceHeight(), fboGLAD.getSurfaceWidth(), fboGLAD.getSurfaceHeight(),
+ false /* mustFlipVertically */);
+ imgSeq.addFrame(gl, tex);
+ markStateDirty();
+ } else if( 0 != fboWidth*fboHeight ) {
+ fboGLAD.setSurfaceSize(fboWidth, fboHeight);
+ fboWidth = 0;
+ fboHeight = 0;
+ markStateDirty();
+ } else if( animateGLEL ) {
+ fboGLAD.display();
+ }
+
+ super.drawShape(gl, renderer, sampleCount);
+
+ if( animateGLEL ) {
+ markStateDirty(); // keep on going
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/ImageSeqButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/ImageSeqButton.java
new file mode 100644
index 000000000..5d8e9e8db
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/ImageSeqButton.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph.demos.ui;
+
+import javax.media.opengl.GL2ES2;
+
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.opengl.util.texture.ImageSequence;
+
+/**
+ * GPU based resolution independent {@link ImageSequence} Button impl
+ */
+public class ImageSeqButton extends TextureSeqButton {
+
+ public ImageSeqButton(final Factory<? extends Vertex> factory, final int renderModes,
+ final float width, final float height, final ImageSequence texSeq) {
+ super(factory, renderModes, width, height, texSeq);
+ setColor(0.95f, 0.95f, 0.95f, 1.0f);
+ setPressedColorMod(1f, 1f, 1f, 0.9f);
+ setToggleOffColorMod(0.8f, 0.8f, 0.8f, 1.0f);
+ setToggleOnColorMod(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ public final void setCurrentIdx(final int idx) {
+ ((ImageSequence)texSeq).setCurrentIdx(idx);
+ markStateDirty();
+ }
+
+ @Override
+ public void drawShape(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
+ super.drawShape(gl, renderer, sampleCount);
+ if( !((ImageSequence)texSeq).getManualStepping() ) {
+ markStateDirty(); // keep on going
+ }
+ };
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java
index 4fef2d8c2..1181ef914 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java
@@ -29,77 +29,89 @@ package com.jogamp.opengl.test.junit.graph.demos.ui;
import javax.media.opengl.GL2ES2;
-import jogamp.graph.curve.text.GlyphString;
+import jogamp.graph.geom.plane.AffineTransform;
+import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.opengl.RegionRenderer;
-import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.curve.opengl.TextRegionUtil;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.geom.Vertex.Factory;
-public abstract class Label extends UIShape implements UITextShape {
+public class Label extends UIShape {
protected Font font;
- protected int size;
+ protected float pixelSize;
protected String text;
- protected GlyphString glyphString;
-
- public Label(Factory<? extends Vertex> factory, Font font, int size, String text) {
- super(factory);
+
+ public Label(final Factory<? extends Vertex> factory, final int renderModes, final Font font, final float pixelSize, final String text) {
+ super(factory, renderModes);
this.font = font;
- this.size = size;
+ this.pixelSize = pixelSize;
this.text = text;
}
-
- public GlyphString getGlyphString() {
- return glyphString;
- }
-
+
public String getText() {
return text;
}
-
- public void setText(String text) {
+
+ public void setText(final String text) {
this.text = text;
- dirty |= DIRTY_SHAPE;
+ markShapeDirty();
}
-
+
public Font getFont() {
return font;
}
- public void setFont(Font font) {
+ public void setFont(final Font font) {
this.font = font;
- dirty |= DIRTY_SHAPE;
+ markShapeDirty();
}
- public int getSize() {
- return size;
+ public float getPixelSize() {
+ return pixelSize;
}
- public void setSize(int size) {
- this.size = size;
- dirty |= DIRTY_SHAPE;
+ public float getLineHeight() {
+ return font.getLineHeight(pixelSize);
}
- public String toString(){
- return "Label [" + font.toString() + ", size " + size + ", " + getText() + "]";
+ public void setPixelSize(final float pixelSize) {
+ this.pixelSize = pixelSize;
+ markShapeDirty();
}
@Override
- protected void clearImpl() {
- if(null != glyphString) {
- glyphString.destroy(null, null);
- }
+ protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) {
}
-
+
+ @Override
+ protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) {
+ }
+
+ private final float[] tmpV3 = new float[3];
+ private final AffineTransform tempT1 = new AffineTransform();
+ private final AffineTransform tempT2 = new AffineTransform();
+
+ private final TextRegionUtil.ShapeVisitor shapeVisitor = new TextRegionUtil.ShapeVisitor() {
+ @Override
+ public void visit(final OutlineShape shape, final AffineTransform t) {
+ shape.setSharpness(shapesSharpness);
+ region.addOutlineShape(shape, t, rgbaColor);
+ box.resize(shape.getBounds(), t, tmpV3);
+ }
+ };
+
@Override
- protected void createShape() {
- clearImpl();
- glyphString = GlyphString.createString(shape, getVertexFactory(), font, size, text);
+ protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) {
+ TextRegionUtil.processString(shapeVisitor, null, font, pixelSize, text, tempT1, tempT2);
+ final float[] ctr = box.getCenter();
+ setRotationOrigin( ctr[0], ctr[1], ctr[2]);
}
@Override
- public void render(GL2ES2 gl, RenderState rs, RegionRenderer renderer,
- int renderModes, int[/*1*/] texSize, boolean selection) {
+ public String getSubString() {
+ final int m = Math.min(text.length(), 8);
+ return super.getSubString()+", psize " + pixelSize + ", '" + text.substring(0, m)+"'";
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java
new file mode 100644
index 000000000..9a12b7175
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label0.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph.demos.ui;
+
+import jogamp.graph.geom.plane.AffineTransform;
+
+import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.TextRegionUtil;
+import com.jogamp.graph.font.Font;
+import com.jogamp.opengl.math.geom.AABBox;
+
+public class Label0 {
+ protected Font font;
+ protected String text;
+ protected final float[] rgbaColor;
+ protected final AABBox box;
+
+ public Label0(final Font font, final String text, final float[] rgbaColor) {
+ this.font = font;
+ this.text = text;
+ this.rgbaColor = rgbaColor;
+ this.box = new AABBox();
+ }
+
+ public final String getText() { return text; }
+
+ public final float[] getColor() { return rgbaColor; }
+
+ public final void setColor(final float r, final float g, final float b, final float a) {
+ this.rgbaColor[0] = r;
+ this.rgbaColor[1] = g;
+ this.rgbaColor[2] = b;
+ this.rgbaColor[3] = a;
+ }
+
+ public final void setText(final String text) {
+ this.text = text;
+ }
+
+ public final Font getFont() { return font; }
+
+ public final void setFont(final Font font) {
+ this.font = font;
+ }
+
+ public final AABBox getBounds() { return box; }
+
+ private final float[] tmpV3 = new float[3];
+ private final AffineTransform tempT1 = new AffineTransform();
+ private final AffineTransform tempT2 = new AffineTransform();
+
+ private final TextRegionUtil.ShapeVisitor shapeVisitor = new TextRegionUtil.ShapeVisitor() {
+ @Override
+ public void visit(final OutlineShape shape, final AffineTransform t) {
+ final AffineTransform t1 = t.preConcatenate(tLeft);
+ region.addOutlineShape(shape, t1, rgbaColor);
+ box.resize(shape.getBounds(), t1, tmpV3);
+ }
+ };
+
+ private Region region;
+ private AffineTransform tLeft;
+
+ public final AABBox addShapeToRegion(final float pixelSize, final Region region, final AffineTransform tLeft) {
+ box.reset();
+ this.region = region;
+ this.tLeft = tLeft;
+ TextRegionUtil.processString(shapeVisitor, null, font, pixelSize, text, tempT1, tempT2);
+ this.region = null;
+ this.tLeft = null;
+ return box;
+ }
+
+ @Override
+ public final String toString(){
+ final int m = Math.min(text.length(), 8);
+ return "Label0 ['" + text.substring(0, m) + "']";
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java
new file mode 100644
index 000000000..4943c9418
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java
@@ -0,0 +1,174 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph.demos.ui;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+
+import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.opengl.math.geom.AABBox;
+
+/**
+ * GPU based resolution independent Button impl
+ */
+public class LabelButton extends RoundButton {
+ /** {@value} */
+ public static final float DEFAULT_SPACING_X = 0.08f;
+ /** {@value} */
+ public static final float DEFAULT_SPACING_Y = 0.40f;
+
+ private static final float DEFAULT_2PASS_LABEL_ZOFFSET = -0.05f;
+
+ private final Label0 label;
+ private float spacingX = DEFAULT_SPACING_X;
+ private float spacingY = DEFAULT_SPACING_Y;
+
+ public LabelButton(final Factory<? extends Vertex> factory, final int renderModes,
+ final Font labelFont, final String labelText,
+ final float width, final float height) {
+ super(factory, renderModes | Region.COLORCHANNEL_RENDERING_BIT, width, height);
+ this.label = new Label0(labelFont, labelText, new float[] { 1.33f, 1.33f, 1.33f, 1.0f }); // 0.75 * 1.33 = 1.0
+ setColor(0.75f, 0.75f, 0.75f, 1.0f);
+ setPressedColorMod(0.9f, 0.9f, 0.9f, 0.7f);
+ setToggleOffColorMod(0.65f, 0.65f, 0.65f, 1.0f);
+ setToggleOnColorMod(0.85f, 0.85f, 0.85f, 1.0f);
+ }
+
+ @Override
+ public void drawShape(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
+ if( false ) {
+ // Setup poly offset for z-fighting
+ gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
+ gl.glPolygonOffset(0f, 1f);
+ super.drawShape(gl, renderer, sampleCount);
+ gl.glDisable(GL.GL_POLYGON_OFFSET_FILL);
+ } else {
+ super.drawShape(gl, renderer, sampleCount);
+ }
+ }
+
+ @Override
+ protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) {
+ final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory());
+ if(corner == 0.0f) {
+ createSharpOutline(shape, DEFAULT_2PASS_LABEL_ZOFFSET);
+ } else {
+ createCurvedOutline(shape, DEFAULT_2PASS_LABEL_ZOFFSET);
+ }
+ shape.setIsQuadraticNurbs();
+ shape.setSharpness(shapesSharpness);
+ region.addOutlineShape(shape, null, rgbaColor);
+ box.resize(shape.getBounds());
+
+ // Precompute text-box size .. guessing pixelSize
+ final float lPixelSize0 = 10f;
+ final float lw = width * ( 1f - spacingX ) ;
+ final float lh = height * ( 1f - spacingY ) ;
+ final AABBox lbox0 = label.font.getMetricBounds(label.text, lPixelSize0);
+ final float lsx = lw / lbox0.getWidth();
+ final float lsy = lh / lbox0.getHeight();
+ final float lPixelSize1 = lsx < lsy ? lPixelSize0 * lsx : lPixelSize0 * lsy;
+ if( DRAW_DEBUG_BOX ) {
+ System.err.println("RIButton: spacing "+spacingX+", "+spacingY);
+ System.err.println("RIButton: bbox "+box);
+ System.err.println("RIButton: lbox "+lbox0+", "+label.text);
+ System.err.println("RIButton: net-text "+lw+" x "+lh);
+ System.err.println("RIButton: lsx "+lsx+", lsy "+lsy+": pixelSize "+lPixelSize0+" -> "+lPixelSize1);
+ }
+
+ // Setting pixelSize based on actual text-box size
+ final AABBox lbox1 = label.font.getPointsBounds(null, label.text, lPixelSize1, tempT1, tempT2);
+ // Center text .. (share same center w/ button)
+ final float[] lctr = lbox1.getCenter();
+ final float[] ctr = box.getCenter();
+ final float[] ltx = new float[] { ctr[0] - lctr[0], ctr[1] - lctr[1], 0f };
+
+ final AABBox lbox2 = label.addShapeToRegion(lPixelSize1, region, tempT1.setToTranslation(ltx[0], ltx[1]));
+ if( DRAW_DEBUG_BOX ) {
+ System.err.printf("RIButton.0: lbox1 %s%n", lbox1);
+ System.err.printf("RIButton.0: lbox2 %s%n", lbox2);
+ }
+
+ setRotationOrigin( ctr[0], ctr[1], ctr[2]);
+
+ if( DRAW_DEBUG_BOX ) {
+ System.err.println("XXX.UIShape.RIButton: Added Shape: "+shape+", "+box);
+ }
+ }
+
+ public final float getSpacingX() { return spacingX; }
+ public final float getSpacingY() { return spacingY; }
+
+ /**
+ * In percent of text label
+ * @param spacingX spacing in percent on X, default is {@link #DEFAULT_SPACING_X}
+ * @param spacingY spacing in percent on Y, default is {@link #DEFAULT_SPACING_Y}
+ */
+ public final void setSpacing(final float spacingX, final float spacingY) {
+ if ( spacingX < 0.0f ) {
+ this.spacingX = 0.0f;
+ } else if ( spacingX > 1.0f ) {
+ this.spacingX = 1.0f;
+ } else {
+ this.spacingX = spacingX;
+ }
+ if ( spacingY < 0.0f ) {
+ this.spacingY = 0.0f;
+ } else if ( spacingY > 1.0f ) {
+ this.spacingY = 1.0f;
+ } else {
+ this.spacingY = spacingY;
+ }
+ markShapeDirty();
+ }
+
+ public final float[] getLabelColor() {
+ return label.getColor();
+ }
+
+ public final void setLabelColor(final float r, final float g, final float b) {
+ label.setColor(r, g, b, 1.0f);
+ markShapeDirty();
+ }
+
+ public final void setLabelText(final Font labelFont, final String labelText) {
+ label.setFont(labelFont);
+ label.setText(labelText);
+ markShapeDirty();
+ }
+
+ @Override
+ public String getSubString() {
+ return super.getSubString()+", "+ label + ", " + "spacing: " + spacingX+"/"+spacingY;
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/MediaPlayerButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/MediaPlayerButton.java
new file mode 100644
index 000000000..76b70ddf8
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/MediaPlayerButton.java
@@ -0,0 +1,131 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph.demos.ui;
+
+import javax.media.opengl.GL2ES2;
+
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+/**
+ * GPU based resolution independent {@link GLMediaPlayer} Button impl
+ */
+public class MediaPlayerButton extends TextureSeqButton {
+ public boolean verbose = false;
+
+ /**
+ * @param factory
+ * @param renderModes
+ * @param width
+ * @param height
+ * @param mPlayer
+ * @param mPlayerListener
+ */
+ public MediaPlayerButton(final Factory<? extends Vertex> factory, final int renderModes,
+ final float width, final float height,
+ final GLMediaPlayer mPlayer) {
+ super(factory, renderModes, width, height, mPlayer);
+ setColor(0.8f, 0.8f, 0.8f, 1.0f);
+ setPressedColorMod(1.1f, 1.1f, 1.1f, 0.7f);
+ setToggleOffColorMod(0.8f, 0.8f, 0.8f, 1.0f);
+ setToggleOnColorMod(1.0f, 1.0f, 1.0f, 1.0f);
+ setEnabled(false); // data and shader n/a yet
+ }
+
+ /**
+ * Add the default {@link GLMediaEventListener} to {@link #getGLMediaPlayer() this class's GLMediaPlayer}.
+ */
+ public void addDefaultEventListener() {
+ getGLMediaPlayer().addEventListener(defGLMediaEventListener);
+ }
+
+ public final GLMediaPlayer getGLMediaPlayer() { return (GLMediaPlayer)texSeq; }
+
+ private final GLMediaEventListener defGLMediaEventListener = new GLMediaEventListener() {
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) {
+ // texButton.markStateDirty();
+ }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ final GLMediaPlayer mPlayer = (GLMediaPlayer)texSeq;
+ if( verbose ) {
+ System.err.println("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieCube State: "+mp);
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ MediaPlayerButton.this.setEnabled(true); // data and shader is available ..
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) {
+ // FIXME: mPlayer.resetGLState();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ new Thread() {
+ public void run() {
+ // loop for-ever ..
+ mPlayer.seek(0);
+ mPlayer.play();
+ } }.start();
+ } else if( 0 != ( GLMediaEventListener.EVENT_CHANGE_ERR & event_mask ) ) {
+ final StreamException se = mPlayer.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ }
+ } };
+
+
+ @Override
+ protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) {
+ ((GLMediaPlayer)texSeq).destroy(gl);
+ }
+
+ @Override
+ public void drawShape(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
+ final GLMediaPlayer mPlayer = (GLMediaPlayer)texSeq;
+ if( GLMediaPlayer.State.Initialized == mPlayer.getState() ) {
+ try {
+ mPlayer.initGL(gl);
+ mPlayer.setAudioVolume( 0f );
+ mPlayer.play();
+ markStateDirty();
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ super.drawShape(gl, renderer, sampleCount);
+ markStateDirty(); // keep on going
+ };
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java
deleted file mode 100644
index bf403900d..000000000
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.opengl.test.junit.graph.demos.ui;
-
-import javax.media.opengl.GL2ES2;
-
-import com.jogamp.graph.curve.opengl.RegionRenderer;
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.font.Font;
-import com.jogamp.graph.geom.AABBox;
-import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.geom.Vertex.Factory;
-import com.jogamp.opengl.test.junit.graph.demos.ui.opengl.UIRegion;
-
-/** GPU based resolution independent Button impl
- */
-public abstract class RIButton extends UIShape {
- private float width, height;
- private Label label;
- private float spacing = 4.0f;
- private float corner = 1.0f;
- private float labelZOffset = -0.05f;
-
- private float[] buttonColor = {0.6f, 0.6f, 0.6f};
- private float[] buttonSelectedColor = {0.8f,0.8f,0.8f};
- private float[] labelColor = {1.0f, 1.0f, 1.0f};
- private float[] labelSelectedColor = {0.1f, 0.1f, 0.1f};
-
-
- public RIButton(Factory<? extends Vertex> factory, Font labelFont, String labelText, float width, float height) {
- super(factory);
-
- // FIXME: Determine font size - PMV Matrix relation ?
- // this.label = new Label(factory, labelFont, (int)(height - 2f * spacing), labelText);
- this.label = new Label(factory, labelFont, 10, labelText){
- public void onClick() { }
- public void onPressed() { }
- public void onRelease() { }
- };
-
- this.width = width;
- this.height = height;
- }
-
- public final float getWidth() { return width; }
- public final float getHeight() { return height; }
- public float getCorner() { return corner; }
- public Label getLabel() { return label; }
-
- public void setDimension(int width, int height) {
- this.width = width;
- this.height = height;
- dirty |= DIRTY_SHAPE;
- }
-
- @Override
- protected void clearImpl() {
- label.clear();
- }
-
- @Override
- protected void createShape() {
- // FIXME: Only possible if all data (color) is
- // is incl. in Outline Shape.
- // Until then - draw each separately!
- //shape.addOutlinShape( label.getShape() );
- label.updateShape();
-
- final AABBox lbox = label.getBounds();
- if(corner == 0.0f) {
- createSharpOutline(lbox);
- } else {
- createCurvedOutline(lbox);
- }
- float sx = getWidth() / ( 2f*spacing + lbox.getWidth() );
- float sy = getHeight() / ( 2f*spacing + lbox.getHeight() );
-
- setScale(sx, sy, 1);
- }
-
-
- private void createSharpOutline(AABBox lbox) {
- float th = (2f*spacing) + lbox.getHeight();
- float tw = (2f*spacing) + lbox.getWidth();
-
- float minX = lbox.getMinX()-spacing;
- float minY = lbox.getMinY()-spacing;
- float minZ = labelZOffset;
-
- shape.addVertex(minX, minY, minZ, true);
- shape.addVertex(minX+tw, minY, minZ, true);
- shape.addVertex(minX+tw, minY + th, minZ, true);
- shape.addVertex(minX, minY + th, minZ, true);
- shape.closeLastOutline();
- }
-
- private void createCurvedOutline(AABBox lbox){
- float th = 2.0f*spacing + lbox.getHeight();
- float tw = 2.0f*spacing + lbox.getWidth();
-
- float cw = 0.5f*corner*Math.min(tw, th);
- float ch = 0.5f*corner*Math.min(tw, th);
-
- float minX = lbox.getMinX()-spacing;
- float minY = lbox.getMinY()-spacing;
- float minZ = labelZOffset;
- shape.addVertex(minX, minY + ch, minZ, true);
- shape.addVertex(minX, minY, minZ, false);
- shape.addVertex(minX + cw, minY, minZ, true);
- shape.addVertex(minX + tw - cw, minY, minZ, true);
- shape.addVertex(minX + tw, minY, minZ, false);
- shape.addVertex(minX + tw, minY + ch, minZ, true);
- shape.addVertex(minX + tw, minY + th- ch, minZ, true);
- shape.addVertex(minX + tw, minY + th, minZ, false);
- shape.addVertex(minX + tw - cw, minY + th, minZ, true);
- shape.addVertex(minX + cw, minY + th, minZ, true);
- shape.addVertex(minX, minY + th, minZ, false);
- shape.addVertex(minX, minY + th - ch, minZ, true);
- shape.closeLastOutline();
- }
-
- public void setCorner(float corner) {
- if(corner > 1.0f){
- this.corner = 1.0f;
- }
- else if(corner < 0.01f){
- this.corner = 0.0f;
- }
- else{
- this.corner = corner;
- }
- dirty |= DIRTY_SHAPE;
- }
-
- public float getLabelZOffset() {
- return labelZOffset;
- }
-
- public void setLabelZOffset(float labelZOffset) {
- this.labelZOffset = -labelZOffset;
- dirty |= DIRTY_SHAPE;
- }
- public float getSpacing() {
- return spacing;
- }
-
- public void setSpacing(float spacing) {
- if(spacing < 0.0f){
- this.spacing = 0.0f;
- }
- else{
- this.spacing = spacing;
- }
- dirty |= DIRTY_SHAPE;
- }
-
- public float[] getButtonColor() {
- return buttonColor;
- }
-
- public void setButtonColor(float r, float g, float b) {
- this.buttonColor = new float[3];
- this.buttonColor[0] = r;
- this.buttonColor[1] = g;
- this.buttonColor[2] = b;
- }
-
- public float[] getLabelColor() {
- return labelColor;
- }
-
- private UIRegion buttonRegion = null;
- private UIRegion labelRegion = null;
- private boolean toggle =false;
- private boolean toggleable = false;
-
- public void render(GL2ES2 gl, RenderState rs, RegionRenderer renderer, int renderModes, int[/*1*/] texSize, boolean selection) {
- if(null == buttonRegion) {
- buttonRegion = new UIRegion(this);
- labelRegion = new UIRegion(getLabel());
- }
-
- gl.glEnable(GL2ES2.GL_POLYGON_OFFSET_FILL);
- gl.glPolygonOffset(0.0f, 1f);
-
- float[] bColor = buttonColor;
- if(isPressed() || toggle){
- bColor = buttonSelectedColor;
- }
- if(!selection){
- renderer.setColorStatic(gl, bColor[0], bColor[1], bColor[2]);
- }
- renderer.draw(gl, buttonRegion.getRegion(gl, rs, renderModes), getPosition(), texSize);
- gl.glDisable(GL2ES2.GL_POLYGON_OFFSET_FILL);
-
- float[] lColor = labelColor;
- if(isPressed() || toggle ){
- lColor = labelSelectedColor;
- }
- if(!selection){
- renderer.setColorStatic(gl, lColor[0], lColor[1], lColor[2]);
- }
- renderer.draw(gl, labelRegion.getRegion(gl, rs, renderModes), getPosition(), texSize);
- }
- public void setPressed(boolean b) {
- super.setPressed(b);
- if(isToggleable() && b) {
- toggle = !toggle;
- }
- }
-
- public void setLabelColor(float r, float g, float b) {
- this.labelColor = new float[3];
- this.labelColor[0] = r;
- this.labelColor[1] = g;
- this.labelColor[2] = b;
- }
-
- public void setButtonSelectedColor(float r, float g, float b){
- this.buttonSelectedColor = new float[3];
- this.buttonSelectedColor[0] = r;
- this.buttonSelectedColor[1] = g;
- this.buttonSelectedColor[2] = b;
- }
-
- public void setLabelSelectedColor(float r, float g, float b){
- this.labelSelectedColor = new float[3];
- this.labelSelectedColor[0] = r;
- this.labelSelectedColor[1] = g;
- this.labelSelectedColor[2] = b;
- }
-
- public boolean isToggleable() {
- return toggleable;
- }
-
- public void setToggleable(boolean toggleable) {
- this.toggleable = toggleable;
- }
-
- public String toString() {
- return "RIButton [" + getWidth() + "x" + getHeight() + ", "
- + getLabel() + ", " + "spacing: " + spacing
- + ", " + "corner: " + corner + ", " + "shapeOffset: " + labelZOffset + " ]";
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RoundButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RoundButton.java
new file mode 100644
index 000000000..c455ea365
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RoundButton.java
@@ -0,0 +1,135 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph.demos.ui;
+
+import javax.media.opengl.GL2ES2;
+
+import jogamp.graph.geom.plane.AffineTransform;
+
+import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
+
+public abstract class RoundButton extends UIShape {
+
+ /** {@value} */
+ public static final float DEFAULT_CORNER = 1f;
+ protected float width;
+ protected float height;
+ protected float corner = DEFAULT_CORNER;
+ protected final AffineTransform tempT1 = new AffineTransform();
+ protected final AffineTransform tempT2 = new AffineTransform();
+
+ protected RoundButton(final Factory<? extends Vertex> factory, final int renderModes, final float width, final float height) {
+ super(factory, renderModes);
+ this.width = width;
+ this.height = height;
+ }
+
+ @Override
+ protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) {
+ }
+
+ @Override
+ protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) {
+ }
+
+ public final float getWidth() { return width; }
+
+ public final float getHeight() { return height; }
+
+ public final float getCorner() { return corner; }
+
+ public void setDimension(final float width, final float height) {
+ this.width = width;
+ this.height = height;
+ markShapeDirty();
+ }
+
+ protected void createSharpOutline(final OutlineShape shape, final float zOffset) {
+ final float tw = getWidth();
+ final float th = getHeight();
+
+ final float minX = 0;
+ final float minY = 0;
+ final float minZ = zOffset;
+
+ shape.addVertex(minX, minY, minZ, true);
+ shape.addVertex(minX+tw, minY, minZ, true);
+ shape.addVertex(minX+tw, minY + th, minZ, true);
+ shape.addVertex(minX, minY + th, minZ, true);
+ shape.closeLastOutline(true);
+ }
+
+ protected void createCurvedOutline(final OutlineShape shape, final float zOffset) {
+ final float tw = getWidth();
+ final float th = getHeight();
+ final float dC = 0.5f*corner*Math.min(tw, th);
+
+ final float minX = 0;
+ final float minY = 0;
+ final float minZ = zOffset;
+
+ shape.addVertex(minX, minY + dC, minZ, true);
+ shape.addVertex(minX, minY, minZ, false);
+
+ shape.addVertex(minX + dC, minY, minZ, true);
+
+ shape.addVertex(minX + tw - dC, minY, minZ, true);
+ shape.addVertex(minX + tw, minY, minZ, false);
+ shape.addVertex(minX + tw, minY + dC, minZ, true);
+ shape.addVertex(minX + tw, minY + th- dC, minZ, true);
+ shape.addVertex(minX + tw, minY + th, minZ, false);
+ shape.addVertex(minX + tw - dC, minY + th, minZ, true);
+ shape.addVertex(minX + dC, minY + th, minZ, true);
+ shape.addVertex(minX, minY + th, minZ, false);
+ shape.addVertex(minX, minY + th - dC, minZ, true);
+
+ shape.closeLastOutline(true);
+ }
+
+ /** Set corner size, default is {@link #DEFAULT_CORNER} */
+ public void setCorner(final float corner) {
+ if(corner > 1.0f){
+ this.corner = 1.0f;
+ }
+ else if(corner < 0.01f){
+ this.corner = 0.0f;
+ }
+ else{
+ this.corner = corner;
+ }
+ markShapeDirty();
+ }
+
+ @Override
+ public String getSubString() {
+ return super.getSubString()+", dim "+getWidth() + "x" + getHeight() + ", corner " + corner;
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java
index c6d43480a..3d4865b5d 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java
@@ -1,261 +1,518 @@
package com.jogamp.opengl.test.junit.graph.demos.ui;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.IntBuffer;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLRunnable;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
-import com.jogamp.common.nio.Buffers;
import com.jogamp.graph.curve.opengl.RegionRenderer;
-import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.newt.event.GestureHandler;
+import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.event.PinchToZoomGesture;
+import com.jogamp.newt.event.GestureHandler.GestureEvent;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.Ray;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.util.PMVMatrix;
public class SceneUIController implements GLEventListener{
- private ArrayList<UIShape> shapes = new ArrayList<UIShape>();
-
- private int count = 0;
- private int renderModes;
- private int[] texSize;
- private RegionRenderer renderer = null;
- private RenderState rs = null;
-
- private float[] translate = new float[3];
- private float[] scale = new float[3];
- private float[] rotation = new float[3];
-
- private float[] sceneClearColor = new float[]{0,0,0,1};
-
- private int activeId = -1;
-
+ private final ArrayList<UIShape> shapes = new ArrayList<UIShape>();
+
+ private final float sceneDist, zNear, zFar;
+
+ private RegionRenderer renderer;
+
+ private final int[] sampleCount = new int[1];
+
+ /** Describing the bounding box in model-coordinates of the near-plane parallel at distance one. */
+ private final AABBox nearPlane1Box = new AABBox();
+ private final int[] viewport = new int[] { 0, 0, 0, 0 };
+ private final float[] sceneScale = new float[3];
+ private final float[] scenePlaneOrigin = new float[3];
+
+
+ private volatile UIShape activeShape = null;
+
private SBCMouseListener sbcMouseListener = null;
-
+ private SBCGestureListener sbcGestureListener = null;
+ private PinchToZoomGesture pinchToZoomGesture = null;
+
private GLAutoDrawable cDrawable = null;
- public SceneUIController() {
+ public SceneUIController(final float sceneDist, final float zNear, final float zFar) {
+ this(null, sceneDist, zNear, zFar);
}
-
- public void setRenderer(RegionRenderer renderer, RenderState rs, int renderModes, int[] texSize) {
+
+ public SceneUIController(final RegionRenderer renderer, final float sceneDist, final float zNear, final float zFar) {
this.renderer = renderer;
- this.rs = rs;
- this.renderModes = renderModes;
- this.texSize = texSize;
+ this.sceneDist = sceneDist;
+ this.zFar = zFar;
+ this.zNear = zNear;
+ this.sampleCount[0] = 4;
}
-
- public SceneUIController(RegionRenderer renderer, RenderState rs, int renderModes, int[] texSize) {
+
+ public void setRenderer(final RegionRenderer renderer) {
this.renderer = renderer;
- this.rs = rs;
- this.renderModes = renderModes;
- this.texSize = texSize;
}
-
- public void attachInputListenerTo(GLWindow window) {
+
+ public void attachInputListenerTo(final GLWindow window) {
if(null == sbcMouseListener) {
sbcMouseListener = new SBCMouseListener();
window.addMouseListener(sbcMouseListener);
+ sbcGestureListener = new SBCGestureListener();
+ window.addGestureListener(sbcGestureListener);
+ pinchToZoomGesture = new PinchToZoomGesture(window.getNativeSurface(), false);
+ window.addGestureHandler(pinchToZoomGesture);
}
}
- public void detachInputListenerFrom(GLWindow window) {
+ public void detachInputListenerFrom(final GLWindow window) {
if(null != sbcMouseListener) {
window.removeMouseListener(sbcMouseListener);
+ sbcMouseListener = null;
+ window.removeGestureListener(sbcGestureListener);
+ sbcGestureListener = null;
+ window.removeGestureHandler(pinchToZoomGesture);
+ pinchToZoomGesture = null;
}
}
-
+
public ArrayList<UIShape> getShapes() {
return shapes;
}
- public void addShape(UIShape b) {
+ public void addShape(final UIShape b) {
shapes.add(b);
- count++;
+ }
+ public void removeShape(final UIShape b) {
+ shapes.remove(b);
}
- public void removeShape(UIShape b) {
- boolean found = shapes.remove(b);
- if(found) {
- count--;
+ public int getSampleCount() { return sampleCount[0]; }
+ public int setSampleCount(final int v) {
+ sampleCount[0] = Math.min(8, Math.max(v, 1)); // clip
+ markAllShapesDirty();
+ return sampleCount[0];
+ }
+
+ public void setAllShapesQuality(final int q) {
+ for(int i=0; i<shapes.size(); i++) {
+ shapes.get(i).setQuality(q);
+ }
+ }
+ public void setAllShapesSharpness(final float sharpness) {
+ for(int i=0; i<shapes.size(); i++) {
+ shapes.get(i).setSharpness(sharpness);
+ }
+ }
+ public void markAllShapesDirty() {
+ for(int i=0; i<shapes.size(); i++) {
+ shapes.get(i).markShapeDirty();
}
}
-
- public void init(GLAutoDrawable drawable) {
+
+ public final float[] getSceneScale() { return sceneScale; }
+ public final float[] getScenePlaneOrigin() { return scenePlaneOrigin; }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
System.err.println("SceneUIController: init");
cDrawable = drawable;
}
- public void display(GLAutoDrawable drawable) {
- // System.err.println("SceneUIController: display");
- final int width = drawable.getWidth();
- final int height = drawable.getHeight();
- GL2ES2 gl = drawable.getGL().getGL2ES2();
- render(gl, width, height, renderModes, texSize, false);
+ private void transformShape(final PMVMatrix pmv, final UIShape uiShape) {
+ final float[] uiTranslate = uiShape.getTranslate();
+ pmv.glTranslatef(uiTranslate[0], uiTranslate[1], uiTranslate[2]);
+ // final float dz = 100f;
+
+ final Quaternion quat = uiShape.getRotation();
+ final boolean rotate = !quat.isIdentity();
+ final float[] uiScale = uiShape.getScale();
+ final boolean scale = !VectorUtil.isVec3Equal(uiScale, 0, VectorUtil.VEC3_ONE, 0, FloatUtil.EPSILON);
+ if( rotate || scale ) {
+ final float[] rotOrigin = uiShape.getRotationOrigin();
+ final boolean pivot = !VectorUtil.isVec3Zero(rotOrigin, 0, FloatUtil.EPSILON);
+ // pmv.glTranslatef(0f, 0f, dz);
+ if( pivot ) {
+ pmv.glTranslatef(rotOrigin[0], rotOrigin[1], rotOrigin[2]);
+ }
+ if( scale ) {
+ pmv.glScalef(uiScale[0], uiScale[1], uiScale[2]);
+ }
+ if( rotate ) {
+ pmv.glRotate(quat);
+ }
+ if( pivot ) {
+ pmv.glTranslatef(-rotOrigin[0], -rotOrigin[1], -rotOrigin[2]);
+ }
+ // pmv.glTranslatef(0f, 0f, -dz);
+ }
}
-
- public void dispose(GLAutoDrawable drawable) {
- System.err.println("SceneUIController: dispose");
- cDrawable = null;
+
+ private static Comparator<UIShape> shapeZAscComparator = new Comparator<UIShape>() {
+ @Override
+ public int compare(final UIShape s1, final UIShape s2) {
+ final float s1Z = s1.getBounds().getMinZ()+s1.getTranslate()[2];
+ final float s2Z = s2.getBounds().getMinZ()+s2.getTranslate()[2];
+ if( FloatUtil.isEqual(s1Z, s2Z, FloatUtil.EPSILON) ) {
+ return 0;
+ } else if( s1Z < s2Z ){
+ return -1;
+ } else {
+ return 1;
+ }
+ } };
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+ final PMVMatrix pmv = renderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+
+ final Object[] shapesS = shapes.toArray();
+ Arrays.sort(shapesS, (Comparator)shapeZAscComparator);
+
+ renderer.enable(gl, true);
+
+ //final int shapeCount = shapes.size();
+ final int shapeCount = shapesS.length;
+ for(int i=0; i<shapeCount; i++) {
+ // final UIShape uiShape = shapes.get(i);
+ final UIShape uiShape = (UIShape)shapesS[i];
+ // System.err.println("Id "+i+": "+uiShape);
+ if( uiShape.isEnabled() ) {
+ uiShape.validate(gl, renderer);
+ pmv.glPushMatrix();
+ transformShape(pmv, uiShape);
+ uiShape.drawShape(gl, renderer, sampleCount);
+ pmv.glPopMatrix();
+ }
+ }
+
+ renderer.enable(gl, false);
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width,
- int height) {
- System.err.println("SceneUIController: reshape");
- GL2ES2 gl = drawable.getGL().getGL2ES2();
- renderer.reshapePerspective(gl, 45.0f, width, height, 5f, 70.0f);
+ public void pickShape(final int glWinX, final int glWinY, final float[] objPos, final UIShape[] shape, final Runnable runnable) {
+ if( null == cDrawable ) {
+ return;
+ }
+ cDrawable.invoke(false, new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ shape[0] = pickShapeImpl(glWinX, glWinY, objPos);
+ if( null != shape[0] ) {
+ runnable.run();
+ }
+ return true;
+ } } );
}
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private UIShape pickShapeImpl(final int glWinX, final int glWinY, final float[] objPos) {
+ final float winZ0 = 0f;
+ final float winZ1 = 0.3f;
+ /**
+ final FloatBuffer winZRB = Buffers.newDirectFloatBuffer(1);
+ gl.glReadPixels( x, y, 1, 1, GL2ES2.GL_DEPTH_COMPONENT, GL.GL_FLOAT, winZRB);
+ winZ1 = winZRB.get(0); // dir
+ */
+ final PMVMatrix pmv = renderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
- public UIShape getShape(GLAutoDrawable drawable,int x, int y) {
- final int width = drawable.getWidth();
- final int height = drawable.getHeight();
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final Ray ray = new Ray();
- int index = checkSelection(gl, x, y, width, height);
- if(index == -1)
- return null;
- return shapes.get(index);
+ final Object[] shapesS = shapes.toArray();
+ Arrays.sort(shapesS, (Comparator)shapeZAscComparator);
+
+ for(int i=shapesS.length-1; i>=0; i--) {
+ final UIShape uiShape = (UIShape)shapesS[i];
+
+ if( uiShape.isEnabled() ) {
+ pmv.glPushMatrix();
+ transformShape(pmv, uiShape);
+ final boolean ok = pmv.gluUnProjectRay(glWinX, glWinY, winZ0, winZ1, viewport, 0, ray);
+ pmv.glPopMatrix();
+ if( ok ) {
+ final AABBox sbox = uiShape.getBounds();
+ if( sbox.intersectsRay(ray) ) {
+ // System.err.printf("Pick.0: shape %d, [%d, %d, %f/%f] -> %s%n", i, glWinX, glWinY, winZ0, winZ1, ray);
+ if( null == sbox.getRayIntersection(objPos, ray, FloatUtil.EPSILON, true, dpyTmp1V3, dpyTmp2V3, dpyTmp3V3) ) {
+ throw new InternalError("Ray "+ray+", box "+sbox);
+ }
+ // System.err.printf("Pick.1: shape %d @ [%f, %f, %f], within %s%n", i, objPos[0], objPos[1], objPos[2], uiShape.getBounds());
+ return uiShape;
+ }
+ }
+ }
+ }
+ return null;
}
-
- public UIShape getActiveUI() {
- if(activeId == -1)
- return null;
- return shapes.get(activeId);
+ private final float[] dpyTmp1V3 = new float[3];
+ private final float[] dpyTmp2V3 = new float[3];
+ private final float[] dpyTmp3V3 = new float[3];
+
+ public void windowToShapeCoords(final UIShape activeShape, final int glWinX, final int glWinY, final float[] objPos, final Runnable runnable) {
+ if( null == cDrawable || null == activeShape ) {
+ return;
+ }
+ cDrawable.invoke(false, new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ if( windowToShapeCoordsImpl(activeShape, glWinX, glWinY, objPos) ) {
+ runnable.run();
+ }
+ return true;
+ } } );
}
-
- public void release() {
- activeId = -1;
+ private boolean windowToShapeCoordsImpl(final UIShape activeShape, final int glWinX, final int glWinY, final float[] objPos) {
+ final PMVMatrix pmv = renderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+
+ pmv.glPushMatrix();
+ transformShape(pmv, activeShape);
+ boolean res = false;
+ final float[] ctr = activeShape.getBounds().getCenter();
+ if( pmv.gluProject(ctr[0], ctr[1], ctr[2], viewport, 0, dpyTmp1V3, 0) ) {
+ // System.err.printf("winToShapeCoords.0: shape %d: obj [%f, %f, %f] -> win [%f, %f, %f]%n", shapeId, ctr[0], ctr[1], ctr[2], dpyTmp1V3[0], dpyTmp1V3[1], dpyTmp1V3[2]);
+ if( pmv.gluUnProject(glWinX, glWinY, dpyTmp1V3[2], viewport, 0, objPos, 0) ) {
+ // System.err.printf("winToShapeCoords.1: shape %d: win [%d, %d, %f] -> obj [%f, %f, %f]%n", shapeId, glWinX, glWinY, dpyTmp1V3[2], objPos[0], objPos[1], objPos[2]);
+ res = true;
+ }
+ }
+ pmv.glPopMatrix();
+ return res;
}
- private int checkSelection(GL2ES2 gl,int x, int y, int width, int height) {
- gl.glPixelStorei(GL2ES2.GL_PACK_ALIGNMENT, 4);
- gl.glPixelStorei(GL2ES2.GL_UNPACK_ALIGNMENT, 4);
- gl.glClearColor(sceneClearColor[0], sceneClearColor[1], sceneClearColor[2], sceneClearColor[3]);
- gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ System.err.println("SceneUIController: dispose");
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ for(int i=0; i<shapes.size(); i++) {
+ shapes.get(i).destroy(gl, renderer);
+ }
+ shapes.clear();
+ cDrawable = null;
+ }
- render(gl, width, height, 0, null, true);
- ByteBuffer pixel = Buffers.newDirectByteBuffer(4);
- pixel.order(ByteOrder.nativeOrder());
- IntBuffer viewport = IntBuffer.allocate(4);
- gl.glGetIntegerv(GL2ES2.GL_VIEWPORT, viewport);
- gl.glReadPixels(x, viewport.get(3) - y, 1, 1, GL2ES2.GL_RGBA,
- GL2ES2.GL_UNSIGNED_BYTE, pixel);
-
- int qp = pixel.get(0) & 0xFF;
- int index = Math.round(((qp/255.0f)*(count+2))-1);
- if(index < 0 || index >= count)
- return -1;
- return index;
+ public static void mapWin2ObjectCoords(final PMVMatrix pmv, final int[] view,
+ final float zNear, final float zFar,
+ final float orthoX, final float orthoY, final float orthoDist,
+ final float[] winZ, final float[] objPos) {
+ winZ[0] = FloatUtil.getOrthoWinZ(orthoDist, zNear, zFar);
+ pmv.gluUnProject(orthoX, orthoY, winZ[0], view, 0, objPos, 0);
}
- private void render(GL2ES2 gl, int width, int height, int renderModes, int[/*1*/] texSize, boolean select) {
- renderer.reshapePerspective(null, 45.0f, width, height, 0.1f, 7000.0f);
-
- for(int index=0; index < count;index++){
- if(select) {
- float color= index+1;
- renderer.setColorStatic(gl, color/(count+2), color/(count+2), color/(count+2));
- }
- float[] s = shapes.get(index).getScale();
- float[] p = shapes.get(index).getPosition();
- renderer.resetModelview(null);
- renderer.translate(null, translate[0]+p[0], translate[1]+p[1], translate[2]+p[2]);
- renderer.scale(gl, s[0], s[1], s[2]);
- renderer.rotate(gl, rotation[0], 1, 0, 0);
- renderer.rotate(gl, rotation[1], 0, 1, 0);
- renderer.rotate(gl, rotation[2], 0, 0, 1);
-
- shapes.get(index).render(gl, rs, renderer, renderModes, texSize, select);
- renderer.rotate(gl, -rotation[0], 1, 0, 0);
- renderer.rotate(gl, -rotation[1], 0, 1, 0);
- renderer.rotate(gl, -rotation[2], 0, 0, 1);
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ viewport[0] = x;
+ viewport[1] = y;
+ viewport[2] = width;
+ viewport[3] = height;
+
+ final PMVMatrix pmv = renderer.getMatrix();
+ renderer.reshapePerspective(45.0f, width, height, zNear, zFar);
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+
+ System.err.printf("Reshape: zNear %f, zFar %f%n", zNear, zFar);
+ System.err.printf("Reshape: Frustum: %s%n", pmv.glGetFrustum());
+ {
+ final float orthoDist = 1f;
+ final float[] obj00Coord = new float[3];
+ final float[] obj11Coord = new float[3];
+ final float[] winZ = new float[1];
+
+ mapWin2ObjectCoords(pmv, viewport, zNear, zFar, 0f, 0f, orthoDist, winZ, obj00Coord);
+ System.err.printf("Reshape: mapped.00: [%f, %f, %f], winZ %f -> [%f, %f, %f]%n", 0f, 0f, orthoDist, winZ[0], obj00Coord[0], obj00Coord[1], obj00Coord[2]);
+
+ mapWin2ObjectCoords(pmv, viewport, zNear, zFar, width, height, orthoDist, winZ, obj11Coord);
+ System.err.printf("Reshape: mapped.11: [%f, %f, %f], winZ %f -> [%f, %f, %f]%n", (float)width, (float)height, orthoDist, winZ[0], obj11Coord[0], obj11Coord[1], obj11Coord[2]);
+
+ nearPlane1Box.setSize( obj00Coord[0], // lx
+ obj00Coord[1], // ly
+ obj00Coord[2], // lz
+ obj11Coord[0], // hx
+ obj11Coord[1], // hy
+ obj11Coord[2] );// hz
+ System.err.printf("Reshape: dist1Box: %s%n", nearPlane1Box);
}
- }
+ scenePlaneOrigin[0] = nearPlane1Box.getMinX() * sceneDist;
+ scenePlaneOrigin[1] = nearPlane1Box.getMinY() * sceneDist;
+ scenePlaneOrigin[2] = nearPlane1Box.getMinZ() * sceneDist;
+ sceneScale[0] = ( nearPlane1Box.getWidth() * sceneDist ) / width;
+ sceneScale[1] = ( nearPlane1Box.getHeight() * sceneDist ) / height;
+ sceneScale[2] = 1f;
+ System.err.printf("Scene Origin [%f, %f, %f]%n", scenePlaneOrigin[0], scenePlaneOrigin[1], scenePlaneOrigin[2]);
+ System.err.printf("Scene Scale %f * [%f x %f] / [%d x %d] = [%f, %f, %f]%n",
+ sceneDist, nearPlane1Box.getWidth(), nearPlane1Box.getHeight(),
+ width, height,
+ sceneScale[0], sceneScale[1], sceneScale[2]);
- public void setTranslate(float x, float y, float z) {
- this.translate[0] = x;
- this.translate[1] = y;
- this.translate[2] = z;
+ pmv.glTranslatef(scenePlaneOrigin[0], scenePlaneOrigin[1], scenePlaneOrigin[2]);
+ pmv.glScalef(sceneScale[0], sceneScale[1], sceneScale[2]);
}
- public void setScale(float x, float y, float z) {
- this.scale[0] = x;
- this.scale[1] = y;
- this.scale[2] = z;
+ public final UIShape getShape(final int id) {
+ if( 0 > id ) {
+ return null;
+ }
+ return shapes.get(id);
+ }
+ public final UIShape getActiveShape() {
+ return activeShape;
}
- public void setRotation(float x, float y, float z) {
- this.rotation[0] = x;
- this.rotation[1] = y;
- this.rotation[2] = z;
+ public void release() {
+ setActiveShape(null);
}
- public float[] getSceneClearColor() {
- return sceneClearColor;
+ private void setActiveShape(final UIShape shape) {
+ activeShape = shape;
}
- public void setSceneClearColor(float r, float g, float b, float a) {
- this.sceneClearColor[0] = r;
- this.sceneClearColor[1] = g;
- this.sceneClearColor[2] = b;
- this.sceneClearColor[3] = a;
+ private final class SBCGestureListener implements GestureHandler.GestureListener {
+ @Override
+ public void gestureDetected(final GestureEvent gh) {
+ if( null != activeShape ) {
+ // gesture .. delegate to active shape!
+ final InputEvent orig = gh.getTrigger();
+ if( orig instanceof MouseEvent ) {
+ final MouseEvent e = (MouseEvent) orig;
+ // flip to GL window coordinates
+ final int glWinX = e.getX();
+ final int glWinY = viewport[3] - e.getY() - 1;
+ final float[] objPos = new float[3];
+ final UIShape shape = activeShape;
+ windowToShapeCoords(shape, glWinX, glWinY, objPos, new Runnable() {
+ public void run() {
+ shape.dispatchGestureEvent(gh, glWinX, glWinY, objPos);
+ } } );
+ }
+ }
+ }
+ }
+
+ final void dispatchMouseEvent(final MouseEvent e, final int glWinX, final int glWinY) {
+ if( null == activeShape ) {
+ dispatchMouseEventPickShape(e, glWinX, glWinY, true);
+ } else {
+ dispatchMouseEventForShape(activeShape, e, glWinX, glWinY);
+ }
}
-
+ final void dispatchMouseEventPickShape(final MouseEvent e, final int glWinX, final int glWinY, final boolean setActive) {
+ final float[] objPos = new float[3];
+ final UIShape[] shape = { null };
+ pickShape(glWinX, glWinY, objPos, shape, new Runnable() {
+ public void run() {
+ if( setActive ) {
+ setActiveShape(shape[0]);
+ }
+ shape[0].dispatchMouseEvent(e, glWinX, glWinY, objPos);
+ } } );
+ }
+ final void dispatchMouseEventForShape(final UIShape shape, final MouseEvent e, final int glWinX, final int glWinY) {
+ final float[] objPos = new float[3];
+ windowToShapeCoords(shape, glWinX, glWinY, objPos, new Runnable() {
+ public void run() {
+ shape.dispatchMouseEvent(e, glWinX, glWinY, objPos);
+ } } );
+ }
+
private class SBCMouseListener implements MouseListener {
- int mouseX = -1;
- int mouseY = -1;
-
- public void mouseClicked(MouseEvent e) {
- UIShape uiShape = getActiveUI();
- if(uiShape != null){
- uiShape.onClick();
- }
+ int lx=-1, ly=-1, lId=-1;
+
+ void clear() {
+ lx = -1; ly = -1; lId = -1;
}
- public void mousePressed(MouseEvent e) {
- if(null==cDrawable) {
- return;
+ @Override
+ public void mousePressed(final MouseEvent e) {
+ if( -1 == lId || e.getPointerId(0) == lId ) {
+ lx = e.getX();
+ ly = e.getY();
+ lId = e.getPointerId(0);
}
- mouseX = e.getX();
- mouseY = e.getY();
-
- GLRunnable runnable = new GLRunnable() {
- public boolean run(GLAutoDrawable drawable) {
- UIShape s = getShape(drawable, mouseX, mouseY);
- if(null != s) {
- activeId = getShapes().indexOf(s);
- }
- else {
- activeId = -1;
- }
- return false;
- }
- };
- cDrawable.invoke(true, runnable);
-
- UIShape uiShape = getActiveUI();
-
- if(uiShape != null) {
- uiShape.setPressed(true);
- uiShape.onPressed();
+ // flip to GL window coordinates
+ final int glWinX = e.getX();
+ final int glWinY = viewport[3] - e.getY() - 1;
+ dispatchMouseEvent(e, glWinX, glWinY);
+ }
+
+ @Override
+ public void mouseReleased(final MouseEvent e) {
+ // flip to GL window coordinates
+ final int glWinX = e.getX();
+ final int glWinY = viewport[3] - e.getY() - 1;
+ dispatchMouseEvent(e, glWinX, glWinY);
+ if( 1 == e.getPointerCount() ) {
+ // Release active shape: last pointer has been lifted!
+ release();
+ clear();
}
}
- public void mouseReleased(MouseEvent e) {
- UIShape uiShape = getActiveUI();
- if(uiShape != null){
- uiShape.setPressed(false);
- uiShape.onRelease();
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ // flip to GL window coordinates
+ final int glWinX = e.getX();
+ final int glWinY = viewport[3] - e.getY() - 1;
+ // activeId should have been released by mouseRelease() already!
+ dispatchMouseEventPickShape(e, glWinX, glWinY, false);
+ // Release active shape: last pointer has been lifted!
+ release();
+ clear();
+ }
+
+ @Override
+ public void mouseDragged(final MouseEvent e) {
+ // drag activeShape, if no gesture-activity, only on 1st pointer
+ if( null != activeShape && !pinchToZoomGesture.isWithinGesture() && e.getPointerId(0) == lId ) {
+ lx = e.getX();
+ ly = e.getY();
+
+ // dragged .. delegate to active shape!
+ // flip to GL window coordinates
+ final int glWinX = lx;
+ final int glWinY = viewport[3] - ly - 1;
+ dispatchMouseEventForShape(activeShape, e, glWinX, glWinY);
}
}
- public void mouseMoved(MouseEvent e) { }
- public void mouseEntered(MouseEvent e) { }
- public void mouseExited(MouseEvent e) { }
- public void mouseDragged(MouseEvent e) { }
- public void mouseWheelMoved(MouseEvent e) { }
-
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
+ // flip to GL window coordinates
+ final int glWinX = lx;
+ final int glWinY = viewport[3] - ly - 1;
+ dispatchMouseEventPickShape(e, glWinX, glWinY, true);
+ }
+
+ @Override
+ public void mouseMoved(final MouseEvent e) {
+ if( -1 == lId || e.getPointerId(0) == lId ) {
+ lx = e.getX();
+ ly = e.getY();
+ lId = e.getPointerId(0);
+ }
+ }
+ @Override
+ public void mouseEntered(final MouseEvent e) { }
+ @Override
+ public void mouseExited(final MouseEvent e) {
+ release();
+ clear();
+ }
}
} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TextureSeqButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TextureSeqButton.java
new file mode 100644
index 000000000..25134edf6
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TextureSeqButton.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph.demos.ui;
+
+import javax.media.opengl.GL2ES2;
+
+import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.opengl.util.texture.TextureSequence;
+
+/**
+ * GPU based resolution independent {@link TextureSequence} Button impl
+ */
+public class TextureSeqButton extends RoundButton {
+ protected final TextureSequence texSeq;
+
+ public TextureSeqButton(final Factory<? extends Vertex> factory, final int renderModes,
+ final float width, final float height, final TextureSequence texSeq) {
+ super(factory, renderModes | Region.COLORTEXTURE_RENDERING_BIT, width, height);
+ this.texSeq = texSeq;
+ }
+
+ @Override
+ protected GLRegion createGLRegion() {
+ return GLRegion.create(getRenderModes(), texSeq);
+ }
+
+ public final TextureSequence getTextureSequence() { return this.texSeq; }
+
+ @Override
+ protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) {
+ final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory());
+ if(corner == 0.0f) {
+ createSharpOutline(shape, 0f);
+ } else {
+ createCurvedOutline(shape, 0f);
+ }
+ shape.setIsQuadraticNurbs();
+ shape.setSharpness(shapesSharpness);
+ region.addOutlineShape(shape, null, rgbaColor);
+ box.resize(shape.getBounds());
+
+ final float[] ctr = box.getCenter();
+ setRotationOrigin( ctr[0], ctr[1], ctr[2]);
+
+ if( DRAW_DEBUG_BOX ) {
+ System.err.println("XXX.UIShape.TextureSeqButton: Added Shape: "+shape+", "+box);
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIGLListener01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIGLListener01.java
index da94f6a7c..65031d7a0 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIGLListener01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIGLListener01.java
@@ -33,32 +33,25 @@ import java.io.IOException;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
-import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.graph.geom.SVertex;
import com.jogamp.opengl.test.junit.graph.demos.MSAATool;
-import com.jogamp.opengl.test.junit.graph.demos.ui.opengl.UIRegion;
+import com.jogamp.opengl.util.PMVMatrix;
public class UIGLListener01 extends UIListenerBase01 {
-
- public UIGLListener01 (RenderState rs, boolean debug, boolean trace) {
- super(RegionRenderer.create(rs, 0), debug, trace);
+
+ public UIGLListener01 (final int renderModes, final RenderState rs, final boolean debug, final boolean trace) {
+ super(renderModes, RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable), debug, trace);
setMatrix(-20, 00, 0f, -50);
try {
final Font font = FontFactory.get(FontFactory.UBUNTU).getDefault();
- button = new RIButton(SVertex.factory(), font, "Click me!", 4f, 3f){
- public void onClick() {
- }
- public void onPressed() {
- }
- public void onRelease() {
- }
-
- };
- button.setPosition(2,1,0);
+ button = new LabelButton(SVertex.factory(), 0, font, "Click me!", 4f, 3f);
+ button.translate(2,1,0);
/** Button defaults !
button.setLabelColor(1.0f,1.0f,1.0f);
button.setButtonColor(0.6f,0.6f,0.6f);
@@ -66,65 +59,49 @@ public class UIGLListener01 extends UIListenerBase01 {
button.setSpacing(2.0f);
*/
System.err.println(button);
- } catch (IOException ex) {
- System.err.println("Catched: "+ex.getMessage());
+ } catch (final IOException ex) {
+ System.err.println("Caught: "+ex.getMessage());
ex.printStackTrace();
- }
+ }
}
-
- public void init(GLAutoDrawable drawable) {
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
super.init(drawable);
-
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
gl.setSwapInterval(1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
- gl.glEnable(GL2ES2.GL_POLYGON_OFFSET_FILL);
-
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
+
MSAATool.dump(drawable);
}
- UIRegion regionButton;
- UIRegion regionLabel;
-
- public void display(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ final int[] sampleCount = { 4 };
+ final float[] translate = button.getTranslate();
+
final RegionRenderer regionRenderer = getRegionRenderer();
- final RenderState rs = regionRenderer.getRenderState();
-
- regionRenderer.resetModelview(null);
-
- regionRenderer.translate(null, getXTran(), getYTran(), getZoom());
- regionRenderer.rotate(gl, getAngle(), 0, 1, 0);
-
- final float[] bColor = button.getButtonColor();
- final float[] lColor = button.getLabelColor();
- if(null == regionButton) {
- regionButton = new UIRegion(button);
- regionLabel = new UIRegion(button.getLabel());
- }
-
- regionRenderer.setColorStatic(gl, bColor[0], bColor[1], bColor[2]);
- regionRenderer.draw(gl, regionButton.getRegion(gl, rs, 0), getPosition(), null);
-// regionRenderer.translate(gl, button.getPosition()[0], button.getPosition()[1], button.getPosition()[2]);
- regionRenderer.setColorStatic(gl, lColor[0], lColor[1], lColor[2]);
- regionRenderer.draw(gl, regionLabel.getRegion(gl, rs, 0), getPosition(), null);
- }
-
- public void dispose(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
- if(null != regionButton) {
- regionButton.destroy(gl, getRegionRenderer().getRenderState());
- regionButton = null;
- }
- if(null != regionLabel) {
- regionLabel.destroy(gl, getRegionRenderer().getRenderState());
- regionButton = null;
- }
+ final PMVMatrix pmv = regionRenderer.getMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ pmv.glTranslatef(getXTran(), getYTran(), getZoom());
+ pmv.glRotatef(getAngle(), 0, 1, 0);
+ pmv.glTranslatef(translate[0], translate[1], 0);
+ button.drawShape(gl, regionRenderer, sampleCount);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ button.destroy(gl, getRegionRenderer());
super.dispose(drawable);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java
index 15daf70cd..796ed2513 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java
@@ -41,6 +41,7 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLPipelineFactory;
import javax.media.opengl.GLRunnable;
+import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
@@ -55,39 +56,41 @@ import com.jogamp.opengl.util.GLReadBufferUtil;
* - 1/2: zoom in/out
* - 4/5: increase/decrease shape/text spacing
* - 6/7: increase/decrease corner size
- * - 0/9: rotate
+ * - 0/9: rotate
* - v: toggle v-sync
* - s: screenshot
*/
public abstract class UIListenerBase01 implements GLEventListener {
- private GLReadBufferUtil screenshot;
- private RegionRenderer rRenderer;
- private boolean debug;
- private boolean trace;
-
- protected RIButton button;
-
+ private final GLReadBufferUtil screenshot;
+ private final int renderModes;
+ private final RegionRenderer rRenderer;
+ private final boolean debug;
+ private final boolean trace;
+
+ protected LabelButton button;
+
private KeyAction keyAction;
private MouseAction mouseAction;
-
+
private volatile GLAutoDrawable autoDrawable = null;
-
+
private final float[] position = new float[] {0,0,0};
-
+
private float xTran = -10;
- private float yTran = 10;
+ private float yTran = 10;
private float ang = 0f;
private float zoom = -70f;
boolean ignoreInput = false;
- public UIListenerBase01(RegionRenderer rRenderer, boolean debug, boolean trace) {
+ public UIListenerBase01(final int renderModes, final RegionRenderer rRenderer, final boolean debug, final boolean trace) {
+ this.renderModes = renderModes;
this.rRenderer = rRenderer;
this.debug = debug;
this.trace = trace;
this.screenshot = new GLReadBufferUtil(false, false);
}
-
+
public final RegionRenderer getRegionRenderer() { return rRenderer; }
public final float getZoom() { return zoom; }
public final float getXTran() { return xTran; }
@@ -95,14 +98,14 @@ public abstract class UIListenerBase01 implements GLEventListener {
public final float getAngle() { return ang; }
public final float[] getPosition() { return position; }
- public void setMatrix(float xtrans, float ytrans, float angle, int zoom) {
+ public void setMatrix(final float xtrans, final float ytrans, final float angle, final int zoom) {
this.xTran = xtrans;
- this.yTran = ytrans;
- this.ang = angle;
+ this.yTran = ytrans;
+ this.ang = angle;
this.zoom = zoom;
}
-
- public void init(GLAutoDrawable drawable) {
+
+ public void init(final GLAutoDrawable drawable) {
autoDrawable = drawable;
GL2ES2 gl = drawable.getGL().getGL2ES2();
if(debug) {
@@ -112,57 +115,57 @@ public abstract class UIListenerBase01 implements GLEventListener {
gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2();
}
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- getRegionRenderer().init(gl);
+ getRegionRenderer().init(gl, renderModes);
}
-
- public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- gl.glViewport(xstart, ystart, width, height);
- rRenderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 7000.0f);
+
+ public void reshape(final GLAutoDrawable drawable, final int xstart, final int ystart, final int width, final int height) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ gl.glViewport(xstart, ystart, width, height);
+ rRenderer.reshapePerspective(45.0f, width, height, 0.1f, 7000.0f);
dumpMatrix();
}
-
- public void dispose(GLAutoDrawable drawable) {
+
+ public void dispose(final GLAutoDrawable drawable) {
autoDrawable = null;
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
screenshot.dispose(gl);
rRenderer.destroy(gl);
- }
-
- public void zoom(int v){
+ }
+
+ public void zoom(final int v){
zoom += v;
dumpMatrix();
}
-
- public void move(float x, float y){
+
+ public void move(final float x, final float y){
xTran += x;
yTran += y;
dumpMatrix();
}
- public void rotate(float delta){
+ public void rotate(final float delta){
ang += delta;
ang %= 360.0f;
dumpMatrix();
}
-
+
void dumpMatrix() {
System.err.println("Matrix: " + xTran + "/" + yTran + " x"+zoom + " @"+ang);
}
-
- /** Attach the input listener to the window */
- public void attachInputListenerTo(GLWindow window) {
+
+ /** Attach the input listener to the window */
+ public void attachInputListenerTo(final GLWindow window) {
if ( null == keyAction ) {
keyAction = new KeyAction();
- window.addKeyListener(keyAction);
+ window.addKeyListener(keyAction);
}
if ( null == mouseAction ) {
mouseAction = new MouseAction();
- window.addMouseListener(mouseAction);
+ window.addMouseListener(mouseAction);
}
}
-
- public void detachFrom(GLWindow window) {
+
+ public void detachFrom(final GLWindow window) {
if ( null == keyAction ) {
return;
}
@@ -173,72 +176,72 @@ public abstract class UIListenerBase01 implements GLEventListener {
window.removeKeyListener(keyAction);
window.removeMouseListener(mouseAction);
}
-
- public void printScreen(GLAutoDrawable drawable, String dir, String tech, String objName, boolean exportAlpha) throws GLException, IOException {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), 0, objName);
-
+
+ public void printScreen(final GLAutoDrawable drawable, final String dir, final String tech, final String objName, final boolean exportAlpha) throws GLException, IOException {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw);
+ pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), (int)Math.abs(zoom), 0, objName);
+
final String filename = dir + tech + sw +".png";
if(screenshot.readPixels(drawable.getGL(), false)) {
screenshot.write(new File(filename));
}
}
-
+
int screenshot_num = 0;
- public void setIgnoreInput(boolean v) {
+ public void setIgnoreInput(final boolean v) {
ignoreInput = v;
}
public boolean getIgnoreInput() {
return ignoreInput;
}
-
+
public class MouseAction implements MouseListener{
- public void mouseClicked(MouseEvent e) {
-
+ public void mouseClicked(final MouseEvent e) {
+
}
- public void mouseEntered(MouseEvent e) {
+ public void mouseEntered(final MouseEvent e) {
}
- public void mouseExited(MouseEvent e) {
+ public void mouseExited(final MouseEvent e) {
}
- public void mousePressed(MouseEvent e) {
+ public void mousePressed(final MouseEvent e) {
button.setLabelColor(0.8f,0.8f,0.8f);
- button.setButtonColor(0.1f, 0.1f, 0.1f);
+ button.setColor(0.1f, 0.1f, 0.1f, 1.0f);
}
- public void mouseReleased(MouseEvent e) {
+ public void mouseReleased(final MouseEvent e) {
button.setLabelColor(1.0f,1.0f,1.0f);
- button.setButtonColor(0.6f,0.6f,0.6f);
+ button.setColor(0.6f,0.6f,0.6f, 1.0f);
}
- public void mouseMoved(MouseEvent e) {
+ public void mouseMoved(final MouseEvent e) {
// TODO Auto-generated method stub
-
+
}
- public void mouseDragged(MouseEvent e) {
+ public void mouseDragged(final MouseEvent e) {
// TODO Auto-generated method stub
-
+
}
- public void mouseWheelMoved(MouseEvent e) {
+ public void mouseWheelMoved(final MouseEvent e) {
// TODO Auto-generated method stub
-
+
}
-
+
}
-
+
public class KeyAction implements KeyListener {
- public void keyPressed(KeyEvent arg0) {
+ public void keyPressed(final KeyEvent arg0) {
if(ignoreInput) {
return;
}
-
+
if(arg0.getKeyCode() == KeyEvent.VK_1){
zoom(10);
}
@@ -258,19 +261,19 @@ public abstract class UIListenerBase01 implements GLEventListener {
move(-1, 0);
}
else if(arg0.getKeyCode() == KeyEvent.VK_4){
- button.setSpacing(button.getSpacing()-0.1f);
- System.err.println("Button Spacing: " + button.getSpacing());
+ button.setSpacing(button.getSpacingX()-0.01f, button.getSpacingY()-0.005f);
+ System.err.println("Button Spacing: " + button.getSpacingX());
}
else if(arg0.getKeyCode() == KeyEvent.VK_5){
- button.setSpacing(button.getSpacing()+0.1f);
- System.err.println("Button Spacing: " + button.getSpacing());
+ button.setSpacing(button.getSpacingX()+0.01f, button.getSpacingY()+0.005f);
+ System.err.println("Button Spacing: " + button.getSpacingX());
}
else if(arg0.getKeyCode() == KeyEvent.VK_6){
- button.setCorner(button.getCorner()-0.1f);
+ button.setCorner(button.getCorner()-0.01f);
System.err.println("Button Corner: " + button.getCorner());
}
else if(arg0.getKeyCode() == KeyEvent.VK_7){
- button.setCorner(button.getCorner()+0.1f);
+ button.setCorner(button.getCorner()+0.01f);
System.err.println("Button Corner: " + button.getCorner());
}
else if(arg0.getKeyCode() == KeyEvent.VK_0){
@@ -278,13 +281,13 @@ public abstract class UIListenerBase01 implements GLEventListener {
}
else if(arg0.getKeyCode() == KeyEvent.VK_9){
rotate(-1);
- }
+ }
else if(arg0.getKeyCode() == KeyEvent.VK_V) {
if(null != autoDrawable) {
autoDrawable.invoke(false, new GLRunnable() {
- public boolean run(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
- int i = gl.getSwapInterval();
+ public boolean run(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ int i = gl.getSwapInterval();
i = i==0 ? 1 : 0;
gl.setSwapInterval(i);
final GLAnimatorControl a = drawable.getAnimator();
@@ -295,29 +298,28 @@ public abstract class UIListenerBase01 implements GLEventListener {
return true;
}
});
- }
+ }
}
else if(arg0.getKeyCode() == KeyEvent.VK_S){
rotate(-1);
if(null != autoDrawable) {
autoDrawable.invoke(false, new GLRunnable() {
- public boolean run(GLAutoDrawable drawable) {
+ public boolean run(final GLAutoDrawable drawable) {
try {
- final String type = ( 1 == rRenderer.getRenderModes() ) ? "r2t0-msaa1" : "r2t1-msaa0" ;
+ final String type = Region.getRenderModeString(renderModes);
printScreen(drawable, "./", "demo-"+type, "snap"+screenshot_num, false);
screenshot_num++;
- } catch (GLException e) {
+ } catch (final GLException e) {
e.printStackTrace();
- } catch (IOException e) {
+ } catch (final IOException e) {
e.printStackTrace();
}
- return true;
+ return true;
}
});
- }
- }
+ }
+ }
}
- public void keyTyped(KeyEvent arg0) {}
- public void keyReleased(KeyEvent arg0) {}
+ public void keyReleased(final KeyEvent arg0) {}
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UINewtDemo01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UINewtDemo01.java
index 0577c5ff0..cd74f194c 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UINewtDemo01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UINewtDemo01.java
@@ -28,68 +28,64 @@
package com.jogamp.opengl.test.junit.graph.demos.ui;
-import javax.media.opengl.FPSCounter;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.graph.geom.SVertex;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.glsl.ShaderState;
/** Demonstrate the rendering of multiple outlines into one region/OutlineShape
* These Outlines are not necessary connected or contained.
* The output of this demo shows two identical shapes but the left one
- * has some vertices with off-curve flag set to true, and the right allt he vertices
- * are on the curve. Demos the Res. Independent Nurbs based Curve rendering
+ * has some vertices with off-curve flag set to true, and the right allt he vertices
+ * are on the curve. Demos the Res. Independent Nurbs based Curve rendering
*
*/
public class UINewtDemo01 {
static final boolean DEBUG = false;
static final boolean TRACE = false;
-
- public static void main(String[] args) {
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
+
+ public static void main(final String[] args) {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
caps.setAlphaBits(4);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
System.out.println("Requested: " + caps);
-
+
final GLWindow window = GLWindow.create(caps);
window.setPosition(10, 10);
window.setSize(800, 400);
window.setTitle("GPU UI Newt Demo 01");
- RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- UIGLListener01 uiGLListener = new UIGLListener01 (rs, DEBUG, TRACE);
- uiGLListener.attachInputListenerTo(window);
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+ final UIGLListener01 uiGLListener = new UIGLListener01 (0, rs, DEBUG, TRACE);
+ uiGLListener.attachInputListenerTo(window);
window.addGLEventListener(uiGLListener);
-
- window.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
window.setVisible(true);
final Animator animator = new Animator();
- animator.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
+ animator.setUpdateFPSFrames(60, System.err);
animator.add(window);
-
+
window.addKeyListener(new KeyAdapter() {
- public void keyPressed(KeyEvent arg0) {
+ public void keyPressed(final KeyEvent arg0) {
if(arg0.getKeyCode() == KeyEvent.VK_F4) {
window.destroy();
}
}
});
window.addWindowListener(new WindowAdapter() {
- public void windowDestroyed(WindowEvent e) {
+ public void windowDestroyed(final WindowEvent e) {
animator.stop();
}
});
-
+
animator.start();
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java
index 2f87fab66..3b8c71ed0 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java
@@ -27,104 +27,517 @@
*/
package com.jogamp.opengl.test.junit.graph.demos.ui;
+import java.util.ArrayList;
+
+import javax.media.nativewindow.NativeWindowException;
import javax.media.opengl.GL2ES2;
import com.jogamp.graph.curve.OutlineShape;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.graph.geom.AABBox;
import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.newt.event.GestureHandler.GestureEvent;
+import com.jogamp.newt.event.GestureHandler.GestureListener;
+import com.jogamp.newt.event.MouseAdapter;
+import com.jogamp.newt.event.NEWTEvent;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.MouseListener;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.geom.AABBox;
public abstract class UIShape {
+ public static final boolean DRAW_DEBUG_BOX = false;
+
+ protected static final int DIRTY_SHAPE = 1 << 0 ;
+ protected static final int DIRTY_STATE = 1 << 1 ;
+
private final Factory<? extends Vertex> vertexFactory;
- protected OutlineShape shape;
-
- protected static final int DIRTY_SHAPE = 1 << 0 ;
- protected int dirty = DIRTY_SHAPE;
-
+ private final int renderModes;
+ protected final AABBox box;
+
+ protected final float[] translate = new float[] { 0f, 0f, 0f };
+ protected final Quaternion rotation = new Quaternion();
+ protected final float[] rotOrigin = new float[] { 0f, 0f, 0f };
+ protected final float[] scale = new float[] { 1f, 1f, 1f };
+
+ protected GLRegion region = null;
+ protected int regionQuality = Region.MAX_QUALITY;
+
+ protected int dirty = DIRTY_SHAPE | DIRTY_STATE;
+ protected float shapesSharpness = OutlineShape.DEFAULT_SHARPNESS;
+
+ /** Default base-color w/o color channel, will be modulated w/ pressed- and toggle color */
+ protected final float[] rgbaColor = {0.75f, 0.75f, 0.75f, 1.0f};
+ /** Default pressed color-factor w/o color channel, modulated base-color. 0.75 * 1.2 = 0.9 */
+ protected final float[] pressedRGBAModulate = {1.2f, 1.2f, 1.2f, 0.7f};
+ /** Default toggle color-factor w/o color channel, modulated base-color. 0.75 * 1.13 ~ 0.85 */
+ protected final float[] toggleOnRGBAModulate = {1.13f, 1.13f, 1.13f, 1.0f};
+ /** Default toggle color-factor w/o color channel, modulated base-color. 0.75 * 0.86 ~ 0.65 */
+ protected final float[] toggleOffRGBAModulate = {0.86f, 0.86f, 0.86f, 1.0f};
+
+ private int name = -1;
+
private boolean down = false;
+ private boolean toggle = false;
+ private boolean toggleable = false;
+ private boolean enabled = true;
+ private ArrayList<MouseGestureListener> mouseListeners = new ArrayList<MouseGestureListener>();
- public UIShape(Factory<? extends Vertex> factory) {
+ public UIShape(final Factory<? extends Vertex> factory, final int renderModes) {
this.vertexFactory = factory;
- this.shape = new OutlineShape(factory);
- }
-
- public void clear() {
- clearImpl();
- shape.clear();
- }
-
- public abstract void render(GL2ES2 gl, RenderState rs, RegionRenderer renderer, int renderModes, int[/*1*/] texSize, boolean selection);
-
- protected boolean positionDirty = false;
-
- private float[] position = new float[]{0,0,0};
- private float[] scale = new float[]{1.0f,1.0f,1.0f};
- public void setScale(float x, float y, float z){
- scale[0] = x;
- scale[1] = y;
- scale[2] = z;
- }
-
- public void setPosition(float x, float y, float z) {
- this.position[0] = x;
- this.position[1] = y;
- this.position[2] = z;
- positionDirty = true;
- }
-
- private void updatePosition () {
- float minX = shape.getBounds().getLow()[0];
- float minY = shape.getBounds().getLow()[1];
- float minZ = shape.getBounds().getLow()[2];
- System.out.println("Position was: " + (position[0]) + " " + (position[1]) + " " + (position[2]));
- System.out.println("Position became: " + (position[0] - minX) + " " + (position[1] - minY) + " " + (position[2] - minZ));
- setPosition(position[0] - minX, position[1] - minY, position[2] - minZ);
- positionDirty = false;
- }
-
- public float[] getScale() { return scale; }
- public float[] getPosition() { return position; }
-
- protected abstract void clearImpl();
-
- protected abstract void createShape();
-
- public boolean updateShape() {
- if( isShapeDirty() ) {
- shape.clear();
- createShape();
- if(positionDirty){
- updatePosition();
+ this.renderModes = renderModes;
+ this.box = new AABBox();
+ }
+
+ public void setName(final int name) { this.name = name; }
+ public int getName() { return this.name; }
+
+ public final Vertex.Factory<? extends Vertex> getVertexFactory() { return vertexFactory; }
+
+ public boolean isEnabled() { return enabled; }
+ public void setEnabled(final boolean v) { enabled = v; }
+
+ /**
+ * Clears all data and reset all states as if this instance was newly created
+ * @param gl TODO
+ * @param renderer TODO\
+ */
+ public void clear(final GL2ES2 gl, final RegionRenderer renderer) {
+ clearImpl(gl, renderer);
+ translate[0] = 0f;
+ translate[1] = 0f;
+ translate[2] = 0f;
+ rotation.setIdentity();
+ rotOrigin[0] = 0f;
+ rotOrigin[1] = 0f;
+ rotOrigin[2] = 0f;
+ scale[0] = 1f;
+ scale[1] = 1f;
+ scale[2] = 1f;
+ box.reset();
+ markShapeDirty();
+ }
+
+ /**
+ * Destroys all data
+ * @param gl
+ * @param renderer
+ */
+ public void destroy(final GL2ES2 gl, final RegionRenderer renderer) {
+ destroyImpl(gl, renderer);
+ translate[0] = 0f;
+ translate[1] = 0f;
+ translate[2] = 0f;
+ rotation.setIdentity();
+ rotOrigin[0] = 0f;
+ rotOrigin[1] = 0f;
+ rotOrigin[2] = 0f;
+ scale[0] = 1f;
+ scale[1] = 1f;
+ scale[2] = 1f;
+ box.reset();
+ markShapeDirty();
+ }
+
+ public void setTranslate(final float tx, final float ty, final float tz) {
+ translate[0] = tx;
+ translate[1] = ty;
+ translate[2] = tz;
+ // System.err.println("UIShape.setTranslate: "+tx+"/"+ty+"/"+tz+": "+toString());
+ }
+ public void translate(final float tx, final float ty, final float tz) {
+ translate[0] += tx;
+ translate[1] += ty;
+ translate[2] += tz;
+ // System.err.println("UIShape.translate: "+tx+"/"+ty+"/"+tz+": "+toString());
+ }
+ public final float[] getTranslate() { return translate; }
+ public final Quaternion getRotation() { return rotation; }
+ public final float[] getRotationOrigin() { return rotOrigin; }
+ public void setRotationOrigin(final float rx, final float ry, final float rz) {
+ rotOrigin[0] = rx;
+ rotOrigin[1] = ry;
+ rotOrigin[2] = rz;
+ }
+ public void setScale(final float sx, final float sy, final float sz) {
+ scale[0] = sx;
+ scale[1] = sy;
+ scale[2] = sz;
+ }
+ public void scale(final float sx, final float sy, final float sz) {
+ scale[0] *= sx;
+ scale[1] *= sy;
+ scale[2] *= sz;
+ }
+ public final float[] getScale() { return scale; }
+
+ public final void markShapeDirty() {
+ dirty |= DIRTY_SHAPE;
+ }
+ public final boolean isShapeDirty() {
+ return 0 != ( dirty & DIRTY_SHAPE ) ;
+ }
+ public final void markStateDirty() {
+ dirty |= DIRTY_STATE;
+ }
+ public final boolean isStateDirty() {
+ return 0 != ( dirty & DIRTY_STATE ) ;
+ }
+
+ public final AABBox getBounds() { return box; }
+
+ public final int getRenderModes() { return renderModes; }
+
+ public GLRegion getRegion(final GL2ES2 gl, final RegionRenderer renderer) {
+ validate(gl, renderer);
+ return region;
+ }
+
+ /**
+ * Renders {@link OutlineShape} using local {@link GLRegion} which might be cached or updated.
+ * <p>
+ * No matrix operations (translate, scale, ..) are performed.
+ * </p>
+ * @param gl
+ * @param renderer
+ * @param sampleCount
+ */
+ public void drawShape(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
+ final float r, g, b, a;
+ final boolean isPressed = isPressed(), isToggleOn = isToggleOn();
+ final boolean modBaseColor = !Region.hasColorChannel( renderModes ) && !Region.hasColorTexture( renderModes );
+ if( modBaseColor ) {
+ if( isPressed ) {
+ r = rgbaColor[0]*pressedRGBAModulate[0];
+ g = rgbaColor[1]*pressedRGBAModulate[1];
+ b = rgbaColor[2]*pressedRGBAModulate[2];
+ a = rgbaColor[3]*pressedRGBAModulate[3];
+ } else if( isToggleable() ) {
+ if( isToggleOn ) {
+ r = rgbaColor[0]*toggleOnRGBAModulate[0];
+ g = rgbaColor[1]*toggleOnRGBAModulate[1];
+ b = rgbaColor[2]*toggleOnRGBAModulate[2];
+ a = rgbaColor[3]*toggleOnRGBAModulate[3];
+ } else {
+ r = rgbaColor[0]*toggleOffRGBAModulate[0];
+ g = rgbaColor[1]*toggleOffRGBAModulate[1];
+ b = rgbaColor[2]*toggleOffRGBAModulate[2];
+ a = rgbaColor[3]*toggleOffRGBAModulate[3];
+ }
+ } else {
+ r = rgbaColor[0];
+ g = rgbaColor[1];
+ b = rgbaColor[2];
+ a = rgbaColor[3];
+ }
+ } else {
+ if( isPressed ) {
+ r = pressedRGBAModulate[0];
+ g = pressedRGBAModulate[1];
+ b = pressedRGBAModulate[2];
+ a = pressedRGBAModulate[3];
+ } else if( isToggleable() ) {
+ if( isToggleOn ) {
+ r = toggleOnRGBAModulate[0];
+ g = toggleOnRGBAModulate[1];
+ b = toggleOnRGBAModulate[2];
+ a = toggleOnRGBAModulate[3];
+ } else {
+ r = toggleOffRGBAModulate[0];
+ g = toggleOffRGBAModulate[1];
+ b = toggleOffRGBAModulate[2];
+ a = toggleOffRGBAModulate[3];
+ }
+ } else {
+ r = rgbaColor[0];
+ g = rgbaColor[1];
+ b = rgbaColor[2];
+ a = rgbaColor[3];
}
- dirty &= ~DIRTY_SHAPE;
- return true;
}
- return false;
- }
-
- public final Vertex.Factory<? extends Vertex> getVertexFactory() { return vertexFactory; }
- public AABBox getBounds() { return shape.getBounds(); }
-
- public OutlineShape getShape() {
- updateShape();
- return shape;
- }
-
- public boolean isShapeDirty() {
- return 0 != ( dirty & DIRTY_SHAPE ) ;
- }
-
- public void setPressed(boolean b) {
+ renderer.getRenderState().setColorStatic(r, g, b, a);
+ getRegion(gl, renderer).draw(gl, renderer, sampleCount);
+ }
+
+ protected GLRegion createGLRegion() {
+ return GLRegion.create(renderModes, null);
+ }
+
+ /**
+ * Validates the shape's underlying {@link GLRegion}.
+ *
+ * @param gl
+ * @param renderer
+ */
+ public final void validate(final GL2ES2 gl, final RegionRenderer renderer) {
+ if( isShapeDirty() || null == region ) {
+ box.reset();
+ if( null == region ) {
+ region = createGLRegion();
+ } else {
+ region.clear(gl);
+ }
+ addShapeToRegion(gl, renderer);
+ if( DRAW_DEBUG_BOX ) {
+ region.clear(gl);
+ final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory());
+ shape.setSharpness(shapesSharpness);
+ shape.setIsQuadraticNurbs();
+ region.addOutlineShape(shape, null, rgbaColor);
+ }
+ region.setQuality(regionQuality);
+ dirty &= ~(DIRTY_SHAPE|DIRTY_STATE);
+ } else if( isStateDirty() ) {
+ region.markStateDirty();
+ dirty &= ~DIRTY_STATE;
+ }
+ }
+
+ public float[] getColor() {
+ return rgbaColor;
+ }
+
+ public final int getQuality() { return regionQuality; }
+ public final void setQuality(final int q) {
+ this.regionQuality = q;
+ if( null != region ) {
+ region.setQuality(q);
+ }
+ }
+ public final void setSharpness(final float sharpness) {
+ this.shapesSharpness = sharpness;
+ markShapeDirty();
+ }
+ public final float getSharpness() {
+ return shapesSharpness;
+ }
+
+ public final void setColor(final float r, final float g, final float b, final float a) {
+ this.rgbaColor[0] = r;
+ this.rgbaColor[1] = g;
+ this.rgbaColor[2] = b;
+ this.rgbaColor[3] = a;
+ }
+ public final void setPressedColorMod(final float r, final float g, final float b, final float a) {
+ this.pressedRGBAModulate[0] = r;
+ this.pressedRGBAModulate[1] = g;
+ this.pressedRGBAModulate[2] = b;
+ this.pressedRGBAModulate[3] = a;
+ }
+ public final void setToggleOnColorMod(final float r, final float g, final float b, final float a) {
+ this.toggleOnRGBAModulate[0] = r;
+ this.toggleOnRGBAModulate[1] = g;
+ this.toggleOnRGBAModulate[2] = b;
+ this.toggleOnRGBAModulate[3] = a;
+ }
+ public final void setToggleOffColorMod(final float r, final float g, final float b, final float a) {
+ this.toggleOffRGBAModulate[0] = r;
+ this.toggleOffRGBAModulate[1] = g;
+ this.toggleOffRGBAModulate[2] = b;
+ this.toggleOffRGBAModulate[3] = a;
+ }
+
+ @Override
+ public final String toString() {
+ return getClass().getSimpleName()+"["+getSubString()+"]";
+ }
+
+ public String getSubString() {
+ return "enabled "+enabled+", toggle[able "+toggleable+", state "+toggle+"], "+translate[0]+" / "+translate[1]+", box "+box;
+ }
+
+ //
+ // Input
+ //
+
+ public void setPressed(final boolean b) {
this.down = b;
+ markStateDirty();
}
-
public boolean isPressed() {
return this.down;
}
-
- public abstract void onClick();
- public abstract void onPressed();
- public abstract void onRelease();
+
+ public void setToggleable(final boolean toggleable) {
+ this.toggleable = toggleable;
+ }
+ public boolean isToggleable() {
+ return toggleable;
+ }
+ public void setToggle(final boolean v) {
+ toggle = v;
+ markStateDirty();
+ }
+ public void toggle() {
+ if( isToggleable() ) {
+ toggle = !toggle;
+ }
+ markStateDirty();
+ }
+ public boolean isToggleOn() { return toggle; }
+
+ public final void addMouseListener(final MouseGestureListener l) {
+ if(l == null) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ final ArrayList<MouseGestureListener> clonedListeners = (ArrayList<MouseGestureListener>) mouseListeners.clone();
+ clonedListeners.add(l);
+ mouseListeners = clonedListeners;
+ }
+
+ public final void removeMouseListener(final MouseGestureListener l) {
+ if (l == null) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ final ArrayList<MouseGestureListener> clonedListeners = (ArrayList<MouseGestureListener>) mouseListeners.clone();
+ clonedListeners.remove(l);
+ mouseListeners = clonedListeners;
+ }
+
+ /**
+ * Combining {@link MouseListener} and {@link GestureListener}
+ */
+ public static interface MouseGestureListener extends MouseListener, GestureListener {
+ }
+
+ /**
+ * Convenient adapter combining dummy implementation for {@link MouseListener} and {@link GestureListener}
+ */
+ public static abstract class MouseGestureAdapter extends MouseAdapter implements MouseGestureListener {
+ @Override
+ public void gestureDetected(final GestureEvent gh) {
+ }
+ }
+
+ /**
+ * {@link UIShape} event details for propagated {@link NEWTEvent}s
+ * containing reference of {@link #shape the intended shape} as well as
+ * the {@link #objPos rotated relative position} and {@link #rotBounds bounding box}.
+ * The latter fields are also normalized to lower-left zero origin, allowing easier usage.
+ */
+ public static class PointerEventInfo {
+ /** The intended {@link UIShape} instance for this event */
+ public final UIShape shape;
+ /** The relative pointer position inside the intended {@link UIShape}. */
+ public final float[] objPos;
+ /** window x-position in OpenGL model space */
+ public final int glWinX;
+ /** window y-position in OpenGL model space */
+ public final int glWinY;
+
+ PointerEventInfo(final int glWinX, final int glWinY, final UIShape shape, final float[] objPos) {
+ this.glWinX = glWinX;
+ this.glWinY = glWinY;
+ this.shape = shape;
+ this.objPos = objPos;
+ }
+
+ public String toString() {
+ return "EventDetails[winPos ["+glWinX+", "+glWinY+"], objPos ["+objPos[0]+", "+objPos[1]+", "+objPos[2]+"], "+shape+"]";
+ }
+ }
+
+ /**
+ * @param e original Newt {@link GestureEvent}
+ * @param glWinX x-position in OpenGL model space
+ * @param glWinY y-position in OpenGL model space
+ */
+ public final void dispatchGestureEvent(final GestureEvent e, final int glWinX, final int glWinY, final float[] objPos) {
+ e.setAttachment(new PointerEventInfo(glWinX, glWinY, this, objPos));
+ for(int i = 0; !e.isConsumed() && i < mouseListeners.size(); i++ ) {
+ mouseListeners.get(i).gestureDetected(e);
+ }
+ }
+
+ /**
+ *
+ * @param e original Newt {@link MouseEvent}
+ * @param glX x-position in OpenGL model space
+ * @param glY y-position in OpenGL model space
+ */
+ public final void dispatchMouseEvent(final MouseEvent e, final int glWinX, final int glWinY, final float[] objPos) {
+ e.setAttachment(new PointerEventInfo(glWinX, glWinY, this, objPos));
+
+ final short eventType = e.getEventType();
+ if( 1 == e.getPointerCount() ) {
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_CLICKED:
+ toggle();
+ break;
+ case MouseEvent.EVENT_MOUSE_PRESSED:
+ setPressed(true);
+ break;
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ setPressed(false);
+ break;
+ }
+ }
+
+ for(int i = 0; !e.isConsumed() && i < mouseListeners.size(); i++ ) {
+ final MouseGestureListener l = mouseListeners.get(i);
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_CLICKED:
+ l.mouseClicked(e);
+ break;
+ case MouseEvent.EVENT_MOUSE_ENTERED:
+ l.mouseEntered(e);
+ break;
+ case MouseEvent.EVENT_MOUSE_EXITED:
+ l.mouseExited(e);
+ break;
+ case MouseEvent.EVENT_MOUSE_PRESSED:
+ l.mousePressed(e);
+ break;
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ l.mouseReleased(e);
+ break;
+ case MouseEvent.EVENT_MOUSE_MOVED:
+ l.mouseMoved(e);
+ break;
+ case MouseEvent.EVENT_MOUSE_DRAGGED:
+ l.mouseDragged(e);
+ break;
+ case MouseEvent.EVENT_MOUSE_WHEEL_MOVED:
+ l.mouseWheelMoved(e);
+ break;
+ default:
+ throw new NativeWindowException("Unexpected mouse event type " + e.getEventType());
+ }
+ }
+ }
+
+ //
+ //
+ //
+
+ protected abstract void clearImpl(GL2ES2 gl, RegionRenderer renderer);
+ protected abstract void destroyImpl(GL2ES2 gl, RegionRenderer renderer);
+ protected abstract void addShapeToRegion(GL2ES2 gl, RegionRenderer renderer);
+
+ //
+ //
+ //
+
+ protected OutlineShape createDebugOutline(final OutlineShape shape, final AABBox box) {
+ final float tw = box.getWidth();
+ final float th = box.getHeight();
+
+ final float minX = box.getMinX();
+ final float minY = box.getMinY();
+ final float z = box.getMinZ() + 0.025f;
+
+ // CCW!
+ shape.addVertex(minX, minY, z, true);
+ shape.addVertex(minX+tw, minY, z, true);
+ shape.addVertex(minX+tw, minY + th, z, true);
+ shape.addVertex(minX, minY + th, z, true);
+ shape.closeLastOutline(true);
+
+ return shape;
+ }
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMono.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMono.ttf
new file mode 100644
index 000000000..c4200565a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMono.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoBold.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoBold.ttf
new file mode 100644
index 000000000..0bee057ec
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoBold.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoBoldOblique.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoBoldOblique.ttf
new file mode 100644
index 000000000..91bbc0e8a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoBoldOblique.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoOblique.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoOblique.ttf
new file mode 100644
index 000000000..3252bdda6
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeMonoOblique.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSans.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSans.ttf
new file mode 100644
index 000000000..e56dc6e90
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSans.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansBold.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansBold.ttf
new file mode 100644
index 000000000..66e19ecb0
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansBold.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansBoldOblique.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansBoldOblique.ttf
new file mode 100644
index 000000000..de8a9e153
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansBoldOblique.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansOblique.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansOblique.ttf
new file mode 100644
index 000000000..b0357eabb
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSansOblique.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerif.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerif.ttf
new file mode 100644
index 000000000..dffa1aedb
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerif.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifBold.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifBold.ttf
new file mode 100644
index 000000000..e2393ad22
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifBold.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifBoldItalic.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifBoldItalic.ttf
new file mode 100644
index 000000000..46bc4695f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifBoldItalic.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifItalic.ttf b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifItalic.ttf
new file mode 100644
index 000000000..d173e3566
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/fonts/freefont/FreeSerifItalic.ttf
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
new file mode 100644
index 000000000..710f53f92
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
@@ -0,0 +1,140 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.font.Font;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Test synchronous GLAutoDrawable display, swap-buffer and read-pixels
+ * including non-MSAA and MSAA framebuffer.
+ * <p>
+ * Analyzes behavior of reported bugs
+ * <ul>
+ * <li>Bug 841 - GLJPanel "lagging" by one frame, https://jogamp.org/bugzilla/show_bug.cgi?id=841</li>
+ * <li>Bug 975 - GLJPanel's OffscreenDrawable shall not double swap (custom swap by GLEventListener using [AWT]GLReadBufferUtil),
+ * https://jogamp.org/bugzilla/show_bug.cgi?id=975</li>
+ * <li>Bug 1020 - First frame on a mac nvidia card not antialiased, https://jogamp.org/bugzilla/show_bug.cgi?id=841</li>
+ * </ul>
+ * </p>
+ *
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class GLReadBuffer00Base extends UITestCase {
+
+ public static class TextRendererGLEL extends TextRendererGLELBase {
+ final Font font = getFont(0, 0, 0);
+ public int frameNo = 0;
+ public int userCounter = 0;
+ private final GLRegion regionFPS;
+
+ public TextRendererGLEL() {
+ // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+ super(Region.VBAA_RENDERING_BIT, new int[] { 4 });
+ this.setRendererCallbacks(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
+ regionFPS = GLRegion.create(renderModes, null);
+
+ staticRGBAColor[0] = 0.9f;
+ staticRGBAColor[1] = 0.9f;
+ staticRGBAColor[2] = 0.9f;
+ staticRGBAColor[3] = 0.99f;
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ regionFPS.destroy(drawable.getGL().getGL2ES2());
+ super.dispose(drawable);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final String text = String.format("Frame %04d (%03d): %04dx%04d", frameNo, userCounter, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ System.err.println("TextRendererGLEL.display: "+text);
+ if( null != renderer ) {
+ final float pixelSize = font.getPixelSize(14f, dpiH);
+ drawable.getGL().glClearColor(1f, 1f, 1f, 0f);
+ renderString(drawable, font, pixelSize, text, 0 /* col */, 0 /* row */, 0, 0, -1, regionFPS);
+ } else {
+ System.err.println(text);
+ }
+ frameNo++;
+ }
+ }
+
+ @BeforeClass
+ public static void initClass() throws IOException {
+ GLProfile.initSingleton();
+ }
+
+ protected abstract void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip);
+
+ @Test
+ public void test00_MSAA0_DefFlip() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */);
+ }
+
+ @Test
+ public void test01_MSAA0_UsrFlip() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */);
+ }
+
+ @Test
+ public void test10_MSAA8_DefFlip() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ caps.setNumSamples(8);
+ caps.setSampleBuffers(true);
+ test(caps, false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */);
+ }
+
+ @Test
+ public void test11_MSAA8_UsrFlip() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ caps.setNumSamples(8);
+ caps.setSampleBuffers(true);
+ test(caps, false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */);
+ }
+
+ static long duration = 500; // ms
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00BaseAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00BaseAWT.java
new file mode 100644
index 000000000..be0d38357
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00BaseAWT.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLEventListener;
+
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Test synchronous GLAutoDrawable display, swap-buffer and read-pixels
+ * including non-MSAA and MSAA framebuffer.
+ * <p>
+ * See {@link GLReadBuffer00Base} for related bugs and further details.
+ * </p>
+ */
+public abstract class GLReadBuffer00BaseAWT extends GLReadBuffer00Base {
+
+ protected class SnapshotGLELAWT implements GLEventListener {
+ final TextRendererGLEL textRendererGLEL;
+ final AWTGLReadBufferUtil glReadBufferUtil;
+ final boolean skipGLOrientationVerticalFlip;
+ boolean defAutoSwapMode;
+ boolean swapBuffersBeforeRead;
+ int i;
+
+ SnapshotGLELAWT(final TextRendererGLEL textRendererGLEL, final AWTGLReadBufferUtil glReadBufferUtil, final boolean skipGLOrientationVerticalFlip) {
+ this.textRendererGLEL = textRendererGLEL;
+ this.glReadBufferUtil = glReadBufferUtil;
+ this.skipGLOrientationVerticalFlip = skipGLOrientationVerticalFlip;
+ this.defAutoSwapMode = true;
+ this.swapBuffersBeforeRead = false;
+ i = 0;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ defAutoSwapMode = drawable.getAutoSwapBufferMode();
+ swapBuffersBeforeRead = GLDrawableUtil.swapBuffersBeforeRead(drawable.getChosenGLCapabilities());
+ drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead );
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ drawable.setAutoSwapBufferMode( defAutoSwapMode );
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ snapshot(i++, drawable.getGL(), TextureIO.PNG, null);
+ }
+ public void snapshot(final int sn, final GL gl, final String fileSuffix, final String destPath) {
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ final String postSNDetail = String.format("awt-usr%03d", textRendererGLEL.userCounter);
+ final String filenameAWT = getSnapshotFilename(sn, postSNDetail,
+ drawable.getChosenGLCapabilities(), drawable.getSurfaceWidth(), drawable.getSurfaceHeight(),
+ glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+ if( swapBuffersBeforeRead ) {
+ drawable.swapBuffers();
+ // Just to test whether we use the right buffer,
+ // i.e. back-buffer shall no more be required ..
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ } else {
+ gl.glFinish(); // just make sure rendering finished ..
+ }
+
+ final boolean awtOrientation = !( drawable.isGLOriented() && skipGLOrientationVerticalFlip );
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: awtOrient/v-flip "+awtOrientation+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameAWT);
+
+ final BufferedImage image = glReadBufferUtil.readPixelsToBufferedImage(gl, awtOrientation);
+ final File fout = new File(filenameAWT);
+ try {
+ ImageIO.write(image, "png", fout);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ /**
+ final String filenameJGL = getSnapshotFilename(sn, "jgl",
+ drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+ glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+ glReadBufferUtil.write(new File(filenameJGL));
+ */
+ }
+ };
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrentNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java
index 7127b0a5f..6bfe73e95 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrentNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,15 +20,13 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.jogl.acore;
-import java.io.IOException;
+package com.jogamp.opengl.test.junit.jogl.acore;
import javax.media.nativewindow.Capabilities;
import javax.media.nativewindow.util.InsetsImmutable;
@@ -37,85 +35,106 @@ import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.BeforeClass;
-import org.junit.Test;
-import com.jogamp.common.os.Platform;
+import com.jogamp.newt.Display;
import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
import com.jogamp.newt.Window;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.ValidateLockListener;
import com.jogamp.opengl.util.Animator;
-public class TestInitConcurrentNEWT extends UITestCase {
+/**
+ * Concurrent and lock-free initialization and rendering using exclusive NEWT Display EDT instances, or
+ * concurrent locked initialization and lock-free rendering using a shared NEWT Display EDT instances.
+ * <p>
+ * Rendering is always lock-free and independent of the EDT.
+ * </p>
+ * <p>
+ * Each test is decorated w/ {@link GLProfile#shutdown()} to ensure that
+ * implicit {@link GLProfile#initSingleton()} is also being tested.
+ * </p>
+ */
+public abstract class InitConcurrentBaseNEWT extends UITestCase {
+
+ static final int demoWinSize = 128;
- static final int demoSize = 128;
-
static long duration = 300; // ms
-
+
static InsetsImmutable insets = null;
- static int scrnHeight, scrnWidth;
static int num_x, num_y;
-
+
@BeforeClass
public static void initClass() {
- Window dummyWindow = NewtFactory.createWindow(new Capabilities());
- dummyWindow.setSize(demoSize, demoSize);
+ final Window dummyWindow = NewtFactory.createWindow(new Capabilities());
+ dummyWindow.setSize(demoWinSize, demoWinSize);
dummyWindow.setVisible(true);
Assert.assertEquals(true, dummyWindow.isVisible());
Assert.assertEquals(true, dummyWindow.isNativeValid());
- insets = dummyWindow.getInsets();
- scrnHeight = dummyWindow.getScreen().getHeight();
- scrnWidth = dummyWindow.getScreen().getWidth();
- num_x = scrnWidth / ( demoSize + insets.getTotalWidth() ) - 2;
- num_y = scrnHeight / ( demoSize + insets.getTotalHeight() ) - 2;
+ insets = dummyWindow.getInsets();
+ final int scrnHeight = dummyWindow.getScreen().getHeight();
+ final int scrnWidth = dummyWindow.getScreen().getWidth();
+ final int[] demoScreenSize = dummyWindow.convertToPixelUnits(new int[] { demoWinSize, demoWinSize });
+ final int[] insetsScreenSize = dummyWindow.convertToPixelUnits(new int[] { insets.getTotalWidth(), insets.getTotalHeight() });
+ num_x = scrnWidth / ( demoScreenSize[0] + insetsScreenSize[0] ) - 2;
+ num_y = scrnHeight / ( demoScreenSize[1] + insetsScreenSize[1] ) - 2;
dummyWindow.destroy();
}
-
- public class JOGLTask implements Runnable {
- private int id;
- private Object postSync;
+
+ public static class JOGLTask implements Runnable {
+ private final int id;
+ private final Object postSync;
+ private final boolean reuse;
private boolean done = false;
-
- public JOGLTask(Object postSync, int id) {
+
+ public JOGLTask(final Object postSync, final int id, final boolean reuse) {
this.postSync = postSync;
this.id = id;
+ this.reuse = reuse;
}
public void run() {
- int x = ( id % num_x ) * ( demoSize + insets.getTotalHeight() );
- int y = ( (id / num_x) % num_y ) * ( demoSize + insets.getTotalHeight() );
-
- System.err.println("JOGLTask "+id+": START: "+x+"/"+y+" - "+Thread.currentThread().getName());
- GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getDefault()));
+ final int x = ( id % num_x ) * ( demoWinSize + insets.getTotalHeight() );
+ final int y = ( (id / num_x) % num_y ) * ( demoWinSize + insets.getTotalHeight() );
+
+ System.err.println("JOGLTask "+id+": START: "+x+"/"+y+", reuse "+reuse+" - "+Thread.currentThread().getName());
+ final Display display = NewtFactory.createDisplay(null, reuse);
+ final Screen screen = NewtFactory.createScreen(display, 0);
+ final GLWindow glWindow = GLWindow.create(screen, new GLCapabilities(GLProfile.getDefault()));
Assert.assertNotNull(glWindow);
glWindow.setTitle("Task "+id);
glWindow.setPosition(x + insets.getLeftWidth(), y + insets.getTopHeight() );
-
+
+ glWindow.addGLEventListener(new ValidateLockListener());
glWindow.addGLEventListener(new GearsES2(0));
-
- Animator animator = new Animator(glWindow);
-
- glWindow.setSize(demoSize, demoSize);
+
+ final Animator animator = new Animator(glWindow);
+
+ glWindow.setSize(demoWinSize, demoWinSize);
glWindow.setVisible(true);
animator.setUpdateFPSFrames(60, null);
+
+ System.err.println("JOGLTask "+id+": INITIALIZED: "+", "+display+" - "+Thread.currentThread().getName());
+
animator.start();
Assert.assertEquals(true, animator.isAnimating());
Assert.assertEquals(true, glWindow.isVisible());
Assert.assertEquals(true, glWindow.isNativeValid());
Assert.assertEquals(true, glWindow.isRealized());
System.err.println("JOGLTask "+id+": RUNNING: "+Thread.currentThread().getName());
-
+
while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
try {
Thread.sleep(100);
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
e.printStackTrace();
}
}
-
+
animator.stop();
glWindow.destroy();
-
+
System.err.println("JOGLTask "+id+": DONE/SYNC: "+Thread.currentThread().getName());
synchronized (postSync) {
done = true;
@@ -123,11 +142,11 @@ public class TestInitConcurrentNEWT extends UITestCase {
postSync.notifyAll();
}
}
-
+
public boolean done() { return done; }
}
- protected static boolean done(JOGLTask[] tasks) {
+ protected static boolean done(final JOGLTask[] tasks) {
for(int i=tasks.length-1; i>=0; i--) {
if(!tasks[i].done()) {
return false;
@@ -135,8 +154,8 @@ public class TestInitConcurrentNEWT extends UITestCase {
}
return true;
}
- protected static String doneDump(JOGLTask[] tasks) {
- StringBuilder sb = new StringBuilder();
+ protected static String doneDump(final JOGLTask[] tasks) {
+ final StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i=0; i<tasks.length; i++) {
if(i>0) {
@@ -147,8 +166,8 @@ public class TestInitConcurrentNEWT extends UITestCase {
sb.append("]");
return sb.toString();
}
-
- protected static boolean isDead(Thread[] threads) {
+
+ protected static boolean isDead(final Thread[] threads) {
for(int i=threads.length-1; i>=0; i--) {
if(threads[i].isAlive()) {
return false;
@@ -156,8 +175,8 @@ public class TestInitConcurrentNEWT extends UITestCase {
}
return true;
}
- protected static String isAliveDump(Thread[] threads) {
- StringBuilder sb = new StringBuilder();
+ protected static String isAliveDump(final Thread[] threads) {
+ final StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i=0; i<threads.length; i++) {
if(i>0) {
@@ -168,29 +187,39 @@ public class TestInitConcurrentNEWT extends UITestCase {
sb.append("]");
return sb.toString();
}
-
- protected void runJOGLTasks(int num) throws InterruptedException {
+
+ protected void runJOGLTasks(final int num, final boolean reuse) throws InterruptedException {
+ GLProfile.shutdown();
+ System.err.println("InitConcurrentBaseNEWT "+num+" threads, reuse display: "+reuse);
final String currentThreadName = Thread.currentThread().getName();
- final Object sync = new Object();
+ final Object syncDone = new Object();
final JOGLTask[] tasks = new JOGLTask[num];
final Thread[] threads = new Thread[num];
int i;
for(i=0; i<num; i++) {
- tasks[i] = new JOGLTask(sync, i);
+ tasks[i] = new JOGLTask(syncDone, i, reuse);
threads[i] = new Thread(tasks[i], currentThreadName+"-jt"+i);
}
+ final long t0 = System.currentTimeMillis();
+
for(i=0; i<num; i++) {
threads[i].start();
}
- synchronized (sync) {
+ i=0;
+ synchronized (syncDone) {
while(!done(tasks)) {
try {
- sync.wait();
- } catch (InterruptedException e) {
+ syncDone.wait(500);
+ } catch (final InterruptedException e) {
throw new RuntimeException(e);
}
+ System.err.println(i+": "+doneDump(tasks));
+ i++;
}
}
+ final long t1 = System.currentTimeMillis();
+ System.err.println("total: "+(t1-t0)/1000.0+"s");
+
Assert.assertTrue("Tasks are incomplete. Complete: "+doneDump(tasks), done(tasks));
i=0;
while(i<30 && !isDead(threads)) {
@@ -198,38 +227,6 @@ public class TestInitConcurrentNEWT extends UITestCase {
i++;
}
Assert.assertTrue("Threads are still alive after 3s. Alive: "+isAliveDump(threads), isDead(threads));
+ GLProfile.shutdown();
}
-
- @Test
- public void test01OneThread() throws InterruptedException {
- runJOGLTasks(1);
- }
-
- @Test
- public void test02TwoThreads() throws InterruptedException {
- runJOGLTasks(2);
- }
-
- @Test
- public void test16SixteenThreads() throws InterruptedException {
- if( Platform.getCPUFamily() == Platform.CPUFamily.ARM ) {
- runJOGLTasks(8);
- } else {
- runJOGLTasks(16);
- }
- }
-
- public static void main(String args[]) throws IOException {
- for(int i=0; i<args.length; i++) {
- if(args[i].equals("-time")) {
- i++;
- try {
- duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
- }
- }
- String tstname = TestInitConcurrentNEWT.class.getName();
- org.junit.runner.JUnitCore.main(tstname);
- }
-
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java
index 8df54988f..0913cd2a8 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java
@@ -3,6 +3,8 @@ package com.jogamp.opengl.test.junit.jogl.acore;
import jogamp.nativewindow.x11.X11Util;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GLCapabilities;
@@ -14,6 +16,7 @@ import java.awt.Frame;
/**
* Tests the closing the device of GLCanvas in JOGL
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestAWTCloseX11DisplayBug565 {
@Test
@@ -22,30 +25,27 @@ public class TestAWTCloseX11DisplayBug565 {
try {
for ( int j = 0; j < 10; j++ ) {
final int open0;
- if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
+ if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
open0 = X11Util.getOpenDisplayConnectionNumber();
} else {
open0 = 0;
}
-
- GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault( ) );
- Frame frame = new Frame( "AWT Resource X11 Leak - #" + j );
-
- GLCanvas glCanvas = new GLCanvas( caps );
+
+ final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault( ) );
+ final Frame frame = new Frame( "AWT Resource X11 Leak - #" + j );
+
+ final GLCanvas glCanvas = new GLCanvas( caps );
frame.add( glCanvas );
- frame.setSize( 128, 128 );
-
- final Frame _frame = frame;
- final GLCanvas _glCanvas = glCanvas;
-
+
try {
javax.swing.SwingUtilities.invokeAndWait( new Runnable() {
public void run() {
- _frame.setVisible( true );
+ frame.setSize( 128, 128 );
+ frame.setVisible( true );
}
} );
}
- catch ( Throwable t ) {
+ catch ( final Throwable t ) {
t.printStackTrace();
Assert.fail(t.getMessage());
}
@@ -53,13 +53,13 @@ public class TestAWTCloseX11DisplayBug565 {
try {
javax.swing.SwingUtilities.invokeAndWait( new Runnable() {
public void run() {
- _frame.setVisible( false );
- _frame.remove( _glCanvas );
- _frame.dispose();
+ frame.setVisible( false );
+ frame.remove( glCanvas );
+ frame.dispose();
}
} );
}
- catch ( Throwable t ) {
+ catch ( final Throwable t ) {
t.printStackTrace();
Assert.fail(t.getMessage());
}
@@ -74,16 +74,16 @@ public class TestAWTCloseX11DisplayBug565 {
}
}
}
- catch ( Exception e ) {
+ catch ( final Exception e ) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestAWTCloseX11DisplayBug565.class.getName());
}
-
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java
new file mode 100644
index 000000000..87da6991a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java
@@ -0,0 +1,293 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestAddRemove01GLCanvasSwingAWT extends UITestCase {
+ static long durationPerTest = 100;
+ static int addRemoveCount = 15;
+ static int pauseEach = 0;
+ static int pauseDuration = 500;
+ static boolean noOnscreenTest = false;
+ static boolean noOffscreenTest = false;
+ static boolean offscreenPBufferOnly = false;
+ static boolean offscreenFBOOnly = false;
+ static GLProfile glpGL2, glpGL2ES2;
+ static int width, height;
+ static boolean waitForKey = false;
+ static boolean waitForKeyPost = false;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glpGL2ES2 = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glpGL2ES2);
+ }
+ if(GLProfile.isAvailable(GLProfile.GL2)) {
+ glpGL2 = GLProfile.get(GLProfile.GL2);
+ Assert.assertNotNull(glpGL2);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected JPanel create(final JFrame[] top, final int width, final int height, final int num)
+ throws InterruptedException, InvocationTargetException
+ {
+ final JPanel[] jPanel = new JPanel[] { null };
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ jPanel[0] = new JPanel();
+ jPanel[0].setLayout(new BorderLayout());
+
+ final JFrame jFrame1 = new JFrame("JFrame #"+num);
+ // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ jFrame1.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
+ jFrame1.getContentPane().add(jPanel[0]);
+ jFrame1.setSize(width, height);
+
+ top[0] = jFrame1;
+ } } );
+ return jPanel[0];
+ }
+
+ protected void add(final Container cont, final Component comp)
+ throws InterruptedException, InvocationTargetException
+ {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ cont.add(comp, BorderLayout.CENTER);
+ } } );
+ }
+
+ protected void dispose(final GLCanvas glc)
+ throws InterruptedException, InvocationTargetException
+ {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ glc.destroy();
+ } } );
+ }
+
+ protected void setVisible(final JFrame jFrame, final boolean visible) throws InterruptedException, InvocationTargetException {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ if( visible ) {
+ jFrame.pack();
+ jFrame.validate();
+ }
+ jFrame.setVisible(visible);
+ } } ) ;
+ }
+
+ protected void dispose(final JFrame jFrame) throws InterruptedException, InvocationTargetException {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ jFrame.dispose();
+ } } ) ;
+ }
+
+ protected void runTestGL(final boolean onscreen, final GLCapabilities caps, final int addRemoveOpCount)
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
+ for(int i=0; i<addRemoveOpCount; i++) {
+ int ti = 0;
+ System.err.println("Loop."+(ti++)+" "+(i+1)+"/"+addRemoveOpCount);
+ final GLCanvas glc = new GLCanvas(caps);
+ Assert.assertNotNull(glc);
+ if( !onscreen ) {
+ glc.setShallUseOffscreenLayer(true);
+ }
+ final Dimension glc_sz = new Dimension(width, height);
+ glc.setMinimumSize(glc_sz);
+ glc.setPreferredSize(glc_sz);
+ glc.setSize(glc_sz);
+ final GearsES2 gears = new GearsES2(1);
+ gears.setVerbose(false);
+ glc.addGLEventListener(gears);
+
+ final JFrame[] top = new JFrame[] { null };
+ final Container glcCont = create(top, width, height, i);
+ add(glcCont, glc);
+
+ setVisible(top[0], true);
+
+ final long t0 = System.currentTimeMillis();
+ do {
+ glc.display();
+ Thread.sleep(10);
+ } while ( ( System.currentTimeMillis() - t0 ) < durationPerTest ) ;
+
+ System.err.println("Loop."+(ti++)+" "+(i+1)+"/"+addRemoveOpCount+": GLCanvas isOffscreenLayerSurfaceEnabled: "+glc.isOffscreenLayerSurfaceEnabled()+": "+glc.getChosenGLCapabilities());
+
+ dispose(top[0]);
+
+ if( 0 < pauseEach && 0 == i % pauseEach ) {
+ System.err.println("******* P A U S E - Start ********");
+ // OSXUtil.WaitUntilFinish();
+ Thread.sleep(pauseDuration);
+ System.err.println("******* P A U S E - End ********");
+ }
+ }
+ if(waitForKeyPost) {
+ UITestCase.waitForKey("End");
+ }
+ }
+
+ @Test
+ public void test01Onscreen()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( noOnscreenTest || JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("No onscreen test requested or platform doesn't support onscreen rendering.");
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glpGL2ES2);
+ runTestGL(true, caps, addRemoveCount);
+ }
+
+ @Test
+ public void test02OffscreenFBO()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( noOffscreenTest || !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("No offscreen test requested or platform doesn't support offscreen rendering.");
+ return;
+ }
+ if( offscreenPBufferOnly ) {
+ System.err.println("Only PBuffer test is requested.");
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glpGL2ES2);
+ if(offscreenPBufferOnly) {
+ caps.setPBuffer(true);
+ caps.setOnscreen(true); // simulate normal behavior ..
+ }
+ runTestGL(false, caps, addRemoveCount);
+ }
+
+ @Test
+ public void test03OffscreenPBuffer()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( noOffscreenTest || !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("No offscreen test requested or platform doesn't support offscreen rendering.");
+ return;
+ }
+ if( offscreenFBOOnly ) {
+ System.err.println("Only FBO test is requested.");
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glpGL2);
+ caps.setPBuffer(true);
+ caps.setOnscreen(true); // simulate normal behavior ..
+ runTestGL(false, caps, addRemoveCount);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ durationPerTest = Long.parseLong(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-loops")) {
+ i++;
+ addRemoveCount = MiscUtils.atoi(args[i], addRemoveCount);
+ } else if(args[i].equals("-pauseEach")) {
+ i++;
+ pauseEach = MiscUtils.atoi(args[i], pauseEach);
+ } else if(args[i].equals("-pauseDuration")) {
+ i++;
+ pauseDuration = MiscUtils.atoi(args[i], pauseDuration);
+ } else if(args[i].equals("-noOnscreen")) {
+ noOnscreenTest = true;
+ } else if(args[i].equals("-noOffscreen")) {
+ noOffscreenTest = true;
+ } else if(args[i].equals("-layeredFBO")) {
+ offscreenFBOOnly = true;
+ } else if(args[i].equals("-layeredPBuffer")) {
+ offscreenPBufferOnly = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ } else if(args[i].equals("-waitPost")) {
+ waitForKeyPost = true;
+ }
+ }
+ System.err.println("waitForKey "+waitForKey);
+ System.err.println("waitForKeyPost "+waitForKeyPost);
+
+ System.err.println("addRemoveCount "+addRemoveCount);
+ System.err.println("pauseEach "+pauseEach);
+ System.err.println("pauseDuration "+pauseDuration);
+
+ System.err.println("noOnscreenTest "+noOnscreenTest);
+ System.err.println("noOffscreenTest "+noOffscreenTest);
+ System.err.println("offscreenPBufferOnly "+offscreenPBufferOnly);
+ System.err.println("offscreenFBOOnly "+offscreenFBOOnly);
+
+ org.junit.runner.JUnitCore.main(TestAddRemove01GLCanvasSwingAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove02GLWindowNewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove02GLWindowNewtCanvasAWT.java
new file mode 100644
index 000000000..7a26c0282
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove02GLWindowNewtCanvasAWT.java
@@ -0,0 +1,289 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestAddRemove02GLWindowNewtCanvasAWT extends UITestCase {
+ static long durationPerTest = 50;
+ static int addRemoveCount = 15;
+ static int pauseEach = 0;
+ static int pauseDuration = 500;
+ static boolean noOnscreenTest = false;
+ static boolean noOffscreenTest = false;
+ static boolean offscreenPBufferOnly = false;
+ static boolean offscreenFBOOnly = false;
+ static GLProfile glp;
+ static int width, height;
+ static boolean waitForKey = false;
+ static boolean waitForKeyPost = false;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ width = 640;
+ height = 480;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected JPanel create(final JFrame[] top, final int width, final int height, final int num)
+ throws InterruptedException, InvocationTargetException
+ {
+ final JPanel[] jPanel = new JPanel[] { null };
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ jPanel[0] = new JPanel();
+ jPanel[0].setLayout(new BorderLayout());
+
+ final JFrame jFrame1 = new JFrame("JFrame #"+num);
+ // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ jFrame1.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
+ jFrame1.getContentPane().add(jPanel[0]);
+ jFrame1.setSize(width, height);
+
+ top[0] = jFrame1;
+ } } );
+ return jPanel[0];
+ }
+
+ protected void add(final Container cont, final Component comp)
+ throws InterruptedException, InvocationTargetException
+ {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ cont.add(comp, BorderLayout.CENTER);
+ } } );
+ }
+
+ protected void dispose(final GLCanvas glc)
+ throws InterruptedException, InvocationTargetException
+ {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ glc.destroy();
+ } } );
+ }
+
+ protected void setVisible(final JFrame jFrame, final boolean visible) throws InterruptedException, InvocationTargetException {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ if( visible ) {
+ jFrame.pack();
+ jFrame.validate();
+ }
+ jFrame.setVisible(visible);
+ } } ) ;
+ }
+
+ protected void dispose(final JFrame jFrame) throws InterruptedException, InvocationTargetException {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ jFrame.dispose();
+ } } ) ;
+ }
+
+ protected void runTestGL(final boolean onscreen, final GLCapabilities caps, final int addRemoveOpCount)
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+
+ for(int i=0; i<addRemoveOpCount; i++) {
+ System.err.println("Loop # "+i+" / "+addRemoveCount);
+ final GLWindow glw = GLWindow.create(caps);
+ Assert.assertNotNull(glw);
+ final NewtCanvasAWT glc = new NewtCanvasAWT(glw);
+ Assert.assertNotNull(glc);
+ if( !onscreen ) {
+ glc.setShallUseOffscreenLayer(true);
+ }
+ final Dimension glc_sz = new Dimension(width, height);
+ glc.setMinimumSize(glc_sz);
+ glc.setPreferredSize(glc_sz);
+ glc.setSize(glc_sz);
+ final GearsES2 gears = new GearsES2(1);
+ gears.setVerbose(false);
+ glw.addGLEventListener(gears);
+
+ final JFrame[] top = new JFrame[] { null };
+ final Container glcCont = create(top, width, height, i);
+ add(glcCont, glc);
+
+ setVisible(top[0], true);
+
+ final long t0 = System.currentTimeMillis();
+ do {
+ glw.display();
+ Thread.sleep(10);
+ } while ( ( System.currentTimeMillis() - t0 ) < durationPerTest ) ;
+
+ System.err.println("GLCanvas isOffscreenLayerSurfaceEnabled: "+glc.isOffscreenLayerSurfaceEnabled()+": "+glw.getChosenGLCapabilities());
+
+ dispose(top[0]);
+ glw.destroy();
+
+ if( 0 < pauseEach && 0 == i % pauseEach ) {
+ System.err.println("******* P A U S E ********");
+ Thread.sleep(pauseDuration);
+ }
+ }
+ if(waitForKeyPost) {
+ UITestCase.waitForKey("End");
+ }
+ }
+
+ @Test
+ public void test01Onscreen()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( noOnscreenTest || JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("No onscreen test requested or platform doesn't support onscreen rendering.");
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(true, caps, addRemoveCount);
+ }
+
+ @Test
+ public void test02OffscreenFBO()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( noOffscreenTest || !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("No offscreen test requested or platform doesn't support offscreen rendering.");
+ return;
+ }
+ if( offscreenPBufferOnly ) {
+ System.err.println("Only PBuffer test is requested.");
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(false, caps, addRemoveCount);
+ }
+
+ @Test
+ public void test03OffscreenPBuffer()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( noOffscreenTest || !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("No offscreen test requested or platform doesn't support offscreen rendering.");
+ return;
+ }
+ if( offscreenFBOOnly ) {
+ System.err.println("Only FBO test is requested.");
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setPBuffer(true);
+ caps.setOnscreen(true); // simulate normal behavior ..
+ runTestGL(false, caps, addRemoveCount);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ durationPerTest = Long.parseLong(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-loops")) {
+ i++;
+ addRemoveCount = MiscUtils.atoi(args[i], addRemoveCount);
+ } else if(args[i].equals("-pauseEach")) {
+ i++;
+ pauseEach = MiscUtils.atoi(args[i], pauseEach);
+ } else if(args[i].equals("-pauseDuration")) {
+ i++;
+ pauseDuration = MiscUtils.atoi(args[i], pauseDuration);
+ } else if(args[i].equals("-noOnscreen")) {
+ noOnscreenTest = true;
+ } else if(args[i].equals("-noOffscreen")) {
+ noOffscreenTest = true;
+ } else if(args[i].equals("-layeredFBO")) {
+ offscreenFBOOnly = true;
+ } else if(args[i].equals("-layeredPBuffer")) {
+ offscreenPBufferOnly = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ } else if(args[i].equals("-waitPost")) {
+ waitForKeyPost = true;
+ }
+ }
+ System.err.println("waitForKey "+waitForKey);
+ System.err.println("waitForKeyPost "+waitForKeyPost);
+
+ System.err.println("addRemoveCount "+addRemoveCount);
+ System.err.println("pauseEach "+pauseEach);
+ System.err.println("pauseDuration "+pauseDuration);
+
+ System.err.println("noOnscreenTest "+noOnscreenTest);
+ System.err.println("noOffscreenTest "+noOffscreenTest);
+ System.err.println("offscreenPBufferOnly "+offscreenPBufferOnly);
+ System.err.println("offscreenFBOOnly "+offscreenFBOOnly);
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
+ org.junit.runner.JUnitCore.main(TestAddRemove02GLWindowNewtCanvasAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove03GLWindowNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove03GLWindowNEWT.java
new file mode 100644
index 000000000..70aa4dff3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove03GLWindowNEWT.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestAddRemove03GLWindowNEWT extends UITestCase {
+ static long durationPerTest = 50;
+ static int addRemoveCount = 15;
+ static int pauseEach = 0;
+ static int pauseDuration = 500;
+ static GLProfile glp;
+ static int width, height;
+ static boolean waitForKey = false;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ width = 640;
+ height = 480;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final int addRemoveOpCount)
+ throws InterruptedException, InvocationTargetException
+ {
+
+ for(int i=0; i<addRemoveOpCount; i++) {
+ System.err.println("Loop # "+i+" / "+addRemoveCount);
+ final GLWindow glw = GLWindow.create(caps);
+ Assert.assertNotNull(glw);
+ glw.setTitle("GLWindow #"+i);
+ glw.setSize(width, height);
+ final GearsES2 gears = new GearsES2(1);
+ gears.setVerbose(false);
+ glw.addGLEventListener(gears);
+
+ glw.setVisible(true);
+
+ final long t0 = System.currentTimeMillis();
+ do {
+ glw.display();
+ Thread.sleep(10);
+ } while ( ( System.currentTimeMillis() - t0 ) < durationPerTest ) ;
+
+ System.err.println("GLWindow: "+glw.getChosenGLCapabilities());
+
+ glw.destroy();
+
+ if( 0 < pauseEach && 0 == i % pauseEach ) {
+ System.err.println("******* P A U S E ********");
+ Thread.sleep(pauseDuration);
+ }
+ }
+ }
+
+ @Test
+ public void test01Onscreen()
+ throws InterruptedException, InvocationTargetException
+ {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, addRemoveCount);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ durationPerTest = Long.parseLong(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-loops")) {
+ i++;
+ addRemoveCount = MiscUtils.atoi(args[i], addRemoveCount);
+ } else if(args[i].equals("-pauseEach")) {
+ i++;
+ pauseEach = MiscUtils.atoi(args[i], pauseEach);
+ } else if(args[i].equals("-pauseDuration")) {
+ i++;
+ pauseDuration = MiscUtils.atoi(args[i], pauseDuration);
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ System.err.println("waitForKey "+waitForKey);
+
+ System.err.println("addRemoveCount "+addRemoveCount);
+ System.err.println("pauseEach "+pauseEach);
+ System.err.println("pauseDuration "+pauseDuration);
+
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
+ org.junit.runner.JUnitCore.main(TestAddRemove03GLWindowNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.java
new file mode 100644
index 000000000..05f70689c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import jogamp.opengl.GLContextImpl;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Tests simple recursive GLContext behavior.
+ *
+ * <p>
+ * Issues {@link GLContext#makeCurrent()} and {@link GLContext#release()}
+ * from within {@link GLEventListener#display(GLAutoDrawable)}.
+ * </p>
+ *
+ * <https://jogamp.org/bugzilla/show_bug.cgi?id=669>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug669RecursiveGLContext01NEWT extends UITestCase {
+
+ @Test(timeout=10000)
+ public void test01_Plain() {
+ test01Impl(false);
+ }
+
+ @Test(timeout=10000)
+ public void test01_Anim() {
+ test01Impl(true);
+ }
+
+ private void test01Impl(final boolean anim) {
+ final String profile = GLProfile.GL2ES2;
+ if(!GLProfile.isAvailable(profile)) { System.err.println(profile+" n/a"); return; }
+
+ final GLProfile pro = GLProfile.get(profile);
+ final GLCapabilities caps = new GLCapabilities(pro);
+ final GLWindow window = GLWindow.create(caps);
+
+ final Animator animator = new Animator();
+ if(anim) {
+ animator.add(window);
+ }
+ animator.start();
+
+ window.setSize(640, 480);
+ window.addGLEventListener(new GLEventListener() {
+ private void makeCurrentRecursive(final GLContextImpl context, final int lockCount) {
+ Assert.assertEquals(true, context.isOwner(Thread.currentThread()));
+ Assert.assertEquals(lockCount, context.getLockCount());
+ Assert.assertEquals(true, context.isCurrent());
+
+ Assert.assertEquals(GLContext.CONTEXT_CURRENT, context.makeCurrent()); // recursive: lock +1
+
+ Assert.assertEquals(true, context.isOwner(Thread.currentThread()));
+ Assert.assertEquals(lockCount+1, context.getLockCount());
+ Assert.assertEquals(true, context.isCurrent());
+ }
+ private void releaseRecursive(final GLContextImpl context, final int lockCount) {
+ Assert.assertEquals(true, context.isOwner(Thread.currentThread()));
+ Assert.assertEquals(lockCount, context.getLockCount());
+ Assert.assertEquals(true, context.isCurrent()); // still current
+
+ context.release(); // recursive: lock -1
+
+ Assert.assertEquals(true, context.isOwner(Thread.currentThread()));
+ Assert.assertEquals(lockCount-1, context.getLockCount());
+ Assert.assertEquals(true, context.isCurrent()); // still current
+ }
+
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+
+ public void init(final GLAutoDrawable drawable) { }
+
+ public void dispose(final GLAutoDrawable drawable) { }
+
+ public void display(final GLAutoDrawable drawable) {
+ final GLContextImpl context = (GLContextImpl)drawable.getContext();
+ makeCurrentRecursive(context, 1);
+ releaseRecursive(context, 2);
+ }
+ });
+ window.addGLEventListener(new GearsES2());
+
+ try {
+ window.setVisible(true);
+ window.display();
+ } finally {
+ animator.stop();
+ window.destroy();
+ }
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestBug669RecursiveGLContext01NEWT.class.getName());
+ }
+
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext02NEWT.java
new file mode 100644
index 000000000..4a8499be2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext02NEWT.java
@@ -0,0 +1,135 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Tests recursive GLContext behavior.
+ *
+ * <p>
+ * Issues {@link GLAutoDrawable#display()} of another {@link GLAutoDrawable}
+ * from within {@link GLEventListener#display(GLAutoDrawable)}.
+ * </p>
+ *
+ * <https://jogamp.org/bugzilla/show_bug.cgi?id=669>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug669RecursiveGLContext02NEWT extends UITestCase {
+
+ @Test(timeout=10000)
+ public void test01_Plain() {
+ test01Impl(false);
+ }
+
+ @Test(timeout=10000)
+ public void test01_Anim() {
+ test01Impl(true);
+ }
+
+ private void test01Impl(final boolean anim) {
+ final String profile = GLProfile.GL2ES2;
+ if(!GLProfile.isAvailable(profile)) { System.err.println(profile+" n/a"); return; }
+
+ final GLProfile pro = GLProfile.get(profile);
+ final GLCapabilities caps = new GLCapabilities(pro);
+
+ final GLWindow window2 = GLWindow.create(caps); // display() triggered by window's GLEventListener!
+ window2.setPosition(0, 0);
+ window2.setSize(200, 200);
+ window2.addGLEventListener(new RedSquareES2());
+
+ final GLWindow window1 = GLWindow.create(caps);
+
+ final Animator animator1 = new Animator();
+ final Animator animator2 = new Animator();
+ if(anim) {
+ animator1.add(window1);
+ animator2.add(window2);
+ }
+ animator1.start();
+ animator2.start();
+
+ window1.setPosition(250, 0);
+ window1.setSize(200, 200);
+ window1.addGLEventListener(new GLEventListener() {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+
+ public void init(final GLAutoDrawable drawable) { }
+
+ public void dispose(final GLAutoDrawable drawable) { }
+
+ public void display(final GLAutoDrawable drawable) {
+ window2.display();
+ }
+ });
+ window1.addGLEventListener(new GearsES2());
+
+ try {
+ window2.setVisible(true);
+ window1.setVisible(true);
+ window1.display();
+ window2.display();
+ if(anim) {
+ try {
+ Thread.sleep(500);
+ } catch(final InterruptedException ie) {}
+ }
+ } finally {
+ animator1.stop();
+
+ final int win1Frames = window1.getTotalFPSFrames();
+ final int win2Frames = window2.getTotalFPSFrames();
+ System.err.println("Window1: frames "+win1Frames);
+ System.err.println("Window2: frames "+win2Frames);
+ Assert.assertTrue("Win2 frames not double the amount of Win1 frames", 2*win2Frames >= win1Frames);
+ window1.destroy();
+ window2.destroy();
+ }
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestBug669RecursiveGLContext02NEWT.class.getName());
+ }
+
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug692GL3VAONEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug692GL3VAONEWT.java
new file mode 100644
index 000000000..0a9ff5a28
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug692GL3VAONEWT.java
@@ -0,0 +1,444 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GL3bc;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLBuffers;
+
+/**
+ * Test Vertex Array Object (VAO) Usage and BufferStateTracker
+ * <p>
+ * All combinations of CPU_SRC, VBO_ONLY and VBO_VAO are tested
+ * and validate the fix for Bug 692, i.e. <https://jogamp.org/bugzilla/show_bug.cgi?id=692>.
+ * </p>
+ * <p>
+ * Test order is important!
+ * </p>
+ * <p>
+ * Note that VAO initialization does unbind the VBO .. since otherwise they are still bound
+ * and the CPU_SRC test will fail!<br/>
+ * The OpenGL spec does not mention that unbinding a VAO will also unbind the bound VBOs
+ * during their setup.<br/>
+ * Local tests here on NV and AMD proprietary driver resulted in <i>no ourput image</i>
+ * when not unbinding said VBOs before the CPU_SRC tests.<br/>
+ * Hence Bug 692 Comment 5 is invalid, i.e. <https://jogamp.org/bugzilla/show_bug.cgi?id=692#c5>,
+ * and we should throw an exception to give users a hint!
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug692GL3VAONEWT extends UITestCase {
+ static long duration = 500; // ms
+
+ static class GL3VAODemo implements GLEventListener {
+ /** Different modes of displaying the geometry */
+ public enum Mode {
+ CPU_SRC {
+ @Override
+ void display(final GL3VAODemo t, final GL3bc gl) {
+ t.displayCPUSourcing(gl);
+ }
+ },
+
+ /** Traditional one without using VAO */
+ VBO_ONLY {
+ @Override
+ void display(final GL3VAODemo t, final GL3bc gl) {
+ t.displayVBOOnly(gl);
+ }
+ },
+
+ /** Using VAOs throws [incorrectly as of JOGL 2.0rc11] a GLException */
+ VBO_VAO {
+ @Override
+ void display(final GL3VAODemo t, final GL3bc gl) {
+ t.displayVBOVAO(gl);
+ }
+ };
+
+ abstract void display(GL3VAODemo t, GL3bc gl);
+ }
+
+ private final Mode[] allModes;
+ private Mode currentMode;
+ private int currentModeIdx;
+
+ public GL3VAODemo(final Mode[] modes) {
+ allModes = modes;
+ currentMode = allModes[0];
+ currentModeIdx = 0;
+ }
+
+ private final static float[] vertexColorData = new float[]{
+ 0.0f, 0.75f, 0.0f, 1,0,0,
+ -0.5f, -0.75f, 0.0f, 0,1,0,
+ 0.9f, -0.75f, 0.0f, 0,0,1
+ };
+ private final FloatBuffer vertexColorDataBuffer = GLBuffers.newDirectFloatBuffer(vertexColorData);
+
+ private final short[] indices = new short[]{0, 1, 2};
+ private final ShortBuffer indicesBuffer = GLBuffers.newDirectShortBuffer(indices);
+
+
+ private int ibo = -1;
+ private int vbo = -1;
+ private int vertID = -1;
+ private int fragID = -1;
+ private int progID = -1;
+
+ private int vao = -1;
+
+ private static int createShader(final GL3 gl, final int type,
+ final String[] srcLines){
+ final int shaderID = gl.glCreateShader(type);
+ assert shaderID > 0;
+ final int[] lengths = new int[srcLines.length];
+ for (int i = 0; i < srcLines.length; i++) {
+ lengths[i] = srcLines[i].length();
+ }
+ gl.glShaderSource(shaderID, srcLines.length, srcLines, lengths, 0);
+ gl.glCompileShader(shaderID);
+ return shaderID;
+ }
+
+ private void initBuffers(final GL3 gl) {
+ // IDs for 2 buffers
+ final int[] buffArray = new int[2];
+ gl.glGenBuffers(buffArray.length, buffArray, 0);
+ vbo = buffArray[0];
+ assert vbo > 0;
+
+ // Bind buffer and upload data
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo);
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, vertexColorData.length * Buffers.SIZEOF_FLOAT,
+ vertexColorDataBuffer, GL.GL_STATIC_DRAW);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+
+ // Buffer with the 3 indices required for one triangle
+ ibo = buffArray[1];
+ assert ibo > 0;
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, ibo);
+ gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,indices.length*Buffers.SIZEOF_SHORT,
+ indicesBuffer, GL.GL_STATIC_DRAW);
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+ private void initShaders(final GL3 gl) {
+ final String[] vertSrc = new String[]{
+ "#version 150\n",
+ "in vec4 vPosition;\n",
+ "in vec4 vColor;\n",
+ "out vec4 pColor;\n",
+ "void main() {\n",
+ " pColor = vColor;\n",
+ " gl_Position = vPosition;\n",
+ "}\n"
+ };
+ vertID = createShader(gl, GL2ES2.GL_VERTEX_SHADER, vertSrc);
+
+ final String[] fragSrc = new String[]{
+ "#version 150\n",
+ "in vec4 pColor;\n",
+ "void main() {\n",
+ " gl_FragColor = pColor;\n",
+ "}\n"
+ };
+ fragID = createShader(gl, GL2ES2.GL_FRAGMENT_SHADER, fragSrc);
+
+ // We're done with the compiler
+ gl.glReleaseShaderCompiler();
+
+ progID = gl.glCreateProgram();
+ assert progID > 0;
+ gl.glAttachShader(progID, vertID);
+ gl.glAttachShader(progID, fragID);
+ gl.glLinkProgram(progID);
+ gl.glValidateProgram(progID);
+ }
+
+ private int initVAO(final GL3 gl) {
+ final int[] buff = new int[1];
+ gl.glGenVertexArrays(1, buff, 0);
+ final int vao = buff[0];
+ Assert.assertTrue("Invalid VAO: "+vao, vao > 0);
+
+
+ gl.glUseProgram(progID);
+ final int posLoc = gl.glGetAttribLocation(progID, "vPosition");
+ final int colorLoc = gl.glGetAttribLocation(progID, "vColor");
+ gl.glUseProgram(0);
+
+ gl.glBindVertexArray(vao);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo);
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, ibo);
+
+ gl.glEnableVertexAttribArray(posLoc);
+ gl.glEnableVertexAttribArray(colorLoc);
+
+ final int stride = 6 * Buffers.SIZEOF_FLOAT;
+ final int cOff = 3 * Buffers.SIZEOF_FLOAT;
+ gl.glVertexAttribPointer(posLoc, 3, GL.GL_FLOAT, false, stride, 0L);
+ gl.glVertexAttribPointer(colorLoc,3, GL.GL_FLOAT, false, stride, cOff);
+
+ gl.glBindVertexArray(0);
+ // See class documentation above!
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
+ return vao;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL3 gl = drawable.getGL().getGL3();
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glDisable(GL.GL_CULL_FACE);
+ initBuffers(gl);
+ initShaders(gl);
+
+ vao = initVAO(gl);
+
+ gl.setSwapInterval(1);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL3 gl = drawable.getGL().getGL3();
+ gl.glDeleteBuffers(2, new int[]{vbo, ibo}, 0);
+ gl.glDetachShader(progID, fragID);
+ gl.glDetachShader(progID, vertID);
+ gl.glDeleteProgram(progID);
+ gl.glDeleteShader(fragID);
+ gl.glDeleteShader(vertID);
+ }
+
+ private void displayCPUSourcing(final GL3bc gl) {
+ final int posLoc = gl.glGetAttribLocation(progID, "vPosition");
+ final int colorLoc = gl.glGetAttribLocation(progID, "vColor");
+ gl.glEnableVertexAttribArray(posLoc);
+ gl.glEnableVertexAttribArray(colorLoc);
+
+ final int stride = 6 * Buffers.SIZEOF_FLOAT;
+ // final int cOff = 3 * Buffers.SIZEOF_FLOAT;
+ gl.glVertexAttribPointer(posLoc, 3, GL.GL_FLOAT, false, stride, vertexColorDataBuffer);
+ vertexColorDataBuffer.position(3); // move to cOff
+ gl.glVertexAttribPointer(colorLoc,3, GL.GL_FLOAT, false, stride, vertexColorDataBuffer);
+ vertexColorDataBuffer.position(0); // rewind cOff
+
+ gl.glDrawElements(GL.GL_TRIANGLES, 3, GL.GL_UNSIGNED_SHORT, indicesBuffer);
+
+ gl.glDisableVertexAttribArray(posLoc);
+ gl.glDisableVertexAttribArray(colorLoc);
+ }
+
+ private void displayVBOOnly(final GL3 gl) {
+ final int posLoc = gl.glGetAttribLocation(progID, "vPosition");
+ final int colorLoc = gl.glGetAttribLocation(progID, "vColor");
+ gl.glEnableVertexAttribArray(posLoc);
+ gl.glEnableVertexAttribArray(colorLoc);
+
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo);
+ final int stride = 6 * Buffers.SIZEOF_FLOAT;
+ final int cOff = 3 * Buffers.SIZEOF_FLOAT;
+ gl.glVertexAttribPointer(posLoc, 3, GL.GL_FLOAT, false, stride, 0L);
+ gl.glVertexAttribPointer(colorLoc,3, GL.GL_FLOAT, false, stride, cOff);
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, ibo);
+ gl.glDrawElements(GL.GL_TRIANGLES, 3, GL.GL_UNSIGNED_SHORT, 0L);
+
+ gl.glDisableVertexAttribArray(posLoc);
+ gl.glDisableVertexAttribArray(colorLoc);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ private void displayVBOVAO(final GL3 gl) {
+ try {
+ gl.glBindVertexArray(vao);
+ gl.glDrawElements(GL.GL_TRIANGLES, 3, GL.GL_UNSIGNED_SHORT, 0L);
+ gl.glBindVertexArray(0);
+ } catch (final GLException ex) {
+ Logger.getLogger(TestBug692GL3VAONEWT.class.getName()).log(Level.SEVERE,null,ex);
+ }
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL3bc gl = drawable.getGL().getGL3bc();
+ final float color = ((float) currentMode.ordinal() + 1) / (Mode.values().length + 2);
+ gl.glClearColor(color, color, color, 0);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl.glUseProgram(progID);
+ final Mode newMode;
+ {
+ currentModeIdx = ( currentModeIdx + 1 ) % allModes.length;
+ newMode = allModes[ currentModeIdx ];
+ }
+ if (newMode != currentMode) {
+ currentMode = newMode;
+ System.out.println("Display mode: " + currentMode);
+ }
+ currentMode.display(this, gl);
+ gl.glUseProgram(0);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int w, final int h) {
+ }
+ }
+
+ private void testImpl(final GLProfile profile, final GL3VAODemo.Mode[] modes) throws InterruptedException {
+ final GLCapabilities capabilities = new GLCapabilities(profile);
+ final GLWindow glWindow = GLWindow.create(capabilities);
+ glWindow.setSize(512, 512);
+
+ final Animator anim = new Animator(glWindow);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ final GL3VAODemo vaoTest = new GL3VAODemo(modes);
+ glWindow.addGLEventListener(vaoTest);
+ glWindow.setVisible(true);
+ anim.start();
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1-t0<duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ anim.stop();
+ glWindow.destroy();
+ }
+
+ @Test
+ public void test01CPUSource() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ final GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.CPU_SRC };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test02VBOOnly() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ final GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.VBO_ONLY };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test03VBOVAO() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ final GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.VBO_VAO };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test12CPUSourceAndVBOOnly() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ final GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.CPU_SRC, GL3VAODemo.Mode.VBO_ONLY };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test13CPUSourceAndVBOVAO() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ final GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.CPU_SRC, GL3VAODemo.Mode.VBO_VAO };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test23VBOOnlyAndVBOVAO() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ final GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.VBO_ONLY, GL3VAODemo.Mode.VBO_VAO };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test88AllModes() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ final GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.CPU_SRC, GL3VAODemo.Mode.VBO_ONLY, GL3VAODemo.Mode.VBO_VAO };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ duration = MiscUtils.atoi(args[++i], (int)duration);
+ }
+ }
+ final String tstname = TestBug692GL3VAONEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestCPUSourcingAPINEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestCPUSourcingAPINEWT.java
new file mode 100644
index 000000000..fe598db35
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestCPUSourcingAPINEWT.java
@@ -0,0 +1,226 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLBuffers;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLOffscreenAutoDrawable;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestCPUSourcingAPINEWT extends UITestCase {
+ static long duration = 500; // ms
+
+ static class Demo implements GLEventListener {
+ private final static float[] vertexColorData = new float[]{
+ 0.0f, 0.75f, 0.0f, 1,0,0,
+ -0.5f, -0.75f, 0.0f, 0,1,0,
+ 0.9f, -0.75f, 0.0f, 0,0,1
+ };
+ private final FloatBuffer vertexColorDataBuffer = GLBuffers.newDirectFloatBuffer(vertexColorData);
+
+ private final short[] indices = new short[]{0, 1, 2};
+ private final ShortBuffer indicesBuffer = GLBuffers.newDirectShortBuffer(indices);
+
+
+ private int vertID = -1;
+ private int fragID = -1;
+ private int progID = -1;
+
+ private static int createShader(final GL2ES2 gl, final int type,
+ final String[] srcLines){
+ final int shaderID = gl.glCreateShader(type);
+ assert shaderID > 0;
+ final int[] lengths = new int[srcLines.length];
+ for (int i = 0; i < srcLines.length; i++) {
+ lengths[i] = srcLines[i].length();
+ }
+ gl.glShaderSource(shaderID, srcLines.length, srcLines, lengths, 0);
+ gl.glCompileShader(shaderID);
+ return shaderID;
+ }
+
+ private void initShaders(final GL2ES2 gl) {
+ final String[] vertSrc = new String[]{
+ "#version 150\n",
+ "in vec4 vPosition;\n",
+ "in vec4 vColor;\n",
+ "out vec4 pColor;\n",
+ "void main() {\n",
+ " pColor = vColor;\n",
+ " gl_Position = vPosition;\n",
+ "}\n"
+ };
+ vertID = createShader(gl, GL2ES2.GL_VERTEX_SHADER, vertSrc);
+
+ final String[] fragSrc = new String[]{
+ "#version 150\n",
+ "in vec4 pColor;\n",
+ "void main() {\n",
+ " gl_FragColor = pColor;\n",
+ "}\n"
+ };
+ fragID = createShader(gl, GL2ES2.GL_FRAGMENT_SHADER, fragSrc);
+
+ // We're done with the compiler
+ gl.glReleaseShaderCompiler();
+
+ progID = gl.glCreateProgram();
+ assert progID > 0;
+ gl.glAttachShader(progID, vertID);
+ gl.glAttachShader(progID, fragID);
+ gl.glLinkProgram(progID);
+ gl.glValidateProgram(progID);
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glDisable(GL.GL_CULL_FACE);
+ initShaders(gl);
+
+ gl.setSwapInterval(1);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.glDetachShader(progID, fragID);
+ gl.glDetachShader(progID, vertID);
+ gl.glDeleteProgram(progID);
+ gl.glDeleteShader(fragID);
+ gl.glDeleteShader(vertID);
+ }
+
+ private void displayCPUSourcing(final GL2 gl) {
+ final int posLoc = gl.glGetAttribLocation(progID, "vPosition");
+ final int colorLoc = gl.glGetAttribLocation(progID, "vColor");
+ gl.glEnableVertexAttribArray(posLoc);
+ gl.glEnableVertexAttribArray(colorLoc);
+
+ final int stride = 6 * Buffers.SIZEOF_FLOAT;
+ // final int cOff = 3 * Buffers.SIZEOF_FLOAT;
+ gl.glVertexAttribPointer(posLoc, 3, GL.GL_FLOAT, false, stride, vertexColorDataBuffer);
+ vertexColorDataBuffer.position(3); // move to cOff
+ gl.glVertexAttribPointer(colorLoc,3, GL.GL_FLOAT, false, stride, vertexColorDataBuffer);
+ vertexColorDataBuffer.position(0); // rewind cOff
+
+ gl.glDrawElements(GL.GL_TRIANGLES, 3, GL.GL_UNSIGNED_SHORT, indicesBuffer);
+
+ gl.glDisableVertexAttribArray(posLoc);
+ gl.glDisableVertexAttribArray(colorLoc);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.glClearColor(0x44, 0x44, 0x44, 0);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl.glUseProgram(progID);
+
+ // Hard casting is of course invalid!
+ // But we need to 'fake' compatibility mode to trigger CPU-sourcing w/ GL3 core
+ displayCPUSourcing((GL2) gl);
+
+ gl.glUseProgram(0);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int w, final int h) {
+ }
+ }
+
+ private void testImpl(final GLProfile profile) throws InterruptedException {
+ final GLCapabilities capabilities = new GLCapabilities(profile);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(profile);
+ final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, capabilities, null, 512, 512);
+
+ final Demo vaoTest = new Demo();
+ glad.addGLEventListener(vaoTest);
+ glad.display();
+
+ glad.destroy();
+ }
+
+ @Test
+ public void test01GL2CPUSource() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL2) ) {
+ System.err.println("GL2 n/a");
+ return;
+ }
+ testImpl(GLProfile.get(GLProfile.GL2));
+ }
+
+ @Test
+ public void test02GL3CPUSource() throws GLException, InterruptedException {
+ final GLProfile glp = GLProfile.getMaxProgrammableCore(true);
+ if( !glp.isGL3ES3() && !glp.isGL2ES2() ) {
+ System.err.println("No GL core profile available, got "+glp);
+ return;
+ }
+ GLException exp = null;
+ try {
+ testImpl(glp);
+ } catch(final GLException gle) {
+ exp = gle;
+ System.err.println("Expected Exception: "+exp.getMessage());
+ }
+ Assert.assertNotNull("Excpected GLException missing due to CPU Sourcing w/ GL3 core context", exp);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestCPUSourcingAPINEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java
index eab1a37e3..929799ecd 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -41,10 +41,13 @@ import jogamp.nativewindow.jawt.JAWTUtil;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.util.RunnableTask;
import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestFBOAutoDrawableDeadlockAWT extends UITestCase {
static GLProfile glp;
static int width, height;
@@ -57,13 +60,9 @@ public class TestFBOAutoDrawableDeadlockAWT extends UITestCase {
height = 512;
}
- protected void runTestGL( GLCapabilities caps ) throws InterruptedException, InvocationTargetException {
- final GLOffscreenAutoDrawable fbod = GLDrawableFactory.getFactory(caps.getGLProfile()).createOffscreenAutoDrawable(
- null,
- caps, new DefaultGLCapabilitiesChooser(),
- 512, 512,
- null
- );
+ protected void runTestGL( final GLCapabilities caps ) throws InterruptedException, InvocationTargetException {
+ final GLOffscreenAutoDrawable fbod = GLDrawableFactory.getFactory(caps.getGLProfile()).createOffscreenAutoDrawable(
+ null, caps, new DefaultGLCapabilitiesChooser(), 512, 512);
final boolean[] done = {false};
final Runnable pbufferCreationAction = new Runnable() {
@@ -74,55 +73,55 @@ public class TestFBOAutoDrawableDeadlockAWT extends UITestCase {
System.err.println("AA.X");
}
};
-
+
EventQueue.invokeAndWait(new Runnable() {
public void run() {
Assert.assertTrue(EventQueue.isDispatchThread());
JAWTUtil.lockToolkit();
try {
- final RunnableTask rTask = new RunnableTask(pbufferCreationAction, new Object(), false);
+ final RunnableTask rTask = new RunnableTask(pbufferCreationAction, new Object(), false, null);
System.err.println("BB.0: "+rTask.getSyncObject());
synchronized (rTask.getSyncObject()) {
System.err.println("BB.1: "+rTask.getSyncObject());
- new Thread(rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start();
+ new Thread(rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start();
try {
System.err.println("BB.2");
rTask.getSyncObject().wait();
System.err.println("BB.3");
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
throw new RuntimeException(e);
- }
+ }
System.err.println("BB.X");
}
} finally {
JAWTUtil.unlockToolkit();
}
- }
+ }
});
Assert.assertTrue(done[0]);
fbod.destroy();
}
- @Test(timeout = 2000) // 2s timeout
+ @Test(timeout = 10000)
public void testDeadlock() throws InterruptedException, InvocationTargetException {
- GLCapabilities caps = new GLCapabilities( glp );
+ final GLCapabilities caps = new GLCapabilities( glp );
runTestGL( caps );
}
static long duration = 500; // ms
- public static void main( String args[] ) {
+ public static void main( final String args[] ) {
for ( int i = 0; i < args.length; i++ ) {
if ( args[ i ].equals( "-time" ) ) {
i++;
try {
duration = Integer.parseInt( args[ i ] );
}
- catch ( Exception ex ) {
+ catch ( final Exception ex ) {
ex.printStackTrace();
}
}
}
org.junit.runner.JUnitCore.main( TestFBOAutoDrawableDeadlockAWT.class.getName() );
}
-}
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java
index 2dc547f39..327fecd25 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,15 +20,13 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.jogl.acore;
-import java.io.IOException;
+package com.jogamp.opengl.test.junit.jogl.acore;
import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilities;
@@ -36,11 +34,14 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLFBODrawable;
import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2;
@@ -50,160 +51,234 @@ import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
/**
- * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the
- * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
+ * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the
+ * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
* <p>
- * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}.
+ * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}.
* </p>
* <p>
* Extensive FBO reconfiguration (size and sample buffer count) and validation are performed.
- * </p>
+ * </p>
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestFBOAutoDrawableFactoryNEWT extends UITestCase {
-
+
static final int widthStep = 800/4;
static final int heightStep = 600/4;
volatile int szStep = 2;
-
+
interface MyGLEventListener extends GLEventListener {
void setMakeSnapshot();
}
-
+
+ @Test
+ public void test01a_GL2ES2_Demo1_SingleBuffer_Normal() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setDoubleBuffered(false);
+ testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0));
+ }
+ @Test
+ public void test01b_GL2ES2_Demo1_SingleBuffer_NoTex() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setDoubleBuffered(false);
+ testGLFBODrawableImpl(caps, 0, new GearsES2(0));
+ }
@Test
- public void testGL2ES2_Demo1_SingleBuffer_Normal() throws InterruptedException {
+ public void test01c_GL2ES2_Demo1_SingleBuffer_NoTexNoDepth() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
caps.setDoubleBuffered(false);
- testGLFBODrawableImpl(caps, new GearsES2(0));
+ caps.setDepthBits(0);
+ testGLFBODrawableImpl(caps, 0, new GearsES2(0));
}
-
+
@Test
- public void testGL2ES2_Demo1_DoubleBuffer_Normal() throws InterruptedException {
+ public void test02a_GL2ES2_Demo1_DoubleBuffer_Normal() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
caps.setDoubleBuffered(true); // default
- testGLFBODrawableImpl(caps, new GearsES2(0));
+ testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0));
+ }
+
+ @Test
+ public void test03a_GL2ES2_Demo2MSAA4_Normal() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(4);
+ testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new MultisampleDemoES2(true));
+ }
+ @Test
+ public void test03b_GL2ES2_Demo2MSAA4_NoTex() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(4);
+ testGLFBODrawableImpl(caps, 0, new MultisampleDemoES2(true));
}
-
@Test
- public void testGL2ES2_Demo2MSAA4() throws InterruptedException {
+ public void test03c_GL2ES2_Demo2MSAA4_NoTexNoDepth() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
- testGLFBODrawableImpl(caps, new MultisampleDemoES2(true));
+ caps.setDepthBits(0);
+ testGLFBODrawableImpl(caps, 0, new MultisampleDemoES2(true));
}
-
+
@Test
- public void testGL2ES2_FBODemoMSAA4() throws InterruptedException {
+ public void test04_GL2ES2_FBODemoMSAA4_Normal() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0);
demo.setDoRotation(false);
final GLCapabilities caps = new GLCapabilities(glp);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
- testGLFBODrawableImpl(caps, demo);
+ testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, demo);
}
-
+
@Test
- public void testEGLES2_Demo0Normal() throws InterruptedException {
+ public void test11_EGLES2_Demo0Normal() throws InterruptedException {
if( GLProfile.isAvailable(GLProfile.GLES2) ) {
final GLProfile glp = GLProfile.get(GLProfile.GLES2);
final GLCapabilities caps = new GLCapabilities(glp);
- testGLFBODrawableImpl(caps, new GearsES2(0));
+ testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0));
} else {
System.err.println("EGL ES2 n/a");
}
}
-
+
@Test
- public void testEGLES2_Demo0MSAA4() throws InterruptedException {
+ public void test13_EGLES2_Demo0MSAA4() throws InterruptedException {
if( GLProfile.isAvailable(GLProfile.GLES2) ) {
final GLProfile glp = GLProfile.get(GLProfile.GLES2);
final GLCapabilities caps = new GLCapabilities(glp);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
- testGLFBODrawableImpl(caps, new GearsES2(0));
+ testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0));
} else {
System.err.println("EGL ES2 n/a");
}
}
- void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException {
+ @Test
+ public void test21_GL3_Demo0Normal() throws InterruptedException {
+ if( GLProfile.isAvailable(GLProfile.GL3) ) {
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0));
+ } else {
+ System.err.println("GL3 n/a");
+ }
+ }
+
+ void testGLFBODrawableImpl(final GLCapabilities caps, final int fboMode, final GLEventListener demo) throws InterruptedException {
caps.setFBO(true);
final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
final GLOffscreenAutoDrawable.FBO glad = (GLOffscreenAutoDrawable.FBO)
- factory.createOffscreenAutoDrawable(null, caps, null, widthStep*szStep, heightStep*szStep, null);
+ factory.createOffscreenAutoDrawable(null, caps, null, widthStep*szStep, heightStep*szStep);
Assert.assertNotNull(glad);
-
+
+ System.out.println("Requested: "+caps);
System.out.println("Realized GLAD: "+glad);
System.out.println("Realized GLAD: "+glad.getChosenGLCapabilities());
Assert.assertTrue("FBO drawable is initialized before ctx creation", !glad.isInitialized());
-
+ glad.setFBOMode(fboMode);
+
glad.display(); // initial display incl. init!
{
final GLContext context = glad.getContext();
Assert.assertNotNull(context);
Assert.assertTrue(context.isCreated());
}
- Assert.assertTrue("FBO drawable is not initialized after ctx creation", glad.isInitialized());
-
+ Assert.assertTrue("FBO drawable is not initialized after ctx creation", glad.isInitialized());
+
+ final boolean expDepth = caps.getDepthBits() > 0;
+ final boolean reqDepth = glad.getRequestedGLCapabilities().getDepthBits() > 0;
+ final boolean hasDepth = glad.getChosenGLCapabilities().getDepthBits() > 0;
+ System.out.println("Depth: exp "+expDepth+", req "+reqDepth+", has "+hasDepth);
+ Assert.assertEquals("Depth: expected not passed to requested", expDepth, reqDepth);
+ Assert.assertEquals("Depth: requested not passed to chosen", reqDepth, hasDepth);
+
//
// FBO incl. MSAA is fully initialized now
//
-
+
final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
System.out.println("Init GLAD: "+glad);
System.out.println("Init GLAD: "+chosenCaps);
-
+
final FBObject fboFront = glad.getFBObject(GL.GL_FRONT);
final FBObject fboBack = glad.getFBObject(GL.GL_BACK);
-
+
System.out.println("Init front FBO: "+fboFront);
System.out.println("Init back FBO: "+fboBack);
-
+
Assert.assertTrue("FBO drawable is not initialized before ctx creation", glad.isInitialized());
Assert.assertTrue("FBO Front is not initialized before ctx creation", fboFront.isInitialized());
Assert.assertTrue("FBO Back is not initialized before ctx creation", fboBack.isInitialized());
-
+
if( chosenCaps.getDoubleBuffered() ) {
- Assert.assertTrue("FBO are equal: "+fboFront+" == "+fboBack, !fboFront.equals(fboBack));
+ Assert.assertNotEquals("FBO are equal: "+fboFront+" == "+fboBack, fboFront, fboBack);
Assert.assertNotSame(fboFront, fboBack);
} else {
- Assert.assertTrue("FBO are not equal: "+fboFront+" != "+fboBack, fboFront.equals(fboBack));
- Assert.assertSame(fboFront, fboBack);
+ Assert.assertEquals("FBO are not equal: "+fboFront+" != "+fboBack, fboFront, fboBack);
+ Assert.assertSame(fboFront, fboBack);
}
-
- final FBObject.TextureAttachment texAttachA, texAttachB;
-
- texAttachA = glad.getTextureBuffer(GL.GL_FRONT);
+
+ final FBObject.Colorbuffer color0, color1;
+
+ color0 = glad.getColorbuffer(GL.GL_FRONT);
if(0==glad.getNumSamples()) {
- texAttachB = glad.getTextureBuffer(GL.GL_BACK);
+ color1 = glad.getColorbuffer(GL.GL_BACK);
} else {
- texAttachB = null;
+ color1 = null;
}
-
+
+ final boolean expTexture = 0 != ( GLFBODrawable.FBOMODE_USE_TEXTURE & glad.getFBOMode() );
+ System.out.println("Texture: exp "+expTexture+", hasFront "+color0.isTextureAttachment());
+ Assert.assertEquals("Texture: Front", expTexture, color0.isTextureAttachment());
+ if(0==glad.getNumSamples()) {
+ Assert.assertEquals("Texture: Back", expTexture, color1.isTextureAttachment());
+ }
+
final FBObject.Colorbuffer colorA, colorB;
final FBObject.RenderAttachment depthA, depthB;
-
+
colorA = fboFront.getColorbuffer(0);
Assert.assertNotNull(colorA);
colorB = fboBack.getColorbuffer(0);
Assert.assertNotNull(colorB);
-
- depthA = fboFront.getDepthAttachment();
- Assert.assertNotNull(depthA);
- depthB = fboBack.getDepthAttachment();
- Assert.assertNotNull(depthB);
+
+ Assert.assertEquals("Texture: Front", expTexture, colorA.isTextureAttachment());
+ if(0==glad.getNumSamples()) {
+ Assert.assertEquals("Texture: Back", expTexture, colorB.isTextureAttachment());
+ } else {
+ Assert.assertEquals("Texture: MSAA Back is Texture", false, colorB.isTextureAttachment());
+ }
+
+ if( hasDepth ) {
+ depthA = fboFront.getDepthAttachment();
+ Assert.assertNotNull(depthA);
+ depthB = fboBack.getDepthAttachment();
+ Assert.assertNotNull(depthB);
+ } else {
+ depthA = null;
+ depthB = null;
+ }
glad.display(); // SWAP_ODD
-
+
if( chosenCaps.getDoubleBuffered() ) {
// double buffer or MSAA
- Assert.assertTrue("Color attachments are equal: "+colorB+" == "+colorA, !colorB.equals(colorA));
+ Assert.assertNotEquals("Color attachments are equal: "+colorB+" == "+colorA, colorA, colorB);
Assert.assertNotSame(colorB, colorA);
- Assert.assertTrue("Depth attachments are equal: "+depthB+" == "+depthA, !depthB.equals(depthA));
- Assert.assertNotSame(depthB, depthA);
+ if( hasDepth ) {
+ Assert.assertNotEquals("Depth attachments are equal: "+depthB+" == "+depthA, depthA, depthB);
+ Assert.assertNotSame(depthB, depthA);
+ }
} else {
// single buffer
Assert.assertEquals(colorA, colorB);
@@ -211,59 +286,59 @@ public class TestFBOAutoDrawableFactoryNEWT extends UITestCase {
Assert.assertEquals(depthA, depthB);
Assert.assertSame(depthA, depthB);
}
-
- Assert.assertEquals(texAttachA, colorA);
- Assert.assertSame(texAttachA, colorA);
+
+ Assert.assertEquals(color0, colorA);
+ Assert.assertSame(color0, colorA);
if(0==glad.getNumSamples()) {
- Assert.assertEquals(texAttachB, colorB);
- Assert.assertSame(texAttachB, colorB);
+ Assert.assertEquals(color1, colorB);
+ Assert.assertSame(color1, colorB);
}
if( chosenCaps.getNumSamples() > 0 ) {
- // MSAA
- FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
- FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
- Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront));
+ // MSAA
+ final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
+ final FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
+ Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront, _fboFront);
Assert.assertSame(fboFront, _fboFront);
- Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack));
+ Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack, _fboBack);
Assert.assertSame(fboBack, _fboBack);
} else if( chosenCaps.getDoubleBuffered() ) {
// real double buffer
- FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
- FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
- Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront));
+ final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
+ final FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
+ Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack, _fboFront);
Assert.assertSame(fboBack, _fboFront);
- Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack));
+ Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront, _fboBack);
Assert.assertSame(fboFront, _fboBack);
} else {
// single buffer
- FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
- FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
- Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront));
+ final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
+ final FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
+ Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront, _fboFront);
Assert.assertSame(fboFront, _fboFront);
- Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront));
+ Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack, _fboFront);
Assert.assertSame(fboBack, _fboFront);
- Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack));
+ Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack, _fboBack);
Assert.assertSame(fboBack, _fboBack);
- Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack));
+ Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront, _fboBack);
Assert.assertSame(fboFront, _fboBack);
}
-
+
glad.addGLEventListener(demo);
-
+
final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
glad.addGLEventListener(snapshotGLEventListener);
-
+
glad.display(); // - SWAP_EVEN
// 1 - szStep = 2
snapshotGLEventListener.setMakeSnapshot();
glad.display(); // - SWAP_ODD
-
+
// 2, 3 (resize + display)
szStep = 1;
- glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_EVEN
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
+ glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); // SWAP_EVEN
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
snapshotGLEventListener.setMakeSnapshot();
glad.display(); // - SWAP_ODD
@@ -280,34 +355,38 @@ public class TestFBOAutoDrawableFactoryNEWT extends UITestCase {
Assert.assertSame(fboFront, _fboFront);
Assert.assertEquals(fboBack, _fboBack);
Assert.assertSame(fboBack, _fboBack);
-
+
FBObject.Colorbuffer _color = _fboFront.getColorbuffer(0);
Assert.assertNotNull(_color);
Assert.assertEquals(colorA, _color);
Assert.assertSame(colorA, _color);
-
+
FBObject.RenderAttachment _depth = _fboFront.getDepthAttachment();
System.err.println("Resize1.oldDepth "+depthA);
System.err.println("Resize1.newDepth "+_depth);
- Assert.assertNotNull(_depth);
-
+ if( hasDepth ) {
+ Assert.assertNotNull(_depth);
+ }
+
Assert.assertEquals(depthA, _depth);
Assert.assertSame(depthA, _depth);
_depth = _fboBack.getDepthAttachment();
- Assert.assertNotNull(_depth);
+ if( hasDepth ) {
+ Assert.assertNotNull(_depth);
+ }
Assert.assertEquals(depthB, _depth);
Assert.assertSame(depthB, _depth);
-
+
_color = _fboFront.getColorbuffer(colorA);
Assert.assertNotNull(_color);
Assert.assertEquals(colorA, _color);
Assert.assertSame(colorA, _color);
}
-
+
// 4, 5 (resize + display)
szStep = 4;
- glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_ODD
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
+ glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); // SWAP_ODD
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
snapshotGLEventListener.setMakeSnapshot();
glad.display(); // - SWAP_EVEN
@@ -327,48 +406,55 @@ public class TestFBOAutoDrawableFactoryNEWT extends UITestCase {
} else {
// single or MSAA
Assert.assertEquals(fboFront, _fboFront);
- Assert.assertEquals(fboBack, _fboBack);
+ Assert.assertEquals(fboBack, _fboBack);
}
-
+
FBObject.Colorbuffer _color = fboBack.getColorbuffer(0);
Assert.assertNotNull(_color);
Assert.assertEquals(colorB, _color);
Assert.assertSame(colorB, _color);
-
+
FBObject.RenderAttachment _depth = fboBack.getDepthAttachment();
- Assert.assertNotNull(_depth); // MSAA back w/ depth
+ if( hasDepth ) {
+ Assert.assertNotNull(_depth); // MSAA back w/ depth
+ }
Assert.assertEquals(depthB, _depth);
Assert.assertSame(depthB, _depth);
-
+
_depth = fboFront.getDepthAttachment();
- Assert.assertNotNull(_depth);
+ if( hasDepth ) {
+ Assert.assertNotNull(_depth);
+ }
Assert.assertEquals(depthA, _depth);
Assert.assertSame(depthA, _depth);
-
+
_color = fboBack.getColorbuffer(colorB);
Assert.assertNotNull(_color);
Assert.assertEquals(colorB, _color);
Assert.assertSame(colorB, _color);
}
-
+
// 6 + 7 (samples + display)
- glad.setNumSamples(glad.getGL(), chosenCaps.getNumSamples() > 0 ? 0 : 4); // triggers repaint
+ final int oldSampleCount = chosenCaps.getNumSamples();
+ final int newSampleCount = oldSampleCount > 0 ? 0 : 4;
+ System.out.println("Resize3.sampleCount: "+oldSampleCount+" -> "+newSampleCount);
+ glad.setNumSamples(glad.getGL(), newSampleCount); // triggers repaint
snapshotGLEventListener.setMakeSnapshot();
glad.display(); // actual screenshot
-
+
// 8, 9 (resize + samples + display)
szStep = 3;
- glad.setSize(widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
+ glad.setSurfaceSize(widthStep*szStep, heightStep*szStep);
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
glad.destroy();
System.out.println("Fin: "+glad);
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws Exception {
org.junit.runner.JUnitCore.main(TestFBOAutoDrawableFactoryNEWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java
index 077baad43..977ecbf03 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java
@@ -50,13 +50,16 @@ import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLDrawable;
-import javax.media.opengl.GLPipelineFactory;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestFBOMRTNEWT01 extends UITestCase {
static long durationPerTest = 10*40*2; // ms
@@ -70,51 +73,55 @@ public class TestFBOMRTNEWT01 extends UITestCase {
System.err.println("Test requires GL2/GL3 profile.");
return;
}
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow(
- new GLCapabilities(GLProfile.getGL2GL3()), width/step, height/step, true);
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(
+ new GLCapabilities(GLProfile.getGL2GL3()), width/step, height/step, true);
final GLDrawable drawable = winctx.context.getGLDrawable();
- GL2GL3 gl = winctx.context.getGL().getGL2GL3();
- gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2GL3();
+ final GL2GL3 gl = winctx.context.getGL().getGL2GL3();
+ // gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2GL3();
System.err.println(winctx.context);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- // test code ..
+ // test code ..
final ShaderState st = new ShaderState();
// st.setVerbose(true);
-
+
final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "fbo-mrt-1", false);
+ "shader/bin", "fbo-mrt-1", true);
final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "fbo-mrt-1", false);
+ "shader/bin", "fbo-mrt-1", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp0 = new ShaderProgram();
sp0.add(gl, vp0, System.err);
- sp0.add(gl, fp0, System.err);
- Assert.assertTrue(0<=sp0.program());
+ sp0.add(gl, fp0, System.err);
+ Assert.assertTrue(0 != sp0.program());
Assert.assertTrue(!sp0.inUse());
Assert.assertTrue(!sp0.linked());
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
st.attachShaderProgram(gl, sp0, false);
-
+
final ShaderCode vp1 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "fbo-mrt-2", false);
+ "shader/bin", "fbo-mrt-2", true);
final ShaderCode fp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "fbo-mrt-2", false);
+ "shader/bin", "fbo-mrt-2", true);
+ vp1.defaultShaderCustomization(gl, true, true);
+ fp1.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp1 = new ShaderProgram();
sp1.add(gl, vp1, System.err);
- sp1.add(gl, fp1, System.err);
- Assert.assertTrue(0<=sp1.program());
+ sp1.add(gl, fp1, System.err);
+ Assert.assertTrue(0 != sp1.program());
Assert.assertTrue(!sp1.inUse());
Assert.assertTrue(!sp1.linked());
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
st.attachShaderProgram(gl, sp1, true);
-
+
final PMVMatrix pmvMatrix = new PMVMatrix();
final GLUniformData pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- st.ownUniform(pmvMatrixUniform);
+ st.ownUniform(pmvMatrixUniform);
st.uniform(gl, pmvMatrixUniform);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
final GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
// st.bindAttribLocation(gl, 0, vertices0);
vertices0.putf(0); vertices0.putf(1); vertices0.putf(0);
@@ -125,7 +132,7 @@ public class TestFBOMRTNEWT01 extends UITestCase {
st.ownAttribute(vertices0, true);
vertices0.enableBuffer(gl, false);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
final GLArrayDataServer colors0 = GLArrayDataServer.createGLSL("gca_Colors", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
// st.bindAttribLocation(gl, 1, colors0);
colors0.putf(1); colors0.putf(0); colors0.putf(1); colors0.putf(1);
@@ -136,20 +143,20 @@ public class TestFBOMRTNEWT01 extends UITestCase {
st.ownAttribute(colors0, true);
colors0.enableBuffer(gl, false);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
final GLUniformData texUnit0 = new GLUniformData("gcs_TexUnit0", 0);
- st.ownUniform(texUnit0);
+ st.ownUniform(texUnit0);
st.uniform(gl, texUnit0);
final GLUniformData texUnit1 = new GLUniformData("gcs_TexUnit1", 1);
- st.ownUniform(texUnit1);
+ st.ownUniform(texUnit1);
st.uniform(gl, texUnit1);
-
+
final GLArrayDataServer texCoords0 = GLArrayDataServer.createGLSL("gca_TexCoords", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
// st.bindAttribLocation(gl, 2, texCoords0);
texCoords0.putf(0f); texCoords0.putf(1f);
texCoords0.putf(1f); texCoords0.putf(1f);
texCoords0.putf(0f); texCoords0.putf(0f);
- texCoords0.putf(1f); texCoords0.putf(0f);
+ texCoords0.putf(1f); texCoords0.putf(0f);
texCoords0.seal(gl, true);
st.ownAttribute(texCoords0, true);
texCoords0.enableBuffer(gl, false);
@@ -157,53 +164,59 @@ public class TestFBOMRTNEWT01 extends UITestCase {
final int texA0Point = 0; // attachment point for texA0
final int texA1Point = 1; // attachment point for texA1
-
+
// FBO w/ 2 texture2D color buffers
final FBObject fbo_mrt = new FBObject();
- fbo_mrt.reset(gl, drawable.getWidth(), drawable.getHeight());
+ fbo_mrt.init(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), 0);
final TextureAttachment texA0 = fbo_mrt.attachTexture2D(gl, texA0Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
- final TextureAttachment texA1 = fbo_mrt.attachTexture2D(gl, texA1Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
- fbo_mrt.attachRenderbuffer(gl, Type.DEPTH, 24);
+ final TextureAttachment texA1;
+ if(fbo_mrt.getMaxColorAttachments() > 1) {
+ texA1 = fbo_mrt.attachTexture2D(gl, texA1Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ } else {
+ texA1 = null;
+ System.err.println("FBO supports only one attachment, no MRT available!");
+ }
+ fbo_mrt.attachRenderbuffer(gl, Type.DEPTH, FBObject.CHOSEN_BITS);
Assert.assertTrue( fbo_mrt.isStatusValid() ) ;
fbo_mrt.unbind(gl);
-
+
// misc GL setup
gl.glClearColor(1, 1, 1, 1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_DEPTH_TEST);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
// reshape
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
pmvMatrix.glOrthof(0f, 1f, 0f, 1f, -10f, 10f);
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
st.uniform(gl, pmvMatrixUniform);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
final int[] two_buffers = new int[] { GL.GL_COLOR_ATTACHMENT0+texA0Point, GL.GL_COLOR_ATTACHMENT0+texA1Point };
final int[] bck_buffers = new int[] { GL2GL3.GL_BACK_LEFT };
-
+
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
int step_i = 0;
- int[] last_snap_size = new int[] { 0, 0 };
-
+ final int[] last_snap_size = new int[] { 0, 0 };
+
for(int i=0; i<durationPerTest; i+=50) {
// pass 1 - MRT: Red -> buffer0, Green -> buffer1
- st.attachShaderProgram(gl, sp0, true);
+ st.attachShaderProgram(gl, sp0, true);
vertices0.enableBuffer(gl, true);
colors0.enableBuffer(gl, true);
-
+
fbo_mrt.bind(gl);
gl.glDrawBuffers(2, two_buffers, 0);
- gl.glViewport(0, 0, fbo_mrt.getWidth(), fbo_mrt.getHeight());
-
+ gl.glViewport(0, 0, fbo_mrt.getWidth(), fbo_mrt.getHeight());
+
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
fbo_mrt.unbind(gl);
vertices0.enableBuffer(gl, false);
colors0.enableBuffer(gl, false);
-
+
// pass 2 - mix buffer0, buffer1 and blue
// rg = buffer0.rg + buffer1.rg, b = Blue - length(rg);
st.attachShaderProgram(gl, sp1, true);
@@ -211,56 +224,58 @@ public class TestFBOMRTNEWT01 extends UITestCase {
colors0.enableBuffer(gl, true);
texCoords0.enableBuffer(gl, true);
gl.glDrawBuffers(1, bck_buffers, 0);
-
- gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
-
- gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue());
+
+ gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue());
fbo_mrt.use(gl, texA0);
- gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue());
- fbo_mrt.use(gl, texA1);
+ if(null != texA1) {
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue());
+ fbo_mrt.use(gl, texA1);
+ }
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
fbo_mrt.unuse(gl);
vertices0.enableBuffer(gl, false);
colors0.enableBuffer(gl, false);
texCoords0.enableBuffer(gl, false);
-
+
{
final NativeSurface ns = gl.getContext().getGLReadDrawable().getNativeSurface();
- if(last_snap_size[0] != ns.getWidth() && last_snap_size[1] != ns.getHeight()) {
+ if(last_snap_size[0] != ns.getSurfaceWidth() && last_snap_size[1] != ns.getSurfaceHeight()) {
gl.glFinish(); // sync .. no swap buffers yet!
snapshot(step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok
- last_snap_size[0] = ns.getWidth();
- last_snap_size[1] = ns.getHeight();
+ last_snap_size[0] = ns.getSurfaceWidth();
+ last_snap_size[1] = ns.getSurfaceHeight();
}
}
-
+
drawable.swapBuffers();
Thread.sleep(50);
- int j = (int) ( (long)i / (durationPerTest/(long)step) ) + 1;
+ final int j = (int) ( i / (durationPerTest/step) ) + 1;
if(j>step_i) {
- int w = width/step * j;
- int h = height/step * j;
+ final int w = width/step * j;
+ final int h = height/step * j;
System.err.println("resize: "+step_i+" -> "+j+" - "+w+"x"+h);
- fbo_mrt.reset(gl, w, h);
+ fbo_mrt.reset(gl, w, h, 0);
winctx.window.setSize(w, h);
step_i = j;
}
}
-
+
NEWTGLContext.destroyWindow(winctx);
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
System.err.println("main - start");
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
}
}
- String tstname = TestFBOMRTNEWT01.class.getName();
+ final String tstname = TestFBOMRTNEWT01.class.getName();
org.junit.runner.JUnitCore.main(tstname);
System.err.println("main - end");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java
index b3c542c63..5eebf9cdd 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.BufferedReader;
@@ -57,29 +57,32 @@ import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
-public class TestFBOMix2DemosES2NEWT extends UITestCase {
- static long duration = 500; // ms
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestFBOMix2DemosES2NEWT extends UITestCase {
+ static long duration = 1000; // ms
static int swapInterval = 1;
static boolean showFPS = false;
static boolean forceES2 = false;
static boolean doRotate = true;
static boolean demo0Only = false;
static int globalNumSamples = 0;
- static boolean mainRun = false;
-
+ static boolean manual = false;
+
@AfterClass
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilitiesImmutable caps, int numSamples) throws InterruptedException {
+ protected void runTestGL(final GLCapabilitiesImmutable caps, final int numSamples) throws InterruptedException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
System.err.println("requested: vsync "+swapInterval+", "+caps);
final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval);
- if(mainRun) {
- glWindow.setSize(512, 512);
+ if(manual) {
+ glWindow.setSize(512, 512);
} else {
glWindow.setSize(128, 128);
}
@@ -92,50 +95,56 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
glWindow.addGLEventListener(new GLEventListener() {
int i=0, c=0;
int origS;
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
origS = demo.getMSAA();
}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
- if(mainRun) return;
-
- final int dw = drawable.getWidth();
- final int dh = drawable.getHeight();
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
+ if(manual) return;
+
+ final int dw = drawable.getSurfaceWidth();
+ final int dh = drawable.getSurfaceHeight();
c++;
-
+
if(dw<800) {
System.err.println("XXX: "+dw+"x"+dh+", c "+c);
if(0 == c%3) {
- snapshot(i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null);
+ snapshot(i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null);
}
if( 3 == c ) {
- new Thread() {
+ demo.setMSAA(4);
+ } else if( 6 == c ) {
+ new Thread() {
@Override
public void run() {
- demo.setMSAA(4);
+ glWindow.setSize(dw+64, dh+64);
} }.start();
- } else if( 6 == c ) {
- new Thread() {
+ } else if( 9 == c ) {
+ demo.setMSAA(8);
+ } else if( 12 == c ) {
+ demo.setMSAA(0);
+ } else if( 15 == c ) {
+ new Thread() {
@Override
public void run() {
- demo.setMSAA(8);
+ glWindow.setSize(dw+128, dh+128);
} }.start();
- } else if(9 == c) {
+ } else if( 18 == c ) {
c=0;
- new Thread() {
+ new Thread() {
@Override
public void run() {
glWindow.setSize(dw+256, dh+256);
demo.setMSAA(origS);
- } }.start();
+ } }.start();
}
}
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
-
- Animator animator = new Animator(glWindow);
- QuitAdapter quitAdapter = new QuitAdapter();
+
+ final Animator animator = new Animator(glWindow);
+ final QuitAdapter quitAdapter = new QuitAdapter();
//glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
//glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
@@ -143,32 +152,35 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
glWindow.addWindowListener(quitAdapter);
glWindow.addWindowListener(new WindowAdapter() {
- public void windowResized(WindowEvent e) {
- System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight());
+ public void windowResized(final WindowEvent e) {
+ System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ public void windowMoved(final WindowEvent e) {
+ System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
}
- public void windowMoved(WindowEvent e) {
- System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight());
- }
});
-
+
glWindow.addKeyListener(new KeyAdapter() {
- public void keyTyped(KeyEvent e) {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
System.err.println("*** "+e);
if(e.getKeyChar()=='f') {
new Thread() {
public void run() {
- System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
glWindow.setFullscreen(!glWindow.isFullscreen());
- System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
} }.start();
} else if(e.getKeyChar()=='d') {
demo.setDemo0Only(!demo.getDemo0Only());
} else {
- int num = e.getKeyChar() - '0';
+ final int num = e.getKeyChar() - '0';
System.err.println("*** "+num);
if(0 <= num && num <= 8) {
System.err.println("MSAA: "+demo.getMSAA()+" -> "+num);
- demo.setMSAA(num);
+ demo.setMSAA(num);
}
}
}
@@ -178,13 +190,13 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
// glWindow.setSkipContextReleaseThread(animator.getThread());
glWindow.setVisible(true);
-
+
System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
- System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets());
-
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+
animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
-
+
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
}
@@ -197,27 +209,35 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
}
@Test
- public void test01_Main() throws InterruptedException {
- if( mainRun ) {
- GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ public void test00_Manual() throws InterruptedException {
+ if( manual ) {
+ final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
caps.setAlphaBits(1);
- runTestGL(caps, globalNumSamples);
+ runTestGL(caps, globalNumSamples);
}
}
-
+
@Test
- public void test01() throws InterruptedException {
- if( mainRun ) return ;
- GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ public void test01_startMSAA0() throws InterruptedException {
+ if( manual ) return ;
+ final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
caps.setAlphaBits(1);
runTestGL(caps, 0);
}
- public static void main(String args[]) throws IOException {
+ @Test
+ public void test02_startMSAA4() throws InterruptedException {
+ if( manual ) return ;
+ final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ caps.setAlphaBits(1);
+ runTestGL(caps, 4);
+ }
+
+ public static void main(final String args[]) throws IOException {
boolean waitForKey = false;
-
- mainRun = true;
-
+
+ manual = false;
+
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
@@ -238,20 +258,21 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
demo0Only = true;
} else if(args[i].equals("-wait")) {
waitForKey = true;
- } else if(args[i].equals("-nomain")) {
- mainRun = false;
+ } else if(args[i].equals("-manual")) {
+ manual = true;
}
}
-
+
System.err.println("swapInterval "+swapInterval);
System.err.println("forceES2 "+forceES2);
+ System.err.println("manual "+manual);
if(waitForKey) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
try {
System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ } catch (final IOException e) { }
}
org.junit.runner.JUnitCore.main(TestFBOMix2DemosES2NEWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java
index 3ecf89bfc..13feb2372 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.BufferedReader;
@@ -44,6 +44,7 @@ import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.texture.TextureIO;
+import com.jogamp.opengl.test.junit.jogl.demos.GLFinishOnDisplay;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.jogl.demos.es2.Mix2TexturesES2;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
@@ -63,12 +64,14 @@ import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/**
- * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the
- * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
+ * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the
+ * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
* <p>
- * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}.
+ * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}.
* </p>
* <p>
* This test simulates shared off-thread GL context / texture usage,
@@ -78,7 +81,7 @@ import org.junit.Test;
* <ul>
* <li>2 {@link GLOffscreenAutoDrawable.FBO} double buffered
* <ul>
- * <li>each with their own {@link GLContext}, which is shares the {@link GLWindow} one (see below)</li>
+ * <li>each with their own {@link GLContext}, which is shares the {@link GLWindow} one (see below)</li>
* <li>both run within one {@link FPSAnimator} @ 30fps</li>
* <li>produce a texture</li>
* <li>notify the onscreen renderer about new textureID (swapping double buffer)</li>
@@ -88,124 +91,129 @@ import org.junit.Test;
* <li>shares it's {@link GLContext} w/ above FBOs</li>
* <li>running within one {@link Animator} at v-sync</li>
* <li>uses the shared FBO textures and blends them onscreen</li>
- * </ul></li>
- * </ul>
- * </p>
+ * </ul></li>
+ * </ul>
+ * </p>
*/
-public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase {
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase {
static long duration = 500; // ms
static int swapInterval = 1;
static boolean showFPS = false;
static boolean forceES2 = false;
static boolean mainRun = false;
-
+
@AfterClass
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException {
+ protected void runTestGL(final GLCapabilitiesImmutable caps) throws InterruptedException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
System.err.println("requested: vsync "+swapInterval+", "+caps);
-
+
final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval);
if(mainRun) {
- glWindow.setSize(512, 512);
+ glWindow.setSize(512, 512);
} else {
glWindow.setSize(256, 256);
}
// eager initialization of context
glWindow.setVisible(true);
- glWindow.display();
+ glWindow.display();
final int fbod1_texUnit = 0;
final int fbod2_texUnit = 1;
-
+
final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
- GLCapabilities fbodCaps = (GLCapabilities) caps.cloneMutable();
+ final GLCapabilities fbodCaps = (GLCapabilities) caps.cloneMutable();
// fbodCaps.setDoubleBuffered(false);
-
+
final Mix2TexturesES2 mixerDemo = new Mix2TexturesES2(1, fbod1_texUnit, fbod2_texUnit);
- // FBOD1
+ // FBOD1
final GLOffscreenAutoDrawable.FBO fbod1 = (GLOffscreenAutoDrawable.FBO)
- factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight(), glWindow.getContext());
+ factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getSurfaceWidth(), glWindow.getSurfaceHeight());
+ fbod1.setSharedAutoDrawable(glWindow);
fbod1.setUpstreamWidget(glWindow); // connect the real GLWindow (mouse/key) to offscreen!
fbod1.setTextureUnit(fbod1_texUnit);
{
- GearsES2 demo0 = new GearsES2(-1);
+ final GearsES2 demo0 = new GearsES2(-1);
fbod1.addGLEventListener(demo0);
+ fbod1.addGLEventListener(new GLFinishOnDisplay());
demo0.setIgnoreFocus(true);
}
fbod1.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() {
@Override
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName());
+ public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
+ mixerDemo.setTexID0(fbod1.getColorbuffer(GL.GL_FRONT).getName());
} });
fbod1.display(); // init
System.err.println("FBOD1 "+fbod1);
Assert.assertTrue(fbod1.isInitialized());
-
+
// FBOD2
final GLOffscreenAutoDrawable.FBO fbod2 = (GLOffscreenAutoDrawable.FBO)
- factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight(), glWindow.getContext());
+ factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getSurfaceWidth(), glWindow.getSurfaceHeight());
+ fbod2.setSharedAutoDrawable(glWindow);
fbod2.setTextureUnit(fbod2_texUnit);
fbod2.addGLEventListener(new RedSquareES2(-1));
+ fbod2.addGLEventListener(new GLFinishOnDisplay());
fbod2.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() {
@Override
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- mixerDemo.setTexID1(fbod2.getTextureBuffer(GL.GL_FRONT).getName());
+ public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
+ mixerDemo.setTexID1(fbod2.getColorbuffer(GL.GL_FRONT).getName());
} });
fbod2.display(); // init
System.err.println("FBOD2 "+fbod2);
Assert.assertTrue(fbod2.isInitialized());
// preinit texIDs
- mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName());
- mixerDemo.setTexID1(fbod2.getTextureBuffer(GL.GL_FRONT).getName());
-
+ mixerDemo.setTexID0(fbod1.getColorbuffer(GL.GL_FRONT).getName());
+ mixerDemo.setTexID1(fbod2.getColorbuffer(GL.GL_FRONT).getName());
+
glWindow.addGLEventListener(mixerDemo);
glWindow.addGLEventListener(new GLEventListener() {
int i=0, c=0;
- public void init(GLAutoDrawable drawable) {}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
if(mainRun) return;
-
- final int dw = drawable.getWidth();
- final int dh = drawable.getHeight();
+
+ final int dw = drawable.getSurfaceWidth();
+ final int dh = drawable.getSurfaceHeight();
c++;
-
+
if(dw<800) {
System.err.println("XXX: "+dw+"x"+dh+", c "+c);
if(8 == c) {
- snapshot(i++, "msaa"+fbod1.getNumSamples(), drawable.getGL(), screenshot, TextureIO.PNG, null);
+ snapshot(i++, "msaa"+fbod1.getNumSamples(), drawable.getGL(), screenshot, TextureIO.PNG, null);
}
if(9 == c) {
c=0;
- new Thread() {
+ new Thread() {
@Override
public void run() {
glWindow.setSize(dw+256, dh+256);
- } }.start();
+ } }.start();
}
}
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- fbod1.setSize(width, height);
- fbod2.setSize(width, height);
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ fbod1.setSurfaceSize(width, height);
+ fbod2.setSurfaceSize(width, height);
}
});
-
+
final FPSAnimator animator0 = new FPSAnimator(30);
animator0.add(fbod1);
animator0.add(fbod2);
-
+
final Animator animator1 = new Animator();
animator1.add(glWindow);
-
- QuitAdapter quitAdapter = new QuitAdapter();
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
//glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
//glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
@@ -213,27 +221,27 @@ public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase {
glWindow.addWindowListener(quitAdapter);
glWindow.addWindowListener(new WindowAdapter() {
- public void windowResized(WindowEvent e) {
- System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight());
+ public void windowResized(final WindowEvent e) {
+ System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ public void windowMoved(final WindowEvent e) {
+ System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
}
- public void windowMoved(WindowEvent e) {
- System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight());
- }
});
-
+
animator0.start();
animator1.start();
// glWindow.setSkipContextReleaseThread(animator.getThread());
glWindow.setVisible(true);
-
+
System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
- System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets());
-
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+
animator0.setUpdateFPSFrames(30, showFPS ? System.err : null);
animator1.setUpdateFPSFrames(60, showFPS ? System.err : null);
-
+
while(!quitAdapter.shouldQuit() && animator1.isAnimating() && animator1.getTotalFPSDuration()<duration) {
Thread.sleep(100);
}
@@ -241,30 +249,30 @@ public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase {
animator0.stop();
Assert.assertFalse(animator0.isAnimating());
Assert.assertFalse(animator0.isStarted());
-
+
animator1.stop();
Assert.assertFalse(animator1.isAnimating());
Assert.assertFalse(animator1.isStarted());
-
+
fbod1.destroy();
fbod2.destroy();
-
+
glWindow.destroy();
Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
}
@Test
public void test01() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
caps.setAlphaBits(1);
- runTestGL(caps);
+ runTestGL(caps);
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
boolean waitForKey = false;
-
+
mainRun = true;
-
+
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
@@ -282,16 +290,16 @@ public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase {
mainRun = false;
}
}
-
+
System.err.println("swapInterval "+swapInterval);
System.err.println("forceES2 "+forceES2);
if(waitForKey) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
try {
System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ } catch (final IOException e) { }
}
org.junit.runner.JUnitCore.main(TestFBOOffThreadSharedContextMix2DemosES2NEWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java
index 7d9a9c662..4ed762a4e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.BufferedReader;
@@ -43,6 +43,7 @@ import com.jogamp.opengl.test.junit.util.QuitAdapter;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.texture.TextureIO;
+import com.jogamp.opengl.test.junit.jogl.demos.GLFinishOnDisplay;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.jogl.demos.es2.Mix2TexturesES2;
@@ -61,12 +62,14 @@ import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/**
- * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the
- * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
+ * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the
+ * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
* <p>
- * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}.
+ * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}.
* </p>
* <p>
* This test simulates shared on-thread GL context / texture usage,
@@ -76,7 +79,7 @@ import org.junit.Test;
* <ul>
* <li>1 {@link GLOffscreenAutoDrawable.FBO} double buffered
* <ul>
- * <liwith its own {@link GLContext}, which is shares the {@link GLWindow} one (see below)</li>
+ * <liwith its own {@link GLContext}, which is shares the {@link GLWindow} one (see below)</li>
* <li>running within common {@link Animator} @ 60fps</li>
* <li>produce a texture</li>
* <li>notify the onscreen renderer about new textureID (swapping double buffer)</li>
@@ -86,108 +89,111 @@ import org.junit.Test;
* <li>shares it's {@link GLContext} w/ above FBO</li>
* <li>running within common {@link Animator} @ 60fps</li>
* <li>uses the shared FBO texture and draws it onscreen</li>
- * </ul></li>
- * </ul>
- * </p>
+ * </ul></li>
+ * </ul>
+ * </p>
*/
-public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase {
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase {
static long duration = 500; // ms
static int swapInterval = 1;
static boolean showFPS = false;
static boolean forceES2 = false;
static boolean mainRun = false;
-
+
@AfterClass
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException {
+ protected void runTestGL(final GLCapabilitiesImmutable caps) throws InterruptedException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
System.err.println("requested: vsync "+swapInterval+", "+caps);
-
+
final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval);
if(mainRun) {
- glWindow.setSize(512, 512);
+ glWindow.setSize(512, 512);
} else {
glWindow.setSize(256, 256);
}
// eager initialization of context
glWindow.setVisible(true);
- glWindow.display();
+ glWindow.display();
final int fbod1_texUnit = 0;
-
+
final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
- GLCapabilities fbodCaps = (GLCapabilities) caps.cloneMutable();
+ final GLCapabilities fbodCaps = (GLCapabilities) caps.cloneMutable();
// fbodCaps.setDoubleBuffered(false);
-
+
final Mix2TexturesES2 mixerDemo = new Mix2TexturesES2(1, fbod1_texUnit, 0);
- // FBOD1
+ // FBOD1
final GLOffscreenAutoDrawable.FBO fbod1 = (GLOffscreenAutoDrawable.FBO)
- factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight(), glWindow.getContext());
+ factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getSurfaceWidth(), glWindow.getSurfaceHeight());
+ fbod1.setSharedAutoDrawable(glWindow);
fbod1.setUpstreamWidget(glWindow); // connect the real GLWindow (mouse/key) to offscreen!
fbod1.setTextureUnit(fbod1_texUnit);
{
- GearsES2 demo0 = new GearsES2(-1);
+ final GearsES2 demo0 = new GearsES2(-1);
fbod1.addGLEventListener(demo0);
+ fbod1.addGLEventListener(new GLFinishOnDisplay());
demo0.setIgnoreFocus(true);
}
fbod1.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() {
@Override
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName());
+ public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
+ mixerDemo.setTexID0(fbod1.getColorbuffer(GL.GL_FRONT).getName());
} });
fbod1.display(); // init
System.err.println("FBOD1 "+fbod1);
Assert.assertTrue(fbod1.isInitialized());
-
+
// preinit texIDs
- mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName());
-
+ mixerDemo.setTexID0(fbod1.getColorbuffer(GL.GL_FRONT).getName());
+
glWindow.addWindowListener(new WindowAdapter() {
@Override
- public void windowResized(WindowEvent e) {
- fbod1.setSize(glWindow.getWidth(), glWindow.getHeight());
+ public void windowResized(final WindowEvent e) {
+ fbod1.setSurfaceSize(glWindow.getSurfaceWidth(), glWindow.getSurfaceHeight());
}
});
glWindow.addGLEventListener(mixerDemo);
glWindow.addGLEventListener(new GLEventListener() {
int i=0, c=0;
- public void init(GLAutoDrawable drawable) {}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
if(mainRun) return;
-
- final int dw = drawable.getWidth();
- final int dh = drawable.getHeight();
+
+ final int dw = drawable.getSurfaceWidth();
+ final int dh = drawable.getSurfaceHeight();
c++;
-
+
if(dw<800) {
System.err.println("XXX: "+dw+"x"+dh+", c "+c);
if(8 == c) {
- snapshot(i++, "msaa"+fbod1.getNumSamples(), drawable.getGL(), screenshot, TextureIO.PNG, null);
+ snapshot(i++, "msaa"+fbod1.getNumSamples(), drawable.getGL(), screenshot, TextureIO.PNG, null);
}
if(9 == c) {
c=0;
- new Thread() {
+ new Thread() {
@Override
public void run() {
glWindow.setSize(dw+256, dh+256);
- } }.start();
+ } }.start();
}
}
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
-
+
final Animator animator1 = new Animator();
animator1.add(fbod1);
animator1.add(glWindow);
-
- QuitAdapter quitAdapter = new QuitAdapter();
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
//glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
//glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
@@ -195,25 +201,25 @@ public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase {
glWindow.addWindowListener(quitAdapter);
glWindow.addWindowListener(new WindowAdapter() {
- public void windowResized(WindowEvent e) {
- System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight());
+ public void windowResized(final WindowEvent e) {
+ System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ public void windowMoved(final WindowEvent e) {
+ System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
}
- public void windowMoved(WindowEvent e) {
- System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight());
- }
});
-
+
animator1.start();
// glWindow.setSkipContextReleaseThread(animator.getThread());
glWindow.setVisible(true);
-
+
System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
- System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets());
-
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+
animator1.setUpdateFPSFrames(60, showFPS ? System.err : null);
-
+
while(!quitAdapter.shouldQuit() && animator1.isAnimating() && animator1.getTotalFPSDuration()<duration) {
Thread.sleep(100);
}
@@ -221,25 +227,25 @@ public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase {
animator1.stop();
Assert.assertFalse(animator1.isAnimating());
Assert.assertFalse(animator1.isStarted());
-
+
fbod1.destroy();
-
+
glWindow.destroy();
Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
}
@Test
public void test01() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
caps.setAlphaBits(1);
- runTestGL(caps);
+ runTestGL(caps);
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
boolean waitForKey = false;
-
+
mainRun = true;
-
+
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
@@ -257,16 +263,16 @@ public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase {
mainRun = false;
}
}
-
+
System.err.println("swapInterval "+swapInterval);
System.err.println("forceES2 "+forceES2);
if(waitForKey) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
try {
System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ } catch (final IOException e) { }
}
org.junit.runner.JUnitCore.main(TestFBOOnThreadSharedContext1DemoES2NEWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java
new file mode 100644
index 000000000..85f9d9e2b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java
@@ -0,0 +1,164 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowUpdateEvent;
+import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+
+/**
+ * Test using a NEWT {@link Window} for onscreen case.
+ * <p>
+ * Creates a {@link GLDrawable} using the
+ * {@link GLDrawableFactory#createGLDrawable(javax.media.nativewindow.NativeSurface) factory model}.
+ * The {@link GLContext} is derived {@link GLDrawable#createContext(GLContext) from the drawable}.
+ * </p>
+ * <p>
+ * Finally a {@link GLAutoDrawableDelegate} is created with the just created {@link GLDrawable} and {@link GLContext}.
+ * It is being used to run the {@link GLEventListener}.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLAutoDrawableDelegateNEWT extends UITestCase {
+ static long duration = 500; // ms
+
+ void doTest(final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile());
+
+ //
+ // Create native windowing resources .. X11/Win/OSX
+ //
+ final Window window = NewtFactory.createWindow(reqGLCaps);
+ Assert.assertNotNull(window);
+ window.setSize(640, 400);
+ window.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
+ System.out.println("Window: "+window.getClass().getName());
+
+ final GLDrawable drawable = factory.createGLDrawable(window);
+ Assert.assertNotNull(drawable);
+ drawable.setRealized(true);
+
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock(); // destroys drawable/context
+ window.destroy(); // destroys the actual window, incl. the device
+ }
+ };
+
+ window.setWindowDestroyNotifyAction( new Runnable() {
+ public void run() {
+ glad.windowDestroyNotifyOp();
+ } } );
+
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowRepaint(final WindowUpdateEvent e) {
+ glad.windowRepaintOp();
+ }
+
+ @Override
+ public void windowResized(final WindowEvent e) {
+ glad.windowResizedOp(window.getSurfaceWidth(), window.getSurfaceHeight());
+ }
+ });
+
+ glad.addGLEventListener(demo);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
+ //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
+ window.addKeyListener(quitAdapter);
+ window.addWindowListener(quitAdapter);
+
+ final Animator animator = new Animator();
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.add(glad);
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+ System.out.println("Fin start ...");
+
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ glad.destroy();
+ System.out.println("Fin Drawable: "+drawable);
+ System.out.println("Fin Window: "+window);
+ }
+
+ @Test
+ public void testOnScreenDblBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = new GLCapabilities( GLProfile.getGL2ES2() );
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLAutoDrawableDelegateNEWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java
index 4628a5a58..94bff728e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
@@ -43,6 +43,8 @@ import jogamp.opengl.GLGraphicsConfigurationUtil;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Window;
@@ -59,39 +61,37 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
/**
* Tests using a NEWT {@link Window} for on- and offscreen cases.
* <p>
- * Each test creates a {@link GLDrawable} using the
+ * Each test creates a {@link GLDrawable} using the
* {@link GLDrawableFactory#createGLDrawable(javax.media.nativewindow.NativeSurface) factory model}.
* The {@link GLContext} is derived {@link GLDrawable#createContext(GLContext) from the drawable}.
* </p>
* <p>
* Finally a {@link GLAutoDrawableDelegate} is created with the just created {@link GLDrawable} and {@link GLContext}.
- * It is being used to run the {@link GLEventListener}.
- * </p>
+ * It is being used to run the {@link GLEventListener}.
+ * </p>
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
static final int widthStep = 800/4;
static final int heightStep = 600/4;
volatile int szStep = 2;
- static GLCapabilities getCaps(String profile) {
+ static GLCapabilities getCaps(final String profile) {
if( !GLProfile.isAvailable(profile) ) {
System.err.println("Profile "+profile+" n/a");
return null;
}
return new GLCapabilities(GLProfile.get(profile));
}
-
- void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException {
+
+ void doTest(final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException {
System.out.println("Requested GL Caps: "+reqGLCaps);
final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile());
-
- final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile());
- final boolean pbufferAvailable = factory.canCreateGLPbuffer(null);
- final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable);
+ final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null);
System.out.println("Expected GL Caps: "+expGLCaps);
//
// Create native windowing resources .. X11/Win/OSX
- //
+ //
final Window window = NewtFactory.createWindow(reqGLCaps);
Assert.assertNotNull(window);
window.setSize(widthStep*szStep, heightStep*szStep);
@@ -99,7 +99,7 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
System.out.println("Window: "+window.getClass().getName());
-
+
// Check caps of NativeWindow config w/o GL
final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities();
System.out.println("Window Caps Pre_GL: "+chosenCaps);
@@ -109,48 +109,61 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
Assert.assertTrue(chosenCaps.getRedBits()>5);
//
- // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
// equivalent to GLAutoDrawable methods: setVisible(true)
- //
+ //
final GLDrawable drawable = factory.createGLDrawable(window);
Assert.assertNotNull(drawable);
System.out.println("Drawable Pre-GL(0): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName());
-
+
//
drawable.setRealized(true);
Assert.assertTrue(drawable.isRealized());
System.out.println("Window Caps PostGL : "+window.getGraphicsConfiguration().getChosenCapabilities());
System.out.println("Drawable Post-GL(1): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName());
-
- // Check caps of GLDrawable after realization
- final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities();
- System.out.println("Chosen GL Caps(1): "+chosenGLCaps);
- Assert.assertNotNull(chosenGLCaps);
- Assert.assertTrue(chosenGLCaps.getGreenBits()>5);
- Assert.assertTrue(chosenGLCaps.getBlueBits()>5);
- Assert.assertTrue(chosenGLCaps.getRedBits()>5);
- Assert.assertTrue(chosenGLCaps.getDepthBits()>4);
- Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen());
- Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO());
- Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer());
- Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap());
- /** Single/Double buffer cannot be checked since result may vary ..
- if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) {
- // dbl buffer may be disabled w/ offscreen pbuffer and bitmap
- Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered());
- } */
- GLContext context = drawable.createContext(null);
+ // Note: FBO Drawable realization happens at 1st context.makeCurrent(),
+ // and hence only then it's caps can _fully_ reflect expectations,
+ // i.e. depth, stencil and MSAA will be valid only after makeCurrent(),
+ // where on-/offscreen state after setRealized(true)
+ // See GLFBODrawable API doc in this regard!
+
+
+ final GLCapabilitiesImmutable chosenGLCaps01 = drawable.getChosenGLCapabilities();
+ System.out.println("Chosen GL Caps(1): "+chosenGLCaps01);
+ Assert.assertNotNull(chosenGLCaps01);
+ Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps01.isOnscreen());
+ Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps01.isFBO());
+ Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps01.isPBuffer());
+ Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps01.isBitmap());
+
+ final GLContext context = drawable.createContext(null);
Assert.assertNotNull(context);
- int res = context.makeCurrent();
+ final int res = context.makeCurrent();
Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
context.release();
-
- System.out.println("Chosen GL Caps(2): "+drawable.getChosenGLCapabilities());
+
+ // Check caps of GLDrawable after realization
+ final GLCapabilitiesImmutable chosenGLCaps02 = drawable.getChosenGLCapabilities();
+ System.out.println("Chosen GL Caps(2): "+chosenGLCaps02);
System.out.println("Chosen GL CTX (2): "+context.getGLVersion());
System.out.println("Drawable Post-GL(2): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName());
-
+ Assert.assertNotNull(chosenGLCaps02);
+ Assert.assertTrue(chosenGLCaps02.getGreenBits()>5);
+ Assert.assertTrue(chosenGLCaps02.getBlueBits()>5);
+ Assert.assertTrue(chosenGLCaps02.getRedBits()>5);
+ Assert.assertTrue(chosenGLCaps02.getDepthBits()>4);
+ Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps02.isOnscreen());
+ Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps02.isFBO());
+ Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps02.isPBuffer());
+ Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps02.isBitmap());
+ /** Single/Double buffer cannot be checked since result may vary ..
+ if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) {
+ // dbl buffer may be disabled w/ offscreen pbuffer and bitmap
+ Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered());
+ } */
+
final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) {
@Override
protected void destroyImplInLock() {
@@ -158,57 +171,64 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
window.destroy(); // destroys the actual window, incl. the device
}
};
-
+
+ window.setWindowDestroyNotifyAction( new Runnable() {
+ public void run() {
+ glad.windowDestroyNotifyOp();
+ } } );
+
window.addWindowListener(new WindowAdapter() {
@Override
- public void windowRepaint(WindowUpdateEvent e) {
+ public void windowRepaint(final WindowUpdateEvent e) {
glad.windowRepaintOp();
}
@Override
- public void windowResized(WindowEvent e) {
- glad.windowResizedOp(window.getWidth(), window.getHeight());
- }
-
- @Override
- public void windowDestroyNotify(WindowEvent e) {
- glad.windowDestroyNotifyOp();
+ public void windowResized(final WindowEvent e) {
+ glad.windowResizedOp(window.getSurfaceWidth(), window.getSurfaceHeight());
}
});
glad.addGLEventListener(demo);
-
+
final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
glad.addGLEventListener(snapshotGLEventListener);
-
+
glad.display(); // initial resize/display
-
+
// 1 - szStep = 2
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ final int[] expSurfaceSize = glad.getNativeSurface().convertToPixelUnits(new int[] { widthStep*szStep, heightStep*szStep });
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
// 2, 3 (resize + display)
szStep = 1;
window.setSize(widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ expSurfaceSize[0] = widthStep*szStep;
+ expSurfaceSize[1] = heightStep*szStep;
+ glad.getNativeSurface().convertToPixelUnits(expSurfaceSize);
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
// 4, 5 (resize + display)
szStep = 4;
window.setSize(widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ expSurfaceSize[0] = widthStep*szStep;
+ expSurfaceSize[1] = heightStep*szStep;
+ glad.getNativeSurface().convertToPixelUnits(expSurfaceSize);
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
Thread.sleep(50);
-
+
glad.destroy();
- System.out.println("Fin Drawable: "+drawable);
+ System.out.println("Fin Drawable: "+drawable);
System.out.println("Fin Window: "+window);
}
@@ -223,22 +243,22 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
}
}
-
+
@Test
- public void testGL2OnScreenDblBuf() throws InterruptedException {
+ public void testGL2OnScreenSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
+ reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testGL2OnScreenSglBuf() throws InterruptedException {
+ public void testGL2OnScreenDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
- reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testGL2OffScreenAutoDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
@@ -248,24 +268,24 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
}
@Test
- public void testGL2OffScreenFBODblBuf() throws InterruptedException {
+ public void testGL2OffScreenFBOSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
+ reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testGL2OffScreenFBOSglBuf() throws InterruptedException {
+ public void testGL2OffScreenFBODblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
- reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testGL2OffScreenPbufferDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
@@ -274,7 +294,7 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setPBuffer(true);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testGL2OffScreenPbufferSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
@@ -284,7 +304,7 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testGL2OffScreenBitmapSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
@@ -294,22 +314,22 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new Gears(1));
}
-
+
@Test
- public void testES2OnScreenDblBuf() throws InterruptedException {
+ public void testES2OnScreenSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
+ reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testES2OnScreenSglBuf() throws InterruptedException {
+ public void testES2OnScreenDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
- reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testES2OffScreenAutoDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
@@ -319,24 +339,24 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
}
@Test
- public void testES2OffScreenFBODblBuf() throws InterruptedException {
+ public void testES2OffScreenFBOSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
+ reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testES2OffScreenFBOSglBuf() throws InterruptedException {
+ public void testES2OffScreenFBODblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
- reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testES2OffScreenPbufferDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
@@ -345,7 +365,7 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setPBuffer(true);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testES2OffScreenPbufferSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
@@ -355,20 +375,20 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
/** Not implemented !
@Test
public void testES2OffScreenBitmapDblBuf() throws InterruptedException {
if(!checkProfile(GLProfile.GLES2)) {
return;
}
- final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
reqGLCaps.setOnscreen(false);
reqGLCaps.setBitmap(true);
doTest(reqGLCaps, new GearsES2(1));
} */
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
org.junit.runner.JUnitCore.main(TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java
index d318446d2..5c90e8021 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
@@ -43,115 +43,115 @@ import jogamp.opengl.GLGraphicsConfigurationUtil;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
/**
- * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the
- * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
+ * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the
+ * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
* <p>
- * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}.
- * </p>
+ * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}.
+ * </p>
*/
-public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLAutoDrawableFactoryES2OffscrnCapsNEWT extends UITestCase {
static final int widthStep = 800/4;
static final int heightStep = 600/4;
volatile int szStep = 2;
- static GLCapabilities getCaps(String profile) {
+ static GLCapabilities getCaps(final String profile) {
if( !GLProfile.isAvailable(profile) ) {
System.err.println("Profile "+profile+" n/a");
return null;
}
return new GLCapabilities(GLProfile.get(profile));
}
-
- void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException {
+
+ void doTest(final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException {
System.out.println("Requested GL Caps: "+reqGLCaps);
final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile());
-
- final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile());
- final boolean pbufferAvailable = factory.canCreateGLPbuffer(null);
- final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable);
+ final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null);
System.out.println("Expected GL Caps: "+expGLCaps);
//
- // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
// equivalent to GLAutoDrawable methods: setVisible(true)
//
- final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep, null);
-
+ final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep);
+
Assert.assertNotNull(glad);
- System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName());
+ System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName());
Assert.assertTrue(glad.isRealized());
-
+
// Check caps of NativeWindow config w/o GL
final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
System.out.println("Drawable Caps Pre_GL : "+chosenCaps);
Assert.assertNotNull(chosenCaps);
- Assert.assertTrue(chosenCaps.getGreenBits()>5);
- Assert.assertTrue(chosenCaps.getBlueBits()>5);
- Assert.assertTrue(chosenCaps.getRedBits()>5);
-
+ Assert.assertTrue(chosenCaps.getGreenBits()>4);
+ Assert.assertTrue(chosenCaps.getBlueBits()>4);
+ Assert.assertTrue(chosenCaps.getRedBits()>4);
+
glad.display(); // force native context creation
// Check caps of GLDrawable after realization
final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities();
- System.out.println("Chosen GL Caps(1): "+chosenGLCaps);
System.out.println("Chosen GL CTX (1): "+glad.getContext().getGLVersion());
+ System.out.println("Chosen GL Caps(1): "+chosenGLCaps);
+ System.out.println("Chosen GL Caps(2): "+glad.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities());
Assert.assertNotNull(chosenGLCaps);
- Assert.assertTrue(chosenGLCaps.getGreenBits()>5);
- Assert.assertTrue(chosenGLCaps.getBlueBits()>5);
- Assert.assertTrue(chosenGLCaps.getRedBits()>5);
+ Assert.assertTrue(chosenGLCaps.getGreenBits()>4);
+ Assert.assertTrue(chosenGLCaps.getBlueBits()>4);
+ Assert.assertTrue(chosenGLCaps.getRedBits()>4);
Assert.assertTrue(chosenGLCaps.getDepthBits()>4);
Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen());
Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO());
Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer());
Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap());
- /** Single/Double buffer cannot be checked since result may vary ..
+ /** Single/Double buffer cannot be checked since result may vary ..
if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) {
// dbl buffer may be disabled w/ offscreen pbuffer and bitmap
Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered());
- } */
+ } */
glad.addGLEventListener(demo);
-
+
final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
glad.addGLEventListener(snapshotGLEventListener);
-
+
glad.display(); // initial resize/display
-
+
// 1 - szStep = 2
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
// 2, 3 (resize + display)
szStep = 1;
- glad.setSize(widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
+ glad.setSurfaceSize(widthStep*szStep, heightStep*szStep);
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
// 4, 5 (resize + display)
szStep = 4;
- glad.setSize(widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
+ glad.setSurfaceSize(widthStep*szStep, heightStep*szStep);
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
Thread.sleep(50);
-
+
glad.destroy();
- System.out.println("Fin Drawable: "+glad);
+ System.out.println("Fin Drawable: "+glad);
}
@Test
@@ -165,144 +165,181 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
}
}
-
+
@Test
- public void testGL2OffScreenAutoDblBuf() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ public void testES2OffScreenAutoDblBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
doTest(reqGLCaps, new GearsES2(1));
}
@Test
- public void testGL2OffScreenFBODblBuf() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ public void testES2OffScreenFBODblBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testGL2OffScreenFBOSglBuf() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ public void testES2OffScreenFBOSglBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testGL2OffScreenFBOStencil() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ public void testES2OffScreenFBODblBufStencil() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
reqGLCaps.setStencilBits(1);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
+ @Test
+ public void testES2OffScreenFBODblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
@Test
- public void testGL2OffScreenFBOStencilMSAA() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ public void testES2OffScreenFBODblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
reqGLCaps.setStencilBits(1);
reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testGL2OffScreenPbufferDblBuf() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ public void testES2OffScreenPbufferDblBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setPBuffer(true);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testGL2OffScreenPbufferSglBuf() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ public void testES2OffScreenPbufferSglBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setPBuffer(true);
reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
+ // Might be reduced to !stencil
@Test
- public void testGL2OffScreenBitmapSglBuf() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ public void testES2OffScreenPbufferDblBufStencil() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
- reqGLCaps.setBitmap(true);
- reqGLCaps.setDoubleBuffered(false);
- doTest(reqGLCaps, new Gears(1));
+ reqGLCaps.setPBuffer(true);
+ reqGLCaps.setStencilBits(1);
+ doTest(reqGLCaps, new GearsES2(1));
}
-
+
+ // Might be reduced to !MSAA
@Test
- public void testES2OffScreenAutoDblBuf() throws InterruptedException {
+ public void testES2OffScreenPbufferDblBufMSAA() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
+ reqGLCaps.setPBuffer(true);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
+ // Might be reduced to !stencil && !MSAA
@Test
- public void testES2OffScreenFBODblBuf() throws InterruptedException {
+ public void testES2OffScreenPbufferDblBufStencilMSAA() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
- reqGLCaps.setFBO(true);
+ reqGLCaps.setPBuffer(true);
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
+ /** NOT Implemented:
+ // Might be reduced to !double-buff
@Test
- public void testES2OffScreenFBOSglBuf() throws InterruptedException {
+ public void testES2OffScreenBitmapDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
- reqGLCaps.setFBO(true);
+ reqGLCaps.setBitmap(true);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testES2OffScreenBitmapSglBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
reqGLCaps.setDoubleBuffered(false);
- doTest(reqGLCaps, new GearsES2(1));
+ doTest(reqGLCaps, new Gears(1));
}
-
+
+ // Might be reduced to !stencil
@Test
- public void testES2OffScreenPbufferDblBuf() throws InterruptedException {
+ public void testES2OffScreenBitmapDblBufStencil() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
- reqGLCaps.setPBuffer(true);
+ reqGLCaps.setBitmap(true);
+ reqGLCaps.setStencilBits(1);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
+ // Might be reduced to !MSAA
@Test
- public void testES2OffScreenPbufferSglBuf() throws InterruptedException {
+ public void testES2OffScreenBitmapDblBufMSAA() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
- reqGLCaps.setPBuffer(true);
- reqGLCaps.setDoubleBuffered(false);
+ reqGLCaps.setBitmap(true);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
-
- /** Not implemented !
+
+ // Might be reduced to !stencil && !MSAA
@Test
- public void testES2OffScreenBitmapDblBuf() throws InterruptedException {
- if(!checkProfile(GLProfile.GLES2)) {
- return;
- }
- final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ public void testES2OffScreenBitmapDblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setBitmap(true);
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
- } */
-
- public static void main(String args[]) throws IOException {
- org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryOffscrnCapsNEWT.class.getName());
+ } */
+
+ public static void main(final String args[]) throws IOException {
+ org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java
new file mode 100644
index 000000000..a5a340b36
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java
@@ -0,0 +1,384 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+
+import javax.media.nativewindow.CapabilitiesImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLOffscreenAutoDrawable;
+import javax.media.opengl.GLProfile;
+
+import jogamp.opengl.GLGraphicsConfigurationUtil;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the
+ * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
+ * <p>
+ * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT extends UITestCase {
+ static final int widthStep = 800/4;
+ static final int heightStep = 600/4;
+ volatile int szStep = 2;
+
+ static GLCapabilities getCaps(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ void doTest(final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException {
+ System.out.println("Requested GL Caps: "+reqGLCaps);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile());
+ final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null);
+ System.out.println("Expected GL Caps: "+expGLCaps);
+
+ //
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // equivalent to GLAutoDrawable methods: setVisible(true)
+ //
+ final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep);
+
+ Assert.assertNotNull(glad);
+ System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName());
+ Assert.assertTrue(glad.isRealized());
+
+ // Check caps of NativeWindow config w/o GL
+ final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
+ System.out.println("Drawable Caps Pre_GL : "+chosenCaps);
+ Assert.assertNotNull(chosenCaps);
+ Assert.assertTrue(chosenCaps.getGreenBits()>4);
+ Assert.assertTrue(chosenCaps.getBlueBits()>4);
+ Assert.assertTrue(chosenCaps.getRedBits()>4);
+
+ glad.display(); // force native context creation
+
+ // Check caps of GLDrawable after realization
+ final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities();
+ System.out.println("Chosen GL CTX (1): "+glad.getContext().getGLVersion());
+ System.out.println("Chosen GL Caps(1): "+chosenGLCaps);
+ System.out.println("Chosen GL Caps(2): "+glad.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities());
+
+ Assert.assertNotNull(chosenGLCaps);
+ Assert.assertTrue(chosenGLCaps.getGreenBits()>4);
+ Assert.assertTrue(chosenGLCaps.getBlueBits()>4);
+ Assert.assertTrue(chosenGLCaps.getRedBits()>4);
+ Assert.assertTrue(chosenGLCaps.getDepthBits()>4);
+ Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen());
+ Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO());
+ Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer());
+ Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap());
+ /** Single/Double buffer cannot be checked since result may vary ..
+ if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) {
+ // dbl buffer may be disabled w/ offscreen pbuffer and bitmap
+ Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered());
+ } */
+
+ glad.addGLEventListener(demo);
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ glad.addGLEventListener(snapshotGLEventListener);
+
+ glad.display(); // initial resize/display
+
+ // 1 - szStep = 2
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ snapshotGLEventListener.setMakeSnapshot();
+ glad.display();
+
+ // 2, 3 (resize + display)
+ szStep = 1;
+ glad.setSurfaceSize(widthStep*szStep, heightStep*szStep);
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ snapshotGLEventListener.setMakeSnapshot();
+ glad.display();
+
+ // 4, 5 (resize + display)
+ szStep = 4;
+ glad.setSurfaceSize(widthStep*szStep, heightStep*szStep);
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ snapshotGLEventListener.setMakeSnapshot();
+ glad.display();
+
+ Thread.sleep(50);
+
+ glad.destroy();
+ System.out.println("Fin Drawable: "+glad);
+ }
+
+ @Test
+ public void testAvailableInfo() {
+ GLDrawableFactory f = GLDrawableFactory.getDesktopFactory();
+ if(null != f) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
+ }
+ f = GLDrawableFactory.getEGLFactory();
+ if(null != f) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
+ }
+ }
+
+ @Test
+ public void testGL2OffScreenAutoDblBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenFBODblBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenFBOSglBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setDoubleBuffered(false);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenFBODblBufStencil() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setStencilBits(1);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenFBODblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenFBODblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenPbufferDblBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setPBuffer(true);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenPbufferSglBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setPBuffer(true);
+ reqGLCaps.setDoubleBuffered(false);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ // Might be reduced to !stencil
+ @Test
+ public void testGL2OffScreenPbufferDblBufStencil() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setPBuffer(true);
+ reqGLCaps.setStencilBits(1);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ // Might be reduced to !MSAA
+ @Test
+ public void testGL2OffScreenPbufferDblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setPBuffer(true);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ // Might be reduced to !stencil && !MSAA
+ @Test
+ public void testGL2OffScreenPbufferDblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setPBuffer(true);
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+
+ // Might be reduced to !double-buff
+ @Test
+ public void testGL2OffScreenBitmapDblBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenBitmapDblBufRGBA8881() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setRedBits(8);
+ reqGLCaps.setGreenBits(8);
+ reqGLCaps.setBlueBits(8);
+ reqGLCaps.setAlphaBits(1);
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenBitmapDblBufRGB555() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setRedBits(5);
+ reqGLCaps.setGreenBits(5);
+ reqGLCaps.setBlueBits(5);
+ reqGLCaps.setAlphaBits(0);
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenBitmapDblBufRGBA5551() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setRedBits(5);
+ reqGLCaps.setGreenBits(5);
+ reqGLCaps.setBlueBits(5);
+ reqGLCaps.setAlphaBits(1);
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ @Test
+ public void testGL2OffScreenBitmapSglBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
+ reqGLCaps.setDoubleBuffered(false);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ // Might be reduced to !stencil
+ @Test
+ public void testGL2OffScreenBitmapDblBufStencil() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
+ reqGLCaps.setStencilBits(1);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ // Might be reduced to !MSAA
+ @Test
+ public void testGL2OffScreenBitmapDblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ // Might be reduced to !stencil && !MSAA
+ @Test
+ public void testGL2OffScreenBitmapDblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ public static void main(final String args[]) throws IOException {
+ org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java
new file mode 100644
index 000000000..51c7c0772
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java
@@ -0,0 +1,185 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+
+import javax.media.nativewindow.CapabilitiesImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLOffscreenAutoDrawable;
+import javax.media.opengl.GLProfile;
+
+import jogamp.opengl.GLGraphicsConfigurationUtil;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the
+ * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
+ * <p>
+ * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLAutoDrawableFactoryGLnBitmapCapsNEWT extends UITestCase {
+ static final int widthStep = 800/4;
+ static final int heightStep = 600/4;
+ volatile int szStep = 2;
+
+ void doTest(final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException {
+ System.out.println("Requested GL Caps: "+reqGLCaps);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile());
+ final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null);
+ System.out.println("Expected GL Caps: "+expGLCaps);
+
+ //
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // equivalent to GLAutoDrawable methods: setVisible(true)
+ //
+ final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep);
+
+ Assert.assertNotNull(glad);
+ System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName());
+ Assert.assertTrue(glad.isRealized());
+
+ // Check caps of NativeWindow config w/o GL
+ final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
+ System.out.println("Drawable Caps Pre_GL : "+chosenCaps);
+ Assert.assertNotNull(chosenCaps);
+ Assert.assertTrue(chosenCaps.getGreenBits()>4);
+ Assert.assertTrue(chosenCaps.getBlueBits()>4);
+ Assert.assertTrue(chosenCaps.getRedBits()>4);
+
+ glad.display(); // force native context creation
+
+ // Check caps of GLDrawable after realization
+ final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities();
+ System.out.println("Chosen GL CTX (1): "+glad.getContext().getGLVersion());
+ System.out.println("Chosen GL Caps(1): "+chosenGLCaps);
+ System.out.println("Chosen GL Caps(2): "+glad.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities());
+
+ Assert.assertNotNull(chosenGLCaps);
+ Assert.assertTrue(chosenGLCaps.getGreenBits()>4);
+ Assert.assertTrue(chosenGLCaps.getBlueBits()>4);
+ Assert.assertTrue(chosenGLCaps.getRedBits()>4);
+ Assert.assertTrue(chosenGLCaps.getDepthBits()>4);
+ Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen());
+ Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO());
+ Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer());
+ Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap());
+ /** Single/Double buffer cannot be checked since result may vary ..
+ if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) {
+ // dbl buffer may be disabled w/ offscreen pbuffer and bitmap
+ Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered());
+ } */
+
+ glad.addGLEventListener(demo);
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ glad.addGLEventListener(snapshotGLEventListener);
+
+ glad.display(); // initial resize/display
+
+ // 1 - szStep = 2
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ snapshotGLEventListener.setMakeSnapshot();
+ glad.display();
+
+ // 2, 3 (resize + display)
+ szStep = 1;
+ glad.setSurfaceSize(widthStep*szStep, heightStep*szStep);
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ snapshotGLEventListener.setMakeSnapshot();
+ glad.display();
+
+ // 4, 5 (resize + display)
+ szStep = 4;
+ glad.setSurfaceSize(widthStep*szStep, heightStep*szStep);
+ Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ snapshotGLEventListener.setMakeSnapshot();
+ glad.display();
+
+ Thread.sleep(50);
+
+ glad.destroy();
+ System.out.println("Fin Drawable: "+glad);
+ }
+
+ @Test
+ public void testAvailableInfo() {
+ GLDrawableFactory f = GLDrawableFactory.getDesktopFactory();
+ if(null != f) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
+ }
+ f = GLDrawableFactory.getEGLFactory();
+ if(null != f) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
+ }
+ }
+
+ // Might be reduced to !double-buff
+ @Test
+ public void testGL2OffScreenBitmapDblBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.getDefault());
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ // Might be reduced to !MSAA
+ @Test
+ public void testGL2OffScreenBitmapDblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.getDefault());
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setBitmap(true);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new Gears(1));
+ }
+
+ public static void main(final String args[]) throws IOException {
+ org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java
index 64a75716b..8f8bb8f3e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.awt.Dimension;
@@ -49,32 +49,32 @@ import jogamp.opengl.GLGraphicsConfigurationUtil;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
-import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
/**
- * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases.
- * <p>
- * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}.
- * </p>
+ * Tests using an AWT {@link GLCanvas} {@link GLAutoDrawable auto drawable} for on- and offscreen cases.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase {
static final int widthStep = 800/4;
static final int heightStep = 600/4;
+ static boolean waitForKey = false;
volatile int szStep = 2;
- static GLCapabilities getCaps(String profile) {
+ static GLCapabilities getCaps(final String profile) {
if( !GLProfile.isAvailable(profile) ) {
System.err.println("Profile "+profile+" n/a");
return null;
}
return new GLCapabilities(GLProfile.get(profile));
}
-
+
static void setGLCanvasSize(final Frame frame, final GLCanvas glc, final int width, final int height) {
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -86,17 +86,17 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase {
frame.pack();
frame.validate();
} } );
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
}
-
+
static interface MyGLEventListener extends GLEventListener {
void setMakeSnapshot();
}
-
- void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException {
+
+ void doTest(final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException {
if(reqGLCaps.isOnscreen() && JAWTUtil.isOffscreenLayerRequired()) {
System.err.println("onscreen layer n/a");
return;
@@ -107,39 +107,36 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase {
}
System.out.println("Requested GL Caps: "+reqGLCaps);
final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile());
-
- final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile());
- final boolean pbufferAvailable = factory.canCreateGLPbuffer(null);
- final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable);
+ final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null);
System.out.println("Expected GL Caps: "+expGLCaps);
//
// Create native windowing resources .. X11/Win/OSX
//
final GLCanvas glad = new GLCanvas(reqGLCaps); // will implicit trigger offscreen layer - if !onscreen && supported
Assert.assertNotNull(glad);
- Dimension glc_sz = new Dimension(widthStep*szStep, heightStep*szStep);
+ final Dimension glc_sz = new Dimension(widthStep*szStep, heightStep*szStep);
glad.setMinimumSize(glc_sz);
glad.setPreferredSize(glc_sz);
glad.setSize(glc_sz);
final Frame frame = new Frame(getSimpleTestName("."));
Assert.assertNotNull(frame);
- frame.add(glad);
-
+ frame.add(glad);
+
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.pack();
frame.setVisible(true);
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
-
+
Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true));
Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true));
System.out.println("Window: "+glad.getClass().getName());
-
+
// Check caps of NativeWindow config w/o GL
final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
System.out.println("Window Caps Pre_GL: "+chosenCaps);
@@ -149,20 +146,20 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase {
Assert.assertTrue(chosenCaps.getRedBits()>5);
glad.display(); // force native context creation
-
+
//
- // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
// equivalent to GLAutoDrawable methods: setVisible(true)
- //
+ //
{
final GLDrawable actualDrawable = glad.getDelegatedDrawable();
Assert.assertNotNull(actualDrawable);
System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName());
}
-
+
System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities());
System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName());
-
+
// Check caps of GLDrawable after realization
final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities();
System.out.println("Chosen GL Caps(1): "+chosenGLCaps);
@@ -175,55 +172,62 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase {
Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO());
Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer());
Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap());
- /** Single/Double buffer cannot be checked since result may vary ..
+ /** Single/Double buffer cannot be checked since result may vary ..
if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) {
// dbl buffer may be disabled w/ offscreen pbuffer and bitmap
Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered());
} */
{
- GLContext context = glad.getContext();
+ final GLContext context = glad.getContext();
System.out.println("Chosen GL CTX (2): "+context.getGLVersion());
Assert.assertNotNull(context);
Assert.assertTrue(context.isCreated());
}
-
+
System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities());
System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName());
-
+
glad.addGLEventListener(demo);
-
+
final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
glad.addGLEventListener(snapshotGLEventListener);
-
+
glad.display(); // initial resize/display
-
+
// 1 - szStep = 2
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ final int[] expSurfaceSize = glad.getNativeSurface().convertToPixelUnits(new int[] { widthStep*szStep, heightStep*szStep });
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
// 2, 3 (resize + display)
szStep = 1;
setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ expSurfaceSize[0] = widthStep*szStep;
+ expSurfaceSize[1] = heightStep*szStep;
+ glad.getNativeSurface().convertToPixelUnits(expSurfaceSize);
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
glad.display();
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
// 4, 5 (resize + display)
szStep = 4;
setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ expSurfaceSize[0] = widthStep*szStep;
+ expSurfaceSize[1] = heightStep*szStep;
+ glad.getNativeSurface().convertToPixelUnits(expSurfaceSize);
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
glad.display();
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
Thread.sleep(50);
-
+
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -231,10 +235,10 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase {
frame.remove(glad);
frame.dispose();
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
System.out.println("Fin: "+glad);
}
@@ -249,79 +253,100 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase {
System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
}
}
-
+
@Test
- public void testGL2OnScreen() throws InterruptedException {
+ public void testGL2OnScreenDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testGL2OffScreenAuto() throws InterruptedException {
+ public void testGL2OnScreenDblBufStencil() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
- reqGLCaps.setOnscreen(false);
+ reqGLCaps.setStencilBits(1);
doTest(reqGLCaps, new GearsES2(1));
}
@Test
- public void testGL2OffScreenFBOMSAA() throws InterruptedException {
+ public void testGL2OnScreenDblBufMSAA() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
- reqGLCaps.setOnscreen(false);
- reqGLCaps.setFBO(true);
reqGLCaps.setSampleBuffers(true);
reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testGL2OffScreenPbuffer() throws InterruptedException {
+ public void testGL2OnScreenDblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testGL2OffScreenAutoDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
- reqGLCaps.setPBuffer(true);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testES2OnScreen() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ public void testGL2OffScreenFBODblBufStencil() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setStencilBits(1);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testES2OffScreenAuto() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ public void testGL2OffScreenFBODblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testES2OffScreenFBOMSAA() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ public void testGL2OffScreenFBODblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
+ reqGLCaps.setStencilBits(1);
reqGLCaps.setSampleBuffers(true);
reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testES2OffScreenPbuffer() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ public void testGL2OffScreenPbuffer() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setPBuffer(true);
doTest(reqGLCaps, new GearsES2(1));
}
-
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java
index 145078629..2e29340a1 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
@@ -44,6 +44,8 @@ import jogamp.opengl.GLGraphicsConfigurationUtil;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.JoglVersion;
@@ -55,9 +57,10 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
/**
* Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases.
* <p>
- * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}.
- * </p>
+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}.
+ * </p>
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
static final int widthStep = 800/4;
static final int heightStep = 600/4;
@@ -66,26 +69,23 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
static interface MyGLEventListener extends GLEventListener {
void setMakeSnapshot();
}
-
- static GLCapabilities getCaps(String profile) {
+
+ static GLCapabilities getCaps(final String profile) {
if( !GLProfile.isAvailable(profile) ) {
System.err.println("Profile "+profile+" n/a");
return null;
}
return new GLCapabilities(GLProfile.get(profile));
}
-
- void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException {
+
+ void doTest(final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException {
System.out.println("Requested GL Caps: "+reqGLCaps);
final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile());
-
- final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile());
- final boolean pbufferAvailable = factory.canCreateGLPbuffer(null);
- final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable);
+ final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null);
System.out.println("Expected GL Caps: "+expGLCaps);
//
// Create native windowing resources .. X11/Win/OSX
- //
+ //
final GLWindow glad = GLWindow.create(reqGLCaps);
Assert.assertNotNull(glad);
glad.setSize(widthStep*szStep, heightStep*szStep);
@@ -93,7 +93,7 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true));
Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true));
System.out.println("Window: "+glad.getClass().getName());
-
+
// Check caps of NativeWindow config w/o GL
final CapabilitiesImmutable chosenCaps = glad.getGraphicsConfiguration().getChosenCapabilities();
System.out.println("Window Caps Pre_GL: "+chosenCaps);
@@ -103,18 +103,18 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
Assert.assertTrue(chosenCaps.getRedBits()>5);
//
- // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
// equivalent to GLAutoDrawable methods: setVisible(true)
- //
+ //
{
final GLDrawable actualDrawable = glad.getDelegatedDrawable();
Assert.assertNotNull(actualDrawable);
System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName());
}
-
+
System.out.println("Window Caps PostGL : "+glad.getGraphicsConfiguration().getChosenCapabilities());
System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName());
-
+
// Check caps of GLDrawable after realization
final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities();
System.out.println("Chosen GL Caps(1): "+chosenGLCaps);
@@ -127,7 +127,7 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO());
Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer());
Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap());
- /** Single/Double buffer cannot be checked since result may vary ..
+ /** Single/Double buffer cannot be checked since result may vary ..
if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) {
// dbl buffer may be disabled w/ offscreen pbuffer and bitmap
Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered());
@@ -135,46 +135,53 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
glad.display();
{
- GLContext context = glad.getContext();
+ final GLContext context = glad.getContext();
System.out.println("Chosen GL CTX (2): "+context.getGLVersion());
Assert.assertNotNull(context);
Assert.assertTrue(context.isCreated());
}
-
+
System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities());
System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName());
-
+
glad.addGLEventListener(demo);
-
+
final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
glad.addGLEventListener(snapshotGLEventListener);
-
+
glad.display(); // initial resize/display
-
+
// 1 - szStep = 2
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ final int[] expSurfaceSize = glad.getNativeSurface().convertToPixelUnits(new int[] { widthStep*szStep, heightStep*szStep });
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
// 2, 3 (resize + display)
szStep = 1;
glad.setSize(widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ expSurfaceSize[0] = widthStep*szStep;
+ expSurfaceSize[1] = heightStep*szStep;
+ glad.getNativeSurface().convertToPixelUnits(expSurfaceSize);
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
// 4, 5 (resize + display)
szStep = 4;
glad.setSize(widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ expSurfaceSize[0] = widthStep*szStep;
+ expSurfaceSize[1] = heightStep*szStep;
+ glad.getNativeSurface().convertToPixelUnits(expSurfaceSize);
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
Thread.sleep(50);
-
+
glad.destroy();
System.out.println("Fin: "+glad);
}
@@ -190,22 +197,49 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
}
}
-
+
+ @Test
+ public void testGL2OnScreenSglBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setDoubleBuffered(false);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
@Test
public void testGL2OnScreenDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testGL2OnScreenSglBuf() throws InterruptedException {
+ public void testGL2OnScreenDblBufStencil() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
- reqGLCaps.setDoubleBuffered(false);
+ reqGLCaps.setStencilBits(1);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testGL2OnScreenDblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
+ @Test
+ public void testGL2OnScreenDblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
@Test
public void testGL2OffScreenAutoDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
@@ -215,6 +249,16 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
}
@Test
+ public void testGL2OffScreenFBOSglBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setDoubleBuffered(false);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
public void testGL2OffScreenFBODblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
@@ -222,17 +266,40 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setFBO(true);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testGL2OffScreenFBOSglBuf() throws InterruptedException {
+ public void testGL2OffScreenFBODblBufStencil() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
- reqGLCaps.setDoubleBuffered(false);
+ reqGLCaps.setStencilBits(1);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testGL2OffScreenFBODblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testGL2OffScreenFBODblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testGL2OffScreenPbufferDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
@@ -241,7 +308,7 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setPBuffer(true);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testGL2OffScreenPbufferSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
@@ -251,7 +318,7 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testGL2OffScreenBitmapSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
@@ -261,22 +328,49 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new Gears(1));
}
-
+
+ @Test
+ public void testES2OnScreenSglBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setDoubleBuffered(false);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
@Test
public void testES2OnScreenDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testES2OnScreenSglBuf() throws InterruptedException {
+ public void testES2OnScreenDblBufStencil() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
- reqGLCaps.setDoubleBuffered(false);
+ reqGLCaps.setStencilBits(1);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testES2OnScreenDblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testES2OnScreenDblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testES2OffScreenAutoDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
@@ -286,6 +380,16 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
}
@Test
+ public void testES2OffScreenFBOSglBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setDoubleBuffered(false);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
public void testES2OffScreenFBODblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
@@ -293,17 +397,40 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setFBO(true);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
- public void testES2OffScreenFBOSglBuf() throws InterruptedException {
+ public void testES2OffScreenFBODblBufStencil() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
reqGLCaps.setOnscreen(false);
reqGLCaps.setFBO(true);
- reqGLCaps.setDoubleBuffered(false);
+ reqGLCaps.setStencilBits(1);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testES2OffScreenFBODblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
+ @Test
+ public void testES2OffScreenFBODblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(reqGLCaps, new GearsES2(1));
+ }
+
@Test
public void testES2OffScreenPbufferDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
@@ -312,7 +439,7 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setPBuffer(true);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testES2OffScreenPbufferSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
@@ -322,20 +449,20 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
reqGLCaps.setDoubleBuffered(false);
doTest(reqGLCaps, new GearsES2(1));
}
-
+
/** Not implemented !
@Test
public void testES2OffScreenBitmapDblBuf() throws InterruptedException {
if(!checkProfile(GLProfile.GLES2)) {
return;
}
- final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
reqGLCaps.setOnscreen(false);
reqGLCaps.setBitmap(true);
doTest(reqGLCaps, new GearsES2(1));
} */
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java
index 47fc99844..b95fa0c8c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.awt.Component;
@@ -33,6 +33,7 @@ import java.awt.Dimension;
import java.awt.Frame;
import java.io.IOException;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -49,6 +50,8 @@ import jogamp.opengl.GLGraphicsConfigurationUtil;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.opengl.GLWindow;
@@ -60,22 +63,23 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
/**
* Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases.
* <p>
- * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}.
- * </p>
+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}.
+ * </p>
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase {
static final int widthStep = 800/4;
static final int heightStep = 600/4;
volatile int szStep = 2;
- static GLCapabilities getCaps(String profile) {
+ static GLCapabilities getCaps(final String profile) {
if( !GLProfile.isAvailable(profile) ) {
System.err.println("Profile "+profile+" n/a");
return null;
}
return new GLCapabilities(GLProfile.get(profile));
}
-
+
static void setComponentSize(final Frame frame, final Component comp, final int width, final int height) {
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -87,17 +91,17 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase
frame.pack();
frame.validate();
} } );
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
}
-
+
static interface MyGLEventListener extends GLEventListener {
void setMakeSnapshot();
}
-
- void doTest(boolean offscreenLayer, GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException {
+
+ void doTest(final boolean offscreenLayer, final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException {
if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) {
System.err.println("onscreen layer n/a");
return;
@@ -108,45 +112,43 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase
}
System.out.println("Requested GL Caps: "+reqGLCaps);
final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile());
-
- final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile());
- final boolean pbufferAvailable = factory.canCreateGLPbuffer(null);
+ final AbstractGraphicsDevice device = factory.getDefaultDevice();
final GLCapabilitiesImmutable expGLCaps = offscreenLayer ?
- GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable) :
- GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable);
+ GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(reqGLCaps, factory, device) :
+ GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, device);
System.out.println("Expected GL Caps: "+expGLCaps);
-
+
final GLWindow glad = GLWindow.create(reqGLCaps);
Assert.assertNotNull(glad);
-
+
final NewtCanvasAWT nca = new NewtCanvasAWT(glad);
Assert.assertNotNull(nca);
- Dimension size0 = new Dimension(widthStep*szStep, heightStep*szStep);
+ final Dimension size0 = new Dimension(widthStep*szStep, heightStep*szStep);
nca.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported
nca.setPreferredSize(size0);
nca.setMinimumSize(size0);
nca.setSize(size0);
-
+
final Frame frame = new Frame(getSimpleTestName("."));
Assert.assertNotNull(frame);
- frame.add(nca);
-
+ frame.add(nca);
+
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.pack();
frame.setVisible(true);
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
-
+
Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true));
Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true));
System.out.println("Window: "+glad.getClass().getName());
-
+
// Check caps of NativeWindow config w/o GL
final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
System.out.println("Window Caps Pre_GL: "+chosenCaps);
@@ -156,20 +158,20 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase
Assert.assertTrue(chosenCaps.getRedBits()>5);
glad.display(); // force native context creation
-
+
//
- // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
// equivalent to GLAutoDrawable methods: setVisible(true)
- //
+ //
{
final GLDrawable actualDrawable = glad.getDelegatedDrawable();
Assert.assertNotNull(actualDrawable);
System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName());
}
-
+
System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities());
System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName());
-
+
// Check caps of GLDrawable after realization
final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities();
System.out.println("Chosen GL Caps(1): "+chosenGLCaps);
@@ -182,55 +184,62 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase
Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO());
Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer());
Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap());
- /** Single/Double buffer cannot be checked since result may vary ..
+ /** Single/Double buffer cannot be checked since result may vary ..
if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) {
// dbl buffer may be disabled w/ offscreen pbuffer and bitmap
Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered());
} */
{
- GLContext context = glad.getContext();
+ final GLContext context = glad.getContext();
System.out.println("Chosen GL CTX (2): "+context.getGLVersion());
Assert.assertNotNull(context);
Assert.assertTrue(context.isCreated());
}
-
+
System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities());
System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName());
-
+
glad.addGLEventListener(demo);
-
+
final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
glad.addGLEventListener(snapshotGLEventListener);
-
+
glad.display(); // initial resize/display
-
+
// 1 - szStep = 2
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ final int[] expSurfaceSize = glad.getNativeSurface().convertToPixelUnits(new int[] { widthStep*szStep, heightStep*szStep });
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
// 2, 3 (resize + display)
szStep = 1;
setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ expSurfaceSize[0] = widthStep*szStep;
+ expSurfaceSize[1] = heightStep*szStep;
+ glad.getNativeSurface().convertToPixelUnits(expSurfaceSize);
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
glad.display();
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
// 4, 5 (resize + display)
szStep = 4;
setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep);
- Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(),
- AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
+ expSurfaceSize[0] = widthStep*szStep;
+ expSurfaceSize[1] = heightStep*szStep;
+ glad.getNativeSurface().convertToPixelUnits(expSurfaceSize);
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glad, expSurfaceSize[0], expSurfaceSize[1]));
glad.display();
snapshotGLEventListener.setMakeSnapshot();
glad.display();
-
+
Thread.sleep(50);
-
+
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -238,10 +247,10 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase
frame.remove(nca);
frame.dispose();
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
glad.destroy();
System.out.println("Fin: "+nca);
System.out.println("Fin: "+glad);
@@ -258,32 +267,81 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase
System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
}
}
-
+
@Test
public void testGL2OnScreenDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
doTest(false, reqGLCaps, new GearsES2(1));
}
-
+
+ @Test
+ public void testGL2OnScreenDblBufStencil() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setStencilBits(1);
+ doTest(false, reqGLCaps, new GearsES2(1));
+ }
+
@Test
- public void testGL2OffScreenLayerAuto() throws InterruptedException {
+ public void testGL2OnScreenDblBufMSAA() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(false, reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testGL2OnScreenDblBufStencilMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setStencilBits(1);
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
+ doTest(false, reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testGL2OffScreenLayerAutoDblBuf() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ doTest(true, reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testGL2OffScreenFBODblBufStencil() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow
+ reqGLCaps.setStencilBits(1);
+ doTest(true, reqGLCaps, new GearsES2(1));
+ }
+
+ @Test
+ public void testGL2OffScreenFBODblBufMSAA() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setFBO(true);
+ reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow
+ reqGLCaps.setSampleBuffers(true);
+ reqGLCaps.setNumSamples(4);
doTest(true, reqGLCaps, new GearsES2(1));
}
@Test
- public void testGL2OffScreenFBOMSAA() throws InterruptedException {
+ public void testGL2OffScreenFBODblBufStencilMSAA() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
reqGLCaps.setFBO(true);
reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow
+ reqGLCaps.setStencilBits(1);
reqGLCaps.setSampleBuffers(true);
reqGLCaps.setNumSamples(4);
doTest(true, reqGLCaps, new GearsES2(1));
}
-
+
@Test
public void testGL2OffScreenPbuffer() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
@@ -292,8 +350,8 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase
reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow
doTest(true, reqGLCaps, new GearsES2(1));
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
org.junit.runner.JUnitCore.main(TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java
index b3516d6b4..b64707350 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,15 +20,16 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.media.nativewindow.NativeSurface;
import javax.media.opengl.GLAutoDrawable;
@@ -37,44 +38,47 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLContextSurfaceLockNEWT extends UITestCase {
static final int demoSize = 64;
-
+
public abstract class MyRunnable implements Runnable {
final Object postSync;
final int id;
boolean done = false;
-
- public MyRunnable(Object postSync, int id) {
+
+ public MyRunnable(final Object postSync, final int id) {
this.postSync = postSync;
this.id = id;
}
-
+
public boolean done() { return done; }
}
-
+
public class RudeAnimator extends MyRunnable {
private final GLAutoDrawable glad;
private final int frameCount;
-
- public RudeAnimator(GLAutoDrawable glad, int frameCount, Object postSync, int id) {
+
+ public RudeAnimator(final GLAutoDrawable glad, final int frameCount, final Object postSync, final int id) {
super(postSync, id);
this.glad = glad;
this.frameCount = frameCount;
}
-
+
public void run() {
System.err.println("Animatr "+id+", count "+frameCount+": PRE: "+Thread.currentThread().getName());
-
+
for(int c=0; c<frameCount; c++) {
glad.display();
}
-
+
System.err.println("Animatr "+id+": DONE/SYNC: "+Thread.currentThread().getName());
synchronized (postSync) {
done = true;
@@ -91,26 +95,26 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
public class RudeResizer extends MyRunnable {
private final GLWindow win;
private final int actionCount;
-
- public RudeResizer(GLWindow win, int actionCount, Object postSync, int id) {
+
+ public RudeResizer(final GLWindow win, final int actionCount, final Object postSync, final int id) {
super(postSync, id);
this.win = win;
this.actionCount = actionCount;
}
-
+
public void run() {
System.err.println("Resizer "+id+", count "+actionCount+": PRE: "+Thread.currentThread().getName());
-
+
for(int c=0; c<actionCount; c++) {
win.runOnEDTIfAvail(true, new Runnable() {
public void run() {
// Normal resize, may trigger immediate display within lock
- win.setSize(win.getWidth()+1, win.getHeight()+1);
+ win.setSize(win.getSurfaceWidth()+1, win.getSurfaceHeight()+1);
// Force display within surface lock.
- // This procedure emulates the sensitive behavior
+ // This procedure emulates the sensitive behavior
// for all platforms directly.
- int res = win.lockSurface();
+ final int res = win.lockSurface();
if(res > NativeSurface.LOCK_SURFACE_NOT_READY) {
try {
win.display();
@@ -120,7 +124,7 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
}
}});
}
-
+
System.err.println("Resizer "+id+": DONE/SYNC: "+Thread.currentThread().getName());
synchronized (postSync) {
done = true;
@@ -129,8 +133,8 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
}
}
}
-
- protected static boolean done(MyRunnable[] tasks) {
+
+ protected static boolean done(final MyRunnable[] tasks) {
for(int i=tasks.length-1; i>=0; i--) {
if(!tasks[i].done()) {
return false;
@@ -138,8 +142,8 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
}
return true;
}
-
- protected static boolean isDead(Thread[] threads) {
+
+ protected static boolean isDead(final Thread[] threads) {
for(int i=threads.length-1; i>=0; i--) {
if(threads[i].isAlive()) {
return false;
@@ -147,52 +151,52 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
}
return true;
}
-
- protected class MyEventCounter implements GLEventListener {
- volatile int reshapeCount = 0;
- volatile int displayCount = 0;
-
+
+ protected static class MyEventCounter implements GLEventListener {
+ AtomicInteger reshapeCount = new AtomicInteger(0);
+ AtomicInteger displayCount = new AtomicInteger(0);
+
@Override
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
}
@Override
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
System.err.println("*** reshapes: "+reshapeCount+", displays "+displayCount);
}
@Override
- public void display(GLAutoDrawable drawable) {
- displayCount++;
+ public void display(final GLAutoDrawable drawable) {
+ displayCount.incrementAndGet();
}
@Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- reshapeCount++;
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ reshapeCount.incrementAndGet();
}
-
+
public void reset() {
- reshapeCount = 0;
- displayCount = 0;
+ reshapeCount.set(0);
+ displayCount.set(0);
}
}
-
- protected void runJOGLTasks(int animThreadCount, int frameCount, int reszThreadCount, int resizeCount) throws InterruptedException {
+
+ protected void runJOGLTasks(final int animThreadCount, final int frameCount, final int reszThreadCount, final int resizeCount) throws InterruptedException {
final GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getDefault()));
final MyEventCounter myEventCounter = new MyEventCounter();
-
+
glWindow.addGLEventListener(new GearsES2(0));
glWindow.addGLEventListener(myEventCounter);
glWindow.setSize(demoSize, demoSize);
glWindow.setVisible(true);
-
+
final String currentThreadName = Thread.currentThread().getName();
final Object sync = new Object();
final MyRunnable[] animTasks = new MyRunnable[animThreadCount];
final MyRunnable[] resizeTasks = new MyRunnable[animThreadCount];
final Thread[] animThreads = new Thread[reszThreadCount];
final Thread[] resizeThreads = new Thread[reszThreadCount];
-
+
System.err.println("animThreadCount "+animThreadCount+", frameCount "+frameCount);
System.err.println("reszThreadCount "+reszThreadCount+", resizeCount "+resizeCount);
System.err.println("tasks "+(animTasks.length+resizeTasks.length)+", threads "+(animThreads.length+resizeThreads.length));
@@ -209,7 +213,7 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
}
myEventCounter.reset();
-
+
int j=0, k=0;
for(int i=0; i<reszThreadCount+animThreadCount; i++) {
if(0==i%2) {
@@ -224,7 +228,7 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
while(!done(resizeTasks) || !done(animTasks)) {
try {
sync.wait();
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
@@ -234,30 +238,30 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase {
Thread.sleep(100);
i++;
}
-
+
glWindow.destroy();
}
-
+
@Test
public void test01_1A1RThreads_100Resizes() throws InterruptedException {
runJOGLTasks(1, 200, 1, 100);
}
-
+
@Test
public void test01_3A3RThreads_50Resizes() throws InterruptedException {
runJOGLTasks(3, 100, 3, 50);
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
// duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
}
- String tstname = TestGLContextSurfaceLockNEWT.class.getName();
+ final String tstname = TestGLContextSurfaceLockNEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java
index 62e74466f..50beb8ab9 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,18 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLContext;
@@ -42,7 +43,8 @@ import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.Test;
-import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.Display;
import com.jogamp.newt.NewtFactory;
@@ -50,57 +52,58 @@ import com.jogamp.newt.Screen;
import com.jogamp.newt.Window;
import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLDebug00NEWT extends UITestCase {
-
+
static String dbgTstMsg0 = "Hello World";
static int dbgTstId0 = 42;
-
- public class WindowContext {
+
+ public static class WindowContext {
public final Window window;
public final GLContext context;
-
- public WindowContext(Window w, GLContext c) {
+
+ public WindowContext(final Window w, final GLContext c) {
window = w;
context = c;
}
- }
-
- WindowContext createWindow(GLProfile glp, boolean debugGL) {
- GLCapabilities caps = new GLCapabilities(glp);
+ }
+
+ WindowContext createWindow(final GLProfile glp, final boolean debugGL) {
+ final GLCapabilities caps = new GLCapabilities(glp);
//
// Create native windowing resources .. X11/Win/OSX
- //
- Display display = NewtFactory.createDisplay(null); // local display
+ //
+ final Display display = NewtFactory.createDisplay(null); // local display
Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
Assert.assertNotNull(screen);
- Window window = NewtFactory.createWindow(screen, caps);
+ final Window window = NewtFactory.createWindow(screen, caps);
Assert.assertNotNull(window);
window.setSize(128, 128);
window.setVisible(true);
- GLDrawableFactory factory = GLDrawableFactory.getFactory(glp);
- GLDrawable drawable = factory.createGLDrawable(window);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp);
+ final GLDrawable drawable = factory.createGLDrawable(window);
Assert.assertNotNull(drawable);
-
+
drawable.setRealized(true);
-
- GLContext context = drawable.createContext(null);
+
+ final GLContext context = drawable.createContext(null);
Assert.assertNotNull(context);
-
+
context.enableGLDebugMessage(debugGL);
-
- int res = context.makeCurrent();
+
+ final int res = context.makeCurrent();
Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
-
+
return new WindowContext(window, context);
}
- void destroyWindow(WindowContext winctx) {
- GLDrawable drawable = winctx.context.getGLDrawable();
-
+ void destroyWindow(final WindowContext winctx) {
+ final GLDrawable drawable = winctx.context.getGLDrawable();
+
Assert.assertNotNull(winctx.context);
winctx.context.destroy();
@@ -111,19 +114,19 @@ public class TestGLDebug00NEWT extends UITestCase {
winctx.window.destroy();
}
-
- void test01GLDebug01EnableDisable(boolean enable) throws InterruptedException {
- GLProfile glp = GLProfile.getDefault();
-
- WindowContext winctx = createWindow(glp, enable);
- String glDebugExt = winctx.context.getGLDebugMessageExtension();
+
+ void test01GLDebug01EnableDisable(final boolean enable) throws InterruptedException {
+ final GLProfile glp = GLProfile.getDefault();
+
+ final WindowContext winctx = createWindow(glp, enable);
+ final String glDebugExt = winctx.context.getGLDebugMessageExtension();
System.err.println("glDebug extension: "+glDebugExt);
System.err.println("glDebug enabled: "+winctx.context.isGLDebugMessageEnabled());
System.err.println("glDebug sync: "+winctx.context.isGLDebugSynchronous());
- System.err.println("context version: "+winctx.context.getGLVersion());
-
+ System.err.println("context version: "+winctx.context.getGLVersion());
+
Assert.assertEquals((null == glDebugExt) ? false : enable, winctx.context.isGLDebugMessageEnabled());
-
+
destroyWindow(winctx);
}
@@ -136,95 +139,95 @@ public class TestGLDebug00NEWT extends UITestCase {
public void test01GLDebugEnabled() throws InterruptedException {
test01GLDebug01EnableDisable(true);
}
-
+
@Test
public void test02GLDebugError() throws InterruptedException {
- GLProfile glp = GLProfile.getDefault();
-
- WindowContext winctx = createWindow(glp, true);
-
- MyGLDebugListener myGLDebugListener = new MyGLDebugListener(
- GL2GL3.GL_DEBUG_SOURCE_API_ARB,
- GL2GL3.GL_DEBUG_TYPE_ERROR_ARB,
- GL2GL3.GL_DEBUG_SEVERITY_HIGH_ARB);
+ final GLProfile glp = GLProfile.getDefault();
+
+ final WindowContext winctx = createWindow(glp, true);
+
+ final MyGLDebugListener myGLDebugListener = new MyGLDebugListener(
+ GL2ES2.GL_DEBUG_SOURCE_API,
+ GL2ES2.GL_DEBUG_TYPE_ERROR,
+ GL2ES2.GL_DEBUG_SEVERITY_HIGH);
winctx.context.addGLDebugListener(myGLDebugListener);
-
- GL gl = winctx.context.getGL();
-
+
+ final GL gl = winctx.context.getGL();
+
gl.glBindFramebuffer(-1, -1); // ERROR !
-
+
if( winctx.context.isGLDebugMessageEnabled() ) {
Assert.assertEquals(true, myGLDebugListener.received());
- }
-
+ }
+
destroyWindow(winctx);
}
-
+
@Test
public void test03GLDebugInsert() throws InterruptedException {
- GLProfile glp = GLProfile.getDefault();
- WindowContext winctx = createWindow(glp, true);
- MyGLDebugListener myGLDebugListener = new MyGLDebugListener(dbgTstMsg0, dbgTstId0);
+ final GLProfile glp = GLProfile.getDefault();
+ final WindowContext winctx = createWindow(glp, true);
+ final MyGLDebugListener myGLDebugListener = new MyGLDebugListener(dbgTstMsg0, dbgTstId0);
winctx.context.addGLDebugListener(myGLDebugListener);
-
- String glDebugExt = winctx.context.getGLDebugMessageExtension();
+
+ final String glDebugExt = winctx.context.getGLDebugMessageExtension();
Assert.assertEquals((null == glDebugExt) ? false : true, winctx.context.isGLDebugMessageEnabled());
-
+
if( winctx.context.isGLDebugMessageEnabled() ) {
- winctx.context.glDebugMessageInsert(GL2GL3.GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL2GL3.GL_DEBUG_TYPE_OTHER_ARB,
- dbgTstId0,
- GL2GL3.GL_DEBUG_SEVERITY_MEDIUM_ARB, dbgTstMsg0);
+ winctx.context.glDebugMessageInsert(GL2ES2.GL_DEBUG_SOURCE_APPLICATION,
+ GL2ES2.GL_DEBUG_TYPE_OTHER,
+ dbgTstId0,
+ GL2ES2.GL_DEBUG_SEVERITY_MEDIUM, dbgTstMsg0);
Assert.assertEquals(true, myGLDebugListener.received());
- }
-
+ }
+
destroyWindow(winctx);
}
-
- public static void main(String args[]) throws IOException {
- String tstname = TestGLDebug00NEWT.class.getName();
+
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestGLDebug00NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
-
- public class MyGLDebugListener implements GLDebugListener {
+
+ public static class MyGLDebugListener implements GLDebugListener {
int recSource;
int recType;
int recSeverity;
-
+
String recMsg;
int recId;
boolean received = false;
-
- public MyGLDebugListener(int recSource, int recType, int recSeverity) {
+
+ public MyGLDebugListener(final int recSource, final int recType, final int recSeverity) {
this.recSource = recSource;
this.recType = recType;
this.recSeverity = recSeverity;
this.recMsg = null;
this.recId = -1;
-
+
}
- public MyGLDebugListener(String recMsg, int recId) {
+ public MyGLDebugListener(final String recMsg, final int recId) {
this.recSource = -1;
this.recType = -1;
this.recSeverity = -1;
this.recMsg = recMsg;
this.recId = recId;
}
-
+
public boolean received() { return received; }
-
- public void messageSent(GLDebugMessage event) {
- System.err.println("XXX: "+event);
+
+ public void messageSent(final GLDebugMessage event) {
+ System.err.println("XXX: "+event);
if(null != recMsg && recMsg.equals(event.getDbgMsg()) && recId == event.getDbgId()) {
received = true;
- } else if(0 <= recSource && recSource == event.getDbgSource() &&
+ } else if(0 <= recSource && recSource == event.getDbgSource() &&
recType == event.getDbgType() &&
recSeverity== event.getDbgSeverity() ) {
- received = true;
+ received = true;
}
// Thread.dumpStack();
- }
+ }
}
}
-
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java
index f9b566c25..742804092 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,16 +20,17 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
+import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -41,21 +42,24 @@ import javax.media.opengl.GLRunnable;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLDebug01NEWT extends UITestCase {
-
+
static String dbgTstMsg0 = "Hello World";
static int dbgTstId0 = 42;
-
- GLWindow createWindow(GLProfile glp, boolean debugGL) {
- GLCapabilities caps = new GLCapabilities(glp);
+
+ GLWindow createWindow(final GLProfile glp, final boolean debugGL) {
+ final GLCapabilities caps = new GLCapabilities(glp);
//
// Create native windowing resources .. X11/Win/OSX
- //
- GLWindow window = GLWindow.create(caps);
+ //
+ final GLWindow window = GLWindow.create(caps);
Assert.assertNotNull(window);
window.setContextCreationFlags(debugGL?GLContext.CTX_OPTION_DEBUG:0);
window.setSize(128, 128);
@@ -63,44 +67,44 @@ public class TestGLDebug01NEWT extends UITestCase {
Assert.assertNotNull(window.getContext());
Assert.assertNotNull(window.getContext().isCreated());
-
+
return window;
}
- void destroyWindow(GLWindow window) {
+ void destroyWindow(final GLWindow window) {
window.destroy();
}
-
- void test01GLDebug01EnableDisable(boolean enable, final String dbgTstMsg, final int dbgTstId) throws InterruptedException {
- GLProfile glp = GLProfile.getDefault();
-
+
+ void test01GLDebug01EnableDisable(final boolean enable, final String dbgTstMsg, final int dbgTstId) throws InterruptedException {
+ final GLProfile glp = GLProfile.getDefault();
+
final GLWindow window = createWindow(glp, enable);
final GLContext ctx = window.getContext();
- MyGLDebugListener myGLDebugListener = new MyGLDebugListener(dbgTstMsg, dbgTstId);
+ final MyGLDebugListener myGLDebugListener = new MyGLDebugListener(dbgTstMsg, dbgTstId);
if(enable) {
ctx.addGLDebugListener(myGLDebugListener);
- }
- String glDebugExt = ctx.getGLDebugMessageExtension();
+ }
+ final String glDebugExt = ctx.getGLDebugMessageExtension();
System.err.println("glDebug extension: "+glDebugExt);
System.err.println("glDebug enabled: "+ctx.isGLDebugMessageEnabled());
System.err.println("glDebug sync: "+ ctx.isGLDebugSynchronous());
System.err.println("context version: "+ctx.getGLVersion());
-
+
Assert.assertEquals((null == glDebugExt) ? false : enable, ctx.isGLDebugMessageEnabled());
if(ctx.isGLDebugMessageEnabled() && null != dbgTstMsg && 0 <= dbgTstId) {
window.invoke(true, new GLRunnable() {
- public boolean run(GLAutoDrawable drawable) {
- drawable.getContext().glDebugMessageInsert(GL2GL3.GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL2GL3.GL_DEBUG_TYPE_OTHER_ARB,
- dbgTstId,
- GL2GL3.GL_DEBUG_SEVERITY_MEDIUM_ARB, dbgTstMsg);
+ public boolean run(final GLAutoDrawable drawable) {
+ drawable.getContext().glDebugMessageInsert(GL2ES2.GL_DEBUG_SOURCE_APPLICATION,
+ GL2ES2.GL_DEBUG_TYPE_OTHER,
+ dbgTstId,
+ GL2ES2.GL_DEBUG_SEVERITY_MEDIUM, dbgTstMsg);
return true;
}
});
Assert.assertEquals(true, myGLDebugListener.received());
- }
-
+ }
+
destroyWindow(window);
}
@@ -113,77 +117,77 @@ public class TestGLDebug01NEWT extends UITestCase {
public void test01GLDebug01Enabled() throws InterruptedException {
test01GLDebug01EnableDisable(true, dbgTstMsg0, dbgTstId0);
}
-
+
@Test
public void test02GLDebug01Error() throws InterruptedException {
- GLProfile glp = GLProfile.getDefault();
-
- GLWindow window = createWindow(glp, true);
-
- MyGLDebugListener myGLDebugListener = new MyGLDebugListener(
- GL2GL3.GL_DEBUG_SOURCE_API_ARB,
- GL2GL3.GL_DEBUG_TYPE_ERROR_ARB,
- GL2GL3.GL_DEBUG_SEVERITY_HIGH_ARB);
+ final GLProfile glp = GLProfile.getDefault();
+
+ final GLWindow window = createWindow(glp, true);
+
+ final MyGLDebugListener myGLDebugListener = new MyGLDebugListener(
+ GL2ES2.GL_DEBUG_SOURCE_API,
+ GL2ES2.GL_DEBUG_TYPE_ERROR,
+ GL2ES2.GL_DEBUG_SEVERITY_HIGH);
window.getContext().addGLDebugListener(myGLDebugListener);
-
+
window.invoke(true, new GLRunnable() {
- public boolean run(GLAutoDrawable drawable) {
+ public boolean run(final GLAutoDrawable drawable) {
drawable.getGL().glBindFramebuffer(-1, -1); // ERROR !
return true;
}
} );
-
+
if( window.getContext().isGLDebugMessageEnabled() ) {
Assert.assertEquals(true, myGLDebugListener.received());
- }
-
+ }
+
destroyWindow(window);
}
-
-
- public static void main(String args[]) throws IOException {
- String tstname = TestGLDebug01NEWT.class.getName();
+
+
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestGLDebug01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
-
- public class MyGLDebugListener implements GLDebugListener {
+
+ public static class MyGLDebugListener implements GLDebugListener {
int recSource;
int recType;
int recSeverity;
-
+
String recMsg;
int recId;
boolean received = false;
-
- public MyGLDebugListener(int recSource, int recType, int recSeverity) {
+
+ public MyGLDebugListener(final int recSource, final int recType, final int recSeverity) {
this.recSource = recSource;
this.recType = recType;
this.recSeverity = recSeverity;
this.recMsg = null;
this.recId = -1;
-
+
}
- public MyGLDebugListener(String recMsg, int recId) {
+ public MyGLDebugListener(final String recMsg, final int recId) {
this.recSource = -1;
this.recType = -1;
this.recSeverity = -1;
this.recMsg = recMsg;
this.recId = recId;
}
-
+
public boolean received() { return received; }
-
- public void messageSent(GLDebugMessage event) {
- System.err.println("XXX: "+event);
+
+ public void messageSent(final GLDebugMessage event) {
+ System.err.println("XXX: "+event);
if(null != recMsg && recMsg.equals(event.getDbgMsg()) && recId == event.getDbgId()) {
received = true;
- } else if(0 <= recSource && recSource == event.getDbgSource() &&
+ } else if(0 <= recSource && recSource == event.getDbgSource() &&
recType == event.getDbgType() &&
recSeverity== event.getDbgSeverity() ) {
- received = true;
+ received = true;
}
// Thread.dumpStack();
- }
+ }
}
}
-
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLException01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLException01NEWT.java
new file mode 100644
index 000000000..cdbe3af94
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLException01NEWT.java
@@ -0,0 +1,412 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLException01NEWT extends UITestCase {
+ static GLProfile glp;
+ static int width, height;
+
+ @SuppressWarnings("serial")
+ static class AnimException extends RuntimeException {
+ final Thread thread;
+ final GLAnimatorControl animator;
+ final GLAutoDrawable drawable;
+ public AnimException(final Thread thread, final GLAnimatorControl animator, final GLAutoDrawable drawable, final Throwable cause) {
+ super(cause);
+ this.thread = thread;
+ this.animator = animator;
+ this.drawable = drawable;
+ }
+ }
+
+ @BeforeClass
+ public static void initClass() {
+ glp = GLProfile.getGL2ES2();
+ Assert.assertNotNull(glp);
+ width = 512;
+ height = 512;
+ }
+
+ public static void dumpThrowable(final Throwable t) {
+ System.err.println("User caught exception "+t.getClass().getSimpleName()+": "+t.getMessage()+" on thread "+Thread.currentThread().getName());
+ t.printStackTrace();
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final boolean onThread,
+ final boolean throwInInit, final boolean throwInDisplay,
+ final boolean throwInReshape, final boolean throwInInvoke,
+ final boolean throwInDispose) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setTitle(getTestMethodName());
+ final GearsES2 demo1 = new GearsES2();
+ demo1.setVerbose(false);
+ glWindow.addGLEventListener(demo1);
+ final AtomicInteger cleanInitCount = new AtomicInteger();
+ final AtomicInteger cleanDisposeCount = new AtomicInteger();
+ final AtomicInteger cleanDisplayCount = new AtomicInteger();
+ final AtomicInteger cleanReshapeCount = new AtomicInteger();
+ final AtomicInteger cleanInvokeCount = new AtomicInteger();
+ final AtomicInteger allInitCount = new AtomicInteger();
+ final AtomicInteger allDisposeCount = new AtomicInteger();
+ final AtomicInteger allDisplayCount = new AtomicInteger();
+ final AtomicInteger allReshapeCount = new AtomicInteger();
+ final AtomicInteger allInvokeCount = new AtomicInteger();
+ final AtomicInteger exceptionSent = new AtomicInteger();
+
+ glWindow.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ if( throwInInit ) {
+ exceptionSent.incrementAndGet();
+ throw new RuntimeException("<Injected GLEventListener exception in init: #"+exceptionSent.get()+" on thread "+Thread.currentThread().getName()+">");
+ }
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( throwInDispose ) {
+ exceptionSent.incrementAndGet();
+ throw new RuntimeException("<Injected GLEventListener exception in dispose: #"+exceptionSent.get()+" on thread "+Thread.currentThread().getName()+">");
+ }
+ }
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ if( throwInDisplay ) {
+ exceptionSent.incrementAndGet();
+ throw new RuntimeException("<Injected GLEventListener exception in display: #"+exceptionSent.get()+" on thread "+Thread.currentThread().getName()+">");
+ }
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ if( throwInReshape ) {
+ exceptionSent.incrementAndGet();
+ throw new RuntimeException("<Injected GLEventListener exception in reshape: #"+exceptionSent.get()+" on thread "+Thread.currentThread().getName()+">");
+ }
+ }
+ });
+ final GLRunnable glRunnableInject = new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ if( throwInInvoke ) {
+ exceptionSent.incrementAndGet();
+ throw new RuntimeException("<Injected GLEventListener exception in invoke: #"+exceptionSent.get()+" on thread "+Thread.currentThread().getName()+">");
+ }
+ return true;
+ }
+ };
+ final GLRunnable glRunnableCount = new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ if( 0 == exceptionSent.get() ) {
+ cleanInvokeCount.incrementAndGet();
+ }
+ allInvokeCount.incrementAndGet();
+ return true;
+ }
+ };
+
+ glWindow.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ if( 0 == exceptionSent.get() ) {
+ cleanInitCount.incrementAndGet();
+ }
+ allInitCount.incrementAndGet();
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( 0 == exceptionSent.get() ) {
+ cleanDisposeCount.incrementAndGet();
+ }
+ allDisposeCount.incrementAndGet();
+ }
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ if( 0 == exceptionSent.get() ) {
+ cleanDisplayCount.incrementAndGet();
+ }
+ allDisplayCount.incrementAndGet();
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ if( 0 == exceptionSent.get() ) {
+ cleanReshapeCount.incrementAndGet();
+ }
+ allReshapeCount.incrementAndGet();
+ }
+ });
+
+ RuntimeException exceptionAtInitReshapeDisplay = null;
+ RuntimeException exceptionAtInvoke = null;
+ RuntimeException exceptionAtDispose = null;
+ final List<AnimException> exceptionsAtGLAnimatorControl = new ArrayList<AnimException>();
+ final GLAnimatorControl.UncaughtExceptionHandler uncaughtExceptionHandler;
+
+ final Animator animator;
+ if( onThread ) {
+ animator = null;
+ uncaughtExceptionHandler = null;
+ } else {
+ animator = new Animator(glWindow);
+ uncaughtExceptionHandler = new GLAnimatorControl.UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(final GLAnimatorControl animator, final GLAutoDrawable drawable, final Throwable cause) {
+ final AnimException ae = new AnimException(animator.getThread(), animator, drawable, cause);
+ exceptionsAtGLAnimatorControl.add(ae);
+ dumpThrowable(ae);
+ } };
+ animator.setUncaughtExceptionHandler(uncaughtExceptionHandler);
+ }
+
+ glWindow.setSize(width, height);
+
+ if( !onThread ) {
+ animator.setUpdateFPSFrames(1, null);
+ animator.start();
+ }
+ try {
+ glWindow.setVisible(true);
+ } catch (final RuntimeException re) {
+ exceptionAtInitReshapeDisplay = re;
+ dumpThrowable(re);
+ }
+
+ try {
+ glWindow.invoke(true, glRunnableInject);
+ glWindow.invoke(true, glRunnableCount);
+ } catch (final RuntimeException re) {
+ exceptionAtInvoke = re;
+ dumpThrowable(re);
+ }
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(0 == exceptionSent.get() && ( onThread || animator.isAnimating() ) && t1-t0<duration ) {
+ if( onThread ) {
+ try {
+ glWindow.display();
+ } catch (final RuntimeException re) {
+ exceptionAtInitReshapeDisplay = re;
+ dumpThrowable(re);
+ }
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ if( !onThread ) {
+ animator.stop();
+ }
+ try {
+ glWindow.destroy();
+ } catch (final RuntimeException re) {
+ exceptionAtDispose = re;
+ dumpThrowable(re);
+ }
+
+ final boolean onAnimThread = !onThread && !throwInDispose; /** dispose happens on [AWT|NEWT] EDT, not on animator thread! */
+
+ System.err.println("This-Thread : "+onThread);
+ System.err.println("Anim-Thread : "+onAnimThread);
+ System.err.println("ExceptionSent : "+exceptionSent.get());
+ System.err.println("Exception @ Init/Reshape/Display: "+(null != exceptionAtInitReshapeDisplay));
+ System.err.println("Exception @ Invoke : "+(null != exceptionAtInvoke));
+ System.err.println("Exception @ Dispose : "+(null != exceptionAtDispose));
+ System.err.println("Exception @ GLAnimatorControl : "+exceptionsAtGLAnimatorControl.size());
+ System.err.println("Init Count : "+cleanInitCount.get()+" / "+allInitCount.get());
+ System.err.println("Reshape Count : "+cleanReshapeCount.get()+" / "+allReshapeCount.get());
+ System.err.println("Display Count : "+cleanDisplayCount.get()+" / "+allDisplayCount.get());
+ System.err.println("Invoke Count : "+cleanInvokeCount.get()+" / "+allInvokeCount.get());
+ System.err.println("Dispose Count : "+cleanDisposeCount.get()+" / "+allDisposeCount.get());
+
+ if( throwInInit || throwInReshape || throwInDisplay || throwInDispose || throwInInvoke ) {
+ Assert.assertTrue("Not one exception sent, but "+exceptionSent.get(), 0 < exceptionSent.get());
+ if( onAnimThread ) {
+ Assert.assertEquals("No exception forwarded from init to animator-handler", 1, exceptionsAtGLAnimatorControl.size());
+ Assert.assertNull("Exception forwarded from init, on-thread", exceptionAtInitReshapeDisplay);
+ }
+ if( throwInInit ) {
+ if( !onAnimThread ) {
+ Assert.assertNotNull("No exception forwarded from init, on-thread", exceptionAtInitReshapeDisplay);
+ Assert.assertEquals("Exception forwarded from init to animator-handler", 0, exceptionsAtGLAnimatorControl.size());
+ }
+ Assert.assertEquals("Init Count", 0, cleanInitCount.get());
+ Assert.assertEquals("Reshape Count", 0, cleanReshapeCount.get());
+ Assert.assertEquals("Display Count", 0, cleanDisplayCount.get());
+ Assert.assertEquals("Invoke Count", 0, cleanInvokeCount.get());
+ Assert.assertEquals("Dispose Count", 0, cleanDisposeCount.get());
+ } else if( throwInReshape ) {
+ if( !onAnimThread ) {
+ Assert.assertNotNull("No exception forwarded from reshape, on-thread", exceptionAtInitReshapeDisplay);
+ Assert.assertEquals("Exception forwarded from init to animator-handler", 0, exceptionsAtGLAnimatorControl.size());
+ }
+ Assert.assertEquals("Init Count", 1, cleanInitCount.get());
+ Assert.assertEquals("Reshape Count", 0, cleanReshapeCount.get());
+ Assert.assertEquals("Display Count", 0, cleanDisplayCount.get());
+ Assert.assertEquals("Invoke Count", 0, cleanInvokeCount.get());
+ Assert.assertEquals("Dispose Count", 0, cleanDisposeCount.get());
+ } else if( throwInDisplay ) {
+ if( !onAnimThread ) {
+ Assert.assertNotNull("No exception forwarded from display, on-thread", exceptionAtInitReshapeDisplay);
+ Assert.assertEquals("Exception forwarded from init to animator-handler", 0, exceptionsAtGLAnimatorControl.size());
+ }
+ Assert.assertEquals("Init Count", 1, cleanInitCount.get());
+ Assert.assertEquals("Reshape Count", 1, cleanReshapeCount.get());
+ Assert.assertEquals("Display Count", 0, cleanDisplayCount.get());
+ Assert.assertEquals("Invoke Count", 0, cleanInvokeCount.get());
+ Assert.assertEquals("Dispose Count", 0, cleanDisposeCount.get());
+ } else if( throwInInvoke ) {
+ if( !onAnimThread ) {
+ Assert.assertNotNull("No exception forwarded from invoke, on-thread", exceptionAtInvoke);
+ Assert.assertEquals("Exception forwarded from init to animator-handler", 0, exceptionsAtGLAnimatorControl.size());
+ }
+ Assert.assertEquals("Init Count", 1, cleanInitCount.get());
+ Assert.assertEquals("Reshape Count", 1, cleanReshapeCount.get());
+ Assert.assertTrue ("Display count not greater-equal 1, but "+cleanDisplayCount.get(), 1 <= cleanDisplayCount.get());
+ Assert.assertEquals("Invoke Count", 0, cleanInvokeCount.get());
+ Assert.assertEquals("Dispose Count", 0, cleanDisposeCount.get());
+ } else if( throwInDispose ) {
+ if( !onAnimThread ) {
+ Assert.assertNotNull("No exception forwarded from dispose, on-thread", exceptionAtDispose);
+ Assert.assertEquals("Exception forwarded from init to animator-handler", 0, exceptionsAtGLAnimatorControl.size());
+ }
+ Assert.assertEquals("Init Count", 1, cleanInitCount.get());
+ Assert.assertEquals("Reshape Count", 1, cleanReshapeCount.get());
+ Assert.assertTrue ("Display count not greater-equal 1, but "+cleanDisplayCount.get(), 1 <= cleanDisplayCount.get());
+ Assert.assertEquals("Invoke Count", 1, cleanInvokeCount.get());
+ Assert.assertEquals("Dispose Count", 0, cleanDisposeCount.get());
+ }
+ }
+ }
+
+ @Test
+ public void test01OnThreadAtInit() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, true /* onThread */, true /* init */, false /* display */, false /* reshape */, false /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test02OnThreadAtReshape() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, true /* onThread */, false /* init */, false /* display */, true /* reshape */, false /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test03OnThreadAtDisplay() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, true /* onThread */, false /* init */, true /* display */, false /* reshape */, false /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test04OnThreadAtInvoke() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, true /* onThread */, false /* init */, true /* display */, false /* reshape */, true /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test05OnThreadAtDispose() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, true /* onThread */, false /* init */, false /* display */, false /* reshape */, false /* invoke */, true /* dispose */);
+ }
+
+ @Test
+ public void test11OffThreadAtInit() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, false /* onThread */, true /* init */, false /* display */, false /* reshape */, false /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test12OffThreadAtReshape() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, false /* onThread */, false /* init */, false /* display */, true /* reshape */, false /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test13OffThreadAtDisplay() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, false /* onThread */, false /* init */, true /* display */, false /* reshape */, false /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test14OffThreadAtInvoke() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, false /* onThread */, false /* init */, true /* display */, false /* reshape */, true /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test15OffThreadAtDispose() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, false /* onThread */, false /* init */, false /* display */, false /* reshape */, false /* invoke */, true /* dispose */);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ boolean waitForKey = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ if( waitForKey ) {
+ UITestCase.waitForKey("main");
+ }
+ org.junit.runner.JUnitCore.main(TestGLException01NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java
index d4f3fece5..b3a0de845 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.util.Collections;
@@ -39,45 +39,24 @@ import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.media.opengl.GLProfile;
-import jogamp.opengl.GLDrawableFactoryImpl;
-
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLExtensionQueryOffscreen {
-
- public static void main(String[] args) {
- TestGLExtensionQueryOffscreen instance = new TestGLExtensionQueryOffscreen();
- instance.testJogl2ExtensionCheck1();
- instance.testJogl2ExtensionCheck2();
- }
- /**
- * @deprecated This test uses a non public API in jogamp.opengl.* and hence is not recommended
- */
- @Test
- public void testJogl2ExtensionCheck1() {
- GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory();
- GLContext sharedContext = factory.getOrCreateSharedContext(null);
- sharedContext.makeCurrent();
- String extensions;
- try {
- extensions = sharedContext.getGL().glGetString(GL.GL_EXTENSIONS);
- } finally {
- sharedContext.release();
- }
- String[] tabExtensions = extensions.split(" ");
- SortedSet<String> setExtensions = new TreeSet<String>();
- Collections.addAll(setExtensions, tabExtensions);
- System.out.println("SharedContext: "+sharedContext);
- System.out.println("SharedContext: "+setExtensions);
+ public static void main(final String[] args) {
+ final TestGLExtensionQueryOffscreen instance = new TestGLExtensionQueryOffscreen();
+ instance.testJogl2ExtensionCheck();
}
-
+
@Test
- public void testJogl2ExtensionCheck2() {
+ public void testJogl2ExtensionCheck() {
final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
- final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
- final GLOffscreenAutoDrawable drawable = factory.createOffscreenAutoDrawable(null, caps, null, 256, 256, null);
-
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLOffscreenAutoDrawable drawable = factory.createOffscreenAutoDrawable(null, caps, null, 256, 256);
+ drawable.display(); // trigger context creation ..
final GLContext context = drawable.getContext();
context.makeCurrent();
String extensions;
@@ -86,8 +65,8 @@ public class TestGLExtensionQueryOffscreen {
} finally {
context.release();
}
- String[] tabExtensions = extensions.split(" ");
- SortedSet<String> setExtensions = new TreeSet<String>();
+ final String[] tabExtensions = extensions.split(" ");
+ final SortedSet<String> setExtensions = new TreeSet<String>();
Collections.addAll(setExtensions, tabExtensions);
System.out.println("DefaultContext: "+context);
System.out.println("DefaultContext: "+setExtensions);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java
new file mode 100644
index 000000000..5ef025460
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java
@@ -0,0 +1,226 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Some GL state values are broken w/ Mesa 9.0 w/ multiple different context.
+ * <p>
+ * This bug lies within Mesa3D (any renderer) and is fixed in
+ * commit 8dc79ae7d73cf6711c2182ff9a5d37ef6c989d23.
+ * </p>
+ * <p>
+ * Mesa3D Version 9.0 still exposes this bug,
+ * where 9.0.1 has it fixed w/ above commit.
+ * </p>
+ * <https://jogamp.org/bugzilla/show_bug.cgi?id=651>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLMesaBug651NEWT extends UITestCase {
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 512;
+ height = 512;
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ static class UnitTester implements GLEventListener {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println("GL UnitTester");
+ System.err.println(" GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println(" GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println(" GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println(" GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber());
+ System.err.println(" GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
+ System.err.println(" GL Profile: "+gl.getGLProfile());
+ System.err.println(" GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
+ System.err.println(" GL:" + gl + ", " + gl.getContext().getGLVersion());
+
+ final int _glerr = gl.glGetError(); // clear pre-error
+ System.err.println(" - pre GL-Error 0x"+Integer.toHexString(_glerr));
+
+ final int[] val = new int[1];
+ final int[] glerr = new int[] { GL.GL_NO_ERROR, GL.GL_NO_ERROR, GL.GL_NO_ERROR, GL.GL_NO_ERROR, GL.GL_NO_ERROR };
+ int i=0;
+
+ val[0]=0;
+ gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
+ System.out.println(" - GL_MAX_TEXTURE_SIZE: " + val[0]);
+ glerr[i] = gl.glGetError(); // clear pre-error
+ System.err.println(" - GL-Error 0x"+Integer.toHexString(glerr[i]));
+ i++;
+
+ val[0]=0;
+ gl.glGetIntegerv(GL.GL_ACTIVE_TEXTURE, val, 0);
+ System.out.println(" - GL_ACTIVE_TEXTURE: " + val[0]);
+ glerr[i] = gl.glGetError(); // clear pre-error
+ System.err.println(" - GL-Error 0x"+Integer.toHexString(glerr[i]));
+ i++;
+
+ if(gl.isGL2ES2()) {
+ val[0]=0;
+ gl.glGetIntegerv(GL2ES2.GL_MAX_TEXTURE_IMAGE_UNITS, val, 0);
+ System.out.println(" - GL_MAX_TEXTURE_IMAGE_UNITS: " + val[0]);
+ glerr[i] = gl.glGetError(); // clear pre-error
+ System.err.println(" - GL-Error 0x"+Integer.toHexString(glerr[i]));
+ }
+ i++;
+
+ if( gl.hasFullFBOSupport() || gl.isExtensionAvailable(GLExtensions.NV_fbo_color_attachments) ) {
+ val[0]=0;
+ gl.glGetIntegerv(GL2ES2.GL_MAX_COLOR_ATTACHMENTS, val, 0);
+ System.out.println(" - GL_MAX_COLOR_ATTACHMENTS: " + val[0]);
+ glerr[i] = gl.glGetError(); // clear pre-error
+ System.err.println(" - GL-Error 0x"+Integer.toHexString(glerr[i]));
+ }
+ i++;
+
+ if( gl.hasFullFBOSupport() ) {
+ val[0]=0;
+ gl.glGetIntegerv(GL2ES3.GL_MAX_SAMPLES, val, 0);
+ System.out.println(" - GL_MAX_SAMPLES: " + val[0]);
+ glerr[i] = gl.glGetError(); // clear pre-error
+ System.err.println(" - GL-Error 0x"+Integer.toHexString(glerr[i]));
+ }
+ i++;
+
+ boolean ok = true;
+ String res="";
+ for(int j=0; j<i; j++) {
+ switch(j) {
+ case 0: res += "GL_MAX_TEXTURE_SIZE"; break;
+ case 1: res += "GL_ACTIVE_TEXTURE"; break;
+ case 2: res += "GL_MAX_TEXTURE_IMAGE_UNITS"; break;
+ case 3: res += "GL_MAX_COLOR_ATTACHMENTS"; break;
+ case 4: res += "GL_MAX_SAMPLES"; break;
+ }
+ if(GL.GL_NO_ERROR == glerr[j]) {
+ res += " OK, ";
+ } else {
+ res += " ERROR, ";
+ ok = false;
+ }
+ }
+ Assert.assertTrue(res, ok);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ }
+ }
+
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setTitle(getSimpleTestName("."));
+
+ final UnitTester demo = new UnitTester();
+
+ glWindow.addGLEventListener(demo);
+
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+ glWindow.display();
+
+ glWindow.destroy();
+ }
+
+ @Test
+ public void test01_ES1() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GLES1)) { System.err.println("GLES1 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES1));
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test02__ES2() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GLES2)) { System.err.println("GLES2 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test03_GL2() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL2)) { System.err.println("GL2 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2));
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test04_GL3() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL3)) { System.err.println("GL3 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL3));
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test05_GL4() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL4)) { System.err.println("GL4 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL4));
+ runTestGL(caps);
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestGLMesaBug651NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java
new file mode 100644
index 000000000..a91eae04c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java
@@ -0,0 +1,203 @@
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * The 3.1 compatibility context on Mesa >= 9.0 seems to be broken.
+ * <p>
+ * This bug lies within Mesa3D (any renderer) and is fixed in
+ * commit ??? (not yet).
+ * </p>
+ * <p>
+ * Mesa3D Version 9.0 still exposes this bug,
+ * where 9.?.? has it fixed w/ above commit.
+ * </p>
+ * <https://jogamp.org/bugzilla/show_bug.cgi?id=658>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLMesaBug658NEWT extends UITestCase {
+
+ @Test
+ public void test00ShowAvailProfiles() {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, false).toString());
+ }
+
+ @Test
+ public void test10GL2PolygonModeFailure() {
+ testGLNPolygonModeFailureImpl(GLProfile.GL2);
+ }
+
+ @Test
+ public void test11GL3bcPolygonModeFailure() {
+ testGLNPolygonModeFailureImpl(GLProfile.GL3bc);
+ }
+
+ @Test
+ public void test12GL3PolygonModeFailure() {
+ testGLNPolygonModeFailureImpl(GLProfile.GL3);
+ }
+
+ private void testGLNPolygonModeFailureImpl(final String profile) {
+ if(!GLProfile.isAvailable(profile)) { System.err.println(profile+" n/a"); return; }
+
+ final GLProfile pro = GLProfile.get(profile);
+ final GLCapabilities caps = new GLCapabilities(pro);
+ final GLWindow window = GLWindow.create(caps);
+
+ window.setSize(640, 480);
+ window.addGLEventListener(new GLEventListener() {
+ public void reshape(
+ final GLAutoDrawable drawable,
+ final int x,
+ final int y,
+ final int width,
+ final int height)
+ {
+ // Nothing.
+ }
+
+ public void init(
+ final GLAutoDrawable drawable)
+ {
+ final GLContext context = drawable.getContext();
+ System.err.println("CTX: "+context.getGLVersion());
+
+ final GL2GL3 gl = drawable.getGL().getGL2GL3();
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
+
+ if( gl.isGL2() || gl.isGLES2() ) { // compatibility profile || ES2
+ gl.glPolygonMode(GL.GL_FRONT, GL2GL3.GL_FILL);
+ } else {
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
+ }
+
+ final int e = gl.glGetError();
+ Assert.assertTrue(e == GL.GL_NO_ERROR); // // FIXME On Mesa 9.0.1 w/ GL 3.1 -> GL.GL_INVALID_OPERATION ?
+ }
+
+ public void dispose(
+ final GLAutoDrawable drawable)
+ {
+ // Nothing.
+ }
+
+ public void display(
+ final GLAutoDrawable drawable)
+ {
+ // Nothing.
+ }
+ });
+
+ try {
+ window.setVisible(true);
+ } finally {
+ window.destroy();
+ }
+ }
+
+ @Test
+ public void test20GL2BindArrayAttributeFails() {
+ testGLNBindArrayAttributeFailsImpl(GLProfile.GL2);
+ }
+
+ @Test
+ public void test21GL3bcBindArrayAttributeFails() {
+ testGLNBindArrayAttributeFailsImpl(GLProfile.GL3bc);
+ }
+
+ @Test
+ public void test22GL3BindArrayAttributeFails() {
+ testGLNBindArrayAttributeFailsImpl(GLProfile.GL3);
+ }
+
+ private void testGLNBindArrayAttributeFailsImpl(final String profile) {
+ if(!GLProfile.isAvailable(profile)) { System.err.println(profile+ " n/a"); return; }
+
+ final GLProfile pro = GLProfile.get(profile);
+ final GLCapabilities caps = new GLCapabilities(pro);
+ final GLWindow window = GLWindow.create(caps);
+
+ window.setSize(640, 480);
+ window.addGLEventListener(new GLEventListener() {
+ public void reshape(
+ final GLAutoDrawable drawable,
+ final int x,
+ final int y,
+ final int width,
+ final int height)
+ {
+ // Nothing.
+ }
+
+ public void init(
+ final GLAutoDrawable drawable)
+ {
+ final GLContext context = drawable.getContext();
+ System.err.println("CTX: "+context.getGLVersion());
+
+ final GL2GL3 gl = drawable.getGL().getGL2GL3();
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
+
+ final int[] name = new int[] { 0 };
+ gl.glGenBuffers(1, name, 0);
+ Assert.assertTrue(gl.glGetError() == GL.GL_NO_ERROR);
+
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, name[0]);
+ Assert.assertTrue(gl.glGetError() == 0);
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, 4 * 32, null, GL.GL_STATIC_DRAW);
+ Assert.assertTrue(gl.glGetError() == 0);
+
+ Assert.assertTrue(gl.getBoundBuffer(GL.GL_ARRAY_BUFFER) == name[0]);
+ gl.glEnableVertexAttribArray(1);
+ Assert.assertTrue(gl.glGetError() == GL.GL_NO_ERROR);
+ gl.glVertexAttribPointer(1, 4, GL.GL_FLOAT, false, 0, 0L);
+ Assert.assertTrue(gl.glGetError() == GL.GL_NO_ERROR); // FIXME On Mesa 9.0.1 w/ GL 3.1 -> GL.GL_INVALID_OPERATION ?
+ }
+
+ public void dispose(
+ final GLAutoDrawable drawable)
+ {
+ // Nothing.
+ }
+
+ public void display(
+ final GLAutoDrawable drawable)
+ {
+ // Nothing.
+ }
+ });
+
+ try {
+ window.setVisible(true);
+ } finally {
+ window.destroy();
+ }
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestGLMesaBug658NEWT.class.getName());
+ }
+
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLOffscreenAutoDrawableBug1044AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLOffscreenAutoDrawableBug1044AWT.java
new file mode 100644
index 000000000..18ac7abc2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLOffscreenAutoDrawableBug1044AWT.java
@@ -0,0 +1,106 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLOffscreenAutoDrawableBug1044AWT extends UITestCase {
+
+ @Test
+ public void test01GLOffscreenDrawable() throws InterruptedException {
+ final GLReadBufferUtil readBufferUtilRGB888 = new GLReadBufferUtil(false, false);
+ final GLReadBufferUtil readBufferUtilRGBA8888 = new GLReadBufferUtil(true, false);
+ final GLDrawableFactory fac = GLDrawableFactory.getFactory(GLProfile.getDefault());
+ final GLCapabilities glCap = new GLCapabilities(GLProfile.getMaxFixedFunc(true));
+ // Without line below, there is an error on Windows.
+ glCap.setDoubleBuffered(false);
+ //makes a new buffer 100x100
+ final GLDrawable glad = fac.createOffscreenDrawable(null, glCap, null, 100, 100);
+ glad.setRealized(true);
+ final GLContext context = glad.createContext(null);
+ context.makeCurrent();
+
+ System.err.println("Chosen: "+glad.getChosenGLCapabilities());
+
+ final GL2 gl2 = context.getGL().getGL2();
+ gl2.glViewport(0, 0, 100, 100);
+
+ gl2.glShadeModel(GLLightingFunc.GL_SMOOTH);
+ gl2.glClearColor(1.0f, 0.80f, 0.80f, 1); // This Will Clear The Background Color
+ gl2.glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
+ gl2.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl2.glLoadIdentity(); // Reset The Projection Matrix
+
+ final AWTGLReadBufferUtil agb = new AWTGLReadBufferUtil(glad.getGLProfile(), true);
+ final BufferedImage image = agb.readPixelsToBufferedImage(context.getGL(), true);
+ try {
+ ImageIO.write(image, "PNG", new File(getSimpleTestName(".")+"-AWTImageIO.png"));
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+
+ if(readBufferUtilRGB888.readPixels(gl2, false)) {
+ readBufferUtilRGB888.write(new File(getSimpleTestName(".")+"-PNGJ-rgb_.png"));
+ }
+ readBufferUtilRGB888.dispose(gl2);
+ if(readBufferUtilRGBA8888.readPixels(gl2, false)) {
+ readBufferUtilRGBA8888.write(new File(getSimpleTestName(".")+"-PNGJ-rgba.png"));
+ }
+ readBufferUtilRGBA8888.dispose(gl2);
+
+ context.destroy();
+ glad.setRealized(false);
+ System.out.println("Done!");
+ }
+
+ public static void main(final String[] args) {
+ org.junit.runner.JUnitCore.main(TestGLOffscreenAutoDrawableBug1044AWT.class.getName());
+ }
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLPointsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLPointsNEWT.java
new file mode 100644
index 000000000..fb6a50f7b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLPointsNEWT.java
@@ -0,0 +1,159 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import com.jogamp.opengl.test.junit.jogl.demos.PointsDemo;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.PointsDemoES1;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.PointsDemoES2;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLPointsNEWT extends UITestCase {
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 512;
+ height = 512;
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL0(final GLCapabilities caps, final PointsDemo demo) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setTitle(getSimpleTestName("."));
+
+ glWindow.addGLEventListener(demo);
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ snap.setPostSNDetail(demo.getClass().getSimpleName());
+ glWindow.addGLEventListener(snap);
+
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+
+ demo.setSmoothPoints(false);
+ snap.setMakeSnapshot();
+ snap.setPostSNDetail("flat");
+ glWindow.display();
+
+ demo.setSmoothPoints(true);
+ snap.setMakeSnapshot();
+ snap.setPostSNDetail("smooth");
+ glWindow.display();
+
+ demo.setPointParams(2f, 40f, 0.01f, 0.0f, 0.01f, 1f);
+ snap.setMakeSnapshot();
+ snap.setPostSNDetail("attn0");
+ glWindow.display();
+
+ glWindow.removeGLEventListener(demo);
+
+ glWindow.destroy();
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final PointsDemo demo, final boolean forceFFPEmu) throws InterruptedException {
+ // final PointsDemoES2 demo01 = new PointsDemoES2();
+ runTestGL0(caps, demo);
+ }
+
+ @Test
+ public void test01FFP__GL2() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL2)) { System.err.println("GL2 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2));
+ runTestGL(caps, new PointsDemoES1(), false);
+ }
+
+ @Test
+ public void test02FFP__ES1() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GLES1)) { System.err.println("GLES1 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES1));
+ runTestGL(caps, new PointsDemoES1(), false);
+ }
+
+ @Test
+ public void test03FFP__ES2() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GLES2)) { System.err.println("GLES2 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ final PointsDemoES1 demo = new PointsDemoES1();
+ demo.setForceFFPEmu(true, false, false, false);
+ runTestGL(caps, demo, false);
+ }
+
+ @Test
+ public void test04FFP__GL2ES2() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL2ES2)) { System.err.println("GL2ES2 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2));
+ final PointsDemoES1 demo = new PointsDemoES1();
+ demo.setForceFFPEmu(true, false, false, false);
+ runTestGL(caps, demo, false);
+ }
+
+ @Test
+ public void test11GLSL_GL2() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL2)) { System.err.println("GL2 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2));
+ runTestGL(caps, new PointsDemoES2(), false);
+ }
+
+ @Test
+ public void test12GLSL_ES2() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GLES2)) { System.err.println("GLES2 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ runTestGL(caps, new PointsDemoES2(), false); // should be FFPEmu implicit
+ }
+
+ static long duration = 1000; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLPointsNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java
index 19402c9cf..69ddb7771 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,31 +20,76 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
+import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.opengl.*;
+import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLProfile00NEWT extends UITestCase {
@Test
- public void testInitSingleton() throws InterruptedException {
+ public void test01InternedString() {
+ final String s1 = "GL2";
+ final String s2 = "GL2";
+ Assert.assertEquals(s1, s2);
+ Assert.assertTrue("s1-ref != s2-ref", s1 == s2);
+ Assert.assertTrue("s1-ref != 'GL2'-ref", s1 == "GL2");
+
+ Assert.assertEquals("GL2", GLProfile.GL2);
+ Assert.assertTrue("GLProfile-ref != 'GL2'-ref", GLProfile.GL2 == "GL2");
+ }
+
+ @Test
+ public void test02InitSingleton() throws InterruptedException {
+ Assert.assertFalse("JOGL is initialized before usage", GLProfile.isInitialized());
GLProfile.initSingleton();
+ Assert.assertTrue("JOGL is not initialized after enforced initialization", GLProfile.isInitialized());
+ }
+
+ @Test
+ public void test11DumpDesktopGLInfo() throws InterruptedException {
+ Assert.assertTrue("JOGL is not initialized ...", GLProfile.isInitialized());
+ System.err.println("Desktop");
+ final GLDrawableFactory desktopFactory = GLDrawableFactory.getDesktopFactory();
+ if( null != desktopFactory ) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(desktopFactory.getDefaultDevice(), null, false));
+ System.err.println(Platform.getNewline()+Platform.getNewline()+Platform.getNewline());
+ } else {
+ System.err.println("\tNULL");
+ }
+ }
+
+ @Test
+ public void test12DumpEGLGLInfo() throws InterruptedException {
+ Assert.assertTrue("JOGL is not initialized ...", GLProfile.isInitialized());
+ System.err.println("EGL");
+ final GLDrawableFactory eglFactory = GLDrawableFactory.getEGLFactory();
+ if( null != eglFactory ) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(eglFactory.getDefaultDevice(), null, false));
+ } else {
+ System.err.println("\tNULL");
+ }
}
- public static void main(String args[]) throws IOException {
- String tstname = TestGLProfile00NEWT.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestGLProfile00NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java
index d9429129b..3262ff996 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,172 +20,1009 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
import org.junit.Assert;
+import org.junit.FixMethodOrder;
import org.junit.Test;
-
-import javax.media.opengl.*;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.util.VersionUtil;
import com.jogamp.nativewindow.NativeWindowVersion;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-import com.jogamp.opengl.test.junit.util.DumpGLInfo;
+import com.jogamp.newt.NewtVersion;
+import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.JoglVersion;
-import com.jogamp.newt.opengl.*;
-import com.jogamp.newt.*;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLProfile01NEWT extends UITestCase {
@Test
- public void testVersion() throws InterruptedException {
+ public void test00Version() throws InterruptedException {
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
System.err.println(NativeWindowVersion.getInstance());
System.err.println(JoglVersion.getInstance());
System.err.println(NewtVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
+ final GLDrawableFactory deskFactory = GLDrawableFactory.getDesktopFactory();
+ if( null != deskFactory ) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(deskFactory.getDefaultDevice(), null, true).toString());
+ }
+ final GLDrawableFactory eglFactory = GLDrawableFactory.getEGLFactory();
+ if( null != eglFactory ) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(eglFactory.getDefaultDevice(), null, true).toString());
+ }
}
- @Test
- public void testGLProfileDefault() throws InterruptedException {
- System.out.println("GLProfile "+GLProfile.glAvailabilityToString());
- System.out.println("GLProfile.getDefaultDevice(): "+GLProfile.getDefaultDevice());
- GLProfile glp = GLProfile.getDefault();
- System.out.println("GLProfile.getDefault(): "+glp);
- if(glp.getName().equals(GLProfile.GL4bc)) {
+ //
+ // GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3, GL4ES3, GL3ES3, GL2ES2, GL2ES1, GLES3, GLES2, GLES1
+ //
+ // Real: GL4bc, GL4, GL3bc, GL3, GL2, GLES3, GLES2, GLES1
+ // Maps: GL2GL3, GL4ES3, GL3ES3, GL2ES2, GL2ES1
+ //
+
+ private static void validateGLProfileGL4bc(final GLProfile glp) {
+ Assert.assertTrue(glp.isGL4bc());
+ Assert.assertTrue(glp.isGL4());
+ Assert.assertTrue(glp.isGL3bc());
+ Assert.assertTrue(glp.isGL3());
+ Assert.assertTrue(glp.isGL2());
+ Assert.assertFalse(glp.isGLES3());
+ Assert.assertFalse(glp.isGLES2());
+ Assert.assertFalse(glp.isGLES1());
+ Assert.assertTrue(glp.isGL2GL3());
+ Assert.assertTrue(glp.isGL4ES3());
+ Assert.assertTrue(glp.isGL3ES3());
+ Assert.assertTrue(glp.isGL2ES2());
+ Assert.assertTrue(glp.isGL2ES1());
+ }
+ private static void validateGL4bc(final GL gl) {
+ final GLContext ctx = gl.getContext();
+ final boolean gles3CompatAvail = ctx.isGLES3Compatible();
+
+ Assert.assertTrue(gl.isGL4bc());
+ Assert.assertTrue(gl.isGL4());
+ Assert.assertTrue(gl.isGL3bc());
+ Assert.assertTrue(gl.isGL3());
+ Assert.assertTrue(gl.isGL2());
+ Assert.assertTrue(gl.isGL2GL3());
+ if( gles3CompatAvail ) {
+ Assert.assertTrue(gl.isGL4ES3());
+ } else {
+ Assert.assertFalse(gl.isGL4ES3());
+ }
+ Assert.assertTrue(gl.isGL3ES3());
+ Assert.assertTrue(gl.isGL2ES2());
+ Assert.assertTrue(gl.isGL2ES1());
+ Assert.assertFalse(gl.isGLES3());
+ Assert.assertFalse(gl.isGLES2());
+ Assert.assertFalse(gl.isGLES1());
+
+ Assert.assertTrue(ctx.isGL4bc());
+ Assert.assertTrue(ctx.isGL4());
+ Assert.assertTrue(ctx.isGL3bc());
+ Assert.assertTrue(ctx.isGL3());
+ Assert.assertTrue(ctx.isGL2());
+ Assert.assertTrue(ctx.isGL2GL3());
+ if( gles3CompatAvail ) {
+ Assert.assertTrue(ctx.isGL4ES3());
+ } else {
+ Assert.assertFalse(ctx.isGL4ES3());
+ }
+ Assert.assertTrue(ctx.isGL3ES3());
+ Assert.assertTrue(ctx.isGL2ES2());
+ Assert.assertTrue(ctx.isGL2ES1());
+ Assert.assertFalse(ctx.isGLES3());
+ Assert.assertFalse(ctx.isGLES2());
+ Assert.assertFalse(ctx.isGLES1());
+ }
+
+ private static void validateGLProfileGL4(final GLProfile glp) {
+ Assert.assertFalse(glp.isGL4bc());
+ Assert.assertTrue(glp.isGL4());
+ Assert.assertFalse(glp.isGL3bc());
+ Assert.assertTrue(glp.isGL3());
+ Assert.assertFalse(glp.isGL2());
+ Assert.assertFalse(glp.isGLES3());
+ Assert.assertFalse(glp.isGLES2());
+ Assert.assertFalse(glp.isGLES1());
+ Assert.assertTrue(glp.isGL2GL3());
+ Assert.assertTrue(glp.isGL4ES3());
+ Assert.assertTrue(glp.isGL3ES3());
+ Assert.assertTrue(glp.isGL2ES2());
+ Assert.assertFalse(glp.isGL2ES1());
+ }
+ private static void validateGL4(final GL gl) {
+ final GLContext ctx = gl.getContext();
+ final boolean gles3CompatAvail = ctx.isGLES3Compatible();
+
+ Assert.assertFalse(gl.isGL4bc());
+ Assert.assertTrue(gl.isGL4());
+ Assert.assertFalse(gl.isGL3bc());
+ Assert.assertTrue(gl.isGL3());
+ Assert.assertFalse(gl.isGL2());
+ Assert.assertTrue(gl.isGL2GL3());
+ if( gles3CompatAvail ) {
+ Assert.assertTrue(gl.isGL4ES3());
+ } else {
+ Assert.assertFalse(gl.isGL4ES3());
+ }
+ Assert.assertTrue(gl.isGL3ES3());
+ Assert.assertTrue(gl.isGL2ES2());
+ Assert.assertFalse(gl.isGL2ES1());
+ Assert.assertFalse(gl.isGLES3());
+ Assert.assertFalse(gl.isGLES2());
+ Assert.assertFalse(gl.isGLES1());
+
+ Assert.assertFalse(ctx.isGL4bc());
+ Assert.assertTrue(ctx.isGL4());
+ Assert.assertFalse(ctx.isGL3bc());
+ Assert.assertTrue(ctx.isGL3());
+ Assert.assertFalse(ctx.isGL2());
+ Assert.assertTrue(ctx.isGL2GL3());
+ if( gles3CompatAvail ) {
+ Assert.assertTrue(ctx.isGL4ES3());
+ } else {
+ Assert.assertFalse(ctx.isGL4ES3());
+ }
+ Assert.assertTrue(ctx.isGL3ES3());
+ Assert.assertTrue(ctx.isGL2ES2());
+ Assert.assertFalse(ctx.isGL2ES1());
+ Assert.assertFalse(ctx.isGLES3());
+ Assert.assertFalse(ctx.isGLES2());
+ Assert.assertFalse(ctx.isGLES1());
+ }
+
+ private static void validateGLProfileGL3bc(final GLProfile glp) {
+ Assert.assertFalse(glp.isGL4bc());
+ Assert.assertFalse(glp.isGL4());
+ Assert.assertTrue(glp.isGL3bc());
+ Assert.assertTrue(glp.isGL3());
+ Assert.assertTrue(glp.isGL2());
+ Assert.assertFalse(glp.isGLES3());
+ Assert.assertFalse(glp.isGLES2());
+ Assert.assertFalse(glp.isGLES1());
+ Assert.assertTrue(glp.isGL2GL3());
+ Assert.assertFalse(glp.isGL4ES3());
+ Assert.assertTrue(glp.isGL3ES3());
+ Assert.assertTrue(glp.isGL2ES2());
+ Assert.assertTrue(glp.isGL2ES1());
+ }
+ private static void validateGL3bc(final GL gl) {
+ final GLContext ctx = gl.getContext();
+ final boolean gles3CompatAvail = ctx.isGLES3Compatible();
+
+ Assert.assertFalse(gl.isGL4bc());
+ Assert.assertFalse(gl.isGL4());
+ Assert.assertTrue(gl.isGL3bc());
+ Assert.assertTrue(gl.isGL3());
+ Assert.assertTrue(gl.isGL2());
+ Assert.assertTrue(gl.isGL2GL3());
+ if( gles3CompatAvail ) { // possible w/ GL3 implementations!
+ Assert.assertTrue(gl.isGL4ES3());
+ } else {
+ Assert.assertFalse(gl.isGL4ES3());
+ }
+ Assert.assertTrue(gl.isGL3ES3());
+ Assert.assertTrue(gl.isGL2ES2());
+ Assert.assertTrue(gl.isGL2ES1());
+ Assert.assertFalse(gl.isGLES3());
+ Assert.assertFalse(gl.isGLES2());
+ Assert.assertFalse(gl.isGLES1());
+
+ Assert.assertFalse(ctx.isGL4bc());
+ Assert.assertFalse(ctx.isGL4());
+ Assert.assertTrue(ctx.isGL3bc());
+ Assert.assertTrue(ctx.isGL3());
+ Assert.assertTrue(ctx.isGL2());
+ Assert.assertTrue(ctx.isGL2GL3());
+ if( gles3CompatAvail ) { // possible w/ GL3 implementations!
+ Assert.assertTrue(ctx.isGL4ES3());
+ } else {
+ Assert.assertFalse(ctx.isGL4ES3());
+ }
+ Assert.assertTrue(ctx.isGL3ES3());
+ Assert.assertTrue(ctx.isGL2ES2());
+ Assert.assertTrue(ctx.isGL2ES1());
+ Assert.assertFalse(ctx.isGLES3());
+ Assert.assertFalse(ctx.isGLES2());
+ Assert.assertFalse(ctx.isGLES1());
+ }
+
+ private static void validateGLProfileGL3(final GLProfile glp) {
+ Assert.assertFalse(glp.isGL4bc());
+ Assert.assertFalse(glp.isGL4());
+ Assert.assertFalse(glp.isGL3bc());
+ Assert.assertTrue(glp.isGL3());
+ Assert.assertFalse(glp.isGL2());
+ Assert.assertFalse(glp.isGLES3());
+ Assert.assertFalse(glp.isGLES2());
+ Assert.assertFalse(glp.isGLES1());
+ Assert.assertTrue(glp.isGL2GL3());
+ Assert.assertFalse(glp.isGL4ES3());
+ Assert.assertTrue(glp.isGL3ES3());
+ Assert.assertTrue(glp.isGL2ES2());
+ Assert.assertFalse(glp.isGL2ES1());
+ }
+ private static void validateGL3(final GL gl) {
+ final GLContext ctx = gl.getContext();
+ final boolean gles3CompatAvail = ctx.isGLES3Compatible();
+
+ Assert.assertFalse(gl.isGL4bc());
+ Assert.assertFalse(gl.isGL4());
+ Assert.assertFalse(gl.isGL3bc());
+ Assert.assertTrue(gl.isGL3());
+ Assert.assertFalse(gl.isGL2());
+ Assert.assertTrue(gl.isGL2GL3());
+ if( gles3CompatAvail ) { // possible w/ GL3 implementations!
+ Assert.assertTrue(gl.isGL4ES3());
+ } else {
+ Assert.assertFalse(gl.isGL4ES3());
+ }
+ Assert.assertTrue(gl.isGL3ES3());
+ Assert.assertTrue(gl.isGL2ES2());
+ Assert.assertFalse(gl.isGL2ES1());
+ Assert.assertFalse(gl.isGLES3());
+ Assert.assertFalse(gl.isGLES2());
+ Assert.assertFalse(gl.isGLES1());
+
+ Assert.assertFalse(ctx.isGL4bc());
+ Assert.assertFalse(ctx.isGL4());
+ Assert.assertFalse(ctx.isGL3bc());
+ Assert.assertTrue(ctx.isGL3());
+ Assert.assertFalse(ctx.isGL2());
+ Assert.assertTrue(ctx.isGL2GL3());
+ if( gles3CompatAvail ) { // possible w/ GL3 implementations!
+ Assert.assertTrue(ctx.isGL4ES3());
+ } else {
+ Assert.assertFalse(ctx.isGL4ES3());
+ }
+ Assert.assertTrue(ctx.isGL3ES3());
+ Assert.assertTrue(ctx.isGL2ES2());
+ Assert.assertFalse(ctx.isGL2ES1());
+ Assert.assertFalse(ctx.isGLES3());
+ Assert.assertFalse(ctx.isGLES2());
+ Assert.assertFalse(ctx.isGLES1());
+ }
+
+ private static void validateGLProfileGL2(final GLProfile glp) {
+ Assert.assertFalse(glp.isGL4bc());
+ Assert.assertFalse(glp.isGL4());
+ Assert.assertFalse(glp.isGL3bc());
+ Assert.assertFalse(glp.isGL3());
+ Assert.assertTrue(glp.isGL2());
+ Assert.assertFalse(glp.isGLES3());
+ Assert.assertFalse(glp.isGLES2());
+ Assert.assertFalse(glp.isGLES1());
+ Assert.assertTrue(glp.isGL2GL3());
+ Assert.assertFalse(glp.isGL4ES3());
+ Assert.assertFalse(glp.isGL3ES3());
+ Assert.assertTrue(glp.isGL2ES2());
+ Assert.assertTrue(glp.isGL2ES1());
+ }
+ private static void validateGL2(final GL gl) {
+ final GLContext ctx = gl.getContext();
+ final boolean gles3CompatAvail = ctx.isGLES3Compatible();
+
+ Assert.assertFalse(gl.isGL4bc());
+ Assert.assertFalse(gl.isGL4());
+ Assert.assertFalse(gl.isGL3bc());
+ Assert.assertFalse(gl.isGL3());
+ Assert.assertTrue(gl.isGL2());
+ Assert.assertTrue(gl.isGL2GL3());
+ Assert.assertFalse(gl.isGL4ES3());
+ Assert.assertFalse(gl.isGL3ES3());
+ Assert.assertTrue(gl.isGL2ES2());
+ Assert.assertTrue(gl.isGL2ES1());
+ Assert.assertFalse(gl.isGLES3());
+ Assert.assertFalse(gl.isGLES2());
+ Assert.assertFalse(gl.isGLES1());
+
+ Assert.assertFalse(ctx.isGL4bc());
+ Assert.assertFalse(ctx.isGL4());
+ Assert.assertFalse(ctx.isGL3bc());
+ Assert.assertFalse(ctx.isGL3());
+ Assert.assertTrue(ctx.isGL2());
+ Assert.assertTrue(ctx.isGL2GL3());
+ Assert.assertFalse(ctx.isGL4ES3());
+ Assert.assertFalse(ctx.isGL3ES3());
+ Assert.assertFalse(gles3CompatAvail);
+ Assert.assertTrue(ctx.isGL2ES2());
+ Assert.assertTrue(ctx.isGL2ES1());
+ Assert.assertFalse(ctx.isGLES3());
+ Assert.assertFalse(ctx.isGLES2());
+ Assert.assertFalse(ctx.isGLES1());
+ }
+
+ private static void validateGLProfileGLES3(final GLProfile glp) {
+ Assert.assertFalse(glp.isGL4bc());
+ Assert.assertFalse(glp.isGL4());
+ Assert.assertFalse(glp.isGL3bc());
+ Assert.assertFalse(glp.isGL3());
+ Assert.assertFalse(glp.isGL2());
+ Assert.assertTrue(glp.isGLES3());
+ Assert.assertTrue(glp.isGLES2());
+ Assert.assertFalse(glp.isGLES1());
+ Assert.assertFalse(glp.isGL2GL3());
+ Assert.assertTrue(glp.isGL4ES3());
+ Assert.assertTrue(glp.isGL3ES3());
+ Assert.assertTrue(glp.isGL2ES2());
+ Assert.assertFalse(glp.isGL2ES1());
+ }
+ private static void validateGLES3(final GL gl) {
+ final GLContext ctx = gl.getContext();
+ final boolean gles3CompatAvail = ctx.isGLES3Compatible();
+
+ Assert.assertFalse(gl.isGL4bc());
+ Assert.assertFalse(gl.isGL4());
+ Assert.assertFalse(gl.isGL3bc());
+ Assert.assertFalse(gl.isGL3());
+ Assert.assertFalse(gl.isGL2());
+ Assert.assertFalse(gl.isGL2GL3());
+ Assert.assertTrue(gl.isGL4ES3());
+ Assert.assertTrue(gl.isGL3ES3());
+ Assert.assertTrue(gl.isGL2ES2());
+ Assert.assertFalse(gl.isGL2ES1());
+ Assert.assertTrue(gl.isGLES3());
+ Assert.assertTrue(gl.isGLES2());
+ Assert.assertFalse(gl.isGLES1());
+
+ Assert.assertFalse(ctx.isGL4bc());
+ Assert.assertFalse(ctx.isGL4());
+ Assert.assertFalse(ctx.isGL3bc());
+ Assert.assertFalse(ctx.isGL3());
+ Assert.assertFalse(ctx.isGL2());
+ Assert.assertFalse(ctx.isGL2GL3());
+ Assert.assertTrue(ctx.isGL4ES3());
+ Assert.assertTrue(ctx.isGL3ES3());
+ Assert.assertTrue(gles3CompatAvail);
+ Assert.assertTrue(ctx.isGL2ES2());
+ Assert.assertFalse(ctx.isGL2ES1());
+ Assert.assertTrue(ctx.isGLES3());
+ Assert.assertTrue(ctx.isGLES2());
+ Assert.assertFalse(ctx.isGLES1());
+ }
+
+ private static void validateGLProfileGLES2(final GLProfile glp) {
+ Assert.assertFalse(glp.isGL4bc());
+ Assert.assertFalse(glp.isGL4());
+ Assert.assertFalse(glp.isGL3bc());
+ Assert.assertFalse(glp.isGL3());
+ Assert.assertFalse(glp.isGL2());
+ Assert.assertFalse(glp.isGLES3());
+ Assert.assertTrue(glp.isGLES2());
+ Assert.assertFalse(glp.isGLES1());
+ Assert.assertFalse(glp.isGL2GL3());
+ Assert.assertFalse(glp.isGL4ES3());
+ Assert.assertFalse(glp.isGL3ES3());
+ Assert.assertTrue(glp.isGL2ES2());
+ Assert.assertFalse(glp.isGL2ES1());
+ }
+ private static void validateGLES2(final GL gl) {
+ final GLContext ctx = gl.getContext();
+ final boolean gles3CompatAvail = ctx.isGLES3Compatible();
+
+ Assert.assertFalse(gl.isGL4bc());
+ Assert.assertFalse(gl.isGL4());
+ Assert.assertFalse(gl.isGL3bc());
+ Assert.assertFalse(gl.isGL3());
+ Assert.assertFalse(gl.isGL2());
+ Assert.assertFalse(gl.isGL2GL3());
+ Assert.assertFalse(gl.isGL4ES3());
+ Assert.assertFalse(gl.isGL3ES3());
+ Assert.assertTrue(gl.isGL2ES2());
+ Assert.assertFalse(gl.isGL2ES1());
+ Assert.assertFalse(gl.isGLES3());
+ Assert.assertTrue(gl.isGLES2());
+ Assert.assertFalse(gl.isGLES1());
+
+ Assert.assertFalse(ctx.isGL4bc());
+ Assert.assertFalse(ctx.isGL4());
+ Assert.assertFalse(ctx.isGL3bc());
+ Assert.assertFalse(ctx.isGL3());
+ Assert.assertFalse(ctx.isGL2());
+ Assert.assertFalse(ctx.isGL2GL3());
+ Assert.assertFalse(ctx.isGL4ES3());
+ Assert.assertFalse(ctx.isGL3ES3());
+ Assert.assertFalse(gles3CompatAvail);
+ Assert.assertTrue(ctx.isGL2ES2());
+ Assert.assertFalse(ctx.isGL2ES1());
+ Assert.assertFalse(ctx.isGLES3());
+ Assert.assertTrue(ctx.isGLES2());
+ Assert.assertFalse(ctx.isGLES1());
+ }
+
+ private static void validateGLProfileGLES1(final GLProfile glp) {
+ Assert.assertFalse(glp.isGL4bc());
+ Assert.assertFalse(glp.isGL4());
+ Assert.assertFalse(glp.isGL3bc());
+ Assert.assertFalse(glp.isGL3());
+ Assert.assertFalse(glp.isGL2());
+ Assert.assertFalse(glp.isGLES3());
+ Assert.assertFalse(glp.isGLES2());
+ Assert.assertTrue(glp.isGLES1());
+ Assert.assertFalse(glp.isGL2GL3());
+ Assert.assertFalse(glp.isGL4ES3());
+ Assert.assertFalse(glp.isGL3ES3());
+ Assert.assertFalse(glp.isGL2ES2());
+ Assert.assertTrue(glp.isGL2ES1());
+ }
+ private static void validateGLES1(final GL gl) {
+ final GLContext ctx = gl.getContext();
+ final boolean gles3CompatAvail = ctx.isGLES3Compatible();
+
+ Assert.assertFalse(gl.isGL4bc());
+ Assert.assertFalse(gl.isGL4());
+ Assert.assertFalse(gl.isGL3bc());
+ Assert.assertFalse(gl.isGL3());
+ Assert.assertFalse(gl.isGL2());
+ Assert.assertFalse(gl.isGL2GL3());
+ Assert.assertFalse(gl.isGL4ES3());
+ Assert.assertFalse(gl.isGL3ES3());
+ Assert.assertFalse(gl.isGL2ES2());
+ Assert.assertTrue(gl.isGL2ES1());
+ Assert.assertFalse(gl.isGLES3());
+ Assert.assertFalse(gl.isGLES2());
+ Assert.assertTrue(gl.isGLES1());
+
+ Assert.assertFalse(ctx.isGL4bc());
+ Assert.assertFalse(ctx.isGL4());
+ Assert.assertFalse(ctx.isGL3bc());
+ Assert.assertFalse(ctx.isGL3());
+ Assert.assertFalse(ctx.isGL2());
+ Assert.assertFalse(ctx.isGL2GL3());
+ Assert.assertFalse(ctx.isGL4ES3());
+ Assert.assertFalse(ctx.isGL3ES3());
+ Assert.assertFalse(gles3CompatAvail);
+ Assert.assertFalse(ctx.isGL2ES2());
+ Assert.assertTrue(ctx.isGL2ES1());
+ Assert.assertFalse(ctx.isGLES3());
+ Assert.assertFalse(ctx.isGLES2());
+ Assert.assertTrue(ctx.isGLES1());
+ }
+
+ private static void validateGLProfileGL2GL3(final GLProfile glp) {
+ if( glp.isGL4bc() ) {
+ validateGLProfileGL4bc(glp);
+ } else if(glp.isGL3bc()) {
+ validateGLProfileGL3bc(glp);
+ } else if(glp.isGL2()) {
+ validateGLProfileGL2(glp);
+ } else if(glp.isGL4()) {
+ validateGLProfileGL4(glp);
+ } else if(glp.isGL3()) {
+ validateGLProfileGL3(glp);
+ } else {
+ throw new GLException("GL2GL3 is neither GL4bc, GL3bc, GL2, GL4 nor GL3");
+ }
+ }
+ private static void validateGL2GL3(final GL gl) {
+ if( gl.isGL4bc() ) {
+ validateGL4bc(gl);
+ } else if(gl.isGL3bc()) {
+ validateGL3bc(gl);
+ } else if(gl.isGL2()) {
+ validateGL2(gl);
+ } else if(gl.isGL4()) {
+ validateGL4(gl);
+ } else if(gl.isGL3()) {
+ validateGL3(gl);
+ } else {
+ throw new GLException("GL2GL3 is neither GL4bc, GL3bc, GL2, GL4 nor GL3");
+ }
+ }
+
+ private static void validateGLProfileGL4ES3(final GLProfile glp) {
+ if( glp.isGL4bc() ) {
+ validateGLProfileGL4bc(glp);
+ } else if( glp.isGL4() ) {
+ validateGLProfileGL4(glp);
+ } else if( glp.isGLES3() ) {
+ validateGLProfileGLES3(glp);
+ } else {
+ throw new GLException("GL4ES3 is neither GL4bc, GL4 nor GLES3");
+ }
+ }
+ private static void validateGL4ES3(final GL gl) {
+ if( gl.isGL4bc() ) {
+ validateGL4bc(gl);
+ } else if( gl.isGL4() ) {
+ validateGL4(gl);
+ } else if( gl.isGLES3() ) {
+ validateGLES3(gl);
+ } else {
+ throw new GLException("GL4ES3 is neither GL4bc, GL4 nor GLES3");
+ }
+ }
+
+ private static void validateGLProfileGL2ES2(final GLProfile glp) {
+ if( glp.isGL4bc() ) {
+ validateGLProfileGL4bc(glp);
+ } else if(glp.isGL3bc()) {
+ validateGLProfileGL3bc(glp);
+ } else if(glp.isGL2()) {
+ validateGLProfileGL2(glp);
+ } else if(glp.isGL4()) {
+ validateGLProfileGL4(glp);
+ } else if(glp.isGL3()) {
+ validateGLProfileGL3(glp);
+ } else if(glp.isGLES3()) {
+ validateGLProfileGLES3(glp);
+ } else if(glp.isGLES2()) {
+ validateGLProfileGLES2(glp);
+ } else {
+ throw new GLException("GL2ES2 is neither GL4bc, GL3bc, GL2, GL4, GL3, GLES3 nor GLES2");
+ }
+ }
+ private static void validateGL2ES2(final GL gl) {
+ if( gl.isGL4bc() ) {
+ validateGL4bc(gl);
+ } else if(gl.isGL3bc()) {
+ validateGL3bc(gl);
+ } else if(gl.isGL2()) {
+ validateGL2(gl);
+ } else if(gl.isGL4()) {
+ validateGL4(gl);
+ } else if(gl.isGL3()) {
+ validateGL3(gl);
+ } else if(gl.isGLES3()) {
+ validateGLES3(gl);
+ } else if(gl.isGLES2()) {
+ validateGLES2(gl);
+ } else {
+ throw new GLException("GL2ES2 is neither GL4bc, GL3bc, GL2, GL4, GL3, GLES3 nor GLES2");
+ }
+ }
+
+ private static void validateGLProfileGL2ES1(final GLProfile glp) {
+ if( glp.isGL4bc() ) {
+ validateGLProfileGL4bc(glp);
+ } else if(glp.isGL3bc()) {
+ validateGLProfileGL3bc(glp);
+ } else if(glp.isGL2()) {
+ validateGLProfileGL2(glp);
+ } else if(glp.isGLES1()) {
+ validateGLProfileGLES1(glp);
+ } else {
+ throw new GLException("GL2ES1 is neither GL4bc, GL3bc, GL2 nor GLES1");
+ }
+ }
+ private static void validateGL2ES1(final GL gl) {
+ if( gl.isGL4bc() ) {
+ validateGL4bc(gl);
+ } else if(gl.isGL3bc()) {
+ validateGL3bc(gl);
+ } else if(gl.isGL2()) {
+ validateGL2(gl);
+ } else if(gl.isGLES1()) {
+ validateGLES1(gl);
+ } else {
+ throw new GLException("GL2ES1 is neither GL4bc, GL3bc, GL2 nor GLES1");
+ }
+ }
+
+ private static void validateOffline(final String requestedProfile, final GLProfile glp) {
+ System.err.println("GLProfile Mapping "+requestedProfile+" -> "+glp);
+
+ final boolean gles3CompatAvail = GLContext.isGLES3CompatibleAvailable(GLProfile.getDefaultDevice());
+ if( glp.getImplName().equals(GLProfile.GL4bc) ) {
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4bc));
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4));
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3bc));
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3));
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2));
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2GL3));
+ if( gles3CompatAvail ) {
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4ES3));
+ } else {
+ Assert.assertFalse(GLProfile.isAvailable(GLProfile.GL4ES3));
+ }
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES1));
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2));
- } else if(glp.getName().equals(GLProfile.GL3bc)) {
+ } else if(glp.getImplName().equals(GLProfile.GL3bc)) {
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3bc));
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3));
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2));
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2GL3));
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES1));
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2));
- } else if(glp.getName().equals(GLProfile.GL2)) {
+ } else if(glp.getImplName().equals(GLProfile.GL2)) {
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2));
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2GL3));
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES1));
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2));
- } else if(glp.getName().equals(GLProfile.GL2ES1)) {
- Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES1));
- }
- dumpVersion(glp);
- }
-
- @Test
- public void testGLProfileMaxProgrammable() throws InterruptedException {
- // Assuming at least one programmable profile is available
- GLProfile glp = GLProfile.getMaxProgrammable(true);
- System.out.println("GLProfile.getMaxProgrammable(): "+glp);
- if(glp.getName().equals(GLProfile.GL4)) {
+ } else if(glp.getImplName().equals(GLProfile.GL4)) {
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4));
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3));
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2GL3));
+ if( gles3CompatAvail ) {
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4ES3));
+ } else {
+ Assert.assertFalse(GLProfile.isAvailable(GLProfile.GL4ES3));
+ }
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2));
- } else if(glp.getName().equals(GLProfile.GL3)) {
+ } else if(glp.getImplName().equals(GLProfile.GL3)) {
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3));
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2GL3));
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2));
+ } else if(glp.getImplName().equals(GLProfile.GLES3)) {
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GLES3));
+ if( gles3CompatAvail ) {
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4ES3));
+ } else {
+ Assert.assertFalse(GLProfile.isAvailable(GLProfile.GL4ES3));
+ }
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2));
- } else if(glp.getName().equals(GLProfile.GL2ES2)) {
+ } else if(glp.getImplName().equals(GLProfile.GLES2)) {
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GLES2));
Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2));
+ } else if(glp.getImplName().equals(GLProfile.GLES1)) {
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GLES1));
+ Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES1));
}
- dumpVersion(glp);
+ if( glp.isGL4bc() ) {
+ validateGLProfileGL4bc(glp);
+ } else if(glp.isGL3bc()) {
+ validateGLProfileGL3bc(glp);
+ } else if(glp.isGL2()) {
+ validateGLProfileGL2(glp);
+ } else if(glp.isGL4()) {
+ validateGLProfileGL4(glp);
+ } else if(glp.isGL3()) {
+ validateGLProfileGL3(glp);
+ } else if(glp.isGLES3()) {
+ validateGLProfileGLES3(glp);
+ } else if(glp.isGLES2()) {
+ validateGLProfileGLES2(glp);
+ } else if(glp.isGLES1()) {
+ validateGLProfileGLES1(glp);
+ }
+
+ if( requestedProfile == GLProfile.GL4bc ) {
+ validateGLProfileGL4bc(glp);
+ } else if( requestedProfile == GLProfile.GL3bc ) {
+ validateGLProfileGL3bc(glp);
+ } else if( requestedProfile == GLProfile.GL2 ) {
+ validateGLProfileGL2(glp);
+ } else if( requestedProfile == GLProfile.GL4 ) {
+ validateGLProfileGL4(glp);
+ } else if( requestedProfile == GLProfile.GL3 ) {
+ validateGLProfileGL3(glp);
+ } else if( requestedProfile == GLProfile.GLES3 ) {
+ validateGLProfileGLES3(glp);
+ } else if( requestedProfile == GLProfile.GLES2 ) {
+ validateGLProfileGLES2(glp);
+ } else if( requestedProfile == GLProfile.GLES1 ) {
+ validateGLProfileGLES1(glp);
+ } else if( requestedProfile == GLProfile.GL2GL3 ) {
+ validateGLProfileGL2GL3(glp);
+ } else if( requestedProfile == GLProfile.GL4ES3 ) {
+ validateGLProfileGL4ES3(glp);
+ } else if( requestedProfile == GLProfile.GL2ES2 ) {
+ validateGLProfileGL2ES2(glp);
+ } else if( requestedProfile == GLProfile.GL2ES1 ) {
+ validateGLProfileGL2ES1(glp);
+ }
+
+ }
+
+ static void validateOnline(final String requestedProfile, final GLProfile glpReq, final GL gl) {
+ final GLContext ctx = gl.getContext();
+ final GLProfile glp = gl.getGLProfile();
+
+ System.err.println("GLContext Mapping "+requestedProfile+" -> "+glpReq+" -> "+glp+" -> "+ctx.getGLVersion());
+
+ System.err.println("GL impl. class "+gl.getClass().getName());
+ if( gl.isGL4() ) {
+ Assert.assertNotNull( gl.getGL4() );
+ System.err.println("GL Mapping "+glp+" -> GL4");
+ }
+ if( gl.isGL4bc() ) {
+ Assert.assertNotNull( gl.getGL4bc() );
+ System.err.println("GL Mapping "+glp+" -> GL4bc");
+ }
+ if( gl.isGL3() ) {
+ Assert.assertNotNull( gl.getGL3() );
+ System.err.println("GL Mapping "+glp+" -> GL3");
+ }
+ if( gl.isGL3bc() ) {
+ Assert.assertNotNull( gl.getGL3bc() );
+ System.err.println("GL Mapping "+glp+" -> GL3bc");
+ }
+ if( gl.isGL2() ) {
+ Assert.assertNotNull( gl.getGL2() );
+ System.err.println("GL Mapping "+glp+" -> GL2");
+ }
+ if( gl.isGLES3() ) {
+ Assert.assertNotNull( gl.getGLES3() );
+ System.err.println("GL Mapping "+glp+" -> GLES3");
+ }
+ if( gl.isGLES2() ) {
+ Assert.assertNotNull( gl.getGLES2() );
+ System.err.println("GL Mapping "+glp+" -> GLES2");
+ }
+ if( gl.isGLES1() ) {
+ Assert.assertNotNull( gl.getGLES1() );
+ System.err.println("GL Mapping "+glp+" -> GLES1");
+ }
+ if( gl.isGL4ES3() ) {
+ Assert.assertNotNull( gl.getGL4ES3() );
+ System.err.println("GL Mapping "+glp+" -> GL4ES3");
+ }
+ if( gl.isGL3ES3() ) {
+ Assert.assertNotNull( gl.getGL3ES3() );
+ System.err.println("GL Mapping "+glp+" -> GL3ES3");
+ }
+ if( gl.isGL2GL3() ) {
+ Assert.assertNotNull( gl.getGL2GL3() );
+ System.err.println("GL Mapping "+glp+" -> GL2GL3");
+ }
+ if( gl.isGL2ES2() ) {
+ Assert.assertNotNull( gl.getGL2ES2() );
+ System.err.println("GL Mapping "+glp+" -> GL2ES2");
+ }
+ if( gl.isGL2ES1() ) {
+ Assert.assertNotNull( gl.getGL2ES1() );
+ System.err.println("GL Mapping "+glp+" -> GL2ES1");
+ }
+
+ if( gl.isGL4bc() ) {
+ validateGL4bc(gl);
+ } else if(gl.isGL3bc()) {
+ validateGL3bc(gl);
+ } else if(gl.isGL2()) {
+ validateGL2(gl);
+ } else if(gl.isGL4()) {
+ validateGL4(gl);
+ } else if(gl.isGL3()) {
+ validateGL3(gl);
+ } else if(gl.isGLES3()) {
+ validateGLES3(gl);
+ } else if(gl.isGLES2()) {
+ validateGLES2(gl);
+ } else if(gl.isGLES1()) {
+ validateGLES1(gl);
+ }
+
+ if( requestedProfile == GLProfile.GL4bc ) {
+ validateGL4bc(gl);
+ } else if( requestedProfile == GLProfile.GL3bc ) {
+ if( gl.isGL4bc() ) {
+ validateGL4bc(gl);
+ } else if( gl.isGL3bc() ) {
+ validateGL3bc(gl);
+ } else {
+ throw new GLException("GL3bc is neither GL4bc nor GL3bc");
+ }
+ } else if( requestedProfile == GLProfile.GL2 ) {
+ if( gl.isGL4bc() ) {
+ validateGL4bc(gl);
+ } else if( gl.isGL3bc() ) {
+ validateGL3bc(gl);
+ } else if( gl.isGL2() ) {
+ validateGL2(gl);
+ } else {
+ throw new GLException("GL2 is neither GL4bc, GL3bc, GL2");
+ }
+ } else if( requestedProfile == GLProfile.GL4 ) {
+ if( gl.isGL4bc() ) {
+ validateGL4bc(gl);
+ } else if( gl.isGL4() ) {
+ validateGL4(gl);
+ } else {
+ throw new GLException("GL4 is neither GL4bc, nor GL4");
+ }
+ } else if( requestedProfile == GLProfile.GL3 ) {
+ if( gl.isGL4bc() ) {
+ validateGL4bc(gl);
+ } else if( gl.isGL3bc() ) {
+ validateGL3bc(gl);
+ } else if( gl.isGL4() ) {
+ validateGL4(gl);
+ } else if( gl.isGL3() ) {
+ validateGL3(gl);
+ } else {
+ throw new GLException("GL3 is neither GL4bc, GL3bc, GL4 nor GL3");
+ }
+ } else if( requestedProfile == GLProfile.GLES3 ) {
+ validateGLES3(gl);
+ } else if( requestedProfile == GLProfile.GLES2 ) {
+ if( gl.isGLES3() ) {
+ validateGLES3(gl);
+ } else if( gl.isGLES2() ) {
+ validateGLES2(gl);
+ } else {
+ throw new GLException("GLES2 is neither GLES3 nor GLES2");
+ }
+ } else if( requestedProfile == GLProfile.GLES1 ) {
+ validateGLES1(gl);
+ } else if( requestedProfile == GLProfile.GL2GL3 ) {
+ validateGL2GL3(gl);
+ } else if( requestedProfile == GLProfile.GL4ES3 ) {
+ validateGL4ES3(gl);
+ } else if( requestedProfile == GLProfile.GL2ES2 ) {
+ validateGL2ES2(gl);
+ } else if( requestedProfile == GLProfile.GL2ES1 ) {
+ validateGL2ES1(gl);
+ }
+ }
+
+ void validateOnline(final String requestedProfile, final GLProfile glp) throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setTitle(getSimpleTestName("."));
+
+ glWindow.addGLEventListener(new GLEventListener() {
+
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println(JoglVersion.getGLStrings(gl, null, false));
+
+ validateOnline(requestedProfile, glp, gl);
+ }
+
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ }
+
+ public void display(final GLAutoDrawable drawable) {
+ }
+
+ public void dispose(final GLAutoDrawable drawable) {
+ }
+ });
+
+ glWindow.setSize(128, 128);
+ glWindow.setVisible(true);
+
+ glWindow.display();
+ Thread.sleep(100);
+ glWindow.destroy();
}
@Test
- public void testGLProfileGL2ES1() throws InterruptedException {
+ public void test01GLProfileDefault() throws InterruptedException {
+ System.out.println("GLProfile "+GLProfile.glAvailabilityToString());
+ System.out.println("GLProfile.getDefaultDevice(): "+GLProfile.getDefaultDevice());
+ final GLProfile glp = GLProfile.getDefault();
+ System.out.println("GLProfile.getDefault(): "+glp);
+ validateOffline("default", glp);
+ validateOnline("default", glp);
+ }
+
+ @Test
+ public void test02GLProfileMaxProgrammable() throws InterruptedException {
+ // Assuming at least one programmable profile is available
+ final GLProfile glp = GLProfile.getMaxProgrammable(true);
+ System.out.println("GLProfile.getMaxProgrammable(): "+glp);
+ validateOffline("maxProgrammable", glp);
+ validateOnline("maxProgrammable", glp);
+ }
+
+ @Test
+ public void test03GLProfileMaxFixedFunc() throws InterruptedException {
+ // Assuming at least one fixed function profile is available
+ final GLProfile glp = GLProfile.getMaxFixedFunc(true);
+ System.out.println("GLProfile.getMaxFixedFunc(): "+glp);
+ validateOffline("maxFixedFunc", glp);
+ validateOnline("maxFixedFunc", glp);
+ }
+
+ @Test
+ public void test04GLProfileGL2ES1() throws InterruptedException {
if(!GLProfile.isAvailable(GLProfile.GL2ES1)) {
System.out.println("GLProfile GL2ES1 n/a");
return;
}
- GLProfile glp = GLProfile.getGL2ES1();
- System.out.println("GLProfile GL2ES1: "+glp);
- dumpVersion(glp);
+ final GLProfile glp = GLProfile.getGL2ES1();
+ validateOffline(GLProfile.GL2ES1, glp);
+ validateOnline(GLProfile.GL2ES1, glp);
}
@Test
- public void testGLProfileGL2ES2() throws InterruptedException {
+ public void test05GLProfileGL2ES2() throws InterruptedException {
if(!GLProfile.isAvailable(GLProfile.GL2ES2)) {
System.out.println("GLProfile GL2ES2 n/a");
return;
}
- GLProfile glp = GLProfile.getGL2ES2();
- System.out.println("GLProfile GL2ES2: "+glp);
- dumpVersion(glp);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ validateOffline(GLProfile.GL2ES2, glp);
+ validateOnline(GLProfile.GL2ES2, glp);
+ }
+
+ @Test
+ public void test06GLProfileGL4ES3() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL4ES3)) {
+ System.out.println("GLProfile GL4ES3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.getGL4ES3();
+ validateOffline(GLProfile.GL4ES3, glp);
+ validateOnline(GLProfile.GL4ES3, glp);
}
-
- void testSpecificProfile(String glps) throws InterruptedException {
+
+ @Test
+ public void test07GLProfileGL2GL3() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL2GL3)) {
+ System.out.println("GLProfile GL2GL3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.getGL2GL3();
+ validateOffline(GLProfile.GL2GL3, glp);
+ validateOnline(GLProfile.GL2GL3, glp);
+ }
+
+ void testSpecificProfile(final String glps) throws InterruptedException {
if(GLProfile.isAvailable(glps)) {
- GLProfile glp = GLProfile.get(glps);
- dumpVersion(glp);
+ final GLProfile glp = GLProfile.get(glps);
+ validateOffline(glps, glp);
+ validateOnline(glps, glp);
} else {
System.err.println("Profile "+glps+" n/a");
}
}
-
+
@Test
- public void testGL4bc() throws InterruptedException {
+ public void test10_GL4bc() throws InterruptedException {
testSpecificProfile(GLProfile.GL4bc);
}
@Test
- public void testGL3bc() throws InterruptedException {
+ public void test11_GL3bc() throws InterruptedException {
testSpecificProfile(GLProfile.GL3bc);
}
@Test
- public void testGL2() throws InterruptedException {
+ public void test12_GL2() throws InterruptedException {
testSpecificProfile(GLProfile.GL2);
}
-
+
@Test
- public void testGL4() throws InterruptedException {
+ public void test13_GL4() throws InterruptedException {
testSpecificProfile(GLProfile.GL4);
}
@Test
- public void testGL3() throws InterruptedException {
+ public void test14_GL3() throws InterruptedException {
testSpecificProfile(GLProfile.GL3);
}
@Test
- public void testGLES1() throws InterruptedException {
+ public void test15_GLES1() throws InterruptedException {
testSpecificProfile(GLProfile.GLES1);
}
@Test
- public void testGLES2() throws InterruptedException {
+ public void test16_GLES2() throws InterruptedException {
testSpecificProfile(GLProfile.GLES2);
}
-
- protected void dumpVersion(GLProfile glp) throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
- GLWindow glWindow = GLWindow.create(caps);
- Assert.assertNotNull(glWindow);
- glWindow.setTitle("TestGLProfile01NEWT");
- glWindow.addGLEventListener(new DumpGLInfo());
-
- glWindow.setSize(128, 128);
- glWindow.setVisible(true);
-
- glWindow.display();
- Thread.sleep(100);
- glWindow.destroy();
+ @Test
+ public void test17_GLES3() throws InterruptedException {
+ testSpecificProfile(GLProfile.GLES3);
}
- public static void main(String args[]) throws IOException {
- String tstname = TestGLProfile01NEWT.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestGLProfile01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLCanvasAWT.java
new file mode 100644
index 000000000..37f1c7555
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLCanvasAWT.java
@@ -0,0 +1,212 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Frame;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+
+/**
+ * Test synchronous GLAutoDrawable display, swap-buffer and read-pixels with AWT GLCanvas
+ * including non-MSAA and MSAA framebuffer.
+ * <p>
+ * See {@link GLReadBuffer00Base} for related bugs and further details.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLReadBuffer01GLCanvasAWT extends GLReadBuffer00BaseAWT {
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ @Override
+ public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) {
+ if( skipGLOrientationVerticalFlip || useSwingDoubleBuffer ) {
+ return; // NOP
+ }
+ final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false);
+ final Frame frame = new Frame();
+ final Dimension d = new Dimension(320, 240);
+ final GLCanvas glad = createGLCanvas(caps, d);
+ final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+ final SnapshotGLELAWT snapshotGLEL = doSnapshot ? new SnapshotGLELAWT(textRendererGLEL, awtGLReadBufferUtil, false) : null;
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setLocation(64, 64);
+ frame.setLayout(new BorderLayout());
+ // final JPanel panel = new JPanel();
+ // panel.setLayout(new BorderLayout());
+ // panel.setDoubleBuffered(useSwingDoubleBuffer);
+ // frame.getContentPane().add(panel);
+
+ glad.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println("GLEventListener init on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {}
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x,final int y, final int width, final int height) {}
+ });
+ {
+ final GearsES2 gears = new GearsES2(1);
+ gears.setVerbose(false);
+ glad.addGLEventListener(gears);
+ }
+ {
+ final MultisampleDemoES2 demo = new MultisampleDemoES2(caps.getSampleBuffers());
+ demo.setClearBuffers(false);;
+ glad.addGLEventListener(demo);
+ }
+
+ glad.addGLEventListener(textRendererGLEL);
+ if( doSnapshot ) {
+ glad.addGLEventListener(snapshotGLEL);
+ }
+ // panel.add(glad);
+ frame.add(glad, BorderLayout.CENTER);
+ frame.pack();
+ frame.setVisible(true);
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ glad.display(); // trigger initialization to get chosen-caps!
+ final Dimension size0 = frame.getSize();
+ final Dimension size1 = new Dimension(size0.width+100, size0.height+100);
+ final Dimension size2 = new Dimension(size0.width-100, size0.height-100);
+ try {
+ for(int i=0; i<3; i++) {
+ final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1);
+ System.err.println(str);
+ if( keyFrame ) {
+ waitForKey(str);
+ }
+ textRendererGLEL.userCounter = i + 1;
+ glad.display();
+ }
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size1);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size2);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size0);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+
+ if( doSnapshot ) {
+ glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+ }
+ final Animator anim = new Animator(glad);
+ anim.start();
+ try { Thread.sleep(2*duration); } catch (final InterruptedException e) { }
+ anim.stop();
+ } catch (final Exception e1) {
+ e1.printStackTrace();
+ }
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.dispose();
+ } } );
+ } catch (final Exception e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ private GLCanvas createGLCanvas(final GLCapabilitiesImmutable caps, final Dimension size) {
+ final GLCanvas canvas = new GLCanvas(caps);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ canvas.setMinimumSize(size);
+ return canvas;
+ }
+
+ static GLCapabilitiesImmutable caps = null;
+ static boolean doSnapshot = true;
+ static boolean keyFrame = false;
+
+ public static void main(final String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-keyFrame")) {
+ keyFrame = true;
+ } else if(args[i].equals("-noSnapshot")) {
+ doSnapshot = false;
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLCanvasAWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java
new file mode 100644
index 000000000..599392d0c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java
@@ -0,0 +1,215 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.GlueGenVersion;
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+
+/**
+ * Test synchronous GLAutoDrawable display, swap-buffer and read-pixels with AWT GLJPanel
+ * including non-MSAA and MSAA framebuffer.
+ * <p>
+ * See {@link GLReadBuffer00Base} for related bugs and further details.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00BaseAWT {
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ @Override
+ public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) {
+ final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false);
+ final JFrame frame = new JFrame();
+ final Dimension d = new Dimension(320, 240);
+ final GLJPanel glad = createGLJPanel(skipGLOrientationVerticalFlip, useSwingDoubleBuffer, caps, d);
+ final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+ final SnapshotGLELAWT snapshotGLEL = doSnapshot ? new SnapshotGLELAWT(textRendererGLEL, awtGLReadBufferUtil, skipGLOrientationVerticalFlip) : null;
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setLocation(64, 64);
+ final JPanel panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.setDoubleBuffered(useSwingDoubleBuffer);
+ frame.getContentPane().add(panel);
+
+ glad.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println("GLEventListener init on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {}
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x,final int y, final int width, final int height) {}
+ });
+ {
+ final GearsES2 gears = new GearsES2(1);
+ gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ gears.setVerbose(false);
+ glad.addGLEventListener(gears);
+ }
+ {
+ final MultisampleDemoES2 demo = new MultisampleDemoES2(caps.getSampleBuffers());
+ demo.setClearBuffers(false);;
+ glad.addGLEventListener(demo);
+ }
+ textRendererGLEL.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glad.addGLEventListener(textRendererGLEL);
+ if( doSnapshot ) {
+ glad.addGLEventListener(snapshotGLEL);
+ }
+ panel.add(glad);
+ frame.pack();
+ frame.setVisible(true);
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ if( keyFrame ) {
+ waitForKey("Post init: Frame# "+textRendererGLEL.frameNo);
+ }
+ glad.display(); // trigger initialization to get chosen-caps!
+ final Dimension size0 = frame.getSize();
+ final Dimension size1 = new Dimension(size0.width+100, size0.height+100);
+ final Dimension size2 = new Dimension(size0.width-100, size0.height-100);
+ try {
+ for(int i=0; i<3; i++) {
+ final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1);
+ System.err.println(str);
+ if( keyFrame ) {
+ waitForKey(str);
+ }
+ textRendererGLEL.userCounter = i + 1;
+ glad.display();
+ }
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size1);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size2);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(size0);
+ frame.validate();
+ } } );
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+
+ if( doSnapshot ) {
+ glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+ }
+ final Animator anim = new Animator(glad);
+ anim.start();
+ try { Thread.sleep(2*duration); } catch (final InterruptedException e) { }
+ anim.stop();
+ } catch (final Exception e1) {
+ e1.printStackTrace();
+ }
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.dispose();
+ } } );
+ } catch (final Exception e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ private GLJPanel createGLJPanel(final boolean skipGLOrientationVerticalFlip, final boolean useSwingDoubleBuffer, final GLCapabilitiesImmutable caps, final Dimension size) {
+ final GLJPanel canvas = new GLJPanel(caps);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ canvas.setMinimumSize(size);
+ canvas.setDoubleBuffered(useSwingDoubleBuffer);
+ canvas.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip);
+ return canvas;
+ }
+
+ static GLCapabilitiesImmutable caps = null;
+ static boolean doSnapshot = true;
+ static boolean keyFrame = false;
+
+ public static void main(final String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-keyFrame")) {
+ keyFrame = true;
+ } else if(args[i].equals("-noSnapshot")) {
+ doSnapshot = false;
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLJPanelAWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java
new file mode 100644
index 000000000..4da73dbca
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java
@@ -0,0 +1,226 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.File;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Test synchronous GLAutoDrawable display, swap-buffer and read-pixels with NEWT
+ * including non-MSAA and MSAA framebuffer.
+ * <p>
+ * See {@link GLReadBuffer00Base} for related bugs and further details.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLReadBuffer01GLWindowNEWT extends GLReadBuffer00Base {
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ @Override
+ public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) {
+ if( skipGLOrientationVerticalFlip || useSwingDoubleBuffer ) {
+ return; // NOP
+ }
+ final GLReadBufferUtil glReadBufferUtil = new GLReadBufferUtil(false, false);
+ final GLWindow glad= GLWindow.create(caps);
+ final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+ final SnapshotGLEL snapshotGLEL = doSnapshot ? new SnapshotGLEL(textRendererGLEL, glReadBufferUtil) : null;
+ try {
+ glad.setPosition(64, 64);
+ glad.setSize(320, 240);
+ glad.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println("GLEventListener init on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {}
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x,final int y, final int width, final int height) {}
+ });
+ {
+ final GearsES2 gears = new GearsES2(1);
+ gears.setVerbose(false);
+ glad.addGLEventListener(gears);
+ }
+ {
+ final MultisampleDemoES2 demo = new MultisampleDemoES2(caps.getSampleBuffers());
+ demo.setClearBuffers(false);;
+ glad.addGLEventListener(demo);
+ }
+ textRendererGLEL.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glad.addGLEventListener(textRendererGLEL);
+ if( doSnapshot ) {
+ glad.addGLEventListener(snapshotGLEL);
+ }
+ glad.setVisible(true);
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ final DimensionImmutable size0 = new Dimension(glad.getSurfaceWidth(), glad.getSurfaceHeight());
+ final DimensionImmutable size1 = new Dimension(size0.getWidth()+100, size0.getHeight()+100);
+ final DimensionImmutable size2 = new Dimension(size0.getWidth()-100, size0.getHeight()-100);
+ try {
+ for(int i=0; i<3; i++) {
+ final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1);
+ System.err.println(str);
+ if( keyFrame ) {
+ waitForKey(str);
+ }
+ textRendererGLEL.userCounter = i + 1;
+ glad.display();
+ }
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+ glad.setSize(size1.getWidth(), size1.getHeight());
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+ glad.setSize(size2.getWidth(), size2.getHeight());
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+ glad.setSize(size0.getWidth(), size0.getHeight());
+ try { Thread.sleep(duration); } catch (final InterruptedException e) { }
+
+ if( doSnapshot ) {
+ glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+ }
+ final Animator anim = new Animator(glad);
+ anim.start();
+ try { Thread.sleep(2*duration); } catch (final InterruptedException e) { }
+ anim.stop();
+ } catch (final Exception e1) {
+ e1.printStackTrace();
+ }
+ glad.destroy();
+ }
+
+ private class SnapshotGLEL implements GLEventListener {
+ final TextRendererGLEL textRendererGLEL;
+ final GLReadBufferUtil glReadBufferUtil;
+ boolean defAutoSwapMode;
+ boolean swapBuffersBeforeRead;
+ int i;
+
+ SnapshotGLEL(final TextRendererGLEL textRendererGLEL, final GLReadBufferUtil glReadBufferUtil) {
+ this.textRendererGLEL = textRendererGLEL;
+ this.glReadBufferUtil = glReadBufferUtil;
+ this.defAutoSwapMode = true;
+ this.swapBuffersBeforeRead = false;
+ i = 0;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ defAutoSwapMode = drawable.getAutoSwapBufferMode();
+ swapBuffersBeforeRead = GLDrawableUtil.swapBuffersBeforeRead(drawable.getChosenGLCapabilities());
+ drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead );
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ drawable.setAutoSwapBufferMode( defAutoSwapMode );
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ snapshot(i++, drawable, TextureIO.PNG, null);
+ }
+ public void snapshot(final int sn, final GLAutoDrawable drawable, final String fileSuffix, final String destPath) {
+ final GL gl = drawable.getGL();
+ final String postSNDetail = String.format("jgl-usr%03d", textRendererGLEL.userCounter);
+ final String filenameJGL = getSnapshotFilename(sn, postSNDetail,
+ drawable.getChosenGLCapabilities(), drawable.getSurfaceWidth(), drawable.getSurfaceHeight(),
+ glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+ if( swapBuffersBeforeRead ) {
+ drawable.swapBuffers();
+ // Just to test whether we use the right buffer,
+ // i.e. back-buffer shall no more be required ..
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ } else {
+ gl.glFinish(); // just make sure rendering finished ..
+ }
+ final boolean mustFlipVertically = !drawable.isGLOriented();
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: v-flip "+mustFlipVertically+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameJGL);
+
+ if(glReadBufferUtil.readPixels(gl, mustFlipVertically)) {
+ glReadBufferUtil.write(new File(filenameJGL));
+ }
+ }
+ };
+
+ static GLCapabilitiesImmutable caps = null;
+ static boolean doSnapshot = true;
+ static boolean keyFrame = false;
+
+ public static void main(final String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-keyFrame")) {
+ keyFrame = true;
+ } else if(args[i].equals("-noSnapshot")) {
+ doSnapshot = false;
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLWindowNEWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java
new file mode 100644
index 000000000..44c937251
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java
@@ -0,0 +1,204 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import jogamp.opengl.GLVersionNumber;
+
+import com.jogamp.common.util.VersionNumberString;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLVersionParsing00NEWT extends UITestCase {
+
+ public static final String[] glVersionStrings00 = new String[] {
+ "GL_VERSION_2_1 DummyTool 1.2.3", // 0
+ "2.1 Mesa 7.0.3-rc2",
+ "4.2.12171 Compatibility Profile Context 9.01.8",
+ "4.2.12198 Compatibility Profile Context 12.102.3.0",
+ "2.1 Mesa 7.0.3-rc2 post odd",
+ "4.2.12171 Compatibility Profile Context 9.01.8 post odd",
+ "4.2.12198 Compatibility Profile Context 12.102.3.0 post odd",
+ "OpenGL ES 2.0 Mesa 9.1.1", // 7
+ "OpenGL ES 2.0 14.10.1",
+ "OpenGL ES GLSL ES 2.0 14.10.1", // 9
+ "OpenGL ES 2.0 3Com L3 11.33.44" // 10
+ };
+ public static final String[] glVersionStrings01 = new String[] {
+ "GL_VERSION_2_1 Dummy Tool 1.2", // 0
+ "2.1 Mesa 7.12",
+ "2.1 Mesa 7.12-devel",
+ "2.1 Mesa 7.12-devel (git-d6c318e)",
+ "2.1 Mesa 7.12-devel la1 la2 li3",
+ "4.3.0 NVIDIA 310.32",
+ "OpenGL ES 2.0 Mesa 9.1", // 6
+ "OpenGL ES 2.0 14.10",
+ "OpenGL ES GLSL ES 2.0 14.10", // 8
+ "OpenGL ES 2.0 3Com L3 11.33" // 9
+ };
+ public static final String[] glVersionStrings02 = new String[] {
+ "GL_VERSION_2_1", // 0
+ "OpenGL ES 2.0", // 1
+ "OpenGL ES GLSL ES 2.0", // 2
+ "OpenGL 2.1 LaLa", // 3
+ "4.2.11762 Compatibility Profile Context" // 4
+ };
+
+ public static final VersionNumberString[] glVersionNumbers = new VersionNumberString[] {
+ new VersionNumberString(2, 1, 0, glVersionStrings00[0]),
+ new VersionNumberString(2, 1, 0, glVersionStrings00[1]),
+ new VersionNumberString(4, 2, 0, glVersionStrings00[2]),
+ new VersionNumberString(4, 2, 0, glVersionStrings00[3]),
+ new VersionNumberString(2, 1, 0, glVersionStrings00[4]),
+ new VersionNumberString(4, 2, 0, glVersionStrings00[5]),
+ new VersionNumberString(4, 2, 0, glVersionStrings00[6]),
+ new VersionNumberString(2, 0, 0, glVersionStrings00[7]),
+ new VersionNumberString(2, 0, 0, glVersionStrings00[8]),
+ new VersionNumberString(2, 0, 0, glVersionStrings00[9]),
+ new VersionNumberString(2, 0, 0, glVersionStrings00[10]),
+
+ new VersionNumberString(2, 1, 0, glVersionStrings01[0]),
+ new VersionNumberString(2, 1, 0, glVersionStrings01[1]),
+ new VersionNumberString(2, 1, 0, glVersionStrings01[2]),
+ new VersionNumberString(2, 1, 0, glVersionStrings01[3]),
+ new VersionNumberString(2, 1, 0, glVersionStrings01[4]),
+ new VersionNumberString(4, 3, 0, glVersionStrings01[5]),
+ new VersionNumberString(2, 0, 0, glVersionStrings01[6]),
+ new VersionNumberString(2, 0, 0, glVersionStrings01[7]),
+ new VersionNumberString(2, 0, 0, glVersionStrings01[8]),
+ new VersionNumberString(2, 0, 0, glVersionStrings01[9]),
+
+ new VersionNumberString(2, 1, 0, glVersionStrings02[0]),
+ new VersionNumberString(2, 0, 0, glVersionStrings02[1]),
+ new VersionNumberString(2, 0, 0, glVersionStrings02[2]),
+ new VersionNumberString(2, 1, 0, glVersionStrings02[3]),
+ new VersionNumberString(4, 2, 0, glVersionStrings02[4])
+ };
+ public static final VersionNumberString[] glVendorVersionNumbersWithSub = new VersionNumberString[] {
+ new VersionNumberString(1, 2, 3, glVersionStrings00[0]),
+ new VersionNumberString(7, 0, 3, glVersionStrings00[1]),
+ new VersionNumberString(9, 1, 8, glVersionStrings00[2]),
+ new VersionNumberString(12, 102, 3, glVersionStrings00[3]),
+ new VersionNumberString(7, 0, 3, glVersionStrings00[4]),
+ new VersionNumberString(9, 1, 8, glVersionStrings00[5]),
+ new VersionNumberString(12, 102, 3, glVersionStrings00[6]),
+ new VersionNumberString(9, 1, 1, glVersionStrings00[7]),
+ new VersionNumberString(14, 10, 1, glVersionStrings00[8]),
+ new VersionNumberString(14, 10, 1, glVersionStrings00[9]),
+ new VersionNumberString(11, 33, 44, glVersionStrings00[10])
+ };
+ public static final VersionNumberString[] glVendorVersionNumbersNoSub = new VersionNumberString[] {
+ new VersionNumberString(1, 2, 0, glVersionStrings01[0]),
+ new VersionNumberString(7, 12, 0, glVersionStrings01[1]),
+ new VersionNumberString(7, 12, 0, glVersionStrings01[2]),
+ new VersionNumberString(7, 12, 0, glVersionStrings01[3]),
+ new VersionNumberString(7, 12, 0, glVersionStrings01[4]),
+ new VersionNumberString(310, 32, 0, glVersionStrings01[5]),
+ new VersionNumberString(9, 1, 0, glVersionStrings01[6]),
+ new VersionNumberString(14, 10, 0, glVersionStrings01[7]),
+ new VersionNumberString(14, 10, 0, glVersionStrings01[8]),
+ new VersionNumberString(11, 33, 0, glVersionStrings01[9])
+ };
+ public static final VersionNumberString[] glVendorVersionNumbersNone = new VersionNumberString[] {
+ new VersionNumberString(0, 0, 0, glVersionStrings02[0]),
+ new VersionNumberString(0, 0, 0, glVersionStrings02[1]),
+ new VersionNumberString(0, 0, 0, glVersionStrings02[2]),
+ new VersionNumberString(0, 0, 0, glVersionStrings02[3]),
+ new VersionNumberString(0, 0, 0, glVersionStrings02[4])
+ };
+
+ @Test
+ public void test01GLVersion() throws InterruptedException {
+ for(int i=0; i<glVersionNumbers.length; i++) {
+ final VersionNumberString exp = glVersionNumbers[i];
+ final GLVersionNumber has = GLVersionNumber.create(exp.getVersionString());
+ System.err.println("Test["+i+"]: "+exp+" -> "+has+", valid "+has.isValid()+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]");
+ Assert.assertTrue(has.hasMajor());
+ Assert.assertTrue(has.hasMinor());
+ Assert.assertTrue(!has.hasSub());
+ Assert.assertTrue(has.isValid());
+ Assert.assertEquals(exp, has);
+ }
+ {
+ final GLVersionNumber has = GLVersionNumber.create("GL_VERSION_2");
+ System.err.println("Test-X1: "+has+", valid "+has.isValid()+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]");
+ Assert.assertTrue(has.hasMajor());
+ Assert.assertTrue(!has.hasMinor());
+ Assert.assertTrue(!has.hasSub());
+ Assert.assertTrue(!has.isValid());
+ }
+ {
+ final GLVersionNumber has = GLVersionNumber.create("GL2 Buggy L3");
+ System.err.println("Test-X2: "+has+", valid "+has.isValid()+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]");
+ Assert.assertTrue(has.hasMajor());
+ Assert.assertTrue(!has.hasMinor());
+ Assert.assertTrue(!has.hasSub());
+ Assert.assertTrue(!has.isValid());
+ }
+ {
+ final GLVersionNumber has = GLVersionNumber.create("GL Nope");
+ System.err.println("Test-X3: "+has+", valid "+has.isValid()+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]");
+ Assert.assertTrue(!has.hasMajor());
+ Assert.assertTrue(!has.hasMinor());
+ Assert.assertTrue(!has.hasSub());
+ Assert.assertTrue(!has.isValid());
+ }
+ }
+
+ private void testGLVendorVersionImpl(final VersionNumberString[] versionNumberString, final boolean withMajor, final boolean withMinor, final boolean withSub) throws InterruptedException {
+ for(int i=0; i<versionNumberString.length; i++) {
+ final VersionNumberString exp = versionNumberString[i];
+ final VersionNumberString has = GLVersionNumber.createVendorVersion(exp.getVersionString());
+ System.err.println("Test["+withMajor+":"+withMinor+":"+withSub+"]["+i+"]: "+exp+" -> "+has+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]");
+ Assert.assertEquals(withMajor, has.hasMajor());
+ Assert.assertEquals(withMinor, has.hasMinor());
+ Assert.assertEquals(withSub, has.hasSub());
+ Assert.assertEquals(exp, has);
+ }
+ }
+
+ @Test
+ public void test02GLVendorVersion() throws InterruptedException {
+ testGLVendorVersionImpl(glVendorVersionNumbersWithSub, true, true, true);
+ testGLVendorVersionImpl(glVendorVersionNumbersNoSub, true, true, false);
+ testGLVendorVersionImpl(glVendorVersionNumbersNone, false, false, false);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestGLVersionParsing00NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java
index bebe3531e..aabd4821d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java
@@ -36,6 +36,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLDrawable;
@@ -44,130 +45,137 @@ import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGPUMemSec01NEWT extends UITestCase {
- static String hexString(int i) {
+ static String hexString(final int i) {
return "0x"+Integer.toHexString(i);
}
- static String exceptionMsg(String pre, int format, int type, int components, int width, int height, int rl1, int rl4, int rl8) {
- return pre +
+ static String exceptionMsg(final String pre, final int format, final int type, final int components, final int width, final int height, final int rl1, final int rl4, final int rl8) {
+ return pre +
": fmt "+hexString(format)+", type "+hexString(type)+", comps "+components+
", "+width+"x"+height+
- ", rowlenA1 "+rl1+", rowlenA4 "+rl4+", rowlenA8 "+rl8;
+ ", rowlenA1 "+rl1+", rowlenA4 "+rl4+", rowlenA8 "+rl8;
}
-
- static NEWTGLContext.WindowContext createCurrentGLOffscreenWindow(GLProfile glp, int width, int height) throws GLException, InterruptedException {
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOffscreenWindow(
- new GLCapabilities(glp), width, height, true);
+
+ static NEWTGLContext.WindowContext createCurrentGLOffscreenWindow(final GLProfile glp, final int width, final int height) throws GLException, InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setOnscreen(false);
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(
+ caps, width, height, true);
final GL gl = winctx.context.getGL();
+ // System.err.println("Pre GL Error: 0x"+Integer.toHexString(gl.glGetError()));
+ // System.err.println(winctx.drawable);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
// misc GL setup
gl.glClearColor(1, 1, 1, 1);
gl.glEnable(GL.GL_DEPTH_TEST);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- gl.glViewport(0, 0, width, height);
+ gl.glViewport(0, 0, width, height);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
return winctx;
}
-
- static int readPixelsCheck(GL gl, int format, int type, int components, int width, int height) throws InterruptedException {
+
+ static int readPixelsCheck(final GL gl, final int format, final int type, final int components, final int width, final int height) throws InterruptedException {
int expectedExceptions = 0;
-
- final int rowlenA1 = width * components;
-
- final int rowlenA4 = ( ( width * components + 3 ) / 4 ) * 4 ;
+
+ final int rowlenA1 = width * components;
+
+ final int rowlenA4 = ( ( width * components + 3 ) / 4 ) * 4 ;
Assert.assertTrue(rowlenA4 % 4 == 0);
final int rowlenA8 = ( ( width * components + 7 ) / 8 ) * 8 ;
Assert.assertTrue(rowlenA8 % 8 == 0);
-
- GLPixelStorageModes psm = new GLPixelStorageModes();
+
+ final GLPixelStorageModes psm = new GLPixelStorageModes();
psm.setPackAlignment(gl, 1);
-
+
Exception ee = null;
-
+
// ok size !
try {
- ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1);
+ final ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1);
gl.glReadPixels(0, 0, width, height, format, type, bb);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- } catch(IndexOutOfBoundsException e) {
+ } catch(final IndexOutOfBoundsException e) {
ee = e;
}
Assert.assertNull(
- exceptionMsg("Unexpected IndexOutOfBoundsException (size ok, alignment 1)",
+ exceptionMsg("Unexpected IndexOutOfBoundsException (size ok, alignment 1)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
ee = null;
-
-
+
+
// too small -10 !
try {
- ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1-10);
+ final ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1-10);
gl.glReadPixels(0, 0, width, height, format, type, bb);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- } catch(IndexOutOfBoundsException e) {
+ } catch(final IndexOutOfBoundsException e) {
ee = e;
System.err.println(
- exceptionMsg("OK Expected IndexOutOfBoundsException (size-10 bytes)",
+ exceptionMsg("OK Expected IndexOutOfBoundsException (size-10 bytes)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8)+
": "+ee.getMessage());
- expectedExceptions++;
+ expectedExceptions++;
}
Assert.assertNotNull(
- exceptionMsg("Expected IndexOutOfBoundsException (size-10 bytes)",
+ exceptionMsg("Expected IndexOutOfBoundsException (size-10 bytes)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
ee = null;
-
+
// too small size/4 !
try {
- ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1/4);
+ final ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1/4);
gl.glReadPixels(0, 0, width, height, format, type, bb);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- } catch(IndexOutOfBoundsException e) {
+ } catch(final IndexOutOfBoundsException e) {
ee = e;
System.err.println(
- exceptionMsg("OK Expected IndexOutOfBoundsException (size/4 bytes)",
+ exceptionMsg("OK Expected IndexOutOfBoundsException (size/4 bytes)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8)+
": "+ee.getMessage());
- expectedExceptions++;
+ expectedExceptions++;
}
Assert.assertNotNull(
- exceptionMsg("Expected IndexOutOfBoundsException (size/4 bytes)",
+ exceptionMsg("Expected IndexOutOfBoundsException (size/4 bytes)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
ee = null;
//
// Alignment test
- //
+ //
psm.setPackAlignment(gl, 4);
-
+
// ok size !
try {
- ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA4);
+ final ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA4);
gl.glReadPixels(0, 0, width, height, format, type, bb);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- } catch(IndexOutOfBoundsException e) {
+ } catch(final IndexOutOfBoundsException e) {
ee = e;
}
Assert.assertNull(
- exceptionMsg("Unexpected IndexOutOfBoundsException (size ok, alignment 4)",
+ exceptionMsg("Unexpected IndexOutOfBoundsException (size ok, alignment 4)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
ee = null;
-
+
// too small if rowlenA1%4 > 0
try {
- ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1);
+ final ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1);
gl.glReadPixels(0, 0, width, height, format, type, bb);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- } catch(IndexOutOfBoundsException e) {
+ } catch(final IndexOutOfBoundsException e) {
ee = e;
if(rowlenA1%4>0) {
System.err.println(
- exceptionMsg("OK Expected IndexOutOfBoundsException (alignment 4)",
+ exceptionMsg("OK Expected IndexOutOfBoundsException (alignment 4)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8)+
": "+ee.getMessage());
expectedExceptions++;
@@ -175,40 +183,40 @@ public class TestGPUMemSec01NEWT extends UITestCase {
}
if(rowlenA1%4>0) {
Assert.assertNotNull(
- exceptionMsg("Expected IndexOutOfBoundsException (alignment 4)",
+ exceptionMsg("Expected IndexOutOfBoundsException (alignment 4)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
} else {
Assert.assertNull(
- exceptionMsg("Unexpected IndexOutOfBoundsException (alignment 4)",
- format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ exceptionMsg("Unexpected IndexOutOfBoundsException (alignment 4)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
}
ee = null;
-
+
psm.setPackAlignment(gl, 8);
-
+
// ok size !
try {
- ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA8);
+ final ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA8);
gl.glReadPixels(0, 0, width, height, format, type, bb);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- } catch(IndexOutOfBoundsException e) {
+ } catch(final IndexOutOfBoundsException e) {
ee = e;
}
Assert.assertNull(
- exceptionMsg("Unexpected IndexOutOfBoundsException (size ok, alignment 8)",
+ exceptionMsg("Unexpected IndexOutOfBoundsException (size ok, alignment 8)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
ee = null;
-
+
// too small if rowlenA1%8 > 0
try {
- ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1);
+ final ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1);
gl.glReadPixels(0, 0, width, height, format, type, bb);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- } catch(IndexOutOfBoundsException e) {
+ } catch(final IndexOutOfBoundsException e) {
ee = e;
if(rowlenA1%8>0) {
System.err.println(
- exceptionMsg("OK Expected IndexOutOfBoundsException (alignment 8)",
+ exceptionMsg("OK Expected IndexOutOfBoundsException (alignment 8)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8)+
": "+ee.getMessage());
expectedExceptions++;
@@ -216,117 +224,117 @@ public class TestGPUMemSec01NEWT extends UITestCase {
}
if(rowlenA1%8>0) {
Assert.assertNotNull(
- exceptionMsg("Expected IndexOutOfBoundsException (alignment 8)",
+ exceptionMsg("Expected IndexOutOfBoundsException (alignment 8)",
format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
} else {
Assert.assertNull(
- exceptionMsg("Unexpected IndexOutOfBoundsException (alignment 8)",
- format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ exceptionMsg("Unexpected IndexOutOfBoundsException (alignment 8)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
}
ee = null;
-
- psm.restore(gl);
-
- return expectedExceptions;
+
+ psm.restore(gl);
+
+ return expectedExceptions;
}
-
+
@Test
public void testReadPixelsGL_640x480xRGBAxUB() throws InterruptedException {
- GLProfile glp = GLProfile.getDefault();
+ final GLProfile glp = GLProfile.getDefault();
final int width = 640;
final int height= 480;
-
+
// preset ..
final NEWTGLContext.WindowContext winctx = createCurrentGLOffscreenWindow(glp, width, height);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL gl = winctx.context.getGL();
-
+
// 2 x too small - 0 x alignment
Assert.assertEquals(2, readPixelsCheck(gl, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, 4, width, height));
-
+
drawable.swapBuffers();
Thread.sleep(50);
-
+
NEWTGLContext.destroyWindow(winctx);
}
-
+
@Test
public void testReadPixelsGL_99x100xRGBxUB() throws InterruptedException {
- GLProfile glp = GLProfile.getGL2ES2();
+ final GLProfile glp = GLProfile.getGL2ES2();
final int wwidth = 640;
final int wheight= 480;
final int rwidth = 99;
final int rheight= 100;
-
+
// preset ..
final NEWTGLContext.WindowContext winctx = createCurrentGLOffscreenWindow(glp, wwidth, wheight);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL gl = winctx.context.getGL();
-
+
// 2 x too small - 1 x alignment
Assert.assertEquals(3, readPixelsCheck(gl, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, 4, rwidth, rheight));
-
+
drawable.swapBuffers();
Thread.sleep(50);
-
+
NEWTGLContext.destroyWindow(winctx);
}
-
+
@Test
public void testReadPixelsGL2GL3_640x480xRGBxUB() throws InterruptedException {
- GLProfile glp = GLProfile.getGL2ES2();
- if(!glp.isGL2GL3()) {
- System.err.println("GL2GL3 n/a skip test");
+ final GLProfile glp = GLProfile.getGL2ES2();
+ if(!glp.isGL2ES3()) {
+ System.err.println("GL2ES3 n/a skip test");
return;
}
final int width = 640;
final int height= 480;
-
+
// preset ..
final NEWTGLContext.WindowContext winctx = createCurrentGLOffscreenWindow(glp, width, height);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL gl = winctx.context.getGL();
-
+
// 2 x too small - 0 x alignment
Assert.assertEquals(2, readPixelsCheck(gl, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, 3, width, height));
-
+
drawable.swapBuffers();
Thread.sleep(50);
-
+
NEWTGLContext.destroyWindow(winctx);
}
-
+
@Test
public void testReadPixelsGL2GL3_99x100xRGBxUB() throws InterruptedException {
- GLProfile glp = GLProfile.getGL2ES2();
- if(!glp.isGL2GL3()) {
- System.err.println("GL2GL3 n/a skip test");
+ final GLProfile glp = GLProfile.getGL2ES2();
+ if(!glp.isGL2ES3()) {
+ System.err.println("GL2ES3 n/a skip test");
return;
}
final int wwidth = 640;
final int wheight= 480;
final int rwidth = 99;
final int rheight= 100;
-
+
// preset ..
final NEWTGLContext.WindowContext winctx = createCurrentGLOffscreenWindow(glp, wwidth, wheight);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL gl = winctx.context.getGL();
-
+
// 2 x too small - 2 x alignment
Assert.assertEquals(4, readPixelsCheck(gl, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, 3, rwidth, rheight));
-
+
drawable.swapBuffers();
Thread.sleep(50);
-
+
NEWTGLContext.destroyWindow(winctx);
}
-
+
@Test
public void testReadPixelsGL2GL3_640x480xREDxUB() throws InterruptedException {
- GLProfile glp = GLProfile.getGL2ES2();
- if(!glp.isGL2GL3()) {
- System.err.println("GL2GL3 n/a skip test");
+ final GLProfile glp = GLProfile.getGL2ES2();
+ if(!glp.isGL2ES3()) {
+ System.err.println("GL2ES3 n/a skip test");
return;
}
final int width = 640;
@@ -336,45 +344,45 @@ public class TestGPUMemSec01NEWT extends UITestCase {
final NEWTGLContext.WindowContext winctx = createCurrentGLOffscreenWindow(glp, width, height);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL2GL3 gl = winctx.context.getGL().getGL2GL3();
-
+
// 2 x too small - 0 x alignment
- Assert.assertEquals(2, readPixelsCheck(gl, GL2GL3.GL_RED, GL.GL_UNSIGNED_BYTE, 1, width, height));
-
+ Assert.assertEquals(2, readPixelsCheck(gl, GL2ES2.GL_RED, GL.GL_UNSIGNED_BYTE, 1, width, height));
+
drawable.swapBuffers();
Thread.sleep(50);
-
+
NEWTGLContext.destroyWindow(winctx);
}
@Test
public void testReadPixelsGL2GL3_102x100xREDxUB() throws InterruptedException {
- GLProfile glp = GLProfile.getGL2ES2();
- if(!glp.isGL2GL3()) {
- System.err.println("GL2GL3 n/a skip test");
+ final GLProfile glp = GLProfile.getGL2ES2();
+ if(!glp.isGL2ES3()) {
+ System.err.println("GL2ES3 n/a skip test");
return;
}
- int wwidth = 640;
- int wheight= 480;
- int rwidth = 102;
- int rheight= 100;
+ final int wwidth = 640;
+ final int wheight= 480;
+ final int rwidth = 102;
+ final int rheight= 100;
// preset ..
final NEWTGLContext.WindowContext winctx = createCurrentGLOffscreenWindow(glp, wwidth, wheight);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL2GL3 gl = winctx.context.getGL().getGL2GL3();
-
+
// 2 x too small - 2 x alignment
- Assert.assertEquals(4, readPixelsCheck(gl, GL2GL3.GL_RED, GL.GL_UNSIGNED_BYTE, 1, rwidth, rheight));
-
+ Assert.assertEquals(4, readPixelsCheck(gl, GL2ES2.GL_RED, GL.GL_UNSIGNED_BYTE, 1, rwidth, rheight));
+
drawable.swapBuffers();
Thread.sleep(50);
-
+
NEWTGLContext.destroyWindow(winctx);
}
-
- public static void main(String args[]) throws IOException {
- String tstname = TestGPUMemSec01NEWT.class.getName();
+
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestGPUMemSec01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
new file mode 100644
index 000000000..a3c5d44cd
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
@@ -0,0 +1,88 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLProfile;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+
+/**
+ * Concurrent initialization and lock-free rendering using shared NEWT Display EDT instances.
+ * <p>
+ * Rendering is always lock-free and independent of the EDT, however shared NEWT Display instances
+ * perform lifecycle actions (window creation etc) with locking.
+ * </p>
+ * <p>
+ * Each test is decorated w/ {@link GLProfile#shutdown()} to ensure that
+ * implicit {@link GLProfile#initSingleton()} is also being tested.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestInitConcurrent01NEWT extends InitConcurrentBaseNEWT {
+
+ @Test(timeout=180000) // TO 3 min
+ public void test02TwoThreads() throws InterruptedException {
+ runJOGLTasks(2, true);
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test04FourThreads() throws InterruptedException {
+ runJOGLTasks(4, true);
+ }
+
+ @Test(timeout=300000) // TO 5 min
+ public void test16SixteenThreads() throws InterruptedException {
+ if( Platform.getCPUFamily() != Platform.CPUFamily.ARM &&
+ Platform.getOSType() != Platform.OSType.WINDOWS ) {
+ runJOGLTasks(16, true);
+ } else {
+ runJOGLTasks( 6, true);
+ }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ final String tstname = TestInitConcurrent01NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java
new file mode 100644
index 000000000..5cbf15b57
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java
@@ -0,0 +1,104 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLProfile;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+
+/**
+ * Concurrent and lock-free initialization and rendering using exclusive NEWT Display EDT instances.
+ * <p>
+ * Rendering is always lock-free and independent of the EDT, using exclusive NEWT Display instances
+ * perform lifecycle actions (window creation etc) w/o locking.
+ * </p>
+ * <p>
+ * Each test is decorated w/ {@link GLProfile#shutdown()} to ensure that
+ * implicit {@link GLProfile#initSingleton()} is also being tested.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestInitConcurrent02NEWT extends InitConcurrentBaseNEWT {
+ static boolean mainRun = false;
+
+ @Test(timeout=180000) // TO 3 min
+ public void test02TwoThreads() throws InterruptedException {
+ if(!mainRun) {
+ System.err.println("Disabled for auto unit test until further analysis - Windows/ATI driver crash");
+ return;
+ }
+ runJOGLTasks(2, false);
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test02FourThreads() throws InterruptedException {
+ if(!mainRun) {
+ System.err.println("Disabled for auto unit test until further analysis - Windows/ATI driver crash");
+ return;
+ }
+ runJOGLTasks(4, false);
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test16SixteenThreads() throws InterruptedException {
+ if(!mainRun) {
+ System.err.println("Disabled for auto unit test until further analysis - Windows/ATI driver crash");
+ return;
+ }
+ if( Platform.getCPUFamily() != Platform.CPUFamily.ARM &&
+ Platform.getOSType() != Platform.OSType.WINDOWS ) {
+ runJOGLTasks(16, false);
+ } else {
+ runJOGLTasks( 6, false);
+ }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ mainRun = true;
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-normalRun")) {
+ mainRun = false;
+ } else if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ final String tstname = TestInitConcurrent02NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLCanvasAWT.java
index 5523ce5ce..6395c1446 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLCanvasAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLCanvasAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
@@ -33,19 +33,22 @@ import java.io.IOException;
import javax.media.opengl.awt.GLCanvas;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestMainVersionGLCanvasAWT extends UITestCase {
@Test
public void testMain() throws InterruptedException {
- GLCanvas.main(null);
+ GLCanvas.main(new String[0]);
}
- public static void main(String args[]) throws IOException {
- String tstname = TestMainVersionGLCanvasAWT.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestMainVersionGLCanvasAWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLWindowNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLWindowNEWT.java
index d178e34f4..3b9a8c97a 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLWindowNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLWindowNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,30 +20,41 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestMainVersionGLWindowNEWT extends UITestCase {
+ private static String[] args = null;
@Test
public void testMain() throws InterruptedException {
- GLWindow.main(null);
+ final JoglVersion j = JoglVersion.getInstance();
+ System.out.println("Implementation-Version: "+j.getImplementationVersion());
+ System.out.println("Implementation-Build: "+j.getImplementationBuild());
+ System.out.println("Implementation-Branch: "+j.getImplementationBranch());
+ System.out.println("Implementation-Commit: "+j.getImplementationCommit());
+ GLWindow.main(args);
}
- public static void main(String args[]) throws IOException {
- String tstname = TestMainVersionGLWindowNEWT.class.getName();
+ public static void main(final String[] args) throws IOException {
+ TestMainVersionGLWindowNEWT.args = args;
+ final String tstname = TestMainVersionGLWindowNEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java
index 158c2aa90..5ba0c7794 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java
@@ -36,88 +36,145 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLBufferStorage;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/**
+ * Verifies content of buffer storage's content
+ * as well as general buffer- and buffer-storage tracking.
*
* @author Luz, et.al.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestMapBufferRead01NEWT extends UITestCase {
static final boolean DEBUG = false;
-
+
@Test
- public void testWriteRead01a() throws InterruptedException {
+ public void testWriteRead01aMap() throws InterruptedException {
if(!GLProfile.isAvailable(GLProfile.GL2GL3)) {
System.err.println("Test requires GL2/GL3 profile.");
return;
}
- ByteBuffer verticiesBB = ByteBuffer.allocate(4*9);
+ final ByteBuffer verticiesBB = ByteBuffer.allocate(4*9);
verticiesBB.order(ByteOrder.nativeOrder());
- testWriteRead01(verticiesBB);
+ testWriteRead01(verticiesBB, false /* useRange */);
}
@Test
- public void testWriteRead01b() throws InterruptedException {
+ public void testWriteRead01bMap() throws InterruptedException {
if(!GLProfile.isAvailable(GLProfile.GL2GL3)) {
System.err.println("Test requires GL2/GL3 profile.");
return;
}
- ByteBuffer verticiesBB = Buffers.newDirectByteBuffer(4*9);
- testWriteRead01(verticiesBB);
+ final ByteBuffer verticiesBB = Buffers.newDirectByteBuffer(4*9);
+ testWriteRead01(verticiesBB, false /* useRange */);
}
- private void testWriteRead01(ByteBuffer verticiesBB) throws InterruptedException {
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOffscreenWindow(
- new GLCapabilities(GLProfile.getGL2GL3()), 800, 600, true);
- final GL gl = winctx.context.getGL();
-
- int[] vertexBuffer = new int[1];
-
- verticiesBB.putFloat(0);
- verticiesBB.putFloat(0.5f);
- verticiesBB.putFloat(0);
-
- verticiesBB.putFloat(0.5f);
- verticiesBB.putFloat(-0.5f);
- verticiesBB.putFloat(0);
-
- verticiesBB.putFloat(-0.5f);
- verticiesBB.putFloat(-0.5f);
- verticiesBB.putFloat(0);
- verticiesBB.rewind();
- if(DEBUG) {
- for(int i=0; i < verticiesBB.capacity(); i+=4) {
- System.out.println("java "+i+": "+verticiesBB.getFloat(i));
- }
+ @Test
+ public void testWriteRead02aMapRange() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL3) && !!GLProfile.isAvailable(GLProfile.GLES3)) {
+ System.err.println("Test requires GL3 or GLES3 profile.");
+ return;
+ }
+ final ByteBuffer verticiesBB = ByteBuffer.allocate(4*9);
+ verticiesBB.order(ByteOrder.nativeOrder());
+ testWriteRead01(verticiesBB, true/* useRange */);
+ }
+ @Test
+ public void testWriteRead02bMapRange() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL3) && !!GLProfile.isAvailable(GLProfile.GLES3)) {
+ System.err.println("Test requires GL3 or GLES3 profile.");
+ return;
}
+ final ByteBuffer verticiesBB = Buffers.newDirectByteBuffer(4*9);
+ testWriteRead01(verticiesBB, true /* useRange */);
+ }
+
+ private void testWriteRead01(final ByteBuffer verticiesBB, final boolean useRange) throws InterruptedException {
+ final GLProfile glp = GLProfile.getMaxProgrammable(true);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setOnscreen(false);
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(
+ caps, 800, 600, true);
+ try {
+ final GL gl = winctx.context.getGL();
+
+ final int[] vertexBuffer = new int[1];
- gl.glGenBuffers(1, vertexBuffer, 0);
+ verticiesBB.putFloat(-0.3f);
+ verticiesBB.putFloat(-0.2f);
+ verticiesBB.putFloat(-0.1f);
- gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBuffer[0]);
+ verticiesBB.putFloat(0.1f);
+ verticiesBB.putFloat(0.2f);
+ verticiesBB.putFloat(0.3f);
- // gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_READ);
- gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_DRAW);
-
- ByteBuffer bb = gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL2GL3.GL_READ_ONLY);
- Assert.assertNotNull(bb);
-
- if(DEBUG) {
+ verticiesBB.putFloat(0.4f);
+ verticiesBB.putFloat(0.5f);
+ verticiesBB.putFloat(0.6f);
+ verticiesBB.rewind();
+ if(DEBUG) {
+ for(int i=0; i < verticiesBB.capacity(); i+=4) {
+ System.err.println("java "+i+": "+verticiesBB.getFloat(i));
+ }
+ }
+
+ gl.glGenBuffers(1, vertexBuffer, 0);
+
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBuffer[0]);
+
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL2ES3.GL_STATIC_READ);
+ // gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_DRAW);
+
+ final int bufferName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER);
+ final GLBufferStorage bufferStorage = gl.getBufferStorage(bufferName);
+ System.err.println("gpu-01 GL_ARRAY_BUFFER -> bufferName "+bufferName+" -> "+bufferStorage);
+ Assert.assertEquals("Buffer storage's bytes-buffer not null before map", null, bufferStorage.getMappedBuffer());
+
+ final int floatOffset, byteOffset, mapByteLength;
+ final ByteBuffer bb;
+ if( useRange ) {
+ floatOffset = 3;
+ byteOffset = Buffers.SIZEOF_FLOAT*floatOffset;
+ mapByteLength = verticiesBB.capacity()-byteOffset;
+ bb = gl.glMapBufferRange(GL.GL_ARRAY_BUFFER, byteOffset, mapByteLength, GL.GL_MAP_READ_BIT);
+ } else {
+ floatOffset = 0;
+ byteOffset = 0;
+ mapByteLength = verticiesBB.capacity();
+ bb = gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL2GL3.GL_READ_ONLY);
+ }
+ System.err.println("gpu-02 mapped GL_ARRAY_BUFFER, floatOffset "+floatOffset+", byteOffset "+byteOffset+", mapByteLength "+mapByteLength+" -> "+bb);
+ System.err.println("gpu-03 GL_ARRAY_BUFFER -> bufferName "+bufferName+" -> "+bufferStorage);
+ Assert.assertNotNull(bb);
+ Assert.assertEquals("BufferStorage size less byteOffset not equals buffer storage size", bufferStorage.getSize()-byteOffset, bb.capacity());
+ Assert.assertEquals("BufferStorage's bytes-buffer not equal with mapped bytes-buffer", bufferStorage.getMappedBuffer(), bb);
+ Assert.assertEquals("Buffer storage size not equals mapByteLength", mapByteLength, bb.capacity());
+
+ if(DEBUG) {
+ System.err.println("floatOffset "+floatOffset+", byteOffset "+byteOffset);
+ for(int i=0; i < bb.capacity(); i+=4) {
+ System.err.println("gpu "+i+": "+bb.getFloat(i));
+ }
+ }
for(int i=0; i < bb.capacity(); i+=4) {
- System.out.println("gpu "+i+": "+bb.getFloat(i));
+ Assert.assertEquals(verticiesBB.getFloat(byteOffset+i), bb.getFloat(i), 0.0001f);
}
+ gl.glUnmapBuffer(GL.GL_ARRAY_BUFFER);
+ Assert.assertEquals("Buffer storage's bytes-buffer not null after unmap", null, bufferStorage.getMappedBuffer());
+ } finally {
+ NEWTGLContext.destroyWindow(winctx);
}
- for(int i=0; i < bb.capacity(); i+=4) {
- Assert.assertEquals(verticiesBB.getFloat(i), bb.getFloat(i), 0.0);
- }
- gl.glUnmapBuffer(GL.GL_ARRAY_BUFFER);
- NEWTGLContext.destroyWindow(winctx);
}
- public static void main(String args[]) throws IOException {
- String tstname = TestMapBufferRead01NEWT.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestMapBufferRead01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java
index c1b7464e7..a0e846d7d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java
@@ -1,42 +1,45 @@
package com.jogamp.opengl.test.junit.jogl.acore;
import jogamp.nativewindow.x11.X11Util;
+
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.opengl.GLWindow;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
+import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLOffscreenAutoDrawable;
-import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;
/**
- * Tests the closing the device of GLWindow and GLPBuffer in JOGL
+ * Tests the closing the device of GLWindow and off-screen GLAutoDrawable using FBO and PBuffer in JOGL
*/
-@SuppressWarnings("deprecation")
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestNEWTCloseX11DisplayBug565 {
@Test
- public void testX11WindowMemoryLeak() throws Exception {
+ public void test01X11WindowMemoryLeak() throws Exception {
GLProfile.initSingleton(); // ensure shared resource runner is done
try {
for ( int j = 0; j < 10; j++ ) {
final int open0;
- if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
+ if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
open0 = X11Util.getOpenDisplayConnectionNumber();
} else {
open0 = 0;
}
-
- GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault( ) );
-
- GLWindow window = GLWindow.create(caps);
- window.setTitle("NEWT Resource X11 Leak - #" + j );
+
+ final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault( ) );
+
+ final GLWindow window = GLWindow.create(caps);
+ window.setTitle("NEWT Resource X11 Leak - #" + j );
window.setSize( 128, 128 );
window.setVisible(true);
window.display();
@@ -53,7 +56,7 @@ public class TestNEWTCloseX11DisplayBug565 {
}
}
}
- catch ( Exception e ) {
+ catch ( final Exception e ) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
@@ -61,28 +64,20 @@ public class TestNEWTCloseX11DisplayBug565 {
@Test
- public void testX11WindowMemoryLeakGLPbuffer() throws Exception {
+ public void test02X11WindowMemoryLeakPBufferAutoDrawable() throws Exception {
GLProfile.initSingleton(); // ensure shared resource runner is done
try {
for ( int j = 0; j < 10; j++ ) {
final int open0;
- if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
+ if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
open0 = X11Util.getOpenDisplayConnectionNumber();
} else {
open0 = 0;
}
final GLProfile glp = GLProfile.getDefault( );
- GLCapabilitiesImmutable caps = new GLCapabilities( glp );
-
-
- GLPbuffer buffer = GLDrawableFactory.getFactory( glp ).createGLPbuffer(
- null,
- caps,
- new DefaultGLCapabilitiesChooser(),
- 256,
- 256,
- null
- );
+ final GLCapabilities caps = new GLCapabilities( glp );
+ caps.setPBuffer(true);
+ final GLAutoDrawable buffer = GLDrawableFactory.getFactory( glp ).createOffscreenAutoDrawable(null, caps, null, 256, 256);
buffer.display();
buffer.destroy();
@@ -96,35 +91,29 @@ public class TestNEWTCloseX11DisplayBug565 {
}
}
}
- catch ( Exception e ) {
+ catch ( final Exception e ) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
@Test
- public void testX11WindowMemoryLeakFBOAutoDrawable() throws Exception {
+ public void test03X11WindowMemoryLeakFBOAutoDrawable() throws Exception {
GLProfile.initSingleton(); // ensure shared resource runner is done
try {
for ( int j = 0; j < 10; j++ ) {
final int open0;
- if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
+ if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) {
open0 = X11Util.getOpenDisplayConnectionNumber();
} else {
open0 = 0;
}
final GLProfile glp = GLProfile.getDefault( );
- GLCapabilitiesImmutable caps = new GLCapabilities( glp );
+ final GLCapabilitiesImmutable caps = new GLCapabilities( glp );
- GLOffscreenAutoDrawable buffer = GLDrawableFactory.getFactory( glp ).createOffscreenAutoDrawable(
- null,
- caps,
- new DefaultGLCapabilitiesChooser(),
- 256,
- 256,
- null
- );
+ final GLOffscreenAutoDrawable buffer = GLDrawableFactory.getFactory( glp ).createOffscreenAutoDrawable(
+ null, caps, new DefaultGLCapabilitiesChooser(), 256, 256);
buffer.display();
buffer.destroy();
@@ -138,15 +127,15 @@ public class TestNEWTCloseX11DisplayBug565 {
}
}
}
- catch ( Exception e ) {
+ catch ( final Exception e ) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
-
- public static void main(String args[]) {
+
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestNEWTCloseX11DisplayBug565.class.getName());
}
-
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNVSwapGroupNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNVSwapGroupNEWT.java
index 54f99433c..b0c6bd670 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNVSwapGroupNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNVSwapGroupNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import com.jogamp.newt.opengl.GLWindow;
@@ -44,7 +44,10 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestNVSwapGroupNEWT extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
@@ -60,31 +63,31 @@ public class TestNVSwapGroupNEWT extends UITestCase {
height = 256;
}
- protected GLWindow runTestGL(Animator animator, int x, int y, final int group, final int barrier) {
- GLWindow glWindow = GLWindow.create(caps);
+ protected GLWindow runTestGL(final Animator animator, final int x, final int y, final int group, final int barrier) {
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y);
glWindow.setSize(width, height);
- GearsES2 gears = new GearsES2(1);
+ final GearsES2 gears = new GearsES2(1);
glWindow.addGLEventListener(new GLEventListener() {
- public void init(GLAutoDrawable drawable) {
- int[] maxVals = new int[] { -1, -1 } ;
- GLContext glc = drawable.getContext();
- boolean r = glc.queryMaxSwapGroups(maxVals, 0, maxVals, 1);
+ public void init(final GLAutoDrawable drawable) {
+ final int[] maxVals = new int[] { -1, -1 } ;
+ final GLContext glc = drawable.getContext();
+ final boolean r = glc.queryMaxSwapGroups(maxVals, 0, maxVals, 1);
System.err.println("swap group max groups "+maxVals[0]+", barriers "+maxVals[0]+", "+r);
if(maxVals[0]>=group) {
System.err.println("swap group joing 1: "+glc.joinSwapGroup(group));
if(maxVals[1]>=barrier) {
System.err.println("swap group bind 1-1: "+glc.bindSwapBarrier(group, barrier));
}
- }
+ }
}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {}
- public void reshape(GLAutoDrawable drawable, int x, int y,
- int width, int height) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {}
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y,
+ final int width, final int height) {}
});
glWindow.addGLEventListener(gears);
@@ -102,14 +105,14 @@ public class TestNVSwapGroupNEWT extends UITestCase {
@Test
public void test01() throws InterruptedException {
// make sure it won't be active for now !
- int swap_group = 9999;
- int swap_barrier = 9999;
-
- Animator animator = new Animator();
- GLWindow f1 = runTestGL(animator, 0, 0, swap_group, swap_barrier);
- InsetsImmutable insets = f1.getInsets();
- GLWindow f2 = runTestGL(animator, width+insets.getTotalWidth(), 0, swap_group, swap_barrier);
- animator.setUpdateFPSFrames(1, null);
+ final int swap_group = 9999;
+ final int swap_barrier = 9999;
+
+ final Animator animator = new Animator();
+ final GLWindow f1 = runTestGL(animator, 0, 0, swap_group, swap_barrier);
+ final InsetsImmutable insets = f1.getInsets();
+ final GLWindow f2 = runTestGL(animator, width+insets.getTotalWidth(), 0, swap_group, swap_barrier);
+ animator.setUpdateFPSFrames(1, null);
animator.start();
while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
@@ -125,13 +128,13 @@ public class TestNVSwapGroupNEWT extends UITestCase {
static long duration = 500; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
}
org.junit.runner.JUnitCore.main(TestNVSwapGroupNEWT.class.getName());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java
index 3c9afbd2f..f96886712 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.awt.BorderLayout;
@@ -33,14 +33,13 @@ import java.awt.Button;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import jogamp.nativewindow.jawt.JAWTUtil;
@@ -48,6 +47,8 @@ import jogamp.nativewindow.jawt.JAWTUtil;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.os.Platform;
import com.jogamp.newt.Window;
@@ -58,7 +59,9 @@ import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
+ static boolean singleBuffer = false;
static boolean useMSAA = false;
static boolean addComp = true;
static int swapInterval = 1;
@@ -68,6 +71,7 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
static Dimension frameSize1;
static Dimension preferredGLSize;
static long durationPerTest = 1000;
+ static boolean waitForKey = false;
@BeforeClass
public static void initClass() {
@@ -76,32 +80,32 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
preferredGLSize = new Dimension(400,200);
}
- private void setupFrameAndShow(final Frame f, java.awt.Component comp) throws InterruptedException, InvocationTargetException {
-
- Container c = new Container();
+ private void setupFrameAndShow(final Frame f, final java.awt.Component comp) throws InterruptedException, InvocationTargetException {
+
+ final Container c = new Container();
c.setLayout(new BorderLayout());
c.add(new Button("north"), BorderLayout.NORTH);
c.add(new Button("south"), BorderLayout.SOUTH);
c.add(new Button("east"), BorderLayout.EAST);
c.add(new Button("west"), BorderLayout.WEST);
c.add(comp, BorderLayout.CENTER);
-
+
f.setLayout(new BorderLayout());
f.add(new Button("NORTH"), BorderLayout.NORTH);
f.add(new Button("SOUTH"), BorderLayout.SOUTH);
f.add(new Button("EAST"), BorderLayout.EAST);
f.add(new Button("WEST"), BorderLayout.WEST);
f.add(c, BorderLayout.CENTER);
-
+
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
f.pack();
f.validate();
f.setVisible(true);
- }});
+ }});
}
-
- private void end(GLAnimatorControl actrl, final Frame f, Window w) throws InterruptedException, InvocationTargetException {
+
+ private void end(final GLAnimatorControl actrl, final Frame f, final Window w) throws InterruptedException, InvocationTargetException {
actrl.stop();
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -115,28 +119,36 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
@Test
public void testInfo00() throws InterruptedException, InvocationTargetException {
System.err.println("Java Version: "+Platform.getJavaVersionNumber());
- System.err.println("OS Version: "+Platform.getOSVersionNumber());
+ System.err.println("OS Version: "+Platform.getOSVersionNumber());
System.err.println("JAWTUtil.isOffscreenLayerRequired(): "+JAWTUtil.isOffscreenLayerRequired());
System.err.println("JAWTUtil.isOffscreenLayerSupported(): "+JAWTUtil.isOffscreenLayerSupported());
}
-
+
@Test
- public void testOffscreenLayerGLCanvas_OffscreenLayerWithOnscreenClass() throws InterruptedException, InvocationTargetException {
- testOffscreenLayerGLCanvas_Impl(true);
+ public void test01_GLDefault() throws InterruptedException, InvocationTargetException {
+ testOffscreenLayerGLCanvas_Impl(null);
}
-
- private void testOffscreenLayerGLCanvas_Impl(boolean offscreenLayer) throws InterruptedException, InvocationTargetException {
- if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) {
- System.err.println("onscreen layer n/a");
+
+ @Test
+ public void test01_GL3() throws InterruptedException, InvocationTargetException {
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
return;
}
- if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) {
+ testOffscreenLayerGLCanvas_Impl(GLProfile.get(GLProfile.GL3));
+ }
+
+ private void testOffscreenLayerGLCanvas_Impl(final GLProfile glp) throws InterruptedException, InvocationTargetException {
+ if(!JAWTUtil.isOffscreenLayerSupported()) {
System.err.println("offscreen layer n/a");
return;
- }
+ }
final Frame frame1 = new Frame("AWT Parent Frame");
-
- GLCapabilities caps = new GLCapabilities(null);
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ if(singleBuffer) {
+ caps.setDoubleBuffered(false);
+ }
if(useMSAA) {
caps.setNumSamples(4);
caps.setSampleBuffers(true);
@@ -146,25 +158,24 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
caps.setOnscreen(true); // simulate normal behavior ..
}
final GLCanvas glc = new GLCanvas(caps);
- glc.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported
+ glc.setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported
glc.setPreferredSize(preferredGLSize);
glc.setMinimumSize(preferredGLSize);
glc.setSize(preferredGLSize);
-
- GearsES2 demo1 = new GearsES2(swapInterval);
+
+ final GearsES2 demo1 = new GearsES2(swapInterval);
if(noAnimation) {
demo1.setDoRotation(false);
}
glc.addGLEventListener(demo1);
-
+
frame1.setSize(frameSize0);
setupFrameAndShow(frame1, glc);
Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true));
Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true));
- Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer,
- glc.isOffscreenLayerSurfaceEnabled());
-
- GLAnimatorControl animator1 = new Animator(glc);
+ Assert.assertEquals(true, glc.isOffscreenLayerSurfaceEnabled());
+
+ final GLAnimatorControl animator1 = new Animator(glc);
if(!noAnimation) {
animator1.start();
}
@@ -176,17 +187,20 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
frame1.setSize(frameSize1);
frame1.pack();
frame1.validate();
- }});
-
+ }});
+
Thread.sleep(durationPerTest/2);
-
- end(animator1, frame1, null);
+
+ end(animator1, frame1, null);
+ if( waitForKey ) {
+ UITestCase.waitForKey("Continue");
+ }
}
-
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -196,16 +210,15 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
- boolean waitForKey = false;
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
@@ -216,6 +229,8 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
shallUseOffscreenPBufferLayer = true;
} else if(args[i].equals("-msaa")) {
useMSAA = true;
+ } else if(args[i].equals("-single")) {
+ singleBuffer = true;
} else if(args[i].equals("-still")) {
noAnimation = true;
} else if(args[i].equals("-wait")) {
@@ -223,13 +238,9 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
}
}
if(waitForKey) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
- System.err.println("Press enter to continue");
- try {
- System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ UITestCase.waitForKey("Start");
}
- String tstname = TestOffscreenLayer01GLCanvasAWT.class.getName();
+ final String tstname = TestOffscreenLayer01GLCanvasAWT.class.getName();
/*
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java
index ef7541d3f..d48d490b2 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.awt.BorderLayout;
@@ -33,20 +33,21 @@ import java.awt.Button;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
import jogamp.nativewindow.jawt.JAWTUtil;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.Window;
import com.jogamp.newt.awt.NewtCanvasAWT;
@@ -58,7 +59,9 @@ import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
+ static boolean singleBuffer = false;
static boolean useMSAA = false;
static boolean addComp = true;
static int swapInterval = 1;
@@ -68,6 +71,7 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
static Dimension frameSize1;
static Dimension preferredGLSize;
static long durationPerTest = 1000;
+ static boolean waitForKey = false;
@BeforeClass
public static void initClass() {
@@ -76,32 +80,31 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
preferredGLSize = new Dimension(400,200);
}
- private void setupFrameAndShow(final Frame f, java.awt.Component comp) throws InterruptedException, InvocationTargetException {
-
- Container c = new Container();
+ private void setupFrameAndShow(final Frame f, final java.awt.Component comp) throws InterruptedException, InvocationTargetException {
+ final Container c = new Container();
c.setLayout(new BorderLayout());
c.add(new Button("north"), BorderLayout.NORTH);
c.add(new Button("south"), BorderLayout.SOUTH);
c.add(new Button("east"), BorderLayout.EAST);
c.add(new Button("west"), BorderLayout.WEST);
c.add(comp, BorderLayout.CENTER);
-
+
f.setLayout(new BorderLayout());
f.add(new Button("NORTH"), BorderLayout.NORTH);
f.add(new Button("SOUTH"), BorderLayout.SOUTH);
f.add(new Button("EAST"), BorderLayout.EAST);
f.add(new Button("WEST"), BorderLayout.WEST);
f.add(c, BorderLayout.CENTER);
-
+
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
f.pack();
f.validate();
f.setVisible(true);
- }});
+ }});
}
-
- private void end(GLAnimatorControl actrl, final Frame f, Window w) throws InterruptedException, InvocationTargetException {
+
+ private void end(final GLAnimatorControl actrl, final Frame f, final Window w) throws InterruptedException, InvocationTargetException {
actrl.stop();
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -111,24 +114,32 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
w.destroy();
}
}
-
+
@Test
- public void testOffscreenLayerNewtCanvas_OffscreenLayerWithOnscreenClass() throws InterruptedException, InvocationTargetException {
- testOffscreenLayerNewtCanvas_Impl(true);
+ public void test01_GLDefault() throws InterruptedException, InvocationTargetException {
+ testOffscreenLayerNewtCanvas_Impl(null);
}
-
- private void testOffscreenLayerNewtCanvas_Impl(boolean offscreenLayer) throws InterruptedException, InvocationTargetException {
- if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) {
- System.err.println("onscreen layer n/a");
+
+ @Test
+ public void test02_GL3() throws InterruptedException, InvocationTargetException {
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
return;
}
- if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) {
+ testOffscreenLayerNewtCanvas_Impl(GLProfile.get(GLProfile.GL3));
+ }
+
+ private void testOffscreenLayerNewtCanvas_Impl(final GLProfile glp) throws InterruptedException, InvocationTargetException {
+ if(!JAWTUtil.isOffscreenLayerSupported()) {
System.err.println("offscreen layer n/a");
return;
- }
+ }
final Frame frame1 = new Frame("AWT Parent Frame");
-
- GLCapabilities caps = new GLCapabilities(null);
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ if(singleBuffer) {
+ caps.setDoubleBuffered(false);
+ }
if(useMSAA) {
caps.setNumSamples(4);
caps.setSampleBuffers(true);
@@ -137,31 +148,30 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
caps.setPBuffer(true);
caps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow
}
- GLWindow glWindow1 = GLWindow.create(caps);
-
+ final GLWindow glWindow1 = GLWindow.create(caps);
+
final NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(glWindow1);
- newtCanvasAWT1.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported
+ newtCanvasAWT1.setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported
newtCanvasAWT1.setPreferredSize(preferredGLSize);
newtCanvasAWT1.setMinimumSize(preferredGLSize);
newtCanvasAWT1.setSize(preferredGLSize);
-
- GearsES2 demo1 = new GearsES2(swapInterval);
+
+ final GearsES2 demo1 = new GearsES2(swapInterval);
if(noAnimation) {
demo1.setDoRotation(false);
}
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
- glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1));
-
+ glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1, null));
+
frame1.setSize(frameSize0);
setupFrameAndShow(frame1, newtCanvasAWT1);
Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true));
Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true));
Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent());
- Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer,
- newtCanvasAWT1.isOffscreenLayerSurfaceEnabled());
+ Assert.assertEquals(true, newtCanvasAWT1.isOffscreenLayerSurfaceEnabled());
- GLAnimatorControl animator1 = new Animator(glWindow1);
+ final GLAnimatorControl animator1 = new Animator(glWindow1);
if(!noAnimation) {
animator1.start();
}
@@ -173,17 +183,20 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
frame1.setSize(frameSize1);
frame1.pack();
frame1.validate();
- }});
-
+ }});
+
Thread.sleep(durationPerTest/2);
-
+
end(animator1, frame1, glWindow1);
+ if( waitForKey ) {
+ UITestCase.waitForKey("Continue");
+ }
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -193,16 +206,15 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
- boolean waitForKey = false;
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
@@ -213,6 +225,8 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
shallUseOffscreenPBufferLayer = true;
} else if(args[i].equals("-msaa")) {
useMSAA = true;
+ } else if(args[i].equals("-single")) {
+ singleBuffer = true;
} else if(args[i].equals("-still")) {
noAnimation = true;
} else if(args[i].equals("-wait")) {
@@ -220,13 +234,9 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
}
}
if(waitForKey) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
- System.err.println("Press enter to continue");
- try {
- System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ UITestCase.waitForKey("Start");
}
- String tstname = TestOffscreenLayer02NewtCanvasAWT.class.getName();
+ final String tstname = TestOffscreenLayer02NewtCanvasAWT.class.getName();
/*
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java
index 90934f1b5..e8b21e935 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -30,10 +30,9 @@ package com.jogamp.opengl.test.junit.jogl.acore;
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
-import javax.media.opengl.DefaultGLCapabilitiesChooser;
+import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;
import jogamp.nativewindow.jawt.JAWTUtil;
@@ -41,30 +40,28 @@ import jogamp.nativewindow.jawt.JAWTUtil;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.util.RunnableTask;
import com.jogamp.opengl.test.junit.util.UITestCase;
-@SuppressWarnings("deprecation")
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestPBufferDeadlockAWT extends UITestCase {
static GLProfile glp;
static int width, height;
@BeforeClass
public static void initClass() {
- glp = GLProfile.getGL2ES2();
+ glp = GLProfile.getMaxFixedFunc(true);
Assert.assertNotNull( glp );
width = 512;
height = 512;
}
- protected void runTestGL( GLCapabilities caps ) throws InterruptedException, InvocationTargetException {
- final GLPbuffer pbuffer = GLDrawableFactory.getFactory( GLProfile.getGL2ES2() ).createGLPbuffer(
- null,
- caps, new DefaultGLCapabilitiesChooser(),
- 512, 512,
- null
- );
+ protected void runTestGL( final GLCapabilities caps ) throws InterruptedException, InvocationTargetException {
+ caps.setPBuffer(true);
+ final GLAutoDrawable pbuffer = GLDrawableFactory.getFactory( caps.getGLProfile() ).createOffscreenAutoDrawable(null, caps, null, 512, 512);
final boolean[] done = {false};
final Runnable pbufferCreationAction = new Runnable() {
@@ -75,55 +72,55 @@ public class TestPBufferDeadlockAWT extends UITestCase {
System.err.println("AA.X");
}
};
-
+
EventQueue.invokeAndWait(new Runnable() {
public void run() {
Assert.assertTrue(EventQueue.isDispatchThread());
JAWTUtil.lockToolkit();
try {
- final RunnableTask rTask = new RunnableTask(pbufferCreationAction, new Object(), false);
+ final RunnableTask rTask = new RunnableTask(pbufferCreationAction, new Object(), false, null);
System.err.println("BB.0: "+rTask.getSyncObject());
synchronized (rTask.getSyncObject()) {
System.err.println("BB.1: "+rTask.getSyncObject());
- new Thread(rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start();
+ new Thread(rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start();
try {
System.err.println("BB.2");
rTask.getSyncObject().wait();
System.err.println("BB.3");
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
throw new RuntimeException(e);
- }
+ }
System.err.println("BB.X");
}
} finally {
JAWTUtil.unlockToolkit();
}
- }
+ }
});
Assert.assertTrue(done[0]);
pbuffer.destroy();
}
- @Test(timeout = 2000) // 2s timeout
+ @Test(timeout = 10000)
public void testDeadlock() throws InterruptedException, InvocationTargetException {
- GLCapabilities caps = new GLCapabilities( glp );
+ final GLCapabilities caps = new GLCapabilities( glp );
runTestGL( caps );
}
static long duration = 500; // ms
- public static void main( String args[] ) {
+ public static void main( final String args[] ) {
for ( int i = 0; i < args.length; i++ ) {
if ( args[ i ].equals( "-time" ) ) {
i++;
try {
duration = Integer.parseInt( args[ i ] );
}
- catch ( Exception ex ) {
+ catch ( final Exception ex ) {
ex.printStackTrace();
}
}
}
org.junit.runner.JUnitCore.main( TestPBufferDeadlockAWT.class.getName() );
}
-}
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java
index 67b70e117..c899a310f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import javax.media.opengl.GLCapabilities;
@@ -47,7 +47,10 @@ import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestSharedContextListAWT extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
@@ -70,7 +73,7 @@ public class TestSharedContextListAWT extends UITestCase {
}
private void initShared() {
- sharedDrawable = GLDrawableFactory.getFactory(glp).createOffscreenAutoDrawable(null, caps, null, width, height, null);
+ sharedDrawable = GLDrawableFactory.getFactory(glp).createOffscreenAutoDrawable(null, caps, null, width, height);
Assert.assertNotNull(sharedDrawable);
sharedGears = new Gears();
Assert.assertNotNull(sharedGears);
@@ -83,8 +86,8 @@ public class TestSharedContextListAWT extends UITestCase {
Assert.assertNotNull(sharedDrawable);
sharedDrawable.destroy();
}
-
- protected void setFrameTitle(final Frame f, final boolean useShared)
+
+ protected void setFrameTitle(final Frame f, final boolean useShared)
throws InterruptedException, InvocationTargetException {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -96,15 +99,16 @@ public class TestSharedContextListAWT extends UITestCase {
protected GLCanvas runTestGL(final Frame frame, final Animator animator, final int x, final int y, final boolean useShared, final boolean vsync)
throws InterruptedException, InvocationTargetException
{
- final GLCanvas glCanvas = new GLCanvas(caps, useShared ? sharedDrawable.getContext() : null);
+ final GLCanvas glCanvas = new GLCanvas(caps);
Assert.assertNotNull(glCanvas);
+ glCanvas.setSharedAutoDrawable(sharedDrawable);
frame.add(glCanvas);
frame.setLocation(x, y);
frame.setSize(width, height);
-
- Gears gears = new Gears(vsync ? 1 : 0);
+
+ final Gears gears = new Gears(vsync ? 1 : 0);
if(useShared) {
- gears.setGears(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3());
+ gears.setSharedGears(sharedGears);
}
glCanvas.addGLEventListener(gears);
@@ -125,27 +129,27 @@ public class TestSharedContextListAWT extends UITestCase {
final Frame f1 = new Frame();
final Frame f2 = new Frame();
final Frame f3 = new Frame();
- Animator animator = new Animator();
+ final Animator animator = new Animator();
final GLCanvas glc1 = runTestGL(f1, animator, 0, 0, true, false);
- int x0 = f1.getX();
- int y0 = f1.getY();
-
- final GLCanvas glc2 = runTestGL(f2, animator,
+ final int x0 = f1.getX();
+ final int y0 = f1.getY();
+
+ final GLCanvas glc2 = runTestGL(f2, animator,
x0+width,
- y0+0,
+ y0+0,
true, false);
-
- final GLCanvas glc3 = runTestGL(f3, animator,
- x0+0,
- y0+height,
+
+ final GLCanvas glc3 = runTestGL(f3, animator,
+ x0+0,
+ y0+height,
false, true);
setFrameTitle(f1, true);
setFrameTitle(f2, true);
setFrameTitle(f3, false);
-
- animator.setUpdateFPSFrames(1, null);
+
+ animator.setUpdateFPSFrames(1, null);
animator.start();
while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
@@ -162,27 +166,27 @@ public class TestSharedContextListAWT extends UITestCase {
Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc2, false));
f3.dispose();
Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc3, false));
- } catch (Throwable t) {
+ } catch (final Throwable t) {
throw new RuntimeException(t);
}
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
-
+ }
+
releaseShared();
}
static long duration = 500; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
}
org.junit.runner.JUnitCore.main(TestSharedContextListAWT.class.getName());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java
index 78c8fd0ae..38b3f92ff 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
@@ -46,7 +46,10 @@ import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestSharedContextListNEWT extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
@@ -69,7 +72,7 @@ public class TestSharedContextListNEWT extends UITestCase {
}
private void initShared() {
- sharedDrawable = GLDrawableFactory.getFactory(glp).createOffscreenAutoDrawable(null, caps, null, width, height, null);
+ sharedDrawable = GLDrawableFactory.getFactory(glp).createOffscreenAutoDrawable(null, caps, null, width, height);
Assert.assertNotNull(sharedDrawable);
sharedGears = new Gears();
Assert.assertNotNull(sharedGears);
@@ -84,19 +87,19 @@ public class TestSharedContextListNEWT extends UITestCase {
sharedDrawable = null;
}
- protected GLWindow runTestGL(Animator animator, int x, int y, boolean useShared, boolean vsync) throws InterruptedException {
- GLWindow glWindow = GLWindow.create(caps);
+ protected GLWindow runTestGL(final Animator animator, final int x, final int y, final boolean useShared, final boolean vsync) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared);
if(useShared) {
- glWindow.setSharedContext(sharedDrawable.getContext());
+ glWindow.setSharedAutoDrawable(sharedDrawable);
}
glWindow.setSize(width, height);
- Gears gears = new Gears(vsync ? 1 : 0);
+ final Gears gears = new Gears(vsync ? 1 : 0);
if(useShared) {
- gears.setGears(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3());
+ gears.setSharedGears(sharedGears);
}
glWindow.addGLEventListener(gears);
@@ -113,14 +116,14 @@ public class TestSharedContextListNEWT extends UITestCase {
@Test
public void test01() throws InterruptedException {
initShared();
- Animator animator = new Animator();
- GLWindow f1 = runTestGL(animator, 0, 0, true, false);
- InsetsImmutable insets = f1.getInsets();
- GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(),
+ final Animator animator = new Animator();
+ final GLWindow f1 = runTestGL(animator, 0, 0, true, false);
+ final InsetsImmutable insets = f1.getInsets();
+ final GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(),
f1.getY()+0, true, false);
- GLWindow f3 = runTestGL(animator, f1.getX()+0,
+ final GLWindow f3 = runTestGL(animator, f1.getX()+0,
f1.getY()+height+insets.getTotalHeight(), false, true);
- animator.setUpdateFPSFrames(1, null);
+ animator.setUpdateFPSFrames(1, null);
animator.start();
while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
@@ -136,19 +139,19 @@ public class TestSharedContextListNEWT extends UITestCase {
static long duration = 500; // ms
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
}
/**
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
- System.err.println(stdin.readLine()); */
+ System.err.println(stdin.readLine()); */
org.junit.runner.JUnitCore.main(TestSharedContextListNEWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java
index 7893c51f1..7f5d50323 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.io.IOException;
@@ -44,7 +44,10 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestSharedContextListNEWT2 extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
@@ -84,20 +87,20 @@ public class TestSharedContextListNEWT2 extends UITestCase {
sharedDrawable = null;
}
- protected GLWindow runTestGL(Animator animator, int x, int y, boolean useShared, boolean vsync) throws InterruptedException {
- GLWindow glWindow = GLWindow.create(caps);
-
+ protected GLWindow runTestGL(final Animator animator, final int x, final int y, final boolean useShared, final boolean vsync) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+
Assert.assertNotNull(glWindow);
glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared);
if(useShared) {
- glWindow.setSharedContext(sharedDrawable.getContext());
+ glWindow.setSharedAutoDrawable(sharedDrawable);
}
glWindow.setSize(width, height);
- Gears gears = new Gears(vsync ? 1 : 0);
+ final Gears gears = new Gears(vsync ? 1 : 0);
if(useShared) {
- gears.setGears(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3());
+ gears.setSharedGears(sharedGears);
}
glWindow.addGLEventListener(gears);
@@ -108,23 +111,24 @@ public class TestSharedContextListNEWT2 extends UITestCase {
Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true));
Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true));
glWindow.setPosition(x, y);
-
+
return glWindow;
}
@Test(timeout=10000)
public void test01() throws InterruptedException {
initShared();
- GLWindow f1 = runTestGL(new Animator(), 0, 0, true, false);
- InsetsImmutable insets = f1.getInsets();
- GLWindow f2 = runTestGL(new Animator(), f1.getX()+width+insets.getTotalWidth(),
- f1.getY()+0, true, false);
- GLWindow f3 = runTestGL(new Animator(), f1.getX()+0,
- f1.getY()+height+insets.getTotalHeight(), true, false);
+
+ final GLWindow f1 = runTestGL(new Animator(), 0, 0, true, false);
+ final InsetsImmutable insets = f1.getInsets();
+ final GLWindow f2 = runTestGL(new Animator(), f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, true, false);
+ final GLWindow f3 = runTestGL(new Animator(), f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), true, false);
try {
Thread.sleep(duration);
- } catch(Exception e) {
+ } catch(final Exception e) {
e.printStackTrace();
}
@@ -132,24 +136,28 @@ public class TestSharedContextListNEWT2 extends UITestCase {
f2.destroy();
f3.destroy();
+ // f1.getAnimator().stop();
+ // f2.getAnimator().stop();
+ // f3.getAnimator().stop();
+
releaseShared();
}
static long duration = 2000; // ms
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
}
/**
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
- System.err.println(stdin.readLine()); */
+ System.err.println(stdin.readLine()); */
org.junit.runner.JUnitCore.main(TestSharedContextListNEWT2.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java
index 7894f3e86..d3cdf5e95 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.awt.Component;
@@ -36,9 +36,13 @@ import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
+import java.util.HashSet;
+import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -48,6 +52,8 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
import javax.media.opengl.glu.GLU;
import javax.swing.Box;
import javax.swing.BoxLayout;
@@ -55,6 +61,7 @@ import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
+import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@@ -62,24 +69,28 @@ import javax.swing.event.ChangeListener;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.nio.Buffers;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener;
import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.GLBuffers;
/**
* TestSharedContextNewtAWTBug523
- *
+ *
* Opens a single JFrame with two OpenGL windows and sliders to adjust the view orientation.
*
* Each window renders a red triangle and a blue triangle.
* The red triangle is rendered using glBegin / glVertex / glEnd.
- * The blue triangle is rendered using vertex buffer objects bound to a vertex array object.
+ * The blue triangle is rendered using vertex buffer objects.
+ *
+ * VAO's are not used to allow testing on OSX GL2 context!
*
* If static useNewt is true, then those windows are GLWindow objects in a NewtCanvasAWT.
* If static useNewt is false, then those windows are GLCanvas objects.
@@ -88,17 +99,18 @@ import com.jogamp.opengl.util.GLBuffers;
* so that they share the vertex buffer and array objects and display lists.
* If shareContext is false, then the two OpenGL windows each have their own context, and the blue
* triangle fails to render in one of the windows.
- *
+ *
* The four test cases run through the four combinations of useNewt and shareContext.
- *
- * Similar test cases are {@link TestSharedContextListNEWT}, {@link TestSharedContextListAWT},
- * {@link TestSharedContextVBOES2NEWT} and {@link TestSharedContextVBOES1NEWT}.
- *
+ *
+ * Similar test cases are {@link TestSharedContextListNEWT}, {@link TestSharedContextListAWT},
+ * {@link TestSharedContextVBOES2NEWT1} and {@link TestSharedContextVBOES1NEWT}.
+ *
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestSharedContextNewtAWTBug523 extends UITestCase {
static long durationPerTest = 1000;
-
+
// counters for instances of event listener TwoTriangles
// private static int instanceCounter;
private static int initializationCounter;
@@ -107,13 +119,11 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
// The main thread waits twice on this semaphore to ensure both canvases have finished cleaning up.
private static Semaphore disposalCompleteSemaphore = new Semaphore(0);
- // Buffer objects can be shared across shared OpenGL context.
+ // Buffer objects can be shared across shared OpenGL context.
// If we run with sharedContext, then the tests will use these shared buffer objects,
// otherwise each event listener allocates its own buffer objects.
- private static int [] sharedVertexBufferObjects = {0};
- private static int [] sharedIndexBufferObjects = {0};
- private static FloatBuffer sharedVertexBuffer;
- private static IntBuffer sharedIndexBuffer;
+ private static AtomicInteger sharedVertexBufferObjects = new AtomicInteger(0);
+ private static AtomicInteger sharedIndexBufferObjects = new AtomicInteger(0);
@BeforeClass
public static void initClass() {
@@ -121,70 +131,97 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
setTestSupported(false);
}
}
-
- static private GLOffscreenAutoDrawable initShared(GLCapabilities caps) {
- final GLOffscreenAutoDrawable sharedDrawable = GLDrawableFactory.getFactory(caps.getGLProfile()).createOffscreenAutoDrawable(null, caps, null, 64, 64, null);
+
+ static private GLOffscreenAutoDrawable initShared(final GLCapabilities caps) {
+ final GLOffscreenAutoDrawable sharedDrawable = GLDrawableFactory.getFactory(caps.getGLProfile()).createOffscreenAutoDrawable(null, caps, null, 64, 64);
Assert.assertNotNull(sharedDrawable);
// init and render one frame, which will setup the Gears display lists
sharedDrawable.display();
+ final GLContext ctx = sharedDrawable.getContext();
+ Assert.assertNotNull("Shared drawable's ctx is null", ctx);
+ Assert.assertTrue("Shared drawable's ctx is not created", ctx.isCreated());
return sharedDrawable;
}
- static private void releaseShared(GLOffscreenAutoDrawable sharedDrawable) {
+ static private void releaseShared(final GLOffscreenAutoDrawable sharedDrawable) {
if(null != sharedDrawable) {
sharedDrawable.destroy();
}
}
-
+
// inner class that implements the event listener
static class TwoTriangles implements GLEventListener {
boolean useShared;
int canvasWidth;
int canvasHeight;
- private float boundsRadius = 2f;
+ private static final float boundsRadius = 2f;
private float viewDistance;
- private float viewDistanceFactor = 1.0f;
+ private static float viewDistanceFactor = 1.0f;
private float xAxisRotation;
private float yAxisRotation;
- private float viewFovDegrees = 15f;
-
- // vertex array objects cannot be shared across open gl canvases;
- //
- // However, display lists can be shared across GLCanvas instances (if those canvases are initialized with the same GLContext),
- // including a display list created in one context that uses a VAO.
- private int [] vertexArrayObjects = {0};
+ private static final float viewFovDegrees = 15f;
// Buffer objects can be shared across canvas instances, if those canvases are initialized with the same GLContext.
// If we run with sharedBufferObjects true, then the tests will use these shared buffer objects.
// If we run with sharedBufferObjects false, then each event listener allocates its own buffer objects.
- private int [] privateVertexBufferObjects = {0};
- private int [] privateIndexBufferObjects = {0};
- private FloatBuffer privateVertexBuffer;
- private IntBuffer privateIndexBuffer;
-
- TwoTriangles (int canvasWidth, int canvasHeight, boolean useShared) {
+ private final int [] privateVertexBufferObjects = {0};
+ private final int [] privateIndexBufferObjects = {0};
+
+ public static int createVertexBuffer(final GL2 gl2) {
+ final FloatBuffer vertexBuffer = Buffers.newDirectFloatBuffer(18);
+ vertexBuffer.put(new float[]{
+ 1.0f, -0.5f, 0f, // vertex 1
+ 0f, 0f, 1f, // normal 1
+ 1.5f, -0.5f, 0f, // vertex 2
+ 0f, 0f, 1f, // normal 2
+ 1.0f, 0.5f, 0f, // vertex 3
+ 0f, 0f, 1f // normal 3
+ });
+ vertexBuffer.position(0);
+
+ final int[] vbo = { 0 };
+ gl2.glGenBuffers(1, vbo, 0);
+ gl2.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo[0]);
+ gl2.glBufferData(GL.GL_ARRAY_BUFFER, vertexBuffer.capacity() * Buffers.SIZEOF_FLOAT, vertexBuffer, GL.GL_STATIC_DRAW);
+ gl2.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ return vbo[0];
+ }
+ public static int createVertexIndexBuffer(final GL2 gl2) {
+ final IntBuffer indexBuffer = Buffers.newDirectIntBuffer(3);
+ indexBuffer.put(new int[]{0, 1, 2});
+ indexBuffer.position(0);
+
+ final int[] vbo = { 0 };
+ gl2.glGenBuffers(1, vbo, 0);
+ gl2.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, vbo[0]);
+ gl2.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * Buffers.SIZEOF_INT, indexBuffer, GL.GL_STATIC_DRAW);
+ gl2.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
+ return vbo[0];
+ }
+
+ TwoTriangles (final int canvasWidth, final int canvasHeight, final boolean useShared) {
// instanceNum = instanceCounter++;
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
this.useShared = useShared;
}
- public void setXAxisRotation(float xRot) {
+ public void setXAxisRotation(final float xRot) {
xAxisRotation = xRot;
}
- public void setYAxisRotation(float yRot) {
+ public void setYAxisRotation(final float yRot) {
yAxisRotation = yRot;
}
- public void setViewDistanceFactor(float factor) {
+ public void setViewDistanceFactor(final float factor) {
viewDistanceFactor = factor;
}
- public void init(GLAutoDrawable drawable) {
- GL2 gl2 = drawable.getGL().getGL2();
+ public void init(final GLAutoDrawable drawable) {
+ final GL2 gl2 = drawable.getGL().getGL2();
System.err.println("INIT GL IS: " + gl2.getClass().getName());
@@ -195,49 +232,32 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
gl2.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// the first instance of TwoTriangles initializes the shared buffer objects;
- // synchronizing to deal with potential liveness issues if the data is intialized from one thread and used on another
+ // synchronizing to deal with potential liveness issues if the data is initialized from one thread and used on another
synchronized (this) {
- gl2.glGenVertexArrays(1, vertexArrayObjects, 0);
-
- gl2.glBindVertexArray(vertexArrayObjects[0]);
-
- // use either the shared or private vertex buffers, as
+ // use either the shared or private vertex buffers, as
int [] vertexBufferObjects;
int [] indexBufferObjects;
- FloatBuffer vertexBuffer;
- IntBuffer indexBuffer;
//
if (useShared) {
- vertexBufferObjects = sharedVertexBufferObjects;
- indexBufferObjects = sharedIndexBufferObjects;
- vertexBuffer = sharedVertexBuffer;
- indexBuffer = sharedIndexBuffer;
+ System.err.println("Using shared VBOs on slave 0x"+Integer.toHexString(hashCode()));
+ privateVertexBufferObjects[0] = sharedVertexBufferObjects.get();
+ privateIndexBufferObjects[0] = sharedIndexBufferObjects.get();
} else {
- vertexBufferObjects = privateVertexBufferObjects;
- indexBufferObjects = privateIndexBufferObjects;
- vertexBuffer = privateVertexBuffer;
- indexBuffer = privateIndexBuffer;
+ System.err.println("Using local VBOs on slave 0x"+Integer.toHexString(hashCode()));
}
-
+ vertexBufferObjects = privateVertexBufferObjects;
+ indexBufferObjects = privateIndexBufferObjects;
+
// if buffer sharing is enabled, then the first of the two event listeners to be
// initialized will allocate the buffers, and the other will re-use the allocated one
if (vertexBufferObjects[0] == 0) {
- vertexBuffer = GLBuffers.newDirectFloatBuffer(18);
- vertexBuffer.put(new float[]{
- 1.0f, -0.5f, 0f, // vertex 1
- 0f, 0f, 1f, // normal 1
- 1.5f, -0.5f, 0f, // vertex 2
- 0f, 0f, 1f, // normal 2
- 1.0f, 0.5f, 0f, // vertex 3
- 0f, 0f, 1f // normal 3
- });
- vertexBuffer.position(0);
-
- gl2.glGenBuffers(1, vertexBufferObjects, 0);
- gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, vertexBufferObjects[0]);
- gl2.glBufferData(GL2.GL_ARRAY_BUFFER, vertexBuffer.capacity() * Buffers.SIZEOF_FLOAT, vertexBuffer, GL2.GL_STATIC_DRAW);
+ System.err.println("Creating vertex VBO on slave 0x"+Integer.toHexString(hashCode()));
+ vertexBufferObjects[0] = createVertexBuffer(gl2);
+ if (useShared) {
+ sharedVertexBufferObjects.set(vertexBufferObjects[0]);
+ }
}
-
+
// A check in the case that buffer sharing is enabled but context sharing is not enabled -- in that
// case, the buffer objects are not shareable, and the blue triangle cannot be rendereds.
// Furthermore, although the calls to bind and draw elements do not cause an error from glGetError
@@ -245,35 +265,36 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
// I found that with my system glDrawElements causes a runtime exception 50% of the time. Executing the binds
// to unshareable buffers sets up glDrawElements for unpredictable crashes -- sometimes it does, sometimes not.
if (gl2.glIsBuffer(vertexBufferObjects[0])) {
- gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, vertexBufferObjects[0]);
+ gl2.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBufferObjects[0]);
//
- gl2.glEnableClientState(GL2.GL_VERTEX_ARRAY);
- gl2.glVertexPointer(3, GL2.GL_FLOAT, 6 * GLBuffers.SIZEOF_FLOAT, 0);
+ gl2.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ gl2.glVertexPointer(3, GL.GL_FLOAT, 6 * Buffers.SIZEOF_FLOAT, 0);
//
- gl2.glEnableClientState(GL2.GL_NORMAL_ARRAY);
- gl2.glNormalPointer(GL2.GL_FLOAT, 6 * GLBuffers.SIZEOF_FLOAT, 3 * GLBuffers.SIZEOF_FLOAT);
+ gl2.glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ gl2.glNormalPointer(GL.GL_FLOAT, 6 * Buffers.SIZEOF_FLOAT, 3 * Buffers.SIZEOF_FLOAT);
+ } else {
+ System.err.println("Vertex VBO is not a buffer on slave 0x"+Integer.toHexString(hashCode()));
}
if (indexBufferObjects[0] == 0) {
- indexBuffer = GLBuffers.newDirectIntBuffer(3);
- indexBuffer.put(new int[]{0, 1, 2});
- indexBuffer.position(0);
-
- gl2.glGenBuffers(1, indexBufferObjects, 0);
- gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, indexBufferObjects[0]);
- gl2.glBufferData(GL2.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * Buffers.SIZEOF_INT, indexBuffer, GL2.GL_STATIC_DRAW);
+ System.err.println("Creating index VBO on slave 0x"+Integer.toHexString(hashCode()));
+ indexBufferObjects[0] = createVertexIndexBuffer(gl2);
+ if (useShared) {
+ sharedIndexBufferObjects.set(indexBufferObjects[0]);
+ }
}
- // again, a check in the case that buffer sharing is enabled but context sharing is not enabled
+ // again, a check in the case that buffer sharing is enabled but context sharing is not enabled
if (gl2.glIsBuffer(indexBufferObjects[0])) {
- gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, indexBufferObjects[0]);
+ gl2.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBufferObjects[0]);
+ } else {
+ System.err.println("Index VBO is not a buffer on slave 0x"+Integer.toHexString(hashCode()));
}
- gl2.glBindVertexArray(0);
- gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, 0);
- gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
- gl2.glDisableClientState(GL2.GL_VERTEX_ARRAY);
- gl2.glDisableClientState(GL2.GL_NORMAL_ARRAY);
+ gl2.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
+ gl2.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ gl2.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ gl2.glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
initializationCounter++;
} // synchronized (this)
@@ -283,35 +304,33 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
}
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
synchronized (this) {
initializationCounter--;
- GL2 gl2 = drawable.getGL().getGL2();
-
- gl2.glDeleteVertexArrays(1, vertexArrayObjects, 0);
- vertexArrayObjects[0] = 0;
- logAnyErrorCodes(gl2, "display");
+ final GL2 gl2 = drawable.getGL().getGL2();
- // release shared resources
+ // release shared resources
if (initializationCounter == 0 || !useShared) {
- // use either the shared or private vertex buffers, as
+ // use either the shared or private vertex buffers, as
int [] vertexBufferObjects;
int [] indexBufferObjects;
if (useShared) {
- vertexBufferObjects = sharedVertexBufferObjects;
- indexBufferObjects = sharedIndexBufferObjects;
- } else {
- vertexBufferObjects = privateVertexBufferObjects;
- indexBufferObjects = privateIndexBufferObjects;
+ privateVertexBufferObjects[0] = sharedVertexBufferObjects.get();
+ privateIndexBufferObjects[0] = sharedIndexBufferObjects.get();
+ sharedVertexBufferObjects.set(0);
+ sharedIndexBufferObjects.set(0);
}
+ vertexBufferObjects = privateVertexBufferObjects;
+ indexBufferObjects = privateIndexBufferObjects;
gl2.glDeleteBuffers(1, vertexBufferObjects, 0);
+ logAnyErrorCodes(this, gl2, "dispose.2");
gl2.glDeleteBuffers(1, indexBufferObjects, 0);
+ logAnyErrorCodes(this, gl2, "dispose.3");
vertexBufferObjects[0] = 0;
indexBufferObjects[0] = 0;
- logAnyErrorCodes(gl2, "display");
}
// release the main thread once for each disposal
@@ -319,34 +338,36 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
} // synchronized (this)
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
}
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
// wait until all instances are initialized before attempting to draw using the
// vertex array object, because the buffers are allocated in init and when the
- // buffers are shared, we need to ensure that they are allocated before trying to use thems
+ // buffers are shared, we need to ensure that they are allocated before trying to use them
synchronized (this) {
if (initializationCounter != 2) {
return;
}
}
- GL2 gl2 = drawable.getGL().getGL2();
- GLU glu = new GLU();
+ final GL2 gl2 = drawable.getGL().getGL2();
+ final GLU glu = new GLU();
+
+ logAnyErrorCodes(this, gl2, "display.0");
// Clear the drawing area
- gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
+ gl2.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl2.glViewport(0, 0, canvasWidth, canvasHeight);
- gl2.glMatrixMode(GL2.GL_PROJECTION);
+ gl2.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl2.glLoadIdentity();
glu.gluPerspective(viewFovDegrees, (float)canvasWidth/(float)canvasHeight,
viewDistance*viewDistanceFactor-boundsRadius, viewDistance*viewDistanceFactor+boundsRadius);
// Reset the current matrix to the "identity"
- gl2.glMatrixMode(GL2.GL_MODELVIEW);
+ gl2.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl2.glLoadIdentity();
// draw the scene
@@ -357,8 +378,10 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
gl2.glRotatef(xAxisRotation, 1, 0, 0);
gl2.glRotatef(yAxisRotation, 0, 1, 0);
- gl2.glDisable(GL2.GL_CULL_FACE);
- gl2.glEnable(GL2.GL_DEPTH_TEST);
+ gl2.glDisable(GL.GL_CULL_FACE);
+ gl2.glEnable(GL.GL_DEPTH_TEST);
+
+ logAnyErrorCodes(this, gl2, "display.1");
// draw the triangles
drawTwoTriangles(gl2);
@@ -369,14 +392,14 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
// Flush all drawing operations to the graphics card
gl2.glFlush();
- logAnyErrorCodes(gl2, "display");
+ logAnyErrorCodes(this, gl2, "display.X");
}
- public void drawTwoTriangles(GL2 gl2) {
+ public void drawTwoTriangles(final GL2 gl2) {
// draw a red triangle the old fashioned way
gl2.glColor3f(1f, 0f, 0f);
- gl2.glBegin(GL2.GL_TRIANGLES);
+ gl2.glBegin(GL.GL_TRIANGLES);
gl2.glVertex3d(-1.5, -0.5, 0);
gl2.glNormal3d(0, 0, 1);
gl2.glVertex3d(-0.5, -0.5, 0);
@@ -385,62 +408,84 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
gl2.glNormal3d(0, 0, 1);
gl2.glEnd();
+ logAnyErrorCodes(this, gl2, "drawTwoTriangles.1");
+
// draw the blue triangle using a vertex array object, sharing the vertex and index buffer objects across
// contexts; if context sharing is not initialized, then one window will simply have to live without a blue triangle
//
- // synchronizing to deal with potential liveness issues if the data is intialized from one
+ // synchronizing to deal with potential liveness issues if the data is initialized from one
// thread and used on another
- boolean vaoBound = false;
- // use either the shared or private vertex buffers, as
+ boolean vboBound = false;
+ // use either the shared or private vertex buffers, as
int [] vertexBufferObjects;
int [] indexBufferObjects;
synchronized (this) {
if (useShared) {
- vertexBufferObjects = sharedVertexBufferObjects;
- indexBufferObjects = sharedIndexBufferObjects;
- } else {
- vertexBufferObjects = privateVertexBufferObjects;
- indexBufferObjects = privateIndexBufferObjects;
+ privateVertexBufferObjects[0] = sharedVertexBufferObjects.get();
+ privateIndexBufferObjects[0] = sharedIndexBufferObjects.get();
}
+ vertexBufferObjects = privateVertexBufferObjects;
+ indexBufferObjects = privateIndexBufferObjects;
} // synchronized (this)
-
+
// A check in the case that buffer sharing is enabled but context sharing is not enabled -- in that
// case, the buffer objects are not shareable, and the blue triangle cannot be rendereds.
// Furthermore, although the calls to bind and draw elements do not cause an error from glGetError
// when this check is removed, true blue triangle is not rendered anyways, and more importantly,
// I found that with my system glDrawElements causes a runtime exception 50% of the time. Executing the binds
// to unshareable buffers sets up glDrawElements for unpredictable crashes -- sometimes it does, sometimes not.
- if (gl2.glIsVertexArray(vertexArrayObjects[0]) &&
- gl2.glIsBuffer(indexBufferObjects[0]) && gl2.glIsBuffer(vertexBufferObjects[0])) {
- gl2.glBindVertexArray(vertexArrayObjects[0]);
- gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, indexBufferObjects[0]);
- vaoBound = true;
+ final boolean isVBO1 = gl2.glIsBuffer(indexBufferObjects[0]);
+ final boolean isVBO2 = gl2.glIsBuffer(vertexBufferObjects[0]);
+ final boolean useVBO = isVBO1 && isVBO2;
+ if ( useVBO ) {
+ gl2.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBufferObjects[0]);
+ gl2.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBufferObjects[0]);
+
+ gl2.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ // gl2.glVertexPointer(3, GL2.GL_FLOAT, 6 * GLBuffers.SIZEOF_FLOAT, 0);
+ gl2.glEnableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ // gl2.glNormalPointer(GL2.GL_FLOAT, 6 * GLBuffers.SIZEOF_FLOAT, 3 * GLBuffers.SIZEOF_FLOAT);
+ vboBound = true;
}
-
- logAnyErrorCodes(gl2, "drawTwoTriangles");
+ // System.err.println("XXX VBO bound "+vboBound+"[ vbo1 "+isVBO1+", vbo2 "+isVBO2+"]");
+
+ logAnyErrorCodes(this, gl2, "drawTwoTriangles.2");
- if (vaoBound) {
+ if (vboBound) {
gl2.glColor3f(0f, 0f, 1f);
- gl2.glDrawElements(GL2.GL_TRIANGLES, 3, GL2.GL_UNSIGNED_INT, 0);
- gl2.glBindVertexArray(0);
- gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, 0);
- }
+ gl2.glDrawElements(GL.GL_TRIANGLES, 3, GL.GL_UNSIGNED_INT, 0);
+ gl2.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ gl2.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
+ gl2.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ gl2.glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ }
+
+ logAnyErrorCodes(this, gl2, "drawTwoTriangles.3");
}
- public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
+ public void displayChanged(final GLAutoDrawable drawable, final boolean modeChanged, final boolean deviceChanged) {
}
-
+
} // inner class TwoTriangles
- public static void logAnyErrorCodes(GL2 gl2, String prefix) {
- int glError = gl2.glGetError();
- while (glError != GL2.GL_NO_ERROR) {
- System.err.println(prefix + ", OpenGL error: 0x" + Integer.toHexString(glError));
- glError = gl2.glGetError();
+ private static final Set<String> errorSet = new HashSet<String>();
+
+ public static void logAnyErrorCodes(final Object obj, final GL gl, final String prefix) {
+ final int glError = gl.glGetError();
+ if(glError != GL.GL_NO_ERROR) {
+ final String errStr = "GL-Error: "+prefix + " on obj 0x"+Integer.toHexString(obj.hashCode())+", OpenGL error: 0x" + Integer.toHexString(glError);
+ if( errorSet.add(errStr) ) {
+ System.err.println(errStr);
+ Thread.dumpStack();
+ }
}
- int status = gl2.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER);
- if (status != GL2.GL_FRAMEBUFFER_COMPLETE) {
- System.err.println(prefix + ", glCheckFramebufferStatus: 0x" + Integer.toHexString(status));
+ final int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
+ if (status != GL.GL_FRAMEBUFFER_COMPLETE) {
+ final String errStr = "GL-Error: "+prefix + " on obj 0x"+Integer.toHexString(obj.hashCode())+", glCheckFramebufferStatus: 0x" + Integer.toHexString(status);
+ if( errorSet.add(errStr) ) {
+ System.err.println(errStr);
+ Thread.dumpStack();
+ }
}
}
@@ -462,19 +507,19 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
* @return the distance the camera should be from the center of the scenes
* bounding sphere
*/
- public static float setupViewFrustum(GL2 gl2, int width, int height, float boundsRadius, float zoomFactor, float viewFovDegrees) {
+ public static float setupViewFrustum(final GL2 gl2, final int width, final int height, final float boundsRadius, final float zoomFactor, final float viewFovDegrees) {
assert boundsRadius > 0.0f;
assert zoomFactor > 0.0f;
assert viewFovDegrees > 0.0f;
- GLU glu = new GLU();
+ final GLU glu = new GLU();
final float aspectRatio = (float) width / (float) height;
final float boundRadiusAdjusted = boundsRadius / zoomFactor;
final float lowestFov = aspectRatio > 1.0f ? viewFovDegrees : aspectRatio * viewFovDegrees;
final float viewDist = (float) (boundRadiusAdjusted / Math.sin( (lowestFov / 2.0) * (Math.PI / 180.0) ));
- gl2.glMatrixMode(GL2.GL_PROJECTION);
+ gl2.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl2.glLoadIdentity();
glu.gluPerspective(viewFovDegrees, aspectRatio, 0.1*viewDist, viewDist + boundRadiusAdjusted);
@@ -482,22 +527,22 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
}
@Test
- public void testContextSharingCreateVisibleDestroy1() throws InterruptedException, InvocationTargetException {
+ public void test01UseAWTNotShared() throws InterruptedException, InvocationTargetException {
testContextSharingCreateVisibleDestroy(false, false);
}
@Test
- public void testContextSharingCreateVisibleDestroy2() throws InterruptedException, InvocationTargetException {
+ public void test02UseAWTSharedContext() throws InterruptedException, InvocationTargetException {
testContextSharingCreateVisibleDestroy(false, true);
}
@Test
- public void testContextSharingCreateVisibleDestroy3() throws InterruptedException, InvocationTargetException {
+ public void test10UseNEWTNotShared() throws InterruptedException, InvocationTargetException {
testContextSharingCreateVisibleDestroy(true, false);
}
@Test
- public void testContextSharingCreateVisibleDestroy4() throws InterruptedException, InvocationTargetException {
+ public void test11UseNEWTSharedContext() throws InterruptedException, InvocationTargetException {
testContextSharingCreateVisibleDestroy(true, true);
}
@@ -507,24 +552,23 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
*/
public void testContextSharingCreateVisibleDestroy(final boolean useNewt, final boolean shareContext) throws InterruptedException, InvocationTargetException {
final JFrame frame = new JFrame("Simple JOGL App for testing context sharing");
+ final WindowClosingListener awtClosingListener = AWTRobotUtil.addClosingListener(frame);
+
//
// GLDrawableFactory factory = GLDrawableFactory.getFactory(GLProfile.get(GLProfile.GL2));
// GLContext sharedContext = factory.getOrCreateSharedContext(factory.getDefaultDevice());
//
- GLCapabilities glCapabilities = new GLCapabilities(GLProfile.get(GLProfile.GL2));
+ final GLCapabilities glCapabilities = new GLCapabilities(GLProfile.get(GLProfile.GL2));
glCapabilities.setSampleBuffers(true);
glCapabilities.setNumSamples(4);
final GLOffscreenAutoDrawable sharedDrawable;
- final GLContext sharedContext;
if(shareContext) {
sharedDrawable = initShared(glCapabilities);
- sharedContext = sharedDrawable.getContext();
} else {
sharedDrawable = null;
- sharedContext = null;
}
-
+
final TwoTriangles eventListener1 = new TwoTriangles(640, 480, shareContext);
final TwoTriangles eventListener2 = new TwoTriangles(320, 480, shareContext);
@@ -534,14 +578,19 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
final GLAutoDrawable openGLAutoDrawable2;
if (useNewt) {
- GLWindow glWindow1 = GLWindow.create(glCapabilities);
- glWindow1.setSharedContext(sharedContext);
- NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(glWindow1);
+ final GLWindow glWindow1 = GLWindow.create(glCapabilities);
+ if(shareContext) {
+ glWindow1.setSharedAutoDrawable(sharedDrawable);
+ }
+ final NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(glWindow1);
newtCanvasAWT1.setPreferredSize(new Dimension(eventListener1.canvasWidth, eventListener1.canvasHeight));
glWindow1.addGLEventListener(eventListener1);
//
- GLWindow glWindow2 = GLWindow.create(glCapabilities);
- NewtCanvasAWT newtCanvasAWT2 = new NewtCanvasAWT(glWindow2);
+ final GLWindow glWindow2 = GLWindow.create(glCapabilities);
+ if(shareContext) {
+ glWindow2.setSharedAutoDrawable(sharedDrawable);
+ }
+ final NewtCanvasAWT newtCanvasAWT2 = new NewtCanvasAWT(glWindow2);
newtCanvasAWT2.setPreferredSize(new Dimension(eventListener2.canvasWidth, eventListener2.canvasHeight));
glWindow2.addGLEventListener(eventListener2);
@@ -557,8 +606,10 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
final GLCanvas canvas2;
if (shareContext) {
- canvas1 = new GLCanvas(glCapabilities, sharedContext);
- canvas2 = new GLCanvas(glCapabilities, sharedContext);
+ canvas1 = new GLCanvas(glCapabilities);
+ canvas1.setSharedAutoDrawable(sharedDrawable);
+ canvas2 = new GLCanvas(glCapabilities);
+ canvas2.setSharedAutoDrawable(sharedDrawable);
} else {
canvas1 = new GLCanvas(glCapabilities);
canvas2 = new GLCanvas(glCapabilities);
@@ -578,52 +629,52 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
// Create slider for x rotation.
// The vertically oriented slider rotates around the x axis
- final JSlider xAxisRotationSlider = new JSlider(JSlider.VERTICAL, -180, 180, 1);
+ final JSlider xAxisRotationSlider = new JSlider(SwingConstants.VERTICAL, -180, 180, 1);
xAxisRotationSlider.setPaintTicks(false);
xAxisRotationSlider.setPaintLabels(false);
xAxisRotationSlider.setSnapToTicks(false);
xAxisRotationSlider.addChangeListener(new ChangeListener() {
- public void stateChanged(ChangeEvent e) {
+ public void stateChanged(final ChangeEvent e) {
eventListener1.setXAxisRotation(xAxisRotationSlider.getValue());
eventListener2.setXAxisRotation(xAxisRotationSlider.getValue());
}
});
- JLabel xAxisRotationLabel = new JLabel("X-Axis Rotation");
+ final JLabel xAxisRotationLabel = new JLabel("X-Axis Rotation");
// Create slider for y rotation.
// The horizontally oriented slider rotates around the y axis
- final JSlider yAxisRotationSlider = new JSlider(JSlider.HORIZONTAL, -180, 180, 1);
+ final JSlider yAxisRotationSlider = new JSlider(SwingConstants.HORIZONTAL, -180, 180, 1);
yAxisRotationSlider.setPaintTicks(false);
yAxisRotationSlider.setPaintLabels(false);
yAxisRotationSlider.setSnapToTicks(false);
yAxisRotationSlider.addChangeListener(new ChangeListener() {
- public void stateChanged(ChangeEvent e) {
+ public void stateChanged(final ChangeEvent e) {
eventListener1.setYAxisRotation(yAxisRotationSlider.getValue());
eventListener2.setYAxisRotation(yAxisRotationSlider.getValue());
}
});
- JLabel yAxisRotationLabel = new JLabel("Y-Axis Rotation");
+ final JLabel yAxisRotationLabel = new JLabel("Y-Axis Rotation");
// Create slider for view distance factor.
// We want a range of 0.0 to 10.0 with 0.1 increments (so we can scale down using 0.0 to 1.0).
// So, set JSlider to 0 to 100 and divide by 10.0 in stateChanged
- final JSlider viewDistanceFactorSlider = new JSlider(JSlider.HORIZONTAL, 0, 100, 10);
+ final JSlider viewDistanceFactorSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 100, 10);
viewDistanceFactorSlider.setPaintTicks(false);
viewDistanceFactorSlider.setPaintLabels(false);
viewDistanceFactorSlider.setSnapToTicks(false);
viewDistanceFactorSlider.addChangeListener(new ChangeListener() {
- public void stateChanged(ChangeEvent e) {
- eventListener1.setViewDistanceFactor((float) viewDistanceFactorSlider.getValue() / 10.0f);
- eventListener2.setViewDistanceFactor((float) viewDistanceFactorSlider.getValue() / 10.0f);
+ public void stateChanged(final ChangeEvent e) {
+ eventListener1.setViewDistanceFactor(viewDistanceFactorSlider.getValue() / 10.0f);
+ eventListener2.setViewDistanceFactor(viewDistanceFactorSlider.getValue() / 10.0f);
}
});
- JLabel viewDistanceFactorLabel = new JLabel("View Distance Factor");
+ final JLabel viewDistanceFactorLabel = new JLabel("View Distance Factor");
// group the view distance and label into a vertical panel
- JPanel viewDistancePanel = new JPanel();
+ final JPanel viewDistancePanel = new JPanel();
viewDistancePanel.setLayout(new BoxLayout(viewDistancePanel, BoxLayout.PAGE_AXIS));
viewDistancePanel.add(Box.createVerticalGlue());
viewDistancePanel.add(viewDistanceFactorSlider);
@@ -631,14 +682,14 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
viewDistancePanel.add(Box.createVerticalGlue());
// group both OpenGL canvases / windows into a horizontal panel
- JPanel openGLPanel = new JPanel();
+ final JPanel openGLPanel = new JPanel();
openGLPanel.setLayout(new BoxLayout(openGLPanel, BoxLayout.LINE_AXIS));
openGLPanel.add(openGLComponent1);
openGLPanel.add(Box.createHorizontalStrut(5));
openGLPanel.add(openGLComponent2);
// group the open GL panel and the y-axis rotation slider into a vertical panel.
- JPanel canvasAndYAxisPanel = new JPanel();
+ final JPanel canvasAndYAxisPanel = new JPanel();
canvasAndYAxisPanel.setLayout(new BoxLayout(canvasAndYAxisPanel, BoxLayout.PAGE_AXIS));
canvasAndYAxisPanel.add(openGLPanel);
canvasAndYAxisPanel.add(Box.createVerticalGlue());
@@ -646,12 +697,12 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
canvasAndYAxisPanel.add(yAxisRotationLabel);
// group the X-axis rotation slider and label into a horizontal panel.
- JPanel xAxisPanel = new JPanel();
+ final JPanel xAxisPanel = new JPanel();
xAxisPanel.setLayout(new BoxLayout(xAxisPanel, BoxLayout.LINE_AXIS));
xAxisPanel.add(xAxisRotationSlider);
xAxisPanel.add(xAxisRotationLabel);
- JPanel mainPanel = (JPanel) frame.getContentPane();
+ final JPanel mainPanel = (JPanel) frame.getContentPane();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS));
mainPanel.add(viewDistancePanel);
mainPanel.add(Box.createHorizontalGlue());
@@ -671,7 +722,7 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
frame.addWindowListener(new WindowAdapter() {
@Override
- public void windowClosing(WindowEvent e) {
+ public void windowClosing(final WindowEvent e) {
closingSemaphore.release();
}
});
@@ -687,9 +738,9 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
// wait for the window to be visible and start the animation
try {
- boolean windowOpened = windowOpenSemaphore.tryAcquire(5000, TimeUnit.MILLISECONDS);
+ final boolean windowOpened = windowOpenSemaphore.tryAcquire(5000, TimeUnit.MILLISECONDS);
Assert.assertEquals(true, windowOpened);
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
System.err.println("Closing wait interrupted: " + e.getMessage());
}
animator.start();
@@ -699,10 +750,10 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
while(animator.isAnimating() && animator.getTotalFPSDuration() < durationPerTest) {
Thread.sleep(100);
}
- AWTRobotUtil.closeWindow(frame, true);
- boolean windowClosed = closingSemaphore.tryAcquire(5000, TimeUnit.MILLISECONDS);
+ AWTRobotUtil.closeWindow(frame, true, awtClosingListener);
+ final boolean windowClosed = closingSemaphore.tryAcquire(5000, TimeUnit.MILLISECONDS);
Assert.assertEquals(true, windowClosed);
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
System.err.println("Closing wait interrupted: " + e.getMessage());
}
animator.stop();
@@ -724,9 +775,9 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
// wait for orderly destruction; it seems that if we share a GLContext across newt windows, bad things happen;
// I must be doing something wrong but I haven't figured it out yet
try {
- boolean windowsDisposed = closingSemaphore.tryAcquire(5000, TimeUnit.MILLISECONDS);
+ final boolean windowsDisposed = closingSemaphore.tryAcquire(5000, TimeUnit.MILLISECONDS);
Assert.assertEquals(true, windowsDisposed);
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
System.err.println("Closing wait interrupted: " + e.getMessage());
}
@@ -742,44 +793,32 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase {
if (acquired){
disposalSuccesses++;
}
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
System.err.println("Clean exit interrupted: " + e.getMessage());
}
Assert.assertEquals(true, disposalSuccesses == 2);
-
+
releaseShared(sharedDrawable);
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String[] args) throws IOException {
+ public static void main(final String[] args) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
if (++i < args.length) {
durationPerTest = atoi(args[i]);
}
- }
+ }
}
-
- String testname = TestSharedContextNewtAWTBug523.class.getName();
- org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
- testname,
- "filtertrace=true",
- "haltOnError=false",
- "haltOnFailure=false",
- "showoutput=true",
- "outputtoformatters=true",
- "logfailedtests=true",
- "logtestlistenerevents=true",
- "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
- "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+testname+".xml" } );
+ org.junit.runner.JUnitCore.main(TestSharedContextNewtAWTBug523.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java
index 6f108d862..855dc9cc6 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,36 +20,61 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import com.jogamp.newt.opengl.GLWindow;
import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.media.opengl.GLProfile;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+/**
+ * Sharing the VBO of 3 GearsES1 instances, each in their own GLWindow.
+ * <p>
+ * This is achieved by creating a <i>master</i> GLContext to an offscreen invisible GLAutoDrawable,
+ * which is then shared by the 3 GLContext of the three GLWindow instances.
+ * </p>
+ * <p>
+ * The original VBO is created by attaching a GearsES1 instance to
+ * the <i>master</i> GLAutoDrawable and initializing it.
+ * </p>
+ * <p>
+ * Above method allows random creation of all GLWindow instances.
+ * </p>
+ * <p>
+ * One animator is being used, hence the GLWindow, GLDrawable and GLContext
+ * creation of all 3 GLWindows is sequential.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestSharedContextVBOES1NEWT extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
static int width, height;
- GLOffscreenAutoDrawable sharedDrawable;
+ GLAutoDrawable sharedDrawable;
GearsES1 sharedGears;
@BeforeClass
@@ -66,14 +91,22 @@ public class TestSharedContextVBOES1NEWT extends UITestCase {
}
}
- private void initShared() {
- sharedDrawable = GLDrawableFactory.getFactory(glp).createOffscreenAutoDrawable(null, caps, null, width, height, null);
+ private void initShared() throws InterruptedException {
+ final GLDrawable dummyDrawable = GLDrawableFactory.getFactory(glp).createDummyDrawable(null, true /* createNewDevice */, caps, null);
+ dummyDrawable.setRealized(true);
+ sharedDrawable = new GLAutoDrawableDelegate(dummyDrawable, null, null, true /*ownDevice*/, null) { };
Assert.assertNotNull(sharedDrawable);
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(sharedDrawable, true));
+
sharedGears = new GearsES1();
Assert.assertNotNull(sharedGears);
sharedDrawable.addGLEventListener(sharedGears);
// init and render one frame, which will setup the Gears display lists
sharedDrawable.display();
+ final GLContext ctxM = sharedDrawable.getContext();
+ Assert.assertTrue("Master ctx not created", AWTRobotUtil.waitForContextCreated(sharedDrawable, true));
+ Assert.assertTrue("Master Ctx is shared before shared creation", !ctxM.isShared());
+ Assert.assertTrue("Master Gears is shared", !sharedGears.usesSharedGears());
}
private void releaseShared() {
@@ -81,19 +114,20 @@ public class TestSharedContextVBOES1NEWT extends UITestCase {
sharedDrawable.destroy();
}
- protected GLWindow runTestGL(Animator animator, int x, int y, boolean useShared, boolean vsync) throws InterruptedException {
- GLWindow glWindow = GLWindow.create(caps);
+ protected GLWindow runTestGL(final Animator animator, final int x, final int y, final boolean useShared, final boolean vsync) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
+ glWindow.setPosition(x, y);
glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared);
if(useShared) {
- glWindow.setSharedContext(sharedDrawable.getContext());
+ glWindow.setSharedAutoDrawable(sharedDrawable);
}
glWindow.setSize(width, height);
- GearsES1 gears = new GearsES1(vsync ? 1 : 0);
+ final GearsES1 gears = new GearsES1(vsync ? 1 : 0);
if(useShared) {
- gears.setGears(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3());
+ gears.setSharedGears(sharedGears);
}
glWindow.addGLEventListener(gears);
@@ -102,23 +136,32 @@ public class TestSharedContextVBOES1NEWT extends UITestCase {
glWindow.setVisible(true);
Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true));
Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(glWindow, true));
- glWindow.setPosition(x, y);
-
+ MiscUtils.dumpSharedGLContext("Master Context", sharedDrawable.getContext());
+ MiscUtils.dumpSharedGLContext("New Context", glWindow.getContext());
+ if( useShared ) {
+ Assert.assertEquals("Master Context not shared as expected", true, sharedDrawable.getContext().isShared());
+ Assert.assertEquals("Master Context is different", sharedDrawable.getContext(), glWindow.getContext().getSharedMaster());
+ } else {
+
+ }
+ Assert.assertEquals("New Context not shared as expected", useShared, glWindow.getContext().isShared());
+ Assert.assertEquals("Gears is not shared as expected", useShared, gears.usesSharedGears());
return glWindow;
}
@Test
public void test01() throws InterruptedException {
initShared();
- Animator animator = new Animator();
- GLWindow f1 = runTestGL(animator, 0, 0, true, false);
- InsetsImmutable insets = f1.getInsets();
- GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(),
+ final Animator animator = new Animator();
+ final GLWindow f1 = runTestGL(animator, 0, 0, true, false);
+ final InsetsImmutable insets = f1.getInsets();
+ final GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(),
f1.getY()+0, true, false);
- GLWindow f3 = runTestGL(animator, f1.getX()+0,
- f1.getY()+height+insets.getTotalHeight(), false, true);
- animator.setUpdateFPSFrames(1, null);
+ final GLWindow f3 = runTestGL(animator, f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), false, true);
+ animator.setUpdateFPSFrames(1, null);
animator.start();
while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
@@ -134,13 +177,13 @@ public class TestSharedContextVBOES1NEWT extends UITestCase {
static long duration = 500; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
}
org.junit.runner.JUnitCore.main(TestSharedContextVBOES1NEWT.class.getName());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java
new file mode 100644
index 000000000..fcbfcb19b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java
@@ -0,0 +1,399 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.Frame;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Sharing the VBO of 3 GearsES2 instances, each in their own AWT GLCanvas.
+ * <p>
+ * This is achieved by using the 1st GLCanvas as the <i>master</i>
+ * and using the build-in blocking mechanism to postpone creation
+ * of the 2nd and 3rd GLCanvas until the 1st GLCanvas's GLContext becomes created.
+ * </p>
+ * <p>
+ * Above method allows random creation of the 1st GLCanvas, which triggers
+ * creation of the <i>dependent</i> other GLCanvas sharing it's GLContext.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSharedContextVBOES2AWT3 extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ width = 256;
+ height = 256;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ protected GLCanvas createGLCanvas(final Frame frame, final int x, final int y, final GearsES2 gears) throws InterruptedException {
+ final GLCanvas glCanvas = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas);
+ glCanvas.addGLEventListener(gears);
+ frame.add(glCanvas);
+ frame.setLocation(x, y);
+ frame.setSize(width, height);
+ frame.setTitle("AWT GLCanvas Shared Gears Test: "+x+"/"+y+" shared true");
+ return glCanvas;
+ }
+
+ @Test
+ public void test01SyncedOneAnimatorCleanDtorOrder() throws InterruptedException, InvocationTargetException {
+ syncedOneAnimator(true);
+ }
+
+ @Test
+ public void test02SyncedOneAnimatorDirtyDtorOrder() throws InterruptedException, InvocationTargetException {
+ syncedOneAnimator(false);
+ }
+
+ public void syncedOneAnimator(final boolean destroyCleanOrder) throws InterruptedException, InvocationTargetException {
+ final Frame f1 = new Frame();
+ final Animator animator = new Animator();
+ final GearsES2 g1 = new GearsES2(0);
+ final GLCanvas c1 = createGLCanvas(f1, 0, 0, g1);
+ animator.add(c1);
+
+ final Frame f2 = new Frame();
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1);
+ final GLCanvas c2 = createGLCanvas(f2, f1.getX()+width,
+ f1.getY()+0, g2);
+ c2.setSharedAutoDrawable(c1);
+ animator.add(c2);
+
+ final Frame f3 = new Frame();
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1);
+ final GLCanvas c3 = createGLCanvas(f3, f1.getX()+0,
+ f1.getY()+height, g3);
+ c3.setSharedAutoDrawable(c1);
+ animator.add(c3);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f2.setVisible(true); // shall wait until f1 is ready
+ f1.setVisible(true); // master ..
+ f3.setVisible(true); // shall wait until f1 is ready
+ } } );
+ animator.start(); // kicks off GLContext .. and hence gears of f2 + f3 completion
+
+ Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid)
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ final GLContext ctx1 = c1.getContext();
+ final GLContext ctx2 = c2.getContext();
+ final GLContext ctx3 = c3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+
+ if( destroyCleanOrder ) {
+ System.err.println("XXX Destroy in clean order NOW");
+ } else {
+ System.err.println("XXX Destroy in creation order NOW - Driver Impl. Ma trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs.");
+ }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ if( destroyCleanOrder ) {
+ f3.dispose();
+ } else {
+ f1.dispose();
+ }
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }});
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ f2.dispose();
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }});
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ if( destroyCleanOrder ) {
+ f1.dispose();
+ } else {
+ f3.dispose();
+ }
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }});
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false));
+ }
+
+ @Test
+ public void test11AsyncEachAnimatorCleanDtorOrder() throws InterruptedException, InvocationTargetException {
+ syncedOneAnimator(true);
+ }
+
+ @Test
+ public void test12AsyncEachAnimatorDirtyDtorOrder() throws InterruptedException, InvocationTargetException {
+ asyncEachOneAnimator(false);
+ }
+
+ public void asyncEachOneAnimator(final boolean destroyCleanOrder) throws InterruptedException, InvocationTargetException {
+ final Frame f1 = new Frame();
+ final Animator a1 = new Animator();
+ final GearsES2 g1 = new GearsES2(0);
+ final GLCanvas c1 = createGLCanvas(f1, 0, 0, g1);
+ a1.add(c1);
+ a1.start();
+ // f1.setVisible(true); // we do this post f2 .. to test pending creation!
+
+ final Frame f2 = new Frame();
+ final Animator a2 = new Animator();
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1);
+ final GLCanvas c2 = createGLCanvas(f2, f1.getX()+width, f1.getY()+0, g2);
+ c2.setSharedAutoDrawable(c1);
+ a2.add(c2);
+ a2.start();
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f2.setVisible(true);
+ } } );
+
+ Thread.sleep(200); // wait a while ..
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f1.setVisible(true); // test pending creation of f2
+ } } );
+
+ final Frame f3 = new Frame();
+ final Animator a3 = new Animator();
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1);
+ final GLCanvas c3 = createGLCanvas(f3, f1.getX()+0, f1.getY()+height, g3);
+ c3.setSharedAutoDrawable(c1);
+ a3.add(c3);
+ a3.start();
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f3.setVisible(true);
+ } } );
+
+ Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid)
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ final GLContext ctx1 = c1.getContext();
+ final GLContext ctx2 = c2.getContext();
+ final GLContext ctx3 = c3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ a1.stop();
+ Assert.assertEquals(false, a1.isAnimating());
+ a2.stop();
+ Assert.assertEquals(false, a2.isAnimating());
+ a3.stop();
+ Assert.assertEquals(false, a3.isAnimating());
+
+ if( destroyCleanOrder ) {
+ System.err.println("XXX Destroy in clean order NOW");
+ } else {
+ System.err.println("XXX Destroy in creation order NOW - Driver Impl. Ma trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs.");
+ }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ if( destroyCleanOrder ) {
+ f3.dispose();
+ } else {
+ f1.dispose();
+ }
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }});
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ f2.dispose();
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }});
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ if( destroyCleanOrder ) {
+ f1.dispose();
+ } else {
+ f3.dispose();
+ }
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }});
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false));
+ }
+
+ static long duration = 1000; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestSharedContextVBOES2AWT3.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java
new file mode 100644
index 000000000..bac84d4fb
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java
@@ -0,0 +1,323 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.Frame;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Sharing the VBO of 3 GearsES2 instances, each in their own AWT GLJPanel.
+ * <p>
+ * This is achieved by using the 1st GLJPanel as the <i>master</i>
+ * and using the build-in blocking mechanism to postpone creation
+ * of the 2nd and 3rd GLJPanel until the 1st GLJPanel 's GLContext becomes created.
+ * </p>
+ * <p>
+ * Above method allows random creation of the 1st GLJPanel, which triggers
+ * creation of the <i>dependent</i> other GLJPanel sharing it's GLContext.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSharedContextVBOES2AWT3b extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ width = 256;
+ height = 256;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ protected GLJPanel createGLJPanel(final Frame frame, final int x, final int y, final GearsES2 gears) throws InterruptedException {
+ final GLJPanel glCanvas = new GLJPanel(caps);
+ Assert.assertNotNull(glCanvas);
+ glCanvas.addGLEventListener(gears);
+ frame.add(glCanvas);
+ frame.setLocation(x, y);
+ frame.setSize(width, height);
+ frame.setTitle("AWT GLJPanel Shared Gears Test: "+x+"/"+y+" shared true");
+ return glCanvas;
+ }
+
+ @Test
+ public void test01SyncedOneAnimator() throws InterruptedException, InvocationTargetException {
+ final Frame f1 = new Frame();
+ final Animator animator = new Animator();
+ final GearsES2 g1 = new GearsES2(0);
+ final GLJPanel c1 = createGLJPanel(f1, 0, 0, g1);
+ animator.add(c1);
+
+ final Frame f2 = new Frame();
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1);
+ final GLJPanel c2 = createGLJPanel(f2, f1.getX()+width,
+ f1.getY()+0, g2);
+ c2.setSharedAutoDrawable(c1);
+ animator.add(c2);
+
+ final Frame f3 = new Frame();
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1);
+ final GLJPanel c3 = createGLJPanel(f3, f1.getX()+0,
+ f1.getY()+height, g3);
+ c3.setSharedAutoDrawable(c1);
+ animator.add(c3);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f2.setVisible(true); // shall wait until f1 is ready
+ f1.setVisible(true); // master ..
+ f3.setVisible(true); // shall wait until f1 is ready
+ } } );
+ animator.start(); // kicks off GLContext .. and hence gears of f2 + f3 completion
+
+ Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid)
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ final GLContext ctx1 = c1.getContext();
+ final GLContext ctx2 = c2.getContext();
+ final GLContext ctx3 = c3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ f3.dispose();
+ f2.dispose();
+ f1.dispose();
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }});
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false));
+ }
+
+ @Test
+ public void test02AsyncEachAnimator() throws InterruptedException, InvocationTargetException {
+ final Frame f1 = new Frame();
+ final Animator a1 = new Animator();
+ final GearsES2 g1 = new GearsES2(0);
+ final GLJPanel c1 = createGLJPanel(f1, 0, 0, g1);
+ a1.add(c1);
+ a1.start();
+ // f1.setVisible(true); // we do this post f2 .. to test pending creation!
+
+ final Frame f2 = new Frame();
+ final Animator a2 = new Animator();
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1);
+ final GLJPanel c2 = createGLJPanel(f2, f1.getX()+width, f1.getY()+0, g2);
+ c2.setSharedAutoDrawable(c1);
+ a2.add(c2);
+ a2.start();
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f2.setVisible(true);
+ } } );
+
+ Thread.sleep(200); // wait a while ..
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f1.setVisible(true); // test pending creation of f2
+ } } );
+
+ final Frame f3 = new Frame();
+ final Animator a3 = new Animator();
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1);
+ final GLJPanel c3 = createGLJPanel(f3, f1.getX()+0, f1.getY()+height, g3);
+ c3.setSharedAutoDrawable(c1);
+ a3.add(c3);
+ a3.start();
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f3.setVisible(true);
+ } } );
+
+ Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid)
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ final GLContext ctx1 = c1.getContext();
+ final GLContext ctx2 = c2.getContext();
+ final GLContext ctx3 = c3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ a1.stop();
+ Assert.assertEquals(false, a1.isAnimating());
+ a2.stop();
+ Assert.assertEquals(false, a2.isAnimating());
+ a3.stop();
+ Assert.assertEquals(false, a3.isAnimating());
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ f3.dispose();
+ f2.dispose();
+ f1.dispose();
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }});
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false));
+ }
+
+ static long duration = 1000; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestSharedContextVBOES2AWT3b.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT.java
deleted file mode 100644
index 4aa977ae8..000000000
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.opengl.test.junit.jogl.acore;
-
-import com.jogamp.common.os.Platform;
-import com.jogamp.common.util.VersionNumber;
-import com.jogamp.newt.opengl.GLWindow;
-
-import javax.media.nativewindow.util.InsetsImmutable;
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLProfile;
-import com.jogamp.opengl.util.Animator;
-
-import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class TestSharedContextVBOES2NEWT extends UITestCase {
- static GLProfile glp;
- static GLCapabilities caps;
- static int width, height;
- GLAutoDrawable sharedDrawable;
- GearsES2 sharedGears;
-
- @BeforeClass
- public static void initClass() {
- if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
- glp = GLProfile.get(GLProfile.GL2ES2);
- Assert.assertNotNull(glp);
- caps = new GLCapabilities(glp);
- Assert.assertNotNull(caps);
- width = 256;
- height = 256;
- } else {
- setTestSupported(false);
- }
- }
-
- private void initShared(boolean onscreen) {
- if(onscreen) {
- GLWindow glWindow = GLWindow.create(caps);
- Assert.assertNotNull(glWindow);
- glWindow.setSize(width, height);
- glWindow.setVisible(true);
- sharedDrawable = glWindow;
- } else {
- sharedDrawable = GLDrawableFactory.getFactory(glp).createOffscreenAutoDrawable(null, caps, null, width, height, null);
- }
- Assert.assertNotNull(sharedDrawable);
- sharedGears = new GearsES2();
- Assert.assertNotNull(sharedGears);
- sharedDrawable.addGLEventListener(sharedGears);
- // init and render one frame, which will setup the Gears display lists
- sharedDrawable.display();
- }
-
- private void releaseShared() {
- Assert.assertNotNull(sharedDrawable);
- sharedDrawable.destroy();
- sharedDrawable = null;
- }
-
- protected GLWindow runTestGL(Animator animator, int x, int y, boolean useShared, boolean vsync) throws InterruptedException {
- GLWindow glWindow = GLWindow.create(caps);
- Assert.assertNotNull(glWindow);
- glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared);
- if(useShared) {
- glWindow.setSharedContext(sharedDrawable.getContext());
- }
-
- glWindow.setSize(width, height);
-
- GearsES2 gears = new GearsES2(vsync ? 1 : 0);
- if(useShared) {
- gears.setGears(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3());
- }
- glWindow.addGLEventListener(gears);
-
- animator.add(glWindow);
- animator.start();
- glWindow.setVisible(true);
- Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true));
- Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true));
-
- glWindow.setPosition(x, y);
-
- return glWindow;
- }
-
- @Test
- public void testCommonAnimatorSharedOnscreen() throws InterruptedException {
- initShared(true);
- Animator animator = new Animator();
- GLWindow f1 = runTestGL(animator, 0, 0, true, false);
- InsetsImmutable insets = f1.getInsets();
- GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(),
- f1.getY()+0, true, false);
- GLWindow f3 = runTestGL(animator, f1.getX()+0,
- f1.getY()+height+insets.getTotalHeight(), true, false);
- try {
- Thread.sleep(duration);
- } catch(Exception e) {
- e.printStackTrace();
- }
- animator.stop();
-
- f1.destroy();
- f2.destroy();
- f3.destroy();
- Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
- Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
- Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
-
- releaseShared();
- }
-
- @Test
- public void testCommonAnimatorSharedOffscreen() throws InterruptedException {
- initShared(false);
- Animator animator = new Animator();
- GLWindow f1 = runTestGL(animator, 0, 0, true, false);
- InsetsImmutable insets = f1.getInsets();
- GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(),
- f1.getY()+0, true, false);
- GLWindow f3 = runTestGL(animator, f1.getX()+0,
- f1.getY()+height+insets.getTotalHeight(), true, false);
- try {
- Thread.sleep(duration);
- } catch(Exception e) {
- e.printStackTrace();
- }
- animator.stop();
-
- f1.destroy();
- f2.destroy();
- f3.destroy();
- Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
- Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
- Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
-
- releaseShared();
- }
-
- @Test
- public void testEachWithAnimatorSharedOffscreen() throws InterruptedException {
- VersionNumber osx1070 = new VersionNumber(10,7,0);
- if( Platform.getOSType() == Platform.OSType.MACOS && Platform.getOSVersionNumber().compareTo(osx1070) > 0 ) {
- // instable on OSX .. driver/OS bug when multi threading (3 animator)
- System.err.println("Shared context w/ 3 context each running in there own thread is instable here on OSX 10.7.4/NVidia,");
- System.err.println("SIGSEGV @ glDrawArrays / glBindBuffer .. any shared VBO.");
- System.err.println("Seems to run fine on 10.6.8/NVidia.");
- return;
- }
- initShared(false);
- Animator animator1 = new Animator();
- Animator animator2 = new Animator();
- Animator animator3 = new Animator();
- GLWindow f1 = runTestGL(animator1, 0, 0, true, false);
- InsetsImmutable insets = f1.getInsets();
- GLWindow f2 = runTestGL(animator2, f1.getX()+width+insets.getTotalWidth(),
- f1.getY()+0, true, false);
- GLWindow f3 = runTestGL(animator3, f1.getX()+0,
- f1.getY()+height+insets.getTotalHeight(), true, false);
-
- try {
- Thread.sleep(duration);
- } catch(Exception e) {
- e.printStackTrace();
- }
- animator1.stop();
- animator2.stop();
- animator3.stop();
-
- f1.destroy();
- f2.destroy();
- f3.destroy();
- Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
- Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
- Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
-
- releaseShared();
- }
-
- static long duration = 2000; // ms
-
- public static void main(String args[]) {
- for(int i=0; i<args.length; i++) {
- if(args[i].equals("-time")) {
- i++;
- try {
- duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
- }
- }
- /**
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
- System.err.println("Press enter to continue");
- System.err.println(stdin.readLine()); */
- org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT.class.getName());
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java
new file mode 100644
index 000000000..54f60f576
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java
@@ -0,0 +1,271 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.util.List;
+
+import com.jogamp.newt.opengl.GLWindow;
+
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Sharing the VBO of 3 GearsES2 instances, each in their own GLWindow.
+ * <p>
+ * This is achieved by relying on the sequential creation
+ * of the 3 GLWindows with their GLDrawable and GLContext.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSharedContextVBOES2NEWT0 extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ width = 256;
+ height = 256;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ protected GLWindow runTestGL(final Animator animator, final int x, final int y, final GearsES2 gears, final GLAutoDrawable sharedDrawable) throws InterruptedException {
+ final boolean useShared = null != sharedDrawable;
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setPosition(x, y);
+ glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared);
+ if(useShared) {
+ glWindow.setSharedAutoDrawable(sharedDrawable);
+ }
+ glWindow.setSize(width, height);
+ glWindow.addGLEventListener(gears);
+
+ animator.add(glWindow);
+ glWindow.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true));
+ glWindow.display();
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(glWindow, true));
+ Assert.assertTrue("Gears not initialized", gears.waitForInit(true));
+
+ return glWindow;
+ }
+
+ @Test
+ public void test01CommonAnimatorSharedCopyBuffer() throws InterruptedException {
+ testCommonAnimatorSharedImpl(false);
+ }
+ @Test
+ public void test02CommonAnimatorMapBuffer() throws InterruptedException {
+ testCommonAnimatorSharedImpl(true);
+ }
+ private void testCommonAnimatorSharedImpl(final boolean useMappedBuffers) throws InterruptedException {
+ final Animator animator = new Animator();
+
+ //
+ // 1st
+ //
+ final GearsES2 g1 = new GearsES2(0);
+ g1.setUseMappedBuffers(useMappedBuffers);
+ g1.setValidateBuffers(true);
+ final GLWindow f1 = runTestGL(animator, 0, 0, g1, null);
+ final GLContext ctx1 = f1.getContext();
+ Assert.assertTrue("Ctx is shared before shared creation", !ctx1.isShared());
+ final InsetsImmutable insets = f1.getInsets();
+
+ MiscUtils.dumpSharedGLContext("XXX-C-1.1", ctx1);
+
+ //
+ // 2nd
+ //
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1);
+ final GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, g2, f1);
+ final GLContext ctx2 = f2.getContext();
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-2.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-2.2", ctx2);
+
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 1, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 1, ctx2Shares.size());
+ }
+
+ //
+ // 3rd
+ //
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1);
+ final GLWindow f3 = runTestGL(animator, f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), g3, f1);
+
+ final GLContext ctx3 = f3.getContext();
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ animator.start();
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ f3.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false));
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-D-0.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-D-0.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-D-0.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 1, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 1, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ }
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+
+ f2.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false));
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-D-1.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-D-1.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-D-1.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 0, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 1, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 1, ctx3Shares.size());
+ }
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+
+ f1.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false));
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-D-2.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-D-2.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-D-2.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", !ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", !ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", !ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 0, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 0, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 0, ctx3Shares.size());
+ }
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ }
+
+ static long duration = 1000; // ms
+ static long durationPostDestroy = 1000; // ms - ~60 frames post destroy
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT0.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java
new file mode 100644
index 000000000..2c547ec06
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java
@@ -0,0 +1,333 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import com.jogamp.newt.opengl.GLWindow;
+
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Sharing the VBO of 3 GearsES2 instances, each in their own GLWindow.
+ * <p>
+ * This is achieved by creating a <i>master</i> GLContext to an offscreen invisible GLAutoDrawable,
+ * which is then shared by the 3 GLContext of the three GLWindow instances.
+ * </p>
+ * <p>
+ * The original VBO is created by attaching a GearsES2 instance to
+ * the <i>master</i> GLAutoDrawable and initializing it.
+ * </p>
+ * <p>
+ * Above method allows random creation of all GLWindow instances.
+ * </p>
+ * <p>
+ * One tests uses only one animator, where the GLWindow, GLDrawable and GLContext
+ * creation of all 3 GLWindows is sequential.
+ * </p>
+ * <p>
+ * Another tests uses 3 animator, one for each GLWindow,
+ * where the GLWindow, GLDrawable and GLContext creation
+ * of all 3 GLWindows is <i>random</i>.
+ * This fact benefits from the <i>master</i> GLContext/GLAutoDrawable,
+ * since it is guaranteed it exist and is realized at the time of the <i>shared</i>
+ * GLWindow creation.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSharedContextVBOES2NEWT1 extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+ GLAutoDrawable sharedDrawable;
+ GearsES2 sharedGears;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ width = 256;
+ height = 256;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ private void initShared(final boolean onscreen) throws InterruptedException {
+ if(onscreen) {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+ sharedDrawable = glWindow;
+ } else {
+ sharedDrawable = GLDrawableFactory.getFactory(glp).createDummyAutoDrawable(null, true /* createNewDevice */, caps, null);
+ }
+ Assert.assertNotNull(sharedDrawable);
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(sharedDrawable, true));
+
+ sharedGears = new GearsES2();
+ Assert.assertNotNull(sharedGears);
+ sharedDrawable.addGLEventListener(sharedGears);
+ // init and render one frame, which will setup the Gears display lists
+ sharedDrawable.display();
+ final GLContext ctxM = sharedDrawable.getContext();
+ Assert.assertTrue("Master ctx not created", AWTRobotUtil.waitForContextCreated(sharedDrawable, true));
+ Assert.assertTrue("Master Ctx is shared before shared creation", !ctxM.isShared());
+ Assert.assertTrue("Master Gears not initialized", sharedGears.waitForInit(true));
+ System.err.println("Master Gears Init done: "+sharedGears);
+ Assert.assertTrue("Master Gears is shared", !sharedGears.usesSharedGears());
+ }
+
+ private void releaseShared() {
+ Assert.assertNotNull(sharedDrawable);
+ sharedDrawable.destroy();
+ sharedDrawable = null;
+ }
+
+ protected GLWindow runTestGL(final Animator animator, final int x, final int y, final boolean useShared, final boolean vsync) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setPosition(x, y);
+ glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared);
+ if(useShared) {
+ glWindow.setSharedAutoDrawable(sharedDrawable);
+ }
+
+ glWindow.setSize(width, height);
+
+ final GearsES2 gears = new GearsES2(vsync ? 1 : 0);
+ if(useShared) {
+ gears.setSharedGears(sharedGears);
+ }
+ glWindow.addGLEventListener(gears);
+
+ animator.add(glWindow);
+ animator.start();
+ glWindow.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(glWindow, true));
+
+ final GLContext sharedMasterContext = sharedDrawable.getContext();
+ MiscUtils.dumpSharedGLContext("Master Context", sharedMasterContext);
+ MiscUtils.dumpSharedGLContext("New Context", glWindow.getContext());
+ if( useShared ) {
+ Assert.assertEquals("Master Context not shared as expected", true, sharedMasterContext.isShared());
+ Assert.assertEquals("Master Context is different", sharedMasterContext, glWindow.getContext().getSharedMaster());
+ } else {
+ Assert.assertEquals("Master Context is not null", null, glWindow.getContext().getSharedMaster());
+ }
+ Assert.assertEquals("New Context not shared as expected", useShared, glWindow.getContext().isShared());
+
+ Assert.assertTrue("Gears not initialized", gears.waitForInit(true));
+ System.err.println("Slave Gears Init done: "+gears);
+ Assert.assertEquals("Gears is not shared as expected", useShared, gears.usesSharedGears());
+
+ return glWindow;
+ }
+
+ @Test
+ public void test01CommonAnimatorSharedOnscreen() throws InterruptedException {
+ initShared(true);
+ final Animator animator = new Animator();
+ final GLWindow f1 = runTestGL(animator, 0, 0, true, false);
+ final InsetsImmutable insets = f1.getInsets();
+ final GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, true, false);
+ final GLWindow f3 = runTestGL(animator, f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), true, false);
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ animator.stop();
+
+ f1.destroy();
+ f2.destroy();
+ f3.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false));
+
+ releaseShared();
+ }
+
+ @Test
+ public void test02EachWithAnimatorSharedOnscreen() throws InterruptedException {
+ initShared(true);
+ final Animator animator1 = new Animator();
+ final Animator animator2 = new Animator();
+ final Animator animator3 = new Animator();
+ final GLWindow f1 = runTestGL(animator1, 0, 0, true, false);
+ final InsetsImmutable insets = f1.getInsets();
+ final GLWindow f2 = runTestGL(animator2, f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, true, false);
+ final GLWindow f3 = runTestGL(animator3, f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), true, false);
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ animator1.stop();
+ animator2.stop();
+ animator3.stop();
+
+ f1.destroy();
+ f2.destroy();
+ f3.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false));
+
+ releaseShared();
+ }
+
+ @Test
+ public void test11CommonAnimatorSharedOffscreen() throws InterruptedException {
+ initShared(false);
+ final Animator animator = new Animator();
+ final GLWindow f1 = runTestGL(animator, 0, 0, true, false);
+ final InsetsImmutable insets = f1.getInsets();
+ final GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, true, false);
+ final GLWindow f3 = runTestGL(animator, f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), true, false);
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ animator.stop();
+
+ f1.destroy();
+ f2.destroy();
+ f3.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false));
+
+ releaseShared();
+ }
+
+ @Test
+ public void test12EachWithAnimatorSharedOffscreen() throws InterruptedException {
+ initShared(false);
+ final Animator animator1 = new Animator();
+ final Animator animator2 = new Animator();
+ final Animator animator3 = new Animator();
+ final GLWindow f1 = runTestGL(animator1, 0, 0, true, false);
+ final InsetsImmutable insets = f1.getInsets();
+ final GLWindow f2 = runTestGL(animator2, f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, true, false);
+ final GLWindow f3 = runTestGL(animator3, f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), true, false);
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ animator1.stop();
+ animator2.stop();
+ animator3.stop();
+
+ f1.destroy();
+ f2.destroy();
+ f3.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false));
+
+ releaseShared();
+ }
+
+ static long duration = 1000; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT1.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java
new file mode 100644
index 000000000..8d040222a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java
@@ -0,0 +1,359 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.util.List;
+
+import com.jogamp.newt.opengl.GLWindow;
+
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Sharing the VBO of 3 GearsES2 instances, each in their own GLWindow.
+ * <p>
+ * This is achieved by using the 1st GLWindow's GLContext as the <i>master</i>
+ * and synchronizing via GLSharedContextSetter to postpone creation
+ * of the 2nd and 3rd GLWindow until the 1st GLWindow's GLContext becomes created.
+ * </p>
+ * <p>
+ * Above method allows random creation of the 1st GLWindow, which triggers
+ * creation of the <i>dependent</i> other GLWindow sharing it's GLContext.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSharedContextVBOES2NEWT2 extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ width = 256;
+ height = 256;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ protected GLWindow createGLWindow(final int x, final int y, final GearsES2 gears) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setPosition(x, y);
+ glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared true");
+ glWindow.setSize(width, height);
+ glWindow.addGLEventListener(gears);
+
+ return glWindow;
+ }
+
+ @Test
+ public void test01SyncedOneAnimatorCleanDtorOrder() throws InterruptedException {
+ syncedOneAnimator(true);
+ }
+
+ @Test
+ public void test02SyncedOneAnimatorDirtyDtorOrder() throws InterruptedException {
+ syncedOneAnimator(false);
+ }
+
+ public void syncedOneAnimator(final boolean destroyCleanOrder) throws InterruptedException {
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GearsES2 g1 = new GearsES2(0);
+ g1.setSyncObjects(g1); // this is master, since rendered we must use it as sync
+ final GLWindow f1 = createGLWindow(0, 0, g1);
+ animator.add(f1);
+ final InsetsImmutable insets = f1.getInsets();
+
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1); // also uses master g1 as sync, if required
+ final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, g2);
+ f2.setSharedAutoDrawable(f1);
+ animator.add(f2);
+ f2.setVisible(true);
+
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1); // also uses master g1 as sync, if required
+ final GLWindow f3 = createGLWindow(f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), g3);
+ f3.setSharedAutoDrawable(f1);
+ animator.add(f3);
+ f3.setVisible(true);
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false));
+
+ f1.setVisible(true); // kick off f1 GLContext .. and hence allow f2 + f3 creation
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ final GLContext ctx1 = f1.getContext();
+ final GLContext ctx2 = f2.getContext();
+ final GLContext ctx3 = f3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ Assert.assertEquals("Ctx1 Master Context is different", ctx1, ctx1.getSharedMaster());
+ Assert.assertEquals("Ctx2 Master Context is different", ctx1, ctx2.getSharedMaster());
+ Assert.assertEquals("Ctx3 Master Context is different", ctx1, ctx3.getSharedMaster());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+
+ if( destroyCleanOrder ) {
+ System.err.println("XXX Destroy in clean order NOW");
+ f3.destroy();
+ f2.destroy();
+ f1.destroy();
+ } else {
+ System.err.println("XXX Destroy in creation order NOW - Driver Impl. May trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs.");
+ f1.destroy();
+ f2.destroy();
+ f3.destroy();
+ }
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
+ }
+
+ @Test
+ public void test11AsyncEachAnimatorCleanDtorOrder() throws InterruptedException {
+ asyncEachAnimator(true);
+ }
+
+ @Test
+ public void test12AsyncEachAnimatorDirtyDtorOrder() throws InterruptedException {
+ asyncEachAnimator(false);
+ }
+
+ public void asyncEachAnimator(final boolean destroyCleanOrder) throws InterruptedException {
+ final Animator a1 = new Animator();
+ final GearsES2 g1 = new GearsES2(0);
+ g1.setSyncObjects(g1); // this is master, since rendered we must use it as sync
+ final GLWindow f1 = createGLWindow(0, 0, g1);
+ a1.add(f1);
+ a1.start();
+
+ final InsetsImmutable insets = f1.getInsets();
+
+ final Animator a2 = new Animator();
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1); // also uses master g1 as sync, if required
+ final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, g2);
+ f2.setSharedAutoDrawable(f1);
+ a2.add(f2);
+ a2.start();
+ f2.setVisible(true);
+
+ final Animator a3 = new Animator();
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1); // also uses master g1 as sync, if required
+ final GLWindow f3 = createGLWindow(f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), g3);
+ f3.setSharedAutoDrawable(f1);
+ a3.add(f3);
+ a3.start();
+ f3.setVisible(true);
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false));
+
+ f1.setVisible(true); // kicks off f1 GLContext .. and hence gears of f2 + f3 completion
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ final GLContext ctx1 = f1.getContext();
+ final GLContext ctx2 = f2.getContext();
+ final GLContext ctx3 = f3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ Assert.assertEquals("Ctx1 Master Context is different", ctx1, ctx1.getSharedMaster());
+ Assert.assertEquals("Ctx2 Master Context is different", ctx1, ctx2.getSharedMaster());
+ Assert.assertEquals("Ctx3 Master Context is different", ctx1, ctx3.getSharedMaster());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ a1.stop();
+ Assert.assertEquals(false, a1.isAnimating());
+ a2.stop();
+ Assert.assertEquals(false, a2.isAnimating());
+ a3.stop();
+ Assert.assertEquals(false, a3.isAnimating());
+
+ if( destroyCleanOrder ) {
+ System.err.println("XXX Destroy in clean order NOW");
+ f3.destroy();
+ f2.destroy();
+ f1.destroy();
+ } else {
+ System.err.println("XXX Destroy in creation order NOW - Driver Impl. May trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs.");
+ f1.destroy();
+ f2.destroy();
+ f3.destroy();
+ }
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
+ }
+
+ static long duration = 1000; // ms
+ static boolean mainRun = false;
+
+ public static void main(final String args[]) {
+ mainRun = true;
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT2.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java
new file mode 100644
index 000000000..a0d111c4d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java
@@ -0,0 +1,396 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.util.List;
+
+import com.jogamp.newt.opengl.GLWindow;
+
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Sharing the VBO of 3 GearsES2 instances, each in their own GLWindow.
+ * <p>
+ * This is achieved by using the 1st GLWindow as the <i>master</i>
+ * and synchronizing via GLSharedContextSetter to postpone creation
+ * of the 2nd and 3rd GLWindow until the 1st GLWindow's GLContext becomes created.
+ * </p>
+ * <p>
+ * Above method allows random creation of the 1st GLWindow, which triggers
+ * creation of the <i>dependent</i> other GLWindow sharing it's GLContext.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSharedContextVBOES2NEWT3 extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ width = 256;
+ height = 256;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ protected GLWindow createGLWindow(final int x, final int y, final GearsES2 gears) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setPosition(x, y);
+ glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared true");
+ glWindow.setSize(width, height);
+ glWindow.addGLEventListener(gears);
+
+ return glWindow;
+ }
+
+ @Test
+ public void test01SyncedOneAnimatorCleanDtorOrderCopyBuffer() throws InterruptedException {
+ syncedOneAnimator(true, false);
+ }
+ @Test
+ public void test02SyncedOneAnimatorCleanDtorOrderMapBuffer() throws InterruptedException {
+ syncedOneAnimator(true, true);
+ }
+
+ @Test
+ public void test03SyncedOneAnimatorDirtyDtorOrderCopyBuffer() throws InterruptedException {
+ syncedOneAnimator(false, false);
+ }
+ @Test
+ public void test04SyncedOneAnimatorDirtyDtorOrderMapBuffer() throws InterruptedException {
+ syncedOneAnimator(false, true);
+ }
+
+ public void syncedOneAnimator(final boolean destroyCleanOrder, final boolean useMappedBuffers) throws InterruptedException {
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GearsES2 g1 = new GearsES2(0);
+ g1.setUseMappedBuffers(useMappedBuffers);
+ g1.setValidateBuffers(true);
+ final GLWindow f1 = createGLWindow(0, 0, g1);
+ animator.add(f1);
+ final InsetsImmutable insets = f1.getInsets();
+
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1);
+ final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, g2);
+ f2.setSharedAutoDrawable(f1);
+ animator.add(f2);
+ f2.setVisible(true); // shall wait until f1 is ready
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false));
+
+ f1.setVisible(true); // kicks off f1 GLContext .. and hence gears of f2 + f3 completion
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1);
+ final GLWindow f3 = createGLWindow(f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), g3);
+ f3.setSharedAutoDrawable(f1);
+ animator.add(f3);
+ f3.setVisible(true); // shall wait until f1 is ready
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ final GLContext ctx1 = f1.getContext();
+ final GLContext ctx2 = f2.getContext();
+ final GLContext ctx3 = f3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ Assert.assertEquals("Ctx1 Master Context is different", ctx1, ctx1.getSharedMaster());
+ Assert.assertEquals("Ctx2 Master Context is different", ctx1, ctx2.getSharedMaster());
+ Assert.assertEquals("Ctx3 Master Context is different", ctx1, ctx3.getSharedMaster());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ if( destroyCleanOrder ) {
+ System.err.println("XXX Destroy in clean order NOW");
+ f3.destroy();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+ f2.destroy();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+ f1.destroy();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+ } else {
+ System.err.println("XXX Destroy in creation order NOW - Driver Impl. Ma trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs.");
+ animator.pause();
+ f1.destroy();
+ animator.resume();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+
+ animator.pause();
+ f2.destroy();
+ animator.resume();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+
+ f3.destroy();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+ }
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
+
+ animator.stop();
+ }
+
+ @Test
+ public void test11ASyncEachAnimatorCleanDtorOrderCopyBuffer() throws InterruptedException {
+ asyncEachAnimator(true, false);
+ }
+ @Test
+ public void test12ASyncEachAnimatorCleanDtorOrderMapBuffer() throws InterruptedException {
+ asyncEachAnimator(true, true);
+ }
+
+ @Test
+ public void test13AsyncEachAnimatorDirtyDtorOrderCopyBuffers() throws InterruptedException {
+ asyncEachAnimator(false, false);
+ }
+ @Test
+ public void test14AsyncEachAnimatorDirtyDtorOrderMapBuffers() throws InterruptedException {
+ asyncEachAnimator(false, true);
+ }
+
+ public void asyncEachAnimator(final boolean destroyCleanOrder, final boolean useMappedBuffers) throws InterruptedException {
+ final Animator a1 = new Animator();
+ final GearsES2 g1 = new GearsES2(0);
+ g1.setSyncObjects(g1); // this is master, since rendered we must use it as sync
+ g1.setUseMappedBuffers(useMappedBuffers);
+ g1.setValidateBuffers(true);
+ final GLWindow f1 = createGLWindow(0, 0, g1);
+ a1.add(f1);
+ a1.start();
+
+ final InsetsImmutable insets = f1.getInsets();
+
+ final Animator a2 = new Animator();
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1); // also uses master g1 as sync, if required
+ final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, g2);
+ f2.setSharedAutoDrawable(f1);
+ a2.add(f2);
+ a2.start();
+ f2.setVisible(true);
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false));
+
+ f1.setVisible(true); // test pending creation of f2
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ final Animator a3 = new Animator();
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1); // also uses master g1 as sync, if required
+ final GLWindow f3 = createGLWindow(f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), g3);
+ f3.setSharedAutoDrawable(f1);
+ a3.add(f3);
+ a3.start();
+ f3.setVisible(true);
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ final GLContext ctx1 = f1.getContext();
+ final GLContext ctx2 = f2.getContext();
+ final GLContext ctx3 = f3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ Assert.assertEquals("Ctx1 Master Context is different", ctx1, ctx1.getSharedMaster());
+ Assert.assertEquals("Ctx2 Master Context is different", ctx1, ctx2.getSharedMaster());
+ Assert.assertEquals("Ctx3 Master Context is different", ctx1, ctx3.getSharedMaster());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ if( destroyCleanOrder ) {
+ System.err.println("XXX Destroy in clean order NOW");
+ a3.stop();
+ f3.destroy();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+ a2.stop();
+ f2.destroy();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+ a1.stop();
+ f1.destroy();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+ } else {
+ System.err.println("XXX Destroy in creation order NOW - Driver Impl. May trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs.");
+ a1.stop();
+ a2.pause();
+ a3.pause();
+ f1.destroy();
+ a2.resume();
+ a3.resume();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+
+ a2.stop();
+ a3.pause();
+ f2.destroy();
+ a3.resume();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+
+ a3.stop();
+ f3.destroy();
+ try { Thread.sleep(durationPostDestroy); } catch(final Exception e) { e.printStackTrace(); }
+ }
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
+ }
+
+ static long duration = 1000; // ms
+ static long durationPostDestroy = 1000; // ms - ~60 frames post destroy
+ static boolean mainRun = false;
+
+ public static void main(final String args[]) {
+ mainRun = true;
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT3.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT4.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT4.java
new file mode 100644
index 000000000..804badbc3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT4.java
@@ -0,0 +1,231 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import com.jogamp.newt.opengl.GLWindow;
+
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Test sharing w/ different shared-master context.
+ * <p>
+ * This is achieved by using the 1st GLWindow as the <i>master</i>
+ * and synchronizing via GLSharedContextSetter to postpone creation
+ * of the 2nd and 3rd GLWindow until the 1st GLWindow's GLContext becomes created.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSharedContextVBOES2NEWT4 extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ width = 256;
+ height = 256;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ protected GLWindow createGLWindow(final int x, final int y, final GearsES2 gears) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setPosition(x, y);
+ glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared true");
+ glWindow.setSize(width, height);
+ glWindow.addGLEventListener(gears);
+
+ return glWindow;
+ }
+
+ @Test
+ public void test01() throws InterruptedException {
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GearsES2 g1 = new GearsES2(0);
+ final GLWindow f1 = createGLWindow(0, 0, g1);
+ animator.add(f1);
+ final InsetsImmutable insets = f1.getInsets();
+
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1);
+ final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(),
+ f1.getY()+0, g2);
+ f2.setSharedAutoDrawable(f1);
+ animator.add(f2);
+ f2.setVisible(true);
+
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1);
+ final GLWindow f3 = createGLWindow(f1.getX()+0,
+ f1.getY()+height+insets.getTotalHeight(), g3);
+ f3.setSharedAutoDrawable(f2); // Mixed master!
+ animator.add(f3);
+ final AtomicBoolean gotAnimException = new AtomicBoolean(false);
+ final AtomicBoolean gotOtherException = new AtomicBoolean(false);
+ animator.setUncaughtExceptionHandler(new GLAnimatorControl.UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(final GLAnimatorControl _animator, final GLAutoDrawable _drawable, final Throwable _cause) {
+ if( _animator == animator && _drawable == f3 && _cause instanceof RuntimeException ) {
+ System.err.println("Caught expected exception: "+_cause.getMessage());
+ gotAnimException.set(true);
+ } else {
+ System.err.println("Caught unexpected exception: "+_cause.getMessage());
+ _cause.printStackTrace();
+ gotOtherException.set(true);
+ }
+ }
+ });
+ f3.setVisible(true);
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false));
+
+ f1.setVisible(true); // kick off f1 GLContext .. and hence allow f2 + f3 creation
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ Assert.assertFalse("Unexpected exception (animator) caught", gotAnimException.get());
+ Assert.assertFalse("Unexpected exception (other) caught", gotOtherException.get());
+
+ final GLContext ctx1 = f1.getContext();
+ final GLContext ctx2 = f2.getContext();
+ final GLContext ctx3 = f3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ Assert.assertEquals("Ctx1 Master Context is different", ctx1, ctx1.getSharedMaster());
+ Assert.assertEquals("Ctx2 Master Context is different", ctx1, ctx2.getSharedMaster());
+ Assert.assertEquals("Ctx3 Master Context is different", ctx2, ctx3.getSharedMaster()); // Mixed master!
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+
+ System.err.println("XXX Destroy in clean order NOW");
+ f3.destroy();
+ f2.destroy();
+ f1.destroy();
+
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false));
+ }
+
+ static long duration = 1000; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT4.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java
new file mode 100644
index 000000000..09f4408f1
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java
@@ -0,0 +1,369 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.util.List;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.swt.GLCanvas;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Sharing the VBO of 3 GearsES2 instances, each in their own SWT GLCanvas.
+ * <p>
+ * This is achieved by using the 1st GLCanvas as the <i>master</i>
+ * and using the build-in blocking mechanism to postpone creation
+ * of the 2nd and 3rd GLCanvas until the 1st GLCanvas's GLContext becomes created.
+ * </p>
+ * <p>
+ * Above method allows random creation of the 1st GLCanvas <b>in theory</b>, which triggers
+ * creation of the <i>dependent</i> other GLCanvas sharing it's GLContext.<br>
+ * However, since this test may perform on the <i>main thread</i> we have
+ * to initialize all in order, since otherwise the <i>test main thread</i>
+ * itself blocks SWT GLCanvas creation ..
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSharedContextVBOES2SWT3 extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ width = 256;
+ height = 256;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ Display display = null;
+ Shell shell1 = null;
+ Composite composite1 = null;
+ Shell shell2 = null;
+ Composite composite2 = null;
+ Shell shell3 = null;
+ Composite composite3 = null;
+
+ @Before
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ }});
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell1 = new Shell( display );
+ shell1.setLayout( new FillLayout() );
+ composite1 = new Composite( shell1, SWT.NO_BACKGROUND );
+ composite1.setLayout( new FillLayout() );
+
+ shell2 = new Shell( display );
+ shell2.setLayout( new FillLayout() );
+ composite2 = new Composite( shell2, SWT.NO_BACKGROUND );
+ composite2.setLayout( new FillLayout() );
+
+ shell3 = new Shell( display );
+ shell3.setLayout( new FillLayout() );
+ composite3 = new Composite( shell3, SWT.NO_BACKGROUND );
+ composite3.setLayout( new FillLayout() );
+ }});
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell1 );
+ Assert.assertNotNull( composite1 );
+ Assert.assertNotNull( shell2 );
+ Assert.assertNotNull( composite2 );
+ Assert.assertNotNull( shell3 );
+ Assert.assertNotNull( composite3 );
+ try {
+ display.syncExec(new Runnable() {
+ public void run() {
+ composite3.dispose();
+ shell3.dispose();
+ composite2.dispose();
+ shell2.dispose();
+ composite1.dispose();
+ shell1.dispose();
+ }});
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display.dispose();
+ }});
+ }
+ catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ display = null;
+ shell1 = null;
+ composite1 = null;
+ shell2 = null;
+ composite2 = null;
+ shell3 = null;
+ composite3 = null;
+ }
+
+ protected GLCanvas createGLCanvas(final Shell shell, final Composite composite, final int x, final int y, final GearsES2 gears) throws InterruptedException {
+ final GLCanvas glCanvas = GLCanvas.create( composite, 0, caps, null);
+ Assert.assertNotNull( glCanvas );
+ glCanvas.addGLEventListener(gears);
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell.setText("SWT GLCanvas Shared Gears Test");
+ shell.setSize( width, height);
+ shell.setLocation(x, y);
+ } } );
+ return glCanvas;
+ }
+
+ @Test
+ public void test01SyncedOneAnimator() throws InterruptedException {
+ final Animator animator = new Animator();
+ final GearsES2 g1 = new GearsES2(0);
+ final GLCanvas c1 = createGLCanvas(shell1, composite1, 0, 0, g1);
+ animator.add(c1);
+
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1);
+ final GLCanvas c2 = createGLCanvas(shell2, composite2, 0+width, 0+0, g2);
+ c2.setSharedAutoDrawable(c1);
+ animator.add(c2);
+
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1);
+ final GLCanvas c3 = createGLCanvas(shell3, composite3, 0, height, g3);
+ c3.setSharedAutoDrawable(c1);
+ animator.add(c3);
+
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell1.open(); // master ..
+ shell2.open(); // shall wait until f1 is ready
+ shell3.open(); // shall wait until f1 is ready
+ } } );
+ animator.start(); // kicks off GLContext .. and hence gears of f2 + f3 completion
+
+ Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid)
+
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ final GLContext ctx1 = c1.getContext();
+ final GLContext ctx2 = c2.getContext();
+ final GLContext ctx3 = c3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+
+ display.syncExec(new Runnable() {
+ public void run() {
+ c3.dispose();
+ c2.dispose();
+ c1.dispose();
+ } } );
+ }
+
+ @Test
+ public void test02AsyncEachAnimator() throws InterruptedException {
+ final Animator a1 = new Animator();
+ final GearsES2 g1 = new GearsES2(0);
+ final GLCanvas c1 = createGLCanvas(shell1, composite1, 0, 0, g1);
+ a1.add(c1);
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell1.open();
+ } } );
+ a1.start();
+
+
+ Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid)
+
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ final Animator a2 = new Animator();
+ final GearsES2 g2 = new GearsES2(0);
+ g2.setSharedGears(g1);
+ final GLCanvas c2 = createGLCanvas(shell2, composite2, width, 0, g2);
+ c2.setSharedAutoDrawable(c1);
+ a2.add(c2);
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell2.open();
+ } } );
+ a2.start();
+
+ Thread.sleep(200); // wait a while ..
+
+ final Animator a3 = new Animator();
+ final GearsES2 g3 = new GearsES2(0);
+ g3.setSharedGears(g1);
+ final GLCanvas c3 = createGLCanvas(shell3, composite3, 0, height, g3);
+ c3.setSharedAutoDrawable(c1);
+ a3.add(c3);
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell3.open();
+ } } );
+ a3.start();
+
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ final GLContext ctx1 = c1.getContext();
+ final GLContext ctx2 = c2.getContext();
+ final GLContext ctx3 = c3.getContext();
+ {
+ final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
+ final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
+ final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
+ MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
+ MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx3);
+
+ Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
+ Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
+ Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
+ Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
+ Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
+ Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
+ }
+
+ Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
+ Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
+ Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
+
+ try {
+ Thread.sleep(duration);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ a1.stop();
+ Assert.assertEquals(false, a1.isAnimating());
+ a2.stop();
+ Assert.assertEquals(false, a2.isAnimating());
+ a3.stop();
+ Assert.assertEquals(false, a3.isAnimating());
+
+ display.syncExec(new Runnable() {
+ public void run() {
+ c3.dispose();
+ c2.dispose();
+ c1.dispose();
+ } } );
+ }
+
+ static long duration = 1000; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestSharedContextVBOES2SWT3.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextWithJTabbedPaneAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextWithJTabbedPaneAWT.java
new file mode 100644
index 000000000..e62bbc63e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextWithJTabbedPaneAWT.java
@@ -0,0 +1,267 @@
+/**
+ * Copyright (C) 2013 United States Government as represented by the Administrator of the
+ * National Aeronautics and Space Administration.
+ * All Rights Reserved.
+ *
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.BorderLayout;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSharedContextWithJTabbedPaneAWT extends UITestCase {
+
+ static class DemoInstance {
+ protected static GLCapabilities getCaps() {
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true));
+
+ caps.setAlphaBits(8);
+ caps.setRedBits(8);
+ caps.setGreenBits(8);
+ caps.setBlueBits(8);
+ caps.setDepthBits(24);
+ caps.setDoubleBuffered(true);
+
+ return caps;
+ }
+
+ int[] bufferId;
+
+ @SuppressWarnings("serial")
+ class SharedGLPanel extends JPanel implements GLEventListener {
+ final GLCanvas canvas;
+ final boolean shared;
+
+ public SharedGLPanel(final GLCanvas shareWith, final int width, final int height) {
+ final GLContext sharedCtx = shareWith != null ? shareWith.getContext() : null;
+ System.err.println("XXX WWPanel: shareWith "+shareWith+", sharedCtx "+sharedCtx);
+ canvas = new GLCanvas(getCaps()); // same caps for 1st and 2nd shared ctx !
+ if( null != shareWith) {
+ canvas.setSharedAutoDrawable(shareWith);
+ shared = true;
+ } else {
+ shared = false;
+ }
+ canvas.setSize(new java.awt.Dimension(width, height));
+
+ setLayout(new BorderLayout(5, 5));
+ add(canvas, BorderLayout.CENTER);
+ setOpaque(false);
+
+ canvas.addGLEventListener(this);
+ }
+
+ @Override
+ public void init(final GLAutoDrawable glAutoDrawable) {
+ if (!shared) {
+ Assert.assertNull("Buffer is set, but instance is share master", bufferId);
+ makeVBO(glAutoDrawable);
+ System.err.println("XXX Create Buffer "+bufferId[0]);
+ } else {
+ Assert.assertNotNull("Buffer is not set, but instance is share slave", bufferId);
+ Assert.assertTrue("Context is not shared", glAutoDrawable.getContext().isShared());
+ System.err.println("XXX Reuse Buffer "+bufferId[0]);
+ }
+ final GL2 gl = glAutoDrawable.getGL().getGL2();
+ if( shared ) {
+ gl.glColor3f(1, 1, 1);
+ gl.glClearColor(0.3f, 0.3f, 0.3f, 1f);
+ } else {
+ gl.glColor3f(0, 0, 0);
+ gl.glClearColor(1f, 1f, 1f, 1f);
+ }
+ gl.glShadeModel(GLLightingFunc.GL_FLAT);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable glAutoDrawable) {}
+
+ @Override
+ public void display(final GLAutoDrawable glAutoDrawable) {
+ final GL2 gl = glAutoDrawable.getGL().getGL2();
+
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+ gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufferId[0]);
+ gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
+ gl.glDrawArrays(GL.GL_LINES, 0, 2);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable glAutoDrawable, final int i, final int i1, final int i2, final int i3) {
+ final int w = getWidth();
+ final int h = getHeight();
+
+ final GL2 gl = glAutoDrawable.getGL().getGL2();
+
+ gl.glViewport(0, 0, w, h);
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glOrtho(0, 1, 0, 1, -1, 1);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ }
+ }
+
+ protected void makeVBO(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
+
+ bufferId = new int[1];
+ gl.glGenBuffers(1, bufferId, 0);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufferId[0]);
+
+ final FloatBuffer vertices = Buffers.newDirectFloatBuffer(6);
+ vertices.put(0).put(0).put(0);
+ vertices.put(1).put(1).put(0);
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, vertices.capacity() * 4, vertices.rewind(), GL.GL_STATIC_DRAW);
+ }
+
+ public JTabbedPane tabbedPanel;
+
+ public DemoInstance(final JFrame f) {
+ try
+ {
+ GLProfile.initSingleton(); // Lets have init debug messages above below marker
+ System.err.println("XXX START DEMO XXX");
+
+ // Create the application frame and the tabbed pane and add the pane to the frame.
+ tabbedPanel = new JTabbedPane();
+ f.add(tabbedPanel, BorderLayout.CENTER);
+
+ // Create two World Windows that share resources.
+ final SharedGLPanel wwpA = new SharedGLPanel(null, 600, 600);
+ final SharedGLPanel wwpB = new SharedGLPanel(wwpA.canvas, wwpA.getWidth(), wwpA.getHeight());
+
+ tabbedPanel.add(wwpA, "Window A");
+ tabbedPanel.add(wwpB, "Window B");
+
+ // Add the card panel to the frame.
+ f.add(tabbedPanel, BorderLayout.CENTER);
+
+ // Position and display the frame.
+ f.setTitle("Multi-Window Tabbed Pane");
+ f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+ f.pack();
+ f.setResizable(true);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ static long durationPerTest = 500*4; // ms
+ static boolean manual = false;
+
+ @Test
+ public void test01() throws InterruptedException, InvocationTargetException {
+ final JFrame f = new JFrame();
+ f.setTitle("Shared GLContext AWT GLCanvas JTabbedPane");
+ final DemoInstance demo = new DemoInstance(f);
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ System.err.println("XXX SetVisible XXX");
+ f.setVisible(true);
+ } });
+
+ if(manual) {
+ for(long w=durationPerTest; w>0; w-=100) {
+ Thread.sleep(100);
+ }
+ } else {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ demo.tabbedPanel.setSelectedIndex(0);
+ }});
+ Thread.sleep(durationPerTest/4);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ demo.tabbedPanel.setSelectedIndex(1);
+ }});
+ Thread.sleep(durationPerTest/4);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ demo.tabbedPanel.setSelectedIndex(0);
+ }});
+ Thread.sleep(durationPerTest/4);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ demo.tabbedPanel.setSelectedIndex(1);
+ }});
+ Thread.sleep(durationPerTest/4);
+ }
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ System.err.println("XXX SetVisible XXX");
+ f.dispose();
+ } });
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
+ } else if(args[i].equals("-manual")) {
+ manual = true;
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestSharedContextWithJTabbedPaneAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java
index 976885de4..d8ae8bcc5 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
import java.awt.Frame;
@@ -36,17 +36,23 @@ import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
+import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestShutdownCompleteAWT extends UITestCase {
static long duration = 300; // ms
-
+
protected void runTestGL() throws InterruptedException, InvocationTargetException {
final Frame frame = new Frame("Gears AWT Test");
Assert.assertNotNull(frame);
@@ -54,18 +60,18 @@ public class TestShutdownCompleteAWT extends UITestCase {
final GLCanvas glCanvas = new GLCanvas(new GLCapabilities(GLProfile.getGL2ES2()));
Assert.assertNotNull(glCanvas);
frame.add(glCanvas);
- frame.setSize(256, 256);
glCanvas.addGLEventListener(new GearsES2(1));
- Animator animator = new Animator(glCanvas);
+ final Animator animator = new Animator(glCanvas);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.setSize(256, 256);
frame.setVisible(true);
}});
-
- animator.setUpdateFPSFrames(60, System.err);
+
+ animator.setUpdateFPSFrames(60, System.err);
animator.start();
Assert.assertEquals(true, animator.isAnimating());
Assert.assertEquals(true, glCanvas.isVisible());
@@ -78,7 +84,10 @@ public class TestShutdownCompleteAWT extends UITestCase {
animator.stop();
Assert.assertEquals(false, animator.isAnimating());
- frame.setVisible(false);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
Assert.assertEquals(false, frame.isVisible());
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -87,38 +96,71 @@ public class TestShutdownCompleteAWT extends UITestCase {
}});
}
- protected void oneLife() throws InterruptedException, InvocationTargetException {
- long t0 = System.nanoTime();
+ @AfterClass
+ public static void afterAll() {
+ if(waitForKey) {
+ UITestCase.waitForKey("Exit");
+ }
+ }
+
+ protected void oneLife(final boolean glInfo) throws InterruptedException, InvocationTargetException {
+ final long t0 = Platform.currentTimeMicros();
GLProfile.initSingleton();
- long t1 = System.nanoTime();
- runTestGL();
- long t2 = System.nanoTime();
- GLProfile.shutdown();
- long t3 = System.nanoTime();
- System.err.println("Total: "+ (t3-t0)/1e6 +"ms");
- System.err.println(" GLProfile.initSingleton(): "+ (t1-t0)/1e6 +"ms");
- System.err.println(" Demo Code: "+ (t2-t1)/1e6 +"ms");
- System.err.println(" GLProfile.shutdown(): "+ (t3-t2)/1e6 +"ms");
+ final long t1 = Platform.currentTimeMicros();
+ if(!initOnly) {
+ runTestGL();
+ }
+ final long t2 = Platform.currentTimeMicros();
+ if(glInfo) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, false).toString());
+ }
+ final long t3 = Platform.currentTimeMicros();
+ GLProfile.shutdown();
+ final long t4 = Platform.currentTimeMicros();
+ System.err.println("Total: "+ (t4-t0)/1e3 +"ms");
+ System.err.println(" GLProfile.initSingleton(): "+ (t1-t0)/1e3 +"ms");
+ System.err.println(" Demo Code: "+ (t2-t1)/1e3 +"ms");
+ System.err.println(" GLInfo: "+ (t3-t2)/1e3 +"ms");
+ System.err.println(" GLProfile.shutdown(): "+ (t4-t3)/1e3 +"ms");
}
-
+
@Test
public void test01OneLife() throws InterruptedException, InvocationTargetException {
- oneLife();
+ oneLife(false);
+ }
+
+ @Test
+ public void test02AnotherLifeWithGLInfo() throws InterruptedException, InvocationTargetException {
+ oneLife(true);
}
@Test
- public void test01AnotherLife() throws InterruptedException, InvocationTargetException {
- oneLife();
+ public void test03AnotherLife() throws InterruptedException, InvocationTargetException {
+ oneLife(true);
}
-
+
@Test
- public void test01TwoLifes() throws InterruptedException, InvocationTargetException {
- oneLife();
- oneLife();
+ public void test03TwoLifes() throws InterruptedException, InvocationTargetException {
+ oneLife(false);
+ oneLife(false);
}
-
- public static void main(String args[]) throws IOException {
- String tstname = TestShutdownCompleteAWT.class.getName();
+
+ static boolean initOnly = false;
+ static boolean waitForKey = false;
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-wait")) {
+ waitForKey = true;
+ } else if(args[i].equals("-initOnly")) {
+ initOnly = true;
+ }
+ }
+
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
+ final String tstname = TestShutdownCompleteAWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java
index f376cd6d4..10f334244 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,46 +20,49 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.acore;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
+import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+import com.jogamp.common.os.Platform;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestShutdownCompleteNEWT extends UITestCase {
static long duration = 300; // ms
-
- protected void runTestGL(boolean onscreen) throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+
+ protected void runTestGL(final boolean onscreen) throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
caps.setOnscreen(onscreen);
caps.setPBuffer(!onscreen);
-
- GLWindow glWindow = GLWindow.create(caps);
+
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Gears NEWT Test");
glWindow.addGLEventListener(new GearsES2());
- Animator animator = new Animator(glWindow);
+ final Animator animator = new Animator(glWindow);
glWindow.setSize(256, 256);
glWindow.setVisible(true);
@@ -78,59 +81,63 @@ public class TestShutdownCompleteNEWT extends UITestCase {
glWindow.destroy();
}
- protected void oneLife(boolean glInfo) throws InterruptedException {
+ @AfterClass
+ public static void afterAll() {
+ if(waitForKey) {
+ UITestCase.waitForKey("Exit");
+ }
+ }
+
+ protected void oneLife(final boolean glInfo) throws InterruptedException {
if(waitForEach) {
- waitForEnter();
+ UITestCase.waitForKey("Start One Life");
}
- long t0 = System.nanoTime();
+ final long t0 = Platform.currentTimeMicros();
GLProfile.initSingleton();
- long t1 = System.nanoTime();
+ final long t1 = Platform.currentTimeMicros();
if(!initOnly) {
runTestGL(true);
}
- long t2 = System.nanoTime();
+ final long t2 = Platform.currentTimeMicros();
if(glInfo) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, false).toString());
}
- long t3 = System.nanoTime();
- GLProfile.shutdown();
- long t4 = System.nanoTime();
- System.err.println("Total: "+ (t3-t0)/1e6 +"ms");
- System.err.println(" GLProfile.initSingleton(): "+ (t1-t0)/1e6 +"ms");
- System.err.println(" Demo Code: "+ (t2-t1)/1e6 +"ms");
- System.err.println(" GLProfile.shutdown(): "+ (t4-t3)/1e6 +"ms");
+ final long t3 = Platform.currentTimeMicros();
+ GLProfile.shutdown();
+ final long t4 = Platform.currentTimeMicros();
+ System.err.println("Total: "+ (t4-t0)/1e3 +"ms");
+ System.err.println(" GLProfile.initSingleton(): "+ (t1-t0)/1e3 +"ms");
+ System.err.println(" Demo Code: "+ (t2-t1)/1e3 +"ms");
+ System.err.println(" GLInfo: "+ (t3-t2)/1e3 +"ms");
+ System.err.println(" GLProfile.shutdown(): "+ (t4-t3)/1e3 +"ms");
}
-
+
@Test
public void test01OneLife() throws InterruptedException {
+ oneLife(false);
+ }
+
+ @Test
+ public void test02AnotherLifeWithGLInfo() throws InterruptedException {
oneLife(true);
}
@Test
- public void test01AnotherLife() throws InterruptedException {
- oneLife(false);
+ public void test03AnotherLife() throws InterruptedException {
+ oneLife(true);
}
-
+
@Test
- public void test01TwoLifes() throws InterruptedException {
+ public void test03TwoLifes() throws InterruptedException {
oneLife(false);
oneLife(false);
}
-
+
static boolean initOnly = false;
static boolean waitForEach = false;
-
- static void waitForEnter() {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
- System.err.println("Press enter to continue");
- try {
- System.err.println(stdin.readLine());
- } catch (IOException e) { }
- }
-
- public static void main(String args[]) throws IOException {
- boolean waitForKey = false;
-
+ static boolean waitForKey = false;
+
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-wait")) {
waitForKey = true;
@@ -141,12 +148,12 @@ public class TestShutdownCompleteNEWT extends UITestCase {
initOnly = true;
}
}
-
+
if(waitForKey) {
- waitForEnter();
+ UITestCase.waitForKey("Start");
}
-
- String tstname = TestShutdownCompleteNEWT.class.getName();
+
+ final String tstname = TestShutdownCompleteNEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestVersionSemanticsNOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestVersionSemanticsNOUI.java
new file mode 100644
index 000000000..5cf9655f8
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestVersionSemanticsNOUI.java
@@ -0,0 +1,126 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.osjava.jardiff.DiffCriteria;
+import org.semver.Delta;
+
+import com.jogamp.common.util.JogampVersion;
+import com.jogamp.common.util.VersionNumberString;
+import com.jogamp.junit.util.SingletonJunitCase;
+import com.jogamp.junit.util.VersionSemanticsUtil;
+import com.jogamp.opengl.JoglVersion;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestVersionSemanticsNOUI extends SingletonJunitCase {
+ static final String jarFile = "jogl-all.jar";
+
+ static final DiffCriteria diffCriteria = new org.osjava.jardiff.SimpleDiffCriteria();
+ // static final DiffCriteria diffCriteria = new org.osjava.jardiff.PublicDiffCriteria();
+
+ static final JogampVersion curVersion = JoglVersion.getInstance();
+ static final VersionNumberString curVersionNumber = new VersionNumberString(curVersion.getImplementationVersion());
+
+ static final Set<String> excludesDefault;
+ static {
+ excludesDefault = new HashSet<String>();
+ excludesDefault.add("^\\Qjogamp/\\E.*$");
+ }
+
+
+ // @Test
+ public void testVersionV212V213() throws IllegalArgumentException, IOException, URISyntaxException {
+ testVersions(diffCriteria, Delta.CompatibilityType.BACKWARD_COMPATIBLE_USER, "2.1.2", "2.1.3", excludesDefault);
+ }
+
+ // @Test
+ public void testVersionV213V214() throws IllegalArgumentException, IOException, URISyntaxException {
+ testVersions(diffCriteria, Delta.CompatibilityType.BACKWARD_COMPATIBLE_USER, "2.1.3", "2.1.4", excludesDefault);
+ }
+
+ // @Test
+ public void testVersionV214V215() throws IllegalArgumentException, IOException, URISyntaxException {
+ testVersions(diffCriteria, Delta.CompatibilityType.BACKWARD_COMPATIBLE_USER, "2.1.4", "2.1.5", excludesDefault);
+ }
+
+ // @Test
+ public void testVersionV215V220() throws IllegalArgumentException, IOException, URISyntaxException {
+ testVersions(diffCriteria, Delta.CompatibilityType.BACKWARD_COMPATIBLE_USER, "2.1.5", "2.2.0", excludesDefault);
+ }
+
+ @Test
+ public void testVersionV220V221() throws IllegalArgumentException, IOException, URISyntaxException {
+ testVersions(diffCriteria, Delta.CompatibilityType.BACKWARD_COMPATIBLE_USER, "2.2.0", "2.2.1", excludesDefault);
+ }
+
+ void testVersions(final DiffCriteria diffCriteria, final Delta.CompatibilityType expectedCompatibilityType,
+ final String v1, final String v2, final Set<String> excludes)
+ throws IllegalArgumentException, IOException, URISyntaxException {
+ final VersionNumberString preVersionNumber = new VersionNumberString(v1);
+ final File previousJar = new File("lib/v"+v1+"/"+jarFile);
+
+ final VersionNumberString curVersionNumber = new VersionNumberString(v2);
+ final File currentJar = new File("lib/v"+v2+"/"+jarFile);
+
+ VersionSemanticsUtil.testVersion(diffCriteria, expectedCompatibilityType,
+ previousJar, preVersionNumber,
+ currentJar, curVersionNumber,
+ excludes);
+ }
+
+ @Test
+ public void testVersionV221V23x() throws IllegalArgumentException, IOException, URISyntaxException {
+ final Delta.CompatibilityType expectedCompatibilityType = Delta.CompatibilityType.NON_BACKWARD_COMPATIBLE;
+ // final Delta.CompatibilityType expectedCompatibilityType = Delta.CompatibilityType.BACKWARD_COMPATIBLE_USER;
+
+ final VersionNumberString preVersionNumber = new VersionNumberString("2.2.1");
+ final File previousJar = new File("lib/v"+preVersionNumber.getVersionString()+"/"+jarFile);
+
+ final ClassLoader currentCL = TestVersionSemanticsNOUI.class.getClassLoader();
+
+ VersionSemanticsUtil.testVersion(diffCriteria, expectedCompatibilityType,
+ previousJar, preVersionNumber,
+ curVersion.getClass(), currentCL, curVersionNumber,
+ excludesDefault);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestVersionSemanticsNOUI.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestX11DefaultDisplay.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestX11DefaultDisplay.java
new file mode 100644
index 000000000..9ac190bc7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestX11DefaultDisplay.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1;
+import com.jogamp.opengl.test.junit.util.DumpGLInfo;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * This is a clone of TestGLPointsNEWT which uses the ability to specify
+ * the X11 default display programmatically instead of relying on the
+ * DISPLAY environment variable.
+ *
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestX11DefaultDisplay extends UITestCase {
+ static long duration = 500; // ms
+ static int width = 512, height = 512;
+ static String x11DefaultDisplay = ":0.0";
+
+ @BeforeClass
+ public static void initClass() {
+ System.setProperty("nativewindow.x11.display.default", x11DefaultDisplay);
+ }
+
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setTitle(getSimpleTestName("."));
+ glWindow.setSize(width, height);
+
+ final RedSquareES1 demo = new RedSquareES1();
+ glWindow.addGLEventListener(demo);
+
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ snap.setPostSNDetail(demo.getClass().getSimpleName());
+ glWindow.addGLEventListener(snap);
+
+ final Animator animator = new Animator(glWindow);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ animator.start();
+
+ glWindow.setVisible(true);
+
+ System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
+ System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+
+ animator.setUpdateFPSFrames(60, System.err);
+ snap.setMakeSnapshot();
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+ glWindow.destroy();
+ }
+
+ @Test
+ public void test00_DefaultDevice() {
+ final AbstractGraphicsDevice defaultDevice = GLProfile.getDefaultDevice();
+ System.out.println("GLProfile "+GLProfile.glAvailabilityToString());
+ System.out.println("GLProfile.getDefaultDevice(): "+defaultDevice);
+ final GLProfile glp = GLProfile.getDefault();
+ System.out.println("GLProfile.getDefault(): "+glp);
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+
+ glWindow.addGLEventListener(new DumpGLInfo());
+
+ glWindow.setSize(128, 128);
+ glWindow.setVisible(true);
+
+ glWindow.display();
+ glWindow.destroy();
+
+ if( NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
+ Assert.assertEquals("X11 Default device does not match", defaultDevice.getConnection(), x11DefaultDisplay);
+ }
+ }
+
+ @Test
+ public void test01_GLDefaultRendering() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ runTestGL(caps);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-x11DefaultDisplay")) {
+ x11DefaultDisplay = args[++i];
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestX11DefaultDisplay.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java
new file mode 100644
index 000000000..764973f06
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore.anim;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.SwingUtilities;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Manual test case to validate Animator pause/resume on AWT-EDT.
+ * <p>
+ * Even though (AWT) Animator is not able to block until pause/resume is finished
+ * when issued on AWT-EDT, best effort shall be made to preserve functionality.
+ * </p>
+ * Original Author: <i>kosukek</i> from JogAmp forum; Modifier a bit.
+ */
+@SuppressWarnings("serial")
+public class Bug898AnimatorFromEDTAWT extends javax.swing.JFrame {
+
+ public Bug898AnimatorFromEDTAWT() {
+ setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+ //Layout
+ setMinimumSize(new Dimension(640, 480));
+ getContentPane().setLayout(new BorderLayout());
+ final GLCanvas panel = new GLCanvas(new GLCapabilities(GLProfile.getMaxProgrammable(true)));
+ getContentPane().add(panel, BorderLayout.CENTER);
+ pack();
+ //Animator
+ final Animator animator = new Animator();
+ animator.add(panel);
+ //GLEventListener
+ panel.addGLEventListener(new GearsES2(1));
+ panel.addGLEventListener(new GLEventListener() {
+ long startTime = 0, lastTime = 0;
+ long step = 1;
+
+ @Override
+ public void init(final GLAutoDrawable glad) {
+ startTime = System.currentTimeMillis();
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable glad) {
+ }
+
+ @Override
+ public void display(final GLAutoDrawable glad) {
+ final long time = System.currentTimeMillis();
+ if (animator.isAnimating() && step * 2000 < time - startTime) {
+ final long td = time - lastTime;
+ lastTime = time;
+ animator.pause();
+ System.out.println(Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.pause(): paused "+animator);
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(1000);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ final long td = System.currentTimeMillis() - lastTime;
+ if (animator.isPaused()) {
+ animator.resume(); //Doesn't work on v2.0.2 or higher
+ System.out.println(Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.resume(): animating "+animator);
+ } else {
+ System.out.println(Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.resume(): Ooops - not paused! - animating "+animator);
+ }
+ } } );
+ }
+ }.start();
+ step++;
+ }
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable glad, final int i, final int i1, final int i2, final int i3) {
+ }
+ });
+ //Start animation
+ animator.start();
+ System.out.println("animator.start()");
+ }
+
+ public static void main(final String args[]) {
+ java.awt.EventQueue.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ new Bug898AnimatorFromEDTAWT().setVisible(true);
+ }
+ });
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAWTCardLayoutAnimatorStartStopBug532.java
index 3f6935588..97f8b3f48 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAWTCardLayoutAnimatorStartStopBug532.java
@@ -1,7 +1,8 @@
-package com.jogamp.opengl.test.junit.jogl.awt;
+package com.jogamp.opengl.test.junit.jogl.acore.anim;
import java.awt.BorderLayout;
import java.awt.CardLayout;
+import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
@@ -17,8 +18,11 @@ import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
+import javax.swing.WindowConstants;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.MiscUtils;
@@ -26,56 +30,62 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.FPSAnimator;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
- static final String LABEL = "Label";
+ static final String LABEL = "Label";
static final String CANVAS = "GLCanvas";
-
+
public enum AnimatorControlBehavior {
StartStop, PauseResume, Continue;
}
-
- static long durationPerTest = 200*4; // ms
+
+ static long durationPerTest = 200*4; // ms
static boolean manual = false;
static volatile boolean shouldStop = false;
-
+
private String selected = LABEL;
-
+
@Test
public void testFPSAnimatorStartStop() throws InterruptedException, InvocationTargetException {
testImpl(AnimatorControlBehavior.StartStop, true);
}
-
+
@Test
public void testFPSAnimatorResumePause() throws InterruptedException, InvocationTargetException {
testImpl(AnimatorControlBehavior.PauseResume, true);
}
-
+
@Test
public void testFPSAnimatorContinue() throws InterruptedException, InvocationTargetException {
testImpl(AnimatorControlBehavior.Continue, true);
}
-
+
@Test
public void testAnimatorStartStop() throws InterruptedException, InvocationTargetException {
testImpl(AnimatorControlBehavior.StartStop, false);
}
-
+
@Test
public void testAnimatorResumePause() throws InterruptedException, InvocationTargetException {
testImpl(AnimatorControlBehavior.PauseResume, false);
}
-
+
@Test
public void testAnimatorContinue() throws InterruptedException, InvocationTargetException {
testImpl(AnimatorControlBehavior.Continue, false);
}
-
- void testImpl(final AnimatorControlBehavior animCtrl, boolean useFPSAnimator) throws InterruptedException, InvocationTargetException {
- final GLProfile glp = GLProfile.get(GLProfile.GL2);
- final GLCapabilities caps = new GLCapabilities(glp);
- final GLCanvas canvas = new GLCanvas(caps);
+
+ private static String id(final Object obj) { return "0x" + ( null!=obj ? Integer.toHexString(obj.hashCode()) : "nil" ); }
+ private static String str(final Component c) {
+ return id(c)+": "+c.getClass().getSimpleName()+"[visible "+c.isVisible()+", showing "+c.isShowing()+", valid "+c.isValid()+
+ ", displayable "+c.isDisplayable()+", "+c.getX()+"/"+c.getY()+" "+c.getWidth()+"x"+c.getHeight()+"]";
+ }
+ void testImpl(final AnimatorControlBehavior animCtrl, final boolean useFPSAnimator) throws InterruptedException, InvocationTargetException {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLCanvas canvas = new GLCanvas(caps);
canvas.setPreferredSize(new Dimension(640, 480));
-
+
final GLAnimatorControl animatorCtrl = useFPSAnimator ? new FPSAnimator(canvas, 60) : new Animator(canvas);
animatorCtrl.setUpdateFPSFrames(60, null);// System.err);
switch (animCtrl) {
@@ -92,7 +102,7 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
canvas.addGLEventListener(new GearsES2(1));
/* if(Platform.OS_TYPE == Platform.OSType.WINDOWS) {
canvas.addGLEventListener(new GLEventListener() {
- public void init(GLAutoDrawable drawable) { }
+ public void init(GLAutoDrawable drawable) { }
public void dispose(GLAutoDrawable drawable) { }
public void display(GLAutoDrawable drawable) {
final NativeWindow win = (NativeWindow) drawable.getNativeSurface();
@@ -109,15 +119,17 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
final JFrame frame = new JFrame();
frame.setTitle(getSimpleTestName(" - "));
- frame.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
animatorCtrl.stop();
shouldStop = true;
- }
+ }
});
- frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
-
- final JPanel cards = new JPanel(new CardLayout());
+ frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+
+ final JLabel label = new JLabel("A label to cover the canvas");
+
+ final JPanel cards = new JPanel(new CardLayout());
final JPanel comboBoxPanel = new JPanel(); // nicer look ..
final JComboBox comboBox = new JComboBox(new String[] { LABEL, CANVAS });
comboBox.setEditable(false);
@@ -128,7 +140,13 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
if(!newSelection.equals(selected)) {
final String oldSelected = selected;
if(newSelection.equals(CANVAS)) {
- cl.show(cards, CANVAS);
+ System.err.println("XXX Card.SHOW Canvas PRE: ");
+ System.err.println(" CANVAS "+str(canvas));
+ System.err.println(" LABEL "+str(label));
+ cl.show(cards, CANVAS);
+ System.err.println("XXX Card.SHOW Canvas POST: ");
+ System.err.println(" CANVAS "+str(canvas));
+ System.err.println(" LABEL "+str(label));
switch (animCtrl) {
case StartStop:
animatorCtrl.start();
@@ -149,32 +167,37 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
break;
default:
}
- cl.show(cards, LABEL);
+ System.err.println("XXX Card.SHOW Label PRE: ");
+ System.err.println(" CANVAS "+str(canvas));
+ System.err.println(" LABEL "+str(label));
+ cl.show(cards, LABEL);
+ System.err.println("XXX Card.SHOW Label POST: ");
+ System.err.println(" CANVAS "+str(canvas));
+ System.err.println(" LABEL "+str(label));
selected = LABEL;
} else {
throw new RuntimeException("oops .. unexpected item: "+evt);
}
- System.err.println("Item Change: "+oldSelected+" -> "+selected+", "+animatorCtrl);
+ System.err.println("Item Change: "+oldSelected+" -> "+selected+", "+animatorCtrl);
} else {
System.err.println("Item Stays: "+selected+", "+animatorCtrl);
}
}
});
- comboBoxPanel.add(comboBox);
+ comboBoxPanel.add(comboBox);
- cards.add(new JLabel("A label to cover the canvas"), LABEL);
+ cards.add(label, LABEL);
cards.add(canvas, CANVAS);
-
+
frame.add(comboBoxPanel, BorderLayout.PAGE_START);
frame.add(cards, BorderLayout.CENTER);
-
- frame.pack();
-
+
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.pack();
frame.setVisible(true);
}});
-
+
if(manual) {
for(long w=durationPerTest; !shouldStop && w>0; w-=100) {
Thread.sleep(100);
@@ -185,35 +208,35 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
comboBox.setSelectedItem(LABEL);
}});
Thread.sleep(durationPerTest/4);
-
+
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
comboBox.setSelectedItem(CANVAS);
}});
Thread.sleep(durationPerTest/4);
-
+
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
comboBox.setSelectedItem(LABEL);
}});
Thread.sleep(durationPerTest/4);
-
+
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
comboBox.setSelectedItem(CANVAS);
}});
Thread.sleep(durationPerTest/4);
}
-
+
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.setVisible(false);
frame.dispose();
}});
-
+
}
-
- public static void main(String args[]) {
+
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java
new file mode 100644
index 000000000..d39abba41
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java
@@ -0,0 +1,301 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.anim;
+
+import java.awt.Frame;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.awt.GLJPanel;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestAnimatorGLJPanel01AWT extends UITestCase {
+ static final int width = 640;
+ static final int height = 480;
+
+ protected GLJPanel createGLJPanel(final GLCapabilities caps, final Frame frame, final int x, final int y, final GearsES2 gears) throws InterruptedException {
+ final GLJPanel glCanvas = new GLJPanel(caps);
+ Assert.assertNotNull(glCanvas);
+ glCanvas.addGLEventListener(gears);
+ frame.add(glCanvas);
+ frame.setLocation(x, y);
+ frame.setSize(width, height);
+ frame.setTitle("GLJPanel: "+x+"/"+y);
+ return glCanvas;
+ }
+
+ static void pauseAnimator(final Animator animator, final boolean pause) {
+ if(pause) {
+ animator.pause();
+ Assert.assertEquals(true, animator.isStarted());
+ Assert.assertEquals(true, animator.isPaused());
+ Assert.assertEquals(false, animator.isAnimating());
+ } else {
+ animator.resume();
+ Assert.assertEquals(true, animator.isStarted());
+ Assert.assertEquals(false, animator.isPaused());
+ Assert.assertEquals(true, animator.isAnimating());
+ }
+ }
+ static void stopAnimator(final Animator animator) {
+ animator.stop();
+ Assert.assertEquals(false, animator.isStarted());
+ Assert.assertEquals(false, animator.isPaused());
+ Assert.assertEquals(false, animator.isAnimating());
+ }
+
+ @Test
+ public void test01SyncedOneAnimator() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ final Frame f1 = new Frame();
+ final Animator animator = new Animator();
+ animator.start();
+ Assert.assertEquals(true, animator.isStarted());
+ Assert.assertEquals(true, animator.isPaused());
+ Assert.assertEquals(false, animator.isAnimating());
+
+ final GearsES2 g1 = new GearsES2(0);
+ final GLJPanel c1 = createGLJPanel(caps, f1, 0, 0, g1);
+ animator.add(c1);
+ Assert.assertEquals(true, animator.isStarted());
+ Assert.assertEquals(false, animator.isPaused());
+ Assert.assertEquals(true, animator.isAnimating());
+
+ final Frame f2 = new Frame();
+ final GearsES2 g2 = new GearsES2(0);
+ final GLJPanel c2 = createGLJPanel(caps, f2, f1.getX()+width,
+ f1.getY()+0, g2);
+ animator.add(c2);
+
+ final Frame f3 = new Frame();
+ final GearsES2 g3 = new GearsES2(0);
+ final GLJPanel c3 = createGLJPanel(caps, f3, f1.getX()+0,
+ f1.getY()+height, g3);
+ animator.add(c3);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f1.setVisible(true);
+ f2.setVisible(true);
+ f3.setVisible(true);
+ } } );
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ pauseAnimator(animator, true);
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ pauseAnimator(animator, false);
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ stopAnimator(animator);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ f1.dispose();
+ f2.dispose();
+ f3.dispose();
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }});
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false));
+ }
+
+ @Test
+ public void test02AsyncEachAnimator() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ final Frame f1 = new Frame();
+ final Animator a1 = new Animator();
+ final GearsES2 g1 = new GearsES2(0);
+ final GLJPanel c1 = createGLJPanel(caps, f1, 0, 0, g1);
+ a1.add(c1);
+ a1.start();
+ Assert.assertEquals(true, a1.isStarted());
+ Assert.assertEquals(false, a1.isPaused());
+ Assert.assertEquals(true, a1.isAnimating());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f1.setVisible(true);
+ } } );
+
+ final Frame f2 = new Frame();
+ final Animator a2 = new Animator();
+ final GearsES2 g2 = new GearsES2(0);
+ final GLJPanel c2 = createGLJPanel(caps, f2, f1.getX()+width, f1.getY()+0, g2);
+ a2.add(c2);
+ a2.start();
+ Assert.assertEquals(true, a2.isStarted());
+ Assert.assertEquals(false, a2.isPaused());
+ Assert.assertEquals(true, a2.isAnimating());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f2.setVisible(true);
+ } } );
+
+ final Frame f3 = new Frame();
+ final Animator a3 = new Animator();
+ final GearsES2 g3 = new GearsES2(0);
+ final GLJPanel c3 = createGLJPanel(caps, f3, f1.getX()+0, f1.getY()+height, g3);
+ a3.add(c3);
+ a3.start();
+ Assert.assertEquals(true, a3.isStarted());
+ Assert.assertEquals(false, a3.isPaused());
+ Assert.assertEquals(true, a3.isAnimating());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f3.setVisible(true);
+ } } );
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ pauseAnimator(a1, true);
+ pauseAnimator(a2, true);
+ pauseAnimator(a3, true);
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ pauseAnimator(a1, false);
+ pauseAnimator(a2, false);
+ pauseAnimator(a3, false);
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ stopAnimator(a1);
+ stopAnimator(a2);
+ stopAnimator(a3);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ f1.dispose();
+ f2.dispose();
+ f3.dispose();
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }});
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false));
+ }
+
+ static long duration = 3*500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestAnimatorGLJPanel01AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java
new file mode 100644
index 000000000..03892518b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java
@@ -0,0 +1,267 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.anim;
+
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestAnimatorGLWindow01NEWT extends UITestCase {
+ static final int width = 640;
+ static final int height = 480;
+
+ protected GLWindow createGLWindow(final GLCapabilities caps, final int x, final int y, final GearsES2 gears) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.addGLEventListener(gears);
+ glWindow.setPosition(x, y);
+ glWindow.setSize(width, height);
+ glWindow.setTitle("GLWindow: "+x+"/"+y);
+ return glWindow;
+ }
+
+ static void pauseAnimator(final Animator animator, final boolean pause) {
+ if(pause) {
+ animator.pause();
+ Assert.assertEquals(true, animator.isStarted());
+ Assert.assertEquals(true, animator.isPaused());
+ Assert.assertEquals(false, animator.isAnimating());
+ } else {
+ animator.resume();
+ Assert.assertEquals(true, animator.isStarted());
+ Assert.assertEquals(false, animator.isPaused());
+ Assert.assertEquals(true, animator.isAnimating());
+ }
+ }
+ static void stopAnimator(final Animator animator) {
+ animator.stop();
+ Assert.assertEquals(false, animator.isStarted());
+ Assert.assertEquals(false, animator.isPaused());
+ Assert.assertEquals(false, animator.isAnimating());
+ }
+
+ @Test
+ public void test01SyncedOneAnimator() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ final Animator animator = new Animator();
+ animator.start();
+ Assert.assertEquals(true, animator.isStarted());
+ Assert.assertEquals(true, animator.isPaused());
+ Assert.assertEquals(false, animator.isAnimating());
+
+ final GearsES2 g1 = new GearsES2(0);
+ final GLWindow c1 = createGLWindow(caps, 0, 0, g1);
+ animator.add(c1);
+ Assert.assertEquals(true, animator.isStarted());
+ Assert.assertEquals(false, animator.isPaused());
+ Assert.assertEquals(true, animator.isAnimating());
+
+ final GearsES2 g2 = new GearsES2(0);
+ final GLWindow c2 = createGLWindow(caps, c1.getX()+width,
+ c1.getY()+0, g2);
+ animator.add(c2);
+
+ final GearsES2 g3 = new GearsES2(0);
+ final GLWindow c3 = createGLWindow(caps, c1.getX()+0,
+ c1.getY()+height, g3);
+ animator.add(c3);
+
+ c1.setVisible(true);
+ c2.setVisible(true);
+ c3.setVisible(true);
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ pauseAnimator(animator, true);
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ pauseAnimator(animator, false);
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ stopAnimator(animator);
+
+ c1.destroy();
+ c2.destroy();
+ c3.destroy();
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false));
+ }
+
+ @Test
+ public void test02AsyncEachAnimator() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ final Animator a1 = new Animator();
+ final GearsES2 g1 = new GearsES2(0);
+ final GLWindow c1 = createGLWindow(caps, 0, 0, g1);
+ a1.add(c1);
+ a1.start();
+ Assert.assertEquals(true, a1.isStarted());
+ Assert.assertEquals(false, a1.isPaused());
+ Assert.assertEquals(true, a1.isAnimating());
+ c1.setVisible(true);
+
+ final Animator a2 = new Animator();
+ final GearsES2 g2 = new GearsES2(0);
+ final GLWindow c2 = createGLWindow(caps, c1.getX()+width, c1.getY()+0, g2);
+ a2.add(c2);
+ a2.start();
+ Assert.assertEquals(true, a2.isStarted());
+ Assert.assertEquals(false, a2.isPaused());
+ Assert.assertEquals(true, a2.isAnimating());
+ c2.setVisible(true);
+
+ final Animator a3 = new Animator();
+ final GearsES2 g3 = new GearsES2(0);
+ final GLWindow c3 = createGLWindow(caps, c1.getX()+0, c1.getY()+height, g3);
+ a3.add(c3);
+ a3.start();
+ Assert.assertEquals(true, a3.isStarted());
+ Assert.assertEquals(false, a3.isPaused());
+ Assert.assertEquals(true, a3.isAnimating());
+ c3.setVisible(true);
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true));
+ Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true));
+ Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true));
+ Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true));
+ Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ pauseAnimator(a1, true);
+ pauseAnimator(a2, true);
+ pauseAnimator(a3, true);
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ pauseAnimator(a1, false);
+ pauseAnimator(a2, false);
+ pauseAnimator(a3, false);
+
+ try {
+ Thread.sleep(duration/3);
+ } catch(final Exception e) {
+ e.printStackTrace();
+ }
+
+ // Stopped animator allows native windowing system 'repaint' event
+ // to trigger GLAD 'display'
+ stopAnimator(a1);
+ stopAnimator(a2);
+ stopAnimator(a3);
+
+ c1.destroy();
+ c2.destroy();
+ c3.destroy();
+
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false));
+ }
+
+ static long duration = 3*500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestAnimatorGLWindow01NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java
new file mode 100644
index 000000000..6e10d65da
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java
@@ -0,0 +1,424 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Window;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.util.InsetsImmutable;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * ExclusiveContextThread base implementation to test correctness of the ExclusiveContext feature _and_ AnimatorBase.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class ExclusiveContextBase00 extends UITestCase {
+ static boolean testExclusiveWithAWT = false;
+ static final int durationParts = 9;
+ static long duration = 320 * durationParts; // ms ~ 20 frames
+
+ static boolean showFPS = false;
+ static int showFPSRate = 100;
+
+ static final int demoWinSize = 128;
+
+ static InsetsImmutable insets = null;
+ static int num_x, num_y;
+
+ static int swapInterval = 0;
+
+ @BeforeClass
+ public static void initClass00() {
+ final Window dummyWindow = NewtFactory.createWindow(new Capabilities());
+ dummyWindow.setSize(demoWinSize, demoWinSize);
+ dummyWindow.setVisible(true);
+ Assert.assertEquals(true, dummyWindow.isVisible());
+ Assert.assertEquals(true, dummyWindow.isNativeValid());
+ insets = dummyWindow.getInsets();
+ final int scrnHeight = dummyWindow.getScreen().getHeight();
+ final int scrnWidth = dummyWindow.getScreen().getWidth();
+ final int[] demoScreenSize = dummyWindow.convertToPixelUnits(new int[] { demoWinSize, demoWinSize });
+ final int[] insetsScreenSize = dummyWindow.convertToPixelUnits(new int[] { insets.getTotalWidth(), insets.getTotalHeight() });
+ num_x = scrnWidth / ( demoScreenSize[0] + insetsScreenSize[0] ) - 2;
+ num_y = scrnHeight / ( demoScreenSize[1] + insetsScreenSize[1] ) - 2;
+ dummyWindow.destroy();
+ }
+
+ @AfterClass
+ public static void releaseClass00() {
+ }
+
+ protected abstract boolean isAWTTestCase();
+ protected abstract Thread getAWTRenderThread();
+ protected abstract AnimatorBase createAnimator();
+ protected abstract GLAutoDrawable createGLAutoDrawable(String title, int x, int y, int width, int height, GLCapabilitiesImmutable caps);
+ protected abstract void setGLAutoDrawableVisible(GLAutoDrawable[] glads);
+ protected abstract void destroyGLAutoDrawableVisible(GLAutoDrawable glad);
+
+ protected void runTestGL(final GLCapabilitiesImmutable caps, final int drawableCount, final boolean exclusive, final boolean preAdd, final boolean shortenTest) throws InterruptedException {
+ final boolean useAWTRenderThread = isAWTTestCase();
+ if( useAWTRenderThread && exclusive ) {
+ if( testExclusiveWithAWT ) {
+ System.err.println("Warning: Testing AWT + Exclusive -> Not advised!");
+ } else {
+ System.err.println("Info: Skip test: AWT + Exclusive!");
+ return;
+ }
+ }
+ if( useAWTRenderThread && exclusive && !testExclusiveWithAWT) {
+ System.err.println("Skip test: AWT + Exclusive -> Not advised!");
+ return;
+ }
+ final Thread awtRenderThread = getAWTRenderThread();
+ final AnimatorBase animator = createAnimator();
+ if( !useAWTRenderThread ) {
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ }
+ final GLAutoDrawable[] drawables = new GLAutoDrawable[drawableCount];
+ for(int i=0; i<drawableCount; i++) {
+ final int x = ( i % num_x ) * ( demoWinSize + insets.getTotalHeight() ) + insets.getLeftWidth();
+ final int y = ( (i / num_x) % num_y ) * ( demoWinSize + insets.getTotalHeight() ) + insets.getTopHeight();
+
+ drawables[i] = createGLAutoDrawable("Win #"+i, x, y, demoWinSize, demoWinSize, caps);
+ Assert.assertNotNull(drawables[i]);
+ final GearsES2 demo = new GearsES2(swapInterval);
+ demo.setVerbose(false);
+ drawables[i].addGLEventListener(demo);
+ }
+
+ if( preAdd ) {
+ for(int i=0; i<drawableCount; i++) {
+ animator.add(drawables[i]);
+ }
+ if( exclusive ) {
+ if( useAWTRenderThread ) {
+ Assert.assertEquals(null, animator.setExclusiveContext(awtRenderThread));
+ } else {
+ Assert.assertEquals(false, animator.setExclusiveContext(true));
+ }
+ }
+ }
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+
+ // Animator Start
+ Assert.assertTrue(animator.start());
+
+ Assert.assertTrue(animator.isStarted());
+ if( preAdd ) {
+ Assert.assertTrue(animator.isAnimating());
+ } else {
+ Assert.assertFalse(animator.isAnimating());
+ if( exclusive ) {
+ if( useAWTRenderThread ) {
+ Assert.assertEquals(null, animator.setExclusiveContext(awtRenderThread));
+ } else {
+ Assert.assertEquals(false, animator.setExclusiveContext(true));
+ }
+ }
+ for(int i=0; i<drawableCount; i++) {
+ animator.add(drawables[i]);
+ }
+ Assert.assertTrue(animator.isAnimating());
+ }
+ Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled());
+
+ // After start, ExclusiveContextThread is set
+ {
+ final Thread ect = animator.getExclusiveContextThread();
+ if(exclusive) {
+ if( useAWTRenderThread ) {
+ Assert.assertEquals(awtRenderThread, ect);
+ } else {
+ Assert.assertEquals(animator.getThread(), ect);
+ }
+ } else {
+ Assert.assertEquals(null, ect);
+ }
+ for(int i=0; i<drawableCount; i++) {
+ Assert.assertEquals(ect, drawables[i].getExclusiveContextThread());
+ }
+ setGLAutoDrawableVisible(drawables);
+ }
+ animator.setUpdateFPSFrames(showFPSRate, showFPS ? System.err : null);
+
+ // Normal run ..
+ Thread.sleep(duration/durationParts); // 1
+
+ if( !shortenTest ) {
+ // Disable/Enable exclusive mode manually for all GLAutoDrawable
+ if(exclusive) {
+ final Thread ect = animator.getExclusiveContextThread();
+ if( useAWTRenderThread ) {
+ Assert.assertEquals(awtRenderThread, ect);
+ } else {
+ Assert.assertEquals(animator.getThread(), ect);
+ }
+ for(int i=0; i<drawableCount; i++) {
+ final Thread t = drawables[i].setExclusiveContextThread(null);
+ Assert.assertEquals(ect, t);
+ }
+
+ Thread.sleep(duration/durationParts); // 2
+
+ for(int i=0; i<drawableCount; i++) {
+ // poll until clearing drawable ECT is established
+ {
+ boolean ok = null == drawables[i].getExclusiveContextThread();
+ int c = 0;
+ while(!ok && c<5*50) { // 5*50*20 = 5s TO
+ Thread.sleep(20);
+ ok = null == drawables[i].getExclusiveContextThread();
+ c++;
+ }
+ if(c>0) {
+ System.err.println("Clearing drawable ECT was done 'later' @ "+(c*20)+"ms, ok "+ok);
+ }
+ Assert.assertEquals(true, ok);
+ }
+ final Thread t = drawables[i].setExclusiveContextThread(ect);
+ Assert.assertEquals(null, t);
+ }
+
+ Thread.sleep(duration/durationParts); // 3
+ }
+
+ // Disable/Enable exclusive mode via Animator for all GLAutoDrawable
+ if(exclusive) {
+ final Thread ect = animator.getExclusiveContextThread();
+ if( useAWTRenderThread ) {
+ Assert.assertEquals(awtRenderThread, ect);
+ } else {
+ Assert.assertEquals(animator.getThread(), ect);
+ }
+
+ Assert.assertEquals(true, animator.setExclusiveContext(false));
+ Assert.assertFalse(animator.isExclusiveContextEnabled());
+ for(int i=0; i<drawableCount; i++) {
+ Assert.assertEquals(null, drawables[i].getExclusiveContextThread());
+ }
+
+ Thread.sleep(duration/durationParts); // 4
+
+ Assert.assertEquals(null, animator.setExclusiveContext(ect));
+ Assert.assertTrue(animator.isExclusiveContextEnabled());
+ Assert.assertEquals(ect, animator.getExclusiveContextThread());
+ for(int i=0; i<drawableCount; i++) {
+ Assert.assertEquals(ect, drawables[i].getExclusiveContextThread());
+ }
+
+ Thread.sleep(duration/durationParts); // 5
+ }
+
+ Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled());
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ Assert.assertFalse(animator.isPaused());
+
+ // Animator Pause
+ Assert.assertTrue(animator.pause());
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertTrue(animator.isPaused());
+ Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled());
+ if(exclusive) {
+ final Thread ect = animator.getExclusiveContextThread();
+ if( useAWTRenderThread ) {
+ Assert.assertEquals(awtRenderThread, ect);
+ } else {
+ Assert.assertEquals(animator.getThread(), ect);
+ }
+ } else {
+ Assert.assertEquals(null, animator.getExclusiveContextThread());
+ }
+ for(int i=0; i<drawableCount; i++) {
+ Assert.assertEquals(null, drawables[i].getExclusiveContextThread());
+ }
+ Thread.sleep(duration/durationParts); // 6
+
+ // Animator Resume
+ Assert.assertTrue(animator.resume());
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ Assert.assertFalse(animator.isPaused());
+ Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled());
+ if(exclusive) {
+ final Thread ect = animator.getExclusiveContextThread();
+ if( useAWTRenderThread ) {
+ Assert.assertEquals(awtRenderThread, ect);
+ } else {
+ Assert.assertEquals(animator.getThread(), ect);
+ }
+ for(int i=0; i<drawableCount; i++) {
+ Assert.assertEquals(ect, drawables[i].getExclusiveContextThread());
+ }
+ } else {
+ Assert.assertEquals(null, animator.getExclusiveContextThread());
+ for(int i=0; i<drawableCount; i++) {
+ Assert.assertEquals(null, drawables[i].getExclusiveContextThread());
+ }
+ }
+ Thread.sleep(duration/durationParts); // 7
+
+ // Animator Stop #1
+ Assert.assertTrue(animator.stop());
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ Assert.assertFalse(animator.isPaused());
+ Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled());
+ Assert.assertEquals(null, animator.getExclusiveContextThread());
+ for(int i=0; i<drawableCount; i++) {
+ Assert.assertEquals(null, drawables[i].getExclusiveContextThread());
+ }
+ Thread.sleep(duration/durationParts); // 8
+
+ // Animator Re-Start
+ Assert.assertTrue(animator.start());
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled());
+ // After start, ExclusiveContextThread is set
+ {
+ final Thread ect = animator.getExclusiveContextThread();
+ if(exclusive) {
+ if( useAWTRenderThread ) {
+ Assert.assertEquals(awtRenderThread, ect);
+ } else {
+ Assert.assertEquals(animator.getThread(), ect);
+ }
+ } else {
+ Assert.assertEquals(null, ect);
+ }
+ for(int i=0; i<drawableCount; i++) {
+ Assert.assertEquals(ect, drawables[i].getExclusiveContextThread());
+ }
+ }
+ Thread.sleep(duration/durationParts); // 9
+
+ // Remove all drawables .. while running!
+ for(int i=0; i<drawableCount; i++) {
+ final GLAutoDrawable drawable = drawables[i];
+ animator.remove(drawable);
+ Assert.assertEquals(null, drawable.getExclusiveContextThread());
+ }
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertFalse(animator.isAnimating()); // no drawables in list!
+ } // !shortenTest
+
+ // Animator Stop #2
+ Assert.assertTrue(animator.stop());
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ Assert.assertFalse(animator.isPaused());
+ Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled());
+ Assert.assertEquals(null, animator.getExclusiveContextThread());
+
+ // Destroy GLWindows
+ for(int i=0; i<drawableCount; i++) {
+ destroyGLAutoDrawableVisible(drawables[i]);
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(drawables[i], false));
+ }
+ }
+
+ @Test
+ public void test01NormalPre_1Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 1 /* numWin */, false /* exclusive */, true /* preAdd */, false /* short */);
+ }
+
+ @Test
+ public void test02NormalPost_1Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 1 /* numWin */, false /* exclusive */, false /* preAdd */, true /* short */);
+ }
+
+ @Test
+ public void test03ExclPre_1Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 1 /* numWin */, true /* exclusive */, true /* preAdd */, false /* short */);
+ }
+
+ @Test
+ public void test04ExclPost_1Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 1 /* numWin */, true /* exclusive */, false /* preAdd */, true /* short */);
+ }
+
+ @Test
+ public void test05NormalPre_4Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 4 /* numWin */, false /* exclusive */, true /* preAdd */, false /* short */);
+ }
+
+ @Test
+ public void test06NormalPost_4Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 4 /* numWin */, false /* exclusive */, false /* preAdd */, true /* short */);
+ }
+
+ @Test
+ public void test07ExclPre_4Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 4 /* numWin */, true /* exclusive */, true /* preAdd */, false /* short */);
+ }
+
+ @Test
+ public void test08ExclPost_4Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 4 /* numWin */, true /* exclusive */, false /* preAdd */, true /* short */);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00AWT.java
new file mode 100644
index 000000000..414841ab0
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00AWT.java
@@ -0,0 +1,164 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Frame;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.awt.GLCanvas;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
+
+/**
+ * ExclusiveContextThread base implementation to test correctness of the ExclusiveContext feature _and_ AnimatorBase with AWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class ExclusiveContextBase00AWT extends ExclusiveContextBase00 {
+
+ static Thread awtEDT;
+ static boolean osxCALayerAWTModBug;
+
+ @BeforeClass
+ public static void initClass00AWT() {
+
+ final VersionNumber version170 = new VersionNumber(1, 7, 0);
+ osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() &&
+ 0 > Platform.getJavaVersionNumber().compareTo(version170);
+ System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug);
+ System.err.println("OSType "+Platform.getOSType());
+ System.err.println("Java Version "+Platform.getJavaVersionNumber());
+
+ try {
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ awtEDT = Thread.currentThread();
+ } } );
+ } catch (final Exception e) {
+ e.printStackTrace();
+ Assert.assertNull(e);
+ }
+
+ }
+
+ @AfterClass
+ public static void releaseClass00AWT() {
+ }
+
+ @Override
+ protected boolean isAWTTestCase() { return true; }
+
+ @Override
+ protected Thread getAWTRenderThread() {
+ return awtEDT;
+ }
+
+ @Override
+ protected GLAutoDrawable createGLAutoDrawable(final String title, final int x, final int y, final int width, final int height, final GLCapabilitiesImmutable caps) {
+ final GLCanvas glCanvas = new GLCanvas();
+
+ // FIXME: Below AWT layouts freezes OSX/Java7 @ setVisible: Window.setVisible .. [email protected]
+ // final Dimension sz = new Dimension(width, height);
+ // glCanvas.setMinimumSize(sz);
+ // glCanvas.setPreferredSize(sz);
+ // glCanvas.setSize(sz);
+ try {
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ final Frame frame = new Frame();
+ frame.setLayout(new BorderLayout());
+ frame.setMinimumSize(new Dimension(width, height));
+ frame.setBounds(x, y, width, height);
+ frame.add(glCanvas, BorderLayout.CENTER);
+ // frame.pack();
+ frame.validate();
+ if( !osxCALayerAWTModBug ) {
+ frame.setTitle(title);
+ }
+ } });
+ } catch (final Exception e) {
+ e.printStackTrace();
+ Assert.assertNull(e);
+ }
+
+ return glCanvas;
+ }
+
+ protected Frame getFrame(final GLAutoDrawable glad) {
+ Container p = ((Component)glad).getParent();
+ while( null != p && !( p instanceof Frame ) ) {
+ p = p.getParent();
+ }
+ return (Frame)p;
+ }
+
+ @Override
+ protected void setGLAutoDrawableVisible(final GLAutoDrawable[] glads) {
+ try {
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ final int count = glads.length;
+ for(int i=0; i<count; i++) {
+ final GLAutoDrawable glad = glads[i];
+ final Frame frame = getFrame(glad);
+ frame.setVisible(true);
+ }
+ } } );
+ } catch (final Exception e) {
+ e.printStackTrace();
+ Assert.assertNull(e);
+ }
+ }
+
+ @Override
+ protected void destroyGLAutoDrawableVisible(final GLAutoDrawable glad) {
+ final Frame frame = getFrame(glad);
+ try {
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.dispose();
+ } } );
+ } catch (final Exception e) {
+ e.printStackTrace();
+ Assert.assertNull(e);
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00NEWT.java
new file mode 100644
index 000000000..9fe8bd03f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00NEWT.java
@@ -0,0 +1,97 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.opengl.GLWindow;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * ExclusiveContextThread base implementation to test correctness of the ExclusiveContext feature _and_ AnimatorBase with NEWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class ExclusiveContextBase00NEWT extends ExclusiveContextBase00 {
+
+ static Display dpy;
+ static Screen screen;
+
+ @BeforeClass
+ public static void initClass00NEWT() {
+ dpy = NewtFactory.createDisplay(null);
+ screen = NewtFactory.createScreen(dpy, 0);
+ }
+
+ @AfterClass
+ public static void releaseClass00NEWT() {
+ screen = null;
+ dpy = null;
+ }
+
+ @Override
+ protected boolean isAWTTestCase() { return false; }
+
+ @Override
+ protected Thread getAWTRenderThread() {
+ return null;
+ }
+
+ @Override
+ protected GLAutoDrawable createGLAutoDrawable(final String title, final int x, final int y, final int width, final int height, final GLCapabilitiesImmutable caps) {
+ final GLWindow glWindow = GLWindow.create(screen, caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setTitle(title);
+ glWindow.setSize(width, height);
+ glWindow.setPosition(x, y);
+ return glWindow;
+ }
+
+ @Override
+ protected void setGLAutoDrawableVisible(final GLAutoDrawable[] glads) {
+ final int count = glads.length;
+ for(int i=0; i<count; i++) {
+ final GLAutoDrawable glad = glads[i];
+ ((GLWindow)glad).setVisible(true);
+ }
+ }
+
+ @Override
+ protected void destroyGLAutoDrawableVisible(final GLAutoDrawable glad) {
+ ((GLWindow)glad).destroy();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java
new file mode 100644
index 000000000..02f6efdeb
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java
@@ -0,0 +1,217 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Window;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.util.InsetsImmutable;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with AnimatorBase.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class ExclusiveContextBase10 extends UITestCase {
+ static boolean testExclusiveWithAWT = false;
+ static long duration = 1400;
+
+ static boolean showFPS = true;
+ static int showFPSRate = 60;
+
+ static final int demoWinSize = 128;
+
+ static InsetsImmutable insets = null;
+ static int num_x, num_y;
+
+ static int swapInterval = 0;
+
+ @BeforeClass
+ public static void initClass00() {
+ final Window dummyWindow = NewtFactory.createWindow(new Capabilities());
+ dummyWindow.setSize(demoWinSize, demoWinSize);
+ dummyWindow.setVisible(true);
+ Assert.assertEquals(true, dummyWindow.isVisible());
+ Assert.assertEquals(true, dummyWindow.isNativeValid());
+ insets = dummyWindow.getInsets();
+ final int scrnHeight = dummyWindow.getScreen().getHeight();
+ final int scrnWidth = dummyWindow.getScreen().getWidth();
+ final int[] demoScreenSize = dummyWindow.convertToPixelUnits(new int[] { demoWinSize, demoWinSize });
+ final int[] insetsScreenSize = dummyWindow.convertToPixelUnits(new int[] { insets.getTotalWidth(), insets.getTotalHeight() });
+ num_x = scrnWidth / ( demoScreenSize[0] + insetsScreenSize[0] ) - 2;
+ num_y = scrnHeight / ( demoScreenSize[1] + insetsScreenSize[1] ) - 2;
+ dummyWindow.destroy();
+ }
+
+ @AfterClass
+ public static void releaseClass00() {
+ }
+
+ protected abstract boolean isAWTTestCase();
+ protected abstract Thread getAWTRenderThread();
+ protected abstract AnimatorBase createAnimator();
+ protected abstract GLAutoDrawable createGLAutoDrawable(String title, int x, int y, int width, int height, GLCapabilitiesImmutable caps);
+ protected abstract void setGLAutoDrawableVisible(GLAutoDrawable[] glads);
+ protected abstract void destroyGLAutoDrawableVisible(GLAutoDrawable glad);
+
+ protected void runTestGL(final GLCapabilitiesImmutable caps, final int drawableCount, final boolean exclusive) throws InterruptedException {
+ final boolean useAWTRenderThread = isAWTTestCase();
+ if( useAWTRenderThread && exclusive ) {
+ if( testExclusiveWithAWT ) {
+ System.err.println("Warning: Testing AWT + Exclusive -> Not advised!");
+ } else {
+ System.err.println("Info: Skip test: AWT + Exclusive!");
+ return;
+ }
+ }
+ if( useAWTRenderThread && exclusive && !testExclusiveWithAWT) {
+ System.err.println("Skip test: AWT + Exclusive -> Not advised!");
+ return;
+ }
+ final Thread awtRenderThread = getAWTRenderThread();
+ final AnimatorBase animator = createAnimator();
+ if( !useAWTRenderThread ) {
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ }
+ final GLAutoDrawable[] drawables = new GLAutoDrawable[drawableCount];
+ for(int i=0; i<drawableCount; i++) {
+ final int x = ( i % num_x ) * ( demoWinSize + insets.getTotalHeight() ) + insets.getLeftWidth();
+ final int y = ( (i / num_x) % num_y ) * ( demoWinSize + insets.getTotalHeight() ) + insets.getTopHeight();
+
+ drawables[i] = createGLAutoDrawable("Win #"+i, x, y, demoWinSize, demoWinSize, caps);
+ Assert.assertNotNull(drawables[i]);
+ final GearsES2 demo = new GearsES2(swapInterval);
+ demo.setVerbose(false);
+ drawables[i].addGLEventListener(demo);
+ }
+
+ for(int i=0; i<drawableCount; i++) {
+ animator.add(drawables[i]);
+ }
+ if( exclusive ) {
+ if( useAWTRenderThread ) {
+ Assert.assertEquals(null, animator.setExclusiveContext(awtRenderThread));
+ } else {
+ Assert.assertEquals(false, animator.setExclusiveContext(true));
+ }
+ }
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+
+ // Animator Start
+ Assert.assertTrue(animator.start());
+
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled());
+
+ // After start, ExclusiveContextThread is set
+ {
+ final Thread ect = animator.getExclusiveContextThread();
+ if(exclusive) {
+ if( useAWTRenderThread ) {
+ Assert.assertEquals(awtRenderThread, ect);
+ } else {
+ Assert.assertEquals(animator.getThread(), ect);
+ }
+ } else {
+ Assert.assertEquals(null, ect);
+ }
+ for(int i=0; i<drawableCount; i++) {
+ Assert.assertEquals(ect, drawables[i].getExclusiveContextThread());
+ }
+ setGLAutoDrawableVisible(drawables);
+ }
+ animator.setUpdateFPSFrames(showFPSRate, showFPS ? System.err : null);
+
+ // Normal run ..
+ Thread.sleep(duration);
+
+ // Animator Stop #2
+ Assert.assertTrue(animator.stop());
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ Assert.assertFalse(animator.isPaused());
+ Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled());
+ Assert.assertEquals(null, animator.getExclusiveContextThread());
+
+ // Destroy GLWindows
+ for(int i=0; i<drawableCount; i++) {
+ destroyGLAutoDrawableVisible(drawables[i]);
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(drawables[i], false));
+ }
+ }
+
+ @Test
+ public void test01Normal_1Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 1 /* numWin */, false /* exclusive */);
+ }
+
+ @Test
+ public void test03Excl_1Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 1 /* numWin */, true /* exclusive */);
+ }
+
+ @Test
+ public void test05Normal_4Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 4 /* numWin */, false /* exclusive */);
+ }
+
+ @Test
+ public void test07Excl_4Win() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, 4 /* numWin */, true /* exclusive */);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10AWT.java
new file mode 100644
index 000000000..8f4715056
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10AWT.java
@@ -0,0 +1,164 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Frame;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.awt.GLCanvas;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
+
+/**
+ * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with AnimatorBase and AWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class ExclusiveContextBase10AWT extends ExclusiveContextBase10 {
+
+ static Thread awtEDT;
+ static boolean osxCALayerAWTModBug;
+
+ @BeforeClass
+ public static void initClass00AWT() {
+
+ final VersionNumber version170 = new VersionNumber(1, 7, 0);
+ osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() &&
+ 0 > Platform.getJavaVersionNumber().compareTo(version170);
+ System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug);
+ System.err.println("OSType "+Platform.getOSType());
+ System.err.println("Java Version "+Platform.getJavaVersionNumber());
+
+ try {
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ awtEDT = Thread.currentThread();
+ } } );
+ } catch (final Exception e) {
+ e.printStackTrace();
+ Assert.assertNull(e);
+ }
+
+ }
+
+ @AfterClass
+ public static void releaseClass00AWT() {
+ }
+
+ @Override
+ protected boolean isAWTTestCase() { return true; }
+
+ @Override
+ protected Thread getAWTRenderThread() {
+ return awtEDT;
+ }
+
+ @Override
+ protected GLAutoDrawable createGLAutoDrawable(final String title, final int x, final int y, final int width, final int height, final GLCapabilitiesImmutable caps) {
+ final GLCanvas glCanvas = new GLCanvas();
+
+ // FIXME: Below AWT layouts freezes OSX/Java7 @ setVisible: Window.setVisible .. [email protected]
+ // final Dimension sz = new Dimension(width, height);
+ // glCanvas.setMinimumSize(sz);
+ // glCanvas.setPreferredSize(sz);
+ // glCanvas.setSize(sz);
+ try {
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ final Frame frame = new Frame();
+ frame.setLayout(new BorderLayout());
+ frame.setMinimumSize(new Dimension(width, height));
+ frame.setBounds(x, y, width, height);
+ frame.add(glCanvas, BorderLayout.CENTER);
+ // frame.pack();
+ frame.validate();
+ if( !osxCALayerAWTModBug ) {
+ frame.setTitle(title);
+ }
+ } });
+ } catch (final Exception e) {
+ e.printStackTrace();
+ Assert.assertNull(e);
+ }
+
+ return glCanvas;
+ }
+
+ protected Frame getFrame(final GLAutoDrawable glad) {
+ Container p = ((Component)glad).getParent();
+ while( null != p && !( p instanceof Frame ) ) {
+ p = p.getParent();
+ }
+ return (Frame)p;
+ }
+
+ @Override
+ protected void setGLAutoDrawableVisible(final GLAutoDrawable[] glads) {
+ try {
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ final int count = glads.length;
+ for(int i=0; i<count; i++) {
+ final GLAutoDrawable glad = glads[i];
+ final Frame frame = getFrame(glad);
+ frame.setVisible(true);
+ }
+ } } );
+ } catch (final Exception e) {
+ e.printStackTrace();
+ Assert.assertNull(e);
+ }
+ }
+
+ @Override
+ protected void destroyGLAutoDrawableVisible(final GLAutoDrawable glad) {
+ final Frame frame = getFrame(glad);
+ try {
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.dispose();
+ } } );
+ } catch (final Exception e) {
+ e.printStackTrace();
+ Assert.assertNull(e);
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10NEWT.java
new file mode 100644
index 000000000..84e6ed7f3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10NEWT.java
@@ -0,0 +1,97 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.opengl.GLWindow;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with AnimatorBase and NEWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class ExclusiveContextBase10NEWT extends ExclusiveContextBase10 {
+
+ static Display dpy;
+ static Screen screen;
+
+ @BeforeClass
+ public static void initClass00NEWT() {
+ dpy = NewtFactory.createDisplay(null);
+ screen = NewtFactory.createScreen(dpy, 0);
+ }
+
+ @AfterClass
+ public static void releaseClass00NEWT() {
+ screen = null;
+ dpy = null;
+ }
+
+ @Override
+ protected boolean isAWTTestCase() { return false; }
+
+ @Override
+ protected Thread getAWTRenderThread() {
+ return null;
+ }
+
+ @Override
+ protected GLAutoDrawable createGLAutoDrawable(final String title, final int x, final int y, final int width, final int height, final GLCapabilitiesImmutable caps) {
+ final GLWindow glWindow = GLWindow.create(screen, caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setTitle(title);
+ glWindow.setSize(width, height);
+ glWindow.setPosition(x, y);
+ return glWindow;
+ }
+
+ @Override
+ protected void setGLAutoDrawableVisible(final GLAutoDrawable[] glads) {
+ final int count = glads.length;
+ for(int i=0; i<count; i++) {
+ final GLAutoDrawable glad = glads[i];
+ ((GLWindow)glad).setVisible(true);
+ }
+ }
+
+ @Override
+ protected void destroyGLAutoDrawableVisible(final GLAutoDrawable glad) {
+ ((GLWindow)glad).destroy();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimAWT.java
new file mode 100644
index 000000000..6a6f579a6
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimAWT.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import java.io.IOException;
+
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * ExclusiveContextThread VSync Animator to test correctness of the ExclusiveContext feature _and_ Animator with AWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestExclusiveContext01VSyncAnimAWT extends ExclusiveContextBase00AWT {
+
+ @Override
+ protected AnimatorBase createAnimator() {
+ return new Animator();
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-showFPS")) {
+ i++;
+ showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ;
+ } else if(args[i].equals("-forceExclusiveTest")) {
+ testExclusiveWithAWT = true;
+ }
+ }
+ System.err.println("duration "+duration);
+ System.err.println("showFPS "+showFPS);
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("testExclusiveWithAWT "+testExclusiveWithAWT);
+
+ org.junit.runner.JUnitCore.main(TestExclusiveContext01VSyncAnimAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimNEWT.java
new file mode 100644
index 000000000..a90dc0a5a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimNEWT.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import java.io.IOException;
+
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * ExclusiveContextThread VSync Animator to test correctness of the ExclusiveContext feature _and_ Animator with NEWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestExclusiveContext01VSyncAnimNEWT extends ExclusiveContextBase00NEWT {
+
+ @Override
+ protected AnimatorBase createAnimator() {
+ return new Animator();
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-showFPS")) {
+ i++;
+ showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ;
+ }
+ }
+ System.err.println("duration "+duration);
+ System.err.println("showFPS "+showFPS);
+ System.err.println("swapInterval "+swapInterval);
+
+ org.junit.runner.JUnitCore.main(TestExclusiveContext01VSyncAnimNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimAWT.java
new file mode 100644
index 000000000..0769fc93e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimAWT.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import java.io.IOException;
+
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.FPSAnimator;
+
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * ExclusiveContextThread FPS Animator to test correctness of the ExclusiveContext feature _and_ FPSAnimator with AWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestExclusiveContext02FPSAnimAWT extends ExclusiveContextBase00AWT {
+
+ @Override
+ protected AnimatorBase createAnimator() {
+ return new FPSAnimator(0);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-showFPS")) {
+ i++;
+ showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ;
+ } else if(args[i].equals("-forceExclusiveTest")) {
+ testExclusiveWithAWT = true;
+ }
+ }
+ System.err.println("duration "+duration);
+ System.err.println("showFPS "+showFPS);
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("testExclusiveWithAWT "+testExclusiveWithAWT);
+
+ org.junit.runner.JUnitCore.main(TestExclusiveContext02FPSAnimAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimNEWT.java
new file mode 100644
index 000000000..c9193071b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimNEWT.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import java.io.IOException;
+
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.FPSAnimator;
+
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * ExclusiveContextThread FPS Animator to test correctness of the ExclusiveContext feature _and_ FPSAnimator with NEWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestExclusiveContext02FPSAnimNEWT extends ExclusiveContextBase00NEWT {
+
+ @Override
+ protected AnimatorBase createAnimator() {
+ return new FPSAnimator(0);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-showFPS")) {
+ i++;
+ showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ;
+ }
+ }
+ System.err.println("duration "+duration);
+ System.err.println("showFPS "+showFPS);
+ System.err.println("swapInterval "+swapInterval);
+
+ org.junit.runner.JUnitCore.main(TestExclusiveContext02FPSAnimNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext11VSyncAnimNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext11VSyncAnimNEWT.java
new file mode 100644
index 000000000..08d385dc3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext11VSyncAnimNEWT.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import java.io.IOException;
+
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with Animator and NEWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestExclusiveContext11VSyncAnimNEWT extends ExclusiveContextBase10NEWT {
+
+ @Override
+ protected AnimatorBase createAnimator() {
+ return new Animator();
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-showFPS")) {
+ i++;
+ showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ;
+ }
+ }
+ System.err.println("duration "+duration);
+ System.err.println("showFPS "+showFPS);
+ System.err.println("swapInterval "+swapInterval);
+
+ org.junit.runner.JUnitCore.main(TestExclusiveContext11VSyncAnimNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext12FPSAnimNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext12FPSAnimNEWT.java
new file mode 100644
index 000000000..8a4519228
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext12FPSAnimNEWT.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
+
+import java.io.IOException;
+
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.FPSAnimator;
+
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with FPSAnimator and NEWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestExclusiveContext12FPSAnimNEWT extends ExclusiveContextBase10NEWT {
+
+ @Override
+ protected AnimatorBase createAnimator() {
+ return new FPSAnimator(0);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-showFPS")) {
+ i++;
+ showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ;
+ }
+ }
+ System.err.println("duration "+duration);
+ System.err.println("showFPS "+showFPS);
+ System.err.println("swapInterval "+swapInterval);
+
+ org.junit.runner.JUnitCore.main(TestExclusiveContext12FPSAnimNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase0.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase0.java
new file mode 100644
index 000000000..08614f9fb
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase0.java
@@ -0,0 +1,264 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
+
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.Threading;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Test re-association (switching) of GLWindow /GLDrawables,
+ * from GLWindow/GLOffscreenAutoDrawable to an GLOffscreenAutoDrawable and back.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class GLContextDrawableSwitchBase0 extends UITestCase {
+ static int width, height;
+ static boolean testEvenUnsafeSwapGLContext = false;
+
+ static GLCapabilities getCaps(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ @BeforeClass
+ public static void initClass() {
+ width = 256;
+ height = 256;
+ }
+
+ public abstract GLAutoDrawable createGLAutoDrawable(final QuitAdapter quitAdapter, final GLCapabilitiesImmutable caps, final int width, final int height) throws InterruptedException, InvocationTargetException;
+ public abstract void destroyGLAutoDrawable(final GLAutoDrawable glad) throws InterruptedException, InvocationTargetException;
+
+ @Test(timeout=30000)
+ public void test01aSwitch2Onscreen2OnscreenGL2ES2_Def() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testImpl(reqGLCaps, true);
+ }
+
+ @Test(timeout=30000)
+ public void test01bSwitch2Onscreen2OffscreenGL2ES2_Def() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testImpl(reqGLCaps, false);
+ }
+
+ @Test(timeout=30000)
+ public void test01cSwitch2Offscreen2OffscreenGL2ES2_Def() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ testImpl(reqGLCaps, false);
+ }
+
+ @Test(timeout=30000)
+ public void test01dSwitch2Offscreen2OnscreenGL2ES2_Def() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ testImpl(reqGLCaps, true);
+ }
+
+ @Test(timeout=30000)
+ public void test02aSwitch2Onscreen2OnscreenGL2ES2_MSAA() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setNumSamples(4);
+ reqGLCaps.setSampleBuffers(true);
+ testImpl(reqGLCaps, true);
+ }
+
+ @Test(timeout=30000)
+ public void test02bSwitch2Onscreen2OffscreenGL2ES2_MSAA() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setNumSamples(4);
+ reqGLCaps.setSampleBuffers(true);
+ testImpl(reqGLCaps, false);
+ }
+
+ @Test(timeout=30000)
+ public void test02cSwitch2Offscreen2OffscreenGL2ES2_MSAA() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setNumSamples(4);
+ reqGLCaps.setSampleBuffers(true);
+ testImpl(reqGLCaps, false);
+ }
+
+ @Test(timeout=30000)
+ public void test02dSwitch2Offscreen2OnscreenGL2ES2_MSAA() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setNumSamples(4);
+ reqGLCaps.setSampleBuffers(true);
+ testImpl(reqGLCaps, true);
+ }
+
+ @Test(timeout=30000)
+ public void test03aSwitch2Onscreen2OnscreenGL2ES2_Accu() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setAccumRedBits(1);
+ reqGLCaps.setAccumGreenBits(1);
+ reqGLCaps.setAccumBlueBits(1);
+ testImpl(reqGLCaps, true);
+ }
+
+ @Test(timeout=30000)
+ public void test03bSwitch2Onscreen2OffscreenGL2ES2_Accu() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setAccumRedBits(1);
+ reqGLCaps.setAccumGreenBits(1);
+ reqGLCaps.setAccumBlueBits(1);
+ testImpl(reqGLCaps, false);
+ }
+
+ @Test(timeout=30000)
+ public void test03cSwitch2Offscreen2OffscreenGL2ES2_Accu() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setAccumRedBits(1);
+ reqGLCaps.setAccumGreenBits(1);
+ reqGLCaps.setAccumBlueBits(1);
+ testImpl(reqGLCaps, false);
+ }
+
+ @Test(timeout=30000)
+ public void test03dSwitch2Offscreen2OnscreenGL2ES2_Accu() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ reqGLCaps.setOnscreen(false);
+ reqGLCaps.setAccumRedBits(1);
+ reqGLCaps.setAccumGreenBits(1);
+ reqGLCaps.setAccumBlueBits(1);
+ testImpl(reqGLCaps, true);
+ }
+
+ private void testImpl(final GLCapabilitiesImmutable srcCapsRequested, final boolean dstOnscreen) throws InterruptedException, InvocationTargetException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ final GLAutoDrawable gladSource = createGLAutoDrawable(quitAdapter, srcCapsRequested, width, height);
+
+ final GLCapabilitiesImmutable srcCapsChosen = gladSource.getChosenGLCapabilities();
+
+ final GLCapabilities dstCaps = (GLCapabilities) srcCapsChosen.cloneMutable();
+ dstCaps.setOnscreen(dstOnscreen);
+
+ final boolean isSwapGLContextSafe = GLDrawableUtil.isSwapGLContextSafe(srcCapsRequested, srcCapsChosen, dstCaps);
+ System.err.println("Source Caps Requested: "+srcCapsRequested);
+ System.err.println("Source Caps Chosen : "+srcCapsChosen);
+ System.err.println("Dest Caps Requested: "+dstCaps);
+ System.err.println("Is SwapGLContext safe: "+isSwapGLContextSafe);
+
+ if( !isSwapGLContextSafe && !testEvenUnsafeSwapGLContext ) {
+ System.err.println("Supressing unsafe tests ...");
+ destroyGLAutoDrawable(gladSource);
+ return;
+ }
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GearsES2 gears = new GearsES2(1);
+ gears.setVerbose(false);
+ gladSource.addGLEventListener(gears);
+ gladSource.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ final Animator animator = new Animator();
+ animator.add(gladSource);
+ animator.start();
+
+ int s = 0;
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ final GLAutoDrawable gladDest = createGLAutoDrawable(quitAdapter, dstCaps, width, height);
+ RuntimeException caught = null;
+ try {
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+
+ final Runnable switchAction = new Runnable() {
+ public void run() {
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(gladSource, gladDest);
+ } };
+
+ // switch context _and_ the demo synchronously
+ if( gladSource.isThreadGLCapable() && gladDest.isThreadGLCapable() ) {
+ switchAction.run();
+ } else {
+ Threading.invokeOnOpenGLThread(true, switchAction);
+ }
+ snapshotGLEventListener.setMakeSnapshot();
+
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+ } catch (final RuntimeException t) {
+ caught = t;
+ }
+
+ animator.stop();
+ destroyGLAutoDrawable(gladDest);
+ destroyGLAutoDrawable(gladSource);
+
+ if( null != caught ) {
+ throw caught;
+ }
+ }
+
+ // default timing for 2 switches
+ static long duration = 2900; // ms
+ static long period = 1000; // ms
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase1.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase1.java
new file mode 100644
index 000000000..0e7ea3e83
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase1.java
@@ -0,0 +1,291 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
+
+import java.awt.Dimension;
+import java.awt.Frame;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLOffscreenAutoDrawable;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.opengl.GLWindow;
+
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.GLEventListenerCounter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+
+/**
+ * Test re-association of GLContext/GLDrawables,
+ * here GLContext's survival of GLDrawable destruction
+ * and reuse w/ new or recreated GLDrawable.
+ * <p>
+ * Test utilizes {@link GLEventListenerState} for preserving the
+ * GLAutoDrawable state, i.e. GLContext, all GLEventListener
+ * and the GLAnimatorControl association.
+ * </p>
+ * <p>
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ * </p>
+ */
+public abstract class GLContextDrawableSwitchBase1 extends UITestCase {
+ static protected enum GLADType { GLCanvasOnscreen, GLCanvasOffscreen, GLWindow, GLOffscreen };
+
+ // default period for 1 GLAD cycle
+ static long duration = 1000; // ms
+
+ static int width, height;
+
+ static GLCapabilities getCaps(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ @BeforeClass
+ public static void initClass() {
+ width = 256;
+ height = 256;
+ }
+
+ static void setGLCanvasSize(final GLCanvas glc, final Dimension new_sz) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ glc.setMinimumSize(new_sz);
+ glc.setPreferredSize(new_sz);
+ glc.setSize(new_sz);
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ static void setFrameVisible(final Frame frame) throws InterruptedException {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ frame.setVisible(true);
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ static void destroyFrame(final Frame frame) throws InterruptedException {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.dispose();
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ private GLOffscreenAutoDrawable createGLOffscreenAutoDrawable(final GLCapabilities caps, final int width, final int height) throws InterruptedException {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ return factory.createOffscreenAutoDrawable(null, caps, null, width, height);
+ }
+
+ protected static boolean validateOnOffscreenLayer(final GLADType gladType1, final GLADType gladType2) {
+ final boolean useOffscreenLayer = GLADType.GLCanvasOffscreen == gladType1 || GLADType.GLCanvasOffscreen == gladType2 ;
+ final boolean useOnscreenLayer = GLADType.GLCanvasOnscreen == gladType1 || GLADType.GLCanvasOnscreen == gladType2 ;
+ if( useOffscreenLayer ) {
+ if( !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("Platform doesn't support offscreen rendering.");
+ return false;
+ }
+ } else if( useOnscreenLayer ) {
+ if( JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("Platform requires offscreen rendering.");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected void testGLADOneLifecycle(final Screen screen, final GLCapabilities caps, final GLADType gladType, final int width,
+ final int height, final GLEventListenerCounter glelTracker,
+ final SnapshotGLEventListener snapshotGLEventListener, final GLEventListenerState glelsIn, final GLEventListenerState glelsOut[], final GLAnimatorControl animator)
+ throws InterruptedException {
+
+ System.err.println("GLAD Lifecycle.0 "+gladType+", restoring "+((null!=glelsIn)?true:false)+", preserving "+((null!=glelsOut)?true:false));
+ final Frame frame;
+ final GLAutoDrawable glad;
+ if( GLADType.GLCanvasOnscreen == gladType ) {
+ if( jogamp.nativewindow.jawt.JAWTUtil.isOffscreenLayerRequired() ) {
+ throw new InternalError("Platform requires offscreen rendering, but onscreen requested: "+gladType);
+ }
+ frame = new Frame("AWT GLCanvas");
+
+ glad = new GLCanvas(caps);
+ setGLCanvasSize((GLCanvas)glad, new Dimension(width, height));
+ frame.add((GLCanvas)glad);
+ } else if( GLADType.GLCanvasOffscreen == gladType ) {
+ if( !jogamp.nativewindow.jawt.JAWTUtil.isOffscreenLayerSupported() ) {
+ throw new InternalError("Platform doesn't support offscreen rendering: "+gladType);
+ }
+ frame = new Frame("AWT GLCanvas");
+
+ glad = new GLCanvas(caps);
+ ((GLCanvas)glad).setShallUseOffscreenLayer(true);
+ setGLCanvasSize((GLCanvas)glad, new Dimension(width, height));
+ frame.add((GLCanvas)glad);
+ } else if( GLADType.GLWindow == gladType ) {
+ frame = null;
+
+ if( null != screen ) {
+ glad = GLWindow.create(screen, caps);
+ } else {
+ glad = GLWindow.create(caps);
+ }
+ ((GLWindow)glad).setTitle("Newt GLWindow");
+ ((GLWindow)glad).setSize(width, height);
+ } else if( GLADType.GLOffscreen == gladType ) {
+ frame = null;
+
+ glad = this.createGLOffscreenAutoDrawable(caps, width, height);
+ } else {
+ throw new InternalError("Unsupported: "+gladType);
+ }
+
+ if( null == glelsIn ) {
+ if( null != animator ) {
+ animator.add(glad);
+ }
+ glad.addGLEventListener(glelTracker);
+ glad.addGLEventListener(new GearsES2(1));
+ glad.addGLEventListener(snapshotGLEventListener);
+ }
+ snapshotGLEventListener.setMakeSnapshot();
+
+ if( GLADType.GLCanvasOnscreen == gladType || GLADType.GLCanvasOffscreen == gladType ) {
+ setFrameVisible(frame);
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ } else if( GLADType.GLWindow == gladType ) {
+ ((GLWindow)glad).setVisible(true);
+ }
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glad, true));
+ Assert.assertNotNull(glad.getContext());
+ Assert.assertTrue(glad.isRealized());
+
+ if( null != glelsIn ) {
+ Assert.assertEquals(0, glad.getGLEventListenerCount());
+ System.err.println(".. restoring.0");
+ glelsIn.moveTo(glad);
+ System.err.println(".. restoring.X");
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(3, glad.getGLEventListenerCount());
+
+ Assert.assertEquals(glelsIn.context, glad.getContext());
+ Assert.assertEquals(glelsIn.listenerCount(), glad.getGLEventListenerCount());
+ Assert.assertEquals(glelsIn.context.getGLReadDrawable(), glad.getDelegatedDrawable());
+ Assert.assertEquals(glelsIn.context.getGLDrawable(), glad.getDelegatedDrawable());
+ Assert.assertEquals(false, glelsIn.isOwner());
+ }
+
+ for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER &&
+ ( 1 > glelTracker.initCount || 1 > glelTracker.reshapeCount || 1 > glelTracker.displayCount );
+ wait++) {
+ Thread.sleep(AWTRobotUtil.TIME_SLICE);
+ }
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( ( t1 - t0 ) < duration ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+
+ if( null != glelsOut ) {
+ final GLContext context1 = glad.getContext();
+ System.err.println(".. preserving.0");
+ glelsOut[0] = GLEventListenerState.moveFrom(glad);
+ System.err.println(".. preserving.X");
+
+ Assert.assertEquals(context1, glelsOut[0].context);
+ Assert.assertNull(context1.getGLReadDrawable());
+ Assert.assertNull(context1.getGLDrawable());
+ Assert.assertEquals(3, glelsOut[0].listenerCount());
+ Assert.assertEquals(true, glelsOut[0].isOwner());
+ Assert.assertEquals(null, glad.getContext());
+ Assert.assertEquals(0, glad.getGLEventListenerCount());
+ }
+ if( GLADType.GLCanvasOnscreen == gladType || GLADType.GLCanvasOffscreen == gladType ) {
+ destroyFrame(frame);
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false));
+ } else if( GLADType.GLWindow == gladType ) {
+ glad.destroy();
+ } else if( GLADType.GLOffscreen == gladType ) {
+ glad.destroy();
+ }
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glad, false));
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ if( null != glelsOut ) {
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ } else {
+ Assert.assertEquals(1, glelTracker.disposeCount);
+ }
+ System.err.println("GLAD Lifecycle.X "+gladType);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java
new file mode 100644
index 000000000..e961fe32d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.GLRendererQuirks;
+import com.jogamp.opengl.test.junit.util.GLEventListenerCounter;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Tests Bug 722
+ * <p>
+ * See Bug 722 - https://jogamp.org/bugzilla/show_bug.cgi?id=722.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug722GLContextDrawableSwitchNewt2AWT extends GLContextDrawableSwitchBase1 {
+
+ static int loops = 10;
+ static long duration2 = 100; // ms
+
+ /**
+ * Interesting artifact w/ ATI proprietary driver is that the
+ * bug causing the quirk {@link GLRendererQuirks#DontCloseX11Display}
+ * also causes an XCB crash when reusing the X11 display connection
+ * from AWT -> NEWT. Pre-allocating the X11 Display and keeping it referenced
+ * to avoid such re-usage worksaround this problem.
+ */
+ public static boolean fixedNewtDisplay = true;
+
+ @Test(timeout=180000) // TO 3 min
+ public void test11GLWindow2GLCanvasOnScrnGL2ES2() throws InterruptedException {
+ final GLCapabilities caps = getCaps(GLProfile.GL2ES2);
+ if(null == caps) {
+ System.err.println("GL2ES2 n/a, test n/a.");
+ return;
+ }
+ if( jogamp.nativewindow.jawt.JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("JAWT required offscreen, test n/a.");
+ return;
+ }
+
+
+ final GLADType gladType1 = GLADType.GLWindow;
+ final GLADType gladType2 = GLADType.GLCanvasOnscreen;
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final Display dpy;
+ final Screen screen;
+ if( fixedNewtDisplay ) {
+ dpy = NewtFactory.createDisplay(null);
+ screen = NewtFactory.createScreen(dpy, 0);
+ screen.addReference();
+ } else {
+ dpy = null;
+ screen = null;
+ }
+
+ duration = duration2;
+
+ for(int i=0; i<loops; i++) {
+ final GLEventListenerState glels[] = new GLEventListenerState[1];
+ final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ System.err.println("Test "+i+"/"+loops+".1: GLAD-1 "+gladType1+", preserving.");
+ testGLADOneLifecycle(screen, caps, gladType1, width, height,
+ glelTracker, snapshotGLEventListener,
+ null,
+ glels, animator);
+ System.err.println("Test "+i+"/"+loops+".1: done");
+ }
+
+ // - create glad2 w/ survived context
+ {
+ System.err.println("Test "+i+"/"+loops+".2: GLAD-1 "+gladType2+", restoring.");
+ testGLADOneLifecycle(screen, caps, gladType2, width+100, height+100,
+ glelTracker, snapshotGLEventListener,
+ glels[0],
+ null, null);
+ System.err.println("Test "+i+"/"+loops+".2: done.");
+ }
+ }
+ animator.stop();
+
+ if( fixedNewtDisplay ) {
+ screen.removeReference();
+ }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration2 = MiscUtils.atol(args[i], duration2);
+ } else if(args[i].equals("-loops")) {
+ i++;
+ loops = MiscUtils.atoi(args[i], loops);
+ } else if(args[i].equals("-noFixedNewtDisplay")) {
+ fixedNewtDisplay = false;
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestBug722GLContextDrawableSwitchNewt2AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java
index 4c1130498..603c858c9 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,13 +20,13 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.jogl.acore;
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
import java.io.IOException;
@@ -43,11 +43,11 @@ import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import com.jogamp.opengl.GLAutoDrawableDelegate;
import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLDrawableUtil;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
@@ -58,22 +58,32 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
-public class TestGLContextDrawableSwitchNEWT extends UITestCase {
- static GLProfile glp;
- static GLCapabilities caps;
+/**
+ * Test re-association (switching) of GLContext/GLDrawables,
+ * i.e. ctx1/draw1, ctx2/draw2 -> ctx1/draw2, ctx2/draw1.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLContextDrawableSwitch01NEWT extends UITestCase {
static int width, height;
+ static GLCapabilities getCaps(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
@BeforeClass
public static void initClass() {
- glp = GLProfile.getGL2ES2();
- caps = new GLCapabilities(glp);
width = 256;
height = 256;
}
- /** Note: No GLContext is attached w/ this implementation ! */
- private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
+ private GLAutoDrawable createGLAutoDrawable(final GLCapabilities caps, final int x, final int y, final int width, final int height, final WindowListener wl) throws InterruptedException {
final Window window = NewtFactory.createWindow(caps);
Assert.assertNotNull(window);
window.setPosition(x, y);
@@ -81,97 +91,103 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
window.setVisible(true);
Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
-
+
final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
final GLDrawable drawable = factory.createGLDrawable(window);
Assert.assertNotNull(drawable);
-
+
drawable.setRealized(true);
Assert.assertTrue(drawable.isRealized());
-
+
final GLContext context = drawable.createContext(null);
Assert.assertNotNull(context);
-
+
final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) {
@Override
protected void destroyImplInLock() {
super.destroyImplInLock();
window.destroy(); // destroys the actual window
- }
+ }
};
-
+
+ window.setWindowDestroyNotifyAction( new Runnable() {
+ public void run() {
+ glad.windowDestroyNotifyOp();
+ } } );
+
// add basic window interaction
window.addWindowListener(new WindowAdapter() {
@Override
- public void windowRepaint(WindowUpdateEvent e) {
+ public void windowRepaint(final WindowUpdateEvent e) {
glad.windowRepaintOp();
}
@Override
- public void windowResized(WindowEvent e) {
- glad.windowResizedOp(window.getWidth(), window.getHeight());
- }
- @Override
- public void windowDestroyNotify(WindowEvent e) {
- glad.windowDestroyNotifyOp();
+ public void windowResized(final WindowEvent e) {
+ glad.windowResizedOp(window.getSurfaceWidth(), window.getSurfaceHeight());
}
});
window.addWindowListener(wl);
-
+
return glad;
}
-
+
+ @Test(timeout=30000)
+ public void testSwitch2WindowSingleContextGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testSwitch2WindowSingleContextImpl(reqGLCaps);
+ }
+
@Test(timeout=30000)
- public void testSwitch2WindowSingleContext() throws InterruptedException {
+ public void testSwitch2WindowSingleContextGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testSwitch2WindowSingleContextImpl(reqGLCaps);
+ }
+
+ private void testSwitch2WindowSingleContextImpl(final GLCapabilities caps) throws InterruptedException {
final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter); // no GLContext!
- GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter); // no GLContext!
-
+
+ final GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
+ final GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+
// create single context using glad1 and assign it to glad1,
- // after destroying the prev. context!
+ // destroy the prev. context afterwards.
{
- final GLContext oldCtx = glad1.getContext();
+ final GLContext newCtx = glad1.createContext(null);
+ Assert.assertNotNull(newCtx);
+ final GLContext oldCtx = glad1.setContext(newCtx, true);
Assert.assertNotNull(oldCtx);
- oldCtx.destroy();
- final GLContext singleCtx = glad1.createContext(null);
- Assert.assertNotNull(singleCtx);
- int res = singleCtx.makeCurrent();
+ Assert.assertFalse(oldCtx.isCreated());
+ final int res = newCtx.makeCurrent();
Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
- singleCtx.release();
- glad1.setContext(singleCtx);
+ newCtx.release();
}
-
- GearsES2 gears = new GearsES2(1);
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GearsES2 gears = new GearsES2(1);
glad1.addGLEventListener(gears);
-
- Animator animator = new Animator();
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ final Animator animator = new Animator();
animator.add(glad1);
animator.add(glad2);
animator.start();
-
+
int s = 0;
- long t0 = System.currentTimeMillis();
+ final long t0 = System.currentTimeMillis();
long t1 = t0;
-
+
while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
if( ( t1 - t0 ) / period > s) {
s++;
System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- animator.pause();
-
- if(0 == s%2) {
- glad1.addGLEventListener(0, glad2.removeGLEventListener(0));
- GLContext ctx1 = glad1.setContext(glad2.getContext());
- glad2.setContext(ctx1);
- } else {
- glad2.addGLEventListener(0, glad1.removeGLEventListener(0));
- GLContext ctx2 = glad2.setContext(glad1.getContext());
- glad1.setContext(ctx2);
- }
-
+
+ // switch context _and_ the demo synchronously
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2);
+
System.err.println(s+" - switch - END "+ ( t1 - t0 ));
-
- animator.resume();
}
Thread.sleep(100);
t1 = System.currentTimeMillis();
@@ -179,58 +195,71 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
animator.stop();
glad1.destroy();
- glad2.destroy();
+ glad2.destroy();
}
-
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowOneDemoGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowOneDemoImpl(reqGLCaps);
+ }
+
@Test(timeout=30000)
- public void testSwitch2GLWindowOneDemo() throws InterruptedException {
- GearsES2 gears = new GearsES2(1);
+ public void testSwitch2GLWindowOneDemoGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowOneDemoImpl(reqGLCaps);
+ }
+
+ private void testSwitch2GLWindowOneDemoImpl(final GLCapabilities caps) throws InterruptedException {
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GearsES2 gears = new GearsES2(1);
final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLWindow glWindow1 = GLWindow.create(caps);
+
+ final GLWindow glWindow1 = GLWindow.create(caps);
glWindow1.setTitle("win1");
glWindow1.setSize(width, height);
glWindow1.setPosition(64, 64);
glWindow1.addGLEventListener(0, gears);
+ glWindow1.addGLEventListener(snapshotGLEventListener);
glWindow1.addWindowListener(quitAdapter);
-
- GLWindow glWindow2 = GLWindow.create(caps);
- glWindow2.setTitle("win2");
+
+ final GLWindow glWindow2 = GLWindow.create(caps);
+ glWindow2.setTitle("win2");
glWindow2.setSize(width+100, height+100);
glWindow2.setPosition(2*64+width, 64);
glWindow2.addWindowListener(quitAdapter);
- Animator animator = new Animator();
+ final Animator animator = new Animator();
animator.add(glWindow1);
animator.add(glWindow2);
animator.start();
-
+
glWindow1.setVisible(true);
glWindow2.setVisible(true);
+ snapshotGLEventListener.setMakeSnapshot();
+
int s = 0;
- long t0 = System.currentTimeMillis();
+ final long t0 = System.currentTimeMillis();
long t1 = t0;
-
+
while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
if( ( t1 - t0 ) / period > s) {
s++;
System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- animator.pause();
-
- if(0 == s%2) {
- glWindow1.addGLEventListener(0, glWindow2.removeGLEventListener(0));
- GLContext ctx1 = glWindow1.setContext(glWindow2.getContext());
- glWindow2.setContext(ctx1);
- } else {
- glWindow2.addGLEventListener(0, glWindow1.removeGLEventListener(0));
- GLContext ctx2 = glWindow2.setContext(glWindow1.getContext());
- glWindow1.setContext(ctx2);
- }
-
+ System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+
+ // switch context _and_ the demo synchronously
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
+
+ System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
System.err.println(s+" - switch - END "+ ( t1 - t0 ));
-
- animator.resume();
+
+ snapshotGLEventListener.setMakeSnapshot();
}
Thread.sleep(100);
t1 = System.currentTimeMillis();
@@ -239,92 +268,110 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
animator.stop();
glWindow1.destroy();
glWindow2.destroy();
-
+
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowEachWithOwnDemoGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps);
}
-
+
@Test(timeout=30000)
- public void testSwitch2GLWindowEachWithOwnDemo() throws InterruptedException {
- GearsES2 gears = new GearsES2(1);
- RedSquareES2 rsquare = new RedSquareES2(1);
+ public void testSwitch2GLWindowEachWithOwnDemoGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps);
+ }
+
+ public void testSwitch2GLWindowEachWithOwnDemoImpl(final GLCapabilities caps) throws InterruptedException {
+ final GearsES2 gears = new GearsES2(1);
+ final RedSquareES2 rsquare = new RedSquareES2(1);
final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLWindow glWindow1 = GLWindow.create(caps);
+ final SnapshotGLEventListener snapshotGLEventListener1 = new SnapshotGLEventListener();
+ final SnapshotGLEventListener snapshotGLEventListener2 = new SnapshotGLEventListener();
+
+ final GLWindow glWindow1 = GLWindow.create(caps);
glWindow1.setTitle("win1");
glWindow1.setSize(width, height);
glWindow1.setPosition(64, 64);
glWindow1.addGLEventListener(0, gears);
+ glWindow1.addGLEventListener(snapshotGLEventListener1);
glWindow1.addWindowListener(quitAdapter);
-
- GLWindow glWindow2 = GLWindow.create(caps);
- glWindow2.setTitle("win2");
+
+ final GLWindow glWindow2 = GLWindow.create(caps);
+ glWindow2.setTitle("win2");
glWindow2.setSize(width+100, height+100);
glWindow2.setPosition(2*64+width, 64);
glWindow2.addGLEventListener(0, rsquare);
+ glWindow2.addGLEventListener(snapshotGLEventListener2);
glWindow2.addWindowListener(quitAdapter);
- Animator animator = new Animator();
+ final Animator animator = new Animator();
animator.add(glWindow1);
animator.add(glWindow2);
animator.start();
-
+
glWindow1.setVisible(true);
glWindow2.setVisible(true);
+ snapshotGLEventListener1.setMakeSnapshot();
+ snapshotGLEventListener2.setMakeSnapshot();
+
int s = 0;
- long t0 = System.currentTimeMillis();
+ final long t0 = System.currentTimeMillis();
long t1 = t0;
-
+
while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
if( ( t1 - t0 ) / period > s) {
s++;
System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- animator.pause();
-
- GLEventListener demo1 = glWindow1.removeGLEventListener(0);
- GLEventListener demo2 = glWindow2.removeGLEventListener(0);
-
- GLContext ctx1 = glWindow1.setContext(glWindow2.getContext());
- glWindow1.addGLEventListener(0, demo2);
-
- glWindow2.setContext(ctx1);
- glWindow2.addGLEventListener(0, demo1);
-
+ System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
+ System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
System.err.println(s+" - switch - END "+ ( t1 - t0 ));
-
- animator.resume();
+ snapshotGLEventListener1.setMakeSnapshot();
+ snapshotGLEventListener2.setMakeSnapshot();
}
Thread.sleep(100);
t1 = System.currentTimeMillis();
}
animator.stop();
+ // System.err.println("pre -del-w1: w1: "+glWindow1);
+ // System.err.println("pre -del-w1: w2: "+glWindow2);
glWindow1.destroy();
+ // System.err.println("post-del-w1: w1: "+glWindow1);
+ // System.err.println("post-del-w1: w2: "+glWindow2);
glWindow2.destroy();
-
+
}
// default timing for 2 switches
static long duration = 2200; // ms
static long period = 1000; // ms
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
} else if(args[i].equals("-period")) {
i++;
try {
period = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
}
/**
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
- System.err.println(stdin.readLine()); */
- org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitchNEWT.class.getName());
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch01NEWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02AWT.java
new file mode 100644
index 000000000..d9f2d0e18
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02AWT.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.awt.GLCanvas;
+
+import jogamp.nativewindow.awt.AWTMisc;
+
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Test re-association (switching) of GLContext/GLDrawables,
+ * from GLCanvas to an GLOffscreenAutoDrawable and back.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLContextDrawableSwitch02AWT extends GLContextDrawableSwitchBase0 {
+
+ @Override
+ public GLAutoDrawable createGLAutoDrawable(final QuitAdapter quitAdapter, final GLCapabilitiesImmutable caps, final int width, final int height) throws InterruptedException, InvocationTargetException {
+ final GLAutoDrawable glad;
+ if( caps.isOnscreen() ) {
+ final Frame frame = new Frame("Gears AWT Test");
+ Assert.assertNotNull(frame);
+
+ final GLCanvas glCanvas = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas);
+ final Dimension glc_sz = new Dimension(width, height);
+ glCanvas.setMinimumSize(glc_sz);
+ glCanvas.setPreferredSize(glc_sz);
+ glCanvas.setSize(glc_sz);
+ glad = glCanvas;
+
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas).addTo(frame);
+
+ frame.setLayout(new BorderLayout());
+ frame.add(glCanvas, BorderLayout.CENTER);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ frame.setVisible(true);
+ }});
+ } else {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ glad = factory.createOffscreenAutoDrawable(null, caps, null, width, height);
+ Assert.assertNotNull(glad);
+ }
+ return glad;
+ }
+
+ @Override
+ public void destroyGLAutoDrawable(final GLAutoDrawable glad) throws InterruptedException, InvocationTargetException {
+ if( glad.getChosenGLCapabilities().isOnscreen() ) {
+ final Frame frame = AWTMisc.getFrame((Component)glad);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final Frame _frame = frame;
+ _frame.dispose();
+ }});
+ } else {
+ glad.destroy();
+ }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-period")) {
+ i++;
+ try {
+ period = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-testUnsafe")) {
+ testEvenUnsafeSwapGLContext = true;
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch02AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02NEWT.java
new file mode 100644
index 000000000..c8a78d05f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02NEWT.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import com.jogamp.newt.opengl.GLWindow;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawableFactory;
+
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Test re-association (switching) of GLWindow /GLDrawables,
+ * from GLWindow/GLOffscreenAutoDrawable to an GLOffscreenAutoDrawable and back.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLContextDrawableSwitch02NEWT extends GLContextDrawableSwitchBase0 {
+ @Override
+ public GLAutoDrawable createGLAutoDrawable(final QuitAdapter quitAdapter, final GLCapabilitiesImmutable caps, final int width, final int height) throws InterruptedException, InvocationTargetException {
+ final GLAutoDrawable glad;
+ if( caps.isOnscreen() ) {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glad = glWindow;
+
+ if( null != quitAdapter ) {
+ glWindow.addWindowListener(quitAdapter);
+ }
+
+ glWindow.setVisible(true);
+ } else {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ glad = factory.createOffscreenAutoDrawable(null, caps, null, width, height);
+ Assert.assertNotNull(glad);
+ }
+ return glad;
+ }
+
+ @Override
+ public void destroyGLAutoDrawable(final GLAutoDrawable glad) throws InterruptedException, InvocationTargetException {
+ glad.destroy();
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-period")) {
+ i++;
+ try {
+ period = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-testUnsafe")) {
+ testEvenUnsafeSwapGLContext = true;
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch02NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java
new file mode 100644
index 000000000..822898e0b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java
@@ -0,0 +1,277 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
+
+import java.io.IOException;
+
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.event.WindowUpdateEvent;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLProfile;
+
+
+import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.util.Animator;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.GLEventListenerCounter;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Test re-association of GLContext/GLDrawables,
+ * here GLContext's survival of GLDrawable destruction
+ * and reuse w/ new or recreated GLDrawable.
+ * <p>
+ * Test utilizes {@link GLEventListenerState} for preserving the
+ * GLAutoDrawable state, i.e. GLContext, all GLEventListener
+ * and the GLAnimatorControl association.
+ * </p>
+ * <p>
+ * This test is using NEWT's plain Window w/ GLAutoDrawableDelegate.
+ * </p>
+ * <p>
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLContextDrawableSwitch10NEWT extends UITestCase {
+ // default period for 1 GLAD cycle
+ static long duration = 1000; // ms
+
+ static int width, height;
+
+ static GLCapabilities getCaps(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ @BeforeClass
+ public static void initClass() {
+ width = 256;
+ height = 256;
+ }
+
+ private GLAutoDrawable createGLAutoDrawableWithoutContext(final GLCapabilities caps, final int x, final int y, final int width, final int height, final WindowListener wl) throws InterruptedException {
+ final Window window = NewtFactory.createWindow(caps);
+ Assert.assertNotNull(window);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable drawable = factory.createGLDrawable(window);
+ Assert.assertNotNull(drawable);
+
+ drawable.setRealized(true);
+ Assert.assertTrue(drawable.isRealized());
+
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock();
+ window.destroy(); // destroys the actual window
+ }
+ };
+
+ window.setWindowDestroyNotifyAction( new Runnable() {
+ public void run() {
+ glad.windowDestroyNotifyOp();
+ } } );
+
+ // add basic window interaction
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowRepaint(final WindowUpdateEvent e) {
+ glad.windowRepaintOp();
+ }
+ @Override
+ public void windowResized(final WindowEvent e) {
+ glad.windowResizedOp(window.getSurfaceWidth(), window.getSurfaceHeight());
+ }
+ });
+ window.addWindowListener(wl);
+
+ return glad;
+ }
+
+ @Test(timeout=30000)
+ public void test01GLADDelegateGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLADDelegateImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void test02GLADDelegateGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLADDelegateImpl(reqGLCaps);
+ }
+
+ private void testGLADDelegateImpl(final GLCapabilities caps) throws InterruptedException {
+ final GLEventListenerCounter glelCounter = new GLEventListenerCounter();
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GLEventListenerState glls1;
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ final GLAutoDrawable glad1 = createGLAutoDrawableWithoutContext(caps, 64, 64, width, height, quitAdapter);
+ final GLContext context1 = glad1.createContext(null);
+ glad1.setContext(context1, true);
+ animator.add(glad1);
+
+ glad1.addGLEventListener(glelCounter);
+ glad1.addGLEventListener(new GearsES2(1));
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(context1, glad1.getContext());
+ Assert.assertEquals(3, glad1.getGLEventListenerCount());
+ Assert.assertEquals(context1.getGLReadDrawable(), glad1.getDelegatedDrawable());
+ Assert.assertEquals(context1.getGLDrawable(), glad1.getDelegatedDrawable());
+
+ // - dis-associate context from glad1
+ // - destroy glad1
+ glls1 = GLEventListenerState.moveFrom(glad1);
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(context1, glls1.context);
+ Assert.assertNull(context1.getGLReadDrawable());
+ Assert.assertNull(context1.getGLDrawable());
+ Assert.assertEquals(3, glls1.listenerCount());
+ Assert.assertEquals(true, glls1.isOwner());
+ Assert.assertEquals(null, glad1.getContext());
+ Assert.assertEquals(0, glad1.getGLEventListenerCount());
+
+ glad1.destroy();
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ final GLAutoDrawable glad2 = createGLAutoDrawableWithoutContext(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Assert.assertEquals(null, glad2.getContext());
+ Assert.assertEquals(0, glad2.getGLEventListenerCount());
+
+ glls1.moveTo(glad2);
+
+ Assert.assertTrue(glad2.isRealized());
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(glls1.context, glad2.getContext());
+ Assert.assertEquals(3, glad2.getGLEventListenerCount());
+ Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(false, glls1.isOwner());
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ glad2.destroy();
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(1, glelCounter.disposeCount);
+ }
+ animator.stop();
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch10NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java
new file mode 100644
index 000000000..f1c08c889
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java
@@ -0,0 +1,121 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.util.Animator;
+
+import com.jogamp.opengl.test.junit.util.GLEventListenerCounter;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Test re-association of GLContext/GLDrawables,
+ * here GLContext's survival of GLDrawable destruction
+ * and reuse w/ new or recreated GLDrawable.
+ * <p>
+ * Test utilizes {@link GLEventListenerState} for preserving the
+ * GLAutoDrawable state, i.e. GLContext, all GLEventListener
+ * and the GLAnimatorControl association.
+ * </p>
+ * <p>
+ * This test is using JOGL's NEWT GLWindow.
+ * </p>
+ * <p>
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLContextDrawableSwitch11NewtAWT extends GLContextDrawableSwitchBase1 {
+
+ @Test(timeout=30000)
+ public void test21GLWindowGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLWindowImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void test22GLWindowGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLWindowImpl(reqGLCaps);
+ }
+
+ private void testGLWindowImpl(final GLCapabilities caps) throws InterruptedException {
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GLEventListenerState glels[] = new GLEventListenerState[1];
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ testGLADOneLifecycle(null, caps, GLADType.GLWindow, width,
+ height, glelTracker,
+ snapshotGLEventListener,
+ null, glels, animator);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ testGLADOneLifecycle(null, caps, GLADType.GLWindow, width+100,
+ height+100, glelTracker,
+ snapshotGLEventListener,
+ glels[0], null, null);
+ }
+ animator.stop();
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch11NewtAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java
new file mode 100644
index 000000000..795e53768
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.util.Animator;
+
+import com.jogamp.opengl.test.junit.util.GLEventListenerCounter;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Test re-association of GLContext/GLDrawables,
+ * here GLContext's survival of GLDrawable destruction
+ * and reuse w/ new or recreated GLDrawable.
+ * <p>
+ * Test utilizes {@link GLEventListenerState} for preserving the
+ * GLAutoDrawable state, i.e. GLContext, all GLEventListener
+ * and the GLAnimatorControl association.
+ * </p>
+ * <p>
+ * This test is using JOGL's AWT GLCanvas
+ * </p>
+ * <p>
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLContextDrawableSwitch12AWT extends GLContextDrawableSwitchBase1 {
+
+ @Test(timeout=30000)
+ public void test01GLCanvasOnscreenGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLCanvasImpl(reqGLCaps, false);
+ }
+
+ @Test(timeout=30000)
+ public void test02GLCanvasOnscreenGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLCanvasImpl(reqGLCaps, false);
+ }
+
+ @Test(timeout=30000)
+ public void test11GLCanvasOffscreenGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLCanvasImpl(reqGLCaps, true);
+ }
+
+ @Test(timeout=30000)
+ public void test12GLCanvasOffscreenGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLCanvasImpl(reqGLCaps, true);
+ }
+
+ private void testGLCanvasImpl(final GLCapabilities caps, final boolean offscreenLayer) throws InterruptedException {
+ if( offscreenLayer ) {
+ if( !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("Platform doesn't support offscreen rendering.");
+ return;
+ }
+ } else {
+ if( JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("Platform requires offscreen rendering.");
+ return;
+ }
+ }
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GLEventListenerState glels[] = new GLEventListenerState[1];
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ testGLADOneLifecycle(null, caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width,
+ height, glelTracker,
+ snapshotGLEventListener,
+ null, glels, animator);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ testGLADOneLifecycle(null, caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width+100,
+ height+100, glelTracker,
+ snapshotGLEventListener,
+ glels[0], null, null);
+ }
+ animator.stop();
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch12AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch13Newt2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch13Newt2AWT.java
new file mode 100644
index 000000000..27d5ff80a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch13Newt2AWT.java
@@ -0,0 +1,195 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.GLRendererQuirks;
+import com.jogamp.opengl.util.Animator;
+
+import com.jogamp.opengl.test.junit.util.GLEventListenerCounter;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Test re-association of GLContext/GLDrawables,
+ * here GLContext's survival of GLDrawable destruction
+ * and reuse w/ new or recreated GLDrawable.
+ * <p>
+ * Test utilizes {@link GLEventListenerState} for preserving the
+ * GLAutoDrawable state, i.e. GLContext, all GLEventListener
+ * and the GLAnimatorControl association.
+ * </p>
+ * <p>
+ * This test moves the {@link GLEventListenerState} from a
+ * NEWT GLWindow before it's destruction to an AWT GLCanvas after it's creation
+ * and vice versa
+ * </p>
+ * <p>
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ * </p>
+ * <p>
+ * Interesting artifact w/ ATI proprietary driver is that the
+ * bug causing the quirk {@link GLRendererQuirks#DontCloseX11Display}
+ * also causes an XCB crash when reusing the X11 display connection
+ * from AWT -> NEWT. Pre-allocating the X11 Display and keeping it referenced
+ * to avoid such re-usage worksaround this problem.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLContextDrawableSwitch13Newt2AWT extends GLContextDrawableSwitchBase1 {
+
+ @Test(timeout=30000)
+ public void test01GLCanvasOnScrn2GLWindowGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow);
+ }
+
+ @Test(timeout=30000)
+ public void test02GLCanvasOnScrn2GLWindowGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow);
+ }
+
+ @Test(timeout=30000)
+ public void test11GLWindow2GLCanvasOnScrnGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ final Display dpy = NewtFactory.createDisplay(null);
+ final Screen screen = NewtFactory.createScreen(dpy, 0);
+ screen.addReference();
+ testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen);
+ screen.removeReference();
+ }
+
+ @Test(timeout=30000)
+ public void test12GLWindow2GLCanvasOnScrnGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ final Display dpy = NewtFactory.createDisplay(null);
+ final Screen screen = NewtFactory.createScreen(dpy, 0);
+ screen.addReference();
+ testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen);
+ screen.removeReference();
+ }
+
+ @Test(timeout=30000)
+ public void test21GLCanvasOffScrn2GLWindowGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow);
+ }
+
+ @Test(timeout=30000)
+ public void test22GLCanvasOffScrn2GLWindowGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow);
+ }
+
+ @Test(timeout=30000)
+ public void test31GLWindow2GLCanvasOffScrnGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ final Display dpy = NewtFactory.createDisplay(null);
+ final Screen screen = NewtFactory.createScreen(dpy, 0);
+ screen.addReference();
+ testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen);
+ screen.removeReference();
+ }
+
+ @Test(timeout=30000)
+ public void test32GLWindow2GLCanvasOffScrnGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ final Display dpy = NewtFactory.createDisplay(null);
+ final Screen screen = NewtFactory.createScreen(dpy, 0);
+ screen.addReference();
+ testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen);
+ screen.removeReference();
+ }
+
+ private void testGLCanvas2GLWindowImpl(final Screen screen, final GLCapabilities caps, final GLADType gladType1, final GLADType gladType2) throws InterruptedException {
+ if( !validateOnOffscreenLayer(gladType1, gladType2) ) {
+ return;
+ }
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GLEventListenerState glels[] = new GLEventListenerState[1];
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ testGLADOneLifecycle(screen, caps, gladType1, width,
+ height, glelTracker,
+ snapshotGLEventListener,
+ null, glels, animator);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ testGLADOneLifecycle(screen, caps, gladType2, width+100,
+ height+100, glelTracker,
+ snapshotGLEventListener,
+ glels[0], null, null);
+ }
+ animator.stop();
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine()); */
+ org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch13Newt2AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/ManualHiDPIBufferedImage01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/ManualHiDPIBufferedImage01AWT.java
new file mode 100644
index 000000000..6ccc9d2c4
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/ManualHiDPIBufferedImage01AWT.java
@@ -0,0 +1,71 @@
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Canvas;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+/**
+ * Manual test for BufferedImage behavior w/ OSX HiDPI pixel scale usage.
+ */
+public class ManualHiDPIBufferedImage01AWT {
+
+ static final int width = 200;
+ static final int height = 100;
+
+ public static void main(final String[] args) throws InterruptedException, InvocationTargetException {
+ final JFrame frame = new JFrame();
+
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ final Image image1 = getImage(getCheckBox("High-DPI (no)", false), width, height, 1);
+ final Image image2 = getImage(getCheckBox("High-DPI (yes)", true), width, height, 2);
+ System.err.println("Image1: "+image1);
+ System.err.println("Image2: "+image2);
+
+ @SuppressWarnings("serial")
+ final Canvas canvas = new Canvas() {
+ @Override
+ public void paint(final Graphics g) {
+ super.paint(g);
+ g.drawImage(image1, 0, 0, width, height, this);
+ g.drawImage(image2, 0, height + 5, width, height, this);
+ }
+ };
+ frame.getContentPane().add(getCheckBox("High-DPI (ref)", false), BorderLayout.NORTH);
+ frame.getContentPane().add(canvas, BorderLayout.CENTER);
+
+ frame.setBounds((1440-400)/2, 100, 400, 400);
+ frame.validate();
+ frame.setVisible(true);
+ }
+ });
+ }
+
+ static JCheckBox getCheckBox(final String text, final boolean selected) {
+ final JCheckBox checkBox = new JCheckBox(text);
+ checkBox.setSelected(selected);
+ checkBox.setSize(new Dimension(width, height));
+ return checkBox;
+ }
+
+ static Image getImage(final JComponent component, final int width, final int height, final int scale) {
+ final BufferedImage image = new BufferedImage(width*scale, height*scale, BufferedImage.TYPE_INT_ARGB);
+ final Graphics g = image.getGraphics();
+ ((Graphics2D) g).scale(scale, scale);
+ component.paint(g);
+ g.dispose();
+
+ return image;
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java
index e1048c2f8..1bfe313ff 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.awt;
import javax.media.opengl.GLProfile;
@@ -42,49 +42,52 @@ import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestAWT01GLn extends UITestCase {
@BeforeClass
public static void startup() {
System.out.println("GLProfile "+GLProfile.glAvailabilityToString());
}
- protected void runTestGL(GLCapabilities caps) throws InterruptedException {
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException {
final Frame frame = new Frame("Texture Test");
Assert.assertNotNull(frame);
-
+
final GLCanvas glCanvas = new GLCanvas(caps);
Assert.assertNotNull(glCanvas);
-
+
glCanvas.addGLEventListener(new GearsES2());
frame.add(glCanvas);
- // Revalidate size/layout.
- // Always validate if component added/removed.
- // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created.
- frame.setSize(512, 512);
- frame.validate();
-
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ // Revalidate size/layout.
+ // Always validate if component added/removed.
+ // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created.
+ frame.setSize(512, 512);
+ frame.validate();
+
frame.setVisible(true);
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
glCanvas.display(); // one in process display
- Animator animator = new Animator(glCanvas);
+ final Animator animator = new Animator(glCanvas);
animator.start();
Thread.sleep(500); // 500 ms
animator.stop();
-
+
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -92,7 +95,7 @@ public class TestAWT01GLn extends UITestCase {
frame.remove(glCanvas);
frame.dispose();
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
@@ -100,10 +103,10 @@ public class TestAWT01GLn extends UITestCase {
@Test
public void test01GLDefault() throws InterruptedException {
- GLProfile glp = GLProfile.getDefault();
+ final GLProfile glp = GLProfile.getDefault();
System.out.println("GLProfile Default: "+glp);
if(glp.isGL2ES2()) {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
runTestGL(caps);
} else {
System.out.println("not a GL2ES2 profile");
@@ -113,9 +116,9 @@ public class TestAWT01GLn extends UITestCase {
@Test
public void test02GL2() throws InterruptedException {
if(GLProfile.isAvailable(GLProfile.GL2)) {
- GLProfile glprofile = GLProfile.get(GLProfile.GL2);
+ final GLProfile glprofile = GLProfile.get(GLProfile.GL2);
System.out.println( "GLProfile GL2: " + glprofile );
- GLCapabilities caps = new GLCapabilities(glprofile);
+ final GLCapabilities caps = new GLCapabilities(glprofile);
runTestGL(caps);
} else {
System.out.println("GL2 n/a");
@@ -125,16 +128,16 @@ public class TestAWT01GLn extends UITestCase {
@Test
public void test02ES2() throws InterruptedException {
if(GLProfile.isAvailable(GLProfile.GLES2)) {
- GLProfile glprofile = GLProfile.get(GLProfile.GLES2);
+ final GLProfile glprofile = GLProfile.get(GLProfile.GLES2);
System.out.println( "GLProfile GLES2: " + glprofile );
- GLCapabilities caps = new GLCapabilities(glprofile);
+ final GLCapabilities caps = new GLCapabilities(glprofile);
runTestGL(caps);
} else {
System.out.println("GLES2 n/a");
}
}
-
- public static void main(String args[]) {
+
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestAWT01GLn.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java
index f83c8c03d..412209482 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,44 +20,42 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.awt;
import com.jogamp.opengl.test.junit.util.UITestCase;
-import javax.media.opengl.GLProfile;
import java.awt.*;
import java.awt.event.*;
import org.junit.Assert;
import org.junit.Assume;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.After;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestAWT02WindowClosing extends UITestCase {
static long durationPerTest = 200; // ms
@Test
public void test01WindowClosing() throws InterruptedException {
- Frame frame = new Frame();
- frame.setSize(500, 500);
- ClosingWindowAdapter closingWindowAdapter = new ClosingWindowAdapter(frame);
+ final Frame frame = new Frame();
+ final ClosingWindowAdapter closingWindowAdapter = new ClosingWindowAdapter(frame);
frame.addWindowListener(closingWindowAdapter);
- final Frame _frame = frame;
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- _frame.setVisible(true);
+ frame.setSize(500, 500);
+ frame.setVisible(true);
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
@@ -65,8 +63,8 @@ public class TestAWT02WindowClosing extends UITestCase {
Thread.sleep(durationPerTest);
if(!closingWindowAdapter.closingCalled) {
// programatically issue windowClosing
- Toolkit tk = Toolkit.getDefaultToolkit();
- EventQueue evtQ = tk.getSystemEventQueue();
+ final Toolkit tk = Toolkit.getDefaultToolkit();
+ final EventQueue evtQ = tk.getSystemEventQueue();
evtQ.postEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
Thread.sleep(200);
}
@@ -76,25 +74,25 @@ public class TestAWT02WindowClosing extends UITestCase {
static class ClosingWindowAdapter extends WindowAdapter {
boolean closingCalled = false;
Frame frame;
- public ClosingWindowAdapter(Frame frame) {
+ public ClosingWindowAdapter(final Frame frame) {
this.frame = frame;
}
- public void windowClosing(WindowEvent ev) {
+ public void windowClosing(final WindowEvent ev) {
System.out.println("windowClosing() called ..");
closingCalled = true;
frame.dispose();
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java
index aa7b4e06b..b074297e2 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,23 +20,23 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.awt;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-
import com.jogamp.opengl.test.junit.util.MiscUtils;
+import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Label;
@@ -46,15 +46,26 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.After;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestAWT03GLCanvasRecreate01 extends UITestCase {
- static long durationPerTest = 1000; // ms
+ static long durationPerTest = 500; // ms
+
+ final static int sizeEps = 64;
+ final static Dimension size1 = new Dimension(512, 512-sizeEps-1);
+ final static Dimension size2 = new Dimension(512+sizeEps+1+256, 512+256);
+ final static Dimension size3 = new Dimension(512-256, 512-sizeEps-1-256);
Frame frame1=null;
Frame frame2=null;
- GLCanvas glCanvas=null;
- Label label = null;
+ Frame frame3=null;
+ GLCanvas glComp=null;
+ Label label1 = null;
+ Label label2 = null;
+ Label label3 = null;
Animator animator = null;
@BeforeClass
@@ -64,115 +75,161 @@ public class TestAWT03GLCanvasRecreate01 extends UITestCase {
@Before
public void init() {
- glCanvas = new GLCanvas();
- Assert.assertNotNull(glCanvas);
- glCanvas.addGLEventListener(new GearsES2());
+ glComp = new GLCanvas();
+ Assert.assertNotNull(glComp);
+ glComp.addGLEventListener(new GearsES2());
- animator = new Animator(glCanvas);
+ animator = new Animator(glComp);
animator.start();
- label = new Label("No GLCanvas");
-
+ label1 = new Label("L1 - No GLCanvas");
+ label1.setMinimumSize(size1);
+ label1.setPreferredSize(size1);
frame1 = new Frame("Frame 1");
Assert.assertNotNull(frame1);
- frame1.add(label);
- frame1.setSize(512, 512);
+ frame1.add(label1);
frame1.setLocation(0, 0);
-
+
+ label2 = new Label("L2 - No GLCanvas");
+ label2.setMinimumSize(size2);
+ label2.setPreferredSize(size2);
frame2 = new Frame("Frame 2");
Assert.assertNotNull(frame2);
- frame2.add(label);
- frame2.setSize(512, 512);
- frame2.setLocation(512, 0);
+ frame2.add(label2);
+ frame2.setLocation(size1.width + size1.width/2, 0);
+
+ label3 = new Label("L3 - No GLCanvas");
+ label3.setMinimumSize(size3);
+ label3.setPreferredSize(size3);
+ frame3 = new Frame("Frame 3");
+ Assert.assertNotNull(frame3);
+ frame3.add(label3);
+ frame3.setLocation(0, size1.height + size1.height/2);
}
@After
public void release() {
Assert.assertNotNull(frame1);
Assert.assertNotNull(frame2);
- Assert.assertNotNull(glCanvas);
+ Assert.assertNotNull(glComp);
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- glCanvas.destroy();
+ glComp.destroy();
frame1.dispose();
frame2.dispose();
+ frame3.dispose();
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
frame1=null;
frame2=null;
- glCanvas=null;
+ frame3=null;
+ glComp=null;
animator.stop();
animator=null;
}
- private void addCanvas(final Frame frame) {
+ private void addCanvas(final Frame frame, final Label label, final Dimension size) {
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.remove(label);
- frame.add(glCanvas);
- frame.validate();
+ glComp.setPreferredSize(size);
+ glComp.setMinimumSize(size);
+ frame.add(glComp);
+ frame.pack();
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
}
- private void removeCanvas(final Frame frame) {
+ private void removeCanvas(final Frame frame, final Label label) {
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- frame.remove(glCanvas);
+ frame.remove(glComp);
frame.add(label);
- frame.validate();
+ frame.pack();
+ frame.repaint();
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
}
private void setVisible(final Frame frame, final boolean v) {
- try {
+ try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.pack();
frame.setVisible(v);
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
}
+ private void assertSize(final Dimension expSize) {
+ final int[] scale = { 1, 1 };
+ glComp.getNativeSurfaceScale(scale);
- @Test
- public void testAddRemove3Times() throws InterruptedException {
- setVisible(frame1, true);
- setVisible(frame2, true);
+ final Dimension hasSize = glComp.getSize(null);
- addCanvas(frame1);
- Thread.sleep(durationPerTest/4);
+ Assert.assertTrue("AWT Size.width mismatch: expected "+expSize+", has "+hasSize,
+ Math.abs(expSize.width-hasSize.width) <= sizeEps);
+ Assert.assertTrue("AWT Size.height mismatch: expected "+expSize+", has "+hasSize,
+ Math.abs(expSize.height-hasSize.height) <= sizeEps);
- removeCanvas(frame1);
- addCanvas(frame2);
- Thread.sleep(durationPerTest/4);
+ final int expSurfWidth = expSize.width * scale[0];
+ final int expSurfHeight = expSize.height * scale[0];
+ final int hasSurfWidth = glComp.getSurfaceWidth();
+ final int hasSurfHeight = glComp.getSurfaceHeight();
- removeCanvas(frame2);
- addCanvas(frame1);
- Thread.sleep(durationPerTest/4);
+ Assert.assertTrue("GL Size.width mismatch: expected "+expSurfWidth+", has "+hasSurfWidth,
+ Math.abs(expSurfWidth-hasSurfWidth) <= sizeEps);
+ Assert.assertTrue("GL Size.height mismatch: expected "+expSurfHeight+", has "+hasSurfHeight,
+ Math.abs(expSurfHeight-hasSurfHeight) <= sizeEps);
+ }
- removeCanvas(frame1);
- addCanvas(frame2);
- Thread.sleep(durationPerTest/4);
+ @Test
+ public void testAddRemove3Times() throws InterruptedException {
+ setVisible(frame1, true);
+ setVisible(frame2, true);
+ setVisible(frame3, true);
+
+ // Init Frame 1
+ addCanvas(frame1, label1, size1);
+ Thread.sleep(durationPerTest);
+ assertSize(size1);
+
+ // Frame 1 -> Frame 2
+ removeCanvas(frame1, label1);
+ addCanvas(frame2, label2, size2);
+ Thread.sleep(durationPerTest);
+ assertSize(size2);
+
+ // Frame 2 -> Frame 3
+ removeCanvas(frame2, label2);
+ addCanvas(frame3, label3, size3);
+ Thread.sleep(durationPerTest);
+ assertSize(size3);
+
+ // Frame 3 -> Frame 1
+ removeCanvas(frame3, label3);
+ addCanvas(frame1, label1, size1);
+ Thread.sleep(durationPerTest);
+ assertSize(size1);
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLJPanelRecreate01.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLJPanelRecreate01.java
new file mode 100644
index 000000000..b2d487784
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLJPanelRecreate01.java
@@ -0,0 +1,241 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestAWT03GLJPanelRecreate01 extends UITestCase {
+ static long durationPerTest = 500; // ms
+
+ final static int sizeEps = 64;
+ final static Dimension size1 = new Dimension(512, 512-sizeEps-1);
+ final static Dimension size2 = new Dimension(512+sizeEps+1+256, 512+256);
+ final static Dimension size3 = new Dimension(512-256, 512-sizeEps-1-256);
+
+ JFrame frame1=null;
+ JFrame frame2=null;
+ JFrame frame3=null;
+ GLJPanel glComp=null;
+ JLabel label1 = null;
+ JLabel label2 = null;
+ JLabel label3 = null;
+ Animator animator = null;
+
+ @BeforeClass
+ public static void startup() {
+ System.out.println("GLProfile "+GLProfile.glAvailabilityToString());
+ }
+
+ @Before
+ public void init() {
+ glComp = new GLJPanel();
+ Assert.assertNotNull(glComp);
+ glComp.addGLEventListener(new GearsES2());
+
+ animator = new Animator(glComp);
+ animator.start();
+
+ label1 = new JLabel("L1 - No GLJPanel");
+ label1.setMinimumSize(size1);
+ label1.setPreferredSize(size1);
+ frame1 = new JFrame("Frame 1");
+ Assert.assertNotNull(frame1);
+ frame1.add(label1);
+ frame1.setLocation(0, 0);
+
+ label2 = new JLabel("L2 - No GLJPanel");
+ label2.setMinimumSize(size2);
+ label2.setPreferredSize(size2);
+ frame2 = new JFrame("Frame 2");
+ Assert.assertNotNull(frame2);
+ frame2.add(label2);
+ frame2.setLocation(size1.width, 0);
+
+ label3 = new JLabel("L3 - No GLJPanel");
+ label3.setMinimumSize(size3);
+ label3.setPreferredSize(size3);
+ frame3 = new JFrame("Frame 3");
+ Assert.assertNotNull(frame3);
+ frame3.add(label3);
+ frame3.setLocation(0, size1.height);
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull(frame1);
+ Assert.assertNotNull(frame2);
+ Assert.assertNotNull(glComp);
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ glComp.destroy();
+ frame1.dispose();
+ frame2.dispose();
+ frame3.dispose();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ frame1=null;
+ frame2=null;
+ frame3=null;
+ glComp=null;
+
+ animator.stop();
+ animator=null;
+ }
+
+ private void addCanvas(final JFrame frame, final JLabel label, final Dimension size) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.getContentPane().remove(label);
+ glComp.setPreferredSize(size);
+ glComp.setMinimumSize(size);
+ frame.getContentPane().add(glComp, BorderLayout.CENTER);
+ frame.pack();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+
+ private void removeCanvas(final JFrame frame, final JLabel label) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.getContentPane().remove(glComp);
+ frame.getContentPane().add(label);
+ frame.pack();
+ frame.repaint();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+
+ private void setVisible(final JFrame frame, final boolean v) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ frame.setVisible(v);
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+
+ private void assertSize(final Dimension expSize) {
+ final int[] scale = { 1, 1 };
+ glComp.getNativeSurfaceScale(scale);
+
+ final Dimension hasSize = glComp.getSize(null);
+
+ Assert.assertTrue("AWT Size.width mismatch: expected "+expSize+", has "+hasSize,
+ Math.abs(expSize.width-hasSize.width) <= sizeEps);
+ Assert.assertTrue("AWT Size.height mismatch: expected "+expSize+", has "+hasSize,
+ Math.abs(expSize.height-hasSize.height) <= sizeEps);
+
+ final int expSurfWidth = expSize.width * scale[0];
+ final int expSurfHeight = expSize.height * scale[0];
+ final int hasSurfWidth = glComp.getSurfaceWidth();
+ final int hasSurfHeight = glComp.getSurfaceHeight();
+
+ Assert.assertTrue("GL Size.width mismatch: expected "+expSurfWidth+", has "+hasSurfWidth,
+ Math.abs(expSurfWidth-hasSurfWidth) <= sizeEps);
+ Assert.assertTrue("GL Size.height mismatch: expected "+expSurfHeight+", has "+hasSurfHeight,
+ Math.abs(expSurfHeight-hasSurfHeight) <= sizeEps);
+ }
+
+ @Test
+ public void testAddRemove3Times() throws InterruptedException {
+ setVisible(frame1, true);
+ setVisible(frame2, true);
+ setVisible(frame3, true);
+
+ // Init Frame 1
+ addCanvas(frame1, label1, size1);
+ Thread.sleep(durationPerTest);
+ assertSize(size1);
+
+ // Frame 1 -> Frame 2
+ removeCanvas(frame1, label1);
+ addCanvas(frame2, label2, size2);
+ Thread.sleep(durationPerTest);
+ assertSize(size2);
+
+ // Frame 2 -> Frame 3
+ removeCanvas(frame2, label2);
+ addCanvas(frame3, label3, size3);
+ Thread.sleep(durationPerTest);
+ assertSize(size3);
+
+ // Frame 3 -> Frame 1
+ removeCanvas(frame3, label3);
+ addCanvas(frame1, label1, size1);
+ Thread.sleep(durationPerTest);
+ assertSize(size1);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestAWT03GLJPanelRecreate01.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug460GLCanvasNPEAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug460GLCanvasNPEAWT.java
index c89ce43f7..8fbe680df 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug460GLCanvasNPEAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug460GLCanvasNPEAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.awt;
import javax.media.opengl.GLCapabilities;
@@ -34,21 +34,24 @@ import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestBug460GLCanvasNPEAWT {
- public static void main(String[] args) {
- TestBug460GLCanvasNPEAWT instance = new TestBug460GLCanvasNPEAWT();
+ public static void main(final String[] args) {
+ final TestBug460GLCanvasNPEAWT instance = new TestBug460GLCanvasNPEAWT();
instance.testIncompleteGLCanvasNPE();
}
@Test
public void testIncompleteGLCanvasNPE() {
- GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
- GLCanvas glc = new GLCanvas(caps);
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ final GLCanvas glc = new GLCanvas(caps);
// GLDrawableFactory factory = glc.getFactory(); // null ok: not realized
// GLCapabilitiesImmutable glci = glc.getChosenGLCapabilities(); -> NPE ok: .. not realized
- GLCapabilitiesImmutable glCapsRequested = glc.getRequestedGLCapabilities();
+ final GLCapabilitiesImmutable glCapsRequested = glc.getRequestedGLCapabilities();
System.out.println("ReqCaps: "+glCapsRequested);
System.out.println("GLCanvas: "+glc);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java
index 42949afef..c85c7467f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -28,9 +28,10 @@
package com.jogamp.opengl.test.junit.jogl.awt;
+import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
-
+
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
@@ -48,24 +49,30 @@ import javax.swing.JLabel;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
/**
- * Tests for bug 461, a failure of GLDrawableFactory.createGLPbuffer() on Windows
+ * Tests for bug 461, a failure of GLDrawableFactory.createOffscreenAutoDrawable(..) on Windows
* when the stencil buffer is turned on.
*
* @author Wade Walker (from code sample provided by Owen Dimond)
*/
-@SuppressWarnings("deprecation")
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GLEventListener {
+ static long durationPerTest = 500;
JFrame jframe;
GLOffscreenAutoDrawable offScreenBuffer;
-
- private void render(GLAutoDrawable drawable) {
- GL2 gl = drawable.getGL().getGL2();
+ AWTGLReadBufferUtil awtGLReadBufferUtil;
+
+ private void render(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
Assert.assertNotNull(gl);
- gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
// draw a triangle filling the window
gl.glBegin(GL.GL_TRIANGLES);
@@ -77,34 +84,46 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
gl.glVertex2d(1, -1);
gl.glEnd();
}
-
+
/* @Override */
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
+ awtGLReadBufferUtil = new AWTGLReadBufferUtil(drawable.getGLProfile(), false);
}
/* @Override */
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- }
-
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ }
+
/* @Override */
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
render(offScreenBuffer);
- BufferedImage outputImage = com.jogamp.opengl.util.awt.Screenshot.readToBufferedImage(200, 200, false);
+ final BufferedImage outputImage = awtGLReadBufferUtil.readPixelsToBufferedImage(drawable.getGL(), 0, 0, 200, 200, true /* awtOrientation */);
Assert.assertNotNull(outputImage);
- ImageIcon imageIcon = new ImageIcon(outputImage);
- JLabel imageLabel = new JLabel(imageIcon);
- jframe.getContentPane().add(imageLabel);
+ final ImageIcon imageIcon = new ImageIcon(outputImage);
+ final JLabel imageLabel = new JLabel(imageIcon);
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final Container cont = jframe.getContentPane();
+ cont.removeAll();
+ cont.add(imageLabel);
+ cont.validate();
+ }});
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
}
/* @Override */
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
try {
+ awtGLReadBufferUtil.dispose(drawable.getGL());
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
jframe.setVisible(false);
jframe.dispose();
}});
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
}
@@ -113,46 +132,55 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
public void testOffscreenSupersampling() throws InterruptedException, InvocationTargetException {
jframe = new JFrame("Offscreen Supersampling");
Assert.assertNotNull(jframe);
- jframe.setSize( 300, 300);
jframe.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
+ public void windowClosing(final WindowEvent e) {
System.exit(0);
}
});
- GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
Assert.assertNotNull(glp);
-
- GLDrawableFactory fac = GLDrawableFactory.getFactory(glp);
+
+ final GLDrawableFactory fac = GLDrawableFactory.getFactory(glp);
Assert.assertNotNull(fac);
-
- Assert.assertTrue( fac.canCreateGLPbuffer(GLProfile.getDefaultDevice()) );
-
- GLCapabilities glCap = new GLCapabilities(glp);
+
+ final GLCapabilities glCap = new GLCapabilities(glp);
Assert.assertNotNull(glCap);
-
- // COMMENTING OUT THIS LINE FIXES THE ISSUE.
+
+ // COMMENTING OUT THIS LINE FIXES THE ISSUE.
// Setting this in JOGL1 works. Thus this is a JOGL2 issue.
glCap.setSampleBuffers(true);
-
+ glCap.setNumSamples(4);
+
// Without line below, there is an error on Windows.
- glCap.setDoubleBuffered(false);
+ // glCap.setDoubleBuffered(false); // implicit double buffer -> MSAA + FBO
+
// Needed for drop shadows
glCap.setStencilBits(1);
//makes a new buffer
- offScreenBuffer = fac.createOffscreenAutoDrawable(GLProfile.getDefaultDevice(), glCap, null, 200, 200, null);
+ offScreenBuffer = fac.createOffscreenAutoDrawable(GLProfile.getDefaultDevice(), glCap, null, 200, 200);
Assert.assertNotNull(offScreenBuffer);
- offScreenBuffer.addGLEventListener(this);
- offScreenBuffer.display();
+ offScreenBuffer.addGLEventListener(this);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ jframe.setSize( 300, 300);
jframe.setVisible(true);
}});
+ offScreenBuffer.display(); // read from front buffer due to FBO+MSAA -> double-buffer
+ offScreenBuffer.display(); // now we have prev. image in front buffer to be read out
+
+ Thread.sleep(durationPerTest);
+
offScreenBuffer.destroy();
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+ }
+ }
org.junit.runner.JUnitCore.main(TestBug461FBOSupersamplingSwingAWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461PBufferSupersamplingSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461PBufferSupersamplingSwingAWT.java
index 5b7052c37..85bf2ceb3 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461PBufferSupersamplingSwingAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461PBufferSupersamplingSwingAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -30,7 +30,6 @@ package com.jogamp.opengl.test.junit.jogl.awt;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
-
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
@@ -40,7 +39,7 @@ import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLPbuffer;
+import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.media.opengl.GLProfile;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
@@ -48,24 +47,28 @@ import javax.swing.JLabel;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
/**
- * Tests for bug 461, a failure of GLDrawableFactory.createGLPbuffer() on Windows
+ * Tests for bug 461, a failure of PBuffer GLDrawableFactory.createOffscreenAutoDrawable(..) on Windows
* when the stencil buffer is turned on.
*
- * @author Wade Walker (from code sample provided by Owen Dimond)
+ * @author Wade Walker (from code sample provided by Owen Dimond), et al.
*/
-@SuppressWarnings("deprecation")
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestBug461PBufferSupersamplingSwingAWT extends UITestCase implements GLEventListener {
JFrame jframe;
- GLPbuffer offScreenBuffer;
-
- private void render(GLAutoDrawable drawable) {
- GL2 gl = drawable.getGL().getGL2();
+ GLOffscreenAutoDrawable offScreenBuffer;
+ AWTGLReadBufferUtil screenshot;
+
+ private void render(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
Assert.assertNotNull(gl);
- gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
// draw a triangle filling the window
gl.glBegin(GL.GL_TRIANGLES);
@@ -77,73 +80,84 @@ public class TestBug461PBufferSupersamplingSwingAWT extends UITestCase implement
gl.glVertex2d(1, -1);
gl.glEnd();
}
-
+
/* @Override */
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
+ screenshot = new AWTGLReadBufferUtil(drawable.getGLProfile(), false);
}
/* @Override */
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- }
-
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ }
+
/* @Override */
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
render(offScreenBuffer);
- BufferedImage outputImage = com.jogamp.opengl.util.awt.Screenshot.readToBufferedImage(200, 200, false);
+ final BufferedImage outputImage = screenshot.readPixelsToBufferedImage(drawable.getGL(), 0, 0, 200, 200, true /* awtOrientation */);
Assert.assertNotNull(outputImage);
- ImageIcon imageIcon = new ImageIcon(outputImage);
- JLabel imageLabel = new JLabel(imageIcon);
+ final ImageIcon imageIcon = new ImageIcon(outputImage);
+ final JLabel imageLabel = new JLabel(imageIcon);
jframe.getContentPane().add(imageLabel);
}
/* @Override */
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
+ screenshot.dispose(drawable.getGL());
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
jframe.setVisible(false);
jframe.dispose();
}});
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
}
@Test
- public void testOffscreenSupersampling() throws InterruptedException, InvocationTargetException {
+ public void test01DefaultOffscreenSupersampling() throws InterruptedException, InvocationTargetException {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ Assert.assertNotNull(glp);
+ final GLCapabilities glCap = new GLCapabilities(glp);
+ test(glCap);
+ }
+
+ @Test
+ public void test02PBufferOffscreenSupersampling() throws InterruptedException, InvocationTargetException {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ Assert.assertNotNull(glp);
+ final GLCapabilities glCap = new GLCapabilities(glp);
+ glCap.setPBuffer(true);
+ test(glCap);
+ }
+
+ void test(final GLCapabilities glCap) throws InterruptedException, InvocationTargetException {
jframe = new JFrame("Offscreen Supersampling");
Assert.assertNotNull(jframe);
jframe.setSize( 300, 300);
jframe.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
+ public void windowClosing(final WindowEvent e) {
System.exit(0);
}
});
- GLProfile glp = GLProfile.get(GLProfile.GL2);
- Assert.assertNotNull(glp);
-
- GLDrawableFactory fac = GLDrawableFactory.getFactory(glp);
+ final GLDrawableFactory fac = GLDrawableFactory.getFactory(glCap.getGLProfile());
Assert.assertNotNull(fac);
-
- Assert.assertTrue( fac.canCreateGLPbuffer(GLProfile.getDefaultDevice()) );
-
- GLCapabilities glCap = new GLCapabilities(glp);
- Assert.assertNotNull(glCap);
-
- // COMMENTING OUT THIS LINE FIXES THE ISSUE.
+
+ // COMMENTING OUT THIS LINE FIXES THE ISSUE.
// Setting this in JOGL1 works. Thus this is a JOGL2 issue.
glCap.setSampleBuffers(true);
-
+ glCap.setNumSamples(4);
+
// Without line below, there is an error on Windows.
glCap.setDoubleBuffered(false);
// Needed for drop shadows
glCap.setStencilBits(1);
//makes a new buffer
- offScreenBuffer = fac.createGLPbuffer(GLProfile.getDefaultDevice(), glCap, null, 200, 200, null);
+ offScreenBuffer = fac.createOffscreenAutoDrawable(null, glCap, null, 200, 200);
Assert.assertNotNull(offScreenBuffer);
- offScreenBuffer.addGLEventListener(this);
+ offScreenBuffer.addGLEventListener(this);
offScreenBuffer.display();
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -152,7 +166,7 @@ public class TestBug461PBufferSupersamplingSwingAWT extends UITestCase implement
offScreenBuffer.destroy();
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestBug461PBufferSupersamplingSwingAWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug551AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug551AWT.java
index e68ddb4c1..8b9934310 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug551AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug551AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.awt;
import java.lang.reflect.InvocationTargetException;
@@ -46,6 +46,8 @@ import java.awt.Window;
import javax.swing.JFrame;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import static org.junit.Assume.*;
import static javax.swing.SwingUtilities.*;
@@ -54,39 +56,40 @@ import static javax.swing.SwingUtilities.*;
* Tests context creation + display on various kinds of Window implementations.
* @author Michael Bien, et. al.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestBug551AWT extends UITestCase {
static void checkGraphicsEnvironment() {
Rectangle virtualBounds = new Rectangle();
- GraphicsEnvironment ge =GraphicsEnvironment.getLocalGraphicsEnvironment();
- GraphicsDevice[] gs = ge.getScreenDevices();
+ final GraphicsEnvironment ge =GraphicsEnvironment.getLocalGraphicsEnvironment();
+ final GraphicsDevice[] gs = ge.getScreenDevices();
- //write graphics devices to log
+ //write graphics devices to log
System.err.println("number of graphics devices " + gs.length);
for(int i =0 ; i < gs.length; i++) {
System.err.println(gs[i].toString());
}
//check for bounds
- for (int j = 0; j < gs.length; j++) {
- GraphicsDevice gd = gs[j];
- GraphicsConfiguration[] gc = gd.getConfigurations();
+ for (int j = 0; j < gs.length; j++) {
+ final GraphicsDevice gd = gs[j];
+ final GraphicsConfiguration[] gc = gd.getConfigurations();
for (int i=0; i < gc.length; i++) {
System.err.println("graphics configuration for device " + j + " is: " + gc[i].getBounds());
virtualBounds = virtualBounds.union(gc[i].getBounds());
- }
+ }
}
}
-
+
protected void runTestGL() throws InterruptedException, InvocationTargetException {
final Window window = new JFrame(this.getSimpleTestName(" - "));
final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
-
+
// final array as mutable container hack
final GLCanvas[] glCanvas = new GLCanvas[1];
- Runnable test = new Runnable() {
+ final Runnable test = new Runnable() {
public void run() {
glCanvas[0] = new GLCanvas(caps);
glCanvas[0].addGLEventListener(new GearsES2());
@@ -103,13 +106,13 @@ public class TestBug551AWT extends UITestCase {
}
};
- Runnable cleanup = new Runnable() {
+ final Runnable cleanup = new Runnable() {
public void run() {
System.out.println("cleaning up...");
window.setVisible(false);
try {
window.removeAll();
- } catch (Throwable t) {
+ } catch (final Throwable t) {
assumeNoException(t);
t.printStackTrace();
}
@@ -121,7 +124,7 @@ public class TestBug551AWT extends UITestCase {
// AWT / Swing on EDT..
invokeAndWait(test);
- Animator animator = new Animator(glCanvas[0]);
+ final Animator animator = new Animator(glCanvas[0]);
animator.start();
Thread.sleep(1000);
animator.stop();
@@ -141,7 +144,7 @@ public class TestBug551AWT extends UITestCase {
runTestGL();
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestBug551AWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java
new file mode 100644
index 000000000..5fb4433c9
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java
@@ -0,0 +1,170 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.Dimension;
+import java.awt.Window;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Test realize GLCanvas and setVisible(true) AWT-Frames on AWT-EDT and on current thread (non AWT-EDT)
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug572AWT extends UITestCase {
+ static long durationPerTest = 150; // ms
+
+ static class Cleanup implements Runnable {
+ Window window;
+
+ public Cleanup(final Window w) {
+ window = w;
+ }
+
+ public void run() {
+ System.err.println("cleaning up...");
+ window.setVisible(false);
+ try {
+ window.removeAll();
+ } catch (final Throwable t) {
+ Assume.assumeNoException(t);
+ t.printStackTrace();
+ }
+ window.dispose();
+ }
+ }
+
+ private void testRealizeGLCanvas(final boolean onAWTEDT, final boolean setFrameSize) throws InterruptedException, InvocationTargetException {
+ final Window window = new JFrame(this.getSimpleTestName(" - "));
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ final GLCanvas glCanvas = new GLCanvas(caps);
+ final SnapshotGLEventListener snapshooter = new SnapshotGLEventListener();
+ snapshooter.setMakeSnapshotAlways(true);
+ glCanvas.addGLEventListener(new GearsES2());
+ glCanvas.addGLEventListener(snapshooter);
+ window.add(glCanvas);
+
+ final Runnable realizeAction = new Runnable() {
+ @Override
+ public void run() {
+ // Revalidate size/layout.
+ // Always validate if component added/removed.
+ // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created.
+ if( setFrameSize ) {
+ window.setSize(512, 512);
+ window.validate();
+ } else {
+ final Dimension size = new Dimension(512, 512);
+ glCanvas.setPreferredSize(size);
+ glCanvas.setMinimumSize(size);
+ window.pack();
+ }
+ window.setVisible(true);
+ } };
+ if( onAWTEDT ) {
+ // trigger realization on AWT-EDT, otherwise it won't immediatly ..
+ SwingUtilities.invokeAndWait( realizeAction );
+ } else {
+ // trigger realization on non AWT-EDT, realization will happen at a later time ..
+ realizeAction.run();
+
+ // Wait until it's displayable after issuing initial setVisible(true) on current thread (non AWT-EDT)!
+ Assert.assertTrue("GLCanvas didn't become visible", AWTRobotUtil.waitForVisible(glCanvas, true));
+ Assert.assertTrue("GLCanvas didn't become realized", AWTRobotUtil.waitForRealized(glCanvas, true)); // implies displayable
+ }
+
+ System.err.println("XXXX-0 "+glCanvas.getDelegatedDrawable().isRealized()+", "+glCanvas);
+
+ Assert.assertTrue("GLCanvas didn't become displayable", glCanvas.isDisplayable());
+ Assert.assertTrue("GLCanvas didn't become realized", glCanvas.isRealized());
+
+ // The AWT-EDT reshape/repaint events happen offthread later ..
+ System.err.println("XXXX-1 reshapeCount "+snapshooter.getReshapeCount());
+ System.err.println("XXXX-1 displayCount "+snapshooter.getDisplayCount());
+
+ // Wait unitl AWT-EDT has issued reshape/repaint
+ for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER &&
+ ( 0 == snapshooter.getReshapeCount() || 0 == snapshooter.getDisplayCount() );
+ wait++) {
+ Thread.sleep(AWTRobotUtil.TIME_SLICE);
+ }
+ System.err.println("XXXX-2 reshapeCount "+snapshooter.getReshapeCount());
+ System.err.println("XXXX-2 displayCount "+snapshooter.getDisplayCount());
+
+ Assert.assertTrue("GLCanvas didn't reshape", snapshooter.getReshapeCount()>0);
+ Assert.assertTrue("GLCanvas didn't display", snapshooter.getDisplayCount()>0);
+
+ Thread.sleep(durationPerTest);
+
+ // After initial 'setVisible(true)' all AWT manipulation needs to be done
+ // via the AWT EDT, according to the AWT spec.
+
+ // AWT / Swing on EDT..
+ SwingUtilities.invokeAndWait(new Cleanup(window));
+ }
+
+ @Test(timeout = 10000) // 10s timeout
+ public void test01RealizeGLCanvasOnAWTEDTUseFrameSize() throws InterruptedException, InvocationTargetException {
+ testRealizeGLCanvas(true, true);
+ }
+
+ @Test(timeout = 10000) // 10s timeout
+ public void test02RealizeGLCanvasOnAWTEDTUseGLCanvasSize() throws InterruptedException, InvocationTargetException {
+ testRealizeGLCanvas(true, false);
+ }
+
+ @Test(timeout = 10000) // 10s timeout
+ public void test11RealizeGLCanvasOnMainTUseFrameSize() throws InterruptedException, InvocationTargetException {
+ testRealizeGLCanvas(false, true);
+ }
+
+ @Test(timeout = 10000) // 10s timeout
+ public void test12RealizeGLCanvasOnMainTUseGLCanvasSize() throws InterruptedException, InvocationTargetException {
+ testRealizeGLCanvas(false, false);
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestBug572AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug611AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug611AWT.java
index b6a7639bd..e64df6687 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug611AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug611AWT.java
@@ -7,30 +7,33 @@ import java.io.File;
import javax.media.opengl.GLProfile;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.os.Platform;
import com.jogamp.opengl.test.junit.util.UITestCase;
/**
* As reported in Bug 611, on Windows XP is a performance issue:
- * After JOGL initialization there seems to be a huge time lag
+ * After JOGL initialization there seems to be a huge time lag
* when trying to open the Desktop folder.
* <p>
* Test disabled since showing the Desktop folder will
- * disturb the 'desktop' .. if there is another way to show
+ * disturb the 'desktop' .. if there is another way to show
* the performance bug, pls do so.
* </p>
* <p>
* Since Windows XP is out of life .. we may not care ..
- * </p>
+ * </p>
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestBug611AWT extends UITestCase {
-
+
@Test
public void test00() {
- // make junit happy
+ // make junit happy
}
-
+
// @Test
public void test01() {
try {
@@ -43,17 +46,17 @@ public class TestBug611AWT extends UITestCase {
desktop = null;
}
if(null != desktop) {
- String home = System.getProperty("user.home");
+ final String home = System.getProperty("user.home");
File homeFolder = null;
if(null != home) {
{
- File tst = new File(home + "/Desktop");
+ final File tst = new File(home + "/Desktop");
if( tst.canRead() ) {
homeFolder = tst;
}
}
if(null == homeFolder) {
- File tst = new File(home);
+ final File tst = new File(home);
if( tst.canRead() ) {
homeFolder = tst;
}
@@ -70,12 +73,12 @@ public class TestBug611AWT extends UITestCase {
desktop.open(homeFolder);
}
}
- } catch(Exception ex) {
+ } catch(final Exception ex) {
ex.printStackTrace();
}
}
-
- public static void main(String args[]) {
+
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestBug611AWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug642JSplitPaneMixHwLw01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug642JSplitPaneMixHwLw01AWT.java
new file mode 100644
index 000000000..fffffcb96
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug642JSplitPaneMixHwLw01AWT.java
@@ -0,0 +1,199 @@
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.BorderLayout;
+// import java.awt.Canvas;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.GraphicsConfiguration;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.io.IOException;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.WindowConstants;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.FPSAnimator;
+
+/**
+ * Documenting Bug 642 (related to Bug 586)
+ *
+ * <p>
+ * JSplitPane cannot mix hw/lw components, only if setting property '-Dsun.awt.disableMixing=true'.
+ * </p>
+ * See Bug 586
+ * See git commit '8df12ca151dfc577c90b485d4ebfe491b88e55aa'.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug642JSplitPaneMixHwLw01AWT extends UITestCase {
+ static long durationPerTest = 500;
+
+ static {
+ // too late: use at cmd-line '-Dsun.awt.disableMixing=true' works
+ // System.setProperty("sun.awt.disableMixing", "true");
+ }
+
+ /**
+ * Doesn't work either ..
+ */
+ @SuppressWarnings("serial")
+ public static class TransparentJScrollPane extends JScrollPane {
+
+ public TransparentJScrollPane(final Component view) {
+ super(view);
+
+ setOpaque(false);
+
+ try {
+ ReflectionUtil.callStaticMethod(
+ "com.sun.awt.AWTUtilities", "setComponentMixingCutoutShape",
+ new Class<?>[] { Component.class, Shape.class },
+ new Object[] { this, new Rectangle() } ,
+ GraphicsConfiguration.class.getClassLoader());
+ System.err.println("com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(..) passed");
+ } catch (final RuntimeException re) {
+ System.err.println("com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(..) failed: "+re.getMessage());
+ }
+ }
+
+ @Override
+ public void setOpaque(final boolean isOpaque) {
+ }
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final boolean useGLJPanel, final boolean useContainer) throws InterruptedException {
+ final String typeS = useGLJPanel ? "LW" : "HW";
+ final JFrame frame = new JFrame("Mix Hw/Lw Swing - Canvas "+typeS);
+ Assert.assertNotNull(frame);
+
+ final Dimension f_sz = new Dimension(824,568);
+ // final Dimension f_sz = new Dimension(600,400);
+ // final Dimension glc_sz = new Dimension(500,600);
+
+ frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+
+ final Component glComp;
+ final GLAutoDrawable glad;
+ if(useGLJPanel) {
+ final GLJPanel glJPanel = new GLJPanel(new GLCapabilities(GLProfile.getDefault()));
+ Assert.assertNotNull(glJPanel);
+ glJPanel.addGLEventListener(new GearsES2());
+ glComp = glJPanel;
+ glad = glJPanel;
+ } else {
+ final GLCanvas glCanvas = new GLCanvas(new GLCapabilities(GLProfile.getDefault()));
+ Assert.assertNotNull(glCanvas);
+ glCanvas.addGLEventListener(new GearsES2());
+ if( useContainer ) {
+ final Container cont = new Container();
+ cont.setLayout(new BorderLayout());
+ cont.add(glCanvas, BorderLayout.CENTER);
+ glComp = cont;
+ } else {
+ glComp = glCanvas;
+ }
+ glad = glCanvas;
+ }
+
+ final Container contentPane = frame.getContentPane();
+
+ final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+ splitPane.setResizeWeight(0.5d);
+ splitPane.setLeftComponent(glComp);
+ // splitPane.setLeftComponent(new JPanel());
+ // splitPane.setLeftComponent(new Canvas());
+ splitPane.setRightComponent(new JPanel());
+ contentPane.add(splitPane, BorderLayout.CENTER);
+
+ final GLAnimatorControl animator = useGLJPanel ? new FPSAnimator(glad, 60) : new Animator(glad);
+ animator.start();
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setPreferredSize(f_sz);
+ frame.setSize(f_sz.width+1, f_sz.height+1); // trick to force pack() to work!
+ frame.pack();
+ frame.setVisible(true);
+ // however, Hw/Lw mixing is still a problem ..
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+
+ animator.setUpdateFPSFrames(60, System.err);
+ Thread.sleep(durationPerTest);
+
+ animator.stop();
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ frame.dispose();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+
+ @Test
+ public void test01JSplitPaneWithHwGLCanvasPlain() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, false, false);
+ }
+
+ @Test
+ public void test02JSplitPaneWithHwGLCanvasContainer() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, false, true);
+ }
+
+ @Test
+ public void test03JSplitPaneWithLwGLJPanel() throws InterruptedException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, true, false);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine());
+ */
+ System.out.println("durationPerTest: "+durationPerTest);
+ final String tstname = TestBug642JSplitPaneMixHwLw01AWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java
new file mode 100644
index 000000000..36c1e11b2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java
@@ -0,0 +1,287 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug664GLCanvasSetVisibleSwingAWT extends UITestCase {
+ static long durationPerTest = 500;
+ static boolean shallUseOffscreenFBOLayer = false;
+ static boolean shallUseOffscreenPBufferLayer = false;
+ static GLProfile glp;
+ static int width, height;
+ static boolean waitForKey = false;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ Assert.assertNotNull(glp);
+ width = 640;
+ height = 480;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected JPanel create(final JFrame[] top, final int width, final int height, final int num)
+ throws InterruptedException, InvocationTargetException
+ {
+ final JPanel[] jPanel = new JPanel[] { null };
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ jPanel[0] = new JPanel();
+ jPanel[0].setLayout(new BorderLayout());
+
+ final JFrame jFrame1 = new JFrame("JFrame #"+num);
+ // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ jFrame1.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
+ jFrame1.getContentPane().add(jPanel[0]);
+ jFrame1.setSize(width, height);
+
+ top[0] = jFrame1;
+ } } );
+ return jPanel[0];
+ }
+
+ protected void add(final Container cont, final Component comp, final JFrame jFrame)
+ throws InterruptedException, InvocationTargetException
+ {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ cont.add(comp, BorderLayout.CENTER);
+ jFrame.pack();
+ jFrame.validate();
+ } } );
+ }
+
+ protected void dispose(final GLCanvas glc)
+ throws InterruptedException, InvocationTargetException
+ {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ glc.destroy();
+ } } );
+ }
+
+ protected void setFrameVisible(final JFrame jFrame, final boolean visible) throws InterruptedException, InvocationTargetException {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ jFrame.setVisible(visible);
+ } } ) ;
+ }
+
+ protected void setComponentVisible(final Component comp, final boolean visible) throws InterruptedException, InvocationTargetException {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ comp.setVisible(visible);
+ } } ) ;
+ }
+
+ protected void dispose(final JFrame jFrame) throws InterruptedException, InvocationTargetException {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ jFrame.dispose();
+ } } ) ;
+ }
+
+ private volatile int frameCount = 0;
+
+ protected void runTestGL(final boolean onscreen, final GLCapabilities caps)
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+
+ for(int i=0; i<1; i++) {
+ final Animator anim = new Animator();
+ final GLCanvas glc = new GLCanvas(caps);
+ Assert.assertNotNull(glc);
+ anim.add(glc);
+ if( !onscreen ) {
+ glc.setShallUseOffscreenLayer(true);
+ }
+ final Dimension glc_sz = new Dimension(width, height);
+ glc.setMinimumSize(glc_sz);
+ glc.setPreferredSize(glc_sz);
+ glc.setSize(glc_sz);
+ glc.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {}
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ frameCount++;
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ });
+ final GearsES2 gears = new GearsES2(1);
+ gears.setVerbose(false);
+ glc.addGLEventListener(gears);
+
+ final JFrame[] top = new JFrame[] { null };
+ final Container glcCont = create(top, width, height, i);
+ add(glcCont, glc, top[0]);
+
+ System.err.println("XXXX Visible Part 1/3");
+ frameCount = 0;
+ setFrameVisible(top[0], true);
+ Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true));
+ Assert.assertTrue("Component didn't become realized", AWTRobotUtil.waitForRealized(glc, true));
+
+ anim.setUpdateFPSFrames(60, System.err);
+ anim.start();
+ anim.resetFPSCounter();
+
+ while( anim.getTotalFPSDuration() < durationPerTest ) {
+ Thread.sleep(60);
+ }
+
+ System.err.println("XXXXX Invisible Part 2/3");
+ setComponentVisible(glc, false);
+ Assert.assertTrue("Component didn't become invisible", AWTRobotUtil.waitForVisible(glc, false));
+ final int frameCountT0 = frameCount;
+ anim.resetFPSCounter();
+
+ while( anim.getTotalFPSDuration() < durationPerTest ) {
+ Thread.sleep(60);
+ }
+
+ final int frameCountT1 = frameCount;
+ System.err.println("GLCanvas invisible frame count: Before "+frameCountT0+", after "+frameCountT1);
+ Assert.assertTrue("GLCanvas rendered more that 4 times while being invisible, before "+frameCountT0+", after "+frameCountT1,
+ 4 >= frameCountT1 - frameCountT0);
+
+ System.err.println("XXXX Visible Part 3/3");
+ setComponentVisible(glc, true);
+ Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true));
+ anim.resetFPSCounter();
+
+ while( anim.getTotalFPSDuration() < durationPerTest ) {
+ Thread.sleep(60);
+ }
+
+ System.err.println("GLCanvas isOffscreenLayerSurfaceEnabled: "+glc.isOffscreenLayerSurfaceEnabled()+": "+glc.getChosenGLCapabilities());
+
+ dispose(top[0]);
+ }
+ }
+
+ @Test
+ public void test01Onscreen()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( shallUseOffscreenFBOLayer || shallUseOffscreenPBufferLayer || JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("Offscreen test requested or platform requires it.");
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ if(shallUseOffscreenPBufferLayer) {
+ caps.setPBuffer(true);
+ caps.setOnscreen(true); // simulate normal behavior ..
+ }
+ runTestGL(true, caps);
+ }
+
+ @Test
+ public void test02Offscreen()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("Platform doesn't support offscreen test.");
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ if(shallUseOffscreenPBufferLayer) {
+ caps.setPBuffer(true);
+ caps.setOnscreen(true); // simulate normal behavior ..
+ }
+ runTestGL(false, caps);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ durationPerTest = Long.parseLong(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-layeredFBO")) {
+ shallUseOffscreenFBOLayer = true;
+ } else if(args[i].equals("-layeredPBuffer")) {
+ shallUseOffscreenPBufferLayer = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ System.err.println("waitForKey "+waitForKey);
+
+ System.err.println("shallUseOffscreenFBOLayer "+shallUseOffscreenFBOLayer);
+ System.err.println("shallUseOffscreenPBufferLayer "+shallUseOffscreenPBufferLayer);
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
+ org.junit.runner.JUnitCore.main(TestBug664GLCanvasSetVisibleSwingAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug675BeansInDesignTimeAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug675BeansInDesignTimeAWT.java
new file mode 100644
index 000000000..12ebe88d3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug675BeansInDesignTimeAWT.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Window;
+import java.beans.Beans;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug675BeansInDesignTimeAWT extends UITestCase {
+ static boolean waitForKey = false;
+ static long durationPerTest = 200;
+
+ @Test
+ public void test01() throws InterruptedException, InvocationTargetException {
+ Beans.setDesignTime(true);
+
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ final GLCanvas glCanvas = new GLCanvas(caps);
+ final Dimension preferredGLSize = new Dimension(400,200);
+ glCanvas.setPreferredSize(preferredGLSize);
+ glCanvas.setMinimumSize(preferredGLSize);
+ glCanvas.setSize(preferredGLSize);
+
+ glCanvas.addGLEventListener(new GearsES2());
+
+ final Window window = new JFrame(this.getSimpleTestName(" - "));
+ window.setLayout(new BorderLayout());
+ window.add(glCanvas, BorderLayout.CENTER);
+
+ // trigger realization on AWT-EDT, otherwise it won't immediatly ..
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ window.pack();
+ window.validate();
+ window.setVisible(true);
+ }
+ } );
+
+ // Immediately displayable after issuing initial setVisible(true) on AWT-EDT!
+ Assert.assertTrue("GLCanvas didn't become displayable", glCanvas.isDisplayable());
+ if( !Beans.isDesignTime() ) {
+ Assert.assertTrue("GLCanvas didn't become realized", glCanvas.isRealized());
+ }
+
+ Thread.sleep(durationPerTest);
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ window.dispose();
+ }
+ } );
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
+ org.junit.runner.JUnitCore.main(TestBug675BeansInDesignTimeAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java
new file mode 100644
index 000000000..f169a27a9
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java
@@ -0,0 +1,262 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Moving GLCanvas between 2 AWT JFrame
+ * <p>
+ * Validates bugs:
+ * <ul>
+ * <li>Bug 816: OSX CALayer Positioning Bug</li>
+ * <li>Bug 729: OSX CALayer shall honor the Component's visibility state</li>
+ * <li>Bug 849: AWT GLAutoDrawables (JAWTWindow) shall honor it's parent visibility state</li>
+ * <li>Bug 878: JAWTWindow's HierarchyListener doesn't set component visible (again) on 'addNotify(..)' - GLCanvas in JtabbedPane disappear</li>
+ * <li>Bug 889: GLCanvas disappear when moves between two JFrame</li>
+ * </ul>
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug816GLCanvasFrameHoppingB849B889AWT extends UITestCase {
+ static long durationPerTest = 500*4; // ms
+ static boolean manual = false;
+
+ @Test
+ public void test01AllVisible() throws InterruptedException, InvocationTargetException {
+ test(false);
+ }
+
+ @Test
+ public void test02VisibleWithCanvas() throws InterruptedException, InvocationTargetException {
+ test(true);
+ }
+
+ private void test(final boolean onlyVisibleWithCanvas) throws InterruptedException, InvocationTargetException {
+ final JFrame frame1 = new JFrame("Bug889 #1");
+ final JPanel panel1 = new javax.swing.JPanel();
+ panel1.setLayout(new BorderLayout());
+ panel1.setSize(new java.awt.Dimension(640, 480));
+ frame1.setContentPane(panel1);
+ frame1.setSize(640, 480);
+ frame1.setLocation(64, 64);
+
+ final JFrame frame2 = new JFrame("Bug889 #2");
+ final JPanel panel2 = new javax.swing.JPanel();
+ panel2.setLayout(new BorderLayout());
+ panel2.setSize(new java.awt.Dimension(640, 480));
+ frame2.setContentPane(panel2);
+ frame2.setSize(640, 480);
+ frame2.setLocation(800, 64);
+
+ final GLProfile profile = GLProfile.get(GLProfile.GL2ES2);
+ final GLCapabilities glCapabilities = new GLCapabilities(profile);
+ final GLCanvas glCanvas = new GLCanvas(glCapabilities);
+ glCanvas.setSize(new java.awt.Dimension(640, 480));
+ glCanvas.addGLEventListener(new GearsES2(1));
+ panel1.add(glCanvas, BorderLayout.CENTER);
+
+ final JButton bMoveP1toP2 = new JButton("Move to Panel2");
+ bMoveP1toP2.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(final java.awt.event.ActionEvent evt) {
+ System.err.println("XXXX Move P1 -> P2 - START");
+ dumpGLCanvasStats(glCanvas);
+ panel2.add(glCanvas, BorderLayout.CENTER);
+ if( onlyVisibleWithCanvas ) {
+ frame1.setVisible(false);
+ frame2.setVisible(true);
+ frame2.toFront();
+ } else {
+ frame1.validate();
+ frame2.validate();
+ }
+ dumpGLCanvasStats(glCanvas);
+ System.err.println("XXXX Move P1 -> P2 - END");
+ }
+ });
+ panel1.add(bMoveP1toP2, BorderLayout.NORTH);
+
+ final JButton bMoveP2toP1 = new JButton("Move to Panel1");
+ bMoveP2toP1.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ System.err.println("XXXX Move P2 -> P1 - START");
+ dumpGLCanvasStats(glCanvas);
+ panel1.add(glCanvas, BorderLayout.CENTER);
+ if( onlyVisibleWithCanvas ) {
+ frame2.setVisible(false);
+ frame1.setVisible(true);
+ frame1.toFront();
+ } else {
+ frame2.validate();
+ frame1.validate();
+ }
+ dumpGLCanvasStats(glCanvas);
+ System.err.println("XXXX Move P2 -> P1 - END");
+ }
+ });
+ panel2.add(bMoveP2toP1, BorderLayout.NORTH);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ // frame1.pack();
+ System.err.println("XXX SetVisible ON XXX GLCanvas on Panel1("+id(panel1)+")");
+ if( onlyVisibleWithCanvas ) {
+ frame1.setVisible(true);
+ } else {
+ frame1.setVisible(true);
+ frame2.setVisible(true);
+ }
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true));
+ dumpGLCanvasStats(glCanvas);
+
+ if(manual) {
+ for(long w=durationPerTest; w>0; w-=100) {
+ Thread.sleep(100);
+ }
+ } else {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ System.err.println("XXXX Add GLCanvas Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START");
+ dumpGLCanvasStats(glCanvas);
+ panel2.add(glCanvas, BorderLayout.CENTER);
+ if( onlyVisibleWithCanvas ) {
+ frame1.setVisible(false);
+ frame2.setVisible(true);
+ frame2.toFront();
+ } else {
+ frame1.validate();
+ frame2.validate();
+ }
+ dumpGLCanvasStats(glCanvas);
+ }});
+ Thread.sleep(durationPerTest/4);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ System.err.println("XXXX Add GLCanvas Panel2("+id(panel2)+") -> Panel1("+id(panel1)+" START");
+ dumpGLCanvasStats(glCanvas);
+ panel1.add(glCanvas, BorderLayout.CENTER);
+ if( onlyVisibleWithCanvas ) {
+ frame2.setVisible(false);
+ frame1.setVisible(true);
+ frame1.toFront();
+ } else {
+ frame2.validate();
+ frame1.validate();
+ }
+ dumpGLCanvasStats(glCanvas);
+ }});
+ Thread.sleep(durationPerTest/4);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ System.err.println("XXXX Add GLCanvas Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START");
+ dumpGLCanvasStats(glCanvas);
+ panel2.add(glCanvas, BorderLayout.CENTER);
+ if( onlyVisibleWithCanvas ) {
+ frame1.setVisible(false);
+ frame2.setVisible(true);
+ frame2.toFront();
+ } else {
+ frame1.validate();
+ frame2.validate();
+ }
+ dumpGLCanvasStats(glCanvas);
+ }});
+ Thread.sleep(durationPerTest/4);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ System.err.println("XXXX Add GLCanvas Panel2("+id(panel2)+") -> Panel1("+id(panel1)+" START");
+ dumpGLCanvasStats(glCanvas);
+ panel1.add(glCanvas, BorderLayout.CENTER);
+ if( onlyVisibleWithCanvas ) {
+ frame2.setVisible(false);
+ frame1.setVisible(true);
+ frame1.toFront();
+ } else {
+ frame2.validate();
+ frame1.validate();
+ }
+ dumpGLCanvasStats(glCanvas);
+ }});
+ Thread.sleep(durationPerTest/4);
+ }
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ System.err.println("XXX SetVisible OFF XXX");
+ frame1.dispose();
+ frame2.dispose();
+ } });
+ }
+
+ private static String id(final Object obj) { return "0x"+Integer.toHexString(obj.hashCode()); }
+
+ static void dumpGLCanvasStats(final GLCanvas glCanvas) {
+ System.err.println("XXXX GLCanvas: comp "+glCanvas+", visible "+glCanvas.isVisible()+", showing "+glCanvas.isShowing()+
+ ", displayable "+glCanvas.isDisplayable()+", "+glCanvas.getSurfaceWidth()+"x"+glCanvas.getSurfaceHeight());
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
+ } else if(args[i].equals("-manual")) {
+ manual = true;
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestBug816GLCanvasFrameHoppingB849B889AWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java
new file mode 100644
index 000000000..efb7119e4
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java
@@ -0,0 +1,194 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.BorderLayout;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * AWT JFrame w/ JTabbedPanel, Moving GLCanvas between it's tabs while selecting.
+ * <p>
+ * Validates bugs:
+ * <ul>
+ * <li>Bug 816: OSX CALayer Positioning Bug</li>
+ * <li>Bug 729: OSX CALayer shall honor the Component's visibility state</li>
+ * <li>Bug 849: AWT GLAutoDrawables (JAWTWindow) shall honor it's parent visibility state</li>
+ * <li>Bug 878: JAWTWindow's HierarchyListener doesn't set component visible (again) on 'addNotify(..)' - GLCanvas in JtabbedPane disappear</li>
+ * </ul>
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug816JTabbedPanelVisibilityB849B878AWT extends UITestCase {
+
+ static long durationPerTest = 500*6; // ms
+ static boolean manual = false;
+
+ @Test
+ public void test() throws InterruptedException, InvocationTargetException {
+ final JFrame frame = new JFrame("TestBug816OSXCALayerPos03dBug878AWT");
+
+ final JPanel panel1 = new javax.swing.JPanel();
+ final JPanel panel2 = new javax.swing.JPanel();
+ final JPanel panel3 = new javax.swing.JPanel();
+
+ panel1.setLayout(new BorderLayout());
+ panel2.setLayout(new BorderLayout());
+
+ final GLProfile profile = GLProfile.get(GLProfile.GL2ES2);
+ final GLCapabilities glCapabilities = new GLCapabilities(profile);
+ final GLCanvas glCanvas = new GLCanvas(glCapabilities);
+ glCanvas.setSize(new java.awt.Dimension(640, 480));
+ glCanvas.addGLEventListener(new GearsES2(1));
+ panel1.add(glCanvas, BorderLayout.CENTER);
+ panel3.add(new JLabel("A label to cover the canvas"), BorderLayout.CENTER);
+
+ final JTabbedPane tabbedPanel = new JTabbedPane();
+ tabbedPanel.addTab("tab1", panel1); // glcanvas
+ tabbedPanel.addTab("tab2", panel2); // glcanvas
+ tabbedPanel.addTab("tab3", panel3); // text
+
+ tabbedPanel.addChangeListener(new javax.swing.event.ChangeListener() {
+ @Override
+ public void stateChanged(final javax.swing.event.ChangeEvent evt) {
+ if (tabbedPanel.getSelectedIndex() == 0) {
+ System.err.println("XXXX Add GLCanvas Panel2("+id(panel2)+" -> Panel1("+id(panel1)+") START");
+ dumpGLCanvasStats(glCanvas);
+ panel1.add(glCanvas, BorderLayout.CENTER);
+ dumpGLCanvasStats(glCanvas);
+ } else if (tabbedPanel.getSelectedIndex() == 1) {
+ System.err.println("XXXX Add GLCanvas Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START");
+ dumpGLCanvasStats(glCanvas);
+ panel2.add(glCanvas, BorderLayout.CENTER);
+ dumpGLCanvasStats(glCanvas);
+ } else {
+ System.err.println("XXXX NOP");
+ dumpGLCanvasStats(glCanvas);
+ }
+ }
+ });
+
+ frame.setContentPane(tabbedPanel);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ System.err.println("XXX SetVisible ON XXX GLCanvas on Panel1("+id(panel1)+")");
+ frame.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true));
+ dumpGLCanvasStats(glCanvas);
+
+ if(manual) {
+ for(long w=durationPerTest; w>0; w-=100) {
+ Thread.sleep(100);
+ }
+ } else {
+ Thread.sleep(durationPerTest/6);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ System.err.println("XXXX Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START");
+ tabbedPanel.setSelectedIndex(1);
+ }});
+
+ Thread.sleep(durationPerTest/6);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ System.err.println("XXXX Panel2("+id(panel2)+") -> Panel3("+id(panel3)+" START");
+ tabbedPanel.setSelectedIndex(2);
+ }});
+
+ Thread.sleep(durationPerTest/6);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ System.err.println("XXXX Panel3("+id(panel3)+") -> Panel1("+id(panel1)+" START");
+ tabbedPanel.setSelectedIndex(0);
+ }});
+
+ // one loop done
+
+ Thread.sleep(durationPerTest/6);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ System.err.println("XXXX Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START");
+ tabbedPanel.setSelectedIndex(1);
+ }});
+
+ Thread.sleep(durationPerTest/6);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ System.err.println("XXXX Panel2("+id(panel2)+") -> Panel1("+id(panel1)+" START");
+ tabbedPanel.setSelectedIndex(0);
+ }});
+
+ Thread.sleep(durationPerTest/6);
+ }
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ System.err.println("XXX SetVisible OFF XXX");
+ frame.dispose();
+ } });
+ }
+
+ private static String id(final Object obj) { return "0x"+Integer.toHexString(obj.hashCode()); }
+
+ static void dumpGLCanvasStats(final GLCanvas glCanvas) {
+ System.err.println("XXXX GLCanvas: comp "+glCanvas+", visible "+glCanvas.isVisible()+", showing "+glCanvas.isShowing()+
+ ", displayable "+glCanvas.isDisplayable()+", "+glCanvas.getSurfaceWidth()+"x"+glCanvas.getSurfaceHeight());
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
+ } else if(args[i].equals("-manual")) {
+ manual = true;
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestBug816JTabbedPanelVisibilityB849B878AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java
new file mode 100644
index 000000000..83cde8f2a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java
@@ -0,0 +1,475 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import javax.media.opengl.*;
+
+import com.jogamp.opengl.util.Animator;
+
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.BoundedRangeModel;
+import javax.swing.BoxLayout;
+import javax.swing.JFrame;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.ScrollPaneConstants;
+
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Bug 816: OSX CALayer Positioning Bug.
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug816OSXCALayerPos01AWT extends UITestCase {
+ public enum FrameLayout { None, Flow, DoubleBorderCenterSurrounded, Box, Split };
+
+ static long duration = 1600; // ms
+ static final int width = 640, height = 480;
+
+ static boolean forceES2 = false;
+ static boolean forceGL3 = false;
+ static int swapInterval = 1;
+ static java.awt.Dimension rwsize = new Dimension(800, 600);
+
+ static void setComponentSize(final Frame frame, final Component comp1, final java.awt.Dimension new_sz1, final Component comp2, final java.awt.Dimension new_sz2) {
+ try {
+ AWTEDTExecutor.singleton.invoke(true /* wait */, new Runnable() {
+ public void run() {
+ comp1.setMinimumSize(new_sz1);
+ comp1.setPreferredSize(new_sz1);
+ comp1.setSize(new_sz1);
+ if( null != comp2 ) {
+ comp2.setMinimumSize(new_sz2);
+ comp2.setPreferredSize(new_sz2);
+ comp2.setSize(new_sz2);
+ }
+ if( null != frame ) {
+ frame.pack();
+ }
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+ static void setFrameSize(final Frame frame, final boolean frameLayout, final java.awt.Dimension new_sz) {
+ try {
+ AWTEDTExecutor.singleton.invoke(true /* wait */, new Runnable() {
+ public void run() {
+ frame.setSize(new_sz);
+ if( frameLayout ) {
+ frame.validate();
+ }
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final FrameLayout frameLayout, final boolean twoCanvas, final boolean resizeByComp) throws InterruptedException, InvocationTargetException {
+ final JFrame frame = new JFrame("Bug816: "+this.getTestMethodName());
+ Assert.assertNotNull(frame);
+ final Container framePane = frame.getContentPane();
+
+ final GLCanvas glCanvas1 = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas1);
+ final GLCanvas glCanvas2;
+ if( twoCanvas ) {
+ glCanvas2 = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas2);
+ } else {
+ glCanvas2 = null;
+ }
+
+ final Dimension glcDim = new Dimension(width/2, height);
+ final Dimension frameDim = new Dimension(twoCanvas ? width + 64: width/2 + 64, height + 64);
+
+ setComponentSize(null, glCanvas1, glcDim, glCanvas2, glcDim);
+
+ switch( frameLayout) {
+ case None: {
+ framePane.add(glCanvas1);
+ }
+ break;
+ case Flow: {
+ final Container c = new Container();
+ c.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
+ c.add(glCanvas1);
+ if( twoCanvas ) {
+ c.add(glCanvas2);
+ }
+ framePane.add(c);
+ }
+ break;
+ case DoubleBorderCenterSurrounded: {
+ final Container c = new Container();
+ c.setLayout(new BorderLayout());
+ c.add(new Button("north"), BorderLayout.NORTH);
+ c.add(new Button("south"), BorderLayout.SOUTH);
+ c.add(new Button("east"), BorderLayout.EAST);
+ c.add(new Button("west"), BorderLayout.WEST);
+ if( twoCanvas ) {
+ final Container c2 = new Container();
+ c2.setLayout(new GridLayout(1, 2));
+ c2.add(glCanvas1);
+ c2.add(glCanvas2);
+ c.add(c2, BorderLayout.CENTER);
+ } else {
+ c.add(glCanvas1, BorderLayout.CENTER);
+ }
+ framePane.setLayout(new BorderLayout());
+ framePane.add(new Button("NORTH"), BorderLayout.NORTH);
+ framePane.add(new Button("SOUTH"), BorderLayout.SOUTH);
+ framePane.add(new Button("EAST"), BorderLayout.EAST);
+ framePane.add(new Button("WEST"), BorderLayout.WEST);
+ framePane.add(c, BorderLayout.CENTER);
+ }
+ break;
+ case Box: {
+ final Container c = new Container();
+ c.setLayout(new BoxLayout(c, BoxLayout.X_AXIS));
+ c.add(glCanvas1);
+ if( twoCanvas ) {
+ c.add(glCanvas2);
+ }
+ framePane.add(c);
+ }
+ break;
+ case Split: {
+ final Dimension sbDim = new Dimension(16, 16);
+ final JScrollPane vsp = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
+ {
+ final JScrollBar vsb = vsp.getVerticalScrollBar();
+ vsb.setPreferredSize(sbDim);
+ final BoundedRangeModel model = vsb.getModel();
+ model.setMinimum(0);
+ model.setMaximum(100);
+ model.setValue(50);
+ model.setExtent(1);
+ vsb.setEnabled(true);
+ }
+ final JScrollPane hsp = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
+ {
+ final JScrollBar hsb = hsp.getHorizontalScrollBar();
+ hsb.setPreferredSize(sbDim);
+ final BoundedRangeModel model = hsb.getModel();
+ model.setMinimum(0);
+ model.setMaximum(100);
+ model.setValue(50);
+ model.setExtent(1);
+ hsb.setEnabled(true);
+ }
+ final JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true,
+ twoCanvas ? glCanvas2 : vsp, glCanvas1 );
+ horizontalSplitPane.setResizeWeight(0.5);
+ final JSplitPane verticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+ true, horizontalSplitPane, hsp);
+ verticalSplitPane.setResizeWeight(0.5);
+ framePane.add(verticalSplitPane);
+ }
+ break;
+ }
+ final GearsES2 demo1 = new GearsES2(swapInterval);
+ glCanvas1.addGLEventListener(demo1);
+ if( twoCanvas ) {
+ final RedSquareES2 demo2 = new RedSquareES2(swapInterval);
+ glCanvas2.addGLEventListener(demo2);
+ }
+
+ final Animator animator = new Animator();
+ animator.add(glCanvas1);
+ if( twoCanvas ) {
+ animator.add(glCanvas2);
+ }
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas1).addTo(frame);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ if( resizeByComp ) {
+ frame.pack();
+ } else {
+ setFrameSize(frame, true, frameDim);
+ }
+ frame.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true));
+ if( twoCanvas ) {
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas2, true));
+ }
+
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+
+ System.err.println("canvas1 pos/siz: "+glCanvas1.getX()+"/"+glCanvas1.getY()+" "+glCanvas1.getSurfaceWidth()+"x"+glCanvas1.getSurfaceHeight());
+ if( twoCanvas ) {
+ System.err.println("canvas2 pos/siz: "+glCanvas2.getX()+"/"+glCanvas2.getY()+" "+glCanvas2.getSurfaceWidth()+"x"+glCanvas2.getSurfaceHeight());
+ }
+
+ Thread.sleep(Math.max(1000, duration/2));
+ if( null != rwsize ) {
+ final Dimension compRSizeHalf = new Dimension(rwsize.width/2, rwsize.height);
+ final Dimension frameRSizeHalf = new Dimension(twoCanvas ? rwsize.width + 64: rwsize.width/2 + 64, rwsize.height + 64);
+ if( resizeByComp ) {
+ setComponentSize(frame, glCanvas1, compRSizeHalf, glCanvas2, compRSizeHalf);
+ } else {
+ setFrameSize(frame, true, frameRSizeHalf);
+ }
+ System.err.println("resize canvas1 pos/siz: "+glCanvas1.getX()+"/"+glCanvas1.getY()+" "+glCanvas1.getSurfaceWidth()+"x"+glCanvas1.getSurfaceHeight());
+ if( twoCanvas ) {
+ System.err.println("resize canvas2 pos/siz: "+glCanvas2.getX()+"/"+glCanvas2.getY()+" "+glCanvas2.getSurfaceWidth()+"x"+glCanvas2.getSurfaceHeight());
+ }
+ }
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glCanvas1);
+ if( twoCanvas ) {
+ Assert.assertNotNull(glCanvas2);
+ } else {
+ Assert.assertNull(glCanvas2);
+ }
+
+ Assert.assertNotNull(animator);
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.remove(glCanvas1);
+ if( twoCanvas ) {
+ frame.remove(glCanvas2);
+ }
+ frame.dispose();
+ }});
+ }
+
+ static GLProfile getGLP() {
+ return GLProfile.getMaxProgrammableCore(true);
+ }
+
+ @Test
+ public void test00_Compo_None_One() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 0 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.None, false /* twoCanvas */, true /* resizeByComp */);
+ }
+
+ @Test
+ public void test01_Compo_Flow_One() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 1 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Flow, false /* twoCanvas */, true /* resizeByComp */);
+ }
+
+ @Test
+ public void test02_Compo_DblBrd_One() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 2 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.DoubleBorderCenterSurrounded, false /* twoCanvas */, true /* resizeByComp */);
+ }
+
+ @Test
+ public void test03_Compo_Box_One() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 3 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Box, false /* twoCanvas */, true /* resizeByComp */);
+ }
+
+ @Test
+ public void test04_Compo_Split_One() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 4 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Split, false /* twoCanvas */, true /* resizeByComp */);
+ }
+
+ @Test
+ public void test05_Compo_Flow_Two() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 5 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Flow, true/* twoCanvas */, true /* resizeByComp */);
+ }
+
+ @Test
+ public void test06_Compo_DblBrd_Two() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 6 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.DoubleBorderCenterSurrounded, true/* twoCanvas */, true /* resizeByComp */);
+ }
+
+ @Test
+ public void test07_Compo_Box_Two() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 7 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Box, true/* twoCanvas */, true /* resizeByComp */);
+ }
+
+ @Test
+ public void test08_Compo_Split_Two() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 8 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Split, true/* twoCanvas */, true /* resizeByComp */);
+ }
+
+ @Test
+ public void test10_Frame_None_One() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 10 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.None, false /* twoCanvas */, false /* resizeByComp */);
+ }
+
+ @Test
+ public void test11_Frame_Flow_One() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 11 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Flow, false /* twoCanvas */, false /* resizeByComp */);
+ }
+
+ @Test
+ public void test12_Frame_DblBrd_One() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 12 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.DoubleBorderCenterSurrounded, false /* twoCanvas */, false /* resizeByComp */);
+ }
+
+ @Test
+ public void test13_Frame_Box_One() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 13 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Box, false /* twoCanvas */, false /* resizeByComp */);
+ }
+
+ @Test
+ public void test14_Frame_Split_One() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 14) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Split, false /* twoCanvas */, false /* resizeByComp */);
+ }
+
+ @Test
+ public void test15_Frame_Flow_Two() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 15 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Flow, true/* twoCanvas */, false /* resizeByComp */);
+ }
+
+ @Test
+ public void test16_Frame_DblBrd_Two() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 16 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.DoubleBorderCenterSurrounded, true/* twoCanvas */, false /* resizeByComp */);
+ }
+
+ @Test
+ public void test17_Frame_Box_Two() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 17 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Box, true/* twoCanvas */, false /* resizeByComp */);
+ }
+
+ @Test
+ public void test18_Frame_Split_Two() throws InterruptedException, InvocationTargetException {
+ if( testNum != -1 && testNum != 18 ) { return ; }
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+ runTestGL(caps, FrameLayout.Split, true/* twoCanvas */, false /* resizeByComp */);
+ }
+
+ static int testNum = -1;
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-test")) {
+ i++;
+ testNum = MiscUtils.atoi(args[i], 0);
+ } else if(args[i].equals("-noresize")) {
+ rwsize = null;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ }
+ }
+
+ System.err.println("resize "+rwsize);
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("swapInterval "+swapInterval);
+
+ org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos01AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java
new file mode 100644
index 000000000..fa9ea7198
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java
@@ -0,0 +1,152 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import javax.media.opengl.*;
+
+import com.jogamp.opengl.util.Animator;
+
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JFrame;
+import javax.swing.JRootPane;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Bug 816: OSX CALayer Positioning Bug - Swing JFrame w/ 2 JRootPanes and 2 JSplitPanes
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ * <p>
+ * See also {@link com.jogamp.opengl.test.junit.jogl.demos.es2.awt.Bug816AppletOSXCALayerPos03b}
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug816OSXCALayerPos02AWT extends UITestCase {
+ static long duration = 1600; // ms
+ static int width=640, height=480;
+
+ @Test
+ public void test() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+
+ final JFrame frame = new JFrame("TestBug816OSXCALayerPos02AWT");
+ Assert.assertNotNull(frame);
+
+ final GLCanvas glCanvas1 = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas1);
+ glCanvas1.addGLEventListener(new GearsES2(1));
+
+ final Animator animator = new Animator();
+ animator.add(glCanvas1);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas1).addTo(frame);
+
+ // Build a GUI where the canvas 3D is located at top right of the frame
+ // and can be resized with split panes dividers
+ final JSplitPane verticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+ true, new JScrollPane(), glCanvas1);
+ verticalSplitPane.setResizeWeight(0.5);
+ final JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+ true, new JScrollPane(), verticalSplitPane);
+ horizontalSplitPane.setResizeWeight(0.5);
+ final JRootPane intermediateRootPane = new JRootPane();
+ intermediateRootPane.setContentPane(horizontalSplitPane);
+ frame.add(intermediateRootPane);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(width, height);
+ frame.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true));
+
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glCanvas1);
+
+ Assert.assertNotNull(animator);
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.remove(glCanvas1);
+ frame.dispose();
+ }});
+ }
+
+ static GLProfile getGLP() {
+ return GLProfile.getMaxProgrammableCore(true);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+
+ org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos02AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java
new file mode 100644
index 000000000..74d18ce9b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java
@@ -0,0 +1,166 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Checkbox;
+import java.awt.Frame;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * AWT Frame BorderLayout w/ Checkbox North, GLCanvas Center.
+ * <p>
+ * Checkbox toggles GLCanvas visibility state.
+ * </p>
+ * <p>
+ * Validates bugs:
+ * <ul>
+ * <li>Bug 816: OSX CALayer Positioning Bug</li>
+ * <li>Bug 729: OSX CALayer shall honor the Component's visibility state</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug816OSXCALayerPos03aB729AWT extends UITestCase {
+ static long duration = 1600; // ms
+ static int width=640, height=480;
+
+ @Test
+ public void test() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+
+ final Frame frame = new Frame("TestBug816OSXCALayerPos03aAWT");
+ Assert.assertNotNull(frame);
+
+ final GLCanvas glCanvas1 = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas1);
+ glCanvas1.addGLEventListener(new GearsES2(1));
+
+ final Animator animator = new Animator();
+ animator.add(glCanvas1);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas1).addTo(frame);
+
+ // Create a check box that hides / shows canvas
+ final Checkbox checkbox = new Checkbox("Visible canvas", true);
+ checkbox.addItemListener(new ItemListener() {
+ public void itemStateChanged(final ItemEvent ev) {
+ final boolean visible = checkbox.getState();
+ System.err.println("XXXX Canvas setVisible "+visible);
+ glCanvas1.setVisible(visible);
+ System.err.println("XXXX Canvas visible: "+glCanvas1.isVisible());
+ if( glCanvas1.isVisible() ) {
+ frame.validate(); // take care of resized frame while hidden
+ }
+ }
+ });
+
+ // Build a GUI that displays canvas and check box
+ frame.setLayout(new BorderLayout());
+ frame.add(glCanvas1, BorderLayout.CENTER);
+ frame.add(checkbox, BorderLayout.NORTH);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(width, height);
+ frame.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true));
+
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glCanvas1);
+
+ Assert.assertNotNull(animator);
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.remove(glCanvas1);
+ frame.dispose();
+ }});
+ }
+
+ static GLProfile getGLP() {
+ return GLProfile.getMaxProgrammableCore(true);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+
+ org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos03aB729AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java
new file mode 100644
index 000000000..9a9a7fce7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Checkbox;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.Panel;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * AWT Frame BorderLayout w/ Checkbox North, Panel.GLCanvas Center.
+ * <p>
+ * Checkbox toggles GLCanvas's parent panel's visibility state.
+ * </p>
+ * <p>
+ * Validates bugs:
+ * <ul>
+ * <li>Bug 816: OSX CALayer Positioning Bug</li>
+ * <li>Bug 729: OSX CALayer shall honor the Component's visibility state</li>
+ * <li>Bug 849: AWT GLAutoDrawables (JAWTWindow) shall honor it's parent visibility state</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug816OSXCALayerPos03bB849AWT extends UITestCase {
+ static long duration = 1600; // ms
+ static int width=640, height=480;
+
+ @Test
+ public void test() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+
+ final Frame frame = new Frame("TestBug816OSXCALayerPos03bAWT");
+ Assert.assertNotNull(frame);
+
+ final GLCanvas glCanvas1 = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas1);
+ glCanvas1.addGLEventListener(new GearsES2(1));
+ // Put it in a panel
+ final Panel panel = new Panel(new GridLayout(1, 1));
+ panel.add(glCanvas1);
+
+ final Animator animator = new Animator();
+ animator.add(glCanvas1);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas1).addTo(frame);
+
+ // Create a check box that hides / shows canvas
+ final Checkbox checkbox = new Checkbox("Visible canvas", true);
+ checkbox.addItemListener(new ItemListener() {
+ public void itemStateChanged(final ItemEvent ev) {
+ final boolean visible = checkbox.getState();
+ System.err.println("XXXX Panel setVisible "+visible);
+ panel.setVisible(visible);
+ System.err.println("XXXX Visible: [panel "+panel.isVisible()+", canvas "+glCanvas1.isVisible()+"]; Displayable: [panel "+panel.isDisplayable()+", canvas "+glCanvas1.isDisplayable()+"]");
+ if( panel.isVisible() ) {
+ frame.validate(); // take care of resized frame while hidden
+ }
+ }
+ });
+
+ // Build a GUI that displays canvas and check box
+ frame.setLayout(new BorderLayout());
+ frame.add(panel, BorderLayout.CENTER);
+ frame.add(checkbox, BorderLayout.NORTH);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(width, height);
+ frame.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true));
+
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glCanvas1);
+
+ Assert.assertNotNull(animator);
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.remove(panel);
+ frame.dispose();
+ }});
+ }
+
+ static GLProfile getGLP() {
+ return GLProfile.getMaxProgrammableCore(true);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+
+ org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos03bB849AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java
new file mode 100644
index 000000000..afdf6fbcb
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java
@@ -0,0 +1,174 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.GridLayout;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JCheckBox;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * AWT JFrame BorderLayout w/ Checkbox North, JPanel.GLCanvas Center.
+ * <p>
+ * Checkbox toggles GLCanvas's parent jpanel's visibility state.
+ * </p>
+ * <p>
+ * Validates bugs:
+ * <ul>
+ * <li>Bug 816: OSX CALayer Positioning Bug</li>
+ * <li>Bug 729: OSX CALayer shall honor the Component's visibility state</li>
+ * <li>Bug 849: AWT GLAutoDrawables (JAWTWindow) shall honor it's parent visibility state</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug816OSXCALayerPos03cB849AWT extends UITestCase {
+ static long duration = 1600; // ms
+ static int width=640, height=480;
+
+ @Test
+ public void test() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+
+ final JFrame frame = new JFrame("TestBug816OSXCALayerPos03cAWT");
+ Assert.assertNotNull(frame);
+ final Container framePane = frame.getContentPane();
+
+ final GLCanvas glCanvas1 = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas1);
+ glCanvas1.addGLEventListener(new GearsES2(1));
+ // Put it in a panel
+ final JPanel panel = new JPanel(new GridLayout(1, 1));
+ panel.add(glCanvas1);
+
+ final Animator animator = new Animator();
+ animator.add(glCanvas1);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas1).addTo(frame);
+
+ // Create a check box that hides / shows canvas
+ final JCheckBox checkbox = new JCheckBox("Visible canvas", true);
+ checkbox.addItemListener(new ItemListener() {
+ public void itemStateChanged(final ItemEvent ev) {
+ final boolean visible = checkbox.getSelectedObjects()!=null;
+ System.err.println("XXXX Panel setVisible "+visible);
+ panel.setVisible(visible);
+ System.err.println("XXXX Visible: [panel "+panel.isVisible()+", canvas "+glCanvas1.isVisible()+"]; Displayable: [panel "+panel.isDisplayable()+", canvas "+glCanvas1.isDisplayable()+"]");
+ if( panel.isVisible() ) {
+ frame.validate(); // take care of resized frame while hidden
+ }
+ }
+ });
+
+ // Build a GUI that displays canvas and check box
+ framePane.setLayout(new BorderLayout());
+ framePane.add(panel, BorderLayout.CENTER);
+ framePane.add(checkbox, BorderLayout.NORTH);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(width, height);
+ frame.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true));
+
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glCanvas1);
+
+ Assert.assertNotNull(animator);
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ framePane.remove(panel);
+ frame.dispose();
+ }});
+ }
+
+ static GLProfile getGLP() {
+ return GLProfile.getMaxProgrammableCore(true);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+
+ org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos03cB849AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java
new file mode 100644
index 000000000..78fcbfed3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java
@@ -0,0 +1,152 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Dialog;
+import java.awt.Frame;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Bug 816: OSX CALayer Positioning Bug - AWT Frame w/ (top-level) Dialog child containing the GLCanvas
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug816OSXCALayerPos04aAWT extends UITestCase {
+ static long duration = 1600; // ms
+ static int width=640, height=480;
+
+ @Test
+ public void test() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+
+ final Frame frame = new Frame("TestBug816OSXCALayerPos04aAWT");
+ Assert.assertNotNull(frame);
+
+ final GLCanvas glCanvas1 = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas1);
+ glCanvas1.addGLEventListener(new GearsES2(1));
+
+ final Animator animator = new Animator();
+ animator.add(glCanvas1);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas1).addTo(frame);
+
+ // Display the canvas 3D in a dialog child of a frame
+ frame.setSize(400, 400);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setLocation(100, 100);
+ frame.setSize(width, height);
+ frame.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+
+ final Dialog dialog = new Dialog(frame, "Bug 816 AWT Top-Level Dialog");
+ dialog.setLayout(new BorderLayout());
+ dialog.add(glCanvas1, BorderLayout.CENTER);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ dialog.setLocation(200, 200);
+ dialog.setSize(width/2, height/2);
+ dialog.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(dialog, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true));
+
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ animator.setUpdateFPSFrames(60, System.err);
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glCanvas1);
+
+ Assert.assertNotNull(animator);
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.remove(glCanvas1);
+ frame.dispose();
+ }});
+ }
+
+ static GLProfile getGLP() {
+ return GLProfile.getMaxProgrammableCore(true);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+
+ org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos04aAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java
new file mode 100644
index 000000000..8f1917e3a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java
@@ -0,0 +1,152 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.BorderLayout;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Bug 816: OSX CALayer Positioning Bug - AWT JFrame w/ JDialog child containing the GLCanvas
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug816OSXCALayerPos04bAWT extends UITestCase {
+ static long duration = 1600; // ms
+ static int width=640, height=480;
+
+ @Test
+ public void test() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(getGLP());
+
+ final JFrame frame = new JFrame("TestBug816OSXCALayerPos04bAWT");
+ Assert.assertNotNull(frame);
+
+ final GLCanvas glCanvas1 = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas1);
+ glCanvas1.addGLEventListener(new GearsES2(1));
+
+ final Animator animator = new Animator();
+ animator.add(glCanvas1);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas1).addTo(frame);
+
+ // Display the canvas 3D in a dialog child of a frame
+ frame.setSize(400, 400);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setLocation(100, 100);
+ frame.setSize(width, height);
+ frame.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+
+ final JDialog dialog = new JDialog(frame, "Bug 816 AWT Top-Level JDialog");
+ dialog.setLayout(new BorderLayout());
+ dialog.add(glCanvas1, BorderLayout.CENTER);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ dialog.setLocation(200, 200);
+ dialog.setSize(width/2, height/2);
+ dialog.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(dialog, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true));
+
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ animator.setUpdateFPSFrames(60, System.err);
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glCanvas1);
+
+ Assert.assertNotNull(animator);
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.remove(glCanvas1);
+ frame.dispose();
+ }});
+ }
+
+ static GLProfile getGLP() {
+ return GLProfile.getMaxProgrammableCore(true);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+
+ org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos04bAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock00AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock00AWT.java
new file mode 100644
index 000000000..edb489a4a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock00AWT.java
@@ -0,0 +1,244 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.awt.GLCanvas;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.FPSAnimator;
+
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+
+import java.awt.BorderLayout;
+import java.awt.Frame;
+import java.awt.Insets;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLCanvasAWTActionDeadlock00AWT extends UITestCase {
+ static long durationPerTest = 1000; // ms
+ static final int width = 512;
+ static final int height = 512;
+
+ GLEventListener gle1 = null;
+ GLEventListener gle2 = null;
+
+ @Test
+ public void test01Animator() throws InterruptedException {
+ testImpl(new Animator(), 0, false);
+ }
+
+ @Test
+ public void test02FPSAnimator() throws InterruptedException {
+ testImpl(new FPSAnimator(30), 0, false);
+ }
+
+ @Test
+ public void test02FPSAnimator_RestartOnAWTEDT() throws InterruptedException {
+ testImpl(new FPSAnimator(30), 100, false);
+ }
+
+ /** May crash due to invalid thread usage, i.e. non AWT-EDT
+ @Test
+ public void test02FPSAnimator_RestartOnCurrentThread() throws InterruptedException {
+ testImpl(new FPSAnimator(30), 100, true);
+ } */
+
+ void testImpl(final AnimatorBase animator, final int restartPeriod, final boolean restartOnCurrentThread) throws InterruptedException {
+ final Frame frame1 = new Frame("Frame 1");
+ gle1 = new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ frame1.setTitle("f "+frameCount+", fps "+animator.getLastFPS());
+ frameCount++;
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ }
+ };
+ gle2 = new GearsES2();
+
+ Assert.assertNotNull(frame1);
+ {
+ final Insets insets = frame1.getInsets();
+ final int w = width + insets.left + insets.right;
+ final int h = height + insets.top + insets.bottom;
+ frame1.setSize(w, h);
+ }
+ frame1.setLocation(0, 0);
+ frame1.setTitle("Generic Title");
+
+ GLCanvas glCanvas = createGLCanvas();
+ glCanvas.addGLEventListener(gle1);
+ glCanvas.addGLEventListener(gle2);
+
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.add(glCanvas);
+ animator.start();
+
+ attachGLCanvas(frame1, glCanvas, false);
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(true);
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+
+ final long sleep = 0 < restartPeriod ? restartPeriod : 100;
+ long togo = durationPerTest;
+ while( 0 < togo ) {
+ if(0 < restartPeriod) {
+ glCanvas = restart(frame1, glCanvas, restartOnCurrentThread);
+ }
+
+ Thread.sleep(sleep);
+
+ togo -= sleep;
+ }
+
+ dispose(frame1, glCanvas);
+ animator.stop();
+
+ gle1 = null;
+ gle2 = null;
+ }
+
+ void dispose(final Frame frame, final GLCanvas glCanvas) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ glCanvas.destroy();
+ frame.dispose();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+
+ GLCanvas restart(final Frame frame, GLCanvas glCanvas, final boolean restartOnCurrentThread) throws InterruptedException {
+ glCanvas.disposeGLEventListener(gle1, true);
+ glCanvas.disposeGLEventListener(gle2, true);
+ detachGLCanvas(frame, glCanvas, restartOnCurrentThread);
+
+ glCanvas = createGLCanvas();
+
+ attachGLCanvas(frame, glCanvas, restartOnCurrentThread);
+ glCanvas.addGLEventListener(gle1);
+ glCanvas.addGLEventListener(gle2);
+
+ return glCanvas;
+ }
+
+ void attachGLCanvas(final Frame frame, final GLCanvas glCanvas, final boolean restartOnCurrentThread) {
+ System.err.println("*** attachGLCanvas.0 on-current-thread "+restartOnCurrentThread+", currentThread "+Thread.currentThread().getName());
+ if( restartOnCurrentThread ) {
+ frame.setLayout(new BorderLayout());
+ frame.add(glCanvas, BorderLayout.CENTER);
+ frame.validate();
+ } else {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setLayout(new BorderLayout());
+ frame.add(glCanvas, BorderLayout.CENTER);
+ frame.validate();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+ System.err.println("*** attachGLCanvas.X");
+ }
+
+ void detachGLCanvas(final Frame frame, final GLCanvas glCanvas, final boolean restartOnCurrentThread) {
+ System.err.println("*** detachGLCanvas.0 on-current-thread "+restartOnCurrentThread+", currentThread "+Thread.currentThread().getName());
+ if( restartOnCurrentThread ) {
+ frame.remove(glCanvas);
+ frame.validate();
+ } else {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.remove(glCanvas);
+ frame.validate();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+ System.err.println("*** detachGLCanvas.X");
+ }
+
+ int frameCount = 0;
+
+ GLCanvas createGLCanvas() {
+ System.err.println("*** createGLCanvas.0");
+ final GLCanvas glCanvas = new GLCanvas();
+ glCanvas.setBounds(0, 0, width, height);
+ Assert.assertNotNull(glCanvas);
+ System.err.println("*** createGLCanvas.X");
+ return glCanvas;
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLCanvasAWTActionDeadlock00AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java
new file mode 100644
index 000000000..5b605ff33
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java
@@ -0,0 +1,351 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.FPSAnimator;
+
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Frame;
+import java.awt.Insets;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * BUG on OSX/CALayer w/ Java6:
+ * If frame.setTitle() is issued right after initialization the call hangs in
+ * <pre>
+ * at apple.awt.CWindow._setTitle(Native Method)
+ * at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909]
+ * </pre>
+ * <p>
+ * OSX/CALayer is forced by using an Applet component in this unit test.
+ * </p>
+ * <p>
+ * Similar deadlock has been experienced w/ other mutable operation on an AWT Container owning a GLCanvas child,
+ * e.g. setResizable*().
+ * </p>
+ * <p>
+ * Users shall make sure all mutable AWT calls are performed on the EDT, even before 1st setVisible(true) !
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
+ static long durationPerTest = 1000; // ms
+ static final int width = 512;
+ static final int height = 512;
+
+ GLEventListener gle1 = null;
+ GLEventListener gle2 = null;
+
+ @Test
+ public void test00NoAnimator() throws InterruptedException, InvocationTargetException {
+ testImpl(null, 0, false);
+ }
+
+ @Test
+ public void test01Animator() throws InterruptedException, InvocationTargetException {
+ testImpl(new Animator(), 0, false);
+ }
+
+ @Test
+ public void test02FPSAnimator() throws InterruptedException, InvocationTargetException {
+ testImpl(new FPSAnimator(30), 0, false);
+ }
+
+ @Test
+ public void test02FPSAnimator_RestartOnAWTEDT() throws InterruptedException, InvocationTargetException {
+ testImpl(new FPSAnimator(30), 200, false);
+ }
+
+ /** May crash due to invalid thread usage, i.e. non AWT-EDT
+ * @throws InvocationTargetException
+ * @throws InterruptedException
+ @Test
+ public void test02FPSAnimator_RestartOnCurrentThread() throws InterruptedException {
+ testImpl(new FPSAnimator(30), 200, true);
+ } */
+
+ private static void setFrameTitle(final Frame frame, final String msg) {
+ System.err.println("About to setTitle: <"+msg+"> CT "+Thread.currentThread().getName()+", "+
+ frame+", displayable "+frame.isDisplayable()+
+ ", valid "+frame.isValid()+", visible "+frame.isVisible());
+ // Thread.dumpStack();
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ frame.setTitle(msg);
+ } } );
+ }
+
+ void testImpl(final AnimatorBase animator, final int restartPeriod, final boolean restartOnCurrentThread) throws InterruptedException, InvocationTargetException {
+ final Frame frame1 = new Frame("Frame 1");
+ final Applet applet1 = new Applet() {
+ private static final long serialVersionUID = 1L;
+ };
+
+ final VersionNumber version170 = new VersionNumber(1, 7, 0);
+ final boolean osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() &&
+ 0 > Platform.getJavaVersionNumber().compareTo(version170);
+ System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug);
+ System.err.println("OSType "+Platform.getOSType());
+ System.err.println("Java Version "+Platform.getJavaVersionNumber());
+
+ Assert.assertNotNull(frame1);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setLayout(null);
+ frame1.pack();
+ {
+ final Insets insets = frame1.getInsets();
+ final int w = width + insets.left + insets.right;
+ final int h = height + insets.top + insets.bottom;
+ frame1.setSize(w, h);
+
+ final int usableH = h - insets.top - insets.bottom;
+ applet1.setBounds((w - width)/2, insets.top + (usableH - height)/2, width, height);
+ }
+ frame1.setLocation(0, 0);
+ frame1.setTitle("Generic Title");
+ frame1.add(applet1);
+ }});
+
+ frame1.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
+ dispose(frame1, applet1);
+ }
+ });
+
+ gle1 = new GLEventListener() {
+ boolean justInitialized = true;
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ justInitialized = true;
+ if( !osxCALayerAWTModBug ) {
+ System.err.println("*Init*: CT "+Thread.currentThread().getName());
+ setFrameTitle(frame1, "INIT");
+ frame1.setResizable(false);
+ }
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ System.err.println("*Dispose*: CT "+Thread.currentThread().getName());
+ setFrameTitle(frame1, "DISPOSE");
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ if( !osxCALayerAWTModBug || !justInitialized ) {
+ System.err.println("*Display*: CT "+Thread.currentThread().getName());
+ setFrameTitle(frame1, "f "+frameCount+", fps "+( null != animator ? animator.getLastFPS() : 0));
+ frame1.setResizable(false);
+ }
+ frameCount++;
+ justInitialized = false;
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ if( !osxCALayerAWTModBug || !justInitialized ) {
+ System.err.println("*Reshape*: CT "+Thread.currentThread().getName());
+ setFrameTitle(frame1, "RESHAPE");
+ }
+ }
+ };
+ gle2 = new GearsES2();
+
+ GLCanvas glCanvas = createGLCanvas();
+ glCanvas.addGLEventListener(gle1);
+ glCanvas.addGLEventListener(gle2);
+
+ if(null != animator) {
+ System.err.println("About to start Animator: CT "+Thread.currentThread().getName());
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.add(glCanvas);
+ animator.start();
+ }
+
+ attachGLCanvas(applet1, glCanvas, false);
+
+ System.err.println("About to setVisible.0 CT "+Thread.currentThread().getName());
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ System.err.println("About to setVisible.1.0 CT "+Thread.currentThread().getName());
+ frame1.setVisible(true);
+ System.err.println("About to setVisible.1.X CT "+Thread.currentThread().getName());
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ System.err.println("About to setVisible.X CT "+Thread.currentThread().getName());
+
+ final long sleep = 0 < restartPeriod ? restartPeriod : 100;
+ long togo = durationPerTest;
+ while( 0 < togo ) {
+ if(null == animator) {
+ glCanvas.display();
+ }
+ if(0 < restartPeriod) {
+ glCanvas = restart(applet1, glCanvas, restartOnCurrentThread);
+ }
+
+ Thread.sleep(sleep);
+
+ togo -= sleep;
+ }
+
+ dispose(frame1, applet1);
+ if(null != animator) {
+ animator.stop();
+ }
+
+ gle1 = null;
+ gle2 = null;
+ }
+
+ int frameCount = 0;
+
+ GLCanvas createGLCanvas() {
+ System.err.println("*** createGLCanvas.0");
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ // Iff using offscreen layer, use pbuffer, hence restore onscreen:=true.
+ // caps.setPBuffer(true);
+ // caps.setOnscreen(true);
+ final GLCanvas glCanvas = new GLCanvas(caps);
+ glCanvas.setBounds(0, 0, width, height);
+ Assert.assertNotNull(glCanvas);
+ System.err.println("*** createGLCanvas.X");
+ frameCount = 0;
+ return glCanvas;
+ }
+
+ void dispose(final Frame frame, final Applet applet) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.remove(applet);
+ frame.dispose();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+
+ GLCanvas restart(final Applet applet, GLCanvas glCanvas, final boolean restartOnCurrentThread) throws InterruptedException {
+ glCanvas.disposeGLEventListener(gle1, true);
+ glCanvas.disposeGLEventListener(gle2, true);
+ detachGLCanvas(applet, glCanvas, restartOnCurrentThread);
+
+ glCanvas = createGLCanvas();
+
+ attachGLCanvas(applet, glCanvas, restartOnCurrentThread);
+ glCanvas.addGLEventListener(gle1);
+ glCanvas.addGLEventListener(gle2);
+
+ return glCanvas;
+ }
+
+ void attachGLCanvas(final Applet applet, final GLCanvas glCanvas, final boolean restartOnCurrentThread) {
+ System.err.println("*** attachGLCanvas.0 on-current-thread "+restartOnCurrentThread+", currentThread "+Thread.currentThread().getName());
+ if( restartOnCurrentThread ) {
+ applet.setLayout(new BorderLayout());
+ applet.add(glCanvas, BorderLayout.CENTER);
+ applet.validate();
+ } else {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ applet.setLayout(new BorderLayout());
+ applet.add(glCanvas, BorderLayout.CENTER);
+ applet.validate();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+ System.err.println("*** attachGLCanvas.X");
+ }
+
+ void detachGLCanvas(final Applet applet, final GLCanvas glCanvas, final boolean restartOnCurrentThread) {
+ System.err.println("*** detachGLCanvas.0 on-current-thread "+restartOnCurrentThread+", currentThread "+Thread.currentThread().getName());
+ if( restartOnCurrentThread ) {
+ applet.remove(glCanvas);
+ applet.validate();
+ } else {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ applet.remove(glCanvas);
+ applet.validate();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+ System.err.println("*** detachGLCanvas.X");
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLCanvasAWTActionDeadlock01AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java
new file mode 100644
index 000000000..596ada665
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java
@@ -0,0 +1,670 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.DisplayMode;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.media.opengl.*;
+import javax.media.opengl.awt.GLCanvas;
+
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Sample program that relies on JOGL's mechanism to handle the OpenGL context
+ * and rendering loop when using an AWT canvas attached to an Applet.
+ * <p>
+ * BUG on OSX/CALayer w/ Java6:
+ * If frame.setTitle() is issued right after initialization the call hangs in
+ * <pre>
+ * at apple.awt.CWindow._setTitle(Native Method)
+ * at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909]
+ * </pre>
+ * </p>
+ * <p>
+ * OSX/CALayer is forced by using an Applet component in this unit test.
+ * </p>
+ * <p>
+ * Similar deadlock has been experienced w/ other mutable operation on an AWT Container owning a GLCanvas child,
+ * e.g. setResizable*().
+ * </p>
+ * <p>
+ * Users shall make sure all mutable AWT calls are performed on the EDT, even before 1st setVisible(true) !
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
+ static int framesPerTest = 240; // frames
+
+ static class MiniPApplet extends Applet implements MouseMotionListener, KeyListener {
+ private static final long serialVersionUID = 1L;
+
+ /////////////////////////////////////////////////////////////
+ //
+ // Test parameters
+
+ public int frameRate = 120;
+ public int numSamples = 4;
+
+ public boolean fullScreen = false;
+ public boolean useAnimator = true;
+ public boolean resizeableFrame = true;
+
+ public boolean restartCanvas = true;
+ public int restartTimeout = 100; // in number of frames.
+
+ public boolean printThreadInfo = false;
+ public boolean printEventInfo = false;
+
+ /////////////////////////////////////////////////////////////
+ //
+ // Internal variables
+
+ int width;
+ int height;
+
+ String OPENGL_VENDOR;
+ String OPENGL_RENDERER;
+ String OPENGL_VERSION;
+ String OPENGL_EXTENSIONS;
+
+ int currentSamples = -1;
+
+ private Frame frame;
+ private GLProfile profile;
+ private GLCapabilities capabilities;
+ private GLCanvas canvas;
+
+ private SimpleListener listener;
+ private CustomAnimator animator;
+
+ private long beforeTime;
+ private long overSleepTime;
+ private final long frameRatePeriod = 1000000000L / frameRate;
+
+ private boolean initialized = false;
+ private boolean osxCALayerAWTModBug = false;
+ boolean justInitialized = true;
+
+ private double theta = 0;
+ private double s = 0;
+ private double c = 0;
+
+ private long millisOffset;
+ private int fcount, lastm;
+ private float frate;
+ private final int fint = 3;
+
+ private boolean setFramerate = false;
+ private boolean restarted = false;
+
+ private int frameCount = 0;
+
+ void run() throws InterruptedException, InvocationTargetException {
+ // Thread loop = new Thread("Animation Thread") {
+ // public void run() {
+ frameCount = 0;
+ while ( frameCount < framesPerTest ) {
+ if (!initialized) {
+ setup();
+ }
+
+ if (restartCanvas && restartTimeout == frameCount) {
+ restart();
+ }
+
+ if (useAnimator) {
+ animator.requestRender();
+ } else {
+ canvas.display();
+ }
+
+ clock();
+
+ frameCount++;
+ if( null == frame ) {
+ break;
+ }
+ }
+ dispose();
+ // }
+ // };
+ // loop.start();
+ }
+
+ void setup() throws InterruptedException, InvocationTargetException {
+ if (printThreadInfo) System.out.println("Current thread at setup(): " + Thread.currentThread());
+
+ millisOffset = System.currentTimeMillis();
+
+ final VersionNumber version170 = new VersionNumber(1, 7, 0);
+ osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() &&
+ 0 > Platform.getJavaVersionNumber().compareTo(version170);
+ System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug);
+ System.err.println("OSType "+Platform.getOSType());
+ System.err.println("Java Version "+Platform.getJavaVersionNumber());
+
+ // Frame setup ----------------------------------------------------------
+
+ width = 300;
+ height = 300;
+ final MiniPApplet applet = this;
+
+ final GraphicsEnvironment environment =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ final GraphicsDevice displayDevice = environment.getDefaultScreenDevice();
+ frame = new Frame(displayDevice.getDefaultConfiguration());
+
+ final Rectangle fullScreenRect;
+ if (fullScreen) {
+ final DisplayMode mode = displayDevice.getDisplayMode();
+ fullScreenRect = new Rectangle(0, 0, mode.getWidth(), mode.getHeight());
+ } else {
+ fullScreenRect = null;
+ }
+ // All AWT Mods on AWT-EDT, especially due to the follow-up complicated code!
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ frame.setTitle("MiniPApplet");
+ } } );
+ if (fullScreen) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setUndecorated(true);
+ frame.setBackground(Color.GRAY);
+ frame.setBounds(fullScreenRect);
+ frame.setVisible(true);
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setLayout(null);
+ frame.add(applet);
+ if (fullScreen) {
+ frame.invalidate();
+ } else {
+ frame.pack();
+ }
+ frame.setResizable(resizeableFrame);
+ if (fullScreen) {
+ // After the pack(), the screen bounds are gonna be 0s
+ frame.setBounds(fullScreenRect);
+ applet.setBounds((fullScreenRect.width - applet.width) / 2,
+ (fullScreenRect.height - applet.height) / 2,
+ applet.width, applet.height);
+ } else {
+ final Insets insets = frame.getInsets();
+
+ final int windowW = applet.width + insets.left + insets.right;
+ final int windowH = applet.height + insets.top + insets.bottom;
+ final int locationX = 100;
+ final int locationY = 100;
+
+ frame.setSize(windowW, windowH);
+ frame.setLocation(locationX, locationY);
+
+ final int usableWindowH = windowH - insets.top - insets.bottom;
+ applet.setBounds((windowW - width)/2, insets.top + (usableWindowH - height)/2, width, height);
+ }
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+
+
+ frame.add(this);
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
+ try {
+ dispose();
+ } catch (final Exception ex) {
+ Assume.assumeNoException(ex);
+ }
+ }
+ });
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(true);
+ } } );
+
+ // Canvas setup ----------------------------------------------------------
+
+ profile = GLProfile.getDefault();
+ capabilities = new GLCapabilities(profile);
+ capabilities.setSampleBuffers(true);
+ capabilities.setNumSamples(numSamples);
+ capabilities.setDepthBits(24);
+ // capabilities.setStencilBits(8); // No Stencil on OSX w/ hw-accel !
+ capabilities.setAlphaBits(8);
+
+ canvas = new GLCanvas(capabilities);
+ canvas.setBounds(0, 0, width, height);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ MiniPApplet.this.setLayout(new BorderLayout());
+ MiniPApplet.this.add(canvas, BorderLayout.CENTER);
+ MiniPApplet.this.validate();
+ } } );
+ canvas.addMouseMotionListener(this);
+ canvas.addKeyListener(this);
+
+ // Setting up animation
+ listener = new SimpleListener();
+ canvas.addGLEventListener(listener);
+ if (useAnimator) {
+ animator = new CustomAnimator(canvas);
+ animator.start();
+ }
+ initialized = true;
+ }
+
+ void restart() throws InterruptedException, InvocationTargetException {
+ System.out.println("Restarting surface...");
+
+ // Stopping animation, removing current canvas.
+ if (useAnimator) {
+ animator.stop();
+ animator.remove(canvas);
+ }
+ canvas.disposeGLEventListener(listener, true);
+ this.remove(canvas);
+
+ capabilities = new GLCapabilities(profile);
+ capabilities.setSampleBuffers(true);
+ capabilities.setNumSamples(numSamples);
+
+ canvas = new GLCanvas(capabilities);
+ canvas.setBounds(0, 0, width, height);
+
+ // Setting up animation again
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ MiniPApplet.this.setLayout(new BorderLayout());
+ MiniPApplet.this.add(canvas, BorderLayout.CENTER);
+ MiniPApplet.this.validate();
+ } } );
+ canvas.addMouseMotionListener(this);
+ canvas.addKeyListener(this);
+
+ canvas.addGLEventListener(listener);
+ if (useAnimator) {
+ animator.add(canvas);
+ animator.start();
+ }
+
+ setFramerate = false;
+ restarted = true;
+
+ System.out.println("Done");
+ }
+
+ void dispose() throws InterruptedException, InvocationTargetException {
+ if( null == frame ) {
+ return;
+ }
+
+ // Stopping animation, removing current canvas.
+ if (useAnimator) {
+ animator.stop();
+ animator.remove(canvas);
+ }
+ canvas.removeGLEventListener(listener);
+ if( EventQueue.isDispatchThread() ) {
+ MiniPApplet.this.remove(canvas);
+ frame.remove(MiniPApplet.this);
+ frame.validate();
+ frame.dispose();
+ frame = null;
+ } else {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ MiniPApplet.this.remove(canvas);
+ frame.remove(MiniPApplet.this);
+ frame.validate();
+ frame.dispose();
+ frame = null;
+ }});
+ }
+ }
+
+ void draw(final GL2 gl) {
+ if( !osxCALayerAWTModBug || !justInitialized ) {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ frame.setTitle("frame " + frameCount);
+ } } );
+ }
+
+ if (printThreadInfo) System.out.println("Current thread at draw(): " + Thread.currentThread());
+
+ if (OPENGL_VENDOR == null) {
+ OPENGL_VENDOR = gl.glGetString(GL.GL_VENDOR);
+ OPENGL_RENDERER = gl.glGetString(GL.GL_RENDERER);
+ OPENGL_VERSION = gl.glGetString(GL.GL_VERSION);
+ OPENGL_EXTENSIONS = gl.glGetString(GL.GL_EXTENSIONS);
+ System.out.println(OPENGL_VENDOR);
+ System.out.println(OPENGL_RENDERER);
+ System.out.println(OPENGL_VERSION);
+ System.out.println(OPENGL_EXTENSIONS);
+
+ final int[] temp = { 0 };
+ gl.glGetIntegerv(GL2ES3.GL_MAX_SAMPLES, temp, 0);
+ System.out.println("Maximum number of samples supported by the hardware: " + temp[0]);
+ System.out.println("Frame: "+frame);
+ System.out.println("Applet: "+MiniPApplet.this);
+ System.out.println("GLCanvas: "+canvas);
+ System.out.println("GLDrawable: "+canvas.getDelegatedDrawable());
+ }
+
+ if (currentSamples == -1) {
+ final int[] temp = { 0 };
+ gl.glGetIntegerv(GL.GL_SAMPLES, temp, 0);
+ currentSamples = temp[0];
+ if (numSamples != currentSamples) {
+ System.err.println("Requested sampling level " + numSamples + " not supported. Using " + currentSamples + " samples instead.");
+ }
+ }
+
+ if (!setFramerate) {
+ if (60 < frameRate) {
+ // Disables vsync
+ gl.setSwapInterval(0);
+ } else if (30 < frameRate) {
+ gl.setSwapInterval(1);
+ } else {
+ gl.setSwapInterval(2);
+ }
+ setFramerate = true;
+ }
+
+ if (restarted) {
+ final int[] temp = { 0 };
+ gl.glGetIntegerv(GL.GL_SAMPLES, temp, 0);
+ if (numSamples != temp[0]) {
+ System.err.println("Multisampling level requested " + numSamples + " not supported. Using " + temp[0] + "samples instead.");
+ }
+ }
+
+ gl.glClearColor(0, 0, 0, 1);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+
+ theta += 0.01;
+ s = Math.sin(theta);
+ c = Math.cos(theta);
+
+ gl.glBegin(GL.GL_TRIANGLES);
+ gl.glColor3f(1, 0, 0);
+ gl.glVertex2d(-c, -c);
+ gl.glColor3f(0, 1, 0);
+ gl.glVertex2d(0, c);
+ gl.glColor3f(0, 0, 1);
+ gl.glVertex2d(s, -s);
+ gl.glEnd();
+
+ gl.glFlush();
+
+ fcount += 1;
+ final int m = (int) (System.currentTimeMillis() - millisOffset);
+ if (m - lastm > 1000 * fint) {
+ frate = (float)(fcount) / fint;
+ fcount = 0;
+ lastm = m;
+ System.err.println("fps: " + frate);
+ }
+ }
+
+ void clock() {
+ final long afterTime = System.nanoTime();
+ final long timeDiff = afterTime - beforeTime;
+ final long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime;
+
+ if (sleepTime > 0) { // some time left in this cycle
+ try {
+ Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L));
+ } catch (final InterruptedException ex) { }
+
+ overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
+
+ } else { // sleepTime <= 0; the frame took longer than the period
+ overSleepTime = 0L;
+ }
+
+ beforeTime = System.nanoTime();
+ }
+
+ class SimpleListener implements GLEventListener {
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ draw(drawable.getGL().getGL2());
+ justInitialized = false;
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) { }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ justInitialized = true;
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int w, final int h) { }
+ }
+
+ public void mouseDragged(final MouseEvent ev) {
+ if (printEventInfo) {
+ System.err.println("Mouse dragged event: " + ev);
+ }
+ }
+
+ public void mouseMoved(final MouseEvent ev) {
+ if (printEventInfo) {
+ System.err.println("Mouse moved event: " + ev);
+ }
+ }
+
+ public void keyPressed(final KeyEvent ev) {
+ if (printEventInfo) {
+ System.err.println("Key pressed event: " + ev);
+ }
+ }
+
+ public void keyReleased(final KeyEvent ev) {
+ if (printEventInfo) {
+ System.err.println("Key released event: " + ev);
+ }
+ }
+
+ public void keyTyped(final KeyEvent ev) {
+ if (printEventInfo) {
+ System.err.println("Key typed event: " + ev);
+ }
+ }
+
+ /** An Animator subclass which renders one frame at the time
+ * upon calls to the requestRender() method.
+ **/
+ public static class CustomAnimator extends AnimatorBase {
+ private Timer timer = null;
+ private TimerTask task = null;
+ private volatile boolean shouldRun;
+
+ protected String getBaseName(final String prefix) {
+ return "Custom" + prefix + "Animator" ;
+ }
+
+ /** Creates an CustomAnimator with an initial drawable to
+ * animate. */
+ public CustomAnimator(final GLAutoDrawable drawable) {
+ if (drawable != null) {
+ add(drawable);
+ }
+ }
+
+ public synchronized void requestRender() {
+ shouldRun = true;
+ }
+
+ public final synchronized boolean isStarted() {
+ return (timer != null);
+ }
+
+ public final synchronized boolean isAnimating() {
+ return (timer != null) && (task != null);
+ }
+
+ private void startTask() {
+ if(null != task) {
+ return;
+ }
+
+ task = new TimerTask() {
+ private boolean firstRun = true;
+ public void run() {
+ if (firstRun) {
+ Thread.currentThread().setName("OPENGL");
+ firstRun = false;
+ }
+ if(CustomAnimator.this.shouldRun) {
+ CustomAnimator.this.animThread = Thread.currentThread();
+ // display impl. uses synchronized block on the animator instance
+ display();
+ synchronized (this) {
+ // done with current frame.
+ shouldRun = false;
+ }
+ }
+ }
+ };
+
+ fpsCounter.resetFPSCounter();
+ shouldRun = false;
+
+ timer.schedule(task, 0, 1);
+ }
+
+ public synchronized boolean start() {
+ if (timer != null) {
+ return false;
+ }
+ timer = new Timer();
+ startTask();
+ return true;
+ }
+
+ /** Stops this CustomAnimator. */
+ public synchronized boolean stop() {
+ if (timer == null) {
+ return false;
+ }
+ shouldRun = false;
+ if(null != task) {
+ task.cancel();
+ task = null;
+ }
+ if(null != timer) {
+ timer.cancel();
+ timer = null;
+ }
+ animThread = null;
+ try {
+ Thread.sleep(20); // ~ 1/60 hz wait, since we can't ctrl stopped threads / holding the lock is OK here!
+ } catch (final InterruptedException e) { }
+ return true;
+ }
+
+ public final synchronized boolean isPaused() { return false; }
+ public synchronized boolean resume() { return false; }
+ public synchronized boolean pause() { return false; }
+ }
+ }
+
+ @Test
+ public void test00() {
+ TestGLCanvasAWTActionDeadlock02AWT.MiniPApplet mini;
+ try {
+ final Class<?> c = Thread.currentThread().getContextClassLoader().loadClass(TestGLCanvasAWTActionDeadlock02AWT.MiniPApplet.class.getName());
+ mini = (TestGLCanvasAWTActionDeadlock02AWT.MiniPApplet) c.newInstance();
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+ if (mini != null) {
+ try {
+ mini.run();
+ } catch (final Exception ex) {
+ Assume.assumeNoException(ex);
+ }
+ }
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-frames")) {
+ framesPerTest = MiscUtils.atoi(args[++i], framesPerTest);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLCanvasAWTActionDeadlock02AWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelResize01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelResize01AWT.java
new file mode 100644
index 000000000..cc2c9ef57
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelResize01AWT.java
@@ -0,0 +1,209 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import java.awt.Dimension;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Multiple GLJPanels in a JFrame
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLJPanelResize01AWT extends UITestCase {
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ static Dimension[] esize00 = {
+ new Dimension(281, 151),
+ new Dimension(282, 151),
+ new Dimension(283, 151),
+ new Dimension(284, 151),
+
+ new Dimension(284, 152),
+ new Dimension(283, 152),
+ new Dimension(282, 152),
+ new Dimension(281, 152),
+
+ new Dimension(291, 153),
+ new Dimension(292, 153),
+ new Dimension(293, 153),
+ new Dimension(294, 153),
+
+ new Dimension(281, 154),
+ new Dimension(282, 154),
+ new Dimension(283, 154),
+ new Dimension(284, 154)
+ };
+ static Dimension[] esize01 = {
+ new Dimension(283, 154), // #3: new sub-aligned image in pixelBuffer-1
+ new Dimension(291, 154), // #2: new pixelBuffer-1
+ new Dimension(282, 154), // #1: new pixelBuffer-0
+ };
+ static Dimension[] esize02 = {
+ new Dimension(291, 154), // #2: new pixelBuffer-1
+ new Dimension(282, 154), // #1: new pixelBuffer-0
+ };
+
+ public void test(final GLCapabilitiesImmutable caps, final Dimension[] dims, final boolean useSwingDoubleBuffer) {
+ final int cols = 4;
+ final int rows = dims.length / cols + ( dims.length % cols > 0 ? 1 : 0 );
+ final JFrame[] frame = new JFrame[] { null };
+
+ System.err.println("Frame size: cols x rows "+cols+"x"+rows);
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame[0] = new JFrame();
+ frame[0].setLocation(64, 64);
+ final JPanel panel = new JPanel();
+ panel.setLayout(null); // new BorderLayout());
+ panel.setDoubleBuffered(useSwingDoubleBuffer);
+ frame[0].getContentPane().add(panel);
+
+ final int x0 = 4;
+ int x = x0, y = 4;
+ int maxRowWidth = 0;
+ for(int i=0; i<rows; i++) {
+ int maxColHeight = 0;
+ for(int j=0; j<cols; j++) {
+ final int idx = i*cols+j;
+ if( idx >= dims.length ) { break; }
+ final Dimension d = dims[idx];
+ if( d.height > maxColHeight ) {
+ maxColHeight = d.height;
+ }
+ final GLJPanel glad = createGLJPanel(useSwingDoubleBuffer, caps, d, "[r "+i+", c "+j+"]");
+ panel.add(glad);
+ glad.setLocation(x, y);
+ x+=d.width+4;
+ }
+ if( x > maxRowWidth ) {
+ maxRowWidth = x;
+ }
+ x = x0;
+ y += maxColHeight+4;
+ }
+ frame[0].setSize(maxRowWidth+4+64, y+4+64);
+ // frame[0].pack();
+ frame[0].setVisible(true);
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ try {
+ Thread.sleep(duration);
+ } catch (final InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame[0].dispose();
+ } } );
+ } catch (final Exception e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ private GLJPanel createGLJPanel(final boolean useSwingDoubleBuffer, final GLCapabilitiesImmutable caps, final Dimension size, final String name) {
+ final GLJPanel canvas = new GLJPanel(caps);
+ canvas.setName(name);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ canvas.setMinimumSize(size);
+ canvas.setDoubleBuffered(useSwingDoubleBuffer);
+ final GearsES2 g = new GearsES2(0);
+ g.setVerbose(false);
+ canvas.addGLEventListener(g);
+ return canvas;
+ }
+
+ static GLCapabilitiesImmutable caps = null;
+
+ // @Test
+ public void test00() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), esize00, false /*useSwingDoubleBuffer*/);
+ }
+
+ @Test
+ public void test01() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), esize01, false /*useSwingDoubleBuffer*/);
+ }
+
+ @Test
+ public void test02() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), esize02, false /*useSwingDoubleBuffer*/);
+ }
+
+ static long duration = 600; // ms
+
+ public static void main(final String[] args) {
+ boolean useSwingDoubleBuffer=false, manual=false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-swingDoubleBuffer")) {
+ useSwingDoubleBuffer = true;
+ } else if(args[i].equals("-manual")) {
+ manual = true;
+ }
+ }
+ if( manual ) {
+ GLProfile.initSingleton();
+ final TestGLJPanelResize01AWT demo = new TestGLJPanelResize01AWT();
+ demo.test(new GLCapabilities(null), esize01, useSwingDoubleBuffer);
+ } else {
+ org.junit.runner.JUnitCore.main(TestGLJPanelResize01AWT.class.getName());
+ }
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java
new file mode 100644
index 000000000..8cf4b6899
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java
@@ -0,0 +1,315 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw02ES2ListenerFBO;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+
+import com.jogamp.opengl.util.texture.TextureIO;
+import com.jogamp.opengl.util.texture.TextureState;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+
+import java.awt.Dimension;
+import java.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Unit test for bug 826, test {@link GLJPanel}'s {@link TextureState} save and restore.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLJPanelTextureStateAWT extends UITestCase {
+ static boolean showFPS = false;
+ static long duration = 250; // ms
+
+ @BeforeClass
+ public static void initClass() {
+ }
+
+ static void setFrameSize(final JFrame frame, final boolean frameLayout, final java.awt.Dimension new_sz) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(new_sz);
+ if( frameLayout ) {
+ frame.validate();
+ }
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ public void testImpl(final boolean keepTextureBound, final int texUnit)
+ throws InterruptedException, IOException
+ {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+ GLProfile glp;
+ if(GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.getGL2ES2();
+ } else {
+ System.err.println(getSimpleTestName(".")+": GLProfile n/a");
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+
+ final GLJPanel glc = new GLJPanel(caps);
+ // final GLCanvas glc = new GLCanvas(caps);
+ final Dimension glc_sz = new Dimension(640, 480);
+ final Dimension glc_sz2 = new Dimension(800, 400);
+ glc.setMinimumSize(glc_sz);
+ glc.setPreferredSize(glc_sz);
+ final JFrame frame = new JFrame("TestGLJPanelTextureStateAWT");
+ Assert.assertNotNull(frame);
+ frame.getContentPane().add(glc);
+
+ final GLEventListener gle0;
+ {
+ final GearsES2 gle0sub = new GearsES2( 0 );
+ // gle1sub.setClearBuffers(false);
+ final TextureDraw02ES2ListenerFBO demo = new TextureDraw02ES2ListenerFBO(gle0sub, 1, texUnit ) ;
+ demo.setKeepTextureBound(keepTextureBound);
+ demo.setClearBuffers(false);
+ gle0 = demo;
+ }
+
+ final GLEventListener gle1;
+ {
+ final RedSquareES2 demo = new RedSquareES2( 1 ) ;
+ demo.setClearBuffers(false);
+ gle1 = demo;
+ }
+
+ final boolean[] glelError = { false };
+
+ glc.addGLEventListener(new GLEventListener() {
+ int gle0X, gle0Y, gle0W, gle0H;
+ int gle1X, gle1Y, gle1W, gle1H;
+ int tX, tY, tW, tH;
+ int shot = 0;
+
+ void setupTex(final GL gl) {
+ // Note: FBObject uses diff defaults, i.e.: GL_NEAREST and GL_CLAMP_TO_EDGE
+ if( keepTextureBound ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
+ }
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ // Initialize w/ arbitrary values !
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.glActiveTexture(GL.GL_TEXTURE0 + 1);
+ gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + 0);
+ gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
+
+ gle0.init(drawable);
+ gle1.init(drawable);
+ setupTex(gl);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ gle0.dispose(drawable);
+ gle1.dispose(drawable);
+ }
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+ // test viewport
+ {
+ final int[] viewport = new int[] { 0, 0, 0, 0 };
+ gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
+ if( gle1X != viewport[0] || gle1Y != viewport[1] || gle1W != viewport[2] || gle1H != viewport[3] ) {
+ final String msg = "Expected "+gle1X+"/"+gle1Y+" "+gle1W+"x"+gle1H+
+ ", actual "+viewport[0]+"/"+viewport[1]+" "+viewport[2]+"x"+viewport[3];
+ Assert.assertTrue("Viewport not restored: "+msg, false);
+ glelError[0] = true;
+ }
+ }
+
+ gl.glViewport(gle0X, gle0Y, gle0W, gle0H);
+ gle0.display(drawable);
+
+ gl.glViewport(gle1X, gle1Y, gle1W, gle1H);
+ gle1.display(drawable);
+
+ shot++;
+ if( 4 == shot ) {
+ gl.glViewport(tX, tY, tW, tH);
+ snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ gl.glViewport(gle1X, gle1Y, gle1W, gle1H); // restore viewport test
+ }
+
+ final TextureState ts = new TextureState(drawable.getGL(), GL.GL_TEXTURE_2D); // as set via gle0!
+ // System.err.println("XXX: "+ts);
+ Assert.assertEquals("Texture unit changed", GL.GL_TEXTURE0+texUnit, ts.getUnit());
+ if( keepTextureBound ) {
+ Assert.assertEquals("Texture mag-filter changed: "+ts, GL.GL_LINEAR, ts.getMagFilter());
+ Assert.assertEquals("Texture mag-filter changed: "+ts, GL.GL_LINEAR, ts.getMinFilter());
+ Assert.assertEquals("Texture wrap-s changed: "+ts, GL.GL_REPEAT, ts.getWrapS());
+ Assert.assertEquals("Texture wrap-t changed: "+ts, GL.GL_REPEAT, ts.getWrapT());
+ glelError[0] = GL.GL_LINEAR != ts.getMagFilter() || GL.GL_LINEAR != ts.getMinFilter() ||
+ GL.GL_REPEAT != ts.getWrapS() || GL.GL_REPEAT != ts.getWrapT();
+ }
+ }
+ final int border = 5;
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ gle0X = x + border;
+ gle0Y = y;
+ gle0W = width/2 - 2*border;
+ gle0H = height;
+ // System.err.println("GLEL0 "+gle0X+"/"+gle0Y+" "+gle0W+"x"+gle0H);
+
+ gle1X = gle0X + gle0W + 2*border;
+ gle1Y = y;
+ gle1W = width/2 - 2*border;
+ gle1H = height;
+ // System.err.println("GLEL1 "+gle1X+"/"+gle1Y+" "+gle1W+"x"+gle1H);
+
+ tX = x;
+ tY = y;
+ tW = width;
+ tH = height;
+ // System.err.println("Total "+tX+"/"+tY+" "+tW+"x"+tH);
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.glViewport(gle0X, gle0Y, gle0W, gle0H);
+ gle0.reshape(drawable, 0, 0, gle0W, gle0H); // don't 'skip' about gle0X/gle0Y
+
+ gl.glViewport(gle1X, gle1Y, gle1W, gle1H);
+ gle1.reshape(drawable, 0, 0, gle1W, gle1H); // don't 'skip' about gle0X/gle0Y
+
+ if( keepTextureBound ) {
+ setupTex(gl);
+ }
+ }
+ });
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter, glc).addTo(glc);
+ new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter, glc).addTo(glc);
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ frame.setVisible(true);
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true));
+ Assert.assertTrue("Component didn't become realized", AWTRobotUtil.waitForRealized(glc, true));
+ Thread.sleep(100);
+ setFrameSize(frame, true, glc_sz2);
+ System.err.println("window resize pos/siz: "+glc.getX()+"/"+glc.getY()+" "+glc.getSurfaceWidth()+"x"+glc.getSurfaceHeight());
+ Thread.sleep(100);
+
+ final long t0 = System.currentTimeMillis();
+ while(!quitAdapter.shouldQuit() && System.currentTimeMillis()-t0<duration) {
+ glc.display();
+ Thread.sleep(100);
+ }
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ frame.remove(glc);
+ frame.dispose();
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ Assume.assumeFalse("Error occured in GLEL .. see log file above", glelError[0]);
+ }
+
+ @Test
+ public void test01_texUnit0_keepTex0_ES2() throws InterruptedException, IOException {
+ testImpl(false /* keepTextureBound */, 0 /* texUnit */);
+ }
+ @Test
+ public void test02_texUnit0_keepTex1_ES2() throws InterruptedException, IOException {
+ testImpl(true /* keepTextureBound */, 0 /* texUnit */);
+ }
+ @Test
+ public void test03_texUnit1_keepTex1_ES2() throws InterruptedException, IOException {
+ testImpl(true /* keepTextureBound */, 1 /* texUnit */);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGLJPanelTextureStateAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestIsRealizedConcurrency01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestIsRealizedConcurrency01AWT.java
new file mode 100644
index 000000000..d75ff6659
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestIsRealizedConcurrency01AWT.java
@@ -0,0 +1,104 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.awt;
+
+import javax.media.opengl.awt.GLCanvas;
+import com.jogamp.opengl.util.Animator;
+
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestIsRealizedConcurrency01AWT extends UITestCase {
+ static long durationPerTest = 500; // ms
+
+ @Test
+ public void testAddRemove() throws InterruptedException, InvocationTargetException {
+ final Dimension f_sz = new Dimension(512, 512);
+
+ final GLCanvas glCanvas = new GLCanvas();
+ Assert.assertNotNull(glCanvas);
+ glCanvas.addGLEventListener(new GearsES2());
+
+ final Animator animator = new Animator(glCanvas);
+ animator.start();
+
+ final Frame frame = new Frame("Frame");
+ Assert.assertNotNull(frame);
+ frame.add(glCanvas);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setLocation(0, 0);
+ frame.setPreferredSize(f_sz);
+ frame.setSize(f_sz);
+ frame.pack();
+ frame.setVisible(true);
+ }});
+ Thread.sleep(durationPerTest/2);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.remove(glCanvas);
+ frame.validate();
+ frame.add(glCanvas);
+ frame.validate();
+ }});
+ Thread.sleep(durationPerTest/2);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ glCanvas.destroy();
+ frame.dispose();
+ }});
+
+ animator.stop();
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestIsRealizedConcurrency01AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java
index bb525c949..ec9cece53 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java
@@ -21,6 +21,8 @@ import javax.swing.WindowConstants;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
@@ -30,7 +32,7 @@ import com.jogamp.opengl.util.Animator;
/**
* Documenting Bug 586
- *
+ *
* <p>
* JScrollPane cannot mix hw/lw components, only if setting property '-Dsun.awt.disableMixing=true'.
* </p>
@@ -40,100 +42,102 @@ import com.jogamp.opengl.util.Animator;
* </p>
* See git commit '8df12ca151dfc577c90b485d4ebfe491b88e55aa'.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestJScrollPaneMixHwLw01AWT extends UITestCase {
static long durationPerTest = 500;
-
+
static {
// too late: use at cmd-line '-Dsun.awt.disableMixing=true' works
// System.setProperty("sun.awt.disableMixing", "true");
}
/**
- * Doesn't work either ..
+ * Doesn't work either ..
*/
@SuppressWarnings("serial")
public static class TransparentJScrollPane extends JScrollPane {
- public TransparentJScrollPane(Component view) {
+ public TransparentJScrollPane(final Component view) {
super(view);
-
+
setOpaque(false);
-
+
try {
ReflectionUtil.callStaticMethod(
- "com.sun.awt.AWTUtilities", "setComponentMixingCutoutShape",
- new Class<?>[] { Component.class, Shape.class },
- new Object[] { this, new Rectangle() } ,
+ "com.sun.awt.AWTUtilities", "setComponentMixingCutoutShape",
+ new Class<?>[] { Component.class, Shape.class },
+ new Object[] { this, new Rectangle() } ,
GraphicsConfiguration.class.getClassLoader());
System.err.println("com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(..) passed");
- } catch (RuntimeException re) {
+ } catch (final RuntimeException re) {
System.err.println("com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(..) failed: "+re.getMessage());
}
}
-
+
@Override
- public void setOpaque(boolean isOpaque) {
+ public void setOpaque(final boolean isOpaque) {
}
}
-
- protected void runTestGL(GLCapabilities caps, boolean useJScroll) throws InterruptedException {
- final JFrame frame = new JFrame("Mix Hw/Lw Swing");
+
+ protected void runTestGL(final GLCapabilities caps, final boolean useJScroll) throws InterruptedException {
+ final String typeS = useJScroll ? "LW" : "HW";
+ final JFrame frame = new JFrame("Mix Hw/Lw Swing - ScrollPane "+typeS);
Assert.assertNotNull(frame);
-
+
final Dimension f_sz = new Dimension(600,400);
final Dimension glc_sz = new Dimension(500,600);
-
+
final GLCanvas glCanvas = new GLCanvas(caps);
- Assert.assertNotNull(glCanvas);
+ Assert.assertNotNull(glCanvas);
glCanvas.addGLEventListener(new GearsES2());
glCanvas.setPreferredSize(glc_sz);
-
- JPanel panel = new JPanel(new BorderLayout());
+
+ final JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(false);
if(useJScroll) {
- final JScrollPane scrollPane = new TransparentJScrollPane(glCanvas);
+ final JScrollPane scrollPane = new TransparentJScrollPane(glCanvas);
panel.add(scrollPane, BorderLayout.CENTER);
} else {
- ScrollPane scrollPane = new ScrollPane();
+ final ScrollPane scrollPane = new ScrollPane();
scrollPane.add(glCanvas);
panel.add(scrollPane, BorderLayout.CENTER);
}
-
- JTextArea textArea = new JTextArea();
+
+ final JTextArea textArea = new JTextArea();
textArea.setText("Test\nTest\nTest\nTest\n");
panel.add(textArea, BorderLayout.NORTH);
frame.add(panel);
- frame.setLocationRelativeTo(null);
- frame.setTitle("GLCanvas in JScrollPane example");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.setLocationRelativeTo(null);
+ frame.setTitle("GLCanvas in JScrollPane example");
frame.setSize(f_sz);
frame.setVisible(true);
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
- Animator animator = new Animator(glCanvas);
+ final Animator animator = new Animator(glCanvas);
animator.start();
Thread.sleep(durationPerTest);
animator.stop();
-
+
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.setVisible(false);
frame.dispose();
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
@@ -141,19 +145,19 @@ public class TestJScrollPaneMixHwLw01AWT extends UITestCase {
// @Test doesn't work
public void test01JScrollPane() throws InterruptedException {
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
runTestGL(caps, true);
}
@Test
public void test01ScrollPane() throws InterruptedException {
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
runTestGL(caps, false);
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
@@ -162,11 +166,11 @@ public class TestJScrollPaneMixHwLw01AWT extends UITestCase {
/**
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
- System.err.println(stdin.readLine());
+ System.err.println(stdin.readLine());
*/
System.out.println("durationPerTest: "+durationPerTest);
- String tstname = TestJScrollPaneMixHwLw01AWT.class.getName();
+ final String tstname = TestJScrollPaneMixHwLw01AWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
-
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestSwingAWT01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestSwingAWT01GLn.java
index 007df9f49..d24101270 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestSwingAWT01GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestSwingAWT01GLn.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.awt;
import java.lang.reflect.InvocationTargetException;
@@ -45,6 +45,8 @@ import javax.swing.JFrame;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import static org.junit.Assume.*;
import static javax.swing.SwingUtilities.*;
@@ -53,6 +55,7 @@ import static javax.swing.SwingUtilities.*;
* Tests context creation + display on various kinds of Window implementations.
* @author Michael Bien, et. al.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestSwingAWT01GLn extends UITestCase {
private Window[] windows;
@@ -80,7 +83,7 @@ public class TestSwingAWT01GLn extends UITestCase {
// final array as mutable container hack
final GLCanvas[] glCanvas = new GLCanvas[1];
- Runnable test = new Runnable() {
+ final Runnable test = new Runnable() {
public void run() {
glCanvas[0] = new GLCanvas(caps);
glCanvas[0].addGLEventListener(new GearsES2());
@@ -97,13 +100,13 @@ public class TestSwingAWT01GLn extends UITestCase {
}
};
- Runnable cleanup = new Runnable() {
+ final Runnable cleanup = new Runnable() {
public void run() {
System.out.println("cleaning up...");
window.setVisible(false);
try {
window.removeAll();
- } catch (Throwable t) {
+ } catch (final Throwable t) {
assumeNoException(t);
t.printStackTrace();
}
@@ -115,7 +118,7 @@ public class TestSwingAWT01GLn extends UITestCase {
// AWT / Swing on EDT..
invokeAndWait(test);
- Animator animator = new Animator(glCanvas[0]);
+ final Animator animator = new Animator(glCanvas[0]);
animator.start();
Thread.sleep(1000);
animator.stop();
@@ -127,10 +130,10 @@ public class TestSwingAWT01GLn extends UITestCase {
@Test
public void test01GLDefault() throws InterruptedException, InvocationTargetException {
- GLProfile glp = GLProfile.getDefault();
+ final GLProfile glp = GLProfile.getDefault();
System.out.println("GLProfile Default: "+glp);
if(glp.isGL2ES2()) {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
runTestGL(caps);
} else {
System.out.println("not a GL2ES2 profile");
@@ -140,16 +143,16 @@ public class TestSwingAWT01GLn extends UITestCase {
@Test
public void test02GL2() throws InterruptedException, InvocationTargetException {
if(GLProfile.isAvailable(GLProfile.GL2)) {
- GLProfile glprofile = GLProfile.get(GLProfile.GL2);
+ final GLProfile glprofile = GLProfile.get(GLProfile.GL2);
System.out.println( "GLProfile GL2: " + glprofile );
- GLCapabilities caps = new GLCapabilities(glprofile);
+ final GLCapabilities caps = new GLCapabilities(glprofile);
runTestGL(caps);
} else {
System.out.println("GL2 n/a");
}
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestSwingAWT01GLn.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java
index ab369a959..4b1da1e2e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.awt.text;
import javax.media.opengl.GLProfile;
@@ -37,7 +37,6 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
import java.awt.Frame;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
import org.junit.Assert;
import org.junit.Assume;
@@ -45,27 +44,30 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.After;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/*
* Unit tests for Bug464
- * Some ATI-Drivers crash the JVM if VBO-related glFunctions are called. This test checks
+ * Some ATI-Drivers crash the JVM if VBO-related glFunctions are called. This test checks
* if TextRenderer calls any of these functions while it's useVertexArray variable is set
* to false.
- * 2D- and 3D-TextRendering is tested by creating a GLCanvas showing a simple line of text
+ * 2D- and 3D-TextRendering is tested by creating a GLCanvas showing a simple line of text
* while filtering all glFunction calls by using a modified version of TraceGL2.
* VBO-related function are logged to the disallowedMethodCalls String of the GLEventListener
- * instead of being executed (to prevent JVM crashes). Therefore, if the
+ * instead of being executed (to prevent JVM crashes). Therefore, if the
* disallowedMethodCalls isn't an empty String after the test, the test fails.
- *
+ *
* Other classes related to this test:
* TestTextRendererGLEventListener01
* TestTextRendererTraceGL2Mock01
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestAWTTextRendererUseVertexArrayBug464 extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
-
+
private GLCanvas glCanvas;
private Frame frame;
@@ -84,9 +86,16 @@ public class TestAWTTextRendererUseVertexArrayBug464 extends UITestCase {
frame = new Frame("TextRenderer Test");
Assert.assertNotNull(frame);
frame.add(glCanvas);
- frame.setSize(512, 512);
- frame.setVisible(true);
-
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(512, 512);
+ frame.setVisible(true);
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
}
@After
@@ -98,10 +107,10 @@ public class TestAWTTextRendererUseVertexArrayBug464 extends UITestCase {
frame.remove(glCanvas);
frame.dispose();
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
glCanvas=null;
frame=null;
}
@@ -109,45 +118,45 @@ public class TestAWTTextRendererUseVertexArrayBug464 extends UITestCase {
@Test
public void testTextRendererDraw2D() throws InterruptedException {
- TextRendererGLEventListener01 listener = new TextRendererGLEventListener01(1);
+ final TextRendererGLEventListener01 listener = new TextRendererGLEventListener01(1);
Assert.assertNotNull(listener);
glCanvas.addGLEventListener(listener);
- Animator animator = new Animator(glCanvas);
+ final Animator animator = new Animator(glCanvas);
animator.start();
-
+
Thread.sleep(500); // 500 ms
-
+
animator.stop();
-
- String disallowedMethods = listener.getDisallowedMethodCalls();
+
+ final String disallowedMethods = listener.getDisallowedMethodCalls();
if (!disallowedMethods.equals("")) {
Assert.fail("Following VBO-related glMethods have been called: "+ disallowedMethods);
}
}
-
+
@Test
public void testTextRendererDraw3D() throws InterruptedException {
- TextRendererGLEventListener01 listener = new TextRendererGLEventListener01(2);
+ final TextRendererGLEventListener01 listener = new TextRendererGLEventListener01(2);
Assert.assertNotNull(listener);
glCanvas.addGLEventListener(listener);
- Animator animator = new Animator(glCanvas);
+ final Animator animator = new Animator(glCanvas);
animator.start();
-
+
Thread.sleep(500); // 500 ms
-
+
animator.stop();
-
- String disallowedMethods = listener.getDisallowedMethodCalls();
+
+ final String disallowedMethods = listener.getDisallowedMethodCalls();
if (!disallowedMethods.equals("")) {
Assert.fail("Following VBO-related glMethods have been called: "+ disallowedMethods);
}
}
- public static void main(String args[]) throws IOException {
- String tstname = TestAWTTextRendererUseVertexArrayBug464.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestAWTTextRendererUseVertexArrayBug464.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
@@ -159,5 +168,5 @@ public class TestAWTTextRendererUseVertexArrayBug464 extends UITestCase {
"logtestlistenerevents=true",
"formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
"formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TextRendererGLEventListener01.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TextRendererGLEventListener01.java
index c96684598..44089ff67 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TextRendererGLEventListener01.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TextRendererGLEventListener01.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.awt.text;
import java.awt.Font;
@@ -33,10 +33,12 @@ import java.io.OutputStream;
import java.io.PrintStream;
import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.media.opengl.GL2ES1;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;
import org.junit.Assert;
@@ -45,58 +47,58 @@ import org.junit.Assert;
* Unit tests for Bug464
* GLEventListener for unit test TestAWTTextRendererUseVertexArrayBug464. The display
* method renders the String "ABC123#+?" to the lower left corner of the canvas.
- *
+ *
* The testNumber variable is used to switch between 2D- and 3D-textrendering in the display
* method.
* The disallowedMethodCalls variable is used to log VBO-related glFunction calls during
* the execution of the test.
- *
+ *
* Other classes related to this test:
* TestAWTTextRendererUseVertexArrayBug464
* TextRendererTraceGL2Mock01
*/
public class TextRendererGLEventListener01 implements GLEventListener {
- private GLU glu = new GLU();
+ private final GLU glu = new GLU();
private TextRenderer renderer;
private String text;
private String disallowedMethodCalls;
- private int testNumber;
-
- public TextRendererGLEventListener01(int testNumber) {
+ private final int testNumber;
+
+ public TextRendererGLEventListener01(final int testNumber) {
this.disallowedMethodCalls = "";
this.testNumber = testNumber;
}
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
renderer = new TextRenderer(new Font("SansSerif", Font.BOLD, 36));
renderer.setUseVertexArrays(false);
Assert.assertNotNull(renderer);
Assert.assertFalse(renderer.getUseVertexArrays());
-
+
text = "ABC123#+?";
-
- PrintStream nullStream = new PrintStream(new OutputStream(){ public void write(int b){}});
+
+ final PrintStream nullStream = new PrintStream(new OutputStream(){ public void write(final int b){}});
drawable.setGL(new TextRendererTraceGL2Mock01(drawable.getGL().getGL2(), nullStream, this));
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- GL2 gl = drawable.getGL().getGL2();
- gl.glMatrixMode(GL2ES1.GL_PROJECTION);
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2 gl = drawable.getGL().getGL2();
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluOrtho2D(0, 1, 0, 1);
- gl.glMatrixMode(GL2ES1.GL_MODELVIEW);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
}
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
renderer.dispose();
}
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
if (disallowedMethodCalls.equals("")) {
if (testNumber == 1) {
- renderer.beginRendering(drawable.getWidth(), drawable.getHeight());
+ renderer.beginRendering(drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
renderer.setColor(1.0f, 1.0f, 1.0f, 1.0f);
renderer.draw(text, 0, 0);
renderer.endRendering();
@@ -109,14 +111,14 @@ public class TextRendererGLEventListener01 implements GLEventListener {
}
}
}
-
- public void disallowedMethodCalled (String method) {
+
+ public void disallowedMethodCalled (final String method) {
if (!disallowedMethodCalls.equals("")) {
disallowedMethodCalls += ", ";
}
disallowedMethodCalls += method;
}
-
+
public String getDisallowedMethodCalls() {
return this.disallowedMethodCalls;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TextRendererTraceGL2Mock01.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TextRendererTraceGL2Mock01.java
index 86714fcc5..3adcf9823 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TextRendererTraceGL2Mock01.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TextRendererTraceGL2Mock01.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -40,8 +40,8 @@ import com.jogamp.common.nio.Buffers;
/*
* Unit tests for Bug464
- * Modified Version of TraceGL2 for unit test TestAWTTextRendererUseVertexArrayBug464.
- * This class overrides all glFunctions related to VBO's according to
+ * Modified Version of TraceGL2 for unit test TestAWTTextRendererUseVertexArrayBug464.
+ * This class overrides all glFunctions related to VBO's according to
* http://code.google.com/p/glextensions/wiki/GL_ARB_vertex_buffer_object:
* glBindBuffer (glBindBufferARB)
* glDeleteBuffers (glDeleteBuffersARB)
@@ -56,81 +56,81 @@ import com.jogamp.common.nio.Buffers;
* glGetBufferPointerv (glGetBufferPointervARB)
* Calls to the overridden methods are logged to the disallowedMethodCalls variable of
* the GLEventListener instead of being passed to the downstreamGL object.
- *
+ *
* Other classes related to this test:
* TestAWTTextRendererUseVertexArrayBug464
* TextRendererGLEventListener01
*/
public class TextRendererTraceGL2Mock01 extends TraceGL2 {
-
+
TextRendererGLEventListener01 listener;
- public TextRendererTraceGL2Mock01(GL2 downstreamGL2, PrintStream stream, TextRendererGLEventListener01 listener) {
+ public TextRendererTraceGL2Mock01(final GL2 downstreamGL2, final PrintStream stream, final TextRendererGLEventListener01 listener) {
super(downstreamGL2, stream);
this.listener = listener;
- }
+ }
@Override
- public void glGetBufferSubData(int arg0, long arg1, long arg2, Buffer arg3) {
+ public void glGetBufferSubData(final int arg0, final long arg1, final long arg2, final Buffer arg3) {
listener.disallowedMethodCalled("glGetBufferSubData");
}
@Override
- public ByteBuffer glMapBuffer(int arg0, int arg1) {
+ public ByteBuffer glMapBuffer(final int arg0, final int arg1) {
listener.disallowedMethodCalled("glMapBuffer");
return Buffers.newDirectByteBuffer(0);
}
@Override
- public void glGetBufferParameteriv(int arg0, int arg1, IntBuffer arg2) {
+ public void glGetBufferParameteriv(final int arg0, final int arg1, final IntBuffer arg2) {
listener.disallowedMethodCalled("glGetBufferParameteriv");
}
@Override
- public boolean glUnmapBuffer(int arg0) {
+ public boolean glUnmapBuffer(final int arg0) {
listener.disallowedMethodCalled("glUnmapBuffer");
return false;
}
-
+
@Override
- public void glGenBuffers(int arg0, IntBuffer arg1) {
+ public void glGenBuffers(final int arg0, final IntBuffer arg1) {
listener.disallowedMethodCalled("glGenBuffers");
}
@Override
- public void glGenBuffers(int arg0, int[] arg1, int arg2) {
+ public void glGenBuffers(final int arg0, final int[] arg1, final int arg2) {
listener.disallowedMethodCalled("glGenBuffers");
}
@Override
- public boolean glIsBuffer(int arg0) {
+ public boolean glIsBuffer(final int arg0) {
listener.disallowedMethodCalled("glIsBuffer");
return false;
}
@Override
- public void glBindBuffer(int arg0, int arg1) {
+ public void glBindBuffer(final int arg0, final int arg1) {
listener.disallowedMethodCalled("glBindBuffer");
}
@Override
- public void glDeleteBuffers(int arg0, int[] arg1, int arg2) {
+ public void glDeleteBuffers(final int arg0, final int[] arg1, final int arg2) {
listener.disallowedMethodCalled("glDeleteBuffers");
}
@Override
- public void glBufferSubData(int arg0, long arg1, long arg2, Buffer arg3) {
+ public void glBufferSubData(final int arg0, final long arg1, final long arg2, final Buffer arg3) {
listener.disallowedMethodCalled("glBufferSubData");
}
@Override
- public void glGetBufferParameteriv(int arg0, int arg1, int[] arg2, int arg3) {
+ public void glGetBufferParameteriv(final int arg0, final int arg1, final int[] arg2, final int arg3) {
listener.disallowedMethodCalled("glGetBufferParameteriv");
}
@Override
- public void glBufferData(int arg0, long arg1, Buffer arg2, int arg3) {
+ public void glBufferData(final int arg0, final long arg1, final Buffer arg2, final int arg3) {
listener.disallowedMethodCalled("glBufferData");
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleChooser01.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleChooser01.java
index efdd2e16d..02265ad0b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleChooser01.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleChooser01.java
@@ -48,22 +48,22 @@ import javax.media.opengl.GLCapabilitiesImmutable;
class MultisampleChooser01 extends DefaultGLCapabilitiesChooser {
@Override
- public int chooseCapabilities(final CapabilitiesImmutable desired,
- final List<? extends CapabilitiesImmutable> available,
+ public int chooseCapabilities(final CapabilitiesImmutable desired,
+ final List<? extends CapabilitiesImmutable> available,
final int windowSystemRecommendedChoice) {
boolean anyHaveSampleBuffers = false;
for (int i = 0; i < available.size(); i++) {
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) available.get(i);
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) available.get(i);
if ( caps.getSampleBuffers() ) {
anyHaveSampleBuffers = true;
break;
}
}
- int selection = super.chooseCapabilities(desired, available, windowSystemRecommendedChoice);
+ final int selection = super.chooseCapabilities(desired, available, windowSystemRecommendedChoice);
if (!anyHaveSampleBuffers) {
System.err.println("WARNING: antialiasing will be disabled because none of the available pixel formats had it to offer");
} else {
- GLCapabilitiesImmutable selected = (GLCapabilitiesImmutable) available.get(selection);
+ final GLCapabilitiesImmutable selected = (GLCapabilitiesImmutable) available.get(selection);
if (!selected.getSampleBuffers()) {
System.err.println("WARNING: antialiasing will be disabled because the DefaultGLCapabilitiesChooser didn't supply it");
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java
new file mode 100644
index 000000000..c1b29b371
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java
@@ -0,0 +1,190 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.caps;
+
+import java.io.File;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+import java.awt.image.BufferedImage;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug605FlippedImageAWT extends UITestCase {
+ class FlippedImageTest implements GLEventListener {
+ AWTGLReadBufferUtil screenshot;
+
+ public void display(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
+
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT | GL2.GL_ACCUM_BUFFER_BIT );
+
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+
+ // red below
+ gl.glColor3f(1, 0, 0);
+ gl.glRectf(-1, -1, 1, 0);
+
+ // green above
+ gl.glColor3f(0, 1, 0);
+ gl.glRectf(-1, 0, 1, 1);
+ gl.glFinish();
+
+ final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
+ if(caps.getAccumGreenBits() > 0) {
+ gl.glAccum(GL2.GL_ACCUM, 1.0f);
+ gl.glAccum(GL2.GL_RETURN, 1.0f);
+ }
+ gl.glFinish();
+
+ final int width = drawable.getSurfaceWidth();
+ final int height = drawable.getSurfaceHeight();
+
+ final String fname = getSnapshotFilename(0, null, caps, width, height, false, TextureIO.PNG, null);
+ final BufferedImage image;
+ try {
+ image = screenshot.readPixelsToBufferedImage(gl, 0, 0, width, height, true /* awtOrientation */);
+ screenshot.write(new File(fname));
+ } catch (final GLException e) {
+ throw e;
+ }
+ testFlipped(image, width, height);
+ }
+
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println("GL_RENDERER: "+gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: "+gl.glGetString(GL.GL_VERSION));
+ screenshot = new AWTGLReadBufferUtil(drawable.getGLProfile(), false);
+ }
+ public void reshape(final GLAutoDrawable glDrawable, final int x, final int y, final int w, final int h) {}
+ public void displayChanged(final GLAutoDrawable drawable, final boolean modeChanged, final boolean deviceChanged) {}
+ public void dispose(final GLAutoDrawable drawable) {
+ screenshot.dispose(drawable.getGL());
+ }
+ }
+
+ static final int green = 0x0000ff00; // above
+ static final int red = 0x00ff0000; // below
+
+ private void testFlipped(final BufferedImage image, final int width, final int height) {
+ // Default origin 0/0 is lower left corner, so is the memory layout
+ // However AWT origin 0/0 is upper left corner
+ final int below = image.getRGB(0, height-1) & 0x00ffffff;
+ System.err.println("below: 0x"+Integer.toHexString(below));
+
+ final int above = image.getRGB(0, 0) & 0x00ffffff;
+ System.err.println("above: 0x"+Integer.toHexString(above));
+
+ if (above == green && below == red) {
+ System.out.println("Image right side up");
+ } else if (above == red && below == green) {
+ Assert.assertTrue("Image is flipped", false);
+ } else {
+ Assert.assertTrue("Error in test", false);
+ }
+ }
+
+ private void test(final GLCapabilitiesImmutable caps) {
+
+ final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLAutoDrawable glad = glFactory.createOffscreenAutoDrawable(null, caps, null, 256, 256);
+ final FlippedImageTest tglel = new FlippedImageTest();
+ glad.addGLEventListener(tglel);
+
+ // 1 frame incl. snapshot to memory & file
+ glad.display();
+ System.err.println("XXX "+glad.getChosenGLCapabilities());
+ System.err.println("XXX "+glad.getContext().getGLVersion());
+
+ glad.destroy();
+ }
+
+ @Test
+ public void test01DefaultFBO() {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setFBO(true);
+ test(caps);
+ }
+
+ @Test
+ public void test01StencilFBO() {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setStencilBits(8);
+ caps.setFBO(true);
+ test(caps);
+ }
+
+ @Test
+ public void test01DefaultPBuffer() {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setPBuffer(true);
+ test(caps);
+ }
+
+ @Test
+ public void test01AccumStencilPBuffer() {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAccumRedBits(16);
+ caps.setAccumGreenBits(16);
+ caps.setAccumBlueBits(16);
+ caps.setStencilBits(8);
+ caps.setPBuffer(true);
+ test(caps);
+ }
+
+ public static void main(final String[] args) {
+ org.junit.runner.JUnitCore.main(TestBug605FlippedImageAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java
new file mode 100644
index 000000000..2d879a6be
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java
@@ -0,0 +1,179 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.caps;
+
+import java.nio.ByteBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug605FlippedImageNEWT extends UITestCase {
+ static class FlippedImageTest implements GLEventListener {
+ public void display(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
+
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT | GL2.GL_ACCUM_BUFFER_BIT );
+
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+
+ // red below
+ gl.glColor3f(1, 0, 0);
+ gl.glRectf(-1, -1, 1, 0);
+
+ // green above
+ gl.glColor3f(0, 1, 0);
+ gl.glRectf(-1, 0, 1, 1);
+ gl.glFinish();
+
+ final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
+ if(caps.getAccumGreenBits() > 0) {
+ gl.glAccum(GL2.GL_ACCUM, 1.0f);
+ gl.glAccum(GL2.GL_RETURN, 1.0f);
+ }
+ gl.glFinish();
+ }
+
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println("GL_RENDERER: "+gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: "+gl.glGetString(GL.GL_VERSION));
+ }
+ public void reshape(final GLAutoDrawable glDrawable, final int x, final int y, final int w, final int h) {}
+ public void displayChanged(final GLAutoDrawable drawable, final boolean modeChanged, final boolean deviceChanged) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ }
+
+ static final int green = 0x0000ff00; // above
+ static final int red = 0x00ff0000; // below
+
+ private int getRGB(final ByteBuffer bb, final int o) {
+ return ( bb.get(o+0) & 0x000000ff ) << 16 |
+ ( bb.get(o+1) & 0x000000ff ) << 8 |
+ ( bb.get(o+2) & 0x000000ff );
+ }
+
+ private void testFlipped(final ByteBuffer bb, final int width, final int height, final int comp) {
+ // Default origin 0/0 is lower left corner, so is the memory layout
+
+ // x=0, y=0: RGB -> _RGB [high-byte .. low-byte]
+ final int below = getRGB(bb, 0);
+ System.err.println("below: 0x"+Integer.toHexString(below));
+
+ // x=0, y=height-1: RGB -> _RGB [high-byte .. low-byte]
+ final int above= getRGB(bb, ( height - 1 ) * ( width * comp ));
+ System.err.println("above: 0x"+Integer.toHexString(above));
+
+ if (above == green && below == red) {
+ System.out.println("Image right side up");
+ } else if (above == red && below == green) {
+ Assert.assertTrue("Image is flipped", false);
+ } else {
+ Assert.assertTrue("Error in test", false);
+ }
+ }
+
+ private void test(final GLCapabilitiesImmutable caps) {
+ final GLReadBufferUtil rbu = new GLReadBufferUtil(false, false);
+ final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLAutoDrawable glad = glFactory.createOffscreenAutoDrawable(null, caps, null, 256, 256);
+ final FlippedImageTest tglel = new FlippedImageTest();
+ glad.addGLEventListener(tglel);
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener(rbu);
+ glad.addGLEventListener(snap);
+ snap.setMakeSnapshotAlways(true);
+
+ // 1 frame incl. snapshot to memory & file
+ glad.display();
+ System.err.println("XXX "+glad.getChosenGLCapabilities());
+ System.err.println("XXX "+glad.getContext().getGLVersion());
+ testFlipped((ByteBuffer)rbu.getPixelBuffer().buffer, glad.getSurfaceWidth(), glad.getSurfaceHeight(), 3);
+
+ glad.destroy();
+ }
+
+ @Test
+ public void test01DefaultFBO() {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setFBO(true);
+ test(caps);
+ }
+
+ @Test
+ public void test01StencilFBO() {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setStencilBits(8);
+ caps.setFBO(true);
+ test(caps);
+ }
+
+ @Test
+ public void test01DefaultPBuffer() {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setPBuffer(true);
+ test(caps);
+ }
+
+ @Test
+ public void test01AccumStencilPBuffer() {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAccumRedBits(16);
+ caps.setAccumGreenBits(16);
+ caps.setAccumBlueBits(16);
+ caps.setStencilBits(8);
+ caps.setPBuffer(true);
+ test(caps);
+ }
+
+ public static void main(final String[] args) {
+ org.junit.runner.JUnitCore.main(TestBug605FlippedImageNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java
index c5bdfb5f3..7ae9e859a 100755..100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -58,20 +58,23 @@ import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.texture.TextureIO;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestMultisampleES1AWT extends UITestCase {
static long durationPerTest = 60; // ms
private GLCanvas canvas;
- public static void main(String[] args) {
+ public static void main(final String[] args) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = MiscUtils.atoi(args[++i], 500);
}
}
System.out.println("durationPerTest: "+durationPerTest);
- String tstname = TestMultisampleES1AWT.class.getName();
+ final String tstname = TestMultisampleES1AWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
@@ -90,37 +93,37 @@ public class TestMultisampleES1AWT extends UITestCase {
testMultiSampleAAImpl(8);
}
- private void testMultiSampleAAImpl(int reqSamples) throws InterruptedException, InvocationTargetException {
+ private void testMultiSampleAAImpl(final int reqSamples) throws InterruptedException, InvocationTargetException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
- GLProfile glp = GLProfile.getMaxFixedFunc(true);
- GLCapabilities caps = new GLCapabilities(glp);
- GLCapabilitiesChooser chooser = new MultisampleChooser01();
+ final GLProfile glp = GLProfile.getMaxFixedFunc(true);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilitiesChooser chooser = new MultisampleChooser01();
if(reqSamples>0) {
caps.setSampleBuffers(true);
caps.setNumSamples(reqSamples);
}
- canvas = new GLCanvas(caps, chooser, null, null);
+ canvas = new GLCanvas(caps, chooser, null);
canvas.addGLEventListener(new MultisampleDemoES1(reqSamples>0?true:false));
canvas.addGLEventListener(new GLEventListener() {
int displayCount = 0;
- public void init(GLAutoDrawable drawable) {}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
-
+
final Frame frame = new Frame("Multi Samples "+reqSamples);
frame.setLayout(new BorderLayout());
canvas.setSize(512, 512);
- frame.add(canvas, BorderLayout.CENTER);
- frame.pack();
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.add(canvas, BorderLayout.CENTER);
+ frame.pack();
frame.setVisible(true);
canvas.requestFocus();
canvas.display();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java
index 5bbd6737c..4996f786d 100755..100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -47,6 +47,8 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es1.MultisampleDemoES1;
@@ -55,71 +57,72 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.texture.TextureIO;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestMultisampleES1NEWT extends UITestCase {
static long durationPerTest = 60; // ms
private GLWindow window;
- public static void main(String[] args) {
+ public static void main(final String[] args) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = MiscUtils.atoi(args[++i], 500);
}
}
System.out.println("durationPerTest: "+durationPerTest);
- String tstname = TestMultisampleES1NEWT.class.getName();
+ final String tstname = TestMultisampleES1NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
@Test
public void testOnscreenMultiSampleAA0() throws InterruptedException {
- testMultiSampleAAImpl(true, 0);
+ testMultiSampleAAImpl(false, false, 0);
}
@Test
public void testOnscreenMultiSampleAA2() throws InterruptedException {
- testMultiSampleAAImpl(true, 2);
+ testMultiSampleAAImpl(false, false, 2);
}
@Test
public void testOnscreenMultiSampleAA4() throws InterruptedException {
- testMultiSampleAAImpl(true, 4);
+ testMultiSampleAAImpl(false, false, 4);
}
@Test
public void testOnscreenMultiSampleAA8() throws InterruptedException {
- testMultiSampleAAImpl(true, 8);
+ testMultiSampleAAImpl(false, false, 8);
}
@Test
- public void testOffscreenMultiSampleAA0() throws InterruptedException {
- testMultiSampleAAImpl(false, 0);
+ public void testOffscreenPBufferMultiSampleAA0() throws InterruptedException {
+ testMultiSampleAAImpl(false, true, 0);
}
@Test
- public void testOffscreenMultiSampleAA2() throws InterruptedException {
- testMultiSampleAAImpl(false, 2);
+ public void testOffsreenPBufferMultiSampleAA8() throws InterruptedException {
+ testMultiSampleAAImpl(false, true, 8);
}
@Test
- public void testOffscreenMultiSampleAA4() throws InterruptedException {
- testMultiSampleAAImpl(false, 4);
+ public void testOffscreenFBOMultiSampleAA0() throws InterruptedException {
+ testMultiSampleAAImpl(true, false, 0);
}
@Test
- public void testOffsreenMultiSampleAA8() throws InterruptedException {
- testMultiSampleAAImpl(false, 8);
+ public void testOffsreenFBOMultiSampleAA8() throws InterruptedException {
+ testMultiSampleAAImpl(true, false, 8);
}
- private void testMultiSampleAAImpl(boolean onscreen, int reqSamples) throws InterruptedException {
+ private void testMultiSampleAAImpl(final boolean useFBO, final boolean usePBuffer, final int reqSamples) throws InterruptedException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
- GLProfile glp = GLProfile.getMaxFixedFunc(true);
- GLCapabilities caps = new GLCapabilities(glp);
- GLCapabilitiesChooser chooser = new MultisampleChooser01();
+ final GLProfile glp = GLProfile.getMaxFixedFunc(true);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilitiesChooser chooser = new MultisampleChooser01();
+
+ caps.setAlphaBits(1);
+ caps.setFBO(useFBO);
+ caps.setPBuffer(usePBuffer);
- if(!onscreen) {
- caps.setOnscreen(onscreen);
- caps.setPBuffer(true);
- }
if(reqSamples>0) {
caps.setSampleBuffers(true);
caps.setNumSamples(reqSamples);
@@ -130,12 +133,12 @@ public class TestMultisampleES1NEWT extends UITestCase {
window.addGLEventListener(new MultisampleDemoES1(reqSamples>0?true:false));
window.addGLEventListener(new GLEventListener() {
int displayCount = 0;
- public void init(GLAutoDrawable drawable) {}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
window.setSize(512, 512);
window.setVisible(true);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java
index c2e3215ae..148e107e3 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -47,6 +47,8 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
@@ -55,17 +57,18 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.texture.TextureIO;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestMultisampleES2NEWT extends UITestCase {
static long durationPerTest = 60; // ms
- public static void main(String[] args) {
+ public static void main(final String[] args) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = MiscUtils.atoi(args[++i], 500);
}
}
System.out.println("durationPerTest: "+durationPerTest);
- String tstname = TestMultisampleES2NEWT.class.getName();
+ final String tstname = TestMultisampleES2NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
@@ -84,35 +87,31 @@ public class TestMultisampleES2NEWT extends UITestCase {
testMultiSampleAAImpl(false, true, 0);
}
- @Test(timeout = 3000) // 3s timeout
+ @Test(timeout = 10000)
public void testOffsreenPBufferMultiSampleAA8() throws InterruptedException {
testMultiSampleAAImpl(false, true, 8);
}
- @Test(timeout = 3000) // 3s timeout
+ @Test(timeout = 10000)
public void testOffscreenFBOMultiSampleAA0() throws InterruptedException {
testMultiSampleAAImpl(true, false, 0);
}
- @Test(timeout = 3000) // 3s timeout
+ @Test(timeout = 10000)
public void testOffsreenFBOMultiSampleAA8() throws InterruptedException {
testMultiSampleAAImpl(true, false, 8);
}
- private void testMultiSampleAAImpl(boolean useFBO, boolean usePBuffer, int reqSamples) throws InterruptedException {
- if(useFBO) {
- System.err.println("NEWT offscreen FBO Window n/a yet");
- return;
- }
+ private void testMultiSampleAAImpl(final boolean useFBO, final boolean usePBuffer, final int reqSamples) throws InterruptedException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
- GLCapabilitiesChooser chooser = new MultisampleChooser01();
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilitiesChooser chooser = new MultisampleChooser01();
caps.setAlphaBits(1);
caps.setFBO(useFBO);
caps.setPBuffer(usePBuffer);
-
+
if(reqSamples>0) {
caps.setSampleBuffers(true);
caps.setNumSamples(reqSamples);
@@ -123,12 +122,12 @@ public class TestMultisampleES2NEWT extends UITestCase {
window.addGLEventListener(new MultisampleDemoES2(reqSamples>0?true:false));
window.addGLEventListener(new GLEventListener() {
int displayCount = 0;
- public void init(GLAutoDrawable drawable) {}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
window.setSize(512, 512);
window.setVisible(true);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java
index 7cce5d1e4..521d9c2fe 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.caps;
import java.awt.BorderLayout;
@@ -50,12 +50,15 @@ import javax.media.opengl.awt.GLCanvas;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTranslucencyAWT extends UITestCase {
static Dimension size;
static long durationPerTest = 400;
@@ -70,23 +73,23 @@ public class TestTranslucencyAWT extends UITestCase {
static Frame getTranslucentFrame() {
GraphicsConfiguration gc=null;
- GraphicsDevice[] devices= GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
+ final GraphicsDevice[] devices= GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
for (int i = 0; i < devices.length ; i++)
{
- GraphicsConfiguration[] configs = devices[i].getConfigurations();
+ final GraphicsConfiguration[] configs = devices[i].getConfigurations();
for (int j = 0; j < configs.length ; j++) {
- GraphicsConfiguration config = configs[j];
- ColorModel tcm = config.getColorModel(Transparency.TRANSLUCENT);
- boolean capable1 = ( null != tcm ) ? tcm.getTransparency() == Transparency.TRANSLUCENT : false;
+ final GraphicsConfiguration config = configs[j];
+ final ColorModel tcm = config.getColorModel(Transparency.TRANSLUCENT);
+ final boolean capable1 = ( null != tcm ) ? tcm.getTransparency() == Transparency.TRANSLUCENT : false;
boolean capable2 = false;
try {
capable2 = ((Boolean)ReflectionUtil.callStaticMethod(
- "com.sun.awt.AWTUtilities", "isTranslucencyCapable",
- new Class<?>[] { GraphicsConfiguration.class },
- new Object[] { config } ,
+ "com.sun.awt.AWTUtilities", "isTranslucencyCapable",
+ new Class<?>[] { GraphicsConfiguration.class },
+ new Object[] { config } ,
GraphicsConfiguration.class.getClassLoader())).booleanValue();
System.err.println("com.sun.awt.AWTUtilities.isTranslucencyCapable(config) passed: "+capable2);
- } catch (RuntimeException re) {
+ } catch (final RuntimeException re) {
System.err.println("com.sun.awt.AWTUtilities.isTranslucencyCapable(config) failed: "+re.getMessage());
}
System.err.println(i+":"+j+" "+config+", "+tcm+", capable "+capable1+"/"+capable2);
@@ -105,32 +108,35 @@ public class TestTranslucencyAWT extends UITestCase {
frame.setTitle("AWT Parent Frame (opaque: "+(null==gc)+")");
return frame;
}
-
+
@Test
public void test() throws InterruptedException, InvocationTargetException {
final Frame frame1 = getTranslucentFrame();
final GLCanvas glCanvas= new GLCanvas(glCaps);
-
+
glCanvas.setPreferredSize(size);
- GLEventListener demo1 = new GearsES2(1);
+ final GLEventListener demo1 = new GearsES2(1);
// setDemoFields(demo1, glCanvas, false);
glCanvas.addGLEventListener(demo1);
- GLAnimatorControl animator1 = new Animator(glCanvas);
+ final GLAnimatorControl animator1 = new Animator(glCanvas);
animator1.start();
- Container cont1 = new Container();
+ final Container cont1 = new Container();
cont1.setLayout(new BorderLayout());
cont1.add(glCanvas, BorderLayout.CENTER);
- cont1.setVisible(true);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ cont1.setVisible(true);
+ }});
frame1.setLayout(new BorderLayout());
frame1.add(cont1, BorderLayout.EAST);
frame1.add(new Label("center"), BorderLayout.CENTER);
- frame1.setLocation(0, 0);
- frame1.setSize((int)size.getWidth(), (int)size.getHeight());
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame1.setLocation(0, 0);
+ frame1.setSize((int)size.getWidth(), (int)size.getHeight());
frame1.pack();
frame1.setVisible(true);
}});
@@ -149,21 +155,21 @@ public class TestTranslucencyAWT extends UITestCase {
frame1.dispose();
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
- String tstname = TestTranslucencyAWT.class.getName();
+ final String tstname = TestTranslucencyAWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java
index 67e8524a3..10ac9417a 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,22 +20,21 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.caps;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
-
import com.jogamp.opengl.util.Animator;
-
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import javax.media.opengl.GLCapabilities;
@@ -45,7 +44,10 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTranslucencyNEWT extends UITestCase {
static GLProfile glp;
static int width, height;
@@ -57,7 +59,7 @@ public class TestTranslucencyNEWT extends UITestCase {
glp = GLProfile.get(GLProfile.getDefaultEGLDevice(), GLProfile.GLES2);
} else */ {
// default device, somehow ES2 compatible
- glp = GLProfile.getGL2ES2();
+ glp = GLProfile.getGL2ES2();
}
Assert.assertNotNull(glp);
width = 512;
@@ -68,15 +70,15 @@ public class TestTranslucencyNEWT extends UITestCase {
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilities caps, boolean undecorated) throws InterruptedException {
- GLWindow glWindow = GLWindow.create(caps);
+ protected void runTestGL(final GLCapabilities caps, final boolean undecorated) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+")");
glWindow.setUndecorated(undecorated);
glWindow.addGLEventListener(new GearsES2());
- Animator animator = new Animator(glWindow);
- QuitAdapter quitAdapter = new QuitAdapter();
+ final Animator animator = new Animator(glWindow);
+ final QuitAdapter quitAdapter = new QuitAdapter();
//glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
//glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
@@ -85,7 +87,10 @@ public class TestTranslucencyNEWT extends UITestCase {
final GLWindow f_glWindow = glWindow;
glWindow.addKeyListener(new KeyAdapter() {
- public void keyTyped(KeyEvent e) {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
if(e.getKeyChar()=='f') {
new Thread() {
public void run() {
@@ -115,40 +120,45 @@ public class TestTranslucencyNEWT extends UITestCase {
@Test
public void test01OpaqueDecorated() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
caps.setBackgroundOpaque(true); // default
runTestGL(caps, false);
}
@Test
public void test01TransparentDecorated() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
caps.setBackgroundOpaque(false);
// This is done implicit now ..
- // caps.setAlphaBits(1);
+ // caps.setAlphaBits(1);
runTestGL(caps, false);
}
@Test
public void test01TransparentUndecorated() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
caps.setBackgroundOpaque(false);
// This is done implicit now ..
- // caps.setAlphaBits(1);
+ // caps.setAlphaBits(1);
runTestGL(caps, true);
}
-
+
static long duration = 500; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
+ boolean waitForKey = false;
+
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
- try {
- duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
}
}
+ if( waitForKey ) {
+ UITestCase.waitForKey("main");
+ }
org.junit.runner.JUnitCore.main(TestTranslucencyNEWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/GLFinishOnDisplay.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GLFinishOnDisplay.java
new file mode 100644
index 000000000..b59cddc71
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GLFinishOnDisplay.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+
+public class GLFinishOnDisplay implements GLEventListener {
+ @Override
+ public void init(final GLAutoDrawable drawable) { }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) { }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ drawable.getGL().glFinish();
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java
index b098e1de9..01cc4b7f2 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java
@@ -7,10 +7,10 @@
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -36,7 +36,8 @@ public abstract class GearsObject {
public static final FloatBuffer green = Buffers.newDirectFloatBuffer( new float[] { 0.0f, 0.8f, 0.2f, 0.7f } );
public static final FloatBuffer blue = Buffers.newDirectFloatBuffer( new float[] { 0.2f, 0.2f, 1.0f, 0.7f } );
public static final float M_PI = (float)Math.PI;
-
+
+ public final FloatBuffer gearColor;
public GLArrayDataServer frontFace;
public GLArrayDataServer frontSide;
public GLArrayDataServer backFace;
@@ -44,12 +45,24 @@ public abstract class GearsObject {
public GLArrayDataServer outwardFace;
public GLArrayDataServer insideRadiusCyl;
public boolean isShared;
+ protected boolean validateBuffers = false;
- public abstract GLArrayDataServer createInterleaved(int comps, int dataType, boolean normalized, int initialSize, int vboUsage);
+ public abstract GLArrayDataServer createInterleaved(boolean useMappedBuffers, int comps, int dataType, boolean normalized, int initialSize, int vboUsage);
public abstract void addInterleavedVertexAndNormalArrays(GLArrayDataServer array, int components);
- public abstract void draw(GL gl, float x, float y, float angle, FloatBuffer color);
-
- public void destroy(GL gl) {
+ public abstract void draw(GL gl, float x, float y, float angle);
+
+ private GLArrayDataServer createInterleavedClone(final GLArrayDataServer ads) {
+ final GLArrayDataServer n = new GLArrayDataServer(ads);
+ n.setInterleavedOffset(0);
+ return n;
+ }
+
+ private void init(final GL gl, final GLArrayDataServer array) {
+ array.enableBuffer(gl, true);
+ array.enableBuffer(gl, false);
+ }
+
+ public void destroy(final GL gl) {
if(!isShared) {
// could be already destroyed by shared configuration
if(null != frontFace) {
@@ -76,39 +89,50 @@ public abstract class GearsObject {
backFace=null;
backSide=null;
outwardFace=null;
- insideRadiusCyl=null;
+ insideRadiusCyl=null;
isShared = false;
}
-
- public GearsObject ( GearsObject shared ) {
+
+ public GearsObject ( final GearsObject shared ) {
isShared = true;
- frontFace = shared.frontFace;
- frontSide = shared.frontSide;
- backFace = shared.backFace;
- backSide = shared.backSide;
- outwardFace = shared.outwardFace;
- insideRadiusCyl = shared.insideRadiusCyl;
+ validateBuffers = shared.validateBuffers;
+ frontFace = createInterleavedClone(shared.frontFace);
+ addInterleavedVertexAndNormalArrays(frontFace, 3);
+ backFace = createInterleavedClone(shared.backFace);
+ addInterleavedVertexAndNormalArrays(backFace, 3);
+ frontSide = createInterleavedClone(shared.frontSide);
+ addInterleavedVertexAndNormalArrays(frontSide, 3);
+ backSide= createInterleavedClone(shared.backSide);
+ addInterleavedVertexAndNormalArrays(backSide, 3);
+ outwardFace = createInterleavedClone(shared.outwardFace);
+ addInterleavedVertexAndNormalArrays(outwardFace, 3);
+ insideRadiusCyl = createInterleavedClone(shared.insideRadiusCyl);
+ addInterleavedVertexAndNormalArrays(insideRadiusCyl, 3);
+ gearColor = shared.gearColor;
}
-
+
public GearsObject (
- float inner_radius,
- float outer_radius,
- float width,
- int teeth,
- float tooth_depth)
+ final GL gl,
+ final boolean useMappedBuffers,
+ final FloatBuffer gearColor,
+ final float inner_radius,
+ final float outer_radius,
+ final float width, final int teeth, final float tooth_depth, final boolean validateBuffers)
{
- final float dz = width * 0.5f;
+ final float dz = width * 0.5f;
int i;
float r0, r1, r2;
float angle, da;
float u, v, len;
- float s[] = new float[5];
- float c[] = new float[5];
- float normal[] = new float[3];
+ final float s[] = new float[5];
+ final float c[] = new float[5];
+ final float normal[] = new float[3];
// final int tris_per_tooth = 32;
- isShared = false;
-
+ this.validateBuffers = validateBuffers;
+ this.isShared = false;
+ this.gearColor = gearColor;
+
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0f;
r2 = outer_radius + tooth_depth / 2.0f;
@@ -118,64 +142,75 @@ public abstract class GearsObject {
s[4] = 0; // sin(0f)
c[4] = 1; // cos(0f)
- frontFace = createInterleaved(6, GL.GL_FLOAT, false, 4*teeth+2, GL.GL_STATIC_DRAW);
+ final int vboUsage = GL.GL_STATIC_DRAW;
+
+ frontFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage);
addInterleavedVertexAndNormalArrays(frontFace, 3);
- backFace = createInterleaved(6, GL.GL_FLOAT, false, 4*teeth+2, GL.GL_STATIC_DRAW);
+ backFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage);
addInterleavedVertexAndNormalArrays(backFace, 3);
- frontSide = createInterleaved(6, GL.GL_FLOAT, false, 6*teeth, GL.GL_STATIC_DRAW);
+ frontSide = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 6*teeth, vboUsage);
addInterleavedVertexAndNormalArrays(frontSide, 3);
- backSide = createInterleaved(6, GL.GL_FLOAT, false, 6*teeth, GL.GL_STATIC_DRAW);
+ backSide = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 6*teeth, vboUsage);
addInterleavedVertexAndNormalArrays(backSide, 3);
- outwardFace = createInterleaved(6, GL.GL_FLOAT, false, 4*4*teeth+2, GL.GL_STATIC_DRAW);
+ outwardFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*4*teeth+2, vboUsage);
addInterleavedVertexAndNormalArrays(outwardFace, 3);
- insideRadiusCyl = createInterleaved(6, GL.GL_FLOAT, false, 2*teeth+2, GL.GL_STATIC_DRAW);
+ insideRadiusCyl = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 2*teeth+2, vboUsage);
addInterleavedVertexAndNormalArrays(insideRadiusCyl, 3);
+ if( useMappedBuffers ) {
+ frontFace.mapStorage(gl, GL.GL_WRITE_ONLY);
+ backFace.mapStorage(gl, GL.GL_WRITE_ONLY);
+ frontSide.mapStorage(gl, GL.GL_WRITE_ONLY);
+ backSide.mapStorage(gl, GL.GL_WRITE_ONLY);
+ outwardFace.mapStorage(gl, GL.GL_WRITE_ONLY);
+ insideRadiusCyl.mapStorage(gl, GL.GL_WRITE_ONLY);
+ }
+
for (i = 0; i < teeth; i++) {
angle = i * 2.0f * M_PI / teeth;
sincos(angle + da * 0f, s, 0, c, 0);
sincos(angle + da * 1f, s, 1, c, 1);
sincos(angle + da * 2f, s, 2, c, 2);
sincos(angle + da * 3f, s, 3, c, 3);
-
+
/* front */
normal[0] = 0.0f;
normal[1] = 0.0f;
normal[2] = 1.0f;
-
+
/* front face - GL.GL_TRIANGLE_STRIP */
vert(frontFace, r0 * c[0], r0 * s[0], dz, normal);
vert(frontFace, r1 * c[0], r1 * s[0], dz, normal);
vert(frontFace, r0 * c[0], r0 * s[0], dz, normal);
vert(frontFace, r1 * c[3], r1 * s[3], dz, normal);
-
+
/* front sides of teeth - GL.GL_TRIANGLES */
vert(frontSide, r1 * c[0], r1 * s[0], dz, normal);
- vert(frontSide, r2 * c[1], r2 * s[1], dz, normal);
+ vert(frontSide, r2 * c[1], r2 * s[1], dz, normal);
vert(frontSide, r2 * c[2], r2 * s[2], dz, normal);
vert(frontSide, r1 * c[0], r1 * s[0], dz, normal);
- vert(frontSide, r2 * c[2], r2 * s[2], dz, normal);
+ vert(frontSide, r2 * c[2], r2 * s[2], dz, normal);
vert(frontSide, r1 * c[3], r1 * s[3], dz, normal);
-
+
/* back */
normal[0] = 0.0f;
normal[1] = 0.0f;
normal[2] = -1.0f;
-
+
/* back face - GL.GL_TRIANGLE_STRIP */
vert(backFace, r1 * c[0], r1 * s[0], -dz, normal);
vert(backFace, r0 * c[0], r0 * s[0], -dz, normal);
vert(backFace, r1 * c[3], r1 * s[3], -dz, normal);
vert(backFace, r0 * c[0], r0 * s[0], -dz, normal);
-
+
/* back sides of teeth - GL.GL_TRIANGLES*/
vert(backSide, r1 * c[3], r1 * s[3], -dz, normal);
vert(backSide, r2 * c[2], r2 * s[2], -dz, normal);
vert(backSide, r2 * c[1], r2 * s[1], -dz, normal);
vert(backSide, r1 * c[3], r1 * s[3], -dz, normal);
- vert(backSide, r2 * c[1], r2 * s[1], -dz, normal);
+ vert(backSide, r2 * c[1], r2 * s[1], -dz, normal);
vert(backSide, r1 * c[0], r1 * s[0], -dz, normal);
-
+
/* outward faces of teeth */
u = r2 * c[1] - r1 * c[0];
v = r2 * s[1] - r1 * s[0];
@@ -201,7 +236,7 @@ public abstract class GearsObject {
normal[0] = ( r1 * s[3] - r2 * s[2] );
normal[1] = ( r1 * c[3] - r2 * c[2] ) * -1.0f ;
vert(outwardFace, r2 * c[2], r2 * s[2], dz, normal);
- vert(outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
+ vert(outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
vert(outwardFace, r1 * c[3], r1 * s[3], dz, normal);
vert(outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
@@ -211,7 +246,7 @@ public abstract class GearsObject {
vert(outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
vert(outwardFace, r1 * c[0], r1 * s[0], dz, normal);
vert(outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
-
+
/* inside radius cylinder */
normal[0] = c[0] * -1.0f;
normal[1] = s[0] * -1.0f;
@@ -226,16 +261,16 @@ public abstract class GearsObject {
vert(frontFace, r0 * c[4], r0 * s[4], dz, normal);
vert(frontFace, r1 * c[4], r1 * s[4], dz, normal);
frontFace.seal(true);
-
+
/* finish back face */
- normal[2] = -1.0f;
+ normal[2] = -1.0f;
vert(backFace, r1 * c[4], r1 * s[4], -dz, normal);
vert(backFace, r0 * c[4], r0 * s[4], -dz, normal);
backFace.seal(true);
-
+
backSide.seal(true);
frontSide.seal(true);
-
+
/* finish outward face */
sincos(da * 1f, s, 1, c, 1);
u = r2 * c[1] - r1 * c[4];
@@ -247,7 +282,7 @@ public abstract class GearsObject {
normal[1] = -u;
normal[2] = 0.0f;
vert(outwardFace, r1 * c[4], r1 * s[4], dz, normal);
- vert(outwardFace, r1 * c[4], r1 * s[4], -dz, normal);
+ vert(outwardFace, r1 * c[4], r1 * s[4], -dz, normal);
outwardFace.seal(true);
/* finish inside radius cylinder */
@@ -257,9 +292,35 @@ public abstract class GearsObject {
vert(insideRadiusCyl, r0 * c[4], r0 * s[4], -dz, normal);
vert(insideRadiusCyl, r0 * c[4], r0 * s[4], dz, normal);
insideRadiusCyl.seal(true);
+
+ if( useMappedBuffers ) {
+ frontFace.unmapStorage(gl);
+ backFace.unmapStorage(gl);
+ frontSide.unmapStorage(gl);
+ backSide.unmapStorage(gl);
+ outwardFace.unmapStorage(gl);
+ insideRadiusCyl.unmapStorage(gl);
+ } else {
+ /** Init VBO and data .. */
+ init(gl, frontFace);
+ init(gl, frontSide);
+ init(gl, backFace);
+ init(gl, backSide);
+ init(gl, outwardFace);
+ init(gl, insideRadiusCyl);
+ }
}
- static void vert(GLArrayDataServer array, float x, float y, float z, float n[]) {
+ @Override
+ public String toString() {
+ final int ffVBO = null != frontFace ? frontFace.getVBOName() : 0;
+ final int fsVBO = null != frontSide ? frontSide.getVBOName() : 0;
+ final int bfVBO = null != backFace ? backFace.getVBOName() : 0;
+ final int bsVBO = null != backSide ? backSide.getVBOName() : 0;
+ return "GearsObj[0x"+Integer.toHexString(hashCode())+", vbo ff "+ffVBO+", fs "+fsVBO+", bf "+bfVBO+", bs "+bsVBO+"]";
+ }
+
+ static void vert(final GLArrayDataServer array, final float x, final float y, final float z, final float n[]) {
array.putf(x);
array.putf(y);
array.putf(z);
@@ -267,8 +328,8 @@ public abstract class GearsObject {
array.putf(n[1]);
array.putf(n[2]);
}
-
- static void sincos(float x, float sin[], int sinIdx, float cos[], int cosIdx) {
+
+ static void sincos(final float x, final float sin[], final int sinIdx, final float cos[], final int cosIdx) {
sin[sinIdx] = (float) Math.sin(x);
cos[cosIdx] = (float) Math.cos(x);
}
diff --git a/src/jogl/classes/jogamp/graph/font/FontInt.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/PointsDemo.java
index 20e1ec028..f394ab31e 100644
--- a/src/jogl/classes/jogamp/graph/font/FontInt.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/PointsDemo.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2011 JogAmp Community. All rights reserved.
+ * Copyright 2012 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -25,23 +25,24 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package jogamp.graph.font;
+package com.jogamp.opengl.test.junit.jogl.demos;
-import java.util.ArrayList;
+import javax.media.opengl.GLEventListener;
-import jogamp.graph.geom.plane.Path2D;
+public abstract class PointsDemo implements GLEventListener {
+ int swapInterval = 0;
+ final int edge = 8; // 8*8
-import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.font.Font;
-import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.geom.Vertex.Factory;
-
-public interface FontInt extends Font {
+ public PointsDemo(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
- public interface GlyphInt extends Font.Glyph {
- public Path2D getPath(); // unscaled path
- public Path2D getPath(float pixelSize);
+ public PointsDemo() {
+ this.swapInterval = 1;
}
- public ArrayList<OutlineShape> getOutlineShapes(CharSequence string, float pixelSize, Factory<? extends Vertex> vertexFactory);
+ public abstract void setSmoothPoints(boolean v);
+
+ public abstract void setPointParams(float minSize, float maxSize, float distAttenConst, float distAttenLinear, float distAttenQuadratic, float fadeThreshold);
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java
index b9ac9faad..a508751c4 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,16 +20,17 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos;
import com.jogamp.opengl.util.texture.Texture;
public interface TextureDraw01Accessor {
+ public void setKeepTextureBound(boolean v);
public Texture getTexture();
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureSequenceDemo01.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureSequenceDemo01.java
deleted file mode 100644
index 6fd47e63f..000000000
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureSequenceDemo01.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package com.jogamp.opengl.test.junit.jogl.demos;
-
-import java.net.URLConnection;
-
-import javax.media.opengl.GL;
-import javax.media.opengl.GLException;
-import javax.media.opengl.GLProfile;
-
-import com.jogamp.common.util.IOUtil;
-import com.jogamp.opengl.util.texture.Texture;
-import com.jogamp.opengl.util.texture.TextureData;
-import com.jogamp.opengl.util.texture.TextureIO;
-import com.jogamp.opengl.util.texture.TextureSequence;
-
-public class TextureSequenceDemo01 implements TextureSequence {
- TextureSequence.TextureFrame frame = null;
- int textureUnit = 0;
- protected int[] texMinMagFilter = { GL.GL_NEAREST, GL.GL_NEAREST };
- protected int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE };
- final boolean useBuildInTexLookup;
-
- public TextureSequenceDemo01(boolean useBuildInTexLookup) {
- this.useBuildInTexLookup = useBuildInTexLookup;
- }
-
- public void initGLResources(GL gl) throws GLException {
- if(null == frame) {
- TextureData texData = null;
- try {
- URLConnection urlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-160x90.png", this.getClass().getClassLoader());
- if(null != urlConn) {
- texData = TextureIO.newTextureData(GLProfile.getGL2ES2(), urlConn.getInputStream(), false, TextureIO.PNG);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- final Texture tex = new Texture(gl, texData);
- frame = new TextureSequence.TextureFrame(tex);
- tex.bind(gl);
- gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_MIN_FILTER, texMinMagFilter[0]);
- gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[1]);
- gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_WRAP_S, texWrapST[0]);
- gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_WRAP_T, texWrapST[1]);
- }
- }
-
- public void destroyGLResources(GL gl) {
- if(null != frame) {
- frame.getTexture().destroy(gl);
- frame = null;
- }
- }
-
- public void destroy(GL gl) throws GLException {
- frame.getTexture().destroy(gl);
- frame = null;
- }
-
- @Override
- public int getTextureUnit() {
- return textureUnit;
- }
-
- @Override
- public int[] getTextureMinMagFilter() {
- return texMinMagFilter;
- }
-
- @Override
- public int[] getTextureWrapST() {
- return texWrapST;
- }
-
- @Override
- public TextureSequence.TextureFrame getLastTexture() throws IllegalStateException {
- return frame; // may return null
- }
-
- @Override
- public TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking) throws IllegalStateException {
- return frame;
- }
-
- @Override
- public String getRequiredExtensionsShaderStub() throws IllegalStateException {
- return "// TextTextureSequence: No extensions required\n";
- }
-
- @Override
- public String getTextureSampler2DType() throws IllegalStateException {
- return "sampler2D" ;
- }
-
- private String textureLookupFunctionName = "myTexture2D";
-
- @Override
- public String getTextureLookupFunctionName(String desiredFuncName) throws IllegalStateException {
- if(useBuildInTexLookup) {
- return "texture2D";
- }
- if(null != desiredFuncName && desiredFuncName.length()>0) {
- textureLookupFunctionName = desiredFuncName;
- }
- return textureLookupFunctionName;
- }
-
- @Override
- public String getTextureLookupFragmentShaderImpl() throws IllegalStateException {
- if(useBuildInTexLookup) {
- return "";
- }
- return
- "\n"+
- "vec4 "+textureLookupFunctionName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+
- " return texture2D(image, texCoord);\n"+
- "}\n\n";
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java
index 40b351a75..9d20495a0 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java
@@ -7,10 +7,10 @@
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -21,13 +21,18 @@
package com.jogamp.opengl.test.junit.jogl.demos.es1;
+import java.nio.FloatBuffer;
+
import javax.media.nativewindow.NativeWindow;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES1;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLPipelineFactory;
import javax.media.opengl.GLProfile;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyAdapter;
@@ -36,37 +41,67 @@ import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseListener;
+import com.jogamp.opengl.GLRendererQuirks;
+import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.test.junit.jogl.demos.GearsObject;
+import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil;
+import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode;
/**
* GearsES1.java <BR>
* @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P>
*/
public class GearsES1 implements GLEventListener {
+ private boolean debugFFPEmu = false;
+ private boolean verboseFFPEmu = false;
+ private boolean traceFFPEmu = false;
+ private boolean forceFFPEmu = false;
+ private boolean debug = false ;
+ private boolean trace = false ;
+
private final float pos[] = { 5.0f, 5.0f, 10.0f, 0.0f };
- private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f;
+ private float view_rotx = 20.0f, view_roty = 30.0f;
+ private final float view_rotz = 0.0f;
private GearsObject gear1=null, gear2=null, gear3=null;
+ private FloatBuffer gear1Color=GearsObject.red, gear2Color=GearsObject.green, gear3Color=GearsObject.blue;
+ private GearsES1 sharedGears;
+ private Object syncObjects;
+ private volatile boolean usesSharedGears = false;
+ private boolean useMappedBuffers = false;
+ private boolean validateBuffers = false;
private float angle = 0.0f;
- private int swapInterval;
- private MouseListener gearsMouse = new GearsMouseAdapter();
- private KeyListener gearsKeys = new GearsKeyAdapter();
+ private final int swapInterval;
+ private final MouseListener gearsMouse = new GearsMouseAdapter();
+ private final KeyListener gearsKeys = new GearsKeyAdapter();
+ private volatile boolean isInit = false;
private int prevMouseX, prevMouseY;
- public GearsES1(int swapInterval) {
+ public GearsES1(final int swapInterval) {
this.swapInterval = swapInterval;
}
public GearsES1() {
this.swapInterval = 1;
}
-
- public void setGears(GearsObject g1, GearsObject g2, GearsObject g3) {
- gear1 = g1;
- gear2 = g2;
- gear3 = g3;
+
+ public void setForceFFPEmu(final boolean forceFFPEmu, final boolean verboseFFPEmu, final boolean debugFFPEmu, final boolean traceFFPEmu) {
+ this.forceFFPEmu = forceFFPEmu;
+ this.verboseFFPEmu = verboseFFPEmu;
+ this.debugFFPEmu = debugFFPEmu;
+ this.traceFFPEmu = traceFFPEmu;
+ }
+
+ public void setGearsColors(final FloatBuffer gear1Color, final FloatBuffer gear2Color, final FloatBuffer gear3Color) {
+ this.gear1Color = gear1Color;
+ this.gear2Color = gear2Color;
+ this.gear3Color = gear3Color;
+ }
+
+ public void setSharedGears(final GearsES1 shared) {
+ sharedGears = shared;
}
/**
@@ -83,117 +118,161 @@ public class GearsES1 implements GLEventListener {
* @return gear3
*/
public GearsObject getGear3() { return gear3; }
-
- public void init(GLAutoDrawable drawable) {
+
+ public boolean usesSharedGears() { return usesSharedGears; }
+
+ public void setUseMappedBuffers(final boolean v) { useMappedBuffers = v; }
+ public void setValidateBuffers(final boolean v) { validateBuffers = v; }
+
+ public void init(final GLAutoDrawable drawable) {
+ if(null != sharedGears && !sharedGears.isInit() ) {
+ System.err.println(Thread.currentThread()+" GearsES1.init.0: pending shared Gears .. re-init later XXXXX");
+ drawable.setGLEventListenerInitState(this, false);
+ return;
+ }
System.err.println(Thread.currentThread()+" GearsES1.init ...");
-
+
// Use debug pipeline
// drawable.setGL(new DebugGL(drawable.getGL()));
GL _gl = drawable.getGL();
- // GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl /*, true*/);
- GL2ES1 gl = _gl.getGL2ES1();
-
+
+ if(debugFFPEmu) {
+ // Debug ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) );
+ debug = false;
+ }
+ if(traceFFPEmu) {
+ // Trace ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) );
+ trace = false;
+ }
+ GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu);
+
+ if(debug) {
+ try {
+ // Debug ..
+ gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES1.class, gl, null) );
+ } catch (final Exception e) {e.printStackTrace();}
+ }
+ if(trace) {
+ try {
+ // Trace ..
+ gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES1.class, gl, new Object[] { System.err } ) );
+ } catch (final Exception e) {e.printStackTrace();}
+ }
+
System.err.println("GearsES1 init on "+Thread.currentThread());
System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
System.err.println("INIT GL IS: " + gl.getClass().getName());
- System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
- System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
- System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
- System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
- System.err.println("GL Profile: "+gl.getGLProfile());
- System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
-
- gl.glLightfv(GL2ES1.GL_LIGHT0, GL2ES1.GL_POSITION, pos, 0);
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+
+ gl.glLightfv(GLLightingFunc.GL_LIGHT0, GLLightingFunc.GL_POSITION, pos, 0);
gl.glEnable(GL.GL_CULL_FACE);
- gl.glEnable(GL2ES1.GL_LIGHTING);
- gl.glEnable(GL2ES1.GL_LIGHT0);
- gl.glEnable(GL2ES1.GL_DEPTH_TEST);
-
+ gl.glEnable(GLLightingFunc.GL_LIGHTING);
+ gl.glEnable(GLLightingFunc.GL_LIGHT0);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+
/* make the gears */
- if(null == gear1) {
- gear1 = new GearsObjectES1(1.0f, 4.0f, 1.0f, 20, 0.7f);
- System.err.println("gear1 created: "+gear1);
+ if( null != sharedGears ) {
+ gear1 = new GearsObjectES1(sharedGears.getGear1());
+ gear2 = new GearsObjectES1(sharedGears.getGear2());
+ gear3 = new GearsObjectES1(sharedGears.getGear3());
+ usesSharedGears = true;
+ System.err.println("gear1 reuse: "+gear1);
+ System.err.println("gear2 reuse: "+gear2);
+ System.err.println("gear3 reuse: "+gear3);
+ if( gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync) ) {
+ syncObjects = sharedGears;
+ System.err.println("Shared GearsES1: Synchronized Objects due to quirk "+GLRendererQuirks.toString(GLRendererQuirks.NeedSharedObjectSync));
+ } else {
+ syncObjects = new Object();
+ System.err.println("Shared GearsES1: Unsynchronized Objects");
+ }
} else {
- System.err.println("gear1 reused: "+gear1);
- }
-
- if(null == gear2) {
- gear2 = new GearsObjectES1(0.5f, 2.0f, 2.0f, 10, 0.7f);
+ gear1 = new GearsObjectES1(gl, useMappedBuffers, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, validateBuffers);
+ System.err.println("gear1 created: "+gear1);
+
+ gear2 = new GearsObjectES1(gl, useMappedBuffers, gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, validateBuffers);
System.err.println("gear2 created: "+gear2);
- } else {
- System.err.println("gear2 reused: "+gear2);
- }
-
- if(null == gear3) {
- gear3 = new GearsObjectES1(1.3f, 2.0f, 0.5f, 10, 0.7f);
+
+ gear3 = new GearsObjectES1(gl, useMappedBuffers, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, validateBuffers);
System.err.println("gear3 created: "+gear3);
- } else {
- System.err.println("gear3 reused: "+gear3);
+
+ syncObjects = new Object();
}
-
- gl.glEnable(GL2ES1.GL_NORMALIZE);
-
+
+ gl.glEnable(GLLightingFunc.GL_NORMALIZE);
+
final Object upstreamWidget = drawable.getUpstreamWidget();
- if (upstreamWidget instanceof Window) {
+ if (upstreamWidget instanceof Window) {
final Window window = (Window) upstreamWidget;
window.addMouseListener(gearsMouse);
window.addKeyListener(gearsKeys);
} else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) {
final java.awt.Component comp = (java.awt.Component) upstreamWidget;
- new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse).addTo(comp);
- new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys).addTo(comp);
+ new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse, drawable).addTo(comp);
+ new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys, drawable).addTo(comp);
}
+ isInit = true;
System.err.println(Thread.currentThread()+" GearsES1.init FIN");
}
-
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+
+ public final boolean isInit() { return isInit; }
+
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ if( !isInit ) { return; }
System.err.println(Thread.currentThread()+" GearsES1.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval);
- GL2ES1 gl = drawable.getGL().getGL2ES1();
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
gl.setSwapInterval(swapInterval);
- gl.glMatrixMode(GL2ES1.GL_PROJECTION);
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
if(height>width) {
- float h = (float)height / (float)width;
+ final float h = (float)height / (float)width;
gl.glFrustumf(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
} else {
- float h = (float)width / (float)height;
+ final float h = (float)width / (float)height;
gl.glFrustumf(-h, h, -1.0f, 1.0f, 5.0f, 60.0f);
}
- gl.glMatrixMode(GL2ES1.GL_MODELVIEW);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -40.0f);
System.err.println(Thread.currentThread()+" GearsES1.reshape FIN");
}
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
+ if( !isInit ) { return; }
+ isInit = false;
System.err.println(Thread.currentThread()+" GearsES1.dispose ... ");
final Object upstreamWidget = drawable.getUpstreamWidget();
- if (upstreamWidget instanceof Window) {
+ if (upstreamWidget instanceof Window) {
final Window window = (Window) upstreamWidget;
window.removeMouseListener(gearsMouse);
window.removeKeyListener(gearsKeys);
}
- GL gl = drawable.getGL();
+ final GL gl = drawable.getGL();
gear1.destroy(gl);
gear1 = null;
gear2.destroy(gl);
gear2 = null;
gear3.destroy(gl);
gear3 = null;
+ sharedGears = null;
+ syncObjects = null;
System.err.println(Thread.currentThread()+" GearsES1.dispose FIN");
}
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
+ if( !isInit ) { return; }
+
// Turn the gears' teeth
- angle += 2.0f;
+ angle += 0.5f;
// Get the GL corresponding to the drawable we are animating
- GL2ES1 gl = drawable.getGL().getGL2ES1();
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
final boolean hasFocus;
final Object upstreamWidget = drawable.getUpstreamWidget();
@@ -207,10 +286,10 @@ public class GearsES1 implements GLEventListener {
} else {
gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
}
-
+
// Special handling for the case where the GLJPanel is translucent
// and wants to be composited with other Java 2D content
- if (GLProfile.isAWTAvailable() &&
+ if (GLProfile.isAWTAvailable() &&
(drawable instanceof javax.media.opengl.awt.GLJPanel) &&
!((javax.media.opengl.awt.GLJPanel) drawable).isOpaque() &&
((javax.media.opengl.awt.GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) {
@@ -220,27 +299,29 @@ public class GearsES1 implements GLEventListener {
}
gl.glNormal3f(0.0f, 0.0f, 1.0f);
-
+
// Rotate the entire assembly of gears based on how the user
// dragged the mouse around
gl.glPushMatrix();
gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
-
- gear1.draw(gl, -3.0f, -2.0f, angle, GearsObject.red);
- gear2.draw(gl, 3.1f, -2.0f, -2.0f * angle - 9.0f, GearsObject.green);
- gear3.draw(gl, -3.1f, 4.2f, -2.0f * angle - 25.0f, GearsObject.blue);
-
+
+ synchronized ( syncObjects ) {
+ gear1.draw(gl, -3.0f, -2.0f, angle);
+ gear2.draw(gl, 3.1f, -2.0f, -2.0f * angle - 9.0f);
+ gear3.draw(gl, -3.1f, 4.2f, -2.0f * angle - 25.0f);
+ }
+
// Remember that every push needs a pop; this one is paired with
// rotating the entire gear assembly
gl.glPopMatrix();
}
-
- class GearsKeyAdapter extends KeyAdapter {
- public void keyPressed(KeyEvent e) {
- int kc = e.getKeyCode();
+
+ class GearsKeyAdapter extends KeyAdapter {
+ public void keyPressed(final KeyEvent e) {
+ final int kc = e.getKeyCode();
if(KeyEvent.VK_LEFT == kc) {
view_roty -= 1;
} else if(KeyEvent.VK_RIGHT == kc) {
@@ -252,35 +333,39 @@ public class GearsES1 implements GLEventListener {
}
}
}
-
+
class GearsMouseAdapter extends MouseAdapter {
- public void mousePressed(MouseEvent e) {
+ public void mousePressed(final MouseEvent e) {
prevMouseX = e.getX();
prevMouseY = e.getY();
}
-
- public void mouseReleased(MouseEvent e) {
+
+ public void mouseReleased(final MouseEvent e) {
}
-
- public void mouseDragged(MouseEvent e) {
- int x = e.getX();
- int y = e.getY();
+
+ public void mouseDragged(final MouseEvent e) {
+ final int x = e.getX();
+ final int y = e.getY();
int width=0, height=0;
- Object source = e.getSource();
+ final Object source = e.getSource();
if(source instanceof Window) {
- Window window = (Window) source;
- width=window.getWidth();
- height=window.getHeight();
+ final Window window = (Window) source;
+ width=window.getSurfaceWidth();
+ height=window.getSurfaceHeight();
+ } else if (source instanceof GLAutoDrawable) {
+ final GLAutoDrawable glad = (GLAutoDrawable) source;
+ width = glad.getSurfaceWidth();
+ height = glad.getSurfaceHeight();
} else if (GLProfile.isAWTAvailable() && source instanceof java.awt.Component) {
- java.awt.Component comp = (java.awt.Component) source;
- width=comp.getWidth();
+ final java.awt.Component comp = (java.awt.Component) source;
+ width=comp.getWidth(); // FIXME HiDPI: May need to convert window units -> pixel units!
height=comp.getHeight();
} else {
throw new RuntimeException("Event source neither Window nor Component: "+source);
}
- float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width);
- float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height);
-
+ final float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width);
+ final float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height);
+
prevMouseX = x;
prevMouseY = y;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java
index 1208dad61..1355a44c8 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java
@@ -7,10 +7,10 @@
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -24,9 +24,11 @@ import java.nio.FloatBuffer;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GLBufferStorage;
+import javax.media.opengl.GLException;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
import javax.media.opengl.fixedfunc.GLPointerFunc;
-
import com.jogamp.opengl.test.junit.jogl.demos.GearsObject;
import com.jogamp.opengl.util.GLArrayDataServer;
@@ -36,45 +38,68 @@ import com.jogamp.opengl.util.GLArrayDataServer;
*/
public class GearsObjectES1 extends GearsObject {
- public GearsObjectES1(float inner_radius, float outer_radius, float width,
- int teeth, float tooth_depth) {
- super(inner_radius, outer_radius, width, teeth, tooth_depth);
+ public GearsObjectES1(final GL gl, final boolean useMappedBuffers, final FloatBuffer gearColor, final float inner_radius,
+ final float outer_radius, final float width, final int teeth, final float tooth_depth, final boolean validateBuffers) {
+ super(gl, useMappedBuffers, gearColor, inner_radius, outer_radius, width, teeth, tooth_depth, validateBuffers);
+ }
+
+ public GearsObjectES1(final GearsObject shared) {
+ super(shared);
}
@Override
- public GLArrayDataServer createInterleaved(int comps, int dataType, boolean normalized, int initialSize, int vboUsage) {
- return GLArrayDataServer.createFixedInterleaved(comps, dataType, normalized, initialSize, vboUsage);
+ public GLArrayDataServer createInterleaved(final boolean useMappedBuffers, final int comps, final int dataType, final boolean normalized, final int initialSize, final int vboUsage) {
+ if( useMappedBuffers ) {
+ return GLArrayDataServer.createFixedInterleavedMapped(comps, dataType, normalized, initialSize, vboUsage);
+ } else {
+ return GLArrayDataServer.createFixedInterleaved(comps, dataType, normalized, initialSize, vboUsage);
+ }
}
-
+
@Override
- public void addInterleavedVertexAndNormalArrays(GLArrayDataServer array,
- int components) {
- array.addFixedSubArray(GLPointerFunc.GL_VERTEX_ARRAY, 3, GL.GL_ARRAY_BUFFER);
- array.addFixedSubArray(GLPointerFunc.GL_NORMAL_ARRAY, 3, GL.GL_ARRAY_BUFFER);
+ public void addInterleavedVertexAndNormalArrays(final GLArrayDataServer array, final int components) {
+ array.addFixedSubArray(GLPointerFunc.GL_VERTEX_ARRAY, components, GL.GL_ARRAY_BUFFER);
+ array.addFixedSubArray(GLPointerFunc.GL_NORMAL_ARRAY, components, GL.GL_ARRAY_BUFFER);
}
- private void draw(GL2ES1 gl, GLArrayDataServer array, int mode) {
- array.enableBuffer(gl, true);
- gl.glDrawArrays(mode, 0, array.getElementCount());
- array.enableBuffer(gl, false);
+ private void draw(final GL2ES1 gl, final GLArrayDataServer array, final int mode) {
+ if( !isShared || gl.glIsBuffer(array.getVBOName()) ) {
+ array.enableBuffer(gl, true);
+ if( validateBuffers ) {
+ final int bufferTarget = array.getVBOTarget();
+ final int bufferName = array.getVBOName();
+ final long bufferSize = array.getSizeInBytes();
+ final int hasBufferName = gl.getBoundBuffer(bufferTarget);
+ final GLBufferStorage hasStorage = gl.getBufferStorage(hasBufferName);
+ final boolean ok = bufferName == hasBufferName &&
+ bufferName == hasStorage.getName() &&
+ bufferSize == hasStorage.getSize();
+ if( !ok ) {
+ throw new GLException("GLBufferStorage Validation Error: Target[exp 0x"+Integer.toHexString(bufferTarget)+", has 0x"+Integer.toHexString(bufferTarget)+
+ ", Name[exp "+bufferName+", has "+hasBufferName+", Size exp "+bufferSize+", Storage "+hasStorage+"]");
+ }
+ }
+ gl.glDrawArrays(mode, 0, array.getElementCount());
+ array.enableBuffer(gl, false);
+ }
}
@Override
- public void draw(GL _gl, float x, float y, float angle, FloatBuffer color) {
- GL2ES1 gl = _gl.getGL2ES1();
+ public void draw(final GL _gl, final float x, final float y, final float angle) {
+ final GL2ES1 gl = _gl.getGL2ES1();
gl.glPushMatrix();
gl.glTranslatef(x, y, 0f);
gl.glRotatef(angle, 0f, 0f, 1f);
- gl.glMaterialfv(GL2ES1.GL_FRONT_AND_BACK, GL2ES1.GL_AMBIENT_AND_DIFFUSE, color);
-
- gl.glShadeModel(GL2ES1.GL_FLAT);
+ gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_AMBIENT_AND_DIFFUSE, gearColor);
+
+ gl.glShadeModel(GLLightingFunc.GL_FLAT);
draw(gl, frontFace, GL.GL_TRIANGLE_STRIP);
draw(gl, frontSide, GL.GL_TRIANGLES);
draw(gl, backFace, GL.GL_TRIANGLE_STRIP);
draw(gl, backSide, GL.GL_TRIANGLES);
draw(gl, outwardFace, GL.GL_TRIANGLE_STRIP);
- gl.glShadeModel(GL2ES1.GL_SMOOTH);
+ gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
draw(gl, insideRadiusCyl, GL.GL_TRIANGLE_STRIP);
gl.glPopMatrix();
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java
index aad56581b..681628a69 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java
@@ -44,6 +44,7 @@ import javax.media.opengl.GL;
import javax.media.opengl.GL2ES1;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.opengl.util.ImmModeSink;
@@ -52,58 +53,59 @@ public class MultisampleDemoES1 implements GLEventListener {
boolean multisample;
ImmModeSink immModeSink;
- public MultisampleDemoES1(boolean multisample) {
+ public MultisampleDemoES1(final boolean multisample) {
this.multisample = multisample;
}
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
System.err.println();
System.err.println("Requested: " + drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities());
System.err.println();
System.err.println("Chosen : " + drawable.getChosenGLCapabilities());
System.err.println();
- GL2ES1 gl = drawable.getGL().getGL2ES1();
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
if (multisample) {
gl.glEnable(GL.GL_MULTISAMPLE);
}
gl.glClearColor(0, 0, 0, 0);
// gl.glEnable(GL.GL_DEPTH_TEST);
// gl.glDepthFunc(GL.GL_LESS);
- gl.glMatrixMode(GL2ES1.GL_MODELVIEW);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
- gl.glMatrixMode(GL2ES1.GL_PROJECTION);
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(-1, 1, -1, 1, -1, 1);
if (multisample) {
gl.glDisable(GL.GL_MULTISAMPLE);
}
- immModeSink = ImmModeSink.createFixed(gl, GL.GL_STATIC_DRAW, 40,
- 3, GL.GL_FLOAT, // vertex
- 0, GL.GL_FLOAT, // color
- 0, GL.GL_FLOAT,// normal
- 0, GL.GL_FLOAT); // texture
+ immModeSink = ImmModeSink.createFixed(40,
+ 3, GL.GL_FLOAT, // vertex
+ 0, GL.GL_FLOAT, // color
+ 0, GL.GL_FLOAT, // normal
+ 0, GL.GL_FLOAT, // texCoords
+ GL.GL_STATIC_DRAW);
final int numSteps = 20;
final double increment = Math.PI / numSteps;
final double radius = 1;
immModeSink.glBegin(GL.GL_LINES);
for (int i = numSteps - 1; i >= 0; i--) {
- immModeSink.glVertex3f((float) (radius * Math.cos(i * increment)),
- (float) (radius * Math.sin(i * increment)),
+ immModeSink.glVertex3f((float) (radius * Math.cos(i * increment)),
+ (float) (radius * Math.sin(i * increment)),
0f);
- immModeSink.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)),
- (float) (-1.0 * radius * Math.sin(i * increment)),
+ immModeSink.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)),
+ (float) (-1.0 * radius * Math.sin(i * increment)),
0f);
}
immModeSink.glEnd(gl, false);
}
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
immModeSink.destroy(drawable.getGL());
immModeSink = null;
}
- public void display(GLAutoDrawable drawable) {
- GL2ES1 gl = drawable.getGL().getGL2ES1();
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
if (multisample) {
gl.glEnable(GL.GL_MULTISAMPLE);
}
@@ -115,9 +117,9 @@ public class MultisampleDemoES1 implements GLEventListener {
}
// Unused routines
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
}
- public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
+ public void displayChanged(final GLAutoDrawable drawable, final boolean modeChanged, final boolean deviceChanged) {
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java
new file mode 100644
index 000000000..9f5940b53
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java
@@ -0,0 +1,359 @@
+/**
+ * OlympicGL2
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es1;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLPipelineFactory;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.glu.GLU;
+import javax.media.opengl.glu.gl2es1.GLUgl2es1;
+
+import com.jogamp.opengl.util.ImmModeSink;
+import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil;
+import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode;
+
+import java.lang.Math;
+
+public class OlympicES1 implements GLEventListener
+{
+ private boolean debugFFPEmu = false;
+ private boolean verboseFFPEmu = false;
+ private boolean traceFFPEmu = false;
+ private boolean forceFFPEmu = false;
+ private boolean debug = false ;
+ private boolean trace = false ;
+
+ // private static final double M_PI= Math.PI;
+ private static final double M_2PI = 2.0*Math.PI;
+
+ private static final int
+ // XSIZE= 100,
+ // YSIZE= 75,
+ RINGS= 5,
+ BLUERING= 0,
+ BLACKRING= 1,
+ REDRING= 2,
+ YELLOWRING =3,
+ GREENRING =4,
+ // BACKGROUND =8,
+ BLACK = 0,
+ RED=1,
+ GREEN=2,
+ YELLOW=3,
+ BLUE=4
+ // ,MAGENTA=5,
+ // CYAN=6,
+ // WHITE=7
+ ;
+
+ private byte rgb_colors[][];
+ private int mapped_colors[];
+ private float dests[][];
+ private float offsets[][];
+ private float angs[];
+ private float rotAxis[][];
+ private int iters[];
+ private ImmModeSink theTorus;
+
+ private final float lmodel_ambient[] = {0.0f, 0.0f, 0.0f, 0.0f};
+ private final float lmodel_twoside[] = {0.0f, 0.0f, 0.0f, 0.0f};
+ // private float lmodel_local[] = {0.0f, 0.0f, 0.0f, 0.0f};
+ private final float light0_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f};
+ private final float light0_diffuse[] = {1.0f, 1.0f, 1.0f, 0.0f};
+ private final float light0_position[] = {0.8660254f, 0.5f, 1f, 0f};
+ private final float light0_specular[] = {1.0f, 1.0f, 1.0f, 0.0f};
+ private final float bevel_mat_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};
+ private final float bevel_mat_shininess[] = {40.0f, 0f, 0f, 0f};
+ private final float bevel_mat_specular[] = {1.0f, 1.0f, 1.0f, 0.0f};
+ private final float bevel_mat_diffuse[] = {1.0f, 0.0f, 0.0f, 0.0f};
+ private final int swapInterval;
+ private GLU glu;
+
+ public OlympicES1() {
+ swapInterval = 1;
+ }
+
+ public OlympicES1(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
+
+ public void setForceFFPEmu(final boolean forceFFPEmu, final boolean verboseFFPEmu, final boolean debugFFPEmu, final boolean traceFFPEmu) {
+ this.forceFFPEmu = forceFFPEmu;
+ this.verboseFFPEmu = verboseFFPEmu;
+ this.debugFFPEmu = debugFFPEmu;
+ this.traceFFPEmu = traceFFPEmu;
+ }
+
+ public void init(final GLAutoDrawable drawable)
+ {
+ GL _gl = drawable.getGL();
+
+ if(debugFFPEmu) {
+ // Debug ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) );
+ debug = false;
+ }
+ if(traceFFPEmu) {
+ // Trace ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) );
+ trace = false;
+ }
+ GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu);
+
+ if(debug) {
+ try {
+ // Debug ..
+ gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES1.class, gl, null) );
+ } catch (final Exception e) {e.printStackTrace();}
+ }
+ if(trace) {
+ try {
+ // Trace ..
+ gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES1.class, gl, new Object[] { System.err } ) );
+ } catch (final Exception e) {e.printStackTrace();}
+ }
+
+ System.err.println("OlympicES1 init on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+ System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
+ System.err.println("GL Profile: "+gl.getGLProfile());
+ System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
+
+ glu = GLU.createGLU(gl);
+ System.err.println("GLU:" + glu.getClass().getName());
+
+ rgb_colors=new byte[RINGS][3];
+ mapped_colors=new int [RINGS];
+ dests=new float [RINGS][3];
+ offsets=new float[RINGS][3];
+ angs=new float[RINGS];
+ rotAxis=new float[RINGS][3];
+ iters=new int[RINGS];
+
+ int i;
+ final float top_y = 1.0f;
+ final float bottom_y = 0.0f;
+ final float top_z = 0.15f;
+ final float bottom_z = 0.69f;
+ final float spacing = 2.5f;
+
+ for (i = 0; i < RINGS; i++) {
+ rgb_colors[i][0] = rgb_colors[i][1] = rgb_colors[i][2] = (byte)0;
+ }
+ rgb_colors[BLUERING][2] = (byte)255;
+ rgb_colors[REDRING][0] = (byte)255;
+ rgb_colors[GREENRING][1] = (byte)255;
+ rgb_colors[YELLOWRING][0] = (byte)255;
+ rgb_colors[YELLOWRING][1] = (byte)255;
+ mapped_colors[BLUERING] = BLUE;
+ mapped_colors[REDRING] = RED;
+ mapped_colors[GREENRING] = GREEN;
+ mapped_colors[YELLOWRING] = YELLOW;
+ mapped_colors[BLACKRING] = BLACK;
+
+ dests[BLUERING][0] = -spacing;
+ dests[BLUERING][1] = top_y;
+ dests[BLUERING][2] = top_z;
+
+ dests[BLACKRING][0] = 0.0f;
+ dests[BLACKRING][1] = top_y;
+ dests[BLACKRING][2] = top_z;
+
+ dests[REDRING][0] = spacing;
+ dests[REDRING][1] = top_y;
+ dests[REDRING][2] = top_z;
+
+ dests[YELLOWRING][0] = -spacing / 2.0f;
+ dests[YELLOWRING][1] = bottom_y;
+ dests[YELLOWRING][2] = bottom_z;
+
+ dests[GREENRING][0] = spacing / 2.0f;
+ dests[GREENRING][1] = bottom_y;
+ dests[GREENRING][2] = bottom_z;
+
+ theTorus = ImmModeSink.createFixed(40,
+ 3, GL.GL_FLOAT, // vertex
+ 0, GL.GL_FLOAT, // color
+ 3, GL.GL_FLOAT, // normal
+ 0, GL.GL_FLOAT, // texCoords
+ GL.GL_STATIC_DRAW);
+ FillTorus(gl, theTorus, 0.1f, 8, 1.0f, 25);
+
+ gl.glEnable(GL.GL_CULL_FACE);
+ gl.glCullFace(GL.GL_BACK);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glClearDepth(1.0);
+
+ gl.glLightfv(GLLightingFunc.GL_LIGHT0, GLLightingFunc.GL_AMBIENT, light0_ambient, 0);
+ gl.glLightfv(GLLightingFunc.GL_LIGHT0, GLLightingFunc.GL_DIFFUSE, light0_diffuse, 0);
+ gl.glLightfv(GLLightingFunc.GL_LIGHT0, GLLightingFunc.GL_SPECULAR, light0_specular, 0);
+ gl.glLightfv(GLLightingFunc.GL_LIGHT0, GLLightingFunc.GL_POSITION, light0_position, 0);
+ gl.glEnable(GLLightingFunc.GL_LIGHT0);
+
+ // gl.glLightModelfv(GL2.GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local, 0);
+ gl.glLightModelfv(GL2ES1.GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside, 0);
+ gl.glLightModelfv(GL2ES1.GL_LIGHT_MODEL_AMBIENT, lmodel_ambient, 0);
+ gl.glEnable(GLLightingFunc.GL_LIGHTING);
+
+ gl.glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
+
+ gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT, bevel_mat_ambient, 0);
+ gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_SHININESS, bevel_mat_shininess, 0);
+ gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_SPECULAR, bevel_mat_specular, 0);
+ gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_DIFFUSE, bevel_mat_diffuse, 0);
+
+ // gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL2ES1.GL_DIFFUSE);
+ gl.glEnable(GLLightingFunc.GL_COLOR_MATERIAL);
+ gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
+
+ ReInit();
+ t0 = System.currentTimeMillis();
+ tL = t0;
+ }
+
+
+ @Override
+ public void dispose(final GLAutoDrawable glad) {
+ glu = null;
+ theTorus.destroy(glad.getGL());
+ theTorus = null;
+ }
+
+
+ @Override
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ final GL2ES1 gl = glad.getGL().getGL2ES1();
+ gl.setSwapInterval(swapInterval);
+
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ glu.gluPerspective(45f, (float) width / (float) height, 0.1f, 100.0f);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ glu.gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable glad) {
+ final GL2ES1 gl = glad.getGL().getGL2ES1();
+ int i;
+
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+ gl.glPushMatrix();
+ for (i = 0; i < RINGS; i++) {
+ gl.glColor4ub(rgb_colors[i][0], rgb_colors[i][1], rgb_colors[i][2], (byte)1);
+ gl.glPushMatrix();
+ gl.glTranslatef(dests[i][0] + offsets[i][0],
+ dests[i][1] + offsets[i][1],
+ dests[i][2] + offsets[i][2]);
+ gl.glRotatef(angs[i], rotAxis[i][0], rotAxis[i][1], rotAxis[i][2]);
+ theTorus.draw(gl, true);
+ gl.glPopMatrix();
+ }
+ gl.glPopMatrix();
+ animationCalc();
+ }
+
+ long t0, tL;
+
+ protected void animationCalc()
+ {
+ int i, j;
+
+ final long t1 = System.currentTimeMillis();
+ if( t1 - tL < 50 ) {
+ return;
+ }
+
+ for (i = 0; i < RINGS; i++) {
+ if (iters[i]!=0) {
+ for (j = 0; j < 3; j++) {
+ offsets[i][j] = Clamp(iters[i], offsets[i][j]);
+ }
+ angs[i] = Clamp(iters[i], angs[i]);
+ iters[i]--;
+ }
+ }
+ if (iters[0]==0)
+ {
+ ReInit();
+ }
+
+ tL = t1;
+ }
+
+ protected void ReInit() {
+ int i;
+ float deviation;
+
+ deviation = MyRand() / 2;
+ deviation = deviation * deviation;
+ for (i = 0; i < RINGS; i++) {
+ offsets[i][0] = MyRand();
+ offsets[i][1] = MyRand();
+ offsets[i][2] = MyRand();
+ angs[i] = (float) (260.0 * MyRand());
+ rotAxis[i][0] = MyRand();
+ rotAxis[i][1] = MyRand();
+ rotAxis[i][2] = MyRand();
+ iters[i] = ( int ) (deviation * MyRand() + 60.0);
+ }
+ }
+
+ protected static void FillTorus(final GL gl, final ImmModeSink immModeSink, final float rc, final int numc, final float rt, final int numt)
+ {
+ int i, j, k;
+ double s, t;
+ float x, y, z;
+
+ for (i = 0; i < numc; i++) {
+ immModeSink.glBegin(ImmModeSink.GL_QUAD_STRIP);
+ for (j = 0; j <= numt; j++) {
+ for (k = 1; k >= 0; k--) {
+ s = (i + k) % numc + 0.5;
+ t = j % numt;
+
+ x = (float) Math.cos(t * M_2PI / numt) * (float) Math.cos(s * M_2PI / numc);
+ y = (float) Math.sin(t * M_2PI / numt) * (float) Math.cos(s * M_2PI / numc);
+ z = (float) Math.sin(s * M_2PI / numc);
+ immModeSink.glNormal3f(x, y, z);
+
+ x = (rt + rc * (float) Math.cos(s * M_2PI / numc)) * (float) Math.cos(t * M_2PI / numt);
+ y = (rt + rc * (float) Math.cos(s * M_2PI / numc)) * (float) Math.sin(t * M_2PI / numt);
+ z = rc * (float) Math.sin(s * M_2PI / numc);
+ immModeSink.glVertex3f(x, y, z);
+ }
+ }
+ immModeSink.glEnd(gl, false);
+ }
+ }
+
+ protected float Clamp(final int iters_left, final float t)
+ {
+ if (iters_left < 3) {
+ return 0.0f;
+ }
+ return (iters_left - 2) * t / iters_left;
+ }
+
+ protected float MyRand()
+ {
+ // return 10.0 * (drand48() - 0.5);
+ return (float) ( 10.0 * (Math.random() - 0.5) );
+ }
+
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OneTriangle.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OneTriangle.java
index 8c9f53b82..aaa7da3fe 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OneTriangle.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OneTriangle.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -30,6 +30,7 @@ package com.jogamp.opengl.test.junit.jogl.demos.es1;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES1;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.gl2es1.GLUgl2es1;
@@ -41,38 +42,39 @@ import com.jogamp.opengl.util.ImmModeSink;
*/
public class OneTriangle {
- public static void setup( GL2ES1 gl, int width, int height ) {
- gl.glMatrixMode( GL2ES1.GL_PROJECTION );
+ public static void setup( final GL2ES1 gl, final int width, final int height ) {
+ gl.glMatrixMode( GLMatrixFunc.GL_PROJECTION );
gl.glLoadIdentity();
// coordinate system origin at lower left with width and height same as the window
- GLU glu = new GLUgl2es1();
+ final GLU glu = new GLUgl2es1();
glu.gluOrtho2D( 0.0f, width, 0.0f, height );
- gl.glMatrixMode( GL2ES1.GL_MODELVIEW );
+ gl.glMatrixMode( GLMatrixFunc.GL_MODELVIEW );
gl.glLoadIdentity();
- gl.glViewport( 0, 0, width, height );
+ gl.glViewport( 0, 0, width, height );
}
- public static void render( GL2ES1 gl, int width, int height) {
+ public static void render( final GL2ES1 gl, final int width, final int height) {
gl.glClear( GL.GL_COLOR_BUFFER_BIT );
// draw a triangle filling the window
gl.glLoadIdentity();
-
- ImmModeSink immModeSink = ImmModeSink.createFixed(gl, GL.GL_STATIC_DRAW, 3,
- 3, GL.GL_FLOAT, // vertex
- 3, GL.GL_FLOAT, // color
- 0, GL.GL_FLOAT,// normal
- 0, GL.GL_FLOAT); // texture
+
+ final ImmModeSink immModeSink = ImmModeSink.createFixed(3*3,
+ 3, GL.GL_FLOAT, // vertex
+ 3, GL.GL_FLOAT, // color
+ 0, GL.GL_FLOAT, // normal
+ 0, GL.GL_FLOAT, // texCoords
+ GL.GL_STATIC_DRAW);
immModeSink.glBegin(GL.GL_TRIANGLES);
immModeSink.glColor3f( 1, 0, 0 );
immModeSink.glVertex2f( 0, 0 );
immModeSink.glColor3f( 0, 1, 0 );
immModeSink.glVertex2f( width, 0 );
immModeSink.glColor3f( 0, 0, 1 );
- immModeSink.glVertex2f( width / 2, height );
+ immModeSink.glVertex2f( width / 2f, height );
immModeSink.glEnd(gl, true);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java
new file mode 100644
index 000000000..3aced12ed
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java
@@ -0,0 +1,200 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es1;
+
+import java.nio.FloatBuffer;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.test.junit.jogl.demos.PointsDemo;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil;
+import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLPipelineFactory;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+import javax.media.opengl.glu.GLU;
+import javax.media.opengl.glu.gl2es1.GLUgl2es1;
+
+public class PointsDemoES1 extends PointsDemo {
+ final static GLU glu = new GLUgl2es1();
+ private boolean debugFFPEmu = false;
+ private boolean verboseFFPEmu = false;
+ private boolean traceFFPEmu = false;
+ private boolean forceFFPEmu = false;
+ private boolean debug = false ;
+ private boolean trace = false ;
+ GLArrayDataServer vertices ;
+ float[] pointSizes ;
+ private int swapInterval = 0;
+ final int edge = 8; // 8*8
+ boolean smooth = false;
+
+ public PointsDemoES1(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
+
+ public PointsDemoES1() {
+ this.swapInterval = 1;
+ }
+
+ public void setForceFFPEmu(final boolean forceFFPEmu, final boolean verboseFFPEmu, final boolean debugFFPEmu, final boolean traceFFPEmu) {
+ this.forceFFPEmu = forceFFPEmu;
+ this.verboseFFPEmu = verboseFFPEmu;
+ this.debugFFPEmu = debugFFPEmu;
+ this.traceFFPEmu = traceFFPEmu;
+ }
+
+ public void setSmoothPoints(final boolean v) { smooth = v; }
+
+ public void init(final GLAutoDrawable glad) {
+ GL _gl = glad.getGL();
+
+ if(debugFFPEmu) {
+ // Debug ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) );
+ debug = false;
+ }
+ if(traceFFPEmu) {
+ // Trace ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) );
+ trace = false;
+ }
+ GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu);
+
+ if(debug) {
+ try {
+ // Debug ..
+ gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES1.class, gl, null) );
+ } catch (final Exception e) {e.printStackTrace();}
+ }
+ if(trace) {
+ try {
+ // Trace ..
+ gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES1.class, gl, new Object[] { System.err } ) );
+ } catch (final Exception e) {e.printStackTrace();}
+ }
+
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println("GL Profile: "+gl.getGLProfile());
+
+ // Allocate Vertex Array
+ vertices = GLArrayDataServer.createFixed(GLPointerFunc.GL_VERTEX_ARRAY, 3, GL.GL_FLOAT, false, edge*edge, GL.GL_STATIC_DRAW);
+ pointSizes = new float[edge*edge];
+ for(int i=0; i<edge; i++) {
+ for(int j=0; j<edge; j++) {
+ final float x = -3+j*0.7f;
+ final float y = -3+i*0.7f;
+ final float p = Math.max(0.000001f, (i*edge+j)*0.5f); // no zero point size!
+ // System.err.println("["+j+"/"+i+"]: "+x+"/"+y+": "+p);
+ vertices.putf(x); vertices.putf(y); vertices.putf( 0);
+ pointSizes[(i*edge+j)] = p;
+ }
+ }
+ vertices.seal(gl, true);
+ vertices.enableBuffer(gl, false);
+
+ // OpenGL Render Settings
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ }
+
+ public void setPointParams(final float minSize, final float maxSize, final float distAttenConst, final float distAttenLinear, final float distAttenQuadratic, final float fadeThreshold) {
+ pointMinSize = minSize;
+ pointMaxSize = maxSize;
+ pointFadeThreshold = fadeThreshold;
+ pointDistAtten.put(0, distAttenConst);
+ pointDistAtten.put(1, distAttenLinear);
+ pointDistAtten.put(2, distAttenQuadratic);
+ }
+
+ /** default values */
+ private float pointMinSize = 0.0f;
+ private float pointMaxSize = 4096.0f;
+ private float pointFadeThreshold = 1.0f;
+ private final FloatBuffer pointDistAtten = Buffers.newDirectFloatBuffer(new float[] { 1.0f, 0.0f, 0.0f });
+
+ public void display(final GLAutoDrawable glad) {
+ final GL2ES1 gl = glad.getGL().getGL2ES1();
+ gl.glClearColor(0f, 0f, 0f, 0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0, 0, -10);
+
+ gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f );
+
+ vertices.enableBuffer(gl, true);
+
+ gl.glEnable ( GL.GL_BLEND );
+ gl.glBlendFunc ( GL.GL_SRC_ALPHA, GL.GL_ONE );
+ if(smooth) {
+ gl.glEnable(GL2ES1.GL_POINT_SMOOTH);
+ } else {
+ gl.glDisable(GL2ES1.GL_POINT_SMOOTH);
+ }
+ gl.glPointParameterf(GL2ES1.GL_POINT_SIZE_MIN, pointMinSize );
+ gl.glPointParameterf(GL2ES1.GL_POINT_SIZE_MAX, pointMaxSize );
+ gl.glPointParameterf(GL.GL_POINT_FADE_THRESHOLD_SIZE, pointFadeThreshold);
+ gl.glPointParameterfv(GL2ES1.GL_POINT_DISTANCE_ATTENUATION, pointDistAtten );
+
+ for(int i=edge*edge-1; i>=0; i--) {
+ gl.glPointSize(pointSizes[i]);
+ gl.glDrawArrays(GL.GL_POINTS, i, 1);
+ }
+
+ vertices.enableBuffer(gl, false);
+ }
+
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ // Thread.dumpStack();
+ final GL2ES1 gl = glad.getGL().getGL2ES1();
+
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ }
+
+ // Set location in front of camera
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ glu.gluPerspective(45.0F, ( (float) width / (float) height ) / 1.0f, 1.0F, 100.0F);
+ //gl.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f);
+ }
+
+ public void dispose(final GLAutoDrawable glad) {
+ final GL2ES1 gl = glad.getGL().getGL2ES1();
+ vertices.destroy(gl);
+ vertices = null;
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java
index 84234d464..1f81261b8 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java
@@ -1,33 +1,74 @@
package com.jogamp.opengl.test.junit.jogl.demos.es1;
import com.jogamp.common.nio.Buffers;
+
import java.nio.*;
+
import javax.media.opengl.*;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.fixedfunc.GLPointerFunc;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.util.TileRendererBase;
import com.jogamp.opengl.util.glsl.fixedfunc.*;
-public class RedSquareES1 implements GLEventListener {
+public class RedSquareES1 implements GLEventListener, TileRendererBase.TileRendererListener {
- public static boolean glDebugEmu = false;
- public static boolean glDebug = false ;
- public static boolean glTrace = false ;
public static boolean oneThread = false;
public static boolean useAnimator = false;
+ private boolean debugFFPEmu = false;
+ private boolean verboseFFPEmu = false;
+ private boolean traceFFPEmu = false;
+ private boolean forceFFPEmu = false;
+ private boolean debug = false ;
+ private boolean trace = false ;
private int swapInterval = 0;
+ private final float aspect = 1.0f;
+ private boolean doRotate = true;
+ private TileRendererBase tileRendererInUse = null;
+ private boolean doRotateBeforePrinting;
+ private boolean flipVerticalInGLOrientation = false;
long startTime = 0;
long curTime = 0;
- public RedSquareES1(int swapInterval) {
+ public RedSquareES1(final int swapInterval) {
this.swapInterval = swapInterval;
}
public RedSquareES1() {
this.swapInterval = 1;
}
-
+
+ @Override
+ public void addTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = tr;
+ doRotateBeforePrinting = doRotate;
+ setDoRotation(false);
+ }
+ @Override
+ public void removeTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = null;
+ setDoRotation(doRotateBeforePrinting);
+ }
+ @Override
+ public void startTileRendering(final TileRendererBase tr) {
+ System.err.println("RedSquareES1.startTileRendering: "+tr);
+ }
+ @Override
+ public void endTileRendering(final TileRendererBase tr) {
+ System.err.println("RedSquareES1.endTileRendering: "+tr);
+ }
+
+ public void setDoRotation(final boolean rotate) { this.doRotate = rotate; }
+ public void setForceFFPEmu(final boolean forceFFPEmu, final boolean verboseFFPEmu, final boolean debugFFPEmu, final boolean traceFFPEmu) {
+ this.forceFFPEmu = forceFFPEmu;
+ this.verboseFFPEmu = verboseFFPEmu;
+ this.debugFFPEmu = debugFFPEmu;
+ this.traceFFPEmu = traceFFPEmu;
+ }
+ public void setFlipVerticalInGLOrientation(final boolean v) { flipVerticalInGLOrientation=v; }
+
// FIXME: we must add storage of the pointers in the GL state to
// the GLImpl classes. The need for this can be seen by making
// these variables method local instead of instance members. The
@@ -38,49 +79,40 @@ public class RedSquareES1 implements GLEventListener {
private FloatBuffer colors;
private FloatBuffer vertices;
- public void init(GLAutoDrawable drawable) {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
System.err.println(Thread.currentThread()+" RedSquareES1.init ...");
GL _gl = drawable.getGL();
- if(glDebugEmu) {
- try {
- // Debug ..
- _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) );
-
- if(glTrace) {
- // Trace ..
- _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) );
- }
- } catch (Exception e) {e.printStackTrace();}
- glDebug = false;
- glTrace = false;
+ if(debugFFPEmu) {
+ // Debug ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) );
+ debug = false;
+ }
+ if(traceFFPEmu) {
+ // Trace ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) );
+ trace = false;
}
+ GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu);
- GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl);
- if(glDebug) {
+ if(debug) {
try {
// Debug ..
gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES1.class, gl, null) );
- } catch (Exception e) {e.printStackTrace();}
+ } catch (final Exception e) {e.printStackTrace();}
}
-
- if(glTrace) {
+ if(trace) {
try {
// Trace ..
gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES1.class, gl, new Object[] { System.err } ) );
- } catch (Exception e) {e.printStackTrace();}
+ } catch (final Exception e) {e.printStackTrace();}
}
System.err.println("RedSquareES1 init on "+Thread.currentThread());
System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
System.err.println("INIT GL IS: " + gl.getClass().getName());
- System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
- System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
- System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
- System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
- System.err.println("GL Profile: "+gl.getGLProfile());
- System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
// Allocate vertex arrays
colors = Buffers.newDirectFloatBuffer(16);
@@ -99,7 +131,6 @@ public class RedSquareES1 implements GLEventListener {
gl.glColorPointer(4, GL.GL_FLOAT, 0, colors);
// OpenGL Render Settings
- gl.glClearColor(0, 0, 0, 1);
gl.glEnable(GL.GL_DEPTH_TEST);
startTime = System.currentTimeMillis();
@@ -107,37 +138,79 @@ public class RedSquareES1 implements GLEventListener {
System.err.println(Thread.currentThread()+" RedSquareES1.init FIN");
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- System.err.println(Thread.currentThread()+" RedSquareES1.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval);
- GL2ES1 gl = drawable.getGL().getGL2ES1();
- gl.setSwapInterval(swapInterval);
-
+ @Override
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ final GL2ES1 gl = glad.getGL().getGL2ES1();
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval);
+ }
+ reshapeImpl(gl, x, y, width, height, width, height);
+ }
+
+ @Override
+ public void reshapeTile(final TileRendererBase tr,
+ final int tileX, final int tileY, final int tileWidth, final int tileHeight,
+ final int imageWidth, final int imageHeight) {
+ final GL2ES1 gl = tr.getAttachedDrawable().getGL().getGL2ES1();
+ gl.setSwapInterval(0);
+ reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
+ }
+
+ void reshapeImpl(final GL2ES1 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight) {
+ System.err.println(Thread.currentThread()+" RedSquareES1.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse);
+
// Set location in front of camera
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
- gluPerspective(gl, 45.0f, (float)width / (float)height, 1.0f, 100.0f);
+ if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) {
+ gl.glScalef(1f, -1f, 1f);
+ }
+
+ // compute projection parameters 'normal' perspective
+ final float fovy=45f;
+ final float aspect2 = ( (float) imageWidth / (float) imageHeight ) / aspect;
+ final float zNear=1f;
+ final float zFar=100f;
+
+ // compute projection parameters 'normal' frustum
+ final float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear;
+ final float bottom=-1.0f*top;
+ final float left=aspect2*bottom;
+ final float right=aspect2*top;
+ final float w = right - left;
+ final float h = top - bottom;
+
+ // compute projection parameters 'tiled'
+ final float l = left + tileX * w / imageWidth;
+ final float r = l + tileWidth * w / imageWidth;
+ final float b = bottom + tileY * h / imageHeight;
+ final float t = b + tileHeight * h / imageHeight;
+
+ gl.glFrustumf(l, r, b, t, zNear, zFar);
// gl.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f);
+
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+
System.err.println(Thread.currentThread()+" RedSquareES1.reshape FIN");
}
-
- void gluPerspective(GL2ES1 gl, final float fovy, final float aspect, final float zNear, final float zFar) {
- float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear;
- float bottom=-1.0f*top;
- float left=aspect*bottom;
- float right=aspect*top;
- gl.glFrustumf(left, right, bottom, top, zNear, zFar);
- }
- public void display(GLAutoDrawable drawable) {
+ @Override
+ public void display(final GLAutoDrawable drawable) {
curTime = System.currentTimeMillis();
- GL2ES1 gl = drawable.getGL().getGL2ES1();
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
+ if( null != tileRendererInUse ) {
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ } else {
+ gl.glClearColor(0, 0, 0, 0);
+ }
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
// One rotation every four seconds
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -10);
- float ang = ((float) (curTime - startTime) * 360.0f) / 4000.0f;
+ final float ang = doRotate ? ((curTime - startTime) * 360.0f) / 4000.0f : 1f;
gl.glRotatef(ang, 0, 0, 1);
gl.glRotatef(ang, 0, 1, 0);
@@ -149,9 +222,10 @@ public class RedSquareES1 implements GLEventListener {
gl.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
}
- public void dispose(GLAutoDrawable drawable) {
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
System.err.println(Thread.currentThread()+" RedSquareES1.dispose ... ");
- GL2ES1 gl = drawable.getGL().getGL2ES1();
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
gl.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
gl.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
colors.clear();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java
index ff168d9e9..a093cc07f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,18 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.es1.newt;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
@@ -45,9 +46,15 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGearsES1NEWT extends UITestCase {
static int width, height;
+ static boolean forceES2 = false;
+ static boolean forceFFPEmu = false;
+ static int swapInterval = 1;
@BeforeClass
public static void initClass() {
@@ -59,15 +66,19 @@ public class TestGearsES1NEWT extends UITestCase {
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilities caps) throws InterruptedException {
- GLWindow glWindow = GLWindow.create(caps);
+ protected void runTestGL(final GLCapabilities caps, final boolean forceFFPEmu) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Gears NEWT Test");
- glWindow.addGLEventListener(new GearsES1());
+ final GearsES1 demo = new GearsES1(swapInterval);
+ demo.setForceFFPEmu(forceFFPEmu, forceFFPEmu, false, false);
+ glWindow.addGLEventListener(demo);
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ glWindow.addGLEventListener(snap);
- Animator animator = new Animator(glWindow);
- QuitAdapter quitAdapter = new QuitAdapter();
+ final Animator animator = new Animator(glWindow);
+ final QuitAdapter quitAdapter = new QuitAdapter();
//glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
//glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
@@ -76,7 +87,10 @@ public class TestGearsES1NEWT extends UITestCase {
final GLWindow f_glWindow = glWindow;
glWindow.addKeyListener(new KeyAdapter() {
- public void keyTyped(KeyEvent e) {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
if(e.getKeyChar()=='f') {
new Thread() {
public void run() {
@@ -95,6 +109,7 @@ public class TestGearsES1NEWT extends UITestCase {
glWindow.setVisible(true);
animator.setUpdateFPSFrames(1, null);
animator.start();
+ snap.setMakeSnapshot();
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
@@ -105,20 +120,27 @@ public class TestGearsES1NEWT extends UITestCase {
}
@Test
- public void test01() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES1());
- runTestGL(caps);
+ public void test00() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES1());
+ runTestGL(caps, forceFFPEmu);
}
static long duration = 500; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-ffpemu")) {
+ forceFFPEmu = true;
}
}
org.junit.runner.JUnitCore.main(TestGearsES1NEWT.class.getName());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestOlympicES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestOlympicES1NEWT.java
new file mode 100644
index 000000000..a29e9a3a6
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestOlympicES1NEWT.java
@@ -0,0 +1,144 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es1.newt;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.OlympicES1;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestOlympicES1NEWT extends UITestCase {
+ static int width, height;
+ static boolean forceES2 = false;
+ static boolean forceFFPEmu = false;
+ static boolean verboseFFPEmu = false;
+ static int swapInterval = 1;
+ static boolean exclusiveContext = false;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setTitle("Olympic NEWT Test");
+
+ final OlympicES1 demo = new OlympicES1( swapInterval );
+ demo.setForceFFPEmu(forceFFPEmu, verboseFFPEmu, false, false);
+ glWindow.addGLEventListener(demo);
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ glWindow.addGLEventListener(snap);
+
+ final Animator animator = new Animator();
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.setExclusiveContext(exclusiveContext);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+
+ animator.add(glWindow);
+ animator.start();
+ animator.setUpdateFPSFrames(60, System.err);
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread());
+
+ snap.setMakeSnapshot();
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread());
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ Assert.assertEquals(null, glWindow.getExclusiveContextThread());
+ glWindow.destroy();
+ }
+
+ @Test
+ public void test00() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES1());
+ runTestGL(caps);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-exclctx")) {
+ exclusiveContext = true;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-ffpemu")) {
+ forceFFPEmu = true;
+ } else if(args[i].equals("-verbose")) {
+ verboseFFPEmu = true;
+ }
+ }
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceFFPEmu "+forceFFPEmu);
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("exclusiveContext "+exclusiveContext);
+ org.junit.runner.JUnitCore.main(TestOlympicES1NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java
index c327a3005..c164990a4 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.es1.newt;
import com.jogamp.newt.event.KeyAdapter;
@@ -45,9 +45,14 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestRedSquareES1NEWT extends UITestCase {
static int width, height;
+ static boolean forceES2 = false;
+ static boolean forceFFPEmu = false;
@BeforeClass
public static void initClass() {
@@ -59,15 +64,19 @@ public class TestRedSquareES1NEWT extends UITestCase {
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilities caps) throws InterruptedException {
- GLWindow glWindow = GLWindow.create(caps);
+ protected void runTestGL(final GLCapabilities caps, final boolean forceFFPEmu) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Gears NEWT Test");
- glWindow.addGLEventListener(new RedSquareES1());
+ final RedSquareES1 demo = new RedSquareES1();
+ demo.setForceFFPEmu(forceFFPEmu, forceFFPEmu, false, false);
+ glWindow.addGLEventListener(demo);
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ glWindow.addGLEventListener(snap);
- Animator animator = new Animator(glWindow);
- QuitAdapter quitAdapter = new QuitAdapter();
+ final Animator animator = new Animator(glWindow);
+ final QuitAdapter quitAdapter = new QuitAdapter();
//glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
//glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
@@ -76,7 +85,10 @@ public class TestRedSquareES1NEWT extends UITestCase {
final GLWindow f_glWindow = glWindow;
glWindow.addKeyListener(new KeyAdapter() {
- public void keyTyped(KeyEvent e) {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
if(e.getKeyChar()=='f') {
new Thread() {
public void run() {
@@ -95,6 +107,7 @@ public class TestRedSquareES1NEWT extends UITestCase {
glWindow.setVisible(true);
animator.setUpdateFPSFrames(1, null);
animator.start();
+ snap.setMakeSnapshot();
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
@@ -105,20 +118,24 @@ public class TestRedSquareES1NEWT extends UITestCase {
}
@Test
- public void test01() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES1());
- runTestGL(caps);
+ public void test00() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES1());
+ runTestGL(caps, forceFFPEmu);
}
- static long duration = 500; // ms
+ static long duration = 1000; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-ffpemu")) {
+ forceFFPEmu = true;
}
}
org.junit.runner.JUnitCore.main(TestRedSquareES1NEWT.class.getName());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java
index cb3eb4351..c54dad458 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -40,6 +40,7 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.common.nio.Buffers;
import com.jogamp.newt.event.KeyAdapter;
@@ -54,36 +55,36 @@ import com.jogamp.opengl.util.glsl.ShaderState;
/**
* <pre>
* __ __|_ ___________________________________________________________________________ ___|__ __
- * // /\ _ /\ \\
- * //____/ \__ __ _____ _____ _____ _____ _____ | | __ _____ _____ __ __/ \____\\
- * \ \ / / __| | | __| _ | | _ | | | __| | | __| | /\ \ / /
- * \____\/_/ | | | | | | | | | | | __| | | | | | | | | | |__ " \_\/____/
- * /\ \ |_____|_____|_____|__|__|_|_|_|__| | | |_____|_____|_____|_____| _ / /\
- * / \____\ http://jogamp.org |_| /____/ \
- * \ / "' _________________________________________________________________________ `" \ /
+ * // /\ _ /\ \\
+ * //____/ \__ __ _____ _____ _____ _____ _____ | | __ _____ _____ __ __/ \____\\
+ * \ \ / / __| | | __| _ | | _ | | | __| | | __| | /\ \ / /
+ * \____\/_/ | | | | | | | | | | | __| | | | | | | | | | |__ " \_\/____/
+ * /\ \ |_____|_____|_____|__|__|_|_|_|__| | | |_____|_____|_____|_____| _ / /\
+ * / \____\ http://jogamp.org |_| /____/ \
+ * \ / "' _________________________________________________________________________ `" \ /
* \/____. .____\/
- * </pre>
+ * </pre>
*
* <p>
- * JOGL2 port of my PC 4k intro competition entry for Revision 2011. Sure it got a little bigger
+ * JOGL2 port of my PC 4k intro competition entry for Revision 2011. Sure it got a little bigger
* while porting but the shader and control code remained more or less untouched. The intro renders
- * a fullscreen billboard using a single fragment shader. The shader encapsulates basically two
+ * a fullscreen billboard using a single fragment shader. The shader encapsulates basically two
* different routines: A sphere-tracing based raymarcher for a single fractal formula and a bitmap
* orbit trap julia+mandelbrot fractal renderer. Additionally an inline-processing analog-distortion
* filter is applied to all rendered fragments to make the overall look more interesting.
* </p>
*
* <p>
- * The different intro parts are all parameter variations of the two routines in the fragment shader
+ * The different intro parts are all parameter variations of the two routines in the fragment shader
* synched to the music: Parts 3+5 are obviously the mandelbrot and julia bitmap orbit traps, and parts
* 1,2,4 and 6 are pure fractal sphere tracing.
* </p>
*
* <p>
* During the development of the intro it turned out that perfectly raymarching every pixel of the orbit
- * trapped julia+mandelbrot fractal was way to slow even on highend hardware. So I inserted a lowres
+ * trapped julia+mandelbrot fractal was way to slow even on highend hardware. So I inserted a lowres
* intermediate FBO to be used by the bitmap based orbit trap routine wich was ofcourse way faster, but
- * had the obvious upscaling artefacts. Maybe I'll produce a perfect quality version for very patient
+ * had the obvious upscaling artefacts. Maybe I'll produce a perfect quality version for very patient
* people with insane hardware :)
* </p>
*
@@ -119,21 +120,21 @@ public class ElektronenMultiplizierer implements GLEventListener {
//BEGIN --- BaseGlobalEnvironment replacement ---
- private final GLCapabilities mCaps;
+ private final GLCapabilities mCaps;
// private final GLU mGlu;
- private String mCommandLineParameter_BaseRoutineClassName;
- private boolean mCommandLineParameter_MultiSampling;
- private int mCommandLineParameter_NumberOfSampleBuffers;
- private boolean mCommandLineParameter_AnisotropicFiltering;
- private float mCommandLineParameter_AnisotropyLevel;
- private boolean mCommandLineParameter_FrameCapture;
- private boolean mCommandLineParameter_FrameSkip;
+ private final String mCommandLineParameter_BaseRoutineClassName;
+ private final boolean mCommandLineParameter_MultiSampling;
+ private final int mCommandLineParameter_NumberOfSampleBuffers;
+ private final boolean mCommandLineParameter_AnisotropicFiltering;
+ private final float mCommandLineParameter_AnisotropyLevel;
+ private final boolean mCommandLineParameter_FrameCapture;
+ private final boolean mCommandLineParameter_FrameSkip;
private boolean mUsesFullScreenMode;
private int mFrameCounter;
- private int mCommandLineParameter_FrameRate;
+ private final int mCommandLineParameter_FrameRate;
private long mFrameSkipAverageFramerateTimeStart;
- private long mFrameSkipAverageFramerateTimeEnd;
+ private long mFrameSkipAverageFramerateTimeEnd;
private boolean mFrameSkipManual;
// private int mSkippedFramesCounter;
// private BaseMusic mBaseMusic;
@@ -145,7 +146,7 @@ public class ElektronenMultiplizierer implements GLEventListener {
private GLUniformData mScreenDimensionUniform;
private GLArrayDataServer vertices0;
// private GLArrayDataServer texCoords0;
-
+
public String getBaseRoutineClassName() { return mCommandLineParameter_BaseRoutineClassName; }
public boolean preferMultiSampling() { return mCommandLineParameter_MultiSampling; }
public int getNumberOfSamplingBuffers() { return mCommandLineParameter_NumberOfSampleBuffers; }
@@ -157,24 +158,24 @@ public class ElektronenMultiplizierer implements GLEventListener {
public boolean usesFullScreenMode() { return mUsesFullScreenMode; }
class TimeShiftKeys extends KeyAdapter {
- public void keyPressed(KeyEvent e) {
+ public void keyPressed(final KeyEvent e) {
if(KeyEvent.VK_RIGHT == e.getKeyCode()) {
skipFrames(120);
} else if(KeyEvent.VK_LEFT == e.getKeyCode()) {
skipFrames(-120);
- }
- }
+ }
+ }
}
TimeShiftKeys timeShiftKeys;
-
+
public ElektronenMultiplizierer (
- String inBaseRoutineClassName,
- boolean inMultiSampling,
- int inNumberOfSampleBuffers,
- boolean inAnisotropicFiltering,
- float inAnisotropyLevel,
- boolean inFrameCapture,
- boolean inFrameSkip, int desiredFrameRate, int startFrame
+ final String inBaseRoutineClassName,
+ final boolean inMultiSampling,
+ final int inNumberOfSampleBuffers,
+ final boolean inAnisotropicFiltering,
+ final float inAnisotropyLevel,
+ final boolean inFrameCapture,
+ final boolean inFrameSkip, final int desiredFrameRate, final int startFrame
) {
// mGlu = new GLU();
mCommandLineParameter_BaseRoutineClassName = inBaseRoutineClassName;
@@ -195,88 +196,91 @@ public class ElektronenMultiplizierer implements GLEventListener {
mCaps.setAccumGreenBits(1);
mCaps.setAccumRedBits(1);
// turns out we need to have alpha, otherwise no AA will be visible
- mCaps.setAlphaBits(1);
+ mCaps.setAlphaBits(1);
}
-
+
mFrameSkipAverageFramerateTimeStart = 0;
- mFrameCounter = 0;
+ mFrameCounter = 0;
skipFrames(startFrame);
timeShiftKeys = new TimeShiftKeys();
}
-
+
public ElektronenMultiplizierer() {
- this(null, false, -1, false, -1.0f, false, true, 30, 0);
+ this(null, false, -1, false, -1.0f, false, true, 30, 0);
}
-
+
/**
* skip frames by turning back start time
- * @param frames positive or negative values
+ * @param frames positive or negative values
*/
- public void skipFrames(int frames) {
+ public void skipFrames(final int frames) {
final long dft = 1000000000/mCommandLineParameter_FrameRate;
mFrameSkipAverageFramerateTimeStart -= frames * dft ;
mFrameSkipManual = true;
}
-
+
public GLCapabilitiesImmutable getGLCapabilities() {
return mCaps;
}
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
if(drawable instanceof GLWindow) {
final GLWindow glw = (GLWindow) drawable;
glw.addKeyListener(0, timeShiftKeys);
}
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
gl.setSwapInterval(1);
- st = new ShaderState();
+ st = new ShaderState();
final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader",
- "shader/bin", "default", false);
+ "shader/bin", "default", true);
final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
- "shader/bin", "elektronenmultiplizierer_development", false);
- // "shader", "shader/bin", "elektronenmultiplizierer_port", false);
+ "shader/bin", "elektronenmultiplizierer_development", true);
+ // "shader", "shader/bin", "elektronenmultiplizierer_port", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+
final ShaderProgram sp0 = new ShaderProgram();
sp0.add(gl, vp0, System.err);
- sp0.add(gl, fp0, System.err);
+ sp0.add(gl, fp0, System.err);
st.attachShaderProgram(gl, sp0, true);
-
- final float XRESf = (float) drawable.getWidth();
- final float YRESf = (float) drawable.getHeight();
+
+ final float XRESf = drawable.getSurfaceWidth();
+ final float YRESf = drawable.getSurfaceHeight();
mScreenDimensionUniform = new GLUniformData("resolution", 2, Buffers.newDirectFloatBuffer(2));
final FloatBuffer mScreenDimensionV = (FloatBuffer) mScreenDimensionUniform.getBuffer();
mScreenDimensionV.put(0, XRESf);
mScreenDimensionV.put(1, YRESf);
- st.ownUniform(mScreenDimensionUniform);
- st.uniform(gl, mScreenDimensionUniform);
-
+ st.ownUniform(mScreenDimensionUniform);
+ st.uniform(gl, mScreenDimensionUniform);
+
pmvMatrix = new PMVMatrix();
pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
st.ownUniform(pmvMatrixUniform);
st.uniform(gl, pmvMatrixUniform);
-
+
vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
vertices0.putf(0); vertices0.putf(YRESf);
vertices0.putf(XRESf); vertices0.putf(YRESf);
vertices0.putf(0); vertices0.putf(0);
vertices0.putf(XRESf); vertices0.putf(0);
- vertices0.seal(gl, true);
+ vertices0.seal(gl, true);
st.ownAttribute(vertices0, true);
vertices0.enableBuffer(gl, false);
-
+
/**
texCoords0 = GLArrayDataServer.createGLSL("gca_TexCoords", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
texCoords0.putf(0f); texCoords0.putf(1f);
texCoords0.putf(1f); texCoords0.putf(1f);
- texCoords0.putf(0f); texCoords0.putf(0f);
+ texCoords0.putf(0f); texCoords0.putf(0f);
texCoords0.putf(1f); texCoords0.putf(0f);
texCoords0.seal(gl, true);
st.ownAttribute(texCoords0, true);
texCoords0.enableBuffer(gl, false); */
//generate framebufferobject
- int[] result = new int[1];
+ final int[] result = new int[1];
gl.glGenTextures(1, result, 0);
mFrameBufferTextureID = result[0];
gl.glBindTexture(GL_TEXTURE_2D, mFrameBufferTextureID);
@@ -305,20 +309,20 @@ public class ElektronenMultiplizierer implements GLEventListener {
// if NO music is used sync to mainloop start ...
// (add up current time due to possible turned back start time by skip frames)
mFrameSkipAverageFramerateTimeStart += System.nanoTime();
-
+
// mBaseMusic = new BaseMusic(BaseGlobalEnvironment.getInstance().getMusicFileName());
// mBaseMusic.init();
// mBaseMusic.play();
}
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
if (wantsFrameSkip()) {
mFrameSkipAverageFramerateTimeEnd = System.nanoTime();
- double tDesiredFrameRate = (float)getDesiredFramerate();
- double tSingleFrameTime = 1000000000.0f/tDesiredFrameRate;
- double tElapsedTime = mFrameSkipAverageFramerateTimeEnd - mFrameSkipAverageFramerateTimeStart;
- double mFrameCounterTargetValue = tElapsedTime/tSingleFrameTime;
- double mFrameCounterDifference = mFrameCounterTargetValue-mFrameCounter;
+ final double tDesiredFrameRate = getDesiredFramerate();
+ final double tSingleFrameTime = 1000000000.0f/tDesiredFrameRate;
+ final double tElapsedTime = mFrameSkipAverageFramerateTimeEnd - mFrameSkipAverageFramerateTimeStart;
+ final double mFrameCounterTargetValue = tElapsedTime/tSingleFrameTime;
+ final double mFrameCounterDifference = mFrameCounterTargetValue-mFrameCounter;
if (mFrameSkipManual || mFrameCounterDifference>2) {
mFrameCounter+=mFrameCounterDifference;
// mSkippedFramesCounter+=mFrameCounterDifference;
@@ -328,11 +332,11 @@ public class ElektronenMultiplizierer implements GLEventListener {
}
mFrameSkipManual = false;
}
-
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- final int XRES = drawable.getWidth();
- final int YRES = drawable.getHeight();
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ final int XRES = drawable.getSurfaceWidth();
+ final int YRES = drawable.getSurfaceHeight();
// if (!getBaseMusic().isOffline()) {
// //if music IS used sync to first second of music ...
@@ -346,7 +350,7 @@ public class ElektronenMultiplizierer implements GLEventListener {
// mBaseMusic.synchonizeMusic();
//use this for offline rendering/capture ...
- int MMTime_u_ms = (int)((((float)mFrameCounter)*44100.0f)/60.0f);
+ int MMTime_u_ms = (int)(((mFrameCounter)*44100.0f)/60.0f);
//use this for music synched rendering ...
//int MMTime_u_ms = (int)(BaseRoutineRuntime.getInstance().getBaseMusic().getPositionInMilliseconds()*(44100.0f/1000.0f));
//dedicated sync variable for each event ... kinda lame but who cares X-)
@@ -359,7 +363,7 @@ public class ElektronenMultiplizierer implements GLEventListener {
if (MMTime_u_ms>=4438408 && !mSyncEvent_07) { mSyncEvent_07 = true; handleSyncEvent(MMTime_u_ms); }
if (MMTime_u_ms>=5482831 && !mSyncEvent_08) { mSyncEvent_08 = true; handleSyncEvent(MMTime_u_ms); }
//calculate current time based on 60fps reference framerate ...
- MMTime_u_ms = (int)((((float)mFrameCounter)*44100.0f)/60.0f);
+ MMTime_u_ms = (int)(((mFrameCounter)*44100.0f)/60.0f);
gl.glDisable(GL_CULL_FACE);
gl.glDisable(GL_DEPTH_TEST);
@@ -368,13 +372,13 @@ public class ElektronenMultiplizierer implements GLEventListener {
vertices0.enableBuffer(gl, true);
// texCoords0.enableBuffer(gl, true);
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
pmvMatrix.glOrthof(0f, XRES, YRES, 0f, -1f, 1f);
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
st.uniform(gl, pmvMatrixUniform);
-
+
gl.glActiveTexture(GL_TEXTURE0);
//gogogo! O-)
@@ -382,8 +386,8 @@ public class ElektronenMultiplizierer implements GLEventListener {
if (tBrightnessSync<1) {
tBrightnessSync=1;
}
- mEffectTime = (float)((MMTime_u_ms-mEffectSyncTime)/100000.0f);
-
+ mEffectTime = (MMTime_u_ms-mEffectSyncTime)/100000.0f;
+
if (mSyncEventNumber==0 && mEffectTime<4.0f) {
//fadein and fullscreen rotate
tBrightnessSync = mEffectTime/4.0f;
@@ -391,12 +395,12 @@ public class ElektronenMultiplizierer implements GLEventListener {
//fullscrenn mushroom transform
tBrightnessSync = 1.0f-((mEffectTime-12.0f)/3.5f);
}
-
+
if (mSyncEventNumber==0 || mSyncEventNumber==1) {
//zoomin from fog
mEffectNumber = 3;
mEffectTime *= 1.75;
- float tEffectTimeMax = 9.3f;
+ final float tEffectTimeMax = 9.3f;
if (mEffectTime>=tEffectTimeMax) {
mEffectTime=tEffectTimeMax;
}
@@ -421,10 +425,10 @@ public class ElektronenMultiplizierer implements GLEventListener {
mEffectNumber = 6;
mEffectTime *= 0.364f;
}
-
+
gl.glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferObjectID);
- // gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
- GLUniformData en = st.getUniform("en");
+ // gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
+ final GLUniformData en = st.getUniform("en");
if(mSyncEventNumber==7) {
en.setData(2);
}
@@ -434,8 +438,8 @@ public class ElektronenMultiplizierer implements GLEventListener {
en.setData(0);
}
st.uniform(gl, en);
-
- GLUniformData et = st.getUniform("et");
+
+ final GLUniformData et = st.getUniform("et");
st.uniform(gl, et.setData(9.1f));
st.uniform(gl, st.getUniform("tm").setData(MMTime_u_ms/40000.0f));
@@ -444,29 +448,31 @@ public class ElektronenMultiplizierer implements GLEventListener {
if(mSyncEventNumber==4 || mSyncEventNumber==7) {
//render to fbo only when using julia/mandel orbittrap ...
// gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
}
gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
st.uniform(gl, en.setData(mEffectNumber));
st.uniform(gl, et.setData(mEffectTime));
- gl.glEnable(GL_TEXTURE_2D);
+ if( !gl.isGLcore() ) {
+ gl.glEnable(GL_TEXTURE_2D);
+ }
gl.glBindTexture(GL_TEXTURE_2D, mFrameBufferTextureID);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
vertices0.enableBuffer(gl, false);
- // texCoords0.enableBuffer(gl, false);
+ // texCoords0.enableBuffer(gl, false);
st.useProgram(gl, false);
//---
mFrameCounter++;
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
st.useProgram(gl, true);
vertices0.seal(false);
vertices0.rewind();
@@ -474,34 +480,34 @@ public class ElektronenMultiplizierer implements GLEventListener {
vertices0.putf(width); vertices0.putf(height);
vertices0.putf(0); vertices0.putf(0);
vertices0.putf(width); vertices0.putf(0);
- vertices0.seal(gl, true);
+ vertices0.seal(gl, true);
st.ownAttribute(vertices0, true);
vertices0.enableBuffer(gl, false);
-
+
final FloatBuffer mScreenDimensionV = (FloatBuffer) mScreenDimensionUniform.getBuffer();
- mScreenDimensionV.put(0, (float) width);
- mScreenDimensionV.put(1, (float) height);
+ mScreenDimensionV.put(0, width);
+ mScreenDimensionV.put(1, height);
st.uniform(gl, mScreenDimensionUniform);
st.useProgram(gl, false);
- gl.glViewport(0, 0, width, height);
+ gl.glViewport(0, 0, width, height);
}
- public void dispose(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
gl.glDeleteFramebuffers(1, new int[] { mFrameBufferObjectID }, 0);
gl.glDeleteTextures(1, new int[] { mFrameBufferTextureID }, 0);
st.destroy(gl);
if(drawable instanceof GLWindow) {
final GLWindow glw = (GLWindow) drawable;
glw.removeKeyListener(timeShiftKeys);
- }
+ }
}
// public BaseMusic getBaseMusic() {
// return mBaseMusic;
// }
-
+
public void resetFrameCounter() {
mFrameCounter = 0;
}
@@ -525,7 +531,7 @@ public class ElektronenMultiplizierer implements GLEventListener {
protected boolean mSyncEvent_07;
protected boolean mSyncEvent_08;
- public void handleSyncEvent(int inMMTime_u_ms) {
+ public void handleSyncEvent(final int inMMTime_u_ms) {
mSyncTime = inMMTime_u_ms;
mSyncEventNumber++;
System.out.println("NEW SYNC EVENT! tSyncEventNumber="+mSyncEventNumber+" tSyncTime="+mSyncTime);
@@ -533,5 +539,5 @@ public class ElektronenMultiplizierer implements GLEventListener {
mEffectSyncTime = inMMTime_u_ms;
}
}
-
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java
index 992f0261c..42f4c5f6e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java
@@ -1,22 +1,29 @@
/**
- * Copyright (C) 2011 JogAmp Community. All rights reserved.
+ * Copyright 2011 JogAmp Community. All rights reserved.
*
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
*/
package com.jogamp.opengl.test.junit.jogl.demos.es2;
@@ -42,166 +49,163 @@ public class FBOMix2DemosES2 implements GLEventListener {
private final GearsES2 demo0;
private final RedSquareES2 demo1;
private final int swapInterval;
- private int numSamples;
+ private volatile int numSamples;
private boolean demo0Only;
-
-
+
+
private final ShaderState st;
private final PMVMatrix pmvMatrix;
-
- private final FBObject fbo0;
+
+ private final FBObject fbo0;
private final FBObject fbo1;
-
+
private TextureAttachment fbo0Tex;
private TextureAttachment fbo1Tex;
-
+
private ShaderProgram sp0;
private GLUniformData pmvMatrixUniform;
private GLArrayDataServer interleavedVBO;
private GLUniformData texUnit0;
private GLUniformData texUnit1;
-
- public FBOMix2DemosES2(int swapInterval) {
+
+ public FBOMix2DemosES2(final int swapInterval) {
demo0 = new GearsES2(-1);
demo0.setIgnoreFocus(true);
demo1 = new RedSquareES2(-1);
this.swapInterval = swapInterval;
-
+
st = new ShaderState();
- // st.setVerbose(true);
+ // st.setVerbose(true);
pmvMatrix = new PMVMatrix();
-
- fbo0 = new FBObject();
+
+ fbo0 = new FBObject();
fbo1 = new FBObject();
-
+
numSamples = 0;
demo0Only = false;
}
-
- public void setDemo0Only(boolean v) {
- this.demo0Only = v;
+
+ public void setDemo0Only(final boolean v) {
+ this.demo0Only = v;
}
public boolean getDemo0Only() { return demo0Only; }
-
- public void setMSAA(int numSamples) {
- this.numSamples=numSamples;
+
+ public void setMSAA(final int numSamples) {
+ this.numSamples=numSamples;
}
public int getMSAA() { return numSamples; }
-
- public void setDoRotation(boolean rotate) { demo1.setDoRotation(rotate); }
-
- static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
- static final String gl2_prelude = "#version 110\n";
-
+
+ public void setDoRotation(final boolean rotate) { demo1.setDoRotation(rotate); }
+
@Override
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
-
+
demo0.init(drawable);
demo1.init(drawable);
-
+
final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, FBOMix2DemosES2.class, "shader",
"shader/bin", "texture01_xxx", true);
final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, FBOMix2DemosES2.class, "shader",
"shader/bin", "texture02_xxx", true);
-
- // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
- int fp0Pos;
- if(gl.isGLES2()) {
- vp0.insertShaderSource(0, 0, es2_prelude[0]);
- fp0Pos = fp0.insertShaderSource(0, 0, es2_prelude[0]);
- } else {
- vp0.insertShaderSource(0, 0, gl2_prelude);
- fp0Pos = fp0.insertShaderSource(0, 0, gl2_prelude);
- }
- if(gl.isGLES2()) {
- fp0Pos = fp0.insertShaderSource(0, fp0Pos, es2_prelude[1]);
- }
-
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+
sp0 = new ShaderProgram();
sp0.add(gl, vp0, System.err);
- sp0.add(gl, fp0, System.err);
+ sp0.add(gl, fp0, System.err);
st.attachShaderProgram(gl, sp0, true);
-
+
pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
- st.ownUniform(pmvMatrixUniform);
+ st.ownUniform(pmvMatrixUniform);
st.uniform(gl, pmvMatrixUniform);
-
+
interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
- {
- interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
- interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ {
+ interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
//interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER);
interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
- FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
-
+ final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
+
for(int i=0; i<4; i++) {
ib.put(s_quadVertices, i*3, 3);
- ib.put(s_quadColors, i*4, 4);
+ ib.put(s_quadColors, i*4, 4);
//ib.put(s_cubeNormals, i*3, 3);
ib.put(s_quadTexCoords, i*2, 2);
- }
+ }
}
interleavedVBO.seal(gl, true);
interleavedVBO.enableBuffer(gl, false);
st.ownAttribute(interleavedVBO, true);
-
+
texUnit0 = new GLUniformData("mgl_Texture0", 0);
- st.ownUniform(texUnit0);
+ st.ownUniform(texUnit0);
st.uniform(gl, texUnit0);
texUnit1 = new GLUniformData("mgl_Texture1", 1);
- st.ownUniform(texUnit1);
+ st.ownUniform(texUnit1);
st.uniform(gl, texUnit1);
-
+
st.useProgram(gl, false);
-
+
System.err.println("**** Init");
- resetFBOs(gl, drawable);
-
- fbo0.attachRenderbuffer(gl, Type.DEPTH, 24);
- fbo0.unbind(gl);
- fbo1.attachRenderbuffer(gl, Type.DEPTH, 24);
- fbo1.unbind(gl);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
-
- numSamples=fbo0.getNumSamples();
+ initFBOs(gl, drawable);
+
+ gl.glEnable(GL.GL_DEPTH_TEST);
}
-
- /** Since we switch MSAA and non-MSAA we need to take extra care, i.e. sync msaa for both FBOs ..*/
- private void resetFBOs(GL gl, GLAutoDrawable drawable) {
- // remove all texture attachments, since MSAA uses just color-render-buffer
- // and non-MSAA uses texture2d-buffer
- fbo0.detachAllColorbuffer(gl);
- fbo1.detachAllColorbuffer(gl);
-
- fbo0.reset(gl, drawable.getWidth(), drawable.getHeight(), numSamples);
- fbo1.reset(gl, drawable.getWidth(), drawable.getHeight(), numSamples);
+
+ private void initFBOs(final GL gl, final GLAutoDrawable drawable) {
+ fbo0.init(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples);
+ fbo1.init(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples);
if(fbo0.getNumSamples() != fbo1.getNumSamples()) {
throw new InternalError("sample size mismatch: \n\t0: "+fbo0+"\n\t1: "+fbo1);
- }
+ }
numSamples = fbo0.getNumSamples();
-
+
if(numSamples>0) {
fbo0.attachColorbuffer(gl, 0, true);
+ fbo0.resetSamplingSink(gl);
fbo1.attachColorbuffer(gl, 0, true);
- fbo0Tex = fbo0.getSamplingSink();
- fbo1Tex = fbo1.getSamplingSink();
+ fbo1.resetSamplingSink(gl);
+ fbo0Tex = fbo0.getSamplingSink().getTextureAttachment();
+ fbo1Tex = fbo1.getSamplingSink().getTextureAttachment();
} else {
fbo0Tex = fbo0.attachTexture2D(gl, 0, true);
fbo1Tex = fbo1.attachTexture2D(gl, 0, true);
- }
+ }
+ numSamples=fbo0.getNumSamples();
+ fbo0.attachRenderbuffer(gl, Type.DEPTH, FBObject.CHOSEN_BITS);
+ fbo0.unbind(gl);
+ fbo1.attachRenderbuffer(gl, Type.DEPTH, FBObject.CHOSEN_BITS);
+ fbo1.unbind(gl);
+ }
+
+ private void resetFBOs(final GL gl, final GLAutoDrawable drawable) {
+ fbo0.reset(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples);
+ fbo1.reset(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), numSamples);
+ if(fbo0.getNumSamples() != fbo1.getNumSamples()) {
+ throw new InternalError("sample size mismatch: \n\t0: "+fbo0+"\n\t1: "+fbo1);
+ }
+ numSamples = fbo0.getNumSamples();
+ if(numSamples>0) {
+ fbo0Tex = fbo0.getSamplingSink().getTextureAttachment();
+ fbo1Tex = fbo1.getSamplingSink().getTextureAttachment();
+ } else {
+ fbo0Tex = fbo0.getColorbuffer(0).getTextureAttachment();
+ fbo1Tex = fbo1.getColorbuffer(0).getTextureAttachment();
+ }
}
@Override
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
demo0.dispose(drawable);
demo1.dispose(drawable);
fbo0.destroy(gl);
fbo1.destroy(gl);
st.destroy(gl);
-
+
fbo0Tex = null;
fbo1Tex = null;
sp0 = null;
@@ -210,32 +214,32 @@ public class FBOMix2DemosES2 implements GLEventListener {
}
@Override
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
if( fbo0.getNumSamples() != numSamples ) {
System.err.println("**** NumSamples: "+fbo0.getNumSamples()+" -> "+numSamples);
resetFBOs(gl, drawable);
}
-
+
if(0 < numSamples) {
gl.glEnable(GL.GL_MULTISAMPLE);
}
-
+
fbo0.bind(gl);
demo0.display(drawable);
fbo0.unbind(gl);
-
+
if(!demo0Only) {
fbo1.bind(gl);
demo1.display(drawable);
fbo1.unbind(gl);
}
-
+
st.useProgram(gl, true);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
-
+
gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue());
fbo0.use(gl, fbo0Tex);
if(!demo0Only) {
@@ -243,68 +247,68 @@ public class FBOMix2DemosES2 implements GLEventListener {
fbo1.use(gl, fbo1Tex);
}
interleavedVBO.enableBuffer(gl, true);
-
- gl.glEnable(GL.GL_TEXTURE_2D);
-
+
+ if( !gl.isGLcore() ) {
+ gl.glEnable(GL.GL_TEXTURE_2D);
+ }
+
gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
-
+
interleavedVBO.enableBuffer(gl, false);
fbo0.unuse(gl);
if(!demo0Only) {
fbo1.unuse(gl);
}
-
- st.useProgram(gl, false);
+
+ st.useProgram(gl, false);
}
@Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- if(-1 != swapInterval) {
+
+ if(-1 != swapInterval) {
gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
}
-
- // if(drawable.getWidth() == fbo0.getWidth() && drawable.getHeight() == fbo0.getHeight() ) {
- System.err.println("**** Reshape: "+width+"x"+height);
- resetFBOs(gl, drawable);
- //}
-
+
+ System.err.println("**** Reshape: "+width+"x"+height);
+ resetFBOs(gl, drawable);
+
fbo0.bind(gl);
demo0.reshape(drawable, x, y, width, height);
fbo0.unbind(gl);
fbo1.bind(gl);
demo1.reshape(drawable, x, y, width, height);
fbo1.unbind(gl);
-
+
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
-
+
st.useProgram(gl, true);
st.uniform(gl, pmvMatrixUniform);
st.useProgram(gl, false);
-
+
}
- private static final float[] s_quadVertices = {
+ private static final float[] s_quadVertices = {
-1f, -1f, 0f, // LB
1f, -1f, 0f, // RB
-1f, 1f, 0f, // LT
- 1f, 1f, 0f // RT
+ 1f, 1f, 0f // RT
};
- private static final float[] s_quadColors = {
+ private static final float[] s_quadColors = {
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f };
- private static final float[] s_quadTexCoords = {
+ private static final float[] s_quadTexCoords = {
0f, 0f, // LB
1f, 0f, // RB
- 0f, 1f, // LT
+ 0f, 1f, // LT
1f, 1f // RT
};
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
index d991e7635..a548d4ccf 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
@@ -7,10 +7,10 @@
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -22,53 +22,84 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2;
import com.jogamp.common.nio.Buffers;
import com.jogamp.newt.Window;
+import com.jogamp.newt.event.GestureHandler;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
-import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.event.PinchToZoomGesture;
+import com.jogamp.newt.event.GestureHandler.GestureEvent;
+import com.jogamp.opengl.GLRendererQuirks;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.VectorUtil;
import com.jogamp.opengl.test.junit.jogl.demos.GearsObject;
+import com.jogamp.opengl.util.CustomGLEventListener;
import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.TileRendererBase;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.util.stereo.EyeParameter;
+import com.jogamp.opengl.util.stereo.EyePose;
+import com.jogamp.opengl.util.stereo.StereoGLEventListener;
+
import java.nio.FloatBuffer;
import javax.media.nativewindow.NativeWindow;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
/**
* GearsES2.java <BR>
* @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P>
*/
-public class GearsES2 implements GLEventListener {
+public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRendererListener {
private final FloatBuffer lightPos = Buffers.newDirectFloatBuffer( new float[] { 5.0f, 5.0f, 10.0f } );
-
+
private ShaderState st = null;
private PMVMatrix pmvMatrix = null;
private GLUniformData pmvMatrixUniform = null;
private GLUniformData colorU = null;
- private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f;
- private GearsObjectES2 gear1=null, gear2=null, gear3=null;
+ private float view_rotx = 20.0f, view_roty = 30.0f;
+ private boolean flipVerticalInGLOrientation = false;
+ private final boolean customRendering = false;
+
+ private final float view_rotz = 0.0f;
+ private float panX = 0.0f, panY = 0.0f, panZ=0.0f;
+ private volatile GearsObjectES2 gear1=null, gear2=null, gear3=null;
+ private GearsES2 sharedGears = null;
+ private Object syncObjects = null;
+ private boolean useMappedBuffers = false;
+ private boolean validateBuffers = false;
+ private volatile boolean usesSharedGears = false;
+ private FloatBuffer gear1Color=GearsObject.red, gear2Color=GearsObject.green, gear3Color=GearsObject.blue;
private float angle = 0.0f;
private int swapInterval = 0;
- private boolean pmvUseBackingArray = true; // the default for PMVMatrix now, since it's faster
// private MouseListener gearsMouse = new TraceMouseAdapter(new GearsMouseAdapter());
- private MouseListener gearsMouse = new GearsMouseAdapter();
- private KeyListener gearsKeys = new GearsKeyAdapter();
+ public MouseListener gearsMouse = new GearsMouseAdapter();
+ public KeyListener gearsKeys = new GearsKeyAdapter();
+ private TileRendererBase tileRendererInUse = null;
+ private boolean doRotateBeforePrinting;
- private int prevMouseX, prevMouseY;
private boolean doRotate = true;
- private boolean isInitialized = false;
- boolean ignoreFocus = false;
+ private boolean ignoreFocus = false;
+ private float[] clearColor = null;
+ private boolean clearBuffers = true;
+ private boolean verbose = true;
+ private volatile boolean isInit = false;
- public GearsES2(int swapInterval) {
+ private PinchToZoomGesture pinchToZoomGesture = null;
+
+
+ public GearsES2(final int swapInterval) {
this.swapInterval = swapInterval;
}
@@ -76,17 +107,49 @@ public class GearsES2 implements GLEventListener {
this.swapInterval = 1;
}
- public void setIgnoreFocus(boolean v) { ignoreFocus = v; }
- public void setDoRotation(boolean rotate) { this.doRotate = rotate; }
-
- public void setPMVUseBackingArray(boolean pmvUseBackingArray) {
- this.pmvUseBackingArray = pmvUseBackingArray;
+ @Override
+ public void addTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = tr;
+ doRotateBeforePrinting = doRotate;
+ setDoRotation(false);
+ }
+ @Override
+ public void removeTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = null;
+ setDoRotation(doRotateBeforePrinting);
+ }
+ @Override
+ public void startTileRendering(final TileRendererBase tr) {
+ System.err.println("GearsES2.startTileRendering: "+sid()+""+tr);
}
-
- public void setGears(GearsObjectES2 g1, GearsObjectES2 g2, GearsObjectES2 g3) {
- gear1 = g1;
- gear2 = g2;
- gear3 = g3;
+ @Override
+ public void endTileRendering(final TileRendererBase tr) {
+ System.err.println("GearsES2.endTileRendering: "+sid()+""+tr);
+ }
+
+ public void setIgnoreFocus(final boolean v) { ignoreFocus = v; }
+ public void setDoRotation(final boolean rotate) { this.doRotate = rotate; }
+ public void setClearBuffers(final boolean v) { clearBuffers = v; }
+ public void setVerbose(final boolean v) { verbose = v; }
+ public void setFlipVerticalInGLOrientation(final boolean v) { flipVerticalInGLOrientation=v; }
+
+ /** float[4] */
+ public void setClearColor(final float[] clearColor) {
+ this.clearColor = clearColor;
+ }
+
+ public void setGearsColors(final FloatBuffer gear1Color, final FloatBuffer gear2Color, final FloatBuffer gear3Color) {
+ this.gear1Color = gear1Color;
+ this.gear2Color = gear2Color;
+ this.gear3Color = gear3Color;
+ }
+
+ public void setSharedGears(final GearsES2 shared) {
+ sharedGears = shared;
+ }
+
+ public void setSyncObjects(final Object sync) {
+ syncObjects = sync;
}
/**
@@ -104,35 +167,61 @@ public class GearsES2 implements GLEventListener {
*/
public GearsObjectES2 getGear3() { return gear3; }
+ public boolean usesSharedGears() { return usesSharedGears; }
+
+ public void setUseMappedBuffers(final boolean v) { useMappedBuffers = v; }
+ public void setValidateBuffers(final boolean v) { validateBuffers = v; }
+
+ public PMVMatrix getPMVMatrix() {
+ return pmvMatrix;
+ }
+
+ private static final int TIME_OUT = 2000; // 2s
+ private static final int POLL_DIVIDER = 20; // TO/20
+ private static final int TIME_SLICE = TIME_OUT / POLL_DIVIDER ;
+
+ /**
+ * @return True if this GLEventListener became initialized within TIME_OUT 2s
+ */
+ public boolean waitForInit(final boolean initialized) throws InterruptedException {
+ int wait;
+ for (wait=0; wait<POLL_DIVIDER && initialized != isInit ; wait++) {
+ Thread.sleep(TIME_SLICE);
+ }
+ return wait<POLL_DIVIDER;
+ }
+
+ private final String sid() { return "0x"+Integer.toHexString(hashCode()); }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ if(null != sharedGears && !sharedGears.isInit() ) {
+ System.err.println(Thread.currentThread()+" GearsES2.init.0 "+sid()+": pending shared Gears .. re-init later XXXXX");
+ drawable.setGLEventListenerInitState(this, false);
+ return;
+ }
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" GearsES2.init.0 "+sid()+": tileRendererInUse "+tileRendererInUse+", "+this);
+ System.err.println("GearsES2 init "+sid()+" on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+ }
+ if( !gl.hasGLSL() ) {
+ System.err.println("No GLSL available, no rendering.");
+ return;
+ }
- public void init(GLAutoDrawable drawable) {
- if(isInitialized) {
- System.err.println(Thread.currentThread()+" GearsES2.init skipped!");
- return;
- }
- isInitialized = true;
- System.err.println(Thread.currentThread()+" GearsES2.init ...");
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- System.err.println("GearsES2 init on "+Thread.currentThread());
- System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
- System.err.println("INIT GL IS: " + gl.getClass().getName());
- System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
- System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
- System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
- System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
- System.err.println("GL Profile: "+gl.getGLProfile());
- System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
-
- gl.glEnable(GL.GL_DEPTH_TEST);
-
st = new ShaderState();
// st.setVerbose(true);
final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader",
- "shader/bin", "gears", false);
+ "shader/bin", "gears", true);
final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
- "shader/bin", "gears", false);
+ "shader/bin", "gears", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp0 = new ShaderProgram();
sp0.add(gl, vp0, System.err);
sp0.add(gl, fp0, System.err);
@@ -140,13 +229,13 @@ public class GearsES2 implements GLEventListener {
// Use debug pipeline
// drawable.setGL(new DebugGL(drawable.getGL()));
- pmvMatrix = new PMVMatrix(pmvUseBackingArray);
+ pmvMatrix = new PMVMatrix();
st.attachObject("pmvMatrix", pmvMatrix);
pmvMatrixUniform = new GLUniformData("pmvMatrix", 4, 4, pmvMatrix.glGetPMvMvitMatrixf()); // P, Mv, Mvi and Mvit
st.ownUniform(pmvMatrixUniform);
st.uniform(gl, pmvMatrixUniform);
- GLUniformData lightU = new GLUniformData("lightPos", 3, lightPos);
+ final GLUniformData lightU = new GLUniformData("lightPos", 3, lightPos);
st.ownUniform(lightU);
st.uniform(gl, lightU);
@@ -154,112 +243,271 @@ public class GearsES2 implements GLEventListener {
st.ownUniform(colorU);
st.uniform(gl, colorU);
- if(null == gear1) {
- gear1 = new GearsObjectES2(1.0f, 4.0f, 1.0f, 20, 0.7f, pmvMatrix, pmvMatrixUniform, colorU);
- System.err.println("gear1 created: "+gear1);
- } else {
- gear1 = new GearsObjectES2(gear1, pmvMatrix, pmvMatrixUniform, colorU);
- System.err.println("gear1 reused: "+gear1);
- }
-
- if(null == gear2) {
- gear2 = new GearsObjectES2(0.5f, 2.0f, 2.0f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU);
- System.err.println("gear2 created: "+gear2);
+ if( null != sharedGears ) {
+ gear1 = new GearsObjectES2(sharedGears.getGear1(), st, pmvMatrix, pmvMatrixUniform, colorU);
+ gear2 = new GearsObjectES2(sharedGears.getGear2(), st, pmvMatrix, pmvMatrixUniform, colorU);
+ gear3 = new GearsObjectES2(sharedGears.getGear3(), st, pmvMatrix, pmvMatrixUniform, colorU);
+ usesSharedGears = true;
+ if(verbose) {
+ System.err.println("gear1 "+sid()+" created w/ share: "+sharedGears.getGear1()+" -> "+gear1);
+ System.err.println("gear2 "+sid()+" created w/ share: "+sharedGears.getGear2()+" -> "+gear2);
+ System.err.println("gear3 "+sid()+" created w/ share: "+sharedGears.getGear3()+" -> "+gear3);
+ }
+ if( gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync) ) {
+ syncObjects = sharedGears;
+ System.err.println("Shared GearsES2: Synchronized Objects due to quirk "+GLRendererQuirks.toString(GLRendererQuirks.NeedSharedObjectSync));
+ } else if( null == syncObjects ) {
+ syncObjects = new Object();
+ System.err.println("Shared GearsES2: Unsynchronized Objects");
+ }
} else {
- gear2 = new GearsObjectES2(gear2, pmvMatrix, pmvMatrixUniform, colorU);
- System.err.println("gear2 reused: "+gear2);
+ gear1 = new GearsObjectES2(gl, useMappedBuffers, st, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers);
+ if(verbose) {
+ System.err.println("gear1 "+sid()+" created: "+gear1);
+ }
+
+ gear2 = new GearsObjectES2(gl, useMappedBuffers, st, gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers);
+ if(verbose) {
+ System.err.println("gear2 "+sid()+" created: "+gear2);
+ }
+
+ gear3 = new GearsObjectES2(gl, useMappedBuffers, st, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers);
+ if(verbose) {
+ System.err.println("gear3 "+sid()+" created: "+gear2);
+ }
+ if( null == syncObjects ) {
+ syncObjects = new Object();
+ }
}
-
- if(null == gear3) {
- gear3 = new GearsObjectES2(1.3f, 2.0f, 0.5f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU);
- System.err.println("gear3 created: "+gear3);
- } else {
- gear3 = new GearsObjectES2(gear3, pmvMatrix, pmvMatrixUniform, colorU);
- System.err.println("gear3 reused: "+gear3);
- }
-
+
final Object upstreamWidget = drawable.getUpstreamWidget();
if (upstreamWidget instanceof Window) {
final Window window = (Window) upstreamWidget;
window.addMouseListener(gearsMouse);
window.addKeyListener(gearsKeys);
+ window.addGestureListener(pinchToZoomListener);
+ pinchToZoomGesture = new PinchToZoomGesture(drawable.getNativeSurface(), false);
+ window.addGestureHandler(pinchToZoomGesture);
} else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) {
final java.awt.Component comp = (java.awt.Component) upstreamWidget;
- new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse).addTo(comp);
- new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys).addTo(comp);
+ new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse, drawable).addTo(comp);
+ new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys, drawable).addTo(comp);
}
+
st.useProgram(gl, false);
-
- System.err.println(Thread.currentThread()+" GearsES2.init FIN");
+
+ gl.glFinish(); // make sure .. for shared context (impacts OSX 10.9)
+
+ isInit = true;
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" GearsES2.init.X "+sid()+" FIN "+this);
+ }
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- System.err.println(Thread.currentThread()+" GearsES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval);
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ public final boolean isInit() { return isInit; }
+ private final GestureHandler.GestureListener pinchToZoomListener = new GestureHandler.GestureListener() {
+ @Override
+ public void gestureDetected(final GestureEvent gh) {
+ final PinchToZoomGesture.ZoomEvent ze = (PinchToZoomGesture.ZoomEvent) gh;
+ final float zoom = ze.getZoom(); // * ( ze.getTrigger().getPointerCount() - 1 ); <- too much ..
+ panZ = zoom * 30f - 30f; // [0 .. 2] -> [-30f .. 30f]
+ }
+ };
+
+ @Override
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ if( !isInit ) { return; }
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
if(-1 != swapInterval) {
- gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ gl.setSwapInterval(swapInterval);
}
-
- st.useProgram(gl, true);
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
- pmvMatrix.glLoadIdentity();
-
- if(height>width) {
- float h = (float)height / (float)width;
- pmvMatrix.glFrustumf(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
+ reshapeImpl(gl, x, y, width, height, width, height);
+ }
+
+ @Override
+ public void reshapeTile(final TileRendererBase tr,
+ final int tileX, final int tileY, final int tileWidth, final int tileHeight,
+ final int imageWidth, final int imageHeight) {
+ if( !isInit ) { return; }
+ final GL2ES2 gl = tr.getAttachedDrawable().getGL().getGL2ES2();
+ gl.setSwapInterval(0);
+ reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
+ }
+
+ private float zNear = 5f;
+ private float zFar = 10000f;
+ private float zViewDist = 40.0f;
+
+ public void setZ(final float zNear, final float zFar, final float zViewDist) {
+ this.zNear = zNear;
+ this.zFar = zFar;
+ this.zViewDist = zViewDist;
+ }
+
+ void reshapeImpl(final GL2ES2 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight) {
+ final boolean msaa = gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers();
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" GearsES2.reshape "+sid()+" "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", msaa "+msaa+", tileRendererInUse "+tileRendererInUse);
+ }
+
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+
+ // compute projection parameters 'normal'
+ float left, right, bottom, top;
+ if( imageHeight > imageWidth ) {
+ final float a = (float)imageHeight / (float)imageWidth;
+ left = -1.0f;
+ right = 1.0f;
+ bottom = -a;
+ top = a;
} else {
- float h = (float)width / (float)height;
- pmvMatrix.glFrustumf(-h, h, -1.0f, 1.0f, 5.0f, 60.0f);
+ final float a = (float)imageWidth / (float)imageHeight;
+ left = -a;
+ right = a;
+ bottom = -1.0f;
+ top = 1.0f;
+ }
+ final float w = right - left;
+ final float h = top - bottom;
+
+ // compute projection parameters 'tiled'
+ final float l = left + tileX * w / imageWidth;
+ final float r = l + tileWidth * w / imageWidth;
+ final float b = bottom + tileY * h / imageHeight;
+ final float t = b + tileHeight * h / imageHeight;
+
+ final float _w = r - l;
+ final float _h = t - b;
+ if(verbose) {
+ System.err.println(">> GearsES2 "+sid()+", angle "+angle+", [l "+left+", r "+right+", b "+bottom+", t "+top+"] "+w+"x"+h+" -> [l "+l+", r "+r+", b "+b+", t "+t+"] "+_w+"x"+_h+", v-flip "+flipVerticalInGLOrientation);
}
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
- pmvMatrix.glTranslatef(0.0f, 0.0f, -40.0f);
+ if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) {
+ pmvMatrix.glScalef(1f, -1f, 1f);
+ }
+ pmvMatrix.glFrustumf(l, r, b, t, zNear, zFar);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glTranslatef(0.0f, 0.0f, -zViewDist);
+ st.useProgram(gl, true);
st.uniform(gl, pmvMatrixUniform);
st.useProgram(gl, false);
-
- // System.err.println(Thread.currentThread()+" GearsES2.reshape FIN");
}
// private boolean useAndroidDebug = false;
- public void dispose(GLAutoDrawable drawable) {
- if(!isInitialized) {
- System.err.println(Thread.currentThread()+" GearsES2.dispose skipped!");
- return;
+ private final float[] mat4Tmp1 = new float[16];
+ private final float[] mat4Tmp2 = new float[16];
+ private final float[] vec3Tmp1 = new float[3];
+ private final float[] vec3Tmp2 = new float[3];
+ private final float[] vec3Tmp3 = new float[3];
+
+ @Override
+ public void reshapeForEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height,
+ final EyeParameter eyeParam, final EyePose eyePose) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ final float[] mat4Projection = FloatUtil.makePerspective(mat4Tmp1, 0, true, eyeParam.fovhv, zNear, zFar);
+ if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) {
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glScalef(1f, -1f, 1f);
+ pmvMatrix.glMultMatrixf(mat4Projection, 0);
+ } else {
+ pmvMatrix.glLoadMatrixf(mat4Projection, 0);
+ }
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+
+ final Quaternion rollPitchYaw = new Quaternion();
+ // private final float eyeYaw = FloatUtil.PI; // 180 degrees in radians
+ // rollPitchYaw.rotateByAngleY(eyeYaw);
+ final float[] shiftedEyePos = rollPitchYaw.rotateVector(vec3Tmp1, 0, eyePose.position, 0);
+ VectorUtil.addVec3(shiftedEyePos, shiftedEyePos, eyeParam.positionOffset);
+
+ rollPitchYaw.mult(eyePose.orientation);
+ final float[] up = rollPitchYaw.rotateVector(vec3Tmp2, 0, VectorUtil.VEC3_UNIT_Y, 0);
+ final float[] forward = rollPitchYaw.rotateVector(vec3Tmp3, 0, VectorUtil.VEC3_UNIT_Z_NEG, 0);
+ final float[] center = VectorUtil.addVec3(forward, shiftedEyePos, forward);
+
+ final float[] mLookAt = FloatUtil.makeLookAt(mat4Tmp1, 0, shiftedEyePos, 0, center, 0, up, 0, mat4Tmp2);
+ final float[] mViewAdjust = FloatUtil.makeTranslation(mat4Tmp2, true, eyeParam.distNoseToPupilX, eyeParam.distMiddleToPupilY, eyeParam.eyeReliefZ);
+ final float[] mat4Modelview = FloatUtil.multMatrix(mViewAdjust, mLookAt);
+
+ pmvMatrix.glLoadMatrixf(mat4Modelview, 0);
+ pmvMatrix.glTranslatef(0.0f, 0.0f, -zViewDist);
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( !isInit ) { return; }
+ isInit = false;
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" GearsES2.dispose "+sid()+": tileRendererInUse "+tileRendererInUse);
}
- isInitialized = false;
- System.err.println(Thread.currentThread()+" GearsES2.dispose ... ");
final Object upstreamWidget = drawable.getUpstreamWidget();
- if (upstreamWidget instanceof Window) {
+ if (upstreamWidget instanceof Window) {
final Window window = (Window) upstreamWidget;
window.removeMouseListener(gearsMouse);
window.removeKeyListener(gearsKeys);
+ window.removeGestureHandler(pinchToZoomGesture);
+ pinchToZoomGesture = null;
+ window.removeGestureListener(pinchToZoomListener);
+ }
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if( !gl.hasGLSL() ) {
+ return;
}
- GL2ES2 gl = drawable.getGL().getGL2ES2();
st.useProgram(gl, false);
gear1.destroy(gl);
gear1 = null;
gear2.destroy(gl);
gear2 = null;
gear3.destroy(gl);
- gear3 = null;
+ gear3 = null;
pmvMatrix = null;
- colorU = null;
+ colorU = null;
st.destroy(gl);
st = null;
+ sharedGears = null;
+ syncObjects = null;
+
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" GearsES2.dispose "+sid()+" FIN");
+ }
+ }
- System.err.println(Thread.currentThread()+" GearsES2.dispose FIN");
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ display(drawable, 0);
}
- public void display(GLAutoDrawable drawable) {
+ @Override
+ public void display(final GLAutoDrawable drawable, final int flags) {
+ if( !isInit ) { return; }
+ if(null != sharedGears && !sharedGears.isInit() ) { return; }
+ final GLAnimatorControl anim = drawable.getAnimator();
+ if( verbose && ( null == anim || !anim.isAnimating() ) ) {
+ System.err.println(Thread.currentThread()+" GearsES2.display "+sid()+" "+drawable.getSurfaceWidth()+"x"+drawable.getSurfaceHeight()+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(drawable.getHandle()));
+ }
+
+ final boolean repeatedFrame = 0 != ( CustomGLEventListener.DISPLAY_REPEAT & flags );
+ final boolean dontClear = 0 != ( CustomGLEventListener.DISPLAY_DONTCLEAR & flags );
+
// Turn the gears' teeth
- if(doRotate) {
- angle += 2.0f;
+ if( doRotate && !repeatedFrame ) {
+ angle += 0.5f;
}
// Get the GL corresponding to the drawable we are animating
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
final boolean hasFocus;
final Object upstreamWidget = drawable.getUpstreamWidget();
@@ -268,50 +516,82 @@ public class GearsES2 implements GLEventListener {
} else {
hasFocus = true;
}
-
- gl.glEnable(GL.GL_CULL_FACE);
-
- if( ignoreFocus || hasFocus ) {
- gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- } else {
- gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
- }
-
- // Special handling for the case where the GLJPanel is translucent
- // and wants to be composited with other Java 2D content
- if (GLProfile.isAWTAvailable() &&
- (drawable instanceof javax.media.opengl.awt.GLJPanel) &&
- !((javax.media.opengl.awt.GLJPanel) drawable).isOpaque() &&
- ((javax.media.opengl.awt.GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) {
- gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
- } else {
- gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+ if( clearBuffers && !dontClear ) {
+ if( null != clearColor ) {
+ gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ } else if( null != tileRendererInUse ) {
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ } else if( ignoreFocus || hasFocus ) {
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ } else {
+ gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
+ }
+ // Special handling for the case where the GLJPanel is translucent
+ // and wants to be composited with other Java 2D content
+ if (GLProfile.isAWTAvailable() &&
+ (drawable instanceof javax.media.opengl.awt.GLJPanel) &&
+ !((javax.media.opengl.awt.GLJPanel) drawable).isOpaque() &&
+ ((javax.media.opengl.awt.GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) {
+ gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
+ } else {
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
}
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+
+ setGLStates(gl, true);
st.useProgram(gl, true);
pmvMatrix.glPushMatrix();
+ pmvMatrix.glTranslatef(panX, panY, panZ);
pmvMatrix.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
pmvMatrix.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
pmvMatrix.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
- gear1.draw(gl, -3.0f, -2.0f, 1f * angle - 0f, GearsObject.red);
- gear2.draw(gl, 3.1f, -2.0f, -2f * angle - 9.0f, GearsObject.green);
- gear3.draw(gl, -3.1f, 4.2f, -2f * angle - 25.0f, GearsObject.blue);
+ synchronized ( syncObjects ) {
+ gear1.draw(gl, -3.0f, -2.0f, 1f * angle - 0f);
+ gear2.draw(gl, 3.1f, -2.0f, -2f * angle - 9.0f);
+ gear3.draw(gl, -3.1f, 4.2f, -2f * angle - 25.0f);
+ }
pmvMatrix.glPopMatrix();
st.useProgram(gl, false);
-
- gl.glDisable(GL.GL_CULL_FACE);
+
+ setGLStates(gl, false);
}
-
+
+ public void setGLStates(final GL2ES2 gl, final boolean enable) {
+ // Culling only possible if we do not flip the projection matrix
+ final boolean useCullFace = ! ( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() || customRendering );
+ if( enable ) {
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ if( useCullFace ) {
+ gl.glEnable(GL.GL_CULL_FACE);
+ }
+ } else {
+ gl.glDisable(GL.GL_DEPTH_TEST);
+ if( useCullFace ) {
+ gl.glDisable(GL.GL_CULL_FACE);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "GearsES2[obj "+sid()+" isInit "+isInit+", usesShared "+usesSharedGears+", 1 "+gear1+", 2 "+gear2+", 3 "+gear3+", sharedGears "+sharedGears+"]";
+ }
+
boolean confinedFixedCenter = false;
-
- public void setConfinedFixedCenter(boolean v) {
+
+ public void setConfinedFixedCenter(final boolean v) {
confinedFixedCenter = v;
}
-
- class GearsKeyAdapter extends KeyAdapter {
- public void keyPressed(KeyEvent e) {
- int kc = e.getKeyCode();
+
+ class GearsKeyAdapter extends KeyAdapter {
+ public void keyPressed(final KeyEvent e) {
+ final int kc = e.getKeyCode();
if(KeyEvent.VK_LEFT == kc) {
view_roty -= 1;
} else if(KeyEvent.VK_RIGHT == kc) {
@@ -324,18 +604,54 @@ public class GearsES2 implements GLEventListener {
}
}
- class GearsMouseAdapter extends MouseAdapter {
- public void mousePressed(MouseEvent e) {
- prevMouseX = e.getX();
- prevMouseY = e.getY();
+ class GearsMouseAdapter implements MouseListener{
+ private int prevMouseX, prevMouseY;
+
+ @Override
+ public void mouseClicked(final MouseEvent e) {
}
- public void mouseReleased(MouseEvent e) {
+ @Override
+ public void mouseEntered(final MouseEvent e) {
}
- public void mouseMoved(MouseEvent e) {
- if(e.isConfined()) {
- navigate(e);
+ @Override
+ public void mouseExited(final MouseEvent e) {
+ }
+
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
+ final float[] rot = e.getRotation();
+ if( e.isControlDown() ) {
+ // alternative zoom
+ final float incr = e.isShiftDown() ? rot[0] : rot[1] * 0.5f ;
+ panZ += incr;
+ System.err.println("panZ.2: incr "+incr+", dblZoom "+e.isShiftDown()+" -> "+panZ);
+ } else {
+ // panning
+ panX -= rot[0]; // positive -> left
+ panY += rot[1]; // positive -> up
+ }
+ }
+
+ public void mousePressed(final MouseEvent e) {
+ if( e.getPointerCount()==1 ) {
+ prevMouseX = e.getX();
+ prevMouseY = e.getY();
+ } else if( e.getPointerCount() == 4 ) {
+ final Object src = e.getSource();
+ if( e.getPressure(0, true) > 0.7f && src instanceof Window) { // show Keyboard
+ ((Window) src).setKeyboardVisible(true);
+ }
+ }
+ }
+
+ public void mouseReleased(final MouseEvent e) {
+ }
+
+ public void mouseMoved(final MouseEvent e) {
+ if( e.isConfined() ) {
+ navigate(e);
} else {
// track prev. position so we don't have 'jumps'
// in case we move to confined navigation.
@@ -343,40 +659,45 @@ public class GearsES2 implements GLEventListener {
prevMouseY = e.getY();
}
}
-
- public void mouseDragged(MouseEvent e) {
+
+ public void mouseDragged(final MouseEvent e) {
navigate(e);
}
-
- private void navigate(MouseEvent e) {
+
+ private void navigate(final MouseEvent e) {
int x = e.getX();
int y = e.getY();
-
+
int width, height;
- Object source = e.getSource();
+ final Object source = e.getSource();
Window window = null;
if(source instanceof Window) {
window = (Window) source;
- width=window.getWidth();
- height=window.getHeight();
+ width=window.getSurfaceWidth();
+ height=window.getSurfaceHeight();
+ } else if (source instanceof GLAutoDrawable) {
+ final GLAutoDrawable glad = (GLAutoDrawable) source;
+ width = glad.getSurfaceWidth();
+ height = glad.getSurfaceHeight();
} else if (GLProfile.isAWTAvailable() && source instanceof java.awt.Component) {
- java.awt.Component comp = (java.awt.Component) source;
- width=comp.getWidth();
+ final java.awt.Component comp = (java.awt.Component) source;
+ width=comp.getWidth(); // FIXME HiDPI: May need to convert window units -> pixel units!
height=comp.getHeight();
} else {
throw new RuntimeException("Event source neither Window nor Component: "+source);
- }
+ }
final float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width);
final float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height);
view_rotx += thetaX;
view_roty += thetaY;
- if(e.isConfined() && confinedFixedCenter && null!=window) {
- x=window.getWidth()/2;
- y=window.getHeight()/2;
+ if(e.isConfined() && confinedFixedCenter && null!=window) {
+ x=window.getSurfaceWidth()/2;
+ y=window.getSurfaceHeight()/2;
window.warpPointer(x, y);
}
prevMouseX = x;
prevMouseY = y;
+ // System.err.println("rotXY.1: "+view_rotx+"/"+view_roty+", source "+e);
}
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java
index 82485ea1a..7088eb757 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java
@@ -7,10 +7,10 @@
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -24,9 +24,10 @@ import java.nio.FloatBuffer;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLBufferStorage;
+import javax.media.opengl.GLException;
import javax.media.opengl.GLUniformData;
-
import com.jogamp.opengl.test.junit.jogl.demos.GearsObject;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
@@ -37,71 +38,108 @@ import com.jogamp.opengl.util.glsl.ShaderState;
* @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P>
*/
public class GearsObjectES2 extends GearsObject {
- PMVMatrix pmvMatrix;
- GLUniformData pmvMatrixUniform;
- GLUniformData colorUniform;
-
- public GearsObjectES2(float inner_radius, float outer_radius, float width,
- int teeth, float tooth_depth,
- PMVMatrix pmvMatrix,
- GLUniformData pmvMatrixUniform,
- GLUniformData colorUniform)
+ final PMVMatrix pmvMatrix;
+ final GLUniformData pmvMatrixUniform;
+ final GLUniformData colorUniform;
+ final ShaderState st;
+
+ public GearsObjectES2(final GL gl, final boolean useMappedBuffers, final ShaderState st, final FloatBuffer gearColor,
+ final float inner_radius, final float outer_radius,
+ final float width,
+ final int teeth,
+ final float tooth_depth, final PMVMatrix pmvMatrix, final GLUniformData pmvMatrixUniform, final GLUniformData colorUniform, final boolean validateBuffers)
{
- super(inner_radius, outer_radius, width, teeth, tooth_depth);
+ super(gl, useMappedBuffers, gearColor, inner_radius, outer_radius, width, teeth, tooth_depth, validateBuffers);
this.pmvMatrix = pmvMatrix;
this.pmvMatrixUniform = pmvMatrixUniform;
this.colorUniform = colorUniform;
+ this.st = st;
+ associate(st);
}
- public GearsObjectES2(GearsObject shared,
- PMVMatrix pmvMatrix,
- GLUniformData pmvMatrixUniform,
- GLUniformData colorUniform)
+ public GearsObjectES2(final GearsObjectES2 shared,
+ final ShaderState st,
+ final PMVMatrix pmvMatrix,
+ final GLUniformData pmvMatrixUniform, final GLUniformData colorUniform)
{
super(shared);
this.pmvMatrix = pmvMatrix;
this.pmvMatrixUniform = pmvMatrixUniform;
this.colorUniform = colorUniform;
+ this.st = st;
+ associate(st);
+ }
+
+ private void associate(final ShaderState st) {
+ frontFace.associate(st, true);
+ frontSide.associate(st, true);
+ backFace.associate(st, true);
+ backSide.associate(st, true);
+ outwardFace.associate(st, true);
+ insideRadiusCyl.associate(st, true);
}
@Override
- public GLArrayDataServer createInterleaved(int comps, int dataType, boolean normalized, int initialSize, int vboUsage) {
- return GLArrayDataServer.createGLSLInterleaved(comps, dataType, normalized, initialSize, vboUsage);
+ public GLArrayDataServer createInterleaved(final boolean useMappedBuffers, final int comps, final int dataType, final boolean normalized, final int initialSize, final int vboUsage) {
+ if( useMappedBuffers ) {
+ return GLArrayDataServer.createGLSLInterleavedMapped(comps, dataType, normalized, initialSize, vboUsage);
+ } else {
+ return GLArrayDataServer.createGLSLInterleaved(comps, dataType, normalized, initialSize, vboUsage);
+ }
}
-
+
@Override
- public void addInterleavedVertexAndNormalArrays(GLArrayDataServer array,
- int components) {
- array.addGLSLSubArray("vertices", 3, GL.GL_ARRAY_BUFFER);
- array.addGLSLSubArray("normals", 3, GL.GL_ARRAY_BUFFER);
+ public void addInterleavedVertexAndNormalArrays(final GLArrayDataServer array, final int components) {
+ array.addGLSLSubArray("vertices", components, GL.GL_ARRAY_BUFFER);
+ array.addGLSLSubArray("normals", components, GL.GL_ARRAY_BUFFER);
}
- private void draw(GL2ES2 gl, GLArrayDataServer array, int mode) {
- array.enableBuffer(gl, true);
- gl.glDrawArrays(mode, 0, array.getElementCount());
- array.enableBuffer(gl, false);
+ private void draw(final GL2ES2 gl, final GLArrayDataServer array, final int mode, final int face) {
+ if( !isShared || gl.glIsBuffer(array.getVBOName()) ) {
+ if( validateBuffers ) {
+ array.bindBuffer(gl, true);
+ final int bufferTarget = array.getVBOTarget();
+ final int bufferName = array.getVBOName();
+ final long bufferSize = array.getSizeInBytes();
+ final int hasBufferName = gl.getBoundBuffer(bufferTarget);
+ final GLBufferStorage hasStorage = gl.getBufferStorage(hasBufferName);
+ final boolean ok = bufferName == hasBufferName &&
+ bufferName == hasStorage.getName() &&
+ bufferSize == hasStorage.getSize();
+ if( !ok ) {
+ throw new GLException("GLBufferStorage Validation Error: Target[exp 0x"+Integer.toHexString(bufferTarget)+", has 0x"+Integer.toHexString(bufferTarget)+
+ ", Name[exp "+bufferName+", has "+hasBufferName+", Size exp "+bufferSize+", Storage "+hasStorage+"]");
+ }
+ }
+ array.enableBuffer(gl, true);
+ // System.err.println("XXX Draw face "+face+" of "+this);
+ gl.glDrawArrays(mode, 0, array.getElementCount());
+ array.enableBuffer(gl, false);
+ }
}
@Override
- public void draw(GL _gl, float x, float y, float angle, FloatBuffer color) {
+ public void draw(final GL _gl, final float x, final float y, final float angle) {
final GL2ES2 gl = _gl.getGL2ES2();
- final ShaderState st = ShaderState.getShaderState(gl);
pmvMatrix.glPushMatrix();
pmvMatrix.glTranslatef(x, y, 0f);
pmvMatrix.glRotatef(angle, 0f, 0f, 1f);
- pmvMatrix.update();
- st.uniform(gl, pmvMatrixUniform);
+ if( pmvMatrix.update() ) {
+ st.uniform(gl, pmvMatrixUniform);
+ } else {
+ throw new InternalError("PMVMatrix.update() returns false after mutable operations");
+ }
- colorUniform.setData(color);
+ colorUniform.setData(gearColor);
st.uniform(gl, colorUniform);
- draw(gl, frontFace, GL.GL_TRIANGLE_STRIP);
- draw(gl, frontSide, GL.GL_TRIANGLES);
- draw(gl, backFace, GL.GL_TRIANGLE_STRIP);
- draw(gl, backSide, GL.GL_TRIANGLES);
- draw(gl, outwardFace, GL.GL_TRIANGLE_STRIP);
- draw(gl, insideRadiusCyl, GL.GL_TRIANGLE_STRIP);
-
+ draw(gl, frontFace, GL.GL_TRIANGLE_STRIP, 0);
+ draw(gl, frontSide, GL.GL_TRIANGLES, 1);
+ draw(gl, backFace, GL.GL_TRIANGLE_STRIP, 2);
+ draw(gl, backSide, GL.GL_TRIANGLES, 3);
+ draw(gl, outwardFace, GL.GL_TRIANGLE_STRIP, 4);
+ draw(gl, insideRadiusCyl, GL.GL_TRIANGLE_STRIP, 5);
+
pmvMatrix.glPopMatrix();
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java
new file mode 100644
index 000000000..72524aa67
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java
@@ -0,0 +1,189 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2;
+
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLUniformData;
+
+/**
+ * LandscapeES2
+ */
+public class LandscapeES2 implements GLEventListener {
+ private int swapInterval = 0;
+ private boolean verbose = true;
+
+ static public final int TARGET_FPS = 120;
+ private long millisOffset;
+ private int frameCount;
+ private float frameRate;
+ private ShaderCode vertShader;
+ private ShaderCode fragShader;
+ private ShaderProgram shaderProg;
+ private ShaderState shaderState;
+ private float[] resolution;
+ private GLUniformData resolutionUni;
+ private GLUniformData timeUni;
+ private GLArrayDataServer vertices;
+
+ private int fcount = 0, lastm = 0;
+ private final int fint = 1;
+
+ public LandscapeES2(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
+
+ public LandscapeES2() {
+ this.swapInterval = 1;
+ }
+
+ public void setVerbose(final boolean v) { verbose = v; }
+
+ public void init(final GLAutoDrawable drawable) {
+ System.err.println(Thread.currentThread()+" LandscapeES2.init ...");
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ if(verbose) {
+ System.err.println("LandscapeES2 init on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber());
+ System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
+ System.err.println("GL Profile: "+gl.getGLProfile());
+ System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
+ System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
+ }
+
+ vertShader = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", "shader/bin", "landscape", true);
+ fragShader = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", "shader/bin", "landscape", true);
+ vertShader.defaultShaderCustomization(gl, true, true);
+ fragShader.defaultShaderCustomization(gl, true, true);
+ shaderProg = new ShaderProgram();
+ shaderProg.add(gl, vertShader, System.err);
+ shaderProg.add(gl, fragShader, System.err);
+
+ shaderState = new ShaderState();
+ shaderState.attachShaderProgram(gl, shaderProg, true);
+
+ resolution = new float[] { drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), 0};
+ resolutionUni = new GLUniformData("iResolution", 3, FloatBuffer.wrap(resolution));
+ shaderState.ownUniform(resolutionUni);
+ shaderState.uniform(gl, resolutionUni);
+
+ timeUni = new GLUniformData("iGlobalTime", 0.0f);
+ shaderState.ownUniform(timeUni);
+
+ vertices = GLArrayDataServer.createGLSL("inVertex", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ vertices.putf(-1.0f); vertices.putf(-1.0f);
+ vertices.putf(+1.0f); vertices.putf(-1.0f);
+ vertices.putf(-1.0f); vertices.putf(+1.0f);
+ vertices.putf(+1.0f); vertices.putf(+1.0f);
+ vertices.seal(gl, true);
+ shaderState.ownAttribute(vertices, true);
+ shaderState.useProgram(gl, false);
+
+ millisOffset = System.currentTimeMillis();
+
+ System.err.println(Thread.currentThread()+" LandscapeES2.init FIN");
+ }
+
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ System.err.println(Thread.currentThread()+" LandscapeES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(drawable.getHandle()));
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ }
+
+ shaderState.useProgram(gl, true);
+
+ resolution[0] = drawable.getSurfaceWidth();
+ resolution[1] = drawable.getSurfaceHeight();
+ shaderState.uniform(gl, resolutionUni);
+
+ shaderState.useProgram(gl, false);
+ }
+
+ public void dispose(final GLAutoDrawable drawable) {
+ System.err.println(Thread.currentThread()+" LandscapeES2.dispose ... ");
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ shaderState.useProgram(gl, false);
+ shaderState.destroy(gl);
+ shaderState = null;
+
+ System.err.println(Thread.currentThread()+" LandscapeES2.dispose FIN");
+ }
+
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ // Shader fills complete framebuffer regardless of DEPTH, no Clear required.
+ // gl.glClearColor(0.5f, 0.1f, 0.1f, 1);
+ // gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+
+ shaderState.useProgram(gl, true);
+
+ timeUni.setData((System.currentTimeMillis() - millisOffset) / 1000.0f);
+ shaderState.uniform(gl, timeUni);
+ vertices.enableBuffer(gl, true);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ vertices.enableBuffer(gl, false);
+
+ shaderState.useProgram(gl, false);
+
+ // Compute current framerate and printout.
+ frameCount++;
+ fcount += 1;
+ final int m = (int) (System.currentTimeMillis() - millisOffset);
+ if (m - lastm > 1000 * fint) {
+ frameRate = (float)(fcount) / fint;
+ fcount = 0;
+ lastm = m;
+ }
+ if (frameCount % TARGET_FPS == 0) {
+ System.out.println("FrameCount: " + frameCount + " - " + "FrameRate: " + frameRate);
+ }
+ }
+
+ boolean confinedFixedCenter = false;
+
+ public void setConfinedFixedCenter(final boolean v) {
+ confinedFixedCenter = v;
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java
index 26e7e234a..58161f50a 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java
@@ -1,22 +1,29 @@
/**
- * Copyright (C) 2011 JogAmp Community. All rights reserved.
+ * Copyright 2011 JogAmp Community. All rights reserved.
*
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
*/
package com.jogamp.opengl.test.junit.jogl.demos.es2;
@@ -37,23 +44,24 @@ import com.jogamp.opengl.util.glsl.ShaderState;
public class Mix2TexturesES2 implements GLEventListener {
private final int swapInterval;
-
+
private final ShaderState st;
private final PMVMatrix pmvMatrix;
private final GLUniformData texUnit0, texUnit1;
-
- private volatile int texID0, texID1;
+
+ private final Object syncTexIDs = new Object();
+ private int texID0, texID1;
private ShaderProgram sp0;
private GLUniformData pmvMatrixUniform;
private GLArrayDataServer interleavedVBO;
-
- public Mix2TexturesES2(int swapInterval, int texUnit0, int texUnit1) {
+
+ public Mix2TexturesES2(final int swapInterval, final int texUnit0, final int texUnit1) {
this.swapInterval = swapInterval;
-
+
st = new ShaderState();
- // st.setVerbose(true);
+ // st.setVerbose(true);
pmvMatrix = new PMVMatrix();
-
+
if(0 == texUnit1) {
this.texUnit0 = new GLUniformData("mgl_ActiveTexture", texUnit0);
this.texUnit1 = null;
@@ -64,153 +72,147 @@ public class Mix2TexturesES2 implements GLEventListener {
this.texID0 = 0;
this.texID1 = 0;
}
-
- public void setTexID0(int texID) {
- this.texID0 = texID;
+
+ public void setTexID0(final int texID) {
+ synchronized( syncTexIDs ) {
+ this.texID0 = texID;
+ }
}
- public void setTexID1(int texID) {
- this.texID1 = texID;
+ public void setTexID1(final int texID) {
+ synchronized( syncTexIDs ) {
+ this.texID1 = texID;
+ }
}
-
- static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
- static final String gl2_prelude = "#version 110\n";
-
+
@Override
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
-
+
final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, Mix2TexturesES2.class, "shader",
"shader/bin", "texture01_xxx", true);
final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, Mix2TexturesES2.class, "shader",
"shader/bin", null == texUnit1 ? "texture01_xxx" : "texture02_xxx", true);
-
- // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
- int fp0Pos;
- if(gl.isGLES2()) {
- vp0.insertShaderSource(0, 0, es2_prelude[0]);
- fp0Pos = fp0.insertShaderSource(0, 0, es2_prelude[0]);
- } else {
- vp0.insertShaderSource(0, 0, gl2_prelude);
- fp0Pos = fp0.insertShaderSource(0, 0, gl2_prelude);
- }
- if(gl.isGLES2()) {
- fp0Pos = fp0.insertShaderSource(0, fp0Pos, es2_prelude[1]);
- }
-
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+
sp0 = new ShaderProgram();
sp0.add(gl, vp0, System.err);
- sp0.add(gl, fp0, System.err);
+ sp0.add(gl, fp0, System.err);
st.attachShaderProgram(gl, sp0, true);
-
+
pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
- st.ownUniform(pmvMatrixUniform);
+ st.ownUniform(pmvMatrixUniform);
st.uniform(gl, pmvMatrixUniform);
-
+
interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
- {
- interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
- interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ {
+ interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
//interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER);
interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
- FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
-
+ final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
+
for(int i=0; i<4; i++) {
ib.put(s_quadVertices, i*3, 3);
- ib.put(s_quadColors, i*4, 4);
+ ib.put(s_quadColors, i*4, 4);
//ib.put(s_cubeNormals, i*3, 3);
ib.put(s_quadTexCoords, i*2, 2);
- }
+ }
}
interleavedVBO.seal(gl, true);
interleavedVBO.enableBuffer(gl, false);
st.ownAttribute(interleavedVBO, true);
-
+
st.ownUniform(texUnit0);
st.uniform(gl, texUnit0);
if(null != texUnit1) {
- st.ownUniform(texUnit1);
+ st.ownUniform(texUnit1);
st.uniform(gl, texUnit1);
}
-
- st.useProgram(gl, false);
+
+ st.useProgram(gl, false);
}
-
+
@Override
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
st.destroy(gl);
-
+
sp0 = null;
pmvMatrixUniform = null;
interleavedVBO = null;
}
@Override
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
st.useProgram(gl, true);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
-
+
interleavedVBO.enableBuffer(gl, true);
-
- if(0<texID0) {
- gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue());
- gl.glBindTexture(GL.GL_TEXTURE_2D, texID0);
- }
-
- if(0<texID1 && null != texUnit1) {
- gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue());
- gl.glBindTexture(GL.GL_TEXTURE_2D, texID1);
+
+ synchronized( syncTexIDs ) {
+ if(0<texID0) {
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue());
+ gl.glBindTexture(GL.GL_TEXTURE_2D, texID0);
+ }
+
+ if(0<texID1 && null != texUnit1) {
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue());
+ gl.glBindTexture(GL.GL_TEXTURE_2D, texID1);
+ }
+
+ if( !gl.isGLcore() ) {
+ gl.glEnable(GL.GL_TEXTURE_2D);
+ }
+
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
}
-
- gl.glEnable(GL.GL_TEXTURE_2D);
-
- gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
-
+
interleavedVBO.enableBuffer(gl, false);
-
- st.useProgram(gl, false);
+
+ st.useProgram(gl, false);
}
@Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- if(-1 != swapInterval) {
+
+ if(-1 != swapInterval) {
gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
}
-
+
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
-
+
st.useProgram(gl, true);
st.uniform(gl, pmvMatrixUniform);
st.useProgram(gl, false);
-
+
}
- private static final float[] s_quadVertices = {
+ private static final float[] s_quadVertices = {
-1f, -1f, 0f, // LB
1f, -1f, 0f, // RB
-1f, 1f, 0f, // LT
- 1f, 1f, 0f // RT
+ 1f, 1f, 0f // RT
};
- private static final float[] s_quadColors = {
+ private static final float[] s_quadColors = {
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f };
- private static final float[] s_quadTexCoords = {
+ private static final float[] s_quadTexCoords = {
0f, 0f, // LB
1f, 0f, // RB
- 0f, 1f, // LT
+ 0f, 1f, // LT
1f, 1f // RT
};
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java
index c80455314..8e4dbfefe 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java
@@ -55,113 +55,105 @@ import com.jogamp.opengl.util.glsl.ShaderState;
public class MultisampleDemoES2 implements GLEventListener {
- private boolean multisample;
+ private boolean multisample, clearBuffers;
private final ShaderState st;
private final PMVMatrix pmvMatrix;
private ShaderProgram sp0;
private GLUniformData pmvMatrixUniform;
private ImmModeSink immModeSink;
- public MultisampleDemoES2(boolean multisample) {
+ public MultisampleDemoES2(final boolean multisample) {
this.multisample = multisample;
+ this.clearBuffers = true;
st = new ShaderState();
- st.setVerbose(true);
- pmvMatrix = new PMVMatrix();
+ st.setVerbose(true);
+ pmvMatrix = new PMVMatrix();
}
- static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
- static final String gl2_prelude = "#version 110\n";
-
- public void init(GLAutoDrawable glad) {
+ public void setClearBuffers(final boolean v) { clearBuffers = v; }
+
+ public void init(final GLAutoDrawable glad) {
final GL2ES2 gl = glad.getGL().getGL2ES2();
-
+
System.err.println();
System.err.println("req. msaa: "+multisample);
System.err.println("Requested: " + glad.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities());
- multisample = multisample & glad.getChosenGLCapabilities().getNumSamples() > 0 ;
+ multisample = multisample && glad.getChosenGLCapabilities().getNumSamples() > 0 ;
System.err.println("Chosen : " + glad.getChosenGLCapabilities());
System.err.println("has msaa: "+multisample);
System.err.println();
-
+
final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MultisampleDemoES2.class, "shader",
"shader/bin", "mgl_default_xxx", true);
final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MultisampleDemoES2.class, "shader",
"shader/bin", "mgl_default_xxx", true);
-
- // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
- int fp0Pos;
- if(gl.isGLES2()) {
- vp0.insertShaderSource(0, 0, es2_prelude[0]);
- fp0Pos = fp0.insertShaderSource(0, 0, es2_prelude[0]);
- } else {
- vp0.insertShaderSource(0, 0, gl2_prelude);
- fp0Pos = fp0.insertShaderSource(0, 0, gl2_prelude);
- }
- if(gl.isGLES2()) {
- fp0Pos = fp0.insertShaderSource(0, fp0Pos, es2_prelude[1]);
- }
-
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+
sp0 = new ShaderProgram();
sp0.add(gl, vp0, System.err);
- sp0.add(gl, fp0, System.err);
+ sp0.add(gl, fp0, System.err);
st.attachShaderProgram(gl, sp0, true);
-
+
pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
- st.ownUniform(pmvMatrixUniform);
+ st.ownUniform(pmvMatrixUniform);
st.uniform(gl, pmvMatrixUniform);
-
- // Using predef array names, see
+
+ // Using predef array names, see
// GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex);
- immModeSink = ImmModeSink.createGLSL(gl, GL.GL_STATIC_DRAW, 40,
+ immModeSink = ImmModeSink.createGLSL(40,
3, GL.GL_FLOAT, // vertex
4, GL.GL_FLOAT, // color
- 0, GL.GL_FLOAT,// normal
- 0, GL.GL_FLOAT); // texture
+ 0, GL.GL_FLOAT, // normal
+ 0, GL.GL_FLOAT, // texCoords
+ GL.GL_STATIC_DRAW, st);
final int numSteps = 20;
final double increment = Math.PI / numSteps;
final double radius = 1;
immModeSink.glBegin(GL.GL_LINES);
for (int i = numSteps - 1; i >= 0; i--) {
- immModeSink.glVertex3f((float) (radius * Math.cos(i * increment)),
- (float) (radius * Math.sin(i * increment)),
+ immModeSink.glVertex3f((float) (radius * Math.cos(i * increment)),
+ (float) (radius * Math.sin(i * increment)),
0f);
- immModeSink.glColor4f( 1f, 1f, 1f, 1f );
- immModeSink.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)),
- (float) (-1.0 * radius * Math.sin(i * increment)),
+ immModeSink.glColor4f( 1f, 1f, 1f, 1f );
+ immModeSink.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)),
+ (float) (-1.0 * radius * Math.sin(i * increment)),
0f);
- immModeSink.glColor4f( 1f, 1f, 1f, 1f );
+ immModeSink.glColor4f( 1f, 1f, 1f, 1f );
}
immModeSink.glEnd(gl, false);
-
+
st.useProgram(gl, false);
}
- public void dispose(GLAutoDrawable glad) {
+ public void dispose(final GLAutoDrawable glad) {
final GL2ES2 gl = glad.getGL().getGL2ES2();
immModeSink.destroy(gl);
immModeSink = null;
st.destroy(gl);
}
- public void display(GLAutoDrawable glad) {
+ public void display(final GLAutoDrawable glad) {
final GL2ES2 gl = glad.getGL().getGL2ES2();
if (multisample) {
gl.glEnable(GL.GL_MULTISAMPLE);
}
- gl.glClearColor(0, 0, 0, 0);
- // gl.glEnable(GL.GL_DEPTH_TEST);
- // gl.glDepthFunc(GL.GL_LESS);
- gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
-
+ if( clearBuffers ) {
+ gl.glClearColor(0, 0, 0, 0);
+ // gl.glEnable(GL.GL_DEPTH_TEST);
+ // gl.glDepthFunc(GL.GL_LESS);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+
st.useProgram(gl, true);
-
+
immModeSink.draw(gl, true);
-
+
st.useProgram(gl, false);
}
// Unused routines
- public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
System.err.println("reshape ..");
final GL2ES2 gl = glad.getGL().getGL2ES2();
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
@@ -170,12 +162,12 @@ public class MultisampleDemoES2 implements GLEventListener {
pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
-
+
st.useProgram(gl, true);
st.uniform(gl, pmvMatrixUniform);
st.useProgram(gl, false);
}
- public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
+ public void displayChanged(final GLAutoDrawable drawable, final boolean modeChanged, final boolean deviceChanged) {
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
new file mode 100644
index 000000000..8a99a4d55
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
@@ -0,0 +1,209 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2;
+
+import java.nio.FloatBuffer;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.test.junit.jogl.demos.PointsDemo;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+public class PointsDemoES2 extends PointsDemo {
+ ShaderState st;
+ PMVMatrix pmvMatrix;
+ GLUniformData pmvMatrixUniform;
+ GLArrayDataServer vertices ;
+ GLArrayDataServer pointSizes ;
+ private int swapInterval = 0;
+ final int edge = 8; // 8*8
+ /** vec4[2]: { (sz, smooth, attnMinSz, attnMaxSz), (attnCoeff(3), attnFadeTs) } */
+ private static final String mgl_PointParams = "mgl_PointParams";
+
+ /** ( pointSize, pointSmooth, attn. pointMinSize, attn. pointMaxSize ) , ( attenuation coefficients 1f 0f 0f, attenuation fade theshold 1f ) */
+ private final FloatBuffer pointParams = Buffers.newDirectFloatBuffer(new float[] { 1.0f, 0.0f, 0.0f, 4096.0f, 1.0f, 0.0f, 0.0f, 1.0f });
+
+ public PointsDemoES2(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
+
+ public PointsDemoES2() {
+ this.swapInterval = 1;
+ }
+
+ public void setSmoothPoints(final boolean v) {
+ pointParams.put(1, v ? 1.0f : 0.0f);
+ }
+
+ public void setPointParams(final float minSize, final float maxSize, final float distAttenConst, final float distAttenLinear, final float distAttenQuadratic, final float fadeThreshold) {
+ pointParams.put(2, minSize);
+ pointParams.put(3, maxSize);
+ pointParams.put(4+0, distAttenConst);
+ pointParams.put(4+1, distAttenLinear);
+ pointParams.put(4+2, distAttenQuadratic);
+ pointParams.put(4+3, fadeThreshold);
+ }
+
+ public void init(final GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+ System.err.println("GL Profile: "+gl.getGLProfile());
+
+ st = new ShaderState();
+ st.setVerbose(true);
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader",
+ "shader/bin", "PointsShader", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
+ "shader/bin", "PointsShader", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+ final ShaderProgram sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ st.attachShaderProgram(gl, sp0, true);
+
+ // setup mgl_PMVMatrix
+ pmvMatrix = new PMVMatrix();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+
+ st.uniform(gl, new GLUniformData(mgl_PointParams, 4, pointParams));
+
+ final GLUniformData colorStaticUniform = new GLUniformData("mgl_ColorStatic", 4, Buffers.newDirectFloatBuffer(new float[] { 1.0f, 1.0f, 1.0f, 1.0f }) );
+ st.uniform(gl, colorStaticUniform);
+ st.ownUniform(colorStaticUniform);
+
+ // Allocate Vertex Array
+ vertices = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, edge*edge, GL.GL_STATIC_DRAW);
+ pointSizes = GLArrayDataServer.createGLSL("mgl_PointSize", 1, GL.GL_FLOAT, false, edge*edge, GL.GL_STATIC_DRAW);
+ for(int i=0; i<edge; i++) {
+ for(int j=0; j<edge; j++) {
+ final float x = -3+j*0.7f;
+ final float y = -3+i*0.7f;
+ final float p = (i*edge+j)*0.5f;
+ // System.err.println("["+j+"/"+i+"]: "+x+"/"+y+": "+p);
+ vertices.putf(x); vertices.putf(y); vertices.putf( 0);
+ pointSizes.putf(p);
+ }
+ }
+ vertices.seal(gl, true);
+ st.ownAttribute(vertices, true);
+ vertices.enableBuffer(gl, false);
+ pointSizes.seal(gl, true);
+ st.ownAttribute(pointSizes, true);
+ pointSizes.enableBuffer(gl, false);
+
+ // OpenGL Render Settings
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ st.useProgram(gl, false);
+ }
+
+ public void display(final GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ gl.glClearColor(0f, 0f, 0f, 0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ st.useProgram(gl, true);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glTranslatef(0, 0, -10);
+ st.uniform(gl, pmvMatrixUniform);
+
+ final GLUniformData ud = st.getUniform(mgl_PointParams);
+ if(null!=ud) {
+ // same data object
+ st.uniform(gl, ud);
+ }
+
+ vertices.enableBuffer(gl, true);
+ pointSizes.enableBuffer(gl, true);
+
+ if(gl.isGL2GL3()) {
+ gl.glEnable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
+ }
+ if(gl.isGL2ES1()) {
+ gl.glEnable(GL2ES1.GL_POINT_SPRITE); // otherwise no gl_PointCoord
+ }
+ gl.glEnable ( GL.GL_BLEND );
+ gl.glBlendFunc ( GL.GL_SRC_ALPHA, GL.GL_ONE );
+
+ gl.glDrawArrays(GL.GL_POINTS, 0, edge*edge);
+
+ if(gl.isGL2GL3()) {
+ gl.glDisable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
+ }
+
+ pointSizes.enableBuffer(gl, false);
+ vertices.enableBuffer(gl, false);
+ st.useProgram(gl, false);
+ }
+
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ // Thread.dumpStack();
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ }
+
+ st.useProgram(gl, true);
+ // Set location in front of camera
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.gluPerspective(45.0F, ( (float) width / (float) height ) / 1.0f, 1.0F, 100.0F);
+ //pmvMatrix.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ }
+
+ public void dispose(final GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ st.destroy(gl);
+ st = null;
+ pmvMatrix = null;
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
index 9629d2102..8058d1b7d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
@@ -27,83 +27,103 @@
*/
package com.jogamp.opengl.test.junit.jogl.demos.es2;
-import com.jogamp.newt.Window;
+import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.TileRendererBase;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.glsl.ShaderState;
+
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
-public class RedSquareES2 implements GLEventListener {
- ShaderState st;
- PMVMatrix pmvMatrix;
- GLUniformData pmvMatrixUniform;
- GLArrayDataServer vertices ;
- GLArrayDataServer colors ;
- long t0;
+public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRendererListener {
+ private ShaderState st;
+ private PMVMatrix pmvMatrix;
+ private GLUniformData pmvMatrixUniform;
+ private GLArrayDataServer vertices ;
+ private GLArrayDataServer colors ;
+ private long t0;
private int swapInterval = 0;
- Window window = null;
- float aspect = 1.0f;
- boolean doRotate = true;
- boolean isInitialized = false;
+ private float aspect = 1.0f;
+ private boolean doRotate = true;
+ private boolean clearBuffers = true;
+ private TileRendererBase tileRendererInUse = null;
+ private boolean doRotateBeforePrinting;
- public RedSquareES2(int swapInterval) {
+ public RedSquareES2(final int swapInterval) {
this.swapInterval = swapInterval;
}
public RedSquareES2() {
this.swapInterval = 1;
}
-
- public void setAspect(float aspect) { this.aspect = aspect; }
- public void setDoRotation(boolean rotate) { this.doRotate = rotate; }
-
- public void init(GLAutoDrawable glad) {
- if(isInitialized) {
- System.err.println(Thread.currentThread()+" RedSquareES2.init skipped!");
- return;
- }
- isInitialized = true;
- System.err.println(Thread.currentThread()+" RedSquareES2.init ...");
- GL2ES2 gl = glad.getGL().getGL2ES2();
-
+
+ @Override
+ public void addTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = tr;
+ doRotateBeforePrinting = doRotate;
+ setDoRotation(false);
+ }
+ @Override
+ public void removeTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = null;
+ setDoRotation(doRotateBeforePrinting);
+ }
+ @Override
+ public void startTileRendering(final TileRendererBase tr) {
+ System.err.println("RedSquareES2.startTileRendering: "+tr);
+ }
+ @Override
+ public void endTileRendering(final TileRendererBase tr) {
+ System.err.println("RedSquareES2.endTileRendering: "+tr);
+ }
+
+ public void setAspect(final float aspect) { this.aspect = aspect; }
+ public void setDoRotation(final boolean rotate) { this.doRotate = rotate; }
+ public void setClearBuffers(final boolean v) { clearBuffers = v; }
+
+ @Override
+ public void init(final GLAutoDrawable glad) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.init: tileRendererInUse "+tileRendererInUse);
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+
System.err.println("RedSquareES2 init on "+Thread.currentThread());
System.err.println("Chosen GLCapabilities: " + glad.getChosenGLCapabilities());
System.err.println("INIT GL IS: " + gl.getClass().getName());
- System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
- System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
- System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
- System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
- System.err.println("GL Profile: "+gl.getGLProfile());
- System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
-
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+ if( !gl.hasGLSL() ) {
+ System.err.println("No GLSL available, no rendering.");
+ return;
+ }
st = new ShaderState();
st.setVerbose(true);
final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp0 = new ShaderProgram();
sp0.add(gl, vp0, System.err);
sp0.add(gl, fp0, System.err);
st.attachShaderProgram(gl, sp0, true);
-
+
// setup mgl_PMVMatrix
pmvMatrix = new PMVMatrix();
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
- pmvMatrix.glLoadIdentity();
pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
st.ownUniform(pmvMatrixUniform);
- st.uniform(gl, pmvMatrixUniform);
-
+ st.uniform(gl, pmvMatrixUniform);
+
// Allocate Vertex Array
vertices = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
vertices.putf(-2); vertices.putf( 2); vertices.putf( 0);
@@ -113,42 +133,52 @@ public class RedSquareES2 implements GLEventListener {
vertices.seal(gl, true);
st.ownAttribute(vertices, true);
vertices.enableBuffer(gl, false);
-
+
// Allocate Color Array
colors= GLArrayDataServer.createGLSL("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
colors.putf(1); colors.putf(0); colors.putf(0); colors.putf(1);
colors.putf(0); colors.putf(0); colors.putf(1); colors.putf(1);
colors.putf(1); colors.putf(0); colors.putf(0); colors.putf(1);
colors.putf(1); colors.putf(0); colors.putf(0); colors.putf(1);
- colors.seal(gl, true);
+ colors.seal(gl, true);
st.ownAttribute(colors, true);
colors.enableBuffer(gl, false);
-
+
// OpenGL Render Settings
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
- st.useProgram(gl, false);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ st.useProgram(gl, false);
t0 = System.currentTimeMillis();
System.err.println(Thread.currentThread()+" RedSquareES2.init FIN");
}
- public void display(GLAutoDrawable glad) {
- long t1 = System.currentTimeMillis();
+ @Override
+ public void display(final GLAutoDrawable glad) {
+ final long t1 = System.currentTimeMillis();
- GL2ES2 gl = glad.getGL().getGL2ES2();
- gl.glClearColor(0, 0, 0, 0);
- gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ if( clearBuffers ) {
+ if( null != tileRendererInUse ) {
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ } else {
+ gl.glClearColor(0, 0, 0, 0);
+ }
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+ if( !gl.hasGLSL() ) {
+ return;
+ }
st.useProgram(gl, true);
// One rotation every four seconds
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
pmvMatrix.glTranslatef(0, 0, -10);
if(doRotate) {
- float ang = ((float) (t1 - t0) * 360.0F) / 4000.0F;
+ final float ang = ((t1 - t0) * 360.0F) / 4000.0F;
pmvMatrix.glRotatef(ang, 0, 0, 1);
pmvMatrix.glRotatef(ang, 0, 1, 0);
}
- st.uniform(gl, pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
// Draw a square
vertices.enableBuffer(gl, true);
@@ -159,38 +189,74 @@ public class RedSquareES2 implements GLEventListener {
st.useProgram(gl, false);
}
- public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {
- System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval);
- GL2ES2 gl = glad.getGL().getGL2ES2();
-
- if(-1 != swapInterval) {
- gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ @Override
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval);
+ }
+ reshapeImpl(gl, x, y, width, height, width, height);
+ }
+
+ @Override
+ public void reshapeTile(final TileRendererBase tr,
+ final int tileX, final int tileY, final int tileWidth, final int tileHeight,
+ final int imageWidth, final int imageHeight) {
+ final GL2ES2 gl = tr.getAttachedDrawable().getGL().getGL2ES2();
+ gl.setSwapInterval(0);
+ reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
+ }
+
+ void reshapeImpl(final GL2ES2 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse);
+ // Thread.dumpStack();
+ if( !gl.hasGLSL() ) {
+ return;
}
-
+
st.useProgram(gl, true);
// Set location in front of camera
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
- pmvMatrix.gluPerspective(45.0F, ( (float) width / (float) height ) / aspect, 1.0F, 100.0F);
+
+ // compute projection parameters 'normal' perspective
+ final float fovy=45f;
+ final float aspect2 = ( (float) imageWidth / (float) imageHeight ) / aspect;
+ final float zNear=1f;
+ final float zFar=100f;
+
+ // compute projection parameters 'normal' frustum
+ final float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear;
+ final float bottom=-1.0f*top;
+ final float left=aspect2*bottom;
+ final float right=aspect2*top;
+ final float w = right - left;
+ final float h = top - bottom;
+
+ // compute projection parameters 'tiled'
+ final float l = left + tileX * w / imageWidth;
+ final float r = l + tileWidth * w / imageWidth;
+ final float b = bottom + tileY * h / imageHeight;
+ final float t = b + tileHeight * h / imageHeight;
+
+ pmvMatrix.glFrustumf(l, r, b, t, zNear, zFar);
//pmvMatrix.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f);
st.uniform(gl, pmvMatrixUniform);
st.useProgram(gl, false);
-
+
System.err.println(Thread.currentThread()+" RedSquareES2.reshape FIN");
}
- public void dispose(GLAutoDrawable glad) {
- if(!isInitialized) {
- System.err.println(Thread.currentThread()+" RedSquareES2.dispose skipped!");
- return;
+ @Override
+ public void dispose(final GLAutoDrawable glad) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.dispose: tileRendererInUse "+tileRendererInUse);
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ if( !gl.hasGLSL() ) {
+ return;
}
- isInitialized = false;
- System.err.println(Thread.currentThread()+" RedSquareES2.dispose ... ");
- GL2ES2 gl = glad.getGL().getGL2ES2();
st.destroy(gl);
st = null;
- pmvMatrix.destroy();
pmvMatrix = null;
System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java
new file mode 100644
index 000000000..35449b3bf
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java
@@ -0,0 +1,281 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2;
+
+import java.nio.FloatBuffer;
+
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.TileRendererBase;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLBufferStorage;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+public class RedSquareMappedES2 implements GLEventListener, TileRendererBase.TileRendererListener {
+ private ShaderState st;
+ private PMVMatrix pmvMatrix;
+ private GLUniformData pmvMatrixUniform;
+ private GLArrayDataServer vertices ;
+ private GLArrayDataServer colors ;
+ private long t0;
+ private int swapInterval = 0;
+ private float aspect = 1.0f;
+ private boolean doRotate = true;
+ private boolean clearBuffers = true;
+ private TileRendererBase tileRendererInUse = null;
+ private boolean doRotateBeforePrinting;
+
+ public RedSquareMappedES2(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
+
+ public RedSquareMappedES2() {
+ this.swapInterval = 1;
+ }
+
+ @Override
+ public void addTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = tr;
+ doRotateBeforePrinting = doRotate;
+ setDoRotation(false);
+ }
+ @Override
+ public void removeTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = null;
+ setDoRotation(doRotateBeforePrinting);
+ }
+ @Override
+ public void startTileRendering(final TileRendererBase tr) {
+ System.err.println("RedSquareES2.startTileRendering: "+tr);
+ }
+ @Override
+ public void endTileRendering(final TileRendererBase tr) {
+ System.err.println("RedSquareES2.endTileRendering: "+tr);
+ }
+
+ public void setAspect(final float aspect) { this.aspect = aspect; }
+ public void setDoRotation(final boolean rotate) { this.doRotate = rotate; }
+ public void setClearBuffers(final boolean v) { clearBuffers = v; }
+
+ @Override
+ public void init(final GLAutoDrawable glad) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.init: tileRendererInUse "+tileRendererInUse);
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+
+ System.err.println("RedSquareES2 init on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + glad.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+ if( !gl.hasGLSL() ) {
+ System.err.println("No GLSL available, no rendering.");
+ return;
+ }
+ st = new ShaderState();
+ st.setVerbose(true);
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader",
+ "shader/bin", "RedSquareShader", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
+ "shader/bin", "RedSquareShader", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+ final ShaderProgram sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ st.attachShaderProgram(gl, sp0, true);
+
+ // setup mgl_PMVMatrix
+ pmvMatrix = new PMVMatrix();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+
+ // Allocate Vertex Array
+ vertices = GLArrayDataServer.createGLSLMapped("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ {
+ final GLArrayDataServer ad = vertices;
+ final GLBufferStorage store = ad.mapStorage(gl, GL.GL_WRITE_ONLY);
+ {
+ final FloatBuffer fb = store.getMappedBuffer().asFloatBuffer();
+ fb.put(-2); fb.put( 2); fb.put( 0);
+ fb.put( 2); fb.put( 2); fb.put( 0);
+ fb.put(-2); fb.put(-2); fb.put( 0);
+ fb.put( 2); fb.put(-2); fb.put( 0);
+ }
+ ad.unmapStorage(gl);
+ }
+ vertices.seal(gl, true);
+ st.ownAttribute(vertices, true);
+ vertices.enableBuffer(gl, false);
+
+ // Allocate Color Array
+ colors = GLArrayDataServer.createGLSLMapped("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ {
+ final GLArrayDataServer ad = colors;
+ final GLBufferStorage store = ad.mapStorage(gl, GL.GL_WRITE_ONLY);
+ {
+ final FloatBuffer fb = store.getMappedBuffer().asFloatBuffer();
+ fb.put(1); fb.put(0); fb.put(0); fb.put(1);
+ fb.put(0); fb.put(0); fb.put(1); fb.put(1);
+ fb.put(1); fb.put(0); fb.put(0); fb.put(1);
+ fb.put(1); fb.put(0); fb.put(0); fb.put(1);
+ }
+ ad.unmapStorage(gl);
+ }
+ colors.seal(gl, true);
+ st.ownAttribute(colors, true);
+ colors.enableBuffer(gl, false);
+
+ // OpenGL Render Settings
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ st.useProgram(gl, false);
+
+ t0 = System.currentTimeMillis();
+ System.err.println(Thread.currentThread()+" RedSquareES2.init FIN");
+ }
+
+ @Override
+ public void display(final GLAutoDrawable glad) {
+ final long t1 = System.currentTimeMillis();
+
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ if( clearBuffers ) {
+ if( null != tileRendererInUse ) {
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ } else {
+ gl.glClearColor(0, 0, 0, 0);
+ }
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+ st.useProgram(gl, true);
+ // One rotation every four seconds
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glTranslatef(0, 0, -10);
+ if(doRotate) {
+ final float ang = ((t1 - t0) * 360.0F) / 4000.0F;
+ pmvMatrix.glRotatef(ang, 0, 0, 1);
+ pmvMatrix.glRotatef(ang, 0, 1, 0);
+ }
+ st.uniform(gl, pmvMatrixUniform);
+
+ // Draw a square
+ vertices.enableBuffer(gl, true);
+ colors.enableBuffer(gl, true);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ vertices.enableBuffer(gl, false);
+ colors.enableBuffer(gl, false);
+ st.useProgram(gl, false);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval);
+ }
+ reshapeImpl(gl, x, y, width, height, width, height);
+ }
+
+ @Override
+ public void reshapeTile(final TileRendererBase tr,
+ final int tileX, final int tileY, final int tileWidth, final int tileHeight,
+ final int imageWidth, final int imageHeight) {
+ final GL2ES2 gl = tr.getAttachedDrawable().getGL().getGL2ES2();
+ gl.setSwapInterval(0);
+ reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
+ }
+
+ void reshapeImpl(final GL2ES2 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse);
+ // Thread.dumpStack();
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+
+ st.useProgram(gl, true);
+ // Set location in front of camera
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+
+ // compute projection parameters 'normal' perspective
+ final float fovy=45f;
+ final float aspect2 = ( (float) imageWidth / (float) imageHeight ) / aspect;
+ final float zNear=1f;
+ final float zFar=100f;
+
+ // compute projection parameters 'normal' frustum
+ final float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear;
+ final float bottom=-1.0f*top;
+ final float left=aspect2*bottom;
+ final float right=aspect2*top;
+ final float w = right - left;
+ final float h = top - bottom;
+
+ // compute projection parameters 'tiled'
+ final float l = left + tileX * w / imageWidth;
+ final float r = l + tileWidth * w / imageWidth;
+ final float b = bottom + tileY * h / imageHeight;
+ final float t = b + tileHeight * h / imageHeight;
+
+ pmvMatrix.glFrustumf(l, r, b, t, zNear, zFar);
+ //pmvMatrix.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+
+ System.err.println(Thread.currentThread()+" RedSquareES2.reshape FIN");
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable glad) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.dispose: tileRendererInUse "+tileRendererInUse);
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+ st.destroy(gl);
+ st = null;
+ pmvMatrix = null;
+ System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN");
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java
index 6e701658c..c87c04f7e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.es2;
import java.nio.FloatBuffer;
@@ -51,43 +51,67 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc;
public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01Accessor {
TextureData textureData;
Texture texture;
-
+ int textureUnit;
+ boolean keepTextureBound;
+
ShaderState st;
PMVMatrix pmvMatrix;
GLUniformData pmvMatrixUniform;
GLArrayDataServer interleavedVBO;
-
-
- public TextureDraw01ES2Listener(TextureData td) {
+ float[] clearColor = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
+
+ /**
+ *
+ * @param td
+ * @param textureUnit of range [0..]
+ */
+ public TextureDraw01ES2Listener(final TextureData td, final int textureUnit) {
this.textureData = td;
+ this.textureUnit = textureUnit;
+ this.keepTextureBound = false;
+ }
+
+ public void setClearColor(final float[] clearColor) {
+ this.clearColor = clearColor;
+ }
+
+ @Override
+ public void setKeepTextureBound(final boolean v) {
+ this.keepTextureBound = v;
}
+ @Override
+ public Texture getTexture( ) {
+ return this.texture;
+ }
+
+ /**
+ public void setTextureData(GL gl, TextureData textureData ) {
+ if(null!=texture) {
+ texture.disable(gl);
+ texture.destroy(gl);
+ }
+ if(null!=this.textureData) {
+ this.textureData.destroy();
+ }
+ this.textureData = textureData;
+ this.texture = TextureIO.newTexture(this.textureData);
+
+ // fix VBO !
+ } */
- static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
- static final String gl2_prelude = "#version 110\n";
static final String shaderBasename = "texture01_xxx";
-
- private void initShader(GL2ES2 gl, boolean use_program) {
+
+ private void initShader(final GL2ES2 gl, final boolean use_program) {
// Create & Compile the shader objects
- ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
+ final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
"shader", "shader/bin", shaderBasename, true);
- ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
+ final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
"shader", "shader/bin", shaderBasename, true);
-
- // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
- int rsFpPos;
- if(gl.isGLES2()) {
- rsVp.insertShaderSource(0, 0, es2_prelude[0]);
- rsFpPos = rsFp.insertShaderSource(0, 0, es2_prelude[0]);
- } else {
- rsVp.insertShaderSource(0, 0, gl2_prelude);
- rsFpPos = rsFp.insertShaderSource(0, 0, gl2_prelude);
- }
- if(gl.isGLES2()) {
- rsFpPos = rsFp.insertShaderSource(0, rsFpPos, es2_prelude[1]);
- }
-
+ rsVp.defaultShaderCustomization(gl, true, true);
+ rsFp.defaultShaderCustomization(gl, true, true);
+
// Create & Link the shader program
- ShaderProgram sp = new ShaderProgram();
+ final ShaderProgram sp = new ShaderProgram();
sp.add(rsVp);
sp.add(rsFp);
if(!sp.link(gl, System.err)) {
@@ -98,103 +122,92 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
st = new ShaderState();
st.attachShaderProgram(gl, sp, use_program);
}
-
- public void init(GLAutoDrawable glad) {
- if(null!=textureData) {
- this.texture = TextureIO.newTexture(glad.getGL(), textureData);
+
+ @Override
+ public void init(final GLAutoDrawable glad) {
+ if( null != textureData ) {
+ texture = TextureIO.newTexture(glad.getGL(), textureData);
}
- GL2ES2 gl = glad.getGL().getGL2ES2();
-
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+
initShader(gl, true);
-
+
// setup mgl_PMVMatrix
pmvMatrix = new PMVMatrix();
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
- pmvMatrix.glLoadIdentity();
pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
-
+
st.ownUniform(pmvMatrixUniform);
if(!st.uniform(gl, pmvMatrixUniform)) {
throw new GLException("Error setting PMVMatrix in shader: "+st);
}
- if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", 0))) {
+ if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", textureUnit))) {
throw new GLException("Error setting mgl_ActiveTexture in shader: "+st);
}
- // fetch the flipped texture coordinates
- texture.getImageTexCoords().getST_LB_RB_LT_RT(s_quadTexCoords, 0, 1f, 1f);
-
+ if( null != texture ) {
+ // fetch the flipped texture coordinates
+ texture.getImageTexCoords().getST_LB_RB_LT_RT(s_quadTexCoords, 0, 1f, 1f);
+ }
+
interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
- {
- interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
- interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ {
+ interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
//interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER);
interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
- FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
-
+ final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
+
for(int i=0; i<4; i++) {
ib.put(s_quadVertices, i*3, 3);
- ib.put(s_quadColors, i*4, 4);
+ ib.put(s_quadColors, i*4, 4);
//ib.put(s_cubeNormals, i*3, 3);
ib.put(s_quadTexCoords, i*2, 2);
- }
+ }
}
interleavedVBO.seal(gl, true);
interleavedVBO.enableBuffer(gl, false);
st.ownAttribute(interleavedVBO, true);
-
+
// OpenGL Render Settings
- gl.glClearColor(0, 0, 0, 1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
- st.useProgram(gl, false);
- }
+ gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ gl.glEnable(GL.GL_DEPTH_TEST);
- public Texture getTexture( ) {
- return this.texture;
- }
-
- /**
- public void setTextureData(GL gl, TextureData textureData ) {
- if(null!=texture) {
- texture.disable(gl);
- texture.destroy(gl);
- }
- if(null!=this.textureData) {
- this.textureData.destroy();
+ if( keepTextureBound && null != texture ) {
+ gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit);
+ texture.enable(gl);
+ texture.bind(gl);
}
- this.textureData = textureData;
- this.texture = TextureIO.newTexture(this.textureData);
-
- // fix VBO !
- } */
+ st.useProgram(gl, false);
+ }
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- gl.glViewport(0, 0, width, height);
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
// Clear background to white
- gl.glClearColor(1.0f, 1.0f, 1.0f, 0.4f);
-
+ gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
if(null != st) {
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
-
+
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
-
+
st.useProgram(gl, true);
st.uniform(gl, pmvMatrixUniform);
st.useProgram(gl, false);
- }
+ }
}
- public void dispose(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
if(null!=texture) {
texture.disable(gl);
texture.destroy(gl);
@@ -204,45 +217,49 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
}
pmvMatrixUniform = null;
- pmvMatrix.destroy();
pmvMatrix=null;
st.destroy(gl);
st=null;
}
- public void display(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- st.useProgram(gl, true);
+ st.useProgram(gl, true);
interleavedVBO.enableBuffer(gl, true);
- gl.glActiveTexture(GL.GL_TEXTURE0);
- texture.enable(gl);
- texture.bind(gl);
-
+ if( !keepTextureBound && null != texture ) {
+ gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit);
+ texture.enable(gl);
+ texture.bind(gl);
+ }
+
gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
-
- texture.disable(gl);
- interleavedVBO.enableBuffer(gl, false);
+
+ if( !keepTextureBound && null != texture ) {
+ texture.disable(gl);
+ }
+ interleavedVBO.enableBuffer(gl, false);
st.useProgram(gl, false);
}
-
- private static final float[] s_quadVertices = {
+
+ private static final float[] s_quadVertices = {
-1f, -1f, 0f, // LB
1f, -1f, 0f, // RB
-1f, 1f, 0f, // LT
- 1f, 1f, 0f // RT
+ 1f, 1f, 0f // RT
};
- private static final float[] s_quadColors = {
+ private static final float[] s_quadColors = {
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f };
- private static final float[] s_quadTexCoords = {
+ private static final float[] s_quadTexCoords = {
0f, 0f, // LB
1f, 0f, // RB
- 0f, 1f, // LT
+ 0f, 1f, // LT
1f, 1f // RT
};
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java
new file mode 100644
index 000000000..27395ea45
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java
@@ -0,0 +1,285 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2;
+
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.TextureAttachment;
+import com.jogamp.opengl.FBObject.Attachment.Type;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+public class TextureDraw02ES2ListenerFBO implements GLEventListener {
+ private final GLEventListener demo;
+ private final int swapInterval;
+ private boolean clearBuffers = true;
+ private int numSamples;
+ int textureUnit;
+ boolean keepTextureBound;
+
+ private final ShaderState st;
+ private final PMVMatrix pmvMatrix;
+
+ private final FBObject fbo0;
+
+ private TextureAttachment fbo0Tex;
+
+ private ShaderProgram sp0;
+ private GLUniformData pmvMatrixUniform;
+ private GLArrayDataServer interleavedVBO;
+ private GLUniformData texUnit0;
+
+ public TextureDraw02ES2ListenerFBO(final GLEventListener demo, final int swapInterval, final int textureUnit) {
+ this.demo = demo;
+ this.swapInterval = swapInterval;
+ this.textureUnit = textureUnit;
+ this.keepTextureBound = false;
+
+ st = new ShaderState();
+ // st.setVerbose(true);
+ pmvMatrix = new PMVMatrix();
+
+ fbo0 = new FBObject();
+
+ numSamples = 0;
+ }
+
+ public void setClearBuffers(final boolean v) { clearBuffers = v; }
+
+ public void setKeepTextureBound(final boolean v) {
+ this.keepTextureBound = v;
+ }
+ public void setMSAA(final int numSamples) {
+ this.numSamples=numSamples;
+ }
+ public int getMSAA() { return numSamples; }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ demo.init(drawable);
+
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TextureDraw02ES2ListenerFBO.class, "shader",
+ "shader/bin", "texture01_xxx", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TextureDraw02ES2ListenerFBO.class, "shader",
+ "shader/bin", "texture02_xxx", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+
+ sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ st.attachShaderProgram(gl, sp0, true);
+
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+
+ interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
+ {
+ interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ //interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
+
+ final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
+
+ for(int i=0; i<4; i++) {
+ ib.put(s_quadVertices, i*3, 3);
+ ib.put(s_quadColors, i*4, 4);
+ //ib.put(s_cubeNormals, i*3, 3);
+ ib.put(s_quadTexCoords, i*2, 2);
+ }
+ }
+ interleavedVBO.seal(gl, true);
+ interleavedVBO.enableBuffer(gl, false);
+ st.ownAttribute(interleavedVBO, true);
+
+ texUnit0 = new GLUniformData("mgl_Texture0", textureUnit);
+ st.ownUniform(texUnit0);
+ st.uniform(gl, texUnit0);
+
+ st.useProgram(gl, false);
+
+ initFBOs(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ }
+
+ private void initFBOs(final GL gl, final int width, final int height) {
+ fbo0.init(gl, width, height, numSamples);
+ numSamples = fbo0.getNumSamples();
+
+ if(numSamples>0) {
+ fbo0.attachColorbuffer(gl, 0, true);
+ fbo0.resetSamplingSink(gl);
+ fbo0Tex = fbo0.getSamplingSink().getTextureAttachment();
+ } else {
+ fbo0Tex = fbo0.attachTexture2D(gl, 0, true);
+ }
+ numSamples=fbo0.getNumSamples();
+ fbo0.attachRenderbuffer(gl, Type.DEPTH, FBObject.CHOSEN_BITS);
+ fbo0.unbind(gl);
+ }
+
+ private void resetFBOs(final GL gl, final int width, final int height) {
+ fbo0.reset(gl, width, height, numSamples);
+ numSamples = fbo0.getNumSamples();
+ if(numSamples>0) {
+ fbo0Tex = fbo0.getSamplingSink().getTextureAttachment();
+ } else {
+ fbo0Tex = fbo0.getColorbuffer(0).getTextureAttachment();
+ }
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ demo.dispose(drawable);
+ fbo0.destroy(gl);
+ st.destroy(gl);
+
+ fbo0Tex = null;
+ sp0 = null;
+ pmvMatrixUniform = null;
+ interleavedVBO = null;
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ if( fbo0.getNumSamples() != numSamples ) {
+ System.err.println("**** NumSamples: "+fbo0.getNumSamples()+" -> "+numSamples);
+ resetFBOs(gl, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ }
+
+ if(0 < numSamples) {
+ gl.glEnable(GL.GL_MULTISAMPLE);
+ }
+
+ fbo0.bind(gl);
+ demo.display(drawable);
+ fbo0.unbind(gl);
+
+ st.useProgram(gl, true);
+ if( clearBuffers ) {
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+
+ if( !keepTextureBound ) {
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue());
+ fbo0.use(gl, fbo0Tex);
+ if( !gl.isGLcore() ) {
+ gl.glEnable(GL.GL_TEXTURE_2D);
+ }
+ }
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue());
+ interleavedVBO.enableBuffer(gl, true);
+
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+
+ interleavedVBO.enableBuffer(gl, false);
+
+ if( !keepTextureBound ) {
+ fbo0.unuse(gl);
+ }
+
+ st.useProgram(gl, false);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ }
+
+ System.err.println("**** Reshape.Reset: "+width+"x"+height);
+ if( keepTextureBound ) {
+ fbo0.unuse(gl);
+ }
+ resetFBOs(gl, width, height);
+
+ fbo0.bind(gl);
+ demo.reshape(drawable, x, y, width, height);
+ fbo0.unbind(gl);
+
+ if( keepTextureBound ) {
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue());
+ fbo0.use(gl, fbo0Tex);
+ if( !gl.isGLcore() ) {
+ gl.glEnable(GL.GL_TEXTURE_2D);
+ }
+ }
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+
+ }
+
+ private static final float[] s_quadVertices = {
+ -1f, -1f, 0f, // LB
+ 1f, -1f, 0f, // RB
+ -1f, 1f, 0f, // LT
+ 1f, 1f, 0f // RT
+ };
+ private static final float[] s_quadColors = {
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f };
+ private static final float[] s_quadTexCoords = {
+ 0f, 0f, // LB
+ 1f, 0f, // RB
+ 0f, 1f, // LT
+ 1f, 1f // RT
+ };
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
index 9217e2b53..99b943c65 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,14 +20,13 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.jogamp.opengl.test.junit.jogl.demos.es2;
-import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import javax.media.opengl.GL;
@@ -40,10 +39,12 @@ import javax.media.opengl.GLProfile;
import javax.media.opengl.GLUniformData;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import com.jogamp.common.os.Platform;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseListener;
+import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
@@ -53,57 +54,61 @@ import com.jogamp.opengl.util.glsl.ShaderState;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureCoords;
import com.jogamp.opengl.util.texture.TextureSequence;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
public class TextureSequenceCubeES2 implements GLEventListener {
- public TextureSequenceCubeES2 (TextureSequence texSource, boolean innerCube, float zoom0, float rotx, float roty) {
+ public TextureSequenceCubeES2 (final TextureSequence texSource, final boolean innerCube, final float zoom0, final float rotx, final float roty) {
this.texSeq = texSource;
this.innerCube = innerCube;
- this.zoom0 = zoom0;
+ this.zoom = zoom0;
this.view_rotx = rotx;
this.view_roty = roty;
}
private TextureSequence texSeq;
- private ShaderState st;
- private PMVMatrix pmvMatrix;
+ public ShaderState st;
+ public PMVMatrix pmvMatrix;
private GLUniformData pmvMatrixUniform;
// private TextureCoords[] textureCoords = null;
private float nearPlaneNormalized;
// private float zoom0=-5.0f, zoom=zoom0;
// private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f;
- private float zoom0=-2.3f, zoom=zoom0;
- private float view_rotx = 0.0f, view_roty = 0.0f, view_rotz = 0.0f;
+ public float zoom=-2.3f;
+ private float view_rotx = 0.0f, view_roty = 0.0f;
+ private final float view_rotz = 0.0f;
int[] vboNames = new int[4];
boolean innerCube;
- boolean initialized = false;
- private ByteBuffer cubeIndices;
-
+
private final MouseListener mouseAction = new MouseAdapter() {
int lx = 0;
int ly = 0;
boolean first = false;
- public void mousePressed(MouseEvent e) {
- first = true;
+ public void mousePressed(final MouseEvent e) {
+ first = true;
}
- public void mouseMoved(MouseEvent e) {
+ public void mouseMoved(final MouseEvent e) {
first = false;
}
- public void mouseDragged(MouseEvent e) {
+ public void mouseDragged(final MouseEvent e) {
int width, height;
- Object source = e.getSource();
+ final Object source = e.getSource();
Window window = null;
if(source instanceof Window) {
window = (Window) source;
- width=window.getWidth();
- height=window.getHeight();
+ width=window.getSurfaceWidth();
+ height=window.getSurfaceHeight();
+ } else if (source instanceof GLAutoDrawable) {
+ final GLAutoDrawable glad = (GLAutoDrawable) source;
+ width = glad.getSurfaceWidth();
+ height = glad.getSurfaceHeight();
} else if (GLProfile.isAWTAvailable() && source instanceof java.awt.Component) {
- java.awt.Component comp = (java.awt.Component) source;
- width=comp.getWidth();
+ final java.awt.Component comp = (java.awt.Component) source;
+ width=comp.getWidth(); // FIXME HiDPI: May need to convert window units -> pixel units!
height=comp.getHeight();
} else {
throw new RuntimeException("Event source neither Window nor Component: "+source);
- }
+ }
if(e.getPointerCount()==2) {
// 2 pointers zoom ..
if(first) {
@@ -111,11 +116,16 @@ public class TextureSequenceCubeES2 implements GLEventListener {
first=false;
return;
}
- int nv = Math.abs(e.getY(0)-e.getY(1));
- int dy = nv - lx;
-
- zoom += 40f*Math.signum(dy)/(float)height;
-
+ final int nv = Math.abs(e.getY(0)-e.getY(1));
+ final int dy = nv - lx;
+
+ {
+ final float o = zoom;
+ final float d = 40f*Math.signum(dy)/height;
+ zoom += d;
+ System.err.println("zoom.d: "+o+" + "+d+" -> "+zoom);
+ }
+
lx = nv;
} else {
// 1 pointer rotate
@@ -125,56 +135,64 @@ public class TextureSequenceCubeES2 implements GLEventListener {
first=false;
return;
}
- int nx = e.getX();
- int ny = e.getY();
+ final int nx = e.getX();
+ final int ny = e.getY();
view_roty += 360f * ( (float)( nx - lx ) / (float)width );
view_rotx += 360f * ( (float)( ny - ly ) / (float)height );
lx = nx;
ly = ny;
}
- }
- public void mouseWheelMoved(MouseEvent e) {
- zoom += e.getWheelRotation()/10f;
- System.err.println("zoom: "+zoom);
+ }
+ public void mouseWheelMoved(final MouseEvent e) {
+ // System.err.println("XXX "+e);
+ if( !e.isShiftDown() ) {
+ final float o = zoom;
+ final float d = e.getRotation()[1]/10f; // vertical: wheel
+ zoom += d;
+ System.err.println("zoom.w: "+o+" + "+d+" -> "+zoom);
+ }
}
};
-
- static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
- static final String gl2_prelude = "#version 110\n";
+
static final String shaderBasename = "texsequence_xxx";
static final String myTextureLookupName = "myTexture2D";
-
- private void initShader(GL2ES2 gl) {
+
+ private void initShader(final GL2ES2 gl) {
// Create & Compile the shader objects
- ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
+ final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
"shader", "shader/bin", shaderBasename, true);
- ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
+ final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
"shader", "shader/bin", shaderBasename, true);
-
- // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
- int rsFpPos;
- if(gl.isGLES2()) {
- rsVp.insertShaderSource(0, 0, es2_prelude[0]);
- rsFpPos = rsFp.insertShaderSource(0, 0, es2_prelude[0]);
- } else {
- rsVp.insertShaderSource(0, 0, gl2_prelude);
- rsFpPos = rsFp.insertShaderSource(0, 0, gl2_prelude);
+
+ boolean preludeGLSLVersion = true;
+ if( GLES2.GL_TEXTURE_EXTERNAL_OES == texSeq.getTextureTarget() ) {
+ if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) {
+ throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available");
+ }
+ if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) {
+ // Bug on Nexus 10, ES3 - Android 4.3, where
+ // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' !
+ // P0003: Extension 'GL_OES_EGL_image_external' not supported
+ preludeGLSLVersion = false;
+ }
}
+ rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true);
+
+ int rsFpPos = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0;
rsFpPos = rsFp.insertShaderSource(0, rsFpPos, texSeq.getRequiredExtensionsShaderStub());
- if(gl.isGLES2()) {
- rsFpPos = rsFp.insertShaderSource(0, rsFpPos, es2_prelude[1]);
- }
- final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName);
+ rsFp.addDefaultShaderPrecision(gl, rsFpPos);
+
+ final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName);
rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName);
-
+
// Inject TextureSequence shader details
final StringBuilder sFpIns = new StringBuilder();
sFpIns.append("uniform ").append(texSeq.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n");
sFpIns.append(texSeq.getTextureLookupFragmentShaderImpl());
rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns);
-
+
// Create & Link the shader program
- ShaderProgram sp = new ShaderProgram();
+ final ShaderProgram sp = new ShaderProgram();
sp.add(rsVp);
sp.add(rsFp);
if(!sp.link(gl, System.err)) {
@@ -185,26 +203,25 @@ public class TextureSequenceCubeES2 implements GLEventListener {
st = new ShaderState();
st.attachShaderProgram(gl, sp, false);
}
-
- GLArrayDataServer interleavedVBO;
-
- public void init(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ GLArrayDataServer interleavedVBO, cubeIndicesVBO;
+
+ public void init(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
System.err.println(JoglVersion.getGLInfo(gl, null));
- final Texture tex= texSeq.getLastTexture().getTexture();
-
- final boolean useExternalTexture = GLES2.GL_TEXTURE_EXTERNAL_OES == tex.getTarget();
- if(useExternalTexture && !gl.isExtensionAvailable("GL_OES_EGL_image_external")) {
- throw new GLException("GL_OES_EGL_image_external requested but not available");
+ final TextureFrame frame = texSeq.getLastTexture();
+ if( null == frame ) {
+ return;
}
-
+ final Texture tex= frame.getTexture();
+
initShader(gl);
- // Push the 1st uniform down the path
+ // Push the 1st uniform down the path
st.useProgram(gl, true);
pmvMatrix = new PMVMatrix();
- reshapePMV(drawable.getWidth(), drawable.getHeight());
+ reshapePMV(drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
if(!st.uniform(gl, pmvMatrixUniform)) {
throw new GLException("Error setting PMVMatrix in shader: "+st);
@@ -212,10 +229,10 @@ public class TextureSequenceCubeES2 implements GLEventListener {
if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", texSeq.getTextureUnit()))) {
throw new GLException("Error setting mgl_ActiveTexture in shader: "+st);
}
-
-
+
+
// calculate centered tex coords w/ aspect ratio
- float[] fixedCubeTexCoords = new float[s_cubeTexCoords.length];
+ final float[] fixedCubeTexCoords = new float[s_cubeTexCoords.length];
{
final float aspect = tex.getAspectRatio();
final TextureCoords tc = tex.getImageTexCoords();
@@ -239,58 +256,58 @@ public class TextureSequenceCubeES2 implements GLEventListener {
}
}
}
-
+
interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*6*4, GL.GL_STATIC_DRAW);
- {
- interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
- interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ {
+ interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
//interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER);
interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
- FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
-
+ final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
+
for(int i=0; i<6*4; i++) {
ib.put(s_cubeVertices, i*3, 3);
- ib.put(s_cubeColors, i*4, 4);
+ ib.put(s_cubeColors, i*4, 4);
//ib.put(s_cubeNormals, i*3, 3);
ib.put(fixedCubeTexCoords, i*2, 2);
- }
+ }
}
interleavedVBO.seal(gl, true);
interleavedVBO.enableBuffer(gl, false);
st.ownAttribute(interleavedVBO, true);
- cubeIndices = ByteBuffer.wrap(s_cubeIndices);
-
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
+
+ cubeIndicesVBO = GLArrayDataServer.createData(6, GL.GL_UNSIGNED_SHORT, 6, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
+ for(int i=0; i<6*6; i++) {
+ cubeIndicesVBO.puts(s_cubeIndices[i]);
+ }
+ cubeIndicesVBO.seal(gl, true);
+ cubeIndicesVBO.enableBuffer(gl, false);
+ st.ownAttribute(cubeIndicesVBO, true);
+
+
+ gl.glEnable(GL.GL_DEPTH_TEST);
st.useProgram(gl, false);
final Object upstreamWidget = drawable.getUpstreamWidget();
- if (upstreamWidget instanceof Window) {
+ if (upstreamWidget instanceof Window) {
final Window window = (Window) upstreamWidget;
window.addMouseListener(mouseAction);
} else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) {
final java.awt.Component comp = (java.awt.Component) upstreamWidget;
- new com.jogamp.newt.event.awt.AWTMouseAdapter(mouseAction).addTo(comp);
+ new com.jogamp.newt.event.awt.AWTMouseAdapter(mouseAction, drawable).addTo(comp);
}
-
+
// Let's show the completed shader state ..
System.out.println("iVBO: "+interleavedVBO);
System.out.println(st);
}
-
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
- gl.glViewport(0, 0, width, height);
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
- if(innerCube) {
- // Clear background to white
- gl.glClearColor(1.0f, 1.0f, 1.0f, 0.4f);
- } else {
- // Clear background to blue
- gl.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
- }
+ gl.glViewport(0, 0, width, height);
if(!innerCube) {
// lights on
@@ -307,44 +324,60 @@ public class TextureSequenceCubeES2 implements GLEventListener {
st.useProgram(gl, false);
}
}
-
-
- private void reshapePMV(int width, int height) {
- pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
- pmvMatrix.glLoadIdentity();
- if(!innerCube) {
- pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, 1f, 10.0f);
- nearPlaneNormalized = 1f/(100f-1f);
- } else {
- pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 10.0f);
- nearPlaneNormalized = 0f;
- }
- System.err.println("XXX0: Perspective nearPlaneNormalized: "+nearPlaneNormalized);
- pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
- pmvMatrix.glLoadIdentity();
- pmvMatrix.glTranslatef(0, 0, zoom0);
+
+ private void reshapePMV(final int width, final int height) {
+ if(null != pmvMatrix) {
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ if(!innerCube) {
+ pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, 1f, 10.0f);
+ nearPlaneNormalized = 1f/(100f-1f);
+ } else {
+ pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 10.0f);
+ nearPlaneNormalized = 0f;
+ }
+ System.err.println("XXX0: Perspective nearPlaneNormalized: "+nearPlaneNormalized);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glTranslatef(0, 0, zoom);
+ }
}
- public void dispose(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
- texSeq = null;
+ texSeq = null;
pmvMatrixUniform = null;
- pmvMatrix.destroy();
pmvMatrix=null;
- st.destroy(gl);
- st=null;
+ if( null != st ) {
+ st.destroy(gl);
+ st=null;
+ }
}
- public void display(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if(innerCube) {
+ // Clear background to white
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.4f);
+ } else {
+ // Clear background to blue
+ gl.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+ }
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ if( null == st ) {
+ return;
+ }
+
st.useProgram(gl, true);
-
+
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
pmvMatrix.glTranslatef(0, 0, zoom);
@@ -355,25 +388,25 @@ public class TextureSequenceCubeES2 implements GLEventListener {
interleavedVBO.enableBuffer(gl, true);
Texture tex = null;
if(null!=texSeq) {
- final TextureSequence.TextureFrame texFrame = texSeq.getNextTexture(gl, true);
+ final TextureSequence.TextureFrame texFrame = texSeq.getNextTexture(gl);
if(null != texFrame) {
tex = texFrame.getTexture();
gl.glActiveTexture(GL.GL_TEXTURE0+texSeq.getTextureUnit());
tex.enable(gl);
- tex.bind(gl);
+ tex.bind(gl);
}
}
- gl.glDrawElements(GL.GL_TRIANGLES, 6 * 6, GL.GL_UNSIGNED_BYTE, cubeIndices);
+ cubeIndicesVBO.bindBuffer(gl, true); // keeps VBO binding
+ gl.glDrawElements(GL.GL_TRIANGLES, cubeIndicesVBO.getElementCount() * cubeIndicesVBO.getComponentCount(), GL.GL_UNSIGNED_SHORT, 0);
+ cubeIndicesVBO.bindBuffer(gl, false);
+
if(null != tex) {
- tex.disable(gl);
+ tex.disable(gl);
}
interleavedVBO.enableBuffer(gl, false);
- st.useProgram(gl, false);
+ st.useProgram(gl, false);
}
- public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
- }
-
static final float[] light_position = { -50.f, 50.f, 50.f, 0.f };
static final float[] light_ambient = { 0.125f, 0.125f, 0.125f, 1.f };
static final float[] light_diffuse = { 1.0f, 1.0f, 1.0f, 1.f };
@@ -383,18 +416,18 @@ public class TextureSequenceCubeES2 implements GLEventListener {
private static final float[] s_cubeVertices = /* f b t b r l */
{
-1f, 1f, 1f, 1f, -1f, 1f, 1f, 1f, 1f, -1f, -1f, 1f,
-
+
-1f, 1f, -1f, 1f, -1f, -1f, 1f, 1f, -1f, -1f, -1f, -1f,
-
+
-1f, -1f, 1f, 1f, -1f, -1f, 1f, -1f, 1f, -1f, -1f, -1f,
-
+
-1f, 1f, 1f, 1f, 1f, -1f, 1f, 1f, 1f, -1f, 1f, -1f,
-
+
1f, -1f, 1f, 1f, 1f, -1f, 1f, 1f, 1f, 1f, -1f, -1f,
-
+
-1f, -1f, 1f, -1f, 1f, -1f, -1f, 1f, 1f, -1f, -1f, -1f
};
-
+
private static final float[] s_cubeTexCoords =
{ // LT RB RT LB
0f, 1f, 1f, 0f, 1f, 1f, 0f, 0f,
@@ -413,39 +446,39 @@ public class TextureSequenceCubeES2 implements GLEventListener {
private static final float[] s_cubeColors =
{
1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f,
-
+
40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f,
40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f,
-
+
40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f,
- 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f,
-
+ 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f,
+
128f/255f, 128f/255f, 128f/255f, 255f/255f, 128f/255f, 128f/255f, 128f/255f, 255f/255f,
128f/255f, 128f/255f, 128f/255f, 255f/255f, 128f/255f, 128f/255f, 128f/255f, 255f/255f,
-
+
255f/255f, 110f/255f, 10f/255f, 255f/255f, 255f/255f, 110f/255f, 10f/255f, 255f/255f,
255f/255f, 110f/255f, 10f/255f, 255f/255f, 255f/255f, 110f/255f, 10f/255f, 255f/255f,
-
+
255f/255f, 70f/255f, 60f/255f, 255f/255f, 255f/255f, 70f/255f, 60f/255f, 255f/255f,
255f/255f, 70f/255f, 60f/255f, 255f/255f, 255f/255f, 70f/255f, 60f/255f, 255f/255f
};
-
+
/*
private static final float[] s_cubeNormals =
{
0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f,
-
+
0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f,
-
+
0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f,
-
+
0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f,
-
+
1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f,
-
+
-1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f
};*/
- private static final byte[] s_cubeIndices =
+ private static final short[] s_cubeIndices =
{
0, 3, 1, 2, 0, 1, /* front */
6, 5, 4, 5, 7, 4, /* back */
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java
new file mode 100644
index 000000000..b2ebc7068
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java
@@ -0,0 +1,211 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2.av;
+
+import com.jogamp.common.net.Uri;
+import com.jogamp.opengl.util.av.AudioSink;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
+import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+import java.io.File;
+
+/**
+ * Parallel media player that demonstrate CrossFade of audio volume during playback.
+ * This also demonstrate audio only playback of the GLMediaPlayer.
+ */
+public class CrossFadePlayer
+{
+ static GLMediaPlayer[] player;
+ static volatile boolean stop = false;
+
+ public static void main(final String[] args)
+ {
+
+ if(args.length==0) {
+ System.out.println("No files! \n" +
+ "pass as many media files you want\n" +
+ "to the CrossFadePlayer arguments \n" +
+ "and i will try CrossFade-play them all in parallel!");
+ }
+
+ final GLMediaEventListener mediaEventListener = new GLMediaEventListener()
+ {
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) { }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when)
+ {
+ System.out.println("\n***\nEvent mask changed: " + event_mask);
+ System.out.println("Timestamp: "+ when);
+ System.out.println("State of player: " + mp.getState().toString() +"\n");
+
+ if ((event_mask & GLMediaEventListener.EVENT_CHANGE_INIT) !=0) {
+ System.out.println("Duration: " + mp.getDuration() + "ms");
+ System.out.println("Volume: " + mp.getAudioVolume());
+ System.out.println("player.initGL()...");
+ new Thread() {
+ public void run() {
+ try {
+ mp.initGL(null);
+ if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK
+ mp.play();
+ }
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ } else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PAUSE) !=0) {
+ System.out.println("player.paused()...");
+ } else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PLAY) !=0) {
+ System.out.println("playing...");
+ System.out.println(mp.toString());
+ System.out.println(mp.getAudioSink().toString());
+ } else if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ final StreamException se = mp.getStreamException();
+ if( null != se ) {
+ System.err.println("Player State: EOS + Exception");
+ stop = true;
+ } else {
+ System.err.println("Player State: EOS");
+ new Thread() {
+ public void run() {
+ System.out.println("mp.setPlaySpeed(1f) returned: " + mp.setPlaySpeed(1f));
+ mp.seek(0);
+ mp.play();
+ }
+ }.start();
+ }
+ }
+ if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
+ final StreamException se = mp.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ new Thread() {
+ public void run() {
+ System.out.println("terminating...");
+ stop = true;
+ }
+ }.start();
+ }
+
+ }
+ };
+
+ // Initialize media players
+ player = new GLMediaPlayer[args.length];
+ int i=0;
+ for( final String arg: args ) {
+ player[i] = GLMediaPlayerFactory.createDefault();
+ if(player[i]!=null){
+ System.out.println("Created CrossFade player: "+ i + " " + player[i].getClass().getName());
+ player[i].addEventListener(mediaEventListener);
+ try {
+ final String filename = arg;
+ if(filename.equals("")){
+ System.out.println("No file selected: arg " + i +" = "+ filename);
+ player[i]=null;
+ } else {
+ final File file = new File(filename);
+ if(!file.exists()){
+ System.out.println("File do not exist");
+ } else {
+ final Uri uri = Uri.valueOf(file);
+ System.out.println("State of player "+ i +": " + player[i].getState().toString());
+ System.out.println("...initializing stream "+ i +"...");
+ player[i].initStream(uri, GLMediaPlayer.STREAM_ID_NONE, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
+
+ }
+ }
+ } catch (final Exception e1) {
+ e1.printStackTrace();
+ }
+ } else {
+ System.out.println("Failed to create player "+ i +"!");
+ }
+ i++;
+ }
+
+
+ // Main thread CrossFade until playback is done
+ final long startTime = com.jogamp.common.os.Platform.currentTimeMillis();
+ final double piPlayers = Math.PI*2.0f/args.length;
+ StreamException se = null;
+ while( null == se && stop == false ) {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException e) { }
+
+ // Find out the longest duration...
+ float maxDuration = 1000.0f ;
+ for(final GLMediaPlayer p: player) {
+ if(p!=null){
+ if( p.getDuration() > maxDuration) {
+ maxDuration = p.getDuration();
+ }
+ }
+ }
+
+ // tune the volume on players to crossfade!
+ final float progress = (com.jogamp.common.os.Platform.currentTimeMillis()-startTime)/maxDuration;
+
+ i = 0;
+ for(final GLMediaPlayer p: player){
+ if(p!=null){
+ final AudioSink sink = p.getAudioSink();
+ if(sink != null){
+ final float volume = (float) (0.5f+(0.5f*(Math.cos(40.0f*progress+(piPlayers*i)))));
+ final float playbacktime = com.jogamp.common.os.Platform.currentTimeMillis()-startTime;
+ // System.out.println("player: "+ i +" volume = " + volume +" progress = "+ progress +" time = "+ playbacktime + " / duration = " + maxDuration);
+ sink.setVolume(volume);
+ }
+
+ se = p.getStreamException();
+ if( null != se) {
+ se.printStackTrace();
+ throw new RuntimeException(se);
+ }
+ }
+
+ i++;
+ }
+ }
+
+ for(final GLMediaPlayer p: player) {
+ if(p!=null)
+ p.destroy(null);
+ }
+ System.out.println("...main exit...");
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
index 7f2713354..428eea42c 100755..100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
@@ -1,52 +1,51 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
*/
package com.jogamp.opengl.test.junit.jogl.demos.es2.av;
-import java.io.BufferedReader;
+import java.io.File;
import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
+import java.net.URISyntaxException;
+import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import com.jogamp.common.net.Uri;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.font.Font;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
@@ -55,184 +54,554 @@ import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureSequenceCubeES2;
import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.av.GLMediaPlayer;
import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
-public class MovieCube implements GLEventListener, GLMediaEventListener {
- static boolean waitForKey = false;
- final URLConnection stream;
- final float zoom0, rotx, roty;
- TextureSequenceCubeES2 cube=null;
- GLMediaPlayer mPlayer=null;
-
- public MovieCube() throws IOException {
- this(new URL("http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4").openConnection(),
- -2.3f, 0f, 0f);
+/**
+ * Simple cube movie player w/ aspect ration true projection on a cube.
+ */
+public class MovieCube implements GLEventListener {
+ public static final float zoom_def = -2.77f;
+ private static boolean waitForKey = false;
+ private final float zoom0, rotx, roty;
+ private TextureSequenceCubeES2 cube=null;
+ private GLMediaPlayer mPlayer=null;
+ private int swapInterval = 1;
+ private int swapIntervalSet = -1;
+ private long lastPerfPos = 0;
+ private volatile boolean resetGLState = false;
+
+ /** Blender's Big Buck Bunny: 24f 416p H.264, AAC 48000 Hz, 2 ch, mpeg stream. */
+ public static final Uri defURI;
+ static {
+ Uri _defURI = null;
+ try {
+ // Blender's Big Buck Bunny Trailer: 24f 640p VP8, Vorbis 44100Hz mono, WebM/Matroska Stream.
+ // _defURI = new URI("http://video.webmfiles.org/big-buck-bunny_trailer.webm");
+ _defURI = Uri.cast("http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ } catch (final URISyntaxException e) {
+ e.printStackTrace();
+ }
+ defURI = _defURI;
+ }
+
+ /**
+ * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values
+ * and polls until the {@link GLMediaPlayer} is {@link GLMediaPlayer.State#Initialized}.
+ * If {@link GLMediaEventListener#EVENT_CHANGE_EOS} is reached, the stream is started over again.
+ * <p>
+ * This default constructor is merely useful for some <i>drop-in</i> test, e.g. using an applet.
+ * </p>
+ */
+ public MovieCube() throws IOException, URISyntaxException {
+ this(zoom_def, 0f, 0f, true);
+
+ mPlayer.addEventListener(new GLMediaEventListener() {
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) { }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ System.err.println("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieCube State: "+mp);
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) {
+ resetGLState();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ new Thread() {
+ public void run() {
+ // loop for-ever ..
+ mPlayer.seek(0);
+ mPlayer.play();
+ } }.start();
+ }
+ }
+ });
+ initStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
+ StreamException se = null;
+ while( null == se && GLMediaPlayer.State.Initialized != mPlayer.getState() ) {
+ try {
+ Thread.sleep(16);
+ } catch (final InterruptedException e) { }
+ se = mPlayer.getStreamException();
+ }
+ if( null != se ) {
+ se.printStackTrace();
+ throw new RuntimeException(se);
+ }
}
-
- public MovieCube(URLConnection stream, float zoom0, float rotx, float roty) throws IOException {
- this.stream = stream;
+
+ /**
+ * Custom constructor, user needs to issue {@link #initStream(URI, int, int, int)} afterwards.
+ */
+ public MovieCube(final float zoom0, final float rotx, final float roty, final boolean showText) throws IOException {
this.zoom0 = zoom0;
this.rotx = rotx;
this.roty = roty;
+ this.showText = showText;
+ mPlayer = GLMediaPlayerFactory.createDefault();
}
+ public void initStream(final Uri streamLoc, final int vid, final int aid, final int textureCount) {
+ mPlayer.initStream(streamLoc, vid, aid, textureCount);
+ System.out.println("pC.1b "+mPlayer);
+ }
+
+ public void setSwapInterval(final int v) { this.swapInterval = v; }
+
+ public GLMediaPlayer getGLMediaPlayer() { return mPlayer; }
+
+ public void resetGLState() {
+ resetGLState = true;
+ }
+
+ final int[] textSampleCount = { 4 };
+
+ private final class InfoTextRendererGLELBase extends TextRendererGLELBase {
+ private static final float z_diff = 0.001f;
+ private final Font font = getFont(0, 0, 0);
+ private final float fontSize1 = 12;
+ private final float fontSize2 = 10;
+ private final GLRegion regionFPS;
+ private float pixelSize1, pixelSize2, underlineSize;
+
+ InfoTextRendererGLELBase(final int rmode, final boolean lowPerfDevice) {
+ // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+ super(rmode, MovieCube.this.textSampleCount);
+ this.setRendererCallbacks(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
+ if( lowPerfDevice ) {
+ regionFPS = null;
+ } else {
+ regionFPS = GLRegion.create(renderModes, null);
+ System.err.println("RegionFPS "+Region.getRenderModeString(renderModes)+", sampleCount "+textSampleCount[0]+", class "+regionFPS.getClass().getName());
+ }
+ staticRGBAColor[0] = 0.1f;
+ staticRGBAColor[1] = 0.1f;
+ staticRGBAColor[2] = 0.1f;
+ staticRGBAColor[3] = 1.0f;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ // non-exclusive mode!
+ this.setSharedPMVMatrix(cube.pmvMatrix);
+ super.init(drawable);
+
+ pixelSize1 = font.getPixelSize(fontSize1, dpiH);
+ pixelSize2 = font.getPixelSize(fontSize2, dpiH);
+ pixelScale = 1.0f / ( pixelSize1 * 20f );
+ // underlineSize: 'underline' amount of pixel below 0/0 (Note: lineGap is negative)
+ final Font.Metrics metrics = font.getMetrics();
+ final float lineGap = metrics.getLineGap(pixelSize1);
+ final float descent = metrics.getDescent(pixelSize1);
+ underlineSize = descent - lineGap;
+ System.err.println("XXX: dpiH "+dpiH+", fontSize "+fontSize1+", pixelSize "+pixelSize1+", pixelScale "+pixelScale+", fLG "+lineGap+", fDesc "+descent+", underlineSize "+underlineSize);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( null != regionFPS ) {
+ regionFPS.destroy(drawable.getGL().getGL2ES2());
+ }
+ super.dispose(drawable);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GLAnimatorControl anim = drawable.getAnimator();
+ final float lfps = null != anim ? anim.getLastFPS() : 0f;
+ final float tfps = null != anim ? anim.getTotalFPS() : 0f;
+ final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+ final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f;
+
+ // Note: MODELVIEW is from [ -1 .. 1 ]
+
+ // dy: position right above video rectangle (bottom text line)
+ final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight();
+ final float aspect_h = 1f/aspect;
+ final float dy = 1f-aspect_h;
+
+ // yoff1: position right above video rectangle (bottom text line)
+ // less than underlineSize, so 'underline' pixels are above video.
+ final float yoff1 = dy-(pixelScale*underlineSize);
+
+ // yoff2: position right below video rectangle (bottom text line)
+ final float yoff2 = 2f-dy;
+
+ /**
+ System.err.println("XXX: a "+aspect+", aspect_h "+aspect_h+", dy "+dy+
+ "; underlineSize "+underlineSize+" "+(pixelScale*underlineSize)+
+ "; yoff "+yoff1+", yoff2 "+yoff2); */
+
+ final GL gl = drawable.getGL();
+ final String ptsPrec = null != regionFPS ? "3.1" : "3.0";
+ final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d",
+ pts, mPlayer.getDuration() / 1000f,
+ mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(),
+ aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet);
+ final String text2 = String.format("audio: id %d, kbps %d, codec %s",
+ mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec());
+ final String text3 = String.format("video: id %d, kbps %d, codec %s",
+ mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec());
+ final String text4 = mPlayer.getUri().path.decode();
+ if( displayOSD && null != renderer ) {
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ if( null != regionFPS ) {
+ renderString(drawable, font, pixelSize1, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff, regionFPS); // no-cache
+ } else {
+ renderString(drawable, font, pixelSize1, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff, true);
+ }
+ renderString(drawable, font, pixelSize2, text2, 1 /* col */, 0 /* row */, -1+z_diff, yoff2, 1f+z_diff, true);
+ renderString(drawable, font, pixelSize2, text3, 1 /* col */, 1 /* row */, -1+z_diff, yoff2, 1f+z_diff, true);
+ renderString(drawable, font, pixelSize2, text4, 1 /* col */, 2 /* row */, -1+z_diff, yoff2, 1f+z_diff, true);
+ }
+ } };
+ private InfoTextRendererGLELBase textRendererGLEL = null;
+ final boolean showText;
+ private boolean displayOSD = true;
+
private final KeyListener keyAction = new KeyAdapter() {
- public void keyTyped(KeyEvent e) {
+ public void keyReleased(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
System.err.println("MC "+e);
- int pts0 = mPlayer.getCurrentPosition();
+ final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
int pts1 = 0;
- switch(e.getKeyCode()) {
- case KeyEvent.VK_3:
+ switch(e.getKeySymbol()) {
+ case KeyEvent.VK_V: {
+ switch(swapIntervalSet) {
+ case 0: swapInterval = 1; break;
+ default: swapInterval = 0; break;
+ }
+ break;
+ }
+ case KeyEvent.VK_O: displayOSD = !displayOSD; break;
case KeyEvent.VK_RIGHT: pts1 = pts0 + 1000; break;
- case KeyEvent.VK_4:
case KeyEvent.VK_UP: pts1 = pts0 + 10000; break;
- case KeyEvent.VK_2:
+ case KeyEvent.VK_PAGE_UP: pts1 = pts0 + 30000; break;
case KeyEvent.VK_LEFT: pts1 = pts0 - 1000; break;
- case KeyEvent.VK_1:
case KeyEvent.VK_DOWN: pts1 = pts0 - 10000; break;
+ case KeyEvent.VK_PAGE_DOWN: pts1 = pts0 - 30000; break;
case KeyEvent.VK_ESCAPE:
- case KeyEvent.VK_DELETE:
+ case KeyEvent.VK_HOME:
case KeyEvent.VK_BACK_SPACE: {
mPlayer.seek(0);
- mPlayer.setPlaySpeed(1.0f);
- mPlayer.start();
break;
}
case KeyEvent.VK_SPACE: {
if(GLMediaPlayer.State.Paused == mPlayer.getState()) {
- mPlayer.start();
+ mPlayer.play();
} else {
- mPlayer.pause();
+ mPlayer.pause(false);
}
break;
}
- case KeyEvent.VK_S: mPlayer.setPlaySpeed(mPlayer.getPlaySpeed()/2.0f); break;
- case KeyEvent.VK_F: mPlayer.setPlaySpeed(mPlayer.getPlaySpeed()*2.0f); break;
+ case KeyEvent.VK_MULTIPLY:
+ mPlayer.setPlaySpeed(1.0f);
+ break;
+ case KeyEvent.VK_SUBTRACT: {
+ float playSpeed = mPlayer.getPlaySpeed();
+ if( e.isShiftDown() ) {
+ playSpeed /= 2.0f;
+ } else {
+ playSpeed -= 0.1f;
+ }
+ mPlayer.setPlaySpeed(playSpeed);
+ } break;
+ case KeyEvent.VK_ADD: {
+ float playSpeed = mPlayer.getPlaySpeed();
+ if( e.isShiftDown() ) {
+ playSpeed *= 2.0f;
+ } else {
+ playSpeed += 0.1f;
+ }
+ mPlayer.setPlaySpeed(playSpeed);
+ } break;
+ case KeyEvent.VK_M: {
+ float audioVolume = mPlayer.getAudioVolume();
+ if( audioVolume > 0.5f ) {
+ audioVolume = 0f;
+ } else {
+ audioVolume = 1f;
+ }
+ mPlayer.setAudioVolume(audioVolume);
+ } break;
}
-
+
if( 0 != pts1 ) {
mPlayer.seek(pts1);
}
- }
+ }
};
-
- @Override
- public void attributesChanges(GLMediaPlayer mp, int event_mask, long when) {
- System.out.println("attributesChanges: "+mp+", 0x"+Integer.toHexString(event_mask)+", when "+when);
- }
@Override
- public void newFrameAvailable(GLMediaPlayer mp, long when) {
- // System.out.println("newFrameAvailable: "+mp+", when "+when);
- }
+ public void init(final GLAutoDrawable drawable) {
+ if(null == mPlayer) {
+ throw new InternalError("mPlayer null");
+ }
+ if( GLMediaPlayer.State.Uninitialized == mPlayer.getState() ) {
+ throw new IllegalStateException("mPlayer in uninitialized state: "+mPlayer);
+ }
+ if( GLMediaPlayer.STREAM_ID_NONE == mPlayer.getVID() ) {
+ // throw new IllegalStateException("mPlayer has no VID/stream selected: "+mPlayer);
+ }
+ resetGLState = false;
- public void init(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
System.err.println(JoglVersion.getGLInfo(gl, null));
- mPlayer = GLMediaPlayerFactory.create();
- mPlayer.addEventListener(this);
- cube = new TextureSequenceCubeES2(mPlayer, false, zoom0, rotx, roty);
-
+ cube = new TextureSequenceCubeES2(mPlayer, false, zoom0, rotx, roty);
+
if(waitForKey) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
- System.err.println("Press enter to continue");
- try {
- System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ UITestCase.waitForKey("Init>");
}
- try {
- System.out.println("p0 "+mPlayer);
- mPlayer.initGLStream(gl, stream);
- System.out.println("p1 "+mPlayer);
- } catch (Exception e) {
- e.printStackTrace();
- if(null != mPlayer) {
- mPlayer.destroy(gl);
- mPlayer = null;
+
+ if( GLMediaPlayer.State.Initialized == mPlayer.getState() ) {
+ try {
+ mPlayer.initGL(gl);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ if(null != mPlayer) {
+ mPlayer.destroy(gl);
+ mPlayer = null;
+ }
+ throw new GLException(e);
}
- throw new GLException(e);
}
-
cube.init(drawable);
- mPlayer.start();
+ mPlayer.play();
+ System.out.println("play.0 "+mPlayer);
boolean added;
final Object upstreamWidget = drawable.getUpstreamWidget();
- if (upstreamWidget instanceof Window) {
+ if (upstreamWidget instanceof Window) {
final Window window = (Window) upstreamWidget;
window.addKeyListener(keyAction);
added = true;
- } else { added = false; }
+ } else { added = false; }
System.err.println("MC.init: kl-added "+added+", "+drawable.getClass().getName());
+
+ if( showText ) {
+ final int rmode = drawable.getChosenGLCapabilities().getSampleBuffers() ? 0 : Region.VBAA_RENDERING_BIT;
+ final boolean lowPerfDevice = gl.isGLES();
+ textRendererGLEL = new InfoTextRendererGLELBase(rmode, lowPerfDevice);
+ drawable.addGLEventListener(textRendererGLEL);
+ }
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
if(null == mPlayer) { return; }
cube.reshape(drawable, x, y, width, height);
}
- public void dispose(GLAutoDrawable drawable) {
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
System.err.println(Thread.currentThread()+" MovieCube.dispose ... ");
+ if( null != textRendererGLEL ) {
+ drawable.disposeGLEventListener(textRendererGLEL, true);
+ textRendererGLEL = null;
+ }
+ disposeImpl(drawable, true);
+ }
+
+ private void disposeImpl(final GLAutoDrawable drawable, final boolean disposePlayer) {
if(null == mPlayer) { return; }
- mPlayer.stop();
- GL2ES2 gl = drawable.getGL().getGL2ES2();
- mPlayer.destroy(gl);
- mPlayer=null;
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
+ window.removeKeyListener(keyAction);
+ }
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if( disposePlayer ) {
+ mPlayer.destroy(gl);
+ mPlayer=null;
+ }
cube.dispose(drawable);
cube=null;
}
- public void display(GLAutoDrawable drawable) {
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ if(-1 != swapInterval) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ drawable.getAnimator().resetFPSCounter();
+ swapIntervalSet = swapInterval;
+ swapInterval = -1;
+ }
if(null == mPlayer) { return; }
+
+ if( resetGLState ) {
+ resetGLState = false;
+ System.err.println("XXX resetGLState");
+ disposeImpl(drawable, false);
+ init(drawable);
+ reshape(drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ }
+
+ final long currentPos = System.currentTimeMillis();
+ if( currentPos - lastPerfPos > 2000 ) {
+ System.err.println( mPlayer.getPerfString() );
+ lastPerfPos = currentPos;
+ }
cube.display(drawable);
}
- public void displayChanged(javax.media.opengl.GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
- }
-
- public static void main(String[] args) throws MalformedURLException, IOException, InterruptedException {
- int width = 510;
- int height = 300;
- System.err.println("TexCubeES2.run()");
-
- String url_s="http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4";
- for(int i=0; i<args.length; i++) {
- if(args[i].equals("-width")) {
- i++;
- width = MiscUtils.atoi(args[i], width);
- } else if(args[i].equals("-height")) {
- i++;
- height = MiscUtils.atoi(args[i], height);
- } else if(args[i].equals("-url")) {
- i++;
- url_s = args[i];
- } else if(args[i].equals("-wait")) {
- waitForKey = true;
+ public static void main(final String[] args) throws IOException, InterruptedException, URISyntaxException {
+ int swapInterval = 1;
+ int width = 800;
+ int height = 600;
+ int textureCount = GLMediaPlayer.TEXTURE_COUNT_DEFAULT; // default - threaded
+
+ boolean forceES2 = false;
+ boolean forceES3 = false;
+ boolean forceGL3 = false;
+ boolean forceGLDef = false;
+ int vid = GLMediaPlayer.STREAM_ID_AUTO;
+ int aid = GLMediaPlayer.STREAM_ID_AUTO;
+ final boolean origSize;
+
+ String url_s=null, file_s=null;
+ {
+ boolean _origSize = false;
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-vid")) {
+ i++;
+ vid = MiscUtils.atoi(args[i], vid);
+ } else if(args[i].equals("-aid")) {
+ i++;
+ aid = MiscUtils.atoi(args[i], aid);
+ } else if(args[i].equals("-width")) {
+ i++;
+ width = MiscUtils.atoi(args[i], width);
+ } else if(args[i].equals("-height")) {
+ i++;
+ height = MiscUtils.atoi(args[i], height);
+ } else if(args[i].equals("-osize")) {
+ _origSize = true;
+ } else if(args[i].equals("-textureCount")) {
+ i++;
+ textureCount = MiscUtils.atoi(args[i], textureCount);
+ } else if(args[i].equals("-url")) {
+ i++;
+ url_s = args[i];
+ } else if(args[i].equals("-file")) {
+ i++;
+ file_s = args[i];
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-es3")) {
+ forceES3 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-gldef")) {
+ forceGLDef = true;
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
}
+ origSize = _origSize;
}
- final MovieCube mc = new MovieCube(new URL(url_s).openConnection(), -2.3f, 0f, 0f);
-
- final GLWindow window = GLWindow.create(new GLCapabilities(GLProfile.getGL2ES2()));
- // Size OpenGL to Video Surface
- window.setSize(width, height);
- window.setFullscreen(false);
- window.setSize(width, height);
- window.addGLEventListener(mc);
+ final Uri streamLoc;
+ if( null != url_s ) {
+ streamLoc = Uri.cast( url_s );
+ } else if( null != file_s ) {
+ streamLoc = Uri.valueOf(new File(file_s));
+ } else {
+ streamLoc = defURI;
+ }
+ System.err.println("url_s "+url_s);
+ System.err.println("file_s "+file_s);
+ System.err.println("stream "+streamLoc);
+ System.err.println("vid "+vid+", aid "+aid);
+ System.err.println("textureCount "+textureCount);
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceES3 "+forceES3);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("forceGLDef "+forceGLDef);
+ System.err.println("swapInterval "+swapInterval);
+
+ final MovieCube mc = new MovieCube(zoom_def, 0f, 0f, true);
+ mc.setSwapInterval(swapInterval);
+
+ final GLProfile glp;
+ if(forceGLDef) {
+ glp = GLProfile.getDefault();
+ } else if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES3) {
+ glp = GLProfile.get(GLProfile.GLES3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ System.err.println("GLProfile: "+glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ // caps.setAlphaBits(4); // NOTE_ALPHA_BLENDING: We go w/o alpha and blending!
+ final GLWindow window = GLWindow.create(caps);
final Animator anim = new Animator(window);
window.addWindowListener(new WindowAdapter() {
- public void windowDestroyed(WindowEvent e) {
+ public void windowDestroyed(final WindowEvent e) {
anim.stop();
- }
+ }
});
- // anim.setUpdateFPSFrames(60, System.err);
- anim.start();
+ window.setSize(width, height);
window.setVisible(true);
+ System.err.println("Chosen: "+window.getChosenGLCapabilities());
+ anim.start();
+
+ mc.mPlayer.addEventListener(new GLMediaEventListener() {
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) {
+ }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ System.err.println("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieCube State: "+mp);
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) {
+ if( origSize ) {
+ window.setSurfaceSize(mp.getWidth(), mp.getHeight());
+ }
+ // window.disposeGLEventListener(ms, false /* remove */ );
+ mc.resetGLState();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ window.addGLEventListener(mc);
+ anim.setUpdateFPSFrames(60, null);
+ anim.resetFPSCounter();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
+ anim.resetFPSCounter();
+ }
+ if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
+ final StreamException se = mc.mPlayer.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ new Thread() {
+ public void run() {
+ window.destroy();
+ } }.start();
+ }
+ }
+ });
+ mc.initStream(streamLoc, vid, aid, textureCount);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java
new file mode 100644
index 000000000..7a3a1ffc7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java
@@ -0,0 +1,872 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2.av;
+
+import java.net.URISyntaxException;
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLES2;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.common.net.Uri;
+import com.jogamp.common.os.Platform;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.font.Font;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.KeyListener;
+import com.jogamp.newt.event.MouseAdapter;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.CustomGLEventListener;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.util.stereo.EyeParameter;
+import com.jogamp.opengl.util.stereo.EyePose;
+import com.jogamp.opengl.util.stereo.StereoClientRenderer;
+import com.jogamp.opengl.util.stereo.StereoGLEventListener;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
+import com.jogamp.opengl.util.texture.TextureSequence;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+/**
+ * Side-By-Side (SBS) 3D Movie Player for {@link StereoClientRenderer}
+ * <p>
+ * The movie is assumed to be symmetrical SBS,
+ * the left-eye receives the left-part of the texture
+ * and the right-eye the right-part.
+ * </p>
+ */
+public class MovieSBSStereo implements StereoGLEventListener {
+ public static final String WINDOW_KEY = "window";
+ public static final String STEREO_RENDERER_KEY = "stereo";
+ public static final String PLAYER = "player";
+
+ private static boolean waitForKey = false;
+ private int surfWidth, surfHeight;
+ private int prevMouseX; // , prevMouseY;
+ private int rotate = 0;
+ private float zoom0;
+ private float zoom1;
+ private float zoom;
+ private long startTime;
+ private final float alpha = 1.0f;
+
+ private GLMediaPlayer mPlayer;
+ private boolean mPlayerScaleOrig;
+ private float[] verts = null;
+ private GLArrayDataServer interleavedVBOLeft;
+ private GLArrayDataServer interleavedVBORight;
+ private volatile boolean resetGLState = false;
+ private StereoClientRenderer stereoClientRenderer;
+
+ private ShaderState st;
+ private PMVMatrix pmvMatrix;
+ private GLUniformData pmvMatrixUniform;
+ private static final String shaderBasename = "texsequence_xxx";
+ private static final String myTextureLookupName = "myTexture2D";
+
+ /** Blender's Big Buck Bunny: 24f 416p H.264, AAC 48000 Hz, 2 ch, mpeg stream. */
+ public static final Uri defURI;
+ static {
+ Uri _defURI = null;
+ try {
+ // Blender's Big Buck Bunny Trailer: 24f 640p VP8, Vorbis 44100Hz mono, WebM/Matroska Stream.
+ // _defURI = new URI("http://video.webmfiles.org/big-buck-bunny_trailer.webm");
+ _defURI = Uri.cast("http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ } catch (final URISyntaxException e) {
+ e.printStackTrace();
+ }
+ defURI = _defURI;
+ }
+
+ final int[] textSampleCount = { 4 };
+
+ private final class InfoTextRendererGLELBase extends TextRendererGLELBase {
+ private final Font font = getFont(0, 0, 0);
+ private final float fontSize = 1f; // 0.01f;
+ private final GLRegion regionFPS;
+
+ InfoTextRendererGLELBase(final int rmode, final boolean lowPerfDevice) {
+ // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+ super(rmode, textSampleCount);
+ this.setRendererCallbacks(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
+ if( lowPerfDevice ) {
+ regionFPS = null;
+ } else {
+ regionFPS = GLRegion.create(renderModes, null);
+ System.err.println("RegionFPS "+Region.getRenderModeString(renderModes)+", sampleCount "+textSampleCount[0]+", class "+regionFPS.getClass().getName());
+ }
+ staticRGBAColor[0] = 0.9f;
+ staticRGBAColor[1] = 0.9f;
+ staticRGBAColor[2] = 0.9f;
+ staticRGBAColor[3] = 1.0f;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ super.init(drawable);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( null != regionFPS ) {
+ regionFPS.destroy(drawable.getGL().getGL2ES2());
+ }
+ super.dispose(drawable);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GLAnimatorControl anim = drawable.getAnimator();
+ final float lfps = null != anim ? anim.getLastFPS() : 0f;
+ final float tfps = null != anim ? anim.getTotalFPS() : 0f;
+ final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+ final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f;
+
+ // Note: MODELVIEW is from [ 0 .. height ]
+
+ final int height = 0; // drawable.getSurfaceHeight();
+
+ final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight();
+
+ final String ptsPrec = null != regionFPS ? "3.1" : "3.0";
+ final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f",
+ pts, mPlayer.getDuration() / 1000f,
+ mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(),
+ aspect, mPlayer.getFramerate(), lfps, tfps);
+ final String text2 = String.format("audio: id %d, kbps %d, codec %s",
+ mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec());
+ final String text3 = String.format("video: id %d, kbps %d, codec %s",
+ mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec());
+ final String text4 = mPlayer.getUri().path.decode();
+ if( displayOSD && null != renderer ) {
+ // We share ClearColor w/ MovieSimple's init !
+ final float pixelSize = font.getPixelSize(fontSize, dpiH);
+ if( null != regionFPS ) {
+ renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, regionFPS); // no-cache
+ } else {
+ renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, true);
+ }
+ renderString(drawable, font, pixelSize, text2, 1 /* col */, -4 /* row */, 0, height, -1, true);
+ renderString(drawable, font, pixelSize, text3, 1 /* col */, -3 /* row */, 0, height, 0, true);
+ renderString(drawable, font, pixelSize, text4, 1 /* col */, -2 /* row */, 0, height, 1, true);
+ }
+ } };
+ private final boolean enableTextRendererGLEL = false;
+ private InfoTextRendererGLELBase textRendererGLEL = null;
+ private boolean displayOSD = false;
+
+ private final MouseListener mouseAction = new MouseAdapter() {
+ public void mousePressed(final MouseEvent e) {
+ if(e.getY()<=surfHeight/2 && null!=mPlayer && 1 == e.getClickCount()) {
+ if(GLMediaPlayer.State.Playing == mPlayer.getState()) {
+ mPlayer.pause(false);
+ } else {
+ mPlayer.play();
+ }
+ }
+ }
+ public void mouseReleased(final MouseEvent e) {
+ if(e.getY()<=surfHeight/2) {
+ rotate = -1;
+ zoom = zoom0;
+ System.err.println("zoom: "+zoom);
+ }
+ }
+ public void mouseMoved(final MouseEvent e) {
+ prevMouseX = e.getX();
+ // prevMouseY = e.getY();
+ }
+ public void mouseDragged(final MouseEvent e) {
+ final int x = e.getX();
+ final int y = e.getY();
+
+ if(y>surfHeight/2) {
+ final float dp = (float)(x-prevMouseX)/(float)surfWidth;
+ final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
+ mPlayer.seek(pts0 + (int) (mPlayer.getDuration() * dp));
+ } else {
+ mPlayer.play();
+ rotate = 1;
+ zoom = zoom1;
+ }
+
+ prevMouseX = x;
+ // prevMouseY = y;
+ }
+ public void mouseWheelMoved(final MouseEvent e) {
+ if( !e.isShiftDown() ) {
+ zoom += e.getRotation()[1]/10f; // vertical: wheel
+ System.err.println("zoom: "+zoom);
+ }
+ } };
+
+ private final KeyListener keyAction = new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ System.err.println("MC "+e);
+ final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
+ int pts1 = 0;
+ switch(e.getKeySymbol()) {
+ case KeyEvent.VK_O: displayOSD = !displayOSD; break;
+ case KeyEvent.VK_RIGHT: pts1 = pts0 + 1000; break;
+ case KeyEvent.VK_UP: pts1 = pts0 + 10000; break;
+ case KeyEvent.VK_PAGE_UP: pts1 = pts0 + 30000; break;
+ case KeyEvent.VK_LEFT: pts1 = pts0 - 1000; break;
+ case KeyEvent.VK_DOWN: pts1 = pts0 - 10000; break;
+ case KeyEvent.VK_PAGE_DOWN: pts1 = pts0 - 30000; break;
+ case KeyEvent.VK_ESCAPE:
+ case KeyEvent.VK_HOME:
+ case KeyEvent.VK_BACK_SPACE: {
+ mPlayer.seek(0);
+ break;
+ }
+ case KeyEvent.VK_SPACE: {
+ if(GLMediaPlayer.State.Paused == mPlayer.getState()) {
+ mPlayer.play();
+ } else {
+ mPlayer.pause(false);
+ }
+ break;
+ }
+ case KeyEvent.VK_MULTIPLY:
+ mPlayer.setPlaySpeed(1.0f);
+ break;
+ case KeyEvent.VK_SUBTRACT: {
+ float playSpeed = mPlayer.getPlaySpeed();
+ if( e.isShiftDown() ) {
+ playSpeed /= 2.0f;
+ } else {
+ playSpeed -= 0.1f;
+ }
+ mPlayer.setPlaySpeed(playSpeed);
+ } break;
+ case KeyEvent.VK_ADD: {
+ float playSpeed = mPlayer.getPlaySpeed();
+ if( e.isShiftDown() ) {
+ playSpeed *= 2.0f;
+ } else {
+ playSpeed += 0.1f;
+ }
+ mPlayer.setPlaySpeed(playSpeed);
+ } break;
+ case KeyEvent.VK_M: {
+ float audioVolume = mPlayer.getAudioVolume();
+ if( audioVolume > 0.5f ) {
+ audioVolume = 0f;
+ } else {
+ audioVolume = 1f;
+ }
+ mPlayer.setAudioVolume(audioVolume);
+ } break;
+ }
+
+ if( 0 != pts1 ) {
+ mPlayer.seek(pts1);
+ }
+ } };
+
+ /** user needs to issue {@link #initStream(URI, int, int, int)} afterwards. */
+ public MovieSBSStereo() throws IllegalStateException {
+ mPlayerScaleOrig = false;
+ mPlayer = GLMediaPlayerFactory.createDefault();
+ mPlayer.attachObject(PLAYER, this);
+ System.out.println("pC.1a "+mPlayer);
+ }
+
+ public void initStream(final Uri streamLoc, final int vid, final int aid, final int textureCount) {
+ mPlayer.initStream(streamLoc, vid, aid, textureCount);
+ System.out.println("pC.1b "+mPlayer);
+ }
+
+ public GLMediaPlayer getGLMediaPlayer() { return mPlayer; }
+
+ public void setScaleOrig(final boolean v) {
+ mPlayerScaleOrig = v;
+ }
+
+ public void setStereoClientRenderer(final StereoClientRenderer scr) {
+ stereoClientRenderer = scr;
+ }
+ public StereoClientRenderer getStereoClientRenderer() { return stereoClientRenderer; }
+
+ public void resetGLState() {
+ resetGLState = true;
+ }
+
+ private void initShader(final GL2ES2 gl) {
+ // Create & Compile the shader objects
+ final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MovieSBSStereo.class,
+ "../shader", "../shader/bin", shaderBasename, true);
+ final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MovieSBSStereo.class,
+ "../shader", "../shader/bin", shaderBasename, true);
+
+ boolean preludeGLSLVersion = true;
+ if( GLES2.GL_TEXTURE_EXTERNAL_OES == mPlayer.getTextureTarget() ) {
+ if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) {
+ throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available");
+ }
+ if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) {
+ // Bug on Nexus 10, ES3 - Android 4.3, where
+ // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' !
+ // P0003: Extension 'GL_OES_EGL_image_external' not supported
+ preludeGLSLVersion = false;
+ }
+ }
+ rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true);
+
+ int rsFpPos = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0;
+ rsFpPos = rsFp.insertShaderSource(0, rsFpPos, mPlayer.getRequiredExtensionsShaderStub());
+ rsFp.addDefaultShaderPrecision(gl, rsFpPos);
+
+ final String texLookupFuncName = mPlayer.getTextureLookupFunctionName(myTextureLookupName);
+ rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName);
+
+ // Inject TextureSequence shader details
+ final StringBuilder sFpIns = new StringBuilder();
+ sFpIns.append("uniform ").append(mPlayer.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n");
+ sFpIns.append(mPlayer.getTextureLookupFragmentShaderImpl());
+ rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns);
+
+ // Create & Link the shader program
+ final ShaderProgram sp = new ShaderProgram();
+ sp.add(rsVp);
+ sp.add(rsFp);
+ if(!sp.link(gl, System.err)) {
+ throw new GLException("Couldn't link program: "+sp);
+ }
+
+ // Let's manage all our states using ShaderState.
+ st = new ShaderState();
+ st.attachShaderProgram(gl, sp, false);
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ if(null == mPlayer) {
+ throw new InternalError("mPlayer null");
+ }
+ if( GLMediaPlayer.State.Uninitialized == mPlayer.getState() ) {
+ throw new IllegalStateException("mPlayer in uninitialized state: "+mPlayer);
+ }
+ final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+ resetGLState = false;
+
+ zoom0 = -2.1f;
+ zoom1 = -5f;
+ zoom = 0f;
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ System.err.println(JoglVersion.getGLInfo(gl, null));
+ System.err.println("Alpha: "+alpha+", opaque "+drawable.getChosenGLCapabilities().isBackgroundOpaque()+
+ ", "+drawable.getClass().getName()+", "+drawable);
+
+ if(waitForKey) {
+ UITestCase.waitForKey("Init>");
+ }
+ final Texture tex;
+ try {
+ System.out.println("p0 "+mPlayer);
+ if(GLMediaPlayer.State.Initialized == mPlayer.getState() ) {
+ mPlayer.initGL(gl);
+ }
+ System.out.println("p1 "+mPlayer);
+ final TextureFrame frame = mPlayer.getLastTexture();
+ if( null != frame ) {
+ if( !hasVideo ) {
+ throw new InternalError("XXX: "+mPlayer);
+ }
+ tex = frame.getTexture();
+ if( null == tex ) {
+ throw new InternalError("XXX: "+mPlayer);
+ }
+ } else {
+ tex = null;
+ if( hasVideo ) {
+ throw new InternalError("XXX: "+mPlayer);
+ }
+ }
+ mPlayer.setTextureMinMagFilter( new int[] { GL.GL_NEAREST, GL.GL_NEAREST } );
+ } catch (final Exception glex) {
+ glex.printStackTrace();
+ if(null != mPlayer) {
+ mPlayer.destroy(gl);
+ mPlayer = null;
+ }
+ throw new GLException(glex);
+ }
+
+ if( hasVideo ) {
+ initShader(gl);
+
+ // Push the 1st uniform down the path
+ st.useProgram(gl, true);
+
+ final int[] viewPort = new int[] { 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()};
+ pmvMatrix = new PMVMatrix();
+ reshapePMV(viewPort[2], viewPort[3]);
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ if(!st.uniform(gl, pmvMatrixUniform)) {
+ throw new GLException("Error setting PMVMatrix in shader: "+st);
+ }
+ if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", mPlayer.getTextureUnit()))) {
+ throw new GLException("Error setting mgl_ActiveTexture in shader: "+st);
+ }
+
+ final float dWidth = drawable.getSurfaceWidth();
+ final float dHeight = drawable.getSurfaceHeight();
+ final float mWidth = mPlayer.getWidth();
+ final float mHeight = mPlayer.getHeight();
+ final float mAspect = mWidth/mHeight;
+ System.err.println("XXX0: mov aspect: "+mAspect);
+ float xs, ys;
+ if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) {
+ xs = mAspect * ( mWidth / dWidth ) ; ys = xs / mAspect ;
+ } else {
+ xs = mAspect; ys = 1f; // b>h
+ }
+ verts = new float[] { -1f*xs, -1f*ys, 0f, // LB
+ 1f*xs, 1f*ys, 0f // RT
+ };
+ {
+ System.err.println("XXX0: pixel LB: "+verts[0]+", "+verts[1]+", "+verts[2]);
+ System.err.println("XXX0: pixel RT: "+verts[3]+", "+verts[4]+", "+verts[5]);
+ final float[] winLB = new float[3];
+ final float[] winRT = new float[3];
+ pmvMatrix.gluProject(verts[0], verts[1], verts[2], viewPort, 0, winLB, 0);
+ pmvMatrix.gluProject(verts[3], verts[4], verts[5], viewPort, 0, winRT, 0);
+ System.err.println("XXX0: win LB: "+winLB[0]+", "+winLB[1]+", "+winLB[2]);
+ System.err.println("XXX0: win RT: "+winRT[0]+", "+winRT[1]+", "+winRT[2]);
+ }
+
+ interleavedVBOLeft = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
+ {
+ interleavedVBOLeft.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBOLeft.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ interleavedVBOLeft.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
+ }
+ interleavedVBORight = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
+ {
+ interleavedVBORight.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBORight.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ interleavedVBORight.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
+ }
+ updateInterleavedVBO(gl, interleavedVBOLeft, tex, 0);
+ updateInterleavedVBO(gl, interleavedVBORight, tex, 1);
+
+ st.ownAttribute(interleavedVBOLeft, true);
+ st.ownAttribute(interleavedVBORight, true);
+ gl.glClearColor(0.3f, 0.3f, 0.3f, 0.3f);
+
+ gl.glEnable(GL.GL_DEPTH_TEST);
+
+ st.useProgram(gl, false);
+
+ // Let's show the completed shader state ..
+ System.out.println("iVBOLeft : "+interleavedVBOLeft);
+ System.out.println("iVBORight: "+interleavedVBORight);
+ System.out.println(st);
+ }
+
+ mPlayer.play();
+ System.out.println("play.0 "+mPlayer);
+ startTime = System.currentTimeMillis();
+
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
+ window.addMouseListener(mouseAction);
+ window.addKeyListener(keyAction);
+ surfWidth = window.getSurfaceWidth();
+ surfHeight = window.getSurfaceHeight();
+ }
+ final int rmode = drawable.getChosenGLCapabilities().getSampleBuffers() ? 0 : Region.VBAA_RENDERING_BIT;
+ final boolean lowPerfDevice = gl.isGLES();
+ if( enableTextRendererGLEL ) {
+ textRendererGLEL = new InfoTextRendererGLELBase(rmode, lowPerfDevice);
+ textRendererGLEL.init(drawable);
+ } else {
+ textRendererGLEL = null;
+ }
+ }
+
+ protected void updateInterleavedVBO(final GL gl, final GLArrayDataServer iVBO, final Texture tex, final int eyeNum) {
+ final boolean wasEnabled = iVBO.enabled();
+ iVBO.seal(gl, false);
+ iVBO.rewind();
+ {
+ final FloatBuffer ib = (FloatBuffer)iVBO.getBuffer();
+ final TextureCoords tc = tex.getImageTexCoords();
+ final float texHalfWidth = tc.right()/2f;
+ System.err.println("XXX0: "+tc+", texHalfWidth "+texHalfWidth);
+ System.err.println("XXX0: tex aspect: "+tex.getAspectRatio());
+ System.err.println("XXX0: tex y-flip: "+tex.getMustFlipVertically());
+
+ // left-bottom
+ ib.put(verts[0]); ib.put(verts[1]); ib.put(verts[2]);
+ ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
+ if( 0 == eyeNum ) {
+ ib.put( tc.left() ); ib.put( tc.bottom() );
+ } else {
+ ib.put( tc.left() + texHalfWidth ); ib.put( tc.bottom() );
+ }
+
+ // right-bottom
+ ib.put(verts[3]); ib.put(verts[1]); ib.put(verts[2]);
+ ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
+ if( 0 == eyeNum ) {
+ ib.put( texHalfWidth ); ib.put( tc.bottom() );
+ } else {
+ ib.put( tc.right() ); ib.put( tc.bottom() );
+ }
+
+ // left-top
+ ib.put(verts[0]); ib.put(verts[4]); ib.put(verts[2]);
+ ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
+ if( 0 == eyeNum ) {
+ ib.put( tc.left() ); ib.put( tc.top() );
+ } else {
+ ib.put( tc.left() + texHalfWidth ); ib.put( tc.top() );
+ }
+
+ // right-top
+ ib.put(verts[3]); ib.put(verts[4]); ib.put(verts[2]);
+ ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
+ if( 0 == eyeNum ) {
+ ib.put( texHalfWidth ); ib.put( tc.top() );
+ } else {
+ ib.put( tc.right() ); ib.put( tc.top() );
+ }
+ }
+ iVBO.seal(gl, true);
+ if( !wasEnabled ) {
+ iVBO.enableBuffer(gl, false);
+ }
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ surfWidth = width;
+ surfHeight = height;
+
+ if(null == mPlayer) { return; }
+
+ if(null != st) {
+ reshapePMV(width, height);
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ }
+
+ System.out.println("pR "+mPlayer);
+ if( null != textRendererGLEL ) {
+ textRendererGLEL.reshape(drawable, 0, 0, width, height);
+ }
+ }
+
+ private final float zNear = 0.1f;
+ private final float zFar = 10000f;
+
+ private void reshapePMV(final int width, final int height) {
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, zNear, zFar);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glTranslatef(0, 0, zoom0);
+ }
+
+ private final float[] mat4Tmp1 = new float[16];
+ private final float[] mat4Tmp2 = new float[16];
+ private final float[] vec3Tmp1 = new float[3];
+ private final float[] vec3Tmp2 = new float[3];
+ private final float[] vec3Tmp3 = new float[3];
+
+ GLArrayDataServer interleavedVBOCurrent = null;
+
+ @Override
+ public void reshapeForEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height,
+ final EyeParameter eyeParam, final EyePose eyePose) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ interleavedVBOCurrent = 0 == eyeParam.number ? interleavedVBOLeft : interleavedVBORight;
+
+ surfWidth = drawable.getSurfaceWidth();
+ surfHeight = drawable.getSurfaceHeight();
+
+ if(null == mPlayer) { return; }
+ if(null == st) { return; }
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ final float[] mat4Projection = FloatUtil.makePerspective(mat4Tmp1, 0, true, eyeParam.fovhv, zNear, zFar);
+ pmvMatrix.glLoadMatrixf(mat4Projection, 0);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ final Quaternion rollPitchYaw = new Quaternion();
+ final float[] shiftedEyePos = rollPitchYaw.rotateVector(vec3Tmp1, 0, eyePose.position, 0);
+ VectorUtil.addVec3(shiftedEyePos, shiftedEyePos, eyeParam.positionOffset);
+
+ rollPitchYaw.mult(eyePose.orientation);
+ final float[] up = rollPitchYaw.rotateVector(vec3Tmp2, 0, VectorUtil.VEC3_UNIT_Y, 0);
+ final float[] forward = rollPitchYaw.rotateVector(vec3Tmp3, 0, VectorUtil.VEC3_UNIT_Z_NEG, 0);
+ final float[] center = VectorUtil.addVec3(forward, shiftedEyePos, forward);
+
+ final float[] mLookAt = FloatUtil.makeLookAt(mat4Tmp1, 0, shiftedEyePos, 0, center, 0, up, 0, mat4Tmp2);
+ final float[] mViewAdjust = FloatUtil.makeTranslation(mat4Tmp2, true, eyeParam.distNoseToPupilX, eyeParam.distMiddleToPupilY, eyeParam.eyeReliefZ);
+ final float[] mat4Modelview = FloatUtil.multMatrix(mViewAdjust, mLookAt);
+ pmvMatrix.glLoadMatrixf(mat4Modelview, 0);
+ pmvMatrix.glTranslatef(0, 0, zoom0);
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ if( null != textRendererGLEL ) {
+ textRendererGLEL.reshape(drawable, 0, 0, width, height);
+ }
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( null != textRendererGLEL ) {
+ textRendererGLEL.dispose(drawable);
+ textRendererGLEL = null;
+ }
+ disposeImpl(drawable, true);
+ }
+
+ private void disposeImpl(final GLAutoDrawable drawable, final boolean disposePlayer) {
+ if(null == mPlayer) { return; }
+
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
+ window.removeMouseListener(mouseAction);
+ window.removeKeyListener(keyAction);
+ }
+
+ System.out.println("pD.1 "+mPlayer+", disposePlayer "+disposePlayer);
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if( disposePlayer ) {
+ mPlayer.destroy(gl);
+ System.out.println("pD.X "+mPlayer);
+ mPlayer=null;
+ }
+ pmvMatrixUniform = null;
+ if(null != pmvMatrix) {
+ pmvMatrix=null;
+ }
+ if(null != st) {
+ st.destroy(gl);
+ st=null;
+ }
+ }
+
+ long lastPerfPos = 0;
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ display(drawable, 0);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable, final int flags) {
+ // TODO Auto-generated method stub
+ final boolean repeatedFrame = 0 != ( CustomGLEventListener.DISPLAY_REPEAT & flags );
+ final boolean dontClear = 0 != ( CustomGLEventListener.DISPLAY_DONTCLEAR & flags );
+ final GLArrayDataServer iVBO = null != interleavedVBOCurrent ? interleavedVBOCurrent : interleavedVBOLeft;
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if(null == mPlayer) { return; }
+
+ if( resetGLState ) {
+ resetGLState = false;
+ System.err.println("XXX resetGLState");
+ disposeImpl(drawable, false);
+ init(drawable);
+ reshape(drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ }
+
+ final long currentPos = System.currentTimeMillis();
+ if( currentPos - lastPerfPos > 2000 ) {
+ System.err.println( mPlayer.getPerfString() );
+ lastPerfPos = currentPos;
+ }
+
+ if( !dontClear ) {
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+
+ if(null == st) {
+ return;
+ }
+
+ st.useProgram(gl, true);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glPushMatrix();
+ pmvMatrix.glTranslatef(0, 0, zoom);
+ if( rotate > 0) {
+ final float ang = ((System.currentTimeMillis() - startTime) * 360.0f) / 8000.0f;
+ pmvMatrix.glRotatef(ang, 0, 0, 1);
+ } else {
+ rotate = 0;
+ }
+ st.uniform(gl, pmvMatrixUniform);
+ iVBO.enableBuffer(gl, true);
+ Texture tex = null;
+ if(null!=mPlayer) {
+ final TextureSequence.TextureFrame texFrame;
+ if( repeatedFrame ) {
+ texFrame=mPlayer.getLastTexture();
+ } else {
+ texFrame=mPlayer.getNextTexture(gl);
+ }
+ if(null != texFrame) {
+ tex = texFrame.getTexture();
+ gl.glActiveTexture(GL.GL_TEXTURE0+mPlayer.getTextureUnit());
+ tex.enable(gl);
+ tex.bind(gl);
+ }
+ }
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ if(null != tex) {
+ tex.disable(gl);
+ }
+ iVBO.enableBuffer(gl, false);
+ st.useProgram(gl, false);
+ pmvMatrix.glPopMatrix();
+
+ if( null != textRendererGLEL ) {
+ textRendererGLEL.display(drawable);
+ }
+ }
+
+ static class StereoGLMediaEventListener implements GLMediaEventListener {
+ void destroyWindow(final Window window) {
+ new Thread() {
+ public void run() {
+ window.destroy();
+ } }.start();
+ }
+
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) {
+ }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ System.err.println("MovieSimple AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieSimple State: "+mp);
+ final GLWindow window = (GLWindow) mp.getAttachedObject(WINDOW_KEY);
+ final MovieSBSStereo ms = (MovieSBSStereo)mp.getAttachedObject(PLAYER);
+ final StereoClientRenderer stereoClientRenderer = (StereoClientRenderer) mp.getAttachedObject(STEREO_RENDERER_KEY);
+
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) {
+ System.err.println("MovieSimple State: CHANGE_SIZE");
+ // window.disposeGLEventListener(ms, false /* remove */ );
+ ms.resetGLState();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ System.err.println("MovieSimple State: INIT");
+ // Use GLEventListener in all cases [A+V, V, A]
+ stereoClientRenderer.addGLEventListener(ms);
+ final GLAnimatorControl anim = window.getAnimator();
+ anim.setUpdateFPSFrames(60, null);
+ anim.resetFPSCounter();
+ ms.setStereoClientRenderer(stereoClientRenderer);
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
+ window.getAnimator().resetFPSCounter();
+ }
+
+ boolean destroy = false;
+ Throwable err = null;
+
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ err = ms.mPlayer.getStreamException();
+ if( null != err ) {
+ System.err.println("MovieSimple State: EOS + Exception");
+ destroy = true;
+ } else {
+ System.err.println("MovieSimple State: EOS");
+ new Thread() {
+ public void run() {
+ mp.setPlaySpeed(1f);
+ mp.seek(0);
+ mp.play();
+ }
+ }.start();
+ }
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_ERR & event_mask ) ) {
+ err = ms.mPlayer.getStreamException();
+ if( null != err ) {
+ System.err.println("MovieSimple State: ERR + Exception");
+ } else {
+ System.err.println("MovieSimple State: ERR");
+ }
+ destroy = true;
+ }
+ if( destroy ) {
+ if( null != err ) {
+ err.printStackTrace();
+ }
+ destroyWindow(window);
+ }
+ }
+ };
+ public final static StereoGLMediaEventListener stereoGLMediaEventListener = new StereoGLMediaEventListener();
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
index e17c9e88b..d963294b4 100755..100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -28,14 +28,14 @@
package com.jogamp.opengl.test.junit.jogl.demos.es2.av;
+import java.io.File;
import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
+import java.net.URISyntaxException;
import java.nio.FloatBuffer;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLES2;
@@ -45,20 +45,33 @@ import javax.media.opengl.GLProfile;
import javax.media.opengl.GLUniformData;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import com.jogamp.common.net.Uri;
+import com.jogamp.common.os.Platform;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.font.Font;
import com.jogamp.newt.Window;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseListener;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.av.GLMediaPlayer;
import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
@@ -66,9 +79,21 @@ import com.jogamp.opengl.util.glsl.ShaderState;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureCoords;
import com.jogamp.opengl.util.texture.TextureSequence;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+/**
+ * Simple planar movie player w/ orthogonal 1:1 projection.
+ */
+public class MovieSimple implements GLEventListener {
+ public static final int EFFECT_NORMAL = 0;
+ public static final int EFFECT_GRADIENT_BOTTOM2TOP = 1<<1;
+ public static final int EFFECT_TRANSPARENT = 1<<3;
-public class MovieSimple implements GLEventListener, GLMediaEventListener {
- private int winWidth, winHeight;
+ public static final String WINDOW_KEY = "window";
+ public static final String PLAYER = "player";
+
+ private static boolean waitForKey = false;
+ private int surfWidth, surfHeight;
private int prevMouseX; // , prevMouseY;
private int rotate = 0;
private boolean orthoProjection = true;
@@ -79,153 +104,345 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener {
private long startTime;
private int effects = EFFECT_NORMAL;
private float alpha = 1.0f;
+ private int swapInterval = 1;
+ private int swapIntervalSet = -1;
- public static final int EFFECT_NORMAL = 0;
- public static final int EFFECT_GRADIENT_BOTTOM2TOP = 1<<1;
- public static final int EFFECT_TRANSPARENT = 1<<3;
+ private GLMediaPlayer mPlayer;
+ private final boolean mPlayerShared;
+ private boolean mPlayerScaleOrig;
+ private float[] verts = null;
+ private GLArrayDataServer interleavedVBO;
+ private volatile boolean resetGLState = false;
- /** defaults to true */
- public void setOrthoProjection(boolean v) { orthoProjection=v; }
- public boolean getOrthoProjection() { return orthoProjection; }
-
- public boolean hasEffect(int e) { return 0 != ( effects & e ) ; }
- public void setEffects(int e) { effects = e; };
- public void setTransparency(float alpha) {
- this.effects |= EFFECT_TRANSPARENT;
- this.alpha = alpha;
- }
+ private ShaderState st;
+ private PMVMatrix pmvMatrix;
+ private GLUniformData pmvMatrixUniform;
+ private static final String shaderBasename = "texsequence_xxx";
+ private static final String myTextureLookupName = "myTexture2D";
+
+ /** Blender's Big Buck Bunny: 24f 416p H.264, AAC 48000 Hz, 2 ch, mpeg stream. */
+ public static final Uri defURI;
+ static {
+ Uri _defURI = null;
+ try {
+ // Blender's Big Buck Bunny Trailer: 24f 640p VP8, Vorbis 44100Hz mono, WebM/Matroska Stream.
+ // _defURI = new URI("http://video.webmfiles.org/big-buck-bunny_trailer.webm");
+ _defURI = Uri.cast("http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ } catch (final URISyntaxException e) {
+ e.printStackTrace();
+ }
+ defURI = _defURI;
+ }
+
+ final int[] textSampleCount = { 4 };
- GLMediaPlayer mPlayer;
- URLConnection stream = null;
- boolean mPlayerExternal;
- boolean mPlayerShared;
- boolean mPlayerScaleOrig;
- GLArrayDataServer interleavedVBO;
+ private final class InfoTextRendererGLELBase extends TextRendererGLELBase {
+ private final Font font = getFont(0, 0, 0);
+ private final float fontSize = 10f;
+ private final GLRegion regionFPS;
+
+ InfoTextRendererGLELBase(final int rmode, final boolean lowPerfDevice) {
+ // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+ super(rmode, textSampleCount);
+ this.setRendererCallbacks(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
+ if( lowPerfDevice ) {
+ regionFPS = null;
+ } else {
+ regionFPS = GLRegion.create(renderModes, null);
+ System.err.println("RegionFPS "+Region.getRenderModeString(renderModes)+", sampleCount "+textSampleCount[0]+", class "+regionFPS.getClass().getName());
+ }
+ staticRGBAColor[0] = 0.9f;
+ staticRGBAColor[1] = 0.9f;
+ staticRGBAColor[2] = 0.9f;
+ staticRGBAColor[3] = 1.0f;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ super.init(drawable);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( null != regionFPS ) {
+ regionFPS.destroy(drawable.getGL().getGL2ES2());
+ }
+ super.dispose(drawable);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GLAnimatorControl anim = drawable.getAnimator();
+ final float lfps = null != anim ? anim.getLastFPS() : 0f;
+ final float tfps = null != anim ? anim.getTotalFPS() : 0f;
+ final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+ final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f;
+
+ // Note: MODELVIEW is from [ 0 .. height ]
+
+ final int height = drawable.getSurfaceHeight();
+
+ final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight();
+
+ final String ptsPrec = null != regionFPS ? "3.1" : "3.0";
+ final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d",
+ pts, mPlayer.getDuration() / 1000f,
+ mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(),
+ aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet);
+ final String text2 = String.format("audio: id %d, kbps %d, codec %s",
+ mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec());
+ final String text3 = String.format("video: id %d, kbps %d, codec %s",
+ mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec());
+ final String text4 = mPlayer.getUri().path.decode();
+ if( displayOSD && null != renderer ) {
+ // We share ClearColor w/ MovieSimple's init !
+ final float pixelSize = font.getPixelSize(fontSize, dpiH);
+ if( null != regionFPS ) {
+ renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, regionFPS); // no-cache
+ } else {
+ renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, true);
+ }
+ renderString(drawable, font, pixelSize, text2, 1 /* col */, -4 /* row */, 0, height, -1, true);
+ renderString(drawable, font, pixelSize, text3, 1 /* col */, -3 /* row */, 0, height, -1, true);
+ renderString(drawable, font, pixelSize, text4, 1 /* col */, -2 /* row */, 0, height, -1, true);
+ }
+ } };
+ private InfoTextRendererGLELBase textRendererGLEL = null;
+ private boolean displayOSD = true;
private final MouseListener mouseAction = new MouseAdapter() {
- public void mousePressed(MouseEvent e) {
- if(e.getY()<=winHeight/2 && null!=mPlayer && 1 == e.getClickCount()) {
+ public void mousePressed(final MouseEvent e) {
+ if(e.getY()<=surfHeight/2 && null!=mPlayer && 1 == e.getClickCount()) {
if(GLMediaPlayer.State.Playing == mPlayer.getState()) {
- mPlayer.pause();
+ mPlayer.pause(false);
} else {
- mPlayer.start();
+ mPlayer.play();
}
}
}
- public void mouseReleased(MouseEvent e) {
- if(e.getY()<=winHeight/2) {
+ public void mouseReleased(final MouseEvent e) {
+ if(e.getY()<=surfHeight/2) {
rotate = -1;
zoom = zoom0;
System.err.println("zoom: "+zoom);
}
}
- public void mouseMoved(MouseEvent e) {
+ public void mouseMoved(final MouseEvent e) {
prevMouseX = e.getX();
// prevMouseY = e.getY();
}
- public void mouseDragged(MouseEvent e) {
- int x = e.getX();
- int y = e.getY();
-
- if(y>winHeight/2) {
- final float dp = (float)(x-prevMouseX)/(float)winWidth;
- mPlayer.seek(mPlayer.getCurrentPosition() + (int) (mPlayer.getDuration() * dp));
+ public void mouseDragged(final MouseEvent e) {
+ final int x = e.getX();
+ final int y = e.getY();
+
+ if(y>surfHeight/2) {
+ final float dp = (float)(x-prevMouseX)/(float)surfWidth;
+ final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
+ mPlayer.seek(pts0 + (int) (mPlayer.getDuration() * dp));
} else {
- mPlayer.start();
- rotate = 1;
+ mPlayer.play();
+ rotate = 1;
zoom = zoom1;
}
-
+
prevMouseX = x;
// prevMouseY = y;
}
- public void mouseWheelMoved(MouseEvent e) {
- zoom += e.getWheelRotation()/10f;
- System.err.println("zoom: "+zoom);
+ public void mouseWheelMoved(final MouseEvent e) {
+ if( !e.isShiftDown() ) {
+ zoom += e.getRotation()[1]/10f; // vertical: wheel
+ System.err.println("zoom: "+zoom);
+ }
+ } };
+
+ private final KeyListener keyAction = new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ System.err.println("MC "+e);
+ final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
+ int pts1 = 0;
+ switch(e.getKeySymbol()) {
+ case KeyEvent.VK_V: {
+ switch(swapIntervalSet) {
+ case 0: swapInterval = 1; break;
+ default: swapInterval = 0; break;
+ }
+ break;
+ }
+ case KeyEvent.VK_O: displayOSD = !displayOSD; break;
+ case KeyEvent.VK_RIGHT: pts1 = pts0 + 1000; break;
+ case KeyEvent.VK_UP: pts1 = pts0 + 10000; break;
+ case KeyEvent.VK_PAGE_UP: pts1 = pts0 + 30000; break;
+ case KeyEvent.VK_LEFT: pts1 = pts0 - 1000; break;
+ case KeyEvent.VK_DOWN: pts1 = pts0 - 10000; break;
+ case KeyEvent.VK_PAGE_DOWN: pts1 = pts0 - 30000; break;
+ case KeyEvent.VK_ESCAPE:
+ case KeyEvent.VK_HOME:
+ case KeyEvent.VK_BACK_SPACE: {
+ mPlayer.seek(0);
+ break;
+ }
+ case KeyEvent.VK_SPACE: {
+ if(GLMediaPlayer.State.Paused == mPlayer.getState()) {
+ mPlayer.play();
+ } else {
+ mPlayer.pause(false);
+ }
+ break;
+ }
+ case KeyEvent.VK_MULTIPLY:
+ mPlayer.setPlaySpeed(1.0f);
+ break;
+ case KeyEvent.VK_SUBTRACT: {
+ float playSpeed = mPlayer.getPlaySpeed();
+ if( e.isShiftDown() ) {
+ playSpeed /= 2.0f;
+ } else {
+ playSpeed -= 0.1f;
+ }
+ mPlayer.setPlaySpeed(playSpeed);
+ } break;
+ case KeyEvent.VK_ADD: {
+ float playSpeed = mPlayer.getPlaySpeed();
+ if( e.isShiftDown() ) {
+ playSpeed *= 2.0f;
+ } else {
+ playSpeed += 0.1f;
+ }
+ mPlayer.setPlaySpeed(playSpeed);
+ } break;
+ case KeyEvent.VK_M: {
+ float audioVolume = mPlayer.getAudioVolume();
+ if( audioVolume > 0.5f ) {
+ audioVolume = 0f;
+ } else {
+ audioVolume = 1f;
+ }
+ mPlayer.setAudioVolume(audioVolume);
+ } break;
+ }
+
+ if( 0 != pts1 ) {
+ mPlayer.seek(pts1);
+ }
+ } };
+
+ /**
+ * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values
+ * and polls until the {@link GLMediaPlayer} is {@link GLMediaPlayer.State#Initialized}.
+ * If {@link GLMediaEventListener#EVENT_CHANGE_EOS} is reached, the stream is started over again.
+ * <p>
+ * This default constructor is merely useful for some <i>drop-in</i> test, e.g. using an applet.
+ * </p>
+ */
+ public MovieSimple() {
+ this(null);
+
+ mPlayer.addEventListener(new GLMediaEventListener() {
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) { }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ System.err.println("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieCube State: "+mp);
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) {
+ resetGLState();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ new Thread() {
+ public void run() {
+ // loop for-ever ..
+ mPlayer.seek(0);
+ mPlayer.play();
+ } }.start();
+ }
+ }
+ });
+ initStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 3 /* textureCount */);
+ StreamException se = null;
+ while( null == se && GLMediaPlayer.State.Initialized != mPlayer.getState() ) {
+ try {
+ Thread.sleep(16);
+ } catch (final InterruptedException e) { }
+ se = mPlayer.getStreamException();
+ }
+ if( null != se ) {
+ se.printStackTrace();
+ throw new RuntimeException(se);
}
- };
-
- public MovieSimple(URLConnection stream) throws IOException {
- mPlayerScaleOrig = false;
- mPlayerShared = false;
- mPlayerExternal = false;
- mPlayer = GLMediaPlayerFactory.create();
- mPlayer.addEventListener(this);
- this.stream = stream;
- System.out.println("pC.1 "+mPlayer);
}
- public MovieSimple(GLMediaPlayer sharedMediaPlayer) throws IllegalStateException {
- mPlayerScaleOrig = false;
- mPlayerShared = true;
- mPlayerExternal = true;
+ /** Custom constructor, user needs to issue {@link #initStream(URI, int, int, int)} afterwards. */
+ public MovieSimple(final GLMediaPlayer sharedMediaPlayer) throws IllegalStateException {
mPlayer = sharedMediaPlayer;
- mPlayer.addEventListener(this);
- this.stream = null;
- System.out.println("pC.2 shared "+mPlayerShared+", "+mPlayer);
+ mPlayerScaleOrig = false;
+ mPlayerShared = null != mPlayer;
+ if( !mPlayerShared ) {
+ mPlayer = GLMediaPlayerFactory.createDefault();
+ mPlayer.attachObject(PLAYER, this);
+ }
+ System.out.println("pC.1a shared "+mPlayerShared+", "+mPlayer);
+ }
+
+ public void initStream(final Uri streamLoc, final int vid, final int aid, final int textureCount) {
+ mPlayer.initStream(streamLoc, vid, aid, textureCount);
+ System.out.println("pC.1b "+mPlayer);
}
-
+
+ public void setSwapInterval(final int v) { this.swapInterval = v; }
+
public GLMediaPlayer getGLMediaPlayer() { return mPlayer; }
-
- public void setScaleOrig(boolean v) {
+
+ public void setScaleOrig(final boolean v) {
mPlayerScaleOrig = v;
}
-
- @Override
- public void attributesChanges(GLMediaPlayer mp, int event_mask, long when) {
- System.out.println("attributesChanges: "+mp+", 0x"+Integer.toHexString(event_mask)+", when "+when);
- }
- @Override
- public void newFrameAvailable(GLMediaPlayer mp, long when) {
- // System.out.println("newFrameAvailable: "+mp+", when "+when);
- }
+ /** defaults to true */
+ public void setOrthoProjection(final boolean v) { orthoProjection=v; }
+ public boolean getOrthoProjection() { return orthoProjection; }
- public void start() {
- if(null!=mPlayer) {
- mPlayer.start();
- System.out.println("pStart "+mPlayer);
- }
+ public boolean hasEffect(final int e) { return 0 != ( effects & e ) ; }
+ public void setEffects(final int e) { effects = e; };
+ public void setTransparency(final float alpha) {
+ this.effects |= EFFECT_TRANSPARENT;
+ this.alpha = alpha;
}
- public void stop() {
- if(null!=mPlayer) {
- mPlayer.stop();
- System.out.println("pStop "+mPlayer);
- }
+ public void resetGLState() {
+ resetGLState = true;
}
-
- ShaderState st;
- PMVMatrix pmvMatrix;
- GLUniformData pmvMatrixUniform;
- static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
- static final String gl2_prelude = "#version 110\n";
- static final String shaderBasename = "texsequence_xxx";
- static final String myTextureLookupName = "myTexture2D";
-
- private void initShader(GL2ES2 gl) {
+
+ private void initShader(final GL2ES2 gl) {
// Create & Compile the shader objects
- ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MovieSimple.class,
+ final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MovieSimple.class,
"../shader", "../shader/bin", shaderBasename, true);
- ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MovieSimple.class,
+ final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MovieSimple.class,
"../shader", "../shader/bin", shaderBasename, true);
- // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
- int rsFpPos;
- if(gl.isGLES2()) {
- rsVp.insertShaderSource(0, 0, es2_prelude[0]);
- rsFpPos = rsFp.insertShaderSource(0, 0, es2_prelude[0]);
- } else {
- rsVp.insertShaderSource(0, 0, gl2_prelude);
- rsFpPos = rsFp.insertShaderSource(0, 0, gl2_prelude);
+ boolean preludeGLSLVersion = true;
+ if( GLES2.GL_TEXTURE_EXTERNAL_OES == mPlayer.getTextureTarget() ) {
+ if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) {
+ throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available");
+ }
+ if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) {
+ // Bug on Nexus 10, ES3 - Android 4.3, where
+ // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' !
+ // P0003: Extension 'GL_OES_EGL_image_external' not supported
+ preludeGLSLVersion = false;
+ }
}
+ rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true);
+
+ int rsFpPos = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0;
rsFpPos = rsFp.insertShaderSource(0, rsFpPos, mPlayer.getRequiredExtensionsShaderStub());
- if(gl.isGLES2()) {
- rsFpPos = rsFp.insertShaderSource(0, rsFpPos, es2_prelude[1]);
- }
- final String texLookupFuncName = mPlayer.getTextureLookupFunctionName(myTextureLookupName);
+ rsFp.addDefaultShaderPrecision(gl, rsFpPos);
+
+ final String texLookupFuncName = mPlayer.getTextureLookupFunctionName(myTextureLookupName);
rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName);
-
+
// Inject TextureSequence shader details
final StringBuilder sFpIns = new StringBuilder();
sFpIns.append("uniform ").append(mPlayer.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n");
@@ -233,7 +450,7 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener {
rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns);
// Create & Link the shader program
- ShaderProgram sp = new ShaderProgram();
+ final ShaderProgram sp = new ShaderProgram();
sp.add(rsVp);
sp.add(rsFp);
if(!sp.link(gl, System.err)) {
@@ -245,105 +462,166 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener {
st.attachShaderProgram(gl, sp, false);
}
- public void init(GLAutoDrawable drawable) {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ if(null == mPlayer) {
+ throw new InternalError("mPlayer null");
+ }
+ if( GLMediaPlayer.State.Uninitialized == mPlayer.getState() ) {
+ throw new IllegalStateException("mPlayer in uninitialized state: "+mPlayer);
+ }
+ final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+ resetGLState = false;
+
zoom0 = orthoProjection ? 0f : -2.5f;
zoom1 = orthoProjection ? 0f : -5f;
- zoom = zoom0;
+ zoom = zoom0;
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
System.err.println(JoglVersion.getGLInfo(gl, null));
System.err.println("Alpha: "+alpha+", opaque "+drawable.getChosenGLCapabilities().isBackgroundOpaque()+
", "+drawable.getClass().getName()+", "+drawable);
-
+
+ if(waitForKey) {
+ UITestCase.waitForKey("Init>");
+ }
final Texture tex;
- boolean useExternalTexture = false;
try {
System.out.println("p0 "+mPlayer+", shared "+mPlayerShared);
- if(!mPlayerShared) {
- mPlayer.initGLStream(gl, stream);
+ if(!mPlayerShared && GLMediaPlayer.State.Initialized == mPlayer.getState() ) {
+ mPlayer.initGL(gl);
}
- tex = mPlayer.getLastTexture().getTexture();
System.out.println("p1 "+mPlayer+", shared "+mPlayerShared);
- useExternalTexture = GLES2.GL_TEXTURE_EXTERNAL_OES == tex.getTarget();
- if(useExternalTexture && !gl.isExtensionAvailable("GL_OES_EGL_image_external")) {
- throw new GLException("GL_OES_EGL_image_external requested but not available");
+ final TextureFrame frame = mPlayer.getLastTexture();
+ if( null != frame ) {
+ if( !hasVideo ) {
+ throw new InternalError("XXX: "+mPlayer);
+ }
+ tex = frame.getTexture();
+ if( null == tex ) {
+ throw new InternalError("XXX: "+mPlayer);
+ }
+ } else {
+ tex = null;
+ if( hasVideo ) {
+ throw new InternalError("XXX: "+mPlayer);
+ }
}
if(!mPlayerShared) {
mPlayer.setTextureMinMagFilter( new int[] { GL.GL_NEAREST, GL.GL_LINEAR } );
}
- } catch (Exception glex) {
+ } catch (final Exception glex) {
+ glex.printStackTrace();
if(!mPlayerShared && null != mPlayer) {
mPlayer.destroy(gl);
mPlayer = null;
}
throw new GLException(glex);
}
-
- initShader(gl);
- // Push the 1st uniform down the path
- st.useProgram(gl, true);
+ if( hasVideo ) {
+ initShader(gl);
- int[] viewPort = new int[] { 0, 0, drawable.getWidth(), drawable.getHeight()};
- pmvMatrix = new PMVMatrix();
- reshapePMV(viewPort[2], viewPort[3]);
- pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
- if(!st.uniform(gl, pmvMatrixUniform)) {
- throw new GLException("Error setting PMVMatrix in shader: "+st);
- }
- if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", mPlayer.getTextureUnit()))) {
- throw new GLException("Error setting mgl_ActiveTexture in shader: "+st);
- }
-
- float dWidth = drawable.getWidth();
- float dHeight = drawable.getHeight();
- float mWidth = mPlayer.getWidth();
- float mHeight = mPlayer.getHeight();
- float mAspect = mWidth/mHeight;
- System.err.println("XXX0: mov aspect: "+mAspect);
- float[] verts;
- float xs, ys;
- if(orthoProjection) {
- if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) {
- xs = mWidth/2f; ys = xs / mAspect;
- } else {
- xs = dWidth/2f; ys = xs / mAspect; // w>h
+ // Push the 1st uniform down the path
+ st.useProgram(gl, true);
+
+ final int[] viewPort = new int[] { 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()};
+ pmvMatrix = new PMVMatrix();
+ reshapePMV(viewPort[2], viewPort[3]);
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ if(!st.uniform(gl, pmvMatrixUniform)) {
+ throw new GLException("Error setting PMVMatrix in shader: "+st);
}
- } else {
- if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) {
- xs = mAspect * ( mWidth / dWidth ) ; ys = xs / mAspect ;
+ if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", mPlayer.getTextureUnit()))) {
+ throw new GLException("Error setting mgl_ActiveTexture in shader: "+st);
+ }
+
+ final float dWidth = drawable.getSurfaceWidth();
+ final float dHeight = drawable.getSurfaceHeight();
+ final float mWidth = mPlayer.getWidth();
+ final float mHeight = mPlayer.getHeight();
+ final float mAspect = mWidth/mHeight;
+ System.err.println("XXX0: mov aspect: "+mAspect);
+ float xs, ys;
+ if(orthoProjection) {
+ if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) {
+ xs = mWidth/2f; ys = xs / mAspect;
+ } else {
+ xs = dWidth/2f; ys = xs / mAspect; // w>h
+ }
} else {
- xs = mAspect; ys = 1f; // b>h
+ if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) {
+ xs = mAspect * ( mWidth / dWidth ) ; ys = xs / mAspect ;
+ } else {
+ xs = mAspect; ys = 1f; // b>h
+ }
+ }
+ verts = new float[] { -1f*xs, -1f*ys, 0f, // LB
+ 1f*xs, 1f*ys, 0f // RT
+ };
+ {
+ System.err.println("XXX0: pixel LB: "+verts[0]+", "+verts[1]+", "+verts[2]);
+ System.err.println("XXX0: pixel RT: "+verts[3]+", "+verts[4]+", "+verts[5]);
+ final float[] winLB = new float[3];
+ final float[] winRT = new float[3];
+ pmvMatrix.gluProject(verts[0], verts[1], verts[2], viewPort, 0, winLB, 0);
+ pmvMatrix.gluProject(verts[3], verts[4], verts[5], viewPort, 0, winRT, 0);
+ System.err.println("XXX0: win LB: "+winLB[0]+", "+winLB[1]+", "+winLB[2]);
+ System.err.println("XXX0: win RT: "+winRT[0]+", "+winRT[1]+", "+winRT[2]);
+ }
+
+ interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
+ {
+ interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
}
+ updateInterleavedVBO(gl, tex);
+
+ st.ownAttribute(interleavedVBO, true);
+ gl.glClearColor(0.3f, 0.3f, 0.3f, 0.3f);
+
+ gl.glEnable(GL.GL_DEPTH_TEST);
+
+ st.useProgram(gl, false);
+
+ // Let's show the completed shader state ..
+ System.out.println("iVBO: "+interleavedVBO);
+ System.out.println(st);
}
- verts = new float[] { -1f*xs, -1f*ys, 0f, // LB
- 1f*xs, 1f*ys, 0f // RT
- };
- {
- System.err.println("XXX0: pixel LB: "+verts[0]+", "+verts[1]+", "+verts[2]);
- System.err.println("XXX0: pixel RT: "+verts[3]+", "+verts[4]+", "+verts[5]);
- float[] winLB = new float[3];
- float[] winRT = new float[3];
- pmvMatrix.gluProject(verts[0], verts[1], verts[2], viewPort, 0, winLB, 0);
- pmvMatrix.gluProject(verts[3], verts[4], verts[5], viewPort, 0, winRT, 0);
- System.err.println("XXX0: win LB: "+winLB[0]+", "+winLB[1]+", "+winLB[2]);
- System.err.println("XXX0: win RT: "+winRT[0]+", "+winRT[1]+", "+winRT[2]);
+
+ if(!mPlayerShared) {
+ mPlayer.play();
+ System.out.println("play.0 "+mPlayer);
}
- final float ss = 1f, ts = 1f; // scale tex-coord
+ startTime = System.currentTimeMillis();
+
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
+ window.addMouseListener(mouseAction);
+ window.addKeyListener(keyAction);
+ surfWidth = window.getSurfaceWidth();
+ surfHeight = window.getSurfaceHeight();
+ }
+ final int rmode = drawable.getChosenGLCapabilities().getSampleBuffers() ? 0 : Region.VBAA_RENDERING_BIT;
+ final boolean lowPerfDevice = gl.isGLES();
+ textRendererGLEL = new InfoTextRendererGLELBase(rmode, lowPerfDevice);
+ drawable.addGLEventListener(textRendererGLEL);
+ }
- interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
- {
- interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
- interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
- interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
-
+ protected void updateInterleavedVBO(final GL gl, final Texture tex) {
+ final float ss = 1f, ts = 1f; // scale tex-coord
+ final boolean wasEnabled = interleavedVBO.enabled();
+ interleavedVBO.seal(gl, false);
+ interleavedVBO.rewind();
+ {
final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
- final TextureCoords tc = tex.getImageTexCoords();
- final float aspect = tex.getAspectRatio();
- System.err.println("XXX0: tex aspect: "+aspect);
+ final TextureCoords tc = tex.getImageTexCoords();
+ System.err.println("XXX0: "+tc);
+ System.err.println("XXX0: tex aspect: "+tex.getAspectRatio());
System.err.println("XXX0: tex y-flip: "+tex.getMustFlipVertically());
- System.err.println("XXX0: "+tex.getImageTexCoords());
-
+
// left-bottom
ib.put(verts[0]); ib.put(verts[1]); ib.put(verts[2]);
if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) {
@@ -352,11 +630,11 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener {
ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
}
ib.put( tc.left() *ss); ib.put( tc.bottom() *ts);
-
+
// right-bottom
ib.put(verts[3]); ib.put(verts[1]); ib.put(verts[2]);
if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) {
- ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha);
+ ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha);
} else {
ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
}
@@ -364,134 +642,148 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener {
// left-top
ib.put(verts[0]); ib.put(verts[4]); ib.put(verts[2]);
- if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) {
- ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
- } else {
- ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
- }
+ ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
ib.put( tc.left() *ss); ib.put( tc.top() *ts);
-
+
// right-top
ib.put(verts[3]); ib.put(verts[4]); ib.put(verts[2]);
- if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) {
- ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
- } else {
- ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
- }
- ib.put( tc.right() *ss); ib.put( tc.top() *ts);
+ ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
+ ib.put( tc.right() *ss); ib.put( tc.top() *ts);
}
interleavedVBO.seal(gl, true);
- interleavedVBO.enableBuffer(gl, false);
- st.ownAttribute(interleavedVBO, true);
- gl.glClearColor(0.3f, 0.3f, 0.3f, 0.3f);
-
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
-
- st.useProgram(gl, false);
-
- // Let's show the completed shader state ..
- System.out.println("iVBO: "+interleavedVBO);
- System.out.println(st);
-
- if(null!=mPlayer) {
- start();
- System.out.println("p2 "+mPlayer);
- }
-
- startTime = System.currentTimeMillis();
-
- final Object upstreamWidget = drawable.getUpstreamWidget();
- if (upstreamWidget instanceof Window) {
- final Window window = (Window) upstreamWidget;
- window.addMouseListener(mouseAction);
- winWidth = window.getWidth();
- winHeight = window.getHeight();
+ if( !wasEnabled ) {
+ interleavedVBO.enableBuffer(gl, false);
}
}
-
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
if(null == mPlayer) { return; }
- winWidth = width;
- winHeight = height;
-
+ surfWidth = width;
+ surfHeight = height;
+
if(null != st) {
reshapePMV(width, height);
- GL2ES2 gl = drawable.getGL().getGL2ES2();
st.useProgram(gl, true);
st.uniform(gl, pmvMatrixUniform);
st.useProgram(gl, false);
}
-
+
System.out.println("pR "+mPlayer);
}
-
- private void reshapePMV(int width, int height) {
+
+ private final float zNear = 1f;
+ private final float zFar = 10f;
+
+ private void reshapePMV(final int width, final int height) {
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
if(orthoProjection) {
- final float fw = (float) width / 2f;
- final float fh = (float) height/ 2f;
+ final float fw = width / 2f;
+ final float fh = height/ 2f;
pmvMatrix.glOrthof(-fw, fw, -fh, fh, -1.0f, 1.0f);
nearPlaneNormalized = 0f;
} else {
- pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, 1f, 10.0f);
+ pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, zNear, zFar);
nearPlaneNormalized = 1f/(10f-1f);
}
System.err.println("XXX0: Perspective nearPlaneNormalized: "+nearPlaneNormalized);
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
- pmvMatrix.glTranslatef(0, 0, zoom0);
+ pmvMatrix.glTranslatef(0, 0, zoom0);
}
- public void dispose(GLAutoDrawable drawable) {
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ drawable.disposeGLEventListener(textRendererGLEL, true);
+ textRendererGLEL = null;
+ disposeImpl(drawable, true);
+ }
+
+ private void disposeImpl(final GLAutoDrawable drawable, final boolean disposePlayer) {
if(null == mPlayer) { return; }
-
- stop();
- System.out.println("pD.1 "+mPlayer);
-
- GL2ES2 gl = drawable.getGL().getGL2ES2();
-
- mPlayer.removeEventListener(this);
- if(!mPlayerExternal) {
- mPlayer.destroy(gl);
- }
- System.out.println("pD.X "+mPlayer);
- mPlayer=null;
+
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
+ window.removeMouseListener(mouseAction);
+ window.removeKeyListener(keyAction);
+ }
+
+ System.out.println("pD.1 "+mPlayer+", disposePlayer "+disposePlayer);
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if( disposePlayer ) {
+ if(!mPlayerShared) {
+ mPlayer.destroy(gl);
+ }
+ System.out.println("pD.X "+mPlayer);
+ mPlayer=null;
+ }
pmvMatrixUniform = null;
- pmvMatrix.destroy();
- pmvMatrix=null;
- st.destroy(gl);
- st=null;
+ if(null != pmvMatrix) {
+ pmvMatrix=null;
+ }
+ if(null != st) {
+ st.destroy(gl);
+ st=null;
+ }
}
- public void display(GLAutoDrawable drawable) {
+ long lastPerfPos = 0;
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+ drawable.getAnimator().resetFPSCounter();
+ swapIntervalSet = swapInterval;
+ swapInterval = -1;
+ }
if(null == mPlayer) { return; }
-
- GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ if( resetGLState ) {
+ resetGLState = false;
+ System.err.println("XXX resetGLState");
+ disposeImpl(drawable, false);
+ init(drawable);
+ reshape(drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ }
+
+ final long currentPos = System.currentTimeMillis();
+ if( currentPos - lastPerfPos > 2000 ) {
+ System.err.println( mPlayer.getPerfString() );
+ lastPerfPos = currentPos;
+ }
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ if(null == st) {
+ return;
+ }
+
st.useProgram(gl, true);
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
pmvMatrix.glTranslatef(0, 0, zoom);
if(rotate > 0) {
- final float ang = ((float) (System.currentTimeMillis() - startTime) * 360.0f) / 8000.0f;
+ final float ang = ((System.currentTimeMillis() - startTime) * 360.0f) / 8000.0f;
pmvMatrix.glRotatef(ang, 0, 0, 1);
} else {
rotate = 0;
}
st.uniform(gl, pmvMatrixUniform);
interleavedVBO.enableBuffer(gl, true);
- Texture tex = null;
+ Texture tex = null;
if(null!=mPlayer) {
final TextureSequence.TextureFrame texFrame;
- if(mPlayerShared) {
+ if( mPlayerShared ) {
texFrame=mPlayer.getLastTexture();
} else {
- texFrame=mPlayer.getNextTexture(gl, true);
+ texFrame=mPlayer.getNextTexture(gl);
}
if(null != texFrame) {
tex = texFrame.getTexture();
@@ -508,53 +800,267 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener {
st.useProgram(gl, false);
}
- public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
- }
+ static class MyGLMediaEventListener implements GLMediaEventListener {
+ void destroyWindow(final Window window) {
+ new Thread() {
+ public void run() {
+ window.destroy();
+ } }.start();
+ }
+
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) {
+ }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ System.err.println("MovieSimple AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieSimple State: "+mp);
+ final GLWindow window = (GLWindow) mp.getAttachedObject(WINDOW_KEY);
+ final MovieSimple ms = (MovieSimple)mp.getAttachedObject(PLAYER);
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) {
+ System.err.println("MovieSimple State: CHANGE_SIZE");
+ if( origSize ) {
+ window.setSurfaceSize(mp.getWidth(), mp.getHeight());
+ }
+ // window.disposeGLEventListener(ms, false /* remove */ );
+ ms.resetGLState();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ System.err.println("MovieSimple State: INIT");
+ // Use GLEventListener in all cases [A+V, V, A]
+ window.addGLEventListener(ms);
+ final GLAnimatorControl anim = window.getAnimator();
+ anim.setUpdateFPSFrames(60, null);
+ anim.resetFPSCounter();
+ /**
+ * Kick off player w/o GLEventListener, i.e. for audio only.
+ *
+ new Thread() {
+ public void run() {
+ try {
+ mp.initGL(null);
+ if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK
+ mp.play();
+ }
+ System.out.println("play.1 "+mp);
+ } catch (Exception e) {
+ e.printStackTrace();
+ destroyWindow();
+ return;
+ }
+ }
+ }.start();
+ */
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
+ window.getAnimator().resetFPSCounter();
+ }
+
+ boolean destroy = false;
+ Throwable err = null;
+
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ err = ms.mPlayer.getStreamException();
+ if( null != err ) {
+ System.err.println("MovieSimple State: EOS + Exception");
+ destroy = true;
+ } else {
+ System.err.println("MovieSimple State: EOS");
+ if( loopEOS ) {
+ new Thread() {
+ public void run() {
+ mp.setPlaySpeed(1f);
+ mp.seek(0);
+ mp.play();
+ }
+ }.start();
+ } else {
+ destroy = true;
+ }
+ }
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_ERR & event_mask ) ) {
+ err = ms.mPlayer.getStreamException();
+ if( null != err ) {
+ System.err.println("MovieSimple State: ERR + Exception");
+ } else {
+ System.err.println("MovieSimple State: ERR");
+ }
+ destroy = true;
+ }
+ if( destroy ) {
+ if( null != err ) {
+ err.printStackTrace();
+ }
+ destroyWindow(window);
+ }
+ }
+ };
+ public final static MyGLMediaEventListener myGLMediaEventListener = new MyGLMediaEventListener();
+
+ static boolean loopEOS = false;
+ static boolean origSize;
- public static void main(String[] args) throws IOException, MalformedURLException {
- int width = 640;
+ public static void main(final String[] args) throws IOException, URISyntaxException {
+ int swapInterval = 1;
+ int width = 800;
int height = 600;
+ int textureCount = 3; // default - threaded
boolean ortho = true;
boolean zoom = false;
-
- String url_s="http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4";
- for(int i=0; i<args.length; i++) {
- if(args[i].equals("-width")) {
- i++;
- width = MiscUtils.atoi(args[i], width);
- } else if(args[i].equals("-height")) {
- i++;
- height = MiscUtils.atoi(args[i], height);
- } else if(args[i].equals("-projection")) {
- ortho=false;
- } else if(args[i].equals("-zoom")) {
- zoom=true;
- } else if(args[i].equals("-url")) {
- i++;
- url_s = args[i];
- }
- }
- final MovieSimple ms = new MovieSimple(new URL(url_s).openConnection());
- ms.setScaleOrig(!zoom);
- ms.setOrthoProjection(ortho);
-
- try {
- GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
- GLWindow window = GLWindow.create(caps);
- window.addGLEventListener(ms);
+ boolean forceES2 = false;
+ boolean forceES3 = false;
+ boolean forceGL3 = false;
+ boolean forceGLDef = false;
+ int vid = GLMediaPlayer.STREAM_ID_AUTO;
+ int aid = GLMediaPlayer.STREAM_ID_AUTO;
- window.setSize(width, height);
- window.setVisible(true);
- final Animator anim = new Animator(window);
+ final int windowCount;
+ {
+ int _windowCount = 1;
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-windows")) {
+ i++;
+ _windowCount = MiscUtils.atoi(args[i], _windowCount);
+ }
+ }
+ windowCount = _windowCount;
+ }
+ final String[] urls_s = new String[windowCount];
+ String file_s1=null, file_s2=null;
+ {
+ boolean _origSize = false;
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-vid")) {
+ i++;
+ vid = MiscUtils.atoi(args[i], vid);
+ } else if(args[i].equals("-aid")) {
+ i++;
+ aid = MiscUtils.atoi(args[i], aid);
+ } else if(args[i].equals("-width")) {
+ i++;
+ width = MiscUtils.atoi(args[i], width);
+ } else if(args[i].equals("-height")) {
+ i++;
+ height = MiscUtils.atoi(args[i], height);
+ } else if(args[i].equals("-osize")) {
+ _origSize = true;
+ } else if(args[i].equals("-textureCount")) {
+ i++;
+ textureCount = MiscUtils.atoi(args[i], textureCount);
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-es3")) {
+ forceES3 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-gldef")) {
+ forceGLDef = true;
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-projection")) {
+ ortho=false;
+ } else if(args[i].equals("-zoom")) {
+ zoom=true;
+ } else if(args[i].equals("-loop")) {
+ loopEOS=true;
+ } else if(args[i].equals("-urlN")) {
+ i++;
+ final int n = MiscUtils.atoi(args[i], 0);
+ i++;
+ urls_s[n] = args[i];
+ } else if(args[i].equals("-url")) {
+ i++;
+ urls_s[0] = args[i];
+ } else if(args[i].equals("-file1")) {
+ i++;
+ file_s1 = args[i];
+ } else if(args[i].equals("-file2")) {
+ i++;
+ file_s2 = args[i];
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ origSize = _origSize;
+ }
+ final Uri streamLoc0;
+ if( null != urls_s[0] ) {
+ streamLoc0 = Uri.cast( urls_s[0] );
+ } else if( null != file_s1 ) {
+ final File movieFile = new File(file_s1);
+ streamLoc0 = Uri.valueOf(movieFile);
+ } else if( null != file_s2 ) {
+ streamLoc0 = Uri.valueOf(new File(file_s2));
+ } else {
+ streamLoc0 = defURI;
+ }
+ System.err.println("url_s "+urls_s[0]);
+ System.err.println("file_s 1: "+file_s1+", 2: "+file_s2);
+ System.err.println("stream0 "+streamLoc0);
+ System.err.println("vid "+vid+", aid "+aid);
+ System.err.println("textureCount "+textureCount);
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceES3 "+forceES3);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("forceGLDef "+forceGLDef);
+ System.err.println("swapInterval "+swapInterval);
+
+ final GLProfile glp;
+ if(forceGLDef) {
+ glp = GLProfile.getDefault();
+ } else if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES3) {
+ glp = GLProfile.get(GLProfile.GLES3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ System.err.println("GLProfile: "+glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ // caps.setAlphaBits(4); // NOTE_ALPHA_BLENDING: We go w/o alpha and blending!
+
+ final MovieSimple[] mss = new MovieSimple[windowCount];
+ final GLWindow[] windows = new GLWindow[windowCount];
+ for(int i=0; i<windowCount; i++) {
+ final Animator anim = new Animator();
anim.start();
- window.addWindowListener(new WindowAdapter() {
- public void windowDestroyed(WindowEvent e) {
+ windows[i] = GLWindow.create(caps);
+ windows[i].addWindowListener(new WindowAdapter() {
+ public void windowDestroyed(final WindowEvent e) {
anim.stop();
- }
+ }
});
- } catch (Throwable t) {
- t.printStackTrace();
+ mss[i] = new MovieSimple(null);
+ mss[i].setSwapInterval(swapInterval);
+ mss[i].setScaleOrig(!zoom);
+ mss[i].setOrthoProjection(ortho);
+ mss[i].mPlayer.attachObject(WINDOW_KEY, windows[i]);
+ mss[i].mPlayer.addEventListener(myGLMediaEventListener);
+
+ windows[i].setTitle("Player "+i);
+ windows[i].setSize(width, height);
+ windows[i].setVisible(true);
+ anim.add(windows[i]);
+
+ final Uri streamLocN;
+ if( 0 == i ) {
+ streamLocN = streamLoc0;
+ } else {
+ if( null != urls_s[i] ) {
+ streamLocN = Uri.cast(urls_s[i]);
+ } else {
+ streamLocN = defURI;
+ }
+ }
+ System.err.println("Win #"+i+": stream "+streamLocN);
+ mss[i].initStream(streamLocN, vid, aid, textureCount);
}
}
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas01.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas01.java
new file mode 100644
index 000000000..9866e769c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas01.java
@@ -0,0 +1,134 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
+
+import java.applet.Applet;
+import java.awt.Color;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+/**
+ * Bug 816: OSX CALayer Positioning Bug.
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ * <p>
+ * Test simply positions a GLCanvas via setBounds(..) within it's Applet.
+ * </p>
+ */
+@SuppressWarnings("serial")
+public class Bug816AppletGLCanvas01 extends Applet implements GLEventListener {
+
+ public Bug816AppletGLCanvas01() {
+ }
+
+ public static JFrame frame;
+ public static JPanel appletHolder;
+ public static boolean isApplet = true;
+
+ static public void main(final String args[]) {
+ Applet myApplet = null;
+ isApplet = false;
+
+ myApplet = new Bug816AppletGLCanvas01();
+ appletStarter(myApplet, "Bug861AppletGLCanvasTest01", 800, 600);
+ }
+
+ static public void appletStarter(final Applet des, final String frameName, final int width, final int height) {
+ appletHolder = new JPanel();
+ if (frame != null) {
+ frame.dispose();
+ frame = null;
+ }
+ frame = new JFrame(frameName);
+ frame.setVisible(false);
+ frame.getContentPane().add(appletHolder);
+
+ appletHolder.setLayout(null);
+ des.setBounds(0, 0, width, height);
+ appletHolder.add(des);
+
+ frame.setVisible(true);
+ final int frameBorderSize = appletHolder.getLocationOnScreen().x - frame.getLocationOnScreen().x;
+ final int titleBarHeight = appletHolder.getLocationOnScreen().y - frame.getLocationOnScreen().y;
+ final int frameWidth = width + 2 * frameBorderSize;
+ final int frameHeight = height + titleBarHeight + frameBorderSize;
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setSize(frameWidth, frameHeight);
+ frame.setVisible(true);
+ des.init();
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
+ System.exit(0);
+ }
+ });
+ }
+
+ public void init() {
+ initOpenGLAWT();
+ }
+
+ public void initOpenGLAWT() {
+ setBackground(Color.gray);
+ setLayout(null);
+
+ final GLProfile glp = GLProfile.getDefault();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLCanvas canvas = new GLCanvas(caps);
+ canvas.setBounds(50, 50, 200, 450);
+ canvas.addGLEventListener(this);
+ add(canvas);
+ }
+
+ public void init(final GLAutoDrawable gLAutoDrawable) {
+ final GL gl = gLAutoDrawable.getGL();
+ gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ gLAutoDrawable.swapBuffers();
+ }
+
+ public void dispose(final GLAutoDrawable glad) {
+ }
+
+ public void display(final GLAutoDrawable glad) {
+ }
+
+ public void reshape(final GLAutoDrawable glad, final int i, final int i1, final int i2, final int i3) {
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02a.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02a.java
new file mode 100644
index 000000000..6218edd50
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02a.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
+
+import java.applet.Applet;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.BoxLayout;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Bug 816: OSX CALayer Positioning Bug.
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ * <p>
+ * Test uses a box layout within the Applet.
+ * </p>
+ */
+@SuppressWarnings("serial")
+public class Bug816AppletGLCanvas02a extends Applet {
+ GLAnimatorControl animator;
+ boolean added = false;
+
+ @Override
+ public void init() {
+ System.err.println("GearsApplet: init() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ animator = new Animator();
+ new BoxLayout(this, BoxLayout.X_AXIS);
+ setSize(664, 364);
+ add(createCanvas());
+ add(createCanvas());
+ System.err.println("GearsApplet: init() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ }
+
+ private GLCanvas createCanvas() {
+ final GLCanvas canvas = new GLCanvas();
+ canvas.addGLEventListener(new GearsES2(1));
+ canvas.setSize(300, 300);
+ animator.add(canvas);
+ return canvas;
+ }
+
+ String currentThreadName() {
+ return Thread.currentThread().getName();
+ }
+
+ @Override
+ public void start() {
+ System.err.println("GearsApplet: start() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ animator.start();
+ animator.setUpdateFPSFrames(60, System.err);
+ System.err.println("GearsApplet: start() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ }
+
+ @Override
+ public void stop() {
+ System.err.println("GearsApplet: stop() - [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ animator.stop();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02b.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02b.java
new file mode 100644
index 000000000..62eb8ea18
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02b.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
+
+import java.applet.Applet;
+import java.awt.GridLayout;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.awt.GLCanvas;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Bug 816: OSX CALayer Positioning Bug.
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ * <p>
+ * Test uses a grid layout within the Applet.
+ * </p>
+ */
+@SuppressWarnings("serial")
+public class Bug816AppletGLCanvas02b extends Applet {
+ GLAnimatorControl animator;
+ boolean added = false;
+
+ @Override
+ public void init() {
+ System.err.println("GearsApplet: init() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ animator = new Animator();
+ this.setLayout(new GridLayout(1, 2));
+ setSize(664, 364);
+ add(createCanvas());
+ add(createCanvas());
+ System.err.println("GearsApplet: init() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ }
+
+ private GLCanvas createCanvas() {
+ final GLCanvas canvas = new GLCanvas();
+ canvas.addGLEventListener(new GearsES2(1));
+ canvas.setSize(300, 300);
+ animator.add(canvas);
+ return canvas;
+ }
+
+ String currentThreadName() {
+ return Thread.currentThread().getName();
+ }
+
+ @Override
+ public void start() {
+ System.err.println("GearsApplet: start() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ animator.start();
+ animator.setUpdateFPSFrames(60, System.err);
+ System.err.println("GearsApplet: start() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ }
+
+ @Override
+ public void stop() {
+ System.err.println("GearsApplet: stop() - [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ animator.stop();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03a.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03a.java
new file mode 100644
index 000000000..32122937e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03a.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JRootPane;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Bug 816: OSX CALayer Positioning Bug - AWT Applet w/ 1 JRootPane and 2 JSplitPanes
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ * <p>
+ * See also {@link com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos02AWT}
+ * </p>
+ * Bug persists in browser (Firefox, Safari) and not in appletviewer!
+ */
+@SuppressWarnings("serial")
+public class Bug816AppletOSXCALayerPos03a extends Applet {
+ GLAnimatorControl animator;
+ boolean added = false;
+
+ @Override
+ public void init() {
+ System.err.println("GearsApplet: init() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ final GLProfile glp = GLProfile.getDefault();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLCanvas glCanvas1 = new GLCanvas(caps);
+ glCanvas1.addGLEventListener(new GearsES2(1));
+
+ animator = new Animator();
+ animator.add(glCanvas1);
+ setLayout(new BorderLayout());
+
+ // Build a GUI where the canvas 3D is located at top right of the frame
+ // and can be resized with split panes dividers
+ final JSplitPane verticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+ true, new JScrollPane(), glCanvas1);
+ verticalSplitPane.setResizeWeight(0.5);
+ final JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+ true, new JScrollPane(), verticalSplitPane);
+ horizontalSplitPane.setResizeWeight(0.5);
+ final JRootPane intermediateRootPane = new JRootPane();
+ intermediateRootPane.setContentPane(horizontalSplitPane);
+ add(intermediateRootPane, BorderLayout.CENTER);
+ System.err.println("GearsApplet: init() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ }
+
+ String currentThreadName() {
+ return Thread.currentThread().getName();
+ }
+
+ @Override
+ public void start() {
+ System.err.println("GearsApplet: start() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ animator.start();
+ animator.setUpdateFPSFrames(60, System.err);
+ System.err.println("GearsApplet: start() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ }
+
+ @Override
+ public void stop() {
+ System.err.println("GearsApplet: stop() - [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ animator.stop();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03b.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03b.java
new file mode 100644
index 000000000..491bc5fbc
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03b.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.JApplet;
+import javax.swing.JRootPane;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Bug 816: OSX CALayer Positioning Bug - Swing JApplet w/ 2 JRootPanes and 2 JSplitPanes
+ * <p>
+ * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40
+ * </p>
+ * <p>
+ * See also {@link com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos02AWT}
+ * </p>
+ * Bug persists in browser (Firefox, Safari) and not in appletviewer!
+ */
+@SuppressWarnings("serial")
+public class Bug816AppletOSXCALayerPos03b extends JApplet {
+ GLAnimatorControl animator;
+ boolean added = false;
+
+ @Override
+ public void init() {
+ System.err.println("GearsApplet: init() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ final GLProfile glp = GLProfile.getDefault();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLCanvas glCanvas1 = new GLCanvas(caps);
+ glCanvas1.addGLEventListener(new GearsES2(1));
+
+ animator = new Animator();
+ animator.add(glCanvas1);
+ setSize(640, 480);
+
+ // Build a GUI where the canvas 3D is located at top right of the frame
+ // and can be resized with split panes dividers
+ final JSplitPane verticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+ true, new JScrollPane(), glCanvas1);
+ verticalSplitPane.setResizeWeight(0.5);
+ final JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+ true, new JScrollPane(), verticalSplitPane);
+ horizontalSplitPane.setResizeWeight(0.5);
+ final JRootPane intermediateRootPane = new JRootPane();
+ intermediateRootPane.setContentPane(horizontalSplitPane);
+ intermediateRootPane.setSize(640, 480);
+ this.add(intermediateRootPane);
+ System.err.println("GearsApplet: init() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ }
+
+ String currentThreadName() {
+ return Thread.currentThread().getName();
+ }
+
+ @Override
+ public void start() {
+ System.err.println("GearsApplet: start() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ animator.start();
+ animator.setUpdateFPSFrames(60, System.err);
+ System.err.println("GearsApplet: start() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ }
+
+ @Override
+ public void stop() {
+ System.err.println("GearsApplet: stop() - [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ animator.stop();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug848AppletGLCanvas01.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug848AppletGLCanvas01.java
new file mode 100644
index 000000000..e85e84cf3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug848AppletGLCanvas01.java
@@ -0,0 +1,94 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
+
+import java.applet.Applet;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.BoxLayout;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Bug 848: Applet on OSX w/ CALayer and 2 or more GLCanvas may 'crash'.
+ * <p>
+ * Test uses 2x3 GLCanvas in a box layout within the Applet.
+ * </p>
+ */
+@SuppressWarnings("serial")
+public class Bug848AppletGLCanvas01 extends Applet {
+ private final List<GLAnimatorControl> animators = new ArrayList<GLAnimatorControl>(2);
+
+ @Override
+ public void init() {
+ System.err.println("GearsApplet: init() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ new BoxLayout(this, BoxLayout.X_AXIS);
+ setSize(1024, 664);
+ add(createCanvas(0));
+ add(createCanvas(0));
+ add(createCanvas(0));
+ add(createCanvas(0));
+ add(createCanvas(0));
+ add(createCanvas(1));
+ System.err.println("GearsApplet: init() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ }
+
+ private GLCanvas createCanvas(final int vsyncI) {
+ final GLCanvas canvas = new GLCanvas();
+ canvas.addGLEventListener(new GearsES2(vsyncI));
+ canvas.setSize(300, 300);
+ animators.add(new Animator(canvas));
+ return canvas;
+ }
+
+ String currentThreadName() {
+ return Thread.currentThread().getName();
+ }
+
+ @Override
+ public void start() {
+ System.err.println("GearsApplet: start() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ for (final GLAnimatorControl control : animators) {
+ control.start();
+ control.setUpdateFPSFrames(60, System.err);
+ }
+ System.err.println("GearsApplet: start() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ }
+
+ @Override
+ public void stop() {
+ System.err.println("GearsApplet: stop() - [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName());
+ for (final GLAnimatorControl control : animators) {
+ control.stop();
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java
index 732036eb0..d8c4341a8 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,173 +20,498 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.opengl.*;
import com.jogamp.opengl.util.Animator;
+
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.common.os.Platform;
import com.jogamp.newt.event.awt.AWTKeyAdapter;
import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.TraceKeyAdapter;
import com.jogamp.newt.event.TraceWindowAdapter;
-
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Component;
+import java.awt.Container;
import java.awt.Dimension;
+import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.TextArea;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import org.junit.Assert;
+import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGearsES2AWT extends UITestCase {
- static int width, height;
+ public enum FrameLayout { None, TextOnBottom, BorderCenterSurrounded, DoubleBorderCenterSurrounded };
+ public enum ResizeBy { Component, Frame };
+
+ static long duration = 500; // ms
+ static int width = 640, height = 480;
+ static int xpos = 10, ypos = 10;
+ static FrameLayout frameLayout = FrameLayout.None;
+ static ResizeBy resizeBy = ResizeBy.Component;
+ static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+
static boolean forceES2 = false;
- static boolean shallUseOffscreenLayer = false;
+ static boolean forceGL3 = false;
+ static boolean manualTest = false;
+ static boolean shallUseOffscreenFBOLayer = false;
static boolean shallUseOffscreenPBufferLayer = false;
static boolean useMSAA = false;
- static boolean addComp = true;
+ static boolean useStencil = false;
+ static boolean shutdownRemoveGLCanvas = true;
+ static boolean shutdownDisposeFrame = true;
+ static boolean shutdownSystemExit = false;
static int swapInterval = 1;
+ static boolean exclusiveContext = false;
+ static boolean useAnimator = true;
+ static Thread awtEDT;
+ static java.awt.Dimension rwsize = null;
@BeforeClass
public static void initClass() {
- width = 640;
- height = 480;
+ try {
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ awtEDT = Thread.currentThread();
+ } } );
+ } catch (final Exception e) {
+ e.printStackTrace();
+ Assert.assertNull(e);
+ }
}
@AfterClass
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilities caps) throws InterruptedException, InvocationTargetException {
+ static void setComponentSize(final Frame frame, final Component comp, final java.awt.Dimension new_sz) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ comp.setMinimumSize(new_sz);
+ comp.setPreferredSize(new_sz);
+ comp.setSize(new_sz);
+ if( null != frame ) {
+ frame.pack();
+ }
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+ static void setFrameSize(final Frame frame, final boolean frameLayout, final java.awt.Dimension new_sz) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(new_sz);
+ if( frameLayout ) {
+ frame.validate();
+ }
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ static void setSize(final ResizeBy resizeBy, final Frame frame, final boolean frameLayout, final Component comp, final java.awt.Dimension new_sz) {
+ switch( resizeBy ) {
+ case Component:
+ setComponentSize(frameLayout ? frame : null, comp, new_sz);
+ break;
+ case Frame:
+ setFrameSize(frame, frameLayout, new_sz);
+ break;
+ }
+ }
+
+ private void setTitle(final Frame frame, final GLCanvas glc, final GLCapabilitiesImmutable caps) {
+ final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl";
+ final java.awt.Rectangle b = glc.getBounds();
+ frame.setTitle("GLCanvas["+capsA+"], swapI "+swapInterval+", win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getSurfaceWidth()+"x"+glc.getSurfaceHeight());
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final ResizeBy resizeBy, final FrameLayout frameLayout) throws InterruptedException, InvocationTargetException {
final Frame frame = new Frame("GearsES2 AWT Test");
Assert.assertNotNull(frame);
final GLCanvas glCanvas = new GLCanvas(caps);
Assert.assertNotNull(glCanvas);
- Dimension glc_sz = new Dimension(width, height);
- glCanvas.setMinimumSize(glc_sz);
- glCanvas.setPreferredSize(glc_sz);
- glCanvas.setSize(glc_sz);
- if(addComp) {
- final TextArea ta = new TextArea(2, 20);
- ta.append("0123456789");
- ta.append(Platform.getNewline());
- ta.append("Some Text");
- ta.append(Platform.getNewline());
- frame.add(ta, BorderLayout.SOUTH);
+ setSize(resizeBy, frame, false, glCanvas, new Dimension(width, height));
+ glCanvas.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = glCanvas.getRequestedSurfaceScale(new int[2]);
+ frame.setLocation(xpos, ypos);
+
+ switch( frameLayout) {
+ case None:
+ frame.add(glCanvas);
+ break;
+ case TextOnBottom:
+ final TextArea ta = new TextArea(2, 20);
+ ta.append("0123456789");
+ ta.append(Platform.getNewline());
+ ta.append("Some Text");
+ ta.append(Platform.getNewline());
+ frame.setLayout(new BorderLayout());
+ frame.add(ta, BorderLayout.SOUTH);
+ frame.add(glCanvas, BorderLayout.CENTER);
+ break;
+ case BorderCenterSurrounded:
+ frame.setLayout(new BorderLayout());
+ frame.add(new Button("NORTH"), BorderLayout.NORTH);
+ frame.add(new Button("SOUTH"), BorderLayout.SOUTH);
+ frame.add(new Button("EAST"), BorderLayout.EAST);
+ frame.add(new Button("WEST"), BorderLayout.WEST);
+ frame.add(glCanvas, BorderLayout.CENTER);
+ break;
+ case DoubleBorderCenterSurrounded:
+ final Container c = new Container();
+ c.setLayout(new BorderLayout());
+ c.add(new Button("north"), BorderLayout.NORTH);
+ c.add(new Button("south"), BorderLayout.SOUTH);
+ c.add(new Button("east"), BorderLayout.EAST);
+ c.add(new Button("west"), BorderLayout.WEST);
+ c.add(glCanvas, BorderLayout.CENTER);
+
+ frame.setLayout(new BorderLayout());
+ frame.add(new Button("NORTH"), BorderLayout.NORTH);
+ frame.add(new Button("SOUTH"), BorderLayout.SOUTH);
+ frame.add(new Button("EAST"), BorderLayout.EAST);
+ frame.add(new Button("WEST"), BorderLayout.WEST);
+ frame.add(c, BorderLayout.CENTER);
+ break;
}
- frame.add(glCanvas, BorderLayout.CENTER);
- frame.setTitle("Gears AWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval);
+ setTitle(frame, glCanvas, caps);
+
+ frame.addComponentListener(new ComponentListener() {
+ @Override
+ public void componentResized(final ComponentEvent e) {
+ setTitle(frame, glCanvas, caps);
+ }
+
+ @Override
+ public void componentMoved(final ComponentEvent e) {
+ setTitle(frame, glCanvas, caps);
+ }
- glCanvas.addGLEventListener(new GearsES2(swapInterval));
+ @Override
+ public void componentShown(final ComponentEvent e) { }
- Animator animator = new Animator(glCanvas);
- QuitAdapter quitAdapter = new QuitAdapter();
+ @Override
+ public void componentHidden(final ComponentEvent e) { }
+ });
- new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glCanvas);
- new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame);
+ final GearsES2 demo = new GearsES2(swapInterval);
+ glCanvas.addGLEventListener(demo);
+
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ glCanvas.addGLEventListener(snap);
+
+ final Animator animator = useAnimator ? new Animator(glCanvas) : null;
+ if( useAnimator && exclusiveContext ) {
+ animator.setExclusiveContext(awtEDT);
+ }
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glCanvas).addTo(glCanvas);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas).addTo(frame);
+
+ final com.jogamp.newt.event.KeyListener kl = new com.jogamp.newt.event.KeyAdapter() {
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='x') {
+ final int[] hadSurfacePixelScale = glCanvas.getCurrentSurfaceScale(new int[2]);
+ final int[] reqSurfacePixelScale;
+ if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
+ reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+ } else {
+ reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ }
+ System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
+ glCanvas.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = glCanvas.getRequestedSurfaceScale(new int[2]);
+ final int[] hasSurfacePixelScale0 = glCanvas.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 });
+ final int[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new int[2]);
+ System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
+ reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ setTitle(frame, glCanvas, caps);
+ Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
+ }
+ } };
+ new AWTKeyAdapter(kl, glCanvas).addTo(glCanvas);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- frame.pack();
- frame.setVisible(true);
+ if( ResizeBy.Frame == resizeBy ) {
+ frame.validate();
+ } else {
+ frame.pack();
+ }
+ frame.setVisible(true);
}});
- animator.start();
- animator.setUpdateFPSFrames(60, System.err);
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true));
+
+ final int[] hasSurfacePixelScale0 = glCanvas.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 });
+ final int[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new int[2]);
+ System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ setTitle(frame, glCanvas, caps);
+ Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
+
+ if( useAnimator ) {
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ Assert.assertEquals(exclusiveContext ? awtEDT : null, glCanvas.getExclusiveContextThread());
+ animator.setUpdateFPSFrames(60, System.err);
+ }
+
+ System.err.println("canvas pos/siz: "+glCanvas.getX()+"/"+glCanvas.getY()+" "+glCanvas.getSurfaceWidth()+"x"+glCanvas.getSurfaceHeight());
+
+ snap.setMakeSnapshot();
+
+ if( null != rwsize ) {
+ Thread.sleep(500); // 500ms delay
+ setSize(resizeBy, frame, true, glCanvas, rwsize);
+ System.err.println("window resize pos/siz: "+glCanvas.getX()+"/"+glCanvas.getY()+" "+glCanvas.getSurfaceWidth()+"x"+glCanvas.getSurfaceHeight());
+ }
- while(!quitAdapter.shouldQuit() /* && animator.isAnimating() */ && animator.getTotalFPSDuration()<duration) {
+ snap.setMakeSnapshot();
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
Thread.sleep(100);
+ t1 = System.currentTimeMillis();
}
Assert.assertNotNull(frame);
Assert.assertNotNull(glCanvas);
- Assert.assertNotNull(animator);
- animator.stop();
- Assert.assertEquals(false, animator.isAnimating());
- frame.setVisible(false);
+ if( useAnimator ) {
+ Assert.assertNotNull(animator);
+ Assert.assertEquals(exclusiveContext ? awtEDT : null, glCanvas.getExclusiveContextThread());
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ Assert.assertEquals(null, glCanvas.getExclusiveContextThread());
+ }
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
Assert.assertEquals(false, frame.isVisible());
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- frame.remove(glCanvas);
- frame.dispose();
+ if(shutdownRemoveGLCanvas) {
+ frame.remove(glCanvas);
+ }
+ if(shutdownDisposeFrame) {
+ frame.dispose();
+ }
+ if(shutdownSystemExit) {
+ System.exit(0);
+ }
}});
}
@Test
public void test01() throws InterruptedException, InvocationTargetException {
- GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
if(useMSAA) {
caps.setNumSamples(4);
caps.setSampleBuffers(true);
}
- if(shallUseOffscreenLayer) {
+ if(useStencil) {
+ caps.setStencilBits(1);
+ }
+ if(shallUseOffscreenFBOLayer) {
caps.setOnscreen(false);
}
if(shallUseOffscreenPBufferLayer) {
caps.setPBuffer(true);
}
- runTestGL(caps);
+ runTestGL(caps, resizeBy, frameLayout);
}
- static long duration = 500; // ms
+ @Test
+ public void test02_GLES2() throws InterruptedException, InvocationTargetException {
+ if(manualTest) return;
- public static void main(String args[]) {
+ if( !GLProfile.isAvailable(GLProfile.GLES2) ) {
+ System.err.println("GLES2 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GLES2);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, resizeBy, frameLayout);
+ }
+
+ @Test
+ public void test03_GL3() throws InterruptedException, InvocationTargetException {
+ if(manualTest) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, resizeBy, frameLayout);
+ }
+
+ @Test
+ public void test99_PixelScale1_DefaultNorm() throws InterruptedException, InvocationTargetException {
+ if( manualTest ) return;
+
+ reqSurfacePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ reqSurfacePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ runTestGL(caps, resizeBy, frameLayout);
+ }
+
+ public static void main(final String args[]) {
boolean waitForKey = false;
-
+ int rw=-1, rh=-1;
+
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
- try {
- duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-width")) {
+ i++;
+ width = MiscUtils.atoi(args[i], width);
+ } else if(args[i].equals("-height")) {
+ i++;
+ height = MiscUtils.atoi(args[i], height);
+ } else if(args[i].equals("-x")) {
+ i++;
+ xpos = MiscUtils.atoi(args[i], xpos);
+ } else if(args[i].equals("-y")) {
+ i++;
+ ypos = MiscUtils.atoi(args[i], ypos);
+ } else if(args[i].equals("-rwidth")) {
+ i++;
+ rw = MiscUtils.atoi(args[i], rw);
+ } else if(args[i].equals("-rheight")) {
+ i++;
+ rh = MiscUtils.atoi(args[i], rh);
+ } else if(args[i].equals("-pixelScale")) {
+ i++;
+ final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+ reqSurfacePixelScale[0] = pS;
+ reqSurfacePixelScale[1] = pS;
+ } else if(args[i].equals("-layout")) {
+ i++;
+ frameLayout = FrameLayout.valueOf(args[i]);
+ } else if(args[i].equals("-resizeBy")) {
+ i++;
+ resizeBy = ResizeBy.valueOf(args[i]);
} else if(args[i].equals("-es2")) {
forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
} else if(args[i].equals("-vsync")) {
i++;
swapInterval = MiscUtils.atoi(args[i], swapInterval);
- } else if(args[i].equals("-layered")) {
- shallUseOffscreenLayer = true;
+ } else if(args[i].equals("-exclctx")) {
+ exclusiveContext = true;
+ } else if(args[i].equals("-noanim")) {
+ useAnimator = false;
+ } else if(args[i].equals("-layeredFBO")) {
+ shallUseOffscreenFBOLayer = true;
} else if(args[i].equals("-layeredPBuffer")) {
shallUseOffscreenPBufferLayer = true;
} else if(args[i].equals("-msaa")) {
useMSAA = true;
+ } else if(args[i].equals("-stencil")) {
+ useStencil = true;
} else if(args[i].equals("-wait")) {
waitForKey = true;
- } else if(args[i].equals("-justGears")) {
- addComp = false;
+ } else if(args[i].equals("-shutdownKeepGLCanvas")) {
+ shutdownRemoveGLCanvas = false;
+ } else if(args[i].equals("-shutdownKeepFrame")) {
+ shutdownDisposeFrame = false;
+ } else if(args[i].equals("-shutdownKeepAll")) {
+ shutdownRemoveGLCanvas = false;
+ shutdownDisposeFrame = false;
+ } else if(args[i].equals("-shutdownSystemExit")) {
+ shutdownSystemExit = true;
+ } else if(args[i].equals("-manual")) {
+ manualTest = true;
}
}
+ if( 0 < rw && 0 < rh ) {
+ rwsize = new Dimension(rw, rh);
+ }
+
+ System.err.println("resize "+rwsize);
+ System.err.println("frameLayout "+frameLayout);
+ System.err.println("resizeBy "+resizeBy);
System.err.println("forceES2 "+forceES2);
+ System.err.println("forceGL3 "+forceGL3);
System.err.println("swapInterval "+swapInterval);
- System.err.println("shallUseOffscreenLayer "+shallUseOffscreenLayer);
-
+ System.err.println("exclusiveContext "+exclusiveContext);
+ System.err.println("useMSAA "+useMSAA);
+ System.err.println("useAnimator "+useAnimator);
+
+ System.err.println("shallUseOffscreenFBOLayer "+shallUseOffscreenFBOLayer);
+ System.err.println("shallUseOffscreenPBufferLayer "+shallUseOffscreenPBufferLayer);
+
if(waitForKey) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
try {
System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ } catch (final IOException e) { }
}
org.junit.runner.JUnitCore.main(TestGearsES2AWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java
new file mode 100644
index 000000000..ae11c9d54
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java
@@ -0,0 +1,514 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.nativewindow.ScalableSurface;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.TraceKeyAdapter;
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTKeyAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.FPSAnimator;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGearsES2GLJPanelAWT extends UITestCase {
+ static Dimension wsize, rwsize=null;
+ static boolean forceES2 = false;
+ static boolean forceGL3 = false;
+ static boolean forceGLFFP = false;
+ static boolean shallUsePBuffer = false;
+ static boolean shallUseBitmap = false;
+ static boolean useMSAA = false;
+ static int swapInterval = 0;
+ static boolean useAnimator = true;
+ static boolean manualTest = false;
+ static boolean skipGLOrientationVerticalFlip = false;
+ static int xpos = 10, ypos = 10;
+ static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+
+ @BeforeClass
+ public static void initClass() {
+ if(null == wsize) {
+ wsize = new Dimension(640, 480);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ static void setFrameSize(final JFrame frame, final boolean frameLayout, final java.awt.Dimension new_sz) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(new_sz);
+ if( frameLayout ) {
+ frame.validate();
+ }
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ private void setTitle(final JFrame frame, final GLJPanel glc, final GLCapabilitiesImmutable caps) {
+ final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl";
+ final java.awt.Rectangle b = glc.getBounds();
+ frame.setTitle("GLJPanel["+capsA+"], swapI "+swapInterval+", win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getSurfaceWidth()+"x"+glc.getSurfaceHeight());
+ }
+
+ protected void runTestGL(final GLCapabilities caps)
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ final JFrame frame = new JFrame("Swing GLJPanel");
+ Assert.assertNotNull(frame);
+
+ final GLJPanel glJPanel = new GLJPanel(caps);
+ Assert.assertNotNull(glJPanel);
+ glJPanel.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip);
+ glJPanel.setMinimumSize(wsize);
+ glJPanel.setPreferredSize(wsize);
+ glJPanel.setSize(wsize);
+ glJPanel.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new int[2]);
+ if( caps.isBitmap() || caps.getGLProfile().isGL2() ) {
+ final Gears gears = new Gears(swapInterval);
+ gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glJPanel.addGLEventListener(gears);
+ } else {
+ final GearsES2 gears = new GearsES2(swapInterval);
+ gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glJPanel.addGLEventListener(gears);
+ }
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ glJPanel.addGLEventListener(snap);
+ glJPanel.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) { }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) { }
+ @Override
+ public void display(final GLAutoDrawable drawable) { }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ setTitle(frame, glJPanel, caps);
+ }
+
+ });
+ setTitle(frame, glJPanel, caps);
+ frame.setLocation(xpos, ypos);
+
+ frame.addComponentListener(new ComponentListener() {
+ @Override
+ public void componentResized(final ComponentEvent e) {
+ setTitle(frame, glJPanel, caps);
+ }
+
+ @Override
+ public void componentMoved(final ComponentEvent e) {
+ setTitle(frame, glJPanel, caps);
+ }
+
+ @Override
+ public void componentShown(final ComponentEvent e) { }
+
+ @Override
+ public void componentHidden(final ComponentEvent e) { }
+ });
+
+ final FPSAnimator animator = useAnimator ? new FPSAnimator(glJPanel, 60) : null;
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.getContentPane().add(glJPanel, BorderLayout.CENTER);
+ frame.getContentPane().validate();
+ frame.pack();
+ frame.setVisible(true);
+ } } ) ;
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel, true));
+
+ final int[] hasSurfacePixelScale0 = glJPanel.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 });
+ final int[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new int[2]);
+ System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ setTitle(frame, glJPanel, caps);
+ Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
+
+ if( useAnimator ) {
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.start();
+ Assert.assertEquals(true, animator.isAnimating());
+ }
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glJPanel).addTo(glJPanel);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glJPanel).addTo(frame);
+
+ final com.jogamp.newt.event.KeyListener kl = new com.jogamp.newt.event.KeyAdapter() {
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='x') {
+ final int[] hadSurfacePixelScale = glJPanel.getCurrentSurfaceScale(new int[2]);
+ final int[] reqSurfacePixelScale;
+ if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
+ reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+ } else {
+ reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ }
+ System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
+ glJPanel.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new int[2]);
+ final int[] hasSurfacePixelScale0 = glJPanel.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 });
+ final int[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new int[2]);
+ System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
+ reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ setTitle(frame, glJPanel, caps);
+ Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
+ } else if(e.getKeyChar()=='m') {
+ final GLCapabilitiesImmutable capsPre = glJPanel.getChosenGLCapabilities();
+ final GLCapabilities capsNew = new GLCapabilities(capsPre.getGLProfile());
+ capsNew.copyFrom(capsPre);
+ final boolean msaa;
+ if( capsPre.getSampleBuffers() ) {
+ capsNew.setSampleBuffers(false);
+ msaa = false;
+ } else {
+ capsNew.setSampleBuffers(true);
+ capsNew.setNumSamples(4);
+ msaa = true;
+ }
+ System.err.println("[set MSAA "+msaa+" Caps had]: "+capsPre);
+ System.err.println("[set MSAA "+msaa+" Caps new]: "+capsNew);
+ System.err.println("XXX-A1: "+animator.toString());
+ glJPanel.setRequestedGLCapabilities(capsNew);
+ System.err.println("XXX-A2: "+animator.toString());
+ System.err.println("XXX: "+glJPanel.toString());
+ }
+ } };
+ new AWTKeyAdapter(kl, glJPanel).addTo(glJPanel);
+
+ snap.setMakeSnapshot();
+
+ if( null != rwsize ) {
+ Thread.sleep(500); // 500ms delay
+ setFrameSize(frame, true, rwsize);
+ System.err.println("window resize pos/siz: "+glJPanel.getX()+"/"+glJPanel.getY()+" "+glJPanel.getSurfaceWidth()+"x"+glJPanel.getSurfaceHeight());
+ }
+
+ snap.setMakeSnapshot();
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ boolean triggerSnap = false;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ snap.getDisplayCount();
+ if( !triggerSnap && snap.getDisplayCount() > 1 ) {
+ // Snapshot only after one frame has been rendered to suite FBO MSAA!
+ snap.setMakeSnapshot();
+ triggerSnap = true;
+ }
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glJPanel);
+
+ if( useAnimator ) {
+ Assert.assertNotNull(animator);
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ } else {
+ Assert.assertNull(animator);
+ }
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ frame.getContentPane().remove(glJPanel);
+ frame.remove(glJPanel);
+ glJPanel.destroy();
+ frame.dispose();
+ } } );
+ }
+
+ @Test
+ public void test01_DefaultNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else if(forceGLFFP) {
+ glp = GLProfile.getMaxFixedFunc(true);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ final GLCapabilities caps = new GLCapabilities( glp );
+ if(useMSAA) {
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ }
+ if(shallUsePBuffer) {
+ caps.setPBuffer(true);
+ }
+ if(shallUseBitmap) {
+ caps.setBitmap(true);
+ }
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test02_DefaultMsaa()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test03_PbufferNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setPBuffer(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test04_PbufferMsaa()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ caps.setPBuffer(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test05_BitmapNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setBitmap(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test06_BitmapMsaa()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ caps.setBitmap(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test20_GLES2()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+
+ if( !GLProfile.isAvailable(GLProfile.GLES2) ) {
+ System.err.println("GLES2 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GLES2);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test30_GL3()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test99_PixelScale1_DefaultNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ reqSurfacePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ reqSurfacePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ runTestGL(caps);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ int w=640, h=480, rw=-1, rh=-1;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-glFFP")) {
+ forceGLFFP = true;
+ } else if(args[i].equals("-width")) {
+ i++;
+ w = MiscUtils.atoi(args[i], w);
+ } else if(args[i].equals("-height")) {
+ i++;
+ h = MiscUtils.atoi(args[i], h);
+ } else if(args[i].equals("-x")) {
+ i++;
+ xpos = MiscUtils.atoi(args[i], xpos);
+ } else if(args[i].equals("-y")) {
+ i++;
+ ypos = MiscUtils.atoi(args[i], ypos);
+ } else if(args[i].equals("-rwidth")) {
+ i++;
+ rw = MiscUtils.atoi(args[i], rw);
+ } else if(args[i].equals("-rheight")) {
+ i++;
+ rh = MiscUtils.atoi(args[i], rh);
+ } else if(args[i].equals("-pixelScale")) {
+ i++;
+ final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+ reqSurfacePixelScale[0] = pS;
+ reqSurfacePixelScale[1] = pS;
+ } else if(args[i].equals("-userVFlip")) {
+ skipGLOrientationVerticalFlip = true;
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-msaa")) {
+ useMSAA = true;
+ } else if(args[i].equals("-noanim")) {
+ useAnimator = false;
+ } else if(args[i].equals("-pbuffer")) {
+ shallUsePBuffer = true;
+ } else if(args[i].equals("-bitmap")) {
+ shallUseBitmap = true;
+ } else if(args[i].equals("-manual")) {
+ manualTest = true;
+ }
+ }
+ wsize = new Dimension(w, h);
+ if( 0 < rw && 0 < rh ) {
+ rwsize = new Dimension(rw, rh);
+ }
+
+ System.err.println("size "+wsize);
+ System.err.println("resize "+rwsize);
+ System.err.println("userVFlip "+skipGLOrientationVerticalFlip);
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("forceGLFFP "+forceGLFFP);
+ System.err.println("useMSAA "+useMSAA);
+ System.err.println("useAnimator "+useAnimator);
+ System.err.println("shallUsePBuffer "+shallUsePBuffer);
+ System.err.println("shallUseBitmap "+shallUseBitmap);
+ System.err.println("manualTest "+manualTest);
+
+ org.junit.runner.JUnitCore.main(TestGearsES2GLJPanelAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java
new file mode 100644
index 000000000..11d9da780
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java
@@ -0,0 +1,422 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.FPSAnimator;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGearsES2GLJPanelsAWT extends UITestCase {
+ static int demoCount = 4;
+ static boolean jOpaque = false; // flicker-less w/o opaque, opaque leads to overdraw w/ mixed clipRects -> flicker - due to JComponent _paintImmediately(..) (?)
+ static boolean glOpaque = true; // can be either ..
+ static float glAlpha = 0.3f;
+ static boolean jZOrder = false;
+ static GLProfile glp;
+ static boolean shallUsePBuffer = false;
+ static boolean shallUseBitmap = false;
+ static boolean useMSAA = false;
+ static int swapInterval = 0;
+ static boolean useAnimator = true;
+ static boolean manualTest = false;
+ static boolean initSingleBuffer = false;
+
+ /**
+ * Even though GLJPanel uses a SingleAWTGLPixelBufferProvider per default,
+ * we like to initialize it's size to a common maximum to ensure
+ * only one {@link AWTGLPixelBuffer} gets allocated.
+ */
+ static SingleAWTGLPixelBufferProvider singleAWTGLPixelBufferProvider;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.get(GLProfile.GL2);
+ Assert.assertNotNull(glp);
+ } else {
+ setTestSupported(false);
+ }
+
+ if( initSingleBuffer ) {
+ singleAWTGLPixelBufferProvider = new SingleAWTGLPixelBufferProvider( glp.isGL2ES3() /* allowRowStride */);
+ singleAWTGLPixelBufferProvider.initSingleton(4, 600, 600, 1, true);
+ } else {
+ singleAWTGLPixelBufferProvider = null;
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ final static boolean useInterPanel = true;
+
+ /** Adds new JPanel to frame's content pane at index 0 */
+ private JComponent addPanel(final GLCapabilitiesImmutable caps, final GLAnimatorControl anim, final JFrame frame, final boolean opaque, final int x, final int y, final int w, final int h, final FloatBuffer color, final float[] clearColor)
+ throws InterruptedException, InvocationTargetException
+ {
+ final GLJPanel canvas = new GLJPanel(caps);
+ if( initSingleBuffer ) {
+ canvas.setPixelBufferProvider( singleAWTGLPixelBufferProvider );
+ }
+ canvas.setOpaque(opaque);
+ if ( !useInterPanel ) {
+ canvas.setBounds(x, y, w, h);
+ }
+ final GLEventListener demo;
+ if( caps.isBitmap() ) {
+ demo = new Gears(swapInterval);
+ } else {
+ final GearsES2 gdemo = new GearsES2(swapInterval);
+ gdemo.setIgnoreFocus(true);
+ gdemo.setGearsColors(color, color, color);
+ gdemo.setClearColor(clearColor);
+ demo = gdemo;
+ }
+ canvas.addGLEventListener(demo);
+ if( null != anim ) {
+ anim.add(canvas);
+ }
+
+ final JPanel panel;
+ final JTextField text;
+ if ( useInterPanel ) {
+ panel = new JPanel(new BorderLayout());
+ panel.setBounds(x, y, w, h);
+ panel.setOpaque(opaque);
+ text = new JTextField(x+"/"+y+" "+w+"x"+h);
+ text.setOpaque(true);
+ } else {
+ panel = null;
+ text = null;
+ }
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ if ( useInterPanel ) {
+ panel.add(text, BorderLayout.NORTH);
+ panel.add(canvas, BorderLayout.CENTER);
+ frame.getContentPane().add(panel, 0);
+ } else {
+ frame.getContentPane().add(canvas, 0);
+ }
+ } } ) ;
+ return useInterPanel ? panel : canvas;
+ }
+
+ public static final FloatBuffer red = Buffers.newDirectFloatBuffer( new float[] { 1.0f, 0.0f, 0.0f, 1.0f } );
+ public static final FloatBuffer green = Buffers.newDirectFloatBuffer( new float[] { 0.0f, 1.0f, 0.0f, 1.0f } );
+ public static final FloatBuffer blue = Buffers.newDirectFloatBuffer( new float[] { 0.0f, 0.0f, 1.0f, 1.0f } );
+ public static final FloatBuffer yellow = Buffers.newDirectFloatBuffer( new float[] { 1.0f, 1.0f, 0.0f, 1.0f } );
+ public static final FloatBuffer grey = Buffers.newDirectFloatBuffer( new float[] { 0.5f, 0.5f, 0.5f, 1.0f } );
+ public static final float grayf = 0.3f;
+ public static final float[] redish = new float[] { grayf, 0.0f, 0.0f, glAlpha };
+ public static final float[] greenish = new float[] { 0.0f, grayf, 0.0f, glAlpha };
+ public static final float[] blueish = new float[] { 0.0f, 0.0f, grayf, glAlpha };
+ public static final float[] yellowish = new float[] { grayf, grayf, 0.0f, glAlpha };
+ public static final float[] greyish = new float[] { grayf, grayf, grayf, glAlpha };
+
+ protected void relayout(final Container cont, final float oW, final float oH) {
+ final int count = cont.getComponentCount();
+ final int nW = cont.getWidth();
+ final int nH = cont.getHeight();
+ for(int i = 0 ; i < count; i++ ) {
+ final Component comp = cont.getComponent(i);
+ final float fx = comp.getX() / oW;
+ final float fy = comp.getY() / oH;
+ final float fw = comp.getWidth() / oW;
+ final float fh = comp.getHeight() / oH;
+ comp.setBounds( (int)(fx * nW), (int)(fy * nH), (int)(fw * nW), (int)(fh * nH) );
+ }
+ }
+
+ protected void runTestGL(final GLCapabilities caps)
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( !glOpaque ) {
+ caps.setAlphaBits(caps.getRedBits());
+ }
+
+ final JFrame frame = new JFrame("Swing GLJPanel");
+ Assert.assertNotNull(frame);
+
+ final FPSAnimator animator = useAnimator ? new FPSAnimator(60) : null;
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.getContentPane().setLayout(null);
+ } } );
+
+ final float[] oldSize = new float[] { 600f, 600f };
+
+ frame.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(final ComponentEvent e) {
+ final int count = frame.getComponentCount();
+ for(int i = 0 ; i < count; i++ ) {
+ relayout(frame.getContentPane(), oldSize[0], oldSize[1]);
+ }
+ frame.getContentPane().invalidate();
+ frame.getContentPane().validate();
+ // frame.pack();
+ oldSize[0] = frame.getContentPane().getWidth();
+ oldSize[1] = frame.getContentPane().getHeight();
+ }
+ } ) ;
+
+ if( demoCount > 0 ) {
+ addPanel(caps, animator, frame, jOpaque, 50, 50, 300, 300, red, redish); // A
+ }
+ if( demoCount > 1 ) {
+ addPanel(caps, animator, frame, jOpaque, 0, 250, 300, 300, blue, blueish); // C
+ }
+ if( demoCount > 2 ) {
+ addPanel(caps, animator, frame, jOpaque, 300, 0, 150, 150, green, greenish); // B
+ }
+ if( demoCount > 3 ) {
+ addPanel(caps, animator, frame, jOpaque, 300, 300, 100, 100, yellow, yellowish); // D
+ }
+ if( jZOrder ) {
+ final Container cont = frame.getContentPane();
+ final int count = cont.getComponentCount();
+ for(int i = 0 ; i < count; i++ ) {
+ cont.setComponentZOrder(cont.getComponent(i), count - 1 - i);
+ }
+ }
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize((int)oldSize[0], (int)oldSize[1]);
+ frame.getContentPane().validate();
+ // frame.pack();
+ frame.setVisible(true);
+ } } ) ;
+
+ if( useAnimator ) {
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.start();
+ Assert.assertEquals(true, animator.isAnimating());
+ }
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(animator);
+
+ if( useAnimator ) {
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ }
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ // frame.getContentPane().removeAll();
+ // frame.removeAll();
+ frame.dispose();
+ } } );
+ }
+
+ @Test
+ public void test01_DefaultNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ if(useMSAA) {
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ }
+ if(shallUsePBuffer) {
+ caps.setPBuffer(true);
+ }
+ if(shallUseBitmap) {
+ caps.setBitmap(true);
+ }
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test02_DefaultMsaa()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test03_PbufferNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setPBuffer(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test04_PbufferMsaa()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ caps.setPBuffer(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test05_BitmapNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setBitmap(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test06_BitmapMsaa()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ caps.setBitmap(true);
+ runTestGL(caps);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-msaa")) {
+ useMSAA = true;
+ } else if(args[i].equals("-jOpaque")) {
+ i++;
+ jOpaque = MiscUtils.atob(args[i], jOpaque);
+ } else if(args[i].equals("-glOpaque")) {
+ i++;
+ glOpaque = MiscUtils.atob(args[i], glOpaque);
+ } else if(args[i].equals("-alpha")) {
+ i++;
+ glAlpha = MiscUtils.atof(args[i], glAlpha);
+ } else if(args[i].equals("-initSingleBuffer")) {
+ i++;
+ initSingleBuffer = MiscUtils.atob(args[i], initSingleBuffer);
+ } else if(args[i].equals("-jZOrder")) {
+ jZOrder = true;
+ } else if(args[i].equals("-noanim")) {
+ useAnimator = false;
+ } else if(args[i].equals("-pbuffer")) {
+ shallUsePBuffer = true;
+ } else if(args[i].equals("-bitmap")) {
+ shallUseBitmap = true;
+ } else if(args[i].equals("-manual")) {
+ manualTest = true;
+ } else if(args[i].equals("-demos")) {
+ i++;
+ demoCount = MiscUtils.atoi(args[i], demoCount);
+ }
+ }
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("opaque gl "+glOpaque+", java/gljpanel "+jOpaque);
+ System.err.println("alpha "+glAlpha);
+ System.err.println("jZOrder "+jZOrder);
+ System.err.println("demos "+demoCount);
+ System.err.println("useMSAA "+useMSAA);
+ System.err.println("useAnimator "+useAnimator);
+ System.err.println("shallUsePBuffer "+shallUsePBuffer);
+ System.err.println("shallUseBitmap "+shallUseBitmap);
+ System.err.println("manualTest "+manualTest);
+ System.err.println("useSingleBuffer "+initSingleBuffer);
+
+ org.junit.runner.JUnitCore.main(TestGearsES2GLJPanelsAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java
index ed308bdfd..2d334e837 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,15 +20,14 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
-import com.jogamp.common.os.Platform;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.TraceWindowAdapter;
@@ -45,13 +44,15 @@ import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.BeforeClass;
-import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/**
* @see com.jogamp.opengl.test.junit.jogl.demos.es2.ElektronenMultiplizierer
* @author Dominik Ströhlein (DemoscenePassivist), et.al.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestElektronenMultipliziererNEWT extends UITestCase {
static final int width = 640, height = 480;
@@ -65,17 +66,17 @@ public class TestElektronenMultipliziererNEWT extends UITestCase {
static final int desiredFrameRate = 30;
static int startFrame = 1700;
static long duration = 5000; // ms
-
+
@BeforeClass
public static void initClass() {
- GLProfile glp = GLProfile.getDefault();
- if( ! ( glp.isHardwareRasterizer() && glp.isGL2GL3() ) ) {
- // Sorry .. mobile is too slow for this one.
+ final GLProfile glp = GLProfile.getDefault();
+ if( ! ( glp.isHardwareRasterizer() && glp.isGL2ES3() ) ) {
+ // Sorry .. mobile ES2 is too slow for this one.
setTestSupported(false);
return;
}
}
-
+
protected void run() throws InterruptedException {
final ElektronenMultiplizierer demo = new ElektronenMultiplizierer(
tRoutineClassName,
@@ -84,17 +85,17 @@ public class TestElektronenMultipliziererNEWT extends UITestCase {
tFrameCapture,
tFrameSkip, desiredFrameRate, startFrame
);
- GLCapabilitiesImmutable caps = demo.getGLCapabilities();
-
- GLWindow glWindow = GLWindow.create(caps);
+ final GLCapabilitiesImmutable caps = demo.getGLCapabilities();
+
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setSize(width, height);
glWindow.setTitle("ElektronenMultiplizierer (GL2ES2/NEWT)");
glWindow.addGLEventListener(demo);
- Animator animator = new Animator(glWindow);
+ final Animator animator = new Animator(glWindow);
animator.setUpdateFPSFrames(60, System.err);
- QuitAdapter quitAdapter = new QuitAdapter();
+ final QuitAdapter quitAdapter = new QuitAdapter();
//glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
@@ -103,7 +104,10 @@ public class TestElektronenMultipliziererNEWT extends UITestCase {
final GLWindow f_glWindow = glWindow;
glWindow.addKeyListener(new KeyAdapter() {
- public void keyTyped(KeyEvent e) {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
if(e.getKeyChar()=='f') {
new Thread() {
public void run() {
@@ -133,19 +137,19 @@ public class TestElektronenMultipliziererNEWT extends UITestCase {
run();
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
if(args[i].equals("-sframe")) {
i++;
try {
startFrame = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
}
org.junit.runner.JUnitCore.main(TestElektronenMultipliziererNEWT.class.getName());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
index a79c924d6..eb2536639 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,21 +20,25 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URLConnection;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.junit.util.JunitTracer;
import com.jogamp.newt.Display;
+import com.jogamp.newt.Display.PointerIcon;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.MouseAdapter;
@@ -42,20 +46,23 @@ import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.EDTUtil;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
-
import com.jogamp.opengl.util.Animator;
-
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.Gamma;
+import com.jogamp.opengl.util.PNGPixelRect;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.nativewindow.util.Dimension;
import javax.media.nativewindow.util.Point;
import javax.media.nativewindow.util.PointImmutable;
import javax.media.nativewindow.util.DimensionImmutable;
-
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -63,31 +70,48 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
+import jogamp.newt.DefaultEDTUtil;
+import jogamp.newt.driver.PNGIcon;
+
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
-public class TestGearsES2NEWT extends UITestCase {
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGearsES2NEWT extends UITestCase {
static int screenIdx = 0;
static PointImmutable wpos;
- static DimensionImmutable wsize;
+ static DimensionImmutable wsize, rwsize=null;
+ static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
static long duration = 500; // ms
static boolean opaque = true;
+ static int forceAlpha = -1;
static boolean undecorated = false;
static boolean alwaysOnTop = false;
static boolean fullscreen = false;
- static boolean pmvUseBackingArray = true;
static int swapInterval = 1;
static boolean waitForKey = false;
static boolean mouseVisible = true;
static boolean mouseConfined = false;
+ static boolean setPointerIcon = false;
static boolean showFPS = false;
static int loops = 1;
static boolean loop_shutdown = false;
static boolean forceES2 = false;
-
+ static boolean forceES3 = false;
+ static boolean forceGL3 = false;
+ static boolean forceGL2 = false;
+ static boolean manualTest = false;
+ static boolean exclusiveContext = false;
+ static boolean useAnimator = true;
+ static boolean useMappedBuffers = false;
+ static enum SysExit { none, testExit, testError, testEDTError, displayExit, displayError, displayEDTError };
+ static SysExit sysExit = SysExit.none;
+
@BeforeClass
public static void initClass() {
if(null == wsize) {
@@ -99,13 +123,21 @@ public class TestGearsES2NEWT extends UITestCase {
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilitiesImmutable caps, boolean undecorated) throws InterruptedException {
+ private void setTitle(final Window win, final GLCapabilitiesImmutable caps) {
+ final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl";
+ final float[] sDPI = win.getPixelsPerMM(new float[2]);
+ sDPI[0] *= 25.4f;
+ sDPI[1] *= 25.4f;
+ win.setTitle("GLWindow["+capsA+"], swapI "+swapInterval+", win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]);
+ }
+ protected void runTestGL(final GLCapabilitiesImmutable caps, final boolean undecorated) throws InterruptedException {
System.err.println("requested: vsync "+swapInterval+", "+caps);
- Display dpy = NewtFactory.createDisplay(null);
- Screen screen = NewtFactory.createScreen(dpy, screenIdx);
+ final Display dpy = NewtFactory.createDisplay(null);
+ final Screen screen = NewtFactory.createScreen(dpy, screenIdx);
final GLWindow glWindow = GLWindow.create(screen, caps);
Assert.assertNotNull(glWindow);
- glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval+", size "+wsize+", pos "+wpos);
+ glWindow.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
glWindow.setSize(wsize.getWidth(), wsize.getHeight());
if(null != wpos) {
glWindow.setPosition(wpos.getX(), wpos.getY());
@@ -117,146 +149,420 @@ public class TestGearsES2NEWT extends UITestCase {
glWindow.confinePointer(mouseConfined);
final GearsES2 demo = new GearsES2(swapInterval);
- demo.setPMVUseBackingArray(pmvUseBackingArray);
+ demo.setUseMappedBuffers(useMappedBuffers);
+ demo.setValidateBuffers(true);
glWindow.addGLEventListener(demo);
+
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ glWindow.addGLEventListener(snap);
if(waitForKey) {
glWindow.addGLEventListener(new GLEventListener() {
- public void init(GLAutoDrawable drawable) { }
- public void dispose(GLAutoDrawable drawable) { }
- public void display(GLAutoDrawable drawable) {
- GLAnimatorControl actrl = drawable.getAnimator();
+ public void init(final GLAutoDrawable drawable) { }
+ public void dispose(final GLAutoDrawable drawable) { }
+ public void display(final GLAutoDrawable drawable) {
+ final GLAnimatorControl actrl = drawable.getAnimator();
if(waitForKey && actrl.getTotalFPSFrames() == 60*3) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
- System.err.println("Press enter to continue");
- try {
- System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ JunitTracer.waitForKey("3s mark");
actrl.resetFPSCounter();
waitForKey = false;
}
}
- public void reshape(GLAutoDrawable drawable, int x, int y,
- int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y,
+ final int width, final int height) { }
});
}
- Animator animator = new Animator(glWindow);
- QuitAdapter quitAdapter = new QuitAdapter();
+ final Animator animator = useAnimator ? new Animator() : null;
+ if( useAnimator ) {
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.setExclusiveContext(exclusiveContext);
+ }
+ final QuitAdapter quitAdapter = new QuitAdapter();
//glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
//glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
glWindow.addKeyListener(quitAdapter);
glWindow.addWindowListener(quitAdapter);
glWindow.addWindowListener(new WindowAdapter() {
- public void windowResized(WindowEvent e) {
- System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight());
+ public void windowResized(final WindowEvent e) {
+ System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ setTitle(glWindow, caps);
+ }
+ public void windowMoved(final WindowEvent e) {
+ System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ setTitle(glWindow, caps);
}
- public void windowMoved(WindowEvent e) {
- System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight());
- }
});
-
+
+ final PointerIcon[] pointerIcons = { null, null, null, null, null };
+ {
+ final Display disp = glWindow.getScreen().getDisplay();
+ disp.createNative();
+ int idx = 0;
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 8, 8);
+ System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ pointerIcons[idx] = _pointerIcon;
+ }
+ idx++;
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/pointer-grey-alpha-16x24.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 0, 0);
+ System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ pointerIcons[idx] = _pointerIcon;
+ }
+ idx++;
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-red-alpha-64x64.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 0, 0);
+ System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ pointerIcons[idx] = _pointerIcon;
+ }
+ idx++;
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-blue-alpha-64x64.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 0, 0);
+ System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ pointerIcons[idx] = _pointerIcon;
+ }
+ idx++;
+ if( PNGIcon.isAvailable() ) {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } );
+ try {
+ final URLConnection urlConn = res.resolve(0);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ System.err.printf("Create PointerIcon #%02d: %s%n", idx, image.toString());
+ _pointerIcon = disp.createPointerIcon(image, 32, 0);
+ System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ pointerIcons[idx] = _pointerIcon;
+ }
+ idx++;
+ }
+ if( setPointerIcon ) {
+ glWindow.setPointerIcon(pointerIcons[0]);
+ System.err.println("Set PointerIcon: "+glWindow.getPointerIcon());
+ }
+
glWindow.addKeyListener(new KeyAdapter() {
- public void keyTyped(KeyEvent e) {
+ int pointerIconIdx = 0;
+ float gamma = 1f;
+ float brightness = 0f;
+ float contrast = 1f;
+
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
if(e.getKeyChar()=='f') {
new Thread() {
public void run() {
- System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
- glWindow.setFullscreen(!glWindow.isFullscreen());
- System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ if( glWindow.isFullscreen() ) {
+ glWindow.setFullscreen( false );
+ } else {
+ if( e.isAltDown() ) {
+ glWindow.setFullscreen( null );
+ } else {
+ glWindow.setFullscreen( true );
+ }
+ }
+ System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setExclusiveContextThread(t);
+ } }.start();
+ } else if( e.getKeySymbol()== KeyEvent.VK_G ) {
+ new Thread() {
+ public void run() {
+ final float newGamma = gamma + ( e.isShiftDown() ? -0.1f : 0.1f );
+ System.err.println("[set gamma]: "+gamma+" -> "+newGamma);
+ if( Gamma.setDisplayGamma(glWindow, newGamma, brightness, contrast) ) {
+ gamma = newGamma;
+ }
} }.start();
} else if(e.getKeyChar()=='a') {
new Thread() {
public void run() {
- System.err.println("[set alwaysontop pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set alwaysontop pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
- System.err.println("[set alwaysontop post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ System.err.println("[set alwaysontop post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setExclusiveContextThread(t);
} }.start();
} else if(e.getKeyChar()=='d') {
new Thread() {
public void run() {
- System.err.println("[set undecorated pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", d "+glWindow.isUndecorated()+", "+glWindow.getInsets());
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ // while( null != glWindow.getExclusiveContextThread() ) ;
+ System.err.println("[set undecorated pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", d "+glWindow.isUndecorated()+", "+glWindow.getInsets());
glWindow.setUndecorated(!glWindow.isUndecorated());
- System.err.println("[set undecorated post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", d "+glWindow.isUndecorated()+", "+glWindow.getInsets());
+ System.err.println("[set undecorated post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", d "+glWindow.isUndecorated()+", "+glWindow.getInsets());
+ glWindow.setExclusiveContextThread(t);
} }.start();
} else if(e.getKeyChar()=='s') {
new Thread() {
public void run() {
- System.err.println("[set position pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets());
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set position pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
glWindow.setPosition(100, 100);
- System.err.println("[set position post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets());
+ System.err.println("[set position post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+ glWindow.setExclusiveContextThread(t);
+ } }.start();
+ } else if(e.getKeyChar()=='c') {
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set pointer-icon pre]");
+ final PointerIcon currentPI = glWindow.getPointerIcon();
+ final PointerIcon newPI;
+ if( pointerIconIdx >= pointerIcons.length ) {
+ newPI=null;
+ pointerIconIdx=0;
+ } else {
+ newPI=pointerIcons[pointerIconIdx++];
+ }
+ glWindow.setPointerIcon( newPI );
+ System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon());
+ glWindow.setExclusiveContextThread(t);
} }.start();
} else if(e.getKeyChar()=='i') {
new Thread() {
public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible());
glWindow.setPointerVisible(!glWindow.isPointerVisible());
System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible());
+ glWindow.setExclusiveContextThread(t);
} }.start();
} else if(e.getKeyChar()=='j') {
new Thread() {
public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
glWindow.confinePointer(!glWindow.isPointerConfined());
System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
if(!glWindow.isPointerConfined()) {
demo.setConfinedFixedCenter(false);
}
+ glWindow.setExclusiveContextThread(t);
} }.start();
} else if(e.getKeyChar()=='J') {
new Thread() {
public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
glWindow.confinePointer(!glWindow.isPointerConfined());
System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
demo.setConfinedFixedCenter(glWindow.isPointerConfined());
+ glWindow.setExclusiveContextThread(t);
} }.start();
} else if(e.getKeyChar()=='w') {
new Thread() {
public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
System.err.println("[set mouse pos pre]");
- glWindow.warpPointer(glWindow.getWidth()/2, glWindow.getHeight()/2);
+ glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2);
System.err.println("[set mouse pos post]");
+ glWindow.setExclusiveContextThread(t);
} }.start();
+ } else if(e.getKeyChar()=='x') {
+ final int[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]);
+ final int[] reqSurfacePixelScale;
+ if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
+ reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+ } else {
+ reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ }
+ System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
+ glWindow.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
+ final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 });
+ final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]);
+ System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
+ reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ setTitle(glWindow, caps);
+ Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
}
}
});
glWindow.addMouseListener(new MouseAdapter() {
- public void mouseClicked(MouseEvent e) {
- glWindow.setFullscreen(!glWindow.isFullscreen());
- System.err.println("setFullscreen: "+glWindow.isFullscreen());
+ public void mouseClicked(final MouseEvent e) {
+ if(e.getClickCount() == 2 && e.getPointerCount() == 1) {
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ System.err.println("setFullscreen: "+glWindow.isFullscreen());
+ }
}
});
- animator.start();
- // glWindow.setSkipContextReleaseThread(animator.getThread());
+ if( useAnimator ) {
+ animator.add(glWindow);
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread());
+ }
+
+ if( SysExit.displayError == sysExit || SysExit.displayExit == sysExit || SysExit.displayEDTError == sysExit ) {
+ glWindow.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {}
+ @Override
+ public void dispose(final GLAutoDrawable drawable) { }
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GLAnimatorControl anim = drawable.getAnimator();
+ if( null != anim && anim.isAnimating() ) {
+ final long ms = anim.getTotalFPSDuration();
+ if( ms >= duration/2 || ms >= 3000 ) { // max 3s wait until provoking error
+ if( SysExit.displayError == sysExit ) {
+ throw new Error("test error send from GLEventListener.display - "+Thread.currentThread());
+ } else if ( SysExit.displayExit == sysExit ) {
+ System.err.println("exit(0) send from GLEventListener");
+ System.exit(0);
+ } else if ( SysExit.displayEDTError == sysExit ) {
+ final Object upstream = drawable.getUpstreamWidget();
+ System.err.println("EDT invokeAndWaitError: upstream type "+upstream.getClass().getName());
+ if( upstream instanceof Window ) {
+ final EDTUtil edt = ((Window)upstream).getScreen().getDisplay().getEDTUtil();
+ System.err.println("EDT invokeAndWaitError: edt type "+edt.getClass().getName());
+ if( edt instanceof DefaultEDTUtil ) {
+ quitAdapter.doQuit();
+ ((DefaultEDTUtil)edt).invokeAndWaitError(new Runnable() {
+ public void run() {
+ throw new RuntimeException("XXX Should never ever be seen! - "+Thread.currentThread());
+ }
+ });
+ }
+ }
+ }
+ }
+ } else {
+ System.exit(0);
+ }
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ });
+ }
glWindow.setVisible(true);
-
+ if( useAnimator ) {
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+ }
+
System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
- System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets());
-
- animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
-
- while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+
+ final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 });
+ final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]);
+ System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ setTitle(glWindow, caps);
+ Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
+
+ snap.setMakeSnapshot();
+
+ if( null != rwsize ) {
+ Thread.sleep(500); // 500ms delay
+ glWindow.setSize(rwsize.getWidth(), rwsize.getHeight());
+ System.err.println("window resize pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+ }
+
+ snap.setMakeSnapshot();
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1-t0<duration) {
Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ if( SysExit.testError == sysExit || SysExit.testExit == sysExit || SysExit.testEDTError == sysExit) {
+ final long ms = t1-t0;
+ if( ms >= duration/2 || ms >= 3000 ) { // max 3s wait until provoking error
+ if( SysExit.testError == sysExit ) {
+ throw new Error("test error send from test thread");
+ } else if ( SysExit.testExit == sysExit ) {
+ System.err.println("exit(0) send from test thread");
+ System.exit(0);
+ } else if ( SysExit.testEDTError == sysExit ) {
+ final EDTUtil edt = glWindow.getScreen().getDisplay().getEDTUtil();
+ System.err.println("EDT invokeAndWaitError: edt type "+edt.getClass().getName());
+ if( edt instanceof DefaultEDTUtil ) {
+ quitAdapter.doQuit();
+ ((DefaultEDTUtil)edt).invokeAndWaitError(new Runnable() {
+ public void run() {
+ throw new RuntimeException("XXX Should never ever be seen!");
+ }
+ });
+ }
+ }
+ }
+ }
}
- animator.stop();
- Assert.assertFalse(animator.isAnimating());
- Assert.assertFalse(animator.isStarted());
+ if( useAnimator ) {
+ Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread());
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ }
+ Assert.assertEquals(null, glWindow.getExclusiveContextThread());
glWindow.destroy();
- Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
+ if( NativeWindowFactory.isAWTAvailable() ) {
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
+ }
}
@Test
- public void test01GL2ES2() throws InterruptedException {
+ public void test01_GL2ES2() throws InterruptedException {
for(int i=1; i<=loops; i++) {
System.err.println("Loop "+i+"/"+loops);
- GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES3) {
+ glp = GLProfile.get(GLProfile.GLES3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else if(forceGL2) {
+ glp = GLProfile.get(GLProfile.GL2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ final GLCapabilities caps = new GLCapabilities( glp );
caps.setBackgroundOpaque(opaque);
+ if(-1 < forceAlpha) {
+ caps.setAlphaBits(forceAlpha);
+ }
runTestGL(caps, undecorated);
if(loop_shutdown) {
GLProfile.shutdown();
@@ -264,35 +570,87 @@ public class TestGearsES2NEWT extends UITestCase {
}
}
- public static void main(String args[]) throws IOException {
- int x=0, y=0, w=640, h=480;
+ @Test
+ public void test02_GLES2() throws InterruptedException {
+ if(manualTest) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GLES2) ) {
+ System.err.println("GLES2 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GLES2);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, undecorated);
+ }
+
+ @Test
+ public void test03_GL3() throws InterruptedException {
+ if(manualTest) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, undecorated);
+ }
+
+ @Test
+ public void test99_PixelScale1_DefaultNorm() throws InterruptedException, InvocationTargetException {
+ if( manualTest ) return;
+
+ reqSurfacePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ reqSurfacePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ runTestGL(caps, undecorated);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ int x=0, y=0, w=640, h=480, rw=-1, rh=-1;
boolean usePos = false;
-
+
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
duration = MiscUtils.atol(args[i], duration);
} else if(args[i].equals("-translucent")) {
opaque = false;
+ } else if(args[i].equals("-forceAlpha")) {
+ i++;
+ forceAlpha = MiscUtils.atoi(args[i], 0);
} else if(args[i].equals("-undecorated")) {
undecorated = true;
} else if(args[i].equals("-atop")) {
alwaysOnTop = true;
} else if(args[i].equals("-fullscreen")) {
fullscreen = true;
- } else if(args[i].equals("-pmvDirect")) {
- pmvUseBackingArray = false;
} else if(args[i].equals("-vsync")) {
i++;
swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-exclctx")) {
+ exclusiveContext = true;
+ } else if(args[i].equals("-noanim")) {
+ useAnimator = false;
} else if(args[i].equals("-es2")) {
forceES2 = true;
+ } else if(args[i].equals("-es3")) {
+ forceES3 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-gl2")) {
+ forceGL2 = true;
+ } else if(args[i].equals("-mappedBuffers")) {
+ useMappedBuffers = true;
} else if(args[i].equals("-wait")) {
waitForKey = true;
} else if(args[i].equals("-mouseInvisible")) {
mouseVisible = false;
} else if(args[i].equals("-mouseConfine")) {
mouseConfined = true;
+ } else if(args[i].equals("-pointerIcon")) {
+ setPointerIcon = true;
} else if(args[i].equals("-showFPS")) {
showFPS = true;
} else if(args[i].equals("-width")) {
@@ -309,6 +667,17 @@ public class TestGearsES2NEWT extends UITestCase {
i++;
y = MiscUtils.atoi(args[i], y);
usePos = true;
+ } else if(args[i].equals("-pixelScale")) {
+ i++;
+ final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+ reqSurfacePixelScale[0] = pS;
+ reqSurfacePixelScale[1] = pS;
+ } else if(args[i].equals("-rwidth")) {
+ i++;
+ rw = MiscUtils.atoi(args[i], rw);
+ } else if(args[i].equals("-rheight")) {
+ i++;
+ rh = MiscUtils.atoi(args[i], rh);
} else if(args[i].equals("-screen")) {
i++;
screenIdx = MiscUtils.atoi(args[i], 0);
@@ -317,34 +686,47 @@ public class TestGearsES2NEWT extends UITestCase {
loops = MiscUtils.atoi(args[i], 1);
} else if(args[i].equals("-loop-shutdown")) {
loop_shutdown = true;
+ } else if(args[i].equals("-sysExit")) {
+ i++;
+ sysExit = SysExit.valueOf(args[i]);
+ } else if(args[i].equals("-manual")) {
+ manualTest = true;
}
}
wsize = new Dimension(w, h);
-
+ if( 0 < rw && 0 < rh ) {
+ rwsize = new Dimension(rw, rh);
+ }
+
if(usePos) {
wpos = new Point(x, y);
}
System.err.println("position "+wpos);
System.err.println("size "+wsize);
+ System.err.println("resize "+rwsize);
System.err.println("screen "+screenIdx);
System.err.println("translucent "+(!opaque));
+ System.err.println("forceAlpha "+forceAlpha);
System.err.println("undecorated "+undecorated);
System.err.println("atop "+alwaysOnTop);
System.err.println("fullscreen "+fullscreen);
- System.err.println("pmvDirect "+(!pmvUseBackingArray));
- System.err.println("swapInterval "+swapInterval);
System.err.println("mouseVisible "+mouseVisible);
System.err.println("mouseConfined "+mouseConfined);
+ System.err.println("pointerIcon "+setPointerIcon);
System.err.println("loops "+loops);
System.err.println("loop shutdown "+loop_shutdown);
System.err.println("forceES2 "+forceES2);
+ System.err.println("forceES3 "+forceES3);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("forceGL2 "+forceGL2);
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("exclusiveContext "+exclusiveContext);
+ System.err.println("useAnimator "+useAnimator);
+ System.err.println("sysExitWithin "+sysExit);
+ System.err.println("mappedBuffers "+useMappedBuffers);
if(waitForKey) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
- System.err.println("Press enter to continue");
- try {
- System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ JunitTracer.waitForKey("Start");
}
org.junit.runner.JUnitCore.main(TestGearsES2NEWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java
new file mode 100644
index 000000000..2dca3ad5e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java
@@ -0,0 +1,550 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Frame;
+import java.awt.TextArea;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter;
+
+import javax.media.nativewindow.ScalableSurface;
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGearsES2NewtCanvasAWT extends UITestCase {
+ public enum FrameLayout { None, TextOnBottom, BorderBottom, BorderBottom2, BorderCenter, BorderCenterSurrounded, DoubleBorderCenterSurrounded };
+ public enum ResizeBy { GLWindow, Component, Frame };
+
+ static int screenIdx = 0;
+ static PointImmutable wpos;
+ static DimensionImmutable wsize, rwsize = null;
+ static FrameLayout frameLayout = FrameLayout.None;
+ static ResizeBy resizeBy = ResizeBy.Component;
+ static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+
+ static long duration = 500; // ms
+ static boolean opaque = true;
+ static int forceAlpha = -1;
+ static boolean fullscreen = false;
+ static int swapInterval = 1;
+ static boolean showFPS = false;
+ static int loops = 1;
+ static boolean loop_shutdown = false;
+ static boolean shallUseOffscreenFBOLayer = false;
+ static boolean forceES2 = false;
+ static boolean forceGL3 = false;
+ static boolean manualTest = false;
+ static boolean exclusiveContext = false;
+ static boolean useAnimator = true;
+
+ @BeforeClass
+ public static void initClass() {
+ if(null == wsize) {
+ wsize = new Dimension(640, 480);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ static void setGLWindowSize(final Frame frame, final GLWindow glw, final DimensionImmutable new_sz) {
+ try {
+ glw.setSize(new_sz.getWidth(), new_sz.getHeight());
+ if( null != frame ) {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ } } );
+ }
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+ static void setComponentSize(final Frame frame, final Component comp, final DimensionImmutable new_sz) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final java.awt.Dimension d = new java.awt.Dimension(new_sz.getWidth(), new_sz.getHeight());
+ comp.setMinimumSize(d);
+ comp.setPreferredSize(d);
+ comp.setSize(d);
+ if( null != frame ) {
+ frame.pack();
+ }
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+ static void setFrameSize(final Frame frame, final boolean frameLayout, final DimensionImmutable new_sz) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final java.awt.Dimension d = new java.awt.Dimension(new_sz.getWidth(), new_sz.getHeight());
+ frame.setSize(d);
+ if( frameLayout ) {
+ frame.validate();
+ }
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ static void setSize(final ResizeBy resizeBy, final Frame frame, final boolean frameLayout, final Component comp, final GLWindow glw, final DimensionImmutable new_sz) {
+ switch( resizeBy ) {
+ case GLWindow:
+ setGLWindowSize(frameLayout ? frame : null, glw, new_sz);
+ break;
+ case Component:
+ setComponentSize(frameLayout ? frame : null, comp, new_sz);
+ break;
+ case Frame:
+ setFrameSize(frame, frameLayout, new_sz);
+ break;
+ }
+ }
+
+ private void setTitle(final Frame frame, final NewtCanvasAWT glc, final Window win, final GLCapabilitiesImmutable caps) {
+ final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl";
+ {
+ final java.awt.Rectangle b = glc.getBounds();
+ frame.setTitle("NewtCanvasAWT["+capsA+"], swapI "+swapInterval+", win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getNativeWindow().getSurfaceWidth()+"x"+glc.getNativeWindow().getSurfaceHeight());
+ }
+ final float[] sDPI = win.getPixelsPerMM(new float[2]);
+ sDPI[0] *= 25.4f;
+ sDPI[1] *= 25.4f;
+ win.setTitle("GLWindow["+capsA+"], swapI "+swapInterval+", win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]);
+ }
+
+ // public enum ResizeBy { GLWindow, Component, Frame };
+ protected void runTestGL(final GLCapabilitiesImmutable caps, final ResizeBy resizeBy, final FrameLayout frameLayout) throws InterruptedException, InvocationTargetException {
+ System.err.println("requested: vsync "+swapInterval+", "+caps);
+ final Display dpy = NewtFactory.createDisplay(null);
+ final Screen screen = NewtFactory.createScreen(dpy, screenIdx);
+ final GLWindow glWindow = GLWindow.create(screen, caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
+
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ if ( shallUseOffscreenFBOLayer ) {
+ newtCanvasAWT.setShallUseOffscreenLayer(true);
+ }
+
+ final Frame frame = new Frame("AWT Parent Frame");
+
+ setSize(resizeBy, frame, false, newtCanvasAWT, glWindow, wsize);
+
+ switch( frameLayout) {
+ case None:
+ frame.add(newtCanvasAWT);
+ break;
+ case TextOnBottom:
+ final TextArea ta = new TextArea(2, 20);
+ ta.append("0123456789");
+ ta.append(Platform.getNewline());
+ ta.append("Some Text");
+ ta.append(Platform.getNewline());
+ frame.setLayout(new BorderLayout());
+ frame.add(ta, BorderLayout.SOUTH);
+ frame.add(newtCanvasAWT, BorderLayout.CENTER);
+ break;
+ case BorderBottom:
+ frame.setLayout(new BorderLayout());
+ frame.add(newtCanvasAWT, BorderLayout.SOUTH);
+ break;
+ case BorderBottom2:
+ frame.setLayout(new BorderLayout());
+ frame.add(newtCanvasAWT, BorderLayout.SOUTH);
+ frame.add(new Button("North"), BorderLayout.NORTH);
+ break;
+ case BorderCenter:
+ frame.setLayout(new BorderLayout());
+ frame.add(newtCanvasAWT, BorderLayout.CENTER);
+ break;
+ case BorderCenterSurrounded:
+ frame.setLayout(new BorderLayout());
+ frame.add(new Button("NORTH"), BorderLayout.NORTH);
+ frame.add(new Button("SOUTH"), BorderLayout.SOUTH);
+ frame.add(new Button("EAST"), BorderLayout.EAST);
+ frame.add(new Button("WEST"), BorderLayout.WEST);
+ frame.add(newtCanvasAWT, BorderLayout.CENTER);
+ break;
+ case DoubleBorderCenterSurrounded:
+ final Container c = new Container();
+ c.setLayout(new BorderLayout());
+ c.add(new Button("north"), BorderLayout.NORTH);
+ c.add(new Button("south"), BorderLayout.SOUTH);
+ c.add(new Button("east"), BorderLayout.EAST);
+ c.add(new Button("west"), BorderLayout.WEST);
+ c.add(newtCanvasAWT, BorderLayout.CENTER);
+
+ frame.setLayout(new BorderLayout());
+ frame.add(new Button("NORTH"), BorderLayout.NORTH);
+ frame.add(new Button("SOUTH"), BorderLayout.SOUTH);
+ frame.add(new Button("EAST"), BorderLayout.EAST);
+ frame.add(new Button("WEST"), BorderLayout.WEST);
+ frame.add(c, BorderLayout.CENTER);
+ break;
+ }
+
+ final GearsES2 demo = new GearsES2(swapInterval);
+ glWindow.addGLEventListener(demo);
+
+ frame.addComponentListener(new ComponentListener() {
+ @Override
+ public void componentResized(final ComponentEvent e) {
+ setTitle(frame, newtCanvasAWT, glWindow, caps);
+ }
+
+ @Override
+ public void componentMoved(final ComponentEvent e) {
+ setTitle(frame, newtCanvasAWT, glWindow, caps);
+ }
+
+ @Override
+ public void componentShown(final ComponentEvent e) { }
+
+ @Override
+ public void componentHidden(final ComponentEvent e) { }
+ });
+
+ final Animator animator = useAnimator ? new Animator() : null;
+ if( useAnimator ) {
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.setExclusiveContext(exclusiveContext);
+ }
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
+ //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ glWindow.addWindowListener(new WindowAdapter() {
+ public void windowResized(final WindowEvent e) {
+ System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ public void windowMoved(final WindowEvent e) {
+ System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ });
+
+ glWindow.addKeyListener(new NewtAWTReparentingKeyAdapter(frame, newtCanvasAWT, glWindow, quitAdapter));
+ glWindow.addKeyListener(new com.jogamp.newt.event.KeyAdapter() {
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='x') {
+ final int[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]);
+ final int[] reqSurfacePixelScale;
+ if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
+ reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+ } else {
+ reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ }
+ System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
+ glWindow.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
+ final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 });
+ final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]);
+ System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
+ reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ setTitle(frame, newtCanvasAWT, glWindow, caps);
+ Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
+ }
+ } } );
+
+ if( useAnimator ) {
+ animator.add(glWindow);
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread());
+ }
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ if( ResizeBy.Frame == resizeBy ) {
+ frame.validate();
+ } else {
+ frame.pack();
+ }
+ frame.setVisible(true);
+ }
+ });
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true));
+
+ if( useAnimator ) {
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+ }
+
+ System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
+ System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+
+ final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 });
+ final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]);
+ System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ setTitle(frame, newtCanvasAWT, glWindow, caps);
+ Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
+
+ if( null != rwsize ) {
+ Thread.sleep(500); // 500ms delay
+ setSize(resizeBy, frame, true, newtCanvasAWT, glWindow, rwsize);
+ System.err.println("window resize "+rwsize+" -> pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+ }
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1-t0<duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ if( useAnimator ) {
+ Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread());
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ }
+ Assert.assertEquals(null, glWindow.getExclusiveContextThread());
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.dispose();
+ }
+ });
+ glWindow.destroy();
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
+ }
+
+ @Test
+ public void test01GL2ES2() throws InterruptedException, InvocationTargetException {
+ for(int i=1; i<=loops; i++) {
+ System.err.println("Loop "+i+"/"+loops);
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ final GLCapabilities caps = new GLCapabilities( glp );
+ caps.setBackgroundOpaque(opaque);
+ if(-1 < forceAlpha) {
+ caps.setAlphaBits(forceAlpha);
+ }
+ runTestGL(caps, resizeBy, frameLayout);
+ if(loop_shutdown) {
+ GLProfile.shutdown();
+ }
+ }
+ }
+
+ @Test
+ public void test02GL3() throws InterruptedException, InvocationTargetException {
+ if(manualTest) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, resizeBy, frameLayout);
+ }
+
+ @Test
+ public void test99_PixelScale1_DefaultNorm() throws InterruptedException, InvocationTargetException {
+ if( manualTest ) return;
+
+ reqSurfacePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ reqSurfacePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ runTestGL(caps, resizeBy, frameLayout);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ int x=0, y=0, w=640, h=480;
+ int rw=-1, rh=-1;
+ boolean usePos = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-rwidth")) {
+ i++;
+ rw = MiscUtils.atoi(args[i], rw);
+ } else if(args[i].equals("-rheight")) {
+ i++;
+ rh = MiscUtils.atoi(args[i], rh);
+ } else if(args[i].equals("-layout")) {
+ i++;
+ frameLayout = FrameLayout.valueOf(args[i]);
+ } else if(args[i].equals("-resizeBy")) {
+ i++;
+ resizeBy = ResizeBy.valueOf(args[i]);
+ } else if(args[i].equals("-translucent")) {
+ opaque = false;
+ } else if(args[i].equals("-forceAlpha")) {
+ i++;
+ forceAlpha = MiscUtils.atoi(args[i], 0);
+ } else if(args[i].equals("-fullscreen")) {
+ fullscreen = true;
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-layeredFBO")) {
+ shallUseOffscreenFBOLayer = true;
+ } else if(args[i].equals("-exclctx")) {
+ exclusiveContext = true;
+ } else if(args[i].equals("-noanim")) {
+ useAnimator = false;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-showFPS")) {
+ showFPS = true;
+ } else if(args[i].equals("-width")) {
+ i++;
+ w = MiscUtils.atoi(args[i], w);
+ } else if(args[i].equals("-height")) {
+ i++;
+ h = MiscUtils.atoi(args[i], h);
+ } else if(args[i].equals("-x")) {
+ i++;
+ x = MiscUtils.atoi(args[i], x);
+ usePos = true;
+ } else if(args[i].equals("-y")) {
+ i++;
+ y = MiscUtils.atoi(args[i], y);
+ usePos = true;
+ } else if(args[i].equals("-pixelScale")) {
+ i++;
+ final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+ reqSurfacePixelScale[0] = pS;
+ reqSurfacePixelScale[1] = pS;
+ } else if(args[i].equals("-screen")) {
+ i++;
+ screenIdx = MiscUtils.atoi(args[i], 0);
+ } else if(args[i].equals("-loops")) {
+ i++;
+ loops = MiscUtils.atoi(args[i], 1);
+ } else if(args[i].equals("-loop-shutdown")) {
+ loop_shutdown = true;
+ } else if(args[i].equals("-manual")) {
+ manualTest = true;
+ }
+ }
+ wsize = new Dimension(w, h);
+ if( 0 < rw && 0 < rh ) {
+ rwsize = new Dimension(rw, rh);
+ }
+
+ if(usePos) {
+ wpos = new Point(x, y);
+ }
+
+ System.err.println("frameLayout "+frameLayout);
+ System.err.println("resizeBy "+resizeBy);
+ System.err.println("position "+wpos);
+ System.err.println("size "+wsize);
+ System.err.println("resize "+rwsize);
+ System.err.println("screen "+screenIdx);
+ System.err.println("translucent "+(!opaque));
+ System.err.println("forceAlpha "+forceAlpha);
+ System.err.println("fullscreen "+fullscreen);
+ System.err.println("loops "+loops);
+ System.err.println("loop shutdown "+loop_shutdown);
+ System.err.println("shallUseOffscreenFBOLayer "+shallUseOffscreenFBOLayer);
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("exclusiveContext "+exclusiveContext);
+ System.err.println("useAnimator "+useAnimator);
+
+ org.junit.runner.JUnitCore.main(TestGearsES2NewtCanvasAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java
new file mode 100644
index 000000000..c3c7d68b3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java
@@ -0,0 +1,377 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.swt.NewtCanvasSWT;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGearsES2NewtCanvasSWT extends UITestCase {
+ static int screenIdx = 0;
+ static PointImmutable wpos;
+ static DimensionImmutable wsize, rwsize = null;
+
+ static long duration = 500; // ms
+ static boolean opaque = true;
+ static int forceAlpha = -1;
+ static boolean fullscreen = false;
+ static int swapInterval = 1;
+ static boolean showFPS = false;
+ static int loops = 1;
+ static boolean loop_shutdown = false;
+ static boolean forceES2 = false;
+ static boolean forceGL3 = false;
+ static boolean mainRun = false;
+ static boolean exclusiveContext = false;
+
+ @BeforeClass
+ public static void initClass() {
+ if(null == wsize) {
+ wsize = new Dimension(640, 480);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ Display display = null;
+ Shell shell = null;
+ Composite composite = null;
+ com.jogamp.newt.Display swtNewtDisplay = null;
+
+ @Before
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ }});
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.NONE );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ }});
+ swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+ try {
+ display.syncExec(new Runnable() {
+ public void run() {
+ composite.dispose();
+ shell.dispose();
+ }});
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display.dispose();
+ }});
+ }
+ catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ swtNewtDisplay = null;
+ display = null;
+ shell = null;
+ composite = null;
+ }
+
+ protected void runTestGL(final GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException {
+ System.err.println("requested: vsync "+swapInterval+", "+caps);
+ final com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, screenIdx);
+ final GLWindow glWindow = GLWindow.create(screen, caps);
+ Assert.assertNotNull(glWindow);
+
+ final GearsES2 demo = new GearsES2(swapInterval);
+ glWindow.addGLEventListener(demo);
+
+ final Animator animator = new Animator();
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.setExclusiveContext(exclusiveContext);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
+ //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ glWindow.addWindowListener(new WindowAdapter() {
+ public void windowResized(final WindowEvent e) {
+ System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ public void windowMoved(final WindowEvent e) {
+ System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ });
+
+ glWindow.addKeyListener(new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='f') {
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setExclusiveContextThread(t);
+ } }.start();
+ }
+ }
+ });
+
+ animator.add(glWindow);
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread());
+
+ final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite, 0, glWindow );
+ Assert.assertNotNull( canvas1 );
+
+ display.syncExec( new Runnable() {
+ public void run() {
+ shell.setText( getSimpleTestName(".") );
+ shell.setSize( wsize.getWidth(), wsize.getHeight() );
+ if( null != wpos ) {
+ shell.setLocation( wpos.getX(), wpos.getY() );
+ }
+ shell.open();
+ }
+ });
+
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+
+ System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
+ System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+
+ if( null != rwsize ) {
+ for(int i=0; i<50; i++) { // 500 ms dispatched delay
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ Thread.sleep(10);
+ }
+ }
+ display.syncExec( new Runnable() {
+ public void run() {
+ shell.setSize( rwsize.getWidth(), rwsize.getHeight() );
+ }
+ });
+ System.err.println("window resize pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+ }
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ Thread.sleep(10);
+ }
+ }
+
+ Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread());
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ Assert.assertEquals(null, glWindow.getExclusiveContextThread());
+
+ canvas1.dispose();
+ glWindow.destroy();
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
+ }
+
+ @Test
+ public void test01GL2ES2() throws InterruptedException, InvocationTargetException {
+ for(int i=1; i<=loops; i++) {
+ System.err.println("Loop "+i+"/"+loops);
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ final GLCapabilities caps = new GLCapabilities( glp );
+ caps.setBackgroundOpaque(opaque);
+ if(-1 < forceAlpha) {
+ caps.setAlphaBits(forceAlpha);
+ }
+ runTestGL(caps);
+ if(loop_shutdown) {
+ GLProfile.shutdown();
+ }
+ }
+ }
+
+ @Test
+ public void test02GL3() throws InterruptedException, InvocationTargetException {
+ if(mainRun) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ mainRun = true;
+
+ int x=0, y=0, w=640, h=480, rw=-1, rh=-1;
+ boolean usePos = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-translucent")) {
+ opaque = false;
+ } else if(args[i].equals("-forceAlpha")) {
+ i++;
+ forceAlpha = MiscUtils.atoi(args[i], 0);
+ } else if(args[i].equals("-fullscreen")) {
+ fullscreen = true;
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-exclctx")) {
+ exclusiveContext = true;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-showFPS")) {
+ showFPS = true;
+ } else if(args[i].equals("-width")) {
+ i++;
+ w = MiscUtils.atoi(args[i], w);
+ } else if(args[i].equals("-height")) {
+ i++;
+ h = MiscUtils.atoi(args[i], h);
+ } else if(args[i].equals("-x")) {
+ i++;
+ x = MiscUtils.atoi(args[i], x);
+ usePos = true;
+ } else if(args[i].equals("-y")) {
+ i++;
+ y = MiscUtils.atoi(args[i], y);
+ usePos = true;
+ } else if(args[i].equals("-rwidth")) {
+ i++;
+ rw = MiscUtils.atoi(args[i], rw);
+ } else if(args[i].equals("-rheight")) {
+ i++;
+ rh = MiscUtils.atoi(args[i], rh);
+ } else if(args[i].equals("-screen")) {
+ i++;
+ screenIdx = MiscUtils.atoi(args[i], 0);
+ } else if(args[i].equals("-loops")) {
+ i++;
+ loops = MiscUtils.atoi(args[i], 1);
+ } else if(args[i].equals("-loop-shutdown")) {
+ loop_shutdown = true;
+ }
+ }
+ wsize = new Dimension(w, h);
+ if( 0 < rw && 0 < rh ) {
+ rwsize = new Dimension(rw, rh);
+ }
+
+ if(usePos) {
+ wpos = new Point(x, y);
+ }
+ System.err.println("position "+wpos);
+ System.err.println("size "+wsize);
+ System.err.println("resize "+rwsize);
+ System.err.println("screen "+screenIdx);
+ System.err.println("translucent "+(!opaque));
+ System.err.println("forceAlpha "+forceAlpha);
+ System.err.println("fullscreen "+fullscreen);
+ System.err.println("loops "+loops);
+ System.err.println("loop shutdown "+loop_shutdown);
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("exclusiveContext "+exclusiveContext);
+
+ org.junit.runner.JUnitCore.main(TestGearsES2NewtCanvasSWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java
new file mode 100644
index 000000000..7f2bf7881
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
+
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestLandscapeES2NEWT extends UITestCase {
+ static int width = 500, height = 290;
+ static int swapInterval = 1;
+ static boolean forceES2 = false;
+ static boolean forceGL3 = false;
+ static boolean mainRun = false;
+ static boolean exclusiveContext = false;
+ static boolean useAnimator = true;
+
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException {
+ System.err.println("requested: swapInterval "+swapInterval+", "+caps);
+ final GLWindow glWindow = GLWindow.create(caps);
+ glWindow.setTitle(getSimpleTestName("."));
+ glWindow.setSize(width, height);
+
+ final LandscapeES2 demo = new LandscapeES2(swapInterval);
+ glWindow.addGLEventListener(demo);
+
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ snap.setPostSNDetail(demo.getClass().getSimpleName());
+ glWindow.addGLEventListener(snap);
+
+ final Animator animator = useAnimator ? new Animator() : null;
+ if( useAnimator ) {
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.setExclusiveContext(exclusiveContext);
+ }
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
+ //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ glWindow.addKeyListener(new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='f') {
+ new Thread() {
+ public void run() {
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ } }.start();
+ } else if(e.getKeyChar()=='d') {
+ new Thread() {
+ public void run() {
+ glWindow.setUndecorated(!glWindow.isUndecorated());
+ } }.start();
+ }
+ }
+ });
+
+ if( useAnimator ) {
+ animator.add(glWindow);
+ animator.start();
+ }
+ glWindow.setVisible(true);
+ if( useAnimator ) {
+ animator.setUpdateFPSFrames(60, System.err);
+ }
+
+ System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
+ System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+
+ snap.setMakeSnapshot();
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ if( useAnimator ) {
+ animator.stop();
+ }
+ glWindow.destroy();
+ }
+
+ @Test
+ public void test01GL2ES2() throws InterruptedException {
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test02GL3() throws InterruptedException {
+ if(mainRun) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
+ static long duration = 1000; // ms
+
+ public static void main(final String args[]) {
+ mainRun = true;
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-exclctx")) {
+ exclusiveContext = true;
+ } else if(args[i].equals("-noanim")) {
+ useAnimator = false;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ }
+ }
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceGL3 "+forceGL3);
+ org.junit.runner.JUnitCore.main(TestLandscapeES2NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java
new file mode 100644
index 000000000..5b64ce3f3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java
@@ -0,0 +1,222 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
+
+import java.awt.Frame;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2;
+import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+import javax.swing.SwingUtilities;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestLandscapeES2NewtCanvasAWT extends UITestCase {
+ static DimensionImmutable wsize = new Dimension(500, 290);
+
+ static long duration = 1000; // ms
+ static int swapInterval = 1;
+ static boolean shallUseOffscreenFBOLayer = false;
+ static boolean forceES2 = false;
+ static boolean forceGL3 = false;
+ static boolean mainRun = false;
+ static boolean exclusiveContext = false;
+ static boolean useAnimator = true;
+
+ // public enum ResizeBy { GLWindow, Component, Frame };
+ protected void runTestGL(final GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException {
+ System.err.println("requested: vsync "+swapInterval+", "+caps);
+ final Display dpy = NewtFactory.createDisplay(null);
+ final Screen screen = NewtFactory.createScreen(dpy, 0);
+ final GLWindow glWindow = GLWindow.create(screen, caps);
+
+ // Enforce landscape shader to be linked once,
+ // since on some platforms (Mesa/AMD) it takes a long time!
+ final LandscapeES2 demo = new LandscapeES2(swapInterval);
+ glWindow.addGLEventListener(demo);
+ glWindow.setVisible(true);
+ glWindow.display();
+
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ if ( shallUseOffscreenFBOLayer ) {
+ newtCanvasAWT.setShallUseOffscreenLayer(true);
+ }
+
+ final Frame frame = new Frame("AWT Parent Frame");
+ {
+ final java.awt.Dimension d = new java.awt.Dimension(wsize.getWidth(), wsize.getHeight());
+ frame.setSize(d);
+ }
+ frame.add(newtCanvasAWT);
+ frame.setTitle("Gears NewtCanvasAWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval+", size "+wsize);
+
+ final Animator animator = useAnimator ? new Animator() : null;
+ if( useAnimator ) {
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.setExclusiveContext(exclusiveContext);
+ }
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
+ //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ glWindow.addWindowListener(new WindowAdapter() {
+ public void windowResized(final WindowEvent e) {
+ System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ public void windowMoved(final WindowEvent e) {
+ System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ });
+
+ glWindow.addKeyListener(new NewtAWTReparentingKeyAdapter(frame, newtCanvasAWT, glWindow, quitAdapter));
+
+ if( useAnimator ) {
+ animator.add(glWindow);
+ animator.start();
+ }
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.validate();
+ frame.setVisible(true);
+ }
+ });
+
+ if( useAnimator ) {
+ animator.setUpdateFPSFrames(60, System.err);
+ }
+
+ System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
+ System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1-t0<duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ if( useAnimator ) {
+ animator.stop();
+ }
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.dispose();
+ }
+ });
+ glWindow.destroy(); // removeNotify does not destroy GLWindow
+ }
+
+ @Test
+ public void test01GL2ES2() throws InterruptedException, InvocationTargetException {
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test02GL3() throws InterruptedException, InvocationTargetException {
+ if(mainRun) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ mainRun = true;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-layeredFBO")) {
+ shallUseOffscreenFBOLayer = true;
+ } else if(args[i].equals("-exclctx")) {
+ exclusiveContext = true;
+ } else if(args[i].equals("-noanim")) {
+ useAnimator = false;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ }
+ }
+
+ System.err.println("size "+wsize);
+ System.err.println("shallUseOffscreenFBOLayer "+shallUseOffscreenFBOLayer);
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("exclusiveContext "+exclusiveContext);
+ System.err.println("useAnimator "+useAnimator);
+
+ org.junit.runner.JUnitCore.main(TestLandscapeES2NewtCanvasAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java
index f0c3bb684..52f4473c3 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
import com.jogamp.newt.event.KeyAdapter;
@@ -35,26 +35,33 @@ import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
-
import com.jogamp.opengl.util.Animator;
-
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareMappedES2;
+import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestRedSquareES2NEWT extends UITestCase {
static int width, height;
static int loops = 1;
static boolean loop_shutdown = false;
static boolean vsync = false;
static boolean forceES2 = false;
+ static boolean forceGL3 = false;
+ static boolean mainRun = false;
static boolean doRotate = true;
+ static boolean useMappedBuffers = false;
@BeforeClass
public static void initClass() {
@@ -66,52 +73,67 @@ public class TestRedSquareES2NEWT extends UITestCase {
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilities caps) throws InterruptedException {
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException {
System.err.println("requested: vsync "+vsync+", "+caps);
- GLWindow glWindow = GLWindow.create(caps);
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
- glWindow.setTitle("Gears NEWT Test");
+ glWindow.setTitle(getSimpleTestName("."));
glWindow.setSize(width, height);
- final RedSquareES2 demo = new RedSquareES2(vsync ? 1 : -1);
- demo.setDoRotation(doRotate);
+ final GLEventListener demo;
+ if( useMappedBuffers ) {
+ final RedSquareMappedES2 red = new RedSquareMappedES2(vsync ? 1 : -1);
+ red.setDoRotation(doRotate);
+ demo = red;
+ } else {
+ final RedSquareES2 red = new RedSquareES2(vsync ? 1 : -1);
+ red.setDoRotation(doRotate);
+ demo = red;
+ }
glWindow.addGLEventListener(demo);
- Animator animator = new Animator(glWindow);
- QuitAdapter quitAdapter = new QuitAdapter();
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ snap.setPostSNDetail(demo.getClass().getSimpleName());
+ glWindow.addGLEventListener(snap);
+
+ final Animator animator = new Animator(glWindow);
+ final QuitAdapter quitAdapter = new QuitAdapter();
//glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
//glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
glWindow.addKeyListener(quitAdapter);
glWindow.addWindowListener(quitAdapter);
- final GLWindow f_glWindow = glWindow;
glWindow.addKeyListener(new KeyAdapter() {
- public void keyTyped(KeyEvent e) {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
if(e.getKeyChar()=='f') {
new Thread() {
public void run() {
- f_glWindow.setFullscreen(!f_glWindow.isFullscreen());
+ glWindow.setFullscreen(!glWindow.isFullscreen());
} }.start();
} else if(e.getKeyChar()=='d') {
new Thread() {
public void run() {
- f_glWindow.setUndecorated(!f_glWindow.isUndecorated());
+ glWindow.setUndecorated(!glWindow.isUndecorated());
} }.start();
}
}
});
animator.start();
-
+
glWindow.setVisible(true);
System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
- System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets());
-
+ System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+
animator.setUpdateFPSFrames(60, System.err);
-
+ snap.setMakeSnapshot();
+
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
}
@@ -120,14 +142,24 @@ public class TestRedSquareES2NEWT extends UITestCase {
Assert.assertFalse(animator.isAnimating());
Assert.assertFalse(animator.isStarted());
glWindow.destroy();
- Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
+ if( NativeWindowFactory.isAWTAvailable() ) {
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
+ }
}
@Test
public void test01GL2ES2() throws InterruptedException {
for(int i=1; i<=loops; i++) {
System.err.println("Loop "+i+"/"+loops);
- GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2());
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
runTestGL(caps);
if(loop_shutdown) {
GLProfile.shutdown();
@@ -135,19 +167,35 @@ public class TestRedSquareES2NEWT extends UITestCase {
}
}
+ @Test
+ public void test02GL3() throws InterruptedException {
+ if(mainRun) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
static long duration = 500; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
+ mainRun = true;
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
- try {
- duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ duration = MiscUtils.atol(args[i], duration);
} else if(args[i].equals("-es2")) {
forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
} else if(args[i].equals("-norotate")) {
doRotate = false;
+ } else if(args[i].equals("-mappedBuffers")) {
+ useMappedBuffers = true;
} else if(args[i].equals("-loops")) {
i++;
loops = MiscUtils.atoi(args[i], 1);
@@ -155,9 +203,12 @@ public class TestRedSquareES2NEWT extends UITestCase {
loop_shutdown = true;
}
}
+ System.err.println("duration "+duration);
System.err.println("loops "+loops);
System.err.println("loop shutdown "+loop_shutdown);
System.err.println("forceES2 "+forceES2);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("mappedBuffers "+useMappedBuffers);
org.junit.runner.JUnitCore.main(TestRedSquareES2NEWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.fp
new file mode 100644
index 000000000..3210762b1
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.fp
@@ -0,0 +1,47 @@
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+// [0].rgba: 0, smooth, attnMinSz, attnMaxSz
+// [1].rgba: attnCoeff(3), attnFadeTs
+uniform vec4 mgl_PointParams[2];
+
+#define pointSmooth (mgl_PointParams[0].g)
+
+varying vec4 frontColor;
+
+// #define TEST 1
+
+void main (void)
+{
+ mgl_FragColor = frontColor;
+
+ if( pointSmooth > 0.5 ) {
+ // smooth (AA)
+ const float border = 0.90; // take/give 10% for AA
+
+ // origin to 0/0, [-1/-1 .. 1/1]
+ vec2 pointPos = 2.0 * gl_PointCoord - 1.0 ;
+ float r = length( pointPos ); // one-circle sqrt(x * x + y * y), range: in-circle [0..1], out >1
+ float r1 = 1.0 - ( step(border, r) * 10.0 * ( r - border ) ) ; // [0..1]
+ #ifndef TEST
+ if( r1 < 0.0 ) {
+ discard;
+ }
+ #endif
+
+ #ifndef TEST
+ mgl_FragColor.a *= r1;
+ #else
+ mgl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ mgl_FragColor.r = r1 < 0.0 ? 1.0 : 0.0;
+ mgl_FragColor.g = r > 1.0 ? 1.0 : 0.0;
+ mgl_FragColor.b = r > border ? 1.0 : 0.0;
+ #endif
+ }
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.vp
new file mode 100644
index 000000000..4fa49b901
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.vp
@@ -0,0 +1,47 @@
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec4 mgl_ColorStatic;
+uniform mat4 mgl_PMVMatrix[4]; // P, Mv, Mvi and Mvit (transpose(inverse(ModelView)) == normalMatrix)
+
+// [0].rgba: 0, smooth, attnMinSz, attnMaxSz
+// [1].rgba: attnCoeff(3), attnFadeTs
+uniform vec4 mgl_PointParams[2];
+
+#define pointSmooth (mgl_PointParams[0].g)
+#define pointSizeMin (mgl_PointParams[0].b)
+#define pointSizeMax (mgl_PointParams[0].a)
+#define pointDistanceConstantAtten (mgl_PointParams[1].r)
+#define pointDistanceLinearAtten (mgl_PointParams[1].g)
+#define pointDistanceQuadraticAtten (mgl_PointParams[1].b)
+#define pointFadeThresholdSize (mgl_PointParams[1].a)
+
+attribute vec4 mgl_Vertex;
+attribute float mgl_PointSize;
+
+varying vec4 frontColor;
+
+void main(void)
+{
+ frontColor = mgl_ColorStatic;
+
+ vec4 eyeCoord = mgl_PMVMatrix[1] * mgl_Vertex;
+ gl_Position = mgl_PMVMatrix[0] * eyeCoord;
+
+ float dist = distance(eyeCoord, vec4(0.0, 0.0, 0.0, 1.0));
+ float atten = sqrt( 1.0 / ( pointDistanceConstantAtten +
+ ( pointDistanceLinearAtten +
+ pointDistanceQuadraticAtten * dist
+ ) * dist
+ )
+ );
+ float size = clamp(mgl_PointSize * atten, pointSizeMin, pointSizeMax);
+ gl_PointSize = max(size, pointFadeThresholdSize);
+
+ float fade = min(size, pointFadeThresholdSize) / pointFadeThresholdSize;
+ frontColor.a *= fade * fade;
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp
index d3cfecd94..60b92401e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp
@@ -1,23 +1,16 @@
// Copyright 2010 JogAmp Community. All rights reserved.
-/**
- * AMD complains: #version must occur before any other statement in the program
-#ifdef GL_ES
- #version 100
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
#else
- #version 110
+ #define mgl_FragColor gl_FragColor
#endif
- */
-#ifdef GL_ES
- precision mediump float;
- precision mediump int;
-#endif
-
-varying vec4 frontColor;
+varying vec4 frontColor;
void main (void)
{
- gl_FragColor = frontColor;
+ mgl_FragColor = frontColor;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.java
index cdbf3d9b8..9284ec48e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.java
@@ -29,12 +29,17 @@
package com.jogamp.opengl.test.junit.jogl.demos.es2.shader;
public class RedSquareShader {
- public static String VERTEX_SHADER_TEXT =
+ public static final String VERTEX_SHADER_TEXT =
" #ifdef GL_ES\n" +
" precision mediump float;\n" +
" precision mediump int;\n" +
"#endif\n" +
"\n" +
+ "#if __VERSION__ >= 130\n" +
+ " #define attribute in\n" +
+ " #define varying out\n" +
+ "#endif\n"+
+ "\n" +
"uniform mat4 mgl_PMVMatrix[2];\n" +
"attribute vec4 mgl_Vertex;\n" +
"attribute vec4 mgl_Color;\n" +
@@ -46,16 +51,23 @@ public class RedSquareShader {
" gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;\n" +
"}\n" ;
- public static String FRAGMENT_SHADER_TEXT =
+ public static final String FRAGMENT_SHADER_TEXT =
" #ifdef GL_ES\n" +
" precision mediump float;\n" +
" precision mediump int;\n" +
"#endif\n" +
"\n" +
+ "#if __VERSION__ >= 130\n" +
+ " #define varying in\n" +
+ " out vec4 mgl_FragColor;\n" +
+ "#else\n" +
+ " #define mgl_FragColor gl_FragColor\n" +
+ "#endif\n" +
+ "\n" +
"varying vec4 frontColor;\n" +
"\n" +
"void main (void)\n" +
"{\n" +
- " gl_FragColor = frontColor;\n" +
+ " mgl_FragColor = frontColor;\n" +
"}\n" ;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp
index bfd44c8f4..9283dd7bd 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp
@@ -1,17 +1,8 @@
// Copyright 2010 JogAmp Community. All rights reserved.
-/**
- * AMD complains: #version must occur before any other statement in the program
-#ifdef GL_ES
- #version 100
-#else
- #version 110
-#endif
- */
-
-#ifdef GL_ES
- precision mediump float;
- precision mediump int;
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
#endif
uniform mat4 mgl_PMVMatrix[2];
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp
index 01e4b0964..25a2df2d7 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp
@@ -1,26 +1,16 @@
// Copyright 2010 JogAmp Community. All rights reserved.
-/**
- * AMD complains: #version must occur before any other statement in the program
-#ifdef GL_ES
- #version 100
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
#else
- #version 110
+ #define mgl_FragColor gl_FragColor
#endif
- */
-#ifdef GL_ES
- #define MEDIUMP mediump
- #define HIGHP highp
-#else
- #define MEDIUMP
- #define HIGHP
-#endif
-
-varying HIGHP vec4 frontColor;
+varying vec4 frontColor;
void main (void)
{
- gl_FragColor = vec4(0.0, frontColor.g, frontColor.b, 1.0);
+ mgl_FragColor = vec4(0.0, frontColor.g, frontColor.b, 1.0);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/default.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/default.vp
index 99ad6e400..2037086f1 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/default.vp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/default.vp
@@ -1,5 +1,10 @@
//Copyright 2010 JogAmp Community. All rights reserved.
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
#ifdef GL_ES
#define MEDIUMP mediump
#define HIGHP highp
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp
index 22fb65e90..60f054b46 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp
@@ -9,6 +9,14 @@
* author: Dominik Stroehlein (DemoscenePassivist)
**/
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
#ifdef GL_ES
precision mediump float;
precision mediump sampler2D;
@@ -343,7 +351,7 @@ void main() {
color = raymarch_orbittrap_image(oglFragCoord.xy);
}
if (en==2 || en==7) {
- gl_FragColor = color;
+ mgl_FragColor = color;
} else {
//do normal rendering ...
//analog-tv distortion ...
@@ -376,6 +384,6 @@ void main() {
//tv flicker effect
color_tv *= 0.97+0.13*sin(2.5*tm);
color_tv *= br;
- gl_FragColor = vec4(color_tv,1.0);
+ mgl_FragColor = vec4(color_tv,1.0);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp
index d3df81994..77c34f74f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp
@@ -12,6 +12,14 @@
//When I wrote this, only God and I understood what I was doing ...
// ... now only God knows! X-)
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
uniform int en;
uniform float et;
uniform sampler2D fb;
@@ -209,7 +217,7 @@ void main() {
} else
n=D(c.xy);
if(en==2||en==7)
- gl_FragColor=n;
+ mgl_FragColor=n;
else {
vec2 i=c.xy/v.xy;
i.y*=-1.;
@@ -229,6 +237,6 @@ void main() {
x*=.9+.1*sin(1.5*tm+i.y*1000.);
x*=.97+.13*sin(2.5*tm);
x*=br;
- gl_FragColor=vec4(x,1.);
+ mgl_FragColor=vec4(x,1.);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.fp
index 1738d96d1..563e0a4b0 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.fp
@@ -1,11 +1,16 @@
//Copyright 2010 JogAmp Community. All rights reserved.
-#version 110
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragData[2];
+#else
+ #define mgl_FragData gl_FragData
+#endif
varying vec4 frontColor;
void main (void)
{
- gl_FragData[0] = vec4( frontColor.r, 0.0, 0.0, 1.0 );
- gl_FragData[1] = vec4( 0.0, frontColor.g, 0.0, 1.0 );
+ mgl_FragData[0] = vec4( frontColor.r, 0.0, 0.0, 1.0 );
+ mgl_FragData[1] = vec4( 0.0, frontColor.g, 0.0, 1.0 );
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.vp
index 7f95a650a..4cab59c64 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.vp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.vp
@@ -1,6 +1,9 @@
// Copyright 2010 JogAmp Community. All rights reserved.
-#version 110
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
uniform mat4 gcu_PMVMatrix[2]; // P, Mv, and Mvi
attribute vec4 gca_Vertices;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.fp
index deac58ce1..510096d66 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.fp
@@ -1,6 +1,12 @@
//Copyright 2010 JogAmp Community. All rights reserved.
-#version 110
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragData[2];
+ #define texture2D texture
+#else
+ #define mgl_FragData gl_FragData
+#endif
uniform sampler2D gcs_TexUnit0;
uniform sampler2D gcs_TexUnit1;
@@ -12,5 +18,5 @@ void main (void)
{
vec2 rg = texture2D(gcs_TexUnit0, texCoord).rg + texture2D(gcs_TexUnit1, texCoord).rg;
float b = frontColor.b - length(rg);
- gl_FragData[0] = vec4( rg, b, 1.0 );
-} \ No newline at end of file
+ mgl_FragData[0] = vec4( rg, b, 1.0 );
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.vp
index 1b2c02328..89290b05a 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.vp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.vp
@@ -1,6 +1,9 @@
//Copyright 2010 JogAmp Community. All rights reserved.
-#version 110
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
uniform mat4 gcu_PMVMatrix[2]; // P, Mv, and Mvi
attribute vec4 gca_Vertices;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.fp
index f41addad8..14328dc1e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.fp
@@ -1,9 +1,11 @@
// Copyright (C) 2011 JogAmp Community. All rights reserved.
// Details see GearsES2.java
-#ifdef GL_ES
- precision mediump float;
- precision mediump int;
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
#endif
uniform vec4 color;
@@ -42,5 +44,5 @@ void main()
specular += color * pow(NdotHV, matShininess) * attenuation * matSpecular;
}
- gl_FragColor = ambient + diffuse + specular ;
+ mgl_FragColor = ambient + diffuse + specular ;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.vp
index b2d77082b..24f4f9c52 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.vp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.vp
@@ -1,10 +1,11 @@
// Copyright (C) 2011 JogAmp Community. All rights reserved.
// Details see GearsES2.java
-#ifdef GL_ES
- precision mediump float;
- precision mediump int;
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
#endif
+
uniform mat4 pmvMatrix[4]; // P, Mv, Mvi and Mvit
uniform vec3 lightPos;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.fp
new file mode 100644
index 000000000..b19c057d3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.fp
@@ -0,0 +1,339 @@
+// Elevated shader
+// https://www.shadertoy.com/view/MdX3Rr by inigo quilez
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+uniform vec3 iResolution;
+uniform float iGlobalTime;
+
+// Created by inigo quilez - iq/2013
+// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
+
+//stereo thanks to Croqueteer
+//#define STEREO
+
+mat3 m = mat3( 0.00, 0.80, 0.60,
+ -0.80, 0.36, -0.48,
+ -0.60, -0.48, 0.64 );
+
+float hash( float n )
+{
+ return fract(sin(n)*43758.5453123);
+}
+
+
+float noise( in vec3 x )
+{
+ vec3 p = floor(x);
+ vec3 f = fract(x);
+
+ f = f*f*(3.0-2.0*f);
+
+ float n = p.x + p.y*57.0 + 113.0*p.z;
+
+ float res = mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x),
+ mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y),
+ mix(mix( hash(n+113.0), hash(n+114.0),f.x),
+ mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
+ return res;
+}
+
+
+
+
+vec3 noised( in vec2 x )
+{
+ vec2 p = floor(x);
+ vec2 f = fract(x);
+
+ vec2 u = f*f*(3.0-2.0*f);
+
+ float n = p.x + p.y*57.0;
+
+ float a = hash(n+ 0.0);
+ float b = hash(n+ 1.0);
+ float c = hash(n+ 57.0);
+ float d = hash(n+ 58.0);
+ return vec3(a+(b-a)*u.x+(c-a)*u.y+(a-b-c+d)*u.x*u.y,
+ 30.0*f*f*(f*(f-2.0)+1.0)*(vec2(b-a,c-a)+(a-b-c+d)*u.yx));
+
+}
+
+float noise( in vec2 x )
+{
+ vec2 p = floor(x);
+ vec2 f = fract(x);
+
+ f = f*f*(3.0-2.0*f);
+
+ float n = p.x + p.y*57.0;
+
+ float res = mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x),
+ mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y);
+
+ return res;
+}
+
+float fbm( vec3 p )
+{
+ float f = 0.0;
+
+ f += 0.5000*noise( p ); p = m*p*2.02;
+ f += 0.2500*noise( p ); p = m*p*2.03;
+ f += 0.1250*noise( p ); p = m*p*2.01;
+ f += 0.0625*noise( p );
+
+ return f/0.9375;
+}
+
+mat2 m2 = mat2(1.6,-1.2,1.2,1.6);
+
+float fbm( vec2 p )
+{
+ float f = 0.0;
+
+ f += 0.5000*noise( p ); p = m2*p*2.02;
+ f += 0.2500*noise( p ); p = m2*p*2.03;
+ f += 0.1250*noise( p ); p = m2*p*2.01;
+ f += 0.0625*noise( p );
+
+ return f/0.9375;
+}
+
+float terrain( in vec2 x )
+{
+ vec2 p = x*0.003;
+ float a = 0.0;
+ float b = 1.0;
+ vec2 d = vec2(0.0);
+ for(int i=0;i<5; i++)
+ {
+ vec3 n = noised(p);
+ d += n.yz;
+ a += b*n.x/(1.0+dot(d,d));
+ b *= 0.5;
+ p=mat2(1.6,-1.2,1.2,1.6)*p;
+ }
+
+ return 140.0*a;
+}
+
+float terrain2( in vec2 x )
+{
+ vec2 p = x*0.003;
+ float a = 0.0;
+ float b = 1.0;
+ vec2 d = vec2(0.0);
+ for(int i=0;i<14; i++)
+ {
+ vec3 n = noised(p);
+ d += n.yz;
+ a += b*n.x/(1.0+dot(d,d));
+ b *= 0.5;
+ p=m2*p;
+ }
+
+ return 140.0*a;
+}
+
+
+float map( in vec3 p )
+{
+ float h = terrain(p.xz);
+
+ float ss = 0.03;
+ float hh = h*ss;
+ float fh = fract(hh);
+ float ih = floor(hh);
+ fh = mix( sqrt(fh), fh, smoothstep(50.0,140.0,h) );
+ h = (ih+fh)/ss;
+
+ return p.y - h;
+}
+
+float map2( in vec3 p )
+{
+ float h = terrain2(p.xz);
+
+
+ float ss = 0.03;
+ float hh = h*ss;
+ float fh = fract(hh);
+ float ih = floor(hh);
+ fh = mix( sqrt(fh), fh, smoothstep(50.0,140.0,h) );
+ h = (ih+fh)/ss;
+
+ return p.y - h;
+}
+
+bool jinteresct(in vec3 rO, in vec3 rD, out float resT )
+{
+ float h = 0.0;
+ float t = 0.0;
+ for( int j=0; j<120; j++ )
+ {
+ //if( t>2000.0 ) break;
+
+ vec3 p = rO + t*rD;
+if( p.y>300.0 ) break;
+ h = map( p );
+
+ if( h<0.1 )
+ {
+ resT = t;
+ return true;
+ }
+ t += max(0.1,0.5*h);
+
+ }
+
+ if( h<5.0 )
+ {
+ resT = t;
+ return true;
+ }
+ return false;
+}
+
+float sinteresct(in vec3 rO, in vec3 rD )
+{
+ float res = 1.0;
+ float t = 0.0;
+ for( int j=0; j<50; j++ )
+ {
+ //if( t>1000.0 ) break;
+ vec3 p = rO + t*rD;
+
+ float h = map( p );
+
+ if( h<0.1 )
+ {
+ return 0.0;
+ }
+ res = min( res, 16.0*h/t );
+ t += h;
+
+ }
+
+ return clamp( res, 0.0, 1.0 );
+}
+
+vec3 calcNormal( in vec3 pos, float t )
+{
+ float e = 0.001;
+ e = 0.001*t;
+ vec3 eps = vec3(e,0.0,0.0);
+ vec3 nor;
+ nor.x = map2(pos+eps.xyy) - map2(pos-eps.xyy);
+ nor.y = map2(pos+eps.yxy) - map2(pos-eps.yxy);
+ nor.z = map2(pos+eps.yyx) - map2(pos-eps.yyx);
+ return normalize(nor);
+}
+
+vec3 camPath( float time )
+{
+ vec2 p = 600.0*vec2( cos(1.4+0.37*time),
+ cos(3.2+0.31*time) );
+
+ return vec3( p.x, 0.0, p.y );
+}
+
+void main(void)
+{
+ vec2 xy = -1.0 + 2.0*gl_FragCoord.xy / iResolution.xy;
+
+ vec2 s = xy*vec2(1.75,1.0);
+
+ #ifdef STEREO
+ float isCyan = mod(gl_FragCoord.x + mod(gl_FragCoord.y,2.0),2.0);
+ #endif
+
+ float time = iGlobalTime*.15;
+
+ vec3 light1 = normalize( vec3( 0.4, 0.22, 0.6 ) );
+ vec3 light2 = vec3( -0.707, 0.000, -0.707 );
+
+
+ vec3 campos = camPath( time );
+ vec3 camtar = camPath( time + 3.0 );
+ campos.y = terrain( campos.xz ) + 15.0;
+ camtar.y = campos.y*0.5;
+
+ float roll = 0.1*cos(0.1*time);
+ vec3 cw = normalize(camtar-campos);
+ vec3 cp = vec3(sin(roll), cos(roll),0.0);
+ vec3 cu = normalize(cross(cw,cp));
+ vec3 cv = normalize(cross(cu,cw));
+ vec3 rd = normalize( s.x*cu + s.y*cv + 1.6*cw );
+
+ #ifdef STEREO
+ campos += 2.0*cu*isCyan; // move camera to the right - the rd vector is still good
+ #endif
+
+ float sundot = clamp(dot(rd,light1),0.0,1.0);
+ vec3 col;
+ float t;
+ if( !jinteresct(campos,rd,t) )
+ {
+ col = 0.9*vec3(0.97,.99,1.0)*(1.0-0.3*rd.y);
+ col += 0.2*vec3(0.8,0.7,0.5)*pow( sundot, 4.0 );
+ }
+ else
+ {
+ vec3 pos = campos + t*rd;
+
+ vec3 nor = calcNormal( pos, t );
+
+ float dif1 = clamp( dot( light1, nor ), 0.0, 1.0 );
+ float dif2 = clamp( 0.2 + 0.8*dot( light2, nor ), 0.0, 1.0 );
+ float sh = 1.0;
+ if( dif1>0.001 )
+ sh = sinteresct(pos+light1*20.0,light1);
+
+ vec3 dif1v = vec3(dif1);
+ dif1v *= vec3( sh, sh*sh*0.5+0.5*sh, sh*sh );
+
+ float r = noise( 7.0*pos.xz );
+
+ col = (r*0.25+0.75)*0.9*mix( vec3(0.10,0.05,0.03), vec3(0.13,0.10,0.08), clamp(terrain2( vec2(pos.x,pos.y*48.0))/200.0,0.0,1.0) );
+ col = mix( col, 0.17*vec3(0.5,.23,0.04)*(0.50+0.50*r),smoothstep(0.70,0.9,nor.y) );
+ col = mix( col, 0.10*vec3(0.2,.30,0.00)*(0.25+0.75*r),smoothstep(0.95,1.0,nor.y) );
+ col *= 0.75;
+ // snow
+ #if 1
+ float h = smoothstep(55.0,80.0,pos.y + 25.0*fbm(0.01*pos.xz) );
+ float e = smoothstep(1.0-0.5*h,1.0-0.1*h,nor.y);
+ float o = 0.3 + 0.7*smoothstep(0.0,0.1,nor.x+h*h);
+ float s = h*e*o;
+ s = smoothstep( 0.1, 0.9, s );
+ col = mix( col, 0.4*vec3(0.6,0.65,0.7), s );
+ #endif
+
+
+ vec3 brdf = 2.0*vec3(0.17,0.19,0.20)*clamp(nor.y,0.0,1.0);
+ brdf += 6.0*vec3(1.00,0.95,0.80)*dif1v;
+ brdf += 2.0*vec3(0.20,0.20,0.20)*dif2;
+
+ col *= brdf;
+
+ float fo = 1.0-exp(-pow(0.0015*t,1.5));
+ vec3 fco = vec3(0.7) + 0.6*vec3(0.8,0.7,0.5)*pow( sundot, 4.0 );
+ col = mix( col, fco, fo );
+ }
+
+ col = sqrt(col);
+
+ vec2 uv = xy*0.5+0.5;
+ col *= 0.7 + 0.3*pow(16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y),0.1);
+
+ #ifdef STEREO
+ col *= vec3( isCyan, 1.0-isCyan, 1.0-isCyan );
+ #endif
+
+ mgl_FragColor = vec4(col,1.0);
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.vp
new file mode 100644
index 000000000..fc698f2a8
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.vp
@@ -0,0 +1,11 @@
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+attribute vec2 inVertex;
+
+void main() {
+ gl_Position = vec4(inVertex, 0, 1);
+} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp
index a26dc9737..a2abf9e2c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp
@@ -1,10 +1,16 @@
// Copyright 2012 JogAmp Community. All rights reserved.
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
varying vec4 frontColor;
void main (void)
{
- gl_FragColor = frontColor;
- // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ mgl_FragColor = frontColor;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp
index 097a73e4c..98e7916ab 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp
@@ -1,5 +1,9 @@
//Copyright 2012 JogAmp Community. All rights reserved.
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
uniform mat4 mgl_PMVMatrix[2]; // P, Mv
attribute vec4 mgl_Vertex;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/ruler.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/ruler.fp
index b2f4d7a6a..f16a3eeb1 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/ruler.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/ruler.fp
@@ -1,5 +1,12 @@
//Copyright 2010 JogAmp Community. All rights reserved.
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
#ifdef GL_ES
#define MEDIUMP mediump
#define HIGHP highp
@@ -19,7 +26,7 @@ void main (void)
{
MEDIUMP vec2 c = step( onev2, mod(gl_FragCoord.xy, gcu_RulerPixFreq) );
if( c.s == 0.0 || c.t == 0.0 ) {
- gl_FragColor = vec4(gcu_RulerColor, 1.0);
+ mgl_FragColor = vec4(gcu_RulerColor, 1.0);
} else {
discard;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.fp
index adde23d0a..e4f21f95f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.fp
@@ -1,5 +1,13 @@
// Copyright 2012 JogAmp Community. All rights reserved.
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
varying vec2 mgl_texCoord;
varying vec4 frontColor;
@@ -17,6 +25,6 @@ void main (void)
}
// mix frontColor with texture ..
- gl_FragColor = vec4(frontColor*texColor);
+ mgl_FragColor = vec4(frontColor*texColor);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.vp
index c521e3757..1030dab47 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.vp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.vp
@@ -1,5 +1,10 @@
// Copyright 2012 JogAmp Community. All rights reserved.
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
uniform mat4 mgl_PMVMatrix[2];
// uniform mat4 mgl_STMatrix;
attribute vec4 mgl_Vertex;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.fp
index 1a4254163..93f252cd6 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.fp
@@ -1,5 +1,13 @@
// Copyright 2012 JogAmp Community. All rights reserved.
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
varying vec2 mgl_texCoord;
varying vec4 frontColor;
@@ -11,10 +19,10 @@ void main (void)
if(0.0 <= mgl_texCoord.t && mgl_texCoord.t<=1.0) {
texColor = texture2D(mgl_ActiveTexture, mgl_texCoord);
} else {
- texColor = vec4(1, 1, 1, 1);
+ discard;
}
- // mix frontColor with texture ..
- gl_FragColor = vec4(frontColor*texColor);
+ // mix frontColor with texture .. pre-multiplying texture alpha
+ mgl_FragColor = vec4( mix( frontColor.rgb, texColor.rgb, texColor.a ), frontColor.a );
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.vp
index c521e3757..1030dab47 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.vp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.vp
@@ -1,5 +1,10 @@
// Copyright 2012 JogAmp Community. All rights reserved.
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
uniform mat4 mgl_PMVMatrix[2];
// uniform mat4 mgl_STMatrix;
attribute vec4 mgl_Vertex;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp
index d222606cd..10073e85c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp
@@ -1,5 +1,13 @@
// Copyright 2012 JogAmp Community. All rights reserved.
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
varying vec2 mgl_texCoord;
varying vec4 frontColor;
@@ -13,8 +21,8 @@ void main (void)
vec4 texColor0 = texture2D(mgl_Texture0, mgl_texCoord);
vec4 texColor1 = texture2D(mgl_Texture1, mgl_texCoord);
- // gl_FragColor = ( ( texColor0 + texColor1 ) / 2.0 ) * frontColor;
- // gl_FragColor = mix(texColor0, texColor1, One/2.0) * frontColor;
- gl_FragColor = min(One, mix(texColor0, texColor1, One/2.0) * 1.6) * frontColor;
+ // mgl_FragColor = ( ( texColor0 + texColor1 ) / 2.0 ) * frontColor;
+ // mgl_FragColor = mix(texColor0, texColor1, One/2.0) * frontColor;
+ mgl_FragColor = min(One, mix(texColor0, texColor1, One/2.0) * 1.6) * frontColor;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java
new file mode 100644
index 000000000..7ecb63938
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java
@@ -0,0 +1,337 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2.swt;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.opengl.swt.GLCanvas;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGearsES2SWT extends UITestCase {
+ static int screenIdx = 0;
+ static PointImmutable wpos;
+ static DimensionImmutable wsize, rwsize=null;
+
+ static long duration = 500; // ms
+ static boolean opaque = true;
+ static int forceAlpha = -1;
+ static boolean fullscreen = false;
+ static int swapInterval = 1;
+ static boolean showFPS = false;
+ static int loops = 1;
+ static boolean loop_shutdown = false;
+ static boolean forceES2 = false;
+ static boolean forceGL3 = false;
+ static boolean mainRun = false;
+ static boolean exclusiveContext = false;
+
+ @BeforeClass
+ public static void initClass() {
+ if(null == wsize) {
+ wsize = new Dimension(640, 480);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ Display display = null;
+ Shell shell = null;
+ Composite composite = null;
+
+ @Before
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ }});
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.NONE );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ }});
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+ try {
+ display.syncExec(new Runnable() {
+ public void run() {
+ composite.dispose();
+ shell.dispose();
+ }});
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display.dispose();
+ }});
+ }
+ catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ display = null;
+ shell = null;
+ composite = null;
+ }
+
+ protected void runTestGL(final GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException {
+ System.err.println("requested: vsync "+swapInterval+", "+caps);
+
+ final GLCanvas canvas = GLCanvas.create( composite, 0, caps, null);
+ Assert.assertNotNull( canvas );
+
+ final GearsES2 demo = new GearsES2(swapInterval);
+ canvas.addGLEventListener(demo);
+
+ final Animator animator = new Animator();
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.setExclusiveContext(exclusiveContext);
+
+ animator.add(canvas);
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ Assert.assertEquals(exclusiveContext ? animator.getThread() : null, canvas.getExclusiveContextThread());
+
+ display.syncExec( new Runnable() {
+ public void run() {
+ shell.setText( getSimpleTestName(".") );
+ shell.setSize( wsize.getWidth(), wsize.getHeight() );
+ if( null != wpos ) {
+ shell.setLocation( wpos.getX(), wpos.getY() );
+ }
+ shell.open();
+ }
+ });
+
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+
+ while(animator.isAnimating() && !canvas.isRealized() && animator.getTotalFPSDuration()<duration) {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ Thread.sleep(10);
+ }
+ }
+ System.err.println("NW chosen: "+canvas.getDelegatedDrawable().getChosenGLCapabilities());
+ System.err.println("GL chosen: "+canvas.getChosenGLCapabilities());
+ System.err.println("window pos/siz: "+canvas.getLocation()+" "+canvas.getSurfaceWidth()+"x"+canvas.getSurfaceHeight());
+
+ if( null != rwsize ) {
+ for(int i=0; i<50; i++) { // 500 ms dispatched delay
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ Thread.sleep(10);
+ }
+ }
+ display.syncExec( new Runnable() {
+ public void run() {
+ shell.setSize( rwsize.getWidth(), rwsize.getHeight() );
+ }
+ });
+ System.err.println("window resize pos/siz: "+canvas.getLocation()+" "+canvas.getSurfaceWidth()+"x"+canvas.getSurfaceHeight());
+ }
+
+ while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ Thread.sleep(10);
+ }
+ }
+
+ Assert.assertEquals(exclusiveContext ? animator.getThread() : null, canvas.getExclusiveContextThread());
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ Assert.assertEquals(null, canvas.getExclusiveContextThread());
+
+ display.syncExec(new Runnable() {
+ public void run() {
+ canvas.dispose();
+ } } );
+ }
+
+ @Test
+ public void test01GL2ES2() throws InterruptedException, InvocationTargetException {
+ for(int i=1; i<=loops; i++) {
+ System.err.println("Loop "+i+"/"+loops);
+ final GLProfile glp;
+ if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getGL2ES2();
+ }
+ final GLCapabilities caps = new GLCapabilities( glp );
+ caps.setBackgroundOpaque(opaque);
+ if(-1 < forceAlpha) {
+ caps.setAlphaBits(forceAlpha);
+ }
+ runTestGL(caps);
+ if(loop_shutdown) {
+ GLProfile.shutdown();
+ }
+ }
+ }
+
+ @Test
+ public void test02GL3() throws InterruptedException, InvocationTargetException {
+ if(mainRun) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ mainRun = true;
+
+ int x=0, y=0, w=640, h=480, rw=-1, rh=-1;
+ boolean usePos = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-translucent")) {
+ opaque = false;
+ } else if(args[i].equals("-forceAlpha")) {
+ i++;
+ forceAlpha = MiscUtils.atoi(args[i], 0);
+ } else if(args[i].equals("-fullscreen")) {
+ fullscreen = true;
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-exclctx")) {
+ exclusiveContext = true;
+ } else if(args[i].equals("-es2")) {
+ forceES2 = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
+ } else if(args[i].equals("-showFPS")) {
+ showFPS = true;
+ } else if(args[i].equals("-width")) {
+ i++;
+ w = MiscUtils.atoi(args[i], w);
+ } else if(args[i].equals("-height")) {
+ i++;
+ h = MiscUtils.atoi(args[i], h);
+ } else if(args[i].equals("-x")) {
+ i++;
+ x = MiscUtils.atoi(args[i], x);
+ usePos = true;
+ } else if(args[i].equals("-y")) {
+ i++;
+ y = MiscUtils.atoi(args[i], y);
+ usePos = true;
+ } else if(args[i].equals("-rwidth")) {
+ i++;
+ rw = MiscUtils.atoi(args[i], rw);
+ } else if(args[i].equals("-rheight")) {
+ i++;
+ rh = MiscUtils.atoi(args[i], rh);
+ } else if(args[i].equals("-screen")) {
+ i++;
+ screenIdx = MiscUtils.atoi(args[i], 0);
+ } else if(args[i].equals("-loops")) {
+ i++;
+ loops = MiscUtils.atoi(args[i], 1);
+ } else if(args[i].equals("-loop-shutdown")) {
+ loop_shutdown = true;
+ }
+ }
+ wsize = new Dimension(w, h);
+ if( 0 < rw && 0 < rh ) {
+ rwsize = new Dimension(rw, rh);
+ }
+
+ if(usePos) {
+ wpos = new Point(x, y);
+ }
+ System.err.println("position "+wpos);
+ System.err.println("size "+wsize);
+ System.err.println("resize "+rwsize);
+ System.err.println("screen "+screenIdx);
+ System.err.println("translucent "+(!opaque));
+ System.err.println("forceAlpha "+forceAlpha);
+ System.err.println("fullscreen "+fullscreen);
+ System.err.println("loops "+loops);
+ System.err.println("loop shutdown "+loop_shutdown);
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("exclusiveContext "+exclusiveContext);
+
+ org.junit.runner.JUnitCore.main(TestGearsES2SWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java
index 9c1293e22..28328fcd2 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java
@@ -3,10 +3,12 @@ package com.jogamp.opengl.test.junit.jogl.demos.gl2;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
-import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.InputEvent;
@@ -18,6 +20,9 @@ import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseListener;
import com.jogamp.newt.event.awt.AWTKeyAdapter;
import com.jogamp.newt.event.awt.AWTMouseAdapter;
+import com.jogamp.opengl.GLRendererQuirks;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.util.TileRendererBase;
/**
* Gears.java <BR>
@@ -25,30 +30,60 @@ import com.jogamp.newt.event.awt.AWTMouseAdapter;
*
* This version is equal to Brian Paul's version 1.2 1999/10/21
*/
-
-public class Gears implements GLEventListener {
- private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f;
+public class Gears implements GLEventListener, TileRendererBase.TileRendererListener {
+ private float view_rotx = 20.0f, view_roty = 30.0f;
+ private final float view_rotz = 0.0f;
private int gear1=0, gear2=0, gear3=0;
+ private Gears sharedGears = null;
+ private Object syncObjects = null;
private float angle = 0.0f;
- private int swapInterval;
- private MouseListener gearsMouse = new GearsMouseAdapter();
- private KeyListener gearsKeys = new GearsKeyAdapter();
+ private boolean doRotate = true;
+ private final int swapInterval;
+ private final MouseListener gearsMouse = new GearsMouseAdapter();
+ private final KeyListener gearsKeys = new GearsKeyAdapter();
+ private TileRendererBase tileRendererInUse = null;
+ private boolean doRotateBeforePrinting;
+ private boolean verbose = true;
+ private boolean flipVerticalInGLOrientation = false;
+ private volatile boolean isInit = false;
// private boolean mouseRButtonDown = false;
private int prevMouseX, prevMouseY;
- public Gears(int swapInterval) {
+ public Gears(final int swapInterval) {
this.swapInterval = swapInterval;
}
public Gears() {
this.swapInterval = 1;
}
-
- public void setGears(int g1, int g2, int g3) {
- gear1 = g1;
- gear2 = g2;
- gear3 = g3;
+
+ @Override
+ public void addTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = tr;
+ doRotateBeforePrinting = doRotate;
+ setDoRotation(false);
+ }
+ @Override
+ public void removeTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = null;
+ setDoRotation(doRotateBeforePrinting);
+ }
+ @Override
+ public void startTileRendering(final TileRendererBase tr) {
+ System.err.println("Gears.startTileRendering: "+tr);
+ }
+ @Override
+ public void endTileRendering(final TileRendererBase tr) {
+ System.err.println("Gears.endTileRendering: "+tr);
+ }
+
+ public void setDoRotation(final boolean rotate) { doRotate = rotate; }
+ public void setVerbose(final boolean v) { verbose = v; }
+ public void setFlipVerticalInGLOrientation(final boolean v) { flipVerticalInGLOrientation=v; }
+
+ public void setSharedGears(final Gears shared) {
+ sharedGears = shared;
}
/**
@@ -66,176 +101,308 @@ public class Gears implements GLEventListener {
*/
public int getGear3() { return gear3; }
- public void init(GLAutoDrawable drawable) {
- System.err.println("Gears: Init: "+drawable);
- // Use debug pipeline
- // drawable.setGL(new DebugGL(drawable.getGL()));
-
- GL2 gl = drawable.getGL().getGL2();
-
- System.err.println("Gears (GL2) init on "+Thread.currentThread());
- System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
- System.err.println("INIT GL IS: " + gl.getClass().getName());
- System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
- System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
- System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
- System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
- System.err.println("GL Profile: "+gl.getGLProfile());
- System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
-
- float pos[] = { 5.0f, 5.0f, 10.0f, 0.0f };
- float red[] = { 0.8f, 0.1f, 0.0f, 0.7f };
- float green[] = { 0.0f, 0.8f, 0.2f, 0.7f };
- float blue[] = { 0.2f, 0.2f, 1.0f, 0.7f };
-
- gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, pos, 0);
- gl.glEnable(GL2.GL_CULL_FACE);
- gl.glEnable(GL2.GL_LIGHTING);
- gl.glEnable(GL2.GL_LIGHT0);
- gl.glEnable(GL2.GL_DEPTH_TEST);
-
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
+
+ if( init(gl) ) {
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
+ window.addMouseListener(gearsMouse);
+ window.addKeyListener(gearsKeys);
+ } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) {
+ final java.awt.Component comp = (java.awt.Component) upstreamWidget;
+ new AWTMouseAdapter(gearsMouse, drawable).addTo(comp);
+ new AWTKeyAdapter(gearsKeys, drawable).addTo(comp);
+ }
+ } else {
+ drawable.setGLEventListenerInitState(this, false);
+ }
+ }
+
+ boolean enableCullFace = false;
+
+ private void enableStates(final GL gl, final boolean enable) {
+ final boolean msaa = gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers();
+ if( enable ) {
+ if( enableCullFace ) {
+ gl.glEnable(GL.GL_CULL_FACE);
+ }
+ gl.glEnable(GLLightingFunc.GL_LIGHTING);
+ gl.glEnable(GLLightingFunc.GL_LIGHT0);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glDepthFunc(GL.GL_LESS); // default
+ gl.glEnable(GLLightingFunc.GL_NORMALIZE);
+ if( msaa ) {
+ gl.glEnable(GL.GL_MULTISAMPLE);
+ }
+ } else {
+ if( enableCullFace ) {
+ gl.glDisable(GL.GL_CULL_FACE);
+ }
+ gl.glDisable(GLLightingFunc.GL_LIGHTING);
+ gl.glDisable(GLLightingFunc.GL_LIGHT0);
+ gl.glDisable(GL.GL_DEPTH_TEST);
+ gl.glDisable(GLLightingFunc.GL_NORMALIZE);
+ if( msaa ) {
+ gl.glDisable(GL.GL_MULTISAMPLE);
+ }
+ }
+ }
+
+ public boolean init(final GL2 gl) {
+ if(null != sharedGears && !sharedGears.isInit() ) {
+ System.err.println(Thread.currentThread()+" GearsES1.init.0: pending shared Gears .. re-init later XXXXX");
+ return false;
+ }
+ final float lightPos[] = { 5.0f, 5.0f, 10.0f, 0.0f };
+ final float red[] = { 0.8f, 0.1f, 0.0f, 0.7f };
+ final float green[] = { 0.0f, 0.8f, 0.2f, 0.7f };
+ final float blue[] = { 0.2f, 0.2f, 1.0f, 0.7f };
+
+ System.err.println(Thread.currentThread()+" Gears.init: tileRendererInUse "+tileRendererInUse);
+ if(verbose) {
+ System.err.println("GearsES2 init on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + gl.getContext().getGLDrawable().getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+ }
+
+ gl.glLightfv(GLLightingFunc.GL_LIGHT0, GLLightingFunc.GL_POSITION, lightPos, 0);
+ if( ! ( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) ) {
+ // Only possible if we do not flip the projection matrix
+ enableCullFace = true;
+ } else {
+ enableCullFace = false;
+ }
+ enableStates(gl, true);
+
/* make the gears */
- if(0>=gear1) {
+ if( null != sharedGears ) {
+ gear1 = sharedGears.getGear1();
+ gear2 = sharedGears.getGear2();
+ gear3 = sharedGears.getGear3();
+ System.err.println("gear1 list reused: "+gear1);
+ System.err.println("gear2 list reused: "+gear2);
+ System.err.println("gear3 list reused: "+gear3);
+ if( gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync) ) {
+ syncObjects = sharedGears;
+ System.err.println("Shared Gears: Synchronized Objects due to quirk "+GLRendererQuirks.toString(GLRendererQuirks.NeedSharedObjectSync));
+ } else {
+ syncObjects = new Object();
+ System.err.println("Shared Gears: Unsynchronized Objects");
+ }
+ } else {
gear1 = gl.glGenLists(1);
gl.glNewList(gear1, GL2.GL_COMPILE);
- gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT_AND_DIFFUSE, red, 0);
+ gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT_AND_DIFFUSE, red, 0);
gear(gl, 1.0f, 4.0f, 1.0f, 20, 0.7f);
gl.glEndList();
System.err.println("gear1 list created: "+gear1);
- } else {
- System.err.println("gear1 list reused: "+gear1);
- }
-
- if(0>=gear2) {
+
gear2 = gl.glGenLists(1);
gl.glNewList(gear2, GL2.GL_COMPILE);
- gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT_AND_DIFFUSE, green, 0);
+ gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT_AND_DIFFUSE, green, 0);
gear(gl, 0.5f, 2.0f, 2.0f, 10, 0.7f);
gl.glEndList();
System.err.println("gear2 list created: "+gear2);
- } else {
- System.err.println("gear2 list reused: "+gear2);
- }
-
- if(0>=gear3) {
+
gear3 = gl.glGenLists(1);
gl.glNewList(gear3, GL2.GL_COMPILE);
- gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT_AND_DIFFUSE, blue, 0);
+ gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT_AND_DIFFUSE, blue, 0);
gear(gl, 1.3f, 2.0f, 0.5f, 10, 0.7f);
gl.glEndList();
System.err.println("gear3 list created: "+gear3);
- } else {
- System.err.println("gear3 list reused: "+gear3);
- }
-
- gl.glEnable(GL2.GL_NORMALIZE);
-
- final Object upstreamWidget = drawable.getUpstreamWidget();
- if (upstreamWidget instanceof Window) {
- final Window window = (Window) upstreamWidget;
- window.addMouseListener(gearsMouse);
- window.addKeyListener(gearsKeys);
- } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) {
- final java.awt.Component comp = (java.awt.Component) upstreamWidget;
- new AWTMouseAdapter(gearsMouse).addTo(comp);
- new AWTKeyAdapter(gearsKeys).addTo(comp);
+
+ syncObjects = new Object();
}
+
+ enableStates(gl, false);
+
+ isInit = true;
+ return true;
}
-
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- System.err.println("Gears: Reshape "+x+"/"+y+" "+width+"x"+height);
- GL2 gl = drawable.getGL().getGL2();
- gl.setSwapInterval(swapInterval);
+ public final boolean isInit() { return isInit; }
- gl.glMatrixMode(GL2.GL_PROJECTION);
+ @Override
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ if( !isInit ) { return; }
+ final GL2 gl = glad.getGL().getGL2();
+ if(-1 != swapInterval) {
+ gl.setSwapInterval(swapInterval);
+ }
+ reshape(gl, x, y, width, height, width, height);
+ }
- gl.glLoadIdentity();
- if(height>width) {
- float h = (float)height / (float)width;
- gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
+ @Override
+ public void reshapeTile(final TileRendererBase tr,
+ final int tileX, final int tileY, final int tileWidth, final int tileHeight,
+ final int imageWidth, final int imageHeight) {
+ if( !isInit ) { return; }
+ final GL2 gl = tr.getAttachedDrawable().getGL().getGL2();
+ gl.setSwapInterval(0);
+ reshape(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
+ }
+
+ public void reshape(final GL2 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight) {
+ System.err.println(Thread.currentThread()+" Gears.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse);
+
+ // compute projection parameters 'normal'
+ float left, right, bottom, top;
+ if( imageHeight > imageWidth ) {
+ final float a = (float)imageHeight / (float)imageWidth;
+ left = -1.0f;
+ right = 1.0f;
+ bottom = -a;
+ top = a;
} else {
- float h = (float)width / (float)height;
- gl.glFrustum(-h, h, -1.0f, 1.0f, 5.0f, 60.0f);
+ final float a = (float)imageWidth / (float)imageHeight;
+ left = -a;
+ right = a;
+ bottom = -1.0f;
+ top = 1.0f;
}
- gl.glMatrixMode(GL2.GL_MODELVIEW);
+ final float w = right - left;
+ final float h = top - bottom;
+
+ // compute projection parameters 'tiled'
+ final float l = left + tileX * w / imageWidth;
+ final float r = l + tileWidth * w / imageWidth;
+
+ final float b = bottom + tileY * h / imageHeight;
+ final float t = b + tileHeight * h / imageHeight;
+
+ final float _w = r - l;
+ final float _h = t - b;
+ if(verbose) {
+ System.err.println(">> Gears angle "+angle+", [l "+left+", r "+right+", b "+bottom+", t "+top+"] "+w+"x"+h+" -> [l "+l+", r "+r+", b "+b+", t "+t+"] "+_w+"x"+_h+", v-flip "+flipVerticalInGLOrientation);
+ }
+
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) {
+ gl.glScalef(1f, -1f, 1f);
+ }
+ gl.glFrustum(l, r, b, t, 5.0f, 60.0f);
+
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -40.0f);
}
- public void dispose(GLAutoDrawable drawable) {
- System.err.println("Gears: Dispose");
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( !isInit ) { return; }
+ isInit = false;
+ System.err.println(Thread.currentThread()+" Gears.dispose: tileRendererInUse "+tileRendererInUse);
try {
final Object upstreamWidget = drawable.getUpstreamWidget();
- if (upstreamWidget instanceof Window) {
+ if (upstreamWidget instanceof Window) {
final Window window = (Window) upstreamWidget;
window.removeMouseListener(gearsMouse);
window.removeKeyListener(gearsKeys);
}
- } catch (Exception e) { System.err.println("Catched: "); e.printStackTrace(); }
- setGears(0, 0, 0);
+ } catch (final Exception e) { System.err.println("Caught: "); e.printStackTrace(); }
+ gear1 = 0;
+ gear2 = 0;
+ gear3 = 0;
+ sharedGears = null;
+ syncObjects = null;
}
- public void display(GLAutoDrawable drawable) {
- // Turn the gears' teeth
- angle += 2.0f;
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ if( !isInit ) { return; }
// Get the GL corresponding to the drawable we are animating
- GL2 gl = drawable.getGL().getGL2();
+ final GL2 gl = drawable.getGL().getGL2();
+
+ enableStates(gl, true);
- gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ if( null == tileRendererInUse ) {
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ } else {
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ }
// Special handling for the case where the GLJPanel is translucent
// and wants to be composited with other Java 2D content
- if (GLProfile.isAWTAvailable() &&
+ if (GLProfile.isAWTAvailable() &&
(drawable instanceof javax.media.opengl.awt.GLJPanel) &&
!((javax.media.opengl.awt.GLJPanel) drawable).isOpaque() &&
((javax.media.opengl.awt.GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) {
- gl.glClear(GL2.GL_DEPTH_BUFFER_BIT);
+ gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
+ } else {
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+ displayImpl(gl);
+
+ enableStates(gl, false);
+ }
+
+ public void display(final GL2 gl) {
+ if( !isInit ) { return; }
+ enableStates(gl, true);
+
+ if( null == tileRendererInUse ) {
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
} else {
- gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ }
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ displayImpl(gl);
+
+ enableStates(gl, false);
+ }
+
+ private void displayImpl(final GL2 gl) {
+ if( doRotate ) {
+ // Turn the gears' teeth
+ angle += 0.5f;
}
-
// Rotate the entire assembly of gears based on how the user
// dragged the mouse around
gl.glPushMatrix();
gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
-
+
// Place the first gear and call its display list
- gl.glPushMatrix();
- gl.glTranslatef(-3.0f, -2.0f, 0.0f);
- gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);
- gl.glCallList(gear1);
- gl.glPopMatrix();
-
- // Place the second gear and call its display list
- gl.glPushMatrix();
- gl.glTranslatef(3.1f, -2.0f, 0.0f);
- gl.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f);
- gl.glCallList(gear2);
- gl.glPopMatrix();
-
- // Place the third gear and call its display list
- gl.glPushMatrix();
- gl.glTranslatef(-3.1f, 4.2f, 0.0f);
- gl.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f);
- gl.glCallList(gear3);
- gl.glPopMatrix();
-
+ synchronized ( syncObjects ) {
+ gl.glPushMatrix();
+ gl.glTranslatef(-3.0f, -2.0f, 0.0f);
+ gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);
+ gl.glCallList(gear1);
+ gl.glPopMatrix();
+
+ // Place the second gear and call its display list
+ gl.glPushMatrix();
+ gl.glTranslatef(3.1f, -2.0f, 0.0f);
+ gl.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f);
+ gl.glCallList(gear2);
+ gl.glPopMatrix();
+
+ // Place the third gear and call its display list
+ gl.glPushMatrix();
+ gl.glTranslatef(-3.1f, 4.2f, 0.0f);
+ gl.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f);
+ gl.glCallList(gear3);
+ gl.glPopMatrix();
+ }
+
// Remember that every push needs a pop; this one is paired with
// rotating the entire gear assembly
gl.glPopMatrix();
}
- public static void gear(GL2 gl,
- float inner_radius,
- float outer_radius,
- float width,
- int teeth,
- float tooth_depth)
+ public static void gear(final GL2 gl,
+ final float inner_radius,
+ final float outer_radius,
+ final float width,
+ final int teeth,
+ final float tooth_depth)
{
int i;
float r0, r1, r2;
@@ -245,10 +412,10 @@ public class Gears implements GLEventListener {
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0f;
r2 = outer_radius + tooth_depth / 2.0f;
-
+
da = 2.0f * (float) Math.PI / teeth / 4.0f;
-
- gl.glShadeModel(GL2.GL_FLAT);
+
+ gl.glShadeModel(GLLightingFunc.GL_FLAT);
gl.glNormal3f(0.0f, 0.0f, 1.0f);
@@ -268,7 +435,7 @@ public class Gears implements GLEventListener {
gl.glEnd();
/* draw front sides of teeth */
- gl.glBegin(GL2.GL_QUADS);
+ gl.glBegin(GL2GL3.GL_QUADS);
for (i = 0; i < teeth; i++)
{
angle = i * 2.0f * (float) Math.PI / teeth;
@@ -278,7 +445,7 @@ public class Gears implements GLEventListener {
gl.glVertex3f(r1 * (float)Math.cos(angle + 3.0f * da), r1 * (float)Math.sin(angle + 3.0f * da), width * 0.5f);
}
gl.glEnd();
-
+
/* draw back face */
gl.glBegin(GL2.GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++)
@@ -290,9 +457,9 @@ public class Gears implements GLEventListener {
gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f);
}
gl.glEnd();
-
+
/* draw back sides of teeth */
- gl.glBegin(GL2.GL_QUADS);
+ gl.glBegin(GL2GL3.GL_QUADS);
for (i = 0; i < teeth; i++)
{
angle = i * 2.0f * (float) Math.PI / teeth;
@@ -302,7 +469,7 @@ public class Gears implements GLEventListener {
gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f);
}
gl.glEnd();
-
+
/* draw outward faces of teeth */
gl.glBegin(GL2.GL_QUAD_STRIP);
for (i = 0; i < teeth; i++)
@@ -331,9 +498,9 @@ public class Gears implements GLEventListener {
gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), width * 0.5f);
gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), -width * 0.5f);
gl.glEnd();
-
- gl.glShadeModel(GL2.GL_SMOOTH);
-
+
+ gl.glShadeModel(GLLightingFunc.GL_SMOOTH); // default
+
/* draw inside radius cylinder */
gl.glBegin(GL2.GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++)
@@ -346,9 +513,9 @@ public class Gears implements GLEventListener {
gl.glEnd();
}
- class GearsKeyAdapter extends KeyAdapter {
- public void keyPressed(KeyEvent e) {
- int kc = e.getKeyCode();
+ class GearsKeyAdapter extends KeyAdapter {
+ public void keyPressed(final KeyEvent e) {
+ final int kc = e.getKeyCode();
if(KeyEvent.VK_LEFT == kc) {
view_roty -= 1;
} else if(KeyEvent.VK_RIGHT == kc) {
@@ -360,41 +527,45 @@ public class Gears implements GLEventListener {
}
}
}
-
+
class GearsMouseAdapter extends MouseAdapter {
- public void mousePressed(MouseEvent e) {
+ public void mousePressed(final MouseEvent e) {
prevMouseX = e.getX();
prevMouseY = e.getY();
if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
// mouseRButtonDown = true;
}
}
-
- public void mouseReleased(MouseEvent e) {
+
+ public void mouseReleased(final MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
// mouseRButtonDown = false;
}
}
-
- public void mouseDragged(MouseEvent e) {
- int x = e.getX();
- int y = e.getY();
+
+ public void mouseDragged(final MouseEvent e) {
+ final int x = e.getX();
+ final int y = e.getY();
int width=0, height=0;
- Object source = e.getSource();
+ final Object source = e.getSource();
if(source instanceof Window) {
- Window window = (Window) source;
- width=window.getWidth();
- height=window.getHeight();
+ final Window window = (Window) source;
+ width=window.getSurfaceWidth();
+ height=window.getSurfaceHeight();
+ } else if (source instanceof GLAutoDrawable) {
+ final GLAutoDrawable glad = (GLAutoDrawable) source;
+ width = glad.getSurfaceWidth();
+ height = glad.getSurfaceHeight();
} else if (GLProfile.isAWTAvailable() && source instanceof java.awt.Component) {
- java.awt.Component comp = (java.awt.Component) source;
- width=comp.getWidth();
+ final java.awt.Component comp = (java.awt.Component) source;
+ width=comp.getWidth(); // FIXME HiDPI: May need to convert window units -> pixel units!
height=comp.getHeight();
} else {
throw new RuntimeException("Event source neither Window nor Component: "+source);
}
- float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width);
- float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height);
-
+ final float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width);
+ final float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height);
+
prevMouseX = x;
prevMouseY = y;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java
new file mode 100644
index 000000000..96d6fdba0
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java
@@ -0,0 +1,149 @@
+package com.jogamp.opengl.test.junit.jogl.demos.gl2;
+
+import java.net.URLConnection;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.test.junit.jogl.util.texture.PNGTstFiles;
+import com.jogamp.opengl.util.gl2.GLUT;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Adapted from
+ * http://www.java-tips.org/other-api-tips/jogl/how-to-draw-a-texture-mapped-teapot-with-automatically-generated-texture-coordi.html
+ */
+public class Teapot implements GLEventListener {
+
+ private GLUT glut;
+
+ /* glTexGen stuff: */
+ // private final float sgenparams[] = { 1.0f, 1.0f, 1.0f, 0.0f };
+
+ private Texture tex = null;
+
+ private void enableStates(final GL2 gl, final boolean enable) {
+ if( enable ) {
+ if( null != tex ) {
+ tex.bind(gl);
+ }
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glDepthFunc(GL.GL_LESS); // default
+ // gl.glEnable(GL2.GL_TEXTURE_GEN_S);
+ // gl.glEnable(GL2.GL_TEXTURE_1D);
+ gl.glEnable(GL.GL_TEXTURE_2D);
+ gl.glEnable(GL.GL_CULL_FACE);
+ gl.glEnable(GLLightingFunc.GL_LIGHTING);
+ gl.glEnable(GLLightingFunc.GL_LIGHT0);
+ gl.glEnable(GL2.GL_AUTO_NORMAL);
+ gl.glEnable(GLLightingFunc.GL_NORMALIZE);
+ gl.glFrontFace(GL.GL_CW);
+ gl.glCullFace(GL.GL_BACK); // default
+ gl.glMaterialf(GL.GL_FRONT, GLLightingFunc.GL_SHININESS, 64.0f);
+ gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
+ } else {
+ if( null != tex ) {
+ gl.glBindTexture(tex.getTarget(), 0);
+ }
+ gl.glDisable(GL.GL_DEPTH_TEST);
+ // gl.glDisable(GL2.GL_TEXTURE_GEN_S);
+ // gl.glDisable(GL2.GL_TEXTURE_1D);
+ gl.glDisable(GL.GL_TEXTURE_2D);
+ gl.glDisable(GL.GL_CULL_FACE);
+ gl.glDisable(GLLightingFunc.GL_LIGHTING);
+ gl.glDisable(GLLightingFunc.GL_LIGHT0);
+ gl.glDisable(GL2.GL_AUTO_NORMAL);
+ gl.glDisable(GLLightingFunc.GL_NORMALIZE);
+ gl.glFrontFace(GL.GL_CCW); // default
+ }
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
+ glut = new GLUT();
+
+ gl.glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
+
+ try {
+ final URLConnection urlConn = IOUtil.getResource(PNGTstFiles.class, "test-ntscP_3-01-160x90.png");
+ tex = TextureIO.newTexture(gl, TextureIO.newTextureData(gl.getGLProfile(), urlConn.getInputStream(), false, TextureIO.PNG));
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ // tex.bind(gl);
+
+ // uncomment this and comment the above to see a working texture
+ // makeStripeImage();
+ // gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
+ // gl.glTexEnvf(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE,
+ // GL2.GL_MODULATE);
+ // gl.glTexParameterf(GL2.GL_TEXTURE_1D, GL.GL_TEXTURE_WRAP_S,
+ // GL.GL_REPEAT);
+ // gl.glTexParameterf(GL2.GL_TEXTURE_1D, GL.GL_TEXTURE_MAG_FILTER,
+ // GL.GL_LINEAR);
+ // gl.glTexParameterf(GL2.GL_TEXTURE_1D, GL.GL_TEXTURE_MIN_FILTER,
+ // GL.GL_LINEAR);
+ // gl.glTexImage1D(GL2.GL_TEXTURE_1D, 0, 3, stripeImageWidth, 0,
+ // GL.GL_RGB, GL.GL_UNSIGNED_BYTE, stripeImageBuf);
+
+ // gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
+
+ // gl.glTexGeni(GL2.GL_S, GL2.GL_TEXTURE_GEN_MODE, GL2.GL_OBJECT_LINEAR);
+ // gl.glTexGenfv(GL2.GL_S, GL2.GL_OBJECT_PLANE, sgenparams, 0);
+ }
+
+ float angleZ = 0.0f;
+ float rotDir = 1.0f;
+ public float rotIncr = 0.4f;
+
+ @Override
+ public void display(final GLAutoDrawable gLDrawable) {
+ final GL2 gl = gLDrawable.getGL().getGL2();
+
+ enableStates(gl, true);
+
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl.glPushMatrix();
+ gl.glRotatef(angleZ, 0.0f, 1.0f, 0.0f);
+ gl.glRotatef(45.0f, 0.0f, 0.0f, 1.0f);
+ glut.glutSolidTeapot(2.0f);
+ gl.glPopMatrix();
+ gl.glFlush();
+ if( angleZ >= 180.0f ) {
+ rotDir = -1.0f;
+ } else if (angleZ <= 0.0f ) {
+ rotDir = +1.0f;
+ }
+ angleZ += rotIncr * rotDir;
+
+ enableStates(gl, false);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable gLDrawable, final int x, final int y, final int w, final int h) {
+ final GL2 gl = gLDrawable.getGL().getGL2();
+
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ if (w <= h) {
+ gl.glOrtho(-3.5, 3.5, -3.5 * h / w,
+ 3.5 * h / w, -3.5, 3.5);
+ } else {
+ gl.glOrtho(-3.5 * w / h,
+ 3.5 * w / h, -3.5, 3.5, -3.5, 3.5);
+ }
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable gLDrawable) {
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java
index af30c265b..786229360 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.gl2;
import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor;
@@ -33,42 +33,61 @@ import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureCoords;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureIO;
+
+import javax.media.opengl.GL;
import javax.media.opengl.GL2ES1;
import javax.media.opengl.GL2;
+import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;
public class TextureDraw01GL2Listener implements GLEventListener, TextureDraw01Accessor {
- private GLU glu = new GLU();
- private TextureData textureData;
+ private final GLU glu = new GLU();
+ private final TextureData textureData;
private Texture texture;
-
- public TextureDraw01GL2Listener(TextureData td) {
+ boolean keepTextureBound;
+
+ public TextureDraw01GL2Listener(final TextureData td) {
this.textureData = td;
+ this.keepTextureBound = false;
+ }
+
+ @Override
+ public void setKeepTextureBound(final boolean v) {
+ this.keepTextureBound = v;
+ }
+ @Override
+ public Texture getTexture( ) {
+ return this.texture;
}
- public void init(GLAutoDrawable drawable) {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
if(null!=textureData) {
this.texture = TextureIO.newTexture(drawable.getGL(), textureData);
+ if( keepTextureBound ) {
+ texture.enable(gl);
+ texture.bind(gl);
+ }
}
}
- public Texture getTexture( ) {
- return this.texture;
- }
-
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- GL2 gl = drawable.getGL().getGL2();
- gl.glMatrixMode(GL2ES1.GL_PROJECTION);
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2 gl = drawable.getGL().getGL2();
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluOrtho2D(0, 1, 0, 1);
- gl.glMatrixMode(GL2ES1.GL_MODELVIEW);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
}
- public void dispose(GLAutoDrawable drawable) {
- GL2 gl = drawable.getGL().getGL2();
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
if(null!=texture) {
texture.disable(gl);
texture.destroy(gl);
@@ -78,16 +97,19 @@ public class TextureDraw01GL2Listener implements GLEventListener, TextureDraw01A
}
}
- public void display(GLAutoDrawable drawable) {
- GL2 gl = drawable.getGL().getGL2();
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2 gl = drawable.getGL().getGL2();
// draw one quad with the texture
if(null!=texture) {
- texture.enable(gl);
- texture.bind(gl);
- gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE);
- TextureCoords coords = texture.getImageTexCoords();
- gl.glBegin(GL2.GL_QUADS);
+ if( !keepTextureBound ) {
+ texture.enable(gl);
+ texture.bind(gl);
+ }
+ gl.glTexEnvi(GL2ES1.GL_TEXTURE_ENV, GL2ES1.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
+ final TextureCoords coords = texture.getImageTexCoords();
+ gl.glBegin(GL2GL3.GL_QUADS);
gl.glTexCoord2f(coords.left(), coords.bottom());
gl.glVertex3f(0, 0, 0);
gl.glTexCoord2f(coords.right(), coords.bottom());
@@ -97,7 +119,9 @@ public class TextureDraw01GL2Listener implements GLEventListener, TextureDraw01A
gl.glTexCoord2f(coords.left(), coords.top());
gl.glVertex3f(0, 1, 0);
gl.glEnd();
- texture.disable(gl);
+ if( !keepTextureBound ) {
+ texture.disable(gl);
+ }
}
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/Bug818GLJPanelAndGLCanvasApplet.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/Bug818GLJPanelAndGLCanvasApplet.java
new file mode 100644
index 000000000..a153fc7ae
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/Bug818GLJPanelAndGLCanvasApplet.java
@@ -0,0 +1,318 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.gl2.awt;
+
+import java.awt.ComponentOrientation;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.awt.GLJPanel;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+import javax.swing.JApplet;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+import javax.swing.SwingConstants;
+
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Bug 818: OSX GLJPanel [and GLCanvas] Crash
+ * <pre>
+ * - NVIDIA GeForce GT 330M
+ * - GL_VENDOR: "NVIDIA Corporation"
+ * - GL_RENDERER: "NVIDIA GeForce GT 330M OpenGL Engine"
+ * - GL_VERSION: "2.1 NVIDIA-8.12.47 310.40.00.05f01"
+ * - Mac OSX 10.6.8
+ * </pre>
+ */
+public class Bug818GLJPanelAndGLCanvasApplet extends JApplet {
+
+ private static final long serialVersionUID = 1L;
+
+ private Animator animatorCanvas;
+
+ private Animator animatorPanel;
+
+ public static JFrame frame;
+ public static JPanel appletHolder;
+ public static boolean isApplet = true;
+
+ static public void main(final String args[]) {
+ isApplet = false;
+
+ final JApplet myApplet = new Bug818GLJPanelAndGLCanvasApplet();
+
+ appletHolder = new JPanel();
+
+ frame = new JFrame("Bug818GLJPanelApplet");
+ frame.getContentPane().add(myApplet);
+
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ myApplet.init();
+ frame.validate();
+ frame.pack();
+ frame.setVisible(true);
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ }
+
+ myApplet.start();
+ }
+
+
+ @Override
+ public void init() {
+
+ final JPanel panel = new JPanel();
+ panel.setLayout(new GridLayout(2, 2));
+ System.err.println("Pre Orientation L2R: "+panel.getComponentOrientation().isLeftToRight());
+ panel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
+ System.err.println("Post Orientation L2R: "+panel.getComponentOrientation().isLeftToRight());
+ setContentPane(panel);
+ panel.add(new JLabel("GLJPanel", SwingConstants.CENTER));
+ panel.add(new JLabel("GLCanvas", SwingConstants.CENTER));
+
+ final GLJPanel gljPanel = new GLJPanel();
+ gljPanel.addGLEventListener(new JOGLQuad(false));
+ animatorPanel = new Animator(gljPanel);
+ gljPanel.setPreferredSize(new Dimension(300, 300));
+ panel.add(gljPanel);
+
+ final GLCanvas glCanvas = new GLCanvas();
+ glCanvas.addGLEventListener(new JOGLQuad(true));
+ animatorCanvas = new Animator(glCanvas);
+ glCanvas.setPreferredSize(new Dimension(300, 300));
+ panel.add(glCanvas);
+ }
+
+ @Override
+ public void start() {
+
+ animatorCanvas.start();
+ animatorCanvas.setUpdateFPSFrames(60, System.err);
+ animatorPanel.start();
+ animatorPanel.setUpdateFPSFrames(60, System.err);
+ }
+
+ @Override
+ public void stop() {
+
+ animatorCanvas.stop();
+ animatorPanel.stop();
+ }
+
+ @Override
+ public void destroy() {}
+
+ /**
+ * Self-contained example (within a single class only to keep it simple) displaying a rotating quad
+ */
+ static class JOGLQuad implements GLEventListener {
+
+ private static final float[] VERTEX_DATA = {
+ -1.0f, 1.0f, 0.0f, // Top Left
+ 1.0f, 1.0f, 0.0f, // Top Right
+ 1.0f, -1.0f, 0.0f, // Bottom Right
+ -1.0f, -1.0f, 0.0f // Bottom Left
+ };
+
+ private static final float[] TEXCOORD_DATA = {
+ 0.0f, 1.0f, // Top Left
+ 1.0f, 1.0f, // Top Right
+ 1.0f, 0.0f, // Bottom Right
+ 0.0f, 0.0f // Bottom Left
+ };
+
+ private final FloatBuffer vertexBuf;
+
+ private final FloatBuffer texCoordBuf;
+
+ private int vertexVBO;
+
+ private int texCoordVBO;
+
+ private float rotateT = 0.0f;
+
+ private final boolean canvas;
+
+ private Texture texture;
+
+ JOGLQuad(final boolean canvas) {
+
+ this.canvas = canvas;
+
+ ByteBuffer bb = ByteBuffer.allocateDirect(VERTEX_DATA.length * 4);
+ bb.order(ByteOrder.nativeOrder());
+ vertexBuf = bb.asFloatBuffer();
+ vertexBuf.put(VERTEX_DATA);
+ vertexBuf.rewind();
+
+ bb = ByteBuffer.allocateDirect(TEXCOORD_DATA.length * 4);
+ bb.order(ByteOrder.nativeOrder());
+ texCoordBuf = bb.asFloatBuffer();
+ texCoordBuf.put(TEXCOORD_DATA);
+ texCoordBuf.rewind();
+ }
+
+ @Override
+ public void init(final GLAutoDrawable glDrawable) {
+
+ final GL2 gl = glDrawable.getGL().getGL2();
+
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println(JoglVersion.getGLInfo(gl, null, false /* withCapabilitiesAndExtensionInfo */).toString());
+
+ gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ gl.glClearDepth(1.0f);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glDepthFunc(GL.GL_LEQUAL);
+ gl.glHint(GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
+
+ final int[] tmp = new int[2];
+ gl.glGenBuffers(tmp.length, tmp, 0);
+ vertexVBO = tmp[0];
+ texCoordVBO = tmp[1];
+
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO);
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, VERTEX_DATA.length * 4, vertexBuf, GL.GL_STATIC_DRAW);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, texCoordVBO);
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, TEXCOORD_DATA.length * 4, texCoordBuf, GL.GL_STATIC_DRAW);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+
+ try {
+ final InputStream stream = getClass().getClassLoader().getResourceAsStream("com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpg");
+ texture = TextureIO.newTexture(stream, true, TextureIO.JPG);
+ } catch (final Exception exc) {
+ exc.printStackTrace(System.err);
+ }
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+
+ final GL2 gl = drawable.getGL().getGL2();
+ final int[] tmp = new int[] {vertexVBO, texCoordVBO};
+ gl.glGenBuffers(tmp.length, tmp, 0);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable gLDrawable, final int x, final int y, final int width, final int height) {
+
+ final GL2 gl = gLDrawable.getGL().getGL2();
+ final float aspect = (float) width / (float) height;
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ final float fh = 0.5f;
+ final float fw = fh * aspect;
+ gl.glFrustumf(-fw, fw, -fh, fh, 1.0f, 1000.0f);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ }
+
+ @Override
+ public void display(final GLAutoDrawable gLDrawable) {
+
+ final GL2 gl = gLDrawable.getGL().getGL2();
+
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0.0f, 0.0f, -5.0f);
+
+ // rotate about the three axes
+ gl.glRotatef(rotateT, 1.0f, 0.0f, 0.0f);
+ gl.glRotatef(rotateT, 0.0f, 1.0f, 0.0f);
+ gl.glRotatef(rotateT, 0.0f, 0.0f, 1.0f);
+
+ // set the color of the quad
+ if (canvas) {
+ gl.glColor3f(0.2f, 0.2f, 1.0f);
+ } else {
+ gl.glColor3f(1.0f, 0.2f, 0.2f);
+ }
+
+ if (texture != null) {
+ texture.bind(gl);
+ texture.enable(gl);
+ } else {
+ System.err.println("no texture");
+ }
+
+ // Draw A Quad
+ gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO);
+ gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, texCoordVBO);
+ gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ gl.glDrawArrays(GL2GL3.GL_QUADS, 0, 4);
+ gl.glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
+ gl.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+
+ if (texture != null) {
+ texture.disable(gl);
+ }
+
+ // increasing rotation for the next iteration
+ rotateT += 0.2f;
+ }
+
+ }
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/GLJPanelsAndGLCanvasDemoGL2Applet.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/GLJPanelsAndGLCanvasDemoGL2Applet.java
new file mode 100644
index 000000000..fcff9e56b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/GLJPanelsAndGLCanvasDemoGL2Applet.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.gl2.awt;
+
+import java.awt.ComponentOrientation;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JApplet;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+import javax.swing.SwingConstants;
+
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Teapot;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ */
+public class GLJPanelsAndGLCanvasDemoGL2Applet extends JApplet {
+
+ private static final long serialVersionUID = 1L;
+
+ private Animator[] animator;
+
+ public static JFrame frame;
+ public static JPanel appletHolder;
+ public static boolean isApplet = true;
+
+ static public void main(final String args[]) {
+ isApplet = false;
+
+ final JApplet myApplet = new GLJPanelsAndGLCanvasDemoGL2Applet();
+
+ appletHolder = new JPanel();
+
+ frame = new JFrame("Bug818GLJPanelApplet");
+ frame.getContentPane().add(myApplet);
+
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(final WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ myApplet.init();
+ frame.validate();
+ frame.pack();
+ frame.setVisible(true);
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ }
+
+ myApplet.start();
+ }
+
+
+ @Override
+ public void init() {
+
+ final JPanel panel = new JPanel();
+ panel.setLayout(new GridLayout(3, 2));
+ System.err.println("Pre Orientation L2R: "+panel.getComponentOrientation().isLeftToRight());
+ panel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
+ System.err.println("Post Orientation L2R: "+panel.getComponentOrientation().isLeftToRight());
+ setContentPane(panel);
+
+ animator = new Animator[3*2];
+ int animIdx = 0;
+
+ panel.add(new JLabel("GLJPanel Auto V-Flip", SwingConstants.CENTER));
+ {
+ {
+ final GLJPanel gljPanel = new GLJPanel();
+ gljPanel.addGLEventListener(new Teapot());
+ animator[animIdx++] = new Animator(gljPanel);
+ gljPanel.setPreferredSize(new Dimension(300, 300));
+ panel.add(gljPanel);
+ }
+ {
+ final GLJPanel gljPanel = new GLJPanel();
+ gljPanel.addGLEventListener(new Gears(0));
+ animator[animIdx++] = new Animator(gljPanel);
+ gljPanel.setPreferredSize(new Dimension(300, 300));
+ panel.add(gljPanel);
+ }
+ }
+ panel.add(new JLabel("GLJPanel User V-Flip", SwingConstants.CENTER));
+ {
+ {
+ final GLJPanel gljPanel = new GLJPanel();
+ gljPanel.setSkipGLOrientationVerticalFlip(true);
+ gljPanel.addGLEventListener(new Teapot());
+ animator[animIdx++] = new Animator(gljPanel);
+ gljPanel.setPreferredSize(new Dimension(300, 300));
+ panel.add(gljPanel);
+ }
+ {
+ final GLJPanel gljPanel = new GLJPanel();
+ gljPanel.setSkipGLOrientationVerticalFlip(true);
+ gljPanel.addGLEventListener(new Gears(0));
+ animator[animIdx++] = new Animator(gljPanel);
+ gljPanel.setPreferredSize(new Dimension(300, 300));
+ panel.add(gljPanel);
+ }
+ }
+
+ panel.add(new JLabel("GLCanvas", SwingConstants.CENTER));
+ {
+ {
+ final GLCanvas glCanvas = new GLCanvas();
+ glCanvas.addGLEventListener(new Teapot());
+ animator[animIdx++] = new Animator(glCanvas);
+ glCanvas.setPreferredSize(new Dimension(300, 300));
+ panel.add(glCanvas);
+ }
+ {
+ final GLCanvas glCanvas = new GLCanvas();
+ glCanvas.addGLEventListener(new Gears(1));
+ animator[animIdx++] = new Animator(glCanvas);
+ glCanvas.setPreferredSize(new Dimension(300, 300));
+ panel.add(glCanvas);
+ }
+ }
+ }
+
+ @Override
+ public void start() {
+ for(int i=0; i<animator.length; i++) {
+ animator[i].start();
+ animator[i].setUpdateFPSFrames(60, System.err);
+ }
+ }
+
+ @Override
+ public void stop() {
+ for(int i=0; i<animator.length; i++) {
+ animator[i].stop();
+ }
+ }
+
+ @Override
+ public void destroy() {}
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java
index bd9b7cae7..ee5149b1c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -38,6 +38,7 @@ import javax.media.opengl.glu.gl2.GLUgl2;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
+
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.lang.reflect.InvocationTargetException;
@@ -50,17 +51,20 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/**
* Test for bug 450, which causes the right part of the frame to be black
* for all x >= height.
- *
+ *
* Draws the Gears demo in a window that's twice as wide than it is tall,
* and checks to see if a particular pixel in the right half of the frame
* is colored.
*
* @author Wade Walker (adapted from TestGearsGLJPanelAWT)
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLJPanelAWTBug450 extends UITestCase {
static GLProfile glp;
static int width, height;
@@ -83,35 +87,35 @@ public class TestGLJPanelAWTBug450 extends UITestCase {
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilities caps)
+ protected void runTestGL(final GLCapabilities caps)
throws AWTException, InterruptedException, InvocationTargetException
{
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
- JFrame frame = new JFrame("Swing GLJPanel");
+ final JFrame frame = new JFrame("Swing GLJPanel");
Assert.assertNotNull(frame);
- GLJPanel glJPanel = new GLJPanel(caps);
+ final GLJPanel glJPanel = new GLJPanel(caps);
Assert.assertNotNull(glJPanel);
- RedSquareES2 demo = new RedSquareES2();
+ final RedSquareES2 demo = new RedSquareES2();
demo.setAspect((float)width/(float)height);
demo.setDoRotation(false);
glJPanel.addGLEventListener(demo);
glJPanel.addGLEventListener(new GLEventListener() {
int f = 0;
@Override
- public void init(GLAutoDrawable drawable) {
- // drawable.getGL().glClearColor(0, 0, 1, 1);
+ public void init(final GLAutoDrawable drawable) {
+ // drawable.getGL().glClearColor(0, 0, 1, 1);
}
@Override
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
// look at one pixel at the bottom of the frame, just right of
// the center line, and make sure it's not black
- GL2 gl = GLUgl2.getCurrentGL2();
- ByteBuffer bytebuffer = ByteBuffer.allocateDirect( 3 );
- gl.glReadPixels( r_x, r_y, 1, 1, GL2.GL_BGR, GL2.GL_UNSIGNED_BYTE, bytebuffer );
- byte byte0 = bytebuffer.get( 0 );
- byte byte1 = bytebuffer.get( 1 );
- byte byte2 = bytebuffer.get( 2 );
+ final GL2 gl = GLUgl2.getCurrentGL2();
+ final ByteBuffer bytebuffer = ByteBuffer.allocateDirect( 3 );
+ gl.glReadPixels( r_x, r_y, 1, 1, GL2GL3.GL_BGR, GL.GL_UNSIGNED_BYTE, bytebuffer );
+ final byte byte0 = bytebuffer.get( 0 );
+ final byte byte1 = bytebuffer.get( 1 );
+ final byte byte2 = bytebuffer.get( 2 );
if( (byte0 == 0) && (byte1 == 0) && (byte2 == 0) ) {
failed = true;
}
@@ -122,23 +126,21 @@ public class TestGLJPanelAWTBug450 extends UITestCase {
f++;
}
@Override
- public void dispose(GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
@Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
- FPSAnimator animator = new FPSAnimator(glJPanel, 60);
+ final FPSAnimator animator = new FPSAnimator(glJPanel, 60);
- final JFrame _frame = frame;
- final GLJPanel _glJPanel = glJPanel;
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- _frame.getContentPane().add(_glJPanel, BorderLayout.CENTER);
- _frame.setSize(width, height);
- _frame.setVisible(true);
+ frame.getContentPane().add(glJPanel, BorderLayout.CENTER);
+ frame.setSize(width, height);
+ frame.setVisible(true);
} } ) ;
- animator.setUpdateFPSFrames(1, null);
+ animator.setUpdateFPSFrames(1, null);
animator.start();
Assert.assertEquals(true, animator.isAnimating());
@@ -154,11 +156,11 @@ public class TestGLJPanelAWTBug450 extends UITestCase {
Assert.assertEquals(false, animator.isAnimating());
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- _frame.setVisible(false);
- _frame.getContentPane().remove(_glJPanel);
- _frame.remove(_glJPanel);
- _glJPanel.destroy();
- _frame.dispose();
+ frame.setVisible(false);
+ frame.getContentPane().remove(glJPanel);
+ frame.remove(glJPanel);
+ glJPanel.destroy();
+ frame.dispose();
} } );
Assert.assertFalse( failed );
@@ -168,19 +170,19 @@ public class TestGLJPanelAWTBug450 extends UITestCase {
public void test01()
throws AWTException, InterruptedException, InvocationTargetException
{
- GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
runTestGL(caps);
}
static long duration = 500; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
}
org.junit.runner.JUnitCore.main(TestGLJPanelAWTBug450.class.getName());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java
index 498a3285a..8e2b02fb2 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,23 +20,24 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.gl2.awt;
import javax.media.opengl.*;
import com.jogamp.opengl.util.Animator;
+
import javax.media.opengl.awt.GLCanvas;
+
import com.jogamp.newt.event.awt.AWTKeyAdapter;
import com.jogamp.newt.event.awt.AWTWindowAdapter;
import com.jogamp.newt.event.TraceKeyAdapter;
import com.jogamp.newt.event.TraceWindowAdapter;
-
import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
@@ -52,11 +53,15 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGearsAWT extends UITestCase {
static GLProfile glp;
static int width, height;
static boolean waitForKey = false;
+ static int msaaCount = 0;
@BeforeClass
public static void initClass() {
@@ -76,13 +81,13 @@ public class TestGearsAWT extends UITestCase {
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilities caps) throws InterruptedException, InvocationTargetException {
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException, InvocationTargetException {
final Frame frame = new Frame("Gears AWT Test");
Assert.assertNotNull(frame);
final GLCanvas glCanvas = new GLCanvas(caps);
Assert.assertNotNull(glCanvas);
- Dimension glc_sz = new Dimension(width, height);
+ final Dimension glc_sz = new Dimension(width, height);
glCanvas.setMinimumSize(glc_sz);
glCanvas.setPreferredSize(glc_sz);
glCanvas.setSize(glc_sz);
@@ -90,18 +95,18 @@ public class TestGearsAWT extends UITestCase {
glCanvas.addGLEventListener(new Gears(1));
- Animator animator = new Animator(glCanvas);
- QuitAdapter quitAdapter = new QuitAdapter();
-
- new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glCanvas);
- new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glCanvas).addTo(glCanvas);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas).addTo(frame);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.pack();
frame.setVisible(true);
}});
- animator.setUpdateFPSFrames(60, System.err);
+
+ final Animator animator = new Animator(glCanvas);
+ animator.setUpdateFPSFrames(60, System.err);
animator.start();
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
@@ -114,7 +119,10 @@ public class TestGearsAWT extends UITestCase {
animator.stop();
Assert.assertEquals(false, animator.isAnimating());
- frame.setVisible(false);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
Assert.assertEquals(false, frame.isVisible());
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -125,29 +133,38 @@ public class TestGearsAWT extends UITestCase {
@Test
public void test01() throws InterruptedException, InvocationTargetException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ if( msaaCount > 0 ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(msaaCount);
+ }
runTestGL(caps);
}
static long duration = 500; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-msaa")) {
+ i++;
+ try {
+ msaaCount = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
} else if(args[i].equals("-wait")) {
waitForKey = true;
}
}
if(waitForKey) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
try {
System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ } catch (final IOException e) { }
}
org.junit.runner.JUnitCore.main(TestGearsAWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java
index 4807e5d25..751bd4488 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,26 +20,28 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.gl2.awt;
import javax.media.opengl.*;
import com.jogamp.opengl.util.Animator;
+
import javax.media.opengl.awt.GLCanvas;
+
import com.jogamp.newt.event.awt.AWTKeyAdapter;
import com.jogamp.newt.event.awt.AWTWindowAdapter;
import com.jogamp.newt.event.TraceKeyAdapter;
import com.jogamp.newt.event.TraceWindowAdapter;
-
import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
+
import java.awt.Frame;
import java.io.BufferedReader;
import java.io.IOException;
@@ -50,7 +52,10 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGearsAWTAnalyzeBug455 extends UITestCase {
static long duration = 500; // ms
static boolean waitForKey = false; // for manual profiling
@@ -76,28 +81,28 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase {
}
static class Swapper implements GLEventListener {
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
System.err.println("auto-swap: "+drawable.getAutoSwapBufferMode());
}
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
}
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
if(!drawable.getAutoSwapBufferMode()) {
- GL2 gl = drawable.getGL().getGL2();
+ final GL2 gl = drawable.getGL().getGL2();
// copy the colored content of the back buffer into the front buffer
// gl.glPushAttrib(GL.GL_COLOR_BUFFER_BIT);
gl.glReadBuffer(GL.GL_BACK); // def. in dbl buff mode: GL_BACK
gl.glDrawBuffer(GL.GL_FRONT); // def. in dbl buff mode: GL_BACK
- gl.glCopyPixels(0, 0, drawable.getWidth(), drawable.getHeight(), GL2.GL_COLOR);
+ gl.glCopyPixels(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), GL2ES3.GL_COLOR);
// gl.glPopAttrib();
gl.glDrawBuffer(GL.GL_BACK); // def. in dbl buff mode: GL_BACK
- }
+ }
+ }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width,
+ final int height) {
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width,
- int height) {
- }
}
- protected void runTestGL(GLCapabilities caps) throws InterruptedException, InvocationTargetException {
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException, InvocationTargetException {
final Frame frame = new Frame("Gears AWT Test");
Assert.assertNotNull(frame);
@@ -105,22 +110,22 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase {
Assert.assertNotNull(glCanvas);
glCanvas.setAutoSwapBufferMode(!altSwap);
frame.add(glCanvas);
- frame.setSize(512, 512);
glCanvas.addGLEventListener(new Gears(0));
glCanvas.addGLEventListener(new Swapper());
- Animator animator = new Animator(glCanvas);
- QuitAdapter quitAdapter = new QuitAdapter();
-
- new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glCanvas);
- new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glCanvas).addTo(glCanvas);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas).addTo(frame);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.setSize(512, 512);
frame.setVisible(true);
}});
- animator.setUpdateFPSFrames(60, System.err);
+
+ final Animator animator = new Animator(glCanvas);
+ animator.setUpdateFPSFrames(60, System.err);
animator.start();
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
@@ -133,7 +138,10 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase {
animator.stop();
Assert.assertEquals(false, animator.isAnimating());
- frame.setVisible(false);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
Assert.assertEquals(false, frame.isVisible());
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -144,18 +152,18 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase {
@Test
public void test01() throws InterruptedException, InvocationTargetException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
caps.setDoubleBuffered(true); // code assumes dbl buffer setup
runTestGL(caps);
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
} else if(args[i].equals("-wait")) {
waitForKey = true;
} else if(args[i].equals("-autoswap")) {
@@ -164,11 +172,11 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase {
}
System.err.println("altSwap "+altSwap);
if(waitForKey) {
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
try {
System.err.println(stdin.readLine());
- } catch (IOException e) { }
+ } catch (final IOException e) { }
}
org.junit.runner.JUnitCore.main(TestGearsAWTAnalyzeBug455.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java
index cb54c26bd..f47a9b794 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,25 +20,35 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.gl2.awt;
import javax.media.opengl.*;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.TraceKeyAdapter;
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTKeyAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
import com.jogamp.opengl.util.FPSAnimator;
+
import javax.media.opengl.awt.GLJPanel;
import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
import com.jogamp.opengl.test.junit.util.UITestCase;
+
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.lang.reflect.InvocationTargetException;
+
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
@@ -46,10 +56,19 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGearsGLJPanelAWT extends UITestCase {
static GLProfile glp;
static int width, height;
+ static boolean shallUsePBuffer = false;
+ static boolean shallUseBitmap = false;
+ static boolean useMSAA = false;
+ static int swapInterval = 0;
+ static boolean useAnimator = true;
+ static boolean manualTest = false;
@BeforeClass
public static void initClass() {
@@ -67,75 +86,236 @@ public class TestGearsGLJPanelAWT extends UITestCase {
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilities caps)
+ protected void runTestGL(final GLCapabilities caps)
throws AWTException, InterruptedException, InvocationTargetException
{
- JFrame frame = new JFrame("Swing GLJPanel");
+ final JFrame frame = new JFrame("Swing GLJPanel");
Assert.assertNotNull(frame);
- GLJPanel glJPanel = new GLJPanel(caps);
+ final GLJPanel glJPanel = new GLJPanel(caps);
Assert.assertNotNull(glJPanel);
- Dimension glc_sz = new Dimension(width, height);
+ final Dimension glc_sz = new Dimension(width, height);
glJPanel.setMinimumSize(glc_sz);
glJPanel.setPreferredSize(glc_sz);
glJPanel.setSize(glc_sz);
- glJPanel.addGLEventListener(new Gears());
+ glJPanel.addGLEventListener(new Gears(swapInterval));
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ glJPanel.addGLEventListener(snap);
- FPSAnimator animator = new FPSAnimator(glJPanel, 60);
+ final FPSAnimator animator = useAnimator ? new FPSAnimator(glJPanel, 60) : null;
- final JFrame _frame = frame;
- final GLJPanel _glJPanel = glJPanel;
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- _frame.getContentPane().add(_glJPanel, BorderLayout.CENTER);
- _frame.getContentPane().validate();
- _frame.pack();
- _frame.setVisible(true);
+ frame.getContentPane().add(glJPanel, BorderLayout.CENTER);
+ frame.getContentPane().validate();
+ frame.pack();
+ frame.setVisible(true);
} } ) ;
- animator.setUpdateFPSFrames(1, null);
- animator.start();
- Assert.assertEquals(true, animator.isAnimating());
+ if( useAnimator ) {
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.start();
+ Assert.assertEquals(true, animator.isAnimating());
+ }
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glJPanel).addTo(glJPanel);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glJPanel).addTo(frame);
+
+ final com.jogamp.newt.event.KeyListener kl = new com.jogamp.newt.event.KeyAdapter() {
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='m') {
+ final GLCapabilitiesImmutable capsPre = glJPanel.getChosenGLCapabilities();
+ final GLCapabilities capsNew = new GLCapabilities(capsPre.getGLProfile());
+ capsNew.copyFrom(capsPre);
+ final boolean msaa;
+ if( capsPre.getSampleBuffers() ) {
+ capsNew.setSampleBuffers(false);
+ capsNew.setDoubleBuffered(false);
+ msaa = false;
+ } else {
+ capsNew.setSampleBuffers(true);
+ capsNew.setNumSamples(4);
+ msaa = true;
+ }
+ System.err.println("[set MSAA "+msaa+" Caps had]: "+capsPre);
+ System.err.println("[set MSAA "+msaa+" Caps new]: "+capsNew);
+ System.err.println("XXX-A1: "+animator.toString());
+ glJPanel.setRequestedGLCapabilities(capsNew);
+ System.err.println("XXX-A2: "+animator.toString());
+ System.err.println("XXX: "+glJPanel.toString());
+ } else if(e.getKeyChar()=='b') {
+ final GLCapabilitiesImmutable capsPre = glJPanel.getChosenGLCapabilities();
+ final GLCapabilities capsNew = new GLCapabilities(capsPre.getGLProfile());
+ capsNew.copyFrom(capsPre);
+ final boolean bmp;
+ if( capsPre.isBitmap() ) {
+ capsNew.setBitmap(false); // auto-choose
+ bmp = false;
+ } else {
+ capsNew.setBitmap(true);
+ capsNew.setFBO(false);
+ capsNew.setPBuffer(false);
+ bmp = true;
+ }
+ System.err.println("[set Bitmap "+bmp+" Caps had]: "+capsPre);
+ System.err.println("[set Bitmap "+bmp+" Caps new]: "+capsNew);
+ System.err.println("XXX-A1: "+animator.toString());
+ glJPanel.setRequestedGLCapabilities(capsNew);
+ System.err.println("XXX-A2: "+animator.toString());
+ System.err.println("XXX: "+glJPanel.toString());
+ }
+ } };
+ new AWTKeyAdapter(kl, glJPanel).addTo(glJPanel);
- while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ boolean triggerSnap = false;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ snap.getDisplayCount();
+ if( !triggerSnap && snap.getDisplayCount() > 1 ) {
+ // Snapshot only after one frame has been rendered to suite FBO MSAA!
+ snap.setMakeSnapshot();
+ triggerSnap = true;
+ }
}
Assert.assertNotNull(frame);
Assert.assertNotNull(glJPanel);
Assert.assertNotNull(animator);
- animator.stop();
- Assert.assertEquals(false, animator.isAnimating());
+ if( useAnimator ) {
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ }
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- _frame.setVisible(false);
- _frame.getContentPane().remove(_glJPanel);
- _frame.remove(_glJPanel);
- _glJPanel.destroy();
- _frame.dispose();
+ frame.setVisible(false);
+ frame.getContentPane().remove(glJPanel);
+ frame.remove(glJPanel);
+ glJPanel.destroy();
+ frame.dispose();
} } );
}
@Test
- public void test01()
+ public void test01_DefaultNorm()
throws AWTException, InterruptedException, InvocationTargetException
{
- GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ if(useMSAA) {
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ }
+ if(shallUsePBuffer) {
+ caps.setPBuffer(true);
+ }
+ if(shallUseBitmap) {
+ caps.setBitmap(true);
+ }
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test02_DefaultMsaa()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test03_PbufferNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setPBuffer(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test04_PbufferMsaa()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ caps.setPBuffer(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test05_BitmapNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setBitmap(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test06_BitmapMsaa()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ caps.setBitmap(true);
runTestGL(caps);
}
static long duration = 500; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
- try {
- duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-msaa")) {
+ useMSAA = true;
+ } else if(args[i].equals("-noanim")) {
+ useAnimator = false;
+ } else if(args[i].equals("-pbuffer")) {
+ shallUsePBuffer = true;
+ } else if(args[i].equals("-bitmap")) {
+ shallUseBitmap = true;
+ } else if(args[i].equals("-manual")) {
+ manualTest = true;
}
}
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("useMSAA "+useMSAA);
+ System.err.println("useAnimator "+useAnimator);
+ System.err.println("shallUsePBuffer "+shallUsePBuffer);
+ System.err.println("shallUseBitmap "+shallUseBitmap);
+ System.err.println("manualTest "+manualTest);
+
org.junit.runner.JUnitCore.main(TestGearsGLJPanelAWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java
index 93dc885b6..4cefd95c0 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.gl2.newt;
import com.jogamp.newt.event.KeyAdapter;
@@ -45,7 +45,10 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGearsNEWT extends UITestCase {
static GLProfile glp;
static int width, height;
@@ -66,15 +69,15 @@ public class TestGearsNEWT extends UITestCase {
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilities caps) throws InterruptedException {
- GLWindow glWindow = GLWindow.create(caps);
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Gears NEWT Test");
glWindow.addGLEventListener(new Gears());
- Animator animator = new Animator(glWindow);
- QuitAdapter quitAdapter = new QuitAdapter();
+ final Animator animator = new Animator(glWindow);
+ final QuitAdapter quitAdapter = new QuitAdapter();
//glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
//glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
@@ -83,7 +86,10 @@ public class TestGearsNEWT extends UITestCase {
final GLWindow f_glWindow = glWindow;
glWindow.addKeyListener(new KeyAdapter() {
- public void keyTyped(KeyEvent e) {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
if(e.getKeyChar()=='f') {
new Thread() {
public void run() {
@@ -113,19 +119,19 @@ public class TestGearsNEWT extends UITestCase {
@Test
public void test01() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
runTestGL(caps);
}
static long duration = 500; // ms
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
try {
duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
}
org.junit.runner.JUnitCore.main(TestGearsNEWT.class.getName());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java
index cc20cc27e..beee5ffde 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.demos.gl2.newt;
import javax.media.nativewindow.*;
@@ -34,6 +34,7 @@ import javax.media.opengl.*;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
@@ -45,10 +46,16 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGearsNewtAWTWrapper extends UITestCase {
static GLProfile glp;
static int width, height;
+ static boolean useAnimator = true;
+ static boolean doResizeTest = true;
+ static long duration = 500; // ms
@BeforeClass
public static void initClass() {
@@ -62,70 +69,89 @@ public class TestGearsNewtAWTWrapper extends UITestCase {
public static void releaseClass() {
}
- protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException {
- Display nDisplay = NewtFactory.createDisplay(NativeWindowFactory.TYPE_AWT, null, false); // local display
- Screen nScreen = NewtFactory.createScreen(nDisplay, 0); // screen 0
- Window nWindow = NewtFactory.createWindow(nScreen, caps);
+ protected void runTestGL(final GLCapabilitiesImmutable caps) throws InterruptedException {
+ final Display nDisplay = NewtFactory.createDisplay(NativeWindowFactory.TYPE_AWT, null, false); // local display
+ final Screen nScreen = NewtFactory.createScreen(nDisplay, 0); // screen 0
+ final Window nWindow = NewtFactory.createWindow(nScreen, caps);
- GLWindow glWindow = GLWindow.create(nWindow);
+ final GLWindow glWindow = GLWindow.create(nWindow);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Gears NewtAWTWrapper Test");
glWindow.addGLEventListener(new GearsES2(1));
- Animator animator = new Animator(glWindow);
- QuitAdapter quitAdapter = new QuitAdapter();
+ final Animator animator = useAnimator ? new Animator(glWindow) : null;
+ final QuitAdapter quitAdapter = new QuitAdapter();
glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
+ if( useAnimator ) {
+ animator.start();
+ }
+
int div = 3;
glWindow.setSize(width/div, height/div);
glWindow.setVisible(true);
- glWindow.display();
- Assert.assertTrue("Size not reached: Expected "+(width/div)+"x"+(height/div)+", Is "+glWindow.getWidth()+"x"+glWindow.getHeight(),
- AWTRobotUtil.waitForSize(glWindow, width/div, height/div));
-
- div = 2;
- glWindow.setSize(width/div, height/div);
- glWindow.display();
- Assert.assertTrue("Size not reached: Expected "+(width/div)+"x"+(height/div)+", Is "+glWindow.getWidth()+"x"+glWindow.getHeight(),
- AWTRobotUtil.waitForSize(glWindow, width/div, height/div));
-
- div = 1;
- glWindow.setSize(width/div, height/div);
- glWindow.display();
- Assert.assertTrue("Size not reached: Expected "+(width/div)+"x"+(height/div)+", Is "+glWindow.getWidth()+"x"+glWindow.getHeight(),
- AWTRobotUtil.waitForSize(glWindow, width/div, height/div));
-
- animator.setUpdateFPSFrames(1, null);
- animator.start();
+ if( doResizeTest ) {
+ glWindow.display();
+ final int[] expSurfaceSize = glWindow.getNativeSurface().convertToPixelUnits(new int[] { width/div, height/div });
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glWindow, expSurfaceSize[0], expSurfaceSize[1]));
+ Thread.sleep(600);
+
+ div = 2;
+ glWindow.setSize(width/div, height/div);
+ glWindow.display();
+ expSurfaceSize[0] = width/div;
+ expSurfaceSize[1] = height/div;
+ glWindow.getNativeSurface().convertToPixelUnits(expSurfaceSize);
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glWindow, expSurfaceSize[0], expSurfaceSize[1]));
+ Thread.sleep(600);
+
+ div = 1;
+ glWindow.setSize(width/div, height/div);
+ glWindow.display();
+ expSurfaceSize[0] = width/div;
+ expSurfaceSize[1] = height/div;
+ glWindow.getNativeSurface().convertToPixelUnits(expSurfaceSize);
+ Assert.assertTrue("Surface Size not reached: Expected "+expSurfaceSize[0]+"x"+expSurfaceSize[1]+", Is "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight(),
+ AWTRobotUtil.waitForSize(glWindow, expSurfaceSize[0], expSurfaceSize[1]));
+ Thread.sleep(600);
+ }
- while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1-t0<duration) {
Thread.sleep(100);
+ t1 = System.currentTimeMillis();
}
- animator.stop();
+ if( useAnimator ) {
+ animator.stop();
+ }
glWindow.destroy();
}
@Test
public void test01() throws InterruptedException {
- GLCapabilitiesImmutable caps = new GLCapabilities(glp);
+ final GLCapabilitiesImmutable caps = new GLCapabilities(glp);
runTestGL(caps);
}
- static long duration = 500; // ms
-
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
- try {
- duration = Integer.parseInt(args[i]);
- } catch (Exception ex) { ex.printStackTrace(); }
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-noanim")) {
+ useAnimator = false;
+ } else if(args[i].equals("-noresize")) {
+ doResizeTest = false;
}
}
+ System.err.println("useAnimator "+useAnimator);
org.junit.runner.JUnitCore.main(TestGearsNewtAWTWrapper.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestTeapotNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestTeapotNEWT.java
new file mode 100644
index 000000000..975d35ad2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestTeapotNEWT.java
@@ -0,0 +1,162 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.gl2.newt;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+
+import com.jogamp.opengl.util.Animator;
+
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Teapot;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTeapotNEWT extends UITestCase {
+ static GLProfile glp;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.get(GLProfile.GL2);
+ Assert.assertNotNull(glp);
+ width = 640;
+ height = 480;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final boolean withAnimator) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+
+ glWindow.setTitle("Teapot NEWT Test");
+ final Teapot demo = new Teapot();
+ if( !withAnimator ) {
+ demo.rotIncr *= 10f;
+ }
+ glWindow.addGLEventListener(demo);
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ glWindow.addGLEventListener(snap);
+
+ final Animator animator = withAnimator ? new Animator(glWindow) : null;
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
+ //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+ if( withAnimator ) {
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.start();
+ }
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ int snaps=3;
+ while(!quitAdapter.shouldQuit() && t1-t0<duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ if( snaps-- > 0 ) {
+ snap.setMakeSnapshot();
+ }
+ if( !withAnimator ) {
+ glWindow.display();
+ }
+ }
+
+ if( withAnimator ) {
+ animator.stop();
+ }
+ glWindow.destroy();
+ }
+
+ @Test
+ public void test01_DefCaps_Anim() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true));
+ runTestGL(caps, true);
+ }
+
+ @Test
+ public void test02_DefCaps_NoAnim() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true));
+ runTestGL(caps, false);
+ }
+
+ @Test
+ public void test12_FBOCaps_NoAnim() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true));
+ caps.setHardwareAccelerated(true);
+ caps.setDoubleBuffered(true);
+ caps.setAlphaBits(8);
+ caps.setDepthBits(8);
+ caps.setNumSamples(0);
+ caps.setSampleBuffers(false);
+ caps.setStencilBits(0);
+ caps.setRedBits(8);
+ caps.setBlueBits(8);
+ caps.setGreenBits(8);
+
+ // caps.setPBuffer(true);
+ caps.setFBO(true);
+
+ runTestGL(caps, false);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestTeapotNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java
new file mode 100644
index 000000000..30840c1b7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java
@@ -0,0 +1,292 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.gl3;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLConnection;
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.util.glsl.ShaderUtil;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * JOGL Geometry ShaderCode test case using OpenGL 3.2 core profile features only.
+ * <p>
+ * Demonstrates <code>pass through</code> and <code>XYZ flipping</code>
+ * geometry shader.
+ * </p>
+ * <p>
+ * If the <code>XYZ flipping</code> geometry shader functions properly,
+ * the texture will be flipped horizontally and vertically.
+ * </p>
+ *
+ * @author Chuck Ritola December 2012
+ * @author Sven Gothel (GL3 core, pass-though, core geometry shader)
+ */
+public class GeomShader01TextureGL3 implements GLEventListener {
+ private final int geomShader;
+ private Texture texture;
+ private ShaderState st;
+ private PMVMatrix pmvMatrix;
+ private GLUniformData pmvMatrixUniform;
+ private GLArrayDataServer interleavedVBO;
+
+ static final String shaderBasename = "texture01_xxx";
+ static final String[] geomShaderBaseNames = new String[] { "passthrough01_xxx", "flipXYZ01_xxx" };
+
+ public GeomShader01TextureGL3(final int geomShader) {
+ this.geomShader = geomShader;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ {
+ final GL gl = drawable.getGL();
+ System.err.println("Init - START - useGeomShader "+geomShader+" -> "+geomShaderBaseNames[geomShader]);
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+ System.err.println("GL Profile: "+gl.getGLProfile());
+ System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
+ System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
+ if( !gl.isGL3() ) {
+ throw new RuntimeException("GL object not a GL3 core compatible profile: "+gl);
+ }
+ if( !ShaderUtil.isGeometryShaderSupported(gl) ) {
+ throw new RuntimeException("GL object not >= 3.2, i.e. no geometry shader support.: "+gl);
+ }
+ }
+ final GL3 gl = drawable.getGL().getGL3();
+
+ final ShaderProgram sp;
+ {
+ final ShaderCode vs, gs, fs;
+ vs = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
+ "shader", "shader/bin", shaderBasename, true);
+ gs = ShaderCode.create(gl, GL3.GL_GEOMETRY_SHADER, this.getClass(),
+ "shader", "shader/bin", geomShaderBaseNames[geomShader], true);
+ fs = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
+ "shader", "shader/bin", shaderBasename, true);
+ vs.defaultShaderCustomization(gl, true, true);
+ gs.defaultShaderCustomization(gl, true, true);
+ fs.defaultShaderCustomization(gl, true, true);
+
+ sp = new ShaderProgram();
+ sp.add(gl, vs, System.err);
+ sp.add(gl, gs, System.err);
+ sp.add(gl, fs, System.err);
+ if(!sp.link(gl, System.err)) {
+ throw new GLException("Couldn't link program: "+sp);
+ }
+ }
+
+ st=new ShaderState();
+ st.attachShaderProgram(gl, sp, true);
+
+ // setup mgl_PMVMatrix
+ pmvMatrix = new PMVMatrix();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+
+ st.ownUniform(pmvMatrixUniform);
+ if(!st.uniform(gl, pmvMatrixUniform)) {
+ throw new GLException("Error setting PMVMatrix in shader: "+st);
+ }
+ if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", 0))) {
+ throw new GLException("Error setting mgl_ActiveTexture in shader: "+st);
+ }
+
+ try {
+ texture = createTestTexture(gl);
+ } catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ if(null == texture) {
+ throw new RuntimeException("Could not load test texture");
+ }
+
+ // Tri order:
+ // TL, BL, BR
+ // TL, TR, BR
+ {
+ int i=0;
+ final TextureCoords tc = texture.getImageTexCoords();
+ s_triTexCoords[i++] = tc.left(); s_triTexCoords[i++] = tc.top();
+ s_triTexCoords[i++] = tc.left(); s_triTexCoords[i++] = tc.bottom();
+ s_triTexCoords[i++] = tc.right(); s_triTexCoords[i++] = tc.bottom();
+ s_triTexCoords[i++] = tc.left(); s_triTexCoords[i++] = tc.top();
+ s_triTexCoords[i++] = tc.right(); s_triTexCoords[i++] = tc.top();
+ s_triTexCoords[i++] = tc.right(); s_triTexCoords[i++] = tc.bottom();
+ }
+
+ interleavedVBO = GLArrayDataServer.createGLSLInterleaved(2+4+2, GL.GL_FLOAT, false, 3*6, GL.GL_STATIC_DRAW);
+ {
+ interleavedVBO.addGLSLSubArray("mgl_Vertex", 2, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
+
+ final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
+
+ for(int i=0; i<6; i++) {
+ ib.put(s_triVertices, i*2, 2);
+ ib.put(s_triColors, i*4, 4);
+ ib.put(s_triTexCoords, i*2, 2);
+ }
+ }
+ interleavedVBO.seal(gl, true);
+ interleavedVBO.enableBuffer(gl, false);
+ st.ownAttribute(interleavedVBO, true);
+
+ gl.glClearColor(0f, 0f, 0f, 0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ st.useProgram(gl, false);
+ }
+
+ private Texture createTestTexture(final GL3 gl) throws IOException {
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), "../../util/texture/test-ntscN_3-01-160x90.png");
+ if(null == urlConn) { return null; }
+ final InputStream istream = urlConn.getInputStream();
+ if(null == istream) { return null; }
+ final TextureData texData = TextureIO.newTextureData(gl.getGLProfile(), istream, false /* mipmap */, TextureIO.PNG);
+ final Texture res = TextureIO.newTexture(gl, texData);
+ texData.destroy();
+ return res;
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL3 gl = drawable.getGL().getGL3();
+ if(null!=texture) {
+ texture.disable(gl);
+ texture.destroy(gl);
+ }
+
+ if(null != st) {
+ pmvMatrixUniform = null;
+ pmvMatrix=null;
+ st.destroy(gl);
+ st=null;
+ }
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL3 gl = drawable.getGL().getGL3();
+
+ gl.setSwapInterval(1);
+
+ // Clear background to white
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.4f);
+
+ if(null != st) {
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ }
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL3 gl = drawable.getGL().getGL3();
+
+ gl.glClear(GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT);
+
+ if(null != st) {
+ //Draw the image as a pseudo-quad using two triangles
+ st.useProgram(gl, true);
+ interleavedVBO.enableBuffer(gl, true);
+ gl.glActiveTexture(GL.GL_TEXTURE0);
+ texture.enable(gl);
+ texture.bind(gl);
+
+ gl.glDrawArrays(GL.GL_TRIANGLES, 0, 6);
+
+ texture.disable(gl);
+ interleavedVBO.enableBuffer(gl, false);
+ st.useProgram(gl, false);
+ }
+ }//end display()
+
+ private static final float[] s_triVertices = {
+ -1f, 1f, // TL
+ -1f, -1f, // BL
+ 1f, -1f, // BR
+ -1f, 1f, // TL
+ 1f, 1f, // TR
+ 1f, -1f // BR
+ };
+ private static final float[] s_triColors = {
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f,
+ 1f, 1f, 1f, 1f
+ };
+ private static final float[] s_triTexCoords = {
+ 0f, 1f, // TL
+ 0f, 0f, // BL
+ 1f, 0f, // BR
+ 0f, 1f, // TL
+ 1f, 1f, // TR
+ 1f, 0f // BR
+ };
+
+}//end Test
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/newt/TestGeomShader01TextureGL3NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/newt/TestGeomShader01TextureGL3NEWT.java
new file mode 100644
index 000000000..583334e1f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/newt/TestGeomShader01TextureGL3NEWT.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.gl3.newt;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.gl3.GeomShader01TextureGL3;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Test Geometry shader demo GeomShader01TextureGL3
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGeomShader01TextureGL3NEWT extends UITestCase {
+ static long duration = 500; // ms
+
+ static GLCapabilities getCaps(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ @Test
+ public void test01_GL3Core_Passthrough() throws InterruptedException {
+ final GLCapabilities caps = getCaps(GLProfile.GL3);
+ if( null == caps ) { return; }
+ testImpl(caps, 0);
+ }
+
+ @Test
+ public void test02_GL3Core_FlipXYZ() throws InterruptedException {
+ final GLCapabilities caps = getCaps(GLProfile.GL3);
+ if( null == caps ) { return; }
+ testImpl(caps, 1);
+ }
+
+ @Test
+ public void test11_GL3Compat_Passthrough() throws InterruptedException {
+ final GLCapabilities caps = getCaps(GLProfile.GL3bc);
+ if( null == caps ) { return; }
+ testImpl(caps, 0);
+ }
+
+ @Test
+ public void test12_GL3Compat_FlipXYZ() throws InterruptedException {
+ final GLCapabilities caps = getCaps(GLProfile.GL3bc);
+ if( null == caps ) { return; }
+ testImpl(caps, 1);
+ }
+
+ private void testImpl(final GLCapabilities caps, final int geomShader) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setSize(800, 600);
+ glWindow.setVisible(true);
+ glWindow.setTitle("JOGL Geometry Shader Banana Test");
+ Assert.assertTrue(glWindow.isNativeValid());
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+ glWindow.addGLEventListener( new GeomShader01TextureGL3(geomShader) );
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ glWindow.addGLEventListener(snapshotGLEventListener);
+
+ final Animator animator = new Animator(glWindow);
+ animator.start();
+
+ animator.setUpdateFPSFrames(60, System.err);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+ glWindow.destroy();
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestGeomShader01TextureGL3NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/flipXYZ01_xxx.gp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/flipXYZ01_xxx.gp
new file mode 100644
index 000000000..f65ffacdb
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/flipXYZ01_xxx.gp
@@ -0,0 +1,32 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+// Requires version >= 150
+
+layout (triangles) in;
+layout (triangle_strip, max_vertices=3) out;
+
+in VertexData {
+ vec4 frontColor;
+ vec2 texCoord;
+} vp_data[3];
+
+out VertexData {
+ vec4 frontColor;
+ vec2 texCoord;
+} gp_data;
+
+void main()
+{
+ for(int i = 0; i < gl_in.length(); i++)
+ {
+ // copy attributes
+ gl_Position = vec4(gl_in[i].gl_Position.xyz*-1,1); // This line flips the coordinates.
+ gp_data.frontColor = vp_data[i].frontColor;
+ gp_data.texCoord = vp_data[i].texCoord;
+
+ // done with the vertex
+ EmitVertex();
+ }
+}
+
+
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/passthrough01_xxx.gp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/passthrough01_xxx.gp
new file mode 100644
index 000000000..588b72426
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/passthrough01_xxx.gp
@@ -0,0 +1,31 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+// Requires version >= 150
+
+layout (triangles) in;
+layout (triangle_strip, max_vertices=3) out;
+
+in VertexData {
+ vec4 frontColor;
+ vec2 texCoord;
+} vp_data[3];
+
+out VertexData {
+ vec4 frontColor;
+ vec2 texCoord;
+} gp_data;
+
+void main()
+{
+ for(int i = 0; i < gl_in.length(); i++)
+ {
+ // copy attributes
+ gl_Position = gl_in[i].gl_Position;
+ gp_data.frontColor = vp_data[i].frontColor;
+ gp_data.texCoord = vp_data[i].texCoord;
+
+ // done with the vertex
+ EmitVertex();
+ }
+}
+
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.fp
new file mode 100644
index 000000000..61f4529ac
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.fp
@@ -0,0 +1,20 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+// Requires version >= 130
+
+in VertexData {
+ vec4 frontColor;
+ vec2 texCoord;
+} gp_data;
+
+out vec4 mgl_FragColor;
+
+uniform sampler2D mgl_ActiveTexture;
+
+void main (void)
+{
+ vec4 texColor = texture(mgl_ActiveTexture, gp_data.texCoord);
+
+ // mix frontColor with texture ..
+ mgl_FragColor = vec4(gp_data.frontColor*texColor);
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.vp
new file mode 100644
index 000000000..b220c83f1
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.vp
@@ -0,0 +1,20 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+// Requires version >= 130
+
+uniform mat4 mgl_PMVMatrix[2];
+
+in vec4 mgl_Vertex;
+in vec4 mgl_Color;
+in vec4 mgl_MultiTexCoord;
+
+out VertexData {
+ vec4 frontColor;
+ vec2 texCoord;
+} vp_data;
+
+void main(void)
+{
+ vp_data.frontColor = mgl_Color;
+ vp_data.texCoord = mgl_MultiTexCoord.st;
+ gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/IInstancedRenderingView.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/IInstancedRenderingView.java
new file mode 100644
index 000000000..e76db6ab5
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/IInstancedRenderingView.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+ package com.jogamp.opengl.test.junit.jogl.demos.gl4;
+
+public interface IInstancedRenderingView {
+ float getScale();
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TessellationShader01aGLSL440CoreHardcoded.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TessellationShader01aGLSL440CoreHardcoded.java
new file mode 100644
index 000000000..223eb1a14
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TessellationShader01aGLSL440CoreHardcoded.java
@@ -0,0 +1,225 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.gl4;
+
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GL4;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+
+/**
+ * JOGL Tessellation ShaderCode GL4 test case.
+ * <p>
+ * Demonstrates tessellation-control and -evaluation shaders.
+ * </p>
+ *
+ * @author Raymond L. Rivera, 2014
+ * @author Sven Gothel
+ */
+public class TessellationShader01aGLSL440CoreHardcoded implements GLEventListener {
+ private static final double ANIMATION_RATE = 950.0;
+
+ private ShaderProgram program;
+ private final int[] vertexArray = new int[1];
+ private FloatBuffer vertexOffset;
+ private FloatBuffer backgroundColor;
+
+
+ @Override
+ public void init(final GLAutoDrawable auto) {
+ final GL4 gl = auto.getGL().getGL4();
+ program = createProgram(auto);
+ if( null == program ) {
+ return;
+ }
+
+ final double theta = System.currentTimeMillis() / ANIMATION_RATE;
+ vertexOffset = FloatBuffer.allocate(4);
+ vertexOffset.put(0, (float)(Math.sin(theta) * 0.5f));
+ vertexOffset.put(1, (float)(Math.cos(theta) * 0.6f));
+ vertexOffset.put(2, 0.0f);
+ vertexOffset.put(3, 0.0f);
+
+ backgroundColor = FloatBuffer.allocate(4);
+ backgroundColor.put(0, 0.25f);
+ backgroundColor.put(1, 0.25f);
+ backgroundColor.put(2, 0.25f);
+ backgroundColor.put(3, 1.0f);
+
+ gl.glGenVertexArrays(vertexArray.length, vertexArray, 0);
+ gl.glBindVertexArray(vertexArray[0]);
+ gl.glPatchParameteri(GL4.GL_PATCH_VERTICES, 3);
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable auto) {
+ if( null == program ) {
+ return;
+ }
+ final GL4 gl = auto.getGL().getGL4();
+ final double value = System.currentTimeMillis() / ANIMATION_RATE;
+ gl.glClearBufferfv(GL2ES3.GL_COLOR, 0, backgroundColor);
+ gl.glUseProgram(program.program());
+ vertexOffset.put(0, (float)(Math.sin(value) * 0.5f));
+ vertexOffset.put(1, (float)(Math.cos(value) * 0.6f));
+ gl.glVertexAttrib4fv(0, vertexOffset);
+ gl.glDrawArrays(GL4.GL_PATCHES, 0, 3);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable auto) {
+ if( null == program ) {
+ return;
+ }
+ final GL4 gl = auto.getGL().getGL4();
+ gl.glDeleteVertexArrays(vertexArray.length, vertexArray, 0);
+ program.destroy(gl);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable auto, final int x, final int y, final int width, final int height) {
+ // final GL4 gl = auto.getGL().getGL4();
+ }
+
+ private ShaderProgram createProgram(final GLAutoDrawable auto) {
+ final GL4 gl = auto.getGL().getGL4();
+ final String vertexSource =
+ "#version 440 core \n" +
+ " \n" +
+ "layout (location = 0) in vec4 offset; \n" +
+ " \n" +
+ "void main(void) \n" +
+ "{ \n" +
+ " const vec4 vertices[3] = vec4[3] ( \n" +
+ " vec4( 0.25, 0.25, 0.5, 1.0), \n" +
+ " vec4(-0.25, -0.25, 0.5, 1.0), \n" +
+ " vec4( 0.25, -0.25, 0.5, 1.0)); \n" +
+ " gl_Position = vertices[gl_VertexID] + offset; \n" +
+ "} \n";
+ final String tessCtrlSource =
+ "#version 440 core \n" +
+ "layout (vertices = 3) out; \n" +
+ " \n" +
+ "void main(void) \n" +
+ "{ \n" +
+ " if (gl_InvocationID == 0) \n" +
+ " { \n" +
+ " gl_TessLevelInner[0] = 5.0; \n" +
+ " gl_TessLevelOuter[0] = 5.0; \n" +
+ " gl_TessLevelOuter[1] = 5.0; \n" +
+ " gl_TessLevelOuter[2] = 5.0; \n" +
+ " } \n" +
+ " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" +
+ "} \n";
+ final String tessEvalSource =
+ "#version 440 core \n" +
+ " \n" +
+ "layout (triangles, equal_spacing, cw) in; \n" +
+ " \n" +
+ "void main(void) \n" +
+ "{ \n" +
+ " gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) + \n" +
+ " (gl_TessCoord.y * gl_in[1].gl_Position) + \n" +
+ " (gl_TessCoord.z * gl_in[2].gl_Position); \n" +
+ "} \n";
+ final String fragmentSource =
+ "#version 440 core \n" +
+ " \n" +
+ "out vec4 color; \n" +
+ " \n" +
+ "void main(void) \n" +
+ "{ \n" +
+ " color = vec4(1.0, 1.0, 1.0, 1.0); \n" +
+ "} \n";
+
+ final ShaderCode vertexShader = createShader(gl, GL2ES2.GL_VERTEX_SHADER, vertexSource);
+ if( null == vertexShader ) {
+ return null;
+ }
+ final ShaderCode tessCtrlShader = createShader(gl, GL4.GL_TESS_CONTROL_SHADER, tessCtrlSource);
+ if( null == tessCtrlShader ) {
+ vertexShader.destroy(gl);
+ return null;
+ }
+ final ShaderCode tessEvalShader = createShader(gl, GL4.GL_TESS_EVALUATION_SHADER, tessEvalSource);
+ if( null == tessEvalShader ) {
+ vertexShader.destroy(gl);
+ tessCtrlShader.destroy(gl);
+ return null;
+ }
+ final ShaderCode fragmentShader = createShader(gl, GL2ES2.GL_FRAGMENT_SHADER, fragmentSource);
+ if( null == fragmentShader ) {
+ vertexShader.destroy(gl);
+ tessCtrlShader.destroy(gl);
+ tessEvalShader.destroy(gl);
+ return null;
+ }
+
+ final ShaderProgram program = new ShaderProgram();
+
+ program.init(gl);
+ program.add(vertexShader);
+ program.add(tessCtrlShader);
+ program.add(tessEvalShader);
+ program.add(fragmentShader);
+
+ program.link(gl, System.err);
+ if( !program.validateProgram(gl, System.out) ) {
+ System.err.println("[error] Program linking failed.");
+ program.destroy(gl);
+ return null;
+ } else {
+ return program;
+ }
+ }
+
+ private ShaderCode createShader(final GL4 gl, final int shaderType, final String source) {
+ final String[][] sources = new String[1][1];
+ sources[0] = new String[]{ source };
+ final ShaderCode shader = new ShaderCode(shaderType, sources.length, sources);
+
+ final boolean compiled = shader.compile(gl, System.err);
+ if (!compiled) {
+ System.err.println("[error] Shader compilation failed.");
+ shader.destroy(gl);
+ return null;
+ } else {
+ return shader;
+ }
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TessellationShader01bGL4.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TessellationShader01bGL4.java
new file mode 100644
index 000000000..bcf4fa6ca
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TessellationShader01bGL4.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.gl4;
+
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GL4;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+
+/**
+ * JOGL Tessellation ShaderCode GL4 test case.
+ * <p>
+ * Demonstrates tessellation-control and -evaluation shaders.
+ * </p>
+ *
+ * @author Raymond L. Rivera, 2014
+ * @author Sven Gothel
+ */
+public class TessellationShader01bGL4 implements GLEventListener {
+ private static final double ANIMATION_RATE = 950.0;
+
+ private ShaderProgram program;
+ private final int[] vertexArray = new int[1];
+ private FloatBuffer vertexOffset;
+ private FloatBuffer backgroundColor;
+
+
+ @Override
+ public void init(final GLAutoDrawable auto) {
+ final GL4 gl = auto.getGL().getGL4();
+ program = createProgram(auto);
+ if( null == program ) {
+ return;
+ }
+
+ final double theta = System.currentTimeMillis() / ANIMATION_RATE;
+ vertexOffset = FloatBuffer.allocate(4);
+ vertexOffset.put(0, (float)(Math.sin(theta) * 0.5f));
+ vertexOffset.put(1, (float)(Math.cos(theta) * 0.6f));
+ vertexOffset.put(2, 0.0f);
+ vertexOffset.put(3, 0.0f);
+
+ backgroundColor = FloatBuffer.allocate(4);
+ backgroundColor.put(0, 0.25f);
+ backgroundColor.put(1, 0.25f);
+ backgroundColor.put(2, 0.25f);
+ backgroundColor.put(3, 1.0f);
+
+ gl.glGenVertexArrays(vertexArray.length, vertexArray, 0);
+ gl.glBindVertexArray(vertexArray[0]);
+ gl.glPatchParameteri(GL4.GL_PATCH_VERTICES, 3);
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable auto) {
+ if( null == program ) {
+ return;
+ }
+ final GL4 gl = auto.getGL().getGL4();
+ final double value = System.currentTimeMillis() / ANIMATION_RATE;
+ gl.glClearBufferfv(GL2ES3.GL_COLOR, 0, backgroundColor);
+ gl.glUseProgram(program.program());
+ vertexOffset.put(0, (float)(Math.sin(value) * 0.5f));
+ vertexOffset.put(1, (float)(Math.cos(value) * 0.6f));
+ gl.glVertexAttrib4fv(0, vertexOffset);
+ gl.glDrawArrays(GL4.GL_PATCHES, 0, 3);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable auto) {
+ if( null == program ) {
+ return;
+ }
+ final GL4 gl = auto.getGL().getGL4();
+ gl.glDeleteVertexArrays(vertexArray.length, vertexArray, 0);
+ program.destroy(gl);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable auto, final int x, final int y, final int width, final int height) {
+ // final GL4 gl = auto.getGL().getGL4();
+ }
+
+ static final String shaderBasename = "tess_example01";
+
+ private ShaderProgram createProgram(final GLAutoDrawable auto) {
+ final GL4 gl = auto.getGL().getGL4();
+
+ final ShaderProgram sp;
+ {
+ final ShaderCode vs, tcs, tes, fs;
+ vs = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
+ "shader", "shader/bin", shaderBasename, true);
+ tcs = ShaderCode.create(gl, GL4.GL_TESS_CONTROL_SHADER, this.getClass(),
+ "shader", "shader/bin", shaderBasename, true);
+ tes = ShaderCode.create(gl, GL4.GL_TESS_EVALUATION_SHADER, this.getClass(),
+ "shader", "shader/bin", shaderBasename, true);
+ fs = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
+ "shader", "shader/bin", shaderBasename, true);
+ vs.defaultShaderCustomization(gl, true, true);
+ tcs.defaultShaderCustomization(gl, true, true);
+ tes.defaultShaderCustomization(gl, true, true);
+ fs.defaultShaderCustomization(gl, true, true);
+
+ sp = new ShaderProgram();
+ sp.add(gl, vs, System.err);
+ sp.add(gl, tcs, System.err);
+ sp.add(gl, tes, System.err);
+ sp.add(gl, fs, System.err);
+ }
+ if( !sp.link(gl, System.err) ) {
+ System.err.println("[error] Couldn't link program: "+sp);
+ sp.destroy(gl);
+ return null;
+ } else {
+ return sp;
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TriangleInstancedRendererWithShaderState.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TriangleInstancedRendererWithShaderState.java
new file mode 100644
index 000000000..9ba0c8d59
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TriangleInstancedRendererWithShaderState.java
@@ -0,0 +1,269 @@
+package com.jogamp.opengl.test.junit.jogl.demos.gl4;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.FloatBuffer;
+import java.util.Random;
+
+import javax.media.opengl.DebugGL4;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL4;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.TraceGL4;
+
+import com.jogamp.opengl.math.Matrix4;
+import com.jogamp.opengl.util.GLArrayDataClient;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+public class TriangleInstancedRendererWithShaderState implements GLEventListener {
+ private float aspect;
+
+ private static final String shaderBasename = "triangles";
+// private static final boolean useInterleaved = false;
+ private static final boolean useInterleaved = true;
+
+ private ShaderState st;
+ private PMVMatrix projectionMatrix;
+ private GLUniformData projectionMatrixUniform;
+ private GLUniformData transformMatrixUniform;
+
+ private GLArrayDataServer interleavedVBO;
+ private GLArrayDataClient verticesVBO;
+ private GLArrayDataClient colorsVBO;
+
+ private static final int NO_OF_INSTANCE = 30;
+ private final FloatBuffer triangleTransform = FloatBuffer.allocate(16 * NO_OF_INSTANCE);
+ private final Matrix4[] mat = new Matrix4[NO_OF_INSTANCE];
+ private final float[] rotationSpeed = new float[NO_OF_INSTANCE];
+
+ private static final boolean useTraceGL = false;
+ private PrintStream stream;
+ private final IInstancedRenderingView view;
+
+ private boolean isInitialized = false;
+
+ public TriangleInstancedRendererWithShaderState(IInstancedRenderingView view) {
+ this.view = view;
+
+ if(useTraceGL) {
+ try {
+ stream = new PrintStream(new FileOutputStream(new File("instanced-with-st.txt")));
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ initTransform();
+ }
+
+ private void initTransform() {
+ Random rnd = new Random();
+ for(int i = 0; i < NO_OF_INSTANCE; i++) {
+ rotationSpeed[i] = 0.3f * rnd.nextFloat();
+ mat[i] = new Matrix4();
+ mat[i].loadIdentity();
+ float scale = 1f + 4 * rnd.nextFloat();
+ mat[i].scale(scale, scale, scale);
+ //setup initial position of each triangle
+ mat[i].translate(20f * rnd.nextFloat() - 10f,
+ 10f * rnd.nextFloat() - 5f,
+ 0f);
+ }
+ }
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ GL4 gl = drawable.getGL().getGL4();
+ drawable.setGL(new DebugGL4(gl));
+ if(useTraceGL) {
+ drawable.setGL(new TraceGL4(gl, stream));
+ }
+
+ gl.glClearColor(1, 1, 1, 1); //white background
+// gl.glClearColor(0, 0, 0, 1); //black background
+ gl.glClearDepth(1.0f);
+
+ System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL4.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL4.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL4.GL_VERSION));
+
+ initShader(gl);
+ projectionMatrix = new PMVMatrix();
+ projectionMatrixUniform = new GLUniformData("mgl_PMatrix", 4, 4, projectionMatrix.glGetPMatrixf());
+ st.ownUniform(projectionMatrixUniform);
+ if(!st.uniform(gl, projectionMatrixUniform)) {
+ throw new GLException("Error setting mgl_PMatrix in shader: " + st);
+ }
+
+ transformMatrixUniform = new GLUniformData("mgl_MVMatrix", 4, 4, triangleTransform);
+
+ st.ownUniform(transformMatrixUniform);
+ if(!st.uniform(gl, transformMatrixUniform)) {
+ throw new GLException("Error setting mgl_MVMatrix in shader: " + st);
+ }
+
+ if(useInterleaved) {
+ initVBO_interleaved(gl);
+ } else {
+ initVBO_nonInterleaved(gl);
+ }
+
+ isInitialized = true;
+ }
+
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ if(!isInitialized ) return;
+
+ GL4 gl = drawable.getGL().getGL4();
+ gl.glClear(GL4.GL_COLOR_BUFFER_BIT | GL4.GL_DEPTH_BUFFER_BIT);
+
+ st.useProgram(gl, true);
+ projectionMatrix.glMatrixMode(GL2.GL_PROJECTION);
+ projectionMatrix.glPushMatrix();
+
+ float winScale = 0.1f;
+ if(view != null) winScale = view.getScale();
+ projectionMatrix.glScalef(winScale, winScale, winScale);
+ projectionMatrix.update();
+ st.uniform(gl, projectionMatrixUniform);
+ projectionMatrix.glPopMatrix();
+
+ generateTriangleTransform();
+ st.uniform(gl, transformMatrixUniform);
+ if(useInterleaved) {
+ interleavedVBO.enableBuffer(gl, true);
+ } else {
+ verticesVBO.enableBuffer(gl, true);
+ colorsVBO.enableBuffer(gl, true);
+ }
+ //gl.glVertexAttribDivisor() is not required since each instance has the same attribute (color).
+ gl.glDrawArraysInstanced(GL4.GL_TRIANGLES, 0, 3, NO_OF_INSTANCE);
+ if(useInterleaved) {
+ interleavedVBO.enableBuffer(gl, false);
+ } else {
+ verticesVBO.enableBuffer(gl, false);
+ colorsVBO.enableBuffer(gl, false);
+ }
+ st.useProgram(gl, false);
+ }
+
+ @Override
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ GL4 gl3 = drawable.getGL().getGL4();
+ gl3.glViewport(0, 0, width, height);
+ aspect = (float) width / (float) height;
+
+ projectionMatrix.glMatrixMode(GL2.GL_PROJECTION);
+ projectionMatrix.glLoadIdentity();
+ projectionMatrix.gluPerspective(45, aspect, 0.001f, 20f);
+ projectionMatrix.gluLookAt(0, 0, -10, 0, 0, 0, 0, 1, 0);
+ }
+
+ @Override
+ public void dispose(GLAutoDrawable drawable){
+ GL4 gl = drawable.getGL().getGL4();
+ st.destroy(gl);
+ }
+
+ private void generateTriangleTransform() {
+ triangleTransform.clear();
+ for(int i = 0; i < NO_OF_INSTANCE; i++) {
+ mat[i].rotate(rotationSpeed[i], 0, 0, 1);
+ triangleTransform.put(mat[i].getMatrix());
+ }
+ triangleTransform.rewind();
+ }
+
+ private void initVBO_nonInterleaved(GL4 gl) {
+ int VERTEX_COUNT = 3;
+
+ verticesVBO = GLArrayDataClient.createGLSL("mgl_Vertex", 3, GL4.GL_FLOAT, false, VERTEX_COUNT);
+ FloatBuffer verticeBuf = (FloatBuffer)verticesVBO.getBuffer();
+ verticeBuf.put(vertices);
+ verticesVBO.seal(gl, true);
+
+ colorsVBO = GLArrayDataClient.createGLSL("mgl_Color", 4, GL4.GL_FLOAT, false, VERTEX_COUNT);
+ FloatBuffer colorBuf = (FloatBuffer)colorsVBO.getBuffer();
+ colorBuf.put(colors);
+ colorsVBO.seal(gl, true);
+
+ verticesVBO.enableBuffer(gl, false);
+ colorsVBO.enableBuffer(gl, false);
+
+ st.ownAttribute(verticesVBO, true);
+ st.ownAttribute(colorsVBO, true);
+ st.useProgram(gl, false);
+ }
+
+ private void initVBO_interleaved(GL4 gl) {
+ int VERTEX_COUNT = 3;
+ interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3 + 4, GL.GL_FLOAT, false, VERTEX_COUNT, GL.GL_STATIC_DRAW);
+ interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+
+ FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
+
+ for(int i = 0; i < VERTEX_COUNT; i++) {
+ ib.put(vertices, i*3, 3);
+ ib.put(colors, i*4, 4);
+ }
+ interleavedVBO.seal(gl, true);
+ interleavedVBO.enableBuffer(gl, false);
+ st.ownAttribute(interleavedVBO, true);
+ st.useProgram(gl, false);
+ }
+
+ private void initShader(GL4 gl) {
+ // Create & Compile the shader objects
+ ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
+ "shader", "shader/bin", shaderBasename, true);
+ ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
+ "shader", "shader/bin", shaderBasename, true);
+ vp0.replaceInShaderSource("NO_OF_INSTANCE", String.valueOf(NO_OF_INSTANCE));
+
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+
+ //vp0.dumpShaderSource(System.out);
+
+ // Create & Link the shader program
+ ShaderProgram sp = new ShaderProgram();
+ sp.add(vp0);
+ sp.add(fp0);
+ if(!sp.link(gl, System.err)) {
+ throw new GLException("Couldn't link program: "+sp);
+ }
+
+ // Let's manage all our states using ShaderState.
+ st = new ShaderState();
+ st.attachShaderProgram(gl, sp, true);
+ }
+
+
+ private static final float[] vertices = {
+ 1.0f, 0.0f, 0,
+ -0.5f, 0.866f, 0,
+ -0.5f, -0.866f, 0
+ };
+
+ private final float[] colors = {
+ 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f, 1.0f,
+ 0f, 0f, 1.0f, 1f
+ };
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TrianglesInstancedRendererHardcoded.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TrianglesInstancedRendererHardcoded.java
new file mode 100644
index 000000000..739670053
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/TrianglesInstancedRendererHardcoded.java
@@ -0,0 +1,285 @@
+package com.jogamp.opengl.test.junit.jogl.demos.gl4;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.FloatBuffer;
+import java.util.Random;
+
+import javax.media.opengl.DebugGL4;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL4;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.TraceGL4;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.math.Matrix4;
+import com.jogamp.opengl.util.PMVMatrix;
+
+public class TrianglesInstancedRendererHardcoded implements GLEventListener {
+ private float aspect;
+
+ private int shaderProgram;
+ private int vertShader;
+ private int fragShader;
+ private int projectionMatrixLocation;
+ private int transformMatrixLocation;
+ private static final int locPos = 1;
+ private static final int locCol = 2;
+ private PMVMatrix projectionMatrix;
+
+ private static final int NO_OF_INSTANCE = 30;
+ private final FloatBuffer triangleTransform = FloatBuffer.allocate(16 * NO_OF_INSTANCE);
+ private final Matrix4[] mat = new Matrix4[NO_OF_INSTANCE];
+ private final float[] rotationSpeed = new float[NO_OF_INSTANCE];
+
+ private int[] vbo;
+ private int[] vao;
+ private PrintStream stream;
+ private final IInstancedRenderingView view;
+
+ private static final boolean useTraceGL = false;
+
+ public TrianglesInstancedRendererHardcoded(IInstancedRenderingView view) {
+ this.view = view;
+ initTransform();
+
+ if(useTraceGL) {
+ try {
+ stream = new PrintStream(new FileOutputStream(new File("instanced.txt")));
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ GL4 gl = drawable.getGL().getGL4();
+ drawable.setGL(new DebugGL4(gl));
+ if(useTraceGL) {
+ drawable.setGL(new TraceGL4(gl, stream));
+ }
+
+ gl.glClearColor(1, 1, 1, 1); //white background
+ // gl.glClearColor(0, 0, 0, 1); //black background
+ gl.glClearDepth(1.0f);
+
+ System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL4.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL4.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL4.GL_VERSION));
+
+ try {
+ initShaders(gl);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ initVBO(gl);
+ }
+
+ @Override
+ public void display(GLAutoDrawable drawable) {
+
+ GL4 gl = drawable.getGL().getGL4();
+ gl.glClear(GL4.GL_COLOR_BUFFER_BIT | GL4.GL_DEPTH_BUFFER_BIT);
+
+ gl.glUseProgram(shaderProgram);
+
+ projectionMatrix.glMatrixMode(GL2.GL_PROJECTION);
+
+ projectionMatrix.glPushMatrix();
+ float winScale = 0.1f;
+ if(view != null) {
+ winScale = view.getScale();
+ }
+ projectionMatrix.glScalef(winScale, winScale, winScale);
+ projectionMatrix.update();
+ gl.glUniformMatrix4fv(projectionMatrixLocation, 1, false, projectionMatrix.glGetPMatrixf());
+ projectionMatrix.glPopMatrix();
+ generateTriangleTransform();
+ gl.glUniformMatrix4fv(transformMatrixLocation, NO_OF_INSTANCE, false, triangleTransform);
+
+ gl.glBindVertexArray(vao[0]);
+ gl.glDrawArraysInstanced(GL4.GL_TRIANGLES, 0, 3, NO_OF_INSTANCE);
+ gl.glBindVertexArray(0);
+ gl.glUseProgram(0);
+ }
+
+ @Override
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ System.out.println("Window resized to width=" + width + " height=" + height);
+ GL4 gl3 = drawable.getGL().getGL4();
+ gl3.glViewport(0, 0, width, height);
+ aspect = (float) width / (float) height;
+
+ projectionMatrix = new PMVMatrix();
+ projectionMatrix.glMatrixMode(GL2.GL_PROJECTION);
+ projectionMatrix.glLoadIdentity();
+ projectionMatrix.gluPerspective(45, aspect, 0.001f, 20f);
+ projectionMatrix.gluLookAt(0, 0, -10, 0, 0, 0, 0, 1, 0);
+ }
+
+ @Override
+ public void dispose(GLAutoDrawable drawable){
+ GL4 gl = drawable.getGL().getGL4();
+ gl.glUseProgram(0);
+ gl.glDeleteBuffers(2, vbo, 0);
+ gl.glDetachShader(shaderProgram, vertShader);
+ gl.glDeleteShader(vertShader);
+ gl.glDetachShader(shaderProgram, fragShader);
+ gl.glDeleteShader(fragShader);
+ gl.glDeleteProgram(shaderProgram);
+ }
+
+ private void initTransform() {
+ Random rnd = new Random();
+ for(int i = 0; i < NO_OF_INSTANCE; i++) {
+ rotationSpeed[i] = 0.3f * rnd.nextFloat();
+ mat[i] = new Matrix4();
+ mat[i].loadIdentity();
+ float scale = 1f + 4 * rnd.nextFloat();
+ mat[i].scale(scale, scale, scale);
+ //setup initial position of each triangle
+ mat[i].translate(20f * rnd.nextFloat() - 10f,
+ 10f * rnd.nextFloat() - 5f,
+ 0f);
+ }
+ }
+
+ private void initVBO(GL4 gl) {
+ FloatBuffer interleavedBuffer = Buffers.newDirectFloatBuffer(vertices.length + colors.length);
+ for(int i = 0; i < vertices.length/3; i++) {
+ for(int j = 0; j < 3; j++) {
+ interleavedBuffer.put(vertices[i*3 + j]);
+ }
+ for(int j = 0; j < 4; j++) {
+ interleavedBuffer.put(colors[i*4 + j]);
+ }
+ }
+ interleavedBuffer.flip();
+
+ vao = new int[1];
+ gl.glGenVertexArrays(1, vao , 0);
+ gl.glBindVertexArray(vao[0]);
+ vbo = new int[1];
+ gl.glGenBuffers(1, vbo, 0);
+ gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, vbo[0]);
+ gl.glBufferData(GL4.GL_ARRAY_BUFFER, interleavedBuffer.limit() * Buffers.SIZEOF_FLOAT, interleavedBuffer, GL4.GL_STATIC_DRAW);
+
+ gl.glEnableVertexAttribArray(locPos);
+ gl.glEnableVertexAttribArray(locCol);
+
+ int stride = Buffers.SIZEOF_FLOAT * (3+4);
+ gl.glVertexAttribPointer( locPos, 3, GL4.GL_FLOAT, false, stride, 0);
+ gl.glVertexAttribPointer( locCol, 4, GL4.GL_FLOAT, false, stride, Buffers.SIZEOF_FLOAT * 3);
+ }
+
+ private void initShaders(GL4 gl) throws IOException {
+ vertShader = gl.glCreateShader(GL4.GL_VERTEX_SHADER);
+ fragShader = gl.glCreateShader(GL4.GL_FRAGMENT_SHADER);
+
+ String[] vlines = new String[] { vertexShaderString };
+ int[] vlengths = new int[] { vlines[0].length() };
+ gl.glShaderSource(vertShader, vlines.length, vlines, vlengths, 0);
+ gl.glCompileShader(vertShader);
+
+ int[] compiled = new int[1];
+ gl.glGetShaderiv(vertShader, GL4.GL_COMPILE_STATUS, compiled, 0);
+ if(compiled[0] != 0) {
+ System.out.println("Vertex shader compiled");
+ } else {
+ int[] logLength = new int[1];
+ gl.glGetShaderiv(vertShader, GL4.GL_INFO_LOG_LENGTH, logLength, 0);
+
+ byte[] log = new byte[logLength[0]];
+ gl.glGetShaderInfoLog(vertShader, logLength[0], (int[])null, 0, log, 0);
+
+ System.err.println("Error compiling the vertex shader: " + new String(log));
+ System.exit(1);
+ }
+
+ String[] flines = new String[] { fragmentShaderString };
+ int[] flengths = new int[] { flines[0].length() };
+ gl.glShaderSource(fragShader, flines.length, flines, flengths, 0);
+ gl.glCompileShader(fragShader);
+
+ gl.glGetShaderiv(fragShader, GL4.GL_COMPILE_STATUS, compiled, 0);
+ if(compiled[0] != 0){
+ System.out.println("Fragment shader compiled.");
+ } else {
+ int[] logLength = new int[1];
+ gl.glGetShaderiv(fragShader, GL4.GL_INFO_LOG_LENGTH, logLength, 0);
+
+ byte[] log = new byte[logLength[0]];
+ gl.glGetShaderInfoLog(fragShader, logLength[0], (int[])null, 0, log, 0);
+
+ System.err.println("Error compiling the fragment shader: " + new String(log));
+ System.exit(1);
+ }
+
+ shaderProgram = gl.glCreateProgram();
+ gl.glAttachShader(shaderProgram, vertShader);
+ gl.glAttachShader(shaderProgram, fragShader);
+
+ gl.glBindAttribLocation(shaderProgram, locPos, "mgl_Vertex");
+ gl.glBindAttribLocation(shaderProgram, locCol, "mgl_Color");
+
+ gl.glLinkProgram(shaderProgram);
+
+ projectionMatrixLocation = gl.glGetUniformLocation(shaderProgram, "mgl_PMatrix");
+ System.out.println("projectionMatrixLocation:" + projectionMatrixLocation);
+ transformMatrixLocation = gl.glGetUniformLocation(shaderProgram, "mgl_MVMatrix");
+ System.out.println("transformMatrixLocation:" + transformMatrixLocation);
+ }
+
+ private void generateTriangleTransform() {
+ triangleTransform.clear();
+ for(int i = 0; i < NO_OF_INSTANCE; i++) {
+ // mat[i].translate(0.1f, 0.1f, 0);
+ mat[i].rotate(rotationSpeed[i], 0, 0, 1);
+ // mat[i].translate(-0.1f, -0.1f, 0);
+ triangleTransform.put(mat[i].getMatrix());
+ }
+ triangleTransform.flip();
+ }
+
+ private final String vertexShaderString =
+ "#version 410 \n" +
+ "\n" +
+ "uniform mat4 mgl_PMatrix; \n" +
+ "uniform mat4 mgl_MVMatrix[" + NO_OF_INSTANCE + "]; \n" +
+ "in vec3 mgl_Vertex; \n" +
+ "in vec4 mgl_Color; \n" +
+ "out vec4 frontColor; \n" +
+ "void main(void) \n" +
+ "{ \n" +
+ " frontColor = mgl_Color; \n" +
+ " gl_Position = mgl_PMatrix * mgl_MVMatrix[gl_InstanceID] * vec4(mgl_Vertex, 1);" +
+ "} ";
+
+ private final String fragmentShaderString =
+ "#version 410\n" +
+ "\n" +
+ "in vec4 frontColor; \n" +
+ "out vec4 mgl_FragColor; \n" +
+ "void main (void) \n" +
+ "{ \n" +
+ " mgl_FragColor = frontColor; \n" +
+ "} ";
+
+ private final float[] vertices = {
+ 1.0f, 0.0f, 0,
+ -0.5f, 0.866f, 0,
+ -0.5f, -0.866f, 0
+ };
+
+ private final float[] colors = {
+ 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f, 1.0f,
+ 0f, 0f, 1.0f, 1f
+ };
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/awt/TestInstancedReneringGL4AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/awt/TestInstancedReneringGL4AWT.java
new file mode 100644
index 000000000..c602ffd7b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/awt/TestInstancedReneringGL4AWT.java
@@ -0,0 +1,244 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.gl4.awt;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.TraceKeyAdapter;
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTKeyAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.gl4.TriangleInstancedRendererWithShaderState;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.FPSAnimator;
+
+/**
+ * Test Instanced rendering demo TrianglesInstancedRenderer
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestInstancedReneringGL4AWT extends UITestCase {
+ static GLProfile glp;
+ static int width, height;
+ static boolean shallUsePBuffer = false;
+ static boolean shallUseBitmap = false;
+ static boolean useMSAA = false;
+ static int swapInterval = 0;
+ static boolean useAnimator = true;
+ static boolean manualTest = false;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL4)) {
+ glp = GLProfile.get(GLProfile.GL4);
+ Assert.assertNotNull(glp);
+ width = 640;
+ height = 480;
+ } else {
+ setTestSupported(false);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL(final GLCapabilities caps)
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ final JFrame frame = new JFrame("Swing GLJPanel");
+ Assert.assertNotNull(frame);
+ final GLJPanel glJPanel = new GLJPanel(caps);
+ Assert.assertNotNull(glJPanel);
+ final Dimension glc_sz = new Dimension(width, height);
+ glJPanel.setMinimumSize(glc_sz);
+ glJPanel.setPreferredSize(glc_sz);
+ glJPanel.setSize(glc_sz);
+ glJPanel.addGLEventListener(new TriangleInstancedRendererWithShaderState(null));
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ glJPanel.addGLEventListener(snap);
+ final FPSAnimator animator = useAnimator ? new FPSAnimator(glJPanel, 60) : null;
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame.getContentPane().add(glJPanel, BorderLayout.CENTER);
+ frame.getContentPane().validate();
+ frame.pack();
+ frame.setVisible(true);
+ } } ) ;
+ if( useAnimator ) {
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.start();
+ Assert.assertEquals(true, animator.isAnimating());
+ }
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glJPanel).addTo(glJPanel);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glJPanel).addTo(frame);
+ final com.jogamp.newt.event.KeyListener kl = new com.jogamp.newt.event.KeyAdapter() {
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='m') {
+ final GLCapabilitiesImmutable capsPre = glJPanel.getChosenGLCapabilities();
+ final GLCapabilities capsNew = new GLCapabilities(capsPre.getGLProfile());
+ capsNew.copyFrom(capsPre);
+ final boolean msaa;
+ if( capsPre.getSampleBuffers() ) {
+ capsNew.setSampleBuffers(false);
+ capsNew.setDoubleBuffered(false);
+ msaa = false;
+ } else {
+ capsNew.setSampleBuffers(true);
+ capsNew.setNumSamples(4);
+ msaa = true;
+ }
+ System.err.println("[set MSAA "+msaa+" Caps had]: "+capsPre);
+ System.err.println("[set MSAA "+msaa+" Caps new]: "+capsNew);
+ System.err.println("XXX-A1: "+animator.toString());
+// glJPanel.setRequestedGLCapabilities(capsNew);
+ System.err.println("XXX-A2: "+animator.toString());
+ System.err.println("XXX: "+glJPanel.toString());
+ } else if(e.getKeyChar()=='b') {
+ final GLCapabilitiesImmutable capsPre = glJPanel.getChosenGLCapabilities();
+ final GLCapabilities capsNew = new GLCapabilities(capsPre.getGLProfile());
+ capsNew.copyFrom(capsPre);
+ final boolean bmp;
+ if( capsPre.isBitmap() ) {
+ capsNew.setBitmap(false); // auto-choose
+ bmp = false;
+ } else {
+ capsNew.setBitmap(true);
+ capsNew.setFBO(false);
+ capsNew.setPBuffer(false);
+ bmp = true;
+ }
+ System.err.println("[set Bitmap "+bmp+" Caps had]: "+capsPre);
+ System.err.println("[set Bitmap "+bmp+" Caps new]: "+capsNew);
+ System.err.println("XXX-A1: "+animator.toString());
+// glJPanel.setRequestedGLCapabilities(capsNew);
+ System.err.println("XXX-A2: "+animator.toString());
+ System.err.println("XXX: "+glJPanel.toString());
+ }
+ } };
+ new AWTKeyAdapter(kl, glJPanel).addTo(glJPanel);
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ boolean triggerSnap = false;
+ while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ snap.getDisplayCount();
+ if( !triggerSnap && snap.getDisplayCount() > 1 ) {
+ // Snapshot only after one frame has been rendered to suite FBO MSAA!
+ snap.setMakeSnapshot();
+ triggerSnap = true;
+ }
+ }
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glJPanel);
+ Assert.assertNotNull(animator);
+ if( useAnimator ) {
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ }
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame.setVisible(false);
+ frame.getContentPane().remove(glJPanel);
+ frame.remove(glJPanel);
+ glJPanel.destroy();
+ frame.dispose();
+ } } );
+ }
+
+ @Test
+ public void test01_DefaultMsaa()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL4));
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
+ runTestGL(caps);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-vsync")) {
+ i++;
+ swapInterval = MiscUtils.atoi(args[i], swapInterval);
+ } else if(args[i].equals("-msaa")) {
+ useMSAA = true;
+ } else if(args[i].equals("-noanim")) {
+ useAnimator = false;
+ } else if(args[i].equals("-pbuffer")) {
+ shallUsePBuffer = true;
+ } else if(args[i].equals("-bitmap")) {
+ shallUseBitmap = true;
+ } else if(args[i].equals("-manual")) {
+ manualTest = true;
+ }
+ }
+ System.err.println("swapInterval "+swapInterval);
+ System.err.println("useMSAA "+useMSAA);
+ System.err.println("useAnimator "+useAnimator);
+ System.err.println("shallUsePBuffer "+shallUsePBuffer);
+ System.err.println("shallUseBitmap "+shallUseBitmap);
+ System.err.println("manualTest "+manualTest);
+ org.junit.runner.JUnitCore.main(TestInstancedReneringGL4AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/newt/TestInstancedReneringGL4NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/newt/TestInstancedReneringGL4NEWT.java
new file mode 100644
index 000000000..aeaaf0846
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/newt/TestInstancedReneringGL4NEWT.java
@@ -0,0 +1,108 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.gl4.newt;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.gl4.TriangleInstancedRendererWithShaderState;
+import com.jogamp.opengl.test.junit.jogl.demos.gl4.TrianglesInstancedRendererHardcoded;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+/**
+ * Test Instanced rendering demo TrianglesInstancedRenderer
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestInstancedReneringGL4NEWT extends UITestCase {
+ static long duration = 500; // ms
+ static GLCapabilities getCaps(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ @Test
+ public void test01_01a() throws InterruptedException {
+ final GLCapabilities caps = getCaps(GLProfile.GL4);
+ if( null == caps ) { return; }
+ testImpl(caps, new TriangleInstancedRendererWithShaderState(null));
+ }
+
+// @Test
+// public void test02_01b() throws InterruptedException {
+// final GLCapabilities caps = getCaps(GLProfile.GL4);
+// if( null == caps ) { return; }
+// testImpl(caps, new TrianglesInstancedRendererHardcoded(null));
+// }
+
+ private void testImpl(final GLCapabilities caps, final GLEventListener glel) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setSize(800, 600);
+ glWindow.setVisible(true);
+ glWindow.setTitle("JOGL Instanced Rendering Test");
+ Assert.assertTrue(glWindow.isNativeValid());
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+ glWindow.addGLEventListener( glel );
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ glWindow.addGLEventListener(snapshotGLEventListener);
+ final Animator animator = new Animator(glWindow);
+ animator.start();
+ animator.setUpdateFPSFrames(60, System.err);
+ snapshotGLEventListener.setMakeSnapshot();
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+ animator.stop();
+ glWindow.destroy();
+ }
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestInstancedReneringGL4NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/newt/TestTessellationShader01GL4NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/newt/TestTessellationShader01GL4NEWT.java
new file mode 100644
index 000000000..ca2638581
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/newt/TestTessellationShader01GL4NEWT.java
@@ -0,0 +1,117 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.demos.gl4.newt;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.gl4.TessellationShader01aGLSL440CoreHardcoded;
+import com.jogamp.opengl.test.junit.jogl.demos.gl4.TessellationShader01bGL4;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Test Geometry shader demo TessellationShader01aGL4 and TessellationShader01bGL4
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTessellationShader01GL4NEWT extends UITestCase {
+ static long duration = 500; // ms
+
+ static GLCapabilities getCaps(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ @Test
+ public void test01_01a() throws InterruptedException {
+ final GLCapabilities caps = getCaps(GLProfile.GL4);
+ if( null == caps ) { return; }
+ testImpl(caps, new TessellationShader01aGLSL440CoreHardcoded());
+ }
+
+ @Test
+ public void test02_01b() throws InterruptedException {
+ final GLCapabilities caps = getCaps(GLProfile.GL4);
+ if( null == caps ) { return; }
+ testImpl(caps, new TessellationShader01bGL4());
+ }
+
+ private void testImpl(final GLCapabilities caps, final GLEventListener glel) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setSize(800, 600);
+ glWindow.setVisible(true);
+ glWindow.setTitle("JOGL Tessellation Shader Test");
+ Assert.assertTrue(glWindow.isNativeValid());
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+ glWindow.addGLEventListener( glel );
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ glWindow.addGLEventListener(snapshotGLEventListener);
+
+ final Animator animator = new Animator(glWindow);
+ animator.start();
+
+ animator.setUpdateFPSFrames(60, System.err);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+ glWindow.destroy();
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestTessellationShader01GL4NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.fp
new file mode 100644
index 000000000..8a3b23203
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.fp
@@ -0,0 +1,6 @@
+
+out vec4 color;
+
+void main(void) {
+ color = vec4(1.0, 1.0, 1.0, 1.0);
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.tcp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.tcp
new file mode 100644
index 000000000..b76aa580d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.tcp
@@ -0,0 +1,12 @@
+
+layout (vertices = 3) out;
+
+void main(void) {
+ if (gl_InvocationID == 0) {
+ gl_TessLevelInner[0] = 5.0;
+ gl_TessLevelOuter[0] = 5.0;
+ gl_TessLevelOuter[1] = 5.0;
+ gl_TessLevelOuter[2] = 5.0;
+ }
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.tep b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.tep
new file mode 100644
index 000000000..9c307f5d4
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.tep
@@ -0,0 +1,8 @@
+
+layout (triangles, equal_spacing, cw) in;
+
+void main(void) {
+ gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +
+ (gl_TessCoord.y * gl_in[1].gl_Position) +
+ (gl_TessCoord.z * gl_in[2].gl_Position);
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.vp
new file mode 100644
index 000000000..c207c1335
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/tess_example01.vp
@@ -0,0 +1,12 @@
+
+layout (location = 0) in vec4 offset;
+
+void main(void)
+{
+ const vec4 vertices[3] =
+ vec4[3] (
+ vec4( 0.25, 0.25, 0.5, 1.0),
+ vec4(-0.25, -0.25, 0.5, 1.0),
+ vec4( 0.25, -0.25, 0.5, 1.0) );
+ gl_Position = vertices[gl_VertexID] + offset;
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/triangles.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/triangles.fp
new file mode 100644
index 000000000..005884a1f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/triangles.fp
@@ -0,0 +1,15 @@
+// Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+varying vec4 frontColor;
+
+void main (void) {
+ mgl_FragColor = frontColor;
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/triangles.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/triangles.vp
new file mode 100644
index 000000000..91cc6eff9
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl4/shader/triangles.vp
@@ -0,0 +1,17 @@
+// Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform mat4 mgl_PMatrix;
+uniform mat4 mgl_MVMatrix[NO_OF_INSTANCE];
+attribute vec3 mgl_Vertex;
+attribute vec4 mgl_Color;
+varying vec4 frontColor;
+
+void main(void) {
+ frontColor = mgl_Color;
+ gl_Position = mgl_PMatrix * mgl_MVMatrix[gl_InstanceID] * vec4(mgl_Vertex, 1);
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java
index 297cbbb90..96db8e564 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java
@@ -32,6 +32,7 @@ import com.jogamp.opengl.util.glsl.ShaderState;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLBufferStorage;
import javax.media.opengl.GLDrawable;
import org.junit.Assert;
@@ -39,34 +40,34 @@ import org.junit.Assert;
public class GLSLMiscHelper {
public static final int frames_perftest = 600; // frames
public static final int frames_warmup = 100; // frames
-
- public static void validateGLArrayDataServerState(GL2ES2 gl, GLArrayDataServer data) {
- final ShaderState st = ShaderState.getShaderState(gl);
- int[] qi = new int[1];
- if(null != st) {
- Assert.assertEquals(data, st.getAttribute(data.getName()));
+
+ public static void validateGLArrayDataServerState(final GL2ES2 gl, final ShaderState st, final GLArrayDataServer data) {
+ final int[] qi = new int[1];
+ if(null != st) {
+ Assert.assertEquals(data, st.getAttribute(data.getName()));
if(st.shaderProgram().linked()) {
Assert.assertEquals(data.getLocation(), st.getCachedAttribLocation(data.getName()));
Assert.assertEquals(data.getLocation(), st.getAttribLocation(gl, data));
Assert.assertEquals(data.getLocation(), st.getAttribLocation(gl, data.getName()));
- Assert.assertEquals(data.getLocation(), gl.glGetAttribLocation(st.shaderProgram().program(), data.getName()));
+ Assert.assertEquals(data.getLocation(), gl.glGetAttribLocation(st.shaderProgram().program(), data.getName()));
}
}
gl.glGetVertexAttribiv(data.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_ENABLED, qi, 0);
Assert.assertEquals(data.enabled()?GL.GL_TRUE:GL.GL_FALSE, qi[0]);
gl.glGetVertexAttribiv(data.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0);
- Assert.assertEquals(data.getVBOName(), qi[0]);
- Assert.assertEquals(data.getSizeInBytes(), gl.glGetBufferSize(data.getVBOName()));
+ Assert.assertEquals(data.getVBOName(), qi[0]);
+ final GLBufferStorage glStore = gl.getBufferStorage(data.getVBOName());
+ Assert.assertEquals("GLBufferStorage size mismatch, storage "+glStore, data.getSizeInBytes(), null != glStore ? glStore.getSize() : -1);
}
- public static void pause(long ms) throws InterruptedException {
- long t0 = System.currentTimeMillis();
+ public static void pause(final long ms) throws InterruptedException {
+ final long t0 = System.currentTimeMillis();
while( System.currentTimeMillis() - t0 < ms) {
Thread.sleep(ms);
- }
+ }
}
-
- public static void displayVCArrays(GLDrawable drawable, GL2ES2 gl, boolean preEnable, GLArrayDataServer vertices, GLArrayDataServer colors, boolean postDisable, int num, long postDelay) throws InterruptedException {
+
+ public static void displayVCArrays(final GLDrawable drawable, final GL2ES2 gl, final ShaderState st, final boolean preEnable, final GLArrayDataServer vertices, final GLArrayDataServer colors, final boolean postDisable, final int num, final long postDelay) throws InterruptedException {
System.err.println("screen #"+num);
if(preEnable) {
vertices.enableBuffer(gl, true);
@@ -80,11 +81,11 @@ public class GLSLMiscHelper {
}
Assert.assertTrue(vertices.enabled());
Assert.assertTrue(colors.enabled());
-
- validateGLArrayDataServerState(gl, vertices);
- validateGLArrayDataServerState(gl, colors);
+
+ validateGLArrayDataServerState(gl, st, vertices);
+ validateGLArrayDataServerState(gl, st, colors);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
if(postDisable) {
vertices.enableBuffer(gl, false);
@@ -94,105 +95,115 @@ public class GLSLMiscHelper {
}
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
drawable.swapBuffers();
- if(postDelay>0) { pause(postDelay); }
+ if(postDelay>0) { pause(postDelay); }
}
-
- public static void displayVCArraysNoChecks(GLDrawable drawable, GL2ES2 gl, boolean preEnable, GLArrayDataServer vertices, GLArrayDataServer colors, boolean postDisable) throws InterruptedException {
+
+ public static void displayVCArraysNoChecks(final GLDrawable drawable, final GL2ES2 gl, final boolean preEnable, final GLArrayDataServer vertices, final GLArrayDataServer colors, final boolean postDisable) throws InterruptedException {
if(preEnable) {
vertices.enableBuffer(gl, true);
colors.enableBuffer(gl, true);
}
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
if(postDisable) {
vertices.enableBuffer(gl, false);
colors.enableBuffer(gl, false);
}
drawable.swapBuffers();
}
-
- public static GLArrayDataServer createRSVertices0(GL2ES2 gl, int location) {
- final ShaderState st = ShaderState.getShaderState(gl);
-
+
+ public static GLArrayDataServer createVertices(final GL2ES2 gl, final ShaderState st, final int shaderProgram, final int location, final float[] vertices) {
+ if(null != st && 0 != shaderProgram) {
+ throw new InternalError("Use either ShaderState _or_ shader-program, not both");
+ }
+ if(null == st && 0 == shaderProgram) {
+ throw new InternalError("Pass a valid ShaderState _xor_ shader-program, not none");
+ }
// Allocate Vertex Array0
- GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
- if(0<=location) {
- st.bindAttribLocation(gl, location, vertices0);
+ final GLArrayDataServer vDataArray = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ if(null != st) {
+ st.ownAttribute(vDataArray, true);
+ if(0<=location) {
+ st.bindAttribLocation(gl, location, vDataArray);
+ }
+ } else {
+ if(0<=location) {
+ vDataArray.setLocation(gl, shaderProgram, location);
+ } else {
+ vDataArray.setLocation(gl, shaderProgram);
+ }
}
- Assert.assertTrue(vertices0.isVBO());
- Assert.assertTrue(vertices0.isVertexAttribute());
- Assert.assertTrue(!vertices0.isVBOWritten());
- Assert.assertTrue(!vertices0.sealed());
- vertices0.putf(-2); vertices0.putf(2); vertices0.putf(0);
- vertices0.putf(2); vertices0.putf(2); vertices0.putf(0);
- vertices0.putf(-2); vertices0.putf(-2); vertices0.putf(0);
- vertices0.putf(2); vertices0.putf(-2); vertices0.putf(0);
- vertices0.seal(gl, true);
- Assert.assertTrue(vertices0.isVBOWritten());
- Assert.assertTrue(vertices0.sealed());
- Assert.assertEquals(4, vertices0.getElementCount());
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- Assert.assertEquals(vertices0.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER));
- validateGLArrayDataServerState(gl, vertices0);
- return vertices0;
- }
-
- public static GLArrayDataServer createRSVertices1(GL2ES2 gl) {
- GLArrayDataServer vertices1 = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
- Assert.assertTrue(vertices1.isVBO());
- Assert.assertTrue(vertices1.isVertexAttribute());
- Assert.assertTrue(!vertices1.isVBOWritten());
- Assert.assertTrue(!vertices1.sealed());
- vertices1.putf(-2); vertices1.putf(1); vertices1.putf(0);
- vertices1.putf(2); vertices1.putf(1); vertices1.putf(0);
- vertices1.putf(-2); vertices1.putf(-1); vertices1.putf(0);
- vertices1.putf(2); vertices1.putf(-1); vertices1.putf(0);
- vertices1.seal(gl, true);
- Assert.assertTrue(vertices1.isVBOWritten());
- Assert.assertTrue(vertices1.sealed());
- Assert.assertEquals(4, vertices1.getElementCount());
+ Assert.assertTrue(vDataArray.isVBO());
+ Assert.assertTrue(vDataArray.isVertexAttribute());
+ Assert.assertTrue(!vDataArray.isVBOWritten());
+ Assert.assertTrue(!vDataArray.sealed());
+ int i=0;
+ vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]);
+ vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]);
+ vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]);
+ vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]);
+ vDataArray.seal(gl, true);
+ Assert.assertTrue(vDataArray.isVBOWritten());
+ Assert.assertTrue(vDataArray.sealed());
+ Assert.assertEquals(4, vDataArray.getElementCount());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- Assert.assertEquals(vertices1.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER));
- validateGLArrayDataServerState(gl, vertices1);
- return vertices1;
+ Assert.assertEquals(0, gl.getBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP
+ validateGLArrayDataServerState(gl, st, vDataArray);
+ return vDataArray;
}
-
- public static GLArrayDataServer createRSColors0(GL2ES2 gl, int location) {
- final ShaderState st = ShaderState.getShaderState(gl);
- GLArrayDataServer colors0 = GLArrayDataServer.createGLSL("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
- if(0<=location) {
- st.bindAttribLocation(gl, location, colors0);
- }
- colors0.putf(1); colors0.putf(0); colors0.putf(0); colors0.putf(1);
- colors0.putf(0); colors0.putf(0); colors0.putf(1); colors0.putf(1);
- colors0.putf(1); colors0.putf(0); colors0.putf(0); colors0.putf(1);
- colors0.putf(1); colors0.putf(0); colors0.putf(0); colors0.putf(1);
- colors0.seal(gl, true);
- Assert.assertTrue(colors0.isVBO());
- Assert.assertTrue(colors0.isVertexAttribute());
- Assert.assertTrue(colors0.isVBOWritten());
- Assert.assertTrue(colors0.sealed());
+ public static final float[] vertices0 = new float[] { -2f, 2f, 0f,
+ 2f, 2f, 0f,
+ -2f, -2f, 0f,
+ 2f, -2f, 0f };
+
+ public static final float[] vertices1 = new float[] { -2f, 1f, 0f,
+ 2f, 1f, 0f,
+ -2f, -1f, 0f,
+ 2f, -1f, 0f };
+
+ public static GLArrayDataServer createColors(final GL2ES2 gl, final ShaderState st, final int shaderProgram, final int location, final float[] colors) {
+ if(null != st && 0 != shaderProgram) {
+ throw new InternalError("Use either ShaderState _or_ shader-program, not both");
+ }
+ if(null == st && 0 == shaderProgram) {
+ throw new InternalError("Pass a valid ShaderState _xor_ shader-program, not none");
+ }
+ final GLArrayDataServer cDataArray = GLArrayDataServer.createGLSL("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ if(null != st) {
+ st.ownAttribute(cDataArray, true);
+ if(0<=location) {
+ st.bindAttribLocation(gl, location, cDataArray);
+ }
+ } else {
+ if(0<=location) {
+ cDataArray.setLocation(gl, shaderProgram, location);
+ } else {
+ cDataArray.setLocation(gl, shaderProgram);
+ }
+ }
+ int i=0;
+ cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]);
+ cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]);
+ cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]);
+ cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]);
+ cDataArray.seal(gl, true);
+ Assert.assertTrue(cDataArray.isVBO());
+ Assert.assertTrue(cDataArray.isVertexAttribute());
+ Assert.assertTrue(cDataArray.isVBOWritten());
+ Assert.assertTrue(cDataArray.sealed());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- Assert.assertEquals(colors0.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER));
- validateGLArrayDataServerState(gl, colors0);
- return colors0;
+ Assert.assertEquals(0, gl.getBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP
+ validateGLArrayDataServerState(gl, st, cDataArray);
+ return cDataArray;
}
-
- public static GLArrayDataServer createRSColors1(GL2ES2 gl) {
- // Allocate Color Array1
- GLArrayDataServer colors1 = GLArrayDataServer.createGLSL("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
- colors1.putf(1); colors1.putf(0); colors1.putf(1); colors1.putf(1);
- colors1.putf(0); colors1.putf(1); colors1.putf(0); colors1.putf(1);
- colors1.putf(1); colors1.putf(0); colors1.putf(1); colors1.putf(1);
- colors1.putf(1); colors1.putf(0); colors1.putf(1); colors1.putf(1);
- colors1.seal(gl, true);
- Assert.assertTrue(colors1.isVBO());
- Assert.assertTrue(colors1.isVertexAttribute());
- Assert.assertTrue(colors1.isVBOWritten());
- Assert.assertTrue(colors1.sealed());
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- Assert.assertEquals(colors1.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER));
- validateGLArrayDataServerState(gl, colors1);
- return colors1;
- }
+ public static final float[] colors0 = new float[] { 1f, 0f, 0f, 1f,
+ 0f, 0f, 1f, 1f,
+ 1f, 0f, 0f, 1f,
+ 1f, 0f, 1f, 1f };
+
+ public static final float[] colors1 = new float[] { 1f, 0f, 1f, 1f,
+ 0f, 1f, 0f, 1f,
+ 1f, 0f, 1f, 1f,
+ 1f, 0f, 1f, 1f };
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java
index 987dedc65..57d6caa85 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java
@@ -38,348 +38,461 @@ import com.jogamp.opengl.test.junit.util.NEWTGLContext;
import com.jogamp.opengl.test.junit.util.UITestCase;
import java.io.IOException;
+
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/**
* Testing different vertex attribute (VA) data sets on one shader
* and shader state in general.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLSLShaderState01NEWT extends UITestCase {
static long durationPerTest = 10; // ms
static boolean firstUIActionOnProcess = false;
static final int vertices0_loc = 0; // FIXME: AMD needs this to be location 0 ? hu ?
static final int colors0_loc = 1;
-
+
@Test
- public void testShaderState01Validation() throws InterruptedException {
+ public void test00NoShaderState_Validation() throws InterruptedException {
// preset ..
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow(
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(
new GLCapabilities(GLProfile.getGL2ES2()), 480, 480, true);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL2ES2 gl = winctx.context.getGL().getGL2ES2();
System.err.println(winctx.context);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- // test code ..
+
+ // test code ..
+ final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class,
+ "shader", "shader/bin", "RedSquareShader", true);
+ final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class,
+ "shader", "shader/bin", "RedSquareShader", true);
+ rsVp.defaultShaderCustomization(gl, true, true);
+ rsFp.defaultShaderCustomization(gl, true, true);
+
+ final ShaderProgram sp = new ShaderProgram();
+ Assert.assertTrue(0 == sp.program());
+
+ sp.add(gl, rsVp, System.err);
+ sp.add(gl, rsFp, System.err);
+
+ Assert.assertTrue(0 != sp.program());
+ Assert.assertTrue(!sp.inUse());
+ Assert.assertTrue(!sp.linked());
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ Assert.assertTrue( sp.link(gl, System.err) );
+ sp.useProgram(gl, true);
+
+ // Allocate Vertex Array0
+ final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, null, sp.program(), vertices0_loc, GLSLMiscHelper.vertices0);
+ System.err.println("vertices0: " + vertices0);
+ vertices0.enableBuffer(gl, false);
+ Assert.assertEquals(vertices0_loc, vertices0.getLocation());
+
+ // Allocate Color Array0
+ final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, null, sp.program(), colors0_loc, GLSLMiscHelper.colors0);
+ System.err.println("colors0: " + colors0);
+ colors0.enableBuffer(gl, false);
+ Assert.assertEquals(colors0_loc, colors0.getLocation());
+
+ Assert.assertTrue(sp.link(gl, System.err));
+ Assert.assertTrue(sp.linked());
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ Assert.assertEquals(vertices0_loc, vertices0.getLocation());
+ GLSLMiscHelper.validateGLArrayDataServerState(gl, null, vertices0);
+
+ Assert.assertEquals(colors0_loc, colors0.getLocation());
+ GLSLMiscHelper.validateGLArrayDataServerState(gl, null, colors0);
+
+ sp.useProgram(gl, true);
+ Assert.assertTrue(sp.inUse());
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ // setup mgl_PMVMatrix
+ final PMVMatrix pmvMatrix = new PMVMatrix();
+ final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ pmvMatrixUniform.setLocation(gl, sp.program());
+ gl.glUniform(pmvMatrixUniform);
+
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ // Allocate Vertex Array1
+ final GLArrayDataServer vertices1 = GLSLMiscHelper.createVertices(gl, null, sp.program(), -1, GLSLMiscHelper.vertices1);
+ System.err.println("vertices1: " + vertices1);
+ vertices1.enableBuffer(gl, false);
+ GLSLMiscHelper.validateGLArrayDataServerState(gl, null, vertices1);
+
+ // Allocate Color Array1
+ final GLArrayDataServer colors1 = GLSLMiscHelper.createColors(gl, null, sp.program(), -1, GLSLMiscHelper.colors1);
+ System.err.println("colors1: " + colors1);
+ colors1.enableBuffer(gl, false);
+ GLSLMiscHelper.validateGLArrayDataServerState(gl, null, colors1);
+
+ // misc GL setup
+ gl.glClearColor(0, 0, 0, 1);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ // reshape
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.gluPerspective(45.0F, (float) drawable.getSurfaceWidth() / (float) drawable.getSurfaceHeight(), 1.0F, 100.0F);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glTranslatef(0, 0, -10);
+ gl.glUniform(pmvMatrixUniform);
+
+ gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ // display #1 vertices0 / colors0 (post-disable)
+ GLSLMiscHelper.displayVCArrays(drawable, gl, null, true, vertices0, colors0, true, 1, durationPerTest);
+
+ // display #2 #1 vertices1 / colors1 (post-disable)
+ GLSLMiscHelper.displayVCArrays(drawable, gl, null, true, vertices1, colors1, true, 2, durationPerTest);
+
+ // display #3 vertices0 / colors0 (post-disable)
+ GLSLMiscHelper.displayVCArrays(drawable, gl, null, true, vertices0, colors0, true, 3, durationPerTest);
+
+ // cleanup
+ sp.useProgram(gl, false);
+ sp.destroy(gl);
+ vertices1.destroy(gl);
+ colors0.destroy(gl);
+ colors1.destroy(gl);
+
+ NEWTGLContext.destroyWindow(winctx);
+ }
+
+ @Test
+ public void test01ShaderState_Validation() throws InterruptedException {
+ // preset ..
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(
+ new GLCapabilities(GLProfile.getGL2ES2()), 480, 480, true);
+ final GLDrawable drawable = winctx.context.getGLDrawable();
+ final GL2ES2 gl = winctx.context.getGL().getGL2ES2();
+ System.err.println(winctx.context);
+
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ // test code ..
final ShaderState st = new ShaderState();
-
+
final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
+ rsVp.defaultShaderCustomization(gl, true, true);
+ rsFp.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp = new ShaderProgram();
- Assert.assertTrue(0>sp.program());
-
+ Assert.assertTrue(0 == sp.program());
+
sp.add(gl, rsVp, System.err);
sp.add(gl, rsFp, System.err);
-
- Assert.assertTrue(0<=sp.program());
+
+ Assert.assertTrue(0 != sp.program());
Assert.assertTrue(!sp.inUse());
Assert.assertTrue(!sp.linked());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
st.attachShaderProgram(gl, sp, false);
Assert.assertTrue(!sp.inUse());
Assert.assertTrue(!sp.linked());
-
- Assert.assertEquals(null, ShaderState.getShaderState(gl));
- st.setShaderState(gl); // pre-use attach
- Assert.assertEquals(st, ShaderState.getShaderState(gl));
-
+
// Allocate Vertex Array0
- final GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, vertices0_loc);
- System.err.println("vertices0: " + vertices0);
+ final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, st, 0, vertices0_loc, GLSLMiscHelper.vertices0);
+ System.err.println("vertices0: " + vertices0);
vertices0.enableBuffer(gl, false);
Assert.assertEquals(vertices0_loc, vertices0.getLocation());
- st.ownAttribute(vertices0, true);
-
+
// Allocate Color Array0
- final GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, colors0_loc);
+ final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, st, 0, colors0_loc, GLSLMiscHelper.colors0);
System.err.println("colors0: " + colors0);
colors0.enableBuffer(gl, false);
Assert.assertEquals(colors0_loc, colors0.getLocation());
- st.ownAttribute(colors0, true);
-
+
Assert.assertTrue(sp.link(gl, System.err));
Assert.assertTrue(sp.linked());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
Assert.assertEquals(vertices0_loc, vertices0.getLocation());
- GLSLMiscHelper.validateGLArrayDataServerState(gl, vertices0);
-
+ GLSLMiscHelper.validateGLArrayDataServerState(gl, st, vertices0);
+
Assert.assertEquals(colors0_loc, colors0.getLocation());
- GLSLMiscHelper.validateGLArrayDataServerState(gl, colors0);
-
+ GLSLMiscHelper.validateGLArrayDataServerState(gl, st, colors0);
+
st.useProgram(gl, true);
Assert.assertTrue(sp.inUse());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
// setup mgl_PMVMatrix
final PMVMatrix pmvMatrix = new PMVMatrix();
final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
st.ownUniform(pmvMatrixUniform);
-
+
st.uniform(gl, pmvMatrixUniform);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
Assert.assertEquals(pmvMatrixUniform, st.getUniform("mgl_PMVMatrix"));
-
+
// Allocate Vertex Array1
- final GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl);
+ final GLArrayDataServer vertices1 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices1);
System.err.println("vertices1: " + vertices1);
vertices1.enableBuffer(gl, false);
- GLSLMiscHelper.validateGLArrayDataServerState(gl, vertices1);
- st.ownAttribute(vertices1, true);
-
+ GLSLMiscHelper.validateGLArrayDataServerState(gl, st, vertices1);
+
// Allocate Color Array1
- final GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl);
+ final GLArrayDataServer colors1 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors1);
System.err.println("colors1: " + colors1);
colors1.enableBuffer(gl, false);
- GLSLMiscHelper.validateGLArrayDataServerState(gl, colors1);
- st.ownAttribute(colors0, true);
-
+ GLSLMiscHelper.validateGLArrayDataServerState(gl, st, colors1);
+
// misc GL setup
gl.glClearColor(0, 0, 0, 1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_DEPTH_TEST);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
// reshape
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
- pmvMatrix.gluPerspective(45.0F, (float) drawable.getWidth() / (float) drawable.getHeight(), 1.0F, 100.0F);
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.gluPerspective(45.0F, (float) drawable.getSurfaceWidth() / (float) drawable.getSurfaceHeight(), 1.0F, 100.0F);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
pmvMatrix.glTranslatef(0, 0, -10);
st.uniform(gl, pmvMatrixUniform);
- gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
+ gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
// display #1 vertices0 / colors0 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 1, durationPerTest);
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 1, durationPerTest);
// display #2 #1 vertices1 / colors1 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 2, durationPerTest);
-
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 2, durationPerTest);
+
// display #3 vertices0 / colors0 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 3, durationPerTest);
-
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 3, durationPerTest);
+
// cleanup
st.destroy(gl);
-
+
NEWTGLContext.destroyWindow(winctx);
}
@Test(timeout=240000)
- public void testShaderState00PerformanceSingleKeepEnabled() throws InterruptedException {
- testShaderState00PerformanceSingle(false);
+ public void test02ShaderState_PerformanceSingleKeepEnabled() throws InterruptedException {
+ testShaderState_PerformanceSingleImpl(false);
}
@Test(timeout=240000)
- public void testShaderState00PerformanceSingleToggleEnable() throws InterruptedException {
- testShaderState00PerformanceSingle(true);
+ public void test03ShaderState_PerformanceSingleToggleEnable() throws InterruptedException {
+ testShaderState_PerformanceSingleImpl(true);
}
-
- void testShaderState00PerformanceSingle(boolean toggleEnable) throws InterruptedException {
+
+ private void testShaderState_PerformanceSingleImpl(final boolean toggleEnable) throws InterruptedException {
// preset ..
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow(
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(
new GLCapabilities(GLProfile.getGL2ES2()), 480, 480, false);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL2ES2 gl = winctx.context.getGL().getGL2ES2();
System.err.println(winctx.context);
gl.setSwapInterval(0);
-
+
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- // test code ..
+
+ // test code ..
final ShaderState st = new ShaderState();
-
+
final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
+ rsVp.defaultShaderCustomization(gl, true, true);
+ rsFp.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp = new ShaderProgram();
sp.add(rsVp);
sp.add(rsFp);
-
+
sp.init(gl);
Assert.assertTrue(sp.link(gl, System.err));
-
- st.attachShaderProgram(gl, sp, true);
-
+
+ st.attachShaderProgram(gl, sp, true);
+
// setup mgl_PMVMatrix
final PMVMatrix pmvMatrix = new PMVMatrix();
- final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
st.ownUniform(pmvMatrixUniform);
st.uniform(gl, pmvMatrixUniform);
-
+
// Allocate Vertex Array0
- final GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, -1);
- st.ownAttribute(vertices0, true);
+ final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices0);
vertices0.enableBuffer(gl, toggleEnable ? false : true);
-
+
// Allocate Color Array0
- final GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, -1);
- st.ownAttribute(colors0, true);
+ final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors0);
colors0.enableBuffer(gl, toggleEnable ? false : true);
-
+
// misc GL setup
gl.glClearColor(0, 0, 0, 1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_DEPTH_TEST);
// reshape
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
- pmvMatrix.gluPerspective(45.0F, (float) drawable.getWidth() / (float) drawable.getHeight(), 1.0F, 100.0F);
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.gluPerspective(45.0F, (float) drawable.getSurfaceWidth() / (float) drawable.getSurfaceHeight(), 1.0F, 100.0F);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
pmvMatrix.glTranslatef(0, 0, -10);
st.uniform(gl, pmvMatrixUniform);
- gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
+ gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
gl.setSwapInterval(0);
-
+
// validation ..
- GLSLMiscHelper.displayVCArrays(drawable, gl, toggleEnable, vertices0, colors0, toggleEnable, 1, 0);
-
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, toggleEnable, vertices0, colors0, toggleEnable, 1, 0);
+
// warmup ..
for(int frames=0; frames<GLSLMiscHelper.frames_warmup; frames++) {
GLSLMiscHelper.displayVCArraysNoChecks(drawable, gl, toggleEnable, vertices0, colors0, toggleEnable);
}
-
+
// measure ..
- long t0 = System.currentTimeMillis();
+ final long t0 = System.currentTimeMillis();
int frames;
-
+
for(frames=0; frames<GLSLMiscHelper.frames_perftest; frames++) {
GLSLMiscHelper.displayVCArraysNoChecks(drawable, gl, toggleEnable, vertices0, colors0, toggleEnable);
- }
+ }
final long t1 = System.currentTimeMillis();
- final long dt = t1 - t0;
- final double fps = ( frames * 1000.0 ) / (double) dt;
- final String fpsS = String.valueOf(fps);
- final int fpsSp = fpsS.indexOf('.');
- System.err.println("testShaderState00PerformanceSingle toggleEnable "+toggleEnable+": "+dt/1000.0 +"s: "+ frames + "f, " + fpsS.substring(0, fpsSp+2) + " fps, "+dt/frames+" ms/f");
-
+ final long dt = t1 - t0;
+ final double fps = ( frames * 1000.0 ) / dt;
+ final String fpsS = String.valueOf(fps);
+ final int fpsSp = fpsS.indexOf('.');
+ System.err.println("testShaderState00PerformanceSingle toggleEnable "+toggleEnable+": "+dt/1000.0 +"s: "+ frames + "f, " + fpsS.substring(0, fpsSp+2) + " fps, "+dt/frames+" ms/f");
+
// cleanup
st.destroy(gl);
-
- NEWTGLContext.destroyWindow(winctx);
+
+ NEWTGLContext.destroyWindow(winctx);
}
-
+
@Test(timeout=240000)
- public void testShaderState01PerformanceDouble() throws InterruptedException {
+ public void test04ShaderState_PerformanceDouble() throws InterruptedException {
// preset ..
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow(
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(
new GLCapabilities(GLProfile.getGL2ES2()), 480, 480, false);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL2ES2 gl = winctx.context.getGL().getGL2ES2();
System.err.println(winctx.context);
gl.setSwapInterval(0);
-
+
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- // test code ..
+
+ // test code ..
final ShaderState st = new ShaderState();
-
+
final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
+ rsVp.defaultShaderCustomization(gl, true, true);
+ rsFp.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp = new ShaderProgram();
sp.add(rsVp);
sp.add(rsFp);
-
+
sp.init(gl);
Assert.assertTrue(sp.link(gl, System.err));
-
- st.attachShaderProgram(gl, sp, true);
-
+
+ st.attachShaderProgram(gl, sp, true);
+
// setup mgl_PMVMatrix
final PMVMatrix pmvMatrix = new PMVMatrix();
final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
st.ownUniform(pmvMatrixUniform);
st.uniform(gl, pmvMatrixUniform);
-
+
// Allocate Vertex Array0
- final GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, -1);
- st.ownAttribute(vertices0, true);
+ final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices0);
vertices0.enableBuffer(gl, false);
-
+
// Allocate Vertex Array1
- final GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl);
- st.ownAttribute(vertices1, true);
+ final GLArrayDataServer vertices1 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices1);
vertices1.enableBuffer(gl, false);
-
+
// Allocate Color Array0
- final GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, -1);
- st.ownAttribute(colors0, true);
+ final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors0);
colors0.enableBuffer(gl, false);
-
+
// Allocate Color Array1
- final GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl);
- st.ownAttribute(colors1, true);
+ final GLArrayDataServer colors1 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors1);
colors1.enableBuffer(gl, false);
-
+
// misc GL setup
gl.glClearColor(0, 0, 0, 1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_DEPTH_TEST);
// reshape
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
- pmvMatrix.gluPerspective(45.0F, (float) drawable.getWidth() / (float) drawable.getHeight(), 1.0F, 100.0F);
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.gluPerspective(45.0F, (float) drawable.getSurfaceWidth() / (float) drawable.getSurfaceHeight(), 1.0F, 100.0F);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
pmvMatrix.glTranslatef(0, 0, -10);
st.uniform(gl, pmvMatrixUniform);
- gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
+ gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
gl.setSwapInterval(0);
-
+
// validation ..
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 1, 0);
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 2, 0);
-
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 1, 0);
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 2, 0);
+
// warmup ..
for(int frames=0; frames<GLSLMiscHelper.frames_warmup; frames+=2) {
GLSLMiscHelper.displayVCArraysNoChecks(drawable, gl, true, vertices0, colors0, true);
GLSLMiscHelper.displayVCArraysNoChecks(drawable, gl, true, vertices1, colors1, true);
}
-
+
// measure ..
- long t0 = System.currentTimeMillis();
+ final long t0 = System.currentTimeMillis();
int frames;
-
+
for(frames=0; frames<GLSLMiscHelper.frames_perftest; frames+=2) {
GLSLMiscHelper.displayVCArraysNoChecks(drawable, gl, true, vertices0, colors0, true);
GLSLMiscHelper.displayVCArraysNoChecks(drawable, gl, true, vertices1, colors1, true);
- }
+ }
final long t1 = System.currentTimeMillis();
- final long dt = t1 - t0;
- final double fps = ( frames * 1000.0 ) / (double) dt;
- final String fpsS = String.valueOf(fps);
- final int fpsSp = fpsS.indexOf('.');
- System.err.println("testShaderState01PerformanceDouble: "+dt/1000.0 +"s: "+ frames + "f, " + fpsS.substring(0, fpsSp+2) + " fps, "+dt/frames+" ms/f");
-
+ final long dt = t1 - t0;
+ final double fps = ( frames * 1000.0 ) / dt;
+ final String fpsS = String.valueOf(fps);
+ final int fpsSp = fpsS.indexOf('.');
+ System.err.println("testShaderState01PerformanceDouble: "+dt/1000.0 +"s: "+ frames + "f, " + fpsS.substring(0, fpsSp+2) + " fps, "+dt/frames+" ms/f");
+
// cleanup
st.destroy(gl);
-
+
NEWTGLContext.destroyWindow(winctx);
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
System.err.println("main - start");
boolean wait = false;
for(int i=0; i<args.length; i++) {
@@ -393,16 +506,16 @@ public class TestGLSLShaderState01NEWT extends UITestCase {
}
if(wait) {
while(-1 == System.in.read()) ;
- TestGLSLShaderState01NEWT tst = new TestGLSLShaderState01NEWT();
+ final TestGLSLShaderState01NEWT tst = new TestGLSLShaderState01NEWT();
try {
- tst.testShaderState01PerformanceDouble();
- } catch (Exception e) {
+ tst.test04ShaderState_PerformanceDouble();
+ } catch (final Exception e) {
e.printStackTrace();
}
} else {
- String tstname = TestGLSLShaderState01NEWT.class.getName();
+ final String tstname = TestGLSLShaderState01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
System.err.println("main - end");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java
index 91dcfc3c3..501850c4f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java
@@ -38,26 +38,31 @@ import com.jogamp.opengl.test.junit.util.NEWTGLContext;
import com.jogamp.opengl.test.junit.util.UITestCase;
import java.io.IOException;
+
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/**
* Testing different vertex attribute (VA) data sets on one shader
* and shader state in general.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLSLShaderState02NEWT extends UITestCase {
static long durationPerTest = 10; // ms
static final int vertices0_loc = 0; // FIXME: AMD needs this to be location 0 ? hu ?
static final int colors0_loc = 5;
-
+
@Test
public void testShaderState01ValidationSP1Linked() throws InterruptedException {
testShaderState01Validation(true);
@@ -66,34 +71,37 @@ public class TestGLSLShaderState02NEWT extends UITestCase {
public void testShaderState01ValidationSP1Unlinked() throws InterruptedException {
testShaderState01Validation(false);
}
-
- private void testShaderState01Validation(boolean linkSP1) throws InterruptedException {
+
+ private void testShaderState01Validation(final boolean linkSP1) throws InterruptedException {
// preset ..
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow(
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(
new GLCapabilities(GLProfile.getGL2ES2()), 480, 480, true);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL2ES2 gl = winctx.context.getGL().getGL2ES2();
System.err.println(winctx.context);
-
+
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- // test code ..
+
+ // test code ..
final ShaderState st = new ShaderState();
-
+
final ShaderCode rsVp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
final ShaderCode rsFp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
final ShaderCode rsFp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader2", false);
+ "shader/bin", "RedSquareShader2", true);
+ rsVp0.defaultShaderCustomization(gl, true, true);
+ rsFp0.defaultShaderCustomization(gl, true, true);
+ rsFp1.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp1 = new ShaderProgram();
sp1.add(rsVp0);
sp1.add(rsFp1);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- Assert.assertTrue(0>sp1.program());
- sp1.init(gl);
- Assert.assertTrue(0<=sp1.program());
+ Assert.assertTrue(0 == sp1.program());
+ Assert.assertTrue(sp1.init(gl));
+ Assert.assertTrue(0 != sp1.program());
Assert.assertTrue(!sp1.inUse());
Assert.assertTrue(!sp1.linked());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
@@ -102,230 +110,223 @@ public class TestGLSLShaderState02NEWT extends UITestCase {
Assert.assertTrue(sp1.linked());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
}
-
- final ShaderProgram sp0 = new ShaderProgram();
+
+ final ShaderProgram sp0 = new ShaderProgram();
sp0.add(rsVp0);
sp0.add(rsFp0);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- Assert.assertTrue(0>sp0.program());
- sp0.init(gl);
- Assert.assertTrue(0<=sp0.program());
+
+ Assert.assertTrue(0 == sp0.program());
+ Assert.assertTrue(sp0.init(gl));
+ Assert.assertTrue(0 != sp0.program());
Assert.assertTrue(!sp0.inUse());
Assert.assertTrue(!sp0.linked());
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
st.attachShaderProgram(gl, sp0, false);
Assert.assertTrue(!sp0.inUse());
Assert.assertTrue(!sp0.linked());
- Assert.assertEquals(null, ShaderState.getShaderState(gl));
- st.setShaderState(gl); // pre-use attach
- Assert.assertEquals(st, ShaderState.getShaderState(gl));
-
+
// Allocate Vertex Array0
- final GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, vertices0_loc);
- st.ownAttribute(vertices0, true);
- System.err.println("vertices0: " + vertices0);
+ final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, st, 0, vertices0_loc, GLSLMiscHelper.vertices0);
+ System.err.println("vertices0: " + vertices0);
vertices0.enableBuffer(gl, false);
Assert.assertEquals(vertices0_loc, vertices0.getLocation());
-
+
// Allocate Color Array0
- final GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, colors0_loc);
- st.ownAttribute(colors0, true);
+ final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, st, 0, colors0_loc, GLSLMiscHelper.colors0);
System.err.println("colors0: " + colors0);
colors0.enableBuffer(gl, false);
Assert.assertEquals(colors0_loc, colors0.getLocation());
-
+
Assert.assertTrue(sp0.link(gl, System.err));
Assert.assertTrue(sp0.linked());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
Assert.assertEquals(vertices0_loc, vertices0.getLocation());
Assert.assertEquals(vertices0_loc, st.getAttribLocation(gl, vertices0.getName()));
Assert.assertEquals(vertices0_loc, gl.glGetAttribLocation(st.shaderProgram().program(), vertices0.getName()));
-
+
Assert.assertEquals(colors0_loc, colors0.getLocation());
Assert.assertEquals(colors0_loc, st.getAttribLocation(gl, colors0.getName()));
Assert.assertEquals(colors0_loc, gl.glGetAttribLocation(st.shaderProgram().program(), colors0.getName()));
-
+
st.useProgram(gl, true);
Assert.assertTrue(sp0.inUse());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
// setup mgl_PMVMatrix
final PMVMatrix pmvMatrix = new PMVMatrix();
final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
st.ownUniform(pmvMatrixUniform);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
st.uniform(gl, pmvMatrixUniform);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
Assert.assertEquals(pmvMatrixUniform, st.getUniform("mgl_PMVMatrix"));
-
+
// Allocate Vertex Array1
- final GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl);
- st.ownAttribute(vertices1, true);
+ final GLArrayDataServer vertices1 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices1);
System.err.println("vertices1: " + vertices1);
vertices1.enableBuffer(gl, false);
-
+
// Allocate Color Array1
- final GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl);
- st.ownAttribute(colors1, true);
+ final GLArrayDataServer colors1 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors1);
System.err.println("colors1: " + colors1);
colors1.enableBuffer(gl, false);
-
+
// misc GL setup
gl.glClearColor(0, 0, 0, 1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_DEPTH_TEST);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
// reshape
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
- pmvMatrix.gluPerspective(45.0F, (float) drawable.getWidth() / (float) drawable.getHeight(), 1.0F, 100.0F);
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.gluPerspective(45.0F, (float) drawable.getSurfaceWidth() / (float) drawable.getSurfaceHeight(), 1.0F, 100.0F);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
pmvMatrix.glTranslatef(0, 0, -10);
st.uniform(gl, pmvMatrixUniform);
- gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
+ gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
// display #1 vertices0 / colors0 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 1, durationPerTest);
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 1, durationPerTest);
// display #2 vertices1 / colors1 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 2, durationPerTest);
-
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 2, durationPerTest);
+
// display #3 vertices0 / colors0 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 3, durationPerTest);
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 3, durationPerTest);
// display #4 vertices1 / colors1 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 4, durationPerTest);
-
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 4, durationPerTest);
+
// SP1
- st.attachShaderProgram(gl, sp1, true);
+ st.attachShaderProgram(gl, sp1, true);
Assert.assertTrue(sp1.inUse());
Assert.assertTrue(sp1.linked());
-
+
if(!linkSP1) {
// all attribute locations shall be same now, due to impl. glBindAttributeLocation
Assert.assertEquals(vertices0_loc, vertices0.getLocation());
Assert.assertEquals(vertices0_loc, st.getAttribLocation(gl, vertices0.getName()));
Assert.assertEquals(vertices0_loc, gl.glGetAttribLocation(st.shaderProgram().program(), vertices0.getName()));
-
+
Assert.assertEquals(colors0_loc, colors0.getLocation());
Assert.assertEquals(colors0_loc, st.getAttribLocation(gl, colors0.getName()));
Assert.assertEquals(colors0_loc, gl.glGetAttribLocation(st.shaderProgram().program(), colors0.getName()));
}
-
+
// display #1 vertices0 / colors0 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 10, durationPerTest);
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 10, durationPerTest);
// display #2 vertices1 / colors1 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 20, durationPerTest);
-
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 20, durationPerTest);
+
// display #3 vertices0 / colors0 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 30, durationPerTest);
-
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 30, durationPerTest);
+
// display #4 vertices1 / colors1 (post-disable)
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 40, durationPerTest);
-
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 40, durationPerTest);
+
// cleanup
st.destroy(gl);
-
+
NEWTGLContext.destroyWindow(winctx);
}
- @Test(timeout=240000)
+ @Test(timeout=240000)
public void testShaderState01PerformanceDouble() throws InterruptedException {
// preset ..
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow(
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(
new GLCapabilities(GLProfile.getGL2ES2()), 480, 480, false);
final GLDrawable drawable = winctx.context.getGLDrawable();
final GL2ES2 gl = winctx.context.getGL().getGL2ES2();
System.err.println(winctx.context);
gl.setSwapInterval(0);
-
+
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- // test code ..
+
+ // test code ..
final ShaderState st = new ShaderState();
-
+
final ShaderCode rsVp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
final ShaderCode rsFp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader", false);
+ "shader/bin", "RedSquareShader", true);
final ShaderCode rsFp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "RedSquareShader2", false);
+ "shader/bin", "RedSquareShader2", true);
+ rsVp0.defaultShaderCustomization(gl, true, true);
+ rsFp0.defaultShaderCustomization(gl, true, true);
+ rsFp1.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp1 = new ShaderProgram();
sp1.add(rsVp0);
sp1.add(rsFp1);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- Assert.assertTrue(0>sp1.program());
- sp1.init(gl);
+ Assert.assertTrue(0 == sp1.program());
+ Assert.assertTrue(sp1.init(gl));
+ Assert.assertTrue(0 != sp1.program());
Assert.assertTrue(sp1.link(gl, System.err));
-
+
final ShaderProgram sp0 = new ShaderProgram();
sp0.add(rsVp0);
sp0.add(rsFp0);
-
- sp0.init(gl);
+
+ Assert.assertTrue(sp0.init(gl));
Assert.assertTrue(sp0.link(gl, System.err));
-
- st.attachShaderProgram(gl, sp0, true);
-
+
+ st.attachShaderProgram(gl, sp0, true);
+
// setup mgl_PMVMatrix
final PMVMatrix pmvMatrix = new PMVMatrix();
final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
st.ownUniform(pmvMatrixUniform);
st.uniform(gl, pmvMatrixUniform);
-
+
// Allocate Vertex Array0
- final GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, -1);
- st.ownAttribute(vertices0, true);
+ final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices0);
vertices0.enableBuffer(gl, false);
-
+
// Allocate Vertex Array1
- final GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl);
- st.ownAttribute(vertices1, true);
+ final GLArrayDataServer vertices1 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices1);
vertices1.enableBuffer(gl, false);
-
+
// Allocate Color Array0
- final GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, -1);
- st.ownAttribute(colors0, true);
+ final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors0);
colors0.enableBuffer(gl, false);
-
+
// Allocate Color Array1
- final GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl);
- st.ownAttribute(colors1, true);
+ final GLArrayDataServer colors1 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors1);
colors1.enableBuffer(gl, false);
-
+
// misc GL setup
gl.glClearColor(0, 0, 0, 1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
+ gl.glEnable(GL.GL_DEPTH_TEST);
// reshape
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
- pmvMatrix.gluPerspective(45.0F, (float) drawable.getWidth() / (float) drawable.getHeight(), 1.0F, 100.0F);
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.gluPerspective(45.0F, (float) drawable.getSurfaceWidth() / (float) drawable.getSurfaceHeight(), 1.0F, 100.0F);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
pmvMatrix.glTranslatef(0, 0, -10);
st.uniform(gl, pmvMatrixUniform);
- gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
+ gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
gl.setSwapInterval(0);
-
+
// validation ..
st.attachShaderProgram(gl, sp0, true);
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 1, 0);
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 2, 0);
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 1, 0);
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 2, 0);
st.attachShaderProgram(gl, sp1, true);
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 1, 0);
- GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 2, 0);
-
- // warmup ..
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 1, 0);
+ GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 2, 0);
+
+ // warmup ..
for(int frames=0; frames<GLSLMiscHelper.frames_warmup; frames+=2) {
// SP0
st.attachShaderProgram(gl, sp0, true);
@@ -334,11 +335,11 @@ public class TestGLSLShaderState02NEWT extends UITestCase {
st.attachShaderProgram(gl, sp1, true);
GLSLMiscHelper.displayVCArraysNoChecks(drawable, gl, true, vertices1, colors1, true);
}
-
+
// measure ..
- long t0 = System.currentTimeMillis();
+ final long t0 = System.currentTimeMillis();
int frames;
-
+
for(frames=0; frames<GLSLMiscHelper.frames_perftest; frames+=4) {
// SP0
st.attachShaderProgram(gl, sp0, true);
@@ -349,20 +350,20 @@ public class TestGLSLShaderState02NEWT extends UITestCase {
GLSLMiscHelper.displayVCArraysNoChecks(drawable, gl, true, vertices0, colors0, true);
GLSLMiscHelper.displayVCArraysNoChecks(drawable, gl, true, vertices1, colors1, true);
}
-
+
final long t1 = System.currentTimeMillis();
- final long dt = t1 - t0;
- final double fps = ( frames * 1000.0 ) / (double) dt;
- final String fpsS = String.valueOf(fps);
- final int fpsSp = fpsS.indexOf('.');
- System.err.println("testShaderState01PerformanceDouble: "+dt/1000.0 +"s: "+ frames + "f, " + fpsS.substring(0, fpsSp+2) + " fps, "+dt/frames+" ms/f");
-
+ final long dt = t1 - t0;
+ final double fps = ( frames * 1000.0 ) / dt;
+ final String fpsS = String.valueOf(fps);
+ final int fpsSp = fpsS.indexOf('.');
+ System.err.println("testShaderState01PerformanceDouble: "+dt/1000.0 +"s: "+ frames + "f, " + fpsS.substring(0, fpsSp+2) + " fps, "+dt/frames+" ms/f");
+
// cleanup
st.destroy(gl);
NEWTGLContext.destroyWindow(winctx);
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
System.err.println("main - start");
boolean wait = false;
for(int i=0; i<args.length; i++) {
@@ -375,16 +376,16 @@ public class TestGLSLShaderState02NEWT extends UITestCase {
}
if(wait) {
while(-1 == System.in.read()) ;
- TestGLSLShaderState02NEWT tst = new TestGLSLShaderState02NEWT();
+ final TestGLSLShaderState02NEWT tst = new TestGLSLShaderState02NEWT();
try {
tst.testShaderState01PerformanceDouble();
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
- }
+ }
} else {
- String tstname = TestGLSLShaderState02NEWT.class.getName();
+ final String tstname = TestGLSLShaderState02NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
System.err.println("main - end");
}
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java
index dde7252e8..b478fcdb6 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java
@@ -39,6 +39,8 @@ import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.Animator;
@@ -48,24 +50,25 @@ import com.jogamp.opengl.test.junit.util.MiscUtils;
import java.io.IOException;
import javax.media.opengl.GL2ES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLSLSimple01NEWT extends UITestCase {
static long durationPerTest = 100; // ms
@Test(timeout=60000)
public void testGLSLCompilation01() {
- GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
Assert.assertNotNull(glp);
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window = GLWindow.create(caps);
+ final GLWindow window = GLWindow.create(caps);
Assert.assertNotNull(window);
window.setSize(800, 600);
window.setVisible(true);
Assert.assertTrue(window.isNativeValid());
- GLContext context = window.getContext();
-
+ final GLContext context = window.getContext();
+
// trigger native creation of drawable/context
window.display();
Assert.assertTrue(window.isRealized());
@@ -75,8 +78,8 @@ public class TestGLSLSimple01NEWT extends UITestCase {
// given
- GL2ES2 gl = context.getGL().getGL2ES2();
- GLSLSimpleProgram myShader = GLSLSimpleProgram.create(gl,
+ final GL2ES2 gl = context.getGL().getGL2ES2();
+ final GLSLSimpleProgram myShader = GLSLSimpleProgram.create(gl,
RedSquareShader.VERTEX_SHADER_TEXT,
RedSquareShader.FRAGMENT_SHADER_TEXT,
true);
@@ -88,20 +91,20 @@ public class TestGLSLSimple01NEWT extends UITestCase {
@Test(timeout=60000)
public void testGLSLUse01() throws InterruptedException {
- GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
Assert.assertNotNull(glp);
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window = GLWindow.create(caps);
+ final GLWindow window = GLWindow.create(caps);
Assert.assertNotNull(window);
window.setSize(800, 600);
window.setVisible(true);
Assert.assertTrue(window.isNativeValid());
window.addGLEventListener(new RedSquareES2());
-
- Animator animator = new Animator(window);
- animator.setUpdateFPSFrames(1, null);
+
+ final Animator animator = new Animator(window);
+ animator.setUpdateFPSFrames(1, null);
animator.start();
Assert.assertEquals(true, animator.isAnimating());
while(animator.isAnimating() && animator.getTotalFPSDuration()<durationPerTest) {
@@ -113,14 +116,14 @@ public class TestGLSLSimple01NEWT extends UITestCase {
animator.stop();
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
System.err.println("main - start");
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
}
}
- String tstname = TestGLSLSimple01NEWT.class.getName();
+ final String tstname = TestGLSLSimple01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
System.err.println("main - end");
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java
index 87d317037..e20bbef2d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java
@@ -28,8 +28,10 @@
package com.jogamp.opengl.test.junit.jogl.glsl;
import com.jogamp.common.nio.Buffers;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.MonitorMode;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.glsl.ShaderCode;
@@ -37,149 +39,220 @@ import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.glsl.ShaderState;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
import com.jogamp.opengl.test.junit.util.MiscUtils;
-import com.jogamp.opengl.test.junit.util.NEWTGLContext;
import com.jogamp.opengl.test.junit.util.UITestCase;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
import java.nio.FloatBuffer;
-import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestRulerNEWT01 extends UITestCase {
- static long durationPerTest = 10; // ms
+ static long durationPerTest = 500; // ms
+ static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+ static boolean manualTest = false;
+
+ private void setTitle(final Window win) {
+ final float[] sDPI = win.getPixelsPerMM(new float[2]);
+ sDPI[0] *= 25.4f;
+ sDPI[1] *= 25.4f;
+ win.setTitle("GLWindow: win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]);
+ }
+
+ private void runTestGL() throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getGL2ES2()));
+ Assert.assertNotNull(glWindow);
+ glWindow.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
+ glWindow.setSize(640, 480);
+
+ glWindow.addGLEventListener(new GLEventListener() {
+ final ShaderState st = new ShaderState();
+ final PMVMatrix pmvMatrix = new PMVMatrix();
+ final GLUniformData pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ final GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ final GLUniformData rulerPixFreq = new GLUniformData("gcu_RulerPixFreq", 2, Buffers.newDirectFloatBuffer(2));
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader",
+ "shader/bin", "default", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
+ "shader/bin", "ruler", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+
+ final ShaderProgram sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ Assert.assertTrue(0 != sp0.program());
+ Assert.assertTrue(!sp0.inUse());
+ Assert.assertTrue(!sp0.linked());
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ st.attachShaderProgram(gl, sp0, true);
+
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ final GLUniformData rulerColor= new GLUniformData("gcu_RulerColor", 3, Buffers.newDirectFloatBuffer(3));
+ final FloatBuffer rulerColorV = (FloatBuffer) rulerColor.getBuffer();
+ rulerColorV.put(0, 0.5f);
+ rulerColorV.put(1, 0.5f);
+ rulerColorV.put(2, 0.5f);
+ st.ownUniform(rulerColor);
+ st.uniform(gl, rulerColor);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ st.ownUniform(rulerPixFreq);
+
+ vertices0.putf(0); vertices0.putf(1); vertices0.putf(0);
+ vertices0.putf(1); vertices0.putf(1); vertices0.putf(0);
+ vertices0.putf(0); vertices0.putf(0); vertices0.putf(0);
+ vertices0.putf(1); vertices0.putf(0); vertices0.putf(0);
+ vertices0.seal(gl, true);
+ st.ownAttribute(vertices0, true);
+
+ // misc GL setup
+ gl.glClearColor(1, 1, 1, 1);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ vertices0.enableBuffer(gl, true);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ vertices0.enableBuffer(gl, false);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glOrthof(0f, 1f, 0f, 1f, -10f, 10f);
+ // pmvMatrix.gluPerspective(45.0F, (float) drawable.getWidth() / (float) drawable.getHeight(), 1.0F, 100.0F);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ // pmvMatrix.glTranslatef(0, 0, -6);
+ // pmvMatrix.glRotatef(45f, 1f, 0f, 0f);
+ st.uniform(gl, pmvMatrixUniform);
+
+ final float[] ppmmStore = glWindow.getPixelsPerMM(new float[2]);
+ final FloatBuffer rulerPixFreqV = (FloatBuffer) rulerPixFreq.getBuffer();
+ rulerPixFreqV.put(0, ppmmStore[0] * 10.0f);
+ rulerPixFreqV.put(1, ppmmStore[1] * 10.0f);
+ st.uniform(gl, rulerPixFreq);
+ System.err.println("Screen pixel/cm "+rulerPixFreqV.get(0)+", "+rulerPixFreqV.get(1));
+ }
+
+ });
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ glWindow.addGLEventListener(snap);
+ glWindow.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='x') {
+ final int[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]);
+ final int[] reqSurfacePixelScale;
+ if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
+ reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+ } else {
+ reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ }
+ System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
+ snap.setMakeSnapshot();
+ glWindow.setSurfaceScale(reqSurfacePixelScale);
+ final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
+ final int[] hasSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]);
+ final int[] nativeSurfacePixelScale = glWindow.getNativeSurfaceScale(new int[2]);
+ System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
+ reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale[0]+"x"+hasSurfacePixelScale[1]+" (has), "+
+ nativeSurfacePixelScale[0]+"x"+nativeSurfacePixelScale[1]+" (native)");
+ setTitle(glWindow);
+ }
+ }
+ });
+
+ glWindow.setVisible(true);
+
+ final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]);
+ System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ setTitle(glWindow);
+
+ snap.setMakeSnapshot();
+ glWindow.display();
+
+ Thread.sleep(durationPerTest);
+
+ glWindow.destroy();
+
+ }
@Test
- public void test01() throws InterruptedException {
- long t0 = System.nanoTime();
- GLProfile.initSingleton();
- long t1 = System.nanoTime();
- // preset ..
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow(
- new GLCapabilities(GLProfile.getGL2ES2()), 640, 480, true);
- final GLDrawable drawable = winctx.context.getGLDrawable();
- final GL2ES2 gl = winctx.context.getGL().getGL2ES2();
- System.err.println(winctx.context);
-
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- // test code ..
- final ShaderState st = new ShaderState();
-
- final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "default", false);
- final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
- "shader/bin", "ruler", false);
-
- final ShaderProgram sp0 = new ShaderProgram();
- sp0.add(gl, vp0, System.err);
- sp0.add(gl, fp0, System.err);
- Assert.assertTrue(0<=sp0.program());
- Assert.assertTrue(!sp0.inUse());
- Assert.assertTrue(!sp0.linked());
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- st.attachShaderProgram(gl, sp0, true);
-
- final PMVMatrix pmvMatrix = new PMVMatrix();
- final GLUniformData pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- st.ownUniform(pmvMatrixUniform);
- st.uniform(gl, pmvMatrixUniform);
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- final GLUniformData rulerColor= new GLUniformData("gcu_RulerColor", 3, Buffers.newDirectFloatBuffer(3));
- final FloatBuffer rulerColorV = (FloatBuffer) rulerColor.getBuffer();
- rulerColorV.put(0, 0.5f);
- rulerColorV.put(1, 0.5f);
- rulerColorV.put(2, 0.5f);
- st.ownUniform(rulerColor);
- st.uniform(gl, rulerColor);
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- Assert.assertNotNull(winctx);
- Assert.assertNotNull(winctx.window);
- Assert.assertNotNull(winctx.window.getScreen());
- ScreenMode sm = winctx.window.getScreen().getCurrentScreenMode();
- Assert.assertNotNull(sm);
- System.err.println(sm);
- final MonitorMode mmode = sm.getMonitorMode();
- final DimensionImmutable sdim = mmode.getScreenSizeMM();
- final DimensionImmutable spix = mmode.getSurfaceSize().getResolution();
- final GLUniformData rulerPixFreq = new GLUniformData("gcu_RulerPixFreq", 2, Buffers.newDirectFloatBuffer(2));
- final FloatBuffer rulerPixFreqV = (FloatBuffer) rulerPixFreq.getBuffer();
- rulerPixFreqV.put(0, (float)spix.getWidth() / (float)sdim.getWidth() * 10.0f);
- rulerPixFreqV.put(1, (float)spix.getHeight() / (float)sdim.getHeight() * 10.0f);
- st.ownUniform(rulerPixFreq);
- st.uniform(gl, rulerPixFreq);
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- System.err.println("Screen dim "+sdim);
- System.err.println("Screen siz "+spix);
- System.err.println("Screen pixel/cm "+rulerPixFreqV.get(0)+", "+rulerPixFreqV.get(1));
-
- final GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
- vertices0.putf(0); vertices0.putf(1); vertices0.putf(0);
- vertices0.putf(1); vertices0.putf(1); vertices0.putf(0);
- vertices0.putf(0); vertices0.putf(0); vertices0.putf(0);
- vertices0.putf(1); vertices0.putf(0); vertices0.putf(0);
- vertices0.seal(gl, true);
- st.ownAttribute(vertices0, true);
-
- // misc GL setup
- gl.glClearColor(1, 1, 1, 1);
- gl.glEnable(GL2ES2.GL_DEPTH_TEST);
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- // reshape
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
- pmvMatrix.glLoadIdentity();
- pmvMatrix.glOrthof(0f, 1f, 0f, 1f, -10f, 10f);
- // pmvMatrix.gluPerspective(45.0F, (float) drawable.getWidth() / (float) drawable.getHeight(), 1.0F, 100.0F);
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
- pmvMatrix.glLoadIdentity();
- // pmvMatrix.glTranslatef(0, 0, -6);
- // pmvMatrix.glRotatef(45f, 1f, 0f, 0f);
- st.uniform(gl, pmvMatrixUniform);
- gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
- Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- for(int i=0; i<10; i++) {
- vertices0.enableBuffer(gl, true);
- gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
- vertices0.enableBuffer(gl, false);
- drawable.swapBuffers();
- Thread.sleep(durationPerTest/10);
- }
-
- long t2 = System.nanoTime();
-
- NEWTGLContext.destroyWindow(winctx);
-
- long t3 = System.nanoTime();
-
- System.err.println("t1-t0: "+ (t1-t0)/1e6 +"ms");
- System.err.println("t3-t0: "+ (t3-t0)/1e6 +"ms");
- System.err.println("t3-t2: "+ (t3-t2)/1e6 +"ms");
+ public void test01_PSA() throws InterruptedException {
+ runTestGL();
}
-
- public static void main(String args[]) throws IOException {
+
+ @Test
+ public void test99_PS1() throws InterruptedException, InvocationTargetException {
+ if(manualTest) return;
+ reqSurfacePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ reqSurfacePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ runTestGL();
+ }
+
+ public static void main(final String args[]) throws IOException {
System.err.println("main - start");
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
+ } else if(args[i].equals("-pixelScale")) {
+ i++;
+ final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+ reqSurfacePixelScale[0] = pS;
+ reqSurfacePixelScale[1] = pS;
+ } else if(args[i].equals("-manual")) {
+ manualTest = true;
}
}
- String tstname = TestRulerNEWT01.class.getName();
+ final String tstname = TestRulerNEWT01.class.getName();
org.junit.runner.JUnitCore.main(tstname);
System.err.println("main - end");
- }
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java
index d133ebde5..e5b2dd2da 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -30,6 +30,8 @@ package com.jogamp.opengl.test.junit.jogl.glsl;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -37,6 +39,7 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
+
import java.awt.Frame;
import org.junit.Assert;
@@ -44,11 +47,14 @@ import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/**
* Duplicates bug 459, where a vertex shader won't compile when 8 bits of stencil are requested.
* This bug is Windows-only; it works on Mac OS X and CentOS.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestShaderCompilationBug459AWT extends UITestCase {
static int width, height;
static long duration = 500; // ms
@@ -67,13 +73,13 @@ public class TestShaderCompilationBug459AWT extends UITestCase {
@Test
public void compileShader() throws InterruptedException {
- GLProfile glp = GLProfile.get(GLProfile.GL2GL3);
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLProfile glp = GLProfile.get(GLProfile.GL2GL3);
+ final GLCapabilities caps = new GLCapabilities(glp);
// commenting out this line makes it work
caps.setStencilBits(8);
// commenting in this line also makes it work
- //caps.setSampleBuffers(true);
+ //caps.setSampleBuffers(true);
final Frame frame = new Frame("Bug 459 shader compilation test");
Assert.assertNotNull(frame);
@@ -81,58 +87,65 @@ public class TestShaderCompilationBug459AWT extends UITestCase {
final GLCanvas glCanvas = new GLCanvas(caps);
Assert.assertNotNull(glCanvas);
frame.add(glCanvas);
- frame.setSize(512, 512);
glCanvas.addGLEventListener(new GLEventListener() {
/* @Override */
- public void init(GLAutoDrawable drawable) {
- String code = "void main(void){gl_Position = vec4(0,0,0,1);}";
+ public void init(final GLAutoDrawable drawable) {
+ final String code = "void main(void){gl_Position = vec4(0,0,0,1);}";
- GL2GL3 gl = drawable.getGL().getGL2GL3();
- int id = gl.glCreateShader(GL2GL3.GL_VERTEX_SHADER);
+ final GL2GL3 gl = drawable.getGL().getGL2GL3();
+ final int id = gl.glCreateShader(GL2ES2.GL_VERTEX_SHADER);
try {
- gl.glShaderSource(id, 1, new String[] { code }, (int[])null, 0);
- gl.glCompileShader(id);
-
- int[] compiled = new int[1];
- gl.glGetShaderiv(id, GL2GL3.GL_COMPILE_STATUS, compiled, 0);
- if (compiled[0] == GL2GL3.GL_FALSE) {
- int[] logLength = new int[1];
- gl.glGetShaderiv(id, GL2GL3.GL_INFO_LOG_LENGTH, logLength, 0);
-
- byte[] log = new byte[logLength[0]];
- gl.glGetShaderInfoLog(id, logLength[0], (int[])null, 0, log, 0);
-
- System.err.println("Error compiling the shader: " + new String(log));
-
- gl.glDeleteShader(id);
- }
+ gl.glShaderSource(id, 1, new String[] { code }, (int[])null, 0);
+ gl.glCompileShader(id);
+
+ final int[] compiled = new int[1];
+ gl.glGetShaderiv(id, GL2ES2.GL_COMPILE_STATUS, compiled, 0);
+ if (compiled[0] == GL.GL_FALSE) {
+ final int[] logLength = new int[1];
+ gl.glGetShaderiv(id, GL2ES2.GL_INFO_LOG_LENGTH, logLength, 0);
+
+ final byte[] log = new byte[logLength[0]];
+ gl.glGetShaderInfoLog(id, logLength[0], (int[])null, 0, log, 0);
+
+ System.err.println("Error compiling the shader: " + new String(log));
+
+ gl.glDeleteShader(id);
+ }
else {
- System.out.println("Shader compiled: id=" + id);
+ System.out.println("Shader compiled: id=" + id);
}
}
- catch( GLException e ) {
+ catch( final GLException e ) {
glexception = e;
}
}
/* @Override */
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
}
/* @Override */
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
}
/* @Override */
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
}
});
- Animator animator = new Animator(glCanvas);
- frame.setVisible(true);
- animator.setUpdateFPSFrames(1, null);
+ final Animator animator = new Animator(glCanvas);
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(512, 512);
+ frame.setVisible(true);
+ } } );
+ } catch(final Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ animator.setUpdateFPSFrames(1, null);
animator.start();
while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
@@ -153,13 +166,13 @@ public class TestShaderCompilationBug459AWT extends UITestCase {
frame.remove(glCanvas);
frame.dispose();
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestShaderCompilationBug459AWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestTransformFeedbackVaryingsBug407NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestTransformFeedbackVaryingsBug407NEWT.java
index 3be08971b..e267d93b1 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestTransformFeedbackVaryingsBug407NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestTransformFeedbackVaryingsBug407NEWT.java
@@ -8,6 +8,7 @@ import java.io.PrintStream;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2ES3;
import javax.media.opengl.GL3;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLException;
@@ -15,6 +16,8 @@ import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.opengl.util.glsl.ShaderUtil;
@@ -24,10 +27,11 @@ import java.io.IOException;
* Bug 'Function glTransformFeedbackVaryings incorrectly passes argument'
* http://jogamp.org/bugzilla/show_bug.cgi?id=407
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTransformFeedbackVaryingsBug407NEWT extends UITestCase {
private static final boolean debugGL = true;
-
+
private static final String VERTEX_SHADER_TEXT =
"#version 150 \n"
+ " \n"
@@ -37,26 +41,26 @@ public class TestTransformFeedbackVaryingsBug407NEWT extends UITestCase {
+ " Position = vec4(1.0, 1.0, 1.0, 1.0); \n"
+ "} \n";
- class MyShader {
+ static class MyShader {
int shaderProgram;
int vertShader;
- MyShader(int shaderProgram, int vertShader) {
+ MyShader(final int shaderProgram, final int vertShader) {
this.shaderProgram = shaderProgram;
this.vertShader = vertShader;
}
}
- private MyShader attachShader(GL3 gl, String text, int type) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream pbaos = new PrintStream(baos);
+ private MyShader attachShader(final GL3 gl, final String text, final int type) {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final PrintStream pbaos = new PrintStream(baos);
- int shaderProgram = gl.glCreateProgram();
+ final int shaderProgram = gl.glCreateProgram();
- int vertShader = gl.glCreateShader(type);
+ final int vertShader = gl.glCreateShader(type);
- String[] lines = new String[]{text};
- int[] lengths = new int[]{lines[0].length()};
+ final String[] lines = new String[]{text};
+ final int[] lengths = new int[]{lines[0].length()};
gl.glShaderSource(vertShader, lines.length, lines, lengths, 0);
gl.glCompileShader(vertShader);
@@ -72,7 +76,7 @@ public class TestTransformFeedbackVaryingsBug407NEWT extends UITestCase {
return new MyShader(shaderProgram, vertShader);
}
- private void releaseShader(GL3 gl, MyShader myShader) {
+ private void releaseShader(final GL3 gl, final MyShader myShader) {
if(null!=myShader) {
gl.glDetachShader(myShader.shaderProgram, myShader.vertShader);
gl.glDeleteShader(myShader.vertShader);
@@ -82,20 +86,20 @@ public class TestTransformFeedbackVaryingsBug407NEWT extends UITestCase {
}
final static String glps = GLProfile.GL3;
-
+
private NEWTGLContext.WindowContext prepareTest() throws GLException, InterruptedException {
- final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow(
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(
new GLCapabilities(GLProfile.getMaxProgrammable(true)), 480, 480, debugGL);
if(!winctx.context.getGL().isGL3()) {
System.err.println("GL3 not available");
cleanupTest(winctx);
return null;
}
- Assert.assertEquals(GL.GL_NO_ERROR, winctx.context.getGL().glGetError());
+ Assert.assertEquals(GL.GL_NO_ERROR, winctx.context.getGL().glGetError());
return winctx;
}
- private void cleanupTest(NEWTGLContext.WindowContext winctx) {
+ private void cleanupTest(final NEWTGLContext.WindowContext winctx) {
if(null!=winctx) {
NEWTGLContext.destroyWindow(winctx);
}
@@ -103,27 +107,27 @@ public class TestTransformFeedbackVaryingsBug407NEWT extends UITestCase {
@Test(timeout=60000)
public void testGlTransformFeedbackVaryings_WhenVarNameOK() throws GLException, InterruptedException {
- NEWTGLContext.WindowContext winctx = prepareTest();
+ final NEWTGLContext.WindowContext winctx = prepareTest();
if(null == winctx) {
return;
}
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream pbaos = new PrintStream(baos);
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final PrintStream pbaos = new PrintStream(baos);
// given
final GL3 gl = winctx.context.getGL().getGL3();
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- MyShader myShader = attachShader(gl, VERTEX_SHADER_TEXT, GL3.GL_VERTEX_SHADER);
- String[] vars = new String[]{"Position"};
+
+ final MyShader myShader = attachShader(gl, VERTEX_SHADER_TEXT, GL2ES2.GL_VERTEX_SHADER);
+ final String[] vars = new String[]{"Position"};
// when
- gl.glTransformFeedbackVaryings(myShader.shaderProgram, 1, vars, GL3.GL_SEPARATE_ATTRIBS);
+ gl.glTransformFeedbackVaryings(myShader.shaderProgram, 1, vars, GL2ES3.GL_SEPARATE_ATTRIBS);
gl.glLinkProgram(myShader.shaderProgram);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
+
// then
boolean error = false;
@@ -133,33 +137,33 @@ public class TestTransformFeedbackVaryingsBug407NEWT extends UITestCase {
error = true;
}
pbaos.flush(); baos.reset();
- Assert.assertEquals(GL3.GL_NO_ERROR, gl.glGetError());
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- releaseShader(gl, myShader);
+ releaseShader(gl, myShader);
cleanupTest(winctx);
Assert.assertFalse(error);
}
@Test(timeout=60000)
public void testGlTransformFeedbackVaryings_WhenVarNameWrong() throws GLException, InterruptedException {
- NEWTGLContext.WindowContext winctx = prepareTest();
+ final NEWTGLContext.WindowContext winctx = prepareTest();
if(null == winctx) {
return;
}
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream pbaos = new PrintStream(baos);
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final PrintStream pbaos = new PrintStream(baos);
// given
final GL3 gl = winctx.context.getGL().getGL3();
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- MyShader myShader = attachShader(gl, VERTEX_SHADER_TEXT, GL3.GL_VERTEX_SHADER);
- String[] vars = new String[]{"PPPosition"};
+ final MyShader myShader = attachShader(gl, VERTEX_SHADER_TEXT, GL2ES2.GL_VERTEX_SHADER);
+ final String[] vars = new String[]{"PPPosition"};
// when
- gl.glTransformFeedbackVaryings(myShader.shaderProgram, 1, vars, GL3.GL_SEPARATE_ATTRIBS);
+ gl.glTransformFeedbackVaryings(myShader.shaderProgram, 1, vars, GL2ES3.GL_SEPARATE_ATTRIBS);
gl.glLinkProgram(myShader.shaderProgram);
// then
@@ -170,21 +174,21 @@ public class TestTransformFeedbackVaryingsBug407NEWT extends UITestCase {
System.out.println("GOOD (expected link error) - testGlTransformFeedbackVaryings_WhenVarNameWrong:postLink: "+baos.toString());
// should be invalid, due to wrong var name
} else {
- // oops
+ // oops
System.out.println("Error (unexpected link success) - testGlTransformFeedbackVaryings_WhenVarNameWrong link worked, but it should not");
error = true;
}
pbaos.flush(); baos.reset();
- Assert.assertEquals(GL3.GL_NO_ERROR, gl.glGetError());
-
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
releaseShader(gl, myShader);
cleanupTest(winctx);
Assert.assertFalse(error);
}
- public static void main(String args[]) throws IOException {
- String tstname = TestTransformFeedbackVaryingsBug407NEWT.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestTransformFeedbackVaryingsBug407NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug365TextureGenerateMipMaps.java b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug365TextureGenerateMipMaps.java
new file mode 100644
index 000000000..dfa26a049
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug365TextureGenerateMipMaps.java
@@ -0,0 +1,272 @@
+package com.jogamp.opengl.test.junit.jogl.glu;
+
+import java.nio.ByteBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLOffscreenAutoDrawable;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import jogamp.opengl.glu.mipmap.Mipmap;
+import jogamp.opengl.glu.mipmap.ScaleInternal;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * This test creates a {@link Texture} from {@link TextureData} of various pixel formats
+ * and pixel types with auto generate mipmaps set to {@code true}.
+ * <br></br>
+ * Bug Reference: https://jogamp.org/bugzilla/show_bug.cgi?id=365
+ * <br></br>
+ * The bug pertains to mipmap generation from a Texture and exists in {@link ScaleInternal}
+ * where a {@link java.nio.BufferUnderflowException} is thrown.
+ * <br></br>
+ * <ul>This suite of test cases test:
+ * <li>{@link ScaleInternal#scale_internal_ubyte(int, int, int, ByteBuffer, int, int, ByteBuffer, int, int, int)}</li>
+ * <li>{@link ScaleInternal#scale_internal_byte(int, int, int, ByteBuffer, int, int, ByteBuffer, int, int, int)}</li>
+ * <li>{@link ScaleInternal#scale_internal_ushort(int, int, int, ByteBuffer, int, int, java.nio.ShortBuffer, int, int, int, boolean)}</li>
+ * <li>{@link ScaleInternal#scale_internal_short(int, int, int, ByteBuffer, int, int, java.nio.ShortBuffer, int, int, int, boolean)}</li>
+ * <li>{@link ScaleInternal#scale_internal_uint(int, int, int, ByteBuffer, int, int, java.nio.IntBuffer, int, int, int, boolean)}</li>
+ * <li>{@link ScaleInternal#scale_internal_int(int, int, int, ByteBuffer, int, int, java.nio.IntBuffer, int, int, int, boolean)}</li>
+ * <li>{@link ScaleInternal#scale_internal_float(int, int, int, ByteBuffer, int, int, java.nio.FloatBuffer, int, int, int, boolean)}</li>
+ * </ul>
+ *
+ * @author Michael Esemplare, et.al.
+ *
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug365TextureGenerateMipMaps extends UITestCase {
+ static GLOffscreenAutoDrawable drawable;
+
+ @BeforeClass
+ public static void setup() throws Throwable {
+ // disableNPOT
+ System.setProperty("jogl.texture.nonpot", "true");
+ try {
+ setUpOffscreenAutoDrawable();
+ } catch (final Throwable t) {
+ throw t;
+ }
+ }
+
+ @AfterClass
+ public static void teardown() {
+ tearDownOffscreenAutoDrawable();
+ }
+
+ private static void setUpOffscreenAutoDrawable() throws Throwable {
+ final GLProfile glp = GLProfile.getDefault();
+ final GLCapabilities caps = new GLCapabilities(glp);
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp);
+
+ // Make a drawable to get an offscreen context
+ drawable = factory.createOffscreenAutoDrawable(null, caps, null, 2, 2);
+ drawable.display(); // trigger context creation
+ final GLContext glContext = drawable.getContext();
+ try {
+ Assert.assertTrue("Could not make context current", GLContext.CONTEXT_NOT_CURRENT < glContext.makeCurrent());
+ } catch (final Throwable t) {
+ tearDownOffscreenAutoDrawable();
+ throw t;
+ }
+ }
+
+ private static void tearDownOffscreenAutoDrawable() {
+ if(drawable != null) {
+ drawable.getContext().release();
+ drawable.destroy();
+ drawable = null;
+ }
+ }
+
+ private static void testTextureMipMapGeneration(final int width, final int height, final int pixelFormat, final int pixelType) {
+ final int internalFormat = pixelFormat;
+ final int border = 0;
+ final boolean mipmap = true;
+ final boolean dataIsCompressed = false;
+ final boolean mustFlipVertically = false;
+
+ final int memReq = Mipmap.image_size( width, height, pixelFormat, pixelType );
+ ByteBuffer buffer = Buffers.newDirectByteBuffer( memReq );
+
+ final TextureData data = new TextureData(drawable.getGLProfile(),
+ internalFormat,
+ width,
+ height,
+ border,
+ pixelFormat,
+ pixelType,
+ mipmap,
+ dataIsCompressed,
+ mustFlipVertically,
+ buffer,
+ null);
+
+ final Texture texture = TextureIO.newTexture(drawable.getGL(), data);
+ // Cleanup
+ texture.destroy(drawable.getGL());
+ data.destroy();
+ buffer.clear();
+ buffer = null;
+ }
+
+ @Test
+ public void test00_MipMap_ScaleInternal_RGB_UBYTE () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGB;
+ final int pixelType = GL.GL_UNSIGNED_BYTE;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test01_MipMap_ScaleInternal_RGBA_UBYTE () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGBA;
+ final int pixelType = GL.GL_UNSIGNED_BYTE;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test02_MipMap_ScaleInternal_RGB_BYTE () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGB;
+ final int pixelType = GL.GL_BYTE;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test03_MipMap_ScaleInternal_RGBA_BYTE () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGBA;
+ final int pixelType = GL.GL_BYTE;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test04_MipMap_ScaleInternal_RGB_USHORT () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGB;
+ final int pixelType = GL.GL_UNSIGNED_SHORT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test05_MipMap_ScaleInternal_RGBA_USHORT () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGBA;
+ final int pixelType = GL.GL_UNSIGNED_SHORT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test06_MipMap_ScaleInternal_RGB_SHORT () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGB;
+ final int pixelType = GL.GL_SHORT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test07_MipMap_ScaleInternal_RGBA_SHORT () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGBA;
+ final int pixelType = GL.GL_SHORT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test08_MipMap_ScaleInternal_RGB_UINT () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGB;
+ final int pixelType = GL.GL_UNSIGNED_INT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test09_MipMap_ScaleInternal_RGBA_UINT () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGBA;
+ final int pixelType = GL.GL_UNSIGNED_INT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test10_MipMap_ScaleInternal_RGB_INT () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGB;
+ final int pixelType = GL2ES2.GL_INT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test11_MipMap_ScaleInternal_RGBA_INT () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGBA;
+ final int pixelType = GL2ES2.GL_INT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test12_MipMap_ScaleInternal_RGB_FLOAT () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGB;
+ final int pixelType = GL.GL_FLOAT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test13_MipMap_ScaleInternal_RGBA_FLOAT () {
+ final int width = 1;
+ final int height = 7;
+ final int pixelFormat = GL.GL_RGBA;
+ final int pixelType = GL.GL_FLOAT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ public static void main(final String[] args) {
+ org.junit.runner.JUnitCore.main(TestBug365TextureGenerateMipMaps.class.getName());
+ }
+} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug463ScaleImageMemoryAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug463ScaleImageMemoryAWT.java
index 3f122accb..5c63b2e1d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug463ScaleImageMemoryAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug463ScaleImageMemoryAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.glu;
import java.awt.Frame;
@@ -41,6 +41,8 @@ import javax.media.opengl.glu.gl2es1.GLUgl2es1;
import org.junit.Assume;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.opengl.test.junit.util.UITestCase;
@@ -49,32 +51,33 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
* 4-byte direct buffer objects inside the tight loops of Image.fill_image() and Image.empty_image(). Since
* the JVM apparently can only allocate direct buffer in 4MB chunks, each 4-byte buffer cost us a million times
* the memory it should have. Changing the constructor of Type_Widget.java back to non-direct buffer (like it
- * was in JOGL 1) solves the problem.
+ * was in JOGL 1) solves the problem.
* @author Wade Walker
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestBug463ScaleImageMemoryAWT extends UITestCase implements GLEventListener {
/* @Override */
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
}
/* @Override */
- public void display(GLAutoDrawable drawable) {
- int widthin = 559;
- int heightin = 425;
-
- int widthout = 1024;
- int heightout = 512;
-
- int textureInLength = widthin * heightin * 4;
- int textureOutLength = widthout * heightout * 4;
-
- byte[] datain = new byte[textureInLength];
- byte[] dataout = new byte[textureOutLength];
-
- ByteBuffer bufferIn = ByteBuffer.wrap(datain);
- ByteBuffer bufferOut = ByteBuffer.wrap(dataout);
- GLUgl2es1 glu = new GLUgl2es1();
+ public void display(final GLAutoDrawable drawable) {
+ final int widthin = 559;
+ final int heightin = 425;
+
+ final int widthout = 1024;
+ final int heightout = 512;
+
+ final int textureInLength = widthin * heightin * 4;
+ final int textureOutLength = widthout * heightout * 4;
+
+ final byte[] datain = new byte[textureInLength];
+ final byte[] dataout = new byte[textureOutLength];
+
+ final ByteBuffer bufferIn = ByteBuffer.wrap(datain);
+ final ByteBuffer bufferOut = ByteBuffer.wrap(dataout);
+ final GLUgl2es1 glu = new GLUgl2es1();
// in the failing case, the system would run out of memory in here
glu.gluScaleImage( GL.GL_RGBA,
widthin, heightin, GL.GL_UNSIGNED_BYTE, bufferIn,
@@ -82,24 +85,24 @@ public class TestBug463ScaleImageMemoryAWT extends UITestCase implements GLEvent
}
/* @Override */
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
}
/* @Override */
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
}
@Test
public void test01() throws InterruptedException {
- GLProfile glprofile = GLProfile.getGL2ES1();
- GLCapabilities glCapabilities = new GLCapabilities(glprofile);
+ final GLProfile glprofile = GLProfile.getGL2ES1();
+ final GLCapabilities glCapabilities = new GLCapabilities(glprofile);
final GLCanvas canvas = new GLCanvas(glCapabilities);
canvas.addGLEventListener( this );
-
+
final Frame frame = new Frame("Test");
frame.add(canvas);
- frame.setSize(256, 256);
+ frame.setSize(256, 256);
frame.validate();
try {
@@ -107,15 +110,15 @@ public class TestBug463ScaleImageMemoryAWT extends UITestCase implements GLEvent
public void run() {
frame.setVisible(true);
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
-
+
canvas.display();
Thread.sleep(200);
-
+
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -123,13 +126,13 @@ public class TestBug463ScaleImageMemoryAWT extends UITestCase implements GLEvent
frame.remove(canvas);
frame.dispose();
}});
- } catch (Throwable t) {
+ } catch (final Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
- }
+ }
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestBug463ScaleImageMemoryAWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug694ScaleImageUnpackBufferSizeAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug694ScaleImageUnpackBufferSizeAWT.java
new file mode 100644
index 000000000..184dea8ba
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug694ScaleImageUnpackBufferSizeAWT.java
@@ -0,0 +1,164 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.glu;
+
+import java.awt.Frame;
+import java.nio.ByteBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.glu.GLU;
+
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLBuffers;
+import com.jogamp.opengl.util.GLPixelStorageModes;
+
+/**
+ * Demonstrates how to use {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean)}
+ * to determine the unpack buffer size for {@link GLU#gluScaleImage(int, int, int, int, java.nio.Buffer, int, int, int, java.nio.Buffer)}.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug694ScaleImageUnpackBufferSizeAWT extends UITestCase implements GLEventListener {
+
+ /* @Override */
+ public void init(final GLAutoDrawable drawable) {
+ }
+
+ /* @Override */
+ public void display(final GLAutoDrawable drawable) {
+ if( !testDone ) {
+ testDone = true;
+
+ final GL gl = drawable.getGL();
+ final GLU glu = GLU.createGLU(gl);
+ testGLUScaleImage(gl, glu, 0); // default 4
+ testGLUScaleImage(gl, glu, 1);
+ testGLUScaleImage(gl, glu, 4);
+ testGLUScaleImage(gl, glu, 8);
+ }
+ }
+
+ boolean testDone = false;
+
+ private void testGLUScaleImage(final GL gl, final GLU glu, final int unpackAlignment) {
+ final GLPixelStorageModes psm = new GLPixelStorageModes();
+ if(0 < unpackAlignment) {
+ psm.setUnpackAlignment(gl, unpackAlignment);
+ }
+
+ final int widthin = 213;
+ final int heightin = 213;
+
+ final int widthout = 256;
+ final int heightout = 256;
+
+ final int glFormat = GL.GL_LUMINANCE;
+ final int glType = GL.GL_UNSIGNED_BYTE;
+ final int tmp[] = new int[1];
+
+ final int unpackSizeInLen = GLBuffers.sizeof(gl, tmp, glFormat, glType, widthin, heightin, 1, false);
+ final int unpackSizeOutLen = GLBuffers.sizeof(gl, tmp, glFormat, glType, widthout, heightout, 1, false);
+
+ System.err.println("Unpack-Alignment "+unpackAlignment+": in-size "+unpackSizeInLen);
+ System.err.println("Unpack-Alignment "+unpackAlignment+": out-size "+unpackSizeOutLen);
+
+ final ByteBuffer bufferIn = Buffers.newDirectByteBuffer(unpackSizeInLen);
+ final ByteBuffer bufferOut = Buffers.newDirectByteBuffer(unpackSizeOutLen);
+
+ glu.gluScaleImage( GL.GL_LUMINANCE,
+ widthin, heightin, GL.GL_UNSIGNED_BYTE, bufferIn,
+ widthout, heightout, GL.GL_UNSIGNED_BYTE, bufferOut );
+
+ if(0 < unpackAlignment) {
+ psm.restore(gl);
+ }
+ }
+
+ /* @Override */
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ }
+
+
+ /* @Override */
+ public void dispose(final GLAutoDrawable drawable) {
+ }
+
+ @Test
+ public void test01() throws InterruptedException {
+ final GLProfile glprofile = GLProfile.getDefault();
+ final GLCapabilities glCapabilities = new GLCapabilities(glprofile);
+ final GLCanvas canvas = new GLCanvas(glCapabilities);
+ canvas.addGLEventListener( this );
+
+ final Frame frame = new Frame("Test");
+ frame.add(canvas);
+ frame.setSize(256, 256);
+ frame.validate();
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(true);
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+
+ canvas.display();
+
+ Thread.sleep(200);
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ frame.remove(canvas);
+ frame.dispose();
+ }});
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ Assume.assumeNoException(t);
+ }
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestBug694ScaleImageUnpackBufferSizeAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary16NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary16NOUI.java
new file mode 100644
index 000000000..5e4166a49
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary16NOUI.java
@@ -0,0 +1,715 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.math;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.math.Binary16;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public final class TestBinary16NOUI extends UITestCase /* due to hardship on machine, we want to run this test exclusively! */
+{
+ static int stepping = 1;
+ static boolean verbose = false;
+
+ /**
+ * Exponents in the range [-15, 16] are encoded and decoded correctly.
+ */
+
+ @SuppressWarnings("static-method") @Test public void testExponentIdentity()
+ {
+ System.out.println("-- Exponent identities");
+ for (int e = -15; e <= 16; ++e) {
+ final char p = Binary16.packSetExponentUnbiasedUnchecked(e);
+ final int u = Binary16.unpackGetExponentUnbiased(p);
+ if( verbose ) {
+ System.out.println("e: " + e +", p: "+Integer.toHexString(p)+", u: "+u);
+ }
+ Assert.assertEquals(e, u);
+ }
+ }
+
+ /**
+ * Infinities are infinite.
+ */
+
+ @SuppressWarnings("static-method") @Test public void testInfinite()
+ {
+ Assert.assertTrue(Binary16.isInfinite(Binary16.POSITIVE_INFINITY));
+ Assert.assertTrue(Binary16.isInfinite(Binary16.NEGATIVE_INFINITY));
+ Assert.assertFalse(Binary16.isInfinite(Binary16.exampleNaN()));
+
+ for (int i = 0; i <= 65535; i+=stepping) {
+ Assert.assertFalse(Binary16.isInfinite(Binary16.packDouble(i)));
+ }
+ }
+
+ /**
+ * The unencoded exponent of infinity is 16.
+ */
+
+ @SuppressWarnings("static-method") @Test public void testInfinityExponent()
+ {
+ Assert.assertEquals(
+ 16,
+ Binary16.unpackGetExponentUnbiased(Binary16.POSITIVE_INFINITY));
+ }
+
+ /**
+ * The unencoded exponent of infinity is 16.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinityNegativeExponent()
+ {
+ Assert.assertEquals(
+ 16,
+ Binary16.unpackGetExponentUnbiased(Binary16.NEGATIVE_INFINITY));
+ }
+
+ /**
+ * The sign of negative infinity is 1.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinityNegativeSign()
+ {
+ Assert
+ .assertEquals(1, Binary16.unpackGetSign(Binary16.NEGATIVE_INFINITY));
+ }
+
+ /**
+ * The significand of infinity is 0.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinityNegativeSignificand()
+ {
+ Assert.assertEquals(
+ 0,
+ Binary16.unpackGetSignificand(Binary16.NEGATIVE_INFINITY));
+ }
+
+ /**
+ * The sign of positive infinity is 0.
+ */
+
+ @SuppressWarnings("static-method") @Test public void testInfinitySign()
+ {
+ Assert
+ .assertEquals(0, Binary16.unpackGetSign(Binary16.POSITIVE_INFINITY));
+ }
+
+ /**
+ * The significand of infinity is 0.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinitySignificand()
+ {
+ Assert.assertEquals(
+ 0,
+ Binary16.unpackGetSignificand(Binary16.POSITIVE_INFINITY));
+ }
+
+ /**
+ * NaN is NaN.
+ */
+
+ @SuppressWarnings("static-method") @Test public void testNaN()
+ {
+ final int n =
+ Binary16.packSetExponentUnbiasedUnchecked(16)
+ | Binary16.packSetSignificandUnchecked(1);
+ final char c = (char) n;
+ Assert.assertEquals(16, Binary16.unpackGetExponentUnbiased(c));
+ Assert.assertEquals(1, Binary16.unpackGetSignificand(c));
+ Assert.assertEquals(
+ 16,
+ Binary16.unpackGetExponentUnbiased(Binary16.exampleNaN()));
+ Assert.assertEquals(
+ 1,
+ Binary16.unpackGetSignificand(Binary16.exampleNaN()));
+ Assert.assertTrue(Binary16.isNaN(c));
+ Assert.assertTrue(Binary16.isNaN(Binary16.exampleNaN()));
+ }
+
+ /**
+ * Packing NaN results in NaN.
+ */
+
+ @SuppressWarnings("static-method") @Test public void testPackDoubleNaN()
+ {
+ final double k = Double.NaN;
+ final char r = Binary16.packDouble(k);
+ Assert.assertTrue(Binary16.isNaN(r));
+ }
+
+ /**
+ * Packing negative infinity results in negative infinity.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testPackDoubleNegativeInfinity()
+ {
+ Assert.assertTrue(Binary16.NEGATIVE_INFINITY == Binary16
+ .packDouble(Double.NEGATIVE_INFINITY));
+ }
+
+ /**
+ * Packing negative zero results in negative zero.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testPackDoubleNegativeZero()
+ {
+ Assert.assertTrue(Binary16.NEGATIVE_ZERO == Binary16.packDouble(-0.0));
+ }
+
+ /**
+ * Packing positive infinity results in positive infinity.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testPackDoublePositiveInfinity()
+ {
+ Assert.assertTrue(Binary16.POSITIVE_INFINITY == Binary16
+ .packDouble(Double.POSITIVE_INFINITY));
+ }
+
+ /**
+ * Packing positive zero results in positive zero.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testPackDoublePositiveZero()
+ {
+ Assert.assertTrue(Binary16.POSITIVE_ZERO == Binary16.packDouble(0.0));
+ }
+
+ /**
+ * Integers in the range [0, 65520] should be representable.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testPackDoubleUnpackFloat()
+ {
+ for (int i = 0; i <= 65536; i+=stepping) {
+ final double in = i;
+ final char packed = Binary16.packDouble(in);
+ final float r = Binary16.unpackFloat(packed);
+ if( verbose ) {
+ System.out.println(String.format(
+ "packed: 0x%04x 0b%s in: %f unpacked: %f",
+ (int) packed,
+ Binary16.toRawBinaryString(packed),
+ in,
+ r));
+ }
+
+ if (i <= 2048) {
+ Assert.assertEquals(in, r, 0.0);
+ }
+ if ((i > 2048) && (i <= 4096)) {
+ Assert.assertTrue((r % 2) == 0);
+ }
+ if ((i > 4096) && (i <= 8192)) {
+ Assert.assertTrue((r % 4) == 0);
+ }
+ if ((i > 8192) && (i <= 16384)) {
+ Assert.assertTrue((r % 8) == 0);
+ }
+ if ((i > 16384) && (i <= 32768)) {
+ Assert.assertTrue((r % 16) == 0);
+ }
+ if ((i > 32768) && (i < 65536)) {
+ Assert.assertTrue((r % 32) == 0);
+ }
+ if (i == 65536) {
+ Assert.assertTrue(Double.isInfinite(r));
+ }
+ }
+ }
+
+ /**
+ * Integers in the range [0, 65520] should be representable.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testPackFloatDoubleEquivalent()
+ {
+ for (int i = 0; i <= 65536; i+=stepping) {
+ final float f_in = i;
+ final double d_in = i;
+ final char pf = Binary16.packFloat(f_in);
+ final char pd = Binary16.packDouble(d_in);
+
+ if( verbose ) {
+ System.out.println("i: " + i);
+ System.out.println(String.format(
+ "pack_f: 0x%04x 0b%s",
+ (int) pf,
+ Binary16.toRawBinaryString(pf)));
+ System.out.println(String.format(
+ "pack_d: 0x%04x 0b%s",
+ (int) pd,
+ Binary16.toRawBinaryString(pd)));
+ }
+
+ Assert.assertEquals(pf, pd);
+ }
+ }
+
+ /**
+ * Packing NaN results in NaN.
+ */
+
+ @SuppressWarnings("static-method") @Test public void testPackFloatNaN()
+ {
+ final float k = Float.NaN;
+ final char r = Binary16.packFloat(k);
+ Assert.assertTrue(Binary16.isNaN(r));
+ }
+
+ /**
+ * Packing negative infinity results in negative infinity.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testPackFloatNegativeInfinity()
+ {
+ Assert.assertTrue(Binary16.NEGATIVE_INFINITY == Binary16
+ .packFloat(Float.NEGATIVE_INFINITY));
+ }
+
+ /**
+ * Packing negative zero results in negative zero.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testPackFloatNegativeZero()
+ {
+ Assert.assertTrue(Binary16.NEGATIVE_ZERO == Binary16.packFloat(-0.0f));
+ }
+
+ /**
+ * Packing positive infinity results in positive infinity.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testPackFloatPositiveInfinity()
+ {
+ Assert.assertTrue(Binary16.POSITIVE_INFINITY == Binary16
+ .packFloat(Float.POSITIVE_INFINITY));
+ }
+
+ /**
+ * Packing positive zero results in positive zero.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testPackFloatPositiveZero()
+ {
+ Assert.assertTrue(Binary16.POSITIVE_ZERO == Binary16.packFloat(0.0f));
+ }
+
+ /**
+ * Integers in the range [0, 65520] should be representable.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testPackFloatUnpackDouble()
+ {
+ for (int i = 0; i <= 65536; i+=stepping) {
+ final float in = i;
+ final char packed = Binary16.packFloat(in);
+ final double r = Binary16.unpackDouble(packed);
+ if( verbose ) {
+ System.out.println(String.format(
+ "packed: 0x%04x 0b%s in: %f unpacked: %f",
+ (int) packed,
+ Binary16.toRawBinaryString(packed),
+ in,
+ r));
+ }
+
+ if (i <= 2048) {
+ Assert.assertEquals(in, r, 0.0);
+ }
+ if ((i > 2048) && (i <= 4096)) {
+ Assert.assertTrue((r % 2) == 0);
+ }
+ if ((i > 4096) && (i <= 8192)) {
+ Assert.assertTrue((r % 4) == 0);
+ }
+ if ((i > 8192) && (i <= 16384)) {
+ Assert.assertTrue((r % 8) == 0);
+ }
+ if ((i > 16384) && (i <= 32768)) {
+ Assert.assertTrue((r % 16) == 0);
+ }
+ if ((i > 32768) && (i < 65536)) {
+ Assert.assertTrue((r % 32) == 0);
+ }
+ if (i == 65536) {
+ Assert.assertTrue(Double.isInfinite(r));
+ }
+ }
+ }
+
+ /**
+ * Integers in the range [0, 65520] should be representable.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testPackUnpackDouble()
+ {
+ for (int i = 0; i <= 65536; i+=stepping) {
+ final double in = i;
+ final char packed = Binary16.packDouble(in);
+ final double r = Binary16.unpackDouble(packed);
+ if( verbose ) {
+ System.out.println(String.format(
+ "packed: 0x%04x 0b%s in: %f unpacked: %f",
+ (int) packed,
+ Binary16.toRawBinaryString(packed),
+ in,
+ r));
+ }
+
+ if (i <= 2048) {
+ Assert.assertEquals(in, r, 0.0);
+ }
+ if ((i > 2048) && (i <= 4096)) {
+ Assert.assertTrue((r % 2) == 0);
+ }
+ if ((i > 4096) && (i <= 8192)) {
+ Assert.assertTrue((r % 4) == 0);
+ }
+ if ((i > 8192) && (i <= 16384)) {
+ Assert.assertTrue((r % 8) == 0);
+ }
+ if ((i > 16384) && (i <= 32768)) {
+ Assert.assertTrue((r % 16) == 0);
+ }
+ if ((i > 32768) && (i < 65536)) {
+ Assert.assertTrue((r % 32) == 0);
+ }
+ if (i == 65536) {
+ Assert.assertTrue(Double.isInfinite(r));
+ }
+ }
+ }
+
+ /**
+ * Integers in the range [0, 65520] should be representable.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testPackUnpackFloat()
+ {
+ for (int i = 0; i <= 65536; i+=stepping) {
+ final float in = i;
+ final char packed = Binary16.packFloat(in);
+ final float r = Binary16.unpackFloat(packed);
+ if( verbose ) {
+ System.out.println(String.format(
+ "packed: 0x%04x 0b%s in: %f unpacked: %f",
+ (int) packed,
+ Binary16.toRawBinaryString(packed),
+ in,
+ r));
+ }
+ if (i <= 2048) {
+ Assert.assertEquals(in, r, 0.0);
+ }
+ if ((i > 2048) && (i <= 4096)) {
+ Assert.assertTrue((r % 2) == 0);
+ }
+ if ((i > 4096) && (i <= 8192)) {
+ Assert.assertTrue((r % 4) == 0);
+ }
+ if ((i > 8192) && (i <= 16384)) {
+ Assert.assertTrue((r % 8) == 0);
+ }
+ if ((i > 16384) && (i <= 32768)) {
+ Assert.assertTrue((r % 16) == 0);
+ }
+ if ((i > 32768) && (i < 65536)) {
+ Assert.assertTrue((r % 32) == 0);
+ }
+ if (i == 65536) {
+ Assert.assertTrue(Float.isInfinite(r));
+ }
+ }
+ }
+
+ /**
+ * Signs in the range [0, 1] are encoded and decoded correctly.
+ */
+
+ @SuppressWarnings("static-method") @Test public void testSignIdentity()
+ {
+ System.out.println("-- Sign identities");
+ for (int e = 0; e <= 1; ++e) {
+ final char p = Binary16.packSetSignUnchecked(e);
+ final int u = Binary16.unpackGetSign(p);
+ if( verbose ) {
+ System.out.println("e: " + e +", p: "+Integer.toHexString(p)+", u: "+u);
+ }
+ Assert.assertEquals(e, u);
+ }
+ }
+
+ /**
+ * Significands in the range [0, 1023] are encoded and decoded correctly.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testSignificandIdentity()
+ {
+ System.out.println("-- Significand identities");
+ for (int e = 0; e <= 1023; ++e) {
+ final char p = Binary16.packSetSignificandUnchecked(e);
+ final int u = Binary16.unpackGetSignificand(p);
+ if( verbose ) {
+ System.out.println("e: " + e +", p: "+Integer.toHexString(p)+", u: "+u);
+ }
+ Assert.assertEquals(e, u);
+ }
+ }
+
+ /**
+ * Unpacking NaN results in NaN.
+ */
+
+ @SuppressWarnings("static-method") @Test public void testUnpackDoubleNaN()
+ {
+ final double k = Binary16.unpackDouble(Binary16.exampleNaN());
+ Assert.assertTrue(Double.isNaN(k));
+ }
+
+ /**
+ * Unpacking negative infinity results in negative infinity.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testUnpackDoubleNegativeInfinity()
+ {
+ Assert.assertTrue(Double.NEGATIVE_INFINITY == Binary16
+ .unpackDouble(Binary16.NEGATIVE_INFINITY));
+ }
+
+ /**
+ * Unpacking negative zero results in negative zero.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testUnpackDoubleNegativeZero()
+ {
+ Assert.assertTrue(-0.0 == Binary16.unpackDouble(Binary16.NEGATIVE_ZERO));
+ }
+
+ /**
+ * Unpacking 1.0 results in 1.0.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testUnpackDoubleOne()
+ {
+ final char one = 0x3C00;
+ final double r = Binary16.unpackDouble(one);
+ System.out.println(String.format("0x%04x -> %f", (int) one, r));
+ Assert.assertEquals(r, 1.0, 0.0);
+ }
+
+ /**
+ * Unpacking -1.0 results in -1.0.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testUnpackDoubleOneNegative()
+ {
+ final char one = 0xBC00;
+ final double r = Binary16.unpackDouble(one);
+ System.out.println(String.format("0x%04x -> %f", (int) one, r));
+ Assert.assertEquals(r, -1.0, 0.0);
+ }
+
+ /**
+ * Unpacking positive infinity results in positive infinity.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testUnpackDoublePositiveInfinity()
+ {
+ Assert.assertTrue(Double.POSITIVE_INFINITY == Binary16
+ .unpackDouble(Binary16.POSITIVE_INFINITY));
+ }
+
+ /**
+ * Unpacking positive zero results in positive zero.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testUnpackDoublePositiveZero()
+ {
+ Assert.assertTrue(0.0 == Binary16.unpackDouble(Binary16.POSITIVE_ZERO));
+ }
+
+ /**
+ * Unpacking 2.0 results in 2.0.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testUnpackDoubleTwo()
+ {
+ final char one = 0x4000;
+ final double r = Binary16.unpackDouble(one);
+ System.out.println(String.format("%04x -> %f", (int) one, r));
+ Assert.assertEquals(r, 2.0, 0.0);
+ }
+
+ /**
+ * Unpacking -2.0 results in -2.0.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testUnpackDoubleTwoNegative()
+ {
+ final char one = 0xC000;
+ final double r = Binary16.unpackDouble(one);
+ System.out.println(String.format("%04x -> %f", (int) one, r));
+ Assert.assertEquals(r, -2.0, 0.0);
+ }
+
+ /**
+ * Unpacking NaN results in NaN.
+ */
+
+ @SuppressWarnings("static-method") @Test public void testUnpackFloatNaN()
+ {
+ final float k = Binary16.unpackFloat(Binary16.exampleNaN());
+ Assert.assertTrue(Float.isNaN(k));
+ }
+
+ /**
+ * Unpacking negative infinity results in negative infinity.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testUnpackFloatNegativeInfinity()
+ {
+ Assert.assertTrue(Float.NEGATIVE_INFINITY == Binary16
+ .unpackFloat(Binary16.NEGATIVE_INFINITY));
+ }
+
+ /**
+ * Unpacking negative zero results in negative zero.
+ */
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testUnpackFloatNegativeZero()
+ {
+ Assert.assertTrue(-0.0 == Binary16.unpackFloat(Binary16.NEGATIVE_ZERO));
+ }
+
+ /**
+ * Unpacking 1.0 results in 1.0.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testUnpackFloatOne()
+ {
+ final char one = 0x3C00;
+ final float r = Binary16.unpackFloat(one);
+ System.out.println(String.format("0x%04x -> %f", (int) one, r));
+ Assert.assertEquals(r, 1.0, 0.0);
+ }
+
+ /**
+ * Unpacking -1.0 results in -1.0.
+ */
+
+ @SuppressWarnings({ "static-method", "boxing" }) @Test public
+ void
+ testUnpackFloatOneNegative()
+ {
+ final char one = 0xBC00;
+ final float r = Binary16.unpackFloat(one);
+ System.out.println(String.format("0x%04x -> %f", (int) one, r));
+ Assert.assertEquals(r, -1.0, 0.0);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-stepping")) {
+ stepping = MiscUtils.atoi(args[++i], stepping);
+ } else if(args[i].equals("-verbose")) {
+ verbose = true;
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestBinary16NOUI.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary32NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary32NOUI.java
new file mode 100644
index 000000000..d2a9a92ce
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary32NOUI.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.math;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.jogamp.opengl.math.Binary32;
+
+public class TestBinary32NOUI
+{
+ @SuppressWarnings("static-method") @Test public void testInfinityExponent()
+ {
+ Assert.assertEquals(
+ 128,
+ Binary32.unpackGetExponentUnbiased(Float.POSITIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinityNegativeExponent()
+ {
+ Assert.assertEquals(
+ 128,
+ Binary32.unpackGetExponentUnbiased(Float.NEGATIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinityNegativeSign()
+ {
+ Assert.assertEquals(1, Binary32.unpackGetSign(Float.NEGATIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinityNegativeSignificand()
+ {
+ Assert.assertEquals(
+ 0,
+ Binary32.unpackGetSignificand(Float.NEGATIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public void testInfinitySign()
+ {
+ Assert.assertEquals(0, Binary32.unpackGetSign(Float.POSITIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinitySignificand()
+ {
+ Assert.assertEquals(
+ 0,
+ Binary32.unpackGetSignificand(Float.POSITIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public void testNaNExponent()
+ {
+ Assert.assertEquals(128, Binary32.unpackGetExponentUnbiased(Float.NaN));
+ }
+
+ @SuppressWarnings("static-method") @Test public void testNaNSignificand()
+ {
+ Assert.assertTrue(Binary32.unpackGetSignificand(Float.NaN) > 0);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary64NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary64NOUI.java
new file mode 100644
index 000000000..f16ea2bee
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary64NOUI.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.math;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.jogamp.opengl.math.Binary64;
+
+public class TestBinary64NOUI
+{
+ @SuppressWarnings("static-method") @Test public void testInfinityExponent()
+ {
+ Assert.assertEquals(
+ 1024,
+ Binary64.unpackGetExponentUnbiased(Double.POSITIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinityNegativeExponent()
+ {
+ Assert.assertEquals(
+ 1024,
+ Binary64.unpackGetExponentUnbiased(Double.NEGATIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinityNegativeSign()
+ {
+ Assert.assertEquals(1, Binary64.unpackGetSign(Double.NEGATIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinityNegativeSignificand()
+ {
+ Assert.assertEquals(
+ 0,
+ Binary64.unpackGetSignificand(Double.NEGATIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public void testInfinitySign()
+ {
+ Assert.assertEquals(0, Binary64.unpackGetSign(Double.POSITIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public
+ void
+ testInfinitySignificand()
+ {
+ Assert.assertEquals(
+ 0,
+ Binary64.unpackGetSignificand(Double.POSITIVE_INFINITY));
+ }
+
+ @SuppressWarnings("static-method") @Test public void testNaNExponent()
+ {
+ Assert.assertEquals(1024, Binary64.unpackGetExponentUnbiased(Double.NaN));
+ }
+
+ @SuppressWarnings("static-method") @Test public void testNaNSignificand()
+ {
+ Assert.assertTrue(Binary64.unpackGetSignificand(Double.NaN) > 0);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil01NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil01NOUI.java
new file mode 100644
index 000000000..0d156c42c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil01NOUI.java
@@ -0,0 +1,282 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.math;
+
+
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.math.FloatUtil;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestFloatUtil01NOUI {
+ static final float MACH_EPSILON = FloatUtil.getMachineEpsilon();
+
+ static boolean deltaMachEpsLEQEpsilon;
+ static boolean deltaFixedEpsLEQEpsilon;
+
+ @BeforeClass
+ public static void test00Epsilon() {
+ System.err.println();
+ System.err.println("Machine Epsilon: "+MACH_EPSILON);
+ System.err.println("Fixed Epsilon: "+FloatUtil.EPSILON+", diff "+Math.abs(MACH_EPSILON-FloatUtil.EPSILON));
+ System.err.println("Float MIN: "+Float.MIN_VALUE);
+
+ final float deltaMachEpsMin = Math.abs(MACH_EPSILON-Float.MIN_VALUE);
+ deltaMachEpsLEQEpsilon = FloatUtil.compare(deltaMachEpsMin, MACH_EPSILON) <= 0;
+
+ final float deltaFixedEpsMin = Math.abs(MACH_EPSILON-Float.MIN_VALUE);
+ deltaFixedEpsLEQEpsilon = FloatUtil.compare(deltaFixedEpsMin, MACH_EPSILON) <= 0;
+
+ System.err.println("deltaMachEpsMin "+deltaMachEpsMin+", deltaMachEpsLEQEpsilon "+deltaMachEpsLEQEpsilon);
+ System.err.println("deltaFixedEpsMin "+deltaFixedEpsMin+", deltaFixedEpsLEQEpsilon "+deltaFixedEpsLEQEpsilon);
+ }
+
+ private void dumpTestWE(final int tstNum, final int expWE, final float a, final float b, final float EPSILON) {
+ final float delta = a-b;
+ final boolean equalWE = FloatUtil.isEqual(a, b, EPSILON);
+ final int compWE = FloatUtil.compare(a, b, EPSILON);
+ final String msgWE = ( expWE != compWE ) ? "**** mismatch ****" : " OK";
+ System.err.println("Print.WE."+tstNum+": a: "+a+", b: "+b+" -> d "+delta+", exp "+expWE+", equal "+equalWE+", comp "+compWE+" - "+msgWE+", epsilon "+EPSILON);
+ }
+ private void dumpTestNE(final int tstNum, final int exp, final float a, final float b) {
+ final float delta = a-b;
+ final boolean equal = FloatUtil.isEqual(a, b);
+ final int comp = FloatUtil.compare(a, b);
+ final String msg = ( exp != comp ) ? "**** mismatch ****" : " OK";
+ System.err.println("Print.NE."+tstNum+": a: "+a+", b: "+b+" -> d "+delta+", exp "+exp+", equal "+equal+", comp "+comp+" - "+msg);
+ }
+
+ @Test
+ public void test01aZeroWithFixedEpsilon() {
+ testZeroWithEpsilon(10, FloatUtil.EPSILON);
+ }
+ @Test
+ public void test01bZeroWithMachEpsilon() {
+ testZeroWithEpsilon(100, MACH_EPSILON);
+ }
+ private void testZeroWithEpsilon(int i, final float EPSILON) {
+ System.err.println();
+ testZeroWithEpsilon(i++, true, 0f, EPSILON);
+ testZeroWithEpsilon(i++, true, 0f-EPSILON/2f, EPSILON);
+ testZeroWithEpsilon(i++, true, 0f+EPSILON/2f, EPSILON);
+ testZeroWithEpsilon(i++, true, 0f-Float.MIN_VALUE, EPSILON);
+ testZeroWithEpsilon(i++, true, 0f+Float.MIN_VALUE, EPSILON);
+ testZeroWithEpsilon(i++, true, -0f, EPSILON);
+ testZeroWithEpsilon(i++, true, +0f, EPSILON);
+
+ testZeroWithEpsilon(i++, false, 0f+EPSILON+Float.MIN_VALUE, EPSILON);
+ testZeroWithEpsilon(i++, false, 0f-EPSILON-Float.MIN_VALUE, EPSILON);
+
+ // Unpredicted .. accuracy beyond epsilon, or deltaMachEpsLEQEpsilon or deltaFixedEpsLEQEpsilon;
+ dumpTestWE(i++, 1, 0f, 0f+EPSILON-Float.MIN_VALUE, EPSILON);
+ dumpTestWE(i++, 1, 0f, 0f-EPSILON+Float.MIN_VALUE, EPSILON);
+ }
+ private void testZeroWithEpsilon(final int tstNum, final boolean exp, final float a, final float EPSILON) {
+ final boolean zero = FloatUtil.isZero(a, EPSILON);
+ final float delta = a-0f;
+ System.err.println("Zero."+tstNum+": a: "+a+", -> d "+delta+", exp "+exp+", zero "+zero+", epsilon "+EPSILON);
+ Assert.assertEquals("Zero failed a: "+a+" within "+EPSILON, exp, zero);
+ }
+
+ @Test
+ public void test02EqualsNoEpsilon() {
+ int i=0;
+ System.err.println();
+ testEqualsNoEpsilon(i++, true, 0f, 0f);
+
+ testEqualsNoEpsilon(i++, true, Float.MAX_VALUE, Float.MAX_VALUE);
+ testEqualsNoEpsilon(i++, true, Float.MIN_VALUE, Float.MIN_VALUE);
+ testEqualsNoEpsilon(i++, true, Float.MIN_NORMAL, Float.MIN_NORMAL);
+ testEqualsNoEpsilon(i++, true, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
+ testEqualsNoEpsilon(i++, true, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
+ testEqualsNoEpsilon(i++, true, Float.NaN, Float.NaN);
+ testEqualsNoEpsilon(i++, false, -0f, 0f);
+ testEqualsNoEpsilon(i++, false, 0f, -0f);
+
+ // Unpredicted .. accuracy beyond epsilon, or deltaMachEpsLEQEpsilon or deltaFixedEpsLEQEpsilon;
+ dumpTestNE(i++, 0, 1f, 1f-MACH_EPSILON/2f);
+ dumpTestNE(i++, 0, 0f, 0f-MACH_EPSILON/2f);
+ dumpTestNE(i++, 0, 1f, 1f+MACH_EPSILON/2f);
+ dumpTestNE(i++, 0, 0f, 0f+MACH_EPSILON/2f);
+ dumpTestNE(i++, 0, 1f, 1f-Float.MIN_VALUE);
+ dumpTestNE(i++, 0, 0f, 0f-Float.MIN_VALUE);
+ dumpTestNE(i++, 0, 1f, 1f+Float.MIN_VALUE);
+ dumpTestNE(i++, 0, 0f, 0f+Float.MIN_VALUE);
+ }
+ private void testEqualsNoEpsilon(final int tstNum, final boolean exp, final float a, final float b) {
+ final boolean equal = FloatUtil.isEqual(a, b);
+ final int comp = FloatUtil.compare(a, b);
+ final float delta = a-b;
+ System.err.println("Equal.NE."+tstNum+": a: "+a+", b: "+b+" -> d "+delta+", exp "+exp+", equal "+equal+", comp "+comp);
+ Assert.assertEquals("Compare failed a: "+a+", b: "+b, exp, 0==comp);
+ Assert.assertEquals("Equal failed a: "+a+", b: "+b, exp, equal);
+ }
+
+ @Test
+ public void test03aEqualsWithFixedEpsilon() {
+ testEqualsWithEpsilon(10, FloatUtil.EPSILON);
+ }
+ @Test
+ public void test03bEqualsWithMachEpsilon() {
+ testEqualsWithEpsilon(50, MACH_EPSILON);
+ }
+ private void testEqualsWithEpsilon(int i, final float EPSILON) {
+ System.err.println();
+ testEqualsWithEpsilon(i++, true, 0f, 0f, EPSILON);
+ testEqualsWithEpsilon(i++, true, 1f, 1f-EPSILON/2f, EPSILON);
+ testEqualsWithEpsilon(i++, true, 1f, 1f+EPSILON/2f, EPSILON);
+ testEqualsWithEpsilon(i++, true, 1f, 1f-Float.MIN_VALUE, EPSILON);
+ testEqualsWithEpsilon(i++, true, 1f, 1f+Float.MIN_VALUE, EPSILON);
+ testEqualsWithEpsilon(i++, true, Float.MAX_VALUE, Float.MAX_VALUE, EPSILON);
+ testEqualsWithEpsilon(i++, true, Float.MIN_VALUE, Float.MIN_VALUE, EPSILON);
+ testEqualsWithEpsilon(i++, true, Float.MIN_NORMAL, Float.MIN_NORMAL, EPSILON);
+ testEqualsWithEpsilon(i++, true, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, EPSILON);
+ testEqualsWithEpsilon(i++, true, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, EPSILON);
+ testEqualsWithEpsilon(i++, true, Float.NaN, Float.NaN, EPSILON);
+ testEqualsWithEpsilon(i++, true, -0f, 0f, EPSILON);
+ testEqualsWithEpsilon(i++, true, 0f, -0f, EPSILON);
+
+ testEqualsWithEpsilon(i++, false, 1f, 1f+EPSILON+Float.MIN_VALUE, EPSILON);
+ testEqualsWithEpsilon(i++, false, 1f, 1f-EPSILON-Float.MIN_VALUE, EPSILON);
+
+ // Unpredicted .. accuracy beyond epsilon, or deltaMachEpsLEQEpsilon or deltaFixedEpsLEQEpsilon;
+ dumpTestWE(i++, 1, 1f, 1f+EPSILON-Float.MIN_VALUE, EPSILON);
+ dumpTestWE(i++, 1, 1f, 1f-EPSILON+Float.MIN_VALUE, EPSILON);
+ }
+ private void testEqualsWithEpsilon(final int tstNum, final boolean exp, final float a, final float b, final float EPSILON) {
+ final boolean equal = FloatUtil.isEqual(a, b, EPSILON);
+ final int comp = FloatUtil.compare(a, b, EPSILON);
+ final float delta = a-b;
+ System.err.println("Equal.WE."+tstNum+": a: "+a+", b: "+b+" -> d "+delta+", exp "+exp+", equal "+equal+", comp "+comp);
+ Assert.assertEquals("Compare failed a: "+a+", b: "+b+" within "+EPSILON, exp, 0==comp);
+ Assert.assertEquals("Equal failed a: "+a+", b: "+b+" within "+EPSILON, exp, equal);
+ }
+
+ @Test
+ public void test04CompareNoEpsilon() {
+ int i=0;
+ System.err.println();
+ testCompareNoEpsilon(i++, 0, 0f, 0f);
+ testCompareNoEpsilon(i++, 0, Float.MAX_VALUE, Float.MAX_VALUE);
+ testCompareNoEpsilon(i++, 0, Float.MIN_VALUE, Float.MIN_VALUE);
+ testCompareNoEpsilon(i++, 0, Float.MIN_NORMAL, Float.MIN_NORMAL);
+ testCompareNoEpsilon(i++, 0, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
+ testCompareNoEpsilon(i++, 0, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
+ testCompareNoEpsilon(i++, 0, Float.NaN, Float.NaN);
+
+ testCompareNoEpsilon(i++, 1, 1f, 0f);
+ testCompareNoEpsilon(i++, -1, 0f, 1f);
+ testCompareNoEpsilon(i++, 1, 0f, -1f);
+ testCompareNoEpsilon(i++, -1, -1f, 0f);
+
+ testCompareNoEpsilon(i++, 1, Float.MAX_VALUE, Float.MIN_VALUE);
+ testCompareNoEpsilon(i++, -1, Float.MIN_VALUE, Float.MAX_VALUE);
+ testCompareNoEpsilon(i++, 1, Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY);
+ testCompareNoEpsilon(i++, -1, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
+
+ testCompareNoEpsilon(i++, -1, 0f, Float.NaN);
+ testCompareNoEpsilon(i++, 1, Float.NaN, 0f);
+
+ testCompareNoEpsilon(i++, -1, -0f, 0f);
+ testCompareNoEpsilon(i++, 1, 0f, -0f);
+
+ // Unpredicted .. accuracy beyond epsilon, or deltaMachEpsLEQEpsilon or deltaFixedEpsLEQEpsilon;
+ dumpTestNE(i++, 0, 1f, 1f-MACH_EPSILON/2f);
+ dumpTestNE(i++, 0, 0f, 0f-MACH_EPSILON/2f);
+ dumpTestNE(i++, 0, 1f, 1f+MACH_EPSILON/2f);
+ dumpTestNE(i++, 0, 0f, 0f+MACH_EPSILON/2f);
+ dumpTestNE(i++, 0, 1f, 1f-Float.MIN_VALUE);
+ dumpTestNE(i++, 0, 0f, 0f-Float.MIN_VALUE);
+ dumpTestNE(i++, 0, 1f, 1f+Float.MIN_VALUE);
+ dumpTestNE(i++, 0, 0f, 0f+Float.MIN_VALUE);
+ }
+ private void testCompareNoEpsilon(final int tstNum, final int exp, final float a, final float b) {
+ final boolean equal = FloatUtil.isEqual(a, b);
+ final int comp = FloatUtil.compare(a, b);
+ final float delta = a-b;
+ System.err.println("Comp.NE."+tstNum+": a: "+a+", b: "+b+" -> d "+delta+", equal "+equal+", comp: exp "+exp+" has "+comp);
+ Assert.assertEquals("Compare failed a: "+a+", b: "+b, exp, comp);
+ }
+
+ @Test
+ public void test05aCompareWithFixedEpsilon() {
+ test05CompareWithEpsilon(10, FloatUtil.EPSILON);
+ }
+ @Test
+ public void test05bCompareWithMachEpsilon() {
+ test05CompareWithEpsilon(50, MACH_EPSILON);
+ }
+ private void test05CompareWithEpsilon(int i, final float EPSILON) {
+ System.err.println();
+ testCompareWithEpsilon(i++, 0, 0f, 0f, EPSILON);
+ testCompareWithEpsilon(i++, 0, 1f, 1f-EPSILON/2f, EPSILON);
+ testCompareWithEpsilon(i++, 0, 1f, 1f+EPSILON/2f, EPSILON);
+ testCompareWithEpsilon(i++, 0, 1f, 1f-Float.MIN_VALUE, EPSILON);
+ testCompareWithEpsilon(i++, 0, 1f, 1f+Float.MIN_VALUE, EPSILON);
+ testCompareWithEpsilon(i++, 0, Float.MAX_VALUE, Float.MAX_VALUE, EPSILON);
+ testCompareWithEpsilon(i++, 0, Float.MIN_VALUE, Float.MIN_VALUE, EPSILON);
+ testCompareWithEpsilon(i++, 0, Float.MIN_NORMAL, Float.MIN_NORMAL, EPSILON);
+ testCompareWithEpsilon(i++, 0, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, EPSILON);
+ testCompareWithEpsilon(i++, 0, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, EPSILON);
+ testCompareWithEpsilon(i++, 0, Float.NaN, Float.NaN, EPSILON);
+
+ testCompareWithEpsilon(i++, 1, 1f, 0f, EPSILON);
+ testCompareWithEpsilon(i++, -1, 0f, 1f, EPSILON);
+ testCompareWithEpsilon(i++, 1, 0f, -1f, EPSILON);
+ testCompareWithEpsilon(i++, -1, -1f, 0f, EPSILON);
+
+ testCompareWithEpsilon(i++, 1, Float.MAX_VALUE, Float.MIN_VALUE, EPSILON);
+ testCompareWithEpsilon(i++, -1, Float.MIN_VALUE, Float.MAX_VALUE, EPSILON);
+ testCompareWithEpsilon(i++, 1, Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, EPSILON);
+ testCompareWithEpsilon(i++, -1, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, EPSILON);
+
+ testCompareWithEpsilon(i++, -1, 0f,Float.NaN, EPSILON);
+ testCompareWithEpsilon(i++, 1, Float.NaN, 0f, EPSILON);
+
+ testCompareWithEpsilon(i++, 0, -0f, 0f, EPSILON);
+ testCompareWithEpsilon(i++, 0, 0f, -0f, EPSILON);
+ }
+ private void testCompareWithEpsilon(final int tstNum, final int exp, final float a, final float b, final float EPSILON) {
+ final boolean equal = FloatUtil.isEqual(a, b, EPSILON);
+ final int comp = FloatUtil.compare(a, b, EPSILON);
+ final float delta = a-b;
+ System.err.println("Comp.WE."+tstNum+": a: "+a+", b: "+b+" -> d "+delta+", equal "+equal+", comp: exp "+exp+" has "+comp);
+ Assert.assertEquals("Compare failed a: "+a+", b: "+b+" within "+EPSILON, exp, comp);
+ }
+
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestFloatUtil01NOUI.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFloatUtil01MatrixMatrixMultNOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil02MatrixMatrixMultNOUI.java
index 42b5972bb..13285ac0b 100755..100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFloatUtil01MatrixMatrixMultNOUI.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil02MatrixMatrixMultNOUI.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,20 +20,23 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.jogl.acore;
+
+package com.jogamp.opengl.test.junit.jogl.math;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
-import com.jogamp.opengl.FloatUtil;
+import com.jogamp.opengl.math.FloatUtil;
-public class TestFloatUtil01MatrixMatrixMultNOUI {
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestFloatUtil02MatrixMatrixMultNOUI {
final float[] m1 = new float[]{ 1, 3, 4, 0,
6, 7, 8, 5,
@@ -45,7 +48,7 @@ public class TestFloatUtil01MatrixMatrixMultNOUI {
4, 8, 6, 2,
0, 5, 9, 5 };
- final float[] m1xm2_RM = // m2xm1_CM
+ final float[] m1xm2_RM = // m2xm1_CM
new float[]{ 26, 59, 143, 71,
59, 174, 730, 386,
143, 730, 9770, 5370,
@@ -56,8 +59,8 @@ public class TestFloatUtil01MatrixMatrixMultNOUI {
893, 116, 116, 113,
748, 116, 120, 104,
1182, 113, 104, 131 };
-
- public static final void multMatrixf_RM(final float[] a, int a_off, final float[] b, int b_off, float[] d, int d_off) {
+
+ public static final void multMatrixf_RM(final float[] a, final int a_off, final float[] b, final int b_off, final float[] d, final int d_off) {
for (int i = 0; i < 4; i++) {
final float ai0=a[a_off+i*4+0], ai1=a[a_off+i*4+1], ai2=a[a_off+i*4+2], ai3=a[a_off+i*4+3];
d[d_off+i*4+0] = ai0 * b[b_off+0*4+0] + ai1 * b[b_off+1*4+0] + ai2 * b[b_off+2*4+0] + ai3 * b[b_off+3*4+0] ;
@@ -69,45 +72,45 @@ public class TestFloatUtil01MatrixMatrixMultNOUI {
@Test
public void testCM_m1xm2(){
-
- float[] r = new float[16];
-
- FloatUtil.multMatrixf(m1, 0, m2, 0, r, 0);
+
+ final float[] r = new float[16];
+
+ FloatUtil.multMatrix(m1, 0, m2, 0, r, 0);
Assert.assertArrayEquals(m2xm1_RM, r, 0f);
}
-
+
@Test
public void testCM_m2xm1(){
-
- float[] r = new float[16];
-
- FloatUtil.multMatrixf(m2, 0, m1, 0, r, 0);
+
+ final float[] r = new float[16];
+
+ FloatUtil.multMatrix(m2, 0, m1, 0, r, 0);
Assert.assertArrayEquals(m1xm2_RM, r, 0f);
}
@Test
public void testRM_m1xm2(){
-
- float[] r = new float[16];
-
+
+ final float[] r = new float[16];
+
multMatrixf_RM(m1, 0, m2, 0, r, 0);
Assert.assertArrayEquals(m1xm2_RM, r, 0f);
}
-
+
@Test
public void testRM_m2xm1(){
-
- float[] r = new float[16];
-
+
+ final float[] r = new float[16];
+
multMatrixf_RM(m2, 0, m1, 0, r, 0);
Assert.assertArrayEquals(m2xm1_RM, r, 0f);
}
-
- public static void main(String args[]) {
- org.junit.runner.JUnitCore.main(TestFloatUtil01MatrixMatrixMultNOUI.class.getName());
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestFloatUtil02MatrixMatrixMultNOUI.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil03InversionNOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil03InversionNOUI.java
new file mode 100644
index 000000000..a2aa69863
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil03InversionNOUI.java
@@ -0,0 +1,262 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.math;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.math.FloatUtil;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestFloatUtil03InversionNOUI {
+
+ @Test
+ public void test01Ident(){
+ final float[] res1 = new float[16];
+ final float[] res2 = new float[16];
+ final float[] temp = new float[16];
+
+ final float[] identity = new float[] { 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1 };
+
+ FloatUtil.invertMatrix(identity, 0, res1, 0);
+ System.err.println(FloatUtil.matrixToString(null, "inv-1: ", "%10.7f", res1, 0, 4, 4, false /* rowMajorOrder */));
+ invertMatrix(identity, 0, res2, 0, temp);
+ System.err.println(FloatUtil.matrixToString(null, "inv-2: ", "%10.7f", res2, 0, 4, 4, false /* rowMajorOrder */));
+
+ Assert.assertArrayEquals("I1/I2 failure", res1, res2, FloatUtil.INV_DEVIANCE);
+ Assert.assertArrayEquals("I2 failure", identity, res2, FloatUtil.INV_DEVIANCE);
+ Assert.assertArrayEquals("I1 failure", identity, res1, FloatUtil.INV_DEVIANCE);
+ }
+
+ private void testImpl(final float[] matrix) {
+ final float[] inv1_0 = new float[16];
+ final float[] inv1_1 = new float[16];
+ final float[] inv1_2 = new float[16];
+ final float[] inv2_0 = new float[16];
+ final float[] inv2_1 = new float[16];
+ final float[] inv2_2 = new float[16];
+ final float[] temp = new float[16];
+
+ System.err.println(FloatUtil.matrixToString(null, "orig : ", "%10.7f", matrix, 0, 4, 4, false /* rowMajorOrder */));
+ invertMatrix(matrix, 0, inv1_0, 0, temp);
+ invertMatrix(inv1_0, 0, inv2_0, 0, temp);
+ System.err.println(FloatUtil.matrixToString(null, "inv1_0: ", "%10.7f", inv1_0, 0, 4, 4, false /* rowMajorOrder */));
+ System.err.println(FloatUtil.matrixToString(null, "inv2_0: ", "%10.7f", inv2_0, 0, 4, 4, false /* rowMajorOrder */));
+ FloatUtil.invertMatrix(matrix, 0, inv1_1, 0);
+ FloatUtil.invertMatrix(inv1_1, 0, inv2_1, 0);
+ System.err.println(FloatUtil.matrixToString(null, "inv1_1: ", "%10.7f", inv1_1, 0, 4, 4, false /* rowMajorOrder */));
+ System.err.println(FloatUtil.matrixToString(null, "inv2_1: ", "%10.7f", inv2_1, 0, 4, 4, false /* rowMajorOrder */));
+ FloatUtil.invertMatrix(matrix, inv1_2);
+ FloatUtil.invertMatrix(inv1_2, inv2_2);
+ System.err.println(FloatUtil.matrixToString(null, "inv1_2: ", "%10.7f", inv1_2, 0, 4, 4, false /* rowMajorOrder */));
+ System.err.println(FloatUtil.matrixToString(null, "inv2_2: ", "%10.7f", inv2_2, 0, 4, 4, false /* rowMajorOrder */));
+
+ Assert.assertArrayEquals("I1_1/I1_2 failure", inv1_1, inv1_2, FloatUtil.INV_DEVIANCE);
+ Assert.assertArrayEquals("I2_1/I2_2 failure", inv2_1, inv2_2, FloatUtil.INV_DEVIANCE);
+
+ Assert.assertArrayEquals("I1_0/I1_1 failure", inv1_0, inv1_2, FloatUtil.INV_DEVIANCE);
+ Assert.assertArrayEquals("I2_0/I2_1 failure", inv2_0, inv2_2, FloatUtil.INV_DEVIANCE);
+
+ Assert.assertArrayEquals("I1 failure", matrix, inv2_0, FloatUtil.INV_DEVIANCE);
+ Assert.assertArrayEquals("I2 failure", matrix, inv2_2, FloatUtil.INV_DEVIANCE);
+ Assert.assertArrayEquals("I2 failure", matrix, inv2_1, FloatUtil.INV_DEVIANCE);
+ }
+
+ @Test
+ public void test02(){
+ final float[] p = new float[] { 2.3464675f, 0, 0, 0,
+ 0, 2.4142134f, 0, 0,
+ 0, 0, -1.0002f, -1,
+ 0, 0, -20.002f, 0 };
+ testImpl(p);
+ }
+
+ @Test
+ public void test03(){
+ final float[] mv = new float[] { 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, -200, 1 } ;
+ testImpl(mv);
+ }
+
+ @Test
+ public void test04(){
+ final float[] p = new float[] { 2.3464675f, 0, 0, 0,
+ 0, 2.4142134f, 0, 0,
+ 0, 0, -1.0002f, -1,
+ 0, 0, -20.002f, 0 };
+
+ testImpl(p);
+ }
+
+ @Test
+ public void test05Perf(){
+ final float[] p1 = new float[] { 2.3464675f, 0, 0, 0,
+ 0, 2.4142134f, 0, 0,
+ 0, 0, -1.0002f, -1,
+ 0, 0, -20.002f, 0 };
+
+ final float[] p2 = new float[]{ 26, 59, 143, 71,
+ 59, 174, 730, 386,
+ 143, 730, 9770, 5370,
+ 71, 386, 5370, 2954 };
+
+ final float[] res1 = new float[16];
+ final float[] res2 = new float[16];
+ final float[] temp = new float[16];
+
+ final int loops = 1000000;
+ long tI0 = 0;
+ long tI1 = 0;
+ long tI2 = 0;
+
+ // warm-up
+ for(int i=0; i<10; i++) {
+ invertMatrix(p1, 0, res2, 0, temp);
+ FloatUtil.invertMatrix(p1, 0, res1, 0);
+ FloatUtil.invertMatrix(p1, res1);
+
+ invertMatrix(p2, 0, res2, 0, temp);
+ FloatUtil.invertMatrix(p2, 0, res1, 0);
+ FloatUtil.invertMatrix(p2, res1);
+ }
+
+
+ for(int i=0; i<loops; i++) {
+
+ final long t_0 = Platform.currentTimeMillis();
+
+ invertMatrix(p1, 0, res2, 0, temp);
+ final long t_1 = Platform.currentTimeMillis();
+ tI0 += t_1 - t_0;
+
+ FloatUtil.invertMatrix(p1, 0, res1, 0);
+ final long t_2 = Platform.currentTimeMillis();
+ tI1 += t_2 - t_1;
+
+ FloatUtil.invertMatrix(p1, res1);
+ final long t_3 = Platform.currentTimeMillis();
+ tI2 += t_3 - t_2;
+
+ invertMatrix(p2, 0, res2, 0, temp);
+ final long t_4 = Platform.currentTimeMillis();
+ tI0 += t_4 - t_3;
+
+ FloatUtil.invertMatrix(p2, 0, res1, 0);
+ final long t_5 = Platform.currentTimeMillis();
+ tI1 += t_5 - t_4;
+
+ FloatUtil.invertMatrix(p2, res2);
+ final long t_6 = Platform.currentTimeMillis();
+ tI2 += t_6 - t_5;
+ }
+ System.err.printf("Summary loops %6d: I1 %6d ms total, %f ms/inv%n", loops, tI0, (double)tI0/loops);
+ System.err.printf("Summary loops %6d: I2 %6d ms total, %f ms/inv%n", loops, tI1, (double)tI1/loops);
+ System.err.printf("Summary loops %6d: I3 %6d ms total, %f ms/inv%n", loops, tI2, (double)tI2/loops);
+
+ }
+
+ public static float[] invertMatrix(final float[] msrc, final int msrc_offset, final float[] mres, final int mres_offset, final float[/*4*4*/] temp) {
+ int i, j, k, swap;
+ float t;
+ for (i = 0; i < 4; i++) {
+ final int i4 = i*4;
+ for (j = 0; j < 4; j++) {
+ temp[i4+j] = msrc[i4+j+msrc_offset];
+ }
+ }
+ FloatUtil.makeIdentity(mres, mres_offset);
+
+ for (i = 0; i < 4; i++) {
+ final int i4 = i*4;
+
+ //
+ // Look for largest element in column
+ //
+ swap = i;
+ for (j = i + 1; j < 4; j++) {
+ if (Math.abs(temp[j*4+i]) > Math.abs(temp[i4+i])) {
+ swap = j;
+ }
+ }
+
+ if (swap != i) {
+ final int swap4 = swap*4;
+ //
+ // Swap rows.
+ //
+ for (k = 0; k < 4; k++) {
+ t = temp[i4+k];
+ temp[i4+k] = temp[swap4+k];
+ temp[swap4+k] = t;
+
+ t = mres[i4+k+mres_offset];
+ mres[i4+k+mres_offset] = mres[swap4+k+mres_offset];
+ mres[swap4+k+mres_offset] = t;
+ }
+ }
+
+ if (temp[i4+i] == 0) {
+ //
+ // No non-zero pivot. The matrix is singular, which shouldn't
+ // happen. This means the user gave us a bad matrix.
+ //
+ return null;
+ }
+
+ t = temp[i4+i];
+ for (k = 0; k < 4; k++) {
+ temp[i4+k] /= t;
+ mres[i4+k+mres_offset] /= t;
+ }
+ for (j = 0; j < 4; j++) {
+ if (j != i) {
+ final int j4 = j*4;
+ t = temp[j4+i];
+ for (k = 0; k < 4; k++) {
+ temp[j4+k] -= temp[i4+k] * t;
+ mres[j4+k+mres_offset] -= mres[i4+k+mres_offset]*t;
+ }
+ }
+ }
+ }
+ return mres;
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestFloatUtil03InversionNOUI.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectDoubleNOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectDoubleNOUI.java
index 34b30f04e..d10a04845 100755..100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectDoubleNOUI.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectDoubleNOUI.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,22 +20,25 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.jogl.glu;
+
+package com.jogamp.opengl.test.junit.jogl.math;
import javax.media.opengl.glu.GLU;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/**
* @author Julien Gouesse
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGluUnprojectDoubleNOUI {
@Test
@@ -48,10 +51,10 @@ public class TestGluUnprojectDoubleNOUI {
final int[] viewport = new int[]{0,0,800,600};
final double[] objCoords = new double[]{Double.NaN,Double.NaN,Double.NaN};
glu.gluUnProject(pickedPoint[0], pickedPoint[1], pickedPointDepth, sceneModelViewValues, 0, projectionValues, 0, viewport, 0, objCoords, 0);
- Assert.assertTrue(!Double.isNaN(objCoords[0])&&!Double.isNaN(objCoords[1])&&!Double.isNaN(objCoords[2]));
+ Assert.assertTrue(!Double.isNaN(objCoords[0])&&!Double.isNaN(objCoords[1])&&!Double.isNaN(objCoords[2]));
}
-
- public static void main(String args[]) {
+
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestGluUnprojectDoubleNOUI.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectFloatNOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectFloatNOUI.java
index 717d5e4b8..278c2450a 100755..100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectFloatNOUI.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectFloatNOUI.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,21 +20,24 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.jogl.glu;
+
+package com.jogamp.opengl.test.junit.jogl.math;
import javax.media.opengl.glu.GLU;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGluUnprojectFloatNOUI {
-
+
@Test
public void testNaN(){
final GLU glu = new GLU();
@@ -45,59 +48,59 @@ public class TestGluUnprojectFloatNOUI {
final int[] viewport = new int[]{0,0,800,600};
final float[] objCoords = new float[]{Float.NaN,Float.NaN,Float.NaN};
glu.gluUnProject(pickedPoint[0], pickedPoint[1], pickedPointDepth, sceneModelViewValues, 0, projectionValues, 0, viewport, 0, objCoords, 0);
- Assert.assertTrue(!Double.isNaN(objCoords[0])&&!Double.isNaN(objCoords[1])&&!Double.isNaN(objCoords[2]));
+ Assert.assertTrue(!Double.isNaN(objCoords[0])&&!Double.isNaN(objCoords[1])&&!Double.isNaN(objCoords[2]));
}
-
+
@Test
public void test01(){
- float[] mv = new float[] { 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
+ final float[] mv = new float[] { 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
0, 0, 0, 1 };
-
- float[] p = new float[] { 2.3464675f, 0, 0, 0,
- 0, 2.4142134f, 0, 0,
- 0, 0, -1.0002f, -1,
+
+ final float[] p = new float[] { 2.3464675f, 0, 0, 0,
+ 0, 2.4142134f, 0, 0,
+ 0, 0, -1.0002f, -1,
0, 0, -20.002f, 0 };
-
- int[] v = new int[] { 0, 0, 1000, 1000 };
-
- float[] s = new float[] { 250, 250, 0.5f };
-
- float[] expected = new float[] { -4.2612f, -4.1417f, -19.9980f };
- float[] result = new float[] { 0, 0, 0 };
-
+
+ final int[] v = new int[] { 0, 0, 1000, 1000 };
+
+ final float[] s = new float[] { 250, 250, 0.5f };
+
+ final float[] expected = new float[] { -4.2612f, -4.1417f, -19.9980f };
+ final float[] result = new float[] { 0, 0, 0 };
+
final GLU glu = new GLU();
glu.gluUnProject(s[0], s[1], s[2], mv, 0, p, 0, v, 0, result, 0);
-
+
Assert.assertArrayEquals(expected, result, 0.0001f);
}
@Test
public void test02(){
- float[] mv = new float[] { 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
+ final float[] mv = new float[] { 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
0, 0, -200, 1 } ;
-
- float[] p = new float[] { 2.3464675f, 0, 0, 0,
- 0, 2.4142134f, 0, 0,
- 0, 0, -1.0002f, -1,
+
+ final float[] p = new float[] { 2.3464675f, 0, 0, 0,
+ 0, 2.4142134f, 0, 0,
+ 0, 0, -1.0002f, -1,
0, 0, -20.002f, 0 };
-
- int[] v = new int[] { 0, 0, 1000, 1000 };
-
- float[] s = new float[] { 250, 250, 0.5f };
- float[] expected = new float[] { -4.2612f, -4.1417f, 180.002f };
- float[] result = new float[] { 0, 0, 0 };
-
+
+ final int[] v = new int[] { 0, 0, 1000, 1000 };
+
+ final float[] s = new float[] { 250, 250, 0.5f };
+ final float[] expected = new float[] { -4.2612f, -4.1417f, 180.002f };
+ final float[] result = new float[] { 0, 0, 0 };
+
final GLU glu = new GLU();
glu.gluUnProject(s[0], s[1], s[2], mv, 0, p, 0, v, 0, result, 0);
-
+
Assert.assertArrayEquals(expected, result, 0.0001f);
}
-
- public static void main(String args[]) {
+
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestGluUnprojectFloatNOUI.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java
new file mode 100644
index 000000000..8c2216f7a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java
@@ -0,0 +1,473 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.math;
+
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import jogamp.common.os.PlatformPropsImpl;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.geom.Frustum;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.PMVMatrix;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPMVMatrix01NEWT extends UITestCase {
+
+ static final float epsilon = 0.00001f;
+
+ // matrix 2 rows x 3 columns - In row major order
+ static FloatBuffer matrix2x3R = FloatBuffer.wrap( new float[] { 1.0f, 2.0f, 3.0f,
+ 4.0f, 5.0f, 6.0f } );
+
+ // matrix 2 rows x 3 columns - In column major order
+ static FloatBuffer matrix2x3C = FloatBuffer.wrap( new float[] { 1.0f, 4.0f,
+ 2.0f, 5.0f,
+ 3.0f, 6.0f } );
+
+ // matrix 3 rows x 2 columns - In row major order
+ static FloatBuffer matrix3x2R = FloatBuffer.wrap( new float[] { 1.0f, 2.0f,
+ 3.0f, 4.0f,
+ 5.0f, 6.0f } );
+
+ // matrix 3 rows x 2 columns - In column major order
+ static FloatBuffer matrix3x2C = FloatBuffer.wrap( new float[] { 1.0f, 3.0f, 5.0f,
+ 2.0f, 4.0f, 6.0f } );
+
+ // Translated xyz 123 - Row - In row major order !
+ static FloatBuffer translated123R = FloatBuffer.wrap( new float[] { 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f, 2.0f,
+ 0.0f, 0.0f, 1.0f, 3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f } );
+
+ // Translated xyz 123 - Column - In column major order !
+ static FloatBuffer translated123C = FloatBuffer.wrap( new float[] { 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 1.0f, 2.0f, 3.0f, 1.0f } );
+
+ // Translated xyz 123 - Inverse - In column major order !
+ static FloatBuffer translated123I = FloatBuffer.wrap( new float[] { 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ -1.0f, -2.0f, -3.0f, 1.0f } );
+
+ // Translated xyz 123 - Inverse and Transposed - In column major order !
+ static FloatBuffer translated123IT = FloatBuffer.wrap( new float[] { 1.0f, 0.0f, 0.0f, -1.0f,
+ 0.0f, 1.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, 1.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f } );
+
+ @Test
+ public void test00MatrixToString() {
+ final String s4x4Cpmv = PMVMatrix.matrixToString(null, "%10.5f", translated123C).toString();
+ final String s4x4Cflu = FloatUtil.matrixToString(null, null, "%10.5f", translated123C, 0, 4, 4, false).toString();
+ final String s4x4Rflu = FloatUtil.matrixToString(null, null, "%10.5f", translated123R, 0, 4, 4, true).toString();
+ System.err.println("PMV-C-O 4x4: ");
+ System.err.println(s4x4Cpmv);
+ System.err.println();
+ System.err.println("FLU-C-O 4x4: ");
+ System.err.println(s4x4Cflu);
+ System.err.println();
+ System.err.println("FLU-R-O 4x4: ");
+ System.err.println(s4x4Rflu);
+ System.err.println();
+ Assert.assertEquals(s4x4Cpmv, s4x4Cflu);
+ Assert.assertEquals(s4x4Cflu, s4x4Rflu);
+
+ final String s2x3Rflu = FloatUtil.matrixToString(null, null, "%10.5f", matrix2x3R, 0, 2, 3, true).toString();
+ final String s2x3Cflu = FloatUtil.matrixToString(null, null, "%10.5f", matrix2x3C, 0, 2, 3, false).toString();
+ System.err.println("FLU-R-O 2x3: ");
+ System.err.println(s2x3Rflu);
+ System.err.println();
+ System.err.println("FLU-C-O 2x3: ");
+ System.err.println(s2x3Cflu);
+ System.err.println();
+ Assert.assertEquals(s2x3Cflu, s2x3Rflu);
+
+ final String s3x2Rflu = FloatUtil.matrixToString(null, null, "%10.5f", matrix3x2R, 0, 3, 2, true).toString();
+ final String s3x2Cflu = FloatUtil.matrixToString(null, null, "%10.5f", matrix3x2C, 0, 3, 2, false).toString();
+ System.err.println("FLU-R-O 3x2: ");
+ System.err.println(s3x2Rflu);
+ System.err.println();
+ System.err.println("FLU-C-O 3x2: ");
+ System.err.println(s3x2Cflu);
+ System.err.println();
+ Assert.assertEquals(s3x2Cflu, s3x2Rflu);
+ }
+
+ /**
+ * Test using traditional access workflow, i.e. 1) operation 2) get-matrix references
+ * <p>
+ * The Mvi, Mvit and Frustum dirty-bits and request-mask will be validated.
+ * </p>
+ */
+ @SuppressWarnings("deprecation")
+ @Test
+ public void test01MviUpdateTraditionalAccess() {
+ FloatBuffer p, mv, mvi, mvit;
+ Frustum frustum;
+ boolean b;
+ final PMVMatrix pmv = new PMVMatrix();
+ // System.err.println("P0: "+pmv.toString());
+
+ Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits());
+ Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+ Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask());
+
+ //
+ // Action #0
+ //
+ final FloatBuffer ident;
+ {
+ pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmv.glLoadIdentity();
+ ident = pmv.glGetPMatrixf();
+
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ }
+ Assert.assertTrue("Modified bits zero", 0 != pmv.getModifiedBits(true)); // clear & test
+ Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits());
+ Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+ Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask());
+
+ //
+ // Action #1
+ //
+ pmv.glTranslatef(1f, 2f, 3f); // all dirty !
+ Assert.assertTrue("Modified bits zero", 0 != pmv.getModifiedBits(true)); // clear & test
+ Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits());
+ Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+ Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask());
+ // System.err.println("P1: "+pmv.toString());
+
+ b = pmv.update(); // will not clean dirty bits, since no request has been made -> false
+ Assert.assertEquals("Update has been perfomed, but non requested", false, b);
+ Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits());
+ Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+ Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask());
+ // System.err.println("P2: "+pmv.toString());
+
+ //
+ // Get
+ //
+ p = pmv.glGetPMatrixf();
+ MiscUtils.assertFloatBufferEquals("P not identity, "+pmv.toString(), ident, p, epsilon);
+ mv = pmv.glGetMvMatrixf();
+ MiscUtils.assertFloatBufferEquals("Mv not translated123, "+pmv.toString(), translated123C, mv, epsilon);
+ mvi = pmv.glGetMviMatrixf();
+ MiscUtils.assertFloatBufferEquals("Mvi not translated123, "+pmv.toString(), translated123I, mvi, epsilon);
+ Assert.assertEquals("Request bit Mvi not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW, pmv.getRequestMask());
+ Assert.assertEquals("Remaining dirty bits not Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+
+ frustum = pmv.glGetFrustum();
+ Assert.assertNotNull("Frustum is null"+pmv.toString(), frustum); // FIXME: Test Frustum value!
+ Assert.assertEquals("Remaining dirty bits not Mvit, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW, pmv.getDirtyBits());
+ Assert.assertEquals("Request bits Mvi|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask());
+ // System.err.println("P3: "+pmv.toString());
+
+ mvit = pmv.glGetMvitMatrixf();
+ MiscUtils.assertFloatBufferEquals("Mvit not translated123, "+pmv.toString()+pmv.toString(), translated123IT, mvit, epsilon);
+ Assert.assertTrue("Dirty bits not clean, "+pmv.toString(), 0 == pmv.getDirtyBits());
+ Assert.assertEquals("Request bits Mvi|Mvit|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask());
+ // System.err.println("P4: "+pmv.toString());
+
+ //
+ // Action #2
+ //
+ pmv.glLoadIdentity(); // all dirty
+ Assert.assertTrue("Modified bits zero", 0 != pmv.getModifiedBits(true)); // clear & test
+ Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits());
+ Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+ Assert.assertEquals("Request bits Mvi|Mvit|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask());
+ MiscUtils.assertFloatBufferEquals("P not identity, "+pmv.toString(), ident, p, epsilon);
+ MiscUtils.assertFloatBufferEquals("Mv not identity, "+pmv.toString(), ident, mv, epsilon);
+ MiscUtils.assertFloatBufferNotEqual("Mvi already identity w/o update, "+pmv.toString(), ident, mvi, epsilon);
+ MiscUtils.assertFloatBufferNotEqual("Mvit already identity w/o update, "+pmv.toString(), ident, mvit, epsilon);
+ MiscUtils.assertFloatBufferEquals("Mvi not translated123, "+pmv.toString()+pmv.toString(), translated123I, mvi, epsilon);
+ MiscUtils.assertFloatBufferEquals("Mvit not translated123, "+pmv.toString()+pmv.toString(), translated123IT, mvit, epsilon);
+ Assert.assertNotNull("Frustum is null"+pmv.toString(), frustum); // FIXME: Test Frustum value!
+
+ b = pmv.update(); // will clean dirty bits, since request has been made -> true
+ Assert.assertEquals("Update has not been perfomed, but requested", true, b);
+ Assert.assertTrue("Dirty bits not clean, "+pmv.toString(), 0 == pmv.getDirtyBits());
+ Assert.assertEquals("Request bits Mvi|Mvit|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask());
+ MiscUtils.assertFloatBufferEquals("Mvi not identity after update, "+pmv.toString(), ident, mvi, epsilon);
+ MiscUtils.assertFloatBufferEquals("Mvit not identity after update, "+pmv.toString(), ident, mvit, epsilon);
+ Assert.assertNotNull("Frustum is null"+pmv.toString(), frustum); // FIXME: Test Frustum value!
+ }
+
+ /**
+ * Test using shader access workflow, i.e. 1) get-matrix references 2) operations
+ * <p>
+ * The Mvi, Mvit and Frustum dirty-bits and request-mask will be validated.
+ * </p>
+ */
+ @SuppressWarnings("deprecation")
+ @Test
+ public void test02MviUpdateShaderAccess() {
+ final FloatBuffer p, mv, mvi, mvit;
+ Frustum frustum;
+ boolean b;
+ final PMVMatrix pmv = new PMVMatrix();
+ // System.err.println("P0: "+pmv.toString());
+
+ Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits());
+ Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+ Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask());
+
+ //
+ // Action #0
+ //
+ final FloatBuffer ident;
+ {
+ pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmv.glLoadIdentity();
+ ident = pmv.glGetPMatrixf();
+
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ }
+ // System.err.println("P0: "+pmv.toString());
+ Assert.assertTrue("Modified bits zero", 0 != pmv.getModifiedBits(true)); // clear & test
+ Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits());
+ Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+ Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask());
+ // System.err.println("P1: "+pmv.toString());
+
+ //
+ // Get
+ //
+ p = pmv.glGetPMatrixf();
+ MiscUtils.assertFloatBufferEquals("P not identity, "+pmv.toString(), ident, p, epsilon);
+ mv = pmv.glGetMvMatrixf();
+ MiscUtils.assertFloatBufferEquals("Mv not identity, "+pmv.toString(), ident, mv, epsilon);
+ Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits());
+ Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask());
+
+ mvi = pmv.glGetMviMatrixf();
+ MiscUtils.assertFloatBufferEquals("Mvi not identity, "+pmv.toString(), ident, mvi, epsilon);
+ Assert.assertEquals("Remaining dirty bits not Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+ Assert.assertEquals("Request bit Mvi not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW, pmv.getRequestMask());
+
+ mvit = pmv.glGetMvitMatrixf();
+ MiscUtils.assertFloatBufferEquals("Mvi not identity, "+pmv.toString(), ident, mvit, epsilon);
+ Assert.assertEquals("Remaining dirty bits not Frustum, "+pmv.toString(), PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+ Assert.assertEquals("Request bits Mvi and Mvit not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW, pmv.getRequestMask());
+
+ frustum = pmv.glGetFrustum();
+ Assert.assertNotNull("Frustum is null"+pmv.toString(), frustum); // FIXME: Test Frustum value!
+ Assert.assertTrue("Dirty bits not clean, "+pmv.toString(), 0 == pmv.getDirtyBits());
+ Assert.assertEquals("Request bits Mvi|Mvit|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask());
+
+ //
+ // Action #1
+ //
+ pmv.glTranslatef(1f, 2f, 3f); // all dirty !
+ Assert.assertTrue("Modified bits zero", 0 != pmv.getModifiedBits(true)); // clear & test
+ Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits());
+ Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits());
+ MiscUtils.assertFloatBufferEquals("P not identity, "+pmv.toString()+pmv.toString(), ident, p, epsilon);
+ MiscUtils.assertFloatBufferEquals("Mv not translated123, "+pmv.toString()+pmv.toString(), translated123C, mv, epsilon);
+ MiscUtils.assertFloatBufferNotEqual("Mvi already translated123 w/o update, "+pmv.toString()+pmv.toString(), translated123I, mvi, epsilon);
+ MiscUtils.assertFloatBufferNotEqual("Mvit already translated123 w/o update, "+pmv.toString()+pmv.toString(), translated123IT, mvit, epsilon);
+ MiscUtils.assertFloatBufferEquals("Mvi not identity, "+pmv.toString()+pmv.toString(), ident, mvi, epsilon);
+ MiscUtils.assertFloatBufferEquals("Mvit not identity, "+pmv.toString()+pmv.toString(), ident, mvit, epsilon);
+ Assert.assertNotNull("Frustum is null"+pmv.toString(), frustum); // FIXME: Test Frustum value!
+
+ b = pmv.update(); // will clean dirty bits, since all requests has been made -> true
+ Assert.assertEquals("Update has not been perfomed, but requested", true, b);
+ Assert.assertTrue("Dirty bits not clean, "+pmv.toString(), 0 == pmv.getDirtyBits());
+ Assert.assertEquals("Request bits Mvi|Mvit|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask());
+ MiscUtils.assertFloatBufferEquals("Mvi not translated123, "+pmv.toString()+pmv.toString(), translated123I, mvi, epsilon);
+ MiscUtils.assertFloatBufferEquals("Mvit not translated123, "+pmv.toString()+pmv.toString(), translated123IT, mvit, epsilon);
+ // System.err.println("P2: "+pmv.toString());
+ }
+
+ @SuppressWarnings("unused")
+ @Test
+ public void test03MvTranslate() {
+ final FloatBuffer pmvMv;
+ // final FloatBuffer pmvMvi, pmvMvit;
+ {
+ final PMVMatrix pmv = new PMVMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmv.glLoadIdentity();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ pmv.glTranslatef(5f, 6f, 7f);
+
+ pmvMv = pmv.glGetMvMatrixf();
+ // pmvMvi = pmv.glGetMviMatrixf();
+ // pmvMvit = pmv.glGetMvitMatrixf();
+ }
+
+ final FloatBuffer glMv = FloatBuffer.allocate(16);
+ {
+ final GL2ES1 gl = dc.glc.getGL().getGL2ES1();
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(5f, 6f, 7f);
+
+ gl.glGetFloatv(GLMatrixFunc.GL_MODELVIEW_MATRIX, glMv);
+ }
+ // System.err.println(PMVMatrix.matrixToString(null, "%10.5f", glMv, pmvMv).toString());
+
+ MiscUtils.assertFloatBufferEquals("Arrays not equal, expected"+PlatformPropsImpl.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", glMv).toString()+
+ ", actual"+PlatformPropsImpl.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMv).toString(),
+ glMv, pmvMv, epsilon);
+
+ // System.err.println("pmvMvi: "+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMvi));
+ // System.err.println("pmvMvit: "+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMvit));
+ }
+
+ @SuppressWarnings("unused")
+ @Test
+ public void test04MvTranslateRotate() {
+ final FloatBuffer pmvMv;
+ // final FloatBuffer pmvMvi, pmvMvit;
+ {
+ final PMVMatrix pmv = new PMVMatrix();
+ pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmv.glLoadIdentity();
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ pmv.glTranslatef(5f, 6f, 7f);
+ pmv.glRotatef(90f, 1f, 0f, 0f);
+
+ pmvMv = pmv.glGetMvMatrixf();
+ // pmvMvi = pmv.glGetMviMatrixf();
+ // pmvMvit = pmv.glGetMvitMatrixf();
+ }
+
+ final FloatBuffer glMv = FloatBuffer.allocate(16);
+ {
+ final GL2ES1 gl = dc.glc.getGL().getGL2ES1();
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(5f, 6f, 7f);
+ gl.glRotatef(90f, 1f, 0f, 0f);
+
+ gl.glGetFloatv(GLMatrixFunc.GL_MODELVIEW_MATRIX, glMv);
+ }
+ // System.err.println(PMVMatrix.matrixToString(null, "%10.5f", glMv, pmvMv).toString());
+
+ MiscUtils.assertFloatBufferEquals("Arrays not equal, expected"+PlatformPropsImpl.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", glMv).toString()+
+ ", actual"+PlatformPropsImpl.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMv).toString(),
+ glMv, pmvMv, epsilon);
+
+ // System.err.println("pmvMvi: "+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMvi));
+ // System.err.println("pmvMvit: "+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMvit));
+ }
+
+ static DrawableContext dc;
+
+ @BeforeClass
+ public static void setup() throws Throwable {
+ try {
+ dc = createOffscreenDrawableAndCurrentFFPContext();
+ } catch (final Throwable t) {
+ setTestSupported(false);
+ throw t;
+ }
+ }
+
+ @AfterClass
+ public static void cleanup() {
+ destroyDrawableContext(dc);
+ }
+
+ static class DrawableContext {
+ DrawableContext(final GLDrawable d, final GLContext glc) {
+ this.d = d;
+ this.glc = glc;
+ }
+ GLDrawable d;
+ GLContext glc;
+ }
+
+ private static DrawableContext createOffscreenDrawableAndCurrentFFPContext() throws Throwable {
+ final GLProfile glp = GLProfile.getMaxFixedFunc(true);
+ final GLCapabilities glCaps = new GLCapabilities(glp);
+ glCaps.setOnscreen(false);
+ glCaps.setPBuffer(true);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp);
+ final GLDrawable d = factory.createOffscreenDrawable(null, glCaps, null, 64, 64);
+ d.setRealized(true);
+ GLContext glc = null;
+ try {
+ glc = d.createContext(null);
+ Assert.assertTrue("Context could not be made current", GLContext.CONTEXT_NOT_CURRENT < glc.makeCurrent());
+ return new DrawableContext(d, glc);
+ } catch (final Throwable t) {
+ if(null != glc) {
+ glc.destroy();
+ }
+ d.setRealized(false);
+ throw t;
+ }
+ }
+
+ private static void destroyDrawableContext(final DrawableContext dc) {
+ if(null != dc.glc) {
+ dc.glc.destroy();
+ dc.glc = null;
+ }
+ if(null != dc.d) {
+ dc.d.setRealized(false);
+ dc.d = null;
+ }
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestPMVMatrix01NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix02NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix02NOUI.java
new file mode 100644
index 000000000..7250e438d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix02NOUI.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.math;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.util.PMVMatrix;
+
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import java.nio.FloatBuffer;
+
+import static org.junit.Assert.assertArrayEquals;
+
+/**
+ * @author Thomas De Bodt
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPMVMatrix02NOUI {
+
+ private PMVMatrix fMat;
+
+ @Before
+ public void setUp() throws Exception {
+ fMat = new PMVMatrix();
+ }
+
+ @Test
+ public void testLookAtNegZIsNoOp() throws Exception {
+ fMat.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ // Look towards -z
+ fMat.gluLookAt(
+ 0, 0, 0,
+ 0, 0, -1,
+ 0, 1, 0
+ );
+ final FloatBuffer mvMatrix = fMat.glGetMvMatrixf();
+ final float[] mvMatrixArr = new float[16];
+ mvMatrix.asReadOnlyBuffer().get(mvMatrixArr);
+ assertArrayEquals(
+ /**
+ * The 3 rows of the matrix (= the 3 columns of the array/buffer) should be: side, up, -forward.
+ */
+ new float[] {
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ },
+ mvMatrixArr,
+ 1e-6f
+ );
+ }
+ @Test
+ public void testLookAtPosY() throws Exception {
+ fMat.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ // Look towards +y
+ fMat.gluLookAt(
+ 0, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1
+ );
+ final FloatBuffer mvMatrix = fMat.glGetMvMatrixf();
+ final float[] mvMatrixArr = new float[16];
+ mvMatrix.asReadOnlyBuffer().get(mvMatrixArr);
+ assertArrayEquals(
+ /**
+ * The 3 rows of the matrix (= the 3 columns of the array/buffer) should be: side, up, -forward.
+ */
+ new float[] {
+ 1, 0, 0, 0,
+ 0, 0, -1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1
+ },
+ mvMatrixArr,
+ 1e-6f
+ );
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestPMVMatrix02NOUI.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix03NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix03NOUI.java
new file mode 100644
index 000000000..87e759919
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix03NOUI.java
@@ -0,0 +1,151 @@
+package com.jogamp.opengl.test.junit.jogl.math;
+
+import java.util.Arrays;
+
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import jogamp.opengl.ProjectFloat;
+
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.util.PMVMatrix;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPMVMatrix03NOUI {
+
+ static final float epsilon = 0.00001f;
+
+ // Simple 10 x 10 view port
+ static final int[] viewport = new int[] { 0,0,10,10};
+
+ @Test
+ public void test01() {
+ final float[] vec4Tmp1 = new float[4];
+ final float[] vec4Tmp2 = new float[4];
+
+ final float[] winA00 = new float[4];
+ final float[] winA01 = new float[4];
+ final float[] winA10 = new float[4];
+ final float[] winA11 = new float[4];
+ final float[] winB00 = new float[4];
+ final float[] winB01 = new float[4];
+ final float[] winB10 = new float[4];
+ final float[] winB11 = new float[4];
+
+ final PMVMatrix m = new PMVMatrix();
+ final float[] mat4PMv = new float[16];
+ m.multPMvMatrixf(mat4PMv, 0);
+ System.err.println(FloatUtil.matrixToString(null, "mat4PMv", "%10.5f", mat4PMv, 0, 4, 4, false /* rowMajorOrder */));
+
+ m.gluProject(1f, 0f, 0f, viewport, 0, winA00, 0);
+ System.err.println("A.0.0 - Project 1,0 -->" + Arrays.toString(winA00));
+ FloatUtil.mapObjToWinCoords(1f, 0f, 0f, mat4PMv, viewport, 0, winB00, 0, vec4Tmp1, vec4Tmp2);
+ System.err.println("B.0.0 - Project 1,0 -->" + Arrays.toString(winB00));
+
+ m.gluProject(0f, 0f, 0f, viewport, 0, winA01, 0);
+ System.err.println("A.0.1 - Project 0,0 -->" + Arrays.toString(winA01));
+ FloatUtil.mapObjToWinCoords(0f, 0f, 0f, mat4PMv, viewport, 0, winB01, 0, vec4Tmp1, vec4Tmp2);
+ System.err.println("B.0.1 - Project 0,0 -->" + Arrays.toString(winB01));
+
+ m.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ m.glOrthof(0, 10, 0, 10, 1, -1);
+ System.err.println("MATRIX - Ortho 0,0,10,10 - Locate the origin in the bottom left and scale");
+ System.err.println(m);
+ m.multPMvMatrixf(mat4PMv, 0);
+ System.err.println(FloatUtil.matrixToString(null, "mat4PMv", "%10.5f", mat4PMv, 0, 4, 4, false /* rowMajorOrder */));
+
+ m.gluProject(1f, 0f, 0f, viewport, 0, winA10, 0);
+ System.err.println("A.1.0 - Project 1,0 -->" +Arrays.toString(winA10));
+ FloatUtil.mapObjToWinCoords(1f, 0f, 0f, mat4PMv, viewport, 0, winB10, 0, vec4Tmp1, vec4Tmp2);
+ System.err.println("B.1.0 - Project 1,0 -->" +Arrays.toString(winB10));
+
+ m.gluProject(0f, 0f, 0f, viewport, 0, winA11, 0);
+ System.err.println("A.1.1 - Project 0,0 -->" +Arrays.toString(winA11));
+ FloatUtil.mapObjToWinCoords(0f, 0f, 0f, mat4PMv, viewport, 0, winB11, 0, vec4Tmp1, vec4Tmp2);
+ System.err.println("B.1.1 - Project 0,0 -->" +Arrays.toString(winB11));
+
+ Assert.assertArrayEquals("A/B 0.0 Project 1,0 failure", winB00, winA00, epsilon);
+ Assert.assertArrayEquals("A/B 0.1 Project 0,0 failure", winB01, winA01, epsilon);
+ Assert.assertArrayEquals("A/B 1.0 Project 1,0 failure", winB10, winA10, epsilon);
+ Assert.assertArrayEquals("A/B 1.1 Project 0,0 failure", winB11, winA11, epsilon);
+
+ ////////////////////
+ /////////////////////
+
+ final float[] winC00 = new float[4];
+ final float[] winC01 = new float[4];
+ final float[] winC10 = new float[4];
+ final float[] winC11 = new float[4];
+ final float[] projMatrixC = new float[16];
+ final float[] modelMatrixC = new float[16];
+ FloatUtil.makeIdentity(projMatrixC);
+ FloatUtil.makeIdentity(modelMatrixC);
+ final ProjectFloat projectFloat = new ProjectFloat();
+
+ projectFloat.gluProject(1f, 0f, 0f, modelMatrixC, 0, projMatrixC, 0, viewport, 0, winC00, 0);
+ System.err.println("C.0.0 - Project 1,0 -->" +Arrays.toString(winC00));
+
+ projectFloat.gluProject(0f, 0f, 0f, modelMatrixC, 0, projMatrixC, 0, viewport, 0, winC01, 0);
+ System.err.println("C.0.1 - Project 0,0 -->" +Arrays.toString(winC01));
+
+ glOrthof(projMatrixC, 0, 10, 0, 10, 1, -1);
+ System.err.println("FloatUtil - Ortho 0,0,10,10 - Locate the origin in the bottom left and scale");
+ System.err.println("Projection");
+ System.err.println(FloatUtil.matrixToString(null, null, "%10.5f", projMatrixC, 0, 4, 4, false /* rowMajorOrder */));
+ System.err.println("Modelview");
+ System.err.println(FloatUtil.matrixToString(null, null, "%10.5f", modelMatrixC, 0, 4, 4, false /* rowMajorOrder */));
+
+ projectFloat.gluProject(1f, 0f, 0f, modelMatrixC, 0, projMatrixC, 0, viewport, 0, winC10, 0);
+ System.err.println("C.1.0 - Project 1,0 -->" +Arrays.toString(winC10));
+
+ projectFloat.gluProject(0f, 0f, 0f, modelMatrixC, 0, projMatrixC, 0, viewport, 0, winC11, 0);
+ System.err.println("B.1.1 - Project 0,0 -->" +Arrays.toString(winC11));
+
+ Assert.assertArrayEquals("A/C 0.0 Project 1,0 failure", winC00, winA00, epsilon);
+ Assert.assertArrayEquals("A/C 0.1 Project 0,0 failure", winC01, winA01, epsilon);
+ Assert.assertArrayEquals("A/C 1.0 Project 1,0 failure", winC10, winA10, epsilon);
+ Assert.assertArrayEquals("A/C 1.1 Project 0,0 failure", winC11, winA11, epsilon);
+
+ Assert.assertEquals("A 0.0 Project 1,0 failure X", 10.0, winA00[0], epsilon);
+ Assert.assertEquals("A 0.0 Project 1,0 failure Y", 5.0, winA00[1], epsilon);
+ Assert.assertEquals("A.0.1 Project 0,0 failure X", 5.0, winA01[0], epsilon);
+ Assert.assertEquals("A.0.1 Project 0,0 failure Y", 5.0, winA01[1], epsilon);
+ Assert.assertEquals("A 1.0 Project 1,0 failure X", 1.0, winA10[0], epsilon);
+ Assert.assertEquals("A 1.0 Project 1,0 failure Y", 0.0, winA10[1], epsilon);
+ Assert.assertEquals("A.1.1 Project 0,0 failure X", 0.0, winA11[0], epsilon);
+ Assert.assertEquals("A.1.1 Project 0,0 failure Y", 0.0, winA11[1], epsilon);
+ }
+
+ public final void glOrthof(final float[] m, final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) {
+ // Ortho matrix:
+ // 2/dx 0 0 tx
+ // 0 2/dy 0 ty
+ // 0 0 2/dz tz
+ // 0 0 0 1
+ final float dx=right-left;
+ final float dy=top-bottom;
+ final float dz=zFar-zNear;
+ final float tx=-1.0f*(right+left)/dx;
+ final float ty=-1.0f*(top+bottom)/dy;
+ final float tz=-1.0f*(zFar+zNear)/dz;
+
+ final float[] matrixOrtho = new float[16];
+ FloatUtil.makeIdentity(matrixOrtho);
+ matrixOrtho[0+4*0] = 2.0f/dx;
+ matrixOrtho[1+4*1] = 2.0f/dy;
+ matrixOrtho[2+4*2] = -2.0f/dz;
+ matrixOrtho[0+4*3] = tx;
+ matrixOrtho[1+4*3] = ty;
+ matrixOrtho[2+4*3] = tz;
+
+ FloatUtil.multMatrix(m, 0, matrixOrtho, 0);
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestPMVMatrix03NOUI.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestQuaternion01NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestQuaternion01NOUI.java
new file mode 100644
index 000000000..d6d7131fa
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestQuaternion01NOUI.java
@@ -0,0 +1,817 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.math;
+
+import java.util.Arrays;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.VectorUtil;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestQuaternion01NOUI {
+ static final boolean DEBUG = false;
+
+ static final Quaternion QUAT_IDENT = new Quaternion(0f, 0f, 0f, 1f);
+
+ static final float[] ZERO = new float[] { 0f, 0f, 0f };
+ static final float[] ONE = new float[] { 1f, 1f, 1f };
+ static final float[] NEG_ONE = new float[] { -1f, -1f, -1f };
+ static final float[] UNIT_X = new float[] { 1f, 0f, 0f };
+ static final float[] UNIT_Y = new float[] { 0f, 1f, 0f };
+ static final float[] UNIT_Z = new float[] { 0f, 0f, 1f };
+ static final float[] NEG_UNIT_X = new float[] { -1f, 0f, 0f };
+ static final float[] NEG_UNIT_Y = new float[] { 0f, -1f, 0f };
+ static final float[] NEG_UNIT_Z = new float[] { 0f, 0f, -1f };
+
+ static final float[] NEG_ONE_v4 = new float[] { -1f, -1f, -1f, 0f };
+ static final float[] ONE_v4 = new float[] { 1f, 1f, 1f, 0f };
+
+ static final float MACH_EPSILON = FloatUtil.getMachineEpsilon();
+
+ //
+ // Basic
+ //
+
+ @Test
+ public void test01Normalize() {
+ final Quaternion quat = new Quaternion(0, 1, 2, 3);
+ final Quaternion quat2 = new Quaternion(quat).normalize();
+ // Assert.assertTrue(Math.abs(1 - quat2.magnitude()) <= MACH_EPSILON);
+ Assert.assertEquals(0f, Math.abs(1 - quat2.magnitude()), MACH_EPSILON);
+ }
+
+ @Test
+ public void test02RotateZeroVector() {
+ final Quaternion quat = new Quaternion();
+ final float[] rotVec0 = quat.rotateVector(new float[3], 0, ZERO, 0);
+ Assert.assertArrayEquals(ZERO, rotVec0, FloatUtil.EPSILON);
+ }
+
+ @Test
+ public void test03InvertAndConj() {
+ // inversion check
+ {
+ final Quaternion quat0 = new Quaternion(0, 1, 2, 3);
+ final Quaternion quat0Inv = new Quaternion(quat0).invert();
+ Assert.assertEquals(quat0, quat0Inv.invert());
+ }
+ // conjugate check
+ {
+ final Quaternion quat0 = new Quaternion(-1f, -2f, -3f, 4f);
+ final Quaternion quat0Conj = new Quaternion( 1f, 2f, 3f, 4f).conjugate();
+ Assert.assertEquals(quat0, quat0Conj);
+ }
+ }
+
+ @Test
+ public void test04Dot() {
+ final Quaternion quat = new Quaternion(7f, 2f, 5f, -1f);
+ Assert.assertTrue(35.0f == quat.dot(3f, 1f, 2f, -2f));
+ Assert.assertTrue(-11.0f == quat.dot(new Quaternion(-1f, 1f, -1f, 1f)));
+ }
+
+
+ //
+ // Conversion
+ //
+
+ @Test
+ public void test10AngleAxis() {
+ final float[] tmpV3f = new float[3];
+ final Quaternion quat1 = new Quaternion().setFromAngleAxis(FloatUtil.HALF_PI, new float[] { 2, 0, 0 }, tmpV3f );
+ final Quaternion quat2 = new Quaternion().setFromAngleNormalAxis(FloatUtil.HALF_PI, new float[] { 1, 0, 0 } );
+
+ Assert.assertEquals(quat2, quat1);
+ // System.err.println("M "+quat2.magnitude()+", 1-M "+(1f-quat2.magnitude())+", Eps "+FloatUtil.EPSILON);
+ Assert.assertEquals(0f, 1 - quat2.magnitude(), FloatUtil.EPSILON);
+ Assert.assertTrue(1 - quat1.magnitude() <= FloatUtil.EPSILON);
+
+ final float[] vecOut1 = new float[3];
+ final float[] vecOut2 = new float[3];
+ quat1.rotateVector(vecOut1, 0, ONE, 0);
+ quat2.rotateVector(vecOut2, 0, ONE, 0);
+ Assert.assertArrayEquals(vecOut1, vecOut2, FloatUtil.EPSILON);
+ Assert.assertEquals(0f, Math.abs( VectorUtil.distVec3(vecOut1, vecOut2) ), FloatUtil.EPSILON );
+
+ quat1.rotateVector(vecOut1, 0, UNIT_Z, 0);
+ Assert.assertEquals(0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_Y, vecOut1) ), FloatUtil.EPSILON );
+
+ quat2.setFromAngleAxis(FloatUtil.HALF_PI, ZERO, tmpV3f);
+ Assert.assertEquals(QUAT_IDENT, quat2);
+
+ float angle = quat1.toAngleAxis(vecOut1);
+ quat2.setFromAngleAxis(angle, vecOut1, tmpV3f);
+ Assert.assertEquals(quat1, quat2);
+
+ quat1.set(0, 0, 0, 0);
+ angle = quat1.toAngleAxis(vecOut1);
+ Assert.assertTrue(0.0f == angle);
+ Assert.assertArrayEquals(UNIT_X, vecOut1, FloatUtil.EPSILON);
+ }
+
+ @Test
+ public void test11FromVectorToVector() {
+ final float[] tmp0V3f = new float[3];
+ final float[] tmp1V3f = new float[3];
+ final float[] vecOut = new float[3];
+ final Quaternion quat = new Quaternion();
+ quat.setFromVectors(UNIT_Z, UNIT_X, tmp0V3f, tmp1V3f);
+
+ final Quaternion quat2 = new Quaternion();
+ quat2.setFromNormalVectors(UNIT_Z, UNIT_X, tmp0V3f);
+ Assert.assertEquals(quat, quat2);
+
+ quat2.setFromAngleAxis(FloatUtil.HALF_PI, UNIT_Y, tmp0V3f);
+ Assert.assertEquals(quat2, quat);
+
+ quat.setFromVectors(UNIT_Z, NEG_UNIT_Z, tmp0V3f, tmp1V3f);
+ quat.rotateVector(vecOut, 0, UNIT_Z, 0);
+ // System.err.println("vecOut: "+Arrays.toString(vecOut));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_Z, vecOut) ), Quaternion.ALLOWED_DEVIANCE );
+
+ quat.setFromVectors(UNIT_X, NEG_UNIT_X, tmp0V3f, tmp1V3f);
+ quat.rotateVector(vecOut, 0, UNIT_X, 0);
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_X, vecOut) ), Quaternion.ALLOWED_DEVIANCE );
+
+ quat.setFromVectors(UNIT_Y, NEG_UNIT_Y, tmp0V3f, tmp1V3f);
+ quat.rotateVector(vecOut, 0, UNIT_Y, 0);
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_Y, vecOut) ), Quaternion.ALLOWED_DEVIANCE );
+
+ quat.setFromVectors(ONE, NEG_ONE, tmp0V3f, tmp1V3f);
+ quat.rotateVector(vecOut, 0, ONE, 0);
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_ONE, vecOut) ), Quaternion.ALLOWED_DEVIANCE );
+
+ quat.setFromVectors(ZERO, ZERO, tmp0V3f, tmp1V3f);
+ Assert.assertEquals(QUAT_IDENT, quat);
+ }
+
+ @Test
+ public void test12FromAndToEulerAngles() {
+ // Y.Z.X -> X.Y.Z
+ final Quaternion quat = new Quaternion();
+ final float[] angles0Exp = new float[] { 0f, FloatUtil.HALF_PI, 0f};
+ quat.setFromEuler(angles0Exp);
+ Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
+
+ final float[] angles0Has = quat.toEuler(new float[3]);
+ // System.err.println("exp0 "+Arrays.toString(angles0Exp));
+ // System.err.println("has0 "+Arrays.toString(angles0Has));
+ Assert.assertArrayEquals(angles0Exp, angles0Has, FloatUtil.EPSILON);
+
+ final Quaternion quat2 = new Quaternion();
+ quat2.setFromEuler(angles0Has);
+ Assert.assertEquals(quat, quat2);
+
+ ///
+
+ final float[] angles1Exp = new float[] { 0f, 0f, -FloatUtil.HALF_PI };
+ quat.setFromEuler(angles1Exp);
+ Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
+
+ final float[] angles1Has = quat.toEuler(new float[3]);
+ // System.err.println("exp1 "+Arrays.toString(angles1Exp));
+ // System.err.println("has1 "+Arrays.toString(angles1Has));
+ Assert.assertArrayEquals(angles1Exp, angles1Has, FloatUtil.EPSILON);
+
+ quat2.setFromEuler(angles1Has);
+ Assert.assertEquals(quat, quat2);
+
+ ///
+
+ final float[] angles2Exp = new float[] { FloatUtil.HALF_PI, 0f, 0f };
+ quat.setFromEuler(angles2Exp);
+ Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
+
+ final float[] angles2Has = quat.toEuler(new float[3]);
+ // System.err.println("exp2 "+Arrays.toString(angles2Exp));
+ // System.err.println("has2 "+Arrays.toString(angles2Has));
+ Assert.assertArrayEquals(angles2Exp, angles2Has, FloatUtil.EPSILON);
+
+ quat2.setFromEuler(angles2Has);
+ Assert.assertEquals(quat, quat2);
+ }
+
+ @Test
+ public void test13FromEulerAnglesAndRotateVector() {
+ final Quaternion quat = new Quaternion();
+ quat.setFromEuler(0, FloatUtil.HALF_PI, 0); // 90 degrees y-axis
+ Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
+
+ final float[] v2 = quat.rotateVector(new float[3], 0, UNIT_X, 0);
+ Assert.assertEquals(0f, Math.abs(VectorUtil.distVec3(NEG_UNIT_Z, v2)), FloatUtil.EPSILON);
+
+ quat.setFromEuler(0, 0, -FloatUtil.HALF_PI);
+ Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
+ quat.rotateVector(v2, 0, UNIT_X, 0);
+ Assert.assertEquals(0f, Math.abs(VectorUtil.distVec3(NEG_UNIT_Y, v2)), FloatUtil.EPSILON);
+
+ quat.setFromEuler(FloatUtil.HALF_PI, 0, 0);
+ Assert.assertEquals(1.0f, quat.magnitude(), FloatUtil.EPSILON);
+ quat.rotateVector(v2, 0, UNIT_Y, 0);
+ Assert.assertEquals(0f, Math.abs(VectorUtil.distVec3(UNIT_Z, v2)), FloatUtil.EPSILON);
+ }
+
+ @Test
+ public void test14Matrix() {
+ final float[] vecHas = new float[3];
+ final float[] vecOut2 = new float[4];
+ float[] mat1 = new float[4*4];
+ final float[] mat2 = new float[4*4];
+ final Quaternion quat = new Quaternion();
+
+ //
+ // IDENTITY CHECK
+ //
+ FloatUtil.makeIdentity(mat1);
+ quat.set(0, 0, 0, 0);
+ quat.toMatrix(mat2, 0);
+ Assert.assertArrayEquals(mat1, mat2, FloatUtil.EPSILON);
+
+ //
+ // 90 degrees rotation on X
+ //
+
+ float a = FloatUtil.HALF_PI;
+ mat1 = new float[] { // Column Order
+ 1, 0, 0, 0, //
+ 0, FloatUtil.cos(a), FloatUtil.sin(a), 0, //
+ 0, -FloatUtil.sin(a), FloatUtil.cos(a), 0,
+ 0, 0, 0, 1 };
+ {
+ // Validate Matrix via Euler rotation on Quaternion!
+ quat.setFromEuler(a, 0f, 0f);
+ quat.toMatrix(mat2, 0);
+ // System.err.println(FloatUtil.matrixToString(null, "quat-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(mat1, mat2, FloatUtil.EPSILON);
+ quat.rotateVector(vecHas, 0, UNIT_Y, 0);
+ // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(UNIT_Z, vecHas) ), Quaternion.ALLOWED_DEVIANCE );
+ }
+ quat.setFromMatrix(mat1, 0);
+ quat.rotateVector(vecHas, 0, UNIT_Y, 0);
+ // System.err.println("exp0 "+Arrays.toString(UNIT_Z));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(UNIT_Z, vecHas) ), Quaternion.ALLOWED_DEVIANCE );
+
+ quat.toMatrix(mat2, 0);
+ // System.err.println(FloatUtil.matrixToString(null, null, "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(mat1, mat2, FloatUtil.EPSILON);
+
+ quat.rotateVector(vecHas, 0, NEG_ONE, 0);
+ FloatUtil.multMatrixVec(mat2, NEG_ONE_v4, vecOut2);
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(vecHas, vecOut2) ), Quaternion.ALLOWED_DEVIANCE );
+
+ //
+ // 180 degrees rotation on X
+ //
+ a = FloatUtil.PI;
+ mat1 = new float[] { // Column Order
+ 1, 0, 0, 0, //
+ 0, FloatUtil.cos(a), FloatUtil.sin(a), 0, //
+ 0, -FloatUtil.sin(a), FloatUtil.cos(a), 0,
+ 0, 0, 0, 1 };
+ {
+ // Validate Matrix via Euler rotation on Quaternion!
+ quat.setFromEuler(a, 0f, 0f);
+ quat.toMatrix(mat2, 0);
+ // System.err.println(FloatUtil.matrixToString(null, "quat-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(mat1, mat2, FloatUtil.EPSILON);
+ quat.rotateVector(vecHas, 0, UNIT_Y, 0);
+ // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_Y, vecHas) ), Quaternion.ALLOWED_DEVIANCE );
+ }
+ quat.setFromMatrix(mat1, 0);
+ quat.rotateVector(vecHas, 0, UNIT_Y, 0);
+ // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_Y));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_Y, vecHas) ), Quaternion.ALLOWED_DEVIANCE );
+
+ quat.toMatrix(mat2, 0);
+ // System.err.println(FloatUtil.matrixToString(null, null, "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(mat1, mat2, FloatUtil.EPSILON);
+
+ quat.rotateVector(vecHas, 0, ONE, 0);
+ FloatUtil.multMatrixVec(mat2, ONE_v4, vecOut2);
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(vecHas, vecOut2) ), Quaternion.ALLOWED_DEVIANCE );
+
+ //
+ // 180 degrees rotation on Y
+ //
+ a = FloatUtil.PI;
+ mat1 = new float[] { // Column Order
+ FloatUtil.cos(a), 0, -FloatUtil.sin(a), 0, //
+ 0, 1, 0, 0, //
+ FloatUtil.sin(a), 0, FloatUtil.cos(a), 0,
+ 0, 0, 0, 1 };
+ {
+ // Validate Matrix via Euler rotation on Quaternion!
+ quat.setFromEuler(0f, a, 0f);
+ quat.toMatrix(mat2, 0);
+ // System.err.println(FloatUtil.matrixToString(null, "quat-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(mat1, mat2, FloatUtil.EPSILON);
+ quat.rotateVector(vecHas, 0, UNIT_X, 0);
+ // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_X, vecHas) ), Quaternion.ALLOWED_DEVIANCE );
+ }
+ quat.setFromMatrix(mat1, 0);
+ quat.rotateVector(vecHas, 0, UNIT_X, 0);
+ // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_X, vecHas) ), Quaternion.ALLOWED_DEVIANCE );
+
+ quat.toMatrix(mat2, 0);
+ // System.err.println(FloatUtil.matrixToString(null, "matr-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(mat1, mat2, FloatUtil.EPSILON);
+
+ quat.rotateVector(vecHas, 0, NEG_ONE, 0);
+ FloatUtil.multMatrixVec(mat2, NEG_ONE_v4, vecOut2);
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(vecHas, vecOut2) ), Quaternion.ALLOWED_DEVIANCE );
+
+ //
+ // 180 degrees rotation on Z
+ //
+ a = FloatUtil.PI;
+ mat1 = new float[] { // Column Order
+ FloatUtil.cos(a), FloatUtil.sin(a), 0, 0, //
+ -FloatUtil.sin(a), FloatUtil.cos(a), 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1 };
+ {
+ // Validate Matrix via Euler rotation on Quaternion!
+ quat.setFromEuler(0f, 0f, a);
+ quat.toMatrix(mat2, 0);
+ // System.err.println(FloatUtil.matrixToString(null, "quat-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(mat1, mat2, FloatUtil.EPSILON);
+ quat.rotateVector(vecHas, 0, UNIT_X, 0);
+ // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_X, vecHas) ), Quaternion.ALLOWED_DEVIANCE );
+ }
+ quat.setFromMatrix(mat1, 0);
+ quat.rotateVector(vecHas, 0, UNIT_X, 0);
+ // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_X, vecHas) ), Quaternion.ALLOWED_DEVIANCE );
+
+ quat.toMatrix(mat2, 0);
+ // System.err.println(FloatUtil.matrixToString(null, "matr-rot", "%10.5f", mat1, 0, mat2, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(mat1, mat2, FloatUtil.EPSILON);
+
+ quat.rotateVector(vecHas, 0, ONE, 0);
+ FloatUtil.multMatrixVec(mat2, ONE_v4, vecOut2);
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(vecHas, vecOut2) ), Quaternion.ALLOWED_DEVIANCE );
+
+ //
+ // Test Matrix-Columns
+ //
+
+ a = FloatUtil.QUARTER_PI;
+ final float[] vecExp = new float[3];
+ final float[] vecCol = new float[3];
+ mat1 = new float[] { // Column Order
+ FloatUtil.cos(a), FloatUtil.sin(a), 0, 0, //
+ -FloatUtil.sin(a), FloatUtil.cos(a), 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1 };
+ quat.setFromMatrix(mat1, 0);
+ FloatUtil.copyMatrixColumn(mat1, 0, 0, vecExp, 0);
+ quat.copyMatrixColumn(0, vecCol, 0);
+ // System.err.println("exp0 "+Arrays.toString(vecExp));
+ // System.err.println("has0 "+Arrays.toString(vecCol));
+ Assert.assertEquals(0f, Math.abs( VectorUtil.distVec3(vecExp, vecCol)), FloatUtil.EPSILON);
+
+ FloatUtil.copyMatrixColumn(mat1, 0, 1, vecExp, 0);
+ quat.copyMatrixColumn(1, vecCol, 0);
+ // System.err.println("exp1 "+Arrays.toString(vecExp));
+ // System.err.println("has1 "+Arrays.toString(vecCol));
+ Assert.assertEquals(0f, Math.abs( VectorUtil.distVec3(vecExp, vecCol)), FloatUtil.EPSILON);
+
+ FloatUtil.copyMatrixColumn(mat1, 0, 2, vecExp, 0);
+ quat.copyMatrixColumn(2, vecCol, 0);
+ // System.err.println("exp2 "+Arrays.toString(vecExp));
+ // System.err.println("has2 "+Arrays.toString(vecCol));
+ Assert.assertEquals(0f, Math.abs( VectorUtil.distVec3(vecExp, vecCol)), FloatUtil.EPSILON);
+
+ quat.set(0f, 0f, 0f, 0f);
+ Assert.assertArrayEquals(UNIT_X, quat.copyMatrixColumn(0, vecCol, 0), FloatUtil.EPSILON);
+
+ }
+
+ @Test
+ public void test15aAxesAndMatrix() {
+ final float[] eulerExp = new float[] { 0f, FloatUtil.HALF_PI, 0f };
+ final float[] matExp = new float[4*4];
+ FloatUtil.makeRotationEuler(matExp, 0, eulerExp[0], eulerExp[1], eulerExp[2]); // 45 degr on X, 90 degr on Y
+
+ final float[] matHas = new float[4*4];
+ final Quaternion quat1 = new Quaternion();
+ quat1.setFromEuler(eulerExp);
+ quat1.toMatrix(matHas, 0);
+ // System.err.println(FloatUtil.matrixToString(null, "exp-has", "%10.5f", matExp, 0, matHas, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(matExp, matHas, FloatUtil.EPSILON);
+
+ final float[] eulerHas = new float[3];
+ final Quaternion quat2 = new Quaternion();
+ quat2.setFromMatrix(matExp, 0);
+ quat2.toEuler(eulerHas);
+ // System.err.println("exp-euler "+Arrays.toString(eulerExp));
+ // System.err.println("has-euler "+Arrays.toString(eulerHas));
+ Assert.assertArrayEquals(eulerExp, eulerHas, FloatUtil.EPSILON);
+
+ Assert.assertEquals(quat2, quat1);
+
+ final float[] angles = new float[3];
+ quat2.toEuler(angles);
+ quat1.setFromEuler(angles);
+ Assert.assertEquals(quat2, quat1);
+ }
+
+ @Test
+ public void test15bAxesAndMatrix() {
+ final float[] eulerExp = new float[] { FloatUtil.HALF_PI, 0f, 0f };
+ final float[] matExp = new float[4*4];
+ FloatUtil.makeRotationEuler(matExp, 0, eulerExp[0], eulerExp[1], eulerExp[2]); // 45 degr on X, 90 degr on Y
+
+ final float[] matHas = new float[4*4];
+ final Quaternion quat1 = new Quaternion();
+ quat1.setFromEuler(eulerExp);
+ quat1.toMatrix(matHas, 0);
+ // System.err.println(FloatUtil.matrixToString(null, "exp-has", "%10.5f", matExp, 0, matHas, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(matExp, matHas, FloatUtil.EPSILON);
+
+ final float[] eulerHas = new float[3];
+ final Quaternion quat2 = new Quaternion();
+ quat2.setFromMatrix(matExp, 0);
+ quat2.toEuler(eulerHas);
+ // System.err.println("exp-euler "+Arrays.toString(eulerExp));
+ // System.err.println("has-euler "+Arrays.toString(eulerHas));
+ Assert.assertArrayEquals(eulerExp, eulerHas, FloatUtil.EPSILON);
+
+ Assert.assertEquals(quat2, quat1);
+
+ final float[] angles = new float[3];
+ quat2.toEuler(angles);
+ quat1.setFromEuler(angles);
+ Assert.assertEquals(quat2, quat1);
+ }
+
+ @Test
+ public void test15cAxesAndMatrix() {
+ final float[] eulerExp = new float[] { FloatUtil.QUARTER_PI, FloatUtil.HALF_PI, 0f };
+ final float[] matExp = new float[4*4];
+ FloatUtil.makeRotationEuler(matExp, 0, eulerExp[0], eulerExp[1], eulerExp[2]); // 45 degr on X, 90 degr on Y
+
+ final float[] matHas = new float[4*4];
+ final Quaternion quat1 = new Quaternion();
+ quat1.setFromEuler(eulerExp);
+ quat1.toMatrix(matHas, 0);
+ // System.err.println(FloatUtil.matrixToString(null, "exp-has", "%10.5f", matExp, 0, matHas, 0, 4, 4, false).toString());
+ Assert.assertArrayEquals(matExp, matHas, FloatUtil.EPSILON);
+
+ final float[] eulerHas = new float[3];
+ final Quaternion quat2 = new Quaternion();
+ quat2.setFromMatrix(matExp, 0);
+ quat2.toEuler(eulerHas);
+ // System.err.println("exp-euler "+Arrays.toString(eulerExp));
+ // System.err.println("has-euler "+Arrays.toString(eulerHas));
+ Assert.assertArrayEquals(eulerExp, eulerHas, FloatUtil.EPSILON);
+
+ Assert.assertEquals(quat2, quat1);
+
+ final float[] angles = new float[3];
+ quat2.toEuler(angles);
+ quat1.setFromEuler(angles);
+ Assert.assertEquals(quat2, quat1);
+ }
+
+ //
+ // Functions
+ //
+
+ @Test
+ public void test20AddSubtract() {
+ final Quaternion quatExp1 = new Quaternion(1, 2, 3, 4);
+ final Quaternion quat1 = new Quaternion(0, 1, 2, 3);
+ final Quaternion quat2 = new Quaternion(1, 1, 1, 1);
+
+ final Quaternion quatHas = new Quaternion();
+ quatHas.set(quat1);
+ quatHas.add(quat2); // q3 = q1 + q2
+ Assert.assertEquals(quatExp1, quatHas);
+
+ quat1.set(0, 1, 2, 3);
+ quat2.set(1, 1, 1, 1);
+ quatHas.set(quat1);
+ quatHas.subtract(quat2); // q3 = q1 - q2
+ Assert.assertEquals(new Quaternion(-1, 0, 1, 2), quatHas);
+ }
+
+ @Test
+ public void test21Multiply() {
+ final Quaternion quat1 = new Quaternion(0.5f, 1f, 2f, 3f);
+ final Quaternion quat2 = new Quaternion();
+
+ quat2.set(quat1);
+ quat2.scale(2f); // q2 = q1 * 2f
+ Assert.assertEquals(new Quaternion(1, 2, 4, 6), quat2);
+
+ quat2.set(quat1);
+ quat2.scale(4f); // q2 = q1 * 4f
+ Assert.assertEquals(new Quaternion(2, 4, 8, 12), quat2);
+
+ //
+ // mul and cmp rotated vector
+ //
+ quat1.setFromAngleNormalAxis(FloatUtil.QUARTER_PI, UNIT_Y); // 45 degr on Y
+ quat2.set(quat1);
+ quat2.mult(quat1); // q2 = q1 * q1 -> 2 * 45 degr -> 90 degr on Y
+
+ final float[] vecOut = new float[3];
+ quat2.rotateVector(vecOut, 0, UNIT_Z, 0);
+ Assert.assertTrue( Math.abs( VectorUtil.distVec3(UNIT_X, vecOut)) <= Quaternion.ALLOWED_DEVIANCE);
+
+ quat2.setFromAngleNormalAxis(FloatUtil.HALF_PI, UNIT_Y); // 90 degr on Y
+ quat1.mult(quat1); // q1 = q1 * q1 -> 2 * 45 degr -> 90 degr on Y
+ quat1.mult(quat2); // q1 = q1 * q2 -> 2 * 90 degr -> 180 degr on Y
+ quat1.rotateVector(vecOut, 0, UNIT_Z, 0);
+ Assert.assertTrue( Math.abs( VectorUtil.distVec3(NEG_UNIT_Z, vecOut)) <= Quaternion.ALLOWED_DEVIANCE);
+
+ quat2.setFromEuler(0f, FloatUtil.HALF_PI, 0f);
+ quat1.mult(quat2); // q1 = q1 * q2 = q1 * rotMat(0, 90degr, 0)
+ quat1.rotateVector(vecOut, 0, UNIT_Z, 0);
+ Assert.assertTrue( Math.abs( VectorUtil.distVec3(NEG_UNIT_X, vecOut)) <= Quaternion.ALLOWED_DEVIANCE);
+ }
+
+ @Test
+ public void test22InvertMultNormalAndConj() {
+ final Quaternion quat0 = new Quaternion(0, 1, 2, 3);
+ final Quaternion quat1 = new Quaternion(quat0);
+ final Quaternion quat2 = new Quaternion(quat0);
+ quat1.invert(); // q1 = invert(q0)
+ quat2.mult(quat1); // q2 = q0 * q1 = q0 * invert(q0)
+ Assert.assertEquals(QUAT_IDENT, quat2);
+ quat1.invert();
+ Assert.assertEquals(quat0, quat1);
+
+ // normalized version
+ quat0.setFromAngleNormalAxis(FloatUtil.QUARTER_PI, UNIT_Y);
+ quat1.set(quat0);
+ quat1.invert(); // q1 = invert(q0)
+ quat2.set(quat0);
+ quat2.mult(quat1); // q2 = q0 * q1 = q0 * invert(q0)
+ Assert.assertEquals(QUAT_IDENT, quat2);
+ quat1.invert();
+ Assert.assertEquals(quat0, quat1);
+
+ // conjugate check
+ quat0.set(-1f, -2f, -3f, 4f);
+ quat1.set( 1f, 2f, 3f, 4f);
+ quat2.set(quat1);
+ quat2.conjugate();
+ Assert.assertEquals(quat0, quat2);
+ }
+
+ @Test
+ public void test23RotationOrder() {
+ {
+ final Quaternion quat1 = new Quaternion().setFromEuler( -2f*FloatUtil.HALF_PI, 0f, 0f); // -180 degr X
+ final Quaternion quat2 = new Quaternion().rotateByAngleX( -2f * FloatUtil.HALF_PI); // angle: -180 degrees, axis X
+ Assert.assertEquals(quat1, quat2);
+ }
+ {
+ final Quaternion quat1 = new Quaternion().setFromEuler( FloatUtil.HALF_PI, 0f, 0f); // 90 degr X
+ final Quaternion quat2 = new Quaternion().rotateByAngleX( FloatUtil.HALF_PI); // angle: 90 degrees, axis X
+ Assert.assertEquals(quat1, quat2);
+ }
+ {
+ final Quaternion quat1 = new Quaternion().setFromEuler( FloatUtil.HALF_PI, FloatUtil.QUARTER_PI, 0f);
+ final Quaternion quat2 = new Quaternion().rotateByAngleY(FloatUtil.QUARTER_PI).rotateByAngleX(FloatUtil.HALF_PI);
+ Assert.assertEquals(quat1, quat2);
+ }
+ {
+ final Quaternion quat1 = new Quaternion().setFromEuler( FloatUtil.PI, FloatUtil.QUARTER_PI, FloatUtil.HALF_PI);
+ final Quaternion quat2 = new Quaternion().rotateByAngleY(FloatUtil.QUARTER_PI).rotateByAngleZ(FloatUtil.HALF_PI).rotateByAngleX(FloatUtil.PI);
+ Assert.assertEquals(quat1, quat2);
+ }
+
+
+ float[] vecExp = new float[3];
+ float[] vecRot = new float[3];
+ final Quaternion quat = new Quaternion();
+
+ // Try a new way with new angles...
+ quat.setFromEuler(FloatUtil.HALF_PI, FloatUtil.QUARTER_PI, FloatUtil.PI);
+ vecRot = new float[] { 1f, 1f, 1f };
+ quat.rotateVector(vecRot, 0, vecRot, 0);
+
+ // expected
+ vecExp = new float[] { 1f, 1f, 1f };
+ final Quaternion worker = new Quaternion();
+ // put together matrix, then apply to vector, so YZX
+ worker.rotateByAngleY(FloatUtil.QUARTER_PI).rotateByAngleZ(FloatUtil.PI).rotateByAngleX(FloatUtil.HALF_PI);
+ quat.rotateVector(vecExp, 0, vecExp, 0);
+ Assert.assertEquals(0f, VectorUtil.distVec3(vecExp, vecRot), FloatUtil.EPSILON);
+
+ // test axis rotation methods against general purpose
+ // X AXIS
+ vecExp = new float[] { 1f, 1f, 1f };
+ vecRot = new float[] { 1f, 1f, 1f };
+ worker.setIdentity().rotateByAngleX(FloatUtil.QUARTER_PI).rotateVector(vecExp, 0, vecExp, 0);
+ worker.setIdentity().rotateByAngleNormalAxis(FloatUtil.QUARTER_PI, 1f, 0f, 0f).rotateVector(vecRot, 0, vecRot, 0);
+ // System.err.println("exp0 "+Arrays.toString(vecExp)+", len "+VectorUtil.length(vecExp));
+ // System.err.println("has0 "+Arrays.toString(vecRot)+", len "+VectorUtil.length(vecRot));
+ Assert.assertEquals(0f, VectorUtil.distVec3(vecExp, vecRot), FloatUtil.EPSILON);
+
+ // Y AXIS
+ vecExp = new float[] { 1f, 1f, 1f };
+ vecRot = new float[] { 1f, 1f, 1f };
+ worker.setIdentity().rotateByAngleY(FloatUtil.QUARTER_PI).rotateVector(vecExp, 0, vecExp, 0);
+ worker.setIdentity().rotateByAngleNormalAxis(FloatUtil.QUARTER_PI, 0f, 1f, 0f).rotateVector(vecRot, 0, vecRot, 0);
+ // System.err.println("exp0 "+Arrays.toString(vecExp));
+ // System.err.println("has0 "+Arrays.toString(vecRot));
+ Assert.assertEquals(0f, VectorUtil.distVec3(vecExp, vecRot), FloatUtil.EPSILON);
+
+ // Z AXIS
+ vecExp = new float[] { 1f, 1f, 1f };
+ vecRot = new float[] { 1f, 1f, 1f };
+ worker.setIdentity().rotateByAngleZ(FloatUtil.QUARTER_PI).rotateVector(vecExp, 0, vecExp, 0);
+ worker.setIdentity().rotateByAngleNormalAxis(FloatUtil.QUARTER_PI, 0f, 0f, 1f).rotateVector(vecRot, 0, vecRot, 0);
+ // System.err.println("exp0 "+Arrays.toString(vecExp));
+ // System.err.println("has0 "+Arrays.toString(vecRot));
+ Assert.assertEquals(0f, VectorUtil.distVec3(vecExp, vecRot), FloatUtil.EPSILON);
+
+ quat.set(worker);
+ worker.rotateByAngleNormalAxis(0f, 0f, 0f, 0f);
+ Assert.assertEquals(quat, worker);
+ }
+
+ @Test
+ public void test24Axes() {
+ final Quaternion quat0 = new Quaternion().rotateByAngleX(FloatUtil.QUARTER_PI).rotateByAngleY(FloatUtil.HALF_PI);
+ final float[] rotMat = new float[4*4];
+ quat0.toMatrix(rotMat, 0);
+ final float[] xAxis = new float[3];
+ final float[] yAxis = new float[3];
+ final float[] zAxis = new float[3];
+ FloatUtil.copyMatrixColumn(rotMat, 0, 0, xAxis, 0);
+ FloatUtil.copyMatrixColumn(rotMat, 0, 1, yAxis, 0);
+ FloatUtil.copyMatrixColumn(rotMat, 0, 2, zAxis, 0);
+
+ final Quaternion quat1 = new Quaternion().setFromAxes(xAxis, yAxis, zAxis);
+ Assert.assertEquals(quat0, quat1);
+ final Quaternion quat2 = new Quaternion().setFromMatrix(rotMat, 0);
+ Assert.assertEquals(quat2, quat1);
+
+ quat1.toAxes(xAxis, yAxis, zAxis, rotMat);
+ quat2.setFromAxes(xAxis, yAxis, zAxis);
+ Assert.assertEquals(quat0, quat2);
+ Assert.assertEquals(quat1, quat2);
+ }
+
+ @Test
+ public void test25Slerp() {
+ final Quaternion quat1 = new Quaternion(); // angle: 0 degrees
+ final Quaternion quat2 = new Quaternion().rotateByAngleY(FloatUtil.HALF_PI); // angle: 90 degrees, axis Y
+
+ float[] vecExp = new float[] { FloatUtil.sin(FloatUtil.QUARTER_PI), 0f, FloatUtil.sin(FloatUtil.QUARTER_PI) };
+ final float[] vecHas = new float[3];
+ final Quaternion quatS = new Quaternion();
+ // System.err.println("Slerp #01: 1/2 * 90 degrees Y");
+ quatS.setSlerp(quat1, quat2, 0.5f);
+ quatS.rotateVector(vecHas, 0, UNIT_Z, 0);
+ // System.err.println("exp0 "+Arrays.toString(vecExp));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(vecExp, vecHas)), Quaternion.ALLOWED_DEVIANCE);
+
+ // delta == 100%
+ quat2.setIdentity().rotateByAngleZ(FloatUtil.PI); // angle: 180 degrees, axis Z
+ // System.err.println("Slerp #02: 1 * 180 degrees Z");
+ quatS.setSlerp(quat1, quat2, 1.0f);
+ quatS.rotateVector(vecHas, 0, UNIT_X, 0);
+ // System.err.println("exp0 "+Arrays.toString(NEG_UNIT_X));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(NEG_UNIT_X, vecHas)), Quaternion.ALLOWED_DEVIANCE);
+
+ quat2.setIdentity().rotateByAngleZ(FloatUtil.PI); // angle: 180 degrees, axis Z
+ // System.err.println("Slerp #03: 1/2 * 180 degrees Z");
+ quatS.setSlerp(quat1, quat2, 0.5f);
+ quatS.rotateVector(vecHas, 0, UNIT_X, 0);
+ // System.err.println("exp0 "+Arrays.toString(UNIT_Y));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(UNIT_Y, vecHas)), Quaternion.ALLOWED_DEVIANCE);
+
+ // delta == 0%
+ quat2.setIdentity().rotateByAngleZ(FloatUtil.PI); // angle: 180 degrees, axis Z
+ // System.err.println("Slerp #04: 0 * 180 degrees Z");
+ quatS.setSlerp(quat1, quat2, 0.0f);
+ quatS.rotateVector(vecHas, 0, UNIT_X, 0);
+ // System.err.println("exp0 "+Arrays.toString(UNIT_X));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(UNIT_X, vecHas)), Quaternion.ALLOWED_DEVIANCE);
+
+ // a==b
+ quat2.setIdentity();
+ // System.err.println("Slerp #05: 1/4 * 0 degrees");
+ quatS.setSlerp(quat1, quat2, 0.25f); // 1/4 of identity .. NOP
+ quatS.rotateVector(vecHas, 0, UNIT_X, 0);
+ // System.err.println("exp0 "+Arrays.toString(UNIT_X));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(UNIT_X, vecHas)), Quaternion.ALLOWED_DEVIANCE);
+
+ // negative dot product
+ vecExp = new float[] { 0f, -FloatUtil.sin(FloatUtil.QUARTER_PI), FloatUtil.sin(FloatUtil.QUARTER_PI) };
+ quat1.setIdentity().rotateByAngleX( -2f * FloatUtil.HALF_PI); // angle: -180 degrees, axis X
+ quat2.setIdentity().rotateByAngleX( FloatUtil.HALF_PI); // angle: 90 degrees, axis X
+ // System.err.println("Slerp #06: 1/2 * 270 degrees");
+ quatS.setSlerp(quat1, quat2, 0.5f);
+ quatS.rotateVector(vecHas, 0, UNIT_Y, 0);
+ // System.err.println("exp0 "+Arrays.toString(vecExp));
+ // System.err.println("has0 "+Arrays.toString(vecHas));
+ Assert.assertEquals( 0f, Math.abs( VectorUtil.distVec3(vecExp, vecHas)), Quaternion.ALLOWED_DEVIANCE);
+
+
+ }
+
+ @Test
+ public void test26LookAt() {
+ final float[] direction = new float[3];
+ final float[] xAxis = new float[3];
+ final float[] yAxis = new float[3];
+ final float[] zAxis = new float[3];
+ final float[] vecHas = new float[3];
+
+ if( DEBUG ) System.err.println("LookAt #01");
+ VectorUtil.copyVec3(direction, 0, NEG_UNIT_X, 0);
+ final Quaternion quat = new Quaternion().setLookAt(direction, UNIT_Y, xAxis, yAxis, zAxis);
+ Assert.assertEquals(0f, VectorUtil.distVec3(direction, quat.rotateVector(vecHas, 0, UNIT_Z, 0)), Quaternion.ALLOWED_DEVIANCE);
+
+ if( DEBUG ) System.err.println("LookAt #02");
+ VectorUtil.normalizeVec3(VectorUtil.copyVec3(direction, 0, ONE, 0));
+ quat.setLookAt(direction, UNIT_Y, xAxis, yAxis, zAxis);
+ if( DEBUG )System.err.println("quat0 "+quat);
+ quat.rotateVector(vecHas, 0, UNIT_Z, 0);
+ if( DEBUG ) {
+ System.err.println("xAxis "+Arrays.toString(xAxis)+", len "+VectorUtil.normVec3(xAxis));
+ System.err.println("yAxis "+Arrays.toString(yAxis)+", len "+VectorUtil.normVec3(yAxis));
+ System.err.println("zAxis "+Arrays.toString(zAxis)+", len "+VectorUtil.normVec3(zAxis));
+ System.err.println("exp0 "+Arrays.toString(direction)+", len "+VectorUtil.normVec3(direction));
+ System.err.println("has0 "+Arrays.toString(vecHas)+", len "+VectorUtil.normVec3(vecHas));
+ }
+ // Assert.assertEquals(0f, VectorUtil.distance(direction, quat.rotateVector(vecHas, 0, UNIT_Z, 0)), Quaternion.ALLOWED_DEVIANCE);
+ Assert.assertEquals(0f, VectorUtil.distVec3(direction, vecHas), Quaternion.ALLOWED_DEVIANCE);
+
+ if( DEBUG )System.err.println("LookAt #03");
+ VectorUtil.normalizeVec3(VectorUtil.copyVec3(direction, 0, new float[] { -1f, 2f, -1f }, 0));
+ quat.setLookAt(direction, UNIT_Y, xAxis, yAxis, zAxis);
+ if( DEBUG )System.err.println("quat0 "+quat);
+ quat.rotateVector(vecHas, 0, UNIT_Z, 0);
+ if( DEBUG ) {
+ System.err.println("xAxis "+Arrays.toString(xAxis)+", len "+VectorUtil.normVec3(xAxis));
+ System.err.println("yAxis "+Arrays.toString(yAxis)+", len "+VectorUtil.normVec3(yAxis));
+ System.err.println("zAxis "+Arrays.toString(zAxis)+", len "+VectorUtil.normVec3(zAxis));
+ System.err.println("exp0 "+Arrays.toString(direction)+", len "+VectorUtil.normVec3(direction));
+ System.err.println("has0 "+Arrays.toString(vecHas)+", len "+VectorUtil.normVec3(vecHas));
+ }
+ // Assert.assertEquals(0f, VectorUtil.distance(direction, quat.rotateVector(vecHas, 0, UNIT_Z, 0)), Quaternion.ALLOWED_DEVIANCE);
+ Assert.assertEquals(0f, VectorUtil.distVec3(direction, vecHas), Quaternion.ALLOWED_DEVIANCE);
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestQuaternion01NOUI.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java b/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java
index b165a9693..883bf4362 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,25 +20,27 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.newt;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-
import com.jogamp.opengl.test.junit.util.*;
import java.lang.reflect.InvocationTargetException;
+
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.util.RectangleImmutable;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.awt.GLCanvas;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.Animator;
import com.jogamp.newt.Screen;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.newt.awt.NewtCanvasAWT;
@@ -55,6 +57,7 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
+
import javax.media.opengl.GLEventListener;
import javax.swing.JButton;
import javax.swing.JFrame;
@@ -66,7 +69,10 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
static long durationPerTest = 150; // ms
static Robot robot;
@@ -79,7 +85,7 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
boolean modLightBrighter = true;
- Color modLight(Color c) {
+ Color modLight(final Color c) {
Color c2;
if(modLightBrighter) {
c2 = c.brighter();
@@ -93,18 +99,18 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
}
class SwingGLAction implements GLEventListener {
- public void init(GLAutoDrawable glad) {
+ public void init(final GLAutoDrawable glad) {
}
- public void dispose(GLAutoDrawable glad) {
+ public void dispose(final GLAutoDrawable glad) {
}
- public void display(GLAutoDrawable glad) {
+ public void display(final GLAutoDrawable glad) {
colorPanel.setBackground(modLight(colorPanel.getBackground()));
colorPanel.repaint();
}
- public void reshape(GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
}
}
@@ -121,34 +127,34 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
button = new JButton("Click me");
button.addMouseListener(new MouseAdapter() {
- public void mouseClicked(MouseEvent e) {
+ public void mouseClicked(final MouseEvent e) {
System.err.println("Test: "+e);
}
});
panel.add(button, BorderLayout.NORTH);
colorPanel = new JPanel();
- Dimension size = new Dimension(400,100);
+ final Dimension size = new Dimension(400,100);
colorPanel.setPreferredSize(size);
colorPanel.setBorder(border);
panel.add(colorPanel, BorderLayout.SOUTH);
frame = new JFrame("PRE JOGL");
frame.addWindowListener( new WindowAdapter() {
- public void windowClosing(WindowEvent ev) {
+ public void windowClosing(final WindowEvent ev) {
windowClosing=true;
}
});
frame.setContentPane(panel);
- frame.setSize(512, 512);
- frame.setLocation(0, 0);
- frame.pack();
// AWT/Swing: From here on (post setVisible(true)
// you need to use AWT/Swing's invokeAndWait()
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.setSize(512, 512);
+ frame.setLocation(0, 0);
+ frame.pack();
frame.setVisible(true);
colorPanel.setBackground(Color.white);
colorPanel.repaint();
@@ -157,8 +163,17 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
robot = new Robot();
robot.setAutoWaitForIdle(true);
- Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
- AWTRobotUtil.clearAWTFocus(robot);
+ // NativeWindow/JOGL is not initialized yet ..
+ for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && !frame.isVisible(); wait++) {
+ Thread.sleep(AWTRobotUtil.TIME_SLICE);
+ }
+ Assert.assertEquals(true, frame.isVisible());
+
+ System.err.println("TestSwingAWTRobotUsageBeforeJOGLInitBug411.setup(): Before NativeWindow init");
+
+ NativeWindowFactory.initSingleton();
+
+ AWTRobotUtil.clearAWTFocus(robot);
AWTRobotUtil.toFrontAndRequestFocus(robot, frame);
AWTRobotUtil.requestFocus(robot, button);
@@ -184,10 +199,10 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
System.err.println("TestSwingAWTRobotUsageBeforeJOGLInitBug411.release(): End");
}
- protected void runTestGL(final Canvas canvas, GLAutoDrawable drawable)
+ protected void runTestGL(final Canvas canvas, final GLAutoDrawable drawable)
throws AWTException, InterruptedException, InvocationTargetException {
- Dimension size = new Dimension(400,400);
+ final Dimension size = new Dimension(400,400);
canvas.setPreferredSize(size);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -199,6 +214,8 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
AWTRobotUtil.toFrontAndRequestFocus(robot, frame);
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(drawable, true));
+
drawable.addGLEventListener(new GearsES2());
for(int i=0; i<100; i++) {
@@ -215,7 +232,7 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
colorPanel.setBackground(Color.blue);
drawable.addGLEventListener(new SwingGLAction());
- Point p0 = canvas.getLocationOnScreen();
+ final Point p0 = canvas.getLocationOnScreen();
p0.translate(10,10);
robot.mouseMove( (int) ( p0.getX() + .5 ) ,
(int) ( p0.getY() + .5 ) );
@@ -245,32 +262,36 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
public void test01NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException {
System.err.println("TestSwingAWTRobotUsageBeforeJOGLInitBug411.test01NewtCanvasAWT(): Start");
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
- GLWindow win0 = GLWindow.create(caps);
+ final GLWindow win0 = GLWindow.create(caps);
win0.setSize(100,100);
win0.setVisible(true);
- Screen screen = win0.getScreen();
- win0.setPosition(screen.getWidth()-150, 0);
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(win0, true));
+
+ final Screen screen = win0.getScreen();
+ final RectangleImmutable screenBoundsInWinU = screen.getViewportInWindowUnits();
+ win0.setPosition(screenBoundsInWinU.getX()-150, 0);
win0.addGLEventListener(new GearsES2());
- Animator anim = new Animator(win0);
+ final Animator anim = new Animator(win0);
anim.start();
- GLWindow win1 = GLWindow.create(caps);
- NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(win1);
+ final GLWindow win1 = GLWindow.create(caps);
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(win1);
anim.add(win1);
runTestGL(newtCanvasAWT, win1);
win0.destroy();
- Assert.assertEquals(false, win0.isNativeValid());
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(win0, false));
+ Assert.assertEquals(false, win0.isNativeValid());
Assert.assertEquals(true, anim.isAnimating()); // due to newtCanvasAWT/win1
newtCanvasAWT.destroy(); // destroys both newtCanvasAWT/win1
Assert.assertEquals(false, win1.isNativeValid());
Assert.assertEquals(false, win0.isNativeValid());
Assert.assertEquals(true, anim.isAnimating());
-
+
Assert.assertEquals(true, anim.stop());
Assert.assertEquals(false, anim.isAnimating());
@@ -280,10 +301,10 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
@Test
public void test02GLCanvas() throws AWTException, InterruptedException, InvocationTargetException {
System.err.println("TestSwingAWTRobotUsageBeforeJOGLInitBug411.test02GLCanvas(): Start");
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
- Animator anim = new Animator();
+ final Animator anim = new Animator();
anim.start();
/**
@@ -299,14 +320,13 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
anim.add(win0);
*/
- GLCanvas glCanvas = new GLCanvas(caps);
+ final GLCanvas glCanvas = new GLCanvas(caps);
anim.add(glCanvas);
runTestGL(glCanvas, glCanvas);
- Assert.assertEquals(true, anim.isAnimating());
anim.remove(glCanvas);
Assert.assertEquals(false, anim.isAnimating());
-
+
/**
win0.destroy();
Assert.assertEquals(true, anim.isAnimating());
@@ -315,15 +335,15 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase {
System.err.println("TestSwingAWTRobotUsageBeforeJOGLInitBug411.test02GLCanvas(): End");
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBuffer2File.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBuffer2File.java
index 9506d00e5..989bd5e3a 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBuffer2File.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBuffer2File.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.offscreen;
import java.io.IOException;
@@ -35,12 +35,12 @@ import java.io.File;
public class ReadBuffer2File extends ReadBufferBase {
- public ReadBuffer2File(GLDrawable externalRead) {
+ public ReadBuffer2File(final GLDrawable externalRead) {
super(externalRead, false);
}
@Override
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
super.dispose(drawable);
}
int shotNum = 0;
@@ -50,18 +50,18 @@ public class ReadBuffer2File extends ReadBufferBase {
return;
}
- File file = File.createTempFile("shot" + shotNum + "-", ".png");
+ final File file = File.createTempFile("shot" + shotNum + "-", ".png");
readBufferUtil.write(file);
System.out.println("Wrote: " + file.getAbsolutePath() + ", ...");
shotNum++;
}
@Override
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
super.display(drawable);
try {
copyTextureData2File();
- } catch (IOException ex) {
+ } catch (final IOException ex) {
throw new RuntimeException("can not read buffer to file", ex);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBuffer2Screen.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBuffer2Screen.java
index 5bdef2869..3f9a64f5b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBuffer2Screen.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBuffer2Screen.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,21 +20,23 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.offscreen;
import java.nio.*;
+
import javax.media.opengl.*;
import javax.media.opengl.fixedfunc.*;
import com.jogamp.opengl.util.*;
import javax.media.opengl.fixedfunc.GLPointerFunc;
+
import com.jogamp.opengl.util.texture.TextureCoords;
import com.jogamp.opengl.util.GLArrayDataClient;
import com.jogamp.opengl.util.GLArrayDataServer;
@@ -46,28 +48,28 @@ public class ReadBuffer2Screen extends ReadBufferBase {
boolean enableBufferAlways = false; // FIXME
boolean enableBufferVBO = true; // FIXME
- public ReadBuffer2Screen (GLDrawable externalRead) {
+ public ReadBuffer2Screen (final GLDrawable externalRead) {
super(externalRead, true);
}
@Override
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
super.init(drawable);
- GL gl = drawable.getGL();
+ final GL gl = drawable.getGL();
pmvMatrix = new PMVMatrix();
- float f_edge = 1f;
+ final float f_edge = 1f;
if(null==readTextureVertices) {
- //readTextureVertices = GLArrayDataClient.createFixed(gl, GLPointerFunc.GL_VERTEX_ARRAY, "mgl_Vertex",
+ //readTextureVertices = GLArrayDataClient.createFixed(gl, GLPointerFunc.GL_VERTEX_ARRAY, "mgl_Vertex",
// 2, GL.GL_FLOAT, true, 4);
- readTextureVertices = GLArrayDataServer.createFixed(GLPointerFunc.GL_VERTEX_ARRAY, 2,
+ readTextureVertices = GLArrayDataServer.createFixed(GLPointerFunc.GL_VERTEX_ARRAY, 2,
GL.GL_FLOAT, true, 4, GL.GL_STATIC_DRAW);
readTextureVertices.setEnableAlways(enableBufferAlways);
readTextureVertices.setVBOEnabled(enableBufferVBO);
{
- FloatBuffer vb = (FloatBuffer)readTextureVertices.getBuffer();
+ final FloatBuffer vb = (FloatBuffer)readTextureVertices.getBuffer();
vb.put(-f_edge); vb.put(-f_edge);
vb.put( f_edge); vb.put(-f_edge);
vb.put(-f_edge); vb.put( f_edge);
@@ -82,10 +84,10 @@ public class ReadBuffer2Screen extends ReadBufferBase {
}
@Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
super.reshape(drawable, x, y, width, height);
- GL gl = drawable.getGL();
+ final GL gl = drawable.getGL();
gl.glViewport(0, 0, width, height);
@@ -101,30 +103,30 @@ public class ReadBuffer2Screen extends ReadBufferBase {
}
// Identity ..
- pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
pmvMatrix.glTranslatef(0, 0, -2.5f);
if(null!=glM) {
- glM.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+ glM.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
glM.glLoadMatrixf(pmvMatrix.glGetMvMatrixf());
}
// Set location in front of camera
- pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, 1.0f, 100.0f);
if(null!=glM) {
- glM.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ glM.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
glM.glLoadMatrixf(pmvMatrix.glGetPMatrixf());
}
}
@Override
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
super.dispose(drawable);
}
- void renderOffscreenTexture(GL gl) {
+ void renderOffscreenTexture(final GL gl) {
if(!readBufferUtil.isValid()) return;
// Now draw one quad with the texture
@@ -152,15 +154,15 @@ public class ReadBuffer2Screen extends ReadBufferBase {
readBufferUtil.getTexture().disable(gl);
}
- void updateTextureCoords(GL gl, boolean force) {
+ void updateTextureCoords(final GL gl, final boolean force) {
if(force || null==readTextureCoords) {
- readTextureCoords = GLArrayDataServer.createFixed(GLPointerFunc.GL_TEXTURE_COORD_ARRAY, 2,
+ readTextureCoords = GLArrayDataServer.createFixed(GLPointerFunc.GL_TEXTURE_COORD_ARRAY, 2,
GL.GL_FLOAT, true, 4, GL.GL_STATIC_DRAW);
readTextureCoords.setEnableAlways(enableBufferAlways);
readTextureCoords.setVBOEnabled(enableBufferVBO);
{
- TextureCoords coords = readBufferUtil.getTexture().getImageTexCoords();
- FloatBuffer cb = (FloatBuffer)readTextureCoords.getBuffer();
+ final TextureCoords coords = readBufferUtil.getTexture().getImageTexCoords();
+ final FloatBuffer cb = (FloatBuffer)readTextureCoords.getBuffer();
cb.put(coords.left()); cb.put(coords.bottom());
cb.put(coords.right()); cb.put(coords.bottom());
cb.put(coords.left()); cb.put(coords.top());
@@ -172,12 +174,12 @@ public class ReadBuffer2Screen extends ReadBufferBase {
}
@Override
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
super.display(drawable);
- GL gl = drawable.getGL();
+ final GL gl = drawable.getGL();
- gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
if(gl instanceof GLLightingFunc) {
((GLLightingFunc)gl).glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java
index f8e064a4e..e834775fc 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.offscreen;
import javax.media.opengl.*;
@@ -40,12 +40,12 @@ public class ReadBufferBase implements GLEventListener {
GLReadBufferUtil readBufferUtil;
- public ReadBufferBase (GLDrawable externalRead, boolean write2Texture) {
+ public ReadBufferBase (final GLDrawable externalRead, final boolean write2Texture) {
this.externalRead = externalRead ;
this.readBufferUtil = new GLReadBufferUtil(false, write2Texture);
}
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
GL _gl = drawable.getGL();
_gl.glGetError(); // flush error ..
@@ -53,7 +53,7 @@ public class ReadBufferBase implements GLEventListener {
if(glDebug) {
try {
_gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, _gl, null) );
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new RuntimeException("can not set debug pipeline", e);
}
}
@@ -61,7 +61,7 @@ public class ReadBufferBase implements GLEventListener {
if(glTrace) {
try {
_gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, _gl, new Object[] { System.err } ) );
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new RuntimeException("can not set trace pipeline", e);
}
}
@@ -77,14 +77,14 @@ public class ReadBufferBase implements GLEventListener {
System.out.println("---------------------------");
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
}
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
readBufferUtil.dispose(drawable.getGL());
}
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
readBufferUtil.readPixels(drawable.getGL(), false);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java
index 974e32289..5c2e80170 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.offscreen;
import javax.media.opengl.*;
@@ -46,29 +46,29 @@ public class Surface2File implements SurfaceUpdatedListener {
final GLReadBufferUtil readBufferUtil;
int shotNum = 0;
- public Surface2File(String filename, boolean alpha) {
+ public Surface2File(final String filename, final boolean alpha) {
this.filename = filename;
- this.alpha = alpha;
+ this.alpha = alpha;
this.readBufferUtil = new GLReadBufferUtil(alpha, false);
}
-
- public void dispose(GL gl) {
+
+ public void dispose(final GL gl) {
readBufferUtil.dispose(gl);
}
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
if (updater instanceof GLDrawable) {
- GLDrawable drawable = (GLDrawable) updater;
- GLContext ctx = GLContext.getCurrent();
+ final GLDrawable drawable = (GLDrawable) updater;
+ final GLContext ctx = GLContext.getCurrent();
if (null != ctx && ctx.getGLDrawable() == drawable) {
- GL gl = ctx.getGL();
+ final GL gl = ctx.getGL();
// FIXME glFinish() is an expensive paranoia sync, should not be necessary due to spec
gl.glFinish();
if(readBufferUtil.readPixels(gl, false)) {
gl.glFinish();
try {
surface2File();
- } catch (IOException ex) {
+ } catch (final IOException ex) {
throw new RuntimeException("can not write survace to file", ex);
}
}
@@ -85,7 +85,7 @@ public class Surface2File implements SurfaceUpdatedListener {
final String pfmt = alpha ? "rgba" : "rgb_" ;
new PrintWriter(sw).printf("%s-I_%s-%04d.png", filename, pfmt, shotNum);
}
- File file = new File(sw.toString());
+ final File file = new File(sw.toString());
readBufferUtil.write(file);
shotNum++;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen01GLPBufferNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen01GLPBufferNEWT.java
index 2ed471436..78224de49 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen01GLPBufferNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen01GLPBufferNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.offscreen;
import com.jogamp.newt.Display;
@@ -38,6 +38,8 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.opengl.*;
@@ -45,6 +47,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
import java.io.IOException;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestOffscreen01GLPBufferNEWT extends UITestCase {
static GLProfile glpDefault;
static GLDrawableFactory glDrawableFactory;
@@ -56,7 +59,7 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase {
glpDefault = GLProfile.getDefault();
Assert.assertNotNull(glpDefault);
glDrawableFactory = GLDrawableFactory.getFactory(glpDefault);
- System.out.println("INFO: PBuffer supported: "+ glDrawableFactory.canCreateGLPbuffer(null));
+ System.out.println("INFO: PBuffer supported: "+ glDrawableFactory.canCreateGLPbuffer(null, glpDefault));
width = 640;
height = 480;
}
@@ -69,22 +72,22 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase {
public void init() {
capsDefault = new GLCapabilities(glpDefault);
Assert.assertNotNull(capsDefault);
- capsDefault.setAlphaBits(1); // req. alpha channel
+ capsDefault.setAlphaBits(1); // req. alpha channel
}
- private void do01OffscreenWindowPBuffer(GLCapabilities caps) {
- Display display = NewtFactory.createDisplay(null); // local display
+ private void do01OffscreenWindowPBuffer(final GLCapabilities caps) {
+ final Display display = NewtFactory.createDisplay(null); // local display
Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
Assert.assertNotNull(screen);
- Window window = NewtFactory.createWindow(screen, caps);
+ final Window window = NewtFactory.createWindow(screen, caps);
Assert.assertNotNull(window);
window.setSize(width, height);
- GLWindow glWindow = GLWindow.create(window);
+ final GLWindow glWindow = GLWindow.create(window);
Assert.assertNotNull(glWindow);
glWindow.setVisible(true);
- GLEventListener demo = new RedSquareES2();
+ final GLEventListener demo = new RedSquareES2();
WindowUtilNEWT.setDemoFields(demo, window, glWindow, false);
glWindow.addGLEventListener(demo);
@@ -108,32 +111,32 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase {
@Test
public void test01aOffscreenWindowPBuffer() {
- if(!glDrawableFactory.canCreateGLPbuffer(null)) {
+ if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) {
System.out.println("WARNING: PBuffer not supported on this platform - cannot test");
return;
}
- GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
+ final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
do01OffscreenWindowPBuffer(caps2);
}
@Test
public void test01bOffscreenWindowPBufferStencil() {
- if(!glDrawableFactory.canCreateGLPbuffer(null)) {
+ if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) {
System.out.println("WARNING: PBuffer not supported on this platform - cannot test");
return;
}
- GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
+ final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
caps2.setStencilBits(8);
do01OffscreenWindowPBuffer(caps2);
}
@Test
public void test01cOffscreenWindowPBufferStencilAlpha() {
- if(!glDrawableFactory.canCreateGLPbuffer(null)) {
+ if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) {
System.out.println("WARNING: PBuffer not supported on this platform - cannot test");
return;
}
- GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
+ final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
caps2.setStencilBits(8);
caps2.setAlphaBits(8);
do01OffscreenWindowPBuffer(caps2);
@@ -141,11 +144,11 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase {
@Test
public void test01cOffscreenWindowPBuffer555() {
- if(!glDrawableFactory.canCreateGLPbuffer(null)) {
+ if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) {
System.out.println("WARNING: PBuffer not supported on this platform - cannot test");
return;
}
- GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
+ final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
caps2.setRedBits(5);
caps2.setGreenBits(5);
caps2.setBlueBits(5);
@@ -154,19 +157,20 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase {
@Test
public void test02Offscreen3Windows1DisplayPBuffer() {
- if(!glDrawableFactory.canCreateGLPbuffer(null)) {
+ if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) {
System.out.println("WARNING: PBuffer not supported on this platform - cannot test");
return;
}
- GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
- int winnum = 3, i;
- Window windows[] = new Window[winnum];
- GLWindow glWindows[] = new GLWindow[winnum];
- GLEventListener demos[] = new GLEventListener[winnum];
+ final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
+ final int winnum = 3;
+ int i;
+ final Window windows[] = new Window[winnum];
+ final GLWindow glWindows[] = new GLWindow[winnum];
+ final GLEventListener demos[] = new GLEventListener[winnum];
- Display display = NewtFactory.createDisplay(null); // local display
+ final Display display = NewtFactory.createDisplay(null); // local display
Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
Assert.assertNotNull(screen);
for(i=0; i<winnum; i++) {
@@ -207,17 +211,18 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase {
@Test
public void test03Offscreen3Windows3DisplaysPBuffer() {
- if(!glDrawableFactory.canCreateGLPbuffer(null)) {
+ if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) {
System.out.println("WARNING: PBuffer not supported on this platform - cannot test");
return;
}
- GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
- int winnum = 3, i;
- Display displays[] = new Display[winnum];
- Screen screens[] = new Screen[winnum];
- Window windows[] = new Window[winnum];
- GLWindow glWindows[] = new GLWindow[winnum];
- GLEventListener demos[] = new GLEventListener[winnum];
+ final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
+ final int winnum = 3;
+ int i;
+ final Display displays[] = new Display[winnum];
+ final Screen screens[] = new Screen[winnum];
+ final Window windows[] = new Window[winnum];
+ final GLWindow glWindows[] = new GLWindow[winnum];
+ final GLEventListener demos[] = new GLEventListener[winnum];
for(i=0; i<winnum; i++) {
System.out.println("Create Window "+i);
@@ -260,25 +265,25 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase {
@Test
public void test04OffscreenSnapshotWithDemoPBuffer() {
- if(!glDrawableFactory.canCreateGLPbuffer(null)) {
+ if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) {
System.out.println("WARNING: PBuffer not supported on this platform - cannot test");
return;
}
- GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
+ final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(capsDefault, false, true, false);
System.out.println("Create Window 1");
- Display display = NewtFactory.createDisplay(null); // local display
+ final Display display = NewtFactory.createDisplay(null); // local display
Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
Assert.assertNotNull(screen);
- Window window = NewtFactory.createWindow(screen, caps2);
+ final Window window = NewtFactory.createWindow(screen, caps2);
Assert.assertNotNull(window);
window.setSize(width, height);
- GLWindow glWindow = GLWindow.create(window);
+ final GLWindow glWindow = GLWindow.create(window);
Assert.assertNotNull(glWindow);
glWindow.setVisible(true);
- WindowUtilNEWT.run(getSimpleTestName("."), glWindow, new RedSquareES2(), null, null, null, null,
+ WindowUtilNEWT.run(getSimpleTestName("."), glWindow, new RedSquareES2(), null, null, null, null,
2 /* frames */, true /*snapshot*/, false /*debug*/);
if(null!=glWindow) {
@@ -295,8 +300,8 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase {
}
}
- public static void main(String args[]) throws IOException {
- String tstname = TestOffscreen01GLPBufferNEWT.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestOffscreen01GLPBufferNEWT.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen02BitmapNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen02BitmapNEWT.java
index 0701d883c..2202b754c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen02BitmapNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen02BitmapNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.offscreen;
@@ -36,6 +36,8 @@ import com.jogamp.newt.Window;
import com.jogamp.newt.opengl.GLWindow;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.opengl.*;
@@ -44,35 +46,36 @@ import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1;
import java.io.IOException;
/**
- * Using ES1 GL demo, since pixmap might not be hw accelerated,
- * hence it is possible to not have GLSL.
+ * Using ES1 GL demo, since pixmap might not be hw accelerated,
+ * hence it is possible to not have GLSL.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestOffscreen02BitmapNEWT extends UITestCase {
static final int width = 640, height = 480;
@Test
public void test11OffscreenWindowPixmap() {
- // we need to stay w/ generic profile GL2ES1
- // since software rasterizer might be required (pixmap/bitmap)
- GLProfile glp = GLProfile.get(GLProfile.GL2ES1);
+ // we need to stay w/ generic profile GL2ES1
+ // since software rasterizer might be required (pixmap/bitmap)
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES1);
Assert.assertNotNull(glp);
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, false, false);
+ final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, false, false);
- Display display = NewtFactory.createDisplay(null); // local display
+ final Display display = NewtFactory.createDisplay(null); // local display
Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
Assert.assertNotNull(screen);
- Window window = NewtFactory.createWindow(screen, caps2);
+ final Window window = NewtFactory.createWindow(screen, caps2);
Assert.assertNotNull(window);
window.setSize(width, height);
- GLWindow glWindow = GLWindow.create(window);
+ final GLWindow glWindow = GLWindow.create(window);
Assert.assertNotNull(glWindow);
glWindow.setVisible(true);
- GLEventListener demo = new RedSquareES1();
+ final GLEventListener demo = new RedSquareES1();
WindowUtilNEWT.setDemoFields(demo, window, glWindow, false);
glWindow.addGLEventListener(demo);
@@ -96,27 +99,27 @@ public class TestOffscreen02BitmapNEWT extends UITestCase {
@Test
public void test14OffscreenSnapshotWithDemoPixmap() {
- // we need to stay w/ generic profile GL2ES1
- // since software rasterizer might be required (pixmap/bitmap)
- GLProfile glp = GLProfile.get(GLProfile.GL2ES1);
+ // we need to stay w/ generic profile GL2ES1
+ // since software rasterizer might be required (pixmap/bitmap)
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES1);
Assert.assertNotNull(glp);
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, false, false);
+ final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, false, false);
- Display display = NewtFactory.createDisplay(null); // local display
+ final Display display = NewtFactory.createDisplay(null); // local display
Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
Assert.assertNotNull(screen);
- Window window = NewtFactory.createWindow(screen, caps2);
+ final Window window = NewtFactory.createWindow(screen, caps2);
Assert.assertNotNull(window);
window.setSize(width, height);
- GLWindow glWindow = GLWindow.create(window);
+ final GLWindow glWindow = GLWindow.create(window);
Assert.assertNotNull(glWindow);
glWindow.setVisible(true);
- WindowUtilNEWT.run(getSimpleTestName("."), glWindow, new RedSquareES1(), null, null, null, null,
+ WindowUtilNEWT.run(getSimpleTestName("."), glWindow, new RedSquareES1(), null, null, null, null,
2 /* frames */, true /*snapshot*/, false /*debug*/);
if(null!=glWindow) {
@@ -132,8 +135,8 @@ public class TestOffscreen02BitmapNEWT extends UITestCase {
display.destroy();
}
}
- public static void main(String args[]) throws IOException {
- String tstname = TestOffscreen02BitmapNEWT.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestOffscreen02BitmapNEWT.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/WindowUtilNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/WindowUtilNEWT.java
index efca752a1..9e66a614e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/WindowUtilNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/WindowUtilNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.offscreen;
import com.jogamp.opengl.test.junit.util.*;
@@ -40,15 +40,15 @@ import com.jogamp.newt.opengl.*;
public class WindowUtilNEWT {
- public static GLCapabilities fixCaps(GLCapabilities caps, boolean onscreen, boolean pbuffer, boolean undecorated) {
- GLCapabilities caps2 = (GLCapabilities) caps.cloneMutable();
+ public static GLCapabilities fixCaps(final GLCapabilities caps, final boolean onscreen, final boolean pbuffer, final boolean undecorated) {
+ final GLCapabilities caps2 = (GLCapabilities) caps.cloneMutable();
caps2.setOnscreen(onscreen);
caps2.setPBuffer(!onscreen && pbuffer);
caps2.setDoubleBuffered(!onscreen);
return caps2;
}
- public static void setDemoFields(GLEventListener demo, Window window, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final Window window, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(window);
if(debug) {
@@ -60,9 +60,9 @@ public class WindowUtilNEWT {
}
}
- public static void run(String testName, GLWindow windowOffScreen, GLEventListener demo,
- GLWindow windowOnScreenBlit, WindowListener wl, MouseListener ml,
- SurfaceUpdatedListener ul, int frames, boolean snapshot, boolean debug) {
+ public static void run(final String testName, final GLWindow windowOffScreen, final GLEventListener demo,
+ final GLWindow windowOnScreenBlit, final WindowListener wl, final MouseListener ml,
+ final SurfaceUpdatedListener ul, final int frames, final boolean snapshot, final boolean debug) {
Assert.assertNotNull(windowOffScreen);
Assert.assertNotNull(demo);
@@ -79,14 +79,14 @@ public class WindowUtilNEWT {
windowOnScreenBlit.setVisible(true);
}
- GLDrawable readDrawable = windowOffScreen.getContext().getGLDrawable() ;
+ final GLDrawable readDrawable = windowOffScreen.getContext().getGLDrawable() ;
if ( null != windowOnScreenBlit ) {
- ReadBuffer2Screen readDemo = new ReadBuffer2Screen( readDrawable ) ;
+ final ReadBuffer2Screen readDemo = new ReadBuffer2Screen( readDrawable ) ;
windowOnScreenBlit.addGLEventListener(readDemo);
}
if(snapshot) {
final boolean alpha = windowOffScreen.getChosenGLCapabilities().getAlphaBits()>0;
- Surface2File s2f = new Surface2File(testName, alpha);
+ final Surface2File s2f = new Surface2File(testName, alpha);
windowOffScreen.addSurfaceUpdatedListener(s2f);
}
if(null!=ul) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit01AWT.java
new file mode 100644
index 000000000..0db2afc32
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit01AWT.java
@@ -0,0 +1,329 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.perf;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Tests multiple [GLJPanels, GLCanvas or NewtCanvasAWT] in a JFrame's Grid
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPerf001GLJPanelInit01AWT extends UITestCase {
+ final long INIT_TIMEOUT = 10L*1000L; // 10s
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ static enum CanvasType { GLCanvas_T, GLJPanel_T, NewtCanvasAWT_T };
+
+ static class GLADComp {
+ GLADComp(final GLAutoDrawable glad, final Component comp) {
+ this.glad = glad;
+ this.comp = comp;
+ }
+ final GLAutoDrawable glad;
+ final Component comp;
+ }
+ public void test(final GLCapabilitiesImmutable caps, final boolean useGears, final int width, final int height, final int rows,
+ final int columns, final CanvasType canvasType, final boolean useAnim) {
+ final GLAnimatorControl animator = useAnim ? new Animator() : null;
+
+ final JFrame frame;
+ final JPanel panel;
+ final List<NewtCanvasAWT> newtCanvasAWTList = new ArrayList<NewtCanvasAWT>();
+
+ panel = new JPanel();
+ frame = new JFrame(getSimpleTestName("."));
+
+ panel.setLayout(new GridLayout(rows, columns));
+ // panel.setBounds(0, 0, width, height);
+ final int panelCount = rows*columns;
+ final Dimension eSize = new Dimension(width/columns, height/rows);
+ final long[] t = new long[10];
+ if( wait ) {
+ UITestCase.waitForKey("Pre-Init");
+ }
+ System.err.println("INIT START");
+ initCount.set(0);
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ t[0] = Platform.currentTimeMillis();
+ for(int i=0; i<panelCount; i++) {
+ final GLADComp gladComp;
+ switch(canvasType) {
+ case GLCanvas_T:
+ gladComp = createGLCanvas(caps, useGears, animator, eSize);
+ break;
+ case GLJPanel_T:
+ gladComp = createGLJPanel(caps, useGears, animator, eSize);
+ break;
+ case NewtCanvasAWT_T:
+ gladComp = createNewtCanvasAWT(caps, useGears, animator, eSize);
+ newtCanvasAWTList.add((NewtCanvasAWT)gladComp.comp);
+ break;
+ default: throw new InternalError("XXX");
+ }
+ gladComp.glad.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ initCount.getAndIncrement();
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {}
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ });
+ panel.add(gladComp.comp);
+ }
+ t[1] = Platform.currentTimeMillis();
+ frame.getContentPane().add(panel);
+
+ // frame.validate();
+ frame.pack();
+ frame.setVisible(true);
+ t[2] = Platform.currentTimeMillis();
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while( panelCount > initCount.get() && INIT_TIMEOUT > t1 - t0 ) {
+ try {
+ Thread.sleep(100);
+ System.err.println("Sleep initialized: "+initCount.get()+"/"+panelCount);
+ } catch (final InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ t1 = System.currentTimeMillis();
+ }
+ t[3] = Platform.currentTimeMillis();
+ final double panelCountF = initCount.get();
+ System.err.printf("P: %d %s:%n\tctor\t%6d/t %6.2f/1%n\tvisible\t%6d/t %6.2f/1%n\tsum-i\t%6d/t %6.2f/1%n",
+ initCount.get(),
+ canvasType,
+ t[1]-t[0], (t[1]-t[0])/panelCountF,
+ t[3]-t[1], (t[3]-t[1])/panelCountF,
+ t[3]-t[0], (t[3]-t[0])/panelCountF);
+ System.err.println("INIT END: "+initCount.get()+"/"+panelCount);
+ if( wait ) {
+ UITestCase.waitForKey("Post-Init");
+ }
+ if( null != animator ) {
+ animator.start();
+ }
+ try {
+ Thread.sleep(duration);
+ } catch (final InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ if( null != animator ) {
+ animator.stop();
+ }
+ t[4] = Platform.currentTimeMillis();
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ while( !newtCanvasAWTList.isEmpty() ) {
+ newtCanvasAWTList.remove(0).destroy(); // removeNotify does not destroy GLWindow
+ }
+ frame.dispose();
+ } } );
+ } catch (final Exception e1) {
+ e1.printStackTrace();
+ }
+ final long ti_net = (t[4]-t[0])-duration;
+ System.err.printf("T: duration %d %d%n\ttotal-d\t%6d/t %6.2f/1%n\ttotal-i\t%6d/t %6.2f/1%n",
+ duration, t[4]-t[3],
+ t[4]-t[0], (t[4]-t[0])/panelCountF,
+ ti_net, ti_net/panelCountF);
+ System.err.println("Total: "+(t[4]-t[0]));
+ }
+
+ private GLADComp createNewtCanvasAWT(final GLCapabilitiesImmutable caps, final boolean useGears, final GLAnimatorControl anim, final Dimension size) {
+ final GLWindow window = GLWindow.create(caps);
+ final NewtCanvasAWT canvas = new NewtCanvasAWT(window);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ if( useGears ) {
+ final GearsES2 g = new GearsES2(0);
+ g.setVerbose(false);
+ window.addGLEventListener(g);
+ }
+ if( null != anim ) {
+ anim.add(window);
+ }
+ return new GLADComp(window, canvas);
+ }
+ private GLADComp createGLCanvas(final GLCapabilitiesImmutable caps, final boolean useGears, final GLAnimatorControl anim, final Dimension size) {
+ final GLCanvas canvas = new GLCanvas(caps);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ if( useGears ) {
+ canvas.addGLEventListener(new GearsES2(0));
+ }
+ if( null != anim ) {
+ anim.add(canvas);
+ }
+ return new GLADComp(canvas, canvas);
+ }
+ private GLADComp createGLJPanel(final GLCapabilitiesImmutable caps, final boolean useGears, final GLAnimatorControl anim, final Dimension size) {
+ final GLJPanel canvas = new GLJPanel(caps);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ if( useGears ) {
+ canvas.addGLEventListener(new GearsES2(0));
+ }
+ if( null != anim ) {
+ anim.add(canvas);
+ }
+ return new GLADComp(canvas, canvas);
+ }
+
+ // @Test
+ public void test01NopGLJPanel() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, width, height, rows, cols, CanvasType.GLJPanel_T, false /*useAnim*/);
+ }
+
+ // @Test
+ public void test02NopGLJPanelBMP() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ caps.setBitmap(true);
+ test(caps, false /*useGears*/, width, height, rows, cols, CanvasType.GLJPanel_T, false /*useAnim*/);
+ }
+
+ // @Test
+ public void test03NopGLCanvas() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, width, height, rows, cols, CanvasType.GLCanvas_T, false /*useAnim*/);
+ }
+
+ // @Test
+ public void test11GearsGLJPanel() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), true /*useGears*/, width, height, rows, cols, CanvasType.GLJPanel_T, true /*useAnim*/);
+ }
+
+ // @Test
+ public void test13GearsGLCanvas() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), true /*useGears*/, width, height, rows, cols, CanvasType.GLCanvas_T, true /*useAnim*/);
+ }
+
+ @Test
+ public void test14GearsNewtCanvasAWT() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), true /*useGears*/, width, height, rows, cols, CanvasType.NewtCanvasAWT_T, true /*useAnim*/);
+ }
+
+ static long duration = 0; // ms
+ static boolean wait = false;
+ static int width = 800, height = 600, rows = 5, cols = 5;
+
+ AtomicInteger initCount = new AtomicInteger(0);
+
+ public static void main(final String[] args) {
+ CanvasType canvasType = CanvasType.GLJPanel_T;
+ boolean useGears = false, manual=false;
+ boolean waitMain = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-width")) {
+ width = MiscUtils.atoi(args[++i], width);
+ } else if(args[i].equals("-height")) {
+ height = MiscUtils.atoi(args[++i], height);
+ } else if(args[i].equals("-rows")) {
+ rows = MiscUtils.atoi(args[++i], rows);
+ } else if(args[i].equals("-cols")) {
+ cols = MiscUtils.atoi(args[++i], cols);
+ } else if(args[i].equals("-type")) {
+ i++;
+ canvasType = CanvasType.valueOf(args[i]);
+ manual = true;
+ } else if(args[i].equals("-gears")) {
+ useGears = true;
+ } else if(args[i].equals("-wait")) {
+ wait = true;
+ manual = true;
+ } else if(args[i].equals("-waitMain")) {
+ waitMain = true;
+ manual = true;
+ } else if(args[i].equals("-manual")) {
+ manual = true;
+ }
+ }
+ if( waitMain ) {
+ UITestCase.waitForKey("Main-Start");
+ }
+ if( manual ) {
+ GLProfile.initSingleton();
+ final TestPerf001GLJPanelInit01AWT demo = new TestPerf001GLJPanelInit01AWT();
+ demo.test(null, useGears, width, height, rows, cols, canvasType, useGears /*useAnim*/);
+ } else {
+ org.junit.runner.JUnitCore.main(TestPerf001GLJPanelInit01AWT.class.getName());
+ }
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit02AWT.java
new file mode 100644
index 000000000..9f2e25fd7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit02AWT.java
@@ -0,0 +1,512 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.perf;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Tests multiple JFrames each with a [GLJPanels, GLCanvas or NewtCanvasAWT]
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPerf001GLJPanelInit02AWT extends UITestCase {
+ final long INIT_TIMEOUT = 10L*1000L; // 10s
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ static enum CanvasType { NOP_T, GLCanvas_T, GLJPanel_T, NewtCanvasAWT_T };
+
+ static class GLADComp {
+ GLADComp(final GLAutoDrawable glad, final Component comp) {
+ this.glad = glad;
+ this.comp = comp;
+ }
+ final GLAutoDrawable glad;
+ final Component comp;
+ }
+
+ public void test(final GLCapabilitiesImmutable caps, final boolean useGears, final boolean skipGLOrientationVerticalFlip, final int width,
+ final int height, final int frameCount, final boolean initMT,
+ final boolean useSwingDoubleBuffer, final CanvasType canvasType, final boolean useAnim, final boolean overlap) {
+ final GLAnimatorControl animator;
+ if( useAnim ) {
+ animator = new Animator();
+ } else {
+ animator = null;
+ }
+ final int eWidth, eHeight;
+ {
+ final int cols = (int)Math.round(Math.sqrt(frameCount));
+ final int rows = frameCount / cols;
+ eWidth = width/cols-32;
+ eHeight = height/rows-32;
+ }
+ System.err.println("Frame size: "+width+"x"+height+" -> "+frameCount+" x "+eWidth+"x"+eHeight+", overlap "+overlap);
+ System.err.println("SkipGLOrientationVerticalFlip "+skipGLOrientationVerticalFlip+", useGears "+useGears+", initMT "+initMT+", useAnim "+useAnim);
+ final JFrame[] frame = new JFrame[frameCount];
+ final List<NewtCanvasAWT> newtCanvasAWTList = new ArrayList<NewtCanvasAWT>();
+
+ final long[] t = new long[10];
+ if( wait ) {
+ UITestCase.waitForKey("Pre-Init");
+ }
+ System.err.println("INIT START");
+ initCount.set(0);
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ t[0] = Platform.currentTimeMillis();
+ int x = 32, y = 32;
+ for(int i=0; i<frameCount; i++) {
+ frame[i] = new JFrame(i+"/"+frameCount);
+ frame[i].setLocation(x, y);
+ if(!overlap) {
+ x+=eWidth+32;
+ if(x>=width) {
+ x=32;
+ y+=eHeight+32;
+ }
+ }
+ final JPanel panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.setDoubleBuffered(useSwingDoubleBuffer);
+ // panel.setBounds(0, 0, width, height);
+ final Dimension eSize = new Dimension(eWidth, eHeight);
+ final GLADComp gladComp;
+ switch(canvasType) {
+ case GLCanvas_T:
+ gladComp = createGLCanvas(caps, useGears, animator, eSize);
+ break;
+ case GLJPanel_T:
+ gladComp = createGLJPanel(initMT, useSwingDoubleBuffer, caps, useGears, skipGLOrientationVerticalFlip, animator, eSize);
+ break;
+ case NewtCanvasAWT_T:
+ gladComp = createNewtCanvasAWT(caps, useGears, animator, eSize);
+ newtCanvasAWTList.add((NewtCanvasAWT)gladComp.comp);
+ break;
+ case NOP_T:
+ gladComp = null;
+ break;
+ default: throw new InternalError("XXX");
+ }
+
+ if( null != gladComp ) {
+ gladComp.glad.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ initCount.incrementAndGet();
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {}
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ });
+ panel.add(gladComp.comp);
+ } else {
+ @SuppressWarnings("serial")
+ final JTextArea c = new JTextArea("area "+i) {
+ boolean initialized = false, added = false;
+ int reshapeWidth=0, reshapeHeight=0;
+ @Override
+ public void addNotify() {
+ added = true;
+ super.addNotify();
+ }
+ @SuppressWarnings("deprecation")
+ @Override
+ public void reshape(final int x, final int y, final int width, final int height) {
+ super.reshape(x, y, width, height);
+ reshapeWidth = width; reshapeHeight = height;
+ }
+ @Override
+ protected void paintComponent(final Graphics g) {
+ super.paintComponent(g);
+ if( !initialized && added && reshapeWidth > 0 && reshapeHeight > 0 && isDisplayable() ) {
+ initialized = true;
+ initCount.incrementAndGet();
+ }
+ }
+ };
+ c.setEditable(false);
+ c.setSize(eSize);
+ c.setPreferredSize(eSize);
+ panel.add(c);
+ }
+ frame[i].getContentPane().add(panel);
+
+ // frame.validate();
+ frame[i].pack();
+ }
+ t[1] = Platform.currentTimeMillis();
+ for(int i=0; i<frameCount; i++) {
+ frame[i].setVisible(true);
+ }
+ t[2] = Platform.currentTimeMillis();
+ } } );
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while( frameCount > initCount.get() && INIT_TIMEOUT > t1 - t0 ) {
+ try {
+ Thread.sleep(100);
+ System.err.println("Sleep initialized: "+initCount+"/"+frameCount);
+ } catch (final InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ t1 = System.currentTimeMillis();
+ }
+ t[3] = Platform.currentTimeMillis();
+ final double panelCountF = initCount.get();
+ System.err.printf("P: %d %s%s:%n\tctor\t%6d/t %6.2f/1%n\tvisible\t%6d/t %6.2f/1%n\tsum-i\t%6d/t %6.2f/1%n",
+ initCount.get(),
+ canvasType, initMT?" (mt)":" (01)",
+ t[1]-t[0], (t[1]-t[0])/panelCountF,
+ t[3]-t[1], (t[3]-t[1])/panelCountF,
+ t[3]-t[0], (t[3]-t[0])/panelCountF);
+
+ System.err.println("INIT END: "+initCount+"/"+frameCount);
+ if( wait ) {
+ UITestCase.waitForKey("Post-Init");
+ }
+ if( null != animator ) {
+ animator.start();
+ }
+ try {
+ Thread.sleep(duration);
+ } catch (final InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ if( null != animator ) {
+ animator.stop();
+ }
+ t[4] = Platform.currentTimeMillis();
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ while( !newtCanvasAWTList.isEmpty() ) {
+ newtCanvasAWTList.remove(0).destroy(); // removeNotify does not destroy GLWindow
+ }
+ for(int i=0; i<frameCount; i++) {
+ frame[i].dispose();
+ }
+ } } );
+ } catch (final Exception e1) {
+ e1.printStackTrace();
+ }
+
+ final long ti_net = (t[4]-t[0])-duration;
+ System.err.printf("T: duration %d %d%n\ttotal-d\t%6d/t %6.2f/1%n\ttotal-i\t%6d/t %6.2f/1%n",
+ duration, t[4]-t[3],
+ t[4]-t[0], (t[4]-t[0])/panelCountF,
+ ti_net, ti_net/panelCountF);
+ System.err.println("Total: "+(t[4]-t[0]));
+ }
+
+ private GLADComp createNewtCanvasAWT(final GLCapabilitiesImmutable caps, final boolean useGears, final GLAnimatorControl anim, final Dimension size) {
+ final GLWindow window = GLWindow.create(caps);
+ final NewtCanvasAWT canvas = new NewtCanvasAWT(window);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ if( useGears ) {
+ final GearsES2 g = new GearsES2(0);
+ g.setVerbose(false);
+ window.addGLEventListener(g);
+ }
+ if( null != anim ) {
+ anim.add(window);
+ }
+ return new GLADComp(window, canvas);
+ }
+ private GLADComp createGLCanvas(final GLCapabilitiesImmutable caps, final boolean useGears, final GLAnimatorControl anim, final Dimension size) {
+ final GLCanvas canvas = new GLCanvas(caps);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ if( useGears ) {
+ final GearsES2 g = new GearsES2(0);
+ g.setVerbose(false);
+ canvas.addGLEventListener(g);
+ }
+ if( null != anim ) {
+ anim.add(canvas);
+ }
+ return new GLADComp(canvas, canvas);
+ }
+ private GLADComp createGLJPanel(final boolean initMT, final boolean useSwingDoubleBuffer, final GLCapabilitiesImmutable caps, final boolean useGears, final boolean skipGLOrientationVerticalFlip, final GLAnimatorControl anim, final Dimension size) {
+ final GLJPanel canvas = new GLJPanel(caps);
+ canvas.setSize(size);
+ canvas.setPreferredSize(size);
+ canvas.setDoubleBuffered(useSwingDoubleBuffer);
+ if( skipGLOrientationVerticalFlip ) { // don't fiddle w/ default ..
+ canvas.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip);
+ }
+ if( useGears ) {
+ final GearsES2 g = new GearsES2(0);
+ g.setVerbose(false);
+ g.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ canvas.addGLEventListener(g);
+ }
+ if( null != anim ) {
+ anim.add(canvas);
+ }
+ if( initMT ) {
+ canvas.initializeBackend(true /* offthread */);
+ }
+ return new GLADComp(canvas, canvas);
+ }
+
+ static GLCapabilitiesImmutable caps = null;
+
+ //
+ // NOP
+ //
+
+ @Test
+ public void test00NopNoGLDefGrid() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.NOP_T, false /*useAnim*/, false /* overlap */);
+ }
+
+ @Test
+ public void test01NopGLCanvasDefGrid() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLCanvas_T, false /*useAnim*/, false /* overlap */);
+ }
+
+ @Test
+ public void test02NopGLJPanelDefGridSingleAutoFlip() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLJPanel_T, false /*useAnim*/, false /* overlap */);
+ }
+
+ @Test
+ public void test03NopGLJPanelDefGridSingleManualFlip() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, true /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLJPanel_T, false /*useAnim*/, false /* overlap */);
+ }
+
+ @Test
+ public void test04NopGLJPanelDefGridMTManualFlip() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, true /*skipGLOrientationVerticalFlip*/, width , height, frameCount, true /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLJPanel_T, false /*useAnim*/, false /* overlap */);
+ }
+
+ @Test
+ public void test05NopNewtCanvasAWTDefGrid() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.NewtCanvasAWT_T, false /*useAnim*/, false /* overlap */);
+ }
+
+ //
+ // Gears
+ //
+
+ @Test
+ public void test11GearsGLCanvasDefGrid() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), true /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLCanvas_T, true /*useAnim*/, false /* overlap */);
+ }
+
+ @Test
+ public void test12GearsGLJPanelDefGridSingleAutoFlip() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), true /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLJPanel_T, true /*useAnim*/, false /* overlap */);
+ }
+
+ @Test
+ public void test13GearsGLJPanelDefGridSingleManualFlip() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), true /*useGears*/, true /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLJPanel_T, true /*useAnim*/, false /* overlap */);
+ }
+
+ @Test
+ public void test14GearsGLJPanelDefGridMTManualFlip() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), true /*useGears*/, true /*skipGLOrientationVerticalFlip*/, width , height, frameCount, true /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLJPanel_T, true /*useAnim*/, false /* overlap */);
+ }
+
+ @Test
+ public void test15GearsNewtCanvasAWTDefGrid() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), true /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.NewtCanvasAWT_T, true /*useAnim*/, false /* overlap */);
+ }
+
+ //
+ // Overlap + NOP
+ //
+
+
+ @Test
+ public void test20NopNoGLDefOverlap() throws InterruptedException, InvocationTargetException {
+ test(null, false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.NOP_T, false /*useAnim*/, true /* overlap */);
+ }
+
+ @Test
+ public void test21NopGLCanvasDefOverlap() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLCanvas_T, false /*useAnim*/, true /* overlap */);
+ }
+
+ @Test
+ public void test22NopGLJPanelDefOverlapSingle() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLJPanel_T, false /*useAnim*/, true /* overlap */);
+ }
+
+ @Test
+ public void test23NopGLJPanelDefOverlapMT() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, true /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLJPanel_T, false /*useAnim*/, true /* overlap */);
+ }
+
+ @Test
+ public void test25NopNewtCanvasAWTDefOverlap() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.NewtCanvasAWT_T, false /*useAnim*/, true /* overlap */);
+ }
+
+ // @Test
+ public void testXXNopGLJPanelDefOverlapSingle() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLJPanel_T, false /*useAnim*/, true /* overlap */);
+ }
+
+ // @Test
+ public void testXXNopGLJPanelBitmapGridSingle() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ caps.setBitmap(true);
+ test(caps, false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */,
+ false /*useSwingDoubleBuffer*/, CanvasType.GLJPanel_T, false /*useAnim*/, false);
+ }
+
+ static long duration = 0; // ms
+ static boolean wait = false;
+ static int width = 800, height = 600, frameCount = 25;
+
+ AtomicInteger initCount = new AtomicInteger(0);
+
+ public static void main(final String[] args) {
+ boolean manual=false;
+ boolean waitMain = false;
+ CanvasType canvasType = CanvasType.GLJPanel_T;
+ boolean initMT = false, useSwingDoubleBuffer=false;
+ boolean useGears = false, skipGLOrientationVerticalFlip=false, useAnim = false;
+ boolean overlap = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-width")) {
+ width = MiscUtils.atoi(args[++i], width);
+ } else if(args[i].equals("-height")) {
+ height = MiscUtils.atoi(args[++i], height);
+ } else if(args[i].equals("-count")) {
+ frameCount = MiscUtils.atoi(args[++i], frameCount);
+ } else if(args[i].equals("-initMT")) {
+ initMT = true;
+ manual = true;
+ } else if(args[i].equals("-type")) {
+ i++;
+ canvasType = CanvasType.valueOf(args[i]);
+ manual = true;
+ } else if(args[i].equals("-swingDoubleBuffer")) {
+ useSwingDoubleBuffer = true;
+ } else if(args[i].equals("-gears")) {
+ useGears = true;
+ } else if(args[i].equals("-anim")) {
+ useAnim = true;
+ } else if(args[i].equals("-userVertFlip")) {
+ skipGLOrientationVerticalFlip = true;
+ } else if(args[i].equals("-overlap")) {
+ overlap = true;
+ } else if(args[i].equals("-wait")) {
+ wait = true;
+ manual = true;
+ } else if(args[i].equals("-waitMain")) {
+ waitMain = true;
+ manual = true;
+ } else if(args[i].equals("-manual")) {
+ manual = true;
+ }
+ }
+ if( waitMain ) {
+ UITestCase.waitForKey("Main-Start");
+ }
+ if( manual ) {
+ GLProfile.initSingleton();
+ final TestPerf001GLJPanelInit02AWT demo = new TestPerf001GLJPanelInit02AWT();
+ demo.test(null, useGears, skipGLOrientationVerticalFlip, width, height, frameCount,
+ initMT, useSwingDoubleBuffer, canvasType, useAnim, overlap);
+ } else {
+ org.junit.runner.JUnitCore.main(TestPerf001GLJPanelInit02AWT.class.getName());
+ }
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLWindowInit03NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLWindowInit03NEWT.java
new file mode 100644
index 000000000..60e31aa6a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLWindowInit03NEWT.java
@@ -0,0 +1,214 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.perf;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Multiple GLJPanels in a JFrame
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPerf001GLWindowInit03NEWT extends UITestCase {
+ final long INIT_TIMEOUT = 10L*1000L; // 10s
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ public void test(final GLCapabilitiesImmutable caps, final boolean useGears, final int width, final int height, final int frameCount, final boolean reuseDevice) {
+ final int cols = (int)Math.round(Math.sqrt(frameCount));
+ final int rows = frameCount / cols;
+ final int eWidth = width/cols;
+ final int eHeight = height/rows;
+
+ final GLWindow[] frame = new GLWindow[frameCount];
+ final long[] t = new long[10];
+ if( wait ) {
+ UITestCase.waitForKey("Pre-Init");
+ }
+ System.err.println("INIT START");
+ initCount.set(0);
+
+ t[0] = Platform.currentTimeMillis();
+ int x = 32, y = 32;
+ for(int i=0; i<frameCount; i++) {
+ final Screen screen = NewtFactory.createScreen(NewtFactory.createDisplay(null, reuseDevice), 0);
+ frame[i] = GLWindow.create(screen, caps);
+ frame[i].setTitle("frame_"+i+"/"+frameCount);
+ frame[i].setPosition(x, y);
+ x+=eWidth+32;
+ if(x>=width) {
+ x=32;
+ y+=eHeight+32;
+ }
+ frame[i].setSize(eWidth, eHeight);
+ if( useGears ) {
+ frame[i].addGLEventListener(new GearsES2());
+ }
+ frame[i].addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ initCount.incrementAndGet();
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {}
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ });
+ }
+ t[1] = Platform.currentTimeMillis();
+ for(int i=0; i<frameCount; i++) {
+ frame[i].setVisible(false /*wait*/, true /*visible*/);
+ }
+ t[2] = Platform.currentTimeMillis();
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while( frameCount > initCount.get() && INIT_TIMEOUT > t1 - t0 ) {
+ try {
+ Thread.sleep(100);
+ System.err.println("Sleep initialized: "+initCount+"/"+frameCount);
+ } catch (final InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ t1 = System.currentTimeMillis();
+ }
+ t[3] = Platform.currentTimeMillis();
+ final double panelCountF = initCount.get();
+ System.err.printf("P: %d GLWindow:%n\tctor\t%6d/t %6.2f/1%n\tvisible\t%6d/t %6.2f/1%n\tsum-i\t%6d/t %6.2f/1%n",
+ initCount.get(),
+ t[1]-t[0], (t[1]-t[0])/panelCountF,
+ t[3]-t[1], (t[3]-t[1])/panelCountF,
+ t[3]-t[0], (t[3]-t[0])/panelCountF);
+
+ System.err.println("INIT END: "+initCount+"/"+frameCount);
+ if( wait ) {
+ UITestCase.waitForKey("Post-Init");
+ }
+ try {
+ Thread.sleep(duration);
+ } catch (final InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ t[4] = Platform.currentTimeMillis();
+ for(int i=0; i<frameCount; i++) {
+ frame[i].destroy();
+ }
+
+ final long ti_net = (t[4]-t[0])-duration;
+ System.err.printf("T: duration %d %d%n\ttotal-d\t%6d/t %6.2f/1%n\ttotal-i\t%6d/t %6.2f/1%n",
+ duration, t[4]-t[3],
+ t[4]-t[0], (t[4]-t[0])/panelCountF,
+ ti_net, ti_net/panelCountF);
+ System.err.println("Total: "+(t[4]-t[0]));
+ }
+
+ static GLCapabilitiesImmutable caps = null;
+
+ @Test
+ public void test01NopGLWindowNoReuse() throws InterruptedException, InvocationTargetException {
+ if(!mainRun) {
+ System.err.println("Disabled for auto unit test until further analysis - Windows/ATI driver crash");
+ return;
+ }
+ test(new GLCapabilities(null), false /*useGears*/, width, height , frameCount, false /* reuseDevice */);
+ }
+ @Test
+ public void test02NopGLWindowReuse() throws InterruptedException, InvocationTargetException {
+ test(new GLCapabilities(null), false /*useGears*/, width, height , frameCount, true /* reuseDevice */);
+ }
+
+ static long duration = 0; // ms
+ static boolean wait = false, mainRun = false;
+ static int width = 800, height = 600, frameCount = 25;
+
+ AtomicInteger initCount = new AtomicInteger(0);
+
+ public static void main(final String[] args) {
+ mainRun = true;
+ boolean useGears = false, manual=false;
+ boolean waitMain = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-width")) {
+ width = MiscUtils.atoi(args[++i], width);
+ } else if(args[i].equals("-height")) {
+ height = MiscUtils.atoi(args[++i], height);
+ } else if(args[i].equals("-count")) {
+ frameCount = MiscUtils.atoi(args[++i], frameCount);
+ } else if(args[i].equals("-gears")) {
+ useGears = true;
+ } else if(args[i].equals("-wait")) {
+ wait = true;
+ manual = true;
+ } else if(args[i].equals("-waitMain")) {
+ waitMain = true;
+ manual = true;
+ } else if(args[i].equals("-manual")) {
+ manual = true;
+ }
+ }
+ if( waitMain ) {
+ UITestCase.waitForKey("Main-Start");
+ }
+ if( manual ) {
+ GLProfile.initSingleton();
+ final TestPerf001GLWindowInit03NEWT demo = new TestPerf001GLWindowInit03NEWT();
+ demo.test(null, useGears, width, height, frameCount, false /* reuseDevice */);
+ } else {
+ org.junit.runner.JUnitCore.main(TestPerf001GLWindowInit03NEWT.class.getName());
+ }
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001RawInit00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001RawInit00NEWT.java
new file mode 100644
index 000000000..f8b15a843
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001RawInit00NEWT.java
@@ -0,0 +1,234 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.perf;
+
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLProfile;
+
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Raw initialization of multiple offscreen GLAutoDrawables
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPerf001RawInit00NEWT extends UITestCase {
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton();
+ }
+
+ public void testChooseOnly(final int runNum, final Screen screen, final int count) throws InterruptedException {
+ final long[] t = new long[10];
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final int[] chosenCfgs = { 0 };
+
+ final GLCapabilitiesImmutable caps = new GLCapabilities(glp);
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDisplay().getGraphicsDevice(), caps);
+
+ if( wait && 0 == runNum ) {
+ UITestCase.waitForKey("Pre-Init");
+ }
+ System.err.println("INIT START #"+runNum);
+ screen.getDisplay().getEDTUtil().invoke(true, new Runnable() {
+ public void run() {
+ t[0] = Platform.currentTimeMillis();
+ for(int i=0; i<count; i++) {
+ final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration(caps, caps, null, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
+ if( null != cfg ) {
+ chosenCfgs[0]++;
+ }
+ }
+ t[1] = Platform.currentTimeMillis();
+ } } );
+
+ final double countF = count;
+ System.err.printf("Run: %d, count %d/%d raw:%n\tchoose\t%6d/t %6.2f/1%n",
+ runNum, chosenCfgs[0], count, t[1]-t[0], (t[1]-t[0])/countF);
+ System.err.println("INIT END #"+runNum);
+ if( wait && 2 == runNum ) {
+ UITestCase.waitForKey("Post-Init");
+ }
+ }
+
+ public void testFull(final int runNum, final int width, final int height, final int count) {
+ // panel.setBounds(0, 0, width, height);
+ final long[] t = new long[10];
+ final GLDrawable[] glDrawables = new GLDrawable[count];
+ final GLContext[] glConti = new GLContext[count];
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilitiesImmutable caps = new GLCapabilities(glp);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp);
+ if( wait && 0 == runNum ) {
+ UITestCase.waitForKey("Pre-Init");
+ }
+ System.err.println("INIT START #"+runNum);
+ t[0] = Platform.currentTimeMillis();
+ for(int i=0; i<count; i++) {
+ glDrawables[i] = factory.createOffscreenDrawable(null, caps, null, width, height);
+ }
+ t[1] = Platform.currentTimeMillis();
+ for(int i=0; i<count; i++) {
+ glDrawables[i].setRealized(true);
+ }
+ t[2] = Platform.currentTimeMillis();
+ // 1st makeCurrent - context creation incl. release
+ for(int i=0; i<count; i++) {
+ final GLContext context = glDrawables[i].createContext(null);
+ if( GLContext.CONTEXT_NOT_CURRENT >= context.makeCurrent() ) {
+ // oops
+ glDrawables[i].setRealized(false);
+ glDrawables[i] = null;
+ glConti[i] = null;
+ continue;
+ }
+ glConti[i] = context;
+ context.release();
+ }
+ t[3] = Platform.currentTimeMillis();
+ // 2nd makeCurrent and release
+ for(int i=0; i<count; i++) {
+ final GLContext context = glConti[i];
+ if( GLContext.CONTEXT_NOT_CURRENT >= context.makeCurrent() ) {
+ // oops
+ glDrawables[i].setRealized(false);
+ glDrawables[i] = null;
+ glConti[i] = null;
+ continue;
+ }
+ context.release();
+ }
+ t[4] = Platform.currentTimeMillis();
+
+ final double countF = count;
+ System.err.printf("Run: %d, count %d raw:%n\tglad-create\t%6d/t %6.2f/1%n"+
+ "\tglad-realize\t%6d/t %6.2f/1%n"+
+ "\tctx-create1\t%6d/t %6.2f/1%n"+
+ "\tctx-curren2\t%6d/t %6.2f/1%n"+
+ "\tglad-ctx-init\t%6d/t %6.2f/1%n",
+ runNum, count,
+ t[1]-t[0], (t[1]-t[0])/countF, // create
+ t[2]-t[1], (t[2]-t[1])/countF, // realize
+ t[3]-t[2], (t[3]-t[2])/countF, // context-create1
+ t[4]-t[3], (t[4]-t[3])/countF, // context-curren2
+ t[3]-t[0], (t[3]-t[0])/countF);// init total
+ System.err.println("INIT END #"+runNum);
+ if( wait && 2 == runNum ) {
+ UITestCase.waitForKey("Post-Init");
+ }
+
+ // destroy
+ for(int i=0; i<count; i++) {
+ final GLContext context = glConti[i];
+ if( null != context ) {
+ context.destroy();
+ }
+ final GLDrawable glDrawable = glDrawables[i];
+ if( null != glDrawable ) {
+ glDrawable.setRealized(false);
+ }
+ glConti[i] = null;
+ glDrawables[i] = null;
+ }
+ }
+
+ @Test
+ public void test01ChooseOnly() throws InterruptedException, InvocationTargetException {
+ if( 0 != manualTest && 1 != manualTest ) {
+ return;
+ }
+ final Display display = NewtFactory.createDisplay(null, false);
+ final Screen screen = NewtFactory.createScreen(display, 0);
+ screen.addReference();
+ try {
+ testChooseOnly(0, screen, count); // warm-up
+ testChooseOnly(1, screen, count);
+ testChooseOnly(2, screen, count);
+ } finally {
+ screen.removeReference();
+ }
+ }
+
+ @Test
+ public void test02Full() throws InterruptedException, InvocationTargetException {
+ if( 0 != manualTest && 2 != manualTest ) {
+ return;
+ }
+ testFull(0, width, height, count); // warm-up
+ testFull(1, width, height, count);
+ testFull(2, width, height, count);
+ }
+
+ static boolean wait = false;
+ static int manualTest = 0;
+ static int width = 800, height = 600, count = 50;
+
+ public static void main(final String[] args) {
+ boolean waitMain = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-width")) {
+ width = MiscUtils.atoi(args[++i], width);
+ } else if(args[i].equals("-height")) {
+ height = MiscUtils.atoi(args[++i], height);
+ } else if(args[i].equals("-count")) {
+ count = MiscUtils.atoi(args[++i], count);
+ } else if(args[i].equals("-wait")) {
+ wait = true;
+ } else if(args[i].equals("-waitMain")) {
+ waitMain = true;
+ } else if(args[i].equals("-test")) {
+ manualTest = MiscUtils.atoi(args[++i], manualTest);
+ }
+ }
+ if( waitMain ) {
+ UITestCase.waitForKey("Main-Start");
+ }
+ org.junit.runner.JUnitCore.main(TestPerf001RawInit00NEWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java b/src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java
new file mode 100644
index 000000000..58aa8cd23
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java
@@ -0,0 +1,366 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.stereo;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import jogamp.opengl.util.stereo.GenericStereoDevice;
+
+import com.jogamp.common.net.Uri;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.math.FovHVHalves;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSBSStereo;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.stereo.StereoDevice;
+import com.jogamp.opengl.util.stereo.StereoDeviceRenderer;
+import com.jogamp.opengl.util.stereo.StereoDeviceFactory;
+import com.jogamp.opengl.util.stereo.StereoClientRenderer;
+import com.jogamp.opengl.util.stereo.StereoGLEventListener;
+import com.jogamp.opengl.util.stereo.StereoUtil;
+
+/**
+ * All distortions, no multisampling, bilinear filtering, manual-swap and using two FBOs (default, good)
+ * <pre>
+ * java StereoDemo01 -time 10000000
+ * </pre>
+ * All distortions, 8x multisampling, bilinear filtering, manual-swap and using two FBOs (best - slowest)
+ * <pre>
+ * java StereoDemo01 -time 10000000 -samples 8
+ * </pre>
+ * All distortions, 8x multisampling, bilinear filtering, manual-swap and using one a big single FBO (w/ all commandline params)
+ * <pre>
+ * java StereoDemo01 -time 10000000 -vignette true -chromatic true -timewarp false -samples 8 -biLinear true -autoSwap false -singleFBO true -mainScreen false
+ * </pre>
+ * No distortions, no multisampling, no filtering, auto-swap and using a big single FBO (worst and fastest)
+ * <pre>
+ * java StereoDemo01 -time 10000000 -vignette false -chromatic false -timewarp false -samples 0 -biLinear false -autoSwap true -singleFBO true
+ * </pre>
+ * Test on main screen:
+ * <pre>
+ * java StereoDemo01 -time 10000000 -mainScreen true
+ * </pre>
+ * Test a 3D SBS Movie:
+ * <pre>
+ * java StereoDemo01 -time 10000000 -filmFile Some_SBS_3D_Movie.mkv
+ * java StereoDemo01 -time 10000000 -filmURI http://whoknows.not/Some_SBS_3D_Movie.mkv
+ * </pre>
+ * <p>
+ * In case user likes to utilize the {@link StereoDeviceFactory.DeviceType#Generic Generic} software implementation,
+ * which is selected {@link StereoDeviceFactory.DeviceType#Default Default} if no other device is available
+ * or explicit via <code>-device Generic</code>, the user can chose between different <i>generic</i> stereo modes:
+ * <pre>
+ * mono : <code>-device Generic -deviceIndex 0</code>
+ * stereo-sbs : <code>-device Generic -deviceIndex 1</code>
+ * stereo-sbs-lense: <code>-device Generic -deviceIndex 2</code>
+ * </pre>
+ * </p>
+ * <p>
+ * Key 'R' enables/disables the VR's sensors, i.e. head rotation ..
+ * </p>
+ *
+ */
+public class StereoDemo01 {
+ static long duration = 10000; // ms
+
+ static boolean useStereoScreen = true;
+
+ static int numSamples = 0;
+ static boolean biLinear = true;
+ static boolean useSingleFBO = false;
+ static boolean useVignette = true;
+ static boolean useChromatic = true;
+ static boolean useTimewarp = true;
+ static boolean useAutoSwap = false;
+ static String useFilmFile = null;
+ static String useFilmURI = null;
+ static StereoDeviceFactory.DeviceType deviceType = StereoDeviceFactory.DeviceType.Default;
+ static int deviceIndex = 0;
+
+ public static void main(final String args[]) throws InterruptedException, URISyntaxException {
+ boolean useRecommendedDistortionBits = true;
+ int posx = -1;
+ int posy = -1;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-samples")) {
+ i++;
+ numSamples = MiscUtils.atoi(args[i], numSamples);
+ } else if(args[i].equals("-biLinear")) {
+ i++;
+ biLinear = MiscUtils.atob(args[i], biLinear);
+ } else if(args[i].equals("-singleFBO")) {
+ i++;
+ useSingleFBO = MiscUtils.atob(args[i], useSingleFBO);
+ } else if(args[i].equals("-vignette")) {
+ i++;
+ useVignette = MiscUtils.atob(args[i], useVignette);
+ useRecommendedDistortionBits = false;
+ } else if(args[i].equals("-chromatic")) {
+ i++;
+ useChromatic = MiscUtils.atob(args[i], useChromatic);
+ useRecommendedDistortionBits = false;
+ } else if(args[i].equals("-timewarp")) {
+ i++;
+ useTimewarp = MiscUtils.atob(args[i], useTimewarp);
+ useRecommendedDistortionBits = false;
+ } else if(args[i].equals("-vignette")) {
+ i++;
+ useVignette = MiscUtils.atob(args[i], useVignette);
+ useRecommendedDistortionBits = false;
+ } else if(args[i].equals("-mainScreen")) {
+ i++;
+ useStereoScreen = !MiscUtils.atob(args[i], useStereoScreen);
+ } else if(args[i].equals("-device")) {
+ i++;
+ deviceType = StereoDeviceFactory.DeviceType.valueOf(args[i]);
+ } else if(args[i].equals("-deviceIndex")) {
+ i++;
+ deviceIndex = MiscUtils.atoi(args[i], deviceIndex);
+ } else if(args[i].equals("-posx")) {
+ i++;
+ posx = MiscUtils.atoi(args[i], posx);
+ } else if(args[i].equals("-posy")) {
+ i++;
+ posy = MiscUtils.atoi(args[i], posy);
+ } else if(args[i].equals("-autoSwap")) {
+ i++;
+ useAutoSwap = MiscUtils.atob(args[i], useAutoSwap);
+ } else if(args[i].equals("-filmFile")) {
+ i++;
+ useFilmFile = args[i];
+ } else if(args[i].equals("-filmURI")) {
+ i++;
+ useFilmURI = args[i];
+ }
+ }
+ final StereoGLEventListener upstream;
+ final MovieSBSStereo movieSimple;
+ final Uri movieURI;
+ if( null != useFilmFile ) {
+ movieSimple = new MovieSBSStereo();
+ movieURI = Uri.valueOf(new File(useFilmFile));
+ upstream = movieSimple;
+ } else if( null != useFilmURI ) {
+ movieSimple = new MovieSBSStereo();
+ movieURI = Uri.cast(useFilmURI);
+ upstream = movieSimple;
+ } else {
+ final GearsES2 demo = new GearsES2(0);
+ demo.setZ(2f, 10000f, 20f); // start closer to eye
+ demo.setVerbose(false);
+ upstream = demo;
+ movieSimple = null;
+ movieURI = null;
+ }
+ final StereoDemo01 demo01 = new StereoDemo01();
+ demo01.doIt(deviceType, deviceIndex, posx, posy,
+ upstream, movieSimple, movieURI, biLinear, numSamples, useSingleFBO,
+ useRecommendedDistortionBits, useVignette, useChromatic, useTimewarp,
+ useAutoSwap, true /* useAnimator */, false /* exclusiveContext*/);
+ }
+
+ public void doIt(final StereoDeviceFactory.DeviceType deviceType, final int deviceIndex, final int posx, final int posy,
+ final StereoGLEventListener upstream, final MovieSBSStereo movieSimple, final Uri movieURI,
+ final boolean biLinear, final int numSamples, final boolean useSingleFBO,
+ final boolean useRecommendedDistortionBits, final boolean useVignette, final boolean useChromatic, final boolean useTimewarp,
+ final boolean useAutoSwap, final boolean useAnimator, final boolean exclusiveContext) throws InterruptedException {
+
+ System.err.println("glob duration "+duration);
+ System.err.println("glob useStereoScreen "+useStereoScreen);
+ System.err.println("deviceType "+deviceType);
+ System.err.println("deviceIndex "+deviceIndex);
+ System.err.println("biLinear "+biLinear);
+ System.err.println("numSamples "+numSamples);
+ System.err.println("useSingleFBO "+useSingleFBO);
+ System.err.println("useRecommendedDistortionBits "+useRecommendedDistortionBits);
+ System.err.println("useVignette "+useVignette);
+ System.err.println("useChromatic "+useChromatic);
+ System.err.println("useTimewarp "+useTimewarp);
+ System.err.println("useAutoSwap "+useAutoSwap);
+
+ final StereoDeviceFactory stereoDeviceFactory = StereoDeviceFactory.createFactory(deviceType);
+ if( null == stereoDeviceFactory ) {
+ System.err.println("No StereoDeviceFactory available");
+ return;
+ }
+
+ final StereoDevice stereoDevice = stereoDeviceFactory.createDevice(deviceIndex, null, true /* verbose */);
+ if( null == stereoDevice ) {
+ System.err.println("No StereoDevice.Context available for index "+deviceIndex);
+ return;
+ }
+
+ final boolean isGenericDevice = stereoDevice instanceof GenericStereoDevice;
+
+ if( 0 <= posx && 0 <= posy && isGenericDevice ) {
+ ((GenericStereoDevice)stereoDevice).setSurfacePosition(posx, posy);
+ }
+ System.err.println("StereoDevice "+stereoDevice);
+
+ // Start the sensor which provides the Rift’s pose and motion.
+ if( !stereoDevice.startSensors(true) ) {
+ System.err.println("Could not start sensors on device "+deviceIndex);
+ }
+
+ //
+ //
+ //
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxProgrammable(true /* favorHardwareRasterizer */));
+ final GLWindow window = GLWindow.create(caps);
+
+ final PointImmutable devicePos = stereoDevice.getPosition();
+ final DimensionImmutable deviceRes = stereoDevice.getSurfaceSize();
+ if( useStereoScreen ) {
+ window.setPosition(devicePos.getX(), devicePos.getY());
+ }
+ window.setSurfaceSize(deviceRes.getWidth(), deviceRes.getHeight()); // might be not correct ..
+ window.setAutoSwapBufferMode(useAutoSwap);
+ window.setUndecorated(true);
+
+ final Animator animator = useAnimator ? new Animator() : null;
+ if( useAnimator ) {
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.setExclusiveContext(exclusiveContext);
+ }
+
+ //
+ // Stereo Device Setup
+ //
+ // EyePos.y = ovrHmd_GetFloat(HMD, OVR_KEY_EYE_HEIGHT, EyePos.y);
+ final FovHVHalves[] defaultEyeFov = stereoDevice.getDefaultFOV();
+ System.err.println("Default Fov[0]: "+defaultEyeFov[0]);
+ System.err.println("Default Fov[0]: "+defaultEyeFov[0].toStringInDegrees());
+ if( defaultEyeFov.length > 1 ) {
+ System.err.println("Default Fov[1]: "+defaultEyeFov[1]);
+ System.err.println("Default Fov[1]: "+defaultEyeFov[1].toStringInDegrees());
+ }
+
+ final boolean usesLenses = 0 != ( StereoDeviceRenderer.DISTORTION_BARREL & stereoDevice.getMinimumDistortionBits() );
+ final float[] eyePositionOffset = null != movieSimple && usesLenses ? new float[] { 0f, 0.3f, 0f } // better fixed movie position w/ lenses
+ : stereoDevice.getDefaultEyePositionOffset(); // default
+ System.err.println("Eye Position Offset: "+Arrays.toString(eyePositionOffset));
+
+ final int textureUnit = 0;
+ final int reqDistortionBits;
+ if( useRecommendedDistortionBits ) {
+ reqDistortionBits = stereoDevice.getRecommendedDistortionBits();
+ } else {
+ reqDistortionBits = ( useVignette ? StereoDeviceRenderer.DISTORTION_VIGNETTE : 0 ) |
+ ( useChromatic ? StereoDeviceRenderer.DISTORTION_CHROMATIC : 0 ) |
+ ( useTimewarp ? StereoDeviceRenderer.DISTORTION_TIMEWARP : 0 );
+ }
+ System.err.println("Requesting Distortion Bits: "+StereoUtil.distortionBitsToString(reqDistortionBits));
+
+ final float pixelsPerDisplayPixel = 1f;
+ final StereoDeviceRenderer stereoDeviceRenderer =
+ stereoDevice.createRenderer(reqDistortionBits, useSingleFBO ? 1 : 2, eyePositionOffset,
+ defaultEyeFov, pixelsPerDisplayPixel, textureUnit);
+ System.err.println("StereoDeviceRenderer: "+stereoDeviceRenderer);
+
+ final int texFilter = biLinear ? GL.GL_LINEAR : GL.GL_NEAREST;
+ final StereoClientRenderer renderer = new StereoClientRenderer(stereoDeviceRenderer, true /* ownsDist */, texFilter, texFilter, numSamples);
+ if( null != movieSimple && null != movieURI) {
+ movieSimple.setScaleOrig(true);
+ final GLMediaPlayer mp = movieSimple.getGLMediaPlayer();
+ mp.attachObject(MovieSimple.WINDOW_KEY, window);
+ mp.attachObject(MovieSBSStereo.STEREO_RENDERER_KEY, renderer);
+ mp.addEventListener(MovieSBSStereo.stereoGLMediaEventListener);
+ movieSimple.initStream(movieURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 3);
+ } else {
+ renderer.addGLEventListener(upstream);
+ }
+ window.addGLEventListener(renderer);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ window.addKeyListener(quitAdapter);
+ window.addWindowListener(quitAdapter);
+
+ window.addKeyListener(new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ switch(e.getKeySymbol()) {
+ case KeyEvent.VK_R: {
+ stereoDevice.startSensors(!stereoDevice.getSensorsStarted());
+ break;
+ }
+ }
+ } } );
+
+ if( useAnimator ) {
+ animator.add(window);
+ animator.start();
+ }
+ window.setVisible(true);
+
+ // Correct window size to actual pixel size,
+ // which ration is unknown before window creation when using multiple displays!
+ System.err.println("Window.0.windowSize : "+window.getWidth()+" x "+window.getHeight());
+ System.err.println("Window.0.surfaceSize: "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight());
+ window.setSurfaceSize(deviceRes.getWidth(), deviceRes.getHeight());
+ System.err.println("Window.1.windowSize : "+window.getWidth()+" x "+window.getHeight());
+ System.err.println("Window.1.surfaceSize: "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight());
+
+ if( useAnimator ) {
+ animator.setUpdateFPSFrames(60, System.err);
+ }
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1-t0<duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ if( useAnimator ) {
+ animator.stop();
+ }
+ window.destroy();
+ stereoDevice.dispose();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java
new file mode 100644
index 000000000..e6cb48764
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java
@@ -0,0 +1,333 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.swt;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.swt.NewtCanvasSWT;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug672NewtCanvasSWTSashForm extends UITestCase {
+ static int screenIdx = 0;
+ static PointImmutable wpos;
+ static DimensionImmutable wsize, rwsize = null;
+
+ static long duration = 500; // ms
+
+ @BeforeClass
+ public static void initClass() {
+ if(null == wsize) {
+ wsize = new Dimension(640, 480);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ Display display = null;
+ Shell shell = null;
+ Composite composite = null;
+ SashForm sash = null;
+ com.jogamp.newt.Display swtNewtDisplay = null;
+
+ @Before
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ }});
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.NONE );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ sash = new SashForm(composite, SWT.NONE);
+ Assert.assertNotNull( sash );
+ final org.eclipse.swt.widgets.Label c = new org.eclipse.swt.widgets.Label(sash, SWT.NONE);
+ c.setText("Left cell");
+ }});
+ swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+ Assert.assertNotNull( sash );
+ try {
+ display.syncExec(new Runnable() {
+ public void run() {
+ sash.dispose();
+ composite.dispose();
+ shell.dispose();
+ }});
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display.dispose();
+ }});
+ }
+ catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ swtNewtDisplay = null;
+ display = null;
+ shell = null;
+ composite = null;
+ sash = null;
+ }
+
+ class WaitAction implements Runnable {
+ private final long sleepMS;
+
+ WaitAction(final long sleepMS) {
+ this.sleepMS = sleepMS;
+ }
+ public void run() {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ try {
+ Thread.sleep(sleepMS);
+ } catch (final InterruptedException e) { }
+ }
+ }
+ }
+ final WaitAction awtRobotWaitAction = new WaitAction(AWTRobotUtil.TIME_SLICE);
+ final WaitAction generalWaitAction = new WaitAction(10);
+
+ protected void runTestGL(final GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException {
+ final com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, screenIdx);
+ final GLWindow glWindow = GLWindow.create(screen, caps);
+ Assert.assertNotNull(glWindow);
+
+ final GearsES2 demo = new GearsES2(1);
+ glWindow.addGLEventListener(demo);
+
+ final Animator animator = new Animator();
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
+ //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ glWindow.addWindowListener(new WindowAdapter() {
+ public void windowResized(final WindowEvent e) {
+ System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ public void windowMoved(final WindowEvent e) {
+ System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ });
+
+ glWindow.addKeyListener(new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='f') {
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setExclusiveContextThread(t);
+ } }.start();
+ }
+ }
+ });
+
+ animator.add(glWindow);
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ animator.setUpdateFPSFrames(60, null);
+ final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( sash, 0, glWindow );
+ Assert.assertNotNull( canvas1 );
+
+ display.syncExec( new Runnable() {
+ public void run() {
+ shell.setText( getSimpleTestName(".") );
+ shell.setSize( wsize.getWidth(), wsize.getHeight() );
+ if( null != wpos ) {
+ shell.setLocation( wpos.getX(), wpos.getY() );
+ }
+ shell.open();
+ }
+ });
+ Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow, awtRobotWaitAction, true));
+ Assert.assertNotNull( canvas1.getNativeWindow() );
+
+ System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
+ System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
+ System.err.println("window pos/siz.0: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+ System.err.println("GLWindow LOS.0: "+glWindow.getLocationOnScreen(null));
+ System.err.println("NewtCanvasSWT LOS.0: "+canvas1.getNativeWindow().getLocationOnScreen(null));
+
+ if( null != rwsize ) {
+ for(int i=0; i<50; i++) { // 500 ms dispatched delay
+ generalWaitAction.run();
+ }
+ display.syncExec( new Runnable() {
+ public void run() {
+ shell.setSize( rwsize.getWidth(), rwsize.getHeight() );
+ }
+ });
+ System.err.println("window resize pos/siz.1: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+ System.err.println("GLWindow LOS.1: "+glWindow.getLocationOnScreen(null));
+ System.err.println("NewtCanvasSWT LOS.1: "+canvas1.getNativeWindow().getLocationOnScreen(null));
+ }
+
+ final PointImmutable pSashRightClient = new Point(wsize.getWidth(), 0);
+ final PointImmutable pNatWinLOS = canvas1.getNativeWindow().getLocationOnScreen(null);
+ final PointImmutable pGLWinLOS = glWindow.getLocationOnScreen(null);
+
+ System.err.println("GLWindow LOS: "+pGLWinLOS);
+ System.err.println("NewtCanvasSWT LOS: "+pNatWinLOS);
+
+ Assert.assertTrue( "NewtCanvasAWT LOS "+pNatWinLOS+" not >= sash-right "+pSashRightClient, pNatWinLOS.compareTo(pSashRightClient) >= 0 );
+ Assert.assertTrue( "GLWindow LOS "+pGLWinLOS+" not >= sash-right "+pSashRightClient, pGLWinLOS.compareTo(pSashRightClient) >= 0 );
+
+ while( !quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration ) {
+ generalWaitAction.run();
+ }
+
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ Assert.assertEquals(null, glWindow.getExclusiveContextThread());
+
+ canvas1.dispose();
+ glWindow.destroy();
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
+ }
+
+ @Test
+ public void test01() throws InterruptedException, InvocationTargetException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ int x=0, y=0, w=640, h=480, rw=-1, rh=-1;
+ boolean usePos = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-width")) {
+ i++;
+ w = MiscUtils.atoi(args[i], w);
+ } else if(args[i].equals("-height")) {
+ i++;
+ h = MiscUtils.atoi(args[i], h);
+ } else if(args[i].equals("-x")) {
+ i++;
+ x = MiscUtils.atoi(args[i], x);
+ usePos = true;
+ } else if(args[i].equals("-y")) {
+ i++;
+ y = MiscUtils.atoi(args[i], y);
+ usePos = true;
+ } else if(args[i].equals("-rwidth")) {
+ i++;
+ rw = MiscUtils.atoi(args[i], rw);
+ } else if(args[i].equals("-rheight")) {
+ i++;
+ rh = MiscUtils.atoi(args[i], rh);
+ } else if(args[i].equals("-screen")) {
+ i++;
+ screenIdx = MiscUtils.atoi(args[i], 0);
+ }
+ }
+ wsize = new Dimension(w, h);
+ if( 0 < rw && 0 < rh ) {
+ rwsize = new Dimension(rw, rh);
+ }
+
+ if(usePos) {
+ wpos = new Point(x, y);
+ }
+ System.err.println("position "+wpos);
+ System.err.println("size "+wsize);
+ System.err.println("resize "+rwsize);
+ System.err.println("screen "+screenIdx);
+
+ org.junit.runner.JUnitCore.main(TestBug672NewtCanvasSWTSashForm.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java
new file mode 100644
index 000000000..944fa1071
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java
@@ -0,0 +1,340 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.swt;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.swt.NewtCanvasSWT;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug672NewtCanvasSWTSashFormComposite extends UITestCase {
+ static int screenIdx = 0;
+ static PointImmutable wpos;
+ static DimensionImmutable wsize, rwsize = null;
+
+ static long duration = 500; // ms
+
+ @BeforeClass
+ public static void initClass() {
+ if(null == wsize) {
+ wsize = new Dimension(640, 480);
+ }
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ Display display = null;
+ Shell shell = null;
+ Composite composite = null;
+ SashForm sash = null;
+ Composite innerComposite = null;
+ com.jogamp.newt.Display swtNewtDisplay = null;
+
+ @Before
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ }});
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.NONE );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ sash = new SashForm(composite, SWT.NONE);
+ Assert.assertNotNull( sash );
+ final org.eclipse.swt.widgets.Label c = new org.eclipse.swt.widgets.Label(sash, SWT.NONE);
+ c.setText("Left cell");
+ innerComposite = new Composite(sash, SWT.NONE);
+ Assert.assertNotNull( innerComposite );
+ innerComposite.setLayout( new FillLayout() );
+ }});
+ swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+ Assert.assertNotNull( sash );
+ Assert.assertNotNull( innerComposite );
+ try {
+ display.syncExec(new Runnable() {
+ public void run() {
+ innerComposite.dispose();
+ sash.dispose();
+ composite.dispose();
+ shell.dispose();
+ }});
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display.dispose();
+ }});
+ }
+ catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ swtNewtDisplay = null;
+ display = null;
+ shell = null;
+ composite = null;
+ sash = null;
+ innerComposite = null;
+ }
+
+ class WaitAction implements Runnable {
+ private final long sleepMS;
+
+ WaitAction(final long sleepMS) {
+ this.sleepMS = sleepMS;
+ }
+ public void run() {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ try {
+ Thread.sleep(sleepMS);
+ } catch (final InterruptedException e) { }
+ }
+ }
+ }
+ final WaitAction awtRobotWaitAction = new WaitAction(AWTRobotUtil.TIME_SLICE);
+ final WaitAction generalWaitAction = new WaitAction(10);
+
+ protected void runTestGL(final GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException {
+ final com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, screenIdx);
+ final GLWindow glWindow = GLWindow.create(screen, caps);
+ Assert.assertNotNull(glWindow);
+
+ final GearsES2 demo = new GearsES2(1);
+ glWindow.addGLEventListener(demo);
+
+ final Animator animator = new Animator();
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter));
+ //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ glWindow.addWindowListener(new WindowAdapter() {
+ public void windowResized(final WindowEvent e) {
+ System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ public void windowMoved(final WindowEvent e) {
+ System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
+ }
+ });
+
+ glWindow.addKeyListener(new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='f') {
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setExclusiveContextThread(t);
+ } }.start();
+ }
+ }
+ });
+
+ animator.add(glWindow);
+ animator.start();
+ Assert.assertTrue(animator.isStarted());
+ Assert.assertTrue(animator.isAnimating());
+ animator.setUpdateFPSFrames(60, null);
+ final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( innerComposite, 0, glWindow );
+ Assert.assertNotNull( canvas1 );
+
+ display.syncExec( new Runnable() {
+ public void run() {
+ shell.setText( getSimpleTestName(".") );
+ shell.setSize( wsize.getWidth(), wsize.getHeight() );
+ if( null != wpos ) {
+ shell.setLocation( wpos.getX(), wpos.getY() );
+ }
+ shell.open();
+ }
+ });
+ Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow, awtRobotWaitAction, true));
+ Assert.assertNotNull( canvas1.getNativeWindow() );
+
+ System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities());
+ System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
+ System.err.println("window pos/siz.0: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+ System.err.println("GLWindow LOS.0: "+glWindow.getLocationOnScreen(null));
+ System.err.println("NewtCanvasSWT LOS.0: "+canvas1.getNativeWindow().getLocationOnScreen(null));
+
+ if( null != rwsize ) {
+ for(int i=0; i<50; i++) { // 500 ms dispatched delay
+ generalWaitAction.run();
+ }
+ display.syncExec( new Runnable() {
+ public void run() {
+ shell.setSize( rwsize.getWidth(), rwsize.getHeight() );
+ }
+ });
+ System.err.println("window resize pos/siz.1: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
+ System.err.println("GLWindow LOS.1: "+glWindow.getLocationOnScreen(null));
+ System.err.println("NewtCanvasSWT LOS.1: "+canvas1.getNativeWindow().getLocationOnScreen(null));
+ }
+
+ final PointImmutable pSashRightClient = new Point(wsize.getWidth(), 0);
+ final PointImmutable pNatWinLOS = canvas1.getNativeWindow().getLocationOnScreen(null);
+ final PointImmutable pGLWinLOS = glWindow.getLocationOnScreen(null);
+
+ System.err.println("GLWindow LOS: "+pGLWinLOS);
+ System.err.println("NewtCanvasSWT LOS: "+pNatWinLOS);
+
+ Assert.assertTrue( "NewtCanvasAWT LOS "+pNatWinLOS+" not >= sash-right "+pSashRightClient, pNatWinLOS.compareTo(pSashRightClient) >= 0 );
+ Assert.assertTrue( "GLWindow LOS "+pGLWinLOS+" not >= sash-right "+pSashRightClient, pGLWinLOS.compareTo(pSashRightClient) >= 0 );
+
+ while( !quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration ) {
+ generalWaitAction.run();
+ }
+
+ animator.stop();
+ Assert.assertFalse(animator.isAnimating());
+ Assert.assertFalse(animator.isStarted());
+ Assert.assertEquals(null, glWindow.getExclusiveContextThread());
+
+ canvas1.dispose();
+ glWindow.destroy();
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
+ }
+
+ @Test
+ public void test01() throws InterruptedException, InvocationTargetException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ int x=0, y=0, w=640, h=480, rw=-1, rh=-1;
+ boolean usePos = false;
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-width")) {
+ i++;
+ w = MiscUtils.atoi(args[i], w);
+ } else if(args[i].equals("-height")) {
+ i++;
+ h = MiscUtils.atoi(args[i], h);
+ } else if(args[i].equals("-x")) {
+ i++;
+ x = MiscUtils.atoi(args[i], x);
+ usePos = true;
+ } else if(args[i].equals("-y")) {
+ i++;
+ y = MiscUtils.atoi(args[i], y);
+ usePos = true;
+ } else if(args[i].equals("-rwidth")) {
+ i++;
+ rw = MiscUtils.atoi(args[i], rw);
+ } else if(args[i].equals("-rheight")) {
+ i++;
+ rh = MiscUtils.atoi(args[i], rh);
+ } else if(args[i].equals("-screen")) {
+ i++;
+ screenIdx = MiscUtils.atoi(args[i], 0);
+ }
+ }
+ wsize = new Dimension(w, h);
+ if( 0 < rw && 0 < rh ) {
+ rwsize = new Dimension(rw, rh);
+ }
+
+ if(usePos) {
+ wpos = new Point(x, y);
+ }
+ System.err.println("position "+wpos);
+ System.err.println("size "+wsize);
+ System.err.println("resize "+rwsize);
+ System.err.println("screen "+screenIdx);
+
+ org.junit.runner.JUnitCore.main(TestBug672NewtCanvasSWTSashFormComposite.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java
new file mode 100644
index 000000000..fb563f955
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java
@@ -0,0 +1,428 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.swt;
+
+import java.awt.AWTException;
+import java.awt.Robot;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.SWT ;
+import org.eclipse.swt.layout.FillLayout ;
+import org.eclipse.swt.widgets.Composite ;
+import org.eclipse.swt.widgets.Display ;
+import org.eclipse.swt.widgets.Shell ;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import javax.media.opengl.GL ;
+import javax.media.opengl.GL2 ;
+import javax.media.opengl.GLAutoDrawable ;
+import javax.media.opengl.GLCapabilities ;
+import javax.media.opengl.GLEventListener ;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.opengl.GLWindow ;
+import com.jogamp.newt.swt.NewtCanvasSWT ;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase {
+
+ static int duration = 500;
+
+ static class BigFlashingX implements GLEventListener
+ {
+ float r = 0f, g = 0f, b = 0f;
+
+ public void init( final GLAutoDrawable drawable )
+ {
+ final GL2 gl = drawable.getGL().getGL2() ;
+
+ gl.glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ) ;
+
+ gl.glEnable( GL.GL_LINE_SMOOTH ) ;
+ gl.glEnable( GL.GL_BLEND ) ;
+ gl.glBlendFunc( GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA ) ;
+ }
+
+ public void reshape( final GLAutoDrawable drawable, final int x, final int y, final int width, final int height )
+ {
+ // System.err.println( ">>>>>>>> reshape " + x + ", " + y + ", " + width + ", " +height ) ;
+ final GL2 gl = drawable.getGL().getGL2() ;
+
+ gl.glViewport( 0, 0, width, height ) ;
+
+ gl.glMatrixMode( GLMatrixFunc.GL_PROJECTION ) ;
+ gl.glLoadIdentity() ;
+ gl.glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ) ;
+
+ gl.glMatrixMode( GLMatrixFunc.GL_MODELVIEW ) ;
+ gl.glLoadIdentity() ;
+ }
+
+ public void display( final GLAutoDrawable drawable )
+ {
+ // System.err.println( ">>>> display" ) ;
+ final GL2 gl = drawable.getGL().getGL2() ;
+
+ // Sven: I could have been seeing things, but it seemed that if this
+ // glClear is in here twice it seems aggravates the problem. Not
+ // sure why other than it just takes longer, but this is pretty
+ // fast operation.
+ gl.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT ) ;
+ gl.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT ) ;
+
+ gl.glColor4f( r, g, b, 1.0f ) ;
+
+ gl.glBegin( GL.GL_LINES ) ;
+ {
+ gl.glVertex2f( -1.0f, 1.0f ) ;
+ gl.glVertex2f( 1.0f, -1.0f ) ;
+
+ gl.glVertex2f( -1.0f, -1.0f ) ;
+ gl.glVertex2f( 1.0f, 1.0f ) ;
+ }
+ gl.glEnd() ;
+
+ if(r<1f) {
+ r+=0.1f;
+ } else if(g<1f) {
+ g+=0.1f;
+ } else if(b<1f) {
+ b+=0.1f;
+ } else {
+ r = 0f;
+ g = 0f;
+ b = 0f;
+ }
+ }
+
+ public void dispose( final GLAutoDrawable drawable )
+ {
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static class ResizeThread extends Thread {
+ volatile boolean shallStop = false;
+ private final Shell _shell ;
+ private int _n ;
+
+ public ResizeThread( final Shell shell )
+ {
+ super();
+ _shell = shell ;
+ }
+
+ final Runnable resizeAction = new Runnable() {
+ public void run()
+ {
+ System.err.println("[R-i shallStop "+shallStop+", disposed "+_shell.isDisposed()+"]");
+ if( shallStop || _shell.isDisposed() ) {
+ return;
+ }
+ try {
+ if( _n % 2 == 0 ) {
+ _shell.setSize( 200, 200 ) ;
+ } else {
+ _shell.setSize( 400, 450 ) ;
+ }
+ } catch (final Exception e0) {
+ e0.printStackTrace();
+ Assert.assertTrue("Deadlock @ setSize: "+e0, false);
+ }
+ ++_n ;
+ } };
+
+ public void run()
+ {
+ // The problem was originally observed by grabbing the lower right
+ // corner of the window and moving the mouse around rapidly e.g. in
+ // a circle. Eventually the UI will hang with something similar to
+ // the backtrace noted in the bug report.
+ //
+ // This loop simulates rapid resizing by the user by toggling
+ // the shell back-and-forth between two sizes.
+
+ System.err.println("[R-0 shallStop "+shallStop+", disposed "+_shell.isDisposed()+"]");
+
+ final Display display = _shell.getDisplay();
+
+ while( !shallStop && !_shell.isDisposed() )
+ {
+ try
+ {
+ System.err.println("[R-n shallStop "+shallStop+", disposed "+_shell.isDisposed()+"]");
+ display.asyncExec( resizeAction );
+ display.wake();
+
+ Thread.sleep( 50L ) ;
+ } catch( final InterruptedException e ) {
+ break ;
+ }
+ }
+ System.err.println("*R-Exit* shallStop "+shallStop+", disposed "+_shell.isDisposed());
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static class KeyfireThread extends Thread
+ {
+ volatile boolean shallStop = false;
+ Display _display;
+ Robot _robot;
+ int _n = 0;
+
+ public KeyfireThread(final Robot robot, final Display display)
+ {
+ _robot = robot;
+ _display = display;
+ }
+
+ public void run()
+ {
+ System.err.println("[K-0]");
+
+ while( !shallStop )
+ {
+ try {
+ System.err.println("[K-"+_n+"]");
+ AWTRobotUtil.waitForIdle(_robot);
+ AWTRobotUtil.newtKeyPress(_n, _robot, true, KeyEvent.VK_0, 10);
+ AWTRobotUtil.newtKeyPress(_n, _robot, false, KeyEvent.VK_0, 0);
+ Thread.sleep( 40L ) ;
+ _n++;
+ if(!_display.isDisposed()) {
+ _display.wake();
+ }
+ } catch( final InterruptedException e ) {
+ break ;
+ }
+ }
+ System.err.println("*K-Exit*");
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ private volatile boolean shallStop = false;
+
+ static class SWT_DSC {
+ volatile Display display;
+ volatile Shell shell;
+ volatile Composite composite;
+ volatile com.jogamp.newt.Display swtNewtDisplay = null;
+
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ }});
+
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.NO_BACKGROUND );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ }});
+ swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse
+ }
+
+ public void dispose() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+ try {
+ display.syncExec(new Runnable() {
+ public void run() {
+ composite.dispose();
+ shell.dispose();
+ }});
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display.dispose();
+ }});
+ }
+ catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ swtNewtDisplay = null;
+ display = null;
+ shell = null;
+ composite = null;
+ }
+ class WaitAction implements Runnable {
+ private final long sleepMS;
+
+ WaitAction(final long sleepMS) {
+ this.sleepMS = sleepMS;
+ }
+ public void run() {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ try {
+ Thread.sleep(sleepMS);
+ } catch (final InterruptedException e) { }
+ }
+ }
+ }
+ final WaitAction awtRobotWaitAction = new WaitAction(AWTRobotUtil.TIME_SLICE);
+ }
+
+ @Test
+ public void test() throws InterruptedException, AWTException, InvocationTargetException {
+ final Robot robot = new Robot();
+
+ final SWT_DSC dsc = new SWT_DSC();
+ dsc.init();
+
+ final GLWindow glWindow;
+ {
+ final GLProfile gl2Profile = GLProfile.get( GLProfile.GL2 ) ;
+ final GLCapabilities caps = new GLCapabilities( gl2Profile ) ;
+ final com.jogamp.newt.Screen screen = NewtFactory.createScreen(dsc.swtNewtDisplay, 0);
+ glWindow = GLWindow.create( screen, caps ) ;
+ glWindow.addGLEventListener( new BigFlashingX() ) ;
+ glWindow.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyReleased(final com.jogamp.newt.event.KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ System.err.print(".");
+ glWindow.display();
+ }
+ });
+ NewtCanvasSWT.create( dsc.composite, 0, glWindow ) ;
+ }
+
+ dsc.display.syncExec( new Runnable() {
+ public void run() {
+ dsc.shell.setText( "NewtCanvasSWT Resize Bug Demo" ) ;
+ dsc.shell.setSize( 400, 450 ) ;
+ dsc.shell.open() ;
+ } } );
+ Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow, dsc.awtRobotWaitAction, true));
+
+ AWTRobotUtil.requestFocus(robot, glWindow, false);
+ AWTRobotUtil.setMouseToClientLocation(robot, glWindow, 50, 50);
+
+ shallStop = false;
+
+ final ResizeThread resizer;
+ {
+ resizer = new ResizeThread( dsc.shell ) ;
+ resizer.start() ;
+ }
+
+ final KeyfireThread keyfire;
+ {
+ keyfire = new KeyfireThread( robot, dsc.display ) ;
+ keyfire.start() ;
+ }
+
+ {
+ final Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(duration);
+ } catch (final InterruptedException e) {}
+ resizer.shallStop = true;
+ keyfire.shallStop = true;
+ try
+ {
+ resizer.join();
+ } catch( final InterruptedException e ) { }
+ try
+ {
+ keyfire.join();
+ } catch( final InterruptedException e ) { }
+ shallStop = true;
+ if( null != dsc.display && !dsc.display.isDisposed() ) {
+ dsc.display.wake();
+ }
+ } } );
+ t.setDaemon(true);
+ t.start();
+ }
+
+ try {
+ while( !shallStop && !dsc.display.isDisposed() ) {
+ dsc.display.syncExec( new Runnable() {
+ public void run() {
+ if( !dsc.display.isDisposed() && !dsc.display.readAndDispatch() && !shallStop ) {
+ // blocks on linux .. dsc.display.sleep();
+ try {
+ Thread.sleep(10);
+ } catch (final InterruptedException ie) { ie.printStackTrace(); }
+ }
+ } } );
+ }
+ } catch (final Exception e0) {
+ e0.printStackTrace();
+ Assert.assertTrue("Deadlock @ dispatch: "+e0, false);
+ }
+
+ // canvas is disposed implicit, due to it's disposed listener !
+
+ dsc.dispose();
+ }
+
+ public static void main( final String[] args ) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ duration = MiscUtils.atoi(args[++i], duration);
+ }
+ }
+ System.out.println("durationPerTest: "+duration);
+ org.junit.runner.JUnitCore.main(TestNewtCanvasSWTBug628ResizeDeadlockAWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java
index fe40cec28..380bd3f7d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.swt;
import javax.media.opengl.GLAutoDrawable;
@@ -39,19 +39,24 @@ import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
-
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.After;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.newt.swt.NewtCanvasSWT;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
@@ -59,17 +64,18 @@ import com.jogamp.opengl.util.texture.TextureIO;
/**
* Tests that a basic SWT app can open without crashing under different GL profiles
- * _and_ custom GLCapabilities.
- * <p>
+ * _and_ custom GLCapabilities.
+ * <p>
* Uses JOGL's NewtCanvasSWT, which allows to be a native container of a NEWT Window.<br/>
* This method allows utilizing custom GLCapability settings,
* independent from the already instantiated SWT visual.
* </p>
* <p>
- * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/
+ * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/
* SWT running on Mac OSX, i.e. to enforce UI action on the main thread.
* </p>
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestNewtCanvasSWTGLn extends UITestCase {
static int duration = 250;
@@ -80,6 +86,7 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
Display display = null;
Shell shell = null;
Composite composite = null;
+ com.jogamp.newt.Display swtNewtDisplay = null;
@BeforeClass
public static void startup() {
@@ -89,9 +96,12 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
@Before
public void init() {
SWTAccessor.invoke(true, new Runnable() {
- public void run() {
+ public void run() {
display = new Display();
Assert.assertNotNull( display );
+ }});
+ display.syncExec(new Runnable() {
+ public void run() {
shell = new Shell( display );
Assert.assertNotNull( shell );
shell.setLayout( new FillLayout() );
@@ -99,6 +109,7 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
composite.setLayout( new FillLayout() );
Assert.assertNotNull( composite );
}});
+ swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse
}
@After
@@ -107,27 +118,50 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
Assert.assertNotNull( shell );
Assert.assertNotNull( composite );
try {
- SWTAccessor.invoke(true, new Runnable() {
+ display.syncExec(new Runnable() {
public void run() {
composite.dispose();
shell.dispose();
+ }});
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
display.dispose();
}});
}
- catch( Throwable throwable ) {
+ catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
+ swtNewtDisplay = null;
display = null;
shell = null;
composite = null;
}
- protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo,
- boolean postAttach, boolean useAnimator ) throws InterruptedException {
+ class WaitAction implements Runnable {
+ private final long sleepMS;
+
+ WaitAction(final long sleepMS) {
+ this.sleepMS = sleepMS;
+ }
+ public void run() {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ try {
+ Thread.sleep(sleepMS);
+ } catch (final InterruptedException e) { }
+ }
+ }
+ }
+ final WaitAction awtRobotWaitAction = new WaitAction(AWTRobotUtil.TIME_SLICE);
+ final WaitAction generalWaitAction = new WaitAction(10);
+
+ protected void runTestAGL( final GLCapabilitiesImmutable caps, final GLEventListener demo,
+ final boolean postAttach, final boolean useAnimator ) throws InterruptedException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
-
- final GLWindow glWindow1 = GLWindow.create(caps);
+
+ final Screen screen = NewtFactory.createScreen(swtNewtDisplay, 0);
+ final GLWindow glWindow1 = GLWindow.create(screen, caps);
Assert.assertNotNull(glWindow1);
Assert.assertEquals(false, glWindow1.isVisible());
Assert.assertEquals(false, glWindow1.isNativeValid());
@@ -135,7 +169,7 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
glWindow1.addGLEventListener(demo);
glWindow1.addGLEventListener(new GLEventListener() {
int displayCount = 0;
- public void init(final GLAutoDrawable drawable) { }
+ public void init(final GLAutoDrawable drawable) { }
public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
public void display(final GLAutoDrawable drawable) {
if(displayCount < 3) {
@@ -143,25 +177,30 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
}
}
public void dispose(final GLAutoDrawable drawable) { }
- });
-
+ });
+
final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite, 0, postAttach ? null : glWindow1 );
Assert.assertNotNull( canvas1 );
- SWTAccessor.invoke(true, new Runnable() {
+ display.syncExec( new Runnable() {
public void run() {
shell.setText( getSimpleTestName(".") );
shell.setSize( 640, 480 );
shell.open();
}
});
-
+
if(postAttach) {
canvas1.setNEWTChild(glWindow1);
}
-
+
+ Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow1, awtRobotWaitAction, true));
+
+ System.err.println("GLWindow LOS.0: "+glWindow1.getLocationOnScreen(null));
+ System.err.println("NewtCanvasSWT LOS.0: "+canvas1.getNativeWindow().getLocationOnScreen(null));
+
// canvas1.update();
-
+
Animator anim;
if(useAnimator) {
anim = new Animator(glWindow1);
@@ -169,24 +208,21 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
} else {
anim = null;
}
-
- long lStartTime = System.currentTimeMillis();
- long lEndTime = lStartTime + duration;
+
+ final long lStartTime = System.currentTimeMillis();
+ final long lEndTime = lStartTime + duration;
try {
while( (System.currentTimeMillis() < lEndTime) && !canvas1.isDisposed() ) {
- if( !display.readAndDispatch() ) {
- // blocks on linux .. display.sleep();
- Thread.sleep(10);
- }
+ generalWaitAction.run();
}
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
if(null != anim) {
anim.stop();
}
-
+
canvas1.dispose();
}
@@ -204,27 +240,19 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
public void postAttach_WithAnimator() throws InterruptedException {
runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), true /* postAttach */, true /* animator */);
}
-
+
@Test
public void test_MultisampleAndAlpha() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
caps.setSampleBuffers(true);
caps.setNumSamples(2);
runTestAGL( caps, new MultisampleDemoES2(true), false /* postAttach */, false /* animator */);
}
- static int atoi(String a) {
- int i=0;
- try {
- i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
- return i;
- }
-
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
- duration = atoi(args[++i]);
+ duration = MiscUtils.atoi(args[++i], duration);
}
}
System.out.println("durationPerTest: "+duration);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
index 080dff396..f18e10bb1 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -51,10 +51,13 @@ import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.os.Platform;
import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
/**
@@ -62,9 +65,10 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
* the SWT_AWT bridge.
* @author Wade Walker, et.al.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestSWTAccessor03AWTGLn extends UITestCase {
- static final int duration = 250;
+ static int duration = 250;
Display display = null;
Shell shell = null;
@@ -81,11 +85,18 @@ public class TestSWTAccessor03AWTGLn extends UITestCase {
UITestCase.setTestSupported(false);
return;
}
- System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() );
- Frame f0 = new Frame("Test - AWT 1st");
+ System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() );
+ final Frame f0 = new Frame("Test - AWT 1st");
f0.add(new java.awt.Label("AWT was here 1st"));
- f0.pack();
- f0.setVisible(true);
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f0.pack();
+ f0.setVisible(true);
+ }});
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
if(!GLProfile.isAvailable(GLProfile.GL2)) {
setTestSupported(false);
}
@@ -93,7 +104,7 @@ public class TestSWTAccessor03AWTGLn extends UITestCase {
protected void init() throws InterruptedException, InvocationTargetException {
SWTAccessor.invoke(true, new Runnable() {
- public void run() {
+ public void run() {
display = new Display();
Assert.assertNotNull( display );
shell = new Shell( display );
@@ -112,15 +123,19 @@ public class TestSWTAccessor03AWTGLn extends UITestCase {
Assert.assertNotNull( shell );
Assert.assertNotNull( composite );
Assert.assertNotNull( glcanvas );
- javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ final Runnable releaseAWT = new Runnable() {
public void run() {
+ // deadlocks Java7 on Windows
frame.setVisible(false);
frame.remove(glcanvas);
frame.dispose();
frame = null;
glcanvas = null;
- }});
-
+ } };
+ // Deadlocks Java7 on Windows
+ // javax.swing.SwingUtilities.invokeAndWait( releaseAWT );
+ releaseAWT.run();
+
SWTAccessor.invoke(true, new Runnable() {
public void run() {
composite.dispose();
@@ -133,47 +148,47 @@ public class TestSWTAccessor03AWTGLn extends UITestCase {
}});
}
- protected void runTestGL( GLProfile glprofile ) throws InterruptedException, InvocationTargetException {
+ protected void runTestGL( final GLProfile glprofile ) throws InterruptedException, InvocationTargetException {
init();
try {
- GLCapabilities glcapabilities = new GLCapabilities( glprofile );
+ final GLCapabilities glcapabilities = new GLCapabilities( glprofile );
glcanvas = new GLCanvas( glcapabilities );
Assert.assertNotNull( glcanvas );
frame.add( glcanvas );
-
+
glcanvas.addGLEventListener( new GLEventListener() {
/* @Override */
- public void init( GLAutoDrawable glautodrawable ) {
+ public void init( final GLAutoDrawable glautodrawable ) {
}
-
+
/* @Override */
- public void dispose( GLAutoDrawable glautodrawable ) {
+ public void dispose( final GLAutoDrawable glautodrawable ) {
}
-
+
/* @Override */
- public void display( GLAutoDrawable glautodrawable ) {
- Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getWidth(), glautodrawable.getHeight() );
- GL2ES1 gl = glautodrawable.getGL().getGL2ES1();
+ public void display( final GLAutoDrawable glautodrawable ) {
+ final Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getSurfaceWidth(), glautodrawable.getSurfaceHeight() );
+ final GL2ES1 gl = glautodrawable.getGL().getGL2ES1();
OneTriangle.render( gl, rectangle.width, rectangle.height );
}
-
+
/* @Override */
- public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height ) {
- Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getWidth(), glautodrawable.getHeight() );
- GL2ES1 gl = glautodrawable.getGL().getGL2ES1();
+ public void reshape( final GLAutoDrawable glautodrawable, final int x, final int y, final int width, final int height ) {
+ final Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getSurfaceWidth(), glautodrawable.getSurfaceHeight() );
+ final GL2ES1 gl = glautodrawable.getGL().getGL2ES1();
OneTriangle.setup( gl, rectangle.width, rectangle.height );
}
});
-
+
SWTAccessor.invoke(true, new Runnable() {
public void run() {
shell.setText( getClass().getName() );
shell.setSize( 640, 480 );
shell.open();
}});
-
- long lStartTime = System.currentTimeMillis();
- long lEndTime = lStartTime + duration;
+
+ final long lStartTime = System.currentTimeMillis();
+ final long lEndTime = lStartTime + duration;
try {
while( (System.currentTimeMillis() < lEndTime) && !composite.isDisposed() ) {
SWTAccessor.invoke(true, new Runnable() {
@@ -182,12 +197,12 @@ public class TestSWTAccessor03AWTGLn extends UITestCase {
// blocks on linux .. display.sleep();
try {
Thread.sleep(10);
- } catch (InterruptedException e) { }
+ } catch (final InterruptedException e) { }
}
}});
}
}
- catch( Throwable throwable ) {
+ catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
@@ -198,11 +213,16 @@ public class TestSWTAccessor03AWTGLn extends UITestCase {
@Test
public void test() throws InterruptedException, InvocationTargetException {
- GLProfile glprofile = GLProfile.getGL2ES1();
+ final GLProfile glprofile = GLProfile.getGL2ES1();
runTestGL( glprofile );
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ duration = MiscUtils.atoi(args[++i], duration);
+ }
+ }
org.junit.runner.JUnitCore.main( TestSWTAccessor03AWTGLn.class.getName() );
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java
new file mode 100644
index 000000000..7b64838cc
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java
@@ -0,0 +1,350 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.swt;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.SWT ;
+
+import org.eclipse.swt.layout.FillLayout ;
+
+import org.eclipse.swt.widgets.Composite ;
+import org.eclipse.swt.widgets.Display ;
+import org.eclipse.swt.widgets.Shell ;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities ;
+import javax.media.opengl.GLProfile;
+
+import jogamp.newt.swt.SWTEDTUtil;
+import jogamp.newt.swt.event.SWTNewtEventFactory;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.opengl.GLWindow ;
+import com.jogamp.newt.swt.NewtCanvasSWT ;
+import com.jogamp.opengl.swt.GLCanvas;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSWTBug643AsyncExec extends UITestCase {
+
+ static int duration = 500;
+ static boolean useAnimator = false;
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static void resetSWTAndNEWTEDTCounter() {
+ synchronized(swtCountSync) {
+ swtCount=0;
+ }
+ synchronized(edtCountSync) {
+ edtCount=0;
+ }
+ }
+ static int incrSWTCount() {
+ synchronized(swtCountSync) {
+ swtCount++;
+ return swtCount;
+ }
+ }
+ static int getSWTCount() {
+ synchronized(swtCountSync) {
+ return swtCount;
+ }
+ }
+ static int incrNEWTCount() {
+ synchronized(edtCountSync) {
+ edtCount++;
+ return edtCount;
+ }
+ }
+ static int getNEWTCount() {
+ synchronized(edtCountSync) {
+ return edtCount;
+ }
+ }
+ static Object swtCountSync = new Object();
+ static int swtCount = 0;
+ static Object edtCountSync = new Object();
+ static int edtCount = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static class AsyncExecEDTFeederThread extends Thread {
+ volatile boolean shallStop = false;
+ private final Display swtDisplay ;
+ private final jogamp.newt.DisplayImpl newtDisplay;
+ private int swtN, newtN ;
+
+ public AsyncExecEDTFeederThread( final Display swtDisplay, final com.jogamp.newt.Display newtDisplay )
+ {
+ super();
+ this.swtDisplay = swtDisplay ;
+ this.newtDisplay = (jogamp.newt.DisplayImpl)newtDisplay;
+ }
+
+ final Runnable swtAsyncAction = new Runnable() {
+ public void run()
+ {
+ ++swtN ; incrSWTCount();
+ System.err.println("[SWT A-i shallStop "+shallStop+"]: Counter[loc "+swtN+", glob: "+getSWTCount()+"]");
+ } };
+
+ final Runnable newtAsyncAction = new Runnable() {
+ public void run()
+ {
+ ++newtN ; incrNEWTCount();
+ System.err.println("[NEWT A-i shallStop "+shallStop+"]: Counter[loc "+newtN+", glob: "+getNEWTCount()+"]");
+ } };
+
+ public void run()
+ {
+ System.err.println("[A-0 shallStop "+shallStop+"]");
+
+ while( !shallStop && !swtDisplay.isDisposed() )
+ {
+ try
+ {
+ if( !swtDisplay.isDisposed() ) {
+ swtDisplay.asyncExec( swtAsyncAction );
+ }
+ if(null != newtDisplay && newtDisplay.isNativeValid() && newtDisplay.getEDTUtil().isRunning()) {
+ // only perform async exec on valid and already running NEWT EDT!
+ newtDisplay.runOnEDTIfAvail(false, newtAsyncAction);
+ }
+ Thread.sleep( 50L ) ;
+ } catch( final InterruptedException e ) {
+ break ;
+ }
+ }
+ System.err.println("*R-Exit* shallStop "+shallStop);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ private volatile boolean shallStop = false;
+
+ static class SWT_DSC {
+ Display display;
+ Shell shell;
+ Composite composite;
+
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ }});
+
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.NO_BACKGROUND );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ }});
+ }
+
+ public void dispose() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+ try {
+ display.syncExec(new Runnable() {
+ public void run() {
+ composite.dispose();
+ shell.dispose();
+ }});
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display.dispose();
+ }});
+ }
+ catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ display = null;
+ shell = null;
+ composite = null;
+ }
+ }
+
+ private void testImpl(final boolean useJOGLGLCanvas, final boolean useNewtCanvasSWT, final boolean glWindowPreVisible) throws InterruptedException, InvocationTargetException {
+ resetSWTAndNEWTEDTCounter();
+
+ final SWT_DSC dsc = new SWT_DSC();
+ dsc.init();
+
+ final com.jogamp.newt.Display newtDisplay;
+ {
+ final GLProfile gl2Profile = GLProfile.get( GLProfile.GL2 ) ;
+ final GLCapabilities caps = new GLCapabilities( gl2Profile ) ;
+
+ final GLAutoDrawable glad;
+ if( useJOGLGLCanvas ) {
+ final GearsES2 demo = new GearsES2();
+ final GLCanvas glc = GLCanvas.create(dsc.composite, 0, caps, null);
+ final SWTNewtEventFactory swtNewtEventFactory = new SWTNewtEventFactory();
+ swtNewtEventFactory.attachDispatchListener(glc, glc, demo.gearsMouse, demo.gearsKeys);
+ glc.addGLEventListener( demo ) ;
+ glad = glc;
+ newtDisplay = null;
+ } else if( useNewtCanvasSWT ) {
+ newtDisplay = NewtFactory.createDisplay(null, false); // no-reuse
+ final com.jogamp.newt.Screen screen = NewtFactory.createScreen(newtDisplay, 0);
+ final GLWindow glWindow = GLWindow.create( screen, caps ) ;
+ glWindow.addGLEventListener( new GearsES2() ) ;
+ if( glWindowPreVisible ) {
+ newtDisplay.setEDTUtil(new SWTEDTUtil(newtDisplay, dsc.display)); // Especially Windows requires creation access via same thread!
+ glWindow.setVisible(true);
+ AWTRobotUtil.waitForRealized(glWindow, true);
+ Thread.sleep(120); // let it render a bit, before consumed by SWT
+ }
+ glad = glWindow;
+ NewtCanvasSWT.create( dsc.composite, 0, glWindow ) ;
+ } else {
+ throw new InternalError("XXX");
+ }
+ if(useAnimator) {
+ final Animator animator = new Animator(glad);
+ animator.start();
+ }
+ }
+
+ System.err.println("**** Pre Shell Open");
+ dsc.display.syncExec( new Runnable() {
+ public void run() {
+ dsc.shell.setText( "NewtCanvasSWT Resize Bug Demo" ) ;
+ dsc.shell.setSize( 400, 450 ) ;
+ dsc.shell.open() ;
+ } } );
+ System.err.println("**** Post Shell Open");
+
+ shallStop = false;
+
+ final int[] counterBeforeExit = new int[] { 0 /* SWT */, 0 /* NEWT */ };
+
+ final AsyncExecEDTFeederThread asyncExecFeeder;
+ {
+ asyncExecFeeder = new AsyncExecEDTFeederThread(dsc.display, newtDisplay) ;
+ asyncExecFeeder.start() ;
+ }
+
+ {
+ final Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(duration);
+ } catch (final InterruptedException e) {}
+
+ counterBeforeExit[0] = getSWTCount();
+ counterBeforeExit[1] = getNEWTCount();
+ asyncExecFeeder.shallStop = true;
+ try
+ {
+ asyncExecFeeder.join();
+ } catch( final InterruptedException e ) { }
+ shallStop = true;
+ dsc.display.wake();
+ } } );
+ t.setDaemon(true);
+ t.start();
+ }
+
+ try {
+ final Display d = dsc.display;
+ while( !shallStop && !d.isDisposed() ) {
+ if( !d.readAndDispatch() && !shallStop ) {
+ // blocks on linux .. dsc.display.sleep();
+ Thread.sleep(10);
+ }
+ }
+ } catch (final Exception e0) {
+ e0.printStackTrace();
+ Assert.assertTrue("Deadlock @ dispatch: "+e0, false);
+ }
+
+ // canvas is disposed implicit, due to it's disposed listener !
+
+ dsc.dispose();
+
+ System.err.println("EDT Counter before exit: SWT " + counterBeforeExit[0] + ", NEWT "+counterBeforeExit[1]);
+ Assert.assertTrue("SWT EDT Counter not greater zero before dispose!", 0 < counterBeforeExit[0]);
+ if( null != newtDisplay ) {
+ Assert.assertTrue("NEWT EDT Counter not greater zero before dispose!", 0 < counterBeforeExit[1]);
+ }
+ }
+
+ @Test
+ public void test01JOGLGLCanvas() throws InterruptedException, InvocationTargetException {
+ testImpl(true /* useJOGLGLCanvas */, false /* useNewtCanvasSWT */, false /* glWindowPreVisible */);
+ }
+
+ @Test
+ public void test02NewtCanvasSWTSimple() throws InterruptedException, InvocationTargetException {
+ testImpl(false /* useJOGLGLCanvas */, true /* useNewtCanvasSWT */, false /* glWindowPreVisible */);
+ }
+
+ @Test
+ public void test02NewtCanvasSWTPreVisible() throws InterruptedException, InvocationTargetException {
+ testImpl(false /* useJOGLGLCanvas */, true /* useNewtCanvasSWT */, true /* glWindowPreVisible */);
+ }
+
+ public static void main( final String[] args ) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ duration = MiscUtils.atoi(args[++i], duration);
+ } else if(args[i].equals("-anim")) {
+ useAnimator = true;
+ }
+ }
+ System.out.println("durationPerTest: "+duration);
+ org.junit.runner.JUnitCore.main(TestSWTBug643AsyncExec.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java
index 0bd47c980..69911c599 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.swt;
import javax.media.opengl.GL2ES1;
@@ -52,6 +52,8 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.After;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
@@ -59,11 +61,12 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
/**
* Tests that a basic SWT app can open without crashing under different GL profiles.
- * <p>
+ * <p>
* Uses the SWT GLCanvas <code>org.eclipse.swt.opengl.GLCanvas</code>.
* </p>
* @author Wade Walker, et.al.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestSWTEclipseGLCanvas01GLn extends UITestCase {
static int duration = 250;
@@ -83,7 +86,7 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase {
@Before
public void init() {
SWTAccessor.invoke(true, new Runnable() {
- public void run() {
+ public void run() {
display = new Display();
Assert.assertNotNull( display );
shell = new Shell( display );
@@ -108,7 +111,7 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase {
display.dispose();
}});
}
- catch( Throwable throwable ) {
+ catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
@@ -117,8 +120,8 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase {
composite = null;
}
- protected void runTestAGL( GLProfile glprofile ) throws InterruptedException {
- GLData gldata = new GLData();
+ protected void runTestAGL( final GLProfile glprofile ) throws InterruptedException {
+ final GLData gldata = new GLData();
gldata.doubleBuffer = true;
// need SWT.NO_BACKGROUND to prevent SWT from clearing the window
// at the wrong times (we use glClear for this instead)
@@ -130,11 +133,11 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase {
// fix the viewport when the user resizes the window
glcanvas.addListener( SWT.Resize, new Listener() {
- public void handleEvent( Event event ) {
- Rectangle rectangle = glcanvas.getClientArea();
+ public void handleEvent( final Event event ) {
+ final Rectangle rectangle = glcanvas.getClientArea();
glcanvas.setCurrent();
glcontext.makeCurrent();
- GL2ES1 gl = glcontext.getGL().getGL2ES1();
+ final GL2ES1 gl = glcontext.getGL().getGL2ES1();
OneTriangle.setup( gl, rectangle.width, rectangle.height );
glcontext.release();
System.err.println("resize");
@@ -143,24 +146,24 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase {
// draw the triangle when the OS tells us that any part of the window needs drawing
glcanvas.addPaintListener( new PaintListener() {
- public void paintControl( PaintEvent paintevent ) {
- Rectangle rectangle = glcanvas.getClientArea();
+ public void paintControl( final PaintEvent paintevent ) {
+ final Rectangle rectangle = glcanvas.getClientArea();
glcanvas.setCurrent();
glcontext.makeCurrent();
- GL2ES1 gl = glcontext.getGL().getGL2ES1();
+ final GL2ES1 gl = glcontext.getGL().getGL2ES1();
OneTriangle.render( gl, rectangle.width, rectangle.height );
glcanvas.swapBuffers();
glcontext.release();
System.err.println("paint");
}
});
-
+
shell.setText( getClass().getName() );
shell.setSize( 640, 480 );
shell.open();
- long lStartTime = System.currentTimeMillis();
- long lEndTime = lStartTime + duration;
+ final long lStartTime = System.currentTimeMillis();
+ final long lEndTime = lStartTime + duration;
try {
while( (System.currentTimeMillis() < lEndTime) && !glcanvas.isDisposed() ) {
if( !display.readAndDispatch() ) {
@@ -168,7 +171,7 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase {
Thread.sleep(10);
}
}
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
@@ -177,19 +180,19 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase {
@Test
public void test() throws InterruptedException {
- GLProfile glprofile = GLProfile.getGL2ES1();
+ final GLProfile glprofile = GLProfile.getGL2ES1();
runTestAGL( glprofile );
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
duration = atoi(args[++i]);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
index 6d9e2219c..04ffdcb1c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.swt;
import javax.media.opengl.GLAutoDrawable;
@@ -46,31 +46,36 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.After;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.opengl.swt.GLCanvas;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.texture.TextureIO;
/**
* Tests that a basic SWT app can open without crashing under different GL profiles.
- * <p>
- * Uses JOGL's new SWT GLCanvas.
- * </p>
* <p>
- * Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used.
+ * Uses JOGL's new SWT GLCanvas,
+ * which allows utilizing custom GLCapability settings,
+ * independent from the already instantiated SWT visual.
* </p>
* <p>
- * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/
+ * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/
* SWT running on Mac OSX, i.e. to enforce UI action on the main thread.
* </p>
* @author Wade Walker, et al.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
static int duration = 250;
+ static boolean doAnimation = true;
static final int iwidth = 640;
static final int iheight = 480;
@@ -87,13 +92,16 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
@Before
public void init() {
SWTAccessor.invoke(true, new Runnable() {
- public void run() {
+ public void run() {
display = new Display();
Assert.assertNotNull( display );
+ }});
+ display.syncExec(new Runnable() {
+ public void run() {
shell = new Shell( display );
Assert.assertNotNull( shell );
shell.setLayout( new FillLayout() );
- composite = new Composite( shell, SWT.NONE );
+ composite = new Composite( shell, SWT.NO_BACKGROUND );
composite.setLayout( new FillLayout() );
Assert.assertNotNull( composite );
}});
@@ -105,14 +113,17 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
Assert.assertNotNull( shell );
Assert.assertNotNull( composite );
try {
- SWTAccessor.invoke(true, new Runnable() {
+ display.syncExec(new Runnable() {
public void run() {
composite.dispose();
shell.dispose();
+ }});
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
display.dispose();
}});
}
- catch( Throwable throwable ) {
+ catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
@@ -121,16 +132,16 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
composite = null;
}
- protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo ) throws InterruptedException {
+ protected void runTestAGL( final GLCapabilitiesImmutable caps, final GLEventListener demo ) throws InterruptedException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
-
- final GLCanvas canvas = GLCanvas.create( composite, 0, caps, null, null);
+
+ final GLCanvas canvas = GLCanvas.create( composite, 0, caps, null);
Assert.assertNotNull( canvas );
canvas.addGLEventListener( demo );
canvas.addGLEventListener(new GLEventListener() {
int displayCount = 0;
- public void init(final GLAutoDrawable drawable) { }
+ public void init(final GLAutoDrawable drawable) { }
public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
public void display(final GLAutoDrawable drawable) {
if(displayCount < 3) {
@@ -138,17 +149,23 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
}
}
public void dispose(final GLAutoDrawable drawable) { }
- });
-
- SWTAccessor.invoke(true, new Runnable() {
+ });
+
+ display.syncExec(new Runnable() {
public void run() {
shell.setText( getSimpleTestName(".") );
shell.setSize( 640, 480 );
shell.open();
} } );
-
- long lStartTime = System.currentTimeMillis();
- long lEndTime = lStartTime + duration;
+
+ final Animator anim = new Animator();
+ if(doAnimation) {
+ anim.add(canvas);
+ anim.start();
+ }
+
+ final long lStartTime = System.currentTimeMillis();
+ final long lEndTime = lStartTime + duration;
try {
while( (System.currentTimeMillis() < lEndTime) && !canvas.isDisposed() ) {
if( !display.readAndDispatch() ) {
@@ -156,11 +173,14 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
Thread.sleep(10);
}
}
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
- SWTAccessor.invoke(true, new Runnable() {
+
+ anim.stop();
+
+ display.syncExec(new Runnable() {
public void run() {
canvas.dispose();
} } );
@@ -171,18 +191,28 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2() );
}
- static int atoi(String a) {
+ @Test
+ public void test_MultisampleAndAlpha() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(2);
+ runTestAGL( caps, new MultisampleDemoES2(true) );
+ }
+
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
duration = atoi(args[++i]);
+ } else if(args[i].equals("-still")) {
+ doAnimation = false;
}
}
System.out.println("durationPerTest: "+duration);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/OffscreenPrintable.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/OffscreenPrintable.java
new file mode 100644
index 000000000..a59662bd2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/OffscreenPrintable.java
@@ -0,0 +1,182 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+import java.awt.print.PageFormat;
+import java.awt.print.Paper;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.nativewindow.awt.DirectDataBufferInt;
+import com.jogamp.opengl.util.TileRenderer;
+
+/**
+ * {@link Printable} implementation using NIO {@link DirectDataBufferInt} {@link BufferedImage}
+ * for offscreen rendered printing.
+ *
+ * @see OnscreenPrintable
+ * @see PrintableBase
+ */
+public class OffscreenPrintable extends PrintableBase implements Printable {
+
+ public final int imageType;
+ public final String pngFilename;
+
+ /**
+ *
+ * @param job
+ * @param printContainer
+ * @param printDPI
+ * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples
+ * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param imageType AWT BufferedImage type (must be one of the integer types)
+ * @param pngFilename TODO
+ */
+ public OffscreenPrintable(final PrinterJob job, final Container printContainer, final int printDPI, final int numSamples, final int tileWidth, final int tileHeight, final int imageType, final String pngFilename) {
+ super(job, printContainer, printDPI, numSamples, tileWidth, tileHeight);
+ this.imageType = imageType;
+ this.pngFilename = pngFilename;
+ }
+
+ @Override
+ public int print(final Graphics g, final PageFormat pf, final int page) throws PrinterException {
+ if (page > 0) { // We have only one page, and 'page' is zero-based
+ return NO_SUCH_PAGE;
+ }
+
+ lockPrinting.lock();
+ try {
+ final Paper paper = pf.getPaper();
+ final double paperWWidthInch = paper.getWidth() / 72.0;
+ final double paperWHeightInch = paper.getHeight() / 72.0;
+ final double paperIWidthInch = paper.getImageableWidth() / 72.0;
+ final double paperIHeightInch = paper.getImageableHeight() / 72.0;
+ final double paperWWidthMM = paperWWidthInch * MM_PER_INCH;
+ final double paperWHeightMM = paperWHeightInch * MM_PER_INCH;
+ final double paperIWidthMM = paperIWidthInch * MM_PER_INCH;
+ final double paperIHeightMM = paperIHeightInch * MM_PER_INCH;
+
+ final double pfWWidthInch = pf.getWidth() / 72.0;
+ final double pfWHeightInch = pf.getHeight() / 72.0;
+ final double pfIWidthInch = pf.getImageableWidth() / 72.0;
+ final double pfIHeightInch = pf.getImageableHeight() / 72.0;
+ final double pfWWidthMM = pfWWidthInch * MM_PER_INCH;
+ final double pfWHeightMM = pfWHeightInch * MM_PER_INCH;
+ final double pfIWidthMM = pfIWidthInch * MM_PER_INCH;
+ final double pfIHeightMM = pfIHeightInch * MM_PER_INCH;
+
+ System.err.println("PF: Paper whole size "+
+ Math.round(paperWWidthMM)+" x "+Math.round(paperWHeightMM)+" mm, "+
+ Math.round(paperWWidthInch)+" x "+Math.round(paperWHeightInch)+" inch");
+
+ System.err.println("PF: Paper image size "+paper.getImageableX()+" / "+paper.getImageableY()+" "+
+ Math.round(paperIWidthMM)+" x "+Math.round(paperIHeightMM)+" mm, "+
+ Math.round(paperIWidthInch)+" x "+Math.round(paperIHeightInch)+" inch, "+
+ Math.round(paper.getImageableWidth())+"x"+Math.round(paper.getImageableHeight())+" 72dpi dots");
+
+ System.err.println("PF: Page whole size "+
+ Math.round(pfWWidthMM)+" x "+Math.round(pfWHeightMM)+" mm, "+
+ Math.round(pfWWidthInch)+" x "+Math.round(pfWHeightInch)+" inch");
+
+ System.err.println("PF: Page image size "+pf.getImageableX()+" / "+pf.getImageableY()+" "+
+ Math.round(pfIWidthMM)+" x "+Math.round(pfIHeightMM)+" mm, "+
+ Math.round(pfIWidthInch)+" x "+Math.round(pfIHeightInch)+" inch, "+
+ Math.round(pf.getImageableWidth())+"x"+Math.round(pf.getImageableHeight())+" 72dpi dots");
+
+ System.err.println("PF: Page orientation "+pf.getOrientation());
+
+ /**
+ * See: 'Scaling of Frame and GL content' in Class description!
+ * Note: Frame size contains the frame border (i.e. insets)!
+ */
+ final Insets frameInsets = cont.getInsets();
+ final int frameWidth = cont.getWidth();
+ final int frameHeight= cont.getHeight();
+ final double scaleGraphics = dpi / 72.0;
+ final int frameSWidth = (int) ( frameWidth * scaleGraphics );
+ final int frameSHeight = (int) ( frameHeight * scaleGraphics );
+ final double scaleComp72;
+ {
+ final double sx = pf.getImageableWidth() / frameSWidth;
+ final double sy = pf.getImageableHeight() / frameSHeight;
+ scaleComp72 = Math.min(sx, sy);
+ }
+
+ System.err.println("PRINT.offscrn thread "+Thread.currentThread().getName());
+ System.err.println("PRINT.offscrn DPI: scaleGraphics "+scaleGraphics+", scaleComp72 "+scaleComp72);
+ System.err.println("PRINT.offscrn DPI: frame: border "+frameInsets+", size "+frameWidth+"x"+frameHeight+
+ " -> scaled "+frameSWidth+ "x" + frameSHeight);
+
+ final BufferedImage image = DirectDataBufferInt.createBufferedImage(frameSWidth, frameSHeight, imageType, null /* location */, null /* properties */);
+ {
+ System.err.println("PRINT.offscrn image "+image);
+ final Graphics2D g2d = (Graphics2D) image.getGraphics();
+ g2d.setClip(0, 0, frameSWidth, frameSHeight);
+ g2d.scale(scaleGraphics, scaleGraphics);
+ // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ cont.printAll(g2d);
+ }
+ });
+ }
+ if( null != pngFilename ) {
+ final File fout = new File(pngFilename);
+ try {
+ ImageIO.write(image, "png", fout);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ final Graphics2D g2d = (Graphics2D)g;
+ g2d.translate(pf.getImageableX(), pf.getImageableY());
+ g2d.scale(scaleComp72, scaleComp72);
+ g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null); // Null ImageObserver since image data is ready.
+
+ /* tell the caller that this page is part of the printed document */
+ return PAGE_EXISTS;
+ } finally {
+ lockPrinting.unlock();
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/OnscreenPrintable.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/OnscreenPrintable.java
new file mode 100644
index 000000000..228fa81e2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/OnscreenPrintable.java
@@ -0,0 +1,165 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+import java.awt.RenderingHints;
+import java.awt.print.PageFormat;
+import java.awt.print.Paper;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.opengl.util.TileRenderer;
+
+/**
+ * <h5>Scaling of Frame and GL content</h5>
+ * <p>
+ * We fit the frame into the imageable area with for 72 dpi,
+ * assuming that is the default AWT painting density.
+ * </p>
+ * <p>
+ * The frame borders are considered.
+ * </p>
+ * <p>
+ * The frame's scale factor is used for the graphics print matrix
+ * of the overall print-job, hence no frame resize is required.
+ * </p>
+ * <p>
+ * The GL scale factor 'scaleGLMatXY', 72dpi/glDPI, is passed to the GL object
+ * which locally scales the print matrix and renders the scene with 1/scaleGLMatXY pixels.
+ * </p>
+ */
+public class OnscreenPrintable extends PrintableBase implements Printable {
+
+ /**
+ *
+ * @param job
+ * @param printContainer
+ * @param printDPI
+ * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples
+ * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ */
+ public OnscreenPrintable(final PrinterJob job, final Container printContainer, final int printDPI, final int numSamples, final int tileWidth, final int tileHeight) {
+ super(job, printContainer, printDPI, numSamples, tileWidth, tileHeight);
+ }
+
+
+ @Override
+ public int print(final Graphics g, final PageFormat pf, final int page) throws PrinterException {
+ if (page > 0) { // We have only one page, and 'page' is zero-based
+ return NO_SUCH_PAGE;
+ }
+
+ lockPrinting.lock();
+ try {
+ final Paper paper = pf.getPaper();
+ final double paperWWidthInch = paper.getWidth() / 72.0;
+ final double paperWHeightInch = paper.getHeight() / 72.0;
+ final double paperIWidthInch = paper.getImageableWidth() / 72.0;
+ final double paperIHeightInch = paper.getImageableHeight() / 72.0;
+ final double paperWWidthMM = paperWWidthInch * MM_PER_INCH;
+ final double paperWHeightMM = paperWHeightInch * MM_PER_INCH;
+ final double paperIWidthMM = paperIWidthInch * MM_PER_INCH;
+ final double paperIHeightMM = paperIHeightInch * MM_PER_INCH;
+
+ final double pfWWidthInch = pf.getWidth() / 72.0;
+ final double pfWHeightInch = pf.getHeight() / 72.0;
+ final double pfIWidthInch = pf.getImageableWidth() / 72.0;
+ final double pfIHeightInch = pf.getImageableHeight() / 72.0;
+ final double pfWWidthMM = pfWWidthInch * MM_PER_INCH;
+ final double pfWHeightMM = pfWHeightInch * MM_PER_INCH;
+ final double pfIWidthMM = pfIWidthInch * MM_PER_INCH;
+ final double pfIHeightMM = pfIHeightInch * MM_PER_INCH;
+
+ System.err.println("PF: Paper whole size "+
+ Math.round(paperWWidthMM)+" x "+Math.round(paperWHeightMM)+" mm, "+
+ Math.round(paperWWidthInch)+" x "+Math.round(paperWHeightInch)+" inch");
+
+ System.err.println("PF: Paper image size "+paper.getImageableX()+" / "+paper.getImageableY()+" "+
+ Math.round(paperIWidthMM)+" x "+Math.round(paperIHeightMM)+" mm, "+
+ Math.round(paperIWidthInch)+" x "+Math.round(paperIHeightInch)+" inch, "+
+ Math.round(paper.getImageableWidth())+"x"+Math.round(paper.getImageableHeight())+" 72dpi dots");
+
+ System.err.println("PF: Page whole size "+
+ Math.round(pfWWidthMM)+" x "+Math.round(pfWHeightMM)+" mm, "+
+ Math.round(pfWWidthInch)+" x "+Math.round(pfWHeightInch)+" inch");
+
+ System.err.println("PF: Page image size "+pf.getImageableX()+" / "+pf.getImageableY()+" "+
+ Math.round(pfIWidthMM)+" x "+Math.round(pfIHeightMM)+" mm, "+
+ Math.round(pfIWidthInch)+" x "+Math.round(pfIHeightInch)+" inch, "+
+ Math.round(pf.getImageableWidth())+"x"+Math.round(pf.getImageableHeight())+" 72dpi dots");
+
+ System.err.println("PF: Page orientation "+pf.getOrientation());
+
+ /**
+ * See: 'Scaling of Frame and GL content' in Class description!
+ * Note: Frame size contains the frame border (i.e. insets)!
+ */
+ final Insets frameInsets = cont.getInsets();
+ final int frameWidth = cont.getWidth();
+ final int frameHeight= cont.getHeight();
+ final double scaleGraphics = dpi / 72.0;
+ final int frameSWidth = (int) ( frameWidth * scaleGraphics );
+ final int frameSHeight = (int) ( frameHeight * scaleGraphics );
+ final double scaleComp72;
+ {
+ final double sx = pf.getImageableWidth() / frameWidth;
+ final double sy = pf.getImageableHeight() / frameHeight;
+ scaleComp72 = Math.min(sx, sy);
+ }
+ System.err.println("PRINT.onscrn thread "+Thread.currentThread().getName());
+ System.err.println("PRINT.onscrn DPI: scaleGraphics "+scaleGraphics+", scaleComp72 "+scaleComp72);
+ System.err.println("PRINT.onscrn DPI: frame: border "+frameInsets+", size "+frameWidth+"x"+frameHeight+
+ " -> scaled "+frameSWidth+ "x" + frameSHeight);
+
+ final Graphics2D g2d = (Graphics2D)g;
+ System.err.println("PRINT at.pre: "+g2d.getTransform());
+ g2d.translate(pf.getImageableX(), pf.getImageableY());
+ g2d.scale(scaleComp72, scaleComp72); // WARNING: Produces rounding artifacts due to diff scale-factor of AWT/GL comps !!!
+ // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ cont.printAll(g2d);
+ }
+ });
+
+ /* tell the caller that this page is part of the printed document */
+ return PAGE_EXISTS;
+ } finally {
+ lockPrinting.unlock();
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/PrintableBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/PrintableBase.java
new file mode 100644
index 000000000..39cc4fbd2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/PrintableBase.java
@@ -0,0 +1,88 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import java.awt.Container;
+import java.awt.print.Printable;
+import java.awt.print.PrinterJob;
+
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.opengl.util.TileRenderer;
+
+/**
+ * Base {@link Printable} implementation class.
+ *
+ * <h5>Virtual printer driver</h5>
+ * <p>
+ * Note, on OSX you might need to setup a dummy printer, i.e. <i>print to file</i>.<br>
+ * As root:
+ * <pre>
+ cupsctl FileDevice=Yes
+ killall -HUP cupsd
+ mkdir /data/lp
+ chown USER /data/lp
+ chmod ugo+rwx /data/lp
+ lpadmin -p lprint -E -v file:/data/lp/out.ps -P /Library/Printers/PPDs/Contents/Resources/HP\ LaserJet\ 4\ Plus.gz
+ * </pre>
+ */
+public abstract class PrintableBase implements Printable {
+
+ public static final double MM_PER_INCH = 25.4;
+
+ public final PrinterJob job;
+ public final Container cont;
+ public final int dpi;
+ public final int numSamples;
+ public final int tileWidth, tileHeight;
+ protected final RecursiveLock lockPrinting = LockFactory.createRecursiveLock();
+
+ /**
+ *
+ * @param job
+ * @param printContainer
+ * @param printDPI
+ * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples
+ * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ */
+ public PrintableBase(final PrinterJob job, final Container printContainer, final int printDPI, final int numSamples, final int tileWidth, final int tileHeight) {
+ this.job = job;
+ this.cont = printContainer;
+ this.dpi = printDPI;
+ this.numSamples = numSamples;
+ this.tileWidth = tileWidth;
+ this.tileHeight = tileHeight;
+ }
+
+ /** Wait for idle .. simply acquiring all locks and releasing them. */
+ public void waitUntilIdle() {
+ lockPrinting.lock();
+ lockPrinting.unlock();
+ }
+} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java
new file mode 100644
index 000000000..546420057
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java
@@ -0,0 +1,193 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLPixelBuffer;
+import com.jogamp.opengl.util.RandomTileRenderer;
+import com.jogamp.opengl.util.TileRendererBase;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLOffscreenAutoDrawable;
+import javax.media.opengl.GLRunnable;
+
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Demos offscreen {@link GLAutoDrawable} being used for
+ * {@link RandomTileRenderer} rendering to produce a PNG file.
+ * <p>
+ * {@link RandomTileRenderer} is being kicked off from the main thread.
+ * </p>
+ * <p>
+ * {@link RandomTileRenderer} buffer allocation is performed
+ * within the pre {@link GLEventListener}
+ * set via {@link TileRendererBase#setGLEventListener(GLEventListener, GLEventListener)}
+ * on the main thread.
+ * </p>
+ * <p>
+ * At tile rendering finish, the viewport and
+ * and the original {@link GLEventListener}'s PMV matrix as well.
+ * The latter is done by calling it's {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape} method.
+ * </p>
+*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestRandomTiledRendering2GL2NEWT extends UITestCase {
+ static long duration = 500; // ms
+
+ @Test
+ public void test01_aa0() throws IOException, InterruptedException, InvocationTargetException {
+ doTest(0);
+ }
+ @Test
+ public void test02_aa8() throws IOException, InterruptedException, InvocationTargetException {
+ doTest(8);
+ }
+
+ void doTest(final int msaaCount) throws IOException, InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ caps.setDoubleBuffered(true);
+ if( msaaCount > 0 ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(msaaCount);
+ }
+
+ final int maxTileSize = 64;
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, caps, null, maxTileSize, maxTileSize);
+
+ final Gears gears = new Gears();
+ glad.addGLEventListener( gears );
+
+ // Fix the image size for now
+ final int imageWidth = 256 * 6;
+ final int imageHeight = 256 * 4;
+
+ final String filename = this.getSnapshotFilename(0, "-tile", glad.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null);
+ final File file = new File(filename);
+
+ // Initialize the tile rendering library
+ final RandomTileRenderer renderer = new RandomTileRenderer();
+ renderer.attachAutoDrawable(glad);
+ renderer.setImageSize(imageWidth, imageHeight);
+
+ final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride;
+ final boolean[] flipVertically = { false };
+
+ final GLEventListener preTileGLEL = new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3);
+ final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0);
+ renderer.setImageBuffer(pixelBuffer);
+ if( drawable.isGLOriented() ) {
+ flipVertically[0] = false;
+ } else {
+ flipVertically[0] = true;
+ }
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {}
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ };
+ renderer.setGLEventListener(preTileGLEL, null);
+
+ final int w = maxTileSize, h = maxTileSize;
+ int dx = 0, dy = 0;
+ while( dx+w <= imageWidth && dy+h <= imageHeight ) {
+ renderer.display(dx, dy, w, h);
+ dx+=w+w/2;
+ if( dx + w > imageWidth ) {
+ dx = 0;
+ dy+=h+h/2;
+ }
+ }
+
+ renderer.detachAutoDrawable();
+
+ // Restore viewport and Gear's PMV matrix
+ // .. even though we close the demo, this is for documentation!
+ glad.invoke(true, new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ drawable.getGL().glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ gears.reshape(drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ return false;
+ }
+ });
+
+ glad.destroy();
+
+ final GLPixelBuffer imageBuffer = renderer.getImageBuffer();
+ imageBuffer.clear(); // full size available
+ System.err.println("XXX2: "+imageBuffer);
+ final TextureData textureData = new TextureData(
+ caps.getGLProfile(),
+ 0 /* internalFormat */,
+ imageWidth, imageHeight,
+ 0,
+ imageBuffer.pixelAttributes,
+ false, false,
+ flipVertically[0],
+ imageBuffer.buffer,
+ null /* Flusher */);
+ System.err.println("XXX3: "+textureData.getPixelFormat()+", "+textureData.getPixelAttributes());
+
+ TextureIO.write(textureData, file);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestRandomTiledRendering2GL2NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java
new file mode 100644
index 000000000..b128f8691
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java
@@ -0,0 +1,261 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import com.jogamp.newt.event.TraceKeyAdapter;
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTKeyAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLPixelBuffer;
+import com.jogamp.opengl.util.RandomTileRenderer;
+import com.jogamp.opengl.util.TileRendererBase;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.awt.GLCanvas;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Demos an onscreen AWT {@link GLCanvas} being used for
+ * {@link RandomTileRenderer} rendering to produce a PNG file.
+ * <p>
+ * {@link RandomTileRenderer} is being kicked off from the main thread.
+ * </p>
+ * <p>
+ * {@link RandomTileRenderer} setup and finishing is performed
+ * within the pre- and post {@link GLEventListener}
+ * set via {@link TileRendererBase#setGLEventListener(GLEventListener, GLEventListener)}
+ * on the animation thread.
+ * </p>
+ * <p>
+ * At tile rendering finish, the viewport and
+ * and the original {@link GLEventListener}'s PMV matrix as well.
+ * The latter is done by calling it's {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape} method.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestRandomTiledRendering3GL2AWT extends UITestCase {
+ static long duration = 3500; // ms
+ static int width = 512;
+ static int height = 512;
+
+ @Test
+ public void test01_aa0() throws IOException, InterruptedException, InvocationTargetException {
+ doTest(0);
+ }
+ @Test
+ public void test02_aa8() throws IOException, InterruptedException, InvocationTargetException {
+ doTest(8);
+ }
+
+ void doTest(final int msaaCount) throws IOException, InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(null);
+ if( msaaCount > 0 ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(msaaCount);
+ }
+
+ final Frame frame = new Frame("Gears AWT Test");
+ Assert.assertNotNull(frame);
+
+ final GLCanvas glad = new GLCanvas(caps);
+ Assert.assertNotNull(glad);
+ final Dimension glc_sz = new Dimension(width, height);
+ glad.setMinimumSize(glc_sz);
+ glad.setPreferredSize(glc_sz);
+ glad.setSize(glc_sz);
+ frame.add(glad);
+
+ final Gears gears = new Gears();
+ glad.addGLEventListener( gears );
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glad).addTo(glad);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glad).addTo(frame);
+
+ // Fix the image size for now
+ final int maxTileSize = 64;
+ final int imageWidth = 256 * 6;
+ final int imageHeight = 256 * 4;
+
+ // Initialize the tile rendering library
+ final RandomTileRenderer renderer = new RandomTileRenderer();
+ renderer.setImageSize(imageWidth, imageHeight);
+ final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride;
+ final boolean[] flipVertically = { false };
+ final boolean[] rendererActive = { true };
+
+ final GLEventListener preTileGLEL = new GLEventListener() {
+ final int w = maxTileSize, h = maxTileSize;
+ int dx = 0, dy = 0;
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3);
+ final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0);
+ renderer.setImageBuffer(pixelBuffer);
+ if( drawable.isGLOriented() ) {
+ flipVertically[0] = false;
+ } else {
+ flipVertically[0] = true;
+ }
+ System.err.println("XXX pre-init: "+renderer);
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ if( dx+w <= imageWidth && dy+h <= imageHeight ) {
+ renderer.setTileRect(dx, dy, w, h);
+ dx+=w+w/2;
+ if( dx + w > imageWidth ) {
+ dx = 0;
+ dy+=h+h/2;
+ }
+ } else if( rendererActive[0] ) {
+ rendererActive[0] = false;
+ }
+ System.err.println("XXX pre-display: "+renderer);
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ };
+ final GLEventListener postTileGLEL = new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {}
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ if( !rendererActive[0] ) {
+ final GLPixelBuffer imageBuffer = renderer.getImageBuffer();
+ imageBuffer.clear(); // full size available
+ System.err.println("XXX !active -> save");
+ System.err.println("XXX post-display: "+renderer);
+ final TextureData textureData = new TextureData(
+ caps.getGLProfile(),
+ 0 /* internalFormat */,
+ imageWidth, imageHeight,
+ 0,
+ imageBuffer.pixelAttributes,
+ false, false,
+ flipVertically[0],
+ imageBuffer.buffer,
+ null /* Flusher */);
+ try {
+ final String filename = getSnapshotFilename(0, "-tile", glad.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null);
+ final File file = new File(filename);
+ TextureIO.write(textureData, file);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ renderer.detachAutoDrawable();
+ System.err.println("XXX post-display detached: "+renderer);
+ drawable.getGL().glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ glad.getGLEventListener(0).reshape(drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ }
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ };
+ renderer.setGLEventListener(preTileGLEL, postTileGLEL);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ frame.setVisible(true);
+ }});
+
+ final Animator animator = new Animator(glad);
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.start();
+
+ boolean signalTileRenderer = true;
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() &&
+ ( rendererActive[0] || animator.getTotalFPSDuration()<duration ) )
+ {
+ if( signalTileRenderer && animator.getTotalFPSDuration() > 90 ) {
+ signalTileRenderer = false;
+ // tile rendering !
+ System.err.println("XXX START TILE RENDERING");
+ renderer.attachAutoDrawable(glad);
+ }
+ Thread.sleep(100);
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glad);
+ Assert.assertNotNull(animator);
+
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.remove(glad);
+ frame.dispose();
+ }});
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestRandomTiledRendering3GL2AWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java
new file mode 100644
index 000000000..87f1f3e7d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java
@@ -0,0 +1,279 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
+import java.awt.print.PageFormat;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.event.TraceKeyAdapter;
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTKeyAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTiledPrintingGearsAWT extends TiledPrintingAWTBase {
+
+ static boolean waitForKey = false;
+ /** only when run manually .. */
+ static boolean allow600dpi = false;
+ static GLProfile glp;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.get(GLProfile.GL2);
+ Assert.assertNotNull(glp);
+ width = 640;
+ height = 480;
+ } else {
+ setTestSupported(false);
+ }
+ // Runtime.getRuntime().traceInstructions(true);
+ // Runtime.getRuntime().traceMethodCalls(true);
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException, InvocationTargetException {
+ final Dimension glc_sz = new Dimension(width/2, height);
+ final GLCanvas glCanvas1 = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas1);
+ glCanvas1.setMinimumSize(glc_sz);
+ glCanvas1.setPreferredSize(glc_sz);
+ glCanvas1.setSize(glc_sz);
+ glCanvas1.addGLEventListener(new Gears());
+
+ final GLCanvas glCanvas2 = new GLCanvas(caps);
+ Assert.assertNotNull(glCanvas2);
+ glCanvas2.setMinimumSize(glc_sz);
+ glCanvas2.setPreferredSize(glc_sz);
+ glCanvas2.setSize(glc_sz);
+ glCanvas2.addGLEventListener(new RedSquareES2());
+
+ final Panel demoPanel = new Panel();
+ demoPanel.add(glCanvas1);
+ demoPanel.add(glCanvas2);
+
+ final Frame frame = new Frame("AWT Print");
+ Assert.assertNotNull(frame);
+
+ final ActionListener print72DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 72, 0, -1, -1);
+ } };
+ final ActionListener print300DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 300, -1, -1, -1);
+ } };
+ final ActionListener print600DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 600, -1, -1, -1);
+ } };
+ final Button print72DPIButton = new Button("72dpi");
+ print72DPIButton.addActionListener(print72DPIAction);
+ final Button print300DPIButton = new Button("300dpi");
+ print300DPIButton.addActionListener(print300DPIAction);
+ final Button print600DPIButton = new Button("600dpi");
+ print600DPIButton.addActionListener(print600DPIAction);
+
+ frame.setLayout(new BorderLayout());
+ final Panel printPanel = new Panel();
+ printPanel.add(print72DPIButton);
+ printPanel.add(print300DPIButton);
+ printPanel.add(print600DPIButton);
+ final Panel southPanel = new Panel();
+ southPanel.add(new Label("South"));
+ final Panel eastPanel = new Panel();
+ eastPanel.add(new Label("East"));
+ final Panel westPanel = new Panel();
+ westPanel.add(new Label("West"));
+ frame.add(printPanel, BorderLayout.NORTH);
+ frame.add(demoPanel, BorderLayout.CENTER);
+ frame.add(southPanel, BorderLayout.SOUTH);
+ frame.add(eastPanel, BorderLayout.EAST);
+ frame.add(westPanel, BorderLayout.WEST);
+ frame.setTitle("Tiles AWT Print Test");
+
+ final Animator animator = new Animator();
+ animator.add(glCanvas1);
+ animator.add(glCanvas2);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glCanvas1).addTo(glCanvas1);
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glCanvas2).addTo(glCanvas2);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas2).addTo(frame);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ frame.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas2, true));
+
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.start();
+
+ boolean printDone = false;
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && ( 0 == duration || animator.getTotalFPSDuration()<duration )) {
+ Thread.sleep(200);
+ if( !printDone ) {
+ printDone = true;
+ {
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 0, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 8, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, 2048, 2048, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, true /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, true/* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ if( allow600dpi ) {
+ // No AA needed for 300 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 600, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ }
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glCanvas1);
+ Assert.assertNotNull(glCanvas2);
+ Assert.assertNotNull(animator);
+
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final Frame _frame = frame;
+ _frame.remove(demoPanel);
+ _frame.dispose();
+ }});
+ }
+
+ @Test
+ public void test01_aa0() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test02_aa8() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(8);
+ runTestGL(caps);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-600dpi")) {
+ allow600dpi = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ if(waitForKey) {
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ try {
+ System.err.println(stdin.readLine());
+ } catch (final IOException e) { }
+ }
+ org.junit.runner.JUnitCore.main(TestTiledPrintingGearsAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java
new file mode 100644
index 000000000..274b1eef3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java
@@ -0,0 +1,286 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
+import java.awt.print.PageFormat;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.TraceKeyAdapter;
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTKeyAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTiledPrintingGearsNewtAWT extends TiledPrintingAWTBase {
+
+ static boolean waitForKey = false;
+ /** only when run manually .. */
+ static boolean allow600dpi = false;
+ static GLProfile glp;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.get(GLProfile.GL2);
+ Assert.assertNotNull(glp);
+ width = 640;
+ height = 480;
+ } else {
+ setTestSupported(false);
+ }
+ // Runtime.getRuntime().traceInstructions(true);
+ // Runtime.getRuntime().traceMethodCalls(true);
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL(final GLCapabilities caps) throws InterruptedException, InvocationTargetException {
+ final Dimension glc_sz = new Dimension(width/2, height);
+ final GLWindow glad1 = GLWindow.create(caps);
+ Assert.assertNotNull(glad1);
+ final NewtCanvasAWT canvas1 = new NewtCanvasAWT(glad1);
+ Assert.assertNotNull(canvas1);
+ canvas1.setMinimumSize(glc_sz);
+ canvas1.setPreferredSize(glc_sz);
+ canvas1.setSize(glc_sz);
+ glad1.addGLEventListener(new Gears());
+
+ final GLWindow glad2 = GLWindow.create(caps);
+ Assert.assertNotNull(glad2);
+ final NewtCanvasAWT canvas2 = new NewtCanvasAWT(glad2);
+ Assert.assertNotNull(canvas2);
+ canvas2.setMinimumSize(glc_sz);
+ canvas2.setPreferredSize(glc_sz);
+ canvas2.setSize(glc_sz);
+ glad2.addGLEventListener(new RedSquareES2());
+
+ final Panel demoPanel = new Panel();
+ demoPanel.add(canvas1);
+ demoPanel.add(canvas2);
+
+ final Frame frame = new Frame("Newt/AWT Print");
+ Assert.assertNotNull(frame);
+
+ final ActionListener print72DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 72, 0, -1, -1);
+ } };
+ final ActionListener print300DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 300, -1, -1, -1);
+ } };
+ final ActionListener print600DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 600, -1, -1, -1);
+ } };
+ final Button print72DPIButton = new Button("72dpi");
+ print72DPIButton.addActionListener(print72DPIAction);
+ final Button print300DPIButton = new Button("300dpi");
+ print300DPIButton.addActionListener(print300DPIAction);
+ final Button print600DPIButton = new Button("600dpi");
+ print600DPIButton.addActionListener(print600DPIAction);
+
+ frame.setLayout(new BorderLayout());
+ final Panel printPanel = new Panel();
+ printPanel.add(print72DPIButton);
+ printPanel.add(print300DPIButton);
+ printPanel.add(print600DPIButton);
+ final Panel southPanel = new Panel();
+ southPanel.add(new Label("South"));
+ final Panel eastPanel = new Panel();
+ eastPanel.add(new Label("East"));
+ final Panel westPanel = new Panel();
+ westPanel.add(new Label("West"));
+ frame.add(printPanel, BorderLayout.NORTH);
+ frame.add(demoPanel, BorderLayout.CENTER);
+ frame.add(southPanel, BorderLayout.SOUTH);
+ frame.add(eastPanel, BorderLayout.EAST);
+ frame.add(westPanel, BorderLayout.WEST);
+ frame.setTitle("Tiles Newt/AWT Print Test");
+
+ final Animator animator = new Animator();
+ animator.add(glad1);
+ animator.add(glad2);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), canvas1.getNEWTChild()).addTo(canvas1);
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), canvas2.getNEWTChild()).addTo(canvas2);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), canvas2.getNEWTChild()).addTo(frame);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ frame.setVisible(true);
+ }});
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas1, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas2, true));
+
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.start();
+
+ boolean printDone = false;
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && ( 0 == duration || animator.getTotalFPSDuration()<duration )) {
+ Thread.sleep(200);
+ if( !printDone ) {
+ printDone = true;
+ {
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 0, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 8, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, 2048, 2048, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, true /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, true /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ if( allow600dpi ) {
+ // No AA needed for 300 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 600, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ }
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(canvas1);
+ Assert.assertNotNull(canvas2);
+ Assert.assertNotNull(animator);
+
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final Frame _frame = frame;
+ _frame.remove(demoPanel);
+ _frame.dispose();
+ }});
+ glad1.destroy();
+ glad2.destroy();
+ }
+
+ @Test
+ public void test01_aa0() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test02_aa8() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(8);
+ runTestGL(caps);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-600dpi")) {
+ allow600dpi = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ if(waitForKey) {
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ try {
+ System.err.println(stdin.readLine());
+ } catch (final IOException e) { }
+ }
+ org.junit.runner.JUnitCore.main(TestTiledPrintingGearsNewtAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java
new file mode 100644
index 000000000..7c8d65c19
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java
@@ -0,0 +1,411 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Label;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
+import java.awt.print.PageFormat;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JLayeredPane;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.newt.event.TraceKeyAdapter;
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTKeyAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTiledPrintingGearsSwingAWT extends TiledPrintingAWTBase {
+
+ static boolean waitForKey = false;
+ /** only when run manually .. */
+ static boolean allow600dpi = false;
+ static GLProfile glp;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.get(GLProfile.GL2);
+ Assert.assertNotNull(glp);
+ width = 640;
+ height = 480;
+ } else {
+ setTestSupported(false);
+ }
+ // Runtime.getRuntime().traceInstructions(true);
+ // Runtime.getRuntime().traceMethodCalls(true);
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final boolean layered, final boolean skipGLOrientationVerticalFlip) throws InterruptedException, InvocationTargetException {
+ final int layerStepX = width/6, layerStepY = height/6;
+ final Dimension glc_sz = new Dimension(layered ? width - 2*layerStepX : width/2, layered ? height - 2*layerStepY : height);
+ final GLJPanel glJPanel1 = new GLJPanel(caps);
+ Assert.assertNotNull(glJPanel1);
+ glJPanel1.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip);
+ glJPanel1.setMinimumSize(glc_sz);
+ glJPanel1.setPreferredSize(glc_sz);
+ if( layered ) {
+ glJPanel1.setBounds(layerStepX/2, layerStepY/2, glc_sz.width, glc_sz.height);
+ } else {
+ glJPanel1.setBounds(0, 0, glc_sz.width, glc_sz.height);
+ }
+ {
+ final Gears demo = new Gears();
+ demo.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glJPanel1.addGLEventListener(demo);
+ }
+
+ final GLJPanel glJPanel2 = new GLJPanel(caps);
+ Assert.assertNotNull(glJPanel2);
+ glJPanel2.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip);
+ glJPanel2.setMinimumSize(glc_sz);
+ glJPanel2.setPreferredSize(glc_sz);
+ if( layered ) {
+ glJPanel2.setBounds(3*layerStepY, 2*layerStepY, glc_sz.width, glc_sz.height);
+ } else {
+ glJPanel2.setBounds(0, 0, glc_sz.width, glc_sz.height);
+ }
+ {
+ final RedSquareES1 demo = new RedSquareES1();
+ demo.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glJPanel2.addGLEventListener(demo);
+ }
+
+ final JComponent demoPanel;
+ if( layered ) {
+ glJPanel1.setOpaque(true);
+ glJPanel2.setOpaque(false);
+ final Dimension lsz = new Dimension(width, height);
+ demoPanel = new JLayeredPane();
+ demoPanel.setMinimumSize(lsz);
+ demoPanel.setPreferredSize(lsz);
+ demoPanel.setBounds(0, 0, lsz.width, lsz.height);
+ demoPanel.setBorder(BorderFactory.createTitledBorder("Layered Pane"));
+ demoPanel.add(glJPanel1, JLayeredPane.DEFAULT_LAYER);
+ demoPanel.add(glJPanel2, Integer.valueOf(1));
+ final JButton tb = new JButton("On Top");
+ tb.setBounds(4*layerStepY, 3*layerStepY, 100, 50);
+ demoPanel.add(tb, Integer.valueOf(2));
+ } else {
+ demoPanel = new JPanel();
+ demoPanel.add(glJPanel1);
+ demoPanel.add(glJPanel2);
+ }
+
+ final JFrame frame = new JFrame("Swing Print");
+ Assert.assertNotNull(frame);
+
+ final ActionListener print72DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 72, 0, -1, -1);
+ } };
+ final ActionListener print300DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 300, -1, -1, -1);
+ } };
+ final ActionListener print600DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 600, -1, -1, -1);
+ } };
+ final Button print72DPIButton = new Button("72dpi");
+ print72DPIButton.addActionListener(print72DPIAction);
+ final Button print300DPIButton = new Button("300dpi");
+ print300DPIButton.addActionListener(print300DPIAction);
+ final Button print600DPIButton = new Button("600dpi");
+ print600DPIButton.addActionListener(print600DPIAction);
+
+ final JPanel printPanel = new JPanel();
+ printPanel.add(print72DPIButton);
+ printPanel.add(print300DPIButton);
+ printPanel.add(print600DPIButton);
+ final JPanel southPanel = new JPanel();
+ southPanel.add(new Label("South"));
+ final JPanel eastPanel = new JPanel();
+ eastPanel.add(new Label("East"));
+ final JPanel westPanel = new JPanel();
+ westPanel.add(new Label("West"));
+
+ final Animator animator = new Animator();
+ animator.add(glJPanel1);
+ animator.add(glJPanel2);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glJPanel1).addTo(glJPanel1);
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glJPanel2).addTo(glJPanel2);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glJPanel2).addTo(frame);
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final Container fcont = frame.getContentPane();
+ fcont.setLayout(new BorderLayout());
+ fcont.add(printPanel, BorderLayout.NORTH);
+ fcont.add(demoPanel, BorderLayout.CENTER);
+ fcont.add(southPanel, BorderLayout.SOUTH);
+ fcont.add(eastPanel, BorderLayout.EAST);
+ fcont.add(westPanel, BorderLayout.WEST);
+ fcont.validate();
+ frame.pack();
+ frame.setVisible(true);
+ } } ) ;
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel2, true));
+
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.start();
+ Assert.assertEquals(true, animator.isAnimating());
+
+ boolean printDone = false;
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && ( 0 == duration || animator.getTotalFPSDuration()<duration )) {
+ Thread.sleep(200);
+ if( !printDone ) {
+ printDone = true;
+ {
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 0, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 8, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, 2048, 2048, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, true /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_RGB /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_BGR /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, true /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ if( allow600dpi ) {
+ // No AA needed for 300 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 600, -1, -1, -1, false /* resizeWithinPrint */);
+ waitUntilPrintJobsIdle(p);
+ }
+ }
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glJPanel1);
+ Assert.assertNotNull(glJPanel2);
+ Assert.assertNotNull(animator);
+
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final Frame _frame = frame;
+ _frame.remove(demoPanel);
+ _frame.dispose();
+ }});
+ }
+
+ @Test
+ public void test01_flip1_aa0() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, false, false);
+ }
+
+ @Test
+ public void test01_flip1_aa0_layered() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(8);
+ runTestGL(caps, true, false);
+ }
+
+ @Test
+ public void test01_flip1_aa0_bitmap() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS == Platform.getOSType() ) {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ runTestGL(caps, false, false);
+ } // issues w/ AMD catalyst driver and pixmap surface ..
+ }
+
+ @Test
+ public void test01_flip1_aa0_bitmap_layered() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS == Platform.getOSType() ) {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ caps.setAlphaBits(8);
+ runTestGL(caps, true, false);
+ } // issues w/ AMD catalyst driver and pixmap surface ..
+ }
+
+ @Test
+ public void test02_flip1_aa8() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(8);
+ runTestGL(caps, false, false);
+ }
+
+ @Test
+ public void test11_flip0_aa0() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, false, true);
+ }
+
+ @Test
+ public void test11_flip0_aa0_layered() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(8);
+ runTestGL(caps, true, true);
+ }
+
+ @Test
+ public void test11_flip0_aa0_bitmap() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS == Platform.getOSType() ) {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ runTestGL(caps, false, true);
+ } // issues w/ AMD catalyst driver and pixmap surface ..
+ }
+
+ @Test
+ public void test11_flip0_aa0_bitmap_layered() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS == Platform.getOSType() ) {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ caps.setAlphaBits(8);
+ runTestGL(caps, true, true);
+ } // issues w/ AMD catalyst driver and pixmap surface ..
+ }
+
+ @Test
+ public void test12_flip0_aa8() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(8);
+ runTestGL(caps, false, true);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-width")) {
+ i++;
+ width = MiscUtils.atoi(args[i], width);
+ } else if(args[i].equals("-height")) {
+ i++;
+ height = MiscUtils.atoi(args[i], height);
+ } else if(args[i].equals("-600dpi")) {
+ allow600dpi = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ if(waitForKey) {
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ try {
+ System.err.println(stdin.readLine());
+ } catch (final IOException e) { }
+ }
+ org.junit.runner.JUnitCore.main(TestTiledPrintingGearsSwingAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java
new file mode 100644
index 000000000..060b85a34
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java
@@ -0,0 +1,408 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Label;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.print.PageFormat;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JLayeredPane;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.newt.event.TraceKeyAdapter;
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.event.awt.AWTKeyAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTiledPrintingGearsSwingAWT2 extends TiledPrintingAWTBase {
+
+ static boolean waitForKey = false;
+ static GLProfile glp;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.get(GLProfile.GL2);
+ Assert.assertNotNull(glp);
+ width = 560; // 640;
+ height = 420; // 480;
+ } else {
+ setTestSupported(false);
+ }
+ // Runtime.getRuntime().traceInstructions(true);
+ // Runtime.getRuntime().traceMethodCalls(true);
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final boolean addLayout, final boolean layered, final boolean skipGLOrientationVerticalFlip, final boolean useAnim) throws InterruptedException, InvocationTargetException {
+ final Dimension glc_sz = new Dimension(width, height);
+ final GLJPanel glJPanel1 = new GLJPanel(caps);
+ Assert.assertNotNull(glJPanel1);
+ glJPanel1.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip);
+ glJPanel1.setMinimumSize(glc_sz);
+ glJPanel1.setPreferredSize(glc_sz);
+ glJPanel1.setBounds(0, 0, glc_sz.width, glc_sz.height);
+ {
+ final Gears demo = new Gears();
+ demo.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glJPanel1.addGLEventListener(demo);
+ }
+
+ final JComponent tPanel, demoPanel;
+ if( layered ) {
+ glJPanel1.setOpaque(true);
+ final JButton tb = new JButton("On Top");
+ tb.setBounds(width/2, height/2, 200, 50);
+ if( addLayout ) {
+ tPanel = null;
+ final Dimension lsz = new Dimension(width, height);
+ demoPanel = new JLayeredPane();
+ demoPanel.setMinimumSize(lsz);
+ demoPanel.setPreferredSize(lsz);
+ demoPanel.setBounds(0, 0, lsz.width, lsz.height);
+ demoPanel.setBorder(BorderFactory.createTitledBorder("Layered Pane"));
+ demoPanel.add(glJPanel1, JLayeredPane.DEFAULT_LAYER);
+ demoPanel.add(tb, Integer.valueOf(2));
+ } else {
+ tPanel = new TransparentPanel();
+ tPanel.setBounds(0, 0, width, height);
+ tPanel.setLayout(null);
+ tPanel.add(tb);
+ demoPanel = glJPanel1;
+ }
+ } else {
+ tPanel = null;
+ if( addLayout ) {
+ demoPanel = new JPanel();
+ demoPanel.add(glJPanel1);
+ } else {
+ demoPanel = glJPanel1;
+ }
+ }
+
+ final JFrame frame = new JFrame("Swing Print");
+ Assert.assertNotNull(frame);
+
+ final ActionListener print72DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 72, 0, -1, -1);
+ } };
+ final ActionListener print150DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 150, -1, -1, -1);
+ } };
+ final ActionListener print300DPIAction = new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ doPrintManual(frame, 300, -1, -1, -1);
+ } };
+ final Button print72DPIButton = new Button("72dpi");
+ print72DPIButton.addActionListener(print72DPIAction);
+ final Button print150DPIButton = new Button("150dpi");
+ print150DPIButton.addActionListener(print150DPIAction);
+ final Button print300DPIButton = new Button("300dpi");
+ print300DPIButton.addActionListener(print300DPIAction);
+
+ final JPanel printPanel = new JPanel();
+ printPanel.add(print72DPIButton);
+ printPanel.add(print150DPIButton);
+ printPanel.add(print300DPIButton);
+ final JPanel southPanel = new JPanel();
+ southPanel.add(new Label("South"));
+ final JPanel eastPanel = new JPanel();
+ eastPanel.add(new Label("East"));
+ final JPanel westPanel = new JPanel();
+ westPanel.add(new Label("West"));
+
+ final Animator animator = useAnim ? new Animator() : null;
+ if( null != animator ) {
+ animator.add(glJPanel1);
+ }
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glJPanel1).addTo(glJPanel1);
+ new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glJPanel1).addTo(frame);
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final Container fcont = frame.getContentPane();
+ if( addLayout ) {
+ fcont.setLayout(new BorderLayout());
+ fcont.add(printPanel, BorderLayout.NORTH);
+ fcont.add(demoPanel, BorderLayout.CENTER);
+ fcont.add(southPanel, BorderLayout.SOUTH);
+ fcont.add(eastPanel, BorderLayout.EAST);
+ fcont.add(westPanel, BorderLayout.WEST);
+ fcont.validate();
+ frame.pack();
+ } else {
+ frame.setSize(glc_sz);
+ fcont.setLayout(null);
+ if( null != tPanel ) {
+ fcont.add(tPanel);
+ }
+ fcont.add(demoPanel);
+ }
+ frame.setVisible(true);
+ } } ) ;
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true));
+
+ if( null != animator ) {
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.start();
+ Assert.assertEquals(true, animator.isAnimating());
+ }
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ boolean printDone = false;
+ while( !quitAdapter.shouldQuit() && ( 0 == duration || ( t1 - t0 ) < duration ) ) {
+ Thread.sleep(200);
+ if( !printDone ) {
+ printDone = true;
+ {
+ // No AA needed for 150 dpi and greater :)
+ final PrintableBase p = doPrintAuto(frame, PageFormat.PORTRAIT, null, -1 /* offscreen-type */, 150, -1, -1, -1, false);
+ waitUntilPrintJobsIdle(p);
+ }
+ }
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glJPanel1);
+
+ if( null != animator ) {
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final Frame _frame = frame;
+ _frame.remove(demoPanel);
+ _frame.dispose();
+ }});
+ }
+
+ @Test
+ public void test001_flip1_norm_layout0_layered0() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, false /* addLayout */, false /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test002_flip1_norm_layout1_layered0() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, true /* addLayout */, false /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test003_flip1_norm_layout0_layered1() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, false /* addLayout */, true /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test004_flip1_norm_layout1_layered1() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, true /* addLayout */, true /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test011_flip1_bitm_layout0_layered0() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS != Platform.getOSType() ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ runTestGL(caps, false /* addLayout */, false /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test012_flip1_bitm_layout1_layered0() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS != Platform.getOSType() ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ runTestGL(caps, true /* addLayout */, false /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test013_flip1_bitm_layout0_layered1() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS != Platform.getOSType() ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ runTestGL(caps, false /* addLayout */, true /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test014_flip1_bitm_layout1_layered1() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS != Platform.getOSType() ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ runTestGL(caps, true /* addLayout */, true /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test101_flip1_norm_layout0_layered0() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, false /* addLayout */, false /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test102_flip1_norm_layout1_layered0() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, true /* addLayout */, false /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test103_flip1_norm_layout0_layered1() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, false /* addLayout */, true /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test104_flip1_norm_layout1_layered1() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, true /* addLayout */, true /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test111_flip1_bitm_layout0_layered0() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS != Platform.getOSType() ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ runTestGL(caps, false /* addLayout */, false /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test112_flip1_bitm_layout1_layered0() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS != Platform.getOSType() ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ runTestGL(caps, true /* addLayout */, false /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test113_flip1_bitm_layout0_layered1() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS != Platform.getOSType() ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ runTestGL(caps, false /* addLayout */, true /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ @Test
+ public void test114_flip1_bitm_layout1_layered1() throws InterruptedException, InvocationTargetException {
+ if( Platform.OSType.WINDOWS != Platform.getOSType() ) {
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBitmap(true);
+ runTestGL(caps, true /* addLayout */, true /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-width")) {
+ i++;
+ width = MiscUtils.atoi(args[i], width);
+ } else if(args[i].equals("-height")) {
+ i++;
+ height = MiscUtils.atoi(args[i], height);
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ if(waitForKey) {
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ try {
+ System.err.println(stdin.readLine());
+ } catch (final IOException e) { }
+ }
+ org.junit.runner.JUnitCore.main(TestTiledPrintingGearsSwingAWT2.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java
new file mode 100644
index 000000000..85edcda6c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java
@@ -0,0 +1,320 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+import java.awt.Label;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.imageio.ImageIO;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JLayeredPane;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
+import com.jogamp.nativewindow.awt.DirectDataBufferInt;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTiledPrintingNIOImageSwingAWT extends UITestCase {
+
+ static boolean waitForKey = false;
+ /** only when run manually .. */
+ static boolean allow600dpi = false;
+ static GLProfile glp;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ if(GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.get(GLProfile.GL2);
+ Assert.assertNotNull(glp);
+ width = 640;
+ height = 480;
+ } else {
+ setTestSupported(false);
+ }
+ // Runtime.getRuntime().traceInstructions(true);
+ // Runtime.getRuntime().traceMethodCalls(true);
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void printOffscreenToFile(final BufferedImage image, final Frame frame, final GLCapabilities caps, final int num, final String detail) {
+ final Insets frameInsets = frame.getInsets();
+ final int frameWidth = frame.getWidth();
+ final int frameHeight= frame.getHeight();
+ final int imageWidth = image.getWidth();
+ final int imageHeight= image.getHeight();
+ final double scaleComp72;
+ // Note: Frame size contains the frame border (i.e. insets)!
+ {
+ final double sx = (double)imageWidth / frameWidth;
+ final double sy = (double)imageHeight / frameHeight;
+ scaleComp72 = Math.min(sx, sy);
+ }
+ System.err.println("PRINT DPI: scaleComp72 "+scaleComp72+", image-size "+imageWidth+"x"+imageHeight+", frame[border "+frameInsets+", size "+frameWidth+"x"+frameHeight+"]");
+
+ System.err.println("XXX: image "+image);
+ System.err.println("XXX: cm "+image.getColorModel());
+ System.err.println("XXX: raster "+image.getRaster());
+ System.err.println("XXX: dataBuffer "+image.getRaster().getDataBuffer());
+
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ final Graphics2D g2d = (Graphics2D) image.getGraphics();
+ g2d.setClip(0, 0, image.getWidth(), image.getHeight());
+ g2d.scale(scaleComp72, scaleComp72);
+ // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+
+ // frame.paintAll(g2d);
+ final AWTPrintLifecycle.Context ctx = AWTPrintLifecycle.Context.setupPrint(frame, 1.0/scaleComp72, 1.0/scaleComp72, 0, -1, -1);
+ try {
+ frame.printAll(g2d);
+ } finally {
+ ctx.releasePrint();
+ }
+ // to file
+ final String fname = getSnapshotFilename(num, detail, caps, image.getWidth(), image.getHeight(), false, TextureIO.PNG, null);
+ System.err.println("XXX file "+fname);
+ final File fout = new File(fname);
+ try {
+ ImageIO.write(image, "png", fout);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ } });
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final boolean layered) throws InterruptedException, InvocationTargetException {
+ final int layerStepX = width/6, layerStepY = height/6;
+ final Dimension glc_sz = new Dimension(layered ? width - 2*layerStepX : width/2, layered ? height - 2*layerStepY : height);
+ final GLJPanel glJPanel1 = new GLJPanel(caps);
+ Assert.assertNotNull(glJPanel1);
+ glJPanel1.setMinimumSize(glc_sz);
+ glJPanel1.setPreferredSize(glc_sz);
+ if( layered ) {
+ glJPanel1.setBounds(layerStepX/2, layerStepY/2, glc_sz.width, glc_sz.height);
+ } else {
+ glJPanel1.setBounds(0, 0, glc_sz.width, glc_sz.height);
+ }
+ glJPanel1.addGLEventListener(new Gears());
+
+ final GLJPanel glJPanel2 = new GLJPanel(caps);
+ Assert.assertNotNull(glJPanel2);
+ glJPanel2.setMinimumSize(glc_sz);
+ glJPanel2.setPreferredSize(glc_sz);
+ if( layered ) {
+ glJPanel2.setBounds(3*layerStepY, 2*layerStepY, glc_sz.width, glc_sz.height);
+ } else {
+ glJPanel2.setBounds(0, 0, glc_sz.width, glc_sz.height);
+ }
+ glJPanel2.addGLEventListener(new RedSquareES2());
+ // glJPanel2.addGLEventListener(new Gears());
+
+ final JComponent demoPanel;
+ if( layered ) {
+ glJPanel1.setOpaque(true);
+ glJPanel2.setOpaque(false);
+ final Dimension lsz = new Dimension(width, height);
+ demoPanel = new JLayeredPane();
+ demoPanel.setMinimumSize(lsz);
+ demoPanel.setPreferredSize(lsz);
+ demoPanel.setBounds(0, 0, lsz.width, lsz.height);
+ demoPanel.setBorder(BorderFactory.createTitledBorder("Layered Pane"));
+ demoPanel.add(glJPanel1, JLayeredPane.DEFAULT_LAYER);
+ demoPanel.add(glJPanel2, Integer.valueOf(1));
+ final JButton tb = new JButton("On Top");
+ tb.setBounds(4*layerStepY, 3*layerStepY, 100, 50);
+ demoPanel.add(tb, Integer.valueOf(2));
+ } else {
+ demoPanel = new JPanel();
+ demoPanel.add(glJPanel1);
+ demoPanel.add(glJPanel2);
+ }
+
+ final JFrame frame = new JFrame("Swing Print");
+ Assert.assertNotNull(frame);
+
+ final Button print72DPIButton = new Button("72dpi"); // dummy
+ final Button print300DPIButton = new Button("300dpi"); // dummy
+ final Button print600DPIButton = new Button("600dpi"); // dummy
+
+ final JPanel printPanel = new JPanel();
+ printPanel.add(print72DPIButton);
+ printPanel.add(print300DPIButton);
+ printPanel.add(print600DPIButton);
+ final JPanel southPanel = new JPanel();
+ southPanel.add(new Label("South"));
+ final JPanel eastPanel = new JPanel();
+ eastPanel.add(new Label("East"));
+ final JPanel westPanel = new JPanel();
+ westPanel.add(new Label("West"));
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final Container fcont = frame.getContentPane();
+ fcont.setLayout(new BorderLayout());
+ fcont.add(printPanel, BorderLayout.NORTH);
+ fcont.add(demoPanel, BorderLayout.CENTER);
+ fcont.add(southPanel, BorderLayout.SOUTH);
+ fcont.add(eastPanel, BorderLayout.EAST);
+ fcont.add(westPanel, BorderLayout.WEST);
+ fcont.validate();
+ frame.pack();
+ frame.setVisible(true);
+ } } ) ;
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel2, true));
+
+ // paint offscreen: array 72dpi ARGB
+ {
+ final BufferedImage image = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB);
+ printOffscreenToFile(image, frame, caps, 0, "array_072dpi_argb");
+ }
+ // paint offscreen: NIO 72dpi ARGB
+ {
+ final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB, null /* location */, null /* properties */);
+ printOffscreenToFile(image, frame, caps, 1, "newio_072dpi_argb");
+ }
+ // paint offscreen: NIO 150dpi ARGB
+ {
+ final int scale = (int) ( 150.0 / 72.0 + 0.5 );
+ final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_ARGB, null /* location */, null /* properties */);
+ printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_argb");
+ }
+ // paint offscreen: NIO 150dpi ARGB_PRE
+ {
+ final int scale = (int) ( 150.0 / 72.0 + 0.5 );
+ final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_ARGB_PRE, null /* location */, null /* properties */);
+ printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_argbp");
+ }
+ // paint offscreen: NIO 150dpi RGB
+ {
+ final int scale = (int) ( 150.0 / 72.0 + 0.5 );
+ final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_RGB, null /* location */, null /* properties */);
+ printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_rgb");
+ }
+ // paint offscreen: NIO 150dpi BGR
+ {
+ final int scale = (int) ( 150.0 / 72.0 + 0.5 );
+ final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_BGR, null /* location */, null /* properties */);
+ printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_bgr");
+ }
+
+ Assert.assertNotNull(frame);
+ Assert.assertNotNull(glJPanel1);
+ Assert.assertNotNull(glJPanel2);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(false);
+ }});
+ Assert.assertEquals(false, frame.isVisible());
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ final Frame _frame = frame;
+ _frame.remove(demoPanel);
+ _frame.dispose();
+ }});
+ }
+
+ @Test
+ public void test01_Offscreen_aa0() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, false);
+ }
+
+ @Test
+ public void test01_Offscreen_aa0_layered() throws InterruptedException, InvocationTargetException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ runTestGL(caps, true);
+ }
+
+ static long duration = 500; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(args[i].equals("-600dpi")) {
+ allow600dpi = true;
+ } else if(args[i].equals("-wait")) {
+ waitForKey = true;
+ }
+ }
+ if(waitForKey) {
+ final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ try {
+ System.err.println(stdin.readLine());
+ } catch (final IOException e) { }
+ }
+ org.junit.runner.JUnitCore.main(TestTiledPrintingNIOImageSwingAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java
new file mode 100644
index 000000000..9dee67e5e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java
@@ -0,0 +1,243 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLPixelBuffer;
+import com.jogamp.opengl.util.TileRenderer;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.TileRendererBase;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Demos offscreen {@link GLDrawable} being used for
+ * {@link TileRenderer} rendering to produce a PNG file.
+ * <p>
+ * All {@link TileRenderer} operations are
+ * being performed from the main thread sequentially
+ * without {@link GLAutoDrawable} or {@link GLEventListener}.
+ * </p>
+*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTiledRendering1GL2NEWT extends UITestCase {
+ static long duration = 500; // ms
+
+ static class DrawableContext {
+ DrawableContext(final GLDrawable d, final GLContext glc) {
+ this.d = d;
+ this.glc = glc;
+ }
+ GLDrawable d;
+ GLContext glc;
+ }
+
+ private static DrawableContext createDrawableAndCurrentCtx(final GLCapabilities glCaps, final int width, final int height) {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(glCaps.getGLProfile());
+ final GLDrawable d = factory.createOffscreenDrawable(null, glCaps, null, width, height);
+ d.setRealized(true);
+ GLContext glc = null;
+ glc = d.createContext(null);
+ Assert.assertTrue("Context could not be made current", GLContext.CONTEXT_NOT_CURRENT < glc.makeCurrent());
+ return new DrawableContext(d, glc);
+ }
+
+ private static void destroyDrawableContext(final DrawableContext dc) {
+ if(null != dc.glc) {
+ dc.glc.destroy();
+ dc.glc = null;
+ }
+ if(null != dc.d) {
+ dc.d.setRealized(false);
+ dc.d = null;
+ }
+ }
+
+ @Test
+ public void test01() throws IOException {
+ final GLProfile glp = GLProfile.getMaxFixedFunc(true);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setOnscreen(false);
+
+ final int maxTileSize = 256;
+ final DrawableContext dc = createDrawableAndCurrentCtx(caps, maxTileSize, maxTileSize);
+ final GL2 gl = dc.glc.getGL().getGL2();
+
+ // Fix the image size for now
+ final int imageWidth = dc.d.getSurfaceWidth() * 6;
+ final int imageHeight = dc.d.getSurfaceHeight() * 4;
+
+ final String filename = this.getSnapshotFilename(0, "-tile", dc.d.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null);
+ final File file = new File(filename);
+
+ // Initialize the tile rendering library
+ final TileRenderer renderer = new com.jogamp.opengl.util.TileRenderer();
+ renderer.setTileSize(dc.d.getSurfaceWidth(), dc.d.getSurfaceHeight(), 0);
+ renderer.setImageSize(imageWidth, imageHeight);
+
+ final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride;
+ final boolean[] flipVertically = { false };
+
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3);
+ final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0);
+ renderer.setImageBuffer(pixelBuffer);
+ flipVertically[0] = false;
+
+ final Gears gears = new Gears();
+ gears.setVerbose(false);
+ gears.init(gl);
+
+ gears.addTileRendererNotify(renderer);
+ while( !renderer.eot() ) {
+ renderer.beginTile(gl);
+ gears.reshape(gl,
+ renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_Y_POS),
+ renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT),
+ renderer.getParam(TileRendererBase.TR_IMAGE_WIDTH), renderer.getParam(TileRendererBase.TR_IMAGE_HEIGHT));
+ gears.display(gl);
+ renderer.endTile(gl);
+ }
+ gears.removeTileRendererNotify(renderer);
+
+ destroyDrawableContext(dc);
+
+ final GLPixelBuffer imageBuffer = renderer.getImageBuffer();
+ final TextureData textureData = new TextureData(
+ caps.getGLProfile(),
+ 0 /* internalFormat */,
+ imageWidth, imageHeight,
+ 0,
+ imageBuffer.pixelAttributes,
+ false, false,
+ flipVertically[0],
+ imageBuffer.buffer,
+ null /* Flusher */);
+
+ TextureIO.write(textureData, file);
+ }
+
+ @Test
+ public void test02_EOT_01() throws IOException {
+ final GLProfile glp = GLProfile.getMaxFixedFunc(true);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setOnscreen(false);
+
+ final int maxTileSize = 256;
+ final DrawableContext dc = createDrawableAndCurrentCtx(caps, maxTileSize, maxTileSize);
+ final GL2 gl = dc.glc.getGL().getGL2();
+
+ // Fix the image size for now
+ final int imageWidth = dc.d.getSurfaceWidth() * 6;
+ final int imageHeight = dc.d.getSurfaceHeight() * 4;
+
+ // Initialize the tile rendering library
+ final TileRenderer renderer = new com.jogamp.opengl.util.TileRenderer();
+ renderer.setTileSize(dc.d.getSurfaceWidth(), dc.d.getSurfaceHeight(), 0);
+
+ IllegalStateException ise = null;
+ try {
+ renderer.beginTile(gl); // Image size has not been set
+ } catch (final IllegalStateException _ise) {
+ ise = _ise;
+ System.err.println("Expected "+ise.getClass().getSimpleName()+": "+ise.getMessage());
+ }
+ Assert.assertNotNull("TileRenderer.beginTile: Image-size exception missing", ise);
+
+ renderer.setImageSize(imageWidth, imageHeight);
+
+ renderer.clipImageSize(0, 0);
+ try {
+ renderer.beginTile(gl); // EOT reached (1)
+ } catch (final IllegalStateException _ise) {
+ ise = _ise;
+ System.err.println("Expected "+ise.getClass().getSimpleName()+": "+ise.getMessage());
+ }
+ Assert.assertNotNull("TileRenderer.beginTile: EOT (1) exception missing", ise);
+
+ renderer.clipImageSize(imageWidth, imageHeight); // back to full size
+
+ final Gears gears = new Gears();
+ gears.setVerbose(false);
+ gears.init(gl);
+
+ gears.addTileRendererNotify(renderer);
+ int numTiles = 0;
+ while( !renderer.eot() ) {
+ renderer.beginTile(gl);
+ gears.reshape(gl,
+ renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_Y_POS),
+ renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT),
+ renderer.getParam(TileRendererBase.TR_IMAGE_WIDTH), renderer.getParam(TileRendererBase.TR_IMAGE_HEIGHT));
+ gears.display(gl);
+ renderer.endTile(gl);
+ numTiles++;
+ }
+ try {
+ renderer.beginTile(gl); // EOT reached (2)
+ } catch (final IllegalStateException _ise) {
+ ise = _ise;
+ System.err.println("Expected "+ise.getClass().getSimpleName()+": "+ise.getMessage());
+ }
+ Assert.assertNotNull("TileRenderer.beginTile: EOT (2) exception missing", ise);
+ gears.removeTileRendererNotify(renderer);
+
+ Assert.assertTrue("TileRenderer not rendered more than one tile but "+numTiles, numTiles > 1);
+
+ destroyDrawableContext(dc);
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestTiledRendering1GL2NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java
new file mode 100644
index 000000000..e979ac966
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java
@@ -0,0 +1,263 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLPixelBuffer;
+import com.jogamp.opengl.util.TileRenderer;
+import com.jogamp.opengl.util.TileRendererBase;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+import java.io.File;
+import java.io.IOException;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
+
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Demos offscreen {@link GLAutoDrawable} being used for
+ * {@link TileRenderer} rendering to produce a PNG file.
+ * <p>
+ * {@link TileRenderer} is being kicked off from the main thread.
+ * </p>
+ * <p>
+ * {@link TileRenderer} buffer allocation is performed
+ * within the pre {@link GLEventListener}
+ * set via {@link TileRendererBase#setGLEventListener(GLEventListener, GLEventListener)}
+ * on the main thread.
+ * </p>
+ * <p>
+ * At tile rendering finish, the viewport and
+ * and the original {@link GLEventListener}'s PMV matrix as well.
+ * The latter is done by calling it's {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape} method.
+ * </p>
+*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTiledRendering2NEWT extends UITestCase {
+ static long duration = 500; // ms
+
+ static GLProfile getGLProfile(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return GLProfile.get(profile);
+ }
+ static GLProfile getGL2ES3() {
+ final GLProfile glp = GLProfile.getMaxProgrammableCore(true);
+ if( null == glp || !glp.isGL2ES3() ) {
+ System.err.println("GL2ES3 n/a, has max-core "+glp);
+ return null;
+ }
+ return glp;
+ }
+
+ @Test
+ public void test001_off_gl2___aa0() throws IOException {
+ final GLProfile glp = getGLProfile(GLProfile.GL2);
+ if( null == glp ) {
+ return;
+ }
+ doTest(false, new Gears(), glp, 0);
+ }
+ @Test
+ public void test002_off_gl2___aa8() throws IOException {
+ final GLProfile glp = getGLProfile(GLProfile.GL2);
+ if( null == glp ) {
+ return;
+ }
+ doTest(false, new Gears(), glp, 8);
+ }
+ @Test
+ public void test011_off_gl2es3_aa0() throws IOException {
+ final GLProfile glp = getGL2ES3();
+ if( null == glp ) {
+ return;
+ }
+ doTest(false, new GearsES2(), glp, 0);
+ }
+ @Test
+ public void test012_off_gl2es3_aa8() throws IOException {
+ final GLProfile glp = getGL2ES3();
+ if( null == glp ) {
+ return;
+ }
+ doTest(false, new GearsES2(), glp, 8);
+ }
+ @Test
+ public void test101_on__gl2___aa0() throws IOException {
+ final GLProfile glp = getGLProfile(GLProfile.GL2);
+ if( null == glp ) {
+ return;
+ }
+ doTest(true, new Gears(), glp, 0);
+ }
+ @Test
+ public void test102_on__gl2___aa8() throws IOException {
+ final GLProfile glp = getGLProfile(GLProfile.GL2);
+ if( null == glp ) {
+ return;
+ }
+ doTest(true, new Gears(), glp, 8);
+ }
+ @Test
+ public void test111_on__gl2es3_aa0() throws IOException {
+ final GLProfile glp = getGL2ES3();
+ if( null == glp ) {
+ return;
+ }
+ doTest(true, new GearsES2(), glp, 0);
+ }
+ @Test
+ public void test112_on__gl2es3_aa8() throws IOException {
+ final GLProfile glp = getGL2ES3();
+ if( null == glp ) {
+ return;
+ }
+ doTest(true, new GearsES2(), glp, 8);
+ }
+
+ void doTest(final boolean onscreen, final GLEventListener demo, final GLProfile glp, final int msaaCount) throws IOException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setDoubleBuffered(onscreen);
+ if( msaaCount > 0 ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(msaaCount);
+ }
+
+ final int maxTileSize = 256;
+ final GLAutoDrawable glad;
+ if( onscreen ) {
+ final GLWindow glWin = GLWindow.create(caps);
+ glWin.setSize(maxTileSize, maxTileSize);
+ glWin.setVisible(true);
+ glad = glWin;
+ } else {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp);
+ glad = factory.createOffscreenAutoDrawable(null, caps, null, maxTileSize, maxTileSize);
+ }
+
+ glad.addGLEventListener( demo );
+
+ // Fix the image size for now
+ final int imageWidth = glad.getSurfaceWidth() * 6;
+ final int imageHeight = glad.getSurfaceHeight() * 4;
+
+ final String filename = this.getSnapshotFilename(0, "-tile", glad.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null);
+ final File file = new File(filename);
+
+ // Initialize the tile rendering library
+ final TileRenderer renderer = new TileRenderer();
+ renderer.setImageSize(imageWidth, imageHeight);
+ renderer.setTileSize(glad.getSurfaceWidth(), glad.getSurfaceHeight(), 0);
+ renderer.attachAutoDrawable(glad);
+
+ final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride;
+ final boolean[] flipVertically = { false };
+
+ final GLEventListener preTileGLEL = new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3);
+ final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0);
+ renderer.setImageBuffer(pixelBuffer);
+ if( drawable.isGLOriented() ) {
+ flipVertically[0] = false;
+ } else {
+ flipVertically[0] = true;
+ }
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {}
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ };
+ renderer.setGLEventListener(preTileGLEL, null);
+
+ while ( !renderer.eot() ) {
+ renderer.display();
+ }
+
+ renderer.detachAutoDrawable();
+
+ // Restore viewport and Gear's PMV matrix
+ // .. even though we close the demo, this is for documentation!
+ glad.invoke(true, new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ drawable.getGL().glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ demo.reshape(drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ return false;
+ }
+ });
+
+ final GLPixelBuffer imageBuffer = renderer.getImageBuffer();
+ final TextureData textureData = new TextureData(
+ caps.getGLProfile(),
+ 0 /* internalFormat */,
+ imageWidth, imageHeight,
+ 0,
+ imageBuffer.pixelAttributes,
+ false, false,
+ flipVertically[0],
+ imageBuffer.buffer,
+ null /* Flusher */);
+
+ TextureIO.write(textureData, file);
+
+ glad.destroy();
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestTiledRendering2NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java
new file mode 100644
index 000000000..e84bb4d74
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java
@@ -0,0 +1,273 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Rectangle;
+import java.awt.Window;
+import java.awt.print.PageFormat;
+import java.awt.print.Paper;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.print.StreamPrintService;
+import javax.print.StreamPrintServiceFactory;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.standard.MediaSizeName;
+
+import jogamp.nativewindow.awt.AWTMisc;
+
+import org.junit.Assert;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.TileRenderer;
+
+/**
+ * Base unit test class implementing
+ * issuing {@link PrinterJob#print()} on a {@link Printable} implementation,
+ * i.e. {@link OnscreenPrintable} or {@link OffscreenPrintable}.
+ */
+public abstract class TiledPrintingAWTBase extends UITestCase {
+
+ private final RecursiveLock lock = LockFactory.createRecursiveLock();
+ private int printCount = 0;
+
+ public TiledPrintingAWTBase() {
+ super();
+ }
+
+ /**
+ *
+ * @param cont
+ * @param pOrientation
+ * @param paper
+ * @param offscrnImageType if < 0 onscreen, otherwise integer BufferedImage type
+ * @param dpi
+ * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples
+ * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param resizeWithinPrintTest TODO
+ */
+ public PrintableBase doPrintAuto(final Container cont, final int pOrientation, final Paper paper,
+ final int offscrnImageType, final int dpi, final int numSamples, final int tileWidth, final int tileHeight, final boolean resizeWithinPrintTest) {
+ lock.lock();
+ try {
+ final PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
+ aset.add(MediaSizeName.ISO_A1); // 594 × 841 mm
+ aset.add(MediaSizeName.ISO_A2); // 420 × 594 mm
+ aset.add(MediaSizeName.ISO_A3); // 297 × 420 mm
+ aset.add(MediaSizeName.ISO_A4); // 210 × 297 mm
+
+ printCount++;
+
+ final String psMimeType = "application/postscript";
+ final String pdfMimeType = "application/pdf";
+ final PrinterJob pj = PrinterJob.getPrinterJob();
+
+ StreamPrintServiceFactory[] factories = PrinterJob.lookupStreamPrintServices(pdfMimeType);
+ if (factories.length > 0) {
+ final String fname = getPrintFilename(offscrnImageType, dpi, numSamples, tileWidth, tileHeight, "pdf", resizeWithinPrintTest);
+ System.err.println("doPrint: dpi "+dpi+", "+fname);
+ FileOutputStream outstream;
+ try {
+ outstream = new FileOutputStream(fname);
+ return doPrintAutoImpl(cont, pj, factories[0].getPrintService(outstream), pOrientation, paper,
+ offscrnImageType, dpi, numSamples, tileWidth, tileHeight, resizeWithinPrintTest);
+ } catch (final FileNotFoundException e) {
+ Assert.assertNull("Unexpected exception", e);
+ }
+ }
+ System.err.println("No PDF");
+
+ factories = PrinterJob.lookupStreamPrintServices(psMimeType);
+ if (factories.length > 0) {
+ final String fname = getPrintFilename(offscrnImageType, dpi, numSamples, tileWidth, tileHeight, "ps", resizeWithinPrintTest);
+ System.err.println("doPrint: dpi "+dpi+", "+fname);
+ FileOutputStream outstream;
+ try {
+ outstream = new FileOutputStream(fname);
+ return doPrintAutoImpl(cont, pj, factories[0].getPrintService(outstream), pOrientation, paper, offscrnImageType, dpi, numSamples, tileWidth, tileHeight, resizeWithinPrintTest);
+ } catch (final FileNotFoundException e) {
+ Assert.assertNull("Unexpected exception", e);
+ }
+ }
+ System.err.println("No PS");
+ return null;
+ } finally {
+ lock.unlock();
+ }
+ }
+ private String getPrintFilename(final int offscrnImageType, final int dpi, final int numSamples, final int tileWidth, final int tileHeight, final String suffix, final boolean resizeWithinPrintTest) {
+ final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1;
+ final String simpleTestName = getSimpleTestName(".");
+ final String onoffscrn = 0 > offscrnImageType ? "on_screen" : "offscrn_"+offscrnImageType;
+ final String aa = 0 <= numSamples ? "aa"+numSamples : "aaN";
+ return String.format("%-"+maxSimpleTestNameLen+"s-n%04d-%s-dpi%03d-%s-tSz%04dx%04d-resize%d.%s",
+ simpleTestName, printCount, onoffscrn, dpi, aa, tileWidth, tileHeight, resizeWithinPrintTest?1:0, suffix).replace(' ', '_');
+ }
+ private PrintableBase doPrintAutoImpl(final Container cont, final PrinterJob job,
+ final StreamPrintService ps, final int pOrientation, final Paper paper,
+ final int offscrnImageType, final int dpi, final int numSamples, final int tileWidth, final int tileHeight, final boolean resizeWithinPrintTest) {
+ try {
+ final PageFormat pageFormat = job.defaultPage();
+ if( null != paper ) {
+ /**
+ Paper paper = new Paper();
+ paper.setSize(500,500); // Large Address Dimension
+ paper.setImageableArea(20, 20, 450, 420); */
+ pageFormat.setPaper(paper);
+ }
+ pageFormat.setOrientation(pOrientation); // PageFormat.LANDSCAPE or PageFormat.PORTRAIT
+ job.setPrintService(ps);
+ final PrintableBase printable;
+ if( 0 < offscrnImageType ) {
+ printable = new OffscreenPrintable(job, cont, dpi, numSamples, tileWidth, tileHeight, offscrnImageType, getPrintFilename(offscrnImageType, dpi, numSamples, tileWidth, tileHeight, "png", resizeWithinPrintTest));
+ } else {
+ printable = new OnscreenPrintable(job, cont, dpi, numSamples, tileWidth, tileHeight);
+ }
+ printable.job.setPrintable(printable, pageFormat);
+ doPrintImpl(printable, resizeWithinPrintTest);
+ return printable;
+ } catch (final PrinterException pe) {
+ pe.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * @param cont
+ * @param dpi
+ * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples
+ * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
+ */
+ public PrintableBase doPrintManual(final Container cont, final int dpi, final int numSamples, final int tileWidth, final int tileHeight) {
+ lock.lock();
+ try {
+ final OnscreenPrintable printable = new OnscreenPrintable(PrinterJob.getPrinterJob(), cont, dpi, numSamples, tileWidth, tileHeight);
+ printable.job.setPrintable(printable);
+ final boolean ok = printable.job.printDialog();
+ if (ok) {
+ doPrintImpl(printable, false);
+ }
+ return printable;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ private final AWTMisc.ComponentAction resizePlusAction = new AWTMisc.ComponentAction() {
+ @Override
+ public void run(final Component c) {
+ final Rectangle r = c.getBounds();
+ r.width += 64;
+ r.height += 64;
+ c.setBounds(r);
+ } };
+ private final AWTMisc.ComponentAction resizeMinusAction = new AWTMisc.ComponentAction() {
+ @Override
+ public void run(final Component c) {
+ final Rectangle r = c.getBounds();
+ r.width -= 64;
+ r.height -= 64;
+ c.setBounds(r);
+ } };
+
+ private void doPrintImpl(final PrintableBase printable, final boolean resizeWithinPrintTest) {
+ final double scaleGLMatXY = 72.0 / printable.dpi;
+ System.err.println("PRINTable: "+printable.getClass().getSimpleName());
+ System.err.println("PRINT DPI: "+printable.dpi+", AA "+printable.numSamples+", scaleGL "+scaleGLMatXY);
+ final AWTPrintLifecycle.Context ctx =
+ AWTPrintLifecycle.Context.setupPrint(printable.cont, scaleGLMatXY, scaleGLMatXY,
+ printable.numSamples, printable.tileWidth, printable.tileHeight);
+ System.err.println("PRINT AWTPrintLifecycle.setup.count "+ctx.getCount());
+ final int w = printable.cont.getWidth();
+ final int h = printable.cont.getHeight();
+ final long t0 = Platform.currentTimeMillis();
+ try {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ try {
+ if( resizeWithinPrintTest ) {
+ System.err.println("PRINT resizeWithinPrint size+ "+(w+64)+"x"+(h+64));
+ AWTMisc.performAction(printable.cont, GLAutoDrawable.class, resizePlusAction);
+ printable.cont.validate();
+ if( printable.cont instanceof Window ) {
+ ((Window)printable.cont).pack();
+ }
+ }
+ printable.job.print();
+ } catch (final PrinterException ex) {
+ ex.printStackTrace();
+ }
+ } });
+ } finally {
+ ctx.releasePrint();
+ final long td = Platform.currentTimeMillis() - t0;
+ System.err.println("PRINT Duration "+td+" ms");
+ if( resizeWithinPrintTest ) {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ System.err.println("PRINT resizeWithinPrint repaint");
+ printable.cont.repaint();
+ System.err.println("PRINT resizeWithinPrint size- "+w+"x"+h);
+ AWTMisc.performAction(printable.cont, GLAutoDrawable.class, resizeMinusAction);
+ printable.cont.validate();
+ if( printable.cont instanceof Window ) {
+ ((Window)printable.cont).pack();
+ }
+ } });
+ }
+ System.err.println("PRINT AWTPrintLifecycle.release.count "+ctx.getCount());
+ }
+ }
+
+ /** Wait for idle .. simply acquiring all locks and releasing them. */
+ public void waitUntilPrintJobsIdle(final PrintableBase p) {
+ lock.lock();
+ try {
+ if( null != p ) {
+ p.waitUntilIdle();
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TransparentPanel.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TransparentPanel.java
new file mode 100644
index 000000000..9fc790a77
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TransparentPanel.java
@@ -0,0 +1,59 @@
+package com.jogamp.opengl.test.junit.jogl.tile;
+
+import java.awt.*;
+import javax.swing.*;
+import java.lang.reflect.Method;
+
+public class TransparentPanel extends JPanel {
+ public TransparentPanel() {
+ super.setOpaque(false);
+ setMixingCutoutShape(new Rectangle());
+ }
+
+ @Override
+ public void setOpaque(final boolean isOpaque) {
+ // Don't let this panel become opaque
+ }
+
+ /**
+ * Helper utility needed to implement TransparentPanel.
+ * This class provides the ability to cut out the background of a lightweight
+ * panel so that it can be layered on top of a heavyweight component and have
+ * the heavyweight component show through. For more infromation, see:
+ *
+ * http://today.java.net/article/2009/11/02/transparent-panel-mixing-heavyweight-and-lightweight-components
+ */
+ private static Method mSetComponentMixing;
+
+ /**
+ * Set the cut out shape on a given Component.
+ *
+ * @param c The Component on which to set the cut out shape.
+ * @param s The shape to cut out of the given Component.
+ */
+ public void setMixingCutoutShape(final Shape s)
+ {
+ // Get the cut out shape method
+ if (mSetComponentMixing == null) {
+ try {
+ final Class<?> awtUtilitiesClass =
+ Class.forName("com.sun.awt.AWTUtilities");
+ mSetComponentMixing =
+ awtUtilitiesClass.getMethod(
+ "setComponentMixingCutoutShape",
+ Component.class, Shape.class);
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ // Cut out the shape
+ if (mSetComponentMixing != null) {
+ try {
+ mSetComponentMixing.invoke( null, this, s );
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1ImmModeSink.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1ImmModeSink.java
new file mode 100644
index 000000000..b3f85e879
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1ImmModeSink.java
@@ -0,0 +1,121 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.util;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLPipelineFactory;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.glu.GLU;
+import javax.media.opengl.glu.gl2es1.GLUgl2es1;
+
+import com.jogamp.opengl.util.ImmModeSink;
+import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil;
+import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode;
+
+class DemoGL2ES1ImmModeSink implements GLEventListener {
+ private boolean debugFFPEmu = false;
+ private boolean verboseFFPEmu = false;
+ private boolean traceFFPEmu = false;
+ private boolean forceFFPEmu = false;
+ final ImmModeSink ims;
+ final GLU glu;
+
+ DemoGL2ES1ImmModeSink(final boolean useVBO) {
+ ims = ImmModeSink.createFixed(3*3,
+ 3, GL.GL_FLOAT, // vertex
+ 3, GL.GL_FLOAT, // color
+ 0, GL.GL_FLOAT, // normal
+ 0, GL.GL_FLOAT, // texCoords
+ useVBO ? GL.GL_STATIC_DRAW : 0);
+ glu = new GLUgl2es1();
+ }
+
+ public void setForceFFPEmu(final boolean forceFFPEmu, final boolean verboseFFPEmu, final boolean debugFFPEmu, final boolean traceFFPEmu) {
+ this.forceFFPEmu = forceFFPEmu;
+ this.verboseFFPEmu = verboseFFPEmu;
+ this.debugFFPEmu = debugFFPEmu;
+ this.traceFFPEmu = traceFFPEmu;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ GL _gl = drawable.getGL();
+ if(debugFFPEmu) {
+ // Debug ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) );
+ }
+ if(traceFFPEmu) {
+ // Trace ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) );
+ }
+ final GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu);
+
+ System.err.println("GL_VENDOR "+gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER "+gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION "+gl.glGetString(GL.GL_VERSION));
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
+
+ gl.glMatrixMode( GLMatrixFunc.GL_PROJECTION );
+ gl.glLoadIdentity();
+
+ // coordinate system origin at lower left with width and height same as the window
+ glu.gluOrtho2D( 0.0f, width, 0.0f, height );
+
+ gl.glMatrixMode( GLMatrixFunc.GL_MODELVIEW );
+ gl.glLoadIdentity();
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
+
+ gl.glClear( GL.GL_COLOR_BUFFER_BIT );
+
+ // draw a triangle filling the window
+ ims.glBegin(GL.GL_TRIANGLES);
+ ims.glColor3f( 1, 0, 0 );
+ ims.glVertex2f( 0, 0 );
+ ims.glColor3f( 0, 1, 0 );
+ ims.glVertex2f( drawable.getSurfaceWidth(), 0 );
+ ims.glColor3f( 0, 0, 1 );
+ ims.glVertex2f( drawable.getSurfaceWidth() / 2f, drawable.getSurfaceHeight() );
+ ims.glEnd(gl, true);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ }
+} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1Plain.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1Plain.java
new file mode 100644
index 000000000..c1dd7fb58
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1Plain.java
@@ -0,0 +1,189 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.util;
+
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+import javax.media.opengl.glu.GLU;
+import javax.media.opengl.glu.gl2es1.GLUgl2es1;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.GLArrayDataWrapper;
+import com.jogamp.opengl.util.GLBuffers;
+
+class DemoGL2ES1Plain implements GLEventListener {
+ final boolean useArrayData;
+ final boolean useVBO;
+ final GLU glu;
+
+ final float[] vertices = new float[] { 0, 0, 0,
+ TestImmModeSinkES1NEWT.iWidth, 0, 0,
+ TestImmModeSinkES1NEWT.iWidth / 2, TestImmModeSinkES1NEWT.iHeight, 0 };
+
+ final float[] colors = new float[] { 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1 };
+
+ final ByteBuffer bufferAll;
+ final int bufferVOffset, bufferCOffset;
+ final int bufferVSize, bufferCSize;
+ final FloatBuffer bufferC, bufferV;
+ final int[] vboName = new int[] { 0 };
+ final GLArrayDataWrapper arrayC, arrayV;
+
+ DemoGL2ES1Plain(final boolean useArrayData, final boolean useVBO) {
+ this.useArrayData = useArrayData;
+ this.useVBO = useVBO;
+ this.glu = new GLUgl2es1();
+
+ bufferAll = Buffers.newDirectByteBuffer( ( colors.length + vertices.length ) * Buffers.SIZEOF_FLOAT );
+
+ bufferVOffset = 0;
+ bufferVSize = 3*3*GLBuffers.sizeOfGLType(GL.GL_FLOAT);
+ bufferCOffset = bufferVSize;
+ bufferCSize = 3*3*GLBuffers.sizeOfGLType(GL.GL_FLOAT);
+
+ bufferV = (FloatBuffer) GLBuffers.sliceGLBuffer(bufferAll, bufferVOffset, bufferVSize, GL.GL_FLOAT);
+ bufferV.put(vertices, 0, vertices.length).rewind();
+ bufferC = (FloatBuffer) GLBuffers.sliceGLBuffer(bufferAll, bufferCOffset, bufferCSize, GL.GL_FLOAT);
+ bufferC.put(colors, 0, colors.length).rewind();
+
+ System.err.println("bufferAll: "+bufferAll+", byteOffset "+Buffers.getDirectBufferByteOffset(bufferAll));
+ System.err.println("bufferV: off "+bufferVOffset+", size "+bufferVSize+": "+bufferV+", byteOffset "+Buffers.getDirectBufferByteOffset(bufferV));
+ System.err.println("bufferC: off "+bufferCOffset+", size "+bufferCSize+": "+bufferC+", byteOffset "+Buffers.getDirectBufferByteOffset(bufferC));
+
+ if(useArrayData) {
+ arrayV = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_VERTEX_ARRAY, 3, GL.GL_FLOAT, false, 0,
+ bufferV, 0, bufferVOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER);
+
+ arrayC = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_COLOR_ARRAY, 3, GL.GL_FLOAT, false, 0,
+ bufferC, 0, bufferCOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER);
+ } else {
+ arrayV = null;
+ arrayC = null;
+ }
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println("GL_VENDOR "+gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER "+gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION "+gl.glGetString(GL.GL_VERSION));
+ if(useVBO) {
+ gl.glGenBuffers(1, vboName, 0);
+ if(0 == vboName[0]) {
+ throw new GLException("glGenBuffers didn't return valid VBO name");
+ }
+ }
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
+
+ gl.glMatrixMode( GLMatrixFunc.GL_PROJECTION );
+ gl.glLoadIdentity();
+
+ // coordinate system origin at lower left with width and height same as the window
+ glu.gluOrtho2D( 0.0f, width, 0.0f, height );
+
+ gl.glMatrixMode( GLMatrixFunc.GL_MODELVIEW );
+ gl.glLoadIdentity();
+
+ gl.glViewport( 0, 0, width, height );
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
+
+ gl.glClear( GL.GL_COLOR_BUFFER_BIT );
+
+ // draw a triangle filling the window
+ gl.glLoadIdentity();
+
+ if(useVBO) {
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName[0]);
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, bufferAll.limit(), bufferAll, GL.GL_STATIC_DRAW);
+ if(useArrayData) {
+ arrayV.setVBOName(vboName[0]);
+ arrayC.setVBOName(vboName[0]);
+ }
+ }
+
+ gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ if(useArrayData) {
+ gl.glVertexPointer(arrayV);
+ } else {
+ if(useVBO) {
+ gl.glVertexPointer(3, GL.GL_FLOAT, 0, bufferVOffset);
+ } else {
+ gl.glVertexPointer(3, GL.GL_FLOAT, 0, bufferV);
+ }
+ }
+
+ gl.glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY);
+ if(useArrayData) {
+ gl.glColorPointer(arrayC);
+ } else {
+ if(useVBO) {
+ gl.glColorPointer(3, GL.GL_FLOAT, 0, bufferCOffset);
+ } else {
+ gl.glColorPointer(3, GL.GL_FLOAT, 0, bufferC);
+ }
+ }
+
+ if(useVBO) {
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ }
+
+ gl.glDrawArrays(GL.GL_TRIANGLES, 0, 3);
+ gl.glFlush();
+
+ gl.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
+ gl.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ if(0 != vboName[0]) {
+ gl.glDeleteBuffers(1, vboName, 0);
+ vboName[0] = 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java
new file mode 100644
index 000000000..d186643b7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java
@@ -0,0 +1,164 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util;
+
+import java.io.InputStream;
+import java.net.URLConnection;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor;
+import com.jogamp.opengl.test.junit.jogl.util.texture.PNGTstFiles;
+import com.jogamp.opengl.util.ImmModeSink;
+import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil;
+import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLPipelineFactory;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.media.opengl.glu.GLU;
+
+public class DemoGL2ES1TextureImmModeSink implements GLEventListener, TextureDraw01Accessor {
+ private boolean debugFFPEmu = false;
+ private boolean verboseFFPEmu = false;
+ private boolean traceFFPEmu = false;
+ private boolean forceFFPEmu = false;
+ private final ImmModeSink ims;
+ private final GLU glu = new GLU();
+ private TextureData textureData;
+ private Texture texture;
+ boolean keepTextureBound;
+
+ public DemoGL2ES1TextureImmModeSink() {
+ this.ims = ImmModeSink.createFixed(32, 3, GL.GL_FLOAT, 4, GL.GL_FLOAT, 0, GL.GL_FLOAT, 2, GL.GL_FLOAT, GL.GL_STATIC_DRAW);
+ this.keepTextureBound = false;
+ }
+
+ public void setForceFFPEmu(final boolean forceFFPEmu, final boolean verboseFFPEmu, final boolean debugFFPEmu, final boolean traceFFPEmu) {
+ this.forceFFPEmu = forceFFPEmu;
+ this.verboseFFPEmu = verboseFFPEmu;
+ this.debugFFPEmu = debugFFPEmu;
+ this.traceFFPEmu = traceFFPEmu;
+ }
+
+
+ @Override
+ public void setKeepTextureBound(final boolean v) {
+ this.keepTextureBound = v;
+ }
+ @Override
+ public Texture getTexture( ) {
+ return this.texture;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ GL _gl = drawable.getGL();
+ if(debugFFPEmu) {
+ // Debug ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) );
+ }
+ if(traceFFPEmu) {
+ // Trace ..
+ _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) );
+ }
+ final GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu);
+
+ final URLConnection testTextureUrlConn = IOUtil.getResource(PNGTstFiles.class, "test-ntscP_3-01-160x90.png");
+ try {
+ final InputStream testTextureStream = testTextureUrlConn.getInputStream();
+ textureData = TextureIO.newTextureData(gl.getGLProfile(), testTextureStream , false /* mipmap */, TextureIO.PNG);
+ texture = TextureIO.newTexture(gl, textureData);
+ if( keepTextureBound && null != texture ) {
+ texture.enable(gl);
+ texture.bind(gl);
+ }
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ glu.gluOrtho2D(0, 1, 0, 1);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
+ if(null!=texture) {
+ texture.disable(gl);
+ texture.destroy(gl);
+ }
+ if(null!=textureData) {
+ textureData.destroy();
+ }
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
+
+ // draw one quad with the texture
+ if(null!=texture) {
+ if( !keepTextureBound ) {
+ texture.enable(gl);
+ texture.bind(gl);
+ }
+ // gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE);
+ final TextureCoords coords = texture.getImageTexCoords();
+ ims.glBegin(ImmModeSink.GL_QUADS);
+ ims.glTexCoord2f(coords.left(), coords.bottom());
+ ims.glVertex3f(0, 0, 0);
+ ims.glTexCoord2f(coords.right(), coords.bottom());
+ ims.glVertex3f(1, 0, 0);
+ ims.glTexCoord2f(coords.right(), coords.top());
+ ims.glVertex3f(1, 1, 0);
+ ims.glTexCoord2f(coords.left(), coords.top());
+ ims.glVertex3f(0, 1, 0);
+ ims.glEnd(gl);
+ if( !keepTextureBound ) {
+ texture.disable(gl);
+ }
+ }
+ }
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES2ImmModeSink.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES2ImmModeSink.java
new file mode 100644
index 000000000..3dc29381a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES2ImmModeSink.java
@@ -0,0 +1,193 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.opengl.util.ImmModeSink;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+public class DemoGL2ES2ImmModeSink implements GLEventListener {
+
+ private final ShaderState st;
+ private final PMVMatrix pmvMatrix;
+ private final int glBufferUsage;
+ private ShaderProgram sp;
+ private GLUniformData pmvMatrixUniform;
+ private ImmModeSink ims;
+
+ public DemoGL2ES2ImmModeSink(final boolean useVBO, final boolean useShaderState) {
+ if(useShaderState) {
+ st = new ShaderState();
+ st.setVerbose(true);
+ } else {
+ st = null;
+ }
+ glBufferUsage = useVBO ? GL.GL_STATIC_DRAW : 0;
+ pmvMatrix = new PMVMatrix();
+ }
+
+ public void init(final GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+
+ System.err.println("GL_VENDOR "+gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER "+gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION "+gl.glGetString(GL.GL_VERSION));
+
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, DemoGL2ES2ImmModeSink.class,
+ "../demos/es2/shader", "../demos/es2/shader/bin", "mgl_default_xxx", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, DemoGL2ES2ImmModeSink.class,
+ "../demos/es2/shader", "../demos/es2/shader/bin", "mgl_default_xxx", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+
+ sp = new ShaderProgram();
+ sp.add(gl, vp0, System.err);
+ sp.add(gl, fp0, System.err);
+ if( null != st ) {
+ st.attachShaderProgram(gl, sp, true);
+ } else {
+ if(!sp.link(gl, System.err)) {
+ throw new GLException("Could not link program: "+sp);
+ }
+ sp.useProgram(gl, true);
+ }
+
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ if(null != st) {
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+ } else {
+ if( pmvMatrixUniform.setLocation(gl, sp.program()) < 0 ) {
+ throw new GLException("Could not find location for uniform: "+pmvMatrixUniform+", "+sp);
+ }
+ gl.glUniform(pmvMatrixUniform);
+ }
+
+ // Using predef array names, see
+ // GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex);
+ if( null != st ) {
+ ims = ImmModeSink.createGLSL(40,
+ 3, GL.GL_FLOAT, // vertex
+ 4, GL.GL_FLOAT, // color
+ 0, GL.GL_FLOAT, // normal
+ 0, GL.GL_FLOAT, // texCoords
+ glBufferUsage, st);
+ } else {
+ ims = ImmModeSink.createGLSL(40,
+ 3, GL.GL_FLOAT, // vertex
+ 4, GL.GL_FLOAT, // color
+ 0, GL.GL_FLOAT, // normal
+ 0, GL.GL_FLOAT, // texCoords
+ glBufferUsage, sp.program());
+ }
+ final int numSteps = 20;
+ final double increment = Math.PI / numSteps;
+ final double radius = 1;
+ ims.glBegin(GL.GL_LINES);
+ for (int i = numSteps - 1; i >= 0; i--) {
+ ims.glVertex3f((float) (radius * Math.cos(i * increment)),
+ (float) (radius * Math.sin(i * increment)),
+ 0f);
+ ims.glColor4f( 1f, 1f, 1f, 1f );
+ ims.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)),
+ (float) (-1.0 * radius * Math.sin(i * increment)),
+ 0f);
+ ims.glColor4f( 1f, 1f, 1f, 1f );
+ }
+ ims.glEnd(gl, false);
+
+ if(null != st) {
+ st.useProgram(gl, false);
+ } else {
+ gl.glUseProgram(0);
+ }
+ }
+
+ public void dispose(final GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ ims.destroy(gl);
+ ims = null;
+ if(null != st) {
+ st.destroy(gl);
+ }
+ }
+
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ gl.glClear( GL.GL_COLOR_BUFFER_BIT );
+
+ // draw a triangle filling the window
+ ims.glBegin(GL.GL_TRIANGLES);
+ ims.glColor3f( 1, 0, 0 );
+ ims.glVertex2f( 0, 0 );
+ ims.glColor3f( 0, 1, 0 );
+ ims.glVertex2f( drawable.getSurfaceWidth(), 0 );
+ ims.glColor3f( 0, 0, 1 );
+ ims.glVertex2f( drawable.getSurfaceWidth() / 2f, drawable.getSurfaceHeight() );
+ ims.glEnd(gl, true);
+ }
+
+ // Unused routines
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ System.err.println("reshape ..");
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+
+ // coordinate system origin at lower left with width and height same as the window
+ pmvMatrix.glOrthof( 0.0f, width, 0.0f, height, -1, 1 );
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+
+ if(null != st) {
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ } else {
+ gl.glUseProgram(sp.program());
+ gl.glUniform(pmvMatrixUniform);
+ gl.glUseProgram(0);
+ }
+ }
+
+ public void displayChanged(final GLAutoDrawable drawable, final boolean modeChanged, final boolean deviceChanged) {
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestES1FixedFunctionPipelineNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestES1FixedFunctionPipelineNEWT.java
new file mode 100644
index 000000000..979c4873e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestES1FixedFunctionPipelineNEWT.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+
+import com.jogamp.opengl.util.Animator;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestES1FixedFunctionPipelineNEWT extends UITestCase {
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 512;
+ height = 512;
+ }
+
+ @AfterClass
+ public static void releaseClass() {
+ }
+
+ protected void runTestGL0(final GLCapabilities caps, final GLEventListener demo) throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ glWindow.setTitle(getSimpleTestName("."));
+
+ glWindow.addGLEventListener(demo);
+ final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+ snap.setPostSNDetail(demo.getClass().getSimpleName());
+ glWindow.addGLEventListener(snap);
+
+ final Animator animator = new Animator(glWindow);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+ animator.setUpdateFPSFrames(1, null);
+ animator.start();
+
+ snap.setMakeSnapshot();
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+ glWindow.removeGLEventListener(demo);
+
+ animator.stop();
+ glWindow.destroy();
+ }
+
+ protected void runTestGL(final GLCapabilities caps, final boolean forceFFPEmu) throws InterruptedException {
+ final RedSquareES1 demo01 = new RedSquareES1();
+ demo01.setForceFFPEmu(forceFFPEmu, false, false, false);
+ runTestGL0(caps, demo01);
+
+ final GearsES1 demo02 = new GearsES1();
+ demo02.setForceFFPEmu(forceFFPEmu, false, false, false);
+ runTestGL0(caps, demo02);
+
+ final DemoGL2ES1ImmModeSink demo03 = new DemoGL2ES1ImmModeSink(true);
+ demo03.setForceFFPEmu(forceFFPEmu, false, false, false);
+ runTestGL0(caps, demo03);
+
+ final DemoGL2ES1TextureImmModeSink demo04 = new DemoGL2ES1TextureImmModeSink();
+ demo04.setForceFFPEmu(forceFFPEmu, false, false, false);
+ runTestGL0(caps, demo04);
+ }
+
+ @Test
+ public void test01GL2Normal() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL2)) { System.err.println("GL2 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2));
+ runTestGL(caps, false);
+ }
+
+ @Test
+ public void test02GL2FFPEmu() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL2)) { System.err.println("GL2 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2));
+ runTestGL(caps, true);
+ }
+
+ @Test
+ public void test03GL2ES1Normal() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GL2ES1)) { System.err.println("GL2ES1 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES1));
+ runTestGL(caps, false);
+ }
+
+ @Test
+ public void test04ES2FFPEmu() throws InterruptedException {
+ if(!GLProfile.isAvailable(GLProfile.GLES2)) { System.err.println("GLES2 n/a"); return; }
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+ runTestGL(caps, false); // should be FFPEmu implicit
+ }
+
+ static long duration = 1000; // ms
+
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ try {
+ duration = Integer.parseInt(args[i]);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestES1FixedFunctionPipelineNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES1NEWT.java
new file mode 100644
index 000000000..790f965b6
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES1NEWT.java
@@ -0,0 +1,143 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Testing the ImmModeSink w/ GL2ES1 context
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestImmModeSinkES1NEWT extends UITestCase {
+ static int duration = 100;
+ static final int iWidth = 400;
+ static final int iHeight = 400;
+
+ static GLCapabilities getCaps(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ void doTest(final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException {
+ System.out.println("Requested GL Caps: "+reqGLCaps);
+
+ //
+ // Create native windowing resources .. X11/Win/OSX
+ //
+ final GLWindow glad = GLWindow.create(reqGLCaps);
+ glad.addGLEventListener(demo);
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ glad.addGLEventListener(snapshotGLEventListener);
+ glad.setSize(iWidth, iHeight);
+ glad.setVisible(true);
+
+ snapshotGLEventListener.setMakeSnapshot();
+ glad.display(); // initial resize/display
+
+ Thread.sleep(duration);
+
+ glad.destroy();
+ }
+
+ @Test
+ public void test01Plain__GL2ES1_VBOOffUsePlain() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1);
+ if(null == reqGLCaps) return;
+ doTest(reqGLCaps, new DemoGL2ES1Plain(false, false));
+ }
+
+ @Test
+ public void test02Plain__GL2ES1_VBOOffUseArrayData() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1);
+ if(null == reqGLCaps) return;
+ doTest(reqGLCaps, new DemoGL2ES1Plain(true, false));
+ }
+
+ @Test
+ public void test03Plain__GL2ES1_VBOOnUsePlain() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1);
+ if(null == reqGLCaps) return;
+ doTest(reqGLCaps, new DemoGL2ES1Plain(false, true));
+ }
+
+ @Test
+ public void test04Plain__GL2ES1_VBOOnUseArrayData() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1);
+ if(null == reqGLCaps) return;
+ doTest(reqGLCaps, new DemoGL2ES1Plain(true, true));
+ }
+
+ @Test
+ public void test05ImmSinkGL2ES1_VBOOff() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1);
+ if(null == reqGLCaps) return;
+ doTest(reqGLCaps, new DemoGL2ES1ImmModeSink(false));
+ }
+
+ @Test
+ public void test06ImmSinkGL2ES1_VBOOn() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1);
+ if(null == reqGLCaps) return;
+ doTest(reqGLCaps, new DemoGL2ES1ImmModeSink(true));
+ }
+
+ @Test
+ public void test07ImmSinkGL2ES1_VBOOnTexture() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1);
+ if(null == reqGLCaps) return;
+ doTest(reqGLCaps, new DemoGL2ES1TextureImmModeSink());
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ duration = MiscUtils.atoi(args[++i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestImmModeSinkES1NEWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES2NEWT.java
new file mode 100644
index 000000000..9cf39a040
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES2NEWT.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Testing the ImmModeSink w/ GL2ES1 context
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestImmModeSinkES2NEWT extends UITestCase {
+ static int duration = 100;
+ static final int iWidth = 400;
+ static final int iHeight = 400;
+
+ static GLCapabilities getCaps(final String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ void doTest(final GLCapabilitiesImmutable reqGLCaps, final GLEventListener demo) throws InterruptedException {
+ System.out.println("Requested GL Caps: "+reqGLCaps);
+
+ //
+ // Create native windowing resources .. X11/Win/OSX
+ //
+ final GLWindow glad = GLWindow.create(reqGLCaps);
+ glad.addGLEventListener(demo);
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ glad.addGLEventListener(snapshotGLEventListener);
+ glad.setSize(iWidth, iHeight);
+ glad.setVisible(true);
+
+ snapshotGLEventListener.setMakeSnapshot();
+ glad.display(); // initial resize/display
+
+ Thread.sleep(duration);
+
+ glad.destroy();
+ }
+
+ @Test
+ public void test05ImmSinkGL2ES2_VBOOff_Direct() throws InterruptedException {
+ final GLCapabilities reqGLCaps = new GLCapabilities( GLProfile.getMaxFixedFunc(true) );
+ doTest(reqGLCaps, new DemoGL2ES2ImmModeSink(false, false));
+ }
+
+ @Test
+ public void test05ImmSinkGL2ES2_VBOOff_ShaderState() throws InterruptedException {
+ final GLCapabilities reqGLCaps = new GLCapabilities( GLProfile.getMaxFixedFunc(true) );
+ doTest(reqGLCaps, new DemoGL2ES2ImmModeSink(false, true));
+ }
+
+ @Test
+ public void test06ImmSinkGL2ES2_VBOOn_Direct() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ doTest(reqGLCaps, new DemoGL2ES2ImmModeSink(true, false));
+ }
+
+ @Test
+ public void test06ImmSinkGL2ES2_VBOOn_ShaderState() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ doTest(reqGLCaps, new DemoGL2ES2ImmModeSink(true, true));
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ duration = MiscUtils.atoi(args[++i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestImmModeSinkES2NEWT.class.getName());
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestPNGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestPNGImage01NEWT.java
deleted file mode 100644
index c7e975ff6..000000000
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestPNGImage01NEWT.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.jogamp.opengl.test.junit.jogl.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URLConnection;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.jogamp.common.util.IOUtil;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-import com.jogamp.opengl.util.texture.spi.PNGImage;
-
-public class TestPNGImage01NEWT extends UITestCase {
- @Test
- public void testPNGReadWriteAndCompare() throws InterruptedException, IOException, MalformedURLException {
- final File out1_f=new File(getSimpleTestName(".")+"-PNGImageTest1.png");
- final File out2_f=new File(getSimpleTestName(".")+"-PNGImageTest2.png");
- final String url_s="jogl/util/data/av/test-ntsc01-160x90.png";
- URLConnection urlConn = IOUtil.getResource(url_s, this.getClass().getClassLoader());
- PNGImage image0 = PNGImage.read(urlConn.getInputStream());
- System.err.println("PNGImage - Orig: "+image0);
- image0.write(out1_f, true);
- {
- Assert.assertEquals(image0.getData(), PNGImage.read(IOUtil.toURL(out1_f).openStream()).getData());
- }
-
- final PNGImage image1 = PNGImage.createFromData(image0.getWidth(), image0.getHeight(),
- image0.getDpi()[0], image0.getDpi()[1],
- image0.getBytesPerPixel(), false, image0.getData());
- image1.write(out2_f, true);
- {
- Assert.assertEquals(image0.getData(), PNGImage.read(IOUtil.toURL(out2_f).openStream()).getData());
- }
- }
-
- public static void main(String args[]) {
- org.junit.runner.JUnitCore.main(TestPNGImage01NEWT.class.getName());
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java
new file mode 100644
index 000000000..0d5d74a97
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+public class PNGTstFiles {
+ static public final String[] allBasenames = {
+ "test-ntscN_3-01-160x90",
+ "test-ntscN_4-01-160x90",
+ "test-ntscNG4-01-160x90",
+ "test-ntscI_3-01-160x90",
+ "test-ntscI_4-01-160x90",
+ "test-ntscIG3-01-160x90",
+ "test-ntscIG4-01-160x90",
+ "test-ntscP_3-01-160x90",
+ "test-ntscP_4-01-160x90",
+ "grayscale_texture",
+ "bug724-transparent-grey_orig",
+ "bug724-transparent-grey_gimpexp",
+ "cross-grey-alpha-16x16",
+ "pointer-grey-alpha-16x24",
+ };
+ static public final String[] greyBasenames = {
+ "grayscale_texture",
+ "bug724-transparent-grey_orig",
+ "bug724-transparent-grey_gimpexp",
+ "cross-grey-alpha-16x16",
+ "pointer-grey-alpha-16x24",
+ };
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java
new file mode 100644
index 000000000..a585e9eaf
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java
@@ -0,0 +1,98 @@
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.ByteBuffer;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.util.texture.spi.DDSImage;
+import com.jogamp.opengl.util.texture.spi.DDSImage.ImageInfo;
+
+/**
+ * This test uses the DDSImage class to read a dds image from file, extract the data,
+ * and use the class to create a new DDSImage from the extracted data
+ * <br></br>
+ * Bug Reference: https://jogamp.org/bugzilla/show_bug.cgi?id=362
+ * <br></br>
+ * The bug pertains to incorrect size calculation for checking validity of data. Compressed DXT1 has min of 8 bytes, DXT5 has min of 16 bytes.
+ * It exists in {@link DDSImage#createFromData(int, int, int, ByteBuffer[])}
+ * where an {@link IllegalArgumentException} is thrown for Mipmap level size mismatch.
+ * <br></br>
+ * <ul>The following cases are tested:
+ * <li>Uncompressed 64x32 RGB DDS Image with all mipmap levels (64x32 --> 1x1)</li>
+ * <li>DXT1 compressed 64x32 RGB DDS Image with all mipmap levels (64x32 --> 1x1)</li>
+ * <li>DXT5 compressed 64x32 RGB DDS Image with all mipmap levels (64x32 --> 1x1)</li>
+ * </ul>
+ *
+ * @author Michael Esemplare
+ *
+ */
+public class TestBug362DDSImageCreateFromData {
+
+ File testDDSImage01Uncompressed;
+ File testDDSImage02DXT1;
+ File testDDSImage03DXT5;
+
+ @Before
+ public void setup() throws Throwable {
+ testDDSImage01Uncompressed = initFile("test-64x32_uncompressed.dds");
+ testDDSImage02DXT1 = initFile("test-64x32_DXT1.dds");
+ testDDSImage03DXT5 = initFile("test-64x32_DXT5.dds");
+ }
+
+ @After
+ public void teardown() {
+ testDDSImage01Uncompressed = null;
+ testDDSImage02DXT1 = null;
+ testDDSImage03DXT5 = null;
+ }
+
+ private File initFile(final String filename) throws URISyntaxException {
+ final URLConnection connection = IOUtil.getResource(getClass(), filename);
+ Assert.assertNotNull(connection);
+ final URL url = connection.getURL();
+ final File file = new File(url.toURI());
+ Assert.assertTrue(file.exists());
+ return file;
+ }
+
+ private void testImpl(final File file) throws IOException {
+ final DDSImage ddsImage = DDSImage.read(file);
+ Assert.assertNotNull(ddsImage);
+ final int numMipMaps = ddsImage.getNumMipMaps();
+ final ByteBuffer[] mipMapArray = new ByteBuffer[numMipMaps];
+ for (int i=0;i<numMipMaps;i++){
+ final ImageInfo info = ddsImage.getMipMap(i);
+ mipMapArray[i] = info.getData();
+ }
+ final DDSImage newImage = DDSImage.createFromData(ddsImage.getPixelFormat(), ddsImage.getWidth(), ddsImage.getHeight(), mipMapArray);
+ Assert.assertNotNull(newImage);
+ }
+
+ @Test
+ public void test00_DDSImage_CreateFromData_Uncompressed_RGB () throws IOException {
+ testImpl(testDDSImage01Uncompressed);
+ }
+
+ @Test
+ public void test01_DDSImage_CreateFromData_DXT1_RGB () throws IOException {
+ testImpl(testDDSImage02DXT1);
+ }
+
+ @Test
+ public void test02_DDSImage_CreateFromData_DXT5_RGB () throws IOException {
+ testImpl(testDDSImage03DXT5);
+ }
+
+ public static void main(final String[] args) {
+ org.junit.runner.JUnitCore.main(TestBug362DDSImageCreateFromData.class.getName());
+ }
+} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java
new file mode 100644
index 000000000..2eb8b45c3
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java
@@ -0,0 +1,130 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelBufferProvider;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT extends UITestCase {
+ static long durationPerTest = 60; // ms
+
+ public static void main(final String[] args) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atoi(args[++i], 500);
+ }
+ }
+ System.out.println("durationPerTest: "+durationPerTest);
+ final String tstname = TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+ @Test
+ public void test00_RGBtoRGB() throws InterruptedException {
+ testImpl(false, false, false, false);
+ }
+ @Test
+ public void test01_RGBtoRGBA() throws InterruptedException {
+ testImpl(false, true, false, false);
+ }
+
+ @Test
+ public void test10_RGBAtoRGB() throws InterruptedException {
+ testImpl(true, false, false, false);
+ }
+ @Test
+ public void test11_RGBAtoRGBA() throws InterruptedException {
+ testImpl(true, true, false, false);
+ }
+ @Test
+ public void test21_RGBtoRGBA_pbuffer() throws InterruptedException {
+ testImpl(false, true, true, false);
+ }
+ @Test
+ public void test22_RGBtoRGBA_fbo() throws InterruptedException {
+ testImpl(false, true, false, true);
+ }
+ @Test
+ public void test31_RGBAtoRGBA_pbuffer() throws InterruptedException {
+ testImpl(true, true, true, false);
+ }
+ @Test
+ public void test32_RGBAtoRGBA_fbo() throws InterruptedException {
+ testImpl(true, true, false, true);
+ }
+
+ private void testImpl(final boolean alphaCaps, final boolean readAlpha, final boolean pbuffer, final boolean fbo) throws InterruptedException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(readAlpha ? true : false, false);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+
+ caps.setAlphaBits( alphaCaps ? 1 : 0 );
+ caps.setPBuffer( pbuffer );
+ caps.setFBO( fbo);
+
+ final GLWindow window = GLWindow.create(caps);
+ window.addGLEventListener(new GearsES2());
+ window.addGLEventListener(new GLEventListener() {
+ int displayCount = 0;
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
+ final GLPixelBufferProvider pixelBufferProvider = screenshot.getPixelBufferProvider();
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(drawable.getGL(), readAlpha ? 4 : 3);
+ System.err.println("GLPixelAttributes: "+pixelAttribs);
+ snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ });
+ window.setSize(512, 512);
+ window.setVisible(true);
+ window.requestFocus();
+
+ Thread.sleep(durationPerTest);
+
+ window.destroy();
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java
index e2252d635..e3be8ce33 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.util.texture;
import java.awt.Dimension;
@@ -51,7 +51,10 @@ import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLReadBufferUtilTextureIOWrite01AWT extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
@@ -68,10 +71,10 @@ public class TestGLReadBufferUtilTextureIOWrite01AWT extends UITestCase {
height = 256;
}
- protected void testWritePNG_Impl(boolean offscreenLayer) throws InterruptedException {
+ protected void testWritePNG_Impl(final boolean offscreenLayer) throws InterruptedException {
final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false);
final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false);
-
+
if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) {
System.err.println("onscreen layer n/a");
return;
@@ -79,40 +82,40 @@ public class TestGLReadBufferUtilTextureIOWrite01AWT extends UITestCase {
if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) {
System.err.println("offscreen layer n/a");
return;
- }
+ }
final GLCanvas glc = new GLCanvas(caps);
glc.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported
- Dimension glc_sz = new Dimension(width, height);
+ final Dimension glc_sz = new Dimension(width, height);
glc.setMinimumSize(glc_sz);
glc.setPreferredSize(glc_sz);
final Frame frame = new Frame(getSimpleTestName("."));
Assert.assertNotNull(frame);
frame.add(glc);
-
+
glc.setSize(width, height);
glc.addGLEventListener(new GearsES2(1));
glc.addGLEventListener(new GLEventListener() {
int f = 0;
- public void init(GLAutoDrawable drawable) {}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
snapshot(f, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null);
snapshot(f, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null);
f++;
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
-
- Animator animator = new Animator(glc);
+
+ final Animator animator = new Animator(glc);
animator.setUpdateFPSFrames(60, null);
-
+
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.pack();
frame.setVisible(true);
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
@@ -125,7 +128,7 @@ public class TestGLReadBufferUtilTextureIOWrite01AWT extends UITestCase {
while(animator.getTotalFPSFrames() < 2) {
Thread.sleep(60);
}
-
+
animator.stop();
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -134,23 +137,23 @@ public class TestGLReadBufferUtilTextureIOWrite01AWT extends UITestCase {
frame.remove(glc);
frame.dispose();
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
}
@Test
public void testOnscreenWritePNG() throws InterruptedException {
testWritePNG_Impl(false);
}
-
+
@Test
public void testOffscreenWritePNG() throws InterruptedException {
testWritePNG_Impl(true);
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestGLReadBufferUtilTextureIOWrite01AWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java
index 16bd94cfe..a10870635 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.util.texture;
import com.jogamp.newt.opengl.GLWindow;
@@ -44,7 +44,10 @@ import com.jogamp.opengl.test.junit.jogl.offscreen.WindowUtilNEWT;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLReadBufferUtilTextureIOWrite01NEWT extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
@@ -65,56 +68,56 @@ public class TestGLReadBufferUtilTextureIOWrite01NEWT extends UITestCase {
public void testOnscreenWritePNG_TGA_PAM() throws InterruptedException {
final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false);
final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false);
- GLWindow glWindow = GLWindow.create(caps);
+ final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
glWindow.setTitle("Shared Gears NEWT Test");
glWindow.setSize(width, height);
glWindow.addGLEventListener(new GearsES2(1));
glWindow.addGLEventListener(new GLEventListener() {
int f = 0;
- public void init(GLAutoDrawable drawable) {}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
snapshot(f++, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null);
- snapshot(f++, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null);
+ snapshot(f++, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null);
snapshot(f++, null, drawable.getGL(), screenshotRGBA, TextureIO.TGA, null);
- snapshot(f++, null, drawable.getGL(), screenshotRGB, TextureIO.TGA, null);
+ snapshot(f++, null, drawable.getGL(), screenshotRGB, TextureIO.TGA, null);
snapshot(f++, null, drawable.getGL(), screenshotRGBA, TextureIO.PAM, null);
- snapshot(f++, null, drawable.getGL(), screenshotRGB, TextureIO.PAM, null);
+ snapshot(f++, null, drawable.getGL(), screenshotRGB, TextureIO.PAM, null);
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
glWindow.setVisible(true);
Thread.sleep(60);
- glWindow.destroy();
+ glWindow.destroy();
}
@Test
public void testOffscreenWritePNG() throws InterruptedException {
final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false);
final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false);
- final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false);
- GLWindow glWindow = GLWindow.create(caps2);
+ final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false);
+ final GLWindow glWindow = GLWindow.create(caps2);
Assert.assertNotNull(glWindow);
glWindow.setSize(width, height);
glWindow.addGLEventListener(new GearsES2(1));
glWindow.addGLEventListener(new GLEventListener() {
int f = 0;
- public void init(GLAutoDrawable drawable) {}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
snapshot(f, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null);
snapshot(f, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null);
f++;
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
glWindow.setVisible(true);
Thread.sleep(60);
- glWindow.destroy();
+ glWindow.destroy();
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestGLReadBufferUtilTextureIOWrite01NEWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java
index bec55d868..8be3fb24b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.util.texture;
import java.awt.Dimension;
@@ -52,7 +52,10 @@ import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
@@ -69,7 +72,7 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase {
height = 64;
}
- protected void testWritePNGWithResizeImpl(boolean offscreenLayer) throws InterruptedException {
+ protected void testWritePNGWithResizeImpl(final boolean offscreenLayer) throws InterruptedException {
if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) {
System.err.println("onscreen layer n/a");
return;
@@ -77,28 +80,28 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase {
if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) {
System.err.println("offscreen layer n/a");
return;
- }
+ }
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
final GLCanvas glc = new GLCanvas(caps);
glc.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported
- Dimension glc_sz = new Dimension(width, height);
+ final Dimension glc_sz = new Dimension(width, height);
glc.setMinimumSize(glc_sz);
glc.setPreferredSize(glc_sz);
glc.setSize(glc_sz);
final Frame frame = new Frame(getSimpleTestName("."));
Assert.assertNotNull(frame);
frame.add(glc);
-
+
glc.addGLEventListener(new GearsES2(1));
glc.addGLEventListener(new GLEventListener() {
int i=0, fw_old=0, dw_old=0, c=0;
- public void init(GLAutoDrawable drawable) {}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
final int fw = frame.getWidth();
final int fh = frame.getHeight();
- final int dw = drawable.getWidth();
- final int dh = drawable.getHeight();
+ final int dw = drawable.getSurfaceWidth();
+ final int dh = drawable.getSurfaceHeight();
final boolean sz_changed = fw_old != fw && dw_old != dw && dw <= 512; // need to check both sizes [frame + drawable], due to async resize of AWT!
final boolean snap;
if(sz_changed) {
@@ -107,7 +110,7 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase {
} else {
snap = false;
}
-
+
if(snap) {
System.err.println("XXX: ["+fw_old+", "+dw_old+"], "+fw+"x"+fh+", "+dw+"x"+dh+", sz_changed "+sz_changed+", snap "+snap);
c=0;
@@ -125,19 +128,19 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase {
} }, glc.getTreeLock());
}
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
-
- Animator animator = new Animator(glc);
+
+ final Animator animator = new Animator(glc);
animator.setUpdateFPSFrames(60, null);
-
+
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.pack();
frame.setVisible(true);
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
@@ -150,7 +153,7 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase {
while(animator.getTotalFPSFrames() < 30) {
Thread.sleep(60);
}
-
+
animator.stop();
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -159,23 +162,23 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase {
frame.remove(glc);
frame.dispose();
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
}
@Test
public void testOnscreenWritePNGWithResize() throws InterruptedException {
testWritePNGWithResizeImpl(false);
}
-
+
@Test
public void testOffscreenWritePNGWithResize() throws InterruptedException {
testWritePNGWithResizeImpl(true);
}
-
- public static void main(String args[]) {
+
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestGLReadBufferUtilTextureIOWrite02AWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java
index 36d905a2c..cfae6f0df 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.util.texture;
import com.jogamp.newt.opengl.GLWindow;
@@ -46,7 +46,10 @@ import com.jogamp.opengl.test.junit.jogl.offscreen.WindowUtilNEWT;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
@@ -63,7 +66,7 @@ public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase {
height = 64;
}
- private void testWritePNGWithResizeImpl(boolean offscreen) throws InterruptedException {
+ private void testWritePNGWithResizeImpl(final boolean offscreen) throws InterruptedException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
final GLCapabilities caps2 = offscreen ? WindowUtilNEWT.fixCaps(caps, false, true, false) : caps;
final GLWindow glWindow = GLWindow.create(caps2);
@@ -73,15 +76,15 @@ public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase {
glWindow.addGLEventListener(new GearsES2(1));
glWindow.addGLEventListener(new GLEventListener() {
int i=0, dw_old=0, c=0;
- public void init(GLAutoDrawable drawable) {
+ public void init(final GLAutoDrawable drawable) {
System.err.println("XXX: init");
}
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
System.err.println("XXX: dispose");
}
- public void display(GLAutoDrawable drawable) {
- final int dw = drawable.getWidth();
- final int dh = drawable.getHeight();
+ public void display(final GLAutoDrawable drawable) {
+ final int dw = drawable.getSurfaceWidth();
+ final int dh = drawable.getSurfaceHeight();
final boolean sz_changed = dw_old != dw && dw <= 512;
final boolean snap;
if(sz_changed) {
@@ -90,35 +93,35 @@ public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase {
} else {
snap = false;
}
-
+
if(snap) {
System.err.println("XXX: ["+dw_old+"], "+dw+"x"+dh+", sz_changed "+sz_changed+", snap "+snap);
c=0;
snapshot(i++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
dw_old = dw;
- new Thread() {
+ new Thread() {
@Override
public void run() {
- glWindow.setSize(2*dw, 2*dh);
+ glWindow.setSize(2*dw, 2*dh);
} }.start();
}
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
- Animator animator = new Animator(glWindow);
+ final Animator animator = new Animator(glWindow);
animator.setUpdateFPSFrames(60, null);
-
+
glWindow.setVisible(true);
animator.start();
-
+
while(animator.getTotalFPSFrames() < 50) {
Thread.sleep(60);
}
-
+
animator.stop();
- glWindow.destroy();
+ glWindow.destroy();
}
-
+
@Test
public void testOnscreenWritePNGWithResize() throws InterruptedException {
testWritePNGWithResizeImpl(false);
@@ -129,7 +132,7 @@ public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase {
testWritePNGWithResizeImpl(true);
}
- public static void main(String args[]) {
+ public static void main(final String args[]) {
org.junit.runner.JUnitCore.main(TestGLReadBufferUtilTextureIOWrite02NEWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java
new file mode 100644
index 000000000..156ca20a1
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java
@@ -0,0 +1,166 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+import com.jogamp.opengl.util.texture.spi.JPEGImage;
+import javax.media.opengl.GL;
+
+/**
+ * Test reading and displaying a JPG image.
+ * <p>
+ * Main function accepts arbitrary JPG file name for manual tests.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestJPEGImage01NEWT extends UITestCase {
+
+ static boolean showFPS = false;
+ static long duration = 100; // ms
+
+ public void testImpl(final InputStream istream) throws InterruptedException, IOException {
+ final JPEGImage image = JPEGImage.read(istream);
+ Assert.assertNotNull(image);
+ final boolean hasAlpha = 4 == image.getBytesPerPixel();
+ System.err.println("JPEGImage: "+image+", hasAlpha "+hasAlpha);
+
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ if( hasAlpha ) {
+ caps.setAlphaBits(1);
+ }
+
+ final int internalFormat;
+ if(glp.isGL2ES3()) {
+ internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ } else {
+ internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB;
+ }
+ final TextureData texData = new TextureData(glp, internalFormat,
+ image.getWidth(),
+ image.getHeight(),
+ 0,
+ new GLPixelAttributes(image.getGLFormat(), image.getGLType()),
+ false /* mipmap */,
+ false /* compressed */,
+ false /* must flip-vert */,
+ image.getData(),
+ null);
+ // final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.JPG);
+ System.err.println("TextureData: "+texData);
+
+ final GLWindow glad = GLWindow.create(caps);
+ glad.setTitle("TestJPEGImage01NEWT");
+ // Size OpenGL to Video Surface
+ glad.setSize(texData.getWidth(), texData.getHeight());
+
+ // load texture from file inside current GL context to match the way
+ // the bug submitter was doing it
+ final GLEventListener gle = new TextureDraw01ES2Listener( texData, 0 ) ;
+ glad.addGLEventListener(gle);
+ glad.addGLEventListener(new GLEventListener() {
+ boolean shot = false;
+
+ @Override public void init(final GLAutoDrawable drawable) {}
+
+ public void display(final GLAutoDrawable drawable) {
+ // 1 snapshot
+ if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
+ shot = true;
+ snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ }
+
+ @Override public void dispose(final GLAutoDrawable drawable) { }
+ @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ });
+
+ final Animator animator = new Animator(glad);
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glad.addKeyListener(quitAdapter);
+ glad.addWindowListener(quitAdapter);
+ glad.setVisible(true);
+ animator.start();
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+ glad.destroy();
+ }
+
+ @Test
+ public void testReadES2_RGBn() throws InterruptedException, IOException, MalformedURLException {
+ final String fname = null == _fname ? "test-ntscN_3-01-160x90-90pct-yuv444-base.jpg" : _fname;
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname);
+ testImpl(urlConn.getInputStream());
+ }
+
+ static String _fname = null;
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-file")) {
+ i++;
+ _fname = args[i];
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestJPEGImage01NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java
new file mode 100644
index 000000000..7c11d7275
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.awt.AWTTextureData;
+import com.jogamp.opengl.util.texture.spi.JPEGImage;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLConnection;
+import java.nio.Buffer;
+
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestJPEGJoglAWTBenchmarkNewtAWT extends UITestCase {
+ static boolean showFPS = false;
+ static String fname = "j1-baseline.jpg";
+
+ @Test
+ public void benchmark() throws IOException {
+ benchmarkImpl(100, fname);
+ }
+ void benchmarkImpl(final int loops, final String fname) throws IOException {
+ {
+ final long t0 = System.currentTimeMillis();
+ for(int i = 0; i< loops; i++ ) {
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname);
+ final InputStream istream = urlConn.getInputStream();
+ final JPEGImage image = JPEGImage.read(istream); // parsing & completion done !!!
+ final int internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB;
+ final TextureData texData = new TextureData(GLProfile.getGL2ES2(), internalFormat,
+ image.getWidth(),
+ image.getHeight(),
+ 0,
+ new GLPixelAttributes(image.getGLFormat(), image.getGLType()),
+ false /* mipmap */,
+ false /* compressed */,
+ false /* must flip-vert */,
+ image.getData(),
+ null);
+ if(0==i || loops-1==i) {
+ System.err.println(i+": "+image.toString());
+ System.err.println(i+": "+texData+", buffer "+texData.getBuffer());
+ }
+ istream.close();
+ }
+ final long t1 = System.currentTimeMillis();
+ final long dt = t1 - t0;
+ final float msPl = (float)dt / (float)loops ;
+ System.err.println("JOGL.RGB Loops "+loops+", dt "+dt+" ms, "+msPl+" ms/l");
+ }
+ {
+ final long t0 = System.currentTimeMillis();
+ for(int i = 0; i< loops; i++ ) {
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname);
+ final InputStream istream = urlConn.getInputStream();
+ final JPEGImage image = JPEGImage.read(istream, TextureData.ColorSpace.YCbCr); // parsing & completion done !!!
+ final int internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB;
+ final TextureData texData = new TextureData(GLProfile.getGL2ES2(), internalFormat,
+ image.getWidth(),
+ image.getHeight(),
+ 0,
+ new GLPixelAttributes(image.getGLFormat(), image.getGLType()),
+ false /* mipmap */,
+ false /* compressed */,
+ false /* must flip-vert */,
+ image.getData(),
+ null);
+ if(0==i || loops-1==i) {
+ System.err.println(i+": "+image.toString());
+ System.err.println(i+": "+texData+", buffer "+texData.getBuffer());
+ }
+ istream.close();
+ }
+ final long t1 = System.currentTimeMillis();
+ final long dt = t1 - t0;
+ final float msPl = (float)dt / (float)loops ;
+ System.err.println("JOGL.YUV Loops "+loops+", dt "+dt+" ms, "+msPl+" ms/l");
+ }
+ {
+ final long t0 = System.currentTimeMillis();
+ for(int i = 0; i< loops; i++ ) {
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname);
+ final InputStream istream = urlConn.getInputStream();
+ Buffer data = null;
+ try {
+ final BufferedImage img = ImageIO.read(istream);
+ final AWTTextureData texData = new AWTTextureData(GLProfile.getGL2ES2(), 0, 0, false, img);
+ data = texData.getBuffer(); // completes data conversion !!!
+ if(0==i || loops-1==i) {
+ System.err.println(i+": "+texData+", buffer "+data);
+ }
+ } catch (final Exception e) {
+ System.err.println("AWT ImageIO failure w/ file "+fname+": "+e.getMessage());
+ }
+ istream.close();
+ }
+ final long t1 = System.currentTimeMillis();
+ final long dt = t1 - t0;
+ final float msPl = (float)dt / (float)loops ;
+ System.err.println("AWT..... Loops "+loops+", dt "+dt+" ms, "+msPl+" ms/l");
+ }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-file")) {
+ i++;
+ fname = args[i];
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestJPEGJoglAWTBenchmarkNewtAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java
new file mode 100644
index 000000000..067ee9d67
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java
@@ -0,0 +1,270 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLCapabilities;
+
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+import com.jogamp.opengl.util.texture.awt.AWTTextureData;
+import com.jogamp.opengl.util.texture.spi.JPEGImage;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLConnection;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestJPEGJoglAWTCompareNewtAWT extends UITestCase {
+ static boolean showFPS = false;
+ static long duration = 100; // ms
+
+ String[] files = { "test-ntscN_3-01-160x90-90pct-yuv444-base.jpg", // 0
+ "test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg", // 1
+ "test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg", // 2
+ "test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg", // 3
+ "j1-baseline.jpg", // 4
+ "j2-progressive.jpg", // 5
+ "j3-baseline_gray.jpg", // 6
+ "test-cmyk-01.jpg", // 7
+ "test-ycck-01.jpg" }; // 8
+
+ void testImpl(final String fname) throws InterruptedException, IOException {
+ final Animator animator = new Animator();
+
+ final GLWindow w1 = testJOGLJpeg(fname);
+ final GLWindow w2 = testAWTJpeg(fname, w1.getSurfaceWidth() + 50);
+
+ animator.add(w1);
+ animator.add(w2);
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ w1.setVisible(true);
+ w2.setVisible(true);
+ animator.start();
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+ w1.destroy();
+ w2.destroy();
+ }
+
+ GLWindow testJOGLJpeg(final String fname) throws InterruptedException, IOException {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), fname);
+ Assert.assertNotNull(testTextureUrlConn);
+ final InputStream istream = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(istream);
+
+ final JPEGImage image = JPEGImage.read(istream);
+ Assert.assertNotNull(image);
+ System.err.println("JPEGImage: "+image);
+
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final int internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB;
+ final TextureData texData = new TextureData(glp, internalFormat,
+ image.getWidth(),
+ image.getHeight(),
+ 0,
+ new GLPixelAttributes(image.getGLFormat(), image.getGLType()),
+ false /* mipmap */,
+ false /* compressed */,
+ false /* must flip-vert */,
+ image.getData(),
+ null);
+ // final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.JPG);
+ System.err.println("TextureData: "+texData);
+
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(1);
+
+ final GLWindow glad1 = GLWindow.create(caps);
+ glad1.setTitle("JPEG JOGL");
+ // Size OpenGL to Video Surface
+ glad1.setSize(texData.getWidth(), texData.getHeight());
+ glad1.setPosition(0, 0);
+
+ // load texture from file inside current GL context to match the way
+ // the bug submitter was doing it
+ final GLEventListener gle = new TextureDraw01ES2Listener( texData, 0 ) ;
+ glad1.addGLEventListener(gle);
+ glad1.addGLEventListener(new GLEventListener() {
+ boolean shot = false;
+
+ @Override public void init(final GLAutoDrawable drawable) {}
+
+ public void display(final GLAutoDrawable drawable) {
+ // 1 snapshot
+ if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
+ shot = true;
+ snapshot(0, "JoglJPEG", drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ }
+
+ @Override public void dispose(final GLAutoDrawable drawable) { }
+ @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ });
+
+ return glad1;
+ }
+
+ GLWindow testAWTJpeg(final String fname, final int xpos) throws InterruptedException, IOException {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), fname);
+ Assert.assertNotNull(testTextureUrlConn);
+ final InputStream istream = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(istream);
+
+ final GLProfile glp = GLProfile.getGL2ES2();
+ TextureData texData = null;
+ int w = 300, h = 300;
+ try {
+ final BufferedImage img = ImageIO.read(istream);
+ texData = new AWTTextureData(glp, 0, 0, false, img);
+ System.err.println("TextureData: "+texData);
+ w = texData.getWidth();
+ h = texData.getHeight();
+ } catch (final Exception e) {
+ System.err.println("AWT ImageIO failure w/ file "+fname+": "+e.getMessage());
+ // e.printStackTrace(); // : CMYK, YCCK -> com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(Unknown Source)
+ }
+
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(1);
+
+ final GLWindow glad1 = GLWindow.create(caps);
+ glad1.setTitle("JPEG AWT");
+ // Size OpenGL to Video Surface
+ glad1.setSize(w, h);
+ glad1.setPosition(xpos, 0);
+
+ // load texture from file inside current GL context to match the way
+ // the bug submitter was doing it
+ final GLEventListener gle;
+ if( texData != null ) {
+ gle = new TextureDraw01ES2Listener( texData, 0 ) ;
+ glad1.addGLEventListener(gle);
+ } else {
+ gle = null;
+ }
+ glad1.addGLEventListener(new GLEventListener() {
+ boolean shot = false;
+
+ @Override public void init(final GLAutoDrawable drawable) {}
+
+ public void display(final GLAutoDrawable drawable) {
+ // 1 snapshot
+ if( null!=gle && null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
+ shot = true;
+ snapshot(0, "AWTJPEG", drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ }
+
+ @Override public void dispose(final GLAutoDrawable drawable) { }
+ @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ });
+
+ return glad1;
+ }
+
+ @Test
+ public void test01YUV444Base__ES2() throws InterruptedException, IOException {
+ testImpl(files[0]);
+ }
+ @Test
+ public void test01YUV444Prog__ES2() throws InterruptedException, IOException {
+ testImpl(files[1]);
+ }
+
+ @Test
+ public void test01YUV422hBase__ES2() throws InterruptedException, IOException {
+ testImpl(files[2]);
+ }
+ @Test
+ public void test01YUV422hProg_ES2() throws InterruptedException, IOException {
+ testImpl(files[3]);
+ }
+
+ @Test
+ public void test02YUV420Base__ES2() throws InterruptedException, IOException {
+ testImpl(files[4]);
+ }
+ @Test
+ public void test02YUV420Prog_ES2() throws InterruptedException, IOException {
+ testImpl(files[5]);
+ }
+ @Test
+ public void test02YUV420BaseGray_ES2() throws InterruptedException, IOException {
+ testImpl(files[6]);
+ }
+
+ @Test
+ public void test03CMYK_01_ES2() throws InterruptedException, IOException {
+ testImpl(files[7]);
+ }
+ @Test
+ public void test03YCCK_01_ES2() throws InterruptedException, IOException {
+ testImpl(files[8]);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestJPEGJoglAWTCompareNewtAWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java
new file mode 100644
index 000000000..565434e2e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java
@@ -0,0 +1,284 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLCapabilities;
+
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLConnection;
+
+import org.junit.Assert;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestJPEGTextureFromFileNEWT extends UITestCase {
+ static boolean showFPS = false;
+ static long duration = 100; // ms
+
+ InputStream testTextureStream01YUV444_Base;
+ InputStream testTextureStream01YUV444_Prog;
+
+ InputStream testTextureStream01YUV422h_Base;
+ InputStream testTextureStream01YUV422h_Prog;
+
+ InputStream testTextureStream02YUV420_Base;
+ InputStream testTextureStream02YUV420_Prog;
+ InputStream testTextureStream02YUV420_BaseGray;
+
+ InputStream testTextureStream03CMYK_01;
+ InputStream testTextureStream03YCCK_01;
+
+ InputStream testTextureStream04QTTDefPostFrame;
+
+ @Before
+ public void initTest() throws IOException {
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-90pct-yuv444-base.jpg");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream01YUV444_Base = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream01YUV444_Base);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream01YUV444_Prog = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream01YUV444_Prog);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream01YUV422h_Base = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream01YUV422h_Base);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream01YUV422h_Prog = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream01YUV422h_Prog);
+ }
+
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "j1-baseline.jpg");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream02YUV420_Base = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream02YUV420_Base);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "j2-progressive.jpg");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream02YUV420_Prog = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream02YUV420_Prog);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "j3-baseline_gray.jpg");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream02YUV420_BaseGray = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream02YUV420_BaseGray);
+ }
+
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-cmyk-01.jpg");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream03CMYK_01 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream03CMYK_01);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ycck-01.jpg");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream03YCCK_01 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream03YCCK_01);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "bug745_qttdef_post_frame.jpg");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream04QTTDefPostFrame = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream04QTTDefPostFrame);
+ }
+
+ }
+
+ @After
+ public void cleanupTest() {
+ testTextureStream01YUV444_Base = null;
+ testTextureStream01YUV444_Prog = null;
+ testTextureStream01YUV422h_Base = null;
+ testTextureStream01YUV422h_Prog = null;
+ testTextureStream02YUV420_Base = null;
+ testTextureStream02YUV420_Prog = null;
+ testTextureStream02YUV420_BaseGray = null;
+ testTextureStream03CMYK_01 = null;
+ testTextureStream03YCCK_01 = null;
+ testTextureStream04QTTDefPostFrame = null;
+ }
+
+ public void testImpl(final boolean useFFP, final InputStream istream) throws InterruptedException, IOException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+ GLProfile glp;
+ if(useFFP && GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.getMaxFixedFunc(true);
+ } else if(!useFFP && GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.getGL2ES2();
+ } else {
+ System.err.println(getSimpleTestName(".")+": GLProfile n/a, useFFP: "+useFFP);
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(1);
+
+ final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.JPG);
+ System.err.println("TextureData: "+texData);
+
+ final GLWindow glad = GLWindow.create(caps);
+ glad.setTitle("TestPNGTextureGL2FromFileNEWT");
+ // Size OpenGL to Video Surface
+ glad.setSize(texData.getWidth(), texData.getHeight());
+
+ // load texture from file inside current GL context to match the way
+ // the bug submitter was doing it
+ final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ;
+ glad.addGLEventListener(gle);
+ glad.addGLEventListener(new GLEventListener() {
+ boolean shot = false;
+
+ @Override public void init(final GLAutoDrawable drawable) {}
+
+ public void display(final GLAutoDrawable drawable) {
+ // 1 snapshot
+ if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
+ shot = true;
+ snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ }
+
+ @Override public void dispose(final GLAutoDrawable drawable) { }
+ @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ });
+
+ final Animator animator = new Animator(glad);
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glad.addKeyListener(quitAdapter);
+ glad.addWindowListener(quitAdapter);
+ glad.setVisible(true);
+ animator.start();
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+ glad.destroy();
+ }
+
+ @Test
+ public void test01YUV444Base__GL2() throws InterruptedException, IOException {
+ testImpl(true, testTextureStream01YUV444_Base);
+ }
+ @Test
+ public void test01YUV444Base__ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStream01YUV444_Base);
+ }
+ @Test
+ public void test01YUV444Prog__GL2() throws InterruptedException, IOException {
+ testImpl(true, testTextureStream01YUV444_Prog);
+ }
+ @Test
+ public void test01YUV444Prog__ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStream01YUV444_Prog);
+ }
+
+ @Test
+ public void test01YUV422hBase__ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStream01YUV422h_Base);
+ }
+ @Test
+ public void test01YUV422hProg_ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStream01YUV422h_Prog);
+ }
+
+ @Test
+ public void test02YUV420Base__ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStream02YUV420_Base);
+ }
+ @Test
+ public void test02YUV420Prog_ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStream02YUV420_Prog);
+ }
+ @Test
+ public void test02YUV420BaseGray_ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStream02YUV420_BaseGray);
+ }
+
+ @Test
+ public void test03CMYK_01_ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStream03CMYK_01);
+ }
+ @Test
+ public void test03YCCK_01_ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStream03YCCK_01);
+ }
+
+ @Test
+ public void test04QTTDefPostFrame_ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStream04QTTDefPostFrame);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestJPEGTextureFromFileNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java
new file mode 100644
index 000000000..8f63a4f4c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java
@@ -0,0 +1,226 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelFormatUtil;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.PNGPixelRect;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPNGPixelRect00NEWT extends UITestCase {
+ @Test
+ public void testPNGRead01_All() throws InterruptedException, IOException, MalformedURLException {
+ for(int i=0; i<PNGTstFiles.allBasenames.length; i++) {
+ final String basename = PNGTstFiles.allBasenames[i];
+ final String pathname="";
+ testPNG01Impl(pathname, basename, null, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ }
+
+ @Test
+ public void testPNGRead02_RGB888_to_RGBA8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_3-01-160x90";
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead03_RGB888_to_RGBA8888_stride1000() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_3-01-160x90"; // 640 bytes = 4 * 160
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 1000 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead04_RGB888_to_RGBA8888_stride999() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_3-01-160x90"; // 640 bytes = 4 * 160
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 999 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead11_RGBA8888_to_LUMINA() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.LUMINANCE, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead12_RGBA8888_to_RGB888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.RGB888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead13_RGBA8888_to_BGR888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.BGR888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead14_RGBA8888_to_BGRA8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.BGRA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testPNGRead15_RGBA8888_to_ARGB8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.ARGB8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testPNGRead16_RGBA8888_to_ABGR8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.ABGR8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ private void testPNG01Impl(final String pathname, final String basename,
+ final PixelFormat destFmt, final int destMinStrideInBytes, final boolean destIsGLOriented)
+ throws InterruptedException, IOException, MalformedURLException
+ {
+ System.err.println("Test01: "+pathname+basename+".png, destFmt "+destFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented);
+
+ final File out1_f=new File(getSimpleTestName(".")+"-01-"+basename+"-orig.png");
+ final File out2F_f=new File(getSimpleTestName(".")+"-02-"+basename+"-flipped.png");
+ final File out2R_f=new File(getSimpleTestName(".")+"-03-"+basename+"-reversed.png");
+ final File out2RF_f=new File(getSimpleTestName(".")+"-04-"+basename+"-reversed_flipped.png");
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png");
+ if( null == urlConn ) {
+ throw new IOException("Cannot find "+pathname+basename+".png");
+ }
+ final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), destFmt, false /* directBuffer */, destMinStrideInBytes, destIsGLOriented);
+ System.err.println("PNGPixelRect - Orig: "+image1);
+ {
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out1_f, true /* allowOverwrite */));
+ image1.write(outs, true /* close */);
+ {
+ final PNGPixelRect image1_R = PNGPixelRect.read(out1_f.toURI().toURL().openStream(), image1.getPixelformat(), false /* directBuffer */, destMinStrideInBytes, destIsGLOriented);
+ System.err.println("PNGPixelRect - Orig (Read Back): "+image1_R);
+ Assert.assertEquals(image1.getPixels(), image1_R.getPixels());
+ }
+ }
+
+ //
+ // Flipped Orientation
+ //
+ {
+ final PNGPixelRect image2F = new PNGPixelRect(image1.getPixelformat(), image1.getSize(),
+ image1.getStride(), !image1.isGLOriented(), image1.getPixels(),
+ image1.getDpi()[0], image1.getDpi()[1]);
+ System.err.println("PNGPixelRect - Flip : "+image2F);
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out2F_f, true /* allowOverwrite */));
+ image2F.write(outs, true /* close */);
+ {
+ // flip again .. to compare w/ original
+ final PNGPixelRect image2F_R = PNGPixelRect.read(out2F_f.toURI().toURL().openStream(), image1.getPixelformat(), false /* directBuffer */, destMinStrideInBytes, !destIsGLOriented);
+ System.err.println("PNGPixelRect - Flip (Read Back): "+image2F_R);
+ Assert.assertEquals(image1.getPixels(), image2F_R.getPixels());
+ }
+ }
+
+ //
+ // Reversed Components
+ //
+ final PixelFormat revFmt = PixelFormatUtil.getReversed(image1.getPixelformat());
+ {
+ final PNGPixelRect image2R = new PNGPixelRect(revFmt, image1.getSize(),
+ image1.getStride(), image1.isGLOriented(), image1.getPixels(),
+ image1.getDpi()[0], image1.getDpi()[1]);
+ System.err.println("PNGPixelRect - Reversed : "+image2R);
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out2R_f, true /* allowOverwrite */));
+ image2R.write(outs, true /* close */);
+ {
+ // reverse again .. to compare w/ original
+ final PNGPixelRect image2R_R = PNGPixelRect.read(out2R_f.toURI().toURL().openStream(), revFmt, false /* directBuffer */, destMinStrideInBytes, destIsGLOriented);
+ System.err.println("PNGPixelRect - Reversed (Read Back): "+image2R_R);
+ Assert.assertEquals(image1.getPixels(), image2R_R.getPixels());
+ }
+ }
+
+ // reversed channels and flipped
+ {
+ final PNGPixelRect image2RF = new PNGPixelRect(revFmt, image1.getSize(),
+ image1.getStride(), !image1.isGLOriented(), image1.getPixels(),
+ image1.getDpi()[0], image1.getDpi()[1]);
+ System.err.println("PNGPixelRect - Reversed+Flipped : "+image2RF);
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out2RF_f, true /* allowOverwrite */));
+ image2RF.write(outs, true /* close */);
+ {
+ // reverse+flip again .. to compare w/ original
+ final PNGPixelRect image2RF_R = PNGPixelRect.read(out2RF_f.toURI().toURL().openStream(), revFmt, false /* directBuffer */, destMinStrideInBytes, !destIsGLOriented);
+ System.err.println("PNGPixelRect - Reversed+FLipped (Read Back): "+image2RF_R);
+ Assert.assertEquals(image1.getPixels(), image2RF_R.getPixels());
+ }
+ }
+ }
+
+ private void testPNG02Impl(final String pathname, final String basename,
+ final PixelFormat destFmt, final int destMinStrideInBytes, final boolean destIsGLOriented)
+ throws InterruptedException, IOException, MalformedURLException
+ {
+ System.err.println("Test02: "+pathname+basename+".png, destFmt "+destFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented);
+
+ final File out1_f=new File(getSimpleTestName(".")+"-"+basename+"-orig.png");
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png");
+
+ final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), destFmt, false /* directBuffer */, destMinStrideInBytes, destIsGLOriented);
+ System.err.println("PNGPixelRect - Orig: "+image1);
+ {
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out1_f, true /* allowOverwrite */));
+ image1.write(outs, true /* close */);
+ {
+ final PNGPixelRect image1_R = PNGPixelRect.read(out1_f.toURI().toURL().openStream(), image1.getPixelformat(), false /* directBuffer */, destMinStrideInBytes, destIsGLOriented);
+ System.err.println("PNGPixelRect - Orig (Read Back): "+image1_R);
+ Assert.assertEquals(image1.getPixels(), image1_R.getPixels());
+ }
+ }
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestPNGPixelRect00NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java
new file mode 100644
index 000000000..4a324f594
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java
@@ -0,0 +1,207 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.PNGPixelRect;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Test reading and displaying a PNG image.
+ * <p>
+ * Main function accepts arbitrary PNG file name for manual tests.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPNGPixelRect01NEWT extends UITestCase {
+ static boolean showFPS = false;
+ static long duration = 200; // ms
+
+ public void testImpl(final int num, final String basename, final InputStream istream, final PixelFormat destFmt) throws InterruptedException, IOException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final PNGPixelRect image = PNGPixelRect.read(istream, destFmt, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */);
+ Assert.assertNotNull(image);
+ final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp);
+ final boolean hasAlpha = 4 == glpa.bytesPerPixel;
+ System.err.println("PNGPixelRect: "+basename+", "+image+", glpa "+glpa);
+
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ if( hasAlpha ) {
+ caps.setAlphaBits(1);
+ }
+
+ final int internalFormat;
+ if(glp.isGL2ES3()) {
+ internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ } else {
+ internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB;
+ }
+ final TextureData texData = new TextureData(glp, internalFormat,
+ image.getSize().getWidth(),
+ image.getSize().getHeight(),
+ 0,
+ glpa,
+ false /* mipmap */,
+ false /* compressed */,
+ false /* must flip-vert */,
+ image.getPixels(),
+ null);
+
+ // final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.PNG);
+ System.err.println("TextureData: "+texData);
+
+ final GLWindow glad = GLWindow.create(caps);
+ glad.setTitle(this.getSimpleTestName("."));
+ // Size OpenGL to Video Surface
+ glad.setSize(texData.getWidth(), texData.getHeight());
+
+ // load texture from file inside current GL context to match the way
+ // the bug submitter was doing it
+ final TextureDraw01ES2Listener gle = new TextureDraw01ES2Listener( texData, 0 ) ;
+ // gle.setClearColor(new float[] { 1.0f, 0.0f, 0.0f, 1.0f } );
+
+ glad.addGLEventListener(gle);
+ glad.addGLEventListener(new GLEventListener() {
+ boolean shot = false;
+
+ @Override public void init(final GLAutoDrawable drawable) {
+ System.err.println("Chosen Caps: " + drawable.getChosenGLCapabilities());
+ System.err.println("GL ctx: " + drawable.getGL().getContext());
+ }
+
+ @Override public void display(final GLAutoDrawable drawable) {
+ // 1 snapshot
+ if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
+ shot = true;
+ snapshot(num, basename, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ }
+
+ @Override public void dispose(final GLAutoDrawable drawable) { }
+ @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ });
+
+ final Animator animator = new Animator(glad);
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glad.addKeyListener(quitAdapter);
+ glad.addWindowListener(quitAdapter);
+ glad.setVisible(true);
+ animator.start();
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+ glad.destroy();
+ }
+
+ @Test
+ public void testRead00_Manual() throws InterruptedException, IOException, MalformedURLException {
+ if( null == _fname ) {
+ return;
+ }
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), _fname);
+ if( null == urlConn ) {
+ throw new IOException("Cannot find "+_fname+".png");
+ }
+ testImpl(0, _fname, urlConn.getInputStream(), null);
+ }
+
+ @Test
+ public void testRead01_All() throws InterruptedException, IOException, MalformedURLException {
+ if( null != _fname ) {
+ return;
+ }
+ for(int i=0; i<PNGTstFiles.allBasenames.length; i++) {
+ final String basename = PNGTstFiles.allBasenames[i];
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), basename+".png");
+ if( null == urlConn ) {
+ throw new IOException("Cannot find "+basename+".png");
+ }
+ testImpl(i, basename, urlConn.getInputStream(), null);
+ }
+ }
+ @Test
+ public void testRead02_Gray2RGBA() throws InterruptedException, IOException, MalformedURLException {
+ if( null != _fname ) {
+ return;
+ }
+ for(int i=0; i<PNGTstFiles.greyBasenames.length; i++) {
+ final String basename = PNGTstFiles.greyBasenames[i];
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), basename+".png");
+ if( null == urlConn ) {
+ throw new IOException("Cannot find "+basename+".png");
+ }
+ testImpl(i, basename, urlConn.getInputStream(), PixelFormat.RGBA8888);
+ }
+ }
+
+ static String _fname = null;
+ public static void main(final String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-file")) {
+ i++;
+ _fname = args[i];
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestPNGPixelRect01NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java
index 7dbccd5e0..bbcd04454 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.util.texture;
@@ -51,7 +51,6 @@ import com.jogamp.opengl.util.GLReadBufferUtil;
import java.awt.Dimension;
import java.awt.Frame;
-
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
@@ -62,6 +61,8 @@ import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
/**
* Unit test for bug 417, which shows a GLException when reading a grayscale texture.
@@ -69,6 +70,7 @@ import org.junit.Test;
* after the bug was submitted.
* @author Wade Walker, et.al.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestPNGTextureFromFileAWT extends UITestCase {
static boolean showFPS = false;
static long duration = 100; // ms
@@ -83,10 +85,12 @@ public class TestPNGTextureFromFileAWT extends UITestCase {
public void initTest() throws IOException {
grayTextureStream = TestPNGTextureFromFileAWT.class.getResourceAsStream( "grayscale_texture.png" );
Assert.assertNotNull(grayTextureStream);
- URLConnection testTextureUrlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-160x90.png", this.getClass().getClassLoader());
- Assert.assertNotNull(testTextureUrlConn);
- testTextureStream = testTextureUrlConn.getInputStream();
- Assert.assertNotNull(testTextureStream);
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90.png");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream);
+ }
}
@After
@@ -95,13 +99,13 @@ public class TestPNGTextureFromFileAWT extends UITestCase {
testTextureStream = null;
}
- public void testImpl(boolean useFFP, final InputStream istream, final boolean useAWTIIOP)
- throws InterruptedException, IOException
+ public void testImpl(final boolean useFFP, final InputStream istream, final boolean useAWTIIOP)
+ throws InterruptedException, IOException
{
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
GLProfile glp;
- if(useFFP && GLProfile.isAvailable(GLProfile.GL2GL3)) {
- glp = GLProfile.getGL2GL3();
+ if(useFFP && GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.getMaxFixedFunc(true);
} else if(!useFFP && GLProfile.isAvailable(GLProfile.GL2ES2)) {
glp = GLProfile.getGL2ES2();
} else {
@@ -117,9 +121,9 @@ public class TestPNGTextureFromFileAWT extends UITestCase {
texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.PNG);
}
System.err.println("TextureData: "+texData);
-
+
final GLCanvas glc = new GLCanvas(caps);
- Dimension glc_sz = new Dimension(texData.getWidth(), texData.getHeight());
+ final Dimension glc_sz = new Dimension(texData.getWidth(), texData.getHeight());
glc.setMinimumSize(glc_sz);
glc.setPreferredSize(glc_sz);
final Frame frame = new Frame("TestPNGTextureGL2FromFileAWT");
@@ -128,15 +132,15 @@ public class TestPNGTextureFromFileAWT extends UITestCase {
// load texture from file inside current GL context to match the way
// the bug submitter was doing it
- final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData ) ;
+ final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ;
glc.addGLEventListener(gle);
- glc.addGLEventListener(new GLEventListener() {
+ glc.addGLEventListener(new GLEventListener() {
boolean shot = false;
-
- @Override public void init(GLAutoDrawable drawable) {}
-
+
+ @Override public void init(final GLAutoDrawable drawable) {}
+
@Override
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
// 1 snapshot
if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
shot = true;
@@ -144,31 +148,33 @@ public class TestPNGTextureFromFileAWT extends UITestCase {
}
}
- @Override public void dispose(GLAutoDrawable drawable) { }
- @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ @Override public void dispose(final GLAutoDrawable drawable) { }
+ @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
- Animator animator = new Animator(glc);
- animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
- QuitAdapter quitAdapter = new QuitAdapter();
- new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter).addTo(glc);
- new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter).addTo(glc);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter, glc).addTo(glc);
+ new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter, glc).addTo(glc);
+
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.pack();
frame.setVisible(true);
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
+
+ final Animator animator = new Animator(glc);
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
animator.start();
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
}
-
+
animator.stop();
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -177,55 +183,55 @@ public class TestPNGTextureFromFileAWT extends UITestCase {
frame.remove(glc);
frame.dispose();
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
}
-
+
@Test
public void testGrayAWTILoaderGL2() throws InterruptedException, IOException {
- testImpl(true, grayTextureStream, true);
- }
+ testImpl(true, grayTextureStream, true);
+ }
@Test
public void testGrayAWTILoaderES2() throws InterruptedException, IOException {
- testImpl(false, grayTextureStream, true);
+ testImpl(false, grayTextureStream, true);
}
-
+
@Test
public void testGrayPNGJLoaderGL2() throws InterruptedException, IOException {
- testImpl(true, grayTextureStream, false);
+ testImpl(true, grayTextureStream, false);
}
@Test
public void testGrayPNGJLoaderES2() throws InterruptedException, IOException {
- testImpl(false, grayTextureStream, false);
+ testImpl(false, grayTextureStream, false);
}
-
+
@Test
public void testTestAWTILoaderGL2() throws InterruptedException, IOException {
- testImpl(true, testTextureStream, true);
+ testImpl(true, testTextureStream, true);
}
@Test
public void testTestAWTILoaderES2() throws InterruptedException, IOException {
- testImpl(false, testTextureStream, true);
+ testImpl(false, testTextureStream, true);
}
-
+
@Test
public void testTestPNGJLoaderGL2() throws InterruptedException, IOException {
- testImpl(true, testTextureStream, false);
+ testImpl(true, testTextureStream, false);
}
@Test
public void testTestPNGJLoaderES2() throws InterruptedException, IOException {
- testImpl(false, testTextureStream, false);
+ testImpl(false, testTextureStream, false);
}
-
- public static void main(String args[]) throws IOException {
+
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
duration = MiscUtils.atol(args[i], duration);
}
}
- org.junit.runner.JUnitCore.main(TestPNGTextureFromFileAWT.class.getName());
+ org.junit.runner.JUnitCore.main(TestPNGTextureFromFileAWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java
index e9ef9b9b6..bbfc2907f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.util.texture;
@@ -56,34 +56,105 @@ import org.junit.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestPNGTextureFromFileNEWT extends UITestCase {
static boolean showFPS = false;
static long duration = 100; // ms
InputStream grayTextureStream;
- InputStream testTextureStream;
+
+ InputStream testTextureStreamN_3;
+ InputStream testTextureStreamN_4;
+ InputStream testTextureStreamNG4;
+
+ InputStream testTextureStreamI_3;
+ InputStream testTextureStreamIG3;
+ InputStream testTextureStreamI_4;
+ InputStream testTextureStreamIG4;
+
+ InputStream testTextureStreamP_3;
+ InputStream testTextureStreamP_4;
@Before
public void initTest() throws IOException {
grayTextureStream = TestPNGTextureFromFileNEWT.class.getResourceAsStream( "grayscale_texture.png" );
Assert.assertNotNull(grayTextureStream);
- URLConnection testTextureUrlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-160x90.png", this.getClass().getClassLoader());
- Assert.assertNotNull(testTextureUrlConn);
- testTextureStream = testTextureUrlConn.getInputStream();
- Assert.assertNotNull(testTextureStream);
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90.png");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStreamN_3 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStreamN_3);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_4-01-160x90.png");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStreamN_4 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStreamN_4);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscNG4-01-160x90.png");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStreamNG4 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStreamNG4);
+ }
+
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscI_3-01-160x90.png");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStreamI_3 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStreamI_3);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscIG3-01-160x90.png");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStreamIG3 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStreamIG3);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscI_4-01-160x90.png");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStreamI_4 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStreamI_4);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscIG4-01-160x90.png");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStreamIG4 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStreamIG4);
+ }
+
+
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscP_3-01-160x90.png");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStreamP_3 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStreamP_3);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscP_4-01-160x90.png");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStreamP_4 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStreamP_4);
+ }
}
@After
public void cleanupTest() {
grayTextureStream = null;
- testTextureStream = null;
+ testTextureStreamN_3 = null;
+ testTextureStreamI_3 = null;
+ testTextureStreamIG3 = null;
+ testTextureStreamP_3 = null;
+ testTextureStreamP_4 = null;
}
- public void testImpl(boolean useFFP, final InputStream istream) throws InterruptedException, IOException {
+ public void testImpl(final boolean useFFP, final InputStream istream) throws InterruptedException, IOException {
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
GLProfile glp;
- if(useFFP && GLProfile.isAvailable(GLProfile.GL2GL3)) {
- glp = GLProfile.getGL2GL3();
+ if(useFFP && GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.getMaxFixedFunc(true);
} else if(!useFFP && GLProfile.isAvailable(GLProfile.GL2ES2)) {
glp = GLProfile.getGL2ES2();
} else {
@@ -91,38 +162,40 @@ public class TestPNGTextureFromFileNEWT extends UITestCase {
return;
}
final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(1);
+
final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.PNG);
System.err.println("TextureData: "+texData);
-
+
final GLWindow glad = GLWindow.create(caps);
glad.setTitle("TestPNGTextureGL2FromFileNEWT");
// Size OpenGL to Video Surface
glad.setSize(texData.getWidth(), texData.getHeight());
-
+
// load texture from file inside current GL context to match the way
// the bug submitter was doing it
- final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData ) ;
+ final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ;
glad.addGLEventListener(gle);
- glad.addGLEventListener(new GLEventListener() {
+ glad.addGLEventListener(new GLEventListener() {
boolean shot = false;
-
- @Override public void init(GLAutoDrawable drawable) {}
-
- public void display(GLAutoDrawable drawable) {
+
+ @Override public void init(final GLAutoDrawable drawable) {}
+
+ public void display(final GLAutoDrawable drawable) {
// 1 snapshot
if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
shot = true;
snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
}
}
-
- @Override public void dispose(GLAutoDrawable drawable) { }
- @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+
+ @Override public void dispose(final GLAutoDrawable drawable) { }
+ @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
- Animator animator = new Animator(glad);
+ final Animator animator = new Animator(glad);
animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
- QuitAdapter quitAdapter = new QuitAdapter();
+ final QuitAdapter quitAdapter = new QuitAdapter();
glad.addKeyListener(quitAdapter);
glad.addWindowListener(quitAdapter);
glad.setVisible(true);
@@ -131,36 +204,74 @@ public class TestPNGTextureFromFileNEWT extends UITestCase {
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
}
-
+
animator.stop();
glad.destroy();
}
-
+
+ @Test
+ public void testGray__GL2() throws InterruptedException, IOException {
+ testImpl(true, grayTextureStream);
+ }
+ @Test
+ public void testGray__ES2() throws InterruptedException, IOException {
+ testImpl(false, grayTextureStream);
+ }
+
+ @Test
+ public void testRGB3__GL2() throws InterruptedException, IOException {
+ testImpl(true, testTextureStreamN_3);
+ }
+ @Test
+ public void testRGB3__ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStreamN_3);
+ }
+ @Test
+ public void testRGB4__GL2() throws InterruptedException, IOException {
+ testImpl(true, testTextureStreamN_4);
+ }
@Test
- public void testGrayPNGJLoaderGL2() throws InterruptedException, IOException {
- testImpl(true, grayTextureStream);
- }
+ public void testRGB4__ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStreamN_4);
+ }
+ @Test
+ public void testRGB4G_ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStreamNG4);
+ }
+
@Test
- public void testGrayPNGJLoaderES2() throws InterruptedException, IOException {
- testImpl(false, grayTextureStream);
+ public void testInterl3__ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStreamI_3);
}
-
@Test
- public void testTestPNGJLoaderGL2() throws InterruptedException, IOException {
- testImpl(true, testTextureStream);
- }
+ public void testInterl4__ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStreamI_4);
+ }
+ @Test
+ public void testInterl3G_ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStreamIG3);
+ }
@Test
- public void testTestPNGJLoaderES2() throws InterruptedException, IOException {
- testImpl(false, testTextureStream);
+ public void testInterl4G_ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStreamIG4);
}
-
- public static void main(String args[]) throws IOException {
+
+ @Test
+ public void testPalette3__ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStreamP_3);
+ }
+ @Test
+ public void testPalette4__ES2() throws InterruptedException, IOException {
+ testImpl(false, testTextureStreamP_4);
+ }
+
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
duration = MiscUtils.atol(args[i], duration);
}
}
- org.junit.runner.JUnitCore.main(TestPNGTextureFromFileNEWT.class.getName());
+ org.junit.runner.JUnitCore.main(TestPNGTextureFromFileNEWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java
new file mode 100644
index 000000000..1b549fa96
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java
@@ -0,0 +1,364 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelFormatUtil;
+import javax.media.nativewindow.util.PixelRectangle;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Testing PixelFormatUtil's Conversion using synthetic test data
+ * including strides, endian-order and all PixelFormat conversions.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPixelFormatUtil00NEWT extends UITestCase {
+ @Test
+ public void testConversion01_srcS000_BE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException {
+ testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testConversion02_srcS000_LE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException {
+ testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.LITTLE_ENDIAN, false /* srcIsGLOriented */,
+ 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testConversion03_srcS000_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
+ testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testConversion04_srcS259_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
+ testPNG00Impl(259 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testConversion05_srcS301_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
+ testPNG00Impl(301 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ static final byte red___val = (byte)0x01;
+ static final byte green_val = (byte)0x02;
+ static final byte blue__val = (byte)0x03;
+ static final byte alpha_val = (byte)0x04;
+ static final byte undef_val = (byte)0xff;
+
+ static final void getComponents(final int srcComps, final PixelFormat fmt, final byte[] components) {
+ final byte b1, b2, b3, b4;
+ if( 1 == srcComps ) {
+ // LUM -> Fmt Conversion
+ switch(fmt) {
+ case LUMINANCE:
+ b1 = red___val;
+ b2 = undef_val;
+ b3 = undef_val;
+ b4 = undef_val;
+ break;
+ case RGB888:
+ b1 = red___val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = undef_val;
+ break;
+ case BGR888:
+ b1 = red___val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = undef_val;
+ break;
+ case RGBA8888:
+ b1 = red___val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = undef_val;
+ break;
+ case ABGR8888:
+ b1 = undef_val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = red___val;
+ break;
+ case BGRA8888:
+ b1 = red___val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = undef_val;
+ break;
+ case ARGB8888:
+ b1 = undef_val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = red___val;
+ break;
+ default:
+ throw new InternalError("Unhandled format "+fmt);
+ }
+ } else {
+ // 1:1 values
+ switch(fmt) {
+ case LUMINANCE:
+ if( srcComps > 1 ) {
+ b1 = ( red___val + green_val+ blue__val ) / 3;
+ b2 = undef_val;
+ b3 = undef_val;
+ b4 = undef_val;
+ } else {
+ b1 = red___val;
+ b2 = undef_val;
+ b3 = undef_val;
+ b4 = undef_val;
+ }
+ break;
+ case RGB888:
+ b1 = red___val;
+ b2 = green_val;
+ b3 = blue__val;
+ b4 = undef_val;
+ break;
+ case BGR888:
+ b1 = blue__val;
+ b2 = green_val;
+ b3 = red___val;
+ b4 = undef_val;
+ break;
+ case RGBA8888:
+ b1 = red___val;
+ b2 = green_val;
+ b3 = blue__val;
+ b4 = srcComps > 3 ? alpha_val : undef_val;
+ break;
+ case ABGR8888:
+ b1 = srcComps > 3 ? alpha_val : undef_val;
+ b2 = blue__val;
+ b3 = green_val;
+ b4 = red___val;
+ break;
+ case BGRA8888:
+ b1 = blue__val;
+ b2 = green_val;
+ b3 = red___val;
+ b4 = srcComps > 3 ? alpha_val : undef_val;
+ break;
+ case ARGB8888:
+ b1 = srcComps > 3 ? alpha_val : undef_val;
+ b2 = red___val;
+ b3 = green_val;
+ b4 = blue__val;
+ break;
+ default:
+ throw new InternalError("Unhandled format "+fmt);
+ }
+ }
+ components[0] = b1;
+ components[1] = b2;
+ components[2] = b3;
+ components[3] = b4;
+ }
+ private void testPNG00Impl(final int srcMinStrideInBytes, final ByteOrder srcByteOrder, final boolean srcIsGLOriented,
+ final int destMinStrideInBytes, final boolean destIsGLOriented)
+ throws InterruptedException, IOException, MalformedURLException
+ {
+ System.err.println("Test00: srcMinStrideInBytes "+srcMinStrideInBytes+", srcByteOrder "+srcByteOrder+", srcIsGLOriented "+srcIsGLOriented+
+ ", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented);
+
+ final PixelFormat[] formats = PixelFormat.values();
+ final int width = 64, height = 64;
+
+ for(int i=0; i<formats.length; i++) {
+ final PixelFormat srcFmt = formats[i];
+ final int srcBpp = srcFmt.bytesPerPixel();
+ final int srcStrideBytes = Math.max(srcMinStrideInBytes, width*srcBpp);
+ final ByteBuffer srcPixels = ByteBuffer.allocate(height*srcStrideBytes).order(srcByteOrder);
+ final byte[] srcComponents = new byte[4];
+ getComponents(srcFmt.componentCount, srcFmt, srcComponents);
+ for(int y=0; y<height; y++) {
+ int o = y*srcStrideBytes;
+ for(int x=0; x<width; x++) {
+ switch(srcFmt) {
+ case LUMINANCE:
+ srcPixels.put(o++, srcComponents[0]);
+ break;
+ case RGB888:
+ case BGR888:
+ srcPixels.put(o++, srcComponents[0]);
+ srcPixels.put(o++, srcComponents[1]);
+ srcPixels.put(o++, srcComponents[2]);
+ break;
+ case RGBA8888:
+ case ABGR8888:
+ case BGRA8888:
+ case ARGB8888:
+ srcPixels.put(o++, srcComponents[0]);
+ srcPixels.put(o++, srcComponents[1]);
+ srcPixels.put(o++, srcComponents[2]);
+ srcPixels.put(o++, srcComponents[3]);
+ break;
+ default:
+ throw new InternalError("Unhandled format "+srcFmt);
+ }
+ }
+ }
+ final PixelRectangle imageSrc = new PixelRectangle.GenericPixelRect(srcFmt, new Dimension(width, height), srcStrideBytes, srcIsGLOriented, srcPixels);
+ System.err.println("CONVERT["+i+"][*]: Image0 - Orig: "+imageSrc);
+ testComponents(imageSrc, 0, 0, srcComponents);
+ testComponents(imageSrc, width-1, height-1, srcComponents);
+
+ for(int j=0; j<formats.length; j++) {
+ final PixelFormat destFmt = formats[j];
+ System.err.println("CONVERT["+i+"]["+j+"]: "+srcFmt+" -> "+destFmt);
+
+ final int destStrideBytes = Math.max(destMinStrideInBytes, width*destFmt.bytesPerPixel());
+ final byte[] destComponents = new byte[4];
+ getComponents(srcFmt.componentCount, destFmt, destComponents);
+ final PixelRectangle imageConv1 = PixelFormatUtil.convert32(imageSrc, destFmt, destStrideBytes, destIsGLOriented, false /* nio */);
+ System.err.println("CONVERT["+i+"]["+j+"]: Conv1: "+imageConv1);
+ testComponents(imageConv1, 0, 0, destComponents);
+ testComponents(imageConv1, width-1, height-1, destComponents);
+ if( PixelFormat.LUMINANCE != srcFmt && PixelFormat.LUMINANCE == destFmt ) {
+ // Cannot convert: RGB* -> LUM -> RGB*
+ System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to RGB* -> LUM");
+ } else if( srcFmt.componentCount > destFmt.componentCount ) {
+ // Cannot convert back if: src.componentCount > dest.componentCount
+ System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to src.componentCount > dest.componentCount");
+ } else {
+ final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, imageSrc.getPixelformat(), imageSrc.getStride(), imageSrc.isGLOriented(), false /* nio */);
+ System.err.println("CONVERT["+i+"]["+j+"]: Conv2: "+imageConv2);
+ testComponents(imageConv2, 0, 0, srcComponents);
+ testComponents(imageConv2, width-1, height-1, srcComponents);
+ if( imageSrc.getStride() == imageConv1.getStride() ) {
+ Assert.assertEquals(imageSrc.getPixels(), imageConv2.getPixels());
+ }
+ }
+ }
+ }
+ }
+ private void dumpComponents(final PixelRectangle image, int x1, int y1, final int w, final int h) {
+ if( x1 + w >= image.getSize().getWidth() ) {
+ x1 = image.getSize().getWidth() - w;
+ }
+ if( y1 + h >= image.getSize().getHeight() ) {
+ y1 = image.getSize().getHeight() - h;
+ }
+ System.err.print("PixelsBytes "+x1+"/"+y1+" "+w+"x"+h+":");
+ final ByteBuffer bb = image.getPixels();
+ final int bpp = image.getPixelformat().bytesPerPixel();
+ for(int y = y1; y< y1+h; y++) {
+ System.err.printf("%n[%3d][%3d] ", x1, y);
+ int o = y * image.getStride()+x1*bpp;
+ for(int x = x1; x< x1+w; x++) {
+ switch(bpp) {
+ case 1: {
+ final byte a = bb.get(o++);
+ System.err.printf(" 0x%02X", a);
+ }
+ break;
+ case 2: {
+ final byte a = bb.get(o++), b = bb.get(o++);
+ System.err.printf(" 0x%02X%02X", b, a);
+ }
+ break;
+ case 3: {
+ final byte a = bb.get(o++), b = bb.get(o++), c = bb.get(o++);
+ System.err.printf(" 0x%02X%02X%02X", c, b, a);
+ }
+ break;
+ case 4: {
+ final byte a = bb.get(o++), b = bb.get(o++), c = bb.get(o++), d = bb.get(o++);
+ System.err.printf(" 0x%02X%02X%02X%02X", d, c, b, a);
+ }
+ break;
+ }
+ }
+ }
+ System.err.println();
+ }
+ private void testComponents(final PixelRectangle image, final int x, final int y, final byte[] components) {
+ dumpComponents(image, x, y, 3, 3);
+ final ByteBuffer bb = image.getPixels();
+ final int bpp = image.getPixelformat().bytesPerPixel();
+ int o = y * image.getStride()+x*bpp;
+ switch(bpp) {
+ case 1: {
+ final byte c1 = bb.get(o++);
+ final boolean equal = c1==components[0];
+ System.err.printf("Test [%3d][%3d] exp 0x%02X == has 0x%02X : %b%n",
+ x, y, components[0], c1, equal );
+ Assert.assertEquals(components[0], c1);
+ }
+ break;
+ case 2: {
+ final byte c1 = bb.get(o++), c2 = bb.get(o++);
+ final boolean equal = c1==components[0] && c2==components[1];
+ System.err.printf("Test [%3d][%3d] exp 0x%02X%02X == has 0x%02X%02X : %b%n",
+ x, y, components[1], components[0], c2, c1, equal );
+ Assert.assertEquals(components[0], c1);
+ Assert.assertEquals(components[1], c2);
+ }
+ break;
+ case 3: {
+ final byte c1 = bb.get(o++), c2 = bb.get(o++), c3 = bb.get(o++);
+ final boolean equal = c1==components[0] && c2==components[1] && c3==components[2];
+ System.err.printf("Test [%3d][%3d] exp 0x%02X%02X%02X == has 0x%02X%02X%02X : %b%n",
+ x, y, components[2], components[1], components[0], c3, c2, c1, equal );
+ Assert.assertEquals(components[0], c1);
+ Assert.assertEquals(components[1], c2);
+ Assert.assertEquals(components[2], c3);
+ }
+ break;
+ case 4: {
+ final byte c1 = bb.get(o++), c2 = bb.get(o++), c3 = bb.get(o++), c4 = bb.get(o++);
+ final boolean equal = c1==components[0] && c2==components[1] && c3==components[2] && c4==components[3];
+ System.err.printf("Test [%3d][%3d] exp 0x%02X%02X%02X%02X == has 0x%02X%02X%02X%02X : %b%n",
+ x, y, components[3], components[2], components[1], components[0], c4, c3, c2, c1, equal );
+ Assert.assertEquals(components[0], c1);
+ Assert.assertEquals(components[1], c2);
+ Assert.assertEquals(components[2], c3);
+ Assert.assertEquals(components[3], c4);
+ }
+ break;
+ }
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestPixelFormatUtil00NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java
new file mode 100644
index 000000000..eba920032
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelFormatUtil;
+import javax.media.nativewindow.util.PixelRectangle;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.PNGPixelRect;
+
+/**
+ * Testing PixelFormatUtil's Conversion using PNG test data
+ * including strides, endian-order and PixelFormat conversions:
+ * { PixelFormat.RGBA8888, PixelFormat.ABGR8888, PixelFormat.BGRA8888, PixelFormat.ARGB8888 }
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPixelFormatUtil01NEWT extends UITestCase {
+ @Test
+ public void testPNGRead11_fromRGBA8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testPNGRead12_fromABGR8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.ABGR8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testPNGRead13_fromBGRA8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.BGRA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testPNGRead14_fromARGB8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.ARGB8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ private void testPNG01Impl(final String pathname, final String basename, final PixelFormat srcFmt,
+ final int destMinStrideInBytes, final boolean destIsGLOriented)
+ throws InterruptedException, IOException, MalformedURLException
+ {
+ System.err.println("Test01: "+pathname+basename+".png, srcFmt "+srcFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented);
+
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png");
+
+ final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), srcFmt, false /* directBuffer */, destMinStrideInBytes, false /* isGLOriented */);
+ System.err.println("PNGPixelRect - Orig: "+image1);
+
+ final PixelFormat[] formats = new PixelFormat[] { PixelFormat.RGBA8888, PixelFormat.ABGR8888, PixelFormat.BGRA8888, PixelFormat.ARGB8888 };
+ for(int i=0; i<formats.length; i++) {
+ final PixelFormat destFmt = formats[i];
+ System.err.println("CONVERT["+i+"]: "+srcFmt+" -> "+destFmt);
+ final PixelRectangle imageConv1 = PixelFormatUtil.convert32(image1, destFmt, destMinStrideInBytes, destIsGLOriented, false /* nio */);
+ System.err.println("PNGPixelRect - Conv1: "+imageConv1);
+ final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, image1.getPixelformat(), image1.getStride(), image1.isGLOriented(), false /* nio */);
+ System.err.println("PNGPixelRect - Conv2: "+imageConv2);
+ Assert.assertEquals(image1.getPixels(), imageConv2.getPixels());
+ }
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestPixelFormatUtil01NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java
new file mode 100644
index 000000000..ed8339b68
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java
@@ -0,0 +1,181 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLConnection;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTGATextureFromFileNEWT extends UITestCase {
+ static boolean showFPS = false;
+ static long duration = 100; // ms
+
+ InputStream testTextureStream01U32;
+ InputStream testTextureStream02RLE32;
+ InputStream testTextureStream03RLE32;
+
+ @Before
+ public void initTest() throws IOException {
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-u32.tga");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream01U32 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream01U32);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "bug744-rle32.tga");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream02RLE32 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream02RLE32);
+ }
+ {
+ final URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "bug982.rle32.256x256.tga");
+ Assert.assertNotNull(testTextureUrlConn);
+ testTextureStream03RLE32 = testTextureUrlConn.getInputStream();
+ Assert.assertNotNull(testTextureStream03RLE32);
+ }
+ }
+
+ public void testImpl(final boolean useFFP, final InputStream istream) throws InterruptedException, IOException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+ GLProfile glp;
+ if(useFFP && GLProfile.isAvailable(GLProfile.GL2)) {
+ glp = GLProfile.getMaxFixedFunc(true);
+ } else if(!useFFP && GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ glp = GLProfile.getGL2ES2();
+ } else {
+ System.err.println(getSimpleTestName(".")+": GLProfile n/a, useFFP: "+useFFP);
+ return;
+ }
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(1);
+
+ final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.TGA);
+ System.err.println("TextureData: "+texData);
+
+ final GLWindow glad = GLWindow.create(caps);
+ glad.setTitle("TestTGATextureGL2FromFileNEWT");
+ // Size OpenGL to Video Surface
+ glad.setSize(texData.getWidth(), texData.getHeight());
+
+ // load texture from file inside current GL context to match the way
+ // the bug submitter was doing it
+ final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ;
+ glad.addGLEventListener(gle);
+ glad.addGLEventListener(new GLEventListener() {
+ boolean shot = false;
+
+ @Override public void init(final GLAutoDrawable drawable) {}
+
+ public void display(final GLAutoDrawable drawable) {
+ // 1 snapshot
+ if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
+ shot = true;
+ snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ }
+
+ @Override public void dispose(final GLAutoDrawable drawable) { }
+ @Override public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ });
+
+ final Animator animator = new Animator(glad);
+ animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glad.addKeyListener(quitAdapter);
+ glad.addWindowListener(quitAdapter);
+ glad.setVisible(true);
+ animator.start();
+
+ while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+ glad.destroy();
+ }
+
+ @Test
+ public void test01U32__GL2() throws InterruptedException, IOException {
+ testImpl(true, testTextureStream01U32);
+ }
+
+ @Test
+ public void test02RLE32__GL2() throws InterruptedException, IOException {
+ testImpl(true, testTextureStream02RLE32);
+ }
+
+ @Test
+ public void test03RLE32__GL2() throws InterruptedException, IOException {
+ testImpl(true, testTextureStream03RLE32);
+ }
+
+ @After
+ public void cleanupTest() {
+ testTextureStream01U32 = null;
+ testTextureStream02RLE32 = null;
+ testTextureStream03RLE32 = null;
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestTGATextureFromFileNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
index 2d7b3b080..5a51473b4 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,26 +20,34 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.jogl.util.texture;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.awt.GLCanvas;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.awt.AWTTextureIO;
-import com.jogamp.opengl.util.Animator;
import java.awt.AlphaComposite;
+import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GradientPaint;
@@ -53,8 +61,18 @@ import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+/**
+ * Demonstrates TextureData w/ AWT usage in both directions,
+ * i.e. generating a texture based on an AWT BufferedImage data
+ * as well as reading out GL framebuffer and displaying it
+ * as an BufferedImage.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTexture01AWT extends UITestCase {
+ static long durationPerTest = 500;
static GLProfile glp;
static GLCapabilities caps;
BufferedImage textureImage;
@@ -65,7 +83,7 @@ public class TestTexture01AWT extends UITestCase {
UITestCase.setTestSupported(false);
return;
}
- glp = GLProfile.getGL2GL3();
+ glp = GLProfile.getMaxFixedFunc(true);
Assert.assertNotNull(glp);
caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
@@ -84,7 +102,7 @@ public class TestTexture01AWT extends UITestCase {
g.dispose();
// create texture image
- int imageType = BufferedImage.TYPE_3BYTE_BGR;
+ final int imageType = BufferedImage.TYPE_3BYTE_BGR;
textureImage = new BufferedImage(baseImage.getWidth(),
baseImage.getHeight(),
imageType);
@@ -107,38 +125,88 @@ public class TestTexture01AWT extends UITestCase {
@Test
public void test1() throws InterruptedException {
+ final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false);
+ final Frame frame0 = new Frame("GL -> AWT");
+ final Canvas canvas = new Canvas();
+ frame0.add(canvas);
+
final GLCanvas glCanvas = new GLCanvas(caps);
- final Frame frame = new Frame("Texture Test");
- Assert.assertNotNull(frame);
- frame.add(glCanvas);
- frame.setSize(512, 512);
+ final Frame frame1 = new Frame("AWT -> Texture");
+ Assert.assertNotNull(frame1);
+ frame1.add(glCanvas);
- // create texture
- TextureData textureData = AWTTextureIO.newTextureData(caps.getGLProfile(), textureImage, false);
+ // create texture
+ final TextureData textureData = AWTTextureIO.newTextureData(caps.getGLProfile(), textureImage, false);
glCanvas.addGLEventListener(new TextureDraw01GL2Listener(textureData));
+ glCanvas.addGLEventListener(new GLEventListener() {
+
+ @Override
+ public void init(final GLAutoDrawable drawable) { }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) { }
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final BufferedImage outputImage = awtGLReadBufferUtil.readPixelsToBufferedImage(drawable.getGL(), true /* awtOrientation */);
+ final ImageIcon imageIcon = new ImageIcon(outputImage);
+ final JLabel imageLabel = new JLabel(imageIcon);
+ try {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ frame0.removeAll();
+ frame0.add(imageLabel);
+ frame0.validate();
+ }});
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ frame0.setSize(frame1.getWidth(), frame1.getHeight());
+ frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY());
+ frame0.validate();
+ }
+ });
- Animator animator = new Animator(glCanvas);
- frame.setVisible(true);
- animator.start();
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setSize(256, 256);
+ frame1.setLocation(0, 0);
+ frame1.setVisible(true);
+ frame0.setSize(frame1.getWidth(), frame1.getHeight());
+ frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY());
+ frame0.setVisible(true);
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
- Thread.sleep(500); // 500 ms
+ Thread.sleep(durationPerTest);
- animator.stop();
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- frame.setVisible(false);
- frame.remove(glCanvas);
- frame.dispose();
+ frame0.setVisible(false);
+ frame0.dispose();
+ frame1.setVisible(false);
+ frame1.dispose();
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
}
- public static void main(String args[]) throws IOException {
- String tstname = TestTexture01AWT.class.getName();
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+ }
+ }
+ final String tstname = TestTexture01AWT.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java
new file mode 100644
index 000000000..c54b9b3e7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java
@@ -0,0 +1,168 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+
+import com.jogamp.opengl.util.FPSAnimator;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+
+import java.awt.Frame;
+import java.awt.image.BufferedImage;
+
+import java.io.IOException;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Demonstrates TextureData w/ AWT usage,
+ * i.e. reading out an animated GL framebuffer and displaying it
+ * as an BufferedImage.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTexture02AWT extends UITestCase {
+ static long durationPerTest = 500;
+ static GLProfile glp;
+ static GLCapabilities caps;
+
+ @BeforeClass
+ public static void initClass() {
+ if(!GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ UITestCase.setTestSupported(false);
+ return;
+ }
+ glp = GLProfile.getGL2ES2();
+ Assert.assertNotNull(glp);
+ caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ }
+
+ @Test
+ public void test1() throws InterruptedException {
+ final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false);
+ final Frame frame0 = new Frame("GL -> AWT");
+ final ImageIcon imageIcon = new ImageIcon();
+ final JLabel imageLabel = new JLabel(imageIcon);
+ frame0.add(imageLabel);
+
+ final GLCanvas glCanvas = new GLCanvas(caps);
+ final Frame frame1 = new Frame("GearsES2");
+ Assert.assertNotNull(frame1);
+ frame1.add(glCanvas);
+
+ glCanvas.addGLEventListener(new GearsES2(1));
+ glCanvas.addGLEventListener(new GLEventListener() {
+ @Override
+ public void init(final GLAutoDrawable drawable) { }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) { }
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final BufferedImage outputImage = awtGLReadBufferUtil.readPixelsToBufferedImage(drawable.getGL(), true /* awtOrientation */);
+ imageIcon.setImage(outputImage);
+ imageLabel.repaint();
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ frame0.setSize(frame1.getWidth(), frame1.getHeight());
+ frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY());
+ frame0.validate();
+ }
+ });
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setSize(256, 256);
+ frame1.setLocation(0, 0);
+ frame1.setVisible(true);
+ frame0.setSize(frame1.getWidth(), frame1.getHeight());
+ frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY());
+ frame0.setVisible(true);
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ final FPSAnimator animator = new FPSAnimator(glCanvas, 15); // 15fps
+ animator.start();
+
+ Thread.sleep(durationPerTest);
+
+ animator.stop();
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame0.setVisible(false);
+ frame0.dispose();
+ frame1.setVisible(false);
+ frame1.dispose();
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+ }
+ }
+ final String tstname = TestTexture02AWT.class.getName();
+ org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
+ tstname,
+ "filtertrace=true",
+ "haltOnError=false",
+ "haltOnFailure=false",
+ "showoutput=true",
+ "outputtoformatters=true",
+ "logfailedtests=true",
+ "logtestlistenerevents=true",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java
index 36dad45e6..5a294eee9 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java
@@ -1,6 +1,7 @@
package com.jogamp.opengl.test.junit.jogl.util.texture;
import java.awt.Frame;
+import java.io.IOException;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -12,14 +13,18 @@ import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
-import com.jogamp.opengl.test.junit.jogl.demos.TextureSequenceDemo01;
import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureSequenceCubeES2;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.texture.ImageSequence;
+import com.jogamp.opengl.util.texture.TextureIO;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTextureSequence01AWT extends UITestCase {
static boolean showFPS = false;
static int width = 510;
@@ -28,7 +33,7 @@ public class TestTextureSequence01AWT extends UITestCase {
static long duration = 500; // ms
static GLProfile glp;
static GLCapabilities caps;
-
+
@BeforeClass
public static void initClass() {
glp = GLProfile.getGL2ES2();
@@ -42,34 +47,49 @@ public class TestTextureSequence01AWT extends UITestCase {
final Frame frame = new Frame("TestTextureSequence01AWT");
Assert.assertNotNull(frame);
frame.add(glc);
- frame.setSize(width, height);
-
- final TextureSequenceDemo01 texSource = new TextureSequenceDemo01(useBuildInTexLookup);
+
+ final ImageSequence texSource = new ImageSequence(0, useBuildInTexLookup);
glc.addGLEventListener(new GLEventListener() {
@Override
- public void init(GLAutoDrawable drawable) {
- texSource.initGLResources(drawable.getGL());
+ public void init(final GLAutoDrawable drawable) {
+ try {
+ texSource.addFrame(drawable.getGL(), TestTextureSequence01AWT.class, "test-ntscP_3-01-160x90.png", TextureIO.PNG);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
}
@Override
- public void dispose(GLAutoDrawable drawable) { }
+ public void dispose(final GLAutoDrawable drawable) { }
@Override
- public void display(GLAutoDrawable drawable) { }
+ public void display(final GLAutoDrawable drawable) { }
@Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
glc.addGLEventListener(new TextureSequenceCubeES2(texSource, false, -2.3f, 0f, 0f));
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter, glc).addTo(glc);
+ new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter, glc).addTo(glc);
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setSize(width, height);
+ frame.setVisible(true);
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+
final Animator animator = new Animator(glc);
animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
- QuitAdapter quitAdapter = new QuitAdapter();
- new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter).addTo(glc);
- new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter).addTo(glc);
- frame.setVisible(true);
animator.start();
-
+
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
}
-
+
animator.stop();
Assert.assertFalse(animator.isAnimating());
Assert.assertFalse(animator.isStarted());
@@ -80,18 +100,18 @@ public class TestTextureSequence01AWT extends UITestCase {
frame.remove(glc);
frame.dispose();
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
}
-
+
@Test
public void test1() throws InterruptedException {
- testImpl();
+ testImpl();
}
-
- public static void main(String[] args) {
+
+ public static void main(final String[] args) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
@@ -106,7 +126,7 @@ public class TestTextureSequence01AWT extends UITestCase {
useBuildInTexLookup = true;
}
}
- org.junit.runner.JUnitCore.main(TestTextureSequence01AWT.class.getName());
+ org.junit.runner.JUnitCore.main(TestTextureSequence01AWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01NEWT.java
index ae4d2c377..47b594e9d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01NEWT.java
@@ -1,5 +1,7 @@
package com.jogamp.opengl.test.junit.jogl.util.texture;
+import java.io.IOException;
+
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
@@ -8,15 +10,19 @@ import javax.media.opengl.GLProfile;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.opengl.test.junit.jogl.demos.TextureSequenceDemo01;
import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureSequenceCubeES2;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.texture.ImageSequence;
+import com.jogamp.opengl.util.texture.TextureIO;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTextureSequence01NEWT extends UITestCase {
static boolean showFPS = false;
static int width = 510;
@@ -25,7 +31,7 @@ public class TestTextureSequence01NEWT extends UITestCase {
static long duration = 500; // ms
static GLProfile glp;
static GLCapabilities caps;
-
+
@BeforeClass
public static void initClass() {
glp = GLProfile.getGL2ES2();
@@ -39,44 +45,48 @@ public class TestTextureSequence01NEWT extends UITestCase {
window.setTitle("TestTextureSequence01NEWT");
// Size OpenGL to Video Surface
window.setSize(width, height);
- final TextureSequenceDemo01 texSource = new TextureSequenceDemo01(useBuildInTexLookup);
+ final ImageSequence texSource = new ImageSequence(0, useBuildInTexLookup);
window.addGLEventListener(new GLEventListener() {
@Override
- public void init(GLAutoDrawable drawable) {
- texSource.initGLResources(drawable.getGL());
+ public void init(final GLAutoDrawable drawable) {
+ try {
+ texSource.addFrame(drawable.getGL(), TestTextureSequence01NEWT.class, "test-ntscP_3-01-160x90.png", TextureIO.PNG);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
}
@Override
- public void dispose(GLAutoDrawable drawable) { }
+ public void dispose(final GLAutoDrawable drawable) { }
@Override
- public void display(GLAutoDrawable drawable) { }
+ public void display(final GLAutoDrawable drawable) { }
@Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
});
window.addGLEventListener(new TextureSequenceCubeES2(texSource, false, -2.3f, 0f, 0f));
final Animator animator = new Animator(window);
animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
- QuitAdapter quitAdapter = new QuitAdapter();
+ final QuitAdapter quitAdapter = new QuitAdapter();
window.addKeyListener(quitAdapter);
window.addWindowListener(quitAdapter);
animator.start();
window.setVisible(true);
-
+
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
}
-
+
animator.stop();
Assert.assertFalse(animator.isAnimating());
Assert.assertFalse(animator.isStarted());
window.destroy();
}
-
+
@Test
public void test1() throws InterruptedException {
- testImpl();
+ testImpl();
}
-
- public static void main(String[] args) {
+
+ public static void main(final String[] args) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
@@ -91,7 +101,7 @@ public class TestTextureSequence01NEWT extends UITestCase {
useBuildInTexLookup = true;
}
}
- org.junit.runner.JUnitCore.main(TestTextureSequence01NEWT.class.getName());
+ org.junit.runner.JUnitCore.main(TestTextureSequence01NEWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_gimpexp.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_gimpexp.png
new file mode 100644
index 000000000..53b2ec07b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_gimpexp.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_orig.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_orig.png
new file mode 100644
index 000000000..b85bf7e15
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_orig.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug744-rle32.tga b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug744-rle32.tga
new file mode 100644
index 000000000..18220ed40
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug744-rle32.tga
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug745_qttdef_post_frame.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug745_qttdef_post_frame.jpg
new file mode 100644
index 000000000..1c7009321
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug745_qttdef_post_frame.jpg
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug982.rle32.256x256.tga b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug982.rle32.256x256.tga
new file mode 100644
index 000000000..d4affa19d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug982.rle32.256x256.tga
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/cross-grey-alpha-16x16.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/cross-grey-alpha-16x16.png
new file mode 100644
index 000000000..303c454fa
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/cross-grey-alpha-16x16.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/grayscale_texture.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/grayscale_texture.png
index dac0f13de..dac0f13de 100755..100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/grayscale_texture.png
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/grayscale_texture.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j1-baseline.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j1-baseline.jpg
new file mode 100644
index 000000000..8efe6af1f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j1-baseline.jpg
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j2-progressive.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j2-progressive.jpg
new file mode 100644
index 000000000..aa5fbd0d9
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j2-progressive.jpg
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j3-baseline_gray.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j3-baseline_gray.jpg
new file mode 100644
index 000000000..048eb791b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j3-baseline_gray.jpg
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/pointer-grey-alpha-16x24.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/pointer-grey-alpha-16x24.png
new file mode 100644
index 000000000..98b2c8640
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/pointer-grey-alpha-16x24.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT1.dds b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT1.dds
new file mode 100644
index 000000000..81ae64e33
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT1.dds
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT5.dds b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT5.dds
new file mode 100644
index 000000000..5b9e364e0
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT5.dds
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_uncompressed.dds b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_uncompressed.dds
new file mode 100644
index 000000000..034d2516c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_uncompressed.dds
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-cmyk-01.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-cmyk-01.jpg
new file mode 100644
index 000000000..40a300f2d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-cmyk-01.jpg
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG3-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG3-01-160x90.png
new file mode 100644
index 000000000..b90a90988
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG3-01-160x90.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG4-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG4-01-160x90.png
new file mode 100644
index 000000000..db0ae01fa
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG4-01-160x90.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_3-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_3-01-160x90.png
new file mode 100644
index 000000000..e579c58c6
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_3-01-160x90.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_4-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_4-01-160x90.png
new file mode 100644
index 000000000..e42d22be6
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_4-01-160x90.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscNG4-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscNG4-01-160x90.png
new file mode 100644
index 000000000..762ba3e57
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscNG4-01-160x90.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg
new file mode 100644
index 000000000..8e4fe9a09
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg
new file mode 100644
index 000000000..35556f90b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpg
new file mode 100644
index 000000000..051a166cd
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpg
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg
new file mode 100644
index 000000000..40b0fc8c2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90.png
new file mode 100644
index 000000000..3df47432e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_4-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_4-01-160x90.png
new file mode 100644
index 000000000..c233c34da
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_4-01-160x90.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_3-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_3-01-160x90.png
new file mode 100644
index 000000000..32e7f0042
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_3-01-160x90.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_4-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_4-01-160x90.png
new file mode 100644
index 000000000..55405ee89
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_4-01-160x90.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-u32.tga b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-u32.tga
new file mode 100644
index 000000000..9066e17f7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-u32.tga
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ycck-01.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ycck-01.jpg
new file mode 100644
index 000000000..84c1984f9
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ycck-01.jpg
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java
new file mode 100644
index 000000000..9ab81ef82
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java
@@ -0,0 +1,140 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.newt;
+
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Manual test case validating closing behavior.
+ * <p>
+ * Validates bugs:
+ * <ul>
+ * <li>Bug 882: Crash on OSX when closing NEWT window</li>
+ * </ul>
+ * </p>
+ *
+ */
+public class DemoCreateAndDisposeOnCloseNEWT {
+ public static void main(final String[] args) {
+ int closeMode = 0; // 0 - none, 1 - window, animator, 2 - animator, window, 3 - System.exit
+
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-close")) {
+ closeMode = MiscUtils.atoi(args[++i], closeMode);
+ }
+ }
+ System.err.println("Close Mode: "+closeMode);
+
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxProgrammable(true));
+ caps.setBackgroundOpaque(true);
+ caps.setDoubleBuffered(true);
+ caps.setDepthBits(16);
+ final Animator animator = new Animator();
+ final GLWindow glWindow = GLWindow.create(caps);
+ animator.add(glWindow);
+ glWindow.addGLEventListener(new GLEventListener() {
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ System.out.println("GLEventListener.reshape");
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ System.out.println("GLEventListener.init");
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ System.out.println("GLEventListener.dispose");
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ }
+ });
+ glWindow.setTitle("Test");
+ glWindow.setSize(1024, 768);
+ glWindow.setUndecorated(false);
+ glWindow.setPointerVisible(true);
+ glWindow.setVisible(true);
+ glWindow.setFullscreen(false);
+ glWindow.setDefaultCloseOperation(WindowClosingProtocol.WindowClosingMode.DISPOSE_ON_CLOSE);
+ glWindow.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowDestroyNotify(final WindowEvent e) {
+ System.out.println("GLWindow.destroyNotify");
+ }
+
+ @Override
+ public void windowDestroyed(final WindowEvent e) {
+ System.out.println("GLWindow.destroyed");
+ animator.stop();
+ }
+ });
+
+ animator.start();
+
+ switch( closeMode ) {
+ case 1:
+ sleep1s();
+ glWindow.destroy();
+ sleep1s();
+ animator.stop();
+ break;
+ case 2:
+ sleep1s();
+ animator.stop();
+ sleep1s();
+ glWindow.destroy();
+ break;
+ case 3:
+ sleep1s();
+ System.exit(0);
+ break;
+ default: break; // 0 - nop
+ }
+ }
+ static void sleep1s() {
+ try {
+ Thread.sleep(1000);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java
index 4ebb7dddd..f9216f082 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -29,12 +29,15 @@
package com.jogamp.opengl.test.junit.newt;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import org.junit.Assert;
import java.lang.reflect.InvocationTargetException;
+
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
-
+import javax.swing.WindowConstants;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.util.Point;
import javax.media.opengl.GLCapabilities;
@@ -45,7 +48,9 @@ import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestCloseNewtAWT extends UITestCase {
GLWindow newtWindow = null;
@@ -54,7 +59,7 @@ public class TestCloseNewtAWT extends UITestCase {
@SuppressWarnings("serial")
class MyCanvas extends NewtCanvasAWT {
- public MyCanvas(Window window) {
+ public MyCanvas(final Window window) {
super(window);
}
@@ -75,10 +80,10 @@ public class TestCloseNewtAWT extends UITestCase {
", holds AWTTreeLock: "+Thread.holdsLock(MyCanvas.this.getTreeLock()));
// Critical: Within NEWT EDT, while AWT is locked
- NativeWindow nw = MyCanvas.this.getNativeWindow();
+ final NativeWindow nw = MyCanvas.this.getNativeWindow();
if(null != nw) {
- Point p = nw.getLocationOnScreen(null);
- System.err.println("MyCanvas On NEWT-EDT: position: "+p);
+ final Point p = nw.getLocationOnScreen(null);
+ System.err.println("MyCanvas On NEWT-EDT: position: "+p);
} else {
System.err.println("MyCanvas On NEWT-EDT: position n/a, null NativeWindow");
}
@@ -100,20 +105,22 @@ public class TestCloseNewtAWT extends UITestCase {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame = new JFrame("NEWT Close Test");
- frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.getContentPane().add(newtCanvas);
frame.pack();
frame.setSize(800, 600);
frame.setVisible(true);
}
});
- Thread.sleep(500);
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(newtWindow, true));
+ final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame);
- Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, closingListener));
}
- public static void main(String[] args) {
- String tstname = TestCloseNewtAWT.class.getName();
+ public static void main(final String[] args) {
+ final String tstname = TestCloseNewtAWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java
index c9450c2d6..c3345708f 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -31,18 +31,23 @@ package com.jogamp.opengl.test.junit.newt;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.opengl.*;
import com.jogamp.newt.*;
import com.jogamp.newt.event.*;
import com.jogamp.newt.opengl.*;
+import com.jogamp.newt.util.EDTUtil;
+
import java.io.IOException;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestDisplayLifecycle01NEWT extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
@@ -57,17 +62,17 @@ public class TestDisplayLifecycle01NEWT extends UITestCase {
caps = new GLCapabilities(glp);
}
- static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height)
+ static GLWindow createWindow(final Screen screen, final GLCapabilities caps, final int width, final int height)
throws InterruptedException
{
Assert.assertNotNull(caps);
//
// Create native windowing resources .. X11/Win/OSX
- //
+ //
GLWindow glWindow;
if(null!=screen) {
- Window window = NewtFactory.createWindow(screen, caps);
+ final Window window = NewtFactory.createWindow(screen, caps);
Assert.assertNotNull(window);
glWindow = GLWindow.create(window);
} else {
@@ -75,7 +80,7 @@ public class TestDisplayLifecycle01NEWT extends UITestCase {
}
glWindow.setUpdateFPSFrames(1, null);
- GLEventListener demo = new GearsES2();
+ final GLEventListener demo = new GearsES2();
setDemoFields(demo, glWindow);
glWindow.addGLEventListener(demo);
glWindow.addWindowListener(new TraceWindowAdapter());
@@ -83,7 +88,7 @@ public class TestDisplayLifecycle01NEWT extends UITestCase {
return glWindow;
}
- private void testDisplayCreate01(Display display, Screen screen) throws InterruptedException {
+ private void testDisplayCreate01(final Display display, final Screen screen) throws InterruptedException {
// start-state == end-state
Assert.assertEquals(0,Display.getActiveDisplayNumber());
Assert.assertEquals(0,display.getReferenceCount());
@@ -94,7 +99,7 @@ public class TestDisplayLifecycle01NEWT extends UITestCase {
Assert.assertEquals(false,screen.isNativeValid());
// Create Window, pending lazy native creation
- GLWindow window = createWindow(screen, caps, width, height);
+ final GLWindow window = createWindow(screen, caps, width, height);
Assert.assertEquals(screen,window.getScreen());
Assert.assertEquals(0,Display.getActiveDisplayNumber());
Assert.assertEquals(0,display.getReferenceCount());
@@ -199,8 +204,18 @@ public class TestDisplayLifecycle01NEWT extends UITestCase {
Assert.assertEquals(0,Display.getActiveDisplayNumber());
Assert.assertEquals(0,display.getReferenceCount());
Assert.assertEquals(false,display.isNativeValid());
- Assert.assertNotNull(display.getEDTUtil());
- Assert.assertEquals(false,display.getEDTUtil().isRunning());
+ {
+ final EDTUtil edtUtil = display.getEDTUtil();
+ Assert.assertNotNull(edtUtil);
+ Assert.assertEquals(false,edtUtil.isRunning());
+ edtUtil.start();
+ Assert.assertEquals(true,edtUtil.isRunning());
+ edtUtil.invoke(true, null);
+ Assert.assertEquals(true,edtUtil.isRunning());
+ edtUtil.invokeStop(true, null);
+ edtUtil.waitUntilStopped();
+ Assert.assertEquals(false,edtUtil.isRunning());
+ }
Assert.assertEquals(0,screen.getReferenceCount());
Assert.assertEquals(false,screen.isNativeValid());
@@ -214,15 +229,15 @@ public class TestDisplayLifecycle01NEWT extends UITestCase {
Assert.assertEquals(0,Display.getActiveDisplayNumber());
// Create Display/Screen, pending lazy native creation
- Display display = NewtFactory.createDisplay(null);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final Display display = NewtFactory.createDisplay(null);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
testDisplayCreate01(display, screen);
testDisplayCreate01(display, screen);
Assert.assertEquals(0,Display.getActiveDisplayNumber());
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
if(!MiscUtils.setFieldIfExists(demo, "window", glWindow)) {
@@ -230,22 +245,22 @@ public class TestDisplayLifecycle01NEWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
System.err.println("durationPerTest: "+durationPerTest);
- String tstname = TestDisplayLifecycle01NEWT.class.getName();
+ final String tstname = TestDisplayLifecycle01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java
index bf509124b..17a66691a 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -31,18 +31,24 @@ package com.jogamp.opengl.test.junit.newt;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+import javax.media.nativewindow.util.RectangleImmutable;
import javax.media.opengl.*;
import com.jogamp.newt.*;
import com.jogamp.newt.event.*;
import com.jogamp.newt.opengl.*;
+
import java.io.IOException;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestDisplayLifecycle02NEWT extends UITestCase {
static GLProfile glp;
static GLCapabilities caps;
@@ -57,18 +63,18 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
caps = new GLCapabilities(glp);
}
- static GLWindow createWindow(GLCapabilities caps, int width, int height)
+ static GLWindow createWindow(final GLCapabilities caps, final int width, final int height)
throws InterruptedException
{
Assert.assertNotNull(caps);
//
// Create native windowing resources .. X11/Win/OSX
- //
- GLWindow glWindow = GLWindow.create(caps);
+ //
+ final GLWindow glWindow = GLWindow.create(caps);
glWindow.setUpdateFPSFrames(1, null);
- GLEventListener demo = new GearsES2();
+ final GLEventListener demo = new GearsES2();
setDemoFields(demo, glWindow);
glWindow.addGLEventListener(demo);
glWindow.addWindowListener(new TraceWindowAdapter());
@@ -81,9 +87,9 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
Assert.assertEquals(0,Display.getActiveDisplayNumber());
// Create Window, pending lazy native creation
- GLWindow window = createWindow(caps, width, height);
- Screen screen = window.getScreen();
- Display display = screen.getDisplay();
+ final GLWindow window = createWindow(caps, width, height);
+ final Screen screen = window.getScreen();
+ final Display display = screen.getDisplay();
Assert.assertEquals(screen,window.getScreen());
Assert.assertEquals(0,Display.getActiveDisplayNumber());
@@ -141,6 +147,9 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
// destruction.. ref count down, but keep all
window.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+
Assert.assertEquals(screen,window.getScreen());
Assert.assertEquals(0,Display.getActiveDisplayNumber());
Assert.assertEquals(0,display.getReferenceCount());
@@ -186,6 +195,9 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
System.err.println("duration: "+window.getTotalFPSDuration());
window.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+
Assert.assertEquals(screen,window.getScreen());
Assert.assertEquals(false,window.isNativeValid());
Assert.assertEquals(false,window.isVisible());
@@ -208,7 +220,9 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
Assert.assertEquals(0,Display.getActiveDisplayNumber());
// Create Display/Screen, pending lazy native creation
+ System.err.println("Pass - 1");
testDisplayCreate01Impl();
+ System.err.println("Pass - 2");
testDisplayCreate01Impl();
Assert.assertEquals(0,Display.getActiveDisplayNumber());
@@ -219,15 +233,16 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
Assert.assertEquals(0,Display.getActiveDisplayNumber());
// Create Window, pending lazy native creation
- GLWindow window1 = createWindow(caps, width, height);
+ final GLWindow window1 = createWindow(caps, width, height);
window1.setPosition(0, 0);
- Screen screen = window1.getScreen();
- Display display = screen.getDisplay();
+ final Screen screen = window1.getScreen();
+ final Display display = screen.getDisplay();
- GLWindow window2 = createWindow(caps, width, height);
+ final GLWindow window2 = createWindow(caps, width, height);
Assert.assertSame(screen, window2.getScreen());
Assert.assertSame(display, window2.getScreen().getDisplay());
- window2.setPosition(screen.getWidth()-width, 0);
+ final RectangleImmutable screenBoundsInWinU = screen.getViewportInWindowUnits();
+ window2.setPosition(screenBoundsInWinU.getWidth()-width, 0);
Assert.assertEquals(0,Display.getActiveDisplayNumber());
Assert.assertEquals(0,display.getReferenceCount());
@@ -285,6 +300,8 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
// destruction ...
window1.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window1, false));
+
Assert.assertNotNull(window1.getScreen());
Assert.assertEquals(false,window1.isNativeValid());
Assert.assertEquals(false,window1.isVisible());
@@ -300,6 +317,9 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
// destruction
window2.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window2, false));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+
Assert.assertNotNull(window2.getScreen());
Assert.assertEquals(false,window2.isNativeValid());
Assert.assertEquals(false,window2.isVisible());
@@ -314,12 +334,12 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
Assert.assertEquals(0,screen.getReferenceCount());
Assert.assertEquals(false,screen.isNativeValid());
- // invalidate .. remove all refs
+ // invalidate (again) ..
window1.destroy();
Assert.assertEquals(false,window1.isNativeValid());
Assert.assertEquals(false,window1.isVisible());
- // invalidate .. remove all refs
+ // invalidate (again) ..
window2.destroy();
Assert.assertEquals(false,window2.isNativeValid());
Assert.assertEquals(false,window2.isVisible());
@@ -331,13 +351,15 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
Assert.assertEquals(0,Display.getActiveDisplayNumber());
// Create Display/Screen, pending lazy native creation
+ System.err.println("Pass - 1");
testDisplayCreate02Impl();
+ System.err.println("Pass - 2");
testDisplayCreate02Impl();
Assert.assertEquals(0,Display.getActiveDisplayNumber());
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
if(!MiscUtils.setFieldIfExists(demo, "window", glWindow)) {
@@ -345,22 +367,22 @@ public class TestDisplayLifecycle02NEWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
System.err.println("durationPerTest: "+durationPerTest);
- String tstname = TestDisplayLifecycle02NEWT.class.getName();
+ final String tstname = TestDisplayLifecycle02NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestEventSourceNotAWTBug.java b/src/test/com/jogamp/opengl/test/junit/newt/TestEventSourceNotAWTBug.java
index ecf0ada8a..eaafd190f 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestEventSourceNotAWTBug.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestEventSourceNotAWTBug.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,16 +20,18 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
@@ -48,6 +50,7 @@ import com.jogamp.opengl.test.junit.util.*;
/**
* This simple program will throw a {@link RuntimeException} when the application is closed.
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestEventSourceNotAWTBug extends UITestCase {
@BeforeClass
@@ -56,7 +59,7 @@ public class TestEventSourceNotAWTBug extends UITestCase {
@Test
public void testEventSourceNotNewtBug() throws InterruptedException, InvocationTargetException {
- JFrame jf = new JFrame();
+ final JFrame jf = new JFrame();
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
@@ -87,8 +90,8 @@ public class TestEventSourceNotAWTBug extends UITestCase {
glWindow.destroy();
}
- public static void main(String args[]) throws IOException {
- String tstname = TestEventSourceNotAWTBug.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestEventSourceNotAWTBug.class.getName();
/*
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowInvisiblePointer01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowInvisiblePointer01NEWT.java
new file mode 100644
index 000000000..546b35503
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowInvisiblePointer01NEWT.java
@@ -0,0 +1,117 @@
+package com.jogamp.opengl.test.junit.newt;
+
+import java.io.IOException;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLWindowInvisiblePointer01NEWT extends UITestCase {
+ static GLProfile glp;
+ static int width, height;
+ static long durationPerTest = 4000; // ms
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ glp = GLProfile.getDefault();
+ }
+
+ static GLWindow createWindow(final Screen screen, final GLCapabilitiesImmutable caps)
+ throws InterruptedException
+ {
+ Assert.assertNotNull(caps);
+ //
+ // Create native windowing resources .. X11/Win/OSX
+ //
+ GLWindow glWindow;
+ if(null!=screen) {
+ glWindow = GLWindow.create(screen, caps);
+ Assert.assertNotNull(glWindow);
+ } else {
+ glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ }
+ glWindow.setUpdateFPSFrames(1, null);
+
+ final GLEventListener demo = new GearsES1();
+ glWindow.addGLEventListener(demo);
+
+ glWindow.setSize(512, 512);
+ glWindow.setVisible(true);
+ Assert.assertEquals(true,glWindow.isVisible());
+ Assert.assertEquals(true,glWindow.isNativeValid());
+
+ return glWindow;
+ }
+
+ static void destroyWindow(final GLWindow glWindow) {
+ if(null!=glWindow) {
+ glWindow.destroy();
+ Assert.assertEquals(false,glWindow.isNativeValid());
+ }
+ }
+
+ @Test
+ public void testWindow00() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ final GLWindow window1 = createWindow(null, caps); // local
+ Assert.assertEquals(true,window1.isNativeValid());
+ Assert.assertEquals(true,window1.isVisible());
+ final Animator animator = new Animator();
+ animator.setUpdateFPSFrames(1, null);
+ animator.add(window1);
+ animator.start();
+ final AbstractGraphicsDevice device1 = window1.getScreen().getDisplay().getGraphicsDevice();
+
+ System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1));
+
+ window1.warpPointer(width / 2, height / 2);
+ window1.requestFocus();
+ while(animator.isAnimating() && animator.getTotalFPSDuration()<durationPerTest) {
+ final boolean pointerVisibleNewVal = (animator.getTotalFPSDuration()/100)%2==0;
+ window1.setPointerVisible(pointerVisibleNewVal);
+ Assert.assertEquals(pointerVisibleNewVal,window1.isPointerVisible());
+ Thread.sleep(100);
+ }
+
+ destroyWindow(window1);
+ }
+
+ static int atoi(final String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ System.out.println("durationPerTest: "+durationPerTest);
+ final String tstname = TestGLWindowInvisiblePointer01NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowWarpPointer01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowWarpPointer01NEWT.java
new file mode 100644
index 000000000..04a27dcc9
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowWarpPointer01NEWT.java
@@ -0,0 +1,174 @@
+package com.jogamp.opengl.test.junit.newt;
+
+import java.io.IOException;
+import java.util.Random;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.event.MouseAdapter;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLWindowWarpPointer01NEWT extends UITestCase {
+ static GLProfile glp;
+ static int width, height;
+ static long durationPerTest = 2000; // ms
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ glp = GLProfile.getDefault();
+ }
+
+ static GLWindow createWindow(final Screen screen, final GLCapabilitiesImmutable caps)
+ throws InterruptedException
+ {
+ Assert.assertNotNull(caps);
+ //
+ // Create native windowing resources .. X11/Win/OSX
+ //
+ GLWindow glWindow;
+ if(null!=screen) {
+ glWindow = GLWindow.create(screen, caps);
+ Assert.assertNotNull(glWindow);
+ } else {
+ glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+ }
+ glWindow.setUpdateFPSFrames(1, null);
+
+ final GLEventListener demo = new GearsES2();
+ glWindow.addGLEventListener(demo);
+
+ glWindow.setSize(512, 512);
+ glWindow.setVisible(true);
+ Assert.assertEquals(true,glWindow.isVisible());
+ Assert.assertEquals(true,glWindow.isNativeValid());
+
+ return glWindow;
+ }
+
+ static void destroyWindow(final GLWindow glWindow) {
+ if(null!=glWindow) {
+ glWindow.destroy();
+ Assert.assertEquals(false,glWindow.isNativeValid());
+ }
+ }
+
+ @Test
+ public void testWarp01Center() throws InterruptedException {
+ testWarpImpl(false);
+ }
+
+ @Test
+ public void testWarp02Random() throws InterruptedException {
+ testWarpImpl(true);
+ }
+
+ void testWarpImpl(final boolean random) throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ final GLWindow window1 = createWindow(null, caps); // local
+ Assert.assertEquals(true,window1.isNativeValid());
+ Assert.assertEquals(true,window1.isVisible());
+ final Animator animator = new Animator();
+ animator.setUpdateFPSFrames(1, null);
+ animator.add(window1);
+ animator.start();
+ final AbstractGraphicsDevice device1 = window1.getScreen().getDisplay().getGraphicsDevice();
+
+ System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1));
+
+ window1.warpPointer(width / 2, height / 2);
+ window1.requestFocus();
+
+ window1.addMouseListener(new MouseAdapter() {
+ void warpCenter() {
+ window1.warpPointer(width / 2, height / 2);
+ }
+
+ @Override
+ public void mouseEntered(final MouseEvent e) {
+ }
+
+ @Override
+ public void mouseExited(final MouseEvent e) {
+ warpCenter();
+ }
+
+ @Override
+ public void mouseMoved(final MouseEvent e) {
+ }
+ });
+
+ if( random ) {
+ window1.addGLEventListener(new GLEventListener() {
+ final Random r = new Random();
+
+ void warpRandom(final int width, final int height) {
+ final int x = r.nextInt(width);
+ final int y = r.nextInt(height);
+ window1.warpPointer(x, y);
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {}
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ warpRandom(drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+
+ });
+ }
+
+ while(animator.isAnimating() && animator.getTotalFPSDuration()<durationPerTest) {
+ Thread.sleep(100);
+ }
+
+ destroyWindow(window1);
+ }
+
+ static int atoi(final String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ System.out.println("durationPerTest: "+durationPerTest);
+ final String tstname = TestGLWindowWarpPointer01NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java
index 309d7c7cb..bd84341b8 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.opengl.*;
@@ -43,6 +45,7 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import javax.media.nativewindow.AbstractGraphicsDevice;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLWindows00NEWT extends UITestCase {
static GLProfile glp;
static int width, height;
@@ -55,13 +58,13 @@ public class TestGLWindows00NEWT extends UITestCase {
glp = GLProfile.getDefault();
}
- static GLWindow createWindow(Screen screen, GLCapabilitiesImmutable caps)
+ static GLWindow createWindow(final Screen screen, final GLCapabilitiesImmutable caps)
throws InterruptedException
{
Assert.assertNotNull(caps);
//
// Create native windowing resources .. X11/Win/OSX
- //
+ //
GLWindow glWindow;
if(null!=screen) {
glWindow = GLWindow.create(screen, caps);
@@ -70,9 +73,9 @@ public class TestGLWindows00NEWT extends UITestCase {
glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
}
- glWindow.setUpdateFPSFrames(1, null);
+ glWindow.setUpdateFPSFrames(1, null);
- GLEventListener demo = new GearsES2();
+ final GLEventListener demo = new GearsES2();
glWindow.addGLEventListener(demo);
glWindow.setSize(512, 512);
@@ -83,7 +86,7 @@ public class TestGLWindows00NEWT extends UITestCase {
return glWindow;
}
- static void destroyWindow(GLWindow glWindow) {
+ static void destroyWindow(final GLWindow glWindow) {
if(null!=glWindow) {
glWindow.destroy();
Assert.assertEquals(false,glWindow.isNativeValid());
@@ -92,12 +95,12 @@ public class TestGLWindows00NEWT extends UITestCase {
@Test
public void testWindow00() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window1 = createWindow(null, caps); // local
+ final GLWindow window1 = createWindow(null, caps); // local
Assert.assertEquals(true,window1.isNativeValid());
Assert.assertEquals(true,window1.isVisible());
- AbstractGraphicsDevice device1 = window1.getScreen().getDisplay().getGraphicsDevice();
+ final AbstractGraphicsDevice device1 = window1.getScreen().getDisplay().getGraphicsDevice();
System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1));
@@ -108,22 +111,22 @@ public class TestGLWindows00NEWT extends UITestCase {
destroyWindow(window1);
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
System.out.println("durationPerTest: "+durationPerTest);
- String tstname = TestGLWindows00NEWT.class.getName();
+ final String tstname = TestGLWindows00NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java
index 0c6f60b5f..ea3e96a47 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.opengl.*;
@@ -43,6 +45,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLWindows01NEWT extends UITestCase {
static GLProfile glp;
static int width, height;
@@ -55,9 +58,9 @@ public class TestGLWindows01NEWT extends UITestCase {
glp = GLProfile.getDefault();
}
- static GLWindow createWindow(Screen screen, GLCapabilities caps,
- int width, int height, boolean onscreen, boolean undecorated,
- boolean addGLEventListenerAfterVisible)
+ static GLWindow createWindow(final Screen screen, final GLCapabilities caps,
+ final int width, final int height, final boolean onscreen, final boolean undecorated,
+ final boolean addGLEventListenerAfterVisible)
throws InterruptedException
{
Assert.assertNotNull(caps);
@@ -66,7 +69,7 @@ public class TestGLWindows01NEWT extends UITestCase {
//
// Create native windowing resources .. X11/Win/OSX
- //
+ //
GLWindow glWindow;
if(null!=screen) {
glWindow = GLWindow.create(screen, caps);
@@ -80,7 +83,7 @@ public class TestGLWindows01NEWT extends UITestCase {
Assert.assertEquals(false,glWindow.isVisible());
Assert.assertEquals(false,glWindow.isNativeValid());
- GLEventListener demo = new GearsES2();
+ final GLEventListener demo = new GearsES2();
setDemoFields(demo, glWindow);
if(!addGLEventListenerAfterVisible) {
glWindow.addGLEventListener(demo);
@@ -97,10 +100,10 @@ public class TestGLWindows01NEWT extends UITestCase {
Assert.assertTrue(0 < glWindow.getTotalFPSFrames());
//
- // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
// equivalent to GLAutoDrawable methods: setVisible(true)
- //
- GLCapabilitiesImmutable caps2 = glWindow.getChosenGLCapabilities();
+ //
+ final GLCapabilitiesImmutable caps2 = glWindow.getChosenGLCapabilities();
Assert.assertNotNull(caps2);
Assert.assertTrue(caps2.getGreenBits()>=5);
Assert.assertTrue(caps2.getBlueBits()>=5);
@@ -115,7 +118,7 @@ public class TestGLWindows01NEWT extends UITestCase {
return glWindow;
}
- static void destroyWindow(GLWindow glWindow) {
+ static void destroyWindow(final GLWindow glWindow) {
if(null!=glWindow) {
glWindow.destroy();
Assert.assertEquals(false,glWindow.isNativeValid());
@@ -124,10 +127,10 @@ public class TestGLWindows01NEWT extends UITestCase {
@Test
public void testWindowNativeRecreate01aSimple() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window = createWindow(null, caps, width, height,
- true /* onscreen */, false /* undecorated */,
+ final GLWindow window = createWindow(null, caps, width, height,
+ true /* onscreen */, false /* undecorated */,
false /*addGLEventListenerAfterVisible*/);
Assert.assertEquals(true,window.isNativeValid());
@@ -153,10 +156,10 @@ public class TestGLWindows01NEWT extends UITestCase {
@Test
public void testWindowNativeRecreate01bSimple() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window = createWindow(null, caps, width, height,
- true /* onscreen */, false /* undecorated */,
+ final GLWindow window = createWindow(null, caps, width, height,
+ true /* onscreen */, false /* undecorated */,
true /*addGLEventListenerAfterVisible*/);
Assert.assertEquals(true,window.isNativeValid());
@@ -182,10 +185,10 @@ public class TestGLWindows01NEWT extends UITestCase {
@Test
public void testWindowDecor01aSimple() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window = createWindow(null, caps, width, height,
- true /* onscreen */, false /* undecorated */,
+ final GLWindow window = createWindow(null, caps, width, height,
+ true /* onscreen */, false /* undecorated */,
false /*addGLEventListenerAfterVisible*/);
System.out.println("Created: "+window);
int state;
@@ -198,10 +201,10 @@ public class TestGLWindows01NEWT extends UITestCase {
@Test
public void testWindowDecor01bSimple() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window = createWindow(null, caps, width, height,
- true /* onscreen */, false /* undecorated */,
+ final GLWindow window = createWindow(null, caps, width, height,
+ true /* onscreen */, false /* undecorated */,
true /*addGLEventListenerAfterVisible*/);
System.out.println("Created: "+window);
int state;
@@ -214,10 +217,10 @@ public class TestGLWindows01NEWT extends UITestCase {
@Test
public void testWindowDecor02DestroyWinTwiceA() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window = createWindow(null, caps, width, height,
- true /* onscreen */, false /* undecorated */,
+ final GLWindow window = createWindow(null, caps, width, height,
+ true /* onscreen */, false /* undecorated */,
false /*addGLEventListenerAfterVisible*/);
int state;
for(state=0; state*100<durationPerTest; state++) {
@@ -229,21 +232,21 @@ public class TestGLWindows01NEWT extends UITestCase {
@Test
public void testWindowDecor03TwoWinOneDisplay() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- Display display = NewtFactory.createDisplay(null); // local display
+ final Display display = NewtFactory.createDisplay(null); // local display
Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
Assert.assertNotNull(screen);
- GLWindow window1 = createWindow(screen, caps, width, height,
- true /* onscreen */, false /* undecorated */,
+ final GLWindow window1 = createWindow(screen, caps, width, height,
+ true /* onscreen */, false /* undecorated */,
false /*addGLEventListenerAfterVisible*/);
Assert.assertNotNull(window1);
- GLWindow window2 = createWindow(screen, caps, width, height,
- true /* onscreen */, false /* undecorated */,
+ final GLWindow window2 = createWindow(screen, caps, width, height,
+ true /* onscreen */, false /* undecorated */,
false /*addGLEventListenerAfterVisible*/);
Assert.assertNotNull(window2);
@@ -279,26 +282,26 @@ public class TestGLWindows01NEWT extends UITestCase {
@Test
public void testWindowDecor03TwoWinTwoDisplays() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- Display display1 = NewtFactory.createDisplay(null, false); // local display
+ final Display display1 = NewtFactory.createDisplay(null, false); // local display
Assert.assertNotNull(display1);
- Display display2 = NewtFactory.createDisplay(null, false); // local display
+ final Display display2 = NewtFactory.createDisplay(null, false); // local display
Assert.assertNotNull(display2);
Assert.assertNotSame(display1, display2);
- Screen screen1 = NewtFactory.createScreen(display1, 0); // screen 0
+ final Screen screen1 = NewtFactory.createScreen(display1, 0); // screen 0
Assert.assertNotNull(screen1);
- GLWindow window1 = createWindow(screen1, caps, width, height,
- true /* onscreen */, false /* undecorated */,
+ final GLWindow window1 = createWindow(screen1, caps, width, height,
+ true /* onscreen */, false /* undecorated */,
false /*addGLEventListenerAfterVisible*/);
Assert.assertNotNull(window1);
- Screen screen2 = NewtFactory.createScreen(display2, 0); // screen 0
+ final Screen screen2 = NewtFactory.createScreen(display2, 0); // screen 0
Assert.assertNotNull(screen2);
- GLWindow window2 = createWindow(screen2, caps, width, height,
- true /* onscreen */, false /* undecorated */,
+ final GLWindow window2 = createWindow(screen2, caps, width, height,
+ true /* onscreen */, false /* undecorated */,
false /*addGLEventListenerAfterVisible*/);
Assert.assertNotNull(window2);
@@ -348,10 +351,10 @@ public class TestGLWindows01NEWT extends UITestCase {
Assert.assertNotNull(display2.getEDTUtil());
Assert.assertEquals(false,display2.getEDTUtil().isRunning());
Assert.assertEquals(0,screen2.getReferenceCount());
- Assert.assertEquals(false,screen2.isNativeValid());
+ Assert.assertEquals(false,screen2.isNativeValid());
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
if(!MiscUtils.setFieldIfExists(demo, "window", glWindow)) {
@@ -359,22 +362,22 @@ public class TestGLWindows01NEWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
System.out.println("durationPerTest: "+durationPerTest);
- String tstname = TestGLWindows01NEWT.class.getName();
+ final String tstname = TestGLWindows01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java
index 6f4ced53c..4969c3b77 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,31 +20,37 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
import javax.media.opengl.*;
import com.jogamp.opengl.util.Animator;
import com.jogamp.newt.*;
import com.jogamp.newt.event.*;
import com.jogamp.newt.opengl.*;
+
import java.io.IOException;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestGLWindows02NEWTAnimated extends UITestCase {
static GLProfile glp;
static int width, height;
@@ -57,27 +63,27 @@ public class TestGLWindows02NEWTAnimated extends UITestCase {
glp = GLProfile.getDefault();
}
- static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated, boolean vsync) {
+ static GLWindow createWindow(final Screen screen, final GLCapabilities caps, final int width, final int height, final boolean onscreen, final boolean undecorated, final boolean vsync) {
Assert.assertNotNull(caps);
caps.setOnscreen(onscreen);
// System.out.println("Requested: "+caps);
//
// Create native windowing resources .. X11/Win/OSX
- //
+ //
GLWindow glWindow;
if(null!=screen) {
- Window window = NewtFactory.createWindow(screen, caps);
+ final Window window = NewtFactory.createWindow(screen, caps);
Assert.assertNotNull(window);
glWindow = GLWindow.create(window);
} else {
glWindow = GLWindow.create(caps);
}
- glWindow.setUpdateFPSFrames(1, null);
+ glWindow.setUpdateFPSFrames(1, null);
Assert.assertNotNull(glWindow);
glWindow.setUndecorated(onscreen && undecorated);
- GLEventListener demo = new GearsES2(vsync ? 1 : 0);
+ final GLEventListener demo = new GearsES2(vsync ? 1 : 0);
setDemoFields(demo, glWindow);
glWindow.addGLEventListener(demo);
glWindow.addWindowListener(new TraceWindowAdapter());
@@ -93,10 +99,10 @@ public class TestGLWindows02NEWTAnimated extends UITestCase {
// System.out.println("Created: "+glWindow);
//
- // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
// equivalent to GLAutoDrawable methods: setVisible(true)
- //
- GLCapabilitiesImmutable caps2 = glWindow.getChosenGLCapabilities();
+ //
+ final GLCapabilitiesImmutable caps2 = glWindow.getChosenGLCapabilities();
Assert.assertNotNull(caps2);
Assert.assertTrue(caps2.getGreenBits()>=5);
Assert.assertTrue(caps2.getBlueBits()>=5);
@@ -106,7 +112,7 @@ public class TestGLWindows02NEWTAnimated extends UITestCase {
return glWindow;
}
- static void destroyWindow(GLWindow glWindow) {
+ static void destroyWindow(final GLWindow glWindow) {
if(null!=glWindow) {
glWindow.destroy();
}
@@ -114,80 +120,88 @@ public class TestGLWindows02NEWTAnimated extends UITestCase {
@Test
public void testWindowDecor01Simple() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */, true /* vsync */);
- Animator animator = new Animator(window);
- animator.setUpdateFPSFrames(1, null);
+ final GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */, true /* vsync */);
+ final Animator animator = new Animator(window);
+ animator.setUpdateFPSFrames(1, null);
Assert.assertTrue(animator.start());
while(animator.isAnimating() && animator.getTotalFPSDuration()<durationPerTest) {
Thread.sleep(100);
}
- destroyWindow(window); // destroy - but still in animator
+ destroyWindow(window); // destroy - but still in animator
Assert.assertEquals(false, window.isNativeValid());
- Assert.assertEquals(false, window.isVisible());
+ Assert.assertEquals(false, window.isVisible());
Assert.assertEquals(true, animator.isAnimating());
Assert.assertEquals(false, animator.isPaused());
Assert.assertEquals(true, animator.isStarted());
-
+
animator.remove(window);
+ Thread.sleep(250); // give animator a chance to become paused
Assert.assertEquals(false, animator.isAnimating());
- Assert.assertEquals(false, animator.isPaused());
+ Assert.assertEquals(true, animator.isPaused()); // zero drawables
Assert.assertEquals(true, animator.isStarted());
Assert.assertTrue(animator.stop());
}
@Test
public void testWindowDecor02DestroyWinTwiceA() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */, true /* vsync */);
- Animator animator = new Animator(window);
- animator.setUpdateFPSFrames(1, null);
+ final GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */, true /* vsync */);
+ final Animator animator = new Animator();
+ animator.setUpdateFPSFrames(1, null);
Assert.assertTrue(animator.start());
+ Thread.sleep(250); // give animator a chance to become paused
+ Assert.assertEquals(false, animator.isAnimating()); // zero drawables
+ Assert.assertEquals(true, animator.isPaused()); // zero drawables
+ animator.add(window);
while(animator.isAnimating() && animator.getTotalFPSDuration()<durationPerTest) {
Thread.sleep(100);
}
destroyWindow(window);
destroyWindow(window);
Assert.assertEquals(true, animator.isAnimating());
- Assert.assertEquals(false, animator.isPaused());
Assert.assertEquals(true, animator.isStarted());
+ Assert.assertEquals(false, animator.isPaused());
animator.remove(window);
+ Thread.sleep(250); // give animator a chance to become paused
Assert.assertEquals(false, animator.isAnimating());
- Assert.assertEquals(false, animator.isPaused());
Assert.assertEquals(true, animator.isStarted());
+ Assert.assertEquals(true, animator.isPaused()); // zero drawables
Assert.assertTrue(animator.stop());
}
@Test
public void testWindowDecor03TwoWinOneDisplay() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- Display display = NewtFactory.createDisplay(null); // local display
+ final Display display = NewtFactory.createDisplay(null); // local display
Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
Assert.assertNotNull(screen);
- GLWindow window1 = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */, false /* vsync */);
+ final GLWindow window1 = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */, false /* vsync */);
Assert.assertNotNull(window1);
window1.setPosition(0, 0);
- GLWindow window2 = createWindow(screen, caps, width-10, height-10, true /* onscreen */, false /* undecorated */, true /* vsync */);
+ final GLWindow window2 = createWindow(screen, caps, width-10, height-10, true /* onscreen */, false /* undecorated */, true /* vsync */);
Assert.assertNotNull(window2);
- window2.setPosition(screen.getWidth()-width, 0);
+ final RectangleImmutable screenBoundsInWinU = screen.getViewportInWindowUnits();
+ window2.setPosition(screenBoundsInWinU.getWidth()-width, 0);
- Animator animator = new Animator();
- animator.setUpdateFPSFrames(1, null);
+ final Animator animator = new Animator();
+ animator.setUpdateFPSFrames(1, null);
Assert.assertEquals(false, animator.isStarted());
- Assert.assertEquals(false, animator.isAnimating());
- Assert.assertEquals(false, animator.isPaused());
+ Assert.assertEquals(false, animator.isAnimating()); // zero drawables
+ Assert.assertEquals(false, animator.isPaused()); // zero drawables, but not started
Assert.assertTrue(animator.start());
Assert.assertEquals(true, animator.isStarted());
- Assert.assertEquals(false, animator.isAnimating());
- Assert.assertEquals(false, animator.isPaused());
+ Thread.sleep(250); // give animator a chance to become paused
+ Assert.assertEquals(false, animator.isAnimating()); // zero drawables
+ Assert.assertEquals(true, animator.isPaused()); // zero drawables
animator.add(window1);
Assert.assertEquals(true, animator.isStarted());
@@ -214,44 +228,47 @@ public class TestGLWindows02NEWTAnimated extends UITestCase {
window2.destroy();
animator.remove(window2);
Assert.assertEquals(true, animator.isStarted());
- Assert.assertEquals(false, animator.isAnimating());
- Assert.assertEquals(false, animator.isPaused());
+ Thread.sleep(250); // give animator a chance to become paused
+ Assert.assertEquals(false, animator.isAnimating()); // zero drawables
+ Assert.assertEquals(true, animator.isPaused()); // zero drawables
Assert.assertTrue(animator.stop());
}
@Test
public void testWindowDecor03TwoWinTwoDisplays() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- Display display1 = NewtFactory.createDisplay(null, false); // local display
+ final Display display1 = NewtFactory.createDisplay(null, false); // local display
Assert.assertNotNull(display1);
- Display display2 = NewtFactory.createDisplay(null, false); // local display
+ final Display display2 = NewtFactory.createDisplay(null, false); // local display
Assert.assertNotNull(display2);
Assert.assertNotSame(display1, display2);
- Screen screen1 = NewtFactory.createScreen(display1, 0); // screen 0
+ final Screen screen1 = NewtFactory.createScreen(display1, 0); // screen 0
Assert.assertNotNull(screen1);
- GLWindow window1 = createWindow(screen1, caps, width, height, true /* onscreen */, false /* undecorated */, false /* vsync */);
+ final GLWindow window1 = createWindow(screen1, caps, width, height, true /* onscreen */, false /* undecorated */, false /* vsync */);
Assert.assertNotNull(window1);
window1.setPosition(0, 0);
- Screen screen2 = NewtFactory.createScreen(display2, 0); // screen 0
+ final Screen screen2 = NewtFactory.createScreen(display2, 0); // screen 0
Assert.assertNotNull(screen2);
- GLWindow window2 = createWindow(screen2, caps, width-10, height-10, true /* onscreen */, false /* undecorated */, true /* vsync */);
+ final GLWindow window2 = createWindow(screen2, caps, width-10, height-10, true /* onscreen */, false /* undecorated */, true /* vsync */);
Assert.assertNotNull(window2);
- window2.setPosition(screen2.getWidth()-width, 0);
+ final RectangleImmutable screen2BoundsInWinU = screen2.getViewportInWindowUnits();
+ window2.setPosition(screen2BoundsInWinU.getWidth()-width, 0);
- Animator animator = new Animator();
- animator.setUpdateFPSFrames(1, null);
+ final Animator animator = new Animator();
+ animator.setUpdateFPSFrames(1, null);
Assert.assertEquals(false, animator.isStarted());
Assert.assertEquals(false, animator.isAnimating());
Assert.assertEquals(false, animator.isPaused());
Assert.assertTrue(animator.start());
Assert.assertEquals(true, animator.isStarted());
- Assert.assertEquals(false, animator.isAnimating());
- Assert.assertEquals(false, animator.isPaused());
+ Thread.sleep(250); // give animator a chance to become paused
+ Assert.assertEquals(false, animator.isAnimating()); // zero drawables
+ Assert.assertEquals(true, animator.isPaused()); // zero drawables
animator.add(window1);
Assert.assertEquals(true, animator.isStarted());
@@ -275,29 +292,37 @@ public class TestGLWindows02NEWTAnimated extends UITestCase {
while(animator.isAnimating() && animator.getTotalFPSDuration()<durationPerTest+durationPerTest/10) {
Thread.sleep(100);
}
- destroyWindow(window2);
- animator.remove(window2);
+
Assert.assertEquals(true, animator.isStarted());
- Assert.assertEquals(false, animator.isAnimating());
+ Assert.assertEquals(true, animator.isAnimating());
Assert.assertEquals(false, animator.isPaused());
Assert.assertEquals(true, animator.pause());
- Assert.assertEquals(true, animator.isStarted());
+
+ Assert.assertEquals(true, animator.isStarted());
Assert.assertEquals(false, animator.isAnimating());
Assert.assertEquals(true, animator.isPaused());
Assert.assertEquals(true, animator.resume());
+
Assert.assertEquals(true, animator.isStarted());
- Assert.assertEquals(false, animator.isAnimating());
+ Assert.assertEquals(true, animator.isAnimating());
Assert.assertEquals(false, animator.isPaused());
+ destroyWindow(window2);
+ animator.remove(window2);
+ Assert.assertEquals(true, animator.isStarted());
+ Thread.sleep(250); // give animator a chance to become paused
+ Assert.assertEquals(false, animator.isAnimating()); // zero drawables
+ Assert.assertEquals(true, animator.isPaused()); // zero drawables
+
Assert.assertTrue(animator.stop());
Assert.assertEquals(false, animator.isStarted());
Assert.assertEquals(false, animator.isAnimating());
Assert.assertEquals(false, animator.isPaused());
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
if(!MiscUtils.setFieldIfExists(demo, "window", glWindow)) {
@@ -305,21 +330,21 @@ public class TestGLWindows02NEWTAnimated extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
- String tstname = TestGLWindows02NEWTAnimated.class.getName();
+ final String tstname = TestGLWindows02NEWTAnimated.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows03NEWTAnimResize.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows03NEWTAnimResize.java
new file mode 100644
index 000000000..f7a45c1b0
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows03NEWTAnimResize.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt;
+
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.event.TraceWindowAdapter;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLWindows03NEWTAnimResize extends UITestCase {
+ static GLProfile glp;
+ static int step = 4;
+ static int width, height;
+ static long durationPerTest = step*500; // ms
+
+ @BeforeClass
+ public static void initClass() {
+ width = 800;
+ height = 600;
+ glp = GLProfile.getDefault();
+ }
+
+ static void test(final GLCapabilitiesImmutable caps, final boolean undecorated) throws InterruptedException {
+ Assert.assertNotNull(caps);
+
+ //
+ // Create native windowing resources .. X11/Win/OSX
+ //
+ final GLWindow glWindow = GLWindow.create(caps);
+
+ glWindow.setUpdateFPSFrames(1, null);
+ Assert.assertNotNull(glWindow);
+ glWindow.setUndecorated(undecorated);
+
+ final GLEventListener demo = new GearsES2(1);
+ glWindow.addGLEventListener(demo);
+ glWindow.addWindowListener(new TraceWindowAdapter());
+ Assert.assertEquals(false,glWindow.isNativeValid());
+
+ glWindow.setPosition(100, 100);
+ glWindow.setSize(width/step, height/step);
+ Assert.assertEquals(false,glWindow.isVisible());
+ glWindow.setVisible(true);
+ Assert.assertEquals(true,glWindow.isVisible());
+ Assert.assertEquals(true,glWindow.isNativeValid());
+
+ final Animator animator = new Animator(glWindow);
+ animator.setUpdateFPSFrames(1, null);
+ Assert.assertTrue(animator.start());
+
+ int step_i = 0;
+ for(int i=0; i<durationPerTest; i+=50) {
+ Thread.sleep(50);
+ final int j = (int) ( i / (durationPerTest/step) ) + 1;
+ if(j>step_i) {
+ final int w = width/step * j;
+ final int h = height/step * j;
+ System.err.println("resize: "+step_i+" -> "+j+" - "+w+"x"+h);
+ glWindow.setSize(w, h);
+ step_i = j;
+ }
+ }
+ Thread.sleep(50);
+
+ animator.stop();
+ glWindow.destroy();
+ Assert.assertEquals(false, glWindow.isNativeValid());
+ Assert.assertEquals(false, glWindow.isVisible());
+ }
+
+ @Test
+ public void test01WindowDecor() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ test(caps, false /* undecorated */);
+ }
+
+ @Test
+ public void test02WindowUndecor() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ test(caps, true /* undecorated */);
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+ }
+ }
+ final String tstname = TestGLWindows03NEWTAnimResize.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestListenerCom01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestListenerCom01AWT.java
index fa7f0f915..588e3cc0f 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestListenerCom01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestListenerCom01AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import java.awt.Frame;
@@ -47,6 +49,7 @@ import java.lang.reflect.InvocationTargetException;
import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestListenerCom01AWT extends UITestCase {
static int width, height;
static long durationPerTest = 500;
@@ -61,19 +64,19 @@ public class TestListenerCom01AWT extends UITestCase {
@Test
public void testListenerStringPassingAndOrder() throws InterruptedException, InvocationTargetException {
// setup NEWT GLWindow ..
- GLWindow glWindow = GLWindow.create(new GLCapabilities(null));
+ final GLWindow glWindow = GLWindow.create(new GLCapabilities(null));
Assert.assertNotNull(glWindow);
glWindow.setTitle("NEWT - CHILD");
System.out.println("durationPerTest "+durationPerTest);
- GLEventListener demo = new GearsES2();
+ final GLEventListener demo = new GearsES2();
setDemoFields(demo, glWindow, false);
glWindow.addGLEventListener(demo);
- WindowEventCom1 wl1 = new WindowEventCom1();
- WindowEventCom2 wl2 = new WindowEventCom2();
- WindowEventCom3 wl3 = new WindowEventCom3();
+ final WindowEventCom1 wl1 = new WindowEventCom1();
+ final WindowEventCom2 wl2 = new WindowEventCom2();
+ final WindowEventCom3 wl3 = new WindowEventCom3();
// TraceWindowAdapter wlT = new TraceWindowAdapter();
// glWindow.addWindowListener(0, wlT);
@@ -88,7 +91,7 @@ public class TestListenerCom01AWT extends UITestCase {
Assert.assertEquals(wl3, glWindow.getWindowListener(2));
// attach NEWT GLWindow to AWT Canvas
- NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
final Frame frame = new Frame("AWT Parent Frame");
frame.add(newtCanvasAWT);
frame.setSize(width, height);
@@ -97,8 +100,8 @@ public class TestListenerCom01AWT extends UITestCase {
frame.setVisible(true);
}});
- Animator animator1 = new Animator(glWindow);
- animator1.setUpdateFPSFrames(1, null);
+ final Animator animator1 = new Animator(glWindow);
+ animator1.setUpdateFPSFrames(1, null);
animator1.start();
while(animator1.isAnimating() && animator1.getTotalFPSDuration()<durationPerTest) {
Thread.sleep(100);
@@ -115,10 +118,10 @@ public class TestListenerCom01AWT extends UITestCase {
glWindow.destroy();
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -128,22 +131,22 @@ public class TestListenerCom01AWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
verbose = true;
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
- String tstname = TestListenerCom01AWT.class.getName();
+ final String tstname = TestListenerCom01AWT.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestMultipleNewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestMultipleNewtCanvasAWT.java
new file mode 100644
index 000000000..0e11ff1e8
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestMultipleNewtCanvasAWT.java
@@ -0,0 +1,185 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.io.IOException;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+
+/**
+ * TestMultipleNewtCanvasAWT
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestMultipleNewtCanvasAWT extends UITestCase {
+
+ static long durationPerTest = 1000;
+
+ @BeforeClass
+ public static void initClass() {
+ if(!GLProfile.isAvailable(GLProfile.GL2ES2)) {
+ setTestSupported(false);
+ }
+ }
+
+ @Test
+ public void test01() throws InterruptedException {
+ testImpl();
+ }
+
+ public void testImpl() throws InterruptedException {
+ final JFrame frame = new JFrame(this.getSimpleTestName("."));
+
+ //
+ // GLDrawableFactory factory = GLDrawableFactory.getFactory(GLProfile.get(GLProfile.GL2));
+ // GLContext sharedContext = factory.getOrCreateSharedContext(factory.getDefaultDevice());
+ //
+ final GLCapabilities glCapabilities = new GLCapabilities(GLProfile.get(GLProfile.GL2));
+ glCapabilities.setSampleBuffers(true);
+ glCapabilities.setNumSamples(4);
+
+ final GearsES2 eventListener1 = new GearsES2(0);
+ final GearsES2 eventListener2 = new GearsES2(1);
+
+ final Component openGLComponent1;
+ final Component openGLComponent2;
+ final GLAutoDrawable openGLAutoDrawable1;
+ final GLAutoDrawable openGLAutoDrawable2;
+
+ final GLWindow glWindow1 = GLWindow.create(glCapabilities);
+ final NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(glWindow1);
+ newtCanvasAWT1.setPreferredSize(new Dimension(640, 480));
+ glWindow1.addGLEventListener(eventListener1);
+ //
+ final GLWindow glWindow2 = GLWindow.create(glCapabilities);
+ final NewtCanvasAWT newtCanvasAWT2 = new NewtCanvasAWT(glWindow2);
+ newtCanvasAWT2.setPreferredSize(new Dimension(640, 480));
+ glWindow2.addGLEventListener(eventListener2);
+
+ openGLComponent1 = newtCanvasAWT1;
+ openGLComponent2 = newtCanvasAWT2;
+ openGLAutoDrawable1 = glWindow1;
+ openGLAutoDrawable2 = glWindow2;
+
+ // group both OpenGL canvases / windows into a horizontal panel
+ final JPanel openGLPanel = new JPanel();
+ openGLPanel.setLayout(new BoxLayout(openGLPanel, BoxLayout.LINE_AXIS));
+ openGLPanel.add(openGLComponent1);
+ openGLPanel.add(Box.createHorizontalStrut(5));
+ openGLPanel.add(openGLComponent2);
+
+ final JPanel mainPanel = (JPanel) frame.getContentPane();
+ mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS));
+ mainPanel.add(Box.createHorizontalGlue());
+ mainPanel.add(openGLPanel);
+ mainPanel.add(Box.createHorizontalGlue());
+
+ final Animator animator = new Animator(Thread.currentThread().getThreadGroup());
+ animator.setUpdateFPSFrames(1, null);
+ animator.add(openGLAutoDrawable1);
+ animator.add(openGLAutoDrawable2);
+
+ // make the window visible using the EDT
+ SwingUtilities.invokeLater( new Runnable() {
+ public void run() {
+ frame.pack();
+ frame.setVisible(true);
+ }
+ });
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent1, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent2, true));
+
+ animator.start();
+
+ // sleep for test duration, then request the window to close, wait for the window to close,s and stop the animation
+ while(animator.isAnimating() && animator.getTotalFPSDuration() < durationPerTest) {
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+
+ // ask the EDT to dispose of the frame;
+ // if using newt, explicitly dispose of the canvases because otherwise it seems our destroy methods are not called
+ SwingUtilities.invokeLater( new Runnable() {
+ public void run() {
+ newtCanvasAWT1.destroy(); // removeNotify does not destroy GLWindow
+ newtCanvasAWT2.destroy(); // removeNotify does not destroy GLWindow
+ frame.dispose();
+ }
+ });
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent1, false));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(openGLComponent2, false));
+ }
+
+ static int atoi(final String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(final String[] args) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ if (++i < args.length) {
+ durationPerTest = atoi(args[i]);
+ }
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestMultipleNewtCanvasAWT.class.getName());
+ }
+
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java
index ef830b660..4d662c47f 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.opengl.*;
@@ -46,18 +48,19 @@ import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestRemoteGLWindows01NEWT extends UITestCase {
static int width = 640, height = 480;
static long durationPerTest = 100; // ms
static String remoteDisplay = "localhost:0.0";
- static GLWindow createWindow(Screen screen, GLCapabilities caps, GLEventListener demo)
+ static GLWindow createWindow(final Screen screen, final GLCapabilities caps, final GLEventListener demo)
throws InterruptedException
{
Assert.assertNotNull(caps);
//
// Create native windowing resources .. X11/Win/OSX
- //
+ //
GLWindow glWindow;
if(null!=screen) {
glWindow = GLWindow.create(screen, caps);
@@ -66,7 +69,7 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
}
-
+
glWindow.addGLEventListener(demo);
glWindow.setSize(512, 512);
@@ -77,7 +80,7 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
return glWindow;
}
- static void destroyWindow(GLWindow glWindow) {
+ static void destroyWindow(final GLWindow glWindow) {
if(null!=glWindow) {
glWindow.destroy();
Assert.assertEquals(false,glWindow.isNativeValid());
@@ -86,16 +89,16 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
@Test
public void testRemoteWindow01() throws InterruptedException {
- Animator animator = new Animator();
- GLProfile glpLocal = GLProfile.getGL2ES1();
+ final Animator animator = new Animator();
+ final GLProfile glpLocal = GLProfile.getGL2ES1();
Assert.assertNotNull(glpLocal);
- GLCapabilities capsLocal = new GLCapabilities(glpLocal);
+ final GLCapabilities capsLocal = new GLCapabilities(glpLocal);
Assert.assertNotNull(capsLocal);
- GearsES1 demoLocal = new GearsES1(1);
- GLWindow windowLocal = createWindow(null, capsLocal, demoLocal); // local with vsync
+ final GearsES1 demoLocal = new GearsES1(1);
+ final GLWindow windowLocal = createWindow(null, capsLocal, demoLocal); // local with vsync
Assert.assertEquals(true,windowLocal.isNativeValid());
Assert.assertEquals(true,windowLocal.isVisible());
- AbstractGraphicsDevice device1 = windowLocal.getScreen().getDisplay().getGraphicsDevice();
+ final AbstractGraphicsDevice device1 = windowLocal.getScreen().getDisplay().getGraphicsDevice();
System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1));
@@ -117,14 +120,14 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
GLProfile.initProfiles(deviceRemote); // just to make sure
System.err.println();
System.err.println("GLProfiles window2: "+deviceRemote.getConnection()+": "+GLProfile.glAvailabilityToString(deviceRemote));
- GLProfile glpRemote = GLProfile.get(deviceRemote, GLProfile.GL2ES1);
+ final GLProfile glpRemote = GLProfile.get(deviceRemote, GLProfile.GL2ES1);
Assert.assertNotNull(glpRemote);
- GLCapabilities capsRemote = new GLCapabilities(glpRemote);
+ final GLCapabilities capsRemote = new GLCapabilities(glpRemote);
Assert.assertNotNull(capsRemote);
screenRemote = NewtFactory.createScreen(displayRemote, 0); // screen 0
demoRemote = new GearsES1(0);
windowRemote = createWindow(screenRemote, capsRemote, demoRemote); // remote, no vsync
- } catch (NativeWindowException nwe) {
+ } catch (final NativeWindowException nwe) {
System.err.println(nwe);
Assume.assumeNoException(nwe);
destroyWindow(windowLocal);
@@ -135,7 +138,7 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
Assert.assertEquals(true,windowRemote.isVisible());
animator.add(windowRemote);
- animator.setUpdateFPSFrames(1, null);
+ animator.setUpdateFPSFrames(1, null);
animator.start();
while(animator.getTotalFPSDuration()<durationPerTest) {
@@ -150,15 +153,15 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
destroyWindow(windowRemote);
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
@@ -168,7 +171,7 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
}
System.out.println("durationPerTest: "+durationPerTest);
System.out.println("display: "+remoteDisplay);
- String tstname = TestRemoteGLWindows01NEWT.class.getName();
+ final String tstname = TestRemoteGLWindows01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java
index 53995e8f7..06e55a5eb 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
@@ -33,6 +33,8 @@ import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.nativewindow.*;
@@ -41,6 +43,7 @@ import java.io.IOException;
import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestRemoteWindow01NEWT extends UITestCase {
static int width, height;
static String remoteDisplay = "localhost:0.0";
@@ -52,15 +55,15 @@ public class TestRemoteWindow01NEWT extends UITestCase {
height = 480;
}
- static Window createWindow(Screen screen, Capabilities caps, int width, int height, boolean onscreen, boolean undecorated) {
+ static Window createWindow(final Screen screen, final Capabilities caps, final int width, final int height, final boolean onscreen, final boolean undecorated) {
Assert.assertNotNull(caps);
caps.setOnscreen(onscreen);
// System.out.println("Requested: "+caps);
//
// Create native windowing resources .. X11/Win/OSX
- //
- Window window = NewtFactory.createWindow(screen, caps);
+ //
+ final Window window = NewtFactory.createWindow(screen, caps);
Assert.assertNotNull(window);
window.setUndecorated(onscreen && undecorated);
window.setSize(width, height);
@@ -74,10 +77,10 @@ public class TestRemoteWindow01NEWT extends UITestCase {
// System.out.println("Created: "+window);
//
- // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
// equivalent to GLAutoDrawable methods: setVisible(true)
- //
- CapabilitiesImmutable chosenCapabilities = window.getGraphicsConfiguration().getChosenCapabilities();
+ //
+ final CapabilitiesImmutable chosenCapabilities = window.getGraphicsConfiguration().getChosenCapabilities();
Assert.assertNotNull(chosenCapabilities);
Assert.assertTrue(chosenCapabilities.getGreenBits()>5);
Assert.assertTrue(chosenCapabilities.getBlueBits()>5);
@@ -87,7 +90,7 @@ public class TestRemoteWindow01NEWT extends UITestCase {
return window;
}
- static void destroyWindow(Display display, Screen screen, Window window) {
+ static void destroyWindow(final Display display, final Screen screen, final Window window) {
if(null!=window) {
window.destroy();
}
@@ -101,10 +104,10 @@ public class TestRemoteWindow01NEWT extends UITestCase {
@Test
public void testRemoteWindow01() throws InterruptedException {
- Capabilities caps = new Capabilities();
- Display display1 = NewtFactory.createDisplay(null); // local display
- Screen screen1 = NewtFactory.createScreen(display1, 0); // screen 0
- Window window1 = createWindow(screen1, caps, width, height, true /* onscreen */, false /* undecorated */);
+ final Capabilities caps = new Capabilities();
+ final Display display1 = NewtFactory.createDisplay(null); // local display
+ final Screen screen1 = NewtFactory.createScreen(display1, 0); // screen 0
+ final Window window1 = createWindow(screen1, caps, width, height, true /* onscreen */, false /* undecorated */);
window1.setVisible(true);
Assert.assertEquals(true,window1.isNativeValid());
@@ -112,16 +115,16 @@ public class TestRemoteWindow01NEWT extends UITestCase {
// Remote Display/Device/Screen/Window ..
Display display2;
- AbstractGraphicsDevice device2;
+ final AbstractGraphicsDevice device2;
Screen screen2;
Window window2;
try {
display2 = NewtFactory.createDisplay(remoteDisplay);
- display2.createNative();
+ display2.createNative();
screen2 = NewtFactory.createScreen(display2, 0); // screen 0
window2 = createWindow(screen2, caps, width, height, true /* onscreen */, false /* undecorated */);
window2.setVisible(true);
- } catch (NativeWindowException nwe) {
+ } catch (final NativeWindowException nwe) {
System.err.println(nwe);
Assume.assumeNoException(nwe);
destroyWindow(display1, screen1, window1);
@@ -137,14 +140,14 @@ public class TestRemoteWindow01NEWT extends UITestCase {
destroyWindow(display2, screen2, window2);
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-display")) {
remoteDisplay = args[++i];
}
}
System.out.println("display: "+remoteDisplay);
- String tstname = TestRemoteWindow01NEWT.class.getName();
+ final String tstname = TestRemoteWindow01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java
deleted file mode 100644
index 577119bcd..000000000
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.opengl.test.junit.newt;
-
-import java.io.IOException;
-import javax.media.nativewindow.NativeWindowFactory;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.jogamp.newt.Display;
-import com.jogamp.newt.NewtFactory;
-import com.jogamp.newt.Screen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.MonitorMode;
-import com.jogamp.newt.util.ScreenModeUtil;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-import java.util.Iterator;
-import java.util.List;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.SurfaceSize;
-
-public class TestScreenMode00NEWT extends UITestCase {
- static int screenIdx = 0;
- static int width, height;
-
- static int waitTimeShort = 4; //1 sec
- static int waitTimeLong = 6; //6 sec
-
-
-
- @BeforeClass
- public static void initClass() {
- NativeWindowFactory.initSingleton();
- width = 640;
- height = 480;
- }
-
- @Test
- public void testScreenModeInfo00() throws InterruptedException {
- DimensionImmutable res = new Dimension(640, 480);
- SurfaceSize surfsz = new SurfaceSize(res, 32);
- DimensionImmutable mm = new Dimension(500, 400);
- MonitorMode mon = new MonitorMode(surfsz, mm, 60);
- ScreenMode sm_out = new ScreenMode(mon, 90);
- System.err.println("00 out: "+sm_out);
-
- int[] props = ScreenModeUtil.streamOut(sm_out);
- ScreenMode sm_in = ScreenModeUtil.streamIn(props, 0);
- System.err.println("00 in : "+sm_in);
-
- Assert.assertEquals(sm_in.getMonitorMode().getSurfaceSize().getResolution(),
- sm_out.getMonitorMode().getSurfaceSize().getResolution());
-
- Assert.assertEquals(sm_in.getMonitorMode().getSurfaceSize(),
- sm_out.getMonitorMode().getSurfaceSize());
-
- Assert.assertEquals(sm_in.getMonitorMode().getScreenSizeMM(),
- sm_out.getMonitorMode().getScreenSizeMM());
-
- Assert.assertEquals(sm_in.getMonitorMode(), sm_out.getMonitorMode());
-
- Assert.assertEquals(sm_in, sm_out);
-
- Assert.assertEquals(sm_out.hashCode(), sm_in.hashCode());
- }
-
- @Test
- public void testScreenModeInfo01() throws InterruptedException {
- Display dpy = NewtFactory.createDisplay(null);
- Screen screen = NewtFactory.createScreen(dpy, screenIdx);
- screen.addReference();
- Assert.assertEquals(true,screen.isNativeValid());
- Assert.assertEquals(true,screen.getDisplay().isNativeValid());
- System.err.println("Screen: "+screen.toString());
-
- List<ScreenMode> screenModes = screen.getScreenModes();
- Assert.assertTrue(screenModes.size()>0);
- int i=0;
- for(Iterator<ScreenMode> iter=screenModes.iterator(); iter.hasNext(); i++) {
- System.err.println(i+": "+iter.next());
- }
- ScreenMode sm_o = screen.getOriginalScreenMode();
- Assert.assertNotNull(sm_o);
- ScreenMode sm_c = screen.getCurrentScreenMode();
- Assert.assertNotNull(sm_c);
- System.err.println("orig SM: "+sm_o);
- System.err.println("curr SM: "+sm_c);
- System.err.println("curr sz: "+screen.getWidth()+"x"+screen.getHeight());
- Assert.assertEquals(sm_o, sm_c);
-
- screen.removeReference();
-
- Assert.assertEquals(false,screen.isNativeValid());
- Assert.assertEquals(false,screen.getDisplay().isNativeValid());
- }
-
- static int atoi(String a) {
- try {
- return Integer.parseInt(a);
- } catch (Exception ex) { throw new RuntimeException(ex); }
- }
-
- public static void main(String args[]) throws IOException {
- for(int i=0; i<args.length; i++) {
- if(args[i].equals("-screen")) {
- i++;
- screenIdx = atoi(args[i]);
- }
- }
- String tstname = TestScreenMode00NEWT.class.getName();
- org.junit.runner.JUnitCore.main(tstname);
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java
deleted file mode 100644
index b9f3e67dc..000000000
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java
+++ /dev/null
@@ -1,355 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.opengl.test.junit.newt;
-
-import java.io.IOException;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLProfile;
-
-import com.jogamp.opengl.util.Animator;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.jogamp.newt.Display;
-import com.jogamp.newt.NewtFactory;
-import com.jogamp.newt.Screen;
-import com.jogamp.newt.Window;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.newt.util.ScreenModeUtil;
-import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-
-import java.util.List;
-import javax.media.nativewindow.util.Dimension;
-
-/**
- * Demonstrates fullscreen with and without ScreenMode change.
- *
- * <p>
- * Also documents NV RANDR/GL bug, see {@link TestScreenMode01NEWT#cleanupGL()}.</p>
- */
-public class TestScreenMode01NEWT extends UITestCase {
- static GLProfile glp;
- static int width, height;
-
- static int waitTimeShort = 2000; // 2 sec
- static int waitTimeLong = 8000; // 8 sec
-
- @BeforeClass
- public static void initClass() {
- width = 640;
- height = 480;
- glp = GLProfile.getDefault();
- }
-
- @AfterClass
- public static void releaseClass() throws InterruptedException {
- Thread.sleep(waitTimeShort);
- }
-
- /**
- * Following configurations results in a SIGSEGV:
- * <pre>
- * Ubuntu 11.04 (natty), NV GTX 460, driver [280.10* - 285.03]
- * </pre>
- *
- * Situation:
- * <pre>
- * 1 - Create Screen, GLWindow (w/ context)
- * 2 - ScreenMode change
- * 3 - Destroy GLWindow (w/ context), Screen
- * 4 - Create Screen, GLWindow (w/ context) (*)
- * </pre>
- *
- * Step 4 causes the exception within 1st 'glXMakeContextCurrent(..)' call
- * on the the created GL context.
- *
- * Remedy:
- * <pre>
- * A) Releasing all resources before step 4 .. works.
- * B) Holding the native Display/Screen in NEWT also works (ie screen.addReference()).
- * </pre>
- *
- * Hence there must be some correlations with the screen randr mode
- * and some of the glcontext/gldrawables.
- *
- * <pre>
- * Remedy A) is demonstrated here
- * Remedy B) is shown in {@link TestScreenMode01bNEWT}
- * </pre>
- */
- @After
- public void cleanupGL() throws InterruptedException {
- GLProfile.shutdown();
- GLProfile.initSingleton();
- }
-
- static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) {
- Assert.assertNotNull(caps);
- caps.setOnscreen(onscreen);
-
- GLWindow window = GLWindow.create(screen, caps);
- window.setSize(width, height);
- window.addGLEventListener(new GearsES2());
- Assert.assertNotNull(window);
- window.setVisible(true);
- return window;
- }
-
- static void destroyWindow(Window window) {
- if(null!=window) {
- window.destroy();
- }
- }
-
- @Test
- public void testFullscreenChange01() throws InterruptedException {
- Thread.sleep(waitTimeShort);
- GLCapabilities caps = new GLCapabilities(glp);
- Assert.assertNotNull(caps);
- Display display = NewtFactory.createDisplay(null); // local display
- Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
- Assert.assertNotNull(screen);
-
- GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
- Animator animator = new Animator(window);
- animator.start();
-
- Assert.assertEquals(false, window.isFullscreen());
- Assert.assertEquals(width, window.getWidth());
- Assert.assertEquals(height, window.getHeight());
-
- window.setFullscreen(true);
- Assert.assertEquals(true, window.isFullscreen());
- Assert.assertEquals(window.getScreen().getWidth(), window.getWidth());
- Assert.assertEquals(window.getScreen().getHeight(), window.getHeight());
-
- Thread.sleep(waitTimeShort);
-
- window.setFullscreen(false);
- Assert.assertEquals(false, window.isFullscreen());
- Assert.assertEquals(width, window.getWidth());
- Assert.assertEquals(height, window.getHeight());
-
- Thread.sleep(waitTimeShort);
-
- animator.stop();
- destroyWindow(window);
- }
-
- @Test
- public void testScreenModeChange01() throws InterruptedException {
- Thread.sleep(waitTimeShort);
-
- GLCapabilities caps = new GLCapabilities(glp);
- Assert.assertNotNull(caps);
- Display display = NewtFactory.createDisplay(null); // local display
- Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
- Assert.assertNotNull(screen);
- GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
- Assert.assertNotNull(window);
-
- List<ScreenMode> screenModes = screen.getScreenModes();
- if(screenModes.size()==1) {
- // no support ..
- System.err.println("Your platform has no ScreenMode change support, sorry");
- destroyWindow(window);
- return;
- }
- Assert.assertTrue(screenModes.size()>0);
-
- Animator animator = new Animator(window);
- animator.start();
-
- ScreenMode smCurrent = screen.getCurrentScreenMode();
- Assert.assertNotNull(smCurrent);
- ScreenMode smOrig = screen.getOriginalScreenMode();
- Assert.assertNotNull(smOrig);
- Assert.assertEquals(smCurrent, smOrig);
- System.err.println("[0] current/orig: "+smCurrent);
-
- screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate());
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
- screenModes = ScreenModeUtil.filterByRotation(screenModes, 0);
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
- screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601));
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
-
- screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
-
- ScreenMode sm = (ScreenMode) screenModes.get(0);
- System.err.println("[0] set current: "+sm);
- screen.setCurrentScreenMode(sm);
- Assert.assertEquals(sm, screen.getCurrentScreenMode());
- Assert.assertNotSame(smOrig, screen.getCurrentScreenMode());
-
- Thread.sleep(waitTimeLong);
-
- // check reset ..
-
- Assert.assertEquals(true,display.isNativeValid());
- Assert.assertEquals(true,screen.isNativeValid());
- Assert.assertEquals(true,window.isNativeValid());
- Assert.assertEquals(true,window.isVisible());
-
- animator.stop();
- destroyWindow(window);
- Thread.sleep(waitTimeShort);
-
- Assert.assertEquals(false,window.isVisible());
- Assert.assertEquals(false,window.isNativeValid());
- Assert.assertEquals(false,screen.isNativeValid());
- Assert.assertEquals(false,display.isNativeValid());
-
- screen.createNative(); // trigger native re-creation
-
- Assert.assertEquals(true,display.isNativeValid());
- Assert.assertEquals(true,screen.isNativeValid());
-
- smCurrent = screen.getCurrentScreenMode();
- System.err.println("[1] current/orig: "+smCurrent);
-
- Assert.assertNotNull(smCurrent);
- Assert.assertEquals(smCurrent, smOrig);
-
- screen.destroy();
-
- Assert.assertEquals(false,screen.isNativeValid());
- Assert.assertEquals(false,display.isNativeValid());
- }
-
- @Test
- public void testScreenModeChangeWithFS01Pre() throws InterruptedException {
- Thread.sleep(waitTimeShort);
- testScreenModeChangeWithFS01Impl(true) ;
- }
-
- @Test
- public void testScreenModeChangeWithFS01Post() throws InterruptedException {
- Thread.sleep(waitTimeShort);
- testScreenModeChangeWithFS01Impl(false) ;
- }
-
- protected void testScreenModeChangeWithFS01Impl(boolean preFS) throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glp);
- Display display = NewtFactory.createDisplay(null); // local display
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
- GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
- Animator animator = new Animator(window);
- animator.start();
-
- ScreenMode smCurrent = screen.getCurrentScreenMode();
- Assert.assertNotNull(smCurrent);
- ScreenMode smOrig = screen.getOriginalScreenMode();
- Assert.assertNotNull(smOrig);
- Assert.assertEquals(smCurrent, smOrig);
- System.err.println("[0] current/orig: "+smCurrent);
-
- List<ScreenMode> screenModes = screen.getScreenModes();
- if(screenModes.size()==1) {
- // no support ..
- destroyWindow(window);
- return;
- }
- Assert.assertTrue(screenModes.size()>0);
- screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate());
- screenModes = ScreenModeUtil.filterByRotation(screenModes, 0);
- screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601));
- screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
-
- ScreenMode screenMode = (ScreenMode) screenModes.get(0);
- Assert.assertNotNull(screenMode);
-
- if(preFS) {
- System.err.println("[0] set FS pre 0: "+window.isFullscreen());
- window.setFullscreen(true);
- System.err.println("[0] set FS pre 1: "+window.isFullscreen());
- Assert.assertEquals(true, window.isFullscreen());
- System.err.println("[0] set FS pre X: "+window.isFullscreen());
- }
-
- System.err.println("[0] set current: "+screenMode);
- screen.setCurrentScreenMode(screenMode);
-
- if(!preFS) {
- System.err.println("[0] set FS post 0: "+window.isFullscreen());
- window.setFullscreen(true);
- Assert.assertEquals(true, window.isFullscreen());
- System.err.println("[0] set FS post X: "+window.isFullscreen());
- }
-
- Thread.sleep(waitTimeLong);
-
- // check reset ..
-
- Assert.assertEquals(true,display.isNativeValid());
- Assert.assertEquals(true,screen.isNativeValid());
- Assert.assertEquals(true,window.isNativeValid());
- Assert.assertEquals(true,window.isVisible());
-
- animator.stop();
- destroyWindow(window);
- Thread.sleep(waitTimeShort);
-
- Assert.assertEquals(false,window.isVisible());
- Assert.assertEquals(false,window.isNativeValid());
- Assert.assertEquals(false,screen.isNativeValid());
- Assert.assertEquals(false,display.isNativeValid());
-
- screen.createNative(); // trigger native re-creation
-
- Assert.assertEquals(true,display.isNativeValid());
- Assert.assertEquals(true,screen.isNativeValid());
-
- smCurrent = screen.getCurrentScreenMode();
- System.err.println("[1] current/orig: "+smCurrent);
-
- Assert.assertNotNull(smCurrent);
- Assert.assertEquals(smCurrent, smOrig);
-
- screen.destroy();
- }
-
- public static void main(String args[]) throws IOException {
- String tstname = TestScreenMode01NEWT.class.getName();
- org.junit.runner.JUnitCore.main(tstname);
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java
deleted file mode 100644
index 38612faa8..000000000
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.opengl.test.junit.newt;
-
-import java.io.IOException;
-import javax.media.nativewindow.NativeWindowFactory;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLProfile;
-
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.jogamp.newt.Display;
-import com.jogamp.newt.NewtFactory;
-import com.jogamp.newt.Screen;
-import com.jogamp.newt.Window;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.newt.util.ScreenModeUtil;
-import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-
-import java.util.List;
-import javax.media.nativewindow.util.Dimension;
-
-/**
- * Documents remedy B) for NV RANDR/GL bug
- *
- * @see TestScreenMode01NEWT#cleanupGL()
- */
-public class TestScreenMode01bNEWT extends UITestCase {
- static GLProfile glp;
- static int width, height;
-
- static int waitTimeShort = 2000;
- static int waitTimeLong = 2000;
-
- @BeforeClass
- public static void initClass() {
- width = 100;
- height = 100;
- glp = GLProfile.getDefault();
- }
-
- @AfterClass
- public static void releaseClass() throws InterruptedException {
- Thread.sleep(waitTimeShort);
- }
-
- static Window createWindow(Screen screen, GLCapabilities caps, String name, int x, int y, int width, int height) {
- Assert.assertNotNull(caps);
-
- GLWindow window = GLWindow.create(screen, caps);
- // Window window = NewtFactory.createWindow(screen, caps);
- window.setTitle(name);
- window.setPosition(x, y);
- window.setSize(width, height);
- window.addGLEventListener(new GearsES2());
- Assert.assertNotNull(window);
- window.setVisible(true);
- return window;
- }
-
- static void destroyWindow(Window window) {
- if(null!=window) {
- window.destroy();
- }
- }
-
- @Test
- public void testScreenModeChange01() throws InterruptedException {
- Thread.sleep(waitTimeShort);
-
- GLCapabilities caps = new GLCapabilities(glp);
- Assert.assertNotNull(caps);
- Display display = NewtFactory.createDisplay(null); // local display
- Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
- Assert.assertNotNull(screen);
- Window window0 = createWindow(screen, caps, "win0", 0, 0, width, height);
- Assert.assertNotNull(window0);
-
- List<ScreenMode> screenModes = screen.getScreenModes();
- if(screenModes.size()==1) {
- // no support ..
- System.err.println("Your platform has no ScreenMode change support, sorry");
- destroyWindow(window0);
- return;
- }
- Assert.assertTrue(screenModes.size()>0);
-
- ScreenMode smCurrent = screen.getCurrentScreenMode();
- Assert.assertNotNull(smCurrent);
- ScreenMode smOrig = screen.getOriginalScreenMode();
- Assert.assertNotNull(smOrig);
- Assert.assertEquals(smCurrent, smOrig);
- System.err.println("[0] current/orig: "+smCurrent);
-
- screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate());
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
- screenModes = ScreenModeUtil.filterByRotation(screenModes, 0);
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
- screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601));
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
-
- screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
-
- ScreenMode sm = (ScreenMode) screenModes.get(0);
- System.err.println("[0] set current: "+sm);
- screen.setCurrentScreenMode(sm);
- Assert.assertEquals(sm, screen.getCurrentScreenMode());
- Assert.assertNotSame(smOrig, screen.getCurrentScreenMode());
-
- Thread.sleep(waitTimeShort);
-
- // check reset ..
-
- Assert.assertEquals(true,display.isNativeValid());
- Assert.assertEquals(true,screen.isNativeValid());
- Assert.assertEquals(true,window0.isNativeValid());
- Assert.assertEquals(true,window0.isVisible());
-
- screen.addReference(); // keep it alive !
- screen.setCurrentScreenMode(smOrig);
-
- destroyWindow(window0);
- Assert.assertEquals(false,window0.isVisible());
- Assert.assertEquals(false,window0.isNativeValid());
- Assert.assertEquals(true,screen.isNativeValid()); // alive !
- Assert.assertEquals(true,display.isNativeValid());
-
- Thread.sleep(waitTimeShort);
-
- Window window1 = createWindow(screen, caps, "win1",
- width+window0.getInsets().getTotalWidth(), 0,
- width, height);
- Assert.assertNotNull(window1);
- Assert.assertEquals(true,window1.isNativeValid());
- Assert.assertEquals(true,window1.isVisible());
-
- Thread.sleep(waitTimeShort);
-
- destroyWindow(window1);
- Assert.assertEquals(false,window1.isNativeValid());
- Assert.assertEquals(false,window1.isVisible());
-
- screen.removeReference();
- Assert.assertEquals(false,screen.isNativeValid());
- Assert.assertEquals(false,display.isNativeValid());
- }
-
- public static void main(String args[]) throws IOException {
- String tstname = TestScreenMode01bNEWT.class.getName();
- org.junit.runner.JUnitCore.main(tstname);
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java
deleted file mode 100644
index 1c9cb91f3..000000000
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.opengl.test.junit.newt;
-
-import java.io.IOException;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLProfile;
-
-import com.jogamp.opengl.util.Animator;
-
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.jogamp.newt.Display;
-import com.jogamp.newt.NewtFactory;
-import com.jogamp.newt.Screen;
-import com.jogamp.newt.Window;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.newt.util.ScreenModeUtil;
-import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-import java.util.List;
-import javax.media.nativewindow.util.Dimension;
-
-public class TestScreenMode02NEWT extends UITestCase {
- static GLProfile glp;
- static int width, height;
-
- static int waitTimeShort = 2000; // 2 sec
- static int waitTimeLong = 8000; // 8 sec
-
- @BeforeClass
- public static void initClass() {
- width = 640;
- height = 480;
- glp = GLProfile.getDefault();
- }
-
- @AfterClass
- public static void releaseClass() throws InterruptedException {
- Thread.sleep(waitTimeShort);
- }
-
- static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) {
- Assert.assertNotNull(caps);
- caps.setOnscreen(onscreen);
-
- GLWindow window = GLWindow.create(screen, caps);
- window.setSize(width, height);
- window.addGLEventListener(new GearsES2());
- Assert.assertNotNull(window);
- window.setVisible(true);
- Assert.assertTrue(window.isVisible());
- return window;
- }
-
- static void destroyWindow(Window window) {
- if(null!=window) {
- window.destroy();
- }
- }
-
- @Test
- public void testScreenRotationChange01() throws InterruptedException {
- Thread.sleep(waitTimeShort);
-
- GLCapabilities caps = new GLCapabilities(glp);
- Assert.assertNotNull(caps);
- Display display = NewtFactory.createDisplay(null); // local display
- Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
- Assert.assertNotNull(screen);
- GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
- Assert.assertNotNull(window);
-
- List<ScreenMode> screenModes = screen.getScreenModes();
- if(screenModes.size()==1) {
- // no support ..
- System.err.println("Your platform has no ScreenMode change support, sorry");
- destroyWindow(window);
- return;
- }
- Assert.assertTrue(screenModes.size()>0);
-
- Animator animator = new Animator(window);
- animator.start();
-
- ScreenMode smCurrent = screen.getCurrentScreenMode();
- Assert.assertNotNull(smCurrent);
- ScreenMode smOrig = screen.getOriginalScreenMode();
- Assert.assertNotNull(smOrig);
- Assert.assertEquals(smCurrent, smOrig);
- System.err.println("[0] current/orig: "+smCurrent);
-
- screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate());
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
- screenModes = ScreenModeUtil.filterByRotation(screenModes, 90);
- if(null==screenModes) {
- // no rotation support ..
- System.err.println("Your platform has no rotation support, sorry");
- destroyWindow(window);
- return;
- }
- Assert.assertTrue(screenModes.size()>0);
- screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601));
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
- screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
- Assert.assertNotNull(screenModes);
- Assert.assertTrue(screenModes.size()>0);
-
- ScreenMode sm = (ScreenMode) screenModes.get(0);
- System.err.println("[0] set current: "+sm);
- screen.setCurrentScreenMode(sm);
- Assert.assertEquals(sm, screen.getCurrentScreenMode());
- Assert.assertNotSame(smOrig, screen.getCurrentScreenMode());
-
- Thread.sleep(waitTimeLong);
-
- // check reset ..
-
- Assert.assertEquals(true,display.isNativeValid());
- Assert.assertEquals(true,screen.isNativeValid());
- Assert.assertEquals(true,window.isNativeValid());
- Assert.assertEquals(true,window.isVisible());
-
- animator.stop();
- destroyWindow(window);
-
- Assert.assertEquals(false,window.isVisible());
- Assert.assertEquals(false,window.isNativeValid());
- Assert.assertEquals(false,screen.isNativeValid());
- Assert.assertEquals(false,display.isNativeValid());
-
- screen.createNative(); // trigger native re-creation
-
- Assert.assertEquals(true,display.isNativeValid());
- Assert.assertEquals(true,screen.isNativeValid());
-
- smCurrent = screen.getCurrentScreenMode();
- System.err.println("[1] current/orig: "+smCurrent);
-
- Assert.assertNotNull(smCurrent);
- Assert.assertEquals(smCurrent, smOrig);
-
- screen.destroy();
-
- Assert.assertEquals(false,screen.isNativeValid());
- Assert.assertEquals(false,display.isNativeValid());
- }
-
- public static void main(String args[]) throws IOException {
- String tstname = TestScreenMode02NEWT.class.getName();
- org.junit.runner.JUnitCore.main(tstname);
- }
-
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowAndPointerIconNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowAndPointerIconNEWT.java
new file mode 100644
index 000000000..75e63f7a7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowAndPointerIconNEWT.java
@@ -0,0 +1,142 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.opengl.GLCapabilities;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.junit.util.SingletonJunitCase;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Display.PointerIcon;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestWindowAndPointerIconNEWT extends SingletonJunitCase {
+
+ static long duration = 1000; // ms
+
+ // As early as possible
+ static {
+ setPointerIcons();
+ }
+
+ static void setPointerIcons() {
+ final Properties sysp = System.getProperties();
+ sysp.put("jnlp.newt.window.icons", "red-16x16.png red-32x32.png");
+ }
+
+ @AfterClass
+ public static void unsetPointerIcons() {
+ final Properties sysp = System.getProperties();
+ sysp.remove("jnlp.newt.window.icons");
+ }
+
+ @Test
+ public void test() throws InterruptedException {
+ final GLWindow glWindow = GLWindow.create(new GLCapabilities(null));
+ Assert.assertNotNull(glWindow);
+
+ glWindow.setSize(800, 600);
+
+ final GearsES2 demo = new GearsES2(1);
+ glWindow.addGLEventListener(demo);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ final PointerIcon pointerIcon;
+ {
+ final Display disp = glWindow.getScreen().getDisplay();
+ disp.createNative();
+ final int idx = 0;
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-red-alpha-64x64.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 0, 0);
+ System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ pointerIcon = _pointerIcon;
+ }
+ }
+ glWindow.setPointerIcon(pointerIcon);
+ System.err.println("Set PointerIcon: "+glWindow.getPointerIcon());
+
+ final Animator animator = new Animator();
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.add(glWindow);
+ animator.start();
+
+ glWindow.setVisible(true);
+ glWindow.warpPointer(3*glWindow.getSurfaceWidth()/4, 3*glWindow.getSurfaceHeight()/4);
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1-t0<duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+
+ glWindow.destroy();
+ if( NativeWindowFactory.isAWTAvailable() ) {
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
+ }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ org.junit.runner.JUnitCore.main(TestWindowAndPointerIconNEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java
index d63f0d2a7..40b60ac69 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -29,32 +29,35 @@
package com.jogamp.opengl.test.junit.newt;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import org.junit.Assert;
import java.lang.reflect.InvocationTargetException;
import java.awt.Frame;
+
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
-
+import javax.swing.WindowConstants;
import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
-
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestWindowClosingProtocol01AWT extends UITestCase {
@Test
public void testCloseFrameGLCanvas() throws InterruptedException, InvocationTargetException {
final Frame frame = new Frame("testCloseFrameGLCanvas AWT");
-
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
+ final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
final GLCanvas glCanvas = new GLCanvas(caps);
glCanvas.addGLEventListener(new GearsES2());
SwingUtilities.invokeAndWait(new Runnable() {
@@ -74,12 +77,14 @@ public class TestWindowClosingProtocol01AWT extends UITestCase {
WindowClosingMode op = glCanvas.getDefaultCloseOperation();
Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op);
- Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); // nop
+ Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // nop
Thread.sleep(100);
- Assert.assertEquals(true, frame.isDisplayable());
+ Assert.assertEquals(true, frame.isDisplayable());
Assert.assertEquals(true, frame.isVisible());
- Assert.assertEquals(true, glCanvas.isValid());
- Assert.assertEquals(true, glCanvas.isDisplayable());
+ Assert.assertEquals(true, glCanvas.isValid());
+ Assert.assertEquals(true, glCanvas.isDisplayable());
+ Assert.assertEquals(true, closingListener.isWindowClosing());
+ Assert.assertEquals(false, closingListener.isWindowClosed());
//
// close with op (GLCanvas): DISPOSE_ON_CLOSE -> dispose
@@ -88,10 +93,17 @@ public class TestWindowClosingProtocol01AWT extends UITestCase {
op = glCanvas.getDefaultCloseOperation();
Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op);
- Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); // no frame close
- Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, false));
+ Thread.sleep(300);
+
+ Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // no frame close, but GLCanvas's GL resources will be destroyed
+ Thread.sleep(100);
Assert.assertEquals(true, frame.isDisplayable());
Assert.assertEquals(true, frame.isVisible());
+ Assert.assertEquals(true, closingListener.isWindowClosing());
+ Assert.assertEquals(false, closingListener.isWindowClosed());
+ for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && glCanvas.isRealized(); wait++) {
+ Thread.sleep(AWTRobotUtil.TIME_SLICE);
+ }
Assert.assertEquals(false, glCanvas.isRealized());
SwingUtilities.invokeAndWait(new Runnable() {
@@ -103,17 +115,18 @@ public class TestWindowClosingProtocol01AWT extends UITestCase {
@Test
public void testCloseJFrameGLCanvas() throws InterruptedException, InvocationTargetException {
final JFrame frame = new JFrame("testCloseJFrameGLCanvas AWT");
+ final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame);
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
- GLCanvas glCanvas = new GLCanvas(caps);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final GLCanvas glCanvas = new GLCanvas(caps);
glCanvas.addGLEventListener(new GearsES2());
- frame.getContentPane().add(glCanvas);
- frame.pack();
- frame.setSize(512, 512);
- frame.validate();
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.getContentPane().add(glCanvas);
+ frame.pack();
+ frame.setSize(512, 512);
+ frame.validate();
frame.setVisible(true);
} });
Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
@@ -122,13 +135,16 @@ public class TestWindowClosingProtocol01AWT extends UITestCase {
//
// close with op: DO_NOTHING_ON_CLOSE -> NOP / HIDE (default)
//
- Assert.assertEquals(JFrame.HIDE_ON_CLOSE, frame.getDefaultCloseOperation());
+ Assert.assertEquals(WindowConstants.HIDE_ON_CLOSE, frame.getDefaultCloseOperation());
WindowClosingMode op = glCanvas.getDefaultCloseOperation();
Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op);
- Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); // nop
- Thread.sleep(100);
+ Thread.sleep(300);
+
+ Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // hide
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); // hide -> invisible
Assert.assertEquals(true, frame.isDisplayable());
+ Assert.assertEquals(false, frame.isVisible());
Assert.assertEquals(true, glCanvas.isValid());
Assert.assertEquals(true, glCanvas.isDisplayable());
@@ -138,16 +154,18 @@ public class TestWindowClosingProtocol01AWT extends UITestCase {
} });
Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true));
+ Assert.assertEquals(true, frame.isDisplayable());
+ Assert.assertEquals(true, frame.isVisible());
//
// close with op (JFrame): DISPOSE_ON_CLOSE -- GLCanvas --> dispose
//
- frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
- Assert.assertEquals(JFrame.DISPOSE_ON_CLOSE, frame.getDefaultCloseOperation());
+ frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ Assert.assertEquals(WindowConstants.DISPOSE_ON_CLOSE, frame.getDefaultCloseOperation());
op = glCanvas.getDefaultCloseOperation();
Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op);
- Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, closingListener));
Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, false));
Assert.assertEquals(false, frame.isDisplayable());
Assert.assertEquals(false, glCanvas.isValid());
@@ -155,8 +173,8 @@ public class TestWindowClosingProtocol01AWT extends UITestCase {
Assert.assertEquals(false, glCanvas.isRealized());
}
- public static void main(String[] args) {
- String tstname = TestWindowClosingProtocol01AWT.class.getName();
+ public static void main(final String[] args) {
+ final String tstname = TestWindowClosingProtocol01AWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java
index 1657fcbe9..ab57065b9 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.newt;
import java.lang.reflect.InvocationTargetException;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import org.junit.Assert;
import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
@@ -45,14 +47,15 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestWindowClosingProtocol02NEWT extends UITestCase {
@Test
public void testCloseGLWindow() throws InterruptedException, InvocationTargetException {
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
final GLWindow glWindow = GLWindow.create(caps);
- final AWTRobotUtil.WindowClosingListener windowClosingListener = AWTRobotUtil.addClosingListener(glWindow);
+ final AWTRobotUtil.WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(glWindow);
glWindow.addGLEventListener(new GearsES2());
glWindow.setSize(512, 512);
@@ -70,10 +73,12 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase {
op = glWindow.getDefaultCloseOperation();
Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op);
- Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, false)); // nop
+ Thread.sleep(300);
+
+ Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, false, closingListener)); // nop
Assert.assertEquals(true, glWindow.isNativeValid());
- Assert.assertEquals(true, windowClosingListener.isWindowClosing());
- windowClosingListener.reset();
+ Assert.assertEquals(true, closingListener.isWindowClosing());
+ closingListener.reset();
//
// close with op (GLCanvas): DISPOSE_ON_CLOSE -> dispose
@@ -82,13 +87,13 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase {
op = glWindow.getDefaultCloseOperation();
Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op);
- Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, true));
+ Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, true, closingListener));
Assert.assertEquals(false, glWindow.isNativeValid());
- Assert.assertEquals(true, windowClosingListener.isWindowClosing());
+ Assert.assertEquals(true, closingListener.isWindowClosing());
}
- public static void main(String[] args) {
- String tstname = TestWindowClosingProtocol02NEWT.class.getName();
+ public static void main(final String[] args) {
+ final String tstname = TestWindowClosingProtocol02NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java
index 65068e9e8..e458862d0 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -30,33 +30,38 @@ package com.jogamp.opengl.test.junit.newt;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.opengl.GLWindow;
+
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import org.junit.Assert;
import java.lang.reflect.InvocationTargetException;
+
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
-
+import javax.swing.WindowConstants;
import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
-
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestWindowClosingProtocol03NewtAWT extends UITestCase {
@Test
public void testCloseJFrameNewtCanvasAWT() throws InterruptedException, InvocationTargetException {
final JFrame frame = new JFrame("testCloseJFrameNewtCanvasAWT");
+ final WindowClosingListener awtClosingListener = AWTRobotUtil.addClosingListener(frame);
- GLProfile glp = GLProfile.getGL2ES2();
- GLCapabilities caps = new GLCapabilities(glp);
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities caps = new GLCapabilities(glp);
final GLWindow glWindow = GLWindow.create(caps);
- final AWTRobotUtil.WindowClosingListener windowClosingListener = AWTRobotUtil.addClosingListener(glWindow);
+ final AWTRobotUtil.WindowClosingListener newtClosingListener = AWTRobotUtil.addClosingListener(glWindow);
glWindow.addGLEventListener(new GearsES2());
@@ -81,46 +86,64 @@ public class TestWindowClosingProtocol03NewtAWT extends UITestCase {
//
// close with op: DO_NOTHING_ON_CLOSE -> NOP / HIDE (default)
//
- Assert.assertEquals(JFrame.HIDE_ON_CLOSE, frame.getDefaultCloseOperation());
- WindowClosingMode op = newtCanvas.getDefaultCloseOperation();
- Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op);
+ {
+ Assert.assertEquals(WindowConstants.HIDE_ON_CLOSE, frame.getDefaultCloseOperation());
+ final WindowClosingMode op = newtCanvas.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op);
+ }
+
+ Thread.sleep(300);
- Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false));
+ Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, awtClosingListener)); // hide
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); // hide -> invisible
Assert.assertEquals(true, frame.isDisplayable());
Assert.assertEquals(false, frame.isVisible());
Assert.assertEquals(true, newtCanvas.isValid());
Assert.assertEquals(true, newtCanvas.isDisplayable());
Assert.assertEquals(true, glWindow.isNativeValid());
- Assert.assertEquals(true, windowClosingListener.isWindowClosing());
- windowClosingListener.reset();
+ Assert.assertEquals(true, awtClosingListener.isWindowClosing());
+ Assert.assertEquals(false, awtClosingListener.isWindowClosed());
+ Assert.assertEquals(true, newtClosingListener.isWindowClosing());
+ Assert.assertEquals(false, newtClosingListener.isWindowClosed());
+ awtClosingListener.reset();
+ newtClosingListener.reset();
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.setVisible(true);
} });
Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true));
Assert.assertEquals(true, frame.isDisplayable());
Assert.assertEquals(true, frame.isVisible());
-
+
//
// close with op (JFrame): DISPOSE_ON_CLOSE -- newtCanvas -- glWindow --> dispose
//
- frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
- Assert.assertEquals(JFrame.DISPOSE_ON_CLOSE, frame.getDefaultCloseOperation());
- op = newtCanvas.getDefaultCloseOperation();
- Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op);
+ {
+ frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ Assert.assertEquals(WindowConstants.DISPOSE_ON_CLOSE, frame.getDefaultCloseOperation());
+ final WindowClosingMode op = newtCanvas.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op);
+ }
+
+ Thread.sleep(300);
- Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true));
+ Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, awtClosingListener));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false));
Assert.assertEquals(false, frame.isDisplayable());
Assert.assertEquals(false, frame.isVisible());
Assert.assertEquals(false, newtCanvas.isValid());
Assert.assertEquals(false, newtCanvas.isDisplayable());
Assert.assertEquals(false, glWindow.isNativeValid());
- Assert.assertEquals(true, windowClosingListener.isWindowClosing());
+ Assert.assertEquals(true, awtClosingListener.isWindowClosing());
+ Assert.assertEquals(true, awtClosingListener.isWindowClosed());
+ Assert.assertEquals(true, newtClosingListener.isWindowClosing());
+ Assert.assertEquals(true, newtClosingListener.isWindowClosed());
}
- public static void main(String[] args) {
- String tstname = TestWindowClosingProtocol03NewtAWT.class.getName();
+ public static void main(final String[] args) {
+ final String tstname = TestWindowClosingProtocol03NewtAWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java
index e03b5e7d6..153da2666 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.nativewindow.*;
@@ -39,6 +41,7 @@ import java.io.IOException;
import com.jogamp.opengl.test.junit.util.UITestCase;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestWindows01NEWT extends UITestCase {
static int width, height;
@@ -49,20 +52,20 @@ public class TestWindows01NEWT extends UITestCase {
height = 256;
}
- static Window createWindow(Capabilities caps, int x, int y, int width, int height, boolean onscreen, boolean undecorated) throws InterruptedException {
+ static Window createWindow(final Capabilities caps, final int x, final int y, final int width, final int height, final boolean onscreen, final boolean undecorated) throws InterruptedException {
final boolean userPos = x>=0 && y>=0 ; // user has specified a position
-
+
Assert.assertNotNull(caps);
caps.setOnscreen(onscreen);
// System.out.println("Requested: "+caps);
//
// Create native windowing resources .. X11/Win/OSX
- //
- Window window = NewtFactory.createWindow(caps);
+ //
+ final Window window = NewtFactory.createWindow(caps);
Assert.assertNotNull(window);
- Screen screen = window.getScreen();
- Display display = screen.getDisplay();
+ final Screen screen = window.getScreen();
+ final Display display = screen.getDisplay();
window.setUndecorated(onscreen && undecorated);
if(userPos) {
window.setPosition(x, y);
@@ -72,8 +75,8 @@ public class TestWindows01NEWT extends UITestCase {
Assert.assertEquals(false,window.isVisible());
window.setVisible(true);
// System.err.println("************* Created: "+window);
-
- Assert.assertEquals(true,display.isNativeValid());
+
+ Assert.assertEquals(true,display.isNativeValid());
Assert.assertEquals(true,screen.isNativeValid());
Assert.assertEquals(true,window.isVisible());
Assert.assertEquals(true,window.isNativeValid());
@@ -89,22 +92,22 @@ public class TestWindows01NEWT extends UITestCase {
Assert.assertEquals(y, window.getY());
} */
- CapabilitiesImmutable chosenCapabilities = window.getGraphicsConfiguration().getChosenCapabilities();
+ final CapabilitiesImmutable chosenCapabilities = window.getGraphicsConfiguration().getChosenCapabilities();
Assert.assertNotNull(chosenCapabilities);
Assert.assertTrue(chosenCapabilities.getGreenBits()>=5);
Assert.assertTrue(chosenCapabilities.getBlueBits()>=5);
Assert.assertTrue(chosenCapabilities.getRedBits()>=5);
Assert.assertEquals(chosenCapabilities.isOnscreen(),onscreen);
-
+
return window;
}
- static void destroyWindow(Window window, boolean last) {
+ static void destroyWindow(final Window window, final boolean last) {
if(null==window) {
return;
}
- Screen screen = window.getScreen();
- Display display = screen.getDisplay();
+ final Screen screen = window.getScreen();
+ final Display display = screen.getDisplay();
window.destroy();
// System.err.println("************* Destroyed: "+window);
if(last) {
@@ -112,7 +115,7 @@ public class TestWindows01NEWT extends UITestCase {
Assert.assertEquals(false,display.isNativeValid());
} else {
Assert.assertEquals(true,screen.isNativeValid());
- Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,display.isNativeValid());
}
Assert.assertEquals(false,window.isNativeValid());
Assert.assertEquals(false,window.isVisible());
@@ -121,31 +124,31 @@ public class TestWindows01NEWT extends UITestCase {
@Test
public void testWindowDecorSimpleWMPos() throws InterruptedException {
- Capabilities caps = new Capabilities();
+ final Capabilities caps = new Capabilities();
Assert.assertNotNull(caps);
- Window window = createWindow(caps, -1, -1, width, height, true /* onscreen */, false /* undecorated */);
+ final Window window = createWindow(caps, -1, -1, width, height, true /* onscreen */, false /* undecorated */);
destroyWindow(window, true);
}
@Test
public void testWindowDecorSimpleUserPos() throws InterruptedException {
- Capabilities caps = new Capabilities();
+ final Capabilities caps = new Capabilities();
Assert.assertNotNull(caps);
- Window window = createWindow(caps, 100, 100, width, height, true /* onscreen */, false /* undecorated */);
+ final Window window = createWindow(caps, 100, 100, width, height, true /* onscreen */, false /* undecorated */);
destroyWindow(window, true);
}
@Test
public void testWindowNativeRecreate01Simple() throws InterruptedException {
- Capabilities caps = new Capabilities();
+ final Capabilities caps = new Capabilities();
Assert.assertNotNull(caps);
- Window window = createWindow(caps, -1, -1, width, height, true /* onscreen */, false /* undecorated */);
+ final Window window = createWindow(caps, -1, -1, width, height, true /* onscreen */, false /* undecorated */);
destroyWindow(window, true);
-
+
window.setVisible(true);
Assert.assertEquals(true,window.isNativeValid());
Assert.assertEquals(true,window.isVisible());
@@ -154,30 +157,30 @@ public class TestWindows01NEWT extends UITestCase {
destroyWindow(window, true);
}
-
+
@Test
public void testWindowDecorDestroyWinTwiceA() throws InterruptedException {
- Capabilities caps = new Capabilities();
+ final Capabilities caps = new Capabilities();
Assert.assertNotNull(caps);
- Window window = createWindow(caps, -1, -1, width, height, true /* onscreen */, false /* undecorated */);
+ final Window window = createWindow(caps, -1, -1, width, height, true /* onscreen */, false /* undecorated */);
destroyWindow(window, true);
destroyWindow(window, true);
}
@Test
public void testWindowDecorTwoWin() throws InterruptedException {
- Capabilities caps = new Capabilities();
+ final Capabilities caps = new Capabilities();
Assert.assertNotNull(caps);
- Window window1 = createWindow(caps, -1, -1, width, height, true /* onscreen */, false /* undecorated */);
- Window window2 = createWindow(caps, 100, 100, width, height, true /* onscreen */, false /* undecorated */);
+ final Window window1 = createWindow(caps, -1, -1, width, height, true /* onscreen */, false /* undecorated */);
+ final Window window2 = createWindow(caps, 100, 100, width, height, true /* onscreen */, false /* undecorated */);
destroyWindow(window2, false);
destroyWindow(window1, true);
}
- public static void main(String args[]) throws IOException {
- String tstname = TestWindows01NEWT.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestWindows01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom1.java b/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom1.java
index 609d443aa..2b6356e14 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom1.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom1.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,23 +20,23 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
import com.jogamp.newt.event.*;
class WindowEventCom1 extends WindowAdapter {
- public void windowResized(WindowEvent e) {
- e.setAttachment(new String("WindowEventCom1.windowResized: "+e));
+ public void windowResized(final WindowEvent e) {
+ e.setAttachment("WindowEventCom1.windowResized: "+e);
}
- public void windowMoved(WindowEvent e) {
- e.setAttachment(new String("WindowEventCom1.windowMoved: "+e));
+ public void windowMoved(final WindowEvent e) {
+ e.setAttachment("WindowEventCom1.windowMoved: "+e);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom2.java b/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom2.java
index d15a3ccd8..bc0415756 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom2.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom2.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,28 +20,28 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
import com.jogamp.newt.event.*;
class WindowEventCom2 extends WindowAdapter {
- public void windowResized(WindowEvent e) {
- String str = (String) e.getAttachment();
+ public void windowResized(final WindowEvent e) {
+ final String str = (String) e.getAttachment();
if(null==str) {
- e.setAttachment(new String("WindowEventCom2.windowResized: "+e));
+ e.setAttachment("WindowEventCom2.windowResized: "+e);
}
}
- public void windowMoved(WindowEvent e) {
- String str = (String) e.getAttachment();
+ public void windowMoved(final WindowEvent e) {
+ final String str = (String) e.getAttachment();
if(null==str) {
- e.setAttachment(new String("WindowEventCom2.windowMoved: "+e));
+ e.setAttachment("WindowEventCom2.windowMoved: "+e);
}
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom3.java b/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom3.java
index 87e5eccbb..d3dd6b5f9 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom3.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/WindowEventCom3.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,24 +20,24 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt;
import com.jogamp.newt.event.*;
class WindowEventCom3 extends WindowAdapter {
- public void windowResized(WindowEvent e) {
- String str = (String) e.getAttachment();
+ public void windowResized(final WindowEvent e) {
+ final String str = (String) e.getAttachment();
System.out.println("WindowEventCom3.windowResized: "+str);
}
- public void windowMoved(WindowEvent e) {
- String str = (String) e.getAttachment();
+ public void windowMoved(final WindowEvent e) {
+ final String str = (String) e.getAttachment();
System.out.println("WindowEventCom3.windowMoved: "+str);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java b/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java
new file mode 100644
index 000000000..a2fd7b08c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java
@@ -0,0 +1,784 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.event ;
+
+import java.io.PrintStream ;
+import java.util.ArrayList ;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.media.opengl.GLProfile ;
+
+import org.junit.Assert ;
+import org.junit.BeforeClass ;
+import org.junit.FixMethodOrder;
+import org.junit.Test ;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.RunnableTask;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase ;
+
+/**
+ * Test whether or not event modifiers are preserved by NEWT. This
+ * class defines most of the tests, but leaves the type of window
+ * and canvas up to subclasses.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class BaseNewtEventModifiers extends UITestCase {
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected static final int TEST_FRAME_X = 100 ;
+ protected static final int TEST_FRAME_Y = 100 ;
+
+ protected static final int TEST_FRAME_WIDTH = 400 ;
+ protected static final int TEST_FRAME_HEIGHT = 400 ;
+
+ protected static final int INITIAL_MOUSE_X = TEST_FRAME_X + ( TEST_FRAME_WIDTH / 2 ) ;
+ protected static final int INITIAL_MOUSE_Y = TEST_FRAME_Y + ( TEST_FRAME_HEIGHT / 2 ) ;
+
+ protected static final int MS_ROBOT_KEY_PRESS_DELAY = 50 ;
+ protected static final int MS_ROBOT_KEY_RELEASE_DELAY = 50 ;
+ protected static final int MS_ROBOT_MOUSE_MOVE_DELAY = 200 ;
+
+ protected static final int MS_ROBOT_AUTO_DELAY = 50 ;
+ protected static final int MS_ROBOT_POST_TEST_DELAY = 100;
+
+ protected static final boolean _debug = true ;
+ protected static final PrintStream _debugPrintStream = System.err ;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ static
+ {
+ GLProfile.initSingleton() ;
+ }
+
+ private static class TestMouseListener implements com.jogamp.newt.event.MouseListener
+ {
+ private static final String NO_EVENT_DELIVERY = "no event delivery" ;
+
+ private boolean _modifierCheckEnabled ;
+ private int _expectedModifiers;
+ private final AtomicInteger _eventCount = new AtomicInteger(0);
+ private ArrayList<String> _failures = new ArrayList<String>() ;
+
+ public synchronized void setModifierCheckEnabled( final boolean value ) {
+ _modifierCheckEnabled = value ;
+ }
+
+ public synchronized boolean modifierCheckEnabled() {
+ return _modifierCheckEnabled ;
+ }
+
+ /**
+ * Sets the modifiers the listener should expect, and clears
+ * out any existing accumulated failures. Normally this kind
+ * of double duty in a setter might be considered evil, but
+ * in this test code it's probably ok.
+ */
+
+ public synchronized void setExpectedModifiers( final int value ) {
+ _expectedModifiers = value ;
+ clear();
+ }
+
+ public synchronized ArrayList<String> clear() {
+ final ArrayList<String> old = _failures;
+
+ _eventCount.set(0);
+
+ // Assume we will have a failure due to no event delivery.
+ // If an event is delivered and it's good this assumed
+ // failure will get cleared out.
+ _failures = new ArrayList<String>();
+ _failures.add( NO_EVENT_DELIVERY );
+ return old;
+ }
+
+ public ArrayList<String> getFailures(final int waitEventCount) {
+ int j;
+ for(j=0; j < 20 && _eventCount.get() < waitEventCount; j++) { // wait until events are collected
+ _robot.delay(MS_ROBOT_AUTO_DELAY);
+ }
+ if(0 == _eventCount.get()) {
+ _debugPrintStream.println("**** No Event. Waited "+j+" * "+MS_ROBOT_AUTO_DELAY+"ms, eventCount "+_eventCount);
+ }
+ return clear();
+ }
+
+ private synchronized void _checkModifiers( final com.jogamp.newt.event.MouseEvent hasEvent ) {
+ if( _modifierCheckEnabled ) {
+
+ final MouseEvent expEvent = new MouseEvent(hasEvent.getEventType(), hasEvent.getSource(), hasEvent.getWhen(), _expectedModifiers,
+ hasEvent.getX(), hasEvent.getY(), hasEvent.getClickCount(), hasEvent.getButton(),
+ hasEvent.getRotation(), hasEvent.getRotationScale());
+
+ _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.SHIFT_MASK, "shift" ) ;
+ _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.CTRL_MASK, "ctrl" ) ;
+ _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.META_MASK, "meta" ) ;
+ _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.ALT_MASK, "alt" ) ;
+ _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK, "graph" ) ;
+
+ for( int n = 0 ; n < _numButtonsToTest ; ++n ) {
+ _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.getButtonMask( n + 1 ), "button"+(n+1) ) ;
+ }
+ }
+ }
+
+ private synchronized void _checkModifierMask( final com.jogamp.newt.event.MouseEvent expEvent, final com.jogamp.newt.event.MouseEvent hasEvent, final int mask, final String maskS ) {
+
+ // If the "no event delivery" failure is still in the list then
+ // get rid of it since that obviously isn't true anymore. We
+ // want to do this whether or not there's an issue with the
+ // modifiers.
+
+ if( _failures.size() == 1 && _failures.get(0).equals( NO_EVENT_DELIVERY ) ) {
+ _failures.clear() ;
+ }
+
+ if( ( hasEvent.getModifiers() & mask ) != ( expEvent.getModifiers() & mask ) ) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( com.jogamp.newt.event.MouseEvent.getEventTypeString( hasEvent.getEventType() ) ).append(": mask ").append(maskS).append(" 0x").append(Integer.toHexString(mask));
+ sb.append(", eventCount ").append(_eventCount).append(", expected:");
+ expEvent.getModifiersString(sb);
+ sb.append(", have: ");
+ hasEvent.getModifiersString(sb);
+ sb.append(" - full event: ");
+ hasEvent.toString(sb);
+ _failures.add( sb.toString() ) ;
+ }
+ }
+
+ public synchronized void mousePressed( final com.jogamp.newt.event.MouseEvent event ) {
+ _eventCount.incrementAndGet();
+ if( _debug ) {
+ _debugPrintStream.println( "MousePressed "+_eventCount+": "+event);
+ }
+ _checkModifiers( event ) ;
+ }
+
+ public synchronized void mouseReleased( final com.jogamp.newt.event.MouseEvent event ) {
+ _eventCount.incrementAndGet();
+ if( _debug ) {
+ _debugPrintStream.println( "MouseReleased "+_eventCount+": "+event);
+ }
+ _checkModifiers( event ) ;
+ }
+
+ public synchronized void mouseDragged( final com.jogamp.newt.event.MouseEvent event ) {
+ _eventCount.incrementAndGet();
+ if( _debug ) {
+ _debugPrintStream.println( "MouseDragged "+_eventCount+": "+event);
+ }
+ _checkModifiers( event ) ;
+ }
+
+ //
+ // IGNORED
+ //
+
+ public synchronized void mouseMoved( final com.jogamp.newt.event.MouseEvent event ) {
+ // Ignored, since mouse MOVE doesn't hold mouse button, we look for DRAGGED!
+ // _eventCount++;
+ if( _debug ) {
+ _debugPrintStream.println( "MouseMoved ignored: "+event);
+ }
+ // _checkModifiers( event ) ;
+ }
+
+ public synchronized void mouseClicked( final com.jogamp.newt.event.MouseEvent event ) {
+ // Ignored, since we look for PRESS/RELEASE only!
+ // _eventCount++;
+ if( _debug ) {
+ _debugPrintStream.println( "MouseClicked ignored: "+event);
+ }
+ // _checkModifiers( event ) ;
+ }
+
+ public synchronized void mouseWheelMoved( final com.jogamp.newt.event.MouseEvent event ) {
+ // _eventCount++;
+ if( _debug ) {
+ _debugPrintStream.println( "MouseWheeleMoved ignored: "+event);
+ }
+ // _checkModifiers( event ) ;
+ }
+
+ public synchronized void mouseEntered( final com.jogamp.newt.event.MouseEvent event ) {
+ // _eventCount++;
+ if( _debug ) {
+ _debugPrintStream.println( "MouseEntered ignored: "+event);
+ }
+ // _checkModifiers( event ) ;
+ }
+
+ public synchronized void mouseExited( final com.jogamp.newt.event.MouseEvent event ) {
+ // _eventCount++;
+ if( _debug ) {
+ _debugPrintStream.println( "MouseExited ignored: "+event);
+ }
+ // _checkModifiers( event ) ;
+ }
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private static int _numButtonsToTest ;
+ private static int _awtButtonMasks[] ;
+
+ protected static java.awt.Robot _robot ;
+
+ protected static TestMouseListener _testMouseListener ;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public static int getAWTButtonMask(final int button) {
+ // Java7: java.awt.event.InputEvent.getMaskForButton( n + 1 ) ; -> using InputEvent.BUTTON1_DOWN_MASK .. etc
+ // Java6: Only use BUTTON1_MASK, ..
+ int m;
+ switch(button) {
+ case 1 : m = java.awt.event.InputEvent.BUTTON1_MASK; break;
+ case 2 : m = java.awt.event.InputEvent.BUTTON2_MASK; break;
+ case 3 : m = java.awt.event.InputEvent.BUTTON3_MASK; break;
+ default: throw new IllegalArgumentException("Only buttons 1-3 have a MASK value, requested button "+button);
+ }
+ return m;
+ }
+
+ @BeforeClass
+ public static void baseBeforeClass() throws Exception {
+
+ // Who know how many buttons the AWT will say exist on given platform.
+ // We'll test the smaller of what NEWT supports and what the
+ // AWT says is available.
+ /** Java7:
+ if( java.awt.Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled() ) {
+ _numButtonsToTest = java.awt.MouseInfo.getNumberOfButtons() ;
+ } else {
+ _numButtonsToTest = 3 ;
+ } */
+ _numButtonsToTest = 3 ;
+
+ // Then again, maybe not:
+
+ // FIXME? - for reasons I'm not quite sure of the AWT MouseEvent
+ // constructor does some strange things for buttons other than
+ // 1, 2, and 3. Furthermore, while developing this test it
+ // appeared that events sent by the robot for buttons 9 and
+ // up weren't even delivered to the listeners.
+ //
+ // So... for now we're only going to test 3 buttons since
+ // that's the common case _and_ Java6 safe.
+
+ _numButtonsToTest = 3 ;
+
+ {
+ if( _numButtonsToTest > com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ) {
+ _numButtonsToTest = com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ;
+ }
+
+ // These two arrays are assumed to be peers, i.e. are the same
+ // size, and a given index references the same button in
+ // either array.
+
+ _awtButtonMasks = new int[_numButtonsToTest] ;
+
+ for( int n = 0 ; n < _awtButtonMasks.length ; ++n ) {
+ _awtButtonMasks[n] = getAWTButtonMask( n + 1 );
+ }
+ }
+
+ _robot = new java.awt.Robot() ;
+ _robot.setAutoWaitForIdle( true ) ;
+
+ _testMouseListener = new TestMouseListener() ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Following both methods are mandatory to deal with SWT's requirement
+ // to run the SWT event dispatch on the TK thread - which must be the main thread on OSX.
+ // We spawn off the actual test-action into another thread,
+ // while dispatching the events until the test-action is completed.
+ // YES: This is sort of ideal - NOT :)
+
+ protected void eventDispatch() {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException e) { }
+ }
+
+ private void execOffThreadWithOnThreadEventDispatch(final Runnable testAction) throws Exception {
+ _testMouseListener.setModifierCheckEnabled( false ) ;
+ _robot.setAutoDelay( MS_ROBOT_AUTO_DELAY ) ;
+ {
+ // Make sure all the buttons and modifier keys are released.
+ clearKeyboadAndMouse();
+ }
+ _testMouseListener.setModifierCheckEnabled( true ) ;
+
+ Throwable throwable = null;
+ // final Object sync = new Object();
+ final RunnableTask rt = new RunnableTask( testAction, null, true, System.err );
+ try {
+ // synchronized(sync) {
+ new Thread(rt, "Test-Thread").start();
+ int i=0;
+ while( !rt.isExecuted() && null == throwable ) {
+ System.err.println("WAIT-till-done: eventDispatch() #"+i++);
+ eventDispatch();
+ }
+ if(null==throwable) {
+ throwable = rt.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ // }
+ } finally {
+ System.err.println("WAIT-till-done: DONE");
+ _testMouseListener.setModifierCheckEnabled( false ) ;
+ clearKeyboadAndMouse();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // The approach on all these tests is to tell the test mouse listener what
+ // modifiers we think it should receive. Then when the events are delivered
+ // it compares what we told it to expect with what actually showed up and
+ // complains if there are differences.
+ //
+ // As things stand currently the tests below generally work for AWTCanvas
+ // and fail for everything else. This may point to a flaw in the test
+ // code, or a flaw in the NEWT stuff; not sure yet. One exception is the
+ // tests involving ALT and META, which on at least X11 cause the desktop
+ // to do undesirable stuff while the tests are in progress. So... these
+ // tests have been commented out for now and probably should be left
+ // that way.
+ //
+ // Due to the fact that a majority of these fail currently for
+ // everything but AWTCanvas for the time being we probably shouldn't
+ // run the tests for NewtCanvasAWT and NewtCanvasSWT until we can
+ // pay more attention to the NEWT event modifier stuff.
+
+ @Test(timeout=180000) // TO 3 min
+ public void testSingleButtonPressAndRelease() throws Exception {
+ execOffThreadWithOnThreadEventDispatch(new Runnable() {
+ public void run() {
+ try {
+ _doSingleButtonPressAndRelease( 0, 0 );
+ } catch (final Exception e) { throw new RuntimeException(e); }
+ } } );
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void testSingleButtonPressAndReleaseWithShift() throws Exception {
+ execOffThreadWithOnThreadEventDispatch(new Runnable() {
+ public void run() {
+ try {
+ _doSingleButtonPressAndRelease( java.awt.event.KeyEvent.VK_SHIFT, java.awt.event.InputEvent.SHIFT_DOWN_MASK ) ;
+ } catch (final Exception e) { throw new RuntimeException(e); }
+ } } );
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void testSingleButtonPressAndReleaseWithCtrl() throws Exception {
+ execOffThreadWithOnThreadEventDispatch(new Runnable() {
+ public void run() {
+ try {
+ _doSingleButtonPressAndRelease( java.awt.event.KeyEvent.VK_CONTROL, java.awt.event.InputEvent.CTRL_DOWN_MASK ) ;
+ } catch (final Exception e) { throw new RuntimeException(e); }
+ } } );
+ }
+
+ /**
+ * The META and ALT tests get too tied up with functions of the window system on X11,
+ * so it's probably best to leave them commented out.
+ @Test(timeout=180000) // TO 3 min
+ public void testSingleButtonPressAndReleaseWithMeta() throws Exception {
+ execOffThreadWithOnThreadEventDispatch(new Runnable() {
+ public void run() {
+ try {
+ _doSingleButtonPressAndRelease( java.awt.event.KeyEvent.VK_META, java.awt.event.InputEvent.META_DOWN_MASK ) ;
+ } catch (Exception e) { throw new RuntimeException(e); }
+ } } );
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void testSingleButtonPressAndReleaseWithAlt() throws Exception {
+ execOffThreadWithOnThreadEventDispatch(new Runnable() {
+ public void run() {
+ try {
+ _doSingleButtonPressAndRelease( java.awt.event.KeyEvent.VK_ALT, java.awt.event.InputEvent.ALT_DOWN_MASK ) ;
+ } catch (Exception e) { throw new RuntimeException(e); }
+ } } );
+ }
+ */
+
+ /**
+ * FIXME - not sure yet what's up with ALT_GRAPH. It appears that this
+ * modifier didn't make it through, so I had to disable this test else it would always fail.
+ *
+ * My US keyboard doesn't have an AltGr key, so maybe X is smart
+ * enough to not let this modifier slip through (?).
+ @Test
+ public void testSingleButtonPressAndReleaseWithAltGraph() throws Exception {
+ execOffThreadWithOnThreadEventDispatch(new Runnable() {
+ public void run() {
+ try {
+ _doSingleButtonPressAndRelease( java.awt.event.KeyEvent.VK_ALT_GRAPH, java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK ) ;
+ } catch (Exception e) { throw new RuntimeException(e); }
+ } } );
+ }
+ */
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ @Test(timeout=180000) // TO 3 min
+ public void testHoldOneButtonAndPressAnother() throws Exception {
+ execOffThreadWithOnThreadEventDispatch(new Runnable() {
+ public void run() {
+ try {
+ _doHoldOneButtonAndPressAnother( 0, 0 ) ;
+ } catch (final Exception e) { throw new RuntimeException(e); }
+ } } );
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void testPressAllButtonsInSequence() throws Exception {
+ execOffThreadWithOnThreadEventDispatch(new Runnable() {
+ public void run() {
+ try {
+ _doPressAllButtonsInSequence( 0, 0 ) ;
+ } catch (final Exception e) { throw new RuntimeException(e); }
+ } } );
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void testSingleButtonClickAndDrag() throws Exception {
+ execOffThreadWithOnThreadEventDispatch(new Runnable() {
+ public void run() {
+ try {
+ _doSingleButtonClickAndDrag( 0, 0 ) ;
+ } catch (final Exception e) { throw new RuntimeException(e); }
+ } } );
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private void _doSingleButtonPressAndRelease( final int keyCode, final int keyModifierMask ) throws Exception {
+
+ if( _debug ) { _debugPrintStream.println( "\n>>>> _doSingleButtonPressAndRelease" ) ; }
+
+ _doKeyPress( keyCode ) ;
+
+ for (int n = 0 ; n < _numButtonsToTest ; ++n) {
+
+ final int awtButtonMask = _awtButtonMasks[n] ;
+
+ if( _debug ) { _debugPrintStream.println( "*** pressing button " + ( n + 1 ) ) ; }
+ _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ;
+ _robot.mousePress( awtButtonMask ) ;
+ _checkFailures("mouse-press("+(n+1)+")", 1) ;
+
+ if( _debug ) { _debugPrintStream.println( "*** releasing button " + ( n + 1 ) ) ; }
+ _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ;
+ _robot.mouseRelease( awtButtonMask ) ;
+ _checkFailures("mouse-release("+(n+1)+")", 1) ;
+ }
+
+ _doKeyRelease( keyCode ) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private void _doHoldOneButtonAndPressAnother( final int keyCode, final int keyModifierMask ) throws Exception {
+
+ if( _debug ) { _debugPrintStream.println( "\n>>>> _doHoldOneButtonAndPressAnother" ) ; }
+
+ _doKeyPress( keyCode ) ;
+
+ for (int n = 0 ; n < _numButtonsToTest ; ++n) {
+
+ final int awtButtonMask = _awtButtonMasks[n] ;
+
+ if( _debug ) { _debugPrintStream.println( "*** pressing button " + ( n + 1 ) ) ; }
+ _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ;
+ _robot.mousePress( awtButtonMask ) ;
+ _checkFailures("mouse-press("+(n+1)+")", 1) ;
+
+ for (int m = 0 ; m < _numButtonsToTest ; ++m) {
+
+ if( n != m ) {
+
+ if( _debug ) { _debugPrintStream.println( "*** pressing additional button " + ( m + 1 ) ) ; }
+ _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask | _awtButtonMasks[m] ) ) ;
+ _robot.mousePress( _awtButtonMasks[m] ) ;
+ _checkFailures("mouse-press("+(n+1)+", "+(m+1)+")", 1) ;
+
+ if( _debug ) { _debugPrintStream.println( "*** releasing additional button " + ( m + 1 ) ) ; }
+ _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask | _awtButtonMasks[m] ) ) ;
+ _robot.mouseRelease( _awtButtonMasks[m] ) ;
+ _checkFailures("mouse-release("+(n+1)+", "+(m+1)+")", 1) ;
+ }
+ }
+
+ if( _debug ) { _debugPrintStream.println( "*** releasing button " + ( n + 1 ) ) ; }
+ _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ;
+ _robot.mouseRelease( awtButtonMask ) ;
+ _checkFailures("mouse-release("+(n+1)+")", 1);
+ }
+
+ _doKeyRelease( keyCode ) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private void _doPressAllButtonsInSequence( final int keyCode, final int keyModifierMask ) throws Exception {
+
+ if( _debug ) { _debugPrintStream.println( "\n>>>> _doPressAllButtonsInSequence" ) ; }
+
+ _doKeyPress( keyCode ) ;
+
+ {
+ int cumulativeAwtModifiers = 0 ;
+
+ for (int n = 0 ; n < _numButtonsToTest ; ++n) {
+
+ cumulativeAwtModifiers |= _awtButtonMasks[n] ;
+
+ if( _debug ) { _debugPrintStream.println( "*** pressing button " + ( n + 1 ) ) ; }
+ _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | cumulativeAwtModifiers ) ) ;
+ _robot.mousePress( _awtButtonMasks[n] ) ;
+ _checkFailures("mouse-press("+(n+1)+")", 1) ;
+ }
+
+ for (int n = _numButtonsToTest - 1 ; n >= 0 ; --n) {
+
+ if( _debug ) { _debugPrintStream.println( "*** releasing button " + ( n + 1 ) ) ; }
+ _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | cumulativeAwtModifiers ) ) ;
+ _robot.mouseRelease( _awtButtonMasks[n] ) ;
+ _checkFailures("mouse-release("+(n+1)+")", 1) ;
+
+ cumulativeAwtModifiers &= ~_awtButtonMasks[n] ;
+ }
+ }
+
+ _doKeyRelease( keyCode ) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private void _doSingleButtonClickAndDrag( final int keyCode, final int keyModifierMask ) throws Exception {
+
+ if( _debug ) { _debugPrintStream.println( "\n>>>> _doSingleButtonClickAndDrag" ) ; }
+
+ _doKeyPress( keyCode ) ;
+
+ _testMouseListener.setModifierCheckEnabled( true ) ;
+
+ for (int n = 0 ; n < _numButtonsToTest ; ++n) {
+
+ final int awtButtonMask = _awtButtonMasks[n] ;
+
+ if( _debug ) { _debugPrintStream.println( "*** pressing button " + ( n + 1 ) ) ; }
+ _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ;
+ _robot.mousePress( awtButtonMask ) ;
+ _checkFailures("mouse-press("+(n+1)+")", 1) ;
+
+ // To get a drag we only need to move one pixel.
+ if( _debug ) { _debugPrintStream.println( "*** moving mouse" ) ; }
+ final int newX = INITIAL_MOUSE_X + 8, newY = INITIAL_MOUSE_Y + 8;
+ _robot.mouseMove( newX, newY ) ;
+ _robot.delay(MS_ROBOT_MOUSE_MOVE_DELAY);
+ _checkFailures("mouse-move("+newX+", "+newY+")", 1) ;
+
+ if( _debug ) { _debugPrintStream.println( "*** releasing button " + ( n + 1 ) ) ; }
+ _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ;
+ _robot.mouseRelease( awtButtonMask ) ;
+ _checkFailures("mouse-release("+(n+1)+")", 1) ;
+
+ _testMouseListener.setModifierCheckEnabled( false ) ;
+ _robot.mouseMove( INITIAL_MOUSE_X, INITIAL_MOUSE_Y ) ;
+ _robot.delay(MS_ROBOT_MOUSE_MOVE_DELAY);
+ _testMouseListener.setModifierCheckEnabled( true ) ;
+ }
+
+ _doKeyRelease( keyCode ) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private void _doKeyPress( final int keyCode ) {
+ AWTRobotUtil.validateAWTEDTIsAlive();
+ if( keyCode != 0 ) {
+ final boolean modifierCheckEnabled = _testMouseListener.modifierCheckEnabled() ;
+ _testMouseListener.setModifierCheckEnabled( false ) ;
+ _robot.keyPress( keyCode ) ;
+ _robot.delay(MS_ROBOT_KEY_PRESS_DELAY);
+ _testMouseListener.setModifierCheckEnabled( modifierCheckEnabled ) ;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private void _doKeyRelease( final int keyCode ) {
+ AWTRobotUtil.validateAWTEDTIsAlive();
+ if( keyCode != 0 ) {
+ final boolean modifierCheckEnabled = _testMouseListener.modifierCheckEnabled() ;
+ _testMouseListener.setModifierCheckEnabled( false ) ;
+ _robot.keyRelease( keyCode ) ;
+ _robot.delay(MS_ROBOT_KEY_RELEASE_DELAY);
+ _testMouseListener.setModifierCheckEnabled( modifierCheckEnabled ) ;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private void _checkFailures(final String descr, final int waitEventCount) {
+ final ArrayList<String> failures = _testMouseListener.getFailures(waitEventCount) ;
+
+ _debugPrintStream.print(getSimpleTestName(".")+" - "+descr+": ");
+ final int numFailures = failures.size() ;
+ if( numFailures == 0 ) {
+ _debugPrintStream.println( " PASSED" ) ;
+ } else {
+ _debugPrintStream.println( " FAILED" ) ;
+ for( int n = 0 ; n < numFailures ; ++n ) {
+ _debugPrintStream.print( " " ) ;
+ _debugPrintStream.println( failures.get(n) ) ;
+ }
+ }
+
+ Assert.assertTrue( failures.size() == 0 ) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void eventDispatchedPostTestDelay() throws Exception {
+ eventDispatch(); eventDispatch(); eventDispatch();
+ Thread.sleep( MS_ROBOT_POST_TEST_DELAY ) ;
+ eventDispatch(); eventDispatch(); eventDispatch();
+ _testMouseListener.clear();
+ }
+
+ public void clearKeyboadAndMouse() throws Exception {
+ // Make sure all modifiers are released, otherwise the user's
+ // desktop can get locked up (ask me how I know this).
+ _releaseModifiers() ;
+ _escape() ;
+ eventDispatchedPostTestDelay();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private void _releaseModifiers() {
+
+ if (_robot != null) {
+ AWTRobotUtil.validateAWTEDTIsAlive();
+
+ _robot.setAutoDelay( MS_ROBOT_AUTO_DELAY ) ;
+
+ final boolean modifierCheckEnabled = _testMouseListener.modifierCheckEnabled() ;
+ _testMouseListener.setModifierCheckEnabled( false ) ;
+
+ {
+ _robot.keyRelease( java.awt.event.KeyEvent.VK_SHIFT ) ;
+ _robot.keyRelease( java.awt.event.KeyEvent.VK_CONTROL ) ;
+ // _robot.keyRelease( java.awt.event.KeyEvent.VK_META ) ;
+ // _robot.keyRelease( java.awt.event.KeyEvent.VK_ALT ) ;
+ // _robot.keyRelease( java.awt.event.KeyEvent.VK_ALT_GRAPH ) ;
+
+ for (int n = 0 ; n < _awtButtonMasks.length ; ++n) {
+ _robot.mouseRelease( _awtButtonMasks[n] ) ;
+ }
+ }
+
+ _testMouseListener.setModifierCheckEnabled( modifierCheckEnabled ) ;
+ }
+ }
+
+ private void _escape() {
+ if (_robot != null) {
+ AWTRobotUtil.validateAWTEDTIsAlive();
+ _robot.keyPress( java.awt.event.KeyEvent.VK_ESCAPE ) ;
+ _robot.keyRelease( java.awt.event.KeyEvent.VK_ESCAPE ) ;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Brute force method to return the NEWT event modifiers equivalent
+ * to the specified AWT event extended modifiers.
+ *
+ * @param awtExtendedModifiers
+ * The AWT extended modifiers.
+ *
+ * @return
+ * The equivalent NEWT modifiers.
+ */
+
+ private int _getNewtModifiersForAwtExtendedModifiers( final int awtExtendedModifiers ) {
+
+ int mask = 0 ;
+
+ if( ( awtExtendedModifiers & java.awt.event.InputEvent.SHIFT_DOWN_MASK ) != 0 ) {
+ mask |= com.jogamp.newt.event.InputEvent.SHIFT_MASK ;
+ }
+
+ if( ( awtExtendedModifiers & java.awt.event.InputEvent.CTRL_DOWN_MASK ) != 0 ) {
+ mask |= com.jogamp.newt.event.InputEvent.CTRL_MASK ;
+ }
+
+ if( ( awtExtendedModifiers & java.awt.event.InputEvent.META_DOWN_MASK ) != 0 ) {
+ mask |= com.jogamp.newt.event.InputEvent.META_MASK ;
+ }
+
+ if( ( awtExtendedModifiers & java.awt.event.InputEvent.ALT_DOWN_MASK ) != 0 ) {
+ mask |= com.jogamp.newt.event.InputEvent.ALT_MASK ;
+ }
+
+ if( ( awtExtendedModifiers & java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK ) != 0 ) {
+ mask |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK ;
+ }
+
+ for (int n = 0 ; n < _numButtonsToTest ; ++n) {
+ if ((awtExtendedModifiers & getAWTButtonMask(n+1)) != 0) {
+ mask |= com.jogamp.newt.event.InputEvent.getButtonMask(n+1) ;
+ }
+ }
+
+ return mask ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java
new file mode 100644
index 000000000..194edbcb5
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java
@@ -0,0 +1,106 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.event;
+
+import javax.media.opengl.awt.GLCanvas ;
+
+import javax.swing.JFrame ;
+import javax.swing.SwingUtilities ;
+import javax.swing.WindowConstants ;
+
+import org.junit.AfterClass ;
+import org.junit.Assert;
+import org.junit.BeforeClass ;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.event.awt.AWTMouseAdapter ;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+
+/**
+ * Test whether or not event modifiers are preserved by NEWT when
+ * the source is an AWT canvas.
+ */
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestNewtEventModifiersAWTCanvas extends BaseNewtEventModifiers {
+
+ private static JFrame _testFrame ;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+
+ final GLCanvas canvas = new GLCanvas() ;
+ canvas.addGLEventListener( new RedSquareES2() ) ;
+ new AWTMouseAdapter( _testMouseListener, canvas ).addTo( canvas ) ;
+
+ _testFrame = new JFrame( "Event Modifier Test AWTCanvas" ) ;
+ _testFrame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE ) ;
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ _testFrame.getContentPane().add( canvas ) ;
+ _testFrame.setBounds( TEST_FRAME_X, TEST_FRAME_Y, TEST_FRAME_WIDTH, TEST_FRAME_HEIGHT ) ;
+ _testFrame.setVisible( true ) ;
+ }
+ }) ;
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(_testFrame, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(canvas, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(canvas, true));
+
+ AWTRobotUtil.assertRequestFocusAndWait(null, canvas, canvas, null, null); // programmatic
+ Assert.assertNotNull(_robot);
+ AWTRobotUtil.requestFocus(_robot, canvas, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ @AfterClass
+ public static void afterClass() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ if( null != _testFrame ) {
+ _testFrame.dispose() ;
+ }
+ }
+ }) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public static void main(final String args[]) throws Exception {
+ final String testName = TestNewtEventModifiersAWTCanvas.class.getName() ;
+ org.junit.runner.JUnitCore.main( testName ) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java
new file mode 100644
index 000000000..d34c36072
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.event;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass ;
+import org.junit.Assert;
+import org.junit.BeforeClass ;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+
+/**
+ * Test whether or not event modifiers are properly delivered by NEWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestNewtEventModifiersNEWTWindowAWT extends BaseNewtEventModifiers {
+
+ private static GLWindow _glWindow;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ _glWindow = GLWindow.create( new GLCapabilities( GLProfile.getGL2ES2() ) );
+ _glWindow.setTitle("Event Modifier Test GLWindow");
+ _glWindow.addGLEventListener( new RedSquareES2() ) ;
+ _glWindow.addMouseListener(_testMouseListener);
+ _glWindow.setSize(TEST_FRAME_WIDTH, TEST_FRAME_HEIGHT);
+ _glWindow.setPosition(TEST_FRAME_X, TEST_FRAME_Y);
+ _glWindow.setVisible(true);
+
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(_glWindow, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(_glWindow, true));
+
+ AWTRobotUtil.assertRequestFocusAndWait(null, _glWindow, _glWindow, null, null); // programmatic
+ Assert.assertNotNull(_robot);
+ AWTRobotUtil.requestFocus(_robot, _glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ @AfterClass
+ public static void afterClass() throws Exception {
+ _glWindow.destroy();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public static void main(final String args[]) throws Exception {
+ final String testName = TestNewtEventModifiersNEWTWindowAWT.class.getName() ;
+ org.junit.runner.JUnitCore.main( testName ) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java
new file mode 100644
index 000000000..c916ddc4d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.event ;
+
+import java.awt.BorderLayout ;
+
+import javax.media.opengl.GLCapabilities ;
+import javax.media.opengl.GLProfile ;
+
+import javax.swing.JFrame ;
+import javax.swing.SwingUtilities ;
+import javax.swing.WindowConstants ;
+
+import org.junit.AfterClass ;
+import org.junit.Assert;
+import org.junit.BeforeClass ;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.awt.NewtCanvasAWT ;
+import com.jogamp.newt.opengl.GLWindow ;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+
+/**
+ * Test whether or not event modifiers are preserved by NEWT when
+ * the canvas is a NewtCanvasAWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestNewtEventModifiersNewtCanvasAWT extends BaseNewtEventModifiers {
+
+ private static JFrame _testFrame ;
+ private static GLWindow _glWindow ;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+
+ SwingUtilities.invokeAndWait( new Runnable() {
+ public void run() {
+
+ _testFrame = new JFrame( "Event Modifier Test NewtCanvasAWT" ) ;
+ _testFrame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE ) ;
+
+ {
+ final GLCapabilities caps = new GLCapabilities( GLProfile.getGL2ES2() ) ;
+ _glWindow = GLWindow.create( caps ) ;
+
+ final NewtCanvasAWT canvas = new NewtCanvasAWT( _glWindow ) ;
+ _testFrame.getContentPane().add( canvas, BorderLayout.CENTER ) ;
+
+ _glWindow.addGLEventListener( new RedSquareES2() ) ;
+ }
+
+ _testFrame.setBounds( TEST_FRAME_X, TEST_FRAME_Y, TEST_FRAME_WIDTH, TEST_FRAME_HEIGHT ) ;
+ _testFrame.setVisible( true ) ;
+ }
+ } ) ;
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(_testFrame, true));
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(_glWindow, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(_glWindow, true));
+
+ AWTRobotUtil.assertRequestFocusAndWait(null, _glWindow, _glWindow, null, null); // programmatic
+ Assert.assertNotNull(_robot);
+ AWTRobotUtil.requestFocus(_robot, _glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+
+ _glWindow.addMouseListener( _testMouseListener ) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ @AfterClass
+ public static void afterClass() throws Exception {
+ SwingUtilities.invokeAndWait( new Runnable() {
+ public void run() {
+ if( null != _testFrame ) {
+ _testFrame.dispose() ;
+ }
+ }
+ } ) ;
+
+ _glWindow.destroy() ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public static void main(final String args[]) throws Exception {
+ final String testName = TestNewtEventModifiersNewtCanvasAWT.class.getName() ;
+ org.junit.runner.JUnitCore.main( testName ) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasSWTAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasSWTAWT.java
new file mode 100644
index 000000000..3e4029cf5
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasSWTAWT.java
@@ -0,0 +1,182 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.event;
+
+import org.eclipse.swt.SWT ;
+import org.eclipse.swt.layout.FillLayout ;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display ;
+import org.eclipse.swt.widgets.Shell ;
+
+import javax.media.opengl.GLCapabilities ;
+import javax.media.opengl.GLProfile ;
+
+import org.junit.AfterClass ;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass ;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.opengl.GLWindow ;
+import com.jogamp.newt.swt.NewtCanvasSWT ;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+
+/**
+ * Test whether or not event modifiers preserved by NEWT when
+ * the canvas is a NewtCanvasSWT.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestNewtEventModifiersNewtCanvasSWTAWT extends BaseNewtEventModifiers {
+
+ private static Display _display = null;
+ private static Shell _shell = null;
+ private static Composite _composite = null;
+ private static GLWindow _glWindow ;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected static void eventDispatchImpl() {
+ final int maxEvents = 10;
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException e) { }
+ final boolean[] res = { false };
+ int i=0;
+ do {
+ SWTAccessor.invoke(_display, true, new Runnable() {
+ public void run() {
+ if( !_display.isDisposed() ) {
+ res[0] = _display.readAndDispatch();
+ } else {
+ res[0] = false;
+ }
+ } } );
+ i++;
+ } while( i<maxEvents && res[0] );
+ }
+
+ @Override
+ protected void eventDispatch() {
+ eventDispatchImpl();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+
+ // FIXME: Hangs .. w/ Java7 .. every now and then!
+ setTestSupported(false);
+
+ /***
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ _display = new Display();
+ }});
+ Assert.assertNotNull( _display );
+
+ SWTAccessor.invoke(_display, true, new Runnable() {
+ public void run() {
+ _shell = new Shell( _display );
+ Assert.assertNotNull( _shell );
+ _shell.setText( "Event Modifier Test NewtCanvasSWT" ) ;
+ _shell.setLayout( new FillLayout() );
+ _composite = new Composite( _shell, SWT.NONE );
+ _composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( _composite );
+ }});
+
+ {
+ GLCapabilities caps = new GLCapabilities( GLProfile.get( GLProfile.GL2ES2 ) ) ;
+ _glWindow = GLWindow.create( caps ) ;
+ _glWindow.addGLEventListener( new RedSquareES2() ) ;
+
+ NewtCanvasSWT.create( _composite, SWT.NO_BACKGROUND, _glWindow ) ;
+ }
+
+ SWTAccessor.invoke(_display, true, new Runnable() {
+ public void run() {
+ _shell.setBounds( TEST_FRAME_X, TEST_FRAME_Y, TEST_FRAME_WIDTH, TEST_FRAME_HEIGHT ) ;
+ _shell.open();
+ }
+ });
+
+ // no AWT idling, may deadlock on OSX!
+ Assert.assertNotNull(_robot);
+ _robot.setAutoWaitForIdle( false ) ;
+
+ // no waiting for results ..
+ AWTRobotUtil.requestFocus(null, _glWindow, false); // programmatic
+ eventDispatchImpl();
+ AWTRobotUtil.requestFocus(_robot, _glWindow, INITIAL_MOUSE_X, INITIAL_MOUSE_Y);
+ eventDispatchImpl();
+
+ _glWindow.addMouseListener( _testMouseListener ) ;
+ */
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ @AfterClass
+ public static void afterClass() throws Exception {
+ /**
+ _glWindow.destroy() ;
+
+ try {
+ SWTAccessor.invoke(_display, true, new Runnable() {
+ public void run() {
+ if( null != _composite ) {
+ _composite.dispose();
+ }
+ if( null != _shell ) {
+ _shell.dispose();
+ }
+ if( null != _display && !_display.isDisposed()) {
+ _display.dispose();
+ }
+ }});
+ }
+ catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ } */
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public static void main(final String args[]) throws Exception {
+ final String testName = TestNewtEventModifiersNewtCanvasSWTAWT.class.getName() ;
+ org.junit.runner.JUnitCore.main( testName ) ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java
new file mode 100644
index 000000000..eebbe5469
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java
@@ -0,0 +1,308 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.event;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.Before;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Robot;
+import java.lang.reflect.InvocationTargetException;
+import java.util.EventObject;
+import java.util.List;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.swing.JFrame;
+
+import java.io.IOException;
+
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+
+import com.jogamp.opengl.test.junit.util.*;
+
+/**
+ * Testing combinations of key code modifiers of key event.
+ *
+ * <p>
+ * Due to limitation of AWT Robot, the test machine needs to have US keyboard enabled,
+ * even though we do unify VK codes to US keyboard across all layouts.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestNewtKeyCodeModifiersAWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 100;
+ static long awtWaitTimeout = 1000;
+
+ static GLCapabilities glCaps;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @AfterClass
+ public static void release() {
+ }
+
+ @Before
+ public void initTest() {
+ }
+
+ @After
+ public void releaseTest() {
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
+ final GLWindow glWindow = GLWindow.create(glCaps);
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+
+ testImpl(glWindow);
+
+ glWindow.destroy();
+ }
+
+ private void testNewtCanvasAWT_Impl(final boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException {
+ final GLWindow glWindow = GLWindow.create(glCaps);
+
+ // Wrap the window in a canvas.
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ if( !onscreen ) {
+ newtCanvasAWT.setShallUseOffscreenLayer(true);
+ }
+
+ // Add the canvas to a frame, and make it all visible.
+ final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle());
+ frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER);
+ frame1.setSize(width, height);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(true);
+ } } );
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true));
+
+ testImpl(glWindow);
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(false);
+ frame1.dispose();
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ glWindow.destroy();
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException {
+ if( JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("Platform doesn't support onscreen rendering.");
+ return;
+ }
+ testNewtCanvasAWT_Impl(true);
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException {
+ if( !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("Platform doesn't support offscreen rendering.");
+ return;
+ }
+ testNewtCanvasAWT_Impl(false);
+ }
+
+ static void testKeyCodeModifier(final Robot robot, final NEWTKeyAdapter keyAdapter, final short modifierKey, final int modifierMask, final short keyCode,
+ final char keyCharOnly, final char keyCharMod) {
+ keyAdapter.reset();
+ AWTRobotUtil.waitForIdle(robot);
+ AWTRobotUtil.newtKeyPress(0, robot, true, keyCode, 10); // press keyCode
+ AWTRobotUtil.newtKeyPress(0, robot, false, keyCode, 100); // release keyCode
+ AWTRobotUtil.waitForIdle(robot);
+ for(int j=0; j < 100 && keyAdapter.getQueueSize() < 2; j++) { // wait until events are collected
+ robot.delay(100);
+ }
+
+ AWTRobotUtil.waitForIdle(robot);
+ AWTRobotUtil.newtKeyPress(0, robot, true, modifierKey, 10); // press MOD
+ AWTRobotUtil.newtKeyPress(0, robot, true, keyCode, 10); // press keyCode
+ AWTRobotUtil.newtKeyPress(0, robot, false, keyCode, 10); // release keyCode
+ AWTRobotUtil.newtKeyPress(0, robot, false, modifierKey, 100); // release MOD
+ AWTRobotUtil.waitForIdle(robot);
+ for(int j=0; j < 100 && keyAdapter.getQueueSize() < 2+4; j++) { // wait until events are collected
+ robot.delay(100);
+ }
+ NEWTKeyUtil.validateKeyAdapterStats(keyAdapter,
+ 3 /* press-SI */, 3 /* release-SI */,
+ 0 /* press-AR */, 0 /* release-AR */ );
+
+ final List<EventObject> queue = keyAdapter.copyQueue();
+ int i=0;
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, 0, keyCode, keyCharOnly);
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, 0, keyCode, keyCharOnly);
+
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, modifierKey, KeyEvent.NULL_CHAR);
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, keyCode, keyCharMod);
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, modifierMask, keyCode, keyCharMod);
+ final KeyEvent e = (KeyEvent) queue.get(i++);
+ NEWTKeyUtil.validateKeyEvent(e, KeyEvent.EVENT_KEY_RELEASED, modifierMask, modifierKey, KeyEvent.NULL_CHAR);
+ }
+
+ static void testKeyCodeAllModifierV1(final Robot robot, final NEWTKeyAdapter keyAdapter) {
+ final short m1k = KeyEvent.VK_ALT;
+ final int m1m = InputEvent.ALT_MASK;
+ final short m2k = KeyEvent.VK_CONTROL;
+ final int m2m = InputEvent.CTRL_MASK;
+ final short m3k = KeyEvent.VK_SHIFT;
+ final int m3m = InputEvent.SHIFT_MASK;
+
+ keyAdapter.reset();
+ AWTRobotUtil.waitForIdle(robot);
+ AWTRobotUtil.newtKeyPress(0, robot, true, m1k, 10); // press MOD1
+ AWTRobotUtil.newtKeyPress(0, robot, true, m2k, 10); // press MOD2
+ AWTRobotUtil.newtKeyPress(0, robot, true, m3k, 10); // press MOD3
+ AWTRobotUtil.newtKeyPress(0, robot, true, KeyEvent.VK_1, 10); // press P
+
+ AWTRobotUtil.newtKeyPress(0, robot, false, KeyEvent.VK_1, 100); // release P
+ AWTRobotUtil.newtKeyPress(0, robot, false, m3k, 10); // release MOD
+ AWTRobotUtil.newtKeyPress(0, robot, false, m2k, 10); // release MOD
+ AWTRobotUtil.newtKeyPress(0, robot, false, m1k, 10); // release MOD
+ AWTRobotUtil.waitForIdle(robot);
+
+ for(int j=0; j < 100 && keyAdapter.getQueueSize() < 4+4; j++) { // wait until events are collected
+ robot.delay(100);
+ }
+ NEWTKeyUtil.validateKeyAdapterStats(keyAdapter,
+ 4 /* press-SI */, 4 /* release-SI */,
+ 0 /* press-AR */, 0 /* release-AR */ );
+
+ final List<EventObject> queue = keyAdapter.copyQueue();
+ int i=0;
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m, m1k, KeyEvent.NULL_CHAR);
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m, m2k, KeyEvent.NULL_CHAR);
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m|m3m, m3k, KeyEvent.NULL_CHAR);
+
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m|m3m, KeyEvent.VK_1, KeyEvent.NULL_CHAR);
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m|m3m, KeyEvent.VK_1, KeyEvent.NULL_CHAR);
+ final KeyEvent e = (KeyEvent) queue.get(i++);
+ NEWTKeyUtil.validateKeyEvent(e, KeyEvent.EVENT_KEY_RELEASED, m1m|m2m|m3m, m3k, KeyEvent.NULL_CHAR);
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m, m2k, KeyEvent.NULL_CHAR);
+ NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m, m1k, KeyEvent.NULL_CHAR);
+ }
+
+ void testImpl(final GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException {
+ final Robot robot = new Robot();
+ robot.setAutoWaitForIdle(true);
+
+ final GLEventListener demo1 = new RedSquareES2();
+ glWindow.addGLEventListener(demo1);
+
+ // NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
+ // glWindow.addWindowListener(glWindow1FA);
+ final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
+ glWindow1KA.setVerbose(false);
+ glWindow.addKeyListener(glWindow1KA);
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true));
+
+ // Continuous animation ..
+ final Animator animator = new Animator(glWindow);
+ animator.start();
+
+ Thread.sleep(durationPerTest); // manual testing
+
+ AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
+ AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+ glWindow1KA.reset();
+
+ testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_1, '1', '!');
+ testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_Y, 'y', 'Y'); // US: Y, DE: Z
+ testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_P, 'p', 'P');
+ testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_CONTROL, InputEvent.CTRL_MASK, KeyEvent.VK_1, '1', KeyEvent.NULL_CHAR);
+ testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_ALT, InputEvent.ALT_MASK, KeyEvent.VK_1, '1', KeyEvent.NULL_CHAR);
+
+ testKeyCodeAllModifierV1(robot, glWindow1KA);
+
+ // Remove listeners to avoid logging during dispose/destroy.
+ glWindow.removeKeyListener(glWindow1KA);
+
+ // Shutdown the test.
+ animator.stop();
+ }
+
+ static int atoi(final String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine());
+ */
+ System.out.println("durationPerTest: "+durationPerTest);
+ final String tstname = TestNewtKeyCodeModifiersAWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java
new file mode 100644
index 000000000..eecc35e4e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java
@@ -0,0 +1,292 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.event;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.Before;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Robot;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.List;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.swing.JFrame;
+
+import java.io.IOException;
+
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.*;
+import com.jogamp.opengl.test.junit.util.NEWTKeyUtil.CodeSeg;
+
+/**
+ * Testing key code of key events.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestNewtKeyCodesAWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 100;
+ static long awtWaitTimeout = 1000;
+
+ static GLCapabilities glCaps;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @AfterClass
+ public static void release() {
+ }
+
+ @Before
+ public void initTest() {
+ }
+
+ @After
+ public void releaseTest() {
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
+ final GLWindow glWindow = GLWindow.create(glCaps);
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+
+ testImpl(glWindow);
+
+ glWindow.destroy();
+ }
+
+ private void testNewtCanvasAWT_Impl(final boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException {
+ final GLWindow glWindow = GLWindow.create(glCaps);
+
+ // Wrap the window in a canvas.
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ if( !onscreen ) {
+ newtCanvasAWT.setShallUseOffscreenLayer(true);
+ }
+
+ // Add the canvas to a frame, and make it all visible.
+ final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle());
+ frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setSize(width, height);
+ frame1.setVisible(true);
+ } } );
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true));
+
+ testImpl(glWindow);
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(false);
+ frame1.dispose();
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ glWindow.destroy();
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException {
+ if( JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("Platform doesn't support onscreen rendering.");
+ return;
+ }
+ testNewtCanvasAWT_Impl(true);
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException {
+ if( !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("Platform doesn't support offscreen rendering.");
+ return;
+ }
+ testNewtCanvasAWT_Impl(false);
+ }
+
+ /** Almost all keyCodes reachable w/o modifiers [shift, alt, ..] on US keyboard! */
+ static CodeSeg[] codeSegments = new CodeSeg[] {
+ // new CodeSeg(KeyEvent.VK_HOME, KeyEvent.VK_PRINTSCREEN, "home, end, final, prnt"),
+ new CodeSeg(KeyEvent.VK_BACK_SPACE, KeyEvent.VK_BACK_SPACE, "bs"),
+ // new CodeSeg(KeyEvent.VK_TAB, KeyEvent.VK_TAB, "tab"), // TAB functions as focus traversal key
+ new CodeSeg(KeyEvent.VK_ENTER, KeyEvent.VK_ENTER, "cr"),
+ new CodeSeg(KeyEvent.VK_PAGE_DOWN, KeyEvent.VK_PAGE_DOWN, "pg_down"),
+ new CodeSeg(KeyEvent.VK_SHIFT, KeyEvent.VK_ALT, "shift, pg_up, ctrl, alt"),
+ // new CodeSeg(KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_ALT_GRAPH, "alt_gr"), // AWT Robot produces 0xff7e on X11
+ // new CodeSeg(KeyEvent.VK_SCROLL_LOCK, KeyEvent.VK_SCROLL_LOCK, "scroll lock"),
+ new CodeSeg(KeyEvent.VK_ESCAPE, KeyEvent.VK_ESCAPE, "esc"),
+ new CodeSeg(KeyEvent.VK_SPACE, KeyEvent.VK_SPACE, "space"),
+ new CodeSeg(KeyEvent.VK_QUOTE, KeyEvent.VK_QUOTE, "quote"),
+ new CodeSeg(KeyEvent.VK_COMMA, KeyEvent.VK_SLASH, ", - . /"),
+ new CodeSeg(KeyEvent.VK_0, KeyEvent.VK_9, "0 - 9"),
+ new CodeSeg(KeyEvent.VK_SEMICOLON, KeyEvent.VK_SEMICOLON, ";"),
+ new CodeSeg(KeyEvent.VK_EQUALS, KeyEvent.VK_EQUALS, "="),
+ new CodeSeg(KeyEvent.VK_A, KeyEvent.VK_Z, "a - z"),
+ new CodeSeg(KeyEvent.VK_OPEN_BRACKET, KeyEvent.VK_CLOSE_BRACKET, "[ \\ ]"),
+ new CodeSeg(KeyEvent.VK_BACK_QUOTE, KeyEvent.VK_BACK_QUOTE, "`"),
+ new CodeSeg(KeyEvent.VK_F1, KeyEvent.VK_F8, "f1..f8"),
+ // new CodeSeg(KeyEvent.VK_F1, KeyEvent.VK_F12, "f1..f12"), // f9-f12 may cause some odd desktop functions!
+ new CodeSeg(KeyEvent.VK_DELETE, KeyEvent.VK_DELETE, "del"),
+ // new CodeSeg(KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD9, "numpad0-9"), // can be mapped to normal keycodes
+ // new CodeSeg(KeyEvent.VK_DECIMAL, KeyEvent.VK_DIVIDE, "numpad ops"), // can be mapped to normal keycodes
+ // new CodeSeg(KeyEvent.VK_NUM_LOCK, KeyEvent.VK_NUM_LOCK, "num lock"),
+ // new CodeSeg(KeyEvent.VK_KP_LEFT, KeyEvent.VK_KP_DOWN, "numpad cursor arrows"),
+ new CodeSeg(KeyEvent.VK_LEFT, KeyEvent.VK_DOWN, "cursor arrows"),
+ // new CodeSeg(KeyEvent.VK_WINDOWS, KeyEvent.VK_HELP, "windows, meta, hlp"),
+ };
+
+ static void testKeyCodes(final Robot robot, final Object obj, final NEWTKeyAdapter keyAdapter) throws InterruptedException, InvocationTargetException {
+ final List<List<EventObject>> cse = new ArrayList<List<EventObject>>();
+
+ keyAdapter.setVerbose(true); // FIXME
+ final int[] objCenter = AWTRobotUtil.getCenterLocation(obj, false /* onTitleBarIfWindow */);
+
+ for(int i=0; i<codeSegments.length; i++) {
+ keyAdapter.reset();
+ final CodeSeg codeSeg = codeSegments[i];
+ // System.err.println("*** Segment "+codeSeg.description);
+ int eventCount = 0;
+ for(short c=codeSeg.min; c<=codeSeg.max; c++) {
+ AWTRobotUtil.waitForIdle(robot);
+ // System.err.println("*** KeyCode 0x"+Integer.toHexString(c));
+ try {
+ AWTRobotUtil.newtKeyPress(0, robot, true, c, 10);
+ } catch (final Exception e) {
+ System.err.println("Exception @ AWT Robot.PRESS "+MiscUtils.toHexString(c)+" - "+e.getMessage());
+ break;
+ }
+ eventCount++;
+ try {
+ AWTRobotUtil.newtKeyPress(0, robot, false, c, 100);
+ } catch (final Exception e) {
+ System.err.println("Exception @ AWT Robot.RELEASE "+MiscUtils.toHexString(c)+" - "+e.getMessage());
+ break;
+ }
+ eventCount++;
+ }
+ AWTRobotUtil.waitForIdle(robot);
+ for(int j=0; j < NEWTKeyUtil.POLL_DIVIDER && keyAdapter.getQueueSize() < eventCount; j++) { // wait until events are collected
+ robot.delay(NEWTKeyUtil.TIME_SLICE);
+ // Bug 919 - TestNewtKeyCodesAWT w/ NewtCanvasAWT Fails on Windows Due to Clogged Key-Release Event by AWT Robot
+ final int off = 0==j%2 ? 1 : -1;
+ AWTRobotUtil.awtRobotMouseMove(robot, objCenter[0]+off, objCenter[1]);
+ }
+ AWTRobotUtil.awtRobotMouseMove(robot, objCenter[0], objCenter[1]); // Bug 919: Reset mouse position
+ cse.add(keyAdapter.copyQueue());
+ }
+ Assert.assertEquals("KeyCode impl. incomplete", true, NEWTKeyUtil.validateKeyCodes(codeSegments, cse, true));
+ }
+
+ void testImpl(final GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException {
+ final Robot robot = new Robot();
+ robot.setAutoWaitForIdle(true);
+
+ final GLEventListener demo1 = new RedSquareES2();
+ glWindow.addGLEventListener(demo1);
+
+ // NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
+ // glWindow.addWindowListener(glWindow1FA);
+ final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
+ glWindow1KA.setVerbose(false);
+ glWindow.addKeyListener(glWindow1KA);
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true));
+
+ // Continuous animation ..
+ final Animator animator = new Animator(glWindow);
+ animator.start();
+
+ Thread.sleep(durationPerTest); // manual testing
+
+ AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
+ AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+ glWindow1KA.reset();
+
+ testKeyCodes(robot, glWindow, glWindow1KA);
+
+ // Remove listeners to avoid logging during dispose/destroy.
+ glWindow.removeKeyListener(glWindow1KA);
+
+ // Shutdown the test.
+ animator.stop();
+ }
+
+ static int atoi(final String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine());
+ */
+ System.out.println("durationPerTest: "+durationPerTest);
+ final String tstname = TestNewtKeyCodesAWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java
new file mode 100644
index 000000000..5e78d908f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java
@@ -0,0 +1,319 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.event;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.Before;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Robot;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.EventObject;
+import java.util.List;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.swing.JFrame;
+
+import java.io.IOException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.*;
+
+/**
+ * Testing key event order incl. auto-repeat (Bug 601)
+ *
+ * <p>
+ * Note Event order:
+ * <ol>
+ * <li>{@link #EVENT_KEY_PRESSED}</li>
+ * <li>{@link #EVENT_KEY_RELEASED}</li>
+ * </ol>
+ * </p>
+ * <p>
+ * Auto-Repeat shall behave as follow:
+ * <pre>
+ D = pressed, U = released
+ 0 = normal, 1 = auto-repeat
+
+ D(0), [ U(1), D(1), U(1), D(1) ..], U(0)
+ * </pre>
+ *
+ * The idea is if you mask out auto-repeat in your event listener
+ * you just get one long pressed key D/U tuple.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 100;
+ static long awtWaitTimeout = 1000;
+
+ static GLCapabilities glCaps;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @AfterClass
+ public static void release() {
+ }
+
+ @Before
+ public void initTest() {
+ }
+
+ @After
+ public void releaseTest() {
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
+ final GLWindow glWindow = GLWindow.create(glCaps);
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+
+ testImpl(glWindow);
+
+ glWindow.destroy();
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException {
+ final GLWindow glWindow = GLWindow.create(glCaps);
+
+ // Wrap the window in a canvas.
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
+
+ // Add the canvas to a frame, and make it all visible.
+ final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle());
+ frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER);
+ frame1.setSize(width, height);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(true);
+ } } );
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true));
+
+ testImpl(glWindow);
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(false);
+ frame1.dispose();
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ glWindow.destroy();
+ }
+
+ static void testKeyEventAutoRepeat(final Robot robot, final NEWTKeyAdapter keyAdapter, final int loops, final int pressDurationMS) {
+ System.err.println("KEY Event Auto-Repeat Test: "+loops);
+ final EventObject[][] first = new EventObject[loops][2];
+ final EventObject[][] last = new EventObject[loops][2];
+
+ keyAdapter.reset();
+ int firstIdx = 0;
+ // final ArrayList<EventObject> keyEvents = new ArrayList<EventObject>();
+ for(int i=0; i<loops; i++) {
+ System.err.println("+++ KEY Event Auto-Repeat START Input Loop: "+i);
+ AWTRobotUtil.waitForIdle(robot);
+ AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_A, pressDurationMS);
+ AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_A, 500); // 1s .. no AR anymore
+ AWTRobotUtil.waitForIdle(robot);
+ final int minCodeCount = firstIdx + 2;
+ final int desiredCodeCount = firstIdx + 4;
+ for(int j=0; j < NEWTKeyUtil.POLL_DIVIDER && keyAdapter.getQueueSize() < desiredCodeCount; j++) { // wait until events are collected
+ robot.delay(NEWTKeyUtil.TIME_SLICE);
+ }
+ final List<EventObject> keyEvents = keyAdapter.copyQueue();
+ Assert.assertTrue("AR Test didn't collect enough key events: required min "+minCodeCount+", received "+(keyAdapter.getQueueSize()-firstIdx)+", "+keyEvents,
+ keyAdapter.getQueueSize() >= minCodeCount );
+ first[i][0] = keyEvents.get(firstIdx+0);
+ first[i][1] = keyEvents.get(firstIdx+1);
+ firstIdx = keyEvents.size() - 2;
+ last[i][0] = keyEvents.get(firstIdx+0);
+ last[i][1] = keyEvents.get(firstIdx+1);
+ System.err.println("+++ KEY Event Auto-Repeat END Input Loop: "+i);
+
+ // add a pair of normal press/release in between auto-repeat!
+ firstIdx = keyEvents.size();
+ AWTRobotUtil.waitForIdle(robot);
+ AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_B, 10);
+ AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_B, 250);
+ AWTRobotUtil.waitForIdle(robot);
+ for(int j=0; j < NEWTKeyUtil.POLL_DIVIDER && keyAdapter.getQueueSize() < firstIdx+2; j++) { // wait until events are collected
+ robot.delay(NEWTKeyUtil.TIME_SLICE);
+ }
+ firstIdx = keyAdapter.getQueueSize();
+ }
+ // dumpKeyEvents(keyEvents);
+ final List<EventObject> keyEvents = keyAdapter.copyQueue();
+ NEWTKeyUtil.validateKeyEventOrder(keyEvents);
+
+ final boolean hasAR = 0 < keyAdapter.getKeyPressedCount(true) ;
+
+ {
+ final int perLoopSI = 2; // per loop: 1 non AR event and 1 for non AR 'B'
+ final int expSI, expAR;
+ if( hasAR ) {
+ expSI = perLoopSI * loops;
+ expAR = ( keyEvents.size() - expSI*2 ) / 2; // auto-repeat release
+ } else {
+ expSI = keyEvents.size() / 2; // all released events
+ expAR = 0;
+ }
+
+ NEWTKeyUtil.validateKeyAdapterStats(keyAdapter,
+ expSI /* press-SI */, expSI /* release-SI */,
+ expAR /* press-AR */, expAR /* release-AR */ );
+ }
+
+ if( !hasAR ) {
+ System.err.println("No AUTO-REPEAT triggered by AWT Robot .. aborting test analysis");
+ return;
+ }
+
+ for(int i=0; i<loops; i++) {
+ System.err.println("Auto-Repeat Loop "+i+" - Head:");
+ NEWTKeyUtil.dumpKeyEvents(Arrays.asList(first[i]));
+ System.err.println("Auto-Repeat Loop "+i+" - Tail:");
+ NEWTKeyUtil.dumpKeyEvents(Arrays.asList(last[i]));
+ }
+ for(int i=0; i<loops; i++) {
+ KeyEvent e = (KeyEvent) first[i][0];
+ Assert.assertTrue("1st Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() );
+ Assert.assertTrue("1st Shall be PRESSED, but is "+e, KeyEvent.EVENT_KEY_PRESSED == e.getEventType() );
+ Assert.assertTrue("1st Shall not be AR, but is "+e, 0 == ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) );
+
+ e = (KeyEvent) first[i][1];
+ Assert.assertTrue("2nd Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() );
+ Assert.assertTrue("2nd Shall be RELEASED, but is "+e, KeyEvent.EVENT_KEY_RELEASED == e.getEventType() );
+ Assert.assertTrue("2nd Shall be AR, but is "+e, 0 != ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) );
+
+ e = (KeyEvent) last[i][0];
+ Assert.assertTrue("last-1 Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() );
+ Assert.assertTrue("last-1 Shall be PRESSED, but is "+e, KeyEvent.EVENT_KEY_PRESSED == e.getEventType() );
+ Assert.assertTrue("last-1 Shall be AR, but is "+e, 0 != ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) );
+
+ e = (KeyEvent) last[i][1];
+ Assert.assertTrue("last-0 Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() );
+ Assert.assertTrue("last-2 Shall be RELEASED, but is "+e, KeyEvent.EVENT_KEY_RELEASED == e.getEventType() );
+ Assert.assertTrue("last-0 Shall not be AR, but is "+e, 0 == ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) );
+ }
+ }
+
+ void testImpl(final GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException {
+ final Robot robot = new Robot();
+ robot.setAutoWaitForIdle(true);
+
+ final GLEventListener demo1 = new RedSquareES2();
+ glWindow.addGLEventListener(demo1);
+
+ final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
+ glWindow1KA.setVerbose(false);
+ glWindow.addKeyListener(glWindow1KA);
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true));
+
+ // Continuous animation ..
+ final Animator animator = new Animator(glWindow);
+ animator.start();
+
+ Thread.sleep(durationPerTest); // manual testing
+
+ AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
+ AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+ glWindow1KA.reset();
+
+ //
+ // Test the key event order w/ auto-repeat
+ //
+ final int origAutoDelay = robot.getAutoDelay();
+ robot.setAutoDelay(10);
+ try {
+ testKeyEventAutoRepeat(robot, glWindow1KA, 3, 1000);
+ } finally {
+ robot.setAutoDelay(origAutoDelay);
+ }
+
+ // Remove listeners to avoid logging during dispose/destroy.
+ glWindow.removeKeyListener(glWindow1KA);
+
+ // Shutdown the test.
+ animator.stop();
+ }
+
+ static int atoi(final String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine());
+ */
+ System.out.println("durationPerTest: "+durationPerTest);
+ final String tstname = TestNewtKeyEventAutoRepeatAWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java
new file mode 100644
index 000000000..3f86c186c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java
@@ -0,0 +1,262 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.event;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.Before;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Robot;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.swing.JFrame;
+
+import java.io.IOException;
+
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+
+import com.jogamp.opengl.test.junit.util.*;
+
+/**
+ * Testing key event order excl. auto-repeat (Bug 601)
+ *
+ * <p>
+ * Note Event order:
+ * <ol>
+ * <li>{@link #EVENT_KEY_PRESSED}</li>
+ * <li>{@link #EVENT_KEY_RELEASED}</li>
+ * </ol>
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestNewtKeyEventOrderAWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 100;
+ static long awtWaitTimeout = 1000;
+
+ static GLCapabilities glCaps;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @AfterClass
+ public static void release() {
+ }
+
+ @Before
+ public void initTest() {
+ }
+
+ @After
+ public void releaseTest() {
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
+ final GLWindow glWindow = GLWindow.create(glCaps);
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+
+ testImpl(glWindow);
+
+ glWindow.destroy();
+ }
+
+ private void testNewtCanvasAWT_Impl(final boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException {
+ final GLWindow glWindow = GLWindow.create(glCaps);
+
+ // Wrap the window in a canvas.
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ if( !onscreen ) {
+ newtCanvasAWT.setShallUseOffscreenLayer(true);
+ }
+
+ // Add the canvas to a frame, and make it all visible.
+ final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle());
+ frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER);
+ frame1.setSize(width, height);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(true);
+ } } );
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true));
+
+ testImpl(glWindow);
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(false);
+ frame1.dispose();
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ glWindow.destroy();
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException {
+ if( JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("Platform doesn't support onscreen rendering.");
+ return;
+ }
+ testNewtCanvasAWT_Impl(true);
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException {
+ if( !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("Platform doesn't support offscreen rendering.");
+ return;
+ }
+ testNewtCanvasAWT_Impl(false);
+ }
+
+ static void testKeyEventOrder(final Robot robot, final NEWTKeyAdapter keyAdapter, final int loops) {
+ System.err.println("KEY Event Order Test: "+loops);
+ keyAdapter.reset();
+ for(int i=0; i<loops; i++) {
+ // 1
+ AWTRobotUtil.waitForIdle(robot);
+ AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_A, 10);
+ AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_A, 100);
+ // 2
+ AWTRobotUtil.waitForIdle(robot);
+ AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_B, 10);
+ AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_B, 100);
+ // 3 + 4
+ AWTRobotUtil.waitForIdle(robot);
+ AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_A, 10);
+ AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_B, 10);
+ AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_A, 10);
+ AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_B, 10);
+ // 5 + 6
+ AWTRobotUtil.waitForIdle(robot);
+ AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_A, 10);
+ AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_B, 10);
+ AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_B, 10);
+ AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_A, 10);
+ }
+ AWTRobotUtil.waitForIdle(robot);
+ robot.delay(250);
+ // dumpKeyEvents(keyAdapter.getQueued());
+
+ NEWTKeyUtil.validateKeyEventOrder(keyAdapter.copyQueue());
+
+ final int expTotal = 6*loops; // all typed events
+ NEWTKeyUtil.validateKeyAdapterStats(keyAdapter,
+ expTotal /* press-SI */, expTotal /* release-SI */,
+ 0 /* press-AR */, 0 /* release-AR */ );
+
+ }
+
+ void testImpl(final GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException {
+ final Robot robot = new Robot();
+ robot.setAutoWaitForIdle(true);
+
+ final GLEventListener demo1 = new RedSquareES2();
+ glWindow.addGLEventListener(demo1);
+
+ final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
+ glWindow1KA.setVerbose(false);
+ glWindow.addKeyListener(glWindow1KA);
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true));
+
+ // Continuous animation ..
+ final Animator animator = new Animator(glWindow);
+ animator.start();
+
+ Thread.sleep(durationPerTest); // manual testing
+
+ AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
+ AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+ glWindow1KA.reset();
+
+ //
+ // Test the key event order w/o auto-repeat
+ //
+ testKeyEventOrder(robot, glWindow1KA, 6);
+
+ // Remove listeners to avoid logging during dispose/destroy.
+ glWindow.removeKeyListener(glWindow1KA);
+
+ // Shutdown the test.
+ animator.stop();
+ }
+
+ static int atoi(final String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine());
+ */
+ System.out.println("durationPerTest: "+durationPerTest);
+ final String tstname = TestNewtKeyEventOrderAWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java
new file mode 100644
index 000000000..faf239910
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java
@@ -0,0 +1,240 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.event;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.Before;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Robot;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.swing.JFrame;
+
+import java.io.IOException;
+
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.KeyListener;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+
+import com.jogamp.opengl.test.junit.util.*;
+
+/**
+ * Testing key press and release events w/o AUTO-REPEAT
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 100;
+ static long awtWaitTimeout = 1000;
+
+ static GLCapabilities glCaps;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @AfterClass
+ public static void release() {
+ }
+
+ @Before
+ public void initTest() {
+ }
+
+ @After
+ public void releaseTest() {
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
+ final GLWindow glWindow = GLWindow.create(glCaps);
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+
+ testImpl(glWindow);
+
+ glWindow.destroy();
+ }
+
+ private void testNewtCanvasAWT_Impl(final boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException {
+ final GLWindow glWindow = GLWindow.create(glCaps);
+
+ // Wrap the window in a canvas.
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ if( !onscreen ) {
+ newtCanvasAWT.setShallUseOffscreenLayer(true);
+ }
+
+ // Add the canvas to a frame, and make it all visible.
+ final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle());
+ frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER);
+ frame1.setSize(width, height);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(true);
+ } } );
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true));
+
+ testImpl(glWindow);
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(false);
+ frame1.dispose();
+ }});
+ } catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ glWindow.destroy();
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException {
+ if( JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("Platform doesn't support onscreen rendering.");
+ return;
+ }
+ testNewtCanvasAWT_Impl(true);
+ }
+
+ @Test(timeout=180000) // TO 3 min
+ public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException {
+ if( !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("Platform doesn't support offscreen rendering.");
+ return;
+ }
+ testNewtCanvasAWT_Impl(false);
+ }
+
+ void testImpl(final GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException {
+ final Robot robot = new Robot();
+ robot.setAutoWaitForIdle(true);
+
+ final GLEventListener demo1 = new RedSquareES2();
+ glWindow.addGLEventListener(demo1);
+
+ final SimpleKeyPressRelease simpleKeyPressRelease = new SimpleKeyPressRelease();
+ glWindow.addKeyListener(simpleKeyPressRelease);
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true));
+
+ // Continuous animation ..
+ final Animator animator = new Animator(glWindow);
+ animator.start();
+
+ Thread.sleep(durationPerTest); // manual testing
+
+ AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
+ AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+
+ // Remove listeners to avoid logging during dispose/destroy.
+ glWindow.removeKeyListener(simpleKeyPressRelease);
+
+ // Shutdown the test.
+ animator.stop();
+ }
+
+ static int atoi(final String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ static class SimpleKeyPressRelease implements KeyListener {
+ int seq;
+
+ SimpleKeyPressRelease() {
+ reset();
+ }
+
+ public void reset() {
+ seq=0;
+ }
+
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ if( 0 == ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) ) {
+ seq++;
+ System.err.println(seq+": "+e);
+ }
+ }
+
+ @Override
+ public void keyReleased(final KeyEvent e) {
+ if( 0 == ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) ) {
+ seq++;
+ System.err.println(seq+": "+e);
+ }
+ }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine());
+ */
+ System.out.println("durationPerTest: "+durationPerTest);
+ final String tstname = TestNewtKeyPressReleaseUnmaskRepeatAWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus01SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus01SwingAWTRobot.java
index 5d6218df4..586c380bf 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus01SwingAWTRobot.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus01SwingAWTRobot.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,13 +20,13 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.newt;
+
+package com.jogamp.opengl.test.junit.newt.event;
import org.junit.Assert;
import org.junit.AfterClass;
@@ -48,24 +48,27 @@ import java.io.IOException;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
-
+import com.jogamp.opengl.test.junit.newt.TestListenerCom01AWT;
import com.jogamp.opengl.test.junit.util.*;
/**
- * Testing focus traversal of an AWT component tree with {@link NewtCanvasAWT} attached.
- * <p>
- * {@link JFrame} . {@link Container}+ . {@link NewtCanvasAWT} . {@link GLWindow}
+ * Testing focus <i>mouse-click</i> and <i>programmatic</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached.
+ * <p>
+ * {@link JFrame} . {@link Container}+ [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ]
* </p>
* <p>
- * <i>+ Container is the JFrame's implicit root content pane</i><br/>
+ * <i>+ Container is the JFrame's implicit root content pane</i><br/>
* </p>
*/
-public class TestFocus01SwingAWTRobot extends UITestCase {
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestParentingFocus01SwingAWTRobot extends UITestCase {
static int width, height;
static long durationPerTest = 10;
static long awtWaitTimeout = 1000;
@@ -90,55 +93,54 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
@Test
public void testFocus02RobotFocus() throws AWTException, InterruptedException, InvocationTargetException {
- Robot robot = new Robot();
+ final Robot robot = new Robot();
robot.setAutoWaitForIdle(true);
testFocus01ProgrFocusImpl(robot);
}
- private void testFocus01ProgrFocusImpl(Robot robot) throws AWTException,
+ private void testFocus01ProgrFocusImpl(final Robot robot) throws AWTException,
InvocationTargetException, InterruptedException {
- ArrayList<EventCountAdapter> eventCountAdapters = new ArrayList<EventCountAdapter>();
+ final ArrayList<EventCountAdapter> eventCountAdapters = new ArrayList<EventCountAdapter>();
// Create a window.
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
glWindow1.setTitle("testNewtChildFocus");
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
TestListenerCom01AWT.setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
- NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
+ final NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
glWindow1.addWindowListener(glWindow1FA);
// Monitor NEWT focus and keyboard events.
- NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
+ final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
eventCountAdapters.add(glWindow1KA);
glWindow1.addKeyListener(glWindow1KA);
// Wrap the window in a canvas.
final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1);
+ // newtCanvasAWT.setShallUseOffscreenLayer(true);
// Monitor AWT focus and keyboard events.
- AWTKeyAdapter newtCanvasAWTKA = new AWTKeyAdapter("NewtCanvasAWT");
+ final AWTKeyAdapter newtCanvasAWTKA = new AWTKeyAdapter("NewtCanvasAWT");
newtCanvasAWT.addKeyListener(newtCanvasAWTKA);
eventCountAdapters.add(newtCanvasAWTKA);
- AWTFocusAdapter newtCanvasAWTFA = new AWTFocusAdapter("NewtCanvasAWT");
+ final AWTFocusAdapter newtCanvasAWTFA = new AWTFocusAdapter("NewtCanvasAWT");
newtCanvasAWT.addFocusListener(newtCanvasAWTFA);
// Add the canvas to a frame, and make it all visible.
final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "
+ glWindow1.getTitle());
- AWTFocusAdapter frame1FA = new AWTFocusAdapter("frame1");
- frame1.addFocusListener(frame1FA);
frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER);
final Button button = new Button("Click me ..");
- AWTFocusAdapter buttonFA = new AWTFocusAdapter("Button");
+ final AWTFocusAdapter buttonFA = new AWTFocusAdapter("Button");
button.addFocusListener(buttonFA);
- AWTKeyAdapter buttonKA = new AWTKeyAdapter("Button");
+ final AWTKeyAdapter buttonKA = new AWTKeyAdapter("Button");
button.addKeyListener(buttonKA);
eventCountAdapters.add(buttonKA);
- AWTMouseAdapter buttonMA = new AWTMouseAdapter("Button");
+ final AWTMouseAdapter buttonMA = new AWTMouseAdapter("Button");
button.addMouseListener(buttonMA);
eventCountAdapters.add(buttonMA);
-
+
frame1.getContentPane().add(button, BorderLayout.NORTH);
frame1.setSize(width, height);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -146,12 +148,12 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
frame1.setVisible(true);
} } );
Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true));
- Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true));
AWTRobotUtil.clearAWTFocus(robot);
Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, frame1));
Thread.sleep(durationPerTest); // manual testing
-
+
int wait=0;
while(wait<awtWaitTimeout/100 && glWindow1.getTotalFPSFrames()<1) { Thread.sleep(awtWaitTimeout/10); wait++; }
System.err.println("Frames for initial setVisible(true): "+glWindow1.getTotalFPSFrames());
@@ -159,22 +161,22 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
Assert.assertTrue(0 < glWindow1.getTotalFPSFrames());
// Continuous animation ..
- Animator animator = new Animator(glWindow1);
+ final Animator animator = new Animator(glWindow1);
animator.start();
// Button Focus
Thread.sleep(200); // allow event sync
-
+
System.err.println("FOCUS AWT Button request");
EventCountAdapterUtil.reset(eventCountAdapters);
- AWTRobotUtil.assertRequestFocusAndWait(robot, button, button, buttonFA, frame1FA); // OSX sporadically button did not gain - major UI failure
+ AWTRobotUtil.assertRequestFocusAndWait(robot, button, button, buttonFA, null); // OSX sporadically button did not gain - major UI failure
Assert.assertEquals(false, glWindow1FA.focusGained());
Assert.assertEquals(false, newtCanvasAWTFA.focusGained());
System.err.println("FOCUS AWT Button sync");
AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, button, buttonKA);
- AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
+ AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
button, buttonMA);
- AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
+ AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
button, buttonMA);
// Request the AWT focus, which should automatically provide the NEWT window with focus.
@@ -182,11 +184,19 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
System.err.println("FOCUS NEWT Canvas/GLWindow request");
EventCountAdapterUtil.reset(eventCountAdapters);
AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonFA); // OSX sporadically button did not loose - minor UI failure
- Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA,
- AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA));
+ // Manually tested on Java7/[Linux,Windows] (where this assertion failed),
+ // Should be OK to have the AWT component assume it also has the focus.
+ // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA,
+ // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA));
+ if( !AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA) ) {
+ System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA);
+ }
System.err.println("FOCUS NEWT Canvas/GLWindow sync");
AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, glWindow1, glWindow1KA);
- Assert.assertEquals("AWT parent canvas received keyboard events", 0, newtCanvasAWTKA.getCount());
+ Assert.assertEquals("AWT parent canvas received non consumed keyboard events", newtCanvasAWTKA.getConsumedCount(), newtCanvasAWTKA.getCount());
+ if( !newtCanvasAWT.isAWTEventPassThrough() ) {
+ Assert.assertEquals("AWT parent canvas received consumed keyboard events", 0, newtCanvasAWTKA.getConsumedCount());
+ }
// Remove listeners to avoid logging during dispose/destroy.
glWindow1.removeKeyListener(glWindow1KA);
@@ -202,22 +212,23 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
frame1.setVisible(false);
frame1.dispose();
}});
- } catch( Throwable throwable ) {
+ } catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
- }
+ }
glWindow1.destroy();
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, false));
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
@@ -226,10 +237,10 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
/**
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println("Press enter to continue");
- System.err.println(stdin.readLine());
+ System.err.println(stdin.readLine());
*/
System.out.println("durationPerTest: "+durationPerTest);
- String tstname = TestFocus01SwingAWTRobot.class.getName();
+ final String tstname = TestParentingFocus01SwingAWTRobot.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus02SwingAWTRobot.java
index 0e87144da..584344ef5 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus02SwingAWTRobot.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,13 +20,13 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.newt;
+
+package com.jogamp.opengl.test.junit.newt.event;
import java.lang.reflect.*;
@@ -34,15 +34,20 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import java.awt.AWTException;
import java.awt.Button;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Robot;
+
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
import java.util.ArrayList;
import javax.media.opengl.*;
@@ -57,30 +62,36 @@ import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
/**
- * Testing focus traversal of an AWT component tree with {@link NewtCanvasAWT} attached.
- * <p>
- * {@link JFrame} . {@link JPanel}+ . {@link Container} . {@link NewtCanvasAWT} . {@link GLWindow}
+ * Testing focus <i>mouse-click</i> and <i>programmatic</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached.
+ * <p>
+ * {@link JFrame} . {@link JPanel}+ . {@link Container} [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ]
* </p>
* <p>
- * <i>+ JPanel is set as JFrame's root content pane</i><br/>
+ * <i>+ JPanel is set as JFrame's root content pane</i><br/>
* </p>
*/
-public class TestFocus02SwingAWTRobot extends UITestCase {
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestParentingFocus02SwingAWTRobot extends UITestCase {
static int width, height;
static long durationPerTest = 10;
static long awtWaitTimeout = 1000;
static GLCapabilities glCaps;
@BeforeClass
- public static void initClass() throws AWTException {
+ public static void initClass() throws AWTException, InterruptedException, InvocationTargetException {
width = 640;
height = 480;
- JFrame f = new JFrame();
- f.setSize(100,100);
- f.setVisible(true);
- f.dispose();
- f=null;
+ final JFrame f = new JFrame();
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f.setSize(100,100);
+ f.setVisible(true);
+ } } );
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f.dispose();
+ } } );
glCaps = new GLCapabilities(null);
}
@@ -88,45 +99,45 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
@AfterClass
public static void release() {
}
-
- private void testFocus01ProgrFocusImpl(Robot robot)
+
+ private void testFocus01ProgrFocusImpl(final Robot robot)
throws AWTException, InterruptedException, InvocationTargetException {
- ArrayList<EventCountAdapter> eventCountAdapters = new ArrayList<EventCountAdapter>();
+ final ArrayList<EventCountAdapter> eventCountAdapters = new ArrayList<EventCountAdapter>();
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
- GLEventListener demo1 = new GearsES2();
+ final GLEventListener demo1 = new GearsES2();
glWindow1.addGLEventListener(demo1);
- NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
+ final NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
glWindow1.addWindowListener(glWindow1FA);
- NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
+ final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
glWindow1.addKeyListener(glWindow1KA);
eventCountAdapters.add(glWindow1KA);
- NEWTMouseAdapter glWindow1MA = new NEWTMouseAdapter("GLWindow1");
+ final NEWTMouseAdapter glWindow1MA = new NEWTMouseAdapter("GLWindow1");
glWindow1.addMouseListener(glWindow1MA);
eventCountAdapters.add(glWindow1MA);
- NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1);
- AWTFocusAdapter newtCanvasAWTFA = new AWTFocusAdapter("NewtCanvasAWT");
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1);
+ final AWTFocusAdapter newtCanvasAWTFA = new AWTFocusAdapter("NewtCanvasAWT");
newtCanvasAWT.addFocusListener(newtCanvasAWTFA);
- AWTKeyAdapter newtCanvasAWTKA = new AWTKeyAdapter("NewtCanvasAWT");
+ final AWTKeyAdapter newtCanvasAWTKA = new AWTKeyAdapter("NewtCanvasAWT");
newtCanvasAWT.addKeyListener(newtCanvasAWTKA);
eventCountAdapters.add(newtCanvasAWTKA);
- AWTMouseAdapter newtCanvasAWTMA = new AWTMouseAdapter("NewtCanvasAWT");
+ final AWTMouseAdapter newtCanvasAWTMA = new AWTMouseAdapter("NewtCanvasAWT");
newtCanvasAWT.addMouseListener(newtCanvasAWTMA);
eventCountAdapters.add(newtCanvasAWTMA);
- Button buttonNorthInner = new Button("north");
- AWTFocusAdapter buttonNorthInnerFA = new AWTFocusAdapter("ButtonNorthInner");
+ final Button buttonNorthInner = new Button("north");
+ final AWTFocusAdapter buttonNorthInnerFA = new AWTFocusAdapter("ButtonNorthInner");
buttonNorthInner.addFocusListener(buttonNorthInnerFA);
- AWTKeyAdapter buttonNorthInnerKA = new AWTKeyAdapter("ButtonNorthInner");
+ final AWTKeyAdapter buttonNorthInnerKA = new AWTKeyAdapter("ButtonNorthInner");
buttonNorthInner.addKeyListener(buttonNorthInnerKA);
eventCountAdapters.add(buttonNorthInnerKA);
- AWTMouseAdapter buttonNorthInnerMA = new AWTMouseAdapter("ButtonNorthInner");
+ final AWTMouseAdapter buttonNorthInnerMA = new AWTMouseAdapter("ButtonNorthInner");
buttonNorthInner.addMouseListener(buttonNorthInnerMA);
eventCountAdapters.add(buttonNorthInnerMA);
- Container container1 = new Container();
+ final Container container1 = new Container();
container1.setLayout(new BorderLayout());
container1.add(buttonNorthInner, BorderLayout.NORTH);
container1.add(new Button("south"), BorderLayout.SOUTH);
@@ -134,16 +145,16 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
container1.add(new Button("west"), BorderLayout.WEST);
container1.add(newtCanvasAWT, BorderLayout.CENTER);
- Button buttonNorthOuter = new Button("north");
- AWTFocusAdapter buttonNorthOuterFA = new AWTFocusAdapter("ButtonNorthOuter");
+ final Button buttonNorthOuter = new Button("north");
+ final AWTFocusAdapter buttonNorthOuterFA = new AWTFocusAdapter("ButtonNorthOuter");
buttonNorthOuter.addFocusListener(buttonNorthOuterFA);
- AWTKeyAdapter buttonNorthOuterKA = new AWTKeyAdapter("ButtonNorthOuter");
+ final AWTKeyAdapter buttonNorthOuterKA = new AWTKeyAdapter("ButtonNorthOuter");
buttonNorthOuter.addKeyListener(buttonNorthOuterKA);
eventCountAdapters.add(buttonNorthOuterKA);
- AWTMouseAdapter buttonNorthOuterMA = new AWTMouseAdapter("ButtonNorthOuter");
+ final AWTMouseAdapter buttonNorthOuterMA = new AWTMouseAdapter("ButtonNorthOuter");
buttonNorthOuter.addMouseListener(buttonNorthOuterMA);
eventCountAdapters.add(buttonNorthOuterMA);
- JPanel jPanel1 = new JPanel();
+ final JPanel jPanel1 = new JPanel();
jPanel1.setLayout(new BorderLayout());
jPanel1.add(buttonNorthOuter, BorderLayout.NORTH);
jPanel1.add(new Button("south"), BorderLayout.SOUTH);
@@ -152,10 +163,8 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
jPanel1.add(container1, BorderLayout.CENTER);
final JFrame jFrame1 = new JFrame("Swing Parent JFrame");
- AWTFocusAdapter jFrame1FA = new AWTFocusAdapter("JFrame1");
- jFrame1.addFocusListener(jFrame1FA);
// jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
+ jFrame1.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
jFrame1.setContentPane(jPanel1);
jFrame1.setSize(width, height);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -163,7 +172,7 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
jFrame1.setVisible(true);
} } );
Assert.assertEquals(true, AWTRobotUtil.waitForVisible(jFrame1, true));
- Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true));
AWTRobotUtil.clearAWTFocus(robot);
Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, jFrame1));
@@ -174,56 +183,64 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
Assert.assertTrue(0 < glWindow1.getTotalFPSFrames());
// Continuous animation ..
- Animator animator1 = new Animator(glWindow1);
+ final Animator animator1 = new Animator(glWindow1);
animator1.start();
Thread.sleep(durationPerTest); // manual testing
-
+
// Button Outer Focus
Thread.sleep(100); // allow event sync
System.err.println("FOCUS AWT Button Outer request");
EventCountAdapterUtil.reset(eventCountAdapters);
- AWTRobotUtil.assertRequestFocusAndWait(robot, buttonNorthOuter, buttonNorthOuter, buttonNorthOuterFA, jFrame1FA); // OSX sporadically buttonNorthOuter did not gain - major UI failure
+ AWTRobotUtil.assertRequestFocusAndWait(robot, buttonNorthOuter, buttonNorthOuter, buttonNorthOuterFA, null); // OSX sporadically buttonNorthOuter did not gain - major UI failure
Assert.assertEquals(false, glWindow1FA.focusGained());
Assert.assertEquals(false, newtCanvasAWTFA.focusGained());
Assert.assertEquals(false, buttonNorthInnerFA.focusGained());
System.err.println("FOCUS AWT Button Outer sync");
AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, buttonNorthOuter, buttonNorthOuterKA); // OSX sporadically won't receive the keyboard input - major UI failure
- AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
+ AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
+ buttonNorthOuter, buttonNorthOuterMA);
+ AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
buttonNorthOuter, buttonNorthOuterMA);
- AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
- buttonNorthOuter, buttonNorthOuterMA);
// NEWT Focus
Thread.sleep(100); // allow event sync
System.err.println("FOCUS NEWT Canvas/GLWindow request");
EventCountAdapterUtil.reset(eventCountAdapters);
AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonNorthOuterFA);
- Assert.assertEquals(false, newtCanvasAWTFA.focusGained());
+ // Manually tested on Java7/[Linux,Windows] (where this assertion failed),
+ // Should be OK to have the AWT component assume it also has the focus.
+ // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA,
+ // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA));
+ if( !AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA) ) {
+ System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA);
+ }
Assert.assertEquals(false, buttonNorthInnerFA.focusGained());
- Assert.assertEquals(false, jFrame1FA.focusGained());
System.err.println("FOCUS NEWT Canvas/GLWindow sync");
AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, glWindow1, glWindow1KA);
- Assert.assertEquals("AWT parent canvas received keyboard events", 0, newtCanvasAWTKA.getCount());
- AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
+ Assert.assertEquals("AWT parent canvas received non consumed keyboard events", newtCanvasAWTKA.getConsumedCount(), newtCanvasAWTKA.getCount());
+ AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
glWindow1, glWindow1MA);
- AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
+ AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
glWindow1, glWindow1MA);
- Assert.assertEquals("AWT parent canvas received mouse events", 0, newtCanvasAWTMA.getCount());
+ if( !newtCanvasAWT.isAWTEventPassThrough() ) {
+ Assert.assertEquals("AWT parent canvas received consumed keyboard events", 0, newtCanvasAWTKA.getConsumedCount());
+ Assert.assertEquals("AWT parent canvas received mouse events", 0, newtCanvasAWTMA.getCount());
+ }
// Button Inner Focus
Thread.sleep(100); // allow event sync
System.err.println("FOCUS AWT Button request");
EventCountAdapterUtil.reset(eventCountAdapters);
AWTRobotUtil.assertRequestFocusAndWait(robot, buttonNorthInner, buttonNorthInner, buttonNorthInnerFA, glWindow1FA);
+ Assert.assertEquals(false, glWindow1FA.focusGained());
Assert.assertEquals(false, newtCanvasAWTFA.focusGained());
Assert.assertEquals(false, buttonNorthOuterFA.focusGained());
- Assert.assertEquals(false, jFrame1FA.focusGained());
System.err.println("FOCUS AWT Button sync");
AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, buttonNorthInner, buttonNorthInnerKA);
- AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
+ AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
buttonNorthInner, buttonNorthInnerMA);
- AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
+ AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
buttonNorthInner, buttonNorthInnerMA);
// NEWT Focus
@@ -231,35 +248,39 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
System.err.println("FOCUS NEWT Canvas/GLWindow request");
EventCountAdapterUtil.reset(eventCountAdapters);
AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonNorthInnerFA);
- Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA,
- AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA));
-
- Assert.assertEquals(false, newtCanvasAWTFA.focusGained());
+ // Manually tested on Java7/[Linux,Windows] (where this assertion failed),
+ // Should be OK to have the AWT component assume it also has the focus.
+ // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA,
+ // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA));
+ if( !AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA) ) {
+ System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA);
+ }
+
Assert.assertEquals(false, buttonNorthOuterFA.focusGained());
- Assert.assertEquals(false, jFrame1FA.focusGained());
System.err.println("FOCUS NEWT Canvas/GLWindow sync");
AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, glWindow1, glWindow1KA);
- Assert.assertEquals("AWT parent canvas received keyboard events", 0, newtCanvasAWTKA.getCount());
- AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
+ Assert.assertEquals("AWT parent canvas received non consumed keyboard events", newtCanvasAWTKA.getConsumedCount(), newtCanvasAWTKA.getCount());
+ AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
glWindow1, glWindow1MA);
- AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
+ AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
glWindow1, glWindow1MA);
- Assert.assertEquals("AWT parent canvas received mouse events", 0, newtCanvasAWTMA.getCount());
+ if( !newtCanvasAWT.isAWTEventPassThrough() ) {
+ Assert.assertEquals("AWT parent canvas received consumed keyboard events", 0, newtCanvasAWTKA.getConsumedCount());
+ Assert.assertEquals("AWT parent canvas received mouse events", 0, newtCanvasAWTMA.getCount());
+ }
animator1.stop();
Assert.assertEquals(false, animator1.isAnimating());
- final JFrame _jFrame1 = jFrame1;
- final JPanel _jPanel1 = jPanel1;
- final Container _container1 = container1;
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- _jFrame1.setVisible(false);
- _jPanel1.remove(_container1);
- _jFrame1.dispose();
+ jFrame1.setVisible(false);
+ jPanel1.remove(container1);
+ jFrame1.dispose();
} });
glWindow1.destroy();
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, false));
}
@Test
@@ -269,22 +290,22 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
@Test
public void testFocus02RobotFocus() throws AWTException, InterruptedException, InvocationTargetException {
- Robot robot = new Robot();
+ final Robot robot = new Robot();
robot.setAutoWaitForIdle(true);
testFocus01ProgrFocusImpl(robot);
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
@SuppressWarnings("unused")
- public static void main(String args[])
- throws IOException, AWTException, InterruptedException, InvocationTargetException
+ public static void main(final String args[])
+ throws IOException, AWTException, InterruptedException, InvocationTargetException
{
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
@@ -292,14 +313,14 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
}
}
if(true) {
- String tstname = TestFocus02SwingAWTRobot.class.getName();
+ final String tstname = TestParentingFocus02SwingAWTRobot.class.getName();
org.junit.runner.JUnitCore.main(tstname);
- } else {
- TestFocus02SwingAWTRobot.initClass();
- TestFocus02SwingAWTRobot test = new TestFocus02SwingAWTRobot();
+ } else {
+ TestParentingFocus02SwingAWTRobot.initClass();
+ final TestParentingFocus02SwingAWTRobot test = new TestParentingFocus02SwingAWTRobot();
test.testFocus01ProgrFocus();
test.testFocus02RobotFocus();
- TestFocus02SwingAWTRobot.release();
+ TestParentingFocus02SwingAWTRobot.release();
}
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus03KeyTraversalAWT.java
index f39b5df3b..ace039688 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus03KeyTraversalAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,13 +20,13 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.newt.parenting;
+
+package com.jogamp.opengl.test.junit.newt.event;
import java.lang.reflect.*;
import java.util.HashSet;
@@ -36,6 +36,8 @@ import java.util.Set;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import java.awt.AWTException;
import java.awt.AWTKeyStroke;
@@ -61,19 +63,28 @@ import jogamp.newt.driver.DriverClearFocus;
import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter;
-public class TestParentingFocusTraversal01AWT extends UITestCase {
+/**
+ * Testing focus <i>key</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached.
+ * <p>
+ * {@link Frame} [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ]
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestParentingFocus03KeyTraversalAWT extends UITestCase {
static Dimension glSize, fSize;
static int numFocus = 8;
static long durationPerTest = numFocus * 200;
static GLCapabilities glCaps;
static boolean manual = false;
+ static boolean forceGL3 = false;
@BeforeClass
public static void initClass() {
glSize = new Dimension(200,200);
fSize = new Dimension(300,300);
- glCaps = new GLCapabilities(null);
+ glCaps = new GLCapabilities( forceGL3 ? GLProfile.get(GLProfile.GL3) : null );
}
@Test
@@ -86,24 +97,24 @@ public class TestParentingFocusTraversal01AWT extends UITestCase {
testWindowParentingAWTFocusTraversal(false);
}
- public void testWindowParentingAWTFocusTraversal(boolean onscreen) throws InterruptedException, InvocationTargetException, AWTException {
- Robot robot = new Robot();
-
+ public void testWindowParentingAWTFocusTraversal(final boolean onscreen) throws InterruptedException, InvocationTargetException, AWTException {
+ final Robot robot = new Robot();
+
// Bug 4908075 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4908075
// Bug 6463168 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6463168
{
final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
- final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
final AWTKeyStroke newBack = AWTKeyStroke.getAWTKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE, 0, false);
Assert.assertNotNull(newBack);
- final Set<AWTKeyStroke> bwdKeys2 = new HashSet<AWTKeyStroke>(bwdKeys);
+ final Set<AWTKeyStroke> bwdKeys2 = new HashSet<AWTKeyStroke>(bwdKeys);
bwdKeys2.add(newBack);
kfm.setDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, bwdKeys2);
}
{
final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
- final Set<AWTKeyStroke> fwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
- final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ final Set<AWTKeyStroke> fwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
Iterator<AWTKeyStroke> iter;
for(iter = fwdKeys.iterator(); iter.hasNext(); ) {
System.err.println("FTKL.fwd-keys: "+iter.next());
@@ -112,7 +123,7 @@ public class TestParentingFocusTraversal01AWT extends UITestCase {
System.err.println("FTKL.bwd-keys: "+iter.next());
}
}
-
+
final Frame frame1 = new Frame("AWT Parent Frame");
final Button cWest = new Button("WEST");
final Button cEast = new Button("EAST");
@@ -124,55 +135,58 @@ public class TestParentingFocusTraversal01AWT extends UITestCase {
newtCanvasAWT1.setFocusable(true);
// Test FocusAdapter
- NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
+ final NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
glWindow1.addWindowListener(glWindow1FA);
- AWTFocusAdapter bWestFA = new AWTFocusAdapter("WEST");
+ final AWTFocusAdapter bWestFA = new AWTFocusAdapter("WEST");
cWest.addFocusListener(bWestFA);
- AWTFocusAdapter bEastFA = new AWTFocusAdapter("EAST");
+ final AWTFocusAdapter bEastFA = new AWTFocusAdapter("EAST");
cEast.addFocusListener(bEastFA);
-
+
// Test KeyAdapter
- NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
+ final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
glWindow1.addKeyListener(glWindow1KA);
- AWTKeyAdapter bWestKA = new AWTKeyAdapter("West");
+ final AWTKeyAdapter bWestKA = new AWTKeyAdapter("West");
cWest.addKeyListener(bWestKA);
- AWTKeyAdapter bEastKA = new AWTKeyAdapter("East");
+ final AWTKeyAdapter bEastKA = new AWTKeyAdapter("East");
cEast.addKeyListener(bEastKA);
-
+
// demo ..
- GLEventListener demo1 = new GearsES2(1);
+ final GLEventListener demo1 = new GearsES2(1);
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
- glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1));
+ glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1, null));
glWindow1.addKeyListener(new KeyAdapter() {
- public void keyTyped(KeyEvent e) {
- if(e.getKeyChar()=='c') {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ if(e.getKeyChar()=='c') {
System.err.println("Focus Clear");
if(glWindow1.getDelegatedWindow() instanceof DriverClearFocus) {
((DriverClearFocus)glWindow1.getDelegatedWindow()).clearFocus();
}
- } else if(e.getKeyChar()=='e') {
+ } else if(e.getKeyChar()=='e') {
System.err.println("Focus East");
try {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
cEast.requestFocusInWindow();
- }
+ }
});
- } catch (Exception ex) { ex.printStackTrace(); }
- } else if(e.getKeyChar()=='w') {
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ } else if(e.getKeyChar()=='w') {
System.err.println("Focus West");
try {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
cWest.requestFocusInWindow();
- }
+ }
});
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
}
- }
+ }
});
- GLAnimatorControl animator1 = new Animator(glWindow1);
+ final GLAnimatorControl animator1 = new Animator(glWindow1);
animator1.start();
// make frame
@@ -182,99 +196,108 @@ public class TestParentingFocusTraversal01AWT extends UITestCase {
frame1.add(newtCanvasAWT1, BorderLayout.CENTER);
frame1.add(cEast, BorderLayout.EAST);
- frame1.setLocation(0, 0);
- frame1.setSize(fSize);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- frame1.validate();
+ frame1.setLocation(0, 0);
+ frame1.setSize(fSize);
+ frame1.validate();
frame1.setVisible(true);
}});
Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true));
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true));
Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent());
AWTRobotUtil.clearAWTFocus(robot);
Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, frame1));
-
+
Assert.assertEquals(true, animator1.isAnimating());
// Assert.assertEquals(false, animator1.isPaused());
Assert.assertNotNull(animator1.getThread());
-
+
if(manual) {
- Thread.sleep(durationPerTest);
+ Thread.sleep(durationPerTest);
} else {
//
// initial focus on bWest
- //
+ //
AWTRobotUtil.assertRequestFocusAndWait(robot, cWest, cWest, bWestFA, null);
Thread.sleep(durationPerTest/numFocus);
-
+
//
// forth
//
-
+
// bWest -> glWin
AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, cWest, null);
- Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
+ Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
Assert.assertEquals(true, glWindow1FA.focusGained());
Assert.assertEquals(true, bWestFA.focusLost());
Thread.sleep(durationPerTest/numFocus);
-
+
// glWin -> bEast
AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, glWindow1, null);
- Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cEast, bEastFA, glWindow1FA));
+ Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cEast, bEastFA, glWindow1FA));
Assert.assertEquals(true, bEastFA.focusGained());
Assert.assertEquals(true, glWindow1FA.focusLost());
Thread.sleep(durationPerTest/numFocus);
-
+
//
// back (using custom back traversal key 'backspace')
//
// bEast -> glWin
AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, cEast, null);
- Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bEastFA));
+ Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bEastFA));
Assert.assertEquals(true, glWindow1FA.focusGained());
Assert.assertEquals(true, bEastFA.focusLost());
Thread.sleep(durationPerTest/numFocus);
-
+
AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, glWindow1, null);
- Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA));
+ Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA));
Assert.assertEquals(true, bWestFA.focusGained());
Assert.assertEquals(true, glWindow1FA.focusLost());
- Thread.sleep(durationPerTest/numFocus);
-
- // direct AWT request focus
+ Thread.sleep(durationPerTest/numFocus);
+
+ System.err.println("Test: Direct NewtCanvasAWT focus");
try {
java.awt.EventQueue.invokeAndWait(new Runnable() {
public void run() {
newtCanvasAWT1.requestFocus();
- }
+ }
});
- } catch (Exception ex) { ex.printStackTrace(); }
- Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
Assert.assertEquals(true, glWindow1FA.focusGained());
Assert.assertEquals(true, bWestFA.focusLost());
Thread.sleep(durationPerTest/numFocus);
-
- // direct AWT request focus
+
+ System.err.println("Test: Direct AWT Button-West focus");
try {
java.awt.EventQueue.invokeAndWait(new Runnable() {
public void run() {
cWest.requestFocus();
- }
+ }
});
- } catch (Exception ex) { ex.printStackTrace(); }
- Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA));
+ } catch (final Exception ex) { ex.printStackTrace(); }
+ Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA));
Assert.assertEquals(true, bWestFA.focusGained());
Assert.assertEquals(true, glWindow1FA.focusLost());
Thread.sleep(durationPerTest/numFocus);
-
- // direct NEWT request focus
+
+ System.err.println("Test: Direct NEWT-Child request focus");
glWindow1.requestFocus();
- Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
+ {
+ // Short: Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
+ // More verbose:
+ final boolean ok = AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA);
+ System.err.println("glWindow hasFocus "+glWindow1.hasFocus());
+ System.err.println("glWindow1FA "+glWindow1FA);
+ System.err.println("bWestFA "+bWestFA);
+ Assert.assertTrue("Did not gain focus", ok);
+ }
Assert.assertEquals(true, glWindow1FA.focusGained());
Assert.assertEquals(true, bWestFA.focusLost());
- Thread.sleep(durationPerTest/numFocus);
+ Thread.sleep(durationPerTest/numFocus);
}
-
+
animator1.stop();
Assert.assertEquals(false, animator1.isAnimating());
Assert.assertEquals(false, animator1.isPaused());
@@ -287,10 +310,10 @@ public class TestParentingFocusTraversal01AWT extends UITestCase {
glWindow1.destroy();
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -300,23 +323,25 @@ public class TestParentingFocusTraversal01AWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
} else if(args[i].equals("-manual")) {
manual = true;
+ } else if(args[i].equals("-gl3")) {
+ forceGL3 = true;
}
}
- String tstname = TestParentingFocusTraversal01AWT.class.getName();
+ final String tstname = TestParentingFocus03KeyTraversalAWT.class.getName();
/*
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/ManualScreenMode03aNEWT.java
index 29ec443f7..2133f25c2 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/ManualScreenMode03aNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,13 +20,13 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.newt;
+
+package com.jogamp.opengl.test.junit.newt.mm;
import java.io.IOException;
import javax.media.opengl.GLCapabilities;
@@ -35,28 +35,29 @@ import javax.media.opengl.GLProfile;
import com.jogamp.opengl.util.Animator;
import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
-import com.jogamp.newt.ScreenMode;
+import com.jogamp.newt.MonitorMode;
import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.newt.util.ScreenModeUtil;
+import com.jogamp.newt.util.MonitorModeUtil;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
import java.util.List;
import javax.media.nativewindow.util.Dimension;
/**
- * Manual testing the ScreenImpl shutdown hook,
+ * Manual testing the ScreenImpl shutdown hook,
* which shall reset the ScreenMode to it's original state
* when the application exists (normal or ctrl-c).
*/
-public class ManualScreenMode03NEWT extends UITestCase {
+public class ManualScreenMode03aNEWT extends UITestCase {
static int waitTime = 7000; // 1 sec
-
- static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) {
+
+ static GLWindow createWindow(final Screen screen, final GLCapabilities caps, final int width, final int height, final boolean onscreen, final boolean undecorated) {
caps.setOnscreen(onscreen);
- GLWindow window = GLWindow.create(screen, caps);
+ final GLWindow window = GLWindow.create(screen, caps);
window.setSize(width, height);
window.addGLEventListener(new GearsES2());
window.setVisible(true);
@@ -64,47 +65,49 @@ public class ManualScreenMode03NEWT extends UITestCase {
}
public void run() {
- int width = 640;
- int height = 480;
- GLProfile glp = GLProfile.getDefault();
- GLCapabilities caps = new GLCapabilities(glp);
- Display display = NewtFactory.createDisplay(null); // local display
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
- GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
+ final int width = 640;
+ final int height = 480;
+ final GLProfile glp = GLProfile.getDefault();
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final Display display = NewtFactory.createDisplay(null); // local display
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
- List<ScreenMode> screenModes = screen.getScreenModes();
- if(null==screenModes) {
+ final Animator animator = new Animator(window);
+ animator.start();
+
+ final MonitorDevice monitor = window.getMainMonitor();
+
+ final MonitorMode mmCurrent = monitor.queryCurrentMode();
+ final MonitorMode mmOrig = monitor.getOriginalMode();
+ System.err.println("[0] orig : "+mmOrig);
+ System.err.println("[0] current: "+mmCurrent);
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ if(null==monitorModes) {
// no support ..
System.err.println("Your platform has no ScreenMode change support, sorry");
return;
}
- Animator animator = new Animator(window);
- animator.start();
-
- ScreenMode smCurrent = screen.getCurrentScreenMode();
- ScreenMode smOrig = screen.getOriginalScreenMode();
- System.err.println("[0] current/orig: "+smCurrent);
-
- screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate());
- screenModes = ScreenModeUtil.filterByRotation(screenModes, 0);
- screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601));
- screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
-
- ScreenMode sm = (ScreenMode) screenModes.get(0);
- System.err.println("[0] set current: "+sm);
- screen.setCurrentScreenMode(sm);
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0);
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601));
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate());
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+ final MonitorMode mm = monitorModes.get(0);
+ System.err.println("[0] set current: "+mm);
+ monitor.setCurrentMode(mm);
System.err.print("[0] post setting .. wait <");
try {
Thread.sleep(waitTime);
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
}
System.err.println("done>");
System.exit(0);
}
- public static void main(String args[]) throws IOException {
- ManualScreenMode03NEWT t = new ManualScreenMode03NEWT();
+ public static void main(final String args[]) throws IOException {
+ final ManualScreenMode03aNEWT t = new ManualScreenMode03aNEWT();
t.run();
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java
new file mode 100644
index 000000000..860560658
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java
@@ -0,0 +1,236 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.mm;
+
+import java.io.IOException;
+
+import javax.media.nativewindow.NativeWindowFactory;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.util.MonitorModeUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.nativewindow.util.SurfaceSize;
+import javax.media.opengl.GLProfile;
+
+import jogamp.newt.MonitorDeviceImpl;
+import jogamp.newt.MonitorModeProps;
+
+/**
+ * Validating consistency of MonitorMode data from Screen (all modes)
+ * and from a particular MonitorDevice.
+ * <p>
+ * Also validates the descending order of the given MonitorMode lists.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestScreenMode00aNEWT extends UITestCase {
+ static int screenIdx = 0;
+ static int width, height;
+
+ static int waitTimeShort = 4; //1 sec
+ static int waitTimeLong = 6; //6 sec
+
+
+
+ @BeforeClass
+ public static void initClass() {
+ setResetXRandRIfX11AfterClass();
+ GLProfile.initSingleton(); // hack to initialize GL for BCM_IV (Rasp.Pi)
+ NativeWindowFactory.initSingleton();
+ width = 640;
+ height = 480;
+ }
+
+ @Test
+ public void testScreenModeInfo00() throws InterruptedException {
+ final DimensionImmutable res = new Dimension(640, 480);
+ final SurfaceSize surfsz = new SurfaceSize(res, 32);
+ final MonitorMode modeOut = new MonitorMode(surfsz, 60.0f, 0, 0);
+ System.err.println("00 out: "+modeOut);
+ final MonitorModeProps.Cache cache = new MonitorModeProps.Cache();
+ cache.monitorModes.add(modeOut);
+ {
+ final int[] props = MonitorModeProps.streamOutMonitorMode(modeOut);
+ final MonitorMode modeIn = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+ System.err.println("00 in : "+modeIn);
+
+ Assert.assertEquals(modeOut.getSurfaceSize().getResolution(), modeIn.getSurfaceSize().getResolution());
+
+ Assert.assertEquals(modeOut.getSurfaceSize(), modeIn.getSurfaceSize());
+
+ Assert.assertEquals(modeOut.hashCode(), modeIn.hashCode());
+
+ Assert.assertEquals(modeOut, modeIn);
+ }
+
+ final DimensionImmutable sizeMM = new Dimension(50, 50);
+ final Rectangle viewport = new Rectangle(0, 0, 1920, 1080);
+ final ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
+ supportedModes.add(modeOut);
+ final MonitorDevice monOut = new MonitorDeviceImpl(null, -1, sizeMM, viewport, viewport, modeOut, supportedModes);
+ System.err.println("01 out : "+monOut);
+ cache.monitorDevices.add(monOut);
+ {
+ final int[] props = MonitorModeProps.streamOutMonitorDevice(monOut);
+ final MonitorDevice monIn = MonitorModeProps.streamInMonitorDevice(null, cache, null, props, 0);
+ System.err.println("01 in : "+monIn);
+
+ Assert.assertEquals(monOut.getCurrentMode(), monOut.getOriginalMode());
+ Assert.assertEquals(monOut.getSupportedModes(), monIn.getSupportedModes());
+ Assert.assertEquals(monOut.getViewport(), monIn.getViewport());
+ Assert.assertEquals(monOut.getViewportInWindowUnits(), monIn.getViewportInWindowUnits());
+ Assert.assertEquals(monOut.getOriginalMode(), monIn.getOriginalMode());
+ Assert.assertEquals(monOut.getCurrentMode(), monIn.getCurrentMode());
+ Assert.assertEquals(monOut.hashCode(), monIn.hashCode());
+ Assert.assertEquals(monOut, monIn);
+ }
+ }
+
+ @Test
+ public void testScreenModeInfo01() throws InterruptedException {
+ final Display dpy = NewtFactory.createDisplay(null);
+ final Screen screen = NewtFactory.createScreen(dpy, screenIdx);
+ screen.addReference();
+ Assert.assertEquals(true,screen.isNativeValid());
+ Assert.assertEquals(true,screen.getDisplay().isNativeValid());
+ System.err.println("Screen: "+screen.toString());
+ final List<MonitorMode> allMonitorModes = screen.getMonitorModes();
+ Assert.assertTrue(allMonitorModes.size()>0);
+ {
+ int i=0;
+ MonitorMode mmPre = null;
+ for(final Iterator<MonitorMode> iMode=allMonitorModes.iterator(); iMode.hasNext(); i++) {
+ final MonitorMode mm = iMode.next();
+ System.err.println(String.format("All-0[%03d]: %s", i, mm));
+ if( null != mmPre ) {
+ Assert.assertTrue("Wrong order", mmPre.compareTo(mm) >= 0);
+ }
+ mmPre = mm;
+ }
+ }
+ MonitorModeUtil.sort(allMonitorModes, true /* ascendingOrder*/);
+ {
+ int i=0;
+ MonitorMode mmPre = null;
+ for(final Iterator<MonitorMode> iMode=allMonitorModes.iterator(); iMode.hasNext(); i++) {
+ final MonitorMode mm = iMode.next();
+ System.err.println(String.format("All-1[%03d]: %s", i, mm));
+ if( null != mmPre ) {
+ Assert.assertTrue("Wrong order", mmPre.compareTo(mm) <= 0);
+ }
+ mmPre = mm;
+ }
+ }
+
+ final List<MonitorDevice> monitors = screen.getMonitorDevices();
+ Assert.assertTrue(monitors.size()>0);
+ int j=0;
+ for(final Iterator<MonitorDevice> iMonitor=monitors.iterator(); iMonitor.hasNext(); j++) {
+ final MonitorDevice monitor = iMonitor.next();
+ System.err.println(j+": "+monitor);
+ final List<MonitorMode> modes = monitor.getSupportedModes();
+ Assert.assertTrue(modes.size()>0);
+ int i=0;
+ MonitorMode mmPre = null;
+ for(final Iterator<MonitorMode> iMode=modes.iterator(); iMode.hasNext(); i++) {
+ final MonitorMode mm = iMode.next();
+ System.err.println(String.format("[%02d][%03d]: %s", j, i, mm));
+ if( null != mmPre ) {
+ Assert.assertTrue("Wrong order", mmPre.compareTo(mm) >= 0);
+ }
+ mmPre = mm;
+ }
+ Assert.assertTrue(allMonitorModes.containsAll(modes));
+
+ final MonitorMode sm_o = monitor.getOriginalMode();
+ Assert.assertNotNull(sm_o);
+ final MonitorMode sm_c = monitor.queryCurrentMode();
+ System.err.println("[0] orig : "+sm_o);
+ System.err.println("[0] current: "+sm_c);
+ Assert.assertNotNull(sm_c);
+ Assert.assertEquals(sm_o, sm_c);
+ }
+
+ final RectangleImmutable zero = new Rectangle();
+
+ final Rectangle monitorViewPU = new Rectangle();
+ final Rectangle monitorViewWU = new Rectangle();
+ MonitorDevice.unionOfViewports(monitorViewPU, monitorViewWU, monitors);
+ System.err.println("Test.0: Monitor union viewport: "+monitorViewPU+" [pu] / "+monitorViewWU+" [wu]");
+ Assert.assertNotEquals(zero, monitorViewPU);
+ Assert.assertNotEquals(zero, monitorViewWU);
+
+ final RectangleImmutable screenViewPU = screen.getViewport();
+ final RectangleImmutable screenViewWU = screen.getViewportInWindowUnits();
+ System.err.println("Test.1: Screen viewport: "+screenViewPU+" [pu] / "+screenViewWU+" [wu]");
+ Assert.assertNotEquals(zero, screenViewPU);
+ Assert.assertNotEquals(zero, screenViewWU);
+
+ screen.removeReference();
+
+ Assert.assertEquals(false,screen.isNativeValid());
+ Assert.assertEquals(false,screen.getDisplay().isNativeValid());
+ }
+
+ static int atoi(final String a) {
+ try {
+ return Integer.parseInt(a);
+ } catch (final Exception ex) { throw new RuntimeException(ex); }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-screen")) {
+ i++;
+ screenIdx = atoi(args[i]);
+ }
+ }
+ final String tstname = TestScreenMode00aNEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00bNEWT.java
index 75a312686..518dbb8db 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00bNEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,13 +20,13 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
-package com.jogamp.opengl.test.junit.newt;
+
+package com.jogamp.opengl.test.junit.newt.mm;
import java.io.IOException;
import javax.media.nativewindow.NativeWindowFactory;
@@ -34,13 +34,17 @@ import javax.media.nativewindow.NativeWindowFactory;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
-import com.jogamp.newt.ScreenMode;
+import com.jogamp.newt.MonitorMode;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
@@ -49,14 +53,20 @@ import java.util.List;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
+/**
+ * Queries the current MonitorMode 50 times,
+ * stressing a possible race condition.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestScreenMode00bNEWT extends UITestCase {
static int width, height;
-
+
static int waitTimeShort = 4; //1 sec
static int waitTimeLong = 6; //6 sec
-
+
@BeforeClass
public static void initClass() {
+ setResetXRandRIfX11AfterClass();
NativeWindowFactory.initSingleton();
width = 640;
height = 480;
@@ -64,56 +74,58 @@ public class TestScreenMode00bNEWT extends UITestCase {
@Test
public void testScreenModeInfo01() throws InterruptedException {
- Display display = NewtFactory.createDisplay(null);
- Screen screen = NewtFactory.createScreen(display, 0);
+ final Display display = NewtFactory.createDisplay(null);
+ final Screen screen = NewtFactory.createScreen(display, 0);
// screen.addReference();
-
+
// put some load on the screen/display context ..
- GLCapabilitiesImmutable caps = new GLCapabilities(null);
- GLWindow window = GLWindow.create(screen, caps);
+ final GLCapabilitiesImmutable caps = new GLCapabilities(null);
+ final GLWindow window = GLWindow.create(screen, caps);
window.addGLEventListener(new GearsES2());
window.setSize(256, 256);
window.setVisible(true);
- Animator anim = new Animator(window);
+ final Animator anim = new Animator(window);
anim.start();
Assert.assertEquals(true,window.isNativeValid());
Assert.assertEquals(true,screen.isNativeValid());
Assert.assertEquals(true,display.isNativeValid());
-
- List<ScreenMode> screenModes = screen.getScreenModes();
+
+ final List<MonitorMode> screenModes = screen.getMonitorModes();
Assert.assertTrue(screenModes.size()>0);
int i=0;
- for(Iterator<ScreenMode> iter=screenModes.iterator(); iter.hasNext(); i++) {
+ for(final Iterator<MonitorMode> iter=screenModes.iterator(); iter.hasNext(); i++) {
System.err.println(i+": "+iter.next());
}
- ScreenMode sm_o = screen.getOriginalScreenMode();
-
- Assert.assertNotNull(sm_o);
- ScreenMode sm_c = screen.getCurrentScreenMode();
- Assert.assertNotNull(sm_c);
- System.err.println("orig: "+sm_o);
- System.err.println("curr: "+sm_c);
-
+ final MonitorDevice monitor = window.getMainMonitor();
+ final MonitorMode mm_o = monitor.getOriginalMode();
+
+ Assert.assertNotNull(mm_o);
+ MonitorMode mm_c = monitor.queryCurrentMode();
+ Assert.assertNotNull(mm_c);
+ System.err.println("orig: "+mm_o);
+ System.err.println("curr: "+mm_c);
+
for(i=0; i<50; i++) {
- sm_c = screen.getCurrentScreenMode();
- Assert.assertNotNull(sm_c);
+ mm_c = monitor.queryCurrentMode();
+ Assert.assertNotNull(mm_c);
System.err.print("."+i);
}
System.err.println("!");
-
+
// screen.removeReference();
anim.stop();
window.destroy();
Assert.assertEquals(false,window.isVisible());
Assert.assertEquals(false,window.isNativeValid());
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
Assert.assertEquals(false,screen.isNativeValid());
Assert.assertEquals(false,display.isNativeValid());
}
- public static void main(String args[]) throws IOException {
- String tstname = TestScreenMode00bNEWT.class.getName();
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestScreenMode00bNEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java
new file mode 100644
index 000000000..37440457a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java
@@ -0,0 +1,282 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.mm;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.MonitorModeUtil;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import java.util.List;
+
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+
+/**
+ * Tests X11 XRandR MonitorMode reset via {@link UITestCase#resetXRandRIfX11()}.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestScreenMode00cNEWT extends UITestCase {
+ static boolean manualTest = false;
+ static GLProfile glp;
+ static int width, height;
+
+ static final int waitTimeShort = 2000;
+ static long duration = 4000;
+
+ static int mm_width = 800;
+ static int mm_height = 600;
+
+ @BeforeClass
+ public static void initClass() {
+ setResetXRandRIfX11AfterClass();
+ NativeWindowFactory.initSingleton();
+ if( !manualTest || NativeWindowFactory.TYPE_X11 != NativeWindowFactory.getNativeWindowType(true) ) {
+ setTestSupported(false);
+ return;
+ }
+ width = 100;
+ height = 100;
+ glp = GLProfile.getDefault();
+ }
+
+ @AfterClass
+ public static void releaseClass() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+ }
+
+ static Window createWindow(final Screen screen, final GLCapabilities caps, final String name, final int x, final int y, final int width, final int height) {
+ Assert.assertNotNull(caps);
+
+ final GLWindow window = GLWindow.create(screen, caps);
+ // Window window = NewtFactory.createWindow(screen, caps);
+ window.setTitle(name);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.addGLEventListener(new GearsES2());
+ Assert.assertNotNull(window);
+ window.setVisible(true);
+ return window;
+ }
+
+ static void destroyWindow(final Window window) throws InterruptedException {
+ if(null!=window) {
+ window.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false));
+ }
+ }
+
+ @Test
+ public void testScreenModeChange01() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ final Window window0 = createWindow(screen, caps, "win0", 0, 0, width, height);
+ Assert.assertNotNull(window0);
+
+ Rectangle window0WindowBounds = window0.getBounds();
+ DimensionImmutable window0SurfaceSize = new Dimension(window0.getSurfaceWidth(), window0.getSurfaceHeight());
+ System.err.println("Test.0: Window bounds : "+window0WindowBounds+" [wu] within "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.0: Window size : "+window0SurfaceSize+" [pixels]");
+ System.err.println("Test.0: Screen viewport : "+screen.getViewport()+" [pixels]");
+
+ final List<MonitorMode> allMonitorModes = screen.getMonitorModes();
+ Assert.assertTrue(allMonitorModes.size()>0);
+ if(allMonitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no MonitorMode change support (all), sorry");
+ destroyWindow(window0);
+ return;
+ }
+
+ final MonitorDevice monitor = screen.getMonitorDevices().get(0);
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ Assert.assertTrue(monitorModes.size()>0);
+ if(monitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no MonitorMode change support (monitor), sorry");
+ destroyWindow(window0);
+ return;
+ }
+ Assert.assertTrue(allMonitorModes.containsAll(monitorModes));
+
+ final MonitorMode mmSet0 = monitor.queryCurrentMode();
+ Assert.assertNotNull(mmSet0);
+ final MonitorMode mmOrig = monitor.getOriginalMode();
+ Assert.assertNotNull(mmOrig);
+ System.err.println("[0] orig : "+mmOrig);
+ System.err.println("[0] current: "+mmSet0);
+ Assert.assertEquals(mmSet0, mmOrig);
+
+
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(mm_width+1, mm_height+1));
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate());
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ // set mode
+ {
+ final MonitorMode mm = monitorModes.get(0);
+ System.err.println("[1] set current: "+mm);
+ final boolean smOk = monitor.setCurrentMode(mm);
+ final MonitorMode mmCachedCurrent = monitor.getCurrentMode();
+ final MonitorMode mmQueriedCurrent = monitor.queryCurrentMode();
+ final boolean mmCurrentEquals = mmQueriedCurrent.equals(mmCachedCurrent);
+ System.err.println("[1] changeOK : "+smOk);
+ System.err.println("[1] has current cached : "+mmCachedCurrent);
+ System.err.println("[1] has current queried : "+mmQueriedCurrent+", equal "+mmCurrentEquals);
+ window0WindowBounds = window0.getBounds();
+ window0SurfaceSize = new Dimension(window0.getSurfaceWidth(), window0.getSurfaceHeight());
+ System.err.println("Test.1: Window bounds : "+window0WindowBounds+" [wu] within "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.1: Window size : "+window0SurfaceSize+" [pixels]");
+ System.err.println("Test.1: Screen viewport : "+screen.getViewport()+" [pixels]");
+
+ Assert.assertTrue(monitor.isModeChangedByUs());
+ Assert.assertEquals(mm, mmCachedCurrent);
+ Assert.assertNotSame(mmOrig, mmCachedCurrent);
+ Assert.assertEquals(mmCachedCurrent, mmQueriedCurrent);
+ Assert.assertTrue(smOk);
+ }
+
+ Thread.sleep(duration);
+
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+ Assert.assertEquals(true,window0.isNativeValid());
+ Assert.assertEquals(true,window0.isVisible());
+
+ // WARNING: See note in 'UITestCase.resetXRandRIfX11();'
+ final int xrandrErrorCode;
+ if( 0 == ( xrandrErrorCode = UITestCase.resetXRandRIfX11() ) ) {
+ System.err.println("XRandR Reset :"+monitor.queryCurrentMode());
+ } else {
+ System.err.println("XRandR Reset : Failed w/ errorCode "+xrandrErrorCode+", fall back to manual reset");
+ final boolean smOk = monitor.setCurrentMode(mmOrig);
+ System.err.println("[X] changeOK : "+smOk);
+ }
+ Thread.sleep(duration);
+ validateScreenModeReset0(mmOrig);
+
+ destroyWindow(window0);
+
+ Thread.sleep(waitTimeShort);
+ validateScreenModeReset(mmOrig);
+ }
+
+ void validateScreenModeReset0(final MonitorMode mmOrig) {
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ screen.addReference();
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+
+ final MonitorDevice monitor = screen.getMonitorDevices().get(0);
+ Assert.assertEquals(mmOrig, monitor.queryCurrentMode());
+
+ screen.removeReference();
+ }
+ void validateScreenModeReset(final MonitorMode mmOrig) {
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ Assert.assertEquals(false,display.isNativeValid());
+ Assert.assertEquals(false,screen.isNativeValid());
+ screen.addReference();
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+
+ final MonitorDevice monitor = screen.getMonitorDevices().get(0);
+ Assert.assertEquals(mmOrig, monitor.getCurrentMode());
+
+ screen.removeReference();
+ Assert.assertEquals(false,display.isNativeValid());
+ Assert.assertEquals(false,screen.isNativeValid());
+ }
+
+ public static void main(final String args[]) throws IOException {
+ manualTest = true;
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-mwidth")) {
+ i++;
+ mm_width = MiscUtils.atoi(args[i], mm_width);
+ } else if(args[i].equals("-mheight")) {
+ i++;
+ mm_height = MiscUtils.atoi(args[i], mm_height);
+ }
+ }
+ System.err.println("Desired mode w/ resolution "+mm_width+"x"+mm_height);
+ final String tstname = TestScreenMode00cNEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java
new file mode 100644
index 000000000..6ddea555c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java
@@ -0,0 +1,267 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.mm;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.MonitorModeUtil;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import java.util.List;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+
+/**
+ * <p>
+ * Tests MonitorMode reset, by destroying the last Screen (reference),
+ * i.e. the original MonitorMode should get reinstated!
+ * </p>
+ * <p>
+ * Documents remedy B) for NV RANDR/GL bug
+ * </p>
+ *
+ * @see TestScreenMode01dNEWT#cleanupGL()
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestScreenMode01aNEWT extends UITestCase {
+ static GLProfile glp;
+ static int width, height;
+
+ static long waitTimeShort = 2000;
+ static long duration = 4000;
+
+ static int mm_width = 800;
+ static int mm_height = 600;
+
+ @BeforeClass
+ public static void initClass() {
+ setResetXRandRIfX11AfterClass();
+ width = 100;
+ height = 100;
+ glp = GLProfile.getDefault();
+ }
+
+ @AfterClass
+ public static void releaseClass() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+ }
+
+ static Window createWindow(final Screen screen, final GLCapabilities caps, final String name, final int x, final int y, final int width, final int height) {
+ Assert.assertNotNull(caps);
+
+ final GLWindow window = GLWindow.create(screen, caps);
+ // Window window = NewtFactory.createWindow(screen, caps);
+ window.setTitle(name);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.addGLEventListener(new GearsES2());
+ Assert.assertNotNull(window);
+ window.setVisible(true);
+ return window;
+ }
+
+ static void destroyWindow(final Window window) throws InterruptedException {
+ if(null!=window) {
+ window.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false));
+ }
+ }
+
+ @Test
+ public void testScreenModeChange01() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ final Window window0 = createWindow(screen, caps, "win0", 0, 0, width, height);
+ Assert.assertNotNull(window0);
+
+ final MonitorDevice monitor = screen.getMonitorDevices().get(0);
+
+ Rectangle window0WindowBounds = window0.getBounds();
+ DimensionImmutable window0SurfaceSize = new Dimension(window0.getSurfaceWidth(), window0.getSurfaceHeight());
+ System.err.println("Test.0: Window bounds : "+window0WindowBounds+" [wu] within "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.0: Window size : "+window0SurfaceSize+" [pixels]");
+ System.err.println("Test.0: Screen viewport : "+screen.getViewport()+" [pixels], "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.0: Monitor viewport : "+monitor.getViewport()+" [pixels], "+monitor.getViewportInWindowUnits()+" [wu]");
+
+ final List<MonitorMode> allMonitorModes = screen.getMonitorModes();
+ Assert.assertTrue(allMonitorModes.size()>0);
+ if(allMonitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no MonitorMode change support (all), sorry");
+ destroyWindow(window0);
+ return;
+ }
+
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ Assert.assertTrue(monitorModes.size()>0);
+ if(monitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no MonitorMode change support (monitor), sorry");
+ destroyWindow(window0);
+ return;
+ }
+ Assert.assertTrue(allMonitorModes.containsAll(monitorModes));
+
+ final MonitorMode mmSet0 = monitor.queryCurrentMode();
+ Assert.assertNotNull(mmSet0);
+ final MonitorMode mmOrig = monitor.getOriginalMode();
+ Assert.assertNotNull(mmOrig);
+ System.err.println("[0] orig : "+mmOrig);
+ System.err.println("[0] current: "+mmSet0);
+ Assert.assertEquals(mmSet0, mmOrig);
+
+
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(mm_width+1, mm_height+1));
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate());
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ // set mode
+ {
+ final MonitorMode mm = monitorModes.get(0);
+ System.err.println("[1] set current: "+mm);
+ final boolean smOk = monitor.setCurrentMode(mm);
+ final MonitorMode mmCachedCurrent = monitor.getCurrentMode();
+ final MonitorMode mmQueriedCurrent = monitor.queryCurrentMode();
+ final boolean mmCurrentEquals = mmQueriedCurrent.equals(mmCachedCurrent);
+ System.err.println("[1] changeOK : "+smOk);
+ System.err.println("[1] has current cached : "+mmCachedCurrent);
+ System.err.println("[1] has current queried : "+mmQueriedCurrent+", equal "+mmCurrentEquals);
+ window0WindowBounds = window0.getBounds();
+ window0SurfaceSize = new Dimension(window0.getSurfaceWidth(), window0.getSurfaceHeight());
+ System.err.println("Test.1: Window bounds : "+window0WindowBounds+" [wu] within "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.1: Window size : "+window0SurfaceSize+" [pixels]");
+ System.err.println("Test.1: Screen viewport : "+screen.getViewport()+" [pixels], "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.1: Monitor viewport : "+monitor.getViewport()+" [pixels], "+monitor.getViewportInWindowUnits()+" [wu]");
+
+ Assert.assertTrue(monitor.isModeChangedByUs());
+ Assert.assertEquals(mm, mmCachedCurrent);
+ Assert.assertNotSame(mmOrig, mmCachedCurrent);
+ Assert.assertEquals(mmCachedCurrent, monitor.queryCurrentMode());
+ Assert.assertTrue(smOk);
+ }
+
+ Thread.sleep(duration);
+
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+ Assert.assertEquals(true,window0.isNativeValid());
+ Assert.assertEquals(true,window0.isVisible());
+
+ // Auto reset by destruction!
+ destroyWindow(window0);
+
+ Assert.assertEquals(false,window0.isVisible());
+ Assert.assertEquals(false,window0.isNativeValid());
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+ Assert.assertEquals(false,screen.isNativeValid());
+ Assert.assertEquals(false,display.isNativeValid());
+
+ Thread.sleep(waitTimeShort);
+
+ validateScreenModeReset(mmOrig, 0);
+ }
+
+ void validateScreenModeReset(final MonitorMode mmOrig, final int mmIdx) {
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ Assert.assertEquals(false,display.isNativeValid());
+ Assert.assertEquals(false,screen.isNativeValid());
+ screen.addReference();
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+
+ final MonitorDevice monitor = screen.getMonitorDevices().get(0);
+ Assert.assertEquals(mmOrig, monitor.getCurrentMode());
+
+ screen.removeReference();
+ Assert.assertEquals(false,display.isNativeValid());
+ Assert.assertEquals(false,screen.isNativeValid());
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-mwidth")) {
+ i++;
+ mm_width = MiscUtils.atoi(args[i], mm_width);
+ } else if(args[i].equals("-mheight")) {
+ i++;
+ mm_height = MiscUtils.atoi(args[i], mm_height);
+ }
+ }
+ System.err.println("Desired mode w/ resolution "+mm_width+"x"+mm_height);
+ final String tstname = TestScreenMode01aNEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java
new file mode 100644
index 000000000..bba663a10
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java
@@ -0,0 +1,285 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.mm;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.MonitorModeUtil;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+import java.util.List;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+/**
+ * Mode change on separate monitors ..
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestScreenMode01bNEWT extends UITestCase {
+ static GLProfile glp;
+ static int width, height;
+
+ static long waitTimeShort = 2000;
+ static long duration = 6000;
+
+ @BeforeClass
+ public static void initClass() {
+ setResetXRandRIfX11AfterClass();
+ width = 200;
+ height = 200;
+ glp = GLProfile.getDefault();
+ }
+
+ @AfterClass
+ public static void releaseClass() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+ }
+
+ static GLWindow createWindow(final Screen screen, final GLCapabilities caps, final String name, final int screenXPos, final int screenYPos, final int width, final int height) throws InterruptedException {
+ Assert.assertNotNull(caps);
+
+ final GLWindow window = GLWindow.create(screen, caps);
+ // Window window = NewtFactory.createWindow(screen, caps);
+ final int[] winPos = window.convertToWindowUnits(new int[] { screenXPos, screenYPos });
+ window.setTitle(name);
+ window.setPosition(winPos[0], winPos[1]);
+ window.setSize(width, height);
+ window.addGLEventListener(new GearsES2());
+ Assert.assertNotNull(window);
+ final long t0 = System.currentTimeMillis();
+ window.setVisible(true);
+ System.err.println("Time for visible/pos: "+(System.currentTimeMillis()-t0)+" ms");
+ return window;
+ }
+
+ static void destroyWindow(final Window window) throws InterruptedException {
+ if(null!=window) {
+ window.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false));
+ }
+ }
+
+ @Test
+ public void testScreenModeChangeSingleQ1() throws InterruptedException {
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ screen.addReference(); // trigger creation
+ try {
+ final RectangleImmutable monitorVp = screen.getMonitorDevices().get(0).getViewport();
+ testScreenModeChangeImpl(screen, monitorVp.getX(), monitorVp.getY());
+ } finally {
+ screen.removeReference();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+ }
+ }
+
+ @Test
+ public void testScreenModeChangeSingleQ2() throws InterruptedException {
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ screen.addReference(); // trigger creation
+ try {
+ if( 2 > screen.getMonitorDevices().size() ) {
+ System.err.println("Test Disabled (1): Monitor count < 2: "+screen);
+ return;
+ }
+ final RectangleImmutable monitorVp = screen.getMonitorDevices().get(1).getViewport();
+ testScreenModeChangeImpl(screen, monitorVp.getX(), monitorVp.getY());
+ } finally {
+ screen.removeReference();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+ }
+ }
+
+ void testScreenModeChangeImpl(final Screen screen, final int screenXPos, final int screenYPos) throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ final Display display = screen.getDisplay();
+ System.err.println("Test.0: Window screen: "+screen);
+
+ System.err.println("Test.0: Window bounds (pre): screenPos "+screenXPos+"/"+screenYPos+" [pixels], windowSize "+width+"x"+height+" [wu] within "+screen.getViewport()+" [pixels]");
+
+ final GLWindow window0 = createWindow(screen, caps, "win0", screenXPos, screenYPos, width, height);
+ Assert.assertNotNull(window0);
+ Rectangle window0WindowBounds = window0.getBounds();
+ DimensionImmutable window0SurfaceSize = new Dimension(window0.getSurfaceWidth(), window0.getSurfaceHeight());
+ System.err.println("Test.0: Window bounds : "+window0WindowBounds+" [wu] within "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.0: Window size : "+window0SurfaceSize+" [pixels]");
+
+ final Animator anim = new Animator(window0);
+ anim.start();
+
+ final List<MonitorMode> allMonitorModes = screen.getMonitorModes();
+ Assert.assertTrue(allMonitorModes.size()>0);
+ if(allMonitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no MonitorMode change support (all), sorry");
+ destroyWindow(window0);
+ return;
+ }
+
+ final MonitorDevice monitor = window0.getMainMonitor();
+ System.err.println("Test.0: Window monitor: "+monitor);
+
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ Assert.assertTrue(monitorModes.size()>0);
+ if(monitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no MonitorMode change support (monitor), sorry");
+ destroyWindow(window0);
+ return;
+ }
+ Assert.assertTrue(allMonitorModes.containsAll(monitorModes));
+
+ MonitorMode mmCurrent = monitor.getCurrentMode();
+ Assert.assertNotNull(mmCurrent);
+ final MonitorMode mmOrig = monitor.getOriginalMode();
+ Assert.assertNotNull(mmOrig);
+ System.err.println("[0] orig : "+mmOrig);
+ System.err.println("[0] current: "+mmCurrent);
+ Assert.assertEquals(mmCurrent, mmOrig);
+
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601));
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate());
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ // set mode
+ {
+ final MonitorMode mm = monitorModes.get(0);
+ System.err.println("[0] set current: "+mm);
+ final boolean smOk = monitor.setCurrentMode(mm);
+ mmCurrent = monitor.getCurrentMode();
+ System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk);
+ Assert.assertTrue(monitor.isModeChangedByUs());
+ Assert.assertEquals(mm, mmCurrent);
+ Assert.assertNotSame(mmOrig, mmCurrent);
+ Assert.assertEquals(mmCurrent, monitor.queryCurrentMode());
+ Assert.assertTrue(smOk);
+ }
+
+ window0WindowBounds = window0.getBounds();
+ window0SurfaceSize = new Dimension(window0.getSurfaceWidth(), window0.getSurfaceHeight());
+ System.err.println("Test.1: Screen : "+screen);
+ System.err.println("Test.1: Window bounds : "+window0WindowBounds+" [wu] within "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.1: Window size : "+window0SurfaceSize+" [pixels]");
+ System.err.println("Test.1: Screen viewport : "+screen.getViewport()+" [pixels]");
+ System.err.println("Test.1: Monitor viewport : "+monitor.getViewport()+" [pixels], "+monitor.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.1: Window main-mon : "+window0.getMainMonitor());
+
+ Thread.sleep(duration);
+
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+ Assert.assertEquals(true,window0.isNativeValid());
+ Assert.assertEquals(true,window0.isVisible());
+
+ // manual restore!
+ {
+ System.err.println("[1] set orig: "+mmOrig);
+ final boolean smOk = monitor.setCurrentMode(mmOrig);
+ mmCurrent = monitor.getCurrentMode();
+ System.err.println("[1] has orig?: "+mmCurrent+", changeOK "+smOk);
+ Assert.assertFalse(monitor.isModeChangedByUs());
+ Assert.assertEquals(mmOrig, mmCurrent);
+ Assert.assertTrue(smOk);
+ }
+
+ window0WindowBounds = window0.getBounds();
+ window0SurfaceSize = new Dimension(window0.getSurfaceWidth(), window0.getSurfaceHeight());
+ System.err.println("Test.2: Screen : "+screen);
+ System.err.println("Test.2: Window bounds : "+window0WindowBounds+" [wu] within "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.2: Window size : "+window0SurfaceSize+" [pixels]");
+ System.err.println("Test.2: Screen viewport : "+screen.getViewport()+" [pixels]");
+ System.err.println("Test.2: Monitor viewport : "+monitor.getViewport()+" [pixels], "+monitor.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.2: Window main-mon : "+window0.getMainMonitor());
+
+ Thread.sleep(duration);
+ anim.stop();
+ destroyWindow(window0);
+
+ Assert.assertEquals(false,window0.isVisible());
+ Assert.assertEquals(false,window0.isNativeValid());
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ final String tstname = TestScreenMode01bNEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java
new file mode 100644
index 000000000..377c35ade
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java
@@ -0,0 +1,275 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.mm;
+
+import java.io.IOException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+/**
+ * Fullscreen on separate monitors, incl. spanning across multiple monitors.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestScreenMode01cNEWT extends UITestCase {
+ static GLProfile glp;
+ static int width, height;
+
+ static long waitTimeShort = 2000;
+ static long duration = 4000;
+
+ @BeforeClass
+ public static void initClass() {
+ setResetXRandRIfX11AfterClass();
+ width = 200;
+ height = 200;
+ glp = GLProfile.getDefault();
+ }
+
+ @AfterClass
+ public static void releaseClass() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+ }
+
+ static GLWindow createWindow(final Screen screen, final GLCapabilities caps, final String name, final int screenXPos, final int screenYPos, final int width, final int height) throws InterruptedException {
+ Assert.assertNotNull(caps);
+
+ final GLWindow window = GLWindow.create(screen, caps);
+ // Window window = NewtFactory.createWindow(screen, caps);
+ final int[] winPos = window.convertToWindowUnits(new int[] { screenXPos, screenYPos });
+ window.setTitle(name);
+ window.setPosition(winPos[0], winPos[1]);
+ window.setSize(width, height);
+ window.addGLEventListener(new GearsES2());
+ Assert.assertNotNull(window);
+ final long t0 = System.currentTimeMillis();
+ window.setVisible(true);
+ System.err.println("Time for visible/pos: "+(System.currentTimeMillis()-t0)+" ms");
+ return window;
+ }
+
+ static void destroyWindow(final Window window) throws InterruptedException {
+ if(null!=window) {
+ window.destroy();
+ AWTRobotUtil.waitForRealized(window, false); // don't override a previous assertion failure
+ }
+ }
+
+ @Test
+ public void testScreenFullscreenSingleQ1() throws InterruptedException {
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ screen.addReference(); // trigger creation
+ try {
+ final RectangleImmutable monitorVp = screen.getMonitorDevices().get(0).getViewport();
+ testScreenFullscreenImpl(screen, monitorVp.getX(), monitorVp.getY(), false, null);
+ } finally {
+ screen.removeReference();
+ AWTRobotUtil.waitForRealized(screen, false); // don't override a previous assertion failure
+ }
+ }
+
+ @Test
+ public void testScreenFullscreenSingleQ2() throws InterruptedException {
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ screen.addReference(); // trigger creation
+ try {
+ if( 2 > screen.getMonitorDevices().size() ) {
+ System.err.println("Test Disabled (1): Monitor count < 2: "+screen);
+ return;
+ }
+ final RectangleImmutable monitorVp = screen.getMonitorDevices().get(1).getViewport();
+ testScreenFullscreenImpl(screen, monitorVp.getX(), monitorVp.getY(), false, null);
+ } finally {
+ screen.removeReference();
+ AWTRobotUtil.waitForRealized(screen, false); // don't override a previous assertion failure
+ }
+ }
+
+ @Test
+ public void testScreenFullscreenSpanQ1Q2() throws InterruptedException {
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ screen.addReference(); // trigger creation
+ try {
+ if( 2 > screen.getMonitorDevices().size() ) {
+ System.err.println("Test Disabled (2): Spanning monitor count < 2: "+screen);
+ return;
+ }
+ final ArrayList<MonitorDevice> monitors = new ArrayList<MonitorDevice>();
+ monitors.add(screen.getMonitorDevices().get(0)); // Q1
+ monitors.add(screen.getMonitorDevices().get(1)); // Q2
+ final RectangleImmutable monitorVp = screen.getMonitorDevices().get(0).getViewport();
+ testScreenFullscreenImpl(screen, monitorVp.getX()+50, monitorVp.getY()+50, true, monitors);
+ } finally {
+ screen.removeReference();
+ AWTRobotUtil.waitForRealized(screen, false); // don't override a previous assertion failure
+ }
+ }
+
+ @Test
+ public void testScreenFullscreenSpanALL() throws InterruptedException {
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ screen.addReference(); // trigger creation
+ try {
+ if( 2 > screen.getMonitorDevices().size() ) {
+ System.err.println("Test Disabled (3): Monitor count < 2: "+screen);
+ return;
+ }
+ final RectangleImmutable monitorVp = screen.getMonitorDevices().get(1).getViewport();
+ testScreenFullscreenImpl(screen, monitorVp.getX()-50, monitorVp.getY()+50, true, null);
+ } finally {
+ screen.removeReference();
+ AWTRobotUtil.waitForRealized(screen, false); // don't override a previous assertion failure
+ }
+ }
+
+ void testScreenFullscreenImpl(final Screen screen, final int screenXPos, final int screenYPos,
+ final boolean spanAcrossMonitors, final List<MonitorDevice> monitors) throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ final Display display = screen.getDisplay();
+
+ System.err.println("Test.0: Window screen: "+screen);
+
+ System.err.println("Test.0: Window bounds (pre): screenPos "+screenXPos+"/"+screenYPos+" [pixels], windowSize "+width+"x"+height+" [wu] within "+screen.getViewport()+" [pixels]");
+
+ final GLWindow window0 = createWindow(screen, caps, "win0", screenXPos, screenYPos, width, height);
+ Assert.assertNotNull(window0);
+ Rectangle window0WindowBounds = window0.getBounds();
+ DimensionImmutable window0SurfaceSize = new Dimension(window0.getSurfaceWidth(), window0.getSurfaceHeight());
+ System.err.println("Test.0: Window bounds : "+window0WindowBounds+" [wu] within "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.0: Window size : "+window0SurfaceSize+" [pixels]");
+ System.err.println("Test.0: Screen viewport : "+screen.getViewport()+" [pixels]");
+
+ final Animator anim = new Animator(window0);
+ anim.start();
+
+ final List<MonitorMode> allMonitorModes = screen.getMonitorModes();
+ Assert.assertTrue(allMonitorModes.size()>0);
+
+ MonitorDevice monitor = window0.getMainMonitor();
+ System.err.println("Test.0: Window monitor: "+monitor);
+ if( !spanAcrossMonitors ) {
+ window0.setFullscreen(true);
+ } else {
+ window0.setFullscreen(monitors);
+ }
+
+ monitor = window0.getMainMonitor();
+ window0WindowBounds = window0.getBounds();
+ window0SurfaceSize = new Dimension(window0.getSurfaceWidth(), window0.getSurfaceHeight());
+ System.err.println("Test.1: Window bounds : "+window0WindowBounds+" [wu] within "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.1: Window size : "+window0SurfaceSize+" [pixels]");
+ System.err.println("Test.1: Screen viewport : "+screen.getViewport()+" [pixels]");
+ System.err.println("Test.1: Monitor viewport : "+monitor.getViewport()+" [pixels], "+monitor.getViewportInWindowUnits()+" [wu]");
+ if( !spanAcrossMonitors ) {
+ Assert.assertEquals(monitor.getViewportInWindowUnits(), window0WindowBounds);
+ } else {
+ List<MonitorDevice> monitorsUsed = monitors;
+ if( null == monitorsUsed ) {
+ monitorsUsed = window0.getScreen().getMonitorDevices();
+ }
+ final Rectangle monitorsUsedViewport = new Rectangle();
+ MonitorDevice.unionOfViewports(null, monitorsUsedViewport, monitorsUsed);
+ Assert.assertEquals(monitorsUsedViewport, window0WindowBounds);
+ }
+
+ Thread.sleep(duration);
+
+ window0.setFullscreen(false);
+
+ window0WindowBounds = window0.getBounds();
+ window0SurfaceSize = new Dimension(window0.getSurfaceWidth(), window0.getSurfaceHeight());;
+ monitor = window0.getMainMonitor();
+ System.err.println("Test.2: Window bounds : "+window0WindowBounds+" [wu] within "+screen.getViewportInWindowUnits()+" [wu]");
+ System.err.println("Test.2: Window size : "+window0SurfaceSize+" [pixels]");
+ System.err.println("Test.2: Screen viewport : "+screen.getViewport()+" [pixels]");
+ System.err.println("Test.2: Monitor viewport : "+monitor.getViewport()+" [pixels], "+monitor.getViewportInWindowUnits()+" [wu]");
+
+ Thread.sleep(duration);
+ anim.stop();
+ destroyWindow(window0);
+ Assert.assertEquals(false,window0.isVisible());
+ Assert.assertEquals(false,window0.isNativeValid());
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ }
+ }
+ final String tstname = TestScreenMode01cNEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01dNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01dNEWT.java
new file mode 100644
index 000000000..4d109a99f
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01dNEWT.java
@@ -0,0 +1,425 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.mm;
+
+import java.io.IOException;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.Animator;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.MonitorModeUtil;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import java.util.List;
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+/**
+ * Demonstrates fullscreen without MonitorMode change
+ * and fullscreen before and after MonitorMode change.
+ * <p>
+ * Also tests MonitorMode reset, by destroying the last Screen (reference),
+ * i.e. the original MonitorMode should get reinstated!
+ * </p>
+ * <p>
+ * Also documents NV RANDR/GL bug, see {@link TestScreenMode01dNEWT#cleanupGL()}.</p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestScreenMode01dNEWT extends UITestCase {
+ static GLProfile glp;
+ static int width, height;
+
+ static int waitTimeShort = 2000; // 2 sec
+ static int waitTimeLong = 8000; // 8 sec
+
+ @BeforeClass
+ public static void initClass() {
+ setResetXRandRIfX11AfterClass();
+ width = 640;
+ height = 480;
+ glp = GLProfile.getDefault();
+ }
+
+ @AfterClass
+ public static void releaseClass() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+ }
+
+ /**
+ * Following configurations results in a SIGSEGV:
+ * <pre>
+ * Ubuntu 11.04 (natty), NV GTX 460, driver [280.10* - 285.03]
+ * </pre>
+ *
+ * Situation:
+ * <pre>
+ * 1 - Create Screen, GLWindow (w/ context)
+ * 2 - ScreenMode change
+ * 3 - Destroy GLWindow (w/ context), Screen
+ * 4 - Create Screen, GLWindow (w/ context) (*)
+ * </pre>
+ *
+ * Step 4 causes the exception within 1st 'glXMakeContextCurrent(..)' call
+ * on the the created GL context.
+ *
+ * Remedy:
+ * <pre>
+ * A) Releasing all resources before step 4 .. works.
+ * B) Holding the native Display/Screen in NEWT also works (ie screen.addReference()).
+ * </pre>
+ *
+ * Hence there must be some correlations with the screen randr mode
+ * and some of the glcontext/gldrawables.
+ *
+ * <pre>
+ * Remedy A) is demonstrated here
+ * Remedy B) is shown in {@link TestScreenMode01bNEWT}
+ * </pre>
+ */
+ private void cleanupGL() throws InterruptedException {
+ System.err.println("*** cleanupGL.shutdown");
+ GLProfile.shutdown();
+ System.err.println("*** cleanupGL.initSingleton");
+ GLProfile.initSingleton();
+ System.err.println("*** cleanupGL.DONE");
+ }
+
+ static GLWindow createWindow(final Screen screen, final GLCapabilities caps, final int width, final int height, final boolean onscreen, final boolean undecorated) {
+ Assert.assertNotNull(caps);
+ caps.setOnscreen(onscreen);
+
+ final GLWindow window = GLWindow.create(screen, caps);
+ window.setSize(width, height);
+ window.addGLEventListener(new GearsES2());
+ Assert.assertNotNull(window);
+ window.setVisible(true);
+ return window;
+ }
+
+ static void destroyWindow(final Window window) throws InterruptedException {
+ if(null!=window) {
+ window.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false));
+ }
+ }
+
+ @Test
+ public void test01FullscreenChange01() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+
+ final GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
+ final Animator animator = new Animator(window);
+ animator.start();
+
+ final MonitorDevice monitor = window.getMainMonitor();
+
+ Assert.assertEquals(false, window.isFullscreen());
+ Assert.assertEquals(width, window.getWidth());
+ Assert.assertEquals(height, window.getHeight());
+
+ window.setFullscreen(true);
+ Assert.assertEquals(true, window.isFullscreen());
+ Assert.assertEquals(monitor.getViewport().getWidth(), window.getSurfaceWidth());
+ Assert.assertEquals(monitor.getViewport().getHeight(), window.getSurfaceHeight());
+
+ Thread.sleep(waitTimeShort);
+
+ window.setFullscreen(false);
+ Assert.assertEquals(false, window.isFullscreen());
+ Assert.assertEquals(width, window.getWidth());
+ Assert.assertEquals(height, window.getHeight());
+
+ Thread.sleep(waitTimeShort);
+
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ Assert.assertEquals(false, animator.isStarted());
+
+ destroyWindow(window);
+
+ Assert.assertEquals(false,window.isVisible());
+ Assert.assertEquals(false,window.isRealized());
+ Assert.assertEquals(false,window.isNativeValid());
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+ Assert.assertEquals(false,screen.isNativeValid());
+ Assert.assertEquals(false,display.isNativeValid());
+
+ cleanupGL();
+ }
+
+ @Test
+ public void test02ScreenModeChange01() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ final GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
+ Assert.assertNotNull(window);
+
+ final RectangleImmutable winRect = window.getBounds();
+ final MonitorDevice monitor = screen.getMainMonitor( winRect );
+
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ Assert.assertTrue(monitorModes.size()>0);
+ if(monitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no MonitorMode change support, sorry");
+ destroyWindow(window);
+ return;
+ }
+
+ final Animator animator = new Animator(window);
+ animator.start();
+
+ MonitorMode mmCurrent = monitor.queryCurrentMode();
+ Assert.assertNotNull(mmCurrent);
+ final MonitorMode mmOrig = monitor.getOriginalMode();
+ Assert.assertNotNull(mmOrig);
+ System.err.println("[0] orig : "+mmOrig);
+ System.err.println("[0] current: "+mmCurrent);
+ Assert.assertEquals(mmCurrent, mmOrig);
+
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601));
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate());
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ // set mode
+ {
+ final MonitorMode sm = monitorModes.get(0);
+ System.err.println("[0] set current: "+sm);
+ final boolean smOk = monitor.setCurrentMode(sm);
+ mmCurrent = monitor.getCurrentMode();
+ System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk);
+ Assert.assertTrue(monitor.isModeChangedByUs());
+ Assert.assertEquals(sm, mmCurrent);
+ Assert.assertNotSame(mmOrig, mmCurrent);
+ Assert.assertEquals(mmCurrent, monitor.queryCurrentMode());
+ Assert.assertTrue(smOk);
+ }
+
+ Thread.sleep(waitTimeLong);
+
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+ Assert.assertEquals(true,window.isNativeValid());
+ Assert.assertEquals(true,window.isVisible());
+
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ Assert.assertEquals(false, animator.isStarted());
+
+ destroyWindow(window);
+
+ Assert.assertEquals(false,window.isVisible());
+ Assert.assertEquals(false,window.isRealized());
+ Assert.assertEquals(false,window.isNativeValid());
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+ Assert.assertEquals(false,screen.isNativeValid());
+ Assert.assertEquals(false,display.isNativeValid());
+
+ validateScreenModeReset(mmOrig, winRect);
+ cleanupGL();
+ }
+
+ @Test
+ public void test03ScreenModeChangeWithFS01Post() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+ testScreenModeChangeWithFS01Impl(false) ;
+ }
+
+ @Test
+ public void test04ScreenModeChangeWithFS01Pre() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+ testScreenModeChangeWithFS01Impl(true) ;
+ }
+
+ protected void testScreenModeChangeWithFS01Impl(final boolean preFS) throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ final Display display = NewtFactory.createDisplay(null); // local display
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
+ final Animator animator = new Animator(window);
+ animator.start();
+
+ final RectangleImmutable winRect = window.getBounds();
+ final MonitorDevice monitor = screen.getMainMonitor(winRect);
+ MonitorMode mmCurrent = monitor.queryCurrentMode();
+ Assert.assertNotNull(mmCurrent);
+ final MonitorMode mmOrig = monitor.getOriginalMode();
+ Assert.assertNotNull(mmOrig);
+ System.err.println("[0] orig : "+mmOrig);
+ System.err.println("[0] current: "+mmCurrent);
+ Assert.assertEquals(mmCurrent, mmOrig);
+
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ if(monitorModes.size()==1) {
+ // no support ..
+ destroyWindow(window);
+ return;
+ }
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0);
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601));
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate());
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+
+ final MonitorMode monitorMode = monitorModes.get(0);
+ Assert.assertNotNull(monitorMode);
+
+ if(preFS) {
+ System.err.println("[1] set FS pre 0: "+window.isFullscreen());
+ window.setFullscreen(true);
+ System.err.println("[1] set FS pre 1: "+window.isFullscreen());
+ Assert.assertEquals(true, window.isFullscreen());
+ System.err.println("[1] set FS pre X: "+window.isFullscreen());
+ }
+ Thread.sleep(waitTimeShort);
+
+ // set mode
+ {
+ System.err.println("[2] set current: "+monitorMode);
+ final boolean smOk = monitor.setCurrentMode(monitorMode);
+ mmCurrent = monitor.getCurrentMode();
+ System.err.println("[2] has current: "+mmCurrent+", changeOK "+smOk);
+ Assert.assertTrue(monitor.isModeChangedByUs());
+ Assert.assertEquals(monitorMode, mmCurrent);
+ Assert.assertNotSame(mmOrig, mmCurrent);
+ Assert.assertEquals(mmCurrent, monitor.queryCurrentMode());
+ Assert.assertTrue(smOk);
+ }
+
+ if(!preFS) {
+ System.err.println("[3] set FS post 0: "+window.isFullscreen());
+ window.setFullscreen(true);
+ Assert.assertEquals(true, window.isFullscreen());
+ System.err.println("[3] set FS post X: "+window.isFullscreen());
+ }
+
+ Thread.sleep(waitTimeLong);
+
+ if(!preFS) {
+ System.err.println("[4] set !FS post 0: "+window.isFullscreen());
+ window.setFullscreen(false);
+ Assert.assertEquals(false, window.isFullscreen());
+ System.err.println("[4] set !FS post X: "+window.isFullscreen());
+ Thread.sleep(waitTimeShort);
+ }
+
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+ Assert.assertEquals(true,window.isNativeValid());
+ Assert.assertEquals(true,window.isVisible());
+
+ animator.stop();
+ Assert.assertEquals(false, animator.isAnimating());
+ Assert.assertEquals(false, animator.isStarted());
+
+ destroyWindow(window);
+
+ Assert.assertEquals(false,window.isVisible());
+ Assert.assertEquals(false,window.isRealized());
+ Assert.assertEquals(false,window.isNativeValid());
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+ Assert.assertEquals(false,screen.isNativeValid());
+ Assert.assertEquals(false,display.isNativeValid());
+
+ validateScreenModeReset(mmOrig, winRect);
+ cleanupGL();
+ }
+
+ /**
+ *
+ * @param mmOrig
+ * @param rect in window units
+ */
+ void validateScreenModeReset(final MonitorMode mmOrig, final RectangleImmutable rect) {
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ Assert.assertEquals(false,display.isNativeValid());
+ Assert.assertEquals(false,screen.isNativeValid());
+ screen.addReference();
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+
+ final MonitorDevice monitor = screen.getMainMonitor(rect);
+ Assert.assertEquals(mmOrig, monitor.getCurrentMode());
+
+ screen.removeReference();
+ Assert.assertEquals(false,display.isNativeValid());
+ Assert.assertEquals(false,screen.isNativeValid());
+ }
+
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestScreenMode01dNEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java
new file mode 100644
index 000000000..c2d769a2e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java
@@ -0,0 +1,253 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.mm;
+
+import java.io.IOException;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.Animator;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.MonitorModeUtil;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import java.util.List;
+import javax.media.nativewindow.util.Dimension;
+
+/**
+ * Tests MonitorMode change w/ changed rotation,
+ * w/ and w/o fullscreen, pre and post MonitorMode change.
+ * <p>
+ * MonitorMode change does not use highest resolution.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestScreenMode02aNEWT extends UITestCase {
+ static GLProfile glp;
+ static int width, height;
+
+ static int waitTimeShort = 2000; // 2 sec
+ static int waitTimeLong = 8000; // 8 sec
+
+ @BeforeClass
+ public static void initClass() {
+ setResetXRandRIfX11AfterClass();
+ width = 640;
+ height = 480;
+ glp = GLProfile.getDefault();
+ }
+
+ static GLWindow createWindow(final Screen screen, final GLCapabilities caps, final int width, final int height, final boolean onscreen, final boolean undecorated) {
+ Assert.assertNotNull(caps);
+ caps.setOnscreen(onscreen);
+
+ final GLWindow window = GLWindow.create(screen, caps);
+ window.setSize(width, height);
+ window.addGLEventListener(new GearsES2(1));
+ Assert.assertNotNull(window);
+ return window;
+ }
+
+ static void destroyWindow(final Window window) throws InterruptedException {
+ if(null!=window) {
+ window.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false));
+ }
+ }
+
+ @Test
+ public void testScreenRotationChange01_PreWin() throws InterruptedException {
+ testScreenRotationChangeImpl(true, true, false);
+ }
+
+ @Test
+ public void testScreenRotationChange02_PreFull() throws InterruptedException {
+ testScreenRotationChangeImpl(true, true, true);
+ }
+
+ @Test
+ public void testScreenRotationChange11_PostWin() throws InterruptedException {
+ testScreenRotationChangeImpl(true, false, false);
+ }
+
+ @Test
+ public void testScreenRotationChange12_PostFull() throws InterruptedException {
+ testScreenRotationChangeImpl(true, false, true);
+ }
+
+ void testScreenRotationChangeImpl(final boolean changeMode, final boolean preVis, final boolean fullscreen) throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ final GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
+ Assert.assertNotNull(window);
+ if( preVis ) {
+ window.setVisible(true);
+ if( fullscreen ) {
+ window.setFullscreen(true);
+ }
+ } else {
+ screen.createNative();
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+ }
+
+ final Animator animator = new Animator(window);
+ animator.start();
+
+ final MonitorDevice monitor = window.getMainMonitor();
+ final MonitorMode mmOrig = monitor.getOriginalMode();
+ Assert.assertNotNull(mmOrig);
+ if(changeMode) {
+ Thread.sleep(waitTimeShort);
+
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ if(monitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no ScreenMode change support, sorry");
+ animator.stop();
+ destroyWindow(window);
+ return;
+ }
+ Assert.assertTrue(monitorModes.size()>0);
+
+ MonitorMode mmCurrent = monitor.getCurrentMode();
+ Assert.assertNotNull(mmCurrent);
+ System.err.println("[0] orig : "+mmOrig);
+ System.err.println("[0] current: "+mmCurrent);
+ Assert.assertEquals(mmCurrent, mmOrig);
+
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 90);
+ if(null==monitorModes || Platform.getOSType() == Platform.OSType.MACOS ) {
+ // no rotation support ..
+ System.err.println("Your platform has no rotation support, sorry");
+ animator.stop();
+ destroyWindow(window);
+ return;
+ }
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601));
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate());
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ // set mode
+ {
+ final MonitorMode mm = monitorModes.get(0);
+ System.err.println("[0] set current: "+mm);
+ final boolean smOk = monitor.setCurrentMode(mm);
+ mmCurrent = monitor.getCurrentMode();
+ System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk);
+ Assert.assertTrue(monitor.isModeChangedByUs());
+ Assert.assertEquals(mm, mmCurrent);
+ Assert.assertNotSame(mmOrig, mmCurrent);
+ Assert.assertEquals(mmCurrent, monitor.queryCurrentMode());
+ Assert.assertTrue(smOk);
+ }
+ }
+
+ if( !preVis ) {
+ if( fullscreen ) {
+ window.setFullscreen(true);
+ }
+ window.setVisible(true);
+ }
+
+ Thread.sleep(waitTimeLong);
+
+ if( !preVis && fullscreen ) {
+ window.setFullscreen(false);
+ }
+
+ if(changeMode) {
+ Thread.sleep(waitTimeShort);
+
+ // manual restore!
+ {
+ System.err.println("[1] set orig: "+mmOrig);
+ final boolean smOk = monitor.setCurrentMode(mmOrig);
+ final MonitorMode mmCurrent = monitor.getCurrentMode();
+ System.err.println("[1] has orig?: "+mmCurrent+", changeOK "+smOk);
+ Assert.assertFalse(monitor.isModeChangedByUs());
+ Assert.assertEquals(mmOrig, mmCurrent);
+ Assert.assertTrue(smOk);
+ }
+ Thread.sleep(waitTimeShort);
+ }
+
+ if( preVis && fullscreen ) {
+ window.setFullscreen(false);
+ }
+
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+ Assert.assertEquals(true,window.isNativeValid());
+ Assert.assertEquals(true,window.isVisible());
+
+ animator.stop();
+ destroyWindow(window);
+
+ Assert.assertEquals(false,window.isVisible());
+ Assert.assertEquals(false,window.isNativeValid());
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+ Assert.assertEquals(false,screen.isNativeValid());
+ Assert.assertEquals(false,display.isNativeValid());
+ }
+
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestScreenMode02aNEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java
new file mode 100644
index 000000000..47fd53e05
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java
@@ -0,0 +1,261 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.mm;
+
+import java.io.IOException;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.MonitorModeUtil;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+import java.util.List;
+import javax.media.nativewindow.util.Dimension;
+
+/**
+ * Tests MonitorMode change w/ changed rotation and fullscreen.
+ * <p>
+ * MonitorMode change uses highest resolution.
+ * </p>
+ * <p>
+ * Bug 734 could not be reproduced, however on tests systems
+ * here - AMD fglrx and Intel Mesa, the rotated height
+ * is cut off .. probably due to bug of driver code and rotation.
+ * </p>
+ * <p>
+ * Documents remedy B) for NV RANDR/GL bug
+ * </p>
+ *
+ * @see TestScreenMode01NEWT#cleanupGL()
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestScreenMode02bNEWT extends UITestCase {
+ static GLProfile glp;
+
+ static int waitTimeShort = 2000; // 2 sec
+ static int waitTimeLong = 8000; // 8 sec
+
+ @BeforeClass
+ public static void initClass() {
+ setResetXRandRIfX11AfterClass();
+ glp = GLProfile.getDefault();
+ }
+
+ @AfterClass
+ public static void releaseClass() throws InterruptedException {
+ Thread.sleep(waitTimeShort);
+ }
+
+ static GLWindow createWindow(final Screen screen, final GLCapabilities caps, final String name, final int x, final int y, final int width, final int height) {
+ Assert.assertNotNull(caps);
+
+ final GLWindow window = GLWindow.create(screen, caps);
+ // Window window = NewtFactory.createWindow(screen, caps);
+ window.setTitle(name);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.addGLEventListener(new GearsES2(1));
+ Assert.assertNotNull(window);
+ return window;
+ }
+
+ static void destroyWindow(final Window window) throws InterruptedException {
+ if(null!=window) {
+ window.destroy();
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false));
+ }
+ }
+
+ @Test
+ public void testScreenModeChange01_PreFull() throws InterruptedException {
+ testScreenModeChangeImpl(true);
+ }
+
+ @Test
+ public void testScreenModeChange02_PostFull() throws InterruptedException {
+ testScreenModeChangeImpl(false);
+ }
+
+ void testScreenModeChangeImpl(final boolean preVis) throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ final Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ screen.createNative(); // instantiate for resolution query and keep it alive !
+ final int swidth = screen.getWidth();
+ final int sheight = screen.getHeight();
+
+ final GLWindow window = createWindow(screen, caps, "win0", 0, 0, 640, 480);
+ if( preVis ) {
+ window.setVisible(true);
+ window.setFullscreen(true);
+ }
+ window.setUndecorated(true);
+ Assert.assertNotNull(window);
+
+ final List<MonitorMode> allMonitorModes = screen.getMonitorModes();
+ Assert.assertTrue(allMonitorModes.size()>0);
+ if(allMonitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no MonitorMode change support (all), sorry");
+ destroyWindow(window);
+ return;
+ }
+
+ final MonitorDevice monitor = window.getMainMonitor();
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ Assert.assertTrue(monitorModes.size()>0);
+ if(monitorModes.size()==1) {
+ // no support ..
+ System.err.println("Your platform has no MonitorMode change support (monitor), sorry");
+ destroyWindow(window);
+ return;
+ }
+ Assert.assertTrue(allMonitorModes.containsAll(monitorModes));
+
+ final Animator animator = new Animator(window);
+ animator.start();
+
+ MonitorMode mmCurrent = monitor.queryCurrentMode();
+ Assert.assertNotNull(mmCurrent);
+ final MonitorMode mmOrig = monitor.getOriginalMode();
+ Assert.assertNotNull(mmOrig);
+ System.err.println("[0] orig : "+mmOrig);
+ System.err.println("[0] current: "+mmCurrent);
+ Assert.assertEquals(mmCurrent, mmOrig);
+
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 90);
+ if(null==monitorModes || Platform.getOSType() == Platform.OSType.MACOS ) {
+ // no rotation support ..
+ System.err.println("Your platform has no rotation support, sorry");
+ animator.stop();
+ destroyWindow(window);
+ return;
+ }
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(swidth, sheight));
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate());
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+ Assert.assertNotNull(monitorModes);
+ Assert.assertTrue(monitorModes.size()>0);
+
+ // set mode
+ {
+ final MonitorMode mm = monitorModes.get(0); // highest resolution ..
+ System.err.println("[0] set current: "+mm);
+ final boolean smOk = monitor.setCurrentMode(mm);
+ mmCurrent = monitor.getCurrentMode();
+ System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk);
+ if( !smOk ) {
+ System.err.println("ERROR: Full MonitorMode w/ rotation failure - Expected on some platforms (NV driver) - Tolerated for now.");
+ animator.stop();
+ destroyWindow(window);
+ return;
+ }
+ Assert.assertTrue(monitor.isModeChangedByUs());
+ Assert.assertEquals(mm, mmCurrent);
+ Assert.assertNotSame(mmOrig, mmCurrent);
+ Assert.assertEquals(mmCurrent, monitor.queryCurrentMode());
+ Assert.assertTrue(smOk);
+ }
+
+ if( !preVis ) {
+ window.setFullscreen(true);
+ window.setVisible(true);
+ }
+
+ Thread.sleep(waitTimeLong);
+
+ if( !preVis ) {
+ window.setFullscreen(false);
+ }
+
+ // manual restore!
+ {
+ System.err.println("[1] set orig: "+mmOrig);
+ final boolean smOk = monitor.setCurrentMode(mmOrig);
+ mmCurrent = monitor.getCurrentMode();
+ System.err.println("[1] has orig?: "+mmCurrent+", changeOK "+smOk);
+ Assert.assertFalse(monitor.isModeChangedByUs());
+ Assert.assertEquals(mmOrig, mmCurrent);
+ Assert.assertTrue(smOk);
+ }
+ Thread.sleep(waitTimeShort);
+
+ if( preVis ) {
+ window.setFullscreen(false);
+ }
+
+ Assert.assertEquals(true,display.isNativeValid());
+ Assert.assertEquals(true,screen.isNativeValid());
+ Assert.assertEquals(true,window.isNativeValid());
+ Assert.assertEquals(true,window.isVisible());
+
+ animator.stop();
+ destroyWindow(window);
+
+ Assert.assertEquals(false,window.isVisible());
+ Assert.assertEquals(false,window.isNativeValid());
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false));
+ Assert.assertEquals(false,screen.isNativeValid());
+ Assert.assertEquals(false,display.isNativeValid());
+ }
+
+ public static void main(final String args[]) throws IOException {
+ final String tstname = TestScreenMode02bNEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/GLRunnableDummy.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/GLRunnableDummy.java
index 1ca74774b..18f2b9b4a 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/GLRunnableDummy.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/GLRunnableDummy.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import javax.media.opengl.*;
@@ -36,8 +36,8 @@ public class GLRunnableDummy implements GLRunnable {
float b=0.0f;
float d=0.1f;
- public boolean run(GLAutoDrawable drawable) {
- GL2ES1 gl = drawable.getGL().getGL2ES1();
+ public boolean run(final GLAutoDrawable drawable) {
+ final GL2ES1 gl = drawable.getGL().getGL2ES1();
gl.glClearColor(r, g, b, 1f);
r+=d;
if(r>1f) {
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/KeyAction.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/KeyAction.java
index 3313ec65c..64867b054 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/KeyAction.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/KeyAction.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
@@ -34,11 +34,14 @@ import com.jogamp.newt.event.*;
class KeyAction extends KeyAdapter {
NEWTEventFiFo eventFifo;
- public KeyAction(NEWTEventFiFo eventFifo) {
- this.eventFifo = eventFifo;
+ public KeyAction(final NEWTEventFiFo eventFifo) {
+ this.eventFifo = eventFifo;
}
- public void keyTyped(KeyEvent e) {
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
eventFifo.put(e);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java
index f7881615d..75037b60c 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -28,72 +28,207 @@
package com.jogamp.opengl.test.junit.newt.parenting;
import java.awt.Frame;
+import java.net.URLConnection;
import javax.media.nativewindow.util.InsetsImmutable;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Display.PointerIcon;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.PNGPixelRect;
public class NewtAWTReparentingKeyAdapter extends KeyAdapter {
- Frame frame;
- NewtCanvasAWT newtCanvasAWT;
- GLWindow glWindow;
-
- public NewtAWTReparentingKeyAdapter(Frame frame, NewtCanvasAWT newtCanvasAWT, GLWindow glWindow) {
+ final Frame frame;
+ final NewtCanvasAWT newtCanvasAWT;
+ final GLWindow glWindow;
+ final QuitAdapter quitAdapter;
+ PointerIcon[] pointerIcons = null;
+ int pointerIconIdx = 0;
+
+ public NewtAWTReparentingKeyAdapter(final Frame frame, final NewtCanvasAWT newtCanvasAWT, final GLWindow glWindow, final QuitAdapter quitAdapter) {
this.frame = frame;
this.newtCanvasAWT = newtCanvasAWT;
this.glWindow = glWindow;
+ this.quitAdapter = quitAdapter;
}
-
- public void keyTyped(KeyEvent e) {
- if(e.getKeyChar()=='d') {
+
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ if( e.getKeySymbol() == KeyEvent.VK_L ) {
+ final javax.media.nativewindow.util.Point p0 = newtCanvasAWT.getNativeWindow().getLocationOnScreen(null);
+ final javax.media.nativewindow.util.Point p1 = glWindow.getLocationOnScreen(null);
+ System.err.println("NewtCanvasAWT position: "+p0+", "+p1);
+ } else if( e.getKeySymbol() == KeyEvent.VK_D ) {
glWindow.setUndecorated(!glWindow.isUndecorated());
- } else if(e.getKeyChar()=='f') {
- glWindow.setFullscreen(!glWindow.isFullscreen());
- } else if(e.getKeyChar()=='l') {
- javax.media.nativewindow.util.Point p0 = newtCanvasAWT.getNativeWindow().getLocationOnScreen(null);
- javax.media.nativewindow.util.Point p1 = glWindow.getLocationOnScreen(null);
- System.err.println("NewtCanvasAWT position: "+p0+", "+p1);
- } else if(e.getKeyChar()=='p') {
+ } else if( e.getKeySymbol() == KeyEvent.VK_S ) {
+ if(glWindow.getParent()==null) {
+ System.err.println("XXX glWin to 100/100");
+ glWindow.setPosition(100, 100);
+ } else {
+ System.err.println("XXX glWin to 0/0");
+ glWindow.setPosition(0, 0);
+ }
+ } else if( e.getKeySymbol() == KeyEvent.VK_F ) {
+ if( null != quitAdapter ) {
+ quitAdapter.enable(false);
+ }
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
+ glWindow.setExclusiveContextThread(t);
+ if( null != quitAdapter ) {
+ quitAdapter.clear();
+ quitAdapter.enable(true);
+ }
+ } }.start();
+ } else if( e.getKeySymbol() == KeyEvent.VK_P ) {
new Thread() {
public void run() {
if(glWindow.getAnimator().isPaused()) {
glWindow.getAnimator().resume();
} else {
- glWindow.getAnimator().pause();
- }
+ glWindow.getAnimator().pause();
+ }
}
}.run();
- } else if(e.getKeyChar()=='r') {
- if(glWindow.getParent()==null) {
- System.err.println("XXX glWin to home");
- glWindow.reparentWindow(newtCanvasAWT.getNativeWindow());
- } else {
- final InsetsImmutable nInsets = glWindow.getInsets();
- java.awt.Insets aInsets = frame.getInsets();
- System.err.println("XXX glWin to TOP - insets " + nInsets + ", " + aInsets);
- glWindow.reparentWindow(null);
- int dx, dy;
- if(nInsets.getTotalHeight()==0) {
- dx = aInsets.left;
- dy = aInsets.top;
- } else {
- dx = nInsets.getLeftWidth();
- dy = nInsets.getTopHeight();
+ } else if( e.getKeySymbol() == KeyEvent.VK_A ) {
+ new Thread() {
+ public void run() {
+ glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
}
- glWindow.setPosition(frame.getX()+frame.getWidth()+dx, frame.getY()+dy);
+ }.run();
+ } else if( e.getKeySymbol() == KeyEvent.VK_R ) {
+ if( null != quitAdapter ) {
+ quitAdapter.enable(false);
}
- glWindow.requestFocus();
- } else if(e.getKeyChar()=='s') {
- if(glWindow.getParent()==null) {
- System.err.println("XXX glWin to 100/100");
- glWindow.setPosition(100, 100);
- } else {
- System.err.println("XXX glWin to 0/0");
- glWindow.setPosition(0, 0);
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ if(glWindow.getParent()==null) {
+ System.err.println("XXX glWin to HOME");
+ glWindow.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, 0 /* hints */);
+ } else {
+ if( null != frame ) {
+ final InsetsImmutable nInsets = glWindow.getInsets();
+ final java.awt.Insets aInsets = frame.getInsets();
+ int dx, dy;
+ if( nInsets.getTotalHeight()==0 ) {
+ dx = aInsets.left;
+ dy = aInsets.top;
+ } else {
+ dx = nInsets.getLeftWidth();
+ dy = nInsets.getTopHeight();
+ }
+ final int topLevelX = frame.getX()+frame.getWidth()+dx;
+ final int topLevelY = frame.getY()+dy;
+ System.err.println("XXX glWin to TOP.1 "+topLevelX+"/"+topLevelY+" - insets " + nInsets + ", " + aInsets);
+ glWindow.reparentWindow(null, topLevelX, topLevelY, 0 /* hint */);
+ } else {
+ System.err.println("XXX glWin to TOP.0");
+ glWindow.reparentWindow(null, -1, -1, 0 /* hints */);
+ }
+ }
+ glWindow.requestFocus();
+ glWindow.setExclusiveContextThread(t);
+ if( null != quitAdapter ) {
+ quitAdapter.clear();
+ quitAdapter.enable(true);
+ }
+ } }.start();
+ } else if(e.getKeySymbol() == KeyEvent.VK_C ) {
+ if( null == pointerIcons ) {
+ {
+ pointerIcons = new PointerIcon[3];
+ final Display disp = glWindow.getScreen().getDisplay();
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 8, 8);
+ System.err.println("Create PointerIcon #01: "+_pointerIcon);
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ }
+ pointerIcons[0] = _pointerIcon;
+ }
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/pointer-grey-alpha-16x24.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 0, 0);
+ System.err.println("Create PointerIcon #02: "+_pointerIcon);
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ }
+ pointerIcons[1] = _pointerIcon;
+ }
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } );
+ try {
+ final URLConnection urlConn = res.resolve(0);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ System.err.println("Create PointerIcon #03: "+image);
+ _pointerIcon = disp.createPointerIcon(image, 32, 0);
+ System.err.println("Create PointerIcon #03: "+_pointerIcon);
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ }
+ pointerIcons[2] = _pointerIcon;
+ }
+ }
}
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set pointer-icon pre]");
+ final PointerIcon currentPI = glWindow.getPointerIcon();
+ final PointerIcon newPI;
+ if( pointerIconIdx >= pointerIcons.length ) {
+ newPI=null;
+ pointerIconIdx=0;
+ } else {
+ newPI=pointerIcons[pointerIconIdx++];
+ }
+ glWindow.setPointerIcon( newPI );
+ System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon());
+ glWindow.setExclusiveContextThread(t);
+ } }.start();
+ } else if( e.getKeySymbol() == KeyEvent.VK_I ) {
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible());
+ glWindow.setPointerVisible(!glWindow.isPointerVisible());
+ System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible());
+ glWindow.setExclusiveContextThread(t);
+ } }.start();
+ } else if(e.getKeySymbol() == KeyEvent.VK_J ) {
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
+ glWindow.confinePointer(!glWindow.isPointerConfined());
+ System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
+ glWindow.setExclusiveContextThread(t);
+ } }.start();
+ } else if(e.getKeySymbol() == KeyEvent.VK_W ) {
+ new Thread() {
+ public void run() {
+ System.err.println("[set mouse pos pre]");
+ glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2);
+ System.err.println("[set mouse pos post]");
+ } }.start();
}
}
-} \ No newline at end of file
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java
index 6b7b155c5..d6658d809 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,18 +20,20 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.opengl.*;
@@ -45,6 +47,7 @@ import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting01NEWT extends UITestCase {
static int width, height;
static long durationPerTest = 600;
@@ -59,12 +62,12 @@ public class TestParenting01NEWT extends UITestCase {
}
@Test
- public void testWindowParenting01CreateVisibleDestroy() throws InterruptedException {
+ public void test01CreateVisibleDestroy() throws InterruptedException {
Assert.assertEquals(0,Display.getActiveDisplayNumber());
Display display = null;
Screen screen = null;
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
Assert.assertNotNull(glWindow1);
Assert.assertEquals(false, glWindow1.isVisible());
Assert.assertEquals(false, glWindow1.isNativeValid());
@@ -74,18 +77,18 @@ public class TestParenting01NEWT extends UITestCase {
Assert.assertEquals(0,display.getReferenceCount());
Assert.assertEquals(false,display.isNativeValid());
Assert.assertNotNull(display.getEDTUtil());
- Assert.assertEquals(true,display.getEDTUtil().isRunning());
+ Assert.assertEquals(false,display.getEDTUtil().isRunning());
Assert.assertEquals(0,screen.getReferenceCount());
Assert.assertEquals(false,screen.isNativeValid());
Assert.assertEquals(0,Display.getActiveDisplayNumber());
- glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
+ glWindow1.setTitle("test01CreateVisibleDestroy");
glWindow1.setSize(640, 480);
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
- GLWindow glWindow2 = GLWindow.create(glWindow1, glCaps);
+ final GLWindow glWindow2 = GLWindow.create(glWindow1, glCaps);
Assert.assertNotNull(glWindow2);
Assert.assertEquals(false, glWindow2.isVisible());
Assert.assertEquals(false, glWindow2.isNativeValid());
@@ -93,7 +96,7 @@ public class TestParenting01NEWT extends UITestCase {
Assert.assertSame(screen,glWindow2.getScreen());
Assert.assertSame(display,glWindow2.getScreen().getDisplay());
glWindow2.setSize(320, 240);
- GLEventListener demo2 = new GearsES2();
+ final GLEventListener demo2 = new GearsES2();
setDemoFields(demo2, glWindow2, false);
glWindow2.addGLEventListener(demo2);
@@ -147,14 +150,14 @@ public class TestParenting01NEWT extends UITestCase {
glWindow1.resetFPSCounter();
glWindow2.resetFPSCounter();
- Animator animator1 = new Animator(glWindow1);
- animator1.setUpdateFPSFrames(1, null);
+ final Animator animator1 = new Animator(glWindow1);
+ animator1.setUpdateFPSFrames(1, null);
animator1.start();
Assert.assertEquals(true, animator1.isAnimating());
Assert.assertEquals(false, animator1.isPaused());
Assert.assertNotNull(animator1.getThread());
- Animator animator2 = new Animator(glWindow2);
- animator2.setUpdateFPSFrames(1, null);
+ final Animator animator2 = new Animator(glWindow2);
+ animator2.setUpdateFPSFrames(1, null);
animator2.start();
Assert.assertEquals(true, animator2.isAnimating());
Assert.assertEquals(false, animator2.isPaused());
@@ -283,27 +286,29 @@ public class TestParenting01NEWT extends UITestCase {
}
@Test
- public void testWindowParenting02ReparentTop2WinReparentRecreate() throws InterruptedException {
- testWindowParenting02ReparentTop2WinImpl(true);
+ public void test02aReparentTop2WinReparentRecreate() throws InterruptedException {
+ test02ReparentTop2WinImpl(true);
}
@Test
- public void testWindowParenting02ReparentTop2WinReparentNative() throws InterruptedException {
- testWindowParenting02ReparentTop2WinImpl(false);
+ public void test02bReparentTop2WinReparentNative() throws InterruptedException {
+ test02ReparentTop2WinImpl(false);
}
/**
* @param reparentRecreate true, if the followup reparent should utilize destroy/create, instead of native reparenting
*/
- protected void testWindowParenting02ReparentTop2WinImpl(boolean reparentRecreate) throws InterruptedException {
+ protected void test02ReparentTop2WinImpl(final boolean reparentRecreate) throws InterruptedException {
+ final int reparentHints = reparentRecreate ? Window.REPARENT_HINT_FORCE_RECREATION : 0;
+
Assert.assertEquals(0,Display.getActiveDisplayNumber());
Display display1 = null;
Screen screen1 = null;
- GLWindow glWindow1 = GLWindow.create(glCaps);
- glWindow1.setTitle("testWindowParenting02ReparentTop2Win");
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
+ glWindow1.setTitle("test02ReparentTop2Win");
glWindow1.setSize(640, 480);
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
screen1 = glWindow1.getScreen();
@@ -317,9 +322,9 @@ public class TestParenting01NEWT extends UITestCase {
Assert.assertEquals(false,screen1.isNativeValid());
Assert.assertEquals(0,Display.getActiveDisplayNumber());
- GLWindow glWindow2 = GLWindow.create(glCaps);
+ final GLWindow glWindow2 = GLWindow.create(glCaps);
glWindow2.setSize(320, 240);
- GLEventListener demo2 = new GearsES2();
+ final GLEventListener demo2 = new GearsES2();
setDemoFields(demo2, glWindow2, false);
glWindow2.addGLEventListener(demo2);
Assert.assertSame(screen1, glWindow2.getScreen());
@@ -360,28 +365,47 @@ public class TestParenting01NEWT extends UITestCase {
System.err.println("Frames for setVisible(true) B1: "+glWindow2.getTotalFPSFrames());
Assert.assertTrue(0 < glWindow1.getTotalFPSFrames());
- Animator animator1 = new Animator(glWindow1);
+ final Animator animator1 = new Animator(glWindow1);
animator1.setUpdateFPSFrames(1, null);
animator1.start();
- Animator animator2 = new Animator(glWindow2);
+ final Animator animator2 = new Animator(glWindow2);
animator2.setUpdateFPSFrames(1, null);
animator2.start();
int state = 0;
Window.ReparentOperation reparentAction;
- while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) {
+ while(animator1.isAnimating() && animator1.getTotalFPSDuration()<7*durationPerTest) {
Thread.sleep(durationPerTest);
switch(state) {
case 0:
+ // top-level glWindow2 hide
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(true, glWindow2.isVisible());
+ glWindow2.setVisible(false);
+ Assert.assertEquals(false, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 1:
+ // top-level glWindow2 show
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow2.isVisible());
+ glWindow2.setVisible(true);
+ Assert.assertEquals(true, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 2:
// glWindow2 -- child --> glWindow1: compatible
Assert.assertEquals(true, glWindow2.isVisible());
System.err.println("Frames(1) "+glWindow2.getTotalFPSFrames());
- reparentAction = glWindow2.reparentWindow(glWindow1, reparentRecreate);
+ reparentAction = glWindow2.reparentWindow(glWindow1, -1, -1, reparentHints);
System.err.println("Frames(2) "+glWindow2.getTotalFPSFrames());
Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction);
Assert.assertEquals(true, glWindow2.isVisible());
Assert.assertEquals(true, glWindow2.isNativeValid());
Assert.assertSame(glWindow1,glWindow2.getParent());
+ Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz
System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B2: "+glWindow2.getTotalFPSFrames());
Assert.assertTrue(0 < glWindow2.getTotalFPSFrames());
@@ -397,15 +421,34 @@ public class TestParenting01NEWT extends UITestCase {
break;
- case 1:
+ case 3:
+ // child glWindow2 hide
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(true, glWindow2.isVisible());
+ glWindow2.setVisible(false);
+ Assert.assertEquals(false, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 4:
+ // child glWindow2 show
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow2.isVisible());
+ glWindow2.setVisible(true);
+ Assert.assertEquals(true, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 5:
// glWindow2 --> top
Assert.assertEquals(true, glWindow2.isVisible());
- reparentAction = glWindow2.reparentWindow(null, reparentRecreate);
+ reparentAction = glWindow2.reparentWindow(null, -1, -1, reparentHints);
Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction);
Assert.assertEquals(true, glWindow2.isVisible());
Assert.assertEquals(true, glWindow2.isNativeValid());
Assert.assertNull(glWindow2.getParent());
+ Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz
System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B3: "+glWindow2.getTotalFPSFrames());
Assert.assertTrue(0 < glWindow2.getTotalFPSFrames());
@@ -479,28 +522,30 @@ public class TestParenting01NEWT extends UITestCase {
}
@Test
- public void testWindowParenting03ReparentWin2TopReparentRecreate() throws InterruptedException {
- testWindowParenting03ReparentWin2TopImpl(true);
+ public void test03aReparentWin2TopReparentRecreate() throws InterruptedException {
+ test03ReparentWin2TopImpl(true);
}
@Test
- public void testWindowParenting03ReparentWin2TopReparentNative() throws InterruptedException {
- testWindowParenting03ReparentWin2TopImpl(false);
+ public void test03bReparentWin2TopReparentNative() throws InterruptedException {
+ test03ReparentWin2TopImpl(false);
}
- protected void testWindowParenting03ReparentWin2TopImpl(boolean reparentRecreate) throws InterruptedException {
+ protected void test03ReparentWin2TopImpl(final boolean reparentRecreate) throws InterruptedException {
+ final int reparentHints = reparentRecreate ? Window.REPARENT_HINT_FORCE_RECREATION : 0;
+
Assert.assertEquals(0,Display.getActiveDisplayNumber());
Display display1 = null;
Screen screen1 = null;
Display display2 = null;
Screen screen2 = null;
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
screen1 = glWindow1.getScreen();
display1 = screen1.getDisplay();
- glWindow1.setTitle("testWindowParenting03ReparentWin2Top");
+ glWindow1.setTitle("test03ReparentWin2Top");
glWindow1.setSize(640, 480);
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
@@ -512,11 +557,11 @@ public class TestParenting01NEWT extends UITestCase {
Assert.assertEquals(false,screen1.isNativeValid());
Assert.assertEquals(0,Display.getActiveDisplayNumber());
- GLWindow glWindow2 = GLWindow.create(glWindow1, glCaps);
+ final GLWindow glWindow2 = GLWindow.create(glWindow1, glCaps);
screen2 = glWindow2.getScreen();
display2 = screen2.getDisplay();
glWindow2.setSize(320, 240);
- GLEventListener demo2 = new GearsES2();
+ final GLEventListener demo2 = new GearsES2();
setDemoFields(demo2, glWindow2, false);
glWindow2.addGLEventListener(demo2);
@@ -548,39 +593,82 @@ public class TestParenting01NEWT extends UITestCase {
Assert.assertSame(screen1,glWindow2.getScreen());
Assert.assertEquals(1,Display.getActiveDisplayNumber());
- Animator animator1 = new Animator(glWindow1);
+ final Animator animator1 = new Animator(glWindow1);
animator1.setUpdateFPSFrames(1, null);
animator1.start();
- Animator animator2 = new Animator(glWindow2);
+ final Animator animator2 = new Animator(glWindow2);
animator2.setUpdateFPSFrames(1, null);
animator2.start();
int state = 0;
Window.ReparentOperation reparentAction;
- while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) {
+ while(animator1.isAnimating() && animator1.getTotalFPSDuration()<7*durationPerTest) {
Thread.sleep(durationPerTest);
switch(state) {
case 0:
+ // child glWindow2 hide
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(true, glWindow2.isVisible());
+ glWindow2.setVisible(false);
+ Assert.assertEquals(false, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 1:
+ // child glWindow2 show
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow2.isVisible());
+ glWindow2.setVisible(true);
Assert.assertEquals(true, glWindow2.isVisible());
- reparentAction = glWindow2.reparentWindow(null, reparentRecreate);
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 2:
+ // glWindow2 --> top
+ Assert.assertEquals(true, glWindow2.isVisible());
+ reparentAction = glWindow2.reparentWindow(null, -1, -1, reparentHints);
Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction);
Assert.assertEquals(true, glWindow2.isVisible());
Assert.assertEquals(true, glWindow2.isNativeValid());
+ Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz
System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B2: "+glWindow2.getTotalFPSFrames());
Assert.assertTrue(0 < glWindow2.getTotalFPSFrames());
+
Assert.assertNull(glWindow2.getParent());
Assert.assertSame(screen1,glWindow2.getScreen());
Assert.assertSame(display1,glWindow2.getScreen().getDisplay());
Assert.assertEquals(1,Display.getActiveDisplayNumber());
break;
- case 1:
+
+ case 3:
+ // top-level glWindow2 hide
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(true, glWindow2.isVisible());
+ glWindow2.setVisible(false);
+ Assert.assertEquals(false, glWindow2.isVisible());
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 4:
+ // top-level glWindow2 show
+ Assert.assertEquals(true, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow2.isVisible());
+ glWindow2.setVisible(true);
Assert.assertEquals(true, glWindow2.isVisible());
- reparentAction = glWindow2.reparentWindow(glWindow1, reparentRecreate);
+ Assert.assertEquals(true, glWindow1.isVisible());
+ break;
+
+ case 5:
+ // glWindow2 -- child --> glWindow1: compatible
+ Assert.assertEquals(true, glWindow2.isVisible());
+ reparentAction = glWindow2.reparentWindow(glWindow1, -1, -1, reparentHints);
Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction);
Assert.assertEquals(true, glWindow2.isVisible());
Assert.assertEquals(true, glWindow2.isNativeValid());
+ Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz
System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B3 "+glWindow2.getTotalFPSFrames());
Assert.assertTrue(0 < glWindow2.getTotalFPSFrames());
+
Assert.assertSame(glWindow1,glWindow2.getParent());
Assert.assertSame(screen1,glWindow2.getScreen());
Assert.assertSame(display1,glWindow2.getScreen().getDisplay());
@@ -646,9 +734,9 @@ public class TestParenting01NEWT extends UITestCase {
Assert.assertEquals(0,Display.getActiveDisplayNumber());
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
- Assert.assertNotNull(glWindow);
+ Assert.assertNotNull(glWindow);
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -658,23 +746,37 @@ public class TestParenting01NEWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
+ boolean asMain = false;
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
+ } else if(args[i].equals("-asMain")) {
+ asMain = true;
}
}
System.err.println("durationPerTest: "+durationPerTest);
- String tstname = TestParenting01NEWT.class.getName();
- org.junit.runner.JUnitCore.main(tstname);
+ if( asMain ) {
+ try {
+ TestParenting01NEWT.initClass();
+ final TestParenting01NEWT m = new TestParenting01NEWT();
+ m.test02aReparentTop2WinReparentRecreate();
+ m.test01CreateVisibleDestroy();
+ } catch (final Throwable t ) {
+ t.printStackTrace();
+ }
+ } else {
+ final String tstname = TestParenting01NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java
index de29db417..6f39985f4 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.newt.parenting;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import java.awt.Button;
import java.awt.BorderLayout;
@@ -50,6 +52,7 @@ import java.lang.reflect.InvocationTargetException;
import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting01aAWT extends UITestCase {
static int width, height;
static long durationPerTest = 800;
@@ -65,14 +68,14 @@ public class TestParenting01aAWT extends UITestCase {
}
@Test
- public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException {
+ public void test01WindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException {
final GLWindow glWindow1 = GLWindow.create(glCaps);
Assert.assertNotNull(glWindow1);
Assert.assertEquals(false, glWindow1.isVisible());
Assert.assertEquals(false, glWindow1.isNativeValid());
Assert.assertNull(glWindow1.getParent());
glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
@@ -98,22 +101,22 @@ public class TestParenting01aAWT extends UITestCase {
container1.add(newtCanvasAWT, BorderLayout.CENTER);
frame1.add(container1, BorderLayout.CENTER);
- frame1.setSize(width, height);
// visible test
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame1.setSize(width, height);
frame1.setVisible(true);
}
});
Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent());
final Animator animator1 = new Animator(glWindow1);
- animator1.setUpdateFPSFrames(1, null);
+ animator1.setUpdateFPSFrames(1, null);
animator1.start();
Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow1, true));
Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, true));
-
+
while(animator1.isAnimating() && animator1.getTotalFPSDuration()<durationPerTest) {
Thread.sleep(100);
}
@@ -123,40 +126,46 @@ public class TestParenting01aAWT extends UITestCase {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame1.setVisible(false);
- } } );
+ } } );
Assert.assertEquals(true, glWindow1.isNativeValid());
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame1.setVisible(true);
- } } );
+ } } );
Assert.assertEquals(true, glWindow1.isNativeValid());
+ final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen();
+
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame1.remove(newtCanvasAWT);
} } );
// Assert.assertNull(glWindow1.getParent());
- Assert.assertEquals(true, glWindow1.isNativeValid());
+ if( wasOnscreen ) {
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+ } // else OK to be destroyed - due to offscreen/onscreen transition
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame1.dispose();
} } );
- Assert.assertEquals(true, glWindow1.isNativeValid());
+ if( wasOnscreen ) {
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+ } // else OK to be destroyed - due to offscreen/onscreen transition
glWindow1.destroy();
Assert.assertEquals(false, glWindow1.isNativeValid());
}
@Test
- public void testWindowParenting02CreateVisibleDestroy2Defered() throws InterruptedException, InvocationTargetException {
+ public void test02WindowParenting02CreateVisibleDestroy2Defered() throws InterruptedException, InvocationTargetException {
final GLWindow glWindow1 = GLWindow.create(glCaps);
Assert.assertNotNull(glWindow1);
Assert.assertEquals(false, glWindow1.isVisible());
Assert.assertEquals(false, glWindow1.isNativeValid());
Assert.assertNull(glWindow1.getParent());
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
@@ -168,11 +177,11 @@ public class TestParenting01aAWT extends UITestCase {
final Frame frame = new Frame("AWT Parent Frame");
Assert.assertNotNull(frame);
- frame.setSize(width, height);
// visible test
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.setSize(width, height);
frame.setVisible(true);
}
});
@@ -185,7 +194,7 @@ public class TestParenting01aAWT extends UITestCase {
});
Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent());
- Animator animator1 = new Animator(glWindow1);
+ final Animator animator1 = new Animator(glWindow1);
animator1.setUpdateFPSFrames(1, null);
animator1.start();
while(animator1.isAnimating() && animator1.getTotalFPSDuration()<durationPerTest) {
@@ -202,9 +211,9 @@ public class TestParenting01aAWT extends UITestCase {
}
@Test
- public void testWindowParenting02CreateVisibleDestroy3Odd() throws InterruptedException, InvocationTargetException {
- GLWindow glWindow1 = GLWindow.create(glCaps);
- GLEventListener demo1 = new RedSquareES2();
+ public void test03WindowParenting02CreateVisibleDestroy3Odd() throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
@@ -212,11 +221,11 @@ public class TestParenting01aAWT extends UITestCase {
final Frame frame = new Frame("AWT Parent Frame");
Assert.assertNotNull(frame);
- frame.setSize(width, height);
// visible test
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.setSize(width, height);
frame.setVisible(true);
}
});
@@ -228,7 +237,7 @@ public class TestParenting01aAWT extends UITestCase {
}
});
- Animator animator1 = new Animator(glWindow1);
+ final Animator animator1 = new Animator(glWindow1);
animator1.setUpdateFPSFrames(1, null);
animator1.start();
Assert.assertEquals(true, animator1.isStarted());
@@ -247,19 +256,19 @@ public class TestParenting01aAWT extends UITestCase {
}
@Test
- public void testWindowParenting03ReparentNewtWin2Top() throws InterruptedException, InvocationTargetException {
- GLWindow glWindow1 = GLWindow.create(glCaps);
- GLEventListener demo1 = new RedSquareES2();
+ public void test04WindowParenting03ReparentNewtWin2Top() throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1);
final Frame frame = new Frame("AWT Parent Frame");
- frame.setSize(width, height);
- frame.setLocation(640, 480);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.setSize(width, height);
+ frame.setLocation(640, 480);
frame.setVisible(true);
}
});
@@ -273,8 +282,8 @@ public class TestParenting01aAWT extends UITestCase {
Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent());
- Animator animator1 = new Animator(glWindow1);
- animator1.setUpdateFPSFrames(1, null);
+ final Animator animator1 = new Animator(glWindow1);
+ animator1.setUpdateFPSFrames(1, null);
animator1.start();
int state = 0;
@@ -282,12 +291,12 @@ public class TestParenting01aAWT extends UITestCase {
Thread.sleep(durationPerTest);
switch(state) {
case 0:
- glWindow1.reparentWindow(null);
+ System.err.println("Reparent CHILD -> TOP: "+glWindow1.reparentWindow(null, -1, -1, 0 /* hints */));
Assert.assertEquals(true, glWindow1.isNativeValid());
Assert.assertNull(glWindow1.getParent());
break;
case 1:
- glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow());
+ System.err.println("Reparent TOP -> CHILD: "+glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, 0 /* hints */));
Assert.assertEquals(true, glWindow1.isNativeValid());
Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent());
break;
@@ -306,9 +315,9 @@ public class TestParenting01aAWT extends UITestCase {
}
@Test
- public void testWindowParenting04ReparentNewtWin2TopLayouted() throws InterruptedException, InvocationTargetException {
- GLWindow glWindow1 = GLWindow.create(glCaps);
- GLEventListener demo1 = new RedSquareES2();
+ public void test05WindowParenting04ReparentNewtWin2TopLayouted() throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
@@ -320,11 +329,11 @@ public class TestParenting01aAWT extends UITestCase {
frame.add(new Button("South"), BorderLayout.SOUTH);
frame.add(new Button("East"), BorderLayout.EAST);
frame.add(new Button("West"), BorderLayout.WEST);
- frame.setSize(width, height);
- frame.setLocation(640, 480);
-
+
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame.setSize(width, height);
+ frame.setLocation(640, 480);
frame.setVisible(true);
}
});
@@ -335,11 +344,11 @@ public class TestParenting01aAWT extends UITestCase {
frame.validate();
}
});
-
+
Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent());
- Animator animator1 = new Animator(glWindow1);
- animator1.setUpdateFPSFrames(1, null);
+ final Animator animator1 = new Animator(glWindow1);
+ animator1.setUpdateFPSFrames(1, null);
animator1.start();
int state = 0;
@@ -347,12 +356,12 @@ public class TestParenting01aAWT extends UITestCase {
Thread.sleep(durationPerTest);
switch(state) {
case 0:
- glWindow1.reparentWindow(null);
+ System.err.println("Reparent CHILD -> TOP: "+glWindow1.reparentWindow(null, -1, -1, 0 /* hints */));
Assert.assertEquals(true, glWindow1.isNativeValid());
Assert.assertNull(glWindow1.getParent());
break;
case 1:
- glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow());
+ System.err.println("Reparent TOP -> CHILD: "+glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, 0 /* hints */));
Assert.assertEquals(true, glWindow1.isNativeValid());
Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent());
break;
@@ -371,10 +380,10 @@ public class TestParenting01aAWT extends UITestCase {
}
@Test
- public void testWindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException {
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ public void test06WindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
glWindow1.setUndecorated(true);
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
@@ -386,10 +395,10 @@ public class TestParenting01aAWT extends UITestCase {
frame1.add(new Button("South"), BorderLayout.SOUTH);
frame1.add(new Button("East"), BorderLayout.EAST);
frame1.add(new Button("West"), BorderLayout.WEST);
- frame1.setSize(width, height);
- frame1.setLocation(0, 0);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame1.setSize(width, height);
+ frame1.setLocation(0, 0);
frame1.setVisible(true);
}
});
@@ -400,10 +409,10 @@ public class TestParenting01aAWT extends UITestCase {
frame2.add(new Button("South"), BorderLayout.SOUTH);
frame2.add(new Button("East"), BorderLayout.EAST);
frame2.add(new Button("West"), BorderLayout.WEST);
- frame2.setSize(width, height);
- frame2.setLocation(640, 480);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame2.setSize(width, height);
+ frame2.setLocation(640, 480);
frame2.setVisible(true);
}
});
@@ -417,8 +426,8 @@ public class TestParenting01aAWT extends UITestCase {
Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent());
- Animator animator1 = new Animator(glWindow1);
- animator1.setUpdateFPSFrames(1, null);
+ final Animator animator1 = new Animator(glWindow1);
+ animator1.setUpdateFPSFrames(1, null);
animator1.start();
int state = 0;
@@ -433,7 +442,7 @@ public class TestParenting01aAWT extends UITestCase {
frame1.validate();
frame2.validate();
}
- });
+ });
break;
case 1:
SwingUtilities.invokeAndWait(new Runnable() {
@@ -443,7 +452,7 @@ public class TestParenting01aAWT extends UITestCase {
frame2.validate();
frame1.validate();
}
- });
+ });
break;
}
state++;
@@ -460,9 +469,9 @@ public class TestParenting01aAWT extends UITestCase {
glWindow1.destroy();
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
- Assert.assertNotNull(glWindow);
+ Assert.assertNotNull(glWindow);
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -472,15 +481,15 @@ public class TestParenting01aAWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
@@ -488,18 +497,8 @@ public class TestParenting01aAWT extends UITestCase {
waitReparent = atoi(args[++i]);
}
}
- String tstname = TestParenting01aAWT.class.getName();
- org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
- tstname,
- "filtertrace=true",
- "haltOnError=false",
- "haltOnFailure=false",
- "showoutput=true",
- "outputtoformatters=true",
- "logfailedtests=true",
- "logtestlistenerevents=true",
- "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
- "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
+ final String tstname = TestParenting01aAWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java
index 11aef7c24..770b7ce4d 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import java.io.IOException;
@@ -45,8 +45,11 @@ import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Window;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.newt.swt.NewtCanvasSWT;
@@ -57,6 +60,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
/**
* Simple visibility test ..
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting01aSWT extends UITestCase {
static int width, height;
static long durationPerTest = 800;
@@ -65,7 +69,8 @@ public class TestParenting01aSWT extends UITestCase {
Display display = null;
Shell shell = null;
Composite composite1 = null;
-
+ com.jogamp.newt.Display swtNewtDisplay = null;
+
@BeforeClass
public static void initClass() {
width = 640;
@@ -76,7 +81,7 @@ public class TestParenting01aSWT extends UITestCase {
@Before
public void init() {
SWTAccessor.invoke(true, new Runnable() {
- public void run() {
+ public void run() {
display = new Display();
Assert.assertNotNull( display );
shell = new Shell( display );
@@ -86,8 +91,9 @@ public class TestParenting01aSWT extends UITestCase {
composite1.setLayout( new FillLayout() );
Assert.assertNotNull( composite1 );
}});
+ swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse
}
-
+
@After
public void release() {
Assert.assertNotNull( display );
@@ -101,25 +107,27 @@ public class TestParenting01aSWT extends UITestCase {
display.dispose();
}});
}
- catch( Throwable throwable ) {
+ catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
+ swtNewtDisplay = null;
display = null;
shell = null;
composite1 = null;
}
-
+
@Test
public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException {
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ final com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, 0);
+ final GLWindow glWindow1 = GLWindow.create(screen, glCaps);
Assert.assertNotNull(glWindow1);
Assert.assertEquals(false, glWindow1.isVisible());
Assert.assertEquals(false, glWindow1.isNativeValid());
Assert.assertNull(glWindow1.getParent());
glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
@@ -136,7 +144,7 @@ public class TestParenting01aSWT extends UITestCase {
shell.open();
}
});
-
+
// visible test
Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent());
@@ -166,10 +174,10 @@ public class TestParenting01aSWT extends UITestCase {
Assert.assertEquals(false, glWindow1.isNativeValid());
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -179,21 +187,21 @@ public class TestParenting01aSWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
- String tstname = TestParenting01aSWT.class.getName();
+ final String tstname = TestParenting01aSWT.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java
index d98a540ec..49e74ddc0 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import java.awt.Button;
import java.awt.BorderLayout;
@@ -51,6 +53,7 @@ import java.lang.reflect.InvocationTargetException;
import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting01bAWT extends UITestCase {
static int width, height;
static long durationPerTest = 800;
@@ -65,35 +68,35 @@ public class TestParenting01bAWT extends UITestCase {
}
@Test
- public void testWindowParenting05ReparentAWTWinHopFrame2FrameFPS25Animator() throws InterruptedException, InvocationTargetException {
- testWindowParenting05ReparentAWTWinHopFrame2FrameImpl(25);
+ public void test01AWTWinHopFrame2FrameFPS25Animator() throws InterruptedException, InvocationTargetException {
+ testAWTWinHopFrame2FrameImpl(25);
}
@Test
- public void testWindowParenting05ReparentAWTWinHopFrame2FrameStdAnimator() throws InterruptedException, InvocationTargetException {
- testWindowParenting05ReparentAWTWinHopFrame2FrameImpl(0);
+ public void test02AWTWinHopFrame2FrameStdAnimator() throws InterruptedException, InvocationTargetException {
+ testAWTWinHopFrame2FrameImpl(0);
}
- public void testWindowParenting05ReparentAWTWinHopFrame2FrameImpl(int fps) throws InterruptedException, InvocationTargetException {
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ public void testAWTWinHopFrame2FrameImpl(final int fps) throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
glWindow1.setUndecorated(true);
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1);
-
+
final Frame frame1 = new Frame("AWT Parent Frame");
frame1.setLayout(new BorderLayout());
frame1.add(new Button("North"), BorderLayout.NORTH);
frame1.add(new Button("South"), BorderLayout.SOUTH);
frame1.add(new Button("East"), BorderLayout.EAST);
frame1.add(new Button("West"), BorderLayout.WEST);
- frame1.setSize(width, height);
- frame1.setLocation(0, 0);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- frame1.setVisible(true);
+ frame1.setSize(width, height);
+ frame1.setLocation(0, 0);
+ frame1.setVisible(true);
}
});
@@ -103,11 +106,11 @@ public class TestParenting01bAWT extends UITestCase {
frame2.add(new Button("South"), BorderLayout.SOUTH);
frame2.add(new Button("East"), BorderLayout.EAST);
frame2.add(new Button("West"), BorderLayout.WEST);
- frame2.setSize(width, height);
- frame2.setLocation(640, 480);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- frame2.setVisible(true);
+ frame2.setSize(width, height);
+ frame2.setLocation(640, 480);
+ frame2.setVisible(true);
}
});
@@ -139,7 +142,7 @@ public class TestParenting01bAWT extends UITestCase {
frame1.validate();
frame2.validate();
}
- });
+ });
break;
case 1:
SwingUtilities.invokeAndWait(new Runnable() {
@@ -149,7 +152,7 @@ public class TestParenting01bAWT extends UITestCase {
frame2.validate();
frame1.validate();
}
- });
+ });
break;
}
}
@@ -170,10 +173,10 @@ public class TestParenting01bAWT extends UITestCase {
glWindow1.destroy();
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -183,15 +186,15 @@ public class TestParenting01bAWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
@@ -199,7 +202,7 @@ public class TestParenting01bAWT extends UITestCase {
waitReparent = atoi(args[++i]);
}
}
- String tstname = TestParenting01bAWT.class.getName();
+ final String tstname = TestParenting01bAWT.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java
index dfd0787e7..30be67ab3 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import java.awt.Button;
import java.awt.BorderLayout;
@@ -50,6 +52,7 @@ import java.lang.reflect.InvocationTargetException;
import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting01cAWT extends UITestCase {
static int width, height;
static long durationPerTest = 800;
@@ -63,16 +66,16 @@ public class TestParenting01cAWT extends UITestCase {
}
@Test
- public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException {
+ public void test01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException {
int i;
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
Assert.assertNotNull(glWindow1);
Assert.assertEquals(false, glWindow1.isVisible());
Assert.assertEquals(false, glWindow1.isNativeValid());
Assert.assertNull(glWindow1.getParent());
glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
@@ -89,7 +92,7 @@ public class TestParenting01cAWT extends UITestCase {
frame1.add(new Button("East"), BorderLayout.EAST);
frame1.add(new Button("West"), BorderLayout.WEST);
- Container container1 = new Container();
+ final Container container1 = new Container();
container1.setLayout(new BorderLayout());
container1.add(new Button("north"), BorderLayout.NORTH);
container1.add(new Button("south"), BorderLayout.SOUTH);
@@ -98,11 +101,11 @@ public class TestParenting01cAWT extends UITestCase {
container1.add(newtCanvasAWT, BorderLayout.CENTER);
frame1.add(container1, BorderLayout.CENTER);
- frame1.setSize(width, height);
// visible test
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame1.setSize(width, height);
frame1.setVisible(true);
}
});
@@ -126,29 +129,35 @@ public class TestParenting01cAWT extends UITestCase {
});
Assert.assertEquals(true, glWindow1.isNativeValid());
+ final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen();
+
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame1.remove(newtCanvasAWT);
}
});
// Assert.assertNull(glWindow1.getParent());
- Assert.assertEquals(true, glWindow1.isNativeValid());
+ if( wasOnscreen ) {
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+ } // else OK to be destroyed - due to offscreen/onscreen transition
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame1.dispose();
} } );
- Assert.assertEquals(true, glWindow1.isNativeValid());
+ if( wasOnscreen ) {
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+ } // else OK to be destroyed - due to offscreen/onscreen transition
glWindow1.destroy();
Assert.assertEquals(false, glWindow1.isNativeValid());
}
@Test
- public void testWindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException {
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ public void test02AWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
glWindow1.setUndecorated(true);
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
@@ -160,10 +169,10 @@ public class TestParenting01cAWT extends UITestCase {
frame1.add(new Button("South"), BorderLayout.SOUTH);
frame1.add(new Button("East"), BorderLayout.EAST);
frame1.add(new Button("West"), BorderLayout.WEST);
- frame1.setSize(width, height);
- frame1.setLocation(0, 0);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame1.setSize(width, height);
+ frame1.setLocation(0, 0);
frame1.setVisible(true);
}
});
@@ -174,10 +183,10 @@ public class TestParenting01cAWT extends UITestCase {
frame2.add(new Button("South"), BorderLayout.SOUTH);
frame2.add(new Button("East"), BorderLayout.EAST);
frame2.add(new Button("West"), BorderLayout.WEST);
- frame2.setSize(width, height);
- frame2.setLocation(640, 480);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame2.setSize(width, height);
+ frame2.setLocation(640, 480);
frame2.setVisible(true);
}
});
@@ -225,10 +234,10 @@ public class TestParenting01cAWT extends UITestCase {
glWindow1.destroy();
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -238,21 +247,21 @@ public class TestParenting01cAWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
- String tstname = TestParenting01cAWT.class.getName();
+ final String tstname = TestParenting01cAWT.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java
index 4b02be873..3726870e3 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import java.lang.reflect.*;
@@ -33,14 +33,17 @@ import java.lang.reflect.*;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import java.awt.Button;
import java.awt.BorderLayout;
import java.awt.Container;
+
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
-
+import javax.swing.WindowConstants;
import javax.media.opengl.*;
import com.jogamp.opengl.util.Animator;
@@ -53,6 +56,7 @@ import java.io.IOException;
import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting01cSwingAWT extends UITestCase {
static int width, height;
static long durationPerTest = 800;
@@ -66,38 +70,38 @@ public class TestParenting01cSwingAWT extends UITestCase {
glCaps = new GLCapabilities(null);
}
- static class GLDisturbanceAction implements Runnable {
+ static class GLDisturbanceAction implements Runnable {
public boolean isRunning = false;
private volatile boolean shallStop = false;
private final GLAutoDrawable glad;
private final GLRunnable glRunnable;
-
- public GLDisturbanceAction(GLAutoDrawable glad) {
+
+ public GLDisturbanceAction(final GLAutoDrawable glad) {
this.glad = glad;
this.glRunnable = new GLRunnableDummy();
}
-
+
public void waitUntilRunning() {
synchronized(this) {
while(!isRunning) {
try {
this.wait();
- } catch (InterruptedException e) { e.printStackTrace(); }
- }
+ } catch (final InterruptedException e) { e.printStackTrace(); }
+ }
}
}
-
+
public void stopAndWaitUntilDone() {
shallStop = true;
synchronized(this) {
while(isRunning) {
try {
this.wait();
- } catch (InterruptedException e) { e.printStackTrace(); }
- }
+ } catch (final InterruptedException e) { e.printStackTrace(); }
+ }
}
}
-
+
public void run() {
synchronized(this) {
isRunning = true;
@@ -108,7 +112,7 @@ public class TestParenting01cSwingAWT extends UITestCase {
try {
glad.invoke(true, glRunnable);
Thread.sleep(100);
- } catch (Throwable t) {}
+ } catch (final Throwable t) {}
}
synchronized(this) {
isRunning = false;
@@ -116,25 +120,25 @@ public class TestParenting01cSwingAWT extends UITestCase {
}
}
}
-
+
@Test
- public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException {
+ public void test01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException {
/**
* JFrame . JPanel . Container . NewtCanvasAWT . GLWindow
*/
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
Assert.assertNotNull(glWindow1);
Assert.assertEquals(false, glWindow1.isVisible());
Assert.assertEquals(false, glWindow1.isNativeValid());
Assert.assertNull(glWindow1.getParent());
glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
- Animator animator1 = new Animator(glWindow1);
+ final Animator animator1 = new Animator(glWindow1);
animator1.setUpdateFPSFrames(1, null);
animator1.start();
-
+
final GLDisturbanceAction disturbanceAction = new GLDisturbanceAction(glWindow1);
new Thread(disturbanceAction).start();
disturbanceAction.waitUntilRunning();
@@ -163,12 +167,13 @@ public class TestParenting01cSwingAWT extends UITestCase {
final JFrame jFrame1 = new JFrame("Swing Parent JFrame");
// jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
+ jFrame1.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
jFrame1.setContentPane(jPanel1);
- jFrame1.setSize(width, height);
System.err.println("Demos: 1 - Visible");
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ jFrame1.setSize(width, height);
+ jFrame1.validate();
jFrame1.setVisible(true);
}
});
@@ -199,6 +204,8 @@ public class TestParenting01cSwingAWT extends UITestCase {
} });
Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true));
+ final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen();
+
// Always recommended to remove our native parented Window
// from the AWT resources before destruction, since it could lead
// to a BadMatch X11 error w/o.
@@ -208,45 +215,49 @@ public class TestParenting01cSwingAWT extends UITestCase {
jPanel1.remove(container1);
jFrame1.validate();
} });
- Assert.assertEquals(true, glWindow1.isNativeValid());
+ if( wasOnscreen ) {
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+ } // else OK to be destroyed - due to offscreen/onscreen transition
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
System.err.println("Demos: 6 - X Frame");
jFrame1.dispose();
} });
- Assert.assertEquals(true, glWindow1.isNativeValid());
+ if( wasOnscreen ) {
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+ } // else OK to be destroyed - due to offscreen/onscreen transition
- System.err.println("Demos: 7 - X GLWindow");
+ System.err.println("Demos: 7 - X GLWindow");
glWindow1.destroy();
Assert.assertEquals(false, glWindow1.isNativeValid());
-
- System.err.println("Demos: 8 - X DisturbanceThread");
+
+ System.err.println("Demos: 8 - X DisturbanceThread");
disturbanceAction.stopAndWaitUntilDone();
}
@Test
- public void testWindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException {
+ public void test02AWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException {
/**
* JFrame . JPanel . Container . NewtCanvasAWT . GLWindow
*/
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
Assert.assertNotNull(glWindow1);
Assert.assertEquals(false, glWindow1.isVisible());
Assert.assertEquals(false, glWindow1.isNativeValid());
Assert.assertNull(glWindow1.getParent());
glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
/*
glWindow1.addGLEventListener(new GLEventListener() {
@Override
public void init(GLAutoDrawable drawable) {
- System.err.println("XXX init");
+ System.err.println("XXX init");
}
@Override
public void dispose(GLAutoDrawable drawable) {
- System.err.println("XXX dispose");
+ System.err.println("XXX dispose");
// Thread.dumpStack();
}
@Override
@@ -255,10 +266,10 @@ public class TestParenting01cSwingAWT extends UITestCase {
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
System.err.println("XXX reshape");
// Thread.dumpStack();
- }
+ }
}); */
glWindow1.addGLEventListener(demo1);
- Animator animator1 = new Animator(glWindow1);
+ final Animator animator1 = new Animator(glWindow1);
animator1.setUpdateFPSFrames(1, null);
animator1.start();
@@ -290,12 +301,12 @@ public class TestParenting01cSwingAWT extends UITestCase {
final JFrame jFrame1 = new JFrame("Swing Parent JFrame");
// jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
+ jFrame1.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
jFrame1.setContentPane(jPanel1);
- jFrame1.setLocation(0, 0);
- jFrame1.setSize(width, height);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ jFrame1.setLocation(0, 0);
+ jFrame1.setSize(width, height);
jFrame1.setVisible(true);
}
});
@@ -309,12 +320,12 @@ public class TestParenting01cSwingAWT extends UITestCase {
final JFrame jFrame2 = new JFrame("Swing Parent JFrame");
// jFrame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- jFrame2.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
+ jFrame2.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
jFrame2.setContentPane(jPanel2);
- jFrame2.setLocation(640, 480);
- jFrame2.setSize(width, height);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ jFrame2.setLocation(640, 480);
+ jFrame2.setSize(width, height);
jFrame2.setVisible(true);
}
});
@@ -322,6 +333,8 @@ public class TestParenting01cSwingAWT extends UITestCase {
// visible test
Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent());
+ final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen();
+
int state = 0;
while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) {
Thread.sleep(durationPerTest);
@@ -341,7 +354,7 @@ public class TestParenting01cSwingAWT extends UITestCase {
jPanel2.remove(newtCanvasAWT);
container1.add(newtCanvasAWT, BorderLayout.CENTER);
jFrame1.validate();
- jFrame2.validate();
+ jFrame2.validate();
} });
break;
}
@@ -364,11 +377,11 @@ public class TestParenting01cSwingAWT extends UITestCase {
jFrame1.validate();
System.err.println("Demos: 1 - X Container 2");
jPanel2.remove(newtCanvasAWT);
- jFrame2.validate();
+ jFrame2.validate();
} }); */
/*
* Invisible X11 windows may also case BadMatch (-> XAWT related)
- */
+ */
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
System.err.println("Demos: 2 - !visible");
@@ -385,20 +398,22 @@ public class TestParenting01cSwingAWT extends UITestCase {
System.err.println("Demos: 5 - X frame");
jFrame2.dispose();
} });
- Assert.assertEquals(true, glWindow1.isNativeValid());
+ if( wasOnscreen ) {
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+ } // else OK to be destroyed - due to offscreen/onscreen transition
- System.err.println("Demos: 6 - X GLWindow");
+ System.err.println("Demos: 6 - X GLWindow");
glWindow1.destroy();
Assert.assertEquals(false, glWindow1.isNativeValid());
-
- System.err.println("Demos: 7 - X DisturbanceThread");
- disturbanceAction.stopAndWaitUntilDone();
+
+ System.err.println("Demos: 7 - X DisturbanceThread");
+ disturbanceAction.stopAndWaitUntilDone();
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -408,15 +423,15 @@ public class TestParenting01cSwingAWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java
new file mode 100644
index 000000000..ad8a6f50e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java
@@ -0,0 +1,251 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt.parenting;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import java.awt.Button;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Frame;
+
+import javax.media.opengl.*;
+import javax.swing.SwingUtilities;
+
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.*;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import com.jogamp.opengl.test.junit.util.*;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+
+/**
+ * Test GL preservation case for reparenting.
+ * <p>
+ * Also simulates adding and attaching an already created GLWindow
+ * to a NewtCanvasAWT in recreation mode, where the GL state shall be preserved.
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestParenting01dAWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 800;
+ static GLCapabilities glCaps;
+
+ @BeforeClass
+ public static void initClass() throws InterruptedException {
+ width = 640;
+ height = 480;
+ glCaps = new GLCapabilities(null);
+ // Thread.sleep(10000);
+ }
+
+ static class MyGLEventListenerCounter extends GLEventListenerCounter {
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ super.init(drawable);
+ System.err.println("MyGLEventListenerCounter.init: "+this);
+ // Thread.dumpStack();
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ super.dispose(drawable);
+ System.err.println("MyGLEventListenerCounter.dispose: "+this);
+ // Thread.dumpStack();
+ }
+ }
+
+ @Test
+ public void test01GLWindowReparentRecreateNoPreserve() throws InterruptedException, InvocationTargetException {
+ testGLWindowInvisibleReparentRecreateImpl(false /* triggerPreserveGLState */);
+ }
+
+ @Test
+ public void test02GLWindowReparentRecreateGLPreserve() throws InterruptedException, InvocationTargetException {
+ testGLWindowInvisibleReparentRecreateImpl(true /* triggerPreserveGLState */);
+ }
+
+ private void testGLWindowInvisibleReparentRecreateImpl(final boolean triggerPreserveGLState) throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
+ Assert.assertNotNull(glWindow1);
+ Assert.assertEquals(false, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertNull(glWindow1.getParent());
+ glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
+ final MyGLEventListenerCounter glelCounter = new MyGLEventListenerCounter();
+ glWindow1.addGLEventListener(glelCounter);
+ final GLEventListener demo1 = new RedSquareES2();
+ glWindow1.addGLEventListener(demo1);
+ Assert.assertEquals("Init Counter Invalid "+glelCounter, 0, glelCounter.initCount);
+
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1);
+ Assert.assertNotNull(newtCanvasAWT);
+ Assert.assertEquals(false, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertNull(glWindow1.getParent());
+ Assert.assertEquals("Init Counter Invalid "+glelCounter, 0, glelCounter.initCount);
+
+ final Frame frame1 = new Frame("AWT Parent Frame");
+ frame1.setLayout(new BorderLayout());
+ frame1.add(new Button("North"), BorderLayout.NORTH);
+ frame1.add(new Button("South"), BorderLayout.SOUTH);
+ frame1.add(new Button("East"), BorderLayout.EAST);
+ frame1.add(new Button("West"), BorderLayout.WEST);
+
+ final Container container1 = new Container();
+ container1.setLayout(new BorderLayout());
+ container1.add(new Button("north"), BorderLayout.NORTH);
+ container1.add(new Button("south"), BorderLayout.SOUTH);
+ container1.add(new Button("east"), BorderLayout.EAST);
+ container1.add(new Button("west"), BorderLayout.WEST);
+ container1.add(newtCanvasAWT, BorderLayout.CENTER);
+
+ frame1.add(container1, BorderLayout.CENTER);
+
+ // visible test
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setSize(width, height);
+ frame1.setVisible(true);
+ }
+ });
+ Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent());
+
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow1, true));
+ glWindow1.display();
+ Assert.assertEquals("Init Counter Invalid "+glelCounter, 1, glelCounter.initCount);
+ Assert.assertEquals("Dispose Counter Invalid "+glelCounter, 0, glelCounter.disposeCount);
+
+ final int reparentingHints = Window.REPARENT_HINT_FORCE_RECREATION |
+ ( triggerPreserveGLState ? Window.REPARENT_HINT_BECOMES_VISIBLE : 0 );
+
+ //
+ // Even though the hint REPARENT_HINT_BECOMES_VISIBLE is not set (triggerPrerveGLState == false),
+ // since GLWindow is visible already the GL state shall be preserved!
+ //
+ System.err.println(getSimpleTestName(".")+": Start Reparent #1");
+ final Window.ReparentOperation rop1 = glWindow1.reparentWindow(null, -1, -1, reparentingHints);
+ System.err.println(getSimpleTestName(".")+": Result Reparent #1: "+rop1);
+ Assert.assertEquals(Window.ReparentOperation.ACTION_NATIVE_CREATION, rop1);
+ glWindow1.display();
+ Assert.assertEquals("Init Counter Invalid (Preserve Failed 1) "+glelCounter, 1, glelCounter.initCount);
+ Assert.assertEquals("Dispose Counter Invalid (Preserve Failed 1) "+glelCounter, 0, glelCounter.disposeCount);
+
+ //
+ // The following step is equivalent with adding and attaching an already created GLWindow
+ // to a NewtCanvasAWT in recreation mode if REPARENT_HINT_BECOMES_VISIBLE hint is set (triggerPrerveGLState == true).
+ // GL state shall be preserved!
+ //
+ glWindow1.setVisible(false);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, false));
+ System.err.println(getSimpleTestName(".")+": Start Reparent #2");
+ final Window.ReparentOperation rop2 = glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, reparentingHints);
+ System.err.println(getSimpleTestName(".")+": Result Reparent #2: "+rop2);
+ Assert.assertEquals(Window.ReparentOperation.ACTION_NATIVE_CREATION, rop2);
+ glWindow1.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow1, true));
+ glWindow1.display();
+ if( triggerPreserveGLState ) {
+ Assert.assertEquals("Init Counter Invalid (Preserve Failed 2) "+glelCounter, 1, glelCounter.initCount);
+ Assert.assertEquals("Dispose Counter Invalid (Preserve Failed 2) "+glelCounter, 0, glelCounter.disposeCount);
+ } else {
+ Assert.assertEquals("Init Counter Invalid (Preserve Failed 2) "+glelCounter, 2, glelCounter.initCount);
+ Assert.assertEquals("Dispose Counter Invalid (Preserve Failed 2) "+glelCounter, 1, glelCounter.disposeCount);
+ }
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while( t1 - t0 < durationPerTest ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(false);
+ } } );
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(true);
+ } } );
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+
+ final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen();
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.remove(newtCanvasAWT);
+ } } );
+ // Assert.assertNull(glWindow1.getParent());
+ if( wasOnscreen ) {
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+ } // else OK to be destroyed - due to offscreen/onscreen transition
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.dispose();
+ } } );
+ if( wasOnscreen ) {
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+ } // else OK to be destroyed - due to offscreen/onscreen transition
+
+ glWindow1.destroy();
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ if( triggerPreserveGLState ) {
+ Assert.assertEquals("Init Counter Invalid (Preserve Failed 1) "+glelCounter, 1, glelCounter.initCount);
+ Assert.assertEquals("Dispose Counter Invalid (Preserve Failed 1) "+glelCounter, 1, glelCounter.disposeCount);
+ } else {
+ Assert.assertEquals("Init Counter Invalid (Preserve Failed 1) "+glelCounter, 2, glelCounter.initCount);
+ Assert.assertEquals("Dispose Counter Invalid (Preserve Failed 1) "+glelCounter, 2, glelCounter.disposeCount);
+ }
+ }
+
+ public static void main(final String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+ }
+ }
+ final String tstname = TestParenting01dAWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java
index da689cea6..ed5c2f8a1 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,17 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import java.awt.Button;
import java.awt.BorderLayout;
@@ -49,6 +51,7 @@ import java.lang.reflect.InvocationTargetException;
import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting02AWT extends UITestCase {
static int width, height;
static long durationPerTest = 500;
@@ -62,27 +65,27 @@ public class TestParenting02AWT extends UITestCase {
}
@Test
- public void testWindowParenting01NewtChildOnAWTParentLayouted() throws InterruptedException, InvocationTargetException {
+ public void test01NewtChildOnAWTParentLayouted() throws InterruptedException, InvocationTargetException {
runNewtChildOnAWTParent(true, false);
}
@Test
- public void testWindowParenting02NewtChildOnAWTParentLayoutedDef() throws InterruptedException, InvocationTargetException {
+ public void test02NewtChildOnAWTParentLayoutedDef() throws InterruptedException, InvocationTargetException {
runNewtChildOnAWTParent(true, true);
}
@Test
- public void testWindowParenting03NewtChildOnAWTParentDirect() throws InterruptedException, InvocationTargetException {
+ public void test03NewtChildOnAWTParentDirect() throws InterruptedException, InvocationTargetException {
runNewtChildOnAWTParent(false, false);
}
@Test
- public void testWindowParenting04NewtChildOnAWTParentDirectDef() throws InterruptedException, InvocationTargetException {
+ public void test04NewtChildOnAWTParentDirectDef() throws InterruptedException, InvocationTargetException {
runNewtChildOnAWTParent(false, true);
}
public void runNewtChildOnAWTParent(final boolean useLayout, final boolean deferredPeer) throws InterruptedException, InvocationTargetException {
- NEWTEventFiFo eventFifo = new NEWTEventFiFo();
+ final NEWTEventFiFo eventFifo = new NEWTEventFiFo();
// setup NEWT GLWindow ..
final GLWindow glWindow = GLWindow.create(new GLCapabilities(null));
@@ -118,11 +121,10 @@ public class TestParenting02AWT extends UITestCase {
}
}
- // frame.setSize(width, height);
- frame.setBounds(100, 100, width, height);
-
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ // frame.setSize(width, height);
+ frame.setBounds(100, 100, width, height);
frame.setVisible(true);
}});
// X11: true, Windows: false - Assert.assertEquals(true, glWindow.isVisible());
@@ -149,6 +151,8 @@ public class TestParenting02AWT extends UITestCase {
glWindow.display();
} while(!glWindow.isNativeValid()) ;
+ final boolean wasOnscreen = glWindow.getChosenCapabilities().isOnscreen();
+
Assert.assertEquals(true, glWindow.isNativeValid());
Assert.assertNotNull(glWindow.getParent());
if(verbose) {
@@ -164,7 +168,9 @@ public class TestParenting02AWT extends UITestCase {
frame.validate();
}});
Assert.assertEquals(false, glWindow.isVisible());
- Assert.assertEquals(true, glWindow.isNativeValid());
+ if( wasOnscreen ) {
+ Assert.assertEquals(true, glWindow.isNativeValid());
+ } // else OK to be destroyed - due to offscreen/onscreen transition
Assert.assertNull(glWindow.getParent());
if(verbose) {
System.out.println("+++++++++++++++++++ REMOVED!");
@@ -188,7 +194,7 @@ public class TestParenting02AWT extends UITestCase {
}
long duration = durationPerTest;
- long step = 20;
+ final long step = 20;
NEWTEvent event;
boolean shouldQuit = false;
@@ -197,10 +203,10 @@ public class TestParenting02AWT extends UITestCase {
Thread.sleep(step);
duration -= step;
- while( null != ( event = (NEWTEvent) eventFifo.get() ) ) {
- Window source = (Window) event.getSource();
+ while( null != ( event = eventFifo.get() ) ) {
+ final Window source = (Window) event.getSource();
if(event instanceof KeyEvent) {
- KeyEvent keyEvent = (KeyEvent) event;
+ final KeyEvent keyEvent = (KeyEvent) event;
switch(keyEvent.getKeyChar()) {
case 'q':
shouldQuit = true;
@@ -209,7 +215,7 @@ public class TestParenting02AWT extends UITestCase {
source.setFullscreen(!source.isFullscreen());
break;
}
- }
+ }
}
}
if(verbose) {
@@ -231,10 +237,10 @@ public class TestParenting02AWT extends UITestCase {
} } );
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -244,15 +250,15 @@ public class TestParenting02AWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
verbose = true;
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
@@ -261,7 +267,7 @@ public class TestParenting02AWT extends UITestCase {
waitReparent = atoi(args[++i]);
}
}
- String tstname = TestParenting02AWT.class.getName();
+ final String tstname = TestParenting02AWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
/*
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java
index 8e2c73e9d..c9a96868f 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,18 +20,20 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import javax.media.opengl.*;
import javax.media.nativewindow.*;
@@ -48,6 +50,7 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
// import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1;
// import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting02NEWT extends UITestCase {
static int width, height;
static long durationPerTest = 500;
@@ -58,22 +61,22 @@ public class TestParenting02NEWT extends UITestCase {
height = 480;
}
- static Window createWindow(Screen screen, Capabilities caps) {
+ static Window createWindow(final Screen screen, final Capabilities caps) {
Assert.assertNotNull(caps);
- Window window = NewtFactory.createWindow(screen, caps) ;
+ final Window window = NewtFactory.createWindow(screen, caps) ;
Assert.assertNotNull(window);
return window;
}
- static Window createWindow(NativeWindow parent, Capabilities caps) {
+ static Window createWindow(final NativeWindow parent, final Capabilities caps) {
Assert.assertNotNull(caps);
- Window window = NewtFactory.createWindow(parent, caps);
+ final Window window = NewtFactory.createWindow(parent, caps);
window.setUndecorated(true);
Assert.assertNotNull(window);
return window;
}
- static void destroyWindow(Display display, Screen screen, Window window, GLWindow glWindow) {
+ static void destroyWindow(final Display display, final Screen screen, final Window window, final GLWindow glWindow) {
if(null!=glWindow) {
glWindow.destroy();
}
@@ -89,32 +92,32 @@ public class TestParenting02NEWT extends UITestCase {
}
@Test
- public void testWindowParenting01NewtOnNewtParentChildDraw() throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(null);
+ public void test01NewtOnNewtParentChildDraw() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(null);
Assert.assertNotNull(caps);
- Display display = NewtFactory.createDisplay(null); // local display
+ final Display display = NewtFactory.createDisplay(null); // local display
Assert.assertNotNull(display);
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
Assert.assertNotNull(screen);
int x = 1;
int y = 1;
- NEWTEventFiFo eventFifo = new NEWTEventFiFo();
+ final NEWTEventFiFo eventFifo = new NEWTEventFiFo();
- Window window1 = createWindow(screen, caps);
+ final Window window1 = createWindow(screen, caps);
Assert.assertNotNull(window1);
- GLWindow glWindow1 = GLWindow.create(window1);
+ final GLWindow glWindow1 = GLWindow.create(window1);
Assert.assertNotNull(glWindow1);
glWindow1.setSize(width, height);
Assert.assertEquals(width,glWindow1.getWidth());
Assert.assertEquals(height,glWindow1.getHeight());
- glWindow1.setTitle("testWindowParenting01NewtOnNewtParentChildDraw - PARENT");
+ glWindow1.setTitle("test01NewtOnNewtParentChildDraw - PARENT");
glWindow1.setPosition(x,y);
//glWindow1.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo)));
//glWindow1.addWindowListener(new TraceWindowAdapter());
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, window1, glWindow1, false);
// glWindow1.addGLEventListener(demo1);
@@ -123,20 +126,20 @@ public class TestParenting02NEWT extends UITestCase {
Assert.assertNotNull(capsChosen);
Assert.assertTrue(capsChosen.isOnscreen()==true);
- Window window2 = createWindow(window1, caps);
+ final Window window2 = createWindow(window1, caps);
Assert.assertNotNull(window2);
- GLWindow glWindow2 = GLWindow.create(window2);
+ final GLWindow glWindow2 = GLWindow.create(window2);
Assert.assertNotNull(glWindow2);
glWindow2.setSize(width/2, height/2);
//Assert.assertEquals(width/2,glWindow2.getWidth());
//Assert.assertEquals(height/2,glWindow2.getHeight());
- glWindow2.setTitle("testWindowParenting01NewtOnNewtParentChildDraw - CHILD");
+ glWindow2.setTitle("test01NewtOnNewtParentChildDraw - CHILD");
glWindow2.setPosition(glWindow1.getWidth()/2, glWindow1.getHeight()/2);
//glWindow2.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo)));
//glWindow2.addWindowListener(new TraceWindowAdapter(new WindowAction(eventFifo)));
// glWindow2.addMouseListener(new TraceMouseAdapter());
- GLEventListener demo2 = new GearsES2();
+ final GLEventListener demo2 = new GearsES2();
setDemoFields(demo2, window2, glWindow2, false);
// glWindow2.addGLEventListener(demo2);
@@ -150,7 +153,7 @@ public class TestParenting02NEWT extends UITestCase {
boolean shouldQuit = false;
long duration = durationPerTest;
- long step = 20;
+ final long step = 20;
NEWTEvent event;
while (duration>0 && !shouldQuit) {
@@ -163,12 +166,12 @@ public class TestParenting02NEWT extends UITestCase {
glWindow2.setPosition(glWindow1.getWidth()/2,glWindow1.getHeight()/2-y);
Thread.sleep(step);
- while( null != ( event = (NEWTEvent) eventFifo.get() ) ) {
- Window source = (Window) event.getSource();
+ while( null != ( event = eventFifo.get() ) ) {
+ final Window source = (Window) event.getSource();
if(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY == event.getEventType()) {
shouldQuit = true;
} else if(event instanceof KeyEvent) {
- KeyEvent keyEvent = (KeyEvent) event;
+ final KeyEvent keyEvent = (KeyEvent) event;
switch(keyEvent.getKeyChar()) {
case 'q':
shouldQuit = true;
@@ -177,14 +180,14 @@ public class TestParenting02NEWT extends UITestCase {
source.setFullscreen(!source.isFullscreen());
break;
}
- }
+ }
}
}
destroyWindow(null, null, window2, glWindow2);
destroyWindow(display, screen, window1, glWindow1);
}
- public static void setDemoFields(GLEventListener demo, Window window, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final Window window, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(window);
if(debug) {
@@ -196,21 +199,21 @@ public class TestParenting02NEWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
- String tstname = TestParenting02NEWT.class.getName();
+ final String tstname = TestParenting02NEWT.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java
index b33a40fae..fde366dd2 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import java.lang.reflect.*;
@@ -33,6 +33,8 @@ import java.lang.reflect.*;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import java.awt.BorderLayout;
import java.awt.Button;
@@ -52,6 +54,7 @@ import java.io.IOException;
import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting03AWT extends UITestCase {
static Dimension glSize, fSize;
static long durationPerTest = 1100;
@@ -66,27 +69,27 @@ public class TestParenting03AWT extends UITestCase {
}
@Test
- public void testWindowParenting1AWTOneNewtChilds01() throws InterruptedException, InvocationTargetException {
- testWindowParenting1AWT(false);
+ public void test01AWTOneNewtChilds01() throws InterruptedException, InvocationTargetException {
+ testImpl(false);
}
@Test
- public void testWindowParenting1AWTTwoNewtChilds01() throws InterruptedException, InvocationTargetException {
- testWindowParenting1AWT(true);
+ public void test02AWTTwoNewtChilds01() throws InterruptedException, InvocationTargetException {
+ testImpl(true);
}
-
- public void testWindowParenting1AWT(boolean use2nd) throws InterruptedException, InvocationTargetException {
+
+ public void testImpl(final boolean use2nd) throws InterruptedException, InvocationTargetException {
final Frame frame1 = new Frame("AWT Parent Frame");
- GLWindow glWindow1 = GLWindow.create(glCaps);
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
glWindow1.setUpdateFPSFrames(1, null);
final NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(glWindow1);
newtCanvasAWT1.setPreferredSize(glSize);
- GLEventListener demo1 = new GearsES2(1);
+ final GLEventListener demo1 = new GearsES2(1);
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
- glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1));
- GLAnimatorControl animator1 = new Animator(glWindow1);
+ glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1, null));
+ final GLAnimatorControl animator1 = new Animator(glWindow1);
animator1.start();
GLWindow glWindow2 = null;
@@ -97,11 +100,11 @@ public class TestParenting03AWT extends UITestCase {
glWindow2.setUpdateFPSFrames(1, null);
newtCanvasAWT2 = new NewtCanvasAWT(glWindow2);
newtCanvasAWT2.setPreferredSize(glSize);
-
- GLEventListener demo2 = new GearsES2(1);
+
+ final GLEventListener demo2 = new GearsES2(1);
setDemoFields(demo2, glWindow2, false);
glWindow2.addGLEventListener(demo2);
- glWindow2.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT2, glWindow2));
+ glWindow2.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT2, glWindow2, null));
animator2 = new Animator(glWindow2);
animator2.start();
}
@@ -133,17 +136,17 @@ public class TestParenting03AWT extends UITestCase {
frame1.add(new Button("CENTER"), BorderLayout.CENTER);
frame1.add(new Button("SOUTH"), BorderLayout.SOUTH);
frame1.add(cont1, BorderLayout.EAST);
- frame1.setLocation(0, 0);
- frame1.setSize(fSize);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
System.err.println("******* Frame setVisible");
- frame1.validate();
+ frame1.setLocation(0, 0);
+ frame1.setSize(fSize);
+ frame1.validate();
frame1.setVisible(true);
}});
Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent());
-
+
Assert.assertEquals(true, animator1.isAnimating());
Assert.assertEquals(false, animator1.isPaused());
Assert.assertNotNull(animator1.getThread());
@@ -154,7 +157,7 @@ public class TestParenting03AWT extends UITestCase {
Assert.assertNotNull(animator2.getThread());
Thread.sleep(waitAdd2nd);
-
+
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame1.add(cont2, BorderLayout.WEST);
@@ -188,10 +191,10 @@ public class TestParenting03AWT extends UITestCase {
}
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -201,15 +204,15 @@ public class TestParenting03AWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
@@ -217,7 +220,7 @@ public class TestParenting03AWT extends UITestCase {
waitAdd2nd = atoi(args[++i]);
}
}
- String tstname = TestParenting03AWT.class.getName();
+ final String tstname = TestParenting03AWT.class.getName();
/*
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java
index 09b6d048c..3ff4ecdaa 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import java.awt.BorderLayout;
@@ -41,6 +41,8 @@ import javax.swing.SwingUtilities;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.newt.Window;
import com.jogamp.newt.awt.NewtCanvasAWT;
@@ -54,6 +56,7 @@ import com.jogamp.opengl.util.Animator;
/**
* Using {@link NewtCanvasAWT#setNEWTChild(Window)} for reparenting, i.e. NEWT/AWT hopping
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting04AWT extends UITestCase {
static int width, height;
static long durationPerTest = 800;
@@ -67,30 +70,30 @@ public class TestParenting04AWT extends UITestCase {
}
@Test
- public void winHopFrame2FrameDirectHop() throws InterruptedException, InvocationTargetException {
+ public void test01WinHopFrame2FrameDirectHop() throws InterruptedException, InvocationTargetException {
// Will produce some artifacts .. resizing etc
winHopFrame2Frame(false);
}
-
+
@Test
- public void winHopFrame2FrameDetachFirst() throws InterruptedException, InvocationTargetException {
- // Note: detaching first setNEWTChild(null) is much cleaner visually
+ public void test02WinHopFrame2FrameDetachFirst() throws InterruptedException, InvocationTargetException {
+ // Note: detaching first setNEWTChild(null) is much cleaner visually
winHopFrame2Frame(true);
}
-
+
protected void winHopFrame2Frame(final boolean detachFirst) throws InterruptedException, InvocationTargetException {
final GLWindow glWindow1 = GLWindow.create(glCaps);
- GLEventListener demo1 = new RedSquareES2();
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
- Animator anim1 = new Animator(glWindow1);
+ final Animator anim1 = new Animator(glWindow1);
final GLWindow glWindow2 = GLWindow.create(glCaps);
- GLEventListener demo2 = new GearsES2();
+ final GLEventListener demo2 = new GearsES2();
setDemoFields(demo2, glWindow2, false);
glWindow2.addGLEventListener(demo2);
- Animator anim2 = new Animator(glWindow2);
-
+ final Animator anim2 = new Animator(glWindow2);
+
final NewtCanvasAWT canvas1 = new NewtCanvasAWT(glWindow1);
final NewtCanvasAWT canvas2 = new NewtCanvasAWT(glWindow2);
@@ -100,10 +103,10 @@ public class TestParenting04AWT extends UITestCase {
frame1.add(new Button("South"), BorderLayout.SOUTH);
frame1.add(new Button("East"), BorderLayout.EAST);
frame1.add(new Button("West"), BorderLayout.WEST);
- frame1.setSize(width, height);
- frame1.setLocation(0, 0);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame1.setSize(width, height);
+ frame1.setLocation(0, 0);
frame1.setVisible(true);
frame1.validate();
}
@@ -116,17 +119,17 @@ public class TestParenting04AWT extends UITestCase {
}
});
Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent());
-
+
final Frame frame2 = new Frame("AWT Parent Frame");
frame2.setLayout(new BorderLayout());
frame2.add(new Button("North"), BorderLayout.NORTH);
frame2.add(new Button("South"), BorderLayout.SOUTH);
frame2.add(new Button("East"), BorderLayout.EAST);
frame2.add(new Button("West"), BorderLayout.WEST);
- frame2.setSize(width, height);
- frame2.setLocation(width+50, 0);
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame2.setSize(width, height);
+ frame2.setLocation(width+50, 0);
frame2.setVisible(true);
frame2.validate();
}
@@ -142,7 +145,7 @@ public class TestParenting04AWT extends UITestCase {
anim1.start();
anim2.start();
-
+
int state;
for(state=0; state<3; state++) {
Thread.sleep(durationPerTest);
@@ -153,12 +156,14 @@ public class TestParenting04AWT extends UITestCase {
// 1 -> 2
if(detachFirst) {
canvas1.setNEWTChild(null);
- canvas2.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
} else {
canvas2.setNEWTChild(null); // free g2 of w2
}
canvas1.setNEWTChild(glWindow2); // put g2 -> w1. free g1 of w1
canvas2.setNEWTChild(glWindow1); // put g1 -> w2
+ frame1.invalidate();
+ frame2.invalidate();
frame1.validate();
frame2.validate();
}
@@ -170,12 +175,14 @@ public class TestParenting04AWT extends UITestCase {
// 2 -> 1
if(detachFirst) {
canvas1.setNEWTChild(null);
- canvas2.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
} else {
canvas2.setNEWTChild(null);
}
canvas1.setNEWTChild(glWindow1);
canvas2.setNEWTChild(glWindow2);
+ frame1.invalidate();
+ frame2.invalidate();
frame1.validate();
frame2.validate();
}
@@ -192,13 +199,13 @@ public class TestParenting04AWT extends UITestCase {
glWindow1.destroy();
glWindow2.destroy();
Assert.assertEquals(false, glWindow1.isNativeValid());
- Assert.assertEquals(false, glWindow2.isNativeValid());
+ Assert.assertEquals(false, glWindow2.isNativeValid());
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -208,21 +215,21 @@ public class TestParenting04AWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
- String tstname = TestParenting04AWT.class.getName();
+ final String tstname = TestParenting04AWT.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java
index 14a36c573..631d2309a 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import java.io.IOException;
@@ -45,8 +45,11 @@ import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Window;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.newt.swt.NewtCanvasSWT;
@@ -59,6 +62,7 @@ import com.jogamp.opengl.util.Animator;
/**
* Using {@link NewtCanvasSWT#setNEWTChild(Window)} for reparenting, i.e. NEWT/AWT hopping
*/
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParenting04SWT extends UITestCase {
static int width, height;
static long durationPerTest = 800;
@@ -69,7 +73,8 @@ public class TestParenting04SWT extends UITestCase {
Shell shell2 = null;
Composite composite1 = null;
Composite composite2 = null;
-
+ com.jogamp.newt.Display swtNewtDisplay = null;
+
@BeforeClass
public static void initClass() {
width = 400;
@@ -80,17 +85,17 @@ public class TestParenting04SWT extends UITestCase {
@Before
public void init() {
SWTAccessor.invoke(true, new Runnable() {
- public void run() {
+ public void run() {
display = new Display();
Assert.assertNotNull( display );
-
+
shell1 = new Shell( display );
Assert.assertNotNull( shell1 );
shell1.setLayout( new FillLayout() );
composite1 = new Composite( shell1, SWT.NONE );
composite1.setLayout( new FillLayout() );
Assert.assertNotNull( composite1 );
-
+
shell2 = new Shell( display );
Assert.assertNotNull( shell2 );
shell2.setLayout( new FillLayout() );
@@ -98,8 +103,9 @@ public class TestParenting04SWT extends UITestCase {
composite2.setLayout( new FillLayout() );
Assert.assertNotNull( composite2 );
}});
+ swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse
}
-
+
@After
public void release() {
Assert.assertNotNull( display );
@@ -117,45 +123,48 @@ public class TestParenting04SWT extends UITestCase {
display.dispose();
}});
}
- catch( Throwable throwable ) {
+ catch( final Throwable throwable ) {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
+ swtNewtDisplay = null;
display = null;
shell1 = null;
shell2 = null;
composite1 = null;
composite2 = null;
}
-
+
@Test
- public void winHopFrame2FrameDirectHop() throws InterruptedException, InvocationTargetException {
+ public void test01WinHopFrame2FrameDirectHop() throws InterruptedException, InvocationTargetException {
// Will produce some artifacts .. resizing etc
winHopFrame2Frame(false);
}
-
+
@Test
- public void winHopFrame2FrameDetachFirst() throws InterruptedException, InvocationTargetException {
- // Note: detaching first setNEWTChild(null) is much cleaner visually
+ public void test02WinHopFrame2FrameDetachFirst() throws InterruptedException, InvocationTargetException {
+ // Note: detaching first setNEWTChild(null) is much cleaner visually
winHopFrame2Frame(true);
}
-
+
protected void winHopFrame2Frame(final boolean detachFirst) throws InterruptedException, InvocationTargetException {
- final GLWindow glWindow1 = GLWindow.create(glCaps);
- GLEventListener demo1 = new RedSquareES2();
+ final com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, 0);
+
+ final GLWindow glWindow1 = GLWindow.create(screen, glCaps);
+ final GLEventListener demo1 = new RedSquareES2();
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
- Animator anim1 = new Animator(glWindow1);
-
- final GLWindow glWindow2 = GLWindow.create(glCaps);
- GLEventListener demo2 = new GearsES2();
+ final Animator anim1 = new Animator(glWindow1);
+
+ final GLWindow glWindow2 = GLWindow.create(screen, glCaps);
+ final GLEventListener demo2 = new GearsES2();
setDemoFields(demo2, glWindow2, false);
glWindow2.addGLEventListener(demo2);
- Animator anim2 = new Animator(glWindow2);
+ final Animator anim2 = new Animator(glWindow2);
final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite1, 0, glWindow1 );
final NewtCanvasSWT canvas2 = NewtCanvasSWT.create( composite2, 0, glWindow2 );
-
+
SWTAccessor.invoke(true, new Runnable() {
public void run() {
shell1.setText( getSimpleTestName(".")+"-Win1" );
@@ -167,13 +176,13 @@ public class TestParenting04SWT extends UITestCase {
shell2.setLocation(width + 50, 0);
shell2.open();
}
- });
+ });
Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent());
Assert.assertEquals(canvas2.getNativeWindow(),glWindow2.getParent());
anim1.start();
anim2.start();
-
+
int state;
for(state=0; state<3; state++) {
for(int i=0; i*10<durationPerTest; i++) {
@@ -189,7 +198,7 @@ public class TestParenting04SWT extends UITestCase {
// 1 -> 2
if(detachFirst) {
canvas1.setNEWTChild(null);
- canvas2.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
} else {
canvas2.setNEWTChild(null); // free g2 of w2
}
@@ -203,7 +212,7 @@ public class TestParenting04SWT extends UITestCase {
// 2 -> 1
if(detachFirst) {
canvas1.setNEWTChild(null);
- canvas2.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
} else {
canvas2.setNEWTChild(null);
}
@@ -217,13 +226,13 @@ public class TestParenting04SWT extends UITestCase {
canvas1.dispose();
canvas2.dispose();
Assert.assertEquals(false, glWindow1.isNativeValid());
- Assert.assertEquals(false, glWindow2.isNativeValid());
+ Assert.assertEquals(false, glWindow2.isNativeValid());
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -233,21 +242,21 @@ public class TestParenting04SWT extends UITestCase {
}
}
- static int atoi(String a) {
+ static int atoi(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
+ } catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
}
}
- String tstname = TestParenting04SWT.class.getName();
+ final String tstname = TestParenting04SWT.class.getName();
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
"filtertrace=true",
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentChildWindowBug632NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentChildWindowBug632NEWT.java
new file mode 100644
index 000000000..c9390f124
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentChildWindowBug632NEWT.java
@@ -0,0 +1,135 @@
+package com.jogamp.opengl.test.junit.newt.parenting;
+
+import java.io.IOException;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestTranslucentChildWindowBug632NEWT extends UITestCase {
+ static long durationPerTest = 2*300;
+ static GLProfile glp;
+ static boolean opaque;
+
+ @BeforeClass
+ public static void initClass() {
+ glp = GLProfile.getDefault();
+ opaque = false;
+ }
+
+ static GLWindow createParentWindow(final GLCapabilitiesImmutable caps, final int width, final int height)
+ throws InterruptedException
+ {
+ Assert.assertNotNull(caps);
+ //
+ // Create native windowing resources .. X11/Win/OSX
+ //
+ GLWindow glWindow;
+ glWindow = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow);
+
+ glWindow.setTitle("NEWT Parenting Window Test");
+
+ glWindow.addGLEventListener(new GearsES2(1));
+
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+ Assert.assertEquals(true,glWindow.isVisible());
+ Assert.assertEquals(true,glWindow.isNativeValid());
+
+ return glWindow;
+ }
+
+ static GLWindow createNestedWindow(final NativeWindow nativeParentWindow, final GLCapabilitiesImmutable caps, final int x, final int y, final int width, final int height)
+ throws InterruptedException {
+
+ Assert.assertNotNull(nativeParentWindow);
+ Assert.assertNotNull(caps);
+ //
+ // Create native windowing resources .. X11/Win/OSX
+ //
+ GLWindow glWindow;
+ glWindow = GLWindow.create(nativeParentWindow, caps);
+ Assert.assertNotNull(glWindow);
+
+ glWindow.setTitle("NEWT Parenting Window Test");
+
+ glWindow.addGLEventListener(new GearsES2(1));
+
+ glWindow.setPosition(x, y);
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+ Assert.assertEquals(true,glWindow.isVisible());
+ Assert.assertEquals(true,glWindow.isNativeValid());
+
+ return glWindow;
+ }
+
+ static void destroyWindow(final GLWindow glWindow) {
+ if(null!=glWindow) {
+ glWindow.destroy();
+ Assert.assertEquals(false,glWindow.isNativeValid());
+ }
+ }
+
+ @Test
+ public void testWindow00() throws InterruptedException {
+ final Animator animator = new Animator();
+
+ final GLCapabilities caps = new GLCapabilities(glp);
+ Assert.assertNotNull(caps);
+ caps.setBackgroundOpaque(opaque);
+ final GLWindow window1 = createParentWindow(caps, 400, 400);
+ Assert.assertEquals(true,window1.isNativeValid());
+ Assert.assertEquals(true,window1.isVisible());
+ animator.add(window1);
+
+ final GLWindow window2 = createNestedWindow(window1, caps, 400-300, 400-300, 300, 300);
+ Assert.assertEquals(true,window2.isNativeValid());
+ Assert.assertEquals(true,window2.isVisible());
+ animator.add(window2);
+
+ animator.start();
+
+ final AbstractGraphicsDevice device1 = window1.getScreen().getDisplay().getGraphicsDevice();
+
+ System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1));
+
+ Thread.sleep(durationPerTest/2);
+
+ window1.setSize(512, 512);
+ window2.setPosition(512-300, 512-300);
+
+ Thread.sleep(durationPerTest/2);
+
+ animator.stop();
+
+ destroyWindow(window2);
+ destroyWindow(window1);
+ }
+
+ public static void main(final String[] args) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+ }
+ }
+ final String testName = TestTranslucentChildWindowBug632NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(testName);
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java
index 373c83fce..3eb0c1325 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.newt.parenting;
import java.awt.BorderLayout;
@@ -49,6 +49,8 @@ import javax.media.opengl.GLEventListener;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.newt.Window;
@@ -59,6 +61,7 @@ import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTranslucentParentingAWT extends UITestCase {
static Dimension size;
static long durationPerTest = 400;
@@ -79,23 +82,23 @@ public class TestTranslucentParentingAWT extends UITestCase {
static Frame getTranslucentFrame() {
GraphicsConfiguration gc=null;
- GraphicsDevice[] devices= GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
+ final GraphicsDevice[] devices= GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
for (int i = 0; i < devices.length ; i++)
{
- GraphicsConfiguration[] configs = devices[i].getConfigurations();
+ final GraphicsConfiguration[] configs = devices[i].getConfigurations();
for (int j = 0; j < configs.length ; j++) {
- GraphicsConfiguration config = configs[j];
- ColorModel tcm = config.getColorModel(Transparency.TRANSLUCENT);
- boolean capable1 = ( null != tcm ) ? tcm.getTransparency() == Transparency.TRANSLUCENT : false;
+ final GraphicsConfiguration config = configs[j];
+ final ColorModel tcm = config.getColorModel(Transparency.TRANSLUCENT);
+ final boolean capable1 = ( null != tcm ) ? tcm.getTransparency() == Transparency.TRANSLUCENT : false;
boolean capable2 = false;
try {
capable2 = ((Boolean)ReflectionUtil.callStaticMethod(
- "com.sun.awt.AWTUtilities", "isTranslucencyCapable",
- new Class<?>[] { GraphicsConfiguration.class },
- new Object[] { config } ,
+ "com.sun.awt.AWTUtilities", "isTranslucencyCapable",
+ new Class<?>[] { GraphicsConfiguration.class },
+ new Object[] { config } ,
GraphicsConfiguration.class.getClassLoader())).booleanValue();
System.err.println("com.sun.awt.AWTUtilities.isTranslucencyCapable(config) passed: "+capable2);
- } catch (RuntimeException re) {
+ } catch (final RuntimeException re) {
System.err.println("com.sun.awt.AWTUtilities.isTranslucencyCapable(config) failed: "+re.getMessage());
}
System.err.println(i+":"+j+" "+config+", "+tcm+", capable "+capable1+"/"+capable2);
@@ -114,7 +117,7 @@ public class TestTranslucentParentingAWT extends UITestCase {
frame.setTitle("AWT Parent Frame (opaque: "+(null==gc)+")");
return frame;
}
-
+
public void testWindowParenting1AWTOneNewtChild() throws InterruptedException, InvocationTargetException {
final Frame frame1 = getTranslucentFrame();
final GLWindow glWindow1 = GLWindow.create(glCaps);
@@ -123,13 +126,13 @@ public class TestTranslucentParentingAWT extends UITestCase {
final NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(frame1.getGraphicsConfiguration(), glWindow1);
newtCanvasAWT1.setPreferredSize(size);
- GLEventListener demo1 = new GearsES2(1);
+ final GLEventListener demo1 = new GearsES2(1);
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
- GLAnimatorControl animator1 = new Animator(glWindow1);
+ final GLAnimatorControl animator1 = new Animator(glWindow1);
animator1.start();
- Container cont1 = new Container();
+ final Container cont1 = new Container();
cont1.setLayout(new BorderLayout());
cont1.add(newtCanvasAWT1, BorderLayout.CENTER);
cont1.setVisible(true);
@@ -137,10 +140,10 @@ public class TestTranslucentParentingAWT extends UITestCase {
frame1.setLayout(new BorderLayout());
frame1.add(cont1, BorderLayout.EAST);
frame1.add(new Label("center"), BorderLayout.CENTER);
- frame1.setLocation(0, 0);
- frame1.setSize((int)size.getWidth(), (int)size.getHeight());
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ frame1.setLocation(0, 0);
+ frame1.setSize((int)size.getWidth(), (int)size.getHeight());
frame1.pack();
frame1.setVisible(true);
}});
@@ -157,14 +160,17 @@ public class TestTranslucentParentingAWT extends UITestCase {
Assert.assertEquals(false, animator1.isPaused());
Assert.assertEquals(null, animator1.getThread());
- frame1.dispose();
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.dispose();
+ } } );
glWindow1.destroy();
}
- public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
- Window window = glWindow.getDelegatedWindow();
+ final Window window = glWindow.getDelegatedWindow();
if(debug) {
MiscUtils.setFieldIfExists(demo, "glDebug", true);
MiscUtils.setFieldIfExists(demo, "glTrace", true);
@@ -174,23 +180,15 @@ public class TestTranslucentParentingAWT extends UITestCase {
}
}
- static int atoi(String a) {
- int i=0;
- try {
- i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
- return i;
- }
-
- public static void main(String args[]) throws IOException {
+ public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
- durationPerTest = atoi(args[++i]);
+ durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
} else if(args[i].equals("-wait")) {
- waitAdd2nd = atoi(args[++i]);
+ waitAdd2nd = MiscUtils.atol(args[++i], waitAdd2nd);
}
}
- String tstname = TestTranslucentParentingAWT.class.getName();
+ final String tstname = TestTranslucentParentingAWT.class.getName();
/*
org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
tstname,
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/WindowAction.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/WindowAction.java
index 05793b96e..b960103d9 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/WindowAction.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/WindowAction.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -33,14 +33,14 @@ import com.jogamp.newt.event.*;
class WindowAction extends WindowAdapter {
NEWTEventFiFo eventFifo;
- public WindowAction(NEWTEventFiFo eventFifo) {
- this.eventFifo = eventFifo;
+ public WindowAction(final NEWTEventFiFo eventFifo) {
+ this.eventFifo = eventFifo;
}
- public void windowDestroyNotify(WindowEvent e) {
+ public void windowDestroyNotify(final WindowEvent e) {
eventFifo.put(e);
}
- public void windowDestroyed(WindowEvent e) {
+ public void windowDestroyed(final WindowEvent e) {
eventFifo.put(e);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTFocusAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTFocusAdapter.java
index fe0f2acc0..d574186cf 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTFocusAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTFocusAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
import java.awt.event.FocusEvent;
@@ -36,20 +36,23 @@ public class AWTFocusAdapter implements FocusEventCountAdapter, FocusListener {
String prefix;
int focusCount;
boolean wasTemporary;
+ boolean verbose = true;
- public AWTFocusAdapter(String prefix) {
+ public AWTFocusAdapter(final String prefix) {
this.prefix = prefix;
reset();
}
+ public void setVerbose(final boolean v) { verbose = false; }
+
public boolean focusLost() {
- return focusCount<0;
+ return focusCount<0;
}
-
+
public boolean focusGained() {
return focusCount>0;
}
-
+
public void reset() {
focusCount = 0;
wasTemporary = false;
@@ -61,20 +64,24 @@ public class AWTFocusAdapter implements FocusEventCountAdapter, FocusListener {
}
/* @Override */
- public void focusGained(FocusEvent e) {
+ public void focusGained(final FocusEvent e) {
if(focusCount<0) { focusCount=0; }
focusCount++;
wasTemporary = e.isTemporary();
- System.err.println("FOCUS AWT GAINED "+(wasTemporary?"TEMP":"PERM")+" [fc "+focusCount+"]: "+prefix+", "+e);
+ if( verbose ) {
+ System.err.println("FOCUS AWT GAINED "+(wasTemporary?"TEMP":"PERM")+" [fc "+focusCount+"]: "+prefix+", "+e);
+ }
}
/* @Override */
- public void focusLost(FocusEvent e) {
+ public void focusLost(final FocusEvent e) {
if(focusCount>0) { focusCount=0; }
focusCount--;
wasTemporary = e.isTemporary();
- System.err.println("FOCUS AWT LOST "+(wasTemporary?"TEMP":"PERM")+" [fc "+focusCount+"]: "+prefix+", "+e);
+ if( verbose ) {
+ System.err.println("FOCUS AWT LOST "+(wasTemporary?"TEMP":"PERM")+" [fc "+focusCount+"]: "+prefix+", "+e);
+ }
}
-
- public String toString() { return prefix+"[focusCount "+focusCount +", temp "+wasTemporary+"]"; }
+
+ public String toString() { return prefix+"[focusCount "+focusCount +", temp "+wasTemporary+"]"; }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java
index 6c0156170..84c19612b 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,55 +20,92 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.List;
-public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements InputEventCountAdapter {
+public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEventCountAdapter {
String prefix;
- int keyTyped;
+ int keyPressed, keyReleased;
+ int consumed;
boolean pressed;
+ List<EventObject> queue = new ArrayList<EventObject>();
+ boolean verbose = true;
- public AWTKeyAdapter(String prefix) {
+ public AWTKeyAdapter(final String prefix) {
this.prefix = prefix;
reset();
}
- public boolean isPressed() {
+ public synchronized void setVerbose(final boolean v) { verbose = v; }
+
+ public synchronized boolean isPressed() {
return pressed;
}
-
- public int getCount() {
- return keyTyped;
+
+ public synchronized int getCount() {
+ return keyReleased;
+ }
+
+ public synchronized int getConsumedCount() {
+ return consumed;
+ }
+
+ public synchronized int getKeyPressedCount(final boolean autoRepeatOnly) {
+ return keyPressed;
}
- public void reset() {
- keyTyped = 0;
+ public synchronized int getKeyReleasedCount(final boolean autoRepeatOnly) {
+ return keyReleased;
+ }
+
+ public synchronized List<EventObject> copyQueue() {
+ return new ArrayList<EventObject>(queue);
+ }
+
+ public synchronized int getQueueSize() {
+ return queue.size();
+ }
+
+ public synchronized void reset() {
+ keyPressed = 0;
+ keyReleased = 0;
+ consumed = 0;
pressed = false;
+ queue.clear();
}
- public void keyPressed(KeyEvent e) {
+ public synchronized void keyPressed(final KeyEvent e) {
pressed = true;
- System.err.println("KEY AWT PRESSED ["+pressed+"]: "+prefix+", "+e);
+ keyPressed++;
+ queue.add(e);
+ if( verbose ) {
+ System.err.println("KEY AWT PRESSED ["+pressed+"]: "+prefix+", "+e);
+ }
}
- public void keyReleased(KeyEvent e) {
+ public synchronized void keyReleased(final KeyEvent e) {
pressed = false;
- System.err.println("KEY AWT RELEASED ["+pressed+"]: "+prefix+", "+e);
+ keyReleased++;
+ if(e.isConsumed()) {
+ consumed++;
+ }
+ queue.add(e);
+ if( verbose ) {
+ System.err.println("KEY AWT RELEASED ["+pressed+"]: "+prefix+", "+e);
+ }
}
- public void keyTyped(java.awt.event.KeyEvent e) {
- ++keyTyped;
- System.err.println("KEY AWT TYPED ["+keyTyped+"]: "+prefix+", "+e);
- }
-
- public String toString() { return prefix+"[pressed "+pressed+", typed "+keyTyped+"]"; }
+ public String toString() { return prefix+"[pressed "+pressed+", keyReleased "+keyReleased+", consumed "+consumed+"]"; }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java
index b94802348..2a4f7a71f 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,54 +20,88 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.List;
public class AWTMouseAdapter extends java.awt.event.MouseAdapter implements InputEventCountAdapter {
String prefix;
int mouseClicked;
+ int consumed;
boolean pressed;
+ List<EventObject> queue = new ArrayList<EventObject>();
+ boolean verbose = true;
- public AWTMouseAdapter(String prefix) {
+ public AWTMouseAdapter(final String prefix) {
this.prefix = prefix;
reset();
}
- public boolean isPressed() {
+ public synchronized void setVerbose(final boolean v) { verbose = v; }
+
+ public synchronized boolean isPressed() {
return pressed;
}
-
- public int getCount() {
+
+ public synchronized int getCount() {
return mouseClicked;
}
-
- public void reset() {
+
+ public synchronized int getConsumedCount() {
+ return consumed;
+ }
+
+ public synchronized List<EventObject> copyQueue() {
+ return new ArrayList<EventObject>(queue);
+ }
+
+ public synchronized int getQueueSize() {
+ return queue.size();
+ }
+
+ public synchronized void reset() {
mouseClicked = 0;
+ consumed = 0;
pressed = false;
+ queue.clear();
}
- public void mousePressed(MouseEvent e) {
+ public synchronized void mousePressed(final MouseEvent e) {
pressed = true;
- System.err.println("MOUSE AWT PRESSED ["+pressed+"]: "+prefix+", "+e);
+ queue.add(e);
+ if( verbose ) {
+ System.err.println("MOUSE AWT PRESSED ["+pressed+"]: "+prefix+", "+e);
+ }
}
- public void mouseReleased(MouseEvent e) {
+ public synchronized void mouseReleased(final MouseEvent e) {
pressed = false;
- System.err.println("MOUSE AWT RELEASED ["+pressed+"]: "+prefix+", "+e);
+ queue.add(e);
+ if( verbose ) {
+ System.err.println("MOUSE AWT RELEASED ["+pressed+"]: "+prefix+", "+e);
+ }
}
-
- public void mouseClicked(java.awt.event.MouseEvent e) {
+
+ public synchronized void mouseClicked(final java.awt.event.MouseEvent e) {
mouseClicked+=e.getClickCount();
- System.err.println("MOUSE AWT CLICKED ["+mouseClicked+"]: "+prefix+", "+e);
- }
-
- public String toString() { return prefix+"[pressed "+pressed+", clicked "+mouseClicked+"]"; }
+ if(e.isConsumed()) {
+ consumed++;
+ }
+ queue.add(e);
+ if( verbose ) {
+ System.err.println("MOUSE AWT CLICKED ["+mouseClicked+"]: "+prefix+", "+e);
+ }
+ }
+
+ public String toString() { return prefix+"[pressed "+pressed+", clicked "+mouseClicked+", consumed "+consumed+"]"; }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
index 160653cd5..31d6b887d 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,40 +20,94 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
import jogamp.newt.WindowImplAccess;
+import jogamp.newt.awt.event.AWTNewtEventFactory;
+
+import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.InvocationTargetException;
+import java.util.concurrent.atomic.AtomicInteger;
import java.awt.AWTException;
-import java.awt.Component;
import java.awt.EventQueue;
-import java.awt.KeyboardFocusManager;
import java.awt.Robot;
-import java.awt.Toolkit;
import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
-import javax.media.opengl.awt.GLCanvas;
import org.junit.Assert;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.newt.event.WindowEvent;
+
public class AWTRobotUtil {
static final boolean DEBUG = false;
-
+
public static final int RETRY_NUMBER = 5;
public static final int ROBOT_DELAY = 100; // ms
public static final int TIME_OUT = 2000; // 2s
public static final int POLL_DIVIDER = 20; // TO/20
public static final int TIME_SLICE = TIME_OUT / POLL_DIVIDER ;
- public static Integer AWT_CLICK_TO = null;
-
+ public static Integer AWT_CLICK_TO = null;
+
+ static class OurUncaughtExceptionHandler implements UncaughtExceptionHandler {
+ @Override
+ public void uncaughtException(final Thread t, final Throwable e) {
+ System.err.println("*** AWTRobotUtil: UncaughtException (this Thread "+Thread.currentThread().getName()+") : Thread <"+t.getName()+">, "+e.getClass().getName()+": "+e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ static {
+ Thread.setDefaultUncaughtExceptionHandler( new OurUncaughtExceptionHandler() );
+ // System.err.println("AWT EDT alive: "+isAWTEDTAlive());
+ }
+
+ /** Probes whether AWT's EDT is alive or not. */
+ public static boolean isAWTEDTAlive() {
+ if( EventQueue.isDispatchThread() ) {
+ return true;
+ }
+ synchronized ( awtEDTAliveSync ) {
+ awtEDTAliveFlag = false;
+ EventQueue.invokeLater(aliveRun);
+ for (int wait=0; wait<POLL_DIVIDER && !awtEDTAliveFlag; wait++) {
+ try {
+ Thread.sleep(TIME_SLICE);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ return awtEDTAliveFlag;
+ }
+ }
+ private static Runnable aliveRun = new Runnable() { public void run() { awtEDTAliveFlag = true; } };
+ private static Object awtEDTAliveSync = new Object();
+ private static volatile boolean awtEDTAliveFlag = false;
+
+ /** Throws Error if {@link #isAWTEDTAlive()} returns false. */
+ public static void validateAWTEDTIsAlive() {
+ if( !isAWTEDTAlive() ) {
+ throw new Error("AWT EDT not alive");
+ }
+ }
+
+ /** Issuing {@link #validateAWTEDTIsAlive()} before calling {@link Robot#waitForIdle()}. */
+ public static void waitForIdle(final Robot robot) {
+ validateAWTEDTIsAlive();
+ robot.waitForIdle();
+ }
+
public static void clearAWTFocus(Robot robot) throws InterruptedException, InvocationTargetException, AWTException {
if(null == robot) {
robot = new Robot();
@@ -62,50 +116,74 @@ public class AWTRobotUtil {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
System.err.println("******** clearAWTFocus.0");
- KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
}});
robot.delay(ROBOT_DELAY);
System.err.println("******** clearAWTFocus.X");
}
-
- public static java.awt.Point getCenterLocation(Object obj, boolean onTitleBarIfWindow)
- throws InterruptedException, InvocationTargetException {
- Component comp = null;
- com.jogamp.newt.Window win = null;
+ public static int[] getCenterLocation(final Object obj, final boolean onTitleBarIfWindow)
+ throws InterruptedException, InvocationTargetException {
if(obj instanceof com.jogamp.newt.Window) {
- win = (com.jogamp.newt.Window) obj;
- } else if(obj instanceof Component) {
- comp = (Component) obj;
+ return getCenterLocationNEWT((com.jogamp.newt.Window)obj, onTitleBarIfWindow);
+ } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) {
+ return getCenterLocationAWT((java.awt.Component)obj, onTitleBarIfWindow);
} else {
throw new RuntimeException("Neither AWT nor NEWT: "+obj);
}
+ }
+ private static int[] getCenterLocationNEWT(final com.jogamp.newt.Window win, final boolean onTitleBarIfWindow)
+ throws InterruptedException, InvocationTargetException {
+ final javax.media.nativewindow.util.Point p0 = win.getLocationOnScreen(null);
+ if( onTitleBarIfWindow ) {
+ final javax.media.nativewindow.util.InsetsImmutable insets = win.getInsets();
+ p0.translate(win.getWidth()/2, insets.getTopHeight()/2);
+ } else {
+ p0.translate(win.getWidth()/2, win.getHeight()/2);
+ }
+ return new int[] { p0.getX(), p0.getY() };
+ }
+ private static int[] getCenterLocationAWT(final java.awt.Component comp, final boolean onTitleBarIfWindow)
+ throws InterruptedException, InvocationTargetException {
int x0, y0;
- if(null!=comp) {
- java.awt.Point p0 = comp.getLocationOnScreen();
- java.awt.Rectangle r0 = comp.getBounds();
- if( onTitleBarIfWindow && comp instanceof java.awt.Window) {
- java.awt.Window window = (java.awt.Window) comp;
- java.awt.Insets insets = window.getInsets();
- y0 = (int) ( p0.getY() + insets.top / 2.0 + .5 ) ;
- } else {
- y0 = (int) ( p0.getY() + r0.getHeight() / 2.0 + .5 ) ;
- }
- x0 = (int) ( p0.getX() + r0.getWidth() / 2.0 + .5 ) ;
+ final java.awt.Point p0 = comp.getLocationOnScreen();
+ final java.awt.Rectangle r0 = comp.getBounds();
+ if( onTitleBarIfWindow && comp instanceof java.awt.Window) {
+ final java.awt.Window window = (java.awt.Window) comp;
+ final java.awt.Insets insets = window.getInsets();
+ y0 = (int) ( p0.getY() + insets.top / 2.0 + .5 ) ;
} else {
- javax.media.nativewindow.util.Point p0 = win.getLocationOnScreen(null);
- if( onTitleBarIfWindow ) {
- javax.media.nativewindow.util.InsetsImmutable insets = win.getInsets();
- p0.translate(win.getWidth()/2, insets.getTopHeight()/2);
- } else {
- p0.translate(win.getWidth()/2, win.getHeight()/2);
- }
- x0 = p0.getX();
- y0 = p0.getY();
+ y0 = (int) ( p0.getY() + r0.getHeight() / 2.0 + .5 ) ;
+ }
+ x0 = (int) ( p0.getX() + r0.getWidth() / 2.0 + .5 ) ;
+ return new int[] { x0, y0 };
+ }
+
+ public static int[] getClientLocation(final Object obj, final int x, final int y)
+ throws InterruptedException, InvocationTargetException {
+ if(obj instanceof com.jogamp.newt.Window) {
+ return getClientLocationNEWT((com.jogamp.newt.Window)obj, x, y);
+ } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) {
+ return getClientLocationAWT((java.awt.Component)obj, x, y);
+ } else {
+ throw new RuntimeException("Neither AWT nor NEWT: "+obj);
}
+ }
+ private static int[] getClientLocationNEWT(final com.jogamp.newt.Window win, final int x, final int y)
+ throws InterruptedException, InvocationTargetException {
+ final javax.media.nativewindow.util.Point p0 = win.getLocationOnScreen(null);
+ return new int[] { p0.getX(), p0.getY() };
+ }
+ private static int[] getClientLocationAWT(final java.awt.Component comp, final int x, final int y)
+ throws InterruptedException, InvocationTargetException {
+ final java.awt.Point p0 = comp.getLocationOnScreen();
+ return new int[] { (int)p0.getX(), (int)p0.getY() };
+ }
- return new java.awt.Point(x0, y0);
+ public static void awtRobotMouseMove(final Robot robot, final int x, final int y) {
+ robot.mouseMove( x, y );
+ robot.delay(ROBOT_DELAY);
}
/**
@@ -119,17 +197,16 @@ public class AWTRobotUtil {
throws AWTException, InterruptedException, InvocationTargetException {
// just for event tracing ..
- AWTWindowFocusAdapter winFA = new AWTWindowFocusAdapter("window");
+ final AWTWindowFocusAdapter winFA = new AWTWindowFocusAdapter("window");
window.addWindowFocusListener(winFA);
-
+
if(null == robot) {
robot = new Robot();
robot.setAutoWaitForIdle(true);
}
- java.awt.Point p0 = getCenterLocation(window, false);
- System.err.println("toFront: robot pos: "+p0);
- robot.mouseMove( (int) p0.getX(), (int) p0.getY() );
- robot.delay(ROBOT_DELAY);
+ final int[] p0 = getCenterLocation(window, false);
+ System.err.println("toFront: robot pos: "+p0[0]+"/"+p0[1]);
+ awtRobotMouseMove(robot, p0[0], p0[1] );
int wait=0;
do {
@@ -146,7 +223,7 @@ public class AWTRobotUtil {
wait++;
} while (wait<POLL_DIVIDER && !window.hasFocus());
final boolean success = wait<POLL_DIVIDER;
-
+
window.removeWindowFocusListener(winFA);
if(!success) {
System.err.println("*** AWTRobotUtil.toFrontAndRequestFocus() UI failure");
@@ -161,7 +238,7 @@ public class AWTRobotUtil {
* centerMouse
* @param onTitleBarIfWindow TODO
*/
- public static void centerMouse(Robot robot, Object obj, boolean onTitleBarIfWindow)
+ public static void centerMouse(Robot robot, final Object obj, final boolean onTitleBarIfWindow)
throws AWTException, InterruptedException, InvocationTargetException {
if(null == robot) {
@@ -169,80 +246,114 @@ public class AWTRobotUtil {
robot.setAutoWaitForIdle(true);
}
- java.awt.Point p0 = getCenterLocation(obj, onTitleBarIfWindow);
- System.err.println("centerMouse: robot pos: "+p0+", onTitleBarIfWindow: "+onTitleBarIfWindow);
+ final int[] p0 = getCenterLocation(obj, onTitleBarIfWindow);
+ System.err.println("centerMouse: robot pos: "+p0[0]+"x"+p0[1]+", onTitleBarIfWindow: "+onTitleBarIfWindow);
+ awtRobotMouseMove(robot, p0[0], p0[1] );
+ }
- robot.mouseMove( (int) p0.getX(), (int) p0.getY() );
- robot.delay(ROBOT_DELAY);
+ public static void setMouseToClientLocation(Robot robot, final Object obj, final int x, final int y)
+ throws AWTException, InterruptedException, InvocationTargetException {
+
+ if(null == robot) {
+ robot = new Robot();
+ robot.setAutoWaitForIdle(true);
+ }
+
+ final int[] p0 = getClientLocation(obj, x, y);
+ awtRobotMouseMove(robot, p0[0], p0[1] );
}
- public static int getClickTimeout(Object obj) {
+ public static int getClickTimeout(final Object obj) {
if(obj instanceof com.jogamp.newt.Window) {
return com.jogamp.newt.event.MouseEvent.getClickTimeout();
- } else if(obj instanceof Component) {
+ } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) {
if(null == AWT_CLICK_TO) {
AWT_CLICK_TO =
- (Integer) Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
- if(null == AWT_CLICK_TO) {
+ (Integer) java.awt.Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
+ if(null == AWT_CLICK_TO) {
AWT_CLICK_TO = new Integer(500);
}
}
return AWT_CLICK_TO.intValue();
} else {
throw new RuntimeException("Neither AWT nor NEWT: "+obj);
- }
+ }
}
-
+
/**
* requestFocus, if robot is valid, use mouse operation,
- * otherwise programatic, ie call requestFocus
+ * otherwise programmatic, ie call requestFocus
*/
- public static void requestFocus(Robot robot, Object obj)
+ public static void requestFocus(final Robot robot, final Object obj)
throws AWTException, InterruptedException, InvocationTargetException {
- final Component comp;
- final com.jogamp.newt.Window win;
+ requestFocus(robot, obj, true);
+ }
- if(obj instanceof com.jogamp.newt.Window) {
- win = (com.jogamp.newt.Window) obj;
- comp = null;
- } else if(obj instanceof Component) {
- win = null;
- comp = (Component) obj;
- } else {
- throw new RuntimeException("Neither AWT nor NEWT: "+obj);
- }
-
- if(null == robot) {
- if(null!=comp) {
- javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
- public void run() {
- comp.requestFocus();
- System.err.println("requestFocus: AWT Component");
- }});
- } else {
- win.requestFocus();
- System.err.println("requestFocus: NEWT Component");
- }
- } else {
- final int mouseButton = java.awt.event.InputEvent.BUTTON1_MASK;
- centerMouse(robot, obj, true);
-
- robot.waitForIdle();
+ /**
+ * requestFocus, if robot is valid, use mouse operation,
+ * otherwise programmatic, ie call requestFocus
+ */
+ public static void requestFocus(final Robot robot, final Object obj, final boolean onTitleBarIfWindow)
+ throws AWTException, InterruptedException, InvocationTargetException {
+ if(null != robot) {
+ final int mouseButton = java.awt.event.InputEvent.BUTTON1_MASK;
+ centerMouse(robot, obj, onTitleBarIfWindow);
+
+ waitForIdle(robot);
robot.mousePress(mouseButton);
robot.mouseRelease(mouseButton);
final int d = getClickTimeout(obj) + 1;
- robot.delay( d );
+ robot.delay( d );
System.err.println("requestFocus: click, d: "+d+" ms");
+ } else {
+ if(obj instanceof com.jogamp.newt.Window) {
+ requestFocusNEWT((com.jogamp.newt.Window) obj, onTitleBarIfWindow);
+ } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) {
+ requestFocusAWT((java.awt.Component) obj, onTitleBarIfWindow);
+ } else {
+ throw new RuntimeException("Neither AWT nor NEWT: "+obj);
+ }
+ }
+ }
+ private static void requestFocusNEWT(final com.jogamp.newt.Window win, final boolean onTitleBarIfWindow)
+ throws AWTException, InterruptedException, InvocationTargetException {
+ win.requestFocus();
+ System.err.println("requestFocus: NEWT Component");
+ }
+ private static void requestFocusAWT(final java.awt.Component comp, final boolean onTitleBarIfWindow)
+ throws AWTException, InterruptedException, InvocationTargetException {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ comp.requestFocus();
+ System.err.println("requestFocus: AWT Component");
+ }});
+ }
+
+ public static void requestFocus(final Robot robot, final Object obj, final int x, final int y)
+ throws AWTException, InterruptedException, InvocationTargetException {
+ validateAWTEDTIsAlive();
+
+ final boolean idling = robot.isAutoWaitForIdle();
+ final int mouseButton = java.awt.event.InputEvent.BUTTON1_MASK;
+ robot.mouseMove( x, y );
+ if( idling ) {
+ robot.waitForIdle();
+ } else {
+ try { Thread.sleep(50); } catch (final InterruptedException e) { }
}
+ robot.mousePress(mouseButton);
+ robot.mouseRelease(mouseButton);
+ final int d = getClickTimeout(obj) + 1;
+ robot.delay( d );
}
- public static boolean hasFocus(Object obj) {
- if(obj instanceof Component) {
- final Component comp = (Component) obj;
- final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
- return comp == kfm.getPermanentFocusOwner();
- } else if(obj instanceof com.jogamp.newt.Window) {
+ public static boolean hasFocus(final Object obj) {
+ if(obj instanceof com.jogamp.newt.Window) {
return ((com.jogamp.newt.Window) obj).hasFocus();
+ } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) {
+ final java.awt.Component comp = (java.awt.Component) obj;
+ final java.awt.KeyboardFocusManager kfm = java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ return comp == kfm.getPermanentFocusOwner();
} else {
throw new RuntimeException("Neither AWT nor NEWT: "+obj);
}
@@ -252,19 +363,19 @@ public class AWTRobotUtil {
*
* @return True if the Window became the global focused Window within TIME_OUT
*/
- public static boolean waitForFocus(Object obj) throws InterruptedException {
+ public static boolean waitForFocus(final Object obj) throws InterruptedException {
int wait;
- if(obj instanceof Component) {
- final Component comp = (Component) obj;
- final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
- for (wait=0; wait<POLL_DIVIDER && comp != kfm.getPermanentFocusOwner(); wait++) {
- Thread.sleep(TIME_SLICE);
- }
- } else if(obj instanceof com.jogamp.newt.Window) {
+ if(obj instanceof com.jogamp.newt.Window) {
final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
for (wait=0; wait<POLL_DIVIDER && !win.hasFocus(); wait++) {
Thread.sleep(TIME_SLICE);
}
+ } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) {
+ final java.awt.Component comp = (java.awt.Component) obj;
+ final java.awt.KeyboardFocusManager kfm = java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ for (wait=0; wait<POLL_DIVIDER && comp != kfm.getPermanentFocusOwner(); wait++) {
+ Thread.sleep(TIME_SLICE);
+ }
} else {
throw new RuntimeException("Neither AWT nor NEWT: "+obj);
}
@@ -275,8 +386,8 @@ public class AWTRobotUtil {
*
* @return True if the Window became the global focused Window within TIME_OUT
*/
- public static boolean waitForFocus(FocusEventCountAdapter gain,
- FocusEventCountAdapter lost) throws InterruptedException {
+ public static boolean waitForFocus(final FocusEventCountAdapter gain,
+ final FocusEventCountAdapter lost) throws InterruptedException {
int wait;
for (wait=0; wait<POLL_DIVIDER; wait++) {
if( ( null == lost || lost.focusLost() ) && ( null == gain || gain.focusGained() ) ) {
@@ -286,92 +397,161 @@ public class AWTRobotUtil {
}
return false;
}
-
+
/**
*
* @return True if the Window became the global focused Window within TIME_OUT
*/
- public static boolean waitForFocus(Object obj, FocusEventCountAdapter gain,
- FocusEventCountAdapter lost) throws InterruptedException {
+ public static boolean waitForFocus(final Object obj, final FocusEventCountAdapter gain,
+ final FocusEventCountAdapter lost) throws InterruptedException {
if(!waitForFocus(obj)) {
return false;
}
return waitForFocus(gain, lost);
}
- public static void assertRequestFocusAndWait(Robot robot, Object requestFocus, Object waitForFocus,
- FocusEventCountAdapter gain, FocusEventCountAdapter lost)
+ public static void assertRequestFocusAndWait(final Robot robot, final Object requestFocus, final Object waitForFocus,
+ final FocusEventCountAdapter gain, final FocusEventCountAdapter lost)
throws AWTException, InterruptedException, InvocationTargetException {
int i = 0;
boolean hasFocus = false;
-
+
for(i=0; i < RETRY_NUMBER && !hasFocus; i++) {
requestFocus(robot, requestFocus);
hasFocus = waitForFocus(waitForFocus, gain, lost);
}
if(!hasFocus) {
System.err.print("*** AWTRobotUtil.assertRequestFocusAndWait() ");
- if(gain.focusGained() && !lost.focusLost()) {
- // be error tolerant here, some impl. may lack focus-lost events (OS X)
+ if( ( null == gain || gain.focusGained() ) && ( null == lost || !lost.focusLost() ) ) {
+ // be error tolerant here, some impl. may lack focus-lost events (OS X)
System.err.println("minor UI failure");
hasFocus = true;
} else {
System.err.println("major UI failure");
}
- if(requestFocus instanceof Component) {
- System.err.println("*** requestFocus.hasFocus() - AWT: "+((Component)requestFocus).hasFocus());
- } else if(requestFocus instanceof NativeWindow) {
+ if(requestFocus instanceof NativeWindow) {
System.err.println("*** requestFocus.hasFocus() - NW: "+((NativeWindow)requestFocus).hasFocus());
+ } else if(NativeWindowFactory.isAWTAvailable() && requestFocus instanceof java.awt.Component) {
+ System.err.println("*** requestFocus.hasFocus() - AWT: "+((java.awt.Component)requestFocus).hasFocus());
}
- if(waitForFocus instanceof Component) {
- System.err.println("*** waitForFocus.hasFocus() - AWT: "+((Component)waitForFocus).hasFocus());
- } else if(waitForFocus instanceof NativeWindow) {
+ if(waitForFocus instanceof NativeWindow) {
System.err.println("*** waitForFocus.hasFocus() - NW: "+((NativeWindow)waitForFocus).hasFocus());
+ } else if(NativeWindowFactory.isAWTAvailable() && waitForFocus instanceof java.awt.Component) {
+ System.err.println("*** waitForFocus.hasFocus() - AWT: "+((java.awt.Component)waitForFocus).hasFocus());
}
System.err.println("*** gain: "+gain);
System.err.println("*** lost: "+lost);
- Thread.dumpStack();
+ Thread.dumpStack();
}
Assert.assertTrue("Did not gain focus", hasFocus);
}
- public static int keyType(int i, Robot robot, int keyCode,
- Object obj, InputEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException
+ private static void awtRobotKeyPress(final Robot robot, final int keyCode, final int msDelay) {
+ robot.keyPress(keyCode);
+ robot.delay(msDelay);
+ }
+ private static void awtRobotKeyRelease(final Robot robot, final int keyCode, final int msDelay) {
+ robot.keyRelease(keyCode);
+ robot.delay(msDelay);
+ }
+
+ public static int keyType(final int i, final Robot robot, final int keyCode,
+ final Object obj, final KeyEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException
{
int tc = 0;
int j;
final long t0 = System.currentTimeMillis();
-
+ final int c0 = null!=counter ? counter.getCount() : 0;
+
for(j=0; 1 > tc && j<RETRY_NUMBER; j++) {
if(!hasFocus(obj)) {
// focus lost for some reason, regain it programmatic
- if(DEBUG) { System.err.println(i+":"+j+" KC1.0: "+counter+" - regain focus"); }
+ if(DEBUG) { System.err.println(i+":"+j+" KC1.0: "+counter+" - regain focus on thread "+Thread.currentThread().getName()); }
requestFocus(null, obj);
}
- final int c0 = null!=counter ? counter.getCount() : 0;
- if(DEBUG) { System.err.println(i+":"+j+" KC1.1: "+counter); }
- robot.waitForIdle();
- robot.keyPress(keyCode);
- robot.keyRelease(keyCode);
- if(DEBUG) { System.err.println(i+":"+j+" KC1.2: "+counter); }
+ waitForIdle(robot);
+ if(DEBUG) { System.err.println(i+":"+j+" KC1.1: "+counter+" on thread "+Thread.currentThread().getName()); }
+ awtRobotKeyPress(robot, keyCode, 50);
+ if(DEBUG) { System.err.println(i+":"+j+" KC1.2: "+counter+" on thread "+Thread.currentThread().getName()); }
+ awtRobotKeyRelease(robot, keyCode, 100);
+ waitForIdle(robot);
+ if(DEBUG) { System.err.println(i+":"+j+" KC1.3: "+counter); }
tc = ( null!=counter ? counter.getCount() : 1 ) - c0;
for (int wait=0; wait<POLL_DIVIDER && 1 > tc; wait++) {
+ if(DEBUG) { System.err.println(i+":"+j+" KC1.4."+wait+": "+counter+", sleep for "+TIME_OUT+"ms"); }
robot.delay(TIME_SLICE);
tc = counter.getCount() - c0;
}
- if(DEBUG) { System.err.println(i+":"+j+" KC1.X: tc "+tc+", "+counter); }
+ if(DEBUG) { System.err.println(i+":"+j+" KC1.X: tc "+tc+", "+counter+" on thread "+Thread.currentThread().getName()); }
+ }
+ Assert.assertEquals("Key ("+i+":"+j+") not typed one time on thread "+Thread.currentThread().getName(), 1, tc);
+ return (int) ( System.currentTimeMillis() - t0 ) ;
+ }
+
+ /** No validation is performed .. */
+ public static int keyPress(final int i, final Robot robot, final boolean press, final int keyCode, final int msDelay) {
+ final long t0 = System.currentTimeMillis();
+ if(press) {
+ awtRobotKeyPress(robot, keyCode, msDelay);
+ } else {
+ awtRobotKeyRelease(robot, keyCode, msDelay);
+ }
+
+ return (int) ( System.currentTimeMillis() - t0 ) ;
+ }
+
+ /** No validation is performed .. */
+ public static int newtKeyPress(final int i, final Robot robot, final boolean press, final short newtKeyCode, final int msDelay) {
+ final int keyCode = AWTNewtEventFactory.newtKeyCode2AWTKeyCode(newtKeyCode);
+ final long t0 = System.currentTimeMillis();
+ if(press) {
+ awtRobotKeyPress(robot, keyCode, msDelay);
+ } else {
+ awtRobotKeyRelease(robot, keyCode, msDelay);
}
- Assert.assertEquals("Key ("+i+":"+j+") not typed one time", 1, tc);
+
return (int) ( System.currentTimeMillis() - t0 ) ;
}
-
+
+ /**
+ * @param keyCode TODO
+ * @param counter shall return the number of keys typed (press + release)
+ */
+ public static void assertKeyType(Robot robot, final int keyCode, final int typeCount,
+ final Object obj, final KeyEventCountAdapter counter)
+ throws AWTException, InterruptedException, InvocationTargetException {
+
+ if(null == robot) {
+ robot = new Robot();
+ robot.setAutoWaitForIdle(true);
+ }
+
+ centerMouse(robot, obj, false);
+
+ Assert.assertEquals("Key already pressed", false, counter.isPressed());
+
+ if(DEBUG) {
+ System.err.println("**************************************");
+ System.err.println("KC0: "+counter);
+ }
+
+ final int c0 = counter.getCount();
+
+ for(int i=0; i<typeCount; i++) {
+ keyType(i, robot, keyCode, obj, counter);
+ }
+
+ if(DEBUG) { System.err.println("KC3.0: "+counter); }
+ Assert.assertEquals("Wrong key count", typeCount, counter.getCount()-c0);
+ }
+
/**
* @param keyCode TODO
* @param counter shall return the number of keys typed (press + release)
*/
- public static void assertKeyType(Robot robot, int keyCode, int typeCount,
- Object obj, InputEventCountAdapter counter)
+ public static void assertKeyPress(Robot robot, final int keyCode, final int typeCount,
+ final Object obj, final KeyEventCountAdapter counter)
throws AWTException, InterruptedException, InvocationTargetException {
if(null == robot) {
@@ -382,29 +562,29 @@ public class AWTRobotUtil {
centerMouse(robot, obj, false);
Assert.assertEquals("Key already pressed", false, counter.isPressed());
-
+
if(DEBUG) {
System.err.println("**************************************");
System.err.println("KC0: "+counter);
}
-
+
final int c0 = counter.getCount();
for(int i=0; i<typeCount; i++) {
- keyType(i, robot, keyCode, obj, counter);
+ keyType(i, robot, keyCode, obj, counter);
}
if(DEBUG) { System.err.println("KC3.0: "+counter); }
Assert.assertEquals("Wrong key count", typeCount, counter.getCount()-c0);
}
- static int mouseClick(int i, Robot robot, int mouseButton,
- Object obj, InputEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException
+ static int mouseClick(final int i, final Robot robot, final int mouseButton,
+ final Object obj, final InputEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException
{
int j;
int tc = 0;
final long t0 = System.currentTimeMillis();
-
+
for(j=0; 1 > tc && j<RETRY_NUMBER; j++) {
if(!hasFocus(obj)) {
// focus lost for some reason, regain it programmatic
@@ -413,7 +593,7 @@ public class AWTRobotUtil {
}
final int c0 = null != counter ? counter.getCount() : 0;
if(DEBUG) { System.err.println(i+":"+j+" MC1.1: "+counter); }
- robot.waitForIdle();
+ waitForIdle(robot);
robot.mousePress(mouseButton);
robot.mouseRelease(mouseButton);
if(DEBUG) { System.err.println(i+":"+j+" MC1.2: "+counter); }
@@ -427,13 +607,13 @@ public class AWTRobotUtil {
Assert.assertEquals("Mouse ("+i+":"+j+") not clicked one time", 1, tc);
return (int) ( System.currentTimeMillis() - t0 ) ;
}
-
+
/**
* @param mouseButton ie InputEvent.BUTTON1_MASK
* @param clickCount ie 1, or 2
*/
- public static void assertMouseClick(Robot robot, int mouseButton, int clickCount,
- Object obj, InputEventCountAdapter counter)
+ public static void assertMouseClick(Robot robot, final int mouseButton, final int clickCount,
+ final Object obj, final InputEventCountAdapter counter)
throws AWTException, InterruptedException, InvocationTargetException {
if(null == robot) {
@@ -446,14 +626,14 @@ public class AWTRobotUtil {
centerMouse(robot, obj, false);
Assert.assertEquals("Mouse already pressed", false, counter.isPressed());
-
+
if(DEBUG) {
System.err.println("**************************************");
System.err.println("MC0: "+counter);
}
-
+
final int c0 = counter.getCount();
-
+
for(int i=0; i<clickCount; i++) {
final int waited = mouseClick(i, robot, mouseButton, obj, counter);
if(DEBUG) { System.err.println(i+": MC2.X: "+counter+", consumed: "+waited); }
@@ -468,16 +648,16 @@ public class AWTRobotUtil {
*
* @return True if the Component becomes <code>visible</code> within TIME_OUT
*/
- public static boolean waitForVisible(Object obj, boolean visible) throws InterruptedException {
+ public static boolean waitForVisible(final Object obj, final boolean visible) throws InterruptedException {
int wait;
- if(obj instanceof Component) {
- Component comp = (Component) obj;
- for (wait=0; wait<POLL_DIVIDER && visible != comp.isVisible(); wait++) {
+ if(obj instanceof com.jogamp.newt.Window) {
+ final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
+ for (wait=0; wait<POLL_DIVIDER && visible != win.isVisible(); wait++) {
Thread.sleep(TIME_SLICE);
}
- } else if(obj instanceof com.jogamp.newt.Window) {
- com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
- for (wait=0; wait<POLL_DIVIDER && visible != win.isVisible(); wait++) {
+ } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) {
+ final java.awt.Component comp = (java.awt.Component) obj;
+ for (wait=0; wait<POLL_DIVIDER && visible != comp.isShowing(); wait++) {
Thread.sleep(TIME_SLICE);
}
} else {
@@ -488,53 +668,131 @@ public class AWTRobotUtil {
/**
*
- * @return True if the GLDrawable recives the expected size within TIME_OUT
+ * @return True if the GLDrawable receives the expected size within TIME_OUT
*/
- public static boolean waitForSize(GLDrawable drawable, int width, int height) throws InterruptedException {
+ public static boolean waitForSize(final GLDrawable drawable, final int width, final int height) throws InterruptedException {
int wait;
- for (wait=0; wait<POLL_DIVIDER && ( width != drawable.getWidth() || height != drawable.getHeight() ) ; wait++) {
+ for (wait=0; wait<POLL_DIVIDER && ( width != drawable.getSurfaceWidth() || height != drawable.getSurfaceHeight() ) ; wait++) {
Thread.sleep(TIME_SLICE);
}
return wait<POLL_DIVIDER;
}
/**
- *
+ * @param obj the component to wait for
+ * @param realized true if waiting for component to become realized, otherwise false
* @return True if the Component becomes realized (not displayable, native invalid) within TIME_OUT
+ * @throws InterruptedException
*/
- public static boolean waitForRealized(Object obj, boolean realized) throws InterruptedException {
- int wait;
- if (obj instanceof Component) {
- Component comp = (Component) obj;
- for (wait=0; wait<POLL_DIVIDER && realized != comp.isDisplayable(); wait++) {
- Thread.sleep(TIME_SLICE);
+ public static boolean waitForRealized(final Object obj, final boolean realized) throws InterruptedException {
+ return waitForRealized(obj, null, realized);
+ }
+
+ /**
+ * @param obj the component to wait for
+ * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate
+ * @param realized true if waiting for component to become realized, otherwise false
+ * @return True if the Component becomes realized (not displayable, native invalid) within TIME_OUT
+ * @throws InterruptedException
+ */
+ public static boolean waitForRealized(final Object obj, final Runnable waitAction, final boolean realized) throws InterruptedException {
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ if(obj instanceof com.jogamp.newt.Screen) {
+ final com.jogamp.newt.Screen screen = (com.jogamp.newt.Screen) obj;
+ while( (t1-t0) < TIME_OUT && realized != screen.isNativeValid() ) {
+ if( null != waitAction ) {
+ waitAction.run();
+ } else {
+ Thread.sleep(TIME_SLICE);
+ }
+ t1 = System.currentTimeMillis();
}
- // if GLCanvas, ensure it got also painted -> drawable.setRealized(true);
- if(wait<POLL_DIVIDER && comp instanceof GLCanvas) {
- GLCanvas glcanvas = (GLCanvas) comp;
- for (wait=0; wait<POLL_DIVIDER && realized != glcanvas.isRealized(); wait++) {
+ } else if(obj instanceof com.jogamp.newt.Window) {
+ final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
+ while( (t1-t0) < TIME_OUT && realized != win.isNativeValid() ) {
+ if( null != waitAction ) {
+ waitAction.run();
+ } else {
Thread.sleep(TIME_SLICE);
}
- if(wait>=POLL_DIVIDER) {
- // for some reason GLCanvas hasn't been painted yet, force it!
- System.err.println("XXX: FORCE REPAINT PRE - canvas: "+glcanvas);
- glcanvas.repaint();
- for (wait=0; wait<POLL_DIVIDER && realized != glcanvas.isRealized(); wait++) {
+ t1 = System.currentTimeMillis();
+ }
+ } else if (NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) {
+ final java.awt.Component comp = (java.awt.Component) obj;
+ while( (t1-t0) < TIME_OUT && realized != comp.isShowing() ) {
+ if( null != waitAction ) {
+ waitAction.run();
+ } else {
+ Thread.sleep(TIME_SLICE);
+ }
+ t1 = System.currentTimeMillis();
+ }
+ // if GLCanvas, ensure it got also painted -> drawable.setRealized(true);
+ if( (t1-t0) < TIME_OUT && comp instanceof GLAutoDrawable) {
+ final GLAutoDrawable glad = (GLAutoDrawable) comp;
+ t0 = System.currentTimeMillis();
+ while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) {
+ if( null != waitAction ) {
+ waitAction.run();
+ } else {
Thread.sleep(TIME_SLICE);
}
- System.err.println("XXX: FORCE REPAINT POST - canvas: "+glcanvas);
+ t1 = System.currentTimeMillis();
+ }
+ if( (t1-t0) >= TIME_OUT ) {
+ // for some reason GLCanvas hasn't been painted yet, force it!
+ System.err.println("XXX: FORCE REPAINT PRE - glad: "+glad);
+ comp.repaint();
+ t0 = System.currentTimeMillis();
+ while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) {
+ if( null != waitAction ) {
+ waitAction.run();
+ } else {
+ Thread.sleep(TIME_SLICE);
+ }
+ t1 = System.currentTimeMillis();
+ }
+ System.err.println("XXX: FORCE REPAINT POST - glad: "+glad);
}
- for (wait=0; wait<POLL_DIVIDER && realized != glcanvas.isRealized(); wait++) {
+ }
+ } else if(obj instanceof GLAutoDrawable) {
+ final GLAutoDrawable glad = (GLAutoDrawable) obj;
+ while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) {
+ if( null != waitAction ) {
+ waitAction.run();
+ } else {
Thread.sleep(TIME_SLICE);
}
- }
- } else if(obj instanceof com.jogamp.newt.Window) {
- com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
- for (wait=0; wait<POLL_DIVIDER && realized != win.isNativeValid(); wait++) {
- Thread.sleep(TIME_SLICE);
+ t1 = System.currentTimeMillis();
}
} else {
- throw new RuntimeException("Neither AWT nor NEWT: "+obj);
+ throw new RuntimeException("Neither AWT nor NEWT nor GLAutoDrawable: "+obj);
+ }
+ return (t1-t0) < TIME_OUT;
+ }
+
+ /**
+ *
+ * @return True if the GLContext becomes created or not within TIME_OUT
+ */
+ public static boolean waitForContextCreated(final GLAutoDrawable autoDrawable, final boolean created) throws InterruptedException {
+ if( null == autoDrawable ) {
+ return !created;
+ }
+ int wait;
+ for (wait=0; wait<POLL_DIVIDER ; wait++) {
+ final GLContext ctx = autoDrawable.getContext();
+ if( created ) {
+ if( null != ctx && ctx.isCreated() ) {
+ break;
+ }
+ } else {
+ if( null == ctx || !ctx.isCreated() ) {
+ break;
+ }
+ }
+ Thread.sleep(TIME_SLICE);
}
return wait<POLL_DIVIDER;
}
@@ -545,21 +803,24 @@ public class AWTRobotUtil {
*
* @param obj either an AWT Window (Frame, JFrame) or NEWT Window
* @param willClose indicating that the window will close, hence this method waits for the window to be closed
+ * @param wcl the WindowClosingListener to determine whether the AWT or NEWT widget has been closed. It should be attached
+ * to the widget ASAP before any other listener, e.g. via {@link #addClosingListener(Object)}.
+ * The WindowClosingListener will be reset before attempting to close the widget.
* @return True if the Window is closing and closed (if willClose is true), each within TIME_OUT
* @throws InterruptedException
*/
- public static boolean closeWindow(Object obj, boolean willClose) throws InterruptedException, InvocationTargetException {
- WindowClosingListener closingListener = addClosingListener(obj);
+ public static boolean closeWindow(final Object obj, final boolean willClose, final WindowClosingListener closingListener) throws InterruptedException {
+ closingListener.reset();
if(obj instanceof java.awt.Window) {
final java.awt.Window win = (java.awt.Window) obj;
- Toolkit tk = Toolkit.getDefaultToolkit();
- final EventQueue evtQ = tk.getSystemEventQueue();
- EventQueue.invokeAndWait(new Runnable() {
+ final java.awt.Toolkit tk = java.awt.Toolkit.getDefaultToolkit();
+ final java.awt.EventQueue evtQ = tk.getSystemEventQueue();
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
public void run() {
evtQ.postEvent(new java.awt.event.WindowEvent(win, java.awt.event.WindowEvent.WINDOW_CLOSING));
} });
} else if(obj instanceof com.jogamp.newt.Window) {
- com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
+ final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
WindowImplAccess.windowDestroyNotify(win);
}
int wait;
@@ -574,16 +835,19 @@ public class AWTRobotUtil {
return wait<POLL_DIVIDER;
}
- public static WindowClosingListener addClosingListener(Object obj) throws InterruptedException {
+ public static WindowClosingListener addClosingListener(final Object obj) {
WindowClosingListener cl = null;
if(obj instanceof java.awt.Window) {
- java.awt.Window win = (java.awt.Window) obj;
- AWTWindowClosingAdapter acl = new AWTWindowClosingAdapter();
- win.addWindowListener(acl);
+ final java.awt.Window win = (java.awt.Window) obj;
+ final AWTWindowClosingAdapter acl = new AWTWindowClosingAdapter();
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ win.addWindowListener(acl);
+ } } );
cl = acl;
} else if(obj instanceof com.jogamp.newt.Window) {
- com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
- NEWTWindowClosingAdapter ncl = new NEWTWindowClosingAdapter();
+ final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
+ final NEWTWindowClosingAdapter ncl = new NEWTWindowClosingAdapter();
win.addWindowListener(ncl);
cl = ncl;
} else {
@@ -593,53 +857,77 @@ public class AWTRobotUtil {
}
public static interface WindowClosingListener {
void reset();
+ public int getWindowClosingCount();
+ public int getWindowClosedCount();
public boolean isWindowClosing();
public boolean isWindowClosed();
}
static class AWTWindowClosingAdapter
extends java.awt.event.WindowAdapter implements WindowClosingListener
{
- volatile boolean closing = false;
- volatile boolean closed = false;
+ AtomicInteger closing = new AtomicInteger(0);
+ AtomicInteger closed = new AtomicInteger(0);
public void reset() {
- closing = false;
- closed = false;
+ closing.set(0);
+ closed.set(0);
+ }
+ public int getWindowClosingCount() {
+ return closing.get();
+ }
+ public int getWindowClosedCount() {
+ return closed.get();
}
public boolean isWindowClosing() {
- return closing;
+ return 0 < closing.get();
}
public boolean isWindowClosed() {
- return closed;
+ return 0 < closed.get();
+ }
+ public void windowClosing(final java.awt.event.WindowEvent e) {
+ closing.incrementAndGet();
+ System.err.println("AWTWindowClosingAdapter.windowClosing: "+this);
}
- public void windowClosing(java.awt.event.WindowEvent e) {
- closing = true;
+ public void windowClosed(final java.awt.event.WindowEvent e) {
+ closed.incrementAndGet();
+ System.err.println("AWTWindowClosingAdapter.windowClosed: "+this);
}
- public void windowClosed(java.awt.event.WindowEvent e) {
- closed = true;
+ public String toString() {
+ return "AWTWindowClosingAdapter[closing "+closing+", closed "+closed+"]";
}
}
static class NEWTWindowClosingAdapter
extends com.jogamp.newt.event.WindowAdapter implements WindowClosingListener
{
- volatile boolean closing = false;
- volatile boolean closed = false;
+ AtomicInteger closing = new AtomicInteger(0);
+ AtomicInteger closed = new AtomicInteger(0);
public void reset() {
- closing = false;
- closed = false;
+ closing.set(0);
+ closed.set(0);
+ }
+ public int getWindowClosingCount() {
+ return closing.get();
+ }
+ public int getWindowClosedCount() {
+ return closed.get();
}
public boolean isWindowClosing() {
- return closing;
+ return 0 < closing.get();
}
public boolean isWindowClosed() {
- return closed;
+ return 0 < closed.get();
+ }
+ public void windowDestroyNotify(final WindowEvent e) {
+ closing.incrementAndGet();
+ System.err.println("NEWTWindowClosingAdapter.windowDestroyNotify: "+this);
}
- public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent e) {
- closing = true;
+ public void windowDestroyed(final WindowEvent e) {
+ closed.incrementAndGet();
+ System.err.println("NEWTWindowClosingAdapter.windowDestroyed: "+this);
}
- public void windowDestroyed(com.jogamp.newt.event.WindowEvent e) {
- closed = true;
+ public String toString() {
+ return "NEWTWindowClosingAdapter[closing "+closing+", closed "+closed+"]";
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTWindowFocusAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTWindowFocusAdapter.java
index 16aacd2fd..e2cafb1de 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTWindowFocusAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTWindowFocusAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
import java.awt.event.WindowEvent;
@@ -35,37 +35,44 @@ public class AWTWindowFocusAdapter implements FocusEventCountAdapter, WindowFocu
String prefix;
int focusCount;
+ boolean verbose = true;
- public AWTWindowFocusAdapter(String prefix) {
+ public AWTWindowFocusAdapter(final String prefix) {
this.prefix = prefix;
reset();
}
+ public void setVerbose(final boolean v) { verbose = false; }
+
public boolean focusLost() {
- return focusCount<0;
+ return focusCount<0;
}
-
+
public boolean focusGained() {
return focusCount>0;
}
-
+
public void reset() {
focusCount = 0;
}
/* @Override */
- public void windowGainedFocus(WindowEvent e) {
+ public void windowGainedFocus(final WindowEvent e) {
if(focusCount<0) { focusCount=0; }
focusCount++;
- System.err.println("FOCUS AWT GAINED (Window) [fc "+focusCount+"]: "+prefix+", "+e);
+ if( verbose ) {
+ System.err.println("FOCUS AWT GAINED (Window) [fc "+focusCount+"]: "+prefix+", "+e);
+ }
}
/* @Override */
- public void windowLostFocus(WindowEvent e) {
+ public void windowLostFocus(final WindowEvent e) {
if(focusCount>0) { focusCount=0; }
focusCount--;
- System.err.println("FOCUS AWT LOST (Window) [fc "+focusCount+"]: "+prefix+", "+e);
+ if( verbose ) {
+ System.err.println("FOCUS AWT LOST (Window) [fc "+focusCount+"]: "+prefix+", "+e);
+ }
}
-
+
public String toString() { return prefix+"[focusCount "+focusCount +"]"; }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/DumpGLInfo.java b/src/test/com/jogamp/opengl/test/junit/util/DumpGLInfo.java
index e49679dc3..ec8276dee 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/DumpGLInfo.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/DumpGLInfo.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
@@ -35,17 +35,17 @@ import com.jogamp.opengl.JoglVersion;
public class DumpGLInfo implements GLEventListener {
- public void init(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
- System.err.println(JoglVersion.getGLInfo(gl, null));
+ public void init(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println(JoglVersion.getGLInfo(gl, null, true));
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
}
- public void display(GLAutoDrawable drawable) {
+ public void display(final GLAutoDrawable drawable) {
}
- public void dispose(GLAutoDrawable drawable) {
+ public void dispose(final GLAutoDrawable drawable) {
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapter.java
index 76a1884c8..804a4eabe 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,15 +20,24 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
+/**
+ * Base event count adapter.
+ * <p>
+ * Instance starts in verbose mode.
+ * </p>
+ */
public interface EventCountAdapter {
void reset();
+
+ /** Instance starts in verbose mode, call w/ false to disable verbosity. */
+ void setVerbose(boolean v);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapterUtil.java b/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapterUtil.java
index d919d7cb6..b2db3e017 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapterUtil.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapterUtil.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
import java.util.List;
@@ -33,15 +33,15 @@ import java.util.Iterator;
public abstract class EventCountAdapterUtil {
- public static void reset(EventCountAdapter[] adapters) {
+ public static void reset(final EventCountAdapter[] adapters) {
for(int i=0; i<adapters.length; i++) {
adapters[i].reset();
}
}
- public static void reset(List/*<EventCountAdapter>*/ adapters) {
- for(Iterator i = adapters.iterator(); i.hasNext(); ) {
- EventCountAdapter adapter = (EventCountAdapter) i.next();
+ public static void reset(final List/*<EventCountAdapter>*/ adapters) {
+ for(final Iterator i = adapters.iterator(); i.hasNext(); ) {
+ final EventCountAdapter adapter = (EventCountAdapter) i.next();
adapter.reset();
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/FocusEventCountAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/FocusEventCountAdapter.java
index 461c72683..54b14543d 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/FocusEventCountAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/FocusEventCountAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
public interface FocusEventCountAdapter extends EventCountAdapter {
diff --git a/src/test/com/jogamp/opengl/test/junit/util/GLEventListenerCounter.java b/src/test/com/jogamp/opengl/test/junit/util/GLEventListenerCounter.java
new file mode 100644
index 000000000..981c5c17c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/util/GLEventListenerCounter.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.util;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+
+public class GLEventListenerCounter implements GLEventListener {
+ public int initCount = 0;
+ public int displayCount = 0;
+ public int reshapeCount = 0;
+ public int disposeCount = 0;
+
+ public void reset() {
+ initCount = 0;
+ displayCount = 0;
+ reshapeCount = 0;
+ disposeCount = 0;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ initCount++;
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ disposeCount++;
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ displayCount++;
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable d, final int x, final int y, final int width, final int height) {
+ reshapeCount++;
+ }
+
+ public String toString() {
+ return "GLEventListenerCounter[init "+initCount+", dispose "+disposeCount+", reshape "+reshapeCount+", display "+displayCount+"]";
+ }
+} \ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/util/GLSLSimpleProgram.java b/src/test/com/jogamp/opengl/test/junit/util/GLSLSimpleProgram.java
index 989de6c7e..5c2b2c56f 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/GLSLSimpleProgram.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/GLSLSimpleProgram.java
@@ -41,25 +41,25 @@ public class GLSLSimpleProgram {
private int fragShader;
private boolean isValid;
- private GLSLSimpleProgram(int shaderProgram, int vertShader, int fragShader) {
+ private GLSLSimpleProgram(final int shaderProgram, final int vertShader, final int fragShader) {
this.shaderProgram = shaderProgram;
this.vertShader = vertShader;
this.fragShader = fragShader;
this.isValid = true;
}
- public static GLSLSimpleProgram create(GL2ES2 gl, String vertShaderCode, String fragShaderCode, boolean link) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream pbaos = new PrintStream(baos);
+ public static GLSLSimpleProgram create(final GL2ES2 gl, final String vertShaderCode, final String fragShaderCode, final boolean link) {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final PrintStream pbaos = new PrintStream(baos);
- int vertShader = gl.glCreateShader(GL2ES2.GL_VERTEX_SHADER);
+ final int vertShader = gl.glCreateShader(GL2ES2.GL_VERTEX_SHADER);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- int fragShader = gl.glCreateShader(GL2ES2.GL_FRAGMENT_SHADER);
+ final int fragShader = gl.glCreateShader(GL2ES2.GL_FRAGMENT_SHADER);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- String[] vlines = new String[] { vertShaderCode };
- int[] vlengths = new int[] { vlines[0].length() };
+ final String[] vlines = new String[] { gl.getContext().getGLSLVersionString()+vertShaderCode };
+ final int[] vlengths = new int[] { vlines[0].length() };
gl.glShaderSource(vertShader, vlines.length, vlines, vlengths, 0);
gl.glCompileShader(vertShader);
if(!ShaderUtil.isShaderStatusValid(gl, vertShader, GL2ES2.GL_COMPILE_STATUS, pbaos)) {
@@ -69,9 +69,9 @@ public class GLSLSimpleProgram {
pbaos.flush(); baos.reset();
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
-
- String[] flines = new String[] { fragShaderCode };
- int[] flengths = new int[] { flines[0].length() };
+
+ final String[] flines = new String[] { gl.getContext().getGLSLVersionString()+fragShaderCode };
+ final int[] flengths = new int[] { flines[0].length() };
gl.glShaderSource(fragShader, flines.length, flines, flengths, 0);
gl.glCompileShader(fragShader);
if(!ShaderUtil.isShaderStatusValid(gl, fragShader, GL2ES2.GL_COMPILE_STATUS, pbaos)) {
@@ -81,7 +81,7 @@ public class GLSLSimpleProgram {
pbaos.flush(); baos.reset();
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- int shaderProgram = gl.glCreateProgram();
+ final int shaderProgram = gl.glCreateProgram();
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
gl.glAttachShader(shaderProgram, vertShader);
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
@@ -96,11 +96,11 @@ public class GLSLSimpleProgram {
}
}
Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
- GLSLSimpleProgram res = new GLSLSimpleProgram(shaderProgram, vertShader, fragShader);
+ final GLSLSimpleProgram res = new GLSLSimpleProgram(shaderProgram, vertShader, fragShader);
return res;
}
- public void release(GL2ES2 gl) {
+ public void release(final GL2ES2 gl) {
gl.glUseProgram(0);
gl.glDetachShader(shaderProgram, vertShader);
gl.glDeleteShader(vertShader);
@@ -124,7 +124,7 @@ public class GLSLSimpleProgram {
public int getVertShader() {
return vertShader;
}
-
+
public boolean isValid() {
return isValid;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java
index 27f3d7e29..a32e995d9 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,16 +20,23 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
+import java.util.EventObject;
+import java.util.List;
+
public interface InputEventCountAdapter extends EventCountAdapter {
+ int getConsumedCount();
int getCount();
boolean isPressed();
+
+ public List<EventObject> copyQueue();
+ public int getQueueSize();
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java
new file mode 100644
index 000000000..aaafeacee
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.util;
+
+public interface KeyEventCountAdapter extends InputEventCountAdapter {
+ public int getKeyPressedCount(boolean autoRepeatOnly);
+
+ public int getKeyReleasedCount(boolean autoRepeatOnly);
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java
index 9cbeabb85..943a99dcf 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,52 +20,229 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
import java.lang.reflect.*;
+import java.nio.FloatBuffer;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.media.opengl.GLContext;
+
+import com.jogamp.common.os.Platform;
public class MiscUtils {
- public static int atoi(String str, int def) {
+ public static boolean atob(final String str, final boolean def) {
+ try {
+ return Boolean.parseBoolean(str);
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ }
+ return def;
+ }
+
+ public static int atoi(final String str, final int def) {
try {
return Integer.parseInt(str);
- } catch (Exception ex) {
+ } catch (final Exception ex) {
ex.printStackTrace();
}
return def;
}
-
- public static long atol(String str, long def) {
+
+ public static long atol(final String str, final long def) {
try {
return Long.parseLong(str);
- } catch (Exception ex) {
+ } catch (final Exception ex) {
ex.printStackTrace();
}
return def;
}
- public static boolean setFieldIfExists(Object instance, String fieldName, Object value) {
+ public static float atof(final String str, final float def) {
+ try {
+ return Float.parseFloat(str);
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ }
+ return def;
+ }
+
+ public static String toHexString(final byte hex) {
+ return "0x" + Integer.toHexString( hex & 0x000000FF );
+ }
+
+ public static String toHexString(final short hex) {
+ return "0x" + Integer.toHexString( hex & 0x0000FFFF );
+ }
+
+ public static String toHexString(final int hex) {
+ return "0x" + Integer.toHexString( hex );
+ }
+
+ public static String toHexString(final long hex) {
+ return "0x" + Long.toHexString( hex );
+ }
+
+ public static void assertFloatBufferEquals(final String errmsg, final FloatBuffer expected, final FloatBuffer actual, final float delta) {
+ if(null == expected && null == actual) {
+ return;
+ }
+ final String msg = null != errmsg ? errmsg + " " : "";
+ if(null == expected) {
+ throw new AssertionError(msg+"; Expected is null, but actual not: "+actual);
+ }
+ if(null == actual) {
+ throw new AssertionError(msg+"; Actual is null, but expected not: "+expected);
+ }
+ if(expected.remaining() != actual.remaining()) {
+ throw new AssertionError(msg+"; Expected has "+expected.remaining()+" remaining, but actual has "+actual.remaining());
+ }
+ final int a0 = expected.position();
+ final int b0 = actual.position();
+ for(int i=0; i<expected.remaining(); i++) {
+ final float ai = expected.get(a0 + i);
+ final float bi = actual.get(b0 + i);
+ final float daibi = Math.abs(ai - bi);
+ if( daibi > delta ) {
+ throw new AssertionError(msg+"; Expected @ ["+a0+"+"+i+"] has "+ai+", but actual @ ["+b0+"+"+i+"] has "+bi+", it's delta "+daibi+" > "+delta);
+ }
+ }
+ }
+
+ public static void assertFloatBufferNotEqual(final String errmsg, final FloatBuffer expected, final FloatBuffer actual, final float delta) {
+ if(null == expected || null == actual) {
+ return;
+ }
+ if(expected.remaining() != actual.remaining()) {
+ return;
+ }
+ final String msg = null != errmsg ? errmsg + " " : "";
+ final int a0 = expected.position();
+ final int b0 = actual.position();
+ for(int i=0; i<expected.remaining(); i++) {
+ final float ai = expected.get(a0 + i);
+ final float bi = actual.get(b0 + i);
+ final float daibi = Math.abs(ai - bi);
+ if( daibi > delta ) {
+ return;
+ }
+ }
+ throw new AssertionError(msg+"; Expected and actual are equal.");
+ }
+
+ public static boolean setFieldIfExists(final Object instance, final String fieldName, final Object value) {
try {
- Field f = instance.getClass().getField(fieldName);
+ final Field f = instance.getClass().getField(fieldName);
if(value instanceof Boolean || f.getType().isInstance(value)) {
f.set(instance, value);
return true;
} else {
System.out.println(instance.getClass()+" '"+fieldName+"' field not assignable with "+value.getClass()+", it's a: "+f.getType());
}
- } catch (IllegalAccessException ex) {
+ } catch (final IllegalAccessException ex) {
throw new RuntimeException(ex);
- } catch (NoSuchFieldException nsfe) {
+ } catch (final NoSuchFieldException nsfe) {
// OK - throw new RuntimeException(instance.getClass()+" has no '"+fieldName+"' field", nsfe);
}
return false;
}
+
+ public static class StreamDump extends Thread {
+ final InputStream is;
+ final StringBuilder outString;
+ final OutputStream outStream;
+ final String prefix;
+ final Object sync;
+ volatile boolean eos = false;
+
+ public StreamDump(final OutputStream out, final String prefix, final InputStream is, final Object sync) {
+ this.is = is;
+ this.outString = null;
+ this.outStream = out;
+ this.prefix = prefix;
+ this.sync = sync;
+ }
+ public StreamDump(final StringBuilder sb, final String prefix, final InputStream is, final Object sync) {
+ this.is = is;
+ this.outString = sb;
+ this.outStream = null;
+ this.prefix = prefix;
+ this.sync = sync;
+ }
+ public StreamDump(final StringBuilder sb, final InputStream is, final Object sync) {
+ this.is = is;
+ this.outString = sb;
+ this.outStream = null;
+ this.prefix = null;
+ this.sync = sync;
+ }
+
+ public final boolean eos() { return eos; }
+
+ @Override
+ public void run() {
+ synchronized ( sync ) {
+ try {
+ final BufferedReader in = new BufferedReader( new InputStreamReader(is) );
+ String line = null;
+ while ((line = in.readLine()) != null) {
+ if( null != outString ) {
+ outString.append(line).append(Platform.getNewline());
+ } else if( null != outStream ) {
+ if( null != prefix ) {
+ outStream.write(prefix.getBytes());
+ }
+ outStream.write(line.getBytes());
+ outStream.write(Platform.getNewline().getBytes());
+ outStream.flush();
+ }
+ }
+ } catch (final IOException ioe) {
+ System.err.println("Caught "+ioe.getClass().getName()+": "+ioe.getMessage());
+ ioe.printStackTrace();
+ } finally {
+ eos = true;
+ sync.notifyAll();
+ }
+ }
+ }
+ }
+
+ public static void dumpSharedGLContext(final String prefix, final GLContext self) {
+ int i = 0, j = 0;
+ final GLContext master = self.getSharedMaster();
+ final int masterHash = null != master ? master.hashCode() : 0;
+ System.err.println(prefix+": hash 0x"+Integer.toHexString(self.hashCode())+", \t(isShared "+self.isShared()+", created "+self.isCreated()+", master 0x"+Integer.toHexString(masterHash)+")");
+ {
+ final List<GLContext> set = self.getCreatedShares();
+ for (final Iterator<GLContext> iter = set.iterator(); iter.hasNext(); ) {
+ final GLContext c = iter.next();
+ System.err.println(" Created Ctx #"+(i++)+": hash 0x"+Integer.toHexString(c.hashCode())+", \t(created "+c.isCreated()+")");
+ }
+ }
+ {
+ final List<GLContext> set = self.getDestroyedShares();
+ for (final Iterator<GLContext> iter = set.iterator(); iter.hasNext(); ) {
+ final GLContext c = iter.next();
+ System.err.println(" Destroyed Ctx #"+(j++)+": hash 0x"+Integer.toHexString(c.hashCode())+", \t(created "+c.isCreated()+")");
+ }
+ }
+ System.err.println("\t Total created "+i+" + destroyed "+j+" = "+(i+j));
+ System.err.println();
+ }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTFocusAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTFocusAdapter.java
index 27d4abd9c..23e08179a 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/NEWTFocusAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTFocusAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
import com.jogamp.newt.event.WindowEvent;
@@ -36,42 +36,49 @@ public class NEWTFocusAdapter implements WindowListener, FocusEventCountAdapter
String prefix;
int focusCount;
+ boolean verbose = true;
- public NEWTFocusAdapter(String prefix) {
+ public NEWTFocusAdapter(final String prefix) {
this.prefix = prefix;
reset();
}
+ public void setVerbose(final boolean v) { verbose = false; }
+
public boolean focusLost() {
- return focusCount<0;
+ return focusCount<0;
}
-
+
public boolean focusGained() {
return focusCount>0;
}
-
+
public void reset() {
focusCount = 0;
}
- public void windowGainedFocus(WindowEvent e) {
+ public void windowGainedFocus(final WindowEvent e) {
if(focusCount<0) { focusCount=0; }
focusCount++;
- System.err.println("FOCUS NEWT GAINED [fc "+focusCount+"]: "+prefix+", "+e);
+ if( verbose ) {
+ System.err.println("FOCUS NEWT GAINED [fc "+focusCount+"]: "+prefix+", "+e);
+ }
}
- public void windowLostFocus(WindowEvent e) {
+ public void windowLostFocus(final WindowEvent e) {
if(focusCount>0) { focusCount=0; }
focusCount--;
- System.err.println("FOCUS NEWT LOST [fc "+focusCount+"]: "+prefix+", "+e);
+ if( verbose ) {
+ System.err.println("FOCUS NEWT LOST [fc "+focusCount+"]: "+prefix+", "+e);
+ }
}
- public void windowResized(WindowEvent e) { }
- public void windowMoved(WindowEvent e) { }
- public void windowDestroyNotify(WindowEvent e) { }
- public void windowDestroyed(WindowEvent e) { }
- public void windowRepaint(WindowUpdateEvent e) { }
-
- public String toString() { return prefix+"[focusCount "+focusCount+"]"; }
+ public void windowResized(final WindowEvent e) { }
+ public void windowMoved(final WindowEvent e) { }
+ public void windowDestroyNotify(final WindowEvent e) { }
+ public void windowDestroyed(final WindowEvent e) { }
+ public void windowRepaint(final WindowUpdateEvent e) { }
+
+ public String toString() { return prefix+"[focusCount "+focusCount+"]"; }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java
index a76b67d57..d897a51a1 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java
@@ -41,102 +41,64 @@ import org.junit.Assert;
public class NEWTGLContext {
- public static class WindowContext {
+ public static class WindowContext {
public final Window window;
public final GLDrawable drawable;
public final GLContext context;
-
- public WindowContext(Window w, GLDrawable d, GLContext c) {
+
+ public WindowContext(final Window w, final GLDrawable d, final GLContext c) {
window = w;
drawable = d;
context = c;
}
}
- public static WindowContext createOffscreenWindow(GLCapabilities caps, int width, int height, boolean debugGL) throws InterruptedException {
- caps.setOnscreen(false);
- caps.setPBuffer(true);
-
+ public static WindowContext createWindow(final GLCapabilities caps, final int width, final int height, final boolean debugGL) throws InterruptedException {
//
// Create native windowing resources .. X11/Win/OSX
- //
- Display display = NewtFactory.createDisplay(null); // local display
- Assert.assertNotNull(display);
-
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
- Assert.assertNotNull(screen);
-
- Window window = NewtFactory.createWindow(screen, caps);
- Assert.assertNotNull(window);
- window.setSize(width, height);
- window.setVisible(true);
- Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
-
- GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
- GLDrawable drawable = factory.createGLDrawable(window);
- Assert.assertNotNull(drawable);
-
- drawable.setRealized(true);
- Assert.assertTrue(drawable.isRealized());
-
- GLContext context = drawable.createContext(null);
- Assert.assertNotNull(context);
-
- context.enableGLDebugMessage(debugGL);
-
- int res = context.makeCurrent();
- Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
-
- return new WindowContext(window, drawable, context);
- }
-
- public static WindowContext createOnscreenWindow(GLCapabilities caps, int width, int height, boolean debugGL) throws InterruptedException {
//
- // Create native windowing resources .. X11/Win/OSX
- //
- Display display = NewtFactory.createDisplay(null); // local display
+ final Display display = NewtFactory.createDisplay(null); // local display
Assert.assertNotNull(display);
-
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+
+ final Screen screen = NewtFactory.createScreen(display, 0); // screen 0
Assert.assertNotNull(screen);
-
- Window window = NewtFactory.createWindow(screen, caps);
+
+ final Window window = NewtFactory.createWindow(screen, caps);
Assert.assertNotNull(window);
window.setSize(width, height);
window.setVisible(true);
Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
-
- GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
- GLDrawable drawable = factory.createGLDrawable(window);
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable drawable = factory.createGLDrawable(window);
Assert.assertNotNull(drawable);
-
+
drawable.setRealized(true);
Assert.assertTrue(drawable.isRealized());
-
- GLContext context = drawable.createContext(null);
+
+ final GLContext context = drawable.createContext(null);
Assert.assertNotNull(context);
-
+
context.enableGLDebugMessage(debugGL);
-
- int res = context.makeCurrent();
+
+ final int res = context.makeCurrent();
Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
-
+
return new WindowContext(window, drawable, context);
}
- public static void destroyWindow(WindowContext winctx) {
- GLDrawable drawable = winctx.context.getGLDrawable();
-
+ public static void destroyWindow(final WindowContext winctx) {
+ final GLDrawable drawable = winctx.context.getGLDrawable();
+
Assert.assertNotNull(winctx.context);
winctx.context.destroy();
-
+
Assert.assertNotNull(drawable);
drawable.setRealized(false);
-
+
Assert.assertNotNull(winctx.window);
winctx.window.destroy();
}
-
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java
index 32b392ca8..95cd0e7d3 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,57 +20,104 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.List;
+
+import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
-public class NEWTKeyAdapter extends KeyAdapter implements InputEventCountAdapter {
+public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
String prefix;
- int keyTyped;
+ int keyPressed, keyReleased;
+ int keyPressedAR, keyReleasedAR;
+ int consumed;
boolean pressed;
+ List<EventObject> queue = new ArrayList<EventObject>();
+ boolean verbose = true;
- public NEWTKeyAdapter(String prefix) {
+ public NEWTKeyAdapter(final String prefix) {
this.prefix = prefix;
reset();
}
- public boolean isPressed() {
+ public synchronized void setVerbose(final boolean v) { verbose = v; }
+
+ public synchronized boolean isPressed() {
return pressed;
}
-
- public int getCount() {
- return keyTyped;
+
+ public synchronized int getCount() {
+ return keyReleased;
}
- public void reset() {
- keyTyped = 0;
+ public synchronized int getConsumedCount() {
+ return consumed;
+ }
+
+ public synchronized int getKeyPressedCount(final boolean autoRepeatOnly) {
+ return autoRepeatOnly ? keyPressedAR: keyPressed;
+ }
+
+ public synchronized int getKeyReleasedCount(final boolean autoRepeatOnly) {
+ return autoRepeatOnly ? keyReleasedAR: keyReleased;
+ }
+
+ public synchronized List<EventObject> copyQueue() {
+ return new ArrayList<EventObject>(queue);
+ }
+
+ public synchronized int getQueueSize() {
+ return queue.size();
+ }
+
+ public synchronized void reset() {
+ keyPressed = 0;
+ keyReleased = 0;
+ consumed = 0;
+ keyPressedAR = 0;
+ keyReleasedAR = 0;
pressed = false;
+ queue.clear();
}
- public void keyPressed(KeyEvent e) {
+ public synchronized void keyPressed(final KeyEvent e) {
pressed = true;
- System.err.println("NEWT AWT PRESSED ["+pressed+"]: "+prefix+", "+e);
+ keyPressed++;
+ if( 0 != ( e.getModifiers() & InputEvent.AUTOREPEAT_MASK ) ) {
+ keyPressedAR++;
+ }
+ queue.add(e);
+ if( verbose ) {
+ System.err.println("KEY NEWT PRESSED ["+pressed+"]: "+prefix+", "+e);
+ }
}
-
- public void keyReleased(KeyEvent e) {
+
+ public synchronized void keyReleased(final KeyEvent e) {
pressed = false;
- System.err.println("NEWT AWT RELEASED ["+pressed+"]: "+prefix+", "+e);
+ keyReleased++;
+ if(e.isConsumed()) {
+ consumed++;
+ }
+ if( 0 != ( e.getModifiers() & InputEvent.AUTOREPEAT_MASK ) ) {
+ keyReleasedAR++;
+ }
+ queue.add(e);
+ if( verbose ) {
+ System.err.println("KEY NEWT RELEASED ["+pressed+"]: "+prefix+", "+e);
+ }
}
-
- @Override
- public void keyTyped(KeyEvent e) {
- ++keyTyped;
- System.err.println("KEY NEWT TYPED ["+keyTyped+"]: "+prefix+", "+e);
- }
-
- public String toString() { return prefix+"[pressed "+pressed+", typed "+keyTyped+"]"; }
+
+ public String toString() { return prefix+"[pressed "+pressed+", keysPressed "+keyPressed+" (AR "+keyPressedAR+"), keyReleased "+keyReleased+" (AR "+keyReleasedAR+"), consumed "+consumed+"]"; }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java
new file mode 100644
index 000000000..623d18229
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java
@@ -0,0 +1,213 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.util;
+
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.List;
+
+import org.junit.Assert;
+
+import com.jogamp.common.util.IntIntHashMap;
+import com.jogamp.newt.event.KeyEvent;
+
+public class NEWTKeyUtil {
+ public static final int TIME_OUT = 2000; // 2s
+ public static final int POLL_DIVIDER = 20; // TO/20
+ public static final int TIME_SLICE = TIME_OUT / POLL_DIVIDER ;
+
+ public static class CodeSeg {
+ public final short min;
+ public final short max;
+ public final String description;
+
+ public CodeSeg(final int min, final int max, final String description) {
+ this.min = (short)min;
+ this.max = (short)max;
+ this.description = description;
+ }
+ }
+ public static class CodeEvent {
+ public final short code;
+ public final String description;
+ public final KeyEvent event;
+
+ public CodeEvent(final short code, final String description, final KeyEvent event) {
+ this.code = code;
+ this.description = description;
+ this.event = event;
+ }
+ public String toString() {
+ return "Code 0x"+Integer.toHexString( code & 0x0000FFFF )+" != "+event+" // "+description;
+ }
+ }
+
+ public static void dumpKeyEvents(final List<EventObject> keyEvents) {
+ for(int i=0; i<keyEvents.size(); i++) {
+ System.err.println(i+": "+keyEvents.get(i));
+ }
+ }
+
+ public static boolean validateKeyCodes(final CodeSeg[] codeSegments, final List<List<EventObject>> keyEventsList, final boolean verbose) {
+ final List<CodeEvent> missCodes = new ArrayList<CodeEvent>();
+ int totalCodeCount = 0;
+ boolean res = true;
+ for(int i=0; i<codeSegments.length; i++) {
+ final CodeSeg codeSeg = codeSegments[i];
+ totalCodeCount += codeSeg.max - codeSeg.min + 1;
+ final List<EventObject> keyEvents = keyEventsList.get(i);
+ res &= validateKeyCodes(missCodes, codeSeg, keyEvents, verbose);
+ }
+ if(verbose) {
+ System.err.println("*** Total KeyCode Misses "+missCodes.size()+" / "+totalCodeCount+", valid "+res);
+ for(int i=0; i<missCodes.size(); i++) {
+ System.err.println("Miss["+i+"]: "+missCodes.get(i));
+ }
+ }
+ return res;
+ }
+ public static boolean validateKeyCodes(final List<CodeEvent> missCodes, final CodeSeg codeSeg, final List<EventObject> keyEvents, final boolean verbose) {
+ final int codeCount = codeSeg.max - codeSeg.min + 1;
+ int misses = 0;
+ int evtIdx = 0;
+ for(int i=0; i<codeCount; i++) {
+ // evtIdx -> KEY_PRESSED !
+ final short c = (short) ( codeSeg.min + i );
+ final KeyEvent e = (KeyEvent) ( evtIdx < keyEvents.size() ? keyEvents.get(evtIdx) : null );
+ if( null == e ) {
+ missCodes.add(new CodeEvent(c, codeSeg.description, e));
+ misses++;
+ evtIdx++;
+ } else {
+ if( c != e.getKeyCode() ) {
+ missCodes.add(new CodeEvent(c, codeSeg.description, e));
+ misses++;
+ }
+ evtIdx += 2;
+ }
+ }
+ final boolean res = evtIdx == keyEvents.size() && 0 == missCodes.size();
+ if(verbose) {
+ System.err.println("+++ Code Segment "+codeSeg.description+", Misses: "+misses+" / "+codeCount+", events "+keyEvents.size()+", valid "+res);
+ }
+ return res;
+ }
+
+ public static void validateKeyEvent(final KeyEvent e, final short eventType, final int modifiers, final short keyCode, final char keyChar) {
+ if(0 <= eventType) {
+ Assert.assertTrue("KeyEvent type mismatch, expected 0x"+Integer.toHexString(eventType)+", has "+e, eventType == e.getEventType());
+ }
+ if(0 <= modifiers) {
+ Assert.assertTrue("KeyEvent modifier mismatch, expected 0x"+Integer.toHexString(modifiers)+", has "+e, modifiers == e.getModifiers());
+ }
+ if(KeyEvent.VK_UNDEFINED != keyCode) {
+ Assert.assertTrue("KeyEvent code mismatch, expected 0x"+Integer.toHexString(keyCode)+", has "+e, keyCode == e.getKeyCode());
+ }
+ if(KeyEvent.NULL_CHAR != keyChar) {
+ Assert.assertTrue("KeyEvent char mismatch, expected 0x"+Integer.toHexString(keyChar)+", has "+e, keyChar == e.getKeyChar());
+ }
+ }
+
+ public static short getNextKeyEventType(final KeyEvent e) {
+ final int et = e.getEventType();
+ switch( et ) {
+ case KeyEvent.EVENT_KEY_PRESSED:
+ return KeyEvent.EVENT_KEY_RELEASED;
+ case KeyEvent.EVENT_KEY_RELEASED:
+ return KeyEvent.EVENT_KEY_PRESSED;
+ default:
+ Assert.assertTrue("Invalid event "+e, false);
+ return 0;
+ }
+ }
+
+ public static void validateKeyEventOrder(final List<EventObject> keyEvents) {
+ final IntIntHashMap keyCode2NextEvent = new IntIntHashMap();
+ for(int i=0; i<keyEvents.size(); i++) {
+ final KeyEvent e = (KeyEvent) keyEvents.get(i);
+ int eet = keyCode2NextEvent.get(e.getKeyCode());
+ if( 0 >= eet ) {
+ eet = KeyEvent.EVENT_KEY_PRESSED;
+ }
+ final int et = e.getEventType();
+ Assert.assertEquals("Key event not in proper order "+i+"/"+keyEvents.size()+" - event "+e, eet, et);
+ eet = getNextKeyEventType(e);
+ keyCode2NextEvent.put(e.getKeyCode(), eet);
+ }
+ }
+
+ /**
+ * @param keyAdapter
+ * @param expPressedCountSI number of single key press events
+ * @param expReleasedCountSI number of single key release events
+ * @param expPressedCountAR number of auto-repeat key press events
+ * @param expReleasedCountAR number of auto-repeat key release events
+ */
+ public static void validateKeyAdapterStats(final NEWTKeyAdapter keyAdapter,
+ final int expPressedCountSI, final int expReleasedCountSI,
+ final int expPressedCountAR, final int expReleasedCountAR) {
+ final int expPressReleaseCountSI = expPressedCountSI + expReleasedCountSI;
+ final int expPressReleaseCountAR = expPressedCountAR + expReleasedCountAR;
+ final int expPressReleaseCountALL = expPressReleaseCountSI + expPressReleaseCountAR;
+
+ final int keyPressedALL = keyAdapter.getKeyPressedCount(false);
+ final int keyPressedAR = keyAdapter.getKeyPressedCount(true);
+ final int keyReleasedALL = keyAdapter.getKeyReleasedCount(false);
+ final int keyReleasedAR = keyAdapter.getKeyReleasedCount(true);
+
+ final int keyPressedSI = keyPressedALL-keyPressedAR;
+ final int keyReleasedSI = keyReleasedALL-keyReleasedAR;
+
+ final int pressReleaseCountALL = keyPressedALL + keyReleasedALL;
+ final int pressReleaseCountSI = keyPressedSI + keyReleasedSI;
+ final int pressReleaseCountAR = keyPressedAR + keyReleasedAR;
+
+ System.err.println("Expec Single Press "+expPressedCountSI +", Release "+expReleasedCountSI);
+ System.err.println("Expec AutoRp Press "+expPressedCountAR +", Release "+expReleasedCountAR);
+
+ System.err.println("Total Single Press "+keyPressedSI +", Release "+keyReleasedSI +", Events "+pressReleaseCountSI);
+ System.err.println("Total AutoRp Press "+keyPressedAR +", Release "+keyReleasedAR +", Events "+pressReleaseCountAR);
+ System.err.println("Total ALL Press "+keyPressedALL +", Release "+keyReleasedALL +", Events "+pressReleaseCountALL);
+
+ Assert.assertEquals("Internal Error: pressReleaseSI != pressReleaseALL - pressReleaseAR", pressReleaseCountSI, pressReleaseCountALL - pressReleaseCountAR);
+
+ Assert.assertEquals("Key press count failure (SI)", expPressedCountSI, keyPressedSI);
+ Assert.assertEquals("Key released count failure (SI)", expReleasedCountSI, keyReleasedSI);
+
+ Assert.assertEquals("Key press count failure (AR)", expPressedCountAR, keyPressedAR);
+ Assert.assertEquals("Key released count failure (AR)", expReleasedCountAR, keyReleasedAR);
+
+ Assert.assertEquals("Key pressRelease count failure (SI)", expPressReleaseCountSI, pressReleaseCountSI);
+ Assert.assertEquals("Key pressRelease count failure (AR)", expPressReleaseCountAR, pressReleaseCountAR);
+
+ final List<EventObject> keyEvents = keyAdapter.copyQueue();
+
+ Assert.assertEquals("Key pressRelease count failure (ALL) w/ list sum ", expPressReleaseCountALL, pressReleaseCountALL);
+ Assert.assertEquals("Key total count failure (ALL) w/ list size ", pressReleaseCountALL, keyEvents.size());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java
index d98b9ca74..bd191dd2c 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,14 +20,18 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.List;
+
import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
@@ -35,41 +39,72 @@ public class NEWTMouseAdapter extends MouseAdapter implements InputEventCountAda
String prefix;
int mouseClicked;
+ int consumed;
boolean pressed;
+ List<EventObject> queue = new ArrayList<EventObject>();
+ boolean verbose = true;
- public NEWTMouseAdapter(String prefix) {
+ public NEWTMouseAdapter(final String prefix) {
this.prefix = prefix;
reset();
}
- public boolean isPressed() {
+ public synchronized void setVerbose(final boolean v) { verbose = v; }
+
+ public synchronized boolean isPressed() {
return pressed;
}
-
- public int getCount() {
+
+ public synchronized int getCount() {
return mouseClicked;
}
- public void reset() {
+ public synchronized int getConsumedCount() {
+ return consumed;
+ }
+
+ public synchronized List<EventObject> copyQueue() {
+ return new ArrayList<EventObject>(queue);
+ }
+
+ public synchronized int getQueueSize() {
+ return queue.size();
+ }
+
+ public synchronized void reset() {
mouseClicked = 0;
+ consumed = 0;
pressed = false;
+ queue.clear();
}
- public void mousePressed(MouseEvent e) {
+ public synchronized void mousePressed(final MouseEvent e) {
pressed = true;
- System.err.println("MOUSE NEWT PRESSED ["+pressed+"]: "+prefix+", "+e);
+ queue.add(e);
+ if( verbose ) {
+ System.err.println("MOUSE NEWT PRESSED ["+pressed+"]: "+prefix+", "+e);
+ }
}
-
- public void mouseReleased(MouseEvent e) {
+
+ public synchronized void mouseReleased(final MouseEvent e) {
pressed = false;
- System.err.println("MOUSE NEWT RELEASED ["+pressed+"]: "+prefix+", "+e);
+ queue.add(e);
+ if( verbose ) {
+ System.err.println("MOUSE NEWT RELEASED ["+pressed+"]: "+prefix+", "+e);
+ }
}
-
- public void mouseClicked(MouseEvent e) {
+
+ public synchronized void mouseClicked(final MouseEvent e) {
mouseClicked+=e.getClickCount();
- System.err.println("MOUSE NEWT CLICKED ["+mouseClicked+"]: "+prefix+", "+e);
+ if(e.isConsumed()) {
+ consumed++;
+ }
+ queue.add(e);
+ if( verbose ) {
+ System.err.println("MOUSE NEWT CLICKED ["+mouseClicked+"]: "+prefix+", "+e);
+ }
}
-
- public String toString() { return prefix+"[pressed "+pressed+", clicked "+mouseClicked+"]"; }
+
+ public String toString() { return prefix+"[pressed "+pressed+", clicked "+mouseClicked+", consumed "+consumed+"]"; }
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java
index 42d68dadb..b355d51e3 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,33 +20,45 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
import com.jogamp.newt.event.*;
public class QuitAdapter extends WindowAdapter implements WindowListener, KeyListener {
boolean shouldQuit = false;
+ boolean enabled = true;
+
+ public void enable(final boolean v) { enabled = v; }
+
+ public void clear() { shouldQuit = false; }
public boolean shouldQuit() { return shouldQuit; }
+ public void doQuit() { shouldQuit=true; }
- public void windowDestroyNotify(WindowEvent e) {
- System.err.println("QUIT Window "+Thread.currentThread());
- shouldQuit = true;
+ public void windowDestroyNotify(final WindowEvent e) {
+ if( enabled ) {
+ System.err.println("QUIT Window "+Thread.currentThread());
+ shouldQuit = true;
+ }
}
- public void keyTyped(KeyEvent e) {
- if(e.getKeyChar()=='q') {
- System.err.println("QUIT Key "+Thread.currentThread());
- shouldQuit = true;
+ public void keyReleased(final KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ if( enabled ) {
+ if(e.getKeyChar()=='q') {
+ System.err.println("QUIT Key "+Thread.currentThread());
+ shouldQuit = true;
+ }
}
}
- public void keyPressed(KeyEvent e) {}
- public void keyReleased(KeyEvent e) {}
+ public void keyPressed(final KeyEvent e) {}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
index c31555969..98d288496 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,71 +20,168 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package com.jogamp.opengl.test.junit.util;
+import java.io.BufferedReader;
import java.io.File;
+import java.io.OutputStream;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.StringTokenizer;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLEventListener;
-import com.jogamp.common.util.locks.SingletonInstance;
+import com.jogamp.junit.util.SingletonJunitCase;
import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.texture.TextureIO;
-import org.junit.Assume;
-import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.After;
import org.junit.AfterClass;
-import org.junit.Rule;
-import org.junit.rules.TestName;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.TestClass;
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class UITestCase extends SingletonJunitCase {
+ private static volatile boolean resetXRandRIfX11AfterClass = false;
-public abstract class UITestCase {
- @Rule public TestName _unitTestName = new TestName();
-
- public static final String SINGLE_INSTANCE_LOCK_FILE = "UITestCase.lock";
- public static final int SINGLE_INSTANCE_LOCK_PORT = 59999;
-
- public static final long SINGLE_INSTANCE_LOCK_TO = 3*60*1000; // wait up to 3 min
- public static final long SINGLE_INSTANCE_LOCK_POLL = 1000; // poll every 1s
-
- private static volatile SingletonInstance singletonInstance;
-
- private static volatile boolean testSupported = true;
-
private static volatile int maxMethodNameLen = 0;
- private static final synchronized void initSingletonInstance() {
- if( null == singletonInstance ) {
- // singletonInstance = SingletonInstance.createFileLock(SINGLE_INSTANCE_LOCK_POLL, SINGLE_INSTANCE_LOCK_FILE);
- singletonInstance = SingletonInstance.createServerSocket(SINGLE_INSTANCE_LOCK_POLL, SINGLE_INSTANCE_LOCK_PORT);
- if(!singletonInstance.tryLock(SINGLE_INSTANCE_LOCK_TO)) {
- throw new RuntimeException("Fatal: Could not lock single instance: "+singletonInstance.getName());
+ public static void setResetXRandRIfX11AfterClass() {
+ resetXRandRIfX11AfterClass = true;
+ }
+
+ /**
+ * Iterates through all outputs and sets the preferred mode and normal rotation using RandR 1.3.
+ * <p>
+ * With NV drivers, one need to add the Modes in proper order to the Screen's Subsection "Display",
+ * otherwise they are either in unsorted resolution order or even n/a!
+ * </p>
+ * @return error-code with {@code zero} for no error
+ */
+ @SuppressWarnings("unused")
+ public static int resetXRandRIfX11() {
+ int errorCode = 0;
+ if( NativeWindowFactory.isInitialized() && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
+ try {
+ final List<String> outputDevices = new ArrayList<String>();
+ // final List<String> outputSizes = new ArrayList<String>();
+ final StringBuilder out = new StringBuilder();
+ final String[] cmdlineQuery = new String[] { "xrandr", "-q" };
+ errorCode = processCommand(cmdlineQuery, null, out, "xrandr-query> ");
+ if( 0 != errorCode ) {
+ System.err.println("XRandR Query Error Code "+errorCode);
+ System.err.println(out.toString());
+ } else {
+ // Parse connected output devices !
+ final BufferedReader in = new BufferedReader( new StringReader( out.toString() ) );
+ String line = null;
+ while ( ( line = in.readLine() ) != null) {
+ final String lline = line.toLowerCase();
+ if( lline.contains("connected") && !lline.contains("disconnected") ) {
+ final String od = getFirst(line);
+ if( null != od ) {
+ outputDevices.add( od );
+ /**
+ if ( ( line = in.readLine() ) != null ) {
+ outputSizes.add( getFirst(line) );
+ } else {
+ outputSizes.add( null );
+ } */
+ }
+ }
+ }
+ for(int i=0; i<outputDevices.size(); i++) {
+ final String outputDevice = outputDevices.get(i);
+ final String outputSize = null; // outputSizes.get(i)
+ final String[] cmdline;
+ if( null != outputSize ) {
+ cmdline = new String[] { "xrandr", "--output", outputDevice, "--mode", outputSize, "--rotate", "normal" };
+ } else {
+ cmdline = new String[] { "xrandr", "--output", outputDevice, "--preferred", "--rotate", "normal" };
+ }
+ System.err.println("XRandR 1.2 Reset: "+Arrays.asList(cmdline));
+ errorCode = processCommand(cmdline, System.err, null, "xrandr-1.2-reset> ");
+ if( 0 != errorCode ) {
+ System.err.println("XRandR 1.2 Reset Error Code "+errorCode);
+ break;
+ }
+ }
+ /**
+ * RandR 1.1 reset does not work ..
+ if( 0 != errorCode ) {
+ final String[] cmdline = new String[] { "xrandr", "-s", "0", "-o", "normal" };
+ System.err.println("XRandR 1.1 Reset: "+Arrays.asList(cmdline));
+ errorCode = processCommand(cmdline, System.err, null, "xrandr-1.1-reset> ");
+ if( 0 != errorCode ) {
+ System.err.println("XRandR 1.1 Reset Error Code "+errorCode);
+ }
+ } */
+ }
+ } catch (final Exception e) {
+ System.err.println("Caught "+e.getClass().getName()+": "+e.getMessage());
+ e.printStackTrace();
+ errorCode = -1;
}
}
+ return errorCode;
}
-
- public static boolean isTestSupported() {
- return testSupported;
+ private static String getFirst(final String line) {
+ final StringTokenizer tok = new StringTokenizer(line);
+ if( tok.hasMoreTokens() ) {
+ final String s = tok.nextToken().trim();
+ if( s.length() > 0 ) {
+ return s;
+ }
+ }
+ return null;
}
-
- public static void setTestSupported(boolean v) {
- System.err.println("setTestSupported: "+v);
- testSupported = v;
+
+ public static int processCommand(final String[] cmdline, final OutputStream outstream, final StringBuilder outstring, final String outPrefix) {
+ int errorCode = 0;
+ final Object ioSync = new Object();
+ try {
+ synchronized ( ioSync ) {
+ final ProcessBuilder pb = new ProcessBuilder(cmdline);
+ pb.redirectErrorStream(true);
+ final Process p = pb.start();
+ final MiscUtils.StreamDump dump;
+ if( null != outstream ) {
+ dump = new MiscUtils.StreamDump( outstream, outPrefix, p.getInputStream(), ioSync);
+ } else if( null != outstring ) {
+ dump = new MiscUtils.StreamDump( outstring, outPrefix, p.getInputStream(), ioSync);
+ } else {
+ throw new IllegalArgumentException("Output stream and string are null");
+ }
+ dump.start();
+ while( !dump.eos() ) {
+ ioSync.wait();
+ }
+ p.waitFor(); // should be fine by now ..
+ errorCode = p.exitValue();
+ }
+ } catch (final Exception e) {
+ System.err.println("Caught "+e.getClass().getName()+": "+e.getMessage());
+ e.printStackTrace();
+ errorCode = Integer.MIN_VALUE;
+ }
+ return errorCode;
}
public int getMaxTestNameLen() {
@@ -92,84 +189,36 @@ public abstract class UITestCase {
int ml = 0;
final TestClass tc = new TestClass(getClass());
final List<FrameworkMethod> testMethods = tc.getAnnotatedMethods(org.junit.Test.class);
- for(Iterator<FrameworkMethod> iter=testMethods.iterator(); iter.hasNext(); ) {
+ for(final Iterator<FrameworkMethod> iter=testMethods.iterator(); iter.hasNext(); ) {
final int l = iter.next().getName().length();
if( ml < l ) { ml = l; }
}
maxMethodNameLen = ml;
}
- return maxMethodNameLen;
- }
-
- public final String getTestMethodName() {
- return _unitTestName.getMethodName();
- }
-
- public final String getSimpleTestName(String separator) {
- return getClass().getSimpleName()+separator+getTestMethodName();
+ return maxMethodNameLen;
}
- public final String getFullTestName(String separator) {
- return getClass().getName()+separator+getTestMethodName();
- }
-
@BeforeClass
- public static void oneTimeSetUp() {
- // one-time initialization code
- initSingletonInstance();
+ public static final void oneTimeSetUpUITest() {
+ // one-time initialization code
}
@AfterClass
- public static void oneTimeTearDown() {
+ public static final void oneTimeTearDownUITest() {
// one-time cleanup code
- System.gc(); // force cleanup
- singletonInstance.unlock();
- }
-
- @Before
- public void setUp() {
- System.err.print("++++ UITestCase.setUp: "+getFullTestName(" - "));
- if(!testSupported) {
- System.err.println(" - "+unsupportedTestMsg);
- Assume.assumeTrue(testSupported); // abort
+ if( resetXRandRIfX11AfterClass ) {
+ resetXRandRIfX11();
}
- System.err.println();
}
- @After
- public void tearDown() {
- System.err.println("++++ UITestCase.tearDown: "+getFullTestName(" - "));
- }
-
- static final String unsupportedTestMsg = "Test not supported on this platform.";
-
- /**
- * Takes a snapshot of the drawable's current front framebuffer. Example filenames:
- * <pre>
- * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgb_-S00_default-0400x0300.png
- * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgb_-S00_default-0200x0150.png
- * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgb_-S00_default-0200x0150.png
- * </pre>
- * @param sn sequential number
- * @param postSNDetail optional detail to be added to the filename after <code>sn</code>
- * @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename.
- * @param readBufferUtil the {@link GLReadBufferUtil} to be used to read the pixels for the screenshot.
- * @param fileSuffix Optional file suffix without a <i>dot</i> defining the file type, i.e. <code>"png"</code>.
- * If <code>null</code> the <code>"png"</code> as defined in {@link TextureIO#PNG} is being used.
- * @param destPath Optional platform dependent file path. It shall use {@link File#separatorChar} as is directory separator.
- * It shall not end with a directory separator, {@link File#separatorChar}.
- * If <code>null</code> the current working directory is being used.
- */
- public void snapshot(int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
+ public String getSnapshotFilename(final int sn, String postSNDetail, final GLCapabilitiesImmutable caps, final int width, final int height, final boolean sinkHasAlpha, String fileSuffix, final String destPath) {
if(null == fileSuffix) {
fileSuffix = TextureIO.PNG;
}
final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1;
final String simpleTestName = this.getSimpleTestName(".");
final String filenameBaseName;
- {
- final GLDrawable drawable = gl.getContext().getGLReadDrawable();
- final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
+ {
final String accel = caps.getHardwareAccelerated() ? "hw" : "sw" ;
final String scrnm;
if(caps.isOnscreen()) {
@@ -184,56 +233,113 @@ public abstract class UITestCase {
scrnm = "unknown_";
}
final String dblb = caps.getDoubleBuffered() ? "dbl" : "one";
- final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_";
- final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_";
+ final String F_pfmt = sinkHasAlpha ? "rgba" : "rgb_";
+ final String pfmt = "rgba" + caps.getRedBits() + caps.getGreenBits() + caps.getBlueBits() + caps.getAlphaBits();
+ final int depthBits = caps.getDepthBits();
+ final int stencilBits = caps.getStencilBits();
final int samples = caps.getNumSamples() ;
final String aaext = caps.getSampleExtension();
postSNDetail = null != postSNDetail ? "-"+postSNDetail : "";
- filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-S%02d_%s-%04dx%04d.%s",
- simpleTestName, sn, postSNDetail, drawable.getGLProfile().getName(), accel,
- scrnm, dblb, F_pfmt, pfmt, samples, aaext,
- drawable.getWidth(), drawable.getHeight(), fileSuffix).replace(' ', '_');
+ filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-D%02d-St%02d-Sa%02d_%s-%04dx%04d.%s",
+ simpleTestName, sn, postSNDetail, caps.getGLProfile().getName(), accel,
+ scrnm, dblb, F_pfmt, pfmt, depthBits, stencilBits, samples, aaext,
+ width, height, fileSuffix).replace(' ', '_');
}
- final String filename = null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName;
- System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename+", maxTestNameLen "+maxSimpleTestNameLen+", <"+simpleTestName+">");
+ return null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName;
+ }
+
+ /**
+ * Takes a snapshot of the drawable's current front framebuffer. Example filenames:
+ * <pre>
+ * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgba8888_-D24-St00-Sa00_default-0400x0300.png
+ * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgba8880-D24-St00-Sa00_default-0200x0150.png
+ * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgba5551-D24-St00-Sa00_default-0200x0150.png
+ * </pre>
+ * @param sn sequential number
+ * @param postSNDetail optional detail to be added to the filename after <code>sn</code>
+ * @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename.
+ * @param readBufferUtil the {@link GLReadBufferUtil} to be used to read the pixels for the screenshot.
+ * @param fileSuffix Optional file suffix without a <i>dot</i> defining the file type, i.e. <code>"png"</code>.
+ * If <code>null</code> the <code>"png"</code> as defined in {@link TextureIO#PNG} is being used.
+ * @param destPath Optional platform dependent file path. It shall use {@link File#separatorChar} as is directory separator.
+ * It shall not end with a directory separator, {@link File#separatorChar}.
+ * If <code>null</code> the current working directory is being used.
+ */
+ public void snapshot(final int sn, final String postSNDetail, final GL gl, final GLReadBufferUtil readBufferUtil, final String fileSuffix, final String destPath) {
+
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ final String filename = getSnapshotFilename(sn, postSNDetail,
+ drawable.getChosenGLCapabilities(), drawable.getSurfaceWidth(), drawable.getSurfaceHeight(),
+ readBufferUtil.hasAlpha(), fileSuffix, destPath);
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename);
gl.glFinish(); // just make sure rendering finished ..
+ try {
+ snapshot(gl, readBufferUtil, filename);
+ } catch (final ClassNotFoundException cnfe) {
+ // Texture class belongs to jogl-util.jar which my not be included in test environment!
+ System.err.println("Caught ClassNotFoundException: "+cnfe.getMessage());
+ } catch (final NoClassDefFoundError cnfe) {
+ // Texture class belongs to jogl-util.jar which my not be included in test environment!
+ System.err.println("Caught NoClassDefFoundError: "+cnfe.getMessage());
+ }
+ }
+ private void snapshot(final GL gl, final GLReadBufferUtil readBufferUtil, final String filename) throws ClassNotFoundException, NoClassDefFoundError {
if(readBufferUtil.readPixels(gl, false)) {
readBufferUtil.write(new File(filename));
- }
+ }
}
-
+
public class SnapshotGLEventListener implements GLEventListener {
private final GLReadBufferUtil screenshot;
private volatile boolean makeShot = false;
- private volatile int displayCount=0;
- private volatile int reshapeCount=0;
- public SnapshotGLEventListener(GLReadBufferUtil screenshot) {
+ private volatile boolean makeShotAlways = false;
+ private volatile boolean verbose = false;
+ private final AtomicInteger displayCount = new AtomicInteger(0);
+ private final AtomicInteger reshapeCount = new AtomicInteger(0);
+ private volatile String postSNDetail = null;
+ public SnapshotGLEventListener(final GLReadBufferUtil screenshot) {
this.screenshot = screenshot;
}
public SnapshotGLEventListener() {
this.screenshot = new GLReadBufferUtil(false, false);
}
-
- public void init(GLAutoDrawable drawable) {}
- public void dispose(GLAutoDrawable drawable) {}
- public void display(GLAutoDrawable drawable) {
+ public int getDisplayCount() { return displayCount.get(); }
+ public int getReshapeCount() { return reshapeCount.get(); }
+ public GLReadBufferUtil getGLReadBufferUtil() { return screenshot; }
+ public void init(final GLAutoDrawable drawable) {}
+ public void dispose(final GLAutoDrawable drawable) {}
+ public void display(final GLAutoDrawable drawable) {
final GL gl = drawable.getGL();
- System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": "+drawable.getWidth()+"x"+drawable.getHeight()+", makeShot "+makeShot);
- if(makeShot) {
+ final boolean _makeShot = makeShot || makeShotAlways;
+ if(verbose) {
+ System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": "+drawable.getSurfaceWidth()+"x"+drawable.getSurfaceHeight()+", makeShot "+_makeShot);
+ }
+ if(_makeShot) {
makeShot=false;
- snapshot(displayCount, null, gl, screenshot, TextureIO.PNG, null);
+ snapshot(displayCount.get(), postSNDetail, gl, screenshot, TextureIO.PNG, null);
}
- displayCount++;
+ displayCount.incrementAndGet();
}
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight());
- reshapeCount++;
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ if(verbose) {
+ System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": "+width+"x"+height+" - "+drawable.getSurfaceWidth()+"x"+drawable.getSurfaceHeight());
+ }
+ reshapeCount.incrementAndGet();
}
public void setMakeSnapshot() {
makeShot=true;
}
+ public void setMakeSnapshotAlways(final boolean v) {
+ makeShotAlways=v;
+ }
+ public void setVerbose(final boolean v) {
+ verbose=v;
+ }
+ public void setPostSNDetail(final String v) {
+ postSNDetail = v;
+ }
};
-
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/opengl/UIRegion.java b/src/test/com/jogamp/opengl/test/junit/util/ValidateLockListener.java
index 88271095c..ceb171529 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/opengl/UIRegion.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/ValidateLockListener.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright 2012 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -25,53 +25,47 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package com.jogamp.opengl.test.junit.graph.demos.ui.opengl;
-import javax.media.opengl.GL2ES2;
+package com.jogamp.opengl.test.junit.util;
-import com.jogamp.graph.curve.opengl.GLRegion;
-import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.opengl.test.junit.graph.demos.ui.UIShape;
-import com.jogamp.opengl.test.junit.graph.demos.ui.UITextShape;
-public class UIRegion {
- protected static final int DIRTY_REGION = 1 << 0 ;
- protected int dirty = DIRTY_REGION;
-
- private UIShape uiShape;
- private GLRegion region;
-
- public UIRegion(UIShape uis) {
- this.uiShape = uis;
- }
-
- public boolean updateRegion(GL2ES2 gl, RenderState rs, int renderModes) {
- if( uiShape.updateShape() || isRegionDirty() ) {
- destroy(gl, rs);
- if(uiShape instanceof UITextShape) {
- region = ((UITextShape)uiShape).getGlyphString().createRegion(gl, renderModes);
- } else {
- region = GLRegion.create(uiShape.getShape(), renderModes);
+import javax.media.nativewindow.NativeSurface;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+
+
+public class ValidateLockListener implements GLEventListener {
+
+ private void validateLock(final GLAutoDrawable drawable) {
+ final NativeSurface ns = drawable.getNativeSurface();
+ ns.getGraphicsConfiguration().getScreen().getDevice().validateLocked();
+
+ final Thread current = Thread.currentThread();
+ final Thread owner = ns.getSurfaceLockOwner();
+ if( ns.isSurfaceLockedByOtherThread() ) {
+ throw new RuntimeException(current.getName()+": Locked by another thread(1), owner "+owner+", "+ns);
+ }
+ if( current != owner ) {
+ if( null == owner ) {
+ throw new RuntimeException(current.getName()+": Not locked: "+ns);
}
- dirty &= ~DIRTY_REGION;
- return true;
+ throw new RuntimeException(current.getName()+": Locked by another thread(2), owner "+owner+", "+ns);
}
- return false;
}
-
- public GLRegion getRegion(GL2ES2 gl, RenderState rs, int renderModes) {
- updateRegion(gl, rs, renderModes);
- return region;
+
+ public void init(final GLAutoDrawable drawable) {
+ validateLock(drawable);
}
-
- public boolean isRegionDirty() {
- return 0 != ( dirty & DIRTY_REGION ) ;
+
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ validateLock(drawable);
}
-
- public void destroy(GL2ES2 gl, RenderState rs) {
- if(null != region) {
- region.destroy(gl, rs);
- region = null;
- }
+
+ public void display(final GLAutoDrawable drawable) {
+ validateLock(drawable);
+ }
+
+ public void dispose(final GLAutoDrawable drawable) {
+ validateLock(drawable);
}
}
diff --git a/src/test/jogamp/newt/WindowImplAccess.java b/src/test/jogamp/newt/WindowImplAccess.java
index 3387a2ae2..b98835f37 100644
--- a/src/test/jogamp/newt/WindowImplAccess.java
+++ b/src/test/jogamp/newt/WindowImplAccess.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -34,13 +34,13 @@ import com.jogamp.newt.Window;
* Allows access to protected methods of WindowImpl
*/
public class WindowImplAccess {
- public static final void windowDestroyNotify(Window win) {
+ public static final void windowDestroyNotify(final Window win) {
final WindowImpl winImpl = (WindowImpl) win.getDelegatedWindow();
winImpl.runOnEDTIfAvail(true, new Runnable() {
public void run() {
winImpl.windowDestroyNotify(false);
}
- });
+ });
}
}